diff --git a/manifest b/manifest index c426ee99bf..e13040d2fc 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\szipfile\sto\sbe\sa\sWITHOUT\sROWID\svirtual\stable\sand\stable-valued\sfunction. -D 2018-01-11T17:33:48.340 +C Add\sthe\ssqlite3_vtab_nochange()\sinterface.\s\sTest\scases\sare\sin\sTH3. +D 2018-01-11T18:15:40.111 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 38f84f301cbef443b2d269f67a74b8cc536469831f70df7c3e912acc04932cc2 @@ -486,7 +486,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 1f1a2da222ec57465794e8984d77f32d0bd0da80cdc136beadda461a0be9d80c +F src/sqlite.h.in f83e63a48fb31fefc69c83bbe8700b4b44acdd64e440219087b0f14e35eeb8d4 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h c02d628cca67f3889c689d82d25c3eb45e2c155db08e4c6089b5840d64687d34 F src/sqliteInt.h fd8702c65994d7de3e2d8f7d85d958731da1ed29476571fdfa2290fd8ec0bf80 @@ -549,14 +549,14 @@ F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c 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 @@ -1698,7 +1698,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 407b5ed35c178bb0dbc69c8b902652038a0653d55a58a7543f9d4857c6baf3ea -R 6ae1fe2ba1a1ad2ab58089676c32c82f -U dan -Z df7413e90ffcbb11e6d9a408fc886735 +P 931201f64e04247ed613a0301fcc86c3a337c2ed162c6370a80c67a1dd919e7c d444b1ff39f0a1673a977b8047e1e14a49d461c9934be080d27c2392a830c1c0 +R 9b5e5f478942b3c80eb44a5edc905e08 +T +closed d444b1ff39f0a1673a977b8047e1e14a49d461c9934be080d27c2392a830c1c0 +U drh +Z 90bbe9ce2100212cdce59fb9703ab09f diff --git a/manifest.uuid b/manifest.uuid index 91e729e259..dea0f276ff 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -931201f64e04247ed613a0301fcc86c3a337c2ed162c6370a80c67a1dd919e7c \ No newline at end of file +a5d09dfaa337fa51d6e702c6aefe58824ab1e7d221c6e79166e2c6f9c7ab1501 \ No newline at end of file diff --git a/src/sqlite.h.in b/src/sqlite.h.in index f63b029312..ba673748ed 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -8297,6 +8297,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 ** diff --git a/src/update.c b/src/update.c index 3e9d11bbf7..3de36fe211 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 4d643d7266..b00174bb10 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 cb783653c0..f646a4036a 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 b9df40b8fd..19aa783bb6 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -745,6 +745,25 @@ sqlite3 *sqlite3_context_db_handle(sqlite3_context *p){ return p->pOut->db; } +/* +** 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