]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add the experimental sqlite3_value_nochange() interface usable by xUpdate
authordrh <drh@noemail.net>
Fri, 12 Jan 2018 21:00:14 +0000 (21:00 +0000)
committerdrh <drh@noemail.net>
Fri, 12 Jan 2018 21:00:14 +0000 (21:00 +0000)
methods of virtual tables to see if a column has actually changed values.

FossilOrigin-Name: 8b7be15ece9e2e83959bb0e21e240106fe1077431242c3cc6b81f1baa2382f40

manifest
manifest.uuid
src/sqlite.h.in
src/update.c
src/vdbe.c
src/vdbeInt.h
src/vdbeapi.c
src/vdbeaux.c
src/vdbemem.c

index d9b6cfb745c2ba5682a32995559234acabeea32d..c96606d8a917102fe71028965bddafd406ae865d 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Simplification\sto\sthe\simplementation\sof\sOP_Insert.
-D 2018-01-12T19:33:18.062
+C Add\sthe\sexperimental\ssqlite3_value_nochange()\sinterface\susable\sby\sxUpdate\nmethods\sof\svirtual\stables\sto\ssee\sif\sa\scolumn\shas\sactually\schanged\svalues.
+D 2018-01-12T21:00:14.387
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F Makefile.in 38f84f301cbef443b2d269f67a74b8cc536469831f70df7c3e912acc04932cc2
@@ -487,7 +487,7 @@ F src/resolve.c bbee7e31d369a18a2f4836644769882e9c5d40ef4a3af911db06410b65cb3730
 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
 F src/select.c 8b22abe193e4d8243befa2038e4ae2405802fed1c446e5e502d11f652e09ba74
 F src/shell.c.in b87abffd0db09203ad8a133d56fe8f154ace5ec0a14197a153fb7d80b1438c01
-F src/sqlite.h.in f83e63a48fb31fefc69c83bbe8700b4b44acdd64e440219087b0f14e35eeb8d4
+F src/sqlite.h.in 8c9b7bf8f635c13371d8060061e83d19623c77e7e4430dff7713e47761d1b972
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
 F src/sqlite3ext.h c02d628cca67f3889c689d82d25c3eb45e2c155db08e4c6089b5840d64687d34
 F src/sqliteInt.h fd8702c65994d7de3e2d8f7d85d958731da1ed29476571fdfa2290fd8ec0bf80
@@ -550,17 +550,17 @@ F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
 F src/tokenize.c 5b0c661a85f783d35b9883830736eeb63be4aefc4f6b7d9cd081d48782c041e2
 F src/treeview.c eae35972ff44f67064de2eaf35f04afe94e7aea3271a8b3bcebb3f954880fec3
 F src/trigger.c a34539c69433276d37b0da9a89c117726ff2d292c0902895af1f393a983cd3a1
-F src/update.c 8bd52c38d6d426925be4488ee106db26d9ee344406315671ed246ddace8d6091
+F src/update.c 7736ffc60d9fdfaae4e294d76158c0a9f752b369ae2b22ef9fc800d08e0bf31e
 F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5
 F src/util.c 7315e97a8dc2c8e19ca64196c652cf0a65d13fd0a211b2cec082062372dc6261
 F src/vacuum.c 90839322fd5f00df9617eb21b68beda9b6e2a2937576b0d65985e4aeb1c53739
-F src/vdbe.c e660530c799acf41616200373cdaec7af3fce5a25de40d900e8319d50971df73
+F src/vdbe.c 07dd1909ceac146717cc248838ffe2f85165e50e468e6a0c378d840c1caf6e98
 F src/vdbe.h 134beb7a12a6213c00eba58febaede33447cc4441bc568a0d9c144b33fc3720a
-F src/vdbeInt.h a0969c14950bcc61b2dfa19c6f62b42c5012013fcda342ca927a192ed37e6592
-F src/vdbeapi.c f519346f6db99a1eb3f85ca3ae8aede9ff9c4d90fec809dae7cb946786b2e270
-F src/vdbeaux.c 7d635c30e55196ee8e0af605aceab0c3036ed6d6ed55dd6639c4b2a2a4593b4f
+F src/vdbeInt.h 5442fc816b6cf19c8801724199fd6b77a02eb31a7a174021713f8c59b30e51fa
+F src/vdbeapi.c 02f773681d06e46454b0606339068d4d4490873dc4a7334bc0c6030552bb2c8c
+F src/vdbeaux.c fc124962c9900b19d201e57084a4302d07136a77f51fdbdfabd625a3ca3b6dc1
 F src/vdbeblob.c f5c70f973ea3a9e915d1693278a5f890dc78594300cf4d54e64f2b0917c94191
-F src/vdbemem.c 8478f7fb1948bf8fdeec7c2cb59ea58155c31258b9cd43c56d485e03ed40bd07
+F src/vdbemem.c 7548dd5af03d24d534a5dbc41e3bbdf1fab83e9c8856a8d2549ed2ccf33d0e80
 F src/vdbesort.c 731a09e5cb9e96b70c394c1b7cf3860fbe84acca7682e178615eb941a3a0ef2f
 F src/vdbetrace.c 48e11ebe040c6b41d146abed2602e3d00d621d7ebe4eb29b0a0f1617fd3c2f6c
 F src/vtab.c 0e4885495172e1bdf54b12cce23b395ac74ef5729031f15e1bc1e3e6b360ed1a
@@ -1699,7 +1699,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 874285e477dd9bd164e25ddb08b6b80daaa8cfd111b4180ecce59b1ce26f77a5
-R 0ce0db05c5816c8a3f6d5399a0318468
+P 6acbdba59e9df4313a6232d925a70390acdc43dfa380b4fba7bb8bd442d6e728
+R 6f0b4cb15335f84e55c45be4e670230a
+T *branch * sqlite3_value_nochange
+T *sym-sqlite3_value_nochange *
+T -sym-trunk *
 U drh
-Z 101b1825b326975007694adf2a0d837c
+Z 9655b705be92f16dc668ac363b3cc0e3
index cf6d922bb8396452f21d1af675386ad767c4f392..7fcc0b51be6a903c9f5ea9473304e01cab5cee56 100644 (file)
@@ -1 +1 @@
-6acbdba59e9df4313a6232d925a70390acdc43dfa380b4fba7bb8bd442d6e728
\ No newline at end of file
+8b7be15ece9e2e83959bb0e21e240106fe1077431242c3cc6b81f1baa2382f40
\ No newline at end of file
index ba673748ed2dbaaba6993e6911d3aa3d76fcc3d9..7579b9926d63a2d04672e82519c6b61990ad6f66 100644 (file)
@@ -4847,6 +4847,12 @@ SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),
 ** then the conversion is performed.  Otherwise no conversion occurs.
 ** The [SQLITE_INTEGER | datatype] after conversion is returned.)^
 **
+** ^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.
+**
 ** Please pay particular attention to the fact that the pointer returned
 ** from [sqlite3_value_blob()], [sqlite3_value_text()], or
 ** [sqlite3_value_text16()] can be invalidated by a subsequent call to
@@ -4869,6 +4875,7 @@ int sqlite3_value_bytes(sqlite3_value*);
 int sqlite3_value_bytes16(sqlite3_value*);
 int sqlite3_value_type(sqlite3_value*);
 int sqlite3_value_numeric_type(sqlite3_value*);
+int sqlite3_value_nochange(sqlite3_value*);
 
 /*
 ** CAPI3REF: Finding The Subtype Of SQL Values
index 3de36fe211a9a39c3f6a7aa0b7833c6443fd5d03..ee920d2a5d9f1850b312951f88c00bbec08e1379 100644 (file)
@@ -827,7 +827,8 @@ static void updateVirtualTable(
     if( aXRef[i]>=0 ){
       sqlite3ExprCode(pParse, pChanges->a[aXRef[i]].pExpr, regArg+2+i);
     }else{
-      sqlite3VdbeAddOp4Int(v, OP_VColumn, iCsr, i, regArg+2+i, 1);
+      sqlite3VdbeAddOp3(v, OP_VColumn, iCsr, i, regArg+2+i);
+      sqlite3VdbeChangeP5(v, 1);
     }
   }
   if( HasRowid(pTab) ){
@@ -862,6 +863,7 @@ 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);
     sqlite3VdbeAddOp2(v, OP_NewRowid, ephemTab, regRowid);
     sqlite3VdbeAddOp3(v, OP_Insert, ephemTab, regRec, regRowid);
   }
index d66387d239b17be9c0f182a11742da3e07874550..dc058b65ffa1fa86b44af9bd4b51d2f03ed2606f 100644 (file)
@@ -464,7 +464,7 @@ static void memTracePrint(Mem *p){
   if( p->flags & MEM_Undefined ){
     printf(" undefined");
   }else if( p->flags & MEM_Null ){
-    printf(" NULL");
+    printf(p->flags & MEM_Zero ? " NULL-nochng" : " NULL");
   }else if( (p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){
     printf(" si:%lld", p->u.i);
   }else if( p->flags & MEM_Int ){
@@ -2794,7 +2794,11 @@ case OP_MakeRecord: {
     assert( memIsValid(pRec) );
     pRec->uTemp = serial_type = sqlite3VdbeSerialType(pRec, file_format, &len);
     if( pRec->flags & MEM_Zero ){
-      if( nData ){
+      if( serial_type==0 ){
+        assert( pOp->p5==2 || CORRUPT_DB );
+        /* serial_type 10 used internally only */
+        pRec->uTemp = 10;
+      }else if( nData ){
         if( sqlite3VdbeMemExpandBlob(pRec) ) goto no_mem;
       }else{
         nZero += pRec->u.nZero;
@@ -6697,15 +6701,15 @@ case OP_VFilter: {   /* jump */
 #endif /* SQLITE_OMIT_VIRTUALTABLE */
 
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-/* Opcode: VColumn P1 P2 P3 P4 *
+/* Opcode: VColumn P1 P2 P3 * P5
 ** Synopsis: r[P3]=vcolumn(P2)
 **
 ** 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
+** an unchanging column during an UPDATE operation, then the P5
+** value is 1.  Otherwise, P5 is 0.  The P5 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.
@@ -6730,8 +6734,13 @@ case OP_VColumn: {
   assert( pModule->xColumn );
   memset(&sContext, 0, sizeof(sContext));
   sContext.pOut = pDest;
-  sContext.bVtabNoChng = pOp->p4.i!=0;
-  MemSetTypeFlag(pDest, MEM_Null);
+  if( pOp->p5 ){
+    sqlite3VdbeMemSetNull(pDest);
+    pDest->flags = MEM_Null|MEM_Zero;
+    pDest->u.nZero = 0;
+  }else{
+    MemSetTypeFlag(pDest, MEM_Null);
+  }
   rc = pModule->xColumn(pCur->uc.pVCur, &sContext, pOp->p2);
   sqlite3VtabImportErrmsg(p, pVtab);
   if( sContext.isError ){
index f646a4036ab6c942594a16466c7de1d4700b2b0a..b7e324c94b441f5e7a234e62deac2b8e3bd4b6a7 100644 (file)
@@ -224,6 +224,8 @@ struct sqlite3_value {
 ** If the MEM_Null flag is set, then the value is an SQL NULL value.
 ** For a pointer type created using sqlite3_bind_pointer() or
 ** sqlite3_result_pointer() the MEM_Term and MEM_Subtype flags are also set.
+** If both MEM_Null and MEM_Zero are set, that means that the value is
+** an unchanging column value from VColumn.
 **
 ** If the MEM_Str flag is set then Mem.z points at a string representation.
 ** Usually this is encoded in the same unicode encoding as the main
index 19aa783bb6e4a5013335663d67c99c37a87eeafe..bdd6d1cd07cde066135acfbd5a335129293d8858 100644 (file)
@@ -268,6 +268,11 @@ int sqlite3_value_type(sqlite3_value* pVal){
   return aType[pVal->flags&MEM_AffMask];
 }
 
+/* Return true if a parameter to xUpdate represents an unchanged column */
+int sqlite3_value_nochange(sqlite3_value *pVal){
+  return (pVal->flags&(MEM_Null|MEM_Zero))==(MEM_Null|MEM_Zero);
+}
+
 /* Make a copy of an sqlite3_value object
 */
 sqlite3_value *sqlite3_value_dup(const sqlite3_value *pOrig){
@@ -761,7 +766,7 @@ sqlite3 *sqlite3_context_db_handle(sqlite3_context *p){
 */
 int sqlite3_vtab_nochange(sqlite3_context *p){
   assert( p );
-  return p->bVtabNoChng;
+  return sqlite3_value_nochange(p->pOut);
 }
 
 /*
index 1780d37b8c9a606e13e771e04331e77761cf7076..72a5b96bba6877513928738a0352226cafd0e580 100644 (file)
@@ -3454,7 +3454,11 @@ u32 sqlite3VdbeSerialGet(
   Mem *pMem                     /* Memory cell to write value into */
 ){
   switch( serial_type ){
-    case 10:   /* Reserved for future use */
+    case 10: { /* Internal use only: NULL with virtual table
+               ** UPDATE no-change flag set */
+      pMem->flags = MEM_Null|MEM_Zero;
+      break;
+    }
     case 11:   /* Reserved for future use */
     case 0: {  /* Null */
       /* EVIDENCE-OF: R-24078-09375 Value is a NULL. */
index 107d831f4c331a32dec4dee78f7581a9530a6273..d8f1e64328ca71fec5e1e1b693835bb40e77083b 100644 (file)
@@ -43,7 +43,7 @@ int sqlite3VdbeCheckMemInvariants(Mem *p){
   if( p->flags & MEM_Null ){
     /* Cannot be both MEM_Null and some other type */
     assert( (p->flags & (MEM_Int|MEM_Real|MEM_Str|MEM_Blob
-                         |MEM_RowSet|MEM_Frame|MEM_Agg|MEM_Zero))==0 );
+                         |MEM_RowSet|MEM_Frame|MEM_Agg))==0 );
 
     /* If MEM_Null is set, then either the value is a pure NULL (the usual
     ** case) or it is a pointer set using sqlite3_bind_pointer() or