From ad9ff1d5f2db2c90271a07fc6e3c6a3d650094b3 Mon Sep 17 00:00:00 2001 From: drh <> Date: Tue, 6 Dec 2022 15:24:05 +0000 Subject: [PATCH 1/5] Simplified experimental changes to promote the use of co-routines. Less cruft than the coroutines-exp1 branch, but still does not work. Checked in as a work-in-progress. FossilOrigin-Name: e2318a30bf6ad2aeb4c4cb29661bc24ff78eb51bf07decc4b8da1ecac0015ef0 --- manifest | 21 ++++++++------ manifest.uuid | 2 +- src/select.c | 74 ++++++++++++++++++++++++++++++++----------------- src/sqliteInt.h | 1 + src/update.c | 1 + src/vdbe.h | 1 + 6 files changed, 65 insertions(+), 35 deletions(-) diff --git a/manifest b/manifest index 38783ac47e..2fab02d772 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\scompiler\swarnings\sin\sthe\snew\sdynamic\scontinuation\sprompt\slogic\sof\nthe\sCLI. -D 2022-12-06T15:11:13.637 +C Simplified\sexperimental\schanges\sto\spromote\sthe\suse\sof\sco-routines.\s\sLess\ncruft\sthan\sthe\scoroutines-exp1\sbranch,\sbut\sstill\sdoes\snot\swork.\s\sChecked\sin\nas\sa\swork-in-progress. +D 2022-12-06T15:24:05.905 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -645,12 +645,12 @@ F src/printf.c e99ee9741e79ae3873458146f59644276657340385ade4e76a5f5d1c25793764 F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c F src/resolve.c efea4e5fbecfd6d0a9071b0be0d952620991673391b6ffaaf4c277b0bb674633 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 -F src/select.c 56162cde2f71314826f831618eae853205628080afa25cd90faef7a9b761dee4 +F src/select.c cbb0ce95039273f436cdad9308251ab3affd69482fd9927495e1c37875afeeb1 F src/shell.c.in f37273af2d5cd2299091b3c1e260254ebd7cd16d7602426983b36009290e8577 F src/sqlite.h.in 1fe1836879ecbb2e28f00f44eb6092db09a2a06bf072af351c6c2466bd515496 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h c4b9fa7a7e2bcdf850cfeb4b8a91d5ec47b7a00033bc996fd2ee96cbf2741f5f -F src/sqliteInt.h 0c9934acd88e0fa14f0d4743233b4cd7bd7bbc84099ba3cad50d8e69676ce2b9 +F src/sqliteInt.h 5a91a427ab821dd3db556411ec0bf0f02bea796ce9927183979c2a1954ae4630 F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657 F src/status.c 160c445d7d28c984a0eae38c144f6419311ed3eace59b44ac6dafc20db4af749 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 @@ -712,13 +712,13 @@ F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c F src/tokenize.c 1305797eab3542a0896b552c6e7669c972c1468e11e92b370533c1f37a37082b F src/treeview.c 29b1dc7e0f84ba090734febe27393d4719682af0cae1b902d5ebf0236ecebea4 F src/trigger.c 5e68b790f022b8dafbfb0eb244786512a95c9575fc198719d2557d73e5795858 -F src/update.c 5b0302c47cf31b533d5dff04c497ca1d8b9d89c39727e633fbe7b882fd5ac5aa +F src/update.c 3cf1cb45674177e09338bdbe5454fb62207c7f2eb8cea288e74286467e901959 F src/upsert.c 5303dc6c518fa7d4b280ec65170f465c7a70b7ac2b22491598f6d0b4875b3145 F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0 F src/util.c 313f3154e2b85a447326f5dd15de8d31a4df6ab0c3579bd58f426ff634ec9050 F src/vacuum.c 84ce7f01f8a7a08748e107a441db83bcec13970190ddcb0c9ff522adbc1c23fd F src/vdbe.c e744259050ec9bbcd47acf9a03a66fe3305d7429c823995de11ed524ca06d16f -F src/vdbe.h 6d921884cf8ec6a53efba99f8b68e32e955367631743e29039840e781aaf547c +F src/vdbe.h c93d4bc242fc9109558aa6b3ce8acef7effe100a42c148dc63239c488ad6c060 F src/vdbeInt.h e83be1eea422758d42302941e96e59d93193c373da655a87befdc03a851e0f95 F src/vdbeapi.c 959cef4c1e5cb6589e67b3295fe9d3e45cbd109ae6618d57b74c900dbd6be0cd F src/vdbeaux.c 0b81f317c86ed9f4ba822af66a52777fed6e8180edc79d4fc62ffe75c8e52d80 @@ -2067,8 +2067,11 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P c0cfe0582add87981826d124a0763482f51fae4b105b5a970dd56919f1d04d60 -R 19f4ce887fdd7ce982932018e71e1a9d +P 0d80500d358fa1c9b5867c2c8250d278ba813bf2ad81bb0bc3f820a71489b374 +R da3604bd27058bf7971e3104c707bf9f +T *branch * coroutines-exp2 +T *sym-coroutines-exp2 * +T -sym-trunk * U drh -Z 087fdbe4ee41c07ef7676876e727f795 +Z 83efea07fbf822c79733971b25cfb62c # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 16c4d729e4..638c179901 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0d80500d358fa1c9b5867c2c8250d278ba813bf2ad81bb0bc3f820a71489b374 \ No newline at end of file +e2318a30bf6ad2aeb4c4cb29661bc24ff78eb51bf07decc4b8da1ecac0015ef0 \ No newline at end of file diff --git a/src/select.c b/src/select.c index 886ac336f2..8f3e5bb9aa 100644 --- a/src/select.c +++ b/src/select.c @@ -6854,6 +6854,52 @@ static int sameSrcAlias(SrcItem *p0, SrcList *pSrc){ return 0; } +/* +** Return TRUE (non-zero) if the i-th entry in the pTabList SrcList can +** be implemented as a co-routine. The i-th entry is guaranteed to be +** a subquery. +** +** The subquery is implemented as a co-routine if all of the following are +** true: +** +** (1) Either of the following are true: +** (1a) The subquery must be the outer loop because it is either +** (i) the only term in the FROM clause, or because (ii) it +** is the left-most term and a CROSS JOIN or similar requires +** it to be the outer loop. subquery and there is nothing +** (1b) There is nothing that would prevent the subquery from +** being an outer loop and the SQLITE_PREPARE_SAFESQL flag +** is not set. +** (2) The subquery is not a CTE that should be materialized +** (3) The subquery is not part of a left operand for a RIGHT JOIN +** (4) The SQLITE_Coroutine optimization disable flag is not set +*/ +static int fromClauseTermCanBeCoroutine( + Parse *pParse, /* Parsing context */ + SrcList *pTabList, /* FROM clause */ + int i /* Which term of the FROM clause */ +){ + SrcItem *pItem = &pTabList->a[i]; + if( pItem->fg.isCte && pItem->u2.pCteUse->eM10d==M10d_Yes ) return 0;/* (2) */ + if( pTabList->a[0].fg.jointype & JT_LTORJ ) return 0; /* (3) */ + if( OptimizationDisabled(pParse->db, SQLITE_Coroutines) ) return 0; /* (4) */ + if( i==0 ){ + if( pTabList->nSrc==1 ) return 1; /* (1a-i) */ + if( pTabList->a[1].fg.jointype & JT_CROSS ) return 1; /* (1a-ii) */ + if( pParse->prepFlags & SQLITE_PREPARE_SAFEOPT ) return 0; + return 1; + } + if( pParse->prepFlags & SQLITE_PREPARE_SAFEOPT ) return 0; + while( 1 /*exit-by-break*/ ){ + if( pItem->fg.jointype & (JT_OUTER|JT_CROSS) ) return 0; + if( i==0 ) break; + i--; + pItem--; + if( pItem->pSelect!=0 ) return 0; + } + return 1; +} + /* ** Generate code for the SELECT statement given in the p argument. ** @@ -7241,35 +7287,19 @@ int sqlite3Select( pParse->zAuthContext = pItem->zName; /* Generate code to implement the subquery - ** - ** The subquery is implemented as a co-routine if all of the following are - ** true: - ** - ** (1) the subquery is guaranteed to be the outer loop (so that - ** it does not need to be computed more than once), and - ** (2) the subquery is not a CTE that should be materialized - ** (3) the subquery is not part of a left operand for a RIGHT JOIN */ - if( i==0 - && (pTabList->nSrc==1 - || (pTabList->a[1].fg.jointype&(JT_OUTER|JT_CROSS))!=0) /* (1) */ - && (pItem->fg.isCte==0 || pItem->u2.pCteUse->eM10d!=M10d_Yes) /* (2) */ - && (pTabList->a[0].fg.jointype & JT_LTORJ)==0 /* (3) */ - ){ + if( fromClauseTermCanBeCoroutine(pParse, pTabList, i) ){ /* Implement a co-routine that will return a single row of the result ** set on each invocation. */ int addrTop = sqlite3VdbeCurrentAddr(v)+1; -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS - int addrExplain; -#endif pItem->regReturn = ++pParse->nMem; sqlite3VdbeAddOp3(v, OP_InitCoroutine, pItem->regReturn, 0, addrTop); VdbeComment((v, "%!S", pItem)); pItem->addrFillSub = addrTop; sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn); - ExplainQueryPlan2(addrExplain, (pParse, 1, "CO-ROUTINE %!S", pItem)); + ExplainQueryPlan((pParse, 1, "CO-ROUTINE %!S", pItem)); sqlite3Select(pParse, pSub, &dest); pItem->pTab->nRowLogEst = pSub->nSelectRow; pItem->fg.viaCoroutine = 1; @@ -7277,10 +7307,6 @@ int sqlite3Select( sqlite3VdbeEndCoroutine(v, pItem->regReturn); sqlite3VdbeJumpHere(v, addrTop-1); sqlite3ClearTempRegCache(pParse); - /* For SQLITE_SCANSTAT_NCYCLE, all instructions from the - ** OP_InitCoroutine coded above until this point are attributed to - ** the CO-ROUTINE query element. */ - sqlite3VdbeScanStatusRange(v, addrExplain, addrExplain-1, -1); }else if( pItem->fg.isCte && pItem->u2.pCteUse->addrM9e>0 ){ /* This is a CTE for which materialization code has already been ** generated. Invoke the subroutine to compute the materialization, @@ -7335,6 +7361,7 @@ int sqlite3Select( if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr); sqlite3VdbeAddOp2(v, OP_Return, pItem->regReturn, topAddr+1); VdbeComment((v, "end %!S", pItem)); + sqlite3VdbeScanStatusRange(v, addrExplain, addrExplain, -1); sqlite3VdbeJumpHere(v, topAddr); sqlite3ClearTempRegCache(pParse); if( pItem->fg.isCte && pItem->fg.isCorrelated==0 ){ @@ -7344,9 +7371,6 @@ int sqlite3Select( pCteUse->iCur = pItem->iCursor; pCteUse->nRowEst = pSub->nSelectRow; } - /* For SQLITE_SCANSTAT_NCYCLE, all instructions from the - ** OP_Explain to here are attibuted to the MATERIALIZE element. */ - sqlite3VdbeScanStatusRange(v, addrExplain, addrExplain, -1); } if( db->mallocFailed ) goto select_end; pParse->nHeight -= sqlite3SelectExprHeight(p); diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 5a19058bd1..393237358a 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1844,6 +1844,7 @@ struct sqlite3 { #define SQLITE_FlttnUnionAll 0x00800000 /* Disable the UNION ALL flattener */ /* TH3 expects this value ^^^^^^^^^^ See flatten04.test */ #define SQLITE_IndexedExpr 0x01000000 /* Pull exprs from index when able */ +#define SQLITE_Coroutines 0x02000000 /* Co-routines for subqueries */ #define SQLITE_AllOpts 0xffffffff /* All optimizations */ /* diff --git a/src/update.c b/src/update.c index 809b306539..0612b2708d 100644 --- a/src/update.c +++ b/src/update.c @@ -268,6 +268,7 @@ static void updateFromSelect( if( pSelect ) pSelect->selFlags |= SF_OrderByReqd; sqlite3SelectDestInit(&dest, eDest, iEph); dest.iSDParm2 = (pPk ? pPk->nKeyCol : -1); + pParse->prepFlags |= SQLITE_PREPARE_SAFEOPT; sqlite3Select(pParse, pSelect, &dest); sqlite3SelectDelete(db, pSelect); } diff --git a/src/vdbe.h b/src/vdbe.h index a199247434..467c999343 100644 --- a/src/vdbe.h +++ b/src/vdbe.h @@ -165,6 +165,7 @@ typedef struct VdbeOpList VdbeOpList; ** Additional non-public SQLITE_PREPARE_* flags */ #define SQLITE_PREPARE_SAVESQL 0x80 /* Preserve SQL text */ +#define SQLITE_PREPARE_SAFEOPT 0x40 /* Use only safe optimizations */ #define SQLITE_PREPARE_MASK 0x0f /* Mask of public flags */ /* From 05cb9d881e3d92b95d021b68a69ceafd83b7a9a7 Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 8 Dec 2022 13:56:06 +0000 Subject: [PATCH 2/5] Do not use a co-routine on a subquery that is participating in a self-join. FossilOrigin-Name: ea4306a03cd8dd706100dac3f11653068a25c50c5d06c34ad08534aec0a580bc --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/select.c | 21 +++++++++++++++------ 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index f0b15b06fe..5ec42e918f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sthe\slatest\sfixes\sand\senhancements\sfrom\strunk\sinto\sthe\ncoroutines-exp2\sbranch. -D 2022-12-07T21:19:37.022 +C Do\snot\suse\sa\sco-routine\son\sa\ssubquery\sthat\sis\sparticipating\sin\sa\sself-join. +D 2022-12-08T13:56:06.070 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -645,7 +645,7 @@ F src/printf.c e99ee9741e79ae3873458146f59644276657340385ade4e76a5f5d1c25793764 F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c F src/resolve.c efea4e5fbecfd6d0a9071b0be0d952620991673391b6ffaaf4c277b0bb674633 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 -F src/select.c cbb0ce95039273f436cdad9308251ab3affd69482fd9927495e1c37875afeeb1 +F src/select.c 02982768da5a6115a95e2a23778260bb70de326648f4ac72df4b25808b6a9840 F src/shell.c.in bcf8552c82f2c84650e39a6d638373569c2035942c0497b83eef197169e0305a F src/sqlite.h.in 1fe1836879ecbb2e28f00f44eb6092db09a2a06bf072af351c6c2466bd515496 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 @@ -2067,8 +2067,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P e2318a30bf6ad2aeb4c4cb29661bc24ff78eb51bf07decc4b8da1ecac0015ef0 212927e97e7be7d237de08359dce0dfb9211ac406b32009a6e15afd79c006475 -R 595e9e236a565d9694fd65430bde0de2 +P 1c5f41986f5af181bf389675361c9f176e9195e847319f07ebd5c87992ded38b +R 849bd6889c31d0dff4fc6b0e1b1e8fd9 U drh -Z 74db0241280ec72e600d83e58941c231 +Z 23e16e45b1613dcb72a8da9bb4a744cf # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index e720758277..2aa30fb03b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1c5f41986f5af181bf389675361c9f176e9195e847319f07ebd5c87992ded38b \ No newline at end of file +ea4306a03cd8dd706100dac3f11653068a25c50c5d06c34ad08534aec0a580bc \ No newline at end of file diff --git a/src/select.c b/src/select.c index 8f3e5bb9aa..827bfb7cf6 100644 --- a/src/select.c +++ b/src/select.c @@ -6697,18 +6697,23 @@ static void havingToWhere(Parse *pParse, Select *p){ } /* -** Check to see if the pThis entry of pTabList is a self-join of a prior view. -** If it is, then return the SrcItem for the prior view. If it is not, -** then return 0. +** Check to see if the pThis entry of pTabList is a self-join of another view. +** Search FROM-clause entries in the range of iFirst..iEnd, including iFirst +** but stopping before iEnd. +** +** If pThis is a self-join, then return the SrcItem for the first other +** instance of that view found. If pThis is not a self-join then return 0. */ static SrcItem *isSelfJoinView( SrcList *pTabList, /* Search for self-joins in this FROM clause */ - SrcItem *pThis /* Search for prior reference to this subquery */ + SrcItem *pThis, /* Search for prior reference to this subquery */ + int iFirst, int iEnd /* Range of FROM-clause entries to search. */ ){ SrcItem *pItem; assert( pThis->pSelect!=0 ); if( pThis->pSelect->selFlags & SF_PushDown ) return 0; - for(pItem = pTabList->a; pItema[iFirst++]; Select *pS1; if( pItem->pSelect==0 ) continue; if( pItem->fg.viaCoroutine ) continue; @@ -6873,6 +6878,7 @@ static int sameSrcAlias(SrcItem *p0, SrcList *pSrc){ ** (2) The subquery is not a CTE that should be materialized ** (3) The subquery is not part of a left operand for a RIGHT JOIN ** (4) The SQLITE_Coroutine optimization disable flag is not set +** (5) The subquery is not self-joined */ static int fromClauseTermCanBeCoroutine( Parse *pParse, /* Parsing context */ @@ -6883,6 +6889,9 @@ static int fromClauseTermCanBeCoroutine( if( pItem->fg.isCte && pItem->u2.pCteUse->eM10d==M10d_Yes ) return 0;/* (2) */ if( pTabList->a[0].fg.jointype & JT_LTORJ ) return 0; /* (3) */ if( OptimizationDisabled(pParse->db, SQLITE_Coroutines) ) return 0; /* (4) */ + if( isSelfJoinView(pTabList, pItem, i+1, pTabList->nSrc)!=0 ){ + return 0; /* (5) */ + } if( i==0 ){ if( pTabList->nSrc==1 ) return 1; /* (1a-i) */ if( pTabList->a[1].fg.jointype & JT_CROSS ) return 1; /* (1a-ii) */ @@ -7319,7 +7328,7 @@ int sqlite3Select( VdbeComment((v, "%!S", pItem)); } pSub->nSelectRow = pCteUse->nRowEst; - }else if( (pPrior = isSelfJoinView(pTabList, pItem))!=0 ){ + }else if( (pPrior = isSelfJoinView(pTabList, pItem, 0, i))!=0 ){ /* This view has already been materialized by a prior entry in ** this same FROM clause. Reuse it. */ if( pPrior->addrFillSub ){ From a60d61bf14ef0aadeabaaebea7fdfd53121c1b1d Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 8 Dec 2022 16:47:16 +0000 Subject: [PATCH 3/5] Improved comments on the new co-routine logic. Fix a C++-ism in the code. Update test cases to accommodate the more aggressive use of co-routines. FossilOrigin-Name: 9243e850ae656d16adc8f0e5c4dcf3dcf476312cee192c39c38685fc437ccbbd --- manifest | 20 ++++++++++---------- manifest.uuid | 2 +- src/select.c | 45 +++++++++++++++++++++++++-------------------- test/cast.test | 2 +- test/eqp.test | 18 +++++++++--------- test/with3.test | 6 +++--- test/with6.test | 8 ++++---- 7 files changed, 53 insertions(+), 48 deletions(-) diff --git a/manifest b/manifest index 5ec42e918f..aa4c045b1d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Do\snot\suse\sa\sco-routine\son\sa\ssubquery\sthat\sis\sparticipating\sin\sa\sself-join. -D 2022-12-08T13:56:06.070 +C Improved\scomments\son\sthe\snew\sco-routine\slogic.\s\sFix\sa\sC++-ism\sin\sthe\scode.\nUpdate\stest\scases\sto\saccommodate\sthe\smore\saggressive\suse\sof\sco-routines. +D 2022-12-08T16:47:16.777 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -645,7 +645,7 @@ F src/printf.c e99ee9741e79ae3873458146f59644276657340385ade4e76a5f5d1c25793764 F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c F src/resolve.c efea4e5fbecfd6d0a9071b0be0d952620991673391b6ffaaf4c277b0bb674633 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 -F src/select.c 02982768da5a6115a95e2a23778260bb70de326648f4ac72df4b25808b6a9840 +F src/select.c 6ec3f7a1760b302193e9155453d42598192f6ad07e875038bf1177e4ce7af728 F src/shell.c.in bcf8552c82f2c84650e39a6d638373569c2035942c0497b83eef197169e0305a F src/sqlite.h.in 1fe1836879ecbb2e28f00f44eb6092db09a2a06bf072af351c6c2466bd515496 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 @@ -863,7 +863,7 @@ F test/capi3c.test 54e2dc0c8fd7c34ad1590d1be6864397da2438c95a9f5aee2f8fbc60c112e F test/capi3d.test 8b778794af891b0dca3d900bd345fbc8ebd2aa2aae425a9dccdd10d5233dfbde F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe F test/carray01.test d55d57bf66b1af1c7ac55fae66ff4910884a8f5d21a90a18797ce386212a2634 -F test/cast.test 6064022ba9af31a8a2ff7bb345e5bd0e74172ffad85bdab5898a42d8227c7585 +F test/cast.test 336fa21989b5170ebcaf90c24266be22dd97b3e23d1fad5ecf6ad4efb04c4423 F test/cffault.test 9d6b20606afe712374952eec4f8fd74b1a8097ef F test/changes.test 9dd8e597d84072122fc8a4fcdea837f4a54a461e6e536053ea984303e8ca937b F test/changes2.test d222c0cbf5ab0ac4d7c180594e486c1bf20b2098d33e56ce33b8e12eba6823b9 @@ -991,7 +991,7 @@ F test/enc.test 9a7be5479da985381d740b15f432800f65e2c87029ee57a318f42cb2eb43763a F test/enc2.test 848bf05f15b011719f478dddb7b5e9aea35e39e457493cba4c4eef75d849a5ec F test/enc3.test 55ef64416d72975c66167310a51dc9fc544ba3ae4858b8d5ab22f4cb6500b087 F test/enc4.test c8f1ce3618508fd0909945beb8b8831feef2c020 -F test/eqp.test 473aea9599b4b7af46614b55198cd78167e4eccd48e60812a40db47c5c41dea9 +F test/eqp.test f3f7548d2f3df03e2f23ecaf35c7c2cc7b89848bd7c3606d94a010521b7ea4f6 F test/errmsg.test eae9f091eb39ce7e20305de45d8e5d115b68fa856fba4ea6757b6ca3705ff7f9 F test/eval.test 73969a2d43a511bf44080c44485a8c4d796b6a4f038d19e491867081155692c0 F test/exclusive.test 7ff63be7503990921838d5c9f77f6e33e68e48ed1a9d48cd28745bf650bf0747 @@ -1942,10 +1942,10 @@ F test/windowfault.test 15094c1529424e62f798bc679e3fe9dfab6e8ba2f7dfe8c923b6248c F test/windowpushd.test d8895d08870b7226f7693665bd292eb177e62ca06799184957b3ca7dc03067df F test/with1.test 9ad67fdeb2bbd808a5763c9060e214ea232f9b18d846ea3a59756dc38bdc3880 F test/with2.test a1df41b987198383b9b70bf5e5fda390582e46398653858dbc6ceb24253b28df -F test/with3.test 1e2e8d5e7b1d955342d0d18c250aaaa6e6bcf36ef2a818477bd01cb74f9a5d66 +F test/with3.test e7bf809bf75c1f44f98bca78bc331dbf542002c5227bf53c1261144db4e824c8 F test/with4.test 257be66c0c67fee1defbbac0f685c3465e2cad037f21ce65f23f86084f198205 F test/with5.test 6248213c41fab36290b5b73aa3f937309dfba337004d9d8434c3fabc8c7d4be8 -F test/with6.test c18592592b5a1c5802fd4e933d506f7b34ebbe8fdd585229793e960ae58d433f +F test/with6.test ae570b31bf1f6fab6210fb1caf6dfa9a6d69c0e6633beb905583bb158a5e309e F test/withM.test 693b61765f2b387b5e3e24a4536e2e82de15ff64 F test/without_rowid1.test a5210b8770dc4736bca4e74bc96588f43025ad03ad6a80f885afd36d9890e217 F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99 @@ -2067,8 +2067,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 1c5f41986f5af181bf389675361c9f176e9195e847319f07ebd5c87992ded38b -R 849bd6889c31d0dff4fc6b0e1b1e8fd9 +P ea4306a03cd8dd706100dac3f11653068a25c50c5d06c34ad08534aec0a580bc +R c0ee619126b867e19f0a23327a8098db U drh -Z 23e16e45b1613dcb72a8da9bb4a744cf +Z d537a6db68af607fd73e77d57f16a3f5 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 2aa30fb03b..118bbb8ad4 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ea4306a03cd8dd706100dac3f11653068a25c50c5d06c34ad08534aec0a580bc \ No newline at end of file +9243e850ae656d16adc8f0e5c4dcf3dcf476312cee192c39c38685fc437ccbbd \ No newline at end of file diff --git a/src/select.c b/src/select.c index 827bfb7cf6..c097d23e47 100644 --- a/src/select.c +++ b/src/select.c @@ -6713,8 +6713,8 @@ static SrcItem *isSelfJoinView( assert( pThis->pSelect!=0 ); if( pThis->pSelect->selFlags & SF_PushDown ) return 0; while( iFirsta[iFirst++]; Select *pS1; + pItem = &pTabList->a[iFirst++]; if( pItem->pSelect==0 ) continue; if( pItem->fg.viaCoroutine ) continue; if( pItem->zName==0 ) continue; @@ -6867,44 +6867,49 @@ static int sameSrcAlias(SrcItem *p0, SrcList *pSrc){ ** The subquery is implemented as a co-routine if all of the following are ** true: ** -** (1) Either of the following are true: -** (1a) The subquery must be the outer loop because it is either -** (i) the only term in the FROM clause, or because (ii) it -** is the left-most term and a CROSS JOIN or similar requires -** it to be the outer loop. subquery and there is nothing -** (1b) There is nothing that would prevent the subquery from -** being an outer loop and the SQLITE_PREPARE_SAFESQL flag -** is not set. -** (2) The subquery is not a CTE that should be materialized +** (1) The subquery will likely be implemented in the outer loop of +** the query. This will be the case if any one of the following +** conditions hold: +** (a) The subquery is the only term in the FROM clause +** (b) The subquery is the left-most term and a CROSS JOIN or similar +** requires it to be the outer loop +** (c) All of the following are true: +** (i) The subquery is the left-most subquery in the FROM clause +** (ii) There is nothing that would prevent the subquery from +** being used as the outer loop if the sqlite3WhereBegin() +** routine nominates it to that position. +** (iii) The SQLITE_PREPARE_SAFEOPT flag is not set +** (2) The subquery is not a CTE that should be materialized because of +** the AS MATERIALIZED keywords ** (3) The subquery is not part of a left operand for a RIGHT JOIN ** (4) The SQLITE_Coroutine optimization disable flag is not set ** (5) The subquery is not self-joined */ static int fromClauseTermCanBeCoroutine( - Parse *pParse, /* Parsing context */ - SrcList *pTabList, /* FROM clause */ - int i /* Which term of the FROM clause */ + Parse *pParse, /* Parsing context */ + SrcList *pTabList, /* FROM clause */ + int i /* Which term of the FROM clause holds the subquery */ ){ SrcItem *pItem = &pTabList->a[i]; if( pItem->fg.isCte && pItem->u2.pCteUse->eM10d==M10d_Yes ) return 0;/* (2) */ if( pTabList->a[0].fg.jointype & JT_LTORJ ) return 0; /* (3) */ if( OptimizationDisabled(pParse->db, SQLITE_Coroutines) ) return 0; /* (4) */ if( isSelfJoinView(pTabList, pItem, i+1, pTabList->nSrc)!=0 ){ - return 0; /* (5) */ + return 0; /* (5) */ } if( i==0 ){ - if( pTabList->nSrc==1 ) return 1; /* (1a-i) */ - if( pTabList->a[1].fg.jointype & JT_CROSS ) return 1; /* (1a-ii) */ - if( pParse->prepFlags & SQLITE_PREPARE_SAFEOPT ) return 0; + if( pTabList->nSrc==1 ) return 1; /* (1a) */ + if( pTabList->a[1].fg.jointype & JT_CROSS ) return 1; /* (1b) */ + if( pParse->prepFlags & SQLITE_PREPARE_SAFEOPT ) return 0; /* (1c-iii) */ return 1; } - if( pParse->prepFlags & SQLITE_PREPARE_SAFEOPT ) return 0; + if( pParse->prepFlags & SQLITE_PREPARE_SAFEOPT ) return 0; /* (1c-iii) */ while( 1 /*exit-by-break*/ ){ - if( pItem->fg.jointype & (JT_OUTER|JT_CROSS) ) return 0; + if( pItem->fg.jointype & (JT_OUTER|JT_CROSS) ) return 0; /* (1c-ii) */ if( i==0 ) break; i--; pItem--; - if( pItem->pSelect!=0 ) return 0; + if( pItem->pSelect!=0 ) return 0; /* (1c-i) */ } return 1; } diff --git a/test/cast.test b/test/cast.test index cbeec47c9d..6ac9bc7efa 100644 --- a/test/cast.test +++ b/test/cast.test @@ -481,7 +481,7 @@ do_execsql_test cast-9.0 { CREATE VIEW v1(c0, c1) AS SELECT CAST(0.0 AS NUMERIC), COUNT(*) OVER () FROM t0; SELECT v1.c0 FROM v1, t0 WHERE v1.c0=0; -} {0} +} {0.0} finish_test diff --git a/test/eqp.test b/test/eqp.test index eda95776f2..61fd617d89 100644 --- a/test/eqp.test +++ b/test/eqp.test @@ -94,7 +94,7 @@ do_eqp_test 1.7.1 { SELECT * FROM t3 JOIN (SELECT 1) } { QUERY PLAN - |--MATERIALIZE (subquery-xxxxxx) + |--CO-ROUTINE (subquery-xxxxxx) | `--SCAN CONSTANT ROW |--SCAN (subquery-xxxxxx) `--SCAN t3 @@ -103,7 +103,7 @@ do_eqp_test 1.7.2 { SELECT * FROM t3 JOIN (SELECT 1) AS v1 } { QUERY PLAN - |--MATERIALIZE v1 + |--CO-ROUTINE v1 | `--SCAN CONSTANT ROW |--SCAN v1 `--SCAN t3 @@ -112,7 +112,7 @@ do_eqp_test 1.7.3 { SELECT * FROM t3 AS xx JOIN (SELECT 1) AS yy } { QUERY PLAN - |--MATERIALIZE yy + |--CO-ROUTINE yy | `--SCAN CONSTANT ROW |--SCAN yy `--SCAN xx @@ -123,7 +123,7 @@ do_eqp_test 1.8 { SELECT * FROM t3 JOIN (SELECT 1 UNION SELECT 2) } { QUERY PLAN - |--MATERIALIZE (subquery-xxxxxx) + |--CO-ROUTINE (subquery-xxxxxx) | `--COMPOUND QUERY | |--LEFT-MOST SUBQUERY | | `--SCAN CONSTANT ROW @@ -136,7 +136,7 @@ do_eqp_test 1.9 { SELECT * FROM t3 JOIN (SELECT 1 EXCEPT SELECT a FROM t3 LIMIT 17) AS abc } { QUERY PLAN - |--MATERIALIZE abc + |--CO-ROUTINE abc | `--COMPOUND QUERY | |--LEFT-MOST SUBQUERY | | `--SCAN CONSTANT ROW @@ -149,7 +149,7 @@ do_eqp_test 1.10 { SELECT * FROM t3 JOIN (SELECT 1 INTERSECT SELECT a FROM t3 LIMIT 17) AS abc } { QUERY PLAN - |--MATERIALIZE abc + |--CO-ROUTINE abc | `--COMPOUND QUERY | |--LEFT-MOST SUBQUERY | | `--SCAN CONSTANT ROW @@ -163,7 +163,7 @@ do_eqp_test 1.11 { SELECT * FROM t3 JOIN (SELECT 1 UNION ALL SELECT a FROM t3 LIMIT 17) abc } { QUERY PLAN - |--MATERIALIZE abc + |--CO-ROUTINE abc | `--COMPOUND QUERY | |--LEFT-MOST SUBQUERY | | `--SCAN CONSTANT ROW @@ -295,7 +295,7 @@ det 3.2.2 { ORDER BY x2.y LIMIT 5 } { QUERY PLAN - |--MATERIALIZE x1 + |--CO-ROUTINE x1 | |--SCAN t1 | `--USE TEMP B-TREE FOR ORDER BY |--MATERIALIZE x2 @@ -834,7 +834,7 @@ do_eqp_test 9.1 { ORDER BY 1; } { QUERY PLAN - |--MATERIALIZE thread + |--CO-ROUTINE thread | |--SCAN x USING INDEX forumthread | |--USING ROWID SEARCH ON TABLE private FOR IN-OPERATOR | |--CORRELATED SCALAR SUBQUERY xxxxxx diff --git a/test/with3.test b/test/with3.test index 1aed92a99a..85889453a0 100644 --- a/test/with3.test +++ b/test/with3.test @@ -89,7 +89,7 @@ ifcapable analyze { SELECT * FROM cnt, y1 WHERE i=a } [string map {"\n " \n} { QUERY PLAN - |--MATERIALIZE cnt + |--CO-ROUTINE cnt | |--SETUP | | `--SCAN CONSTANT ROW | `--RECURSIVE STEP @@ -103,7 +103,7 @@ ifcapable analyze { SELECT * FROM cnt, y1 WHERE i=a } [string map {"\n " \n} { QUERY PLAN - |--MATERIALIZE cnt + |--CO-ROUTINE cnt | |--SETUP | | `--SCAN CONSTANT ROW | `--RECURSIVE STEP @@ -125,7 +125,7 @@ do_eqp_test 3.2.2 { WHERE c.id=w2.pk AND c.id=w1.pk; } { QUERY PLAN - |--MATERIALIZE c + |--CO-ROUTINE c | |--SETUP | | |--SCAN CONSTANT ROW | | `--SCALAR SUBQUERY xxxxxx diff --git a/test/with6.test b/test/with6.test index 20e518b01a..7fce34687e 100644 --- a/test/with6.test +++ b/test/with6.test @@ -87,7 +87,7 @@ do_eqp_test 131 { (SELECT x FROM c LIMIT 5) AS c3; } { QUERY PLAN - |--MATERIALIZE c1 + |--CO-ROUTINE c1 | |--CO-ROUTINE c | | `--SCAN 2 CONSTANT ROWS | `--SCAN c @@ -123,7 +123,7 @@ do_eqp_test 141 { (SELECT x FROM c LIMIT 7) AS c3; } { QUERY PLAN - |--MATERIALIZE c1 + |--CO-ROUTINE c1 | |--MATERIALIZE c | | `--SCAN 2 CONSTANT ROWS | `--SCAN c @@ -151,7 +151,7 @@ do_eqp_test 151 { (SELECT x FROM c LIMIT 7) AS c3; } { QUERY PLAN - |--MATERIALIZE c1 + |--CO-ROUTINE c1 | |--MATERIALIZE c | | `--SCAN 2 CONSTANT ROWS | `--SCAN c @@ -228,7 +228,7 @@ do_eqp_test 211 { SELECT y FROM t2 ORDER BY y; } { QUERY PLAN - |--MATERIALIZE c1 + |--CO-ROUTINE c1 | |--CO-ROUTINE c | | `--SCAN 3 CONSTANT ROWS | `--SCAN c From e974e73f69adc314367b4c26f9d0c6fc0163fa23 Mon Sep 17 00:00:00 2001 From: drh <> Date: Fri, 9 Dec 2022 17:33:21 +0000 Subject: [PATCH 4/5] Do not allow OOM faults in EQP messages associated with automatic indexes on co-routines to go unreported. FossilOrigin-Name: d125d5afdf1b0a1c64fc64f180898099af07b8290ea9da49419df75d8b455f71 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/where.c | 18 ++++++++++++------ 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index aa4c045b1d..8050d01280 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improved\scomments\son\sthe\snew\sco-routine\slogic.\s\sFix\sa\sC++-ism\sin\sthe\scode.\nUpdate\stest\scases\sto\saccommodate\sthe\smore\saggressive\suse\sof\sco-routines. -D 2022-12-08T16:47:16.777 +C Do\snot\sallow\sOOM\sfaults\sin\sEQP\smessages\sassociated\swith\sautomatic\sindexes\non\sco-routines\sto\sgo\sunreported. +D 2022-12-09T17:33:21.007 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -732,7 +732,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c b9df133a705093da8977da5eb202eaadb844839f1c7297c08d33471f5491843d F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b -F src/where.c 3ee4050e453dfd03da4a8e4b5561d20b20b2302ec9d02437fb62c6f29bb78401 +F src/where.c 1425edc179cce7db5e7e9626b01716fed8498cc1f63875e96905d515e5e90bec F src/whereInt.h e25203e5bfee149f5f1225ae0166cfb4f1e65490c998a024249e98bb0647377c F src/wherecode.c 76bca3379219880d2527493b71a3be49e696f75396d3481e4de5d4ceec7886b2 F src/whereexpr.c 05295b44b54eea76d1ba766f0908928d0e20e990c249344c9521454d3d09c7ae @@ -2067,8 +2067,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P ea4306a03cd8dd706100dac3f11653068a25c50c5d06c34ad08534aec0a580bc -R c0ee619126b867e19f0a23327a8098db +P 9243e850ae656d16adc8f0e5c4dcf3dcf476312cee192c39c38685fc437ccbbd +R 007d4f781a18a8f9fcf2791b8d77bab0 U drh -Z d537a6db68af607fd73e77d57f16a3f5 +Z 822da98b746323e73cbe562572963994 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 118bbb8ad4..3f367b86a3 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9243e850ae656d16adc8f0e5c4dcf3dcf476312cee192c39c38685fc437ccbbd \ No newline at end of file +d125d5afdf1b0a1c64fc64f180898099af07b8290ea9da49419df75d8b455f71 \ No newline at end of file diff --git a/src/where.c b/src/where.c index 25ad18b282..d3e04808f3 100644 --- a/src/where.c +++ b/src/where.c @@ -836,7 +836,8 @@ static void explainAutomaticIndex( const char *zSep = ""; char *zText = 0; int ii = 0; - zText = sqlite3_mprintf("CREATE AUTOMATIC INDEX ON %s(", pTab->zName); + sqlite3_str *pStr = sqlite3_str_new(pParse->db); + sqlite3_str_appendf(pStr,"CREATE AUTOMATIC INDEX ON %s(", pTab->zName); assert( pIdx->nColumn>1 ); assert( pIdx->aiColumn[pIdx->nColumn-1]==XN_ROWID ); for(ii=0; ii<(pIdx->nColumn-1); ii++){ @@ -844,13 +845,18 @@ static void explainAutomaticIndex( int iCol = pIdx->aiColumn[ii]; zName = pTab->aCol[iCol].zCnName; - zText = sqlite3_mprintf("%z%s%s", zText, zSep, zName); + sqlite3_str_appendf(pStr, "%s%s", zSep, zName); zSep = ", "; } - *pAddrExplain = sqlite3VdbeExplain( - pParse, 0, "%s)%s", zText, (bPartial ? " WHERE " : "") - ); - sqlite3_free(zText); + zText = sqlite3_str_finish(pStr); + if( zText==0 ){ + sqlite3OomFault(pParse->db); + }else{ + *pAddrExplain = sqlite3VdbeExplain( + pParse, 0, "%s)%s", zText, (bPartial ? " WHERE " : "") + ); + sqlite3_free(zText); + } } } #else From 93f41e22d4863404adc2b8f141b0dde9da9627e6 Mon Sep 17 00:00:00 2001 From: drh <> Date: Fri, 9 Dec 2022 18:26:15 +0000 Subject: [PATCH 5/5] Remove the SQLITE_PREPARE_SAFEOPT flag. The name is obsolete and it is at the wrong level. Instead use the SF_UpdateFrom flags on the Select object. FossilOrigin-Name: 78723a9a7e72b42d28fc5645661da17f20cedcf864819b861800ad9340007be1 --- manifest | 18 +++++++++--------- manifest.uuid | 2 +- src/select.c | 11 ++++++----- src/sqliteInt.h | 1 + src/update.c | 4 ++-- src/vdbe.h | 1 - 6 files changed, 19 insertions(+), 18 deletions(-) diff --git a/manifest b/manifest index 8050d01280..e7bfc23fe3 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Do\snot\sallow\sOOM\sfaults\sin\sEQP\smessages\sassociated\swith\sautomatic\sindexes\non\sco-routines\sto\sgo\sunreported. -D 2022-12-09T17:33:21.007 +C Remove\sthe\sSQLITE_PREPARE_SAFEOPT\sflag.\s\sThe\sname\sis\sobsolete\sand\sit\sis\sat\sthe\nwrong\slevel.\s\sInstead\suse\sthe\sSF_UpdateFrom\sflags\son\sthe\sSelect\sobject. +D 2022-12-09T18:26:15.981 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -645,12 +645,12 @@ F src/printf.c e99ee9741e79ae3873458146f59644276657340385ade4e76a5f5d1c25793764 F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c F src/resolve.c efea4e5fbecfd6d0a9071b0be0d952620991673391b6ffaaf4c277b0bb674633 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 -F src/select.c 6ec3f7a1760b302193e9155453d42598192f6ad07e875038bf1177e4ce7af728 +F src/select.c d4df3eb74a1b0e1bd5a95525f2b571baeef3e3bedcc9d6401152dc0e0bdd7384 F src/shell.c.in bcf8552c82f2c84650e39a6d638373569c2035942c0497b83eef197169e0305a F src/sqlite.h.in 1fe1836879ecbb2e28f00f44eb6092db09a2a06bf072af351c6c2466bd515496 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h c4b9fa7a7e2bcdf850cfeb4b8a91d5ec47b7a00033bc996fd2ee96cbf2741f5f -F src/sqliteInt.h 5a91a427ab821dd3db556411ec0bf0f02bea796ce9927183979c2a1954ae4630 +F src/sqliteInt.h ef0c1af2d7b46ce89fe698ce5f1a26d19110780ac19ec1ef5a227f7e51e97de3 F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657 F src/status.c 160c445d7d28c984a0eae38c144f6419311ed3eace59b44ac6dafc20db4af749 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 @@ -712,13 +712,13 @@ F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c F src/tokenize.c 1305797eab3542a0896b552c6e7669c972c1468e11e92b370533c1f37a37082b F src/treeview.c 29b1dc7e0f84ba090734febe27393d4719682af0cae1b902d5ebf0236ecebea4 F src/trigger.c 5e68b790f022b8dafbfb0eb244786512a95c9575fc198719d2557d73e5795858 -F src/update.c 3cf1cb45674177e09338bdbe5454fb62207c7f2eb8cea288e74286467e901959 +F src/update.c f118e51768d2c1309e3c81e9f91141b22b8a1339cbc5969b1b2d810feaa25b22 F src/upsert.c 5303dc6c518fa7d4b280ec65170f465c7a70b7ac2b22491598f6d0b4875b3145 F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0 F src/util.c 313f3154e2b85a447326f5dd15de8d31a4df6ab0c3579bd58f426ff634ec9050 F src/vacuum.c 84ce7f01f8a7a08748e107a441db83bcec13970190ddcb0c9ff522adbc1c23fd F src/vdbe.c df9ff3fcaa3c60fa9b0bca340c3f3cfc63a51361901ca06fe18bdeadeb2a1a24 -F src/vdbe.h 934387e28f0a6b1a6a60904ddfe4ab61099e8767daf3cf59e6bbc3981d7ce426 +F src/vdbe.h 73b904a6b3bb27f308c6cc287a5751ebc7f1f89456be0ed068a12b92844c6e8c F src/vdbeInt.h 8651e4c4e04d1860d0bdcf330cb8294e3778a9d4222be30ce4c490d9220af783 F src/vdbeapi.c df3f73a4d0a487f2068e3c84776cd6e3fba5ae80ff612659dcfda4307686420b F src/vdbeaux.c 25691b395bf57ae0a754570fc3ba2d6f8bd2f0a8944f1d2589b9e68114e01c2b @@ -2067,8 +2067,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 9243e850ae656d16adc8f0e5c4dcf3dcf476312cee192c39c38685fc437ccbbd -R 007d4f781a18a8f9fcf2791b8d77bab0 +P d125d5afdf1b0a1c64fc64f180898099af07b8290ea9da49419df75d8b455f71 +R bf6e5a558d8631cb7969118db6751e4e U drh -Z 822da98b746323e73cbe562572963994 +Z 2ad12df38bfb5c0313f6be39e7ec9c86 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 3f367b86a3..428524bc2d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d125d5afdf1b0a1c64fc64f180898099af07b8290ea9da49419df75d8b455f71 \ No newline at end of file +78723a9a7e72b42d28fc5645661da17f20cedcf864819b861800ad9340007be1 \ No newline at end of file diff --git a/src/select.c b/src/select.c index c097d23e47..e151b0fac8 100644 --- a/src/select.c +++ b/src/select.c @@ -6878,7 +6878,7 @@ static int sameSrcAlias(SrcItem *p0, SrcList *pSrc){ ** (ii) There is nothing that would prevent the subquery from ** being used as the outer loop if the sqlite3WhereBegin() ** routine nominates it to that position. -** (iii) The SQLITE_PREPARE_SAFEOPT flag is not set +** (iii) The query is not a UPDATE ... FROM ** (2) The subquery is not a CTE that should be materialized because of ** the AS MATERIALIZED keywords ** (3) The subquery is not part of a left operand for a RIGHT JOIN @@ -6888,7 +6888,8 @@ static int sameSrcAlias(SrcItem *p0, SrcList *pSrc){ static int fromClauseTermCanBeCoroutine( Parse *pParse, /* Parsing context */ SrcList *pTabList, /* FROM clause */ - int i /* Which term of the FROM clause holds the subquery */ + int i, /* Which term of the FROM clause holds the subquery */ + int selFlags /* Flags on the SELECT statement */ ){ SrcItem *pItem = &pTabList->a[i]; if( pItem->fg.isCte && pItem->u2.pCteUse->eM10d==M10d_Yes ) return 0;/* (2) */ @@ -6900,10 +6901,10 @@ static int fromClauseTermCanBeCoroutine( if( i==0 ){ if( pTabList->nSrc==1 ) return 1; /* (1a) */ if( pTabList->a[1].fg.jointype & JT_CROSS ) return 1; /* (1b) */ - if( pParse->prepFlags & SQLITE_PREPARE_SAFEOPT ) return 0; /* (1c-iii) */ + if( selFlags & SF_UpdateFrom ) return 0; /* (1c-iii) */ return 1; } - if( pParse->prepFlags & SQLITE_PREPARE_SAFEOPT ) return 0; /* (1c-iii) */ + if( selFlags & SF_UpdateFrom ) return 0; /* (1c-iii) */ while( 1 /*exit-by-break*/ ){ if( pItem->fg.jointype & (JT_OUTER|JT_CROSS) ) return 0; /* (1c-ii) */ if( i==0 ) break; @@ -7302,7 +7303,7 @@ int sqlite3Select( /* Generate code to implement the subquery */ - if( fromClauseTermCanBeCoroutine(pParse, pTabList, i) ){ + if( fromClauseTermCanBeCoroutine(pParse, pTabList, i, p->selFlags) ){ /* Implement a co-routine that will return a single row of the result ** set on each invocation. */ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 393237358a..4c9aede1b1 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3466,6 +3466,7 @@ struct Select { #define SF_MultiPart 0x2000000 /* Has multiple incompatible PARTITIONs */ #define SF_CopyCte 0x4000000 /* SELECT statement is a copy of a CTE */ #define SF_OrderByReqd 0x8000000 /* The ORDER BY clause may not be omitted */ +#define SF_UpdateFrom 0x10000000 /* Query originates with UPDATE FROM */ /* True if S exists and has SF_NestedFrom */ #define IsNestedFrom(S) ((S)!=0 && ((S)->selFlags&SF_NestedFrom)!=0) diff --git a/src/update.c b/src/update.c index 0612b2708d..a4e57d1d42 100644 --- a/src/update.c +++ b/src/update.c @@ -263,12 +263,12 @@ static void updateFromSelect( } } pSelect = sqlite3SelectNew(pParse, pList, - pSrc, pWhere2, pGrp, 0, pOrderBy2, SF_UFSrcCheck|SF_IncludeHidden, pLimit2 + pSrc, pWhere2, pGrp, 0, pOrderBy2, + SF_UFSrcCheck|SF_IncludeHidden|SF_UpdateFrom, pLimit2 ); if( pSelect ) pSelect->selFlags |= SF_OrderByReqd; sqlite3SelectDestInit(&dest, eDest, iEph); dest.iSDParm2 = (pPk ? pPk->nKeyCol : -1); - pParse->prepFlags |= SQLITE_PREPARE_SAFEOPT; sqlite3Select(pParse, pSelect, &dest); sqlite3SelectDelete(db, pSelect); } diff --git a/src/vdbe.h b/src/vdbe.h index 17a301bd82..3caf1f7872 100644 --- a/src/vdbe.h +++ b/src/vdbe.h @@ -169,7 +169,6 @@ typedef struct VdbeOpList VdbeOpList; ** Additional non-public SQLITE_PREPARE_* flags */ #define SQLITE_PREPARE_SAVESQL 0x80 /* Preserve SQL text */ -#define SQLITE_PREPARE_SAFEOPT 0x40 /* Use only safe optimizations */ #define SQLITE_PREPARE_MASK 0x0f /* Mask of public flags */ /*