mirror of
				https://github.com/sqlite/sqlite.git
				synced 2025-10-30 07:05:46 +03:00 
			
		
		
		
	Fix ticket #1046 by removing code and simplifying the query optimizer.
Remarkably, this simplification also makes the optimizer do a better job. Ticket #1051 was fixed as a side-effect. (CVS 2172) FossilOrigin-Name: 5fd1f4711885e3dd6fb2c2700287f78bb0ea178a
This commit is contained in:
		
							
								
								
									
										28
									
								
								manifest
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								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) | 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-20T19:01:32 | D 2004-12-25T01:03:14 | ||||||
| F Makefile.in 02a184d734a2b4bbbc1ecc2e3ef504fcb13de069 | F Makefile.in 02a184d734a2b4bbbc1ecc2e3ef504fcb13de069 | ||||||
| F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457 | F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457 | ||||||
| F README a01693e454a00cc117967e3f9fdab2d4d52e9bc1 | F README a01693e454a00cc117967e3f9fdab2d4d52e9bc1 | ||||||
| @@ -34,7 +34,7 @@ F src/btree.h 861e40b759a195ba63819740e484390012cf81ab | |||||||
| F src/build.c af1296e8a21a406b4f4c4f1e1365e075071219f3 | F src/build.c af1296e8a21a406b4f4c4f1e1365e075071219f3 | ||||||
| F src/cursor.c f883813759742068890b1f699335872bfa8fdf41 | F src/cursor.c f883813759742068890b1f699335872bfa8fdf41 | ||||||
| F src/date.c 65536e7ea04fdde6e0551264fca15966966e171f | F src/date.c 65536e7ea04fdde6e0551264fca15966966e171f | ||||||
| F src/delete.c 6debe7893fa09bb5b386df0f26165f13132423e6 | F src/delete.c 5e5bcf0092b146a399e571d1e704b3b22633d2d0 | ||||||
| F src/expr.c d718509e56f58b06bc5f9b46afb295675334d544 | F src/expr.c d718509e56f58b06bc5f9b46afb295675334d544 | ||||||
| F src/func.c b668e5ad043176049454c95a6a780367a0e8f6bb | F src/func.c b668e5ad043176049454c95a6a780367a0e8f6bb | ||||||
| F src/hash.c a97721a55440b7bea31ffe471bb2f6b4123cddd5 | F src/hash.c a97721a55440b7bea31ffe471bb2f6b4123cddd5 | ||||||
| @@ -56,13 +56,13 @@ F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b | |||||||
| F src/pager.c 7b4dc9a94228efde924f1d9f4b7751f332da4587 | F src/pager.c 7b4dc9a94228efde924f1d9f4b7751f332da4587 | ||||||
| F src/pager.h 9eba8c53dd91eae7f3f90743b2ee242da02a9862 | F src/pager.h 9eba8c53dd91eae7f3f90743b2ee242da02a9862 | ||||||
| F src/parse.y ceba179b9703657180963568f54b0e75f33e36e1 | F src/parse.y ceba179b9703657180963568f54b0e75f33e36e1 | ||||||
| F src/pragma.c 639a7e7ef0999211aafa1f3d474ecc7241033cb9 | F src/pragma.c 0394f9361a497b7f74c1e5909bfc95a1f5bf0ce4 | ||||||
| F src/printf.c 3d20b21cfecadacecac3fb7274e746cb81d3d357 | F src/printf.c 3d20b21cfecadacecac3fb7274e746cb81d3d357 | ||||||
| F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3 | F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3 | ||||||
| F src/select.c ac6610b4b2c5bd5ffc46536b760dacc420119dac | F src/select.c 080c0d1d684ff6154a2f042347f34bc07e50590c | ||||||
| F src/shell.c e8f4f486cbf6e60d81173146ac8a6522c930fa51 | F src/shell.c e8f4f486cbf6e60d81173146ac8a6522c930fa51 | ||||||
| F src/sqlite.h.in 0d5e48e506845b74a845c9470e01d3f472b59611 | F src/sqlite.h.in 0d5e48e506845b74a845c9470e01d3f472b59611 | ||||||
| F src/sqliteInt.h a922cfd13711c68538684619fb15a4d262b12b9d | F src/sqliteInt.h ef924e4a1a4b69d68f01af3242ab080de6069131 | ||||||
| F src/table.c 25b3ff2b39b7d87e8d4a5da0713d68dfc06cbee9 | F src/table.c 25b3ff2b39b7d87e8d4a5da0713d68dfc06cbee9 | ||||||
| F src/tclsqlite.c 3a4044ef609565c8cc51e887d8b96933ba9f3b5c | F src/tclsqlite.c 3a4044ef609565c8cc51e887d8b96933ba9f3b5c | ||||||
| F src/test1.c b7d94c54e58f95452387a5cabdf98b2be8059f29 | F src/test1.c b7d94c54e58f95452387a5cabdf98b2be8059f29 | ||||||
| @@ -72,17 +72,17 @@ F src/test4.c 7c6b9fc33dd1f3f93c7f1ee6e5e6d016afa6c1df | |||||||
| F src/test5.c 64f08b2a50ef371a1bd68ff206829e7b1b9997f5 | F src/test5.c 64f08b2a50ef371a1bd68ff206829e7b1b9997f5 | ||||||
| F src/tokenize.c 2ad3d1ae1a0a70746db0b31a0a74f58050a3c39a | F src/tokenize.c 2ad3d1ae1a0a70746db0b31a0a74f58050a3c39a | ||||||
| F src/trigger.c 98f3b07c08ba01b34cff139ef9687883d325ae8e | F src/trigger.c 98f3b07c08ba01b34cff139ef9687883d325ae8e | ||||||
| F src/update.c aa92fa2203b2233008dd75a1e97c4b441be24a7f | F src/update.c 0979397c41ac29c54fe0cc687a356d8629a633af | ||||||
| F src/utf.c e45ce11be6922408cd381561721f6cca7d3b992a | F src/utf.c e45ce11be6922408cd381561721f6cca7d3b992a | ||||||
| F src/util.c 4a8db4e97a3cfda12ad8dda3e77dd2d00ad1de5e | F src/util.c 29f43c4a7b9ff29302f7899f793be6836b6cd7f9 | ||||||
| F src/vacuum.c 705256e1111521fa04f0029de7f1667bc131d015 | F src/vacuum.c 705256e1111521fa04f0029de7f1667bc131d015 | ||||||
| F src/vdbe.c caeb3f88d9a027d300c8fd27cf885ca964e5354e | F src/vdbe.c 40ab8e30eca1ed0e5d9e17b6d835660edf14c7c2 | ||||||
| F src/vdbe.h 067ca8d6750ba4f69a50284765e5883dee860181 | F src/vdbe.h 067ca8d6750ba4f69a50284765e5883dee860181 | ||||||
| F src/vdbeInt.h 0f74561e629af86172de7cdf0ecaea014c51696c | F src/vdbeInt.h 0f74561e629af86172de7cdf0ecaea014c51696c | ||||||
| F src/vdbeapi.c 0cf3bdc1072616bedc8eec7fc22e3f5a169d33fd | F src/vdbeapi.c 0cf3bdc1072616bedc8eec7fc22e3f5a169d33fd | ||||||
| F src/vdbeaux.c a7c4c90786e2633b38f2d89f3dc49aed747454e4 | F src/vdbeaux.c a7c4c90786e2633b38f2d89f3dc49aed747454e4 | ||||||
| F src/vdbemem.c 5876c8abf4374fef671f4fd8dc333ef3fc95a2f0 | F src/vdbemem.c 5876c8abf4374fef671f4fd8dc333ef3fc95a2f0 | ||||||
| F src/where.c e4a34a8fd159d5ca59f87bb689bb513f1a2620df | F src/where.c 5307677f772a7b44628e65383c30697dee9a63f3 | ||||||
| F tclinstaller.tcl 36478c3bbfc5b93ceac42d94e3c736937b808432 | F tclinstaller.tcl 36478c3bbfc5b93ceac42d94e3c736937b808432 | ||||||
| F test/all.test 929bfa932b55e75c96fe2203f7650ba451c1862c | F test/all.test 929bfa932b55e75c96fe2203f7650ba451c1862c | ||||||
| F test/alter.test 95c57a4f461fa81293e0dccef7f83889aadb169a | F test/alter.test 95c57a4f461fa81293e0dccef7f83889aadb169a | ||||||
| @@ -263,7 +263,7 @@ F www/tclsqlite.tcl e73f8f8e5f20e8277619433f7970060ab01088fc | |||||||
| F www/vdbe.tcl 095f106d93875c94b47367384ebc870517431618 | F www/vdbe.tcl 095f106d93875c94b47367384ebc870517431618 | ||||||
| F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0 | F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0 | ||||||
| F www/whentouse.tcl fdacb0ba2d39831e8a6240d05a490026ad4c4e4c | F www/whentouse.tcl fdacb0ba2d39831e8a6240d05a490026ad4c4e4c | ||||||
| P e5aa489453bf31126da6473ef93c89ec27935cde | P 772e22cbd69463be41c2e73b4fd4eb33946193c4 | ||||||
| R 80852dba2ab3f55be612ddeeffa02604 | R 1a0697c736404780d6feff68a7939368 | ||||||
| U tpoindex | U drh | ||||||
| Z 5d44d728827caef4bb2a5da252002b6d | Z 1ae722789e543e8f74d632edf76f862b | ||||||
|   | |||||||
| @@ -1 +1 @@ | |||||||
| 772e22cbd69463be41c2e73b4fd4eb33946193c4 | 5fd1f4711885e3dd6fb2c2700287f78bb0ea178a | ||||||
| @@ -12,7 +12,7 @@ | |||||||
| ** This file contains C code routines that are called by the parser | ** This file contains C code routines that are called by the parser | ||||||
| ** in order to generate code for DELETE FROM statements. | ** 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" | #include "sqliteInt.h" | ||||||
|  |  | ||||||
| @@ -225,11 +225,12 @@ void sqlite3DeleteFrom( | |||||||
|  |  | ||||||
|     /* Begin the database scan |     /* 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; |     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); |     sqlite3VdbeAddOp(v, OP_ListWrite, 0, 0); | ||||||
|     if( db->flags & SQLITE_CountRows ){ |     if( db->flags & SQLITE_CountRows ){ | ||||||
|       sqlite3VdbeAddOp(v, OP_AddImm, 1, 0); |       sqlite3VdbeAddOp(v, OP_AddImm, 1, 0); | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ | |||||||
| ************************************************************************* | ************************************************************************* | ||||||
| ** This file contains code used to implement the PRAGMA command. | ** 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 "sqliteInt.h" | ||||||
| #include <ctype.h> | #include <ctype.h> | ||||||
| @@ -389,14 +389,14 @@ void sqlite3Pragma( | |||||||
|         if( sqlite3_temp_directory ){ |         if( sqlite3_temp_directory ){ | ||||||
|           if( strlen(sqlite3_temp_directory) < strlen(zRight) + 1){ |           if( strlen(sqlite3_temp_directory) < strlen(zRight) + 1){ | ||||||
|             sqlite3FreeX(sqlite3_temp_directory); |             sqlite3FreeX(sqlite3_temp_directory); | ||||||
|             sqlite3_temp_directory = sqlite3Malloc( strlen(zRight) + 1 ); |             sqlite3_temp_directory = sqliteMalloc( strlen(zRight) + 1 ); | ||||||
|             if( sqlite3_temp_directory==0 ){ |             if( sqlite3_temp_directory==0 ){ | ||||||
|               goto pragma_out; |               goto pragma_out; | ||||||
|             } |             } | ||||||
|             sqlite3_temp_directory[0] = '\0'; |             sqlite3_temp_directory[0] = '\0'; | ||||||
|           } |           } | ||||||
|         }else{ |         }else{ | ||||||
|           sqlite3_temp_directory = sqlite3Malloc( strlen(zRight) + 1 ); |           sqlite3_temp_directory = sqliteMalloc( strlen(zRight) + 1 ); | ||||||
|           if( sqlite3_temp_directory==0 ){ |           if( sqlite3_temp_directory==0 ){ | ||||||
|             goto pragma_out; |             goto pragma_out; | ||||||
|           } |           } | ||||||
|   | |||||||
| @@ -12,7 +12,7 @@ | |||||||
| ** This file contains C code routines that are called by the parser | ** This file contains C code routines that are called by the parser | ||||||
| ** to handle SELECT statements in SQLite. | ** 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" | #include "sqliteInt.h" | ||||||
|  |  | ||||||
| @@ -2549,7 +2549,7 @@ int sqlite3Select( | |||||||
|  |  | ||||||
|   /* Begin the database scan |   /* Begin the database scan | ||||||
|   */ |   */ | ||||||
|   pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, |   pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, | ||||||
|                              pGroupBy ? 0 : &pOrderBy, p->pFetch); |                              pGroupBy ? 0 : &pOrderBy, p->pFetch); | ||||||
|   if( pWInfo==0 ) goto select_end; |   if( pWInfo==0 ) goto select_end; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ | |||||||
| ************************************************************************* | ************************************************************************* | ||||||
| ** Internal interface definitions for SQLite. | ** 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_ | #ifndef _SQLITEINT_H_ | ||||||
| #define _SQLITEINT_H_ | #define _SQLITEINT_H_ | ||||||
| @@ -1359,7 +1359,7 @@ void sqlite3OpenTableForReading(Vdbe*, int iCur, Table*); | |||||||
| void sqlite3OpenTable(Vdbe*, int iCur, Table*, int); | void sqlite3OpenTable(Vdbe*, int iCur, Table*, int); | ||||||
| void sqlite3DeleteFrom(Parse*, SrcList*, Expr*); | void sqlite3DeleteFrom(Parse*, SrcList*, Expr*); | ||||||
| void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int); | 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 sqlite3WhereEnd(WhereInfo*); | ||||||
| void sqlite3ExprCode(Parse*, Expr*); | void sqlite3ExprCode(Parse*, Expr*); | ||||||
| void sqlite3ExprCodeAndCache(Parse*, Expr*); | void sqlite3ExprCodeAndCache(Parse*, Expr*); | ||||||
|   | |||||||
| @@ -12,7 +12,7 @@ | |||||||
| ** This file contains C code routines that are called by the parser | ** This file contains C code routines that are called by the parser | ||||||
| ** to handle UPDATE statements. | ** 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" | #include "sqliteInt.h" | ||||||
|  |  | ||||||
| @@ -227,11 +227,12 @@ void sqlite3Update( | |||||||
|  |  | ||||||
|   /* Begin the database scan |   /* 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; |   if( pWInfo==0 ) goto update_cleanup; | ||||||
|  |  | ||||||
|   /* Remember the index of every item to be updated. |   /* Remember the index of every item to be updated. | ||||||
|   */ |   */ | ||||||
|  |   sqlite3VdbeAddOp(v, OP_Recno, iCur, 0); | ||||||
|   sqlite3VdbeAddOp(v, OP_ListWrite, 0, 0); |   sqlite3VdbeAddOp(v, OP_ListWrite, 0, 0); | ||||||
|  |  | ||||||
|   /* End the database scan loop. |   /* End the database scan loop. | ||||||
|   | |||||||
							
								
								
									
										15
									
								
								src/util.c
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								src/util.c
									
									
									
									
									
								
							| @@ -14,7 +14,7 @@ | |||||||
| ** This file contains functions for allocating memory, comparing | ** This file contains functions for allocating memory, comparing | ||||||
| ** strings, and stuff like that. | ** 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 "sqliteInt.h" | ||||||
| #include <stdarg.h> | #include <stdarg.h> | ||||||
| @@ -872,6 +872,7 @@ int sqlite3GetVarint32(const unsigned char *p, u32 *v){ | |||||||
|   u32 x; |   u32 x; | ||||||
|   int n; |   int n; | ||||||
|   unsigned char c; |   unsigned char c; | ||||||
|  | #if 0 | ||||||
|   if( ((c = p[0]) & 0x80)==0 ){ |   if( ((c = p[0]) & 0x80)==0 ){ | ||||||
|     *v = c; |     *v = c; | ||||||
|     return 1; |     return 1; | ||||||
| @@ -882,6 +883,18 @@ int sqlite3GetVarint32(const unsigned char *p, u32 *v){ | |||||||
|     return 2; |     return 2; | ||||||
|   } |   } | ||||||
|   x = (x<<7) | (c & 0x7f); |   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; |   n = 2; | ||||||
|   do{ |   do{ | ||||||
|     x = (x<<7) | ((c = p[n++])&0x7f); |     x = (x<<7) | ((c = p[n++])&0x7f); | ||||||
|   | |||||||
| @@ -43,7 +43,7 @@ | |||||||
| ** in this file for details.  If in doubt, do not deviate from existing | ** in this file for details.  If in doubt, do not deviate from existing | ||||||
| ** commenting and indentation practices when changing or adding code. | ** 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 "sqliteInt.h" | ||||||
| #include "os.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 | ** 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. | ** 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 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: { | case OP_Integer: { | ||||||
|   pTos++; |   pTos++; | ||||||
| @@ -1100,7 +1103,7 @@ divide_by_zero: | |||||||
| ** P3 is a pointer to a CollSeq struct. If the next call to a user function | ** P3 is a pointer to a CollSeq struct. If the next call to a user function | ||||||
| ** or aggregate calls sqlite3GetFuncCollSeq(), this collation sequence will | ** or aggregate calls sqlite3GetFuncCollSeq(), this collation sequence will | ||||||
| ** be returned. This is used by the built-in min(), max() and nullif() | ** 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 | ** The interface used by the implementation of the aforementioned functions | ||||||
| ** to retrieve the collation sequence set by this opcode is not available | ** to retrieve the collation sequence set by this opcode is not available | ||||||
|   | |||||||
							
								
								
									
										58
									
								
								src/where.c
									
									
									
									
									
								
							
							
						
						
									
										58
									
								
								src/where.c
									
									
									
									
									
								
							| @@ -16,7 +16,7 @@ | |||||||
| ** so is applicable.  Because this module is responsible for selecting | ** so is applicable.  Because this module is responsible for selecting | ||||||
| ** indices, you might also think of this module as the "query optimizer". | ** 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" | #include "sqliteInt.h" | ||||||
|  |  | ||||||
| @@ -525,6 +525,11 @@ static void codeEqualityTerm( | |||||||
| ** And so forth.  This routine generates code to open those VDBE cursors | ** And so forth.  This routine generates code to open those VDBE cursors | ||||||
| ** and sqlite3WhereEnd() generates the code to close them. | ** 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 | ** 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 | ** 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 | ** the tables have indices and there are terms in the WHERE clause that | ||||||
| @@ -575,7 +580,6 @@ WhereInfo *sqlite3WhereBegin( | |||||||
|   Parse *pParse,        /* The parser context */ |   Parse *pParse,        /* The parser context */ | ||||||
|   SrcList *pTabList,    /* A list of all tables to be scanned */ |   SrcList *pTabList,    /* A list of all tables to be scanned */ | ||||||
|   Expr *pWhere,         /* The WHERE clause */ |   Expr *pWhere,         /* The WHERE clause */ | ||||||
|   int pushKey,          /* If TRUE, leave the table key on the stack */ |  | ||||||
|   ExprList **ppOrderBy, /* An ORDER BY clause, or NULL */ |   ExprList **ppOrderBy, /* An ORDER BY clause, or NULL */ | ||||||
|   Fetch *pFetch         /* Initial location of cursors.  NULL otherwise */ |   Fetch *pFetch         /* Initial location of cursors.  NULL otherwise */ | ||||||
| ){ | ){ | ||||||
| @@ -585,7 +589,6 @@ WhereInfo *sqlite3WhereBegin( | |||||||
|   int brk, cont = 0;         /* Addresses used during code generation */ |   int brk, cont = 0;         /* Addresses used during code generation */ | ||||||
|   int nExpr;           /* Number of subexpressions in the WHERE clause */ |   int nExpr;           /* Number of subexpressions in the WHERE clause */ | ||||||
|   Bitmask loopMask;    /* One bit set for each outer loop */ |   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[] */ |   ExprInfo *pTerm;     /* A single term in the WHERE clause; ptr to aExpr[] */ | ||||||
|   ExprMaskSet maskSet; /* The expression mask set */ |   ExprMaskSet maskSet; /* The expression mask set */ | ||||||
|   int iDirectEq[BMS];  /* Term of the form ROWID==X for the N-th table */ |   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 */ |   struct SrcList_item *pTabItem;  /* A single entry from pTabList */ | ||||||
|   WhereLevel *pLevel;             /* A single level in the pWInfo list */ |   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 |   /* Split the WHERE clause into separate subexpressions where each | ||||||
|   ** subexpression is separated by an AND operator.  If the aExpr[] |   ** subexpression is separated by an AND operator.  If the aExpr[] | ||||||
|   ** array fills up, the last entry might point to an expression which |   ** array fills up, the last entry might point to an expression which | ||||||
| @@ -996,7 +994,6 @@ WhereInfo *sqlite3WhereBegin( | |||||||
|       cont = pLevel->cont = sqlite3VdbeMakeLabel(v); |       cont = pLevel->cont = sqlite3VdbeMakeLabel(v); | ||||||
|       sqlite3VdbeAddOp(v, OP_MustBeInt, 1, brk); |       sqlite3VdbeAddOp(v, OP_MustBeInt, 1, brk); | ||||||
|       sqlite3VdbeAddOp(v, OP_NotExists, iCur, brk); |       sqlite3VdbeAddOp(v, OP_NotExists, iCur, brk); | ||||||
|       haveRowid = 0; |  | ||||||
|       pLevel->op = OP_Noop; |       pLevel->op = OP_Noop; | ||||||
|     }else if( pIdx!=0 && pLevel->score>3 && (pLevel->score&0x0c)==0 ){ |     }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 |       /* 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_RowKey, iIdxCur, 0); | ||||||
|       sqlite3VdbeAddOp(v, OP_IdxIsNull, nColumn, cont); |       sqlite3VdbeAddOp(v, OP_IdxIsNull, nColumn, cont); | ||||||
|       if( omitTable ){ |       if( !omitTable ){ | ||||||
|         haveRowid = 0; |  | ||||||
|       }else{ |  | ||||||
|         sqlite3VdbeAddOp(v, OP_IdxRecno, iIdxCur, 0); |         sqlite3VdbeAddOp(v, OP_IdxRecno, iIdxCur, 0); | ||||||
|         haveRowid = 1; |         sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0); | ||||||
|       } |       } | ||||||
|       pLevel->p1 = iIdxCur; |       pLevel->p1 = iIdxCur; | ||||||
|       pLevel->p2 = start; |       pLevel->p2 = start; | ||||||
| @@ -1115,7 +1110,6 @@ WhereInfo *sqlite3WhereBegin( | |||||||
|         sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0); |         sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0); | ||||||
|         sqlite3VdbeAddOp(v, testOp, 0, brk); |         sqlite3VdbeAddOp(v, testOp, 0, brk); | ||||||
|       } |       } | ||||||
|       haveRowid = 0; |  | ||||||
|     }else if( pIdx==0 ){ |     }else if( pIdx==0 ){ | ||||||
|       /* Case 4:  There is no usable index.  We must do a complete |       /* Case 4:  There is no usable index.  We must do a complete | ||||||
|       **          scan of the entire database table. |       **          scan of the entire database table. | ||||||
| @@ -1137,7 +1131,6 @@ WhereInfo *sqlite3WhereBegin( | |||||||
|       start = sqlite3VdbeCurrentAddr(v); |       start = sqlite3VdbeCurrentAddr(v); | ||||||
|       pLevel->p1 = iCur; |       pLevel->p1 = iCur; | ||||||
|       pLevel->p2 = start; |       pLevel->p2 = start; | ||||||
|       haveRowid = 0; |  | ||||||
|     }else{ |     }else{ | ||||||
|       /* Case 5: The WHERE clause term that refers to the right-most |       /* Case 5: The WHERE clause term that refers to the right-most | ||||||
|       **         column of the index is an inequality.  For example, if |       **         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_RowKey, iIdxCur, 0); | ||||||
|       sqlite3VdbeAddOp(v, OP_IdxIsNull, nEqColumn + ((score&4)!=0), cont); |       sqlite3VdbeAddOp(v, OP_IdxIsNull, nEqColumn + ((score&4)!=0), cont); | ||||||
|       if( omitTable ){ |       if( !omitTable ){ | ||||||
|         haveRowid = 0; |  | ||||||
|       }else{ |  | ||||||
|         sqlite3VdbeAddOp(v, OP_IdxRecno, iIdxCur, 0); |         sqlite3VdbeAddOp(v, OP_IdxRecno, iIdxCur, 0); | ||||||
|         haveRowid = 1; |         sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0); | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       /* Record the instruction used to terminate the loop. |       /* Record the instruction used to terminate the loop. | ||||||
| @@ -1311,14 +1302,6 @@ WhereInfo *sqlite3WhereBegin( | |||||||
|       if( pLevel->iLeftJoin && !ExprHasProperty(pTerm->p,EP_FromJoin) ){ |       if( pLevel->iLeftJoin && !ExprHasProperty(pTerm->p,EP_FromJoin) ){ | ||||||
|         continue; |         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); |       sqlite3ExprIfFalse(pParse, pTerm->p, cont, 1); | ||||||
|       pTerm->p = 0; |       pTerm->p = 0; | ||||||
|     } |     } | ||||||
| @@ -1335,33 +1318,12 @@ WhereInfo *sqlite3WhereBegin( | |||||||
|       for(pTerm=aExpr, j=0; j<nExpr; j++, pTerm++){ |       for(pTerm=aExpr, j=0; j<nExpr; j++, pTerm++){ | ||||||
|         if( pTerm->p==0 ) continue; |         if( pTerm->p==0 ) continue; | ||||||
|         if( (pTerm->prereqAll & loopMask)!=pTerm->prereqAll ) 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); |         sqlite3ExprIfFalse(pParse, pTerm->p, cont, 1); | ||||||
|         pTerm->p = 0; |         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; |   pWInfo->iContinue = cont; | ||||||
|   if( pushKey && !haveRowid ){ |  | ||||||
|     sqlite3VdbeAddOp(v, OP_Recno, pTabList->a[0].iCursor, 0); |  | ||||||
|   } |  | ||||||
|   freeMaskSet(&maskSet); |   freeMaskSet(&maskSet); | ||||||
|   return pWInfo; |   return pWInfo; | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user