mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-07 02:42:48 +03:00
Early exit if one of the inner loops of a 3-way or larger join is an
empty table. FossilOrigin-Name: eaad6ac707a5960d9518d4049b7b1759e7512727ce87be3c402408144bda0a97
This commit is contained in:
23
manifest
23
manifest
@@ -1,5 +1,5 @@
|
|||||||
C If\sthe\sLHS\sfor\san\sEXCEPT\sor\sINTERSECT\soperator\sis\sempty,\sskip\sover\sthe\ncomputation\sof\sthe\sRHS.
|
C Early\sexit\sif\sone\sof\sthe\sinner\sloops\sof\sa\s3-way\sor\slarger\sjoin\sis\san\nempty\stable.
|
||||||
D 2025-07-02T13:19:24.955
|
D 2025-07-02T14:53:48.889
|
||||||
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
|
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
|
||||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||||
@@ -726,8 +726,8 @@ F src/auth.c 54ab9c6c5803b47c0d45b76ce27eff22a03b4b1f767c5945a3a4eb13aa4c78dc
|
|||||||
F src/backup.c 5c97e8023aab1ce14a42387eb3ae00ba5a0644569e3476f38661fa6f824c3523
|
F src/backup.c 5c97e8023aab1ce14a42387eb3ae00ba5a0644569e3476f38661fa6f824c3523
|
||||||
F src/bitvec.c e242d4496774dfc88fa278177dd23b607dce369ccafb3f61b41638eea2c9b399
|
F src/bitvec.c e242d4496774dfc88fa278177dd23b607dce369ccafb3f61b41638eea2c9b399
|
||||||
F src/btmutex.c 30dada73a819a1ef5b7583786370dce1842e12e1ad941e4d05ac29695528daea
|
F src/btmutex.c 30dada73a819a1ef5b7583786370dce1842e12e1ad941e4d05ac29695528daea
|
||||||
F src/btree.c 20c243f1531c806b112dc5f2cd8e2e81618284d8d04897755338ca40e7eaf29b
|
F src/btree.c 96fcbe6db6af625e5a14c34d8f13688d1d22c5f924a436b12395aaf09ec65944
|
||||||
F src/btree.h 53a4f92a4c79470c18f88e0cf42755e2a74833044b0b4610aa328083379c7767
|
F src/btree.h e823c46d87f63d904d735a24b76146d19f51f04445ea561f71cc3382fd1307f0
|
||||||
F src/btreeInt.h 9c0f9ea5c9b5f4dcaea18111d43efe95f2ac276cd86d770dce10fd99ccc93886
|
F src/btreeInt.h 9c0f9ea5c9b5f4dcaea18111d43efe95f2ac276cd86d770dce10fd99ccc93886
|
||||||
F src/build.c 67c1db4c5e89a8519fe9b6dafc287f6bc3627696b5b8536dc5e06db570d8c05f
|
F src/build.c 67c1db4c5e89a8519fe9b6dafc287f6bc3627696b5b8536dc5e06db570d8c05f
|
||||||
F src/callback.c acae8c8dddda41ee85cfdf19b926eefe830f371069f8aadca3aa39adf5b1c859
|
F src/callback.c acae8c8dddda41ee85cfdf19b926eefe830f371069f8aadca3aa39adf5b1c859
|
||||||
@@ -785,7 +785,7 @@ F src/printf.c 71b6d3a0093bf23f473e25480ca0024e8962681506c75f4ffd3d343a3f0ab113
|
|||||||
F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
|
F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
|
||||||
F src/resolve.c d40fe18d7c2fd0339f5846ffcf7d6809866e380acdf14c76fb2af87e9fe13f64
|
F src/resolve.c d40fe18d7c2fd0339f5846ffcf7d6809866e380acdf14c76fb2af87e9fe13f64
|
||||||
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
|
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
|
||||||
F src/select.c 68b43b6a2de2440fb05aa4745e164fc2347d739b990b63ba494a7b18fc55b200
|
F src/select.c 0d30f9718594b6c208373c28c174432dda5c555bd18a5a3d37fd623fdb64aafb
|
||||||
F src/shell.c.in 4f14a1f5196b6006abc8e73cc8fd6c1a62cf940396f8ba909d6711f35f074bb6
|
F src/shell.c.in 4f14a1f5196b6006abc8e73cc8fd6c1a62cf940396f8ba909d6711f35f074bb6
|
||||||
F src/sqlite.h.in 5c54f2461a1ea529bab8499148a2b238e2d4bb571d59e8ea5322d0c190abb693
|
F src/sqlite.h.in 5c54f2461a1ea529bab8499148a2b238e2d4bb571d59e8ea5322d0c190abb693
|
||||||
F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479
|
F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479
|
||||||
@@ -852,7 +852,7 @@ F src/upsert.c 215328c3f91623c520ec8672c44323553f12caeb4f01b1090ebdca99fdf7b4f1
|
|||||||
F src/utf.c 7267c3fb9e2467020507601af3354c2446c61f444387e094c779dccd5ca62165
|
F src/utf.c 7267c3fb9e2467020507601af3354c2446c61f444387e094c779dccd5ca62165
|
||||||
F src/util.c 36fb1150062957280777655976f3f9a75db236cb8207a0770ceae8d5ec17fcd3
|
F src/util.c 36fb1150062957280777655976f3f9a75db236cb8207a0770ceae8d5ec17fcd3
|
||||||
F src/vacuum.c 1bacdd0a81d2b5dc1c508fbf0d938c89fa78dd8d5b46ec92686d44030d4f4789
|
F src/vacuum.c 1bacdd0a81d2b5dc1c508fbf0d938c89fa78dd8d5b46ec92686d44030d4f4789
|
||||||
F src/vdbe.c 5fb85ec6f2f6cdfb8efac6c4dd4f7eed388dfb5041bf71e1c55f213eb0ed5421
|
F src/vdbe.c e505b8b879a330e8dafbe3ed9582eae2fc671b44a64748d1b58c07e4e0f527da
|
||||||
F src/vdbe.h 93761ed7c6b8bc19524912fd9b9b587d41bf4f1d0ade650a00dadc10518d8958
|
F src/vdbe.h 93761ed7c6b8bc19524912fd9b9b587d41bf4f1d0ade650a00dadc10518d8958
|
||||||
F src/vdbeInt.h 0bc581a9763be385e3af715e8c0a503ba8422c2b7074922faf4bb0d6ae31b15e
|
F src/vdbeInt.h 0bc581a9763be385e3af715e8c0a503ba8422c2b7074922faf4bb0d6ae31b15e
|
||||||
F src/vdbeapi.c f9a4881a9674fec3fa13da35044a1484d3c4b95f9ec891cc8ffb02ef2b7a41df
|
F src/vdbeapi.c f9a4881a9674fec3fa13da35044a1484d3c4b95f9ec891cc8ffb02ef2b7a41df
|
||||||
@@ -867,7 +867,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
|
|||||||
F src/wal.c 20be6f0a25a80b7897cf2a5369bfd37ef198e6f0b6cdef16d83eee856056b159
|
F src/wal.c 20be6f0a25a80b7897cf2a5369bfd37ef198e6f0b6cdef16d83eee856056b159
|
||||||
F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
|
F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
|
||||||
F src/walker.c d5006d6b005e4ea7302ad390957a8d41ed83faa177e412f89bc5600a7462a014
|
F src/walker.c d5006d6b005e4ea7302ad390957a8d41ed83faa177e412f89bc5600a7462a014
|
||||||
F src/where.c f58d41d0923eeb21cab8e4fc87a0b36c0724ff4f279ce95ab2731b4696b8e75a
|
F src/where.c e03e764dcbc205d40b01a033b744c583b090f29df56d2efaa1a12a79d8a1b053
|
||||||
F src/whereInt.h 8d94cb116c9e06205c3d5ac87af065fc044f8cf08bfdccd94b6ea1c1308e65da
|
F src/whereInt.h 8d94cb116c9e06205c3d5ac87af065fc044f8cf08bfdccd94b6ea1c1308e65da
|
||||||
F src/wherecode.c 504f3c1270c3ffd51ebcdf7a31de08aa51a63b33a2ccdf8f5736afe3dfa73d45
|
F src/wherecode.c 504f3c1270c3ffd51ebcdf7a31de08aa51a63b33a2ccdf8f5736afe3dfa73d45
|
||||||
F src/whereexpr.c 566ca4382e07a4ba1fd86c97ae0781cdf84004c7d9c59466bf5db75733548807
|
F src/whereexpr.c 566ca4382e07a4ba1fd86c97ae0781cdf84004c7d9c59466bf5db75733548807
|
||||||
@@ -2208,11 +2208,8 @@ F tool/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd7227350
|
|||||||
F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
|
F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
|
||||||
F tool/warnings.sh 1ad0169b022b280bcaaf94a7fa231591be96b514230ab5c98fbf15cd7df842dd
|
F tool/warnings.sh 1ad0169b022b280bcaaf94a7fa231591be96b514230ab5c98fbf15cd7df842dd
|
||||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||||
P 2d2b61cba44a756a3a41ef5c95bbb0c0b7111f4b679c578fec9bd0b214cca367
|
P 13f096ae8a850a05d4a8684561066f11693ee66289e6568c44ef32822cca06f6
|
||||||
R c6049700927657d653d5f08e5f12e785
|
R 004cef124bcae73b595e9860d518af27
|
||||||
T *branch * empty-table-optimizations
|
|
||||||
T *sym-empty-table-optimizations *
|
|
||||||
T -sym-trunk *
|
|
||||||
U drh
|
U drh
|
||||||
Z de7126eae59d141656689f55b14fd34e
|
Z 93bde8048b1cba4fc1e568dc39724e75
|
||||||
# Remove this line to create a well-formed Fossil manifest.
|
# Remove this line to create a well-formed Fossil manifest.
|
||||||
|
@@ -1 +1 @@
|
|||||||
13f096ae8a850a05d4a8684561066f11693ee66289e6568c44ef32822cca06f6
|
eaad6ac707a5960d9518d4049b7b1759e7512727ce87be3c402408144bda0a97
|
||||||
|
25
src/btree.c
25
src/btree.c
@@ -5667,21 +5667,28 @@ int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return true if the BTree pointed to by cursor pCur contains zero
|
/* Set *pRes to 1 (true) if the BTree pointed to by cursor pCur contains zero
|
||||||
** rows of content. Return false if the table contains content or if
|
** rows of content. Set *pRes to 0 (false) if the table contains content.
|
||||||
** if there is some kind of error. This routine is used as an optimization.
|
** Return SQLITE_OK on success or some error code (ex: SQLITE_NOMEM) if
|
||||||
** Returning false (a false negative) will always result in a correct
|
** something goes wrong.
|
||||||
** answer, though perhaps more slowly. But a false positive (an incorrect
|
|
||||||
** return of true) can yield an incorrect answer.
|
|
||||||
*/
|
*/
|
||||||
int sqlite3BtreeIsEmpty(BtCursor *pCur){
|
int sqlite3BtreeIsEmpty(BtCursor *pCur, int *pRes){
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
assert( cursorOwnsBtShared(pCur) );
|
assert( cursorOwnsBtShared(pCur) );
|
||||||
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
|
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
|
||||||
if( pCur->eState==CURSOR_VALID ) return 0;
|
if( pCur->eState==CURSOR_VALID ){
|
||||||
|
*pRes = 0;
|
||||||
|
return SQLITE_OK;
|
||||||
|
}
|
||||||
rc = moveToRoot(pCur);
|
rc = moveToRoot(pCur);
|
||||||
return rc==SQLITE_EMPTY;
|
if( rc==SQLITE_EMPTY ){
|
||||||
|
*pRes = 1;
|
||||||
|
rc = SQLITE_OK;
|
||||||
|
}else{
|
||||||
|
*pRes = 0;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SQLITE_DEBUG
|
#ifdef SQLITE_DEBUG
|
||||||
|
@@ -317,7 +317,7 @@ struct BtreePayload {
|
|||||||
int sqlite3BtreeInsert(BtCursor*, const BtreePayload *pPayload,
|
int sqlite3BtreeInsert(BtCursor*, const BtreePayload *pPayload,
|
||||||
int flags, int seekResult);
|
int flags, int seekResult);
|
||||||
int sqlite3BtreeFirst(BtCursor*, int *pRes);
|
int sqlite3BtreeFirst(BtCursor*, int *pRes);
|
||||||
int sqlite3BtreeIsEmpty(BtCursor *pCur);
|
int sqlite3BtreeIsEmpty(BtCursor *pCur, int *pRes);
|
||||||
int sqlite3BtreeLast(BtCursor*, int *pRes);
|
int sqlite3BtreeLast(BtCursor*, int *pRes);
|
||||||
int sqlite3BtreeNext(BtCursor*, int flags);
|
int sqlite3BtreeNext(BtCursor*, int flags);
|
||||||
int sqlite3BtreeEof(BtCursor*);
|
int sqlite3BtreeEof(BtCursor*);
|
||||||
|
@@ -3099,6 +3099,7 @@ static int multiSelect(
|
|||||||
if( p->op==TK_UNION ){
|
if( p->op==TK_UNION ){
|
||||||
p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
|
p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
|
||||||
}
|
}
|
||||||
|
if( emptyBypass ) sqlite3VdbeJumpHere(v, emptyBypass);
|
||||||
sqlite3ExprDelete(db, p->pLimit);
|
sqlite3ExprDelete(db, p->pLimit);
|
||||||
p->pLimit = pLimit;
|
p->pLimit = pLimit;
|
||||||
p->iLimit = 0;
|
p->iLimit = 0;
|
||||||
@@ -3121,7 +3122,6 @@ static int multiSelect(
|
|||||||
sqlite3VdbeResolveLabel(v, iCont);
|
sqlite3VdbeResolveLabel(v, iCont);
|
||||||
sqlite3VdbeAddOp2(v, OP_Next, unionTab, iStart); VdbeCoverage(v);
|
sqlite3VdbeAddOp2(v, OP_Next, unionTab, iStart); VdbeCoverage(v);
|
||||||
sqlite3VdbeResolveLabel(v, iBreak);
|
sqlite3VdbeResolveLabel(v, iBreak);
|
||||||
if( emptyBypass ) sqlite3VdbeJumpHere(v, emptyBypass);
|
|
||||||
sqlite3VdbeAddOp2(v, OP_Close, unionTab, 0);
|
sqlite3VdbeAddOp2(v, OP_Close, unionTab, 0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@@ -6417,7 +6417,8 @@ case OP_IfEmpty: { /* jump */
|
|||||||
assert( pC->eCurType==CURTYPE_BTREE );
|
assert( pC->eCurType==CURTYPE_BTREE );
|
||||||
pCrsr = pC->uc.pCursor;
|
pCrsr = pC->uc.pCursor;
|
||||||
assert( pCrsr );
|
assert( pCrsr );
|
||||||
res = sqlite3BtreeIsEmpty(pCrsr);
|
rc = sqlite3BtreeIsEmpty(pCrsr, &res);
|
||||||
|
if( rc ) goto abort_due_to_error;
|
||||||
VdbeBranchTaken(res!=0,2);
|
VdbeBranchTaken(res!=0,2);
|
||||||
if( res ) goto jump_to_p2;
|
if( res ) goto jump_to_p2;
|
||||||
break;
|
break;
|
||||||
|
@@ -7134,6 +7134,12 @@ WhereInfo *sqlite3WhereBegin(
|
|||||||
sqlite3VdbeAddOp4Dup8(v, OP_ColumnsUsed, pTabItem->iCursor, 0, 0,
|
sqlite3VdbeAddOp4Dup8(v, OP_ColumnsUsed, pTabItem->iCursor, 0, 0,
|
||||||
(const u8*)&pTabItem->colUsed, P4_INT64);
|
(const u8*)&pTabItem->colUsed, P4_INT64);
|
||||||
#endif
|
#endif
|
||||||
|
if( ii>=2
|
||||||
|
&& (pTabItem[0].fg.jointype & (JT_LTORJ|JT_LEFT))==0
|
||||||
|
&& pLevel->addrHalt==pWInfo->a[0].addrHalt
|
||||||
|
){
|
||||||
|
sqlite3VdbeAddOp2(v, OP_IfEmpty, pTabItem->iCursor, pLevel->addrHalt);
|
||||||
|
}
|
||||||
}else{
|
}else{
|
||||||
sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
|
sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user