aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2013-10-31 20:34:06 +0000
committerdrh <drh@noemail.net>2013-10-31 20:34:06 +0000
commit313619f5725632e4ea69b5f5d2b4ba9a50a31c3a (patch)
tree6c1679eac506105f99099c3057fbf1c1449ee7da /src
parentee0ec8e1db6049e6c38c94fa08201ca73ef3f60a (diff)
downloadsqlite-313619f5725632e4ea69b5f5d2b4ba9a50a31c3a.tar.gz
sqlite-313619f5725632e4ea69b5f5d2b4ba9a50a31c3a.zip
Fix the Synopsis on OP_Concat. Added test_addop_breakpoint() during
SQLITE_DEBUG. Enhanced sqlite3VdbeChangeToNoop() to omit the instruction if it is the most recent added. Continue to fix problems with UPDATE and WITHOUT ROWID. FossilOrigin-Name: 9b6d9e106aaa3c2efb33d234d26cf08cd3c967b9
Diffstat (limited to 'src')
-rw-r--r--src/delete.c8
-rw-r--r--src/expr.c4
-rw-r--r--src/update.c45
-rw-r--r--src/vdbe.c2
-rw-r--r--src/vdbeaux.c13
5 files changed, 47 insertions, 25 deletions
diff --git a/src/delete.c b/src/delete.c
index 4d27f98f9..55688409b 100644
--- a/src/delete.c
+++ b/src/delete.c
@@ -407,7 +407,7 @@ void sqlite3DeleteFrom(
/* Delete the row */
sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
- iPk, nPk, 1, OE_Default);
+ iPk, 0, 1, OE_Default);
/* End of the delete loop */
sqlite3VdbeAddOp2(v, OP_Next, iEph, addr+1);
@@ -537,7 +537,9 @@ delete_from_cleanup:
** cursor number iIdxCur+i for the i-th index.
**
** 3. The primary key for the row to be deleted must be stored in a
-** sequence of nPk memory cells starting at iPk.
+** sequence of nPk memory cells starting at iPk. If nPk==0 that means
+** that a search record formed from OP_MakeRecord is contained in the
+** single memory location iPk.
*/
void sqlite3GenerateRowDelete(
Parse *pParse, /* Parsing context */
@@ -669,6 +671,7 @@ void sqlite3GenerateRowIndexDelete(
Index *pPk; /* PRIMARY KEY index, or NULL for rowid tables */
v = pParse->pVdbe;
+ VdbeModuleComment((v, "BEGIN: GenRowIdxDel(%d,%d)", iDataCur, iIdxCur));
pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
for(i=0, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
assert( iIdxCur+i!=iDataCur || pPk==pIdx );
@@ -679,6 +682,7 @@ void sqlite3GenerateRowIndexDelete(
pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn);
sqlite3VdbeResolveLabel(v, iPartIdxLabel);
}
+ VdbeModuleComment((v, "END: GenRowIdxDel()"));
}
/*
diff --git a/src/expr.c b/src/expr.c
index 24d866f19..4a321dbc4 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -2214,9 +2214,9 @@ static void sqlite3ExprCachePinRegister(Parse *pParse, int iReg){
void sqlite3ExprCodeGetColumnOfTable(
Vdbe *v, /* The VDBE under construction */
Table *pTab, /* The table containing the value */
- int iTabCur, /* The cursor for this table */
+ int iTabCur, /* The table cursor. Or the PK cursor for WITHOUT ROWID */
int iCol, /* Index of the column to extract */
- int regOut /* Extract the valud into this register */
+ int regOut /* Extract the value into this register */
){
if( iCol<0 || iCol==pTab->iPKey ){
sqlite3VdbeAddOp2(v, OP_Rowid, iTabCur, regOut);
diff --git a/src/update.c b/src/update.c
index 5c92f6fd6..c06fcd2a0 100644
--- a/src/update.c
+++ b/src/update.c
@@ -101,7 +101,6 @@ void sqlite3Update(
Index *pIdx; /* For looping over indices */
Index *pPk; /* The PRIMARY KEY index for WITHOUT ROWID tables */
int nIdx; /* Number of indices that need updating */
- int iTabCur; /* VDBE Cursor number of pTab */
int iDataCur; /* Cursor for the canonical data btree */
int iIdxCur; /* Cursor for the first index */
sqlite3 *db; /* The database structure */
@@ -182,11 +181,14 @@ void sqlite3Update(
** need to occur right after the database cursor. So go ahead and
** allocate enough space, just in case.
*/
- pTabList->a[0].iCursor = iTabCur = iDataCur = pParse->nTab++;
- iIdxCur = iTabCur+1;
+ pTabList->a[0].iCursor = iDataCur = pParse->nTab++;
+ iIdxCur = iDataCur+1;
pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){
- if( pIdx->autoIndex==2 && pPk!=0 ) iDataCur = pParse->nTab;
+ if( pIdx->autoIndex==2 && pPk!=0 ){
+ iDataCur = pParse->nTab;
+ pTabList->a[0].iCursor = iDataCur;
+ }
pParse->nTab++;
}
@@ -199,9 +201,11 @@ void sqlite3Update(
** of the UPDATE statement. Also find the column index
** for each column to be updated in the pChanges array. For each
** column to be updated, make sure we have authorization to change
- ** that column.
+ ** that column. Set chngPk if the iDataCur key changes. Note that
+ ** for WITHOUT ROWID columns, the iDataCur key contains all columns of
+ ** the table and so it will always change.
*/
- chngPk = 0;
+ chngPk = (pPk!=0);
for(i=0; i<pChanges->nExpr; i++){
if( sqlite3ResolveExprNames(&sNC, pChanges->a[i].pExpr) ){
goto update_cleanup;
@@ -211,8 +215,6 @@ void sqlite3Update(
if( j==pTab->iPKey ){
chngPk = 1;
pRowidExpr = pChanges->a[i].pExpr;
- }else if( pPk && (pTab->aCol[j].colFlags & COLFLAG_PRIMKEY)!=0 ){
- chngPk = 1;
}
aXRef[j] = i;
break;
@@ -311,7 +313,7 @@ void sqlite3Update(
*/
#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
if( isView ){
- sqlite3MaterializeView(pParse, pTab, pWhere, iTabCur);
+ sqlite3MaterializeView(pParse, pTab, pWhere, iDataCur);
}
#endif
@@ -334,7 +336,7 @@ void sqlite3Update(
/* Remember the rowid of every item to be updated.
*/
- sqlite3VdbeAddOp2(v, OP_Rowid, iTabCur, regOldRowid);
+ sqlite3VdbeAddOp2(v, OP_Rowid, iDataCur, regOldRowid);
if( !okOnePass ){
sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, regOldRowid);
}
@@ -383,7 +385,7 @@ void sqlite3Update(
** to be deleting some records.
*/
if( !okOnePass && HasRowid(pTab) ){
- sqlite3OpenTable(pParse, iTabCur, iDb, pTab, OP_OpenWrite);
+ sqlite3OpenTable(pParse, iDataCur, iDb, pTab, OP_OpenWrite);
}
if( onError==OE_Replace ){
openAll = 1;
@@ -403,6 +405,7 @@ void sqlite3Update(
sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdxCur+i, pIdx->tnum, iDb,
(char*)pKey, P4_KEYINFO_HANDOFF);
assert( pParse->nTab>iIdxCur+i );
+ VdbeComment((v, "%s", pIdx->zName));
}
}
}
@@ -413,7 +416,7 @@ void sqlite3Update(
if( pPk ){
sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak);
addr = sqlite3VdbeAddOp2(v, OP_RowKey, iEph, regKey);
- sqlite3VdbeAddOp3(v, OP_NotFound, iEph, labelContinue, regKey);
+ sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue, regKey, 0);
}else if( okOnePass ){
int a1 = sqlite3VdbeAddOp1(v, OP_NotNull, regOldRowid);
addr = sqlite3VdbeAddOp2(v, OP_Goto, 0, labelBreak);
@@ -429,7 +432,7 @@ void sqlite3Update(
** then regNewRowid is the same register as regOldRowid, which is
** already populated. */
assert( chngPk || pTrigger || hasFK || regOldRowid==regNewRowid );
- if( chngPk ){
+ if( chngPk && pPk==0 ){
sqlite3ExprCode(pParse, pRowidExpr, regNewRowid);
sqlite3VdbeAddOp1(v, OP_MustBeInt, regNewRowid);
}
@@ -485,8 +488,7 @@ void sqlite3Update(
*/
testcase( i==31 );
testcase( i==32 );
- sqlite3VdbeAddOp3(v, OP_Column, iDataCur, i, regNew+i);
- sqlite3ColumnDefault(v, pTab, i, regNew+i);
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regNew+i);
}
}
}
@@ -515,8 +517,7 @@ void sqlite3Update(
*/
for(i=0; i<pTab->nCol; i++){
if( aXRef[i]<0 && i!=pTab->iPKey ){
- sqlite3VdbeAddOp3(v, OP_Column, iDataCur, i, regNew+i);
- sqlite3ColumnDefault(v, pTab, i, regNew+i);
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regNew+i);
}
}
}
@@ -535,17 +536,21 @@ void sqlite3Update(
/* Delete the index entries associated with the current record. */
if( pPk ){
- j1 = sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, 0, regOldRowid, 1);
+ j1 = sqlite3VdbeAddOp3(v, OP_NotFound, iDataCur, 0, regOldRowid);
}else{
j1 = sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, 0, regOldRowid);
- sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, aRegIdx);
}
+ sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, aRegIdx);
/* If changing the record number, delete the old record. */
if( hasFK || chngPk ){
sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, 0);
}
- sqlite3VdbeJumpHere(v, j1);
+ if( sqlite3VdbeCurrentAddr(v)==j1+1 ){
+ sqlite3VdbeChangeToNoop(v, j1);
+ }else{
+ sqlite3VdbeJumpHere(v, j1);
+ }
if( hasFK ){
sqlite3FkCheck(pParse, pTab, 0, regNewRowid, aXRef, chngPk);
diff --git a/src/vdbe.c b/src/vdbe.c
index 2f648a76a..b72ef40ca 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -1203,7 +1203,7 @@ case OP_ResultRow: {
}
/* Opcode: Concat P1 P2 P3 * *
-** Synopsis: r[P3]=r[P2]+r[P3]
+** Synopsis: r[P3]=r[P2]+r[P1]
**
** Add the text in register P1 onto the end of the text in
** register P2 and store the result in register P3.
diff --git a/src/vdbeaux.c b/src/vdbeaux.c
index e2ef4eee1..8a1eea1b8 100644
--- a/src/vdbeaux.c
+++ b/src/vdbeaux.c
@@ -107,6 +107,17 @@ static int growOpArray(Vdbe *p){
return (pNew ? SQLITE_OK : SQLITE_NOMEM);
}
+#ifdef SQLITE_DEBUG
+/* This routine is just a convenient place to set a breakpoint that will
+** fire after each opcode is inserted and displayed using
+** "PRAGMA vdbe_addoptrace=on".
+*/
+static void test_addop_breakpoint(void){
+ static int n = 0;
+ n++;
+}
+#endif
+
/*
** Add a new instruction to the list of instructions current in the
** VDBE. Return the address of the new instruction.
@@ -150,6 +161,7 @@ int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
#ifdef SQLITE_DEBUG
if( p->db->flags & SQLITE_VdbeAddopTrace ){
sqlite3VdbePrintOp(0, i, &p->aOp[i]);
+ test_addop_breakpoint();
}
#endif
#ifdef VDBE_PROFILE
@@ -695,6 +707,7 @@ void sqlite3VdbeChangeToNoop(Vdbe *p, int addr){
freeP4(db, pOp->p4type, pOp->p4.p);
memset(pOp, 0, sizeof(pOp[0]));
pOp->opcode = OP_Noop;
+ if( addr==p->nOp-1 ) p->nOp--;
}
}