From 815e055bff42d57f49cf46cc70771cdcf5930d83 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 11 Mar 2024 17:27:19 +0000 Subject: [PATCH 01/34] Attempt to reduce the memory used by VALUES clauses in as many statements as possible, not just INSERT. This branch still has problems. FossilOrigin-Name: 17d1f7cfabc7593d0725051b0c7c9619a23a482265f30f15ab9493fef5caeeb0 --- manifest | 29 +++-- manifest.uuid | 2 +- src/expr.c | 1 + src/insert.c | 137 +++++++++++++++++++--- src/parse.y | 27 ++--- src/select.c | 2 +- src/sqliteInt.h | 4 + src/where.c | 1 + test/values.test | 256 ++++++++++++++++++++++++++++++++++++++++++ test/valuesfault.test | 37 ++++++ 10 files changed, 451 insertions(+), 45 deletions(-) create mode 100644 test/values.test create mode 100644 test/valuesfault.test diff --git a/manifest b/manifest index 49e6d916e1..afde134bd1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sthe\s".import"\scommand\sin\sthe\sCLI\sso\sthat\sit\sworks\scorrectly\swith\stables\nthat\scontain\scomputed\scolumns.\n[forum:/forumpost/ca014d7358|forum\spost\sca014d7358]. -D 2024-03-11T11:24:59.268 +C Attempt\sto\sreduce\sthe\smemory\sused\sby\sVALUES\sclauses\sin\sas\smany\sstatements\sas\spossible,\snot\sjust\sINSERT.\sThis\sbranch\sstill\shas\sproblems. +D 2024-03-11T17:27:19.668 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -700,7 +700,7 @@ F src/date.c 126ba2ab10aeb2e7ba6e089b5f07b747c0625b8287f78b60da346eda8d23c875 F src/dbpage.c 80e46e1df623ec40486da7a5086cb723b0275a6e2a7b01d9f9b5da0f04ba2782 F src/dbstat.c 3b677254d512fcafd4d0b341bf267b38b235ccfddbef24f9154e19360fa22e43 F src/delete.c cb766727c78e715f9fb7ec8a7d03658ed2a3016343ca687acfcec9083cdca500 -F src/expr.c 05516e8b7d7d22f98160a0360fde69edce3304a430600567ed33e66d588ca59b +F src/expr.c 7d0280860f8683fa1e81202304a5107f493fe9bd52be6590d0d0d6c3564c7a07 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c a47610f0a5c6cb0ad79f8fcef039c01833dec0c751bb695f28dc0ec6a4c3ba00 F src/func.c 4204c56196847faefef57fa14e43b8e4d65eb8d7e65318abe463472e3fd148cb @@ -709,7 +709,7 @@ F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220 F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51 F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 -F src/insert.c eb33ea46dcab93e90f112fced343aaf41f59cbd2e951d5066f1f9302be1c2f34 +F src/insert.c 2c34cf51e9d8c00498ba68b7f130e448038bb31f624c9c1ca80fa8e3237b51fb F src/json.c e2e40760d6689134c3e2ece38c6a496b34ff5e2661a8f238444a119af666fdce F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36 @@ -739,7 +739,7 @@ F src/os_win.c 6ff43bac175bd9ed79e7c0f96840b139f2f51d01689a638fd05128becf94908a F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/pager.c ff60e98138d2499082ac6230f01ac508aba545315debccfca2fd6042f5f10fcd F src/pager.h 4b1140d691860de0be1347474c51fee07d5420bd7f802d38cbab8ea4ab9f538a -F src/parse.y 6209f01e8e7495379571454744fa82a5cfc2e7eeb89e46dee3f410d73ea6252d +F src/parse.y 3d022ba4c68bf8c7c4c40b3e364d7a8226c4089fc9ff7a3a95f969f8f1bec959 F src/pcache.c 040b165f30622a21b7a9a77c6f2e4877a32fb7f22d4c7f0d2a6fa6833a156a75 F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5 F src/pcache1.c 602acb23c471bb8d557a6f0083cc2be641d6cafcafa19e481eba7ef4c9ca0f00 @@ -750,12 +750,12 @@ F src/printf.c 10e8bad30042f8bd6114a013b4afc229ec8ad255ab27518d7d9f52e8cbc5cd0a F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c F src/resolve.c ef87e3bc7700bfe761a7bbee2ce6084f1766dc816dd82a3ae77c133eec898432 F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97 -F src/select.c 43fabfc01bf87addd15e39f112f1e2ade15b19594835ab8a9e5bd50839d4e1b1 +F src/select.c 2a12c6ed8131db7c49b6f8141c3420cab825cfc6bd222d347fa1382f36b174b7 F src/shell.c.in cf80c636bccb0ff9db46995e39d69ca21fde2a8a331d1691e4d62a69d7841c8a F src/sqlite.h.in 19a2db3995a699bd7f6dfb423856242bfceb7ec849a93c91d241d19fc28d9f0f F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54 -F src/sqliteInt.h 6123ce6ca6a1ef351c3b87189e92c92042728f16c088de56b9b5bc2552d0ae33 +F src/sqliteInt.h b3ac44ca090011813d5a07f63be59785a4558e74052eb94b686f52eef1af684b F src/sqliteLimit.h 6878ab64bdeb8c24a1d762d45635e34b96da21132179023338c93f820eee6728 F src/status.c cb11f8589a6912af2da3bb1ec509a94dd8ef27df4d4c1a97e0bcf2309ece972b F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 @@ -835,7 +835,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c 887fc4ca3f020ebb2e376f222069570834ac63bf50111ef0cbf3ae417048ed89 F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452 F src/walker.c 7c7ea0115345851c3da4e04e2e239a29983b61fb5b038b94eede6aba462640e2 -F src/where.c 33eaaeef3aef10c2b9e82096e70a174d6636e35cb0b180321b8ddf804590e5cd +F src/where.c 8bb70b3caadcf35073f8857ecd83d33d97bf6aa03de3342287037bae43c6f364 F src/whereInt.h 82a13766f13d1a53b05387c2e60726289ef26404bc7b9b1f7770204d97357fb8 F src/wherecode.c 5d77db30a2a3dd532492ae882de114edba2fae672622056b1c7fd61f5917a8f1 F src/whereexpr.c 6ebd90b553f4bb5c7df5a4b2f39b6a7c81a67484353827cdd2048f2514ec6f30 @@ -1921,6 +1921,8 @@ F test/vacuum4.test 7ea76b769fffeb41f925303b04cbcf5a5bbeabe55e4c60ae754ff24eeeb7 F test/vacuum5.test 263b144d537e92ad8e9ca8a73cc6e1583f41cfd0dda9432b87f7806174a2f48c F test/vacuum6.test b137b04bf3392d3f5c3b8fda0ce85a6775a70ca112f6559f74ff52dc9ce042fd F test/vacuummem.test 4b30f5b95a9ff86e9d5c20741e50a898b2dc10b0962a3211571eb165357003fb +F test/values.test 8438dea6826738291ff2019993d62e1eae7a3efb66ea8312fa9ac9bfaf0f95cb +F test/valuesfault.test 2ef23ed965e3bd08e268cdc38a0d11653390ddbbe1e8e2e98d16f55edd30f6e8 F test/varint.test bbce22cda8fc4d135bcc2b589574be8410614e62 F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661 F test/view.test d4c4281e1679245829db35597817282f60dc513fc39cc5439078f009bd118487 @@ -2177,8 +2179,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 cb8d9c269c01f78f09069a2361e15087d9aeac63e9f1fd63fbd96b951384e9aa -R 9bba8f8b4bc3bf41627766fe1aa44b9c -U drh -Z 1d2e3bf230fd6cd6fbc6ff6c84cfd8fb +P 95a9c88b258f18ac671a4c712603931167cc8bd0b86e41481b200c08043338b5 +R 62b6db11e5c879766b23978dd0871f55 +T *branch * exp-values-clause2 +T *sym-exp-values-clause2 * +T -sym-trunk * +U dan +Z 521a450017e9a427470d7f09cc068c5e # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index c57a5b98bf..633c59c43c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -95a9c88b258f18ac671a4c712603931167cc8bd0b86e41481b200c08043338b5 \ No newline at end of file +17d1f7cfabc7593d0725051b0c7c9619a23a482265f30f15ab9493fef5caeeb0 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 6640d1907d..e4bfa995d7 100644 --- a/src/expr.c +++ b/src/expr.c @@ -1869,6 +1869,7 @@ SrcList *sqlite3SrcListDup(sqlite3 *db, const SrcList *p, int flags){ pNewItem->iCursor = pOldItem->iCursor; pNewItem->addrFillSub = pOldItem->addrFillSub; pNewItem->regReturn = pOldItem->regReturn; + pNewItem->regResult = pOldItem->regResult; if( pNewItem->fg.isIndexedBy ){ pNewItem->u1.zIndexedBy = sqlite3DbStrDup(db, pOldItem->u1.zIndexedBy); } diff --git a/src/insert.c b/src/insert.c index 095298b90c..7b253e9262 100644 --- a/src/insert.c +++ b/src/insert.c @@ -577,6 +577,104 @@ void sqlite3AutoincrementEnd(Parse *pParse){ # define autoIncStep(A,B,C) #endif /* SQLITE_OMIT_AUTOINCREMENT */ +void sqlite3MultiValuesEnd(Parse *pParse, Select *pVal){ + if( pVal->pSrc->nSrc>0 ){ + SrcItem *pItem = &pVal->pSrc->a[0]; + sqlite3VdbeEndCoroutine(pParse->pVdbe, pItem->regReturn); + sqlite3VdbeJumpHere(pParse->pVdbe, pItem->addrFillSub - 1); + } +} + +static int multiValueIsConstant(ExprList *pRow){ + int ii; + for(ii=0; iinExpr; ii++){ + if( 0==sqlite3ExprIsConstant(pRow->a[ii].pExpr) ) return 0; + } + return 1; +} + +Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow){ + SrcItem *p; + SelectDest dest; + Select *pSelect = 0; + + if( pParse->db->init.busy + || pParse->pNewTrigger + || pParse->bHasWith + || multiValueIsConstant(pRow)==0 + || pLeft->pPrior + ){ + int f = SF_Values | SF_MultiValue; + if( pLeft->pPrior || pLeft->pSrc->nSrc ){ + sqlite3MultiValuesEnd(pParse, pLeft); + f = SF_Values; + } + /* This VALUES clause is part of a VIEW or some other schema item. In + ** this case the co-routine cannot be coded immediately. */ + pSelect = sqlite3SelectNew(pParse,pRow,0,0,0,0,0,f,0); + pLeft->selFlags &= ~SF_MultiValue; + if( pSelect ){ + pSelect->op = TK_ALL; + pSelect->pPrior = pLeft; + pLeft = pSelect; + } + }else{ + + if( pLeft->pSrc->nSrc==0 ){ + /* Co-routine has not yet been started. */ + Vdbe *v = sqlite3GetVdbe(pParse); + Select *pRet; + + if( v==0 ) return pLeft; + pRet = sqlite3SelectNew(pParse, 0, 0, 0, 0, 0, 0, 0, 0); + if( pRet==0 ) return pLeft; + p = &pRet->pSrc->a[0]; + pRet->pSrc->nSrc = 1; + + p->pSelect = pLeft; + p->fg.viaCoroutine = 1; + p->addrFillSub = sqlite3VdbeCurrentAddr(v) + 1; + p->regReturn = ++pParse->nMem; + + sqlite3VdbeAddOp3(v,OP_InitCoroutine,p->regReturn,0,p->addrFillSub); + sqlite3SelectDestInit(&dest, SRT_Coroutine, p->regReturn); + sqlite3Select(pParse, pLeft, &dest); + p->regResult = dest.iSdst; + assert( pParse->nErr || dest.iSdst>0 ); + + pLeft = pRet; + }else{ + p = &pLeft->pSrc->a[0]; + } + + if( pParse->nErr==0 ){ + pSelect = sqlite3SelectNew(pParse, pRow, 0, 0, 0, 0, 0, SF_Values, 0); + if( pSelect ){ + if( p->pSelect->pEList->nExpr!=pSelect->pEList->nExpr ){ + sqlite3SelectWrongNumTermsError(pParse, pSelect); + }else{ + sqlite3SelectPrep(pParse, pSelect, 0); +#ifndef SQLITE_OMIT_WINDOWFUNC + if( pSelect->pWin ){ + sqlite3SelectDestInit(&dest, SRT_Coroutine, p->regReturn); + dest.iSdst = p->regResult; + dest.nSdst = pRow->nExpr; + dest.iSDParm = p->regReturn; + sqlite3Select(pParse, pSelect, &dest); + }else +#endif + { + sqlite3ExprCodeExprList(pParse, pSelect->pEList,p->regResult,0,0); + sqlite3VdbeAddOp1(pParse->pVdbe, OP_Yield, p->regReturn); + } + } + sqlite3SelectDelete(pParse->db, pSelect); + } + } + } + + return pLeft; +} /* Forward declaration */ static int xferOptimization( @@ -914,24 +1012,31 @@ void sqlite3Insert( /* Data is coming from a SELECT or from a multi-row VALUES clause. ** Generate a co-routine to run the SELECT. */ int regYield; /* Register holding co-routine entry-point */ - int addrTop; /* Top of the co-routine */ int rc; /* Result code */ - regYield = ++pParse->nMem; - addrTop = sqlite3VdbeCurrentAddr(v) + 1; - sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop); - sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield); - dest.iSdst = bIdListInOrder ? regData : 0; - dest.nSdst = pTab->nCol; - rc = sqlite3Select(pParse, pSelect, &dest); - regFromSelect = dest.iSdst; - assert( db->pParse==pParse ); - if( rc || pParse->nErr ) goto insert_cleanup; - assert( db->mallocFailed==0 ); - sqlite3VdbeEndCoroutine(v, regYield); - sqlite3VdbeJumpHere(v, addrTop - 1); /* label B: */ - assert( pSelect->pEList ); - nColumn = pSelect->pEList->nExpr; + if( pSelect->pSrc->nSrc==1 && pSelect->pSrc->a[0].fg.viaCoroutine ){ + SrcItem *pItem = &pSelect->pSrc->a[0]; + dest.iSDParm = regYield = pItem->regReturn; + regFromSelect = pItem->regResult; + nColumn = pItem->pSelect->pEList->nExpr; + }else{ + int addrTop; /* Top of the co-routine */ + regYield = ++pParse->nMem; + addrTop = sqlite3VdbeCurrentAddr(v) + 1; + sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop); + sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield); + dest.iSdst = bIdListInOrder ? regData : 0; + dest.nSdst = pTab->nCol; + rc = sqlite3Select(pParse, pSelect, &dest); + regFromSelect = dest.iSdst; + assert( db->pParse==pParse ); + if( rc || pParse->nErr ) goto insert_cleanup; + assert( db->mallocFailed==0 ); + sqlite3VdbeEndCoroutine(v, regYield); + sqlite3VdbeJumpHere(v, addrTop - 1); /* label B: */ + assert( pSelect->pEList ); + nColumn = pSelect->pEList->nExpr; + } /* Set useTempTable to TRUE if the result of the SELECT statement ** should be written into a temporary table (template 4). Set to diff --git a/src/parse.y b/src/parse.y index 37c9fa8bc9..515d512f2c 100644 --- a/src/parse.y +++ b/src/parse.y @@ -562,9 +562,13 @@ cmd ::= select(X). { } %ifndef SQLITE_OMIT_CTE -select(A) ::= WITH wqlist(W) selectnowith(X). {A = attachWithToSelect(pParse,X,W);} -select(A) ::= WITH RECURSIVE wqlist(W) selectnowith(X). +select(A) ::= withkw wqlist(W) selectnowith(X). {A = attachWithToSelect(pParse,X,W);} +select(A) ::= withkw RECURSIVE wqlist(W) selectnowith(X). {A = attachWithToSelect(pParse,X,W);} + +withkw ::= WITH. { + pParse->bHasWith = 1; +} %endif /* SQLITE_OMIT_CTE */ select(A) ::= selectnowith(A). { Select *p = A; @@ -622,7 +626,9 @@ oneselect(A) ::= SELECT distinct(D) selcollist(W) from(X) where_opt(Y) %endif -oneselect(A) ::= values(A). +oneselect(A) ::= values(A). { + sqlite3MultiValuesEnd(pParse, A); +} %type values {Select*} %destructor values {sqlite3SelectDelete(pParse->db, $$);} @@ -630,16 +636,7 @@ values(A) ::= VALUES LP nexprlist(X) RP. { A = sqlite3SelectNew(pParse,X,0,0,0,0,0,SF_Values,0); } values(A) ::= values(A) COMMA LP nexprlist(Y) RP. { - Select *pRight, *pLeft = A; - pRight = sqlite3SelectNew(pParse,Y,0,0,0,0,0,SF_Values|SF_MultiValue,0); - if( ALWAYS(pLeft) ) pLeft->selFlags &= ~SF_MultiValue; - if( pRight ){ - pRight->op = TK_ALL; - pRight->pPrior = pLeft; - A = pRight; - }else{ - A = pLeft; - } + A = sqlite3MultiValues(pParse, A, Y); } // The "distinct" nonterminal is true (1) if the DISTINCT keyword is @@ -1754,8 +1751,8 @@ anylist ::= anylist ANY. with ::= . %ifndef SQLITE_OMIT_CTE -with ::= WITH wqlist(W). { sqlite3WithPush(pParse, W, 1); } -with ::= WITH RECURSIVE wqlist(W). { sqlite3WithPush(pParse, W, 1); } +with ::= withkw wqlist(W). { sqlite3WithPush(pParse, W, 1); } +with ::= withkw RECURSIVE wqlist(W). { sqlite3WithPush(pParse, W, 1); } %type wqas {u8} wqas(A) ::= AS. {A = M10d_Any;} diff --git a/src/select.c b/src/select.c index 81e802d6e4..4158dd2fdc 100644 --- a/src/select.c +++ b/src/select.c @@ -7636,7 +7636,7 @@ int sqlite3Select( /* Generate code for all sub-queries in the FROM clause */ pSub = pItem->pSelect; - if( pSub==0 ) continue; + if( pSub==0 || pItem->addrFillSub!=0 ) continue; /* The code for a subquery should only be generated once. */ assert( pItem->addrFillSub==0 ); diff --git a/src/sqliteInt.h b/src/sqliteInt.h index e11b5b3a4e..3913392712 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3812,6 +3812,7 @@ struct Parse { u8 disableLookaside; /* Number of times lookaside has been disabled */ u8 prepFlags; /* SQLITE_PREPARE_* flags */ u8 withinRJSubrtn; /* Nesting level for RIGHT JOIN body subroutines */ + u8 bHasWith; /* True if statement contains WITH */ #if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST) u8 earlyCleanup; /* OOM inside sqlite3ParserAddCleanup() */ #endif @@ -4486,6 +4487,9 @@ struct Window { ** due to the SQLITE_SUBTYPE flag */ }; +Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow); +void sqlite3MultiValuesEnd(Parse *pParse, Select *pVal); + #ifndef SQLITE_OMIT_WINDOWFUNC void sqlite3WindowDelete(sqlite3*, Window*); void sqlite3WindowUnlinkFromSelect(Window*); diff --git a/src/where.c b/src/where.c index 9850d22cc3..9abc8e30f6 100644 --- a/src/where.c +++ b/src/where.c @@ -6896,6 +6896,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){ */ if( pTabItem->fg.viaCoroutine ){ testcase( pParse->db->mallocFailed ); + assert( pTabItem->regResult>=0 ); translateColumnToCopy(pParse, pLevel->addrBody, pLevel->iTabCur, pTabItem->regResult, 0); continue; diff --git a/test/values.test b/test/values.test new file mode 100644 index 0000000000..66e29ef6f0 --- /dev/null +++ b/test/values.test @@ -0,0 +1,256 @@ +# 2024 March 3 +# +# 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. +# +#*********************************************************************** +# This file implements regression tests for SQLite library. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix values + + +do_execsql_test 1.0 { + CREATE TABLE x1(a, b, c); +} + + +explain_i { + INSERT INTO x1(a, b, c) VALUES(1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4); +} +do_execsql_test 1.1.1 { + INSERT INTO x1 VALUES(1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4); +} +do_execsql_test 1.1.2 { + SELECT * FROM x1; +} { + 1 1 1 + 2 2 2 + 3 3 3 + 4 4 4 +} + +do_execsql_test 1.2.0 { + DELETE FROM x1 +} +do_execsql_test 1.2.1 { + INSERT INTO x1 VALUES(1, 1, 1), (2, 2, 2), (3, 3, 3) UNION ALL SELECT 4, 4, 4; + SELECT * FROM x1; +} {1 1 1 2 2 2 3 3 3 4 4 4} + +sqlite3_limit db SQLITE_LIMIT_COMPOUND_SELECT 4 + +do_execsql_test 1.2.2 { + DELETE FROM x1; + INSERT INTO x1 + VALUES(1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4), (5, 5, 5) + UNION ALL SELECT 6, 6, 6; + SELECT * FROM x1; +} {1 1 1 2 2 2 3 3 3 4 4 4 5 5 5 6 6 6} + +do_execsql_test 1.2.3 { + DELETE FROM x1; + INSERT INTO x1 + VALUES(1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4) + UNION ALL SELECT 6, 6, 6; + SELECT * FROM x1; +} {1 1 1 2 2 2 3 3 3 4 4 4 6 6 6} + +do_execsql_test 1.2.4 { + DELETE FROM x1; + INSERT INTO x1 VALUES(1, 1, 1), (2, 2, 2), (3, 3, 3) UNION ALL SELECT 6, 6, 6; + SELECT * FROM x1; +} { + 1 1 1 + 2 2 2 + 3 3 3 + 6 6 6 +} + +set a 4 +set b 5 +set c 6 +do_execsql_test 1.2.5 { + DELETE FROM x1; + INSERT INTO x1 + VALUES(1, 1, 1), (2, 2, 2), (3, 3, 3), + (4, 4, $a), (5, 5, $b), (6, 6, $c) +} + +do_execsql_test 1.2.6 { + SELECT * FROM x1; +} { + 1 1 1 + 2 2 2 + 3 3 3 + 4 4 4 + 5 5 5 + 6 6 6 +} + +#------------------------------------------------------------------------- +# SQLITE_LIMIT_COMPOUND_SELECT set to 0. +# +reset_db + +do_execsql_test 2.0 { + CREATE TABLE x1(a, b, c); +} + +sqlite3_limit db SQLITE_LIMIT_COMPOUND_SELECT 3 + +do_catchsql_test 2.1.1 { + INSERT INTO x1 VALUES + (1, 1, 1), + (2, 2, 2), + (3, 3, 3), + (4, 4, 4), + (5, 5, 5), + (6, 6, 6), + (7, 7, 7), + (8, 8, 8), + (9, 9, 9), + (10, 10, 10, 10) +} {1 {all VALUES must have the same number of terms}} + +do_catchsql_test 2.1.2 { + INSERT INTO x1 VALUES + (1, 1, 1), + (2, 2, 2, 2), + (3, 3, 3), + (4, 4, 4), + (5, 5, 5), + (6, 6, 6), + (7, 7, 7), + (8, 8, 8), + (9, 9, 9), + (10, 10, 10) +} {1 {all VALUES must have the same number of terms}} + +sqlite3_limit db SQLITE_LIMIT_COMPOUND_SELECT 0 + +do_execsql_test 2.2 { + INSERT INTO x1 VALUES + (1, 1, 1), + (2, 2, 2), + (3, 3, 3), + (4, 4, 4), + (5, 5, 5), + (6, 6, 6), + (7, 7, 7), + (8, 8, 8), + (9, 9, 9), + (10, 10, 10) +} {} +do_execsql_test 2.3 { + INSERT INTO x1 VALUES + (1, 1, 1), + (2, 2, 2), + (3, 3, 3), + (4, 4, 4), + (5, 5, 5), + (6, 6, 6), + (7, 7, 7), + (8, 8, 8), + (9, 9, 9), + (10, 10, 10) + UNION ALL + SELECT 5, 12, 12 + ORDER BY 1 +} {} + +#------------------------------------------------------------------------- +reset_db + +do_execsql_test 3.0 { + CREATE TABLE y1(x, y); +} + +do_execsql_test 3.1.1 { + DELETE FROM y1; + INSERT INTO y1 VALUES(1, 2), (3, 4), (row_number() OVER (), 5); +} +do_execsql_test 3.1.2 { + SELECT * FROM y1; +} {1 2 3 4 1 5} +do_execsql_test 3.2.1 { + DELETE FROM y1; + INSERT INTO y1 VALUES(1, 2), (3, 4), (row_number() OVER (), 6) + , (row_number() OVER (), 7) +} +do_execsql_test 3.1.2 { + SELECT * FROM y1; +} {1 2 3 4 1 6 1 7} + +#------------------------------------------------------------------------- +reset_db + +do_execsql_test 4.0 { + CREATE TABLE x1(a PRIMARY KEY, b) WITHOUT ROWID; +} + +foreach {tn iLimit} {1 0 2 3} { + sqlite3_limit db SQLITE_LIMIT_COMPOUND_SELECT $iLimit + + do_execsql_test 4.1.1 { + DELETE FROM x1; + INSERT INTO x1 VALUES + (1, 1), + (2, (SELECT * FROM (VALUES('a'), ('b'), ('c'), ('d')) )) + } + do_execsql_test 4.1.2 { + SELECT * FROM x1 + } {1 1 2 a} + + do_execsql_test 4.2.1 { + DELETE FROM x1; + INSERT INTO x1 VALUES + (1, 1), + (2, 2), + (3, 3), + (4, 4), + (5, (SELECT * FROM (VALUES('a'), ('b'), ('c'), ('d')) )) + } + do_execsql_test 4.2.2 { + SELECT * FROM x1 + } {1 1 2 2 3 3 4 4 5 a} + + do_execsql_test 4.3.1 { + DELETE FROM x1; + INSERT INTO x1 VALUES + (1, (SELECT * FROM (VALUES('a'), ('b'), ('c'), ('d'), ('e')) )) + } + do_execsql_test 4.3.2 { + SELECT * FROM x1 + } {1 a} +} + +#------------------------------------------------------------------------ +reset_db + +do_execsql_test 5.0 { + CREATE VIEW v1 AS VALUES(1, 2, 3), (4, 5, 6), (7, 8, 9); +} +do_execsql_test 5.1 { + SELECT * FROM v1 +} {1 2 3 4 5 6 7 8 9} + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 6.0 { + CREATE TABLE t1(x); + INSERT INTO t1 VALUES(1), (2); +} + +do_execsql_test 6.1 { + SELECT ( VALUES( x ), ( x ) ) FROM t1; +} {1 2} + + +finish_test diff --git a/test/valuesfault.test b/test/valuesfault.test new file mode 100644 index 0000000000..bc5dddfb0e --- /dev/null +++ b/test/valuesfault.test @@ -0,0 +1,37 @@ +# 2024 March 3 +# +# 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. +# +#*********************************************************************** +# This file implements regression tests for SQLite library. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix valuesfault +source $testdir/malloc_common.tcl + + +do_execsql_test 1.0 { + CREATE TABLE x1(a, b, c); +} +faultsim_save_and_close + +do_faultsim_test 1 -prep { + faultsim_restore_and_reopen + sqlite3_limit db SQLITE_LIMIT_COMPOUND_SELECT 2 +} -body { + execsql { + INSERT INTO x1 VALUES(1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4); + } +} -test { + faultsim_test_result {0 {}} +} + + +finish_test From 5badd048d2e63b900683eefd01a3427a3d82b277 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 12 Mar 2024 20:10:46 +0000 Subject: [PATCH 02/34] Correctly initialize the SrcItem.iCursor field to -1 when creating a co-routine from a multi-values VALUES clause. FossilOrigin-Name: c32953ff6d72910815eaff29ab1b790c412e1a741d02c03c5911dda0c08e5130 --- manifest | 17 +++++++---------- manifest.uuid | 2 +- src/insert.c | 1 + test/values.test | 11 +++++++++++ 4 files changed, 20 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index afde134bd1..ae283f24ef 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Attempt\sto\sreduce\sthe\smemory\sused\sby\sVALUES\sclauses\sin\sas\smany\sstatements\sas\spossible,\snot\sjust\sINSERT.\sThis\sbranch\sstill\shas\sproblems. -D 2024-03-11T17:27:19.668 +C Correctly\sinitialize\sthe\sSrcItem.iCursor\sfield\sto\s-1\swhen\screating\sa\sco-routine\sfrom\sa\smulti-values\sVALUES\sclause. +D 2024-03-12T20:10:46.651 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -709,7 +709,7 @@ F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220 F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51 F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 -F src/insert.c 2c34cf51e9d8c00498ba68b7f130e448038bb31f624c9c1ca80fa8e3237b51fb +F src/insert.c 9d48439a0fff35d3c4850bc9ab3657f9d45b2800af52ef3b083e7068e32d8aa2 F src/json.c e2e40760d6689134c3e2ece38c6a496b34ff5e2661a8f238444a119af666fdce F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36 @@ -1921,7 +1921,7 @@ F test/vacuum4.test 7ea76b769fffeb41f925303b04cbcf5a5bbeabe55e4c60ae754ff24eeeb7 F test/vacuum5.test 263b144d537e92ad8e9ca8a73cc6e1583f41cfd0dda9432b87f7806174a2f48c F test/vacuum6.test b137b04bf3392d3f5c3b8fda0ce85a6775a70ca112f6559f74ff52dc9ce042fd F test/vacuummem.test 4b30f5b95a9ff86e9d5c20741e50a898b2dc10b0962a3211571eb165357003fb -F test/values.test 8438dea6826738291ff2019993d62e1eae7a3efb66ea8312fa9ac9bfaf0f95cb +F test/values.test 042f30d897d3b2bfa54dc89a48ef6c8f6ba3ffdfd4fc35c2cc877d28a1095ce3 F test/valuesfault.test 2ef23ed965e3bd08e268cdc38a0d11653390ddbbe1e8e2e98d16f55edd30f6e8 F test/varint.test bbce22cda8fc4d135bcc2b589574be8410614e62 F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661 @@ -2179,11 +2179,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 95a9c88b258f18ac671a4c712603931167cc8bd0b86e41481b200c08043338b5 -R 62b6db11e5c879766b23978dd0871f55 -T *branch * exp-values-clause2 -T *sym-exp-values-clause2 * -T -sym-trunk * +P 17d1f7cfabc7593d0725051b0c7c9619a23a482265f30f15ab9493fef5caeeb0 +R bc124d03e15c7cb41c52570d66be2e47 U dan -Z 521a450017e9a427470d7f09cc068c5e +Z 476dd3f62c65ec97a150406261356d2a # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 633c59c43c..bc849bef9a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -17d1f7cfabc7593d0725051b0c7c9619a23a482265f30f15ab9493fef5caeeb0 \ No newline at end of file +c32953ff6d72910815eaff29ab1b790c412e1a741d02c03c5911dda0c08e5130 \ No newline at end of file diff --git a/src/insert.c b/src/insert.c index 7b253e9262..071d9aeff9 100644 --- a/src/insert.c +++ b/src/insert.c @@ -635,6 +635,7 @@ Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow){ p->fg.viaCoroutine = 1; p->addrFillSub = sqlite3VdbeCurrentAddr(v) + 1; p->regReturn = ++pParse->nMem; + p->iCursor = -1; sqlite3VdbeAddOp3(v,OP_InitCoroutine,p->regReturn,0,p->addrFillSub); sqlite3SelectDestInit(&dest, SRT_Coroutine, p->regReturn); diff --git a/test/values.test b/test/values.test index 66e29ef6f0..8df0e6138f 100644 --- a/test/values.test +++ b/test/values.test @@ -252,5 +252,16 @@ do_execsql_test 6.1 { SELECT ( VALUES( x ), ( x ) ) FROM t1; } {1 2} +#------------------------------------------------------------------------- +reset_db +do_execsql_test 6.0 { + CREATE TABLE t1(x); + INSERT INTO t1 VALUES('x'), ('y'); +} + +do_execsql_test 6.1 { + SELECT * FROM t1, (VALUES(1), (2)) +} {x 1 x 2 y 1 y 2} finish_test + From 609aba00d930c4909a1dfa313645847de5804b68 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 13 Mar 2024 15:34:44 +0000 Subject: [PATCH 03/34] Avoid creating a co-routine incrementally for a VALUES clause that has affinities other than NONE. FossilOrigin-Name: 4229b12b327b05561dcf49b8585a66467d17d4e998b14eff65eb886f2434b53c --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/insert.c | 12 ++++++++++++ test/values.test | 4 ++++ 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index ae283f24ef..1eef7fdddb 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Correctly\sinitialize\sthe\sSrcItem.iCursor\sfield\sto\s-1\swhen\screating\sa\sco-routine\sfrom\sa\smulti-values\sVALUES\sclause. -D 2024-03-12T20:10:46.651 +C Avoid\screating\sa\sco-routine\sincrementally\sfor\sa\sVALUES\sclause\sthat\shas\saffinities\sother\sthan\sNONE. +D 2024-03-13T15:34:44.818 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -709,7 +709,7 @@ F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220 F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51 F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 -F src/insert.c 9d48439a0fff35d3c4850bc9ab3657f9d45b2800af52ef3b083e7068e32d8aa2 +F src/insert.c aef8d3dfc86116e0226a90549b5fbe8c63cda51eaca01d22f4d16e7b4e554a1b F src/json.c e2e40760d6689134c3e2ece38c6a496b34ff5e2661a8f238444a119af666fdce F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36 @@ -1921,7 +1921,7 @@ F test/vacuum4.test 7ea76b769fffeb41f925303b04cbcf5a5bbeabe55e4c60ae754ff24eeeb7 F test/vacuum5.test 263b144d537e92ad8e9ca8a73cc6e1583f41cfd0dda9432b87f7806174a2f48c F test/vacuum6.test b137b04bf3392d3f5c3b8fda0ce85a6775a70ca112f6559f74ff52dc9ce042fd F test/vacuummem.test 4b30f5b95a9ff86e9d5c20741e50a898b2dc10b0962a3211571eb165357003fb -F test/values.test 042f30d897d3b2bfa54dc89a48ef6c8f6ba3ffdfd4fc35c2cc877d28a1095ce3 +F test/values.test 3f0fe0e8859306e9a5cfc800e327278762510c8d5b075d8ddce40f2d13d1405a F test/valuesfault.test 2ef23ed965e3bd08e268cdc38a0d11653390ddbbe1e8e2e98d16f55edd30f6e8 F test/varint.test bbce22cda8fc4d135bcc2b589574be8410614e62 F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661 @@ -2179,8 +2179,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 17d1f7cfabc7593d0725051b0c7c9619a23a482265f30f15ab9493fef5caeeb0 -R bc124d03e15c7cb41c52570d66be2e47 +P c32953ff6d72910815eaff29ab1b790c412e1a741d02c03c5911dda0c08e5130 +R 919d468c68cfa043ffb3132b71e307d6 U dan -Z 476dd3f62c65ec97a150406261356d2a +Z 074e750da48e105e4f7bff52672dad88 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index bc849bef9a..e4e6f66f77 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c32953ff6d72910815eaff29ab1b790c412e1a741d02c03c5911dda0c08e5130 \ No newline at end of file +4229b12b327b05561dcf49b8585a66467d17d4e998b14eff65eb886f2434b53c \ No newline at end of file diff --git a/src/insert.c b/src/insert.c index 071d9aeff9..10eafaa413 100644 --- a/src/insert.c +++ b/src/insert.c @@ -593,6 +593,17 @@ static int multiValueIsConstant(ExprList *pRow){ return 1; } +static int multiValueIsConstantNoAff(ExprList *pRow){ + int ii; + if( multiValueIsConstant(pRow)==0 ) return 0; + for(ii=0; iinExpr; ii++){ + assert( pRow->a[ii].pExpr->affExpr==0 ); + if( 0!=sqlite3ExprAffinity(pRow->a[ii].pExpr) ) return 0; + } + return 1; + +} + Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow){ SrcItem *p; SelectDest dest; @@ -603,6 +614,7 @@ Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow){ || pParse->bHasWith || multiValueIsConstant(pRow)==0 || pLeft->pPrior + || (pLeft->pSrc->nSrc==0 && multiValueIsConstantNoAff(pLeft->pEList)==0) ){ int f = SF_Values | SF_MultiValue; if( pLeft->pPrior || pLeft->pSrc->nSrc ){ diff --git a/test/values.test b/test/values.test index 8df0e6138f..627987b43b 100644 --- a/test/values.test +++ b/test/values.test @@ -263,5 +263,9 @@ do_execsql_test 6.1 { SELECT * FROM t1, (VALUES(1), (2)) } {x 1 x 2 y 1 y 2} +do_execsql_test 6.2 { + VALUES(CAST(44 AS REAL)),(55); +} {44.0 55} + finish_test From e116fa153f752192ce96e285f7a3685549e0e2a4 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 13 Mar 2024 15:44:31 +0000 Subject: [PATCH 04/34] Ensure that if a multi-row VALUES cannot be coded while being parsed, the SF_MultiValue flag is correctly set. FossilOrigin-Name: 94791824a6f04782aac6bc16c182685e2d6ebf5c688dc9f8d59e479c6fd5a40e --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/insert.c | 9 ++++++--- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 1eef7fdddb..fc5a54bd05 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Avoid\screating\sa\sco-routine\sincrementally\sfor\sa\sVALUES\sclause\sthat\shas\saffinities\sother\sthan\sNONE. -D 2024-03-13T15:34:44.818 +C Ensure\sthat\sif\sa\smulti-row\sVALUES\scannot\sbe\scoded\swhile\sbeing\sparsed,\sthe\sSF_MultiValue\sflag\sis\scorrectly\sset. +D 2024-03-13T15:44:31.439 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -709,7 +709,7 @@ F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220 F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51 F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 -F src/insert.c aef8d3dfc86116e0226a90549b5fbe8c63cda51eaca01d22f4d16e7b4e554a1b +F src/insert.c 88f3c98b0ebbee295bb5085753bdb64ef1546ee5f0f0100b8be4f756b8a1acc6 F src/json.c e2e40760d6689134c3e2ece38c6a496b34ff5e2661a8f238444a119af666fdce F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36 @@ -2179,8 +2179,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 c32953ff6d72910815eaff29ab1b790c412e1a741d02c03c5911dda0c08e5130 -R 919d468c68cfa043ffb3132b71e307d6 +P 4229b12b327b05561dcf49b8585a66467d17d4e998b14eff65eb886f2434b53c +R 759c4fdaf4045c9f2dff7c53c191816c U dan -Z 074e750da48e105e4f7bff52672dad88 +Z 9143cafae67b08f919f57c93acfe5550 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index e4e6f66f77..bd6f8334d3 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4229b12b327b05561dcf49b8585a66467d17d4e998b14eff65eb886f2434b53c \ No newline at end of file +94791824a6f04782aac6bc16c182685e2d6ebf5c688dc9f8d59e479c6fd5a40e \ No newline at end of file diff --git a/src/insert.c b/src/insert.c index 10eafaa413..7303e1950a 100644 --- a/src/insert.c +++ b/src/insert.c @@ -616,13 +616,16 @@ Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow){ || pLeft->pPrior || (pLeft->pSrc->nSrc==0 && multiValueIsConstantNoAff(pLeft->pEList)==0) ){ + /* This row of the VALUES clause cannot be coded immediately. */ int f = SF_Values | SF_MultiValue; - if( pLeft->pPrior || pLeft->pSrc->nSrc ){ + if( pLeft->pSrc->nSrc ){ sqlite3MultiValuesEnd(pParse, pLeft); f = SF_Values; + }else if( pLeft->pPrior ){ + /* In this case set the SF_MultiValue flag only if it was set on + ** the previous Select structure. */ + f = (f & pLeft->selFlags); } - /* This VALUES clause is part of a VIEW or some other schema item. In - ** this case the co-routine cannot be coded immediately. */ pSelect = sqlite3SelectNew(pParse,pRow,0,0,0,0,0,f,0); pLeft->selFlags &= ~SF_MultiValue; if( pSelect ){ From 35057fb4bc78c5080fc41e81ab3f6c4f4d2a797c Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 13 Mar 2024 17:33:45 +0000 Subject: [PATCH 05/34] Fix some OOM handling problems on this branch. FossilOrigin-Name: 2085c7f12a3916ec883c31795e29f2e2b6641c30ecf748cce9bff7b13b061d1f --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/insert.c | 39 ++++++++++++++++++++------------------- 3 files changed, 27 insertions(+), 26 deletions(-) diff --git a/manifest b/manifest index 80413c4c4e..a91c89a359 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\strunk\sinto\sthis\sbranch. -D 2024-03-13T15:47:52.750 +C Fix\ssome\sOOM\shandling\sproblems\son\sthis\sbranch. +D 2024-03-13T17:33:45.566 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -709,7 +709,7 @@ F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220 F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51 F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 -F src/insert.c 88f3c98b0ebbee295bb5085753bdb64ef1546ee5f0f0100b8be4f756b8a1acc6 +F src/insert.c 7d4e27871c23ad98d062dcf21509573229b41307e125d4569a89e4a489383134 F src/json.c e2e40760d6689134c3e2ece38c6a496b34ff5e2661a8f238444a119af666fdce F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36 @@ -2179,8 +2179,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 94791824a6f04782aac6bc16c182685e2d6ebf5c688dc9f8d59e479c6fd5a40e 924281b94d8e6ba674d6fe2f7f01da890351355a854e9e6fe623fad1180f7392 -R af81f2952048774d882db6d201804b0c +P 38635651f08d42110c01d6b24f6e362e340511846294f8696af4afc795dae80d +R 3557bbe553b856781f68b1001ce502f1 U dan -Z a427b7a910e44c4f56ce4ce6ef8524f2 +Z cbe8c4c577b21b3ca1560ccfb96c64e5 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 4f0c6af8d4..f60296676d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -38635651f08d42110c01d6b24f6e362e340511846294f8696af4afc795dae80d \ No newline at end of file +2085c7f12a3916ec883c31795e29f2e2b6641c30ecf748cce9bff7b13b061d1f \ No newline at end of file diff --git a/src/insert.c b/src/insert.c index 7303e1950a..627a4892ec 100644 --- a/src/insert.c +++ b/src/insert.c @@ -578,7 +578,7 @@ void sqlite3AutoincrementEnd(Parse *pParse){ #endif /* SQLITE_OMIT_AUTOINCREMENT */ void sqlite3MultiValuesEnd(Parse *pParse, Select *pVal){ - if( pVal->pSrc->nSrc>0 ){ + if( pVal && pVal->pSrc->nSrc>0 ){ SrcItem *pItem = &pVal->pSrc->a[0]; sqlite3VdbeEndCoroutine(pParse->pVdbe, pItem->regReturn); sqlite3VdbeJumpHere(pParse->pVdbe, pItem->addrFillSub - 1); @@ -640,25 +640,24 @@ Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow){ Vdbe *v = sqlite3GetVdbe(pParse); Select *pRet; - if( v==0 ) return pLeft; pRet = sqlite3SelectNew(pParse, 0, 0, 0, 0, 0, 0, 0, 0); - if( pRet==0 ) return pLeft; - p = &pRet->pSrc->a[0]; - pRet->pSrc->nSrc = 1; - - p->pSelect = pLeft; - p->fg.viaCoroutine = 1; - p->addrFillSub = sqlite3VdbeCurrentAddr(v) + 1; - p->regReturn = ++pParse->nMem; - p->iCursor = -1; - - sqlite3VdbeAddOp3(v,OP_InitCoroutine,p->regReturn,0,p->addrFillSub); - sqlite3SelectDestInit(&dest, SRT_Coroutine, p->regReturn); - sqlite3Select(pParse, pLeft, &dest); - p->regResult = dest.iSdst; - assert( pParse->nErr || dest.iSdst>0 ); - - pLeft = pRet; + if( pRet ){ + p = &pRet->pSrc->a[0]; + pRet->pSrc->nSrc = 1; + + p->pSelect = pLeft; + p->fg.viaCoroutine = 1; + p->addrFillSub = sqlite3VdbeCurrentAddr(v) + 1; + p->regReturn = ++pParse->nMem; + p->iCursor = -1; + + sqlite3VdbeAddOp3(v,OP_InitCoroutine,p->regReturn,0,p->addrFillSub); + sqlite3SelectDestInit(&dest, SRT_Coroutine, p->regReturn); + sqlite3Select(pParse, pLeft, &dest); + p->regResult = dest.iSdst; + assert( pParse->nErr || dest.iSdst>0 ); + pLeft = pRet; + } }else{ p = &pLeft->pSrc->a[0]; } @@ -686,6 +685,8 @@ Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow){ } sqlite3SelectDelete(pParse->db, pSelect); } + }else{ + sqlite3ExprListDelete(pParse->db, pRow); } } From aa2e244e146de01c51be139cc95cec92aa7fe104 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 13 Mar 2024 18:41:05 +0000 Subject: [PATCH 06/34] Remove unreachable code from this branch. FossilOrigin-Name: 657c7b4f9df53e041a33cfad00ee2f507ac09c97a2ae61164bd189d660d167da --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/insert.c | 53 +++++++++++++++++---------------------------------- 3 files changed, 25 insertions(+), 42 deletions(-) diff --git a/manifest b/manifest index a91c89a359..1f5591b8ed 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\ssome\sOOM\shandling\sproblems\son\sthis\sbranch. -D 2024-03-13T17:33:45.566 +C Remove\sunreachable\scode\sfrom\sthis\sbranch. +D 2024-03-13T18:41:05.450 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -709,7 +709,7 @@ F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220 F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51 F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 -F src/insert.c 7d4e27871c23ad98d062dcf21509573229b41307e125d4569a89e4a489383134 +F src/insert.c 05dd5ea1b8da8a81e1132140fd4dd6d4d9e777ee282799c53cce4f3e9d7dd0ca F src/json.c e2e40760d6689134c3e2ece38c6a496b34ff5e2661a8f238444a119af666fdce F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36 @@ -2179,8 +2179,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 38635651f08d42110c01d6b24f6e362e340511846294f8696af4afc795dae80d -R 3557bbe553b856781f68b1001ce502f1 +P 2085c7f12a3916ec883c31795e29f2e2b6641c30ecf748cce9bff7b13b061d1f +R 77c42a89dcd308559626c377320e4df2 U dan -Z cbe8c4c577b21b3ca1560ccfb96c64e5 +Z 54b19091c4c166a485c83de0a7190e37 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index f60296676d..0dc187c408 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2085c7f12a3916ec883c31795e29f2e2b6641c30ecf748cce9bff7b13b061d1f \ No newline at end of file +657c7b4f9df53e041a33cfad00ee2f507ac09c97a2ae61164bd189d660d167da \ No newline at end of file diff --git a/src/insert.c b/src/insert.c index 627a4892ec..49ec5e0dc9 100644 --- a/src/insert.c +++ b/src/insert.c @@ -604,29 +604,29 @@ static int multiValueIsConstantNoAff(ExprList *pRow){ } +/* +** This function is called by the parser for the second and subsequent +** rows of a multi-row VALUES clause. +*/ Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow){ - SrcItem *p; - SelectDest dest; - Select *pSelect = 0; - if( pParse->db->init.busy - || pParse->pNewTrigger + if( pLeft->pPrior || pParse->bHasWith + || pParse->db->init.busy || multiValueIsConstant(pRow)==0 - || pLeft->pPrior || (pLeft->pSrc->nSrc==0 && multiValueIsConstantNoAff(pLeft->pEList)==0) ){ /* This row of the VALUES clause cannot be coded immediately. */ + Select *pSelect = 0; int f = SF_Values | SF_MultiValue; if( pLeft->pSrc->nSrc ){ sqlite3MultiValuesEnd(pParse, pLeft); f = SF_Values; }else if( pLeft->pPrior ){ - /* In this case set the SF_MultiValue flag only if it was set on - ** the previous Select structure. */ + /* In this case set the SF_MultiValue flag only if it was set on pLeft */ f = (f & pLeft->selFlags); } - pSelect = sqlite3SelectNew(pParse,pRow,0,0,0,0,0,f,0); + pSelect = sqlite3SelectNew(pParse, pRow, 0, 0, 0, 0, 0, f, 0); pLeft->selFlags &= ~SF_MultiValue; if( pSelect ){ pSelect->op = TK_ALL; @@ -634,6 +634,7 @@ Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow){ pLeft = pSelect; } }else{ + SrcItem *p = 0; if( pLeft->pSrc->nSrc==0 ){ /* Co-routine has not yet been started. */ @@ -642,15 +643,14 @@ Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow){ pRet = sqlite3SelectNew(pParse, 0, 0, 0, 0, 0, 0, 0, 0); if( pRet ){ - p = &pRet->pSrc->a[0]; + SelectDest dest; pRet->pSrc->nSrc = 1; - + p = &pRet->pSrc->a[0]; p->pSelect = pLeft; p->fg.viaCoroutine = 1; p->addrFillSub = sqlite3VdbeCurrentAddr(v) + 1; p->regReturn = ++pParse->nMem; p->iCursor = -1; - sqlite3VdbeAddOp3(v,OP_InitCoroutine,p->regReturn,0,p->addrFillSub); sqlite3SelectDestInit(&dest, SRT_Coroutine, p->regReturn); sqlite3Select(pParse, pLeft, &dest); @@ -663,31 +663,14 @@ Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow){ } if( pParse->nErr==0 ){ - pSelect = sqlite3SelectNew(pParse, pRow, 0, 0, 0, 0, 0, SF_Values, 0); - if( pSelect ){ - if( p->pSelect->pEList->nExpr!=pSelect->pEList->nExpr ){ - sqlite3SelectWrongNumTermsError(pParse, pSelect); - }else{ - sqlite3SelectPrep(pParse, pSelect, 0); -#ifndef SQLITE_OMIT_WINDOWFUNC - if( pSelect->pWin ){ - sqlite3SelectDestInit(&dest, SRT_Coroutine, p->regReturn); - dest.iSdst = p->regResult; - dest.nSdst = pRow->nExpr; - dest.iSDParm = p->regReturn; - sqlite3Select(pParse, pSelect, &dest); - }else -#endif - { - sqlite3ExprCodeExprList(pParse, pSelect->pEList,p->regResult,0,0); - sqlite3VdbeAddOp1(pParse->pVdbe, OP_Yield, p->regReturn); - } - } - sqlite3SelectDelete(pParse->db, pSelect); + if( p->pSelect->pEList->nExpr!=pRow->nExpr ){ + sqlite3SelectWrongNumTermsError(pParse, p->pSelect); + }else{ + sqlite3ExprCodeExprList(pParse, pRow, p->regResult, 0, 0); + sqlite3VdbeAddOp1(pParse->pVdbe, OP_Yield, p->regReturn); } - }else{ - sqlite3ExprListDelete(pParse->db, pRow); } + sqlite3ExprListDelete(pParse->db, pRow); } return pLeft; From 56be6f6c084070026fe720668f644f82fd628f8a Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 13 Mar 2024 20:04:11 +0000 Subject: [PATCH 07/34] Change the way parse.y handles multi-row VALUES clauses to save a few cycles. FossilOrigin-Name: 88d5bc91a52675d2a83748b79ad50de0e9732b2afd23107627bdc604f744d275 --- manifest | 16 ++++----- manifest.uuid | 2 +- src/insert.c | 90 ++++++++++++++++++++++++++++++++++++++++-------- src/parse.y | 34 +++++++++++------- test/values.test | 13 +++++++ 5 files changed, 118 insertions(+), 37 deletions(-) diff --git a/manifest b/manifest index 1f5591b8ed..86fcabaf5e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\sunreachable\scode\sfrom\sthis\sbranch. -D 2024-03-13T18:41:05.450 +C Change\sthe\sway\sparse.y\shandles\smulti-row\sVALUES\sclauses\sto\ssave\sa\sfew\scycles. +D 2024-03-13T20:04:11.997 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -709,7 +709,7 @@ F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220 F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51 F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 -F src/insert.c 05dd5ea1b8da8a81e1132140fd4dd6d4d9e777ee282799c53cce4f3e9d7dd0ca +F src/insert.c 6323a2da33b5af954f914f33e06af30cce354bbd2553261a4b64e578339e498f F src/json.c e2e40760d6689134c3e2ece38c6a496b34ff5e2661a8f238444a119af666fdce F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36 @@ -739,7 +739,7 @@ F src/os_win.c 6ff43bac175bd9ed79e7c0f96840b139f2f51d01689a638fd05128becf94908a F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/pager.c ff60e98138d2499082ac6230f01ac508aba545315debccfca2fd6042f5f10fcd F src/pager.h 4b1140d691860de0be1347474c51fee07d5420bd7f802d38cbab8ea4ab9f538a -F src/parse.y 3d022ba4c68bf8c7c4c40b3e364d7a8226c4089fc9ff7a3a95f969f8f1bec959 +F src/parse.y 2ff84e5e346974100b7ed37f01abfd148012e1ce65a6b5a72d5025258077121e F src/pcache.c 040b165f30622a21b7a9a77c6f2e4877a32fb7f22d4c7f0d2a6fa6833a156a75 F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5 F src/pcache1.c 602acb23c471bb8d557a6f0083cc2be641d6cafcafa19e481eba7ef4c9ca0f00 @@ -1921,7 +1921,7 @@ F test/vacuum4.test 7ea76b769fffeb41f925303b04cbcf5a5bbeabe55e4c60ae754ff24eeeb7 F test/vacuum5.test 263b144d537e92ad8e9ca8a73cc6e1583f41cfd0dda9432b87f7806174a2f48c F test/vacuum6.test b137b04bf3392d3f5c3b8fda0ce85a6775a70ca112f6559f74ff52dc9ce042fd F test/vacuummem.test 4b30f5b95a9ff86e9d5c20741e50a898b2dc10b0962a3211571eb165357003fb -F test/values.test 3f0fe0e8859306e9a5cfc800e327278762510c8d5b075d8ddce40f2d13d1405a +F test/values.test 1f0a7f8468d7f087bc4add7a95545afb15e22d5e629a18fbea73b9d76f3ef8bd F test/valuesfault.test 2ef23ed965e3bd08e268cdc38a0d11653390ddbbe1e8e2e98d16f55edd30f6e8 F test/varint.test bbce22cda8fc4d135bcc2b589574be8410614e62 F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661 @@ -2179,8 +2179,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 2085c7f12a3916ec883c31795e29f2e2b6641c30ecf748cce9bff7b13b061d1f -R 77c42a89dcd308559626c377320e4df2 +P 657c7b4f9df53e041a33cfad00ee2f507ac09c97a2ae61164bd189d660d167da +R c74bcaf2a43ef6c41ceff5cdf5beeb0e U dan -Z 54b19091c4c166a485c83de0a7190e37 +Z dc10b4e059ebbb23528a1aebd608a6c4 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 0dc187c408..e561c09c27 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -657c7b4f9df53e041a33cfad00ee2f507ac09c97a2ae61164bd189d660d167da \ No newline at end of file +88d5bc91a52675d2a83748b79ad50de0e9732b2afd23107627bdc604f744d275 \ No newline at end of file diff --git a/src/insert.c b/src/insert.c index 49ec5e0dc9..9302c10417 100644 --- a/src/insert.c +++ b/src/insert.c @@ -577,6 +577,11 @@ void sqlite3AutoincrementEnd(Parse *pParse){ # define autoIncStep(A,B,C) #endif /* SQLITE_OMIT_AUTOINCREMENT */ +/* +** If argument pVal is a Select object returned by an sqlite3MultiValues() +** that was able to use the co-routine optimization, finish coding the +** co-routine. +*/ void sqlite3MultiValuesEnd(Parse *pParse, Select *pVal){ if( pVal && pVal->pSrc->nSrc>0 ){ SrcItem *pItem = &pVal->pSrc->a[0]; @@ -585,7 +590,11 @@ void sqlite3MultiValuesEnd(Parse *pParse, Select *pVal){ } } -static int multiValueIsConstant(ExprList *pRow){ +/* +** Return true if all expressions in the expression-list passed as the +** only argument are constant. +*/ +static int exprListIsConstant(ExprList *pRow){ int ii; for(ii=0; iinExpr; ii++){ if( 0==sqlite3ExprIsConstant(pRow->a[ii].pExpr) ) return 0; @@ -593,9 +602,13 @@ static int multiValueIsConstant(ExprList *pRow){ return 1; } -static int multiValueIsConstantNoAff(ExprList *pRow){ +/* +** Return true if all expressions in the expression-list passed as the +** only argument are both constant and have no affinity. +*/ +static int exprListIsNoAffinity(ExprList *pRow){ int ii; - if( multiValueIsConstant(pRow)==0 ) return 0; + if( exprListIsConstant(pRow)==0 ) return 0; for(ii=0; iinExpr; ii++){ assert( pRow->a[ii].pExpr->affExpr==0 ); if( 0!=sqlite3ExprAffinity(pRow->a[ii].pExpr) ) return 0; @@ -606,17 +619,64 @@ static int multiValueIsConstantNoAff(ExprList *pRow){ /* ** This function is called by the parser for the second and subsequent -** rows of a multi-row VALUES clause. +** rows of a multi-row VALUES clause. Argument pLeft is the part of +** the VALUES clause already parsed, argument pRow is the vector of values +** for the new row. The Select object returned represents the complete +** VALUES clause, including the new row. +** +** There are two ways in which this may be achieved - by incremental +** coding of a co-routine (the "co-routine" method) or by returning a +** Select object equivalent to the following (the "UNION ALL" method): +** +** "pLeft UNION ALL SELECT pRow" +** +** If the VALUES clause contains a lot of rows, this compound Select +** object may consume a lot of memory. +** +** When the co-routine method is used, each row that will be returned +** by the VALUES clause is coded into part of a co-routine as it is +** passed to this function. The returned Select object is equivalent to: +** +** SELECT * FROM ( +** Select object to read co-routine +** ) +** +** The co-routine method is used in most cases. Exceptions are: +** +** a) If the current statement has a WITH clause. This is to avoid +** statements like: +** +** WITH cte AS ( VALUES('x'), ('y') ... ) +** SELECT * FROM cte AS a, cte AS b; +** +** This will not work, as the co-routine uses a hard-coded register +** for its OP_Yield instructions, and so it is not possible for two +** cursors to iterate through it concurrently. +** +** b) The schema is currently being parsed (i.e. the VALUES clause is part +** of a schema item like a VIEW or TRIGGER). In this case there is no VM +** being generated when parsing is taking place, and so generating +** a co-routine is not possible. +** +** c) There are non-constant expressions in the VALUES clause (e.g. +** the VALUES clause is part of a correlated sub-query). +** +** d) One or more of the values in the first row of the VALUES clause +** has an affinity (i.e. is a CAST expression). This causes problems +** because the complex rules SQLite uses (see function +** sqlite3SubqueryColumnTypes() in select.c) to determine the effective +** affinity of such a column for all rows require access to all values in +** the column simultaneously. */ Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow){ - if( pLeft->pPrior - || pParse->bHasWith - || pParse->db->init.busy - || multiValueIsConstant(pRow)==0 - || (pLeft->pSrc->nSrc==0 && multiValueIsConstantNoAff(pLeft->pEList)==0) + if( pLeft->pPrior /* co-routine precluded by prior row */ + || pParse->bHasWith /* condition (a) above */ + || pParse->db->init.busy /* condition (b) above */ + || exprListIsConstant(pRow)==0 /* condition (c) above */ + || (pLeft->pSrc->nSrc==0 && exprListIsNoAffinity(pLeft->pEList)==0) /* (d) */ ){ - /* This row of the VALUES clause cannot be coded immediately. */ + /* The co-routine method cannot be used. Fall back to UNION ALL. */ Select *pSelect = 0; int f = SF_Values | SF_MultiValue; if( pLeft->pSrc->nSrc ){ @@ -634,14 +694,14 @@ Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow){ pLeft = pSelect; } }else{ - SrcItem *p = 0; + SrcItem *p = 0; /* SrcItem that reads from co-routine */ if( pLeft->pSrc->nSrc==0 ){ - /* Co-routine has not yet been started. */ + /* Co-routine has not yet been started and the special Select object + ** that accesses the co-routine has not yet been created. This block + ** does both those things. */ Vdbe *v = sqlite3GetVdbe(pParse); - Select *pRet; - - pRet = sqlite3SelectNew(pParse, 0, 0, 0, 0, 0, 0, 0, 0); + Select *pRet = sqlite3SelectNew(pParse, 0, 0, 0, 0, 0, 0, 0, 0); if( pRet ){ SelectDest dest; pRet->pSrc->nSrc = 1; diff --git a/src/parse.y b/src/parse.y index 515d512f2c..36566d28aa 100644 --- a/src/parse.y +++ b/src/parse.y @@ -562,13 +562,10 @@ cmd ::= select(X). { } %ifndef SQLITE_OMIT_CTE -select(A) ::= withkw wqlist(W) selectnowith(X). {A = attachWithToSelect(pParse,X,W);} -select(A) ::= withkw RECURSIVE wqlist(W) selectnowith(X). +select(A) ::= WITH wqlist(W) selectnowith(X). {A = attachWithToSelect(pParse,X,W);} +select(A) ::= WITH RECURSIVE wqlist(W) selectnowith(X). {A = attachWithToSelect(pParse,X,W);} -withkw ::= WITH. { - pParse->bHasWith = 1; -} %endif /* SQLITE_OMIT_CTE */ select(A) ::= selectnowith(A). { Select *p = A; @@ -626,16 +623,26 @@ oneselect(A) ::= SELECT distinct(D) selcollist(W) from(X) where_opt(Y) %endif -oneselect(A) ::= values(A). { - sqlite3MultiValuesEnd(pParse, A); -} - +// Single row VALUES clause. +// %type values {Select*} +oneselect(A) ::= values(A). %destructor values {sqlite3SelectDelete(pParse->db, $$);} values(A) ::= VALUES LP nexprlist(X) RP. { A = sqlite3SelectNew(pParse,X,0,0,0,0,0,SF_Values,0); } -values(A) ::= values(A) COMMA LP nexprlist(Y) RP. { + +// Multiple row VALUES clause. +// +%type mvalues {Select*} +oneselect(A) ::= mvalues(A). { + sqlite3MultiValuesEnd(pParse, A); +} +%destructor mvalues {sqlite3SelectDelete(pParse->db, $$);} +mvalues(A) ::= values(A) COMMA LP nexprlist(Y) RP. { + A = sqlite3MultiValues(pParse, A, Y); +} +mvalues(A) ::= mvalues(A) COMMA LP nexprlist(Y) RP. { A = sqlite3MultiValues(pParse, A, Y); } @@ -1751,16 +1758,17 @@ anylist ::= anylist ANY. with ::= . %ifndef SQLITE_OMIT_CTE -with ::= withkw wqlist(W). { sqlite3WithPush(pParse, W, 1); } -with ::= withkw RECURSIVE wqlist(W). { sqlite3WithPush(pParse, W, 1); } +with ::= WITH wqlist(W). { sqlite3WithPush(pParse, W, 1); } +with ::= WITH RECURSIVE wqlist(W). { sqlite3WithPush(pParse, W, 1); } %type wqas {u8} wqas(A) ::= AS. {A = M10d_Any;} wqas(A) ::= AS MATERIALIZED. {A = M10d_Yes;} wqas(A) ::= AS NOT MATERIALIZED. {A = M10d_No;} -wqitem(A) ::= nm(X) eidlist_opt(Y) wqas(M) LP select(Z) RP. { +wqitem(A) ::= withnm(X) eidlist_opt(Y) wqas(M) LP select(Z) RP. { A = sqlite3CteNew(pParse, &X, Y, Z, M); /*A-overwrites-X*/ } +withnm(A) ::= nm(A). {pParse->bHasWith = 1;} wqlist(A) ::= wqitem(X). { A = sqlite3WithAdd(pParse, 0, X); /*A-overwrites-X*/ } diff --git a/test/values.test b/test/values.test index 627987b43b..7c260260d0 100644 --- a/test/values.test +++ b/test/values.test @@ -267,5 +267,18 @@ do_execsql_test 6.2 { VALUES(CAST(44 AS REAL)),(55); } {44.0 55} +#------------------------------------------------------------------------ +do_execsql_test 7.1 { + WITH x1(a, b) AS ( + VALUES(1, 2), ('a', 'b') + ) + SELECT * FROM x1 one, x1 two +} { + 1 2 1 2 + 1 2 a b + a b 1 2 + a b a b +} + finish_test From a06c046e29d5024efafb1cc5a90fead8731bc96b Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 14 Mar 2024 11:45:39 +0000 Subject: [PATCH 08/34] Add further tests for VALUES clauses in various contexts. FossilOrigin-Name: 973d197d9676c066a95cea77a27e36d2d7f5778283919d8cac4424d2ec952f47 --- manifest | 12 +++---- manifest.uuid | 2 +- test/values.test | 91 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 98 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index 86fcabaf5e..92b88f4681 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\sthe\sway\sparse.y\shandles\smulti-row\sVALUES\sclauses\sto\ssave\sa\sfew\scycles. -D 2024-03-13T20:04:11.997 +C Add\sfurther\stests\sfor\sVALUES\sclauses\sin\svarious\scontexts. +D 2024-03-14T11:45:39.711 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -1921,7 +1921,7 @@ F test/vacuum4.test 7ea76b769fffeb41f925303b04cbcf5a5bbeabe55e4c60ae754ff24eeeb7 F test/vacuum5.test 263b144d537e92ad8e9ca8a73cc6e1583f41cfd0dda9432b87f7806174a2f48c F test/vacuum6.test b137b04bf3392d3f5c3b8fda0ce85a6775a70ca112f6559f74ff52dc9ce042fd F test/vacuummem.test 4b30f5b95a9ff86e9d5c20741e50a898b2dc10b0962a3211571eb165357003fb -F test/values.test 1f0a7f8468d7f087bc4add7a95545afb15e22d5e629a18fbea73b9d76f3ef8bd +F test/values.test 97a12553a3bb5bae5bdd924e1bdc53540e59d255f5072fe1f744412497ffb8e9 F test/valuesfault.test 2ef23ed965e3bd08e268cdc38a0d11653390ddbbe1e8e2e98d16f55edd30f6e8 F test/varint.test bbce22cda8fc4d135bcc2b589574be8410614e62 F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661 @@ -2179,8 +2179,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 657c7b4f9df53e041a33cfad00ee2f507ac09c97a2ae61164bd189d660d167da -R c74bcaf2a43ef6c41ceff5cdf5beeb0e +P 88d5bc91a52675d2a83748b79ad50de0e9732b2afd23107627bdc604f744d275 +R ff7025814ffdce6724f42ac930401faa U dan -Z dc10b4e059ebbb23528a1aebd608a6c4 +Z a6579ddbeb44182b511c7d09df6cac16 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index e561c09c27..21731dcc23 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -88d5bc91a52675d2a83748b79ad50de0e9732b2afd23107627bdc604f744d275 \ No newline at end of file +973d197d9676c066a95cea77a27e36d2d7f5778283919d8cac4424d2ec952f47 \ No newline at end of file diff --git a/test/values.test b/test/values.test index 7c260260d0..08f8193f95 100644 --- a/test/values.test +++ b/test/values.test @@ -280,5 +280,96 @@ do_execsql_test 7.1 { a b a b } +#------------------------------------------------------------------------- +reset_db + +set VVV { + ( VALUES('a', 'b'), ('c', 'd'), (123, NULL) ) +} +set VVV2 { + ( + SELECT 'a' AS column1, 'b' AS column2 + UNION ALL SELECT 'c', 'd' UNION ALL SELECT 123, NULL + ) +} + +do_execsql_test 8.0 { + CREATE TABLE t1(x); + INSERT INTO t1 VALUES('d'), (NULL), (123) +} +foreach {tn q res} { + 1 "SELECT * FROM t1 LEFT JOIN VVV" { + d a b d c d d 123 {} + {} a b {} c d {} 123 {} + 123 a b 123 c d 123 123 {} + } + + 2 "SELECT * FROM t1 LEFT JOIN VVV ON (column1=x)" { + d {} {} + {} {} {} + 123 123 {} + } + + 3 "SELECT * FROM t1 RIGHT JOIN VVV" { + d a b d c d d 123 {} + {} a b {} c d {} 123 {} + 123 a b 123 c d 123 123 {} + } + + 4 "SELECT * FROM t1 RIGHT JOIN VVV ON (column1=x)" { + 123 123 {} + {} a b + {} c d + } + + 5 "SELECT * FROM t1 FULL OUTER JOIN VVV ON (column1=x)" { + d {} {} + {} {} {} + 123 123 {} + {} a b + {} c d + } + + 6 "SELECT count(*) FROM VVV" { 3 } + + 7 "SELECT (SELECT column1 FROM VVV)" { a } + + 8 "SELECT * FROM VVV UNION ALL SELECT * FROM VVV" { + a b c d 123 {} + a b c d 123 {} + } + + 9 "SELECT * FROM VVV INTERSECT SELECT * FROM VVV" { + 123 {} a b c d + } + + 10 "SELECT * FROM VVV eXCEPT SELECT * FROM VVV" { } + + 11 "SELECT * FROM VVV eXCEPT SELECT 'a', 'b'" { 123 {} c d } + +} { + set q1 [string map [list VVV $VVV] $q] + set q2 [string map [list VVV $VVV2] $q] + set q3 "WITH VVV AS $VVV $q" + + do_execsql_test 8.1.$tn.1 $q1 $res + do_execsql_test 8.1.$tn.2 $q2 $res + do_execsql_test 8.1.$tn.3 $q3 $res +} + +#------------------------------------------------------------------------- +reset_db + +do_execsql_test 9.1 { + VALUES(456), (123), (NULL) UNION ALL SELECT 122 ORDER BY 1 +} { {} 122 123 456 } + +do_execsql_test 9.2 { + VALUES (1, 2), (3, 4), ( + ( SELECT column1 FROM ( VALUES (5, 6), (7, 8) ) ), + ( SELECT max(column2) FROM ( VALUES (5, 1), (7, 6) ) ) + ) +} { 1 2 3 4 5 6 } + finish_test From 5a0fd81fcec15afd0ecdcbb565b6014ad21b2c96 Mon Sep 17 00:00:00 2001 From: stephan Date: Thu, 14 Mar 2024 13:18:19 +0000 Subject: [PATCH 09/34] JS: remove an unused function argument and some debug-related comments. No functional changes. FossilOrigin-Name: f15709430d4ba2fcf5729bc30a45dacb77102927b82cda12de0b67935b526cc0 --- ext/wasm/api/sqlite3-opfs-async-proxy.js | 9 +++------ manifest | 14 +++++++------- manifest.uuid | 2 +- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/ext/wasm/api/sqlite3-opfs-async-proxy.js b/ext/wasm/api/sqlite3-opfs-async-proxy.js index 58b8bcb233..e671094f04 100644 --- a/ext/wasm/api/sqlite3-opfs-async-proxy.js +++ b/ext/wasm/api/sqlite3-opfs-async-proxy.js @@ -51,7 +51,7 @@ */ "use strict"; const wPost = (type,...args)=>postMessage({type, payload:args}); -const installAsyncProxy = function(self){ +const installAsyncProxy = function(){ const toss = function(...args){throw new Error(args.join(' '))}; if(globalThis.window === globalThis){ toss("This code cannot run from the main thread.", @@ -563,12 +563,9 @@ const installAsyncProxy = function(self){ return; } if( state.opfsFlags.OPFS_UNLINK_BEFORE_OPEN & opfsFlags ){ - //log("async proxy opfsFlags =",opfsFlags); try{ await hDir.removeEntry(filenamePart); - //log("Unlinked",filename,hDir,filenamePart); - } - catch(e){ + }catch(e){ /* ignoring */ //warn("Ignoring failed Unlink of",filename,":",e); } @@ -922,5 +919,5 @@ if(!globalThis.SharedArrayBuffer){ !navigator?.storage?.getDirectory){ wPost('opfs-unavailable',"Missing required OPFS APIs."); }else{ - installAsyncProxy(self); + installAsyncProxy(); } diff --git a/manifest b/manifest index d831726a46..d9e3176a98 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Minor\schange\sto\sthe\s"mdevtest"\sand\s"sdevtest"\sin\stestrunner.tcl,\sto\smake\sit\neasier\sto\sadd\sconfigurations\sin\sbranches. -D 2024-03-13T16:32:05.539 +C JS:\sremove\san\sunused\sfunction\sargument\sand\ssome\sdebug-related\scomments.\sNo\sfunctional\schanges. +D 2024-03-14T13:18:19.313 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -610,7 +610,7 @@ F ext/wasm/api/sqlite3-api-oo1.js 7f3bcf0549ac44cde4b9da0b642d771916738d3f6781fb F ext/wasm/api/sqlite3-api-prologue.js 93a72b07b2a5d964d2edc76a90b439ece49298bd7ba60a1c6ae5d4878213701e F ext/wasm/api/sqlite3-api-worker1.js 8d9c0562831f62218170a3373468d8a0b7a6503b5985e309b69bf71187b525cf F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89 -F ext/wasm/api/sqlite3-opfs-async-proxy.js b4c7ce9d7f7957f243d0fbd5b6e28bac80cd3c1b738374cd0c96d89df8f2f316 +F ext/wasm/api/sqlite3-opfs-async-proxy.js 196ad83d36ca794e564044788c9d21b964679d63cad865f604da37c4afc9a285 F ext/wasm/api/sqlite3-vfs-helper.c-pp.js 3f828cc66758acb40e9c5b4dcfd87fd478a14c8fb7f0630264e6c7fa0e57515d F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js 5a430874906ff3f4a6ca69aadf0c2aaedc1bb45489b8365bff7e955a83a8d42a F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 3c72f1a0e6a7343c8c882d29d01bb440f10be12c844651605b486e76f3d6cc8c @@ -2177,8 +2177,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 924281b94d8e6ba674d6fe2f7f01da890351355a854e9e6fe623fad1180f7392 -R 92509b8a5762b034ecb1ec5b7039a632 -U drh -Z 644a950afdac6e39b6751ae1898b20f1 +P 9349d94e05dcf266b02afcd89f1e433cdc45f23e8536b2f3f9aa242d5d89c307 +R e2c267441183e97923991728d71c55b9 +U stephan +Z f0980170118e0dee3925f721da1aaab7 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index cd3ae2f7ad..19a52c5ee0 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9349d94e05dcf266b02afcd89f1e433cdc45f23e8536b2f3f9aa242d5d89c307 \ No newline at end of file +f15709430d4ba2fcf5729bc30a45dacb77102927b82cda12de0b67935b526cc0 \ No newline at end of file From f0f43238248e3e6491686acf1104217face58b00 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 14 Mar 2024 17:04:18 +0000 Subject: [PATCH 10/34] Avoid some OP_SCopy instructions in "INSERT INTO .. VALUES" statements that insert more than one row in cases where the VALUES clause contains a value for all columns of the table. FossilOrigin-Name: 988f0ea70cd21b3194011e0cd1ddd4990a07669e0fd9c37afa48f69698ab7212 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/insert.c | 15 +++++++++++++++ test/values.test | 17 +++++++++++++++++ 4 files changed, 40 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 92b88f4681..4b2722dbe6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sfurther\stests\sfor\sVALUES\sclauses\sin\svarious\scontexts. -D 2024-03-14T11:45:39.711 +C Avoid\ssome\sOP_SCopy\sinstructions\sin\s"INSERT\sINTO\s..\sVALUES"\sstatements\sthat\sinsert\smore\sthan\sone\srow\sin\scases\swhere\sthe\sVALUES\sclause\scontains\sa\svalue\sfor\sall\scolumns\sof\sthe\stable. +D 2024-03-14T17:04:18.708 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -709,7 +709,7 @@ F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220 F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51 F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 -F src/insert.c 6323a2da33b5af954f914f33e06af30cce354bbd2553261a4b64e578339e498f +F src/insert.c 49b1f253248a7492595ee5b602f8b9f8f5bd25037148ca4429b24bd11d9033ed F src/json.c e2e40760d6689134c3e2ece38c6a496b34ff5e2661a8f238444a119af666fdce F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36 @@ -1921,7 +1921,7 @@ F test/vacuum4.test 7ea76b769fffeb41f925303b04cbcf5a5bbeabe55e4c60ae754ff24eeeb7 F test/vacuum5.test 263b144d537e92ad8e9ca8a73cc6e1583f41cfd0dda9432b87f7806174a2f48c F test/vacuum6.test b137b04bf3392d3f5c3b8fda0ce85a6775a70ca112f6559f74ff52dc9ce042fd F test/vacuummem.test 4b30f5b95a9ff86e9d5c20741e50a898b2dc10b0962a3211571eb165357003fb -F test/values.test 97a12553a3bb5bae5bdd924e1bdc53540e59d255f5072fe1f744412497ffb8e9 +F test/values.test 9ec708b15ef0c6a63ece21b2cffcf1bc11cdc96b7fc778e62995de51609afcad F test/valuesfault.test 2ef23ed965e3bd08e268cdc38a0d11653390ddbbe1e8e2e98d16f55edd30f6e8 F test/varint.test bbce22cda8fc4d135bcc2b589574be8410614e62 F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661 @@ -2179,8 +2179,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 88d5bc91a52675d2a83748b79ad50de0e9732b2afd23107627bdc604f744d275 -R ff7025814ffdce6724f42ac930401faa +P 973d197d9676c066a95cea77a27e36d2d7f5778283919d8cac4424d2ec952f47 +R 35577c4549391d6fa401c7e1873df695 U dan -Z a6579ddbeb44182b511c7d09df6cac16 +Z 98186a481119713b14ebbdd018027220 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 21731dcc23..591f868806 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -973d197d9676c066a95cea77a27e36d2d7f5778283919d8cac4424d2ec952f47 \ No newline at end of file +988f0ea70cd21b3194011e0cd1ddd4990a07669e0fd9c37afa48f69698ab7212 \ No newline at end of file diff --git a/src/insert.c b/src/insert.c index 9302c10417..3fc5f6ccdb 100644 --- a/src/insert.c +++ b/src/insert.c @@ -713,6 +713,16 @@ Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow){ p->iCursor = -1; sqlite3VdbeAddOp3(v,OP_InitCoroutine,p->regReturn,0,p->addrFillSub); sqlite3SelectDestInit(&dest, SRT_Coroutine, p->regReturn); + + /* Allocate registers for the output of the co-routine. Do so so + ** that there are two unused registers immediately before those + ** used by the co-routine. This allows the code in sqlite3Insert() + ** to use these registers directly, instead of copying the output + ** of the co-routine to a separate array for processing. */ + dest.iSdst = pParse->nMem + 3; + dest.nSdst = pLeft->pEList->nExpr; + pParse->nMem += 2 + dest.nSdst; + sqlite3Select(pParse, pLeft, &dest); p->regResult = dest.iSdst; assert( pParse->nErr || dest.iSdst>0 ); @@ -1079,6 +1089,11 @@ void sqlite3Insert( dest.iSDParm = regYield = pItem->regReturn; regFromSelect = pItem->regResult; nColumn = pItem->pSelect->pEList->nExpr; + if( bIdListInOrder && nColumn==pTab->nCol ){ + regData = regFromSelect; + regRowid = regData - 1; + regIns = regRowid - (IsVirtual(pTab) ? 1 : 0); + } }else{ int addrTop; /* Top of the co-routine */ regYield = ++pParse->nMem; diff --git a/test/values.test b/test/values.test index 08f8193f95..51fb818a3a 100644 --- a/test/values.test +++ b/test/values.test @@ -371,5 +371,22 @@ do_execsql_test 9.2 { ) } { 1 2 3 4 5 6 } +do_execsql_test 10.1 { + CREATE TABLE a2(a, b, c DEFAULT 'xyz'); +} +do_execsql_test 10.2 { + INSERT INTO a2(a) VALUES(3),(4); +} + +#------------------------------------------------------------------------- +reset_db +ifcapable fts5 { + do_execsql_test 11.0 { + CREATE VIRTUAL TABLE ft USING fts3(x); + } + do_execsql_test 11.1 { + INSERT INTO ft VALUES('one'), ('two'); + } +} finish_test From 400992b1c4e48b10bbfb29301f5582f74e3188a3 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 14 Mar 2024 19:01:17 +0000 Subject: [PATCH 11/34] Fix a problem handling "INSERT INTO ... SELECT ... UNION VALUES(...), (...)" and similar statements. FossilOrigin-Name: e8a2a8198a97046ff376bc5d38e4bc0a24fcac79f5a0dadb9d29d953a862a012 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/insert.c | 5 ++++- test/values.test | 14 ++++++++++++++ 4 files changed, 26 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 4b2722dbe6..70d506eb4c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Avoid\ssome\sOP_SCopy\sinstructions\sin\s"INSERT\sINTO\s..\sVALUES"\sstatements\sthat\sinsert\smore\sthan\sone\srow\sin\scases\swhere\sthe\sVALUES\sclause\scontains\sa\svalue\sfor\sall\scolumns\sof\sthe\stable. -D 2024-03-14T17:04:18.708 +C Fix\sa\sproblem\shandling\s"INSERT\sINTO\s...\sSELECT\s...\sUNION\sVALUES(...),\s(...)"\sand\ssimilar\sstatements. +D 2024-03-14T19:01:17.847 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -709,7 +709,7 @@ F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220 F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51 F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 -F src/insert.c 49b1f253248a7492595ee5b602f8b9f8f5bd25037148ca4429b24bd11d9033ed +F src/insert.c 609b1862f7047c13f5bf531210b6918367e3f594fddd6deb0f9a3bc90aebc1a5 F src/json.c e2e40760d6689134c3e2ece38c6a496b34ff5e2661a8f238444a119af666fdce F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36 @@ -1921,7 +1921,7 @@ F test/vacuum4.test 7ea76b769fffeb41f925303b04cbcf5a5bbeabe55e4c60ae754ff24eeeb7 F test/vacuum5.test 263b144d537e92ad8e9ca8a73cc6e1583f41cfd0dda9432b87f7806174a2f48c F test/vacuum6.test b137b04bf3392d3f5c3b8fda0ce85a6775a70ca112f6559f74ff52dc9ce042fd F test/vacuummem.test 4b30f5b95a9ff86e9d5c20741e50a898b2dc10b0962a3211571eb165357003fb -F test/values.test 9ec708b15ef0c6a63ece21b2cffcf1bc11cdc96b7fc778e62995de51609afcad +F test/values.test f888bc7e833cc84258497f2c1b016f04515db00f9ee2e37ea12164eb9c8f47cf F test/valuesfault.test 2ef23ed965e3bd08e268cdc38a0d11653390ddbbe1e8e2e98d16f55edd30f6e8 F test/varint.test bbce22cda8fc4d135bcc2b589574be8410614e62 F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661 @@ -2179,8 +2179,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 973d197d9676c066a95cea77a27e36d2d7f5778283919d8cac4424d2ec952f47 -R 35577c4549391d6fa401c7e1873df695 +P 988f0ea70cd21b3194011e0cd1ddd4990a07669e0fd9c37afa48f69698ab7212 +R 15823514808bcf5b8985bdd8c17c3034 U dan -Z 98186a481119713b14ebbdd018027220 +Z 3a0769f650aec425942250a7ea141fa5 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 591f868806..9344f0ae07 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -988f0ea70cd21b3194011e0cd1ddd4990a07669e0fd9c37afa48f69698ab7212 \ No newline at end of file +e8a2a8198a97046ff376bc5d38e4bc0a24fcac79f5a0dadb9d29d953a862a012 \ No newline at end of file diff --git a/src/insert.c b/src/insert.c index 3fc5f6ccdb..428d5c1940 100644 --- a/src/insert.c +++ b/src/insert.c @@ -1084,7 +1084,10 @@ void sqlite3Insert( int regYield; /* Register holding co-routine entry-point */ int rc; /* Result code */ - if( pSelect->pSrc->nSrc==1 && pSelect->pSrc->a[0].fg.viaCoroutine ){ + if( pSelect->pSrc->nSrc==1 + && pSelect->pSrc->a[0].fg.viaCoroutine + && pSelect->pPrior==0 + ){ SrcItem *pItem = &pSelect->pSrc->a[0]; dest.iSDParm = regYield = pItem->regReturn; regFromSelect = pItem->regResult; diff --git a/test/values.test b/test/values.test index 51fb818a3a..3dba3dda94 100644 --- a/test/values.test +++ b/test/values.test @@ -388,5 +388,19 @@ ifcapable fts5 { INSERT INTO ft VALUES('one'), ('two'); } } + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 12.0 { + CREATE TABLE t1(a, b); +} +do_execsql_test 12.1 { + INSERT INTO t1 SELECT 1, 2 UNION ALL VALUES(3, 4), (5, 6); +} +do_execsql_test 12.2 { + SELECT * FROM t1 +} {1 2 3 4 5 6} + + finish_test From 26a3ef7557c6118a717f6555aefc7e424ffe1ca9 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 14 Mar 2024 19:31:06 +0000 Subject: [PATCH 12/34] Fix a problem with ALTER TABLE and correlated multi-row VALUES clauses. FossilOrigin-Name: d543c829ef74dbd64105bd757ca660e4f02e9ce562be4f1688a701fa535351c4 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/insert.c | 1 + test/altertab3.test | 27 +++++++++++++++++++++++++++ 4 files changed, 36 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 70d506eb4c..fb7853d8f0 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sproblem\shandling\s"INSERT\sINTO\s...\sSELECT\s...\sUNION\sVALUES(...),\s(...)"\sand\ssimilar\sstatements. -D 2024-03-14T19:01:17.847 +C Fix\sa\sproblem\swith\sALTER\sTABLE\sand\scorrelated\smulti-row\sVALUES\sclauses. +D 2024-03-14T19:31:06.929 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -709,7 +709,7 @@ F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220 F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51 F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 -F src/insert.c 609b1862f7047c13f5bf531210b6918367e3f594fddd6deb0f9a3bc90aebc1a5 +F src/insert.c b03721dfe0679445c635c33f137fde594e73abdd5bc042ca3c15990b339151d0 F src/json.c e2e40760d6689134c3e2ece38c6a496b34ff5e2661a8f238444a119af666fdce F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36 @@ -867,7 +867,7 @@ F test/altermalloc3.test 8040e486368403f2fdd6fc3998258b499bd4cc2f3ddbb5f8f874cd4 F test/alterqf.test 8ec03d776de9c391daa0078ea8f838903bdcfb11dfae4ba3576b48436834ccba F test/altertab.test 8a2712f9076da5012a002d0b5cc0a421398a5bf61c25bab41b77c427586a7a27 F test/altertab2.test 62597b6fd08feaba1b6bfe7d31dac6117c67e06dc9ce9c478a3abe75b5926de0 -F test/altertab3.test 6c432fbb9963e0bd6549bf1422f6861d744ee5a80cb3298564e81e556481df16 +F test/altertab3.test e167ce3b8e243b52306c1e40b13eb868f402a969513c063998593862cc643b44 F test/altertrig.test aacc980b657354fe2d3d4d3a004f07d04ccc1a93e5ef82d68a79088c274ddc6b F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f F test/analyze.test 2fb21d7d64748636384e6cb8998dbf83968caf644c07fcb4f76c18f2e7ede94b @@ -2179,8 +2179,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 988f0ea70cd21b3194011e0cd1ddd4990a07669e0fd9c37afa48f69698ab7212 -R 15823514808bcf5b8985bdd8c17c3034 +P e8a2a8198a97046ff376bc5d38e4bc0a24fcac79f5a0dadb9d29d953a862a012 +R 52836dd49dafb492a11e027744e0ffa5 U dan -Z 3a0769f650aec425942250a7ea141fa5 +Z 97470bd397212d168f5c1df2d58f75c8 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 9344f0ae07..8c9e08af96 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e8a2a8198a97046ff376bc5d38e4bc0a24fcac79f5a0dadb9d29d953a862a012 \ No newline at end of file +d543c829ef74dbd64105bd757ca660e4f02e9ce562be4f1688a701fa535351c4 \ No newline at end of file diff --git a/src/insert.c b/src/insert.c index 428d5c1940..2bd846e834 100644 --- a/src/insert.c +++ b/src/insert.c @@ -675,6 +675,7 @@ Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow){ || pParse->db->init.busy /* condition (b) above */ || exprListIsConstant(pRow)==0 /* condition (c) above */ || (pLeft->pSrc->nSrc==0 && exprListIsNoAffinity(pLeft->pEList)==0) /* (d) */ + || IN_SPECIAL_PARSE ){ /* The co-routine method cannot be used. Fall back to UNION ALL. */ Select *pSelect = 0; diff --git a/test/altertab3.test b/test/altertab3.test index 5fd17f3a2f..cb6f00de48 100644 --- a/test/altertab3.test +++ b/test/altertab3.test @@ -736,4 +736,31 @@ do_execsql_test 29.7 { END} } +#------------------------------------------------------------------------- +reset_db +do_execsql_test 30.0 { + CREATE TABLE t1(a, b); + CREATE VIEW v1 AS + SELECT ( VALUES(a), (b) ) FROM ( + SELECT a, b FROM t1 + ) + ; +} + +do_execsql_test 30.1 { + SELECT * FROM v1 +} + +do_execsql_test 30.1 { + ALTER TABLE t1 RENAME TO t2; +} +do_execsql_test 30.2 { + SELECT sql FROM sqlite_schema WHERE type='view' +} { + {CREATE VIEW v1 AS + SELECT ( VALUES(a), (b) ) FROM ( + SELECT a, b FROM "t2" + )} +} + finish_test From 932b5f457509f5141f75f5cce7a6050124d1cc8c Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 14 Mar 2024 20:39:03 +0000 Subject: [PATCH 13/34] Fix testcase to account for new behaviors with this branch. FossilOrigin-Name: 823e579362c05bb8accf6c3b158c5162a16eb23cf81d6021c9e3246e32583d1c --- manifest | 14 +++++++------- manifest.uuid | 2 +- test/sqllimits1.test | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index fb7853d8f0..e6296bc3ee 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sproblem\swith\sALTER\sTABLE\sand\scorrelated\smulti-row\sVALUES\sclauses. -D 2024-03-14T19:31:06.929 +C Fix\stestcase\sto\saccount\sfor\snew\sbehaviors\swith\sthis\sbranch. +D 2024-03-14T20:39:03.615 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -1648,7 +1648,7 @@ F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3 F test/spellfix3.test 0f9efaaa502a0e0a09848028518a6fb096c8ad33 F test/spellfix4.test 51c7c26514ade169855c66bcf130bd5acfb4d7fd090cc624645ab275ae6a41fb F test/sqldiff1.test 1b7ab4f312442c5cc6b3a5f299fa8ca051416d1dd173cb1126fd51bf64f2c3fb -F test/sqllimits1.test 5880a2f107185744ba4d93637f44c78d17706a9899a38b694d50f209735c81cc +F test/sqllimits1.test dee96a51b83ef866d06ec3c687d4c951d97b02549facc5be88c9dfcb215b98bf F test/sqllog.test 6af6cb0b09f4e44e1917e06ce85be7670302517a F test/startup.c 1beb5ca66fcc0fce95c3444db9d1674f90fc605499a574ae2434dcfc10d22805 F test/stat.test 123212a20ceb496893d5254a5f6c76442ce549fdc08d1702d8288a2bbaac8408 @@ -2179,8 +2179,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 e8a2a8198a97046ff376bc5d38e4bc0a24fcac79f5a0dadb9d29d953a862a012 -R 52836dd49dafb492a11e027744e0ffa5 -U dan -Z 97470bd397212d168f5c1df2d58f75c8 +P d543c829ef74dbd64105bd757ca660e4f02e9ce562be4f1688a701fa535351c4 +R 9a3605a04234115bfc68cd6fc0f2125f +U drh +Z eb4b6e81254ae60e2fa77bddac123f09 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 8c9e08af96..ad17c6052c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d543c829ef74dbd64105bd757ca660e4f02e9ce562be4f1688a701fa535351c4 \ No newline at end of file +823e579362c05bb8accf6c3b158c5162a16eb23cf81d6021c9e3246e32583d1c \ No newline at end of file diff --git a/test/sqllimits1.test b/test/sqllimits1.test index e9e20f40cc..14d39e6911 100644 --- a/test/sqllimits1.test +++ b/test/sqllimits1.test @@ -922,7 +922,7 @@ do_catchsql_test sqllimits1-18.1 { do_catchsql_test sqllimits1-18.2 { INSERT INTO b1 VALUES(1), (2), (3), (4), (5), (6), (7), (8), (9), (10) UNION VALUES(11); -} {1 {too many terms in compound SELECT}} +} {0 {}} #------------------------------------------------------------------------- # From 0ebd1c382cfbe4cd5fd09a9929add6b203d93d0a Mon Sep 17 00:00:00 2001 From: drh <> Date: Fri, 15 Mar 2024 13:16:13 +0000 Subject: [PATCH 14/34] Tweaks to the func4.test test module (which tests the rarely used totype.c extension) so that it works on i586 compiled using gcc-13 with -O0. Details at [forum:/forumpost/0a7553b0f734c033|forum post 0a7553b0f734c033]. FossilOrigin-Name: d0fbe779bc2460e120da4f39063a9f4121c700f0b86d85f4311715b1366c3515 --- manifest | 14 +++++++------- manifest.uuid | 2 +- test/func4.test | 35 +++++++++++++++++++++++++++++------ 3 files changed, 37 insertions(+), 14 deletions(-) diff --git a/manifest b/manifest index d9e3176a98..dcb0f53470 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C JS:\sremove\san\sunused\sfunction\sargument\sand\ssome\sdebug-related\scomments.\sNo\sfunctional\schanges. -D 2024-03-14T13:18:19.313 +C Tweaks\sto\sthe\sfunc4.test\stest\smodule\s(which\stests\sthe\srarely\sused\stotype.c\nextension)\sso\sthat\sit\sworks\son\si586\scompiled\susing\sgcc-13\swith\s-O0.\s\sDetails\nat\s[forum:/forumpost/0a7553b0f734c033|forum\spost\s0a7553b0f734c033]. +D 2024-03-15T13:16:13.460 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -1231,7 +1231,7 @@ F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d F test/func.test 504d202650c7940b5aa98364dd68f242df87f39f829e51074a55d79fc7bc7414 F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f F test/func3.test 600a632c305a88f3946d38f9a51efe145c989b2e13bd2b2a488db47fe76bab6a -F test/func4.test e8ef9b2bd6a192a213cbd5cf31a3b35e25cd6ff2fdaeea0b58d63be31b03d220 +F test/func4.test a3f9062487dbd826776f54f4e0e9517fe8c3cf689af92735308965774d51fac5 F test/func5.test 863e6d1bd0013d09c17236f8a13ea34008dd857d87d85a13a673960e4c25d82a F test/func6.test 9cc9b1f43b435af34fe1416eb1e318c8920448ea7a6962f2121972f5215cb9b0 F test/func7.test adbfc910385a6ffd15dc47be3c619ef070c542fcb7488964badb17b2d9a4d080 @@ -2177,8 +2177,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 9349d94e05dcf266b02afcd89f1e433cdc45f23e8536b2f3f9aa242d5d89c307 -R e2c267441183e97923991728d71c55b9 -U stephan -Z f0980170118e0dee3925f721da1aaab7 +P f15709430d4ba2fcf5729bc30a45dacb77102927b82cda12de0b67935b526cc0 +R 5b57f46c94d279354a994dbd1c18ea0b +U drh +Z ac2ce8f2de4e984fc417325734d61778 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 19a52c5ee0..e7275106fa 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f15709430d4ba2fcf5729bc30a45dacb77102927b82cda12de0b67935b526cc0 \ No newline at end of file +d0fbe779bc2460e120da4f39063a9f4121c700f0b86d85f4311715b1366c3515 \ No newline at end of file diff --git a/test/func4.test b/test/func4.test index 64c7a11edc..56cc9063a1 100644 --- a/test/func4.test +++ b/test/func4.test @@ -1,4 +1,4 @@ -# 2013 March 10 +# 2023-03-10 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: @@ -9,7 +9,10 @@ # #*********************************************************************** # This file implements regression tests for SQLite library. The focus of -# this file is testing the tointeger() and toreal() functions. +# this file is testing the tointeger() and toreal() functions that are +# part of the "totype.c" extension. This file does not test the core +# SQLite library. Failures of tests in this file are related to the +# ext/misc/totype.c extension. # # Several of the toreal() tests are disabled on platforms where floating # point precision is not high enough to represent their constant integer @@ -23,6 +26,20 @@ load_static_extension db totype set highPrecision(1) [expr \ {[db eval {SELECT tointeger(9223372036854775807 + 1);}] eq {{}}}] +set highPrecision(2) [expr \ + {[db eval {SELECT toreal(-9223372036854775808 + 1);}] eq {{}}}] + +# highPrecision(3) is only known to be false on i586 with gcc-13 and -O2. +# It is true on the exact same platform with -O0. Both results seem +# reasonable, so we'll just very the expectation accordingly. +# +set highPrecision(3) [expr \ + {[db eval {SELECT toreal(9007199254740992 + 1);}] eq {{}}}] + +if {!$highPrecision(1) || !$highPrecision(2) || !$highPrecision(3)} { + puts "NOTICE: use_long_double: [use_long_double] \ + highPrecision: $highPrecision(1) $highPrecision(2) $highPrecision(3)" +} do_execsql_test func4-1.1 { SELECT tointeger(NULL); @@ -195,8 +212,6 @@ do_execsql_test func4-1.55 { } {{}} ifcapable floatingpoint { - set highPrecision(2) [expr \ - {[db eval {SELECT toreal(-9223372036854775808 + 1);}] eq {{}}}] do_execsql_test func4-2.1 { SELECT toreal(NULL); @@ -341,10 +356,14 @@ ifcapable floatingpoint { do_execsql_test func4-2.45 { SELECT toreal(9007199254740992); } {9007199254740992.0} - if {$highPrecision(2)} { + if {$highPrecision(3)} { do_execsql_test func4-2.46 { SELECT toreal(9007199254740992 + 1); } {{}} + } else { + do_execsql_test func4-2.46 { + SELECT toreal(9007199254740992 + 1); + } {9007199254740992.0} } do_execsql_test func4-2.47 { SELECT toreal(9007199254740992 + 2); @@ -626,10 +645,14 @@ ifcapable floatingpoint { do_execsql_test func4-5.22 { SELECT tointeger(toreal(9007199254740992)); } {9007199254740992} - if {$highPrecision(2)} { + if {$highPrecision(3)} { do_execsql_test func4-5.23 { SELECT tointeger(toreal(9007199254740992 + 1)); } {{}} + } else { + do_execsql_test func4-5.23 { + SELECT tointeger(toreal(9007199254740992 + 1)); + } {9007199254740992} } do_execsql_test func4-5.24 { SELECT tointeger(toreal(9007199254740992 + 2)); From 825596481fad09348607da0b161216fa7d2ef4ae Mon Sep 17 00:00:00 2001 From: drh <> Date: Fri, 15 Mar 2024 17:04:55 +0000 Subject: [PATCH 15/34] Fix (totally harmless) memory leaks in Lemon to avoid warnings during ASAN builds. FossilOrigin-Name: ce009205a8edc02b7d45ac01bd0e692c3d2c3ffeadb68e4f1bad20c39075e692 --- manifest | 12 +-- manifest.uuid | 2 +- tool/lemon.c | 219 +++++++++++++++++++++++++++++++++----------------- 3 files changed, 153 insertions(+), 80 deletions(-) diff --git a/manifest b/manifest index dcb0f53470..f747e5569e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Tweaks\sto\sthe\sfunc4.test\stest\smodule\s(which\stests\sthe\srarely\sused\stotype.c\nextension)\sso\sthat\sit\sworks\son\si586\scompiled\susing\sgcc-13\swith\s-O0.\s\sDetails\nat\s[forum:/forumpost/0a7553b0f734c033|forum\spost\s0a7553b0f734c033]. -D 2024-03-15T13:16:13.460 +C Fix\s(totally\sharmless)\smemory\sleaks\sin\sLemon\sto\savoid\swarnings\sduring\sASAN\nbuilds. +D 2024-03-15T17:04:55.912 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -2088,7 +2088,7 @@ F tool/genfkey.test b6afd7b825d797a1e1274f519ab5695373552ecad5cd373530c63533638a F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce F tool/index_usage.c f62a0c701b2c7ff2f3e21d206f093c123f222dbf07136a10ffd1ca15a5c706c5 F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f -F tool/lemon.c 7f264d5d06450f929a20fa63a1b7e8f2df47dfaa6d7f80e4afef3639157497a4 +F tool/lemon.c 2eaee61479f9b97056950741c8f671a13281c819b94246698264a322360319a9 F tool/lempar.c e6b649778e5c027c8365ff01d7ef39297cd7285fa1f881cce31792689541e79f F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9 F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 @@ -2177,8 +2177,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 f15709430d4ba2fcf5729bc30a45dacb77102927b82cda12de0b67935b526cc0 -R 5b57f46c94d279354a994dbd1c18ea0b +P d0fbe779bc2460e120da4f39063a9f4121c700f0b86d85f4311715b1366c3515 +R 23ce63f7e666b66fe29613cc12e69c85 U drh -Z ac2ce8f2de4e984fc417325734d61778 +Z 6317df74aefa1b57098e3d6e2401e93c # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index e7275106fa..d62b446349 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d0fbe779bc2460e120da4f39063a9f4121c700f0b86d85f4311715b1366c3515 \ No newline at end of file +ce009205a8edc02b7d45ac01bd0e692c3d2c3ffeadb68e4f1bad20c39075e692 \ No newline at end of file diff --git a/tool/lemon.c b/tool/lemon.c index 0239b2d86f..06b9109a1d 100644 --- a/tool/lemon.c +++ b/tool/lemon.c @@ -59,6 +59,82 @@ static char *msort(char*,char**,int(*)(const char*,const char*)); */ #define lemonStrlen(X) ((int)strlen(X)) +/* +** Header on the linked list of memory allocations. +*/ +typedef struct MemChunk MemChunk; +struct MemChunk { + MemChunk *pNext; + size_t sz; + /* Actually memory follows */ +}; + +/* +** Global linked list of all memory allocations. +*/ +static MemChunk *memChunkList = 0; + +/* +** Wrappers around malloc(), calloc(), realloc() and free(). +** +** All memory allocations are kept on a doubly-linked list. The +** lemon_free_all() function can be called prior to exit to clean +** up any memory leaks. +** +** This is not necessary. But compilers and getting increasingly +** fussy about memory leaks, even in command-line programs like Lemon +** where they do not matter. So this code is provided to hush the +** warnings. +*/ +static void *lemon_malloc(size_t nByte){ + MemChunk *p; + if( nByte<0 ) return 0; + p = malloc( nByte + sizeof(MemChunk) ); + if( p==0 ){ + fprintf(stderr, "Out of memory. Failed to allocate %lld bytes.\n", + (long long int)nByte); + exit(1); + } + p->pNext = memChunkList; + p->sz = nByte; + memChunkList = p; + return (void*)&p[1]; +} +static void *lemon_calloc(size_t nElem, size_t sz){ + void *p = lemon_malloc(nElem*sz); + memset(p, 0, nElem*sz); + return p; +} +static void lemon_free(void *pOld){ + if( pOld ){ + MemChunk *p = (MemChunk*)pOld; + p--; + memset(pOld, 0, p->sz); + } +} +static void *lemon_realloc(void *pOld, size_t nNew){ + void *pNew; + MemChunk *p; + if( pOld==0 ) return lemon_malloc(nNew); + p = (MemChunk*)pOld; + p--; + if( p->sz>=nNew ) return pOld; + pNew = lemon_malloc( nNew ); + memcpy(pNew, pOld, p->sz); + return pNew; +} + +/* Free all outstanding memory allocations. +** Do this right before exiting. +*/ +static void lemon_free_all(void){ + while( memChunkList ){ + MemChunk *pNext = memChunkList->pNext; + free( memChunkList ); + memChunkList = pNext; + } +} + /* ** Compilers are starting to complain about the use of sprintf() and strcpy(), ** saying they are unsafe. So we define our own versions of those routines too. @@ -497,7 +573,7 @@ static struct action *Action_new(void){ if( actionfreelist==0 ){ int i; int amt = 100; - actionfreelist = (struct action *)calloc(amt, sizeof(struct action)); + actionfreelist = (struct action *)lemon_calloc(amt, sizeof(struct action)); if( actionfreelist==0 ){ fprintf(stderr,"Unable to allocate memory for a new parser action."); exit(1); @@ -616,14 +692,14 @@ struct acttab { /* Free all memory associated with the given acttab */ void acttab_free(acttab *p){ - free( p->aAction ); - free( p->aLookahead ); - free( p ); + lemon_free( p->aAction ); + lemon_free( p->aLookahead ); + lemon_free( p ); } /* Allocate a new acttab structure */ acttab *acttab_alloc(int nsymbol, int nterminal){ - acttab *p = (acttab *) calloc( 1, sizeof(*p) ); + acttab *p = (acttab *) lemon_calloc( 1, sizeof(*p) ); if( p==0 ){ fprintf(stderr,"Unable to allocate memory for a new acttab."); exit(1); @@ -642,7 +718,7 @@ acttab *acttab_alloc(int nsymbol, int nterminal){ void acttab_action(acttab *p, int lookahead, int action){ if( p->nLookahead>=p->nLookaheadAlloc ){ p->nLookaheadAlloc += 25; - p->aLookahead = (struct lookahead_action *) realloc( p->aLookahead, + p->aLookahead = (struct lookahead_action *) lemon_realloc( p->aLookahead, sizeof(p->aLookahead[0])*p->nLookaheadAlloc ); if( p->aLookahead==0 ){ fprintf(stderr,"malloc failed\n"); @@ -692,7 +768,7 @@ int acttab_insert(acttab *p, int makeItSafe){ if( p->nAction + n >= p->nActionAlloc ){ int oldAlloc = p->nActionAlloc; p->nActionAlloc = p->nAction + n + p->nActionAlloc + 20; - p->aAction = (struct lookahead_action *) realloc( p->aAction, + p->aAction = (struct lookahead_action *) lemon_realloc( p->aAction, sizeof(p->aAction[0])*p->nActionAlloc); if( p->aAction==0 ){ fprintf(stderr,"malloc failed\n"); @@ -1314,7 +1390,7 @@ static struct config **basisend = 0; /* End of list of basis configs */ /* Return a pointer to a new configuration */ PRIVATE struct config *newconfig(void){ - return (struct config*)calloc(1, sizeof(struct config)); + return (struct config*)lemon_calloc(1, sizeof(struct config)); } /* The configuration "old" is no longer used */ @@ -1530,19 +1606,19 @@ static char *bDefineUsed = 0; /* True for every -D macro actually used */ static void handle_D_option(char *z){ char **paz; nDefine++; - azDefine = (char **) realloc(azDefine, sizeof(azDefine[0])*nDefine); + azDefine = (char **) lemon_realloc(azDefine, sizeof(azDefine[0])*nDefine); if( azDefine==0 ){ fprintf(stderr,"out of memory\n"); exit(1); } - bDefineUsed = (char*)realloc(bDefineUsed, nDefine); + bDefineUsed = (char*)lemon_realloc(bDefineUsed, nDefine); if( bDefineUsed==0 ){ fprintf(stderr,"out of memory\n"); exit(1); } bDefineUsed[nDefine-1] = 0; paz = &azDefine[nDefine-1]; - *paz = (char *) malloc( lemonStrlen(z)+1 ); + *paz = (char *) lemon_malloc( lemonStrlen(z)+1 ); if( *paz==0 ){ fprintf(stderr,"out of memory\n"); exit(1); @@ -1556,7 +1632,7 @@ static void handle_D_option(char *z){ */ static char *outputDir = NULL; static void handle_d_option(char *z){ - outputDir = (char *) malloc( lemonStrlen(z)+1 ); + outputDir = (char *) lemon_malloc( lemonStrlen(z)+1 ); if( outputDir==0 ){ fprintf(stderr,"out of memory\n"); exit(1); @@ -1566,7 +1642,7 @@ static void handle_d_option(char *z){ static char *user_templatename = NULL; static void handle_T_option(char *z){ - user_templatename = (char *) malloc( lemonStrlen(z)+1 ); + user_templatename = (char *) lemon_malloc( lemonStrlen(z)+1 ); if( user_templatename==0 ){ memory_error(); } @@ -1803,6 +1879,7 @@ int main(int argc, char **argv){ /* return 0 on success, 1 on failure. */ exitcode = ((lem.errorcnt > 0) || (lem.nconflict > 0)) ? 1 : 0; + lemon_free_all(); exit(exitcode); return (exitcode); } @@ -2391,7 +2468,7 @@ static void parseonetoken(struct pstate *psp) case IN_RHS: if( x[0]=='.' ){ struct rule *rp; - rp = (struct rule *)calloc( sizeof(struct rule) + + rp = (struct rule *)lemon_calloc( sizeof(struct rule) + sizeof(struct symbol*)*psp->nrhs + sizeof(char*)*psp->nrhs, 1); if( rp==0 ){ ErrorMsg(psp->filename,psp->tokenlineno, @@ -2443,17 +2520,17 @@ static void parseonetoken(struct pstate *psp) struct symbol *msp = psp->rhs[psp->nrhs-1]; if( msp->type!=MULTITERMINAL ){ struct symbol *origsp = msp; - msp = (struct symbol *) calloc(1,sizeof(*msp)); + msp = (struct symbol *) lemon_calloc(1,sizeof(*msp)); memset(msp, 0, sizeof(*msp)); msp->type = MULTITERMINAL; msp->nsubsym = 1; - msp->subsym = (struct symbol **) calloc(1,sizeof(struct symbol*)); + msp->subsym = (struct symbol**)lemon_calloc(1,sizeof(struct symbol*)); msp->subsym[0] = origsp; msp->name = origsp->name; psp->rhs[psp->nrhs-1] = msp; } msp->nsubsym++; - msp->subsym = (struct symbol **) realloc(msp->subsym, + msp->subsym = (struct symbol **) lemon_realloc(msp->subsym, sizeof(struct symbol*)*msp->nsubsym); msp->subsym[msp->nsubsym-1] = Symbol_new(&x[1]); if( ISLOWER(x[1]) || ISLOWER(msp->subsym[0]->name[0]) ){ @@ -2669,7 +2746,7 @@ static void parseonetoken(struct pstate *psp) nLine = lemonStrlen(zLine); n += nLine + lemonStrlen(psp->filename) + nBack; } - *psp->declargslot = (char *) realloc(*psp->declargslot, n); + *psp->declargslot = (char *) lemon_realloc(*psp->declargslot, n); zBuf = *psp->declargslot + nOld; if( addLineMacro ){ if( nOld && zBuf[-1]!='\n' ){ @@ -2783,7 +2860,7 @@ static void parseonetoken(struct pstate *psp) }else if( ISUPPER(x[0]) || ((x[0]=='|' || x[0]=='/') && ISUPPER(x[1])) ){ struct symbol *msp = psp->tkclass; msp->nsubsym++; - msp->subsym = (struct symbol **) realloc(msp->subsym, + msp->subsym = (struct symbol **) lemon_realloc(msp->subsym, sizeof(struct symbol*)*msp->nsubsym); if( !ISUPPER(x[0]) ) x++; msp->subsym[msp->nsubsym-1] = Symbol_new(x); @@ -2998,10 +3075,10 @@ void Parse(struct lemon *gp) fseek(fp,0,2); filesize = ftell(fp); rewind(fp); - filebuf = (char *)malloc( filesize+1 ); + filebuf = (char *)lemon_malloc( filesize+1 ); if( filesize>100000000 || filebuf==0 ){ ErrorMsg(ps.filename,0,"Input file too large."); - free(filebuf); + lemon_free(filebuf); gp->errorcnt++; fclose(fp); return; @@ -3009,7 +3086,7 @@ void Parse(struct lemon *gp) if( fread(filebuf,1,filesize,fp)!=filesize ){ ErrorMsg(ps.filename,0,"Can't read in all %d bytes of this file.", filesize); - free(filebuf); + lemon_free(filebuf); gp->errorcnt++; fclose(fp); return; @@ -3121,7 +3198,7 @@ void Parse(struct lemon *gp) *cp = (char)c; /* Restore the buffer */ cp = nextcp; } - free(filebuf); /* Release the buffer after parsing */ + lemon_free(filebuf); /* Release the buffer after parsing */ gp->rule = ps.firstrule; gp->errorcnt = ps.errorcnt; } @@ -3139,7 +3216,7 @@ struct plink *Plink_new(void){ if( plink_freelist==0 ){ int i; int amt = 100; - plink_freelist = (struct plink *)calloc( amt, sizeof(struct plink) ); + plink_freelist = (struct plink *)lemon_calloc( amt, sizeof(struct plink) ); if( plink_freelist==0 ){ fprintf(stderr, "Unable to allocate memory for a new follow-set propagation link.\n"); @@ -3192,9 +3269,7 @@ void Plink_delete(struct plink *plp) ** Procedures for generating reports and tables in the LEMON parser generator. */ -/* Generate a filename with the given suffix. Space to hold the -** name comes from malloc() and must be freed by the calling -** function. +/* Generate a filename with the given suffix. */ PRIVATE char *file_makename(struct lemon *lemp, const char *suffix) { @@ -3211,7 +3286,7 @@ PRIVATE char *file_makename(struct lemon *lemp, const char *suffix) sz += lemonStrlen(suffix); if( outputDir ) sz += lemonStrlen(outputDir) + 1; sz += 5; - name = (char*)malloc( sz ); + name = (char*)lemon_malloc( sz ); if( name==0 ){ fprintf(stderr,"Can't allocate space for a filename.\n"); exit(1); @@ -3238,7 +3313,7 @@ PRIVATE FILE *file_open( ){ FILE *fp; - if( lemp->outname ) free(lemp->outname); + if( lemp->outname ) lemon_free(lemp->outname); lemp->outname = file_makename(lemp, suffix); fp = fopen(lemp->outname,mode); if( fp==0 && *mode=='w' ){ @@ -3554,14 +3629,14 @@ PRIVATE char *pathsearch(char *argv0, char *name, int modemask) if( cp ){ c = *cp; *cp = 0; - path = (char *)malloc( lemonStrlen(argv0) + lemonStrlen(name) + 2 ); + path = (char *)lemon_malloc( lemonStrlen(argv0) + lemonStrlen(name) + 2 ); if( path ) lemon_sprintf(path,"%s/%s",argv0,name); *cp = c; }else{ pathlist = getenv("PATH"); if( pathlist==0 ) pathlist = ".:/bin:/usr/bin"; - pathbuf = (char *) malloc( lemonStrlen(pathlist) + 1 ); - path = (char *)malloc( lemonStrlen(pathlist)+lemonStrlen(name)+2 ); + pathbuf = (char *) lemon_malloc( lemonStrlen(pathlist) + 1 ); + path = (char *)lemon_malloc( lemonStrlen(pathlist)+lemonStrlen(name)+2 ); if( (pathbuf != 0) && (path!=0) ){ pathbufptr = pathbuf; lemon_strcpy(pathbuf, pathlist); @@ -3577,7 +3652,7 @@ PRIVATE char *pathsearch(char *argv0, char *name, int modemask) if( access(path,modemask)==0 ) break; } } - free(pathbufptr); + lemon_free(pathbufptr); } return path; } @@ -3708,7 +3783,7 @@ PRIVATE FILE *tplt_open(struct lemon *lemp) fprintf(stderr,"Can't open the template file \"%s\".\n",tpltname); lemp->errorcnt++; } - free(toFree); + lemon_free(toFree); return in; } @@ -3837,7 +3912,7 @@ PRIVATE char *append_str(const char *zText, int n, int p1, int p2){ } if( (int) (n+sizeof(zInt)*2+used) >= alloced ){ alloced = n + sizeof(zInt)*2 + used + 200; - z = (char *) realloc(z, alloced); + z = (char *) lemon_realloc(z, alloced); } if( z==0 ) return empty; while( n-- > 0 ){ @@ -4127,7 +4202,7 @@ void print_stack_union( /* Allocate and initialize types[] and allocate stddt[] */ arraysize = lemp->nsymbol * 2; - types = (char**)calloc( arraysize, sizeof(char*) ); + types = (char**)lemon_calloc( arraysize, sizeof(char*) ); if( types==0 ){ fprintf(stderr,"Out of memory.\n"); exit(1); @@ -4144,7 +4219,7 @@ void print_stack_union( len = lemonStrlen(sp->datatype); if( len>maxdtlength ) maxdtlength = len; } - stddt = (char*)malloc( maxdtlength*2 + 1 ); + stddt = (char*)lemon_malloc( maxdtlength*2 + 1 ); if( stddt==0 ){ fprintf(stderr,"Out of memory.\n"); exit(1); @@ -4193,7 +4268,7 @@ void print_stack_union( } if( types[hash]==0 ){ sp->dtnum = hash + 1; - types[hash] = (char*)malloc( lemonStrlen(stddt)+1 ); + types[hash] = (char*)lemon_malloc( lemonStrlen(stddt)+1 ); if( types[hash]==0 ){ fprintf(stderr,"Out of memory.\n"); exit(1); @@ -4215,13 +4290,13 @@ void print_stack_union( for(i=0; ierrsym && lemp->errsym->useCnt ){ fprintf(out," int yy%d;\n",lemp->errsym->dtnum); lineno++; } - free(stddt); - free(types); + lemon_free(stddt); + lemon_free(types); fprintf(out,"} YYMINORTYPE;\n"); lineno++; *plineno = lineno; } @@ -4450,7 +4525,7 @@ void ReportTable( if( mhflag ){ char *incName = file_makename(lemp, ".h"); fprintf(out,"#include \"%s\"\n", incName); lineno++; - free(incName); + lemon_free(incName); } tplt_xfer(lemp->name,in,out,&lineno); @@ -4557,7 +4632,7 @@ void ReportTable( ** table must be computed before generating the YYNSTATE macro because ** we need to know how many states can be eliminated. */ - ax = (struct axset *) calloc(lemp->nxstate*2, sizeof(ax[0])); + ax = (struct axset *) lemon_calloc(lemp->nxstate*2, sizeof(ax[0])); if( ax==0 ){ fprintf(stderr,"malloc failed\n"); exit(1); @@ -4615,7 +4690,7 @@ void ReportTable( } #endif } - free(ax); + lemon_free(ax); /* Mark rules that are actually used for reduce actions after all ** optimizations have been applied @@ -5241,7 +5316,7 @@ void SetSize(int n) /* Allocate a new set */ char *SetNew(void){ char *s; - s = (char*)calloc( size, 1); + s = (char*)lemon_calloc( size, 1); if( s==0 ){ memory_error(); } @@ -5251,7 +5326,7 @@ char *SetNew(void){ /* Deallocate a set */ void SetFree(char *s) { - free(s); + lemon_free(s); } /* Add a new element to the set. Return TRUE if the element was added @@ -5310,7 +5385,7 @@ const char *Strsafe(const char *y) if( y==0 ) return 0; z = Strsafe_find(y); - if( z==0 && (cpy=(char *)malloc( lemonStrlen(y)+1 ))!=0 ){ + if( z==0 && (cpy=(char *)lemon_malloc( lemonStrlen(y)+1 ))!=0 ){ lemon_strcpy(cpy,y); z = cpy; Strsafe_insert(z); @@ -5346,13 +5421,13 @@ static struct s_x1 *x1a; /* Allocate a new associative array */ void Strsafe_init(void){ if( x1a ) return; - x1a = (struct s_x1*)malloc( sizeof(struct s_x1) ); + x1a = (struct s_x1*)lemon_malloc( sizeof(struct s_x1) ); if( x1a ){ x1a->size = 1024; x1a->count = 0; - x1a->tbl = (x1node*)calloc(1024, sizeof(x1node) + sizeof(x1node*)); + x1a->tbl = (x1node*)lemon_calloc(1024, sizeof(x1node) + sizeof(x1node*)); if( x1a->tbl==0 ){ - free(x1a); + lemon_free(x1a); x1a = 0; }else{ int i; @@ -5387,7 +5462,7 @@ int Strsafe_insert(const char *data) struct s_x1 array; array.size = arrSize = x1a->size*2; array.count = x1a->count; - array.tbl = (x1node*)calloc(arrSize, sizeof(x1node) + sizeof(x1node*)); + array.tbl = (x1node*)lemon_calloc(arrSize, sizeof(x1node)+sizeof(x1node*)); if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ array.ht = (x1node**)&(array.tbl[arrSize]); for(i=0; ifrom = &(array.ht[h]); array.ht[h] = newnp; } - /* free(x1a->tbl); // This program was originally for 16-bit machines. + /* lemon_free(x1a->tbl); // This program was originally for 16-bit machines. ** Don't worry about freeing memory on modern platforms. */ *x1a = array; } @@ -5443,7 +5518,7 @@ struct symbol *Symbol_new(const char *x) sp = Symbol_find(x); if( sp==0 ){ - sp = (struct symbol *)calloc(1, sizeof(struct symbol) ); + sp = (struct symbol *)lemon_calloc(1, sizeof(struct symbol) ); MemoryCheck(sp); sp->name = Strsafe(x); sp->type = ISUPPER(*x) ? TERMINAL : NONTERMINAL; @@ -5514,13 +5589,13 @@ static struct s_x2 *x2a; /* Allocate a new associative array */ void Symbol_init(void){ if( x2a ) return; - x2a = (struct s_x2*)malloc( sizeof(struct s_x2) ); + x2a = (struct s_x2*)lemon_malloc( sizeof(struct s_x2) ); if( x2a ){ x2a->size = 128; x2a->count = 0; - x2a->tbl = (x2node*)calloc(128, sizeof(x2node) + sizeof(x2node*)); + x2a->tbl = (x2node*)lemon_calloc(128, sizeof(x2node) + sizeof(x2node*)); if( x2a->tbl==0 ){ - free(x2a); + lemon_free(x2a); x2a = 0; }else{ int i; @@ -5555,7 +5630,7 @@ int Symbol_insert(struct symbol *data, const char *key) struct s_x2 array; array.size = arrSize = x2a->size*2; array.count = x2a->count; - array.tbl = (x2node*)calloc(arrSize, sizeof(x2node) + sizeof(x2node*)); + array.tbl = (x2node*)lemon_calloc(arrSize, sizeof(x2node)+sizeof(x2node*)); if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ array.ht = (x2node**)&(array.tbl[arrSize]); for(i=0; ifrom = &(array.ht[h]); array.ht[h] = newnp; } - /* free(x2a->tbl); // This program was originally written for 16-bit + /* lemon_free(x2a->tbl); // This program was originally written for 16-bit ** machines. Don't worry about freeing this trivial amount of memory ** on modern platforms. Just leak it. */ *x2a = array; @@ -5632,7 +5707,7 @@ struct symbol **Symbol_arrayof() int i,arrSize; if( x2a==0 ) return 0; arrSize = x2a->count; - array = (struct symbol **)calloc(arrSize, sizeof(struct symbol *)); + array = (struct symbol **)lemon_calloc(arrSize, sizeof(struct symbol *)); if( array ){ for(i=0; itbl[i].data; } @@ -5680,7 +5755,7 @@ PRIVATE unsigned statehash(struct config *a) struct state *State_new() { struct state *newstate; - newstate = (struct state *)calloc(1, sizeof(struct state) ); + newstate = (struct state *)lemon_calloc(1, sizeof(struct state) ); MemoryCheck(newstate); return newstate; } @@ -5713,13 +5788,13 @@ static struct s_x3 *x3a; /* Allocate a new associative array */ void State_init(void){ if( x3a ) return; - x3a = (struct s_x3*)malloc( sizeof(struct s_x3) ); + x3a = (struct s_x3*)lemon_malloc( sizeof(struct s_x3) ); if( x3a ){ x3a->size = 128; x3a->count = 0; - x3a->tbl = (x3node*)calloc(128, sizeof(x3node) + sizeof(x3node*)); + x3a->tbl = (x3node*)lemon_calloc(128, sizeof(x3node) + sizeof(x3node*)); if( x3a->tbl==0 ){ - free(x3a); + lemon_free(x3a); x3a = 0; }else{ int i; @@ -5754,7 +5829,7 @@ int State_insert(struct state *data, struct config *key) struct s_x3 array; array.size = arrSize = x3a->size*2; array.count = x3a->count; - array.tbl = (x3node*)calloc(arrSize, sizeof(x3node) + sizeof(x3node*)); + array.tbl = (x3node*)lemon_calloc(arrSize, sizeof(x3node)+sizeof(x3node*)); if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ array.ht = (x3node**)&(array.tbl[arrSize]); for(i=0; ifrom = &(array.ht[h]); array.ht[h] = newnp; } - free(x3a->tbl); + lemon_free(x3a->tbl); *x3a = array; } /* Insert the new data */ @@ -5811,7 +5886,7 @@ struct state **State_arrayof(void) int i,arrSize; if( x3a==0 ) return 0; arrSize = x3a->count; - array = (struct state **)calloc(arrSize, sizeof(struct state *)); + array = (struct state **)lemon_calloc(arrSize, sizeof(struct state *)); if( array ){ for(i=0; itbl[i].data; } @@ -5853,13 +5928,13 @@ static struct s_x4 *x4a; /* Allocate a new associative array */ void Configtable_init(void){ if( x4a ) return; - x4a = (struct s_x4*)malloc( sizeof(struct s_x4) ); + x4a = (struct s_x4*)lemon_malloc( sizeof(struct s_x4) ); if( x4a ){ x4a->size = 64; x4a->count = 0; - x4a->tbl = (x4node*)calloc(64, sizeof(x4node) + sizeof(x4node*)); + x4a->tbl = (x4node*)lemon_calloc(64, sizeof(x4node) + sizeof(x4node*)); if( x4a->tbl==0 ){ - free(x4a); + lemon_free(x4a); x4a = 0; }else{ int i; @@ -5894,7 +5969,8 @@ int Configtable_insert(struct config *data) struct s_x4 array; array.size = arrSize = x4a->size*2; array.count = x4a->count; - array.tbl = (x4node*)calloc(arrSize, sizeof(x4node) + sizeof(x4node*)); + array.tbl = (x4node*)lemon_calloc(arrSize, + sizeof(x4node) + sizeof(x4node*)); if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ array.ht = (x4node**)&(array.tbl[arrSize]); for(i=0; ifrom = &(array.ht[h]); array.ht[h] = newnp; } - /* free(x4a->tbl); // This code was originall written for 16-bit machines. - ** on modern machines, don't worry about freeing this trival amount of - ** memory. */ *x4a = array; } /* Insert the new data */ From d31fc6e9cfd4d25d2fdea2f5aa41fee0a1d5e80c Mon Sep 17 00:00:00 2001 From: drh <> Date: Fri, 15 Mar 2024 17:57:58 +0000 Subject: [PATCH 16/34] New options for testrunner.tcl: --stop-on-error and --stop-on-coredump. FossilOrigin-Name: 82035b9cfd28ef6b0ecc6f469f03d2b001189aa4925147cdb784b6b1964eb3b2 --- manifest | 12 ++++++------ manifest.uuid | 2 +- test/testrunner.tcl | 16 ++++++++++++++++ 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index f747e5569e..345be73124 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\s(totally\sharmless)\smemory\sleaks\sin\sLemon\sto\savoid\swarnings\sduring\sASAN\nbuilds. -D 2024-03-15T17:04:55.912 +C New\soptions\sfor\stestrunner.tcl:\s\s--stop-on-error\sand\s--stop-on-coredump. +D 2024-03-15T17:57:58.502 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -1687,7 +1687,7 @@ F test/temptable2.test 76821347810ecc88203e6ef0dd6897b6036ac788e9dd3e6b04fd4d163 F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637 F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc F test/tester.tcl fe617b88c7eb08bdf983d2aaa31c20fbf439eee7b8e0d61ca636fcd0c305bbbf -F test/testrunner.tcl 9f198e41c0d8899d547a5beb4af0c0d512021d18da136918dd96be6a242dbab5 +F test/testrunner.tcl 01bc3b5bc900dc73b076180727eb2869dc61426b1ab95ac2f42def5d1f3d407e F test/testrunner_data.tcl 2f94974e5e3a56af880be72f7a7fd239aa9d4ecf978625435fcc698319c927fa F test/thread001.test a0985c117eab62c0c65526e9fa5d1360dd1cac5b03bde223902763274ce21899 F test/thread002.test c24c83408e35ba5a952a3638b7ac03ccdf1ce4409289c54a050ac4c5f1de7502 @@ -2177,8 +2177,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 d0fbe779bc2460e120da4f39063a9f4121c700f0b86d85f4311715b1366c3515 -R 23ce63f7e666b66fe29613cc12e69c85 +P ce009205a8edc02b7d45ac01bd0e692c3d2c3ffeadb68e4f1bad20c39075e692 +R 6f65d3d8f9136f71ba32b06be27a8871 U drh -Z 6317df74aefa1b57098e3d6e2401e93c +Z 3ec0c84d38eb2a8a3a9b0c26445e8068 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index d62b446349..39c5e3d4e3 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ce009205a8edc02b7d45ac01bd0e692c3d2c3ffeadb68e4f1bad20c39075e692 \ No newline at end of file +82035b9cfd28ef6b0ecc6f469f03d2b001189aa4925147cdb784b6b1964eb3b2 \ No newline at end of file diff --git a/test/testrunner.tcl b/test/testrunner.tcl index e8d0f76864..e8570ddf19 100644 --- a/test/testrunner.tcl +++ b/test/testrunner.tcl @@ -64,6 +64,8 @@ Usage: --dryrun --explain --jobs NUMBER-OF-JOBS + --stop-on-coredump + --stop-on-error --zipvfs ZIPVFS-SOURCE-DIR Special values for PERMUTATION that work with plain tclsh: @@ -172,6 +174,8 @@ set TRG(zipvfs) "" ;# -zipvfs option, if any set TRG(buildonly) 0 ;# True if --buildonly option set TRG(dryrun) 0 ;# True if --dryrun option set TRG(explain) 0 ;# True for the --explain option +set TRG(stopOnError) 0 ;# Stop running at first failure +set TRG(stopOnCore) 0 ;# Stop on a core-dump switch -nocase -glob -- $tcl_platform(os) { *darwin* { @@ -468,6 +472,10 @@ for {set ii 0} {$ii < [llength $argv]} {incr ii} { set TRG(dryrun) 1 } elseif {($n>2 && [string match "$a*" --explain]) || $a=="-e"} { set TRG(explain) 1 + } elseif {[string match "$a*" --stop-on-error]} { + set TRG(stopOnError) 1 + } elseif {[string match "$a*" --stop-on-coredump]} { + set TRG(stopOnCore) 1 } else { usage } @@ -992,6 +1000,14 @@ proc script_input_ready {fd iJob jobid} { } puts "FAILED: $job(displayname) ($iJob)" set state "failed" + if {$TRG(stopOnError)} { + puts "OUTPUT: $O($iJob)" + exit 1 + } + if {$TRG(stopOnCore) && [string first {core dumped} $O($iJob)]>0} { + puts "OUTPUT: $O($iJob)" + exit 1 + } } set tm [clock_milliseconds] From f696591dd45bea11c24d9f219e6f17161a329934 Mon Sep 17 00:00:00 2001 From: drh <> Date: Sat, 16 Mar 2024 13:18:48 +0000 Subject: [PATCH 17/34] Enhance the sqlite3ExprIsConstant() function so that it recognizes constant functions. So far the enhancement only applies to the multi-row VALUES clause, but it could possibly be applied in many other places. FossilOrigin-Name: c9e0488c6c0135932b6e76b0f3f3acd69ef65327e0a54daa59777f35da1aef26 --- manifest | 29 ++++++++++--------- manifest.uuid | 2 +- src/expr.c | 74 +++++++++++++++++++++++++++++++++++++++++++++---- src/insert.c | 19 +++++++------ src/parse.y | 2 +- src/select.c | 6 ++-- src/sqliteInt.h | 2 +- src/where.c | 10 +++---- src/whereexpr.c | 2 +- src/window.c | 2 +- 10 files changed, 108 insertions(+), 40 deletions(-) diff --git a/manifest b/manifest index e6296bc3ee..5926610ec1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\stestcase\sto\saccount\sfor\snew\sbehaviors\swith\sthis\sbranch. -D 2024-03-14T20:39:03.615 +C Enhance\sthe\ssqlite3ExprIsConstant()\sfunction\sso\sthat\sit\srecognizes\nconstant\sfunctions.\s\sSo\sfar\sthe\senhancement\sonly\sapplies\sto\sthe\smulti-row\nVALUES\sclause,\sbut\sit\scould\spossibly\sbe\sapplied\sin\smany\sother\splaces. +D 2024-03-16T13:18:48.351 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -700,7 +700,7 @@ F src/date.c 126ba2ab10aeb2e7ba6e089b5f07b747c0625b8287f78b60da346eda8d23c875 F src/dbpage.c 80e46e1df623ec40486da7a5086cb723b0275a6e2a7b01d9f9b5da0f04ba2782 F src/dbstat.c 3b677254d512fcafd4d0b341bf267b38b235ccfddbef24f9154e19360fa22e43 F src/delete.c cb766727c78e715f9fb7ec8a7d03658ed2a3016343ca687acfcec9083cdca500 -F src/expr.c 7d0280860f8683fa1e81202304a5107f493fe9bd52be6590d0d0d6c3564c7a07 +F src/expr.c 023e84202023d58bc10cb1f7a4dcc7fe1342e11daa054ea1024e8b78144bd589 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c a47610f0a5c6cb0ad79f8fcef039c01833dec0c751bb695f28dc0ec6a4c3ba00 F src/func.c 4204c56196847faefef57fa14e43b8e4d65eb8d7e65318abe463472e3fd148cb @@ -709,7 +709,7 @@ F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220 F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51 F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 -F src/insert.c b03721dfe0679445c635c33f137fde594e73abdd5bc042ca3c15990b339151d0 +F src/insert.c e28426630ebbac5763d5802099164ad24fbf46fea79d48a8313117a64b950871 F src/json.c e2e40760d6689134c3e2ece38c6a496b34ff5e2661a8f238444a119af666fdce F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36 @@ -739,7 +739,7 @@ F src/os_win.c 6ff43bac175bd9ed79e7c0f96840b139f2f51d01689a638fd05128becf94908a F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/pager.c ff60e98138d2499082ac6230f01ac508aba545315debccfca2fd6042f5f10fcd F src/pager.h 4b1140d691860de0be1347474c51fee07d5420bd7f802d38cbab8ea4ab9f538a -F src/parse.y 2ff84e5e346974100b7ed37f01abfd148012e1ce65a6b5a72d5025258077121e +F src/parse.y 004faaa6b6d6a88d9ec5e535281d7a203e1a03e83617ef8249f40e18bda23dc4 F src/pcache.c 040b165f30622a21b7a9a77c6f2e4877a32fb7f22d4c7f0d2a6fa6833a156a75 F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5 F src/pcache1.c 602acb23c471bb8d557a6f0083cc2be641d6cafcafa19e481eba7ef4c9ca0f00 @@ -750,12 +750,12 @@ F src/printf.c 10e8bad30042f8bd6114a013b4afc229ec8ad255ab27518d7d9f52e8cbc5cd0a F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c F src/resolve.c ef87e3bc7700bfe761a7bbee2ce6084f1766dc816dd82a3ae77c133eec898432 F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97 -F src/select.c 2a12c6ed8131db7c49b6f8141c3420cab825cfc6bd222d347fa1382f36b174b7 +F src/select.c 4a3abb346d184a5b1f4f10f10da22465ff18db170099c2d2e0b0cb6ea5f2720e F src/shell.c.in cf80c636bccb0ff9db46995e39d69ca21fde2a8a331d1691e4d62a69d7841c8a F src/sqlite.h.in 19a2db3995a699bd7f6dfb423856242bfceb7ec849a93c91d241d19fc28d9f0f F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54 -F src/sqliteInt.h b3ac44ca090011813d5a07f63be59785a4558e74052eb94b686f52eef1af684b +F src/sqliteInt.h 92d3323ba58a1a745f0f6a300d619ea12a6b142f0e8d8d49ce24d84ed85092f1 F src/sqliteLimit.h 6878ab64bdeb8c24a1d762d45635e34b96da21132179023338c93f820eee6728 F src/status.c cb11f8589a6912af2da3bb1ec509a94dd8ef27df4d4c1a97e0bcf2309ece972b F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 @@ -835,11 +835,11 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c 887fc4ca3f020ebb2e376f222069570834ac63bf50111ef0cbf3ae417048ed89 F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452 F src/walker.c 7c7ea0115345851c3da4e04e2e239a29983b61fb5b038b94eede6aba462640e2 -F src/where.c 8bb70b3caadcf35073f8857ecd83d33d97bf6aa03de3342287037bae43c6f364 +F src/where.c 3efa165f9205602eef711af071db3862531fcda2b1ad875cda5e2c5effa56fee F src/whereInt.h 82a13766f13d1a53b05387c2e60726289ef26404bc7b9b1f7770204d97357fb8 F src/wherecode.c 5d77db30a2a3dd532492ae882de114edba2fae672622056b1c7fd61f5917a8f1 -F src/whereexpr.c 6ebd90b553f4bb5c7df5a4b2f39b6a7c81a67484353827cdd2048f2514ec6f30 -F src/window.c 5b1387d59df30d481ed14cceef5f4d1dab1f8752aa106ba72c8b62777bd139d2 +F src/whereexpr.c 7b64295f1d82ad0928df435925dd7bbd5997b44a026153113eace0d9e71ff435 +F src/window.c 5d95122dd330bfaebd732358c8ef067c5a9394a53ac249470d611d0ce2c52be2 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627 F test/affinity3.test f094773025eddf31135c7ad4cde722b7696f8eb07b97511f98585addf2a510a9 @@ -2179,8 +2179,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 d543c829ef74dbd64105bd757ca660e4f02e9ce562be4f1688a701fa535351c4 -R 9a3605a04234115bfc68cd6fc0f2125f +P 823e579362c05bb8accf6c3b158c5162a16eb23cf81d6021c9e3246e32583d1c +R 2ac63c110cf6a72c96a474d2b73e892b +T *branch * enhanced-expr-is-const +T *sym-enhanced-expr-is-const * +T -sym-exp-values-clause2 * U drh -Z eb4b6e81254ae60e2fa77bddac123f09 +Z 0a7dc94654580f17d6264250f37030ea # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index ad17c6052c..38b8366e49 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -823e579362c05bb8accf6c3b158c5162a16eb23cf81d6021c9e3246e32583d1c \ No newline at end of file +c9e0488c6c0135932b6e76b0f3f3acd69ef65327e0a54daa59777f35da1aef26 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index e4bfa995d7..6050058e43 100644 --- a/src/expr.c +++ b/src/expr.c @@ -2346,6 +2346,52 @@ Expr *sqlite3ExprSimplifiedAndOr(Expr *pExpr){ return pExpr; } +/* +** pExpr is a TK_FUNCTION node. Try to determine whether or not the +** function is a constant function. A function is constant if all of +** the following are true: +** +** (1) It is a scalar function (not an aggregate or window function) +** (2) It has either the SQLITE_FUNC_CONSTANT or SQLITE_FUNC_SLOCHNG +** property. +** (3) All of its arguments are constants +** +** This routine sets pWalker->eCode to 0 if pExpr is not a constant. +** It makes no changes to pWalker->eCode if pExpr is constant. In +** every case, it returns WRC_Abort. +** +** Called as a service subroutine from exprNodeIsConstant(). +*/ +static SQLITE_NOINLINE int exprNodeIsConstantFunction( + Walker *pWalker, + Expr *pExpr +){ + int n; /* Number of arguments */ + ExprList *pList; /* List of arguments */ + FuncDef *pDef; /* The function */ + sqlite3 *db; /* The database */ + + assert( pExpr->op==TK_FUNCTION ); + if( pWalker->eCode==0 ) return WRC_Abort; + pList = pExpr->x.pList; + if( pList==0 ){ + n = 0; + }else{ + n = pList->nExpr; + sqlite3WalkExprList(pWalker, pList); + if( pWalker->eCode==0 ) return WRC_Abort; + } + db = pWalker->pParse->db; + pDef = sqlite3FindFunction(db, pExpr->u.zToken, n, ENC(db), 0); + if( pDef==0 + || pDef->xFinalize!=0 + || (pDef->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG))==0 + ){ + pWalker->eCode = 0; + } + return WRC_Abort; +} + /* ** These routines are Walker callbacks used to check expressions to @@ -2393,6 +2439,8 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){ ){ if( pWalker->eCode==5 ) ExprSetProperty(pExpr, EP_FromDDL); return WRC_Continue; + }else if( pWalker->pParse ){ + return exprNodeIsConstantFunction(pWalker, pExpr); }else{ pWalker->eCode = 0; return WRC_Abort; @@ -2448,6 +2496,7 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){ static int exprIsConst(Expr *p, int initFlag, int iCur){ Walker w; w.eCode = initFlag; + w.pParse = 0; w.xExprCallback = exprNodeIsConstant; w.xSelectCallback = sqlite3SelectWalkFail; #ifdef SQLITE_DEBUG @@ -2465,9 +2514,24 @@ static int exprIsConst(Expr *p, int initFlag, int iCur){ ** For the purposes of this function, a double-quoted string (ex: "abc") ** is considered a variable but a single-quoted string (ex: 'abc') is ** a constant. +** +** The pParse parameter may be NULL. But if it is NULL, there is no way +** to determine if function calls are constant or not, and hence all +** function calls will be considered to be non-constant. If pParse is +** not NULL, then a function call might be constant, depending on the +** function and on its parameters. */ -int sqlite3ExprIsConstant(Expr *p){ - return exprIsConst(p, 1, 0); +int sqlite3ExprIsConstant(Parse *pParse, Expr *p){ + Walker w; + w.eCode = 1; + w.pParse = pParse; + w.xExprCallback = exprNodeIsConstant; + w.xSelectCallback = sqlite3SelectWalkFail; +#ifdef SQLITE_DEBUG + w.xSelectCallback2 = sqlite3SelectWalkAssert2; +#endif + sqlite3WalkExpr(&w, p); + return w.eCode; } /* @@ -2902,7 +2966,7 @@ static int sqlite3InRhsIsConstant(Expr *pIn){ assert( !ExprHasProperty(pIn, EP_xIsSelect) ); pLHS = pIn->pLeft; pIn->pLeft = 0; - res = sqlite3ExprIsConstant(pIn); + res = sqlite3ExprIsConstant(0, pIn); pIn->pLeft = pLHS; return res; } @@ -3454,7 +3518,7 @@ void sqlite3CodeRhsOfIN( ** this code only executes once. Because for a non-constant ** expression we need to rerun this code each time. */ - if( addrOnce && !sqlite3ExprIsConstant(pE2) ){ + if( addrOnce && !sqlite3ExprIsConstant(0, pE2) ){ sqlite3VdbeChangeToNoop(v, addrOnce-1); sqlite3VdbeChangeToNoop(v, addrOnce); ExprClearProperty(pExpr, EP_Subrtn); @@ -4822,7 +4886,7 @@ expr_code_doover: } for(i=0; ia[i].pExpr) ){ + if( i<32 && sqlite3ExprIsConstant(0, pFarg->a[i].pExpr) ){ testcase( i==31 ); constMask |= MASKBIT32(i); } diff --git a/src/insert.c b/src/insert.c index 2bd846e834..915f368fbd 100644 --- a/src/insert.c +++ b/src/insert.c @@ -594,10 +594,10 @@ void sqlite3MultiValuesEnd(Parse *pParse, Select *pVal){ ** Return true if all expressions in the expression-list passed as the ** only argument are constant. */ -static int exprListIsConstant(ExprList *pRow){ +static int exprListIsConstant(Parse *pParse, ExprList *pRow){ int ii; for(ii=0; iinExpr; ii++){ - if( 0==sqlite3ExprIsConstant(pRow->a[ii].pExpr) ) return 0; + if( 0==sqlite3ExprIsConstant(pParse, pRow->a[ii].pExpr) ) return 0; } return 1; } @@ -606,9 +606,9 @@ static int exprListIsConstant(ExprList *pRow){ ** Return true if all expressions in the expression-list passed as the ** only argument are both constant and have no affinity. */ -static int exprListIsNoAffinity(ExprList *pRow){ +static int exprListIsNoAffinity(Parse *pParse, ExprList *pRow){ int ii; - if( exprListIsConstant(pRow)==0 ) return 0; + if( exprListIsConstant(pParse,pRow)==0 ) return 0; for(ii=0; iinExpr; ii++){ assert( pRow->a[ii].pExpr->affExpr==0 ); if( 0!=sqlite3ExprAffinity(pRow->a[ii].pExpr) ) return 0; @@ -670,11 +670,12 @@ static int exprListIsNoAffinity(ExprList *pRow){ */ Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow){ - if( pLeft->pPrior /* co-routine precluded by prior row */ - || pParse->bHasWith /* condition (a) above */ - || pParse->db->init.busy /* condition (b) above */ - || exprListIsConstant(pRow)==0 /* condition (c) above */ - || (pLeft->pSrc->nSrc==0 && exprListIsNoAffinity(pLeft->pEList)==0) /* (d) */ + if( pLeft->pPrior /* co-routine precluded by prior row */ + || pParse->bHasWith /* condition (a) above */ + || pParse->db->init.busy /* condition (b) above */ + || exprListIsConstant(pParse,pRow)==0 /* condition (c) above */ + || (pLeft->pSrc->nSrc==0 && + exprListIsNoAffinity(pParse,pLeft->pEList)==0) /* condition (d) above */ || IN_SPECIAL_PARSE ){ /* The co-routine method cannot be used. Fall back to UNION ALL. */ diff --git a/src/parse.y b/src/parse.y index 36566d28aa..78404ce673 100644 --- a/src/parse.y +++ b/src/parse.y @@ -1325,7 +1325,7 @@ expr(A) ::= expr(A) between_op(N) expr(X) AND expr(Y). [BETWEEN] { if( A ) sqlite3ExprIdToTrueFalse(A); }else{ Expr *pRHS = Y->a[0].pExpr; - if( Y->nExpr==1 && sqlite3ExprIsConstant(pRHS) && A->op!=TK_VECTOR ){ + if( Y->nExpr==1 && sqlite3ExprIsConstant(0,pRHS) && A->op!=TK_VECTOR ){ Y->a[0].pExpr = 0; sqlite3ExprListDelete(pParse->db, Y); pRHS = sqlite3PExpr(pParse, TK_UPLUS, pRHS, 0); diff --git a/src/select.c b/src/select.c index 4158dd2fdc..bffbaa9800 100644 --- a/src/select.c +++ b/src/select.c @@ -4776,7 +4776,7 @@ static void constInsert( ){ int i; assert( pColumn->op==TK_COLUMN ); - assert( sqlite3ExprIsConstant(pValue) ); + assert( sqlite3ExprIsConstant(0, pValue) ); if( ExprHasProperty(pColumn, EP_FixedCol) ) return; if( sqlite3ExprAffinity(pValue)!=0 ) return; @@ -4834,10 +4834,10 @@ static void findConstInWhere(WhereConst *pConst, Expr *pExpr){ pLeft = pExpr->pLeft; assert( pRight!=0 ); assert( pLeft!=0 ); - if( pRight->op==TK_COLUMN && sqlite3ExprIsConstant(pLeft) ){ + if( pRight->op==TK_COLUMN && sqlite3ExprIsConstant(0, pLeft) ){ constInsert(pConst,pRight,pLeft,pExpr); } - if( pLeft->op==TK_COLUMN && sqlite3ExprIsConstant(pRight) ){ + if( pLeft->op==TK_COLUMN && sqlite3ExprIsConstant(0, pRight) ){ constInsert(pConst,pLeft,pRight,pExpr); } } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 3913392712..205cb6afe0 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -5058,7 +5058,7 @@ void sqlite3LeaveMutexAndCloseZombie(sqlite3*); u32 sqlite3IsTrueOrFalse(const char*); int sqlite3ExprIdToTrueFalse(Expr*); int sqlite3ExprTruthValue(const Expr*); -int sqlite3ExprIsConstant(Expr*); +int sqlite3ExprIsConstant(Parse*,Expr*); int sqlite3ExprIsConstantNotJoin(Expr*); int sqlite3ExprIsConstantOrFunction(Expr*, u8); int sqlite3ExprIsConstantOrGroupBy(Parse*, Expr*, ExprList*); diff --git a/src/where.c b/src/where.c index 9abc8e30f6..2a99c73980 100644 --- a/src/where.c +++ b/src/where.c @@ -1329,7 +1329,7 @@ static sqlite3_index_info *allocateIndexInfo( Expr *pE2; /* Skip over constant terms in the ORDER BY clause */ - if( sqlite3ExprIsConstant(pExpr) ){ + if( sqlite3ExprIsConstant(0, pExpr) ){ continue; } @@ -1441,7 +1441,7 @@ static sqlite3_index_info *allocateIndexInfo( pIdxInfo->nConstraint = j; for(i=j=0; ia[i].pExpr; - if( sqlite3ExprIsConstant(pExpr) ) continue; + if( sqlite3ExprIsConstant(0, pExpr) ) continue; assert( pExpr->op==TK_COLUMN || (pExpr->op==TK_COLLATE && pExpr->pLeft->op==TK_COLUMN && pExpr->iColumn==pExpr->pLeft->iColumn) ); @@ -3623,7 +3623,7 @@ static void wherePartIdxExpr( u8 aff; if( pLeft->op!=TK_COLUMN ) return; - if( !sqlite3ExprIsConstant(pRight) ) return; + if( !sqlite3ExprIsConstant(0, pRight) ) return; if( !sqlite3IsBinary(sqlite3ExprCompareCollSeq(pParse, pPart)) ) return; if( pLeft->iColumn<0 ) return; aff = pIdx->pTable->aCol[pLeft->iColumn].affinity; @@ -4997,7 +4997,7 @@ static i8 wherePathSatisfiesOrderBy( if( MASKBIT(i) & obSat ) continue; p = pOrderBy->a[i].pExpr; mTerm = sqlite3WhereExprUsage(&pWInfo->sMaskSet,p); - if( mTerm==0 && !sqlite3ExprIsConstant(p) ) continue; + if( mTerm==0 && !sqlite3ExprIsConstant(0,p) ) continue; if( (mTerm&~orderDistinctMask)==0 ){ obSat |= MASKBIT(i); } @@ -5866,7 +5866,7 @@ static SQLITE_NOINLINE void whereAddIndexedExpr( }else{ continue; } - if( sqlite3ExprIsConstant(pExpr) ) continue; + if( sqlite3ExprIsConstant(0,pExpr) ) continue; if( pExpr->op==TK_FUNCTION ){ /* Functions that might set a subtype should not be replaced by the ** value taken from an expression index since the index omits the diff --git a/src/whereexpr.c b/src/whereexpr.c index 25db8f396f..9d1f947a09 100644 --- a/src/whereexpr.c +++ b/src/whereexpr.c @@ -989,7 +989,7 @@ static SQLITE_NOINLINE int exprMightBeIndexed2( if( pIdx->aiColumn[i]!=XN_EXPR ) continue; assert( pIdx->bHasExpr ); if( sqlite3ExprCompareSkip(pExpr,pIdx->aColExpr->a[i].pExpr,iCur)==0 - && !sqlite3ExprIsConstant(pIdx->aColExpr->a[i].pExpr) + && !sqlite3ExprIsConstant(0,pIdx->aColExpr->a[i].pExpr) ){ aiCurCol[0] = iCur; aiCurCol[1] = XN_EXPR; diff --git a/src/window.c b/src/window.c index 62df349fb3..bcee65d924 100644 --- a/src/window.c +++ b/src/window.c @@ -1164,7 +1164,7 @@ void sqlite3WindowListDelete(sqlite3 *db, Window *p){ ** variable values in the expression tree. */ static Expr *sqlite3WindowOffsetExpr(Parse *pParse, Expr *pExpr){ - if( 0==sqlite3ExprIsConstant(pExpr) ){ + if( 0==sqlite3ExprIsConstant(0,pExpr) ){ if( IN_RENAME_OBJECT ) sqlite3RenameExprUnmap(pParse, pExpr); sqlite3ExprDelete(pParse->db, pExpr); pExpr = sqlite3ExprAlloc(pParse->db, TK_NULL, 0, 0); From 40514dd1f661ad05b679cda3df90ed4efd0133fc Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 16 Mar 2024 14:27:10 +0000 Subject: [PATCH 18/34] Fix exprNodeIsConstantFunction() so that it returns WRC_Continue, not WRC_Abort, if the function really is constant. FossilOrigin-Name: d85dd4de2d0989127e0ae6a2eec9d83a577777f8d5ba40700084a0b498016634 --- manifest | 19 ++++++++----------- manifest.uuid | 2 +- src/expr.c | 3 ++- test/values.test | 13 +++++++++++++ 4 files changed, 24 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index 5926610ec1..521628dfe1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\sthe\ssqlite3ExprIsConstant()\sfunction\sso\sthat\sit\srecognizes\nconstant\sfunctions.\s\sSo\sfar\sthe\senhancement\sonly\sapplies\sto\sthe\smulti-row\nVALUES\sclause,\sbut\sit\scould\spossibly\sbe\sapplied\sin\smany\sother\splaces. -D 2024-03-16T13:18:48.351 +C Fix\sexprNodeIsConstantFunction()\sso\sthat\sit\sreturns\sWRC_Continue,\snot\sWRC_Abort,\sif\sthe\sfunction\sreally\sis\sconstant. +D 2024-03-16T14:27:10.517 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -700,7 +700,7 @@ F src/date.c 126ba2ab10aeb2e7ba6e089b5f07b747c0625b8287f78b60da346eda8d23c875 F src/dbpage.c 80e46e1df623ec40486da7a5086cb723b0275a6e2a7b01d9f9b5da0f04ba2782 F src/dbstat.c 3b677254d512fcafd4d0b341bf267b38b235ccfddbef24f9154e19360fa22e43 F src/delete.c cb766727c78e715f9fb7ec8a7d03658ed2a3016343ca687acfcec9083cdca500 -F src/expr.c 023e84202023d58bc10cb1f7a4dcc7fe1342e11daa054ea1024e8b78144bd589 +F src/expr.c b3914ec5ac4f1c43d0743123fabab27c089f16dcfdcfd47973e2eebe0834f94b F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c a47610f0a5c6cb0ad79f8fcef039c01833dec0c751bb695f28dc0ec6a4c3ba00 F src/func.c 4204c56196847faefef57fa14e43b8e4d65eb8d7e65318abe463472e3fd148cb @@ -1921,7 +1921,7 @@ F test/vacuum4.test 7ea76b769fffeb41f925303b04cbcf5a5bbeabe55e4c60ae754ff24eeeb7 F test/vacuum5.test 263b144d537e92ad8e9ca8a73cc6e1583f41cfd0dda9432b87f7806174a2f48c F test/vacuum6.test b137b04bf3392d3f5c3b8fda0ce85a6775a70ca112f6559f74ff52dc9ce042fd F test/vacuummem.test 4b30f5b95a9ff86e9d5c20741e50a898b2dc10b0962a3211571eb165357003fb -F test/values.test f888bc7e833cc84258497f2c1b016f04515db00f9ee2e37ea12164eb9c8f47cf +F test/values.test 60723a55f68e8e42027d49a159a1be8b92cb0f538a65cb363ff65637e8a41703 F test/valuesfault.test 2ef23ed965e3bd08e268cdc38a0d11653390ddbbe1e8e2e98d16f55edd30f6e8 F test/varint.test bbce22cda8fc4d135bcc2b589574be8410614e62 F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661 @@ -2179,11 +2179,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 823e579362c05bb8accf6c3b158c5162a16eb23cf81d6021c9e3246e32583d1c -R 2ac63c110cf6a72c96a474d2b73e892b -T *branch * enhanced-expr-is-const -T *sym-enhanced-expr-is-const * -T -sym-exp-values-clause2 * -U drh -Z 0a7dc94654580f17d6264250f37030ea +P c9e0488c6c0135932b6e76b0f3f3acd69ef65327e0a54daa59777f35da1aef26 +R 073539ebd1c8b85d1f5a19f0731cb417 +U dan +Z afcb8a3f36080c6ea414186a5d7c11c8 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 38b8366e49..35e0b4aa0d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c9e0488c6c0135932b6e76b0f3f3acd69ef65327e0a54daa59777f35da1aef26 \ No newline at end of file +d85dd4de2d0989127e0ae6a2eec9d83a577777f8d5ba40700084a0b498016634 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 6050058e43..95567de799 100644 --- a/src/expr.c +++ b/src/expr.c @@ -2388,8 +2388,9 @@ static SQLITE_NOINLINE int exprNodeIsConstantFunction( || (pDef->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG))==0 ){ pWalker->eCode = 0; + return WRC_Abort; } - return WRC_Abort; + return WRC_Continue; } diff --git a/test/values.test b/test/values.test index 3dba3dda94..b96c9e5d23 100644 --- a/test/values.test +++ b/test/values.test @@ -401,6 +401,19 @@ do_execsql_test 12.2 { SELECT * FROM t1 } {1 2 3 4 5 6} +#------------------------------------------------------------------------- +reset_db +do_execsql_test 13.0 { + CREATE TABLE t1(x); + INSERT INTO t1 VALUES('xyz'); + + SELECT ( + VALUES( (max(substr('abc', 1, 1), x)) ), + (123), + (456) + ) + FROM t1; +} {xyz} finish_test From bf4105d76851ba3fb4ad56190284f9ebc6decfd8 Mon Sep 17 00:00:00 2001 From: drh <> Date: Sat, 16 Mar 2024 17:04:08 +0000 Subject: [PATCH 19/34] Extend the scope expr-is-constant for function to cover the IN-to-EQ optimization. FossilOrigin-Name: dae669245c86021bcd28716aff6e316257cc8075d02081745d4b7de17f8ad553 --- manifest | 18 +++++++++--------- manifest.uuid | 2 +- src/parse.y | 2 +- src/test1.c | 21 +++++++++++++++++++++ test/in4.test | 5 +++-- 5 files changed, 35 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index 521628dfe1..bbfca938b7 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sexprNodeIsConstantFunction()\sso\sthat\sit\sreturns\sWRC_Continue,\snot\sWRC_Abort,\sif\sthe\sfunction\sreally\sis\sconstant. -D 2024-03-16T14:27:10.517 +C Extend\sthe\sscope\sexpr-is-constant\sfor\sfunction\sto\scover\sthe\sIN-to-EQ\noptimization. +D 2024-03-16T17:04:08.435 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -739,7 +739,7 @@ F src/os_win.c 6ff43bac175bd9ed79e7c0f96840b139f2f51d01689a638fd05128becf94908a F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/pager.c ff60e98138d2499082ac6230f01ac508aba545315debccfca2fd6042f5f10fcd F src/pager.h 4b1140d691860de0be1347474c51fee07d5420bd7f802d38cbab8ea4ab9f538a -F src/parse.y 004faaa6b6d6a88d9ec5e535281d7a203e1a03e83617ef8249f40e18bda23dc4 +F src/parse.y 5bcef16094213efcc365a9d4dc4e3131f09251dc8838dce4a9e5f9764bff5b82 F src/pcache.c 040b165f30622a21b7a9a77c6f2e4877a32fb7f22d4c7f0d2a6fa6833a156a75 F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5 F src/pcache1.c 602acb23c471bb8d557a6f0083cc2be641d6cafcafa19e481eba7ef4c9ca0f00 @@ -760,7 +760,7 @@ F src/sqliteLimit.h 6878ab64bdeb8c24a1d762d45635e34b96da21132179023338c93f820eee F src/status.c cb11f8589a6912af2da3bb1ec509a94dd8ef27df4d4c1a97e0bcf2309ece972b F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 F src/tclsqlite.c ecbc3c99c0d0c3ed122a913f143026c26d38d57f33e06bb71185dd5c1efe37cd -F src/test1.c 310f43eb17a9252a7790726ca652e4ea3197da17c19eec93b8578863a49dc7b4 +F src/test1.c 5a67577fa7d93a19a72aa165b7013606a35e53f62d0de11587940aed5797d92d F src/test2.c 54520d0565ef2b9bf0f8f1dcac43dc4d06baf4ffe13d10905f8d8c3ad3e4b9ab F src/test3.c e5178558c41ff53236ae0271e9acb3d6885a94981d2eb939536ee6474598840e F src/test4.c 4533b76419e7feb41b40582554663ed3cd77aaa54e135cf76b3205098cd6e664 @@ -1271,7 +1271,7 @@ F test/imposter1.test c3f1db2d3db2c24611a6596a3fc0ffc14f1466c8 F test/in.test d1cad4ededd425568b2e39fb0c31fa9a3772311dd595801ff13ba3912b69bba6 F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75 F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0 -F test/in4.test fdd1d8134da8376985c2edba6035a2de1f6c731524d2ffa651419e8fe2cd1c5a +F test/in4.test 176719161ba96c9386027891602700738aadac3419964f72b628f59d2071d53d F test/in5.test b32ce7f4a93f44c5dee94af16886d922cc16ebe33c8e1765c73d4049d0f4b40f F test/in6.test f5f40d6816a8bb7c784424b58a10ac38efb76ab29127a2c17399e0cbeeda0e4b F test/incrblob.test c9b96afc292aeff43d6687bcb09b0280aa599822 @@ -2179,8 +2179,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 c9e0488c6c0135932b6e76b0f3f3acd69ef65327e0a54daa59777f35da1aef26 -R 073539ebd1c8b85d1f5a19f0731cb417 -U dan -Z afcb8a3f36080c6ea414186a5d7c11c8 +P d85dd4de2d0989127e0ae6a2eec9d83a577777f8d5ba40700084a0b498016634 +R ca429b76372fd82d8194dbd47566db28 +U drh +Z 9b82b5806afe1db311bd1eb3f3eb021c # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 35e0b4aa0d..23dbdeae40 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d85dd4de2d0989127e0ae6a2eec9d83a577777f8d5ba40700084a0b498016634 \ No newline at end of file +dae669245c86021bcd28716aff6e316257cc8075d02081745d4b7de17f8ad553 \ No newline at end of file diff --git a/src/parse.y b/src/parse.y index 78404ce673..d22c8e6fc2 100644 --- a/src/parse.y +++ b/src/parse.y @@ -1325,7 +1325,7 @@ expr(A) ::= expr(A) between_op(N) expr(X) AND expr(Y). [BETWEEN] { if( A ) sqlite3ExprIdToTrueFalse(A); }else{ Expr *pRHS = Y->a[0].pExpr; - if( Y->nExpr==1 && sqlite3ExprIsConstant(0,pRHS) && A->op!=TK_VECTOR ){ + if( Y->nExpr==1 && sqlite3ExprIsConstant(pParse,pRHS) && A->op!=TK_VECTOR ){ Y->a[0].pExpr = 0; sqlite3ExprListDelete(pParse->db, Y); pRHS = sqlite3PExpr(pParse, TK_UPLUS, pRHS, 0); diff --git a/src/test1.c b/src/test1.c index 8faf5a397b..a552c3f509 100644 --- a/src/test1.c +++ b/src/test1.c @@ -1024,6 +1024,23 @@ static void addRealTypeFunction( sqlite3_result_value(context, argv[0]); } +/* +** Implementation of the noop(X) SQL function. +** +** The result is just a copy of its argument. However, this function +** does not have the SQLITE_FUNC_CONSTANT flag, so it is consider +** non-constant by sqlite3ExprIsConstant(). +*/ +static void noopFunction( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + (void)argc; + sqlite3_result_value(context, argv[0]); +} + + /* ** SQL function: strtod(X) ** @@ -1151,6 +1168,10 @@ static int SQLITE_TCLAPI test_create_function( rc = sqlite3_create_function(db, "add_real_type", 1, SQLITE_UTF8, 0, addRealTypeFunction, 0, 0); } + if( rc==SQLITE_OK ){ + rc = sqlite3_create_function(db, "noop", 1, SQLITE_UTF8, + 0, noopFunction, 0, 0); + } /* Functions strtod() and dtostr() work as in the shell. These routines ** use the standard C library to convert between floating point and diff --git a/test/in4.test b/test/in4.test index a3fe22e787..81f2b2840d 100644 --- a/test/in4.test +++ b/test/in4.test @@ -455,17 +455,18 @@ do_execsql_test 11.0 { INSERT INTO sqlite_stat1 VALUES('t1','t1abc','10000 5 00 2003 10'); ANALYZE sqlite_schema; } {} +sqlite3_create_function db do_execsql_test 11.1 { SELECT * FROM t1 WHERE b IN (345, (SELECT 1 FROM t1 - WHERE b IN (345 NOT GLOB 510) + WHERE b IN (noop(1)) AND c GLOB 'abc*xyz')) AND c BETWEEN 'abc' AND 'xyz'; } {xyz 1 abcdefxyz 99} do_execsql_test 11.2 { EXPLAIN SELECT * FROM t1 WHERE b IN (345, (SELECT 1 FROM t1 - WHERE b IN (345 NOT GLOB 510) + WHERE b IN (noop(1)) AND c GLOB 'abc*xyz')) AND c BETWEEN 'abc' AND 'xyz'; } {/ SeekScan /} From b918a0f8215b43d62e2824dbe439261cafaf48c2 Mon Sep 17 00:00:00 2001 From: drh <> Date: Sat, 16 Mar 2024 19:36:18 +0000 Subject: [PATCH 20/34] Activate the enhanced constant-expression for the [constant propagation optimization](/info/f4229707ac08d66c). FossilOrigin-Name: 92afea38881a1a4f266c79ddc6e1027cf17c288dcc8f7e7d50466899ac0054c4 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/select.c | 6 +++--- test/whereL.test | 26 ++++++++++++++++++++++++++ 4 files changed, 37 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index bbfca938b7..8f71171d11 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Extend\sthe\sscope\sexpr-is-constant\sfor\sfunction\sto\scover\sthe\sIN-to-EQ\noptimization. -D 2024-03-16T17:04:08.435 +C Activate\sthe\senhanced\sconstant-expression\sfor\sthe\n[constant\spropagation\soptimization](/info/f4229707ac08d66c). +D 2024-03-16T19:36:18.764 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -750,7 +750,7 @@ F src/printf.c 10e8bad30042f8bd6114a013b4afc229ec8ad255ab27518d7d9f52e8cbc5cd0a F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c F src/resolve.c ef87e3bc7700bfe761a7bbee2ce6084f1766dc816dd82a3ae77c133eec898432 F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97 -F src/select.c 4a3abb346d184a5b1f4f10f10da22465ff18db170099c2d2e0b0cb6ea5f2720e +F src/select.c df2bf515fc36e02e97959a70e82da8a4967d6c85590646a7fda2926a734c81ce F src/shell.c.in cf80c636bccb0ff9db46995e39d69ca21fde2a8a331d1691e4d62a69d7841c8a F src/sqlite.h.in 19a2db3995a699bd7f6dfb423856242bfceb7ec849a93c91d241d19fc28d9f0f F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 @@ -2011,7 +2011,7 @@ F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2 F test/whereI.test c4bb7e2ca56d49bd8ab5c7bd085b8b83e353922b46904d68aefb3c7468643581 F test/whereJ.test fc05e374cc9f2dc204148d6c06822c380ad388895fe97a6d335b94a26a08aecf F test/whereK.test 0270ab7f04ba5436fb9156d31d642a1c82727f4c4bfe5ba90d435c78cf44684a -F test/whereL.test f0e9585623af522ee9f382f8f945ad4b7eb7d806d18746f33f00c374acf6ab65 +F test/whereL.test bf41203fda5e19e4c554a296b4ad2ff3eb27207549b94a819a2bc37275b4529d F test/whereM.test 0dbc9998783458ddcf3cc078ca7c2951d8b2677d472ecf0028f449ed327c0250 F test/wherefault.test 6cf2a9c5712952d463d3f45ebee7f6caf400984df51a195d884cfb7eb0e837a7 F test/wherelfault.test 9012e4ef5259058b771606616bd007af5d154e64cc25fa9fd4170f6411db44e3 @@ -2179,8 +2179,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 d85dd4de2d0989127e0ae6a2eec9d83a577777f8d5ba40700084a0b498016634 -R ca429b76372fd82d8194dbd47566db28 +P dae669245c86021bcd28716aff6e316257cc8075d02081745d4b7de17f8ad553 +R 02d7863e0170a404854cbdb7daab35da U drh -Z 9b82b5806afe1db311bd1eb3f3eb021c +Z 4782493dacf06603b1147674a9e69d60 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 23dbdeae40..7aaeff4fab 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -dae669245c86021bcd28716aff6e316257cc8075d02081745d4b7de17f8ad553 \ No newline at end of file +92afea38881a1a4f266c79ddc6e1027cf17c288dcc8f7e7d50466899ac0054c4 \ No newline at end of file diff --git a/src/select.c b/src/select.c index bffbaa9800..1085b99436 100644 --- a/src/select.c +++ b/src/select.c @@ -4776,7 +4776,7 @@ static void constInsert( ){ int i; assert( pColumn->op==TK_COLUMN ); - assert( sqlite3ExprIsConstant(0, pValue) ); + assert( sqlite3ExprIsConstant(pConst->pParse, pValue) ); if( ExprHasProperty(pColumn, EP_FixedCol) ) return; if( sqlite3ExprAffinity(pValue)!=0 ) return; @@ -4834,10 +4834,10 @@ static void findConstInWhere(WhereConst *pConst, Expr *pExpr){ pLeft = pExpr->pLeft; assert( pRight!=0 ); assert( pLeft!=0 ); - if( pRight->op==TK_COLUMN && sqlite3ExprIsConstant(0, pLeft) ){ + if( pRight->op==TK_COLUMN && sqlite3ExprIsConstant(pConst->pParse, pLeft) ){ constInsert(pConst,pRight,pLeft,pExpr); } - if( pLeft->op==TK_COLUMN && sqlite3ExprIsConstant(0, pRight) ){ + if( pLeft->op==TK_COLUMN && sqlite3ExprIsConstant(pConst->pParse, pRight) ){ constInsert(pConst,pLeft,pRight,pExpr); } } diff --git a/test/whereL.test b/test/whereL.test index 068ee05cd4..9d1054964c 100644 --- a/test/whereL.test +++ b/test/whereL.test @@ -49,6 +49,32 @@ do_eqp_test 120 { |--SEARCH t2 USING INDEX sqlite_autoindex_t2_1 (a=?) `--SCAN t3 } +do_eqp_test 121 { + SELECT * FROM t1, t2, t3 + WHERE t1.a=t2.a AND t2.a=t3.j AND t3.j=abs(5) + ORDER BY t1.a; +} { + QUERY PLAN + |--SEARCH t1 USING INDEX sqlite_autoindex_t1_1 (a=?) + |--SEARCH t2 USING INDEX sqlite_autoindex_t2_1 (a=?) + `--SCAN t3 +} + +# The sqlite3ExprIsConstant() routine does not believe that noop(3) +# is constant. So the optimization does not apply in this case. +# +sqlite3_create_function db +do_eqp_test 122 { + SELECT * FROM t1, t2, t3 + WHERE t1.a=t2.a AND t2.a=t3.j AND t3.j=noop(5) + ORDER BY t1.a; +} { + QUERY PLAN + |--SCAN t3 + |--SEARCH t1 USING INDEX sqlite_autoindex_t1_1 (a=?) + |--SEARCH t2 USING INDEX sqlite_autoindex_t2_1 (a=?) + `--USE TEMP B-TREE FOR ORDER BY +} # Constant propagation in the face of collating sequences: # From 4713b2d73ca0053671c7b6e8502647e1a2c0a411 Mon Sep 17 00:00:00 2001 From: drh <> Date: Sat, 16 Mar 2024 19:48:51 +0000 Subject: [PATCH 21/34] Assert that the eCode is always non-zero upon entry into exprNodeIsConstant(). FossilOrigin-Name: f71b28f6713126745bca53e098dfe3444d4235d6a2b87ced5b333a7f0ee79be8 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/expr.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 8f71171d11..fb57f31af9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Activate\sthe\senhanced\sconstant-expression\sfor\sthe\n[constant\spropagation\soptimization](/info/f4229707ac08d66c). -D 2024-03-16T19:36:18.764 +C Assert\sthat\sthe\seCode\sis\salways\snon-zero\supon\sentry\sinto\sexprNodeIsConstant(). +D 2024-03-16T19:48:51.062 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -700,7 +700,7 @@ F src/date.c 126ba2ab10aeb2e7ba6e089b5f07b747c0625b8287f78b60da346eda8d23c875 F src/dbpage.c 80e46e1df623ec40486da7a5086cb723b0275a6e2a7b01d9f9b5da0f04ba2782 F src/dbstat.c 3b677254d512fcafd4d0b341bf267b38b235ccfddbef24f9154e19360fa22e43 F src/delete.c cb766727c78e715f9fb7ec8a7d03658ed2a3016343ca687acfcec9083cdca500 -F src/expr.c b3914ec5ac4f1c43d0743123fabab27c089f16dcfdcfd47973e2eebe0834f94b +F src/expr.c a6cc77ccca00905f5ba0739dd8112fcb0411231d9228239553829a85bf35b0dd F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c a47610f0a5c6cb0ad79f8fcef039c01833dec0c751bb695f28dc0ec6a4c3ba00 F src/func.c 4204c56196847faefef57fa14e43b8e4d65eb8d7e65318abe463472e3fd148cb @@ -2179,8 +2179,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 dae669245c86021bcd28716aff6e316257cc8075d02081745d4b7de17f8ad553 -R 02d7863e0170a404854cbdb7daab35da +P 92afea38881a1a4f266c79ddc6e1027cf17c288dcc8f7e7d50466899ac0054c4 +R 03a747756d1c2eaa7bed49327f66bff5 U drh -Z 4782493dacf06603b1147674a9e69d60 +Z 34a5fcb15810c923d4200d4da137f642 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 7aaeff4fab..5218da70b2 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -92afea38881a1a4f266c79ddc6e1027cf17c288dcc8f7e7d50466899ac0054c4 \ No newline at end of file +f71b28f6713126745bca53e098dfe3444d4235d6a2b87ced5b333a7f0ee79be8 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 95567de799..66070db5b9 100644 --- a/src/expr.c +++ b/src/expr.c @@ -2372,7 +2372,6 @@ static SQLITE_NOINLINE int exprNodeIsConstantFunction( sqlite3 *db; /* The database */ assert( pExpr->op==TK_FUNCTION ); - if( pWalker->eCode==0 ) return WRC_Abort; pList = pExpr->x.pList; if( pList==0 ){ n = 0; @@ -2421,6 +2420,7 @@ static SQLITE_NOINLINE int exprNodeIsConstantFunction( ** malformed schema error. */ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){ + assert( pWalker->eCode>0 ); /* If pWalker->eCode is 2 then any term of the expression that comes from ** the ON or USING clauses of an outer join disqualifies the expression From 7dc3e923c4066eeb3c8a16f9de736c755b621b00 Mon Sep 17 00:00:00 2001 From: drh <> Date: Sat, 16 Mar 2024 20:15:34 +0000 Subject: [PATCH 22/34] Further expand the scope of usage for the enhacement to expr-is-constant. FossilOrigin-Name: d7eadcf7dd089f0f4aa963c58f0df32edd951368c9906375fd62b0a61cd393b8 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/expr.c | 48 +++++++++++++++++++++--------------------------- src/sqliteInt.h | 1 - 4 files changed, 29 insertions(+), 36 deletions(-) diff --git a/manifest b/manifest index fb57f31af9..bbd7c592eb 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Assert\sthat\sthe\seCode\sis\salways\snon-zero\supon\sentry\sinto\sexprNodeIsConstant(). -D 2024-03-16T19:48:51.062 +C Further\sexpand\sthe\sscope\sof\susage\sfor\sthe\senhacement\sto\sexpr-is-constant. +D 2024-03-16T20:15:34.449 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -700,7 +700,7 @@ F src/date.c 126ba2ab10aeb2e7ba6e089b5f07b747c0625b8287f78b60da346eda8d23c875 F src/dbpage.c 80e46e1df623ec40486da7a5086cb723b0275a6e2a7b01d9f9b5da0f04ba2782 F src/dbstat.c 3b677254d512fcafd4d0b341bf267b38b235ccfddbef24f9154e19360fa22e43 F src/delete.c cb766727c78e715f9fb7ec8a7d03658ed2a3016343ca687acfcec9083cdca500 -F src/expr.c a6cc77ccca00905f5ba0739dd8112fcb0411231d9228239553829a85bf35b0dd +F src/expr.c 8968e7bef87f595a3e7a5a31b1ee849dd26b600cae9caae17d0bd151f7771eb3 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c a47610f0a5c6cb0ad79f8fcef039c01833dec0c751bb695f28dc0ec6a4c3ba00 F src/func.c 4204c56196847faefef57fa14e43b8e4d65eb8d7e65318abe463472e3fd148cb @@ -755,7 +755,7 @@ F src/shell.c.in cf80c636bccb0ff9db46995e39d69ca21fde2a8a331d1691e4d62a69d7841c8 F src/sqlite.h.in 19a2db3995a699bd7f6dfb423856242bfceb7ec849a93c91d241d19fc28d9f0f F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54 -F src/sqliteInt.h 92d3323ba58a1a745f0f6a300d619ea12a6b142f0e8d8d49ce24d84ed85092f1 +F src/sqliteInt.h 4bf7dcc1d2015a6cdd0a2cba5ef33f8f4f7bc14ebc7205321e2488c14eead77d F src/sqliteLimit.h 6878ab64bdeb8c24a1d762d45635e34b96da21132179023338c93f820eee6728 F src/status.c cb11f8589a6912af2da3bb1ec509a94dd8ef27df4d4c1a97e0bcf2309ece972b F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 @@ -2179,8 +2179,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 92afea38881a1a4f266c79ddc6e1027cf17c288dcc8f7e7d50466899ac0054c4 -R 03a747756d1c2eaa7bed49327f66bff5 +P f71b28f6713126745bca53e098dfe3444d4235d6a2b87ced5b333a7f0ee79be8 +R d3bfccf80dd34f5216cfa96d96bbce32 U drh -Z 34a5fcb15810c923d4200d4da137f642 +Z d29542cf1f94495f6b9d8836a34942e6 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 5218da70b2..ce44e01dd6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f71b28f6713126745bca53e098dfe3444d4235d6a2b87ced5b333a7f0ee79be8 \ No newline at end of file +d7eadcf7dd089f0f4aa963c58f0df32edd951368c9906375fd62b0a61cd393b8 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 66070db5b9..4b312873f7 100644 --- a/src/expr.c +++ b/src/expr.c @@ -2372,8 +2372,9 @@ static SQLITE_NOINLINE int exprNodeIsConstantFunction( sqlite3 *db; /* The database */ assert( pExpr->op==TK_FUNCTION ); - pList = pExpr->x.pList; - if( pList==0 ){ + if( ExprHasProperty(pExpr, EP_TokenOnly) + || (pList = pExpr->x.pList)==0 + ){; n = 0; }else{ n = pList->nExpr; @@ -2494,10 +2495,10 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){ return WRC_Continue; } } -static int exprIsConst(Expr *p, int initFlag, int iCur){ +static int exprIsConst(Parse *pParse, Expr *p, int initFlag, int iCur){ Walker w; w.eCode = initFlag; - w.pParse = 0; + w.pParse = pParse; w.xExprCallback = exprNodeIsConstant; w.xSelectCallback = sqlite3SelectWalkFail; #ifdef SQLITE_DEBUG @@ -2523,16 +2524,7 @@ static int exprIsConst(Expr *p, int initFlag, int iCur){ ** function and on its parameters. */ int sqlite3ExprIsConstant(Parse *pParse, Expr *p){ - Walker w; - w.eCode = 1; - w.pParse = pParse; - w.xExprCallback = exprNodeIsConstant; - w.xSelectCallback = sqlite3SelectWalkFail; -#ifdef SQLITE_DEBUG - w.xSelectCallback2 = sqlite3SelectWalkAssert2; -#endif - sqlite3WalkExpr(&w, p); - return w.eCode; + return exprIsConst(pParse, p, 1, 0); } /* @@ -2548,8 +2540,8 @@ int sqlite3ExprIsConstant(Parse *pParse, Expr *p){ ** can be added to the pParse->pConstExpr list and evaluated once when ** the prepared statement starts up. See sqlite3ExprCodeRunJustOnce(). */ -int sqlite3ExprIsConstantNotJoin(Expr *p){ - return exprIsConst(p, 2, 0); +static int sqlite3ExprIsConstantNotJoin(Parse *pParse, Expr *p){ + return exprIsConst(pParse, p, 2, 0); } /* @@ -2559,7 +2551,7 @@ int sqlite3ExprIsConstantNotJoin(Expr *p){ ** table other than iCur. */ int sqlite3ExprIsTableConstant(Expr *p, int iCur){ - return exprIsConst(p, 3, iCur); + return exprIsConst(0, p, 3, iCur); } /* @@ -2716,7 +2708,7 @@ int sqlite3ExprIsConstantOrGroupBy(Parse *pParse, Expr *p, ExprList *pGroupBy){ */ int sqlite3ExprIsConstantOrFunction(Expr *p, u8 isInit){ assert( isInit==0 || isInit==1 ); - return exprIsConst(p, 4+isInit, 0); + return exprIsConst(0, p, 4+isInit, 0); } #ifdef SQLITE_ENABLE_CURSOR_HINTS @@ -2961,13 +2953,13 @@ static void sqlite3SetHasNullFlag(Vdbe *v, int iCur, int regHasNull){ ** The argument is an IN operator with a list (not a subquery) on the ** right-hand side. Return TRUE if that list is constant. */ -static int sqlite3InRhsIsConstant(Expr *pIn){ +static int sqlite3InRhsIsConstant(Parse *pParse, Expr *pIn){ Expr *pLHS; int res; assert( !ExprHasProperty(pIn, EP_xIsSelect) ); pLHS = pIn->pLeft; pIn->pLeft = 0; - res = sqlite3ExprIsConstant(0, pIn); + res = sqlite3ExprIsConstant(pParse, pIn); pIn->pLeft = pLHS; return res; } @@ -3236,7 +3228,7 @@ int sqlite3FindInIndex( if( eType==0 && (inFlags & IN_INDEX_NOOP_OK) && ExprUseXList(pX) - && (!sqlite3InRhsIsConstant(pX) || pX->x.pList->nExpr<=2) + && (!sqlite3InRhsIsConstant(pParse,pX) || pX->x.pList->nExpr<=2) ){ pParse->nTab--; /* Back out the allocation of the unused cursor */ iTab = -1; /* Cursor is not allocated */ @@ -3519,7 +3511,7 @@ void sqlite3CodeRhsOfIN( ** this code only executes once. Because for a non-constant ** expression we need to rerun this code each time. */ - if( addrOnce && !sqlite3ExprIsConstant(0, pE2) ){ + if( addrOnce && !sqlite3ExprIsConstant(pParse, pE2) ){ sqlite3VdbeChangeToNoop(v, addrOnce-1); sqlite3VdbeChangeToNoop(v, addrOnce); ExprClearProperty(pExpr, EP_Subrtn); @@ -4856,7 +4848,9 @@ expr_code_doover: } #endif - if( ConstFactorOk(pParse) && sqlite3ExprIsConstantNotJoin(pExpr) ){ + if( ConstFactorOk(pParse) + && sqlite3ExprIsConstantNotJoin(pParse,pExpr) + ){ /* SQL functions can be expensive. So try to avoid running them ** multiple times if we know they always give the same result */ return sqlite3ExprCodeRunJustOnce(pParse, pExpr, -1); @@ -4887,7 +4881,7 @@ expr_code_doover: } for(i=0; ia[i].pExpr) ){ + if( i<32 && sqlite3ExprIsConstant(pParse, pFarg->a[i].pExpr) ){ testcase( i==31 ); constMask |= MASKBIT32(i); } @@ -5354,7 +5348,7 @@ int sqlite3ExprCodeTemp(Parse *pParse, Expr *pExpr, int *pReg){ if( ConstFactorOk(pParse) && ALWAYS(pExpr!=0) && pExpr->op!=TK_REGISTER - && sqlite3ExprIsConstantNotJoin(pExpr) + && sqlite3ExprIsConstantNotJoin(pParse, pExpr) ){ *pReg = 0; r2 = sqlite3ExprCodeRunJustOnce(pParse, pExpr, -1); @@ -5418,7 +5412,7 @@ void sqlite3ExprCodeCopy(Parse *pParse, Expr *pExpr, int target){ ** might choose to code the expression at initialization time. */ void sqlite3ExprCodeFactorable(Parse *pParse, Expr *pExpr, int target){ - if( pParse->okConstFactor && sqlite3ExprIsConstantNotJoin(pExpr) ){ + if( pParse->okConstFactor && sqlite3ExprIsConstantNotJoin(pParse,pExpr) ){ sqlite3ExprCodeRunJustOnce(pParse, pExpr, target); }else{ sqlite3ExprCodeCopy(pParse, pExpr, target); @@ -5477,7 +5471,7 @@ int sqlite3ExprCodeExprList( sqlite3VdbeAddOp2(v, copyOp, j+srcReg-1, target+i); } }else if( (flags & SQLITE_ECEL_FACTOR)!=0 - && sqlite3ExprIsConstantNotJoin(pExpr) + && sqlite3ExprIsConstantNotJoin(pParse,pExpr) ){ sqlite3ExprCodeRunJustOnce(pParse, pExpr, target+i); }else{ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 205cb6afe0..54fe9458fc 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -5059,7 +5059,6 @@ u32 sqlite3IsTrueOrFalse(const char*); int sqlite3ExprIdToTrueFalse(Expr*); int sqlite3ExprTruthValue(const Expr*); int sqlite3ExprIsConstant(Parse*,Expr*); -int sqlite3ExprIsConstantNotJoin(Expr*); int sqlite3ExprIsConstantOrFunction(Expr*, u8); int sqlite3ExprIsConstantOrGroupBy(Parse*, Expr*, ExprList*); int sqlite3ExprIsTableConstant(Expr*,int); From ec00a4d11148e4127a30bb1b1d26bf09409204e6 Mon Sep 17 00:00:00 2001 From: drh <> Date: Sat, 16 Mar 2024 21:04:32 +0000 Subject: [PATCH 23/34] A formerly impossible case has now become possible because of the new ExprIsConstant enhancements. So deal with that. FossilOrigin-Name: 9ba3cff9d48fe8fc8a0a51291169599209d464465e44bdfd60058fd1e314a2b1 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/expr.c | 5 +++-- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index bbd7c592eb..5a88394c42 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Further\sexpand\sthe\sscope\sof\susage\sfor\sthe\senhacement\sto\sexpr-is-constant. -D 2024-03-16T20:15:34.449 +C A\sformerly\simpossible\scase\shas\snow\sbecome\spossible\sbecause\sof\sthe\snew\nExprIsConstant\senhancements.\s\sSo\sdeal\swith\sthat. +D 2024-03-16T21:04:32.468 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -700,7 +700,7 @@ F src/date.c 126ba2ab10aeb2e7ba6e089b5f07b747c0625b8287f78b60da346eda8d23c875 F src/dbpage.c 80e46e1df623ec40486da7a5086cb723b0275a6e2a7b01d9f9b5da0f04ba2782 F src/dbstat.c 3b677254d512fcafd4d0b341bf267b38b235ccfddbef24f9154e19360fa22e43 F src/delete.c cb766727c78e715f9fb7ec8a7d03658ed2a3016343ca687acfcec9083cdca500 -F src/expr.c 8968e7bef87f595a3e7a5a31b1ee849dd26b600cae9caae17d0bd151f7771eb3 +F src/expr.c eef4b58b1c5f488c7bd099af3a571ff32509d00a1c990f17c0bc5e752ed33462 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c a47610f0a5c6cb0ad79f8fcef039c01833dec0c751bb695f28dc0ec6a4c3ba00 F src/func.c 4204c56196847faefef57fa14e43b8e4d65eb8d7e65318abe463472e3fd148cb @@ -2179,8 +2179,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 f71b28f6713126745bca53e098dfe3444d4235d6a2b87ced5b333a7f0ee79be8 -R d3bfccf80dd34f5216cfa96d96bbce32 +P d7eadcf7dd089f0f4aa963c58f0df32edd951368c9906375fd62b0a61cd393b8 +R 8cf165d7d4e6171fbfcc63e324d78f15 U drh -Z d29542cf1f94495f6b9d8836a34942e6 +Z 950e1346eed1b73efa50ee1189a08fc5 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index ce44e01dd6..3675f57590 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d7eadcf7dd089f0f4aa963c58f0df32edd951368c9906375fd62b0a61cd393b8 \ No newline at end of file +9ba3cff9d48fe8fc8a0a51291169599209d464465e44bdfd60058fd1e314a2b1 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 4b312873f7..3ba07fb2dc 100644 --- a/src/expr.c +++ b/src/expr.c @@ -218,9 +218,10 @@ Expr *sqlite3ExprSkipCollateAndLikely(Expr *pExpr){ assert( pExpr->x.pList->nExpr>0 ); assert( pExpr->op==TK_FUNCTION ); pExpr = pExpr->x.pList->a[0].pExpr; - }else{ - assert( pExpr->op==TK_COLLATE ); + }else if( pExpr->op==TK_COLLATE ){ pExpr = pExpr->pLeft; + }else{ + break; } } return pExpr; From e4a1b4da4f8e76293209071b7bc3588d6c05f736 Mon Sep 17 00:00:00 2001 From: drh <> Date: Sun, 17 Mar 2024 00:13:12 +0000 Subject: [PATCH 24/34] Add an ALWAYS on an unreachable branch. FossilOrigin-Name: 0dce6211690210e802545cbca9b3375e07075e117fad3f8c921879da7671d981 --- manifest | 13 ++++++------- manifest.uuid | 2 +- src/insert.c | 2 +- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index ee5a613c1a..d667045fa5 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Recognize\swhen\san\sSQL\sfunction\sis\sconstant\sand\scan\soccur\sinside\san\noptimized\sVALUES\sclause. -D 2024-03-16T21:12:51.251 +C Add\san\sALWAYS\son\san\sunreachable\sbranch. +D 2024-03-17T00:13:12.278 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -709,7 +709,7 @@ F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220 F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51 F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 -F src/insert.c e28426630ebbac5763d5802099164ad24fbf46fea79d48a8313117a64b950871 +F src/insert.c f0755de645ee8e632445b731951c75b7484ccadb890ade4cbc8db269327ff4b8 F src/json.c e2e40760d6689134c3e2ece38c6a496b34ff5e2661a8f238444a119af666fdce F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36 @@ -2179,9 +2179,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 823e579362c05bb8accf6c3b158c5162a16eb23cf81d6021c9e3246e32583d1c 9ba3cff9d48fe8fc8a0a51291169599209d464465e44bdfd60058fd1e314a2b1 -R 8cf165d7d4e6171fbfcc63e324d78f15 -T +closed 9ba3cff9d48fe8fc8a0a51291169599209d464465e44bdfd60058fd1e314a2b1 +P c0e5ceb87d3cf28f22d381f863b8f91043804fd7901f23f3afb02fe698e6a12a +R c0fd5d4c2ab2c847266cf4b9416ae243 U drh -Z 1c2f2833c22bf92aec87aab6cf84bca7 +Z 061bbac91348ec107ed9e1ccfd2e024e # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index ca62261369..9a374d564f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c0e5ceb87d3cf28f22d381f863b8f91043804fd7901f23f3afb02fe698e6a12a \ No newline at end of file +0dce6211690210e802545cbca9b3375e07075e117fad3f8c921879da7671d981 \ No newline at end of file diff --git a/src/insert.c b/src/insert.c index 915f368fbd..2c6a76b78d 100644 --- a/src/insert.c +++ b/src/insert.c @@ -583,7 +583,7 @@ void sqlite3AutoincrementEnd(Parse *pParse){ ** co-routine. */ void sqlite3MultiValuesEnd(Parse *pParse, Select *pVal){ - if( pVal && pVal->pSrc->nSrc>0 ){ + if( ALWAYS(pVal) && pVal->pSrc->nSrc>0 ){ SrcItem *pItem = &pVal->pSrc->a[0]; sqlite3VdbeEndCoroutine(pParse->pVdbe, pItem->regReturn); sqlite3VdbeJumpHere(pParse->pVdbe, pItem->addrFillSub - 1); From 54bf109e807cc2c12cd81883affd008d718d0748 Mon Sep 17 00:00:00 2001 From: drh <> Date: Sun, 17 Mar 2024 16:01:23 +0000 Subject: [PATCH 25/34] Omit the "noop(X)" test SQL function. Accomplish the same thing using the idiom: "coalesce(X,random())". FossilOrigin-Name: 0eb2fbb8910e7a372c50db3ae44238d7b161f0e45858b74061b5228aec5fcc7e --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/test1.c | 21 --------------------- test/in4.test | 5 ++--- test/whereL.test | 7 ++++--- 5 files changed, 15 insertions(+), 36 deletions(-) diff --git a/manifest b/manifest index d667045fa5..7f30177097 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\san\sALWAYS\son\san\sunreachable\sbranch. -D 2024-03-17T00:13:12.278 +C Omit\sthe\s"noop(X)"\stest\sSQL\sfunction.\s\sAccomplish\sthe\ssame\sthing\susing\nthe\sidiom:\s\s"coalesce(X,random())". +D 2024-03-17T16:01:23.923 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -760,7 +760,7 @@ F src/sqliteLimit.h 6878ab64bdeb8c24a1d762d45635e34b96da21132179023338c93f820eee F src/status.c cb11f8589a6912af2da3bb1ec509a94dd8ef27df4d4c1a97e0bcf2309ece972b F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 F src/tclsqlite.c ecbc3c99c0d0c3ed122a913f143026c26d38d57f33e06bb71185dd5c1efe37cd -F src/test1.c 5a67577fa7d93a19a72aa165b7013606a35e53f62d0de11587940aed5797d92d +F src/test1.c 310f43eb17a9252a7790726ca652e4ea3197da17c19eec93b8578863a49dc7b4 F src/test2.c 54520d0565ef2b9bf0f8f1dcac43dc4d06baf4ffe13d10905f8d8c3ad3e4b9ab F src/test3.c e5178558c41ff53236ae0271e9acb3d6885a94981d2eb939536ee6474598840e F src/test4.c 4533b76419e7feb41b40582554663ed3cd77aaa54e135cf76b3205098cd6e664 @@ -1271,7 +1271,7 @@ F test/imposter1.test c3f1db2d3db2c24611a6596a3fc0ffc14f1466c8 F test/in.test d1cad4ededd425568b2e39fb0c31fa9a3772311dd595801ff13ba3912b69bba6 F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75 F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0 -F test/in4.test 176719161ba96c9386027891602700738aadac3419964f72b628f59d2071d53d +F test/in4.test bb767ec1cfd1730256f0a83219f0acda36bc251b63f8b8bb7d8c7cff17875a4f F test/in5.test b32ce7f4a93f44c5dee94af16886d922cc16ebe33c8e1765c73d4049d0f4b40f F test/in6.test f5f40d6816a8bb7c784424b58a10ac38efb76ab29127a2c17399e0cbeeda0e4b F test/incrblob.test c9b96afc292aeff43d6687bcb09b0280aa599822 @@ -2011,7 +2011,7 @@ F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2 F test/whereI.test c4bb7e2ca56d49bd8ab5c7bd085b8b83e353922b46904d68aefb3c7468643581 F test/whereJ.test fc05e374cc9f2dc204148d6c06822c380ad388895fe97a6d335b94a26a08aecf F test/whereK.test 0270ab7f04ba5436fb9156d31d642a1c82727f4c4bfe5ba90d435c78cf44684a -F test/whereL.test bf41203fda5e19e4c554a296b4ad2ff3eb27207549b94a819a2bc37275b4529d +F test/whereL.test 438a397fa883b77bb6361c08a8befa41b52e9cfbe15a2a43715d122f8cfa8649 F test/whereM.test 0dbc9998783458ddcf3cc078ca7c2951d8b2677d472ecf0028f449ed327c0250 F test/wherefault.test 6cf2a9c5712952d463d3f45ebee7f6caf400984df51a195d884cfb7eb0e837a7 F test/wherelfault.test 9012e4ef5259058b771606616bd007af5d154e64cc25fa9fd4170f6411db44e3 @@ -2179,8 +2179,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 c0e5ceb87d3cf28f22d381f863b8f91043804fd7901f23f3afb02fe698e6a12a -R c0fd5d4c2ab2c847266cf4b9416ae243 +P 0dce6211690210e802545cbca9b3375e07075e117fad3f8c921879da7671d981 +R 04c934383a09ffd06af013a1dd47675b U drh -Z 061bbac91348ec107ed9e1ccfd2e024e +Z ca3e70db7b33adfad0eeda8b7a11174b # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 9a374d564f..186e057cef 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0dce6211690210e802545cbca9b3375e07075e117fad3f8c921879da7671d981 \ No newline at end of file +0eb2fbb8910e7a372c50db3ae44238d7b161f0e45858b74061b5228aec5fcc7e \ No newline at end of file diff --git a/src/test1.c b/src/test1.c index a552c3f509..8faf5a397b 100644 --- a/src/test1.c +++ b/src/test1.c @@ -1024,23 +1024,6 @@ static void addRealTypeFunction( sqlite3_result_value(context, argv[0]); } -/* -** Implementation of the noop(X) SQL function. -** -** The result is just a copy of its argument. However, this function -** does not have the SQLITE_FUNC_CONSTANT flag, so it is consider -** non-constant by sqlite3ExprIsConstant(). -*/ -static void noopFunction( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - (void)argc; - sqlite3_result_value(context, argv[0]); -} - - /* ** SQL function: strtod(X) ** @@ -1168,10 +1151,6 @@ static int SQLITE_TCLAPI test_create_function( rc = sqlite3_create_function(db, "add_real_type", 1, SQLITE_UTF8, 0, addRealTypeFunction, 0, 0); } - if( rc==SQLITE_OK ){ - rc = sqlite3_create_function(db, "noop", 1, SQLITE_UTF8, - 0, noopFunction, 0, 0); - } /* Functions strtod() and dtostr() work as in the shell. These routines ** use the standard C library to convert between floating point and diff --git a/test/in4.test b/test/in4.test index 81f2b2840d..71993e7003 100644 --- a/test/in4.test +++ b/test/in4.test @@ -455,18 +455,17 @@ do_execsql_test 11.0 { INSERT INTO sqlite_stat1 VALUES('t1','t1abc','10000 5 00 2003 10'); ANALYZE sqlite_schema; } {} -sqlite3_create_function db do_execsql_test 11.1 { SELECT * FROM t1 WHERE b IN (345, (SELECT 1 FROM t1 - WHERE b IN (noop(1)) + WHERE b IN (coalesce(1,random())) AND c GLOB 'abc*xyz')) AND c BETWEEN 'abc' AND 'xyz'; } {xyz 1 abcdefxyz 99} do_execsql_test 11.2 { EXPLAIN SELECT * FROM t1 WHERE b IN (345, (SELECT 1 FROM t1 - WHERE b IN (noop(1)) + WHERE b IN (coalesce(1,random())) AND c GLOB 'abc*xyz')) AND c BETWEEN 'abc' AND 'xyz'; } {/ SeekScan /} diff --git a/test/whereL.test b/test/whereL.test index 9d1054964c..2e9ae219e1 100644 --- a/test/whereL.test +++ b/test/whereL.test @@ -60,13 +60,14 @@ do_eqp_test 121 { `--SCAN t3 } -# The sqlite3ExprIsConstant() routine does not believe that noop(3) -# is constant. So the optimization does not apply in this case. +# The sqlite3ExprIsConstant() routine does not believe that +# the expression "coalesce(5,random())" is constant. So the +# optimization does not apply in this case. # sqlite3_create_function db do_eqp_test 122 { SELECT * FROM t1, t2, t3 - WHERE t1.a=t2.a AND t2.a=t3.j AND t3.j=noop(5) + WHERE t1.a=t2.a AND t2.a=t3.j AND t3.j=coalesce(5,random()) ORDER BY t1.a; } { QUERY PLAN From 2f4a8cc2d8f1ce29814a97887d9e8e96e9ed7725 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 18 Mar 2024 10:54:48 +0000 Subject: [PATCH 26/34] Fix a problem caused by a non-aggregate function with an OVER clause in a multi-row VALUES clause. FossilOrigin-Name: 10ee6fcba08ab1281235197602148fe062560e1d5034a477b8e7b574dd3e2907 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/expr.c | 1 + test/values.test | 5 +++++ 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 7f30177097..f72f4d1d80 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Omit\sthe\s"noop(X)"\stest\sSQL\sfunction.\s\sAccomplish\sthe\ssame\sthing\susing\nthe\sidiom:\s\s"coalesce(X,random())". -D 2024-03-17T16:01:23.923 +C Fix\sa\sproblem\scaused\sby\sa\snon-aggregate\sfunction\swith\san\sOVER\sclause\sin\sa\smulti-row\sVALUES\sclause. +D 2024-03-18T10:54:48.739 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -700,7 +700,7 @@ F src/date.c 126ba2ab10aeb2e7ba6e089b5f07b747c0625b8287f78b60da346eda8d23c875 F src/dbpage.c 80e46e1df623ec40486da7a5086cb723b0275a6e2a7b01d9f9b5da0f04ba2782 F src/dbstat.c 3b677254d512fcafd4d0b341bf267b38b235ccfddbef24f9154e19360fa22e43 F src/delete.c cb766727c78e715f9fb7ec8a7d03658ed2a3016343ca687acfcec9083cdca500 -F src/expr.c eef4b58b1c5f488c7bd099af3a571ff32509d00a1c990f17c0bc5e752ed33462 +F src/expr.c 27fdcdc65bca88934dfc4af0efe7a3eae095267bf7592b562abb6a11292c2b82 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c a47610f0a5c6cb0ad79f8fcef039c01833dec0c751bb695f28dc0ec6a4c3ba00 F src/func.c 4204c56196847faefef57fa14e43b8e4d65eb8d7e65318abe463472e3fd148cb @@ -1921,7 +1921,7 @@ F test/vacuum4.test 7ea76b769fffeb41f925303b04cbcf5a5bbeabe55e4c60ae754ff24eeeb7 F test/vacuum5.test 263b144d537e92ad8e9ca8a73cc6e1583f41cfd0dda9432b87f7806174a2f48c F test/vacuum6.test b137b04bf3392d3f5c3b8fda0ce85a6775a70ca112f6559f74ff52dc9ce042fd F test/vacuummem.test 4b30f5b95a9ff86e9d5c20741e50a898b2dc10b0962a3211571eb165357003fb -F test/values.test 60723a55f68e8e42027d49a159a1be8b92cb0f538a65cb363ff65637e8a41703 +F test/values.test 336ce9404c15cc9ff70f74a374e6da474724c94e69ea658aeab279d94623142f F test/valuesfault.test 2ef23ed965e3bd08e268cdc38a0d11653390ddbbe1e8e2e98d16f55edd30f6e8 F test/varint.test bbce22cda8fc4d135bcc2b589574be8410614e62 F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661 @@ -2179,8 +2179,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 0dce6211690210e802545cbca9b3375e07075e117fad3f8c921879da7671d981 -R 04c934383a09ffd06af013a1dd47675b -U drh -Z ca3e70db7b33adfad0eeda8b7a11174b +P 0eb2fbb8910e7a372c50db3ae44238d7b161f0e45858b74061b5228aec5fcc7e +R 0c271dec25d4e7ba3707539d1d6d785b +U dan +Z 92342f3e47401a6da453743f142fe632 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 186e057cef..18c1998557 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0eb2fbb8910e7a372c50db3ae44238d7b161f0e45858b74061b5228aec5fcc7e \ No newline at end of file +10ee6fcba08ab1281235197602148fe062560e1d5034a477b8e7b574dd3e2907 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 3ba07fb2dc..be8339c305 100644 --- a/src/expr.c +++ b/src/expr.c @@ -2387,6 +2387,7 @@ static SQLITE_NOINLINE int exprNodeIsConstantFunction( if( pDef==0 || pDef->xFinalize!=0 || (pDef->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG))==0 + || pExpr->y.pWin ){ pWalker->eCode = 0; return WRC_Abort; diff --git a/test/values.test b/test/values.test index b96c9e5d23..caa33058bf 100644 --- a/test/values.test +++ b/test/values.test @@ -415,5 +415,10 @@ do_execsql_test 13.0 { FROM t1; } {xyz} +do_catchsql_test 13.1 { + VALUES(300), (zeroblob(300) OVER win); +} {1 {zeroblob() may not be used as a window function}} + + finish_test From 75924d3ae22587cac6c68caad9212a7621e47135 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 18 Mar 2024 11:12:22 +0000 Subject: [PATCH 27/34] Ensure the database schema has been loaded and the database encoding gleaned before beginning to code a multi-row VALUES clause. FossilOrigin-Name: 2ff476eb3d1f4a2146f4a48b57895a00a3ff5beb29afa679ae53ea58cac07c76 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/insert.c | 8 ++++++++ test/values.test | 16 ++++++++++++++++ 4 files changed, 32 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index f72f4d1d80..b3ff72f880 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sproblem\scaused\sby\sa\snon-aggregate\sfunction\swith\san\sOVER\sclause\sin\sa\smulti-row\sVALUES\sclause. -D 2024-03-18T10:54:48.739 +C Ensure\sthe\sdatabase\sschema\shas\sbeen\sloaded\sand\sthe\sdatabase\sencoding\sgleaned\sbefore\sbeginning\sto\scode\sa\smulti-row\sVALUES\sclause. +D 2024-03-18T11:12:22.121 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -709,7 +709,7 @@ F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220 F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51 F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 -F src/insert.c f0755de645ee8e632445b731951c75b7484ccadb890ade4cbc8db269327ff4b8 +F src/insert.c 507113439413cdda2705b98089068be2b84273984bd2fbefe5e6a63efd2654a4 F src/json.c e2e40760d6689134c3e2ece38c6a496b34ff5e2661a8f238444a119af666fdce F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36 @@ -1921,7 +1921,7 @@ F test/vacuum4.test 7ea76b769fffeb41f925303b04cbcf5a5bbeabe55e4c60ae754ff24eeeb7 F test/vacuum5.test 263b144d537e92ad8e9ca8a73cc6e1583f41cfd0dda9432b87f7806174a2f48c F test/vacuum6.test b137b04bf3392d3f5c3b8fda0ce85a6775a70ca112f6559f74ff52dc9ce042fd F test/vacuummem.test 4b30f5b95a9ff86e9d5c20741e50a898b2dc10b0962a3211571eb165357003fb -F test/values.test 336ce9404c15cc9ff70f74a374e6da474724c94e69ea658aeab279d94623142f +F test/values.test 301f9dcf37e654e9fb7f210ebeded878b620f17965f3b6b0d273323183538e82 F test/valuesfault.test 2ef23ed965e3bd08e268cdc38a0d11653390ddbbe1e8e2e98d16f55edd30f6e8 F test/varint.test bbce22cda8fc4d135bcc2b589574be8410614e62 F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661 @@ -2179,8 +2179,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 0eb2fbb8910e7a372c50db3ae44238d7b161f0e45858b74061b5228aec5fcc7e -R 0c271dec25d4e7ba3707539d1d6d785b +P 10ee6fcba08ab1281235197602148fe062560e1d5034a477b8e7b574dd3e2907 +R 22155fb84ed7e9f97f13e6f0600beffd U dan -Z 92342f3e47401a6da453743f142fe632 +Z 0dcb69e533979c58b8fa8014884ff3fb # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 18c1998557..f196850839 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -10ee6fcba08ab1281235197602148fe062560e1d5034a477b8e7b574dd3e2907 \ No newline at end of file +2ff476eb3d1f4a2146f4a48b57895a00a3ff5beb29afa679ae53ea58cac07c76 \ No newline at end of file diff --git a/src/insert.c b/src/insert.c index 2c6a76b78d..7d386f5d2b 100644 --- a/src/insert.c +++ b/src/insert.c @@ -698,12 +698,20 @@ Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow){ }else{ SrcItem *p = 0; /* SrcItem that reads from co-routine */ + if( pLeft->pSrc->nSrc==0 ){ /* Co-routine has not yet been started and the special Select object ** that accesses the co-routine has not yet been created. This block ** does both those things. */ Vdbe *v = sqlite3GetVdbe(pParse); Select *pRet = sqlite3SelectNew(pParse, 0, 0, 0, 0, 0, 0, 0, 0); + + /* Ensure the database schema has been read. This is to ensure we have + ** the correct text encoding. */ + if( (pParse->db->mDbFlags & DBFLAG_SchemaKnownOk)==0 ){ + sqlite3ReadSchema(pParse); + } + if( pRet ){ SelectDest dest; pRet->pSrc->nSrc = 1; diff --git a/test/values.test b/test/values.test index caa33058bf..d6eb0684e1 100644 --- a/test/values.test +++ b/test/values.test @@ -419,6 +419,22 @@ do_catchsql_test 13.1 { VALUES(300), (zeroblob(300) OVER win); } {1 {zeroblob() may not be used as a window function}} +#-------------------------------------------------------------------------- +reset_db +do_execsql_test 14.1 { + PRAGMA encoding = utf16; + CREATE TABLE t1(a, b); +} {} + +db close +sqlite3 db test.db + +do_execsql_test 14.2 { + INSERT INTO t1 VALUES + (17, 'craft'), + (16, 'urtlek' IN(1,2,3)); +} + finish_test From 27a5ee855d6428246ea7fc9511a2a10a85c3199c Mon Sep 17 00:00:00 2001 From: drh <> Date: Mon, 18 Mar 2024 12:49:30 +0000 Subject: [PATCH 28/34] Improvements to EXPLAIN QUERY PLAN output for multi-row VALUES claues. FossilOrigin-Name: ac6f095e13e43d66c06552c8b01f6bec3407c9d41a34c4cdb0be57b0b828ad0d --- manifest | 22 ++++++++++---------- manifest.uuid | 2 +- src/insert.c | 4 ++++ src/printf.c | 3 +++ src/sqliteInt.h | 1 + src/where.c | 6 +++++- test/values.test | 52 +++++++++++++++++++++++++++++++++++++++++++++++- 7 files changed, 76 insertions(+), 14 deletions(-) diff --git a/manifest b/manifest index b3ff72f880..93cb0216d1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Ensure\sthe\sdatabase\sschema\shas\sbeen\sloaded\sand\sthe\sdatabase\sencoding\sgleaned\sbefore\sbeginning\sto\scode\sa\smulti-row\sVALUES\sclause. -D 2024-03-18T11:12:22.121 +C Improvements\sto\sEXPLAIN\sQUERY\sPLAN\soutput\sfor\smulti-row\sVALUES\sclaues. +D 2024-03-18T12:49:30.989 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -709,7 +709,7 @@ F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220 F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51 F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 -F src/insert.c 507113439413cdda2705b98089068be2b84273984bd2fbefe5e6a63efd2654a4 +F src/insert.c 3b3661886b198d9c5e26c189a802782d35e6b415d0edf57af8c273225c2ae8f2 F src/json.c e2e40760d6689134c3e2ece38c6a496b34ff5e2661a8f238444a119af666fdce F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36 @@ -746,7 +746,7 @@ F src/pcache1.c 602acb23c471bb8d557a6f0083cc2be641d6cafcafa19e481eba7ef4c9ca0f00 F src/pragma.c e8221d6310c9923c80f6fa6d09b7ea7c5263a671f53db8d0894df23efcdb617b F src/pragma.h e690a356c18e98414d2e870ea791c1be1545a714ba623719deb63f7f226d8bb7 F src/prepare.c 371f6115cb69286ebc12c6f2d7511279c2e47d9f54f475d46a554d687a3b312c -F src/printf.c 10e8bad30042f8bd6114a013b4afc229ec8ad255ab27518d7d9f52e8cbc5cd0a +F src/printf.c aec4a5d743796be82d61c5d127d0f4615efbe61620a7a16968c5e2c9378ab37b F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c F src/resolve.c ef87e3bc7700bfe761a7bbee2ce6084f1766dc816dd82a3ae77c133eec898432 F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97 @@ -755,7 +755,7 @@ F src/shell.c.in cf80c636bccb0ff9db46995e39d69ca21fde2a8a331d1691e4d62a69d7841c8 F src/sqlite.h.in 19a2db3995a699bd7f6dfb423856242bfceb7ec849a93c91d241d19fc28d9f0f F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54 -F src/sqliteInt.h 4bf7dcc1d2015a6cdd0a2cba5ef33f8f4f7bc14ebc7205321e2488c14eead77d +F src/sqliteInt.h f0014674d40b401795b4ff026fc4804aed3887f50d206fb221ddf4f2004bc3ef F src/sqliteLimit.h 6878ab64bdeb8c24a1d762d45635e34b96da21132179023338c93f820eee6728 F src/status.c cb11f8589a6912af2da3bb1ec509a94dd8ef27df4d4c1a97e0bcf2309ece972b F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 @@ -835,7 +835,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c 887fc4ca3f020ebb2e376f222069570834ac63bf50111ef0cbf3ae417048ed89 F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452 F src/walker.c 7c7ea0115345851c3da4e04e2e239a29983b61fb5b038b94eede6aba462640e2 -F src/where.c 3efa165f9205602eef711af071db3862531fcda2b1ad875cda5e2c5effa56fee +F src/where.c 5e9a5d642cceb666152c59091a3dbb645a9dda209b4e65a2f9215ee9298d26cf F src/whereInt.h 82a13766f13d1a53b05387c2e60726289ef26404bc7b9b1f7770204d97357fb8 F src/wherecode.c 5d77db30a2a3dd532492ae882de114edba2fae672622056b1c7fd61f5917a8f1 F src/whereexpr.c 7b64295f1d82ad0928df435925dd7bbd5997b44a026153113eace0d9e71ff435 @@ -1921,7 +1921,7 @@ F test/vacuum4.test 7ea76b769fffeb41f925303b04cbcf5a5bbeabe55e4c60ae754ff24eeeb7 F test/vacuum5.test 263b144d537e92ad8e9ca8a73cc6e1583f41cfd0dda9432b87f7806174a2f48c F test/vacuum6.test b137b04bf3392d3f5c3b8fda0ce85a6775a70ca112f6559f74ff52dc9ce042fd F test/vacuummem.test 4b30f5b95a9ff86e9d5c20741e50a898b2dc10b0962a3211571eb165357003fb -F test/values.test 301f9dcf37e654e9fb7f210ebeded878b620f17965f3b6b0d273323183538e82 +F test/values.test 77f72e80ad7b9e362e309bccb391307f41d0a41d1cd159cbdadb2de043505184 F test/valuesfault.test 2ef23ed965e3bd08e268cdc38a0d11653390ddbbe1e8e2e98d16f55edd30f6e8 F test/varint.test bbce22cda8fc4d135bcc2b589574be8410614e62 F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661 @@ -2179,8 +2179,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 10ee6fcba08ab1281235197602148fe062560e1d5034a477b8e7b574dd3e2907 -R 22155fb84ed7e9f97f13e6f0600beffd -U dan -Z 0dcb69e533979c58b8fa8014884ff3fb +P 2ff476eb3d1f4a2146f4a48b57895a00a3ff5beb29afa679ae53ea58cac07c76 +R dd6d36e36b292e54015829bdd4a764a6 +U drh +Z 67655d85fa3f7ad082be72ee3ee927a1 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index f196850839..21dcd3d6f2 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2ff476eb3d1f4a2146f4a48b57895a00a3ff5beb29afa679ae53ea58cac07c76 \ No newline at end of file +ac6f095e13e43d66c06552c8b01f6bec3407c9d41a34c4cdb0be57b0b828ad0d \ No newline at end of file diff --git a/src/insert.c b/src/insert.c index 7d386f5d2b..7256281fd2 100644 --- a/src/insert.c +++ b/src/insert.c @@ -721,6 +721,7 @@ Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow){ p->addrFillSub = sqlite3VdbeCurrentAddr(v) + 1; p->regReturn = ++pParse->nMem; p->iCursor = -1; + p->u1.nRow = 2; sqlite3VdbeAddOp3(v,OP_InitCoroutine,p->regReturn,0,p->addrFillSub); sqlite3SelectDestInit(&dest, SRT_Coroutine, p->regReturn); @@ -733,6 +734,7 @@ Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow){ dest.nSdst = pLeft->pEList->nExpr; pParse->nMem += 2 + dest.nSdst; + pLeft->selFlags |= SF_MultiValue; sqlite3Select(pParse, pLeft, &dest); p->regResult = dest.iSdst; assert( pParse->nErr || dest.iSdst>0 ); @@ -740,6 +742,7 @@ Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow){ } }else{ p = &pLeft->pSrc->a[0]; + p->u1.nRow++; } if( pParse->nErr==0 ){ @@ -1102,6 +1105,7 @@ void sqlite3Insert( dest.iSDParm = regYield = pItem->regReturn; regFromSelect = pItem->regResult; nColumn = pItem->pSelect->pEList->nExpr; + ExplainQueryPlan((pParse, 0, "SCAN %S", pItem)); if( bIdListInOrder && nColumn==pTab->nCol ){ regData = regFromSelect; regRowid = regData - 1; diff --git a/src/printf.c b/src/printf.c index 186e95bb85..0aea74e890 100644 --- a/src/printf.c +++ b/src/printf.c @@ -860,6 +860,9 @@ void sqlite3_str_vappendf( assert( pSel!=0 ); if( pSel->selFlags & SF_NestedFrom ){ sqlite3_str_appendf(pAccum, "(join-%u)", pSel->selId); + }else if( pSel->selFlags & SF_MultiValue ){ + sqlite3_str_appendf(pAccum, "%u-ROW VALUES CLAUSE", + pItem->u1.nRow); }else{ sqlite3_str_appendf(pAccum, "(subquery-%u)", pSel->selId); } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 54fe9458fc..01a5126499 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3311,6 +3311,7 @@ struct SrcItem { union { char *zIndexedBy; /* Identifier from "INDEXED BY " clause */ ExprList *pFuncArg; /* Arguments to table-valued-function */ + u32 nRow; /* Number of rows in a VALUES clause */ } u1; union { Index *pIBIndex; /* Index structure corresponding to u1.zIndexedBy */ diff --git a/src/where.c b/src/where.c index 2a99c73980..2463e823c8 100644 --- a/src/where.c +++ b/src/where.c @@ -6144,7 +6144,11 @@ WhereInfo *sqlite3WhereBegin( ){ pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE; } - ExplainQueryPlan((pParse, 0, "SCAN CONSTANT ROW")); + if( ALWAYS(pWInfo->pSelect) + && (pWInfo->pSelect->selFlags & SF_MultiValue)==0 + ){ + ExplainQueryPlan((pParse, 0, "SCAN CONSTANT ROW")); + } }else{ /* Assign a bit from the bitmask to every term in the FROM clause. ** diff --git a/test/values.test b/test/values.test index d6eb0684e1..8365584b4a 100644 --- a/test/values.test +++ b/test/values.test @@ -435,6 +435,56 @@ do_execsql_test 14.2 { (16, 'urtlek' IN(1,2,3)); } +#-------------------------------------------------------------------------- +# +reset_db +do_eqp_test 15.1 { + VALUES(1),(2),(3),(4),(5); +} { + QUERY PLAN + `--SCAN 5-ROW VALUES CLAUSE +} +do_execsql_test 15.2 { + CREATE TABLE t1(a,b); +} +do_eqp_test 15.3 { + INSERT INTO t1 VALUES + (1,2),(3,4),(7,8); +} { + QUERY PLAN + `--SCAN 3-ROW VALUES CLAUSE +} +do_eqp_test 15.4 { + INSERT INTO t1 VALUES + (1,2),(3,4),(7,8), + (5,coalesce(6,random())); +} { + QUERY PLAN + `--COMPOUND QUERY + |--LEFT-MOST SUBQUERY + | `--SCAN 3-ROW VALUES CLAUSE + `--UNION ALL + `--SCAN CONSTANT ROW +} +do_eqp_test 15.5 { + SELECT * FROM (VALUES(1),(2),(3),(4),(5),(6)), (VALUES('a'),('b'),('c')); +} { + QUERY PLAN + |--SCAN 6-ROW VALUES CLAUSE + `--SCAN 3-ROW VALUES CLAUSE +} +do_execsql_test 15.6 { + CREATE TABLE t2(x,y); +} +do_eqp_test 15.7 { + SELECT * FROM t2 UNION ALL VALUES(1,2),(3,4),(5,6),(7,8); +} { + QUERY PLAN + `--COMPOUND QUERY + |--LEFT-MOST SUBQUERY + | `--SCAN t2 + `--UNION ALL + `--SCAN 4-ROW VALUES CLAUSE +} finish_test - From 871786b7927bc101e25e38d1c446cecd55939ed4 Mon Sep 17 00:00:00 2001 From: drh <> Date: Mon, 18 Mar 2024 13:10:54 +0000 Subject: [PATCH 29/34] Fix the patch at [10ee6fcba08ab128] so that it works on reduced-size Expr nodes. FossilOrigin-Name: 260bd764c3f2d6d067adb9cd0045b7c24d5e00b02ab2735b1cba455a6143ff4c --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/expr.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 93cb0216d1..5876e426d7 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improvements\sto\sEXPLAIN\sQUERY\sPLAN\soutput\sfor\smulti-row\sVALUES\sclaues. -D 2024-03-18T12:49:30.989 +C Fix\sthe\spatch\sat\s[10ee6fcba08ab128]\sso\sthat\sit\sworks\son\sreduced-size\sExpr\nnodes. +D 2024-03-18T13:10:54.954 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -700,7 +700,7 @@ F src/date.c 126ba2ab10aeb2e7ba6e089b5f07b747c0625b8287f78b60da346eda8d23c875 F src/dbpage.c 80e46e1df623ec40486da7a5086cb723b0275a6e2a7b01d9f9b5da0f04ba2782 F src/dbstat.c 3b677254d512fcafd4d0b341bf267b38b235ccfddbef24f9154e19360fa22e43 F src/delete.c cb766727c78e715f9fb7ec8a7d03658ed2a3016343ca687acfcec9083cdca500 -F src/expr.c 27fdcdc65bca88934dfc4af0efe7a3eae095267bf7592b562abb6a11292c2b82 +F src/expr.c d7cfe9b9fe7ab47b254706589467d2e65fec3536b936d6f4eb28b84da6726ecc F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c a47610f0a5c6cb0ad79f8fcef039c01833dec0c751bb695f28dc0ec6a4c3ba00 F src/func.c 4204c56196847faefef57fa14e43b8e4d65eb8d7e65318abe463472e3fd148cb @@ -2179,8 +2179,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 2ff476eb3d1f4a2146f4a48b57895a00a3ff5beb29afa679ae53ea58cac07c76 -R dd6d36e36b292e54015829bdd4a764a6 +P ac6f095e13e43d66c06552c8b01f6bec3407c9d41a34c4cdb0be57b0b828ad0d +R 5e57ddae8e8fa784e790916f6a9e17d3 U drh -Z 67655d85fa3f7ad082be72ee3ee927a1 +Z 9ad56bfa46f009d741e8a52554c68de1 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 21dcd3d6f2..2ca2f7c4e3 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ac6f095e13e43d66c06552c8b01f6bec3407c9d41a34c4cdb0be57b0b828ad0d \ No newline at end of file +260bd764c3f2d6d067adb9cd0045b7c24d5e00b02ab2735b1cba455a6143ff4c \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index be8339c305..3a7065b21f 100644 --- a/src/expr.c +++ b/src/expr.c @@ -2387,7 +2387,7 @@ static SQLITE_NOINLINE int exprNodeIsConstantFunction( if( pDef==0 || pDef->xFinalize!=0 || (pDef->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG))==0 - || pExpr->y.pWin + || ExprHasProperty(pExpr, EP_WinFunc) ){ pWalker->eCode = 0; return WRC_Abort; From ac7c6f58540e07a1db2cda5ed58b5fe06fc23dd2 Mon Sep 17 00:00:00 2001 From: drh <> Date: Mon, 18 Mar 2024 13:31:24 +0000 Subject: [PATCH 30/34] Add assert() statements to validate access to the SrcItem.u1.nRow union member. FossilOrigin-Name: 21f616d9b948efca441f8d45d0a95f4c052ce8b6daec7fa582ad9a00b82ca570 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/insert.c | 2 +- src/printf.c | 1 + src/sqliteInt.h | 10 ++++++---- 5 files changed, 17 insertions(+), 14 deletions(-) diff --git a/manifest b/manifest index 5876e426d7..96cee0f9f8 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sthe\spatch\sat\s[10ee6fcba08ab128]\sso\sthat\sit\sworks\son\sreduced-size\sExpr\nnodes. -D 2024-03-18T13:10:54.954 +C Add\sassert()\sstatements\sto\svalidate\saccess\sto\sthe\sSrcItem.u1.nRow\sunion\smember. +D 2024-03-18T13:31:24.110 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -709,7 +709,7 @@ F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220 F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51 F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 -F src/insert.c 3b3661886b198d9c5e26c189a802782d35e6b415d0edf57af8c273225c2ae8f2 +F src/insert.c 59ae6959ccd23ea084159b4268d3fb5e6daffcc26b7cf1ad37201d823eecad82 F src/json.c e2e40760d6689134c3e2ece38c6a496b34ff5e2661a8f238444a119af666fdce F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36 @@ -746,7 +746,7 @@ F src/pcache1.c 602acb23c471bb8d557a6f0083cc2be641d6cafcafa19e481eba7ef4c9ca0f00 F src/pragma.c e8221d6310c9923c80f6fa6d09b7ea7c5263a671f53db8d0894df23efcdb617b F src/pragma.h e690a356c18e98414d2e870ea791c1be1545a714ba623719deb63f7f226d8bb7 F src/prepare.c 371f6115cb69286ebc12c6f2d7511279c2e47d9f54f475d46a554d687a3b312c -F src/printf.c aec4a5d743796be82d61c5d127d0f4615efbe61620a7a16968c5e2c9378ab37b +F src/printf.c 87b67bba3662a0523f39ae6b084a3907109702f717c654d6cecb838af5cd57f1 F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c F src/resolve.c ef87e3bc7700bfe761a7bbee2ce6084f1766dc816dd82a3ae77c133eec898432 F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97 @@ -755,7 +755,7 @@ F src/shell.c.in cf80c636bccb0ff9db46995e39d69ca21fde2a8a331d1691e4d62a69d7841c8 F src/sqlite.h.in 19a2db3995a699bd7f6dfb423856242bfceb7ec849a93c91d241d19fc28d9f0f F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54 -F src/sqliteInt.h f0014674d40b401795b4ff026fc4804aed3887f50d206fb221ddf4f2004bc3ef +F src/sqliteInt.h a58b4a33a9807667503a053721a4cd736cda8b60daae896a1b04f120a64c9fd2 F src/sqliteLimit.h 6878ab64bdeb8c24a1d762d45635e34b96da21132179023338c93f820eee6728 F src/status.c cb11f8589a6912af2da3bb1ec509a94dd8ef27df4d4c1a97e0bcf2309ece972b F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 @@ -2179,8 +2179,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 ac6f095e13e43d66c06552c8b01f6bec3407c9d41a34c4cdb0be57b0b828ad0d -R 5e57ddae8e8fa784e790916f6a9e17d3 +P 260bd764c3f2d6d067adb9cd0045b7c24d5e00b02ab2735b1cba455a6143ff4c +R 75dcb9b9acd93ebd15b87898d6bfec55 U drh -Z 9ad56bfa46f009d741e8a52554c68de1 +Z 5ddd66d0b5fd1a33a6a204e07bcebf08 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 2ca2f7c4e3..242c703a39 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -260bd764c3f2d6d067adb9cd0045b7c24d5e00b02ab2735b1cba455a6143ff4c \ No newline at end of file +21f616d9b948efca441f8d45d0a95f4c052ce8b6daec7fa582ad9a00b82ca570 \ No newline at end of file diff --git a/src/insert.c b/src/insert.c index 7256281fd2..be558be78d 100644 --- a/src/insert.c +++ b/src/insert.c @@ -698,7 +698,6 @@ Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow){ }else{ SrcItem *p = 0; /* SrcItem that reads from co-routine */ - if( pLeft->pSrc->nSrc==0 ){ /* Co-routine has not yet been started and the special Select object ** that accesses the co-routine has not yet been created. This block @@ -742,6 +741,7 @@ Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow){ } }else{ p = &pLeft->pSrc->a[0]; + assert( !p->fg.isTabFunc && !p->fg.isIndexedBy ); p->u1.nRow++; } diff --git a/src/printf.c b/src/printf.c index 0aea74e890..eb22ee320d 100644 --- a/src/printf.c +++ b/src/printf.c @@ -861,6 +861,7 @@ void sqlite3_str_vappendf( if( pSel->selFlags & SF_NestedFrom ){ sqlite3_str_appendf(pAccum, "(join-%u)", pSel->selId); }else if( pSel->selFlags & SF_MultiValue ){ + assert( !pItem->fg.isTabFunc && !pItem->fg.isIndexedBy ); sqlite3_str_appendf(pAccum, "%u-ROW VALUES CLAUSE", pItem->u1.nRow); }else{ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 01a5126499..8d18bfdfbb 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3270,10 +3270,12 @@ struct IdList { ** ** Union member validity: ** -** u1.zIndexedBy fg.isIndexedBy && !fg.isTabFunc -** u1.pFuncArg fg.isTabFunc && !fg.isIndexedBy -** u2.pIBIndex fg.isIndexedBy && !fg.isCte -** u2.pCteUse fg.isCte && !fg.isIndexedBy +** u1.zIndexedBy fg.isIndexedBy && !fg.isTabFunc +** u1.pFuncArg fg.isTabFunc && !fg.isIndexedBy +** u1.nRow !fg.isTabFunc && !fg.isIndexedBy +** +** u2.pIBIndex fg.isIndexedBy && !fg.isCte +** u2.pCteUse fg.isCte && !fg.isIndexedBy */ struct SrcItem { Schema *pSchema; /* Schema to which this item is fixed */ From b03805b70b1312dc92b6a394ac0d09be132e6a68 Mon Sep 17 00:00:00 2001 From: drh <> Date: Mon, 18 Mar 2024 15:10:00 +0000 Subject: [PATCH 31/34] Change a test case to use a window function rather than random() to disable the VALUES clause optimization. FossilOrigin-Name: c589149a138fa0a6be3153986fc0f315e052e13ebc0e7006b6529ca02bae413b --- manifest | 12 ++++++------ manifest.uuid | 2 +- test/values.test | 6 ++++-- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 96cee0f9f8..1e6486f30b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sassert()\sstatements\sto\svalidate\saccess\sto\sthe\sSrcItem.u1.nRow\sunion\smember. -D 2024-03-18T13:31:24.110 +C Change\sa\stest\scase\sto\suse\sa\swindow\sfunction\srather\sthan\srandom()\sto\sdisable\nthe\sVALUES\sclause\soptimization. +D 2024-03-18T15:10:00.843 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -1921,7 +1921,7 @@ F test/vacuum4.test 7ea76b769fffeb41f925303b04cbcf5a5bbeabe55e4c60ae754ff24eeeb7 F test/vacuum5.test 263b144d537e92ad8e9ca8a73cc6e1583f41cfd0dda9432b87f7806174a2f48c F test/vacuum6.test b137b04bf3392d3f5c3b8fda0ce85a6775a70ca112f6559f74ff52dc9ce042fd F test/vacuummem.test 4b30f5b95a9ff86e9d5c20741e50a898b2dc10b0962a3211571eb165357003fb -F test/values.test 77f72e80ad7b9e362e309bccb391307f41d0a41d1cd159cbdadb2de043505184 +F test/values.test 28aae97e976968c8540df0294c3f1cee80780c0df87101ca8969f184789f3029 F test/valuesfault.test 2ef23ed965e3bd08e268cdc38a0d11653390ddbbe1e8e2e98d16f55edd30f6e8 F test/varint.test bbce22cda8fc4d135bcc2b589574be8410614e62 F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661 @@ -2179,8 +2179,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 260bd764c3f2d6d067adb9cd0045b7c24d5e00b02ab2735b1cba455a6143ff4c -R 75dcb9b9acd93ebd15b87898d6bfec55 +P 21f616d9b948efca441f8d45d0a95f4c052ce8b6daec7fa582ad9a00b82ca570 +R 8397e730ec47ff60644573ff69916492 U drh -Z 5ddd66d0b5fd1a33a6a204e07bcebf08 +Z 4aa38dc309434c1f95f0da72b0b4ecc4 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 242c703a39..168fa1695d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -21f616d9b948efca441f8d45d0a95f4c052ce8b6daec7fa582ad9a00b82ca570 \ No newline at end of file +c589149a138fa0a6be3153986fc0f315e052e13ebc0e7006b6529ca02bae413b \ No newline at end of file diff --git a/test/values.test b/test/values.test index 8365584b4a..14b242c9ec 100644 --- a/test/values.test +++ b/test/values.test @@ -457,14 +457,16 @@ do_eqp_test 15.3 { do_eqp_test 15.4 { INSERT INTO t1 VALUES (1,2),(3,4),(7,8), - (5,coalesce(6,random())); + (5,row_number()OVER()); } { QUERY PLAN `--COMPOUND QUERY |--LEFT-MOST SUBQUERY | `--SCAN 3-ROW VALUES CLAUSE `--UNION ALL - `--SCAN CONSTANT ROW + |--CO-ROUTINE (subquery-xxxxxx) + | `--SCAN CONSTANT ROW + `--SCAN (subquery-xxxxxx) } do_eqp_test 15.5 { SELECT * FROM (VALUES(1),(2),(3),(4),(5),(6)), (VALUES('a'),('b'),('c')); From c195e2374b63d29190e00a74482238eaf426d73f Mon Sep 17 00:00:00 2001 From: drh <> Date: Mon, 18 Mar 2024 16:30:00 +0000 Subject: [PATCH 32/34] Allow the VALUES-as-coroutine optimization to be applied to later rows of a VALUES clause even if earlier rows do not qualify. FossilOrigin-Name: 9a47ea7f0f675f7bf4710901487ce34c7689e618cd1d8b9f94f0ff7ebc3f2841 --- manifest | 14 ++++---- manifest.uuid | 2 +- src/insert.c | 9 +++-- test/values.test | 91 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 106 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 1e6486f30b..e3e832688e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\sa\stest\scase\sto\suse\sa\swindow\sfunction\srather\sthan\srandom()\sto\sdisable\nthe\sVALUES\sclause\soptimization. -D 2024-03-18T15:10:00.843 +C Allow\sthe\sVALUES-as-coroutine\soptimization\sto\sbe\sapplied\sto\slater\srows\sof\na\sVALUES\sclause\seven\sif\searlier\srows\sdo\snot\squalify. +D 2024-03-18T16:30:00.996 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -709,7 +709,7 @@ F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220 F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51 F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 -F src/insert.c 59ae6959ccd23ea084159b4268d3fb5e6daffcc26b7cf1ad37201d823eecad82 +F src/insert.c a71901268468aff9bc5d4034209026b45a0163c7a21422337de21940c8ab5310 F src/json.c e2e40760d6689134c3e2ece38c6a496b34ff5e2661a8f238444a119af666fdce F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36 @@ -1921,7 +1921,7 @@ F test/vacuum4.test 7ea76b769fffeb41f925303b04cbcf5a5bbeabe55e4c60ae754ff24eeeb7 F test/vacuum5.test 263b144d537e92ad8e9ca8a73cc6e1583f41cfd0dda9432b87f7806174a2f48c F test/vacuum6.test b137b04bf3392d3f5c3b8fda0ce85a6775a70ca112f6559f74ff52dc9ce042fd F test/vacuummem.test 4b30f5b95a9ff86e9d5c20741e50a898b2dc10b0962a3211571eb165357003fb -F test/values.test 28aae97e976968c8540df0294c3f1cee80780c0df87101ca8969f184789f3029 +F test/values.test e7c156f92d32ed645908fbad0a1144f0f31650376cdcb212fde701978c89d3b1 F test/valuesfault.test 2ef23ed965e3bd08e268cdc38a0d11653390ddbbe1e8e2e98d16f55edd30f6e8 F test/varint.test bbce22cda8fc4d135bcc2b589574be8410614e62 F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661 @@ -2179,8 +2179,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 21f616d9b948efca441f8d45d0a95f4c052ce8b6daec7fa582ad9a00b82ca570 -R 8397e730ec47ff60644573ff69916492 +P c589149a138fa0a6be3153986fc0f315e052e13ebc0e7006b6529ca02bae413b +R 940f14de84991bdaec1e3874c3d6141e U drh -Z 4aa38dc309434c1f95f0da72b0b4ecc4 +Z d0598787dc817aed0c423e65e0b46555 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 168fa1695d..c08cd51c0e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c589149a138fa0a6be3153986fc0f315e052e13ebc0e7006b6529ca02bae413b \ No newline at end of file +9a47ea7f0f675f7bf4710901487ce34c7689e618cd1d8b9f94f0ff7ebc3f2841 \ No newline at end of file diff --git a/src/insert.c b/src/insert.c index be558be78d..a87d714a0c 100644 --- a/src/insert.c +++ b/src/insert.c @@ -670,8 +670,7 @@ static int exprListIsNoAffinity(Parse *pParse, ExprList *pRow){ */ Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow){ - if( pLeft->pPrior /* co-routine precluded by prior row */ - || pParse->bHasWith /* condition (a) above */ + if( pParse->bHasWith /* condition (a) above */ || pParse->db->init.busy /* condition (b) above */ || exprListIsConstant(pParse,pRow)==0 /* condition (c) above */ || (pLeft->pSrc->nSrc==0 && @@ -714,6 +713,12 @@ Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow){ if( pRet ){ SelectDest dest; pRet->pSrc->nSrc = 1; + pRet->pPrior = pLeft->pPrior; + pRet->op = pLeft->op; + pLeft->pPrior = 0; + pLeft->op = TK_SELECT; + assert( pLeft->pNext==0 ); + assert( pRet->pNext==0 ); p = &pRet->pSrc->a[0]; p->pSelect = pLeft; p->fg.viaCoroutine = 1; diff --git a/test/values.test b/test/values.test index 14b242c9ec..43f8e0e6fe 100644 --- a/test/values.test +++ b/test/values.test @@ -489,4 +489,95 @@ do_eqp_test 15.7 { `--SCAN 4-ROW VALUES CLAUSE } +#-------------------------------------------------------------------------- +# The VALUES-as-coroutine optimization can be applied to later rows of +# a VALUES clause even if earlier rows do not qualify. +# +reset_db +do_execsql_test 16.1 { + CREATE TABLE t1(a,b); +} +do_execsql_test 16.2 { + BEGIN; + INSERT INTO t1 VALUES(1,2),(3,4),(5,6), + (7,row_number()OVER()), + (9,10), (11,12), (13,14), (15,16); + SELECT * FROM t1 ORDER BY a, b; + ROLLBACK; +} {1 2 3 4 5 6 7 1 9 10 11 12 13 14 15 16} +do_eqp_test 16.3 { + INSERT INTO t1 VALUES(1,2),(3,4),(5,6), + (7,row_number()OVER()), + (9,10), (11,12), (13,14), (15,16); +} { + QUERY PLAN + `--COMPOUND QUERY + |--LEFT-MOST SUBQUERY + | `--SCAN 3-ROW VALUES CLAUSE + |--UNION ALL + | |--CO-ROUTINE (subquery-xxxxxx) + | | `--SCAN CONSTANT ROW + | `--SCAN (subquery-xxxxxx) + `--UNION ALL + `--SCAN 4-ROW VALUES CLAUSE +} +do_execsql_test 16.4 { + BEGIN; + INSERT INTO t1 VALUES + (1,row_number()OVER()), + (2,3), (4,5), (6,7); + SELECT * FROM t1 ORDER BY a, b; + ROLLBACK; +} {1 1 2 3 4 5 6 7} +do_eqp_test 16.5 { + INSERT INTO t1 VALUES + (1,row_number()OVER()), + (2,3), (4,5), (6,7); +} { + QUERY PLAN + `--COMPOUND QUERY + |--LEFT-MOST SUBQUERY + | |--CO-ROUTINE (subquery-xxxxxx) + | | `--SCAN CONSTANT ROW + | `--SCAN (subquery-xxxxxx) + `--UNION ALL + `--SCAN 3-ROW VALUES CLAUSE +} +do_execsql_test 16.6 { + BEGIN; + INSERT INTO t1 VALUES + (1,2),(3,4), + (5,row_number()OVER()), + (7,8),(9,10),(11,12), + (13,row_number()OVER()), + (15,16),(17,18),(19,20),(21,22); + SELECT * FROM t1 ORDER BY a, b; + ROLLBACK; +} { 1 2 3 4 5 1 7 8 9 10 11 12 13 1 15 16 17 18 19 20 21 22} +do_eqp_test 16.7 { + INSERT INTO t1 VALUES + (1,2),(3,4), + (5,row_number()OVER()), + (7,8),(9,10),(11,12), + (13,row_number()OVER()), + (15,16),(17,18),(19,20),(21,22); +} { + QUERY PLAN + `--COMPOUND QUERY + |--LEFT-MOST SUBQUERY + | `--SCAN 2-ROW VALUES CLAUSE + |--UNION ALL + | |--CO-ROUTINE (subquery-xxxxxx) + | | `--SCAN CONSTANT ROW + | `--SCAN (subquery-xxxxxx) + |--UNION ALL + | `--SCAN 3-ROW VALUES CLAUSE + |--UNION ALL + | |--CO-ROUTINE (subquery-xxxxxx) + | | `--SCAN CONSTANT ROW + | `--SCAN (subquery-xxxxxx) + `--UNION ALL + `--SCAN 4-ROW VALUES CLAUSE +} + finish_test From 2ad2584581992f59543bc00c3be313d29448aeb0 Mon Sep 17 00:00:00 2001 From: drh <> Date: Mon, 18 Mar 2024 17:13:52 +0000 Subject: [PATCH 33/34] Fix harmless compiler (scan-build) warnings. FossilOrigin-Name: c86f9f2a15ffc726b7f0d9bba5a8c4dfdaeea6a297e0b591c554fff3d1fe6e1c --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/insert.c | 6 +++--- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index e3e832688e..1e94c6c964 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Allow\sthe\sVALUES-as-coroutine\soptimization\sto\sbe\sapplied\sto\slater\srows\sof\na\sVALUES\sclause\seven\sif\searlier\srows\sdo\snot\squalify. -D 2024-03-18T16:30:00.996 +C Fix\sharmless\scompiler\s(scan-build)\swarnings. +D 2024-03-18T17:13:52.924 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -709,7 +709,7 @@ F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220 F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51 F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 -F src/insert.c a71901268468aff9bc5d4034209026b45a0163c7a21422337de21940c8ab5310 +F src/insert.c 06ce505713e86172612f9e01febefd2d3331d1f70461b4ada0eae5a76bb6349f F src/json.c e2e40760d6689134c3e2ece38c6a496b34ff5e2661a8f238444a119af666fdce F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36 @@ -2179,8 +2179,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 c589149a138fa0a6be3153986fc0f315e052e13ebc0e7006b6529ca02bae413b -R 940f14de84991bdaec1e3874c3d6141e +P 9a47ea7f0f675f7bf4710901487ce34c7689e618cd1d8b9f94f0ff7ebc3f2841 +R 99b0c172599c8a90caf2454e462eb6ef U drh -Z d0598787dc817aed0c423e65e0b46555 +Z e6f67e954fdd4f797f1644f6604d7595 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index c08cd51c0e..7f56713a39 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9a47ea7f0f675f7bf4710901487ce34c7689e618cd1d8b9f94f0ff7ebc3f2841 \ No newline at end of file +c86f9f2a15ffc726b7f0d9bba5a8c4dfdaeea6a297e0b591c554fff3d1fe6e1c \ No newline at end of file diff --git a/src/insert.c b/src/insert.c index a87d714a0c..fe7ba05dc1 100644 --- a/src/insert.c +++ b/src/insert.c @@ -751,6 +751,7 @@ Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow){ } if( pParse->nErr==0 ){ + assert( p!=0 ); if( p->pSelect->pEList->nExpr!=pRow->nExpr ){ sqlite3SelectWrongNumTermsError(pParse, p->pSelect); }else{ @@ -1099,7 +1100,6 @@ void sqlite3Insert( if( pSelect ){ /* Data is coming from a SELECT or from a multi-row VALUES clause. ** Generate a co-routine to run the SELECT. */ - int regYield; /* Register holding co-routine entry-point */ int rc; /* Result code */ if( pSelect->pSrc->nSrc==1 @@ -1107,7 +1107,7 @@ void sqlite3Insert( && pSelect->pPrior==0 ){ SrcItem *pItem = &pSelect->pSrc->a[0]; - dest.iSDParm = regYield = pItem->regReturn; + dest.iSDParm = pItem->regReturn; regFromSelect = pItem->regResult; nColumn = pItem->pSelect->pEList->nExpr; ExplainQueryPlan((pParse, 0, "SCAN %S", pItem)); @@ -1118,7 +1118,7 @@ void sqlite3Insert( } }else{ int addrTop; /* Top of the co-routine */ - regYield = ++pParse->nMem; + int regYield = ++pParse->nMem; addrTop = sqlite3VdbeCurrentAddr(v) + 1; sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop); sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield); From fc2d862318876ff36910b57f8ecafdda8d36fa59 Mon Sep 17 00:00:00 2001 From: drh <> Date: Mon, 18 Mar 2024 18:03:17 +0000 Subject: [PATCH 34/34] Remove unnecessary blank lines from build commands in the default Makefile.in. FossilOrigin-Name: 76fb3a908f45230b956cb659c754e47603e80aa72a2aad50d479437a9c013f61 --- Makefile.in | 6 ++---- manifest | 13 ++++++------- manifest.uuid | 2 +- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/Makefile.in b/Makefile.in index e16fa94345..c16e1c127d 100644 --- a/Makefile.in +++ b/Makefile.in @@ -817,8 +817,7 @@ has_tclsh85: touch .target_source sqlite3.c: .target_source $(TOP)/tool/mksqlite3c.tcl src-verify has_tclsh84 - $(TCLSH_CMD) $(TOP)/tool/mksqlite3c.tcl $(AMALGAMATION_LINE_MACROS) \ - $(EXTRA_SRC) + $(TCLSH_CMD) $(TOP)/tool/mksqlite3c.tcl $(AMALGAMATION_LINE_MACROS) $(EXTRA_SRC) cp tsrc/sqlite3ext.h . cp $(TOP)/ext/session/sqlite3session.h . @@ -829,8 +828,7 @@ sqlite3r.c: sqlite3.c sqlite3r.h has_tclsh84 cp $(TOP)/ext/recover/sqlite3recover.c tsrc/ cp $(TOP)/ext/recover/sqlite3recover.h tsrc/ cp $(TOP)/ext/recover/dbdata.c tsrc/ - $(TCLSH_CMD) $(TOP)/tool/mksqlite3c.tcl --enable-recover \ - $(AMALGAMATION_LINE_MACROS) $(EXTRA_SRC) + $(TCLSH_CMD) $(TOP)/tool/mksqlite3c.tcl --enable-recover $(AMALGAMATION_LINE_MACROS) $(EXTRA_SRC) sqlite3ext.h: .target_source cp tsrc/sqlite3ext.h . diff --git a/manifest b/manifest index 55bb6354bf..68196a51d6 100644 --- a/manifest +++ b/manifest @@ -1,9 +1,9 @@ -C Add\sthe\s"VALUES-as-coroutine"\soptimization.\s\sLarge\sVALUES\sclauses\son\san\nINSERT,\sfor\sexample,\sprepare\sand\srun\sin\sabout\shalf\sthe\stime\sand\swith\shalf\nthe\smemory.\s\sThis\scheck-in\salso\sincludes\senhancements\sto\sthe\sinternal\nsqlite3ExprIsConstant()\sroutine\sto\srecognize\spure\sSQL\sfunctions\sas\sconstant\nif\sthey\shave\sconstant\sarguments. -D 2024-03-18T18:00:17.106 +C Remove\sunnecessary\sblank\slines\sfrom\sbuild\scommands\sin\sthe\sdefault\sMakefile.in. +D 2024-03-18T18:03:17.115 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 -F Makefile.in 5f2389d2a3c44b56621bb5156a9cb6e2bef01f7ec14a19335b1559cf0474bdde +F Makefile.in 993a7874e3d3721df61846f03dda4a9ef7490da11953ae36ba1bb0c0346eaf4a F Makefile.linux-gcc f3842a0b1efbfbb74ac0ef60e56b301836d05b4d867d014f714fa750048f1ab6 F Makefile.msc e64a52619310d3067f6c38f56eedd15918a82dade70954197d6da486ad99d7f4 F README.md 6358805260a03ebead84e168bbf3740ddf3f683b477e478567186aa7afb490d3 @@ -2179,9 +2179,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 82035b9cfd28ef6b0ecc6f469f03d2b001189aa4925147cdb784b6b1964eb3b2 c86f9f2a15ffc726b7f0d9bba5a8c4dfdaeea6a297e0b591c554fff3d1fe6e1c -R d086636689a6bb7c4b198edffb3a7c63 -T +closed c86f9f2a15ffc726b7f0d9bba5a8c4dfdaeea6a297e0b591c554fff3d1fe6e1c +P a120c9235f125e05be494038c16a9dd326fd79837698bef17e7879cd0cd75831 +R 8ff4324227d383f5da29d0bfe203141e U drh -Z 48e8dd6fe42c5583ed5ba3f909ede536 +Z 25814839eb089de12c64c949b849b19e # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 82d6efaeee..73c10f1cd5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a120c9235f125e05be494038c16a9dd326fd79837698bef17e7879cd0cd75831 \ No newline at end of file +76fb3a908f45230b956cb659c754e47603e80aa72a2aad50d479437a9c013f61 \ No newline at end of file