diff --git a/ext/lsm1/Makefile b/ext/lsm1/Makefile index 2ce8831074..37511ef978 100644 --- a/ext/lsm1/Makefile +++ b/ext/lsm1/Makefile @@ -4,7 +4,7 @@ # Replace with something more portable, if the experiments actually work out. # CC = gcc -CFLAGS =-g -fPIC -Wall -I. -I/home/drh/sqlite/bld +CFLAGS =-g -fPIC -Wall -I. -I../.. LSMOBJ = \ lsm_ckpt.o \ diff --git a/manifest b/manifest index 7f7120c7c5..af5d4531d2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Work\stoward\smore\sflexible\styping\sfor\skeys\sand\svalues. -D 2015-11-19T19:27:07.806 +C Merge\sthe\slatest\senhancements\sfrom\strunk. +D 2015-11-19T19:31:33.352 F Makefile.in d828db6afa6c1fa060d01e33e4674408df1942a1 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc e928e68168df69b353300ac87c10105206653a03 @@ -190,7 +190,7 @@ F ext/fts5/tool/showfts5.tcl d54da0e067306663e2d5d523965ca487698e722c F ext/icu/README.txt d9fbbad0c2f647c3fdf715fc9fd64af53aedfc43 F ext/icu/icu.c b2732aef0b076e4276d9b39b5a33cec7a05e1413 F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37 -F ext/lsm1/Makefile f8d8f229fbeafa5352edab5be7e722ed71233b12 +F ext/lsm1/Makefile 9eed37365e0df2fe58a3011c6aacc4646f22a4ef F ext/lsm1/lsm.h 0f6f64ff071471cb87bf98beb8386566f30ea001 F ext/lsm1/lsmInt.h bc270dd81b3355c7410b06a6d54dd3eb9493a3e8 F ext/lsm1/lsm_ckpt.c e7907e782fe2e95de0833675e35e726e487cc4cd @@ -301,13 +301,13 @@ F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79 F src/btree.c d3bdd8462a86492e2ebc9aca4a0168429017de25 F src/btree.h 2d76dee44704c47eed323356a758662724b674a0 F src/btreeInt.h 3ab435ed27adea54d040584b0bcc488ee7db1e38 -F src/build.c ca574d33ffb1763cfd2979383f4d507095bfbe19 +F src/build.c 5a3b71786e2b96d2bb92d40f190eb1fe736f25ca F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0 F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f F src/ctime.c 509ef9c64d1321f42448f111da86400b1799218a F src/date.c fb1c99172017dcc8e237339132c91a21a0788584 F src/dbstat.c ffd63fc8ba7541476ced189b95e95d7f2bc63f78 -F src/delete.c c4c6fb9da78b946fcba2a6aac5b24bc5c15e752a +F src/delete.c 00af9f08a15ddc5cba5962d3d3e5bf2d67b2e7da F src/expr.c 0080c0f12806eca91e75a23a121a68918e9da357 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c 31900763094a3736a5fc887469202eb579fef2d0 @@ -316,7 +316,7 @@ F src/global.c 508e4087f7b41d688e4762dcf4d4fe28cfbc87f9 F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5 F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 -F src/insert.c 419a947f27ce2da18eebf440a5aa80cc825defae +F src/insert.c e1d20ae8979e25519c2670233718676bedcfedc9 F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e F src/loadext.c 18586e45a215325f15096821e9c082035d4fb810 @@ -339,12 +339,12 @@ F src/os.c 8fd25588eeba74068d41102d26810e216999b6c8 F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf F src/os_common.h abdb9a191a367793268fe553d25bab894e986a0e F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa -F src/os_unix.c cf72e06e15839ebe7121e01d3eebf256c039b0ca -F src/os_win.c 1716291e5ec2dbfc5a1fe0b32182030f1f7d8acf +F src/os_unix.c eb24e0340fbe3cfd0eabfb15a71476953e54fa73 +F src/os_win.c 2d77dab5c555a18c0aff379c6a692fc3499044d9 F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c 18341e2b759b447cbc82fb9215d08d9c5864e92e F src/pager.h 87c4118a71ba3965184148b379a6d93179071091 -F src/parse.y aad5cc866dc23719f361fe7e0b8eaec8ce4861a4 +F src/parse.y 23737e649c26ce327603799e57f5c2ff50e5e6ba F src/pcache.c 73895411fa6b7bd6f0091212feabbe833b358d23 F src/pcache.h 1ff11adce609ba7de139b6abfabaf9a2bac947b5 F src/pcache1.c 902e1bc7bdaa81b40f8543407c5e2ac8ef4dc035 @@ -355,17 +355,17 @@ F src/printf.c f8fc8f04e75b1e983ef2793c27ec7a43b287e94a F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c 1954a0f01bf65d78d7d559aea3d5c67f33376d91 F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e -F src/select.c 4c58ae319df6862e5ea237e757b5d317c4491798 -F src/shell.c 0092cd4e1da5322b7bc35bedbec1f0dea627451e +F src/select.c 2376d320907a5c28c55290f18fd94aa3400bf97c +F src/shell.c f0f59ea60ad297f671b7ae0fb957a736ad17c92c F src/sqlite.h.in fa62718f73553f06b2f2e362fd09ccb4e1cbb626 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 4b66e3e3435da4b4c8c83696d0349f0c503b3924 -F src/sqliteInt.h 1b8c1b37f0bd2cec784c9f257e449f72096b37f8 +F src/sqliteInt.h 25d0792e6d355a27975dc7c49c4514b3f6eb2294 F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e F src/tclsqlite.c d9439b6a910985b7fff43ba6756bcef00de22649 -F src/test1.c 05df2a9e4f483b2fb642162209e3aeb11c24b44f +F src/test1.c 4004bcc1b3b361a9137acd1d875599ecbdd6f961 F src/test2.c 5586f43fcd9a1be0830793cf9d354082c261b25b F src/test3.c a8887dabbbee3059af338f20d290084a63ed1b0f F src/test4.c d168f83cc78d02e8d35567bb5630e40dcd85ac1e @@ -379,7 +379,7 @@ F src/test_autoext.c dea8a01a7153b9adc97bd26161e4226329546e12 F src/test_backup.c 2e6e6a081870150f20c526a2e9d0d29cda47d803 F src/test_blob.c e5a7a81d61a780da79101aeb1e60d300af169e07 F src/test_btree.c 2e9978eca99a9a4bfa8cae949efb00886860a64f -F src/test_config.c 7523f8bd7604aec88a9d1c303d93c925bcfcc9f9 +F src/test_config.c f2824de39f59d8d621e2d6ec5cc67006d000b2eb F src/test_demovfs.c 0de72c2c89551629f58486fde5734b7d90758852 F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc F src/test_fs.c ced436e3d4b8e4681328409b8081051ce614e28f @@ -778,6 +778,7 @@ F test/fuzzer1.test d4c52aaf3ef923da293a2653cfab33d02f718a36 F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536 F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98 F test/hexlit.test 1d312fa816dfd3650a3bb488093bc09a0c927f67 +F test/hidden.test 23c1393a79e846d68fd902d72c85d5e5dcf98711 F test/hook.test 162d7cef7a2d2b04839fe14402934e6a1b79442f F test/icu.test 70df4faca133254c042d02ae342c0a141f2663f4 F test/ieee754.test 118b665a97a8df0e8f2fbdb07d113e596f4a6b53 @@ -965,7 +966,7 @@ F test/rbu.test 168573d353cd0fd10196b87b0caa322c144ef736 F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8 F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8 F test/reindex.test 44edd3966b474468b823d481eafef0c305022254 -F test/releasetest.tcl 30cf0851a6fb0343b65f27dc89ab7bed3c3cc77d +F test/releasetest.tcl 622f2381b217facdf429584a5c292cc1fc47e7c0 F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb F test/rollback.test 458fe73eb3ffdfdf9f6ba3e9b7350a6220414dea F test/rollback2.test fc14cf6d1a2b250d2735ef16124b971bce152f14 @@ -1360,7 +1361,7 @@ F test/zeroblob.test 3857870fe681b8185654414a9bccfde80b62a0fa F test/zerodamage.test cf6748bad89553cc1632be51a6f54e487e4039ac F tool/GetFile.cs a15e08acb5dd7539b75ba23501581d7c2b462cb5 F tool/GetTclKit.bat 8606413d3035c05373a0d7fae82ebf59ae9e16c3 -F tool/addopcodes.tcl f1fd17b639910226749d1ae006beef8f60378274 +F tool/addopcodes.tcl 4ca9c3ef196f08da30add5d07ce0c9458dc8c633 F tool/build-all-msvc.bat e42141ca3c3812315432f9813ef9eb78aa8d99c9 x F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367 F tool/cg_anno.tcl 692ce4b8693d59e3a3de77ca97f4139ecfa641b0 x @@ -1377,7 +1378,7 @@ F tool/lempar.c 3ec1463a034b37d87d782be5f6b8b10a3b1ecbe7 F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6 F tool/mkautoconfamal.sh 4bdf61548a143e5977bd86ab93d68b694d10c8fa -F tool/mkkeywordhash.c 37f9c2e62c31384b697ede8825e2d344e98db22c +F tool/mkkeywordhash.c 06ec0b78bd4fa68c12d90ef2bdfe76b039133ff8 F tool/mkopcodec.tcl edde8adc42621b5e598127f8cdc6d52cfe21f52b F tool/mkopcodeh.tcl e04177031532b7aa9379ded50e820231ac4abd6e F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e @@ -1419,7 +1420,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P aa129c51ecf5c917cfac30be330886f8a10f49e1 -R 0be85f8175b37708c20cac5856fe94dc +P 5c79f53131a7ab3c83f49e35a5021a6cdb2518fc 126b998cf163dcdd5a222634f1e929f04db3c700 +R 3aa36152d0afbf358fe2d9294f027d01 U drh -Z 35d0ab7ac6da941b099070286c057861 +Z a2d9cb37921cba70bc9062c45a920229 diff --git a/manifest.uuid b/manifest.uuid index 61047cebc0..b7d676b362 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5c79f53131a7ab3c83f49e35a5021a6cdb2518fc \ No newline at end of file +8aede091c4740511d11ea14da253fe39bbfe75a6 \ No newline at end of file diff --git a/src/build.c b/src/build.c index 8cb2d44ac7..f928ba3075 100644 --- a/src/build.c +++ b/src/build.c @@ -1049,18 +1049,19 @@ begin_table_error: return; } -/* -** This macro is used to compare two strings in a case-insensitive manner. -** It is slightly faster than calling sqlite3StrICmp() directly, but -** produces larger code. -** -** WARNING: This macro is not compatible with the strcmp() family. It -** returns true if the two strings are equal, otherwise false. +/* Set properties of a table column based on the (magical) +** name of the column. */ -#define STRICMP(x, y) (\ -sqlite3UpperToLower[*(unsigned char *)(x)]== \ -sqlite3UpperToLower[*(unsigned char *)(y)] \ -&& sqlite3StrICmp((x)+1,(y)+1)==0 ) +void sqlite3ColumnPropertiesFromName(Table *pTab, Column *pCol){ +#if SQLITE_ENABLE_HIDDEN_COLUMNS + if( sqlite3_strnicmp(pCol->zName, "__hidden__", 10)==0 ){ + pCol->colFlags |= COLFLAG_HIDDEN; + }else if( pTab && pCol!=pTab->aCol && (pCol[-1].colFlags & COLFLAG_HIDDEN) ){ + pTab->tabFlags |= TF_OOOHidden; + } +#endif +} + /* ** Add a new column to the table currently being constructed. @@ -1086,7 +1087,7 @@ void sqlite3AddColumn(Parse *pParse, Token *pName){ z = sqlite3NameFromToken(db, pName); if( z==0 ) return; for(i=0; inCol; i++){ - if( STRICMP(z, p->aCol[i].zName) ){ + if( sqlite3_stricmp(z, p->aCol[i].zName)==0 ){ sqlite3ErrorMsg(pParse, "duplicate column name: %s", z); sqlite3DbFree(db, z); return; @@ -1104,6 +1105,7 @@ void sqlite3AddColumn(Parse *pParse, Token *pName){ pCol = &p->aCol[p->nCol]; memset(pCol, 0, sizeof(p->aCol[0])); pCol->zName = z; + sqlite3ColumnPropertiesFromName(p, pCol); /* If there is no type specified, columns have the default affinity ** 'BLOB'. If there is a type specified, then sqlite3AddColumnType() will diff --git a/src/delete.c b/src/delete.c index cd683e37d8..ed273bde81 100644 --- a/src/delete.c +++ b/src/delete.c @@ -106,7 +106,8 @@ void sqlite3MaterializeView( assert( pFrom->a[0].pOn==0 ); assert( pFrom->a[0].pUsing==0 ); } - pSel = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, 0, 0, 0); + pSel = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, + SF_IncludeHidden, 0, 0); sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur); sqlite3Select(pParse, pSel, &dest); sqlite3SelectDelete(db, pSel); diff --git a/src/insert.c b/src/insert.c index 3d213a8d37..52769e9c4f 100644 --- a/src/insert.c +++ b/src/insert.c @@ -736,10 +736,8 @@ void sqlite3Insert( /* Make sure the number of columns in the source data matches the number ** of columns to be inserted into the table. */ - if( IsVirtual(pTab) ){ - for(i=0; inCol; i++){ - nHidden += (IsHiddenColumn(&pTab->aCol[i]) ? 1 : 0); - } + for(i=0; inCol; i++){ + nHidden += (IsHiddenColumn(&pTab->aCol[i]) ? 1 : 0); } if( pColumn==0 && nColumn && nColumn!=(pTab->nCol-nHidden) ){ sqlite3ErrorMsg(pParse, @@ -835,15 +833,14 @@ void sqlite3Insert( /* Create the new column data */ - for(i=0; inCol; i++){ - if( pColumn==0 ){ - j = i; - }else{ + for(i=j=0; inCol; i++){ + if( pColumn ){ for(j=0; jnId; j++){ if( pColumn->a[j].idx==i ) break; } } - if( (!useTempTable && !pList) || (pColumn && j>=pColumn->nId) ){ + if( (!useTempTable && !pList) || (pColumn && j>=pColumn->nId) + || (pColumn==0 && IsOrdinaryHiddenColumn(&pTab->aCol[i])) ){ sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regCols+i+1); }else if( useTempTable ){ sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, regCols+i+1); @@ -851,6 +848,7 @@ void sqlite3Insert( assert( pSelect==0 ); /* Otherwise useTempTable is true */ sqlite3ExprCodeAndCache(pParse, pList->a[j].pExpr, regCols+i+1); } + if( pColumn==0 && !IsOrdinaryHiddenColumn(&pTab->aCol[i]) ) j++; } /* If this is an INSERT on a view with an INSTEAD OF INSERT trigger, @@ -934,7 +932,6 @@ void sqlite3Insert( } if( pColumn==0 ){ if( IsHiddenColumn(&pTab->aCol[i]) ){ - assert( IsVirtual(pTab) ); j = -1; nHidden++; }else{ @@ -1876,7 +1873,7 @@ static int xferOptimization( return 0; /* The result set must have exactly one column */ } assert( pEList->a[0].pExpr ); - if( pEList->a[0].pExpr->op!=TK_ALL ){ + if( pEList->a[0].pExpr->op!=TK_ASTERISK ){ return 0; /* The result set must be the special operator "*" */ } @@ -1912,6 +1909,13 @@ static int xferOptimization( for(i=0; inCol; i++){ Column *pDestCol = &pDest->aCol[i]; Column *pSrcCol = &pSrc->aCol[i]; +#ifdef SQLITE_ENABLE_HIDDEN_COLUMNS + if( (db->flags & SQLITE_Vacuum)==0 + && (pDestCol->colFlags | pSrcCol->colFlags) & COLFLAG_HIDDEN + ){ + return 0; /* Neither table may have __hidden__ columns */ + } +#endif if( pDestCol->affinity!=pSrcCol->affinity ){ return 0; /* Affinity must be the same on all columns */ } diff --git a/src/os_unix.c b/src/os_unix.c index b322d238e8..3d4524296b 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -3349,7 +3349,7 @@ static int unixWrite( } #endif -#if SQLITE_MAX_MMAP_SIZE>0 +#if defined(SQLITE_MMAP_READWRITE) && SQLITE_MAX_MMAP_SIZE>0 /* Deal with as much of this write request as possible by transfering ** data from the memory mapping using memcpy(). */ if( offsetmmapSize ){ @@ -4774,7 +4774,9 @@ static void unixRemapfile( assert( pFd->mmapSizeActual>=pFd->mmapSize ); assert( MAP_FAILED!=0 ); +#ifdef SQLITE_MMAP_READWRITE if( (pFd->ctrlFlags & UNIXFILE_RDONLY)==0 ) flags |= PROT_WRITE; +#endif if( pOrig ){ #if HAVE_MREMAP diff --git a/src/os_win.c b/src/os_win.c index 251107528b..9ae40e22af 100644 --- a/src/os_win.c +++ b/src/os_win.c @@ -2602,7 +2602,7 @@ static int winWrite( "offset=%lld, lock=%d\n", osGetCurrentProcessId(), pFile, pFile->h, pBuf, amt, offset, pFile->locktype)); -#if SQLITE_MAX_MMAP_SIZE>0 +#if defined(SQLITE_MMAP_READWRITE) && SQLITE_MAX_MMAP_SIZE>0 /* Deal with as much of this write request as possible by transfering ** data from the memory mapping using memcpy(). */ if( offsetmmapSize ){ @@ -4096,10 +4096,12 @@ static int winMapfile(winFile *pFd, sqlite3_int64 nByte){ DWORD flags = FILE_MAP_READ; winUnmapfile(pFd); +#ifdef SQLITE_MMAP_READWRITE if( (pFd->ctrlFlags & WINFILE_RDONLY)==0 ){ protect = PAGE_READWRITE; flags |= FILE_MAP_WRITE; } +#endif #if SQLITE_OS_WINRT pFd->hMap = osCreateFileMappingFromApp(pFd->h, NULL, protect, nMap, NULL); #elif defined(SQLITE_WIN32_HAS_WIDE) diff --git a/src/parse.y b/src/parse.y index e504e64548..6ac2be21f2 100644 --- a/src/parse.y +++ b/src/parse.y @@ -546,7 +546,7 @@ distinct(A) ::= . {A = 0;} // selcollist is a list of expressions that are to become the return // values of the SELECT statement. The "*" in statements like // "SELECT * FROM ..." is encoded as a special expression with an -// opcode of TK_ALL. +// opcode of TK_ASTERISK. // %type selcollist {ExprList*} %destructor selcollist {sqlite3ExprListDelete(pParse->db, $$);} @@ -560,11 +560,11 @@ selcollist(A) ::= sclp(P) expr(X) as(Y). { sqlite3ExprListSetSpan(pParse,A,&X); } selcollist(A) ::= sclp(P) STAR. { - Expr *p = sqlite3Expr(pParse->db, TK_ALL, 0); + Expr *p = sqlite3Expr(pParse->db, TK_ASTERISK, 0); A = sqlite3ExprListAppend(pParse, P, p); } selcollist(A) ::= sclp(P) nm(X) DOT STAR(Y). { - Expr *pRight = sqlite3PExpr(pParse, TK_ALL, 0, 0, &Y); + Expr *pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0, &Y); Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, &X); Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0); A = sqlite3ExprListAppend(pParse,P, pDot); diff --git a/src/select.c b/src/select.c index 126d4cc282..3d69dfb03a 100644 --- a/src/select.c +++ b/src/select.c @@ -118,7 +118,7 @@ Select *sqlite3SelectNew( memset(pNew, 0, sizeof(*pNew)); } if( pEList==0 ){ - pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db,TK_ALL,0)); + pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db,TK_ASTERISK,0)); } pNew->pEList = pEList; if( pSrc==0 ) pSrc = sqlite3DbMallocZero(db, sizeof(*pSrc)); @@ -1659,6 +1659,7 @@ int sqlite3ColumnsFromExprList( if( cnt>3 ) sqlite3_randomness(sizeof(cnt), &cnt); } pCol->zName = zName; + sqlite3ColumnPropertiesFromName(0, pCol); if( zName && sqlite3HashInsert(&ht, zName, pCol)==pCol ){ db->mallocFailed = 1; } @@ -3937,7 +3938,7 @@ static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){ if( pNewSrc==0 ) return WRC_Abort; *pNew = *p; p->pSrc = pNewSrc; - p->pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db, TK_ALL, 0)); + p->pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db, TK_ASTERISK, 0)); p->op = TK_SELECT; p->pWhere = 0; pNew->pGroupBy = 0; @@ -4278,19 +4279,20 @@ static int selectExpander(Walker *pWalker, Select *p){ /* For every "*" that occurs in the column list, insert the names of ** all columns in all tables. And for every TABLE.* insert the names ** of all columns in TABLE. The parser inserted a special expression - ** with the TK_ALL operator for each "*" that it found in the column list. - ** The following code just has to locate the TK_ALL expressions and expand - ** each one to the list of all columns in all tables. + ** with the TK_ASTERISK operator for each "*" that it found in the column + ** list. The following code just has to locate the TK_ASTERISK + ** expressions and expand each one to the list of all columns in + ** all tables. ** ** The first loop just checks to see if there are any "*" operators ** that need expanding. */ for(k=0; knExpr; k++){ pE = pEList->a[k].pExpr; - if( pE->op==TK_ALL ) break; + if( pE->op==TK_ASTERISK ) break; assert( pE->op!=TK_DOT || pE->pRight!=0 ); assert( pE->op!=TK_DOT || (pE->pLeft!=0 && pE->pLeft->op==TK_ID) ); - if( pE->op==TK_DOT && pE->pRight->op==TK_ALL ) break; + if( pE->op==TK_DOT && pE->pRight->op==TK_ASTERISK ) break; } if( knExpr ){ /* @@ -4308,7 +4310,9 @@ static int selectExpander(Walker *pWalker, Select *p){ pE = a[k].pExpr; pRight = pE->pRight; assert( pE->op!=TK_DOT || pRight!=0 ); - if( pE->op!=TK_ALL && (pE->op!=TK_DOT || pRight->op!=TK_ALL) ){ + if( pE->op!=TK_ASTERISK + && (pE->op!=TK_DOT || pRight->op!=TK_ASTERISK) + ){ /* This particular expression does not need to be expanded. */ pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr); @@ -4360,12 +4364,13 @@ static int selectExpander(Walker *pWalker, Select *p){ continue; } - /* If a column is marked as 'hidden' (currently only possible - ** for virtual tables), do not include it in the expanded - ** result-set list. + /* If a column is marked as 'hidden', omit it from the expanded + ** result-set list unless the SELECT has the SF_IncludeHidden + ** bit set. */ - if( IsHiddenColumn(&pTab->aCol[j]) ){ - assert(IsVirtual(pTab)); + if( (p->selFlags & SF_IncludeHidden)==0 + && IsHiddenColumn(&pTab->aCol[j]) + ){ continue; } tableSeen = 1; diff --git a/src/shell.c b/src/shell.c index 84f693300f..d2f9ca500a 100644 --- a/src/shell.c +++ b/src/shell.c @@ -2560,7 +2560,7 @@ static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){ { "schema size:", "SELECT total(length(sql)) FROM %s" }, }; - sqlite3_file *pFile; + sqlite3_file *pFile = 0; int i; char *zSchemaTab; char *zDb = nArg>=2 ? azArg[1] : "main"; diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 0a1eb770f7..2e1adb82e6 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1673,7 +1673,7 @@ struct Table { /* ** Allowed values for Table.tabFlags. ** -** TF_OOOHidden applies to virtual tables that have hidden columns that are +** TF_OOOHidden applies to tables or view that have hidden columns that are ** followed by non-hidden columns. Example: "CREATE VIRTUAL TABLE x USING ** vtab1(a HIDDEN, b);". Since "b" is a non-hidden column but "a" is hidden, ** the TF_OOOHidden attribute would apply in this case. Such tables require @@ -1696,12 +1696,28 @@ struct Table { */ #ifndef SQLITE_OMIT_VIRTUALTABLE # define IsVirtual(X) (((X)->tabFlags & TF_Virtual)!=0) -# define IsHiddenColumn(X) (((X)->colFlags & COLFLAG_HIDDEN)!=0) #else # define IsVirtual(X) 0 -# define IsHiddenColumn(X) 0 #endif +/* +** Macros to determine if a column is hidden. IsOrdinaryHiddenColumn() +** only works for non-virtual tables (ordinary tables and views) and is +** always false unless SQLITE_ENABLE_HIDDEN_COLUMNS is defined. The +** IsHiddenColumn() macro is general purpose. +*/ +#if defined(SQLITE_ENABLE_HIDDEN_COLUMNS) +# define IsHiddenColumn(X) (((X)->colFlags & COLFLAG_HIDDEN)!=0) +# define IsOrdinaryHiddenColumn(X) (((X)->colFlags & COLFLAG_HIDDEN)!=0) +#elif !defined(SQLITE_OMIT_VIRTUALTABLE) +# define IsHiddenColumn(X) (((X)->colFlags & COLFLAG_HIDDEN)!=0) +# define IsOrdinaryHiddenColumn(X) 0 +#else +# define IsHiddenColumn(X) 0 +# define IsOrdinaryHiddenColumn(X) 0 +#endif + + /* Does the table have a rowid */ #define HasRowid(X) (((X)->tabFlags & TF_WithoutRowid)==0) #define VisibleRowid(X) (((X)->tabFlags & TF_NoVisibleRowid)==0) @@ -2495,6 +2511,7 @@ struct Select { #define SF_MinMaxAgg 0x1000 /* Aggregate containing min() or max() */ #define SF_Recursive 0x2000 /* The recursive part of a recursive CTE */ #define SF_Converted 0x4000 /* By convertCompoundSelectToSubquery() */ +#define SF_IncludeHidden 0x8000 /* Include hidden columns in output */ /* @@ -3314,6 +3331,7 @@ void sqlite3OpenMasterTable(Parse *, int); Index *sqlite3PrimaryKeyIndex(Table*); i16 sqlite3ColumnOfIndex(Index*, i16); void sqlite3StartTable(Parse*,Token*,Token*,int,int,int,int); +void sqlite3ColumnPropertiesFromName(Table*, Column*); void sqlite3AddColumn(Parse*,Token*); void sqlite3AddNotNull(Parse*, int); void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int); diff --git a/src/test1.c b/src/test1.c index 43feb2dc2d..186e4e4684 100644 --- a/src/test1.c +++ b/src/test1.c @@ -2238,7 +2238,6 @@ static int test_config_sqllog( int objc, Tcl_Obj *CONST objv[] ){ - sqlite3_stmt *pStmt; /* First argument */ if( objc!=1 ){ Tcl_WrongNumArgs(interp, 1, objv, ""); return TCL_ERROR; @@ -2248,6 +2247,28 @@ static int test_config_sqllog( } #endif +/* +** Usage: vfs_current_time_int64 +** +** Return the value returned by the default VFS's xCurrentTimeInt64 method. +*/ +static int vfsCurrentTimeInt64( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + i64 t; + sqlite3_vfs *pVfs = sqlite3_vfs_find(0); + if( objc!=1 ){ + Tcl_WrongNumArgs(interp, 1, objv, ""); + return TCL_ERROR; + } + pVfs->xCurrentTimeInt64(pVfs, &t); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(t)); + return TCL_OK; +} + /* ** Usage: sqlite3_next_stmt DB STMT ** @@ -7061,7 +7082,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ #ifdef SQLITE_ENABLE_SQLLOG { "sqlite3_config_sqllog", test_config_sqllog, 0 }, #endif - + { "vfs_current_time_int64", vfsCurrentTimeInt64, 0 }, }; static int bitmask_size = sizeof(Bitmask)*8; static int longdouble_size = sizeof(LONGDOUBLE_TYPE); diff --git a/src/test_config.c b/src/test_config.c index 4cb5c0057a..b84424bbdc 100644 --- a/src/test_config.c +++ b/src/test_config.c @@ -125,6 +125,12 @@ static void set_options(Tcl_Interp *interp){ Tcl_SetVar2(interp, "sqlite_options", "cursorhints", "0", TCL_GLOBAL_ONLY); #endif +#ifdef SQLITE_ENABLE_HIDDEN_COLUMNS + Tcl_SetVar2(interp, "sqlite_options", "hiddencolumns", "1", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "hiddencolumns", "0", TCL_GLOBAL_ONLY); +#endif + #ifdef SQLITE_ENABLE_MEMSYS3 Tcl_SetVar2(interp, "sqlite_options", "mem3", "1", TCL_GLOBAL_ONLY); #else diff --git a/test/hidden.test b/test/hidden.test new file mode 100644 index 0000000000..1db2cad12e --- /dev/null +++ b/test/hidden.test @@ -0,0 +1,153 @@ +# 2015 November 18 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# +# Test the __hidden__ hack. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix hidden + +ifcapable !hiddencolumns { + finish_test + return +} + +do_execsql_test 1.1 { + CREATE TABLE t1(__hidden__a, b); + INSERT INTO t1 VALUES('1'); + INSERT INTO t1(__hidden__a, b) VALUES('x', 'y'); +} {} + +do_execsql_test 1.2 { + SELECT * FROM t1; +} {1 y} + +do_execsql_test 1.3 { + SELECT __hidden__a, * FROM t1; +} {{} 1 x y} + +foreach {tn view} { + 1 { CREATE VIEW v1(a, b, __hidden__c) AS SELECT a, b, c FROM x1 } + 2 { CREATE VIEW v1 AS SELECT a, b, c AS __hidden__c FROM x1 } +} { + do_execsql_test 2.$tn.1 { + DROP TABLE IF EXISTS x1; + CREATE TABLE x1(a, b, c); + INSERT INTO x1 VALUES(1, 2, 3); + } + + catchsql { DROP VIEW v1 } + execsql $view + + do_execsql_test 2.$tn.2 { + SELECT a, b, __hidden__c FROM v1; + } {1 2 3} + + do_execsql_test 2.$tn.3 { + SELECT * FROM v1; + } {1 2} + + do_execsql_test 2.$tn.4 { + CREATE TRIGGER tr1 INSTEAD OF INSERT ON v1 BEGIN + INSERT INTO x1 VALUES(new.a, new.b, new.__hidden__c); + END; + + INSERT INTO v1 VALUES(4, 5); + SELECT * FROM x1; + } {1 2 3 4 5 {}} + + do_execsql_test 2.$tn.5 { + INSERT INTO v1(a, b, __hidden__c) VALUES(7, 8, 9); + SELECT * FROM x1; + } {1 2 3 4 5 {} 7 8 9} +} + +#------------------------------------------------------------------------- +# Test INSERT INTO ... SELECT ... statements that write to tables with +# hidden columns. +# +do_execsql_test 3.1 { + CREATE TABLE t4(a, __hidden__b, c); + INSERT INTO t4 SELECT 1, 2; + SELECT a, __hidden__b, c FROM t4; +} {1 {} 2} + +do_execsql_test 3.2.1 { + CREATE TABLE t5(__hidden__a, b, c); + CREATE TABLE t6(__hidden__a, b, c); + INSERT INTO t6(__hidden__a, b, c) VALUES(1, 2, 3); + INSERT INTO t6(__hidden__a, b, c) VALUES(4, 5, 6); + INSERT INTO t6(__hidden__a, b, c) VALUES(7, 8, 9); +} + +do_execsql_test 3.2.2 { + INSERT INTO t5 SELECT * FROM t6; + SELECT * FROM t5; +} {2 3 5 6 8 9} + +do_execsql_test 3.2.3 { + SELECT __hidden__a FROM t5; +} {{} {} {}} + + +do_execsql_test 3.3.1 { + CREATE TABLE t5a(a, b, __hidden__c); + CREATE TABLE t6a(a, b, __hidden__c); + INSERT INTO t6a(a, b, __hidden__c) VALUES(1, 2, 3); + INSERT INTO t6a(a, b, __hidden__c) VALUES(4, 5, 6); + INSERT INTO t6a(a, b, __hidden__c) VALUES(7, 8, 9); +} + +do_execsql_test 3.3.2 { + INSERT INTO t5a SELECT * FROM t6a; + SELECT * FROM t5a; +} {1 2 4 5 7 8} + +do_execsql_test 3.3.3 { + SELECT __hidden__c FROM t5a; +} {{} {} {}} + +do_execsql_test 3.4.1 { + CREATE TABLE t5b(a, __hidden__b, c); + CREATE TABLE t6b(a, b, __hidden__c); + INSERT INTO t6b(a, b, __hidden__c) VALUES(1, 2, 3); + INSERT INTO t6b(a, b, __hidden__c) VALUES(4, 5, 6); + INSERT INTO t6b(a, b, __hidden__c) VALUES(7, 8, 9); +} + +do_execsql_test 3.4.2 { + INSERT INTO t5b SELECT * FROM t6b; + SELECT * FROM t5b; +} {1 2 4 5 7 8} + +do_execsql_test 3.4.3 { + SELECT __hidden__b FROM t5b; +} {{} {} {}} + +#------------------------------------------------------------------------- +# Test VACUUM +# +reset_db +do_execsql_test 4.1 { + CREATE TABLE t1(a, __hidden__b, c UNIQUE); + INSERT INTO t1(a, __hidden__b, c) VALUES(1, 2, 3); + INSERT INTO t1(a, __hidden__b, c) VALUES(4, 5, 6); + INSERT INTO t1(a, __hidden__b, c) VALUES(7, 8, 9); + DELETE FROM t1 WHERE __hidden__b = 5; + SELECT rowid, a, __hidden__b, c FROM t1; +} {1 1 2 3 3 7 8 9} +do_execsql_test 4.2 { + VACUUM; + SELECT rowid, a, __hidden__b, c FROM t1; +} {1 1 2 3 3 7 8 9} + +finish_test diff --git a/test/releasetest.tcl b/test/releasetest.tcl index f9c4406d40..7f53fd1523 100644 --- a/test/releasetest.tcl +++ b/test/releasetest.tcl @@ -119,6 +119,7 @@ array set ::Configs [strip_comments { -DSQLITE_ENABLE_MEMSYS3=1 -DSQLITE_ENABLE_COLUMN_METADATA=1 -DSQLITE_ENABLE_STAT4 + -DSQLITE_ENABLE_HIDDEN_COLUMNS -DSQLITE_MAX_ATTACHED=125 } "Fast-One" { @@ -145,6 +146,7 @@ array set ::Configs [strip_comments { -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_OMIT_PROGRESS_CALLBACK=1 -DSQLITE_OMIT_VIRTUALTABLE=1 + -DSQLITE_ENABLE_HIDDEN_COLUMNS -DSQLITE_TEMP_STORE=3 --enable-json1 } @@ -213,6 +215,7 @@ array set ::Configs [strip_comments { -DSQLITE_ENABLE_STAT4 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_RTREE + -DSQLITE_ENABLE_HIDDEN_COLUMNS --enable-json1 } diff --git a/tool/addopcodes.tcl b/tool/addopcodes.tcl index bd0b73a35f..84e3994ce8 100644 --- a/tool/addopcodes.tcl +++ b/tool/addopcodes.tcl @@ -37,6 +37,7 @@ set extras { UMINUS UPLUS REGISTER + ASTERISK SPACE ILLEGAL } diff --git a/tool/mkkeywordhash.c b/tool/mkkeywordhash.c index e4d393e3fa..003ed7d66e 100644 --- a/tool/mkkeywordhash.c +++ b/tool/mkkeywordhash.c @@ -328,7 +328,7 @@ static Keyword *findById(int id){ ** output. */ int main(int argc, char **argv){ - int i, j, k, h, m; + int i, j, k, h; int bestSize, bestCount; int count; int nChar;