aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2018-01-12 23:18:38 +0000
committerdrh <drh@noemail.net>2018-01-12 23:18:38 +0000
commit41fb367a2c5aec8973fa004ba030f2aa55bbad5c (patch)
tree59f7c66ef7c66f94056931c9f7590703eb41ab78 /src
parentce2fbd1b029477fd8745ca6381cd0b264fd901c5 (diff)
downloadsqlite-41fb367a2c5aec8973fa004ba030f2aa55bbad5c.tar.gz
sqlite-41fb367a2c5aec8973fa004ba030f2aa55bbad5c.zip
Improved comments. Slightly tighter implementation, but no big changes.
FossilOrigin-Name: a1b3f28569f2a8d82b2931527fdfe191b421f3e1ea18ee30e04211e1ad645993
Diffstat (limited to 'src')
-rw-r--r--src/sqlite.h.in9
-rw-r--r--src/sqliteInt.h1
-rw-r--r--src/update.c8
-rw-r--r--src/vdbe.c14
4 files changed, 24 insertions, 8 deletions
diff --git a/src/sqlite.h.in b/src/sqlite.h.in
index 7579b9926..cd524a046 100644
--- a/src/sqlite.h.in
+++ b/src/sqlite.h.in
@@ -4850,8 +4850,13 @@ SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),
** ^Within the [xUpdate] method of a [virtual table], the
** sqlite3_value_nochange(X) interface returns true if and only if
** the column corresponding to X is unchanged by the UPDATE operation
-** and the [xColumn] method had previously queried [sqlite3_vtab_nochange()]
-** for that column and returned a NULL as a result.
+** that the xUpdate method call was invoked to implement and if
+** and the prior [xColumn] method call that was invoked to extracted
+** the value for that column returned without setting a result (probably
+** because it queried [sqlite3_vtab_nochange()] and found that the column
+** was unchanging). If sqlite3_value_nochange(X) is invoked anywhere other
+** than within an [xUpdate] method call for an UPDATE statement, then
+** the return value is arbitrary and meaningless.
**
** Please pay particular attention to the fact that the pointer returned
** from [sqlite3_value_blob()], [sqlite3_value_text()], or
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 8e7913320..b7b402b8e 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -3117,6 +3117,7 @@ struct AuthContext {
#define OPFLAG_PERMUTE 0x01 /* OP_Compare: use the permutation */
#define OPFLAG_SAVEPOSITION 0x02 /* OP_Delete/Insert: save cursor pos */
#define OPFLAG_AUXDELETE 0x04 /* OP_Delete: index in a DELETE op */
+#define OPFLAG_NOCHNG_MAGIC 0x6d /* OP_MakeRecord: serialtype 10 is ok */
/*
* Each trigger present in the database schema is stored as an instance of
diff --git a/src/update.c b/src/update.c
index ee920d2a5..32c1a8371 100644
--- a/src/update.c
+++ b/src/update.c
@@ -828,7 +828,7 @@ static void updateVirtualTable(
sqlite3ExprCode(pParse, pChanges->a[aXRef[i]].pExpr, regArg+2+i);
}else{
sqlite3VdbeAddOp3(v, OP_VColumn, iCsr, i, regArg+2+i);
- sqlite3VdbeChangeP5(v, 1);
+ sqlite3VdbeChangeP5(v, 1); /* Enable sqlite3_vtab_nochange() */
}
}
if( HasRowid(pTab) ){
@@ -863,7 +863,11 @@ static void updateVirtualTable(
/* Create a record from the argument register contents and insert it into
** the ephemeral table. */
sqlite3VdbeAddOp3(v, OP_MakeRecord, regArg, nArg, regRec);
- sqlite3VdbeChangeP5(v, 2);
+#ifdef SQLITE_DEBUG
+ /* Signal an assert() within OP_MakeRecord that it is allowed to
+ ** accept no-change records with serial_type 10 */
+ sqlite3VdbeChangeP5(v, OPFLAG_NOCHNG_MAGIC);
+#endif
sqlite3VdbeAddOp2(v, OP_NewRowid, ephemTab, regRowid);
sqlite3VdbeAddOp3(v, OP_Insert, ephemTab, regRec, regRowid);
}
diff --git a/src/vdbe.c b/src/vdbe.c
index dc058b65f..d878ca8e3 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -2792,12 +2792,17 @@ case OP_MakeRecord: {
pRec = pLast;
do{
assert( memIsValid(pRec) );
- pRec->uTemp = serial_type = sqlite3VdbeSerialType(pRec, file_format, &len);
+ serial_type = sqlite3VdbeSerialType(pRec, file_format, &len);
if( pRec->flags & MEM_Zero ){
if( serial_type==0 ){
- assert( pOp->p5==2 || CORRUPT_DB );
- /* serial_type 10 used internally only */
- pRec->uTemp = 10;
+ /* Values with MEM_Null and MEM_Zero are created by xColumn virtual
+ ** table methods that never invoke sqlite3_result_xxxxx() while
+ ** computing an unchanging column value in an UPDATE statement.
+ ** Give such values a special internal-use-only serial-type of 10
+ ** so that they can be passed through to xUpdate and have
+ ** a true sqlite3_value_nochange(). */
+ assert( pOp->p5==OPFLAG_NOCHNG_MAGIC || CORRUPT_DB );
+ serial_type = 10;
}else if( nData ){
if( sqlite3VdbeMemExpandBlob(pRec) ) goto no_mem;
}else{
@@ -2809,6 +2814,7 @@ case OP_MakeRecord: {
testcase( serial_type==127 );
testcase( serial_type==128 );
nHdr += serial_type<=127 ? 1 : sqlite3VarintLen(serial_type);
+ pRec->uTemp = serial_type;
if( pRec==pData0 ) break;
pRec--;
}while(1);