-C "LATERAL"\smay\snot\sbe\sa\skeyword,\sas\sthat\swould\scause\sproblems\sfor\slegacy\ndatabases\sthat\shave\stables\snamed\s"lateral".\s\sIt\shas\sto\sbe\sparsed\sas\san\nidentifier.
-D 2024-07-20T03:19:40.623
+C Do\snot\sdo\san\searly\sabort\sif\sa\slateral\ssubquery\sis\san\sempty\sset.
+D 2024-07-20T03:57:10.925
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F src/walker.c 7c7ea0115345851c3da4e04e2e239a29983b61fb5b038b94eede6aba462640e2
F src/where.c e411ef973e520428a3cbbf8a348c7b37bc8f7f639ebdabd64f835861364be3ee
F src/whereInt.h 002adc3aa2cc10733b9b27958fdbe893987cd989fab25a9853941c1f9b9b0a65
-F src/wherecode.c c9cac0b0b8e809c5e7e79d7796918907fb685ad99be2aaa9737f9787aa47349c
+F src/wherecode.c e6518bac30e75554996c50ffd4d6d01522de0beb54020446fd498dfc2111a193
F src/whereexpr.c 7d0d34b42b9edfd8e8ca66beb3a6ef63fe211c001af54caf2ccbcd989b783290
F src/window.c 1e40ffc509bae21e466f6106382d238e91eb73edd4ba10e66ca4fd7af2b96896
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/joinE.test d5d182f3812771e2c0d97c9dcf5dbe4c41c8e21c82560e59358731c4a3981d6b
F test/joinF.test 53dd66158806823ea680dd7543b5406af151b5aafa5cd06a7f3231cd94938127
F test/joinH.test 55f69e64da74d4eca2235237f3acb657aef181e22e45daa228e35bba865e0255
-F test/joinL.test d18dc1f85a8254b260ef5d0e1d3695dca65309f20f04b79e0b1cb754fdef9334
+F test/joinL.test 63ce1df014bb648f99b24def9af6f67f8bec0017a87c5bd707a81d417c6213c2
F test/journal1.test c7b768041b7f494471531e17abc2f4f5ebf9e5096984f43ed17c4eb80ba34497
F test/journal2.test 9dac6b4ba0ca79c3b21446bbae993a462c2397c4
F test/journal3.test 7c3cf23ffc77db06601c1fcfc9743de8441cb77db9d1aa931863d94f5ffa140e
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 3c045a96bc65713e5544af82b8547cdcdf93fa20f9b7b0851d77f8c090cc650b
-R f090a6ec615c741ecafebf974126b522
+P 8217bddaf8c0697799c7518746996665bbd1f5a327315d18091a6ab3250f1112
+R 5c22f2a95f0481fb172addeee95820dd
U drh
-Z ff3d32fb657fae9cfdb48424d2f017eb
+Z 86dc0c94580a9c5283fa406f79f2dc76
# Remove this line to create a well-formed Fossil manifest.
return 0;
}
+/*
+** Find an appropriate label for iLevel loop to jump to if it the table
+** for that loop is empty.
+**
+** For a simple query, we might as well jump to the break-address of the
+** outermost loop, halting the query, since if one of the joined tables
+** is empty, the result set will be empty. But that does not work if
+** there are outer joins. Nor does it work if the empty table is a
+** correlated subquery (with the LATERAL keyword).
+*/
+static SQLITE_NOINLINE int haltAddress(
+ WhereInfo *pWInfo,
+ int iLevel,
+ SrcItem *pTabItem
+){
+ if( pTabItem->fg.isLateral==0 ){
+ while( 1 /*exit-by-break*/ ){
+ if( pWInfo->a[iLevel].iLeftJoin ) break;
+ if( pWInfo->a[iLevel].pRJ ) break;
+ if( iLevel==0 ) break;
+ iLevel--;
+ };
+ }
+ return pWInfo->a[iLevel].addrBrk;
+}
+
/*
** Generate code for the start of the iLevel-th loop in the WHERE clause
** implementation described by pWInfo.
sqlite3 *db; /* Database connection */
SrcItem *pTabItem; /* FROM clause term being coded */
int addrBrk; /* Jump here to break out of the loop */
- int addrHalt; /* addrBrk for the outermost loop */
int addrCont; /* Jump here to continue with next cycle */
int iRowidReg = 0; /* Rowid is stored in this register, if not zero */
int iReleaseReg = 0; /* Temp register to free before returning */
VdbeComment((v, "init LEFT JOIN match flag"));
}
- /* Compute a safe address to jump to if we discover that the table for
- ** this loop is empty and can never contribute content. */
- for(j=iLevel; j>0; j--){
- if( pWInfo->a[j].iLeftJoin ) break;
- if( pWInfo->a[j].pRJ ) break;
- }
- addrHalt = pWInfo->a[j].addrBrk;
-
/* Special case of a FROM clause subquery implemented as a co-routine */
if( pTabItem->fg.viaCoroutine ){
int regYield = pTabItem->regReturn;
VdbeCoverageIf(v, pX->op==TK_GE);
sqlite3ReleaseTempReg(pParse, rTemp);
}else{
- sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, addrHalt);
+ sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur,
+ haltAddress(pWInfo, iLevel, pTabItem));
VdbeCoverageIf(v, bRev==0);
VdbeCoverageIf(v, bRev!=0);
}
codeCursorHint(pTabItem, pWInfo, pLevel, 0);
pLevel->op = aStep[bRev];
pLevel->p1 = iCur;
- pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrHalt);
+ pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur,
+ haltAddress(pWInfo, iLevel, pTabItem));
VdbeCoverageIf(v, bRev==0);
VdbeCoverageIf(v, bRev!=0);
pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;