]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
If there is any question about whether or not the WHERE_IDX_ONLY flag in the
authordrh <>
Fri, 9 Aug 2024 01:38:14 +0000 (01:38 +0000)
committerdrh <>
Fri, 9 Aug 2024 01:38:14 +0000 (01:38 +0000)
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

manifest
manifest.uuid
src/expr.c
src/where.c

index 173aea971f795920f5aea7353f0d7a3f3fc483ac..4fa08baaa5fce2e4f6f5f3d7f73bd66a74f70477 100644 (file)
--- 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.
index f7625aad2727def1f7969f62103581147c2cfc64..784303648376f450d69f5ab0e1255e2ca65aeb83 100644 (file)
@@ -1 +1 @@
-123b154ce3b6fee1bbf483704812bd6f8538966f9687520b4470d700f0270719
+7f1617f7bf53cf96954541f73fb99622051f86be9c8ea4b8038b2aa7c8f49e47
index 53b0170ab4ec040398417e2338d7a70992db1c26..f94472a894032df794a637d61b638e69e9e65363 100644 (file)
@@ -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);
index c850121c3405fe1b9a79db16477d60c83bc170e7..2d6e95611d6b26aca51f3001052784c98281a940 100644 (file)
@@ -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;