diff options
Diffstat (limited to 'src/vdbeapi.c')
-rw-r--r-- | src/vdbeapi.c | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/src/vdbeapi.c b/src/vdbeapi.c index 17df807de..1521eee79 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -847,6 +847,83 @@ int sqlite3_vtab_nochange(sqlite3_context *p){ } /* +** The first argument is an iterator value created by VDBE instruction +** OP_VInitIn. The iterator is guaranteed to point to a valid entry. This +** function attempts to load the current value from the iterator into +** object pVal->u.pVal. If successful, (*ppOut) is set to point to +** pVal->u.pVal and SQLITE_OK is returned. Otherwise, if an error +** occurs, an SQLite error code is returned and (*ppOut) is left unchanged. +*/ +static int vtabInLoadValue(sqlite3_value *pVal, sqlite3_value **ppOut){ + BtCursor *pCsr = (BtCursor*)pVal->z; + sqlite3_value *pOut = pVal->u.pVal; + int sz; + int rc; + + sz = (int)sqlite3BtreePayloadSize(pCsr); + if( sz>pVal->szMalloc ){ + if( pVal->szMalloc==0 ) pVal->zMalloc = 0; + pVal->zMalloc = sqlite3DbReallocOrFree(pVal->db, pVal->zMalloc, sz*2); + if( pVal->zMalloc ){ + pVal->szMalloc = sqlite3DbMallocSize(pVal->db, pVal->zMalloc); + }else{ + pVal->szMalloc = 0; + return SQLITE_NOMEM_BKPT; + } + } + + rc = sqlite3BtreePayload(pCsr, 0, sz, pVal->zMalloc); + if( rc==SQLITE_OK ){ + u32 iSerial; + int iOff = 1 + getVarint32((const u8*)&pVal->zMalloc[1], iSerial); + sqlite3VdbeSerialGet((const u8*)&pVal->zMalloc[iOff], iSerial, pOut); + pOut->enc = ENC(pVal->db); + *ppOut = pOut; + } + return rc; +} + +/* +** Implementation of sqlite3_vtab_in_first() (if bNext==0) and +** sqlite3_vtab_in_next() (if bNext!=0). +*/ +static int vtabInOp(sqlite3_value *pVal, sqlite3_value **ppOut, int bNext){ + int rc = SQLITE_OK; + *ppOut = 0; + if( pVal && pVal->uTemp==SQLITE_VTAB_IN_MAGIC ){ + BtCursor *pCsr = (BtCursor*)pVal->z; + + if( bNext ){ + rc = sqlite3BtreeNext(pCsr, 0); + }else{ + int dummy = 0; + rc = sqlite3BtreeFirst(pCsr, &dummy); + } + + if( rc==SQLITE_OK && sqlite3BtreeEof(pCsr)==0 ){ + rc = vtabInLoadValue(pVal, ppOut); + } + } + return rc; +} + +/* +** Set the iterator value pVal to point to the first value in the set. +** Set (*ppOut) to point to this value before returning. +*/ +int sqlite3_vtab_in_first(sqlite3_value *pVal, sqlite3_value **ppOut){ + return vtabInOp(pVal, ppOut, 0); +} + +/* +** Set the iterator value pVal to point to the next value in the set. +** Set (*ppOut) to point to this value before returning. +*/ +int sqlite3_vtab_in_next(sqlite3_value *pVal, sqlite3_value **ppOut){ + return vtabInOp(pVal, ppOut, 1); +} + +/* ** Return the current time for a statement. If the current time ** is requested more than once within the same run of a single prepared ** statement, the exact same time is returned for each invocation regardless |