mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-11 01:42:22 +03:00
Registerify the AUTOINCREMENT processing and the OP_IsNull and OP_NotNull
operators. (CVS 4692) FossilOrigin-Name: aa48867cfa04da265b906e5b583bc7ac6b6a1157
This commit is contained in:
186
src/insert.c
186
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 @@ static int readsTable(Vdbe *v, int iStartAddr, int iDb, Table *pTab){
|
||||
/*
|
||||
** 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 @@ static int autoIncBegin(
|
||||
** 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 @@ static void autoIncEnd(
|
||||
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 @@ void sqlite3Insert(
|
||||
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 @@ void sqlite3Insert(
|
||||
#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 @@ void sqlite3Insert(
|
||||
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 @@ void sqlite3Insert(
|
||||
*/
|
||||
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 @@ void sqlite3Insert(
|
||||
/* 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 @@ void sqlite3Insert(
|
||||
}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 @@ void sqlite3Insert(
|
||||
}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 @@ void sqlite3Insert(
|
||||
** 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 @@ void sqlite3Insert(
|
||||
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 @@ void sqlite3Insert(
|
||||
#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 @@ void sqlite3Insert(
|
||||
/* 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 @@ void sqlite3Insert(
|
||||
}
|
||||
|
||||
/* 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 @@ void sqlite3Insert(
|
||||
** 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 @@ insert_cleanup:
|
||||
}
|
||||
|
||||
/*
|
||||
** 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 @@ void sqlite3GenerateConstraintChecks(
|
||||
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 @@ static int xferOptimization(
|
||||
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 @@ static int xferOptimization(
|
||||
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 @@ static int xferOptimization(
|
||||
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 @@ static int xferOptimization(
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user