Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch hidden-columns-in-tables Excluding Merge-Ins
This is equivalent to a diff from 4f521b5bb3 to 5490646b2e
2015-11-19
| ||
14:11 | If compiled with SQLITE_ENABLE_HIDDEN_COLUMNS, then columns in ordinary tables and views that have names beginning with "__hidden__" are omitted from the "*" expansion in SELECT statements and from the automatic list of columns following the table name in an INSERT INTO statement. (check-in: 011904cad2 user: drh tags: trunk) | |
13:53 | Only support the magic "__hidden__" column name prefix interpretation when compiled with SQLITE_ENABLE_HIDDEN_COLUMNS. (Closed-Leaf check-in: 5490646b2e user: drh tags: hidden-columns-in-tables) | |
13:21 | Fix a 10-year-old misguided attempt at parser performance improvement that actually made parsing slightly slower. (check-in: 3833cbac07 user: drh tags: trunk) | |
2015-11-18
| ||
21:22 | Get the __hidden__ column mechanism working on views with INSTEAD OF triggers. (check-in: 20c1e9ce75 user: drh tags: hidden-columns-in-tables) | |
18:43 | If a table column name begins with "__hidden__" then do not include that column in "*" expansions in SELECT statements, nor fill in that column in an INSERT INTO that omits the column list. <i>This branch is a proof-of-concept only and is not intended to ever be merged into trunk.</i> (check-in: 2dbffb3a3b user: drh tags: hidden-columns-in-tables) | |
2015-11-17
| ||
21:42 | When using mmap mode on Win32, use a read-only mapping by default. Write to the database file using WriteFile(). Unless SQLITE_MMAP_READWRITE is defined, in which case use a read/write mapping and write into the file using memcpy(). (check-in: 4f521b5bb3 user: mistachkin tags: trunk) | |
20:56 | When using mmap mode on unix, use a read-only mapping by default. Write to the database file using write(). Unless SQLITE_MMAP_READWRITE is defined, in which case use a read/write mapping and write into the file using memcpy(). (check-in: 67c5d3c646 user: dan tags: trunk) | |
Changes to src/build.c.
1044 1044 return; 1045 1045 1046 1046 /* If an error occurs, we jump here */ 1047 1047 begin_table_error: 1048 1048 sqlite3DbFree(db, zName); 1049 1049 return; 1050 1050 } 1051 + 1052 +/* Set properties of a table column based on the (magical) 1053 +** name of the column. 1054 +*/ 1055 +void sqlite3ColumnPropertiesFromName(Column *pCol){ 1056 +#if SQLITE_ENABLE_HIDDEN_COLUMNS 1057 + if( sqlite3_strnicmp(pCol->zName, "__hidden__", 10)==0 ){ 1058 + pCol->colFlags |= COLFLAG_HIDDEN; 1059 + } 1060 +#endif 1061 +} 1062 + 1051 1063 1052 1064 /* 1053 1065 ** This macro is used to compare two strings in a case-insensitive manner. 1054 1066 ** It is slightly faster than calling sqlite3StrICmp() directly, but 1055 1067 ** produces larger code. 1056 1068 ** 1057 1069 ** WARNING: This macro is not compatible with the strcmp() family. It ................................................................................ 1100 1112 return; 1101 1113 } 1102 1114 p->aCol = aNew; 1103 1115 } 1104 1116 pCol = &p->aCol[p->nCol]; 1105 1117 memset(pCol, 0, sizeof(p->aCol[0])); 1106 1118 pCol->zName = z; 1119 + sqlite3ColumnPropertiesFromName(pCol); 1107 1120 1108 1121 /* If there is no type specified, columns have the default affinity 1109 1122 ** 'BLOB'. If there is a type specified, then sqlite3AddColumnType() will 1110 1123 ** be called next to set pCol->affinity correctly. 1111 1124 */ 1112 1125 pCol->affinity = SQLITE_AFF_BLOB; 1113 1126 pCol->szEst = 1;
Changes to src/insert.c.
732 732 if( pColumn==0 && nColumn>0 ){ 733 733 ipkColumn = pTab->iPKey; 734 734 } 735 735 736 736 /* Make sure the number of columns in the source data matches the number 737 737 ** of columns to be inserted into the table. 738 738 */ 739 - if( IsVirtual(pTab) ){ 740 - for(i=0; i<pTab->nCol; i++){ 741 - nHidden += (IsHiddenColumn(&pTab->aCol[i]) ? 1 : 0); 742 - } 739 + for(i=0; i<pTab->nCol; i++){ 740 + nHidden += (IsHiddenColumn(&pTab->aCol[i]) ? 1 : 0); 743 741 } 744 742 if( pColumn==0 && nColumn && nColumn!=(pTab->nCol-nHidden) ){ 745 743 sqlite3ErrorMsg(pParse, 746 744 "table %S has %d columns but %d values were supplied", 747 745 pTabList, 0, pTab->nCol-nHidden, nColumn); 748 746 goto insert_cleanup; 749 747 } ................................................................................ 831 829 /* Cannot have triggers on a virtual table. If it were possible, 832 830 ** this block would have to account for hidden column. 833 831 */ 834 832 assert( !IsVirtual(pTab) ); 835 833 836 834 /* Create the new column data 837 835 */ 838 - for(i=0; i<pTab->nCol; i++){ 839 - if( pColumn==0 ){ 840 - j = i; 841 - }else{ 836 + for(i=j=0; i<pTab->nCol; i++){ 837 + if( pColumn ){ 842 838 for(j=0; j<pColumn->nId; j++){ 843 839 if( pColumn->a[j].idx==i ) break; 844 840 } 845 841 } 846 - if( (!useTempTable && !pList) || (pColumn && j>=pColumn->nId) ){ 842 + if( (!useTempTable && !pList) || (pColumn && j>=pColumn->nId) 843 + || (pColumn==0 && IsOrdinaryHiddenColumn(&pTab->aCol[i])) ){ 847 844 sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regCols+i+1); 848 845 }else if( useTempTable ){ 849 846 sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, regCols+i+1); 850 847 }else{ 851 848 assert( pSelect==0 ); /* Otherwise useTempTable is true */ 852 849 sqlite3ExprCodeAndCache(pParse, pList->a[j].pExpr, regCols+i+1); 853 850 } 851 + if( pColumn==0 && !IsOrdinaryHiddenColumn(&pTab->aCol[i]) ) j++; 854 852 } 855 853 856 854 /* If this is an INSERT on a view with an INSTEAD OF INSERT trigger, 857 855 ** do not attempt any conversions before assembling the record. 858 856 ** If this is a real table, attempt conversions as required by the 859 857 ** table column affinities. 860 858 */ ................................................................................ 930 928 ** taking up data space with information that will never be used. 931 929 ** As there may be shallow copies of this value, make it a soft-NULL */ 932 930 sqlite3VdbeAddOp1(v, OP_SoftNull, iRegStore); 933 931 continue; 934 932 } 935 933 if( pColumn==0 ){ 936 934 if( IsHiddenColumn(&pTab->aCol[i]) ){ 937 - assert( IsVirtual(pTab) ); 938 935 j = -1; 939 936 nHidden++; 940 937 }else{ 941 938 j = i - nHidden; 942 939 } 943 940 }else{ 944 941 for(j=0; j<pColumn->nId; j++){
Changes to src/select.c.
1655 1655 for(j=nName-1; j>0 && sqlite3Isdigit(zName[j]); j--){} 1656 1656 if( zName[j]==':' ) nName = j; 1657 1657 } 1658 1658 zName = sqlite3MPrintf(db, "%.*z:%u", nName, zName, ++cnt); 1659 1659 if( cnt>3 ) sqlite3_randomness(sizeof(cnt), &cnt); 1660 1660 } 1661 1661 pCol->zName = zName; 1662 + sqlite3ColumnPropertiesFromName(pCol); 1662 1663 if( zName && sqlite3HashInsert(&ht, zName, pCol)==pCol ){ 1663 1664 db->mallocFailed = 1; 1664 1665 } 1665 1666 } 1666 1667 sqlite3HashClear(&ht); 1667 1668 if( db->mallocFailed ){ 1668 1669 for(j=0; j<i; j++){ ................................................................................ 4356 4357 assert( zName ); 4357 4358 if( zTName && pSub 4358 4359 && sqlite3MatchSpanName(pSub->pEList->a[j].zSpan, 0, zTName, 0)==0 4359 4360 ){ 4360 4361 continue; 4361 4362 } 4362 4363 4363 - /* If a column is marked as 'hidden' (currently only possible 4364 - ** for virtual tables), do not include it in the expanded 4365 - ** result-set list. 4364 + /* If a column is marked as 'hidden', do not include it in 4365 + ** the expanded result-set list. 4366 4366 */ 4367 4367 if( IsHiddenColumn(&pTab->aCol[j]) ){ 4368 - assert(IsVirtual(pTab)); 4369 4368 continue; 4370 4369 } 4371 4370 tableSeen = 1; 4372 4371 4373 4372 if( i>0 && zTName==0 ){ 4374 4373 if( (pFrom->fg.jointype & JT_NATURAL)!=0 4375 4374 && tableAndColumnIndex(pTabList, i, zName, 0, 0)
Changes to src/sqliteInt.h.
1692 1692 /* 1693 1693 ** Test to see whether or not a table is a virtual table. This is 1694 1694 ** done as a macro so that it will be optimized out when virtual 1695 1695 ** table support is omitted from the build. 1696 1696 */ 1697 1697 #ifndef SQLITE_OMIT_VIRTUALTABLE 1698 1698 # define IsVirtual(X) (((X)->tabFlags & TF_Virtual)!=0) 1699 -# define IsHiddenColumn(X) (((X)->colFlags & COLFLAG_HIDDEN)!=0) 1700 1699 #else 1701 1700 # define IsVirtual(X) 0 1702 1701 # define IsHiddenColumn(X) 0 1703 1702 #endif 1703 + 1704 +/* 1705 +** Macros to determine if a column is hidden. IsOrdinaryHiddenColumn() 1706 +** only works for non-virtual tables (ordinary tables and views) and is 1707 +** always false unless SQLITE_ENABLE_HIDDEN_COLUMNS is defined. The 1708 +** IsHiddenColumn() macro is general purpose. 1709 +*/ 1710 +#if defined(SQLITE_ENABLE_HIDDEN_COLUMNS) 1711 +# define IsHiddenColumn(X) (((X)->colFlags & COLFLAG_HIDDEN)!=0) 1712 +# define IsOrdinaryHiddenColumn(X) (((X)->colFlags & COLFLAG_HIDDEN)!=0) 1713 +#elif !defined(SQLITE_OMIT_VIRTUAL) 1714 +# define IsHiddenColumn(X) (((X)->colFlags & COLFLAG_HIDDEN)!=0) 1715 +# define IsOrdinaryHiddenColumn(X) 0 1716 +#else 1717 +# define IsHiddenColumn(X) 0 1718 +# define IsOrdinaryHiddenColumn(X) 0 1719 +#endif 1720 + 1704 1721 1705 1722 /* Does the table have a rowid */ 1706 1723 #define HasRowid(X) (((X)->tabFlags & TF_WithoutRowid)==0) 1707 1724 #define VisibleRowid(X) (((X)->tabFlags & TF_NoVisibleRowid)==0) 1708 1725 1709 1726 /* 1710 1727 ** Each foreign key constraint is an instance of the following structure. ................................................................................ 3310 3327 void sqlite3DeleteColumnNames(sqlite3*,Table*); 3311 3328 int sqlite3ColumnsFromExprList(Parse*,ExprList*,i16*,Column**); 3312 3329 Table *sqlite3ResultSetOfSelect(Parse*,Select*); 3313 3330 void sqlite3OpenMasterTable(Parse *, int); 3314 3331 Index *sqlite3PrimaryKeyIndex(Table*); 3315 3332 i16 sqlite3ColumnOfIndex(Index*, i16); 3316 3333 void sqlite3StartTable(Parse*,Token*,Token*,int,int,int,int); 3334 +void sqlite3ColumnPropertiesFromName(Column*); 3317 3335 void sqlite3AddColumn(Parse*,Token*); 3318 3336 void sqlite3AddNotNull(Parse*, int); 3319 3337 void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int); 3320 3338 void sqlite3AddCheckConstraint(Parse*, Expr*); 3321 3339 void sqlite3AddColumnType(Parse*,Token*); 3322 3340 void sqlite3AddDefaultValue(Parse*,ExprSpan*); 3323 3341 void sqlite3AddCollateType(Parse*, Token*);
Changes to src/test_config.c.
120 120 #endif 121 121 122 122 #ifdef SQLITE_ENABLE_CURSOR_HINTS 123 123 Tcl_SetVar2(interp, "sqlite_options", "cursorhints", "1", TCL_GLOBAL_ONLY); 124 124 #else 125 125 Tcl_SetVar2(interp, "sqlite_options", "cursorhints", "0", TCL_GLOBAL_ONLY); 126 126 #endif 127 + 128 +#ifdef SQLITE_ENABLE_HIDDEN_COLUMNS 129 + Tcl_SetVar2(interp, "sqlite_options", "hiddencolumns", "1", TCL_GLOBAL_ONLY); 130 +#else 131 + Tcl_SetVar2(interp, "sqlite_options", "hiddencolumns", "0", TCL_GLOBAL_ONLY); 132 +#endif 127 133 128 134 #ifdef SQLITE_ENABLE_MEMSYS3 129 135 Tcl_SetVar2(interp, "sqlite_options", "mem3", "1", TCL_GLOBAL_ONLY); 130 136 #else 131 137 Tcl_SetVar2(interp, "sqlite_options", "mem3", "0", TCL_GLOBAL_ONLY); 132 138 #endif 133 139
Added test/hidden.test.
1 +# 2015 November 18 2 +# 3 +# The author disclaims copyright to this source code. In place of 4 +# a legal notice, here is a blessing: 5 +# 6 +# May you do good and not evil. 7 +# May you find forgiveness for yourself and forgive others. 8 +# May you share freely, never taking more than you give. 9 +# 10 +#*********************************************************************** 11 +# 12 +# Test the __hidden__ hack. 13 +# 14 + 15 +set testdir [file dirname $argv0] 16 +source $testdir/tester.tcl 17 +set testprefix hidden 18 + 19 +ifcapable !hiddencolumns { 20 + finish_test 21 + return 22 +} 23 + 24 +do_execsql_test 1.1 { 25 + CREATE TABLE t1(__hidden__a, b); 26 + INSERT INTO t1 VALUES('1'); 27 + INSERT INTO t1(__hidden__a, b) VALUES('x', 'y'); 28 +} {} 29 + 30 +do_execsql_test 1.2 { 31 + SELECT * FROM t1; 32 +} {1 y} 33 + 34 +do_execsql_test 1.3 { 35 + SELECT __hidden__a, * FROM t1; 36 +} {{} 1 x y} 37 + 38 +foreach {tn view} { 39 + 1 { CREATE VIEW v1(a, b, __hidden__c) AS SELECT a, b, c FROM x1 } 40 + 2 { CREATE VIEW v1 AS SELECT a, b, c AS __hidden__c FROM x1 } 41 +} { 42 + do_execsql_test 2.$tn.1 { 43 + DROP TABLE IF EXISTS x1; 44 + CREATE TABLE x1(a, b, c); 45 + INSERT INTO x1 VALUES(1, 2, 3); 46 + } 47 + 48 + catchsql { DROP VIEW v1 } 49 + execsql $view 50 + 51 + do_execsql_test 2.$tn.2 { 52 + SELECT a, b, __hidden__c FROM v1; 53 + } {1 2 3} 54 + 55 + do_execsql_test 2.$tn.3 { 56 + SELECT * FROM v1; 57 + } {1 2} 58 + 59 + do_execsql_test 2.$tn.4 { 60 + CREATE TRIGGER tr1 INSTEAD OF INSERT ON v1 BEGIN 61 + INSERT INTO x1 VALUES(new.a, new.b, new.__hidden__c); 62 + END; 63 + 64 + INSERT INTO v1 VALUES(4, 5); 65 + SELECT * FROM x1; 66 + } {1 2 3 4 5 {}} 67 + 68 + do_execsql_test 2.$tn.5 { 69 + INSERT INTO v1(a, b, __hidden__c) VALUES(7, 8, 9); 70 + SELECT * FROM x1; 71 + } {1 2 3 4 5 {} 7 8 9} 72 +} 73 + 74 +finish_test
Changes to test/releasetest.tcl.
115 115 -DSQLITE_TCL_DEFAULT_FULLMUTEX=1 116 116 -DSQLITE_ENABLE_FTS3=1 117 117 -DSQLITE_ENABLE_RTREE=1 118 118 -DSQLITE_ENABLE_MEMSYS5=1 119 119 -DSQLITE_ENABLE_MEMSYS3=1 120 120 -DSQLITE_ENABLE_COLUMN_METADATA=1 121 121 -DSQLITE_ENABLE_STAT4 122 + -DSQLITE_ENABLE_HIDDEN_COLUMNS 122 123 -DSQLITE_MAX_ATTACHED=125 123 124 } 124 125 "Fast-One" { 125 126 -O6 126 127 -DSQLITE_ENABLE_FTS4=1 127 128 -DSQLITE_ENABLE_RTREE=1 128 129 -DSQLITE_ENABLE_STAT4 ................................................................................ 141 142 -DSQLITE_ENABLE_ATOMIC_WRITE=1 142 143 -DSQLITE_ENABLE_IOTRACE=1 143 144 -DSQLITE_ENABLE_MEMORY_MANAGEMENT=1 144 145 -DSQLITE_MAX_PAGE_SIZE=4096 145 146 -DSQLITE_OMIT_LOAD_EXTENSION=1 146 147 -DSQLITE_OMIT_PROGRESS_CALLBACK=1 147 148 -DSQLITE_OMIT_VIRTUALTABLE=1 149 + -DSQLITE_ENABLE_HIDDEN_COLUMNS 148 150 -DSQLITE_TEMP_STORE=3 149 151 --enable-json1 150 152 } 151 153 "Device-Two" { 152 154 -DSQLITE_4_BYTE_ALIGNED_MALLOC=1 153 155 -DSQLITE_DEFAULT_AUTOVACUUM=1 154 156 -DSQLITE_DEFAULT_CACHE_SIZE=1000 ................................................................................ 209 211 -DSQLITE_OMIT_LOOKASIDE=1 210 212 -DHAVE_USLEEP=1 211 213 } 212 214 "Valgrind" { 213 215 -DSQLITE_ENABLE_STAT4 214 216 -DSQLITE_ENABLE_FTS4 215 217 -DSQLITE_ENABLE_RTREE 218 + -DSQLITE_ENABLE_HIDDEN_COLUMNS 216 219 --enable-json1 217 220 } 218 221 219 222 # The next group of configurations are used only by the 220 223 # Failure-Detection platform. They are all the same, but we need 221 224 # different names for them all so that they results appear in separate 222 225 # subdirectories.