mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-07 02:42:48 +03:00
Update older opcode names to be more meaningful in light of the latest
code design. (CVS 2506) FossilOrigin-Name: 36f2da1f8d8d434f861ecad55c9d86549751c954
This commit is contained in:
38
manifest
38
manifest
@@ -1,5 +1,5 @@
|
||||
C Elminiate\sa\sVM\sopcode\sthat\swas\sno\slonger\sneeded.\s(CVS\s2505)
|
||||
D 2005-06-12T12:01:19
|
||||
C Update\solder\sopcode\snames\sto\sbe\smore\smeaningful\sin\slight\sof\sthe\slatest\ncode\sdesign.\s(CVS\s2506)
|
||||
D 2005-06-12T21:35:52
|
||||
F Makefile.in 8129e7f261d405db783676f9ca31e0841768c652
|
||||
F Makefile.linux-gcc 06be33b2a9ad4f005a5f42b22c4a19dab3cbb5c7
|
||||
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
|
||||
@@ -32,16 +32,16 @@ F src/attach.c 3615dbe960cbee4aa5ea300b8a213dad36527b0f
|
||||
F src/auth.c 18c5a0befe20f3a58a41e3ddd78f372faeeefe1f
|
||||
F src/btree.c d2e09ebf755bfd665727133361b22c6a915b12d7
|
||||
F src/btree.h 41a71ce027db9ddee72cb43df2316bbe3a1d92af
|
||||
F src/build.c 407343b7dac62f7ea44f166943708f6557906ae1
|
||||
F src/build.c 593d8fda0576a72e6f1fbf8f1a61db110dde9264
|
||||
F src/callback.c 0910b611e0c158f107ee3ff86f8a371654971e2b
|
||||
F src/date.c 2134ef4388256e8247405178df8a61bd60dc180a
|
||||
F src/delete.c 811f90d1c5950e57f985fc9d207d7eee1800096e
|
||||
F src/delete.c 4b68127f55971c7fb459146e0b6cf3bd70cfffe9
|
||||
F src/experimental.c 50c1e3b34f752f4ac10c36f287db095c2b61766d
|
||||
F src/expr.c e7245e9c3b1f890221cf5e7472c1aa1fed30d7ab
|
||||
F src/expr.c 6d7058944c5f4b7e4304be3fe63ada91dac221a1
|
||||
F src/func.c f208d71f741d47b63277530939f552815af8ce35
|
||||
F src/hash.c 2b1b13f7400e179631c83a1be0c664608c8f021f
|
||||
F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84
|
||||
F src/insert.c 34c25c33f51a43644a42cc091ac967b070c6b6d5
|
||||
F src/insert.c 8c0868a975fe37366ed92e1b976853be96284607
|
||||
F src/legacy.c d58ea507bce885298a2c8c3cbb0f4bff5d47830b
|
||||
F src/main.c f61bdb0a1afeb2eff7285f4f3752e1085ecc55ed
|
||||
F src/md5.c 7ae1c39044b95de2f62e066f47bb1deb880a1070
|
||||
@@ -56,14 +56,14 @@ F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
|
||||
F src/pager.c 841a2cdddd4275de36cda26ed9dc54ae942660ce
|
||||
F src/pager.h 0d9153d6269d60d04af3dd84a0cc0a96253cf4a4
|
||||
F src/parse.y 72cd7553f05fbc7b63ea9476108d0da6237f2818
|
||||
F src/pragma.c 344e50166437194c21332ada036671a3ac95652c
|
||||
F src/pragma.c 5ea2ba0e43f6a83968a936b071b77bd4516d11f0
|
||||
F src/prepare.c d53602d2f8e097225ae7c76ec764ae68f759ba47
|
||||
F src/printf.c 3d20b21cfecadacecac3fb7274e746cb81d3d357
|
||||
F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3
|
||||
F src/select.c 266416bb8af3827dd925f12646db8d59e2fe02ac
|
||||
F src/random.c 90adff4e73a3b249eb4f1fc2a6ff9cf78c7233a4
|
||||
F src/select.c 28b752e58955c7920711fbdbfdcd369a2bd09448
|
||||
F src/shell.c 25b3217d7c64e6497225439d261a253a23efff26
|
||||
F src/sqlite.h.in f28f5b018f03a66aaf0bc1ab6985d8605d6b964f
|
||||
F src/sqliteInt.h 42b464cd380dd81bf7873476fc5974985a506d71
|
||||
F src/sqliteInt.h c620e07e0c7e6e09d8623d165427f0f1f659aad5
|
||||
F src/table.c 25b3ff2b39b7d87e8d4a5da0713d68dfc06cbee9
|
||||
F src/tclsqlite.c af0f002d9d6ab4f7f32b9bee5b57665946e76ad9
|
||||
F src/test1.c 1ab9e62dd51a999ea1842f0bc8ae677d5ca04861
|
||||
@@ -72,18 +72,18 @@ F src/test3.c 683e1e3819152ffd35da2f201e507228921148d0
|
||||
F src/test4.c 7c6b9fc33dd1f3f93c7f1ee6e5e6d016afa6c1df
|
||||
F src/test5.c 64f08b2a50ef371a1bd68ff206829e7b1b9997f5
|
||||
F src/tokenize.c d89743f2c0d05d49b5b4d6462432a1f3cc4765f1
|
||||
F src/trigger.c 1a6d0c7c51b70bdc58d5068be72034071eff23ad
|
||||
F src/update.c 04ea9dd784ccfeaf38a681b3edfe3b1c4edfdda7
|
||||
F src/trigger.c f51dec15921629591cb98bf2e350018e268b109a
|
||||
F src/update.c e96c7b342cd8903c672162f4cf84d2c737943347
|
||||
F src/utf.c bda5eb85039ef16f2d17004c1e18c96e1ab0a80c
|
||||
F src/util.c 96008b52604d08b9cc57ed37350149d6ac8a1bf3
|
||||
F src/vacuum.c 829d9e1a6d7c094b80e0899686670932eafd768c
|
||||
F src/vdbe.c 77c53143c329df6a1d5b14cbb3ed61164063c5e4
|
||||
F src/vdbe.c c2511f392598928254504e3b2c5ec47f4fef2b53
|
||||
F src/vdbe.h 75e466d84d362b0c4498978a9d6b1e6bd32ecf3b
|
||||
F src/vdbeInt.h 4afaae2f4adcab54ad2a40dabb2e689fba7b1561
|
||||
F src/vdbeInt.h 4312faf41630a6c215924b6c7c2f39ebb1af8ffb
|
||||
F src/vdbeapi.c 9a9556b9d7e3a052f58de389caf69449558e7380
|
||||
F src/vdbeaux.c d078d96e47a391666af10fce2fbabb1ace19a4b0
|
||||
F src/vdbeaux.c c99e32abeba4b7522e3922afff2c32ff4bd17eb5
|
||||
F src/vdbemem.c 48a64ae95a9edc6e8d940300dad15d70d1670398
|
||||
F src/where.c f02baff03e2a9ed7bdc36b363b8e4024a94de919
|
||||
F src/where.c 3a9a2258ab3364655e9ea215ad5ae7bf41813f54
|
||||
F tclinstaller.tcl 046e3624671962dc50f0481d7c25b38ef803eb42
|
||||
F test/all.test 7f0988442ab811dfa41793b5b550f5828ce316f3
|
||||
F test/alter.test 9d6837a3d946b73df692b7cef2a7644d2e2f6bc6
|
||||
@@ -281,7 +281,7 @@ F www/tclsqlite.tcl 425be741b8ae664f55cb1ef2371aab0a75109cf9
|
||||
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
||||
F www/version3.tcl a99cf5f6d8bd4d5537584a2b342f0fb9fa601d8b
|
||||
F www/whentouse.tcl 528299b8316726dbcc5548e9aa0648c8b1bd055b
|
||||
P 62a7353d4af4886b1561832e8b36e8e788b38834
|
||||
R 59f3cd1f9900eff80ed20c2925adf396
|
||||
P 97b348a5ad2f090ba7a75467b97c6dfb575df09c
|
||||
R 8569c8c1f2245087cc1ec4a7869dfa68
|
||||
U drh
|
||||
Z 09f39e38571ac1460392187d00e1cd29
|
||||
Z 08316380432fe4e2f32db98927281007
|
||||
|
@@ -1 +1 @@
|
||||
97b348a5ad2f090ba7a75467b97c6dfb575df09c
|
||||
36f2da1f8d8d434f861ecad55c9d86549751c954
|
10
src/build.c
10
src/build.c
@@ -22,7 +22,7 @@
|
||||
** COMMIT
|
||||
** ROLLBACK
|
||||
**
|
||||
** $Id: build.c,v 1.325 2005/06/06 21:19:57 drh Exp $
|
||||
** $Id: build.c,v 1.326 2005/06/12 21:35:52 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <ctype.h>
|
||||
@@ -791,10 +791,10 @@ void sqlite3StartTable(
|
||||
sqlite3VdbeAddOp(v, OP_CreateTable, iDb, 0);
|
||||
}
|
||||
sqlite3OpenMasterTable(v, iDb);
|
||||
sqlite3VdbeAddOp(v, OP_NewRecno, 0, 0);
|
||||
sqlite3VdbeAddOp(v, OP_NewRowid, 0, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
|
||||
sqlite3VdbeAddOp(v, OP_String8, 0, 0);
|
||||
sqlite3VdbeAddOp(v, OP_PutIntKey, 0, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Null, 0, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Insert, 0, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Close, 0, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Pull, 1, 0);
|
||||
}
|
||||
@@ -2008,7 +2008,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
|
||||
addr1 = sqlite3VdbeAddOp(v, OP_Rewind, iTab, 0);
|
||||
sqlite3GenerateIndexKey(v, pIndex, iTab);
|
||||
isUnique = pIndex->onError!=OE_None;
|
||||
sqlite3VdbeAddOp(v, OP_IdxPut, iIdx, isUnique);
|
||||
sqlite3VdbeAddOp(v, OP_IdxInsert, iIdx, isUnique);
|
||||
if( isUnique ){
|
||||
sqlite3VdbeChangeP3(v, -1, "indexed columns are not unique", P3_STATIC);
|
||||
}
|
||||
|
10
src/delete.c
10
src/delete.c
@@ -12,7 +12,7 @@
|
||||
** This file contains C code routines that are called by the parser
|
||||
** in order to generate code for DELETE FROM statements.
|
||||
**
|
||||
** $Id: delete.c,v 1.105 2005/06/06 21:19:57 drh Exp $
|
||||
** $Id: delete.c,v 1.106 2005/06/12 21:35:52 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@@ -239,7 +239,7 @@ void sqlite3DeleteFrom(
|
||||
|
||||
/* Remember the rowid of every item to be deleted.
|
||||
*/
|
||||
sqlite3VdbeAddOp(v, OP_Recno, iCur, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
|
||||
sqlite3VdbeAddOp(v, OP_ListWrite, 0, 0);
|
||||
if( db->flags & SQLITE_CountRows ){
|
||||
sqlite3VdbeAddOp(v, OP_AddImm, 1, 0);
|
||||
@@ -273,9 +273,9 @@ void sqlite3DeleteFrom(
|
||||
sqlite3OpenTableForReading(v, iCur, pTab);
|
||||
}
|
||||
sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Recno, iCur, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
|
||||
sqlite3VdbeAddOp(v, OP_RowData, iCur, 0);
|
||||
sqlite3VdbeAddOp(v, OP_PutIntKey, oldIdx, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Insert, oldIdx, 0);
|
||||
if( !isView ){
|
||||
sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
|
||||
}
|
||||
@@ -432,7 +432,7 @@ void sqlite3GenerateIndexKey(
|
||||
int j;
|
||||
Table *pTab = pIdx->pTable;
|
||||
|
||||
sqlite3VdbeAddOp(v, OP_Recno, iCur, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
|
||||
for(j=0; j<pIdx->nColumn; j++){
|
||||
int idx = pIdx->aiColumn[j];
|
||||
if( idx==pTab->iPKey ){
|
||||
|
23
src/expr.c
23
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.205 2005/06/06 21:19:57 drh Exp $
|
||||
** $Id: expr.c,v 1.206 2005/06/12 21:35:52 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <ctype.h>
|
||||
@@ -138,7 +138,7 @@ int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity){
|
||||
*/
|
||||
static int binaryCompareP1(Expr *pExpr1, Expr *pExpr2, int jumpIfNull){
|
||||
char aff = sqlite3ExprAffinity(pExpr2);
|
||||
return (((int)sqlite3CompareAffinity(pExpr1, aff))<<8)+(jumpIfNull?1:0);
|
||||
return ((int)sqlite3CompareAffinity(pExpr1, aff))+(jumpIfNull?0x100:0);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1309,8 +1309,7 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
|
||||
/* Evaluate the expression and insert it into the temp table */
|
||||
sqlite3ExprCode(pParse, pE2);
|
||||
sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, &affinity, 1);
|
||||
sqlite3VdbeAddOp(v, OP_String8, 0, 0);
|
||||
sqlite3VdbeAddOp(v, OP_PutStrKey, pExpr->iTable, 0);
|
||||
sqlite3VdbeAddOp(v, OP_IdxInsert, pExpr->iTable, 0);
|
||||
}
|
||||
}
|
||||
sqlite3VdbeChangeP3(v, addr, (void *)&keyInfo, P3_KEYINFO);
|
||||
@@ -1382,7 +1381,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
|
||||
int op;
|
||||
if( v==0 ) return;
|
||||
if( pExpr==0 ){
|
||||
sqlite3VdbeAddOp(v, OP_String8, 0, 0); /* Empty expression evals to NULL */
|
||||
sqlite3VdbeAddOp(v, OP_Null, 0, 0);
|
||||
return;
|
||||
}
|
||||
op = pExpr->op;
|
||||
@@ -1394,7 +1393,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
|
||||
sqlite3VdbeAddOp(v, OP_Column, pExpr->iTable, pExpr->iColumn);
|
||||
sqlite3ColumnDefault(v, pExpr->pTab, pExpr->iColumn);
|
||||
}else{
|
||||
sqlite3VdbeAddOp(v, OP_Recno, pExpr->iTable, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Rowid, pExpr->iTable, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1410,6 +1409,10 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
|
||||
sqlite3VdbeDequoteP3(v, -1);
|
||||
break;
|
||||
}
|
||||
case TK_NULL: {
|
||||
sqlite3VdbeAddOp(v, OP_Null, 0, 0);
|
||||
break;
|
||||
}
|
||||
#ifndef SQLITE_OMIT_BLOB_LITERAL
|
||||
case TK_BLOB: {
|
||||
assert( TK_BLOB==OP_HexBlob );
|
||||
@@ -1418,10 +1421,6 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case TK_NULL: {
|
||||
sqlite3VdbeAddOp(v, OP_String8, 0, 0);
|
||||
break;
|
||||
}
|
||||
case TK_VARIABLE: {
|
||||
sqlite3VdbeAddOp(v, OP_Variable, pExpr->iTable, 0);
|
||||
if( pExpr->token.n>1 ){
|
||||
@@ -1578,7 +1577,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
|
||||
addr = sqlite3VdbeCurrentAddr(v);
|
||||
sqlite3VdbeAddOp(v, OP_NotNull, -1, addr+4); /* addr + 0 */
|
||||
sqlite3VdbeAddOp(v, OP_Pop, 2, 0);
|
||||
sqlite3VdbeAddOp(v, OP_String8, 0, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Null, 0, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Goto, 0, addr+7);
|
||||
sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, &affinity, 1); /* addr + 4 */
|
||||
sqlite3VdbeAddOp(v, OP_Found, pExpr->iTable, addr+7);
|
||||
@@ -1648,7 +1647,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
|
||||
if( pExpr->pRight ){
|
||||
sqlite3ExprCode(pParse, pExpr->pRight);
|
||||
}else{
|
||||
sqlite3VdbeAddOp(v, OP_String8, 0, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Null, 0, 0);
|
||||
}
|
||||
sqlite3VdbeResolveLabel(v, expr_end_label);
|
||||
break;
|
||||
|
64
src/insert.c
64
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.138 2005/03/21 01:20:58 drh Exp $
|
||||
** $Id: insert.c,v 1.139 2005/06/12 21:35:52 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@@ -308,7 +308,7 @@ void sqlite3Insert(
|
||||
sqlite3VdbeAddOp(v, OP_Column, iCur, 0);
|
||||
sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->zName, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Ne, 28417, base+12);
|
||||
sqlite3VdbeAddOp(v, OP_Recno, iCur, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
|
||||
sqlite3VdbeAddOp(v, OP_MemStore, counterRowid, 1);
|
||||
sqlite3VdbeAddOp(v, OP_Column, iCur, 1);
|
||||
sqlite3VdbeAddOp(v, OP_MemStore, counterMem, 1);
|
||||
@@ -363,9 +363,9 @@ void sqlite3Insert(
|
||||
sqlite3VdbeResolveLabel(v, iInsertBlock);
|
||||
sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0);
|
||||
sqlite3TableAffinityStr(v, pTab);
|
||||
sqlite3VdbeAddOp(v, OP_NewRecno, srcTab, 0);
|
||||
sqlite3VdbeAddOp(v, OP_NewRowid, srcTab, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Pull, 1, 0);
|
||||
sqlite3VdbeAddOp(v, OP_PutIntKey, srcTab, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Insert, srcTab, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Return, 0, 0);
|
||||
|
||||
/* The following code runs first because the GOTO at the very top
|
||||
@@ -547,7 +547,7 @@ void sqlite3Insert(
|
||||
if( !isView ){
|
||||
sqlite3TableAffinityStr(v, pTab);
|
||||
}
|
||||
sqlite3VdbeAddOp(v, OP_PutIntKey, newIdx, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Insert, newIdx, 0);
|
||||
|
||||
/* Fire BEFORE or INSTEAD OF triggers */
|
||||
if( sqlite3CodeRowTrigger(pParse, TK_INSERT, 0, TRIGGER_BEFORE, pTab,
|
||||
@@ -565,7 +565,7 @@ void sqlite3Insert(
|
||||
}
|
||||
|
||||
/* Push the record number for the new entry onto the stack. The
|
||||
** record number is a randomly generate integer created by NewRecno
|
||||
** record number is a randomly generate integer created by NewRowid
|
||||
** except when the table has an INTEGER PRIMARY KEY column, in which
|
||||
** case the record number is the same as that column.
|
||||
*/
|
||||
@@ -578,15 +578,15 @@ void sqlite3Insert(
|
||||
}else{
|
||||
sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr);
|
||||
}
|
||||
/* If the PRIMARY KEY expression is NULL, then use OP_NewRecno
|
||||
/* If the PRIMARY KEY expression is NULL, then use OP_NewRowid
|
||||
** to generate a unique primary key value.
|
||||
*/
|
||||
sqlite3VdbeAddOp(v, OP_NotNull, -1, sqlite3VdbeCurrentAddr(v)+3);
|
||||
sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
|
||||
sqlite3VdbeAddOp(v, OP_NewRecno, base, counterMem);
|
||||
sqlite3VdbeAddOp(v, OP_NewRowid, base, counterMem);
|
||||
sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0);
|
||||
}else{
|
||||
sqlite3VdbeAddOp(v, OP_NewRecno, base, counterMem);
|
||||
sqlite3VdbeAddOp(v, OP_NewRowid, base, counterMem);
|
||||
}
|
||||
#ifndef SQLITE_OMIT_AUTOINCREMENT
|
||||
if( pTab->autoInc ){
|
||||
@@ -603,7 +603,7 @@ void sqlite3Insert(
|
||||
** Whenever this column is read, the record number will be substituted
|
||||
** in its place. So will fill this column with a NULL to avoid
|
||||
** taking up data space with information that will never be used. */
|
||||
sqlite3VdbeAddOp(v, OP_String8, 0, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Null, 0, 0);
|
||||
continue;
|
||||
}
|
||||
if( pColumn==0 ){
|
||||
@@ -690,11 +690,11 @@ void sqlite3Insert(
|
||||
sqlite3VdbeAddOp(v, OP_MemLoad, counterRowid, 0);
|
||||
sqlite3VdbeAddOp(v, OP_NotNull, -1, base+7);
|
||||
sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
|
||||
sqlite3VdbeAddOp(v, OP_NewRecno, iCur, 0);
|
||||
sqlite3VdbeAddOp(v, OP_NewRowid, iCur, 0);
|
||||
sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->zName, 0);
|
||||
sqlite3VdbeAddOp(v, OP_MemLoad, counterMem, 0);
|
||||
sqlite3VdbeAddOp(v, OP_MakeRecord, 2, 0);
|
||||
sqlite3VdbeAddOp(v, OP_PutIntKey, iCur, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Insert, iCur, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
|
||||
}
|
||||
#endif
|
||||
@@ -724,11 +724,11 @@ insert_cleanup:
|
||||
** When this routine is called, the stack contains (from bottom to top)
|
||||
** the following values:
|
||||
**
|
||||
** 1. The recno of the row to be updated before the update. This
|
||||
** 1. The rowid of the row to be updated before the update. This
|
||||
** value is omitted unless we are doing an UPDATE that involves a
|
||||
** change to the record number.
|
||||
**
|
||||
** 2. The recno of the row after the update.
|
||||
** 2. The rowid of the row after the update.
|
||||
**
|
||||
** 3. The data in the first column of the entry after the update.
|
||||
**
|
||||
@@ -736,9 +736,9 @@ insert_cleanup:
|
||||
**
|
||||
** N. The data in the last column of the entry after the update.
|
||||
**
|
||||
** The old recno shown as entry (1) above is omitted unless both isUpdate
|
||||
** and recnoChng are 1. isUpdate is true for UPDATEs and false for
|
||||
** INSERTs and recnoChng is true if the record number is being changed.
|
||||
** The old rowid shown as entry (1) above is omitted unless both isUpdate
|
||||
** and rowidChng are 1. isUpdate is true for UPDATEs and false for
|
||||
** INSERTs and rowidChng is true if the record number is being changed.
|
||||
**
|
||||
** The code generated by this routine pushes additional entries onto
|
||||
** the stack which are the keys for new index entries for the new record.
|
||||
@@ -802,7 +802,7 @@ void sqlite3GenerateConstraintChecks(
|
||||
Table *pTab, /* the table into which we are inserting */
|
||||
int base, /* Index of a read/write cursor pointing at pTab */
|
||||
char *aIdxUsed, /* Which indices are used. NULL means all are used */
|
||||
int recnoChng, /* True if the record number will change */
|
||||
int rowidChng, /* True if the record number will change */
|
||||
int isUpdate, /* True for UPDATE, False for INSERT */
|
||||
int overrideError, /* Override onError to this if not OE_Default */
|
||||
int ignoreDest /* Jump to this label on an OE_Ignore resolution */
|
||||
@@ -818,7 +818,7 @@ void sqlite3GenerateConstraintChecks(
|
||||
int seenReplace = 0;
|
||||
int jumpInst1=0, jumpInst2;
|
||||
int contAddr;
|
||||
int hasTwoRecnos = (isUpdate && recnoChng);
|
||||
int hasTwoRowids = (isUpdate && rowidChng);
|
||||
|
||||
v = sqlite3GetVdbe(pParse);
|
||||
assert( v!=0 );
|
||||
@@ -857,7 +857,7 @@ void sqlite3GenerateConstraintChecks(
|
||||
break;
|
||||
}
|
||||
case OE_Ignore: {
|
||||
sqlite3VdbeAddOp(v, OP_Pop, nCol+1+hasTwoRecnos, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Pop, nCol+1+hasTwoRowids, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Goto, 0, ignoreDest);
|
||||
break;
|
||||
}
|
||||
@@ -878,7 +878,7 @@ void sqlite3GenerateConstraintChecks(
|
||||
** of the new record does not previously exist. Except, if this
|
||||
** is an UPDATE and the primary key is not changing, that is OK.
|
||||
*/
|
||||
if( recnoChng ){
|
||||
if( rowidChng ){
|
||||
onError = pTab->keyConf;
|
||||
if( overrideError!=OE_Default ){
|
||||
onError = overrideError;
|
||||
@@ -908,7 +908,7 @@ void sqlite3GenerateConstraintChecks(
|
||||
case OE_Replace: {
|
||||
sqlite3GenerateRowIndexDelete(pParse->db, v, pTab, base, 0);
|
||||
if( isUpdate ){
|
||||
sqlite3VdbeAddOp(v, OP_Dup, nCol+hasTwoRecnos, 1);
|
||||
sqlite3VdbeAddOp(v, OP_Dup, nCol+hasTwoRowids, 1);
|
||||
sqlite3VdbeAddOp(v, OP_MoveGe, base, 0);
|
||||
}
|
||||
seenReplace = 1;
|
||||
@@ -916,7 +916,7 @@ void sqlite3GenerateConstraintChecks(
|
||||
}
|
||||
case OE_Ignore: {
|
||||
assert( seenReplace==0 );
|
||||
sqlite3VdbeAddOp(v, OP_Pop, nCol+1+hasTwoRecnos, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Pop, nCol+1+hasTwoRowids, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Goto, 0, ignoreDest);
|
||||
break;
|
||||
}
|
||||
@@ -967,7 +967,7 @@ void sqlite3GenerateConstraintChecks(
|
||||
|
||||
|
||||
/* Check to see if the new index entry will be unique */
|
||||
sqlite3VdbeAddOp(v, OP_Dup, extra+nCol+1+hasTwoRecnos, 1);
|
||||
sqlite3VdbeAddOp(v, OP_Dup, extra+nCol+1+hasTwoRowids, 1);
|
||||
jumpInst2 = sqlite3VdbeAddOp(v, OP_IsUnique, base+iCur+1, 0);
|
||||
|
||||
/* Generate code that executes if the new index entry is not unique */
|
||||
@@ -1004,14 +1004,14 @@ void sqlite3GenerateConstraintChecks(
|
||||
}
|
||||
case OE_Ignore: {
|
||||
assert( seenReplace==0 );
|
||||
sqlite3VdbeAddOp(v, OP_Pop, nCol+extra+3+hasTwoRecnos, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Pop, nCol+extra+3+hasTwoRowids, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Goto, 0, ignoreDest);
|
||||
break;
|
||||
}
|
||||
case OE_Replace: {
|
||||
sqlite3GenerateRowDelete(pParse->db, v, pTab, base, 0);
|
||||
if( isUpdate ){
|
||||
sqlite3VdbeAddOp(v, OP_Dup, nCol+extra+1+hasTwoRecnos, 1);
|
||||
sqlite3VdbeAddOp(v, OP_Dup, nCol+extra+1+hasTwoRowids, 1);
|
||||
sqlite3VdbeAddOp(v, OP_MoveGe, base, 0);
|
||||
}
|
||||
seenReplace = 1;
|
||||
@@ -1031,7 +1031,7 @@ void sqlite3GenerateConstraintChecks(
|
||||
** This routine generates code to finish the INSERT or UPDATE operation
|
||||
** that was started by a prior call to sqlite3GenerateConstraintChecks.
|
||||
** The stack must contain keys for all active indices followed by data
|
||||
** and the recno for the new entry. This routine creates the new
|
||||
** and the rowid for the new entry. This routine creates the new
|
||||
** entries in all indices and in the main table.
|
||||
**
|
||||
** The arguments to this routine should be the same as the first six
|
||||
@@ -1042,7 +1042,7 @@ void sqlite3CompleteInsertion(
|
||||
Table *pTab, /* the table into which we are inserting */
|
||||
int base, /* Index of a read/write cursor pointing at pTab */
|
||||
char *aIdxUsed, /* Which indices are used. NULL means all are used */
|
||||
int recnoChng, /* True if the record number will change */
|
||||
int rowidChng, /* True if the record number will change */
|
||||
int isUpdate, /* True for UPDATE, False for INSERT */
|
||||
int newIdx /* Index of NEW table for triggers. -1 if none */
|
||||
){
|
||||
@@ -1058,7 +1058,7 @@ void sqlite3CompleteInsertion(
|
||||
for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){}
|
||||
for(i=nIdx-1; i>=0; i--){
|
||||
if( aIdxUsed && aIdxUsed[i]==0 ) continue;
|
||||
sqlite3VdbeAddOp(v, OP_IdxPut, base+i+1, 0);
|
||||
sqlite3VdbeAddOp(v, OP_IdxInsert, base+i+1, 0);
|
||||
}
|
||||
sqlite3VdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
|
||||
sqlite3TableAffinityStr(v, pTab);
|
||||
@@ -1066,7 +1066,7 @@ void sqlite3CompleteInsertion(
|
||||
if( newIdx>=0 ){
|
||||
sqlite3VdbeAddOp(v, OP_Dup, 1, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Dup, 1, 0);
|
||||
sqlite3VdbeAddOp(v, OP_PutIntKey, newIdx, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Insert, newIdx, 0);
|
||||
}
|
||||
#endif
|
||||
if( pParse->nested ){
|
||||
@@ -1074,9 +1074,9 @@ void sqlite3CompleteInsertion(
|
||||
}else{
|
||||
pik_flags = (OPFLAG_NCHANGE|(isUpdate?0:OPFLAG_LASTROWID));
|
||||
}
|
||||
sqlite3VdbeAddOp(v, OP_PutIntKey, base, pik_flags);
|
||||
sqlite3VdbeAddOp(v, OP_Insert, base, pik_flags);
|
||||
|
||||
if( isUpdate && recnoChng ){
|
||||
if( isUpdate && rowidChng ){
|
||||
sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
|
||||
}
|
||||
}
|
||||
|
@@ -11,7 +11,7 @@
|
||||
*************************************************************************
|
||||
** This file contains code used to implement the PRAGMA command.
|
||||
**
|
||||
** $Id: pragma.c,v 1.94 2005/06/07 22:22:51 drh Exp $
|
||||
** $Id: pragma.c,v 1.95 2005/06/12 21:35:52 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "os.h"
|
||||
@@ -693,7 +693,7 @@ void sqlite3Pragma(
|
||||
static const VdbeOpList idxErr[] = {
|
||||
{ OP_MemIncr, 0, 0, 0},
|
||||
{ OP_String8, 0, 0, "rowid "},
|
||||
{ OP_Recno, 1, 0, 0},
|
||||
{ OP_Rowid, 1, 0, 0},
|
||||
{ OP_String8, 0, 0, " missing from index "},
|
||||
{ OP_String8, 0, 0, 0}, /* 4 */
|
||||
{ OP_Concat, 2, 0, 0},
|
||||
|
10
src/random.c
10
src/random.c
@@ -15,7 +15,7 @@
|
||||
** Random numbers are used by some of the database backends in order
|
||||
** to generate random integer keys for tables or random filenames.
|
||||
**
|
||||
** $Id: random.c,v 1.12 2004/05/08 08:23:32 danielk1977 Exp $
|
||||
** $Id: random.c,v 1.13 2005/06/12 21:35:52 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "os.h"
|
||||
@@ -26,13 +26,16 @@
|
||||
** must be held while executing this routine.
|
||||
**
|
||||
** Why not just use a library random generator like lrand48() for this?
|
||||
** Because the OP_NewRecno opcode in the VDBE depends on having a very
|
||||
** Because the OP_NewRowid opcode in the VDBE depends on having a very
|
||||
** good source of random numbers. The lrand48() library function may
|
||||
** well be good enough. But maybe not. Or maybe lrand48() has some
|
||||
** subtle problems on some systems that could cause problems. It is hard
|
||||
** to know. To minimize the risk of problems due to bad lrand48()
|
||||
** implementations, SQLite uses this random number generator based
|
||||
** on RC4, which we know works very well.
|
||||
**
|
||||
** (Later): Actually, OP_NewRowid does not depend on a good source of
|
||||
** randomness any more. But we will leave this code in all the same.
|
||||
*/
|
||||
static int randomByte(){
|
||||
unsigned char t;
|
||||
@@ -95,6 +98,3 @@ void sqlite3Randomness(int N, void *pBuf){
|
||||
}
|
||||
sqlite3OsLeaveMutex();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
42
src/select.c
42
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.251 2005/06/12 12:01:19 drh Exp $
|
||||
** $Id: select.c,v 1.252 2005/06/12 21:35:52 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@@ -326,7 +326,7 @@ static void pushOntoSorter(Parse *pParse, Vdbe *v, ExprList *pOrderBy){
|
||||
sqlite3ExprCode(pParse, pOrderBy->a[i].pExpr);
|
||||
}
|
||||
sqlite3VdbeAddOp(v, OP_MakeRecord, pOrderBy->nExpr, 0);
|
||||
sqlite3VdbeAddOp(v, OP_SortPut, 0, 0);
|
||||
sqlite3VdbeAddOp(v, OP_SortInsert, 0, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -422,8 +422,7 @@ static int selectInnerLoop(
|
||||
sqlite3VdbeAddOp(v, OP_Pop, pEList->nExpr+1, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Goto, 0, iContinue);
|
||||
VdbeComment((v, "# skip indistinct records"));
|
||||
sqlite3VdbeAddOp(v, OP_String8, 0, 0);
|
||||
sqlite3VdbeAddOp(v, OP_PutStrKey, distinct, 0);
|
||||
sqlite3VdbeAddOp(v, OP_IdxInsert, distinct, 0);
|
||||
if( pOrderBy==0 ){
|
||||
codeLimiter(v, p, iContinue, iBreak, nColumn);
|
||||
}
|
||||
@@ -437,8 +436,7 @@ static int selectInnerLoop(
|
||||
case SRT_Union: {
|
||||
sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, NULL_ALWAYS_DISTINCT);
|
||||
sqlite3VdbeChangeP3(v, -1, aff, P3_STATIC);
|
||||
sqlite3VdbeAddOp(v, OP_String8, 0, 0);
|
||||
sqlite3VdbeAddOp(v, OP_PutStrKey, iParm, 0);
|
||||
sqlite3VdbeAddOp(v, OP_IdxInsert, iParm, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -464,9 +462,9 @@ static int selectInnerLoop(
|
||||
if( pOrderBy ){
|
||||
pushOntoSorter(pParse, v, pOrderBy);
|
||||
}else{
|
||||
sqlite3VdbeAddOp(v, OP_NewRecno, iParm, 0);
|
||||
sqlite3VdbeAddOp(v, OP_NewRowid, iParm, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Pull, 1, 0);
|
||||
sqlite3VdbeAddOp(v, OP_PutIntKey, iParm, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Insert, iParm, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -490,8 +488,7 @@ static int selectInnerLoop(
|
||||
char aff = (iParm>>16)&0xFF;
|
||||
aff = sqlite3CompareAffinity(pEList->a[0].pExpr, aff);
|
||||
sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, &aff, 1);
|
||||
sqlite3VdbeAddOp(v, OP_String8, 0, 0);
|
||||
sqlite3VdbeAddOp(v, OP_PutStrKey, (iParm&0x0000FFFF), 0);
|
||||
sqlite3VdbeAddOp(v, OP_IdxInsert, (iParm&0x0000FFFF), 0);
|
||||
}
|
||||
sqlite3VdbeChangeP2(v, addr2, sqlite3VdbeCurrentAddr(v));
|
||||
break;
|
||||
@@ -603,9 +600,9 @@ static void generateSortTail(
|
||||
switch( eDest ){
|
||||
case SRT_Table:
|
||||
case SRT_TempTable: {
|
||||
sqlite3VdbeAddOp(v, OP_NewRecno, iParm, 0);
|
||||
sqlite3VdbeAddOp(v, OP_NewRowid, iParm, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Pull, 1, 0);
|
||||
sqlite3VdbeAddOp(v, OP_PutIntKey, iParm, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Insert, iParm, 0);
|
||||
break;
|
||||
}
|
||||
#ifndef SQLITE_OMIT_SUBQUERY
|
||||
@@ -615,8 +612,7 @@ static void generateSortTail(
|
||||
sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+3);
|
||||
sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, "n", P3_STATIC);
|
||||
sqlite3VdbeAddOp(v, OP_String8, 0, 0);
|
||||
sqlite3VdbeAddOp(v, OP_PutStrKey, (iParm&0x0000FFFF), 0);
|
||||
sqlite3VdbeAddOp(v, OP_IdxInsert, (iParm&0x0000FFFF), 0);
|
||||
break;
|
||||
}
|
||||
case SRT_Exists:
|
||||
@@ -1326,11 +1322,9 @@ static void computeLimitRegisters(Parse *pParse, Select *p){
|
||||
** DISTINCT, UNION, INTERSECT and EXCEPT select statements (but not
|
||||
** UNION ALL).
|
||||
**
|
||||
** Make the new table a KeyAsData table if keyAsData is true.
|
||||
**
|
||||
** The value returned is the address of the OP_OpenTemp instruction.
|
||||
*/
|
||||
static int openTempIndex(Parse *pParse, Select *p, int iTab, int keyAsData){
|
||||
static int openTempIndex(Parse *pParse, Select *p, int iTab){
|
||||
KeyInfo *pKeyInfo;
|
||||
int nColumn;
|
||||
sqlite3 *db = pParse->db;
|
||||
@@ -1354,9 +1348,6 @@ static int openTempIndex(Parse *pParse, Select *p, int iTab, int keyAsData){
|
||||
}
|
||||
addr = sqlite3VdbeOp3(v, OP_OpenTemp, iTab, 0,
|
||||
(char*)pKeyInfo, P3_KEYINFO_HANDOFF);
|
||||
if( keyAsData ){
|
||||
sqlite3VdbeAddOp(v, OP_KeyAsData, iTab, 1);
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
@@ -1551,7 +1542,6 @@ static int multiSelect(
|
||||
if( rc!=SQLITE_OK ){
|
||||
goto multi_select_end;
|
||||
}
|
||||
sqlite3VdbeAddOp(v, OP_KeyAsData, unionTab, 1);
|
||||
}
|
||||
assert( nAddr<sizeof(aAddr)/sizeof(aAddr[0]) );
|
||||
aAddr[nAddr++] = sqlite3VdbeAddOp(v, OP_SetNumColumns, unionTab, 0);
|
||||
@@ -1643,7 +1633,6 @@ static int multiSelect(
|
||||
if( rc!=SQLITE_OK ){
|
||||
goto multi_select_end;
|
||||
}
|
||||
sqlite3VdbeAddOp(v, OP_KeyAsData, tab1, 1);
|
||||
assert( nAddr<sizeof(aAddr)/sizeof(aAddr[0]) );
|
||||
aAddr[nAddr++] = sqlite3VdbeAddOp(v, OP_SetNumColumns, tab1, 0);
|
||||
assert( p->pEList );
|
||||
@@ -1662,7 +1651,6 @@ static int multiSelect(
|
||||
if( rc!=SQLITE_OK ){
|
||||
goto multi_select_end;
|
||||
}
|
||||
sqlite3VdbeAddOp(v, OP_KeyAsData, tab2, 1);
|
||||
assert( nAddr<sizeof(aAddr)/sizeof(aAddr[0]) );
|
||||
aAddr[nAddr++] = sqlite3VdbeAddOp(v, OP_SetNumColumns, tab2, 0);
|
||||
p->pPrior = 0;
|
||||
@@ -2226,12 +2214,12 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
|
||||
sqlite3VdbeOp3(v, OP_OpenRead, iIdx, pIdx->tnum,
|
||||
(char*)&pIdx->keyInfo, P3_KEYINFO);
|
||||
if( seekOp==OP_Rewind ){
|
||||
sqlite3VdbeAddOp(v, OP_String, 0, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Null, 0, 0);
|
||||
sqlite3VdbeAddOp(v, OP_MakeRecord, 1, 0);
|
||||
seekOp = OP_MoveGt;
|
||||
}
|
||||
sqlite3VdbeAddOp(v, seekOp, iIdx, 0);
|
||||
sqlite3VdbeAddOp(v, OP_IdxRecno, iIdx, 0);
|
||||
sqlite3VdbeAddOp(v, OP_IdxRowid, iIdx, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Close, iIdx, 0);
|
||||
sqlite3VdbeAddOp(v, OP_MoveGe, base, 0);
|
||||
}
|
||||
@@ -2741,7 +2729,7 @@ int sqlite3Select(
|
||||
/* Initialize the memory cell to NULL for SRT_Mem or 0 for SRT_Exists
|
||||
*/
|
||||
if( eDest==SRT_Mem || eDest==SRT_Exists ){
|
||||
sqlite3VdbeAddOp(v, eDest==SRT_Mem ? OP_String8 : OP_Integer, 0, 0);
|
||||
sqlite3VdbeAddOp(v, eDest==SRT_Mem ? OP_Null : OP_Integer, 0, 0);
|
||||
sqlite3VdbeAddOp(v, OP_MemStore, iParm, 1);
|
||||
}
|
||||
|
||||
@@ -2749,7 +2737,7 @@ int sqlite3Select(
|
||||
*/
|
||||
if( isDistinct ){
|
||||
distinct = pParse->nTab++;
|
||||
openTempIndex(pParse, p, distinct, 0);
|
||||
openTempIndex(pParse, p, distinct);
|
||||
}else{
|
||||
distinct = -1;
|
||||
}
|
||||
|
@@ -11,7 +11,7 @@
|
||||
*************************************************************************
|
||||
** Internal interface definitions for SQLite.
|
||||
**
|
||||
** @(#) $Id: sqliteInt.h,v 1.386 2005/06/06 21:19:57 drh Exp $
|
||||
** @(#) $Id: sqliteInt.h,v 1.387 2005/06/12 21:35:52 drh Exp $
|
||||
*/
|
||||
#ifndef _SQLITEINT_H_
|
||||
#define _SQLITEINT_H_
|
||||
@@ -1141,7 +1141,7 @@ struct AuthContext {
|
||||
};
|
||||
|
||||
/*
|
||||
** Bitfield flags for P2 value in OP_PutIntKey and OP_Delete
|
||||
** Bitfield flags for P2 value in OP_Insert and OP_Delete
|
||||
*/
|
||||
#define OPFLAG_NCHANGE 1 /* Set to update db->nChange */
|
||||
#define OPFLAG_LASTROWID 2 /* Set to update db->lastRowid */
|
||||
|
@@ -215,7 +215,7 @@ void sqlite3FinishTrigger(
|
||||
*/
|
||||
if( !db->init.busy ){
|
||||
static const VdbeOpList insertTrig[] = {
|
||||
{ OP_NewRecno, 0, 0, 0 },
|
||||
{ OP_NewRowid, 0, 0, 0 },
|
||||
{ OP_String8, 0, 0, "trigger" },
|
||||
{ OP_String8, 0, 0, 0 }, /* 2: trigger name */
|
||||
{ OP_String8, 0, 0, 0 }, /* 3: table name */
|
||||
@@ -224,7 +224,7 @@ void sqlite3FinishTrigger(
|
||||
{ OP_String8, 0, 0, 0 }, /* 6: SQL */
|
||||
{ OP_Concat, 0, 0, 0 },
|
||||
{ OP_MakeRecord, 5, 0, "tttit" },
|
||||
{ OP_PutIntKey, 0, 0, 0 },
|
||||
{ OP_Insert, 0, 0, 0 },
|
||||
};
|
||||
int addr;
|
||||
Vdbe *v;
|
||||
|
48
src/update.c
48
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.107 2005/04/22 02:38:38 drh Exp $
|
||||
** $Id: update.c,v 1.108 2005/06/12 21:35:53 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@@ -80,8 +80,8 @@ void sqlite3Update(
|
||||
int *aXRef = 0; /* aXRef[i] is the index in pChanges->a[] of the
|
||||
** an expression for the i-th column of the table.
|
||||
** aXRef[i]==-1 if the i-th column is not changed. */
|
||||
int chngRecno; /* True if the record number is being changed */
|
||||
Expr *pRecnoExpr = 0; /* Expression defining the new record number */
|
||||
int chngRowid; /* True if the record number is being changed */
|
||||
Expr *pRowidExpr = 0; /* Expression defining the new record number */
|
||||
int openAll = 0; /* True if all indices need to be opened */
|
||||
AuthContext sContext; /* The authorization context */
|
||||
NameContext sNC; /* The name-context to resolve expressions in */
|
||||
@@ -160,7 +160,7 @@ void sqlite3Update(
|
||||
** column to be updated, make sure we have authorization to change
|
||||
** that column.
|
||||
*/
|
||||
chngRecno = 0;
|
||||
chngRowid = 0;
|
||||
for(i=0; i<pChanges->nExpr; i++){
|
||||
if( sqlite3ExprResolveNames(&sNC, pChanges->a[i].pExpr) ){
|
||||
goto update_cleanup;
|
||||
@@ -168,8 +168,8 @@ void sqlite3Update(
|
||||
for(j=0; j<pTab->nCol; j++){
|
||||
if( sqlite3StrICmp(pTab->aCol[j].zName, pChanges->a[i].zName)==0 ){
|
||||
if( j==pTab->iPKey ){
|
||||
chngRecno = 1;
|
||||
pRecnoExpr = pChanges->a[i].pExpr;
|
||||
chngRowid = 1;
|
||||
pRowidExpr = pChanges->a[i].pExpr;
|
||||
}
|
||||
aXRef[j] = i;
|
||||
break;
|
||||
@@ -177,8 +177,8 @@ void sqlite3Update(
|
||||
}
|
||||
if( j>=pTab->nCol ){
|
||||
if( sqlite3IsRowid(pChanges->a[i].zName) ){
|
||||
chngRecno = 1;
|
||||
pRecnoExpr = pChanges->a[i].pExpr;
|
||||
chngRowid = 1;
|
||||
pRowidExpr = pChanges->a[i].pExpr;
|
||||
}else{
|
||||
sqlite3ErrorMsg(pParse, "no such column: %s", pChanges->a[i].zName);
|
||||
goto update_cleanup;
|
||||
@@ -204,7 +204,7 @@ void sqlite3Update(
|
||||
** number of the original table entry is changing.
|
||||
*/
|
||||
for(nIdx=nIdxTotal=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdxTotal++){
|
||||
if( chngRecno ){
|
||||
if( chngRowid ){
|
||||
i = 0;
|
||||
}else {
|
||||
for(i=0; i<pIdx->nColumn; i++){
|
||||
@@ -219,7 +219,7 @@ void sqlite3Update(
|
||||
aIdxUsed = (char*)&apIdx[nIdx];
|
||||
}
|
||||
for(nIdx=j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
|
||||
if( chngRecno ){
|
||||
if( chngRowid ){
|
||||
i = 0;
|
||||
}else{
|
||||
for(i=0; i<pIdx->nColumn; i++){
|
||||
@@ -272,7 +272,7 @@ void sqlite3Update(
|
||||
|
||||
/* Remember the index of every item to be updated.
|
||||
*/
|
||||
sqlite3VdbeAddOp(v, OP_Recno, iCur, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
|
||||
sqlite3VdbeAddOp(v, OP_ListWrite, 0, 0);
|
||||
|
||||
/* End the database scan loop.
|
||||
@@ -310,20 +310,20 @@ void sqlite3Update(
|
||||
|
||||
/* Generate the OLD table
|
||||
*/
|
||||
sqlite3VdbeAddOp(v, OP_Recno, iCur, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
|
||||
sqlite3VdbeAddOp(v, OP_RowData, iCur, 0);
|
||||
sqlite3VdbeAddOp(v, OP_PutIntKey, oldIdx, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Insert, oldIdx, 0);
|
||||
|
||||
/* Generate the NEW table
|
||||
*/
|
||||
if( chngRecno ){
|
||||
sqlite3ExprCodeAndCache(pParse, pRecnoExpr);
|
||||
if( chngRowid ){
|
||||
sqlite3ExprCodeAndCache(pParse, pRowidExpr);
|
||||
}else{
|
||||
sqlite3VdbeAddOp(v, OP_Recno, iCur, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
|
||||
}
|
||||
for(i=0; i<pTab->nCol; i++){
|
||||
if( i==pTab->iPKey ){
|
||||
sqlite3VdbeAddOp(v, OP_String8, 0, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Null, 0, 0);
|
||||
continue;
|
||||
}
|
||||
j = aXRef[i];
|
||||
@@ -339,7 +339,7 @@ void sqlite3Update(
|
||||
sqlite3TableAffinityStr(v, pTab);
|
||||
}
|
||||
if( pParse->nErr ) goto update_cleanup;
|
||||
sqlite3VdbeAddOp(v, OP_PutIntKey, newIdx, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Insert, newIdx, 0);
|
||||
if( !isView ){
|
||||
sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
|
||||
}
|
||||
@@ -399,8 +399,8 @@ void sqlite3Update(
|
||||
** will be after the update. (The old record number is currently
|
||||
** on top of the stack.)
|
||||
*/
|
||||
if( chngRecno ){
|
||||
sqlite3ExprCode(pParse, pRecnoExpr);
|
||||
if( chngRowid ){
|
||||
sqlite3ExprCode(pParse, pRowidExpr);
|
||||
sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0);
|
||||
}
|
||||
|
||||
@@ -408,7 +408,7 @@ void sqlite3Update(
|
||||
*/
|
||||
for(i=0; i<pTab->nCol; i++){
|
||||
if( i==pTab->iPKey ){
|
||||
sqlite3VdbeAddOp(v, OP_String8, 0, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Null, 0, 0);
|
||||
continue;
|
||||
}
|
||||
j = aXRef[i];
|
||||
@@ -422,7 +422,7 @@ void sqlite3Update(
|
||||
|
||||
/* Do constraint checks
|
||||
*/
|
||||
sqlite3GenerateConstraintChecks(pParse, pTab, iCur, aIdxUsed, chngRecno, 1,
|
||||
sqlite3GenerateConstraintChecks(pParse, pTab, iCur, aIdxUsed, chngRowid, 1,
|
||||
onError, addr);
|
||||
|
||||
/* Delete the old indices for the current record.
|
||||
@@ -431,13 +431,13 @@ void sqlite3Update(
|
||||
|
||||
/* If changing the record number, delete the old record.
|
||||
*/
|
||||
if( chngRecno ){
|
||||
if( chngRowid ){
|
||||
sqlite3VdbeAddOp(v, OP_Delete, iCur, 0);
|
||||
}
|
||||
|
||||
/* Create the new index entries and the new record.
|
||||
*/
|
||||
sqlite3CompleteInsertion(pParse, pTab, iCur, aIdxUsed, chngRecno, 1, -1);
|
||||
sqlite3CompleteInsertion(pParse, pTab, iCur, aIdxUsed, chngRowid, 1, -1);
|
||||
}
|
||||
|
||||
/* Increment the row counter
|
||||
|
318
src/vdbe.c
318
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.468 2005/06/12 12:01:19 drh Exp $
|
||||
** $Id: vdbe.c,v 1.469 2005/06/12 21:35:53 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "os.h"
|
||||
@@ -717,7 +717,8 @@ case OP_String8: { /* same as TK_STRING */
|
||||
#ifndef SQLITE_OMIT_UTF16
|
||||
pOp->opcode = OP_String;
|
||||
|
||||
if( db->enc!=SQLITE_UTF8 && pOp->p3 ){
|
||||
assert( pOp->p3!=0 );
|
||||
if( db->enc!=SQLITE_UTF8 ){
|
||||
pTos++;
|
||||
sqlite3VdbeMemSetStr(pTos, pOp->p3, -1, SQLITE_UTF8, SQLITE_STATIC);
|
||||
if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pTos, db->enc) ) goto no_mem;
|
||||
@@ -743,26 +744,34 @@ case OP_String8: { /* same as TK_STRING */
|
||||
*/
|
||||
case OP_String: {
|
||||
pTos++;
|
||||
if( pOp->p3 ){
|
||||
pTos->flags = MEM_Str|MEM_Static|MEM_Term;
|
||||
pTos->z = pOp->p3;
|
||||
assert( pOp->p3!=0 );
|
||||
pTos->flags = MEM_Str|MEM_Static|MEM_Term;
|
||||
pTos->z = pOp->p3;
|
||||
#ifndef SQLITE_OMIT_UTF16
|
||||
if( db->enc==SQLITE_UTF8 ){
|
||||
pTos->n = strlen(pTos->z);
|
||||
}else{
|
||||
pTos->n = sqlite3utf16ByteLen(pTos->z, -1);
|
||||
}
|
||||
#else
|
||||
assert( db->enc==SQLITE_UTF8 );
|
||||
if( db->enc==SQLITE_UTF8 ){
|
||||
pTos->n = strlen(pTos->z);
|
||||
#endif
|
||||
pTos->enc = db->enc;
|
||||
}else{
|
||||
pTos->flags = MEM_Null;
|
||||
pTos->n = sqlite3utf16ByteLen(pTos->z, -1);
|
||||
}
|
||||
#else
|
||||
assert( db->enc==SQLITE_UTF8 );
|
||||
pTos->n = strlen(pTos->z);
|
||||
#endif
|
||||
pTos->enc = db->enc;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: Null * * *
|
||||
**
|
||||
** Push a NULL onto the stack.
|
||||
*/
|
||||
case OP_Null: {
|
||||
pTos++;
|
||||
pTos->flags = MEM_Null;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
#ifndef SQLITE_OMIT_BLOB_LITERAL
|
||||
/* Opcode: HexBlob * * P3
|
||||
**
|
||||
@@ -1373,11 +1382,11 @@ case OP_MustBeInt: { /* no-push */
|
||||
** Pop the top two elements from the stack. If they are equal, then
|
||||
** jump to instruction P2. Otherwise, continue to the next instruction.
|
||||
**
|
||||
** The least significant byte of P1 may be either 0x00 or 0x01. If either
|
||||
** operand is NULL (and thus if the result is unknown) then take the jump
|
||||
** only if the least significant byte of P1 is 0x01.
|
||||
** If the 0x100 bit of P1 is true and either operand is NULL then take the
|
||||
** jump. If the 0x100 bit of P1 is false then fall thru if either operand
|
||||
** is NULL.
|
||||
**
|
||||
** The second least significant byte of P1 must be an affinity character -
|
||||
** The least significant byte of P1 (mask 0xff) must be an affinity character -
|
||||
** 'n', 't', 'i' or 'o' - or 0x00. An attempt is made to coerce both values
|
||||
** according to the affinity before the comparison is made. If the byte is
|
||||
** 0x00, then numeric affinity is used.
|
||||
@@ -1446,7 +1455,7 @@ case OP_Ge: { /* same as TK_GE, no-push */
|
||||
if( flags&MEM_Null ){
|
||||
popStack(&pTos, 2);
|
||||
if( pOp->p2 ){
|
||||
if( (pOp->p1&0xFF) ) pc = pOp->p2-1;
|
||||
if( pOp->p1 & 0x100 ) pc = pOp->p2-1;
|
||||
}else{
|
||||
pTos++;
|
||||
pTos->flags = MEM_Null;
|
||||
@@ -1454,7 +1463,7 @@ case OP_Ge: { /* same as TK_GE, no-push */
|
||||
break;
|
||||
}
|
||||
|
||||
affinity = (pOp->p1>>8)&0xFF;
|
||||
affinity = pOp->p1 & 0xFF;
|
||||
if( affinity ){
|
||||
applyAffinity(pNos, affinity, db->enc);
|
||||
applyAffinity(pTos, affinity, db->enc);
|
||||
@@ -1708,10 +1717,6 @@ case OP_SetNumColumns: { /* no-push */
|
||||
assert( p->apCsr[pOp->p1]!=0 );
|
||||
pC = p->apCsr[pOp->p1];
|
||||
pC->nField = pOp->p2;
|
||||
if( (!pC->keyAsData && pC->zeroData) || (pC->keyAsData && pC->intKey) ){
|
||||
rc = SQLITE_CORRUPT;
|
||||
goto abort_due_to_error;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1795,7 +1800,7 @@ case OP_Column: {
|
||||
}else if( pC->cacheValid ){
|
||||
payloadSize = pC->payloadSize;
|
||||
zRec = pC->aRow;
|
||||
}else if( pC->keyAsData ){
|
||||
}else if( pC->isIndex ){
|
||||
i64 payloadSize64;
|
||||
sqlite3BtreeKeySize(pCrsr, &payloadSize64);
|
||||
payloadSize = payloadSize64;
|
||||
@@ -1850,7 +1855,7 @@ case OP_Column: {
|
||||
if( zRec ){
|
||||
zData = zRec;
|
||||
}else{
|
||||
if( pC->keyAsData ){
|
||||
if( pC->isIndex ){
|
||||
zData = (char*)sqlite3BtreeKeyFetch(pCrsr, &avail);
|
||||
}else{
|
||||
zData = (char*)sqlite3BtreeDataFetch(pCrsr, &avail);
|
||||
@@ -1876,7 +1881,7 @@ case OP_Column: {
|
||||
** acquire the complete header text.
|
||||
*/
|
||||
if( !zRec && avail<szHdr ){
|
||||
rc = sqlite3VdbeMemFromBtree(pCrsr, 0, szHdr, pC->keyAsData, &sMem);
|
||||
rc = sqlite3VdbeMemFromBtree(pCrsr, 0, szHdr, pC->isIndex, &sMem);
|
||||
if( rc!=SQLITE_OK ){
|
||||
goto op_column_out;
|
||||
}
|
||||
@@ -1940,7 +1945,7 @@ case OP_Column: {
|
||||
zData = &zRec[aOffset[p2]];
|
||||
}else{
|
||||
len = sqlite3VdbeSerialTypeLen(aType[p2]);
|
||||
rc = sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len,pC->keyAsData,&sMem);
|
||||
rc = sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len, pC->isIndex,&sMem);
|
||||
if( rc!=SQLITE_OK ){
|
||||
goto op_column_out;
|
||||
}
|
||||
@@ -2440,11 +2445,12 @@ case OP_OpenWrite: { /* no-push */
|
||||
rc = sqlite3BtreeCursor(pX, p2, wrFlag,
|
||||
sqlite3VdbeRecordCompare, pOp->p3,
|
||||
&pCur->pCursor);
|
||||
pCur->pKeyInfo = (KeyInfo*)pOp->p3;
|
||||
if( pCur->pKeyInfo ){
|
||||
if( pOp->p3type==P3_KEYINFO ){
|
||||
pCur->pKeyInfo = (KeyInfo*)pOp->p3;
|
||||
pCur->pIncrKey = &pCur->pKeyInfo->incrKey;
|
||||
pCur->pKeyInfo->enc = p->db->enc;
|
||||
}else{
|
||||
pCur->pKeyInfo = 0;
|
||||
pCur->pIncrKey = &pCur->bogusIncrKey;
|
||||
}
|
||||
switch( rc ){
|
||||
@@ -2456,11 +2462,32 @@ case OP_OpenWrite: { /* no-push */
|
||||
}
|
||||
case SQLITE_OK: {
|
||||
int flags = sqlite3BtreeFlags(pCur->pCursor);
|
||||
pCur->intKey = (flags & BTREE_INTKEY)!=0;
|
||||
pCur->zeroData = (flags & BTREE_ZERODATA)!=0;
|
||||
/* Sanity checking. Only the lower four bits of the flags byte should
|
||||
** be used. Bit 3 (mask 0x08) is unpreditable. The lower 3 bits
|
||||
** (mask 0x07) should be either 5 (intkey+leafdata for tables) or
|
||||
** 2 (zerodata for indices). If these conditions are not met it can
|
||||
** only mean that we are dealing with a corrupt database file
|
||||
*/
|
||||
if( (flags & 0xf0)!=0 || ((flags & 0x07)!=5 && (flags & 0x07)!=2) ){
|
||||
rc = SQLITE_CORRUPT;
|
||||
goto abort_due_to_error;
|
||||
}
|
||||
pCur->isTable = (flags & BTREE_INTKEY)!=0;
|
||||
pCur->isIndex = (flags & BTREE_ZERODATA)!=0;
|
||||
/* If P3==0 it means we are expected to open a table. If P3!=0 then
|
||||
** we expect to be opening an index. If this is not what happened,
|
||||
** then the database is corrupt
|
||||
*/
|
||||
if( (pCur->isTable && pOp->p3type==P3_KEYINFO)
|
||||
|| (pCur->isIndex && pOp->p3type!=P3_KEYINFO) ){
|
||||
rc = SQLITE_CORRUPT;
|
||||
goto abort_due_to_error;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SQLITE_EMPTY: {
|
||||
pCur->isTable = pOp->p3type!=P3_KEYINFO;
|
||||
pCur->isIndex = !pCur->isTable;
|
||||
rc = SQLITE_OK;
|
||||
break;
|
||||
}
|
||||
@@ -2518,12 +2545,14 @@ case OP_OpenTemp: { /* no-push */
|
||||
pCx->pKeyInfo->enc = p->db->enc;
|
||||
pCx->pIncrKey = &pCx->pKeyInfo->incrKey;
|
||||
}
|
||||
pCx->isTable = 0;
|
||||
}else{
|
||||
rc = sqlite3BtreeCursor(pCx->pBt, MASTER_ROOT, 1, 0, 0, &pCx->pCursor);
|
||||
pCx->intKey = 1;
|
||||
pCx->isTable = 1;
|
||||
pCx->pIncrKey = &pCx->bogusIncrKey;
|
||||
}
|
||||
}
|
||||
pCx->isIndex = !pCx->isTable;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2547,6 +2576,8 @@ case OP_OpenPseudo: { /* no-push */
|
||||
pCx->nullRow = 1;
|
||||
pCx->pseudoTable = 1;
|
||||
pCx->pIncrKey = &pCx->bogusIncrKey;
|
||||
pCx->isTable = 1;
|
||||
pCx->isIndex = 0;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
@@ -2621,7 +2652,7 @@ case OP_MoveGt: { /* no-push */
|
||||
oc = pOp->opcode;
|
||||
pC->nullRow = 0;
|
||||
*pC->pIncrKey = oc==OP_MoveGt || oc==OP_MoveLe;
|
||||
if( pC->intKey ){
|
||||
if( pC->isTable ){
|
||||
i64 iKey;
|
||||
Integerify(pTos);
|
||||
iKey = intToKey(pTos->i);
|
||||
@@ -2636,15 +2667,15 @@ case OP_MoveGt: { /* no-push */
|
||||
if( rc!=SQLITE_OK ){
|
||||
goto abort_due_to_error;
|
||||
}
|
||||
pC->lastRecno = pTos->i;
|
||||
pC->recnoIsValid = res==0;
|
||||
pC->lastRowid = pTos->i;
|
||||
pC->rowidIsValid = res==0;
|
||||
}else{
|
||||
Stringify(pTos, db->enc);
|
||||
rc = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res);
|
||||
if( rc!=SQLITE_OK ){
|
||||
goto abort_due_to_error;
|
||||
}
|
||||
pC->recnoIsValid = 0;
|
||||
pC->rowidIsValid = 0;
|
||||
}
|
||||
pC->deferredMoveto = 0;
|
||||
pC->cacheValid = 0;
|
||||
@@ -2654,7 +2685,7 @@ case OP_MoveGt: { /* no-push */
|
||||
if( res<0 ){
|
||||
rc = sqlite3BtreeNext(pC->pCursor, &res);
|
||||
if( rc!=SQLITE_OK ) goto abort_due_to_error;
|
||||
pC->recnoIsValid = 0;
|
||||
pC->rowidIsValid = 0;
|
||||
}else{
|
||||
res = 0;
|
||||
}
|
||||
@@ -2663,7 +2694,7 @@ case OP_MoveGt: { /* no-push */
|
||||
if( res>=0 ){
|
||||
rc = sqlite3BtreePrevious(pC->pCursor, &res);
|
||||
if( rc!=SQLITE_OK ) goto abort_due_to_error;
|
||||
pC->recnoIsValid = 0;
|
||||
pC->rowidIsValid = 0;
|
||||
}else{
|
||||
/* res might be negative because the table is empty. Check to
|
||||
** see if this is the case.
|
||||
@@ -2686,31 +2717,46 @@ case OP_MoveGt: { /* no-push */
|
||||
|
||||
/* Opcode: Distinct P1 P2 *
|
||||
**
|
||||
** Use the top of the stack as a string key. If a record with that key does
|
||||
** not exist in the table of cursor P1, then jump to P2. If the record
|
||||
** does already exist, then fall thru. The cursor is left pointing
|
||||
** at the record if it exists. The key is not popped from the stack.
|
||||
** Use the top of the stack as a record created using MakeRecord. P1 is a
|
||||
** cursor on a table that declared as an index. If that table contains an
|
||||
** entry that matches the top of the stack fall thru. If the top of the stack
|
||||
** matches no entry in P1 then jump to P2.
|
||||
**
|
||||
** This operation is similar to NotFound except that this operation
|
||||
** The cursor is left pointing at the matching entry if it exists. The
|
||||
** record on the top of the stack is not popped.
|
||||
**
|
||||
** This instruction is similar to NotFound except that this operation
|
||||
** does not pop the key from the stack.
|
||||
**
|
||||
** The instruction is used to implement the DISTINCT operator on SELECT
|
||||
** statements. The P1 table is not a true index but rather a record of
|
||||
** all results that have produced so far.
|
||||
**
|
||||
** See also: Found, NotFound, MoveTo, IsUnique, NotExists
|
||||
*/
|
||||
/* Opcode: Found P1 P2 *
|
||||
**
|
||||
** Use the top of the stack as a string key. If a record with that key
|
||||
** does exist in table of P1, then jump to P2. If the record
|
||||
** does not exist, then fall thru. The cursor is left pointing
|
||||
** to the record if it exists. The key is popped from the stack.
|
||||
** Top of the stack holds a blob constructed by MakeRecord. P1 is an index.
|
||||
** If an entry that matches the top of the stack exists in P1 then
|
||||
** jump to P2. If the top of the stack does not match any entry in P1
|
||||
** then fall thru. The P1 cursor is left pointing at the matching entry
|
||||
** if it exists. The blob is popped off the top of the stack.
|
||||
**
|
||||
** This instruction is used to implement the IN operator where the
|
||||
** left-hand side is a SELECT statement. P1 is not a true index but
|
||||
** is instead a temporary index that holds the results of the SELECT
|
||||
** statement. This instruction just checks to see if the left-hand side
|
||||
** of the IN operator (stored on the top of the stack) exists in the
|
||||
** result of the SELECT statement.
|
||||
**
|
||||
** See also: Distinct, NotFound, MoveTo, IsUnique, NotExists
|
||||
*/
|
||||
/* Opcode: NotFound P1 P2 *
|
||||
**
|
||||
** Use the top of the stack as a string key. If a record with that key
|
||||
** does not exist in table of P1, then jump to P2. If the record
|
||||
** does exist, then fall thru. The cursor is left pointing to the
|
||||
** record if it exists. The key is popped from the stack.
|
||||
** The top of the stack holds a blob constructed by MakeRecord. P1 is
|
||||
** an index. If no entry exists in P1 that matches the blob then jump
|
||||
** to P1. If an entry does existing, fall through. The cursor is left
|
||||
** pointing to the entry that matches. The blob is popped from the stack.
|
||||
**
|
||||
** The difference between this operation and Distinct is that
|
||||
** Distinct does not pop the key from the stack.
|
||||
@@ -2728,7 +2774,7 @@ case OP_Found: { /* no-push */
|
||||
assert( p->apCsr[i]!=0 );
|
||||
if( (pC = p->apCsr[i])->pCursor!=0 ){
|
||||
int res, rx;
|
||||
assert( pC->intKey==0 );
|
||||
assert( pC->isTable==0 );
|
||||
Stringify(pTos, db->enc);
|
||||
rx = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res);
|
||||
alreadyExists = rx==SQLITE_OK && res==0;
|
||||
@@ -2755,8 +2801,8 @@ case OP_Found: { /* no-push */
|
||||
** stack but it leaves K unchanged.
|
||||
**
|
||||
** P1 is an index. So it has no data and its key consists of a
|
||||
** record generated by OP_MakeIdxKey. This key contains one or more
|
||||
** fields followed by a ROWID field.
|
||||
** record generated by OP_MakeRecord where the last field is the
|
||||
** rowid of the entry that the index refers to.
|
||||
**
|
||||
** This instruction asks if there is an entry in P1 where the
|
||||
** fields matches K but the rowid is different from R.
|
||||
@@ -2857,8 +2903,9 @@ case OP_IsUnique: { /* no-push */
|
||||
** record if it exists. The integer key is popped from the stack.
|
||||
**
|
||||
** The difference between this operation and NotFound is that this
|
||||
** operation assumes the key is an integer and NotFound assumes it
|
||||
** is a string.
|
||||
** operation assumes the key is an integer and that P1 is a table whereas
|
||||
** NotFound assumes key is a blob constructed from MakeRecord and
|
||||
** P1 is an index.
|
||||
**
|
||||
** See also: Distinct, Found, MoveTo, NotFound, IsUnique
|
||||
*/
|
||||
@@ -2873,16 +2920,16 @@ case OP_NotExists: { /* no-push */
|
||||
int res;
|
||||
u64 iKey;
|
||||
assert( pTos->flags & MEM_Int );
|
||||
assert( p->apCsr[i]->intKey );
|
||||
assert( p->apCsr[i]->isTable );
|
||||
iKey = intToKey(pTos->i);
|
||||
rc = sqlite3BtreeMoveto(pCrsr, 0, iKey, &res);
|
||||
pC->lastRecno = pTos->i;
|
||||
pC->recnoIsValid = res==0;
|
||||
pC->lastRowid = pTos->i;
|
||||
pC->rowidIsValid = res==0;
|
||||
pC->nullRow = 0;
|
||||
pC->cacheValid = 0;
|
||||
if( res!=0 ){
|
||||
pc = pOp->p2 - 1;
|
||||
pC->recnoIsValid = 0;
|
||||
pC->rowidIsValid = 0;
|
||||
}
|
||||
}
|
||||
Release(pTos);
|
||||
@@ -2890,9 +2937,9 @@ case OP_NotExists: { /* no-push */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: NewRecno P1 P2 *
|
||||
/* Opcode: NewRowid P1 P2 *
|
||||
**
|
||||
** Get a new integer record number used as the key to a table.
|
||||
** Get a new integer record number (a.k.a "rowid") used as the key to a table.
|
||||
** The record number is not previously used as a key in the database
|
||||
** table that cursor P1 points to. The new record number is pushed
|
||||
** onto the stack.
|
||||
@@ -2904,7 +2951,7 @@ case OP_NotExists: { /* no-push */
|
||||
** record number. This P2 mechanism is used to help implement the
|
||||
** AUTOINCREMENT feature.
|
||||
*/
|
||||
case OP_NewRecno: {
|
||||
case OP_NewRowid: {
|
||||
int i = pOp->p1;
|
||||
i64 v = 0;
|
||||
Cursor *pC;
|
||||
@@ -3032,7 +3079,7 @@ case OP_NewRecno: {
|
||||
goto abort_due_to_error;
|
||||
}
|
||||
}
|
||||
pC->recnoIsValid = 0;
|
||||
pC->rowidIsValid = 0;
|
||||
pC->deferredMoveto = 0;
|
||||
pC->cacheValid = 0;
|
||||
}
|
||||
@@ -3042,7 +3089,7 @@ case OP_NewRecno: {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: PutIntKey P1 P2 *
|
||||
/* Opcode: Insert P1 P2 *
|
||||
**
|
||||
** Write an entry into the table of cursor P1. A new entry is
|
||||
** created if it doesn't already exist or the data for an existing
|
||||
@@ -3054,19 +3101,11 @@ case OP_NewRecno: {
|
||||
** incremented (otherwise not). If the OPFLAG_LASTROWID flag of P2 is set,
|
||||
** then rowid is stored for subsequent return by the
|
||||
** sqlite3_last_insert_rowid() function (otherwise it's unmodified).
|
||||
*/
|
||||
/* Opcode: PutStrKey P1 * *
|
||||
**
|
||||
** Write an entry into the table of cursor P1. A new entry is
|
||||
** created if it doesn't already exist or the data for an existing
|
||||
** entry is overwritten. The data is the value on the top of the
|
||||
** stack. The key is the next value down on the stack. The key must
|
||||
** be a string. The stack is popped twice by this instruction.
|
||||
**
|
||||
** P1 may not be a pseudo-table opened using the OpenPseudo opcode.
|
||||
** This instruction only works on tables. The equivalent instruction
|
||||
** for indices is OP_IdxInsert.
|
||||
*/
|
||||
case OP_PutIntKey: /* no-push */
|
||||
case OP_PutStrKey: { /* no-push */
|
||||
case OP_Insert: { /* no-push */
|
||||
Mem *pNos = &pTos[-1];
|
||||
int i = pOp->p1;
|
||||
Cursor *pC;
|
||||
@@ -3074,36 +3113,16 @@ case OP_PutStrKey: { /* no-push */
|
||||
assert( i>=0 && i<p->nCursor );
|
||||
assert( p->apCsr[i]!=0 );
|
||||
if( ((pC = p->apCsr[i])->pCursor!=0 || pC->pseudoTable) ){
|
||||
char *zKey;
|
||||
i64 nKey;
|
||||
i64 iKey;
|
||||
if( pOp->opcode==OP_PutStrKey ){
|
||||
assert( pNos->flags & MEM_Blob );
|
||||
Stringify(pNos, db->enc);
|
||||
nKey = pNos->n;
|
||||
zKey = pNos->z;
|
||||
}else{
|
||||
assert( pNos->flags & MEM_Int );
|
||||
i64 iKey; /* The integer ROWID or key for the record to be inserted */
|
||||
|
||||
/* If the table is an INTKEY table, set nKey to the value of
|
||||
** the integer key, and zKey to NULL. Otherwise, set nKey to
|
||||
** sizeof(i64) and point zKey at iKey. iKey contains the integer
|
||||
** key in the on-disk byte order.
|
||||
*/
|
||||
iKey = intToKey(pNos->i);
|
||||
if( pC->intKey ){
|
||||
nKey = intToKey(pNos->i);
|
||||
zKey = 0;
|
||||
}else{
|
||||
nKey = sizeof(i64);
|
||||
zKey = (char*)&iKey;
|
||||
}
|
||||
assert( pNos->flags & MEM_Int );
|
||||
assert( pC->isTable );
|
||||
iKey = intToKey(pNos->i);
|
||||
|
||||
if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++;
|
||||
if( pOp->p2 & OPFLAG_LASTROWID ) db->lastRowid = pNos->i;
|
||||
if( pC->nextRowidValid && pTos->i>=pC->nextRowid ){
|
||||
pC->nextRowidValid = 0;
|
||||
}
|
||||
if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++;
|
||||
if( pOp->p2 & OPFLAG_LASTROWID ) db->lastRowid = pNos->i;
|
||||
if( pC->nextRowidValid && pTos->i>=pC->nextRowid ){
|
||||
pC->nextRowidValid = 0;
|
||||
}
|
||||
if( pTos->flags & MEM_Null ){
|
||||
pTos->z = 0;
|
||||
@@ -3113,11 +3132,6 @@ assert( pNos->flags & MEM_Blob );
|
||||
}
|
||||
#ifndef SQLITE_OMIT_TRIGGER
|
||||
if( pC->pseudoTable ){
|
||||
/* PutStrKey does not work for pseudo-tables.
|
||||
** The following assert makes sure we are not trying to use
|
||||
** PutStrKey on a pseudo-table
|
||||
*/
|
||||
assert( pOp->opcode==OP_PutIntKey );
|
||||
sqliteFree(pC->pData);
|
||||
pC->iKey = iKey;
|
||||
pC->nData = pTos->n;
|
||||
@@ -3134,12 +3148,12 @@ assert( pNos->flags & MEM_Blob );
|
||||
pC->nullRow = 0;
|
||||
}else{
|
||||
#endif
|
||||
rc = sqlite3BtreeInsert(pC->pCursor, zKey, nKey, pTos->z, pTos->n);
|
||||
rc = sqlite3BtreeInsert(pC->pCursor, 0, iKey, pTos->z, pTos->n);
|
||||
#ifndef SQLITE_OMIT_TRIGGER
|
||||
}
|
||||
#endif
|
||||
|
||||
pC->recnoIsValid = 0;
|
||||
pC->rowidIsValid = 0;
|
||||
pC->deferredMoveto = 0;
|
||||
pC->cacheValid = 0;
|
||||
}
|
||||
@@ -3193,23 +3207,6 @@ case OP_ResetCount: { /* no-push */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: KeyAsData P1 P2 *
|
||||
**
|
||||
** Turn the key-as-data mode for cursor P1 either on (if P2==1) or
|
||||
** off (if P2==0). In key-as-data mode, the OP_Column opcode pulls
|
||||
** data off of the key rather than the data. This is used for
|
||||
** processing compound selects.
|
||||
*/
|
||||
case OP_KeyAsData: { /* no-push */
|
||||
int i = pOp->p1;
|
||||
Cursor *pC;
|
||||
assert( i>=0 && i<p->nCursor );
|
||||
pC = p->apCsr[i];
|
||||
assert( pC!=0 );
|
||||
pC->keyAsData = pOp->p2;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: RowData P1 * *
|
||||
**
|
||||
** Push onto the stack the complete row data for cursor P1.
|
||||
@@ -3234,9 +3231,12 @@ case OP_RowData: {
|
||||
Cursor *pC;
|
||||
u32 n;
|
||||
|
||||
/* Note that RowKey and RowData are really exactly the same instruction */
|
||||
pTos++;
|
||||
assert( i>=0 && i<p->nCursor );
|
||||
pC = p->apCsr[i];
|
||||
assert( pC->isTable || pOp->opcode==OP_RowKey );
|
||||
assert( pC->isIndex || pOp->opcode==OP_RowData );
|
||||
assert( pC!=0 );
|
||||
if( pC->nullRow ){
|
||||
pTos->flags = MEM_Null;
|
||||
@@ -3247,13 +3247,12 @@ case OP_RowData: {
|
||||
if( pC->nullRow ){
|
||||
pTos->flags = MEM_Null;
|
||||
break;
|
||||
}else if( pC->keyAsData || pOp->opcode==OP_RowKey ){
|
||||
}else if( pC->isIndex ){
|
||||
i64 n64;
|
||||
assert( !pC->intKey );
|
||||
assert( !pC->isTable );
|
||||
sqlite3BtreeKeySize(pCrsr, &n64);
|
||||
n = n64;
|
||||
}else{
|
||||
assert( pC->intKey );
|
||||
sqlite3BtreeDataSize(pCrsr, &n);
|
||||
}
|
||||
pTos->n = n;
|
||||
@@ -3267,11 +3266,9 @@ assert( pC->intKey );
|
||||
pTos->xDel = 0;
|
||||
pTos->z = z;
|
||||
}
|
||||
if( pC->keyAsData || pOp->opcode==OP_RowKey ){
|
||||
assert( !pC->intKey );
|
||||
if( pC->isIndex ){
|
||||
sqlite3BtreeKey(pCrsr, 0, n, pTos->z);
|
||||
}else{
|
||||
assert( pC->intKey );
|
||||
sqlite3BtreeData(pCrsr, 0, n, pTos->z);
|
||||
}
|
||||
#ifndef SQLITE_OMIT_TRIGGER
|
||||
@@ -3286,14 +3283,12 @@ assert( pC->intKey );
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: Recno P1 * *
|
||||
/* Opcode: Rowid P1 * *
|
||||
**
|
||||
** Push onto the stack an integer which is the first 4 bytes of the
|
||||
** the key to the current entry in a sequential scan of the database
|
||||
** file P1. The sequential scan should have been started using the
|
||||
** Next opcode.
|
||||
** Push onto the stack an integer which is the key of the table entry that
|
||||
** P1 is currently point to.
|
||||
*/
|
||||
case OP_Recno: {
|
||||
case OP_Rowid: {
|
||||
int i = pOp->p1;
|
||||
Cursor *pC;
|
||||
i64 v;
|
||||
@@ -3304,8 +3299,8 @@ case OP_Recno: {
|
||||
rc = sqlite3VdbeCursorMoveto(pC);
|
||||
if( rc ) goto abort_due_to_error;
|
||||
pTos++;
|
||||
if( pC->recnoIsValid ){
|
||||
v = pC->lastRecno;
|
||||
if( pC->rowidIsValid ){
|
||||
v = pC->lastRowid;
|
||||
}else if( pC->pseudoTable ){
|
||||
v = keyToInt(pC->iKey);
|
||||
}else if( pC->nullRow || pC->pCursor==0 ){
|
||||
@@ -3335,13 +3330,13 @@ case OP_NullRow: { /* no-push */
|
||||
pC = p->apCsr[i];
|
||||
assert( pC!=0 );
|
||||
pC->nullRow = 1;
|
||||
pC->recnoIsValid = 0;
|
||||
pC->rowidIsValid = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: Last P1 P2 *
|
||||
**
|
||||
** The next use of the Recno or Column or Next instruction for P1
|
||||
** The next use of the Rowid or Column or Next instruction for P1
|
||||
** will refer to the last entry in the database table or index.
|
||||
** If the table or index is empty and P2>0, then jump immediately to P2.
|
||||
** If P2 is 0 or if the table or index is not empty, fall through
|
||||
@@ -3372,7 +3367,7 @@ case OP_Last: { /* no-push */
|
||||
|
||||
/* Opcode: Rewind P1 P2 *
|
||||
**
|
||||
** The next use of the Recno or Column or Next instruction for P1
|
||||
** The next use of the Rowid or Column or Next instruction for P1
|
||||
** will refer to the first entry in the database table or index.
|
||||
** If the table or index is empty and P2>0, then jump immediately to P2.
|
||||
** If P2 is 0 or if the table or index is not empty, fall through
|
||||
@@ -3445,11 +3440,11 @@ case OP_Next: { /* no-push */
|
||||
}else{
|
||||
pC->nullRow = 1;
|
||||
}
|
||||
pC->recnoIsValid = 0;
|
||||
pC->rowidIsValid = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: IdxPut P1 P2 P3
|
||||
/* Opcode: IdxInsert P1 P2 P3
|
||||
**
|
||||
** The top of the stack holds a SQL index key made using the
|
||||
** MakeIdxKey instruction. This opcode writes that key into the
|
||||
@@ -3459,8 +3454,11 @@ case OP_Next: { /* no-push */
|
||||
** the program aborts with a SQLITE_CONSTRAINT error and the database
|
||||
** is rolled back. If P3 is not null, then it becomes part of the
|
||||
** error message returned with the SQLITE_CONSTRAINT.
|
||||
**
|
||||
** This instruction only works for indices. The equivalent instruction
|
||||
** for tables is OP_Insert.
|
||||
*/
|
||||
case OP_IdxPut: { /* no-push */
|
||||
case OP_IdxInsert: { /* no-push */
|
||||
int i = pOp->p1;
|
||||
Cursor *pC;
|
||||
BtCursor *pCrsr;
|
||||
@@ -3497,7 +3495,7 @@ case OP_IdxPut: { /* no-push */
|
||||
}
|
||||
}
|
||||
}
|
||||
assert( pC->intKey==0 );
|
||||
assert( pC->isTable==0 );
|
||||
rc = sqlite3BtreeInsert(pCrsr, zKey, nKey, "", 0);
|
||||
assert( pC->deferredMoveto==0 );
|
||||
pC->cacheValid = 0;
|
||||
@@ -3534,15 +3532,15 @@ case OP_IdxDelete: { /* no-push */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: IdxRecno P1 * *
|
||||
/* Opcode: IdxRowid P1 * *
|
||||
**
|
||||
** Push onto the stack an integer which is the varint located at the
|
||||
** end of the index key pointed to by cursor P1. This integer should be
|
||||
** the record number of the table entry to which this index entry points.
|
||||
** Push onto the stack an integer which is the last entry in the record at
|
||||
** the end of the index key pointed to by cursor P1. This integer should be
|
||||
** the rowid of the table entry to which this index entry points.
|
||||
**
|
||||
** See also: Recno, MakeIdxKey.
|
||||
** See also: Rowid, MakeIdxKey.
|
||||
*/
|
||||
case OP_IdxRecno: {
|
||||
case OP_IdxRowid: {
|
||||
int i = pOp->p1;
|
||||
BtCursor *pCrsr;
|
||||
Cursor *pC;
|
||||
@@ -3555,7 +3553,7 @@ case OP_IdxRecno: {
|
||||
i64 rowid;
|
||||
|
||||
assert( pC->deferredMoveto==0 );
|
||||
assert( pC->intKey==0 );
|
||||
assert( pC->isTable==0 );
|
||||
if( pC->nullRow ){
|
||||
pTos->flags = MEM_Null;
|
||||
}else{
|
||||
@@ -4060,13 +4058,13 @@ case OP_ContextPop: { /* no-push */
|
||||
}
|
||||
#endif /* #ifndef SQLITE_OMIT_TRIGGER */
|
||||
|
||||
/* Opcode: SortPut * * *
|
||||
/* Opcode: SortInsert * * *
|
||||
**
|
||||
** The TOS is the key and the NOS is the data. Pop both from the stack
|
||||
** and put them on the sorter. The key and data should have been
|
||||
** made using the MakeRecord opcode.
|
||||
*/
|
||||
case OP_SortPut: { /* no-push */
|
||||
case OP_SortInsert: { /* no-push */
|
||||
Mem *pNos = &pTos[-1];
|
||||
Sorter *pSorter;
|
||||
assert( pNos>=p->aStack );
|
||||
|
@@ -60,19 +60,18 @@ typedef unsigned char Bool;
|
||||
*/
|
||||
struct Cursor {
|
||||
BtCursor *pCursor; /* The cursor structure of the backend */
|
||||
i64 lastRecno; /* Last recno from a Next or NextIdx operation */
|
||||
i64 lastRowid; /* Last rowid from a Next or NextIdx operation */
|
||||
i64 nextRowid; /* Next rowid returned by OP_NewRowid */
|
||||
Bool zeroed; /* True if zeroed out and ready for reuse */
|
||||
Bool recnoIsValid; /* True if lastRecno is valid */
|
||||
Bool keyAsData; /* The OP_Column command works on key instead of data */
|
||||
Bool rowidIsValid; /* True if lastRowid is valid */
|
||||
Bool atFirst; /* True if pointing to first entry */
|
||||
Bool useRandomRowid; /* Generate new record numbers semi-randomly */
|
||||
Bool nullRow; /* True if pointing to a row with no data */
|
||||
Bool nextRowidValid; /* True if the nextRowid field is valid */
|
||||
Bool pseudoTable; /* This is a NEW or OLD pseudo-tables of a trigger */
|
||||
Bool deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */
|
||||
Bool intKey; /* True if the table requires integer keys */
|
||||
Bool zeroData; /* True if table contains keys only - no data */
|
||||
Bool isTable; /* True if a table requiring integer keys */
|
||||
Bool isIndex; /* True if an index containing keys only - no data */
|
||||
u8 bogusIncrKey; /* Something for pIncrKey to point to if pKeyInfo==0 */
|
||||
i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */
|
||||
Btree *pBt; /* Separate file holding temporary table */
|
||||
|
@@ -223,7 +223,7 @@ int sqlite3VdbeOpcodeNoPush(u8 op){
|
||||
**
|
||||
** This routine also does the following optimization: It scans for
|
||||
** Halt instructions where P1==SQLITE_CONSTRAINT or P2==OE_Abort or for
|
||||
** IdxPut instructions where P2!=0. If no such instruction is
|
||||
** IdxInsert instructions where P2!=0. If no such instruction is
|
||||
** found, then every Statement instruction is changed to a Noop. In
|
||||
** this way, we avoid creating the statement journal file unnecessarily.
|
||||
*/
|
||||
@@ -249,7 +249,7 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs, int *pMaxStack){
|
||||
if( pOp->p1==SQLITE_CONSTRAINT && pOp->p2==OE_Abort ){
|
||||
doesStatementRollback = 1;
|
||||
}
|
||||
}else if( opcode==OP_IdxPut ){
|
||||
}else if( opcode==OP_IdxInsert ){
|
||||
if( pOp->p2 ){
|
||||
doesStatementRollback = 1;
|
||||
}
|
||||
@@ -1572,8 +1572,8 @@ int sqlite3VdbeCursorMoveto(Cursor *p){
|
||||
if( p->deferredMoveto ){
|
||||
int res, rc;
|
||||
extern int sqlite3_search_count;
|
||||
assert( p->intKey );
|
||||
if( p->intKey ){
|
||||
assert( p->isTable );
|
||||
if( p->isTable ){
|
||||
rc = sqlite3BtreeMoveto(p->pCursor, 0, p->movetoTarget, &res);
|
||||
}else{
|
||||
rc = sqlite3BtreeMoveto(p->pCursor,(char*)&p->movetoTarget,
|
||||
@@ -1581,8 +1581,8 @@ int sqlite3VdbeCursorMoveto(Cursor *p){
|
||||
}
|
||||
if( rc ) return rc;
|
||||
*p->pIncrKey = 0;
|
||||
p->lastRecno = keyToInt(p->movetoTarget);
|
||||
p->recnoIsValid = res==0;
|
||||
p->lastRowid = keyToInt(p->movetoTarget);
|
||||
p->rowidIsValid = res==0;
|
||||
if( res<0 ){
|
||||
rc = sqlite3BtreeNext(p->pCursor, &res);
|
||||
if( rc ) return rc;
|
||||
|
20
src/where.c
20
src/where.c
@@ -16,7 +16,7 @@
|
||||
** so is applicable. Because this module is responsible for selecting
|
||||
** indices, you might also think of this module as the "query optimizer".
|
||||
**
|
||||
** $Id: where.c,v 1.138 2005/05/19 01:26:14 drh Exp $
|
||||
** $Id: where.c,v 1.139 2005/06/12 21:35:53 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@@ -497,7 +497,6 @@ static void codeEqualityTerm(
|
||||
sqlite3CodeSubselect(pParse, pX);
|
||||
iTab = pX->iTable;
|
||||
sqlite3VdbeAddOp(v, OP_Rewind, iTab, brk);
|
||||
sqlite3VdbeAddOp(v, OP_KeyAsData, iTab, 1);
|
||||
VdbeComment((v, "# %.*s", pX->span.n, pX->span.z));
|
||||
pLevel->inP2 = sqlite3VdbeAddOp(v, OP_Column, iTab, 0);
|
||||
pLevel->inOp = OP_Next;
|
||||
@@ -546,7 +545,7 @@ static void codeEqualityTerm(
|
||||
**
|
||||
** The code that sqlite3WhereBegin() generates leaves the cursors named
|
||||
** in pTabList pointing at their appropriate entries. The [...] code
|
||||
** can use OP_Column and OP_Recno opcodes on these cursors to extract
|
||||
** can use OP_Column and OP_Rowid opcodes on these cursors to extract
|
||||
** data from the various tables of the loop.
|
||||
**
|
||||
** If the WHERE clause is empty, the foreach loops must each scan their
|
||||
@@ -949,7 +948,6 @@ WhereInfo *sqlite3WhereBegin(
|
||||
(char*)&pIx->keyInfo, P3_KEYINFO);
|
||||
}
|
||||
if( (pLevel->score & 1)!=0 ){
|
||||
sqlite3VdbeAddOp(v, OP_KeyAsData, iIdxCur, 1);
|
||||
sqlite3VdbeAddOp(v, OP_SetNumColumns, iIdxCur, pIx->nColumn+1);
|
||||
}
|
||||
sqlite3CodeVerifySchema(pParse, pTab->iDb);
|
||||
@@ -984,7 +982,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
if( i>0 && (pTabList->a[i-1].jointype & JT_LEFT)!=0 ){
|
||||
if( !pParse->nMem ) pParse->nMem++;
|
||||
pLevel->iLeftJoin = pParse->nMem++;
|
||||
sqlite3VdbeAddOp(v, OP_String8, 0, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Null, 0, 0);
|
||||
sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iLeftJoin, 1);
|
||||
VdbeComment((v, "# init LEFT JOIN no-match flag"));
|
||||
}
|
||||
@@ -1061,7 +1059,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
sqlite3VdbeAddOp(v, OP_RowKey, iIdxCur, 0);
|
||||
sqlite3VdbeAddOp(v, OP_IdxIsNull, nColumn, cont);
|
||||
if( !omitTable ){
|
||||
sqlite3VdbeAddOp(v, OP_IdxRecno, iIdxCur, 0);
|
||||
sqlite3VdbeAddOp(v, OP_IdxRowid, iIdxCur, 0);
|
||||
sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0);
|
||||
}
|
||||
pLevel->p1 = iIdxCur;
|
||||
@@ -1120,9 +1118,9 @@ WhereInfo *sqlite3WhereBegin(
|
||||
pLevel->p1 = iCur;
|
||||
pLevel->p2 = start;
|
||||
if( testOp!=OP_Noop ){
|
||||
sqlite3VdbeAddOp(v, OP_Recno, iCur, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
|
||||
sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);
|
||||
sqlite3VdbeAddOp(v, testOp, (int)(('n'<<8)&0x0000FF00), brk);
|
||||
sqlite3VdbeAddOp(v, testOp, 'n', brk);
|
||||
}
|
||||
}else if( pIdx==0 ){
|
||||
/* Case 4: There is no usable index. We must do a complete
|
||||
@@ -1295,7 +1293,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
sqlite3VdbeAddOp(v, OP_RowKey, iIdxCur, 0);
|
||||
sqlite3VdbeAddOp(v, OP_IdxIsNull, nEqColumn + ((score&4)!=0), cont);
|
||||
if( !omitTable ){
|
||||
sqlite3VdbeAddOp(v, OP_IdxRecno, iIdxCur, 0);
|
||||
sqlite3VdbeAddOp(v, OP_IdxRowid, iIdxCur, 0);
|
||||
sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0);
|
||||
}
|
||||
|
||||
@@ -1424,9 +1422,9 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
|
||||
break;
|
||||
}
|
||||
}
|
||||
}else if( pOp->opcode==OP_Recno ){
|
||||
}else if( pOp->opcode==OP_Rowid ){
|
||||
pOp->p1 = pLevel->iIdxCur;
|
||||
pOp->opcode = OP_IdxRecno;
|
||||
pOp->opcode = OP_IdxRowid;
|
||||
}else if( pOp->opcode==OP_NullRow ){
|
||||
pOp->opcode = OP_Noop;
|
||||
}
|
||||
|
Reference in New Issue
Block a user