From: drh Date: Fri, 14 Jun 2002 20:58:45 +0000 (+0000) Subject: Improvements to comments. No code changes. (CVS 618) X-Git-Tag: version-3.6.10~5457 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c27a1ce4bd75154f3c7aaf7b4f921ee3a21a9b2d;p=thirdparty%2Fsqlite.git Improvements to comments. No code changes. (CVS 618) FossilOrigin-Name: 7e10e60bb78b680bb822908a0b7763f8f5e3ee5a --- diff --git a/manifest b/manifest index 20a76a0eda..27c2e0c6c5 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sfor\sbug\s#72:\sMake\ssure\sthe\sfile\sdescriptors\sare\sproperly\sclosed\sif\nsqliteInit()\sfails\sfor\sany\sreason.\s(CVS\s617) -D 2002-06-14T20:54:15 +C Improvements\sto\scomments.\s\sNo\scode\schanges.\s(CVS\s618) +D 2002-06-14T20:58:45 F Makefile.in 6291a33b87d2a395aafd7646ee1ed562c6f2c28c F Makefile.template 4e11752e0b5c7a043ca50af4296ec562857ba495 F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0 @@ -51,10 +51,10 @@ F src/threadtest.c 81f0598e0f031c1bd506af337fdc1b7e8dff263f F src/tokenize.c 890ca022d45f1798dadc300a798951597428853e F src/trigger.c 21342af6ac031fece39c8fc6eabd1739ca5327c1 F src/update.c 05431e23a9c83502fd7911e771c8366fc2b90b4c -F src/util.c 7cf46b5612f5d12601c697374b9c6b38b2332ce8 +F src/util.c 876b259f9186e84b944b72e793dd3dad50e63e95 F src/vdbe.c 836f2c4f823c94c3c3454125d9ba9283e8b22dda F src/vdbe.h 1742d6f8b40f40879475b4c41cf4f9980ceb0e21 -F src/where.c b7c653054d4941d17f3112776ebcaf00d9613cb7 +F src/where.c bd25559800ba1fbe1fd596eaec14c417aa1e1b46 F test/all.test e4d3821eeba751829b419cd47814bd20af4286d1 F test/bigrow.test 8ab252dba108f12ad64e337b0f2ff31a807ac578 F test/btree.test bf326f546a666617367a7033fa2c07451bd4f8e1 @@ -137,7 +137,7 @@ F www/speed.tcl da8afcc1d3ccc5696cfb388a68982bc3d9f7f00f F www/sqlite.tcl 8b5884354cb615049aed83039f8dfe1552a44279 F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218 -P 3387d5b6d62fbafea69fac7bb8256c37d5c6a4ba -R 55f4a18ed8c64842b0e836d93bcc263f +P e67ac0fec51788aca0429d04310f86c9c1cf9d13 +R c5c72185b42e3894c8a67dc4dc44e497 U drh -Z 3504b88b5175db600e1d0221cbd874dc +Z ec1b6ad2227bde141b128cfba4f6e91b diff --git a/manifest.uuid b/manifest.uuid index 7b9c0aa687..f1e8e0b894 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e67ac0fec51788aca0429d04310f86c9c1cf9d13 \ No newline at end of file +7e10e60bb78b680bb822908a0b7763f8f5e3ee5a \ No newline at end of file diff --git a/src/util.c b/src/util.c index d14e6d3710..007dd5aa1d 100644 --- a/src/util.c +++ b/src/util.c @@ -14,7 +14,7 @@ ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** -** $Id: util.c,v 1.45 2002/05/31 15:51:25 drh Exp $ +** $Id: util.c,v 1.46 2002/06/14 20:58:45 drh Exp $ */ #include "sqliteInt.h" #include @@ -1084,7 +1084,7 @@ sqliteLikeCompare(const unsigned char *zPattern, const unsigned char *zString){ ** same sqlite* pointer at the same time. There is a race ** condition so it is possible that the error is not detected. ** But usually the problem will be seen. The result will be an -** error which can be used to debugging the application that is +** error which can be used to debug the application that is ** using SQLite incorrectly. */ int sqliteSafetyOn(sqlite *db){ diff --git a/src/where.c b/src/where.c index d71121ea9e..c658ab59e7 100644 --- a/src/where.c +++ b/src/where.c @@ -13,7 +13,7 @@ ** the WHERE clause of SQL statements. Also found here are subroutines ** to generate VDBE code to evaluate expressions. ** -** $Id: where.c,v 1.50 2002/06/09 01:55:20 drh Exp $ +** $Id: where.c,v 1.51 2002/06/14 20:58:45 drh Exp $ */ #include "sqliteInt.h" @@ -103,7 +103,7 @@ static int exprTableUsage(int base, Expr *p){ /* ** Return TRUE if the given operator is one of the operators that is ** allowed for an indexable WHERE clause. The allowed operators are -** "=", "<", ">", "<=", and ">=". +** "=", "<", ">", "<=", ">=", and "IN". */ static int allowedOp(int op){ switch( op ){ @@ -156,6 +156,58 @@ static void exprAnalyze(int base, ExprInfo *pInfo){ ** in order to complete the WHERE clause processing. ** ** If an error occurs, this routine returns NULL. +** +** The basic idea is to do a nested loop, one loop for each table in +** the FROM clause of a select. (INSERT and UPDATE statements are the +** same as a SELECT with only a single table in the FROM clause.) For +** example, if the SQL is this: +** +** SELECT * FROM t1, t2, t3 WHERE ...; +** +** Then the code generated is conceptually like the following: +** +** foreach row1 in t1 do \ Code generated +** foreach row2 in t2 do |-- by sqliteWhereBegin() +** foreach row3 in t3 do / +** ... +** end \ Code generated +** end |-- by sqliteWhereEnd() +** end / +** +** There are Btree cursors associated with each table. t1 uses cursor +** "base". t2 uses cursor "base+1". And so forth. This routine generates +** the code to open those cursors. sqliteWhereEnd() generates the code +** to close them. +** +** 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 +** refer to those indices, a complete table scan can be avoided and the +** code will run much faster. Most of the work of this routine is checking +** to see if there are indices that can be used to speed up the loop. +** +** Terms of the WHERE clause are also used to limit which rows actually +** make it to the "..." in the middle of the loop. After each "foreach", +** terms of the WHERE clause that use only terms in that loop and outer +** loops are evaluated and if false a jump is made around all subsequent +** inner loops (or around the "..." if the test occurs within the inner- +** most loop) +** +** OUTER JOINS +** +** An outer join of tables t1 and t2 is conceptally coded as follows: +** +** foreach row1 in t1 do +** flag = 0 +** foreach row2 in t2 do +** start: +** ... +** flag = 1 +** end +** if flag==0 goto start +** end +** +** In words, if the right */ WhereInfo *sqliteWhereBegin( Parse *pParse, /* The parser context */ @@ -178,6 +230,11 @@ WhereInfo *sqliteWhereBegin( int iDirectGt[32]; /* Term of the form ROWID>X or ROWID>=X */ ExprInfo aExpr[50]; /* The WHERE clause is divided into these expressions */ + /* pushKey is only allowed if there is a single table (as in an INSERT or + ** UPDATE statement) + */ + assert( pushKey==0 || pTabList->nSrc==1 ); + /* Allocate space for aOrder[] and aiMem[]. */ aOrder = sqliteMalloc( sizeof(int) * pTabList->nSrc ); @@ -332,14 +389,17 @@ WhereInfo *sqliteWhereBegin( ** If score&2 is not 0 then there is an inequality used as the ** start key. (ex: "x>..."); ** - ** The IN operator as in " IN (...)" is treated the same as - ** an equality comparison. + ** The IN operator (as in " IN (...)") is treated the same as + ** an equality comparison except that it can only be used on the + ** left-most column of an index and other terms of the WHERE clause + ** cannot be used in conjunction with the IN operator to help satisfy + ** other columns of the index. */ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - int eqMask = 0; /* Index columns covered by an x=... constraint */ - int ltMask = 0; /* Index columns covered by an x<... constraint */ - int gtMask = 0; /* Index columns covered by an x>... constraint */ - int inMask = 0; /* Index columns covered by an x IN .. constraint */ + int eqMask = 0; /* Index columns covered by an x=... term */ + int ltMask = 0; /* Index columns covered by an x<... term */ + int gtMask = 0; /* Index columns covered by an x>... term */ + int inMask = 0; /* Index columns covered by an x IN .. term */ int nEq, m, score; if( pIdx->isDropped ) continue; /* Ignore dropped indices */ @@ -468,7 +528,7 @@ WhereInfo *sqliteWhereBegin( /* If this is the right table of a LEFT OUTER JOIN, allocate and ** initialize a memory cell that record if this table matches any - ** row of the left table in the join. + ** row of the left table of the join. */ if( i>0 && (pTabList->a[i-1].jointype & JT_LEFT)!=0 ){ if( !pParse->nMem ) pParse->nMem++; @@ -481,7 +541,9 @@ WhereInfo *sqliteWhereBegin( pLevel->inOp = OP_Noop; if( i=0 ){ /* Case 1: We can directly reference a single row using an - ** equality comparison against the ROWID field. + ** equality comparison against the ROWID field. Or + ** we reference multiple rows using a "rowid IN (...)" + ** construct. */ k = iDirectEq[i]; assert( kop = OP_Noop; }else if( pIdx!=0 && pLevel->score%4==0 ){ - /* Case 2: All index constraints are equality operators. + /* Case 2: There is an index and all terms of the WHERE clause that + ** refer to the index use the "==" or "IN" operators. */ int start; int testOp; @@ -646,7 +709,7 @@ WhereInfo *sqliteWhereBegin( } haveKey = 0; }else if( pIdx==0 ){ - /* Case 4: There was 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. */ int start; @@ -660,8 +723,12 @@ WhereInfo *sqliteWhereBegin( pLevel->p2 = start; haveKey = 0; }else{ - /* Case 5: The contraint on the right-most index field is - ** an inequality. + /* Case 5: The WHERE clause term that refers to the right-most + ** column of the index is an inequality. For example, if + ** the index is on (x,y,z) and the WHERE clause is of the + ** form "x=5 AND y<10" then this case is used. Only the + ** right-most column can be an inequality - the rest must + ** use the "==" operator. */ int score = pLevel->score; int nEqColumn = score/4; @@ -695,7 +762,7 @@ WhereInfo *sqliteWhereBegin( } } - /* Duplicate the equality contraint values because they will all be + /* Duplicate the equality term values because they will all be ** used twice: once to make the termination key and once to make the ** start key. */ @@ -705,7 +772,7 @@ WhereInfo *sqliteWhereBegin( /* Generate the termination key. This is the key value that ** will end the search. There is no termination key if there - ** are no equality contraints and no "X<..." constraint. + ** are no equality terms and no "X<..." term. */ if( (score & 1)!=0 ){ for(k=0; k..." constraint. In + ** bound on the search. There is no start key if there are no + ** equality terms and if there is no "X>..." term. In ** that case, generate a "Rewind" instruction in place of the ** start key search. */ @@ -850,7 +917,8 @@ WhereInfo *sqliteWhereBegin( } /* -** Generate the end of the WHERE loop. +** Generate the end of the WHERE loop. See comments on +** sqliteWhereBegin() for additional information. */ void sqliteWhereEnd(WhereInfo *pWInfo){ Vdbe *v = pWInfo->pParse->pVdbe;