From: drh <> Date: Fri, 9 Aug 2024 01:38:14 +0000 (+0000) Subject: If there is any question about whether or not the WHERE_IDX_ONLY flag in the X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3a37a3a5b8768b8428025f45d19d6a99f2f3bfb5;p=thirdparty%2Fsqlite.git If there is any question about whether or not the WHERE_IDX_ONLY flag in the query planner is correct, create a backup null-cursor for the table, so that we never try to run an OP_Column against an unopened cursor. FossilOrigin-Name: 7f1617f7bf53cf96954541f73fb99622051f86be9c8ea4b8038b2aa7c8f49e47 --- diff --git a/manifest b/manifest index 173aea971f..4fa08baaa5 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Ensure\ssqlite3expert.c\sunregisters\sany\sSQL\suser-functions\sit\sregisters\swith\sthe\sdatabase\shandle\sbefore\sreturning. -D 2024-08-08T15:26:11.708 +C If\sthere\sis\sany\squestion\sabout\swhether\sor\snot\sthe\sWHERE_IDX_ONLY\sflag\sin\sthe\nquery\splanner\sis\scorrect,\screate\sa\sbackup\snull-cursor\sfor\sthe\stable,\sso\sthat\nwe\snever\stry\sto\srun\san\sOP_Column\sagainst\san\sunopened\scursor. +D 2024-08-09T01:38:14.598 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -710,7 +710,7 @@ F src/date.c 13dd752847afb32ed70510ad7345a5b9c841f51ad904dba5d010f1fa3a6a324e F src/dbpage.c 80e46e1df623ec40486da7a5086cb723b0275a6e2a7b01d9f9b5da0f04ba2782 F src/dbstat.c 3b677254d512fcafd4d0b341bf267b38b235ccfddbef24f9154e19360fa22e43 F src/delete.c cb766727c78e715f9fb7ec8a7d03658ed2a3016343ca687acfcec9083cdca500 -F src/expr.c fe958028b36af640b70b2174354c044f75b8c4a4645c921592122aa2a022083a +F src/expr.c 79ac19d455e14b3ca52812f4cc0b3d694b5b9074442e9e643601439f05086f20 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c 852f93c0ef995e0c2b8983059a2b97151c194cc8259e21f5bc2b7ac508348c2a F src/func.c 1f61e32e7a357e615b5d2e774bee563761fce4f2fd97ecb0f72c33e62a2ada5f @@ -846,7 +846,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 5bbe53db73ae6c8ee34a5eab693a5586ad8ff4f094ff0e524df965b683bec884 +F src/where.c b1c25ee0a1e9546a8929b00e59abc62c4421068ba74b1d20c87e448543506cef F src/whereInt.h 002adc3aa2cc10733b9b27958fdbe893987cd989fab25a9853941c1f9b9b0a65 F src/wherecode.c c9cac0b0b8e809c5e7e79d7796918907fb685ad99be2aaa9737f9787aa47349c F src/whereexpr.c 7d0d34b42b9edfd8e8ca66beb3a6ef63fe211c001af54caf2ccbcd989b783290 @@ -2204,8 +2204,11 @@ F vsixtest/vsixtest.tcl 6195aba1f12a5e10efc2b8c0009532167be5e301abe5b31385638080 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 797b0a13fd7a42b0a48ecbf0cd1961aa932da3e9c9ccffd903a3a4d963d0cc54 -R 524433c41a8ffc46e95c387bd9dc2975 -U dan -Z fa7382f01ce16aee65751b978df534e7 +P 123b154ce3b6fee1bbf483704812bd6f8538966f9687520b4470d700f0270719 +R 3ee712d9b08c2746de61c5d667402293 +T *branch * defensive-null-cursor +T *sym-defensive-null-cursor * +T -sym-trunk * +U drh +Z d76829c48a82072ec06d5f57872d0f44 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index f7625aad27..7843036483 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -123b154ce3b6fee1bbf483704812bd6f8538966f9687520b4470d700f0270719 +7f1617f7bf53cf96954541f73fb99622051f86be9c8ea4b8038b2aa7c8f49e47 diff --git a/src/expr.c b/src/expr.c index 53b0170ab4..f94472a894 100644 --- a/src/expr.c +++ b/src/expr.c @@ -5439,6 +5439,13 @@ expr_code_doover: break; } #endif + + /* Special opcode used to generate a cursor that always returns NULL. + ** Used by the sqlite3OpenNullCursor() routine. */ + case TK_TABLE: { + sqlite3VdbeAddOp3(v, OP_OpenPseudo, pExpr->iTable, 0, 1); + break; + } } sqlite3ReleaseTempReg(pParse, regFree1); sqlite3ReleaseTempReg(pParse, regFree2); diff --git a/src/where.c b/src/where.c index c850121c34..2d6e95611d 100644 --- a/src/where.c +++ b/src/where.c @@ -7098,6 +7098,20 @@ static int cursorIsOpen(Vdbe *v, int iCur, int k){ } #endif /* SQLITE_DEBUG */ +/* +** Make arrangements to open cursor number iCur in the startup code of +** the prepared statement. This cursor will always returns NULL +** for any OP_Column opcode. +*/ +static SQLITE_NOINLINE void sqlite3OpenNullCursor(Parse *pParse, int iCur){ + Expr e; + memset(&e, 0, sizeof(e)); + e.op = TK_TABLE; + e.iTable = iCur; + sqlite3ExprCodeRunJustOnce(pParse, &e, -1); +} + + /* ** Generate the end of the WHERE loop. See comments on ** sqlite3WhereBegin() for additional information. @@ -7376,37 +7390,34 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){ assert( pIdx->pTable==pTab ); #ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC if( pOp->opcode==OP_Offset ){ - /* Do not need to translate the column number */ + x = 0; }else #endif - if( !HasRowid(pTab) ){ - Index *pPk = sqlite3PrimaryKeyIndex(pTab); - x = pPk->aiColumn[x]; - assert( x>=0 ); - }else{ - testcase( x!=sqlite3StorageColumnToTable(pTab,x) ); - x = sqlite3StorageColumnToTable(pTab,x); + { + if( !HasRowid(pTab) ){ + Index *pPk = sqlite3PrimaryKeyIndex(pTab); + x = pPk->aiColumn[x]; + assert( x>=0 ); + }else{ + testcase( x!=sqlite3StorageColumnToTable(pTab,x) ); + x = sqlite3StorageColumnToTable(pTab,x); + } + x = sqlite3TableColumnToIndex(pIdx, x); } - x = sqlite3TableColumnToIndex(pIdx, x); if( x>=0 ){ pOp->p2 = x; pOp->p1 = pLevel->iIdxCur; OpcodeRewriteTrace(db, k, pOp); - }else{ - /* Unable to translate the table reference into an index - ** reference. Verify that this is harmless - that the - ** table being referenced really is open. - */ -#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC - assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 - || cursorIsOpen(v,pOp->p1,k) - || pOp->opcode==OP_Offset - ); -#else - assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 - || cursorIsOpen(v,pOp->p1,k) - ); -#endif + }else if( pLoop->wsFlags & WHERE_IDX_ONLY ){ + OpcodeRewriteTrace(db, k, pOp); + assert( cursorIsOpen(v,pOp->p1,k) ); + + /* This following call to sqlite3OpenNullCursor() is defensive + ** code. The null cursor should never be used, unless there is + ** a bug in the covering-index logic of the query planner, in + ** which case the null cursor might prevent a NULL-pointer + ** dereference in OP_Column. */ + sqlite3OpenNullCursor(pParse, pLevel->iTabCur); } }else if( pOp->opcode==OP_Rowid ){ pOp->p1 = pLevel->iIdxCur;