-C Registerify\sthe\sAUTOINCREMENT\sprocessing\sand\sthe\sOP_IsNull\sand\sOP_NotNull\noperators.\s(CVS\s4692)
-D 2008-01-07T19:20:25
+C Progress\stoward\sregisterification\sof\sthe\sconstraint\schecking\slogic\sfor\nINSERT\sand\sUPDATE.\s(CVS\s4693)
+D 2008-01-08T02:57:56
F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
F Makefile.in 30789bf70614bad659351660d76b8e533f3340e9
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
F src/callback.c 77b302b0d41468dcda78c70e706e5b84577f0fa0
F src/complete.c 4cf68fd75d60257524cbe74f87351b9848399131
F src/date.c 49c5a6d2de6c12000905b4d36868b07d3011bbf6
-F src/delete.c 09c7b312a061d08df8a95b1f75cb10c6af14114a
+F src/delete.c d78e46b259a94a5f98a1bceee206c5fd21276ae7
F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b
-F src/expr.c f84b4901dff3bacd08ece3f0de09318a5a298121
+F src/expr.c 6f2a852227ba2abd5ad0916f539c1f2159da28b4
F src/func.c 996071cf0af9d967e58b69fce1909555059ebc7d
F src/hash.c 45a7005aac044b6c86bd7e49c44bc15d30006d6c
F src/hash.h 031cd9f915aff27e12262cb9eb570ac1b8326b53
-F src/insert.c 9c1a6501d79c9c4e674e0e2c3bc4a5207f9b3b95
+F src/insert.c 3a45102002b611aa1707bb6c6c5c148547d2630a
F src/journal.c 807bed7a158979ac8d63953e1774e8d85bff65e2
F src/legacy.c 4ac53191fad2e3c4d59bde1228879b2dc5a96d66
F src/limits.h 71ab25f17e35e0a9f3f6f234b8ed49cc56731d35
F src/shell.c 5391e889384d2062249f668110d64ed16f601c4b
F src/sqlite.h.in 2a7e3776534bbe6ff2cdc058f3abebe91e7e429f
F src/sqlite3ext.h a93f59cdee3638dc0c9c086f80df743a4e68c3cb
-F src/sqliteInt.h 95cdddce11ee871fad1d91d6b6e405969dcc405f
+F src/sqliteInt.h 964754dcd508ddf0dd0b326072ad80678452e5c2
F src/sqliteLimit.h ee4430f88f69bf63527967bb35ca52af7b0ccb1e
F src/table.c 1aeb9eab57b4235db86fe15a35dec76fb445a9c4
F src/tclsqlite.c 9923abeffc9b3d7dad58e92b319661521f60debf
F src/test_thread.c e297dd41db0b249646e69f97d36ec13e56e8b730
F src/tokenize.c a4e04438c11fed2c67ec47fe3edbef9cca2d1b48
F src/trigger.c 33071215111825634b85567bfc36c14094eebe54
-F src/update.c 38e9e4c27896df2d189927e3b483cadf5641f47c
+F src/update.c acd1c38dbbf253183fe2a8e5be0b3f3fee59be15
F src/utf.c ef4b7d83bae533b76c3e1bf635b113fdad86a736
F src/util.c 05f31144bbd3f1a24f4139ae029c42545cb72624
F src/vacuum.c 3f34f278809bf3eb0b62ec46ff779e9c385b28f0
-F src/vdbe.c 3d849013558e52b2c85134fc6ed655d6dc00ace7
+F src/vdbe.c e71595acce83c585c31ac0551cee1c8cf9540fd2
F src/vdbe.h bb128757b84280504a1243c450fd13ead248ede5
F src/vdbeInt.h 31bd686595356284d5484592e2dc6e58025aa346
F src/vdbeapi.c f14174843bf4be2c9afdf2ef48b61e7c3ac62d7c
-F src/vdbeaux.c 75b7d3e42c94310f28f6f7d3e08b69797fbe8a78
+F src/vdbeaux.c b6241be0277795ecd902743366434704f03b7636
F src/vdbeblob.c b90f7494c408d47ce6835000b01e40b371e27baf
F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6
-F src/vdbemem.c 123994fcd344993d2fb050a83b91b341bbbd08b4
+F src/vdbemem.c a94f3e9e85578ba457133ad3446fc6114a03ec5a
F src/vtab.c 03014b2bfa8096ecac5fcdc80d34cd76e06af52a
F src/where.c 306fafa709ced14b1c816d38b96a8f4446ec1eeb
F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
-P 38020592f15c072e0d221ae2e0df13508ac4bd49
-R dde2d5dbca593f8bc201758cd5d40a3d
+P aa48867cfa04da265b906e5b583bc7ac6b6a1157
+R af4f73c6bffdbedd3861a3c5eb6d920e
U drh
-Z 07f47472df3751ae71471b817e3e70f7
+Z 313f66697e8ae592eab31fdd061363d6
-aa48867cfa04da265b906e5b583bc7ac6b6a1157
\ No newline at end of file
+b9bf509e39f5ac38c2149d2a648f68e5df5ae9e3
\ No newline at end of file
** 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.152 2008/01/06 00:25:22 drh Exp $
+** $Id: delete.c,v 1.153 2008/01/08 02:57:56 drh Exp $
*/
#include "sqliteInt.h"
Vdbe *v, /* Generate code into this VDBE */
Table *pTab, /* Table containing the row to be deleted */
int iCur, /* Cursor number for the table */
- char *aIdxUsed /* Only delete if aIdxUsed!=0 && aIdxUsed[i]!=0 */
+ int *aRegIdx /* Only delete if aRegIdx!=0 && aRegIdx[i]>0 */
){
int i;
Index *pIdx;
for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
- if( aIdxUsed!=0 && aIdxUsed[i-1]==0 ) continue;
+ if( aRegIdx!=0 && aRegIdx[i-1]==0 ) continue;
sqlite3GenerateIndexKey(v, pIdx, iCur);
sqlite3VdbeAddOp1(v, OP_IdxDelete, iCur+i);
}
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
-** $Id: expr.c,v 1.336 2008/01/07 19:20:25 drh Exp $
+** $Id: expr.c,v 1.337 2008/01/08 02:57:56 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
Vdbe *v = pParse->pVdbe;
int op;
int inReg = 0;
- int stackChng = 0;
int origTarget = target;
assert( v!=0 || pParse->db->mallocFailed );
if( v==0 ) return 0;
if( target<0 ){
target = ++pParse->nMem;
- }else if( target==0 ){
- stackChng = 1;
}
if( pExpr==0 ){
case TK_COLUMN: {
if( pExpr->iTable<0 ){
/* This only happens when coding check constraints */
- assert( pParse->ckOffset>0 );
- sqlite3VdbeAddOp1(v, OP_SCopy, -(pParse->ckOffset-pExpr->iColumn-1));
- /* inReg = -(pParse->ckOffset-pExpr->iColumn-1); */
+ assert( pParse->ckBase>0 );
+ inReg = pExpr->iColumn + pParse->ckBase;
}else{
sqlite3ExprCodeGetColumn(v, pExpr->pTab,
pExpr->iColumn, pExpr->iTable, target);
assert( to_op==OP_ToInt || aff!=SQLITE_AFF_INTEGER );
assert( to_op==OP_ToReal || aff!=SQLITE_AFF_REAL );
sqlite3VdbeAddOp1(v, to_op, target);
- stackChng = 0;
inReg = target;
break;
}
sqlite3ExprCode(pParse, pExpr->pLeft, 0);
sqlite3ExprCode(pParse, pExpr->pRight, 0);
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, 0, 0);
- stackChng = -1;
break;
}
case TK_AND:
assert( TK_LSHIFT==OP_ShiftLeft );
assert( TK_RSHIFT==OP_ShiftRight );
assert( TK_CONCAT==OP_Concat );
- r1 = sqlite3ExprCode(pParse, pExpr->pLeft, 0);
- r2 = sqlite3ExprCode(pParse, pExpr->pRight, 0);
+ r1 = sqlite3ExprCode(pParse, pExpr->pLeft, -1);
+ r2 = sqlite3ExprCode(pParse, pExpr->pRight, -1);
sqlite3VdbeAddOp3(v, op, r2, r1, target);
- if( r1==0 ) stackChng--;
- if( r2==0 ) stackChng--;
- if( target==0 ) stackChng++;
inReg = target;
break;
}
assert( TK_NOT==OP_Not );
sqlite3ExprCode(pParse, pExpr->pLeft, 0);
sqlite3VdbeAddOp0(v, op);
- stackChng = 0;
break;
}
case TK_ISNULL:
addr = sqlite3VdbeAddOp0(v, op);
sqlite3VdbeAddOp2(v, OP_AddImm, target, -1);
sqlite3VdbeJumpHere(v, addr);
- stackChng = 0;
inReg = target;
break;
}
}
sqlite3VdbeAddOp4(v, OP_Function, constMask, nExpr, 0,
(char*)pDef, P4_FUNCDEF);
- stackChng = 1-nExpr;
break;
}
#ifndef SQLITE_OMIT_SUBQUERY
case TK_IN: {
int j1, j2, j3, j4, j5;
char affinity;
- int ckOffset = pParse->ckOffset;
int eType;
eType = sqlite3FindInIndex(pParse, pExpr, 0);
affinity = comparisonAffinity(pExpr);
sqlite3VdbeAddOp1(v, OP_Integer, 1);
- pParse->ckOffset = (ckOffset ? (ckOffset+1) : 0);
/* Code the <expr> from "<expr> IN (...)". The temporary table
** pExpr->iTable contains the values that make up the (...) set.
}
case TK_UPLUS: {
inReg = sqlite3ExprCode(pParse, pExpr->pLeft, origTarget);
- stackChng = 0;
break;
}
case TK_CASE: {
sqlite3VdbeAddOp2(v, OP_Goto, 0, pParse->trigStack->ignoreJump);
VdbeComment((v, "raise(IGNORE)"));
}
- stackChng = 0;
break;
}
#endif
}else{
target = inReg;
}
- stackChng = 0;
- }
- if( pParse->ckOffset ){
- pParse->ckOffset += stackChng;
- assert( pParse->ckOffset );
}
return target;
}
void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
Vdbe *v = pParse->pVdbe;
int op = 0;
- int ckOffset = pParse->ckOffset;
if( v==0 || pExpr==0 ) return;
op = pExpr->op;
switch( op ){
break;
}
}
- pParse->ckOffset = ckOffset;
}
/*
void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
Vdbe *v = pParse->pVdbe;
int op = 0;
- int ckOffset = pParse->ckOffset;
if( v==0 || pExpr==0 ) return;
/* The value of pExpr->op and op are related as follows:
break;
}
}
- pParse->ckOffset = ckOffset;
}
/*
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
**
-** $Id: insert.c,v 1.215 2008/01/07 19:20:25 drh Exp $
+** $Id: insert.c,v 1.216 2008/01/08 02:57:56 drh Exp $
*/
#include "sqliteInt.h"
int regRowid; /* registers holding insert rowid */
int regData; /* register holding first column to insert */
int regRecord; /* Holds the assemblied row record */
+ int *aRegIdx = 0; /* One register allocated to each index */
#ifndef SQLITE_OMIT_TRIGGER
/* If this is not a view, open the table and and all indices */
if( !isView ){
+ int nIdx;
+ int i;
+
base = pParse->nTab;
- sqlite3OpenTableAndIndices(pParse, pTab, base, OP_OpenWrite);
+ nIdx = sqlite3OpenTableAndIndices(pParse, pTab, base, OP_OpenWrite);
+ aRegIdx = sqlite3DbMallocZero(db, sizeof(int)*(nIdx+1));
+ if( aRegIdx==0 ){
+ goto insert_cleanup;
+ }
+ for(i=0; i<nIdx; i++){
+ aRegIdx[i] = ++pParse->nMem;
+ }
}
/* If the data source is a temporary table, then we have to create
#endif
{
sqlite3RegToStack(pParse, regIns, pTab->nCol+1);
- sqlite3GenerateConstraintChecks(pParse, pTab, base, 0, keyColumn>=0,
+ sqlite3GenerateConstraintChecks(pParse, pTab, base, aRegIdx, keyColumn>=0,
0, onError, endOfLoop);
- sqlite3CompleteInsertion(pParse, pTab, base, 0,0,0,
+ sqlite3CompleteInsertion(pParse, pTab, base, aRegIdx,0,0,
(triggers_exist & TRIGGER_AFTER)!=0 ? newIdx : -1,
appendFlag);
}
sqlite3ExprListDelete(pList);
sqlite3SelectDelete(pSelect);
sqlite3IdListDelete(pColumn);
+ sqlite3_free(aRegIdx);
}
/*
** 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.
-** The order of index keys is the same as the order of the indices on
-** the pTable->pIndex list. A key is only created for index i if
-** aIdxUsed!=0 and aIdxUsed[i]!=0.
+** The code generated by this routine store new index entries into
+** registers identified by aRegIdx[]. No index entry is created for
+** indices where aRegIdx[i]==0. The order of indices in aRegIdx[] is
+** the same as the order of indices on the linked list of indices
+** attached to the table.
**
** This routine also generates code to check constraints. NOT NULL,
** CHECK, and UNIQUE constraints are all checked. If a constraint fails,
** cursor number "base". All indices of pTab must also have open
** read/write cursors with cursor number base+i for the i-th cursor.
** Except, if there is no possibility of a REPLACE action then
-** cursors do not need to be open for indices where aIdxUsed[i]==0.
+** cursors do not need to be open for indices where aRegIdx[i]==0.
**
** If the isUpdate flag is true, it means that the "base" cursor is
** initially pointing to an entry that is being updated. The isUpdate
Parse *pParse, /* The parser context */
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 *aRegIdx, /* Register used by each index. 0 for unused indices */
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 */
Vdbe *v;
int nCol;
int onError;
- int addr;
- int extra;
+ int j1, j2, j3; /* Address of jump instructions */
int iCur;
Index *pIdx;
int seenReplace = 0;
- int jumpInst1=0, jumpInst2;
int hasTwoRowids = (isUpdate && rowidChng);
+ int regRowid, regData;
+
v = sqlite3GetVdbe(pParse);
assert( v!=0 );
assert( pTab->pSelect==0 ); /* This table is not a VIEW */
nCol = pTab->nCol;
+ /* Copy rowids and data into registers
+ */
+ regRowid = sqlite3StackToReg(pParse, nCol+1+hasTwoRowids);
+ sqlite3RegToStack(pParse, regRowid, nCol+1+hasTwoRowids);
+ if( hasTwoRowids ) regRowid++;
+ regData = regRowid+1;
+
/* Test all NOT NULL constraints.
*/
for(i=0; i<nCol; i++){
if( onError==OE_Replace && pTab->aCol[i].pDflt==0 ){
onError = OE_Abort;
}
- sqlite3VdbeAddOp1(v, OP_SCopy, -(nCol-1-i));
- addr = sqlite3VdbeAddOp0(v, OP_NotNull);
+ j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regData+i);
assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
|| onError==OE_Ignore || onError==OE_Replace );
switch( onError ){
}
case OE_Replace: {
sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, 0);
+ sqlite3VdbeAddOp2(v, OP_Copy, 0, regData+i);
sqlite3VdbeAddOp1(v, OP_Push, nCol-i);
break;
}
}
- sqlite3VdbeJumpHere(v, addr);
+ sqlite3VdbeJumpHere(v, j1);
}
/* Test all CHECK constraints
#ifndef SQLITE_OMIT_CHECK
if( pTab->pCheck && (pParse->db->flags & SQLITE_IgnoreChecks)==0 ){
int allOk = sqlite3VdbeMakeLabel(v);
- assert( pParse->ckOffset==0 );
- pParse->ckOffset = nCol;
+ pParse->ckBase = regData;
sqlite3ExprIfTrue(pParse, pTab->pCheck, allOk, 1);
- assert( pParse->ckOffset==nCol );
- pParse->ckOffset = 0;
onError = overrideError!=OE_Default ? overrideError : OE_Abort;
if( onError==OE_Ignore ){
sqlite3VdbeAddOp2(v, OP_Pop, nCol+1+hasTwoRowids, 0);
}
if( isUpdate ){
- sqlite3VdbeAddOp1(v, OP_SCopy, -(nCol+1));
- sqlite3VdbeAddOp1(v, OP_SCopy, -(nCol+1));
- jumpInst1 = sqlite3VdbeAddOp2(v, OP_Eq, 0, 0);
+ sqlite3VdbeAddOp1(v, OP_SCopy, regRowid-1);
+ sqlite3VdbeAddOp1(v, OP_SCopy, regRowid);
+ j2 = sqlite3VdbeAddOp2(v, OP_Eq, 0, 0);
}
- sqlite3VdbeAddOp1(v, OP_SCopy, -nCol);
- jumpInst2 = sqlite3VdbeAddOp2(v, OP_NotExists, base, 0);
+ j3 = sqlite3VdbeAddOp3(v, OP_NotExists, base, 0, regRowid);
switch( onError ){
default: {
onError = OE_Abort;
case OE_Replace: {
sqlite3GenerateRowIndexDelete(v, pTab, base, 0);
if( isUpdate ){
- sqlite3VdbeAddOp1(v, OP_SCopy, -(nCol+hasTwoRowids));
+ sqlite3VdbeAddOp1(v, OP_SCopy, regRowid-hasTwoRowids);
sqlite3VdbeAddOp2(v, OP_MoveGe, base, 0);
}
seenReplace = 1;
break;
}
}
- sqlite3VdbeJumpHere(v, jumpInst2);
+ sqlite3VdbeJumpHere(v, j3);
if( isUpdate ){
- sqlite3VdbeJumpHere(v, jumpInst1);
- sqlite3VdbeAddOp1(v, OP_SCopy, -(nCol+1));
+ sqlite3VdbeJumpHere(v, j2);
+ sqlite3VdbeAddOp1(v, OP_SCopy, regRowid-1);
sqlite3VdbeAddOp2(v, OP_MoveGe, base, 0);
}
}
** index and making sure that duplicate entries do not already exist.
** Add the new records to the indices as we go.
*/
- extra = -1;
for(iCur=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, iCur++){
- if( aIdxUsed && aIdxUsed[iCur]==0 ) continue; /* Skip unused indices */
- extra++;
+ if( aRegIdx[iCur]==0 ) continue; /* Skip unused indices */
/* Create a key for accessing the index entry */
- sqlite3VdbeAddOp1(v, OP_SCopy, -(nCol+extra));
+ sqlite3VdbeAddOp1(v, OP_SCopy, regRowid);
for(i=0; i<pIdx->nColumn; i++){
int idx = pIdx->aiColumn[i];
if( idx==pTab->iPKey ){
- sqlite3VdbeAddOp1(v, OP_SCopy, -(i+extra+nCol+1));
+ sqlite3VdbeAddOp1(v, OP_SCopy, regRowid);
}else{
- sqlite3VdbeAddOp1(v, OP_SCopy, -(i+extra+nCol-idx));
+ sqlite3VdbeAddOp1(v, OP_SCopy, regData+idx);
}
}
- jumpInst1 = sqlite3VdbeAddOp2(v, OP_MakeIdxRec, pIdx->nColumn, 0);
+ j2 = sqlite3VdbeAddOp3(v, OP_MakeIdxRec, pIdx->nColumn, 0, aRegIdx[iCur]);
sqlite3IndexAffinityStr(v, pIdx);
/* Find out what action to take in case there is an indexing conflict */
/* Check to see if the new index entry will be unique */
- sqlite3VdbeAddOp1(v, OP_SCopy, -(extra+nCol+1+hasTwoRowids));
- jumpInst2 = sqlite3VdbeAddOp2(v, OP_IsUnique, base+iCur+1, 0);
+ sqlite3VdbeAddOp1(v, OP_SCopy, aRegIdx[iCur]);
+ sqlite3VdbeAddOp1(v, OP_SCopy, regRowid-hasTwoRowids);
+ j3 = sqlite3VdbeAddOp2(v, OP_IsUnique, base+iCur+1, 0);
/* Generate code that executes if the new index entry is not unique */
assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
}
case OE_Ignore: {
assert( seenReplace==0 );
- sqlite3VdbeAddOp2(v, OP_Pop, nCol+extra+3+hasTwoRowids, 0);
+ sqlite3VdbeAddOp2(v, OP_Pop, nCol+3+hasTwoRowids, 0);
sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
break;
}
int iRowid = sqlite3StackToReg(pParse, 1);
sqlite3GenerateRowDelete(pParse->db, v, pTab, base, iRowid, 0);
if( isUpdate ){
- sqlite3VdbeAddOp1(v, OP_SCopy, -(nCol+extra+1+hasTwoRowids));
+ sqlite3VdbeAddOp1(v, OP_SCopy, regRowid-hasTwoRowids);
sqlite3VdbeAddOp2(v, OP_MoveGe, base, 0);
}
seenReplace = 1;
break;
}
}
+ sqlite3VdbeJumpHere(v, j3);
+ sqlite3VdbeAddOp1(v, OP_Pop, 1);
#if NULL_DISTINCT_FOR_UNIQUE
- sqlite3VdbeJumpHere(v, jumpInst1);
+ sqlite3VdbeJumpHere(v, j2);
#endif
- sqlite3VdbeJumpHere(v, jumpInst2);
}
}
Parse *pParse, /* The parser context */
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 *aRegIdx, /* Register used by each index. 0 for unused indices */
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 */
assert( pTab->pSelect==0 ); /* This table is not a VIEW */
for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){}
for(i=nIdx-1; i>=0; i--){
- if( aIdxUsed && aIdxUsed[i]==0 ) continue;
- sqlite3VdbeAddOp2(v, OP_IdxInsert, base+i+1, 0);
+ if( aRegIdx[i]==0 ) continue;
+ sqlite3VdbeAddOp2(v, OP_IdxInsert, base+i+1, aRegIdx[i]);
}
sqlite3VdbeAddOp2(v, OP_MakeRecord, pTab->nCol, 0);
sqlite3TableAffinityStr(v, pTab);
** Generate code that will open cursors for a table and for all
** indices of that table. The "base" parameter is the cursor number used
** for the table. Indices are opened on subsequent cursors.
+**
+** Return the number of indices on the table.
*/
-void sqlite3OpenTableAndIndices(
+int sqlite3OpenTableAndIndices(
Parse *pParse, /* Parsing context */
Table *pTab, /* Table to be opened */
int base, /* Cursor number assigned to the table */
Index *pIdx;
Vdbe *v;
- if( IsVirtual(pTab) ) return;
+ if( IsVirtual(pTab) ) return 0;
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
v = sqlite3GetVdbe(pParse);
assert( v!=0 );
if( pParse->nTab<=base+i ){
pParse->nTab = base+i;
}
+ return i-1;
}
VdbeComment((v, "%s", pDestIdx->zName));
addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0);
sqlite3VdbeAddOp2(v, OP_RowKey, iSrc, 0);
- sqlite3VdbeAddOp2(v, OP_IdxInsert, iDest, 1);
+ sqlite3VdbeAddOp3(v, OP_IdxInsert, iDest, 0, 1);
sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1);
sqlite3VdbeJumpHere(v, addr1);
}
*************************************************************************
** Internal interface definitions for SQLite.
**
-** @(#) $Id: sqliteInt.h,v 1.641 2008/01/06 00:25:22 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.642 2008/01/08 02:57:56 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_
int nTab; /* Number of previously allocated VDBE cursors */
int nMem; /* Number of memory cells used so far */
int nSet; /* Number of sets used so far */
- int ckOffset; /* Stack offset to data used by CHECK constraints */
+ int ckBase; /* Base register of data during check constraints */
u32 writeMask; /* Start a write transaction on these databases */
u32 cookieMask; /* Bitmask of schema verified databases */
int cookieGoto; /* Address of OP_Goto to cookie verifier subroutine */
int sqlite3ExprIsInteger(Expr*, int*);
int sqlite3IsRowid(const char*);
void sqlite3GenerateRowDelete(sqlite3*, Vdbe*, Table*, int, int, int);
-void sqlite3GenerateRowIndexDelete(Vdbe*, Table*, int, char*);
+void sqlite3GenerateRowIndexDelete(Vdbe*, Table*, int, int*);
void sqlite3GenerateIndexKey(Vdbe*, Index*, int);
-void sqlite3GenerateConstraintChecks(Parse*,Table*,int,char*,int,int,int,int);
-void sqlite3CompleteInsertion(Parse*, Table*, int, char*, int, int, int, int);
-void sqlite3OpenTableAndIndices(Parse*, Table*, int, int);
+void sqlite3GenerateConstraintChecks(Parse*,Table*,int,int*,int,int,int,int);
+void sqlite3CompleteInsertion(Parse*, Table*, int, int*, int, int, int, int);
+int sqlite3OpenTableAndIndices(Parse*, Table*, int, int);
void sqlite3BeginWriteOperation(Parse*, int, int);
Expr *sqlite3ExprDup(sqlite3*,Expr*);
void sqlite3TokenCopy(sqlite3*,Token*, Token*);
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
-** $Id: update.c,v 1.162 2008/01/06 00:25:22 drh Exp $
+** $Id: update.c,v 1.163 2008/01/08 02:57:56 drh Exp $
*/
#include "sqliteInt.h"
Vdbe *v; /* The virtual database engine */
Index *pIdx; /* For looping over indices */
int nIdx; /* Number of indices that need updating */
- int nIdxTotal; /* Total number of indices */
int iCur; /* VDBE Cursor number of pTab */
sqlite3 *db; /* The database structure */
- Index **apIdx = 0; /* An array of indices that need updating too */
- char *aIdxUsed = 0; /* aIdxUsed[i]==1 if the i-th index is used */
+ int *aRegIdx = 0; /* One register assigned to each index to be updated */
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. */
#endif
}
- /* Allocate memory for the array apIdx[] and fill it with pointers to every
- ** index that needs to be updated. Indices only need updating if their
- ** key includes one of the columns named in pChanges or if the record
- ** number of the original table entry is changing.
+ /* Allocate memory for the array aRegIdx[]. There is one entry in the
+ ** array for each index associated with table being updated. Fill in
+ ** the value with a register number for indices that are to be used
+ ** and with zero for unused indices.
*/
- for(nIdx=nIdxTotal=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdxTotal++){
- if( chngRowid ){
- i = 0;
- }else {
- for(i=0; i<pIdx->nColumn; i++){
- if( aXRef[pIdx->aiColumn[i]]>=0 ) break;
- }
- }
- if( i<pIdx->nColumn ) nIdx++;
- }
- if( nIdxTotal>0 ){
- apIdx = sqlite3DbMallocRaw(db, sizeof(Index*) * nIdx + nIdxTotal );
- if( apIdx==0 ) goto update_cleanup;
- aIdxUsed = (char*)&apIdx[nIdx];
+ for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){}
+ if( nIdx>0 ){
+ aRegIdx = sqlite3DbMallocRaw(db, sizeof(Index*) * nIdx );
+ if( aRegIdx==0 ) goto update_cleanup;
}
- for(nIdx=j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
+ for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
+ int reg;
if( chngRowid ){
- i = 0;
+ reg = ++pParse->nMem;
}else{
+ reg = 0;
for(i=0; i<pIdx->nColumn; i++){
- if( aXRef[pIdx->aiColumn[i]]>=0 ) break;
+ if( aXRef[pIdx->aiColumn[i]]>=0 ){
+ reg = ++pParse->nMem;
+ break;
+ }
}
}
- if( i<pIdx->nColumn ){
- apIdx[nIdx++] = pIdx;
- aIdxUsed[j] = 1;
- }else{
- aIdxUsed[j] = 0;
- }
+ aRegIdx[j] = reg;
}
/* Begin generating code.
}
}
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
- if( openAll || aIdxUsed[i] ){
+ if( openAll || aRegIdx[i]>0 ){
KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
sqlite3VdbeAddOp4(v, OP_OpenWrite, iCur+i+1, pIdx->tnum, iDb,
(char*)pKey, P4_KEYINFO_HANDOFF);
/* Do constraint checks
*/
- sqlite3GenerateConstraintChecks(pParse, pTab, iCur, aIdxUsed, chngRowid, 1,
+ sqlite3GenerateConstraintChecks(pParse, pTab, iCur, aRegIdx, chngRowid, 1,
onError, addr);
/* Delete the old indices for the current record.
*/
- sqlite3GenerateRowIndexDelete(v, pTab, iCur, aIdxUsed);
+ sqlite3GenerateRowIndexDelete(v, pTab, iCur, aRegIdx);
/* If changing the record number, delete the old record.
*/
/* Create the new index entries and the new record.
*/
- sqlite3CompleteInsertion(pParse, pTab, iCur, aIdxUsed, chngRowid, 1, -1, 0);
+ sqlite3CompleteInsertion(pParse, pTab, iCur, aRegIdx, chngRowid, 1, -1, 0);
}
/* Increment the row counter
/* Close all tables */
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
- if( openAll || aIdxUsed[i] ){
+ if( openAll || aRegIdx[i]>0 ){
sqlite3VdbeAddOp2(v, OP_Close, iCur+i+1, 0);
}
}
update_cleanup:
sqlite3AuthContextPop(&sContext);
- sqlite3_free(apIdx);
+ sqlite3_free(aRegIdx);
sqlite3_free(aXRef);
sqlite3SrcListDelete(pTabList);
sqlite3ExprListDelete(pChanges);
** 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.687 2008/01/07 19:20:25 drh Exp $
+** $Id: vdbe.c,v 1.688 2008/01/08 02:57:56 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
pOut = &p->aMem[pOp->p2];
}
}
+ }else if( (opProperty & OPFLG_IN2)!=0 ){
+ assert( pOp->p2>=0 );
+ if( pOp->p2==0 ){
+ pIn2 = pTos;
+ nPop = 1;
+ }else{
+ assert( pOp->p2<=p->nMem );
+ pIn2 = &p->aMem[pOp->p2];
+ REGISTER_TRACE(pOp->p2, pIn2);
+ }
+ }else if( (opProperty & OPFLG_IN3)!=0 ){
+ assert( pOp->p3>=0 );
+ if( pOp->p3==0 ){
+ pIn3 = pTos;
+ nPop = 1;
+ }else{
+ assert( pOp->p3<=p->nMem );
+ pIn3 = &p->aMem[pOp->p3];
+ REGISTER_TRACE(pOp->p3, pIn3);
+ }
}
switch( pOp->opcode ){
break;
}
-/* Opcode: IdxInsert P1 P2 *
+/* Opcode: IdxInsert P1 P2 P3
**
-** The top of the stack holds a SQL index key made using either the
-** MakeIdxRec or MakeRecord instructions. This opcode writes that key
+** Register P2 holds a SQL index key made using the
+** MakeIdxRec instructions. This opcode writes that key
** into the index P1. Data for the entry is nil.
**
-** P2 is a flag that provides a hint to the b-tree layer that this
+** P3 is a flag that provides a hint to the b-tree layer that this
** insert is likely to be an append.
**
** This instruction only works for indices. The equivalent instruction
** for tables is OP_Insert.
*/
-case OP_IdxInsert: { /* no-push */
+case OP_IdxInsert: { /* no-push, in2 */
int i = pOp->p1;
Cursor *pC;
BtCursor *pCrsr;
- assert( pTos>=p->aStack );
assert( i>=0 && i<p->nCursor );
assert( p->apCsr[i]!=0 );
- assert( pTos->flags & MEM_Blob );
+ assert( pIn2->flags & MEM_Blob );
if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
assert( pC->isTable==0 );
- rc = ExpandBlob(pTos);
+ rc = ExpandBlob(pIn2);
if( rc==SQLITE_OK ){
- int nKey = pTos->n;
- const char *zKey = pTos->z;
- rc = sqlite3BtreeInsert(pCrsr, zKey, nKey, "", 0, 0, pOp->p2);
+ int nKey = pIn2->n;
+ const char *zKey = pIn2->z;
+ rc = sqlite3BtreeInsert(pCrsr, zKey, nKey, "", 0, 0, pOp->p3);
assert( pC->deferredMoveto==0 );
pC->cacheStatus = CACHE_STALE;
}
}
- Release(pTos);
- pTos--;
break;
}
-/* Opcode: IdxDelete P1 * *
+/* Opcode: IdxDelete P1 P2 *
**
-** The top of the stack is an index key built using the either the
-** MakeIdxRec or MakeRecord opcodes.
-** This opcode removes that entry from the index.
+** The content of register P2 is an index key built using the either the
+** MakeIdxRec opcode. Removes that entry from the index.
*/
-case OP_IdxDelete: { /* no-push */
+case OP_IdxDelete: { /* no-push, in2 */
int i = pOp->p1;
Cursor *pC;
BtCursor *pCrsr;
- assert( pTos>=p->aStack );
- assert( pTos->flags & MEM_Blob );
+ assert( pIn2->flags & MEM_Blob );
assert( i>=0 && i<p->nCursor );
assert( p->apCsr[i]!=0 );
if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
int res;
- rc = sqlite3BtreeMoveto(pCrsr, pTos->z, pTos->n, 0, &res);
+ rc = sqlite3BtreeMoveto(pCrsr, pIn2->z, pIn2->n, 0, &res);
if( rc==SQLITE_OK && res==0 ){
rc = sqlite3BtreeDelete(pCrsr);
}
assert( pC->deferredMoveto==0 );
pC->cacheStatus = CACHE_STALE;
}
- Release(pTos);
- pTos--;
break;
}
pMem++;
pMem->flags = MEM_Null; /* Comment */
+#ifdef SQLITE_DEBUG
if( pOp->zComment ){
pMem->flags = MEM_Str|MEM_Term;
pMem->z = pOp->zComment;
pMem->n = strlen(pMem->z);
pMem->enc = SQLITE_UTF8;
}
+#endif
}
p->nResColumn = 8 - 5*(p->explain-1);
}
pFrom->flags = MEM_Null;
pFrom->xDel = 0;
- if( pTo->flags & MEM_Ephem ){
+ if( 0 /* pTo->flags & MEM_Ephem */ ){
rc = sqlite3VdbeMemMakeWriteable(pTo);
}else{
rc = SQLITE_OK;