From 2fc865c1153d739208657ea652f74426bf20f678 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 16 Dec 2017 20:20:37 +0000 Subject: [PATCH 1/5] Add an experimental location(X) SQL function that attempt to return the location of the payload within the database for the record that contains column X. location(X) returns NULL if X is not an ordinary table column or if SQLite cannot figure out the location because it is using a covering index. FossilOrigin-Name: 51be9558164301c5dd4df23ab8b3e67de0b522f8d36f79f3d84d45d3dc2a83a4 --- manifest | 29 ++++++++++++++++------------- manifest.uuid | 2 +- src/btree.c | 13 +++++++++++++ src/btree.h | 1 + src/expr.c | 15 ++++++++++++--- src/func.c | 2 ++ src/sqliteInt.h | 1 + src/vdbe.c | 20 ++++++++++++++++++++ test/func6.test | 36 ++++++++++++++++++++++++++++++++++++ 9 files changed, 102 insertions(+), 17 deletions(-) create mode 100644 test/func6.test diff --git a/manifest b/manifest index c3b80112dd..8e46d8e601 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\ssqlite3_vtab_collation()\sfunction,\swhich\sallows\san\sxBestIndex\scallback\nto\sdetermine\sthe\scollation\ssequence\sthat\sSQLite\swill\suse\sfor\sa\scomparison.\sAnd\nthe\sSQLITE_DBCONFIG_FULL_EQP\sconfiguration\soption,\swhich\senhances\sthe\soutput\nof\s"EXPLAIN\sQUERY\sPLAN"\sso\sthat\sit\sincludes\sstatements\srun\sby\striggers.\sAnd\nthe\scode\sfor\sthe\ssqlite3_expert\sextension\sand\scommand\sline\sapplication. -D 2017-12-16T19:36:52.802 +C Add\san\sexperimental\slocation(X)\sSQL\sfunction\sthat\sattempt\sto\sreturn\sthe\nlocation\sof\sthe\spayload\swithin\sthe\sdatabase\sfor\sthe\srecord\sthat\scontains\ncolumn\sX.\s\slocation(X)\sreturns\sNULL\sif\sX\sis\snot\san\sordinary\stable\scolumn\sor\nif\sSQLite\scannot\sfigure\sout\sthe\slocation\sbecause\sit\sis\susing\sa\scovering\sindex. +D 2017-12-16T20:20:37.221 F Makefile.in ceb40bfcb30ebba8e1202b34c56ff7e13e112f9809e2381d99be32c2726058f5 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6480671f7c129e61208d69492b3c71ce4310d49fceac83cfb17f1c081e242b69 @@ -420,8 +420,8 @@ F src/auth.c 6277d63837357549fe14e723490d6dc1a38768d71c795c5eb5c0f8a99f918f73 F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33 F src/btmutex.c 0e9ce2d56159b89b9bc8e197e023ee11e39ff8ca -F src/btree.c b83a6b03f160528020bb965f0c3a40af5286cd4923c3870fd218177f03a120a7 -F src/btree.h 32ef5d3f25dc70ef1ee9cecf84a023c21378f06a57cd701d2e866e141b150f09 +F src/btree.c 6fba32ea06e9be55849dd486e88df6c467bf69cf306d38ca3c3a8df34e6499e9 +F src/btree.h e9d22d0475b37422cc2db53f4336cc814645dcca8634bc4aae25ed52d043ef53 F src/btreeInt.h 55b702efce17e5d1941865464227d3802cfc9c7c832fac81d4c94dced47a71fc F src/build.c 87b68e3b45559ec404b12f095f0ba5f06f91a6dd2d21bd8443e41d8ac2e67196 F src/callback.c fe677cb5f5abb02f7a772a62a98c2f516426081df68856e8f2d5f950929b966a @@ -431,10 +431,10 @@ F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957 F src/dbpage.c 8db4c97f630e7d83f884ea75caf1ffd0988c160e9d530194d93721c80821e0f6 F src/dbstat.c 7a4ba8518b6369ef3600c49cf9c918ad979acba610b2aebef1b656d649b96720 F src/delete.c 74667ad914ac143731a444a1bacf29ceb18f6eded8a0dd17aafae80baa07f8bb -F src/expr.c fe11b91bb65b869143bd42023427c4429778ae42c0a0db7762f68f75b347a958 +F src/expr.c 261d1eb0954a7813d512d8edafd6db26736a3dcb650785652a6234d5ddb394aa F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c d617daf66b5515e2b42c1405b2b4984c30ca50fb705ab164271a9bf66c69e331 -F src/func.c 0fb9a2d678d3c8aba89b46468b309cd7e8fa9806a369a30aa89024660845bb13 +F src/func.c a23ea9b8869ca47e20a273985013b36a2294788fde5abe1a610be4bb90c8e6e8 F src/global.c ac3094f1dc59fbeb919aef7cc0cc827a8459d1fb1adb7972ef75bd9e0c10b75b F src/hash.c a12580e143f10301ed5166ea4964ae2853d3905a511d4e0c44497245c7ce1f7a F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4 @@ -483,7 +483,7 @@ F src/shell.c.in 6ffed0c589f5aff180789a8c8abf5b2d3e2eea7470c86b30e797887cb0c9d0e F src/sqlite.h.in 95afbec6e623843d702e727765efc833586fecc688867f41f87be7db3ff1fa62 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h c02d628cca67f3889c689d82d25c3eb45e2c155db08e4c6089b5840d64687d34 -F src/sqliteInt.h 4d6580ab911e9bc36447ef05bf4d2aab929dde161ac117c7de6220eef06d6175 +F src/sqliteInt.h 3aca12018eb1528f9bc7af4a9ea141759f2487ff42b9f9f688210d09742dfe1e F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/status.c 9737ed017279a9e0c5da748701c3c7bf1e8ae0dae459aad20dd64fcff97a7e35 F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 @@ -547,7 +547,7 @@ F src/update.c 961bd1265d4d1e5cd65c9a54fa5122fb7aefcb003fcf2de0c092fceb7e58972c F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5 F src/util.c d01fa6f45bfad3b65fb2490513aa2e0676412c61b4b094340b513cf72c3704a4 F src/vacuum.c 90839322fd5f00df9617eb21b68beda9b6e2a2937576b0d65985e4aeb1c53739 -F src/vdbe.c 3393b508d9ad084ffce232a7c53e375ef5ac99b50b685c5131fcdfce97a9d534 +F src/vdbe.c beed55b540e01e9be3b87b0d3aa491b41d933bd391ca4d8470882f77e1090871 F src/vdbe.h d50cadf12bcf9fb99117ef392ce1ea283aa429270481426b6e8b0280c101fd97 F src/vdbeInt.h 1fe00770144c12c4913128f35262d11527ef3284561baaab59b947a41c08d0d9 F src/vdbeapi.c 9c670ca0dcc1cd86373aa353b747b26fe531ca5cd4331690c611d1f03842e2a1 @@ -917,6 +917,7 @@ F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f F test/func3.test d202a7606d23f90988a664e88e268aed1087c11c F test/func4.test 6beacdfcb0e18c358e6c2dcacf1b65d1fa80955f F test/func5.test cdd224400bc3e48d891827cc913a57051a426fa4 +F test/func6.test 5d4b0526f5013db07e2f6de43df42d990500f636fa32258cfac0c87113a1c1ce F test/fuzz-oss1.test e58330d01cbbd8215ee636b17a03fe220b37dbfa F test/fuzz.test 96083052bf5765e4518c1ba686ce2bab785670d1 F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1 @@ -1687,8 +1688,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 64487d658cb3b6c8c67f1e198c70813c963de52599f3ea974bdc2aa432e74de9 d5b597b52a1213cdf382d96f4df3535727be0852b25bafd12bbef54da946c5f2 -R 864c298149f75794a8b0c88eee2c8573 -T +closed d5b597b52a1213cdf382d96f4df3535727be0852b25bafd12bbef54da946c5f2 -U dan -Z 532f71905753147684a848f63aad67ba +P 4c782c950204c09c1d8f857c39c4cf476539ec4e7eee6fd86419d47cf0f8b9e0 +R c224d72a40caf69fa2477f10805805e4 +T *branch * location-function +T *sym-location-function * +T -sym-trunk * +U drh +Z 078a2a780a60eba456bb0addd6858536 diff --git a/manifest.uuid b/manifest.uuid index 7b68239262..e971cdd459 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4c782c950204c09c1d8f857c39c4cf476539ec4e7eee6fd86419d47cf0f8b9e0 \ No newline at end of file +51be9558164301c5dd4df23ab8b3e67de0b522f8d36f79f3d84d45d3dc2a83a4 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 0fa00a2e12..d17cbde846 100644 --- a/src/btree.c +++ b/src/btree.c @@ -4432,6 +4432,19 @@ i64 sqlite3BtreeIntegerKey(BtCursor *pCur){ return pCur->info.nKey; } +/* +** Return the offset into the database file for the start of the +** payload to which the cursor is pointing. +*/ +i64 sqlite3BtreeLocation(BtCursor *pCur){ + assert( cursorHoldsMutex(pCur) ); + assert( pCur->eState==CURSOR_VALID ); + assert( pCur->curIntKey ); + getCellInfo(pCur); + return (i64)pCur->pBt->pageSize*(i64)pCur->pPage->pgno + + (i64)(pCur->info.pPayload - pCur->pPage->aData); +} + /* ** Return the number of bytes of payload for the entry that pCur is ** currently pointing to. For table btrees, this will be the amount diff --git a/src/btree.h b/src/btree.h index e2c271cdc5..43c0b9a8a4 100644 --- a/src/btree.h +++ b/src/btree.h @@ -291,6 +291,7 @@ int sqlite3BtreeNext(BtCursor*, int flags); int sqlite3BtreeEof(BtCursor*); int sqlite3BtreePrevious(BtCursor*, int flags); i64 sqlite3BtreeIntegerKey(BtCursor*); +i64 sqlite3BtreeLocation(BtCursor*); int sqlite3BtreePayload(BtCursor*, u32 offset, u32 amt, void*); const void *sqlite3BtreePayloadFetch(BtCursor*, u32 *pAmt); u32 sqlite3BtreePayloadSize(BtCursor*); diff --git a/src/expr.c b/src/expr.c index 524e539349..b7c64d3c11 100644 --- a/src/expr.c +++ b/src/expr.c @@ -3871,9 +3871,18 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ if( !pColl ) pColl = db->pDfltColl; sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ); } - sqlite3VdbeAddOp4(v, pParse->iSelfTab ? OP_PureFunc0 : OP_Function0, - constMask, r1, target, (char*)pDef, P4_FUNCDEF); - sqlite3VdbeChangeP5(v, (u8)nFarg); + if( pDef->funcFlags & SQLITE_FUNC_LOCATION ){ + Expr *pArg = pFarg->a[0].pExpr; + if( pArg->op==TK_COLUMN ){ + sqlite3VdbeAddOp2(v, OP_Location, pArg->iTable, target); + }else{ + sqlite3VdbeAddOp2(v, OP_Null, 0, target); + } + }else{ + sqlite3VdbeAddOp4(v, pParse->iSelfTab ? OP_PureFunc0 : OP_Function0, + constMask, r1, target, (char*)pDef, P4_FUNCDEF); + sqlite3VdbeChangeP5(v, (u8)nFarg); + } if( nFarg && constMask==0 ){ sqlite3ReleaseTempRange(pParse, r1, nFarg); } diff --git a/src/func.c b/src/func.c index 7528fa8b4d..f81c4865d8 100644 --- a/src/func.c +++ b/src/func.c @@ -1799,6 +1799,8 @@ void sqlite3RegisterBuiltinFunctions(void){ #ifdef SQLITE_DEBUG FUNCTION2(affinity, 1, 0, 0, noopFunc, SQLITE_FUNC_AFFINITY), #endif + FUNCTION2(location, 1, 0, 0, noopFunc, SQLITE_FUNC_LOCATION| + SQLITE_FUNC_TYPEOF), FUNCTION(ltrim, 1, 1, 0, trimFunc ), FUNCTION(ltrim, 2, 1, 0, trimFunc ), FUNCTION(rtrim, 1, 2, 0, trimFunc ), diff --git a/src/sqliteInt.h b/src/sqliteInt.h index efe823a654..f85682a393 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1630,6 +1630,7 @@ struct FuncDestructor { #define SQLITE_FUNC_SLOCHNG 0x2000 /* "Slow Change". Value constant during a ** single query - might change over time */ #define SQLITE_FUNC_AFFINITY 0x4000 /* Built-in affinity() function */ +#define SQLITE_FUNC_LOCATION 0x8000 /* Built-in location() function */ /* ** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are diff --git a/src/vdbe.c b/src/vdbe.c index cfe18a9d1e..74cf82c4c1 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -2349,6 +2349,26 @@ case OP_IfNullRow: { /* jump */ break; } +/* Opcode: Location P1 P2 * * * +** Synopsis: r[P2] = location(P1) +** +** Store in register r[P2] the location in the database file that is the +** start of the payload for the record at which that cursor P1 is currently +** pointing. +*/ +case OP_Location: { /* out2 */ + VdbeCursor *pC; /* The VDBE cursor */ + assert( pOp->p1>=0 && pOp->p1nCursor ); + pC = p->apCsr[pOp->p1]; + pOut = out2Prerelease(p, pOp); + if( pC==0 || pC->eCurType!=CURTYPE_BTREE ){ + pOut->flags = MEM_Null; + }else{ + pOut->u.i = sqlite3BtreeLocation(pC->uc.pCursor); + } + break; +} + /* Opcode: Column P1 P2 P3 P4 P5 ** Synopsis: r[P3]=PX ** diff --git a/test/func6.test b/test/func6.test new file mode 100644 index 0000000000..5350aeaa7b --- /dev/null +++ b/test/func6.test @@ -0,0 +1,36 @@ +# 2017-12-16 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#************************************************************************* +# +# Test cases for the location() function. +# +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +do_execsql_test func6-100 { + CREATE TABLE t1(a,b,c,d); + WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100) + INSERT INTO t1(a,b,c,d) SELECT printf('abc%03x',x), x, 1000-x, NULL FROM c; +} +do_execsql_test func6-110 { + SELECT a, typeof(location(a)) FROM t1 ORDER BY rowid LIMIT 2; +} {abc001 integer abc002 integer} +do_execsql_test func6-120 { + SELECT a, typeof(location(+a)) FROM t1 ORDER BY rowid LIMIT 2; +} {abc001 null abc002 null} +do_execsql_test func6-130 { + CREATE INDEX t1a ON t1(a); + SELECT a, typeof(location(a)) FROM t1 ORDER BY a LIMIT 2; +} {abc001 null abc002 null} +do_execsql_test func6-140 { + SELECT a, typeof(location(a)) FROM t1 NOT INDEXED ORDER BY a LIMIT 2; +} {abc001 integer abc002 integer} + +finish_test From fe6d20e9f4d17ad82fd4c4cc69181ad5f52d9d93 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 29 Dec 2017 14:33:54 +0000 Subject: [PATCH 2/5] Enhance location(X) so that it works with indexes and WITHOUT ROWID tables. The function might return an offset to the main table or to an index, depending on whether the column X would be loaded from the main table or from the index. FossilOrigin-Name: dd94d6a880dfec4bddd247239b815b84964f804d24841e25f33f1d46a4b5274d --- manifest | 20 ++++++++++---------- manifest.uuid | 2 +- src/btree.c | 3 +-- src/expr.c | 2 +- src/vdbe.c | 19 ++++++++++++------- src/where.c | 2 +- test/func6.test | 2 +- 7 files changed, 27 insertions(+), 23 deletions(-) diff --git a/manifest b/manifest index 89d90d3cf5..12c0ae8735 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\srecent\senhancements\sfrom\strunk. -D 2017-12-29T13:35:09.867 +C Enhance\slocation(X)\sso\sthat\sit\sworks\swith\sindexes\sand\sWITHOUT\sROWID\stables.\nThe\sfunction\smight\sreturn\san\soffset\sto\sthe\smain\stable\sor\sto\san\sindex,\ndepending\son\swhether\sthe\scolumn\sX\swould\sbe\sloaded\sfrom\sthe\smain\stable\sor\nfrom\sthe\sindex. +D 2017-12-29T14:33:54.266 F Makefile.in ceb40bfcb30ebba8e1202b34c56ff7e13e112f9809e2381d99be32c2726058f5 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6480671f7c129e61208d69492b3c71ce4310d49fceac83cfb17f1c081e242b69 @@ -420,7 +420,7 @@ F src/auth.c 6277d63837357549fe14e723490d6dc1a38768d71c795c5eb5c0f8a99f918f73 F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33 F src/btmutex.c 0e9ce2d56159b89b9bc8e197e023ee11e39ff8ca -F src/btree.c 6fba32ea06e9be55849dd486e88df6c467bf69cf306d38ca3c3a8df34e6499e9 +F src/btree.c 516fea6cad0d904ba1f7d599cb3d8ec9f14c2c6d1b71cf883dcef81d77bc6a5a F src/btree.h e9d22d0475b37422cc2db53f4336cc814645dcca8634bc4aae25ed52d043ef53 F src/btreeInt.h 55b702efce17e5d1941865464227d3802cfc9c7c832fac81d4c94dced47a71fc F src/build.c a03eb5a1cfff74784c24a4478ba5455711571936f1ac9d43f94fa7df57509977 @@ -431,7 +431,7 @@ F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957 F src/dbpage.c 8db4c97f630e7d83f884ea75caf1ffd0988c160e9d530194d93721c80821e0f6 F src/dbstat.c 7a4ba8518b6369ef3600c49cf9c918ad979acba610b2aebef1b656d649b96720 F src/delete.c 74667ad914ac143731a444a1bacf29ceb18f6eded8a0dd17aafae80baa07f8bb -F src/expr.c db1f29a1ee0c8a3abec55134ae7e149fa5684d77b569c6a62121b9e13becc43a +F src/expr.c 119aa8d492bfc05ecf73ff4160b48c65d696972b2c954149271a1363e795874b F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c d617daf66b5515e2b42c1405b2b4984c30ca50fb705ab164271a9bf66c69e331 F src/func.c a23ea9b8869ca47e20a273985013b36a2294788fde5abe1a610be4bb90c8e6e8 @@ -547,7 +547,7 @@ F src/update.c 961bd1265d4d1e5cd65c9a54fa5122fb7aefcb003fcf2de0c092fceb7e58972c F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5 F src/util.c 7315e97a8dc2c8e19ca64196c652cf0a65d13fd0a211b2cec082062372dc6261 F src/vacuum.c 90839322fd5f00df9617eb21b68beda9b6e2a2937576b0d65985e4aeb1c53739 -F src/vdbe.c 742812438ab9c897db18025c6040af23feb4679fc63c53bdf25a9b190c7f91ec +F src/vdbe.c 42e79ef2da625fd8c4364bf952b0515760958775beb38cc9f9e84bcec4115964 F src/vdbe.h d50cadf12bcf9fb99117ef392ce1ea283aa429270481426b6e8b0280c101fd97 F src/vdbeInt.h 1fe00770144c12c4913128f35262d11527ef3284561baaab59b947a41c08d0d9 F src/vdbeapi.c 9c670ca0dcc1cd86373aa353b747b26fe531ca5cd4331690c611d1f03842e2a1 @@ -561,7 +561,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c 5a3f464edd64596f601683ed321d12e6fd93c5fb9afdfb3653d6ffd0fee9c48f F src/wal.h 8de5d2d3de0956d6f6cb48c83a4012d5f227b8fe940f3a349a4b7e85ebcb492a F src/walker.c da987a20d40145c0a03c07d8fefcb2ed363becc7680d0500d9c79915591f5b1f -F src/where.c 5876c9100b622f7b9e5ee7f579b8b6a71ae5ba627724cea4546d9114c32b3cb5 +F src/where.c 9c1fca74de02cf5d8ac6437fc385b683e194c403a2ae675eb4f15a5c19086726 F src/whereInt.h 82c04c5075308abbac59180c8bad5ecb45b07453981f60a53f3c7dee21e1e971 F src/wherecode.c af1e79154aaa88cd802d6f2e5b945f67eaca7c958d1525fbf8ee19d5bd7b9020 F src/whereexpr.c 427ea8e96ec24f2a7814c67b8024ad664a9c7656264c4566c34743cb23186e46 @@ -917,7 +917,7 @@ F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f F test/func3.test d202a7606d23f90988a664e88e268aed1087c11c F test/func4.test 6beacdfcb0e18c358e6c2dcacf1b65d1fa80955f F test/func5.test cdd224400bc3e48d891827cc913a57051a426fa4 -F test/func6.test 5d4b0526f5013db07e2f6de43df42d990500f636fa32258cfac0c87113a1c1ce +F test/func6.test afd2f720b333f0fbbb220887b3f1b3637ef9bfde47015f664e9bb4ba14a01535 F test/fuzz-oss1.test e58330d01cbbd8215ee636b17a03fe220b37dbfa F test/fuzz.test 96083052bf5765e4518c1ba686ce2bab785670d1 F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1 @@ -1688,7 +1688,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 51be9558164301c5dd4df23ab8b3e67de0b522f8d36f79f3d84d45d3dc2a83a4 f4349c0c26611de8a7d5beb99431a575cf531cdeb0ca2413efabcf0a61e6f424 -R 21534cc483241840a2ab1c4e82c69566 +P 6251e438f2a76170fd1e95aa512a46086ed88ab93b9b97a1dba97c4558689305 +R f543ccd2667c3e9285e509d3e9a274bf U drh -Z 27f7d54e41b653412b0ccbce7bf65d00 +Z e0ddcaae57472f72e53764b52bf6363b diff --git a/manifest.uuid b/manifest.uuid index c839229c61..b83335d6cc 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6251e438f2a76170fd1e95aa512a46086ed88ab93b9b97a1dba97c4558689305 \ No newline at end of file +dd94d6a880dfec4bddd247239b815b84964f804d24841e25f33f1d46a4b5274d \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index d17cbde846..a8d91cc0c9 100644 --- a/src/btree.c +++ b/src/btree.c @@ -4439,9 +4439,8 @@ i64 sqlite3BtreeIntegerKey(BtCursor *pCur){ i64 sqlite3BtreeLocation(BtCursor *pCur){ assert( cursorHoldsMutex(pCur) ); assert( pCur->eState==CURSOR_VALID ); - assert( pCur->curIntKey ); getCellInfo(pCur); - return (i64)pCur->pBt->pageSize*(i64)pCur->pPage->pgno + + return (i64)pCur->pBt->pageSize*((i64)pCur->pPage->pgno - 1) + (i64)(pCur->info.pPayload - pCur->pPage->aData); } diff --git a/src/expr.c b/src/expr.c index dbfc1b7ed3..dd7d548edc 100644 --- a/src/expr.c +++ b/src/expr.c @@ -3873,7 +3873,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ if( pDef->funcFlags & SQLITE_FUNC_LOCATION ){ Expr *pArg = pFarg->a[0].pExpr; if( pArg->op==TK_COLUMN ){ - sqlite3VdbeAddOp2(v, OP_Location, pArg->iTable, target); + sqlite3VdbeAddOp3(v, OP_Location, pArg->iTable, pArg->iColumn,target); }else{ sqlite3VdbeAddOp2(v, OP_Null, 0, target); } diff --git a/src/vdbe.c b/src/vdbe.c index 975a098198..68762ae5e1 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -2349,22 +2349,27 @@ case OP_IfNullRow: { /* jump */ break; } -/* Opcode: Location P1 P2 * * * -** Synopsis: r[P2] = location(P1) +/* Opcode: Location P1 P2 P3 * * +** Synopsis: r[P3] = location(P1) ** -** Store in register r[P2] the location in the database file that is the +** Store in register r[P3] the location in the database file that is the ** start of the payload for the record at which that cursor P1 is currently ** pointing. +** +** P2 is the column number for the argument to the location() function. +** This opcode does not use P2 itself, but the P2 value is used by the +** code generator. The P1, P2, and P3 operands to this opcode are the +** as as for OP_Column. */ -case OP_Location: { /* out2 */ +case OP_Location: { /* out3 */ VdbeCursor *pC; /* The VDBE cursor */ assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; - pOut = out2Prerelease(p, pOp); + pOut = &p->aMem[pOp->p3]; if( pC==0 || pC->eCurType!=CURTYPE_BTREE ){ - pOut->flags = MEM_Null; + sqlite3VdbeMemSetNull(pOut); }else{ - pOut->u.i = sqlite3BtreeLocation(pC->uc.pCursor); + sqlite3VdbeMemSetInt64(pOut, sqlite3BtreeLocation(pC->uc.pCursor)); } break; } diff --git a/src/where.c b/src/where.c index d3aec354ba..146c8124c8 100644 --- a/src/where.c +++ b/src/where.c @@ -5146,7 +5146,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){ pOp = sqlite3VdbeGetOp(v, k); for(; kp1!=pLevel->iTabCur ) continue; - if( pOp->opcode==OP_Column ){ + if( pOp->opcode==OP_Column || pOp->opcode==OP_Location ){ int x = pOp->p2; assert( pIdx->pTable==pTab ); if( !HasRowid(pTab) ){ diff --git a/test/func6.test b/test/func6.test index 5350aeaa7b..3630aa33db 100644 --- a/test/func6.test +++ b/test/func6.test @@ -28,7 +28,7 @@ do_execsql_test func6-120 { do_execsql_test func6-130 { CREATE INDEX t1a ON t1(a); SELECT a, typeof(location(a)) FROM t1 ORDER BY a LIMIT 2; -} {abc001 null abc002 null} +} {abc001 integer abc002 integer} do_execsql_test func6-140 { SELECT a, typeof(location(a)) FROM t1 NOT INDEXED ORDER BY a LIMIT 2; } {abc001 integer abc002 integer} From 092457b18ce71b6b0f30ea8a67817310feffaebc Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 29 Dec 2017 15:04:49 +0000 Subject: [PATCH 3/5] Change the function name to sqlite_unsupported_offset(X). Only enable the function if compiled with -DSQLITE_ENABLE_OFFSET_SQL_FUNC. The makefiles add that definition to shell builds. FossilOrigin-Name: 7a7f826e324b1a2c332e2f1d0740fd0babffcaca6275a798572f02ad367b99ab --- Makefile.in | 1 + Makefile.msc | 1 + main.mk | 1 + manifest | 34 +++++++++++++++++----------------- manifest.uuid | 2 +- src/btree.c | 4 +++- src/btree.h | 4 +++- src/expr.c | 9 ++++++--- src/func.c | 5 ++++- src/sqliteInt.h | 2 +- src/test_config.c | 6 ++++++ src/vdbe.c | 17 +++++++++++------ src/where.c | 6 +++++- test/func6.test | 18 +++++++++++++----- 14 files changed, 73 insertions(+), 37 deletions(-) diff --git a/Makefile.in b/Makefile.in index 009ab2e061..3c9e7b3a96 100644 --- a/Makefile.in +++ b/Makefile.in @@ -582,6 +582,7 @@ SHELL_OPT += -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION SHELL_OPT += -DSQLITE_ENABLE_STMTVTAB SHELL_OPT += -DSQLITE_ENABLE_DBPAGE_VTAB SHELL_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB +SHELL_OPT += -DSQLITE_ENABLE_OFFSET_SQL_FUNC FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1 FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000 diff --git a/Makefile.msc b/Makefile.msc index 652bd81fd0..94fa32dc3a 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -1513,6 +1513,7 @@ FUZZDATA = \ !IF $(DYNAMIC_SHELL)==0 && $(FOR_WIN10)==0 SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_STMTVTAB SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_ENABLE_DBSTAT_VTAB +SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_EANBLE_OFFSET_SQL_FUNC !ENDIF # <> diff --git a/main.mk b/main.mk index 8692450441..b46ffa1a52 100644 --- a/main.mk +++ b/main.mk @@ -509,6 +509,7 @@ SHELL_OPT += -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION SHELL_OPT += -DSQLITE_ENABLE_STMTVTAB SHELL_OPT += -DSQLITE_ENABLE_DBPAGE_VTAB SHELL_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB +SHELL_OPT += -DSQLITE_ENABLE_OFFSET_SQL_FUNC FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1 FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000 diff --git a/manifest b/manifest index 12c0ae8735..1328eaf9ce 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,8 @@ -C Enhance\slocation(X)\sso\sthat\sit\sworks\swith\sindexes\sand\sWITHOUT\sROWID\stables.\nThe\sfunction\smight\sreturn\san\soffset\sto\sthe\smain\stable\sor\sto\san\sindex,\ndepending\son\swhether\sthe\scolumn\sX\swould\sbe\sloaded\sfrom\sthe\smain\stable\sor\nfrom\sthe\sindex. -D 2017-12-29T14:33:54.266 -F Makefile.in ceb40bfcb30ebba8e1202b34c56ff7e13e112f9809e2381d99be32c2726058f5 +C Change\sthe\sfunction\sname\sto\ssqlite_unsupported_offset(X).\s\sOnly\senable\sthe\nfunction\sif\scompiled\swith\s-DSQLITE_ENABLE_OFFSET_SQL_FUNC.\s\sThe\smakefiles\sadd\nthat\sdefinition\sto\sshell\sbuilds. +D 2017-12-29T15:04:49.734 +F Makefile.in 804c347948b0ad5a962aea3e59413e897227e0173d0e76910f11f473e6c7ae9b F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 -F Makefile.msc 6480671f7c129e61208d69492b3c71ce4310d49fceac83cfb17f1c081e242b69 +F Makefile.msc f11644a365122b16628da7839a8ed2e3a781b578a94cb1ebd25ebad260bdc9c2 F README.md eeae1e552f93ef72ef7c5b8f6647b368a001c28820ad1df179d3dae602bef681 F VERSION 0c10cdfed866fdd2d80434f64f042c3330f1daaed12e54287beb104f04b3faaf F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@ -401,7 +401,7 @@ F ext/userauth/userauth.c 3410be31283abba70255d71fd24734e017a4497f F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 -F main.mk 50bac9920024b5485f06398b3980f09e97ab28cd4b5b6dcd829d2a5e3ce22e7a +F main.mk b5f569262e4f8111bb8cf6110784b8210fe14ea45f6c7ea50fb4230ebe7a4880 F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271 F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504 @@ -420,8 +420,8 @@ F src/auth.c 6277d63837357549fe14e723490d6dc1a38768d71c795c5eb5c0f8a99f918f73 F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33 F src/btmutex.c 0e9ce2d56159b89b9bc8e197e023ee11e39ff8ca -F src/btree.c 516fea6cad0d904ba1f7d599cb3d8ec9f14c2c6d1b71cf883dcef81d77bc6a5a -F src/btree.h e9d22d0475b37422cc2db53f4336cc814645dcca8634bc4aae25ed52d043ef53 +F src/btree.c 0a1f63b50ab1ac5d4b1637c30cb1ae123fbc162ec8cb6336ddb9491a0bc1e363 +F src/btree.h 0866c0a08255142ea0e754aabd211c843cab32045c978a592a43152405ed0c84 F src/btreeInt.h 55b702efce17e5d1941865464227d3802cfc9c7c832fac81d4c94dced47a71fc F src/build.c a03eb5a1cfff74784c24a4478ba5455711571936f1ac9d43f94fa7df57509977 F src/callback.c fe677cb5f5abb02f7a772a62a98c2f516426081df68856e8f2d5f950929b966a @@ -431,10 +431,10 @@ F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957 F src/dbpage.c 8db4c97f630e7d83f884ea75caf1ffd0988c160e9d530194d93721c80821e0f6 F src/dbstat.c 7a4ba8518b6369ef3600c49cf9c918ad979acba610b2aebef1b656d649b96720 F src/delete.c 74667ad914ac143731a444a1bacf29ceb18f6eded8a0dd17aafae80baa07f8bb -F src/expr.c 119aa8d492bfc05ecf73ff4160b48c65d696972b2c954149271a1363e795874b +F src/expr.c ad6e7a9c34a4bab9d10cc857d647ae7ce370a633b5c0bfa71f1c29b81ae364b8 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c d617daf66b5515e2b42c1405b2b4984c30ca50fb705ab164271a9bf66c69e331 -F src/func.c a23ea9b8869ca47e20a273985013b36a2294788fde5abe1a610be4bb90c8e6e8 +F src/func.c 697a3ee3b8c8481db497226e9e71935727d6a9fb3d3cc049e82a1c717a0a8342 F src/global.c ac3094f1dc59fbeb919aef7cc0cc827a8459d1fb1adb7972ef75bd9e0c10b75b F src/hash.c a12580e143f10301ed5166ea4964ae2853d3905a511d4e0c44497245c7ce1f7a F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4 @@ -483,7 +483,7 @@ F src/shell.c.in f3ec8f90dd698ea98781a90642c91eacbc24f4e55bb551c7b2762000d3ef55d F src/sqlite.h.in b4dc75265ed04b98e2184011a7dd0054ce2137ff84867a6be8b4f3bdfbc03d30 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h c02d628cca67f3889c689d82d25c3eb45e2c155db08e4c6089b5840d64687d34 -F src/sqliteInt.h 623712d1ae728cc0ca78c9d8985b9665d89afff3082c1b664cbba08b0b01476d +F src/sqliteInt.h fd8702c65994d7de3e2d8f7d85d958731da1ed29476571fdfa2290fd8ec0bf80 F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/status.c 9737ed017279a9e0c5da748701c3c7bf1e8ae0dae459aad20dd64fcff97a7e35 F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 @@ -503,7 +503,7 @@ F src/test_backup.c bf5da90c9926df0a4b941f2d92825a01bbe090a0 F src/test_bestindex.c 78809f11026f18a93fcfd798d9479cba37e1201c830260bf1edc674b2fa9b857 F src/test_blob.c ae4a0620b478548afb67963095a7417cd06a4ec0a56adb453542203bfdcb31ce F src/test_btree.c 8b2dc8b8848cf3a4db93f11578f075e82252a274 -F src/test_config.c 3904a8682aac58b77d20ca236face2b11e50781be4116004ba1ba79f69896ec9 +F src/test_config.c cc8a1d44648d9392a14f4ecfc841d027daaf61f952b9f70792edf11373aaa3dd F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf9f8f F src/test_demovfs.c a0c3bdd45ed044115c2c9f7779e56eafff18741e F src/test_devsym.c 1960abbb234b97e9b920f07e99503fc04b443f62bbc3c6ff2c2cea2133e3b8a2 @@ -547,7 +547,7 @@ F src/update.c 961bd1265d4d1e5cd65c9a54fa5122fb7aefcb003fcf2de0c092fceb7e58972c F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5 F src/util.c 7315e97a8dc2c8e19ca64196c652cf0a65d13fd0a211b2cec082062372dc6261 F src/vacuum.c 90839322fd5f00df9617eb21b68beda9b6e2a2937576b0d65985e4aeb1c53739 -F src/vdbe.c 42e79ef2da625fd8c4364bf952b0515760958775beb38cc9f9e84bcec4115964 +F src/vdbe.c cb3b5035f337c9fed4a0170ca20325dc4500b832c57d00561310cbb78149a73c F src/vdbe.h d50cadf12bcf9fb99117ef392ce1ea283aa429270481426b6e8b0280c101fd97 F src/vdbeInt.h 1fe00770144c12c4913128f35262d11527ef3284561baaab59b947a41c08d0d9 F src/vdbeapi.c 9c670ca0dcc1cd86373aa353b747b26fe531ca5cd4331690c611d1f03842e2a1 @@ -561,7 +561,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c 5a3f464edd64596f601683ed321d12e6fd93c5fb9afdfb3653d6ffd0fee9c48f F src/wal.h 8de5d2d3de0956d6f6cb48c83a4012d5f227b8fe940f3a349a4b7e85ebcb492a F src/walker.c da987a20d40145c0a03c07d8fefcb2ed363becc7680d0500d9c79915591f5b1f -F src/where.c 9c1fca74de02cf5d8ac6437fc385b683e194c403a2ae675eb4f15a5c19086726 +F src/where.c 36b92103f726609cc3dbe07c619426bd6886bede455de56ccff54c8e567f5582 F src/whereInt.h 82c04c5075308abbac59180c8bad5ecb45b07453981f60a53f3c7dee21e1e971 F src/wherecode.c af1e79154aaa88cd802d6f2e5b945f67eaca7c958d1525fbf8ee19d5bd7b9020 F src/whereexpr.c 427ea8e96ec24f2a7814c67b8024ad664a9c7656264c4566c34743cb23186e46 @@ -917,7 +917,7 @@ F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f F test/func3.test d202a7606d23f90988a664e88e268aed1087c11c F test/func4.test 6beacdfcb0e18c358e6c2dcacf1b65d1fa80955f F test/func5.test cdd224400bc3e48d891827cc913a57051a426fa4 -F test/func6.test afd2f720b333f0fbbb220887b3f1b3637ef9bfde47015f664e9bb4ba14a01535 +F test/func6.test 8a6ecb974a9d0bdeef6a06aff8e305b1667c3b922103037735b39c716360ebc2 F test/fuzz-oss1.test e58330d01cbbd8215ee636b17a03fe220b37dbfa F test/fuzz.test 96083052bf5765e4518c1ba686ce2bab785670d1 F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1 @@ -1688,7 +1688,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 6251e438f2a76170fd1e95aa512a46086ed88ab93b9b97a1dba97c4558689305 -R f543ccd2667c3e9285e509d3e9a274bf +P dd94d6a880dfec4bddd247239b815b84964f804d24841e25f33f1d46a4b5274d +R 78409e335314d524c66761480a13a3e4 U drh -Z e0ddcaae57472f72e53764b52bf6363b +Z 5cd44f60a8e786e38b3cacae6fe91794 diff --git a/manifest.uuid b/manifest.uuid index b83335d6cc..9bbedd7b51 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -dd94d6a880dfec4bddd247239b815b84964f804d24841e25f33f1d46a4b5274d \ No newline at end of file +7a7f826e324b1a2c332e2f1d0740fd0babffcaca6275a798572f02ad367b99ab \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index a8d91cc0c9..8cd5ee6739 100644 --- a/src/btree.c +++ b/src/btree.c @@ -4432,17 +4432,19 @@ i64 sqlite3BtreeIntegerKey(BtCursor *pCur){ return pCur->info.nKey; } +#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC /* ** Return the offset into the database file for the start of the ** payload to which the cursor is pointing. */ -i64 sqlite3BtreeLocation(BtCursor *pCur){ +i64 sqlite3BtreeOffset(BtCursor *pCur){ assert( cursorHoldsMutex(pCur) ); assert( pCur->eState==CURSOR_VALID ); getCellInfo(pCur); return (i64)pCur->pBt->pageSize*((i64)pCur->pPage->pgno - 1) + (i64)(pCur->info.pPayload - pCur->pPage->aData); } +#endif /* SQLITE_ENABLE_OFFSET_SQL_FUNC */ /* ** Return the number of bytes of payload for the entry that pCur is diff --git a/src/btree.h b/src/btree.h index 43c0b9a8a4..e8e114bd2a 100644 --- a/src/btree.h +++ b/src/btree.h @@ -291,7 +291,9 @@ int sqlite3BtreeNext(BtCursor*, int flags); int sqlite3BtreeEof(BtCursor*); int sqlite3BtreePrevious(BtCursor*, int flags); i64 sqlite3BtreeIntegerKey(BtCursor*); -i64 sqlite3BtreeLocation(BtCursor*); +#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC +i64 sqlite3BtreeOffset(BtCursor*); +#endif int sqlite3BtreePayload(BtCursor*, u32 offset, u32 amt, void*); const void *sqlite3BtreePayloadFetch(BtCursor*, u32 *pAmt); u32 sqlite3BtreePayloadSize(BtCursor*); diff --git a/src/expr.c b/src/expr.c index dd7d548edc..32cc4423fa 100644 --- a/src/expr.c +++ b/src/expr.c @@ -3870,14 +3870,17 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ if( !pColl ) pColl = db->pDfltColl; sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ); } - if( pDef->funcFlags & SQLITE_FUNC_LOCATION ){ +#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC + if( pDef->funcFlags & SQLITE_FUNC_OFFSET ){ Expr *pArg = pFarg->a[0].pExpr; if( pArg->op==TK_COLUMN ){ - sqlite3VdbeAddOp3(v, OP_Location, pArg->iTable, pArg->iColumn,target); + sqlite3VdbeAddOp3(v, OP_Offset, pArg->iTable, pArg->iColumn, target); }else{ sqlite3VdbeAddOp2(v, OP_Null, 0, target); } - }else{ + }else +#endif + { sqlite3VdbeAddOp4(v, pParse->iSelfTab ? OP_PureFunc0 : OP_Function0, constMask, r1, target, (char*)pDef, P4_FUNCDEF); sqlite3VdbeChangeP5(v, (u8)nFarg); diff --git a/src/func.c b/src/func.c index f81c4865d8..4758b0191d 100644 --- a/src/func.c +++ b/src/func.c @@ -1799,8 +1799,11 @@ void sqlite3RegisterBuiltinFunctions(void){ #ifdef SQLITE_DEBUG FUNCTION2(affinity, 1, 0, 0, noopFunc, SQLITE_FUNC_AFFINITY), #endif - FUNCTION2(location, 1, 0, 0, noopFunc, SQLITE_FUNC_LOCATION| +#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC + FUNCTION2(sqlite_unsupported_offset, + 1, 0, 0, noopFunc, SQLITE_FUNC_OFFSET| SQLITE_FUNC_TYPEOF), +#endif FUNCTION(ltrim, 1, 1, 0, trimFunc ), FUNCTION(ltrim, 2, 1, 0, trimFunc ), FUNCTION(rtrim, 1, 2, 0, trimFunc ), diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 24a36e2c50..8e79133200 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1629,7 +1629,7 @@ struct FuncDestructor { #define SQLITE_FUNC_SLOCHNG 0x2000 /* "Slow Change". Value constant during a ** single query - might change over time */ #define SQLITE_FUNC_AFFINITY 0x4000 /* Built-in affinity() function */ -#define SQLITE_FUNC_LOCATION 0x8000 /* Built-in location() function */ +#define SQLITE_FUNC_OFFSET 0x8000 /* Built-in sqlite_offset() function */ /* ** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are diff --git a/src/test_config.c b/src/test_config.c index 24a7287da2..ad63016baf 100644 --- a/src/test_config.c +++ b/src/test_config.c @@ -160,6 +160,12 @@ static void set_options(Tcl_Interp *interp){ Tcl_SetVar2(interp, "sqlite_options", "mem5", "0", TCL_GLOBAL_ONLY); #endif +#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC + Tcl_SetVar2(interp, "sqlite_options", "offset_sql_func","1",TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "offset_sql_func","0",TCL_GLOBAL_ONLY); +#endif + #ifdef SQLITE_ENABLE_PREUPDATE_HOOK Tcl_SetVar2(interp, "sqlite_options", "preupdate", "1", TCL_GLOBAL_ONLY); #else diff --git a/src/vdbe.c b/src/vdbe.c index 68762ae5e1..26336d940b 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -2349,19 +2349,23 @@ case OP_IfNullRow: { /* jump */ break; } -/* Opcode: Location P1 P2 P3 * * -** Synopsis: r[P3] = location(P1) +#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC +/* Opcode: Offset P1 P2 P3 * * +** Synopsis: r[P3] = sqlite_offset(P1) ** -** Store in register r[P3] the location in the database file that is the +** Store in register r[P3] the byte offset into the database file that is the ** start of the payload for the record at which that cursor P1 is currently ** pointing. ** -** P2 is the column number for the argument to the location() function. +** P2 is the column number for the argument to the sqlite_offset() function. ** This opcode does not use P2 itself, but the P2 value is used by the ** code generator. The P1, P2, and P3 operands to this opcode are the ** as as for OP_Column. +** +** This opcode is only available if SQLite is compiled with the +** -DSQLITE_ENABLE_OFFSET_SQL_FUNC option. */ -case OP_Location: { /* out3 */ +case OP_Offset: { /* out3 */ VdbeCursor *pC; /* The VDBE cursor */ assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; @@ -2369,10 +2373,11 @@ case OP_Location: { /* out3 */ if( pC==0 || pC->eCurType!=CURTYPE_BTREE ){ sqlite3VdbeMemSetNull(pOut); }else{ - sqlite3VdbeMemSetInt64(pOut, sqlite3BtreeLocation(pC->uc.pCursor)); + sqlite3VdbeMemSetInt64(pOut, sqlite3BtreeOffset(pC->uc.pCursor)); } break; } +#endif /* SQLITE_ENABLE_OFFSET_SQL_FUNC */ /* Opcode: Column P1 P2 P3 P4 P5 ** Synopsis: r[P3]=PX diff --git a/src/where.c b/src/where.c index 146c8124c8..ec53527943 100644 --- a/src/where.c +++ b/src/where.c @@ -5146,7 +5146,11 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){ pOp = sqlite3VdbeGetOp(v, k); for(; kp1!=pLevel->iTabCur ) continue; - if( pOp->opcode==OP_Column || pOp->opcode==OP_Location ){ + if( pOp->opcode==OP_Column +#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC + || pOp->opcode==OP_Offset +#endif + ){ int x = pOp->p2; assert( pIdx->pTable==pTab ); if( !HasRowid(pTab) ){ diff --git a/test/func6.test b/test/func6.test index 3630aa33db..ff05ee78c5 100644 --- a/test/func6.test +++ b/test/func6.test @@ -9,10 +9,14 @@ # #************************************************************************* # -# Test cases for the location() function. +# Test cases for the sqlite_unsupported_offset() function. # set testdir [file dirname $argv0] source $testdir/tester.tcl +ifcapable !offset_sql_func { + finish_test + return +} do_execsql_test func6-100 { CREATE TABLE t1(a,b,c,d); @@ -20,17 +24,21 @@ do_execsql_test func6-100 { INSERT INTO t1(a,b,c,d) SELECT printf('abc%03x',x), x, 1000-x, NULL FROM c; } do_execsql_test func6-110 { - SELECT a, typeof(location(a)) FROM t1 ORDER BY rowid LIMIT 2; + SELECT a, typeof(sqlite_unsupported_offset(a)) FROM t1 + ORDER BY rowid LIMIT 2; } {abc001 integer abc002 integer} do_execsql_test func6-120 { - SELECT a, typeof(location(+a)) FROM t1 ORDER BY rowid LIMIT 2; + SELECT a, typeof(sqlite_unsupported_offset(+a)) FROM t1 + ORDER BY rowid LIMIT 2; } {abc001 null abc002 null} do_execsql_test func6-130 { CREATE INDEX t1a ON t1(a); - SELECT a, typeof(location(a)) FROM t1 ORDER BY a LIMIT 2; + SELECT a, typeof(sqlite_unsupported_offset(a)) FROM t1 + ORDER BY a LIMIT 2; } {abc001 integer abc002 integer} do_execsql_test func6-140 { - SELECT a, typeof(location(a)) FROM t1 NOT INDEXED ORDER BY a LIMIT 2; + SELECT a, typeof(sqlite_unsupported_offset(a)) FROM t1 NOT INDEXED + ORDER BY a LIMIT 2; } {abc001 integer abc002 integer} finish_test From 23b440f8832a0d239d32008cb1f611508d88b89d Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 29 Dec 2017 15:19:03 +0000 Subject: [PATCH 4/5] Fix a typo in the MSVC makefile. FossilOrigin-Name: 89e5720a8d8d46d4e2f16f15678e91336117e64abc977174e2b345a30308d0d2 --- Makefile.msc | 2 +- manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Makefile.msc b/Makefile.msc index 94fa32dc3a..27eb23a240 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -1513,7 +1513,7 @@ FUZZDATA = \ !IF $(DYNAMIC_SHELL)==0 && $(FOR_WIN10)==0 SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_STMTVTAB SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_ENABLE_DBSTAT_VTAB -SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_EANBLE_OFFSET_SQL_FUNC +SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_OFFSET_SQL_FUNC !ENDIF # <> diff --git a/manifest b/manifest index 1328eaf9ce..3d0577aaea 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,8 @@ -C Change\sthe\sfunction\sname\sto\ssqlite_unsupported_offset(X).\s\sOnly\senable\sthe\nfunction\sif\scompiled\swith\s-DSQLITE_ENABLE_OFFSET_SQL_FUNC.\s\sThe\smakefiles\sadd\nthat\sdefinition\sto\sshell\sbuilds. -D 2017-12-29T15:04:49.734 +C Fix\sa\stypo\sin\sthe\sMSVC\smakefile. +D 2017-12-29T15:19:03.549 F Makefile.in 804c347948b0ad5a962aea3e59413e897227e0173d0e76910f11f473e6c7ae9b F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 -F Makefile.msc f11644a365122b16628da7839a8ed2e3a781b578a94cb1ebd25ebad260bdc9c2 +F Makefile.msc 57dcce0595d4a0c4b94b6f6ba732b8e33540358adf5fb8e1aa8389d34a9677e8 F README.md eeae1e552f93ef72ef7c5b8f6647b368a001c28820ad1df179d3dae602bef681 F VERSION 0c10cdfed866fdd2d80434f64f042c3330f1daaed12e54287beb104f04b3faaf F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@ -1688,7 +1688,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P dd94d6a880dfec4bddd247239b815b84964f804d24841e25f33f1d46a4b5274d -R 78409e335314d524c66761480a13a3e4 +P 7a7f826e324b1a2c332e2f1d0740fd0babffcaca6275a798572f02ad367b99ab +R 0e2a4a2bb72ba4dcfe2f3a815db6ddb3 U drh -Z 5cd44f60a8e786e38b3cacae6fe91794 +Z 9e1beeafb001196cab204d1af69f0fe2 diff --git a/manifest.uuid b/manifest.uuid index 9bbedd7b51..a57419f54c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7a7f826e324b1a2c332e2f1d0740fd0babffcaca6275a798572f02ad367b99ab \ No newline at end of file +89e5720a8d8d46d4e2f16f15678e91336117e64abc977174e2b345a30308d0d2 \ No newline at end of file From 9af41ff4524bce2756d807c43c09a15944f52ed1 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 29 Dec 2017 16:37:33 +0000 Subject: [PATCH 5/5] Stricter test cases. FossilOrigin-Name: 9406c0a685fd5ff3516a66402b0514a1440652822a5eecf0b7af85929f3079e8 --- manifest | 12 +++++------ manifest.uuid | 2 +- test/func6.test | 56 ++++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 56 insertions(+), 14 deletions(-) diff --git a/manifest b/manifest index 3d0577aaea..6b6ae42bc2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\stypo\sin\sthe\sMSVC\smakefile. -D 2017-12-29T15:19:03.549 +C Stricter\stest\scases. +D 2017-12-29T16:37:33.070 F Makefile.in 804c347948b0ad5a962aea3e59413e897227e0173d0e76910f11f473e6c7ae9b F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 57dcce0595d4a0c4b94b6f6ba732b8e33540358adf5fb8e1aa8389d34a9677e8 @@ -917,7 +917,7 @@ F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f F test/func3.test d202a7606d23f90988a664e88e268aed1087c11c F test/func4.test 6beacdfcb0e18c358e6c2dcacf1b65d1fa80955f F test/func5.test cdd224400bc3e48d891827cc913a57051a426fa4 -F test/func6.test 8a6ecb974a9d0bdeef6a06aff8e305b1667c3b922103037735b39c716360ebc2 +F test/func6.test 1a2bc511fedb779e2bd3154361385216c6d35080f36bfe896b8cdd1b1954294a F test/fuzz-oss1.test e58330d01cbbd8215ee636b17a03fe220b37dbfa F test/fuzz.test 96083052bf5765e4518c1ba686ce2bab785670d1 F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1 @@ -1688,7 +1688,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 7a7f826e324b1a2c332e2f1d0740fd0babffcaca6275a798572f02ad367b99ab -R 0e2a4a2bb72ba4dcfe2f3a815db6ddb3 +P 89e5720a8d8d46d4e2f16f15678e91336117e64abc977174e2b345a30308d0d2 +R 9cb794037b97521b258cb5fdbbf60d53 U drh -Z 9e1beeafb001196cab204d1af69f0fe2 +Z 8d1ee588df9bbfd069e3afd64819112f diff --git a/manifest.uuid b/manifest.uuid index a57419f54c..b37d8e1f54 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -89e5720a8d8d46d4e2f16f15678e91336117e64abc977174e2b345a30308d0d2 \ No newline at end of file +9406c0a685fd5ff3516a66402b0514a1440652822a5eecf0b7af85929f3079e8 \ No newline at end of file diff --git a/test/func6.test b/test/func6.test index ff05ee78c5..0d3de8ef49 100644 --- a/test/func6.test +++ b/test/func6.test @@ -11,6 +11,10 @@ # # Test cases for the sqlite_unsupported_offset() function. # +# Some of the tests in this file depend on the exact placement of content +# within b-tree pages. Such placement is at the implementations discretion, +# and so it is possible for results to change from one release to the next. +# set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable !offset_sql_func { @@ -19,26 +23,64 @@ ifcapable !offset_sql_func { } do_execsql_test func6-100 { + PRAGMA page_size=4096; + PRAGMA auto_vacuum=NONE; CREATE TABLE t1(a,b,c,d); WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100) INSERT INTO t1(a,b,c,d) SELECT printf('abc%03x',x), x, 1000-x, NULL FROM c; + CREATE INDEX t1a ON t1(a); + CREATE INDEX t1bc ON t1(b,c); + CREATE TABLE t2(x TEXT PRIMARY KEY, y) WITHOUT ROWID; + INSERT INTO t2(x,y) SELECT a, b FROM t1; } do_execsql_test func6-110 { - SELECT a, typeof(sqlite_unsupported_offset(a)) FROM t1 + SELECT a, sqlite_unsupported_offset(d)/4096 + 1, + sqlite_unsupported_offset(d)%4096 FROM t1 ORDER BY rowid LIMIT 2; -} {abc001 integer abc002 integer} +} {abc001 2 4084 abc002 2 4069} do_execsql_test func6-120 { SELECT a, typeof(sqlite_unsupported_offset(+a)) FROM t1 ORDER BY rowid LIMIT 2; } {abc001 null abc002 null} do_execsql_test func6-130 { - CREATE INDEX t1a ON t1(a); - SELECT a, typeof(sqlite_unsupported_offset(a)) FROM t1 + SELECT a, sqlite_unsupported_offset(a)/4096+1, + sqlite_unsupported_offset(a)%4096 + FROM t1 ORDER BY a LIMIT 2; -} {abc001 integer abc002 integer} +} {abc001 3 4087 abc002 3 4076} do_execsql_test func6-140 { - SELECT a, typeof(sqlite_unsupported_offset(a)) FROM t1 NOT INDEXED + SELECT a, sqlite_unsupported_offset(d)/4096+1, + sqlite_unsupported_offset(d)%4096 + FROM t1 ORDER BY a LIMIT 2; -} {abc001 integer abc002 integer} +} {abc001 2 4084 abc002 2 4069} +do_execsql_test func6-150 { + SELECT a, + sqlite_unsupported_offset(a)/4096+1, + sqlite_unsupported_offset(a)%4096, + sqlite_unsupported_offset(d)/4096+1, + sqlite_unsupported_offset(d)%4096 + FROM t1 + ORDER BY a LIMIT 2; +} {abc001 3 4087 2 4084 abc002 3 4076 2 4069} +do_execsql_test func6-160 { + SELECT b, + sqlite_unsupported_offset(b)/4096+1, + sqlite_unsupported_offset(b)%4096, + sqlite_unsupported_offset(c)/4096+1, + sqlite_unsupported_offset(c)%4096, + sqlite_unsupported_offset(d)/4096+1, + sqlite_unsupported_offset(d)%4096 + FROM t1 + ORDER BY b LIMIT 2; +} {1 4 4090 4 4090 2 4084 2 4 4081 4 4081 2 4069} + + +do_execsql_test func6-200 { + SELECT y, sqlite_unsupported_offset(y)/4096+1, + sqlite_unsupported_offset(y)%4096 + FROM t2 + ORDER BY x LIMIT 2; +} {1 5 4087 2 5 4076} finish_test