diff options
Diffstat (limited to 'src')
-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 |
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 ** |