aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2018-01-11 18:15:40 +0000
committerdrh <drh@noemail.net>2018-01-11 18:15:40 +0000
commitafd4eef575eecf2f29fd9c3efa53e23f424fa0a1 (patch)
tree2f4c8cf58ba3773d06e60c5d94ce14bc86046d1a /src
parent66a3a91aa6ddc324dd396f0efc475f552c89c9cd (diff)
parent6f390beb7f96774e81420548ef0be7c16567bca1 (diff)
downloadsqlite-afd4eef575eecf2f29fd9c3efa53e23f424fa0a1.tar.gz
sqlite-afd4eef575eecf2f29fd9c3efa53e23f424fa0a1.zip
Add the sqlite3_vtab_nochange() interface. Test cases are in TH3.
FossilOrigin-Name: a5d09dfaa337fa51d6e702c6aefe58824ab1e7d221c6e79166e2c6f9c7ab1501
Diffstat (limited to 'src')
-rw-r--r--src/sqlite.h.in12
-rw-r--r--src/update.c2
-rw-r--r--src/vdbe.c15
-rw-r--r--src/vdbeInt.h1
-rw-r--r--src/vdbeapi.c19
5 files changed, 44 insertions, 5 deletions
diff --git a/src/sqlite.h.in b/src/sqlite.h.in
index f63b02931..ba673748e 100644
--- a/src/sqlite.h.in
+++ b/src/sqlite.h.in
@@ -8298,6 +8298,18 @@ int sqlite3_vtab_config(sqlite3*, int op, ...);
int sqlite3_vtab_on_conflict(sqlite3 *);
/*
+** CAPI3REF: Determine If Virtual Table Column Access Is For UPDATE
+**
+** If the sqlite3_vtab_nochange(X) routine is called within the [xColumn]
+** method of a [virtual table], then it returns true if and only if the
+** column is being fetched as part of an UPDATE operation during which the
+** column value will not change. Applications might use this to substitute
+** a lighter-weight value to return that the corresponding [xUpdate] method
+** understands as a "no-change" value.
+*/
+int sqlite3_vtab_nochange(sqlite3_context*);
+
+/*
** CAPI3REF: Determine The Collation For a Virtual Table Constraint
**
** This function may only be called from within a call to the [xBestIndex]
diff --git a/src/update.c b/src/update.c
index 3e9d11bbf..3de36fe21 100644
--- a/src/update.c
+++ b/src/update.c
@@ -827,7 +827,7 @@ static void updateVirtualTable(
if( aXRef[i]>=0 ){
sqlite3ExprCode(pParse, pChanges->a[aXRef[i]].pExpr, regArg+2+i);
}else{
- sqlite3VdbeAddOp3(v, OP_VColumn, iCsr, i, regArg+2+i);
+ sqlite3VdbeAddOp4Int(v, OP_VColumn, iCsr, i, regArg+2+i, 1);
}
}
if( HasRowid(pTab) ){
diff --git a/src/vdbe.c b/src/vdbe.c
index 4d643d726..b00174bb1 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -6693,12 +6693,18 @@ case OP_VFilter: { /* jump */
#endif /* SQLITE_OMIT_VIRTUALTABLE */
#ifndef SQLITE_OMIT_VIRTUALTABLE
-/* Opcode: VColumn P1 P2 P3 * *
+/* Opcode: VColumn P1 P2 P3 P4 *
** Synopsis: r[P3]=vcolumn(P2)
**
-** Store the value of the P2-th column of
-** the row of the virtual-table that the
-** P1 cursor is pointing to into register P3.
+** Store in register P3 the value of the P2-th column of
+** the current row of the virtual-table of cursor P1.
+**
+** If the VColumn opcode is being used to fetch the value of
+** an unchanging column during an UPDATE operation, then the P4
+** value is 1. Otherwise, P4 is 0. The P4 value is returned
+** by sqlite3_vtab_nochange() routine can can be used
+** by virtual table implementations to return special "no-change"
+** marks which can be more efficient, depending on the virtual table.
*/
case OP_VColumn: {
sqlite3_vtab *pVtab;
@@ -6720,6 +6726,7 @@ case OP_VColumn: {
assert( pModule->xColumn );
memset(&sContext, 0, sizeof(sContext));
sContext.pOut = pDest;
+ sContext.bVtabNoChng = pOp->p4.i!=0;
MemSetTypeFlag(pDest, MEM_Null);
rc = pModule->xColumn(pCur->uc.pVCur, &sContext, pOp->p2);
sqlite3VtabImportErrmsg(p, pVtab);
diff --git a/src/vdbeInt.h b/src/vdbeInt.h
index cb783653c..f646a4036 100644
--- a/src/vdbeInt.h
+++ b/src/vdbeInt.h
@@ -318,6 +318,7 @@ struct sqlite3_context {
int isError; /* Error code returned by the function. */
u8 skipFlag; /* Skip accumulator loading if true */
u8 fErrorOrAux; /* isError!=0 or pVdbe->pAuxData modified */
+ u8 bVtabNoChng; /* Fetching an unchanging column in a vtab UPDATE */
u8 argc; /* Number of arguments */
sqlite3_value *argv[1]; /* Argument set */
};
diff --git a/src/vdbeapi.c b/src/vdbeapi.c
index b9df40b8f..19aa783bb 100644
--- a/src/vdbeapi.c
+++ b/src/vdbeapi.c
@@ -746,6 +746,25 @@ sqlite3 *sqlite3_context_db_handle(sqlite3_context *p){
}
/*
+** If this routine is invoked from within an xColumn method of a virtual
+** table, then it returns true if and only if the the call is during an
+** UPDATE operation and the value of the column will not be modified
+** by the UPDATE.
+**
+** If this routine is called from any context other than within the
+** xColumn method of a virtual table, then the return value is meaningless
+** and arbitrary.
+**
+** Virtual table implements might use this routine to optimize their
+** performance by substituting a NULL result, or some other light-weight
+** value, as a signal to the xUpdate routine that the column is unchanged.
+*/
+int sqlite3_vtab_nochange(sqlite3_context *p){
+ assert( p );
+ return p->bVtabNoChng;
+}
+
+/*
** Return the current time for a statement. If the current time
** is requested more than once within the same run of a single prepared
** statement, the exact same time is returned for each invocation regardless