diff options
-rw-r--r-- | manifest | 23 | ||||
-rw-r--r-- | manifest.uuid | 2 | ||||
-rw-r--r-- | src/btree.c | 13 | ||||
-rw-r--r-- | src/btree.h | 1 | ||||
-rw-r--r-- | src/expr.c | 15 | ||||
-rw-r--r-- | src/func.c | 2 | ||||
-rw-r--r-- | src/sqliteInt.h | 1 | ||||
-rw-r--r-- | src/vdbe.c | 20 | ||||
-rw-r--r-- | test/func6.test | 36 |
9 files changed, 98 insertions, 15 deletions
@@ -1,5 +1,5 @@ -C Add\stest\scases\sfor\sthe\sundocumented\sbehavior\sof\sduplicate\scolumns\son\san\nINSERT\sor\sUPDATE. -D 2017-12-29T12:50:43.938 +C Merge\srecent\senhancements\sfrom\strunk. +D 2017-12-29T13:35:09.867 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 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 f03666d7f50caf4139eb777085833808028e8af6b6dfafa722b3e843a369a126 +F src/expr.c db1f29a1ee0c8a3abec55134ae7e149fa5684d77b569c6a62121b9e13becc43a 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 f3ec8f90dd698ea98781a90642c91eacbc24f4e55bb551c7b2762000d3ef55d F src/sqlite.h.in b4dc75265ed04b98e2184011a7dd0054ce2137ff84867a6be8b4f3bdfbc03d30 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h c02d628cca67f3889c689d82d25c3eb45e2c155db08e4c6089b5840d64687d34 -F src/sqliteInt.h 394655443ab2ee9bde2c2f629bd1e613d5ee211dd6c16995f68e6014bbe60b5d +F src/sqliteInt.h 623712d1ae728cc0ca78c9d8985b9665d89afff3082c1b664cbba08b0b01476d 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 7315e97a8dc2c8e19ca64196c652cf0a65d13fd0a211b2cec082062372dc6261 F src/vacuum.c 90839322fd5f00df9617eb21b68beda9b6e2a2937576b0d65985e4aeb1c53739 -F src/vdbe.c e0a1ca7539d7071d5fa582bdf27195a51197b5ae1ab0f143888b1561df592fd0 +F src/vdbe.c 742812438ab9c897db18025c6040af23feb4679fc63c53bdf25a9b190c7f91ec 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,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 0fdf97efe5df745510c6b4b377a8ee5683a3a237630bfbd0f56e57c7c6e5b246 -R 9fe2cb7c2c9b946d64749c1df6cc4954 +P 51be9558164301c5dd4df23ab8b3e67de0b522f8d36f79f3d84d45d3dc2a83a4 f4349c0c26611de8a7d5beb99431a575cf531cdeb0ca2413efabcf0a61e6f424 +R 21534cc483241840a2ab1c4e82c69566 U drh -Z 157cf27648c17a2b2af97b1730aa1c08 +Z 27f7d54e41b653412b0ccbce7bf65d00 diff --git a/manifest.uuid b/manifest.uuid index 3c028df06..c839229c6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f4349c0c26611de8a7d5beb99431a575cf531cdeb0ca2413efabcf0a61e6f424
\ No newline at end of file +6251e438f2a76170fd1e95aa512a46086ed88ab93b9b97a1dba97c4558689305
\ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 0fa00a2e1..d17cbde84 100644 --- a/src/btree.c +++ b/src/btree.c @@ -4433,6 +4433,19 @@ i64 sqlite3BtreeIntegerKey(BtCursor *pCur){ } /* +** 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 ** of data. For index btrees, this will be the size of the key. diff --git a/src/btree.h b/src/btree.h index e2c271cdc..43c0b9a8a 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 1592f1040..dbfc1b7ed 100644 --- a/src/expr.c +++ b/src/expr.c @@ -3870,9 +3870,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 7528fa8b4..f81c4865d 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 b11b5a8ad..24a36e2c5 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1629,6 +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 */ /* ** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are diff --git a/src/vdbe.c b/src/vdbe.c index 100556056..975a09819 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->p1<p->nCursor ); + 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 000000000..5350aeaa7 --- /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 |