Registerify the AUTOINCREMENT processing and the OP_IsNull and OP_NotNull
operators. (CVS 4692)
FossilOrigin-Name: aa48867cfa04da265b906e5b583bc7ac6b6a1157
diff --git a/src/expr.c b/src/expr.c
index 41d4fcc..d332e4f 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.335 2008/01/06 00:25:22 drh Exp $
+** $Id: expr.c,v 1.336 2008/01/07 19:20:25 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@@ -2134,14 +2134,14 @@
}
case TK_ISNULL:
case TK_NOTNULL: {
- int dest;
+ int addr;
assert( TK_ISNULL==OP_IsNull );
assert( TK_NOTNULL==OP_NotNull );
sqlite3VdbeAddOp2(v, OP_Integer, 1, target);
sqlite3ExprCode(pParse, pExpr->pLeft, 0);
- dest = sqlite3VdbeCurrentAddr(v) + 2;
- sqlite3VdbeAddOp2(v, op, 1, dest);
+ addr = sqlite3VdbeAddOp0(v, op);
sqlite3VdbeAddOp2(v, OP_AddImm, target, -1);
+ sqlite3VdbeJumpHere(v, addr);
stackChng = 0;
inReg = target;
break;
@@ -2222,11 +2222,10 @@
break;
}
case TK_IN: {
- int addr;
+ int j1, j2, j3, j4, j5;
char affinity;
int ckOffset = pParse->ckOffset;
int eType;
- int iLabel = sqlite3VdbeMakeLabel(v);
eType = sqlite3FindInIndex(pParse, pExpr, 0);
@@ -2243,24 +2242,25 @@
** pExpr->iTable contains the values that make up the (...) set.
*/
sqlite3ExprCode(pParse, pExpr->pLeft, 0);
- addr = sqlite3VdbeCurrentAddr(v);
- sqlite3VdbeAddOp2(v, OP_NotNull, -1, addr+4); /* addr + 0 */
+ sqlite3VdbeAddOp0(v, OP_SCopy);
+ j1 = sqlite3VdbeAddOp0(v, OP_NotNull);
sqlite3VdbeAddOp1(v, OP_Pop, 2);
sqlite3VdbeAddOp0(v, OP_Null);
- sqlite3VdbeAddOp2(v, OP_Goto, 0, iLabel);
+ j2 = sqlite3VdbeAddOp0(v, OP_Goto);
+ sqlite3VdbeJumpHere(v, j1);
if( eType==IN_INDEX_ROWID ){
- int iAddr = sqlite3VdbeCurrentAddr(v)+3;
- sqlite3VdbeAddOp2(v, OP_MustBeInt, 1, iAddr);
- sqlite3VdbeAddOp2(v, OP_NotExists, pExpr->iTable, iAddr);
- sqlite3VdbeAddOp2(v, OP_Goto, pExpr->iTable, iLabel);
+ j3 = sqlite3VdbeAddOp1(v, OP_MustBeInt, 1);
+ j4 = sqlite3VdbeAddOp1(v, OP_NotExists, pExpr->iTable);
+ j5 = sqlite3VdbeAddOp0(v, OP_Goto);
+ sqlite3VdbeJumpHere(v, j3);
+ sqlite3VdbeJumpHere(v, j4);
}else{
- sqlite3VdbeAddOp4(v, OP_MakeRecord, 1, 0, 0,
- &affinity, 1); /* addr + 4 */
- sqlite3VdbeAddOp2(v, OP_Found, pExpr->iTable, iLabel);
+ sqlite3VdbeAddOp4(v, OP_MakeRecord, 1, 0, 0, &affinity, 1);
+ j5 = sqlite3VdbeAddOp1(v, OP_Found, pExpr->iTable);
}
- sqlite3VdbeAddOp2(v, OP_AddImm, 0, -1); /* addr + 6 */
- sqlite3VdbeResolveLabel(v, iLabel);
-
+ sqlite3VdbeAddOp2(v, OP_AddImm, 0, -1);
+ sqlite3VdbeJumpHere(v, j2);
+ sqlite3VdbeJumpHere(v, j5);
break;
}
#endif
@@ -2485,7 +2485,7 @@
assert( TK_ISNULL==OP_IsNull );
assert( TK_NOTNULL==OP_NotNull );
sqlite3ExprCode(pParse, pExpr->pLeft, 0);
- sqlite3VdbeAddOp2(v, op, 1, dest);
+ sqlite3VdbeAddOp2(v, op, 0, dest);
break;
}
case TK_BETWEEN: {
@@ -2597,7 +2597,7 @@
case TK_ISNULL:
case TK_NOTNULL: {
sqlite3ExprCode(pParse, pExpr->pLeft, 0);
- sqlite3VdbeAddOp2(v, op, 1, dest);
+ sqlite3VdbeAddOp2(v, op, 0, dest);
break;
}
case TK_BETWEEN: {
diff --git a/src/insert.c b/src/insert.c
index c0ef2ae..c4fe107 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.214 2008/01/06 00:25:22 drh Exp $
+** $Id: insert.c,v 1.215 2008/01/07 19:20:25 drh Exp $
*/
#include "sqliteInt.h"
@@ -138,44 +138,46 @@
/*
** Write out code to initialize the autoincrement logic. This code
** looks up the current autoincrement value in the sqlite_sequence
-** table and stores that value in a memory cell. Code generated by
-** autoIncStep() will keep that memory cell holding the largest
+** table and stores that value in a register. Code generated by
+** autoIncStep() will keep that register holding the largest
** rowid value. Code generated by autoIncEnd() will write the new
** largest value of the counter back into the sqlite_sequence table.
**
** This routine returns the index of the mem[] cell that contains
** the maximum rowid counter.
**
-** Two memory cells are allocated. The next memory cell befor the
-** one returned holds the rowid in sqlite_sequence where we will
-** write back the revised maximum rowid.
+** Three consecutive registers are allocated by this routine. The
+** first two hold the name of the target table and the maximum rowid
+** inserted into the target table, respectively.
+** The third holds the rowid in sqlite_sequence where we will
+** write back the revised maximum rowid. This routine returns the
+** index of the second of these three registers.
*/
static int autoIncBegin(
Parse *pParse, /* Parsing context */
int iDb, /* Index of the database holding pTab */
Table *pTab /* The table we are writing to */
){
- int memId = 0;
+ int memId = 0; /* Register holding maximum rowid */
if( pTab->autoInc ){
Vdbe *v = pParse->pVdbe;
Db *pDb = &pParse->db->aDb[iDb];
int iCur = pParse->nTab;
- int addr;
+ int addr; /* Address of the top of the loop */
assert( v );
- addr = sqlite3VdbeCurrentAddr(v);
- pParse->nMem += 2;
- memId = pParse->nMem;
+ pParse->nMem++; /* Holds name of table */
+ memId = ++pParse->nMem;
+ pParse->nMem++;
sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenRead);
- sqlite3VdbeAddOp2(v, OP_Rewind, iCur, addr+12);
+ addr = sqlite3VdbeCurrentAddr(v);
+ sqlite3VdbeAddOp2(v, OP_Rewind, iCur, addr+8);
sqlite3VdbeAddOp2(v, OP_Column, iCur, 0);
sqlite3VdbeAddOp4(v, OP_String8, 0, 0, 0, pTab->zName, 0);
- sqlite3VdbeAddOp2(v, OP_Ne, 0x100, addr+11);
- sqlite3VdbeAddOp2(v, OP_Rowid, iCur, 0);
- sqlite3VdbeAddOp2(v, OP_Move, 0, memId-1);
- sqlite3VdbeAddOp2(v, OP_Column, iCur, 1);
- sqlite3VdbeAddOp2(v, OP_Move, 0, memId);
- sqlite3VdbeAddOp2(v, OP_Goto, 0, addr+12);
- sqlite3VdbeAddOp2(v, OP_Next, iCur, addr+3);
+ sqlite3VdbeAddOp2(v, OP_Ne, 0x100, addr+7);
+ sqlite3VdbeAddOp2(v, OP_Rowid, iCur, memId+1);
+ sqlite3VdbeAddOp3(v, OP_Column, iCur, 1, memId);
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, addr+8);
+ sqlite3VdbeAddOp2(v, OP_Next, iCur, addr+1);
sqlite3VdbeAddOp2(v, OP_Close, iCur, 0);
}
return memId;
@@ -189,15 +191,15 @@
** larger than the maximum rowid in the memId memory cell, then the
** memory cell is updated. The stack is unchanged.
*/
-static void autoIncStep(Parse *pParse, int memId, int iRowid){
+static void autoIncStep(Parse *pParse, int memId, int regRowid){
if( memId>0 ){
- sqlite3VdbeAddOp2(pParse->pVdbe, OP_MemMax, memId, iRowid);
+ sqlite3VdbeAddOp2(pParse->pVdbe, OP_MemMax, memId, regRowid);
}
}
/*
** After doing one or more inserts, the maximum rowid is stored
-** in mem[memId]. Generate code to write this value back into the
+** in reg[memId]. Generate code to write this value back into the
** the sqlite_sequence table.
*/
static void autoIncEnd(
@@ -210,19 +212,18 @@
int iCur = pParse->nTab;
Vdbe *v = pParse->pVdbe;
Db *pDb = &pParse->db->aDb[iDb];
- int addr;
+ int j1;
+
assert( v );
- addr = sqlite3VdbeCurrentAddr(v);
sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenWrite);
- sqlite3VdbeAddOp2(v, OP_SCopy, memId-1, 0);
- sqlite3VdbeAddOp2(v, OP_NotNull, -1, addr+6);
- sqlite3VdbeAddOp2(v, OP_Pop, 1, 0);
- sqlite3VdbeAddOp1(v, OP_NewRowid, iCur);
- sqlite3VdbeAddOp4(v, OP_String8, 0, 0, 0, pTab->zName, 0);
- sqlite3VdbeAddOp2(v, OP_SCopy, memId, 0);
- sqlite3VdbeAddOp2(v, OP_MakeRecord, 2, 0);
- sqlite3CodeInsert(pParse, iCur, OPFLAG_APPEND);
- sqlite3VdbeAddOp2(v, OP_Close, iCur, 0);
+ j1 = sqlite3VdbeAddOp1(v, OP_NotNull, memId+1);
+ sqlite3VdbeAddOp2(v, OP_NewRowid, iCur, memId+1);
+ sqlite3VdbeJumpHere(v, j1);
+ sqlite3VdbeAddOp4(v, OP_String8, 0, memId-1, 0, pTab->zName, 0);
+ sqlite3VdbeAddOp3(v, OP_RegMakeRec, memId-1, 2, memId-1);
+ sqlite3VdbeAddOp3(v, OP_Insert, iCur, memId-1, memId+1);
+ sqlite3VdbeChangeP5(v, -1, OPFLAG_APPEND);
+ sqlite3VdbeAddOp1(v, OP_Close, iCur);
}
}
#else
@@ -341,32 +342,38 @@
IdList *pColumn, /* Column names corresponding to IDLIST. */
int onError /* How to handle constraint errors */
){
- Table *pTab; /* The table to insert into */
+ sqlite3 *db; /* The main database structure */
+ Table *pTab; /* The table to insert into. aka TABLE */
char *zTab; /* Name of the table into which we are inserting */
const char *zDb; /* Name of the database holding this table */
int i, j, idx; /* Loop counters */
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 nHidden = 0; /* Number of hidden columns if TABLE is virtual */
int base = 0; /* VDBE Cursor number for pTab */
- int iCont=0,iBreak=0; /* Beginning and end of the loop over srcTab */
- sqlite3 *db; /* The main database structure */
int keyColumn = -1; /* Column that is the INTEGER PRIMARY KEY */
int endOfLoop; /* Label for the end of the insertion loop */
int useTempTable = 0; /* Store SELECT results in intermediate table */
int srcTab = 0; /* Data comes from this temporary cursor if >=0 */
+ int iCont=0,iBreak=0; /* Beginning and end of the loop over srcTab */
int iSelectLoop = 0; /* Address of code that implements the SELECT */
int iCleanup = 0; /* Address of the cleanup code */
int iInsertBlock = 0; /* Address of the subroutine used to insert data */
- int iCntMem = 0; /* Memory cell used for the row counter */
- int iBaseReg; /* Base register for data */
- int newIdx = -1; /* Cursor for the NEW table */
+ int newIdx = -1; /* Cursor for the NEW pseudo-table */
+ int iDb; /* Index of database holding TABLE */
Db *pDb; /* The database containing table being inserted into */
- int counterMem = 0; /* Memory cell holding AUTOINCREMENT counter */
int appendFlag = 0; /* True if the insert is likely to be an append */
- int iDb;
- int nHidden = 0;
+ /* Register allocations */
+ int regFromSelect; /* Base register for data coming from SELECT */
+ int regAutoinc = 0; /* Register holding the AUTOINCREMENT counter */
+ int regRowCount = 0; /* Memory cell used for the row counter */
+ int regIns; /* Block of regs holding rowid+data being inserted */
+ int regRowid; /* registers holding insert rowid */
+ int regData; /* register holding first column to insert */
+ int regRecord; /* Holds the assemblied row record */
+
#ifndef SQLITE_OMIT_TRIGGER
int isView; /* True if attempting to insert into a view */
@@ -455,11 +462,9 @@
#endif /* SQLITE_OMIT_XFER_OPT */
/* If this is an AUTOINCREMENT table, look up the sequence number in the
- ** sqlite_sequence table and store it in memory cell counterMem. Also
- ** remember the rowid of the sqlite_sequence table entry in memory cell
- ** counterRowid.
+ ** sqlite_sequence table and store it in memory cell regAutoinc.
*/
- counterMem = autoIncBegin(pParse, iDb, pTab);
+ regAutoinc = autoIncBegin(pParse, iDb, pTab);
/* Figure out how many columns of data are supplied. If the data
** is coming from a SELECT statement, then this step also generates
@@ -486,7 +491,7 @@
goto insert_cleanup;
}
- iBaseReg = dest.iMem;
+ regFromSelect = dest.iMem;
iCleanup = sqlite3VdbeMakeLabel(v);
sqlite3VdbeAddOp2(v, OP_Goto, 0, iCleanup);
assert( pSelect->pEList );
@@ -510,7 +515,7 @@
*/
srcTab = pParse->nTab++;
sqlite3VdbeResolveLabel(v, iInsertBlock);
- sqlite3VdbeAddOp2(v, OP_RegMakeRec, iBaseReg, nColumn);
+ sqlite3VdbeAddOp2(v, OP_RegMakeRec, regFromSelect, nColumn);
sqlite3VdbeAddOp1(v, OP_NewRowid, srcTab);
sqlite3VdbeAddOp2(v, OP_Pull, 1, 0);
sqlite3CodeInsert(pParse, srcTab, OPFLAG_APPEND);
@@ -620,8 +625,8 @@
/* Initialize the count of rows to be inserted
*/
if( db->flags & SQLITE_CountRows ){
- iCntMem = ++pParse->nMem;
- sqlite3VdbeAddOp2(v, OP_Integer, 0, iCntMem);
+ regRowCount = ++pParse->nMem;
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount);
}
/* If this is not a view, open the table and and all indices */
@@ -642,10 +647,22 @@
}else if( pSelect ){
sqlite3VdbeAddOp2(v, OP_Goto, 0, iSelectLoop);
sqlite3VdbeResolveLabel(v, iInsertBlock);
- sqlite3RegToStack(pParse, iBaseReg, nColumn);
+ sqlite3RegToStack(pParse, regFromSelect, nColumn);
sqlite3VdbeAddOp2(v, OP_StackDepth, -1, 0);
}
+ /* Allocate registers for holding the rowid of the new row,
+ ** the content of the new row, and the assemblied row record.
+ */
+ regRecord = ++pParse->nMem;
+ regRowid = regIns = pParse->nMem+1;
+ pParse->nMem += pTab->nCol + 1;
+ if( IsVirtual(pTab) ){
+ regRowid++;
+ pParse->nMem++;
+ }
+ regData = regRowid+1;
+
/* Run the BEFORE and INSTEAD OF triggers, if there are any
*/
endOfLoop = sqlite3VdbeMakeLabel(v);
@@ -662,12 +679,15 @@
}else if( useTempTable ){
sqlite3VdbeAddOp2(v, OP_Column, srcTab, keyColumn);
}else{
+ int j1;
assert( pSelect==0 ); /* Otherwise useTempTable is true */
sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, 0);
- sqlite3VdbeAddOp2(v, OP_NotNull, -1, sqlite3VdbeCurrentAddr(v)+3);
- sqlite3VdbeAddOp2(v, OP_Pop, 1, 0);
- sqlite3VdbeAddOp2(v, OP_Integer, -1, 0);
- sqlite3VdbeAddOp2(v, OP_MustBeInt, 0, 0);
+ sqlite3VdbeAddOp0(v, OP_SCopy);
+ j1 = sqlite3VdbeAddOp0(v, OP_NotNull);
+ sqlite3VdbeAddOp1(v, OP_Pop, 1);
+ sqlite3VdbeAddOp1(v, OP_Integer, -1);
+ sqlite3VdbeJumpHere(v, j1);
+ sqlite3VdbeAddOp0(v, OP_MustBeInt);
}
/* Cannot have triggers on a virtual table. If it were possible,
@@ -719,19 +739,15 @@
** case the record number is the same as that column.
*/
if( !isView ){
- int iReg = pParse->nMem+1;
- int iRowid = iReg+(IsVirtual(pTab)?1:0);
- pParse->nMem += pTab->nCol + (IsVirtual(pTab)?2:1);
-
if( IsVirtual(pTab) ){
/* The row that the VUpdate opcode will delete: none */
- sqlite3VdbeAddOp2(v, OP_Null, 0, iReg);
+ sqlite3VdbeAddOp2(v, OP_Null, 0, regIns);
}
if( keyColumn>=0 ){
if( useTempTable ){
- sqlite3VdbeAddOp3(v, OP_Column, srcTab, keyColumn, iRowid);
+ sqlite3VdbeAddOp3(v, OP_Column, srcTab, keyColumn, regRowid);
}else if( pSelect ){
- sqlite3VdbeAddOp2(v, OP_SCopy, -(nColumn - keyColumn - 1), iRowid);
+ sqlite3VdbeAddOp2(v, OP_SCopy, -(nColumn - keyColumn - 1), regRowid);
}else{
VdbeOp *pOp;
sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, 0);
@@ -740,36 +756,36 @@
appendFlag = 1;
pOp->opcode = OP_NewRowid;
pOp->p1 = base;
- pOp->p2 = iRowid;
- pOp->p3 = counterMem;
+ pOp->p2 = regRowid;
+ pOp->p3 = regAutoinc;
}else{
/* TODO: Avoid this use of the stack. */
- sqlite3VdbeAddOp2(v, OP_Move, 0, iRowid);
+ sqlite3VdbeAddOp2(v, OP_Move, 0, regRowid);
}
}
/* If the PRIMARY KEY expression is NULL, then use OP_NewRowid
** to generate a unique primary key value.
*/
if( !appendFlag ){
- sqlite3VdbeAddOp2(v, OP_IfMemNull, iRowid, sqlite3VdbeCurrentAddr(v)+2);
+ sqlite3VdbeAddOp2(v, OP_IfMemNull, regRowid, sqlite3VdbeCurrentAddr(v)+2);
sqlite3VdbeAddOp2(v, OP_Goto, -1, sqlite3VdbeCurrentAddr(v)+2);
- sqlite3VdbeAddOp3(v, OP_NewRowid, base, iRowid, counterMem);
- sqlite3VdbeAddOp3(v, OP_MustBeInt, 0, 0, iRowid);
+ sqlite3VdbeAddOp3(v, OP_NewRowid, base, regRowid, regAutoinc);
+ sqlite3VdbeAddOp3(v, OP_MustBeInt, 0, 0, regRowid);
}
}else if( IsVirtual(pTab) ){
- sqlite3VdbeAddOp2(v, OP_Null, 0, iRowid);
+ sqlite3VdbeAddOp2(v, OP_Null, 0, regRowid);
}else{
- sqlite3VdbeAddOp3(v, OP_NewRowid, base, iRowid, counterMem);
+ sqlite3VdbeAddOp3(v, OP_NewRowid, base, regRowid, regAutoinc);
appendFlag = 1;
}
- autoIncStep(pParse, counterMem, iRowid);
+ autoIncStep(pParse, regAutoinc, regRowid);
/* Push onto the stack, data for all columns of the new entry, beginning
** with the first column.
*/
nHidden = 0;
for(i=0; i<pTab->nCol; i++){
- int iRegStore = iRowid+1+i;
+ int iRegStore = regRowid+1+i;
if( i==pTab->iPKey ){
/* The value of the INTEGER PRIMARY KEY column is always a NULL.
** Whenever this column is read, the record number will be substituted
@@ -808,12 +824,12 @@
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( IsVirtual(pTab) ){
pParse->pVirtualLock = pTab;
- sqlite3VdbeAddOp4(v, OP_VUpdate, 1, pTab->nCol+2, iReg,
+ sqlite3VdbeAddOp4(v, OP_VUpdate, 1, pTab->nCol+2, regIns,
(const char*)pTab->pVtab, P4_VTAB);
}else
#endif
{
- sqlite3RegToStack(pParse, iReg, pTab->nCol+1);
+ sqlite3RegToStack(pParse, regIns, pTab->nCol+1);
sqlite3GenerateConstraintChecks(pParse, pTab, base, 0, keyColumn>=0,
0, onError, endOfLoop);
sqlite3CompleteInsertion(pParse, pTab, base, 0,0,0,
@@ -825,7 +841,7 @@
/* Update the count of rows that are inserted
*/
if( (db->flags & SQLITE_CountRows)!=0 ){
- sqlite3VdbeAddOp2(v, OP_AddImm, iCntMem, 1);
+ sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1);
}
if( triggers_exist ){
@@ -858,10 +874,10 @@
}
/* Update the sqlite_sequence table by storing the content of the
- ** counter value in memory counterMem back into the sqlite_sequence
+ ** counter value in memory regAutoinc back into the sqlite_sequence
** table.
*/
- autoIncEnd(pParse, iDb, pTab, counterMem);
+ autoIncEnd(pParse, iDb, pTab, regAutoinc);
/*
** Return the number of rows inserted. If this routine is
@@ -869,7 +885,7 @@
** invoke the callback function.
*/
if( db->flags & SQLITE_CountRows && pParse->nested==0 && !pParse->trigStack ){
- sqlite3VdbeAddOp2(v, OP_ResultRow, iCntMem, 1);
+ sqlite3VdbeAddOp2(v, OP_ResultRow, regRowCount, 1);
sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows inserted", P4_STATIC);
}
@@ -882,14 +898,14 @@
}
/*
-** Generate code to do a constraint check prior to an INSERT or an UPDATE.
+** Generate code to do constraint checks prior to an INSERT or an UPDATE.
**
** When this routine is called, the stack contains (from bottom to top)
** the following values:
**
** 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.
+** change to the record number. (Or writing to a virtual table.)
**
** 2. The rowid of the row after the update.
**
@@ -1004,7 +1020,7 @@
onError = OE_Abort;
}
sqlite3VdbeAddOp1(v, OP_SCopy, -(nCol-1-i));
- addr = sqlite3VdbeAddOp2(v, OP_NotNull, 1, 0);
+ addr = sqlite3VdbeAddOp0(v, OP_NotNull);
assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
|| onError==OE_Ignore || onError==OE_Replace );
switch( onError ){
@@ -1413,7 +1429,7 @@
int emptySrcTest; /* Address of test for empty pSrc */
Vdbe *v; /* The VDBE we are building */
KeyInfo *pKey; /* Key information for an index */
- int counterMem; /* Memory register used by AUTOINC */
+ int regAutoinc; /* Memory register used by AUTOINC */
int destHasUniqueIdx = 0; /* True if pDest has a UNIQUE index */
if( pSelect==0 ){
@@ -1541,7 +1557,7 @@
sqlite3CodeVerifySchema(pParse, iDbSrc);
iSrc = pParse->nTab++;
iDest = pParse->nTab++;
- counterMem = autoIncBegin(pParse, iDbDest, pDest);
+ regAutoinc = autoIncBegin(pParse, iDbDest, pDest);
sqlite3OpenTable(pParse, iDest, iDbDest, pDest, OP_OpenWrite);
if( (pDest->iPKey<0 && pDest->pIndex!=0) || destHasUniqueIdx ){
/* If tables do not have an INTEGER PRIMARY KEY and there
@@ -1569,7 +1585,7 @@
sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, onError, 0,
"PRIMARY KEY must be unique", P4_STATIC);
sqlite3VdbeJumpHere(v, addr2);
- autoIncStep(pParse, counterMem, 0);
+ autoIncStep(pParse, regAutoinc, 0);
}else if( pDest->pIndex==0 ){
addr1 = sqlite3VdbeAddOp1(v, OP_NewRowid, iDest);
}else{
@@ -1580,7 +1596,7 @@
sqlite3CodeInsert(pParse,iDest,OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND);
sqlite3VdbeChangeP4(v, -1, pDest->zName, 0);
sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1);
- autoIncEnd(pParse, iDbDest, pDest, counterMem);
+ autoIncEnd(pParse, iDbDest, pDest, regAutoinc);
for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){
for(pSrcIdx=pSrc->pIndex; pSrcIdx; pSrcIdx=pSrcIdx->pNext){
if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break;
diff --git a/src/pragma.c b/src/pragma.c
index 50e3f9c..b4b4059 100644
--- a/src/pragma.c
+++ b/src/pragma.c
@@ -11,7 +11,7 @@
*************************************************************************
** This file contains code used to implement the PRAGMA command.
**
-** $Id: pragma.c,v 1.161 2008/01/05 16:29:28 drh Exp $
+** $Id: pragma.c,v 1.162 2008/01/07 19:20:25 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@@ -882,7 +882,7 @@
}
if( cnt==0 ) continue;
sqlite3VdbeAddOp2(v, OP_IntegrityCk, 1, i);
- addr = sqlite3VdbeAddOp2(v, OP_IsNull, -1, 0);
+ addr = sqlite3VdbeAddOp2(v, OP_StackIsNull, -1, 0);
sqlite3VdbeAddOp4(v, OP_String8, 0, 0, 0,
sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zName),
P4_DYNAMIC);
diff --git a/src/select.c b/src/select.c
index e818218..4e39192 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.391 2008/01/07 10:16:41 danielk1977 Exp $
+** $Id: select.c,v 1.392 2008/01/07 19:20:25 drh Exp $
*/
#include "sqliteInt.h"
@@ -809,12 +809,16 @@
}
#ifndef SQLITE_OMIT_SUBQUERY
case SRT_Set: {
+ int j1, j2;
assert( nColumn==1 );
- sqlite3VdbeAddOp2(v, OP_NotNull, -1, sqlite3VdbeCurrentAddr(v)+3);
- sqlite3VdbeAddOp2(v, OP_Pop, 1, 0);
- sqlite3VdbeAddOp2(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+3);
+ sqlite3VdbeAddOp0(v, OP_SCopy);
+ j1 = sqlite3VdbeAddOp0(v, OP_NotNull);
+ sqlite3VdbeAddOp1(v, OP_Pop, 1);
+ j2 = sqlite3VdbeAddOp0(v, OP_Goto);
+ sqlite3VdbeJumpHere(v, j1);
sqlite3VdbeAddOp4(v, OP_MakeRecord, 1, 0, 0, &p->affinity, 1);
sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, 0);
+ sqlite3VdbeJumpHere(v, j2);
break;
}
case SRT_Mem: {
diff --git a/src/vdbe.c b/src/vdbe.c
index a8643d9..58b1b14 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -43,7 +43,7 @@
** in this file for details. If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
-** $Id: vdbe.c,v 1.686 2008/01/06 00:25:22 drh Exp $
+** $Id: vdbe.c,v 1.687 2008/01/07 19:20:25 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@@ -2110,7 +2110,7 @@
break;
}
-/* Opcode: IsNull P1 P2 *
+/* Opcode: StackIsNull P1 P2 *
**
** Check the top of the stack and jump to P2 if the top of the stack
** is NULL. If P1 is positive, then pop P1 elements from the stack
@@ -2118,7 +2118,7 @@
** pop -P1 elements from the stack only if the jump is taken and leave
** the stack unchanged if the jump is not taken.
*/
-case OP_IsNull: { /* same as TK_ISNULL, no-push, jump */
+case OP_StackIsNull: { /* no-push, jump */
if( pTos->flags & MEM_Null ){
pc = pOp->p2-1;
if( pOp->p1<0 ){
@@ -2131,40 +2131,31 @@
break;
}
-/* Opcode: AnyNull P1 P2 P3 * *
+/* Opcode: IsNull P1 P2 *
**
-** Check P3 registers beginning with P1. If any are NULL then jump
-** to P2.
+** Jump to P2 if the value in register P1 is NULL.
+**
+** If P1 is 0 then use the top of the stack instead of a register
+** and pop the stack regardless of whether or not the jump is taken.
*/
-case OP_AnyNull: { /* no-push, jump, in1 */
- int n = pOp->p3;
- assert( n>0 && pOp->p1+n<=p->nMem );
- while( n>0 ){
- if( pIn1->flags & MEM_Null ){
- pc = pOp->p2-1;
- break;
- }
- n--;
- pIn1++;
+case OP_IsNull: { /* same as TK_ISNULL, no-push, jump, in1 */
+ if( (pIn1->flags & MEM_Null)!=0 ){
+ pc = pOp->p2 - 1;
}
break;
}
/* Opcode: NotNull P1 P2 *
**
-** Jump to P2 if the top abs(P1) values on the stack are all not NULL.
-** Regardless of whether or not the jump is taken, pop the stack
-** P1 times if P1 is greater than zero. But if P1 is negative,
-** leave the stack unchanged.
+** Jump to P2 if the value in register P1 is not NULL.
+**
+** If P1 is 0 then use the top of the stack instead of a register
+** and pop the stack regardless of whether or not the jump is taken.
*/
-case OP_NotNull: { /* same as TK_NOTNULL, no-push, jump */
- int i, cnt;
- cnt = pOp->p1;
- if( cnt<0 ) cnt = -cnt;
- assert( &pTos[1-cnt] >= p->aStack );
- for(i=0; i<cnt && (pTos[1+i-cnt].flags & MEM_Null)==0; i++){}
- if( i>=cnt ) pc = pOp->p2-1;
- if( pOp->p1>0 ) popStack(&pTos, cnt);
+case OP_NotNull: { /* same as TK_NOTNULL, no-push, jump, in1 */
+ if( (pIn1->flags & MEM_Null)==0 ){
+ pc = pOp->p2 - 1;
+ }
break;
}
diff --git a/src/where.c b/src/where.c
index 360e191..4d9454f 100644
--- a/src/where.c
+++ b/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.276 2008/01/05 17:39:30 danielk1977 Exp $
+** $Id: where.c,v 1.277 2008/01/07 19:20:25 drh Exp $
*/
#include "sqliteInt.h"
@@ -1757,7 +1757,7 @@
pIn += pLevel->nIn - 1;
pIn->iCur = iTab;
pIn->topAddr = sqlite3VdbeAddOp2(v, op, iTab, 0);
- sqlite3VdbeAddOp2(v, OP_IsNull, -1, 0);
+ sqlite3VdbeAddOp2(v, OP_StackIsNull, -1, 0);
}else{
pLevel->nIn = 0;
}
@@ -1824,7 +1824,7 @@
assert( (pTerm->flags & TERM_CODED)==0 );
codeEqualityTerm(pParse, pTerm, pLevel);
if( (pTerm->eOperator & (WO_ISNULL|WO_IN))==0 ){
- sqlite3VdbeAddOp2(v, OP_IsNull, termsInMem ? -1 : -(j+1), pLevel->brk);
+ sqlite3VdbeAddOp2(v, OP_StackIsNull, termsInMem ? -1 : -(j+1), pLevel->brk);
}
if( termsInMem ){
sqlite3VdbeAddOp2(v, OP_Move, 0, pLevel->iMem+j+1);
@@ -2467,7 +2467,7 @@
pX = pTerm->pExpr;
assert( (pTerm->flags & TERM_CODED)==0 );
sqlite3ExprCode(pParse, pX->pRight, 0);
- sqlite3VdbeAddOp2(v, OP_IsNull, -(nEq*2+1), nxt);
+ sqlite3VdbeAddOp2(v, OP_StackIsNull, -(nEq*2+1), nxt);
topEq = pTerm->eOperator & (WO_LE|WO_GE);
disableTerm(pLevel, pTerm);
testOp = OP_IdxGE;
@@ -2511,7 +2511,7 @@
pX = pTerm->pExpr;
assert( (pTerm->flags & TERM_CODED)==0 );
sqlite3ExprCode(pParse, pX->pRight, 0);
- sqlite3VdbeAddOp2(v, OP_IsNull, -(nEq+1), nxt);
+ sqlite3VdbeAddOp2(v, OP_StackIsNull, -(nEq+1), nxt);
btmEq = pTerm->eOperator & (WO_LE|WO_GE);
disableTerm(pLevel, pTerm);
}else{
@@ -2553,7 +2553,7 @@
}
if( topLimit | btmLimit ){
sqlite3VdbeAddOp2(v, OP_Column, iIdxCur, nEq);
- sqlite3VdbeAddOp2(v, OP_IsNull, 1, cont);
+ sqlite3VdbeAddOp2(v, OP_StackIsNull, 1, cont);
}
if( !omitTable ){
sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, 0);