aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/insert.c73
-rw-r--r--src/pragma.c5
-rw-r--r--src/sqliteInt.h2
-rw-r--r--src/vdbeaux.c6
-rw-r--r--src/vdbeblob.c22
5 files changed, 68 insertions, 40 deletions
diff --git a/src/insert.c b/src/insert.c
index cbe933c22..5f36c089f 100644
--- a/src/insert.c
+++ b/src/insert.c
@@ -254,7 +254,6 @@ void sqlite3AutoincrementBegin(Parse *pParse){
sqlite3 *db = pParse->db; /* The database connection */
Db *pDb; /* Database only autoinc table */
int memId; /* Register holding max rowid */
- int addr; /* A VDBE address */
Vdbe *v = pParse->pVdbe; /* VDBE under construction */
/* This routine is never called during trigger-generation. It is
@@ -264,33 +263,46 @@ void sqlite3AutoincrementBegin(Parse *pParse){
assert( v ); /* We failed long ago if this is not so */
for(p = pParse->pAinc; p; p = p->pNext){
+ static const int iLn = VDBE_OFFSET_LINENO(2);
+ static const VdbeOpList autoInc[] = {
+ /* 0 */ {OP_Null, 0, 0, 0},
+ /* 1 */ {OP_Rewind, 0, 9, 0},
+ /* 2 */ {OP_Column, 0, 0, 0},
+ /* 3 */ {OP_Ne, 0, 7, 0},
+ /* 4 */ {OP_Rowid, 0, 0, 0},
+ /* 5 */ {OP_Column, 0, 1, 0},
+ /* 6 */ {OP_Goto, 0, 9, 0},
+ /* 7 */ {OP_Next, 0, 2, 0},
+ /* 8 */ {OP_Integer, 0, 0, 0},
+ /* 9 */ {OP_Close, 0, 0, 0}
+ };
+ VdbeOp *aOp;
pDb = &db->aDb[p->iDb];
memId = p->regCtr;
assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) );
sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenRead);
- sqlite3VdbeAddOp3(v, OP_Null, 0, memId, memId+1);
- addr = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeLoadString(v, memId-1, p->pTab->zName);
- sqlite3VdbeAddOp2(v, OP_Rewind, 0, addr+9); VdbeCoverage(v);
- sqlite3VdbeAddOp3(v, OP_Column, 0, 0, memId);
- sqlite3VdbeAddOp3(v, OP_Ne, memId-1, addr+7, memId); VdbeCoverage(v);
- sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL);
- sqlite3VdbeAddOp2(v, OP_Rowid, 0, memId+1);
- sqlite3VdbeAddOp3(v, OP_Column, 0, 1, memId);
- sqlite3VdbeGoto(v, addr+9);
- sqlite3VdbeAddOp2(v, OP_Next, 0, addr+2); VdbeCoverage(v);
- sqlite3VdbeAddOp2(v, OP_Integer, 0, memId);
- sqlite3VdbeAddOp0(v, OP_Close);
+ aOp = sqlite3VdbeAddOpList(v, ArraySize(autoInc), autoInc, iLn);
+ if( aOp==0 ) break;
+ aOp[0].p2 = memId;
+ aOp[0].p3 = memId+1;
+ aOp[2].p3 = memId;
+ aOp[3].p1 = memId-1;
+ aOp[3].p3 = memId;
+ aOp[3].p5 = SQLITE_JUMPIFNULL;
+ aOp[4].p2 = memId+1;
+ aOp[5].p3 = memId;
+ aOp[8].p2 = memId;
}
}
/*
** Update the maximum rowid for an autoincrement calculation.
**
-** This routine should be called when the top of the stack holds a
+** This routine should be called when the regRowid register holds a
** new rowid that is about to be inserted. If that new rowid is
** larger than the maximum rowid in the memId memory cell, then the
-** memory cell is updated. The stack is unchanged.
+** memory cell is updated.
*/
static void autoIncStep(Parse *pParse, int memId, int regRowid){
if( memId>0 ){
@@ -305,31 +317,44 @@ static void autoIncStep(Parse *pParse, int memId, int regRowid){
** table (either directly or through triggers) needs to call this
** routine just before the "exit" code.
*/
-void sqlite3AutoincrementEnd(Parse *pParse){
+static SQLITE_NOINLINE void autoIncrementEnd(Parse *pParse){
AutoincInfo *p;
Vdbe *v = pParse->pVdbe;
sqlite3 *db = pParse->db;
assert( v );
for(p = pParse->pAinc; p; p = p->pNext){
+ static const int iLn = VDBE_OFFSET_LINENO(2);
+ static const VdbeOpList autoIncEnd[] = {
+ /* 0 */ {OP_NotNull, 0, 2, 0},
+ /* 1 */ {OP_NewRowid, 0, 0, 0},
+ /* 2 */ {OP_MakeRecord, 0, 2, 0},
+ /* 3 */ {OP_Insert, 0, 0, 0},
+ /* 4 */ {OP_Close, 0, 0, 0}
+ };
+ VdbeOp *aOp;
Db *pDb = &db->aDb[p->iDb];
- int addr1;
int iRec;
int memId = p->regCtr;
iRec = sqlite3GetTempReg(pParse);
assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) );
sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenWrite);
- addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, memId+1); VdbeCoverage(v);
- sqlite3VdbeAddOp2(v, OP_NewRowid, 0, memId+1);
- sqlite3VdbeJumpHere(v, addr1);
- sqlite3VdbeAddOp3(v, OP_MakeRecord, memId-1, 2, iRec);
- sqlite3VdbeAddOp3(v, OP_Insert, 0, iRec, memId+1);
- sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
- sqlite3VdbeAddOp0(v, OP_Close);
+ aOp = sqlite3VdbeAddOpList(v, ArraySize(autoIncEnd), autoIncEnd, iLn);
+ if( aOp==0 ) break;
+ aOp[0].p1 = memId+1;
+ aOp[1].p2 = memId+1;
+ aOp[2].p1 = memId-1;
+ aOp[2].p3 = iRec;
+ aOp[3].p2 = iRec;
+ aOp[3].p3 = memId+1;
+ aOp[3].p5 = OPFLAG_APPEND;
sqlite3ReleaseTempReg(pParse, iRec);
}
}
+void sqlite3AutoincrementEnd(Parse *pParse){
+ if( pParse->pAinc ) autoIncrementEnd(pParse);
+}
#else
/*
** If SQLITE_OMIT_AUTOINCREMENT is defined, then the three routines
diff --git a/src/pragma.c b/src/pragma.c
index 1d827d7b7..c62c8d2af 100644
--- a/src/pragma.c
+++ b/src/pragma.c
@@ -1599,16 +1599,15 @@ void sqlite3Pragma(
static const int iLn = VDBE_OFFSET_LINENO(2);
static const VdbeOpList endCode[] = {
{ OP_AddImm, 1, 0, 0}, /* 0 */
- { OP_If, 1, 0, 0}, /* 1 */
+ { OP_If, 1, 4, 0}, /* 1 */
{ OP_String8, 0, 3, 0}, /* 2 */
- { OP_ResultRow, 3, 1, 0},
+ { OP_ResultRow, 3, 1, 0}, /* 3 */
};
VdbeOp *aOp;
aOp = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode, iLn);
if( aOp ){
aOp[0].p2 = -mxErr;
- aOp[1].p2 = sqlite3VdbeCurrentAddr(v);
aOp[2].p4type = P4_STATIC;
aOp[2].p4.z = "ok";
}
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index dbe1595af..c18e83726 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -2641,7 +2641,7 @@ struct SelectDest {
** tables, the following information is attached to the Table.u.autoInc.p
** pointer of each autoincrement table to record some side information that
** the code generator needs. We have to keep per-table autoincrement
-** information in case inserts are down within triggers. Triggers do not
+** information in case inserts are done within triggers. Triggers do not
** normally coordinate their activities, but we do need to coordinate the
** loading and saving of autoincrement information.
*/
diff --git a/src/vdbeaux.c b/src/vdbeaux.c
index 13aef0d7f..632c1231a 100644
--- a/src/vdbeaux.c
+++ b/src/vdbeaux.c
@@ -646,6 +646,9 @@ VdbeOp *sqlite3VdbeTakeOpArray(Vdbe *p, int *pnOp, int *pnMaxArg){
/*
** Add a whole list of operations to the operation stack. Return a
** pointer to the first operation inserted.
+**
+** Non-zero P2 arguments to jump instructions are automatically adjusted
+** so that the jump target is relative to the first operation inserted.
*/
VdbeOp *sqlite3VdbeAddOpList(
Vdbe *p, /* Add opcodes to the prepared statement */
@@ -666,6 +669,9 @@ VdbeOp *sqlite3VdbeAddOpList(
pOut->p1 = aOp->p1;
pOut->p2 = aOp->p2;
assert( aOp->p2>=0 );
+ if( (sqlite3OpcodeProperty[aOp->opcode] & OPFLG_JUMP)!=0 && aOp->p2>0 ){
+ pOut->p2 += p->nOp;
+ }
pOut->p3 = aOp->p3;
pOut->p4type = P4_NOTUSED;
pOut->p4.p = 0;
diff --git a/src/vdbeblob.c b/src/vdbeblob.c
index f9015ad6f..2ba5301e7 100644
--- a/src/vdbeblob.c
+++ b/src/vdbeblob.c
@@ -249,19 +249,17 @@ int sqlite3_blob_open(
** which closes the b-tree cursor and (possibly) commits the
** transaction.
*/
- static const int iLn = VDBE_OFFSET_LINENO(4);
+ static const int iLn = VDBE_OFFSET_LINENO(2);
static const VdbeOpList openBlob[] = {
- /* addr/ofst */
- /* {OP_Transaction, 0, 0, 0}, // 0/ inserted separately */
- {OP_TableLock, 0, 0, 0}, /* 1/0: Acquire a read or write lock */
- {OP_OpenRead, 0, 0, 0}, /* 2/1: Open a cursor */
- {OP_Variable, 1, 1, 0}, /* 3/2: Move ?1 into reg[1] */
- {OP_NotExists, 0, 8, 1}, /* 4/3: Seek the cursor */
- {OP_Column, 0, 0, 1}, /* 5/4 */
- {OP_ResultRow, 1, 0, 0}, /* 6/5 */
- {OP_Goto, 0, 3, 0}, /* 7/6 */
- {OP_Close, 0, 0, 0}, /* 8/7 */
- {OP_Halt, 0, 0, 0}, /* 9/8 */
+ {OP_TableLock, 0, 0, 0}, /* 0: Acquire a read or write lock */
+ {OP_OpenRead, 0, 0, 0}, /* 1: Open a cursor */
+ {OP_Variable, 1, 1, 0}, /* 2: Move ?1 into reg[1] */
+ {OP_NotExists, 0, 7, 1}, /* 3: Seek the cursor */
+ {OP_Column, 0, 0, 1}, /* 4 */
+ {OP_ResultRow, 1, 0, 0}, /* 5 */
+ {OP_Goto, 0, 2, 0}, /* 6 */
+ {OP_Close, 0, 0, 0}, /* 7 */
+ {OP_Halt, 0, 0, 0}, /* 8 */
};
Vdbe *v = (Vdbe *)pBlob->pStmt;
int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);