]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix ticket #1046 by removing code and simplifying the query optimizer.
authordrh <drh@noemail.net>
Sat, 25 Dec 2004 01:03:13 +0000 (01:03 +0000)
committerdrh <drh@noemail.net>
Sat, 25 Dec 2004 01:03:13 +0000 (01:03 +0000)
Remarkably, this simplification also makes the optimizer do a better job.
Ticket #1051 was fixed as a side-effect. (CVS 2172)

FossilOrigin-Name: 5fd1f4711885e3dd6fb2c2700287f78bb0ea178a

manifest
manifest.uuid
src/delete.c
src/pragma.c
src/select.c
src/sqliteInt.h
src/update.c
src/util.c
src/vdbe.c
src/where.c

index 1effda3b28112d8b28dd4ea70d197aaff5b959c2..07e2fb3c46a0528b159e3e2de6ca74f1faccef24 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Add\sPRAGMA\s'temp_store_directory'.\s\sAdded\sos_*.c\sfunction\nsqlite3OsIsDirWritable(),\ssplit\spragma.c\schangeTempStorage()\sfunction\sinto\ninvalidateTempStorage().\s(CVS\s2171)
-D 2004-12-20T19:01:32
+C Fix\sticket\s#1046\sby\sremoving\scode\sand\ssimplifying\sthe\squery\soptimizer.\nRemarkably,\sthis\ssimplification\salso\smakes\sthe\soptimizer\sdo\sa\sbetter\sjob.\nTicket\s#1051\swas\sfixed\sas\sa\sside-effect.\s(CVS\s2172)
+D 2004-12-25T01:03:14
 F Makefile.in 02a184d734a2b4bbbc1ecc2e3ef504fcb13de069
 F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457
 F README a01693e454a00cc117967e3f9fdab2d4d52e9bc1
@@ -34,7 +34,7 @@ F src/btree.h 861e40b759a195ba63819740e484390012cf81ab
 F src/build.c af1296e8a21a406b4f4c4f1e1365e075071219f3
 F src/cursor.c f883813759742068890b1f699335872bfa8fdf41
 F src/date.c 65536e7ea04fdde6e0551264fca15966966e171f
-F src/delete.c 6debe7893fa09bb5b386df0f26165f13132423e6
+F src/delete.c 5e5bcf0092b146a399e571d1e704b3b22633d2d0
 F src/expr.c d718509e56f58b06bc5f9b46afb295675334d544
 F src/func.c b668e5ad043176049454c95a6a780367a0e8f6bb
 F src/hash.c a97721a55440b7bea31ffe471bb2f6b4123cddd5
@@ -56,13 +56,13 @@ F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
 F src/pager.c 7b4dc9a94228efde924f1d9f4b7751f332da4587
 F src/pager.h 9eba8c53dd91eae7f3f90743b2ee242da02a9862
 F src/parse.y ceba179b9703657180963568f54b0e75f33e36e1
-F src/pragma.c 639a7e7ef0999211aafa1f3d474ecc7241033cb9
+F src/pragma.c 0394f9361a497b7f74c1e5909bfc95a1f5bf0ce4
 F src/printf.c 3d20b21cfecadacecac3fb7274e746cb81d3d357
 F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3
-F src/select.c ac6610b4b2c5bd5ffc46536b760dacc420119dac
+F src/select.c 080c0d1d684ff6154a2f042347f34bc07e50590c
 F src/shell.c e8f4f486cbf6e60d81173146ac8a6522c930fa51
 F src/sqlite.h.in 0d5e48e506845b74a845c9470e01d3f472b59611
-F src/sqliteInt.h a922cfd13711c68538684619fb15a4d262b12b9d
+F src/sqliteInt.h ef924e4a1a4b69d68f01af3242ab080de6069131
 F src/table.c 25b3ff2b39b7d87e8d4a5da0713d68dfc06cbee9
 F src/tclsqlite.c 3a4044ef609565c8cc51e887d8b96933ba9f3b5c
 F src/test1.c b7d94c54e58f95452387a5cabdf98b2be8059f29
@@ -72,17 +72,17 @@ F src/test4.c 7c6b9fc33dd1f3f93c7f1ee6e5e6d016afa6c1df
 F src/test5.c 64f08b2a50ef371a1bd68ff206829e7b1b9997f5
 F src/tokenize.c 2ad3d1ae1a0a70746db0b31a0a74f58050a3c39a
 F src/trigger.c 98f3b07c08ba01b34cff139ef9687883d325ae8e
-F src/update.c aa92fa2203b2233008dd75a1e97c4b441be24a7f
+F src/update.c 0979397c41ac29c54fe0cc687a356d8629a633af
 F src/utf.c e45ce11be6922408cd381561721f6cca7d3b992a
-F src/util.c 4a8db4e97a3cfda12ad8dda3e77dd2d00ad1de5e
+F src/util.c 29f43c4a7b9ff29302f7899f793be6836b6cd7f9
 F src/vacuum.c 705256e1111521fa04f0029de7f1667bc131d015
-F src/vdbe.c caeb3f88d9a027d300c8fd27cf885ca964e5354e
+F src/vdbe.c 40ab8e30eca1ed0e5d9e17b6d835660edf14c7c2
 F src/vdbe.h 067ca8d6750ba4f69a50284765e5883dee860181
 F src/vdbeInt.h 0f74561e629af86172de7cdf0ecaea014c51696c
 F src/vdbeapi.c 0cf3bdc1072616bedc8eec7fc22e3f5a169d33fd
 F src/vdbeaux.c a7c4c90786e2633b38f2d89f3dc49aed747454e4
 F src/vdbemem.c 5876c8abf4374fef671f4fd8dc333ef3fc95a2f0
-F src/where.c e4a34a8fd159d5ca59f87bb689bb513f1a2620df
+F src/where.c 5307677f772a7b44628e65383c30697dee9a63f3
 F tclinstaller.tcl 36478c3bbfc5b93ceac42d94e3c736937b808432
 F test/all.test 929bfa932b55e75c96fe2203f7650ba451c1862c
 F test/alter.test 95c57a4f461fa81293e0dccef7f83889aadb169a
@@ -263,7 +263,7 @@ F www/tclsqlite.tcl e73f8f8e5f20e8277619433f7970060ab01088fc
 F www/vdbe.tcl 095f106d93875c94b47367384ebc870517431618
 F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0
 F www/whentouse.tcl fdacb0ba2d39831e8a6240d05a490026ad4c4e4c
-P e5aa489453bf31126da6473ef93c89ec27935cde
-R 80852dba2ab3f55be612ddeeffa02604
-U tpoindex
-Z 5d44d728827caef4bb2a5da252002b6d
+P 772e22cbd69463be41c2e73b4fd4eb33946193c4
+R 1a0697c736404780d6feff68a7939368
+U drh
+Z 1ae722789e543e8f74d632edf76f862b
index a08b47c486af9c7d6a245c2e53c690995a2a9271..8e9d964100c4d4d22a43562b6f98887e4d411e03 100644 (file)
@@ -1 +1 @@
-772e22cbd69463be41c2e73b4fd4eb33946193c4
\ No newline at end of file
+5fd1f4711885e3dd6fb2c2700287f78bb0ea178a
\ No newline at end of file
index 41dbca16ddda16fec42829a06f32a2d9870a2842..f786bdd78a08b016b877d7d556e668b3f560b036 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains C code routines that are called by the parser
 ** in order to generate code for DELETE FROM statements.
 **
-** $Id: delete.c,v 1.93 2004/12/14 03:34:34 drh Exp $
+** $Id: delete.c,v 1.94 2004/12/25 01:03:14 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -225,11 +225,12 @@ void sqlite3DeleteFrom(
 
     /* Begin the database scan
     */
-    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 1, 0, 0);
+    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0);
     if( pWInfo==0 ) goto delete_from_cleanup;
 
-    /* Remember the key of every item to be deleted.
+    /* Remember the rowid of every item to be deleted.
     */
+    sqlite3VdbeAddOp(v, OP_Recno, iCur, 0);
     sqlite3VdbeAddOp(v, OP_ListWrite, 0, 0);
     if( db->flags & SQLITE_CountRows ){
       sqlite3VdbeAddOp(v, OP_AddImm, 1, 0);
index 5589e9317db6faa2973e904758768df06f17dc45..51f7f43a20049c3314832a7e50e5a5ecceb2ac0c 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** This file contains code used to implement the PRAGMA command.
 **
-** $Id: pragma.c,v 1.80 2004/12/20 19:01:33 tpoindex Exp $
+** $Id: pragma.c,v 1.81 2004/12/25 01:03:14 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -389,14 +389,14 @@ void sqlite3Pragma(
         if( sqlite3_temp_directory ){
           if( strlen(sqlite3_temp_directory) < strlen(zRight) + 1){
             sqlite3FreeX(sqlite3_temp_directory);
-            sqlite3_temp_directory = sqlite3Malloc( strlen(zRight) + 1 );
+            sqlite3_temp_directory = sqliteMalloc( strlen(zRight) + 1 );
             if( sqlite3_temp_directory==0 ){
               goto pragma_out;
             }
             sqlite3_temp_directory[0] = '\0';
           }
         }else{
-          sqlite3_temp_directory = sqlite3Malloc( strlen(zRight) + 1 );
+          sqlite3_temp_directory = sqliteMalloc( strlen(zRight) + 1 );
           if( sqlite3_temp_directory==0 ){
             goto pragma_out;
           }
index a2a4d5e3421b4aad91ad299892a4f8a4e463251f..a889fc58eb71342a515ccefbf9e60e62980bfc4b 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains C code routines that are called by the parser
 ** to handle SELECT statements in SQLite.
 **
-** $Id: select.c,v 1.218 2004/12/16 21:09:17 drh Exp $
+** $Id: select.c,v 1.219 2004/12/25 01:03:14 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -2549,7 +2549,7 @@ int sqlite3Select(
 
   /* Begin the database scan
   */
-  pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0,
+  pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere,
                              pGroupBy ? 0 : &pOrderBy, p->pFetch);
   if( pWInfo==0 ) goto select_end;
 
index fbfd184b709b8b849337c79ea9707131c6569429..35b1bad1724ec59d2eda1ba10f54d8b9b78244e2 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.348 2004/12/19 00:11:35 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.349 2004/12/25 01:03:14 drh Exp $
 */
 #ifndef _SQLITEINT_H_
 #define _SQLITEINT_H_
@@ -1359,7 +1359,7 @@ void sqlite3OpenTableForReading(Vdbe*, int iCur, Table*);
 void sqlite3OpenTable(Vdbe*, int iCur, Table*, int);
 void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
 void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
-WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, int, ExprList**, Fetch*);
+WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**, Fetch*);
 void sqlite3WhereEnd(WhereInfo*);
 void sqlite3ExprCode(Parse*, Expr*);
 void sqlite3ExprCodeAndCache(Parse*, Expr*);
index 134b4815512ebf96de75f3e34207f2f8d760e4ff..d3929984e95008d44f981d3ec7d68c29a6b4787d 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains C code routines that are called by the parser
 ** to handle UPDATE statements.
 **
-** $Id: update.c,v 1.99 2004/12/07 15:41:49 drh Exp $
+** $Id: update.c,v 1.100 2004/12/25 01:03:14 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -227,11 +227,12 @@ void sqlite3Update(
 
   /* Begin the database scan
   */
-  pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 1, 0, 0);
+  pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0);
   if( pWInfo==0 ) goto update_cleanup;
 
   /* Remember the index of every item to be updated.
   */
+  sqlite3VdbeAddOp(v, OP_Recno, iCur, 0);
   sqlite3VdbeAddOp(v, OP_ListWrite, 0, 0);
 
   /* End the database scan loop.
index 8994dfd6112f96199afd0ddfc06fcd0d96aedc0a..55d792485f16e84c4435006ebd12a659bf2f5aca 100644 (file)
@@ -14,7 +14,7 @@
 ** This file contains functions for allocating memory, comparing
 ** strings, and stuff like that.
 **
-** $Id: util.c,v 1.122 2004/11/20 19:18:01 drh Exp $
+** $Id: util.c,v 1.123 2004/12/25 01:03:14 drh Exp $
 */
 #include "sqliteInt.h"
 #include <stdarg.h>
@@ -872,6 +872,7 @@ int sqlite3GetVarint32(const unsigned char *p, u32 *v){
   u32 x;
   int n;
   unsigned char c;
+#if 0
   if( ((c = p[0]) & 0x80)==0 ){
     *v = c;
     return 1;
@@ -882,6 +883,18 @@ int sqlite3GetVarint32(const unsigned char *p, u32 *v){
     return 2;
   }
   x = (x<<7) | (c & 0x7f);
+#else
+  if( ((signed char*)p)[0]>=0 ){
+    *v = p[0];
+    return 1;
+  }
+  x = p[0] & 0x7f;
+  if( ((signed char*)p)[1]>=0 ){
+    *v = (x<<7) | p[1];
+    return 2;
+  }
+  x = (x<<7) | (p[1] & 0x7f);
+#endif
   n = 2;
   do{
     x = (x<<7) | ((c = p[n++])&0x7f);
index d38c5f11ad28686d76cec34ee4f22f1471e397a2..711899e3da8c7130c93103daf86886f4ab4637f4 100644 (file)
@@ -43,7 +43,7 @@
 ** in this file for details.  If in doubt, do not deviate from existing
 ** commenting and indentation practices when changing or adding code.
 **
-** $Id: vdbe.c,v 1.434 2004/12/19 00:11:35 drh Exp $
+** $Id: vdbe.c,v 1.435 2004/12/25 01:03:14 drh Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -641,6 +641,9 @@ case OP_Halt: {
 ** The integer value P1 is pushed onto the stack.  If P3 is not zero
 ** then it is assumed to be a string representation of the same integer.
 ** If P1 is zero and P3 is not zero, then the value is derived from P3.
+**
+** If the value cannot be represented as a 32-bits then its value
+** will be in P3.
 */
 case OP_Integer: {
   pTos++;
@@ -1100,7 +1103,7 @@ divide_by_zero:
 ** P3 is a pointer to a CollSeq struct. If the next call to a user function
 ** or aggregate calls sqlite3GetFuncCollSeq(), this collation sequence will
 ** be returned. This is used by the built-in min(), max() and nullif()
-** built-in functions.
+** functions.
 **
 ** The interface used by the implementation of the aforementioned functions
 ** to retrieve the collation sequence set by this opcode is not available
index e1998624fa04ec1062fdb6e73dae690afa551799..d8c8aecdd7b7bc1ba3765b6d9cec80bafbd17764 100644 (file)
@@ -16,7 +16,7 @@
 ** so is applicable.  Because this module is responsible for selecting
 ** indices, you might also think of this module as the "query optimizer".
 **
-** $Id: where.c,v 1.123 2004/12/19 00:11:35 drh Exp $
+** $Id: where.c,v 1.124 2004/12/25 01:03:14 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -525,6 +525,11 @@ static void codeEqualityTerm(
 ** And so forth.  This routine generates code to open those VDBE cursors
 ** and sqlite3WhereEnd() generates the code to close them.
 **
+** The code that sqlite3WhereBegin() generates leaves the cursors named
+** in pTabList pointing at their appropriate entries.  The [...] code
+** can use OP_Column and OP_Recno opcodes on these cursors to extra
+** data from the various tables of the loop.
+**
 ** If the WHERE clause is empty, the foreach loops must each scan their
 ** entire tables.  Thus a three-way join is an O(N^3) operation.  But if
 ** the tables have indices and there are terms in the WHERE clause that
@@ -575,7 +580,6 @@ WhereInfo *sqlite3WhereBegin(
   Parse *pParse,        /* The parser context */
   SrcList *pTabList,    /* A list of all tables to be scanned */
   Expr *pWhere,         /* The WHERE clause */
-  int pushKey,          /* If TRUE, leave the table key on the stack */
   ExprList **ppOrderBy, /* An ORDER BY clause, or NULL */
   Fetch *pFetch         /* Initial location of cursors.  NULL otherwise */
 ){
@@ -585,7 +589,6 @@ WhereInfo *sqlite3WhereBegin(
   int brk, cont = 0;         /* Addresses used during code generation */
   int nExpr;           /* Number of subexpressions in the WHERE clause */
   Bitmask loopMask;    /* One bit set for each outer loop */
-  int haveRowid = 0;   /* True if the ROWID is on the stack */
   ExprInfo *pTerm;     /* A single term in the WHERE clause; ptr to aExpr[] */
   ExprMaskSet maskSet; /* The expression mask set */
   int iDirectEq[BMS];  /* Term of the form ROWID==X for the N-th table */
@@ -595,11 +598,6 @@ WhereInfo *sqlite3WhereBegin(
   struct SrcList_item *pTabItem;  /* A single entry from pTabList */
   WhereLevel *pLevel;             /* A single level in the pWInfo list */
 
-  /* pushKey is only allowed if there is a single table (as in an INSERT or
-  ** UPDATE statement)
-  */
-  assert( pushKey==0 || pTabList->nSrc==1 );
-
   /* Split the WHERE clause into separate subexpressions where each
   ** subexpression is separated by an AND operator.  If the aExpr[]
   ** array fills up, the last entry might point to an expression which
@@ -996,7 +994,6 @@ WhereInfo *sqlite3WhereBegin(
       cont = pLevel->cont = sqlite3VdbeMakeLabel(v);
       sqlite3VdbeAddOp(v, OP_MustBeInt, 1, brk);
       sqlite3VdbeAddOp(v, OP_NotExists, iCur, brk);
-      haveRowid = 0;
       pLevel->op = OP_Noop;
     }else if( pIdx!=0 && pLevel->score>3 && (pLevel->score&0x0c)==0 ){
       /* Case 2:  There is an index and all terms of the WHERE clause that
@@ -1050,11 +1047,9 @@ WhereInfo *sqlite3WhereBegin(
       }
       sqlite3VdbeAddOp(v, OP_RowKey, iIdxCur, 0);
       sqlite3VdbeAddOp(v, OP_IdxIsNull, nColumn, cont);
-      if( omitTable ){
-        haveRowid = 0;
-      }else{
+      if( !omitTable ){
         sqlite3VdbeAddOp(v, OP_IdxRecno, iIdxCur, 0);
-        haveRowid = 1;
+        sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0);
       }
       pLevel->p1 = iIdxCur;
       pLevel->p2 = start;
@@ -1115,7 +1110,6 @@ WhereInfo *sqlite3WhereBegin(
         sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);
         sqlite3VdbeAddOp(v, testOp, 0, brk);
       }
-      haveRowid = 0;
     }else if( pIdx==0 ){
       /* Case 4:  There is no usable index.  We must do a complete
       **          scan of the entire database table.
@@ -1137,7 +1131,6 @@ WhereInfo *sqlite3WhereBegin(
       start = sqlite3VdbeCurrentAddr(v);
       pLevel->p1 = iCur;
       pLevel->p2 = start;
-      haveRowid = 0;
     }else{
       /* Case 5: The WHERE clause term that refers to the right-most
       **         column of the index is an inequality.  For example, if
@@ -1287,11 +1280,9 @@ WhereInfo *sqlite3WhereBegin(
       }
       sqlite3VdbeAddOp(v, OP_RowKey, iIdxCur, 0);
       sqlite3VdbeAddOp(v, OP_IdxIsNull, nEqColumn + ((score&4)!=0), cont);
-      if( omitTable ){
-        haveRowid = 0;
-      }else{
+      if( !omitTable ){
         sqlite3VdbeAddOp(v, OP_IdxRecno, iIdxCur, 0);
-        haveRowid = 1;
+        sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0);
       }
 
       /* Record the instruction used to terminate the loop.
@@ -1311,14 +1302,6 @@ WhereInfo *sqlite3WhereBegin(
       if( pLevel->iLeftJoin && !ExprHasProperty(pTerm->p,EP_FromJoin) ){
         continue;
       }
-      if( haveRowid ){
-        haveRowid = 0;
-        if( omitTable ){
-          sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
-        }else{
-          sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0);
-        }
-      }
       sqlite3ExprIfFalse(pParse, pTerm->p, cont, 1);
       pTerm->p = 0;
     }
@@ -1335,33 +1318,12 @@ WhereInfo *sqlite3WhereBegin(
       for(pTerm=aExpr, j=0; j<nExpr; j++, pTerm++){
         if( pTerm->p==0 ) continue;
         if( (pTerm->prereqAll & loopMask)!=pTerm->prereqAll ) continue;
-        if( haveRowid ){
-          /* Cannot happen.  "haveRowid" can only be true if pushKey is true
-          ** an pushKey can only be true for DELETE and UPDATE and there are
-          ** no outer joins with DELETE and UPDATE.
-          */
-          assert( 0 );
-          haveRowid = 0;
-          sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0);
-        }
         sqlite3ExprIfFalse(pParse, pTerm->p, cont, 1);
         pTerm->p = 0;
       }
     }
-
-    if( haveRowid && (i<pTabList->nSrc-1 || !pushKey) ){
-      haveRowid = 0;
-      if( omitTable ){
-        sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
-      }else{
-        sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0);
-      }
-    }    
   }
   pWInfo->iContinue = cont;
-  if( pushKey && !haveRowid ){
-    sqlite3VdbeAddOp(v, OP_Recno, pTabList->a[0].iCursor, 0);
-  }
   freeMaskSet(&maskSet);
   return pWInfo;
 }