aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/btree.c13
-rw-r--r--src/btree.h1
-rw-r--r--src/expr.c15
-rw-r--r--src/func.c2
-rw-r--r--src/sqliteInt.h1
-rw-r--r--src/vdbe.c20
6 files changed, 49 insertions, 3 deletions
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
**