1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-18 10:21:03 +03:00

Merge recent trunk enhancements into the bloom-filter branch.

FossilOrigin-Name: 11d97fb8be6b5155f38df130d7e828edd0f381e32f651458939b1cb9cb973fff
This commit is contained in:
drh
2021-12-03 16:02:05 +00:00
9 changed files with 188 additions and 113 deletions

View File

@@ -1,5 +1,5 @@
C Merge\strunk\sfixes\sinto\sthe\sbloom-filter\sbranch. C Merge\srecent\strunk\senhancements\sinto\sthe\sbloom-filter\sbranch.
D 2021-12-01T21:07:05.915 D 2021-12-03T16:02:05.551
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -491,10 +491,10 @@ F src/auth.c f4fa91b6a90bbc8e0d0f738aa284551739c9543a367071f55574681e0f24f8cf
F src/backup.c 3014889fa06e20e6adfa0d07b60097eec1f6e5b06671625f476a714d2356513d F src/backup.c 3014889fa06e20e6adfa0d07b60097eec1f6e5b06671625f476a714d2356513d
F src/bitvec.c 7c849aac407230278445cb069bebc5f89bf2ddd87c5ed9459b070a9175707b3d F src/bitvec.c 7c849aac407230278445cb069bebc5f89bf2ddd87c5ed9459b070a9175707b3d
F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
F src/btree.c 13b965a0f3cd57221e3b4e61e24452ec264a5b163de347b03b5039ddcd95cd54 F src/btree.c 81feddbcc60d524518a7afc713b6dab0ad7caadb7370433f117c8c557dcdc889
F src/btree.h 74d64b8f28cfa4a894d14d4ed64fa432cd697b98b61708d4351482ae15913e22 F src/btree.h 74d64b8f28cfa4a894d14d4ed64fa432cd697b98b61708d4351482ae15913e22
F src/btreeInt.h ee9348c4cb9077243b049edc93a82c1f32ca48baeabf2140d41362b9f9139ff7 F src/btreeInt.h ee9348c4cb9077243b049edc93a82c1f32ca48baeabf2140d41362b9f9139ff7
F src/build.c 179b11b07484497052096d88b953b9a6c22cbb0c23ba75c4347e9a99dae4a6c0 F src/build.c 70759481a346322934332485381805c9ba9442bbe7959bf40bdc14140c832517
F src/callback.c 106b585da1edd57d75fa579d823a5218e0bf37f191dbf7417eeb4a8a9a267dbc F src/callback.c 106b585da1edd57d75fa579d823a5218e0bf37f191dbf7417eeb4a8a9a267dbc
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c 8159d5f706551861c18ec6c8f6bdf105e15ea00367f05d9ab65d31a1077facc1 F src/ctime.c 8159d5f706551861c18ec6c8f6bdf105e15ea00367f05d9ab65d31a1077facc1
@@ -539,7 +539,7 @@ F src/os_win.c 77d39873836f1831a9b0b91894fec45ab0e9ca8e067dc8c549e1d1eca1566fe9
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
F src/pager.c bc10c191d18bffd3d76eda5f162799e43a9f875ecfe7c4869f752e2ddef87ea2 F src/pager.c bc10c191d18bffd3d76eda5f162799e43a9f875ecfe7c4869f752e2ddef87ea2
F src/pager.h 4bf9b3213a4b2bebbced5eaa8b219cf25d4a82f385d093cd64b7e93e5285f66f F src/pager.h 4bf9b3213a4b2bebbced5eaa8b219cf25d4a82f385d093cd64b7e93e5285f66f
F src/parse.y 0bd7971a7489bbf6c3726f1b50da6e508bdff8fa493e9cc3f5a96b12cbb2361e F src/parse.y 761b5d30a7ea9bd2db3b3571438cfcceb5f7dbf4fcad6881c8de65bdda07135a
F src/pcache.c 084e638432c610f95aea72b8509f0845d2791293f39d1b82f0c0a7e089c3bb6b F src/pcache.c 084e638432c610f95aea72b8509f0845d2791293f39d1b82f0c0a7e089c3bb6b
F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586 F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
F src/pcache1.c 54881292a9a5db202b2c0ac541c5e3ef9a5e8c4f1c1383adb2601d5499a60e65 F src/pcache1.c 54881292a9a5db202b2c0ac541c5e3ef9a5e8c4f1c1383adb2601d5499a60e65
@@ -551,7 +551,7 @@ F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c
F src/resolve.c 4a1db4aadd802683db40ca2dbbb268187bd195f10cbdb7206dbd8ac988795571 F src/resolve.c 4a1db4aadd802683db40ca2dbbb268187bd195f10cbdb7206dbd8ac988795571
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
F src/select.c a7a3d9f54eb24821ec5f67f2e5589b68a5d42d46fc5849d7376886777d93a85a F src/select.c a7a3d9f54eb24821ec5f67f2e5589b68a5d42d46fc5849d7376886777d93a85a
F src/shell.c.in 975f268ef261773fcbed1e519dfa10c4f33e8b1cffc12120563e61857fff07c6 F src/shell.c.in e7ee6517544d075d9f06ee2571567026b89cf9fbeef16a74918019b1cb425764
F src/sqlite.h.in 5cd209ac7dc4180f0e19292846f40440b8488015849ca0110c70b906b57d68f0 F src/sqlite.h.in 5cd209ac7dc4180f0e19292846f40440b8488015849ca0110c70b906b57d68f0
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 8ff2fd2c166150b2e48639f5e506fb44e29f1a3f65031710b9e89d1c126ac839 F src/sqlite3ext.h 8ff2fd2c166150b2e48639f5e506fb44e29f1a3f65031710b9e89d1c126ac839
@@ -637,10 +637,10 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c ed0398a7adf02c31e34aada42cc86c58f413a7afe5f741a5d373ad087abde028 F src/wal.c ed0398a7adf02c31e34aada42cc86c58f413a7afe5f741a5d373ad087abde028
F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a
F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b
F src/where.c 1b8a6c53c34c59c765190484d245c457bedc211325de4c75a2070432fd67e314 F src/where.c c04c4108028513cf2f264505f2bc3e861c2ed96985d7a5feead4cf76fe057dc1
F src/whereInt.h 23f990791dc428f0bbb31f8ef5026b78b6290272de86185f4822c85f4c774803 F src/whereInt.h 83ae6f7d0fce8b5164d97698790e0005a909b3d06d73df86a4a6bb0d9411861e
F src/wherecode.c 620e81077588a727876a86f87aab310c02fc4e4960691e48153d8a87ca1fa453 F src/wherecode.c 620e81077588a727876a86f87aab310c02fc4e4960691e48153d8a87ca1fa453
F src/whereexpr.c 17bdbf4f5b490e70a18635498f0b910a558f953a9bf80af7f19cbde6e60e6825 F src/whereexpr.c 19394cb463003e9cc9305730b1508b8817a22bb7247170d81234b691a7f05b89
F src/window.c 5d3b397b0c026d0ff5890244ac41359e524c01ae31e78782e1ff418c3e271a9e F src/window.c 5d3b397b0c026d0ff5890244ac41359e524c01ae31e78782e1ff418c3e271a9e
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627 F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627
@@ -1933,7 +1933,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 50ac4de1d7cbb586ea7969e1ae80ea8b021e194edc2fa7db19374b4ee9369bee a818ba2ed635b91e279dde44236fc7446a33db2b46c9409b67021248c01bf4e5 P 0864bfbf079a98beaa484911edb17c3dc728e78eca231d4247b282fd824cc098 8029e6bab508bf0b8ec1df00a829c5d4de2a84d66dc56b9ff03da879ceef7788
R 890b5445e197091ccaaa040621e42f1c R 62eaa6fad42f4285b48b7186b5cb4970
U drh U drh
Z bba2c27b0261227719d25ee9783d113a Z 2d614121b81c56be6760e2166ceb6c54

View File

@@ -1 +1 @@
0864bfbf079a98beaa484911edb17c3dc728e78eca231d4247b282fd824cc098 11d97fb8be6b5155f38df130d7e828edd0f381e32f651458939b1cb9cb973fff

View File

@@ -2693,30 +2693,38 @@ static int removeFromSharingList(BtShared *pBt){
** MX_CELL_SIZE(pBt) bytes with a 4-byte prefix for a left-child ** MX_CELL_SIZE(pBt) bytes with a 4-byte prefix for a left-child
** pointer. ** pointer.
*/ */
static void allocateTempSpace(BtShared *pBt){ static SQLITE_NOINLINE int allocateTempSpace(BtShared *pBt){
if( !pBt->pTmpSpace ){ assert( pBt!=0 );
pBt->pTmpSpace = sqlite3PageMalloc( pBt->pageSize ); assert( pBt->pTmpSpace==0 );
/* This routine is called only by btreeCursor() when allocating the
/* One of the uses of pBt->pTmpSpace is to format cells before ** first write cursor for the BtShared object */
** inserting them into a leaf page (function fillInCell()). If assert( pBt->pCursor!=0 && (pBt->pCursor->curFlags & BTCF_WriteFlag)!=0 );
** a cell is less than 4 bytes in size, it is rounded up to 4 bytes pBt->pTmpSpace = sqlite3PageMalloc( pBt->pageSize );
** by the various routines that manipulate binary cells. Which if( pBt->pTmpSpace==0 ){
** can mean that fillInCell() only initializes the first 2 or 3 BtCursor *pCur = pBt->pCursor;
** bytes of pTmpSpace, but that the first 4 bytes are copied from pBt->pCursor = pCur->pNext; /* Unlink the cursor */
** it into a database page. This is not actually a problem, but it memset(pCur, 0, sizeof(*pCur));
** does cause a valgrind error when the 1 or 2 bytes of unitialized return SQLITE_NOMEM_BKPT;
** data is passed to system call write(). So to avoid this error,
** zero the first 4 bytes of temp space here.
**
** Also: Provide four bytes of initialized space before the
** beginning of pTmpSpace as an area available to prepend the
** left-child pointer to the beginning of a cell.
*/
if( pBt->pTmpSpace ){
memset(pBt->pTmpSpace, 0, 8);
pBt->pTmpSpace += 4;
}
} }
/* One of the uses of pBt->pTmpSpace is to format cells before
** inserting them into a leaf page (function fillInCell()). If
** a cell is less than 4 bytes in size, it is rounded up to 4 bytes
** by the various routines that manipulate binary cells. Which
** can mean that fillInCell() only initializes the first 2 or 3
** bytes of pTmpSpace, but that the first 4 bytes are copied from
** it into a database page. This is not actually a problem, but it
** does cause a valgrind error when the 1 or 2 bytes of unitialized
** data is passed to system call write(). So to avoid this error,
** zero the first 4 bytes of temp space here.
**
** Also: Provide four bytes of initialized space before the
** beginning of pTmpSpace as an area available to prepend the
** left-child pointer to the beginning of a cell.
*/
memset(pBt->pTmpSpace, 0, 8);
pBt->pTmpSpace += 4;
return SQLITE_OK;
} }
/* /*
@@ -4457,10 +4465,6 @@ static int btreeCursor(
assert( pBt->pPage1 && pBt->pPage1->aData ); assert( pBt->pPage1 && pBt->pPage1->aData );
assert( wrFlag==0 || (pBt->btsFlags & BTS_READ_ONLY)==0 ); assert( wrFlag==0 || (pBt->btsFlags & BTS_READ_ONLY)==0 );
if( wrFlag ){
allocateTempSpace(pBt);
if( pBt->pTmpSpace==0 ) return SQLITE_NOMEM_BKPT;
}
if( iTable<=1 ){ if( iTable<=1 ){
if( iTable<1 ){ if( iTable<1 ){
return SQLITE_CORRUPT_BKPT; return SQLITE_CORRUPT_BKPT;
@@ -4477,19 +4481,25 @@ static int btreeCursor(
pCur->pKeyInfo = pKeyInfo; pCur->pKeyInfo = pKeyInfo;
pCur->pBtree = p; pCur->pBtree = p;
pCur->pBt = pBt; pCur->pBt = pBt;
pCur->curFlags = wrFlag ? BTCF_WriteFlag : 0; pCur->curFlags = 0;
pCur->curPagerFlags = wrFlag ? 0 : PAGER_GET_READONLY;
/* If there are two or more cursors on the same btree, then all such /* If there are two or more cursors on the same btree, then all such
** cursors *must* have the BTCF_Multiple flag set. */ ** cursors *must* have the BTCF_Multiple flag set. */
for(pX=pBt->pCursor; pX; pX=pX->pNext){ for(pX=pBt->pCursor; pX; pX=pX->pNext){
if( pX->pgnoRoot==iTable ){ if( pX->pgnoRoot==iTable ){
pX->curFlags |= BTCF_Multiple; pX->curFlags |= BTCF_Multiple;
pCur->curFlags |= BTCF_Multiple; pCur->curFlags = BTCF_Multiple;
} }
} }
pCur->eState = CURSOR_INVALID;
pCur->pNext = pBt->pCursor; pCur->pNext = pBt->pCursor;
pBt->pCursor = pCur; pBt->pCursor = pCur;
pCur->eState = CURSOR_INVALID; if( wrFlag ){
pCur->curFlags |= BTCF_WriteFlag;
pCur->curPagerFlags = 0;
if( pBt->pTmpSpace==0 ) return allocateTempSpace(pBt);
}else{
pCur->curPagerFlags = PAGER_GET_READONLY;
}
return SQLITE_OK; return SQLITE_OK;
} }
static int btreeCursorWithLock( static int btreeCursorWithLock(

View File

@@ -4406,13 +4406,13 @@ void sqlite3CreateIndex(
/* Add an entry in sqlite_schema for this index /* Add an entry in sqlite_schema for this index
*/ */
sqlite3NestedParse(pParse, sqlite3NestedParse(pParse,
"INSERT INTO %Q." LEGACY_SCHEMA_TABLE " VALUES('index',%Q,%Q,#%d,%Q);", "INSERT INTO %Q." LEGACY_SCHEMA_TABLE " VALUES('index',%Q,%Q,#%d,%Q);",
db->aDb[iDb].zDbSName, db->aDb[iDb].zDbSName,
pIndex->zName, pIndex->zName,
pTab->zName, pTab->zName,
iMem, iMem,
zStmt zStmt
); );
sqlite3DbFree(db, zStmt); sqlite3DbFree(db, zStmt);
/* Fill the index with data and reparse the schema. Code an OP_Expire /* Fill the index with data and reparse the schema. Code an OP_Expire

View File

@@ -236,7 +236,7 @@ columnname(A) ::= nm(A) typetoken(Y). {sqlite3AddColumn(pParse,A,Y);}
// //
%token ABORT ACTION AFTER ANALYZE ASC ATTACH BEFORE BEGIN BY CASCADE CAST. %token ABORT ACTION AFTER ANALYZE ASC ATTACH BEFORE BEGIN BY CASCADE CAST.
%token CONFLICT DATABASE DEFERRED DESC DETACH EACH END EXCLUSIVE EXPLAIN FAIL. %token CONFLICT DATABASE DEFERRED DESC DETACH EACH END EXCLUSIVE EXPLAIN FAIL.
%token OR AND NOT IS MATCH LIKE_KW BETWEEN IN ISNULL NOTNULL NE EQ. %token OR AND NOT MATCH LIKE_KW BETWEEN IS IN ISNULL NOTNULL NE EQ.
%token GT LE LT GE ESCAPE. %token GT LE LT GE ESCAPE.
// The following directive causes tokens ABORT, AFTER, ASC, etc. to // The following directive causes tokens ABORT, AFTER, ASC, etc. to

View File

@@ -8941,16 +8941,8 @@ static int do_meta_command(char *zLine, ShellState *p){
char *zNewFilename = 0; /* Name of the database file to open */ char *zNewFilename = 0; /* Name of the database file to open */
int iName = 1; /* Index in azArg[] of the filename */ int iName = 1; /* Index in azArg[] of the filename */
int newFlag = 0; /* True to delete file before opening */ int newFlag = 0; /* True to delete file before opening */
/* Close the existing database */ int openMode = SHELL_OPEN_UNSPEC;
session_close_all(p, -1);
close_db(p->db);
p->db = 0;
p->pAuxDb->zDbFilename = 0;
sqlite3_free(p->pAuxDb->zFreeOnClose);
p->pAuxDb->zFreeOnClose = 0;
p->openMode = SHELL_OPEN_UNSPEC;
p->openFlags = 0;
p->szMax = 0;
/* Check for command-line arguments */ /* Check for command-line arguments */
for(iName=1; iName<nArg; iName++){ for(iName=1; iName<nArg; iName++){
const char *z = azArg[iName]; const char *z = azArg[iName];
@@ -8958,19 +8950,19 @@ static int do_meta_command(char *zLine, ShellState *p){
newFlag = 1; newFlag = 1;
#ifdef SQLITE_HAVE_ZLIB #ifdef SQLITE_HAVE_ZLIB
}else if( optionMatch(z, "zip") ){ }else if( optionMatch(z, "zip") ){
p->openMode = SHELL_OPEN_ZIPFILE; openMode = SHELL_OPEN_ZIPFILE;
#endif #endif
}else if( optionMatch(z, "append") ){ }else if( optionMatch(z, "append") ){
p->openMode = SHELL_OPEN_APPENDVFS; openMode = SHELL_OPEN_APPENDVFS;
}else if( optionMatch(z, "readonly") ){ }else if( optionMatch(z, "readonly") ){
p->openMode = SHELL_OPEN_READONLY; openMode = SHELL_OPEN_READONLY;
}else if( optionMatch(z, "nofollow") ){ }else if( optionMatch(z, "nofollow") ){
p->openFlags |= SQLITE_OPEN_NOFOLLOW; p->openFlags |= SQLITE_OPEN_NOFOLLOW;
#ifndef SQLITE_OMIT_DESERIALIZE #ifndef SQLITE_OMIT_DESERIALIZE
}else if( optionMatch(z, "deserialize") ){ }else if( optionMatch(z, "deserialize") ){
p->openMode = SHELL_OPEN_DESERIALIZE; openMode = SHELL_OPEN_DESERIALIZE;
}else if( optionMatch(z, "hexdb") ){ }else if( optionMatch(z, "hexdb") ){
p->openMode = SHELL_OPEN_HEXDB; openMode = SHELL_OPEN_HEXDB;
}else if( optionMatch(z, "maxsize") && iName+1<nArg ){ }else if( optionMatch(z, "maxsize") && iName+1<nArg ){
p->szMax = integerValue(azArg[++iName]); p->szMax = integerValue(azArg[++iName]);
#endif /* SQLITE_OMIT_DESERIALIZE */ #endif /* SQLITE_OMIT_DESERIALIZE */
@@ -8986,6 +8978,18 @@ static int do_meta_command(char *zLine, ShellState *p){
zNewFilename = sqlite3_mprintf("%s", z); zNewFilename = sqlite3_mprintf("%s", z);
} }
} }
/* Close the existing database */
session_close_all(p, -1);
close_db(p->db);
p->db = 0;
p->pAuxDb->zDbFilename = 0;
sqlite3_free(p->pAuxDb->zFreeOnClose);
p->pAuxDb->zFreeOnClose = 0;
p->openMode = openMode;
p->openFlags = 0;
p->szMax = 0;
/* If a filename is specified, try to open it first */ /* If a filename is specified, try to open it first */
if( zNewFilename || p->openMode==SHELL_OPEN_HEXDB ){ if( zNewFilename || p->openMode==SHELL_OPEN_HEXDB ){
if( newFlag && !p->bSafeMode ) shellDeleteFile(zNewFilename); if( newFlag && !p->bSafeMode ) shellDeleteFile(zNewFilename);

View File

@@ -234,7 +234,12 @@ whereOrInsert_done:
Bitmask sqlite3WhereGetMask(WhereMaskSet *pMaskSet, int iCursor){ Bitmask sqlite3WhereGetMask(WhereMaskSet *pMaskSet, int iCursor){
int i; int i;
assert( pMaskSet->n<=(int)sizeof(Bitmask)*8 ); assert( pMaskSet->n<=(int)sizeof(Bitmask)*8 );
for(i=0; i<pMaskSet->n; i++){ assert( pMaskSet->n>0 || pMaskSet->ix[0]<0 );
assert( iCursor>=-1 );
if( pMaskSet->ix[0]==iCursor ){
return 1;
}
for(i=1; i<pMaskSet->n; i++){
if( pMaskSet->ix[i]==iCursor ){ if( pMaskSet->ix[i]==iCursor ){
return MASKBIT(i); return MASKBIT(i);
} }
@@ -419,16 +424,16 @@ static WhereTerm *whereScanInit(
if( pIdx ){ if( pIdx ){
int j = iColumn; int j = iColumn;
iColumn = pIdx->aiColumn[j]; iColumn = pIdx->aiColumn[j];
if( iColumn==XN_EXPR ){ if( iColumn==pIdx->pTable->iPKey ){
pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr;
pScan->zCollName = pIdx->azColl[j];
pScan->aiColumn[0] = XN_EXPR;
return whereScanInitIndexExpr(pScan);
}else if( iColumn==pIdx->pTable->iPKey ){
iColumn = XN_ROWID; iColumn = XN_ROWID;
}else if( iColumn>=0 ){ }else if( iColumn>=0 ){
pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity; pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity;
pScan->zCollName = pIdx->azColl[j]; pScan->zCollName = pIdx->azColl[j];
}else if( iColumn==XN_EXPR ){
pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr;
pScan->zCollName = pIdx->azColl[j];
pScan->aiColumn[0] = XN_EXPR;
return whereScanInitIndexExpr(pScan);
} }
}else if( iColumn==XN_EXPR ){ }else if( iColumn==XN_EXPR ){
return 0; return 0;
@@ -4876,12 +4881,6 @@ WhereInfo *sqlite3WhereBegin(
if( pOrderBy && pOrderBy->nExpr>=BMS ) pOrderBy = 0; if( pOrderBy && pOrderBy->nExpr>=BMS ) pOrderBy = 0;
sWLB.pOrderBy = pOrderBy; sWLB.pOrderBy = pOrderBy;
/* Disable the DISTINCT optimization if SQLITE_DistinctOpt is set via
** sqlite3_test_ctrl(SQLITE_TESTCTRL_OPTIMIZATIONS,...) */
if( OptimizationDisabled(db, SQLITE_DistinctOpt) ){
wctrlFlags &= ~WHERE_WANT_DISTINCT;
}
/* The number of tables in the FROM clause is limited by the number of /* The number of tables in the FROM clause is limited by the number of
** bits in a Bitmask ** bits in a Bitmask
*/ */
@@ -4928,6 +4927,10 @@ WhereInfo *sqlite3WhereBegin(
memset(&pWInfo->a[0], 0, sizeof(WhereLoop)+nTabList*sizeof(WhereLevel)); memset(&pWInfo->a[0], 0, sizeof(WhereLoop)+nTabList*sizeof(WhereLevel));
assert( pWInfo->eOnePass==ONEPASS_OFF ); /* ONEPASS defaults to OFF */ assert( pWInfo->eOnePass==ONEPASS_OFF ); /* ONEPASS defaults to OFF */
pMaskSet = &pWInfo->sMaskSet; pMaskSet = &pWInfo->sMaskSet;
pMaskSet->n = 0;
pMaskSet->ix[0] = -99; /* Initialize ix[0] to a value that can never be
** a valid cursor number, to avoid an initial
** test for pMaskSet->n==0 in sqlite3WhereGetMask() */
sWLB.pWInfo = pWInfo; sWLB.pWInfo = pWInfo;
sWLB.pWC = &pWInfo->sWC; sWLB.pWC = &pWInfo->sWC;
sWLB.pNew = (WhereLoop*)(((char*)pWInfo)+nByteWInfo); sWLB.pNew = (WhereLoop*)(((char*)pWInfo)+nByteWInfo);
@@ -4940,7 +4943,6 @@ WhereInfo *sqlite3WhereBegin(
/* Split the WHERE clause into separate subexpressions where each /* Split the WHERE clause into separate subexpressions where each
** subexpression is separated by an AND operator. ** subexpression is separated by an AND operator.
*/ */
initMaskSet(pMaskSet);
sqlite3WhereClauseInit(&pWInfo->sWC, pWInfo); sqlite3WhereClauseInit(&pWInfo->sWC, pWInfo);
sqlite3WhereSplit(&pWInfo->sWC, pWhere, TK_AND); sqlite3WhereSplit(&pWInfo->sWC, pWhere, TK_AND);
@@ -4948,7 +4950,9 @@ WhereInfo *sqlite3WhereBegin(
*/ */
if( nTabList==0 ){ if( nTabList==0 ){
if( pOrderBy ) pWInfo->nOBSat = pOrderBy->nExpr; if( pOrderBy ) pWInfo->nOBSat = pOrderBy->nExpr;
if( wctrlFlags & WHERE_WANT_DISTINCT ){ if( (wctrlFlags & WHERE_WANT_DISTINCT)!=0
&& OptimizationEnabled(db, SQLITE_DistinctOpt)
){
pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE; pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
} }
ExplainQueryPlan((pParse, 0, "SCAN CONSTANT ROW")); ExplainQueryPlan((pParse, 0, "SCAN CONSTANT ROW"));
@@ -5009,7 +5013,12 @@ WhereInfo *sqlite3WhereBegin(
} }
if( wctrlFlags & WHERE_WANT_DISTINCT ){ if( wctrlFlags & WHERE_WANT_DISTINCT ){
if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pResultSet) ){ if( OptimizationDisabled(db, SQLITE_DistinctOpt) ){
/* Disable the DISTINCT optimization if SQLITE_DistinctOpt is set via
** sqlite3_test_ctrl(SQLITE_TESTCTRL_OPTIMIZATIONS,...) */
wctrlFlags &= ~WHERE_WANT_DISTINCT;
pWInfo->wctrlFlags &= ~WHERE_WANT_DISTINCT;
}else if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pResultSet) ){
/* The DISTINCT marking is pointless. Ignore it. */ /* The DISTINCT marking is pointless. Ignore it. */
pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE; pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
}else if( pOrderBy==0 ){ }else if( pOrderBy==0 ){

View File

@@ -293,11 +293,11 @@ struct WhereScan {
WhereClause *pWC; /* WhereClause currently being scanned */ WhereClause *pWC; /* WhereClause currently being scanned */
const char *zCollName; /* Required collating sequence, if not NULL */ const char *zCollName; /* Required collating sequence, if not NULL */
Expr *pIdxExpr; /* Search for this index expression */ Expr *pIdxExpr; /* Search for this index expression */
char idxaff; /* Must match this affinity, if zCollName!=NULL */
unsigned char nEquiv; /* Number of entries in aiCur[] and aiColumn[] */
unsigned char iEquiv; /* Next unused slot in aiCur[] and aiColumn[] */
u32 opMask; /* Acceptable operators */
int k; /* Resume scanning at this->pWC->a[this->k] */ int k; /* Resume scanning at this->pWC->a[this->k] */
u32 opMask; /* Acceptable operators */
char idxaff; /* Must match this affinity, if zCollName!=NULL */
unsigned char iEquiv; /* Current slot in aiCur[] and aiColumn[] */
unsigned char nEquiv; /* Number of entries in aiCur[] and aiColumn[] */
int aiCur[11]; /* Cursors in the equivalence class */ int aiCur[11]; /* Cursors in the equivalence class */
i16 aiColumn[11]; /* Corresponding column number in the eq-class */ i16 aiColumn[11]; /* Corresponding column number in the eq-class */
}; };
@@ -378,11 +378,6 @@ struct WhereMaskSet {
int ix[BMS]; /* Cursor assigned to each bit */ int ix[BMS]; /* Cursor assigned to each bit */
}; };
/*
** Initialize a WhereMaskSet object
*/
#define initMaskSet(P) (P)->n=0
/* /*
** This object is a convenience wrapper holding all information needed ** This object is a convenience wrapper holding all information needed
** to construct WhereLoop objects for a particular query. ** to construct WhereLoop objects for a particular query.

View File

@@ -1070,10 +1070,13 @@ static void exprAnalyze(
if( db->mallocFailed ){ if( db->mallocFailed ){
return; return;
} }
assert( pWC->nTerm > idxTerm );
pTerm = &pWC->a[idxTerm]; pTerm = &pWC->a[idxTerm];
pMaskSet = &pWInfo->sMaskSet; pMaskSet = &pWInfo->sMaskSet;
pExpr = pTerm->pExpr; pExpr = pTerm->pExpr;
assert( pExpr!=0 ); /* Because malloc() has not failed */
assert( pExpr->op!=TK_AS && pExpr->op!=TK_COLLATE ); assert( pExpr->op!=TK_AS && pExpr->op!=TK_COLLATE );
pMaskSet->bVarSelect = 0;
prereqLeft = sqlite3WhereExprUsage(pMaskSet, pExpr->pLeft); prereqLeft = sqlite3WhereExprUsage(pMaskSet, pExpr->pLeft);
op = pExpr->op; op = pExpr->op;
if( op==TK_IN ){ if( op==TK_IN ){
@@ -1084,14 +1087,28 @@ static void exprAnalyze(
}else{ }else{
pTerm->prereqRight = sqlite3WhereExprListUsage(pMaskSet, pExpr->x.pList); pTerm->prereqRight = sqlite3WhereExprListUsage(pMaskSet, pExpr->x.pList);
} }
}else if( op==TK_ISNULL ){ prereqAll = prereqLeft | pTerm->prereqRight;
pTerm->prereqRight = 0;
}else{ }else{
pTerm->prereqRight = sqlite3WhereExprUsage(pMaskSet, pExpr->pRight); pTerm->prereqRight = sqlite3WhereExprUsage(pMaskSet, pExpr->pRight);
if( pExpr->pLeft==0
|| ExprHasProperty(pExpr, EP_xIsSelect|EP_IfNullRow)
|| pExpr->x.pList!=0
){
prereqAll = sqlite3WhereExprUsageNN(pMaskSet, pExpr);
}else{
prereqAll = prereqLeft | pTerm->prereqRight;
}
} }
pMaskSet->bVarSelect = 0;
prereqAll = sqlite3WhereExprUsageNN(pMaskSet, pExpr);
if( pMaskSet->bVarSelect ) pTerm->wtFlags |= TERM_VARSELECT; if( pMaskSet->bVarSelect ) pTerm->wtFlags |= TERM_VARSELECT;
#ifdef SQLITE_DEBUG
if( prereqAll!=sqlite3WhereExprUsageNN(pMaskSet, pExpr) ){
printf("\n*** Incorrect prereqAll computed for:\n");
sqlite3TreeViewExpr(0,pExpr,0);
abort();
}
#endif
if( ExprHasProperty(pExpr, EP_FromJoin) ){ if( ExprHasProperty(pExpr, EP_FromJoin) ){
Bitmask x = sqlite3WhereGetMask(pMaskSet, pExpr->iRightJoinTable); Bitmask x = sqlite3WhereGetMask(pMaskSet, pExpr->iRightJoinTable);
prereqAll |= x; prereqAll |= x;
@@ -1525,17 +1542,25 @@ void sqlite3WhereClauseInit(
** sqlite3WhereClauseInit(). ** sqlite3WhereClauseInit().
*/ */
void sqlite3WhereClauseClear(WhereClause *pWC){ void sqlite3WhereClauseClear(WhereClause *pWC){
int i;
WhereTerm *a;
sqlite3 *db = pWC->pWInfo->pParse->db; sqlite3 *db = pWC->pWInfo->pParse->db;
for(i=pWC->nTerm-1, a=pWC->a; i>=0; i--, a++){ if( pWC->nTerm>0 ){
if( a->wtFlags & TERM_DYNAMIC ){ WhereTerm *a = pWC->a;
sqlite3ExprDelete(db, a->pExpr); WhereTerm *aLast = &pWC->a[pWC->nTerm-1];
} while(1){
if( a->wtFlags & TERM_ORINFO ){ if( a->wtFlags & TERM_DYNAMIC ){
whereOrInfoDelete(db, a->u.pOrInfo); sqlite3ExprDelete(db, a->pExpr);
}else if( a->wtFlags & TERM_ANDINFO ){ }
whereAndInfoDelete(db, a->u.pAndInfo); if( a->wtFlags & (TERM_ORINFO|TERM_ANDINFO) ){
if( a->wtFlags & TERM_ORINFO ){
assert( (a->wtFlags & TERM_ANDINFO)==0 );
whereOrInfoDelete(db, a->u.pOrInfo);
}else{
assert( (a->wtFlags & TERM_ANDINFO)!=0 );
whereAndInfoDelete(db, a->u.pAndInfo);
}
}
if( a==aLast ) break;
a++;
} }
} }
if( pWC->a!=pWC->aStatic ){ if( pWC->a!=pWC->aStatic ){
@@ -1548,15 +1573,38 @@ void sqlite3WhereClauseClear(WhereClause *pWC){
** These routines walk (recursively) an expression tree and generate ** These routines walk (recursively) an expression tree and generate
** a bitmask indicating which tables are used in that expression ** a bitmask indicating which tables are used in that expression
** tree. ** tree.
**
** sqlite3WhereExprUsage(MaskSet, Expr) ->
**
** Return a Bitmask of all tables referenced by Expr. Expr can be
** be NULL, in which case 0 is returned.
**
** sqlite3WhereExprUsageNN(MaskSet, Expr) ->
**
** Same as sqlite3WhereExprUsage() except that Expr must not be
** NULL. The "NN" suffix on the name stands for "Not Null".
**
** sqlite3WhereExprListUsage(MaskSet, ExprList) ->
**
** Return a Bitmask of all tables referenced by every expression
** in the expression list ExprList. ExprList can be NULL, in which
** case 0 is returned.
**
** sqlite3WhereExprUsageFull(MaskSet, ExprList) ->
**
** Internal use only. Called only by sqlite3WhereExprUsageNN() for
** complex expressions that require pushing register values onto
** the stack. Many calls to sqlite3WhereExprUsageNN() do not need
** the more complex analysis done by this routine. Hence, the
** computations done by this routine are broken out into a separate
** "no-inline" function to avoid the stack push overhead in the
** common case where it is not needed.
*/ */
Bitmask sqlite3WhereExprUsageNN(WhereMaskSet *pMaskSet, Expr *p){ static SQLITE_NOINLINE Bitmask sqlite3WhereExprUsageFull(
WhereMaskSet *pMaskSet,
Expr *p
){
Bitmask mask; Bitmask mask;
if( p->op==TK_COLUMN && !ExprHasProperty(p, EP_FixedCol) ){
return sqlite3WhereGetMask(pMaskSet, p->iTable);
}else if( ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){
assert( p->op!=TK_IF_NULL_ROW );
return 0;
}
mask = (p->op==TK_IF_NULL_ROW) ? sqlite3WhereGetMask(pMaskSet, p->iTable) : 0; mask = (p->op==TK_IF_NULL_ROW) ? sqlite3WhereGetMask(pMaskSet, p->iTable) : 0;
if( p->pLeft ) mask |= sqlite3WhereExprUsageNN(pMaskSet, p->pLeft); if( p->pLeft ) mask |= sqlite3WhereExprUsageNN(pMaskSet, p->pLeft);
if( p->pRight ){ if( p->pRight ){
@@ -1578,6 +1626,15 @@ Bitmask sqlite3WhereExprUsageNN(WhereMaskSet *pMaskSet, Expr *p){
#endif #endif
return mask; return mask;
} }
Bitmask sqlite3WhereExprUsageNN(WhereMaskSet *pMaskSet, Expr *p){
if( p->op==TK_COLUMN && !ExprHasProperty(p, EP_FixedCol) ){
return sqlite3WhereGetMask(pMaskSet, p->iTable);
}else if( ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){
assert( p->op!=TK_IF_NULL_ROW );
return 0;
}
return sqlite3WhereExprUsageFull(pMaskSet, p);
}
Bitmask sqlite3WhereExprUsage(WhereMaskSet *pMaskSet, Expr *p){ Bitmask sqlite3WhereExprUsage(WhereMaskSet *pMaskSet, Expr *p){
return p ? sqlite3WhereExprUsageNN(pMaskSet,p) : 0; return p ? sqlite3WhereExprUsageNN(pMaskSet,p) : 0;
} }