diff --git a/manifest b/manifest index 7dc1a5c59d..a8fa559387 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Tcl\sinterface\stransfers\svalues\sdirectly\sbetween\sSQLite\sand\sTcl_Objs,\swithout\nat\stranslation\sto\sstrings.\s(CVS\s1898) -D 2004-08-20T18:34:20 +C Optimizations\sto\sthe\scode\sgenerator.\s(CVS\s1899) +D 2004-08-21T17:54:45 F Makefile.in 4a5e570a9e2d35b09c31b3cf01b78cea764ade4b F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd @@ -29,17 +29,17 @@ F src/attach.c 0bd4f11da6999665da30625665a4096ba7898de6 F src/auth.c 60db23b98bb94c8b0178180faaf49dc116674217 F src/btree.c 14c20dfb320473a1fd4e37d43eba5e2afd606757 F src/btree.h 94dfec0a1722d33359b23e7e310f2b64ffedf029 -F src/build.c bad6652b33a447a06fca79a257f74932412fc110 +F src/build.c 7d93b19d03bffd171f7c7873739688cab7e300c5 F src/date.c edff4aa851eeca8abbc737dc3933a2f0671156ce -F src/delete.c e81545e546f6bc87d7508a93a09ca70695265af3 +F src/delete.c 0ccc3424d72e5aaded165a8861b9d958c9d0afe6 F src/encode.c a876af473d1d636faa3dca51c7571f2e007eea37 -F src/expr.c 39ef5c141483f88c82472dbe0b5606b14d0a766d +F src/expr.c 3694386726ca140dddb839837ba24b58563d10af F src/func.c 7e2eeebe219aa612ce7a04c74ae6d57379c6656b F src/hash.c a97721a55440b7bea31ffe471bb2f6b4123cddd5 F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84 -F src/insert.c bedcba371401395033a1a1c578d8fdc3fec87bec +F src/insert.c fc1ce65a0fe68f226143de9b43c3582164a92aff F src/legacy.c 2f3617c61bcdcd1d776154a9cfebf99facda8ad8 -F src/main.c a779422c5402df92c390e233ac32ab718fc4436b +F src/main.c 581ccf00909842d05c42ce02bb19b92859f447db F src/md5.c 7ae1c39044b95de2f62e066f47bb1deb880a1070 F src/os.h d1780e0db95cad01f213d48da22ab490eb4fd345 F src/os_common.h cd7eb025fdab7dc91e0e97bf6310f1648205857f @@ -54,13 +54,13 @@ F src/os_win.h babd4e912967c6b09088cfe38a45e8005a07ba44 F src/pager.c 2698653a3bd895b2156c108a37a32d240a55bb0e F src/pager.h 67739fe649f33be55dba522ca8a9cc4e42d14f71 F src/parse.y 8b4cab1901900927f717d10885b7a1bd3375345b -F src/pragma.c 5cf335adfdac453a2d03ab0c82f93847c43bea81 +F src/pragma.c a7cea75286fcff6666a5412b04478fcf0ecef5c4 F src/printf.c 17b28a1eedfe8129b05de981719306c18c3f1327 F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3 -F src/select.c cbed45f4af76ad7fdfc0a0df6878b2b3827ae1d4 +F src/select.c 24b9ab865e34c0d5e7f2447558f93d1fe6f9d588 F src/shell.c 42f65424a948f197f389e13bc7aaa3cf24dafd0c F src/sqlite.h.in de2be4043f0bfa16958d33392a3e7a5e7d4bd50b -F src/sqliteInt.h 251662c89dd35c4ed745681ff00758d19ffd0906 +F src/sqliteInt.h c7ed161ecc40f9fd0f080fbcc00e34bd7d6735ee F src/table.c 4521c278892f60e4d630788c0ea5cf4db1e75c49 F src/tclsqlite.c 2e044cb0638c03fa38575fe607bdd4ee4885e1f4 F src/test1.c b87fae63b2994c150a579c4101f302be48ad77bc @@ -69,18 +69,18 @@ F src/test3.c 94d0a2a90bccd85802488cb42c69ec8afd2e4646 F src/test4.c c38766914e924091516030b6a8b677d849c08bf0 F src/test5.c b001fa7f1b9e2dc5c2331de62fc641b5ab2bd7a1 F src/tokenize.c b96043fdf662d93ccfc758d3e1cdf2513f23eca2 -F src/trigger.c 360cf8f12edd4eb3a8a2895b136aac238c3cf44e -F src/update.c b66b1896c9da54678ba3eff2bf0b4d291a95986a +F src/trigger.c 8b147c6b8ae0bab3a13463a4ca9ab6ad61f1361d +F src/update.c 151f1869ce532ed883f1ce26306f0b0fa7b2589a F src/utf.c 3d8f7bffcbefcced69a436c9e0a1c7eb9e0bb4fa F src/util.c e2c631849cc9e035f6fd387f507ad8886f77cedd F src/vacuum.c 9978a5760c2c430bc5b5e66505a02dad76f25813 -F src/vdbe.c 281af7f601a3220e86be2152eeb2ec6d82a6f71a -F src/vdbe.h 75b241c02431b9c0f16eaa9cdbb34146c6287f52 -F src/vdbeInt.h 5e57e36a03ebf09f2653caec0d9c18a904e0d060 -F src/vdbeapi.c 4f9b3072589dcad2fcd3abb3538e5e8f00d224a1 -F src/vdbeaux.c cc86e59cb56dad2f9335933f71268227f5f91bce +F src/vdbe.c ea662188cc489934a567d1eaa3fb6754d5b92b7d +F src/vdbe.h e081c72cd0f7c19d49b1927460aeefcf0fbc85ac +F src/vdbeInt.h 16322cbfccf0b05631fcf0df68b115c46584d6c9 +F src/vdbeapi.c e20e646a0ec4e74934bfcb82bd0fbb3c3c4a21f7 +F src/vdbeaux.c 022c484dba235d2dcbb1faca0f1943702f4232ed F src/vdbemem.c 68fefaf83adb48fe44135da01502c9327f6172b0 -F src/where.c cf8a54641eea01f1af5d09529ad69166db92f658 +F src/where.c a84eee276cd072158224da6b5f30733df2d56027 F test/all.test 3b692eb43583b52c99c344b2fa8934512d179016 F test/attach.test feb2ce54e78688df4c84553416d5aec3b2a0112e F test/attach2.test 9be9656bc1e929b224861960299920c76d45b14d @@ -105,7 +105,7 @@ F test/collate4.test 4a7902b7560686af11d6cace717d876c6937b7ef F test/collate5.test 1dd5f0f508c46667f9d4606c7950c414b0bdc0d5 F test/collate6.test 2a45768914f04c1447a69d1358bbede376552675 F test/conflict.test c5b849b01cfbe0a4f63a90cba6f68e2fe3a75f87 -F test/crash.test 3ea432ce624369c04ba1a23a5288115e40f5daa2 +F test/crash.test 59a91b7fbb41e9e5cb8ab652f22a7e639a0adc78 F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2 F test/date.test fd3db29bba089578b1b008e3511ea9e74840377a F test/delete.test ec0b455f2dcc0e189d96ee438438ba026c4e51d8 @@ -243,7 +243,7 @@ F www/tclsqlite.tcl 06a86cba4d7fc88e2bcd633b57702d3d16abebb5 F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9 F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4 -P d3be0b7c5a39c02b9b2d6d85f1595d591984a569 -R 1cbcdf6d3d0885857959264a9f52fa75 +P e97c331362545ce21117776c7b61d3488668f2bf +R b22d8f216bcbbb8b75e2380cdf547c74 U drh -Z e2be1e764ed7eb73ae85dcaeb658f10f +Z d01e8ee90bb832b679bd3adc8a30a5ef diff --git a/manifest.uuid b/manifest.uuid index a74654c7ee..7611e3fcff 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e97c331362545ce21117776c7b61d3488668f2bf \ No newline at end of file +bd6649c5aae1bf182610eb267b546c297a34481d \ No newline at end of file diff --git a/src/build.c b/src/build.c index 7f6ac411db..ca536f7643 100644 --- a/src/build.c +++ b/src/build.c @@ -23,7 +23,7 @@ ** ROLLBACK ** PRAGMA ** -** $Id: build.c,v 1.248 2004/08/18 15:58:23 drh Exp $ +** $Id: build.c,v 1.249 2004/08/21 17:54:45 drh Exp $ */ #include "sqliteInt.h" #include @@ -96,7 +96,8 @@ void sqlite3FinishCoding(Parse *pParse){ if( v && pParse->nErr==0 ){ FILE *trace = (db->flags & SQLITE_VdbeTrace)!=0 ? stdout : 0; sqlite3VdbeTrace(v, trace); - sqlite3VdbeMakeReady(v, pParse->nVar, pParse->explain); + sqlite3VdbeMakeReady(v, pParse->nVar, pParse->nMem+3, + pParse->nTab+3, pParse->explain); pParse->rc = pParse->nErr ? SQLITE_ERROR : SQLITE_DONE; pParse->colNamesSet = 0; }else if( pParse->rc==SQLITE_OK ){ diff --git a/src/delete.c b/src/delete.c index 7308eb817e..bfe1cbde5b 100644 --- a/src/delete.c +++ b/src/delete.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle DELETE FROM statements. ** -** $Id: delete.c,v 1.77 2004/06/21 18:14:47 drh Exp $ +** $Id: delete.c,v 1.78 2004/08/21 17:54:45 drh Exp $ */ #include "sqliteInt.h" @@ -121,13 +121,8 @@ void sqlite3DeleteFrom( */ assert( pTabList->nSrc==1 ); iCur = pTabList->a[0].iCursor = pParse->nTab++; - if( pWhere ){ - if( sqlite3ExprResolveIds(pParse, pTabList, 0, pWhere) ){ - goto delete_from_cleanup; - } - if( sqlite3ExprCheck(pParse, pWhere, 0, 0) ){ - goto delete_from_cleanup; - } + if( sqlite3ExprResolveAndCheck(pParse, pTabList, 0, pWhere, 0, 0) ){ + goto delete_from_cleanup; } /* Start the view context @@ -262,8 +257,7 @@ void sqlite3DeleteFrom( ** before the trigger fires. If there are no row triggers, the ** cursors are opened only once on the outside the loop. */ - pParse->nTab = iCur + 1; - sqlite3OpenTableAndIndices(pParse, pTab, iCur); + sqlite3OpenTableAndIndices(pParse, pTab, iCur, OP_OpenWrite); /* This is the beginning of the delete loop when there are no ** row triggers */ @@ -301,7 +295,6 @@ void sqlite3DeleteFrom( sqlite3VdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum); } sqlite3VdbeAddOp(v, OP_Close, iCur, 0); - pParse->nTab = iCur; } } sqlite3EndWriteOperation(pParse); diff --git a/src/expr.c b/src/expr.c index 6e8a75ee47..5377a2daa5 100644 --- a/src/expr.c +++ b/src/expr.c @@ -12,7 +12,7 @@ ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** -** $Id: expr.c,v 1.156 2004/08/20 16:02:39 drh Exp $ +** $Id: expr.c,v 1.157 2004/08/21 17:54:45 drh Exp $ */ #include "sqliteInt.h" #include @@ -1079,6 +1079,27 @@ int sqlite3ExprCheck(Parse *pParse, Expr *pExpr, int allowAgg, int *pIsAgg){ return nErr; } +/* +** Call sqlite3ExprResolveIds() followed by sqlite3ExprCheck(). +** +** This routine is provided as a convenience since it is very common +** to call ResolveIds() and Check() back to back. +*/ +int sqlite3ExprResolveAndCheck( + Parse *pParse, /* The parser context */ + SrcList *pSrcList, /* List of tables used to resolve column names */ + ExprList *pEList, /* List of expressions used to resolve "AS" */ + Expr *pExpr, /* The expression to be analyzed. */ + int allowAgg, /* True to allow aggregate expressions */ + int *pIsAgg /* Set to TRUE if aggregates are found */ +){ + if( pExpr==0 ) return 0; + if( sqlite3ExprResolveIds(pParse,pSrcList,pEList,pExpr) ){ + return 1; + } + return sqlite3ExprCheck(pParse, pExpr, allowAgg, pIsAgg); +} + /* ** Generate an instruction that will put the integer describe by ** text z[0..n-1] on the stack. diff --git a/src/insert.c b/src/insert.c index 7959947d15..77638b7f2e 100644 --- a/src/insert.c +++ b/src/insert.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle INSERT statements in SQLite. ** -** $Id: insert.c,v 1.114 2004/07/24 17:38:29 drh Exp $ +** $Id: insert.c,v 1.115 2004/08/21 17:54:45 drh Exp $ */ #include "sqliteInt.h" @@ -333,10 +333,7 @@ void sqlite3Insert( nColumn = pList->nExpr; dummy.nSrc = 0; for(i=0; ia[i].pExpr) ){ - goto insert_cleanup; - } - if( sqlite3ExprCheck(pParse, pList->a[i].pExpr, 0, 0) ){ + if( sqlite3ExprResolveAndCheck(pParse,&dummy,0,pList->a[i].pExpr,0,0) ){ goto insert_cleanup; } } @@ -420,8 +417,7 @@ void sqlite3Insert( /* Open tables and indices if there are no row triggers */ if( !row_triggers_exist ){ base = pParse->nTab; - idx = sqlite3OpenTableAndIndices(pParse, pTab, base); - pParse->nTab += idx; + sqlite3OpenTableAndIndices(pParse, pTab, base, OP_OpenWrite); } /* If the data source is a temporary table, then we have to create @@ -507,8 +503,7 @@ void sqlite3Insert( */ if( row_triggers_exist && !isView ){ base = pParse->nTab; - idx = sqlite3OpenTableAndIndices(pParse, pTab, base); - pParse->nTab += idx; + sqlite3OpenTableAndIndices(pParse, pTab, base, OP_OpenWrite); } /* Push the record number for the new entry onto the stack. The @@ -993,25 +988,29 @@ void sqlite3CompleteInsertion( } /* -** Generate code that will open write cursors for a table and for all +** Generate code that will open cursors for a table and for all ** indices of that table. The "base" parameter is the cursor number used ** for the table. Indices are opened on subsequent cursors. -** -** Return the total number of cursors opened. This is always at least -** 1 (for the main table) plus more for each cursor. */ -int sqlite3OpenTableAndIndices(Parse *pParse, Table *pTab, int base){ +void sqlite3OpenTableAndIndices( + Parse *pParse, /* Parsing context */ + Table *pTab, /* Table to be opened */ + int base, /* Cursor number assigned to the table */ + int op /* OP_OpenRead or OP_OpenWrite */ +){ int i; Index *pIdx; Vdbe *v = sqlite3GetVdbe(pParse); assert( v!=0 ); sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0); - sqlite3VdbeAddOp(v, OP_OpenWrite, base, pTab->tnum); + sqlite3VdbeAddOp(v, op, base, pTab->tnum); sqlite3VdbeAddOp(v, OP_SetNumColumns, base, pTab->nCol); for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ sqlite3VdbeAddOp(v, OP_Integer, pIdx->iDb, 0); - sqlite3VdbeOp3(v, OP_OpenWrite, i+base, pIdx->tnum, + sqlite3VdbeOp3(v, op, i+base, pIdx->tnum, (char*)&pIdx->keyInfo, P3_KEYINFO); } - return i; + if( pParse->nTab<=base+i ){ + pParse->nTab = base+i; + } } diff --git a/src/main.c b/src/main.c index 0d34349fa4..35b9c387d2 100644 --- a/src/main.c +++ b/src/main.c @@ -14,7 +14,7 @@ ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** -** $Id: main.c,v 1.252 2004/08/18 02:10:15 drh Exp $ +** $Id: main.c,v 1.253 2004/08/21 17:54:45 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -1253,7 +1253,7 @@ int sqlite3_finalize(sqlite3_stmt *pStmt){ */ int sqlite3_reset(sqlite3_stmt *pStmt){ int rc = sqlite3VdbeReset((Vdbe*)pStmt); - sqlite3VdbeMakeReady((Vdbe*)pStmt, -1, 0); + sqlite3VdbeMakeReady((Vdbe*)pStmt, -1, 0, 0, 0); return rc; } diff --git a/src/pragma.c b/src/pragma.c index a7189945a3..172ace3591 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -11,7 +11,7 @@ ************************************************************************* ** This file contains code used to implement the PRAGMA command. ** -** $Id: pragma.c,v 1.59 2004/08/08 20:22:18 drh Exp $ +** $Id: pragma.c,v 1.60 2004/08/21 17:54:45 drh Exp $ */ #include "sqliteInt.h" #include @@ -538,7 +538,7 @@ void sqlite3Pragma( { OP_MemLoad, 0, 0, 0}, { OP_Integer, 0, 0, 0}, { OP_Ne, 0, 0, 0}, /* 2 */ - { OP_String8, 0, 0, "ok"}, + { OP_String8, 0, 0, "ok"}, { OP_Callback, 1, 0, 0}, }; @@ -589,15 +589,7 @@ void sqlite3Pragma( int loopTop; if( pTab->pIndex==0 ) continue; - sqlite3VdbeAddOp(v, OP_Integer, i, 0); - sqlite3VdbeAddOp(v, OP_OpenRead, 1, pTab->tnum); - sqlite3VdbeAddOp(v, OP_SetNumColumns, 1, pTab->nCol); - for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ - if( pIdx->tnum==0 ) continue; - sqlite3VdbeAddOp(v, OP_Integer, pIdx->iDb, 0); - sqlite3VdbeOp3(v, OP_OpenRead, j+2, pIdx->tnum, - (char*)&pIdx->keyInfo, P3_KEYINFO); - } + sqlite3OpenTableAndIndices(pParse, pTab, 1, OP_OpenRead); sqlite3VdbeAddOp(v, OP_Integer, 0, 0); sqlite3VdbeAddOp(v, OP_MemStore, 1, 1); loopTop = sqlite3VdbeAddOp(v, OP_Rewind, 1, 0); @@ -606,11 +598,11 @@ void sqlite3Pragma( int jmp2; static VdbeOpList idxErr[] = { { OP_MemIncr, 0, 0, 0}, - { OP_String8, 0, 0, "rowid "}, + { OP_String8, 0, 0, "rowid "}, { OP_Recno, 1, 0, 0}, - { OP_String8, 0, 0, " missing from index "}, - { OP_String8, 0, 0, 0}, /* 4 */ - { OP_Concat8, 4, 0, 0}, + { OP_String8, 0, 0, " missing from index "}, + { OP_String8, 0, 0, 0}, /* 4 */ + { OP_Concat8, 4, 0, 0}, { OP_Callback, 1, 0, 0}, }; sqlite3GenerateIndexKey(v, pIdx, 1); @@ -632,9 +624,9 @@ void sqlite3Pragma( { OP_MemLoad, 2, 0, 0}, { OP_Eq, 0, 0, 0}, /* 7 */ { OP_MemIncr, 0, 0, 0}, - { OP_String8, 0, 0, "wrong # of entries in index "}, - { OP_String8, 0, 0, 0}, /* 10 */ - { OP_Concat8, 2, 0, 0}, + { OP_String8, 0, 0, "wrong # of entries in index "}, + { OP_String8, 0, 0, 0}, /* 10 */ + { OP_Concat8, 2, 0, 0}, { OP_Callback, 1, 0, 0}, }; if( pIdx->tnum==0 ) continue; diff --git a/src/select.c b/src/select.c index 820f73ffc5..191ec4ba1c 100644 --- a/src/select.c +++ b/src/select.c @@ -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.202 2004/07/26 23:32:27 drh Exp $ +** $Id: select.c,v 1.203 2004/08/21 17:54:45 drh Exp $ */ #include "sqliteInt.h" @@ -83,8 +83,8 @@ int sqlite3JoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){ Token *p; static struct { const char *zKeyword; - int nChar; - int code; + u8 nChar; + u8 code; } keywords[] = { { "natural", 7, JT_NATURAL }, { "left", 4, JT_LEFT|JT_OUTER }, @@ -804,7 +804,7 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){ Table *pTab; int i, j; ExprList *pEList; - Column *aCol; + Column *aCol, *pCol; if( fillInColumnList(pParse, pSelect) ){ return 0; @@ -818,44 +818,45 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){ pTab->nCol = pEList->nExpr; assert( pTab->nCol>0 ); pTab->aCol = aCol = sqliteMalloc( sizeof(pTab->aCol[0])*pTab->nCol ); - for(i=0; inCol; i++){ + for(i=0, pCol=aCol; inCol; i++, pCol++){ Expr *pR; char *zType; Expr *p = pEList->a[i].pExpr; + assert( p->pRight==0 || p->pRight->token.z==0 || p->pRight->token.z[0]!=0 ); if( pEList->a[i].zName ){ - aCol[i].zName = sqliteStrDup(pEList->a[i].zName); + pCol->zName = sqliteStrDup(pEList->a[i].zName); }else if( p->op==TK_DOT && (pR=p->pRight)!=0 && pR->token.z && pR->token.z[0] ){ int cnt; - sqlite3SetNString(&aCol[i].zName, pR->token.z, pR->token.n, 0); + sqlite3SetNString(&pCol->zName, pR->token.z, pR->token.n, 0); for(j=cnt=0; jzName)==0 ){ int n; char zBuf[30]; sprintf(zBuf,"_%d",++cnt); n = strlen(zBuf); - sqlite3SetNString(&aCol[i].zName, pR->token.z, pR->token.n, zBuf,n,0); + sqlite3SetNString(&pCol->zName, pR->token.z, pR->token.n, zBuf,n,0); j = -1; } } }else if( p->span.z && p->span.z[0] ){ - sqlite3SetNString(&pTab->aCol[i].zName, p->span.z, p->span.n, 0); + sqlite3SetNString(&pCol->zName, p->span.z, p->span.n, 0); }else{ char zBuf[30]; sprintf(zBuf, "column%d", i+1); - pTab->aCol[i].zName = sqliteStrDup(zBuf); + pCol->zName = sqliteStrDup(zBuf); } - sqlite3Dequote(aCol[i].zName); + sqlite3Dequote(pCol->zName); zType = sqliteStrDup(columnType(pParse, pSelect->pSrc ,p)); - pTab->aCol[i].zType = zType; - pTab->aCol[i].affinity = SQLITE_AFF_NUMERIC; + pCol->zType = zType; + pCol->affinity = SQLITE_AFF_NUMERIC; if( zType ){ - pTab->aCol[i].affinity = sqlite3AffinityType(zType, strlen(zType)); + pCol->affinity = sqlite3AffinityType(zType, strlen(zType)); } - pTab->aCol[i].pColl = sqlite3ExprCollSeq(pParse, p); - if( !pTab->aCol[i].pColl ){ - pTab->aCol[i].pColl = pParse->db->pDfltColl; + pCol->pColl = sqlite3ExprCollSeq(pParse, p); + if( !pCol->pColl ){ + pCol->pColl = pParse->db->pDfltColl; } } pTab->iPKey = -1; @@ -889,6 +890,7 @@ static int fillInColumnList(Parse *pParse, Select *p){ SrcList *pTabList; ExprList *pEList; Table *pTab; + struct SrcList_item *pFrom; if( p==0 || p->pSrc==0 ) return 1; pTabList = p->pSrc; @@ -896,23 +898,21 @@ static int fillInColumnList(Parse *pParse, Select *p){ /* Look up every table in the table list. */ - for(i=0; inSrc; i++){ - if( pTabList->a[i].pTab ){ + for(i=0, pFrom=pTabList->a; inSrc; i++, pFrom++){ + if( pFrom->pTab ){ /* This routine has run before! No need to continue */ return 0; } - if( pTabList->a[i].zName==0 ){ + if( pFrom->zName==0 ){ /* A sub-query in the FROM clause of a SELECT */ - assert( pTabList->a[i].pSelect!=0 ); - if( pTabList->a[i].zAlias==0 ){ + assert( pFrom->pSelect!=0 ); + if( pFrom->zAlias==0 ){ char zFakeName[60]; - sprintf(zFakeName, "sqlite_subquery_%p_", - (void*)pTabList->a[i].pSelect); - sqlite3SetString(&pTabList->a[i].zAlias, zFakeName, 0); + sprintf(zFakeName, "sqlite_subquery_%p_", (void*)pFrom->pSelect); + sqlite3SetString(&pFrom->zAlias, zFakeName, 0); } - pTabList->a[i].pTab = pTab = - sqlite3ResultSetOfSelect(pParse, pTabList->a[i].zAlias, - pTabList->a[i].pSelect); + pFrom->pTab = pTab = + sqlite3ResultSetOfSelect(pParse, pFrom->zAlias, pFrom->pSelect); if( pTab==0 ){ return 1; } @@ -923,8 +923,8 @@ static int fillInColumnList(Parse *pParse, Select *p){ pTab->isTransient = 1; }else{ /* An ordinary table or view name in the FROM clause */ - pTabList->a[i].pTab = pTab = - sqlite3LocateTable(pParse,pTabList->a[i].zName,pTabList->a[i].zDatabase); + pFrom->pTab = pTab = + sqlite3LocateTable(pParse,pFrom->zName,pFrom->zDatabase); if( pTab==0 ){ return 1; } @@ -933,13 +933,13 @@ static int fillInColumnList(Parse *pParse, Select *p){ if( sqlite3ViewGetColumnNames(pParse, pTab) ){ return 1; } - /* If pTabList->a[i].pSelect!=0 it means we are dealing with a + /* If pFrom->pSelect!=0 it means we are dealing with a ** view within a view. The SELECT structure has already been ** copied by the outer view so we can skip the copy step here ** in the inner view. */ - if( pTabList->a[i].pSelect==0 ){ - pTabList->a[i].pSelect = sqlite3SelectDup(pTab->pSelect); + if( pFrom->pSelect==0 ){ + pFrom->pSelect = sqlite3SelectDup(pTab->pSelect); } } } @@ -994,9 +994,9 @@ static int fillInColumnList(Parse *pParse, Select *p){ }else{ zTName = 0; } - for(i=0; inSrc; i++){ - Table *pTab = pTabList->a[i].pTab; - char *zTabName = pTabList->a[i].zAlias; + for(i=0, pFrom=pTabList->a; inSrc; i++, pFrom++){ + Table *pTab = pFrom->pTab; + char *zTabName = pFrom->zAlias; if( zTabName==0 || zTabName[0]==0 ){ zTabName = pTab->zName; } @@ -1188,21 +1188,6 @@ Vdbe *sqlite3GetVdbe(Parse *pParse){ return v; } -#if 0 /***** This routine needs deleting *****/ -static void multiSelectAffinity(Select *p, char *zAff){ - int i; - - if( !p ) return; - multiSelectAffinity(p->pPrior, zAff); - - for(i=0; ipEList->nExpr; i++){ - if( zAff[i]=='\0' ){ - zAff[i] = sqlite3ExprAffinity(p->pEList->a[i].pExpr); - } - } -} -#endif - /* ** Compute the iLimit and iOffset fields of the SELECT based on the ** nLimit and nOffset fields. nLimit and nOffset hold the integers @@ -2112,6 +2097,50 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){ return 1; } +/* +** Analyze and ORDER BY or GROUP BY clause in a SELECT statement. Return +** the number of errors seen. +** +** An ORDER BY or GROUP BY is a list of expressions. If any expression +** is an integer constant, then that expression is replaced by the +** corresponding entry in the result set. +*/ +static int processOrderGroupBy( + Parse *pParse, /* Parsing context */ + ExprList *pOrderBy, /* The ORDER BY or GROUP BY clause to be processed */ + SrcList *pTabList, /* The FROM clause */ + ExprList *pEList, /* The result set */ + int isAgg, /* True if aggregate functions are involved */ + const char *zType /* Either "ORDER" or "GROUP", as appropriate */ +){ + int i; + if( pOrderBy==0 ) return 0; + for(i=0; inExpr; i++){ + int iCol; + Expr *pE = pOrderBy->a[i].pExpr; + if( sqlite3ExprIsInteger(pE, &iCol) && iCol>0 && iCol<=pEList->nExpr ){ + sqlite3ExprDelete(pE); + pE = pOrderBy->a[i].pExpr = sqlite3ExprDup(pEList->a[iCol-1].pExpr); + } + if( sqlite3ExprResolveAndCheck(pParse, pTabList, pEList, pE, isAgg, 0) ){ + return 1; + } + if( sqlite3ExprIsConstant(pE) ){ + if( sqlite3ExprIsInteger(pE, &iCol)==0 ){ + sqlite3ErrorMsg(pParse, + "%s BY terms must not be non-integer constants", zType); + return 1; + }else if( iCol<=0 || iCol>pEList->nExpr ){ + sqlite3ErrorMsg(pParse, + "%s BY column number %d out of range - should be " + "between 1 and %d", zType, iCol, pEList->nExpr); + return 1; + } + } + } + return 0; +} + /* ** Generate code for the given SELECT statement. ** @@ -2254,88 +2283,27 @@ int sqlite3Select( ** Resolve the column names and do a semantics check on all the expressions. */ for(i=0; inExpr; i++){ - if( sqlite3ExprResolveIds(pParse, pTabList, 0, pEList->a[i].pExpr) ){ - goto select_end; - } - if( sqlite3ExprCheck(pParse, pEList->a[i].pExpr, 1, &isAgg) ){ + if( sqlite3ExprResolveAndCheck(pParse, pTabList, 0, pEList->a[i].pExpr, + 1, &isAgg) ){ goto select_end; } } - if( pWhere ){ - if( sqlite3ExprResolveIds(pParse, pTabList, pEList, pWhere) ){ - goto select_end; - } - if( sqlite3ExprCheck(pParse, pWhere, 0, 0) ){ - goto select_end; - } + if( sqlite3ExprResolveAndCheck(pParse, pTabList, pEList, pWhere, 0, 0) ){ + goto select_end; } if( pHaving ){ if( pGroupBy==0 ){ sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING"); goto select_end; } - if( sqlite3ExprResolveIds(pParse, pTabList, pEList, pHaving) ){ - goto select_end; - } - if( sqlite3ExprCheck(pParse, pHaving, 1, &isAgg) ){ + if( sqlite3ExprResolveAndCheck(pParse, pTabList, pEList,pHaving,1,&isAgg) ){ goto select_end; } } - if( pOrderBy ){ - for(i=0; inExpr; i++){ - int iCol; - Expr *pE = pOrderBy->a[i].pExpr; - if( sqlite3ExprIsInteger(pE, &iCol) && iCol>0 && iCol<=pEList->nExpr ){ - sqlite3ExprDelete(pE); - pE = pOrderBy->a[i].pExpr = sqlite3ExprDup(pEList->a[iCol-1].pExpr); - } - if( sqlite3ExprResolveIds(pParse, pTabList, pEList, pE) ){ - goto select_end; - } - if( sqlite3ExprCheck(pParse, pE, isAgg, 0) ){ - goto select_end; - } - if( sqlite3ExprIsConstant(pE) ){ - if( sqlite3ExprIsInteger(pE, &iCol)==0 ){ - sqlite3ErrorMsg(pParse, - "ORDER BY terms must not be non-integer constants"); - goto select_end; - }else if( iCol<=0 || iCol>pEList->nExpr ){ - sqlite3ErrorMsg(pParse, - "ORDER BY column number %d out of range - should be " - "between 1 and %d", iCol, pEList->nExpr); - goto select_end; - } - } - } - } - if( pGroupBy ){ - for(i=0; inExpr; i++){ - int iCol; - Expr *pE = pGroupBy->a[i].pExpr; - if( sqlite3ExprIsInteger(pE, &iCol) && iCol>0 && iCol<=pEList->nExpr ){ - sqlite3ExprDelete(pE); - pE = pGroupBy->a[i].pExpr = sqlite3ExprDup(pEList->a[iCol-1].pExpr); - } - if( sqlite3ExprResolveIds(pParse, pTabList, pEList, pE) ){ - goto select_end; - } - if( sqlite3ExprCheck(pParse, pE, isAgg, 0) ){ - goto select_end; - } - if( sqlite3ExprIsConstant(pE) ){ - if( sqlite3ExprIsInteger(pE, &iCol)==0 ){ - sqlite3ErrorMsg(pParse, - "GROUP BY terms must not be non-integer constants"); - goto select_end; - }else if( iCol<=0 || iCol>pEList->nExpr ){ - sqlite3ErrorMsg(pParse, - "GROUP BY column number %d out of range - should be " - "between 1 and %d", iCol, pEList->nExpr); - goto select_end; - } - } - } + if( processOrderGroupBy(pParse, pOrderBy, pTabList, pEList, isAgg, "ORDER") + || processOrderGroupBy(pParse, pGroupBy, pTabList, pEList, isAgg, "GROUP") + ){ + goto select_end; } /* Begin generating code. diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 5ae24c4b13..3881dfa435 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.315 2004/08/08 20:22:18 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.316 2004/08/21 17:54:45 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -888,8 +888,6 @@ struct WhereInfo { int iContinue; /* Jump here to continue with next record */ int iBreak; /* Jump here to break out of the loop */ int nLevel; /* Number of nested loop */ - int savedNTab; /* Value of pParse->nTab before WhereBegin() */ - int peakNTab; /* Value of pParse->nTab after WhereBegin() */ WhereLevel a[1]; /* Information about each nest loop in the WHERE */ }; @@ -1278,6 +1276,7 @@ int sqlite3ExprCheck(Parse*, Expr*, int, int*); int sqlite3ExprCompare(Expr*, Expr*); int sqliteFuncId(Token*); int sqlite3ExprResolveIds(Parse*, SrcList*, ExprList*, Expr*); +int sqlite3ExprResolveAndCheck(Parse*,SrcList*,ExprList*,Expr*,int,int*); int sqlite3ExprAnalyzeAggregates(Parse*, Expr*); Vdbe *sqlite3GetVdbe(Parse*); void sqlite3Randomness(int, void*); @@ -1294,7 +1293,7 @@ void sqlite3GenerateRowIndexDelete(sqlite*, Vdbe*, Table*, int, char*); void sqlite3GenerateIndexKey(Vdbe*, Index*, int); void sqlite3GenerateConstraintChecks(Parse*,Table*,int,char*,int,int,int,int); void sqlite3CompleteInsertion(Parse*, Table*, int, char*, int, int, int); -int sqlite3OpenTableAndIndices(Parse*, Table*, int); +void sqlite3OpenTableAndIndices(Parse*, Table*, int, int); void sqlite3BeginWriteOperation(Parse*, int, int); void sqlite3EndWriteOperation(Parse*); Expr *sqlite3ExprDup(Expr*); diff --git a/src/trigger.c b/src/trigger.c index 49bd0768cd..df8e5fb4d7 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -647,8 +647,6 @@ static int codeTriggerProgram( int orconf; while( pTriggerStep ){ - int saveNTab = pParse->nTab; - orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin; pParse->trigStack->orconf = orconf; switch( pTriggerStep->op ){ @@ -696,7 +694,6 @@ static int codeTriggerProgram( default: assert(0); } - pParse->nTab = saveNTab; pTriggerStep = pTriggerStep->pNext; } diff --git a/src/update.c b/src/update.c index 59a373aab6..e57537d5b2 100644 --- a/src/update.c +++ b/src/update.c @@ -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.85 2004/06/21 06:50:29 danielk1977 Exp $ +** $Id: update.c,v 1.86 2004/08/21 17:54:45 drh Exp $ */ #include "sqliteInt.h" @@ -111,10 +111,8 @@ void sqlite3Update( */ chngRecno = 0; for(i=0; inExpr; i++){ - if( sqlite3ExprResolveIds(pParse, pTabList, 0, pChanges->a[i].pExpr) ){ - goto update_cleanup; - } - if( sqlite3ExprCheck(pParse, pChanges->a[i].pExpr, 0, 0) ){ + if( sqlite3ExprResolveAndCheck(pParse, pTabList, 0, + pChanges->a[i].pExpr, 0, 0) ){ goto update_cleanup; } for(j=0; jnCol; j++){ @@ -190,13 +188,8 @@ void sqlite3Update( /* Resolve the column names in all the expressions in the ** WHERE clause. */ - if( pWhere ){ - if( sqlite3ExprResolveIds(pParse, pTabList, 0, pWhere) ){ - goto update_cleanup; - } - if( sqlite3ExprCheck(pParse, pWhere, 0, 0) ){ - goto update_cleanup; - } + if( sqlite3ExprResolveAndCheck(pParse, pTabList, 0, pWhere, 0, 0) ){ + goto update_cleanup; } /* Start the view context @@ -412,7 +405,6 @@ void sqlite3Update( sqlite3VdbeAddOp(v, OP_Close, iCur+i+1, 0); } sqlite3VdbeAddOp(v, OP_Close, iCur, 0); - pParse->nTab = iCur; } if( sqlite3CodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_AFTER, pTab, newIdx, oldIdx, onError, addr) ){ @@ -435,7 +427,6 @@ void sqlite3Update( } } sqlite3VdbeAddOp(v, OP_Close, iCur, 0); - pParse->nTab = iCur; }else{ sqlite3VdbeAddOp(v, OP_Close, newIdx, 0); sqlite3VdbeAddOp(v, OP_Close, oldIdx, 0); diff --git a/src/vdbe.c b/src/vdbe.c index 12c8eadfce..5a92c9b078 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -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.408 2004/08/08 23:39:19 drh Exp $ +** $Id: vdbe.c,v 1.409 2004/08/21 17:54:45 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -261,18 +261,8 @@ static Sorter *Merge(Sorter *pLeft, Sorter *pRight, KeyInfo *pKeyInfo){ */ static Cursor *allocateCursor(Vdbe *p, int iCur){ Cursor *pCx; - if( iCur>=p->nCursor ){ - int i; - p->apCsr = sqliteRealloc( p->apCsr, (iCur+1)*sizeof(Cursor*) ); - if( p->apCsr==0 ){ - p->nCursor = 0; - return 0; - } - for(i=p->nCursor; iapCsr[i] = 0; - } - p->nCursor = iCur+1; - }else if( p->apCsr[iCur] ){ + assert( iCurnCursor ); + if( p->apCsr[iCur] ){ sqlite3VdbeFreeCursor(p->apCsr[iCur]); } p->apCsr[iCur] = pCx = sqliteMalloc( sizeof(Cursor) ); @@ -802,8 +792,7 @@ case OP_Variable: { assert( j>=0 && jnVar ); pTos++; - /* sqlite3VdbeMemCopyStatic(pTos, &p->apVar[j]); */ - memcpy(pTos, &p->apVar[j], sizeof(*pTos)-NBFS); + memcpy(pTos, &p->aVar[j], sizeof(*pTos)-NBFS); pTos->xDel = 0; if( pTos->flags&(MEM_Str|MEM_Blob) ){ pTos->flags &= ~(MEM_Dyn|MEM_Ephem|MEM_Short); @@ -4056,7 +4045,7 @@ case OP_Sort: { p->pSort = pElem->pNext; pElem->pNext = 0; for(i=0; ip1; Mem *pMem; assert( pTos>=p->aStack ); - if( i>=p->nMem ){ - int nOld = p->nMem; - Mem *aMem; - p->nMem = i + 5; - aMem = sqliteRealloc(p->aMem, p->nMem*sizeof(p->aMem[0])); - if( aMem==0 ) goto no_mem; - if( aMem!=p->aMem ){ - int j; - for(j=0; jaMem = aMem; - if( nOldnMem ){ - memset(&p->aMem[nOld], 0, sizeof(p->aMem[0])*(p->nMem-nOld)); - } - } + assert( inMem ); Deephemeralize(pTos); pMem = &p->aMem[i]; Release(pMem); *pMem = *pTos; - if( pMem->flags & MEM_Dyn ){ - if( pOp->p2 ){ - pTos->flags = MEM_Null; - }else{ - pMem->z = sqliteMallocRaw( pMem->n+2 ); - if( pMem->z==0 ) goto no_mem; - memcpy(pMem->z, pTos->z, pMem->n); - memcpy(&pMem->z[pMem->n], "\000", 2); - pMem->flags |= MEM_Term; - } - }else if( pMem->flags & MEM_Short ){ + pTos->flags = MEM_Null; + if( pMem->flags & MEM_Short ){ pMem->z = pMem->zShort; } - if( pOp->p2 ){ - Release(pTos); - pTos--; - } - break; -} + pTos--; + /* If P2 is 0 then fall thru to the next opcode, OP_MemLoad, that will + ** restore the top of the stack to its original value. + */ + if( pOp->p2 ){ + break; + } +} /* Opcode: MemLoad P1 * * ** ** Push a copy of the value in memory location P1 onto the stack. @@ -4338,15 +4302,12 @@ case OP_AggFocus: { if( res==0 ){ rc = sqlite3BtreeData(p->agg.pCsr, 0, sizeof(AggElem*), (char *)&p->agg.pCurrent); - if( rc!=SQLITE_OK ){ - goto abort_due_to_error; - } pc = pOp->p2 - 1; }else{ rc = AggInsert(&p->agg, zKey, nKey); - if( rc!=SQLITE_OK ){ - goto abort_due_to_error; - } + } + if( rc!=SQLITE_OK ){ + goto abort_due_to_error; } Release(pTos); pTos--; @@ -4371,9 +4332,8 @@ case OP_AggSet: { pMem = &pFocus->aMem[i]; Release(pMem); *pMem = *pTos; - if( pMem->flags & MEM_Dyn ){ - pTos->flags = MEM_Null; - }else if( pMem->flags & MEM_Short ){ + pTos->flags = MEM_Null; + if( pMem->flags & MEM_Short ){ pMem->z = pMem->zShort; } pTos--; @@ -4422,23 +4382,23 @@ case OP_AggGet: { */ case OP_AggNext: { int res; + assert( rc==SQLITE_OK ); CHECK_FOR_INTERRUPT; if( p->agg.searching==0 ){ p->agg.searching = 1; if( p->agg.pCsr ){ rc = sqlite3BtreeFirst(p->agg.pCsr, &res); - if( rc!=SQLITE_OK ) goto abort_due_to_error; }else{ res = 0; } }else{ if( p->agg.pCsr ){ rc = sqlite3BtreeNext(p->agg.pCsr, &res); - if( rc!=SQLITE_OK ) goto abort_due_to_error; }else{ res = 1; } } + if( rc!=SQLITE_OK ) goto abort_due_to_error; if( res!=0 ){ pc = pOp->p2 - 1; }else{ @@ -4453,24 +4413,23 @@ case OP_AggNext: { } aMem = p->agg.pCurrent->aMem; for(i=0; iagg.nMem; i++){ - int freeCtx; - if( p->agg.apFunc[i]==0 ) continue; - if( p->agg.apFunc[i]->xFinalize==0 ) continue; + FuncDef *pFunc = p->agg.apFunc[i]; + Mem *pMem = &aMem[i]; + if( pFunc==0 || pFunc->xFinalize==0 ) continue; ctx.s.flags = MEM_Null; - ctx.s.z = aMem[i].zShort; - ctx.pAgg = (void*)aMem[i].z; - ctx.cnt = aMem[i].i; + ctx.s.z = pMem->zShort; + ctx.pAgg = (void*)pMem->z; + ctx.cnt = pMem->i; ctx.isStep = 0; - ctx.pFunc = p->agg.apFunc[i]; - (*p->agg.apFunc[i]->xFinalize)(&ctx); - aMem[i].z = ctx.pAgg; - freeCtx = aMem[i].z && aMem[i].z!=aMem[i].zShort; - if( freeCtx ){ - sqliteFree( aMem[i].z ); + ctx.pFunc = pFunc; + pFunc->xFinalize(&ctx); + pMem->z = ctx.pAgg; + if( pMem->z && pMem->z!=pMem->zShort ){ + sqliteFree( pMem->z ); } - aMem[i] = ctx.s; - if( aMem[i].flags & MEM_Short ){ - aMem[i].z = aMem[i].zShort; + *pMem = ctx.s; + if( pMem->flags & MEM_Short ){ + pMem->z = pMem->zShort; } } } diff --git a/src/vdbe.h b/src/vdbe.h index 6c11f22873..6e7d11c3dd 100644 --- a/src/vdbe.h +++ b/src/vdbe.h @@ -15,7 +15,7 @@ ** or VDBE. The VDBE implements an abstract machine that runs a ** simple program to access and modify the underlying database. ** -** $Id: vdbe.h,v 1.89 2004/06/27 21:31:40 drh Exp $ +** $Id: vdbe.h,v 1.90 2004/08/21 17:54:45 drh Exp $ */ #ifndef _SQLITE_VDBE_H_ #define _SQLITE_VDBE_H_ @@ -110,7 +110,7 @@ int sqlite3VdbeFindOp(Vdbe*, int, int, int); VdbeOp *sqlite3VdbeGetOp(Vdbe*, int); int sqlite3VdbeMakeLabel(Vdbe*); void sqlite3VdbeDelete(Vdbe*); -void sqlite3VdbeMakeReady(Vdbe*,int,int); +void sqlite3VdbeMakeReady(Vdbe*,int,int,int,int); int sqlite3VdbeFinalize(Vdbe*); void sqlite3VdbeResolveLabel(Vdbe*, int); int sqlite3VdbeCurrentAddr(Vdbe*); diff --git a/src/vdbeInt.h b/src/vdbeInt.h index c010b572c4..af6667a9f1 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -311,15 +311,10 @@ struct Vdbe { int nCursor; /* Number of slots in apCsr[] */ Cursor **apCsr; /* One element of this array for each open cursor */ Sorter *pSort; /* A linked list of objects to be sorted */ - FILE *pFile; /* At most one open file handler */ - int nField; /* Number of file fields */ - char **azField; /* Data for each file field */ - int nVar; /* Number of entries in apVar[] */ - Mem *apVar; /* Values for the OP_Variable opcode. */ + int nVar; /* Number of entries in aVar[] */ + Mem *aVar; /* Values for the OP_Variable opcode. */ char **azVar; /* Name of variables */ int okVar; /* True if azVar[] has been initialized */ - char *zLine; /* A single line from the input file */ - int nLineAlloc; /* Number of spaces allocated for zLine */ int magic; /* Magic number for sanity checking */ int nMem; /* Number of memory locations currently allocated */ Mem *aMem; /* The memory locations */ diff --git a/src/vdbeapi.c b/src/vdbeapi.c index 2bc31bd23b..b955190aec 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -414,7 +414,7 @@ static int vdbeUnbind(Vdbe *p, int i){ return SQLITE_RANGE; } i--; - pVar = &p->apVar[i]; + pVar = &p->aVar[i]; sqlite3VdbeMemRelease(pVar); pVar->flags = MEM_Null; sqlite3Error(p->db, SQLITE_OK, 0); @@ -439,7 +439,7 @@ int sqlite3_bind_blob( if( rc || zData==0 ){ return rc; } - pVar = &p->apVar[i-1]; + pVar = &p->aVar[i-1]; rc = sqlite3VdbeMemSetStr(pVar, zData, nData, 0, xDel); return rc; } @@ -448,7 +448,7 @@ int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){ Vdbe *p = (Vdbe *)pStmt; rc = vdbeUnbind(p, i); if( rc==SQLITE_OK ){ - sqlite3VdbeMemSetDouble(&p->apVar[i-1], rValue); + sqlite3VdbeMemSetDouble(&p->aVar[i-1], rValue); } return rc; } @@ -460,7 +460,7 @@ int sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValue){ Vdbe *p = (Vdbe *)pStmt; rc = vdbeUnbind(p, i); if( rc==SQLITE_OK ){ - sqlite3VdbeMemSetInt64(&p->apVar[i-1], iValue); + sqlite3VdbeMemSetInt64(&p->aVar[i-1], iValue); } return rc; } @@ -482,7 +482,7 @@ int sqlite3_bind_text( if( rc || zData==0 ){ return rc; } - pVar = &p->apVar[i-1]; + pVar = &p->aVar[i-1]; rc = sqlite3VdbeMemSetStr(pVar, zData, nData, SQLITE_UTF8, xDel); if( rc ){ return rc; @@ -505,7 +505,7 @@ int sqlite3_bind_text16( if( rc || zData==0 ){ return rc; } - pVar = &p->apVar[i-1]; + pVar = &p->aVar[i-1]; rc = sqlite3VdbeMemSetStr(pVar, zData, nData, SQLITE_UTF16NATIVE, xDel); if( rc ){ diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 9e72062053..1734677c31 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -547,6 +547,8 @@ void sqlite3VdbePrintSql(Vdbe *p){ void sqlite3VdbeMakeReady( Vdbe *p, /* The VDBE */ int nVar, /* Number of '?' see in the SQL statement */ + int nMem, /* Number of memory cells to allocate */ + int nCursor, /* Number of cursors to allocate */ int isExplain /* True if the EXPLAIN keywords is present */ ){ int n; @@ -568,20 +570,31 @@ void sqlite3VdbeMakeReady( ** Allocation all the stack space we will ever need. */ if( p->aStack==0 ){ - p->nVar = nVar; assert( nVar>=0 ); n = isExplain ? 10 : p->nOp; p->aStack = sqliteMalloc( n*(sizeof(p->aStack[0])+sizeof(Mem*)) /* aStack, apArg */ - + p->nVar*sizeof(Mem) /* apVar */ - + p->nVar*sizeof(char*) /* apVarName */ + + nVar*sizeof(Mem) /* aVar */ + + nVar*sizeof(char*) /* azVar */ + + nMem*sizeof(Mem) /* aMem */ + + nCursor*sizeof(Cursor*) /* apCsr */ ); - p->apArg = (Mem **)&p->aStack[n]; - p->apVar = (Mem *)&p->apArg[n]; - p->azVar = (char**)&p->apVar[p->nVar]; - p->okVar = 0; - for(n=0; nnVar; n++){ - p->apVar[n].flags = MEM_Null; + if( !sqlite3_malloc_failed ){ + p->apArg = (Mem **)&p->aStack[n]; + p->aVar = (Mem *)&p->apArg[n]; + p->azVar = (char**)&p->aVar[nVar]; + p->okVar = 0; + p->nVar = nVar; + p->aMem = (Mem*)&p->azVar[nVar]; + p->nMem = nMem; + p->apCsr = (Cursor**)&p->aMem[nMem]; + p->nCursor = nCursor; + for(n=0; naVar[n].flags = MEM_Null; + } + for(n=0; naMem[n].flags = MEM_Null; + } } } @@ -800,12 +813,11 @@ void sqlite3VdbeFreeCursor(Cursor *pCx){ */ static void closeAllCursors(Vdbe *p){ int i; + if( p->apCsr==0 ) return; for(i=0; inCursor; i++){ sqlite3VdbeFreeCursor(p->apCsr[i]); + p->apCsr[i] = 0; } - sqliteFree(p->apCsr); - p->apCsr = 0; - p->nCursor = 0; } /* @@ -826,33 +838,14 @@ static void Cleanup(Vdbe *p){ p->pTos = pTos; } closeAllCursors(p); - if( p->aMem ){ - for(i=0; inMem; i++){ - sqlite3VdbeMemRelease(&p->aMem[i]); - } + for(i=0; inMem; i++){ + sqlite3VdbeMemRelease(&p->aMem[i]); } - sqliteFree(p->aMem); - p->aMem = 0; - p->nMem = 0; if( p->pList ){ sqlite3VdbeKeylistFree(p->pList); p->pList = 0; } sqlite3VdbeSorterReset(p); - if( p->pFile ){ - if( p->pFile!=stdin ) fclose(p->pFile); - p->pFile = 0; - } - if( p->azField ){ - sqliteFree(p->azField); - p->azField = 0; - } - p->nField = 0; - if( p->zLine ){ - sqliteFree(p->zLine); - p->zLine = 0; - } - p->nLineAlloc = 0; sqlite3VdbeAggReset(0, &p->agg, 0); if( p->keylistStack ){ int ii; @@ -1360,7 +1353,7 @@ void sqlite3VdbeDelete(Vdbe *p){ } } for(i=0; inVar; i++){ - sqlite3VdbeMemRelease(&p->apVar[i]); + sqlite3VdbeMemRelease(&p->aVar[i]); } sqliteFree(p->aOp); sqliteFree(p->aLabel); diff --git a/src/where.c b/src/where.c index 0145873bc2..49091d4760 100644 --- a/src/where.c +++ b/src/where.c @@ -12,7 +12,7 @@ ** This module contains C code that generates VDBE code used to process ** the WHERE clause of SQL statements. ** -** $Id: where.c,v 1.111 2004/07/20 18:23:15 drh Exp $ +** $Id: where.c,v 1.112 2004/08/21 17:54:45 drh Exp $ */ #include "sqliteInt.h" @@ -484,7 +484,6 @@ WhereInfo *sqlite3WhereBegin( } pWInfo->pParse = pParse; pWInfo->pTabList = pTabList; - pWInfo->peakNTab = pWInfo->savedNTab = pParse->nTab; pWInfo->iBreak = sqlite3VdbeMakeLabel(v); /* Special case: a WHERE clause that is constant. Evaluate the @@ -686,7 +685,6 @@ WhereInfo *sqlite3WhereBegin( loopMask |= mask; if( pBestIdx ){ pWInfo->a[i].iCur = pParse->nTab++; - pWInfo->peakNTab = pParse->nTab; } } @@ -721,7 +719,6 @@ WhereInfo *sqlite3WhereBegin( if( pIdx==0 ){ pWInfo->a[0].pIdx = pSortIdx; pWInfo->a[0].iCur = pParse->nTab++; - pWInfo->peakNTab = pParse->nTab; } pWInfo->a[0].bRev = bRev; *ppOrderBy = 0; @@ -1210,11 +1207,6 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){ sqlite3VdbeAddOp(v, OP_Close, pLevel->iCur, 0); } } -#if 0 /* Never reuse a cursor */ - if( pWInfo->pParse->nTab==pWInfo->peakNTab ){ - pWInfo->pParse->nTab = pWInfo->savedNTab; - } -#endif sqliteFree(pWInfo); return; } diff --git a/test/crash.test b/test/crash.test index 963d628d97..1522a1a820 100644 --- a/test/crash.test +++ b/test/crash.test @@ -20,7 +20,7 @@ # The special crash-test module with its os_test.c backend only works # on Unix. # -# $Id: crash.test,v 1.7 2004/06/28 04:52:31 danielk1977 Exp $ +# $Id: crash.test,v 1.8 2004/08/21 17:54:46 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -167,7 +167,7 @@ do_test crash-2.1 { execsql { COMMIT } set ::sig [signature] execsql { SELECT sum(a), sum(b), sum(c) from abc } -} {499500 999000 1498500} +} {499500.0 999000.0 1498500.0} do_test crash-2.2 { expr [file size test.db] / 1024 } {19} @@ -273,6 +273,7 @@ for {set i 1} {$i<$repeats} {incr i} { } $sig2 } set i 0 +set i 55 while {[incr i]} { set sig [signature] set sig2 [signature2]