diff --git a/manifest b/manifest index f6a66bf714..8e7eec4f88 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Correctly\screate\san\sindex\sthat\suses\san\sINTEGER\sPRIMARY\sKEY\sas\sone\sof\scolumns\nto\sbe\sindexed.\s(CVS\s946) -D 2003-05-01T16:56:03 +C VDBE\scursors\snumbers\sfor\stables\sin\sa\sjoin\sdo\snot\shave\sto\sbe\sconsecutive.\nThis\sis\sone\sstep\son\sthe\sroad\sto\sfixing\sticket\s#272.\s(CVS\s947) +D 2003-05-02T14:32:13 F Makefile.in 004acec253ecdde985c8ecd5b7c9accdb210378f F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd @@ -20,19 +20,19 @@ F spec.template 238f7db425a78dc1bb7682e56e3834c7270a3f5e F sqlite.1 83f4a9d37bdf2b7ef079a82d54eaf2e3509ee6ea F sqlite.pc.in 30552343140c53304c2a658c080fbe810cd09ca2 F src/attach.c 7ebc7487de43e357a64226f8abef81f2669f2183 -F src/auth.c 3be3c7434592117f049703966b940e0b07088ae2 +F src/auth.c 53b8923f17f364af84501fa99dc00c779913a26d F src/btree.c 077d75aee4ed63f3628698611ba43c87097d458d F src/btree.h 23c50e00709de16a5dce1fcea9c0429cc955ff0e F src/btree_rb.c 8e00e40be264716e1929987878672e55d9e0e76d -F src/build.c d35b7a6595af2ab07083b7f63bd5d22578b3c189 +F src/build.c e24461d42381a36de88de6af06c03d9f14588705 F src/copy.c 44b13fd4d2444fb53bff8a5ecee1c5f6f86a8263 -F src/delete.c 0f7c26aaebc417ad66a2a1099e59cc4056512c31 +F src/delete.c f9536a75b444a21f11b7a1bc0fb8c876f691b013 F src/encode.c faf03741efe921755ec371cf4a6984536de00042 -F src/expr.c 46e2bb93abd6c70e67c8cdc5d92fdcd0b95498f3 +F src/expr.c a666ef5220ca90ebcf40c8ccc783966a345a7616 F src/func.c 882c3ed5a02be18cd904715c7ec62947a34a3605 F src/hash.c 4fc39feb7b7711f6495ee9f2159559bedb043e1f F src/hash.h cd0433998bc1a3759d244e1637fe5a3c13b53bf8 -F src/insert.c 19882be1edc4b1629b8f3097e2615164f2c9cecb +F src/insert.c c230a8c216f6788095d46f0e270406a93aae45af F src/main.c 5265058c9a598b4714dc9e528152b81fcb31e7ad F src/md5.c fe4f9c9c6f71dfc26af8da63e4d04489b1430565 F src/os.c 94b618c0c0a76210e53857d77c96d2f042dc33b1 @@ -43,11 +43,11 @@ F src/parse.y 39b5240cb78047dc56d6d37c398baed7ba556779 F src/pragma.c 118fe400d71b7fdcc03580d5eab6bb5aa00772a5 F src/printf.c fc5fdef6e92ad205005263661fe9716f55a49f3e F src/random.c 19e8e00fe0df32a742f115773f57651be327cabe -F src/select.c d1c876b9078894bc956cf1a5b38abd1a5abaf70b +F src/select.c 493360f3003719ad61d49863c4f5db0bad9022cb F src/shell.c 6f59240f69e65a1c4e1d06492eb9238092defc34 F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e F src/sqlite.h.in eec06462cba262c0ee03f38462a18a4bc66dda4e -F src/sqliteInt.h faf133e1441b7c7b93ad5d8a58201d4849033b75 +F src/sqliteInt.h a3d84942dacaf72fbe1426adfbd37e8cf5f57e97 F src/table.c eed2098c9b577aa17f8abe89313a9c4413f57d63 F src/tclsqlite.c 9e25f98f1765afa0716144ef57abda75c88f688d F src/test1.c 4596acd9d9f2a49fda0160a8a6dee5bfc7c6c325 @@ -55,13 +55,13 @@ F src/test2.c 5014337d8576b731cce5b5a14bec4f0daf432700 F src/test3.c 30985ebdfaf3ee1462a9b0652d3efbdc8d9798f5 F src/threadtest.c d641a5219e718e18a1a80a50eb9bb549f451f42e F src/tokenize.c 067d1a477a94af7712ca74e09aaa6bd0f7299527 -F src/trigger.c 62d1e1b837a98f1fa7511c77977d51c8516ddb65 -F src/update.c f40376ed2e092a7040c6fc6fa0add59fad5c5e76 +F src/trigger.c 8ee811986080de60d9d883ad96daffea82014f27 +F src/update.c dc3b680b4cf2cb6d839950b68d632850746639b9 F src/util.c 87635cfdfffa056a8d3147719357aa442374f78c F src/vacuum.c 14ac3073203fa021e01ffe33db56968ad79a8344 -F src/vdbe.c 48098080d2b5d35d4cc28ac2a4855c7730f6ee7b +F src/vdbe.c 829fa31c2169588db7a041950cb95c6bb75811a6 F src/vdbe.h 985c24f312d10f9ef8f9a8b8ea62fcdf68e82f21 -F src/where.c f632cd30f013163484a4d60c249d36fe31f5be12 +F src/where.c ef11773a07cf075740378d7d1cbabf328146fdc9 F test/all.test 569a92a8ee88f5300c057cc4a8f50fbbc69a3242 F test/attach.test b311c83e370e6b22b79a8279317039440ce64862 F test/auth.test dee78be1f4f920bd6b15c4c947ce4d01bfe2826d @@ -92,7 +92,7 @@ F test/limit.test 9ffb965a0f5bf7152187ef3d8d1249b96e5620bf F test/lock.test 388a3a10962d2d571c0c1821cc35bf069ee73473 F test/main.test a028743affca67670e24c97527d1f4ad4bc2aad3 F test/malloc.test 7ba32a9ebd3aeed52ae4aaa6d42ca37e444536fd -F test/memdb.test 4494051bcf72df58d9c631a5bc1260cba2b021cc +F test/memdb.test 3acf1453a5705d1aa524d3027667ca3d9c77c69f F test/memleak.test a18e6810cae96d2f6f5136920267adbefc8e1e90 F test/minmax.test b54ac3bc45460a4976b08ef363e05c032418726e F test/misc1.test 865c907df58195364eaf2e69426e9674bc8d1a8c @@ -127,7 +127,7 @@ F test/unique.test 22a46df72a3e0a3fd1a2d39e96fb59f18448dd5f F test/update.test 198360dfa14e65354dbcc66d5b98d8070780e42b F test/vacuum.test 4d8c8af30338577af03e563bc815d7898ae65258 F test/version.test 605fd0d7e7d571370c32b12dbf395b58953de246 -F test/view.test d356f445d481c04ffa6036a4c61cb8ba70289f69 +F test/view.test 8b3b0b30674865af2c87acbdf945e369f92012a5 F test/where.test d719129a052280fe245a2ddcbd09bcc0b8c17ce4 F tool/diffdb.c 7524b1b5df217c20cd0431f6789851a4e0cb191b F tool/lemon.c 14fedcde9cf70aa6040b89de164cf8f56f92a4b9 @@ -165,7 +165,7 @@ F www/speed.tcl cb4c10a722614aea76d2c51f32ee43400d5951be F www/sqlite.tcl ae3dcfb077e53833b59d4fcc94d8a12c50a44098 F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218 -P 20fcead42bc875f13eec52971530342ff00c5eda -R 7ac507f145c490883ec534eb0c6164c6 +P 6d019e0baa3219614a9bc5b550a0f9fe3f7e731a +R f7e61e2db6268bcec64f93ca941fa9e1 U drh -Z a8877957a40cc5dcaf456e37a442b5a4 +Z affbf408d9fd8c226a5447c7e8084f51 diff --git a/manifest.uuid b/manifest.uuid index 3b2c178722..a5fdcd2ea5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6d019e0baa3219614a9bc5b550a0f9fe3f7e731a \ No newline at end of file +be7aed2011b4af868b6a0c370c3d41354ae0cdf4 \ No newline at end of file diff --git a/src/auth.c b/src/auth.c index 2a5a8f5648..4bd4903f9e 100644 --- a/src/auth.c +++ b/src/auth.c @@ -14,7 +14,7 @@ ** systems that do not need this facility may omit it by recompiling ** the library with -DSQLITE_OMIT_AUTHORIZATION=1 ** -** $Id: auth.c,v 1.8 2003/04/25 17:52:11 drh Exp $ +** $Id: auth.c,v 1.9 2003/05/02 14:32:13 drh Exp $ */ #include "sqliteInt.h" @@ -76,8 +76,8 @@ static void sqliteAuthBadReturnCode(Parse *pParse, int rc){ /* ** The pExpr should be a TK_COLUMN expression. The table referred to -** is in pTabList with an offset of base. Check to see if it is OK to read -** this particular column. +** is in pTabList or else it is the NEW or OLD table of a trigger. +** Check to see if it is OK to read this particular column. ** ** If the auth function returns SQLITE_IGNORE, change the TK_COLUMN ** instruction into a TK_NULL. If the auth function returns SQLITE_DENY, @@ -86,8 +86,7 @@ static void sqliteAuthBadReturnCode(Parse *pParse, int rc){ void sqliteAuthRead( Parse *pParse, /* The parser context */ Expr *pExpr, /* The expression to check authorization on */ - SrcList *pTabList, /* All table that pExpr might refer to */ - int base /* Offset of pTabList relative to pExpr */ + SrcList *pTabList /* All table that pExpr might refer to */ ){ sqlite *db = pParse->db; int rc; @@ -98,7 +97,9 @@ void sqliteAuthRead( if( db->xAuth==0 ) return; assert( pExpr->op==TK_COLUMN ); - iSrc = pExpr->iTable - base; + for(iSrc=0; iSrcnSrc; iSrc++){ + if( pExpr->iTable==pTabList->a[iSrc].iCursor ) break; + } if( iSrc>=0 && iSrcnSrc ){ pTab = pTabList->a[iSrc].pTab; }else{ diff --git a/src/build.c b/src/build.c index 95eb73a17d..a4091d81f7 100644 --- a/src/build.c +++ b/src/build.c @@ -23,7 +23,7 @@ ** ROLLBACK ** PRAGMA ** -** $Id: build.c,v 1.151 2003/05/01 16:56:03 drh Exp $ +** $Id: build.c,v 1.152 2003/05/02 14:32:13 drh Exp $ */ #include "sqliteInt.h" #include @@ -1767,7 +1767,7 @@ void sqliteCreateIndex( if( pTab->iPKey==iCol ){ sqliteVdbeAddOp(v, OP_Dup, i, 0); }else{ - sqliteVdbeAddOp(v, OP_Column, 2, pIndex->aiColumn[i]); + sqliteVdbeAddOp(v, OP_Column, 2, iCol); } } sqliteVdbeAddOp(v, OP_MakeIdxKey, pIndex->nColumn, 0); @@ -1993,7 +1993,7 @@ void sqliteSrcListAssignCursors(Parse *pParse, SrcList *pList){ int i; for(i=0; inSrc; i++){ if( pList->a[i].iCursor<0 ){ - pList->a[i].iCursor = ++pParse->nTab; + pList->a[i].iCursor = pParse->nTab++; } } } diff --git a/src/delete.c b/src/delete.c index 14c7a20e16..6c46c122d8 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.55 2003/04/25 17:52:11 drh Exp $ +** $Id: delete.c,v 1.56 2003/05/02 14:32:13 drh Exp $ */ #include "sqliteInt.h" @@ -65,7 +65,7 @@ void sqliteDeleteFrom( int i; /* Loop counter */ WhereInfo *pWInfo; /* Information about the WHERE clause */ Index *pIdx; /* For looping over indices of the table */ - int base; /* Index of the first available table cursor */ + int iCur; /* VDBE Cursor number for pTab */ sqlite *db; /* Main database structure */ int isView; /* True if attempting to delete from a view */ AuthContext sContext; /* Authorization context */ @@ -119,9 +119,10 @@ void sqliteDeleteFrom( /* Resolve the column names in all the expressions. */ - base = pParse->nTab++; + assert( pTabList->nSrc==1 ); + iCur = pTabList->a[0].iCursor = pParse->nTab++; if( pWhere ){ - if( sqliteExprResolveIds(pParse, base, pTabList, 0, pWhere) ){ + if( sqliteExprResolveIds(pParse, pTabList, 0, pWhere) ){ goto delete_from_cleanup; } if( sqliteExprCheck(pParse, pWhere, 0, 0) ){ @@ -149,7 +150,7 @@ void sqliteDeleteFrom( */ if( isView ){ Select *pView = sqliteSelectDup(pTab->pSelect); - sqliteSelect(pParse, pView, SRT_TempTable, base, 0, 0, 0); + sqliteSelect(pParse, pView, SRT_TempTable, iCur, 0, 0, 0); sqliteSelectDelete(pView); } @@ -172,13 +173,13 @@ void sqliteDeleteFrom( int addr; if( !isView ){ sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0); - sqliteVdbeAddOp(v, OP_OpenRead, base, pTab->tnum); + sqliteVdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum); } - sqliteVdbeAddOp(v, OP_Rewind, base, sqliteVdbeCurrentAddr(v)+2); + sqliteVdbeAddOp(v, OP_Rewind, iCur, sqliteVdbeCurrentAddr(v)+2); addr = sqliteVdbeAddOp(v, OP_AddImm, 1, 0); - sqliteVdbeAddOp(v, OP_Next, base, addr); + sqliteVdbeAddOp(v, OP_Next, iCur, addr); sqliteVdbeResolveLabel(v, endOfLoop); - sqliteVdbeAddOp(v, OP_Close, base, 0); + sqliteVdbeAddOp(v, OP_Close, iCur, 0); } if( !isView ){ sqliteVdbeAddOp(v, OP_Clear, pTab->tnum, pTab->iDb); @@ -194,7 +195,7 @@ void sqliteDeleteFrom( else{ /* Begin the database scan */ - pWInfo = sqliteWhereBegin(pParse, base, pTabList, pWhere, 1, 0); + pWInfo = sqliteWhereBegin(pParse, pTabList, pWhere, 1, 0); if( pWInfo==0 ) goto delete_from_cleanup; /* Remember the key of every item to be deleted. @@ -229,15 +230,15 @@ void sqliteDeleteFrom( sqliteVdbeAddOp(v, OP_Dup, 0, 0); if( !isView ){ sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0); - sqliteVdbeAddOp(v, OP_OpenRead, base, pTab->tnum); + sqliteVdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum); } - sqliteVdbeAddOp(v, OP_MoveTo, base, 0); + sqliteVdbeAddOp(v, OP_MoveTo, iCur, 0); - sqliteVdbeAddOp(v, OP_Recno, base, 0); - sqliteVdbeAddOp(v, OP_RowData, base, 0); + sqliteVdbeAddOp(v, OP_Recno, iCur, 0); + sqliteVdbeAddOp(v, OP_RowData, iCur, 0); sqliteVdbeAddOp(v, OP_PutIntKey, oldIdx, 0); if( !isView ){ - sqliteVdbeAddOp(v, OP_Close, base, 0); + sqliteVdbeAddOp(v, OP_Close, iCur, 0); } sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_BEFORE, pTab, -1, @@ -252,9 +253,9 @@ void sqliteDeleteFrom( ** before the trigger fires. If there are no row triggers, the ** cursors are opened only once on the outside the loop. */ - pParse->nTab = base + 1; + pParse->nTab = iCur + 1; sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0); - sqliteVdbeAddOp(v, OP_OpenWrite, base, pTab->tnum); + sqliteVdbeAddOp(v, OP_OpenWrite, iCur, pTab->tnum); for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ sqliteVdbeAddOp(v, OP_Integer, pIdx->iDb, 0); sqliteVdbeAddOp(v, OP_OpenWrite, pParse->nTab++, pIdx->tnum); @@ -267,7 +268,7 @@ void sqliteDeleteFrom( } /* Delete the row */ - sqliteGenerateRowDelete(db, v, pTab, base, pParse->trigStack==0); + sqliteGenerateRowDelete(db, v, pTab, iCur, pParse->trigStack==0); } /* If there are row triggers, close all cursors then invoke @@ -276,9 +277,9 @@ void sqliteDeleteFrom( if( row_triggers_exist ){ if( !isView ){ for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ - sqliteVdbeAddOp(v, OP_Close, base + i, pIdx->tnum); + sqliteVdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum); } - sqliteVdbeAddOp(v, OP_Close, base, 0); + sqliteVdbeAddOp(v, OP_Close, iCur, 0); } sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_AFTER, pTab, -1, oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default, @@ -293,10 +294,10 @@ void sqliteDeleteFrom( /* Close the cursors after the loop if there are no row triggers */ if( !row_triggers_exist ){ for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ - sqliteVdbeAddOp(v, OP_Close, base + i, pIdx->tnum); + sqliteVdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum); } - sqliteVdbeAddOp(v, OP_Close, base, 0); - pParse->nTab = base; + sqliteVdbeAddOp(v, OP_Close, iCur, 0); + pParse->nTab = iCur; } } sqliteEndWriteOperation(pParse); @@ -341,13 +342,13 @@ void sqliteGenerateRowDelete( sqlite *db, /* The database containing the index */ Vdbe *v, /* Generate code into this VDBE */ Table *pTab, /* Table containing the row to be deleted */ - int base, /* Cursor number for the table */ + int iCur, /* Cursor number for the table */ int count /* Increment the row change counter */ ){ int addr; - addr = sqliteVdbeAddOp(v, OP_NotExists, base, 0); - sqliteGenerateRowIndexDelete(db, v, pTab, base, 0); - sqliteVdbeAddOp(v, OP_Delete, base, count); + addr = sqliteVdbeAddOp(v, OP_NotExists, iCur, 0); + sqliteGenerateRowIndexDelete(db, v, pTab, iCur, 0); + sqliteVdbeAddOp(v, OP_Delete, iCur, count); sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v)); } @@ -359,19 +360,19 @@ void sqliteGenerateRowDelete( ** These are the requirements: ** ** 1. A read/write cursor pointing to pTab, the table containing the row -** to be deleted, must be opened as cursor number "base". +** to be deleted, must be opened as cursor number "iCur". ** ** 2. Read/write cursors for all indices of pTab must be open as -** cursor number base+i for the i-th index. +** cursor number iCur+i for the i-th index. ** -** 3. The "base" cursor must be pointing to the row that is to be +** 3. The "iCur" cursor must be pointing to the row that is to be ** deleted. */ void sqliteGenerateRowIndexDelete( sqlite *db, /* The database containing the index */ Vdbe *v, /* Generate code into this VDBE */ Table *pTab, /* Table containing the row to be deleted */ - int base, /* Cursor number for the table */ + int iCur, /* Cursor number for the table */ char *aIdxUsed /* Only delete if aIdxUsed!=0 && aIdxUsed[i]!=0 */ ){ int i; @@ -380,17 +381,17 @@ void sqliteGenerateRowIndexDelete( for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ int j; if( aIdxUsed!=0 && aIdxUsed[i-1]==0 ) continue; - sqliteVdbeAddOp(v, OP_Recno, base, 0); + sqliteVdbeAddOp(v, OP_Recno, iCur, 0); for(j=0; jnColumn; j++){ int idx = pIdx->aiColumn[j]; if( idx==pTab->iPKey ){ sqliteVdbeAddOp(v, OP_Dup, j, 0); }else{ - sqliteVdbeAddOp(v, OP_Column, base, idx); + sqliteVdbeAddOp(v, OP_Column, iCur, idx); } } sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0); if( db->file_format>=4 ) sqliteAddIdxKeyType(v, pIdx); - sqliteVdbeAddOp(v, OP_IdxDelete, base+i, 0); + sqliteVdbeAddOp(v, OP_IdxDelete, iCur+i, 0); } } diff --git a/src/expr.c b/src/expr.c index 90f00f3aa0..fbd15163f7 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.94 2003/04/22 20:30:39 drh Exp $ +** $Id: expr.c,v 1.95 2003/05/02 14:32:13 drh Exp $ */ #include "sqliteInt.h" #include @@ -194,6 +194,7 @@ SrcList *sqliteSrcListDup(SrcList *p){ pNew->a[i].zName = sqliteStrDup(p->a[i].zName); pNew->a[i].zAlias = sqliteStrDup(p->a[i].zAlias); pNew->a[i].jointype = p->a[i].jointype; + pNew->a[i].iCursor = p->a[i].iCursor; pNew->a[i].pTab = 0; pNew->a[i].pSelect = sqliteSelectDup(p->a[i].pSelect); pNew->a[i].pOn = sqliteExprDup(p->a[i].pOn); @@ -402,13 +403,16 @@ int sqliteIsRowid(const char *z){ */ int sqliteExprResolveIds( Parse *pParse, /* The parser context */ - int base, /* VDBE cursor number for first entry in pTabList */ SrcList *pTabList, /* 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 i; + if( pExpr==0 || pTabList==0 ) return 0; - assert( base+pTabList->nSrc<=pParse->nTab ); + for(i=0; inSrc; i++){ + assert( pTabList->a[i].iCursor>=0 && pTabList->a[i].iCursornTab ); + } switch( pExpr->op ){ /* Double-quoted strings (ex: "abc") are used as identifiers if ** possible. Otherwise they remain as strings. Single-quoted @@ -430,7 +434,6 @@ int sqliteExprResolveIds( */ case TK_ID: { int cnt = 0; /* Number of matches */ - int i; /* Loop counter */ char *z; int iDb = -1; @@ -447,7 +450,7 @@ int sqliteExprResolveIds( for(j=0; jnCol; j++){ if( sqliteStrICmp(pTab->aCol[j].zName, z)==0 ){ cnt++; - pExpr->iTable = i + base; + pExpr->iTable = pTabList->a[i].iCursor; pExpr->iDb = pTab->iDb; if( j==pTab->iPKey ){ /* Substitute the record number for the INTEGER PRIMARY KEY */ @@ -476,7 +479,7 @@ int sqliteExprResolveIds( } if( cnt==0 && iDb>=0 && sqliteIsRowid(z) ){ pExpr->iColumn = -1; - pExpr->iTable = base; + pExpr->iTable = pTabList->a[0].iCursor; pExpr->iDb = iDb; cnt = 1 + (pTabList->nSrc>1); pExpr->op = TK_COLUMN; @@ -491,7 +494,7 @@ int sqliteExprResolveIds( return 1; } if( pExpr->op==TK_COLUMN ){ - sqliteAuthRead(pParse, pExpr, pTabList, base); + sqliteAuthRead(pParse, pExpr, pTabList); } break; } @@ -550,13 +553,13 @@ int sqliteExprResolveIds( } } if( 0==(cntTab++) ){ - pExpr->iTable = i + base; + pExpr->iTable = pTabList->a[i].iCursor; pExpr->iDb = pTab->iDb; } for(j=0; jnCol; j++){ if( sqliteStrICmp(pTab->aCol[j].zName, zRight)==0 ){ cnt++; - pExpr->iTable = i + base; + pExpr->iTable = pTabList->a[i].iCursor; pExpr->iDb = pTab->iDb; /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */ pExpr->iColumn = j==pTab->iPKey ? -1 : j; @@ -620,14 +623,14 @@ int sqliteExprResolveIds( sqliteExprDelete(pExpr->pRight); pExpr->pRight = 0; pExpr->op = TK_COLUMN; - sqliteAuthRead(pParse, pExpr, pTabList, base); + sqliteAuthRead(pParse, pExpr, pTabList); break; } case TK_IN: { Vdbe *v = sqliteGetVdbe(pParse); if( v==0 ) return 1; - if( sqliteExprResolveIds(pParse, base, pTabList, pEList, pExpr->pLeft) ){ + if( sqliteExprResolveIds(pParse, pTabList, pEList, pExpr->pLeft) ){ return 1; } if( pExpr->pSelect ){ @@ -697,11 +700,11 @@ int sqliteExprResolveIds( /* For all else, just recursively walk the tree */ default: { if( pExpr->pLeft - && sqliteExprResolveIds(pParse, base, pTabList, pEList, pExpr->pLeft) ){ + && sqliteExprResolveIds(pParse, pTabList, pEList, pExpr->pLeft) ){ return 1; } if( pExpr->pRight - && sqliteExprResolveIds(pParse, base, pTabList, pEList, pExpr->pRight) ){ + && sqliteExprResolveIds(pParse, pTabList, pEList, pExpr->pRight) ){ return 1; } if( pExpr->pList ){ @@ -709,7 +712,7 @@ int sqliteExprResolveIds( ExprList *pList = pExpr->pList; for(i=0; inExpr; i++){ Expr *pArg = pList->a[i].pExpr; - if( sqliteExprResolveIds(pParse, base, pTabList, pEList, pArg) ){ + if( sqliteExprResolveIds(pParse, pTabList, pEList, pArg) ){ return 1; } } diff --git a/src/insert.c b/src/insert.c index e83224a2f8..71a0000902 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.82 2003/04/24 01:45:04 drh Exp $ +** $Id: insert.c,v 1.83 2003/05/02 14:32:13 drh Exp $ */ #include "sqliteInt.h" @@ -98,7 +98,7 @@ void sqliteInsert( Vdbe *v; /* Generate code into this virtual machine */ Index *pIdx; /* For looping over indices of the table */ int nColumn; /* Number of columns in the data */ - int base; /* First available cursor */ + int base; /* VDBE Cursor number for pTab */ int iCont, iBreak; /* Beginning and end of the loop over srcTab */ sqlite *db; /* The main database structure */ int keyColumn = -1; /* Column that is the INTEGER PRIMARY KEY */ @@ -245,7 +245,7 @@ void sqliteInsert( nColumn = pList->nExpr; dummy.nSrc = 0; for(i=0; ia[i].pExpr) ){ + if( sqliteExprResolveIds(pParse, &dummy, 0, pList->a[i].pExpr) ){ goto insert_cleanup; } if( sqliteExprCheck(pParse, pList->a[i].pExpr, 0, 0) ){ diff --git a/src/select.c b/src/select.c index 7dfdcc9f6e..7b8733f4a8 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.135 2003/04/29 16:20:46 drh Exp $ +** $Id: select.c,v 1.136 2003/05/02 14:32:13 drh Exp $ */ #include "sqliteInt.h" @@ -296,13 +296,15 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){ ** will work correctly for both SQLite and Oracle8. */ static int sqliteOracle8JoinFixup( - int base, /* VDBE cursor number for first table in pSrc */ SrcList *pSrc, /* List of tables being joined */ Expr *pWhere /* The WHERE clause of the SELECT statement */ ){ int rc = 0; if( ExprHasProperty(pWhere, EP_Oracle8Join) && pWhere->op==TK_COLUMN ){ - int idx = pWhere->iTable - base; + int idx; + for(idx=0; idxnSrc; idx++){ + if( pSrc->a[idx].iCursor==pWhere->iTable ) break; + } assert( idx>=0 && idxnSrc ); if( idx>0 ){ pSrc->a[idx-1].jointype &= ~JT_INNER; @@ -311,16 +313,16 @@ static int sqliteOracle8JoinFixup( } } if( pWhere->pRight ){ - rc = sqliteOracle8JoinFixup(base, pSrc, pWhere->pRight); + rc = sqliteOracle8JoinFixup(pSrc, pWhere->pRight); } if( pWhere->pLeft ){ - rc |= sqliteOracle8JoinFixup(base, pSrc, pWhere->pLeft); + rc |= sqliteOracle8JoinFixup(pSrc, pWhere->pLeft); } if( pWhere->pList ){ int i; ExprList *pList = pWhere->pList; for(i=0; inExpr && rc==0; i++){ - rc |= sqliteOracle8JoinFixup(base, pSrc, pList->a[i].pExpr); + rc |= sqliteOracle8JoinFixup(pSrc, pList->a[i].pExpr); } } if( rc==1 && (pWhere->op==TK_AND || pWhere->op==TK_EQ) ){ @@ -687,12 +689,11 @@ static void generateSortTail( */ static void generateColumnTypes( Parse *pParse, /* Parser context */ - int base, /* VDBE cursor corresponding to first entry in pTabList */ SrcList *pTabList, /* List of tables */ ExprList *pEList /* Expressions defining the result set */ ){ Vdbe *v = pParse->pVdbe; - int i; + int i, j; if( pParse->useCallback && (pParse->db->flags & SQLITE_ReportTypes)==0 ){ return; } @@ -701,8 +702,11 @@ static void generateColumnTypes( char *zType = 0; if( p==0 ) continue; if( p->op==TK_COLUMN && pTabList ){ - Table *pTab = pTabList->a[p->iTable - base].pTab; + Table *pTab; int iCol = p->iColumn; + for(j=0; jnSrc && pTabList->a[j].iCursor!=p->iTable; j++){} + assert( jnSrc ); + pTab = pTabList->a[j].pTab; if( iCol<0 ) iCol = pTab->iPKey; assert( iCol==-1 || (iCol>=0 && iColnCol) ); if( iCol<0 ){ @@ -729,12 +733,11 @@ static void generateColumnTypes( */ static void generateColumnNames( Parse *pParse, /* Parser context */ - int base, /* VDBE cursor corresponding to first entry in pTabList */ SrcList *pTabList, /* List of tables */ ExprList *pEList /* Expressions defining the result set */ ){ Vdbe *v = pParse->pVdbe; - int i; + int i, j; if( pParse->colNamesSet || v==0 || sqlite_malloc_failed ) return; pParse->colNamesSet = 1; for(i=0; inExpr; i++){ @@ -751,9 +754,12 @@ static void generateColumnNames( } showFullNames = (pParse->db->flags & SQLITE_FullColNames)!=0; if( p->op==TK_COLUMN && pTabList ){ - Table *pTab = pTabList->a[p->iTable - base].pTab; + Table *pTab; char *zCol; int iCol = p->iColumn; + for(j=0; jnSrc && pTabList->a[j].iCursor!=p->iTable; j++){} + assert( jnSrc ); + pTab = pTabList->a[j].pTab; if( iCol<0 ) iCol = pTab->iPKey; assert( iCol==-1 || (iCol>=0 && iColnCol) ); if( iCol<0 ){ @@ -771,7 +777,7 @@ static void generateColumnNames( char *zName = 0; char *zTab; - zTab = pTabList->a[p->iTable - base].zAlias; + zTab = pTabList->a[j].zAlias; if( showFullNames || zTab==0 ) zTab = pTab->zName; sqliteSetString(&zName, zTab, ".", zCol, 0); sqliteVdbeAddOp(v, OP_ColumnName, i, 0); @@ -1368,8 +1374,8 @@ static int multiSelect(Parse *pParse, Select *p, int eDest, int iParm){ int iCont, iBreak, iStart; assert( p->pEList ); if( eDest==SRT_Callback ){ - generateColumnNames(pParse, p->base, 0, p->pEList); - generateColumnTypes(pParse, p->base, p->pSrc, p->pEList); + generateColumnNames(pParse, 0, p->pEList); + generateColumnTypes(pParse, p->pSrc, p->pEList); } iBreak = sqliteVdbeMakeLabel(v); iCont = sqliteVdbeMakeLabel(v); @@ -1425,8 +1431,8 @@ static int multiSelect(Parse *pParse, Select *p, int eDest, int iParm){ */ assert( p->pEList ); if( eDest==SRT_Callback ){ - generateColumnNames(pParse, p->base, 0, p->pEList); - generateColumnTypes(pParse, p->base, p->pSrc, p->pEList); + generateColumnNames(pParse, 0, p->pEList); + generateColumnTypes(pParse, p->pSrc, p->pEList); } iBreak = sqliteVdbeMakeLabel(v); iCont = sqliteVdbeMakeLabel(v); @@ -1466,37 +1472,11 @@ static int multiSelect(Parse *pParse, Select *p, int eDest, int iParm){ return 0; } -/* -** Recursively scan through an expression tree. For every reference -** to a column in table number iFrom, change that reference to the -** same column in table number iTo. -*/ -static void changeTablesInList(ExprList*, int, int); /* Forward Declaration */ -static void changeTables(Expr *pExpr, int iFrom, int iTo){ - if( pExpr==0 ) return; - if( pExpr->op==TK_COLUMN && pExpr->iTable==iFrom ){ - pExpr->iTable = iTo; - }else{ - changeTables(pExpr->pLeft, iFrom, iTo); - changeTables(pExpr->pRight, iFrom, iTo); - changeTablesInList(pExpr->pList, iFrom, iTo); - } -} -static void changeTablesInList(ExprList *pList, int iFrom, int iTo){ - if( pList ){ - int i; - for(i=0; inExpr; i++){ - changeTables(pList->a[i].pExpr, iFrom, iTo); - } - } -} - /* ** Scan through the expression pExpr. Replace every reference to -** a column in table number iTable with a copy of the corresponding +** a column in table number iTable with a copy of the iColumn-th ** entry in pEList. (But leave references to the ROWID column -** unchanged.) When making a copy of an expression in pEList, change -** references to columns in table iSub into references to table iTable. +** unchanged.) ** ** This routine is part of the flattening procedure. A subquery ** whose result set is defined by pEList appears as entry in the @@ -1505,8 +1485,8 @@ static void changeTablesInList(ExprList *pList, int iFrom, int iTo){ ** changes to pExpr so that it refers directly to the source table ** of the subquery rather the result set of the subquery. */ -static void substExprList(ExprList*,int,ExprList*,int); /* Forward Decl */ -static void substExpr(Expr *pExpr, int iTable, ExprList *pEList, int iSub){ +static void substExprList(ExprList*,int,ExprList*); /* Forward Decl */ +static void substExpr(Expr *pExpr, int iTable, ExprList *pEList){ if( pExpr==0 ) return; if( pExpr->op==TK_COLUMN && pExpr->iTable==iTable && pExpr->iColumn>=0 ){ Expr *pNew; @@ -1527,21 +1507,18 @@ static void substExpr(Expr *pExpr, int iTable, ExprList *pEList, int iSub){ pExpr->iAgg = pNew->iAgg; sqliteTokenCopy(&pExpr->token, &pNew->token); sqliteTokenCopy(&pExpr->span, &pNew->span); - if( iSub!=iTable ){ - changeTables(pExpr, iSub, iTable); - } }else{ - substExpr(pExpr->pLeft, iTable, pEList, iSub); - substExpr(pExpr->pRight, iTable, pEList, iSub); - substExprList(pExpr->pList, iTable, pEList, iSub); + substExpr(pExpr->pLeft, iTable, pEList); + substExpr(pExpr->pRight, iTable, pEList); + substExprList(pExpr->pList, iTable, pEList); } } static void -substExprList(ExprList *pList, int iTable, ExprList *pEList, int iSub){ +substExprList(ExprList *pList, int iTable, ExprList *pEList){ int i; if( pList==0 ) return; for(i=0; inExpr; i++){ - substExpr(pList->a[i].pExpr, iTable, pEList, iSub); + substExpr(pList->a[i].pExpr, iTable, pEList); } } @@ -1621,8 +1598,8 @@ static int flattenSubquery( SrcList *pSrc; /* The FROM clause of the outer query */ SrcList *pSubSrc; /* The FROM clause of the subquery */ ExprList *pList; /* The result set of the outer query */ + int iParent; /* VDBE cursor number of the pSub result set temp table */ int i; - int iParent, iSub; Expr *pWhere; /* Check to see if flattening is permitted. Return 0 if not. @@ -1646,9 +1623,9 @@ static int flattenSubquery( /* If we reach this point, it means flattening is permitted for the ** iFrom-th entry of the FROM clause in the outer query. */ - iParent = p->base + iFrom; - iSub = pSub->base; - substExprList(p->pEList, iParent, pSub->pEList, iSub); + iParent = pSrc->a[iFrom].iCursor; + pSrc->a[iFrom].iCursor = pSubSrc->a[0].iCursor; + substExprList(p->pEList, iParent, pSub->pEList); pList = p->pEList; for(i=0; inExpr; i++){ Expr *pExpr; @@ -1657,22 +1634,18 @@ static int flattenSubquery( } } if( isAgg ){ - substExprList(p->pGroupBy, iParent, pSub->pEList, iSub); - substExpr(p->pHaving, iParent, pSub->pEList, iSub); + substExprList(p->pGroupBy, iParent, pSub->pEList); + substExpr(p->pHaving, iParent, pSub->pEList); } if( pSub->pOrderBy ){ assert( p->pOrderBy==0 ); p->pOrderBy = pSub->pOrderBy; pSub->pOrderBy = 0; - changeTablesInList(p->pOrderBy, iSub, iParent); }else if( p->pOrderBy ){ - substExprList(p->pOrderBy, iParent, pSub->pEList, iSub); + substExprList(p->pOrderBy, iParent, pSub->pEList); } if( pSub->pWhere ){ pWhere = sqliteExprDup(pSub->pWhere); - if( iParent!=iSub ){ - changeTables(pWhere, iSub, iParent); - } }else{ pWhere = 0; } @@ -1680,12 +1653,9 @@ static int flattenSubquery( assert( p->pHaving==0 ); p->pHaving = p->pWhere; p->pWhere = pWhere; - substExpr(p->pHaving, iParent, pSub->pEList, iSub); + substExpr(p->pHaving, iParent, pSub->pEList); if( pSub->pHaving ){ Expr *pHaving = sqliteExprDup(pSub->pHaving); - if( iParent!=iSub ){ - changeTables(pHaving, iSub, iParent); - } if( p->pHaving ){ p->pHaving = sqliteExpr(TK_AND, p->pHaving, pHaving, 0); }else{ @@ -1694,13 +1664,10 @@ static int flattenSubquery( } assert( p->pGroupBy==0 ); p->pGroupBy = sqliteExprListDup(pSub->pGroupBy); - if( iParent!=iSub ){ - changeTablesInList(p->pGroupBy, iSub, iParent); - } }else if( p->pWhere==0 ){ p->pWhere = pWhere; }else{ - substExpr(p->pWhere, iParent, pSub->pEList, iSub); + substExpr(p->pWhere, iParent, pSub->pEList); if( pWhere ){ p->pWhere = sqliteExpr(TK_AND, p->pWhere, pWhere, 0); } @@ -1716,19 +1683,6 @@ static int flattenSubquery( } p->nOffset += pSub->nOffset; - /* If the subquery contains subqueries of its own, that were not - ** flattened, then code will have already been generated to put - ** the results of those sub-subqueries into VDBE cursors relative - ** to the subquery. We must translate the cursor number into values - ** suitable for use by the outer query. - */ - for(i=0; inSrc; i++){ - Vdbe *v; - if( pSubSrc->a[i].pSelect==0 ) continue; - v = sqliteGetVdbe(pParse); - sqliteVdbeAddOp(v, OP_RenameCursor, pSub->base+i, p->base+i); - } - if( pSrc->a[iFrom].pTab && pSrc->a[iFrom].pTab->isTransient ){ sqliteDeleteTable(0, pSrc->a[iFrom].pTab); } @@ -1817,8 +1771,8 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){ v = sqliteGetVdbe(pParse); if( v==0 ) return 0; if( eDest==SRT_Callback ){ - generateColumnNames(pParse, p->base, p->pSrc, p->pEList); - generateColumnTypes(pParse, p->base, p->pSrc, p->pEList); + generateColumnNames(pParse, p->pSrc, p->pEList); + generateColumnTypes(pParse, p->pSrc, p->pEList); } /* Generating code to find the min or the max. Basically all we have @@ -1829,7 +1783,7 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){ if( !pParse->schemaVerified && (pParse->db->flags & SQLITE_InTrans)==0 ){ sqliteCodeVerifySchema(pParse); } - base = p->base; + base = p->pSrc->a[0].iCursor; sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0); sqliteVdbeAddOp(v, OP_OpenRead, base, pTab->tnum); sqliteVdbeChangeP3(v, -1, pTab->zName, P3_STATIC); @@ -1928,7 +1882,6 @@ int sqliteSelect( Expr *pHaving; /* The HAVING clause. May be NULL */ int isDistinct; /* True if the DISTINCT keyword is present */ int distinct; /* Table to use for the distinct set */ - int base; /* First cursor available for use */ int rc = 1; /* Value to return from this function */ if( sqlite_malloc_failed || pParse->nErr || p==0 ) return 1; @@ -1949,12 +1902,9 @@ int sqliteSelect( pHaving = p->pHaving; isDistinct = p->isDistinct; - /* Allocate a block of VDBE cursors, one for each table in the FROM clause. - ** The WHERE processing requires that the cursors for the tables in the - ** FROM clause be consecutive. + /* Allocate VDBE cursors for each table in the FROM clause */ - base = p->base = pParse->nTab; - pParse->nTab += pTabList->nSrc; + sqliteSrcListAssignCursors(pParse, pTabList); /* ** Do not even attempt to generate any code if we have already seen @@ -2000,7 +1950,7 @@ int sqliteSelect( ** Resolve the column names and do a semantics check on all the expressions. */ for(i=0; inExpr; i++){ - if( sqliteExprResolveIds(pParse, base, pTabList, 0, pEList->a[i].pExpr) ){ + if( sqliteExprResolveIds(pParse, pTabList, 0, pEList->a[i].pExpr) ){ goto select_end; } if( sqliteExprCheck(pParse, pEList->a[i].pExpr, 1, &isAgg) ){ @@ -2008,20 +1958,20 @@ int sqliteSelect( } } if( pWhere ){ - if( sqliteExprResolveIds(pParse, base, pTabList, pEList, pWhere) ){ + if( sqliteExprResolveIds(pParse, pTabList, pEList, pWhere) ){ goto select_end; } if( sqliteExprCheck(pParse, pWhere, 0, 0) ){ goto select_end; } - sqliteOracle8JoinFixup(base, pTabList, pWhere); + sqliteOracle8JoinFixup(pTabList, pWhere); } if( pHaving ){ if( pGroupBy==0 ){ sqliteErrorMsg(pParse, "a GROUP BY clause is required before HAVING"); goto select_end; } - if( sqliteExprResolveIds(pParse, base, pTabList, pEList, pHaving) ){ + if( sqliteExprResolveIds(pParse, pTabList, pEList, pHaving) ){ goto select_end; } if( sqliteExprCheck(pParse, pHaving, 1, &isAgg) ){ @@ -2036,7 +1986,7 @@ int sqliteSelect( sqliteExprDelete(pE); pE = pOrderBy->a[i].pExpr = sqliteExprDup(pEList->a[iCol-1].pExpr); } - if( sqliteExprResolveIds(pParse, base, pTabList, pEList, pE) ){ + if( sqliteExprResolveIds(pParse, pTabList, pEList, pE) ){ goto select_end; } if( sqliteExprCheck(pParse, pE, isAgg, 0) ){ @@ -2064,7 +2014,7 @@ int sqliteSelect( sqliteExprDelete(pE); pE = pGroupBy->a[i].pExpr = sqliteExprDup(pEList->a[iCol-1].pExpr); } - if( sqliteExprResolveIds(pParse, base, pTabList, pEList, pE) ){ + if( sqliteExprResolveIds(pParse, pTabList, pEList, pE) ){ goto select_end; } if( sqliteExprCheck(pParse, pE, isAgg, 0) ){ @@ -2102,7 +2052,7 @@ int sqliteSelect( ** step is skipped if the output is going to some other destination. */ if( eDest==SRT_Callback ){ - generateColumnNames(pParse, p->base, pTabList, pEList); + generateColumnNames(pParse, pTabList, pEList); } /* Set the limiter @@ -2134,8 +2084,8 @@ int sqliteSelect( zSavedAuthContext = pParse->zAuthContext; pParse->zAuthContext = pTabList->a[i].zName; } - sqliteSelect(pParse, pTabList->a[i].pSelect, SRT_TempTable, base+i, - p, i, &isAgg); + sqliteSelect(pParse, pTabList->a[i].pSelect, SRT_TempTable, + pTabList->a[i].iCursor, p, i, &isAgg); if( pTabList->a[i].zName!=0 ){ pParse->zAuthContext = zSavedAuthContext; } @@ -2163,7 +2113,7 @@ int sqliteSelect( ** than a callback. */ if( eDest==SRT_Callback ){ - generateColumnTypes(pParse, p->base, pTabList, pEList); + generateColumnTypes(pParse, pTabList, pEList); } /* If the output is destined for a temporary table, open that table. @@ -2237,7 +2187,7 @@ int sqliteSelect( /* Begin the database scan */ - pWInfo = sqliteWhereBegin(pParse, p->base, pTabList, pWhere, 0, + pWInfo = sqliteWhereBegin(pParse, pTabList, pWhere, 0, pGroupBy ? 0 : &pOrderBy); if( pWInfo==0 ) goto select_end; diff --git a/src/sqliteInt.h b/src/sqliteInt.h index cec4bc1e93..f75495e00f 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.182 2003/04/29 16:20:46 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.183 2003/05/02 14:32:14 drh Exp $ */ #include "config.h" #include "sqlite.h" @@ -717,7 +717,6 @@ struct WhereInfo { SrcList *pTabList; /* List of tables in the join */ int iContinue; /* Jump here to continue with next record */ int iBreak; /* Jump here to break out of the loop */ - int base; /* Index of first Open opcode */ int nLevel; /* Number of nested loop */ int savedNTab; /* Value of pParse->nTab before WhereBegin() */ int peakNTab; /* Value of pParse->nTab after WhereBegin() */ @@ -754,7 +753,6 @@ struct Select { Select *pPrior; /* Prior select in a compound select statement */ int nLimit, nOffset; /* LIMIT and OFFSET values. -1 means not used */ char *zSelect; /* Complete text of the SELECT command */ - int base; /* Index of VDBE cursor for left-most FROM table */ }; /* @@ -1039,6 +1037,7 @@ IdList *sqliteIdListAppend(IdList*, Token*); int sqliteIdListIndex(IdList*,const char*); SrcList *sqliteSrcListAppend(SrcList*, Token*, Token*); void sqliteSrcListAddAlias(SrcList*, Token*); +void sqliteSrcListAssignCursors(Parse*, SrcList*); void sqliteIdListDelete(IdList*); void sqliteSrcListDelete(SrcList*); void sqliteCreateIndex(Parse*,Token*,SrcList*,IdList*,int,int,Token*,Token*); @@ -1054,7 +1053,7 @@ Table *sqliteSrcListLookup(Parse*, SrcList*); int sqliteIsReadOnly(Parse*, Table*, int); void sqliteDeleteFrom(Parse*, SrcList*, Expr*); void sqliteUpdate(Parse*, SrcList*, ExprList*, Expr*, int); -WhereInfo *sqliteWhereBegin(Parse*, int, SrcList*, Expr*, int, ExprList**); +WhereInfo *sqliteWhereBegin(Parse*, SrcList*, Expr*, int, ExprList**); void sqliteWhereEnd(WhereInfo*); void sqliteExprCode(Parse*, Expr*); void sqliteExprIfTrue(Parse*, Expr*, int, int); @@ -1072,7 +1071,7 @@ int sqliteExprCheck(Parse*, Expr*, int, int*); int sqliteExprType(Expr*); int sqliteExprCompare(Expr*, Expr*); int sqliteFuncId(Token*); -int sqliteExprResolveIds(Parse*, int, SrcList*, ExprList*, Expr*); +int sqliteExprResolveIds(Parse*, SrcList*, ExprList*, Expr*); int sqliteExprAnalyzeAggregates(Parse*, Expr*); Vdbe *sqliteGetVdbe(Parse*); int sqliteRandomByte(void); @@ -1120,12 +1119,12 @@ int sqliteJoinType(Parse*, Token*, Token*, Token*); void sqliteCreateForeignKey(Parse*, IdList*, Token*, IdList*, int); void sqliteDeferForeignKey(Parse*, int); #ifndef SQLITE_OMIT_AUTHORIZATION - void sqliteAuthRead(Parse*,Expr*,SrcList*,int); + void sqliteAuthRead(Parse*,Expr*,SrcList*); int sqliteAuthCheck(Parse*,int, const char*, const char*, const char*); void sqliteAuthContextPush(Parse*, AuthContext*, const char*); void sqliteAuthContextPop(AuthContext*); #else -# define sqliteAuthRead(a,b,c,d) +# define sqliteAuthRead(a,b,c) # define sqliteAuthCheck(a,b,c,d) SQLITE_OK # define sqliteAuthContextPush(a,b,c) # define sqliteAuthContextPop(a) diff --git a/src/trigger.c b/src/trigger.c index b07b8c5a87..227e471534 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -678,7 +678,7 @@ int sqliteCodeRowTrigger( /* code the WHEN clause */ endTrigger = sqliteVdbeMakeLabel(pParse->pVdbe); whenExpr = sqliteExprDup(pTrigger->pWhen); - if( sqliteExprResolveIds(pParse, 0, &dummyTablist, 0, whenExpr) ){ + if( sqliteExprResolveIds(pParse, &dummyTablist, 0, whenExpr) ){ pParse->trigStack = pParse->trigStack->pNext; sqliteFree(pTriggerStack); sqliteExprDelete(whenExpr); diff --git a/src/update.c b/src/update.c index cd98c82c06..56021b7460 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.64 2003/04/25 17:52:11 drh Exp $ +** $Id: update.c,v 1.65 2003/05/02 14:32:14 drh Exp $ */ #include "sqliteInt.h" @@ -38,7 +38,7 @@ void sqliteUpdate( Index *pIdx; /* For looping over indices */ int nIdx; /* Number of indices that need updating */ int nIdxTotal; /* Total number of indices */ - int base; /* Index of first available table cursor */ + int iCur; /* VDBE Cursor number of pTab */ sqlite *db; /* The database structure */ Index **apIdx = 0; /* An array of indices that need updating too */ char *aIdxUsed = 0; /* aIdxUsed[i]==1 if the i-th index is used */ @@ -98,7 +98,7 @@ void sqliteUpdate( ** need to occur right after the database cursor. So go ahead and ** allocate enough space, just in case. */ - base = pParse->nTab++; + pTabList->a[0].iCursor = iCur = pParse->nTab++; for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ pParse->nTab++; } @@ -111,7 +111,7 @@ void sqliteUpdate( */ chngRecno = 0; for(i=0; inExpr; i++){ - if( sqliteExprResolveIds(pParse, base, pTabList, 0, pChanges->a[i].pExpr) ){ + if( sqliteExprResolveIds(pParse, pTabList, 0, pChanges->a[i].pExpr) ){ goto update_cleanup; } if( sqliteExprCheck(pParse, pChanges->a[i].pExpr, 0, 0) ){ @@ -185,7 +185,7 @@ void sqliteUpdate( ** WHERE clause. */ if( pWhere ){ - if( sqliteExprResolveIds(pParse, base, pTabList, 0, pWhere) ){ + if( sqliteExprResolveIds(pParse, pTabList, 0, pWhere) ){ goto update_cleanup; } if( sqliteExprCheck(pParse, pWhere, 0, 0) ){ @@ -211,13 +211,13 @@ void sqliteUpdate( if( isView ){ Select *pView; pView = sqliteSelectDup(pTab->pSelect); - sqliteSelect(pParse, pView, SRT_TempTable, base, 0, 0, 0); + sqliteSelect(pParse, pView, SRT_TempTable, iCur, 0, 0, 0); sqliteSelectDelete(pView); } /* Begin the database scan */ - pWInfo = sqliteWhereBegin(pParse, base, pTabList, pWhere, 1, 0); + pWInfo = sqliteWhereBegin(pParse, pTabList, pWhere, 1, 0); if( pWInfo==0 ) goto update_cleanup; /* Remember the index of every item to be updated. @@ -252,14 +252,14 @@ void sqliteUpdate( sqliteVdbeAddOp(v, OP_Dup, 0, 0); if( !isView ){ sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0); - sqliteVdbeAddOp(v, OP_OpenRead, base, pTab->tnum); + sqliteVdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum); } - sqliteVdbeAddOp(v, OP_MoveTo, base, 0); + sqliteVdbeAddOp(v, OP_MoveTo, iCur, 0); /* Generate the OLD table */ - sqliteVdbeAddOp(v, OP_Recno, base, 0); - sqliteVdbeAddOp(v, OP_RowData, base, 0); + sqliteVdbeAddOp(v, OP_Recno, iCur, 0); + sqliteVdbeAddOp(v, OP_RowData, iCur, 0); sqliteVdbeAddOp(v, OP_PutIntKey, oldIdx, 0); /* Generate the NEW table @@ -267,7 +267,7 @@ void sqliteUpdate( if( chngRecno ){ sqliteExprCode(pParse, pRecnoExpr); }else{ - sqliteVdbeAddOp(v, OP_Recno, base, 0); + sqliteVdbeAddOp(v, OP_Recno, iCur, 0); } for(i=0; inCol; i++){ if( i==pTab->iPKey ){ @@ -276,7 +276,7 @@ void sqliteUpdate( } j = aXRef[i]; if( j<0 ){ - sqliteVdbeAddOp(v, OP_Column, base, i); + sqliteVdbeAddOp(v, OP_Column, iCur, i); }else{ sqliteExprCode(pParse, pChanges->a[j].pExpr); } @@ -284,7 +284,7 @@ void sqliteUpdate( sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0); sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0); if( !isView ){ - sqliteVdbeAddOp(v, OP_Close, base, 0); + sqliteVdbeAddOp(v, OP_Close, iCur, 0); } /* Fire the BEFORE and INSTEAD OF triggers @@ -303,7 +303,7 @@ void sqliteUpdate( ** to be deleting some records. */ sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0); - sqliteVdbeAddOp(v, OP_OpenWrite, base, pTab->tnum); + sqliteVdbeAddOp(v, OP_OpenWrite, iCur, pTab->tnum); if( onError==OE_Replace ){ openAll = 1; }else{ @@ -318,8 +318,8 @@ void sqliteUpdate( for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ if( openAll || aIdxUsed[i] ){ sqliteVdbeAddOp(v, OP_Integer, pIdx->iDb, 0); - sqliteVdbeAddOp(v, OP_OpenWrite, base+i+1, pIdx->tnum); - assert( pParse->nTab>base+i+1 ); + sqliteVdbeAddOp(v, OP_OpenWrite, iCur+i+1, pIdx->tnum); + assert( pParse->nTab>iCur+i+1 ); } } @@ -334,7 +334,7 @@ void sqliteUpdate( addr = sqliteVdbeAddOp(v, OP_ListRead, 0, 0); sqliteVdbeAddOp(v, OP_Dup, 0, 0); } - sqliteVdbeAddOp(v, OP_NotExists, base, addr); + sqliteVdbeAddOp(v, OP_NotExists, iCur, addr); /* If the record number will change, push the record number as it ** will be after the update. (The old record number is currently @@ -354,7 +354,7 @@ void sqliteUpdate( } j = aXRef[i]; if( j<0 ){ - sqliteVdbeAddOp(v, OP_Column, base, i); + sqliteVdbeAddOp(v, OP_Column, iCur, i); }else{ sqliteExprCode(pParse, pChanges->a[j].pExpr); } @@ -362,22 +362,22 @@ void sqliteUpdate( /* Do constraint checks */ - sqliteGenerateConstraintChecks(pParse, pTab, base, aIdxUsed, chngRecno, 1, + sqliteGenerateConstraintChecks(pParse, pTab, iCur, aIdxUsed, chngRecno, 1, onError, addr); /* Delete the old indices for the current record. */ - sqliteGenerateRowIndexDelete(db, v, pTab, base, aIdxUsed); + sqliteGenerateRowIndexDelete(db, v, pTab, iCur, aIdxUsed); /* If changing the record number, delete the old record. */ if( chngRecno ){ - sqliteVdbeAddOp(v, OP_Delete, base, 0); + sqliteVdbeAddOp(v, OP_Delete, iCur, 0); } /* Create the new index entries and the new record. */ - sqliteCompleteInsertion(pParse, pTab, base, aIdxUsed, chngRecno, 1, -1); + sqliteCompleteInsertion(pParse, pTab, iCur, aIdxUsed, chngRecno, 1, -1); } /* Increment the row counter @@ -393,10 +393,10 @@ void sqliteUpdate( if( !isView ){ for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ if( openAll || aIdxUsed[i] ) - sqliteVdbeAddOp(v, OP_Close, base+i+1, 0); + sqliteVdbeAddOp(v, OP_Close, iCur+i+1, 0); } - sqliteVdbeAddOp(v, OP_Close, base, 0); - pParse->nTab = base; + sqliteVdbeAddOp(v, OP_Close, iCur, 0); + pParse->nTab = iCur; } if( sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_AFTER, pTab, newIdx, oldIdx, onError, addr) ){ @@ -415,11 +415,11 @@ void sqliteUpdate( if( !row_triggers_exist ){ for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ if( openAll || aIdxUsed[i] ){ - sqliteVdbeAddOp(v, OP_Close, base+i+1, 0); + sqliteVdbeAddOp(v, OP_Close, iCur+i+1, 0); } } - sqliteVdbeAddOp(v, OP_Close, base, 0); - pParse->nTab = base; + sqliteVdbeAddOp(v, OP_Close, iCur, 0); + pParse->nTab = iCur; }else{ sqliteVdbeAddOp(v, OP_Close, newIdx, 0); sqliteVdbeAddOp(v, OP_Close, oldIdx, 0); diff --git a/src/vdbe.c b/src/vdbe.c index 3c921d2f8a..511e76cb05 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -36,7 +36,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.220 2003/04/25 15:37:58 drh Exp $ +** $Id: vdbe.c,v 1.221 2003/05/02 14:32:14 drh Exp $ */ #include "sqliteInt.h" #include @@ -3520,27 +3520,6 @@ case OP_OpenPseudo: { break; } -/* -** Opcode: RenameCursor P1 P2 * -** -** Rename cursor number P1 as cursor number P2. If P2 was previously -** opened is is closed before the renaming occurs. -*/ -case OP_RenameCursor: { - int from = pOp->p1; - int to = pOp->p2; - VERIFY( if( from<0 || to<0 ) goto bad_instruction; ) - if( tonCursor && p->aCsr[to].pCursor ){ - cleanupCursor(&p->aCsr[to]); - } - expandCursorArraySize(p, to); - if( fromnCursor ){ - memcpy(&p->aCsr[to], &p->aCsr[from], sizeof(p->aCsr[0])); - memset(&p->aCsr[from], 0, sizeof(p->aCsr[0])); - } - break; -} - /* Opcode: Close P1 * * ** ** Close a cursor previously opened as P1. If P1 is not diff --git a/src/where.c b/src/where.c index 82903047fe..fda6b299d8 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.77 2003/04/24 01:45:05 drh Exp $ +** $Id: where.c,v 1.78 2003/05/02 14:32:14 drh Exp $ */ #include "sqliteInt.h" @@ -36,6 +36,21 @@ struct ExprInfo { unsigned prereqAll; /* Bitmask of tables referenced by p */ }; +/* +** An instance of the following structure keeps track of a mapping +** between VDBE cursor numbers and bitmasks. The VDBE cursor numbers +** are small integers contained in SrcList_item.iCursor and Expr.iTable +** fields. For any given WHERE clause, we want to track which cursors +** are being used, so we assign a single bit in a 32-bit word to track +** that cursor. Then a 32-bit integer is able to show the set of all +** cursors being used. +*/ +typedef struct ExprMaskSet ExprMaskSet; +struct ExprMaskSet { + int n; /* Number of assigned cursor values */ + int ix[32]; /* Cursor assigned to each bit */ +}; + /* ** Determine the number of elements in an array. */ @@ -67,37 +82,61 @@ static int exprSplit(int nSlot, ExprInfo *aSlot, Expr *pExpr){ return cnt; } +/* +** Initialize an expression mask set +*/ +#define initMaskSet(P) memset(P, 0, sizeof(*P)) + +/* +** Return the bitmask for the given cursor. Assign a new bitmask +** if this is the first time the cursor has been seen. +*/ +static int getMask(ExprMaskSet *pMaskSet, int iCursor){ + int i; + for(i=0; in; i++){ + if( pMaskSet->ix[i]==iCursor ) return 1<n && iix) ){ + pMaskSet->n++; + pMaskSet->ix[i] = iCursor; + return 1<op==TK_COLUMN ){ - return 1<< (p->iTable - base); + return getMask(pMaskSet, p->iTable); } if( p->pRight ){ - mask = exprTableUsage(base, p->pRight); + mask = exprTableUsage(pMaskSet, p->pRight); } if( p->pLeft ){ - mask |= exprTableUsage(base, p->pLeft); + mask |= exprTableUsage(pMaskSet, p->pLeft); } if( p->pList ){ int i; for(i=0; ipList->nExpr; i++){ - mask |= exprTableUsage(base, p->pList->a[i].pExpr); + mask |= exprTableUsage(pMaskSet, p->pList->a[i].pExpr); } } return mask; @@ -127,25 +166,22 @@ static int allowedOp(int op){ ** "p" field filled in. The job of this routine is to analyze the ** subexpression and populate all the other fields of the ExprInfo ** structure. -** -** "base" is the cursor number (the value of the iTable field) that -** corresponds to the first entry in the table list. */ -static void exprAnalyze(int base, ExprInfo *pInfo){ +static void exprAnalyze(ExprMaskSet *pMaskSet, ExprInfo *pInfo){ Expr *pExpr = pInfo->p; - pInfo->prereqLeft = exprTableUsage(base, pExpr->pLeft); - pInfo->prereqRight = exprTableUsage(base, pExpr->pRight); - pInfo->prereqAll = exprTableUsage(base, pExpr); + pInfo->prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft); + pInfo->prereqRight = exprTableUsage(pMaskSet, pExpr->pRight); + pInfo->prereqAll = exprTableUsage(pMaskSet, pExpr); pInfo->indexable = 0; pInfo->idxLeft = -1; pInfo->idxRight = -1; if( allowedOp(pExpr->op) && (pInfo->prereqRight & pInfo->prereqLeft)==0 ){ if( pExpr->pRight && pExpr->pRight->op==TK_COLUMN ){ - pInfo->idxRight = pExpr->pRight->iTable - base; + pInfo->idxRight = pExpr->pRight->iTable; pInfo->indexable = 1; } if( pExpr->pLeft->op==TK_COLUMN ){ - pInfo->idxLeft = pExpr->pLeft->iTable - base; + pInfo->idxLeft = pExpr->pLeft->iTable; pInfo->indexable = 1; } } @@ -262,9 +298,9 @@ static Index *findSortingIndex( ** 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. +** number pTabList->a[0].iCursor. t2 uses the cursor pTabList->a[1].iCursor. +** And so forth. This routine generates code to open those VDBE cursors +** and 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 @@ -314,7 +350,6 @@ static Index *findSortingIndex( */ WhereInfo *sqliteWhereBegin( Parse *pParse, /* The parser context */ - int base, /* VDBE cursor index for left-most table in pTabList */ 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 */ @@ -327,6 +362,7 @@ WhereInfo *sqliteWhereBegin( int nExpr; /* Number of subexpressions in the WHERE clause */ int loopMask; /* One bit set for each outer loop */ int haveKey; /* True if KEY is on the stack */ + ExprMaskSet maskSet; /* The expression mask set */ int iDirectEq[32]; /* Term of the form ROWID==X for the N-th table */ int iDirectLt[32]; /* Term of the form ROWIDX or ROWID>=X */ @@ -342,6 +378,7 @@ WhereInfo *sqliteWhereBegin( ** array fills up, the last entry might point to an expression which ** contains additional unfactored AND operators. */ + initMaskSet(&maskSet); memset(aExpr, 0, sizeof(aExpr)); nExpr = exprSplit(ARRAYSIZE(aExpr), aExpr, pWhere); if( nExpr==ARRAYSIZE(aExpr) ){ @@ -363,7 +400,6 @@ WhereInfo *sqliteWhereBegin( } pWInfo->pParse = pParse; pWInfo->pTabList = pTabList; - pWInfo->base = base; pWInfo->peakNTab = pWInfo->savedNTab = pParse->nTab; pWInfo->iBreak = sqliteVdbeMakeLabel(v); @@ -378,7 +414,7 @@ WhereInfo *sqliteWhereBegin( /* Analyze all of the subexpressions. */ for(i=0; itrigStack ){ int x; if( (x = pParse->trigStack->newIdx) >= 0 ){ - int mask = ~(1 << (x - base)); + int mask = ~getMask(&maskSet, x); aExpr[i].prereqRight &= mask; aExpr[i].prereqLeft &= mask; aExpr[i].prereqAll &= mask; } if( (x = pParse->trigStack->oldIdx) >= 0 ){ - int mask = ~(1 << (x - base)); + int mask = ~getMask(&maskSet, x); aExpr[i].prereqRight &= mask; aExpr[i].prereqLeft &= mask; aExpr[i].prereqAll &= mask; @@ -419,8 +455,9 @@ WhereInfo *sqliteWhereBegin( loopMask = 0; for(i=0; inSrc && ia[idx].pTab; + int iCur = pTabList->a[i].iCursor; /* The cursor for this table */ + int mask = getMask(&maskSet, iCur); /* Cursor mask for this table */ + Table *pTab = pTabList->a[i].pTab; Index *pIdx; Index *pBestIdx = 0; int bestScore = 0; @@ -438,7 +475,7 @@ WhereInfo *sqliteWhereBegin( iDirectLt[i] = -1; iDirectGt[i] = -1; for(j=0; jpLeft->iColumn<0 + if( aExpr[j].idxLeft==iCur && aExpr[j].p->pLeft->iColumn<0 && (aExpr[j].prereqRight & loopMask)==aExpr[j].prereqRight ){ switch( aExpr[j].p->op ){ case TK_IN: @@ -449,7 +486,7 @@ WhereInfo *sqliteWhereBegin( case TK_GT: iDirectGt[i] = j; break; } } - if( aExpr[j].idxRight==idx && aExpr[j].p->pRight->iColumn<0 + if( aExpr[j].idxRight==iCur && aExpr[j].p->pRight->iColumn<0 && (aExpr[j].prereqLeft & loopMask)==aExpr[j].prereqLeft ){ switch( aExpr[j].p->op ){ case TK_EQ: iDirectEq[i] = j; break; @@ -461,7 +498,7 @@ WhereInfo *sqliteWhereBegin( } } if( iDirectEq[i]>=0 ){ - loopMask |= 1<a[i].pIdx = 0; continue; } @@ -500,7 +537,7 @@ WhereInfo *sqliteWhereBegin( if( pIdx->nColumn>32 ) continue; /* Ignore indices too many columns */ for(j=0; jpLeft->iColumn; int k; @@ -535,7 +572,7 @@ WhereInfo *sqliteWhereBegin( } } } - if( aExpr[j].idxRight==idx + if( aExpr[j].idxRight==iCur && (aExpr[j].prereqLeft & loopMask)==aExpr[j].prereqLeft ){ int iColumn = aExpr[j].p->pRight->iColumn; int k; @@ -588,7 +625,7 @@ WhereInfo *sqliteWhereBegin( pWInfo->a[i].pIdx = pBestIdx; pWInfo->a[i].score = bestScore; pWInfo->a[i].bRev = 0; - loopMask |= 1<a[i].iCur = pParse->nTab++; pWInfo->peakNTab = pParse->nTab; @@ -619,7 +656,8 @@ WhereInfo *sqliteWhereBegin( pSortIdx = 0; }else{ int nEqCol = (pWInfo->a[0].score+4)/8; - pSortIdx = findSortingIndex(pTab, base, *ppOrderBy, pIdx, nEqCol, &bRev); + pSortIdx = findSortingIndex(pTab, pTabList->a[0].iCursor, + *ppOrderBy, pIdx, nEqCol, &bRev); } if( pSortIdx && (pIdx==0 || pIdx==pSortIdx) ){ if( pIdx==0 ){ @@ -640,7 +678,7 @@ WhereInfo *sqliteWhereBegin( pTab = pTabList->a[i].pTab; if( pTab->isTransient || pTab->pSelect ) continue; sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0); - sqliteVdbeAddOp(v, OP_OpenRead, base+i, pTab->tnum); + sqliteVdbeAddOp(v, OP_OpenRead, pTabList->a[i].iCursor, pTab->tnum); sqliteVdbeChangeP3(v, -1, pTab->zName, P3_STATIC); if( i==0 && !pParse->schemaVerified && (pParse->db->flags & SQLITE_InTrans)==0 ){ @@ -659,7 +697,7 @@ WhereInfo *sqliteWhereBegin( loopMask = 0; for(i=0; inSrc; i++){ int j, k; - int idx = i; + int iCur = pTabList->a[i].iCursor; Index *pIdx; WhereLevel *pLevel = &pWInfo->a[i]; @@ -685,9 +723,9 @@ WhereInfo *sqliteWhereBegin( k = iDirectEq[i]; assert( kbrk = sqliteVdbeMakeLabel(v); - if( aExpr[k].idxLeft==idx ){ + if( aExpr[k].idxLeft==iCur ){ Expr *pX = aExpr[k].p; if( pX->op!=TK_IN ){ sqliteExprCode(pParse, aExpr[k].p->pRight); @@ -711,7 +749,7 @@ WhereInfo *sqliteWhereBegin( cont = pLevel->cont = sqliteVdbeMakeLabel(v); sqliteVdbeAddOp(v, OP_MustBeInt, 1, brk); haveKey = 0; - sqliteVdbeAddOp(v, OP_NotExists, base+idx, brk); + sqliteVdbeAddOp(v, OP_NotExists, iCur, brk); pLevel->op = OP_Noop; }else if( pIdx!=0 && pLevel->score>0 && pLevel->score%4==0 ){ /* Case 2: There is an index and all terms of the WHERE clause that @@ -725,7 +763,7 @@ WhereInfo *sqliteWhereBegin( for(k=0; kpLeft->iColumn==pIdx->aiColumn[j] ){ @@ -752,7 +790,7 @@ WhereInfo *sqliteWhereBegin( break; } } - if( aExpr[k].idxRight==idx + if( aExpr[k].idxRight==iCur && aExpr[k].p->op==TK_EQ && (aExpr[k].prereqLeft & loopMask)==aExpr[k].prereqLeft && aExpr[k].p->pRight->iColumn==pIdx->aiColumn[j] @@ -795,7 +833,7 @@ WhereInfo *sqliteWhereBegin( if( i==pTabList->nSrc-1 && pushKey ){ haveKey = 1; }else{ - sqliteVdbeAddOp(v, OP_MoveTo, base+idx, 0); + sqliteVdbeAddOp(v, OP_MoveTo, iCur, 0); haveKey = 0; } pLevel->p1 = pLevel->iCur; @@ -812,8 +850,8 @@ WhereInfo *sqliteWhereBegin( k = iDirectGt[i]; assert( kpRight); }else{ sqliteExprCode(pParse, aExpr[k].p->pLeft); @@ -822,17 +860,17 @@ WhereInfo *sqliteWhereBegin( if( aExpr[k].p->op==TK_LT || aExpr[k].p->op==TK_GT ){ sqliteVdbeAddOp(v, OP_AddImm, 1, 0); } - sqliteVdbeAddOp(v, OP_MoveTo, base+idx, brk); + sqliteVdbeAddOp(v, OP_MoveTo, iCur, brk); aExpr[k].p = 0; }else{ - sqliteVdbeAddOp(v, OP_Rewind, base+idx, brk); + sqliteVdbeAddOp(v, OP_Rewind, iCur, brk); } if( iDirectLt[i]>=0 ){ k = iDirectLt[i]; assert( kpRight); }else{ sqliteExprCode(pParse, aExpr[k].p->pLeft); @@ -849,10 +887,10 @@ WhereInfo *sqliteWhereBegin( } start = sqliteVdbeCurrentAddr(v); pLevel->op = OP_Next; - pLevel->p1 = base+idx; + pLevel->p1 = iCur; pLevel->p2 = start; if( testOp!=OP_Noop ){ - sqliteVdbeAddOp(v, OP_Recno, base+idx, 0); + sqliteVdbeAddOp(v, OP_Recno, iCur, 0); sqliteVdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0); sqliteVdbeAddOp(v, testOp, 0, brk); } @@ -865,10 +903,10 @@ WhereInfo *sqliteWhereBegin( brk = pLevel->brk = sqliteVdbeMakeLabel(v); cont = pLevel->cont = sqliteVdbeMakeLabel(v); - sqliteVdbeAddOp(v, OP_Rewind, base+idx, brk); + sqliteVdbeAddOp(v, OP_Rewind, iCur, brk); start = sqliteVdbeCurrentAddr(v); pLevel->op = OP_Next; - pLevel->p1 = base+idx; + pLevel->p1 = iCur; pLevel->p2 = start; haveKey = 0; }else{ @@ -894,7 +932,7 @@ WhereInfo *sqliteWhereBegin( for(j=0; jop==TK_EQ && (aExpr[k].prereqRight & loopMask)==aExpr[k].prereqRight && aExpr[k].p->pLeft->iColumn==pIdx->aiColumn[j] @@ -903,7 +941,7 @@ WhereInfo *sqliteWhereBegin( aExpr[k].p = 0; break; } - if( aExpr[k].idxRight==idx + if( aExpr[k].idxRight==iCur && aExpr[k].p->op==TK_EQ && (aExpr[k].prereqLeft & loopMask)==aExpr[k].prereqLeft && aExpr[k].p->pRight->iColumn==pIdx->aiColumn[j] @@ -939,7 +977,7 @@ WhereInfo *sqliteWhereBegin( for(k=0; kop==TK_LT || pExpr->op==TK_LE) && (aExpr[k].prereqRight & loopMask)==aExpr[k].prereqRight && pExpr->pLeft->iColumn==pIdx->aiColumn[j] @@ -949,7 +987,7 @@ WhereInfo *sqliteWhereBegin( aExpr[k].p = 0; break; } - if( aExpr[k].idxRight==idx + if( aExpr[k].idxRight==iCur && (pExpr->op==TK_GT || pExpr->op==TK_GE) && (aExpr[k].prereqLeft & loopMask)==aExpr[k].prereqLeft && pExpr->pRight->iColumn==pIdx->aiColumn[j] @@ -994,7 +1032,7 @@ WhereInfo *sqliteWhereBegin( for(k=0; kop==TK_GT || pExpr->op==TK_GE) && (aExpr[k].prereqRight & loopMask)==aExpr[k].prereqRight && pExpr->pLeft->iColumn==pIdx->aiColumn[j] @@ -1004,7 +1042,7 @@ WhereInfo *sqliteWhereBegin( aExpr[k].p = 0; break; } - if( aExpr[k].idxRight==idx + if( aExpr[k].idxRight==iCur && (pExpr->op==TK_LT || pExpr->op==TK_LE) && (aExpr[k].prereqLeft & loopMask)==aExpr[k].prereqLeft && pExpr->pRight->iColumn==pIdx->aiColumn[j] @@ -1050,7 +1088,7 @@ WhereInfo *sqliteWhereBegin( if( i==pTabList->nSrc-1 && pushKey ){ haveKey = 1; }else{ - sqliteVdbeAddOp(v, OP_MoveTo, base+idx, 0); + sqliteVdbeAddOp(v, OP_MoveTo, iCur, 0); haveKey = 0; } @@ -1060,7 +1098,7 @@ WhereInfo *sqliteWhereBegin( pLevel->p1 = pLevel->iCur; pLevel->p2 = start; } - loopMask |= 1<iContinue = cont; if( pushKey && !haveKey ){ - sqliteVdbeAddOp(v, OP_Recno, base, 0); + sqliteVdbeAddOp(v, OP_Recno, pTabList->a[0].iCursor, 0); } + freeMaskSet(&maskSet); return pWInfo; } @@ -1117,7 +1156,6 @@ WhereInfo *sqliteWhereBegin( void sqliteWhereEnd(WhereInfo *pWInfo){ Vdbe *v = pWInfo->pParse->pVdbe; int i; - int base = pWInfo->base; WhereLevel *pLevel; SrcList *pTabList = pWInfo->pTabList; @@ -1135,7 +1173,7 @@ void sqliteWhereEnd(WhereInfo *pWInfo){ int addr; addr = sqliteVdbeAddOp(v, OP_MemLoad, pLevel->iLeftJoin, 0); sqliteVdbeAddOp(v, OP_NotNull, 1, addr+4 + (pLevel->iCur>=0)); - sqliteVdbeAddOp(v, OP_NullRow, base+i, 0); + sqliteVdbeAddOp(v, OP_NullRow, pTabList->a[i].iCursor, 0); if( pLevel->iCur>=0 ){ sqliteVdbeAddOp(v, OP_NullRow, pLevel->iCur, 0); } @@ -1148,7 +1186,7 @@ void sqliteWhereEnd(WhereInfo *pWInfo){ assert( pTab!=0 ); if( pTab->isTransient || pTab->pSelect ) continue; pLevel = &pWInfo->a[i]; - sqliteVdbeAddOp(v, OP_Close, base+i, 0); + sqliteVdbeAddOp(v, OP_Close, pTabList->a[i].iCursor, 0); if( pLevel->pIdx!=0 ){ sqliteVdbeAddOp(v, OP_Close, pLevel->iCur, 0); } diff --git a/test/memdb.test b/test/memdb.test index 01e356d0ae..af62196043 100644 --- a/test/memdb.test +++ b/test/memdb.test @@ -11,7 +11,7 @@ # This file implements regression tests for SQLite library. The # focus of this script is in-memory database backend. # -# $Id: memdb.test,v 1.2 2003/04/20 23:45:23 drh Exp $ +# $Id: memdb.test,v 1.3 2003/05/02 14:32:15 drh Exp $ set testdir [file dirname $argv0] @@ -53,15 +53,25 @@ do_test memdb-1.1 { # make lots of changes to t3, then rollback and take another signature. # The two signatures should be the same. # -proc signature {} { - return [db eval {SELECT count(*), md5sum(x) FROM t3}] +proc signature {{fn {}}} { + set rx [db eval {SELECT x FROM t3}] + # set r1 [md5 $rx\n] + if {$fn!=""} { + # set fd [open $fn w] + # puts $fd $rx + # close $fd + } + # set r [db eval {SELECT count(*), md5sum(x) FROM t3}] + # puts "SIG($fn)=$r1" + return [list [string length $rx] $rx] } # Do rollbacks. Make sure the signature does not change. # set limit 10 for {set i 2} {$i<=$limit} {incr i} { - set ::sig [signature] + set ::sig [signature one] + # puts "sig=$sig" set cnt [lindex $::sig 0] set ::journal_format [expr {($i%3)+1}] if {$i%2==0} { @@ -77,8 +87,10 @@ for {set i 2} {$i<=$limit} {incr i} { INSERT INTO t3 SELECT randstr(10,10)||x FROM t3; ROLLBACK; } - signature + set sig2 [signature two] } $sig + # puts "sig2=$sig2" + # if {$sig2!=$sig} exit do_test memdb-1.$i.2-$cnt { execsql { BEGIN; diff --git a/test/view.test b/test/view.test index 3e088d169c..57043cfc01 100644 --- a/test/view.test +++ b/test/view.test @@ -11,7 +11,7 @@ # This file implements regression tests for SQLite library. The # focus of this file is testing VIEW statements. # -# $Id: view.test,v 1.13 2003/04/24 01:45:05 drh Exp $ +# $Id: view.test,v 1.14 2003/05/02 14:32:15 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -296,6 +296,16 @@ do_test view-8.5 { SELECT mx+10, mx*2 FROM v8; } } {13 6} +do_test view-8.6 { + execsql { + SELECT mx+10, pqr FROM v6, v8 WHERE xyz=2; + } +} {13 7} +do_test view-8.7 { + execsql { + SELECT mx+10, pqr FROM v6, v8 WHERE xyz>2; + } +} {13 13 13 19 13 27} # Tests for a bug found by Michiel de Wit involving ORDER BY in a VIEW. #