Add the sqlite3_vtab_nochange() method which virtual table implementations
can use to optimize UPDATEs.

FossilOrigin-Name: d444b1ff39f0a1673a977b8047e1e14a49d461c9934be080d27c2392a830c1c0
diff --git a/manifest b/manifest
index ee79e40..977b35b 100644
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Minor\sformatting\schanges\sin\szipfile.c.\s\sNo\slogical\scode\sdifferences.
-D 2018-01-11T14:50:40.176
+C Add\sthe\ssqlite3_vtab_nochange()\smethod\swhich\svirtual\stable\simplementations\ncan\suse\sto\soptimize\sUPDATEs.
+D 2018-01-11T17:04:26.957
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F Makefile.in 38f84f301cbef443b2d269f67a74b8cc536469831f70df7c3e912acc04932cc2
@@ -485,7 +485,7 @@
 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
 F src/select.c 8b22abe193e4d8243befa2038e4ae2405802fed1c446e5e502d11f652e09ba74
 F src/shell.c.in b87abffd0db09203ad8a133d56fe8f154ace5ec0a14197a153fb7d80b1438c01
-F src/sqlite.h.in 1f1a2da222ec57465794e8984d77f32d0bd0da80cdc136beadda461a0be9d80c
+F src/sqlite.h.in f83e63a48fb31fefc69c83bbe8700b4b44acdd64e440219087b0f14e35eeb8d4
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
 F src/sqlite3ext.h c02d628cca67f3889c689d82d25c3eb45e2c155db08e4c6089b5840d64687d34
 F src/sqliteInt.h fd8702c65994d7de3e2d8f7d85d958731da1ed29476571fdfa2290fd8ec0bf80
@@ -548,14 +548,14 @@
 F src/tokenize.c 5b0c661a85f783d35b9883830736eeb63be4aefc4f6b7d9cd081d48782c041e2
 F src/treeview.c eae35972ff44f67064de2eaf35f04afe94e7aea3271a8b3bcebb3f954880fec3
 F src/trigger.c a34539c69433276d37b0da9a89c117726ff2d292c0902895af1f393a983cd3a1
-F src/update.c f75a8bf497219fa0c4ba9293022db64cca13e457e33d62f58306f107327506ac
+F src/update.c 8bd52c38d6d426925be4488ee106db26d9ee344406315671ed246ddace8d6091
 F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5
 F src/util.c 7315e97a8dc2c8e19ca64196c652cf0a65d13fd0a211b2cec082062372dc6261
 F src/vacuum.c 90839322fd5f00df9617eb21b68beda9b6e2a2937576b0d65985e4aeb1c53739
-F src/vdbe.c c70267613df80345ed9bbd9c249c365b53bb9cbbe9d3e78e6d5c049d00ef5501
+F src/vdbe.c 4d0666741d884dfaceb6ac5bbededbd947068e4b742163898feea84a027dace6
 F src/vdbe.h d50cadf12bcf9fb99117ef392ce1ea283aa429270481426b6e8b0280c101fd97
-F src/vdbeInt.h 1fe00770144c12c4913128f35262d11527ef3284561baaab59b947a41c08d0d9
-F src/vdbeapi.c 9c670ca0dcc1cd86373aa353b747b26fe531ca5cd4331690c611d1f03842e2a1
+F src/vdbeInt.h a0969c14950bcc61b2dfa19c6f62b42c5012013fcda342ca927a192ed37e6592
+F src/vdbeapi.c f519346f6db99a1eb3f85ca3ae8aede9ff9c4d90fec809dae7cb946786b2e270
 F src/vdbeaux.c 7ae48b180e5dd5d282e6752d155f1ab7929196d8e6577b82742044188152ca85
 F src/vdbeblob.c f5c70f973ea3a9e915d1693278a5f890dc78594300cf4d54e64f2b0917c94191
 F src/vdbemem.c 8478f7fb1948bf8fdeec7c2cb59ea58155c31258b9cd43c56d485e03ed40bd07
@@ -1697,7 +1697,10 @@
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 2c55571baaae58d6f5b6210cf85d0fa325a9977682bd449e3802191f7a4142de
-R 33de751c900466ee2a12d260dcb2a3de
+P 4f68bed3b9a63a349a2a2d7f26609491577e9717034ad86af404cf9eed9d6aaf
+R ca3c0ce043db4afb0303f36904592ef8
+T *branch * sqlite3_vtab_nochange
+T *sym-sqlite3_vtab_nochange *
+T -sym-trunk *
 U drh
-Z 324651d5684ea52cfa823d4ea5809b01
+Z 5a280540fff60985c8c72fc104fac16d
diff --git a/manifest.uuid b/manifest.uuid
index 774aa87..3f07ede 100644
--- a/manifest.uuid
+++ b/manifest.uuid
@@ -1 +1 @@
-4f68bed3b9a63a349a2a2d7f26609491577e9717034ad86af404cf9eed9d6aaf
\ No newline at end of file
+d444b1ff39f0a1673a977b8047e1e14a49d461c9934be080d27c2392a830c1c0
\ No newline at end of file
diff --git a/src/sqlite.h.in b/src/sqlite.h.in
index f63b029..ba67374 100644
--- a/src/sqlite.h.in
+++ b/src/sqlite.h.in
@@ -8298,6 +8298,18 @@
 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 3e9d11b..3de36fe 100644
--- a/src/update.c
+++ b/src/update.c
@@ -827,7 +827,7 @@
     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 4d643d7..b00174b 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -6693,12 +6693,18 @@
 #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 @@
   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 cb78365..f646a40 100644
--- a/src/vdbeInt.h
+++ b/src/vdbeInt.h
@@ -318,6 +318,7 @@
   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 b9df40b..19aa783 100644
--- a/src/vdbeapi.c
+++ b/src/vdbeapi.c
@@ -746,6 +746,25 @@
 }
 
 /*
+** 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