mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-07 02:42:48 +03:00
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
This commit is contained in:
29
manifest
29
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
|
||||
|
@@ -1 +1 @@
|
||||
4c782c950204c09c1d8f857c39c4cf476539ec4e7eee6fd86419d47cf0f8b9e0
|
||||
51be9558164301c5dd4df23ab8b3e67de0b522f8d36f79f3d84d45d3dc2a83a4
|
13
src/btree.c
13
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
|
||||
|
@@ -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*);
|
||||
|
15
src/expr.c
15
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);
|
||||
}
|
||||
|
@@ -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 ),
|
||||
|
@@ -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
|
||||
|
20
src/vdbe.c
20
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
|
||||
**
|
||||
|
36
test/func6.test
Normal file
36
test/func6.test
Normal file
@@ -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
|
Reference in New Issue
Block a user