| Index: third_party/sqlite/amalgamation/sqlite3.03.c
|
| diff --git a/third_party/sqlite/amalgamation/sqlite3.03.c b/third_party/sqlite/amalgamation/sqlite3.03.c
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..a7afba7d0ab37f31b9a9c0d980a07f399c7eeb9d
|
| --- /dev/null
|
| +++ b/third_party/sqlite/amalgamation/sqlite3.03.c
|
| @@ -0,0 +1,25391 @@
|
| +/************** Begin file vdbemem.c *****************************************/
|
| +/*
|
| +** 2004 May 26
|
| +**
|
| +** 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.
|
| +**
|
| +*************************************************************************
|
| +**
|
| +** This file contains code use to manipulate "Mem" structure. A "Mem"
|
| +** stores a single value in the VDBE. Mem is an opaque structure visible
|
| +** only within the VDBE. Interface routines refer to a Mem using the
|
| +** name sqlite_value
|
| +*/
|
| +/* #include "sqliteInt.h" */
|
| +/* #include "vdbeInt.h" */
|
| +
|
| +#ifdef SQLITE_DEBUG
|
| +/*
|
| +** Check invariants on a Mem object.
|
| +**
|
| +** This routine is intended for use inside of assert() statements, like
|
| +** this: assert( sqlite3VdbeCheckMemInvariants(pMem) );
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3VdbeCheckMemInvariants(Mem *p){
|
| + /* If MEM_Dyn is set then Mem.xDel!=0.
|
| + ** Mem.xDel is might not be initialized if MEM_Dyn is clear.
|
| + */
|
| + assert( (p->flags & MEM_Dyn)==0 || p->xDel!=0 );
|
| +
|
| + /* MEM_Dyn may only be set if Mem.szMalloc==0. In this way we
|
| + ** ensure that if Mem.szMalloc>0 then it is safe to do
|
| + ** Mem.z = Mem.zMalloc without having to check Mem.flags&MEM_Dyn.
|
| + ** That saves a few cycles in inner loops. */
|
| + assert( (p->flags & MEM_Dyn)==0 || p->szMalloc==0 );
|
| +
|
| + /* Cannot be both MEM_Int and MEM_Real at the same time */
|
| + assert( (p->flags & (MEM_Int|MEM_Real))!=(MEM_Int|MEM_Real) );
|
| +
|
| + /* The szMalloc field holds the correct memory allocation size */
|
| + assert( p->szMalloc==0
|
| + || p->szMalloc==sqlite3DbMallocSize(p->db,p->zMalloc) );
|
| +
|
| + /* If p holds a string or blob, the Mem.z must point to exactly
|
| + ** one of the following:
|
| + **
|
| + ** (1) Memory in Mem.zMalloc and managed by the Mem object
|
| + ** (2) Memory to be freed using Mem.xDel
|
| + ** (3) An ephemeral string or blob
|
| + ** (4) A static string or blob
|
| + */
|
| + if( (p->flags & (MEM_Str|MEM_Blob)) && p->n>0 ){
|
| + assert(
|
| + ((p->szMalloc>0 && p->z==p->zMalloc)? 1 : 0) +
|
| + ((p->flags&MEM_Dyn)!=0 ? 1 : 0) +
|
| + ((p->flags&MEM_Ephem)!=0 ? 1 : 0) +
|
| + ((p->flags&MEM_Static)!=0 ? 1 : 0) == 1
|
| + );
|
| + }
|
| + return 1;
|
| +}
|
| +#endif
|
| +
|
| +
|
| +/*
|
| +** If pMem is an object with a valid string representation, this routine
|
| +** ensures the internal encoding for the string representation is
|
| +** 'desiredEnc', one of SQLITE_UTF8, SQLITE_UTF16LE or SQLITE_UTF16BE.
|
| +**
|
| +** If pMem is not a string object, or the encoding of the string
|
| +** representation is already stored using the requested encoding, then this
|
| +** routine is a no-op.
|
| +**
|
| +** SQLITE_OK is returned if the conversion is successful (or not required).
|
| +** SQLITE_NOMEM may be returned if a malloc() fails during conversion
|
| +** between formats.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){
|
| +#ifndef SQLITE_OMIT_UTF16
|
| + int rc;
|
| +#endif
|
| + assert( (pMem->flags&MEM_RowSet)==0 );
|
| + assert( desiredEnc==SQLITE_UTF8 || desiredEnc==SQLITE_UTF16LE
|
| + || desiredEnc==SQLITE_UTF16BE );
|
| + if( !(pMem->flags&MEM_Str) || pMem->enc==desiredEnc ){
|
| + return SQLITE_OK;
|
| + }
|
| + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
|
| +#ifdef SQLITE_OMIT_UTF16
|
| + return SQLITE_ERROR;
|
| +#else
|
| +
|
| + /* MemTranslate() may return SQLITE_OK or SQLITE_NOMEM. If NOMEM is returned,
|
| + ** then the encoding of the value may not have changed.
|
| + */
|
| + rc = sqlite3VdbeMemTranslate(pMem, (u8)desiredEnc);
|
| + assert(rc==SQLITE_OK || rc==SQLITE_NOMEM);
|
| + assert(rc==SQLITE_OK || pMem->enc!=desiredEnc);
|
| + assert(rc==SQLITE_NOMEM || pMem->enc==desiredEnc);
|
| + return rc;
|
| +#endif
|
| +}
|
| +
|
| +/*
|
| +** Make sure pMem->z points to a writable allocation of at least
|
| +** min(n,32) bytes.
|
| +**
|
| +** If the bPreserve argument is true, then copy of the content of
|
| +** pMem->z into the new allocation. pMem must be either a string or
|
| +** blob if bPreserve is true. If bPreserve is false, any prior content
|
| +** in pMem->z is discarded.
|
| +*/
|
| +SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){
|
| + assert( sqlite3VdbeCheckMemInvariants(pMem) );
|
| + assert( (pMem->flags&MEM_RowSet)==0 );
|
| +
|
| + /* If the bPreserve flag is set to true, then the memory cell must already
|
| + ** contain a valid string or blob value. */
|
| + assert( bPreserve==0 || pMem->flags&(MEM_Blob|MEM_Str) );
|
| + testcase( bPreserve && pMem->z==0 );
|
| +
|
| + assert( pMem->szMalloc==0
|
| + || pMem->szMalloc==sqlite3DbMallocSize(pMem->db, pMem->zMalloc) );
|
| + if( pMem->szMalloc<n ){
|
| + if( n<32 ) n = 32;
|
| + if( bPreserve && pMem->szMalloc>0 && pMem->z==pMem->zMalloc ){
|
| + pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n);
|
| + bPreserve = 0;
|
| + }else{
|
| + if( pMem->szMalloc>0 ) sqlite3DbFree(pMem->db, pMem->zMalloc);
|
| + pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, n);
|
| + }
|
| + if( pMem->zMalloc==0 ){
|
| + sqlite3VdbeMemSetNull(pMem);
|
| + pMem->z = 0;
|
| + pMem->szMalloc = 0;
|
| + return SQLITE_NOMEM;
|
| + }else{
|
| + pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc);
|
| + }
|
| + }
|
| +
|
| + if( bPreserve && pMem->z && pMem->z!=pMem->zMalloc ){
|
| + memcpy(pMem->zMalloc, pMem->z, pMem->n);
|
| + }
|
| + if( (pMem->flags&MEM_Dyn)!=0 ){
|
| + assert( pMem->xDel!=0 && pMem->xDel!=SQLITE_DYNAMIC );
|
| + pMem->xDel((void *)(pMem->z));
|
| + }
|
| +
|
| + pMem->z = pMem->zMalloc;
|
| + pMem->flags &= ~(MEM_Dyn|MEM_Ephem|MEM_Static);
|
| + return SQLITE_OK;
|
| +}
|
| +
|
| +/*
|
| +** Change the pMem->zMalloc allocation to be at least szNew bytes.
|
| +** If pMem->zMalloc already meets or exceeds the requested size, this
|
| +** routine is a no-op.
|
| +**
|
| +** Any prior string or blob content in the pMem object may be discarded.
|
| +** The pMem->xDel destructor is called, if it exists. Though MEM_Str
|
| +** and MEM_Blob values may be discarded, MEM_Int, MEM_Real, and MEM_Null
|
| +** values are preserved.
|
| +**
|
| +** Return SQLITE_OK on success or an error code (probably SQLITE_NOMEM)
|
| +** if unable to complete the resizing.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3VdbeMemClearAndResize(Mem *pMem, int szNew){
|
| + assert( szNew>0 );
|
| + assert( (pMem->flags & MEM_Dyn)==0 || pMem->szMalloc==0 );
|
| + if( pMem->szMalloc<szNew ){
|
| + return sqlite3VdbeMemGrow(pMem, szNew, 0);
|
| + }
|
| + assert( (pMem->flags & MEM_Dyn)==0 );
|
| + pMem->z = pMem->zMalloc;
|
| + pMem->flags &= (MEM_Null|MEM_Int|MEM_Real);
|
| + return SQLITE_OK;
|
| +}
|
| +
|
| +/*
|
| +** Change pMem so that its MEM_Str or MEM_Blob value is stored in
|
| +** MEM.zMalloc, where it can be safely written.
|
| +**
|
| +** Return SQLITE_OK on success or SQLITE_NOMEM if malloc fails.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem *pMem){
|
| + int f;
|
| + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
|
| + assert( (pMem->flags&MEM_RowSet)==0 );
|
| + ExpandBlob(pMem);
|
| + f = pMem->flags;
|
| + if( (f&(MEM_Str|MEM_Blob)) && (pMem->szMalloc==0 || pMem->z!=pMem->zMalloc) ){
|
| + if( sqlite3VdbeMemGrow(pMem, pMem->n + 2, 1) ){
|
| + return SQLITE_NOMEM;
|
| + }
|
| + pMem->z[pMem->n] = 0;
|
| + pMem->z[pMem->n+1] = 0;
|
| + pMem->flags |= MEM_Term;
|
| + }
|
| + pMem->flags &= ~MEM_Ephem;
|
| +#ifdef SQLITE_DEBUG
|
| + pMem->pScopyFrom = 0;
|
| +#endif
|
| +
|
| + return SQLITE_OK;
|
| +}
|
| +
|
| +/*
|
| +** If the given Mem* has a zero-filled tail, turn it into an ordinary
|
| +** blob stored in dynamically allocated space.
|
| +*/
|
| +#ifndef SQLITE_OMIT_INCRBLOB
|
| +SQLITE_PRIVATE int sqlite3VdbeMemExpandBlob(Mem *pMem){
|
| + if( pMem->flags & MEM_Zero ){
|
| + int nByte;
|
| + assert( pMem->flags&MEM_Blob );
|
| + assert( (pMem->flags&MEM_RowSet)==0 );
|
| + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
|
| +
|
| + /* Set nByte to the number of bytes required to store the expanded blob. */
|
| + nByte = pMem->n + pMem->u.nZero;
|
| + if( nByte<=0 ){
|
| + nByte = 1;
|
| + }
|
| + if( sqlite3VdbeMemGrow(pMem, nByte, 1) ){
|
| + return SQLITE_NOMEM;
|
| + }
|
| +
|
| + memset(&pMem->z[pMem->n], 0, pMem->u.nZero);
|
| + pMem->n += pMem->u.nZero;
|
| + pMem->flags &= ~(MEM_Zero|MEM_Term);
|
| + }
|
| + return SQLITE_OK;
|
| +}
|
| +#endif
|
| +
|
| +/*
|
| +** It is already known that pMem contains an unterminated string.
|
| +** Add the zero terminator.
|
| +*/
|
| +static SQLITE_NOINLINE int vdbeMemAddTerminator(Mem *pMem){
|
| + if( sqlite3VdbeMemGrow(pMem, pMem->n+2, 1) ){
|
| + return SQLITE_NOMEM;
|
| + }
|
| + pMem->z[pMem->n] = 0;
|
| + pMem->z[pMem->n+1] = 0;
|
| + pMem->flags |= MEM_Term;
|
| + return SQLITE_OK;
|
| +}
|
| +
|
| +/*
|
| +** Make sure the given Mem is \u0000 terminated.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3VdbeMemNulTerminate(Mem *pMem){
|
| + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
|
| + testcase( (pMem->flags & (MEM_Term|MEM_Str))==(MEM_Term|MEM_Str) );
|
| + testcase( (pMem->flags & (MEM_Term|MEM_Str))==0 );
|
| + if( (pMem->flags & (MEM_Term|MEM_Str))!=MEM_Str ){
|
| + return SQLITE_OK; /* Nothing to do */
|
| + }else{
|
| + return vdbeMemAddTerminator(pMem);
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Add MEM_Str to the set of representations for the given Mem. Numbers
|
| +** are converted using sqlite3_snprintf(). Converting a BLOB to a string
|
| +** is a no-op.
|
| +**
|
| +** Existing representations MEM_Int and MEM_Real are invalidated if
|
| +** bForce is true but are retained if bForce is false.
|
| +**
|
| +** A MEM_Null value will never be passed to this function. This function is
|
| +** used for converting values to text for returning to the user (i.e. via
|
| +** sqlite3_value_text()), or for ensuring that values to be used as btree
|
| +** keys are strings. In the former case a NULL pointer is returned the
|
| +** user and the latter is an internal programming error.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem *pMem, u8 enc, u8 bForce){
|
| + int fg = pMem->flags;
|
| + const int nByte = 32;
|
| +
|
| + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
|
| + assert( !(fg&MEM_Zero) );
|
| + assert( !(fg&(MEM_Str|MEM_Blob)) );
|
| + assert( fg&(MEM_Int|MEM_Real) );
|
| + assert( (pMem->flags&MEM_RowSet)==0 );
|
| + assert( EIGHT_BYTE_ALIGNMENT(pMem) );
|
| +
|
| +
|
| + if( sqlite3VdbeMemClearAndResize(pMem, nByte) ){
|
| + return SQLITE_NOMEM;
|
| + }
|
| +
|
| + /* For a Real or Integer, use sqlite3_snprintf() to produce the UTF-8
|
| + ** string representation of the value. Then, if the required encoding
|
| + ** is UTF-16le or UTF-16be do a translation.
|
| + **
|
| + ** FIX ME: It would be better if sqlite3_snprintf() could do UTF-16.
|
| + */
|
| + if( fg & MEM_Int ){
|
| + sqlite3_snprintf(nByte, pMem->z, "%lld", pMem->u.i);
|
| + }else{
|
| + assert( fg & MEM_Real );
|
| + sqlite3_snprintf(nByte, pMem->z, "%!.15g", pMem->u.r);
|
| + }
|
| + pMem->n = sqlite3Strlen30(pMem->z);
|
| + pMem->enc = SQLITE_UTF8;
|
| + pMem->flags |= MEM_Str|MEM_Term;
|
| + if( bForce ) pMem->flags &= ~(MEM_Int|MEM_Real);
|
| + sqlite3VdbeChangeEncoding(pMem, enc);
|
| + return SQLITE_OK;
|
| +}
|
| +
|
| +/*
|
| +** Memory cell pMem contains the context of an aggregate function.
|
| +** This routine calls the finalize method for that function. The
|
| +** result of the aggregate is stored back into pMem.
|
| +**
|
| +** Return SQLITE_ERROR if the finalizer reports an error. SQLITE_OK
|
| +** otherwise.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){
|
| + int rc = SQLITE_OK;
|
| + if( ALWAYS(pFunc && pFunc->xFinalize) ){
|
| + sqlite3_context ctx;
|
| + Mem t;
|
| + assert( (pMem->flags & MEM_Null)!=0 || pFunc==pMem->u.pDef );
|
| + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
|
| + memset(&ctx, 0, sizeof(ctx));
|
| + memset(&t, 0, sizeof(t));
|
| + t.flags = MEM_Null;
|
| + t.db = pMem->db;
|
| + ctx.pOut = &t;
|
| + ctx.pMem = pMem;
|
| + ctx.pFunc = pFunc;
|
| + pFunc->xFinalize(&ctx); /* IMP: R-24505-23230 */
|
| + assert( (pMem->flags & MEM_Dyn)==0 );
|
| + if( pMem->szMalloc>0 ) sqlite3DbFree(pMem->db, pMem->zMalloc);
|
| + memcpy(pMem, &t, sizeof(t));
|
| + rc = ctx.isError;
|
| + }
|
| + return rc;
|
| +}
|
| +
|
| +/*
|
| +** If the memory cell contains a value that must be freed by
|
| +** invoking the external callback in Mem.xDel, then this routine
|
| +** will free that value. It also sets Mem.flags to MEM_Null.
|
| +**
|
| +** This is a helper routine for sqlite3VdbeMemSetNull() and
|
| +** for sqlite3VdbeMemRelease(). Use those other routines as the
|
| +** entry point for releasing Mem resources.
|
| +*/
|
| +static SQLITE_NOINLINE void vdbeMemClearExternAndSetNull(Mem *p){
|
| + assert( p->db==0 || sqlite3_mutex_held(p->db->mutex) );
|
| + assert( VdbeMemDynamic(p) );
|
| + if( p->flags&MEM_Agg ){
|
| + sqlite3VdbeMemFinalize(p, p->u.pDef);
|
| + assert( (p->flags & MEM_Agg)==0 );
|
| + testcase( p->flags & MEM_Dyn );
|
| + }
|
| + if( p->flags&MEM_Dyn ){
|
| + assert( (p->flags&MEM_RowSet)==0 );
|
| + assert( p->xDel!=SQLITE_DYNAMIC && p->xDel!=0 );
|
| + p->xDel((void *)p->z);
|
| + }else if( p->flags&MEM_RowSet ){
|
| + sqlite3RowSetClear(p->u.pRowSet);
|
| + }else if( p->flags&MEM_Frame ){
|
| + VdbeFrame *pFrame = p->u.pFrame;
|
| + pFrame->pParent = pFrame->v->pDelFrame;
|
| + pFrame->v->pDelFrame = pFrame;
|
| + }
|
| + p->flags = MEM_Null;
|
| +}
|
| +
|
| +/*
|
| +** Release memory held by the Mem p, both external memory cleared
|
| +** by p->xDel and memory in p->zMalloc.
|
| +**
|
| +** This is a helper routine invoked by sqlite3VdbeMemRelease() in
|
| +** the unusual case where there really is memory in p that needs
|
| +** to be freed.
|
| +*/
|
| +static SQLITE_NOINLINE void vdbeMemClear(Mem *p){
|
| + if( VdbeMemDynamic(p) ){
|
| + vdbeMemClearExternAndSetNull(p);
|
| + }
|
| + if( p->szMalloc ){
|
| + sqlite3DbFree(p->db, p->zMalloc);
|
| + p->szMalloc = 0;
|
| + }
|
| + p->z = 0;
|
| +}
|
| +
|
| +/*
|
| +** Release any memory resources held by the Mem. Both the memory that is
|
| +** free by Mem.xDel and the Mem.zMalloc allocation are freed.
|
| +**
|
| +** Use this routine prior to clean up prior to abandoning a Mem, or to
|
| +** reset a Mem back to its minimum memory utilization.
|
| +**
|
| +** Use sqlite3VdbeMemSetNull() to release just the Mem.xDel space
|
| +** prior to inserting new content into the Mem.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p){
|
| + assert( sqlite3VdbeCheckMemInvariants(p) );
|
| + if( VdbeMemDynamic(p) || p->szMalloc ){
|
| + vdbeMemClear(p);
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Convert a 64-bit IEEE double into a 64-bit signed integer.
|
| +** If the double is out of range of a 64-bit signed integer then
|
| +** return the closest available 64-bit signed integer.
|
| +*/
|
| +static i64 doubleToInt64(double r){
|
| +#ifdef SQLITE_OMIT_FLOATING_POINT
|
| + /* When floating-point is omitted, double and int64 are the same thing */
|
| + return r;
|
| +#else
|
| + /*
|
| + ** Many compilers we encounter do not define constants for the
|
| + ** minimum and maximum 64-bit integers, or they define them
|
| + ** inconsistently. And many do not understand the "LL" notation.
|
| + ** So we define our own static constants here using nothing
|
| + ** larger than a 32-bit integer constant.
|
| + */
|
| + static const i64 maxInt = LARGEST_INT64;
|
| + static const i64 minInt = SMALLEST_INT64;
|
| +
|
| + if( r<=(double)minInt ){
|
| + return minInt;
|
| + }else if( r>=(double)maxInt ){
|
| + return maxInt;
|
| + }else{
|
| + return (i64)r;
|
| + }
|
| +#endif
|
| +}
|
| +
|
| +/*
|
| +** Return some kind of integer value which is the best we can do
|
| +** at representing the value that *pMem describes as an integer.
|
| +** If pMem is an integer, then the value is exact. If pMem is
|
| +** a floating-point then the value returned is the integer part.
|
| +** If pMem is a string or blob, then we make an attempt to convert
|
| +** it into an integer and return that. If pMem represents an
|
| +** an SQL-NULL value, return 0.
|
| +**
|
| +** If pMem represents a string value, its encoding might be changed.
|
| +*/
|
| +SQLITE_PRIVATE i64 sqlite3VdbeIntValue(Mem *pMem){
|
| + int flags;
|
| + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
|
| + assert( EIGHT_BYTE_ALIGNMENT(pMem) );
|
| + flags = pMem->flags;
|
| + if( flags & MEM_Int ){
|
| + return pMem->u.i;
|
| + }else if( flags & MEM_Real ){
|
| + return doubleToInt64(pMem->u.r);
|
| + }else if( flags & (MEM_Str|MEM_Blob) ){
|
| + i64 value = 0;
|
| + assert( pMem->z || pMem->n==0 );
|
| + sqlite3Atoi64(pMem->z, &value, pMem->n, pMem->enc);
|
| + return value;
|
| + }else{
|
| + return 0;
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Return the best representation of pMem that we can get into a
|
| +** double. If pMem is already a double or an integer, return its
|
| +** value. If it is a string or blob, try to convert it to a double.
|
| +** If it is a NULL, return 0.0.
|
| +*/
|
| +SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem *pMem){
|
| + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
|
| + assert( EIGHT_BYTE_ALIGNMENT(pMem) );
|
| + if( pMem->flags & MEM_Real ){
|
| + return pMem->u.r;
|
| + }else if( pMem->flags & MEM_Int ){
|
| + return (double)pMem->u.i;
|
| + }else if( pMem->flags & (MEM_Str|MEM_Blob) ){
|
| + /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
|
| + double val = (double)0;
|
| + sqlite3AtoF(pMem->z, &val, pMem->n, pMem->enc);
|
| + return val;
|
| + }else{
|
| + /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
|
| + return (double)0;
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** The MEM structure is already a MEM_Real. Try to also make it a
|
| +** MEM_Int if we can.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem *pMem){
|
| + i64 ix;
|
| + assert( pMem->flags & MEM_Real );
|
| + assert( (pMem->flags & MEM_RowSet)==0 );
|
| + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
|
| + assert( EIGHT_BYTE_ALIGNMENT(pMem) );
|
| +
|
| + ix = doubleToInt64(pMem->u.r);
|
| +
|
| + /* Only mark the value as an integer if
|
| + **
|
| + ** (1) the round-trip conversion real->int->real is a no-op, and
|
| + ** (2) The integer is neither the largest nor the smallest
|
| + ** possible integer (ticket #3922)
|
| + **
|
| + ** The second and third terms in the following conditional enforces
|
| + ** the second condition under the assumption that addition overflow causes
|
| + ** values to wrap around.
|
| + */
|
| + if( pMem->u.r==ix && ix>SMALLEST_INT64 && ix<LARGEST_INT64 ){
|
| + pMem->u.i = ix;
|
| + MemSetTypeFlag(pMem, MEM_Int);
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Convert pMem to type integer. Invalidate any prior representations.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3VdbeMemIntegerify(Mem *pMem){
|
| + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
|
| + assert( (pMem->flags & MEM_RowSet)==0 );
|
| + assert( EIGHT_BYTE_ALIGNMENT(pMem) );
|
| +
|
| + pMem->u.i = sqlite3VdbeIntValue(pMem);
|
| + MemSetTypeFlag(pMem, MEM_Int);
|
| + return SQLITE_OK;
|
| +}
|
| +
|
| +/*
|
| +** Convert pMem so that it is of type MEM_Real.
|
| +** Invalidate any prior representations.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem *pMem){
|
| + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
|
| + assert( EIGHT_BYTE_ALIGNMENT(pMem) );
|
| +
|
| + pMem->u.r = sqlite3VdbeRealValue(pMem);
|
| + MemSetTypeFlag(pMem, MEM_Real);
|
| + return SQLITE_OK;
|
| +}
|
| +
|
| +/*
|
| +** Convert pMem so that it has types MEM_Real or MEM_Int or both.
|
| +** Invalidate any prior representations.
|
| +**
|
| +** Every effort is made to force the conversion, even if the input
|
| +** is a string that does not look completely like a number. Convert
|
| +** as much of the string as we can and ignore the rest.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem *pMem){
|
| + if( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))==0 ){
|
| + assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 );
|
| + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
|
| + if( 0==sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc) ){
|
| + MemSetTypeFlag(pMem, MEM_Int);
|
| + }else{
|
| + pMem->u.r = sqlite3VdbeRealValue(pMem);
|
| + MemSetTypeFlag(pMem, MEM_Real);
|
| + sqlite3VdbeIntegerAffinity(pMem);
|
| + }
|
| + }
|
| + assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))!=0 );
|
| + pMem->flags &= ~(MEM_Str|MEM_Blob);
|
| + return SQLITE_OK;
|
| +}
|
| +
|
| +/*
|
| +** Cast the datatype of the value in pMem according to the affinity
|
| +** "aff". Casting is different from applying affinity in that a cast
|
| +** is forced. In other words, the value is converted into the desired
|
| +** affinity even if that results in loss of data. This routine is
|
| +** used (for example) to implement the SQL "cast()" operator.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbeMemCast(Mem *pMem, u8 aff, u8 encoding){
|
| + if( pMem->flags & MEM_Null ) return;
|
| + switch( aff ){
|
| + case SQLITE_AFF_BLOB: { /* Really a cast to BLOB */
|
| + if( (pMem->flags & MEM_Blob)==0 ){
|
| + sqlite3ValueApplyAffinity(pMem, SQLITE_AFF_TEXT, encoding);
|
| + assert( pMem->flags & MEM_Str || pMem->db->mallocFailed );
|
| + MemSetTypeFlag(pMem, MEM_Blob);
|
| + }else{
|
| + pMem->flags &= ~(MEM_TypeMask&~MEM_Blob);
|
| + }
|
| + break;
|
| + }
|
| + case SQLITE_AFF_NUMERIC: {
|
| + sqlite3VdbeMemNumerify(pMem);
|
| + break;
|
| + }
|
| + case SQLITE_AFF_INTEGER: {
|
| + sqlite3VdbeMemIntegerify(pMem);
|
| + break;
|
| + }
|
| + case SQLITE_AFF_REAL: {
|
| + sqlite3VdbeMemRealify(pMem);
|
| + break;
|
| + }
|
| + default: {
|
| + assert( aff==SQLITE_AFF_TEXT );
|
| + assert( MEM_Str==(MEM_Blob>>3) );
|
| + pMem->flags |= (pMem->flags&MEM_Blob)>>3;
|
| + sqlite3ValueApplyAffinity(pMem, SQLITE_AFF_TEXT, encoding);
|
| + assert( pMem->flags & MEM_Str || pMem->db->mallocFailed );
|
| + pMem->flags &= ~(MEM_Int|MEM_Real|MEM_Blob|MEM_Zero);
|
| + break;
|
| + }
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Initialize bulk memory to be a consistent Mem object.
|
| +**
|
| +** The minimum amount of initialization feasible is performed.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbeMemInit(Mem *pMem, sqlite3 *db, u16 flags){
|
| + assert( (flags & ~MEM_TypeMask)==0 );
|
| + pMem->flags = flags;
|
| + pMem->db = db;
|
| + pMem->szMalloc = 0;
|
| +}
|
| +
|
| +
|
| +/*
|
| +** Delete any previous value and set the value stored in *pMem to NULL.
|
| +**
|
| +** This routine calls the Mem.xDel destructor to dispose of values that
|
| +** require the destructor. But it preserves the Mem.zMalloc memory allocation.
|
| +** To free all resources, use sqlite3VdbeMemRelease(), which both calls this
|
| +** routine to invoke the destructor and deallocates Mem.zMalloc.
|
| +**
|
| +** Use this routine to reset the Mem prior to insert a new value.
|
| +**
|
| +** Use sqlite3VdbeMemRelease() to complete erase the Mem prior to abandoning it.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbeMemSetNull(Mem *pMem){
|
| + if( VdbeMemDynamic(pMem) ){
|
| + vdbeMemClearExternAndSetNull(pMem);
|
| + }else{
|
| + pMem->flags = MEM_Null;
|
| + }
|
| +}
|
| +SQLITE_PRIVATE void sqlite3ValueSetNull(sqlite3_value *p){
|
| + sqlite3VdbeMemSetNull((Mem*)p);
|
| +}
|
| +
|
| +/*
|
| +** Delete any previous value and set the value to be a BLOB of length
|
| +** n containing all zeros.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbeMemSetZeroBlob(Mem *pMem, int n){
|
| + sqlite3VdbeMemRelease(pMem);
|
| + pMem->flags = MEM_Blob|MEM_Zero;
|
| + pMem->n = 0;
|
| + if( n<0 ) n = 0;
|
| + pMem->u.nZero = n;
|
| + pMem->enc = SQLITE_UTF8;
|
| + pMem->z = 0;
|
| +}
|
| +
|
| +/*
|
| +** The pMem is known to contain content that needs to be destroyed prior
|
| +** to a value change. So invoke the destructor, then set the value to
|
| +** a 64-bit integer.
|
| +*/
|
| +static SQLITE_NOINLINE void vdbeReleaseAndSetInt64(Mem *pMem, i64 val){
|
| + sqlite3VdbeMemSetNull(pMem);
|
| + pMem->u.i = val;
|
| + pMem->flags = MEM_Int;
|
| +}
|
| +
|
| +/*
|
| +** Delete any previous value and set the value stored in *pMem to val,
|
| +** manifest type INTEGER.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem *pMem, i64 val){
|
| + if( VdbeMemDynamic(pMem) ){
|
| + vdbeReleaseAndSetInt64(pMem, val);
|
| + }else{
|
| + pMem->u.i = val;
|
| + pMem->flags = MEM_Int;
|
| + }
|
| +}
|
| +
|
| +#ifndef SQLITE_OMIT_FLOATING_POINT
|
| +/*
|
| +** Delete any previous value and set the value stored in *pMem to val,
|
| +** manifest type REAL.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem *pMem, double val){
|
| + sqlite3VdbeMemSetNull(pMem);
|
| + if( !sqlite3IsNaN(val) ){
|
| + pMem->u.r = val;
|
| + pMem->flags = MEM_Real;
|
| + }
|
| +}
|
| +#endif
|
| +
|
| +/*
|
| +** Delete any previous value and set the value of pMem to be an
|
| +** empty boolean index.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbeMemSetRowSet(Mem *pMem){
|
| + sqlite3 *db = pMem->db;
|
| + assert( db!=0 );
|
| + assert( (pMem->flags & MEM_RowSet)==0 );
|
| + sqlite3VdbeMemRelease(pMem);
|
| + pMem->zMalloc = sqlite3DbMallocRaw(db, 64);
|
| + if( db->mallocFailed ){
|
| + pMem->flags = MEM_Null;
|
| + pMem->szMalloc = 0;
|
| + }else{
|
| + assert( pMem->zMalloc );
|
| + pMem->szMalloc = sqlite3DbMallocSize(db, pMem->zMalloc);
|
| + pMem->u.pRowSet = sqlite3RowSetInit(db, pMem->zMalloc, pMem->szMalloc);
|
| + assert( pMem->u.pRowSet!=0 );
|
| + pMem->flags = MEM_RowSet;
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Return true if the Mem object contains a TEXT or BLOB that is
|
| +** too large - whose size exceeds SQLITE_MAX_LENGTH.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3VdbeMemTooBig(Mem *p){
|
| + assert( p->db!=0 );
|
| + if( p->flags & (MEM_Str|MEM_Blob) ){
|
| + int n = p->n;
|
| + if( p->flags & MEM_Zero ){
|
| + n += p->u.nZero;
|
| + }
|
| + return n>p->db->aLimit[SQLITE_LIMIT_LENGTH];
|
| + }
|
| + return 0;
|
| +}
|
| +
|
| +#ifdef SQLITE_DEBUG
|
| +/*
|
| +** This routine prepares a memory cell for modification by breaking
|
| +** its link to a shallow copy and by marking any current shallow
|
| +** copies of this cell as invalid.
|
| +**
|
| +** This is used for testing and debugging only - to make sure shallow
|
| +** copies are not misused.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbeMemAboutToChange(Vdbe *pVdbe, Mem *pMem){
|
| + int i;
|
| + Mem *pX;
|
| + for(i=1, pX=&pVdbe->aMem[1]; i<=pVdbe->nMem; i++, pX++){
|
| + if( pX->pScopyFrom==pMem ){
|
| + pX->flags |= MEM_Undefined;
|
| + pX->pScopyFrom = 0;
|
| + }
|
| + }
|
| + pMem->pScopyFrom = 0;
|
| +}
|
| +#endif /* SQLITE_DEBUG */
|
| +
|
| +
|
| +/*
|
| +** Make an shallow copy of pFrom into pTo. Prior contents of
|
| +** pTo are freed. The pFrom->z field is not duplicated. If
|
| +** pFrom->z is used, then pTo->z points to the same thing as pFrom->z
|
| +** and flags gets srcType (either MEM_Ephem or MEM_Static).
|
| +*/
|
| +static SQLITE_NOINLINE void vdbeClrCopy(Mem *pTo, const Mem *pFrom, int eType){
|
| + vdbeMemClearExternAndSetNull(pTo);
|
| + assert( !VdbeMemDynamic(pTo) );
|
| + sqlite3VdbeMemShallowCopy(pTo, pFrom, eType);
|
| +}
|
| +SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){
|
| + assert( (pFrom->flags & MEM_RowSet)==0 );
|
| + assert( pTo->db==pFrom->db );
|
| + if( VdbeMemDynamic(pTo) ){ vdbeClrCopy(pTo,pFrom,srcType); return; }
|
| + memcpy(pTo, pFrom, MEMCELLSIZE);
|
| + if( (pFrom->flags&MEM_Static)==0 ){
|
| + pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Ephem);
|
| + assert( srcType==MEM_Ephem || srcType==MEM_Static );
|
| + pTo->flags |= srcType;
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Make a full copy of pFrom into pTo. Prior contents of pTo are
|
| +** freed before the copy is made.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){
|
| + int rc = SQLITE_OK;
|
| +
|
| + /* The pFrom==0 case in the following assert() is when an sqlite3_value
|
| + ** from sqlite3_value_dup() is used as the argument
|
| + ** to sqlite3_result_value(). */
|
| + assert( pTo->db==pFrom->db || pFrom->db==0 );
|
| + assert( (pFrom->flags & MEM_RowSet)==0 );
|
| + if( VdbeMemDynamic(pTo) ) vdbeMemClearExternAndSetNull(pTo);
|
| + memcpy(pTo, pFrom, MEMCELLSIZE);
|
| + pTo->flags &= ~MEM_Dyn;
|
| + if( pTo->flags&(MEM_Str|MEM_Blob) ){
|
| + if( 0==(pFrom->flags&MEM_Static) ){
|
| + pTo->flags |= MEM_Ephem;
|
| + rc = sqlite3VdbeMemMakeWriteable(pTo);
|
| + }
|
| + }
|
| +
|
| + return rc;
|
| +}
|
| +
|
| +/*
|
| +** Transfer the contents of pFrom to pTo. Any existing value in pTo is
|
| +** freed. If pFrom contains ephemeral data, a copy is made.
|
| +**
|
| +** pFrom contains an SQL NULL when this routine returns.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbeMemMove(Mem *pTo, Mem *pFrom){
|
| + assert( pFrom->db==0 || sqlite3_mutex_held(pFrom->db->mutex) );
|
| + assert( pTo->db==0 || sqlite3_mutex_held(pTo->db->mutex) );
|
| + assert( pFrom->db==0 || pTo->db==0 || pFrom->db==pTo->db );
|
| +
|
| + sqlite3VdbeMemRelease(pTo);
|
| + memcpy(pTo, pFrom, sizeof(Mem));
|
| + pFrom->flags = MEM_Null;
|
| + pFrom->szMalloc = 0;
|
| +}
|
| +
|
| +/*
|
| +** Change the value of a Mem to be a string or a BLOB.
|
| +**
|
| +** The memory management strategy depends on the value of the xDel
|
| +** parameter. If the value passed is SQLITE_TRANSIENT, then the
|
| +** string is copied into a (possibly existing) buffer managed by the
|
| +** Mem structure. Otherwise, any existing buffer is freed and the
|
| +** pointer copied.
|
| +**
|
| +** If the string is too large (if it exceeds the SQLITE_LIMIT_LENGTH
|
| +** size limit) then no memory allocation occurs. If the string can be
|
| +** stored without allocating memory, then it is. If a memory allocation
|
| +** is required to store the string, then value of pMem is unchanged. In
|
| +** either case, SQLITE_TOOBIG is returned.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3VdbeMemSetStr(
|
| + Mem *pMem, /* Memory cell to set to string value */
|
| + const char *z, /* String pointer */
|
| + int n, /* Bytes in string, or negative */
|
| + u8 enc, /* Encoding of z. 0 for BLOBs */
|
| + void (*xDel)(void*) /* Destructor function */
|
| +){
|
| + int nByte = n; /* New value for pMem->n */
|
| + int iLimit; /* Maximum allowed string or blob size */
|
| + u16 flags = 0; /* New value for pMem->flags */
|
| +
|
| + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
|
| + assert( (pMem->flags & MEM_RowSet)==0 );
|
| +
|
| + /* If z is a NULL pointer, set pMem to contain an SQL NULL. */
|
| + if( !z ){
|
| + sqlite3VdbeMemSetNull(pMem);
|
| + return SQLITE_OK;
|
| + }
|
| +
|
| + if( pMem->db ){
|
| + iLimit = pMem->db->aLimit[SQLITE_LIMIT_LENGTH];
|
| + }else{
|
| + iLimit = SQLITE_MAX_LENGTH;
|
| + }
|
| + flags = (enc==0?MEM_Blob:MEM_Str);
|
| + if( nByte<0 ){
|
| + assert( enc!=0 );
|
| + if( enc==SQLITE_UTF8 ){
|
| + nByte = sqlite3Strlen30(z);
|
| + if( nByte>iLimit ) nByte = iLimit+1;
|
| + }else{
|
| + for(nByte=0; nByte<=iLimit && (z[nByte] | z[nByte+1]); nByte+=2){}
|
| + }
|
| + flags |= MEM_Term;
|
| + }
|
| +
|
| + /* The following block sets the new values of Mem.z and Mem.xDel. It
|
| + ** also sets a flag in local variable "flags" to indicate the memory
|
| + ** management (one of MEM_Dyn or MEM_Static).
|
| + */
|
| + if( xDel==SQLITE_TRANSIENT ){
|
| + int nAlloc = nByte;
|
| + if( flags&MEM_Term ){
|
| + nAlloc += (enc==SQLITE_UTF8?1:2);
|
| + }
|
| + if( nByte>iLimit ){
|
| + return SQLITE_TOOBIG;
|
| + }
|
| + testcase( nAlloc==0 );
|
| + testcase( nAlloc==31 );
|
| + testcase( nAlloc==32 );
|
| + if( sqlite3VdbeMemClearAndResize(pMem, MAX(nAlloc,32)) ){
|
| + return SQLITE_NOMEM;
|
| + }
|
| + memcpy(pMem->z, z, nAlloc);
|
| + }else if( xDel==SQLITE_DYNAMIC ){
|
| + sqlite3VdbeMemRelease(pMem);
|
| + pMem->zMalloc = pMem->z = (char *)z;
|
| + pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc);
|
| + }else{
|
| + sqlite3VdbeMemRelease(pMem);
|
| + pMem->z = (char *)z;
|
| + pMem->xDel = xDel;
|
| + flags |= ((xDel==SQLITE_STATIC)?MEM_Static:MEM_Dyn);
|
| + }
|
| +
|
| + pMem->n = nByte;
|
| + pMem->flags = flags;
|
| + pMem->enc = (enc==0 ? SQLITE_UTF8 : enc);
|
| +
|
| +#ifndef SQLITE_OMIT_UTF16
|
| + if( pMem->enc!=SQLITE_UTF8 && sqlite3VdbeMemHandleBom(pMem) ){
|
| + return SQLITE_NOMEM;
|
| + }
|
| +#endif
|
| +
|
| + if( nByte>iLimit ){
|
| + return SQLITE_TOOBIG;
|
| + }
|
| +
|
| + return SQLITE_OK;
|
| +}
|
| +
|
| +/*
|
| +** Move data out of a btree key or data field and into a Mem structure.
|
| +** The data or key is taken from the entry that pCur is currently pointing
|
| +** to. offset and amt determine what portion of the data or key to retrieve.
|
| +** key is true to get the key or false to get data. The result is written
|
| +** into the pMem element.
|
| +**
|
| +** The pMem object must have been initialized. This routine will use
|
| +** pMem->zMalloc to hold the content from the btree, if possible. New
|
| +** pMem->zMalloc space will be allocated if necessary. The calling routine
|
| +** is responsible for making sure that the pMem object is eventually
|
| +** destroyed.
|
| +**
|
| +** If this routine fails for any reason (malloc returns NULL or unable
|
| +** to read from the disk) then the pMem is left in an inconsistent state.
|
| +*/
|
| +static SQLITE_NOINLINE int vdbeMemFromBtreeResize(
|
| + BtCursor *pCur, /* Cursor pointing at record to retrieve. */
|
| + u32 offset, /* Offset from the start of data to return bytes from. */
|
| + u32 amt, /* Number of bytes to return. */
|
| + int key, /* If true, retrieve from the btree key, not data. */
|
| + Mem *pMem /* OUT: Return data in this Mem structure. */
|
| +){
|
| + int rc;
|
| + pMem->flags = MEM_Null;
|
| + if( SQLITE_OK==(rc = sqlite3VdbeMemClearAndResize(pMem, amt+2)) ){
|
| + if( key ){
|
| + rc = sqlite3BtreeKey(pCur, offset, amt, pMem->z);
|
| + }else{
|
| + rc = sqlite3BtreeData(pCur, offset, amt, pMem->z);
|
| + }
|
| + if( rc==SQLITE_OK ){
|
| + pMem->z[amt] = 0;
|
| + pMem->z[amt+1] = 0;
|
| + pMem->flags = MEM_Blob|MEM_Term;
|
| + pMem->n = (int)amt;
|
| + }else{
|
| + sqlite3VdbeMemRelease(pMem);
|
| + }
|
| + }
|
| + return rc;
|
| +}
|
| +SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(
|
| + BtCursor *pCur, /* Cursor pointing at record to retrieve. */
|
| + u32 offset, /* Offset from the start of data to return bytes from. */
|
| + u32 amt, /* Number of bytes to return. */
|
| + int key, /* If true, retrieve from the btree key, not data. */
|
| + Mem *pMem /* OUT: Return data in this Mem structure. */
|
| +){
|
| + char *zData; /* Data from the btree layer */
|
| + u32 available = 0; /* Number of bytes available on the local btree page */
|
| + int rc = SQLITE_OK; /* Return code */
|
| +
|
| + assert( sqlite3BtreeCursorIsValid(pCur) );
|
| + assert( !VdbeMemDynamic(pMem) );
|
| +
|
| + /* Note: the calls to BtreeKeyFetch() and DataFetch() below assert()
|
| + ** that both the BtShared and database handle mutexes are held. */
|
| + assert( (pMem->flags & MEM_RowSet)==0 );
|
| + if( key ){
|
| + zData = (char *)sqlite3BtreeKeyFetch(pCur, &available);
|
| + }else{
|
| + zData = (char *)sqlite3BtreeDataFetch(pCur, &available);
|
| + }
|
| + assert( zData!=0 );
|
| +
|
| + if( offset+amt<=available ){
|
| + pMem->z = &zData[offset];
|
| + pMem->flags = MEM_Blob|MEM_Ephem;
|
| + pMem->n = (int)amt;
|
| + }else{
|
| + rc = vdbeMemFromBtreeResize(pCur, offset, amt, key, pMem);
|
| + }
|
| +
|
| + return rc;
|
| +}
|
| +
|
| +/*
|
| +** The pVal argument is known to be a value other than NULL.
|
| +** Convert it into a string with encoding enc and return a pointer
|
| +** to a zero-terminated version of that string.
|
| +*/
|
| +static SQLITE_NOINLINE const void *valueToText(sqlite3_value* pVal, u8 enc){
|
| + assert( pVal!=0 );
|
| + assert( pVal->db==0 || sqlite3_mutex_held(pVal->db->mutex) );
|
| + assert( (enc&3)==(enc&~SQLITE_UTF16_ALIGNED) );
|
| + assert( (pVal->flags & MEM_RowSet)==0 );
|
| + assert( (pVal->flags & (MEM_Null))==0 );
|
| + if( pVal->flags & (MEM_Blob|MEM_Str) ){
|
| + pVal->flags |= MEM_Str;
|
| + if( pVal->flags & MEM_Zero ){
|
| + sqlite3VdbeMemExpandBlob(pVal);
|
| + }
|
| + if( pVal->enc != (enc & ~SQLITE_UTF16_ALIGNED) ){
|
| + sqlite3VdbeChangeEncoding(pVal, enc & ~SQLITE_UTF16_ALIGNED);
|
| + }
|
| + if( (enc & SQLITE_UTF16_ALIGNED)!=0 && 1==(1&SQLITE_PTR_TO_INT(pVal->z)) ){
|
| + assert( (pVal->flags & (MEM_Ephem|MEM_Static))!=0 );
|
| + if( sqlite3VdbeMemMakeWriteable(pVal)!=SQLITE_OK ){
|
| + return 0;
|
| + }
|
| + }
|
| + sqlite3VdbeMemNulTerminate(pVal); /* IMP: R-31275-44060 */
|
| + }else{
|
| + sqlite3VdbeMemStringify(pVal, enc, 0);
|
| + assert( 0==(1&SQLITE_PTR_TO_INT(pVal->z)) );
|
| + }
|
| + assert(pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) || pVal->db==0
|
| + || pVal->db->mallocFailed );
|
| + if( pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) ){
|
| + return pVal->z;
|
| + }else{
|
| + return 0;
|
| + }
|
| +}
|
| +
|
| +/* This function is only available internally, it is not part of the
|
| +** external API. It works in a similar way to sqlite3_value_text(),
|
| +** except the data returned is in the encoding specified by the second
|
| +** parameter, which must be one of SQLITE_UTF16BE, SQLITE_UTF16LE or
|
| +** SQLITE_UTF8.
|
| +**
|
| +** (2006-02-16:) The enc value can be or-ed with SQLITE_UTF16_ALIGNED.
|
| +** If that is the case, then the result must be aligned on an even byte
|
| +** boundary.
|
| +*/
|
| +SQLITE_PRIVATE const void *sqlite3ValueText(sqlite3_value* pVal, u8 enc){
|
| + if( !pVal ) return 0;
|
| + assert( pVal->db==0 || sqlite3_mutex_held(pVal->db->mutex) );
|
| + assert( (enc&3)==(enc&~SQLITE_UTF16_ALIGNED) );
|
| + assert( (pVal->flags & MEM_RowSet)==0 );
|
| + if( (pVal->flags&(MEM_Str|MEM_Term))==(MEM_Str|MEM_Term) && pVal->enc==enc ){
|
| + return pVal->z;
|
| + }
|
| + if( pVal->flags&MEM_Null ){
|
| + return 0;
|
| + }
|
| + return valueToText(pVal, enc);
|
| +}
|
| +
|
| +/*
|
| +** Create a new sqlite3_value object.
|
| +*/
|
| +SQLITE_PRIVATE sqlite3_value *sqlite3ValueNew(sqlite3 *db){
|
| + Mem *p = sqlite3DbMallocZero(db, sizeof(*p));
|
| + if( p ){
|
| + p->flags = MEM_Null;
|
| + p->db = db;
|
| + }
|
| + return p;
|
| +}
|
| +
|
| +/*
|
| +** Context object passed by sqlite3Stat4ProbeSetValue() through to
|
| +** valueNew(). See comments above valueNew() for details.
|
| +*/
|
| +struct ValueNewStat4Ctx {
|
| + Parse *pParse;
|
| + Index *pIdx;
|
| + UnpackedRecord **ppRec;
|
| + int iVal;
|
| +};
|
| +
|
| +/*
|
| +** Allocate and return a pointer to a new sqlite3_value object. If
|
| +** the second argument to this function is NULL, the object is allocated
|
| +** by calling sqlite3ValueNew().
|
| +**
|
| +** Otherwise, if the second argument is non-zero, then this function is
|
| +** being called indirectly by sqlite3Stat4ProbeSetValue(). If it has not
|
| +** already been allocated, allocate the UnpackedRecord structure that
|
| +** that function will return to its caller here. Then return a pointer to
|
| +** an sqlite3_value within the UnpackedRecord.a[] array.
|
| +*/
|
| +static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){
|
| +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
| + if( p ){
|
| + UnpackedRecord *pRec = p->ppRec[0];
|
| +
|
| + if( pRec==0 ){
|
| + Index *pIdx = p->pIdx; /* Index being probed */
|
| + int nByte; /* Bytes of space to allocate */
|
| + int i; /* Counter variable */
|
| + int nCol = pIdx->nColumn; /* Number of index columns including rowid */
|
| +
|
| + nByte = sizeof(Mem) * nCol + ROUND8(sizeof(UnpackedRecord));
|
| + pRec = (UnpackedRecord*)sqlite3DbMallocZero(db, nByte);
|
| + if( pRec ){
|
| + pRec->pKeyInfo = sqlite3KeyInfoOfIndex(p->pParse, pIdx);
|
| + if( pRec->pKeyInfo ){
|
| + assert( pRec->pKeyInfo->nField+pRec->pKeyInfo->nXField==nCol );
|
| + assert( pRec->pKeyInfo->enc==ENC(db) );
|
| + pRec->aMem = (Mem *)((u8*)pRec + ROUND8(sizeof(UnpackedRecord)));
|
| + for(i=0; i<nCol; i++){
|
| + pRec->aMem[i].flags = MEM_Null;
|
| + pRec->aMem[i].db = db;
|
| + }
|
| + }else{
|
| + sqlite3DbFree(db, pRec);
|
| + pRec = 0;
|
| + }
|
| + }
|
| + if( pRec==0 ) return 0;
|
| + p->ppRec[0] = pRec;
|
| + }
|
| +
|
| + pRec->nField = p->iVal+1;
|
| + return &pRec->aMem[p->iVal];
|
| + }
|
| +#else
|
| + UNUSED_PARAMETER(p);
|
| +#endif /* defined(SQLITE_ENABLE_STAT3_OR_STAT4) */
|
| + return sqlite3ValueNew(db);
|
| +}
|
| +
|
| +/*
|
| +** The expression object indicated by the second argument is guaranteed
|
| +** to be a scalar SQL function. If
|
| +**
|
| +** * all function arguments are SQL literals,
|
| +** * one of the SQLITE_FUNC_CONSTANT or _SLOCHNG function flags is set, and
|
| +** * the SQLITE_FUNC_NEEDCOLL function flag is not set,
|
| +**
|
| +** then this routine attempts to invoke the SQL function. Assuming no
|
| +** error occurs, output parameter (*ppVal) is set to point to a value
|
| +** object containing the result before returning SQLITE_OK.
|
| +**
|
| +** Affinity aff is applied to the result of the function before returning.
|
| +** If the result is a text value, the sqlite3_value object uses encoding
|
| +** enc.
|
| +**
|
| +** If the conditions above are not met, this function returns SQLITE_OK
|
| +** and sets (*ppVal) to NULL. Or, if an error occurs, (*ppVal) is set to
|
| +** NULL and an SQLite error code returned.
|
| +*/
|
| +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
| +static int valueFromFunction(
|
| + sqlite3 *db, /* The database connection */
|
| + Expr *p, /* The expression to evaluate */
|
| + u8 enc, /* Encoding to use */
|
| + u8 aff, /* Affinity to use */
|
| + sqlite3_value **ppVal, /* Write the new value here */
|
| + struct ValueNewStat4Ctx *pCtx /* Second argument for valueNew() */
|
| +){
|
| + sqlite3_context ctx; /* Context object for function invocation */
|
| + sqlite3_value **apVal = 0; /* Function arguments */
|
| + int nVal = 0; /* Size of apVal[] array */
|
| + FuncDef *pFunc = 0; /* Function definition */
|
| + sqlite3_value *pVal = 0; /* New value */
|
| + int rc = SQLITE_OK; /* Return code */
|
| + int nName; /* Size of function name in bytes */
|
| + ExprList *pList = 0; /* Function arguments */
|
| + int i; /* Iterator variable */
|
| +
|
| + assert( pCtx!=0 );
|
| + assert( (p->flags & EP_TokenOnly)==0 );
|
| + pList = p->x.pList;
|
| + if( pList ) nVal = pList->nExpr;
|
| + nName = sqlite3Strlen30(p->u.zToken);
|
| + pFunc = sqlite3FindFunction(db, p->u.zToken, nName, nVal, enc, 0);
|
| + assert( pFunc );
|
| + if( (pFunc->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG))==0
|
| + || (pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL)
|
| + ){
|
| + return SQLITE_OK;
|
| + }
|
| +
|
| + if( pList ){
|
| + apVal = (sqlite3_value**)sqlite3DbMallocZero(db, sizeof(apVal[0]) * nVal);
|
| + if( apVal==0 ){
|
| + rc = SQLITE_NOMEM;
|
| + goto value_from_function_out;
|
| + }
|
| + for(i=0; i<nVal; i++){
|
| + rc = sqlite3ValueFromExpr(db, pList->a[i].pExpr, enc, aff, &apVal[i]);
|
| + if( apVal[i]==0 || rc!=SQLITE_OK ) goto value_from_function_out;
|
| + }
|
| + }
|
| +
|
| + pVal = valueNew(db, pCtx);
|
| + if( pVal==0 ){
|
| + rc = SQLITE_NOMEM;
|
| + goto value_from_function_out;
|
| + }
|
| +
|
| + assert( pCtx->pParse->rc==SQLITE_OK );
|
| + memset(&ctx, 0, sizeof(ctx));
|
| + ctx.pOut = pVal;
|
| + ctx.pFunc = pFunc;
|
| + pFunc->xFunc(&ctx, nVal, apVal);
|
| + if( ctx.isError ){
|
| + rc = ctx.isError;
|
| + sqlite3ErrorMsg(pCtx->pParse, "%s", sqlite3_value_text(pVal));
|
| + }else{
|
| + sqlite3ValueApplyAffinity(pVal, aff, SQLITE_UTF8);
|
| + assert( rc==SQLITE_OK );
|
| + rc = sqlite3VdbeChangeEncoding(pVal, enc);
|
| + if( rc==SQLITE_OK && sqlite3VdbeMemTooBig(pVal) ){
|
| + rc = SQLITE_TOOBIG;
|
| + pCtx->pParse->nErr++;
|
| + }
|
| + }
|
| + pCtx->pParse->rc = rc;
|
| +
|
| + value_from_function_out:
|
| + if( rc!=SQLITE_OK ){
|
| + pVal = 0;
|
| + }
|
| + if( apVal ){
|
| + for(i=0; i<nVal; i++){
|
| + sqlite3ValueFree(apVal[i]);
|
| + }
|
| + sqlite3DbFree(db, apVal);
|
| + }
|
| +
|
| + *ppVal = pVal;
|
| + return rc;
|
| +}
|
| +#else
|
| +# define valueFromFunction(a,b,c,d,e,f) SQLITE_OK
|
| +#endif /* defined(SQLITE_ENABLE_STAT3_OR_STAT4) */
|
| +
|
| +/*
|
| +** Extract a value from the supplied expression in the manner described
|
| +** above sqlite3ValueFromExpr(). Allocate the sqlite3_value object
|
| +** using valueNew().
|
| +**
|
| +** If pCtx is NULL and an error occurs after the sqlite3_value object
|
| +** has been allocated, it is freed before returning. Or, if pCtx is not
|
| +** NULL, it is assumed that the caller will free any allocated object
|
| +** in all cases.
|
| +*/
|
| +static int valueFromExpr(
|
| + sqlite3 *db, /* The database connection */
|
| + Expr *pExpr, /* The expression to evaluate */
|
| + u8 enc, /* Encoding to use */
|
| + u8 affinity, /* Affinity to use */
|
| + sqlite3_value **ppVal, /* Write the new value here */
|
| + struct ValueNewStat4Ctx *pCtx /* Second argument for valueNew() */
|
| +){
|
| + int op;
|
| + char *zVal = 0;
|
| + sqlite3_value *pVal = 0;
|
| + int negInt = 1;
|
| + const char *zNeg = "";
|
| + int rc = SQLITE_OK;
|
| +
|
| + if( !pExpr ){
|
| + *ppVal = 0;
|
| + return SQLITE_OK;
|
| + }
|
| + while( (op = pExpr->op)==TK_UPLUS ) pExpr = pExpr->pLeft;
|
| + if( NEVER(op==TK_REGISTER) ) op = pExpr->op2;
|
| +
|
| + /* Compressed expressions only appear when parsing the DEFAULT clause
|
| + ** on a table column definition, and hence only when pCtx==0. This
|
| + ** check ensures that an EP_TokenOnly expression is never passed down
|
| + ** into valueFromFunction(). */
|
| + assert( (pExpr->flags & EP_TokenOnly)==0 || pCtx==0 );
|
| +
|
| + if( op==TK_CAST ){
|
| + u8 aff = sqlite3AffinityType(pExpr->u.zToken,0);
|
| + rc = valueFromExpr(db, pExpr->pLeft, enc, aff, ppVal, pCtx);
|
| + testcase( rc!=SQLITE_OK );
|
| + if( *ppVal ){
|
| + sqlite3VdbeMemCast(*ppVal, aff, SQLITE_UTF8);
|
| + sqlite3ValueApplyAffinity(*ppVal, affinity, SQLITE_UTF8);
|
| + }
|
| + return rc;
|
| + }
|
| +
|
| + /* Handle negative integers in a single step. This is needed in the
|
| + ** case when the value is -9223372036854775808.
|
| + */
|
| + if( op==TK_UMINUS
|
| + && (pExpr->pLeft->op==TK_INTEGER || pExpr->pLeft->op==TK_FLOAT) ){
|
| + pExpr = pExpr->pLeft;
|
| + op = pExpr->op;
|
| + negInt = -1;
|
| + zNeg = "-";
|
| + }
|
| +
|
| + if( op==TK_STRING || op==TK_FLOAT || op==TK_INTEGER ){
|
| + pVal = valueNew(db, pCtx);
|
| + if( pVal==0 ) goto no_mem;
|
| + if( ExprHasProperty(pExpr, EP_IntValue) ){
|
| + sqlite3VdbeMemSetInt64(pVal, (i64)pExpr->u.iValue*negInt);
|
| + }else{
|
| + zVal = sqlite3MPrintf(db, "%s%s", zNeg, pExpr->u.zToken);
|
| + if( zVal==0 ) goto no_mem;
|
| + sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC);
|
| + }
|
| + if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE_AFF_BLOB ){
|
| + sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, SQLITE_UTF8);
|
| + }else{
|
| + sqlite3ValueApplyAffinity(pVal, affinity, SQLITE_UTF8);
|
| + }
|
| + if( pVal->flags & (MEM_Int|MEM_Real) ) pVal->flags &= ~MEM_Str;
|
| + if( enc!=SQLITE_UTF8 ){
|
| + rc = sqlite3VdbeChangeEncoding(pVal, enc);
|
| + }
|
| + }else if( op==TK_UMINUS ) {
|
| + /* This branch happens for multiple negative signs. Ex: -(-5) */
|
| + if( SQLITE_OK==sqlite3ValueFromExpr(db,pExpr->pLeft,enc,affinity,&pVal)
|
| + && pVal!=0
|
| + ){
|
| + sqlite3VdbeMemNumerify(pVal);
|
| + if( pVal->flags & MEM_Real ){
|
| + pVal->u.r = -pVal->u.r;
|
| + }else if( pVal->u.i==SMALLEST_INT64 ){
|
| + pVal->u.r = -(double)SMALLEST_INT64;
|
| + MemSetTypeFlag(pVal, MEM_Real);
|
| + }else{
|
| + pVal->u.i = -pVal->u.i;
|
| + }
|
| + sqlite3ValueApplyAffinity(pVal, affinity, enc);
|
| + }
|
| + }else if( op==TK_NULL ){
|
| + pVal = valueNew(db, pCtx);
|
| + if( pVal==0 ) goto no_mem;
|
| + }
|
| +#ifndef SQLITE_OMIT_BLOB_LITERAL
|
| + else if( op==TK_BLOB ){
|
| + int nVal;
|
| + assert( pExpr->u.zToken[0]=='x' || pExpr->u.zToken[0]=='X' );
|
| + assert( pExpr->u.zToken[1]=='\'' );
|
| + pVal = valueNew(db, pCtx);
|
| + if( !pVal ) goto no_mem;
|
| + zVal = &pExpr->u.zToken[2];
|
| + nVal = sqlite3Strlen30(zVal)-1;
|
| + assert( zVal[nVal]=='\'' );
|
| + sqlite3VdbeMemSetStr(pVal, sqlite3HexToBlob(db, zVal, nVal), nVal/2,
|
| + 0, SQLITE_DYNAMIC);
|
| + }
|
| +#endif
|
| +
|
| +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
| + else if( op==TK_FUNCTION && pCtx!=0 ){
|
| + rc = valueFromFunction(db, pExpr, enc, affinity, &pVal, pCtx);
|
| + }
|
| +#endif
|
| +
|
| + *ppVal = pVal;
|
| + return rc;
|
| +
|
| +no_mem:
|
| + db->mallocFailed = 1;
|
| + sqlite3DbFree(db, zVal);
|
| + assert( *ppVal==0 );
|
| +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
| + if( pCtx==0 ) sqlite3ValueFree(pVal);
|
| +#else
|
| + assert( pCtx==0 ); sqlite3ValueFree(pVal);
|
| +#endif
|
| + return SQLITE_NOMEM;
|
| +}
|
| +
|
| +/*
|
| +** Create a new sqlite3_value object, containing the value of pExpr.
|
| +**
|
| +** This only works for very simple expressions that consist of one constant
|
| +** token (i.e. "5", "5.1", "'a string'"). If the expression can
|
| +** be converted directly into a value, then the value is allocated and
|
| +** a pointer written to *ppVal. The caller is responsible for deallocating
|
| +** the value by passing it to sqlite3ValueFree() later on. If the expression
|
| +** cannot be converted to a value, then *ppVal is set to NULL.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3ValueFromExpr(
|
| + sqlite3 *db, /* The database connection */
|
| + Expr *pExpr, /* The expression to evaluate */
|
| + u8 enc, /* Encoding to use */
|
| + u8 affinity, /* Affinity to use */
|
| + sqlite3_value **ppVal /* Write the new value here */
|
| +){
|
| + return valueFromExpr(db, pExpr, enc, affinity, ppVal, 0);
|
| +}
|
| +
|
| +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
| +/*
|
| +** The implementation of the sqlite_record() function. This function accepts
|
| +** a single argument of any type. The return value is a formatted database
|
| +** record (a blob) containing the argument value.
|
| +**
|
| +** This is used to convert the value stored in the 'sample' column of the
|
| +** sqlite_stat3 table to the record format SQLite uses internally.
|
| +*/
|
| +static void recordFunc(
|
| + sqlite3_context *context,
|
| + int argc,
|
| + sqlite3_value **argv
|
| +){
|
| + const int file_format = 1;
|
| + u32 iSerial; /* Serial type */
|
| + int nSerial; /* Bytes of space for iSerial as varint */
|
| + u32 nVal; /* Bytes of space required for argv[0] */
|
| + int nRet;
|
| + sqlite3 *db;
|
| + u8 *aRet;
|
| +
|
| + UNUSED_PARAMETER( argc );
|
| + iSerial = sqlite3VdbeSerialType(argv[0], file_format, &nVal);
|
| + nSerial = sqlite3VarintLen(iSerial);
|
| + db = sqlite3_context_db_handle(context);
|
| +
|
| + nRet = 1 + nSerial + nVal;
|
| + aRet = sqlite3DbMallocRaw(db, nRet);
|
| + if( aRet==0 ){
|
| + sqlite3_result_error_nomem(context);
|
| + }else{
|
| + aRet[0] = nSerial+1;
|
| + putVarint32(&aRet[1], iSerial);
|
| + sqlite3VdbeSerialPut(&aRet[1+nSerial], argv[0], iSerial);
|
| + sqlite3_result_blob(context, aRet, nRet, SQLITE_TRANSIENT);
|
| + sqlite3DbFree(db, aRet);
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Register built-in functions used to help read ANALYZE data.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3AnalyzeFunctions(void){
|
| + static SQLITE_WSD FuncDef aAnalyzeTableFuncs[] = {
|
| + FUNCTION(sqlite_record, 1, 0, 0, recordFunc),
|
| + };
|
| + int i;
|
| + FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
|
| + FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aAnalyzeTableFuncs);
|
| + for(i=0; i<ArraySize(aAnalyzeTableFuncs); i++){
|
| + sqlite3FuncDefInsert(pHash, &aFunc[i]);
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Attempt to extract a value from pExpr and use it to construct *ppVal.
|
| +**
|
| +** If pAlloc is not NULL, then an UnpackedRecord object is created for
|
| +** pAlloc if one does not exist and the new value is added to the
|
| +** UnpackedRecord object.
|
| +**
|
| +** A value is extracted in the following cases:
|
| +**
|
| +** * (pExpr==0). In this case the value is assumed to be an SQL NULL,
|
| +**
|
| +** * The expression is a bound variable, and this is a reprepare, or
|
| +**
|
| +** * The expression is a literal value.
|
| +**
|
| +** On success, *ppVal is made to point to the extracted value. The caller
|
| +** is responsible for ensuring that the value is eventually freed.
|
| +*/
|
| +static int stat4ValueFromExpr(
|
| + Parse *pParse, /* Parse context */
|
| + Expr *pExpr, /* The expression to extract a value from */
|
| + u8 affinity, /* Affinity to use */
|
| + struct ValueNewStat4Ctx *pAlloc,/* How to allocate space. Or NULL */
|
| + sqlite3_value **ppVal /* OUT: New value object (or NULL) */
|
| +){
|
| + int rc = SQLITE_OK;
|
| + sqlite3_value *pVal = 0;
|
| + sqlite3 *db = pParse->db;
|
| +
|
| + /* Skip over any TK_COLLATE nodes */
|
| + pExpr = sqlite3ExprSkipCollate(pExpr);
|
| +
|
| + if( !pExpr ){
|
| + pVal = valueNew(db, pAlloc);
|
| + if( pVal ){
|
| + sqlite3VdbeMemSetNull((Mem*)pVal);
|
| + }
|
| + }else if( pExpr->op==TK_VARIABLE
|
| + || NEVER(pExpr->op==TK_REGISTER && pExpr->op2==TK_VARIABLE)
|
| + ){
|
| + Vdbe *v;
|
| + int iBindVar = pExpr->iColumn;
|
| + sqlite3VdbeSetVarmask(pParse->pVdbe, iBindVar);
|
| + if( (v = pParse->pReprepare)!=0 ){
|
| + pVal = valueNew(db, pAlloc);
|
| + if( pVal ){
|
| + rc = sqlite3VdbeMemCopy((Mem*)pVal, &v->aVar[iBindVar-1]);
|
| + if( rc==SQLITE_OK ){
|
| + sqlite3ValueApplyAffinity(pVal, affinity, ENC(db));
|
| + }
|
| + pVal->db = pParse->db;
|
| + }
|
| + }
|
| + }else{
|
| + rc = valueFromExpr(db, pExpr, ENC(db), affinity, &pVal, pAlloc);
|
| + }
|
| +
|
| + assert( pVal==0 || pVal->db==db );
|
| + *ppVal = pVal;
|
| + return rc;
|
| +}
|
| +
|
| +/*
|
| +** This function is used to allocate and populate UnpackedRecord
|
| +** structures intended to be compared against sample index keys stored
|
| +** in the sqlite_stat4 table.
|
| +**
|
| +** A single call to this function attempts to populates field iVal (leftmost
|
| +** is 0 etc.) of the unpacked record with a value extracted from expression
|
| +** pExpr. Extraction of values is possible if:
|
| +**
|
| +** * (pExpr==0). In this case the value is assumed to be an SQL NULL,
|
| +**
|
| +** * The expression is a bound variable, and this is a reprepare, or
|
| +**
|
| +** * The sqlite3ValueFromExpr() function is able to extract a value
|
| +** from the expression (i.e. the expression is a literal value).
|
| +**
|
| +** If a value can be extracted, the affinity passed as the 5th argument
|
| +** is applied to it before it is copied into the UnpackedRecord. Output
|
| +** parameter *pbOk is set to true if a value is extracted, or false
|
| +** otherwise.
|
| +**
|
| +** When this function is called, *ppRec must either point to an object
|
| +** allocated by an earlier call to this function, or must be NULL. If it
|
| +** is NULL and a value can be successfully extracted, a new UnpackedRecord
|
| +** is allocated (and *ppRec set to point to it) before returning.
|
| +**
|
| +** Unless an error is encountered, SQLITE_OK is returned. It is not an
|
| +** error if a value cannot be extracted from pExpr. If an error does
|
| +** occur, an SQLite error code is returned.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3Stat4ProbeSetValue(
|
| + Parse *pParse, /* Parse context */
|
| + Index *pIdx, /* Index being probed */
|
| + UnpackedRecord **ppRec, /* IN/OUT: Probe record */
|
| + Expr *pExpr, /* The expression to extract a value from */
|
| + u8 affinity, /* Affinity to use */
|
| + int iVal, /* Array element to populate */
|
| + int *pbOk /* OUT: True if value was extracted */
|
| +){
|
| + int rc;
|
| + sqlite3_value *pVal = 0;
|
| + struct ValueNewStat4Ctx alloc;
|
| +
|
| + alloc.pParse = pParse;
|
| + alloc.pIdx = pIdx;
|
| + alloc.ppRec = ppRec;
|
| + alloc.iVal = iVal;
|
| +
|
| + rc = stat4ValueFromExpr(pParse, pExpr, affinity, &alloc, &pVal);
|
| + assert( pVal==0 || pVal->db==pParse->db );
|
| + *pbOk = (pVal!=0);
|
| + return rc;
|
| +}
|
| +
|
| +/*
|
| +** Attempt to extract a value from expression pExpr using the methods
|
| +** as described for sqlite3Stat4ProbeSetValue() above.
|
| +**
|
| +** If successful, set *ppVal to point to a new value object and return
|
| +** SQLITE_OK. If no value can be extracted, but no other error occurs
|
| +** (e.g. OOM), return SQLITE_OK and set *ppVal to NULL. Or, if an error
|
| +** does occur, return an SQLite error code. The final value of *ppVal
|
| +** is undefined in this case.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3Stat4ValueFromExpr(
|
| + Parse *pParse, /* Parse context */
|
| + Expr *pExpr, /* The expression to extract a value from */
|
| + u8 affinity, /* Affinity to use */
|
| + sqlite3_value **ppVal /* OUT: New value object (or NULL) */
|
| +){
|
| + return stat4ValueFromExpr(pParse, pExpr, affinity, 0, ppVal);
|
| +}
|
| +
|
| +/*
|
| +** Extract the iCol-th column from the nRec-byte record in pRec. Write
|
| +** the column value into *ppVal. If *ppVal is initially NULL then a new
|
| +** sqlite3_value object is allocated.
|
| +**
|
| +** If *ppVal is initially NULL then the caller is responsible for
|
| +** ensuring that the value written into *ppVal is eventually freed.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3Stat4Column(
|
| + sqlite3 *db, /* Database handle */
|
| + const void *pRec, /* Pointer to buffer containing record */
|
| + int nRec, /* Size of buffer pRec in bytes */
|
| + int iCol, /* Column to extract */
|
| + sqlite3_value **ppVal /* OUT: Extracted value */
|
| +){
|
| + u32 t; /* a column type code */
|
| + int nHdr; /* Size of the header in the record */
|
| + int iHdr; /* Next unread header byte */
|
| + int iField; /* Next unread data byte */
|
| + int szField; /* Size of the current data field */
|
| + int i; /* Column index */
|
| + u8 *a = (u8*)pRec; /* Typecast byte array */
|
| + Mem *pMem = *ppVal; /* Write result into this Mem object */
|
| +
|
| + assert( iCol>0 );
|
| + iHdr = getVarint32(a, nHdr);
|
| + if( nHdr>nRec || iHdr>=nHdr ) return SQLITE_CORRUPT_BKPT;
|
| + iField = nHdr;
|
| + for(i=0; i<=iCol; i++){
|
| + iHdr += getVarint32(&a[iHdr], t);
|
| + testcase( iHdr==nHdr );
|
| + testcase( iHdr==nHdr+1 );
|
| + if( iHdr>nHdr ) return SQLITE_CORRUPT_BKPT;
|
| + szField = sqlite3VdbeSerialTypeLen(t);
|
| + iField += szField;
|
| + }
|
| + testcase( iField==nRec );
|
| + testcase( iField==nRec+1 );
|
| + if( iField>nRec ) return SQLITE_CORRUPT_BKPT;
|
| + if( pMem==0 ){
|
| + pMem = *ppVal = sqlite3ValueNew(db);
|
| + if( pMem==0 ) return SQLITE_NOMEM;
|
| + }
|
| + sqlite3VdbeSerialGet(&a[iField-szField], t, pMem);
|
| + pMem->enc = ENC(db);
|
| + return SQLITE_OK;
|
| +}
|
| +
|
| +/*
|
| +** Unless it is NULL, the argument must be an UnpackedRecord object returned
|
| +** by an earlier call to sqlite3Stat4ProbeSetValue(). This call deletes
|
| +** the object.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3Stat4ProbeFree(UnpackedRecord *pRec){
|
| + if( pRec ){
|
| + int i;
|
| + int nCol = pRec->pKeyInfo->nField+pRec->pKeyInfo->nXField;
|
| + Mem *aMem = pRec->aMem;
|
| + sqlite3 *db = aMem[0].db;
|
| + for(i=0; i<nCol; i++){
|
| + sqlite3VdbeMemRelease(&aMem[i]);
|
| + }
|
| + sqlite3KeyInfoUnref(pRec->pKeyInfo);
|
| + sqlite3DbFree(db, pRec);
|
| + }
|
| +}
|
| +#endif /* ifdef SQLITE_ENABLE_STAT4 */
|
| +
|
| +/*
|
| +** Change the string value of an sqlite3_value object
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3ValueSetStr(
|
| + sqlite3_value *v, /* Value to be set */
|
| + int n, /* Length of string z */
|
| + const void *z, /* Text of the new string */
|
| + u8 enc, /* Encoding to use */
|
| + void (*xDel)(void*) /* Destructor for the string */
|
| +){
|
| + if( v ) sqlite3VdbeMemSetStr((Mem *)v, z, n, enc, xDel);
|
| +}
|
| +
|
| +/*
|
| +** Free an sqlite3_value object
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3ValueFree(sqlite3_value *v){
|
| + if( !v ) return;
|
| + sqlite3VdbeMemRelease((Mem *)v);
|
| + sqlite3DbFree(((Mem*)v)->db, v);
|
| +}
|
| +
|
| +/*
|
| +** The sqlite3ValueBytes() routine returns the number of bytes in the
|
| +** sqlite3_value object assuming that it uses the encoding "enc".
|
| +** The valueBytes() routine is a helper function.
|
| +*/
|
| +static SQLITE_NOINLINE int valueBytes(sqlite3_value *pVal, u8 enc){
|
| + return valueToText(pVal, enc)!=0 ? pVal->n : 0;
|
| +}
|
| +SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value *pVal, u8 enc){
|
| + Mem *p = (Mem*)pVal;
|
| + assert( (p->flags & MEM_Null)==0 || (p->flags & (MEM_Str|MEM_Blob))==0 );
|
| + if( (p->flags & MEM_Str)!=0 && pVal->enc==enc ){
|
| + return p->n;
|
| + }
|
| + if( (p->flags & MEM_Blob)!=0 ){
|
| + if( p->flags & MEM_Zero ){
|
| + return p->n + p->u.nZero;
|
| + }else{
|
| + return p->n;
|
| + }
|
| + }
|
| + if( p->flags & MEM_Null ) return 0;
|
| + return valueBytes(pVal, enc);
|
| +}
|
| +
|
| +/************** End of vdbemem.c *********************************************/
|
| +/************** Begin file vdbeaux.c *****************************************/
|
| +/*
|
| +** 2003 September 6
|
| +**
|
| +** 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.
|
| +**
|
| +*************************************************************************
|
| +** This file contains code used for creating, destroying, and populating
|
| +** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.)
|
| +*/
|
| +/* #include "sqliteInt.h" */
|
| +/* #include "vdbeInt.h" */
|
| +
|
| +/*
|
| +** Create a new virtual database engine.
|
| +*/
|
| +SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(Parse *pParse){
|
| + sqlite3 *db = pParse->db;
|
| + Vdbe *p;
|
| + p = sqlite3DbMallocZero(db, sizeof(Vdbe) );
|
| + if( p==0 ) return 0;
|
| + p->db = db;
|
| + if( db->pVdbe ){
|
| + db->pVdbe->pPrev = p;
|
| + }
|
| + p->pNext = db->pVdbe;
|
| + p->pPrev = 0;
|
| + db->pVdbe = p;
|
| + p->magic = VDBE_MAGIC_INIT;
|
| + p->pParse = pParse;
|
| + assert( pParse->aLabel==0 );
|
| + assert( pParse->nLabel==0 );
|
| + assert( pParse->nOpAlloc==0 );
|
| + assert( pParse->szOpAlloc==0 );
|
| + return p;
|
| +}
|
| +
|
| +/*
|
| +** Change the error string stored in Vdbe.zErrMsg
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbeError(Vdbe *p, const char *zFormat, ...){
|
| + va_list ap;
|
| + sqlite3DbFree(p->db, p->zErrMsg);
|
| + va_start(ap, zFormat);
|
| + p->zErrMsg = sqlite3VMPrintf(p->db, zFormat, ap);
|
| + va_end(ap);
|
| +}
|
| +
|
| +/*
|
| +** Remember the SQL string for a prepared statement.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, int isPrepareV2){
|
| + assert( isPrepareV2==1 || isPrepareV2==0 );
|
| + if( p==0 ) return;
|
| +#if defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_ENABLE_SQLLOG)
|
| + if( !isPrepareV2 ) return;
|
| +#endif
|
| + assert( p->zSql==0 );
|
| + p->zSql = sqlite3DbStrNDup(p->db, z, n);
|
| + p->isPrepareV2 = (u8)isPrepareV2;
|
| +}
|
| +
|
| +/*
|
| +** Return the SQL associated with a prepared statement
|
| +*/
|
| +SQLITE_API const char *SQLITE_STDCALL sqlite3_sql(sqlite3_stmt *pStmt){
|
| + Vdbe *p = (Vdbe *)pStmt;
|
| + return p ? p->zSql : 0;
|
| +}
|
| +
|
| +/*
|
| +** Swap all content between two VDBE structures.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe *pA, Vdbe *pB){
|
| + Vdbe tmp, *pTmp;
|
| + char *zTmp;
|
| + tmp = *pA;
|
| + *pA = *pB;
|
| + *pB = tmp;
|
| + pTmp = pA->pNext;
|
| + pA->pNext = pB->pNext;
|
| + pB->pNext = pTmp;
|
| + pTmp = pA->pPrev;
|
| + pA->pPrev = pB->pPrev;
|
| + pB->pPrev = pTmp;
|
| + zTmp = pA->zSql;
|
| + pA->zSql = pB->zSql;
|
| + pB->zSql = zTmp;
|
| + pB->isPrepareV2 = pA->isPrepareV2;
|
| +}
|
| +
|
| +/*
|
| +** Resize the Vdbe.aOp array so that it is at least nOp elements larger
|
| +** than its current size. nOp is guaranteed to be less than or equal
|
| +** to 1024/sizeof(Op).
|
| +**
|
| +** If an out-of-memory error occurs while resizing the array, return
|
| +** SQLITE_NOMEM. In this case Vdbe.aOp and Parse.nOpAlloc remain
|
| +** unchanged (this is so that any opcodes already allocated can be
|
| +** correctly deallocated along with the rest of the Vdbe).
|
| +*/
|
| +static int growOpArray(Vdbe *v, int nOp){
|
| + VdbeOp *pNew;
|
| + Parse *p = v->pParse;
|
| +
|
| + /* The SQLITE_TEST_REALLOC_STRESS compile-time option is designed to force
|
| + ** more frequent reallocs and hence provide more opportunities for
|
| + ** simulated OOM faults. SQLITE_TEST_REALLOC_STRESS is generally used
|
| + ** during testing only. With SQLITE_TEST_REALLOC_STRESS grow the op array
|
| + ** by the minimum* amount required until the size reaches 512. Normal
|
| + ** operation (without SQLITE_TEST_REALLOC_STRESS) is to double the current
|
| + ** size of the op array or add 1KB of space, whichever is smaller. */
|
| +#ifdef SQLITE_TEST_REALLOC_STRESS
|
| + int nNew = (p->nOpAlloc>=512 ? p->nOpAlloc*2 : p->nOpAlloc+nOp);
|
| +#else
|
| + int nNew = (p->nOpAlloc ? p->nOpAlloc*2 : (int)(1024/sizeof(Op)));
|
| + UNUSED_PARAMETER(nOp);
|
| +#endif
|
| +
|
| + assert( nOp<=(1024/sizeof(Op)) );
|
| + assert( nNew>=(p->nOpAlloc+nOp) );
|
| + pNew = sqlite3DbRealloc(p->db, v->aOp, nNew*sizeof(Op));
|
| + if( pNew ){
|
| + p->szOpAlloc = sqlite3DbMallocSize(p->db, pNew);
|
| + p->nOpAlloc = p->szOpAlloc/sizeof(Op);
|
| + v->aOp = pNew;
|
| + }
|
| + return (pNew ? SQLITE_OK : SQLITE_NOMEM);
|
| +}
|
| +
|
| +#ifdef SQLITE_DEBUG
|
| +/* This routine is just a convenient place to set a breakpoint that will
|
| +** fire after each opcode is inserted and displayed using
|
| +** "PRAGMA vdbe_addoptrace=on".
|
| +*/
|
| +static void test_addop_breakpoint(void){
|
| + static int n = 0;
|
| + n++;
|
| +}
|
| +#endif
|
| +
|
| +/*
|
| +** Add a new instruction to the list of instructions current in the
|
| +** VDBE. Return the address of the new instruction.
|
| +**
|
| +** Parameters:
|
| +**
|
| +** p Pointer to the VDBE
|
| +**
|
| +** op The opcode for this instruction
|
| +**
|
| +** p1, p2, p3 Operands
|
| +**
|
| +** Use the sqlite3VdbeResolveLabel() function to fix an address and
|
| +** the sqlite3VdbeChangeP4() function to change the value of the P4
|
| +** operand.
|
| +*/
|
| +static SQLITE_NOINLINE int growOp3(Vdbe *p, int op, int p1, int p2, int p3){
|
| + assert( p->pParse->nOpAlloc<=p->nOp );
|
| + if( growOpArray(p, 1) ) return 1;
|
| + assert( p->pParse->nOpAlloc>p->nOp );
|
| + return sqlite3VdbeAddOp3(p, op, p1, p2, p3);
|
| +}
|
| +SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
|
| + int i;
|
| + VdbeOp *pOp;
|
| +
|
| + i = p->nOp;
|
| + assert( p->magic==VDBE_MAGIC_INIT );
|
| + assert( op>0 && op<0xff );
|
| + if( p->pParse->nOpAlloc<=i ){
|
| + return growOp3(p, op, p1, p2, p3);
|
| + }
|
| + p->nOp++;
|
| + pOp = &p->aOp[i];
|
| + pOp->opcode = (u8)op;
|
| + pOp->p5 = 0;
|
| + pOp->p1 = p1;
|
| + pOp->p2 = p2;
|
| + pOp->p3 = p3;
|
| + pOp->p4.p = 0;
|
| + pOp->p4type = P4_NOTUSED;
|
| +#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
|
| + pOp->zComment = 0;
|
| +#endif
|
| +#ifdef SQLITE_DEBUG
|
| + if( p->db->flags & SQLITE_VdbeAddopTrace ){
|
| + int jj, kk;
|
| + Parse *pParse = p->pParse;
|
| + for(jj=kk=0; jj<SQLITE_N_COLCACHE; jj++){
|
| + struct yColCache *x = pParse->aColCache + jj;
|
| + if( x->iLevel>pParse->iCacheLevel || x->iReg==0 ) continue;
|
| + printf(" r[%d]={%d:%d}", x->iReg, x->iTable, x->iColumn);
|
| + kk++;
|
| + }
|
| + if( kk ) printf("\n");
|
| + sqlite3VdbePrintOp(0, i, &p->aOp[i]);
|
| + test_addop_breakpoint();
|
| + }
|
| +#endif
|
| +#ifdef VDBE_PROFILE
|
| + pOp->cycles = 0;
|
| + pOp->cnt = 0;
|
| +#endif
|
| +#ifdef SQLITE_VDBE_COVERAGE
|
| + pOp->iSrcLine = 0;
|
| +#endif
|
| + return i;
|
| +}
|
| +SQLITE_PRIVATE int sqlite3VdbeAddOp0(Vdbe *p, int op){
|
| + return sqlite3VdbeAddOp3(p, op, 0, 0, 0);
|
| +}
|
| +SQLITE_PRIVATE int sqlite3VdbeAddOp1(Vdbe *p, int op, int p1){
|
| + return sqlite3VdbeAddOp3(p, op, p1, 0, 0);
|
| +}
|
| +SQLITE_PRIVATE int sqlite3VdbeAddOp2(Vdbe *p, int op, int p1, int p2){
|
| + return sqlite3VdbeAddOp3(p, op, p1, p2, 0);
|
| +}
|
| +
|
| +/* Generate code for an unconditional jump to instruction iDest
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3VdbeGoto(Vdbe *p, int iDest){
|
| + return sqlite3VdbeAddOp3(p, OP_Goto, 0, iDest, 0);
|
| +}
|
| +
|
| +/* Generate code to cause the string zStr to be loaded into
|
| +** register iDest
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3VdbeLoadString(Vdbe *p, int iDest, const char *zStr){
|
| + return sqlite3VdbeAddOp4(p, OP_String8, 0, iDest, 0, zStr, 0);
|
| +}
|
| +
|
| +/*
|
| +** Generate code that initializes multiple registers to string or integer
|
| +** constants. The registers begin with iDest and increase consecutively.
|
| +** One register is initialized for each characgter in zTypes[]. For each
|
| +** "s" character in zTypes[], the register is a string if the argument is
|
| +** not NULL, or OP_Null if the value is a null pointer. For each "i" character
|
| +** in zTypes[], the register is initialized to an integer.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbeMultiLoad(Vdbe *p, int iDest, const char *zTypes, ...){
|
| + va_list ap;
|
| + int i;
|
| + char c;
|
| + va_start(ap, zTypes);
|
| + for(i=0; (c = zTypes[i])!=0; i++){
|
| + if( c=='s' ){
|
| + const char *z = va_arg(ap, const char*);
|
| + int addr = sqlite3VdbeAddOp2(p, z==0 ? OP_Null : OP_String8, 0, iDest++);
|
| + if( z ) sqlite3VdbeChangeP4(p, addr, z, 0);
|
| + }else{
|
| + assert( c=='i' );
|
| + sqlite3VdbeAddOp2(p, OP_Integer, va_arg(ap, int), iDest++);
|
| + }
|
| + }
|
| + va_end(ap);
|
| +}
|
| +
|
| +/*
|
| +** Add an opcode that includes the p4 value as a pointer.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3VdbeAddOp4(
|
| + Vdbe *p, /* Add the opcode to this VM */
|
| + int op, /* The new opcode */
|
| + int p1, /* The P1 operand */
|
| + int p2, /* The P2 operand */
|
| + int p3, /* The P3 operand */
|
| + const char *zP4, /* The P4 operand */
|
| + int p4type /* P4 operand type */
|
| +){
|
| + int addr = sqlite3VdbeAddOp3(p, op, p1, p2, p3);
|
| + sqlite3VdbeChangeP4(p, addr, zP4, p4type);
|
| + return addr;
|
| +}
|
| +
|
| +/*
|
| +** Add an opcode that includes the p4 value with a P4_INT64 or
|
| +** P4_REAL type.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3VdbeAddOp4Dup8(
|
| + Vdbe *p, /* Add the opcode to this VM */
|
| + int op, /* The new opcode */
|
| + int p1, /* The P1 operand */
|
| + int p2, /* The P2 operand */
|
| + int p3, /* The P3 operand */
|
| + const u8 *zP4, /* The P4 operand */
|
| + int p4type /* P4 operand type */
|
| +){
|
| + char *p4copy = sqlite3DbMallocRaw(sqlite3VdbeDb(p), 8);
|
| + if( p4copy ) memcpy(p4copy, zP4, 8);
|
| + return sqlite3VdbeAddOp4(p, op, p1, p2, p3, p4copy, p4type);
|
| +}
|
| +
|
| +/*
|
| +** Add an OP_ParseSchema opcode. This routine is broken out from
|
| +** sqlite3VdbeAddOp4() since it needs to also needs to mark all btrees
|
| +** as having been used.
|
| +**
|
| +** The zWhere string must have been obtained from sqlite3_malloc().
|
| +** This routine will take ownership of the allocated memory.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe *p, int iDb, char *zWhere){
|
| + int j;
|
| + int addr = sqlite3VdbeAddOp3(p, OP_ParseSchema, iDb, 0, 0);
|
| + sqlite3VdbeChangeP4(p, addr, zWhere, P4_DYNAMIC);
|
| + for(j=0; j<p->db->nDb; j++) sqlite3VdbeUsesBtree(p, j);
|
| +}
|
| +
|
| +/*
|
| +** Add an opcode that includes the p4 value as an integer.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3VdbeAddOp4Int(
|
| + Vdbe *p, /* Add the opcode to this VM */
|
| + int op, /* The new opcode */
|
| + int p1, /* The P1 operand */
|
| + int p2, /* The P2 operand */
|
| + int p3, /* The P3 operand */
|
| + int p4 /* The P4 operand as an integer */
|
| +){
|
| + int addr = sqlite3VdbeAddOp3(p, op, p1, p2, p3);
|
| + sqlite3VdbeChangeP4(p, addr, SQLITE_INT_TO_PTR(p4), P4_INT32);
|
| + return addr;
|
| +}
|
| +
|
| +/*
|
| +** Create a new symbolic label for an instruction that has yet to be
|
| +** coded. The symbolic label is really just a negative number. The
|
| +** label can be used as the P2 value of an operation. Later, when
|
| +** the label is resolved to a specific address, the VDBE will scan
|
| +** through its operation list and change all values of P2 which match
|
| +** the label into the resolved address.
|
| +**
|
| +** The VDBE knows that a P2 value is a label because labels are
|
| +** always negative and P2 values are suppose to be non-negative.
|
| +** Hence, a negative P2 value is a label that has yet to be resolved.
|
| +**
|
| +** Zero is returned if a malloc() fails.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe *v){
|
| + Parse *p = v->pParse;
|
| + int i = p->nLabel++;
|
| + assert( v->magic==VDBE_MAGIC_INIT );
|
| + if( (i & (i-1))==0 ){
|
| + p->aLabel = sqlite3DbReallocOrFree(p->db, p->aLabel,
|
| + (i*2+1)*sizeof(p->aLabel[0]));
|
| + }
|
| + if( p->aLabel ){
|
| + p->aLabel[i] = -1;
|
| + }
|
| + return ADDR(i);
|
| +}
|
| +
|
| +/*
|
| +** Resolve label "x" to be the address of the next instruction to
|
| +** be inserted. The parameter "x" must have been obtained from
|
| +** a prior call to sqlite3VdbeMakeLabel().
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe *v, int x){
|
| + Parse *p = v->pParse;
|
| + int j = ADDR(x);
|
| + assert( v->magic==VDBE_MAGIC_INIT );
|
| + assert( j<p->nLabel );
|
| + assert( j>=0 );
|
| + if( p->aLabel ){
|
| + p->aLabel[j] = v->nOp;
|
| + }
|
| + p->iFixedOp = v->nOp - 1;
|
| +}
|
| +
|
| +/*
|
| +** Mark the VDBE as one that can only be run one time.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbeRunOnlyOnce(Vdbe *p){
|
| + p->runOnlyOnce = 1;
|
| +}
|
| +
|
| +#ifdef SQLITE_DEBUG /* sqlite3AssertMayAbort() logic */
|
| +
|
| +/*
|
| +** The following type and function are used to iterate through all opcodes
|
| +** in a Vdbe main program and each of the sub-programs (triggers) it may
|
| +** invoke directly or indirectly. It should be used as follows:
|
| +**
|
| +** Op *pOp;
|
| +** VdbeOpIter sIter;
|
| +**
|
| +** memset(&sIter, 0, sizeof(sIter));
|
| +** sIter.v = v; // v is of type Vdbe*
|
| +** while( (pOp = opIterNext(&sIter)) ){
|
| +** // Do something with pOp
|
| +** }
|
| +** sqlite3DbFree(v->db, sIter.apSub);
|
| +**
|
| +*/
|
| +typedef struct VdbeOpIter VdbeOpIter;
|
| +struct VdbeOpIter {
|
| + Vdbe *v; /* Vdbe to iterate through the opcodes of */
|
| + SubProgram **apSub; /* Array of subprograms */
|
| + int nSub; /* Number of entries in apSub */
|
| + int iAddr; /* Address of next instruction to return */
|
| + int iSub; /* 0 = main program, 1 = first sub-program etc. */
|
| +};
|
| +static Op *opIterNext(VdbeOpIter *p){
|
| + Vdbe *v = p->v;
|
| + Op *pRet = 0;
|
| + Op *aOp;
|
| + int nOp;
|
| +
|
| + if( p->iSub<=p->nSub ){
|
| +
|
| + if( p->iSub==0 ){
|
| + aOp = v->aOp;
|
| + nOp = v->nOp;
|
| + }else{
|
| + aOp = p->apSub[p->iSub-1]->aOp;
|
| + nOp = p->apSub[p->iSub-1]->nOp;
|
| + }
|
| + assert( p->iAddr<nOp );
|
| +
|
| + pRet = &aOp[p->iAddr];
|
| + p->iAddr++;
|
| + if( p->iAddr==nOp ){
|
| + p->iSub++;
|
| + p->iAddr = 0;
|
| + }
|
| +
|
| + if( pRet->p4type==P4_SUBPROGRAM ){
|
| + int nByte = (p->nSub+1)*sizeof(SubProgram*);
|
| + int j;
|
| + for(j=0; j<p->nSub; j++){
|
| + if( p->apSub[j]==pRet->p4.pProgram ) break;
|
| + }
|
| + if( j==p->nSub ){
|
| + p->apSub = sqlite3DbReallocOrFree(v->db, p->apSub, nByte);
|
| + if( !p->apSub ){
|
| + pRet = 0;
|
| + }else{
|
| + p->apSub[p->nSub++] = pRet->p4.pProgram;
|
| + }
|
| + }
|
| + }
|
| + }
|
| +
|
| + return pRet;
|
| +}
|
| +
|
| +/*
|
| +** Check if the program stored in the VM associated with pParse may
|
| +** throw an ABORT exception (causing the statement, but not entire transaction
|
| +** to be rolled back). This condition is true if the main program or any
|
| +** sub-programs contains any of the following:
|
| +**
|
| +** * OP_Halt with P1=SQLITE_CONSTRAINT and P2=OE_Abort.
|
| +** * OP_HaltIfNull with P1=SQLITE_CONSTRAINT and P2=OE_Abort.
|
| +** * OP_Destroy
|
| +** * OP_VUpdate
|
| +** * OP_VRename
|
| +** * OP_FkCounter with P2==0 (immediate foreign key constraint)
|
| +** * OP_CreateTable and OP_InitCoroutine (for CREATE TABLE AS SELECT ...)
|
| +**
|
| +** Then check that the value of Parse.mayAbort is true if an
|
| +** ABORT may be thrown, or false otherwise. Return true if it does
|
| +** match, or false otherwise. This function is intended to be used as
|
| +** part of an assert statement in the compiler. Similar to:
|
| +**
|
| +** assert( sqlite3VdbeAssertMayAbort(pParse->pVdbe, pParse->mayAbort) );
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
|
| + int hasAbort = 0;
|
| + int hasFkCounter = 0;
|
| + int hasCreateTable = 0;
|
| + int hasInitCoroutine = 0;
|
| + Op *pOp;
|
| + VdbeOpIter sIter;
|
| + memset(&sIter, 0, sizeof(sIter));
|
| + sIter.v = v;
|
| +
|
| + while( (pOp = opIterNext(&sIter))!=0 ){
|
| + int opcode = pOp->opcode;
|
| + if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename
|
| + || ((opcode==OP_Halt || opcode==OP_HaltIfNull)
|
| + && ((pOp->p1&0xff)==SQLITE_CONSTRAINT && pOp->p2==OE_Abort))
|
| + ){
|
| + hasAbort = 1;
|
| + break;
|
| + }
|
| + if( opcode==OP_CreateTable ) hasCreateTable = 1;
|
| + if( opcode==OP_InitCoroutine ) hasInitCoroutine = 1;
|
| +#ifndef SQLITE_OMIT_FOREIGN_KEY
|
| + if( opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1 ){
|
| + hasFkCounter = 1;
|
| + }
|
| +#endif
|
| + }
|
| + sqlite3DbFree(v->db, sIter.apSub);
|
| +
|
| + /* Return true if hasAbort==mayAbort. Or if a malloc failure occurred.
|
| + ** If malloc failed, then the while() loop above may not have iterated
|
| + ** through all opcodes and hasAbort may be set incorrectly. Return
|
| + ** true for this case to prevent the assert() in the callers frame
|
| + ** from failing. */
|
| + return ( v->db->mallocFailed || hasAbort==mayAbort || hasFkCounter
|
| + || (hasCreateTable && hasInitCoroutine) );
|
| +}
|
| +#endif /* SQLITE_DEBUG - the sqlite3AssertMayAbort() function */
|
| +
|
| +/*
|
| +** This routine is called after all opcodes have been inserted. It loops
|
| +** through all the opcodes and fixes up some details.
|
| +**
|
| +** (1) For each jump instruction with a negative P2 value (a label)
|
| +** resolve the P2 value to an actual address.
|
| +**
|
| +** (2) Compute the maximum number of arguments used by any SQL function
|
| +** and store that value in *pMaxFuncArgs.
|
| +**
|
| +** (3) Update the Vdbe.readOnly and Vdbe.bIsReader flags to accurately
|
| +** indicate what the prepared statement actually does.
|
| +**
|
| +** (4) Initialize the p4.xAdvance pointer on opcodes that use it.
|
| +**
|
| +** (5) Reclaim the memory allocated for storing labels.
|
| +*/
|
| +static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
|
| + int i;
|
| + int nMaxArgs = *pMaxFuncArgs;
|
| + Op *pOp;
|
| + Parse *pParse = p->pParse;
|
| + int *aLabel = pParse->aLabel;
|
| + p->readOnly = 1;
|
| + p->bIsReader = 0;
|
| + for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){
|
| + u8 opcode = pOp->opcode;
|
| +
|
| + /* NOTE: Be sure to update mkopcodeh.awk when adding or removing
|
| + ** cases from this switch! */
|
| + switch( opcode ){
|
| + case OP_Transaction: {
|
| + if( pOp->p2!=0 ) p->readOnly = 0;
|
| + /* fall thru */
|
| + }
|
| + case OP_AutoCommit:
|
| + case OP_Savepoint: {
|
| + p->bIsReader = 1;
|
| + break;
|
| + }
|
| +#ifndef SQLITE_OMIT_WAL
|
| + case OP_Checkpoint:
|
| +#endif
|
| + case OP_Vacuum:
|
| + case OP_JournalMode: {
|
| + p->readOnly = 0;
|
| + p->bIsReader = 1;
|
| + break;
|
| + }
|
| +#ifndef SQLITE_OMIT_VIRTUALTABLE
|
| + case OP_VUpdate: {
|
| + if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2;
|
| + break;
|
| + }
|
| + case OP_VFilter: {
|
| + int n;
|
| + assert( p->nOp - i >= 3 );
|
| + assert( pOp[-1].opcode==OP_Integer );
|
| + n = pOp[-1].p1;
|
| + if( n>nMaxArgs ) nMaxArgs = n;
|
| + break;
|
| + }
|
| +#endif
|
| + case OP_Next:
|
| + case OP_NextIfOpen:
|
| + case OP_SorterNext: {
|
| + pOp->p4.xAdvance = sqlite3BtreeNext;
|
| + pOp->p4type = P4_ADVANCE;
|
| + break;
|
| + }
|
| + case OP_Prev:
|
| + case OP_PrevIfOpen: {
|
| + pOp->p4.xAdvance = sqlite3BtreePrevious;
|
| + pOp->p4type = P4_ADVANCE;
|
| + break;
|
| + }
|
| + }
|
| +
|
| + pOp->opflags = sqlite3OpcodeProperty[opcode];
|
| + if( (pOp->opflags & OPFLG_JUMP)!=0 && pOp->p2<0 ){
|
| + assert( ADDR(pOp->p2)<pParse->nLabel );
|
| + pOp->p2 = aLabel[ADDR(pOp->p2)];
|
| + }
|
| + }
|
| + sqlite3DbFree(p->db, pParse->aLabel);
|
| + pParse->aLabel = 0;
|
| + pParse->nLabel = 0;
|
| + *pMaxFuncArgs = nMaxArgs;
|
| + assert( p->bIsReader!=0 || DbMaskAllZero(p->btreeMask) );
|
| +}
|
| +
|
| +/*
|
| +** Return the address of the next instruction to be inserted.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3VdbeCurrentAddr(Vdbe *p){
|
| + assert( p->magic==VDBE_MAGIC_INIT );
|
| + return p->nOp;
|
| +}
|
| +
|
| +/*
|
| +** This function returns a pointer to the array of opcodes associated with
|
| +** the Vdbe passed as the first argument. It is the callers responsibility
|
| +** to arrange for the returned array to be eventually freed using the
|
| +** vdbeFreeOpArray() function.
|
| +**
|
| +** Before returning, *pnOp is set to the number of entries in the returned
|
| +** array. Also, *pnMaxArg is set to the larger of its current value and
|
| +** the number of entries in the Vdbe.apArg[] array required to execute the
|
| +** returned program.
|
| +*/
|
| +SQLITE_PRIVATE VdbeOp *sqlite3VdbeTakeOpArray(Vdbe *p, int *pnOp, int *pnMaxArg){
|
| + VdbeOp *aOp = p->aOp;
|
| + assert( aOp && !p->db->mallocFailed );
|
| +
|
| + /* Check that sqlite3VdbeUsesBtree() was not called on this VM */
|
| + assert( DbMaskAllZero(p->btreeMask) );
|
| +
|
| + resolveP2Values(p, pnMaxArg);
|
| + *pnOp = p->nOp;
|
| + p->aOp = 0;
|
| + return aOp;
|
| +}
|
| +
|
| +/*
|
| +** Add a whole list of operations to the operation stack. Return the
|
| +** address of the first operation added.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp, int iLineno){
|
| + int addr, i;
|
| + VdbeOp *pOut;
|
| + assert( nOp>0 );
|
| + assert( p->magic==VDBE_MAGIC_INIT );
|
| + if( p->nOp + nOp > p->pParse->nOpAlloc && growOpArray(p, nOp) ){
|
| + return 0;
|
| + }
|
| + addr = p->nOp;
|
| + pOut = &p->aOp[addr];
|
| + for(i=0; i<nOp; i++, aOp++, pOut++){
|
| + pOut->opcode = aOp->opcode;
|
| + pOut->p1 = aOp->p1;
|
| + pOut->p2 = aOp->p2;
|
| + assert( aOp->p2>=0 );
|
| + pOut->p3 = aOp->p3;
|
| + pOut->p4type = P4_NOTUSED;
|
| + pOut->p4.p = 0;
|
| + pOut->p5 = 0;
|
| +#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
|
| + pOut->zComment = 0;
|
| +#endif
|
| +#ifdef SQLITE_VDBE_COVERAGE
|
| + pOut->iSrcLine = iLineno+i;
|
| +#else
|
| + (void)iLineno;
|
| +#endif
|
| +#ifdef SQLITE_DEBUG
|
| + if( p->db->flags & SQLITE_VdbeAddopTrace ){
|
| + sqlite3VdbePrintOp(0, i+addr, &p->aOp[i+addr]);
|
| + }
|
| +#endif
|
| + }
|
| + p->nOp += nOp;
|
| + return addr;
|
| +}
|
| +
|
| +#if defined(SQLITE_ENABLE_STMT_SCANSTATUS)
|
| +/*
|
| +** Add an entry to the array of counters managed by sqlite3_stmt_scanstatus().
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbeScanStatus(
|
| + Vdbe *p, /* VM to add scanstatus() to */
|
| + int addrExplain, /* Address of OP_Explain (or 0) */
|
| + int addrLoop, /* Address of loop counter */
|
| + int addrVisit, /* Address of rows visited counter */
|
| + LogEst nEst, /* Estimated number of output rows */
|
| + const char *zName /* Name of table or index being scanned */
|
| +){
|
| + int nByte = (p->nScan+1) * sizeof(ScanStatus);
|
| + ScanStatus *aNew;
|
| + aNew = (ScanStatus*)sqlite3DbRealloc(p->db, p->aScan, nByte);
|
| + if( aNew ){
|
| + ScanStatus *pNew = &aNew[p->nScan++];
|
| + pNew->addrExplain = addrExplain;
|
| + pNew->addrLoop = addrLoop;
|
| + pNew->addrVisit = addrVisit;
|
| + pNew->nEst = nEst;
|
| + pNew->zName = sqlite3DbStrDup(p->db, zName);
|
| + p->aScan = aNew;
|
| + }
|
| +}
|
| +#endif
|
| +
|
| +
|
| +/*
|
| +** Change the value of the opcode, or P1, P2, P3, or P5 operands
|
| +** for a specific instruction.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbeChangeOpcode(Vdbe *p, u32 addr, u8 iNewOpcode){
|
| + sqlite3VdbeGetOp(p,addr)->opcode = iNewOpcode;
|
| +}
|
| +SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe *p, u32 addr, int val){
|
| + sqlite3VdbeGetOp(p,addr)->p1 = val;
|
| +}
|
| +SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe *p, u32 addr, int val){
|
| + sqlite3VdbeGetOp(p,addr)->p2 = val;
|
| +}
|
| +SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe *p, u32 addr, int val){
|
| + sqlite3VdbeGetOp(p,addr)->p3 = val;
|
| +}
|
| +SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe *p, u8 p5){
|
| + sqlite3VdbeGetOp(p,-1)->p5 = p5;
|
| +}
|
| +
|
| +/*
|
| +** Change the P2 operand of instruction addr so that it points to
|
| +** the address of the next instruction to be coded.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe *p, int addr){
|
| + p->pParse->iFixedOp = p->nOp - 1;
|
| + sqlite3VdbeChangeP2(p, addr, p->nOp);
|
| +}
|
| +
|
| +
|
| +/*
|
| +** If the input FuncDef structure is ephemeral, then free it. If
|
| +** the FuncDef is not ephermal, then do nothing.
|
| +*/
|
| +static void freeEphemeralFunction(sqlite3 *db, FuncDef *pDef){
|
| + if( ALWAYS(pDef) && (pDef->funcFlags & SQLITE_FUNC_EPHEM)!=0 ){
|
| + sqlite3DbFree(db, pDef);
|
| + }
|
| +}
|
| +
|
| +static void vdbeFreeOpArray(sqlite3 *, Op *, int);
|
| +
|
| +/*
|
| +** Delete a P4 value if necessary.
|
| +*/
|
| +static void freeP4(sqlite3 *db, int p4type, void *p4){
|
| + if( p4 ){
|
| + assert( db );
|
| + switch( p4type ){
|
| + case P4_FUNCCTX: {
|
| + freeEphemeralFunction(db, ((sqlite3_context*)p4)->pFunc);
|
| + /* Fall through into the next case */
|
| + }
|
| + case P4_REAL:
|
| + case P4_INT64:
|
| + case P4_DYNAMIC:
|
| + case P4_INTARRAY: {
|
| + sqlite3DbFree(db, p4);
|
| + break;
|
| + }
|
| + case P4_KEYINFO: {
|
| + if( db->pnBytesFreed==0 ) sqlite3KeyInfoUnref((KeyInfo*)p4);
|
| + break;
|
| + }
|
| +#ifdef SQLITE_ENABLE_CURSOR_HINTS
|
| + case P4_EXPR: {
|
| + sqlite3ExprDelete(db, (Expr*)p4);
|
| + break;
|
| + }
|
| +#endif
|
| + case P4_MPRINTF: {
|
| + if( db->pnBytesFreed==0 ) sqlite3_free(p4);
|
| + break;
|
| + }
|
| + case P4_FUNCDEF: {
|
| + freeEphemeralFunction(db, (FuncDef*)p4);
|
| + break;
|
| + }
|
| + case P4_MEM: {
|
| + if( db->pnBytesFreed==0 ){
|
| + sqlite3ValueFree((sqlite3_value*)p4);
|
| + }else{
|
| + Mem *p = (Mem*)p4;
|
| + if( p->szMalloc ) sqlite3DbFree(db, p->zMalloc);
|
| + sqlite3DbFree(db, p);
|
| + }
|
| + break;
|
| + }
|
| + case P4_VTAB : {
|
| + if( db->pnBytesFreed==0 ) sqlite3VtabUnlock((VTable *)p4);
|
| + break;
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Free the space allocated for aOp and any p4 values allocated for the
|
| +** opcodes contained within. If aOp is not NULL it is assumed to contain
|
| +** nOp entries.
|
| +*/
|
| +static void vdbeFreeOpArray(sqlite3 *db, Op *aOp, int nOp){
|
| + if( aOp ){
|
| + Op *pOp;
|
| + for(pOp=aOp; pOp<&aOp[nOp]; pOp++){
|
| + freeP4(db, pOp->p4type, pOp->p4.p);
|
| +#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
|
| + sqlite3DbFree(db, pOp->zComment);
|
| +#endif
|
| + }
|
| + }
|
| + sqlite3DbFree(db, aOp);
|
| +}
|
| +
|
| +/*
|
| +** Link the SubProgram object passed as the second argument into the linked
|
| +** list at Vdbe.pSubProgram. This list is used to delete all sub-program
|
| +** objects when the VM is no longer required.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *pVdbe, SubProgram *p){
|
| + p->pNext = pVdbe->pProgram;
|
| + pVdbe->pProgram = p;
|
| +}
|
| +
|
| +/*
|
| +** Change the opcode at addr into OP_Noop
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe *p, int addr){
|
| + if( addr<p->nOp ){
|
| + VdbeOp *pOp = &p->aOp[addr];
|
| + sqlite3 *db = p->db;
|
| + freeP4(db, pOp->p4type, pOp->p4.p);
|
| + memset(pOp, 0, sizeof(pOp[0]));
|
| + pOp->opcode = OP_Noop;
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** If the last opcode is "op" and it is not a jump destination,
|
| +** then remove it. Return true if and only if an opcode was removed.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3VdbeDeletePriorOpcode(Vdbe *p, u8 op){
|
| + if( (p->nOp-1)>(p->pParse->iFixedOp) && p->aOp[p->nOp-1].opcode==op ){
|
| + sqlite3VdbeChangeToNoop(p, p->nOp-1);
|
| + return 1;
|
| + }else{
|
| + return 0;
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Change the value of the P4 operand for a specific instruction.
|
| +** This routine is useful when a large program is loaded from a
|
| +** static array using sqlite3VdbeAddOpList but we want to make a
|
| +** few minor changes to the program.
|
| +**
|
| +** If n>=0 then the P4 operand is dynamic, meaning that a copy of
|
| +** the string is made into memory obtained from sqlite3_malloc().
|
| +** A value of n==0 means copy bytes of zP4 up to and including the
|
| +** first null byte. If n>0 then copy n+1 bytes of zP4.
|
| +**
|
| +** Other values of n (P4_STATIC, P4_COLLSEQ etc.) indicate that zP4 points
|
| +** to a string or structure that is guaranteed to exist for the lifetime of
|
| +** the Vdbe. In these cases we can just copy the pointer.
|
| +**
|
| +** If addr<0 then change P4 on the most recently inserted instruction.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int n){
|
| + Op *pOp;
|
| + sqlite3 *db;
|
| + assert( p!=0 );
|
| + db = p->db;
|
| + assert( p->magic==VDBE_MAGIC_INIT );
|
| + if( p->aOp==0 || db->mallocFailed ){
|
| + if( n!=P4_VTAB ){
|
| + freeP4(db, n, (void*)*(char**)&zP4);
|
| + }
|
| + return;
|
| + }
|
| + assert( p->nOp>0 );
|
| + assert( addr<p->nOp );
|
| + if( addr<0 ){
|
| + addr = p->nOp - 1;
|
| + }
|
| + pOp = &p->aOp[addr];
|
| + assert( pOp->p4type==P4_NOTUSED
|
| + || pOp->p4type==P4_INT32
|
| + || pOp->p4type==P4_KEYINFO );
|
| + freeP4(db, pOp->p4type, pOp->p4.p);
|
| + pOp->p4.p = 0;
|
| + if( n==P4_INT32 ){
|
| + /* Note: this cast is safe, because the origin data point was an int
|
| + ** that was cast to a (const char *). */
|
| + pOp->p4.i = SQLITE_PTR_TO_INT(zP4);
|
| + pOp->p4type = P4_INT32;
|
| + }else if( zP4==0 ){
|
| + pOp->p4.p = 0;
|
| + pOp->p4type = P4_NOTUSED;
|
| + }else if( n==P4_KEYINFO ){
|
| + pOp->p4.p = (void*)zP4;
|
| + pOp->p4type = P4_KEYINFO;
|
| +#ifdef SQLITE_ENABLE_CURSOR_HINTS
|
| + }else if( n==P4_EXPR ){
|
| + /* Responsibility for deleting the Expr tree is handed over to the
|
| + ** VDBE by this operation. The caller should have already invoked
|
| + ** sqlite3ExprDup() or whatever other routine is needed to make a
|
| + ** private copy of the tree. */
|
| + pOp->p4.pExpr = (Expr*)zP4;
|
| + pOp->p4type = P4_EXPR;
|
| +#endif
|
| + }else if( n==P4_VTAB ){
|
| + pOp->p4.p = (void*)zP4;
|
| + pOp->p4type = P4_VTAB;
|
| + sqlite3VtabLock((VTable *)zP4);
|
| + assert( ((VTable *)zP4)->db==p->db );
|
| + }else if( n<0 ){
|
| + pOp->p4.p = (void*)zP4;
|
| + pOp->p4type = (signed char)n;
|
| + }else{
|
| + if( n==0 ) n = sqlite3Strlen30(zP4);
|
| + pOp->p4.z = sqlite3DbStrNDup(p->db, zP4, n);
|
| + pOp->p4type = P4_DYNAMIC;
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Set the P4 on the most recently added opcode to the KeyInfo for the
|
| +** index given.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbeSetP4KeyInfo(Parse *pParse, Index *pIdx){
|
| + Vdbe *v = pParse->pVdbe;
|
| + assert( v!=0 );
|
| + assert( pIdx!=0 );
|
| + sqlite3VdbeChangeP4(v, -1, (char*)sqlite3KeyInfoOfIndex(pParse, pIdx),
|
| + P4_KEYINFO);
|
| +}
|
| +
|
| +#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
|
| +/*
|
| +** Change the comment on the most recently coded instruction. Or
|
| +** insert a No-op and add the comment to that new instruction. This
|
| +** makes the code easier to read during debugging. None of this happens
|
| +** in a production build.
|
| +*/
|
| +static void vdbeVComment(Vdbe *p, const char *zFormat, va_list ap){
|
| + assert( p->nOp>0 || p->aOp==0 );
|
| + assert( p->aOp==0 || p->aOp[p->nOp-1].zComment==0 || p->db->mallocFailed );
|
| + if( p->nOp ){
|
| + assert( p->aOp );
|
| + sqlite3DbFree(p->db, p->aOp[p->nOp-1].zComment);
|
| + p->aOp[p->nOp-1].zComment = sqlite3VMPrintf(p->db, zFormat, ap);
|
| + }
|
| +}
|
| +SQLITE_PRIVATE void sqlite3VdbeComment(Vdbe *p, const char *zFormat, ...){
|
| + va_list ap;
|
| + if( p ){
|
| + va_start(ap, zFormat);
|
| + vdbeVComment(p, zFormat, ap);
|
| + va_end(ap);
|
| + }
|
| +}
|
| +SQLITE_PRIVATE void sqlite3VdbeNoopComment(Vdbe *p, const char *zFormat, ...){
|
| + va_list ap;
|
| + if( p ){
|
| + sqlite3VdbeAddOp0(p, OP_Noop);
|
| + va_start(ap, zFormat);
|
| + vdbeVComment(p, zFormat, ap);
|
| + va_end(ap);
|
| + }
|
| +}
|
| +#endif /* NDEBUG */
|
| +
|
| +#ifdef SQLITE_VDBE_COVERAGE
|
| +/*
|
| +** Set the value if the iSrcLine field for the previously coded instruction.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbeSetLineNumber(Vdbe *v, int iLine){
|
| + sqlite3VdbeGetOp(v,-1)->iSrcLine = iLine;
|
| +}
|
| +#endif /* SQLITE_VDBE_COVERAGE */
|
| +
|
| +/*
|
| +** Return the opcode for a given address. If the address is -1, then
|
| +** return the most recently inserted opcode.
|
| +**
|
| +** If a memory allocation error has occurred prior to the calling of this
|
| +** routine, then a pointer to a dummy VdbeOp will be returned. That opcode
|
| +** is readable but not writable, though it is cast to a writable value.
|
| +** The return of a dummy opcode allows the call to continue functioning
|
| +** after an OOM fault without having to check to see if the return from
|
| +** this routine is a valid pointer. But because the dummy.opcode is 0,
|
| +** dummy will never be written to. This is verified by code inspection and
|
| +** by running with Valgrind.
|
| +*/
|
| +SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){
|
| + /* C89 specifies that the constant "dummy" will be initialized to all
|
| + ** zeros, which is correct. MSVC generates a warning, nevertheless. */
|
| + static VdbeOp dummy; /* Ignore the MSVC warning about no initializer */
|
| + assert( p->magic==VDBE_MAGIC_INIT );
|
| + if( addr<0 ){
|
| + addr = p->nOp - 1;
|
| + }
|
| + assert( (addr>=0 && addr<p->nOp) || p->db->mallocFailed );
|
| + if( p->db->mallocFailed ){
|
| + return (VdbeOp*)&dummy;
|
| + }else{
|
| + return &p->aOp[addr];
|
| + }
|
| +}
|
| +
|
| +#if defined(SQLITE_ENABLE_EXPLAIN_COMMENTS)
|
| +/*
|
| +** Return an integer value for one of the parameters to the opcode pOp
|
| +** determined by character c.
|
| +*/
|
| +static int translateP(char c, const Op *pOp){
|
| + if( c=='1' ) return pOp->p1;
|
| + if( c=='2' ) return pOp->p2;
|
| + if( c=='3' ) return pOp->p3;
|
| + if( c=='4' ) return pOp->p4.i;
|
| + return pOp->p5;
|
| +}
|
| +
|
| +/*
|
| +** Compute a string for the "comment" field of a VDBE opcode listing.
|
| +**
|
| +** The Synopsis: field in comments in the vdbe.c source file gets converted
|
| +** to an extra string that is appended to the sqlite3OpcodeName(). In the
|
| +** absence of other comments, this synopsis becomes the comment on the opcode.
|
| +** Some translation occurs:
|
| +**
|
| +** "PX" -> "r[X]"
|
| +** "PX@PY" -> "r[X..X+Y-1]" or "r[x]" if y is 0 or 1
|
| +** "PX@PY+1" -> "r[X..X+Y]" or "r[x]" if y is 0
|
| +** "PY..PY" -> "r[X..Y]" or "r[x]" if y<=x
|
| +*/
|
| +static int displayComment(
|
| + const Op *pOp, /* The opcode to be commented */
|
| + const char *zP4, /* Previously obtained value for P4 */
|
| + char *zTemp, /* Write result here */
|
| + int nTemp /* Space available in zTemp[] */
|
| +){
|
| + const char *zOpName;
|
| + const char *zSynopsis;
|
| + int nOpName;
|
| + int ii, jj;
|
| + zOpName = sqlite3OpcodeName(pOp->opcode);
|
| + nOpName = sqlite3Strlen30(zOpName);
|
| + if( zOpName[nOpName+1] ){
|
| + int seenCom = 0;
|
| + char c;
|
| + zSynopsis = zOpName += nOpName + 1;
|
| + for(ii=jj=0; jj<nTemp-1 && (c = zSynopsis[ii])!=0; ii++){
|
| + if( c=='P' ){
|
| + c = zSynopsis[++ii];
|
| + if( c=='4' ){
|
| + sqlite3_snprintf(nTemp-jj, zTemp+jj, "%s", zP4);
|
| + }else if( c=='X' ){
|
| + sqlite3_snprintf(nTemp-jj, zTemp+jj, "%s", pOp->zComment);
|
| + seenCom = 1;
|
| + }else{
|
| + int v1 = translateP(c, pOp);
|
| + int v2;
|
| + sqlite3_snprintf(nTemp-jj, zTemp+jj, "%d", v1);
|
| + if( strncmp(zSynopsis+ii+1, "@P", 2)==0 ){
|
| + ii += 3;
|
| + jj += sqlite3Strlen30(zTemp+jj);
|
| + v2 = translateP(zSynopsis[ii], pOp);
|
| + if( strncmp(zSynopsis+ii+1,"+1",2)==0 ){
|
| + ii += 2;
|
| + v2++;
|
| + }
|
| + if( v2>1 ){
|
| + sqlite3_snprintf(nTemp-jj, zTemp+jj, "..%d", v1+v2-1);
|
| + }
|
| + }else if( strncmp(zSynopsis+ii+1, "..P3", 4)==0 && pOp->p3==0 ){
|
| + ii += 4;
|
| + }
|
| + }
|
| + jj += sqlite3Strlen30(zTemp+jj);
|
| + }else{
|
| + zTemp[jj++] = c;
|
| + }
|
| + }
|
| + if( !seenCom && jj<nTemp-5 && pOp->zComment ){
|
| + sqlite3_snprintf(nTemp-jj, zTemp+jj, "; %s", pOp->zComment);
|
| + jj += sqlite3Strlen30(zTemp+jj);
|
| + }
|
| + if( jj<nTemp ) zTemp[jj] = 0;
|
| + }else if( pOp->zComment ){
|
| + sqlite3_snprintf(nTemp, zTemp, "%s", pOp->zComment);
|
| + jj = sqlite3Strlen30(zTemp);
|
| + }else{
|
| + zTemp[0] = 0;
|
| + jj = 0;
|
| + }
|
| + return jj;
|
| +}
|
| +#endif /* SQLITE_DEBUG */
|
| +
|
| +#if VDBE_DISPLAY_P4 && defined(SQLITE_ENABLE_CURSOR_HINTS)
|
| +/*
|
| +** Translate the P4.pExpr value for an OP_CursorHint opcode into text
|
| +** that can be displayed in the P4 column of EXPLAIN output.
|
| +*/
|
| +static int displayP4Expr(int nTemp, char *zTemp, Expr *pExpr){
|
| + const char *zOp = 0;
|
| + int n;
|
| + switch( pExpr->op ){
|
| + case TK_STRING:
|
| + sqlite3_snprintf(nTemp, zTemp, "%Q", pExpr->u.zToken);
|
| + break;
|
| + case TK_INTEGER:
|
| + sqlite3_snprintf(nTemp, zTemp, "%d", pExpr->u.iValue);
|
| + break;
|
| + case TK_NULL:
|
| + sqlite3_snprintf(nTemp, zTemp, "NULL");
|
| + break;
|
| + case TK_REGISTER: {
|
| + sqlite3_snprintf(nTemp, zTemp, "r[%d]", pExpr->iTable);
|
| + break;
|
| + }
|
| + case TK_COLUMN: {
|
| + if( pExpr->iColumn<0 ){
|
| + sqlite3_snprintf(nTemp, zTemp, "rowid");
|
| + }else{
|
| + sqlite3_snprintf(nTemp, zTemp, "c%d", (int)pExpr->iColumn);
|
| + }
|
| + break;
|
| + }
|
| + case TK_LT: zOp = "LT"; break;
|
| + case TK_LE: zOp = "LE"; break;
|
| + case TK_GT: zOp = "GT"; break;
|
| + case TK_GE: zOp = "GE"; break;
|
| + case TK_NE: zOp = "NE"; break;
|
| + case TK_EQ: zOp = "EQ"; break;
|
| + case TK_IS: zOp = "IS"; break;
|
| + case TK_ISNOT: zOp = "ISNOT"; break;
|
| + case TK_AND: zOp = "AND"; break;
|
| + case TK_OR: zOp = "OR"; break;
|
| + case TK_PLUS: zOp = "ADD"; break;
|
| + case TK_STAR: zOp = "MUL"; break;
|
| + case TK_MINUS: zOp = "SUB"; break;
|
| + case TK_REM: zOp = "REM"; break;
|
| + case TK_BITAND: zOp = "BITAND"; break;
|
| + case TK_BITOR: zOp = "BITOR"; break;
|
| + case TK_SLASH: zOp = "DIV"; break;
|
| + case TK_LSHIFT: zOp = "LSHIFT"; break;
|
| + case TK_RSHIFT: zOp = "RSHIFT"; break;
|
| + case TK_CONCAT: zOp = "CONCAT"; break;
|
| + case TK_UMINUS: zOp = "MINUS"; break;
|
| + case TK_UPLUS: zOp = "PLUS"; break;
|
| + case TK_BITNOT: zOp = "BITNOT"; break;
|
| + case TK_NOT: zOp = "NOT"; break;
|
| + case TK_ISNULL: zOp = "ISNULL"; break;
|
| + case TK_NOTNULL: zOp = "NOTNULL"; break;
|
| +
|
| + default:
|
| + sqlite3_snprintf(nTemp, zTemp, "%s", "expr");
|
| + break;
|
| + }
|
| +
|
| + if( zOp ){
|
| + sqlite3_snprintf(nTemp, zTemp, "%s(", zOp);
|
| + n = sqlite3Strlen30(zTemp);
|
| + n += displayP4Expr(nTemp-n, zTemp+n, pExpr->pLeft);
|
| + if( n<nTemp-1 && pExpr->pRight ){
|
| + zTemp[n++] = ',';
|
| + n += displayP4Expr(nTemp-n, zTemp+n, pExpr->pRight);
|
| + }
|
| + sqlite3_snprintf(nTemp-n, zTemp+n, ")");
|
| + }
|
| + return sqlite3Strlen30(zTemp);
|
| +}
|
| +#endif /* VDBE_DISPLAY_P4 && defined(SQLITE_ENABLE_CURSOR_HINTS) */
|
| +
|
| +
|
| +#if VDBE_DISPLAY_P4
|
| +/*
|
| +** Compute a string that describes the P4 parameter for an opcode.
|
| +** Use zTemp for any required temporary buffer space.
|
| +*/
|
| +static char *displayP4(Op *pOp, char *zTemp, int nTemp){
|
| + char *zP4 = zTemp;
|
| + assert( nTemp>=20 );
|
| + switch( pOp->p4type ){
|
| + case P4_KEYINFO: {
|
| + int i, j;
|
| + KeyInfo *pKeyInfo = pOp->p4.pKeyInfo;
|
| + assert( pKeyInfo->aSortOrder!=0 );
|
| + sqlite3_snprintf(nTemp, zTemp, "k(%d", pKeyInfo->nField);
|
| + i = sqlite3Strlen30(zTemp);
|
| + for(j=0; j<pKeyInfo->nField; j++){
|
| + CollSeq *pColl = pKeyInfo->aColl[j];
|
| + const char *zColl = pColl ? pColl->zName : "nil";
|
| + int n = sqlite3Strlen30(zColl);
|
| + if( n==6 && memcmp(zColl,"BINARY",6)==0 ){
|
| + zColl = "B";
|
| + n = 1;
|
| + }
|
| + if( i+n>nTemp-7 ){
|
| + memcpy(&zTemp[i],",...",4);
|
| + i += 4;
|
| + break;
|
| + }
|
| + zTemp[i++] = ',';
|
| + if( pKeyInfo->aSortOrder[j] ){
|
| + zTemp[i++] = '-';
|
| + }
|
| + memcpy(&zTemp[i], zColl, n+1);
|
| + i += n;
|
| + }
|
| + zTemp[i++] = ')';
|
| + zTemp[i] = 0;
|
| + assert( i<nTemp );
|
| + break;
|
| + }
|
| +#ifdef SQLITE_ENABLE_CURSOR_HINTS
|
| + case P4_EXPR: {
|
| + displayP4Expr(nTemp, zTemp, pOp->p4.pExpr);
|
| + break;
|
| + }
|
| +#endif
|
| + case P4_COLLSEQ: {
|
| + CollSeq *pColl = pOp->p4.pColl;
|
| + sqlite3_snprintf(nTemp, zTemp, "(%.20s)", pColl->zName);
|
| + break;
|
| + }
|
| + case P4_FUNCDEF: {
|
| + FuncDef *pDef = pOp->p4.pFunc;
|
| + sqlite3_snprintf(nTemp, zTemp, "%s(%d)", pDef->zName, pDef->nArg);
|
| + break;
|
| + }
|
| +#ifdef SQLITE_DEBUG
|
| + case P4_FUNCCTX: {
|
| + FuncDef *pDef = pOp->p4.pCtx->pFunc;
|
| + sqlite3_snprintf(nTemp, zTemp, "%s(%d)", pDef->zName, pDef->nArg);
|
| + break;
|
| + }
|
| +#endif
|
| + case P4_INT64: {
|
| + sqlite3_snprintf(nTemp, zTemp, "%lld", *pOp->p4.pI64);
|
| + break;
|
| + }
|
| + case P4_INT32: {
|
| + sqlite3_snprintf(nTemp, zTemp, "%d", pOp->p4.i);
|
| + break;
|
| + }
|
| + case P4_REAL: {
|
| + sqlite3_snprintf(nTemp, zTemp, "%.16g", *pOp->p4.pReal);
|
| + break;
|
| + }
|
| + case P4_MEM: {
|
| + Mem *pMem = pOp->p4.pMem;
|
| + if( pMem->flags & MEM_Str ){
|
| + zP4 = pMem->z;
|
| + }else if( pMem->flags & MEM_Int ){
|
| + sqlite3_snprintf(nTemp, zTemp, "%lld", pMem->u.i);
|
| + }else if( pMem->flags & MEM_Real ){
|
| + sqlite3_snprintf(nTemp, zTemp, "%.16g", pMem->u.r);
|
| + }else if( pMem->flags & MEM_Null ){
|
| + sqlite3_snprintf(nTemp, zTemp, "NULL");
|
| + }else{
|
| + assert( pMem->flags & MEM_Blob );
|
| + zP4 = "(blob)";
|
| + }
|
| + break;
|
| + }
|
| +#ifndef SQLITE_OMIT_VIRTUALTABLE
|
| + case P4_VTAB: {
|
| + sqlite3_vtab *pVtab = pOp->p4.pVtab->pVtab;
|
| + sqlite3_snprintf(nTemp, zTemp, "vtab:%p", pVtab);
|
| + break;
|
| + }
|
| +#endif
|
| + case P4_INTARRAY: {
|
| + sqlite3_snprintf(nTemp, zTemp, "intarray");
|
| + break;
|
| + }
|
| + case P4_SUBPROGRAM: {
|
| + sqlite3_snprintf(nTemp, zTemp, "program");
|
| + break;
|
| + }
|
| + case P4_ADVANCE: {
|
| + zTemp[0] = 0;
|
| + break;
|
| + }
|
| + default: {
|
| + zP4 = pOp->p4.z;
|
| + if( zP4==0 ){
|
| + zP4 = zTemp;
|
| + zTemp[0] = 0;
|
| + }
|
| + }
|
| + }
|
| + assert( zP4!=0 );
|
| + return zP4;
|
| +}
|
| +#endif /* VDBE_DISPLAY_P4 */
|
| +
|
| +/*
|
| +** Declare to the Vdbe that the BTree object at db->aDb[i] is used.
|
| +**
|
| +** The prepared statements need to know in advance the complete set of
|
| +** attached databases that will be use. A mask of these databases
|
| +** is maintained in p->btreeMask. The p->lockMask value is the subset of
|
| +** p->btreeMask of databases that will require a lock.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe *p, int i){
|
| + assert( i>=0 && i<p->db->nDb && i<(int)sizeof(yDbMask)*8 );
|
| + assert( i<(int)sizeof(p->btreeMask)*8 );
|
| + DbMaskSet(p->btreeMask, i);
|
| + if( i!=1 && sqlite3BtreeSharable(p->db->aDb[i].pBt) ){
|
| + DbMaskSet(p->lockMask, i);
|
| + }
|
| +}
|
| +
|
| +#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
|
| +/*
|
| +** If SQLite is compiled to support shared-cache mode and to be threadsafe,
|
| +** this routine obtains the mutex associated with each BtShared structure
|
| +** that may be accessed by the VM passed as an argument. In doing so it also
|
| +** sets the BtShared.db member of each of the BtShared structures, ensuring
|
| +** that the correct busy-handler callback is invoked if required.
|
| +**
|
| +** If SQLite is not threadsafe but does support shared-cache mode, then
|
| +** sqlite3BtreeEnter() is invoked to set the BtShared.db variables
|
| +** of all of BtShared structures accessible via the database handle
|
| +** associated with the VM.
|
| +**
|
| +** If SQLite is not threadsafe and does not support shared-cache mode, this
|
| +** function is a no-op.
|
| +**
|
| +** The p->btreeMask field is a bitmask of all btrees that the prepared
|
| +** statement p will ever use. Let N be the number of bits in p->btreeMask
|
| +** corresponding to btrees that use shared cache. Then the runtime of
|
| +** this routine is N*N. But as N is rarely more than 1, this should not
|
| +** be a problem.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbeEnter(Vdbe *p){
|
| + int i;
|
| + sqlite3 *db;
|
| + Db *aDb;
|
| + int nDb;
|
| + if( DbMaskAllZero(p->lockMask) ) return; /* The common case */
|
| + db = p->db;
|
| + aDb = db->aDb;
|
| + nDb = db->nDb;
|
| + for(i=0; i<nDb; i++){
|
| + if( i!=1 && DbMaskTest(p->lockMask,i) && ALWAYS(aDb[i].pBt!=0) ){
|
| + sqlite3BtreeEnter(aDb[i].pBt);
|
| + }
|
| + }
|
| +}
|
| +#endif
|
| +
|
| +#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
|
| +/*
|
| +** Unlock all of the btrees previously locked by a call to sqlite3VdbeEnter().
|
| +*/
|
| +static SQLITE_NOINLINE void vdbeLeave(Vdbe *p){
|
| + int i;
|
| + sqlite3 *db;
|
| + Db *aDb;
|
| + int nDb;
|
| + db = p->db;
|
| + aDb = db->aDb;
|
| + nDb = db->nDb;
|
| + for(i=0; i<nDb; i++){
|
| + if( i!=1 && DbMaskTest(p->lockMask,i) && ALWAYS(aDb[i].pBt!=0) ){
|
| + sqlite3BtreeLeave(aDb[i].pBt);
|
| + }
|
| + }
|
| +}
|
| +SQLITE_PRIVATE void sqlite3VdbeLeave(Vdbe *p){
|
| + if( DbMaskAllZero(p->lockMask) ) return; /* The common case */
|
| + vdbeLeave(p);
|
| +}
|
| +#endif
|
| +
|
| +#if defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
|
| +/*
|
| +** Print a single opcode. This routine is used for debugging only.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE *pOut, int pc, Op *pOp){
|
| + char *zP4;
|
| + char zPtr[50];
|
| + char zCom[100];
|
| + static const char *zFormat1 = "%4d %-13s %4d %4d %4d %-13s %.2X %s\n";
|
| + if( pOut==0 ) pOut = stdout;
|
| + zP4 = displayP4(pOp, zPtr, sizeof(zPtr));
|
| +#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
|
| + displayComment(pOp, zP4, zCom, sizeof(zCom));
|
| +#else
|
| + zCom[0] = 0;
|
| +#endif
|
| + /* NB: The sqlite3OpcodeName() function is implemented by code created
|
| + ** by the mkopcodeh.awk and mkopcodec.awk scripts which extract the
|
| + ** information from the vdbe.c source text */
|
| + fprintf(pOut, zFormat1, pc,
|
| + sqlite3OpcodeName(pOp->opcode), pOp->p1, pOp->p2, pOp->p3, zP4, pOp->p5,
|
| + zCom
|
| + );
|
| + fflush(pOut);
|
| +}
|
| +#endif
|
| +
|
| +/*
|
| +** Release an array of N Mem elements
|
| +*/
|
| +static void releaseMemArray(Mem *p, int N){
|
| + if( p && N ){
|
| + Mem *pEnd = &p[N];
|
| + sqlite3 *db = p->db;
|
| + u8 malloc_failed = db->mallocFailed;
|
| + if( db->pnBytesFreed ){
|
| + do{
|
| + if( p->szMalloc ) sqlite3DbFree(db, p->zMalloc);
|
| + }while( (++p)<pEnd );
|
| + return;
|
| + }
|
| + do{
|
| + assert( (&p[1])==pEnd || p[0].db==p[1].db );
|
| + assert( sqlite3VdbeCheckMemInvariants(p) );
|
| +
|
| + /* This block is really an inlined version of sqlite3VdbeMemRelease()
|
| + ** that takes advantage of the fact that the memory cell value is
|
| + ** being set to NULL after releasing any dynamic resources.
|
| + **
|
| + ** The justification for duplicating code is that according to
|
| + ** callgrind, this causes a certain test case to hit the CPU 4.7
|
| + ** percent less (x86 linux, gcc version 4.1.2, -O6) than if
|
| + ** sqlite3MemRelease() were called from here. With -O2, this jumps
|
| + ** to 6.6 percent. The test case is inserting 1000 rows into a table
|
| + ** with no indexes using a single prepared INSERT statement, bind()
|
| + ** and reset(). Inserts are grouped into a transaction.
|
| + */
|
| + testcase( p->flags & MEM_Agg );
|
| + testcase( p->flags & MEM_Dyn );
|
| + testcase( p->flags & MEM_Frame );
|
| + testcase( p->flags & MEM_RowSet );
|
| + if( p->flags&(MEM_Agg|MEM_Dyn|MEM_Frame|MEM_RowSet) ){
|
| + sqlite3VdbeMemRelease(p);
|
| + }else if( p->szMalloc ){
|
| + sqlite3DbFree(db, p->zMalloc);
|
| + p->szMalloc = 0;
|
| + }
|
| +
|
| + p->flags = MEM_Undefined;
|
| + }while( (++p)<pEnd );
|
| + db->mallocFailed = malloc_failed;
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Delete a VdbeFrame object and its contents. VdbeFrame objects are
|
| +** allocated by the OP_Program opcode in sqlite3VdbeExec().
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame *p){
|
| + int i;
|
| + Mem *aMem = VdbeFrameMem(p);
|
| + VdbeCursor **apCsr = (VdbeCursor **)&aMem[p->nChildMem];
|
| + for(i=0; i<p->nChildCsr; i++){
|
| + sqlite3VdbeFreeCursor(p->v, apCsr[i]);
|
| + }
|
| + releaseMemArray(aMem, p->nChildMem);
|
| + sqlite3DbFree(p->v->db, p);
|
| +}
|
| +
|
| +#ifndef SQLITE_OMIT_EXPLAIN
|
| +/*
|
| +** Give a listing of the program in the virtual machine.
|
| +**
|
| +** The interface is the same as sqlite3VdbeExec(). But instead of
|
| +** running the code, it invokes the callback once for each instruction.
|
| +** This feature is used to implement "EXPLAIN".
|
| +**
|
| +** When p->explain==1, each instruction is listed. When
|
| +** p->explain==2, only OP_Explain instructions are listed and these
|
| +** are shown in a different format. p->explain==2 is used to implement
|
| +** EXPLAIN QUERY PLAN.
|
| +**
|
| +** When p->explain==1, first the main program is listed, then each of
|
| +** the trigger subprograms are listed one by one.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3VdbeList(
|
| + Vdbe *p /* The VDBE */
|
| +){
|
| + int nRow; /* Stop when row count reaches this */
|
| + int nSub = 0; /* Number of sub-vdbes seen so far */
|
| + SubProgram **apSub = 0; /* Array of sub-vdbes */
|
| + Mem *pSub = 0; /* Memory cell hold array of subprogs */
|
| + sqlite3 *db = p->db; /* The database connection */
|
| + int i; /* Loop counter */
|
| + int rc = SQLITE_OK; /* Return code */
|
| + Mem *pMem = &p->aMem[1]; /* First Mem of result set */
|
| +
|
| + assert( p->explain );
|
| + assert( p->magic==VDBE_MAGIC_RUN );
|
| + assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY || p->rc==SQLITE_NOMEM );
|
| +
|
| + /* Even though this opcode does not use dynamic strings for
|
| + ** the result, result columns may become dynamic if the user calls
|
| + ** sqlite3_column_text16(), causing a translation to UTF-16 encoding.
|
| + */
|
| + releaseMemArray(pMem, 8);
|
| + p->pResultSet = 0;
|
| +
|
| + if( p->rc==SQLITE_NOMEM ){
|
| + /* This happens if a malloc() inside a call to sqlite3_column_text() or
|
| + ** sqlite3_column_text16() failed. */
|
| + db->mallocFailed = 1;
|
| + return SQLITE_ERROR;
|
| + }
|
| +
|
| + /* When the number of output rows reaches nRow, that means the
|
| + ** listing has finished and sqlite3_step() should return SQLITE_DONE.
|
| + ** nRow is the sum of the number of rows in the main program, plus
|
| + ** the sum of the number of rows in all trigger subprograms encountered
|
| + ** so far. The nRow value will increase as new trigger subprograms are
|
| + ** encountered, but p->pc will eventually catch up to nRow.
|
| + */
|
| + nRow = p->nOp;
|
| + if( p->explain==1 ){
|
| + /* The first 8 memory cells are used for the result set. So we will
|
| + ** commandeer the 9th cell to use as storage for an array of pointers
|
| + ** to trigger subprograms. The VDBE is guaranteed to have at least 9
|
| + ** cells. */
|
| + assert( p->nMem>9 );
|
| + pSub = &p->aMem[9];
|
| + if( pSub->flags&MEM_Blob ){
|
| + /* On the first call to sqlite3_step(), pSub will hold a NULL. It is
|
| + ** initialized to a BLOB by the P4_SUBPROGRAM processing logic below */
|
| + nSub = pSub->n/sizeof(Vdbe*);
|
| + apSub = (SubProgram **)pSub->z;
|
| + }
|
| + for(i=0; i<nSub; i++){
|
| + nRow += apSub[i]->nOp;
|
| + }
|
| + }
|
| +
|
| + do{
|
| + i = p->pc++;
|
| + }while( i<nRow && p->explain==2 && p->aOp[i].opcode!=OP_Explain );
|
| + if( i>=nRow ){
|
| + p->rc = SQLITE_OK;
|
| + rc = SQLITE_DONE;
|
| + }else if( db->u1.isInterrupted ){
|
| + p->rc = SQLITE_INTERRUPT;
|
| + rc = SQLITE_ERROR;
|
| + sqlite3VdbeError(p, sqlite3ErrStr(p->rc));
|
| + }else{
|
| + char *zP4;
|
| + Op *pOp;
|
| + if( i<p->nOp ){
|
| + /* The output line number is small enough that we are still in the
|
| + ** main program. */
|
| + pOp = &p->aOp[i];
|
| + }else{
|
| + /* We are currently listing subprograms. Figure out which one and
|
| + ** pick up the appropriate opcode. */
|
| + int j;
|
| + i -= p->nOp;
|
| + for(j=0; i>=apSub[j]->nOp; j++){
|
| + i -= apSub[j]->nOp;
|
| + }
|
| + pOp = &apSub[j]->aOp[i];
|
| + }
|
| + if( p->explain==1 ){
|
| + pMem->flags = MEM_Int;
|
| + pMem->u.i = i; /* Program counter */
|
| + pMem++;
|
| +
|
| + pMem->flags = MEM_Static|MEM_Str|MEM_Term;
|
| + pMem->z = (char*)sqlite3OpcodeName(pOp->opcode); /* Opcode */
|
| + assert( pMem->z!=0 );
|
| + pMem->n = sqlite3Strlen30(pMem->z);
|
| + pMem->enc = SQLITE_UTF8;
|
| + pMem++;
|
| +
|
| + /* When an OP_Program opcode is encounter (the only opcode that has
|
| + ** a P4_SUBPROGRAM argument), expand the size of the array of subprograms
|
| + ** kept in p->aMem[9].z to hold the new program - assuming this subprogram
|
| + ** has not already been seen.
|
| + */
|
| + if( pOp->p4type==P4_SUBPROGRAM ){
|
| + int nByte = (nSub+1)*sizeof(SubProgram*);
|
| + int j;
|
| + for(j=0; j<nSub; j++){
|
| + if( apSub[j]==pOp->p4.pProgram ) break;
|
| + }
|
| + if( j==nSub && SQLITE_OK==sqlite3VdbeMemGrow(pSub, nByte, nSub!=0) ){
|
| + apSub = (SubProgram **)pSub->z;
|
| + apSub[nSub++] = pOp->p4.pProgram;
|
| + pSub->flags |= MEM_Blob;
|
| + pSub->n = nSub*sizeof(SubProgram*);
|
| + }
|
| + }
|
| + }
|
| +
|
| + pMem->flags = MEM_Int;
|
| + pMem->u.i = pOp->p1; /* P1 */
|
| + pMem++;
|
| +
|
| + pMem->flags = MEM_Int;
|
| + pMem->u.i = pOp->p2; /* P2 */
|
| + pMem++;
|
| +
|
| + pMem->flags = MEM_Int;
|
| + pMem->u.i = pOp->p3; /* P3 */
|
| + pMem++;
|
| +
|
| + if( sqlite3VdbeMemClearAndResize(pMem, 100) ){ /* P4 */
|
| + assert( p->db->mallocFailed );
|
| + return SQLITE_ERROR;
|
| + }
|
| + pMem->flags = MEM_Str|MEM_Term;
|
| + zP4 = displayP4(pOp, pMem->z, pMem->szMalloc);
|
| + if( zP4!=pMem->z ){
|
| + sqlite3VdbeMemSetStr(pMem, zP4, -1, SQLITE_UTF8, 0);
|
| + }else{
|
| + assert( pMem->z!=0 );
|
| + pMem->n = sqlite3Strlen30(pMem->z);
|
| + pMem->enc = SQLITE_UTF8;
|
| + }
|
| + pMem++;
|
| +
|
| + if( p->explain==1 ){
|
| + if( sqlite3VdbeMemClearAndResize(pMem, 4) ){
|
| + assert( p->db->mallocFailed );
|
| + return SQLITE_ERROR;
|
| + }
|
| + pMem->flags = MEM_Str|MEM_Term;
|
| + pMem->n = 2;
|
| + sqlite3_snprintf(3, pMem->z, "%.2x", pOp->p5); /* P5 */
|
| + pMem->enc = SQLITE_UTF8;
|
| + pMem++;
|
| +
|
| +#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
|
| + if( sqlite3VdbeMemClearAndResize(pMem, 500) ){
|
| + assert( p->db->mallocFailed );
|
| + return SQLITE_ERROR;
|
| + }
|
| + pMem->flags = MEM_Str|MEM_Term;
|
| + pMem->n = displayComment(pOp, zP4, pMem->z, 500);
|
| + pMem->enc = SQLITE_UTF8;
|
| +#else
|
| + pMem->flags = MEM_Null; /* Comment */
|
| +#endif
|
| + }
|
| +
|
| + p->nResColumn = 8 - 4*(p->explain-1);
|
| + p->pResultSet = &p->aMem[1];
|
| + p->rc = SQLITE_OK;
|
| + rc = SQLITE_ROW;
|
| + }
|
| + return rc;
|
| +}
|
| +#endif /* SQLITE_OMIT_EXPLAIN */
|
| +
|
| +#ifdef SQLITE_DEBUG
|
| +/*
|
| +** Print the SQL that was used to generate a VDBE program.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbePrintSql(Vdbe *p){
|
| + const char *z = 0;
|
| + if( p->zSql ){
|
| + z = p->zSql;
|
| + }else if( p->nOp>=1 ){
|
| + const VdbeOp *pOp = &p->aOp[0];
|
| + if( pOp->opcode==OP_Init && pOp->p4.z!=0 ){
|
| + z = pOp->p4.z;
|
| + while( sqlite3Isspace(*z) ) z++;
|
| + }
|
| + }
|
| + if( z ) printf("SQL: [%s]\n", z);
|
| +}
|
| +#endif
|
| +
|
| +#if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE)
|
| +/*
|
| +** Print an IOTRACE message showing SQL content.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbeIOTraceSql(Vdbe *p){
|
| + int nOp = p->nOp;
|
| + VdbeOp *pOp;
|
| + if( sqlite3IoTrace==0 ) return;
|
| + if( nOp<1 ) return;
|
| + pOp = &p->aOp[0];
|
| + if( pOp->opcode==OP_Init && pOp->p4.z!=0 ){
|
| + int i, j;
|
| + char z[1000];
|
| + sqlite3_snprintf(sizeof(z), z, "%s", pOp->p4.z);
|
| + for(i=0; sqlite3Isspace(z[i]); i++){}
|
| + for(j=0; z[i]; i++){
|
| + if( sqlite3Isspace(z[i]) ){
|
| + if( z[i-1]!=' ' ){
|
| + z[j++] = ' ';
|
| + }
|
| + }else{
|
| + z[j++] = z[i];
|
| + }
|
| + }
|
| + z[j] = 0;
|
| + sqlite3IoTrace("SQL %s\n", z);
|
| + }
|
| +}
|
| +#endif /* !SQLITE_OMIT_TRACE && SQLITE_ENABLE_IOTRACE */
|
| +
|
| +/*
|
| +** Allocate space from a fixed size buffer and return a pointer to
|
| +** that space. If insufficient space is available, return NULL.
|
| +**
|
| +** The pBuf parameter is the initial value of a pointer which will
|
| +** receive the new memory. pBuf is normally NULL. If pBuf is not
|
| +** NULL, it means that memory space has already been allocated and that
|
| +** this routine should not allocate any new memory. When pBuf is not
|
| +** NULL simply return pBuf. Only allocate new memory space when pBuf
|
| +** is NULL.
|
| +**
|
| +** nByte is the number of bytes of space needed.
|
| +**
|
| +** pFrom points to *pnFrom bytes of available space. New space is allocated
|
| +** from the end of the pFrom buffer and *pnFrom is decremented.
|
| +**
|
| +** *pnNeeded is a counter of the number of bytes of space that have failed
|
| +** to allocate. If there is insufficient space in pFrom to satisfy the
|
| +** request, then increment *pnNeeded by the amount of the request.
|
| +*/
|
| +static void *allocSpace(
|
| + void *pBuf, /* Where return pointer will be stored */
|
| + int nByte, /* Number of bytes to allocate */
|
| + u8 *pFrom, /* Memory available for allocation */
|
| + int *pnFrom, /* IN/OUT: Space available at pFrom */
|
| + int *pnNeeded /* If allocation cannot be made, increment *pnByte */
|
| +){
|
| + assert( EIGHT_BYTE_ALIGNMENT(pFrom) );
|
| + if( pBuf==0 ){
|
| + nByte = ROUND8(nByte);
|
| + if( nByte <= *pnFrom ){
|
| + *pnFrom -= nByte;
|
| + pBuf = &pFrom[*pnFrom];
|
| + }else{
|
| + *pnNeeded += nByte;
|
| + }
|
| + }
|
| + assert( EIGHT_BYTE_ALIGNMENT(pBuf) );
|
| + return pBuf;
|
| +}
|
| +
|
| +/*
|
| +** Rewind the VDBE back to the beginning in preparation for
|
| +** running it.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbeRewind(Vdbe *p){
|
| +#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
|
| + int i;
|
| +#endif
|
| + assert( p!=0 );
|
| + assert( p->magic==VDBE_MAGIC_INIT );
|
| +
|
| + /* There should be at least one opcode.
|
| + */
|
| + assert( p->nOp>0 );
|
| +
|
| + /* Set the magic to VDBE_MAGIC_RUN sooner rather than later. */
|
| + p->magic = VDBE_MAGIC_RUN;
|
| +
|
| +#ifdef SQLITE_DEBUG
|
| + for(i=1; i<p->nMem; i++){
|
| + assert( p->aMem[i].db==p->db );
|
| + }
|
| +#endif
|
| + p->pc = -1;
|
| + p->rc = SQLITE_OK;
|
| + p->errorAction = OE_Abort;
|
| + p->magic = VDBE_MAGIC_RUN;
|
| + p->nChange = 0;
|
| + p->cacheCtr = 1;
|
| + p->minWriteFileFormat = 255;
|
| + p->iStatement = 0;
|
| + p->nFkConstraint = 0;
|
| +#ifdef VDBE_PROFILE
|
| + for(i=0; i<p->nOp; i++){
|
| + p->aOp[i].cnt = 0;
|
| + p->aOp[i].cycles = 0;
|
| + }
|
| +#endif
|
| +}
|
| +
|
| +/*
|
| +** Prepare a virtual machine for execution for the first time after
|
| +** creating the virtual machine. This involves things such
|
| +** as allocating registers and initializing the program counter.
|
| +** After the VDBE has be prepped, it can be executed by one or more
|
| +** calls to sqlite3VdbeExec().
|
| +**
|
| +** This function may be called exactly once on each virtual machine.
|
| +** After this routine is called the VM has been "packaged" and is ready
|
| +** to run. After this routine is called, further calls to
|
| +** sqlite3VdbeAddOp() functions are prohibited. This routine disconnects
|
| +** the Vdbe from the Parse object that helped generate it so that the
|
| +** the Vdbe becomes an independent entity and the Parse object can be
|
| +** destroyed.
|
| +**
|
| +** Use the sqlite3VdbeRewind() procedure to restore a virtual machine back
|
| +** to its initial state after it has been run.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbeMakeReady(
|
| + Vdbe *p, /* The VDBE */
|
| + Parse *pParse /* Parsing context */
|
| +){
|
| + sqlite3 *db; /* The database connection */
|
| + int nVar; /* Number of parameters */
|
| + int nMem; /* Number of VM memory registers */
|
| + int nCursor; /* Number of cursors required */
|
| + int nArg; /* Number of arguments in subprograms */
|
| + int nOnce; /* Number of OP_Once instructions */
|
| + int n; /* Loop counter */
|
| + int nFree; /* Available free space */
|
| + u8 *zCsr; /* Memory available for allocation */
|
| + int nByte; /* How much extra memory is needed */
|
| +
|
| + assert( p!=0 );
|
| + assert( p->nOp>0 );
|
| + assert( pParse!=0 );
|
| + assert( p->magic==VDBE_MAGIC_INIT );
|
| + assert( pParse==p->pParse );
|
| + db = p->db;
|
| + assert( db->mallocFailed==0 );
|
| + nVar = pParse->nVar;
|
| + nMem = pParse->nMem;
|
| + nCursor = pParse->nTab;
|
| + nArg = pParse->nMaxArg;
|
| + nOnce = pParse->nOnce;
|
| + if( nOnce==0 ) nOnce = 1; /* Ensure at least one byte in p->aOnceFlag[] */
|
| +
|
| + /* For each cursor required, also allocate a memory cell. Memory
|
| + ** cells (nMem+1-nCursor)..nMem, inclusive, will never be used by
|
| + ** the vdbe program. Instead they are used to allocate space for
|
| + ** VdbeCursor/BtCursor structures. The blob of memory associated with
|
| + ** cursor 0 is stored in memory cell nMem. Memory cell (nMem-1)
|
| + ** stores the blob of memory associated with cursor 1, etc.
|
| + **
|
| + ** See also: allocateCursor().
|
| + */
|
| + nMem += nCursor;
|
| +
|
| + /* zCsr will initially point to nFree bytes of unused space at the
|
| + ** end of the opcode array, p->aOp. The computation of nFree is
|
| + ** conservative - it might be smaller than the true number of free
|
| + ** bytes, but never larger. nFree must be a multiple of 8 - it is
|
| + ** rounded down if is not.
|
| + */
|
| + n = ROUND8(sizeof(Op)*p->nOp); /* Bytes of opcode space used */
|
| + zCsr = &((u8*)p->aOp)[n]; /* Unused opcode space */
|
| + assert( EIGHT_BYTE_ALIGNMENT(zCsr) );
|
| + nFree = ROUNDDOWN8(pParse->szOpAlloc - n); /* Bytes of unused space */
|
| + assert( nFree>=0 );
|
| + if( nFree>0 ){
|
| + memset(zCsr, 0, nFree);
|
| + assert( EIGHT_BYTE_ALIGNMENT(&zCsr[nFree]) );
|
| + }
|
| +
|
| + resolveP2Values(p, &nArg);
|
| + p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort);
|
| + if( pParse->explain && nMem<10 ){
|
| + nMem = 10;
|
| + }
|
| + p->expired = 0;
|
| +
|
| + /* Memory for registers, parameters, cursor, etc, is allocated in two
|
| + ** passes. On the first pass, we try to reuse unused space at the
|
| + ** end of the opcode array. If we are unable to satisfy all memory
|
| + ** requirements by reusing the opcode array tail, then the second
|
| + ** pass will fill in the rest using a fresh allocation.
|
| + **
|
| + ** This two-pass approach that reuses as much memory as possible from
|
| + ** the leftover space at the end of the opcode array can significantly
|
| + ** reduce the amount of memory held by a prepared statement.
|
| + */
|
| + do {
|
| + nByte = 0;
|
| + p->aMem = allocSpace(p->aMem, nMem*sizeof(Mem), zCsr, &nFree, &nByte);
|
| + p->aVar = allocSpace(p->aVar, nVar*sizeof(Mem), zCsr, &nFree, &nByte);
|
| + p->apArg = allocSpace(p->apArg, nArg*sizeof(Mem*), zCsr, &nFree, &nByte);
|
| + p->azVar = allocSpace(p->azVar, nVar*sizeof(char*), zCsr, &nFree, &nByte);
|
| + p->apCsr = allocSpace(p->apCsr, nCursor*sizeof(VdbeCursor*),
|
| + zCsr, &nFree, &nByte);
|
| + p->aOnceFlag = allocSpace(p->aOnceFlag, nOnce, zCsr, &nFree, &nByte);
|
| +#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
| + p->anExec = allocSpace(p->anExec, p->nOp*sizeof(i64), zCsr, &nFree, &nByte);
|
| +#endif
|
| + if( nByte ){
|
| + p->pFree = sqlite3DbMallocZero(db, nByte);
|
| + }
|
| + zCsr = p->pFree;
|
| + nFree = nByte;
|
| + }while( nByte && !db->mallocFailed );
|
| +
|
| + p->nCursor = nCursor;
|
| + p->nOnceFlag = nOnce;
|
| + if( p->aVar ){
|
| + p->nVar = (ynVar)nVar;
|
| + for(n=0; n<nVar; n++){
|
| + p->aVar[n].flags = MEM_Null;
|
| + p->aVar[n].db = db;
|
| + }
|
| + }
|
| + if( p->azVar && pParse->nzVar>0 ){
|
| + p->nzVar = pParse->nzVar;
|
| + memcpy(p->azVar, pParse->azVar, p->nzVar*sizeof(p->azVar[0]));
|
| + memset(pParse->azVar, 0, pParse->nzVar*sizeof(pParse->azVar[0]));
|
| + }
|
| + if( p->aMem ){
|
| + p->aMem--; /* aMem[] goes from 1..nMem */
|
| + p->nMem = nMem; /* not from 0..nMem-1 */
|
| + for(n=1; n<=nMem; n++){
|
| + p->aMem[n].flags = MEM_Undefined;
|
| + p->aMem[n].db = db;
|
| + }
|
| + }
|
| + p->explain = pParse->explain;
|
| + sqlite3VdbeRewind(p);
|
| +}
|
| +
|
| +/*
|
| +** Close a VDBE cursor and release all the resources that cursor
|
| +** happens to hold.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){
|
| + if( pCx==0 ){
|
| + return;
|
| + }
|
| + assert( pCx->pBt==0 || pCx->eCurType==CURTYPE_BTREE );
|
| + switch( pCx->eCurType ){
|
| + case CURTYPE_SORTER: {
|
| + sqlite3VdbeSorterClose(p->db, pCx);
|
| + break;
|
| + }
|
| + case CURTYPE_BTREE: {
|
| + if( pCx->pBt ){
|
| + sqlite3BtreeClose(pCx->pBt);
|
| + /* The pCx->pCursor will be close automatically, if it exists, by
|
| + ** the call above. */
|
| + }else{
|
| + assert( pCx->uc.pCursor!=0 );
|
| + sqlite3BtreeCloseCursor(pCx->uc.pCursor);
|
| + }
|
| + break;
|
| + }
|
| +#ifndef SQLITE_OMIT_VIRTUALTABLE
|
| + case CURTYPE_VTAB: {
|
| + sqlite3_vtab_cursor *pVCur = pCx->uc.pVCur;
|
| + const sqlite3_module *pModule = pVCur->pVtab->pModule;
|
| + assert( pVCur->pVtab->nRef>0 );
|
| + pVCur->pVtab->nRef--;
|
| + pModule->xClose(pVCur);
|
| + break;
|
| + }
|
| +#endif
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Close all cursors in the current frame.
|
| +*/
|
| +static void closeCursorsInFrame(Vdbe *p){
|
| + if( p->apCsr ){
|
| + int i;
|
| + for(i=0; i<p->nCursor; i++){
|
| + VdbeCursor *pC = p->apCsr[i];
|
| + if( pC ){
|
| + sqlite3VdbeFreeCursor(p, pC);
|
| + p->apCsr[i] = 0;
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Copy the values stored in the VdbeFrame structure to its Vdbe. This
|
| +** is used, for example, when a trigger sub-program is halted to restore
|
| +** control to the main program.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *pFrame){
|
| + Vdbe *v = pFrame->v;
|
| + closeCursorsInFrame(v);
|
| +#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
| + v->anExec = pFrame->anExec;
|
| +#endif
|
| + v->aOnceFlag = pFrame->aOnceFlag;
|
| + v->nOnceFlag = pFrame->nOnceFlag;
|
| + v->aOp = pFrame->aOp;
|
| + v->nOp = pFrame->nOp;
|
| + v->aMem = pFrame->aMem;
|
| + v->nMem = pFrame->nMem;
|
| + v->apCsr = pFrame->apCsr;
|
| + v->nCursor = pFrame->nCursor;
|
| + v->db->lastRowid = pFrame->lastRowid;
|
| + v->nChange = pFrame->nChange;
|
| + v->db->nChange = pFrame->nDbChange;
|
| + return pFrame->pc;
|
| +}
|
| +
|
| +/*
|
| +** Close all cursors.
|
| +**
|
| +** Also release any dynamic memory held by the VM in the Vdbe.aMem memory
|
| +** cell array. This is necessary as the memory cell array may contain
|
| +** pointers to VdbeFrame objects, which may in turn contain pointers to
|
| +** open cursors.
|
| +*/
|
| +static void closeAllCursors(Vdbe *p){
|
| + if( p->pFrame ){
|
| + VdbeFrame *pFrame;
|
| + for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent);
|
| + sqlite3VdbeFrameRestore(pFrame);
|
| + p->pFrame = 0;
|
| + p->nFrame = 0;
|
| + }
|
| + assert( p->nFrame==0 );
|
| + closeCursorsInFrame(p);
|
| + if( p->aMem ){
|
| + releaseMemArray(&p->aMem[1], p->nMem);
|
| + }
|
| + while( p->pDelFrame ){
|
| + VdbeFrame *pDel = p->pDelFrame;
|
| + p->pDelFrame = pDel->pParent;
|
| + sqlite3VdbeFrameDelete(pDel);
|
| + }
|
| +
|
| + /* Delete any auxdata allocations made by the VM */
|
| + if( p->pAuxData ) sqlite3VdbeDeleteAuxData(p, -1, 0);
|
| + assert( p->pAuxData==0 );
|
| +}
|
| +
|
| +/*
|
| +** Clean up the VM after a single run.
|
| +*/
|
| +static void Cleanup(Vdbe *p){
|
| + sqlite3 *db = p->db;
|
| +
|
| +#ifdef SQLITE_DEBUG
|
| + /* Execute assert() statements to ensure that the Vdbe.apCsr[] and
|
| + ** Vdbe.aMem[] arrays have already been cleaned up. */
|
| + int i;
|
| + if( p->apCsr ) for(i=0; i<p->nCursor; i++) assert( p->apCsr[i]==0 );
|
| + if( p->aMem ){
|
| + for(i=1; i<=p->nMem; i++) assert( p->aMem[i].flags==MEM_Undefined );
|
| + }
|
| +#endif
|
| +
|
| + sqlite3DbFree(db, p->zErrMsg);
|
| + p->zErrMsg = 0;
|
| + p->pResultSet = 0;
|
| +}
|
| +
|
| +/*
|
| +** Set the number of result columns that will be returned by this SQL
|
| +** statement. This is now set at compile time, rather than during
|
| +** execution of the vdbe program so that sqlite3_column_count() can
|
| +** be called on an SQL statement before sqlite3_step().
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbeSetNumCols(Vdbe *p, int nResColumn){
|
| + Mem *pColName;
|
| + int n;
|
| + sqlite3 *db = p->db;
|
| +
|
| + releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
|
| + sqlite3DbFree(db, p->aColName);
|
| + n = nResColumn*COLNAME_N;
|
| + p->nResColumn = (u16)nResColumn;
|
| + p->aColName = pColName = (Mem*)sqlite3DbMallocZero(db, sizeof(Mem)*n );
|
| + if( p->aColName==0 ) return;
|
| + while( n-- > 0 ){
|
| + pColName->flags = MEM_Null;
|
| + pColName->db = p->db;
|
| + pColName++;
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Set the name of the idx'th column to be returned by the SQL statement.
|
| +** zName must be a pointer to a nul terminated string.
|
| +**
|
| +** This call must be made after a call to sqlite3VdbeSetNumCols().
|
| +**
|
| +** The final parameter, xDel, must be one of SQLITE_DYNAMIC, SQLITE_STATIC
|
| +** or SQLITE_TRANSIENT. If it is SQLITE_DYNAMIC, then the buffer pointed
|
| +** to by zName will be freed by sqlite3DbFree() when the vdbe is destroyed.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3VdbeSetColName(
|
| + Vdbe *p, /* Vdbe being configured */
|
| + int idx, /* Index of column zName applies to */
|
| + int var, /* One of the COLNAME_* constants */
|
| + const char *zName, /* Pointer to buffer containing name */
|
| + void (*xDel)(void*) /* Memory management strategy for zName */
|
| +){
|
| + int rc;
|
| + Mem *pColName;
|
| + assert( idx<p->nResColumn );
|
| + assert( var<COLNAME_N );
|
| + if( p->db->mallocFailed ){
|
| + assert( !zName || xDel!=SQLITE_DYNAMIC );
|
| + return SQLITE_NOMEM;
|
| + }
|
| + assert( p->aColName!=0 );
|
| + pColName = &(p->aColName[idx+var*p->nResColumn]);
|
| + rc = sqlite3VdbeMemSetStr(pColName, zName, -1, SQLITE_UTF8, xDel);
|
| + assert( rc!=0 || !zName || (pColName->flags&MEM_Term)!=0 );
|
| + return rc;
|
| +}
|
| +
|
| +/*
|
| +** A read or write transaction may or may not be active on database handle
|
| +** db. If a transaction is active, commit it. If there is a
|
| +** write-transaction spanning more than one database file, this routine
|
| +** takes care of the master journal trickery.
|
| +*/
|
| +static int vdbeCommit(sqlite3 *db, Vdbe *p){
|
| + int i;
|
| + int nTrans = 0; /* Number of databases with an active write-transaction */
|
| + int rc = SQLITE_OK;
|
| + int needXcommit = 0;
|
| +
|
| +#ifdef SQLITE_OMIT_VIRTUALTABLE
|
| + /* With this option, sqlite3VtabSync() is defined to be simply
|
| + ** SQLITE_OK so p is not used.
|
| + */
|
| + UNUSED_PARAMETER(p);
|
| +#endif
|
| +
|
| + /* Before doing anything else, call the xSync() callback for any
|
| + ** virtual module tables written in this transaction. This has to
|
| + ** be done before determining whether a master journal file is
|
| + ** required, as an xSync() callback may add an attached database
|
| + ** to the transaction.
|
| + */
|
| + rc = sqlite3VtabSync(db, p);
|
| +
|
| + /* This loop determines (a) if the commit hook should be invoked and
|
| + ** (b) how many database files have open write transactions, not
|
| + ** including the temp database. (b) is important because if more than
|
| + ** one database file has an open write transaction, a master journal
|
| + ** file is required for an atomic commit.
|
| + */
|
| + for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
|
| + Btree *pBt = db->aDb[i].pBt;
|
| + if( sqlite3BtreeIsInTrans(pBt) ){
|
| + needXcommit = 1;
|
| + if( i!=1 ) nTrans++;
|
| + sqlite3BtreeEnter(pBt);
|
| + rc = sqlite3PagerExclusiveLock(sqlite3BtreePager(pBt));
|
| + sqlite3BtreeLeave(pBt);
|
| + }
|
| + }
|
| + if( rc!=SQLITE_OK ){
|
| + return rc;
|
| + }
|
| +
|
| + /* If there are any write-transactions at all, invoke the commit hook */
|
| + if( needXcommit && db->xCommitCallback ){
|
| + rc = db->xCommitCallback(db->pCommitArg);
|
| + if( rc ){
|
| + return SQLITE_CONSTRAINT_COMMITHOOK;
|
| + }
|
| + }
|
| +
|
| + /* The simple case - no more than one database file (not counting the
|
| + ** TEMP database) has a transaction active. There is no need for the
|
| + ** master-journal.
|
| + **
|
| + ** If the return value of sqlite3BtreeGetFilename() is a zero length
|
| + ** string, it means the main database is :memory: or a temp file. In
|
| + ** that case we do not support atomic multi-file commits, so use the
|
| + ** simple case then too.
|
| + */
|
| + if( 0==sqlite3Strlen30(sqlite3BtreeGetFilename(db->aDb[0].pBt))
|
| + || nTrans<=1
|
| + ){
|
| + for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
|
| + Btree *pBt = db->aDb[i].pBt;
|
| + if( pBt ){
|
| + rc = sqlite3BtreeCommitPhaseOne(pBt, 0);
|
| + }
|
| + }
|
| +
|
| + /* Do the commit only if all databases successfully complete phase 1.
|
| + ** If one of the BtreeCommitPhaseOne() calls fails, this indicates an
|
| + ** IO error while deleting or truncating a journal file. It is unlikely,
|
| + ** but could happen. In this case abandon processing and return the error.
|
| + */
|
| + for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
|
| + Btree *pBt = db->aDb[i].pBt;
|
| + if( pBt ){
|
| + rc = sqlite3BtreeCommitPhaseTwo(pBt, 0);
|
| + }
|
| + }
|
| + if( rc==SQLITE_OK ){
|
| + sqlite3VtabCommit(db);
|
| + }
|
| + }
|
| +
|
| + /* The complex case - There is a multi-file write-transaction active.
|
| + ** This requires a master journal file to ensure the transaction is
|
| + ** committed atomically.
|
| + */
|
| +#ifndef SQLITE_OMIT_DISKIO
|
| + else{
|
| + sqlite3_vfs *pVfs = db->pVfs;
|
| + int needSync = 0;
|
| + char *zMaster = 0; /* File-name for the master journal */
|
| + char const *zMainFile = sqlite3BtreeGetFilename(db->aDb[0].pBt);
|
| + sqlite3_file *pMaster = 0;
|
| + i64 offset = 0;
|
| + int res;
|
| + int retryCount = 0;
|
| + int nMainFile;
|
| +
|
| + /* Select a master journal file name */
|
| + nMainFile = sqlite3Strlen30(zMainFile);
|
| + zMaster = sqlite3MPrintf(db, "%s-mjXXXXXX9XXz", zMainFile);
|
| + if( zMaster==0 ) return SQLITE_NOMEM;
|
| + do {
|
| + u32 iRandom;
|
| + if( retryCount ){
|
| + if( retryCount>100 ){
|
| + sqlite3_log(SQLITE_FULL, "MJ delete: %s", zMaster);
|
| + sqlite3OsDelete(pVfs, zMaster, 0);
|
| + break;
|
| + }else if( retryCount==1 ){
|
| + sqlite3_log(SQLITE_FULL, "MJ collide: %s", zMaster);
|
| + }
|
| + }
|
| + retryCount++;
|
| + sqlite3_randomness(sizeof(iRandom), &iRandom);
|
| + sqlite3_snprintf(13, &zMaster[nMainFile], "-mj%06X9%02X",
|
| + (iRandom>>8)&0xffffff, iRandom&0xff);
|
| + /* The antipenultimate character of the master journal name must
|
| + ** be "9" to avoid name collisions when using 8+3 filenames. */
|
| + assert( zMaster[sqlite3Strlen30(zMaster)-3]=='9' );
|
| + sqlite3FileSuffix3(zMainFile, zMaster);
|
| + rc = sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS, &res);
|
| + }while( rc==SQLITE_OK && res );
|
| + if( rc==SQLITE_OK ){
|
| + /* Open the master journal. */
|
| + rc = sqlite3OsOpenMalloc(pVfs, zMaster, &pMaster,
|
| + SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|
|
| + SQLITE_OPEN_EXCLUSIVE|SQLITE_OPEN_MASTER_JOURNAL, 0
|
| + );
|
| + }
|
| + if( rc!=SQLITE_OK ){
|
| + sqlite3DbFree(db, zMaster);
|
| + return rc;
|
| + }
|
| +
|
| + /* Write the name of each database file in the transaction into the new
|
| + ** master journal file. If an error occurs at this point close
|
| + ** and delete the master journal file. All the individual journal files
|
| + ** still have 'null' as the master journal pointer, so they will roll
|
| + ** back independently if a failure occurs.
|
| + */
|
| + for(i=0; i<db->nDb; i++){
|
| + Btree *pBt = db->aDb[i].pBt;
|
| + if( sqlite3BtreeIsInTrans(pBt) ){
|
| + char const *zFile = sqlite3BtreeGetJournalname(pBt);
|
| + if( zFile==0 ){
|
| + continue; /* Ignore TEMP and :memory: databases */
|
| + }
|
| + assert( zFile[0]!=0 );
|
| + if( !needSync && !sqlite3BtreeSyncDisabled(pBt) ){
|
| + needSync = 1;
|
| + }
|
| + rc = sqlite3OsWrite(pMaster, zFile, sqlite3Strlen30(zFile)+1, offset);
|
| + offset += sqlite3Strlen30(zFile)+1;
|
| + if( rc!=SQLITE_OK ){
|
| + sqlite3OsCloseFree(pMaster);
|
| + sqlite3OsDelete(pVfs, zMaster, 0);
|
| + sqlite3DbFree(db, zMaster);
|
| + return rc;
|
| + }
|
| + }
|
| + }
|
| +
|
| + /* Sync the master journal file. If the IOCAP_SEQUENTIAL device
|
| + ** flag is set this is not required.
|
| + */
|
| + if( needSync
|
| + && 0==(sqlite3OsDeviceCharacteristics(pMaster)&SQLITE_IOCAP_SEQUENTIAL)
|
| + && SQLITE_OK!=(rc = sqlite3OsSync(pMaster, SQLITE_SYNC_NORMAL))
|
| + ){
|
| + sqlite3OsCloseFree(pMaster);
|
| + sqlite3OsDelete(pVfs, zMaster, 0);
|
| + sqlite3DbFree(db, zMaster);
|
| + return rc;
|
| + }
|
| +
|
| + /* Sync all the db files involved in the transaction. The same call
|
| + ** sets the master journal pointer in each individual journal. If
|
| + ** an error occurs here, do not delete the master journal file.
|
| + **
|
| + ** If the error occurs during the first call to
|
| + ** sqlite3BtreeCommitPhaseOne(), then there is a chance that the
|
| + ** master journal file will be orphaned. But we cannot delete it,
|
| + ** in case the master journal file name was written into the journal
|
| + ** file before the failure occurred.
|
| + */
|
| + for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
|
| + Btree *pBt = db->aDb[i].pBt;
|
| + if( pBt ){
|
| + rc = sqlite3BtreeCommitPhaseOne(pBt, zMaster);
|
| + }
|
| + }
|
| + sqlite3OsCloseFree(pMaster);
|
| + assert( rc!=SQLITE_BUSY );
|
| + if( rc!=SQLITE_OK ){
|
| + sqlite3DbFree(db, zMaster);
|
| + return rc;
|
| + }
|
| +
|
| + /* Delete the master journal file. This commits the transaction. After
|
| + ** doing this the directory is synced again before any individual
|
| + ** transaction files are deleted.
|
| + */
|
| + rc = sqlite3OsDelete(pVfs, zMaster, needSync);
|
| + sqlite3DbFree(db, zMaster);
|
| + zMaster = 0;
|
| + if( rc ){
|
| + return rc;
|
| + }
|
| +
|
| + /* All files and directories have already been synced, so the following
|
| + ** calls to sqlite3BtreeCommitPhaseTwo() are only closing files and
|
| + ** deleting or truncating journals. If something goes wrong while
|
| + ** this is happening we don't really care. The integrity of the
|
| + ** transaction is already guaranteed, but some stray 'cold' journals
|
| + ** may be lying around. Returning an error code won't help matters.
|
| + */
|
| + disable_simulated_io_errors();
|
| + sqlite3BeginBenignMalloc();
|
| + for(i=0; i<db->nDb; i++){
|
| + Btree *pBt = db->aDb[i].pBt;
|
| + if( pBt ){
|
| + sqlite3BtreeCommitPhaseTwo(pBt, 1);
|
| + }
|
| + }
|
| + sqlite3EndBenignMalloc();
|
| + enable_simulated_io_errors();
|
| +
|
| + sqlite3VtabCommit(db);
|
| + }
|
| +#endif
|
| +
|
| + return rc;
|
| +}
|
| +
|
| +/*
|
| +** This routine checks that the sqlite3.nVdbeActive count variable
|
| +** matches the number of vdbe's in the list sqlite3.pVdbe that are
|
| +** currently active. An assertion fails if the two counts do not match.
|
| +** This is an internal self-check only - it is not an essential processing
|
| +** step.
|
| +**
|
| +** This is a no-op if NDEBUG is defined.
|
| +*/
|
| +#ifndef NDEBUG
|
| +static void checkActiveVdbeCnt(sqlite3 *db){
|
| + Vdbe *p;
|
| + int cnt = 0;
|
| + int nWrite = 0;
|
| + int nRead = 0;
|
| + p = db->pVdbe;
|
| + while( p ){
|
| + if( sqlite3_stmt_busy((sqlite3_stmt*)p) ){
|
| + cnt++;
|
| + if( p->readOnly==0 ) nWrite++;
|
| + if( p->bIsReader ) nRead++;
|
| + }
|
| + p = p->pNext;
|
| + }
|
| + assert( cnt==db->nVdbeActive );
|
| + assert( nWrite==db->nVdbeWrite );
|
| + assert( nRead==db->nVdbeRead );
|
| +}
|
| +#else
|
| +#define checkActiveVdbeCnt(x)
|
| +#endif
|
| +
|
| +/*
|
| +** If the Vdbe passed as the first argument opened a statement-transaction,
|
| +** close it now. Argument eOp must be either SAVEPOINT_ROLLBACK or
|
| +** SAVEPOINT_RELEASE. If it is SAVEPOINT_ROLLBACK, then the statement
|
| +** transaction is rolled back. If eOp is SAVEPOINT_RELEASE, then the
|
| +** statement transaction is committed.
|
| +**
|
| +** If an IO error occurs, an SQLITE_IOERR_XXX error code is returned.
|
| +** Otherwise SQLITE_OK.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){
|
| + sqlite3 *const db = p->db;
|
| + int rc = SQLITE_OK;
|
| +
|
| + /* If p->iStatement is greater than zero, then this Vdbe opened a
|
| + ** statement transaction that should be closed here. The only exception
|
| + ** is that an IO error may have occurred, causing an emergency rollback.
|
| + ** In this case (db->nStatement==0), and there is nothing to do.
|
| + */
|
| + if( db->nStatement && p->iStatement ){
|
| + int i;
|
| + const int iSavepoint = p->iStatement-1;
|
| +
|
| + assert( eOp==SAVEPOINT_ROLLBACK || eOp==SAVEPOINT_RELEASE);
|
| + assert( db->nStatement>0 );
|
| + assert( p->iStatement==(db->nStatement+db->nSavepoint) );
|
| +
|
| + for(i=0; i<db->nDb; i++){
|
| + int rc2 = SQLITE_OK;
|
| + Btree *pBt = db->aDb[i].pBt;
|
| + if( pBt ){
|
| + if( eOp==SAVEPOINT_ROLLBACK ){
|
| + rc2 = sqlite3BtreeSavepoint(pBt, SAVEPOINT_ROLLBACK, iSavepoint);
|
| + }
|
| + if( rc2==SQLITE_OK ){
|
| + rc2 = sqlite3BtreeSavepoint(pBt, SAVEPOINT_RELEASE, iSavepoint);
|
| + }
|
| + if( rc==SQLITE_OK ){
|
| + rc = rc2;
|
| + }
|
| + }
|
| + }
|
| + db->nStatement--;
|
| + p->iStatement = 0;
|
| +
|
| + if( rc==SQLITE_OK ){
|
| + if( eOp==SAVEPOINT_ROLLBACK ){
|
| + rc = sqlite3VtabSavepoint(db, SAVEPOINT_ROLLBACK, iSavepoint);
|
| + }
|
| + if( rc==SQLITE_OK ){
|
| + rc = sqlite3VtabSavepoint(db, SAVEPOINT_RELEASE, iSavepoint);
|
| + }
|
| + }
|
| +
|
| + /* If the statement transaction is being rolled back, also restore the
|
| + ** database handles deferred constraint counter to the value it had when
|
| + ** the statement transaction was opened. */
|
| + if( eOp==SAVEPOINT_ROLLBACK ){
|
| + db->nDeferredCons = p->nStmtDefCons;
|
| + db->nDeferredImmCons = p->nStmtDefImmCons;
|
| + }
|
| + }
|
| + return rc;
|
| +}
|
| +
|
| +/*
|
| +** This function is called when a transaction opened by the database
|
| +** handle associated with the VM passed as an argument is about to be
|
| +** committed. If there are outstanding deferred foreign key constraint
|
| +** violations, return SQLITE_ERROR. Otherwise, SQLITE_OK.
|
| +**
|
| +** If there are outstanding FK violations and this function returns
|
| +** SQLITE_ERROR, set the result of the VM to SQLITE_CONSTRAINT_FOREIGNKEY
|
| +** and write an error message to it. Then return SQLITE_ERROR.
|
| +*/
|
| +#ifndef SQLITE_OMIT_FOREIGN_KEY
|
| +SQLITE_PRIVATE int sqlite3VdbeCheckFk(Vdbe *p, int deferred){
|
| + sqlite3 *db = p->db;
|
| + if( (deferred && (db->nDeferredCons+db->nDeferredImmCons)>0)
|
| + || (!deferred && p->nFkConstraint>0)
|
| + ){
|
| + p->rc = SQLITE_CONSTRAINT_FOREIGNKEY;
|
| + p->errorAction = OE_Abort;
|
| + sqlite3VdbeError(p, "FOREIGN KEY constraint failed");
|
| + return SQLITE_ERROR;
|
| + }
|
| + return SQLITE_OK;
|
| +}
|
| +#endif
|
| +
|
| +/*
|
| +** This routine is called the when a VDBE tries to halt. If the VDBE
|
| +** has made changes and is in autocommit mode, then commit those
|
| +** changes. If a rollback is needed, then do the rollback.
|
| +**
|
| +** This routine is the only way to move the state of a VM from
|
| +** SQLITE_MAGIC_RUN to SQLITE_MAGIC_HALT. It is harmless to
|
| +** call this on a VM that is in the SQLITE_MAGIC_HALT state.
|
| +**
|
| +** Return an error code. If the commit could not complete because of
|
| +** lock contention, return SQLITE_BUSY. If SQLITE_BUSY is returned, it
|
| +** means the close did not happen and needs to be repeated.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
|
| + int rc; /* Used to store transient return codes */
|
| + sqlite3 *db = p->db;
|
| +
|
| + /* This function contains the logic that determines if a statement or
|
| + ** transaction will be committed or rolled back as a result of the
|
| + ** execution of this virtual machine.
|
| + **
|
| + ** If any of the following errors occur:
|
| + **
|
| + ** SQLITE_NOMEM
|
| + ** SQLITE_IOERR
|
| + ** SQLITE_FULL
|
| + ** SQLITE_INTERRUPT
|
| + **
|
| + ** Then the internal cache might have been left in an inconsistent
|
| + ** state. We need to rollback the statement transaction, if there is
|
| + ** one, or the complete transaction if there is no statement transaction.
|
| + */
|
| +
|
| + if( p->db->mallocFailed ){
|
| + p->rc = SQLITE_NOMEM;
|
| + }
|
| + if( p->aOnceFlag ) memset(p->aOnceFlag, 0, p->nOnceFlag);
|
| + closeAllCursors(p);
|
| + if( p->magic!=VDBE_MAGIC_RUN ){
|
| + return SQLITE_OK;
|
| + }
|
| + checkActiveVdbeCnt(db);
|
| +
|
| + /* No commit or rollback needed if the program never started or if the
|
| + ** SQL statement does not read or write a database file. */
|
| + if( p->pc>=0 && p->bIsReader ){
|
| + int mrc; /* Primary error code from p->rc */
|
| + int eStatementOp = 0;
|
| + int isSpecialError; /* Set to true if a 'special' error */
|
| +
|
| + /* Lock all btrees used by the statement */
|
| + sqlite3VdbeEnter(p);
|
| +
|
| + /* Check for one of the special errors */
|
| + mrc = p->rc & 0xff;
|
| + isSpecialError = mrc==SQLITE_NOMEM || mrc==SQLITE_IOERR
|
| + || mrc==SQLITE_INTERRUPT || mrc==SQLITE_FULL;
|
| + if( isSpecialError ){
|
| + /* If the query was read-only and the error code is SQLITE_INTERRUPT,
|
| + ** no rollback is necessary. Otherwise, at least a savepoint
|
| + ** transaction must be rolled back to restore the database to a
|
| + ** consistent state.
|
| + **
|
| + ** Even if the statement is read-only, it is important to perform
|
| + ** a statement or transaction rollback operation. If the error
|
| + ** occurred while writing to the journal, sub-journal or database
|
| + ** file as part of an effort to free up cache space (see function
|
| + ** pagerStress() in pager.c), the rollback is required to restore
|
| + ** the pager to a consistent state.
|
| + */
|
| + if( !p->readOnly || mrc!=SQLITE_INTERRUPT ){
|
| + if( (mrc==SQLITE_NOMEM || mrc==SQLITE_FULL) && p->usesStmtJournal ){
|
| + eStatementOp = SAVEPOINT_ROLLBACK;
|
| + }else{
|
| + /* We are forced to roll back the active transaction. Before doing
|
| + ** so, abort any other statements this handle currently has active.
|
| + */
|
| + sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK);
|
| + sqlite3CloseSavepoints(db);
|
| + db->autoCommit = 1;
|
| + p->nChange = 0;
|
| + }
|
| + }
|
| + }
|
| +
|
| + /* Check for immediate foreign key violations. */
|
| + if( p->rc==SQLITE_OK ){
|
| + sqlite3VdbeCheckFk(p, 0);
|
| + }
|
| +
|
| + /* If the auto-commit flag is set and this is the only active writer
|
| + ** VM, then we do either a commit or rollback of the current transaction.
|
| + **
|
| + ** Note: This block also runs if one of the special errors handled
|
| + ** above has occurred.
|
| + */
|
| + if( !sqlite3VtabInSync(db)
|
| + && db->autoCommit
|
| + && db->nVdbeWrite==(p->readOnly==0)
|
| + ){
|
| + if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){
|
| + rc = sqlite3VdbeCheckFk(p, 1);
|
| + if( rc!=SQLITE_OK ){
|
| + if( NEVER(p->readOnly) ){
|
| + sqlite3VdbeLeave(p);
|
| + return SQLITE_ERROR;
|
| + }
|
| + rc = SQLITE_CONSTRAINT_FOREIGNKEY;
|
| + }else{
|
| + /* The auto-commit flag is true, the vdbe program was successful
|
| + ** or hit an 'OR FAIL' constraint and there are no deferred foreign
|
| + ** key constraints to hold up the transaction. This means a commit
|
| + ** is required. */
|
| + rc = vdbeCommit(db, p);
|
| + }
|
| + if( rc==SQLITE_BUSY && p->readOnly ){
|
| + sqlite3VdbeLeave(p);
|
| + return SQLITE_BUSY;
|
| + }else if( rc!=SQLITE_OK ){
|
| + p->rc = rc;
|
| + sqlite3RollbackAll(db, SQLITE_OK);
|
| + p->nChange = 0;
|
| + }else{
|
| + db->nDeferredCons = 0;
|
| + db->nDeferredImmCons = 0;
|
| + db->flags &= ~SQLITE_DeferFKs;
|
| + sqlite3CommitInternalChanges(db);
|
| + }
|
| + }else{
|
| + sqlite3RollbackAll(db, SQLITE_OK);
|
| + p->nChange = 0;
|
| + }
|
| + db->nStatement = 0;
|
| + }else if( eStatementOp==0 ){
|
| + if( p->rc==SQLITE_OK || p->errorAction==OE_Fail ){
|
| + eStatementOp = SAVEPOINT_RELEASE;
|
| + }else if( p->errorAction==OE_Abort ){
|
| + eStatementOp = SAVEPOINT_ROLLBACK;
|
| + }else{
|
| + sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK);
|
| + sqlite3CloseSavepoints(db);
|
| + db->autoCommit = 1;
|
| + p->nChange = 0;
|
| + }
|
| + }
|
| +
|
| + /* If eStatementOp is non-zero, then a statement transaction needs to
|
| + ** be committed or rolled back. Call sqlite3VdbeCloseStatement() to
|
| + ** do so. If this operation returns an error, and the current statement
|
| + ** error code is SQLITE_OK or SQLITE_CONSTRAINT, then promote the
|
| + ** current statement error code.
|
| + */
|
| + if( eStatementOp ){
|
| + rc = sqlite3VdbeCloseStatement(p, eStatementOp);
|
| + if( rc ){
|
| + if( p->rc==SQLITE_OK || (p->rc&0xff)==SQLITE_CONSTRAINT ){
|
| + p->rc = rc;
|
| + sqlite3DbFree(db, p->zErrMsg);
|
| + p->zErrMsg = 0;
|
| + }
|
| + sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK);
|
| + sqlite3CloseSavepoints(db);
|
| + db->autoCommit = 1;
|
| + p->nChange = 0;
|
| + }
|
| + }
|
| +
|
| + /* If this was an INSERT, UPDATE or DELETE and no statement transaction
|
| + ** has been rolled back, update the database connection change-counter.
|
| + */
|
| + if( p->changeCntOn ){
|
| + if( eStatementOp!=SAVEPOINT_ROLLBACK ){
|
| + sqlite3VdbeSetChanges(db, p->nChange);
|
| + }else{
|
| + sqlite3VdbeSetChanges(db, 0);
|
| + }
|
| + p->nChange = 0;
|
| + }
|
| +
|
| + /* Release the locks */
|
| + sqlite3VdbeLeave(p);
|
| + }
|
| +
|
| + /* We have successfully halted and closed the VM. Record this fact. */
|
| + if( p->pc>=0 ){
|
| + db->nVdbeActive--;
|
| + if( !p->readOnly ) db->nVdbeWrite--;
|
| + if( p->bIsReader ) db->nVdbeRead--;
|
| + assert( db->nVdbeActive>=db->nVdbeRead );
|
| + assert( db->nVdbeRead>=db->nVdbeWrite );
|
| + assert( db->nVdbeWrite>=0 );
|
| + }
|
| + p->magic = VDBE_MAGIC_HALT;
|
| + checkActiveVdbeCnt(db);
|
| + if( p->db->mallocFailed ){
|
| + p->rc = SQLITE_NOMEM;
|
| + }
|
| +
|
| + /* If the auto-commit flag is set to true, then any locks that were held
|
| + ** by connection db have now been released. Call sqlite3ConnectionUnlocked()
|
| + ** to invoke any required unlock-notify callbacks.
|
| + */
|
| + if( db->autoCommit ){
|
| + sqlite3ConnectionUnlocked(db);
|
| + }
|
| +
|
| + assert( db->nVdbeActive>0 || db->autoCommit==0 || db->nStatement==0 );
|
| + return (p->rc==SQLITE_BUSY ? SQLITE_BUSY : SQLITE_OK);
|
| +}
|
| +
|
| +
|
| +/*
|
| +** Each VDBE holds the result of the most recent sqlite3_step() call
|
| +** in p->rc. This routine sets that result back to SQLITE_OK.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbeResetStepResult(Vdbe *p){
|
| + p->rc = SQLITE_OK;
|
| +}
|
| +
|
| +/*
|
| +** Copy the error code and error message belonging to the VDBE passed
|
| +** as the first argument to its database handle (so that they will be
|
| +** returned by calls to sqlite3_errcode() and sqlite3_errmsg()).
|
| +**
|
| +** This function does not clear the VDBE error code or message, just
|
| +** copies them to the database handle.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p){
|
| + sqlite3 *db = p->db;
|
| + int rc = p->rc;
|
| + if( p->zErrMsg ){
|
| + u8 mallocFailed = db->mallocFailed;
|
| + sqlite3BeginBenignMalloc();
|
| + if( db->pErr==0 ) db->pErr = sqlite3ValueNew(db);
|
| + sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, SQLITE_TRANSIENT);
|
| + sqlite3EndBenignMalloc();
|
| + db->mallocFailed = mallocFailed;
|
| + db->errCode = rc;
|
| + }else{
|
| + sqlite3Error(db, rc);
|
| + }
|
| + return rc;
|
| +}
|
| +
|
| +#ifdef SQLITE_ENABLE_SQLLOG
|
| +/*
|
| +** If an SQLITE_CONFIG_SQLLOG hook is registered and the VM has been run,
|
| +** invoke it.
|
| +*/
|
| +static void vdbeInvokeSqllog(Vdbe *v){
|
| + if( sqlite3GlobalConfig.xSqllog && v->rc==SQLITE_OK && v->zSql && v->pc>=0 ){
|
| + char *zExpanded = sqlite3VdbeExpandSql(v, v->zSql);
|
| + assert( v->db->init.busy==0 );
|
| + if( zExpanded ){
|
| + sqlite3GlobalConfig.xSqllog(
|
| + sqlite3GlobalConfig.pSqllogArg, v->db, zExpanded, 1
|
| + );
|
| + sqlite3DbFree(v->db, zExpanded);
|
| + }
|
| + }
|
| +}
|
| +#else
|
| +# define vdbeInvokeSqllog(x)
|
| +#endif
|
| +
|
| +/*
|
| +** Clean up a VDBE after execution but do not delete the VDBE just yet.
|
| +** Write any error messages into *pzErrMsg. Return the result code.
|
| +**
|
| +** After this routine is run, the VDBE should be ready to be executed
|
| +** again.
|
| +**
|
| +** To look at it another way, this routine resets the state of the
|
| +** virtual machine from VDBE_MAGIC_RUN or VDBE_MAGIC_HALT back to
|
| +** VDBE_MAGIC_INIT.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){
|
| + sqlite3 *db;
|
| + db = p->db;
|
| +
|
| + /* If the VM did not run to completion or if it encountered an
|
| + ** error, then it might not have been halted properly. So halt
|
| + ** it now.
|
| + */
|
| + sqlite3VdbeHalt(p);
|
| +
|
| + /* If the VDBE has be run even partially, then transfer the error code
|
| + ** and error message from the VDBE into the main database structure. But
|
| + ** if the VDBE has just been set to run but has not actually executed any
|
| + ** instructions yet, leave the main database error information unchanged.
|
| + */
|
| + if( p->pc>=0 ){
|
| + vdbeInvokeSqllog(p);
|
| + sqlite3VdbeTransferError(p);
|
| + sqlite3DbFree(db, p->zErrMsg);
|
| + p->zErrMsg = 0;
|
| + if( p->runOnlyOnce ) p->expired = 1;
|
| + }else if( p->rc && p->expired ){
|
| + /* The expired flag was set on the VDBE before the first call
|
| + ** to sqlite3_step(). For consistency (since sqlite3_step() was
|
| + ** called), set the database error in this case as well.
|
| + */
|
| + sqlite3ErrorWithMsg(db, p->rc, p->zErrMsg ? "%s" : 0, p->zErrMsg);
|
| + sqlite3DbFree(db, p->zErrMsg);
|
| + p->zErrMsg = 0;
|
| + }
|
| +
|
| + /* Reclaim all memory used by the VDBE
|
| + */
|
| + Cleanup(p);
|
| +
|
| + /* Save profiling information from this VDBE run.
|
| + */
|
| +#ifdef VDBE_PROFILE
|
| + {
|
| + FILE *out = fopen("vdbe_profile.out", "a");
|
| + if( out ){
|
| + int i;
|
| + fprintf(out, "---- ");
|
| + for(i=0; i<p->nOp; i++){
|
| + fprintf(out, "%02x", p->aOp[i].opcode);
|
| + }
|
| + fprintf(out, "\n");
|
| + if( p->zSql ){
|
| + char c, pc = 0;
|
| + fprintf(out, "-- ");
|
| + for(i=0; (c = p->zSql[i])!=0; i++){
|
| + if( pc=='\n' ) fprintf(out, "-- ");
|
| + putc(c, out);
|
| + pc = c;
|
| + }
|
| + if( pc!='\n' ) fprintf(out, "\n");
|
| + }
|
| + for(i=0; i<p->nOp; i++){
|
| + char zHdr[100];
|
| + sqlite3_snprintf(sizeof(zHdr), zHdr, "%6u %12llu %8llu ",
|
| + p->aOp[i].cnt,
|
| + p->aOp[i].cycles,
|
| + p->aOp[i].cnt>0 ? p->aOp[i].cycles/p->aOp[i].cnt : 0
|
| + );
|
| + fprintf(out, "%s", zHdr);
|
| + sqlite3VdbePrintOp(out, i, &p->aOp[i]);
|
| + }
|
| + fclose(out);
|
| + }
|
| + }
|
| +#endif
|
| + p->iCurrentTime = 0;
|
| + p->magic = VDBE_MAGIC_INIT;
|
| + return p->rc & db->errMask;
|
| +}
|
| +
|
| +/*
|
| +** Clean up and delete a VDBE after execution. Return an integer which is
|
| +** the result code. Write any error message text into *pzErrMsg.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe *p){
|
| + int rc = SQLITE_OK;
|
| + if( p->magic==VDBE_MAGIC_RUN || p->magic==VDBE_MAGIC_HALT ){
|
| + rc = sqlite3VdbeReset(p);
|
| + assert( (rc & p->db->errMask)==rc );
|
| + }
|
| + sqlite3VdbeDelete(p);
|
| + return rc;
|
| +}
|
| +
|
| +/*
|
| +** If parameter iOp is less than zero, then invoke the destructor for
|
| +** all auxiliary data pointers currently cached by the VM passed as
|
| +** the first argument.
|
| +**
|
| +** Or, if iOp is greater than or equal to zero, then the destructor is
|
| +** only invoked for those auxiliary data pointers created by the user
|
| +** function invoked by the OP_Function opcode at instruction iOp of
|
| +** VM pVdbe, and only then if:
|
| +**
|
| +** * the associated function parameter is the 32nd or later (counting
|
| +** from left to right), or
|
| +**
|
| +** * the corresponding bit in argument mask is clear (where the first
|
| +** function parameter corresponds to bit 0 etc.).
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(Vdbe *pVdbe, int iOp, int mask){
|
| + AuxData **pp = &pVdbe->pAuxData;
|
| + while( *pp ){
|
| + AuxData *pAux = *pp;
|
| + if( (iOp<0)
|
| + || (pAux->iOp==iOp && (pAux->iArg>31 || !(mask & MASKBIT32(pAux->iArg))))
|
| + ){
|
| + testcase( pAux->iArg==31 );
|
| + if( pAux->xDelete ){
|
| + pAux->xDelete(pAux->pAux);
|
| + }
|
| + *pp = pAux->pNext;
|
| + sqlite3DbFree(pVdbe->db, pAux);
|
| + }else{
|
| + pp= &pAux->pNext;
|
| + }
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Free all memory associated with the Vdbe passed as the second argument,
|
| +** except for object itself, which is preserved.
|
| +**
|
| +** The difference between this function and sqlite3VdbeDelete() is that
|
| +** VdbeDelete() also unlinks the Vdbe from the list of VMs associated with
|
| +** the database connection and frees the object itself.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){
|
| + SubProgram *pSub, *pNext;
|
| + int i;
|
| + assert( p->db==0 || p->db==db );
|
| + releaseMemArray(p->aVar, p->nVar);
|
| + releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
|
| + for(pSub=p->pProgram; pSub; pSub=pNext){
|
| + pNext = pSub->pNext;
|
| + vdbeFreeOpArray(db, pSub->aOp, pSub->nOp);
|
| + sqlite3DbFree(db, pSub);
|
| + }
|
| + for(i=p->nzVar-1; i>=0; i--) sqlite3DbFree(db, p->azVar[i]);
|
| + vdbeFreeOpArray(db, p->aOp, p->nOp);
|
| + sqlite3DbFree(db, p->aColName);
|
| + sqlite3DbFree(db, p->zSql);
|
| + sqlite3DbFree(db, p->pFree);
|
| +#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
| + for(i=0; i<p->nScan; i++){
|
| + sqlite3DbFree(db, p->aScan[i].zName);
|
| + }
|
| + sqlite3DbFree(db, p->aScan);
|
| +#endif
|
| +}
|
| +
|
| +/*
|
| +** Delete an entire VDBE.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe *p){
|
| + sqlite3 *db;
|
| +
|
| + if( NEVER(p==0) ) return;
|
| + db = p->db;
|
| + assert( sqlite3_mutex_held(db->mutex) );
|
| + sqlite3VdbeClearObject(db, p);
|
| + if( p->pPrev ){
|
| + p->pPrev->pNext = p->pNext;
|
| + }else{
|
| + assert( db->pVdbe==p );
|
| + db->pVdbe = p->pNext;
|
| + }
|
| + if( p->pNext ){
|
| + p->pNext->pPrev = p->pPrev;
|
| + }
|
| + p->magic = VDBE_MAGIC_DEAD;
|
| + p->db = 0;
|
| + sqlite3DbFree(db, p);
|
| +}
|
| +
|
| +/*
|
| +** The cursor "p" has a pending seek operation that has not yet been
|
| +** carried out. Seek the cursor now. If an error occurs, return
|
| +** the appropriate error code.
|
| +*/
|
| +static int SQLITE_NOINLINE handleDeferredMoveto(VdbeCursor *p){
|
| + int res, rc;
|
| +#ifdef SQLITE_TEST
|
| + extern int sqlite3_search_count;
|
| +#endif
|
| + assert( p->deferredMoveto );
|
| + assert( p->isTable );
|
| + assert( p->eCurType==CURTYPE_BTREE );
|
| + rc = sqlite3BtreeMovetoUnpacked(p->uc.pCursor, 0, p->movetoTarget, 0, &res);
|
| + if( rc ) return rc;
|
| + if( res!=0 ) return SQLITE_CORRUPT_BKPT;
|
| +#ifdef SQLITE_TEST
|
| + sqlite3_search_count++;
|
| +#endif
|
| + p->deferredMoveto = 0;
|
| + p->cacheStatus = CACHE_STALE;
|
| + return SQLITE_OK;
|
| +}
|
| +
|
| +/*
|
| +** Something has moved cursor "p" out of place. Maybe the row it was
|
| +** pointed to was deleted out from under it. Or maybe the btree was
|
| +** rebalanced. Whatever the cause, try to restore "p" to the place it
|
| +** is supposed to be pointing. If the row was deleted out from under the
|
| +** cursor, set the cursor to point to a NULL row.
|
| +*/
|
| +static int SQLITE_NOINLINE handleMovedCursor(VdbeCursor *p){
|
| + int isDifferentRow, rc;
|
| + assert( p->eCurType==CURTYPE_BTREE );
|
| + assert( p->uc.pCursor!=0 );
|
| + assert( sqlite3BtreeCursorHasMoved(p->uc.pCursor) );
|
| + rc = sqlite3BtreeCursorRestore(p->uc.pCursor, &isDifferentRow);
|
| + p->cacheStatus = CACHE_STALE;
|
| + if( isDifferentRow ) p->nullRow = 1;
|
| + return rc;
|
| +}
|
| +
|
| +/*
|
| +** Check to ensure that the cursor is valid. Restore the cursor
|
| +** if need be. Return any I/O error from the restore operation.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3VdbeCursorRestore(VdbeCursor *p){
|
| + assert( p->eCurType==CURTYPE_BTREE );
|
| + if( sqlite3BtreeCursorHasMoved(p->uc.pCursor) ){
|
| + return handleMovedCursor(p);
|
| + }
|
| + return SQLITE_OK;
|
| +}
|
| +
|
| +/*
|
| +** Make sure the cursor p is ready to read or write the row to which it
|
| +** was last positioned. Return an error code if an OOM fault or I/O error
|
| +** prevents us from positioning the cursor to its correct position.
|
| +**
|
| +** If a MoveTo operation is pending on the given cursor, then do that
|
| +** MoveTo now. If no move is pending, check to see if the row has been
|
| +** deleted out from under the cursor and if it has, mark the row as
|
| +** a NULL row.
|
| +**
|
| +** If the cursor is already pointing to the correct row and that row has
|
| +** not been deleted out from under the cursor, then this routine is a no-op.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor *p){
|
| + if( p->eCurType==CURTYPE_BTREE ){
|
| + if( p->deferredMoveto ){
|
| + return handleDeferredMoveto(p);
|
| + }
|
| + if( sqlite3BtreeCursorHasMoved(p->uc.pCursor) ){
|
| + return handleMovedCursor(p);
|
| + }
|
| + }
|
| + return SQLITE_OK;
|
| +}
|
| +
|
| +/*
|
| +** The following functions:
|
| +**
|
| +** sqlite3VdbeSerialType()
|
| +** sqlite3VdbeSerialTypeLen()
|
| +** sqlite3VdbeSerialLen()
|
| +** sqlite3VdbeSerialPut()
|
| +** sqlite3VdbeSerialGet()
|
| +**
|
| +** encapsulate the code that serializes values for storage in SQLite
|
| +** data and index records. Each serialized value consists of a
|
| +** 'serial-type' and a blob of data. The serial type is an 8-byte unsigned
|
| +** integer, stored as a varint.
|
| +**
|
| +** In an SQLite index record, the serial type is stored directly before
|
| +** the blob of data that it corresponds to. In a table record, all serial
|
| +** types are stored at the start of the record, and the blobs of data at
|
| +** the end. Hence these functions allow the caller to handle the
|
| +** serial-type and data blob separately.
|
| +**
|
| +** The following table describes the various storage classes for data:
|
| +**
|
| +** serial type bytes of data type
|
| +** -------------- --------------- ---------------
|
| +** 0 0 NULL
|
| +** 1 1 signed integer
|
| +** 2 2 signed integer
|
| +** 3 3 signed integer
|
| +** 4 4 signed integer
|
| +** 5 6 signed integer
|
| +** 6 8 signed integer
|
| +** 7 8 IEEE float
|
| +** 8 0 Integer constant 0
|
| +** 9 0 Integer constant 1
|
| +** 10,11 reserved for expansion
|
| +** N>=12 and even (N-12)/2 BLOB
|
| +** N>=13 and odd (N-13)/2 text
|
| +**
|
| +** The 8 and 9 types were added in 3.3.0, file format 4. Prior versions
|
| +** of SQLite will not understand those serial types.
|
| +*/
|
| +
|
| +/*
|
| +** Return the serial-type for the value stored in pMem.
|
| +*/
|
| +SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem *pMem, int file_format, u32 *pLen){
|
| + int flags = pMem->flags;
|
| + u32 n;
|
| +
|
| + assert( pLen!=0 );
|
| + if( flags&MEM_Null ){
|
| + *pLen = 0;
|
| + return 0;
|
| + }
|
| + if( flags&MEM_Int ){
|
| + /* Figure out whether to use 1, 2, 4, 6 or 8 bytes. */
|
| +# define MAX_6BYTE ((((i64)0x00008000)<<32)-1)
|
| + i64 i = pMem->u.i;
|
| + u64 u;
|
| + if( i<0 ){
|
| + u = ~i;
|
| + }else{
|
| + u = i;
|
| + }
|
| + if( u<=127 ){
|
| + if( (i&1)==i && file_format>=4 ){
|
| + *pLen = 0;
|
| + return 8+(u32)u;
|
| + }else{
|
| + *pLen = 1;
|
| + return 1;
|
| + }
|
| + }
|
| + if( u<=32767 ){ *pLen = 2; return 2; }
|
| + if( u<=8388607 ){ *pLen = 3; return 3; }
|
| + if( u<=2147483647 ){ *pLen = 4; return 4; }
|
| + if( u<=MAX_6BYTE ){ *pLen = 6; return 5; }
|
| + *pLen = 8;
|
| + return 6;
|
| + }
|
| + if( flags&MEM_Real ){
|
| + *pLen = 8;
|
| + return 7;
|
| + }
|
| + assert( pMem->db->mallocFailed || flags&(MEM_Str|MEM_Blob) );
|
| + assert( pMem->n>=0 );
|
| + n = (u32)pMem->n;
|
| + if( flags & MEM_Zero ){
|
| + n += pMem->u.nZero;
|
| + }
|
| + *pLen = n;
|
| + return ((n*2) + 12 + ((flags&MEM_Str)!=0));
|
| +}
|
| +
|
| +/*
|
| +** The sizes for serial types less than 128
|
| +*/
|
| +static const u8 sqlite3SmallTypeSizes[] = {
|
| + /* 0 1 2 3 4 5 6 7 8 9 */
|
| +/* 0 */ 0, 1, 2, 3, 4, 6, 8, 8, 0, 0,
|
| +/* 10 */ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3,
|
| +/* 20 */ 4, 4, 5, 5, 6, 6, 7, 7, 8, 8,
|
| +/* 30 */ 9, 9, 10, 10, 11, 11, 12, 12, 13, 13,
|
| +/* 40 */ 14, 14, 15, 15, 16, 16, 17, 17, 18, 18,
|
| +/* 50 */ 19, 19, 20, 20, 21, 21, 22, 22, 23, 23,
|
| +/* 60 */ 24, 24, 25, 25, 26, 26, 27, 27, 28, 28,
|
| +/* 70 */ 29, 29, 30, 30, 31, 31, 32, 32, 33, 33,
|
| +/* 80 */ 34, 34, 35, 35, 36, 36, 37, 37, 38, 38,
|
| +/* 90 */ 39, 39, 40, 40, 41, 41, 42, 42, 43, 43,
|
| +/* 100 */ 44, 44, 45, 45, 46, 46, 47, 47, 48, 48,
|
| +/* 110 */ 49, 49, 50, 50, 51, 51, 52, 52, 53, 53,
|
| +/* 120 */ 54, 54, 55, 55, 56, 56, 57, 57
|
| +};
|
| +
|
| +/*
|
| +** Return the length of the data corresponding to the supplied serial-type.
|
| +*/
|
| +SQLITE_PRIVATE u32 sqlite3VdbeSerialTypeLen(u32 serial_type){
|
| + if( serial_type>=128 ){
|
| + return (serial_type-12)/2;
|
| + }else{
|
| + assert( serial_type<12
|
| + || sqlite3SmallTypeSizes[serial_type]==(serial_type - 12)/2 );
|
| + return sqlite3SmallTypeSizes[serial_type];
|
| + }
|
| +}
|
| +SQLITE_PRIVATE u8 sqlite3VdbeOneByteSerialTypeLen(u8 serial_type){
|
| + assert( serial_type<128 );
|
| + return sqlite3SmallTypeSizes[serial_type];
|
| +}
|
| +
|
| +/*
|
| +** If we are on an architecture with mixed-endian floating
|
| +** points (ex: ARM7) then swap the lower 4 bytes with the
|
| +** upper 4 bytes. Return the result.
|
| +**
|
| +** For most architectures, this is a no-op.
|
| +**
|
| +** (later): It is reported to me that the mixed-endian problem
|
| +** on ARM7 is an issue with GCC, not with the ARM7 chip. It seems
|
| +** that early versions of GCC stored the two words of a 64-bit
|
| +** float in the wrong order. And that error has been propagated
|
| +** ever since. The blame is not necessarily with GCC, though.
|
| +** GCC might have just copying the problem from a prior compiler.
|
| +** I am also told that newer versions of GCC that follow a different
|
| +** ABI get the byte order right.
|
| +**
|
| +** Developers using SQLite on an ARM7 should compile and run their
|
| +** application using -DSQLITE_DEBUG=1 at least once. With DEBUG
|
| +** enabled, some asserts below will ensure that the byte order of
|
| +** floating point values is correct.
|
| +**
|
| +** (2007-08-30) Frank van Vugt has studied this problem closely
|
| +** and has send his findings to the SQLite developers. Frank
|
| +** writes that some Linux kernels offer floating point hardware
|
| +** emulation that uses only 32-bit mantissas instead of a full
|
| +** 48-bits as required by the IEEE standard. (This is the
|
| +** CONFIG_FPE_FASTFPE option.) On such systems, floating point
|
| +** byte swapping becomes very complicated. To avoid problems,
|
| +** the necessary byte swapping is carried out using a 64-bit integer
|
| +** rather than a 64-bit float. Frank assures us that the code here
|
| +** works for him. We, the developers, have no way to independently
|
| +** verify this, but Frank seems to know what he is talking about
|
| +** so we trust him.
|
| +*/
|
| +#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT
|
| +static u64 floatSwap(u64 in){
|
| + union {
|
| + u64 r;
|
| + u32 i[2];
|
| + } u;
|
| + u32 t;
|
| +
|
| + u.r = in;
|
| + t = u.i[0];
|
| + u.i[0] = u.i[1];
|
| + u.i[1] = t;
|
| + return u.r;
|
| +}
|
| +# define swapMixedEndianFloat(X) X = floatSwap(X)
|
| +#else
|
| +# define swapMixedEndianFloat(X)
|
| +#endif
|
| +
|
| +/*
|
| +** Write the serialized data blob for the value stored in pMem into
|
| +** buf. It is assumed that the caller has allocated sufficient space.
|
| +** Return the number of bytes written.
|
| +**
|
| +** nBuf is the amount of space left in buf[]. The caller is responsible
|
| +** for allocating enough space to buf[] to hold the entire field, exclusive
|
| +** of the pMem->u.nZero bytes for a MEM_Zero value.
|
| +**
|
| +** Return the number of bytes actually written into buf[]. The number
|
| +** of bytes in the zero-filled tail is included in the return value only
|
| +** if those bytes were zeroed in buf[].
|
| +*/
|
| +SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(u8 *buf, Mem *pMem, u32 serial_type){
|
| + u32 len;
|
| +
|
| + /* Integer and Real */
|
| + if( serial_type<=7 && serial_type>0 ){
|
| + u64 v;
|
| + u32 i;
|
| + if( serial_type==7 ){
|
| + assert( sizeof(v)==sizeof(pMem->u.r) );
|
| + memcpy(&v, &pMem->u.r, sizeof(v));
|
| + swapMixedEndianFloat(v);
|
| + }else{
|
| + v = pMem->u.i;
|
| + }
|
| + len = i = sqlite3SmallTypeSizes[serial_type];
|
| + assert( i>0 );
|
| + do{
|
| + buf[--i] = (u8)(v&0xFF);
|
| + v >>= 8;
|
| + }while( i );
|
| + return len;
|
| + }
|
| +
|
| + /* String or blob */
|
| + if( serial_type>=12 ){
|
| + assert( pMem->n + ((pMem->flags & MEM_Zero)?pMem->u.nZero:0)
|
| + == (int)sqlite3VdbeSerialTypeLen(serial_type) );
|
| + len = pMem->n;
|
| + if( len>0 ) memcpy(buf, pMem->z, len);
|
| + return len;
|
| + }
|
| +
|
| + /* NULL or constants 0 or 1 */
|
| + return 0;
|
| +}
|
| +
|
| +/* Input "x" is a sequence of unsigned characters that represent a
|
| +** big-endian integer. Return the equivalent native integer
|
| +*/
|
| +#define ONE_BYTE_INT(x) ((i8)(x)[0])
|
| +#define TWO_BYTE_INT(x) (256*(i8)((x)[0])|(x)[1])
|
| +#define THREE_BYTE_INT(x) (65536*(i8)((x)[0])|((x)[1]<<8)|(x)[2])
|
| +#define FOUR_BYTE_UINT(x) (((u32)(x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3])
|
| +#define FOUR_BYTE_INT(x) (16777216*(i8)((x)[0])|((x)[1]<<16)|((x)[2]<<8)|(x)[3])
|
| +
|
| +/*
|
| +** Deserialize the data blob pointed to by buf as serial type serial_type
|
| +** and store the result in pMem. Return the number of bytes read.
|
| +**
|
| +** This function is implemented as two separate routines for performance.
|
| +** The few cases that require local variables are broken out into a separate
|
| +** routine so that in most cases the overhead of moving the stack pointer
|
| +** is avoided.
|
| +*/
|
| +static u32 SQLITE_NOINLINE serialGet(
|
| + const unsigned char *buf, /* Buffer to deserialize from */
|
| + u32 serial_type, /* Serial type to deserialize */
|
| + Mem *pMem /* Memory cell to write value into */
|
| +){
|
| + u64 x = FOUR_BYTE_UINT(buf);
|
| + u32 y = FOUR_BYTE_UINT(buf+4);
|
| + x = (x<<32) + y;
|
| + if( serial_type==6 ){
|
| + /* EVIDENCE-OF: R-29851-52272 Value is a big-endian 64-bit
|
| + ** twos-complement integer. */
|
| + pMem->u.i = *(i64*)&x;
|
| + pMem->flags = MEM_Int;
|
| + testcase( pMem->u.i<0 );
|
| + }else{
|
| + /* EVIDENCE-OF: R-57343-49114 Value is a big-endian IEEE 754-2008 64-bit
|
| + ** floating point number. */
|
| +#if !defined(NDEBUG) && !defined(SQLITE_OMIT_FLOATING_POINT)
|
| + /* Verify that integers and floating point values use the same
|
| + ** byte order. Or, that if SQLITE_MIXED_ENDIAN_64BIT_FLOAT is
|
| + ** defined that 64-bit floating point values really are mixed
|
| + ** endian.
|
| + */
|
| + static const u64 t1 = ((u64)0x3ff00000)<<32;
|
| + static const double r1 = 1.0;
|
| + u64 t2 = t1;
|
| + swapMixedEndianFloat(t2);
|
| + assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, &t2, sizeof(r1))==0 );
|
| +#endif
|
| + assert( sizeof(x)==8 && sizeof(pMem->u.r)==8 );
|
| + swapMixedEndianFloat(x);
|
| + memcpy(&pMem->u.r, &x, sizeof(x));
|
| + pMem->flags = sqlite3IsNaN(pMem->u.r) ? MEM_Null : MEM_Real;
|
| + }
|
| + return 8;
|
| +}
|
| +SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(
|
| + const unsigned char *buf, /* Buffer to deserialize from */
|
| + u32 serial_type, /* Serial type to deserialize */
|
| + Mem *pMem /* Memory cell to write value into */
|
| +){
|
| + switch( serial_type ){
|
| + case 10: /* Reserved for future use */
|
| + case 11: /* Reserved for future use */
|
| + case 0: { /* Null */
|
| + /* EVIDENCE-OF: R-24078-09375 Value is a NULL. */
|
| + pMem->flags = MEM_Null;
|
| + break;
|
| + }
|
| + case 1: {
|
| + /* EVIDENCE-OF: R-44885-25196 Value is an 8-bit twos-complement
|
| + ** integer. */
|
| + pMem->u.i = ONE_BYTE_INT(buf);
|
| + pMem->flags = MEM_Int;
|
| + testcase( pMem->u.i<0 );
|
| + return 1;
|
| + }
|
| + case 2: { /* 2-byte signed integer */
|
| + /* EVIDENCE-OF: R-49794-35026 Value is a big-endian 16-bit
|
| + ** twos-complement integer. */
|
| + pMem->u.i = TWO_BYTE_INT(buf);
|
| + pMem->flags = MEM_Int;
|
| + testcase( pMem->u.i<0 );
|
| + return 2;
|
| + }
|
| + case 3: { /* 3-byte signed integer */
|
| + /* EVIDENCE-OF: R-37839-54301 Value is a big-endian 24-bit
|
| + ** twos-complement integer. */
|
| + pMem->u.i = THREE_BYTE_INT(buf);
|
| + pMem->flags = MEM_Int;
|
| + testcase( pMem->u.i<0 );
|
| + return 3;
|
| + }
|
| + case 4: { /* 4-byte signed integer */
|
| + /* EVIDENCE-OF: R-01849-26079 Value is a big-endian 32-bit
|
| + ** twos-complement integer. */
|
| + pMem->u.i = FOUR_BYTE_INT(buf);
|
| +#ifdef __HP_cc
|
| + /* Work around a sign-extension bug in the HP compiler for HP/UX */
|
| + if( buf[0]&0x80 ) pMem->u.i |= 0xffffffff80000000LL;
|
| +#endif
|
| + pMem->flags = MEM_Int;
|
| + testcase( pMem->u.i<0 );
|
| + return 4;
|
| + }
|
| + case 5: { /* 6-byte signed integer */
|
| + /* EVIDENCE-OF: R-50385-09674 Value is a big-endian 48-bit
|
| + ** twos-complement integer. */
|
| + pMem->u.i = FOUR_BYTE_UINT(buf+2) + (((i64)1)<<32)*TWO_BYTE_INT(buf);
|
| + pMem->flags = MEM_Int;
|
| + testcase( pMem->u.i<0 );
|
| + return 6;
|
| + }
|
| + case 6: /* 8-byte signed integer */
|
| + case 7: { /* IEEE floating point */
|
| + /* These use local variables, so do them in a separate routine
|
| + ** to avoid having to move the frame pointer in the common case */
|
| + return serialGet(buf,serial_type,pMem);
|
| + }
|
| + case 8: /* Integer 0 */
|
| + case 9: { /* Integer 1 */
|
| + /* EVIDENCE-OF: R-12976-22893 Value is the integer 0. */
|
| + /* EVIDENCE-OF: R-18143-12121 Value is the integer 1. */
|
| + pMem->u.i = serial_type-8;
|
| + pMem->flags = MEM_Int;
|
| + return 0;
|
| + }
|
| + default: {
|
| + /* EVIDENCE-OF: R-14606-31564 Value is a BLOB that is (N-12)/2 bytes in
|
| + ** length.
|
| + ** EVIDENCE-OF: R-28401-00140 Value is a string in the text encoding and
|
| + ** (N-13)/2 bytes in length. */
|
| + static const u16 aFlag[] = { MEM_Blob|MEM_Ephem, MEM_Str|MEM_Ephem };
|
| + pMem->z = (char *)buf;
|
| + pMem->n = (serial_type-12)/2;
|
| + pMem->flags = aFlag[serial_type&1];
|
| + return pMem->n;
|
| + }
|
| + }
|
| + return 0;
|
| +}
|
| +/*
|
| +** This routine is used to allocate sufficient space for an UnpackedRecord
|
| +** structure large enough to be used with sqlite3VdbeRecordUnpack() if
|
| +** the first argument is a pointer to KeyInfo structure pKeyInfo.
|
| +**
|
| +** The space is either allocated using sqlite3DbMallocRaw() or from within
|
| +** the unaligned buffer passed via the second and third arguments (presumably
|
| +** stack space). If the former, then *ppFree is set to a pointer that should
|
| +** be eventually freed by the caller using sqlite3DbFree(). Or, if the
|
| +** allocation comes from the pSpace/szSpace buffer, *ppFree is set to NULL
|
| +** before returning.
|
| +**
|
| +** If an OOM error occurs, NULL is returned.
|
| +*/
|
| +SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(
|
| + KeyInfo *pKeyInfo, /* Description of the record */
|
| + char *pSpace, /* Unaligned space available */
|
| + int szSpace, /* Size of pSpace[] in bytes */
|
| + char **ppFree /* OUT: Caller should free this pointer */
|
| +){
|
| + UnpackedRecord *p; /* Unpacked record to return */
|
| + int nOff; /* Increment pSpace by nOff to align it */
|
| + int nByte; /* Number of bytes required for *p */
|
| +
|
| + /* We want to shift the pointer pSpace up such that it is 8-byte aligned.
|
| + ** Thus, we need to calculate a value, nOff, between 0 and 7, to shift
|
| + ** it by. If pSpace is already 8-byte aligned, nOff should be zero.
|
| + */
|
| + nOff = (8 - (SQLITE_PTR_TO_INT(pSpace) & 7)) & 7;
|
| + nByte = ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*(pKeyInfo->nField+1);
|
| + if( nByte>szSpace+nOff ){
|
| + p = (UnpackedRecord *)sqlite3DbMallocRaw(pKeyInfo->db, nByte);
|
| + *ppFree = (char *)p;
|
| + if( !p ) return 0;
|
| + }else{
|
| + p = (UnpackedRecord*)&pSpace[nOff];
|
| + *ppFree = 0;
|
| + }
|
| +
|
| + p->aMem = (Mem*)&((char*)p)[ROUND8(sizeof(UnpackedRecord))];
|
| + assert( pKeyInfo->aSortOrder!=0 );
|
| + p->pKeyInfo = pKeyInfo;
|
| + p->nField = pKeyInfo->nField + 1;
|
| + return p;
|
| +}
|
| +
|
| +/*
|
| +** Given the nKey-byte encoding of a record in pKey[], populate the
|
| +** UnpackedRecord structure indicated by the fourth argument with the
|
| +** contents of the decoded record.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(
|
| + KeyInfo *pKeyInfo, /* Information about the record format */
|
| + int nKey, /* Size of the binary record */
|
| + const void *pKey, /* The binary record */
|
| + UnpackedRecord *p /* Populate this structure before returning. */
|
| +){
|
| + const unsigned char *aKey = (const unsigned char *)pKey;
|
| + int d;
|
| + u32 idx; /* Offset in aKey[] to read from */
|
| + u16 u; /* Unsigned loop counter */
|
| + u32 szHdr;
|
| + Mem *pMem = p->aMem;
|
| +
|
| + p->default_rc = 0;
|
| + assert( EIGHT_BYTE_ALIGNMENT(pMem) );
|
| + idx = getVarint32(aKey, szHdr);
|
| + d = szHdr;
|
| + u = 0;
|
| + while( idx<szHdr && d<=nKey ){
|
| + u32 serial_type;
|
| +
|
| + idx += getVarint32(&aKey[idx], serial_type);
|
| + pMem->enc = pKeyInfo->enc;
|
| + pMem->db = pKeyInfo->db;
|
| + /* pMem->flags = 0; // sqlite3VdbeSerialGet() will set this for us */
|
| + pMem->szMalloc = 0;
|
| + d += sqlite3VdbeSerialGet(&aKey[d], serial_type, pMem);
|
| + pMem++;
|
| + if( (++u)>=p->nField ) break;
|
| + }
|
| + assert( u<=pKeyInfo->nField + 1 );
|
| + p->nField = u;
|
| +}
|
| +
|
| +#if SQLITE_DEBUG
|
| +/*
|
| +** This function compares two index or table record keys in the same way
|
| +** as the sqlite3VdbeRecordCompare() routine. Unlike VdbeRecordCompare(),
|
| +** this function deserializes and compares values using the
|
| +** sqlite3VdbeSerialGet() and sqlite3MemCompare() functions. It is used
|
| +** in assert() statements to ensure that the optimized code in
|
| +** sqlite3VdbeRecordCompare() returns results with these two primitives.
|
| +**
|
| +** Return true if the result of comparison is equivalent to desiredResult.
|
| +** Return false if there is a disagreement.
|
| +*/
|
| +static int vdbeRecordCompareDebug(
|
| + int nKey1, const void *pKey1, /* Left key */
|
| + const UnpackedRecord *pPKey2, /* Right key */
|
| + int desiredResult /* Correct answer */
|
| +){
|
| + u32 d1; /* Offset into aKey[] of next data element */
|
| + u32 idx1; /* Offset into aKey[] of next header element */
|
| + u32 szHdr1; /* Number of bytes in header */
|
| + int i = 0;
|
| + int rc = 0;
|
| + const unsigned char *aKey1 = (const unsigned char *)pKey1;
|
| + KeyInfo *pKeyInfo;
|
| + Mem mem1;
|
| +
|
| + pKeyInfo = pPKey2->pKeyInfo;
|
| + if( pKeyInfo->db==0 ) return 1;
|
| + mem1.enc = pKeyInfo->enc;
|
| + mem1.db = pKeyInfo->db;
|
| + /* mem1.flags = 0; // Will be initialized by sqlite3VdbeSerialGet() */
|
| + VVA_ONLY( mem1.szMalloc = 0; ) /* Only needed by assert() statements */
|
| +
|
| + /* Compilers may complain that mem1.u.i is potentially uninitialized.
|
| + ** We could initialize it, as shown here, to silence those complaints.
|
| + ** But in fact, mem1.u.i will never actually be used uninitialized, and doing
|
| + ** the unnecessary initialization has a measurable negative performance
|
| + ** impact, since this routine is a very high runner. And so, we choose
|
| + ** to ignore the compiler warnings and leave this variable uninitialized.
|
| + */
|
| + /* mem1.u.i = 0; // not needed, here to silence compiler warning */
|
| +
|
| + idx1 = getVarint32(aKey1, szHdr1);
|
| + if( szHdr1>98307 ) return SQLITE_CORRUPT;
|
| + d1 = szHdr1;
|
| + assert( pKeyInfo->nField+pKeyInfo->nXField>=pPKey2->nField || CORRUPT_DB );
|
| + assert( pKeyInfo->aSortOrder!=0 );
|
| + assert( pKeyInfo->nField>0 );
|
| + assert( idx1<=szHdr1 || CORRUPT_DB );
|
| + do{
|
| + u32 serial_type1;
|
| +
|
| + /* Read the serial types for the next element in each key. */
|
| + idx1 += getVarint32( aKey1+idx1, serial_type1 );
|
| +
|
| + /* Verify that there is enough key space remaining to avoid
|
| + ** a buffer overread. The "d1+serial_type1+2" subexpression will
|
| + ** always be greater than or equal to the amount of required key space.
|
| + ** Use that approximation to avoid the more expensive call to
|
| + ** sqlite3VdbeSerialTypeLen() in the common case.
|
| + */
|
| + if( d1+serial_type1+2>(u32)nKey1
|
| + && d1+sqlite3VdbeSerialTypeLen(serial_type1)>(u32)nKey1
|
| + ){
|
| + break;
|
| + }
|
| +
|
| + /* Extract the values to be compared.
|
| + */
|
| + d1 += sqlite3VdbeSerialGet(&aKey1[d1], serial_type1, &mem1);
|
| +
|
| + /* Do the comparison
|
| + */
|
| + rc = sqlite3MemCompare(&mem1, &pPKey2->aMem[i], pKeyInfo->aColl[i]);
|
| + if( rc!=0 ){
|
| + assert( mem1.szMalloc==0 ); /* See comment below */
|
| + if( pKeyInfo->aSortOrder[i] ){
|
| + rc = -rc; /* Invert the result for DESC sort order. */
|
| + }
|
| + goto debugCompareEnd;
|
| + }
|
| + i++;
|
| + }while( idx1<szHdr1 && i<pPKey2->nField );
|
| +
|
| + /* No memory allocation is ever used on mem1. Prove this using
|
| + ** the following assert(). If the assert() fails, it indicates a
|
| + ** memory leak and a need to call sqlite3VdbeMemRelease(&mem1).
|
| + */
|
| + assert( mem1.szMalloc==0 );
|
| +
|
| + /* rc==0 here means that one of the keys ran out of fields and
|
| + ** all the fields up to that point were equal. Return the default_rc
|
| + ** value. */
|
| + rc = pPKey2->default_rc;
|
| +
|
| +debugCompareEnd:
|
| + if( desiredResult==0 && rc==0 ) return 1;
|
| + if( desiredResult<0 && rc<0 ) return 1;
|
| + if( desiredResult>0 && rc>0 ) return 1;
|
| + if( CORRUPT_DB ) return 1;
|
| + if( pKeyInfo->db->mallocFailed ) return 1;
|
| + return 0;
|
| +}
|
| +#endif
|
| +
|
| +#if SQLITE_DEBUG
|
| +/*
|
| +** Count the number of fields (a.k.a. columns) in the record given by
|
| +** pKey,nKey. The verify that this count is less than or equal to the
|
| +** limit given by pKeyInfo->nField + pKeyInfo->nXField.
|
| +**
|
| +** If this constraint is not satisfied, it means that the high-speed
|
| +** vdbeRecordCompareInt() and vdbeRecordCompareString() routines will
|
| +** not work correctly. If this assert() ever fires, it probably means
|
| +** that the KeyInfo.nField or KeyInfo.nXField values were computed
|
| +** incorrectly.
|
| +*/
|
| +static void vdbeAssertFieldCountWithinLimits(
|
| + int nKey, const void *pKey, /* The record to verify */
|
| + const KeyInfo *pKeyInfo /* Compare size with this KeyInfo */
|
| +){
|
| + int nField = 0;
|
| + u32 szHdr;
|
| + u32 idx;
|
| + u32 notUsed;
|
| + const unsigned char *aKey = (const unsigned char*)pKey;
|
| +
|
| + if( CORRUPT_DB ) return;
|
| + idx = getVarint32(aKey, szHdr);
|
| + assert( nKey>=0 );
|
| + assert( szHdr<=(u32)nKey );
|
| + while( idx<szHdr ){
|
| + idx += getVarint32(aKey+idx, notUsed);
|
| + nField++;
|
| + }
|
| + assert( nField <= pKeyInfo->nField+pKeyInfo->nXField );
|
| +}
|
| +#else
|
| +# define vdbeAssertFieldCountWithinLimits(A,B,C)
|
| +#endif
|
| +
|
| +/*
|
| +** Both *pMem1 and *pMem2 contain string values. Compare the two values
|
| +** using the collation sequence pColl. As usual, return a negative , zero
|
| +** or positive value if *pMem1 is less than, equal to or greater than
|
| +** *pMem2, respectively. Similar in spirit to "rc = (*pMem1) - (*pMem2);".
|
| +*/
|
| +static int vdbeCompareMemString(
|
| + const Mem *pMem1,
|
| + const Mem *pMem2,
|
| + const CollSeq *pColl,
|
| + u8 *prcErr /* If an OOM occurs, set to SQLITE_NOMEM */
|
| +){
|
| + if( pMem1->enc==pColl->enc ){
|
| + /* The strings are already in the correct encoding. Call the
|
| + ** comparison function directly */
|
| + return pColl->xCmp(pColl->pUser,pMem1->n,pMem1->z,pMem2->n,pMem2->z);
|
| + }else{
|
| + int rc;
|
| + const void *v1, *v2;
|
| + int n1, n2;
|
| + Mem c1;
|
| + Mem c2;
|
| + sqlite3VdbeMemInit(&c1, pMem1->db, MEM_Null);
|
| + sqlite3VdbeMemInit(&c2, pMem1->db, MEM_Null);
|
| + sqlite3VdbeMemShallowCopy(&c1, pMem1, MEM_Ephem);
|
| + sqlite3VdbeMemShallowCopy(&c2, pMem2, MEM_Ephem);
|
| + v1 = sqlite3ValueText((sqlite3_value*)&c1, pColl->enc);
|
| + n1 = v1==0 ? 0 : c1.n;
|
| + v2 = sqlite3ValueText((sqlite3_value*)&c2, pColl->enc);
|
| + n2 = v2==0 ? 0 : c2.n;
|
| + rc = pColl->xCmp(pColl->pUser, n1, v1, n2, v2);
|
| + sqlite3VdbeMemRelease(&c1);
|
| + sqlite3VdbeMemRelease(&c2);
|
| + if( (v1==0 || v2==0) && prcErr ) *prcErr = SQLITE_NOMEM;
|
| + return rc;
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Compare two blobs. Return negative, zero, or positive if the first
|
| +** is less than, equal to, or greater than the second, respectively.
|
| +** If one blob is a prefix of the other, then the shorter is the lessor.
|
| +*/
|
| +static SQLITE_NOINLINE int sqlite3BlobCompare(const Mem *pB1, const Mem *pB2){
|
| + int c = memcmp(pB1->z, pB2->z, pB1->n>pB2->n ? pB2->n : pB1->n);
|
| + if( c ) return c;
|
| + return pB1->n - pB2->n;
|
| +}
|
| +
|
| +/*
|
| +** Do a comparison between a 64-bit signed integer and a 64-bit floating-point
|
| +** number. Return negative, zero, or positive if the first (i64) is less than,
|
| +** equal to, or greater than the second (double).
|
| +*/
|
| +static int sqlite3IntFloatCompare(i64 i, double r){
|
| + if( sizeof(LONGDOUBLE_TYPE)>8 ){
|
| + LONGDOUBLE_TYPE x = (LONGDOUBLE_TYPE)i;
|
| + if( x<r ) return -1;
|
| + if( x>r ) return +1;
|
| + return 0;
|
| + }else{
|
| + i64 y;
|
| + double s;
|
| + if( r<-9223372036854775808.0 ) return +1;
|
| + if( r>9223372036854775807.0 ) return -1;
|
| + y = (i64)r;
|
| + if( i<y ) return -1;
|
| + if( i>y ){
|
| + if( y==SMALLEST_INT64 && r>0.0 ) return -1;
|
| + return +1;
|
| + }
|
| + s = (double)i;
|
| + if( s<r ) return -1;
|
| + if( s>r ) return +1;
|
| + return 0;
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Compare the values contained by the two memory cells, returning
|
| +** negative, zero or positive if pMem1 is less than, equal to, or greater
|
| +** than pMem2. Sorting order is NULL's first, followed by numbers (integers
|
| +** and reals) sorted numerically, followed by text ordered by the collating
|
| +** sequence pColl and finally blob's ordered by memcmp().
|
| +**
|
| +** Two NULL values are considered equal by this function.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){
|
| + int f1, f2;
|
| + int combined_flags;
|
| +
|
| + f1 = pMem1->flags;
|
| + f2 = pMem2->flags;
|
| + combined_flags = f1|f2;
|
| + assert( (combined_flags & MEM_RowSet)==0 );
|
| +
|
| + /* If one value is NULL, it is less than the other. If both values
|
| + ** are NULL, return 0.
|
| + */
|
| + if( combined_flags&MEM_Null ){
|
| + return (f2&MEM_Null) - (f1&MEM_Null);
|
| + }
|
| +
|
| + /* At least one of the two values is a number
|
| + */
|
| + if( combined_flags&(MEM_Int|MEM_Real) ){
|
| + if( (f1 & f2 & MEM_Int)!=0 ){
|
| + if( pMem1->u.i < pMem2->u.i ) return -1;
|
| + if( pMem1->u.i > pMem2->u.i ) return +1;
|
| + return 0;
|
| + }
|
| + if( (f1 & f2 & MEM_Real)!=0 ){
|
| + if( pMem1->u.r < pMem2->u.r ) return -1;
|
| + if( pMem1->u.r > pMem2->u.r ) return +1;
|
| + return 0;
|
| + }
|
| + if( (f1&MEM_Int)!=0 ){
|
| + if( (f2&MEM_Real)!=0 ){
|
| + return sqlite3IntFloatCompare(pMem1->u.i, pMem2->u.r);
|
| + }else{
|
| + return -1;
|
| + }
|
| + }
|
| + if( (f1&MEM_Real)!=0 ){
|
| + if( (f2&MEM_Int)!=0 ){
|
| + return -sqlite3IntFloatCompare(pMem2->u.i, pMem1->u.r);
|
| + }else{
|
| + return -1;
|
| + }
|
| + }
|
| + return +1;
|
| + }
|
| +
|
| + /* If one value is a string and the other is a blob, the string is less.
|
| + ** If both are strings, compare using the collating functions.
|
| + */
|
| + if( combined_flags&MEM_Str ){
|
| + if( (f1 & MEM_Str)==0 ){
|
| + return 1;
|
| + }
|
| + if( (f2 & MEM_Str)==0 ){
|
| + return -1;
|
| + }
|
| +
|
| + assert( pMem1->enc==pMem2->enc || pMem1->db->mallocFailed );
|
| + assert( pMem1->enc==SQLITE_UTF8 ||
|
| + pMem1->enc==SQLITE_UTF16LE || pMem1->enc==SQLITE_UTF16BE );
|
| +
|
| + /* The collation sequence must be defined at this point, even if
|
| + ** the user deletes the collation sequence after the vdbe program is
|
| + ** compiled (this was not always the case).
|
| + */
|
| + assert( !pColl || pColl->xCmp );
|
| +
|
| + if( pColl ){
|
| + return vdbeCompareMemString(pMem1, pMem2, pColl, 0);
|
| + }
|
| + /* If a NULL pointer was passed as the collate function, fall through
|
| + ** to the blob case and use memcmp(). */
|
| + }
|
| +
|
| + /* Both values must be blobs. Compare using memcmp(). */
|
| + return sqlite3BlobCompare(pMem1, pMem2);
|
| +}
|
| +
|
| +
|
| +/*
|
| +** The first argument passed to this function is a serial-type that
|
| +** corresponds to an integer - all values between 1 and 9 inclusive
|
| +** except 7. The second points to a buffer containing an integer value
|
| +** serialized according to serial_type. This function deserializes
|
| +** and returns the value.
|
| +*/
|
| +static i64 vdbeRecordDecodeInt(u32 serial_type, const u8 *aKey){
|
| + u32 y;
|
| + assert( CORRUPT_DB || (serial_type>=1 && serial_type<=9 && serial_type!=7) );
|
| + switch( serial_type ){
|
| + case 0:
|
| + case 1:
|
| + testcase( aKey[0]&0x80 );
|
| + return ONE_BYTE_INT(aKey);
|
| + case 2:
|
| + testcase( aKey[0]&0x80 );
|
| + return TWO_BYTE_INT(aKey);
|
| + case 3:
|
| + testcase( aKey[0]&0x80 );
|
| + return THREE_BYTE_INT(aKey);
|
| + case 4: {
|
| + testcase( aKey[0]&0x80 );
|
| + y = FOUR_BYTE_UINT(aKey);
|
| + return (i64)*(int*)&y;
|
| + }
|
| + case 5: {
|
| + testcase( aKey[0]&0x80 );
|
| + return FOUR_BYTE_UINT(aKey+2) + (((i64)1)<<32)*TWO_BYTE_INT(aKey);
|
| + }
|
| + case 6: {
|
| + u64 x = FOUR_BYTE_UINT(aKey);
|
| + testcase( aKey[0]&0x80 );
|
| + x = (x<<32) | FOUR_BYTE_UINT(aKey+4);
|
| + return (i64)*(i64*)&x;
|
| + }
|
| + }
|
| +
|
| + return (serial_type - 8);
|
| +}
|
| +
|
| +/*
|
| +** This function compares the two table rows or index records
|
| +** specified by {nKey1, pKey1} and pPKey2. It returns a negative, zero
|
| +** or positive integer if key1 is less than, equal to or
|
| +** greater than key2. The {nKey1, pKey1} key must be a blob
|
| +** created by the OP_MakeRecord opcode of the VDBE. The pPKey2
|
| +** key must be a parsed key such as obtained from
|
| +** sqlite3VdbeParseRecord.
|
| +**
|
| +** If argument bSkip is non-zero, it is assumed that the caller has already
|
| +** determined that the first fields of the keys are equal.
|
| +**
|
| +** Key1 and Key2 do not have to contain the same number of fields. If all
|
| +** fields that appear in both keys are equal, then pPKey2->default_rc is
|
| +** returned.
|
| +**
|
| +** If database corruption is discovered, set pPKey2->errCode to
|
| +** SQLITE_CORRUPT and return 0. If an OOM error is encountered,
|
| +** pPKey2->errCode is set to SQLITE_NOMEM and, if it is not NULL, the
|
| +** malloc-failed flag set on database handle (pPKey2->pKeyInfo->db).
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(
|
| + int nKey1, const void *pKey1, /* Left key */
|
| + UnpackedRecord *pPKey2, /* Right key */
|
| + int bSkip /* If true, skip the first field */
|
| +){
|
| + u32 d1; /* Offset into aKey[] of next data element */
|
| + int i; /* Index of next field to compare */
|
| + u32 szHdr1; /* Size of record header in bytes */
|
| + u32 idx1; /* Offset of first type in header */
|
| + int rc = 0; /* Return value */
|
| + Mem *pRhs = pPKey2->aMem; /* Next field of pPKey2 to compare */
|
| + KeyInfo *pKeyInfo = pPKey2->pKeyInfo;
|
| + const unsigned char *aKey1 = (const unsigned char *)pKey1;
|
| + Mem mem1;
|
| +
|
| + /* If bSkip is true, then the caller has already determined that the first
|
| + ** two elements in the keys are equal. Fix the various stack variables so
|
| + ** that this routine begins comparing at the second field. */
|
| + if( bSkip ){
|
| + u32 s1;
|
| + idx1 = 1 + getVarint32(&aKey1[1], s1);
|
| + szHdr1 = aKey1[0];
|
| + d1 = szHdr1 + sqlite3VdbeSerialTypeLen(s1);
|
| + i = 1;
|
| + pRhs++;
|
| + }else{
|
| + idx1 = getVarint32(aKey1, szHdr1);
|
| + d1 = szHdr1;
|
| + if( d1>(unsigned)nKey1 ){
|
| + pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT;
|
| + return 0; /* Corruption */
|
| + }
|
| + i = 0;
|
| + }
|
| +
|
| + VVA_ONLY( mem1.szMalloc = 0; ) /* Only needed by assert() statements */
|
| + assert( pPKey2->pKeyInfo->nField+pPKey2->pKeyInfo->nXField>=pPKey2->nField
|
| + || CORRUPT_DB );
|
| + assert( pPKey2->pKeyInfo->aSortOrder!=0 );
|
| + assert( pPKey2->pKeyInfo->nField>0 );
|
| + assert( idx1<=szHdr1 || CORRUPT_DB );
|
| + do{
|
| + u32 serial_type;
|
| +
|
| + /* RHS is an integer */
|
| + if( pRhs->flags & MEM_Int ){
|
| + serial_type = aKey1[idx1];
|
| + testcase( serial_type==12 );
|
| + if( serial_type>=10 ){
|
| + rc = +1;
|
| + }else if( serial_type==0 ){
|
| + rc = -1;
|
| + }else if( serial_type==7 ){
|
| + sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1);
|
| + rc = -sqlite3IntFloatCompare(pRhs->u.i, mem1.u.r);
|
| + }else{
|
| + i64 lhs = vdbeRecordDecodeInt(serial_type, &aKey1[d1]);
|
| + i64 rhs = pRhs->u.i;
|
| + if( lhs<rhs ){
|
| + rc = -1;
|
| + }else if( lhs>rhs ){
|
| + rc = +1;
|
| + }
|
| + }
|
| + }
|
| +
|
| + /* RHS is real */
|
| + else if( pRhs->flags & MEM_Real ){
|
| + serial_type = aKey1[idx1];
|
| + if( serial_type>=10 ){
|
| + /* Serial types 12 or greater are strings and blobs (greater than
|
| + ** numbers). Types 10 and 11 are currently "reserved for future
|
| + ** use", so it doesn't really matter what the results of comparing
|
| + ** them to numberic values are. */
|
| + rc = +1;
|
| + }else if( serial_type==0 ){
|
| + rc = -1;
|
| + }else{
|
| + sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1);
|
| + if( serial_type==7 ){
|
| + if( mem1.u.r<pRhs->u.r ){
|
| + rc = -1;
|
| + }else if( mem1.u.r>pRhs->u.r ){
|
| + rc = +1;
|
| + }
|
| + }else{
|
| + rc = sqlite3IntFloatCompare(mem1.u.i, pRhs->u.r);
|
| + }
|
| + }
|
| + }
|
| +
|
| + /* RHS is a string */
|
| + else if( pRhs->flags & MEM_Str ){
|
| + getVarint32(&aKey1[idx1], serial_type);
|
| + testcase( serial_type==12 );
|
| + if( serial_type<12 ){
|
| + rc = -1;
|
| + }else if( !(serial_type & 0x01) ){
|
| + rc = +1;
|
| + }else{
|
| + mem1.n = (serial_type - 12) / 2;
|
| + testcase( (d1+mem1.n)==(unsigned)nKey1 );
|
| + testcase( (d1+mem1.n+1)==(unsigned)nKey1 );
|
| + if( (d1+mem1.n) > (unsigned)nKey1 ){
|
| + pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT;
|
| + return 0; /* Corruption */
|
| + }else if( pKeyInfo->aColl[i] ){
|
| + mem1.enc = pKeyInfo->enc;
|
| + mem1.db = pKeyInfo->db;
|
| + mem1.flags = MEM_Str;
|
| + mem1.z = (char*)&aKey1[d1];
|
| + rc = vdbeCompareMemString(
|
| + &mem1, pRhs, pKeyInfo->aColl[i], &pPKey2->errCode
|
| + );
|
| + }else{
|
| + int nCmp = MIN(mem1.n, pRhs->n);
|
| + rc = memcmp(&aKey1[d1], pRhs->z, nCmp);
|
| + if( rc==0 ) rc = mem1.n - pRhs->n;
|
| + }
|
| + }
|
| + }
|
| +
|
| + /* RHS is a blob */
|
| + else if( pRhs->flags & MEM_Blob ){
|
| + getVarint32(&aKey1[idx1], serial_type);
|
| + testcase( serial_type==12 );
|
| + if( serial_type<12 || (serial_type & 0x01) ){
|
| + rc = -1;
|
| + }else{
|
| + int nStr = (serial_type - 12) / 2;
|
| + testcase( (d1+nStr)==(unsigned)nKey1 );
|
| + testcase( (d1+nStr+1)==(unsigned)nKey1 );
|
| + if( (d1+nStr) > (unsigned)nKey1 ){
|
| + pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT;
|
| + return 0; /* Corruption */
|
| + }else{
|
| + int nCmp = MIN(nStr, pRhs->n);
|
| + rc = memcmp(&aKey1[d1], pRhs->z, nCmp);
|
| + if( rc==0 ) rc = nStr - pRhs->n;
|
| + }
|
| + }
|
| + }
|
| +
|
| + /* RHS is null */
|
| + else{
|
| + serial_type = aKey1[idx1];
|
| + rc = (serial_type!=0);
|
| + }
|
| +
|
| + if( rc!=0 ){
|
| + if( pKeyInfo->aSortOrder[i] ){
|
| + rc = -rc;
|
| + }
|
| + assert( vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, rc) );
|
| + assert( mem1.szMalloc==0 ); /* See comment below */
|
| + return rc;
|
| + }
|
| +
|
| + i++;
|
| + pRhs++;
|
| + d1 += sqlite3VdbeSerialTypeLen(serial_type);
|
| + idx1 += sqlite3VarintLen(serial_type);
|
| + }while( idx1<(unsigned)szHdr1 && i<pPKey2->nField && d1<=(unsigned)nKey1 );
|
| +
|
| + /* No memory allocation is ever used on mem1. Prove this using
|
| + ** the following assert(). If the assert() fails, it indicates a
|
| + ** memory leak and a need to call sqlite3VdbeMemRelease(&mem1). */
|
| + assert( mem1.szMalloc==0 );
|
| +
|
| + /* rc==0 here means that one or both of the keys ran out of fields and
|
| + ** all the fields up to that point were equal. Return the default_rc
|
| + ** value. */
|
| + assert( CORRUPT_DB
|
| + || vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, pPKey2->default_rc)
|
| + || pKeyInfo->db->mallocFailed
|
| + );
|
| + pPKey2->eqSeen = 1;
|
| + return pPKey2->default_rc;
|
| +}
|
| +SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
|
| + int nKey1, const void *pKey1, /* Left key */
|
| + UnpackedRecord *pPKey2 /* Right key */
|
| +){
|
| + return sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 0);
|
| +}
|
| +
|
| +
|
| +/*
|
| +** This function is an optimized version of sqlite3VdbeRecordCompare()
|
| +** that (a) the first field of pPKey2 is an integer, and (b) the
|
| +** size-of-header varint at the start of (pKey1/nKey1) fits in a single
|
| +** byte (i.e. is less than 128).
|
| +**
|
| +** To avoid concerns about buffer overreads, this routine is only used
|
| +** on schemas where the maximum valid header size is 63 bytes or less.
|
| +*/
|
| +static int vdbeRecordCompareInt(
|
| + int nKey1, const void *pKey1, /* Left key */
|
| + UnpackedRecord *pPKey2 /* Right key */
|
| +){
|
| + const u8 *aKey = &((const u8*)pKey1)[*(const u8*)pKey1 & 0x3F];
|
| + int serial_type = ((const u8*)pKey1)[1];
|
| + int res;
|
| + u32 y;
|
| + u64 x;
|
| + i64 v = pPKey2->aMem[0].u.i;
|
| + i64 lhs;
|
| +
|
| + vdbeAssertFieldCountWithinLimits(nKey1, pKey1, pPKey2->pKeyInfo);
|
| + assert( (*(u8*)pKey1)<=0x3F || CORRUPT_DB );
|
| + switch( serial_type ){
|
| + case 1: { /* 1-byte signed integer */
|
| + lhs = ONE_BYTE_INT(aKey);
|
| + testcase( lhs<0 );
|
| + break;
|
| + }
|
| + case 2: { /* 2-byte signed integer */
|
| + lhs = TWO_BYTE_INT(aKey);
|
| + testcase( lhs<0 );
|
| + break;
|
| + }
|
| + case 3: { /* 3-byte signed integer */
|
| + lhs = THREE_BYTE_INT(aKey);
|
| + testcase( lhs<0 );
|
| + break;
|
| + }
|
| + case 4: { /* 4-byte signed integer */
|
| + y = FOUR_BYTE_UINT(aKey);
|
| + lhs = (i64)*(int*)&y;
|
| + testcase( lhs<0 );
|
| + break;
|
| + }
|
| + case 5: { /* 6-byte signed integer */
|
| + lhs = FOUR_BYTE_UINT(aKey+2) + (((i64)1)<<32)*TWO_BYTE_INT(aKey);
|
| + testcase( lhs<0 );
|
| + break;
|
| + }
|
| + case 6: { /* 8-byte signed integer */
|
| + x = FOUR_BYTE_UINT(aKey);
|
| + x = (x<<32) | FOUR_BYTE_UINT(aKey+4);
|
| + lhs = *(i64*)&x;
|
| + testcase( lhs<0 );
|
| + break;
|
| + }
|
| + case 8:
|
| + lhs = 0;
|
| + break;
|
| + case 9:
|
| + lhs = 1;
|
| + break;
|
| +
|
| + /* This case could be removed without changing the results of running
|
| + ** this code. Including it causes gcc to generate a faster switch
|
| + ** statement (since the range of switch targets now starts at zero and
|
| + ** is contiguous) but does not cause any duplicate code to be generated
|
| + ** (as gcc is clever enough to combine the two like cases). Other
|
| + ** compilers might be similar. */
|
| + case 0: case 7:
|
| + return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2);
|
| +
|
| + default:
|
| + return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2);
|
| + }
|
| +
|
| + if( v>lhs ){
|
| + res = pPKey2->r1;
|
| + }else if( v<lhs ){
|
| + res = pPKey2->r2;
|
| + }else if( pPKey2->nField>1 ){
|
| + /* The first fields of the two keys are equal. Compare the trailing
|
| + ** fields. */
|
| + res = sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1);
|
| + }else{
|
| + /* The first fields of the two keys are equal and there are no trailing
|
| + ** fields. Return pPKey2->default_rc in this case. */
|
| + res = pPKey2->default_rc;
|
| + pPKey2->eqSeen = 1;
|
| + }
|
| +
|
| + assert( vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, res) );
|
| + return res;
|
| +}
|
| +
|
| +/*
|
| +** This function is an optimized version of sqlite3VdbeRecordCompare()
|
| +** that (a) the first field of pPKey2 is a string, that (b) the first field
|
| +** uses the collation sequence BINARY and (c) that the size-of-header varint
|
| +** at the start of (pKey1/nKey1) fits in a single byte.
|
| +*/
|
| +static int vdbeRecordCompareString(
|
| + int nKey1, const void *pKey1, /* Left key */
|
| + UnpackedRecord *pPKey2 /* Right key */
|
| +){
|
| + const u8 *aKey1 = (const u8*)pKey1;
|
| + int serial_type;
|
| + int res;
|
| +
|
| + assert( pPKey2->aMem[0].flags & MEM_Str );
|
| + vdbeAssertFieldCountWithinLimits(nKey1, pKey1, pPKey2->pKeyInfo);
|
| + getVarint32(&aKey1[1], serial_type);
|
| + if( serial_type<12 ){
|
| + res = pPKey2->r1; /* (pKey1/nKey1) is a number or a null */
|
| + }else if( !(serial_type & 0x01) ){
|
| + res = pPKey2->r2; /* (pKey1/nKey1) is a blob */
|
| + }else{
|
| + int nCmp;
|
| + int nStr;
|
| + int szHdr = aKey1[0];
|
| +
|
| + nStr = (serial_type-12) / 2;
|
| + if( (szHdr + nStr) > nKey1 ){
|
| + pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT;
|
| + return 0; /* Corruption */
|
| + }
|
| + nCmp = MIN( pPKey2->aMem[0].n, nStr );
|
| + res = memcmp(&aKey1[szHdr], pPKey2->aMem[0].z, nCmp);
|
| +
|
| + if( res==0 ){
|
| + res = nStr - pPKey2->aMem[0].n;
|
| + if( res==0 ){
|
| + if( pPKey2->nField>1 ){
|
| + res = sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1);
|
| + }else{
|
| + res = pPKey2->default_rc;
|
| + pPKey2->eqSeen = 1;
|
| + }
|
| + }else if( res>0 ){
|
| + res = pPKey2->r2;
|
| + }else{
|
| + res = pPKey2->r1;
|
| + }
|
| + }else if( res>0 ){
|
| + res = pPKey2->r2;
|
| + }else{
|
| + res = pPKey2->r1;
|
| + }
|
| + }
|
| +
|
| + assert( vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, res)
|
| + || CORRUPT_DB
|
| + || pPKey2->pKeyInfo->db->mallocFailed
|
| + );
|
| + return res;
|
| +}
|
| +
|
| +/*
|
| +** Return a pointer to an sqlite3VdbeRecordCompare() compatible function
|
| +** suitable for comparing serialized records to the unpacked record passed
|
| +** as the only argument.
|
| +*/
|
| +SQLITE_PRIVATE RecordCompare sqlite3VdbeFindCompare(UnpackedRecord *p){
|
| + /* varintRecordCompareInt() and varintRecordCompareString() both assume
|
| + ** that the size-of-header varint that occurs at the start of each record
|
| + ** fits in a single byte (i.e. is 127 or less). varintRecordCompareInt()
|
| + ** also assumes that it is safe to overread a buffer by at least the
|
| + ** maximum possible legal header size plus 8 bytes. Because there is
|
| + ** guaranteed to be at least 74 (but not 136) bytes of padding following each
|
| + ** buffer passed to varintRecordCompareInt() this makes it convenient to
|
| + ** limit the size of the header to 64 bytes in cases where the first field
|
| + ** is an integer.
|
| + **
|
| + ** The easiest way to enforce this limit is to consider only records with
|
| + ** 13 fields or less. If the first field is an integer, the maximum legal
|
| + ** header size is (12*5 + 1 + 1) bytes. */
|
| + if( (p->pKeyInfo->nField + p->pKeyInfo->nXField)<=13 ){
|
| + int flags = p->aMem[0].flags;
|
| + if( p->pKeyInfo->aSortOrder[0] ){
|
| + p->r1 = 1;
|
| + p->r2 = -1;
|
| + }else{
|
| + p->r1 = -1;
|
| + p->r2 = 1;
|
| + }
|
| + if( (flags & MEM_Int) ){
|
| + return vdbeRecordCompareInt;
|
| + }
|
| + testcase( flags & MEM_Real );
|
| + testcase( flags & MEM_Null );
|
| + testcase( flags & MEM_Blob );
|
| + if( (flags & (MEM_Real|MEM_Null|MEM_Blob))==0 && p->pKeyInfo->aColl[0]==0 ){
|
| + assert( flags & MEM_Str );
|
| + return vdbeRecordCompareString;
|
| + }
|
| + }
|
| +
|
| + return sqlite3VdbeRecordCompare;
|
| +}
|
| +
|
| +/*
|
| +** pCur points at an index entry created using the OP_MakeRecord opcode.
|
| +** Read the rowid (the last field in the record) and store it in *rowid.
|
| +** Return SQLITE_OK if everything works, or an error code otherwise.
|
| +**
|
| +** pCur might be pointing to text obtained from a corrupt database file.
|
| +** So the content cannot be trusted. Do appropriate checks on the content.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3 *db, BtCursor *pCur, i64 *rowid){
|
| + i64 nCellKey = 0;
|
| + int rc;
|
| + u32 szHdr; /* Size of the header */
|
| + u32 typeRowid; /* Serial type of the rowid */
|
| + u32 lenRowid; /* Size of the rowid */
|
| + Mem m, v;
|
| +
|
| + /* Get the size of the index entry. Only indices entries of less
|
| + ** than 2GiB are support - anything large must be database corruption.
|
| + ** Any corruption is detected in sqlite3BtreeParseCellPtr(), though, so
|
| + ** this code can safely assume that nCellKey is 32-bits
|
| + */
|
| + assert( sqlite3BtreeCursorIsValid(pCur) );
|
| + VVA_ONLY(rc =) sqlite3BtreeKeySize(pCur, &nCellKey);
|
| + assert( rc==SQLITE_OK ); /* pCur is always valid so KeySize cannot fail */
|
| + assert( (nCellKey & SQLITE_MAX_U32)==(u64)nCellKey );
|
| +
|
| + /* Read in the complete content of the index entry */
|
| + sqlite3VdbeMemInit(&m, db, 0);
|
| + rc = sqlite3VdbeMemFromBtree(pCur, 0, (u32)nCellKey, 1, &m);
|
| + if( rc ){
|
| + return rc;
|
| + }
|
| +
|
| + /* The index entry must begin with a header size */
|
| + (void)getVarint32((u8*)m.z, szHdr);
|
| + testcase( szHdr==3 );
|
| + testcase( szHdr==m.n );
|
| + if( unlikely(szHdr<3 || (int)szHdr>m.n) ){
|
| + goto idx_rowid_corruption;
|
| + }
|
| +
|
| + /* The last field of the index should be an integer - the ROWID.
|
| + ** Verify that the last entry really is an integer. */
|
| + (void)getVarint32((u8*)&m.z[szHdr-1], typeRowid);
|
| + testcase( typeRowid==1 );
|
| + testcase( typeRowid==2 );
|
| + testcase( typeRowid==3 );
|
| + testcase( typeRowid==4 );
|
| + testcase( typeRowid==5 );
|
| + testcase( typeRowid==6 );
|
| + testcase( typeRowid==8 );
|
| + testcase( typeRowid==9 );
|
| + if( unlikely(typeRowid<1 || typeRowid>9 || typeRowid==7) ){
|
| + goto idx_rowid_corruption;
|
| + }
|
| + lenRowid = sqlite3SmallTypeSizes[typeRowid];
|
| + testcase( (u32)m.n==szHdr+lenRowid );
|
| + if( unlikely((u32)m.n<szHdr+lenRowid) ){
|
| + goto idx_rowid_corruption;
|
| + }
|
| +
|
| + /* Fetch the integer off the end of the index record */
|
| + sqlite3VdbeSerialGet((u8*)&m.z[m.n-lenRowid], typeRowid, &v);
|
| + *rowid = v.u.i;
|
| + sqlite3VdbeMemRelease(&m);
|
| + return SQLITE_OK;
|
| +
|
| + /* Jump here if database corruption is detected after m has been
|
| + ** allocated. Free the m object and return SQLITE_CORRUPT. */
|
| +idx_rowid_corruption:
|
| + testcase( m.szMalloc!=0 );
|
| + sqlite3VdbeMemRelease(&m);
|
| + return SQLITE_CORRUPT_BKPT;
|
| +}
|
| +
|
| +/*
|
| +** Compare the key of the index entry that cursor pC is pointing to against
|
| +** the key string in pUnpacked. Write into *pRes a number
|
| +** that is negative, zero, or positive if pC is less than, equal to,
|
| +** or greater than pUnpacked. Return SQLITE_OK on success.
|
| +**
|
| +** pUnpacked is either created without a rowid or is truncated so that it
|
| +** omits the rowid at the end. The rowid at the end of the index entry
|
| +** is ignored as well. Hence, this routine only compares the prefixes
|
| +** of the keys prior to the final rowid, not the entire key.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(
|
| + sqlite3 *db, /* Database connection */
|
| + VdbeCursor *pC, /* The cursor to compare against */
|
| + UnpackedRecord *pUnpacked, /* Unpacked version of key */
|
| + int *res /* Write the comparison result here */
|
| +){
|
| + i64 nCellKey = 0;
|
| + int rc;
|
| + BtCursor *pCur;
|
| + Mem m;
|
| +
|
| + assert( pC->eCurType==CURTYPE_BTREE );
|
| + pCur = pC->uc.pCursor;
|
| + assert( sqlite3BtreeCursorIsValid(pCur) );
|
| + VVA_ONLY(rc =) sqlite3BtreeKeySize(pCur, &nCellKey);
|
| + assert( rc==SQLITE_OK ); /* pCur is always valid so KeySize cannot fail */
|
| + /* nCellKey will always be between 0 and 0xffffffff because of the way
|
| + ** that btreeParseCellPtr() and sqlite3GetVarint32() are implemented */
|
| + if( nCellKey<=0 || nCellKey>0x7fffffff ){
|
| + *res = 0;
|
| + return SQLITE_CORRUPT_BKPT;
|
| + }
|
| + sqlite3VdbeMemInit(&m, db, 0);
|
| + rc = sqlite3VdbeMemFromBtree(pCur, 0, (u32)nCellKey, 1, &m);
|
| + if( rc ){
|
| + return rc;
|
| + }
|
| + *res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked);
|
| + sqlite3VdbeMemRelease(&m);
|
| + return SQLITE_OK;
|
| +}
|
| +
|
| +/*
|
| +** This routine sets the value to be returned by subsequent calls to
|
| +** sqlite3_changes() on the database handle 'db'.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *db, int nChange){
|
| + assert( sqlite3_mutex_held(db->mutex) );
|
| + db->nChange = nChange;
|
| + db->nTotalChange += nChange;
|
| +}
|
| +
|
| +/*
|
| +** Set a flag in the vdbe to update the change counter when it is finalised
|
| +** or reset.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbeCountChanges(Vdbe *v){
|
| + v->changeCntOn = 1;
|
| +}
|
| +
|
| +/*
|
| +** Mark every prepared statement associated with a database connection
|
| +** as expired.
|
| +**
|
| +** An expired statement means that recompilation of the statement is
|
| +** recommend. Statements expire when things happen that make their
|
| +** programs obsolete. Removing user-defined functions or collating
|
| +** sequences, or changing an authorization function are the types of
|
| +** things that make prepared statements obsolete.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3 *db){
|
| + Vdbe *p;
|
| + for(p = db->pVdbe; p; p=p->pNext){
|
| + p->expired = 1;
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Return the database associated with the Vdbe.
|
| +*/
|
| +SQLITE_PRIVATE sqlite3 *sqlite3VdbeDb(Vdbe *v){
|
| + return v->db;
|
| +}
|
| +
|
| +/*
|
| +** Return a pointer to an sqlite3_value structure containing the value bound
|
| +** parameter iVar of VM v. Except, if the value is an SQL NULL, return
|
| +** 0 instead. Unless it is NULL, apply affinity aff (one of the SQLITE_AFF_*
|
| +** constants) to the value before returning it.
|
| +**
|
| +** The returned value must be freed by the caller using sqlite3ValueFree().
|
| +*/
|
| +SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe *v, int iVar, u8 aff){
|
| + assert( iVar>0 );
|
| + if( v ){
|
| + Mem *pMem = &v->aVar[iVar-1];
|
| + if( 0==(pMem->flags & MEM_Null) ){
|
| + sqlite3_value *pRet = sqlite3ValueNew(v->db);
|
| + if( pRet ){
|
| + sqlite3VdbeMemCopy((Mem *)pRet, pMem);
|
| + sqlite3ValueApplyAffinity(pRet, aff, SQLITE_UTF8);
|
| + }
|
| + return pRet;
|
| + }
|
| + }
|
| + return 0;
|
| +}
|
| +
|
| +/*
|
| +** Configure SQL variable iVar so that binding a new value to it signals
|
| +** to sqlite3_reoptimize() that re-preparing the statement may result
|
| +** in a better query plan.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe *v, int iVar){
|
| + assert( iVar>0 );
|
| + if( iVar>32 ){
|
| + v->expmask = 0xffffffff;
|
| + }else{
|
| + v->expmask |= ((u32)1 << (iVar-1));
|
| + }
|
| +}
|
| +
|
| +#ifndef SQLITE_OMIT_VIRTUALTABLE
|
| +/*
|
| +** Transfer error message text from an sqlite3_vtab.zErrMsg (text stored
|
| +** in memory obtained from sqlite3_malloc) into a Vdbe.zErrMsg (text stored
|
| +** in memory obtained from sqlite3DbMalloc).
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VtabImportErrmsg(Vdbe *p, sqlite3_vtab *pVtab){
|
| + sqlite3 *db = p->db;
|
| + sqlite3DbFree(db, p->zErrMsg);
|
| + p->zErrMsg = sqlite3DbStrDup(db, pVtab->zErrMsg);
|
| + sqlite3_free(pVtab->zErrMsg);
|
| + pVtab->zErrMsg = 0;
|
| +}
|
| +#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
| +
|
| +/************** End of vdbeaux.c *********************************************/
|
| +/************** Begin file vdbeapi.c *****************************************/
|
| +/*
|
| +** 2004 May 26
|
| +**
|
| +** 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.
|
| +**
|
| +*************************************************************************
|
| +**
|
| +** This file contains code use to implement APIs that are part of the
|
| +** VDBE.
|
| +*/
|
| +/* #include "sqliteInt.h" */
|
| +/* #include "vdbeInt.h" */
|
| +
|
| +#ifndef SQLITE_OMIT_DEPRECATED
|
| +/*
|
| +** Return TRUE (non-zero) of the statement supplied as an argument needs
|
| +** to be recompiled. A statement needs to be recompiled whenever the
|
| +** execution environment changes in a way that would alter the program
|
| +** that sqlite3_prepare() generates. For example, if new functions or
|
| +** collating sequences are registered or if an authorizer function is
|
| +** added or changed.
|
| +*/
|
| +SQLITE_API int SQLITE_STDCALL sqlite3_expired(sqlite3_stmt *pStmt){
|
| + Vdbe *p = (Vdbe*)pStmt;
|
| + return p==0 || p->expired;
|
| +}
|
| +#endif
|
| +
|
| +/*
|
| +** Check on a Vdbe to make sure it has not been finalized. Log
|
| +** an error and return true if it has been finalized (or is otherwise
|
| +** invalid). Return false if it is ok.
|
| +*/
|
| +static int vdbeSafety(Vdbe *p){
|
| + if( p->db==0 ){
|
| + sqlite3_log(SQLITE_MISUSE, "API called with finalized prepared statement");
|
| + return 1;
|
| + }else{
|
| + return 0;
|
| + }
|
| +}
|
| +static int vdbeSafetyNotNull(Vdbe *p){
|
| + if( p==0 ){
|
| + sqlite3_log(SQLITE_MISUSE, "API called with NULL prepared statement");
|
| + return 1;
|
| + }else{
|
| + return vdbeSafety(p);
|
| + }
|
| +}
|
| +
|
| +#ifndef SQLITE_OMIT_TRACE
|
| +/*
|
| +** Invoke the profile callback. This routine is only called if we already
|
| +** know that the profile callback is defined and needs to be invoked.
|
| +*/
|
| +static SQLITE_NOINLINE void invokeProfileCallback(sqlite3 *db, Vdbe *p){
|
| + sqlite3_int64 iNow;
|
| + assert( p->startTime>0 );
|
| + assert( db->xProfile!=0 );
|
| + assert( db->init.busy==0 );
|
| + assert( p->zSql!=0 );
|
| + sqlite3OsCurrentTimeInt64(db->pVfs, &iNow);
|
| + db->xProfile(db->pProfileArg, p->zSql, (iNow - p->startTime)*1000000);
|
| + p->startTime = 0;
|
| +}
|
| +/*
|
| +** The checkProfileCallback(DB,P) macro checks to see if a profile callback
|
| +** is needed, and it invokes the callback if it is needed.
|
| +*/
|
| +# define checkProfileCallback(DB,P) \
|
| + if( ((P)->startTime)>0 ){ invokeProfileCallback(DB,P); }
|
| +#else
|
| +# define checkProfileCallback(DB,P) /*no-op*/
|
| +#endif
|
| +
|
| +/*
|
| +** The following routine destroys a virtual machine that is created by
|
| +** the sqlite3_compile() routine. The integer returned is an SQLITE_
|
| +** success/failure code that describes the result of executing the virtual
|
| +** machine.
|
| +**
|
| +** This routine sets the error code and string returned by
|
| +** sqlite3_errcode(), sqlite3_errmsg() and sqlite3_errmsg16().
|
| +*/
|
| +SQLITE_API int SQLITE_STDCALL sqlite3_finalize(sqlite3_stmt *pStmt){
|
| + int rc;
|
| + if( pStmt==0 ){
|
| + /* IMPLEMENTATION-OF: R-57228-12904 Invoking sqlite3_finalize() on a NULL
|
| + ** pointer is a harmless no-op. */
|
| + rc = SQLITE_OK;
|
| + }else{
|
| + Vdbe *v = (Vdbe*)pStmt;
|
| + sqlite3 *db = v->db;
|
| + if( vdbeSafety(v) ) return SQLITE_MISUSE_BKPT;
|
| + sqlite3_mutex_enter(db->mutex);
|
| + checkProfileCallback(db, v);
|
| + rc = sqlite3VdbeFinalize(v);
|
| + rc = sqlite3ApiExit(db, rc);
|
| + sqlite3LeaveMutexAndCloseZombie(db);
|
| + }
|
| + return rc;
|
| +}
|
| +
|
| +/*
|
| +** Terminate the current execution of an SQL statement and reset it
|
| +** back to its starting state so that it can be reused. A success code from
|
| +** the prior execution is returned.
|
| +**
|
| +** This routine sets the error code and string returned by
|
| +** sqlite3_errcode(), sqlite3_errmsg() and sqlite3_errmsg16().
|
| +*/
|
| +SQLITE_API int SQLITE_STDCALL sqlite3_reset(sqlite3_stmt *pStmt){
|
| + int rc;
|
| + if( pStmt==0 ){
|
| + rc = SQLITE_OK;
|
| + }else{
|
| + Vdbe *v = (Vdbe*)pStmt;
|
| + sqlite3 *db = v->db;
|
| + sqlite3_mutex_enter(db->mutex);
|
| + checkProfileCallback(db, v);
|
| + rc = sqlite3VdbeReset(v);
|
| + sqlite3VdbeRewind(v);
|
| + assert( (rc & (db->errMask))==rc );
|
| + rc = sqlite3ApiExit(db, rc);
|
| + sqlite3_mutex_leave(db->mutex);
|
| + }
|
| + return rc;
|
| +}
|
| +
|
| +/*
|
| +** Set all the parameters in the compiled SQL statement to NULL.
|
| +*/
|
| +SQLITE_API int SQLITE_STDCALL sqlite3_clear_bindings(sqlite3_stmt *pStmt){
|
| + int i;
|
| + int rc = SQLITE_OK;
|
| + Vdbe *p = (Vdbe*)pStmt;
|
| +#if SQLITE_THREADSAFE
|
| + sqlite3_mutex *mutex = ((Vdbe*)pStmt)->db->mutex;
|
| +#endif
|
| + sqlite3_mutex_enter(mutex);
|
| + for(i=0; i<p->nVar; i++){
|
| + sqlite3VdbeMemRelease(&p->aVar[i]);
|
| + p->aVar[i].flags = MEM_Null;
|
| + }
|
| + if( p->isPrepareV2 && p->expmask ){
|
| + p->expired = 1;
|
| + }
|
| + sqlite3_mutex_leave(mutex);
|
| + return rc;
|
| +}
|
| +
|
| +
|
| +/**************************** sqlite3_value_ *******************************
|
| +** The following routines extract information from a Mem or sqlite3_value
|
| +** structure.
|
| +*/
|
| +SQLITE_API const void *SQLITE_STDCALL sqlite3_value_blob(sqlite3_value *pVal){
|
| + Mem *p = (Mem*)pVal;
|
| + if( p->flags & (MEM_Blob|MEM_Str) ){
|
| + if( sqlite3VdbeMemExpandBlob(p)!=SQLITE_OK ){
|
| + assert( p->flags==MEM_Null && p->z==0 );
|
| + return 0;
|
| + }
|
| + p->flags |= MEM_Blob;
|
| + return p->n ? p->z : 0;
|
| + }else{
|
| + return sqlite3_value_text(pVal);
|
| + }
|
| +}
|
| +SQLITE_API int SQLITE_STDCALL sqlite3_value_bytes(sqlite3_value *pVal){
|
| + return sqlite3ValueBytes(pVal, SQLITE_UTF8);
|
| +}
|
| +SQLITE_API int SQLITE_STDCALL sqlite3_value_bytes16(sqlite3_value *pVal){
|
| + return sqlite3ValueBytes(pVal, SQLITE_UTF16NATIVE);
|
| +}
|
| +SQLITE_API double SQLITE_STDCALL sqlite3_value_double(sqlite3_value *pVal){
|
| + return sqlite3VdbeRealValue((Mem*)pVal);
|
| +}
|
| +SQLITE_API int SQLITE_STDCALL sqlite3_value_int(sqlite3_value *pVal){
|
| + return (int)sqlite3VdbeIntValue((Mem*)pVal);
|
| +}
|
| +SQLITE_API sqlite_int64 SQLITE_STDCALL sqlite3_value_int64(sqlite3_value *pVal){
|
| + return sqlite3VdbeIntValue((Mem*)pVal);
|
| +}
|
| +SQLITE_API unsigned int SQLITE_STDCALL sqlite3_value_subtype(sqlite3_value *pVal){
|
| + return ((Mem*)pVal)->eSubtype;
|
| +}
|
| +SQLITE_API const unsigned char *SQLITE_STDCALL sqlite3_value_text(sqlite3_value *pVal){
|
| + return (const unsigned char *)sqlite3ValueText(pVal, SQLITE_UTF8);
|
| +}
|
| +#ifndef SQLITE_OMIT_UTF16
|
| +SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16(sqlite3_value* pVal){
|
| + return sqlite3ValueText(pVal, SQLITE_UTF16NATIVE);
|
| +}
|
| +SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16be(sqlite3_value *pVal){
|
| + return sqlite3ValueText(pVal, SQLITE_UTF16BE);
|
| +}
|
| +SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16le(sqlite3_value *pVal){
|
| + return sqlite3ValueText(pVal, SQLITE_UTF16LE);
|
| +}
|
| +#endif /* SQLITE_OMIT_UTF16 */
|
| +/* EVIDENCE-OF: R-12793-43283 Every value in SQLite has one of five
|
| +** fundamental datatypes: 64-bit signed integer 64-bit IEEE floating
|
| +** point number string BLOB NULL
|
| +*/
|
| +SQLITE_API int SQLITE_STDCALL sqlite3_value_type(sqlite3_value* pVal){
|
| + static const u8 aType[] = {
|
| + SQLITE_BLOB, /* 0x00 */
|
| + SQLITE_NULL, /* 0x01 */
|
| + SQLITE_TEXT, /* 0x02 */
|
| + SQLITE_NULL, /* 0x03 */
|
| + SQLITE_INTEGER, /* 0x04 */
|
| + SQLITE_NULL, /* 0x05 */
|
| + SQLITE_INTEGER, /* 0x06 */
|
| + SQLITE_NULL, /* 0x07 */
|
| + SQLITE_FLOAT, /* 0x08 */
|
| + SQLITE_NULL, /* 0x09 */
|
| + SQLITE_FLOAT, /* 0x0a */
|
| + SQLITE_NULL, /* 0x0b */
|
| + SQLITE_INTEGER, /* 0x0c */
|
| + SQLITE_NULL, /* 0x0d */
|
| + SQLITE_INTEGER, /* 0x0e */
|
| + SQLITE_NULL, /* 0x0f */
|
| + SQLITE_BLOB, /* 0x10 */
|
| + SQLITE_NULL, /* 0x11 */
|
| + SQLITE_TEXT, /* 0x12 */
|
| + SQLITE_NULL, /* 0x13 */
|
| + SQLITE_INTEGER, /* 0x14 */
|
| + SQLITE_NULL, /* 0x15 */
|
| + SQLITE_INTEGER, /* 0x16 */
|
| + SQLITE_NULL, /* 0x17 */
|
| + SQLITE_FLOAT, /* 0x18 */
|
| + SQLITE_NULL, /* 0x19 */
|
| + SQLITE_FLOAT, /* 0x1a */
|
| + SQLITE_NULL, /* 0x1b */
|
| + SQLITE_INTEGER, /* 0x1c */
|
| + SQLITE_NULL, /* 0x1d */
|
| + SQLITE_INTEGER, /* 0x1e */
|
| + SQLITE_NULL, /* 0x1f */
|
| + };
|
| + return aType[pVal->flags&MEM_AffMask];
|
| +}
|
| +
|
| +/* Make a copy of an sqlite3_value object
|
| +*/
|
| +SQLITE_API sqlite3_value *SQLITE_STDCALL sqlite3_value_dup(const sqlite3_value *pOrig){
|
| + sqlite3_value *pNew;
|
| + if( pOrig==0 ) return 0;
|
| + pNew = sqlite3_malloc( sizeof(*pNew) );
|
| + if( pNew==0 ) return 0;
|
| + memset(pNew, 0, sizeof(*pNew));
|
| + memcpy(pNew, pOrig, MEMCELLSIZE);
|
| + pNew->flags &= ~MEM_Dyn;
|
| + pNew->db = 0;
|
| + if( pNew->flags&(MEM_Str|MEM_Blob) ){
|
| + pNew->flags &= ~(MEM_Static|MEM_Dyn);
|
| + pNew->flags |= MEM_Ephem;
|
| + if( sqlite3VdbeMemMakeWriteable(pNew)!=SQLITE_OK ){
|
| + sqlite3ValueFree(pNew);
|
| + pNew = 0;
|
| + }
|
| + }
|
| + return pNew;
|
| +}
|
| +
|
| +/* Destroy an sqlite3_value object previously obtained from
|
| +** sqlite3_value_dup().
|
| +*/
|
| +SQLITE_API void SQLITE_STDCALL sqlite3_value_free(sqlite3_value *pOld){
|
| + sqlite3ValueFree(pOld);
|
| +}
|
| +
|
| +
|
| +/**************************** sqlite3_result_ *******************************
|
| +** The following routines are used by user-defined functions to specify
|
| +** the function result.
|
| +**
|
| +** The setStrOrError() function calls sqlite3VdbeMemSetStr() to store the
|
| +** result as a string or blob but if the string or blob is too large, it
|
| +** then sets the error code to SQLITE_TOOBIG
|
| +**
|
| +** The invokeValueDestructor(P,X) routine invokes destructor function X()
|
| +** on value P is not going to be used and need to be destroyed.
|
| +*/
|
| +static void setResultStrOrError(
|
| + sqlite3_context *pCtx, /* Function context */
|
| + const char *z, /* String pointer */
|
| + int n, /* Bytes in string, or negative */
|
| + u8 enc, /* Encoding of z. 0 for BLOBs */
|
| + void (*xDel)(void*) /* Destructor function */
|
| +){
|
| + if( sqlite3VdbeMemSetStr(pCtx->pOut, z, n, enc, xDel)==SQLITE_TOOBIG ){
|
| + sqlite3_result_error_toobig(pCtx);
|
| + }
|
| +}
|
| +static int invokeValueDestructor(
|
| + const void *p, /* Value to destroy */
|
| + void (*xDel)(void*), /* The destructor */
|
| + sqlite3_context *pCtx /* Set a SQLITE_TOOBIG error if no NULL */
|
| +){
|
| + assert( xDel!=SQLITE_DYNAMIC );
|
| + if( xDel==0 ){
|
| + /* noop */
|
| + }else if( xDel==SQLITE_TRANSIENT ){
|
| + /* noop */
|
| + }else{
|
| + xDel((void*)p);
|
| + }
|
| + if( pCtx ) sqlite3_result_error_toobig(pCtx);
|
| + return SQLITE_TOOBIG;
|
| +}
|
| +SQLITE_API void SQLITE_STDCALL sqlite3_result_blob(
|
| + sqlite3_context *pCtx,
|
| + const void *z,
|
| + int n,
|
| + void (*xDel)(void *)
|
| +){
|
| + assert( n>=0 );
|
| + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
|
| + setResultStrOrError(pCtx, z, n, 0, xDel);
|
| +}
|
| +SQLITE_API void SQLITE_STDCALL sqlite3_result_blob64(
|
| + sqlite3_context *pCtx,
|
| + const void *z,
|
| + sqlite3_uint64 n,
|
| + void (*xDel)(void *)
|
| +){
|
| + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
|
| + assert( xDel!=SQLITE_DYNAMIC );
|
| + if( n>0x7fffffff ){
|
| + (void)invokeValueDestructor(z, xDel, pCtx);
|
| + }else{
|
| + setResultStrOrError(pCtx, z, (int)n, 0, xDel);
|
| + }
|
| +}
|
| +SQLITE_API void SQLITE_STDCALL sqlite3_result_double(sqlite3_context *pCtx, double rVal){
|
| + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
|
| + sqlite3VdbeMemSetDouble(pCtx->pOut, rVal);
|
| +}
|
| +SQLITE_API void SQLITE_STDCALL sqlite3_result_error(sqlite3_context *pCtx, const char *z, int n){
|
| + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
|
| + pCtx->isError = SQLITE_ERROR;
|
| + pCtx->fErrorOrAux = 1;
|
| + sqlite3VdbeMemSetStr(pCtx->pOut, z, n, SQLITE_UTF8, SQLITE_TRANSIENT);
|
| +}
|
| +#ifndef SQLITE_OMIT_UTF16
|
| +SQLITE_API void SQLITE_STDCALL sqlite3_result_error16(sqlite3_context *pCtx, const void *z, int n){
|
| + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
|
| + pCtx->isError = SQLITE_ERROR;
|
| + pCtx->fErrorOrAux = 1;
|
| + sqlite3VdbeMemSetStr(pCtx->pOut, z, n, SQLITE_UTF16NATIVE, SQLITE_TRANSIENT);
|
| +}
|
| +#endif
|
| +SQLITE_API void SQLITE_STDCALL sqlite3_result_int(sqlite3_context *pCtx, int iVal){
|
| + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
|
| + sqlite3VdbeMemSetInt64(pCtx->pOut, (i64)iVal);
|
| +}
|
| +SQLITE_API void SQLITE_STDCALL sqlite3_result_int64(sqlite3_context *pCtx, i64 iVal){
|
| + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
|
| + sqlite3VdbeMemSetInt64(pCtx->pOut, iVal);
|
| +}
|
| +SQLITE_API void SQLITE_STDCALL sqlite3_result_null(sqlite3_context *pCtx){
|
| + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
|
| + sqlite3VdbeMemSetNull(pCtx->pOut);
|
| +}
|
| +SQLITE_API void SQLITE_STDCALL sqlite3_result_subtype(sqlite3_context *pCtx, unsigned int eSubtype){
|
| + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
|
| + pCtx->pOut->eSubtype = eSubtype & 0xff;
|
| +}
|
| +SQLITE_API void SQLITE_STDCALL sqlite3_result_text(
|
| + sqlite3_context *pCtx,
|
| + const char *z,
|
| + int n,
|
| + void (*xDel)(void *)
|
| +){
|
| + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
|
| + setResultStrOrError(pCtx, z, n, SQLITE_UTF8, xDel);
|
| +}
|
| +SQLITE_API void SQLITE_STDCALL sqlite3_result_text64(
|
| + sqlite3_context *pCtx,
|
| + const char *z,
|
| + sqlite3_uint64 n,
|
| + void (*xDel)(void *),
|
| + unsigned char enc
|
| +){
|
| + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
|
| + assert( xDel!=SQLITE_DYNAMIC );
|
| + if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE;
|
| + if( n>0x7fffffff ){
|
| + (void)invokeValueDestructor(z, xDel, pCtx);
|
| + }else{
|
| + setResultStrOrError(pCtx, z, (int)n, enc, xDel);
|
| + }
|
| +}
|
| +#ifndef SQLITE_OMIT_UTF16
|
| +SQLITE_API void SQLITE_STDCALL sqlite3_result_text16(
|
| + sqlite3_context *pCtx,
|
| + const void *z,
|
| + int n,
|
| + void (*xDel)(void *)
|
| +){
|
| + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
|
| + setResultStrOrError(pCtx, z, n, SQLITE_UTF16NATIVE, xDel);
|
| +}
|
| +SQLITE_API void SQLITE_STDCALL sqlite3_result_text16be(
|
| + sqlite3_context *pCtx,
|
| + const void *z,
|
| + int n,
|
| + void (*xDel)(void *)
|
| +){
|
| + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
|
| + setResultStrOrError(pCtx, z, n, SQLITE_UTF16BE, xDel);
|
| +}
|
| +SQLITE_API void SQLITE_STDCALL sqlite3_result_text16le(
|
| + sqlite3_context *pCtx,
|
| + const void *z,
|
| + int n,
|
| + void (*xDel)(void *)
|
| +){
|
| + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
|
| + setResultStrOrError(pCtx, z, n, SQLITE_UTF16LE, xDel);
|
| +}
|
| +#endif /* SQLITE_OMIT_UTF16 */
|
| +SQLITE_API void SQLITE_STDCALL sqlite3_result_value(sqlite3_context *pCtx, sqlite3_value *pValue){
|
| + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
|
| + sqlite3VdbeMemCopy(pCtx->pOut, pValue);
|
| +}
|
| +SQLITE_API void SQLITE_STDCALL sqlite3_result_zeroblob(sqlite3_context *pCtx, int n){
|
| + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
|
| + sqlite3VdbeMemSetZeroBlob(pCtx->pOut, n);
|
| +}
|
| +SQLITE_API int SQLITE_STDCALL sqlite3_result_zeroblob64(sqlite3_context *pCtx, u64 n){
|
| + Mem *pOut = pCtx->pOut;
|
| + assert( sqlite3_mutex_held(pOut->db->mutex) );
|
| + if( n>(u64)pOut->db->aLimit[SQLITE_LIMIT_LENGTH] ){
|
| + return SQLITE_TOOBIG;
|
| + }
|
| + sqlite3VdbeMemSetZeroBlob(pCtx->pOut, (int)n);
|
| + return SQLITE_OK;
|
| +}
|
| +SQLITE_API void SQLITE_STDCALL sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){
|
| + pCtx->isError = errCode;
|
| + pCtx->fErrorOrAux = 1;
|
| +#ifdef SQLITE_DEBUG
|
| + if( pCtx->pVdbe ) pCtx->pVdbe->rcApp = errCode;
|
| +#endif
|
| + if( pCtx->pOut->flags & MEM_Null ){
|
| + sqlite3VdbeMemSetStr(pCtx->pOut, sqlite3ErrStr(errCode), -1,
|
| + SQLITE_UTF8, SQLITE_STATIC);
|
| + }
|
| +}
|
| +
|
| +/* Force an SQLITE_TOOBIG error. */
|
| +SQLITE_API void SQLITE_STDCALL sqlite3_result_error_toobig(sqlite3_context *pCtx){
|
| + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
|
| + pCtx->isError = SQLITE_TOOBIG;
|
| + pCtx->fErrorOrAux = 1;
|
| + sqlite3VdbeMemSetStr(pCtx->pOut, "string or blob too big", -1,
|
| + SQLITE_UTF8, SQLITE_STATIC);
|
| +}
|
| +
|
| +/* An SQLITE_NOMEM error. */
|
| +SQLITE_API void SQLITE_STDCALL sqlite3_result_error_nomem(sqlite3_context *pCtx){
|
| + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
|
| + sqlite3VdbeMemSetNull(pCtx->pOut);
|
| + pCtx->isError = SQLITE_NOMEM;
|
| + pCtx->fErrorOrAux = 1;
|
| + pCtx->pOut->db->mallocFailed = 1;
|
| +}
|
| +
|
| +/*
|
| +** This function is called after a transaction has been committed. It
|
| +** invokes callbacks registered with sqlite3_wal_hook() as required.
|
| +*/
|
| +static int doWalCallbacks(sqlite3 *db){
|
| + int rc = SQLITE_OK;
|
| +#ifndef SQLITE_OMIT_WAL
|
| + int i;
|
| + for(i=0; i<db->nDb; i++){
|
| + Btree *pBt = db->aDb[i].pBt;
|
| + if( pBt ){
|
| + int nEntry;
|
| + sqlite3BtreeEnter(pBt);
|
| + nEntry = sqlite3PagerWalCallback(sqlite3BtreePager(pBt));
|
| + sqlite3BtreeLeave(pBt);
|
| + if( db->xWalCallback && nEntry>0 && rc==SQLITE_OK ){
|
| + rc = db->xWalCallback(db->pWalArg, db, db->aDb[i].zName, nEntry);
|
| + }
|
| + }
|
| + }
|
| +#endif
|
| + return rc;
|
| +}
|
| +
|
| +
|
| +/*
|
| +** Execute the statement pStmt, either until a row of data is ready, the
|
| +** statement is completely executed or an error occurs.
|
| +**
|
| +** This routine implements the bulk of the logic behind the sqlite_step()
|
| +** API. The only thing omitted is the automatic recompile if a
|
| +** schema change has occurred. That detail is handled by the
|
| +** outer sqlite3_step() wrapper procedure.
|
| +*/
|
| +static int sqlite3Step(Vdbe *p){
|
| + sqlite3 *db;
|
| + int rc;
|
| +
|
| + assert(p);
|
| + if( p->magic!=VDBE_MAGIC_RUN ){
|
| + /* We used to require that sqlite3_reset() be called before retrying
|
| + ** sqlite3_step() after any error or after SQLITE_DONE. But beginning
|
| + ** with version 3.7.0, we changed this so that sqlite3_reset() would
|
| + ** be called automatically instead of throwing the SQLITE_MISUSE error.
|
| + ** This "automatic-reset" change is not technically an incompatibility,
|
| + ** since any application that receives an SQLITE_MISUSE is broken by
|
| + ** definition.
|
| + **
|
| + ** Nevertheless, some published applications that were originally written
|
| + ** for version 3.6.23 or earlier do in fact depend on SQLITE_MISUSE
|
| + ** returns, and those were broken by the automatic-reset change. As a
|
| + ** a work-around, the SQLITE_OMIT_AUTORESET compile-time restores the
|
| + ** legacy behavior of returning SQLITE_MISUSE for cases where the
|
| + ** previous sqlite3_step() returned something other than a SQLITE_LOCKED
|
| + ** or SQLITE_BUSY error.
|
| + */
|
| +#ifdef SQLITE_OMIT_AUTORESET
|
| + if( (rc = p->rc&0xff)==SQLITE_BUSY || rc==SQLITE_LOCKED ){
|
| + sqlite3_reset((sqlite3_stmt*)p);
|
| + }else{
|
| + return SQLITE_MISUSE_BKPT;
|
| + }
|
| +#else
|
| + sqlite3_reset((sqlite3_stmt*)p);
|
| +#endif
|
| + }
|
| +
|
| + /* Check that malloc() has not failed. If it has, return early. */
|
| + db = p->db;
|
| + if( db->mallocFailed ){
|
| + p->rc = SQLITE_NOMEM;
|
| + return SQLITE_NOMEM;
|
| + }
|
| +
|
| + if( p->pc<=0 && p->expired ){
|
| + p->rc = SQLITE_SCHEMA;
|
| + rc = SQLITE_ERROR;
|
| + goto end_of_step;
|
| + }
|
| + if( p->pc<0 ){
|
| + /* If there are no other statements currently running, then
|
| + ** reset the interrupt flag. This prevents a call to sqlite3_interrupt
|
| + ** from interrupting a statement that has not yet started.
|
| + */
|
| + if( db->nVdbeActive==0 ){
|
| + db->u1.isInterrupted = 0;
|
| + }
|
| +
|
| + assert( db->nVdbeWrite>0 || db->autoCommit==0
|
| + || (db->nDeferredCons==0 && db->nDeferredImmCons==0)
|
| + );
|
| +
|
| +#ifndef SQLITE_OMIT_TRACE
|
| + if( db->xProfile && !db->init.busy && p->zSql ){
|
| + sqlite3OsCurrentTimeInt64(db->pVfs, &p->startTime);
|
| + }else{
|
| + assert( p->startTime==0 );
|
| + }
|
| +#endif
|
| +
|
| + db->nVdbeActive++;
|
| + if( p->readOnly==0 ) db->nVdbeWrite++;
|
| + if( p->bIsReader ) db->nVdbeRead++;
|
| + p->pc = 0;
|
| + }
|
| +#ifdef SQLITE_DEBUG
|
| + p->rcApp = SQLITE_OK;
|
| +#endif
|
| +#ifndef SQLITE_OMIT_EXPLAIN
|
| + if( p->explain ){
|
| + rc = sqlite3VdbeList(p);
|
| + }else
|
| +#endif /* SQLITE_OMIT_EXPLAIN */
|
| + {
|
| + db->nVdbeExec++;
|
| + rc = sqlite3VdbeExec(p);
|
| + db->nVdbeExec--;
|
| + }
|
| +
|
| +#ifndef SQLITE_OMIT_TRACE
|
| + /* If the statement completed successfully, invoke the profile callback */
|
| + if( rc!=SQLITE_ROW ) checkProfileCallback(db, p);
|
| +#endif
|
| +
|
| + if( rc==SQLITE_DONE ){
|
| + assert( p->rc==SQLITE_OK );
|
| + p->rc = doWalCallbacks(db);
|
| + if( p->rc!=SQLITE_OK ){
|
| + rc = SQLITE_ERROR;
|
| + }
|
| + }
|
| +
|
| + db->errCode = rc;
|
| + if( SQLITE_NOMEM==sqlite3ApiExit(p->db, p->rc) ){
|
| + p->rc = SQLITE_NOMEM;
|
| + }
|
| +end_of_step:
|
| + /* At this point local variable rc holds the value that should be
|
| + ** returned if this statement was compiled using the legacy
|
| + ** sqlite3_prepare() interface. According to the docs, this can only
|
| + ** be one of the values in the first assert() below. Variable p->rc
|
| + ** contains the value that would be returned if sqlite3_finalize()
|
| + ** were called on statement p.
|
| + */
|
| + assert( rc==SQLITE_ROW || rc==SQLITE_DONE || rc==SQLITE_ERROR
|
| + || (rc&0xff)==SQLITE_BUSY || rc==SQLITE_MISUSE
|
| + );
|
| + assert( (p->rc!=SQLITE_ROW && p->rc!=SQLITE_DONE) || p->rc==p->rcApp );
|
| + if( p->isPrepareV2 && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
|
| + /* If this statement was prepared using sqlite3_prepare_v2(), and an
|
| + ** error has occurred, then return the error code in p->rc to the
|
| + ** caller. Set the error code in the database handle to the same value.
|
| + */
|
| + rc = sqlite3VdbeTransferError(p);
|
| + }
|
| + return (rc&db->errMask);
|
| +}
|
| +
|
| +/*
|
| +** This is the top-level implementation of sqlite3_step(). Call
|
| +** sqlite3Step() to do most of the work. If a schema error occurs,
|
| +** call sqlite3Reprepare() and try again.
|
| +*/
|
| +SQLITE_API int SQLITE_STDCALL sqlite3_step(sqlite3_stmt *pStmt){
|
| + int rc = SQLITE_OK; /* Result from sqlite3Step() */
|
| + int rc2 = SQLITE_OK; /* Result from sqlite3Reprepare() */
|
| + Vdbe *v = (Vdbe*)pStmt; /* the prepared statement */
|
| + int cnt = 0; /* Counter to prevent infinite loop of reprepares */
|
| + sqlite3 *db; /* The database connection */
|
| +
|
| + if( vdbeSafetyNotNull(v) ){
|
| + return SQLITE_MISUSE_BKPT;
|
| + }
|
| + db = v->db;
|
| + sqlite3_mutex_enter(db->mutex);
|
| + v->doingRerun = 0;
|
| + while( (rc = sqlite3Step(v))==SQLITE_SCHEMA
|
| + && cnt++ < SQLITE_MAX_SCHEMA_RETRY ){
|
| + int savedPc = v->pc;
|
| + rc2 = rc = sqlite3Reprepare(v);
|
| + if( rc!=SQLITE_OK) break;
|
| + sqlite3_reset(pStmt);
|
| + if( savedPc>=0 ) v->doingRerun = 1;
|
| + assert( v->expired==0 );
|
| + }
|
| + if( rc2!=SQLITE_OK ){
|
| + /* This case occurs after failing to recompile an sql statement.
|
| + ** The error message from the SQL compiler has already been loaded
|
| + ** into the database handle. This block copies the error message
|
| + ** from the database handle into the statement and sets the statement
|
| + ** program counter to 0 to ensure that when the statement is
|
| + ** finalized or reset the parser error message is available via
|
| + ** sqlite3_errmsg() and sqlite3_errcode().
|
| + */
|
| + const char *zErr = (const char *)sqlite3_value_text(db->pErr);
|
| + sqlite3DbFree(db, v->zErrMsg);
|
| + if( !db->mallocFailed ){
|
| + v->zErrMsg = sqlite3DbStrDup(db, zErr);
|
| + v->rc = rc2;
|
| + } else {
|
| + v->zErrMsg = 0;
|
| + v->rc = rc = SQLITE_NOMEM;
|
| + }
|
| + }
|
| + rc = sqlite3ApiExit(db, rc);
|
| + sqlite3_mutex_leave(db->mutex);
|
| + return rc;
|
| +}
|
| +
|
| +
|
| +/*
|
| +** Extract the user data from a sqlite3_context structure and return a
|
| +** pointer to it.
|
| +*/
|
| +SQLITE_API void *SQLITE_STDCALL sqlite3_user_data(sqlite3_context *p){
|
| + assert( p && p->pFunc );
|
| + return p->pFunc->pUserData;
|
| +}
|
| +
|
| +/*
|
| +** Extract the user data from a sqlite3_context structure and return a
|
| +** pointer to it.
|
| +**
|
| +** IMPLEMENTATION-OF: R-46798-50301 The sqlite3_context_db_handle() interface
|
| +** returns a copy of the pointer to the database connection (the 1st
|
| +** parameter) of the sqlite3_create_function() and
|
| +** sqlite3_create_function16() routines that originally registered the
|
| +** application defined function.
|
| +*/
|
| +SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_context_db_handle(sqlite3_context *p){
|
| + assert( p && p->pOut );
|
| + return p->pOut->db;
|
| +}
|
| +
|
| +/*
|
| +** 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
|
| +** of the amount of time that elapses between invocations. In other words,
|
| +** the time returned is always the time of the first call.
|
| +*/
|
| +SQLITE_PRIVATE sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context *p){
|
| + int rc;
|
| +#ifndef SQLITE_ENABLE_STAT3_OR_STAT4
|
| + sqlite3_int64 *piTime = &p->pVdbe->iCurrentTime;
|
| + assert( p->pVdbe!=0 );
|
| +#else
|
| + sqlite3_int64 iTime = 0;
|
| + sqlite3_int64 *piTime = p->pVdbe!=0 ? &p->pVdbe->iCurrentTime : &iTime;
|
| +#endif
|
| + if( *piTime==0 ){
|
| + rc = sqlite3OsCurrentTimeInt64(p->pOut->db->pVfs, piTime);
|
| + if( rc ) *piTime = 0;
|
| + }
|
| + return *piTime;
|
| +}
|
| +
|
| +/*
|
| +** The following is the implementation of an SQL function that always
|
| +** fails with an error message stating that the function is used in the
|
| +** wrong context. The sqlite3_overload_function() API might construct
|
| +** SQL function that use this routine so that the functions will exist
|
| +** for name resolution but are actually overloaded by the xFindFunction
|
| +** method of virtual tables.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3InvalidFunction(
|
| + sqlite3_context *context, /* The function calling context */
|
| + int NotUsed, /* Number of arguments to the function */
|
| + sqlite3_value **NotUsed2 /* Value of each argument */
|
| +){
|
| + const char *zName = context->pFunc->zName;
|
| + char *zErr;
|
| + UNUSED_PARAMETER2(NotUsed, NotUsed2);
|
| + zErr = sqlite3_mprintf(
|
| + "unable to use function %s in the requested context", zName);
|
| + sqlite3_result_error(context, zErr, -1);
|
| + sqlite3_free(zErr);
|
| +}
|
| +
|
| +/*
|
| +** Create a new aggregate context for p and return a pointer to
|
| +** its pMem->z element.
|
| +*/
|
| +static SQLITE_NOINLINE void *createAggContext(sqlite3_context *p, int nByte){
|
| + Mem *pMem = p->pMem;
|
| + assert( (pMem->flags & MEM_Agg)==0 );
|
| + if( nByte<=0 ){
|
| + sqlite3VdbeMemSetNull(pMem);
|
| + pMem->z = 0;
|
| + }else{
|
| + sqlite3VdbeMemClearAndResize(pMem, nByte);
|
| + pMem->flags = MEM_Agg;
|
| + pMem->u.pDef = p->pFunc;
|
| + if( pMem->z ){
|
| + memset(pMem->z, 0, nByte);
|
| + }
|
| + }
|
| + return (void*)pMem->z;
|
| +}
|
| +
|
| +/*
|
| +** Allocate or return the aggregate context for a user function. A new
|
| +** context is allocated on the first call. Subsequent calls return the
|
| +** same context that was returned on prior calls.
|
| +*/
|
| +SQLITE_API void *SQLITE_STDCALL sqlite3_aggregate_context(sqlite3_context *p, int nByte){
|
| + assert( p && p->pFunc && p->pFunc->xStep );
|
| + assert( sqlite3_mutex_held(p->pOut->db->mutex) );
|
| + testcase( nByte<0 );
|
| + if( (p->pMem->flags & MEM_Agg)==0 ){
|
| + return createAggContext(p, nByte);
|
| + }else{
|
| + return (void*)p->pMem->z;
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Return the auxiliary data pointer, if any, for the iArg'th argument to
|
| +** the user-function defined by pCtx.
|
| +*/
|
| +SQLITE_API void *SQLITE_STDCALL sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){
|
| + AuxData *pAuxData;
|
| +
|
| + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
|
| +#if SQLITE_ENABLE_STAT3_OR_STAT4
|
| + if( pCtx->pVdbe==0 ) return 0;
|
| +#else
|
| + assert( pCtx->pVdbe!=0 );
|
| +#endif
|
| + for(pAuxData=pCtx->pVdbe->pAuxData; pAuxData; pAuxData=pAuxData->pNext){
|
| + if( pAuxData->iOp==pCtx->iOp && pAuxData->iArg==iArg ) break;
|
| + }
|
| +
|
| + return (pAuxData ? pAuxData->pAux : 0);
|
| +}
|
| +
|
| +/*
|
| +** Set the auxiliary data pointer and delete function, for the iArg'th
|
| +** argument to the user-function defined by pCtx. Any previous value is
|
| +** deleted by calling the delete function specified when it was set.
|
| +*/
|
| +SQLITE_API void SQLITE_STDCALL sqlite3_set_auxdata(
|
| + sqlite3_context *pCtx,
|
| + int iArg,
|
| + void *pAux,
|
| + void (*xDelete)(void*)
|
| +){
|
| + AuxData *pAuxData;
|
| + Vdbe *pVdbe = pCtx->pVdbe;
|
| +
|
| + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
|
| + if( iArg<0 ) goto failed;
|
| +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
| + if( pVdbe==0 ) goto failed;
|
| +#else
|
| + assert( pVdbe!=0 );
|
| +#endif
|
| +
|
| + for(pAuxData=pVdbe->pAuxData; pAuxData; pAuxData=pAuxData->pNext){
|
| + if( pAuxData->iOp==pCtx->iOp && pAuxData->iArg==iArg ) break;
|
| + }
|
| + if( pAuxData==0 ){
|
| + pAuxData = sqlite3DbMallocZero(pVdbe->db, sizeof(AuxData));
|
| + if( !pAuxData ) goto failed;
|
| + pAuxData->iOp = pCtx->iOp;
|
| + pAuxData->iArg = iArg;
|
| + pAuxData->pNext = pVdbe->pAuxData;
|
| + pVdbe->pAuxData = pAuxData;
|
| + if( pCtx->fErrorOrAux==0 ){
|
| + pCtx->isError = 0;
|
| + pCtx->fErrorOrAux = 1;
|
| + }
|
| + }else if( pAuxData->xDelete ){
|
| + pAuxData->xDelete(pAuxData->pAux);
|
| + }
|
| +
|
| + pAuxData->pAux = pAux;
|
| + pAuxData->xDelete = xDelete;
|
| + return;
|
| +
|
| +failed:
|
| + if( xDelete ){
|
| + xDelete(pAux);
|
| + }
|
| +}
|
| +
|
| +#ifndef SQLITE_OMIT_DEPRECATED
|
| +/*
|
| +** Return the number of times the Step function of an aggregate has been
|
| +** called.
|
| +**
|
| +** This function is deprecated. Do not use it for new code. It is
|
| +** provide only to avoid breaking legacy code. New aggregate function
|
| +** implementations should keep their own counts within their aggregate
|
| +** context.
|
| +*/
|
| +SQLITE_API int SQLITE_STDCALL sqlite3_aggregate_count(sqlite3_context *p){
|
| + assert( p && p->pMem && p->pFunc && p->pFunc->xStep );
|
| + return p->pMem->n;
|
| +}
|
| +#endif
|
| +
|
| +/*
|
| +** Return the number of columns in the result set for the statement pStmt.
|
| +*/
|
| +SQLITE_API int SQLITE_STDCALL sqlite3_column_count(sqlite3_stmt *pStmt){
|
| + Vdbe *pVm = (Vdbe *)pStmt;
|
| + return pVm ? pVm->nResColumn : 0;
|
| +}
|
| +
|
| +/*
|
| +** Return the number of values available from the current row of the
|
| +** currently executing statement pStmt.
|
| +*/
|
| +SQLITE_API int SQLITE_STDCALL sqlite3_data_count(sqlite3_stmt *pStmt){
|
| + Vdbe *pVm = (Vdbe *)pStmt;
|
| + if( pVm==0 || pVm->pResultSet==0 ) return 0;
|
| + return pVm->nResColumn;
|
| +}
|
| +
|
| +/*
|
| +** Return a pointer to static memory containing an SQL NULL value.
|
| +*/
|
| +static const Mem *columnNullValue(void){
|
| + /* Even though the Mem structure contains an element
|
| + ** of type i64, on certain architectures (x86) with certain compiler
|
| + ** switches (-Os), gcc may align this Mem object on a 4-byte boundary
|
| + ** instead of an 8-byte one. This all works fine, except that when
|
| + ** running with SQLITE_DEBUG defined the SQLite code sometimes assert()s
|
| + ** that a Mem structure is located on an 8-byte boundary. To prevent
|
| + ** these assert()s from failing, when building with SQLITE_DEBUG defined
|
| + ** using gcc, we force nullMem to be 8-byte aligned using the magical
|
| + ** __attribute__((aligned(8))) macro. */
|
| + static const Mem nullMem
|
| +#if defined(SQLITE_DEBUG) && defined(__GNUC__)
|
| + __attribute__((aligned(8)))
|
| +#endif
|
| + = {
|
| + /* .u = */ {0},
|
| + /* .flags = */ (u16)MEM_Null,
|
| + /* .enc = */ (u8)0,
|
| + /* .eSubtype = */ (u8)0,
|
| + /* .n = */ (int)0,
|
| + /* .z = */ (char*)0,
|
| + /* .zMalloc = */ (char*)0,
|
| + /* .szMalloc = */ (int)0,
|
| + /* .uTemp = */ (u32)0,
|
| + /* .db = */ (sqlite3*)0,
|
| + /* .xDel = */ (void(*)(void*))0,
|
| +#ifdef SQLITE_DEBUG
|
| + /* .pScopyFrom = */ (Mem*)0,
|
| + /* .pFiller = */ (void*)0,
|
| +#endif
|
| + };
|
| + return &nullMem;
|
| +}
|
| +
|
| +/*
|
| +** Check to see if column iCol of the given statement is valid. If
|
| +** it is, return a pointer to the Mem for the value of that column.
|
| +** If iCol is not valid, return a pointer to a Mem which has a value
|
| +** of NULL.
|
| +*/
|
| +static Mem *columnMem(sqlite3_stmt *pStmt, int i){
|
| + Vdbe *pVm;
|
| + Mem *pOut;
|
| +
|
| + pVm = (Vdbe *)pStmt;
|
| + if( pVm && pVm->pResultSet!=0 && i<pVm->nResColumn && i>=0 ){
|
| + sqlite3_mutex_enter(pVm->db->mutex);
|
| + pOut = &pVm->pResultSet[i];
|
| + }else{
|
| + if( pVm && ALWAYS(pVm->db) ){
|
| + sqlite3_mutex_enter(pVm->db->mutex);
|
| + sqlite3Error(pVm->db, SQLITE_RANGE);
|
| + }
|
| + pOut = (Mem*)columnNullValue();
|
| + }
|
| + return pOut;
|
| +}
|
| +
|
| +/*
|
| +** This function is called after invoking an sqlite3_value_XXX function on a
|
| +** column value (i.e. a value returned by evaluating an SQL expression in the
|
| +** select list of a SELECT statement) that may cause a malloc() failure. If
|
| +** malloc() has failed, the threads mallocFailed flag is cleared and the result
|
| +** code of statement pStmt set to SQLITE_NOMEM.
|
| +**
|
| +** Specifically, this is called from within:
|
| +**
|
| +** sqlite3_column_int()
|
| +** sqlite3_column_int64()
|
| +** sqlite3_column_text()
|
| +** sqlite3_column_text16()
|
| +** sqlite3_column_real()
|
| +** sqlite3_column_bytes()
|
| +** sqlite3_column_bytes16()
|
| +** sqiite3_column_blob()
|
| +*/
|
| +static void columnMallocFailure(sqlite3_stmt *pStmt)
|
| +{
|
| + /* If malloc() failed during an encoding conversion within an
|
| + ** sqlite3_column_XXX API, then set the return code of the statement to
|
| + ** SQLITE_NOMEM. The next call to _step() (if any) will return SQLITE_ERROR
|
| + ** and _finalize() will return NOMEM.
|
| + */
|
| + Vdbe *p = (Vdbe *)pStmt;
|
| + if( p ){
|
| + p->rc = sqlite3ApiExit(p->db, p->rc);
|
| + sqlite3_mutex_leave(p->db->mutex);
|
| + }
|
| +}
|
| +
|
| +/**************************** sqlite3_column_ *******************************
|
| +** The following routines are used to access elements of the current row
|
| +** in the result set.
|
| +*/
|
| +SQLITE_API const void *SQLITE_STDCALL sqlite3_column_blob(sqlite3_stmt *pStmt, int i){
|
| + const void *val;
|
| + val = sqlite3_value_blob( columnMem(pStmt,i) );
|
| + /* Even though there is no encoding conversion, value_blob() might
|
| + ** need to call malloc() to expand the result of a zeroblob()
|
| + ** expression.
|
| + */
|
| + columnMallocFailure(pStmt);
|
| + return val;
|
| +}
|
| +SQLITE_API int SQLITE_STDCALL sqlite3_column_bytes(sqlite3_stmt *pStmt, int i){
|
| + int val = sqlite3_value_bytes( columnMem(pStmt,i) );
|
| + columnMallocFailure(pStmt);
|
| + return val;
|
| +}
|
| +SQLITE_API int SQLITE_STDCALL sqlite3_column_bytes16(sqlite3_stmt *pStmt, int i){
|
| + int val = sqlite3_value_bytes16( columnMem(pStmt,i) );
|
| + columnMallocFailure(pStmt);
|
| + return val;
|
| +}
|
| +SQLITE_API double SQLITE_STDCALL sqlite3_column_double(sqlite3_stmt *pStmt, int i){
|
| + double val = sqlite3_value_double( columnMem(pStmt,i) );
|
| + columnMallocFailure(pStmt);
|
| + return val;
|
| +}
|
| +SQLITE_API int SQLITE_STDCALL sqlite3_column_int(sqlite3_stmt *pStmt, int i){
|
| + int val = sqlite3_value_int( columnMem(pStmt,i) );
|
| + columnMallocFailure(pStmt);
|
| + return val;
|
| +}
|
| +SQLITE_API sqlite_int64 SQLITE_STDCALL sqlite3_column_int64(sqlite3_stmt *pStmt, int i){
|
| + sqlite_int64 val = sqlite3_value_int64( columnMem(pStmt,i) );
|
| + columnMallocFailure(pStmt);
|
| + return val;
|
| +}
|
| +SQLITE_API const unsigned char *SQLITE_STDCALL sqlite3_column_text(sqlite3_stmt *pStmt, int i){
|
| + const unsigned char *val = sqlite3_value_text( columnMem(pStmt,i) );
|
| + columnMallocFailure(pStmt);
|
| + return val;
|
| +}
|
| +SQLITE_API sqlite3_value *SQLITE_STDCALL sqlite3_column_value(sqlite3_stmt *pStmt, int i){
|
| + Mem *pOut = columnMem(pStmt, i);
|
| + if( pOut->flags&MEM_Static ){
|
| + pOut->flags &= ~MEM_Static;
|
| + pOut->flags |= MEM_Ephem;
|
| + }
|
| + columnMallocFailure(pStmt);
|
| + return (sqlite3_value *)pOut;
|
| +}
|
| +#ifndef SQLITE_OMIT_UTF16
|
| +SQLITE_API const void *SQLITE_STDCALL sqlite3_column_text16(sqlite3_stmt *pStmt, int i){
|
| + const void *val = sqlite3_value_text16( columnMem(pStmt,i) );
|
| + columnMallocFailure(pStmt);
|
| + return val;
|
| +}
|
| +#endif /* SQLITE_OMIT_UTF16 */
|
| +SQLITE_API int SQLITE_STDCALL sqlite3_column_type(sqlite3_stmt *pStmt, int i){
|
| + int iType = sqlite3_value_type( columnMem(pStmt,i) );
|
| + columnMallocFailure(pStmt);
|
| + return iType;
|
| +}
|
| +
|
| +/*
|
| +** Convert the N-th element of pStmt->pColName[] into a string using
|
| +** xFunc() then return that string. If N is out of range, return 0.
|
| +**
|
| +** There are up to 5 names for each column. useType determines which
|
| +** name is returned. Here are the names:
|
| +**
|
| +** 0 The column name as it should be displayed for output
|
| +** 1 The datatype name for the column
|
| +** 2 The name of the database that the column derives from
|
| +** 3 The name of the table that the column derives from
|
| +** 4 The name of the table column that the result column derives from
|
| +**
|
| +** If the result is not a simple column reference (if it is an expression
|
| +** or a constant) then useTypes 2, 3, and 4 return NULL.
|
| +*/
|
| +static const void *columnName(
|
| + sqlite3_stmt *pStmt,
|
| + int N,
|
| + const void *(*xFunc)(Mem*),
|
| + int useType
|
| +){
|
| + const void *ret;
|
| + Vdbe *p;
|
| + int n;
|
| + sqlite3 *db;
|
| +#ifdef SQLITE_ENABLE_API_ARMOR
|
| + if( pStmt==0 ){
|
| + (void)SQLITE_MISUSE_BKPT;
|
| + return 0;
|
| + }
|
| +#endif
|
| + ret = 0;
|
| + p = (Vdbe *)pStmt;
|
| + db = p->db;
|
| + assert( db!=0 );
|
| + n = sqlite3_column_count(pStmt);
|
| + if( N<n && N>=0 ){
|
| + N += useType*n;
|
| + sqlite3_mutex_enter(db->mutex);
|
| + assert( db->mallocFailed==0 );
|
| + ret = xFunc(&p->aColName[N]);
|
| + /* A malloc may have failed inside of the xFunc() call. If this
|
| + ** is the case, clear the mallocFailed flag and return NULL.
|
| + */
|
| + if( db->mallocFailed ){
|
| + db->mallocFailed = 0;
|
| + ret = 0;
|
| + }
|
| + sqlite3_mutex_leave(db->mutex);
|
| + }
|
| + return ret;
|
| +}
|
| +
|
| +/*
|
| +** Return the name of the Nth column of the result set returned by SQL
|
| +** statement pStmt.
|
| +*/
|
| +SQLITE_API const char *SQLITE_STDCALL sqlite3_column_name(sqlite3_stmt *pStmt, int N){
|
| + return columnName(
|
| + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_NAME);
|
| +}
|
| +#ifndef SQLITE_OMIT_UTF16
|
| +SQLITE_API const void *SQLITE_STDCALL sqlite3_column_name16(sqlite3_stmt *pStmt, int N){
|
| + return columnName(
|
| + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_NAME);
|
| +}
|
| +#endif
|
| +
|
| +/*
|
| +** Constraint: If you have ENABLE_COLUMN_METADATA then you must
|
| +** not define OMIT_DECLTYPE.
|
| +*/
|
| +#if defined(SQLITE_OMIT_DECLTYPE) && defined(SQLITE_ENABLE_COLUMN_METADATA)
|
| +# error "Must not define both SQLITE_OMIT_DECLTYPE \
|
| + and SQLITE_ENABLE_COLUMN_METADATA"
|
| +#endif
|
| +
|
| +#ifndef SQLITE_OMIT_DECLTYPE
|
| +/*
|
| +** Return the column declaration type (if applicable) of the 'i'th column
|
| +** of the result set of SQL statement pStmt.
|
| +*/
|
| +SQLITE_API const char *SQLITE_STDCALL sqlite3_column_decltype(sqlite3_stmt *pStmt, int N){
|
| + return columnName(
|
| + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_DECLTYPE);
|
| +}
|
| +#ifndef SQLITE_OMIT_UTF16
|
| +SQLITE_API const void *SQLITE_STDCALL sqlite3_column_decltype16(sqlite3_stmt *pStmt, int N){
|
| + return columnName(
|
| + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_DECLTYPE);
|
| +}
|
| +#endif /* SQLITE_OMIT_UTF16 */
|
| +#endif /* SQLITE_OMIT_DECLTYPE */
|
| +
|
| +#ifdef SQLITE_ENABLE_COLUMN_METADATA
|
| +/*
|
| +** Return the name of the database from which a result column derives.
|
| +** NULL is returned if the result column is an expression or constant or
|
| +** anything else which is not an unambiguous reference to a database column.
|
| +*/
|
| +SQLITE_API const char *SQLITE_STDCALL sqlite3_column_database_name(sqlite3_stmt *pStmt, int N){
|
| + return columnName(
|
| + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_DATABASE);
|
| +}
|
| +#ifndef SQLITE_OMIT_UTF16
|
| +SQLITE_API const void *SQLITE_STDCALL sqlite3_column_database_name16(sqlite3_stmt *pStmt, int N){
|
| + return columnName(
|
| + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_DATABASE);
|
| +}
|
| +#endif /* SQLITE_OMIT_UTF16 */
|
| +
|
| +/*
|
| +** Return the name of the table from which a result column derives.
|
| +** NULL is returned if the result column is an expression or constant or
|
| +** anything else which is not an unambiguous reference to a database column.
|
| +*/
|
| +SQLITE_API const char *SQLITE_STDCALL sqlite3_column_table_name(sqlite3_stmt *pStmt, int N){
|
| + return columnName(
|
| + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_TABLE);
|
| +}
|
| +#ifndef SQLITE_OMIT_UTF16
|
| +SQLITE_API const void *SQLITE_STDCALL sqlite3_column_table_name16(sqlite3_stmt *pStmt, int N){
|
| + return columnName(
|
| + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_TABLE);
|
| +}
|
| +#endif /* SQLITE_OMIT_UTF16 */
|
| +
|
| +/*
|
| +** Return the name of the table column from which a result column derives.
|
| +** NULL is returned if the result column is an expression or constant or
|
| +** anything else which is not an unambiguous reference to a database column.
|
| +*/
|
| +SQLITE_API const char *SQLITE_STDCALL sqlite3_column_origin_name(sqlite3_stmt *pStmt, int N){
|
| + return columnName(
|
| + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_COLUMN);
|
| +}
|
| +#ifndef SQLITE_OMIT_UTF16
|
| +SQLITE_API const void *SQLITE_STDCALL sqlite3_column_origin_name16(sqlite3_stmt *pStmt, int N){
|
| + return columnName(
|
| + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_COLUMN);
|
| +}
|
| +#endif /* SQLITE_OMIT_UTF16 */
|
| +#endif /* SQLITE_ENABLE_COLUMN_METADATA */
|
| +
|
| +
|
| +/******************************* sqlite3_bind_ ***************************
|
| +**
|
| +** Routines used to attach values to wildcards in a compiled SQL statement.
|
| +*/
|
| +/*
|
| +** Unbind the value bound to variable i in virtual machine p. This is the
|
| +** the same as binding a NULL value to the column. If the "i" parameter is
|
| +** out of range, then SQLITE_RANGE is returned. Othewise SQLITE_OK.
|
| +**
|
| +** A successful evaluation of this routine acquires the mutex on p.
|
| +** the mutex is released if any kind of error occurs.
|
| +**
|
| +** The error code stored in database p->db is overwritten with the return
|
| +** value in any case.
|
| +*/
|
| +static int vdbeUnbind(Vdbe *p, int i){
|
| + Mem *pVar;
|
| + if( vdbeSafetyNotNull(p) ){
|
| + return SQLITE_MISUSE_BKPT;
|
| + }
|
| + sqlite3_mutex_enter(p->db->mutex);
|
| + if( p->magic!=VDBE_MAGIC_RUN || p->pc>=0 ){
|
| + sqlite3Error(p->db, SQLITE_MISUSE);
|
| + sqlite3_mutex_leave(p->db->mutex);
|
| + sqlite3_log(SQLITE_MISUSE,
|
| + "bind on a busy prepared statement: [%s]", p->zSql);
|
| + return SQLITE_MISUSE_BKPT;
|
| + }
|
| + if( i<1 || i>p->nVar ){
|
| + sqlite3Error(p->db, SQLITE_RANGE);
|
| + sqlite3_mutex_leave(p->db->mutex);
|
| + return SQLITE_RANGE;
|
| + }
|
| + i--;
|
| + pVar = &p->aVar[i];
|
| + sqlite3VdbeMemRelease(pVar);
|
| + pVar->flags = MEM_Null;
|
| + sqlite3Error(p->db, SQLITE_OK);
|
| +
|
| + /* If the bit corresponding to this variable in Vdbe.expmask is set, then
|
| + ** binding a new value to this variable invalidates the current query plan.
|
| + **
|
| + ** IMPLEMENTATION-OF: R-48440-37595 If the specific value bound to host
|
| + ** parameter in the WHERE clause might influence the choice of query plan
|
| + ** for a statement, then the statement will be automatically recompiled,
|
| + ** as if there had been a schema change, on the first sqlite3_step() call
|
| + ** following any change to the bindings of that parameter.
|
| + */
|
| + if( p->isPrepareV2 &&
|
| + ((i<32 && p->expmask & ((u32)1 << i)) || p->expmask==0xffffffff)
|
| + ){
|
| + p->expired = 1;
|
| + }
|
| + return SQLITE_OK;
|
| +}
|
| +
|
| +/*
|
| +** Bind a text or BLOB value.
|
| +*/
|
| +static int bindText(
|
| + sqlite3_stmt *pStmt, /* The statement to bind against */
|
| + int i, /* Index of the parameter to bind */
|
| + const void *zData, /* Pointer to the data to be bound */
|
| + int nData, /* Number of bytes of data to be bound */
|
| + void (*xDel)(void*), /* Destructor for the data */
|
| + u8 encoding /* Encoding for the data */
|
| +){
|
| + Vdbe *p = (Vdbe *)pStmt;
|
| + Mem *pVar;
|
| + int rc;
|
| +
|
| + rc = vdbeUnbind(p, i);
|
| + if( rc==SQLITE_OK ){
|
| + if( zData!=0 ){
|
| + pVar = &p->aVar[i-1];
|
| + rc = sqlite3VdbeMemSetStr(pVar, zData, nData, encoding, xDel);
|
| + if( rc==SQLITE_OK && encoding!=0 ){
|
| + rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db));
|
| + }
|
| + sqlite3Error(p->db, rc);
|
| + rc = sqlite3ApiExit(p->db, rc);
|
| + }
|
| + sqlite3_mutex_leave(p->db->mutex);
|
| + }else if( xDel!=SQLITE_STATIC && xDel!=SQLITE_TRANSIENT ){
|
| + xDel((void*)zData);
|
| + }
|
| + return rc;
|
| +}
|
| +
|
| +
|
| +/*
|
| +** Bind a blob value to an SQL statement variable.
|
| +*/
|
| +SQLITE_API int SQLITE_STDCALL sqlite3_bind_blob(
|
| + sqlite3_stmt *pStmt,
|
| + int i,
|
| + const void *zData,
|
| + int nData,
|
| + void (*xDel)(void*)
|
| +){
|
| + return bindText(pStmt, i, zData, nData, xDel, 0);
|
| +}
|
| +SQLITE_API int SQLITE_STDCALL sqlite3_bind_blob64(
|
| + sqlite3_stmt *pStmt,
|
| + int i,
|
| + const void *zData,
|
| + sqlite3_uint64 nData,
|
| + void (*xDel)(void*)
|
| +){
|
| + assert( xDel!=SQLITE_DYNAMIC );
|
| + if( nData>0x7fffffff ){
|
| + return invokeValueDestructor(zData, xDel, 0);
|
| + }else{
|
| + return bindText(pStmt, i, zData, (int)nData, xDel, 0);
|
| + }
|
| +}
|
| +SQLITE_API int SQLITE_STDCALL sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){
|
| + int rc;
|
| + Vdbe *p = (Vdbe *)pStmt;
|
| + rc = vdbeUnbind(p, i);
|
| + if( rc==SQLITE_OK ){
|
| + sqlite3VdbeMemSetDouble(&p->aVar[i-1], rValue);
|
| + sqlite3_mutex_leave(p->db->mutex);
|
| + }
|
| + return rc;
|
| +}
|
| +SQLITE_API int SQLITE_STDCALL sqlite3_bind_int(sqlite3_stmt *p, int i, int iValue){
|
| + return sqlite3_bind_int64(p, i, (i64)iValue);
|
| +}
|
| +SQLITE_API int SQLITE_STDCALL sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValue){
|
| + int rc;
|
| + Vdbe *p = (Vdbe *)pStmt;
|
| + rc = vdbeUnbind(p, i);
|
| + if( rc==SQLITE_OK ){
|
| + sqlite3VdbeMemSetInt64(&p->aVar[i-1], iValue);
|
| + sqlite3_mutex_leave(p->db->mutex);
|
| + }
|
| + return rc;
|
| +}
|
| +SQLITE_API int SQLITE_STDCALL sqlite3_bind_null(sqlite3_stmt *pStmt, int i){
|
| + int rc;
|
| + Vdbe *p = (Vdbe*)pStmt;
|
| + rc = vdbeUnbind(p, i);
|
| + if( rc==SQLITE_OK ){
|
| + sqlite3_mutex_leave(p->db->mutex);
|
| + }
|
| + return rc;
|
| +}
|
| +SQLITE_API int SQLITE_STDCALL sqlite3_bind_text(
|
| + sqlite3_stmt *pStmt,
|
| + int i,
|
| + const char *zData,
|
| + int nData,
|
| + void (*xDel)(void*)
|
| +){
|
| + return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF8);
|
| +}
|
| +SQLITE_API int SQLITE_STDCALL sqlite3_bind_text64(
|
| + sqlite3_stmt *pStmt,
|
| + int i,
|
| + const char *zData,
|
| + sqlite3_uint64 nData,
|
| + void (*xDel)(void*),
|
| + unsigned char enc
|
| +){
|
| + assert( xDel!=SQLITE_DYNAMIC );
|
| + if( nData>0x7fffffff ){
|
| + return invokeValueDestructor(zData, xDel, 0);
|
| + }else{
|
| + if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE;
|
| + return bindText(pStmt, i, zData, (int)nData, xDel, enc);
|
| + }
|
| +}
|
| +#ifndef SQLITE_OMIT_UTF16
|
| +SQLITE_API int SQLITE_STDCALL sqlite3_bind_text16(
|
| + sqlite3_stmt *pStmt,
|
| + int i,
|
| + const void *zData,
|
| + int nData,
|
| + void (*xDel)(void*)
|
| +){
|
| + return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF16NATIVE);
|
| +}
|
| +#endif /* SQLITE_OMIT_UTF16 */
|
| +SQLITE_API int SQLITE_STDCALL sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){
|
| + int rc;
|
| + switch( sqlite3_value_type((sqlite3_value*)pValue) ){
|
| + case SQLITE_INTEGER: {
|
| + rc = sqlite3_bind_int64(pStmt, i, pValue->u.i);
|
| + break;
|
| + }
|
| + case SQLITE_FLOAT: {
|
| + rc = sqlite3_bind_double(pStmt, i, pValue->u.r);
|
| + break;
|
| + }
|
| + case SQLITE_BLOB: {
|
| + if( pValue->flags & MEM_Zero ){
|
| + rc = sqlite3_bind_zeroblob(pStmt, i, pValue->u.nZero);
|
| + }else{
|
| + rc = sqlite3_bind_blob(pStmt, i, pValue->z, pValue->n,SQLITE_TRANSIENT);
|
| + }
|
| + break;
|
| + }
|
| + case SQLITE_TEXT: {
|
| + rc = bindText(pStmt,i, pValue->z, pValue->n, SQLITE_TRANSIENT,
|
| + pValue->enc);
|
| + break;
|
| + }
|
| + default: {
|
| + rc = sqlite3_bind_null(pStmt, i);
|
| + break;
|
| + }
|
| + }
|
| + return rc;
|
| +}
|
| +SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){
|
| + int rc;
|
| + Vdbe *p = (Vdbe *)pStmt;
|
| + rc = vdbeUnbind(p, i);
|
| + if( rc==SQLITE_OK ){
|
| + sqlite3VdbeMemSetZeroBlob(&p->aVar[i-1], n);
|
| + sqlite3_mutex_leave(p->db->mutex);
|
| + }
|
| + return rc;
|
| +}
|
| +SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob64(sqlite3_stmt *pStmt, int i, sqlite3_uint64 n){
|
| + int rc;
|
| + Vdbe *p = (Vdbe *)pStmt;
|
| + sqlite3_mutex_enter(p->db->mutex);
|
| + if( n>(u64)p->db->aLimit[SQLITE_LIMIT_LENGTH] ){
|
| + rc = SQLITE_TOOBIG;
|
| + }else{
|
| + assert( (n & 0x7FFFFFFF)==n );
|
| + rc = sqlite3_bind_zeroblob(pStmt, i, n);
|
| + }
|
| + rc = sqlite3ApiExit(p->db, rc);
|
| + sqlite3_mutex_leave(p->db->mutex);
|
| + return rc;
|
| +}
|
| +
|
| +/*
|
| +** Return the number of wildcards that can be potentially bound to.
|
| +** This routine is added to support DBD::SQLite.
|
| +*/
|
| +SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_count(sqlite3_stmt *pStmt){
|
| + Vdbe *p = (Vdbe*)pStmt;
|
| + return p ? p->nVar : 0;
|
| +}
|
| +
|
| +/*
|
| +** Return the name of a wildcard parameter. Return NULL if the index
|
| +** is out of range or if the wildcard is unnamed.
|
| +**
|
| +** The result is always UTF-8.
|
| +*/
|
| +SQLITE_API const char *SQLITE_STDCALL sqlite3_bind_parameter_name(sqlite3_stmt *pStmt, int i){
|
| + Vdbe *p = (Vdbe*)pStmt;
|
| + if( p==0 || i<1 || i>p->nzVar ){
|
| + return 0;
|
| + }
|
| + return p->azVar[i-1];
|
| +}
|
| +
|
| +/*
|
| +** Given a wildcard parameter name, return the index of the variable
|
| +** with that name. If there is no variable with the given name,
|
| +** return 0.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3VdbeParameterIndex(Vdbe *p, const char *zName, int nName){
|
| + int i;
|
| + if( p==0 ){
|
| + return 0;
|
| + }
|
| + if( zName ){
|
| + for(i=0; i<p->nzVar; i++){
|
| + const char *z = p->azVar[i];
|
| + if( z && strncmp(z,zName,nName)==0 && z[nName]==0 ){
|
| + return i+1;
|
| + }
|
| + }
|
| + }
|
| + return 0;
|
| +}
|
| +SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_index(sqlite3_stmt *pStmt, const char *zName){
|
| + return sqlite3VdbeParameterIndex((Vdbe*)pStmt, zName, sqlite3Strlen30(zName));
|
| +}
|
| +
|
| +/*
|
| +** Transfer all bindings from the first statement over to the second.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){
|
| + Vdbe *pFrom = (Vdbe*)pFromStmt;
|
| + Vdbe *pTo = (Vdbe*)pToStmt;
|
| + int i;
|
| + assert( pTo->db==pFrom->db );
|
| + assert( pTo->nVar==pFrom->nVar );
|
| + sqlite3_mutex_enter(pTo->db->mutex);
|
| + for(i=0; i<pFrom->nVar; i++){
|
| + sqlite3VdbeMemMove(&pTo->aVar[i], &pFrom->aVar[i]);
|
| + }
|
| + sqlite3_mutex_leave(pTo->db->mutex);
|
| + return SQLITE_OK;
|
| +}
|
| +
|
| +#ifndef SQLITE_OMIT_DEPRECATED
|
| +/*
|
| +** Deprecated external interface. Internal/core SQLite code
|
| +** should call sqlite3TransferBindings.
|
| +**
|
| +** It is misuse to call this routine with statements from different
|
| +** database connections. But as this is a deprecated interface, we
|
| +** will not bother to check for that condition.
|
| +**
|
| +** If the two statements contain a different number of bindings, then
|
| +** an SQLITE_ERROR is returned. Nothing else can go wrong, so otherwise
|
| +** SQLITE_OK is returned.
|
| +*/
|
| +SQLITE_API int SQLITE_STDCALL sqlite3_transfer_bindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){
|
| + Vdbe *pFrom = (Vdbe*)pFromStmt;
|
| + Vdbe *pTo = (Vdbe*)pToStmt;
|
| + if( pFrom->nVar!=pTo->nVar ){
|
| + return SQLITE_ERROR;
|
| + }
|
| + if( pTo->isPrepareV2 && pTo->expmask ){
|
| + pTo->expired = 1;
|
| + }
|
| + if( pFrom->isPrepareV2 && pFrom->expmask ){
|
| + pFrom->expired = 1;
|
| + }
|
| + return sqlite3TransferBindings(pFromStmt, pToStmt);
|
| +}
|
| +#endif
|
| +
|
| +/*
|
| +** Return the sqlite3* database handle to which the prepared statement given
|
| +** in the argument belongs. This is the same database handle that was
|
| +** the first argument to the sqlite3_prepare() that was used to create
|
| +** the statement in the first place.
|
| +*/
|
| +SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_db_handle(sqlite3_stmt *pStmt){
|
| + return pStmt ? ((Vdbe*)pStmt)->db : 0;
|
| +}
|
| +
|
| +/*
|
| +** Return true if the prepared statement is guaranteed to not modify the
|
| +** database.
|
| +*/
|
| +SQLITE_API int SQLITE_STDCALL sqlite3_stmt_readonly(sqlite3_stmt *pStmt){
|
| + return pStmt ? ((Vdbe*)pStmt)->readOnly : 1;
|
| +}
|
| +
|
| +/*
|
| +** Return true if the prepared statement is in need of being reset.
|
| +*/
|
| +SQLITE_API int SQLITE_STDCALL sqlite3_stmt_busy(sqlite3_stmt *pStmt){
|
| + Vdbe *v = (Vdbe*)pStmt;
|
| + return v!=0 && v->pc>=0 && v->magic==VDBE_MAGIC_RUN;
|
| +}
|
| +
|
| +/*
|
| +** Return a pointer to the next prepared statement after pStmt associated
|
| +** with database connection pDb. If pStmt is NULL, return the first
|
| +** prepared statement for the database connection. Return NULL if there
|
| +** are no more.
|
| +*/
|
| +SQLITE_API sqlite3_stmt *SQLITE_STDCALL sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt){
|
| + sqlite3_stmt *pNext;
|
| +#ifdef SQLITE_ENABLE_API_ARMOR
|
| + if( !sqlite3SafetyCheckOk(pDb) ){
|
| + (void)SQLITE_MISUSE_BKPT;
|
| + return 0;
|
| + }
|
| +#endif
|
| + sqlite3_mutex_enter(pDb->mutex);
|
| + if( pStmt==0 ){
|
| + pNext = (sqlite3_stmt*)pDb->pVdbe;
|
| + }else{
|
| + pNext = (sqlite3_stmt*)((Vdbe*)pStmt)->pNext;
|
| + }
|
| + sqlite3_mutex_leave(pDb->mutex);
|
| + return pNext;
|
| +}
|
| +
|
| +/*
|
| +** Return the value of a status counter for a prepared statement
|
| +*/
|
| +SQLITE_API int SQLITE_STDCALL sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){
|
| + Vdbe *pVdbe = (Vdbe*)pStmt;
|
| + u32 v;
|
| +#ifdef SQLITE_ENABLE_API_ARMOR
|
| + if( !pStmt ){
|
| + (void)SQLITE_MISUSE_BKPT;
|
| + return 0;
|
| + }
|
| +#endif
|
| + v = pVdbe->aCounter[op];
|
| + if( resetFlag ) pVdbe->aCounter[op] = 0;
|
| + return (int)v;
|
| +}
|
| +
|
| +#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
| +/*
|
| +** Return status data for a single loop within query pStmt.
|
| +*/
|
| +SQLITE_API int SQLITE_STDCALL sqlite3_stmt_scanstatus(
|
| + sqlite3_stmt *pStmt, /* Prepared statement being queried */
|
| + int idx, /* Index of loop to report on */
|
| + int iScanStatusOp, /* Which metric to return */
|
| + void *pOut /* OUT: Write the answer here */
|
| +){
|
| + Vdbe *p = (Vdbe*)pStmt;
|
| + ScanStatus *pScan;
|
| + if( idx<0 || idx>=p->nScan ) return 1;
|
| + pScan = &p->aScan[idx];
|
| + switch( iScanStatusOp ){
|
| + case SQLITE_SCANSTAT_NLOOP: {
|
| + *(sqlite3_int64*)pOut = p->anExec[pScan->addrLoop];
|
| + break;
|
| + }
|
| + case SQLITE_SCANSTAT_NVISIT: {
|
| + *(sqlite3_int64*)pOut = p->anExec[pScan->addrVisit];
|
| + break;
|
| + }
|
| + case SQLITE_SCANSTAT_EST: {
|
| + double r = 1.0;
|
| + LogEst x = pScan->nEst;
|
| + while( x<100 ){
|
| + x += 10;
|
| + r *= 0.5;
|
| + }
|
| + *(double*)pOut = r*sqlite3LogEstToInt(x);
|
| + break;
|
| + }
|
| + case SQLITE_SCANSTAT_NAME: {
|
| + *(const char**)pOut = pScan->zName;
|
| + break;
|
| + }
|
| + case SQLITE_SCANSTAT_EXPLAIN: {
|
| + if( pScan->addrExplain ){
|
| + *(const char**)pOut = p->aOp[ pScan->addrExplain ].p4.z;
|
| + }else{
|
| + *(const char**)pOut = 0;
|
| + }
|
| + break;
|
| + }
|
| + case SQLITE_SCANSTAT_SELECTID: {
|
| + if( pScan->addrExplain ){
|
| + *(int*)pOut = p->aOp[ pScan->addrExplain ].p1;
|
| + }else{
|
| + *(int*)pOut = -1;
|
| + }
|
| + break;
|
| + }
|
| + default: {
|
| + return 1;
|
| + }
|
| + }
|
| + return 0;
|
| +}
|
| +
|
| +/*
|
| +** Zero all counters associated with the sqlite3_stmt_scanstatus() data.
|
| +*/
|
| +SQLITE_API void SQLITE_STDCALL sqlite3_stmt_scanstatus_reset(sqlite3_stmt *pStmt){
|
| + Vdbe *p = (Vdbe*)pStmt;
|
| + memset(p->anExec, 0, p->nOp * sizeof(i64));
|
| +}
|
| +#endif /* SQLITE_ENABLE_STMT_SCANSTATUS */
|
| +
|
| +/************** End of vdbeapi.c *********************************************/
|
| +/************** Begin file vdbetrace.c ***************************************/
|
| +/*
|
| +** 2009 November 25
|
| +**
|
| +** 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.
|
| +**
|
| +*************************************************************************
|
| +**
|
| +** This file contains code used to insert the values of host parameters
|
| +** (aka "wildcards") into the SQL text output by sqlite3_trace().
|
| +**
|
| +** The Vdbe parse-tree explainer is also found here.
|
| +*/
|
| +/* #include "sqliteInt.h" */
|
| +/* #include "vdbeInt.h" */
|
| +
|
| +#ifndef SQLITE_OMIT_TRACE
|
| +
|
| +/*
|
| +** zSql is a zero-terminated string of UTF-8 SQL text. Return the number of
|
| +** bytes in this text up to but excluding the first character in
|
| +** a host parameter. If the text contains no host parameters, return
|
| +** the total number of bytes in the text.
|
| +*/
|
| +static int findNextHostParameter(const char *zSql, int *pnToken){
|
| + int tokenType;
|
| + int nTotal = 0;
|
| + int n;
|
| +
|
| + *pnToken = 0;
|
| + while( zSql[0] ){
|
| + n = sqlite3GetToken((u8*)zSql, &tokenType);
|
| + assert( n>0 && tokenType!=TK_ILLEGAL );
|
| + if( tokenType==TK_VARIABLE ){
|
| + *pnToken = n;
|
| + break;
|
| + }
|
| + nTotal += n;
|
| + zSql += n;
|
| + }
|
| + return nTotal;
|
| +}
|
| +
|
| +/*
|
| +** This function returns a pointer to a nul-terminated string in memory
|
| +** obtained from sqlite3DbMalloc(). If sqlite3.nVdbeExec is 1, then the
|
| +** string contains a copy of zRawSql but with host parameters expanded to
|
| +** their current bindings. Or, if sqlite3.nVdbeExec is greater than 1,
|
| +** then the returned string holds a copy of zRawSql with "-- " prepended
|
| +** to each line of text.
|
| +**
|
| +** If the SQLITE_TRACE_SIZE_LIMIT macro is defined to an integer, then
|
| +** then long strings and blobs are truncated to that many bytes. This
|
| +** can be used to prevent unreasonably large trace strings when dealing
|
| +** with large (multi-megabyte) strings and blobs.
|
| +**
|
| +** The calling function is responsible for making sure the memory returned
|
| +** is eventually freed.
|
| +**
|
| +** ALGORITHM: Scan the input string looking for host parameters in any of
|
| +** these forms: ?, ?N, $A, @A, :A. Take care to avoid text within
|
| +** string literals, quoted identifier names, and comments. For text forms,
|
| +** the host parameter index is found by scanning the prepared
|
| +** statement for the corresponding OP_Variable opcode. Once the host
|
| +** parameter index is known, locate the value in p->aVar[]. Then render
|
| +** the value as a literal in place of the host parameter name.
|
| +*/
|
| +SQLITE_PRIVATE char *sqlite3VdbeExpandSql(
|
| + Vdbe *p, /* The prepared statement being evaluated */
|
| + const char *zRawSql /* Raw text of the SQL statement */
|
| +){
|
| + sqlite3 *db; /* The database connection */
|
| + int idx = 0; /* Index of a host parameter */
|
| + int nextIndex = 1; /* Index of next ? host parameter */
|
| + int n; /* Length of a token prefix */
|
| + int nToken; /* Length of the parameter token */
|
| + int i; /* Loop counter */
|
| + Mem *pVar; /* Value of a host parameter */
|
| + StrAccum out; /* Accumulate the output here */
|
| + char zBase[100]; /* Initial working space */
|
| +
|
| + db = p->db;
|
| + sqlite3StrAccumInit(&out, db, zBase, sizeof(zBase),
|
| + db->aLimit[SQLITE_LIMIT_LENGTH]);
|
| + if( db->nVdbeExec>1 ){
|
| + while( *zRawSql ){
|
| + const char *zStart = zRawSql;
|
| + while( *(zRawSql++)!='\n' && *zRawSql );
|
| + sqlite3StrAccumAppend(&out, "-- ", 3);
|
| + assert( (zRawSql - zStart) > 0 );
|
| + sqlite3StrAccumAppend(&out, zStart, (int)(zRawSql-zStart));
|
| + }
|
| + }else if( p->nVar==0 ){
|
| + sqlite3StrAccumAppend(&out, zRawSql, sqlite3Strlen30(zRawSql));
|
| + }else{
|
| + while( zRawSql[0] ){
|
| + n = findNextHostParameter(zRawSql, &nToken);
|
| + assert( n>0 );
|
| + sqlite3StrAccumAppend(&out, zRawSql, n);
|
| + zRawSql += n;
|
| + assert( zRawSql[0] || nToken==0 );
|
| + if( nToken==0 ) break;
|
| + if( zRawSql[0]=='?' ){
|
| + if( nToken>1 ){
|
| + assert( sqlite3Isdigit(zRawSql[1]) );
|
| + sqlite3GetInt32(&zRawSql[1], &idx);
|
| + }else{
|
| + idx = nextIndex;
|
| + }
|
| + }else{
|
| + assert( zRawSql[0]==':' || zRawSql[0]=='$' ||
|
| + zRawSql[0]=='@' || zRawSql[0]=='#' );
|
| + testcase( zRawSql[0]==':' );
|
| + testcase( zRawSql[0]=='$' );
|
| + testcase( zRawSql[0]=='@' );
|
| + testcase( zRawSql[0]=='#' );
|
| + idx = sqlite3VdbeParameterIndex(p, zRawSql, nToken);
|
| + assert( idx>0 );
|
| + }
|
| + zRawSql += nToken;
|
| + nextIndex = idx + 1;
|
| + assert( idx>0 && idx<=p->nVar );
|
| + pVar = &p->aVar[idx-1];
|
| + if( pVar->flags & MEM_Null ){
|
| + sqlite3StrAccumAppend(&out, "NULL", 4);
|
| + }else if( pVar->flags & MEM_Int ){
|
| + sqlite3XPrintf(&out, 0, "%lld", pVar->u.i);
|
| + }else if( pVar->flags & MEM_Real ){
|
| + sqlite3XPrintf(&out, 0, "%!.15g", pVar->u.r);
|
| + }else if( pVar->flags & MEM_Str ){
|
| + int nOut; /* Number of bytes of the string text to include in output */
|
| +#ifndef SQLITE_OMIT_UTF16
|
| + u8 enc = ENC(db);
|
| + Mem utf8;
|
| + if( enc!=SQLITE_UTF8 ){
|
| + memset(&utf8, 0, sizeof(utf8));
|
| + utf8.db = db;
|
| + sqlite3VdbeMemSetStr(&utf8, pVar->z, pVar->n, enc, SQLITE_STATIC);
|
| + sqlite3VdbeChangeEncoding(&utf8, SQLITE_UTF8);
|
| + pVar = &utf8;
|
| + }
|
| +#endif
|
| + nOut = pVar->n;
|
| +#ifdef SQLITE_TRACE_SIZE_LIMIT
|
| + if( nOut>SQLITE_TRACE_SIZE_LIMIT ){
|
| + nOut = SQLITE_TRACE_SIZE_LIMIT;
|
| + while( nOut<pVar->n && (pVar->z[nOut]&0xc0)==0x80 ){ nOut++; }
|
| + }
|
| +#endif
|
| + sqlite3XPrintf(&out, 0, "'%.*q'", nOut, pVar->z);
|
| +#ifdef SQLITE_TRACE_SIZE_LIMIT
|
| + if( nOut<pVar->n ){
|
| + sqlite3XPrintf(&out, 0, "/*+%d bytes*/", pVar->n-nOut);
|
| + }
|
| +#endif
|
| +#ifndef SQLITE_OMIT_UTF16
|
| + if( enc!=SQLITE_UTF8 ) sqlite3VdbeMemRelease(&utf8);
|
| +#endif
|
| + }else if( pVar->flags & MEM_Zero ){
|
| + sqlite3XPrintf(&out, 0, "zeroblob(%d)", pVar->u.nZero);
|
| + }else{
|
| + int nOut; /* Number of bytes of the blob to include in output */
|
| + assert( pVar->flags & MEM_Blob );
|
| + sqlite3StrAccumAppend(&out, "x'", 2);
|
| + nOut = pVar->n;
|
| +#ifdef SQLITE_TRACE_SIZE_LIMIT
|
| + if( nOut>SQLITE_TRACE_SIZE_LIMIT ) nOut = SQLITE_TRACE_SIZE_LIMIT;
|
| +#endif
|
| + for(i=0; i<nOut; i++){
|
| + sqlite3XPrintf(&out, 0, "%02x", pVar->z[i]&0xff);
|
| + }
|
| + sqlite3StrAccumAppend(&out, "'", 1);
|
| +#ifdef SQLITE_TRACE_SIZE_LIMIT
|
| + if( nOut<pVar->n ){
|
| + sqlite3XPrintf(&out, 0, "/*+%d bytes*/", pVar->n-nOut);
|
| + }
|
| +#endif
|
| + }
|
| + }
|
| + }
|
| + return sqlite3StrAccumFinish(&out);
|
| +}
|
| +
|
| +#endif /* #ifndef SQLITE_OMIT_TRACE */
|
| +
|
| +/************** End of vdbetrace.c *******************************************/
|
| +/************** Begin file vdbe.c ********************************************/
|
| +/*
|
| +** 2001 September 15
|
| +**
|
| +** 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.
|
| +**
|
| +*************************************************************************
|
| +** The code in this file implements the function that runs the
|
| +** bytecode of a prepared statement.
|
| +**
|
| +** Various scripts scan this source file in order to generate HTML
|
| +** documentation, headers files, or other derived files. The formatting
|
| +** of the code in this file is, therefore, important. See other comments
|
| +** in this file for details. If in doubt, do not deviate from existing
|
| +** commenting and indentation practices when changing or adding code.
|
| +*/
|
| +/* #include "sqliteInt.h" */
|
| +/* #include "vdbeInt.h" */
|
| +
|
| +/*
|
| +** Invoke this macro on memory cells just prior to changing the
|
| +** value of the cell. This macro verifies that shallow copies are
|
| +** not misused. A shallow copy of a string or blob just copies a
|
| +** pointer to the string or blob, not the content. If the original
|
| +** is changed while the copy is still in use, the string or blob might
|
| +** be changed out from under the copy. This macro verifies that nothing
|
| +** like that ever happens.
|
| +*/
|
| +#ifdef SQLITE_DEBUG
|
| +# define memAboutToChange(P,M) sqlite3VdbeMemAboutToChange(P,M)
|
| +#else
|
| +# define memAboutToChange(P,M)
|
| +#endif
|
| +
|
| +/*
|
| +** The following global variable is incremented every time a cursor
|
| +** moves, either by the OP_SeekXX, OP_Next, or OP_Prev opcodes. The test
|
| +** procedures use this information to make sure that indices are
|
| +** working correctly. This variable has no function other than to
|
| +** help verify the correct operation of the library.
|
| +*/
|
| +#ifdef SQLITE_TEST
|
| +SQLITE_API int sqlite3_search_count = 0;
|
| +#endif
|
| +
|
| +/*
|
| +** When this global variable is positive, it gets decremented once before
|
| +** each instruction in the VDBE. When it reaches zero, the u1.isInterrupted
|
| +** field of the sqlite3 structure is set in order to simulate an interrupt.
|
| +**
|
| +** This facility is used for testing purposes only. It does not function
|
| +** in an ordinary build.
|
| +*/
|
| +#ifdef SQLITE_TEST
|
| +SQLITE_API int sqlite3_interrupt_count = 0;
|
| +#endif
|
| +
|
| +/*
|
| +** The next global variable is incremented each type the OP_Sort opcode
|
| +** is executed. The test procedures use this information to make sure that
|
| +** sorting is occurring or not occurring at appropriate times. This variable
|
| +** has no function other than to help verify the correct operation of the
|
| +** library.
|
| +*/
|
| +#ifdef SQLITE_TEST
|
| +SQLITE_API int sqlite3_sort_count = 0;
|
| +#endif
|
| +
|
| +/*
|
| +** The next global variable records the size of the largest MEM_Blob
|
| +** or MEM_Str that has been used by a VDBE opcode. The test procedures
|
| +** use this information to make sure that the zero-blob functionality
|
| +** is working correctly. This variable has no function other than to
|
| +** help verify the correct operation of the library.
|
| +*/
|
| +#ifdef SQLITE_TEST
|
| +SQLITE_API int sqlite3_max_blobsize = 0;
|
| +static void updateMaxBlobsize(Mem *p){
|
| + if( (p->flags & (MEM_Str|MEM_Blob))!=0 && p->n>sqlite3_max_blobsize ){
|
| + sqlite3_max_blobsize = p->n;
|
| + }
|
| +}
|
| +#endif
|
| +
|
| +/*
|
| +** The next global variable is incremented each time the OP_Found opcode
|
| +** is executed. This is used to test whether or not the foreign key
|
| +** operation implemented using OP_FkIsZero is working. This variable
|
| +** has no function other than to help verify the correct operation of the
|
| +** library.
|
| +*/
|
| +#ifdef SQLITE_TEST
|
| +SQLITE_API int sqlite3_found_count = 0;
|
| +#endif
|
| +
|
| +/*
|
| +** Test a register to see if it exceeds the current maximum blob size.
|
| +** If it does, record the new maximum blob size.
|
| +*/
|
| +#if defined(SQLITE_TEST) && !defined(SQLITE_OMIT_BUILTIN_TEST)
|
| +# define UPDATE_MAX_BLOBSIZE(P) updateMaxBlobsize(P)
|
| +#else
|
| +# define UPDATE_MAX_BLOBSIZE(P)
|
| +#endif
|
| +
|
| +/*
|
| +** Invoke the VDBE coverage callback, if that callback is defined. This
|
| +** feature is used for test suite validation only and does not appear an
|
| +** production builds.
|
| +**
|
| +** M is an integer, 2 or 3, that indices how many different ways the
|
| +** branch can go. It is usually 2. "I" is the direction the branch
|
| +** goes. 0 means falls through. 1 means branch is taken. 2 means the
|
| +** second alternative branch is taken.
|
| +**
|
| +** iSrcLine is the source code line (from the __LINE__ macro) that
|
| +** generated the VDBE instruction. This instrumentation assumes that all
|
| +** source code is in a single file (the amalgamation). Special values 1
|
| +** and 2 for the iSrcLine parameter mean that this particular branch is
|
| +** always taken or never taken, respectively.
|
| +*/
|
| +#if !defined(SQLITE_VDBE_COVERAGE)
|
| +# define VdbeBranchTaken(I,M)
|
| +#else
|
| +# define VdbeBranchTaken(I,M) vdbeTakeBranch(pOp->iSrcLine,I,M)
|
| + static void vdbeTakeBranch(int iSrcLine, u8 I, u8 M){
|
| + if( iSrcLine<=2 && ALWAYS(iSrcLine>0) ){
|
| + M = iSrcLine;
|
| + /* Assert the truth of VdbeCoverageAlwaysTaken() and
|
| + ** VdbeCoverageNeverTaken() */
|
| + assert( (M & I)==I );
|
| + }else{
|
| + if( sqlite3GlobalConfig.xVdbeBranch==0 ) return; /*NO_TEST*/
|
| + sqlite3GlobalConfig.xVdbeBranch(sqlite3GlobalConfig.pVdbeBranchArg,
|
| + iSrcLine,I,M);
|
| + }
|
| + }
|
| +#endif
|
| +
|
| +/*
|
| +** Convert the given register into a string if it isn't one
|
| +** already. Return non-zero if a malloc() fails.
|
| +*/
|
| +#define Stringify(P, enc) \
|
| + if(((P)->flags&(MEM_Str|MEM_Blob))==0 && sqlite3VdbeMemStringify(P,enc,0)) \
|
| + { goto no_mem; }
|
| +
|
| +/*
|
| +** An ephemeral string value (signified by the MEM_Ephem flag) contains
|
| +** a pointer to a dynamically allocated string where some other entity
|
| +** is responsible for deallocating that string. Because the register
|
| +** does not control the string, it might be deleted without the register
|
| +** knowing it.
|
| +**
|
| +** This routine converts an ephemeral string into a dynamically allocated
|
| +** string that the register itself controls. In other words, it
|
| +** converts an MEM_Ephem string into a string with P.z==P.zMalloc.
|
| +*/
|
| +#define Deephemeralize(P) \
|
| + if( ((P)->flags&MEM_Ephem)!=0 \
|
| + && sqlite3VdbeMemMakeWriteable(P) ){ goto no_mem;}
|
| +
|
| +/* Return true if the cursor was opened using the OP_OpenSorter opcode. */
|
| +#define isSorter(x) ((x)->eCurType==CURTYPE_SORTER)
|
| +
|
| +/*
|
| +** Allocate VdbeCursor number iCur. Return a pointer to it. Return NULL
|
| +** if we run out of memory.
|
| +*/
|
| +static VdbeCursor *allocateCursor(
|
| + Vdbe *p, /* The virtual machine */
|
| + int iCur, /* Index of the new VdbeCursor */
|
| + int nField, /* Number of fields in the table or index */
|
| + int iDb, /* Database the cursor belongs to, or -1 */
|
| + u8 eCurType /* Type of the new cursor */
|
| +){
|
| + /* Find the memory cell that will be used to store the blob of memory
|
| + ** required for this VdbeCursor structure. It is convenient to use a
|
| + ** vdbe memory cell to manage the memory allocation required for a
|
| + ** VdbeCursor structure for the following reasons:
|
| + **
|
| + ** * Sometimes cursor numbers are used for a couple of different
|
| + ** purposes in a vdbe program. The different uses might require
|
| + ** different sized allocations. Memory cells provide growable
|
| + ** allocations.
|
| + **
|
| + ** * When using ENABLE_MEMORY_MANAGEMENT, memory cell buffers can
|
| + ** be freed lazily via the sqlite3_release_memory() API. This
|
| + ** minimizes the number of malloc calls made by the system.
|
| + **
|
| + ** Memory cells for cursors are allocated at the top of the address
|
| + ** space. Memory cell (p->nMem) corresponds to cursor 0. Space for
|
| + ** cursor 1 is managed by memory cell (p->nMem-1), etc.
|
| + */
|
| + Mem *pMem = &p->aMem[p->nMem-iCur];
|
| +
|
| + int nByte;
|
| + VdbeCursor *pCx = 0;
|
| + nByte =
|
| + ROUND8(sizeof(VdbeCursor)) + 2*sizeof(u32)*nField +
|
| + (eCurType==CURTYPE_BTREE?sqlite3BtreeCursorSize():0);
|
| +
|
| + assert( iCur<p->nCursor );
|
| + if( p->apCsr[iCur] ){
|
| + sqlite3VdbeFreeCursor(p, p->apCsr[iCur]);
|
| + p->apCsr[iCur] = 0;
|
| + }
|
| + if( SQLITE_OK==sqlite3VdbeMemClearAndResize(pMem, nByte) ){
|
| + p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->z;
|
| + memset(pCx, 0, sizeof(VdbeCursor));
|
| + pCx->eCurType = eCurType;
|
| + pCx->iDb = iDb;
|
| + pCx->nField = nField;
|
| + pCx->aOffset = &pCx->aType[nField];
|
| + if( eCurType==CURTYPE_BTREE ){
|
| + pCx->uc.pCursor = (BtCursor*)
|
| + &pMem->z[ROUND8(sizeof(VdbeCursor))+2*sizeof(u32)*nField];
|
| + sqlite3BtreeCursorZero(pCx->uc.pCursor);
|
| + }
|
| + }
|
| + return pCx;
|
| +}
|
| +
|
| +/*
|
| +** Try to convert a value into a numeric representation if we can
|
| +** do so without loss of information. In other words, if the string
|
| +** looks like a number, convert it into a number. If it does not
|
| +** look like a number, leave it alone.
|
| +**
|
| +** If the bTryForInt flag is true, then extra effort is made to give
|
| +** an integer representation. Strings that look like floating point
|
| +** values but which have no fractional component (example: '48.00')
|
| +** will have a MEM_Int representation when bTryForInt is true.
|
| +**
|
| +** If bTryForInt is false, then if the input string contains a decimal
|
| +** point or exponential notation, the result is only MEM_Real, even
|
| +** if there is an exact integer representation of the quantity.
|
| +*/
|
| +static void applyNumericAffinity(Mem *pRec, int bTryForInt){
|
| + double rValue;
|
| + i64 iValue;
|
| + u8 enc = pRec->enc;
|
| + assert( (pRec->flags & (MEM_Str|MEM_Int|MEM_Real))==MEM_Str );
|
| + if( sqlite3AtoF(pRec->z, &rValue, pRec->n, enc)==0 ) return;
|
| + if( 0==sqlite3Atoi64(pRec->z, &iValue, pRec->n, enc) ){
|
| + pRec->u.i = iValue;
|
| + pRec->flags |= MEM_Int;
|
| + }else{
|
| + pRec->u.r = rValue;
|
| + pRec->flags |= MEM_Real;
|
| + if( bTryForInt ) sqlite3VdbeIntegerAffinity(pRec);
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Processing is determine by the affinity parameter:
|
| +**
|
| +** SQLITE_AFF_INTEGER:
|
| +** SQLITE_AFF_REAL:
|
| +** SQLITE_AFF_NUMERIC:
|
| +** Try to convert pRec to an integer representation or a
|
| +** floating-point representation if an integer representation
|
| +** is not possible. Note that the integer representation is
|
| +** always preferred, even if the affinity is REAL, because
|
| +** an integer representation is more space efficient on disk.
|
| +**
|
| +** SQLITE_AFF_TEXT:
|
| +** Convert pRec to a text representation.
|
| +**
|
| +** SQLITE_AFF_BLOB:
|
| +** No-op. pRec is unchanged.
|
| +*/
|
| +static void applyAffinity(
|
| + Mem *pRec, /* The value to apply affinity to */
|
| + char affinity, /* The affinity to be applied */
|
| + u8 enc /* Use this text encoding */
|
| +){
|
| + if( affinity>=SQLITE_AFF_NUMERIC ){
|
| + assert( affinity==SQLITE_AFF_INTEGER || affinity==SQLITE_AFF_REAL
|
| + || affinity==SQLITE_AFF_NUMERIC );
|
| + if( (pRec->flags & MEM_Int)==0 ){
|
| + if( (pRec->flags & MEM_Real)==0 ){
|
| + if( pRec->flags & MEM_Str ) applyNumericAffinity(pRec,1);
|
| + }else{
|
| + sqlite3VdbeIntegerAffinity(pRec);
|
| + }
|
| + }
|
| + }else if( affinity==SQLITE_AFF_TEXT ){
|
| + /* Only attempt the conversion to TEXT if there is an integer or real
|
| + ** representation (blob and NULL do not get converted) but no string
|
| + ** representation.
|
| + */
|
| + if( 0==(pRec->flags&MEM_Str) && (pRec->flags&(MEM_Real|MEM_Int)) ){
|
| + sqlite3VdbeMemStringify(pRec, enc, 1);
|
| + }
|
| + pRec->flags &= ~(MEM_Real|MEM_Int);
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Try to convert the type of a function argument or a result column
|
| +** into a numeric representation. Use either INTEGER or REAL whichever
|
| +** is appropriate. But only do the conversion if it is possible without
|
| +** loss of information and return the revised type of the argument.
|
| +*/
|
| +SQLITE_API int SQLITE_STDCALL sqlite3_value_numeric_type(sqlite3_value *pVal){
|
| + int eType = sqlite3_value_type(pVal);
|
| + if( eType==SQLITE_TEXT ){
|
| + Mem *pMem = (Mem*)pVal;
|
| + applyNumericAffinity(pMem, 0);
|
| + eType = sqlite3_value_type(pVal);
|
| + }
|
| + return eType;
|
| +}
|
| +
|
| +/*
|
| +** Exported version of applyAffinity(). This one works on sqlite3_value*,
|
| +** not the internal Mem* type.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3ValueApplyAffinity(
|
| + sqlite3_value *pVal,
|
| + u8 affinity,
|
| + u8 enc
|
| +){
|
| + applyAffinity((Mem *)pVal, affinity, enc);
|
| +}
|
| +
|
| +/*
|
| +** pMem currently only holds a string type (or maybe a BLOB that we can
|
| +** interpret as a string if we want to). Compute its corresponding
|
| +** numeric type, if has one. Set the pMem->u.r and pMem->u.i fields
|
| +** accordingly.
|
| +*/
|
| +static u16 SQLITE_NOINLINE computeNumericType(Mem *pMem){
|
| + assert( (pMem->flags & (MEM_Int|MEM_Real))==0 );
|
| + assert( (pMem->flags & (MEM_Str|MEM_Blob))!=0 );
|
| + if( sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc)==0 ){
|
| + return 0;
|
| + }
|
| + if( sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc)==SQLITE_OK ){
|
| + return MEM_Int;
|
| + }
|
| + return MEM_Real;
|
| +}
|
| +
|
| +/*
|
| +** Return the numeric type for pMem, either MEM_Int or MEM_Real or both or
|
| +** none.
|
| +**
|
| +** Unlike applyNumericAffinity(), this routine does not modify pMem->flags.
|
| +** But it does set pMem->u.r and pMem->u.i appropriately.
|
| +*/
|
| +static u16 numericType(Mem *pMem){
|
| + if( pMem->flags & (MEM_Int|MEM_Real) ){
|
| + return pMem->flags & (MEM_Int|MEM_Real);
|
| + }
|
| + if( pMem->flags & (MEM_Str|MEM_Blob) ){
|
| + return computeNumericType(pMem);
|
| + }
|
| + return 0;
|
| +}
|
| +
|
| +#ifdef SQLITE_DEBUG
|
| +/*
|
| +** Write a nice string representation of the contents of cell pMem
|
| +** into buffer zBuf, length nBuf.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){
|
| + char *zCsr = zBuf;
|
| + int f = pMem->flags;
|
| +
|
| + static const char *const encnames[] = {"(X)", "(8)", "(16LE)", "(16BE)"};
|
| +
|
| + if( f&MEM_Blob ){
|
| + int i;
|
| + char c;
|
| + if( f & MEM_Dyn ){
|
| + c = 'z';
|
| + assert( (f & (MEM_Static|MEM_Ephem))==0 );
|
| + }else if( f & MEM_Static ){
|
| + c = 't';
|
| + assert( (f & (MEM_Dyn|MEM_Ephem))==0 );
|
| + }else if( f & MEM_Ephem ){
|
| + c = 'e';
|
| + assert( (f & (MEM_Static|MEM_Dyn))==0 );
|
| + }else{
|
| + c = 's';
|
| + }
|
| +
|
| + sqlite3_snprintf(100, zCsr, "%c", c);
|
| + zCsr += sqlite3Strlen30(zCsr);
|
| + sqlite3_snprintf(100, zCsr, "%d[", pMem->n);
|
| + zCsr += sqlite3Strlen30(zCsr);
|
| + for(i=0; i<16 && i<pMem->n; i++){
|
| + sqlite3_snprintf(100, zCsr, "%02X", ((int)pMem->z[i] & 0xFF));
|
| + zCsr += sqlite3Strlen30(zCsr);
|
| + }
|
| + for(i=0; i<16 && i<pMem->n; i++){
|
| + char z = pMem->z[i];
|
| + if( z<32 || z>126 ) *zCsr++ = '.';
|
| + else *zCsr++ = z;
|
| + }
|
| +
|
| + sqlite3_snprintf(100, zCsr, "]%s", encnames[pMem->enc]);
|
| + zCsr += sqlite3Strlen30(zCsr);
|
| + if( f & MEM_Zero ){
|
| + sqlite3_snprintf(100, zCsr,"+%dz",pMem->u.nZero);
|
| + zCsr += sqlite3Strlen30(zCsr);
|
| + }
|
| + *zCsr = '\0';
|
| + }else if( f & MEM_Str ){
|
| + int j, k;
|
| + zBuf[0] = ' ';
|
| + if( f & MEM_Dyn ){
|
| + zBuf[1] = 'z';
|
| + assert( (f & (MEM_Static|MEM_Ephem))==0 );
|
| + }else if( f & MEM_Static ){
|
| + zBuf[1] = 't';
|
| + assert( (f & (MEM_Dyn|MEM_Ephem))==0 );
|
| + }else if( f & MEM_Ephem ){
|
| + zBuf[1] = 'e';
|
| + assert( (f & (MEM_Static|MEM_Dyn))==0 );
|
| + }else{
|
| + zBuf[1] = 's';
|
| + }
|
| + k = 2;
|
| + sqlite3_snprintf(100, &zBuf[k], "%d", pMem->n);
|
| + k += sqlite3Strlen30(&zBuf[k]);
|
| + zBuf[k++] = '[';
|
| + for(j=0; j<15 && j<pMem->n; j++){
|
| + u8 c = pMem->z[j];
|
| + if( c>=0x20 && c<0x7f ){
|
| + zBuf[k++] = c;
|
| + }else{
|
| + zBuf[k++] = '.';
|
| + }
|
| + }
|
| + zBuf[k++] = ']';
|
| + sqlite3_snprintf(100,&zBuf[k], encnames[pMem->enc]);
|
| + k += sqlite3Strlen30(&zBuf[k]);
|
| + zBuf[k++] = 0;
|
| + }
|
| +}
|
| +#endif
|
| +
|
| +#ifdef SQLITE_DEBUG
|
| +/*
|
| +** Print the value of a register for tracing purposes:
|
| +*/
|
| +static void memTracePrint(Mem *p){
|
| + if( p->flags & MEM_Undefined ){
|
| + printf(" undefined");
|
| + }else if( p->flags & MEM_Null ){
|
| + printf(" NULL");
|
| + }else if( (p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){
|
| + printf(" si:%lld", p->u.i);
|
| + }else if( p->flags & MEM_Int ){
|
| + printf(" i:%lld", p->u.i);
|
| +#ifndef SQLITE_OMIT_FLOATING_POINT
|
| + }else if( p->flags & MEM_Real ){
|
| + printf(" r:%g", p->u.r);
|
| +#endif
|
| + }else if( p->flags & MEM_RowSet ){
|
| + printf(" (rowset)");
|
| + }else{
|
| + char zBuf[200];
|
| + sqlite3VdbeMemPrettyPrint(p, zBuf);
|
| + printf(" %s", zBuf);
|
| + }
|
| +}
|
| +static void registerTrace(int iReg, Mem *p){
|
| + printf("REG[%d] = ", iReg);
|
| + memTracePrint(p);
|
| + printf("\n");
|
| +}
|
| +#endif
|
| +
|
| +#ifdef SQLITE_DEBUG
|
| +# define REGISTER_TRACE(R,M) if(db->flags&SQLITE_VdbeTrace)registerTrace(R,M)
|
| +#else
|
| +# define REGISTER_TRACE(R,M)
|
| +#endif
|
| +
|
| +
|
| +#ifdef VDBE_PROFILE
|
| +
|
| +/*
|
| +** hwtime.h contains inline assembler code for implementing
|
| +** high-performance timing routines.
|
| +*/
|
| +/************** Include hwtime.h in the middle of vdbe.c *********************/
|
| +/************** Begin file hwtime.h ******************************************/
|
| +/*
|
| +** 2008 May 27
|
| +**
|
| +** 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.
|
| +**
|
| +******************************************************************************
|
| +**
|
| +** This file contains inline asm code for retrieving "high-performance"
|
| +** counters for x86 class CPUs.
|
| +*/
|
| +#ifndef _HWTIME_H_
|
| +#define _HWTIME_H_
|
| +
|
| +/*
|
| +** The following routine only works on pentium-class (or newer) processors.
|
| +** It uses the RDTSC opcode to read the cycle count value out of the
|
| +** processor and returns that value. This can be used for high-res
|
| +** profiling.
|
| +*/
|
| +#if (defined(__GNUC__) || defined(_MSC_VER)) && \
|
| + (defined(i386) || defined(__i386__) || defined(_M_IX86))
|
| +
|
| + #if defined(__GNUC__)
|
| +
|
| + __inline__ sqlite_uint64 sqlite3Hwtime(void){
|
| + unsigned int lo, hi;
|
| + __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
|
| + return (sqlite_uint64)hi << 32 | lo;
|
| + }
|
| +
|
| + #elif defined(_MSC_VER)
|
| +
|
| + __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){
|
| + __asm {
|
| + rdtsc
|
| + ret ; return value at EDX:EAX
|
| + }
|
| + }
|
| +
|
| + #endif
|
| +
|
| +#elif (defined(__GNUC__) && defined(__x86_64__))
|
| +
|
| + __inline__ sqlite_uint64 sqlite3Hwtime(void){
|
| + unsigned long val;
|
| + __asm__ __volatile__ ("rdtsc" : "=A" (val));
|
| + return val;
|
| + }
|
| +
|
| +#elif (defined(__GNUC__) && defined(__ppc__))
|
| +
|
| + __inline__ sqlite_uint64 sqlite3Hwtime(void){
|
| + unsigned long long retval;
|
| + unsigned long junk;
|
| + __asm__ __volatile__ ("\n\
|
| + 1: mftbu %1\n\
|
| + mftb %L0\n\
|
| + mftbu %0\n\
|
| + cmpw %0,%1\n\
|
| + bne 1b"
|
| + : "=r" (retval), "=r" (junk));
|
| + return retval;
|
| + }
|
| +
|
| +#else
|
| +
|
| + #error Need implementation of sqlite3Hwtime() for your platform.
|
| +
|
| + /*
|
| + ** To compile without implementing sqlite3Hwtime() for your platform,
|
| + ** you can remove the above #error and use the following
|
| + ** stub function. You will lose timing support for many
|
| + ** of the debugging and testing utilities, but it should at
|
| + ** least compile and run.
|
| + */
|
| +SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
|
| +
|
| +#endif
|
| +
|
| +#endif /* !defined(_HWTIME_H_) */
|
| +
|
| +/************** End of hwtime.h **********************************************/
|
| +/************** Continuing where we left off in vdbe.c ***********************/
|
| +
|
| +#endif
|
| +
|
| +#ifndef NDEBUG
|
| +/*
|
| +** This function is only called from within an assert() expression. It
|
| +** checks that the sqlite3.nTransaction variable is correctly set to
|
| +** the number of non-transaction savepoints currently in the
|
| +** linked list starting at sqlite3.pSavepoint.
|
| +**
|
| +** Usage:
|
| +**
|
| +** assert( checkSavepointCount(db) );
|
| +*/
|
| +static int checkSavepointCount(sqlite3 *db){
|
| + int n = 0;
|
| + Savepoint *p;
|
| + for(p=db->pSavepoint; p; p=p->pNext) n++;
|
| + assert( n==(db->nSavepoint + db->isTransactionSavepoint) );
|
| + return 1;
|
| +}
|
| +#endif
|
| +
|
| +/*
|
| +** Return the register of pOp->p2 after first preparing it to be
|
| +** overwritten with an integer value.
|
| +*/
|
| +static SQLITE_NOINLINE Mem *out2PrereleaseWithClear(Mem *pOut){
|
| + sqlite3VdbeMemSetNull(pOut);
|
| + pOut->flags = MEM_Int;
|
| + return pOut;
|
| +}
|
| +static Mem *out2Prerelease(Vdbe *p, VdbeOp *pOp){
|
| + Mem *pOut;
|
| + assert( pOp->p2>0 );
|
| + assert( pOp->p2<=(p->nMem-p->nCursor) );
|
| + pOut = &p->aMem[pOp->p2];
|
| + memAboutToChange(p, pOut);
|
| + if( VdbeMemDynamic(pOut) ){
|
| + return out2PrereleaseWithClear(pOut);
|
| + }else{
|
| + pOut->flags = MEM_Int;
|
| + return pOut;
|
| + }
|
| +}
|
| +
|
| +
|
| +/*
|
| +** Execute as much of a VDBE program as we can.
|
| +** This is the core of sqlite3_step().
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3VdbeExec(
|
| + Vdbe *p /* The VDBE */
|
| +){
|
| + Op *aOp = p->aOp; /* Copy of p->aOp */
|
| + Op *pOp = aOp; /* Current operation */
|
| +#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
|
| + Op *pOrigOp; /* Value of pOp at the top of the loop */
|
| +#endif
|
| + int rc = SQLITE_OK; /* Value to return */
|
| + sqlite3 *db = p->db; /* The database */
|
| + u8 resetSchemaOnFault = 0; /* Reset schema after an error if positive */
|
| + u8 encoding = ENC(db); /* The database encoding */
|
| + int iCompare = 0; /* Result of last OP_Compare operation */
|
| + unsigned nVmStep = 0; /* Number of virtual machine steps */
|
| +#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
|
| + unsigned nProgressLimit = 0;/* Invoke xProgress() when nVmStep reaches this */
|
| +#endif
|
| + Mem *aMem = p->aMem; /* Copy of p->aMem */
|
| + Mem *pIn1 = 0; /* 1st input operand */
|
| + Mem *pIn2 = 0; /* 2nd input operand */
|
| + Mem *pIn3 = 0; /* 3rd input operand */
|
| + Mem *pOut = 0; /* Output operand */
|
| + int *aPermute = 0; /* Permutation of columns for OP_Compare */
|
| + i64 lastRowid = db->lastRowid; /* Saved value of the last insert ROWID */
|
| +#ifdef VDBE_PROFILE
|
| + u64 start; /* CPU clock count at start of opcode */
|
| +#endif
|
| + /*** INSERT STACK UNION HERE ***/
|
| +
|
| + assert( p->magic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */
|
| + sqlite3VdbeEnter(p);
|
| + if( p->rc==SQLITE_NOMEM ){
|
| + /* This happens if a malloc() inside a call to sqlite3_column_text() or
|
| + ** sqlite3_column_text16() failed. */
|
| + goto no_mem;
|
| + }
|
| + assert( p->rc==SQLITE_OK || (p->rc&0xff)==SQLITE_BUSY );
|
| + assert( p->bIsReader || p->readOnly!=0 );
|
| + p->rc = SQLITE_OK;
|
| + p->iCurrentTime = 0;
|
| + assert( p->explain==0 );
|
| + p->pResultSet = 0;
|
| + db->busyHandler.nBusy = 0;
|
| + if( db->u1.isInterrupted ) goto abort_due_to_interrupt;
|
| + sqlite3VdbeIOTraceSql(p);
|
| +#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
|
| + if( db->xProgress ){
|
| + u32 iPrior = p->aCounter[SQLITE_STMTSTATUS_VM_STEP];
|
| + assert( 0 < db->nProgressOps );
|
| + nProgressLimit = db->nProgressOps - (iPrior % db->nProgressOps);
|
| + }
|
| +#endif
|
| +#ifdef SQLITE_DEBUG
|
| + sqlite3BeginBenignMalloc();
|
| + if( p->pc==0
|
| + && (p->db->flags & (SQLITE_VdbeListing|SQLITE_VdbeEQP|SQLITE_VdbeTrace))!=0
|
| + ){
|
| + int i;
|
| + int once = 1;
|
| + sqlite3VdbePrintSql(p);
|
| + if( p->db->flags & SQLITE_VdbeListing ){
|
| + printf("VDBE Program Listing:\n");
|
| + for(i=0; i<p->nOp; i++){
|
| + sqlite3VdbePrintOp(stdout, i, &aOp[i]);
|
| + }
|
| + }
|
| + if( p->db->flags & SQLITE_VdbeEQP ){
|
| + for(i=0; i<p->nOp; i++){
|
| + if( aOp[i].opcode==OP_Explain ){
|
| + if( once ) printf("VDBE Query Plan:\n");
|
| + printf("%s\n", aOp[i].p4.z);
|
| + once = 0;
|
| + }
|
| + }
|
| + }
|
| + if( p->db->flags & SQLITE_VdbeTrace ) printf("VDBE Trace:\n");
|
| + }
|
| + sqlite3EndBenignMalloc();
|
| +#endif
|
| + for(pOp=&aOp[p->pc]; rc==SQLITE_OK; pOp++){
|
| + assert( pOp>=aOp && pOp<&aOp[p->nOp]);
|
| + if( db->mallocFailed ) goto no_mem;
|
| +#ifdef VDBE_PROFILE
|
| + start = sqlite3Hwtime();
|
| +#endif
|
| + nVmStep++;
|
| +#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
| + if( p->anExec ) p->anExec[(int)(pOp-aOp)]++;
|
| +#endif
|
| +
|
| + /* Only allow tracing if SQLITE_DEBUG is defined.
|
| + */
|
| +#ifdef SQLITE_DEBUG
|
| + if( db->flags & SQLITE_VdbeTrace ){
|
| + sqlite3VdbePrintOp(stdout, (int)(pOp - aOp), pOp);
|
| + }
|
| +#endif
|
| +
|
| +
|
| + /* Check to see if we need to simulate an interrupt. This only happens
|
| + ** if we have a special test build.
|
| + */
|
| +#ifdef SQLITE_TEST
|
| + if( sqlite3_interrupt_count>0 ){
|
| + sqlite3_interrupt_count--;
|
| + if( sqlite3_interrupt_count==0 ){
|
| + sqlite3_interrupt(db);
|
| + }
|
| + }
|
| +#endif
|
| +
|
| + /* Sanity checking on other operands */
|
| +#ifdef SQLITE_DEBUG
|
| + assert( pOp->opflags==sqlite3OpcodeProperty[pOp->opcode] );
|
| + if( (pOp->opflags & OPFLG_IN1)!=0 ){
|
| + assert( pOp->p1>0 );
|
| + assert( pOp->p1<=(p->nMem-p->nCursor) );
|
| + assert( memIsValid(&aMem[pOp->p1]) );
|
| + assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p1]) );
|
| + REGISTER_TRACE(pOp->p1, &aMem[pOp->p1]);
|
| + }
|
| + if( (pOp->opflags & OPFLG_IN2)!=0 ){
|
| + assert( pOp->p2>0 );
|
| + assert( pOp->p2<=(p->nMem-p->nCursor) );
|
| + assert( memIsValid(&aMem[pOp->p2]) );
|
| + assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p2]) );
|
| + REGISTER_TRACE(pOp->p2, &aMem[pOp->p2]);
|
| + }
|
| + if( (pOp->opflags & OPFLG_IN3)!=0 ){
|
| + assert( pOp->p3>0 );
|
| + assert( pOp->p3<=(p->nMem-p->nCursor) );
|
| + assert( memIsValid(&aMem[pOp->p3]) );
|
| + assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p3]) );
|
| + REGISTER_TRACE(pOp->p3, &aMem[pOp->p3]);
|
| + }
|
| + if( (pOp->opflags & OPFLG_OUT2)!=0 ){
|
| + assert( pOp->p2>0 );
|
| + assert( pOp->p2<=(p->nMem-p->nCursor) );
|
| + memAboutToChange(p, &aMem[pOp->p2]);
|
| + }
|
| + if( (pOp->opflags & OPFLG_OUT3)!=0 ){
|
| + assert( pOp->p3>0 );
|
| + assert( pOp->p3<=(p->nMem-p->nCursor) );
|
| + memAboutToChange(p, &aMem[pOp->p3]);
|
| + }
|
| +#endif
|
| +#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
|
| + pOrigOp = pOp;
|
| +#endif
|
| +
|
| + switch( pOp->opcode ){
|
| +
|
| +/*****************************************************************************
|
| +** What follows is a massive switch statement where each case implements a
|
| +** separate instruction in the virtual machine. If we follow the usual
|
| +** indentation conventions, each case should be indented by 6 spaces. But
|
| +** that is a lot of wasted space on the left margin. So the code within
|
| +** the switch statement will break with convention and be flush-left. Another
|
| +** big comment (similar to this one) will mark the point in the code where
|
| +** we transition back to normal indentation.
|
| +**
|
| +** The formatting of each case is important. The makefile for SQLite
|
| +** generates two C files "opcodes.h" and "opcodes.c" by scanning this
|
| +** file looking for lines that begin with "case OP_". The opcodes.h files
|
| +** will be filled with #defines that give unique integer values to each
|
| +** opcode and the opcodes.c file is filled with an array of strings where
|
| +** each string is the symbolic name for the corresponding opcode. If the
|
| +** case statement is followed by a comment of the form "/# same as ... #/"
|
| +** that comment is used to determine the particular value of the opcode.
|
| +**
|
| +** Other keywords in the comment that follows each case are used to
|
| +** construct the OPFLG_INITIALIZER value that initializes opcodeProperty[].
|
| +** Keywords include: in1, in2, in3, out2, out3. See
|
| +** the mkopcodeh.awk script for additional information.
|
| +**
|
| +** Documentation about VDBE opcodes is generated by scanning this file
|
| +** for lines of that contain "Opcode:". That line and all subsequent
|
| +** comment lines are used in the generation of the opcode.html documentation
|
| +** file.
|
| +**
|
| +** SUMMARY:
|
| +**
|
| +** Formatting is important to scripts that scan this file.
|
| +** Do not deviate from the formatting style currently in use.
|
| +**
|
| +*****************************************************************************/
|
| +
|
| +/* Opcode: Goto * P2 * * *
|
| +**
|
| +** An unconditional jump to address P2.
|
| +** The next instruction executed will be
|
| +** the one at index P2 from the beginning of
|
| +** the program.
|
| +**
|
| +** The P1 parameter is not actually used by this opcode. However, it
|
| +** is sometimes set to 1 instead of 0 as a hint to the command-line shell
|
| +** that this Goto is the bottom of a loop and that the lines from P2 down
|
| +** to the current line should be indented for EXPLAIN output.
|
| +*/
|
| +case OP_Goto: { /* jump */
|
| +jump_to_p2_and_check_for_interrupt:
|
| + pOp = &aOp[pOp->p2 - 1];
|
| +
|
| + /* Opcodes that are used as the bottom of a loop (OP_Next, OP_Prev,
|
| + ** OP_VNext, OP_RowSetNext, or OP_SorterNext) all jump here upon
|
| + ** completion. Check to see if sqlite3_interrupt() has been called
|
| + ** or if the progress callback needs to be invoked.
|
| + **
|
| + ** This code uses unstructured "goto" statements and does not look clean.
|
| + ** But that is not due to sloppy coding habits. The code is written this
|
| + ** way for performance, to avoid having to run the interrupt and progress
|
| + ** checks on every opcode. This helps sqlite3_step() to run about 1.5%
|
| + ** faster according to "valgrind --tool=cachegrind" */
|
| +check_for_interrupt:
|
| + if( db->u1.isInterrupted ) goto abort_due_to_interrupt;
|
| +#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
|
| + /* Call the progress callback if it is configured and the required number
|
| + ** of VDBE ops have been executed (either since this invocation of
|
| + ** sqlite3VdbeExec() or since last time the progress callback was called).
|
| + ** If the progress callback returns non-zero, exit the virtual machine with
|
| + ** a return code SQLITE_ABORT.
|
| + */
|
| + if( db->xProgress!=0 && nVmStep>=nProgressLimit ){
|
| + assert( db->nProgressOps!=0 );
|
| + nProgressLimit = nVmStep + db->nProgressOps - (nVmStep%db->nProgressOps);
|
| + if( db->xProgress(db->pProgressArg) ){
|
| + rc = SQLITE_INTERRUPT;
|
| + goto vdbe_error_halt;
|
| + }
|
| + }
|
| +#endif
|
| +
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: Gosub P1 P2 * * *
|
| +**
|
| +** Write the current address onto register P1
|
| +** and then jump to address P2.
|
| +*/
|
| +case OP_Gosub: { /* jump */
|
| + assert( pOp->p1>0 && pOp->p1<=(p->nMem-p->nCursor) );
|
| + pIn1 = &aMem[pOp->p1];
|
| + assert( VdbeMemDynamic(pIn1)==0 );
|
| + memAboutToChange(p, pIn1);
|
| + pIn1->flags = MEM_Int;
|
| + pIn1->u.i = (int)(pOp-aOp);
|
| + REGISTER_TRACE(pOp->p1, pIn1);
|
| +
|
| + /* Most jump operations do a goto to this spot in order to update
|
| + ** the pOp pointer. */
|
| +jump_to_p2:
|
| + pOp = &aOp[pOp->p2 - 1];
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: Return P1 * * * *
|
| +**
|
| +** Jump to the next instruction after the address in register P1. After
|
| +** the jump, register P1 becomes undefined.
|
| +*/
|
| +case OP_Return: { /* in1 */
|
| + pIn1 = &aMem[pOp->p1];
|
| + assert( pIn1->flags==MEM_Int );
|
| + pOp = &aOp[pIn1->u.i];
|
| + pIn1->flags = MEM_Undefined;
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: InitCoroutine P1 P2 P3 * *
|
| +**
|
| +** Set up register P1 so that it will Yield to the coroutine
|
| +** located at address P3.
|
| +**
|
| +** If P2!=0 then the coroutine implementation immediately follows
|
| +** this opcode. So jump over the coroutine implementation to
|
| +** address P2.
|
| +**
|
| +** See also: EndCoroutine
|
| +*/
|
| +case OP_InitCoroutine: { /* jump */
|
| + assert( pOp->p1>0 && pOp->p1<=(p->nMem-p->nCursor) );
|
| + assert( pOp->p2>=0 && pOp->p2<p->nOp );
|
| + assert( pOp->p3>=0 && pOp->p3<p->nOp );
|
| + pOut = &aMem[pOp->p1];
|
| + assert( !VdbeMemDynamic(pOut) );
|
| + pOut->u.i = pOp->p3 - 1;
|
| + pOut->flags = MEM_Int;
|
| + if( pOp->p2 ) goto jump_to_p2;
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: EndCoroutine P1 * * * *
|
| +**
|
| +** The instruction at the address in register P1 is a Yield.
|
| +** Jump to the P2 parameter of that Yield.
|
| +** After the jump, register P1 becomes undefined.
|
| +**
|
| +** See also: InitCoroutine
|
| +*/
|
| +case OP_EndCoroutine: { /* in1 */
|
| + VdbeOp *pCaller;
|
| + pIn1 = &aMem[pOp->p1];
|
| + assert( pIn1->flags==MEM_Int );
|
| + assert( pIn1->u.i>=0 && pIn1->u.i<p->nOp );
|
| + pCaller = &aOp[pIn1->u.i];
|
| + assert( pCaller->opcode==OP_Yield );
|
| + assert( pCaller->p2>=0 && pCaller->p2<p->nOp );
|
| + pOp = &aOp[pCaller->p2 - 1];
|
| + pIn1->flags = MEM_Undefined;
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: Yield P1 P2 * * *
|
| +**
|
| +** Swap the program counter with the value in register P1. This
|
| +** has the effect of yielding to a coroutine.
|
| +**
|
| +** If the coroutine that is launched by this instruction ends with
|
| +** Yield or Return then continue to the next instruction. But if
|
| +** the coroutine launched by this instruction ends with
|
| +** EndCoroutine, then jump to P2 rather than continuing with the
|
| +** next instruction.
|
| +**
|
| +** See also: InitCoroutine
|
| +*/
|
| +case OP_Yield: { /* in1, jump */
|
| + int pcDest;
|
| + pIn1 = &aMem[pOp->p1];
|
| + assert( VdbeMemDynamic(pIn1)==0 );
|
| + pIn1->flags = MEM_Int;
|
| + pcDest = (int)pIn1->u.i;
|
| + pIn1->u.i = (int)(pOp - aOp);
|
| + REGISTER_TRACE(pOp->p1, pIn1);
|
| + pOp = &aOp[pcDest];
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: HaltIfNull P1 P2 P3 P4 P5
|
| +** Synopsis: if r[P3]=null halt
|
| +**
|
| +** Check the value in register P3. If it is NULL then Halt using
|
| +** parameter P1, P2, and P4 as if this were a Halt instruction. If the
|
| +** value in register P3 is not NULL, then this routine is a no-op.
|
| +** The P5 parameter should be 1.
|
| +*/
|
| +case OP_HaltIfNull: { /* in3 */
|
| + pIn3 = &aMem[pOp->p3];
|
| + if( (pIn3->flags & MEM_Null)==0 ) break;
|
| + /* Fall through into OP_Halt */
|
| +}
|
| +
|
| +/* Opcode: Halt P1 P2 * P4 P5
|
| +**
|
| +** Exit immediately. All open cursors, etc are closed
|
| +** automatically.
|
| +**
|
| +** P1 is the result code returned by sqlite3_exec(), sqlite3_reset(),
|
| +** or sqlite3_finalize(). For a normal halt, this should be SQLITE_OK (0).
|
| +** For errors, it can be some other value. If P1!=0 then P2 will determine
|
| +** whether or not to rollback the current transaction. Do not rollback
|
| +** if P2==OE_Fail. Do the rollback if P2==OE_Rollback. If P2==OE_Abort,
|
| +** then back out all changes that have occurred during this execution of the
|
| +** VDBE, but do not rollback the transaction.
|
| +**
|
| +** If P4 is not null then it is an error message string.
|
| +**
|
| +** P5 is a value between 0 and 4, inclusive, that modifies the P4 string.
|
| +**
|
| +** 0: (no change)
|
| +** 1: NOT NULL contraint failed: P4
|
| +** 2: UNIQUE constraint failed: P4
|
| +** 3: CHECK constraint failed: P4
|
| +** 4: FOREIGN KEY constraint failed: P4
|
| +**
|
| +** If P5 is not zero and P4 is NULL, then everything after the ":" is
|
| +** omitted.
|
| +**
|
| +** There is an implied "Halt 0 0 0" instruction inserted at the very end of
|
| +** every program. So a jump past the last instruction of the program
|
| +** is the same as executing Halt.
|
| +*/
|
| +case OP_Halt: {
|
| + const char *zType;
|
| + const char *zLogFmt;
|
| + VdbeFrame *pFrame;
|
| + int pcx;
|
| +
|
| + pcx = (int)(pOp - aOp);
|
| + if( pOp->p1==SQLITE_OK && p->pFrame ){
|
| + /* Halt the sub-program. Return control to the parent frame. */
|
| + pFrame = p->pFrame;
|
| + p->pFrame = pFrame->pParent;
|
| + p->nFrame--;
|
| + sqlite3VdbeSetChanges(db, p->nChange);
|
| + pcx = sqlite3VdbeFrameRestore(pFrame);
|
| + lastRowid = db->lastRowid;
|
| + if( pOp->p2==OE_Ignore ){
|
| + /* Instruction pcx is the OP_Program that invoked the sub-program
|
| + ** currently being halted. If the p2 instruction of this OP_Halt
|
| + ** instruction is set to OE_Ignore, then the sub-program is throwing
|
| + ** an IGNORE exception. In this case jump to the address specified
|
| + ** as the p2 of the calling OP_Program. */
|
| + pcx = p->aOp[pcx].p2-1;
|
| + }
|
| + aOp = p->aOp;
|
| + aMem = p->aMem;
|
| + pOp = &aOp[pcx];
|
| + break;
|
| + }
|
| + p->rc = pOp->p1;
|
| + p->errorAction = (u8)pOp->p2;
|
| + p->pc = pcx;
|
| + if( p->rc ){
|
| + if( pOp->p5 ){
|
| + static const char * const azType[] = { "NOT NULL", "UNIQUE", "CHECK",
|
| + "FOREIGN KEY" };
|
| + assert( pOp->p5>=1 && pOp->p5<=4 );
|
| + testcase( pOp->p5==1 );
|
| + testcase( pOp->p5==2 );
|
| + testcase( pOp->p5==3 );
|
| + testcase( pOp->p5==4 );
|
| + zType = azType[pOp->p5-1];
|
| + }else{
|
| + zType = 0;
|
| + }
|
| + assert( zType!=0 || pOp->p4.z!=0 );
|
| + zLogFmt = "abort at %d in [%s]: %s";
|
| + if( zType && pOp->p4.z ){
|
| + sqlite3VdbeError(p, "%s constraint failed: %s", zType, pOp->p4.z);
|
| + }else if( pOp->p4.z ){
|
| + sqlite3VdbeError(p, "%s", pOp->p4.z);
|
| + }else{
|
| + sqlite3VdbeError(p, "%s constraint failed", zType);
|
| + }
|
| + sqlite3_log(pOp->p1, zLogFmt, pcx, p->zSql, p->zErrMsg);
|
| + }
|
| + rc = sqlite3VdbeHalt(p);
|
| + assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR );
|
| + if( rc==SQLITE_BUSY ){
|
| + p->rc = rc = SQLITE_BUSY;
|
| + }else{
|
| + assert( rc==SQLITE_OK || (p->rc&0xff)==SQLITE_CONSTRAINT );
|
| + assert( rc==SQLITE_OK || db->nDeferredCons>0 || db->nDeferredImmCons>0 );
|
| + rc = p->rc ? SQLITE_ERROR : SQLITE_DONE;
|
| + }
|
| + goto vdbe_return;
|
| +}
|
| +
|
| +/* Opcode: Integer P1 P2 * * *
|
| +** Synopsis: r[P2]=P1
|
| +**
|
| +** The 32-bit integer value P1 is written into register P2.
|
| +*/
|
| +case OP_Integer: { /* out2 */
|
| + pOut = out2Prerelease(p, pOp);
|
| + pOut->u.i = pOp->p1;
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: Int64 * P2 * P4 *
|
| +** Synopsis: r[P2]=P4
|
| +**
|
| +** P4 is a pointer to a 64-bit integer value.
|
| +** Write that value into register P2.
|
| +*/
|
| +case OP_Int64: { /* out2 */
|
| + pOut = out2Prerelease(p, pOp);
|
| + assert( pOp->p4.pI64!=0 );
|
| + pOut->u.i = *pOp->p4.pI64;
|
| + break;
|
| +}
|
| +
|
| +#ifndef SQLITE_OMIT_FLOATING_POINT
|
| +/* Opcode: Real * P2 * P4 *
|
| +** Synopsis: r[P2]=P4
|
| +**
|
| +** P4 is a pointer to a 64-bit floating point value.
|
| +** Write that value into register P2.
|
| +*/
|
| +case OP_Real: { /* same as TK_FLOAT, out2 */
|
| + pOut = out2Prerelease(p, pOp);
|
| + pOut->flags = MEM_Real;
|
| + assert( !sqlite3IsNaN(*pOp->p4.pReal) );
|
| + pOut->u.r = *pOp->p4.pReal;
|
| + break;
|
| +}
|
| +#endif
|
| +
|
| +/* Opcode: String8 * P2 * P4 *
|
| +** Synopsis: r[P2]='P4'
|
| +**
|
| +** P4 points to a nul terminated UTF-8 string. This opcode is transformed
|
| +** into a String opcode before it is executed for the first time. During
|
| +** this transformation, the length of string P4 is computed and stored
|
| +** as the P1 parameter.
|
| +*/
|
| +case OP_String8: { /* same as TK_STRING, out2 */
|
| + assert( pOp->p4.z!=0 );
|
| + pOut = out2Prerelease(p, pOp);
|
| + pOp->opcode = OP_String;
|
| + pOp->p1 = sqlite3Strlen30(pOp->p4.z);
|
| +
|
| +#ifndef SQLITE_OMIT_UTF16
|
| + if( encoding!=SQLITE_UTF8 ){
|
| + rc = sqlite3VdbeMemSetStr(pOut, pOp->p4.z, -1, SQLITE_UTF8, SQLITE_STATIC);
|
| + if( rc==SQLITE_TOOBIG ) goto too_big;
|
| + if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pOut, encoding) ) goto no_mem;
|
| + assert( pOut->szMalloc>0 && pOut->zMalloc==pOut->z );
|
| + assert( VdbeMemDynamic(pOut)==0 );
|
| + pOut->szMalloc = 0;
|
| + pOut->flags |= MEM_Static;
|
| + if( pOp->p4type==P4_DYNAMIC ){
|
| + sqlite3DbFree(db, pOp->p4.z);
|
| + }
|
| + pOp->p4type = P4_DYNAMIC;
|
| + pOp->p4.z = pOut->z;
|
| + pOp->p1 = pOut->n;
|
| + }
|
| +#endif
|
| + if( pOp->p1>db->aLimit[SQLITE_LIMIT_LENGTH] ){
|
| + goto too_big;
|
| + }
|
| + /* Fall through to the next case, OP_String */
|
| +}
|
| +
|
| +/* Opcode: String P1 P2 P3 P4 P5
|
| +** Synopsis: r[P2]='P4' (len=P1)
|
| +**
|
| +** The string value P4 of length P1 (bytes) is stored in register P2.
|
| +**
|
| +** If P5!=0 and the content of register P3 is greater than zero, then
|
| +** the datatype of the register P2 is converted to BLOB. The content is
|
| +** the same sequence of bytes, it is merely interpreted as a BLOB instead
|
| +** of a string, as if it had been CAST.
|
| +*/
|
| +case OP_String: { /* out2 */
|
| + assert( pOp->p4.z!=0 );
|
| + pOut = out2Prerelease(p, pOp);
|
| + pOut->flags = MEM_Str|MEM_Static|MEM_Term;
|
| + pOut->z = pOp->p4.z;
|
| + pOut->n = pOp->p1;
|
| + pOut->enc = encoding;
|
| + UPDATE_MAX_BLOBSIZE(pOut);
|
| +#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS
|
| + if( pOp->p5 ){
|
| + assert( pOp->p3>0 );
|
| + assert( pOp->p3<=(p->nMem-p->nCursor) );
|
| + pIn3 = &aMem[pOp->p3];
|
| + assert( pIn3->flags & MEM_Int );
|
| + if( pIn3->u.i ) pOut->flags = MEM_Blob|MEM_Static|MEM_Term;
|
| + }
|
| +#endif
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: Null P1 P2 P3 * *
|
| +** Synopsis: r[P2..P3]=NULL
|
| +**
|
| +** Write a NULL into registers P2. If P3 greater than P2, then also write
|
| +** NULL into register P3 and every register in between P2 and P3. If P3
|
| +** is less than P2 (typically P3 is zero) then only register P2 is
|
| +** set to NULL.
|
| +**
|
| +** If the P1 value is non-zero, then also set the MEM_Cleared flag so that
|
| +** NULL values will not compare equal even if SQLITE_NULLEQ is set on
|
| +** OP_Ne or OP_Eq.
|
| +*/
|
| +case OP_Null: { /* out2 */
|
| + int cnt;
|
| + u16 nullFlag;
|
| + pOut = out2Prerelease(p, pOp);
|
| + cnt = pOp->p3-pOp->p2;
|
| + assert( pOp->p3<=(p->nMem-p->nCursor) );
|
| + pOut->flags = nullFlag = pOp->p1 ? (MEM_Null|MEM_Cleared) : MEM_Null;
|
| + while( cnt>0 ){
|
| + pOut++;
|
| + memAboutToChange(p, pOut);
|
| + sqlite3VdbeMemSetNull(pOut);
|
| + pOut->flags = nullFlag;
|
| + cnt--;
|
| + }
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: SoftNull P1 * * * *
|
| +** Synopsis: r[P1]=NULL
|
| +**
|
| +** Set register P1 to have the value NULL as seen by the OP_MakeRecord
|
| +** instruction, but do not free any string or blob memory associated with
|
| +** the register, so that if the value was a string or blob that was
|
| +** previously copied using OP_SCopy, the copies will continue to be valid.
|
| +*/
|
| +case OP_SoftNull: {
|
| + assert( pOp->p1>0 && pOp->p1<=(p->nMem-p->nCursor) );
|
| + pOut = &aMem[pOp->p1];
|
| + pOut->flags = (pOut->flags|MEM_Null)&~MEM_Undefined;
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: Blob P1 P2 * P4 *
|
| +** Synopsis: r[P2]=P4 (len=P1)
|
| +**
|
| +** P4 points to a blob of data P1 bytes long. Store this
|
| +** blob in register P2.
|
| +*/
|
| +case OP_Blob: { /* out2 */
|
| + assert( pOp->p1 <= SQLITE_MAX_LENGTH );
|
| + pOut = out2Prerelease(p, pOp);
|
| + sqlite3VdbeMemSetStr(pOut, pOp->p4.z, pOp->p1, 0, 0);
|
| + pOut->enc = encoding;
|
| + UPDATE_MAX_BLOBSIZE(pOut);
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: Variable P1 P2 * P4 *
|
| +** Synopsis: r[P2]=parameter(P1,P4)
|
| +**
|
| +** Transfer the values of bound parameter P1 into register P2
|
| +**
|
| +** If the parameter is named, then its name appears in P4.
|
| +** The P4 value is used by sqlite3_bind_parameter_name().
|
| +*/
|
| +case OP_Variable: { /* out2 */
|
| + Mem *pVar; /* Value being transferred */
|
| +
|
| + assert( pOp->p1>0 && pOp->p1<=p->nVar );
|
| + assert( pOp->p4.z==0 || pOp->p4.z==p->azVar[pOp->p1-1] );
|
| + pVar = &p->aVar[pOp->p1 - 1];
|
| + if( sqlite3VdbeMemTooBig(pVar) ){
|
| + goto too_big;
|
| + }
|
| + pOut = out2Prerelease(p, pOp);
|
| + sqlite3VdbeMemShallowCopy(pOut, pVar, MEM_Static);
|
| + UPDATE_MAX_BLOBSIZE(pOut);
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: Move P1 P2 P3 * *
|
| +** Synopsis: r[P2@P3]=r[P1@P3]
|
| +**
|
| +** Move the P3 values in register P1..P1+P3-1 over into
|
| +** registers P2..P2+P3-1. Registers P1..P1+P3-1 are
|
| +** left holding a NULL. It is an error for register ranges
|
| +** P1..P1+P3-1 and P2..P2+P3-1 to overlap. It is an error
|
| +** for P3 to be less than 1.
|
| +*/
|
| +case OP_Move: {
|
| + int n; /* Number of registers left to copy */
|
| + int p1; /* Register to copy from */
|
| + int p2; /* Register to copy to */
|
| +
|
| + n = pOp->p3;
|
| + p1 = pOp->p1;
|
| + p2 = pOp->p2;
|
| + assert( n>0 && p1>0 && p2>0 );
|
| + assert( p1+n<=p2 || p2+n<=p1 );
|
| +
|
| + pIn1 = &aMem[p1];
|
| + pOut = &aMem[p2];
|
| + do{
|
| + assert( pOut<=&aMem[(p->nMem-p->nCursor)] );
|
| + assert( pIn1<=&aMem[(p->nMem-p->nCursor)] );
|
| + assert( memIsValid(pIn1) );
|
| + memAboutToChange(p, pOut);
|
| + sqlite3VdbeMemMove(pOut, pIn1);
|
| +#ifdef SQLITE_DEBUG
|
| + if( pOut->pScopyFrom>=&aMem[p1] && pOut->pScopyFrom<pOut ){
|
| + pOut->pScopyFrom += pOp->p2 - p1;
|
| + }
|
| +#endif
|
| + Deephemeralize(pOut);
|
| + REGISTER_TRACE(p2++, pOut);
|
| + pIn1++;
|
| + pOut++;
|
| + }while( --n );
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: Copy P1 P2 P3 * *
|
| +** Synopsis: r[P2@P3+1]=r[P1@P3+1]
|
| +**
|
| +** Make a copy of registers P1..P1+P3 into registers P2..P2+P3.
|
| +**
|
| +** This instruction makes a deep copy of the value. A duplicate
|
| +** is made of any string or blob constant. See also OP_SCopy.
|
| +*/
|
| +case OP_Copy: {
|
| + int n;
|
| +
|
| + n = pOp->p3;
|
| + pIn1 = &aMem[pOp->p1];
|
| + pOut = &aMem[pOp->p2];
|
| + assert( pOut!=pIn1 );
|
| + while( 1 ){
|
| + sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem);
|
| + Deephemeralize(pOut);
|
| +#ifdef SQLITE_DEBUG
|
| + pOut->pScopyFrom = 0;
|
| +#endif
|
| + REGISTER_TRACE(pOp->p2+pOp->p3-n, pOut);
|
| + if( (n--)==0 ) break;
|
| + pOut++;
|
| + pIn1++;
|
| + }
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: SCopy P1 P2 * * *
|
| +** Synopsis: r[P2]=r[P1]
|
| +**
|
| +** Make a shallow copy of register P1 into register P2.
|
| +**
|
| +** This instruction makes a shallow copy of the value. If the value
|
| +** is a string or blob, then the copy is only a pointer to the
|
| +** original and hence if the original changes so will the copy.
|
| +** Worse, if the original is deallocated, the copy becomes invalid.
|
| +** Thus the program must guarantee that the original will not change
|
| +** during the lifetime of the copy. Use OP_Copy to make a complete
|
| +** copy.
|
| +*/
|
| +case OP_SCopy: { /* out2 */
|
| + pIn1 = &aMem[pOp->p1];
|
| + pOut = &aMem[pOp->p2];
|
| + assert( pOut!=pIn1 );
|
| + sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem);
|
| +#ifdef SQLITE_DEBUG
|
| + if( pOut->pScopyFrom==0 ) pOut->pScopyFrom = pIn1;
|
| +#endif
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: IntCopy P1 P2 * * *
|
| +** Synopsis: r[P2]=r[P1]
|
| +**
|
| +** Transfer the integer value held in register P1 into register P2.
|
| +**
|
| +** This is an optimized version of SCopy that works only for integer
|
| +** values.
|
| +*/
|
| +case OP_IntCopy: { /* out2 */
|
| + pIn1 = &aMem[pOp->p1];
|
| + assert( (pIn1->flags & MEM_Int)!=0 );
|
| + pOut = &aMem[pOp->p2];
|
| + sqlite3VdbeMemSetInt64(pOut, pIn1->u.i);
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: ResultRow P1 P2 * * *
|
| +** Synopsis: output=r[P1@P2]
|
| +**
|
| +** The registers P1 through P1+P2-1 contain a single row of
|
| +** results. This opcode causes the sqlite3_step() call to terminate
|
| +** with an SQLITE_ROW return code and it sets up the sqlite3_stmt
|
| +** structure to provide access to the r(P1)..r(P1+P2-1) values as
|
| +** the result row.
|
| +*/
|
| +case OP_ResultRow: {
|
| + Mem *pMem;
|
| + int i;
|
| + assert( p->nResColumn==pOp->p2 );
|
| + assert( pOp->p1>0 );
|
| + assert( pOp->p1+pOp->p2<=(p->nMem-p->nCursor)+1 );
|
| +
|
| +#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
|
| + /* Run the progress counter just before returning.
|
| + */
|
| + if( db->xProgress!=0
|
| + && nVmStep>=nProgressLimit
|
| + && db->xProgress(db->pProgressArg)!=0
|
| + ){
|
| + rc = SQLITE_INTERRUPT;
|
| + goto vdbe_error_halt;
|
| + }
|
| +#endif
|
| +
|
| + /* If this statement has violated immediate foreign key constraints, do
|
| + ** not return the number of rows modified. And do not RELEASE the statement
|
| + ** transaction. It needs to be rolled back. */
|
| + if( SQLITE_OK!=(rc = sqlite3VdbeCheckFk(p, 0)) ){
|
| + assert( db->flags&SQLITE_CountRows );
|
| + assert( p->usesStmtJournal );
|
| + break;
|
| + }
|
| +
|
| + /* If the SQLITE_CountRows flag is set in sqlite3.flags mask, then
|
| + ** DML statements invoke this opcode to return the number of rows
|
| + ** modified to the user. This is the only way that a VM that
|
| + ** opens a statement transaction may invoke this opcode.
|
| + **
|
| + ** In case this is such a statement, close any statement transaction
|
| + ** opened by this VM before returning control to the user. This is to
|
| + ** ensure that statement-transactions are always nested, not overlapping.
|
| + ** If the open statement-transaction is not closed here, then the user
|
| + ** may step another VM that opens its own statement transaction. This
|
| + ** may lead to overlapping statement transactions.
|
| + **
|
| + ** The statement transaction is never a top-level transaction. Hence
|
| + ** the RELEASE call below can never fail.
|
| + */
|
| + assert( p->iStatement==0 || db->flags&SQLITE_CountRows );
|
| + rc = sqlite3VdbeCloseStatement(p, SAVEPOINT_RELEASE);
|
| + if( NEVER(rc!=SQLITE_OK) ){
|
| + break;
|
| + }
|
| +
|
| + /* Invalidate all ephemeral cursor row caches */
|
| + p->cacheCtr = (p->cacheCtr + 2)|1;
|
| +
|
| + /* Make sure the results of the current row are \000 terminated
|
| + ** and have an assigned type. The results are de-ephemeralized as
|
| + ** a side effect.
|
| + */
|
| + pMem = p->pResultSet = &aMem[pOp->p1];
|
| + for(i=0; i<pOp->p2; i++){
|
| + assert( memIsValid(&pMem[i]) );
|
| + Deephemeralize(&pMem[i]);
|
| + assert( (pMem[i].flags & MEM_Ephem)==0
|
| + || (pMem[i].flags & (MEM_Str|MEM_Blob))==0 );
|
| + sqlite3VdbeMemNulTerminate(&pMem[i]);
|
| + REGISTER_TRACE(pOp->p1+i, &pMem[i]);
|
| + }
|
| + if( db->mallocFailed ) goto no_mem;
|
| +
|
| + /* Return SQLITE_ROW
|
| + */
|
| + p->pc = (int)(pOp - aOp) + 1;
|
| + rc = SQLITE_ROW;
|
| + goto vdbe_return;
|
| +}
|
| +
|
| +/* Opcode: Concat P1 P2 P3 * *
|
| +** Synopsis: r[P3]=r[P2]+r[P1]
|
| +**
|
| +** Add the text in register P1 onto the end of the text in
|
| +** register P2 and store the result in register P3.
|
| +** If either the P1 or P2 text are NULL then store NULL in P3.
|
| +**
|
| +** P3 = P2 || P1
|
| +**
|
| +** It is illegal for P1 and P3 to be the same register. Sometimes,
|
| +** if P3 is the same register as P2, the implementation is able
|
| +** to avoid a memcpy().
|
| +*/
|
| +case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */
|
| + i64 nByte;
|
| +
|
| + pIn1 = &aMem[pOp->p1];
|
| + pIn2 = &aMem[pOp->p2];
|
| + pOut = &aMem[pOp->p3];
|
| + assert( pIn1!=pOut );
|
| + if( (pIn1->flags | pIn2->flags) & MEM_Null ){
|
| + sqlite3VdbeMemSetNull(pOut);
|
| + break;
|
| + }
|
| + if( ExpandBlob(pIn1) || ExpandBlob(pIn2) ) goto no_mem;
|
| + Stringify(pIn1, encoding);
|
| + Stringify(pIn2, encoding);
|
| + nByte = pIn1->n + pIn2->n;
|
| + if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
|
| + goto too_big;
|
| + }
|
| + if( sqlite3VdbeMemGrow(pOut, (int)nByte+2, pOut==pIn2) ){
|
| + goto no_mem;
|
| + }
|
| + MemSetTypeFlag(pOut, MEM_Str);
|
| + if( pOut!=pIn2 ){
|
| + memcpy(pOut->z, pIn2->z, pIn2->n);
|
| + }
|
| + memcpy(&pOut->z[pIn2->n], pIn1->z, pIn1->n);
|
| + pOut->z[nByte]=0;
|
| + pOut->z[nByte+1] = 0;
|
| + pOut->flags |= MEM_Term;
|
| + pOut->n = (int)nByte;
|
| + pOut->enc = encoding;
|
| + UPDATE_MAX_BLOBSIZE(pOut);
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: Add P1 P2 P3 * *
|
| +** Synopsis: r[P3]=r[P1]+r[P2]
|
| +**
|
| +** Add the value in register P1 to the value in register P2
|
| +** and store the result in register P3.
|
| +** If either input is NULL, the result is NULL.
|
| +*/
|
| +/* Opcode: Multiply P1 P2 P3 * *
|
| +** Synopsis: r[P3]=r[P1]*r[P2]
|
| +**
|
| +**
|
| +** Multiply the value in register P1 by the value in register P2
|
| +** and store the result in register P3.
|
| +** If either input is NULL, the result is NULL.
|
| +*/
|
| +/* Opcode: Subtract P1 P2 P3 * *
|
| +** Synopsis: r[P3]=r[P2]-r[P1]
|
| +**
|
| +** Subtract the value in register P1 from the value in register P2
|
| +** and store the result in register P3.
|
| +** If either input is NULL, the result is NULL.
|
| +*/
|
| +/* Opcode: Divide P1 P2 P3 * *
|
| +** Synopsis: r[P3]=r[P2]/r[P1]
|
| +**
|
| +** Divide the value in register P1 by the value in register P2
|
| +** and store the result in register P3 (P3=P2/P1). If the value in
|
| +** register P1 is zero, then the result is NULL. If either input is
|
| +** NULL, the result is NULL.
|
| +*/
|
| +/* Opcode: Remainder P1 P2 P3 * *
|
| +** Synopsis: r[P3]=r[P2]%r[P1]
|
| +**
|
| +** Compute the remainder after integer register P2 is divided by
|
| +** register P1 and store the result in register P3.
|
| +** If the value in register P1 is zero the result is NULL.
|
| +** If either operand is NULL, the result is NULL.
|
| +*/
|
| +case OP_Add: /* same as TK_PLUS, in1, in2, out3 */
|
| +case OP_Subtract: /* same as TK_MINUS, in1, in2, out3 */
|
| +case OP_Multiply: /* same as TK_STAR, in1, in2, out3 */
|
| +case OP_Divide: /* same as TK_SLASH, in1, in2, out3 */
|
| +case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */
|
| + char bIntint; /* Started out as two integer operands */
|
| + u16 flags; /* Combined MEM_* flags from both inputs */
|
| + u16 type1; /* Numeric type of left operand */
|
| + u16 type2; /* Numeric type of right operand */
|
| + i64 iA; /* Integer value of left operand */
|
| + i64 iB; /* Integer value of right operand */
|
| + double rA; /* Real value of left operand */
|
| + double rB; /* Real value of right operand */
|
| +
|
| + pIn1 = &aMem[pOp->p1];
|
| + type1 = numericType(pIn1);
|
| + pIn2 = &aMem[pOp->p2];
|
| + type2 = numericType(pIn2);
|
| + pOut = &aMem[pOp->p3];
|
| + flags = pIn1->flags | pIn2->flags;
|
| + if( (flags & MEM_Null)!=0 ) goto arithmetic_result_is_null;
|
| + if( (type1 & type2 & MEM_Int)!=0 ){
|
| + iA = pIn1->u.i;
|
| + iB = pIn2->u.i;
|
| + bIntint = 1;
|
| + switch( pOp->opcode ){
|
| + case OP_Add: if( sqlite3AddInt64(&iB,iA) ) goto fp_math; break;
|
| + case OP_Subtract: if( sqlite3SubInt64(&iB,iA) ) goto fp_math; break;
|
| + case OP_Multiply: if( sqlite3MulInt64(&iB,iA) ) goto fp_math; break;
|
| + case OP_Divide: {
|
| + if( iA==0 ) goto arithmetic_result_is_null;
|
| + if( iA==-1 && iB==SMALLEST_INT64 ) goto fp_math;
|
| + iB /= iA;
|
| + break;
|
| + }
|
| + default: {
|
| + if( iA==0 ) goto arithmetic_result_is_null;
|
| + if( iA==-1 ) iA = 1;
|
| + iB %= iA;
|
| + break;
|
| + }
|
| + }
|
| + pOut->u.i = iB;
|
| + MemSetTypeFlag(pOut, MEM_Int);
|
| + }else{
|
| + bIntint = 0;
|
| +fp_math:
|
| + rA = sqlite3VdbeRealValue(pIn1);
|
| + rB = sqlite3VdbeRealValue(pIn2);
|
| + switch( pOp->opcode ){
|
| + case OP_Add: rB += rA; break;
|
| + case OP_Subtract: rB -= rA; break;
|
| + case OP_Multiply: rB *= rA; break;
|
| + case OP_Divide: {
|
| + /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
|
| + if( rA==(double)0 ) goto arithmetic_result_is_null;
|
| + rB /= rA;
|
| + break;
|
| + }
|
| + default: {
|
| + iA = (i64)rA;
|
| + iB = (i64)rB;
|
| + if( iA==0 ) goto arithmetic_result_is_null;
|
| + if( iA==-1 ) iA = 1;
|
| + rB = (double)(iB % iA);
|
| + break;
|
| + }
|
| + }
|
| +#ifdef SQLITE_OMIT_FLOATING_POINT
|
| + pOut->u.i = rB;
|
| + MemSetTypeFlag(pOut, MEM_Int);
|
| +#else
|
| + if( sqlite3IsNaN(rB) ){
|
| + goto arithmetic_result_is_null;
|
| + }
|
| + pOut->u.r = rB;
|
| + MemSetTypeFlag(pOut, MEM_Real);
|
| + if( ((type1|type2)&MEM_Real)==0 && !bIntint ){
|
| + sqlite3VdbeIntegerAffinity(pOut);
|
| + }
|
| +#endif
|
| + }
|
| + break;
|
| +
|
| +arithmetic_result_is_null:
|
| + sqlite3VdbeMemSetNull(pOut);
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: CollSeq P1 * * P4
|
| +**
|
| +** P4 is a pointer to a CollSeq struct. If the next call to a user function
|
| +** or aggregate calls sqlite3GetFuncCollSeq(), this collation sequence will
|
| +** be returned. This is used by the built-in min(), max() and nullif()
|
| +** functions.
|
| +**
|
| +** If P1 is not zero, then it is a register that a subsequent min() or
|
| +** max() aggregate will set to 1 if the current row is not the minimum or
|
| +** maximum. The P1 register is initialized to 0 by this instruction.
|
| +**
|
| +** The interface used by the implementation of the aforementioned functions
|
| +** to retrieve the collation sequence set by this opcode is not available
|
| +** publicly. Only built-in functions have access to this feature.
|
| +*/
|
| +case OP_CollSeq: {
|
| + assert( pOp->p4type==P4_COLLSEQ );
|
| + if( pOp->p1 ){
|
| + sqlite3VdbeMemSetInt64(&aMem[pOp->p1], 0);
|
| + }
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: Function0 P1 P2 P3 P4 P5
|
| +** Synopsis: r[P3]=func(r[P2@P5])
|
| +**
|
| +** Invoke a user function (P4 is a pointer to a FuncDef object that
|
| +** defines the function) with P5 arguments taken from register P2 and
|
| +** successors. The result of the function is stored in register P3.
|
| +** Register P3 must not be one of the function inputs.
|
| +**
|
| +** P1 is a 32-bit bitmask indicating whether or not each argument to the
|
| +** function was determined to be constant at compile time. If the first
|
| +** argument was constant then bit 0 of P1 is set. This is used to determine
|
| +** whether meta data associated with a user function argument using the
|
| +** sqlite3_set_auxdata() API may be safely retained until the next
|
| +** invocation of this opcode.
|
| +**
|
| +** See also: Function, AggStep, AggFinal
|
| +*/
|
| +/* Opcode: Function P1 P2 P3 P4 P5
|
| +** Synopsis: r[P3]=func(r[P2@P5])
|
| +**
|
| +** Invoke a user function (P4 is a pointer to an sqlite3_context object that
|
| +** contains a pointer to the function to be run) with P5 arguments taken
|
| +** from register P2 and successors. The result of the function is stored
|
| +** in register P3. Register P3 must not be one of the function inputs.
|
| +**
|
| +** P1 is a 32-bit bitmask indicating whether or not each argument to the
|
| +** function was determined to be constant at compile time. If the first
|
| +** argument was constant then bit 0 of P1 is set. This is used to determine
|
| +** whether meta data associated with a user function argument using the
|
| +** sqlite3_set_auxdata() API may be safely retained until the next
|
| +** invocation of this opcode.
|
| +**
|
| +** SQL functions are initially coded as OP_Function0 with P4 pointing
|
| +** to a FuncDef object. But on first evaluation, the P4 operand is
|
| +** automatically converted into an sqlite3_context object and the operation
|
| +** changed to this OP_Function opcode. In this way, the initialization of
|
| +** the sqlite3_context object occurs only once, rather than once for each
|
| +** evaluation of the function.
|
| +**
|
| +** See also: Function0, AggStep, AggFinal
|
| +*/
|
| +case OP_Function0: {
|
| + int n;
|
| + sqlite3_context *pCtx;
|
| +
|
| + assert( pOp->p4type==P4_FUNCDEF );
|
| + n = pOp->p5;
|
| + assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
|
| + assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem-p->nCursor)+1) );
|
| + assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n );
|
| + pCtx = sqlite3DbMallocRaw(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*));
|
| + if( pCtx==0 ) goto no_mem;
|
| + pCtx->pOut = 0;
|
| + pCtx->pFunc = pOp->p4.pFunc;
|
| + pCtx->iOp = (int)(pOp - aOp);
|
| + pCtx->pVdbe = p;
|
| + pCtx->argc = n;
|
| + pOp->p4type = P4_FUNCCTX;
|
| + pOp->p4.pCtx = pCtx;
|
| + pOp->opcode = OP_Function;
|
| + /* Fall through into OP_Function */
|
| +}
|
| +case OP_Function: {
|
| + int i;
|
| + sqlite3_context *pCtx;
|
| +
|
| + assert( pOp->p4type==P4_FUNCCTX );
|
| + pCtx = pOp->p4.pCtx;
|
| +
|
| + /* If this function is inside of a trigger, the register array in aMem[]
|
| + ** might change from one evaluation to the next. The next block of code
|
| + ** checks to see if the register array has changed, and if so it
|
| + ** reinitializes the relavant parts of the sqlite3_context object */
|
| + pOut = &aMem[pOp->p3];
|
| + if( pCtx->pOut != pOut ){
|
| + pCtx->pOut = pOut;
|
| + for(i=pCtx->argc-1; i>=0; i--) pCtx->argv[i] = &aMem[pOp->p2+i];
|
| + }
|
| +
|
| + memAboutToChange(p, pCtx->pOut);
|
| +#ifdef SQLITE_DEBUG
|
| + for(i=0; i<pCtx->argc; i++){
|
| + assert( memIsValid(pCtx->argv[i]) );
|
| + REGISTER_TRACE(pOp->p2+i, pCtx->argv[i]);
|
| + }
|
| +#endif
|
| + MemSetTypeFlag(pCtx->pOut, MEM_Null);
|
| + pCtx->fErrorOrAux = 0;
|
| + db->lastRowid = lastRowid;
|
| + (*pCtx->pFunc->xFunc)(pCtx, pCtx->argc, pCtx->argv); /* IMP: R-24505-23230 */
|
| + lastRowid = db->lastRowid; /* Remember rowid changes made by xFunc */
|
| +
|
| + /* If the function returned an error, throw an exception */
|
| + if( pCtx->fErrorOrAux ){
|
| + if( pCtx->isError ){
|
| + sqlite3VdbeError(p, "%s", sqlite3_value_text(pCtx->pOut));
|
| + rc = pCtx->isError;
|
| + }
|
| + sqlite3VdbeDeleteAuxData(p, pCtx->iOp, pOp->p1);
|
| + }
|
| +
|
| + /* Copy the result of the function into register P3 */
|
| + if( pOut->flags & (MEM_Str|MEM_Blob) ){
|
| + sqlite3VdbeChangeEncoding(pCtx->pOut, encoding);
|
| + if( sqlite3VdbeMemTooBig(pCtx->pOut) ) goto too_big;
|
| + }
|
| +
|
| + REGISTER_TRACE(pOp->p3, pCtx->pOut);
|
| + UPDATE_MAX_BLOBSIZE(pCtx->pOut);
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: BitAnd P1 P2 P3 * *
|
| +** Synopsis: r[P3]=r[P1]&r[P2]
|
| +**
|
| +** Take the bit-wise AND of the values in register P1 and P2 and
|
| +** store the result in register P3.
|
| +** If either input is NULL, the result is NULL.
|
| +*/
|
| +/* Opcode: BitOr P1 P2 P3 * *
|
| +** Synopsis: r[P3]=r[P1]|r[P2]
|
| +**
|
| +** Take the bit-wise OR of the values in register P1 and P2 and
|
| +** store the result in register P3.
|
| +** If either input is NULL, the result is NULL.
|
| +*/
|
| +/* Opcode: ShiftLeft P1 P2 P3 * *
|
| +** Synopsis: r[P3]=r[P2]<<r[P1]
|
| +**
|
| +** Shift the integer value in register P2 to the left by the
|
| +** number of bits specified by the integer in register P1.
|
| +** Store the result in register P3.
|
| +** If either input is NULL, the result is NULL.
|
| +*/
|
| +/* Opcode: ShiftRight P1 P2 P3 * *
|
| +** Synopsis: r[P3]=r[P2]>>r[P1]
|
| +**
|
| +** Shift the integer value in register P2 to the right by the
|
| +** number of bits specified by the integer in register P1.
|
| +** Store the result in register P3.
|
| +** If either input is NULL, the result is NULL.
|
| +*/
|
| +case OP_BitAnd: /* same as TK_BITAND, in1, in2, out3 */
|
| +case OP_BitOr: /* same as TK_BITOR, in1, in2, out3 */
|
| +case OP_ShiftLeft: /* same as TK_LSHIFT, in1, in2, out3 */
|
| +case OP_ShiftRight: { /* same as TK_RSHIFT, in1, in2, out3 */
|
| + i64 iA;
|
| + u64 uA;
|
| + i64 iB;
|
| + u8 op;
|
| +
|
| + pIn1 = &aMem[pOp->p1];
|
| + pIn2 = &aMem[pOp->p2];
|
| + pOut = &aMem[pOp->p3];
|
| + if( (pIn1->flags | pIn2->flags) & MEM_Null ){
|
| + sqlite3VdbeMemSetNull(pOut);
|
| + break;
|
| + }
|
| + iA = sqlite3VdbeIntValue(pIn2);
|
| + iB = sqlite3VdbeIntValue(pIn1);
|
| + op = pOp->opcode;
|
| + if( op==OP_BitAnd ){
|
| + iA &= iB;
|
| + }else if( op==OP_BitOr ){
|
| + iA |= iB;
|
| + }else if( iB!=0 ){
|
| + assert( op==OP_ShiftRight || op==OP_ShiftLeft );
|
| +
|
| + /* If shifting by a negative amount, shift in the other direction */
|
| + if( iB<0 ){
|
| + assert( OP_ShiftRight==OP_ShiftLeft+1 );
|
| + op = 2*OP_ShiftLeft + 1 - op;
|
| + iB = iB>(-64) ? -iB : 64;
|
| + }
|
| +
|
| + if( iB>=64 ){
|
| + iA = (iA>=0 || op==OP_ShiftLeft) ? 0 : -1;
|
| + }else{
|
| + memcpy(&uA, &iA, sizeof(uA));
|
| + if( op==OP_ShiftLeft ){
|
| + uA <<= iB;
|
| + }else{
|
| + uA >>= iB;
|
| + /* Sign-extend on a right shift of a negative number */
|
| + if( iA<0 ) uA |= ((((u64)0xffffffff)<<32)|0xffffffff) << (64-iB);
|
| + }
|
| + memcpy(&iA, &uA, sizeof(iA));
|
| + }
|
| + }
|
| + pOut->u.i = iA;
|
| + MemSetTypeFlag(pOut, MEM_Int);
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: AddImm P1 P2 * * *
|
| +** Synopsis: r[P1]=r[P1]+P2
|
| +**
|
| +** Add the constant P2 to the value in register P1.
|
| +** The result is always an integer.
|
| +**
|
| +** To force any register to be an integer, just add 0.
|
| +*/
|
| +case OP_AddImm: { /* in1 */
|
| + pIn1 = &aMem[pOp->p1];
|
| + memAboutToChange(p, pIn1);
|
| + sqlite3VdbeMemIntegerify(pIn1);
|
| + pIn1->u.i += pOp->p2;
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: MustBeInt P1 P2 * * *
|
| +**
|
| +** Force the value in register P1 to be an integer. If the value
|
| +** in P1 is not an integer and cannot be converted into an integer
|
| +** without data loss, then jump immediately to P2, or if P2==0
|
| +** raise an SQLITE_MISMATCH exception.
|
| +*/
|
| +case OP_MustBeInt: { /* jump, in1 */
|
| + pIn1 = &aMem[pOp->p1];
|
| + if( (pIn1->flags & MEM_Int)==0 ){
|
| + applyAffinity(pIn1, SQLITE_AFF_NUMERIC, encoding);
|
| + VdbeBranchTaken((pIn1->flags&MEM_Int)==0, 2);
|
| + if( (pIn1->flags & MEM_Int)==0 ){
|
| + if( pOp->p2==0 ){
|
| + rc = SQLITE_MISMATCH;
|
| + goto abort_due_to_error;
|
| + }else{
|
| + goto jump_to_p2;
|
| + }
|
| + }
|
| + }
|
| + MemSetTypeFlag(pIn1, MEM_Int);
|
| + break;
|
| +}
|
| +
|
| +#ifndef SQLITE_OMIT_FLOATING_POINT
|
| +/* Opcode: RealAffinity P1 * * * *
|
| +**
|
| +** If register P1 holds an integer convert it to a real value.
|
| +**
|
| +** This opcode is used when extracting information from a column that
|
| +** has REAL affinity. Such column values may still be stored as
|
| +** integers, for space efficiency, but after extraction we want them
|
| +** to have only a real value.
|
| +*/
|
| +case OP_RealAffinity: { /* in1 */
|
| + pIn1 = &aMem[pOp->p1];
|
| + if( pIn1->flags & MEM_Int ){
|
| + sqlite3VdbeMemRealify(pIn1);
|
| + }
|
| + break;
|
| +}
|
| +#endif
|
| +
|
| +#ifndef SQLITE_OMIT_CAST
|
| +/* Opcode: Cast P1 P2 * * *
|
| +** Synopsis: affinity(r[P1])
|
| +**
|
| +** Force the value in register P1 to be the type defined by P2.
|
| +**
|
| +** <ul>
|
| +** <li value="97"> TEXT
|
| +** <li value="98"> BLOB
|
| +** <li value="99"> NUMERIC
|
| +** <li value="100"> INTEGER
|
| +** <li value="101"> REAL
|
| +** </ul>
|
| +**
|
| +** A NULL value is not changed by this routine. It remains NULL.
|
| +*/
|
| +case OP_Cast: { /* in1 */
|
| + assert( pOp->p2>=SQLITE_AFF_BLOB && pOp->p2<=SQLITE_AFF_REAL );
|
| + testcase( pOp->p2==SQLITE_AFF_TEXT );
|
| + testcase( pOp->p2==SQLITE_AFF_BLOB );
|
| + testcase( pOp->p2==SQLITE_AFF_NUMERIC );
|
| + testcase( pOp->p2==SQLITE_AFF_INTEGER );
|
| + testcase( pOp->p2==SQLITE_AFF_REAL );
|
| + pIn1 = &aMem[pOp->p1];
|
| + memAboutToChange(p, pIn1);
|
| + rc = ExpandBlob(pIn1);
|
| + sqlite3VdbeMemCast(pIn1, pOp->p2, encoding);
|
| + UPDATE_MAX_BLOBSIZE(pIn1);
|
| + break;
|
| +}
|
| +#endif /* SQLITE_OMIT_CAST */
|
| +
|
| +/* Opcode: Lt P1 P2 P3 P4 P5
|
| +** Synopsis: if r[P1]<r[P3] goto P2
|
| +**
|
| +** Compare the values in register P1 and P3. If reg(P3)<reg(P1) then
|
| +** jump to address P2.
|
| +**
|
| +** If the SQLITE_JUMPIFNULL bit of P5 is set and either reg(P1) or
|
| +** reg(P3) is NULL then take the jump. If the SQLITE_JUMPIFNULL
|
| +** bit is clear then fall through if either operand is NULL.
|
| +**
|
| +** The SQLITE_AFF_MASK portion of P5 must be an affinity character -
|
| +** SQLITE_AFF_TEXT, SQLITE_AFF_INTEGER, and so forth. An attempt is made
|
| +** to coerce both inputs according to this affinity before the
|
| +** comparison is made. If the SQLITE_AFF_MASK is 0x00, then numeric
|
| +** affinity is used. Note that the affinity conversions are stored
|
| +** back into the input registers P1 and P3. So this opcode can cause
|
| +** persistent changes to registers P1 and P3.
|
| +**
|
| +** Once any conversions have taken place, and neither value is NULL,
|
| +** the values are compared. If both values are blobs then memcmp() is
|
| +** used to determine the results of the comparison. If both values
|
| +** are text, then the appropriate collating function specified in
|
| +** P4 is used to do the comparison. If P4 is not specified then
|
| +** memcmp() is used to compare text string. If both values are
|
| +** numeric, then a numeric comparison is used. If the two values
|
| +** are of different types, then numbers are considered less than
|
| +** strings and strings are considered less than blobs.
|
| +**
|
| +** If the SQLITE_STOREP2 bit of P5 is set, then do not jump. Instead,
|
| +** store a boolean result (either 0, or 1, or NULL) in register P2.
|
| +**
|
| +** If the SQLITE_NULLEQ bit is set in P5, then NULL values are considered
|
| +** equal to one another, provided that they do not have their MEM_Cleared
|
| +** bit set.
|
| +*/
|
| +/* Opcode: Ne P1 P2 P3 P4 P5
|
| +** Synopsis: if r[P1]!=r[P3] goto P2
|
| +**
|
| +** This works just like the Lt opcode except that the jump is taken if
|
| +** the operands in registers P1 and P3 are not equal. See the Lt opcode for
|
| +** additional information.
|
| +**
|
| +** If SQLITE_NULLEQ is set in P5 then the result of comparison is always either
|
| +** true or false and is never NULL. If both operands are NULL then the result
|
| +** of comparison is false. If either operand is NULL then the result is true.
|
| +** If neither operand is NULL the result is the same as it would be if
|
| +** the SQLITE_NULLEQ flag were omitted from P5.
|
| +*/
|
| +/* Opcode: Eq P1 P2 P3 P4 P5
|
| +** Synopsis: if r[P1]==r[P3] goto P2
|
| +**
|
| +** This works just like the Lt opcode except that the jump is taken if
|
| +** the operands in registers P1 and P3 are equal.
|
| +** See the Lt opcode for additional information.
|
| +**
|
| +** If SQLITE_NULLEQ is set in P5 then the result of comparison is always either
|
| +** true or false and is never NULL. If both operands are NULL then the result
|
| +** of comparison is true. If either operand is NULL then the result is false.
|
| +** If neither operand is NULL the result is the same as it would be if
|
| +** the SQLITE_NULLEQ flag were omitted from P5.
|
| +*/
|
| +/* Opcode: Le P1 P2 P3 P4 P5
|
| +** Synopsis: if r[P1]<=r[P3] goto P2
|
| +**
|
| +** This works just like the Lt opcode except that the jump is taken if
|
| +** the content of register P3 is less than or equal to the content of
|
| +** register P1. See the Lt opcode for additional information.
|
| +*/
|
| +/* Opcode: Gt P1 P2 P3 P4 P5
|
| +** Synopsis: if r[P1]>r[P3] goto P2
|
| +**
|
| +** This works just like the Lt opcode except that the jump is taken if
|
| +** the content of register P3 is greater than the content of
|
| +** register P1. See the Lt opcode for additional information.
|
| +*/
|
| +/* Opcode: Ge P1 P2 P3 P4 P5
|
| +** Synopsis: if r[P1]>=r[P3] goto P2
|
| +**
|
| +** This works just like the Lt opcode except that the jump is taken if
|
| +** the content of register P3 is greater than or equal to the content of
|
| +** register P1. See the Lt opcode for additional information.
|
| +*/
|
| +case OP_Eq: /* same as TK_EQ, jump, in1, in3 */
|
| +case OP_Ne: /* same as TK_NE, jump, in1, in3 */
|
| +case OP_Lt: /* same as TK_LT, jump, in1, in3 */
|
| +case OP_Le: /* same as TK_LE, jump, in1, in3 */
|
| +case OP_Gt: /* same as TK_GT, jump, in1, in3 */
|
| +case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
|
| + int res; /* Result of the comparison of pIn1 against pIn3 */
|
| + char affinity; /* Affinity to use for comparison */
|
| + u16 flags1; /* Copy of initial value of pIn1->flags */
|
| + u16 flags3; /* Copy of initial value of pIn3->flags */
|
| +
|
| + pIn1 = &aMem[pOp->p1];
|
| + pIn3 = &aMem[pOp->p3];
|
| + flags1 = pIn1->flags;
|
| + flags3 = pIn3->flags;
|
| + if( (flags1 | flags3)&MEM_Null ){
|
| + /* One or both operands are NULL */
|
| + if( pOp->p5 & SQLITE_NULLEQ ){
|
| + /* If SQLITE_NULLEQ is set (which will only happen if the operator is
|
| + ** OP_Eq or OP_Ne) then take the jump or not depending on whether
|
| + ** or not both operands are null.
|
| + */
|
| + assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne );
|
| + assert( (flags1 & MEM_Cleared)==0 );
|
| + assert( (pOp->p5 & SQLITE_JUMPIFNULL)==0 );
|
| + if( (flags1&MEM_Null)!=0
|
| + && (flags3&MEM_Null)!=0
|
| + && (flags3&MEM_Cleared)==0
|
| + ){
|
| + res = 0; /* Results are equal */
|
| + }else{
|
| + res = 1; /* Results are not equal */
|
| + }
|
| + }else{
|
| + /* SQLITE_NULLEQ is clear and at least one operand is NULL,
|
| + ** then the result is always NULL.
|
| + ** The jump is taken if the SQLITE_JUMPIFNULL bit is set.
|
| + */
|
| + if( pOp->p5 & SQLITE_STOREP2 ){
|
| + pOut = &aMem[pOp->p2];
|
| + memAboutToChange(p, pOut);
|
| + MemSetTypeFlag(pOut, MEM_Null);
|
| + REGISTER_TRACE(pOp->p2, pOut);
|
| + }else{
|
| + VdbeBranchTaken(2,3);
|
| + if( pOp->p5 & SQLITE_JUMPIFNULL ){
|
| + goto jump_to_p2;
|
| + }
|
| + }
|
| + break;
|
| + }
|
| + }else{
|
| + /* Neither operand is NULL. Do a comparison. */
|
| + affinity = pOp->p5 & SQLITE_AFF_MASK;
|
| + if( affinity>=SQLITE_AFF_NUMERIC ){
|
| + if( (flags1 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){
|
| + applyNumericAffinity(pIn1,0);
|
| + }
|
| + if( (flags3 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){
|
| + applyNumericAffinity(pIn3,0);
|
| + }
|
| + }else if( affinity==SQLITE_AFF_TEXT ){
|
| + if( (flags1 & MEM_Str)==0 && (flags1 & (MEM_Int|MEM_Real))!=0 ){
|
| + testcase( pIn1->flags & MEM_Int );
|
| + testcase( pIn1->flags & MEM_Real );
|
| + sqlite3VdbeMemStringify(pIn1, encoding, 1);
|
| + testcase( (flags1&MEM_Dyn) != (pIn1->flags&MEM_Dyn) );
|
| + flags1 = (pIn1->flags & ~MEM_TypeMask) | (flags1 & MEM_TypeMask);
|
| + }
|
| + if( (flags3 & MEM_Str)==0 && (flags3 & (MEM_Int|MEM_Real))!=0 ){
|
| + testcase( pIn3->flags & MEM_Int );
|
| + testcase( pIn3->flags & MEM_Real );
|
| + sqlite3VdbeMemStringify(pIn3, encoding, 1);
|
| + testcase( (flags3&MEM_Dyn) != (pIn3->flags&MEM_Dyn) );
|
| + flags3 = (pIn3->flags & ~MEM_TypeMask) | (flags3 & MEM_TypeMask);
|
| + }
|
| + }
|
| + assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 );
|
| + if( flags1 & MEM_Zero ){
|
| + sqlite3VdbeMemExpandBlob(pIn1);
|
| + flags1 &= ~MEM_Zero;
|
| + }
|
| + if( flags3 & MEM_Zero ){
|
| + sqlite3VdbeMemExpandBlob(pIn3);
|
| + flags3 &= ~MEM_Zero;
|
| + }
|
| + res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl);
|
| + }
|
| + switch( pOp->opcode ){
|
| + case OP_Eq: res = res==0; break;
|
| + case OP_Ne: res = res!=0; break;
|
| + case OP_Lt: res = res<0; break;
|
| + case OP_Le: res = res<=0; break;
|
| + case OP_Gt: res = res>0; break;
|
| + default: res = res>=0; break;
|
| + }
|
| +
|
| + /* Undo any changes made by applyAffinity() to the input registers. */
|
| + assert( (pIn1->flags & MEM_Dyn) == (flags1 & MEM_Dyn) );
|
| + pIn1->flags = flags1;
|
| + assert( (pIn3->flags & MEM_Dyn) == (flags3 & MEM_Dyn) );
|
| + pIn3->flags = flags3;
|
| +
|
| + if( pOp->p5 & SQLITE_STOREP2 ){
|
| + pOut = &aMem[pOp->p2];
|
| + memAboutToChange(p, pOut);
|
| + MemSetTypeFlag(pOut, MEM_Int);
|
| + pOut->u.i = res;
|
| + REGISTER_TRACE(pOp->p2, pOut);
|
| + }else{
|
| + VdbeBranchTaken(res!=0, (pOp->p5 & SQLITE_NULLEQ)?2:3);
|
| + if( res ){
|
| + goto jump_to_p2;
|
| + }
|
| + }
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: Permutation * * * P4 *
|
| +**
|
| +** Set the permutation used by the OP_Compare operator to be the array
|
| +** of integers in P4.
|
| +**
|
| +** The permutation is only valid until the next OP_Compare that has
|
| +** the OPFLAG_PERMUTE bit set in P5. Typically the OP_Permutation should
|
| +** occur immediately prior to the OP_Compare.
|
| +*/
|
| +case OP_Permutation: {
|
| + assert( pOp->p4type==P4_INTARRAY );
|
| + assert( pOp->p4.ai );
|
| + aPermute = pOp->p4.ai;
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: Compare P1 P2 P3 P4 P5
|
| +** Synopsis: r[P1@P3] <-> r[P2@P3]
|
| +**
|
| +** Compare two vectors of registers in reg(P1)..reg(P1+P3-1) (call this
|
| +** vector "A") and in reg(P2)..reg(P2+P3-1) ("B"). Save the result of
|
| +** the comparison for use by the next OP_Jump instruct.
|
| +**
|
| +** If P5 has the OPFLAG_PERMUTE bit set, then the order of comparison is
|
| +** determined by the most recent OP_Permutation operator. If the
|
| +** OPFLAG_PERMUTE bit is clear, then register are compared in sequential
|
| +** order.
|
| +**
|
| +** P4 is a KeyInfo structure that defines collating sequences and sort
|
| +** orders for the comparison. The permutation applies to registers
|
| +** only. The KeyInfo elements are used sequentially.
|
| +**
|
| +** The comparison is a sort comparison, so NULLs compare equal,
|
| +** NULLs are less than numbers, numbers are less than strings,
|
| +** and strings are less than blobs.
|
| +*/
|
| +case OP_Compare: {
|
| + int n;
|
| + int i;
|
| + int p1;
|
| + int p2;
|
| + const KeyInfo *pKeyInfo;
|
| + int idx;
|
| + CollSeq *pColl; /* Collating sequence to use on this term */
|
| + int bRev; /* True for DESCENDING sort order */
|
| +
|
| + if( (pOp->p5 & OPFLAG_PERMUTE)==0 ) aPermute = 0;
|
| + n = pOp->p3;
|
| + pKeyInfo = pOp->p4.pKeyInfo;
|
| + assert( n>0 );
|
| + assert( pKeyInfo!=0 );
|
| + p1 = pOp->p1;
|
| + p2 = pOp->p2;
|
| +#if SQLITE_DEBUG
|
| + if( aPermute ){
|
| + int k, mx = 0;
|
| + for(k=0; k<n; k++) if( aPermute[k]>mx ) mx = aPermute[k];
|
| + assert( p1>0 && p1+mx<=(p->nMem-p->nCursor)+1 );
|
| + assert( p2>0 && p2+mx<=(p->nMem-p->nCursor)+1 );
|
| + }else{
|
| + assert( p1>0 && p1+n<=(p->nMem-p->nCursor)+1 );
|
| + assert( p2>0 && p2+n<=(p->nMem-p->nCursor)+1 );
|
| + }
|
| +#endif /* SQLITE_DEBUG */
|
| + for(i=0; i<n; i++){
|
| + idx = aPermute ? aPermute[i] : i;
|
| + assert( memIsValid(&aMem[p1+idx]) );
|
| + assert( memIsValid(&aMem[p2+idx]) );
|
| + REGISTER_TRACE(p1+idx, &aMem[p1+idx]);
|
| + REGISTER_TRACE(p2+idx, &aMem[p2+idx]);
|
| + assert( i<pKeyInfo->nField );
|
| + pColl = pKeyInfo->aColl[i];
|
| + bRev = pKeyInfo->aSortOrder[i];
|
| + iCompare = sqlite3MemCompare(&aMem[p1+idx], &aMem[p2+idx], pColl);
|
| + if( iCompare ){
|
| + if( bRev ) iCompare = -iCompare;
|
| + break;
|
| + }
|
| + }
|
| + aPermute = 0;
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: Jump P1 P2 P3 * *
|
| +**
|
| +** Jump to the instruction at address P1, P2, or P3 depending on whether
|
| +** in the most recent OP_Compare instruction the P1 vector was less than
|
| +** equal to, or greater than the P2 vector, respectively.
|
| +*/
|
| +case OP_Jump: { /* jump */
|
| + if( iCompare<0 ){
|
| + VdbeBranchTaken(0,3); pOp = &aOp[pOp->p1 - 1];
|
| + }else if( iCompare==0 ){
|
| + VdbeBranchTaken(1,3); pOp = &aOp[pOp->p2 - 1];
|
| + }else{
|
| + VdbeBranchTaken(2,3); pOp = &aOp[pOp->p3 - 1];
|
| + }
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: And P1 P2 P3 * *
|
| +** Synopsis: r[P3]=(r[P1] && r[P2])
|
| +**
|
| +** Take the logical AND of the values in registers P1 and P2 and
|
| +** write the result into register P3.
|
| +**
|
| +** If either P1 or P2 is 0 (false) then the result is 0 even if
|
| +** the other input is NULL. A NULL and true or two NULLs give
|
| +** a NULL output.
|
| +*/
|
| +/* Opcode: Or P1 P2 P3 * *
|
| +** Synopsis: r[P3]=(r[P1] || r[P2])
|
| +**
|
| +** Take the logical OR of the values in register P1 and P2 and
|
| +** store the answer in register P3.
|
| +**
|
| +** If either P1 or P2 is nonzero (true) then the result is 1 (true)
|
| +** even if the other input is NULL. A NULL and false or two NULLs
|
| +** give a NULL output.
|
| +*/
|
| +case OP_And: /* same as TK_AND, in1, in2, out3 */
|
| +case OP_Or: { /* same as TK_OR, in1, in2, out3 */
|
| + int v1; /* Left operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */
|
| + int v2; /* Right operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */
|
| +
|
| + pIn1 = &aMem[pOp->p1];
|
| + if( pIn1->flags & MEM_Null ){
|
| + v1 = 2;
|
| + }else{
|
| + v1 = sqlite3VdbeIntValue(pIn1)!=0;
|
| + }
|
| + pIn2 = &aMem[pOp->p2];
|
| + if( pIn2->flags & MEM_Null ){
|
| + v2 = 2;
|
| + }else{
|
| + v2 = sqlite3VdbeIntValue(pIn2)!=0;
|
| + }
|
| + if( pOp->opcode==OP_And ){
|
| + static const unsigned char and_logic[] = { 0, 0, 0, 0, 1, 2, 0, 2, 2 };
|
| + v1 = and_logic[v1*3+v2];
|
| + }else{
|
| + static const unsigned char or_logic[] = { 0, 1, 2, 1, 1, 1, 2, 1, 2 };
|
| + v1 = or_logic[v1*3+v2];
|
| + }
|
| + pOut = &aMem[pOp->p3];
|
| + if( v1==2 ){
|
| + MemSetTypeFlag(pOut, MEM_Null);
|
| + }else{
|
| + pOut->u.i = v1;
|
| + MemSetTypeFlag(pOut, MEM_Int);
|
| + }
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: Not P1 P2 * * *
|
| +** Synopsis: r[P2]= !r[P1]
|
| +**
|
| +** Interpret the value in register P1 as a boolean value. Store the
|
| +** boolean complement in register P2. If the value in register P1 is
|
| +** NULL, then a NULL is stored in P2.
|
| +*/
|
| +case OP_Not: { /* same as TK_NOT, in1, out2 */
|
| + pIn1 = &aMem[pOp->p1];
|
| + pOut = &aMem[pOp->p2];
|
| + sqlite3VdbeMemSetNull(pOut);
|
| + if( (pIn1->flags & MEM_Null)==0 ){
|
| + pOut->flags = MEM_Int;
|
| + pOut->u.i = !sqlite3VdbeIntValue(pIn1);
|
| + }
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: BitNot P1 P2 * * *
|
| +** Synopsis: r[P1]= ~r[P1]
|
| +**
|
| +** Interpret the content of register P1 as an integer. Store the
|
| +** ones-complement of the P1 value into register P2. If P1 holds
|
| +** a NULL then store a NULL in P2.
|
| +*/
|
| +case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */
|
| + pIn1 = &aMem[pOp->p1];
|
| + pOut = &aMem[pOp->p2];
|
| + sqlite3VdbeMemSetNull(pOut);
|
| + if( (pIn1->flags & MEM_Null)==0 ){
|
| + pOut->flags = MEM_Int;
|
| + pOut->u.i = ~sqlite3VdbeIntValue(pIn1);
|
| + }
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: Once P1 P2 * * *
|
| +**
|
| +** Check the "once" flag number P1. If it is set, jump to instruction P2.
|
| +** Otherwise, set the flag and fall through to the next instruction.
|
| +** In other words, this opcode causes all following opcodes up through P2
|
| +** (but not including P2) to run just once and to be skipped on subsequent
|
| +** times through the loop.
|
| +**
|
| +** All "once" flags are initially cleared whenever a prepared statement
|
| +** first begins to run.
|
| +*/
|
| +case OP_Once: { /* jump */
|
| + assert( pOp->p1<p->nOnceFlag );
|
| + VdbeBranchTaken(p->aOnceFlag[pOp->p1]!=0, 2);
|
| + if( p->aOnceFlag[pOp->p1] ){
|
| + goto jump_to_p2;
|
| + }else{
|
| + p->aOnceFlag[pOp->p1] = 1;
|
| + }
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: If P1 P2 P3 * *
|
| +**
|
| +** Jump to P2 if the value in register P1 is true. The value
|
| +** is considered true if it is numeric and non-zero. If the value
|
| +** in P1 is NULL then take the jump if and only if P3 is non-zero.
|
| +*/
|
| +/* Opcode: IfNot P1 P2 P3 * *
|
| +**
|
| +** Jump to P2 if the value in register P1 is False. The value
|
| +** is considered false if it has a numeric value of zero. If the value
|
| +** in P1 is NULL then take the jump if and only if P3 is non-zero.
|
| +*/
|
| +case OP_If: /* jump, in1 */
|
| +case OP_IfNot: { /* jump, in1 */
|
| + int c;
|
| + pIn1 = &aMem[pOp->p1];
|
| + if( pIn1->flags & MEM_Null ){
|
| + c = pOp->p3;
|
| + }else{
|
| +#ifdef SQLITE_OMIT_FLOATING_POINT
|
| + c = sqlite3VdbeIntValue(pIn1)!=0;
|
| +#else
|
| + c = sqlite3VdbeRealValue(pIn1)!=0.0;
|
| +#endif
|
| + if( pOp->opcode==OP_IfNot ) c = !c;
|
| + }
|
| + VdbeBranchTaken(c!=0, 2);
|
| + if( c ){
|
| + goto jump_to_p2;
|
| + }
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: IsNull P1 P2 * * *
|
| +** Synopsis: if r[P1]==NULL goto P2
|
| +**
|
| +** Jump to P2 if the value in register P1 is NULL.
|
| +*/
|
| +case OP_IsNull: { /* same as TK_ISNULL, jump, in1 */
|
| + pIn1 = &aMem[pOp->p1];
|
| + VdbeBranchTaken( (pIn1->flags & MEM_Null)!=0, 2);
|
| + if( (pIn1->flags & MEM_Null)!=0 ){
|
| + goto jump_to_p2;
|
| + }
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: NotNull P1 P2 * * *
|
| +** Synopsis: if r[P1]!=NULL goto P2
|
| +**
|
| +** Jump to P2 if the value in register P1 is not NULL.
|
| +*/
|
| +case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */
|
| + pIn1 = &aMem[pOp->p1];
|
| + VdbeBranchTaken( (pIn1->flags & MEM_Null)==0, 2);
|
| + if( (pIn1->flags & MEM_Null)==0 ){
|
| + goto jump_to_p2;
|
| + }
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: Column P1 P2 P3 P4 P5
|
| +** Synopsis: r[P3]=PX
|
| +**
|
| +** Interpret the data that cursor P1 points to as a structure built using
|
| +** the MakeRecord instruction. (See the MakeRecord opcode for additional
|
| +** information about the format of the data.) Extract the P2-th column
|
| +** from this record. If there are less that (P2+1)
|
| +** values in the record, extract a NULL.
|
| +**
|
| +** The value extracted is stored in register P3.
|
| +**
|
| +** If the column contains fewer than P2 fields, then extract a NULL. Or,
|
| +** if the P4 argument is a P4_MEM use the value of the P4 argument as
|
| +** the result.
|
| +**
|
| +** If the OPFLAG_CLEARCACHE bit is set on P5 and P1 is a pseudo-table cursor,
|
| +** then the cache of the cursor is reset prior to extracting the column.
|
| +** The first OP_Column against a pseudo-table after the value of the content
|
| +** register has changed should have this bit set.
|
| +**
|
| +** If the OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG bits are set on P5 when
|
| +** the result is guaranteed to only be used as the argument of a length()
|
| +** or typeof() function, respectively. The loading of large blobs can be
|
| +** skipped for length() and all content loading can be skipped for typeof().
|
| +*/
|
| +case OP_Column: {
|
| + i64 payloadSize64; /* Number of bytes in the record */
|
| + int p2; /* column number to retrieve */
|
| + VdbeCursor *pC; /* The VDBE cursor */
|
| + BtCursor *pCrsr; /* The BTree cursor */
|
| + u32 *aOffset; /* aOffset[i] is offset to start of data for i-th column */
|
| + int len; /* The length of the serialized data for the column */
|
| + int i; /* Loop counter */
|
| + Mem *pDest; /* Where to write the extracted value */
|
| + Mem sMem; /* For storing the record being decoded */
|
| + const u8 *zData; /* Part of the record being decoded */
|
| + const u8 *zHdr; /* Next unparsed byte of the header */
|
| + const u8 *zEndHdr; /* Pointer to first byte after the header */
|
| + u32 offset; /* Offset into the data */
|
| + u64 offset64; /* 64-bit offset */
|
| + u32 avail; /* Number of bytes of available data */
|
| + u32 t; /* A type code from the record header */
|
| + u16 fx; /* pDest->flags value */
|
| + Mem *pReg; /* PseudoTable input register */
|
| +
|
| + p2 = pOp->p2;
|
| + assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
|
| + pDest = &aMem[pOp->p3];
|
| + memAboutToChange(p, pDest);
|
| + assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
| + pC = p->apCsr[pOp->p1];
|
| + assert( pC!=0 );
|
| + assert( p2<pC->nField );
|
| + aOffset = pC->aOffset;
|
| + assert( pC->eCurType!=CURTYPE_VTAB );
|
| + assert( pC->eCurType!=CURTYPE_PSEUDO || pC->nullRow );
|
| + assert( pC->eCurType!=CURTYPE_SORTER );
|
| + pCrsr = pC->uc.pCursor;
|
| +
|
| + /* If the cursor cache is stale, bring it up-to-date */
|
| + rc = sqlite3VdbeCursorMoveto(pC);
|
| + if( rc ) goto abort_due_to_error;
|
| + if( pC->cacheStatus!=p->cacheCtr ){
|
| + if( pC->nullRow ){
|
| + if( pC->eCurType==CURTYPE_PSEUDO ){
|
| + assert( pC->uc.pseudoTableReg>0 );
|
| + pReg = &aMem[pC->uc.pseudoTableReg];
|
| + assert( pReg->flags & MEM_Blob );
|
| + assert( memIsValid(pReg) );
|
| + pC->payloadSize = pC->szRow = avail = pReg->n;
|
| + pC->aRow = (u8*)pReg->z;
|
| + }else{
|
| + sqlite3VdbeMemSetNull(pDest);
|
| + goto op_column_out;
|
| + }
|
| + }else{
|
| + assert( pC->eCurType==CURTYPE_BTREE );
|
| + assert( pCrsr );
|
| + if( pC->isTable==0 ){
|
| + assert( sqlite3BtreeCursorIsValid(pCrsr) );
|
| + VVA_ONLY(rc =) sqlite3BtreeKeySize(pCrsr, &payloadSize64);
|
| + assert( rc==SQLITE_OK ); /* True because of CursorMoveto() call above */
|
| + /* sqlite3BtreeParseCellPtr() uses getVarint32() to extract the
|
| + ** payload size, so it is impossible for payloadSize64 to be
|
| + ** larger than 32 bits. */
|
| + assert( (payloadSize64 & SQLITE_MAX_U32)==(u64)payloadSize64 );
|
| + pC->aRow = sqlite3BtreeKeyFetch(pCrsr, &avail);
|
| + pC->payloadSize = (u32)payloadSize64;
|
| + }else{
|
| + assert( sqlite3BtreeCursorIsValid(pCrsr) );
|
| + VVA_ONLY(rc =) sqlite3BtreeDataSize(pCrsr, &pC->payloadSize);
|
| + assert( rc==SQLITE_OK ); /* DataSize() cannot fail */
|
| + pC->aRow = sqlite3BtreeDataFetch(pCrsr, &avail);
|
| + }
|
| + assert( avail<=65536 ); /* Maximum page size is 64KiB */
|
| + if( pC->payloadSize <= (u32)avail ){
|
| + pC->szRow = pC->payloadSize;
|
| + }else if( pC->payloadSize > (u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
|
| + goto too_big;
|
| + }else{
|
| + pC->szRow = avail;
|
| + }
|
| + }
|
| + pC->cacheStatus = p->cacheCtr;
|
| + pC->iHdrOffset = getVarint32(pC->aRow, offset);
|
| + pC->nHdrParsed = 0;
|
| + aOffset[0] = offset;
|
| +
|
| +
|
| + if( avail<offset ){
|
| + /* pC->aRow does not have to hold the entire row, but it does at least
|
| + ** need to cover the header of the record. If pC->aRow does not contain
|
| + ** the complete header, then set it to zero, forcing the header to be
|
| + ** dynamically allocated. */
|
| + pC->aRow = 0;
|
| + pC->szRow = 0;
|
| +
|
| + /* Make sure a corrupt database has not given us an oversize header.
|
| + ** Do this now to avoid an oversize memory allocation.
|
| + **
|
| + ** Type entries can be between 1 and 5 bytes each. But 4 and 5 byte
|
| + ** types use so much data space that there can only be 4096 and 32 of
|
| + ** them, respectively. So the maximum header length results from a
|
| + ** 3-byte type for each of the maximum of 32768 columns plus three
|
| + ** extra bytes for the header length itself. 32768*3 + 3 = 98307.
|
| + */
|
| + if( offset > 98307 || offset > pC->payloadSize ){
|
| + rc = SQLITE_CORRUPT_BKPT;
|
| + goto op_column_error;
|
| + }
|
| + }
|
| +
|
| + /* The following goto is an optimization. It can be omitted and
|
| + ** everything will still work. But OP_Column is measurably faster
|
| + ** by skipping the subsequent conditional, which is always true.
|
| + */
|
| + assert( pC->nHdrParsed<=p2 ); /* Conditional skipped */
|
| + goto op_column_read_header;
|
| + }
|
| +
|
| + /* Make sure at least the first p2+1 entries of the header have been
|
| + ** parsed and valid information is in aOffset[] and pC->aType[].
|
| + */
|
| + if( pC->nHdrParsed<=p2 ){
|
| + /* If there is more header available for parsing in the record, try
|
| + ** to extract additional fields up through the p2+1-th field
|
| + */
|
| + op_column_read_header:
|
| + if( pC->iHdrOffset<aOffset[0] ){
|
| + /* Make sure zData points to enough of the record to cover the header. */
|
| + if( pC->aRow==0 ){
|
| + memset(&sMem, 0, sizeof(sMem));
|
| + rc = sqlite3VdbeMemFromBtree(pCrsr, 0, aOffset[0], !pC->isTable, &sMem);
|
| + if( rc!=SQLITE_OK ) goto op_column_error;
|
| + zData = (u8*)sMem.z;
|
| + }else{
|
| + zData = pC->aRow;
|
| + }
|
| +
|
| + /* Fill in pC->aType[i] and aOffset[i] values through the p2-th field. */
|
| + i = pC->nHdrParsed;
|
| + offset64 = aOffset[i];
|
| + zHdr = zData + pC->iHdrOffset;
|
| + zEndHdr = zData + aOffset[0];
|
| + assert( i<=p2 && zHdr<zEndHdr );
|
| + do{
|
| + if( (t = zHdr[0])<0x80 ){
|
| + zHdr++;
|
| + offset64 += sqlite3VdbeOneByteSerialTypeLen(t);
|
| + }else{
|
| + zHdr += sqlite3GetVarint32(zHdr, &t);
|
| + offset64 += sqlite3VdbeSerialTypeLen(t);
|
| + }
|
| + pC->aType[i++] = t;
|
| + aOffset[i] = (u32)(offset64 & 0xffffffff);
|
| + }while( i<=p2 && zHdr<zEndHdr );
|
| + pC->nHdrParsed = i;
|
| + pC->iHdrOffset = (u32)(zHdr - zData);
|
| + if( pC->aRow==0 ) sqlite3VdbeMemRelease(&sMem);
|
| +
|
| + /* The record is corrupt if any of the following are true:
|
| + ** (1) the bytes of the header extend past the declared header size
|
| + ** (2) the entire header was used but not all data was used
|
| + ** (3) the end of the data extends beyond the end of the record.
|
| + */
|
| + if( (zHdr>=zEndHdr && (zHdr>zEndHdr || offset64!=pC->payloadSize))
|
| + || (offset64 > pC->payloadSize)
|
| + ){
|
| + rc = SQLITE_CORRUPT_BKPT;
|
| + goto op_column_error;
|
| + }
|
| + }else{
|
| + t = 0;
|
| + }
|
| +
|
| + /* If after trying to extract new entries from the header, nHdrParsed is
|
| + ** still not up to p2, that means that the record has fewer than p2
|
| + ** columns. So the result will be either the default value or a NULL.
|
| + */
|
| + if( pC->nHdrParsed<=p2 ){
|
| + if( pOp->p4type==P4_MEM ){
|
| + sqlite3VdbeMemShallowCopy(pDest, pOp->p4.pMem, MEM_Static);
|
| + }else{
|
| + sqlite3VdbeMemSetNull(pDest);
|
| + }
|
| + goto op_column_out;
|
| + }
|
| + }else{
|
| + t = pC->aType[p2];
|
| + }
|
| +
|
| + /* Extract the content for the p2+1-th column. Control can only
|
| + ** reach this point if aOffset[p2], aOffset[p2+1], and pC->aType[p2] are
|
| + ** all valid.
|
| + */
|
| + assert( p2<pC->nHdrParsed );
|
| + assert( rc==SQLITE_OK );
|
| + assert( sqlite3VdbeCheckMemInvariants(pDest) );
|
| + if( VdbeMemDynamic(pDest) ) sqlite3VdbeMemSetNull(pDest);
|
| + assert( t==pC->aType[p2] );
|
| + if( pC->szRow>=aOffset[p2+1] ){
|
| + /* This is the common case where the desired content fits on the original
|
| + ** page - where the content is not on an overflow page */
|
| + sqlite3VdbeSerialGet(pC->aRow+aOffset[p2], t, pDest);
|
| + }else{
|
| + /* This branch happens only when content is on overflow pages */
|
| + if( ((pOp->p5 & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG))!=0
|
| + && ((t>=12 && (t&1)==0) || (pOp->p5 & OPFLAG_TYPEOFARG)!=0))
|
| + || (len = sqlite3VdbeSerialTypeLen(t))==0
|
| + ){
|
| + /* Content is irrelevant for
|
| + ** 1. the typeof() function,
|
| + ** 2. the length(X) function if X is a blob, and
|
| + ** 3. if the content length is zero.
|
| + ** So we might as well use bogus content rather than reading
|
| + ** content from disk. NULL will work for the value for strings
|
| + ** and blobs and whatever is in the payloadSize64 variable
|
| + ** will work for everything else. */
|
| + sqlite3VdbeSerialGet(t<=13 ? (u8*)&payloadSize64 : 0, t, pDest);
|
| + }else{
|
| + rc = sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len, !pC->isTable,
|
| + pDest);
|
| + if( rc!=SQLITE_OK ){
|
| + goto op_column_error;
|
| + }
|
| + sqlite3VdbeSerialGet((const u8*)pDest->z, t, pDest);
|
| + pDest->flags &= ~MEM_Ephem;
|
| + }
|
| + }
|
| + pDest->enc = encoding;
|
| +
|
| +op_column_out:
|
| + /* If the column value is an ephemeral string, go ahead and persist
|
| + ** that string in case the cursor moves before the column value is
|
| + ** used. The following code does the equivalent of Deephemeralize()
|
| + ** but does it faster. */
|
| + if( (pDest->flags & MEM_Ephem)!=0 && pDest->z ){
|
| + fx = pDest->flags & (MEM_Str|MEM_Blob);
|
| + assert( fx!=0 );
|
| + zData = (const u8*)pDest->z;
|
| + len = pDest->n;
|
| + if( sqlite3VdbeMemClearAndResize(pDest, len+2) ) goto no_mem;
|
| + memcpy(pDest->z, zData, len);
|
| + pDest->z[len] = 0;
|
| + pDest->z[len+1] = 0;
|
| + pDest->flags = fx|MEM_Term;
|
| + }
|
| +op_column_error:
|
| + UPDATE_MAX_BLOBSIZE(pDest);
|
| + REGISTER_TRACE(pOp->p3, pDest);
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: Affinity P1 P2 * P4 *
|
| +** Synopsis: affinity(r[P1@P2])
|
| +**
|
| +** Apply affinities to a range of P2 registers starting with P1.
|
| +**
|
| +** P4 is a string that is P2 characters long. The nth character of the
|
| +** string indicates the column affinity that should be used for the nth
|
| +** memory cell in the range.
|
| +*/
|
| +case OP_Affinity: {
|
| + const char *zAffinity; /* The affinity to be applied */
|
| + char cAff; /* A single character of affinity */
|
| +
|
| + zAffinity = pOp->p4.z;
|
| + assert( zAffinity!=0 );
|
| + assert( zAffinity[pOp->p2]==0 );
|
| + pIn1 = &aMem[pOp->p1];
|
| + while( (cAff = *(zAffinity++))!=0 ){
|
| + assert( pIn1 <= &p->aMem[(p->nMem-p->nCursor)] );
|
| + assert( memIsValid(pIn1) );
|
| + applyAffinity(pIn1, cAff, encoding);
|
| + pIn1++;
|
| + }
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: MakeRecord P1 P2 P3 P4 *
|
| +** Synopsis: r[P3]=mkrec(r[P1@P2])
|
| +**
|
| +** Convert P2 registers beginning with P1 into the [record format]
|
| +** use as a data record in a database table or as a key
|
| +** in an index. The OP_Column opcode can decode the record later.
|
| +**
|
| +** P4 may be a string that is P2 characters long. The nth character of the
|
| +** string indicates the column affinity that should be used for the nth
|
| +** field of the index key.
|
| +**
|
| +** The mapping from character to affinity is given by the SQLITE_AFF_
|
| +** macros defined in sqliteInt.h.
|
| +**
|
| +** If P4 is NULL then all index fields have the affinity BLOB.
|
| +*/
|
| +case OP_MakeRecord: {
|
| + u8 *zNewRecord; /* A buffer to hold the data for the new record */
|
| + Mem *pRec; /* The new record */
|
| + u64 nData; /* Number of bytes of data space */
|
| + int nHdr; /* Number of bytes of header space */
|
| + i64 nByte; /* Data space required for this record */
|
| + i64 nZero; /* Number of zero bytes at the end of the record */
|
| + int nVarint; /* Number of bytes in a varint */
|
| + u32 serial_type; /* Type field */
|
| + Mem *pData0; /* First field to be combined into the record */
|
| + Mem *pLast; /* Last field of the record */
|
| + int nField; /* Number of fields in the record */
|
| + char *zAffinity; /* The affinity string for the record */
|
| + int file_format; /* File format to use for encoding */
|
| + int i; /* Space used in zNewRecord[] header */
|
| + int j; /* Space used in zNewRecord[] content */
|
| + u32 len; /* Length of a field */
|
| +
|
| + /* Assuming the record contains N fields, the record format looks
|
| + ** like this:
|
| + **
|
| + ** ------------------------------------------------------------------------
|
| + ** | hdr-size | type 0 | type 1 | ... | type N-1 | data0 | ... | data N-1 |
|
| + ** ------------------------------------------------------------------------
|
| + **
|
| + ** Data(0) is taken from register P1. Data(1) comes from register P1+1
|
| + ** and so forth.
|
| + **
|
| + ** Each type field is a varint representing the serial type of the
|
| + ** corresponding data element (see sqlite3VdbeSerialType()). The
|
| + ** hdr-size field is also a varint which is the offset from the beginning
|
| + ** of the record to data0.
|
| + */
|
| + nData = 0; /* Number of bytes of data space */
|
| + nHdr = 0; /* Number of bytes of header space */
|
| + nZero = 0; /* Number of zero bytes at the end of the record */
|
| + nField = pOp->p1;
|
| + zAffinity = pOp->p4.z;
|
| + assert( nField>0 && pOp->p2>0 && pOp->p2+nField<=(p->nMem-p->nCursor)+1 );
|
| + pData0 = &aMem[nField];
|
| + nField = pOp->p2;
|
| + pLast = &pData0[nField-1];
|
| + file_format = p->minWriteFileFormat;
|
| +
|
| + /* Identify the output register */
|
| + assert( pOp->p3<pOp->p1 || pOp->p3>=pOp->p1+pOp->p2 );
|
| + pOut = &aMem[pOp->p3];
|
| + memAboutToChange(p, pOut);
|
| +
|
| + /* Apply the requested affinity to all inputs
|
| + */
|
| + assert( pData0<=pLast );
|
| + if( zAffinity ){
|
| + pRec = pData0;
|
| + do{
|
| + applyAffinity(pRec++, *(zAffinity++), encoding);
|
| + assert( zAffinity[0]==0 || pRec<=pLast );
|
| + }while( zAffinity[0] );
|
| + }
|
| +
|
| + /* Loop through the elements that will make up the record to figure
|
| + ** out how much space is required for the new record.
|
| + */
|
| + pRec = pLast;
|
| + do{
|
| + assert( memIsValid(pRec) );
|
| + pRec->uTemp = serial_type = sqlite3VdbeSerialType(pRec, file_format, &len);
|
| + if( pRec->flags & MEM_Zero ){
|
| + if( nData ){
|
| + if( sqlite3VdbeMemExpandBlob(pRec) ) goto no_mem;
|
| + }else{
|
| + nZero += pRec->u.nZero;
|
| + len -= pRec->u.nZero;
|
| + }
|
| + }
|
| + nData += len;
|
| + testcase( serial_type==127 );
|
| + testcase( serial_type==128 );
|
| + nHdr += serial_type<=127 ? 1 : sqlite3VarintLen(serial_type);
|
| + }while( (--pRec)>=pData0 );
|
| +
|
| + /* EVIDENCE-OF: R-22564-11647 The header begins with a single varint
|
| + ** which determines the total number of bytes in the header. The varint
|
| + ** value is the size of the header in bytes including the size varint
|
| + ** itself. */
|
| + testcase( nHdr==126 );
|
| + testcase( nHdr==127 );
|
| + if( nHdr<=126 ){
|
| + /* The common case */
|
| + nHdr += 1;
|
| + }else{
|
| + /* Rare case of a really large header */
|
| + nVarint = sqlite3VarintLen(nHdr);
|
| + nHdr += nVarint;
|
| + if( nVarint<sqlite3VarintLen(nHdr) ) nHdr++;
|
| + }
|
| + nByte = nHdr+nData;
|
| + if( nByte+nZero>db->aLimit[SQLITE_LIMIT_LENGTH] ){
|
| + goto too_big;
|
| + }
|
| +
|
| + /* Make sure the output register has a buffer large enough to store
|
| + ** the new record. The output register (pOp->p3) is not allowed to
|
| + ** be one of the input registers (because the following call to
|
| + ** sqlite3VdbeMemClearAndResize() could clobber the value before it is used).
|
| + */
|
| + if( sqlite3VdbeMemClearAndResize(pOut, (int)nByte) ){
|
| + goto no_mem;
|
| + }
|
| + zNewRecord = (u8 *)pOut->z;
|
| +
|
| + /* Write the record */
|
| + i = putVarint32(zNewRecord, nHdr);
|
| + j = nHdr;
|
| + assert( pData0<=pLast );
|
| + pRec = pData0;
|
| + do{
|
| + serial_type = pRec->uTemp;
|
| + /* EVIDENCE-OF: R-06529-47362 Following the size varint are one or more
|
| + ** additional varints, one per column. */
|
| + i += putVarint32(&zNewRecord[i], serial_type); /* serial type */
|
| + /* EVIDENCE-OF: R-64536-51728 The values for each column in the record
|
| + ** immediately follow the header. */
|
| + j += sqlite3VdbeSerialPut(&zNewRecord[j], pRec, serial_type); /* content */
|
| + }while( (++pRec)<=pLast );
|
| + assert( i==nHdr );
|
| + assert( j==nByte );
|
| +
|
| + assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
|
| + pOut->n = (int)nByte;
|
| + pOut->flags = MEM_Blob;
|
| + if( nZero ){
|
| + pOut->u.nZero = nZero;
|
| + pOut->flags |= MEM_Zero;
|
| + }
|
| + pOut->enc = SQLITE_UTF8; /* In case the blob is ever converted to text */
|
| + REGISTER_TRACE(pOp->p3, pOut);
|
| + UPDATE_MAX_BLOBSIZE(pOut);
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: Count P1 P2 * * *
|
| +** Synopsis: r[P2]=count()
|
| +**
|
| +** Store the number of entries (an integer value) in the table or index
|
| +** opened by cursor P1 in register P2
|
| +*/
|
| +#ifndef SQLITE_OMIT_BTREECOUNT
|
| +case OP_Count: { /* out2 */
|
| + i64 nEntry;
|
| + BtCursor *pCrsr;
|
| +
|
| + assert( p->apCsr[pOp->p1]->eCurType==CURTYPE_BTREE );
|
| + pCrsr = p->apCsr[pOp->p1]->uc.pCursor;
|
| + assert( pCrsr );
|
| + nEntry = 0; /* Not needed. Only used to silence a warning. */
|
| + rc = sqlite3BtreeCount(pCrsr, &nEntry);
|
| + pOut = out2Prerelease(p, pOp);
|
| + pOut->u.i = nEntry;
|
| + break;
|
| +}
|
| +#endif
|
| +
|
| +/* Opcode: Savepoint P1 * * P4 *
|
| +**
|
| +** Open, release or rollback the savepoint named by parameter P4, depending
|
| +** on the value of P1. To open a new savepoint, P1==0. To release (commit) an
|
| +** existing savepoint, P1==1, or to rollback an existing savepoint P1==2.
|
| +*/
|
| +case OP_Savepoint: {
|
| + int p1; /* Value of P1 operand */
|
| + char *zName; /* Name of savepoint */
|
| + int nName;
|
| + Savepoint *pNew;
|
| + Savepoint *pSavepoint;
|
| + Savepoint *pTmp;
|
| + int iSavepoint;
|
| + int ii;
|
| +
|
| + p1 = pOp->p1;
|
| + zName = pOp->p4.z;
|
| +
|
| + /* Assert that the p1 parameter is valid. Also that if there is no open
|
| + ** transaction, then there cannot be any savepoints.
|
| + */
|
| + assert( db->pSavepoint==0 || db->autoCommit==0 );
|
| + assert( p1==SAVEPOINT_BEGIN||p1==SAVEPOINT_RELEASE||p1==SAVEPOINT_ROLLBACK );
|
| + assert( db->pSavepoint || db->isTransactionSavepoint==0 );
|
| + assert( checkSavepointCount(db) );
|
| + assert( p->bIsReader );
|
| +
|
| + if( p1==SAVEPOINT_BEGIN ){
|
| + if( db->nVdbeWrite>0 ){
|
| + /* A new savepoint cannot be created if there are active write
|
| + ** statements (i.e. open read/write incremental blob handles).
|
| + */
|
| + sqlite3VdbeError(p, "cannot open savepoint - SQL statements in progress");
|
| + rc = SQLITE_BUSY;
|
| + }else{
|
| + nName = sqlite3Strlen30(zName);
|
| +
|
| +#ifndef SQLITE_OMIT_VIRTUALTABLE
|
| + /* This call is Ok even if this savepoint is actually a transaction
|
| + ** savepoint (and therefore should not prompt xSavepoint()) callbacks.
|
| + ** If this is a transaction savepoint being opened, it is guaranteed
|
| + ** that the db->aVTrans[] array is empty. */
|
| + assert( db->autoCommit==0 || db->nVTrans==0 );
|
| + rc = sqlite3VtabSavepoint(db, SAVEPOINT_BEGIN,
|
| + db->nStatement+db->nSavepoint);
|
| + if( rc!=SQLITE_OK ) goto abort_due_to_error;
|
| +#endif
|
| +
|
| + /* Create a new savepoint structure. */
|
| + pNew = sqlite3DbMallocRaw(db, sizeof(Savepoint)+nName+1);
|
| + if( pNew ){
|
| + pNew->zName = (char *)&pNew[1];
|
| + memcpy(pNew->zName, zName, nName+1);
|
| +
|
| + /* If there is no open transaction, then mark this as a special
|
| + ** "transaction savepoint". */
|
| + if( db->autoCommit ){
|
| + db->autoCommit = 0;
|
| + db->isTransactionSavepoint = 1;
|
| + }else{
|
| + db->nSavepoint++;
|
| + }
|
| +
|
| + /* Link the new savepoint into the database handle's list. */
|
| + pNew->pNext = db->pSavepoint;
|
| + db->pSavepoint = pNew;
|
| + pNew->nDeferredCons = db->nDeferredCons;
|
| + pNew->nDeferredImmCons = db->nDeferredImmCons;
|
| + }
|
| + }
|
| + }else{
|
| + iSavepoint = 0;
|
| +
|
| + /* Find the named savepoint. If there is no such savepoint, then an
|
| + ** an error is returned to the user. */
|
| + for(
|
| + pSavepoint = db->pSavepoint;
|
| + pSavepoint && sqlite3StrICmp(pSavepoint->zName, zName);
|
| + pSavepoint = pSavepoint->pNext
|
| + ){
|
| + iSavepoint++;
|
| + }
|
| + if( !pSavepoint ){
|
| + sqlite3VdbeError(p, "no such savepoint: %s", zName);
|
| + rc = SQLITE_ERROR;
|
| + }else if( db->nVdbeWrite>0 && p1==SAVEPOINT_RELEASE ){
|
| + /* It is not possible to release (commit) a savepoint if there are
|
| + ** active write statements.
|
| + */
|
| + sqlite3VdbeError(p, "cannot release savepoint - "
|
| + "SQL statements in progress");
|
| + rc = SQLITE_BUSY;
|
| + }else{
|
| +
|
| + /* Determine whether or not this is a transaction savepoint. If so,
|
| + ** and this is a RELEASE command, then the current transaction
|
| + ** is committed.
|
| + */
|
| + int isTransaction = pSavepoint->pNext==0 && db->isTransactionSavepoint;
|
| + if( isTransaction && p1==SAVEPOINT_RELEASE ){
|
| + if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){
|
| + goto vdbe_return;
|
| + }
|
| + db->autoCommit = 1;
|
| + if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){
|
| + p->pc = (int)(pOp - aOp);
|
| + db->autoCommit = 0;
|
| + p->rc = rc = SQLITE_BUSY;
|
| + goto vdbe_return;
|
| + }
|
| + db->isTransactionSavepoint = 0;
|
| + rc = p->rc;
|
| + }else{
|
| + int isSchemaChange;
|
| + iSavepoint = db->nSavepoint - iSavepoint - 1;
|
| + if( p1==SAVEPOINT_ROLLBACK ){
|
| + isSchemaChange = (db->flags & SQLITE_InternChanges)!=0;
|
| + for(ii=0; ii<db->nDb; ii++){
|
| + rc = sqlite3BtreeTripAllCursors(db->aDb[ii].pBt,
|
| + SQLITE_ABORT_ROLLBACK,
|
| + isSchemaChange==0);
|
| + if( rc!=SQLITE_OK ) goto abort_due_to_error;
|
| + }
|
| + }else{
|
| + isSchemaChange = 0;
|
| + }
|
| + for(ii=0; ii<db->nDb; ii++){
|
| + rc = sqlite3BtreeSavepoint(db->aDb[ii].pBt, p1, iSavepoint);
|
| + if( rc!=SQLITE_OK ){
|
| + goto abort_due_to_error;
|
| + }
|
| + }
|
| + if( isSchemaChange ){
|
| + sqlite3ExpirePreparedStatements(db);
|
| + sqlite3ResetAllSchemasOfConnection(db);
|
| + db->flags = (db->flags | SQLITE_InternChanges);
|
| + }
|
| + }
|
| +
|
| + /* Regardless of whether this is a RELEASE or ROLLBACK, destroy all
|
| + ** savepoints nested inside of the savepoint being operated on. */
|
| + while( db->pSavepoint!=pSavepoint ){
|
| + pTmp = db->pSavepoint;
|
| + db->pSavepoint = pTmp->pNext;
|
| + sqlite3DbFree(db, pTmp);
|
| + db->nSavepoint--;
|
| + }
|
| +
|
| + /* If it is a RELEASE, then destroy the savepoint being operated on
|
| + ** too. If it is a ROLLBACK TO, then set the number of deferred
|
| + ** constraint violations present in the database to the value stored
|
| + ** when the savepoint was created. */
|
| + if( p1==SAVEPOINT_RELEASE ){
|
| + assert( pSavepoint==db->pSavepoint );
|
| + db->pSavepoint = pSavepoint->pNext;
|
| + sqlite3DbFree(db, pSavepoint);
|
| + if( !isTransaction ){
|
| + db->nSavepoint--;
|
| + }
|
| + }else{
|
| + db->nDeferredCons = pSavepoint->nDeferredCons;
|
| + db->nDeferredImmCons = pSavepoint->nDeferredImmCons;
|
| + }
|
| +
|
| + if( !isTransaction || p1==SAVEPOINT_ROLLBACK ){
|
| + rc = sqlite3VtabSavepoint(db, p1, iSavepoint);
|
| + if( rc!=SQLITE_OK ) goto abort_due_to_error;
|
| + }
|
| + }
|
| + }
|
| +
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: AutoCommit P1 P2 * * *
|
| +**
|
| +** Set the database auto-commit flag to P1 (1 or 0). If P2 is true, roll
|
| +** back any currently active btree transactions. If there are any active
|
| +** VMs (apart from this one), then a ROLLBACK fails. A COMMIT fails if
|
| +** there are active writing VMs or active VMs that use shared cache.
|
| +**
|
| +** This instruction causes the VM to halt.
|
| +*/
|
| +case OP_AutoCommit: {
|
| + int desiredAutoCommit;
|
| + int iRollback;
|
| + int turnOnAC;
|
| +
|
| + desiredAutoCommit = pOp->p1;
|
| + iRollback = pOp->p2;
|
| + turnOnAC = desiredAutoCommit && !db->autoCommit;
|
| + assert( desiredAutoCommit==1 || desiredAutoCommit==0 );
|
| + assert( desiredAutoCommit==1 || iRollback==0 );
|
| + assert( db->nVdbeActive>0 ); /* At least this one VM is active */
|
| + assert( p->bIsReader );
|
| +
|
| + if( turnOnAC && !iRollback && db->nVdbeWrite>0 ){
|
| + /* If this instruction implements a COMMIT and other VMs are writing
|
| + ** return an error indicating that the other VMs must complete first.
|
| + */
|
| + sqlite3VdbeError(p, "cannot commit transaction - "
|
| + "SQL statements in progress");
|
| + rc = SQLITE_BUSY;
|
| + }else if( desiredAutoCommit!=db->autoCommit ){
|
| + if( iRollback ){
|
| + assert( desiredAutoCommit==1 );
|
| + sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK);
|
| + db->autoCommit = 1;
|
| + }else if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){
|
| + goto vdbe_return;
|
| + }else{
|
| + db->autoCommit = (u8)desiredAutoCommit;
|
| + }
|
| + if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){
|
| + p->pc = (int)(pOp - aOp);
|
| + db->autoCommit = (u8)(1-desiredAutoCommit);
|
| + p->rc = rc = SQLITE_BUSY;
|
| + goto vdbe_return;
|
| + }
|
| + assert( db->nStatement==0 );
|
| + sqlite3CloseSavepoints(db);
|
| + if( p->rc==SQLITE_OK ){
|
| + rc = SQLITE_DONE;
|
| + }else{
|
| + rc = SQLITE_ERROR;
|
| + }
|
| + goto vdbe_return;
|
| + }else{
|
| + sqlite3VdbeError(p,
|
| + (!desiredAutoCommit)?"cannot start a transaction within a transaction":(
|
| + (iRollback)?"cannot rollback - no transaction is active":
|
| + "cannot commit - no transaction is active"));
|
| +
|
| + rc = SQLITE_ERROR;
|
| + }
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: Transaction P1 P2 P3 P4 P5
|
| +**
|
| +** Begin a transaction on database P1 if a transaction is not already
|
| +** active.
|
| +** If P2 is non-zero, then a write-transaction is started, or if a
|
| +** read-transaction is already active, it is upgraded to a write-transaction.
|
| +** If P2 is zero, then a read-transaction is started.
|
| +**
|
| +** P1 is the index of the database file on which the transaction is
|
| +** started. Index 0 is the main database file and index 1 is the
|
| +** file used for temporary tables. Indices of 2 or more are used for
|
| +** attached databases.
|
| +**
|
| +** If a write-transaction is started and the Vdbe.usesStmtJournal flag is
|
| +** true (this flag is set if the Vdbe may modify more than one row and may
|
| +** throw an ABORT exception), a statement transaction may also be opened.
|
| +** More specifically, a statement transaction is opened iff the database
|
| +** connection is currently not in autocommit mode, or if there are other
|
| +** active statements. A statement transaction allows the changes made by this
|
| +** VDBE to be rolled back after an error without having to roll back the
|
| +** entire transaction. If no error is encountered, the statement transaction
|
| +** will automatically commit when the VDBE halts.
|
| +**
|
| +** If P5!=0 then this opcode also checks the schema cookie against P3
|
| +** and the schema generation counter against P4.
|
| +** The cookie changes its value whenever the database schema changes.
|
| +** This operation is used to detect when that the cookie has changed
|
| +** and that the current process needs to reread the schema. If the schema
|
| +** cookie in P3 differs from the schema cookie in the database header or
|
| +** if the schema generation counter in P4 differs from the current
|
| +** generation counter, then an SQLITE_SCHEMA error is raised and execution
|
| +** halts. The sqlite3_step() wrapper function might then reprepare the
|
| +** statement and rerun it from the beginning.
|
| +*/
|
| +case OP_Transaction: {
|
| + Btree *pBt;
|
| + int iMeta;
|
| + int iGen;
|
| +
|
| + assert( p->bIsReader );
|
| + assert( p->readOnly==0 || pOp->p2==0 );
|
| + assert( pOp->p1>=0 && pOp->p1<db->nDb );
|
| + assert( DbMaskTest(p->btreeMask, pOp->p1) );
|
| + if( pOp->p2 && (db->flags & SQLITE_QueryOnly)!=0 ){
|
| + rc = SQLITE_READONLY;
|
| + goto abort_due_to_error;
|
| + }
|
| + pBt = db->aDb[pOp->p1].pBt;
|
| +
|
| + if( pBt ){
|
| + rc = sqlite3BtreeBeginTrans(pBt, pOp->p2);
|
| + testcase( rc==SQLITE_BUSY_SNAPSHOT );
|
| + testcase( rc==SQLITE_BUSY_RECOVERY );
|
| + if( (rc&0xff)==SQLITE_BUSY ){
|
| + p->pc = (int)(pOp - aOp);
|
| + p->rc = rc;
|
| + goto vdbe_return;
|
| + }
|
| + if( rc!=SQLITE_OK ){
|
| + goto abort_due_to_error;
|
| + }
|
| +
|
| + if( pOp->p2 && p->usesStmtJournal
|
| + && (db->autoCommit==0 || db->nVdbeRead>1)
|
| + ){
|
| + assert( sqlite3BtreeIsInTrans(pBt) );
|
| + if( p->iStatement==0 ){
|
| + assert( db->nStatement>=0 && db->nSavepoint>=0 );
|
| + db->nStatement++;
|
| + p->iStatement = db->nSavepoint + db->nStatement;
|
| + }
|
| +
|
| + rc = sqlite3VtabSavepoint(db, SAVEPOINT_BEGIN, p->iStatement-1);
|
| + if( rc==SQLITE_OK ){
|
| + rc = sqlite3BtreeBeginStmt(pBt, p->iStatement);
|
| + }
|
| +
|
| + /* Store the current value of the database handles deferred constraint
|
| + ** counter. If the statement transaction needs to be rolled back,
|
| + ** the value of this counter needs to be restored too. */
|
| + p->nStmtDefCons = db->nDeferredCons;
|
| + p->nStmtDefImmCons = db->nDeferredImmCons;
|
| + }
|
| +
|
| + /* Gather the schema version number for checking:
|
| + ** IMPLEMENTATION-OF: R-32195-19465 The schema version is used by SQLite
|
| + ** each time a query is executed to ensure that the internal cache of the
|
| + ** schema used when compiling the SQL query matches the schema of the
|
| + ** database against which the compiled query is actually executed.
|
| + */
|
| + sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&iMeta);
|
| + iGen = db->aDb[pOp->p1].pSchema->iGeneration;
|
| + }else{
|
| + iGen = iMeta = 0;
|
| + }
|
| + assert( pOp->p5==0 || pOp->p4type==P4_INT32 );
|
| + if( pOp->p5 && (iMeta!=pOp->p3 || iGen!=pOp->p4.i) ){
|
| + sqlite3DbFree(db, p->zErrMsg);
|
| + p->zErrMsg = sqlite3DbStrDup(db, "database schema has changed");
|
| + /* If the schema-cookie from the database file matches the cookie
|
| + ** stored with the in-memory representation of the schema, do
|
| + ** not reload the schema from the database file.
|
| + **
|
| + ** If virtual-tables are in use, this is not just an optimization.
|
| + ** Often, v-tables store their data in other SQLite tables, which
|
| + ** are queried from within xNext() and other v-table methods using
|
| + ** prepared queries. If such a query is out-of-date, we do not want to
|
| + ** discard the database schema, as the user code implementing the
|
| + ** v-table would have to be ready for the sqlite3_vtab structure itself
|
| + ** to be invalidated whenever sqlite3_step() is called from within
|
| + ** a v-table method.
|
| + */
|
| + if( db->aDb[pOp->p1].pSchema->schema_cookie!=iMeta ){
|
| + sqlite3ResetOneSchema(db, pOp->p1);
|
| + }
|
| + p->expired = 1;
|
| + rc = SQLITE_SCHEMA;
|
| + }
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: ReadCookie P1 P2 P3 * *
|
| +**
|
| +** Read cookie number P3 from database P1 and write it into register P2.
|
| +** P3==1 is the schema version. P3==2 is the database format.
|
| +** P3==3 is the recommended pager cache size, and so forth. P1==0 is
|
| +** the main database file and P1==1 is the database file used to store
|
| +** temporary tables.
|
| +**
|
| +** There must be a read-lock on the database (either a transaction
|
| +** must be started or there must be an open cursor) before
|
| +** executing this instruction.
|
| +*/
|
| +case OP_ReadCookie: { /* out2 */
|
| + int iMeta;
|
| + int iDb;
|
| + int iCookie;
|
| +
|
| + assert( p->bIsReader );
|
| + iDb = pOp->p1;
|
| + iCookie = pOp->p3;
|
| + assert( pOp->p3<SQLITE_N_BTREE_META );
|
| + assert( iDb>=0 && iDb<db->nDb );
|
| + assert( db->aDb[iDb].pBt!=0 );
|
| + assert( DbMaskTest(p->btreeMask, iDb) );
|
| +
|
| + sqlite3BtreeGetMeta(db->aDb[iDb].pBt, iCookie, (u32 *)&iMeta);
|
| + pOut = out2Prerelease(p, pOp);
|
| + pOut->u.i = iMeta;
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: SetCookie P1 P2 P3 * *
|
| +**
|
| +** Write the content of register P3 (interpreted as an integer)
|
| +** into cookie number P2 of database P1. P2==1 is the schema version.
|
| +** P2==2 is the database format. P2==3 is the recommended pager cache
|
| +** size, and so forth. P1==0 is the main database file and P1==1 is the
|
| +** database file used to store temporary tables.
|
| +**
|
| +** A transaction must be started before executing this opcode.
|
| +*/
|
| +case OP_SetCookie: { /* in3 */
|
| + Db *pDb;
|
| + assert( pOp->p2<SQLITE_N_BTREE_META );
|
| + assert( pOp->p1>=0 && pOp->p1<db->nDb );
|
| + assert( DbMaskTest(p->btreeMask, pOp->p1) );
|
| + assert( p->readOnly==0 );
|
| + pDb = &db->aDb[pOp->p1];
|
| + assert( pDb->pBt!=0 );
|
| + assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) );
|
| + pIn3 = &aMem[pOp->p3];
|
| + sqlite3VdbeMemIntegerify(pIn3);
|
| + /* See note about index shifting on OP_ReadCookie */
|
| + rc = sqlite3BtreeUpdateMeta(pDb->pBt, pOp->p2, (int)pIn3->u.i);
|
| + if( pOp->p2==BTREE_SCHEMA_VERSION ){
|
| + /* When the schema cookie changes, record the new cookie internally */
|
| + pDb->pSchema->schema_cookie = (int)pIn3->u.i;
|
| + db->flags |= SQLITE_InternChanges;
|
| + }else if( pOp->p2==BTREE_FILE_FORMAT ){
|
| + /* Record changes in the file format */
|
| + pDb->pSchema->file_format = (u8)pIn3->u.i;
|
| + }
|
| + if( pOp->p1==1 ){
|
| + /* Invalidate all prepared statements whenever the TEMP database
|
| + ** schema is changed. Ticket #1644 */
|
| + sqlite3ExpirePreparedStatements(db);
|
| + p->expired = 0;
|
| + }
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: OpenRead P1 P2 P3 P4 P5
|
| +** Synopsis: root=P2 iDb=P3
|
| +**
|
| +** Open a read-only cursor for the database table whose root page is
|
| +** P2 in a database file. The database file is determined by P3.
|
| +** P3==0 means the main database, P3==1 means the database used for
|
| +** temporary tables, and P3>1 means used the corresponding attached
|
| +** database. Give the new cursor an identifier of P1. The P1
|
| +** values need not be contiguous but all P1 values should be small integers.
|
| +** It is an error for P1 to be negative.
|
| +**
|
| +** If P5!=0 then use the content of register P2 as the root page, not
|
| +** the value of P2 itself.
|
| +**
|
| +** There will be a read lock on the database whenever there is an
|
| +** open cursor. If the database was unlocked prior to this instruction
|
| +** then a read lock is acquired as part of this instruction. A read
|
| +** lock allows other processes to read the database but prohibits
|
| +** any other process from modifying the database. The read lock is
|
| +** released when all cursors are closed. If this instruction attempts
|
| +** to get a read lock but fails, the script terminates with an
|
| +** SQLITE_BUSY error code.
|
| +**
|
| +** The P4 value may be either an integer (P4_INT32) or a pointer to
|
| +** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo
|
| +** structure, then said structure defines the content and collating
|
| +** sequence of the index being opened. Otherwise, if P4 is an integer
|
| +** value, it is set to the number of columns in the table.
|
| +**
|
| +** See also: OpenWrite, ReopenIdx
|
| +*/
|
| +/* Opcode: ReopenIdx P1 P2 P3 P4 P5
|
| +** Synopsis: root=P2 iDb=P3
|
| +**
|
| +** The ReopenIdx opcode works exactly like ReadOpen except that it first
|
| +** checks to see if the cursor on P1 is already open with a root page
|
| +** number of P2 and if it is this opcode becomes a no-op. In other words,
|
| +** if the cursor is already open, do not reopen it.
|
| +**
|
| +** The ReopenIdx opcode may only be used with P5==0 and with P4 being
|
| +** a P4_KEYINFO object. Furthermore, the P3 value must be the same as
|
| +** every other ReopenIdx or OpenRead for the same cursor number.
|
| +**
|
| +** See the OpenRead opcode documentation for additional information.
|
| +*/
|
| +/* Opcode: OpenWrite P1 P2 P3 P4 P5
|
| +** Synopsis: root=P2 iDb=P3
|
| +**
|
| +** Open a read/write cursor named P1 on the table or index whose root
|
| +** page is P2. Or if P5!=0 use the content of register P2 to find the
|
| +** root page.
|
| +**
|
| +** The P4 value may be either an integer (P4_INT32) or a pointer to
|
| +** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo
|
| +** structure, then said structure defines the content and collating
|
| +** sequence of the index being opened. Otherwise, if P4 is an integer
|
| +** value, it is set to the number of columns in the table, or to the
|
| +** largest index of any column of the table that is actually used.
|
| +**
|
| +** This instruction works just like OpenRead except that it opens the cursor
|
| +** in read/write mode. For a given table, there can be one or more read-only
|
| +** cursors or a single read/write cursor but not both.
|
| +**
|
| +** See also OpenRead.
|
| +*/
|
| +case OP_ReopenIdx: {
|
| + int nField;
|
| + KeyInfo *pKeyInfo;
|
| + int p2;
|
| + int iDb;
|
| + int wrFlag;
|
| + Btree *pX;
|
| + VdbeCursor *pCur;
|
| + Db *pDb;
|
| +
|
| + assert( pOp->p5==0 || pOp->p5==OPFLAG_SEEKEQ );
|
| + assert( pOp->p4type==P4_KEYINFO );
|
| + pCur = p->apCsr[pOp->p1];
|
| + if( pCur && pCur->pgnoRoot==(u32)pOp->p2 ){
|
| + assert( pCur->iDb==pOp->p3 ); /* Guaranteed by the code generator */
|
| + goto open_cursor_set_hints;
|
| + }
|
| + /* If the cursor is not currently open or is open on a different
|
| + ** index, then fall through into OP_OpenRead to force a reopen */
|
| +case OP_OpenRead:
|
| +case OP_OpenWrite:
|
| +
|
| + assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 || pOp->p5==OPFLAG_SEEKEQ );
|
| + assert( p->bIsReader );
|
| + assert( pOp->opcode==OP_OpenRead || pOp->opcode==OP_ReopenIdx
|
| + || p->readOnly==0 );
|
| +
|
| + if( p->expired ){
|
| + rc = SQLITE_ABORT_ROLLBACK;
|
| + break;
|
| + }
|
| +
|
| + nField = 0;
|
| + pKeyInfo = 0;
|
| + p2 = pOp->p2;
|
| + iDb = pOp->p3;
|
| + assert( iDb>=0 && iDb<db->nDb );
|
| + assert( DbMaskTest(p->btreeMask, iDb) );
|
| + pDb = &db->aDb[iDb];
|
| + pX = pDb->pBt;
|
| + assert( pX!=0 );
|
| + if( pOp->opcode==OP_OpenWrite ){
|
| + assert( OPFLAG_FORDELETE==BTREE_FORDELETE );
|
| + wrFlag = BTREE_WRCSR | (pOp->p5 & OPFLAG_FORDELETE);
|
| + assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
| + if( pDb->pSchema->file_format < p->minWriteFileFormat ){
|
| + p->minWriteFileFormat = pDb->pSchema->file_format;
|
| + }
|
| + }else{
|
| + wrFlag = 0;
|
| + }
|
| + if( pOp->p5 & OPFLAG_P2ISREG ){
|
| + assert( p2>0 );
|
| + assert( p2<=(p->nMem-p->nCursor) );
|
| + pIn2 = &aMem[p2];
|
| + assert( memIsValid(pIn2) );
|
| + assert( (pIn2->flags & MEM_Int)!=0 );
|
| + sqlite3VdbeMemIntegerify(pIn2);
|
| + p2 = (int)pIn2->u.i;
|
| + /* The p2 value always comes from a prior OP_CreateTable opcode and
|
| + ** that opcode will always set the p2 value to 2 or more or else fail.
|
| + ** If there were a failure, the prepared statement would have halted
|
| + ** before reaching this instruction. */
|
| + if( NEVER(p2<2) ) {
|
| + rc = SQLITE_CORRUPT_BKPT;
|
| + goto abort_due_to_error;
|
| + }
|
| + }
|
| + if( pOp->p4type==P4_KEYINFO ){
|
| + pKeyInfo = pOp->p4.pKeyInfo;
|
| + assert( pKeyInfo->enc==ENC(db) );
|
| + assert( pKeyInfo->db==db );
|
| + nField = pKeyInfo->nField+pKeyInfo->nXField;
|
| + }else if( pOp->p4type==P4_INT32 ){
|
| + nField = pOp->p4.i;
|
| + }
|
| + assert( pOp->p1>=0 );
|
| + assert( nField>=0 );
|
| + testcase( nField==0 ); /* Table with INTEGER PRIMARY KEY and nothing else */
|
| + pCur = allocateCursor(p, pOp->p1, nField, iDb, CURTYPE_BTREE);
|
| + if( pCur==0 ) goto no_mem;
|
| + pCur->nullRow = 1;
|
| + pCur->isOrdered = 1;
|
| + pCur->pgnoRoot = p2;
|
| + rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->uc.pCursor);
|
| + pCur->pKeyInfo = pKeyInfo;
|
| + /* Set the VdbeCursor.isTable variable. Previous versions of
|
| + ** SQLite used to check if the root-page flags were sane at this point
|
| + ** and report database corruption if they were not, but this check has
|
| + ** since moved into the btree layer. */
|
| + pCur->isTable = pOp->p4type!=P4_KEYINFO;
|
| +
|
| +open_cursor_set_hints:
|
| + assert( OPFLAG_BULKCSR==BTREE_BULKLOAD );
|
| + assert( OPFLAG_SEEKEQ==BTREE_SEEK_EQ );
|
| + testcase( pOp->p5 & OPFLAG_BULKCSR );
|
| +#ifdef SQLITE_ENABLE_CURSOR_HINTS
|
| + testcase( pOp->p2 & OPFLAG_SEEKEQ );
|
| +#endif
|
| + sqlite3BtreeCursorHintFlags(pCur->uc.pCursor,
|
| + (pOp->p5 & (OPFLAG_BULKCSR|OPFLAG_SEEKEQ)));
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: OpenEphemeral P1 P2 * P4 P5
|
| +** Synopsis: nColumn=P2
|
| +**
|
| +** Open a new cursor P1 to a transient table.
|
| +** The cursor is always opened read/write even if
|
| +** the main database is read-only. The ephemeral
|
| +** table is deleted automatically when the cursor is closed.
|
| +**
|
| +** P2 is the number of columns in the ephemeral table.
|
| +** The cursor points to a BTree table if P4==0 and to a BTree index
|
| +** if P4 is not 0. If P4 is not NULL, it points to a KeyInfo structure
|
| +** that defines the format of keys in the index.
|
| +**
|
| +** The P5 parameter can be a mask of the BTREE_* flags defined
|
| +** in btree.h. These flags control aspects of the operation of
|
| +** the btree. The BTREE_OMIT_JOURNAL and BTREE_SINGLE flags are
|
| +** added automatically.
|
| +*/
|
| +/* Opcode: OpenAutoindex P1 P2 * P4 *
|
| +** Synopsis: nColumn=P2
|
| +**
|
| +** This opcode works the same as OP_OpenEphemeral. It has a
|
| +** different name to distinguish its use. Tables created using
|
| +** by this opcode will be used for automatically created transient
|
| +** indices in joins.
|
| +*/
|
| +case OP_OpenAutoindex:
|
| +case OP_OpenEphemeral: {
|
| + VdbeCursor *pCx;
|
| + KeyInfo *pKeyInfo;
|
| +
|
| + static const int vfsFlags =
|
| + SQLITE_OPEN_READWRITE |
|
| + SQLITE_OPEN_CREATE |
|
| + SQLITE_OPEN_EXCLUSIVE |
|
| + SQLITE_OPEN_DELETEONCLOSE |
|
| + SQLITE_OPEN_TRANSIENT_DB;
|
| + assert( pOp->p1>=0 );
|
| + assert( pOp->p2>=0 );
|
| + pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, CURTYPE_BTREE);
|
| + if( pCx==0 ) goto no_mem;
|
| + pCx->nullRow = 1;
|
| + pCx->isEphemeral = 1;
|
| + rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->pBt,
|
| + BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags);
|
| + if( rc==SQLITE_OK ){
|
| + rc = sqlite3BtreeBeginTrans(pCx->pBt, 1);
|
| + }
|
| + if( rc==SQLITE_OK ){
|
| + /* If a transient index is required, create it by calling
|
| + ** sqlite3BtreeCreateTable() with the BTREE_BLOBKEY flag before
|
| + ** opening it. If a transient table is required, just use the
|
| + ** automatically created table with root-page 1 (an BLOB_INTKEY table).
|
| + */
|
| + if( (pKeyInfo = pOp->p4.pKeyInfo)!=0 ){
|
| + int pgno;
|
| + assert( pOp->p4type==P4_KEYINFO );
|
| + rc = sqlite3BtreeCreateTable(pCx->pBt, &pgno, BTREE_BLOBKEY | pOp->p5);
|
| + if( rc==SQLITE_OK ){
|
| + assert( pgno==MASTER_ROOT+1 );
|
| + assert( pKeyInfo->db==db );
|
| + assert( pKeyInfo->enc==ENC(db) );
|
| + pCx->pKeyInfo = pKeyInfo;
|
| + rc = sqlite3BtreeCursor(pCx->pBt, pgno, BTREE_WRCSR,
|
| + pKeyInfo, pCx->uc.pCursor);
|
| + }
|
| + pCx->isTable = 0;
|
| + }else{
|
| + rc = sqlite3BtreeCursor(pCx->pBt, MASTER_ROOT, BTREE_WRCSR,
|
| + 0, pCx->uc.pCursor);
|
| + pCx->isTable = 1;
|
| + }
|
| + }
|
| + pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: SorterOpen P1 P2 P3 P4 *
|
| +**
|
| +** This opcode works like OP_OpenEphemeral except that it opens
|
| +** a transient index that is specifically designed to sort large
|
| +** tables using an external merge-sort algorithm.
|
| +**
|
| +** If argument P3 is non-zero, then it indicates that the sorter may
|
| +** assume that a stable sort considering the first P3 fields of each
|
| +** key is sufficient to produce the required results.
|
| +*/
|
| +case OP_SorterOpen: {
|
| + VdbeCursor *pCx;
|
| +
|
| + assert( pOp->p1>=0 );
|
| + assert( pOp->p2>=0 );
|
| + pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, CURTYPE_SORTER);
|
| + if( pCx==0 ) goto no_mem;
|
| + pCx->pKeyInfo = pOp->p4.pKeyInfo;
|
| + assert( pCx->pKeyInfo->db==db );
|
| + assert( pCx->pKeyInfo->enc==ENC(db) );
|
| + rc = sqlite3VdbeSorterInit(db, pOp->p3, pCx);
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: SequenceTest P1 P2 * * *
|
| +** Synopsis: if( cursor[P1].ctr++ ) pc = P2
|
| +**
|
| +** P1 is a sorter cursor. If the sequence counter is currently zero, jump
|
| +** to P2. Regardless of whether or not the jump is taken, increment the
|
| +** the sequence value.
|
| +*/
|
| +case OP_SequenceTest: {
|
| + VdbeCursor *pC;
|
| + assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
| + pC = p->apCsr[pOp->p1];
|
| + assert( isSorter(pC) );
|
| + if( (pC->seqCount++)==0 ){
|
| + goto jump_to_p2;
|
| + }
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: OpenPseudo P1 P2 P3 * *
|
| +** Synopsis: P3 columns in r[P2]
|
| +**
|
| +** Open a new cursor that points to a fake table that contains a single
|
| +** row of data. The content of that one row is the content of memory
|
| +** register P2. In other words, cursor P1 becomes an alias for the
|
| +** MEM_Blob content contained in register P2.
|
| +**
|
| +** A pseudo-table created by this opcode is used to hold a single
|
| +** row output from the sorter so that the row can be decomposed into
|
| +** individual columns using the OP_Column opcode. The OP_Column opcode
|
| +** is the only cursor opcode that works with a pseudo-table.
|
| +**
|
| +** P3 is the number of fields in the records that will be stored by
|
| +** the pseudo-table.
|
| +*/
|
| +case OP_OpenPseudo: {
|
| + VdbeCursor *pCx;
|
| +
|
| + assert( pOp->p1>=0 );
|
| + assert( pOp->p3>=0 );
|
| + pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, CURTYPE_PSEUDO);
|
| + if( pCx==0 ) goto no_mem;
|
| + pCx->nullRow = 1;
|
| + pCx->uc.pseudoTableReg = pOp->p2;
|
| + pCx->isTable = 1;
|
| + assert( pOp->p5==0 );
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: Close P1 * * * *
|
| +**
|
| +** Close a cursor previously opened as P1. If P1 is not
|
| +** currently open, this instruction is a no-op.
|
| +*/
|
| +case OP_Close: {
|
| + assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
| + sqlite3VdbeFreeCursor(p, p->apCsr[pOp->p1]);
|
| + p->apCsr[pOp->p1] = 0;
|
| + break;
|
| +}
|
| +
|
| +#ifdef SQLITE_ENABLE_COLUMN_USED_MASK
|
| +/* Opcode: ColumnsUsed P1 * * P4 *
|
| +**
|
| +** This opcode (which only exists if SQLite was compiled with
|
| +** SQLITE_ENABLE_COLUMN_USED_MASK) identifies which columns of the
|
| +** table or index for cursor P1 are used. P4 is a 64-bit integer
|
| +** (P4_INT64) in which the first 63 bits are one for each of the
|
| +** first 63 columns of the table or index that are actually used
|
| +** by the cursor. The high-order bit is set if any column after
|
| +** the 64th is used.
|
| +*/
|
| +case OP_ColumnsUsed: {
|
| + VdbeCursor *pC;
|
| + pC = p->apCsr[pOp->p1];
|
| + assert( pC->eCurType==CURTYPE_BTREE );
|
| + pC->maskUsed = *(u64*)pOp->p4.pI64;
|
| + break;
|
| +}
|
| +#endif
|
| +
|
| +/* Opcode: SeekGE P1 P2 P3 P4 *
|
| +** Synopsis: key=r[P3@P4]
|
| +**
|
| +** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
|
| +** use the value in register P3 as the key. If cursor P1 refers
|
| +** to an SQL index, then P3 is the first in an array of P4 registers
|
| +** that are used as an unpacked index key.
|
| +**
|
| +** Reposition cursor P1 so that it points to the smallest entry that
|
| +** is greater than or equal to the key value. If there are no records
|
| +** greater than or equal to the key and P2 is not zero, then jump to P2.
|
| +**
|
| +** If the cursor P1 was opened using the OPFLAG_SEEKEQ flag, then this
|
| +** opcode will always land on a record that equally equals the key, or
|
| +** else jump immediately to P2. When the cursor is OPFLAG_SEEKEQ, this
|
| +** opcode must be followed by an IdxLE opcode with the same arguments.
|
| +** The IdxLE opcode will be skipped if this opcode succeeds, but the
|
| +** IdxLE opcode will be used on subsequent loop iterations.
|
| +**
|
| +** This opcode leaves the cursor configured to move in forward order,
|
| +** from the beginning toward the end. In other words, the cursor is
|
| +** configured to use Next, not Prev.
|
| +**
|
| +** See also: Found, NotFound, SeekLt, SeekGt, SeekLe
|
| +*/
|
| +/* Opcode: SeekGT P1 P2 P3 P4 *
|
| +** Synopsis: key=r[P3@P4]
|
| +**
|
| +** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
|
| +** use the value in register P3 as a key. If cursor P1 refers
|
| +** to an SQL index, then P3 is the first in an array of P4 registers
|
| +** that are used as an unpacked index key.
|
| +**
|
| +** Reposition cursor P1 so that it points to the smallest entry that
|
| +** is greater than the key value. If there are no records greater than
|
| +** the key and P2 is not zero, then jump to P2.
|
| +**
|
| +** This opcode leaves the cursor configured to move in forward order,
|
| +** from the beginning toward the end. In other words, the cursor is
|
| +** configured to use Next, not Prev.
|
| +**
|
| +** See also: Found, NotFound, SeekLt, SeekGe, SeekLe
|
| +*/
|
| +/* Opcode: SeekLT P1 P2 P3 P4 *
|
| +** Synopsis: key=r[P3@P4]
|
| +**
|
| +** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
|
| +** use the value in register P3 as a key. If cursor P1 refers
|
| +** to an SQL index, then P3 is the first in an array of P4 registers
|
| +** that are used as an unpacked index key.
|
| +**
|
| +** Reposition cursor P1 so that it points to the largest entry that
|
| +** is less than the key value. If there are no records less than
|
| +** the key and P2 is not zero, then jump to P2.
|
| +**
|
| +** This opcode leaves the cursor configured to move in reverse order,
|
| +** from the end toward the beginning. In other words, the cursor is
|
| +** configured to use Prev, not Next.
|
| +**
|
| +** See also: Found, NotFound, SeekGt, SeekGe, SeekLe
|
| +*/
|
| +/* Opcode: SeekLE P1 P2 P3 P4 *
|
| +** Synopsis: key=r[P3@P4]
|
| +**
|
| +** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
|
| +** use the value in register P3 as a key. If cursor P1 refers
|
| +** to an SQL index, then P3 is the first in an array of P4 registers
|
| +** that are used as an unpacked index key.
|
| +**
|
| +** Reposition cursor P1 so that it points to the largest entry that
|
| +** is less than or equal to the key value. If there are no records
|
| +** less than or equal to the key and P2 is not zero, then jump to P2.
|
| +**
|
| +** This opcode leaves the cursor configured to move in reverse order,
|
| +** from the end toward the beginning. In other words, the cursor is
|
| +** configured to use Prev, not Next.
|
| +**
|
| +** If the cursor P1 was opened using the OPFLAG_SEEKEQ flag, then this
|
| +** opcode will always land on a record that equally equals the key, or
|
| +** else jump immediately to P2. When the cursor is OPFLAG_SEEKEQ, this
|
| +** opcode must be followed by an IdxGE opcode with the same arguments.
|
| +** The IdxGE opcode will be skipped if this opcode succeeds, but the
|
| +** IdxGE opcode will be used on subsequent loop iterations.
|
| +**
|
| +** See also: Found, NotFound, SeekGt, SeekGe, SeekLt
|
| +*/
|
| +case OP_SeekLT: /* jump, in3 */
|
| +case OP_SeekLE: /* jump, in3 */
|
| +case OP_SeekGE: /* jump, in3 */
|
| +case OP_SeekGT: { /* jump, in3 */
|
| + int res; /* Comparison result */
|
| + int oc; /* Opcode */
|
| + VdbeCursor *pC; /* The cursor to seek */
|
| + UnpackedRecord r; /* The key to seek for */
|
| + int nField; /* Number of columns or fields in the key */
|
| + i64 iKey; /* The rowid we are to seek to */
|
| + int eqOnly; /* Only interested in == results */
|
| +
|
| + assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
| + assert( pOp->p2!=0 );
|
| + pC = p->apCsr[pOp->p1];
|
| + assert( pC!=0 );
|
| + assert( pC->eCurType==CURTYPE_BTREE );
|
| + assert( OP_SeekLE == OP_SeekLT+1 );
|
| + assert( OP_SeekGE == OP_SeekLT+2 );
|
| + assert( OP_SeekGT == OP_SeekLT+3 );
|
| + assert( pC->isOrdered );
|
| + assert( pC->uc.pCursor!=0 );
|
| + oc = pOp->opcode;
|
| + eqOnly = 0;
|
| + pC->nullRow = 0;
|
| +#ifdef SQLITE_DEBUG
|
| + pC->seekOp = pOp->opcode;
|
| +#endif
|
| +
|
| + if( pC->isTable ){
|
| + /* The BTREE_SEEK_EQ flag is only set on index cursors */
|
| + assert( sqlite3BtreeCursorHasHint(pC->uc.pCursor, BTREE_SEEK_EQ)==0 );
|
| +
|
| + /* The input value in P3 might be of any type: integer, real, string,
|
| + ** blob, or NULL. But it needs to be an integer before we can do
|
| + ** the seek, so convert it. */
|
| + pIn3 = &aMem[pOp->p3];
|
| + if( (pIn3->flags & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){
|
| + applyNumericAffinity(pIn3, 0);
|
| + }
|
| + iKey = sqlite3VdbeIntValue(pIn3);
|
| +
|
| + /* If the P3 value could not be converted into an integer without
|
| + ** loss of information, then special processing is required... */
|
| + if( (pIn3->flags & MEM_Int)==0 ){
|
| + if( (pIn3->flags & MEM_Real)==0 ){
|
| + /* If the P3 value cannot be converted into any kind of a number,
|
| + ** then the seek is not possible, so jump to P2 */
|
| + VdbeBranchTaken(1,2); goto jump_to_p2;
|
| + break;
|
| + }
|
| +
|
| + /* If the approximation iKey is larger than the actual real search
|
| + ** term, substitute >= for > and < for <=. e.g. if the search term
|
| + ** is 4.9 and the integer approximation 5:
|
| + **
|
| + ** (x > 4.9) -> (x >= 5)
|
| + ** (x <= 4.9) -> (x < 5)
|
| + */
|
| + if( pIn3->u.r<(double)iKey ){
|
| + assert( OP_SeekGE==(OP_SeekGT-1) );
|
| + assert( OP_SeekLT==(OP_SeekLE-1) );
|
| + assert( (OP_SeekLE & 0x0001)==(OP_SeekGT & 0x0001) );
|
| + if( (oc & 0x0001)==(OP_SeekGT & 0x0001) ) oc--;
|
| + }
|
| +
|
| + /* If the approximation iKey is smaller than the actual real search
|
| + ** term, substitute <= for < and > for >=. */
|
| + else if( pIn3->u.r>(double)iKey ){
|
| + assert( OP_SeekLE==(OP_SeekLT+1) );
|
| + assert( OP_SeekGT==(OP_SeekGE+1) );
|
| + assert( (OP_SeekLT & 0x0001)==(OP_SeekGE & 0x0001) );
|
| + if( (oc & 0x0001)==(OP_SeekLT & 0x0001) ) oc++;
|
| + }
|
| + }
|
| + rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, 0, (u64)iKey, 0, &res);
|
| + pC->movetoTarget = iKey; /* Used by OP_Delete */
|
| + if( rc!=SQLITE_OK ){
|
| + goto abort_due_to_error;
|
| + }
|
| + }else{
|
| + /* For a cursor with the BTREE_SEEK_EQ hint, only the OP_SeekGE and
|
| + ** OP_SeekLE opcodes are allowed, and these must be immediately followed
|
| + ** by an OP_IdxGT or OP_IdxLT opcode, respectively, with the same key.
|
| + */
|
| + if( sqlite3BtreeCursorHasHint(pC->uc.pCursor, BTREE_SEEK_EQ) ){
|
| + eqOnly = 1;
|
| + assert( pOp->opcode==OP_SeekGE || pOp->opcode==OP_SeekLE );
|
| + assert( pOp[1].opcode==OP_IdxLT || pOp[1].opcode==OP_IdxGT );
|
| + assert( pOp[1].p1==pOp[0].p1 );
|
| + assert( pOp[1].p2==pOp[0].p2 );
|
| + assert( pOp[1].p3==pOp[0].p3 );
|
| + assert( pOp[1].p4.i==pOp[0].p4.i );
|
| + }
|
| +
|
| + nField = pOp->p4.i;
|
| + assert( pOp->p4type==P4_INT32 );
|
| + assert( nField>0 );
|
| + r.pKeyInfo = pC->pKeyInfo;
|
| + r.nField = (u16)nField;
|
| +
|
| + /* The next line of code computes as follows, only faster:
|
| + ** if( oc==OP_SeekGT || oc==OP_SeekLE ){
|
| + ** r.default_rc = -1;
|
| + ** }else{
|
| + ** r.default_rc = +1;
|
| + ** }
|
| + */
|
| + r.default_rc = ((1 & (oc - OP_SeekLT)) ? -1 : +1);
|
| + assert( oc!=OP_SeekGT || r.default_rc==-1 );
|
| + assert( oc!=OP_SeekLE || r.default_rc==-1 );
|
| + assert( oc!=OP_SeekGE || r.default_rc==+1 );
|
| + assert( oc!=OP_SeekLT || r.default_rc==+1 );
|
| +
|
| + r.aMem = &aMem[pOp->p3];
|
| +#ifdef SQLITE_DEBUG
|
| + { int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
|
| +#endif
|
| + ExpandBlob(r.aMem);
|
| + r.eqSeen = 0;
|
| + rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, &r, 0, 0, &res);
|
| + if( rc!=SQLITE_OK ){
|
| + goto abort_due_to_error;
|
| + }
|
| + if( eqOnly && r.eqSeen==0 ){
|
| + assert( res!=0 );
|
| + goto seek_not_found;
|
| + }
|
| + }
|
| + pC->deferredMoveto = 0;
|
| + pC->cacheStatus = CACHE_STALE;
|
| +#ifdef SQLITE_TEST
|
| + sqlite3_search_count++;
|
| +#endif
|
| + if( oc>=OP_SeekGE ){ assert( oc==OP_SeekGE || oc==OP_SeekGT );
|
| + if( res<0 || (res==0 && oc==OP_SeekGT) ){
|
| + res = 0;
|
| + rc = sqlite3BtreeNext(pC->uc.pCursor, &res);
|
| + if( rc!=SQLITE_OK ) goto abort_due_to_error;
|
| + }else{
|
| + res = 0;
|
| + }
|
| + }else{
|
| + assert( oc==OP_SeekLT || oc==OP_SeekLE );
|
| + if( res>0 || (res==0 && oc==OP_SeekLT) ){
|
| + res = 0;
|
| + rc = sqlite3BtreePrevious(pC->uc.pCursor, &res);
|
| + if( rc!=SQLITE_OK ) goto abort_due_to_error;
|
| + }else{
|
| + /* res might be negative because the table is empty. Check to
|
| + ** see if this is the case.
|
| + */
|
| + res = sqlite3BtreeEof(pC->uc.pCursor);
|
| + }
|
| + }
|
| +seek_not_found:
|
| + assert( pOp->p2>0 );
|
| + VdbeBranchTaken(res!=0,2);
|
| + if( res ){
|
| + goto jump_to_p2;
|
| + }else if( eqOnly ){
|
| + assert( pOp[1].opcode==OP_IdxLT || pOp[1].opcode==OP_IdxGT );
|
| + pOp++; /* Skip the OP_IdxLt or OP_IdxGT that follows */
|
| + }
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: Seek P1 P2 * * *
|
| +** Synopsis: intkey=r[P2]
|
| +**
|
| +** P1 is an open table cursor and P2 is a rowid integer. Arrange
|
| +** for P1 to move so that it points to the rowid given by P2.
|
| +**
|
| +** This is actually a deferred seek. Nothing actually happens until
|
| +** the cursor is used to read a record. That way, if no reads
|
| +** occur, no unnecessary I/O happens.
|
| +*/
|
| +case OP_Seek: { /* in2 */
|
| + VdbeCursor *pC;
|
| +
|
| + assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
| + pC = p->apCsr[pOp->p1];
|
| + assert( pC!=0 );
|
| + assert( pC->eCurType==CURTYPE_BTREE );
|
| + assert( pC->uc.pCursor!=0 );
|
| + assert( pC->isTable );
|
| + pC->nullRow = 0;
|
| + pIn2 = &aMem[pOp->p2];
|
| + pC->movetoTarget = sqlite3VdbeIntValue(pIn2);
|
| + pC->deferredMoveto = 1;
|
| + break;
|
| +}
|
| +
|
| +
|
| +/* Opcode: Found P1 P2 P3 P4 *
|
| +** Synopsis: key=r[P3@P4]
|
| +**
|
| +** If P4==0 then register P3 holds a blob constructed by MakeRecord. If
|
| +** P4>0 then register P3 is the first of P4 registers that form an unpacked
|
| +** record.
|
| +**
|
| +** Cursor P1 is on an index btree. If the record identified by P3 and P4
|
| +** is a prefix of any entry in P1 then a jump is made to P2 and
|
| +** P1 is left pointing at the matching entry.
|
| +**
|
| +** This operation leaves the cursor in a state where it can be
|
| +** advanced in the forward direction. The Next instruction will work,
|
| +** but not the Prev instruction.
|
| +**
|
| +** See also: NotFound, NoConflict, NotExists. SeekGe
|
| +*/
|
| +/* Opcode: NotFound P1 P2 P3 P4 *
|
| +** Synopsis: key=r[P3@P4]
|
| +**
|
| +** If P4==0 then register P3 holds a blob constructed by MakeRecord. If
|
| +** P4>0 then register P3 is the first of P4 registers that form an unpacked
|
| +** record.
|
| +**
|
| +** Cursor P1 is on an index btree. If the record identified by P3 and P4
|
| +** is not the prefix of any entry in P1 then a jump is made to P2. If P1
|
| +** does contain an entry whose prefix matches the P3/P4 record then control
|
| +** falls through to the next instruction and P1 is left pointing at the
|
| +** matching entry.
|
| +**
|
| +** This operation leaves the cursor in a state where it cannot be
|
| +** advanced in either direction. In other words, the Next and Prev
|
| +** opcodes do not work after this operation.
|
| +**
|
| +** See also: Found, NotExists, NoConflict
|
| +*/
|
| +/* Opcode: NoConflict P1 P2 P3 P4 *
|
| +** Synopsis: key=r[P3@P4]
|
| +**
|
| +** If P4==0 then register P3 holds a blob constructed by MakeRecord. If
|
| +** P4>0 then register P3 is the first of P4 registers that form an unpacked
|
| +** record.
|
| +**
|
| +** Cursor P1 is on an index btree. If the record identified by P3 and P4
|
| +** contains any NULL value, jump immediately to P2. If all terms of the
|
| +** record are not-NULL then a check is done to determine if any row in the
|
| +** P1 index btree has a matching key prefix. If there are no matches, jump
|
| +** immediately to P2. If there is a match, fall through and leave the P1
|
| +** cursor pointing to the matching row.
|
| +**
|
| +** This opcode is similar to OP_NotFound with the exceptions that the
|
| +** branch is always taken if any part of the search key input is NULL.
|
| +**
|
| +** This operation leaves the cursor in a state where it cannot be
|
| +** advanced in either direction. In other words, the Next and Prev
|
| +** opcodes do not work after this operation.
|
| +**
|
| +** See also: NotFound, Found, NotExists
|
| +*/
|
| +case OP_NoConflict: /* jump, in3 */
|
| +case OP_NotFound: /* jump, in3 */
|
| +case OP_Found: { /* jump, in3 */
|
| + int alreadyExists;
|
| + int takeJump;
|
| + int ii;
|
| + VdbeCursor *pC;
|
| + int res;
|
| + char *pFree;
|
| + UnpackedRecord *pIdxKey;
|
| + UnpackedRecord r;
|
| + char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*4 + 7];
|
| +
|
| +#ifdef SQLITE_TEST
|
| + if( pOp->opcode!=OP_NoConflict ) sqlite3_found_count++;
|
| +#endif
|
| +
|
| + assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
| + assert( pOp->p4type==P4_INT32 );
|
| + pC = p->apCsr[pOp->p1];
|
| + assert( pC!=0 );
|
| +#ifdef SQLITE_DEBUG
|
| + pC->seekOp = pOp->opcode;
|
| +#endif
|
| + pIn3 = &aMem[pOp->p3];
|
| + assert( pC->eCurType==CURTYPE_BTREE );
|
| + assert( pC->uc.pCursor!=0 );
|
| + assert( pC->isTable==0 );
|
| + pFree = 0;
|
| + if( pOp->p4.i>0 ){
|
| + r.pKeyInfo = pC->pKeyInfo;
|
| + r.nField = (u16)pOp->p4.i;
|
| + r.aMem = pIn3;
|
| + for(ii=0; ii<r.nField; ii++){
|
| + assert( memIsValid(&r.aMem[ii]) );
|
| + ExpandBlob(&r.aMem[ii]);
|
| +#ifdef SQLITE_DEBUG
|
| + if( ii ) REGISTER_TRACE(pOp->p3+ii, &r.aMem[ii]);
|
| +#endif
|
| + }
|
| + pIdxKey = &r;
|
| + }else{
|
| + pIdxKey = sqlite3VdbeAllocUnpackedRecord(
|
| + pC->pKeyInfo, aTempRec, sizeof(aTempRec), &pFree
|
| + );
|
| + if( pIdxKey==0 ) goto no_mem;
|
| + assert( pIn3->flags & MEM_Blob );
|
| + ExpandBlob(pIn3);
|
| + sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z, pIdxKey);
|
| + }
|
| + pIdxKey->default_rc = 0;
|
| + takeJump = 0;
|
| + if( pOp->opcode==OP_NoConflict ){
|
| + /* For the OP_NoConflict opcode, take the jump if any of the
|
| + ** input fields are NULL, since any key with a NULL will not
|
| + ** conflict */
|
| + for(ii=0; ii<pIdxKey->nField; ii++){
|
| + if( pIdxKey->aMem[ii].flags & MEM_Null ){
|
| + takeJump = 1;
|
| + break;
|
| + }
|
| + }
|
| + }
|
| + rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, pIdxKey, 0, 0, &res);
|
| + sqlite3DbFree(db, pFree);
|
| + if( rc!=SQLITE_OK ){
|
| + break;
|
| + }
|
| + pC->seekResult = res;
|
| + alreadyExists = (res==0);
|
| + pC->nullRow = 1-alreadyExists;
|
| + pC->deferredMoveto = 0;
|
| + pC->cacheStatus = CACHE_STALE;
|
| + if( pOp->opcode==OP_Found ){
|
| + VdbeBranchTaken(alreadyExists!=0,2);
|
| + if( alreadyExists ) goto jump_to_p2;
|
| + }else{
|
| + VdbeBranchTaken(takeJump||alreadyExists==0,2);
|
| + if( takeJump || !alreadyExists ) goto jump_to_p2;
|
| + }
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: NotExists P1 P2 P3 * *
|
| +** Synopsis: intkey=r[P3]
|
| +**
|
| +** P1 is the index of a cursor open on an SQL table btree (with integer
|
| +** keys). P3 is an integer rowid. If P1 does not contain a record with
|
| +** rowid P3 then jump immediately to P2. Or, if P2 is 0, raise an
|
| +** SQLITE_CORRUPT error. If P1 does contain a record with rowid P3 then
|
| +** leave the cursor pointing at that record and fall through to the next
|
| +** instruction.
|
| +**
|
| +** The OP_NotFound opcode performs the same operation on index btrees
|
| +** (with arbitrary multi-value keys).
|
| +**
|
| +** This opcode leaves the cursor in a state where it cannot be advanced
|
| +** in either direction. In other words, the Next and Prev opcodes will
|
| +** not work following this opcode.
|
| +**
|
| +** See also: Found, NotFound, NoConflict
|
| +*/
|
| +case OP_NotExists: { /* jump, in3 */
|
| + VdbeCursor *pC;
|
| + BtCursor *pCrsr;
|
| + int res;
|
| + u64 iKey;
|
| +
|
| + pIn3 = &aMem[pOp->p3];
|
| + assert( pIn3->flags & MEM_Int );
|
| + assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
| + pC = p->apCsr[pOp->p1];
|
| + assert( pC!=0 );
|
| +#ifdef SQLITE_DEBUG
|
| + pC->seekOp = 0;
|
| +#endif
|
| + assert( pC->isTable );
|
| + assert( pC->eCurType==CURTYPE_BTREE );
|
| + pCrsr = pC->uc.pCursor;
|
| + assert( pCrsr!=0 );
|
| + res = 0;
|
| + iKey = pIn3->u.i;
|
| + rc = sqlite3BtreeMovetoUnpacked(pCrsr, 0, iKey, 0, &res);
|
| + assert( rc==SQLITE_OK || res==0 );
|
| + pC->movetoTarget = iKey; /* Used by OP_Delete */
|
| + pC->nullRow = 0;
|
| + pC->cacheStatus = CACHE_STALE;
|
| + pC->deferredMoveto = 0;
|
| + VdbeBranchTaken(res!=0,2);
|
| + pC->seekResult = res;
|
| + if( res!=0 ){
|
| + assert( rc==SQLITE_OK );
|
| + if( pOp->p2==0 ){
|
| + rc = SQLITE_CORRUPT_BKPT;
|
| + }else{
|
| + goto jump_to_p2;
|
| + }
|
| + }
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: Sequence P1 P2 * * *
|
| +** Synopsis: r[P2]=cursor[P1].ctr++
|
| +**
|
| +** Find the next available sequence number for cursor P1.
|
| +** Write the sequence number into register P2.
|
| +** The sequence number on the cursor is incremented after this
|
| +** instruction.
|
| +*/
|
| +case OP_Sequence: { /* out2 */
|
| + assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
| + assert( p->apCsr[pOp->p1]!=0 );
|
| + assert( p->apCsr[pOp->p1]->eCurType!=CURTYPE_VTAB );
|
| + pOut = out2Prerelease(p, pOp);
|
| + pOut->u.i = p->apCsr[pOp->p1]->seqCount++;
|
| + break;
|
| +}
|
| +
|
| +
|
| +/* Opcode: NewRowid P1 P2 P3 * *
|
| +** Synopsis: r[P2]=rowid
|
| +**
|
| +** Get a new integer record number (a.k.a "rowid") used as the key to a table.
|
| +** The record number is not previously used as a key in the database
|
| +** table that cursor P1 points to. The new record number is written
|
| +** written to register P2.
|
| +**
|
| +** If P3>0 then P3 is a register in the root frame of this VDBE that holds
|
| +** the largest previously generated record number. No new record numbers are
|
| +** allowed to be less than this value. When this value reaches its maximum,
|
| +** an SQLITE_FULL error is generated. The P3 register is updated with the '
|
| +** generated record number. This P3 mechanism is used to help implement the
|
| +** AUTOINCREMENT feature.
|
| +*/
|
| +case OP_NewRowid: { /* out2 */
|
| + i64 v; /* The new rowid */
|
| + VdbeCursor *pC; /* Cursor of table to get the new rowid */
|
| + int res; /* Result of an sqlite3BtreeLast() */
|
| + int cnt; /* Counter to limit the number of searches */
|
| + Mem *pMem; /* Register holding largest rowid for AUTOINCREMENT */
|
| + VdbeFrame *pFrame; /* Root frame of VDBE */
|
| +
|
| + v = 0;
|
| + res = 0;
|
| + pOut = out2Prerelease(p, pOp);
|
| + assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
| + pC = p->apCsr[pOp->p1];
|
| + assert( pC!=0 );
|
| + assert( pC->eCurType==CURTYPE_BTREE );
|
| + assert( pC->uc.pCursor!=0 );
|
| + {
|
| + /* The next rowid or record number (different terms for the same
|
| + ** thing) is obtained in a two-step algorithm.
|
| + **
|
| + ** First we attempt to find the largest existing rowid and add one
|
| + ** to that. But if the largest existing rowid is already the maximum
|
| + ** positive integer, we have to fall through to the second
|
| + ** probabilistic algorithm
|
| + **
|
| + ** The second algorithm is to select a rowid at random and see if
|
| + ** it already exists in the table. If it does not exist, we have
|
| + ** succeeded. If the random rowid does exist, we select a new one
|
| + ** and try again, up to 100 times.
|
| + */
|
| + assert( pC->isTable );
|
| +
|
| +#ifdef SQLITE_32BIT_ROWID
|
| +# define MAX_ROWID 0x7fffffff
|
| +#else
|
| + /* Some compilers complain about constants of the form 0x7fffffffffffffff.
|
| + ** Others complain about 0x7ffffffffffffffffLL. The following macro seems
|
| + ** to provide the constant while making all compilers happy.
|
| + */
|
| +# define MAX_ROWID (i64)( (((u64)0x7fffffff)<<32) | (u64)0xffffffff )
|
| +#endif
|
| +
|
| + if( !pC->useRandomRowid ){
|
| + rc = sqlite3BtreeLast(pC->uc.pCursor, &res);
|
| + if( rc!=SQLITE_OK ){
|
| + goto abort_due_to_error;
|
| + }
|
| + if( res ){
|
| + v = 1; /* IMP: R-61914-48074 */
|
| + }else{
|
| + assert( sqlite3BtreeCursorIsValid(pC->uc.pCursor) );
|
| + rc = sqlite3BtreeKeySize(pC->uc.pCursor, &v);
|
| + assert( rc==SQLITE_OK ); /* Cannot fail following BtreeLast() */
|
| + if( v>=MAX_ROWID ){
|
| + pC->useRandomRowid = 1;
|
| + }else{
|
| + v++; /* IMP: R-29538-34987 */
|
| + }
|
| + }
|
| + }
|
| +
|
| +#ifndef SQLITE_OMIT_AUTOINCREMENT
|
| + if( pOp->p3 ){
|
| + /* Assert that P3 is a valid memory cell. */
|
| + assert( pOp->p3>0 );
|
| + if( p->pFrame ){
|
| + for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent);
|
| + /* Assert that P3 is a valid memory cell. */
|
| + assert( pOp->p3<=pFrame->nMem );
|
| + pMem = &pFrame->aMem[pOp->p3];
|
| + }else{
|
| + /* Assert that P3 is a valid memory cell. */
|
| + assert( pOp->p3<=(p->nMem-p->nCursor) );
|
| + pMem = &aMem[pOp->p3];
|
| + memAboutToChange(p, pMem);
|
| + }
|
| + assert( memIsValid(pMem) );
|
| +
|
| + REGISTER_TRACE(pOp->p3, pMem);
|
| + sqlite3VdbeMemIntegerify(pMem);
|
| + assert( (pMem->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */
|
| + if( pMem->u.i==MAX_ROWID || pC->useRandomRowid ){
|
| + rc = SQLITE_FULL; /* IMP: R-12275-61338 */
|
| + goto abort_due_to_error;
|
| + }
|
| + if( v<pMem->u.i+1 ){
|
| + v = pMem->u.i + 1;
|
| + }
|
| + pMem->u.i = v;
|
| + }
|
| +#endif
|
| + if( pC->useRandomRowid ){
|
| + /* IMPLEMENTATION-OF: R-07677-41881 If the largest ROWID is equal to the
|
| + ** largest possible integer (9223372036854775807) then the database
|
| + ** engine starts picking positive candidate ROWIDs at random until
|
| + ** it finds one that is not previously used. */
|
| + assert( pOp->p3==0 ); /* We cannot be in random rowid mode if this is
|
| + ** an AUTOINCREMENT table. */
|
| + cnt = 0;
|
| + do{
|
| + sqlite3_randomness(sizeof(v), &v);
|
| + v &= (MAX_ROWID>>1); v++; /* Ensure that v is greater than zero */
|
| + }while( ((rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, 0, (u64)v,
|
| + 0, &res))==SQLITE_OK)
|
| + && (res==0)
|
| + && (++cnt<100));
|
| + if( rc==SQLITE_OK && res==0 ){
|
| + rc = SQLITE_FULL; /* IMP: R-38219-53002 */
|
| + goto abort_due_to_error;
|
| + }
|
| + assert( v>0 ); /* EV: R-40812-03570 */
|
| + }
|
| + pC->deferredMoveto = 0;
|
| + pC->cacheStatus = CACHE_STALE;
|
| + }
|
| + pOut->u.i = v;
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: Insert P1 P2 P3 P4 P5
|
| +** Synopsis: intkey=r[P3] data=r[P2]
|
| +**
|
| +** Write an entry into the table of cursor P1. A new entry is
|
| +** created if it doesn't already exist or the data for an existing
|
| +** entry is overwritten. The data is the value MEM_Blob stored in register
|
| +** number P2. The key is stored in register P3. The key must
|
| +** be a MEM_Int.
|
| +**
|
| +** If the OPFLAG_NCHANGE flag of P5 is set, then the row change count is
|
| +** incremented (otherwise not). If the OPFLAG_LASTROWID flag of P5 is set,
|
| +** then rowid is stored for subsequent return by the
|
| +** sqlite3_last_insert_rowid() function (otherwise it is unmodified).
|
| +**
|
| +** If the OPFLAG_USESEEKRESULT flag of P5 is set and if the result of
|
| +** the last seek operation (OP_NotExists) was a success, then this
|
| +** operation will not attempt to find the appropriate row before doing
|
| +** the insert but will instead overwrite the row that the cursor is
|
| +** currently pointing to. Presumably, the prior OP_NotExists opcode
|
| +** has already positioned the cursor correctly. This is an optimization
|
| +** that boosts performance by avoiding redundant seeks.
|
| +**
|
| +** If the OPFLAG_ISUPDATE flag is set, then this opcode is part of an
|
| +** UPDATE operation. Otherwise (if the flag is clear) then this opcode
|
| +** is part of an INSERT operation. The difference is only important to
|
| +** the update hook.
|
| +**
|
| +** Parameter P4 may point to a string containing the table-name, or
|
| +** may be NULL. If it is not NULL, then the update-hook
|
| +** (sqlite3.xUpdateCallback) is invoked following a successful insert.
|
| +**
|
| +** (WARNING/TODO: If P1 is a pseudo-cursor and P2 is dynamically
|
| +** allocated, then ownership of P2 is transferred to the pseudo-cursor
|
| +** and register P2 becomes ephemeral. If the cursor is changed, the
|
| +** value of register P2 will then change. Make sure this does not
|
| +** cause any problems.)
|
| +**
|
| +** This instruction only works on tables. The equivalent instruction
|
| +** for indices is OP_IdxInsert.
|
| +*/
|
| +/* Opcode: InsertInt P1 P2 P3 P4 P5
|
| +** Synopsis: intkey=P3 data=r[P2]
|
| +**
|
| +** This works exactly like OP_Insert except that the key is the
|
| +** integer value P3, not the value of the integer stored in register P3.
|
| +*/
|
| +case OP_Insert:
|
| +case OP_InsertInt: {
|
| + Mem *pData; /* MEM cell holding data for the record to be inserted */
|
| + Mem *pKey; /* MEM cell holding key for the record */
|
| + i64 iKey; /* The integer ROWID or key for the record to be inserted */
|
| + VdbeCursor *pC; /* Cursor to table into which insert is written */
|
| + int nZero; /* Number of zero-bytes to append */
|
| + int seekResult; /* Result of prior seek or 0 if no USESEEKRESULT flag */
|
| + const char *zDb; /* database name - used by the update hook */
|
| + const char *zTbl; /* Table name - used by the opdate hook */
|
| + int op; /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */
|
| +
|
| + pData = &aMem[pOp->p2];
|
| + assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
| + assert( memIsValid(pData) );
|
| + pC = p->apCsr[pOp->p1];
|
| + assert( pC!=0 );
|
| + assert( pC->eCurType==CURTYPE_BTREE );
|
| + assert( pC->uc.pCursor!=0 );
|
| + assert( pC->isTable );
|
| + REGISTER_TRACE(pOp->p2, pData);
|
| +
|
| + if( pOp->opcode==OP_Insert ){
|
| + pKey = &aMem[pOp->p3];
|
| + assert( pKey->flags & MEM_Int );
|
| + assert( memIsValid(pKey) );
|
| + REGISTER_TRACE(pOp->p3, pKey);
|
| + iKey = pKey->u.i;
|
| + }else{
|
| + assert( pOp->opcode==OP_InsertInt );
|
| + iKey = pOp->p3;
|
| + }
|
| +
|
| + if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
|
| + if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = lastRowid = iKey;
|
| + if( pData->flags & MEM_Null ){
|
| + pData->z = 0;
|
| + pData->n = 0;
|
| + }else{
|
| + assert( pData->flags & (MEM_Blob|MEM_Str) );
|
| + }
|
| + seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0);
|
| + if( pData->flags & MEM_Zero ){
|
| + nZero = pData->u.nZero;
|
| + }else{
|
| + nZero = 0;
|
| + }
|
| + rc = sqlite3BtreeInsert(pC->uc.pCursor, 0, iKey,
|
| + pData->z, pData->n, nZero,
|
| + (pOp->p5 & OPFLAG_APPEND)!=0, seekResult
|
| + );
|
| + pC->deferredMoveto = 0;
|
| + pC->cacheStatus = CACHE_STALE;
|
| +
|
| + /* Invoke the update-hook if required. */
|
| + if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z ){
|
| + zDb = db->aDb[pC->iDb].zName;
|
| + zTbl = pOp->p4.z;
|
| + op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT);
|
| + assert( pC->isTable );
|
| + db->xUpdateCallback(db->pUpdateArg, op, zDb, zTbl, iKey);
|
| + assert( pC->iDb>=0 );
|
| + }
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: Delete P1 P2 * P4 P5
|
| +**
|
| +** Delete the record at which the P1 cursor is currently pointing.
|
| +**
|
| +** If the P5 parameter is non-zero, the cursor will be left pointing at
|
| +** either the next or the previous record in the table. If it is left
|
| +** pointing at the next record, then the next Next instruction will be a
|
| +** no-op. As a result, in this case it is OK to delete a record from within a
|
| +** Next loop. If P5 is zero, then the cursor is left in an undefined state.
|
| +**
|
| +** If the OPFLAG_NCHANGE flag of P2 is set, then the row change count is
|
| +** incremented (otherwise not).
|
| +**
|
| +** P1 must not be pseudo-table. It has to be a real table with
|
| +** multiple rows.
|
| +**
|
| +** If P4 is not NULL, then it is the name of the table that P1 is
|
| +** pointing to. The update hook will be invoked, if it exists.
|
| +** If P4 is not NULL then the P1 cursor must have been positioned
|
| +** using OP_NotFound prior to invoking this opcode.
|
| +*/
|
| +case OP_Delete: {
|
| + VdbeCursor *pC;
|
| + u8 hasUpdateCallback;
|
| +
|
| + assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
| + pC = p->apCsr[pOp->p1];
|
| + assert( pC!=0 );
|
| + assert( pC->eCurType==CURTYPE_BTREE );
|
| + assert( pC->uc.pCursor!=0 );
|
| + assert( pC->deferredMoveto==0 );
|
| +
|
| + hasUpdateCallback = db->xUpdateCallback && pOp->p4.z && pC->isTable;
|
| + if( pOp->p5 && hasUpdateCallback ){
|
| + sqlite3BtreeKeySize(pC->uc.pCursor, &pC->movetoTarget);
|
| + }
|
| +
|
| +#ifdef SQLITE_DEBUG
|
| + /* The seek operation that positioned the cursor prior to OP_Delete will
|
| + ** have also set the pC->movetoTarget field to the rowid of the row that
|
| + ** is being deleted */
|
| + if( pOp->p4.z && pC->isTable && pOp->p5==0 ){
|
| + i64 iKey = 0;
|
| + sqlite3BtreeKeySize(pC->uc.pCursor, &iKey);
|
| + assert( pC->movetoTarget==iKey );
|
| + }
|
| +#endif
|
| +
|
| + rc = sqlite3BtreeDelete(pC->uc.pCursor, pOp->p5);
|
| + pC->cacheStatus = CACHE_STALE;
|
| +
|
| + /* Invoke the update-hook if required. */
|
| + if( rc==SQLITE_OK && hasUpdateCallback ){
|
| + db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE,
|
| + db->aDb[pC->iDb].zName, pOp->p4.z, pC->movetoTarget);
|
| + assert( pC->iDb>=0 );
|
| + }
|
| + if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++;
|
| + break;
|
| +}
|
| +/* Opcode: ResetCount * * * * *
|
| +**
|
| +** The value of the change counter is copied to the database handle
|
| +** change counter (returned by subsequent calls to sqlite3_changes()).
|
| +** Then the VMs internal change counter resets to 0.
|
| +** This is used by trigger programs.
|
| +*/
|
| +case OP_ResetCount: {
|
| + sqlite3VdbeSetChanges(db, p->nChange);
|
| + p->nChange = 0;
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: SorterCompare P1 P2 P3 P4
|
| +** Synopsis: if key(P1)!=trim(r[P3],P4) goto P2
|
| +**
|
| +** P1 is a sorter cursor. This instruction compares a prefix of the
|
| +** record blob in register P3 against a prefix of the entry that
|
| +** the sorter cursor currently points to. Only the first P4 fields
|
| +** of r[P3] and the sorter record are compared.
|
| +**
|
| +** If either P3 or the sorter contains a NULL in one of their significant
|
| +** fields (not counting the P4 fields at the end which are ignored) then
|
| +** the comparison is assumed to be equal.
|
| +**
|
| +** Fall through to next instruction if the two records compare equal to
|
| +** each other. Jump to P2 if they are different.
|
| +*/
|
| +case OP_SorterCompare: {
|
| + VdbeCursor *pC;
|
| + int res;
|
| + int nKeyCol;
|
| +
|
| + pC = p->apCsr[pOp->p1];
|
| + assert( isSorter(pC) );
|
| + assert( pOp->p4type==P4_INT32 );
|
| + pIn3 = &aMem[pOp->p3];
|
| + nKeyCol = pOp->p4.i;
|
| + res = 0;
|
| + rc = sqlite3VdbeSorterCompare(pC, pIn3, nKeyCol, &res);
|
| + VdbeBranchTaken(res!=0,2);
|
| + if( res ) goto jump_to_p2;
|
| + break;
|
| +};
|
| +
|
| +/* Opcode: SorterData P1 P2 P3 * *
|
| +** Synopsis: r[P2]=data
|
| +**
|
| +** Write into register P2 the current sorter data for sorter cursor P1.
|
| +** Then clear the column header cache on cursor P3.
|
| +**
|
| +** This opcode is normally use to move a record out of the sorter and into
|
| +** a register that is the source for a pseudo-table cursor created using
|
| +** OpenPseudo. That pseudo-table cursor is the one that is identified by
|
| +** parameter P3. Clearing the P3 column cache as part of this opcode saves
|
| +** us from having to issue a separate NullRow instruction to clear that cache.
|
| +*/
|
| +case OP_SorterData: {
|
| + VdbeCursor *pC;
|
| +
|
| + pOut = &aMem[pOp->p2];
|
| + pC = p->apCsr[pOp->p1];
|
| + assert( isSorter(pC) );
|
| + rc = sqlite3VdbeSorterRowkey(pC, pOut);
|
| + assert( rc!=SQLITE_OK || (pOut->flags & MEM_Blob) );
|
| + assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
| + p->apCsr[pOp->p3]->cacheStatus = CACHE_STALE;
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: RowData P1 P2 * * *
|
| +** Synopsis: r[P2]=data
|
| +**
|
| +** Write into register P2 the complete row data for cursor P1.
|
| +** There is no interpretation of the data.
|
| +** It is just copied onto the P2 register exactly as
|
| +** it is found in the database file.
|
| +**
|
| +** If the P1 cursor must be pointing to a valid row (not a NULL row)
|
| +** of a real table, not a pseudo-table.
|
| +*/
|
| +/* Opcode: RowKey P1 P2 * * *
|
| +** Synopsis: r[P2]=key
|
| +**
|
| +** Write into register P2 the complete row key for cursor P1.
|
| +** There is no interpretation of the data.
|
| +** The key is copied onto the P2 register exactly as
|
| +** it is found in the database file.
|
| +**
|
| +** If the P1 cursor must be pointing to a valid row (not a NULL row)
|
| +** of a real table, not a pseudo-table.
|
| +*/
|
| +case OP_RowKey:
|
| +case OP_RowData: {
|
| + VdbeCursor *pC;
|
| + BtCursor *pCrsr;
|
| + u32 n;
|
| + i64 n64;
|
| +
|
| + pOut = &aMem[pOp->p2];
|
| + memAboutToChange(p, pOut);
|
| +
|
| + /* Note that RowKey and RowData are really exactly the same instruction */
|
| + assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
| + pC = p->apCsr[pOp->p1];
|
| + assert( pC!=0 );
|
| + assert( pC->eCurType==CURTYPE_BTREE );
|
| + assert( isSorter(pC)==0 );
|
| + assert( pC->isTable || pOp->opcode!=OP_RowData );
|
| + assert( pC->isTable==0 || pOp->opcode==OP_RowData );
|
| + assert( pC->nullRow==0 );
|
| + assert( pC->uc.pCursor!=0 );
|
| + pCrsr = pC->uc.pCursor;
|
| +
|
| + /* The OP_RowKey and OP_RowData opcodes always follow OP_NotExists or
|
| + ** OP_Rewind/Op_Next with no intervening instructions that might invalidate
|
| + ** the cursor. If this where not the case, on of the following assert()s
|
| + ** would fail. Should this ever change (because of changes in the code
|
| + ** generator) then the fix would be to insert a call to
|
| + ** sqlite3VdbeCursorMoveto().
|
| + */
|
| + assert( pC->deferredMoveto==0 );
|
| + assert( sqlite3BtreeCursorIsValid(pCrsr) );
|
| +#if 0 /* Not required due to the previous to assert() statements */
|
| + rc = sqlite3VdbeCursorMoveto(pC);
|
| + if( rc!=SQLITE_OK ) goto abort_due_to_error;
|
| +#endif
|
| +
|
| + if( pC->isTable==0 ){
|
| + assert( !pC->isTable );
|
| + VVA_ONLY(rc =) sqlite3BtreeKeySize(pCrsr, &n64);
|
| + assert( rc==SQLITE_OK ); /* True because of CursorMoveto() call above */
|
| + if( n64>db->aLimit[SQLITE_LIMIT_LENGTH] ){
|
| + goto too_big;
|
| + }
|
| + n = (u32)n64;
|
| + }else{
|
| + VVA_ONLY(rc =) sqlite3BtreeDataSize(pCrsr, &n);
|
| + assert( rc==SQLITE_OK ); /* DataSize() cannot fail */
|
| + if( n>(u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
|
| + goto too_big;
|
| + }
|
| + }
|
| + testcase( n==0 );
|
| + if( sqlite3VdbeMemClearAndResize(pOut, MAX(n,32)) ){
|
| + goto no_mem;
|
| + }
|
| + pOut->n = n;
|
| + MemSetTypeFlag(pOut, MEM_Blob);
|
| + if( pC->isTable==0 ){
|
| + rc = sqlite3BtreeKey(pCrsr, 0, n, pOut->z);
|
| + }else{
|
| + rc = sqlite3BtreeData(pCrsr, 0, n, pOut->z);
|
| + }
|
| + pOut->enc = SQLITE_UTF8; /* In case the blob is ever cast to text */
|
| + UPDATE_MAX_BLOBSIZE(pOut);
|
| + REGISTER_TRACE(pOp->p2, pOut);
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: Rowid P1 P2 * * *
|
| +** Synopsis: r[P2]=rowid
|
| +**
|
| +** Store in register P2 an integer which is the key of the table entry that
|
| +** P1 is currently point to.
|
| +**
|
| +** P1 can be either an ordinary table or a virtual table. There used to
|
| +** be a separate OP_VRowid opcode for use with virtual tables, but this
|
| +** one opcode now works for both table types.
|
| +*/
|
| +case OP_Rowid: { /* out2 */
|
| + VdbeCursor *pC;
|
| + i64 v;
|
| + sqlite3_vtab *pVtab;
|
| + const sqlite3_module *pModule;
|
| +
|
| + pOut = out2Prerelease(p, pOp);
|
| + assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
| + pC = p->apCsr[pOp->p1];
|
| + assert( pC!=0 );
|
| + assert( pC->eCurType!=CURTYPE_PSEUDO || pC->nullRow );
|
| + if( pC->nullRow ){
|
| + pOut->flags = MEM_Null;
|
| + break;
|
| + }else if( pC->deferredMoveto ){
|
| + v = pC->movetoTarget;
|
| +#ifndef SQLITE_OMIT_VIRTUALTABLE
|
| + }else if( pC->eCurType==CURTYPE_VTAB ){
|
| + assert( pC->uc.pVCur!=0 );
|
| + pVtab = pC->uc.pVCur->pVtab;
|
| + pModule = pVtab->pModule;
|
| + assert( pModule->xRowid );
|
| + rc = pModule->xRowid(pC->uc.pVCur, &v);
|
| + sqlite3VtabImportErrmsg(p, pVtab);
|
| +#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
| + }else{
|
| + assert( pC->eCurType==CURTYPE_BTREE );
|
| + assert( pC->uc.pCursor!=0 );
|
| + rc = sqlite3VdbeCursorRestore(pC);
|
| + if( rc ) goto abort_due_to_error;
|
| + if( pC->nullRow ){
|
| + pOut->flags = MEM_Null;
|
| + break;
|
| + }
|
| + rc = sqlite3BtreeKeySize(pC->uc.pCursor, &v);
|
| + assert( rc==SQLITE_OK ); /* Always so because of CursorRestore() above */
|
| + }
|
| + pOut->u.i = v;
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: NullRow P1 * * * *
|
| +**
|
| +** Move the cursor P1 to a null row. Any OP_Column operations
|
| +** that occur while the cursor is on the null row will always
|
| +** write a NULL.
|
| +*/
|
| +case OP_NullRow: {
|
| + VdbeCursor *pC;
|
| +
|
| + assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
| + pC = p->apCsr[pOp->p1];
|
| + assert( pC!=0 );
|
| + pC->nullRow = 1;
|
| + pC->cacheStatus = CACHE_STALE;
|
| + if( pC->eCurType==CURTYPE_BTREE ){
|
| + assert( pC->uc.pCursor!=0 );
|
| + sqlite3BtreeClearCursor(pC->uc.pCursor);
|
| + }
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: Last P1 P2 P3 * *
|
| +**
|
| +** The next use of the Rowid or Column or Prev instruction for P1
|
| +** will refer to the last entry in the database table or index.
|
| +** If the table or index is empty and P2>0, then jump immediately to P2.
|
| +** If P2 is 0 or if the table or index is not empty, fall through
|
| +** to the following instruction.
|
| +**
|
| +** This opcode leaves the cursor configured to move in reverse order,
|
| +** from the end toward the beginning. In other words, the cursor is
|
| +** configured to use Prev, not Next.
|
| +*/
|
| +case OP_Last: { /* jump */
|
| + VdbeCursor *pC;
|
| + BtCursor *pCrsr;
|
| + int res;
|
| +
|
| + assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
| + pC = p->apCsr[pOp->p1];
|
| + assert( pC!=0 );
|
| + assert( pC->eCurType==CURTYPE_BTREE );
|
| + pCrsr = pC->uc.pCursor;
|
| + res = 0;
|
| + assert( pCrsr!=0 );
|
| + rc = sqlite3BtreeLast(pCrsr, &res);
|
| + pC->nullRow = (u8)res;
|
| + pC->deferredMoveto = 0;
|
| + pC->cacheStatus = CACHE_STALE;
|
| + pC->seekResult = pOp->p3;
|
| +#ifdef SQLITE_DEBUG
|
| + pC->seekOp = OP_Last;
|
| +#endif
|
| + if( pOp->p2>0 ){
|
| + VdbeBranchTaken(res!=0,2);
|
| + if( res ) goto jump_to_p2;
|
| + }
|
| + break;
|
| +}
|
| +
|
| +
|
| +/* Opcode: Sort P1 P2 * * *
|
| +**
|
| +** This opcode does exactly the same thing as OP_Rewind except that
|
| +** it increments an undocumented global variable used for testing.
|
| +**
|
| +** Sorting is accomplished by writing records into a sorting index,
|
| +** then rewinding that index and playing it back from beginning to
|
| +** end. We use the OP_Sort opcode instead of OP_Rewind to do the
|
| +** rewinding so that the global variable will be incremented and
|
| +** regression tests can determine whether or not the optimizer is
|
| +** correctly optimizing out sorts.
|
| +*/
|
| +case OP_SorterSort: /* jump */
|
| +case OP_Sort: { /* jump */
|
| +#ifdef SQLITE_TEST
|
| + sqlite3_sort_count++;
|
| + sqlite3_search_count--;
|
| +#endif
|
| + p->aCounter[SQLITE_STMTSTATUS_SORT]++;
|
| + /* Fall through into OP_Rewind */
|
| +}
|
| +/* Opcode: Rewind P1 P2 * * *
|
| +**
|
| +** The next use of the Rowid or Column or Next instruction for P1
|
| +** will refer to the first entry in the database table or index.
|
| +** If the table or index is empty, jump immediately to P2.
|
| +** If the table or index is not empty, fall through to the following
|
| +** instruction.
|
| +**
|
| +** This opcode leaves the cursor configured to move in forward order,
|
| +** from the beginning toward the end. In other words, the cursor is
|
| +** configured to use Next, not Prev.
|
| +*/
|
| +case OP_Rewind: { /* jump */
|
| + VdbeCursor *pC;
|
| + BtCursor *pCrsr;
|
| + int res;
|
| +
|
| + assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
| + pC = p->apCsr[pOp->p1];
|
| + assert( pC!=0 );
|
| + assert( isSorter(pC)==(pOp->opcode==OP_SorterSort) );
|
| + res = 1;
|
| +#ifdef SQLITE_DEBUG
|
| + pC->seekOp = OP_Rewind;
|
| +#endif
|
| + if( isSorter(pC) ){
|
| + rc = sqlite3VdbeSorterRewind(pC, &res);
|
| + }else{
|
| + assert( pC->eCurType==CURTYPE_BTREE );
|
| + pCrsr = pC->uc.pCursor;
|
| + assert( pCrsr );
|
| + rc = sqlite3BtreeFirst(pCrsr, &res);
|
| + pC->deferredMoveto = 0;
|
| + pC->cacheStatus = CACHE_STALE;
|
| + }
|
| + pC->nullRow = (u8)res;
|
| + assert( pOp->p2>0 && pOp->p2<p->nOp );
|
| + VdbeBranchTaken(res!=0,2);
|
| + if( res ) goto jump_to_p2;
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: Next P1 P2 P3 P4 P5
|
| +**
|
| +** Advance cursor P1 so that it points to the next key/data pair in its
|
| +** table or index. If there are no more key/value pairs then fall through
|
| +** to the following instruction. But if the cursor advance was successful,
|
| +** jump immediately to P2.
|
| +**
|
| +** The Next opcode is only valid following an SeekGT, SeekGE, or
|
| +** OP_Rewind opcode used to position the cursor. Next is not allowed
|
| +** to follow SeekLT, SeekLE, or OP_Last.
|
| +**
|
| +** The P1 cursor must be for a real table, not a pseudo-table. P1 must have
|
| +** been opened prior to this opcode or the program will segfault.
|
| +**
|
| +** The P3 value is a hint to the btree implementation. If P3==1, that
|
| +** means P1 is an SQL index and that this instruction could have been
|
| +** omitted if that index had been unique. P3 is usually 0. P3 is
|
| +** always either 0 or 1.
|
| +**
|
| +** P4 is always of type P4_ADVANCE. The function pointer points to
|
| +** sqlite3BtreeNext().
|
| +**
|
| +** If P5 is positive and the jump is taken, then event counter
|
| +** number P5-1 in the prepared statement is incremented.
|
| +**
|
| +** See also: Prev, NextIfOpen
|
| +*/
|
| +/* Opcode: NextIfOpen P1 P2 P3 P4 P5
|
| +**
|
| +** This opcode works just like Next except that if cursor P1 is not
|
| +** open it behaves a no-op.
|
| +*/
|
| +/* Opcode: Prev P1 P2 P3 P4 P5
|
| +**
|
| +** Back up cursor P1 so that it points to the previous key/data pair in its
|
| +** table or index. If there is no previous key/value pairs then fall through
|
| +** to the following instruction. But if the cursor backup was successful,
|
| +** jump immediately to P2.
|
| +**
|
| +**
|
| +** The Prev opcode is only valid following an SeekLT, SeekLE, or
|
| +** OP_Last opcode used to position the cursor. Prev is not allowed
|
| +** to follow SeekGT, SeekGE, or OP_Rewind.
|
| +**
|
| +** The P1 cursor must be for a real table, not a pseudo-table. If P1 is
|
| +** not open then the behavior is undefined.
|
| +**
|
| +** The P3 value is a hint to the btree implementation. If P3==1, that
|
| +** means P1 is an SQL index and that this instruction could have been
|
| +** omitted if that index had been unique. P3 is usually 0. P3 is
|
| +** always either 0 or 1.
|
| +**
|
| +** P4 is always of type P4_ADVANCE. The function pointer points to
|
| +** sqlite3BtreePrevious().
|
| +**
|
| +** If P5 is positive and the jump is taken, then event counter
|
| +** number P5-1 in the prepared statement is incremented.
|
| +*/
|
| +/* Opcode: PrevIfOpen P1 P2 P3 P4 P5
|
| +**
|
| +** This opcode works just like Prev except that if cursor P1 is not
|
| +** open it behaves a no-op.
|
| +*/
|
| +case OP_SorterNext: { /* jump */
|
| + VdbeCursor *pC;
|
| + int res;
|
| +
|
| + pC = p->apCsr[pOp->p1];
|
| + assert( isSorter(pC) );
|
| + res = 0;
|
| + rc = sqlite3VdbeSorterNext(db, pC, &res);
|
| + goto next_tail;
|
| +case OP_PrevIfOpen: /* jump */
|
| +case OP_NextIfOpen: /* jump */
|
| + if( p->apCsr[pOp->p1]==0 ) break;
|
| + /* Fall through */
|
| +case OP_Prev: /* jump */
|
| +case OP_Next: /* jump */
|
| + assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
| + assert( pOp->p5<ArraySize(p->aCounter) );
|
| + pC = p->apCsr[pOp->p1];
|
| + res = pOp->p3;
|
| + assert( pC!=0 );
|
| + assert( pC->deferredMoveto==0 );
|
| + assert( pC->eCurType==CURTYPE_BTREE );
|
| + assert( res==0 || (res==1 && pC->isTable==0) );
|
| + testcase( res==1 );
|
| + assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext );
|
| + assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious );
|
| + assert( pOp->opcode!=OP_NextIfOpen || pOp->p4.xAdvance==sqlite3BtreeNext );
|
| + assert( pOp->opcode!=OP_PrevIfOpen || pOp->p4.xAdvance==sqlite3BtreePrevious);
|
| +
|
| + /* The Next opcode is only used after SeekGT, SeekGE, and Rewind.
|
| + ** The Prev opcode is only used after SeekLT, SeekLE, and Last. */
|
| + assert( pOp->opcode!=OP_Next || pOp->opcode!=OP_NextIfOpen
|
| + || pC->seekOp==OP_SeekGT || pC->seekOp==OP_SeekGE
|
| + || pC->seekOp==OP_Rewind || pC->seekOp==OP_Found);
|
| + assert( pOp->opcode!=OP_Prev || pOp->opcode!=OP_PrevIfOpen
|
| + || pC->seekOp==OP_SeekLT || pC->seekOp==OP_SeekLE
|
| + || pC->seekOp==OP_Last );
|
| +
|
| + rc = pOp->p4.xAdvance(pC->uc.pCursor, &res);
|
| +next_tail:
|
| + pC->cacheStatus = CACHE_STALE;
|
| + VdbeBranchTaken(res==0,2);
|
| + if( res==0 ){
|
| + pC->nullRow = 0;
|
| + p->aCounter[pOp->p5]++;
|
| +#ifdef SQLITE_TEST
|
| + sqlite3_search_count++;
|
| +#endif
|
| + goto jump_to_p2_and_check_for_interrupt;
|
| + }else{
|
| + pC->nullRow = 1;
|
| + }
|
| + goto check_for_interrupt;
|
| +}
|
| +
|
| +/* Opcode: IdxInsert P1 P2 P3 * P5
|
| +** Synopsis: key=r[P2]
|
| +**
|
| +** Register P2 holds an SQL index key made using the
|
| +** MakeRecord instructions. This opcode writes that key
|
| +** into the index P1. Data for the entry is nil.
|
| +**
|
| +** P3 is a flag that provides a hint to the b-tree layer that this
|
| +** insert is likely to be an append.
|
| +**
|
| +** If P5 has the OPFLAG_NCHANGE bit set, then the change counter is
|
| +** incremented by this instruction. If the OPFLAG_NCHANGE bit is clear,
|
| +** then the change counter is unchanged.
|
| +**
|
| +** If P5 has the OPFLAG_USESEEKRESULT bit set, then the cursor must have
|
| +** just done a seek to the spot where the new entry is to be inserted.
|
| +** This flag avoids doing an extra seek.
|
| +**
|
| +** This instruction only works for indices. The equivalent instruction
|
| +** for tables is OP_Insert.
|
| +*/
|
| +case OP_SorterInsert: /* in2 */
|
| +case OP_IdxInsert: { /* in2 */
|
| + VdbeCursor *pC;
|
| + int nKey;
|
| + const char *zKey;
|
| +
|
| + assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
| + pC = p->apCsr[pOp->p1];
|
| + assert( pC!=0 );
|
| + assert( isSorter(pC)==(pOp->opcode==OP_SorterInsert) );
|
| + pIn2 = &aMem[pOp->p2];
|
| + assert( pIn2->flags & MEM_Blob );
|
| + if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
|
| + assert( pC->eCurType==CURTYPE_BTREE || pOp->opcode==OP_SorterInsert );
|
| + assert( pC->isTable==0 );
|
| + rc = ExpandBlob(pIn2);
|
| + if( rc==SQLITE_OK ){
|
| + if( pOp->opcode==OP_SorterInsert ){
|
| + rc = sqlite3VdbeSorterWrite(pC, pIn2);
|
| + }else{
|
| + nKey = pIn2->n;
|
| + zKey = pIn2->z;
|
| + rc = sqlite3BtreeInsert(pC->uc.pCursor, zKey, nKey, "", 0, 0, pOp->p3,
|
| + ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0)
|
| + );
|
| + assert( pC->deferredMoveto==0 );
|
| + pC->cacheStatus = CACHE_STALE;
|
| + }
|
| + }
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: IdxDelete P1 P2 P3 * *
|
| +** Synopsis: key=r[P2@P3]
|
| +**
|
| +** The content of P3 registers starting at register P2 form
|
| +** an unpacked index key. This opcode removes that entry from the
|
| +** index opened by cursor P1.
|
| +*/
|
| +case OP_IdxDelete: {
|
| + VdbeCursor *pC;
|
| + BtCursor *pCrsr;
|
| + int res;
|
| + UnpackedRecord r;
|
| +
|
| + assert( pOp->p3>0 );
|
| + assert( pOp->p2>0 && pOp->p2+pOp->p3<=(p->nMem-p->nCursor)+1 );
|
| + assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
| + pC = p->apCsr[pOp->p1];
|
| + assert( pC!=0 );
|
| + assert( pC->eCurType==CURTYPE_BTREE );
|
| + pCrsr = pC->uc.pCursor;
|
| + assert( pCrsr!=0 );
|
| + assert( pOp->p5==0 );
|
| + r.pKeyInfo = pC->pKeyInfo;
|
| + r.nField = (u16)pOp->p3;
|
| + r.default_rc = 0;
|
| + r.aMem = &aMem[pOp->p2];
|
| +#ifdef SQLITE_DEBUG
|
| + { int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
|
| +#endif
|
| + rc = sqlite3BtreeMovetoUnpacked(pCrsr, &r, 0, 0, &res);
|
| + if( rc==SQLITE_OK && res==0 ){
|
| + rc = sqlite3BtreeDelete(pCrsr, 0);
|
| + }
|
| + assert( pC->deferredMoveto==0 );
|
| + pC->cacheStatus = CACHE_STALE;
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: IdxRowid P1 P2 * * *
|
| +** Synopsis: r[P2]=rowid
|
| +**
|
| +** Write into register P2 an integer which is the last entry in the record at
|
| +** the end of the index key pointed to by cursor P1. This integer should be
|
| +** the rowid of the table entry to which this index entry points.
|
| +**
|
| +** See also: Rowid, MakeRecord.
|
| +*/
|
| +case OP_IdxRowid: { /* out2 */
|
| + BtCursor *pCrsr;
|
| + VdbeCursor *pC;
|
| + i64 rowid;
|
| +
|
| + pOut = out2Prerelease(p, pOp);
|
| + assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
| + pC = p->apCsr[pOp->p1];
|
| + assert( pC!=0 );
|
| + assert( pC->eCurType==CURTYPE_BTREE );
|
| + pCrsr = pC->uc.pCursor;
|
| + assert( pCrsr!=0 );
|
| + pOut->flags = MEM_Null;
|
| + assert( pC->isTable==0 );
|
| + assert( pC->deferredMoveto==0 );
|
| +
|
| + /* sqlite3VbeCursorRestore() can only fail if the record has been deleted
|
| + ** out from under the cursor. That will never happend for an IdxRowid
|
| + ** opcode, hence the NEVER() arround the check of the return value.
|
| + */
|
| + rc = sqlite3VdbeCursorRestore(pC);
|
| + if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error;
|
| +
|
| + if( !pC->nullRow ){
|
| + rowid = 0; /* Not needed. Only used to silence a warning. */
|
| + rc = sqlite3VdbeIdxRowid(db, pCrsr, &rowid);
|
| + if( rc!=SQLITE_OK ){
|
| + goto abort_due_to_error;
|
| + }
|
| + pOut->u.i = rowid;
|
| + pOut->flags = MEM_Int;
|
| + }
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: IdxGE P1 P2 P3 P4 P5
|
| +** Synopsis: key=r[P3@P4]
|
| +**
|
| +** The P4 register values beginning with P3 form an unpacked index
|
| +** key that omits the PRIMARY KEY. Compare this key value against the index
|
| +** that P1 is currently pointing to, ignoring the PRIMARY KEY or ROWID
|
| +** fields at the end.
|
| +**
|
| +** If the P1 index entry is greater than or equal to the key value
|
| +** then jump to P2. Otherwise fall through to the next instruction.
|
| +*/
|
| +/* Opcode: IdxGT P1 P2 P3 P4 P5
|
| +** Synopsis: key=r[P3@P4]
|
| +**
|
| +** The P4 register values beginning with P3 form an unpacked index
|
| +** key that omits the PRIMARY KEY. Compare this key value against the index
|
| +** that P1 is currently pointing to, ignoring the PRIMARY KEY or ROWID
|
| +** fields at the end.
|
| +**
|
| +** If the P1 index entry is greater than the key value
|
| +** then jump to P2. Otherwise fall through to the next instruction.
|
| +*/
|
| +/* Opcode: IdxLT P1 P2 P3 P4 P5
|
| +** Synopsis: key=r[P3@P4]
|
| +**
|
| +** The P4 register values beginning with P3 form an unpacked index
|
| +** key that omits the PRIMARY KEY or ROWID. Compare this key value against
|
| +** the index that P1 is currently pointing to, ignoring the PRIMARY KEY or
|
| +** ROWID on the P1 index.
|
| +**
|
| +** If the P1 index entry is less than the key value then jump to P2.
|
| +** Otherwise fall through to the next instruction.
|
| +*/
|
| +/* Opcode: IdxLE P1 P2 P3 P4 P5
|
| +** Synopsis: key=r[P3@P4]
|
| +**
|
| +** The P4 register values beginning with P3 form an unpacked index
|
| +** key that omits the PRIMARY KEY or ROWID. Compare this key value against
|
| +** the index that P1 is currently pointing to, ignoring the PRIMARY KEY or
|
| +** ROWID on the P1 index.
|
| +**
|
| +** If the P1 index entry is less than or equal to the key value then jump
|
| +** to P2. Otherwise fall through to the next instruction.
|
| +*/
|
| +case OP_IdxLE: /* jump */
|
| +case OP_IdxGT: /* jump */
|
| +case OP_IdxLT: /* jump */
|
| +case OP_IdxGE: { /* jump */
|
| + VdbeCursor *pC;
|
| + int res;
|
| + UnpackedRecord r;
|
| +
|
| + assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
| + pC = p->apCsr[pOp->p1];
|
| + assert( pC!=0 );
|
| + assert( pC->isOrdered );
|
| + assert( pC->eCurType==CURTYPE_BTREE );
|
| + assert( pC->uc.pCursor!=0);
|
| + assert( pC->deferredMoveto==0 );
|
| + assert( pOp->p5==0 || pOp->p5==1 );
|
| + assert( pOp->p4type==P4_INT32 );
|
| + r.pKeyInfo = pC->pKeyInfo;
|
| + r.nField = (u16)pOp->p4.i;
|
| + if( pOp->opcode<OP_IdxLT ){
|
| + assert( pOp->opcode==OP_IdxLE || pOp->opcode==OP_IdxGT );
|
| + r.default_rc = -1;
|
| + }else{
|
| + assert( pOp->opcode==OP_IdxGE || pOp->opcode==OP_IdxLT );
|
| + r.default_rc = 0;
|
| + }
|
| + r.aMem = &aMem[pOp->p3];
|
| +#ifdef SQLITE_DEBUG
|
| + { int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
|
| +#endif
|
| + res = 0; /* Not needed. Only used to silence a warning. */
|
| + rc = sqlite3VdbeIdxKeyCompare(db, pC, &r, &res);
|
| + assert( (OP_IdxLE&1)==(OP_IdxLT&1) && (OP_IdxGE&1)==(OP_IdxGT&1) );
|
| + if( (pOp->opcode&1)==(OP_IdxLT&1) ){
|
| + assert( pOp->opcode==OP_IdxLE || pOp->opcode==OP_IdxLT );
|
| + res = -res;
|
| + }else{
|
| + assert( pOp->opcode==OP_IdxGE || pOp->opcode==OP_IdxGT );
|
| + res++;
|
| + }
|
| + VdbeBranchTaken(res>0,2);
|
| + if( res>0 ) goto jump_to_p2;
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: Destroy P1 P2 P3 * *
|
| +**
|
| +** Delete an entire database table or index whose root page in the database
|
| +** file is given by P1.
|
| +**
|
| +** The table being destroyed is in the main database file if P3==0. If
|
| +** P3==1 then the table to be clear is in the auxiliary database file
|
| +** that is used to store tables create using CREATE TEMPORARY TABLE.
|
| +**
|
| +** If AUTOVACUUM is enabled then it is possible that another root page
|
| +** might be moved into the newly deleted root page in order to keep all
|
| +** root pages contiguous at the beginning of the database. The former
|
| +** value of the root page that moved - its value before the move occurred -
|
| +** is stored in register P2. If no page
|
| +** movement was required (because the table being dropped was already
|
| +** the last one in the database) then a zero is stored in register P2.
|
| +** If AUTOVACUUM is disabled then a zero is stored in register P2.
|
| +**
|
| +** See also: Clear
|
| +*/
|
| +case OP_Destroy: { /* out2 */
|
| + int iMoved;
|
| + int iDb;
|
| +
|
| + assert( p->readOnly==0 );
|
| + pOut = out2Prerelease(p, pOp);
|
| + pOut->flags = MEM_Null;
|
| + if( db->nVdbeRead > db->nVDestroy+1 ){
|
| + rc = SQLITE_LOCKED;
|
| + p->errorAction = OE_Abort;
|
| + }else{
|
| + iDb = pOp->p3;
|
| + assert( DbMaskTest(p->btreeMask, iDb) );
|
| + iMoved = 0; /* Not needed. Only to silence a warning. */
|
| + rc = sqlite3BtreeDropTable(db->aDb[iDb].pBt, pOp->p1, &iMoved);
|
| + pOut->flags = MEM_Int;
|
| + pOut->u.i = iMoved;
|
| +#ifndef SQLITE_OMIT_AUTOVACUUM
|
| + if( rc==SQLITE_OK && iMoved!=0 ){
|
| + sqlite3RootPageMoved(db, iDb, iMoved, pOp->p1);
|
| + /* All OP_Destroy operations occur on the same btree */
|
| + assert( resetSchemaOnFault==0 || resetSchemaOnFault==iDb+1 );
|
| + resetSchemaOnFault = iDb+1;
|
| + }
|
| +#endif
|
| + }
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: Clear P1 P2 P3
|
| +**
|
| +** Delete all contents of the database table or index whose root page
|
| +** in the database file is given by P1. But, unlike Destroy, do not
|
| +** remove the table or index from the database file.
|
| +**
|
| +** The table being clear is in the main database file if P2==0. If
|
| +** P2==1 then the table to be clear is in the auxiliary database file
|
| +** that is used to store tables create using CREATE TEMPORARY TABLE.
|
| +**
|
| +** If the P3 value is non-zero, then the table referred to must be an
|
| +** intkey table (an SQL table, not an index). In this case the row change
|
| +** count is incremented by the number of rows in the table being cleared.
|
| +** If P3 is greater than zero, then the value stored in register P3 is
|
| +** also incremented by the number of rows in the table being cleared.
|
| +**
|
| +** See also: Destroy
|
| +*/
|
| +case OP_Clear: {
|
| + int nChange;
|
| +
|
| + nChange = 0;
|
| + assert( p->readOnly==0 );
|
| + assert( DbMaskTest(p->btreeMask, pOp->p2) );
|
| + rc = sqlite3BtreeClearTable(
|
| + db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &nChange : 0)
|
| + );
|
| + if( pOp->p3 ){
|
| + p->nChange += nChange;
|
| + if( pOp->p3>0 ){
|
| + assert( memIsValid(&aMem[pOp->p3]) );
|
| + memAboutToChange(p, &aMem[pOp->p3]);
|
| + aMem[pOp->p3].u.i += nChange;
|
| + }
|
| + }
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: ResetSorter P1 * * * *
|
| +**
|
| +** Delete all contents from the ephemeral table or sorter
|
| +** that is open on cursor P1.
|
| +**
|
| +** This opcode only works for cursors used for sorting and
|
| +** opened with OP_OpenEphemeral or OP_SorterOpen.
|
| +*/
|
| +case OP_ResetSorter: {
|
| + VdbeCursor *pC;
|
| +
|
| + assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
| + pC = p->apCsr[pOp->p1];
|
| + assert( pC!=0 );
|
| + if( isSorter(pC) ){
|
| + sqlite3VdbeSorterReset(db, pC->uc.pSorter);
|
| + }else{
|
| + assert( pC->eCurType==CURTYPE_BTREE );
|
| + assert( pC->isEphemeral );
|
| + rc = sqlite3BtreeClearTableOfCursor(pC->uc.pCursor);
|
| + }
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: CreateTable P1 P2 * * *
|
| +** Synopsis: r[P2]=root iDb=P1
|
| +**
|
| +** Allocate a new table in the main database file if P1==0 or in the
|
| +** auxiliary database file if P1==1 or in an attached database if
|
| +** P1>1. Write the root page number of the new table into
|
| +** register P2
|
| +**
|
| +** The difference between a table and an index is this: A table must
|
| +** have a 4-byte integer key and can have arbitrary data. An index
|
| +** has an arbitrary key but no data.
|
| +**
|
| +** See also: CreateIndex
|
| +*/
|
| +/* Opcode: CreateIndex P1 P2 * * *
|
| +** Synopsis: r[P2]=root iDb=P1
|
| +**
|
| +** Allocate a new index in the main database file if P1==0 or in the
|
| +** auxiliary database file if P1==1 or in an attached database if
|
| +** P1>1. Write the root page number of the new table into
|
| +** register P2.
|
| +**
|
| +** See documentation on OP_CreateTable for additional information.
|
| +*/
|
| +case OP_CreateIndex: /* out2 */
|
| +case OP_CreateTable: { /* out2 */
|
| + int pgno;
|
| + int flags;
|
| + Db *pDb;
|
| +
|
| + pOut = out2Prerelease(p, pOp);
|
| + pgno = 0;
|
| + assert( pOp->p1>=0 && pOp->p1<db->nDb );
|
| + assert( DbMaskTest(p->btreeMask, pOp->p1) );
|
| + assert( p->readOnly==0 );
|
| + pDb = &db->aDb[pOp->p1];
|
| + assert( pDb->pBt!=0 );
|
| + if( pOp->opcode==OP_CreateTable ){
|
| + /* flags = BTREE_INTKEY; */
|
| + flags = BTREE_INTKEY;
|
| + }else{
|
| + flags = BTREE_BLOBKEY;
|
| + }
|
| + rc = sqlite3BtreeCreateTable(pDb->pBt, &pgno, flags);
|
| + pOut->u.i = pgno;
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: ParseSchema P1 * * P4 *
|
| +**
|
| +** Read and parse all entries from the SQLITE_MASTER table of database P1
|
| +** that match the WHERE clause P4.
|
| +**
|
| +** This opcode invokes the parser to create a new virtual machine,
|
| +** then runs the new virtual machine. It is thus a re-entrant opcode.
|
| +*/
|
| +case OP_ParseSchema: {
|
| + int iDb;
|
| + const char *zMaster;
|
| + char *zSql;
|
| + InitData initData;
|
| +
|
| + /* Any prepared statement that invokes this opcode will hold mutexes
|
| + ** on every btree. This is a prerequisite for invoking
|
| + ** sqlite3InitCallback().
|
| + */
|
| +#ifdef SQLITE_DEBUG
|
| + for(iDb=0; iDb<db->nDb; iDb++){
|
| + assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) );
|
| + }
|
| +#endif
|
| +
|
| + iDb = pOp->p1;
|
| + assert( iDb>=0 && iDb<db->nDb );
|
| + assert( DbHasProperty(db, iDb, DB_SchemaLoaded) );
|
| + /* Used to be a conditional */ {
|
| + zMaster = SCHEMA_TABLE(iDb);
|
| + initData.db = db;
|
| + initData.iDb = pOp->p1;
|
| + initData.pzErrMsg = &p->zErrMsg;
|
| + zSql = sqlite3MPrintf(db,
|
| + "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid",
|
| + db->aDb[iDb].zName, zMaster, pOp->p4.z);
|
| + if( zSql==0 ){
|
| + rc = SQLITE_NOMEM;
|
| + }else{
|
| + assert( db->init.busy==0 );
|
| + db->init.busy = 1;
|
| + initData.rc = SQLITE_OK;
|
| + assert( !db->mallocFailed );
|
| + rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0);
|
| + if( rc==SQLITE_OK ) rc = initData.rc;
|
| + sqlite3DbFree(db, zSql);
|
| + db->init.busy = 0;
|
| + }
|
| + }
|
| + if( rc ) sqlite3ResetAllSchemasOfConnection(db);
|
| + if( rc==SQLITE_NOMEM ){
|
| + goto no_mem;
|
| + }
|
| + break;
|
| +}
|
| +
|
| +#if !defined(SQLITE_OMIT_ANALYZE)
|
| +/* Opcode: LoadAnalysis P1 * * * *
|
| +**
|
| +** Read the sqlite_stat1 table for database P1 and load the content
|
| +** of that table into the internal index hash table. This will cause
|
| +** the analysis to be used when preparing all subsequent queries.
|
| +*/
|
| +case OP_LoadAnalysis: {
|
| + assert( pOp->p1>=0 && pOp->p1<db->nDb );
|
| + rc = sqlite3AnalysisLoad(db, pOp->p1);
|
| + break;
|
| +}
|
| +#endif /* !defined(SQLITE_OMIT_ANALYZE) */
|
| +
|
| +/* Opcode: DropTable P1 * * P4 *
|
| +**
|
| +** Remove the internal (in-memory) data structures that describe
|
| +** the table named P4 in database P1. This is called after a table
|
| +** is dropped from disk (using the Destroy opcode) in order to keep
|
| +** the internal representation of the
|
| +** schema consistent with what is on disk.
|
| +*/
|
| +case OP_DropTable: {
|
| + sqlite3UnlinkAndDeleteTable(db, pOp->p1, pOp->p4.z);
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: DropIndex P1 * * P4 *
|
| +**
|
| +** Remove the internal (in-memory) data structures that describe
|
| +** the index named P4 in database P1. This is called after an index
|
| +** is dropped from disk (using the Destroy opcode)
|
| +** in order to keep the internal representation of the
|
| +** schema consistent with what is on disk.
|
| +*/
|
| +case OP_DropIndex: {
|
| + sqlite3UnlinkAndDeleteIndex(db, pOp->p1, pOp->p4.z);
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: DropTrigger P1 * * P4 *
|
| +**
|
| +** Remove the internal (in-memory) data structures that describe
|
| +** the trigger named P4 in database P1. This is called after a trigger
|
| +** is dropped from disk (using the Destroy opcode) in order to keep
|
| +** the internal representation of the
|
| +** schema consistent with what is on disk.
|
| +*/
|
| +case OP_DropTrigger: {
|
| + sqlite3UnlinkAndDeleteTrigger(db, pOp->p1, pOp->p4.z);
|
| + break;
|
| +}
|
| +
|
| +
|
| +#ifndef SQLITE_OMIT_INTEGRITY_CHECK
|
| +/* Opcode: IntegrityCk P1 P2 P3 * P5
|
| +**
|
| +** Do an analysis of the currently open database. Store in
|
| +** register P1 the text of an error message describing any problems.
|
| +** If no problems are found, store a NULL in register P1.
|
| +**
|
| +** The register P3 contains the maximum number of allowed errors.
|
| +** At most reg(P3) errors will be reported.
|
| +** In other words, the analysis stops as soon as reg(P1) errors are
|
| +** seen. Reg(P1) is updated with the number of errors remaining.
|
| +**
|
| +** The root page numbers of all tables in the database are integer
|
| +** stored in reg(P1), reg(P1+1), reg(P1+2), .... There are P2 tables
|
| +** total.
|
| +**
|
| +** If P5 is not zero, the check is done on the auxiliary database
|
| +** file, not the main database file.
|
| +**
|
| +** This opcode is used to implement the integrity_check pragma.
|
| +*/
|
| +case OP_IntegrityCk: {
|
| + int nRoot; /* Number of tables to check. (Number of root pages.) */
|
| + int *aRoot; /* Array of rootpage numbers for tables to be checked */
|
| + int j; /* Loop counter */
|
| + int nErr; /* Number of errors reported */
|
| + char *z; /* Text of the error report */
|
| + Mem *pnErr; /* Register keeping track of errors remaining */
|
| +
|
| + assert( p->bIsReader );
|
| + nRoot = pOp->p2;
|
| + assert( nRoot>0 );
|
| + aRoot = sqlite3DbMallocRaw(db, sizeof(int)*(nRoot+1) );
|
| + if( aRoot==0 ) goto no_mem;
|
| + assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
|
| + pnErr = &aMem[pOp->p3];
|
| + assert( (pnErr->flags & MEM_Int)!=0 );
|
| + assert( (pnErr->flags & (MEM_Str|MEM_Blob))==0 );
|
| + pIn1 = &aMem[pOp->p1];
|
| + for(j=0; j<nRoot; j++){
|
| + aRoot[j] = (int)sqlite3VdbeIntValue(&pIn1[j]);
|
| + }
|
| + aRoot[j] = 0;
|
| + assert( pOp->p5<db->nDb );
|
| + assert( DbMaskTest(p->btreeMask, pOp->p5) );
|
| + z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, aRoot, nRoot,
|
| + (int)pnErr->u.i, &nErr);
|
| + sqlite3DbFree(db, aRoot);
|
| + pnErr->u.i -= nErr;
|
| + sqlite3VdbeMemSetNull(pIn1);
|
| + if( nErr==0 ){
|
| + assert( z==0 );
|
| + }else if( z==0 ){
|
| + goto no_mem;
|
| + }else{
|
| + sqlite3VdbeMemSetStr(pIn1, z, -1, SQLITE_UTF8, sqlite3_free);
|
| + }
|
| + UPDATE_MAX_BLOBSIZE(pIn1);
|
| + sqlite3VdbeChangeEncoding(pIn1, encoding);
|
| + break;
|
| +}
|
| +#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
|
| +
|
| +/* Opcode: RowSetAdd P1 P2 * * *
|
| +** Synopsis: rowset(P1)=r[P2]
|
| +**
|
| +** Insert the integer value held by register P2 into a boolean index
|
| +** held in register P1.
|
| +**
|
| +** An assertion fails if P2 is not an integer.
|
| +*/
|
| +case OP_RowSetAdd: { /* in1, in2 */
|
| + pIn1 = &aMem[pOp->p1];
|
| + pIn2 = &aMem[pOp->p2];
|
| + assert( (pIn2->flags & MEM_Int)!=0 );
|
| + if( (pIn1->flags & MEM_RowSet)==0 ){
|
| + sqlite3VdbeMemSetRowSet(pIn1);
|
| + if( (pIn1->flags & MEM_RowSet)==0 ) goto no_mem;
|
| + }
|
| + sqlite3RowSetInsert(pIn1->u.pRowSet, pIn2->u.i);
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: RowSetRead P1 P2 P3 * *
|
| +** Synopsis: r[P3]=rowset(P1)
|
| +**
|
| +** Extract the smallest value from boolean index P1 and put that value into
|
| +** register P3. Or, if boolean index P1 is initially empty, leave P3
|
| +** unchanged and jump to instruction P2.
|
| +*/
|
| +case OP_RowSetRead: { /* jump, in1, out3 */
|
| + i64 val;
|
| +
|
| + pIn1 = &aMem[pOp->p1];
|
| + if( (pIn1->flags & MEM_RowSet)==0
|
| + || sqlite3RowSetNext(pIn1->u.pRowSet, &val)==0
|
| + ){
|
| + /* The boolean index is empty */
|
| + sqlite3VdbeMemSetNull(pIn1);
|
| + VdbeBranchTaken(1,2);
|
| + goto jump_to_p2_and_check_for_interrupt;
|
| + }else{
|
| + /* A value was pulled from the index */
|
| + VdbeBranchTaken(0,2);
|
| + sqlite3VdbeMemSetInt64(&aMem[pOp->p3], val);
|
| + }
|
| + goto check_for_interrupt;
|
| +}
|
| +
|
| +/* Opcode: RowSetTest P1 P2 P3 P4
|
| +** Synopsis: if r[P3] in rowset(P1) goto P2
|
| +**
|
| +** Register P3 is assumed to hold a 64-bit integer value. If register P1
|
| +** contains a RowSet object and that RowSet object contains
|
| +** the value held in P3, jump to register P2. Otherwise, insert the
|
| +** integer in P3 into the RowSet and continue on to the
|
| +** next opcode.
|
| +**
|
| +** The RowSet object is optimized for the case where successive sets
|
| +** of integers, where each set contains no duplicates. Each set
|
| +** of values is identified by a unique P4 value. The first set
|
| +** must have P4==0, the final set P4=-1. P4 must be either -1 or
|
| +** non-negative. For non-negative values of P4 only the lower 4
|
| +** bits are significant.
|
| +**
|
| +** This allows optimizations: (a) when P4==0 there is no need to test
|
| +** the rowset object for P3, as it is guaranteed not to contain it,
|
| +** (b) when P4==-1 there is no need to insert the value, as it will
|
| +** never be tested for, and (c) when a value that is part of set X is
|
| +** inserted, there is no need to search to see if the same value was
|
| +** previously inserted as part of set X (only if it was previously
|
| +** inserted as part of some other set).
|
| +*/
|
| +case OP_RowSetTest: { /* jump, in1, in3 */
|
| + int iSet;
|
| + int exists;
|
| +
|
| + pIn1 = &aMem[pOp->p1];
|
| + pIn3 = &aMem[pOp->p3];
|
| + iSet = pOp->p4.i;
|
| + assert( pIn3->flags&MEM_Int );
|
| +
|
| + /* If there is anything other than a rowset object in memory cell P1,
|
| + ** delete it now and initialize P1 with an empty rowset
|
| + */
|
| + if( (pIn1->flags & MEM_RowSet)==0 ){
|
| + sqlite3VdbeMemSetRowSet(pIn1);
|
| + if( (pIn1->flags & MEM_RowSet)==0 ) goto no_mem;
|
| + }
|
| +
|
| + assert( pOp->p4type==P4_INT32 );
|
| + assert( iSet==-1 || iSet>=0 );
|
| + if( iSet ){
|
| + exists = sqlite3RowSetTest(pIn1->u.pRowSet, iSet, pIn3->u.i);
|
| + VdbeBranchTaken(exists!=0,2);
|
| + if( exists ) goto jump_to_p2;
|
| + }
|
| + if( iSet>=0 ){
|
| + sqlite3RowSetInsert(pIn1->u.pRowSet, pIn3->u.i);
|
| + }
|
| + break;
|
| +}
|
| +
|
| +
|
| +#ifndef SQLITE_OMIT_TRIGGER
|
| +
|
| +/* Opcode: Program P1 P2 P3 P4 P5
|
| +**
|
| +** Execute the trigger program passed as P4 (type P4_SUBPROGRAM).
|
| +**
|
| +** P1 contains the address of the memory cell that contains the first memory
|
| +** cell in an array of values used as arguments to the sub-program. P2
|
| +** contains the address to jump to if the sub-program throws an IGNORE
|
| +** exception using the RAISE() function. Register P3 contains the address
|
| +** of a memory cell in this (the parent) VM that is used to allocate the
|
| +** memory required by the sub-vdbe at runtime.
|
| +**
|
| +** P4 is a pointer to the VM containing the trigger program.
|
| +**
|
| +** If P5 is non-zero, then recursive program invocation is enabled.
|
| +*/
|
| +case OP_Program: { /* jump */
|
| + int nMem; /* Number of memory registers for sub-program */
|
| + int nByte; /* Bytes of runtime space required for sub-program */
|
| + Mem *pRt; /* Register to allocate runtime space */
|
| + Mem *pMem; /* Used to iterate through memory cells */
|
| + Mem *pEnd; /* Last memory cell in new array */
|
| + VdbeFrame *pFrame; /* New vdbe frame to execute in */
|
| + SubProgram *pProgram; /* Sub-program to execute */
|
| + void *t; /* Token identifying trigger */
|
| +
|
| + pProgram = pOp->p4.pProgram;
|
| + pRt = &aMem[pOp->p3];
|
| + assert( pProgram->nOp>0 );
|
| +
|
| + /* If the p5 flag is clear, then recursive invocation of triggers is
|
| + ** disabled for backwards compatibility (p5 is set if this sub-program
|
| + ** is really a trigger, not a foreign key action, and the flag set
|
| + ** and cleared by the "PRAGMA recursive_triggers" command is clear).
|
| + **
|
| + ** It is recursive invocation of triggers, at the SQL level, that is
|
| + ** disabled. In some cases a single trigger may generate more than one
|
| + ** SubProgram (if the trigger may be executed with more than one different
|
| + ** ON CONFLICT algorithm). SubProgram structures associated with a
|
| + ** single trigger all have the same value for the SubProgram.token
|
| + ** variable. */
|
| + if( pOp->p5 ){
|
| + t = pProgram->token;
|
| + for(pFrame=p->pFrame; pFrame && pFrame->token!=t; pFrame=pFrame->pParent);
|
| + if( pFrame ) break;
|
| + }
|
| +
|
| + if( p->nFrame>=db->aLimit[SQLITE_LIMIT_TRIGGER_DEPTH] ){
|
| + rc = SQLITE_ERROR;
|
| + sqlite3VdbeError(p, "too many levels of trigger recursion");
|
| + break;
|
| + }
|
| +
|
| + /* Register pRt is used to store the memory required to save the state
|
| + ** of the current program, and the memory required at runtime to execute
|
| + ** the trigger program. If this trigger has been fired before, then pRt
|
| + ** is already allocated. Otherwise, it must be initialized. */
|
| + if( (pRt->flags&MEM_Frame)==0 ){
|
| + /* SubProgram.nMem is set to the number of memory cells used by the
|
| + ** program stored in SubProgram.aOp. As well as these, one memory
|
| + ** cell is required for each cursor used by the program. Set local
|
| + ** variable nMem (and later, VdbeFrame.nChildMem) to this value.
|
| + */
|
| + nMem = pProgram->nMem + pProgram->nCsr;
|
| + nByte = ROUND8(sizeof(VdbeFrame))
|
| + + nMem * sizeof(Mem)
|
| + + pProgram->nCsr * sizeof(VdbeCursor *)
|
| + + pProgram->nOnce * sizeof(u8);
|
| + pFrame = sqlite3DbMallocZero(db, nByte);
|
| + if( !pFrame ){
|
| + goto no_mem;
|
| + }
|
| + sqlite3VdbeMemRelease(pRt);
|
| + pRt->flags = MEM_Frame;
|
| + pRt->u.pFrame = pFrame;
|
| +
|
| + pFrame->v = p;
|
| + pFrame->nChildMem = nMem;
|
| + pFrame->nChildCsr = pProgram->nCsr;
|
| + pFrame->pc = (int)(pOp - aOp);
|
| + pFrame->aMem = p->aMem;
|
| + pFrame->nMem = p->nMem;
|
| + pFrame->apCsr = p->apCsr;
|
| + pFrame->nCursor = p->nCursor;
|
| + pFrame->aOp = p->aOp;
|
| + pFrame->nOp = p->nOp;
|
| + pFrame->token = pProgram->token;
|
| + pFrame->aOnceFlag = p->aOnceFlag;
|
| + pFrame->nOnceFlag = p->nOnceFlag;
|
| +#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
| + pFrame->anExec = p->anExec;
|
| +#endif
|
| +
|
| + pEnd = &VdbeFrameMem(pFrame)[pFrame->nChildMem];
|
| + for(pMem=VdbeFrameMem(pFrame); pMem!=pEnd; pMem++){
|
| + pMem->flags = MEM_Undefined;
|
| + pMem->db = db;
|
| + }
|
| + }else{
|
| + pFrame = pRt->u.pFrame;
|
| + assert( pProgram->nMem+pProgram->nCsr==pFrame->nChildMem );
|
| + assert( pProgram->nCsr==pFrame->nChildCsr );
|
| + assert( (int)(pOp - aOp)==pFrame->pc );
|
| + }
|
| +
|
| + p->nFrame++;
|
| + pFrame->pParent = p->pFrame;
|
| + pFrame->lastRowid = lastRowid;
|
| + pFrame->nChange = p->nChange;
|
| + pFrame->nDbChange = p->db->nChange;
|
| + p->nChange = 0;
|
| + p->pFrame = pFrame;
|
| + p->aMem = aMem = &VdbeFrameMem(pFrame)[-1];
|
| + p->nMem = pFrame->nChildMem;
|
| + p->nCursor = (u16)pFrame->nChildCsr;
|
| + p->apCsr = (VdbeCursor **)&aMem[p->nMem+1];
|
| + p->aOp = aOp = pProgram->aOp;
|
| + p->nOp = pProgram->nOp;
|
| + p->aOnceFlag = (u8 *)&p->apCsr[p->nCursor];
|
| + p->nOnceFlag = pProgram->nOnce;
|
| +#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
| + p->anExec = 0;
|
| +#endif
|
| + pOp = &aOp[-1];
|
| + memset(p->aOnceFlag, 0, p->nOnceFlag);
|
| +
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: Param P1 P2 * * *
|
| +**
|
| +** This opcode is only ever present in sub-programs called via the
|
| +** OP_Program instruction. Copy a value currently stored in a memory
|
| +** cell of the calling (parent) frame to cell P2 in the current frames
|
| +** address space. This is used by trigger programs to access the new.*
|
| +** and old.* values.
|
| +**
|
| +** The address of the cell in the parent frame is determined by adding
|
| +** the value of the P1 argument to the value of the P1 argument to the
|
| +** calling OP_Program instruction.
|
| +*/
|
| +case OP_Param: { /* out2 */
|
| + VdbeFrame *pFrame;
|
| + Mem *pIn;
|
| + pOut = out2Prerelease(p, pOp);
|
| + pFrame = p->pFrame;
|
| + pIn = &pFrame->aMem[pOp->p1 + pFrame->aOp[pFrame->pc].p1];
|
| + sqlite3VdbeMemShallowCopy(pOut, pIn, MEM_Ephem);
|
| + break;
|
| +}
|
| +
|
| +#endif /* #ifndef SQLITE_OMIT_TRIGGER */
|
| +
|
| +#ifndef SQLITE_OMIT_FOREIGN_KEY
|
| +/* Opcode: FkCounter P1 P2 * * *
|
| +** Synopsis: fkctr[P1]+=P2
|
| +**
|
| +** Increment a "constraint counter" by P2 (P2 may be negative or positive).
|
| +** If P1 is non-zero, the database constraint counter is incremented
|
| +** (deferred foreign key constraints). Otherwise, if P1 is zero, the
|
| +** statement counter is incremented (immediate foreign key constraints).
|
| +*/
|
| +case OP_FkCounter: {
|
| + if( db->flags & SQLITE_DeferFKs ){
|
| + db->nDeferredImmCons += pOp->p2;
|
| + }else if( pOp->p1 ){
|
| + db->nDeferredCons += pOp->p2;
|
| + }else{
|
| + p->nFkConstraint += pOp->p2;
|
| + }
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: FkIfZero P1 P2 * * *
|
| +** Synopsis: if fkctr[P1]==0 goto P2
|
| +**
|
| +** This opcode tests if a foreign key constraint-counter is currently zero.
|
| +** If so, jump to instruction P2. Otherwise, fall through to the next
|
| +** instruction.
|
| +**
|
| +** If P1 is non-zero, then the jump is taken if the database constraint-counter
|
| +** is zero (the one that counts deferred constraint violations). If P1 is
|
| +** zero, the jump is taken if the statement constraint-counter is zero
|
| +** (immediate foreign key constraint violations).
|
| +*/
|
| +case OP_FkIfZero: { /* jump */
|
| + if( pOp->p1 ){
|
| + VdbeBranchTaken(db->nDeferredCons==0 && db->nDeferredImmCons==0, 2);
|
| + if( db->nDeferredCons==0 && db->nDeferredImmCons==0 ) goto jump_to_p2;
|
| + }else{
|
| + VdbeBranchTaken(p->nFkConstraint==0 && db->nDeferredImmCons==0, 2);
|
| + if( p->nFkConstraint==0 && db->nDeferredImmCons==0 ) goto jump_to_p2;
|
| + }
|
| + break;
|
| +}
|
| +#endif /* #ifndef SQLITE_OMIT_FOREIGN_KEY */
|
| +
|
| +#ifndef SQLITE_OMIT_AUTOINCREMENT
|
| +/* Opcode: MemMax P1 P2 * * *
|
| +** Synopsis: r[P1]=max(r[P1],r[P2])
|
| +**
|
| +** P1 is a register in the root frame of this VM (the root frame is
|
| +** different from the current frame if this instruction is being executed
|
| +** within a sub-program). Set the value of register P1 to the maximum of
|
| +** its current value and the value in register P2.
|
| +**
|
| +** This instruction throws an error if the memory cell is not initially
|
| +** an integer.
|
| +*/
|
| +case OP_MemMax: { /* in2 */
|
| + VdbeFrame *pFrame;
|
| + if( p->pFrame ){
|
| + for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent);
|
| + pIn1 = &pFrame->aMem[pOp->p1];
|
| + }else{
|
| + pIn1 = &aMem[pOp->p1];
|
| + }
|
| + assert( memIsValid(pIn1) );
|
| + sqlite3VdbeMemIntegerify(pIn1);
|
| + pIn2 = &aMem[pOp->p2];
|
| + sqlite3VdbeMemIntegerify(pIn2);
|
| + if( pIn1->u.i<pIn2->u.i){
|
| + pIn1->u.i = pIn2->u.i;
|
| + }
|
| + break;
|
| +}
|
| +#endif /* SQLITE_OMIT_AUTOINCREMENT */
|
| +
|
| +/* Opcode: IfPos P1 P2 P3 * *
|
| +** Synopsis: if r[P1]>0 then r[P1]-=P3, goto P2
|
| +**
|
| +** Register P1 must contain an integer.
|
| +** If the value of register P1 is 1 or greater, subtract P3 from the
|
| +** value in P1 and jump to P2.
|
| +**
|
| +** If the initial value of register P1 is less than 1, then the
|
| +** value is unchanged and control passes through to the next instruction.
|
| +*/
|
| +case OP_IfPos: { /* jump, in1 */
|
| + pIn1 = &aMem[pOp->p1];
|
| + assert( pIn1->flags&MEM_Int );
|
| + VdbeBranchTaken( pIn1->u.i>0, 2);
|
| + if( pIn1->u.i>0 ){
|
| + pIn1->u.i -= pOp->p3;
|
| + goto jump_to_p2;
|
| + }
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: SetIfNotPos P1 P2 P3 * *
|
| +** Synopsis: if r[P1]<=0 then r[P2]=P3
|
| +**
|
| +** Register P1 must contain an integer.
|
| +** If the value of register P1 is not positive (if it is less than 1) then
|
| +** set the value of register P2 to be the integer P3.
|
| +*/
|
| +case OP_SetIfNotPos: { /* in1, in2 */
|
| + pIn1 = &aMem[pOp->p1];
|
| + assert( pIn1->flags&MEM_Int );
|
| + if( pIn1->u.i<=0 ){
|
| + pOut = out2Prerelease(p, pOp);
|
| + pOut->u.i = pOp->p3;
|
| + }
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: IfNotZero P1 P2 P3 * *
|
| +** Synopsis: if r[P1]!=0 then r[P1]-=P3, goto P2
|
| +**
|
| +** Register P1 must contain an integer. If the content of register P1 is
|
| +** initially nonzero, then subtract P3 from the value in register P1 and
|
| +** jump to P2. If register P1 is initially zero, leave it unchanged
|
| +** and fall through.
|
| +*/
|
| +case OP_IfNotZero: { /* jump, in1 */
|
| + pIn1 = &aMem[pOp->p1];
|
| + assert( pIn1->flags&MEM_Int );
|
| + VdbeBranchTaken(pIn1->u.i<0, 2);
|
| + if( pIn1->u.i ){
|
| + pIn1->u.i -= pOp->p3;
|
| + goto jump_to_p2;
|
| + }
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: DecrJumpZero P1 P2 * * *
|
| +** Synopsis: if (--r[P1])==0 goto P2
|
| +**
|
| +** Register P1 must hold an integer. Decrement the value in register P1
|
| +** then jump to P2 if the new value is exactly zero.
|
| +*/
|
| +case OP_DecrJumpZero: { /* jump, in1 */
|
| + pIn1 = &aMem[pOp->p1];
|
| + assert( pIn1->flags&MEM_Int );
|
| + pIn1->u.i--;
|
| + VdbeBranchTaken(pIn1->u.i==0, 2);
|
| + if( pIn1->u.i==0 ) goto jump_to_p2;
|
| + break;
|
| +}
|
| +
|
| +
|
| +/* Opcode: JumpZeroIncr P1 P2 * * *
|
| +** Synopsis: if (r[P1]++)==0 ) goto P2
|
| +**
|
| +** The register P1 must contain an integer. If register P1 is initially
|
| +** zero, then jump to P2. Increment register P1 regardless of whether or
|
| +** not the jump is taken.
|
| +*/
|
| +case OP_JumpZeroIncr: { /* jump, in1 */
|
| + pIn1 = &aMem[pOp->p1];
|
| + assert( pIn1->flags&MEM_Int );
|
| + VdbeBranchTaken(pIn1->u.i==0, 2);
|
| + if( (pIn1->u.i++)==0 ) goto jump_to_p2;
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: AggStep0 * P2 P3 P4 P5
|
| +** Synopsis: accum=r[P3] step(r[P2@P5])
|
| +**
|
| +** Execute the step function for an aggregate. The
|
| +** function has P5 arguments. P4 is a pointer to the FuncDef
|
| +** structure that specifies the function. Register P3 is the
|
| +** accumulator.
|
| +**
|
| +** The P5 arguments are taken from register P2 and its
|
| +** successors.
|
| +*/
|
| +/* Opcode: AggStep * P2 P3 P4 P5
|
| +** Synopsis: accum=r[P3] step(r[P2@P5])
|
| +**
|
| +** Execute the step function for an aggregate. The
|
| +** function has P5 arguments. P4 is a pointer to an sqlite3_context
|
| +** object that is used to run the function. Register P3 is
|
| +** as the accumulator.
|
| +**
|
| +** The P5 arguments are taken from register P2 and its
|
| +** successors.
|
| +**
|
| +** This opcode is initially coded as OP_AggStep0. On first evaluation,
|
| +** the FuncDef stored in P4 is converted into an sqlite3_context and
|
| +** the opcode is changed. In this way, the initialization of the
|
| +** sqlite3_context only happens once, instead of on each call to the
|
| +** step function.
|
| +*/
|
| +case OP_AggStep0: {
|
| + int n;
|
| + sqlite3_context *pCtx;
|
| +
|
| + assert( pOp->p4type==P4_FUNCDEF );
|
| + n = pOp->p5;
|
| + assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
|
| + assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem-p->nCursor)+1) );
|
| + assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n );
|
| + pCtx = sqlite3DbMallocRaw(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*));
|
| + if( pCtx==0 ) goto no_mem;
|
| + pCtx->pMem = 0;
|
| + pCtx->pFunc = pOp->p4.pFunc;
|
| + pCtx->iOp = (int)(pOp - aOp);
|
| + pCtx->pVdbe = p;
|
| + pCtx->argc = n;
|
| + pOp->p4type = P4_FUNCCTX;
|
| + pOp->p4.pCtx = pCtx;
|
| + pOp->opcode = OP_AggStep;
|
| + /* Fall through into OP_AggStep */
|
| +}
|
| +case OP_AggStep: {
|
| + int i;
|
| + sqlite3_context *pCtx;
|
| + Mem *pMem;
|
| + Mem t;
|
| +
|
| + assert( pOp->p4type==P4_FUNCCTX );
|
| + pCtx = pOp->p4.pCtx;
|
| + pMem = &aMem[pOp->p3];
|
| +
|
| + /* If this function is inside of a trigger, the register array in aMem[]
|
| + ** might change from one evaluation to the next. The next block of code
|
| + ** checks to see if the register array has changed, and if so it
|
| + ** reinitializes the relavant parts of the sqlite3_context object */
|
| + if( pCtx->pMem != pMem ){
|
| + pCtx->pMem = pMem;
|
| + for(i=pCtx->argc-1; i>=0; i--) pCtx->argv[i] = &aMem[pOp->p2+i];
|
| + }
|
| +
|
| +#ifdef SQLITE_DEBUG
|
| + for(i=0; i<pCtx->argc; i++){
|
| + assert( memIsValid(pCtx->argv[i]) );
|
| + REGISTER_TRACE(pOp->p2+i, pCtx->argv[i]);
|
| + }
|
| +#endif
|
| +
|
| + pMem->n++;
|
| + sqlite3VdbeMemInit(&t, db, MEM_Null);
|
| + pCtx->pOut = &t;
|
| + pCtx->fErrorOrAux = 0;
|
| + pCtx->skipFlag = 0;
|
| + (pCtx->pFunc->xStep)(pCtx,pCtx->argc,pCtx->argv); /* IMP: R-24505-23230 */
|
| + if( pCtx->fErrorOrAux ){
|
| + if( pCtx->isError ){
|
| + sqlite3VdbeError(p, "%s", sqlite3_value_text(&t));
|
| + rc = pCtx->isError;
|
| + }
|
| + sqlite3VdbeMemRelease(&t);
|
| + }else{
|
| + assert( t.flags==MEM_Null );
|
| + }
|
| + if( pCtx->skipFlag ){
|
| + assert( pOp[-1].opcode==OP_CollSeq );
|
| + i = pOp[-1].p1;
|
| + if( i ) sqlite3VdbeMemSetInt64(&aMem[i], 1);
|
| + }
|
| + break;
|
| +}
|
| +
|
| +/* Opcode: AggFinal P1 P2 * P4 *
|
| +** Synopsis: accum=r[P1] N=P2
|
| +**
|
| +** Execute the finalizer function for an aggregate. P1 is
|
| +** the memory location that is the accumulator for the aggregate.
|
| +**
|
| +** P2 is the number of arguments that the step function takes and
|
| +** P4 is a pointer to the FuncDef for this function. The P2
|
| +** argument is not used by this opcode. It is only there to disambiguate
|
| +** functions that can take varying numbers of arguments. The
|
| +** P4 argument is only needed for the degenerate case where
|
| +** the step function was not previously called.
|
| +*/
|
| +case OP_AggFinal: {
|
| + Mem *pMem;
|
| + assert( pOp->p1>0 && pOp->p1<=(p->nMem-p->nCursor) );
|
| + pMem = &aMem[pOp->p1];
|
| + assert( (pMem->flags & ~(MEM_Null|MEM_Agg))==0 );
|
| + rc = sqlite3VdbeMemFinalize(pMem, pOp->p4.pFunc);
|
| + if( rc ){
|
| + sqlite3VdbeError(p, "%s", sqlite3_value_text(pMem));
|
| + }
|
| + sqlite3VdbeChangeEncoding(pMem, encoding);
|
| + UPDATE_MAX_BLOBSIZE(pMem);
|
| + if( sqlite3VdbeMemTooBig(pMem) ){
|
| + goto too_big;
|
| + }
|
| + break;
|
| +}
|
| +
|
| +#ifndef SQLITE_OMIT_WAL
|
| +/* Opcode: Checkpoint P1 P2 P3 * *
|
| +**
|
| +** Checkpoint database P1. This is a no-op if P1 is not currently in
|
| +** WAL mode. Parameter P2 is one of SQLITE_CHECKPOINT_PASSIVE, FULL,
|
| +** RESTART, or TRUNCATE. Write 1 or 0 into mem[P3] if the checkpoint returns
|
| +** SQLITE_BUSY or not, respectively. Write the number of pages in the
|
| +** WAL after the checkpoint into mem[P3+1] and the number of pages
|
| +** in the WAL that have been checkpointed after the checkpoint
|
| +** completes into mem[P3+2]. However on an error, mem[P3+1] and
|
| +** mem[P3+2] are initialized to -1.
|
| +*/
|
| +case OP_Checkpoint: {
|
| + int i; /* Loop counter */
|
| + int aRes[3]; /* Results */
|
| + Mem *pMem; /* Write results here */
|
| +
|
| + assert( p->readOnly==0 );
|
| + aRes[0] = 0;
|
| + aRes[1] = aRes[2] = -1;
|
| + assert( pOp->p2==SQLITE_CHECKPOINT_PASSIVE
|
| + || pOp->p2==SQLITE_CHECKPOINT_FULL
|
| + || pOp->p2==SQLITE_CHECKPOINT_RESTART
|
| + || pOp->p2==SQLITE_CHECKPOINT_TRUNCATE
|
| + );
|
| + rc = sqlite3Checkpoint(db, pOp->p1, pOp->p2, &aRes[1], &aRes[2]);
|
| + if( rc==SQLITE_BUSY ){
|
| + rc = SQLITE_OK;
|
| + aRes[0] = 1;
|
| + }
|
| + for(i=0, pMem = &aMem[pOp->p3]; i<3; i++, pMem++){
|
| + sqlite3VdbeMemSetInt64(pMem, (i64)aRes[i]);
|
| + }
|
| + break;
|
| +};
|
| +#endif
|
| +
|
| +#ifndef SQLITE_OMIT_PRAGMA
|
| +/* Opcode: JournalMode P1 P2 P3 * *
|
| +**
|
| +** Change the journal mode of database P1 to P3. P3 must be one of the
|
| +** PAGER_JOURNALMODE_XXX values. If changing between the various rollback
|
| +** modes (delete, truncate, persist, off and memory), this is a simple
|
| +** operation. No IO is required.
|
| +**
|
| +** If changing into or out of WAL mode the procedure is more complicated.
|
| +**
|
| +** Write a string containing the final journal-mode to register P2.
|
| +*/
|
| +case OP_JournalMode: { /* out2 */
|
| + Btree *pBt; /* Btree to change journal mode of */
|
| + Pager *pPager; /* Pager associated with pBt */
|
| + int eNew; /* New journal mode */
|
| + int eOld; /* The old journal mode */
|
| +#ifndef SQLITE_OMIT_WAL
|
| + const char *zFilename; /* Name of database file for pPager */
|
| +#endif
|
| +
|
| + pOut = out2Prerelease(p, pOp);
|
| + eNew = pOp->p3;
|
| + assert( eNew==PAGER_JOURNALMODE_DELETE
|
| + || eNew==PAGER_JOURNALMODE_TRUNCATE
|
| + || eNew==PAGER_JOURNALMODE_PERSIST
|
| + || eNew==PAGER_JOURNALMODE_OFF
|
| + || eNew==PAGER_JOURNALMODE_MEMORY
|
| + || eNew==PAGER_JOURNALMODE_WAL
|
| + || eNew==PAGER_JOURNALMODE_QUERY
|
| + );
|
| + assert( pOp->p1>=0 && pOp->p1<db->nDb );
|
| + assert( p->readOnly==0 );
|
| +
|
| + pBt = db->aDb[pOp->p1].pBt;
|
| + pPager = sqlite3BtreePager(pBt);
|
| + eOld = sqlite3PagerGetJournalMode(pPager);
|
| + if( eNew==PAGER_JOURNALMODE_QUERY ) eNew = eOld;
|
| + if( !sqlite3PagerOkToChangeJournalMode(pPager) ) eNew = eOld;
|
| +
|
| +#ifndef SQLITE_OMIT_WAL
|
| + zFilename = sqlite3PagerFilename(pPager, 1);
|
| +
|
| + /* Do not allow a transition to journal_mode=WAL for a database
|
| + ** in temporary storage or if the VFS does not support shared memory
|
| + */
|
| + if( eNew==PAGER_JOURNALMODE_WAL
|
| + && (sqlite3Strlen30(zFilename)==0 /* Temp file */
|
| + || !sqlite3PagerWalSupported(pPager)) /* No shared-memory support */
|
| + ){
|
| + eNew = eOld;
|
| + }
|
| +
|
| + if( (eNew!=eOld)
|
| + && (eOld==PAGER_JOURNALMODE_WAL || eNew==PAGER_JOURNALMODE_WAL)
|
| + ){
|
| + if( !db->autoCommit || db->nVdbeRead>1 ){
|
| + rc = SQLITE_ERROR;
|
| + sqlite3VdbeError(p,
|
| + "cannot change %s wal mode from within a transaction",
|
| + (eNew==PAGER_JOURNALMODE_WAL ? "into" : "out of")
|
| + );
|
| + break;
|
| + }else{
|
| +
|
| + if( eOld==PAGER_JOURNALMODE_WAL ){
|
| + /* If leaving WAL mode, close the log file. If successful, the call
|
| + ** to PagerCloseWal() checkpoints and deletes the write-ahead-log
|
| + ** file. An EXCLUSIVE lock may still be held on the database file
|
| + ** after a successful return.
|
| + */
|
| + rc = sqlite3PagerCloseWal(pPager);
|
| + if( rc==SQLITE_OK ){
|
| + sqlite3PagerSetJournalMode(pPager, eNew);
|
| + }
|
| + }else if( eOld==PAGER_JOURNALMODE_MEMORY ){
|
| + /* Cannot transition directly from MEMORY to WAL. Use mode OFF
|
| + ** as an intermediate */
|
| + sqlite3PagerSetJournalMode(pPager, PAGER_JOURNALMODE_OFF);
|
| + }
|
| +
|
| + /* Open a transaction on the database file. Regardless of the journal
|
| + ** mode, this transaction always uses a rollback journal.
|
| + */
|
| + assert( sqlite3BtreeIsInTrans(pBt)==0 );
|
| + if( rc==SQLITE_OK ){
|
| + rc = sqlite3BtreeSetVersion(pBt, (eNew==PAGER_JOURNALMODE_WAL ? 2 : 1));
|
| + }
|
| + }
|
| + }
|
| +#endif /* ifndef SQLITE_OMIT_WAL */
|
| +
|
| + if( rc ){
|
| + eNew = eOld;
|
| + }
|
| + eNew = sqlite3PagerSetJournalMode(pPager, eNew);
|
| +
|
| + pOut->flags = MEM_Str|MEM_Static|MEM_Term;
|
| + pOut->z = (char *)sqlite3JournalModename(eNew);
|
| + pOut->n = sqlite3Strlen30(pOut->z);
|
| + pOut->enc = SQLITE_UTF8;
|
| + sqlite3VdbeChangeEncoding(pOut, encoding);
|
| + break;
|
| +};
|
| +#endif /* SQLITE_OMIT_PRAGMA */
|
| +
|
| +#if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH)
|
| +/* Opcode: Vacuum * * * * *
|
| +**
|
| +** Vacuum the entire database. This opcode will cause other virtual
|
| +** machines to be created and run. It may not be called from within
|
| +** a transaction.
|
| +*/
|
| +case OP_Vacuum: {
|
| + assert( p->readOnly==0 );
|
| + rc = sqlite3RunVacuum(&p->zErrMsg, db);
|
| + break;
|
| +}
|
| +#endif
|
| +
|
| +#if !defined(SQLITE_OMIT_AUTOVACUUM)
|
| +/* Opcode: IncrVacuum P1 P2 * * *
|
| +**
|
| +** Perform a single step of the incremental vacuum procedure on
|
| +** the P1 database. If the vacuum has finished, jump to instruction
|
| +** P2. Otherwise, fall through to the next instruction.
|
| +*/
|
| +case OP_IncrVacuum: { /* jump */
|
| + Btree *pBt;
|
| +
|
| + assert( pOp->p1>=0 && pOp->p1<db->nDb );
|
| + assert( DbMaskTest(p->btreeMask, pOp->p1) );
|
| + assert( p->readOnly==0 );
|
| + pBt = db->aDb[pOp->p1].pBt;
|
| + rc = sqlite3BtreeIncrVacuum(pBt);
|
| + VdbeBranchTaken(rc==SQLITE_DONE,2);
|
| + if( rc==SQLITE_DONE ){
|
| + rc = SQLITE_OK;
|
| + goto jump_to_p2;
|
| + }
|
| + break;
|
| +}
|
| +#endif
|
| +
|
| +/* Opcode: Expire P1 * * * *
|
| +**
|
| +** Cause precompiled statements to expire. When an expired statement
|
| +** is executed using sqlite3_step() it will either automatically
|
| +** reprepare itself (if it was originally created using sqlite3_prepare_v2())
|
| +** or it will fail with SQLITE_SCHEMA.
|
| +**
|
| +** If P1 is 0, then all SQL statements become expired. If P1 is non-zero,
|
| +** then only the currently executing statement is expired.
|
| +*/
|
| +case OP_Expire: {
|
| + if( !pOp->p1 ){
|
| + sqlite3ExpirePreparedStatements(db);
|
| + }else{
|
| + p->expired = 1;
|
| + }
|
| + break;
|
| +}
|
| +
|
| +#ifndef SQLITE_OMIT_SHARED_CACHE
|
| +/* Opcode: TableLock P1 P2 P3 P4 *
|
| +** Synopsis: iDb=P1 root=P2 write=P3
|
| +**
|
| +** Obtain a lock on a particular table. This instruction is only used when
|
| +** the shared-cache feature is enabled.
|
| +**
|
| +** P1 is the index of the database in sqlite3.aDb[] of the database
|
| +** on which the lock is acquired. A readlock is obtained if P3==0 or
|
| +** a write lock if P3==1.
|
| +**
|
| +** P2 contains the root-page of the table to lock.
|
| +**
|
| +** P4 contains a pointer to the name of the table being locked. This is only
|
| +** used to generate an error message if the lock cannot be obtained.
|
| +*/
|
| +case OP_TableLock: {
|
| + u8 isWriteLock = (u8)pOp->p3;
|
| + if( isWriteLock || 0==(db->flags&SQLITE_ReadUncommitted) ){
|
| + int p1 = pOp->p1;
|
| + assert( p1>=0 && p1<db->nDb );
|
| + assert( DbMaskTest(p->btreeMask, p1) );
|
| + assert( isWriteLock==0 || isWriteLock==1 );
|
| + rc = sqlite3BtreeLockTable(db->aDb[p1].pBt, pOp->p2, isWriteLock);
|
| + if( (rc&0xFF)==SQLITE_LOCKED ){
|
| + const char *z = pOp->p4.z;
|
| + sqlite3VdbeError(p, "database table is locked: %s", z);
|
| + }
|
| + }
|
| + break;
|
| +}
|
| +#endif /* SQLITE_OMIT_SHARED_CACHE */
|
| +
|
| +#ifndef SQLITE_OMIT_VIRTUALTABLE
|
| +/* Opcode: VBegin * * * P4 *
|
| +**
|
| +** P4 may be a pointer to an sqlite3_vtab structure. If so, call the
|
| +** xBegin method for that table.
|
| +**
|
| +** Also, whether or not P4 is set, check that this is not being called from
|
| +** within a callback to a virtual table xSync() method. If it is, the error
|
| +** code will be set to SQLITE_LOCKED.
|
| +*/
|
| +case OP_VBegin: {
|
| + VTable *pVTab;
|
| + pVTab = pOp->p4.pVtab;
|
| + rc = sqlite3VtabBegin(db, pVTab);
|
| + if( pVTab ) sqlite3VtabImportErrmsg(p, pVTab->pVtab);
|
| + break;
|
| +}
|
| +#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
| +
|
| +#ifndef SQLITE_OMIT_VIRTUALTABLE
|
| +/* Opcode: VCreate P1 P2 * * *
|
| +**
|
| +** P2 is a register that holds the name of a virtual table in database
|
| +** P1. Call the xCreate method for that table.
|
| +*/
|
| +case OP_VCreate: {
|
| + Mem sMem; /* For storing the record being decoded */
|
| + const char *zTab; /* Name of the virtual table */
|
| +
|
| + memset(&sMem, 0, sizeof(sMem));
|
| + sMem.db = db;
|
| + /* Because P2 is always a static string, it is impossible for the
|
| + ** sqlite3VdbeMemCopy() to fail */
|
| + assert( (aMem[pOp->p2].flags & MEM_Str)!=0 );
|
| + assert( (aMem[pOp->p2].flags & MEM_Static)!=0 );
|
| + rc = sqlite3VdbeMemCopy(&sMem, &aMem[pOp->p2]);
|
| + assert( rc==SQLITE_OK );
|
| + zTab = (const char*)sqlite3_value_text(&sMem);
|
| + assert( zTab || db->mallocFailed );
|
| + if( zTab ){
|
| + rc = sqlite3VtabCallCreate(db, pOp->p1, zTab, &p->zErrMsg);
|
| + }
|
| + sqlite3VdbeMemRelease(&sMem);
|
| + break;
|
| +}
|
| +#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
| +
|
| +#ifndef SQLITE_OMIT_VIRTUALTABLE
|
| +/* Opcode: VDestroy P1 * * P4 *
|
| +**
|
| +** P4 is the name of a virtual table in database P1. Call the xDestroy method
|
| +** of that table.
|
| +*/
|
| +case OP_VDestroy: {
|
| + db->nVDestroy++;
|
| + rc = sqlite3VtabCallDestroy(db, pOp->p1, pOp->p4.z);
|
| + db->nVDestroy--;
|
| + break;
|
| +}
|
| +#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
| +
|
| +#ifndef SQLITE_OMIT_VIRTUALTABLE
|
| +/* Opcode: VOpen P1 * * P4 *
|
| +**
|
| +** P4 is a pointer to a virtual table object, an sqlite3_vtab structure.
|
| +** P1 is a cursor number. This opcode opens a cursor to the virtual
|
| +** table and stores that cursor in P1.
|
| +*/
|
| +case OP_VOpen: {
|
| + VdbeCursor *pCur;
|
| + sqlite3_vtab_cursor *pVCur;
|
| + sqlite3_vtab *pVtab;
|
| + const sqlite3_module *pModule;
|
| +
|
| + assert( p->bIsReader );
|
| + pCur = 0;
|
| + pVCur = 0;
|
| + pVtab = pOp->p4.pVtab->pVtab;
|
| + if( pVtab==0 || NEVER(pVtab->pModule==0) ){
|
| + rc = SQLITE_LOCKED;
|
| + break;
|
| + }
|
| + pModule = pVtab->pModule;
|
| + rc = pModule->xOpen(pVtab, &pVCur);
|
| + sqlite3VtabImportErrmsg(p, pVtab);
|
| + if( SQLITE_OK==rc ){
|
| + /* Initialize sqlite3_vtab_cursor base class */
|
| + pVCur->pVtab = pVtab;
|
| +
|
| + /* Initialize vdbe cursor object */
|
| + pCur = allocateCursor(p, pOp->p1, 0, -1, CURTYPE_VTAB);
|
| + if( pCur ){
|
| + pCur->uc.pVCur = pVCur;
|
| + pVtab->nRef++;
|
| + }else{
|
| + assert( db->mallocFailed );
|
| + pModule->xClose(pVCur);
|
| + goto no_mem;
|
| + }
|
| + }
|
| + break;
|
| +}
|
| +#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
| +
|
| +#ifndef SQLITE_OMIT_VIRTUALTABLE
|
| +/* Opcode: VFilter P1 P2 P3 P4 *
|
| +** Synopsis: iplan=r[P3] zplan='P4'
|
| +**
|
| +** P1 is a cursor opened using VOpen. P2 is an address to jump to if
|
| +** the filtered result set is empty.
|
| +**
|
| +** P4 is either NULL or a string that was generated by the xBestIndex
|
| +** method of the module. The interpretation of the P4 string is left
|
| +** to the module implementation.
|
| +**
|
| +** This opcode invokes the xFilter method on the virtual table specified
|
| +** by P1. The integer query plan parameter to xFilter is stored in register
|
| +** P3. Register P3+1 stores the argc parameter to be passed to the
|
| +** xFilter method. Registers P3+2..P3+1+argc are the argc
|
| +** additional parameters which are passed to
|
| +** xFilter as argv. Register P3+2 becomes argv[0] when passed to xFilter.
|
| +**
|
| +** A jump is made to P2 if the result set after filtering would be empty.
|
| +*/
|
| +case OP_VFilter: { /* jump */
|
| + int nArg;
|
| + int iQuery;
|
| + const sqlite3_module *pModule;
|
| + Mem *pQuery;
|
| + Mem *pArgc;
|
| + sqlite3_vtab_cursor *pVCur;
|
| + sqlite3_vtab *pVtab;
|
| + VdbeCursor *pCur;
|
| + int res;
|
| + int i;
|
| + Mem **apArg;
|
| +
|
| + pQuery = &aMem[pOp->p3];
|
| + pArgc = &pQuery[1];
|
| + pCur = p->apCsr[pOp->p1];
|
| + assert( memIsValid(pQuery) );
|
| + REGISTER_TRACE(pOp->p3, pQuery);
|
| + assert( pCur->eCurType==CURTYPE_VTAB );
|
| + pVCur = pCur->uc.pVCur;
|
| + pVtab = pVCur->pVtab;
|
| + pModule = pVtab->pModule;
|
| +
|
| + /* Grab the index number and argc parameters */
|
| + assert( (pQuery->flags&MEM_Int)!=0 && pArgc->flags==MEM_Int );
|
| + nArg = (int)pArgc->u.i;
|
| + iQuery = (int)pQuery->u.i;
|
| +
|
| + /* Invoke the xFilter method */
|
| + res = 0;
|
| + apArg = p->apArg;
|
| + for(i = 0; i<nArg; i++){
|
| + apArg[i] = &pArgc[i+1];
|
| + }
|
| + rc = pModule->xFilter(pVCur, iQuery, pOp->p4.z, nArg, apArg);
|
| + sqlite3VtabImportErrmsg(p, pVtab);
|
| + if( rc==SQLITE_OK ){
|
| + res = pModule->xEof(pVCur);
|
| + }
|
| + pCur->nullRow = 0;
|
| + VdbeBranchTaken(res!=0,2);
|
| + if( res ) goto jump_to_p2;
|
| + break;
|
| +}
|
| +#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
| +
|
| +#ifndef SQLITE_OMIT_VIRTUALTABLE
|
| +/* Opcode: VColumn P1 P2 P3 * *
|
| +** Synopsis: r[P3]=vcolumn(P2)
|
| +**
|
| +** Store the value of the P2-th column of
|
| +** the row of the virtual-table that the
|
| +** P1 cursor is pointing to into register P3.
|
| +*/
|
| +case OP_VColumn: {
|
| + sqlite3_vtab *pVtab;
|
| + const sqlite3_module *pModule;
|
| + Mem *pDest;
|
| + sqlite3_context sContext;
|
| +
|
| + VdbeCursor *pCur = p->apCsr[pOp->p1];
|
| + assert( pCur->eCurType==CURTYPE_VTAB );
|
| + assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
|
| + pDest = &aMem[pOp->p3];
|
| + memAboutToChange(p, pDest);
|
| + if( pCur->nullRow ){
|
| + sqlite3VdbeMemSetNull(pDest);
|
| + break;
|
| + }
|
| + pVtab = pCur->uc.pVCur->pVtab;
|
| + pModule = pVtab->pModule;
|
| + assert( pModule->xColumn );
|
| + memset(&sContext, 0, sizeof(sContext));
|
| + sContext.pOut = pDest;
|
| + MemSetTypeFlag(pDest, MEM_Null);
|
| + rc = pModule->xColumn(pCur->uc.pVCur, &sContext, pOp->p2);
|
| + sqlite3VtabImportErrmsg(p, pVtab);
|
| + if( sContext.isError ){
|
| + rc = sContext.isError;
|
| + }
|
| + sqlite3VdbeChangeEncoding(pDest, encoding);
|
| + REGISTER_TRACE(pOp->p3, pDest);
|
| + UPDATE_MAX_BLOBSIZE(pDest);
|
| +
|
| + if( sqlite3VdbeMemTooBig(pDest) ){
|
| + goto too_big;
|
| + }
|
| + break;
|
| +}
|
| +#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
| +
|
| +#ifndef SQLITE_OMIT_VIRTUALTABLE
|
| +/* Opcode: VNext P1 P2 * * *
|
| +**
|
| +** Advance virtual table P1 to the next row in its result set and
|
| +** jump to instruction P2. Or, if the virtual table has reached
|
| +** the end of its result set, then fall through to the next instruction.
|
| +*/
|
| +case OP_VNext: { /* jump */
|
| + sqlite3_vtab *pVtab;
|
| + const sqlite3_module *pModule;
|
| + int res;
|
| + VdbeCursor *pCur;
|
| +
|
| + res = 0;
|
| + pCur = p->apCsr[pOp->p1];
|
| + assert( pCur->eCurType==CURTYPE_VTAB );
|
| + if( pCur->nullRow ){
|
| + break;
|
| + }
|
| + pVtab = pCur->uc.pVCur->pVtab;
|
| + pModule = pVtab->pModule;
|
| + assert( pModule->xNext );
|
| +
|
| + /* Invoke the xNext() method of the module. There is no way for the
|
| + ** underlying implementation to return an error if one occurs during
|
| + ** xNext(). Instead, if an error occurs, true is returned (indicating that
|
| + ** data is available) and the error code returned when xColumn or
|
| + ** some other method is next invoked on the save virtual table cursor.
|
| + */
|
| + rc = pModule->xNext(pCur->uc.pVCur);
|
| + sqlite3VtabImportErrmsg(p, pVtab);
|
| + if( rc==SQLITE_OK ){
|
| + res = pModule->xEof(pCur->uc.pVCur);
|
| + }
|
| + VdbeBranchTaken(!res,2);
|
| + if( !res ){
|
| + /* If there is data, jump to P2 */
|
| + goto jump_to_p2_and_check_for_interrupt;
|
| + }
|
| + goto check_for_interrupt;
|
| +}
|
| +#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
| +
|
| +#ifndef SQLITE_OMIT_VIRTUALTABLE
|
| +/* Opcode: VRename P1 * * P4 *
|
| +**
|
| +** P4 is a pointer to a virtual table object, an sqlite3_vtab structure.
|
| +** This opcode invokes the corresponding xRename method. The value
|
| +** in register P1 is passed as the zName argument to the xRename method.
|
| +*/
|
| +case OP_VRename: {
|
| + sqlite3_vtab *pVtab;
|
| + Mem *pName;
|
| +
|
| + pVtab = pOp->p4.pVtab->pVtab;
|
| + pName = &aMem[pOp->p1];
|
| + assert( pVtab->pModule->xRename );
|
| + assert( memIsValid(pName) );
|
| + assert( p->readOnly==0 );
|
| + REGISTER_TRACE(pOp->p1, pName);
|
| + assert( pName->flags & MEM_Str );
|
| + testcase( pName->enc==SQLITE_UTF8 );
|
| + testcase( pName->enc==SQLITE_UTF16BE );
|
| + testcase( pName->enc==SQLITE_UTF16LE );
|
| + rc = sqlite3VdbeChangeEncoding(pName, SQLITE_UTF8);
|
| + if( rc==SQLITE_OK ){
|
| + rc = pVtab->pModule->xRename(pVtab, pName->z);
|
| + sqlite3VtabImportErrmsg(p, pVtab);
|
| + p->expired = 0;
|
| + }
|
| + break;
|
| +}
|
| +#endif
|
| +
|
| +#ifndef SQLITE_OMIT_VIRTUALTABLE
|
| +/* Opcode: VUpdate P1 P2 P3 P4 P5
|
| +** Synopsis: data=r[P3@P2]
|
| +**
|
| +** P4 is a pointer to a virtual table object, an sqlite3_vtab structure.
|
| +** This opcode invokes the corresponding xUpdate method. P2 values
|
| +** are contiguous memory cells starting at P3 to pass to the xUpdate
|
| +** invocation. The value in register (P3+P2-1) corresponds to the
|
| +** p2th element of the argv array passed to xUpdate.
|
| +**
|
| +** The xUpdate method will do a DELETE or an INSERT or both.
|
| +** The argv[0] element (which corresponds to memory cell P3)
|
| +** is the rowid of a row to delete. If argv[0] is NULL then no
|
| +** deletion occurs. The argv[1] element is the rowid of the new
|
| +** row. This can be NULL to have the virtual table select the new
|
| +** rowid for itself. The subsequent elements in the array are
|
| +** the values of columns in the new row.
|
| +**
|
| +** If P2==1 then no insert is performed. argv[0] is the rowid of
|
| +** a row to delete.
|
| +**
|
| +** P1 is a boolean flag. If it is set to true and the xUpdate call
|
| +** is successful, then the value returned by sqlite3_last_insert_rowid()
|
| +** is set to the value of the rowid for the row just inserted.
|
| +**
|
| +** P5 is the error actions (OE_Replace, OE_Fail, OE_Ignore, etc) to
|
| +** apply in the case of a constraint failure on an insert or update.
|
| +*/
|
| +case OP_VUpdate: {
|
| + sqlite3_vtab *pVtab;
|
| + const sqlite3_module *pModule;
|
| + int nArg;
|
| + int i;
|
| + sqlite_int64 rowid;
|
| + Mem **apArg;
|
| + Mem *pX;
|
| +
|
| + assert( pOp->p2==1 || pOp->p5==OE_Fail || pOp->p5==OE_Rollback
|
| + || pOp->p5==OE_Abort || pOp->p5==OE_Ignore || pOp->p5==OE_Replace
|
| + );
|
| + assert( p->readOnly==0 );
|
| + pVtab = pOp->p4.pVtab->pVtab;
|
| + if( pVtab==0 || NEVER(pVtab->pModule==0) ){
|
| + rc = SQLITE_LOCKED;
|
| + break;
|
| + }
|
| + pModule = pVtab->pModule;
|
| + nArg = pOp->p2;
|
| + assert( pOp->p4type==P4_VTAB );
|
| + if( ALWAYS(pModule->xUpdate) ){
|
| + u8 vtabOnConflict = db->vtabOnConflict;
|
| + apArg = p->apArg;
|
| + pX = &aMem[pOp->p3];
|
| + for(i=0; i<nArg; i++){
|
| + assert( memIsValid(pX) );
|
| + memAboutToChange(p, pX);
|
| + apArg[i] = pX;
|
| + pX++;
|
| + }
|
| + db->vtabOnConflict = pOp->p5;
|
| + rc = pModule->xUpdate(pVtab, nArg, apArg, &rowid);
|
| + db->vtabOnConflict = vtabOnConflict;
|
| + sqlite3VtabImportErrmsg(p, pVtab);
|
| + if( rc==SQLITE_OK && pOp->p1 ){
|
| + assert( nArg>1 && apArg[0] && (apArg[0]->flags&MEM_Null) );
|
| + db->lastRowid = lastRowid = rowid;
|
| + }
|
| + if( (rc&0xff)==SQLITE_CONSTRAINT && pOp->p4.pVtab->bConstraint ){
|
| + if( pOp->p5==OE_Ignore ){
|
| + rc = SQLITE_OK;
|
| + }else{
|
| + p->errorAction = ((pOp->p5==OE_Replace) ? OE_Abort : pOp->p5);
|
| + }
|
| + }else{
|
| + p->nChange++;
|
| + }
|
| + }
|
| + break;
|
| +}
|
| +#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
| +
|
| +#ifndef SQLITE_OMIT_PAGER_PRAGMAS
|
| +/* Opcode: Pagecount P1 P2 * * *
|
| +**
|
| +** Write the current number of pages in database P1 to memory cell P2.
|
| +*/
|
| +case OP_Pagecount: { /* out2 */
|
| + pOut = out2Prerelease(p, pOp);
|
| + pOut->u.i = sqlite3BtreeLastPage(db->aDb[pOp->p1].pBt);
|
| + break;
|
| +}
|
| +#endif
|
| +
|
| +
|
| +#ifndef SQLITE_OMIT_PAGER_PRAGMAS
|
| +/* Opcode: MaxPgcnt P1 P2 P3 * *
|
| +**
|
| +** Try to set the maximum page count for database P1 to the value in P3.
|
| +** Do not let the maximum page count fall below the current page count and
|
| +** do not change the maximum page count value if P3==0.
|
| +**
|
| +** Store the maximum page count after the change in register P2.
|
| +*/
|
| +case OP_MaxPgcnt: { /* out2 */
|
| + unsigned int newMax;
|
| + Btree *pBt;
|
| +
|
| + pOut = out2Prerelease(p, pOp);
|
| + pBt = db->aDb[pOp->p1].pBt;
|
| + newMax = 0;
|
| + if( pOp->p3 ){
|
| + newMax = sqlite3BtreeLastPage(pBt);
|
| + if( newMax < (unsigned)pOp->p3 ) newMax = (unsigned)pOp->p3;
|
| + }
|
| + pOut->u.i = sqlite3BtreeMaxPageCount(pBt, newMax);
|
| + break;
|
| +}
|
| +#endif
|
| +
|
| +
|
| +/* Opcode: Init * P2 * P4 *
|
| +** Synopsis: Start at P2
|
| +**
|
| +** Programs contain a single instance of this opcode as the very first
|
| +** opcode.
|
| +**
|
| +** If tracing is enabled (by the sqlite3_trace()) interface, then
|
| +** the UTF-8 string contained in P4 is emitted on the trace callback.
|
| +** Or if P4 is blank, use the string returned by sqlite3_sql().
|
| +**
|
| +** If P2 is not zero, jump to instruction P2.
|
| +*/
|
| +case OP_Init: { /* jump */
|
| + char *zTrace;
|
| + char *z;
|
| +
|
| +#ifndef SQLITE_OMIT_TRACE
|
| + if( db->xTrace
|
| + && !p->doingRerun
|
| + && (zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0
|
| + ){
|
| + z = sqlite3VdbeExpandSql(p, zTrace);
|
| + db->xTrace(db->pTraceArg, z);
|
| + sqlite3DbFree(db, z);
|
| + }
|
| +#ifdef SQLITE_USE_FCNTL_TRACE
|
| + zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql);
|
| + if( zTrace ){
|
| + int i;
|
| + for(i=0; i<db->nDb; i++){
|
| + if( DbMaskTest(p->btreeMask, i)==0 ) continue;
|
| + sqlite3_file_control(db, db->aDb[i].zName, SQLITE_FCNTL_TRACE, zTrace);
|
| + }
|
| + }
|
| +#endif /* SQLITE_USE_FCNTL_TRACE */
|
| +#ifdef SQLITE_DEBUG
|
| + if( (db->flags & SQLITE_SqlTrace)!=0
|
| + && (zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0
|
| + ){
|
| + sqlite3DebugPrintf("SQL-trace: %s\n", zTrace);
|
| + }
|
| +#endif /* SQLITE_DEBUG */
|
| +#endif /* SQLITE_OMIT_TRACE */
|
| + if( pOp->p2 ) goto jump_to_p2;
|
| + break;
|
| +}
|
| +
|
| +#ifdef SQLITE_ENABLE_CURSOR_HINTS
|
| +/* Opcode: CursorHint P1 * * P4 *
|
| +**
|
| +** Provide a hint to cursor P1 that it only needs to return rows that
|
| +** satisfy the Expr in P4. TK_REGISTER terms in the P4 expression refer
|
| +** to values currently held in registers. TK_COLUMN terms in the P4
|
| +** expression refer to columns in the b-tree to which cursor P1 is pointing.
|
| +*/
|
| +case OP_CursorHint: {
|
| + VdbeCursor *pC;
|
| +
|
| + assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
| + assert( pOp->p4type==P4_EXPR );
|
| + pC = p->apCsr[pOp->p1];
|
| + if( pC ){
|
| + assert( pC->eCurType==CURTYPE_BTREE );
|
| + sqlite3BtreeCursorHint(pC->uc.pCursor, BTREE_HINT_RANGE,
|
| + pOp->p4.pExpr, aMem);
|
| + }
|
| + break;
|
| +}
|
| +#endif /* SQLITE_ENABLE_CURSOR_HINTS */
|
| +
|
| +/* Opcode: Noop * * * * *
|
| +**
|
| +** Do nothing. This instruction is often useful as a jump
|
| +** destination.
|
| +*/
|
| +/*
|
| +** The magic Explain opcode are only inserted when explain==2 (which
|
| +** is to say when the EXPLAIN QUERY PLAN syntax is used.)
|
| +** This opcode records information from the optimizer. It is the
|
| +** the same as a no-op. This opcodesnever appears in a real VM program.
|
| +*/
|
| +default: { /* This is really OP_Noop and OP_Explain */
|
| + assert( pOp->opcode==OP_Noop || pOp->opcode==OP_Explain );
|
| + break;
|
| +}
|
| +
|
| +/*****************************************************************************
|
| +** The cases of the switch statement above this line should all be indented
|
| +** by 6 spaces. But the left-most 6 spaces have been removed to improve the
|
| +** readability. From this point on down, the normal indentation rules are
|
| +** restored.
|
| +*****************************************************************************/
|
| + }
|
| +
|
| +#ifdef VDBE_PROFILE
|
| + {
|
| + u64 endTime = sqlite3Hwtime();
|
| + if( endTime>start ) pOrigOp->cycles += endTime - start;
|
| + pOrigOp->cnt++;
|
| + }
|
| +#endif
|
| +
|
| + /* The following code adds nothing to the actual functionality
|
| + ** of the program. It is only here for testing and debugging.
|
| + ** On the other hand, it does burn CPU cycles every time through
|
| + ** the evaluator loop. So we can leave it out when NDEBUG is defined.
|
| + */
|
| +#ifndef NDEBUG
|
| + assert( pOp>=&aOp[-1] && pOp<&aOp[p->nOp-1] );
|
| +
|
| +#ifdef SQLITE_DEBUG
|
| + if( db->flags & SQLITE_VdbeTrace ){
|
| + if( rc!=0 ) printf("rc=%d\n",rc);
|
| + if( pOrigOp->opflags & (OPFLG_OUT2) ){
|
| + registerTrace(pOrigOp->p2, &aMem[pOrigOp->p2]);
|
| + }
|
| + if( pOrigOp->opflags & OPFLG_OUT3 ){
|
| + registerTrace(pOrigOp->p3, &aMem[pOrigOp->p3]);
|
| + }
|
| + }
|
| +#endif /* SQLITE_DEBUG */
|
| +#endif /* NDEBUG */
|
| + } /* The end of the for(;;) loop the loops through opcodes */
|
| +
|
| + /* If we reach this point, it means that execution is finished with
|
| + ** an error of some kind.
|
| + */
|
| +vdbe_error_halt:
|
| + assert( rc );
|
| + p->rc = rc;
|
| + testcase( sqlite3GlobalConfig.xLog!=0 );
|
| + sqlite3_log(rc, "statement aborts at %d: [%s] %s",
|
| + (int)(pOp - aOp), p->zSql, p->zErrMsg);
|
| + sqlite3VdbeHalt(p);
|
| + if( rc==SQLITE_IOERR_NOMEM ) db->mallocFailed = 1;
|
| + rc = SQLITE_ERROR;
|
| + if( resetSchemaOnFault>0 ){
|
| + sqlite3ResetOneSchema(db, resetSchemaOnFault-1);
|
| + }
|
| +
|
| + /* This is the only way out of this procedure. We have to
|
| + ** release the mutexes on btrees that were acquired at the
|
| + ** top. */
|
| +vdbe_return:
|
| + db->lastRowid = lastRowid;
|
| + testcase( nVmStep>0 );
|
| + p->aCounter[SQLITE_STMTSTATUS_VM_STEP] += (int)nVmStep;
|
| + sqlite3VdbeLeave(p);
|
| + return rc;
|
| +
|
| + /* Jump to here if a string or blob larger than SQLITE_MAX_LENGTH
|
| + ** is encountered.
|
| + */
|
| +too_big:
|
| + sqlite3VdbeError(p, "string or blob too big");
|
| + rc = SQLITE_TOOBIG;
|
| + goto vdbe_error_halt;
|
| +
|
| + /* Jump to here if a malloc() fails.
|
| + */
|
| +no_mem:
|
| + db->mallocFailed = 1;
|
| + sqlite3VdbeError(p, "out of memory");
|
| + rc = SQLITE_NOMEM;
|
| + goto vdbe_error_halt;
|
| +
|
| + /* Jump to here for any other kind of fatal error. The "rc" variable
|
| + ** should hold the error number.
|
| + */
|
| +abort_due_to_error:
|
| + assert( p->zErrMsg==0 );
|
| + if( db->mallocFailed ) rc = SQLITE_NOMEM;
|
| + if( rc!=SQLITE_IOERR_NOMEM ){
|
| + sqlite3VdbeError(p, "%s", sqlite3ErrStr(rc));
|
| + }
|
| + goto vdbe_error_halt;
|
| +
|
| + /* Jump to here if the sqlite3_interrupt() API sets the interrupt
|
| + ** flag.
|
| + */
|
| +abort_due_to_interrupt:
|
| + assert( db->u1.isInterrupted );
|
| + rc = SQLITE_INTERRUPT;
|
| + p->rc = rc;
|
| + sqlite3VdbeError(p, "%s", sqlite3ErrStr(rc));
|
| + goto vdbe_error_halt;
|
| +}
|
| +
|
| +
|
| +/************** End of vdbe.c ************************************************/
|
| +/************** Begin file vdbeblob.c ****************************************/
|
| +/*
|
| +** 2007 May 1
|
| +**
|
| +** 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.
|
| +**
|
| +*************************************************************************
|
| +**
|
| +** This file contains code used to implement incremental BLOB I/O.
|
| +*/
|
| +
|
| +/* #include "sqliteInt.h" */
|
| +/* #include "vdbeInt.h" */
|
| +
|
| +#ifndef SQLITE_OMIT_INCRBLOB
|
| +
|
| +/*
|
| +** Valid sqlite3_blob* handles point to Incrblob structures.
|
| +*/
|
| +typedef struct Incrblob Incrblob;
|
| +struct Incrblob {
|
| + int flags; /* Copy of "flags" passed to sqlite3_blob_open() */
|
| + int nByte; /* Size of open blob, in bytes */
|
| + int iOffset; /* Byte offset of blob in cursor data */
|
| + int iCol; /* Table column this handle is open on */
|
| + BtCursor *pCsr; /* Cursor pointing at blob row */
|
| + sqlite3_stmt *pStmt; /* Statement holding cursor open */
|
| + sqlite3 *db; /* The associated database */
|
| +};
|
| +
|
| +
|
| +/*
|
| +** This function is used by both blob_open() and blob_reopen(). It seeks
|
| +** the b-tree cursor associated with blob handle p to point to row iRow.
|
| +** If successful, SQLITE_OK is returned and subsequent calls to
|
| +** sqlite3_blob_read() or sqlite3_blob_write() access the specified row.
|
| +**
|
| +** If an error occurs, or if the specified row does not exist or does not
|
| +** contain a value of type TEXT or BLOB in the column nominated when the
|
| +** blob handle was opened, then an error code is returned and *pzErr may
|
| +** be set to point to a buffer containing an error message. It is the
|
| +** responsibility of the caller to free the error message buffer using
|
| +** sqlite3DbFree().
|
| +**
|
| +** If an error does occur, then the b-tree cursor is closed. All subsequent
|
| +** calls to sqlite3_blob_read(), blob_write() or blob_reopen() will
|
| +** immediately return SQLITE_ABORT.
|
| +*/
|
| +static int blobSeekToRow(Incrblob *p, sqlite3_int64 iRow, char **pzErr){
|
| + int rc; /* Error code */
|
| + char *zErr = 0; /* Error message */
|
| + Vdbe *v = (Vdbe *)p->pStmt;
|
| +
|
| + /* Set the value of the SQL statements only variable to integer iRow.
|
| + ** This is done directly instead of using sqlite3_bind_int64() to avoid
|
| + ** triggering asserts related to mutexes.
|
| + */
|
| + assert( v->aVar[0].flags&MEM_Int );
|
| + v->aVar[0].u.i = iRow;
|
| +
|
| + rc = sqlite3_step(p->pStmt);
|
| + if( rc==SQLITE_ROW ){
|
| + VdbeCursor *pC = v->apCsr[0];
|
| + u32 type = pC->aType[p->iCol];
|
| + if( type<12 ){
|
| + zErr = sqlite3MPrintf(p->db, "cannot open value of type %s",
|
| + type==0?"null": type==7?"real": "integer"
|
| + );
|
| + rc = SQLITE_ERROR;
|
| + sqlite3_finalize(p->pStmt);
|
| + p->pStmt = 0;
|
| + }else{
|
| + p->iOffset = pC->aType[p->iCol + pC->nField];
|
| + p->nByte = sqlite3VdbeSerialTypeLen(type);
|
| + p->pCsr = pC->uc.pCursor;
|
| + sqlite3BtreeIncrblobCursor(p->pCsr);
|
| + }
|
| + }
|
| +
|
| + if( rc==SQLITE_ROW ){
|
| + rc = SQLITE_OK;
|
| + }else if( p->pStmt ){
|
| + rc = sqlite3_finalize(p->pStmt);
|
| + p->pStmt = 0;
|
| + if( rc==SQLITE_OK ){
|
| + zErr = sqlite3MPrintf(p->db, "no such rowid: %lld", iRow);
|
| + rc = SQLITE_ERROR;
|
| + }else{
|
| + zErr = sqlite3MPrintf(p->db, "%s", sqlite3_errmsg(p->db));
|
| + }
|
| + }
|
| +
|
| + assert( rc!=SQLITE_OK || zErr==0 );
|
| + assert( rc!=SQLITE_ROW && rc!=SQLITE_DONE );
|
| +
|
| + *pzErr = zErr;
|
| + return rc;
|
| +}
|
| +
|
| +/*
|
| +** Open a blob handle.
|
| +*/
|
| +SQLITE_API int SQLITE_STDCALL sqlite3_blob_open(
|
| + sqlite3* db, /* The database connection */
|
| + const char *zDb, /* The attached database containing the blob */
|
| + const char *zTable, /* The table containing the blob */
|
| + const char *zColumn, /* The column containing the blob */
|
| + sqlite_int64 iRow, /* The row containing the glob */
|
| + int flags, /* True -> read/write access, false -> read-only */
|
| + sqlite3_blob **ppBlob /* Handle for accessing the blob returned here */
|
| +){
|
| + int nAttempt = 0;
|
| + int iCol; /* Index of zColumn in row-record */
|
| +
|
| + /* This VDBE program seeks a btree cursor to the identified
|
| + ** db/table/row entry. The reason for using a vdbe program instead
|
| + ** of writing code to use the b-tree layer directly is that the
|
| + ** vdbe program will take advantage of the various transaction,
|
| + ** locking and error handling infrastructure built into the vdbe.
|
| + **
|
| + ** After seeking the cursor, the vdbe executes an OP_ResultRow.
|
| + ** Code external to the Vdbe then "borrows" the b-tree cursor and
|
| + ** uses it to implement the blob_read(), blob_write() and
|
| + ** blob_bytes() functions.
|
| + **
|
| + ** The sqlite3_blob_close() function finalizes the vdbe program,
|
| + ** which closes the b-tree cursor and (possibly) commits the
|
| + ** transaction.
|
| + */
|
| + static const int iLn = VDBE_OFFSET_LINENO(4);
|
| + static const VdbeOpList openBlob[] = {
|
| + /* {OP_Transaction, 0, 0, 0}, // 0: Inserted separately */
|
| + {OP_TableLock, 0, 0, 0}, /* 1: Acquire a read or write lock */
|
| + /* One of the following two instructions is replaced by an OP_Noop. */
|
| + {OP_OpenRead, 0, 0, 0}, /* 2: Open cursor 0 for reading */
|
| + {OP_OpenWrite, 0, 0, 0}, /* 3: Open cursor 0 for read/write */
|
| + {OP_Variable, 1, 1, 1}, /* 4: Push the rowid to the stack */
|
| + {OP_NotExists, 0, 10, 1}, /* 5: Seek the cursor */
|
| + {OP_Column, 0, 0, 1}, /* 6 */
|
| + {OP_ResultRow, 1, 0, 0}, /* 7 */
|
| + {OP_Goto, 0, 4, 0}, /* 8 */
|
| + {OP_Close, 0, 0, 0}, /* 9 */
|
| + {OP_Halt, 0, 0, 0}, /* 10 */
|
| + };
|
| +
|
| + int rc = SQLITE_OK;
|
| + char *zErr = 0;
|
| + Table *pTab;
|
| + Parse *pParse = 0;
|
| + Incrblob *pBlob = 0;
|
| +
|
| +#ifdef SQLITE_ENABLE_API_ARMOR
|
| + if( ppBlob==0 ){
|
| + return SQLITE_MISUSE_BKPT;
|
| + }
|
| +#endif
|
| + *ppBlob = 0;
|
| +#ifdef SQLITE_ENABLE_API_ARMOR
|
| + if( !sqlite3SafetyCheckOk(db) || zTable==0 ){
|
| + return SQLITE_MISUSE_BKPT;
|
| + }
|
| +#endif
|
| + flags = !!flags; /* flags = (flags ? 1 : 0); */
|
| +
|
| + sqlite3_mutex_enter(db->mutex);
|
| +
|
| + pBlob = (Incrblob *)sqlite3DbMallocZero(db, sizeof(Incrblob));
|
| + if( !pBlob ) goto blob_open_out;
|
| + pParse = sqlite3StackAllocRaw(db, sizeof(*pParse));
|
| + if( !pParse ) goto blob_open_out;
|
| +
|
| + do {
|
| + memset(pParse, 0, sizeof(Parse));
|
| + pParse->db = db;
|
| + sqlite3DbFree(db, zErr);
|
| + zErr = 0;
|
| +
|
| + sqlite3BtreeEnterAll(db);
|
| + pTab = sqlite3LocateTable(pParse, 0, zTable, zDb);
|
| + if( pTab && IsVirtual(pTab) ){
|
| + pTab = 0;
|
| + sqlite3ErrorMsg(pParse, "cannot open virtual table: %s", zTable);
|
| + }
|
| + if( pTab && !HasRowid(pTab) ){
|
| + pTab = 0;
|
| + sqlite3ErrorMsg(pParse, "cannot open table without rowid: %s", zTable);
|
| + }
|
| +#ifndef SQLITE_OMIT_VIEW
|
| + if( pTab && pTab->pSelect ){
|
| + pTab = 0;
|
| + sqlite3ErrorMsg(pParse, "cannot open view: %s", zTable);
|
| + }
|
| +#endif
|
| + if( !pTab ){
|
| + if( pParse->zErrMsg ){
|
| + sqlite3DbFree(db, zErr);
|
| + zErr = pParse->zErrMsg;
|
| + pParse->zErrMsg = 0;
|
| + }
|
| + rc = SQLITE_ERROR;
|
| + sqlite3BtreeLeaveAll(db);
|
| + goto blob_open_out;
|
| + }
|
| +
|
| + /* Now search pTab for the exact column. */
|
| + for(iCol=0; iCol<pTab->nCol; iCol++) {
|
| + if( sqlite3StrICmp(pTab->aCol[iCol].zName, zColumn)==0 ){
|
| + break;
|
| + }
|
| + }
|
| + if( iCol==pTab->nCol ){
|
| + sqlite3DbFree(db, zErr);
|
| + zErr = sqlite3MPrintf(db, "no such column: \"%s\"", zColumn);
|
| + rc = SQLITE_ERROR;
|
| + sqlite3BtreeLeaveAll(db);
|
| + goto blob_open_out;
|
| + }
|
| +
|
| + /* If the value is being opened for writing, check that the
|
| + ** column is not indexed, and that it is not part of a foreign key.
|
| + ** It is against the rules to open a column to which either of these
|
| + ** descriptions applies for writing. */
|
| + if( flags ){
|
| + const char *zFault = 0;
|
| + Index *pIdx;
|
| +#ifndef SQLITE_OMIT_FOREIGN_KEY
|
| + if( db->flags&SQLITE_ForeignKeys ){
|
| + /* Check that the column is not part of an FK child key definition. It
|
| + ** is not necessary to check if it is part of a parent key, as parent
|
| + ** key columns must be indexed. The check below will pick up this
|
| + ** case. */
|
| + FKey *pFKey;
|
| + for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){
|
| + int j;
|
| + for(j=0; j<pFKey->nCol; j++){
|
| + if( pFKey->aCol[j].iFrom==iCol ){
|
| + zFault = "foreign key";
|
| + }
|
| + }
|
| + }
|
| + }
|
| +#endif
|
| + for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
|
| + int j;
|
| + for(j=0; j<pIdx->nKeyCol; j++){
|
| + /* FIXME: Be smarter about indexes that use expressions */
|
| + if( pIdx->aiColumn[j]==iCol || pIdx->aiColumn[j]==XN_EXPR ){
|
| + zFault = "indexed";
|
| + }
|
| + }
|
| + }
|
| + if( zFault ){
|
| + sqlite3DbFree(db, zErr);
|
| + zErr = sqlite3MPrintf(db, "cannot open %s column for writing", zFault);
|
| + rc = SQLITE_ERROR;
|
| + sqlite3BtreeLeaveAll(db);
|
| + goto blob_open_out;
|
| + }
|
| + }
|
| +
|
| + pBlob->pStmt = (sqlite3_stmt *)sqlite3VdbeCreate(pParse);
|
| + assert( pBlob->pStmt || db->mallocFailed );
|
| + if( pBlob->pStmt ){
|
| + Vdbe *v = (Vdbe *)pBlob->pStmt;
|
| + int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
| +
|
| +
|
| + sqlite3VdbeAddOp4Int(v, OP_Transaction, iDb, flags,
|
| + pTab->pSchema->schema_cookie,
|
| + pTab->pSchema->iGeneration);
|
| + sqlite3VdbeChangeP5(v, 1);
|
| + sqlite3VdbeAddOpList(v, ArraySize(openBlob), openBlob, iLn);
|
| +
|
| + /* Make sure a mutex is held on the table to be accessed */
|
| + sqlite3VdbeUsesBtree(v, iDb);
|
| +
|
| + /* Configure the OP_TableLock instruction */
|
| +#ifdef SQLITE_OMIT_SHARED_CACHE
|
| + sqlite3VdbeChangeToNoop(v, 1);
|
| +#else
|
| + sqlite3VdbeChangeP1(v, 1, iDb);
|
| + sqlite3VdbeChangeP2(v, 1, pTab->tnum);
|
| + sqlite3VdbeChangeP3(v, 1, flags);
|
| + sqlite3VdbeChangeP4(v, 1, pTab->zName, P4_TRANSIENT);
|
| +#endif
|
| +
|
| + /* Remove either the OP_OpenWrite or OpenRead. Set the P2
|
| + ** parameter of the other to pTab->tnum. */
|
| + sqlite3VdbeChangeToNoop(v, 3 - flags);
|
| + sqlite3VdbeChangeP2(v, 2 + flags, pTab->tnum);
|
| + sqlite3VdbeChangeP3(v, 2 + flags, iDb);
|
| +
|
| + /* Configure the number of columns. Configure the cursor to
|
| + ** think that the table has one more column than it really
|
| + ** does. An OP_Column to retrieve this imaginary column will
|
| + ** always return an SQL NULL. This is useful because it means
|
| + ** we can invoke OP_Column to fill in the vdbe cursors type
|
| + ** and offset cache without causing any IO.
|
| + */
|
| + sqlite3VdbeChangeP4(v, 2+flags, SQLITE_INT_TO_PTR(pTab->nCol+1),P4_INT32);
|
| + sqlite3VdbeChangeP2(v, 6, pTab->nCol);
|
| + if( !db->mallocFailed ){
|
| + pParse->nVar = 1;
|
| + pParse->nMem = 1;
|
| + pParse->nTab = 1;
|
| + sqlite3VdbeMakeReady(v, pParse);
|
| + }
|
| + }
|
| +
|
| + pBlob->flags = flags;
|
| + pBlob->iCol = iCol;
|
| + pBlob->db = db;
|
| + sqlite3BtreeLeaveAll(db);
|
| + if( db->mallocFailed ){
|
| + goto blob_open_out;
|
| + }
|
| + sqlite3_bind_int64(pBlob->pStmt, 1, iRow);
|
| + rc = blobSeekToRow(pBlob, iRow, &zErr);
|
| + } while( (++nAttempt)<SQLITE_MAX_SCHEMA_RETRY && rc==SQLITE_SCHEMA );
|
| +
|
| +blob_open_out:
|
| + if( rc==SQLITE_OK && db->mallocFailed==0 ){
|
| + *ppBlob = (sqlite3_blob *)pBlob;
|
| + }else{
|
| + if( pBlob && pBlob->pStmt ) sqlite3VdbeFinalize((Vdbe *)pBlob->pStmt);
|
| + sqlite3DbFree(db, pBlob);
|
| + }
|
| + sqlite3ErrorWithMsg(db, rc, (zErr ? "%s" : 0), zErr);
|
| + sqlite3DbFree(db, zErr);
|
| + sqlite3ParserReset(pParse);
|
| + sqlite3StackFree(db, pParse);
|
| + rc = sqlite3ApiExit(db, rc);
|
| + sqlite3_mutex_leave(db->mutex);
|
| + return rc;
|
| +}
|
| +
|
| +/*
|
| +** Close a blob handle that was previously created using
|
| +** sqlite3_blob_open().
|
| +*/
|
| +SQLITE_API int SQLITE_STDCALL sqlite3_blob_close(sqlite3_blob *pBlob){
|
| + Incrblob *p = (Incrblob *)pBlob;
|
| + int rc;
|
| + sqlite3 *db;
|
| +
|
| + if( p ){
|
| + db = p->db;
|
| + sqlite3_mutex_enter(db->mutex);
|
| + rc = sqlite3_finalize(p->pStmt);
|
| + sqlite3DbFree(db, p);
|
| + sqlite3_mutex_leave(db->mutex);
|
| + }else{
|
| + rc = SQLITE_OK;
|
| + }
|
| + return rc;
|
| +}
|
| +
|
| +/*
|
| +** Perform a read or write operation on a blob
|
| +*/
|
| +static int blobReadWrite(
|
| + sqlite3_blob *pBlob,
|
| + void *z,
|
| + int n,
|
| + int iOffset,
|
| + int (*xCall)(BtCursor*, u32, u32, void*)
|
| +){
|
| + int rc;
|
| + Incrblob *p = (Incrblob *)pBlob;
|
| + Vdbe *v;
|
| + sqlite3 *db;
|
| +
|
| + if( p==0 ) return SQLITE_MISUSE_BKPT;
|
| + db = p->db;
|
| + sqlite3_mutex_enter(db->mutex);
|
| + v = (Vdbe*)p->pStmt;
|
| +
|
| + if( n<0 || iOffset<0 || ((sqlite3_int64)iOffset+n)>p->nByte ){
|
| + /* Request is out of range. Return a transient error. */
|
| + rc = SQLITE_ERROR;
|
| + }else if( v==0 ){
|
| + /* If there is no statement handle, then the blob-handle has
|
| + ** already been invalidated. Return SQLITE_ABORT in this case.
|
| + */
|
| + rc = SQLITE_ABORT;
|
| + }else{
|
| + /* Call either BtreeData() or BtreePutData(). If SQLITE_ABORT is
|
| + ** returned, clean-up the statement handle.
|
| + */
|
| + assert( db == v->db );
|
| + sqlite3BtreeEnterCursor(p->pCsr);
|
| + rc = xCall(p->pCsr, iOffset+p->iOffset, n, z);
|
| + sqlite3BtreeLeaveCursor(p->pCsr);
|
| + if( rc==SQLITE_ABORT ){
|
| + sqlite3VdbeFinalize(v);
|
| + p->pStmt = 0;
|
| + }else{
|
| + v->rc = rc;
|
| + }
|
| + }
|
| + sqlite3Error(db, rc);
|
| + rc = sqlite3ApiExit(db, rc);
|
| + sqlite3_mutex_leave(db->mutex);
|
| + return rc;
|
| +}
|
| +
|
| +/*
|
| +** Read data from a blob handle.
|
| +*/
|
| +SQLITE_API int SQLITE_STDCALL sqlite3_blob_read(sqlite3_blob *pBlob, void *z, int n, int iOffset){
|
| + return blobReadWrite(pBlob, z, n, iOffset, sqlite3BtreeData);
|
| +}
|
| +
|
| +/*
|
| +** Write data to a blob handle.
|
| +*/
|
| +SQLITE_API int SQLITE_STDCALL sqlite3_blob_write(sqlite3_blob *pBlob, const void *z, int n, int iOffset){
|
| + return blobReadWrite(pBlob, (void *)z, n, iOffset, sqlite3BtreePutData);
|
| +}
|
| +
|
| +/*
|
| +** Query a blob handle for the size of the data.
|
| +**
|
| +** The Incrblob.nByte field is fixed for the lifetime of the Incrblob
|
| +** so no mutex is required for access.
|
| +*/
|
| +SQLITE_API int SQLITE_STDCALL sqlite3_blob_bytes(sqlite3_blob *pBlob){
|
| + Incrblob *p = (Incrblob *)pBlob;
|
| + return (p && p->pStmt) ? p->nByte : 0;
|
| +}
|
| +
|
| +/*
|
| +** Move an existing blob handle to point to a different row of the same
|
| +** database table.
|
| +**
|
| +** If an error occurs, or if the specified row does not exist or does not
|
| +** contain a blob or text value, then an error code is returned and the
|
| +** database handle error code and message set. If this happens, then all
|
| +** subsequent calls to sqlite3_blob_xxx() functions (except blob_close())
|
| +** immediately return SQLITE_ABORT.
|
| +*/
|
| +SQLITE_API int SQLITE_STDCALL sqlite3_blob_reopen(sqlite3_blob *pBlob, sqlite3_int64 iRow){
|
| + int rc;
|
| + Incrblob *p = (Incrblob *)pBlob;
|
| + sqlite3 *db;
|
| +
|
| + if( p==0 ) return SQLITE_MISUSE_BKPT;
|
| + db = p->db;
|
| + sqlite3_mutex_enter(db->mutex);
|
| +
|
| + if( p->pStmt==0 ){
|
| + /* If there is no statement handle, then the blob-handle has
|
| + ** already been invalidated. Return SQLITE_ABORT in this case.
|
| + */
|
| + rc = SQLITE_ABORT;
|
| + }else{
|
| + char *zErr;
|
| + rc = blobSeekToRow(p, iRow, &zErr);
|
| + if( rc!=SQLITE_OK ){
|
| + sqlite3ErrorWithMsg(db, rc, (zErr ? "%s" : 0), zErr);
|
| + sqlite3DbFree(db, zErr);
|
| + }
|
| + assert( rc!=SQLITE_SCHEMA );
|
| + }
|
| +
|
| + rc = sqlite3ApiExit(db, rc);
|
| + assert( rc==SQLITE_OK || p->pStmt==0 );
|
| + sqlite3_mutex_leave(db->mutex);
|
| + return rc;
|
| +}
|
| +
|
| +#endif /* #ifndef SQLITE_OMIT_INCRBLOB */
|
| +
|
| +/************** End of vdbeblob.c ********************************************/
|
| +/************** Begin file vdbesort.c ****************************************/
|
| +/*
|
| +** 2011-07-09
|
| +**
|
| +** 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.
|
| +**
|
| +*************************************************************************
|
| +** This file contains code for the VdbeSorter object, used in concert with
|
| +** a VdbeCursor to sort large numbers of keys for CREATE INDEX statements
|
| +** or by SELECT statements with ORDER BY clauses that cannot be satisfied
|
| +** using indexes and without LIMIT clauses.
|
| +**
|
| +** The VdbeSorter object implements a multi-threaded external merge sort
|
| +** algorithm that is efficient even if the number of elements being sorted
|
| +** exceeds the available memory.
|
| +**
|
| +** Here is the (internal, non-API) interface between this module and the
|
| +** rest of the SQLite system:
|
| +**
|
| +** sqlite3VdbeSorterInit() Create a new VdbeSorter object.
|
| +**
|
| +** sqlite3VdbeSorterWrite() Add a single new row to the VdbeSorter
|
| +** object. The row is a binary blob in the
|
| +** OP_MakeRecord format that contains both
|
| +** the ORDER BY key columns and result columns
|
| +** in the case of a SELECT w/ ORDER BY, or
|
| +** the complete record for an index entry
|
| +** in the case of a CREATE INDEX.
|
| +**
|
| +** sqlite3VdbeSorterRewind() Sort all content previously added.
|
| +** Position the read cursor on the
|
| +** first sorted element.
|
| +**
|
| +** sqlite3VdbeSorterNext() Advance the read cursor to the next sorted
|
| +** element.
|
| +**
|
| +** sqlite3VdbeSorterRowkey() Return the complete binary blob for the
|
| +** row currently under the read cursor.
|
| +**
|
| +** sqlite3VdbeSorterCompare() Compare the binary blob for the row
|
| +** currently under the read cursor against
|
| +** another binary blob X and report if
|
| +** X is strictly less than the read cursor.
|
| +** Used to enforce uniqueness in a
|
| +** CREATE UNIQUE INDEX statement.
|
| +**
|
| +** sqlite3VdbeSorterClose() Close the VdbeSorter object and reclaim
|
| +** all resources.
|
| +**
|
| +** sqlite3VdbeSorterReset() Refurbish the VdbeSorter for reuse. This
|
| +** is like Close() followed by Init() only
|
| +** much faster.
|
| +**
|
| +** The interfaces above must be called in a particular order. Write() can
|
| +** only occur in between Init()/Reset() and Rewind(). Next(), Rowkey(), and
|
| +** Compare() can only occur in between Rewind() and Close()/Reset(). i.e.
|
| +**
|
| +** Init()
|
| +** for each record: Write()
|
| +** Rewind()
|
| +** Rowkey()/Compare()
|
| +** Next()
|
| +** Close()
|
| +**
|
| +** Algorithm:
|
| +**
|
| +** Records passed to the sorter via calls to Write() are initially held
|
| +** unsorted in main memory. Assuming the amount of memory used never exceeds
|
| +** a threshold, when Rewind() is called the set of records is sorted using
|
| +** an in-memory merge sort. In this case, no temporary files are required
|
| +** and subsequent calls to Rowkey(), Next() and Compare() read records
|
| +** directly from main memory.
|
| +**
|
| +** If the amount of space used to store records in main memory exceeds the
|
| +** threshold, then the set of records currently in memory are sorted and
|
| +** written to a temporary file in "Packed Memory Array" (PMA) format.
|
| +** A PMA created at this point is known as a "level-0 PMA". Higher levels
|
| +** of PMAs may be created by merging existing PMAs together - for example
|
| +** merging two or more level-0 PMAs together creates a level-1 PMA.
|
| +**
|
| +** The threshold for the amount of main memory to use before flushing
|
| +** records to a PMA is roughly the same as the limit configured for the
|
| +** page-cache of the main database. Specifically, the threshold is set to
|
| +** the value returned by "PRAGMA main.page_size" multipled by
|
| +** that returned by "PRAGMA main.cache_size", in bytes.
|
| +**
|
| +** If the sorter is running in single-threaded mode, then all PMAs generated
|
| +** are appended to a single temporary file. Or, if the sorter is running in
|
| +** multi-threaded mode then up to (N+1) temporary files may be opened, where
|
| +** N is the configured number of worker threads. In this case, instead of
|
| +** sorting the records and writing the PMA to a temporary file itself, the
|
| +** calling thread usually launches a worker thread to do so. Except, if
|
| +** there are already N worker threads running, the main thread does the work
|
| +** itself.
|
| +**
|
| +** The sorter is running in multi-threaded mode if (a) the library was built
|
| +** with pre-processor symbol SQLITE_MAX_WORKER_THREADS set to a value greater
|
| +** than zero, and (b) worker threads have been enabled at runtime by calling
|
| +** "PRAGMA threads=N" with some value of N greater than 0.
|
| +**
|
| +** When Rewind() is called, any data remaining in memory is flushed to a
|
| +** final PMA. So at this point the data is stored in some number of sorted
|
| +** PMAs within temporary files on disk.
|
| +**
|
| +** If there are fewer than SORTER_MAX_MERGE_COUNT PMAs in total and the
|
| +** sorter is running in single-threaded mode, then these PMAs are merged
|
| +** incrementally as keys are retreived from the sorter by the VDBE. The
|
| +** MergeEngine object, described in further detail below, performs this
|
| +** merge.
|
| +**
|
| +** Or, if running in multi-threaded mode, then a background thread is
|
| +** launched to merge the existing PMAs. Once the background thread has
|
| +** merged T bytes of data into a single sorted PMA, the main thread
|
| +** begins reading keys from that PMA while the background thread proceeds
|
| +** with merging the next T bytes of data. And so on.
|
| +**
|
| +** Parameter T is set to half the value of the memory threshold used
|
| +** by Write() above to determine when to create a new PMA.
|
| +**
|
| +** If there are more than SORTER_MAX_MERGE_COUNT PMAs in total when
|
| +** Rewind() is called, then a hierarchy of incremental-merges is used.
|
| +** First, T bytes of data from the first SORTER_MAX_MERGE_COUNT PMAs on
|
| +** disk are merged together. Then T bytes of data from the second set, and
|
| +** so on, such that no operation ever merges more than SORTER_MAX_MERGE_COUNT
|
| +** PMAs at a time. This done is to improve locality.
|
| +**
|
| +** If running in multi-threaded mode and there are more than
|
| +** SORTER_MAX_MERGE_COUNT PMAs on disk when Rewind() is called, then more
|
| +** than one background thread may be created. Specifically, there may be
|
| +** one background thread for each temporary file on disk, and one background
|
| +** thread to merge the output of each of the others to a single PMA for
|
| +** the main thread to read from.
|
| +*/
|
| +/* #include "sqliteInt.h" */
|
| +/* #include "vdbeInt.h" */
|
| +
|
| +/*
|
| +** If SQLITE_DEBUG_SORTER_THREADS is defined, this module outputs various
|
| +** messages to stderr that may be helpful in understanding the performance
|
| +** characteristics of the sorter in multi-threaded mode.
|
| +*/
|
| +#if 0
|
| +# define SQLITE_DEBUG_SORTER_THREADS 1
|
| +#endif
|
| +
|
| +/*
|
| +** Hard-coded maximum amount of data to accumulate in memory before flushing
|
| +** to a level 0 PMA. The purpose of this limit is to prevent various integer
|
| +** overflows. 512MiB.
|
| +*/
|
| +#define SQLITE_MAX_PMASZ (1<<29)
|
| +
|
| +/*
|
| +** Private objects used by the sorter
|
| +*/
|
| +typedef struct MergeEngine MergeEngine; /* Merge PMAs together */
|
| +typedef struct PmaReader PmaReader; /* Incrementally read one PMA */
|
| +typedef struct PmaWriter PmaWriter; /* Incrementally write one PMA */
|
| +typedef struct SorterRecord SorterRecord; /* A record being sorted */
|
| +typedef struct SortSubtask SortSubtask; /* A sub-task in the sort process */
|
| +typedef struct SorterFile SorterFile; /* Temporary file object wrapper */
|
| +typedef struct SorterList SorterList; /* In-memory list of records */
|
| +typedef struct IncrMerger IncrMerger; /* Read & merge multiple PMAs */
|
| +
|
| +/*
|
| +** A container for a temp file handle and the current amount of data
|
| +** stored in the file.
|
| +*/
|
| +struct SorterFile {
|
| + sqlite3_file *pFd; /* File handle */
|
| + i64 iEof; /* Bytes of data stored in pFd */
|
| +};
|
| +
|
| +/*
|
| +** An in-memory list of objects to be sorted.
|
| +**
|
| +** If aMemory==0 then each object is allocated separately and the objects
|
| +** are connected using SorterRecord.u.pNext. If aMemory!=0 then all objects
|
| +** are stored in the aMemory[] bulk memory, one right after the other, and
|
| +** are connected using SorterRecord.u.iNext.
|
| +*/
|
| +struct SorterList {
|
| + SorterRecord *pList; /* Linked list of records */
|
| + u8 *aMemory; /* If non-NULL, bulk memory to hold pList */
|
| + int szPMA; /* Size of pList as PMA in bytes */
|
| +};
|
| +
|
| +/*
|
| +** The MergeEngine object is used to combine two or more smaller PMAs into
|
| +** one big PMA using a merge operation. Separate PMAs all need to be
|
| +** combined into one big PMA in order to be able to step through the sorted
|
| +** records in order.
|
| +**
|
| +** The aReadr[] array contains a PmaReader object for each of the PMAs being
|
| +** merged. An aReadr[] object either points to a valid key or else is at EOF.
|
| +** ("EOF" means "End Of File". When aReadr[] is at EOF there is no more data.)
|
| +** For the purposes of the paragraphs below, we assume that the array is
|
| +** actually N elements in size, where N is the smallest power of 2 greater
|
| +** to or equal to the number of PMAs being merged. The extra aReadr[] elements
|
| +** are treated as if they are empty (always at EOF).
|
| +**
|
| +** The aTree[] array is also N elements in size. The value of N is stored in
|
| +** the MergeEngine.nTree variable.
|
| +**
|
| +** The final (N/2) elements of aTree[] contain the results of comparing
|
| +** pairs of PMA keys together. Element i contains the result of
|
| +** comparing aReadr[2*i-N] and aReadr[2*i-N+1]. Whichever key is smaller, the
|
| +** aTree element is set to the index of it.
|
| +**
|
| +** For the purposes of this comparison, EOF is considered greater than any
|
| +** other key value. If the keys are equal (only possible with two EOF
|
| +** values), it doesn't matter which index is stored.
|
| +**
|
| +** The (N/4) elements of aTree[] that precede the final (N/2) described
|
| +** above contains the index of the smallest of each block of 4 PmaReaders
|
| +** And so on. So that aTree[1] contains the index of the PmaReader that
|
| +** currently points to the smallest key value. aTree[0] is unused.
|
| +**
|
| +** Example:
|
| +**
|
| +** aReadr[0] -> Banana
|
| +** aReadr[1] -> Feijoa
|
| +** aReadr[2] -> Elderberry
|
| +** aReadr[3] -> Currant
|
| +** aReadr[4] -> Grapefruit
|
| +** aReadr[5] -> Apple
|
| +** aReadr[6] -> Durian
|
| +** aReadr[7] -> EOF
|
| +**
|
| +** aTree[] = { X, 5 0, 5 0, 3, 5, 6 }
|
| +**
|
| +** The current element is "Apple" (the value of the key indicated by
|
| +** PmaReader 5). When the Next() operation is invoked, PmaReader 5 will
|
| +** be advanced to the next key in its segment. Say the next key is
|
| +** "Eggplant":
|
| +**
|
| +** aReadr[5] -> Eggplant
|
| +**
|
| +** The contents of aTree[] are updated first by comparing the new PmaReader
|
| +** 5 key to the current key of PmaReader 4 (still "Grapefruit"). The PmaReader
|
| +** 5 value is still smaller, so aTree[6] is set to 5. And so on up the tree.
|
| +** The value of PmaReader 6 - "Durian" - is now smaller than that of PmaReader
|
| +** 5, so aTree[3] is set to 6. Key 0 is smaller than key 6 (Banana<Durian),
|
| +** so the value written into element 1 of the array is 0. As follows:
|
| +**
|
| +** aTree[] = { X, 0 0, 6 0, 3, 5, 6 }
|
| +**
|
| +** In other words, each time we advance to the next sorter element, log2(N)
|
| +** key comparison operations are required, where N is the number of segments
|
| +** being merged (rounded up to the next power of 2).
|
| +*/
|
| +struct MergeEngine {
|
| + int nTree; /* Used size of aTree/aReadr (power of 2) */
|
| + SortSubtask *pTask; /* Used by this thread only */
|
| + int *aTree; /* Current state of incremental merge */
|
| + PmaReader *aReadr; /* Array of PmaReaders to merge data from */
|
| +};
|
| +
|
| +/*
|
| +** This object represents a single thread of control in a sort operation.
|
| +** Exactly VdbeSorter.nTask instances of this object are allocated
|
| +** as part of each VdbeSorter object. Instances are never allocated any
|
| +** other way. VdbeSorter.nTask is set to the number of worker threads allowed
|
| +** (see SQLITE_CONFIG_WORKER_THREADS) plus one (the main thread). Thus for
|
| +** single-threaded operation, there is exactly one instance of this object
|
| +** and for multi-threaded operation there are two or more instances.
|
| +**
|
| +** Essentially, this structure contains all those fields of the VdbeSorter
|
| +** structure for which each thread requires a separate instance. For example,
|
| +** each thread requries its own UnpackedRecord object to unpack records in
|
| +** as part of comparison operations.
|
| +**
|
| +** Before a background thread is launched, variable bDone is set to 0. Then,
|
| +** right before it exits, the thread itself sets bDone to 1. This is used for
|
| +** two purposes:
|
| +**
|
| +** 1. When flushing the contents of memory to a level-0 PMA on disk, to
|
| +** attempt to select a SortSubtask for which there is not already an
|
| +** active background thread (since doing so causes the main thread
|
| +** to block until it finishes).
|
| +**
|
| +** 2. If SQLITE_DEBUG_SORTER_THREADS is defined, to determine if a call
|
| +** to sqlite3ThreadJoin() is likely to block. Cases that are likely to
|
| +** block provoke debugging output.
|
| +**
|
| +** In both cases, the effects of the main thread seeing (bDone==0) even
|
| +** after the thread has finished are not dire. So we don't worry about
|
| +** memory barriers and such here.
|
| +*/
|
| +typedef int (*SorterCompare)(SortSubtask*,int*,const void*,int,const void*,int);
|
| +struct SortSubtask {
|
| + SQLiteThread *pThread; /* Background thread, if any */
|
| + int bDone; /* Set if thread is finished but not joined */
|
| + VdbeSorter *pSorter; /* Sorter that owns this sub-task */
|
| + UnpackedRecord *pUnpacked; /* Space to unpack a record */
|
| + SorterList list; /* List for thread to write to a PMA */
|
| + int nPMA; /* Number of PMAs currently in file */
|
| + SorterCompare xCompare; /* Compare function to use */
|
| + SorterFile file; /* Temp file for level-0 PMAs */
|
| + SorterFile file2; /* Space for other PMAs */
|
| +};
|
| +
|
| +
|
| +/*
|
| +** Main sorter structure. A single instance of this is allocated for each
|
| +** sorter cursor created by the VDBE.
|
| +**
|
| +** mxKeysize:
|
| +** As records are added to the sorter by calls to sqlite3VdbeSorterWrite(),
|
| +** this variable is updated so as to be set to the size on disk of the
|
| +** largest record in the sorter.
|
| +*/
|
| +struct VdbeSorter {
|
| + int mnPmaSize; /* Minimum PMA size, in bytes */
|
| + int mxPmaSize; /* Maximum PMA size, in bytes. 0==no limit */
|
| + int mxKeysize; /* Largest serialized key seen so far */
|
| + int pgsz; /* Main database page size */
|
| + PmaReader *pReader; /* Readr data from here after Rewind() */
|
| + MergeEngine *pMerger; /* Or here, if bUseThreads==0 */
|
| + sqlite3 *db; /* Database connection */
|
| + KeyInfo *pKeyInfo; /* How to compare records */
|
| + UnpackedRecord *pUnpacked; /* Used by VdbeSorterCompare() */
|
| + SorterList list; /* List of in-memory records */
|
| + int iMemory; /* Offset of free space in list.aMemory */
|
| + int nMemory; /* Size of list.aMemory allocation in bytes */
|
| + u8 bUsePMA; /* True if one or more PMAs created */
|
| + u8 bUseThreads; /* True to use background threads */
|
| + u8 iPrev; /* Previous thread used to flush PMA */
|
| + u8 nTask; /* Size of aTask[] array */
|
| + u8 typeMask;
|
| + SortSubtask aTask[1]; /* One or more subtasks */
|
| +};
|
| +
|
| +#define SORTER_TYPE_INTEGER 0x01
|
| +#define SORTER_TYPE_TEXT 0x02
|
| +
|
| +/*
|
| +** An instance of the following object is used to read records out of a
|
| +** PMA, in sorted order. The next key to be read is cached in nKey/aKey.
|
| +** aKey might point into aMap or into aBuffer. If neither of those locations
|
| +** contain a contiguous representation of the key, then aAlloc is allocated
|
| +** and the key is copied into aAlloc and aKey is made to poitn to aAlloc.
|
| +**
|
| +** pFd==0 at EOF.
|
| +*/
|
| +struct PmaReader {
|
| + i64 iReadOff; /* Current read offset */
|
| + i64 iEof; /* 1 byte past EOF for this PmaReader */
|
| + int nAlloc; /* Bytes of space at aAlloc */
|
| + int nKey; /* Number of bytes in key */
|
| + sqlite3_file *pFd; /* File handle we are reading from */
|
| + u8 *aAlloc; /* Space for aKey if aBuffer and pMap wont work */
|
| + u8 *aKey; /* Pointer to current key */
|
| + u8 *aBuffer; /* Current read buffer */
|
| + int nBuffer; /* Size of read buffer in bytes */
|
| + u8 *aMap; /* Pointer to mapping of entire file */
|
| + IncrMerger *pIncr; /* Incremental merger */
|
| +};
|
| +
|
| +/*
|
| +** Normally, a PmaReader object iterates through an existing PMA stored
|
| +** within a temp file. However, if the PmaReader.pIncr variable points to
|
| +** an object of the following type, it may be used to iterate/merge through
|
| +** multiple PMAs simultaneously.
|
| +**
|
| +** There are two types of IncrMerger object - single (bUseThread==0) and
|
| +** multi-threaded (bUseThread==1).
|
| +**
|
| +** A multi-threaded IncrMerger object uses two temporary files - aFile[0]
|
| +** and aFile[1]. Neither file is allowed to grow to more than mxSz bytes in
|
| +** size. When the IncrMerger is initialized, it reads enough data from
|
| +** pMerger to populate aFile[0]. It then sets variables within the
|
| +** corresponding PmaReader object to read from that file and kicks off
|
| +** a background thread to populate aFile[1] with the next mxSz bytes of
|
| +** sorted record data from pMerger.
|
| +**
|
| +** When the PmaReader reaches the end of aFile[0], it blocks until the
|
| +** background thread has finished populating aFile[1]. It then exchanges
|
| +** the contents of the aFile[0] and aFile[1] variables within this structure,
|
| +** sets the PmaReader fields to read from the new aFile[0] and kicks off
|
| +** another background thread to populate the new aFile[1]. And so on, until
|
| +** the contents of pMerger are exhausted.
|
| +**
|
| +** A single-threaded IncrMerger does not open any temporary files of its
|
| +** own. Instead, it has exclusive access to mxSz bytes of space beginning
|
| +** at offset iStartOff of file pTask->file2. And instead of using a
|
| +** background thread to prepare data for the PmaReader, with a single
|
| +** threaded IncrMerger the allocate part of pTask->file2 is "refilled" with
|
| +** keys from pMerger by the calling thread whenever the PmaReader runs out
|
| +** of data.
|
| +*/
|
| +struct IncrMerger {
|
| + SortSubtask *pTask; /* Task that owns this merger */
|
| + MergeEngine *pMerger; /* Merge engine thread reads data from */
|
| + i64 iStartOff; /* Offset to start writing file at */
|
| + int mxSz; /* Maximum bytes of data to store */
|
| + int bEof; /* Set to true when merge is finished */
|
| + int bUseThread; /* True to use a bg thread for this object */
|
| + SorterFile aFile[2]; /* aFile[0] for reading, [1] for writing */
|
| +};
|
| +
|
| +/*
|
| +** An instance of this object is used for writing a PMA.
|
| +**
|
| +** The PMA is written one record at a time. Each record is of an arbitrary
|
| +** size. But I/O is more efficient if it occurs in page-sized blocks where
|
| +** each block is aligned on a page boundary. This object caches writes to
|
| +** the PMA so that aligned, page-size blocks are written.
|
| +*/
|
| +struct PmaWriter {
|
| + int eFWErr; /* Non-zero if in an error state */
|
| + u8 *aBuffer; /* Pointer to write buffer */
|
| + int nBuffer; /* Size of write buffer in bytes */
|
| + int iBufStart; /* First byte of buffer to write */
|
| + int iBufEnd; /* Last byte of buffer to write */
|
| + i64 iWriteOff; /* Offset of start of buffer in file */
|
| + sqlite3_file *pFd; /* File handle to write to */
|
| +};
|
| +
|
| +/*
|
| +** This object is the header on a single record while that record is being
|
| +** held in memory and prior to being written out as part of a PMA.
|
| +**
|
| +** How the linked list is connected depends on how memory is being managed
|
| +** by this module. If using a separate allocation for each in-memory record
|
| +** (VdbeSorter.list.aMemory==0), then the list is always connected using the
|
| +** SorterRecord.u.pNext pointers.
|
| +**
|
| +** Or, if using the single large allocation method (VdbeSorter.list.aMemory!=0),
|
| +** then while records are being accumulated the list is linked using the
|
| +** SorterRecord.u.iNext offset. This is because the aMemory[] array may
|
| +** be sqlite3Realloc()ed while records are being accumulated. Once the VM
|
| +** has finished passing records to the sorter, or when the in-memory buffer
|
| +** is full, the list is sorted. As part of the sorting process, it is
|
| +** converted to use the SorterRecord.u.pNext pointers. See function
|
| +** vdbeSorterSort() for details.
|
| +*/
|
| +struct SorterRecord {
|
| + int nVal; /* Size of the record in bytes */
|
| + union {
|
| + SorterRecord *pNext; /* Pointer to next record in list */
|
| + int iNext; /* Offset within aMemory of next record */
|
| + } u;
|
| + /* The data for the record immediately follows this header */
|
| +};
|
| +
|
| +/* Return a pointer to the buffer containing the record data for SorterRecord
|
| +** object p. Should be used as if:
|
| +**
|
| +** void *SRVAL(SorterRecord *p) { return (void*)&p[1]; }
|
| +*/
|
| +#define SRVAL(p) ((void*)((SorterRecord*)(p) + 1))
|
| +
|
| +
|
| +/* Maximum number of PMAs that a single MergeEngine can merge */
|
| +#define SORTER_MAX_MERGE_COUNT 16
|
| +
|
| +static int vdbeIncrSwap(IncrMerger*);
|
| +static void vdbeIncrFree(IncrMerger *);
|
| +
|
| +/*
|
| +** Free all memory belonging to the PmaReader object passed as the
|
| +** argument. All structure fields are set to zero before returning.
|
| +*/
|
| +static void vdbePmaReaderClear(PmaReader *pReadr){
|
| + sqlite3_free(pReadr->aAlloc);
|
| + sqlite3_free(pReadr->aBuffer);
|
| + if( pReadr->aMap ) sqlite3OsUnfetch(pReadr->pFd, 0, pReadr->aMap);
|
| + vdbeIncrFree(pReadr->pIncr);
|
| + memset(pReadr, 0, sizeof(PmaReader));
|
| +}
|
| +
|
| +/*
|
| +** Read the next nByte bytes of data from the PMA p.
|
| +** If successful, set *ppOut to point to a buffer containing the data
|
| +** and return SQLITE_OK. Otherwise, if an error occurs, return an SQLite
|
| +** error code.
|
| +**
|
| +** The buffer returned in *ppOut is only valid until the
|
| +** next call to this function.
|
| +*/
|
| +static int vdbePmaReadBlob(
|
| + PmaReader *p, /* PmaReader from which to take the blob */
|
| + int nByte, /* Bytes of data to read */
|
| + u8 **ppOut /* OUT: Pointer to buffer containing data */
|
| +){
|
| + int iBuf; /* Offset within buffer to read from */
|
| + int nAvail; /* Bytes of data available in buffer */
|
| +
|
| + if( p->aMap ){
|
| + *ppOut = &p->aMap[p->iReadOff];
|
| + p->iReadOff += nByte;
|
| + return SQLITE_OK;
|
| + }
|
| +
|
| + assert( p->aBuffer );
|
| +
|
| + /* If there is no more data to be read from the buffer, read the next
|
| + ** p->nBuffer bytes of data from the file into it. Or, if there are less
|
| + ** than p->nBuffer bytes remaining in the PMA, read all remaining data. */
|
| + iBuf = p->iReadOff % p->nBuffer;
|
| + if( iBuf==0 ){
|
| + int nRead; /* Bytes to read from disk */
|
| + int rc; /* sqlite3OsRead() return code */
|
| +
|
| + /* Determine how many bytes of data to read. */
|
| + if( (p->iEof - p->iReadOff) > (i64)p->nBuffer ){
|
| + nRead = p->nBuffer;
|
| + }else{
|
| + nRead = (int)(p->iEof - p->iReadOff);
|
| + }
|
| + assert( nRead>0 );
|
| +
|
| + /* Readr data from the file. Return early if an error occurs. */
|
| + rc = sqlite3OsRead(p->pFd, p->aBuffer, nRead, p->iReadOff);
|
| + assert( rc!=SQLITE_IOERR_SHORT_READ );
|
| + if( rc!=SQLITE_OK ) return rc;
|
| + }
|
| + nAvail = p->nBuffer - iBuf;
|
| +
|
| + if( nByte<=nAvail ){
|
| + /* The requested data is available in the in-memory buffer. In this
|
| + ** case there is no need to make a copy of the data, just return a
|
| + ** pointer into the buffer to the caller. */
|
| + *ppOut = &p->aBuffer[iBuf];
|
| + p->iReadOff += nByte;
|
| + }else{
|
| + /* The requested data is not all available in the in-memory buffer.
|
| + ** In this case, allocate space at p->aAlloc[] to copy the requested
|
| + ** range into. Then return a copy of pointer p->aAlloc to the caller. */
|
| + int nRem; /* Bytes remaining to copy */
|
| +
|
| + /* Extend the p->aAlloc[] allocation if required. */
|
| + if( p->nAlloc<nByte ){
|
| + u8 *aNew;
|
| + int nNew = MAX(128, p->nAlloc*2);
|
| + while( nByte>nNew ) nNew = nNew*2;
|
| + aNew = sqlite3Realloc(p->aAlloc, nNew);
|
| + if( !aNew ) return SQLITE_NOMEM;
|
| + p->nAlloc = nNew;
|
| + p->aAlloc = aNew;
|
| + }
|
| +
|
| + /* Copy as much data as is available in the buffer into the start of
|
| + ** p->aAlloc[]. */
|
| + memcpy(p->aAlloc, &p->aBuffer[iBuf], nAvail);
|
| + p->iReadOff += nAvail;
|
| + nRem = nByte - nAvail;
|
| +
|
| + /* The following loop copies up to p->nBuffer bytes per iteration into
|
| + ** the p->aAlloc[] buffer. */
|
| + while( nRem>0 ){
|
| + int rc; /* vdbePmaReadBlob() return code */
|
| + int nCopy; /* Number of bytes to copy */
|
| + u8 *aNext; /* Pointer to buffer to copy data from */
|
| +
|
| + nCopy = nRem;
|
| + if( nRem>p->nBuffer ) nCopy = p->nBuffer;
|
| + rc = vdbePmaReadBlob(p, nCopy, &aNext);
|
| + if( rc!=SQLITE_OK ) return rc;
|
| + assert( aNext!=p->aAlloc );
|
| + memcpy(&p->aAlloc[nByte - nRem], aNext, nCopy);
|
| + nRem -= nCopy;
|
| + }
|
| +
|
| + *ppOut = p->aAlloc;
|
| + }
|
| +
|
| + return SQLITE_OK;
|
| +}
|
| +
|
| +/*
|
| +** Read a varint from the stream of data accessed by p. Set *pnOut to
|
| +** the value read.
|
| +*/
|
| +static int vdbePmaReadVarint(PmaReader *p, u64 *pnOut){
|
| + int iBuf;
|
| +
|
| + if( p->aMap ){
|
| + p->iReadOff += sqlite3GetVarint(&p->aMap[p->iReadOff], pnOut);
|
| + }else{
|
| + iBuf = p->iReadOff % p->nBuffer;
|
| + if( iBuf && (p->nBuffer-iBuf)>=9 ){
|
| + p->iReadOff += sqlite3GetVarint(&p->aBuffer[iBuf], pnOut);
|
| + }else{
|
| + u8 aVarint[16], *a;
|
| + int i = 0, rc;
|
| + do{
|
| + rc = vdbePmaReadBlob(p, 1, &a);
|
| + if( rc ) return rc;
|
| + aVarint[(i++)&0xf] = a[0];
|
| + }while( (a[0]&0x80)!=0 );
|
| + sqlite3GetVarint(aVarint, pnOut);
|
| + }
|
| + }
|
| +
|
| + return SQLITE_OK;
|
| +}
|
| +
|
| +/*
|
| +** Attempt to memory map file pFile. If successful, set *pp to point to the
|
| +** new mapping and return SQLITE_OK. If the mapping is not attempted
|
| +** (because the file is too large or the VFS layer is configured not to use
|
| +** mmap), return SQLITE_OK and set *pp to NULL.
|
| +**
|
| +** Or, if an error occurs, return an SQLite error code. The final value of
|
| +** *pp is undefined in this case.
|
| +*/
|
| +static int vdbeSorterMapFile(SortSubtask *pTask, SorterFile *pFile, u8 **pp){
|
| + int rc = SQLITE_OK;
|
| + if( pFile->iEof<=(i64)(pTask->pSorter->db->nMaxSorterMmap) ){
|
| + sqlite3_file *pFd = pFile->pFd;
|
| + if( pFd->pMethods->iVersion>=3 ){
|
| + rc = sqlite3OsFetch(pFd, 0, (int)pFile->iEof, (void**)pp);
|
| + testcase( rc!=SQLITE_OK );
|
| + }
|
| + }
|
| + return rc;
|
| +}
|
| +
|
| +/*
|
| +** Attach PmaReader pReadr to file pFile (if it is not already attached to
|
| +** that file) and seek it to offset iOff within the file. Return SQLITE_OK
|
| +** if successful, or an SQLite error code if an error occurs.
|
| +*/
|
| +static int vdbePmaReaderSeek(
|
| + SortSubtask *pTask, /* Task context */
|
| + PmaReader *pReadr, /* Reader whose cursor is to be moved */
|
| + SorterFile *pFile, /* Sorter file to read from */
|
| + i64 iOff /* Offset in pFile */
|
| +){
|
| + int rc = SQLITE_OK;
|
| +
|
| + assert( pReadr->pIncr==0 || pReadr->pIncr->bEof==0 );
|
| +
|
| + if( sqlite3FaultSim(201) ) return SQLITE_IOERR_READ;
|
| + if( pReadr->aMap ){
|
| + sqlite3OsUnfetch(pReadr->pFd, 0, pReadr->aMap);
|
| + pReadr->aMap = 0;
|
| + }
|
| + pReadr->iReadOff = iOff;
|
| + pReadr->iEof = pFile->iEof;
|
| + pReadr->pFd = pFile->pFd;
|
| +
|
| + rc = vdbeSorterMapFile(pTask, pFile, &pReadr->aMap);
|
| + if( rc==SQLITE_OK && pReadr->aMap==0 ){
|
| + int pgsz = pTask->pSorter->pgsz;
|
| + int iBuf = pReadr->iReadOff % pgsz;
|
| + if( pReadr->aBuffer==0 ){
|
| + pReadr->aBuffer = (u8*)sqlite3Malloc(pgsz);
|
| + if( pReadr->aBuffer==0 ) rc = SQLITE_NOMEM;
|
| + pReadr->nBuffer = pgsz;
|
| + }
|
| + if( rc==SQLITE_OK && iBuf ){
|
| + int nRead = pgsz - iBuf;
|
| + if( (pReadr->iReadOff + nRead) > pReadr->iEof ){
|
| + nRead = (int)(pReadr->iEof - pReadr->iReadOff);
|
| + }
|
| + rc = sqlite3OsRead(
|
| + pReadr->pFd, &pReadr->aBuffer[iBuf], nRead, pReadr->iReadOff
|
| + );
|
| + testcase( rc!=SQLITE_OK );
|
| + }
|
| + }
|
| +
|
| + return rc;
|
| +}
|
| +
|
| +/*
|
| +** Advance PmaReader pReadr to the next key in its PMA. Return SQLITE_OK if
|
| +** no error occurs, or an SQLite error code if one does.
|
| +*/
|
| +static int vdbePmaReaderNext(PmaReader *pReadr){
|
| + int rc = SQLITE_OK; /* Return Code */
|
| + u64 nRec = 0; /* Size of record in bytes */
|
| +
|
| +
|
| + if( pReadr->iReadOff>=pReadr->iEof ){
|
| + IncrMerger *pIncr = pReadr->pIncr;
|
| + int bEof = 1;
|
| + if( pIncr ){
|
| + rc = vdbeIncrSwap(pIncr);
|
| + if( rc==SQLITE_OK && pIncr->bEof==0 ){
|
| + rc = vdbePmaReaderSeek(
|
| + pIncr->pTask, pReadr, &pIncr->aFile[0], pIncr->iStartOff
|
| + );
|
| + bEof = 0;
|
| + }
|
| + }
|
| +
|
| + if( bEof ){
|
| + /* This is an EOF condition */
|
| + vdbePmaReaderClear(pReadr);
|
| + testcase( rc!=SQLITE_OK );
|
| + return rc;
|
| + }
|
| + }
|
| +
|
| + if( rc==SQLITE_OK ){
|
| + rc = vdbePmaReadVarint(pReadr, &nRec);
|
| + }
|
| + if( rc==SQLITE_OK ){
|
| + pReadr->nKey = (int)nRec;
|
| + rc = vdbePmaReadBlob(pReadr, (int)nRec, &pReadr->aKey);
|
| + testcase( rc!=SQLITE_OK );
|
| + }
|
| +
|
| + return rc;
|
| +}
|
| +
|
| +/*
|
| +** Initialize PmaReader pReadr to scan through the PMA stored in file pFile
|
| +** starting at offset iStart and ending at offset iEof-1. This function
|
| +** leaves the PmaReader pointing to the first key in the PMA (or EOF if the
|
| +** PMA is empty).
|
| +**
|
| +** If the pnByte parameter is NULL, then it is assumed that the file
|
| +** contains a single PMA, and that that PMA omits the initial length varint.
|
| +*/
|
| +static int vdbePmaReaderInit(
|
| + SortSubtask *pTask, /* Task context */
|
| + SorterFile *pFile, /* Sorter file to read from */
|
| + i64 iStart, /* Start offset in pFile */
|
| + PmaReader *pReadr, /* PmaReader to populate */
|
| + i64 *pnByte /* IN/OUT: Increment this value by PMA size */
|
| +){
|
| + int rc;
|
| +
|
| + assert( pFile->iEof>iStart );
|
| + assert( pReadr->aAlloc==0 && pReadr->nAlloc==0 );
|
| + assert( pReadr->aBuffer==0 );
|
| + assert( pReadr->aMap==0 );
|
| +
|
| + rc = vdbePmaReaderSeek(pTask, pReadr, pFile, iStart);
|
| + if( rc==SQLITE_OK ){
|
| + u64 nByte; /* Size of PMA in bytes */
|
| + rc = vdbePmaReadVarint(pReadr, &nByte);
|
| + pReadr->iEof = pReadr->iReadOff + nByte;
|
| + *pnByte += nByte;
|
| + }
|
| +
|
| + if( rc==SQLITE_OK ){
|
| + rc = vdbePmaReaderNext(pReadr);
|
| + }
|
| + return rc;
|
| +}
|
| +
|
| +/*
|
| +** A version of vdbeSorterCompare() that assumes that it has already been
|
| +** determined that the first field of key1 is equal to the first field of
|
| +** key2.
|
| +*/
|
| +static int vdbeSorterCompareTail(
|
| + SortSubtask *pTask, /* Subtask context (for pKeyInfo) */
|
| + int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */
|
| + const void *pKey1, int nKey1, /* Left side of comparison */
|
| + const void *pKey2, int nKey2 /* Right side of comparison */
|
| +){
|
| + UnpackedRecord *r2 = pTask->pUnpacked;
|
| + if( *pbKey2Cached==0 ){
|
| + sqlite3VdbeRecordUnpack(pTask->pSorter->pKeyInfo, nKey2, pKey2, r2);
|
| + *pbKey2Cached = 1;
|
| + }
|
| + return sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, r2, 1);
|
| +}
|
| +
|
| +/*
|
| +** Compare key1 (buffer pKey1, size nKey1 bytes) with key2 (buffer pKey2,
|
| +** size nKey2 bytes). Use (pTask->pKeyInfo) for the collation sequences
|
| +** used by the comparison. Return the result of the comparison.
|
| +**
|
| +** If IN/OUT parameter *pbKey2Cached is true when this function is called,
|
| +** it is assumed that (pTask->pUnpacked) contains the unpacked version
|
| +** of key2. If it is false, (pTask->pUnpacked) is populated with the unpacked
|
| +** version of key2 and *pbKey2Cached set to true before returning.
|
| +**
|
| +** If an OOM error is encountered, (pTask->pUnpacked->error_rc) is set
|
| +** to SQLITE_NOMEM.
|
| +*/
|
| +static int vdbeSorterCompare(
|
| + SortSubtask *pTask, /* Subtask context (for pKeyInfo) */
|
| + int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */
|
| + const void *pKey1, int nKey1, /* Left side of comparison */
|
| + const void *pKey2, int nKey2 /* Right side of comparison */
|
| +){
|
| + UnpackedRecord *r2 = pTask->pUnpacked;
|
| + if( !*pbKey2Cached ){
|
| + sqlite3VdbeRecordUnpack(pTask->pSorter->pKeyInfo, nKey2, pKey2, r2);
|
| + *pbKey2Cached = 1;
|
| + }
|
| + return sqlite3VdbeRecordCompare(nKey1, pKey1, r2);
|
| +}
|
| +
|
| +/*
|
| +** A specially optimized version of vdbeSorterCompare() that assumes that
|
| +** the first field of each key is a TEXT value and that the collation
|
| +** sequence to compare them with is BINARY.
|
| +*/
|
| +static int vdbeSorterCompareText(
|
| + SortSubtask *pTask, /* Subtask context (for pKeyInfo) */
|
| + int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */
|
| + const void *pKey1, int nKey1, /* Left side of comparison */
|
| + const void *pKey2, int nKey2 /* Right side of comparison */
|
| +){
|
| + const u8 * const p1 = (const u8 * const)pKey1;
|
| + const u8 * const p2 = (const u8 * const)pKey2;
|
| + const u8 * const v1 = &p1[ p1[0] ]; /* Pointer to value 1 */
|
| + const u8 * const v2 = &p2[ p2[0] ]; /* Pointer to value 2 */
|
| +
|
| + int n1;
|
| + int n2;
|
| + int res;
|
| +
|
| + getVarint32(&p1[1], n1); n1 = (n1 - 13) / 2;
|
| + getVarint32(&p2[1], n2); n2 = (n2 - 13) / 2;
|
| + res = memcmp(v1, v2, MIN(n1, n2));
|
| + if( res==0 ){
|
| + res = n1 - n2;
|
| + }
|
| +
|
| + if( res==0 ){
|
| + if( pTask->pSorter->pKeyInfo->nField>1 ){
|
| + res = vdbeSorterCompareTail(
|
| + pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2
|
| + );
|
| + }
|
| + }else{
|
| + if( pTask->pSorter->pKeyInfo->aSortOrder[0] ){
|
| + res = res * -1;
|
| + }
|
| + }
|
| +
|
| + return res;
|
| +}
|
| +
|
| +/*
|
| +** A specially optimized version of vdbeSorterCompare() that assumes that
|
| +** the first field of each key is an INTEGER value.
|
| +*/
|
| +static int vdbeSorterCompareInt(
|
| + SortSubtask *pTask, /* Subtask context (for pKeyInfo) */
|
| + int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */
|
| + const void *pKey1, int nKey1, /* Left side of comparison */
|
| + const void *pKey2, int nKey2 /* Right side of comparison */
|
| +){
|
| + const u8 * const p1 = (const u8 * const)pKey1;
|
| + const u8 * const p2 = (const u8 * const)pKey2;
|
| + const int s1 = p1[1]; /* Left hand serial type */
|
| + const int s2 = p2[1]; /* Right hand serial type */
|
| + const u8 * const v1 = &p1[ p1[0] ]; /* Pointer to value 1 */
|
| + const u8 * const v2 = &p2[ p2[0] ]; /* Pointer to value 2 */
|
| + int res; /* Return value */
|
| +
|
| + assert( (s1>0 && s1<7) || s1==8 || s1==9 );
|
| + assert( (s2>0 && s2<7) || s2==8 || s2==9 );
|
| +
|
| + if( s1>7 && s2>7 ){
|
| + res = s1 - s2;
|
| + }else{
|
| + if( s1==s2 ){
|
| + if( (*v1 ^ *v2) & 0x80 ){
|
| + /* The two values have different signs */
|
| + res = (*v1 & 0x80) ? -1 : +1;
|
| + }else{
|
| + /* The two values have the same sign. Compare using memcmp(). */
|
| + static const u8 aLen[] = {0, 1, 2, 3, 4, 6, 8 };
|
| + int i;
|
| + res = 0;
|
| + for(i=0; i<aLen[s1]; i++){
|
| + if( (res = v1[i] - v2[i]) ) break;
|
| + }
|
| + }
|
| + }else{
|
| + if( s2>7 ){
|
| + res = +1;
|
| + }else if( s1>7 ){
|
| + res = -1;
|
| + }else{
|
| + res = s1 - s2;
|
| + }
|
| + assert( res!=0 );
|
| +
|
| + if( res>0 ){
|
| + if( *v1 & 0x80 ) res = -1;
|
| + }else{
|
| + if( *v2 & 0x80 ) res = +1;
|
| + }
|
| + }
|
| + }
|
| +
|
| + if( res==0 ){
|
| + if( pTask->pSorter->pKeyInfo->nField>1 ){
|
| + res = vdbeSorterCompareTail(
|
| + pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2
|
| + );
|
| + }
|
| + }else if( pTask->pSorter->pKeyInfo->aSortOrder[0] ){
|
| + res = res * -1;
|
| + }
|
| +
|
| + return res;
|
| +}
|
| +
|
| +/*
|
| +** Initialize the temporary index cursor just opened as a sorter cursor.
|
| +**
|
| +** Usually, the sorter module uses the value of (pCsr->pKeyInfo->nField)
|
| +** to determine the number of fields that should be compared from the
|
| +** records being sorted. However, if the value passed as argument nField
|
| +** is non-zero and the sorter is able to guarantee a stable sort, nField
|
| +** is used instead. This is used when sorting records for a CREATE INDEX
|
| +** statement. In this case, keys are always delivered to the sorter in
|
| +** order of the primary key, which happens to be make up the final part
|
| +** of the records being sorted. So if the sort is stable, there is never
|
| +** any reason to compare PK fields and they can be ignored for a small
|
| +** performance boost.
|
| +**
|
| +** The sorter can guarantee a stable sort when running in single-threaded
|
| +** mode, but not in multi-threaded mode.
|
| +**
|
| +** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3VdbeSorterInit(
|
| + sqlite3 *db, /* Database connection (for malloc()) */
|
| + int nField, /* Number of key fields in each record */
|
| + VdbeCursor *pCsr /* Cursor that holds the new sorter */
|
| +){
|
| + int pgsz; /* Page size of main database */
|
| + int i; /* Used to iterate through aTask[] */
|
| + int mxCache; /* Cache size */
|
| + VdbeSorter *pSorter; /* The new sorter */
|
| + KeyInfo *pKeyInfo; /* Copy of pCsr->pKeyInfo with db==0 */
|
| + int szKeyInfo; /* Size of pCsr->pKeyInfo in bytes */
|
| + int sz; /* Size of pSorter in bytes */
|
| + int rc = SQLITE_OK;
|
| +#if SQLITE_MAX_WORKER_THREADS==0
|
| +# define nWorker 0
|
| +#else
|
| + int nWorker;
|
| +#endif
|
| +
|
| + /* Initialize the upper limit on the number of worker threads */
|
| +#if SQLITE_MAX_WORKER_THREADS>0
|
| + if( sqlite3TempInMemory(db) || sqlite3GlobalConfig.bCoreMutex==0 ){
|
| + nWorker = 0;
|
| + }else{
|
| + nWorker = db->aLimit[SQLITE_LIMIT_WORKER_THREADS];
|
| + }
|
| +#endif
|
| +
|
| + /* Do not allow the total number of threads (main thread + all workers)
|
| + ** to exceed the maximum merge count */
|
| +#if SQLITE_MAX_WORKER_THREADS>=SORTER_MAX_MERGE_COUNT
|
| + if( nWorker>=SORTER_MAX_MERGE_COUNT ){
|
| + nWorker = SORTER_MAX_MERGE_COUNT-1;
|
| + }
|
| +#endif
|
| +
|
| + assert( pCsr->pKeyInfo && pCsr->pBt==0 );
|
| + assert( pCsr->eCurType==CURTYPE_SORTER );
|
| + szKeyInfo = sizeof(KeyInfo) + (pCsr->pKeyInfo->nField-1)*sizeof(CollSeq*);
|
| + sz = sizeof(VdbeSorter) + nWorker * sizeof(SortSubtask);
|
| +
|
| + pSorter = (VdbeSorter*)sqlite3DbMallocZero(db, sz + szKeyInfo);
|
| + pCsr->uc.pSorter = pSorter;
|
| + if( pSorter==0 ){
|
| + rc = SQLITE_NOMEM;
|
| + }else{
|
| + pSorter->pKeyInfo = pKeyInfo = (KeyInfo*)((u8*)pSorter + sz);
|
| + memcpy(pKeyInfo, pCsr->pKeyInfo, szKeyInfo);
|
| + pKeyInfo->db = 0;
|
| + if( nField && nWorker==0 ){
|
| + pKeyInfo->nXField += (pKeyInfo->nField - nField);
|
| + pKeyInfo->nField = nField;
|
| + }
|
| + pSorter->pgsz = pgsz = sqlite3BtreeGetPageSize(db->aDb[0].pBt);
|
| + pSorter->nTask = nWorker + 1;
|
| + pSorter->iPrev = (u8)(nWorker - 1);
|
| + pSorter->bUseThreads = (pSorter->nTask>1);
|
| + pSorter->db = db;
|
| + for(i=0; i<pSorter->nTask; i++){
|
| + SortSubtask *pTask = &pSorter->aTask[i];
|
| + pTask->pSorter = pSorter;
|
| + }
|
| +
|
| + if( !sqlite3TempInMemory(db) ){
|
| + u32 szPma = sqlite3GlobalConfig.szPma;
|
| + pSorter->mnPmaSize = szPma * pgsz;
|
| + mxCache = db->aDb[0].pSchema->cache_size;
|
| + if( mxCache<(int)szPma ) mxCache = (int)szPma;
|
| + pSorter->mxPmaSize = MIN((i64)mxCache*pgsz, SQLITE_MAX_PMASZ);
|
| +
|
| + /* EVIDENCE-OF: R-26747-61719 When the application provides any amount of
|
| + ** scratch memory using SQLITE_CONFIG_SCRATCH, SQLite avoids unnecessary
|
| + ** large heap allocations.
|
| + */
|
| + if( sqlite3GlobalConfig.pScratch==0 ){
|
| + assert( pSorter->iMemory==0 );
|
| + pSorter->nMemory = pgsz;
|
| + pSorter->list.aMemory = (u8*)sqlite3Malloc(pgsz);
|
| + if( !pSorter->list.aMemory ) rc = SQLITE_NOMEM;
|
| + }
|
| + }
|
| +
|
| + if( (pKeyInfo->nField+pKeyInfo->nXField)<13
|
| + && (pKeyInfo->aColl[0]==0 || pKeyInfo->aColl[0]==db->pDfltColl)
|
| + ){
|
| + pSorter->typeMask = SORTER_TYPE_INTEGER | SORTER_TYPE_TEXT;
|
| + }
|
| + }
|
| +
|
| + return rc;
|
| +}
|
| +#undef nWorker /* Defined at the top of this function */
|
| +
|
| +/*
|
| +** Free the list of sorted records starting at pRecord.
|
| +*/
|
| +static void vdbeSorterRecordFree(sqlite3 *db, SorterRecord *pRecord){
|
| + SorterRecord *p;
|
| + SorterRecord *pNext;
|
| + for(p=pRecord; p; p=pNext){
|
| + pNext = p->u.pNext;
|
| + sqlite3DbFree(db, p);
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Free all resources owned by the object indicated by argument pTask. All
|
| +** fields of *pTask are zeroed before returning.
|
| +*/
|
| +static void vdbeSortSubtaskCleanup(sqlite3 *db, SortSubtask *pTask){
|
| + sqlite3DbFree(db, pTask->pUnpacked);
|
| +#if SQLITE_MAX_WORKER_THREADS>0
|
| + /* pTask->list.aMemory can only be non-zero if it was handed memory
|
| + ** from the main thread. That only occurs SQLITE_MAX_WORKER_THREADS>0 */
|
| + if( pTask->list.aMemory ){
|
| + sqlite3_free(pTask->list.aMemory);
|
| + }else
|
| +#endif
|
| + {
|
| + assert( pTask->list.aMemory==0 );
|
| + vdbeSorterRecordFree(0, pTask->list.pList);
|
| + }
|
| + if( pTask->file.pFd ){
|
| + sqlite3OsCloseFree(pTask->file.pFd);
|
| + }
|
| + if( pTask->file2.pFd ){
|
| + sqlite3OsCloseFree(pTask->file2.pFd);
|
| + }
|
| + memset(pTask, 0, sizeof(SortSubtask));
|
| +}
|
| +
|
| +#ifdef SQLITE_DEBUG_SORTER_THREADS
|
| +static void vdbeSorterWorkDebug(SortSubtask *pTask, const char *zEvent){
|
| + i64 t;
|
| + int iTask = (pTask - pTask->pSorter->aTask);
|
| + sqlite3OsCurrentTimeInt64(pTask->pSorter->db->pVfs, &t);
|
| + fprintf(stderr, "%lld:%d %s\n", t, iTask, zEvent);
|
| +}
|
| +static void vdbeSorterRewindDebug(const char *zEvent){
|
| + i64 t;
|
| + sqlite3OsCurrentTimeInt64(sqlite3_vfs_find(0), &t);
|
| + fprintf(stderr, "%lld:X %s\n", t, zEvent);
|
| +}
|
| +static void vdbeSorterPopulateDebug(
|
| + SortSubtask *pTask,
|
| + const char *zEvent
|
| +){
|
| + i64 t;
|
| + int iTask = (pTask - pTask->pSorter->aTask);
|
| + sqlite3OsCurrentTimeInt64(pTask->pSorter->db->pVfs, &t);
|
| + fprintf(stderr, "%lld:bg%d %s\n", t, iTask, zEvent);
|
| +}
|
| +static void vdbeSorterBlockDebug(
|
| + SortSubtask *pTask,
|
| + int bBlocked,
|
| + const char *zEvent
|
| +){
|
| + if( bBlocked ){
|
| + i64 t;
|
| + sqlite3OsCurrentTimeInt64(pTask->pSorter->db->pVfs, &t);
|
| + fprintf(stderr, "%lld:main %s\n", t, zEvent);
|
| + }
|
| +}
|
| +#else
|
| +# define vdbeSorterWorkDebug(x,y)
|
| +# define vdbeSorterRewindDebug(y)
|
| +# define vdbeSorterPopulateDebug(x,y)
|
| +# define vdbeSorterBlockDebug(x,y,z)
|
| +#endif
|
| +
|
| +#if SQLITE_MAX_WORKER_THREADS>0
|
| +/*
|
| +** Join thread pTask->thread.
|
| +*/
|
| +static int vdbeSorterJoinThread(SortSubtask *pTask){
|
| + int rc = SQLITE_OK;
|
| + if( pTask->pThread ){
|
| +#ifdef SQLITE_DEBUG_SORTER_THREADS
|
| + int bDone = pTask->bDone;
|
| +#endif
|
| + void *pRet = SQLITE_INT_TO_PTR(SQLITE_ERROR);
|
| + vdbeSorterBlockDebug(pTask, !bDone, "enter");
|
| + (void)sqlite3ThreadJoin(pTask->pThread, &pRet);
|
| + vdbeSorterBlockDebug(pTask, !bDone, "exit");
|
| + rc = SQLITE_PTR_TO_INT(pRet);
|
| + assert( pTask->bDone==1 );
|
| + pTask->bDone = 0;
|
| + pTask->pThread = 0;
|
| + }
|
| + return rc;
|
| +}
|
| +
|
| +/*
|
| +** Launch a background thread to run xTask(pIn).
|
| +*/
|
| +static int vdbeSorterCreateThread(
|
| + SortSubtask *pTask, /* Thread will use this task object */
|
| + void *(*xTask)(void*), /* Routine to run in a separate thread */
|
| + void *pIn /* Argument passed into xTask() */
|
| +){
|
| + assert( pTask->pThread==0 && pTask->bDone==0 );
|
| + return sqlite3ThreadCreate(&pTask->pThread, xTask, pIn);
|
| +}
|
| +
|
| +/*
|
| +** Join all outstanding threads launched by SorterWrite() to create
|
| +** level-0 PMAs.
|
| +*/
|
| +static int vdbeSorterJoinAll(VdbeSorter *pSorter, int rcin){
|
| + int rc = rcin;
|
| + int i;
|
| +
|
| + /* This function is always called by the main user thread.
|
| + **
|
| + ** If this function is being called after SorterRewind() has been called,
|
| + ** it is possible that thread pSorter->aTask[pSorter->nTask-1].pThread
|
| + ** is currently attempt to join one of the other threads. To avoid a race
|
| + ** condition where this thread also attempts to join the same object, join
|
| + ** thread pSorter->aTask[pSorter->nTask-1].pThread first. */
|
| + for(i=pSorter->nTask-1; i>=0; i--){
|
| + SortSubtask *pTask = &pSorter->aTask[i];
|
| + int rc2 = vdbeSorterJoinThread(pTask);
|
| + if( rc==SQLITE_OK ) rc = rc2;
|
| + }
|
| + return rc;
|
| +}
|
| +#else
|
| +# define vdbeSorterJoinAll(x,rcin) (rcin)
|
| +# define vdbeSorterJoinThread(pTask) SQLITE_OK
|
| +#endif
|
| +
|
| +/*
|
| +** Allocate a new MergeEngine object capable of handling up to
|
| +** nReader PmaReader inputs.
|
| +**
|
| +** nReader is automatically rounded up to the next power of two.
|
| +** nReader may not exceed SORTER_MAX_MERGE_COUNT even after rounding up.
|
| +*/
|
| +static MergeEngine *vdbeMergeEngineNew(int nReader){
|
| + int N = 2; /* Smallest power of two >= nReader */
|
| + int nByte; /* Total bytes of space to allocate */
|
| + MergeEngine *pNew; /* Pointer to allocated object to return */
|
| +
|
| + assert( nReader<=SORTER_MAX_MERGE_COUNT );
|
| +
|
| + while( N<nReader ) N += N;
|
| + nByte = sizeof(MergeEngine) + N * (sizeof(int) + sizeof(PmaReader));
|
| +
|
| + pNew = sqlite3FaultSim(100) ? 0 : (MergeEngine*)sqlite3MallocZero(nByte);
|
| + if( pNew ){
|
| + pNew->nTree = N;
|
| + pNew->pTask = 0;
|
| + pNew->aReadr = (PmaReader*)&pNew[1];
|
| + pNew->aTree = (int*)&pNew->aReadr[N];
|
| + }
|
| + return pNew;
|
| +}
|
| +
|
| +/*
|
| +** Free the MergeEngine object passed as the only argument.
|
| +*/
|
| +static void vdbeMergeEngineFree(MergeEngine *pMerger){
|
| + int i;
|
| + if( pMerger ){
|
| + for(i=0; i<pMerger->nTree; i++){
|
| + vdbePmaReaderClear(&pMerger->aReadr[i]);
|
| + }
|
| + }
|
| + sqlite3_free(pMerger);
|
| +}
|
| +
|
| +/*
|
| +** Free all resources associated with the IncrMerger object indicated by
|
| +** the first argument.
|
| +*/
|
| +static void vdbeIncrFree(IncrMerger *pIncr){
|
| + if( pIncr ){
|
| +#if SQLITE_MAX_WORKER_THREADS>0
|
| + if( pIncr->bUseThread ){
|
| + vdbeSorterJoinThread(pIncr->pTask);
|
| + if( pIncr->aFile[0].pFd ) sqlite3OsCloseFree(pIncr->aFile[0].pFd);
|
| + if( pIncr->aFile[1].pFd ) sqlite3OsCloseFree(pIncr->aFile[1].pFd);
|
| + }
|
| +#endif
|
| + vdbeMergeEngineFree(pIncr->pMerger);
|
| + sqlite3_free(pIncr);
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Reset a sorting cursor back to its original empty state.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbeSorterReset(sqlite3 *db, VdbeSorter *pSorter){
|
| + int i;
|
| + (void)vdbeSorterJoinAll(pSorter, SQLITE_OK);
|
| + assert( pSorter->bUseThreads || pSorter->pReader==0 );
|
| +#if SQLITE_MAX_WORKER_THREADS>0
|
| + if( pSorter->pReader ){
|
| + vdbePmaReaderClear(pSorter->pReader);
|
| + sqlite3DbFree(db, pSorter->pReader);
|
| + pSorter->pReader = 0;
|
| + }
|
| +#endif
|
| + vdbeMergeEngineFree(pSorter->pMerger);
|
| + pSorter->pMerger = 0;
|
| + for(i=0; i<pSorter->nTask; i++){
|
| + SortSubtask *pTask = &pSorter->aTask[i];
|
| + vdbeSortSubtaskCleanup(db, pTask);
|
| + pTask->pSorter = pSorter;
|
| + }
|
| + if( pSorter->list.aMemory==0 ){
|
| + vdbeSorterRecordFree(0, pSorter->list.pList);
|
| + }
|
| + pSorter->list.pList = 0;
|
| + pSorter->list.szPMA = 0;
|
| + pSorter->bUsePMA = 0;
|
| + pSorter->iMemory = 0;
|
| + pSorter->mxKeysize = 0;
|
| + sqlite3DbFree(db, pSorter->pUnpacked);
|
| + pSorter->pUnpacked = 0;
|
| +}
|
| +
|
| +/*
|
| +** Free any cursor components allocated by sqlite3VdbeSorterXXX routines.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *db, VdbeCursor *pCsr){
|
| + VdbeSorter *pSorter;
|
| + assert( pCsr->eCurType==CURTYPE_SORTER );
|
| + pSorter = pCsr->uc.pSorter;
|
| + if( pSorter ){
|
| + sqlite3VdbeSorterReset(db, pSorter);
|
| + sqlite3_free(pSorter->list.aMemory);
|
| + sqlite3DbFree(db, pSorter);
|
| + pCsr->uc.pSorter = 0;
|
| + }
|
| +}
|
| +
|
| +#if SQLITE_MAX_MMAP_SIZE>0
|
| +/*
|
| +** The first argument is a file-handle open on a temporary file. The file
|
| +** is guaranteed to be nByte bytes or smaller in size. This function
|
| +** attempts to extend the file to nByte bytes in size and to ensure that
|
| +** the VFS has memory mapped it.
|
| +**
|
| +** Whether or not the file does end up memory mapped of course depends on
|
| +** the specific VFS implementation.
|
| +*/
|
| +static void vdbeSorterExtendFile(sqlite3 *db, sqlite3_file *pFd, i64 nByte){
|
| + if( nByte<=(i64)(db->nMaxSorterMmap) && pFd->pMethods->iVersion>=3 ){
|
| + void *p = 0;
|
| + int chunksize = 4*1024;
|
| + sqlite3OsFileControlHint(pFd, SQLITE_FCNTL_CHUNK_SIZE, &chunksize);
|
| + sqlite3OsFileControlHint(pFd, SQLITE_FCNTL_SIZE_HINT, &nByte);
|
| + sqlite3OsFetch(pFd, 0, (int)nByte, &p);
|
| + sqlite3OsUnfetch(pFd, 0, p);
|
| + }
|
| +}
|
| +#else
|
| +# define vdbeSorterExtendFile(x,y,z)
|
| +#endif
|
| +
|
| +/*
|
| +** Allocate space for a file-handle and open a temporary file. If successful,
|
| +** set *ppFd to point to the malloc'd file-handle and return SQLITE_OK.
|
| +** Otherwise, set *ppFd to 0 and return an SQLite error code.
|
| +*/
|
| +static int vdbeSorterOpenTempFile(
|
| + sqlite3 *db, /* Database handle doing sort */
|
| + i64 nExtend, /* Attempt to extend file to this size */
|
| + sqlite3_file **ppFd
|
| +){
|
| + int rc;
|
| + if( sqlite3FaultSim(202) ) return SQLITE_IOERR_ACCESS;
|
| + rc = sqlite3OsOpenMalloc(db->pVfs, 0, ppFd,
|
| + SQLITE_OPEN_TEMP_JOURNAL |
|
| + SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |
|
| + SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE, &rc
|
| + );
|
| + if( rc==SQLITE_OK ){
|
| + i64 max = SQLITE_MAX_MMAP_SIZE;
|
| + sqlite3OsFileControlHint(*ppFd, SQLITE_FCNTL_MMAP_SIZE, (void*)&max);
|
| + if( nExtend>0 ){
|
| + vdbeSorterExtendFile(db, *ppFd, nExtend);
|
| + }
|
| + }
|
| + return rc;
|
| +}
|
| +
|
| +/*
|
| +** If it has not already been allocated, allocate the UnpackedRecord
|
| +** structure at pTask->pUnpacked. Return SQLITE_OK if successful (or
|
| +** if no allocation was required), or SQLITE_NOMEM otherwise.
|
| +*/
|
| +static int vdbeSortAllocUnpacked(SortSubtask *pTask){
|
| + if( pTask->pUnpacked==0 ){
|
| + char *pFree;
|
| + pTask->pUnpacked = sqlite3VdbeAllocUnpackedRecord(
|
| + pTask->pSorter->pKeyInfo, 0, 0, &pFree
|
| + );
|
| + assert( pTask->pUnpacked==(UnpackedRecord*)pFree );
|
| + if( pFree==0 ) return SQLITE_NOMEM;
|
| + pTask->pUnpacked->nField = pTask->pSorter->pKeyInfo->nField;
|
| + pTask->pUnpacked->errCode = 0;
|
| + }
|
| + return SQLITE_OK;
|
| +}
|
| +
|
| +
|
| +/*
|
| +** Merge the two sorted lists p1 and p2 into a single list.
|
| +** Set *ppOut to the head of the new list.
|
| +*/
|
| +static void vdbeSorterMerge(
|
| + SortSubtask *pTask, /* Calling thread context */
|
| + SorterRecord *p1, /* First list to merge */
|
| + SorterRecord *p2, /* Second list to merge */
|
| + SorterRecord **ppOut /* OUT: Head of merged list */
|
| +){
|
| + SorterRecord *pFinal = 0;
|
| + SorterRecord **pp = &pFinal;
|
| + int bCached = 0;
|
| +
|
| + while( p1 && p2 ){
|
| + int res;
|
| + res = pTask->xCompare(
|
| + pTask, &bCached, SRVAL(p1), p1->nVal, SRVAL(p2), p2->nVal
|
| + );
|
| +
|
| + if( res<=0 ){
|
| + *pp = p1;
|
| + pp = &p1->u.pNext;
|
| + p1 = p1->u.pNext;
|
| + }else{
|
| + *pp = p2;
|
| + pp = &p2->u.pNext;
|
| + p2 = p2->u.pNext;
|
| + bCached = 0;
|
| + }
|
| + }
|
| + *pp = p1 ? p1 : p2;
|
| + *ppOut = pFinal;
|
| +}
|
| +
|
| +/*
|
| +** Return the SorterCompare function to compare values collected by the
|
| +** sorter object passed as the only argument.
|
| +*/
|
| +static SorterCompare vdbeSorterGetCompare(VdbeSorter *p){
|
| + if( p->typeMask==SORTER_TYPE_INTEGER ){
|
| + return vdbeSorterCompareInt;
|
| + }else if( p->typeMask==SORTER_TYPE_TEXT ){
|
| + return vdbeSorterCompareText;
|
| + }
|
| + return vdbeSorterCompare;
|
| +}
|
| +
|
| +/*
|
| +** Sort the linked list of records headed at pTask->pList. Return
|
| +** SQLITE_OK if successful, or an SQLite error code (i.e. SQLITE_NOMEM) if
|
| +** an error occurs.
|
| +*/
|
| +static int vdbeSorterSort(SortSubtask *pTask, SorterList *pList){
|
| + int i;
|
| + SorterRecord **aSlot;
|
| + SorterRecord *p;
|
| + int rc;
|
| +
|
| + rc = vdbeSortAllocUnpacked(pTask);
|
| + if( rc!=SQLITE_OK ) return rc;
|
| +
|
| + p = pList->pList;
|
| + pTask->xCompare = vdbeSorterGetCompare(pTask->pSorter);
|
| +
|
| + aSlot = (SorterRecord **)sqlite3MallocZero(64 * sizeof(SorterRecord *));
|
| + if( !aSlot ){
|
| + return SQLITE_NOMEM;
|
| + }
|
| +
|
| + while( p ){
|
| + SorterRecord *pNext;
|
| + if( pList->aMemory ){
|
| + if( (u8*)p==pList->aMemory ){
|
| + pNext = 0;
|
| + }else{
|
| + assert( p->u.iNext<sqlite3MallocSize(pList->aMemory) );
|
| + pNext = (SorterRecord*)&pList->aMemory[p->u.iNext];
|
| + }
|
| + }else{
|
| + pNext = p->u.pNext;
|
| + }
|
| +
|
| + p->u.pNext = 0;
|
| + for(i=0; aSlot[i]; i++){
|
| + vdbeSorterMerge(pTask, p, aSlot[i], &p);
|
| + aSlot[i] = 0;
|
| + }
|
| + aSlot[i] = p;
|
| + p = pNext;
|
| + }
|
| +
|
| + p = 0;
|
| + for(i=0; i<64; i++){
|
| + vdbeSorterMerge(pTask, p, aSlot[i], &p);
|
| + }
|
| + pList->pList = p;
|
| +
|
| + sqlite3_free(aSlot);
|
| + assert( pTask->pUnpacked->errCode==SQLITE_OK
|
| + || pTask->pUnpacked->errCode==SQLITE_NOMEM
|
| + );
|
| + return pTask->pUnpacked->errCode;
|
| +}
|
| +
|
| +/*
|
| +** Initialize a PMA-writer object.
|
| +*/
|
| +static void vdbePmaWriterInit(
|
| + sqlite3_file *pFd, /* File handle to write to */
|
| + PmaWriter *p, /* Object to populate */
|
| + int nBuf, /* Buffer size */
|
| + i64 iStart /* Offset of pFd to begin writing at */
|
| +){
|
| + memset(p, 0, sizeof(PmaWriter));
|
| + p->aBuffer = (u8*)sqlite3Malloc(nBuf);
|
| + if( !p->aBuffer ){
|
| + p->eFWErr = SQLITE_NOMEM;
|
| + }else{
|
| + p->iBufEnd = p->iBufStart = (iStart % nBuf);
|
| + p->iWriteOff = iStart - p->iBufStart;
|
| + p->nBuffer = nBuf;
|
| + p->pFd = pFd;
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Write nData bytes of data to the PMA. Return SQLITE_OK
|
| +** if successful, or an SQLite error code if an error occurs.
|
| +*/
|
| +static void vdbePmaWriteBlob(PmaWriter *p, u8 *pData, int nData){
|
| + int nRem = nData;
|
| + while( nRem>0 && p->eFWErr==0 ){
|
| + int nCopy = nRem;
|
| + if( nCopy>(p->nBuffer - p->iBufEnd) ){
|
| + nCopy = p->nBuffer - p->iBufEnd;
|
| + }
|
| +
|
| + memcpy(&p->aBuffer[p->iBufEnd], &pData[nData-nRem], nCopy);
|
| + p->iBufEnd += nCopy;
|
| + if( p->iBufEnd==p->nBuffer ){
|
| + p->eFWErr = sqlite3OsWrite(p->pFd,
|
| + &p->aBuffer[p->iBufStart], p->iBufEnd - p->iBufStart,
|
| + p->iWriteOff + p->iBufStart
|
| + );
|
| + p->iBufStart = p->iBufEnd = 0;
|
| + p->iWriteOff += p->nBuffer;
|
| + }
|
| + assert( p->iBufEnd<p->nBuffer );
|
| +
|
| + nRem -= nCopy;
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Flush any buffered data to disk and clean up the PMA-writer object.
|
| +** The results of using the PMA-writer after this call are undefined.
|
| +** Return SQLITE_OK if flushing the buffered data succeeds or is not
|
| +** required. Otherwise, return an SQLite error code.
|
| +**
|
| +** Before returning, set *piEof to the offset immediately following the
|
| +** last byte written to the file.
|
| +*/
|
| +static int vdbePmaWriterFinish(PmaWriter *p, i64 *piEof){
|
| + int rc;
|
| + if( p->eFWErr==0 && ALWAYS(p->aBuffer) && p->iBufEnd>p->iBufStart ){
|
| + p->eFWErr = sqlite3OsWrite(p->pFd,
|
| + &p->aBuffer[p->iBufStart], p->iBufEnd - p->iBufStart,
|
| + p->iWriteOff + p->iBufStart
|
| + );
|
| + }
|
| + *piEof = (p->iWriteOff + p->iBufEnd);
|
| + sqlite3_free(p->aBuffer);
|
| + rc = p->eFWErr;
|
| + memset(p, 0, sizeof(PmaWriter));
|
| + return rc;
|
| +}
|
| +
|
| +/*
|
| +** Write value iVal encoded as a varint to the PMA. Return
|
| +** SQLITE_OK if successful, or an SQLite error code if an error occurs.
|
| +*/
|
| +static void vdbePmaWriteVarint(PmaWriter *p, u64 iVal){
|
| + int nByte;
|
| + u8 aByte[10];
|
| + nByte = sqlite3PutVarint(aByte, iVal);
|
| + vdbePmaWriteBlob(p, aByte, nByte);
|
| +}
|
| +
|
| +/*
|
| +** Write the current contents of in-memory linked-list pList to a level-0
|
| +** PMA in the temp file belonging to sub-task pTask. Return SQLITE_OK if
|
| +** successful, or an SQLite error code otherwise.
|
| +**
|
| +** The format of a PMA is:
|
| +**
|
| +** * A varint. This varint contains the total number of bytes of content
|
| +** in the PMA (not including the varint itself).
|
| +**
|
| +** * One or more records packed end-to-end in order of ascending keys.
|
| +** Each record consists of a varint followed by a blob of data (the
|
| +** key). The varint is the number of bytes in the blob of data.
|
| +*/
|
| +static int vdbeSorterListToPMA(SortSubtask *pTask, SorterList *pList){
|
| + sqlite3 *db = pTask->pSorter->db;
|
| + int rc = SQLITE_OK; /* Return code */
|
| + PmaWriter writer; /* Object used to write to the file */
|
| +
|
| +#ifdef SQLITE_DEBUG
|
| + /* Set iSz to the expected size of file pTask->file after writing the PMA.
|
| + ** This is used by an assert() statement at the end of this function. */
|
| + i64 iSz = pList->szPMA + sqlite3VarintLen(pList->szPMA) + pTask->file.iEof;
|
| +#endif
|
| +
|
| + vdbeSorterWorkDebug(pTask, "enter");
|
| + memset(&writer, 0, sizeof(PmaWriter));
|
| + assert( pList->szPMA>0 );
|
| +
|
| + /* If the first temporary PMA file has not been opened, open it now. */
|
| + if( pTask->file.pFd==0 ){
|
| + rc = vdbeSorterOpenTempFile(db, 0, &pTask->file.pFd);
|
| + assert( rc!=SQLITE_OK || pTask->file.pFd );
|
| + assert( pTask->file.iEof==0 );
|
| + assert( pTask->nPMA==0 );
|
| + }
|
| +
|
| + /* Try to get the file to memory map */
|
| + if( rc==SQLITE_OK ){
|
| + vdbeSorterExtendFile(db, pTask->file.pFd, pTask->file.iEof+pList->szPMA+9);
|
| + }
|
| +
|
| + /* Sort the list */
|
| + if( rc==SQLITE_OK ){
|
| + rc = vdbeSorterSort(pTask, pList);
|
| + }
|
| +
|
| + if( rc==SQLITE_OK ){
|
| + SorterRecord *p;
|
| + SorterRecord *pNext = 0;
|
| +
|
| + vdbePmaWriterInit(pTask->file.pFd, &writer, pTask->pSorter->pgsz,
|
| + pTask->file.iEof);
|
| + pTask->nPMA++;
|
| + vdbePmaWriteVarint(&writer, pList->szPMA);
|
| + for(p=pList->pList; p; p=pNext){
|
| + pNext = p->u.pNext;
|
| + vdbePmaWriteVarint(&writer, p->nVal);
|
| + vdbePmaWriteBlob(&writer, SRVAL(p), p->nVal);
|
| + if( pList->aMemory==0 ) sqlite3_free(p);
|
| + }
|
| + pList->pList = p;
|
| + rc = vdbePmaWriterFinish(&writer, &pTask->file.iEof);
|
| + }
|
| +
|
| + vdbeSorterWorkDebug(pTask, "exit");
|
| + assert( rc!=SQLITE_OK || pList->pList==0 );
|
| + assert( rc!=SQLITE_OK || pTask->file.iEof==iSz );
|
| + return rc;
|
| +}
|
| +
|
| +/*
|
| +** Advance the MergeEngine to its next entry.
|
| +** Set *pbEof to true there is no next entry because
|
| +** the MergeEngine has reached the end of all its inputs.
|
| +**
|
| +** Return SQLITE_OK if successful or an error code if an error occurs.
|
| +*/
|
| +static int vdbeMergeEngineStep(
|
| + MergeEngine *pMerger, /* The merge engine to advance to the next row */
|
| + int *pbEof /* Set TRUE at EOF. Set false for more content */
|
| +){
|
| + int rc;
|
| + int iPrev = pMerger->aTree[1];/* Index of PmaReader to advance */
|
| + SortSubtask *pTask = pMerger->pTask;
|
| +
|
| + /* Advance the current PmaReader */
|
| + rc = vdbePmaReaderNext(&pMerger->aReadr[iPrev]);
|
| +
|
| + /* Update contents of aTree[] */
|
| + if( rc==SQLITE_OK ){
|
| + int i; /* Index of aTree[] to recalculate */
|
| + PmaReader *pReadr1; /* First PmaReader to compare */
|
| + PmaReader *pReadr2; /* Second PmaReader to compare */
|
| + int bCached = 0;
|
| +
|
| + /* Find the first two PmaReaders to compare. The one that was just
|
| + ** advanced (iPrev) and the one next to it in the array. */
|
| + pReadr1 = &pMerger->aReadr[(iPrev & 0xFFFE)];
|
| + pReadr2 = &pMerger->aReadr[(iPrev | 0x0001)];
|
| +
|
| + for(i=(pMerger->nTree+iPrev)/2; i>0; i=i/2){
|
| + /* Compare pReadr1 and pReadr2. Store the result in variable iRes. */
|
| + int iRes;
|
| + if( pReadr1->pFd==0 ){
|
| + iRes = +1;
|
| + }else if( pReadr2->pFd==0 ){
|
| + iRes = -1;
|
| + }else{
|
| + iRes = pTask->xCompare(pTask, &bCached,
|
| + pReadr1->aKey, pReadr1->nKey, pReadr2->aKey, pReadr2->nKey
|
| + );
|
| + }
|
| +
|
| + /* If pReadr1 contained the smaller value, set aTree[i] to its index.
|
| + ** Then set pReadr2 to the next PmaReader to compare to pReadr1. In this
|
| + ** case there is no cache of pReadr2 in pTask->pUnpacked, so set
|
| + ** pKey2 to point to the record belonging to pReadr2.
|
| + **
|
| + ** Alternatively, if pReadr2 contains the smaller of the two values,
|
| + ** set aTree[i] to its index and update pReadr1. If vdbeSorterCompare()
|
| + ** was actually called above, then pTask->pUnpacked now contains
|
| + ** a value equivalent to pReadr2. So set pKey2 to NULL to prevent
|
| + ** vdbeSorterCompare() from decoding pReadr2 again.
|
| + **
|
| + ** If the two values were equal, then the value from the oldest
|
| + ** PMA should be considered smaller. The VdbeSorter.aReadr[] array
|
| + ** is sorted from oldest to newest, so pReadr1 contains older values
|
| + ** than pReadr2 iff (pReadr1<pReadr2). */
|
| + if( iRes<0 || (iRes==0 && pReadr1<pReadr2) ){
|
| + pMerger->aTree[i] = (int)(pReadr1 - pMerger->aReadr);
|
| + pReadr2 = &pMerger->aReadr[ pMerger->aTree[i ^ 0x0001] ];
|
| + bCached = 0;
|
| + }else{
|
| + if( pReadr1->pFd ) bCached = 0;
|
| + pMerger->aTree[i] = (int)(pReadr2 - pMerger->aReadr);
|
| + pReadr1 = &pMerger->aReadr[ pMerger->aTree[i ^ 0x0001] ];
|
| + }
|
| + }
|
| + *pbEof = (pMerger->aReadr[pMerger->aTree[1]].pFd==0);
|
| + }
|
| +
|
| + return (rc==SQLITE_OK ? pTask->pUnpacked->errCode : rc);
|
| +}
|
| +
|
| +#if SQLITE_MAX_WORKER_THREADS>0
|
| +/*
|
| +** The main routine for background threads that write level-0 PMAs.
|
| +*/
|
| +static void *vdbeSorterFlushThread(void *pCtx){
|
| + SortSubtask *pTask = (SortSubtask*)pCtx;
|
| + int rc; /* Return code */
|
| + assert( pTask->bDone==0 );
|
| + rc = vdbeSorterListToPMA(pTask, &pTask->list);
|
| + pTask->bDone = 1;
|
| + return SQLITE_INT_TO_PTR(rc);
|
| +}
|
| +#endif /* SQLITE_MAX_WORKER_THREADS>0 */
|
| +
|
| +/*
|
| +** Flush the current contents of VdbeSorter.list to a new PMA, possibly
|
| +** using a background thread.
|
| +*/
|
| +static int vdbeSorterFlushPMA(VdbeSorter *pSorter){
|
| +#if SQLITE_MAX_WORKER_THREADS==0
|
| + pSorter->bUsePMA = 1;
|
| + return vdbeSorterListToPMA(&pSorter->aTask[0], &pSorter->list);
|
| +#else
|
| + int rc = SQLITE_OK;
|
| + int i;
|
| + SortSubtask *pTask = 0; /* Thread context used to create new PMA */
|
| + int nWorker = (pSorter->nTask-1);
|
| +
|
| + /* Set the flag to indicate that at least one PMA has been written.
|
| + ** Or will be, anyhow. */
|
| + pSorter->bUsePMA = 1;
|
| +
|
| + /* Select a sub-task to sort and flush the current list of in-memory
|
| + ** records to disk. If the sorter is running in multi-threaded mode,
|
| + ** round-robin between the first (pSorter->nTask-1) tasks. Except, if
|
| + ** the background thread from a sub-tasks previous turn is still running,
|
| + ** skip it. If the first (pSorter->nTask-1) sub-tasks are all still busy,
|
| + ** fall back to using the final sub-task. The first (pSorter->nTask-1)
|
| + ** sub-tasks are prefered as they use background threads - the final
|
| + ** sub-task uses the main thread. */
|
| + for(i=0; i<nWorker; i++){
|
| + int iTest = (pSorter->iPrev + i + 1) % nWorker;
|
| + pTask = &pSorter->aTask[iTest];
|
| + if( pTask->bDone ){
|
| + rc = vdbeSorterJoinThread(pTask);
|
| + }
|
| + if( rc!=SQLITE_OK || pTask->pThread==0 ) break;
|
| + }
|
| +
|
| + if( rc==SQLITE_OK ){
|
| + if( i==nWorker ){
|
| + /* Use the foreground thread for this operation */
|
| + rc = vdbeSorterListToPMA(&pSorter->aTask[nWorker], &pSorter->list);
|
| + }else{
|
| + /* Launch a background thread for this operation */
|
| + u8 *aMem = pTask->list.aMemory;
|
| + void *pCtx = (void*)pTask;
|
| +
|
| + assert( pTask->pThread==0 && pTask->bDone==0 );
|
| + assert( pTask->list.pList==0 );
|
| + assert( pTask->list.aMemory==0 || pSorter->list.aMemory!=0 );
|
| +
|
| + pSorter->iPrev = (u8)(pTask - pSorter->aTask);
|
| + pTask->list = pSorter->list;
|
| + pSorter->list.pList = 0;
|
| + pSorter->list.szPMA = 0;
|
| + if( aMem ){
|
| + pSorter->list.aMemory = aMem;
|
| + pSorter->nMemory = sqlite3MallocSize(aMem);
|
| + }else if( pSorter->list.aMemory ){
|
| + pSorter->list.aMemory = sqlite3Malloc(pSorter->nMemory);
|
| + if( !pSorter->list.aMemory ) return SQLITE_NOMEM;
|
| + }
|
| +
|
| + rc = vdbeSorterCreateThread(pTask, vdbeSorterFlushThread, pCtx);
|
| + }
|
| + }
|
| +
|
| + return rc;
|
| +#endif /* SQLITE_MAX_WORKER_THREADS!=0 */
|
| +}
|
| +
|
| +/*
|
| +** Add a record to the sorter.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3VdbeSorterWrite(
|
| + const VdbeCursor *pCsr, /* Sorter cursor */
|
| + Mem *pVal /* Memory cell containing record */
|
| +){
|
| + VdbeSorter *pSorter;
|
| + int rc = SQLITE_OK; /* Return Code */
|
| + SorterRecord *pNew; /* New list element */
|
| + int bFlush; /* True to flush contents of memory to PMA */
|
| + int nReq; /* Bytes of memory required */
|
| + int nPMA; /* Bytes of PMA space required */
|
| + int t; /* serial type of first record field */
|
| +
|
| + assert( pCsr->eCurType==CURTYPE_SORTER );
|
| + pSorter = pCsr->uc.pSorter;
|
| + getVarint32((const u8*)&pVal->z[1], t);
|
| + if( t>0 && t<10 && t!=7 ){
|
| + pSorter->typeMask &= SORTER_TYPE_INTEGER;
|
| + }else if( t>10 && (t & 0x01) ){
|
| + pSorter->typeMask &= SORTER_TYPE_TEXT;
|
| + }else{
|
| + pSorter->typeMask = 0;
|
| + }
|
| +
|
| + assert( pSorter );
|
| +
|
| + /* Figure out whether or not the current contents of memory should be
|
| + ** flushed to a PMA before continuing. If so, do so.
|
| + **
|
| + ** If using the single large allocation mode (pSorter->aMemory!=0), then
|
| + ** flush the contents of memory to a new PMA if (a) at least one value is
|
| + ** already in memory and (b) the new value will not fit in memory.
|
| + **
|
| + ** Or, if using separate allocations for each record, flush the contents
|
| + ** of memory to a PMA if either of the following are true:
|
| + **
|
| + ** * The total memory allocated for the in-memory list is greater
|
| + ** than (page-size * cache-size), or
|
| + **
|
| + ** * The total memory allocated for the in-memory list is greater
|
| + ** than (page-size * 10) and sqlite3HeapNearlyFull() returns true.
|
| + */
|
| + nReq = pVal->n + sizeof(SorterRecord);
|
| + nPMA = pVal->n + sqlite3VarintLen(pVal->n);
|
| + if( pSorter->mxPmaSize ){
|
| + if( pSorter->list.aMemory ){
|
| + bFlush = pSorter->iMemory && (pSorter->iMemory+nReq) > pSorter->mxPmaSize;
|
| + }else{
|
| + bFlush = (
|
| + (pSorter->list.szPMA > pSorter->mxPmaSize)
|
| + || (pSorter->list.szPMA > pSorter->mnPmaSize && sqlite3HeapNearlyFull())
|
| + );
|
| + }
|
| + if( bFlush ){
|
| + rc = vdbeSorterFlushPMA(pSorter);
|
| + pSorter->list.szPMA = 0;
|
| + pSorter->iMemory = 0;
|
| + assert( rc!=SQLITE_OK || pSorter->list.pList==0 );
|
| + }
|
| + }
|
| +
|
| + pSorter->list.szPMA += nPMA;
|
| + if( nPMA>pSorter->mxKeysize ){
|
| + pSorter->mxKeysize = nPMA;
|
| + }
|
| +
|
| + if( pSorter->list.aMemory ){
|
| + int nMin = pSorter->iMemory + nReq;
|
| +
|
| + if( nMin>pSorter->nMemory ){
|
| + u8 *aNew;
|
| + int nNew = pSorter->nMemory * 2;
|
| + while( nNew < nMin ) nNew = nNew*2;
|
| + if( nNew > pSorter->mxPmaSize ) nNew = pSorter->mxPmaSize;
|
| + if( nNew < nMin ) nNew = nMin;
|
| +
|
| + aNew = sqlite3Realloc(pSorter->list.aMemory, nNew);
|
| + if( !aNew ) return SQLITE_NOMEM;
|
| + pSorter->list.pList = (SorterRecord*)(
|
| + aNew + ((u8*)pSorter->list.pList - pSorter->list.aMemory)
|
| + );
|
| + pSorter->list.aMemory = aNew;
|
| + pSorter->nMemory = nNew;
|
| + }
|
| +
|
| + pNew = (SorterRecord*)&pSorter->list.aMemory[pSorter->iMemory];
|
| + pSorter->iMemory += ROUND8(nReq);
|
| + pNew->u.iNext = (int)((u8*)(pSorter->list.pList) - pSorter->list.aMemory);
|
| + }else{
|
| + pNew = (SorterRecord *)sqlite3Malloc(nReq);
|
| + if( pNew==0 ){
|
| + return SQLITE_NOMEM;
|
| + }
|
| + pNew->u.pNext = pSorter->list.pList;
|
| + }
|
| +
|
| + memcpy(SRVAL(pNew), pVal->z, pVal->n);
|
| + pNew->nVal = pVal->n;
|
| + pSorter->list.pList = pNew;
|
| +
|
| + return rc;
|
| +}
|
| +
|
| +/*
|
| +** Read keys from pIncr->pMerger and populate pIncr->aFile[1]. The format
|
| +** of the data stored in aFile[1] is the same as that used by regular PMAs,
|
| +** except that the number-of-bytes varint is omitted from the start.
|
| +*/
|
| +static int vdbeIncrPopulate(IncrMerger *pIncr){
|
| + int rc = SQLITE_OK;
|
| + int rc2;
|
| + i64 iStart = pIncr->iStartOff;
|
| + SorterFile *pOut = &pIncr->aFile[1];
|
| + SortSubtask *pTask = pIncr->pTask;
|
| + MergeEngine *pMerger = pIncr->pMerger;
|
| + PmaWriter writer;
|
| + assert( pIncr->bEof==0 );
|
| +
|
| + vdbeSorterPopulateDebug(pTask, "enter");
|
| +
|
| + vdbePmaWriterInit(pOut->pFd, &writer, pTask->pSorter->pgsz, iStart);
|
| + while( rc==SQLITE_OK ){
|
| + int dummy;
|
| + PmaReader *pReader = &pMerger->aReadr[ pMerger->aTree[1] ];
|
| + int nKey = pReader->nKey;
|
| + i64 iEof = writer.iWriteOff + writer.iBufEnd;
|
| +
|
| + /* Check if the output file is full or if the input has been exhausted.
|
| + ** In either case exit the loop. */
|
| + if( pReader->pFd==0 ) break;
|
| + if( (iEof + nKey + sqlite3VarintLen(nKey))>(iStart + pIncr->mxSz) ) break;
|
| +
|
| + /* Write the next key to the output. */
|
| + vdbePmaWriteVarint(&writer, nKey);
|
| + vdbePmaWriteBlob(&writer, pReader->aKey, nKey);
|
| + assert( pIncr->pMerger->pTask==pTask );
|
| + rc = vdbeMergeEngineStep(pIncr->pMerger, &dummy);
|
| + }
|
| +
|
| + rc2 = vdbePmaWriterFinish(&writer, &pOut->iEof);
|
| + if( rc==SQLITE_OK ) rc = rc2;
|
| + vdbeSorterPopulateDebug(pTask, "exit");
|
| + return rc;
|
| +}
|
| +
|
| +#if SQLITE_MAX_WORKER_THREADS>0
|
| +/*
|
| +** The main routine for background threads that populate aFile[1] of
|
| +** multi-threaded IncrMerger objects.
|
| +*/
|
| +static void *vdbeIncrPopulateThread(void *pCtx){
|
| + IncrMerger *pIncr = (IncrMerger*)pCtx;
|
| + void *pRet = SQLITE_INT_TO_PTR( vdbeIncrPopulate(pIncr) );
|
| + pIncr->pTask->bDone = 1;
|
| + return pRet;
|
| +}
|
| +
|
| +/*
|
| +** Launch a background thread to populate aFile[1] of pIncr.
|
| +*/
|
| +static int vdbeIncrBgPopulate(IncrMerger *pIncr){
|
| + void *p = (void*)pIncr;
|
| + assert( pIncr->bUseThread );
|
| + return vdbeSorterCreateThread(pIncr->pTask, vdbeIncrPopulateThread, p);
|
| +}
|
| +#endif
|
| +
|
| +/*
|
| +** This function is called when the PmaReader corresponding to pIncr has
|
| +** finished reading the contents of aFile[0]. Its purpose is to "refill"
|
| +** aFile[0] such that the PmaReader should start rereading it from the
|
| +** beginning.
|
| +**
|
| +** For single-threaded objects, this is accomplished by literally reading
|
| +** keys from pIncr->pMerger and repopulating aFile[0].
|
| +**
|
| +** For multi-threaded objects, all that is required is to wait until the
|
| +** background thread is finished (if it is not already) and then swap
|
| +** aFile[0] and aFile[1] in place. If the contents of pMerger have not
|
| +** been exhausted, this function also launches a new background thread
|
| +** to populate the new aFile[1].
|
| +**
|
| +** SQLITE_OK is returned on success, or an SQLite error code otherwise.
|
| +*/
|
| +static int vdbeIncrSwap(IncrMerger *pIncr){
|
| + int rc = SQLITE_OK;
|
| +
|
| +#if SQLITE_MAX_WORKER_THREADS>0
|
| + if( pIncr->bUseThread ){
|
| + rc = vdbeSorterJoinThread(pIncr->pTask);
|
| +
|
| + if( rc==SQLITE_OK ){
|
| + SorterFile f0 = pIncr->aFile[0];
|
| + pIncr->aFile[0] = pIncr->aFile[1];
|
| + pIncr->aFile[1] = f0;
|
| + }
|
| +
|
| + if( rc==SQLITE_OK ){
|
| + if( pIncr->aFile[0].iEof==pIncr->iStartOff ){
|
| + pIncr->bEof = 1;
|
| + }else{
|
| + rc = vdbeIncrBgPopulate(pIncr);
|
| + }
|
| + }
|
| + }else
|
| +#endif
|
| + {
|
| + rc = vdbeIncrPopulate(pIncr);
|
| + pIncr->aFile[0] = pIncr->aFile[1];
|
| + if( pIncr->aFile[0].iEof==pIncr->iStartOff ){
|
| + pIncr->bEof = 1;
|
| + }
|
| + }
|
| +
|
| + return rc;
|
| +}
|
| +
|
| +/*
|
| +** Allocate and return a new IncrMerger object to read data from pMerger.
|
| +**
|
| +** If an OOM condition is encountered, return NULL. In this case free the
|
| +** pMerger argument before returning.
|
| +*/
|
| +static int vdbeIncrMergerNew(
|
| + SortSubtask *pTask, /* The thread that will be using the new IncrMerger */
|
| + MergeEngine *pMerger, /* The MergeEngine that the IncrMerger will control */
|
| + IncrMerger **ppOut /* Write the new IncrMerger here */
|
| +){
|
| + int rc = SQLITE_OK;
|
| + IncrMerger *pIncr = *ppOut = (IncrMerger*)
|
| + (sqlite3FaultSim(100) ? 0 : sqlite3MallocZero(sizeof(*pIncr)));
|
| + if( pIncr ){
|
| + pIncr->pMerger = pMerger;
|
| + pIncr->pTask = pTask;
|
| + pIncr->mxSz = MAX(pTask->pSorter->mxKeysize+9,pTask->pSorter->mxPmaSize/2);
|
| + pTask->file2.iEof += pIncr->mxSz;
|
| + }else{
|
| + vdbeMergeEngineFree(pMerger);
|
| + rc = SQLITE_NOMEM;
|
| + }
|
| + return rc;
|
| +}
|
| +
|
| +#if SQLITE_MAX_WORKER_THREADS>0
|
| +/*
|
| +** Set the "use-threads" flag on object pIncr.
|
| +*/
|
| +static void vdbeIncrMergerSetThreads(IncrMerger *pIncr){
|
| + pIncr->bUseThread = 1;
|
| + pIncr->pTask->file2.iEof -= pIncr->mxSz;
|
| +}
|
| +#endif /* SQLITE_MAX_WORKER_THREADS>0 */
|
| +
|
| +
|
| +
|
| +/*
|
| +** Recompute pMerger->aTree[iOut] by comparing the next keys on the
|
| +** two PmaReaders that feed that entry. Neither of the PmaReaders
|
| +** are advanced. This routine merely does the comparison.
|
| +*/
|
| +static void vdbeMergeEngineCompare(
|
| + MergeEngine *pMerger, /* Merge engine containing PmaReaders to compare */
|
| + int iOut /* Store the result in pMerger->aTree[iOut] */
|
| +){
|
| + int i1;
|
| + int i2;
|
| + int iRes;
|
| + PmaReader *p1;
|
| + PmaReader *p2;
|
| +
|
| + assert( iOut<pMerger->nTree && iOut>0 );
|
| +
|
| + if( iOut>=(pMerger->nTree/2) ){
|
| + i1 = (iOut - pMerger->nTree/2) * 2;
|
| + i2 = i1 + 1;
|
| + }else{
|
| + i1 = pMerger->aTree[iOut*2];
|
| + i2 = pMerger->aTree[iOut*2+1];
|
| + }
|
| +
|
| + p1 = &pMerger->aReadr[i1];
|
| + p2 = &pMerger->aReadr[i2];
|
| +
|
| + if( p1->pFd==0 ){
|
| + iRes = i2;
|
| + }else if( p2->pFd==0 ){
|
| + iRes = i1;
|
| + }else{
|
| + SortSubtask *pTask = pMerger->pTask;
|
| + int bCached = 0;
|
| + int res;
|
| + assert( pTask->pUnpacked!=0 ); /* from vdbeSortSubtaskMain() */
|
| + res = pTask->xCompare(
|
| + pTask, &bCached, p1->aKey, p1->nKey, p2->aKey, p2->nKey
|
| + );
|
| + if( res<=0 ){
|
| + iRes = i1;
|
| + }else{
|
| + iRes = i2;
|
| + }
|
| + }
|
| +
|
| + pMerger->aTree[iOut] = iRes;
|
| +}
|
| +
|
| +/*
|
| +** Allowed values for the eMode parameter to vdbeMergeEngineInit()
|
| +** and vdbePmaReaderIncrMergeInit().
|
| +**
|
| +** Only INCRINIT_NORMAL is valid in single-threaded builds (when
|
| +** SQLITE_MAX_WORKER_THREADS==0). The other values are only used
|
| +** when there exists one or more separate worker threads.
|
| +*/
|
| +#define INCRINIT_NORMAL 0
|
| +#define INCRINIT_TASK 1
|
| +#define INCRINIT_ROOT 2
|
| +
|
| +/*
|
| +** Forward reference required as the vdbeIncrMergeInit() and
|
| +** vdbePmaReaderIncrInit() routines are called mutually recursively when
|
| +** building a merge tree.
|
| +*/
|
| +static int vdbePmaReaderIncrInit(PmaReader *pReadr, int eMode);
|
| +
|
| +/*
|
| +** Initialize the MergeEngine object passed as the second argument. Once this
|
| +** function returns, the first key of merged data may be read from the
|
| +** MergeEngine object in the usual fashion.
|
| +**
|
| +** If argument eMode is INCRINIT_ROOT, then it is assumed that any IncrMerge
|
| +** objects attached to the PmaReader objects that the merger reads from have
|
| +** already been populated, but that they have not yet populated aFile[0] and
|
| +** set the PmaReader objects up to read from it. In this case all that is
|
| +** required is to call vdbePmaReaderNext() on each PmaReader to point it at
|
| +** its first key.
|
| +**
|
| +** Otherwise, if eMode is any value other than INCRINIT_ROOT, then use
|
| +** vdbePmaReaderIncrMergeInit() to initialize each PmaReader that feeds data
|
| +** to pMerger.
|
| +**
|
| +** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
|
| +*/
|
| +static int vdbeMergeEngineInit(
|
| + SortSubtask *pTask, /* Thread that will run pMerger */
|
| + MergeEngine *pMerger, /* MergeEngine to initialize */
|
| + int eMode /* One of the INCRINIT_XXX constants */
|
| +){
|
| + int rc = SQLITE_OK; /* Return code */
|
| + int i; /* For looping over PmaReader objects */
|
| + int nTree = pMerger->nTree;
|
| +
|
| + /* eMode is always INCRINIT_NORMAL in single-threaded mode */
|
| + assert( SQLITE_MAX_WORKER_THREADS>0 || eMode==INCRINIT_NORMAL );
|
| +
|
| + /* Verify that the MergeEngine is assigned to a single thread */
|
| + assert( pMerger->pTask==0 );
|
| + pMerger->pTask = pTask;
|
| +
|
| + for(i=0; i<nTree; i++){
|
| + if( SQLITE_MAX_WORKER_THREADS>0 && eMode==INCRINIT_ROOT ){
|
| + /* PmaReaders should be normally initialized in order, as if they are
|
| + ** reading from the same temp file this makes for more linear file IO.
|
| + ** However, in the INCRINIT_ROOT case, if PmaReader aReadr[nTask-1] is
|
| + ** in use it will block the vdbePmaReaderNext() call while it uses
|
| + ** the main thread to fill its buffer. So calling PmaReaderNext()
|
| + ** on this PmaReader before any of the multi-threaded PmaReaders takes
|
| + ** better advantage of multi-processor hardware. */
|
| + rc = vdbePmaReaderNext(&pMerger->aReadr[nTree-i-1]);
|
| + }else{
|
| + rc = vdbePmaReaderIncrInit(&pMerger->aReadr[i], INCRINIT_NORMAL);
|
| + }
|
| + if( rc!=SQLITE_OK ) return rc;
|
| + }
|
| +
|
| + for(i=pMerger->nTree-1; i>0; i--){
|
| + vdbeMergeEngineCompare(pMerger, i);
|
| + }
|
| + return pTask->pUnpacked->errCode;
|
| +}
|
| +
|
| +/*
|
| +** The PmaReader passed as the first argument is guaranteed to be an
|
| +** incremental-reader (pReadr->pIncr!=0). This function serves to open
|
| +** and/or initialize the temp file related fields of the IncrMerge
|
| +** object at (pReadr->pIncr).
|
| +**
|
| +** If argument eMode is set to INCRINIT_NORMAL, then all PmaReaders
|
| +** in the sub-tree headed by pReadr are also initialized. Data is then
|
| +** loaded into the buffers belonging to pReadr and it is set to point to
|
| +** the first key in its range.
|
| +**
|
| +** If argument eMode is set to INCRINIT_TASK, then pReadr is guaranteed
|
| +** to be a multi-threaded PmaReader and this function is being called in a
|
| +** background thread. In this case all PmaReaders in the sub-tree are
|
| +** initialized as for INCRINIT_NORMAL and the aFile[1] buffer belonging to
|
| +** pReadr is populated. However, pReadr itself is not set up to point
|
| +** to its first key. A call to vdbePmaReaderNext() is still required to do
|
| +** that.
|
| +**
|
| +** The reason this function does not call vdbePmaReaderNext() immediately
|
| +** in the INCRINIT_TASK case is that vdbePmaReaderNext() assumes that it has
|
| +** to block on thread (pTask->thread) before accessing aFile[1]. But, since
|
| +** this entire function is being run by thread (pTask->thread), that will
|
| +** lead to the current background thread attempting to join itself.
|
| +**
|
| +** Finally, if argument eMode is set to INCRINIT_ROOT, it may be assumed
|
| +** that pReadr->pIncr is a multi-threaded IncrMerge objects, and that all
|
| +** child-trees have already been initialized using IncrInit(INCRINIT_TASK).
|
| +** In this case vdbePmaReaderNext() is called on all child PmaReaders and
|
| +** the current PmaReader set to point to the first key in its range.
|
| +**
|
| +** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
|
| +*/
|
| +static int vdbePmaReaderIncrMergeInit(PmaReader *pReadr, int eMode){
|
| + int rc = SQLITE_OK;
|
| + IncrMerger *pIncr = pReadr->pIncr;
|
| + SortSubtask *pTask = pIncr->pTask;
|
| + sqlite3 *db = pTask->pSorter->db;
|
| +
|
| + /* eMode is always INCRINIT_NORMAL in single-threaded mode */
|
| + assert( SQLITE_MAX_WORKER_THREADS>0 || eMode==INCRINIT_NORMAL );
|
| +
|
| + rc = vdbeMergeEngineInit(pTask, pIncr->pMerger, eMode);
|
| +
|
| + /* Set up the required files for pIncr. A multi-theaded IncrMerge object
|
| + ** requires two temp files to itself, whereas a single-threaded object
|
| + ** only requires a region of pTask->file2. */
|
| + if( rc==SQLITE_OK ){
|
| + int mxSz = pIncr->mxSz;
|
| +#if SQLITE_MAX_WORKER_THREADS>0
|
| + if( pIncr->bUseThread ){
|
| + rc = vdbeSorterOpenTempFile(db, mxSz, &pIncr->aFile[0].pFd);
|
| + if( rc==SQLITE_OK ){
|
| + rc = vdbeSorterOpenTempFile(db, mxSz, &pIncr->aFile[1].pFd);
|
| + }
|
| + }else
|
| +#endif
|
| + /*if( !pIncr->bUseThread )*/{
|
| + if( pTask->file2.pFd==0 ){
|
| + assert( pTask->file2.iEof>0 );
|
| + rc = vdbeSorterOpenTempFile(db, pTask->file2.iEof, &pTask->file2.pFd);
|
| + pTask->file2.iEof = 0;
|
| + }
|
| + if( rc==SQLITE_OK ){
|
| + pIncr->aFile[1].pFd = pTask->file2.pFd;
|
| + pIncr->iStartOff = pTask->file2.iEof;
|
| + pTask->file2.iEof += mxSz;
|
| + }
|
| + }
|
| + }
|
| +
|
| +#if SQLITE_MAX_WORKER_THREADS>0
|
| + if( rc==SQLITE_OK && pIncr->bUseThread ){
|
| + /* Use the current thread to populate aFile[1], even though this
|
| + ** PmaReader is multi-threaded. If this is an INCRINIT_TASK object,
|
| + ** then this function is already running in background thread
|
| + ** pIncr->pTask->thread.
|
| + **
|
| + ** If this is the INCRINIT_ROOT object, then it is running in the
|
| + ** main VDBE thread. But that is Ok, as that thread cannot return
|
| + ** control to the VDBE or proceed with anything useful until the
|
| + ** first results are ready from this merger object anyway.
|
| + */
|
| + assert( eMode==INCRINIT_ROOT || eMode==INCRINIT_TASK );
|
| + rc = vdbeIncrPopulate(pIncr);
|
| + }
|
| +#endif
|
| +
|
| + if( rc==SQLITE_OK && (SQLITE_MAX_WORKER_THREADS==0 || eMode!=INCRINIT_TASK) ){
|
| + rc = vdbePmaReaderNext(pReadr);
|
| + }
|
| +
|
| + return rc;
|
| +}
|
| +
|
| +#if SQLITE_MAX_WORKER_THREADS>0
|
| +/*
|
| +** The main routine for vdbePmaReaderIncrMergeInit() operations run in
|
| +** background threads.
|
| +*/
|
| +static void *vdbePmaReaderBgIncrInit(void *pCtx){
|
| + PmaReader *pReader = (PmaReader*)pCtx;
|
| + void *pRet = SQLITE_INT_TO_PTR(
|
| + vdbePmaReaderIncrMergeInit(pReader,INCRINIT_TASK)
|
| + );
|
| + pReader->pIncr->pTask->bDone = 1;
|
| + return pRet;
|
| +}
|
| +#endif
|
| +
|
| +/*
|
| +** If the PmaReader passed as the first argument is not an incremental-reader
|
| +** (if pReadr->pIncr==0), then this function is a no-op. Otherwise, it invokes
|
| +** the vdbePmaReaderIncrMergeInit() function with the parameters passed to
|
| +** this routine to initialize the incremental merge.
|
| +**
|
| +** If the IncrMerger object is multi-threaded (IncrMerger.bUseThread==1),
|
| +** then a background thread is launched to call vdbePmaReaderIncrMergeInit().
|
| +** Or, if the IncrMerger is single threaded, the same function is called
|
| +** using the current thread.
|
| +*/
|
| +static int vdbePmaReaderIncrInit(PmaReader *pReadr, int eMode){
|
| + IncrMerger *pIncr = pReadr->pIncr; /* Incremental merger */
|
| + int rc = SQLITE_OK; /* Return code */
|
| + if( pIncr ){
|
| +#if SQLITE_MAX_WORKER_THREADS>0
|
| + assert( pIncr->bUseThread==0 || eMode==INCRINIT_TASK );
|
| + if( pIncr->bUseThread ){
|
| + void *pCtx = (void*)pReadr;
|
| + rc = vdbeSorterCreateThread(pIncr->pTask, vdbePmaReaderBgIncrInit, pCtx);
|
| + }else
|
| +#endif
|
| + {
|
| + rc = vdbePmaReaderIncrMergeInit(pReadr, eMode);
|
| + }
|
| + }
|
| + return rc;
|
| +}
|
| +
|
| +/*
|
| +** Allocate a new MergeEngine object to merge the contents of nPMA level-0
|
| +** PMAs from pTask->file. If no error occurs, set *ppOut to point to
|
| +** the new object and return SQLITE_OK. Or, if an error does occur, set *ppOut
|
| +** to NULL and return an SQLite error code.
|
| +**
|
| +** When this function is called, *piOffset is set to the offset of the
|
| +** first PMA to read from pTask->file. Assuming no error occurs, it is
|
| +** set to the offset immediately following the last byte of the last
|
| +** PMA before returning. If an error does occur, then the final value of
|
| +** *piOffset is undefined.
|
| +*/
|
| +static int vdbeMergeEngineLevel0(
|
| + SortSubtask *pTask, /* Sorter task to read from */
|
| + int nPMA, /* Number of PMAs to read */
|
| + i64 *piOffset, /* IN/OUT: Readr offset in pTask->file */
|
| + MergeEngine **ppOut /* OUT: New merge-engine */
|
| +){
|
| + MergeEngine *pNew; /* Merge engine to return */
|
| + i64 iOff = *piOffset;
|
| + int i;
|
| + int rc = SQLITE_OK;
|
| +
|
| + *ppOut = pNew = vdbeMergeEngineNew(nPMA);
|
| + if( pNew==0 ) rc = SQLITE_NOMEM;
|
| +
|
| + for(i=0; i<nPMA && rc==SQLITE_OK; i++){
|
| + i64 nDummy;
|
| + PmaReader *pReadr = &pNew->aReadr[i];
|
| + rc = vdbePmaReaderInit(pTask, &pTask->file, iOff, pReadr, &nDummy);
|
| + iOff = pReadr->iEof;
|
| + }
|
| +
|
| + if( rc!=SQLITE_OK ){
|
| + vdbeMergeEngineFree(pNew);
|
| + *ppOut = 0;
|
| + }
|
| + *piOffset = iOff;
|
| + return rc;
|
| +}
|
| +
|
| +/*
|
| +** Return the depth of a tree comprising nPMA PMAs, assuming a fanout of
|
| +** SORTER_MAX_MERGE_COUNT. The returned value does not include leaf nodes.
|
| +**
|
| +** i.e.
|
| +**
|
| +** nPMA<=16 -> TreeDepth() == 0
|
| +** nPMA<=256 -> TreeDepth() == 1
|
| +** nPMA<=65536 -> TreeDepth() == 2
|
| +*/
|
| +static int vdbeSorterTreeDepth(int nPMA){
|
| + int nDepth = 0;
|
| + i64 nDiv = SORTER_MAX_MERGE_COUNT;
|
| + while( nDiv < (i64)nPMA ){
|
| + nDiv = nDiv * SORTER_MAX_MERGE_COUNT;
|
| + nDepth++;
|
| + }
|
| + return nDepth;
|
| +}
|
| +
|
| +/*
|
| +** pRoot is the root of an incremental merge-tree with depth nDepth (according
|
| +** to vdbeSorterTreeDepth()). pLeaf is the iSeq'th leaf to be added to the
|
| +** tree, counting from zero. This function adds pLeaf to the tree.
|
| +**
|
| +** If successful, SQLITE_OK is returned. If an error occurs, an SQLite error
|
| +** code is returned and pLeaf is freed.
|
| +*/
|
| +static int vdbeSorterAddToTree(
|
| + SortSubtask *pTask, /* Task context */
|
| + int nDepth, /* Depth of tree according to TreeDepth() */
|
| + int iSeq, /* Sequence number of leaf within tree */
|
| + MergeEngine *pRoot, /* Root of tree */
|
| + MergeEngine *pLeaf /* Leaf to add to tree */
|
| +){
|
| + int rc = SQLITE_OK;
|
| + int nDiv = 1;
|
| + int i;
|
| + MergeEngine *p = pRoot;
|
| + IncrMerger *pIncr;
|
| +
|
| + rc = vdbeIncrMergerNew(pTask, pLeaf, &pIncr);
|
| +
|
| + for(i=1; i<nDepth; i++){
|
| + nDiv = nDiv * SORTER_MAX_MERGE_COUNT;
|
| + }
|
| +
|
| + for(i=1; i<nDepth && rc==SQLITE_OK; i++){
|
| + int iIter = (iSeq / nDiv) % SORTER_MAX_MERGE_COUNT;
|
| + PmaReader *pReadr = &p->aReadr[iIter];
|
| +
|
| + if( pReadr->pIncr==0 ){
|
| + MergeEngine *pNew = vdbeMergeEngineNew(SORTER_MAX_MERGE_COUNT);
|
| + if( pNew==0 ){
|
| + rc = SQLITE_NOMEM;
|
| + }else{
|
| + rc = vdbeIncrMergerNew(pTask, pNew, &pReadr->pIncr);
|
| + }
|
| + }
|
| + if( rc==SQLITE_OK ){
|
| + p = pReadr->pIncr->pMerger;
|
| + nDiv = nDiv / SORTER_MAX_MERGE_COUNT;
|
| + }
|
| + }
|
| +
|
| + if( rc==SQLITE_OK ){
|
| + p->aReadr[iSeq % SORTER_MAX_MERGE_COUNT].pIncr = pIncr;
|
| + }else{
|
| + vdbeIncrFree(pIncr);
|
| + }
|
| + return rc;
|
| +}
|
| +
|
| +/*
|
| +** This function is called as part of a SorterRewind() operation on a sorter
|
| +** that has already written two or more level-0 PMAs to one or more temp
|
| +** files. It builds a tree of MergeEngine/IncrMerger/PmaReader objects that
|
| +** can be used to incrementally merge all PMAs on disk.
|
| +**
|
| +** If successful, SQLITE_OK is returned and *ppOut set to point to the
|
| +** MergeEngine object at the root of the tree before returning. Or, if an
|
| +** error occurs, an SQLite error code is returned and the final value
|
| +** of *ppOut is undefined.
|
| +*/
|
| +static int vdbeSorterMergeTreeBuild(
|
| + VdbeSorter *pSorter, /* The VDBE cursor that implements the sort */
|
| + MergeEngine **ppOut /* Write the MergeEngine here */
|
| +){
|
| + MergeEngine *pMain = 0;
|
| + int rc = SQLITE_OK;
|
| + int iTask;
|
| +
|
| +#if SQLITE_MAX_WORKER_THREADS>0
|
| + /* If the sorter uses more than one task, then create the top-level
|
| + ** MergeEngine here. This MergeEngine will read data from exactly
|
| + ** one PmaReader per sub-task. */
|
| + assert( pSorter->bUseThreads || pSorter->nTask==1 );
|
| + if( pSorter->nTask>1 ){
|
| + pMain = vdbeMergeEngineNew(pSorter->nTask);
|
| + if( pMain==0 ) rc = SQLITE_NOMEM;
|
| + }
|
| +#endif
|
| +
|
| + for(iTask=0; rc==SQLITE_OK && iTask<pSorter->nTask; iTask++){
|
| + SortSubtask *pTask = &pSorter->aTask[iTask];
|
| + assert( pTask->nPMA>0 || SQLITE_MAX_WORKER_THREADS>0 );
|
| + if( SQLITE_MAX_WORKER_THREADS==0 || pTask->nPMA ){
|
| + MergeEngine *pRoot = 0; /* Root node of tree for this task */
|
| + int nDepth = vdbeSorterTreeDepth(pTask->nPMA);
|
| + i64 iReadOff = 0;
|
| +
|
| + if( pTask->nPMA<=SORTER_MAX_MERGE_COUNT ){
|
| + rc = vdbeMergeEngineLevel0(pTask, pTask->nPMA, &iReadOff, &pRoot);
|
| + }else{
|
| + int i;
|
| + int iSeq = 0;
|
| + pRoot = vdbeMergeEngineNew(SORTER_MAX_MERGE_COUNT);
|
| + if( pRoot==0 ) rc = SQLITE_NOMEM;
|
| + for(i=0; i<pTask->nPMA && rc==SQLITE_OK; i += SORTER_MAX_MERGE_COUNT){
|
| + MergeEngine *pMerger = 0; /* New level-0 PMA merger */
|
| + int nReader; /* Number of level-0 PMAs to merge */
|
| +
|
| + nReader = MIN(pTask->nPMA - i, SORTER_MAX_MERGE_COUNT);
|
| + rc = vdbeMergeEngineLevel0(pTask, nReader, &iReadOff, &pMerger);
|
| + if( rc==SQLITE_OK ){
|
| + rc = vdbeSorterAddToTree(pTask, nDepth, iSeq++, pRoot, pMerger);
|
| + }
|
| + }
|
| + }
|
| +
|
| + if( rc==SQLITE_OK ){
|
| +#if SQLITE_MAX_WORKER_THREADS>0
|
| + if( pMain!=0 ){
|
| + rc = vdbeIncrMergerNew(pTask, pRoot, &pMain->aReadr[iTask].pIncr);
|
| + }else
|
| +#endif
|
| + {
|
| + assert( pMain==0 );
|
| + pMain = pRoot;
|
| + }
|
| + }else{
|
| + vdbeMergeEngineFree(pRoot);
|
| + }
|
| + }
|
| + }
|
| +
|
| + if( rc!=SQLITE_OK ){
|
| + vdbeMergeEngineFree(pMain);
|
| + pMain = 0;
|
| + }
|
| + *ppOut = pMain;
|
| + return rc;
|
| +}
|
| +
|
| +/*
|
| +** This function is called as part of an sqlite3VdbeSorterRewind() operation
|
| +** on a sorter that has written two or more PMAs to temporary files. It sets
|
| +** up either VdbeSorter.pMerger (for single threaded sorters) or pReader
|
| +** (for multi-threaded sorters) so that it can be used to iterate through
|
| +** all records stored in the sorter.
|
| +**
|
| +** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
|
| +*/
|
| +static int vdbeSorterSetupMerge(VdbeSorter *pSorter){
|
| + int rc; /* Return code */
|
| + SortSubtask *pTask0 = &pSorter->aTask[0];
|
| + MergeEngine *pMain = 0;
|
| +#if SQLITE_MAX_WORKER_THREADS
|
| + sqlite3 *db = pTask0->pSorter->db;
|
| + int i;
|
| + SorterCompare xCompare = vdbeSorterGetCompare(pSorter);
|
| + for(i=0; i<pSorter->nTask; i++){
|
| + pSorter->aTask[i].xCompare = xCompare;
|
| + }
|
| +#endif
|
| +
|
| + rc = vdbeSorterMergeTreeBuild(pSorter, &pMain);
|
| + if( rc==SQLITE_OK ){
|
| +#if SQLITE_MAX_WORKER_THREADS
|
| + assert( pSorter->bUseThreads==0 || pSorter->nTask>1 );
|
| + if( pSorter->bUseThreads ){
|
| + int iTask;
|
| + PmaReader *pReadr = 0;
|
| + SortSubtask *pLast = &pSorter->aTask[pSorter->nTask-1];
|
| + rc = vdbeSortAllocUnpacked(pLast);
|
| + if( rc==SQLITE_OK ){
|
| + pReadr = (PmaReader*)sqlite3DbMallocZero(db, sizeof(PmaReader));
|
| + pSorter->pReader = pReadr;
|
| + if( pReadr==0 ) rc = SQLITE_NOMEM;
|
| + }
|
| + if( rc==SQLITE_OK ){
|
| + rc = vdbeIncrMergerNew(pLast, pMain, &pReadr->pIncr);
|
| + if( rc==SQLITE_OK ){
|
| + vdbeIncrMergerSetThreads(pReadr->pIncr);
|
| + for(iTask=0; iTask<(pSorter->nTask-1); iTask++){
|
| + IncrMerger *pIncr;
|
| + if( (pIncr = pMain->aReadr[iTask].pIncr) ){
|
| + vdbeIncrMergerSetThreads(pIncr);
|
| + assert( pIncr->pTask!=pLast );
|
| + }
|
| + }
|
| + for(iTask=0; rc==SQLITE_OK && iTask<pSorter->nTask; iTask++){
|
| + /* Check that:
|
| + **
|
| + ** a) The incremental merge object is configured to use the
|
| + ** right task, and
|
| + ** b) If it is using task (nTask-1), it is configured to run
|
| + ** in single-threaded mode. This is important, as the
|
| + ** root merge (INCRINIT_ROOT) will be using the same task
|
| + ** object.
|
| + */
|
| + PmaReader *p = &pMain->aReadr[iTask];
|
| + assert( p->pIncr==0 || (
|
| + (p->pIncr->pTask==&pSorter->aTask[iTask]) /* a */
|
| + && (iTask!=pSorter->nTask-1 || p->pIncr->bUseThread==0) /* b */
|
| + ));
|
| + rc = vdbePmaReaderIncrInit(p, INCRINIT_TASK);
|
| + }
|
| + }
|
| + pMain = 0;
|
| + }
|
| + if( rc==SQLITE_OK ){
|
| + rc = vdbePmaReaderIncrMergeInit(pReadr, INCRINIT_ROOT);
|
| + }
|
| + }else
|
| +#endif
|
| + {
|
| + rc = vdbeMergeEngineInit(pTask0, pMain, INCRINIT_NORMAL);
|
| + pSorter->pMerger = pMain;
|
| + pMain = 0;
|
| + }
|
| + }
|
| +
|
| + if( rc!=SQLITE_OK ){
|
| + vdbeMergeEngineFree(pMain);
|
| + }
|
| + return rc;
|
| +}
|
| +
|
| +
|
| +/*
|
| +** Once the sorter has been populated by calls to sqlite3VdbeSorterWrite,
|
| +** this function is called to prepare for iterating through the records
|
| +** in sorted order.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3VdbeSorterRewind(const VdbeCursor *pCsr, int *pbEof){
|
| + VdbeSorter *pSorter;
|
| + int rc = SQLITE_OK; /* Return code */
|
| +
|
| + assert( pCsr->eCurType==CURTYPE_SORTER );
|
| + pSorter = pCsr->uc.pSorter;
|
| + assert( pSorter );
|
| +
|
| + /* If no data has been written to disk, then do not do so now. Instead,
|
| + ** sort the VdbeSorter.pRecord list. The vdbe layer will read data directly
|
| + ** from the in-memory list. */
|
| + if( pSorter->bUsePMA==0 ){
|
| + if( pSorter->list.pList ){
|
| + *pbEof = 0;
|
| + rc = vdbeSorterSort(&pSorter->aTask[0], &pSorter->list);
|
| + }else{
|
| + *pbEof = 1;
|
| + }
|
| + return rc;
|
| + }
|
| +
|
| + /* Write the current in-memory list to a PMA. When the VdbeSorterWrite()
|
| + ** function flushes the contents of memory to disk, it immediately always
|
| + ** creates a new list consisting of a single key immediately afterwards.
|
| + ** So the list is never empty at this point. */
|
| + assert( pSorter->list.pList );
|
| + rc = vdbeSorterFlushPMA(pSorter);
|
| +
|
| + /* Join all threads */
|
| + rc = vdbeSorterJoinAll(pSorter, rc);
|
| +
|
| + vdbeSorterRewindDebug("rewind");
|
| +
|
| + /* Assuming no errors have occurred, set up a merger structure to
|
| + ** incrementally read and merge all remaining PMAs. */
|
| + assert( pSorter->pReader==0 );
|
| + if( rc==SQLITE_OK ){
|
| + rc = vdbeSorterSetupMerge(pSorter);
|
| + *pbEof = 0;
|
| + }
|
| +
|
| + vdbeSorterRewindDebug("rewinddone");
|
| + return rc;
|
| +}
|
| +
|
| +/*
|
| +** Advance to the next element in the sorter.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *db, const VdbeCursor *pCsr, int *pbEof){
|
| + VdbeSorter *pSorter;
|
| + int rc; /* Return code */
|
| +
|
| + assert( pCsr->eCurType==CURTYPE_SORTER );
|
| + pSorter = pCsr->uc.pSorter;
|
| + assert( pSorter->bUsePMA || (pSorter->pReader==0 && pSorter->pMerger==0) );
|
| + if( pSorter->bUsePMA ){
|
| + assert( pSorter->pReader==0 || pSorter->pMerger==0 );
|
| + assert( pSorter->bUseThreads==0 || pSorter->pReader );
|
| + assert( pSorter->bUseThreads==1 || pSorter->pMerger );
|
| +#if SQLITE_MAX_WORKER_THREADS>0
|
| + if( pSorter->bUseThreads ){
|
| + rc = vdbePmaReaderNext(pSorter->pReader);
|
| + *pbEof = (pSorter->pReader->pFd==0);
|
| + }else
|
| +#endif
|
| + /*if( !pSorter->bUseThreads )*/ {
|
| + assert( pSorter->pMerger!=0 );
|
| + assert( pSorter->pMerger->pTask==(&pSorter->aTask[0]) );
|
| + rc = vdbeMergeEngineStep(pSorter->pMerger, pbEof);
|
| + }
|
| + }else{
|
| + SorterRecord *pFree = pSorter->list.pList;
|
| + pSorter->list.pList = pFree->u.pNext;
|
| + pFree->u.pNext = 0;
|
| + if( pSorter->list.aMemory==0 ) vdbeSorterRecordFree(db, pFree);
|
| + *pbEof = !pSorter->list.pList;
|
| + rc = SQLITE_OK;
|
| + }
|
| + return rc;
|
| +}
|
| +
|
| +/*
|
| +** Return a pointer to a buffer owned by the sorter that contains the
|
| +** current key.
|
| +*/
|
| +static void *vdbeSorterRowkey(
|
| + const VdbeSorter *pSorter, /* Sorter object */
|
| + int *pnKey /* OUT: Size of current key in bytes */
|
| +){
|
| + void *pKey;
|
| + if( pSorter->bUsePMA ){
|
| + PmaReader *pReader;
|
| +#if SQLITE_MAX_WORKER_THREADS>0
|
| + if( pSorter->bUseThreads ){
|
| + pReader = pSorter->pReader;
|
| + }else
|
| +#endif
|
| + /*if( !pSorter->bUseThreads )*/{
|
| + pReader = &pSorter->pMerger->aReadr[pSorter->pMerger->aTree[1]];
|
| + }
|
| + *pnKey = pReader->nKey;
|
| + pKey = pReader->aKey;
|
| + }else{
|
| + *pnKey = pSorter->list.pList->nVal;
|
| + pKey = SRVAL(pSorter->list.pList);
|
| + }
|
| + return pKey;
|
| +}
|
| +
|
| +/*
|
| +** Copy the current sorter key into the memory cell pOut.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(const VdbeCursor *pCsr, Mem *pOut){
|
| + VdbeSorter *pSorter;
|
| + void *pKey; int nKey; /* Sorter key to copy into pOut */
|
| +
|
| + assert( pCsr->eCurType==CURTYPE_SORTER );
|
| + pSorter = pCsr->uc.pSorter;
|
| + pKey = vdbeSorterRowkey(pSorter, &nKey);
|
| + if( sqlite3VdbeMemClearAndResize(pOut, nKey) ){
|
| + return SQLITE_NOMEM;
|
| + }
|
| + pOut->n = nKey;
|
| + MemSetTypeFlag(pOut, MEM_Blob);
|
| + memcpy(pOut->z, pKey, nKey);
|
| +
|
| + return SQLITE_OK;
|
| +}
|
| +
|
| +/*
|
| +** Compare the key in memory cell pVal with the key that the sorter cursor
|
| +** passed as the first argument currently points to. For the purposes of
|
| +** the comparison, ignore the rowid field at the end of each record.
|
| +**
|
| +** If the sorter cursor key contains any NULL values, consider it to be
|
| +** less than pVal. Even if pVal also contains NULL values.
|
| +**
|
| +** If an error occurs, return an SQLite error code (i.e. SQLITE_NOMEM).
|
| +** Otherwise, set *pRes to a negative, zero or positive value if the
|
| +** key in pVal is smaller than, equal to or larger than the current sorter
|
| +** key.
|
| +**
|
| +** This routine forms the core of the OP_SorterCompare opcode, which in
|
| +** turn is used to verify uniqueness when constructing a UNIQUE INDEX.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3VdbeSorterCompare(
|
| + const VdbeCursor *pCsr, /* Sorter cursor */
|
| + Mem *pVal, /* Value to compare to current sorter key */
|
| + int nKeyCol, /* Compare this many columns */
|
| + int *pRes /* OUT: Result of comparison */
|
| +){
|
| + VdbeSorter *pSorter;
|
| + UnpackedRecord *r2;
|
| + KeyInfo *pKeyInfo;
|
| + int i;
|
| + void *pKey; int nKey; /* Sorter key to compare pVal with */
|
| +
|
| + assert( pCsr->eCurType==CURTYPE_SORTER );
|
| + pSorter = pCsr->uc.pSorter;
|
| + r2 = pSorter->pUnpacked;
|
| + pKeyInfo = pCsr->pKeyInfo;
|
| + if( r2==0 ){
|
| + char *p;
|
| + r2 = pSorter->pUnpacked = sqlite3VdbeAllocUnpackedRecord(pKeyInfo,0,0,&p);
|
| + assert( pSorter->pUnpacked==(UnpackedRecord*)p );
|
| + if( r2==0 ) return SQLITE_NOMEM;
|
| + r2->nField = nKeyCol;
|
| + }
|
| + assert( r2->nField==nKeyCol );
|
| +
|
| + pKey = vdbeSorterRowkey(pSorter, &nKey);
|
| + sqlite3VdbeRecordUnpack(pKeyInfo, nKey, pKey, r2);
|
| + for(i=0; i<nKeyCol; i++){
|
| + if( r2->aMem[i].flags & MEM_Null ){
|
| + *pRes = -1;
|
| + return SQLITE_OK;
|
| + }
|
| + }
|
| +
|
| + *pRes = sqlite3VdbeRecordCompare(pVal->n, pVal->z, r2);
|
| + return SQLITE_OK;
|
| +}
|
| +
|
| +/************** End of vdbesort.c ********************************************/
|
| +/************** Begin file journal.c *****************************************/
|
| +/*
|
| +** 2007 August 22
|
| +**
|
| +** 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.
|
| +**
|
| +*************************************************************************
|
| +**
|
| +** This file implements a special kind of sqlite3_file object used
|
| +** by SQLite to create journal files if the atomic-write optimization
|
| +** is enabled.
|
| +**
|
| +** The distinctive characteristic of this sqlite3_file is that the
|
| +** actual on disk file is created lazily. When the file is created,
|
| +** the caller specifies a buffer size for an in-memory buffer to
|
| +** be used to service read() and write() requests. The actual file
|
| +** on disk is not created or populated until either:
|
| +**
|
| +** 1) The in-memory representation grows too large for the allocated
|
| +** buffer, or
|
| +** 2) The sqlite3JournalCreate() function is called.
|
| +*/
|
| +#ifdef SQLITE_ENABLE_ATOMIC_WRITE
|
| +/* #include "sqliteInt.h" */
|
| +
|
| +
|
| +/*
|
| +** A JournalFile object is a subclass of sqlite3_file used by
|
| +** as an open file handle for journal files.
|
| +*/
|
| +struct JournalFile {
|
| + sqlite3_io_methods *pMethod; /* I/O methods on journal files */
|
| + int nBuf; /* Size of zBuf[] in bytes */
|
| + char *zBuf; /* Space to buffer journal writes */
|
| + int iSize; /* Amount of zBuf[] currently used */
|
| + int flags; /* xOpen flags */
|
| + sqlite3_vfs *pVfs; /* The "real" underlying VFS */
|
| + sqlite3_file *pReal; /* The "real" underlying file descriptor */
|
| + const char *zJournal; /* Name of the journal file */
|
| +};
|
| +typedef struct JournalFile JournalFile;
|
| +
|
| +/*
|
| +** If it does not already exists, create and populate the on-disk file
|
| +** for JournalFile p.
|
| +*/
|
| +static int createFile(JournalFile *p){
|
| + int rc = SQLITE_OK;
|
| + if( !p->pReal ){
|
| + sqlite3_file *pReal = (sqlite3_file *)&p[1];
|
| + rc = sqlite3OsOpen(p->pVfs, p->zJournal, pReal, p->flags, 0);
|
| + if( rc==SQLITE_OK ){
|
| + p->pReal = pReal;
|
| + if( p->iSize>0 ){
|
| + assert(p->iSize<=p->nBuf);
|
| + rc = sqlite3OsWrite(p->pReal, p->zBuf, p->iSize, 0);
|
| + }
|
| + if( rc!=SQLITE_OK ){
|
| + /* If an error occurred while writing to the file, close it before
|
| + ** returning. This way, SQLite uses the in-memory journal data to
|
| + ** roll back changes made to the internal page-cache before this
|
| + ** function was called. */
|
| + sqlite3OsClose(pReal);
|
| + p->pReal = 0;
|
| + }
|
| + }
|
| + }
|
| + return rc;
|
| +}
|
| +
|
| +/*
|
| +** Close the file.
|
| +*/
|
| +static int jrnlClose(sqlite3_file *pJfd){
|
| + JournalFile *p = (JournalFile *)pJfd;
|
| + if( p->pReal ){
|
| + sqlite3OsClose(p->pReal);
|
| + }
|
| + sqlite3_free(p->zBuf);
|
| + return SQLITE_OK;
|
| +}
|
| +
|
| +/*
|
| +** Read data from the file.
|
| +*/
|
| +static int jrnlRead(
|
| + sqlite3_file *pJfd, /* The journal file from which to read */
|
| + void *zBuf, /* Put the results here */
|
| + int iAmt, /* Number of bytes to read */
|
| + sqlite_int64 iOfst /* Begin reading at this offset */
|
| +){
|
| + int rc = SQLITE_OK;
|
| + JournalFile *p = (JournalFile *)pJfd;
|
| + if( p->pReal ){
|
| + rc = sqlite3OsRead(p->pReal, zBuf, iAmt, iOfst);
|
| + }else if( (iAmt+iOfst)>p->iSize ){
|
| + rc = SQLITE_IOERR_SHORT_READ;
|
| + }else{
|
| + memcpy(zBuf, &p->zBuf[iOfst], iAmt);
|
| + }
|
| + return rc;
|
| +}
|
| +
|
| +/*
|
| +** Write data to the file.
|
| +*/
|
| +static int jrnlWrite(
|
| + sqlite3_file *pJfd, /* The journal file into which to write */
|
| + const void *zBuf, /* Take data to be written from here */
|
| + int iAmt, /* Number of bytes to write */
|
| + sqlite_int64 iOfst /* Begin writing at this offset into the file */
|
| +){
|
| + int rc = SQLITE_OK;
|
| + JournalFile *p = (JournalFile *)pJfd;
|
| + if( !p->pReal && (iOfst+iAmt)>p->nBuf ){
|
| + rc = createFile(p);
|
| + }
|
| + if( rc==SQLITE_OK ){
|
| + if( p->pReal ){
|
| + rc = sqlite3OsWrite(p->pReal, zBuf, iAmt, iOfst);
|
| + }else{
|
| + memcpy(&p->zBuf[iOfst], zBuf, iAmt);
|
| + if( p->iSize<(iOfst+iAmt) ){
|
| + p->iSize = (iOfst+iAmt);
|
| + }
|
| + }
|
| + }
|
| + return rc;
|
| +}
|
| +
|
| +/*
|
| +** Truncate the file.
|
| +*/
|
| +static int jrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size){
|
| + int rc = SQLITE_OK;
|
| + JournalFile *p = (JournalFile *)pJfd;
|
| + if( p->pReal ){
|
| + rc = sqlite3OsTruncate(p->pReal, size);
|
| + }else if( size<p->iSize ){
|
| + p->iSize = size;
|
| + }
|
| + return rc;
|
| +}
|
| +
|
| +/*
|
| +** Sync the file.
|
| +*/
|
| +static int jrnlSync(sqlite3_file *pJfd, int flags){
|
| + int rc;
|
| + JournalFile *p = (JournalFile *)pJfd;
|
| + if( p->pReal ){
|
| + rc = sqlite3OsSync(p->pReal, flags);
|
| + }else{
|
| + rc = SQLITE_OK;
|
| + }
|
| + return rc;
|
| +}
|
| +
|
| +/*
|
| +** Query the size of the file in bytes.
|
| +*/
|
| +static int jrnlFileSize(sqlite3_file *pJfd, sqlite_int64 *pSize){
|
| + int rc = SQLITE_OK;
|
| + JournalFile *p = (JournalFile *)pJfd;
|
| + if( p->pReal ){
|
| + rc = sqlite3OsFileSize(p->pReal, pSize);
|
| + }else{
|
| + *pSize = (sqlite_int64) p->iSize;
|
| + }
|
| + return rc;
|
| +}
|
| +
|
| +/*
|
| +** Table of methods for JournalFile sqlite3_file object.
|
| +*/
|
| +static struct sqlite3_io_methods JournalFileMethods = {
|
| + 1, /* iVersion */
|
| + jrnlClose, /* xClose */
|
| + jrnlRead, /* xRead */
|
| + jrnlWrite, /* xWrite */
|
| + jrnlTruncate, /* xTruncate */
|
| + jrnlSync, /* xSync */
|
| + jrnlFileSize, /* xFileSize */
|
| + 0, /* xLock */
|
| + 0, /* xUnlock */
|
| + 0, /* xCheckReservedLock */
|
| + 0, /* xFileControl */
|
| + 0, /* xSectorSize */
|
| + 0, /* xDeviceCharacteristics */
|
| + 0, /* xShmMap */
|
| + 0, /* xShmLock */
|
| + 0, /* xShmBarrier */
|
| + 0 /* xShmUnmap */
|
| +};
|
| +
|
| +/*
|
| +** Open a journal file.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3JournalOpen(
|
| + sqlite3_vfs *pVfs, /* The VFS to use for actual file I/O */
|
| + const char *zName, /* Name of the journal file */
|
| + sqlite3_file *pJfd, /* Preallocated, blank file handle */
|
| + int flags, /* Opening flags */
|
| + int nBuf /* Bytes buffered before opening the file */
|
| +){
|
| + JournalFile *p = (JournalFile *)pJfd;
|
| + memset(p, 0, sqlite3JournalSize(pVfs));
|
| + if( nBuf>0 ){
|
| + p->zBuf = sqlite3MallocZero(nBuf);
|
| + if( !p->zBuf ){
|
| + return SQLITE_NOMEM;
|
| + }
|
| + }else{
|
| + return sqlite3OsOpen(pVfs, zName, pJfd, flags, 0);
|
| + }
|
| + p->pMethod = &JournalFileMethods;
|
| + p->nBuf = nBuf;
|
| + p->flags = flags;
|
| + p->zJournal = zName;
|
| + p->pVfs = pVfs;
|
| + return SQLITE_OK;
|
| +}
|
| +
|
| +/*
|
| +** If the argument p points to a JournalFile structure, and the underlying
|
| +** file has not yet been created, create it now.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3JournalCreate(sqlite3_file *p){
|
| + if( p->pMethods!=&JournalFileMethods ){
|
| + return SQLITE_OK;
|
| + }
|
| + return createFile((JournalFile *)p);
|
| +}
|
| +
|
| +/*
|
| +** The file-handle passed as the only argument is guaranteed to be an open
|
| +** file. It may or may not be of class JournalFile. If the file is a
|
| +** JournalFile, and the underlying file on disk has not yet been opened,
|
| +** return 0. Otherwise, return 1.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3JournalExists(sqlite3_file *p){
|
| + return (p->pMethods!=&JournalFileMethods || ((JournalFile *)p)->pReal!=0);
|
| +}
|
| +
|
| +/*
|
| +** Return the number of bytes required to store a JournalFile that uses vfs
|
| +** pVfs to create the underlying on-disk files.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3JournalSize(sqlite3_vfs *pVfs){
|
| + return (pVfs->szOsFile+sizeof(JournalFile));
|
| +}
|
| +#endif
|
| +
|
| +/************** End of journal.c *********************************************/
|
| +/************** Begin file memjournal.c **************************************/
|
| +/*
|
| +** 2008 October 7
|
| +**
|
| +** 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.
|
| +**
|
| +*************************************************************************
|
| +**
|
| +** This file contains code use to implement an in-memory rollback journal.
|
| +** The in-memory rollback journal is used to journal transactions for
|
| +** ":memory:" databases and when the journal_mode=MEMORY pragma is used.
|
| +*/
|
| +/* #include "sqliteInt.h" */
|
| +
|
| +/* Forward references to internal structures */
|
| +typedef struct MemJournal MemJournal;
|
| +typedef struct FilePoint FilePoint;
|
| +typedef struct FileChunk FileChunk;
|
| +
|
| +/* Space to hold the rollback journal is allocated in increments of
|
| +** this many bytes.
|
| +**
|
| +** The size chosen is a little less than a power of two. That way,
|
| +** the FileChunk object will have a size that almost exactly fills
|
| +** a power-of-two allocation. This minimizes wasted space in power-of-two
|
| +** memory allocators.
|
| +*/
|
| +#define JOURNAL_CHUNKSIZE ((int)(1024-sizeof(FileChunk*)))
|
| +
|
| +/*
|
| +** The rollback journal is composed of a linked list of these structures.
|
| +*/
|
| +struct FileChunk {
|
| + FileChunk *pNext; /* Next chunk in the journal */
|
| + u8 zChunk[JOURNAL_CHUNKSIZE]; /* Content of this chunk */
|
| +};
|
| +
|
| +/*
|
| +** An instance of this object serves as a cursor into the rollback journal.
|
| +** The cursor can be either for reading or writing.
|
| +*/
|
| +struct FilePoint {
|
| + sqlite3_int64 iOffset; /* Offset from the beginning of the file */
|
| + FileChunk *pChunk; /* Specific chunk into which cursor points */
|
| +};
|
| +
|
| +/*
|
| +** This subclass is a subclass of sqlite3_file. Each open memory-journal
|
| +** is an instance of this class.
|
| +*/
|
| +struct MemJournal {
|
| + sqlite3_io_methods *pMethod; /* Parent class. MUST BE FIRST */
|
| + FileChunk *pFirst; /* Head of in-memory chunk-list */
|
| + FilePoint endpoint; /* Pointer to the end of the file */
|
| + FilePoint readpoint; /* Pointer to the end of the last xRead() */
|
| +};
|
| +
|
| +/*
|
| +** Read data from the in-memory journal file. This is the implementation
|
| +** of the sqlite3_vfs.xRead method.
|
| +*/
|
| +static int memjrnlRead(
|
| + sqlite3_file *pJfd, /* The journal file from which to read */
|
| + void *zBuf, /* Put the results here */
|
| + int iAmt, /* Number of bytes to read */
|
| + sqlite_int64 iOfst /* Begin reading at this offset */
|
| +){
|
| + MemJournal *p = (MemJournal *)pJfd;
|
| + u8 *zOut = zBuf;
|
| + int nRead = iAmt;
|
| + int iChunkOffset;
|
| + FileChunk *pChunk;
|
| +
|
| + /* SQLite never tries to read past the end of a rollback journal file */
|
| + assert( iOfst+iAmt<=p->endpoint.iOffset );
|
| +
|
| + if( p->readpoint.iOffset!=iOfst || iOfst==0 ){
|
| + sqlite3_int64 iOff = 0;
|
| + for(pChunk=p->pFirst;
|
| + ALWAYS(pChunk) && (iOff+JOURNAL_CHUNKSIZE)<=iOfst;
|
| + pChunk=pChunk->pNext
|
| + ){
|
| + iOff += JOURNAL_CHUNKSIZE;
|
| + }
|
| + }else{
|
| + pChunk = p->readpoint.pChunk;
|
| + }
|
| +
|
| + iChunkOffset = (int)(iOfst%JOURNAL_CHUNKSIZE);
|
| + do {
|
| + int iSpace = JOURNAL_CHUNKSIZE - iChunkOffset;
|
| + int nCopy = MIN(nRead, (JOURNAL_CHUNKSIZE - iChunkOffset));
|
| + memcpy(zOut, &pChunk->zChunk[iChunkOffset], nCopy);
|
| + zOut += nCopy;
|
| + nRead -= iSpace;
|
| + iChunkOffset = 0;
|
| + } while( nRead>=0 && (pChunk=pChunk->pNext)!=0 && nRead>0 );
|
| + p->readpoint.iOffset = iOfst+iAmt;
|
| + p->readpoint.pChunk = pChunk;
|
| +
|
| + return SQLITE_OK;
|
| +}
|
| +
|
| +/*
|
| +** Write data to the file.
|
| +*/
|
| +static int memjrnlWrite(
|
| + sqlite3_file *pJfd, /* The journal file into which to write */
|
| + const void *zBuf, /* Take data to be written from here */
|
| + int iAmt, /* Number of bytes to write */
|
| + sqlite_int64 iOfst /* Begin writing at this offset into the file */
|
| +){
|
| + MemJournal *p = (MemJournal *)pJfd;
|
| + int nWrite = iAmt;
|
| + u8 *zWrite = (u8 *)zBuf;
|
| +
|
| + /* An in-memory journal file should only ever be appended to. Random
|
| + ** access writes are not required by sqlite.
|
| + */
|
| + assert( iOfst==p->endpoint.iOffset );
|
| + UNUSED_PARAMETER(iOfst);
|
| +
|
| + while( nWrite>0 ){
|
| + FileChunk *pChunk = p->endpoint.pChunk;
|
| + int iChunkOffset = (int)(p->endpoint.iOffset%JOURNAL_CHUNKSIZE);
|
| + int iSpace = MIN(nWrite, JOURNAL_CHUNKSIZE - iChunkOffset);
|
| +
|
| + if( iChunkOffset==0 ){
|
| + /* New chunk is required to extend the file. */
|
| + FileChunk *pNew = sqlite3_malloc(sizeof(FileChunk));
|
| + if( !pNew ){
|
| + return SQLITE_IOERR_NOMEM;
|
| + }
|
| + pNew->pNext = 0;
|
| + if( pChunk ){
|
| + assert( p->pFirst );
|
| + pChunk->pNext = pNew;
|
| + }else{
|
| + assert( !p->pFirst );
|
| + p->pFirst = pNew;
|
| + }
|
| + p->endpoint.pChunk = pNew;
|
| + }
|
| +
|
| + memcpy(&p->endpoint.pChunk->zChunk[iChunkOffset], zWrite, iSpace);
|
| + zWrite += iSpace;
|
| + nWrite -= iSpace;
|
| + p->endpoint.iOffset += iSpace;
|
| + }
|
| +
|
| + return SQLITE_OK;
|
| +}
|
| +
|
| +/*
|
| +** Truncate the file.
|
| +*/
|
| +static int memjrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size){
|
| + MemJournal *p = (MemJournal *)pJfd;
|
| + FileChunk *pChunk;
|
| + assert(size==0);
|
| + UNUSED_PARAMETER(size);
|
| + pChunk = p->pFirst;
|
| + while( pChunk ){
|
| + FileChunk *pTmp = pChunk;
|
| + pChunk = pChunk->pNext;
|
| + sqlite3_free(pTmp);
|
| + }
|
| + sqlite3MemJournalOpen(pJfd);
|
| + return SQLITE_OK;
|
| +}
|
| +
|
| +/*
|
| +** Close the file.
|
| +*/
|
| +static int memjrnlClose(sqlite3_file *pJfd){
|
| + memjrnlTruncate(pJfd, 0);
|
| + return SQLITE_OK;
|
| +}
|
| +
|
| +
|
| +/*
|
| +** Sync the file.
|
| +**
|
| +** Syncing an in-memory journal is a no-op. And, in fact, this routine
|
| +** is never called in a working implementation. This implementation
|
| +** exists purely as a contingency, in case some malfunction in some other
|
| +** part of SQLite causes Sync to be called by mistake.
|
| +*/
|
| +static int memjrnlSync(sqlite3_file *NotUsed, int NotUsed2){
|
| + UNUSED_PARAMETER2(NotUsed, NotUsed2);
|
| + return SQLITE_OK;
|
| +}
|
| +
|
| +/*
|
| +** Query the size of the file in bytes.
|
| +*/
|
| +static int memjrnlFileSize(sqlite3_file *pJfd, sqlite_int64 *pSize){
|
| + MemJournal *p = (MemJournal *)pJfd;
|
| + *pSize = (sqlite_int64) p->endpoint.iOffset;
|
| + return SQLITE_OK;
|
| +}
|
| +
|
| +/*
|
| +** Table of methods for MemJournal sqlite3_file object.
|
| +*/
|
| +static const struct sqlite3_io_methods MemJournalMethods = {
|
| + 1, /* iVersion */
|
| + memjrnlClose, /* xClose */
|
| + memjrnlRead, /* xRead */
|
| + memjrnlWrite, /* xWrite */
|
| + memjrnlTruncate, /* xTruncate */
|
| + memjrnlSync, /* xSync */
|
| + memjrnlFileSize, /* xFileSize */
|
| + 0, /* xLock */
|
| + 0, /* xUnlock */
|
| + 0, /* xCheckReservedLock */
|
| + 0, /* xFileControl */
|
| + 0, /* xSectorSize */
|
| + 0, /* xDeviceCharacteristics */
|
| + 0, /* xShmMap */
|
| + 0, /* xShmLock */
|
| + 0, /* xShmBarrier */
|
| + 0, /* xShmUnmap */
|
| + 0, /* xFetch */
|
| + 0 /* xUnfetch */
|
| +};
|
| +
|
| +/*
|
| +** Open a journal file.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3MemJournalOpen(sqlite3_file *pJfd){
|
| + MemJournal *p = (MemJournal *)pJfd;
|
| + assert( EIGHT_BYTE_ALIGNMENT(p) );
|
| + memset(p, 0, sqlite3MemJournalSize());
|
| + p->pMethod = (sqlite3_io_methods*)&MemJournalMethods;
|
| +}
|
| +
|
| +/*
|
| +** Return true if the file-handle passed as an argument is
|
| +** an in-memory journal
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3IsMemJournal(sqlite3_file *pJfd){
|
| + return pJfd->pMethods==&MemJournalMethods;
|
| +}
|
| +
|
| +/*
|
| +** Return the number of bytes required to store a MemJournal file descriptor.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3MemJournalSize(void){
|
| + return sizeof(MemJournal);
|
| +}
|
| +
|
| +/************** End of memjournal.c ******************************************/
|
| +/************** Begin file walker.c ******************************************/
|
| +/*
|
| +** 2008 August 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.
|
| +**
|
| +*************************************************************************
|
| +** This file contains routines used for walking the parser tree for
|
| +** an SQL statement.
|
| +*/
|
| +/* #include "sqliteInt.h" */
|
| +/* #include <stdlib.h> */
|
| +/* #include <string.h> */
|
| +
|
| +
|
| +/*
|
| +** Walk an expression tree. Invoke the callback once for each node
|
| +** of the expression, while descending. (In other words, the callback
|
| +** is invoked before visiting children.)
|
| +**
|
| +** The return value from the callback should be one of the WRC_*
|
| +** constants to specify how to proceed with the walk.
|
| +**
|
| +** WRC_Continue Continue descending down the tree.
|
| +**
|
| +** WRC_Prune Do not descend into child nodes. But allow
|
| +** the walk to continue with sibling nodes.
|
| +**
|
| +** WRC_Abort Do no more callbacks. Unwind the stack and
|
| +** return the top-level walk call.
|
| +**
|
| +** The return value from this routine is WRC_Abort to abandon the tree walk
|
| +** and WRC_Continue to continue.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3WalkExpr(Walker *pWalker, Expr *pExpr){
|
| + int rc;
|
| + if( pExpr==0 ) return WRC_Continue;
|
| + testcase( ExprHasProperty(pExpr, EP_TokenOnly) );
|
| + testcase( ExprHasProperty(pExpr, EP_Reduced) );
|
| + rc = pWalker->xExprCallback(pWalker, pExpr);
|
| + if( rc==WRC_Continue
|
| + && !ExprHasProperty(pExpr,EP_TokenOnly) ){
|
| + if( sqlite3WalkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort;
|
| + if( sqlite3WalkExpr(pWalker, pExpr->pRight) ) return WRC_Abort;
|
| + if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
| + if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort;
|
| + }else{
|
| + if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort;
|
| + }
|
| + }
|
| + return rc & WRC_Abort;
|
| +}
|
| +
|
| +/*
|
| +** Call sqlite3WalkExpr() for every expression in list p or until
|
| +** an abort request is seen.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3WalkExprList(Walker *pWalker, ExprList *p){
|
| + int i;
|
| + struct ExprList_item *pItem;
|
| + if( p ){
|
| + for(i=p->nExpr, pItem=p->a; i>0; i--, pItem++){
|
| + if( sqlite3WalkExpr(pWalker, pItem->pExpr) ) return WRC_Abort;
|
| + }
|
| + }
|
| + return WRC_Continue;
|
| +}
|
| +
|
| +/*
|
| +** Walk all expressions associated with SELECT statement p. Do
|
| +** not invoke the SELECT callback on p, but do (of course) invoke
|
| +** any expr callbacks and SELECT callbacks that come from subqueries.
|
| +** Return WRC_Abort or WRC_Continue.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3WalkSelectExpr(Walker *pWalker, Select *p){
|
| + if( sqlite3WalkExprList(pWalker, p->pEList) ) return WRC_Abort;
|
| + if( sqlite3WalkExpr(pWalker, p->pWhere) ) return WRC_Abort;
|
| + if( sqlite3WalkExprList(pWalker, p->pGroupBy) ) return WRC_Abort;
|
| + if( sqlite3WalkExpr(pWalker, p->pHaving) ) return WRC_Abort;
|
| + if( sqlite3WalkExprList(pWalker, p->pOrderBy) ) return WRC_Abort;
|
| + if( sqlite3WalkExpr(pWalker, p->pLimit) ) return WRC_Abort;
|
| + if( sqlite3WalkExpr(pWalker, p->pOffset) ) return WRC_Abort;
|
| + return WRC_Continue;
|
| +}
|
| +
|
| +/*
|
| +** Walk the parse trees associated with all subqueries in the
|
| +** FROM clause of SELECT statement p. Do not invoke the select
|
| +** callback on p, but do invoke it on each FROM clause subquery
|
| +** and on any subqueries further down in the tree. Return
|
| +** WRC_Abort or WRC_Continue;
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){
|
| + SrcList *pSrc;
|
| + int i;
|
| + struct SrcList_item *pItem;
|
| +
|
| + pSrc = p->pSrc;
|
| + if( ALWAYS(pSrc) ){
|
| + for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){
|
| + if( sqlite3WalkSelect(pWalker, pItem->pSelect) ){
|
| + return WRC_Abort;
|
| + }
|
| + if( pItem->fg.isTabFunc
|
| + && sqlite3WalkExprList(pWalker, pItem->u1.pFuncArg)
|
| + ){
|
| + return WRC_Abort;
|
| + }
|
| + }
|
| + }
|
| + return WRC_Continue;
|
| +}
|
| +
|
| +/*
|
| +** Call sqlite3WalkExpr() for every expression in Select statement p.
|
| +** Invoke sqlite3WalkSelect() for subqueries in the FROM clause and
|
| +** on the compound select chain, p->pPrior.
|
| +**
|
| +** If it is not NULL, the xSelectCallback() callback is invoked before
|
| +** the walk of the expressions and FROM clause. The xSelectCallback2()
|
| +** method, if it is not NULL, is invoked following the walk of the
|
| +** expressions and FROM clause.
|
| +**
|
| +** Return WRC_Continue under normal conditions. Return WRC_Abort if
|
| +** there is an abort request.
|
| +**
|
| +** If the Walker does not have an xSelectCallback() then this routine
|
| +** is a no-op returning WRC_Continue.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3WalkSelect(Walker *pWalker, Select *p){
|
| + int rc;
|
| + if( p==0 || (pWalker->xSelectCallback==0 && pWalker->xSelectCallback2==0) ){
|
| + return WRC_Continue;
|
| + }
|
| + rc = WRC_Continue;
|
| + pWalker->walkerDepth++;
|
| + while( p ){
|
| + if( pWalker->xSelectCallback ){
|
| + rc = pWalker->xSelectCallback(pWalker, p);
|
| + if( rc ) break;
|
| + }
|
| + if( sqlite3WalkSelectExpr(pWalker, p)
|
| + || sqlite3WalkSelectFrom(pWalker, p)
|
| + ){
|
| + pWalker->walkerDepth--;
|
| + return WRC_Abort;
|
| + }
|
| + if( pWalker->xSelectCallback2 ){
|
| + pWalker->xSelectCallback2(pWalker, p);
|
| + }
|
| + p = p->pPrior;
|
| + }
|
| + pWalker->walkerDepth--;
|
| + return rc & WRC_Abort;
|
| +}
|
| +
|
| +/************** End of walker.c **********************************************/
|
| +/************** Begin file resolve.c *****************************************/
|
| +/*
|
| +** 2008 August 18
|
| +**
|
| +** 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.
|
| +**
|
| +*************************************************************************
|
| +**
|
| +** This file contains routines used for walking the parser tree and
|
| +** resolve all identifiers by associating them with a particular
|
| +** table and column.
|
| +*/
|
| +/* #include "sqliteInt.h" */
|
| +/* #include <stdlib.h> */
|
| +/* #include <string.h> */
|
| +
|
| +/*
|
| +** Walk the expression tree pExpr and increase the aggregate function
|
| +** depth (the Expr.op2 field) by N on every TK_AGG_FUNCTION node.
|
| +** This needs to occur when copying a TK_AGG_FUNCTION node from an
|
| +** outer query into an inner subquery.
|
| +**
|
| +** incrAggFunctionDepth(pExpr,n) is the main routine. incrAggDepth(..)
|
| +** is a helper function - a callback for the tree walker.
|
| +*/
|
| +static int incrAggDepth(Walker *pWalker, Expr *pExpr){
|
| + if( pExpr->op==TK_AGG_FUNCTION ) pExpr->op2 += pWalker->u.n;
|
| + return WRC_Continue;
|
| +}
|
| +static void incrAggFunctionDepth(Expr *pExpr, int N){
|
| + if( N>0 ){
|
| + Walker w;
|
| + memset(&w, 0, sizeof(w));
|
| + w.xExprCallback = incrAggDepth;
|
| + w.u.n = N;
|
| + sqlite3WalkExpr(&w, pExpr);
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Turn the pExpr expression into an alias for the iCol-th column of the
|
| +** result set in pEList.
|
| +**
|
| +** If the reference is followed by a COLLATE operator, then make sure
|
| +** the COLLATE operator is preserved. For example:
|
| +**
|
| +** SELECT a+b, c+d FROM t1 ORDER BY 1 COLLATE nocase;
|
| +**
|
| +** Should be transformed into:
|
| +**
|
| +** SELECT a+b, c+d FROM t1 ORDER BY (a+b) COLLATE nocase;
|
| +**
|
| +** The nSubquery parameter specifies how many levels of subquery the
|
| +** alias is removed from the original expression. The usual value is
|
| +** zero but it might be more if the alias is contained within a subquery
|
| +** of the original expression. The Expr.op2 field of TK_AGG_FUNCTION
|
| +** structures must be increased by the nSubquery amount.
|
| +*/
|
| +static void resolveAlias(
|
| + Parse *pParse, /* Parsing context */
|
| + ExprList *pEList, /* A result set */
|
| + int iCol, /* A column in the result set. 0..pEList->nExpr-1 */
|
| + Expr *pExpr, /* Transform this into an alias to the result set */
|
| + const char *zType, /* "GROUP" or "ORDER" or "" */
|
| + int nSubquery /* Number of subqueries that the label is moving */
|
| +){
|
| + Expr *pOrig; /* The iCol-th column of the result set */
|
| + Expr *pDup; /* Copy of pOrig */
|
| + sqlite3 *db; /* The database connection */
|
| +
|
| + assert( iCol>=0 && iCol<pEList->nExpr );
|
| + pOrig = pEList->a[iCol].pExpr;
|
| + assert( pOrig!=0 );
|
| + db = pParse->db;
|
| + pDup = sqlite3ExprDup(db, pOrig, 0);
|
| + if( pDup==0 ) return;
|
| + if( zType[0]!='G' ) incrAggFunctionDepth(pDup, nSubquery);
|
| + if( pExpr->op==TK_COLLATE ){
|
| + pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken);
|
| + }
|
| + ExprSetProperty(pDup, EP_Alias);
|
| +
|
| + /* Before calling sqlite3ExprDelete(), set the EP_Static flag. This
|
| + ** prevents ExprDelete() from deleting the Expr structure itself,
|
| + ** allowing it to be repopulated by the memcpy() on the following line.
|
| + ** The pExpr->u.zToken might point into memory that will be freed by the
|
| + ** sqlite3DbFree(db, pDup) on the last line of this block, so be sure to
|
| + ** make a copy of the token before doing the sqlite3DbFree().
|
| + */
|
| + ExprSetProperty(pExpr, EP_Static);
|
| + sqlite3ExprDelete(db, pExpr);
|
| + memcpy(pExpr, pDup, sizeof(*pExpr));
|
| + if( !ExprHasProperty(pExpr, EP_IntValue) && pExpr->u.zToken!=0 ){
|
| + assert( (pExpr->flags & (EP_Reduced|EP_TokenOnly))==0 );
|
| + pExpr->u.zToken = sqlite3DbStrDup(db, pExpr->u.zToken);
|
| + pExpr->flags |= EP_MemToken;
|
| + }
|
| + sqlite3DbFree(db, pDup);
|
| +}
|
| +
|
| +
|
| +/*
|
| +** Return TRUE if the name zCol occurs anywhere in the USING clause.
|
| +**
|
| +** Return FALSE if the USING clause is NULL or if it does not contain
|
| +** zCol.
|
| +*/
|
| +static int nameInUsingClause(IdList *pUsing, const char *zCol){
|
| + if( pUsing ){
|
| + int k;
|
| + for(k=0; k<pUsing->nId; k++){
|
| + if( sqlite3StrICmp(pUsing->a[k].zName, zCol)==0 ) return 1;
|
| + }
|
| + }
|
| + return 0;
|
| +}
|
| +
|
| +/*
|
| +** Subqueries stores the original database, table and column names for their
|
| +** result sets in ExprList.a[].zSpan, in the form "DATABASE.TABLE.COLUMN".
|
| +** Check to see if the zSpan given to this routine matches the zDb, zTab,
|
| +** and zCol. If any of zDb, zTab, and zCol are NULL then those fields will
|
| +** match anything.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3MatchSpanName(
|
| + const char *zSpan,
|
| + const char *zCol,
|
| + const char *zTab,
|
| + const char *zDb
|
| +){
|
| + int n;
|
| + for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){}
|
| + if( zDb && (sqlite3StrNICmp(zSpan, zDb, n)!=0 || zDb[n]!=0) ){
|
| + return 0;
|
| + }
|
| + zSpan += n+1;
|
| + for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){}
|
| + if( zTab && (sqlite3StrNICmp(zSpan, zTab, n)!=0 || zTab[n]!=0) ){
|
| + return 0;
|
| + }
|
| + zSpan += n+1;
|
| + if( zCol && sqlite3StrICmp(zSpan, zCol)!=0 ){
|
| + return 0;
|
| + }
|
| + return 1;
|
| +}
|
| +
|
| +/*
|
| +** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up
|
| +** that name in the set of source tables in pSrcList and make the pExpr
|
| +** expression node refer back to that source column. The following changes
|
| +** are made to pExpr:
|
| +**
|
| +** pExpr->iDb Set the index in db->aDb[] of the database X
|
| +** (even if X is implied).
|
| +** pExpr->iTable Set to the cursor number for the table obtained
|
| +** from pSrcList.
|
| +** pExpr->pTab Points to the Table structure of X.Y (even if
|
| +** X and/or Y are implied.)
|
| +** pExpr->iColumn Set to the column number within the table.
|
| +** pExpr->op Set to TK_COLUMN.
|
| +** pExpr->pLeft Any expression this points to is deleted
|
| +** pExpr->pRight Any expression this points to is deleted.
|
| +**
|
| +** The zDb variable is the name of the database (the "X"). This value may be
|
| +** NULL meaning that name is of the form Y.Z or Z. Any available database
|
| +** can be used. The zTable variable is the name of the table (the "Y"). This
|
| +** value can be NULL if zDb is also NULL. If zTable is NULL it
|
| +** means that the form of the name is Z and that columns from any table
|
| +** can be used.
|
| +**
|
| +** If the name cannot be resolved unambiguously, leave an error message
|
| +** in pParse and return WRC_Abort. Return WRC_Prune on success.
|
| +*/
|
| +static int lookupName(
|
| + Parse *pParse, /* The parsing context */
|
| + const char *zDb, /* Name of the database containing table, or NULL */
|
| + const char *zTab, /* Name of table containing column, or NULL */
|
| + const char *zCol, /* Name of the column. */
|
| + NameContext *pNC, /* The name context used to resolve the name */
|
| + Expr *pExpr /* Make this EXPR node point to the selected column */
|
| +){
|
| + int i, j; /* Loop counters */
|
| + int cnt = 0; /* Number of matching column names */
|
| + int cntTab = 0; /* Number of matching table names */
|
| + int nSubquery = 0; /* How many levels of subquery */
|
| + sqlite3 *db = pParse->db; /* The database connection */
|
| + struct SrcList_item *pItem; /* Use for looping over pSrcList items */
|
| + struct SrcList_item *pMatch = 0; /* The matching pSrcList item */
|
| + NameContext *pTopNC = pNC; /* First namecontext in the list */
|
| + Schema *pSchema = 0; /* Schema of the expression */
|
| + int isTrigger = 0; /* True if resolved to a trigger column */
|
| + Table *pTab = 0; /* Table hold the row */
|
| + Column *pCol; /* A column of pTab */
|
| +
|
| + assert( pNC ); /* the name context cannot be NULL. */
|
| + assert( zCol ); /* The Z in X.Y.Z cannot be NULL */
|
| + assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) );
|
| +
|
| + /* Initialize the node to no-match */
|
| + pExpr->iTable = -1;
|
| + pExpr->pTab = 0;
|
| + ExprSetVVAProperty(pExpr, EP_NoReduce);
|
| +
|
| + /* Translate the schema name in zDb into a pointer to the corresponding
|
| + ** schema. If not found, pSchema will remain NULL and nothing will match
|
| + ** resulting in an appropriate error message toward the end of this routine
|
| + */
|
| + if( zDb ){
|
| + testcase( pNC->ncFlags & NC_PartIdx );
|
| + testcase( pNC->ncFlags & NC_IsCheck );
|
| + if( (pNC->ncFlags & (NC_PartIdx|NC_IsCheck))!=0 ){
|
| + /* Silently ignore database qualifiers inside CHECK constraints and
|
| + ** partial indices. Do not raise errors because that might break
|
| + ** legacy and because it does not hurt anything to just ignore the
|
| + ** database name. */
|
| + zDb = 0;
|
| + }else{
|
| + for(i=0; i<db->nDb; i++){
|
| + assert( db->aDb[i].zName );
|
| + if( sqlite3StrICmp(db->aDb[i].zName,zDb)==0 ){
|
| + pSchema = db->aDb[i].pSchema;
|
| + break;
|
| + }
|
| + }
|
| + }
|
| + }
|
| +
|
| + /* Start at the inner-most context and move outward until a match is found */
|
| + while( pNC && cnt==0 ){
|
| + ExprList *pEList;
|
| + SrcList *pSrcList = pNC->pSrcList;
|
| +
|
| + if( pSrcList ){
|
| + for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){
|
| + pTab = pItem->pTab;
|
| + assert( pTab!=0 && pTab->zName!=0 );
|
| + assert( pTab->nCol>0 );
|
| + if( pItem->pSelect && (pItem->pSelect->selFlags & SF_NestedFrom)!=0 ){
|
| + int hit = 0;
|
| + pEList = pItem->pSelect->pEList;
|
| + for(j=0; j<pEList->nExpr; j++){
|
| + if( sqlite3MatchSpanName(pEList->a[j].zSpan, zCol, zTab, zDb) ){
|
| + cnt++;
|
| + cntTab = 2;
|
| + pMatch = pItem;
|
| + pExpr->iColumn = j;
|
| + hit = 1;
|
| + }
|
| + }
|
| + if( hit || zTab==0 ) continue;
|
| + }
|
| + if( zDb && pTab->pSchema!=pSchema ){
|
| + continue;
|
| + }
|
| + if( zTab ){
|
| + const char *zTabName = pItem->zAlias ? pItem->zAlias : pTab->zName;
|
| + assert( zTabName!=0 );
|
| + if( sqlite3StrICmp(zTabName, zTab)!=0 ){
|
| + continue;
|
| + }
|
| + }
|
| + if( 0==(cntTab++) ){
|
| + pMatch = pItem;
|
| + }
|
| + for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
|
| + if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
|
| + /* If there has been exactly one prior match and this match
|
| + ** is for the right-hand table of a NATURAL JOIN or is in a
|
| + ** USING clause, then skip this match.
|
| + */
|
| + if( cnt==1 ){
|
| + if( pItem->fg.jointype & JT_NATURAL ) continue;
|
| + if( nameInUsingClause(pItem->pUsing, zCol) ) continue;
|
| + }
|
| + cnt++;
|
| + pMatch = pItem;
|
| + /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
|
| + pExpr->iColumn = j==pTab->iPKey ? -1 : (i16)j;
|
| + break;
|
| + }
|
| + }
|
| + }
|
| + if( pMatch ){
|
| + pExpr->iTable = pMatch->iCursor;
|
| + pExpr->pTab = pMatch->pTab;
|
| + /* RIGHT JOIN not (yet) supported */
|
| + assert( (pMatch->fg.jointype & JT_RIGHT)==0 );
|
| + if( (pMatch->fg.jointype & JT_LEFT)!=0 ){
|
| + ExprSetProperty(pExpr, EP_CanBeNull);
|
| + }
|
| + pSchema = pExpr->pTab->pSchema;
|
| + }
|
| + } /* if( pSrcList ) */
|
| +
|
| +#ifndef SQLITE_OMIT_TRIGGER
|
| + /* If we have not already resolved the name, then maybe
|
| + ** it is a new.* or old.* trigger argument reference
|
| + */
|
| + if( zDb==0 && zTab!=0 && cntTab==0 && pParse->pTriggerTab!=0 ){
|
| + int op = pParse->eTriggerOp;
|
| + assert( op==TK_DELETE || op==TK_UPDATE || op==TK_INSERT );
|
| + if( op!=TK_DELETE && sqlite3StrICmp("new",zTab) == 0 ){
|
| + pExpr->iTable = 1;
|
| + pTab = pParse->pTriggerTab;
|
| + }else if( op!=TK_INSERT && sqlite3StrICmp("old",zTab)==0 ){
|
| + pExpr->iTable = 0;
|
| + pTab = pParse->pTriggerTab;
|
| + }else{
|
| + pTab = 0;
|
| + }
|
| +
|
| + if( pTab ){
|
| + int iCol;
|
| + pSchema = pTab->pSchema;
|
| + cntTab++;
|
| + for(iCol=0, pCol=pTab->aCol; iCol<pTab->nCol; iCol++, pCol++){
|
| + if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
|
| + if( iCol==pTab->iPKey ){
|
| + iCol = -1;
|
| + }
|
| + break;
|
| + }
|
| + }
|
| + if( iCol>=pTab->nCol && sqlite3IsRowid(zCol) && VisibleRowid(pTab) ){
|
| + /* IMP: R-51414-32910 */
|
| + iCol = -1;
|
| + }
|
| + if( iCol<pTab->nCol ){
|
| + cnt++;
|
| + if( iCol<0 ){
|
| + pExpr->affinity = SQLITE_AFF_INTEGER;
|
| + }else if( pExpr->iTable==0 ){
|
| + testcase( iCol==31 );
|
| + testcase( iCol==32 );
|
| + pParse->oldmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<<iCol));
|
| + }else{
|
| + testcase( iCol==31 );
|
| + testcase( iCol==32 );
|
| + pParse->newmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<<iCol));
|
| + }
|
| + pExpr->iColumn = (i16)iCol;
|
| + pExpr->pTab = pTab;
|
| + isTrigger = 1;
|
| + }
|
| + }
|
| + }
|
| +#endif /* !defined(SQLITE_OMIT_TRIGGER) */
|
| +
|
| + /*
|
| + ** Perhaps the name is a reference to the ROWID
|
| + */
|
| + if( cnt==0
|
| + && cntTab==1
|
| + && pMatch
|
| + && (pNC->ncFlags & NC_IdxExpr)==0
|
| + && sqlite3IsRowid(zCol)
|
| + && VisibleRowid(pMatch->pTab)
|
| + ){
|
| + cnt = 1;
|
| + pExpr->iColumn = -1;
|
| + pExpr->affinity = SQLITE_AFF_INTEGER;
|
| + }
|
| +
|
| + /*
|
| + ** If the input is of the form Z (not Y.Z or X.Y.Z) then the name Z
|
| + ** might refer to an result-set alias. This happens, for example, when
|
| + ** we are resolving names in the WHERE clause of the following command:
|
| + **
|
| + ** SELECT a+b AS x FROM table WHERE x<10;
|
| + **
|
| + ** In cases like this, replace pExpr with a copy of the expression that
|
| + ** forms the result set entry ("a+b" in the example) and return immediately.
|
| + ** Note that the expression in the result set should have already been
|
| + ** resolved by the time the WHERE clause is resolved.
|
| + **
|
| + ** The ability to use an output result-set column in the WHERE, GROUP BY,
|
| + ** or HAVING clauses, or as part of a larger expression in the ORDER BY
|
| + ** clause is not standard SQL. This is a (goofy) SQLite extension, that
|
| + ** is supported for backwards compatibility only. Hence, we issue a warning
|
| + ** on sqlite3_log() whenever the capability is used.
|
| + */
|
| + if( (pEList = pNC->pEList)!=0
|
| + && zTab==0
|
| + && cnt==0
|
| + ){
|
| + for(j=0; j<pEList->nExpr; j++){
|
| + char *zAs = pEList->a[j].zName;
|
| + if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
|
| + Expr *pOrig;
|
| + assert( pExpr->pLeft==0 && pExpr->pRight==0 );
|
| + assert( pExpr->x.pList==0 );
|
| + assert( pExpr->x.pSelect==0 );
|
| + pOrig = pEList->a[j].pExpr;
|
| + if( (pNC->ncFlags&NC_AllowAgg)==0 && ExprHasProperty(pOrig, EP_Agg) ){
|
| + sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs);
|
| + return WRC_Abort;
|
| + }
|
| + resolveAlias(pParse, pEList, j, pExpr, "", nSubquery);
|
| + cnt = 1;
|
| + pMatch = 0;
|
| + assert( zTab==0 && zDb==0 );
|
| + goto lookupname_end;
|
| + }
|
| + }
|
| + }
|
| +
|
| + /* Advance to the next name context. The loop will exit when either
|
| + ** we have a match (cnt>0) or when we run out of name contexts.
|
| + */
|
| + if( cnt==0 ){
|
| + pNC = pNC->pNext;
|
| + nSubquery++;
|
| + }
|
| + }
|
| +
|
| + /*
|
| + ** If X and Y are NULL (in other words if only the column name Z is
|
| + ** supplied) and the value of Z is enclosed in double-quotes, then
|
| + ** Z is a string literal if it doesn't match any column names. In that
|
| + ** case, we need to return right away and not make any changes to
|
| + ** pExpr.
|
| + **
|
| + ** Because no reference was made to outer contexts, the pNC->nRef
|
| + ** fields are not changed in any context.
|
| + */
|
| + if( cnt==0 && zTab==0 && ExprHasProperty(pExpr,EP_DblQuoted) ){
|
| + pExpr->op = TK_STRING;
|
| + pExpr->pTab = 0;
|
| + return WRC_Prune;
|
| + }
|
| +
|
| + /*
|
| + ** cnt==0 means there was not match. cnt>1 means there were two or
|
| + ** more matches. Either way, we have an error.
|
| + */
|
| + if( cnt!=1 ){
|
| + const char *zErr;
|
| + zErr = cnt==0 ? "no such column" : "ambiguous column name";
|
| + if( zDb ){
|
| + sqlite3ErrorMsg(pParse, "%s: %s.%s.%s", zErr, zDb, zTab, zCol);
|
| + }else if( zTab ){
|
| + sqlite3ErrorMsg(pParse, "%s: %s.%s", zErr, zTab, zCol);
|
| + }else{
|
| + sqlite3ErrorMsg(pParse, "%s: %s", zErr, zCol);
|
| + }
|
| + pParse->checkSchema = 1;
|
| + pTopNC->nErr++;
|
| + }
|
| +
|
| + /* If a column from a table in pSrcList is referenced, then record
|
| + ** this fact in the pSrcList.a[].colUsed bitmask. Column 0 causes
|
| + ** bit 0 to be set. Column 1 sets bit 1. And so forth. If the
|
| + ** column number is greater than the number of bits in the bitmask
|
| + ** then set the high-order bit of the bitmask.
|
| + */
|
| + if( pExpr->iColumn>=0 && pMatch!=0 ){
|
| + int n = pExpr->iColumn;
|
| + testcase( n==BMS-1 );
|
| + if( n>=BMS ){
|
| + n = BMS-1;
|
| + }
|
| + assert( pMatch->iCursor==pExpr->iTable );
|
| + pMatch->colUsed |= ((Bitmask)1)<<n;
|
| + }
|
| +
|
| + /* Clean up and return
|
| + */
|
| + sqlite3ExprDelete(db, pExpr->pLeft);
|
| + pExpr->pLeft = 0;
|
| + sqlite3ExprDelete(db, pExpr->pRight);
|
| + pExpr->pRight = 0;
|
| + pExpr->op = (isTrigger ? TK_TRIGGER : TK_COLUMN);
|
| +lookupname_end:
|
| + if( cnt==1 ){
|
| + assert( pNC!=0 );
|
| + if( !ExprHasProperty(pExpr, EP_Alias) ){
|
| + sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList);
|
| + }
|
| + /* Increment the nRef value on all name contexts from TopNC up to
|
| + ** the point where the name matched. */
|
| + for(;;){
|
| + assert( pTopNC!=0 );
|
| + pTopNC->nRef++;
|
| + if( pTopNC==pNC ) break;
|
| + pTopNC = pTopNC->pNext;
|
| + }
|
| + return WRC_Prune;
|
| + } else {
|
| + return WRC_Abort;
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Allocate and return a pointer to an expression to load the column iCol
|
| +** from datasource iSrc in SrcList pSrc.
|
| +*/
|
| +SQLITE_PRIVATE Expr *sqlite3CreateColumnExpr(sqlite3 *db, SrcList *pSrc, int iSrc, int iCol){
|
| + Expr *p = sqlite3ExprAlloc(db, TK_COLUMN, 0, 0);
|
| + if( p ){
|
| + struct SrcList_item *pItem = &pSrc->a[iSrc];
|
| + p->pTab = pItem->pTab;
|
| + p->iTable = pItem->iCursor;
|
| + if( p->pTab->iPKey==iCol ){
|
| + p->iColumn = -1;
|
| + }else{
|
| + p->iColumn = (ynVar)iCol;
|
| + testcase( iCol==BMS );
|
| + testcase( iCol==BMS-1 );
|
| + pItem->colUsed |= ((Bitmask)1)<<(iCol>=BMS ? BMS-1 : iCol);
|
| + }
|
| + ExprSetProperty(p, EP_Resolved);
|
| + }
|
| + return p;
|
| +}
|
| +
|
| +/*
|
| +** Report an error that an expression is not valid for some set of
|
| +** pNC->ncFlags values determined by validMask.
|
| +*/
|
| +static void notValid(
|
| + Parse *pParse, /* Leave error message here */
|
| + NameContext *pNC, /* The name context */
|
| + const char *zMsg, /* Type of error */
|
| + int validMask /* Set of contexts for which prohibited */
|
| +){
|
| + assert( (validMask&~(NC_IsCheck|NC_PartIdx|NC_IdxExpr))==0 );
|
| + if( (pNC->ncFlags & validMask)!=0 ){
|
| + const char *zIn = "partial index WHERE clauses";
|
| + if( pNC->ncFlags & NC_IdxExpr ) zIn = "index expressions";
|
| +#ifndef SQLITE_OMIT_CHECK
|
| + else if( pNC->ncFlags & NC_IsCheck ) zIn = "CHECK constraints";
|
| +#endif
|
| + sqlite3ErrorMsg(pParse, "%s prohibited in %s", zMsg, zIn);
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Expression p should encode a floating point value between 1.0 and 0.0.
|
| +** Return 1024 times this value. Or return -1 if p is not a floating point
|
| +** value between 1.0 and 0.0.
|
| +*/
|
| +static int exprProbability(Expr *p){
|
| + double r = -1.0;
|
| + if( p->op!=TK_FLOAT ) return -1;
|
| + sqlite3AtoF(p->u.zToken, &r, sqlite3Strlen30(p->u.zToken), SQLITE_UTF8);
|
| + assert( r>=0.0 );
|
| + if( r>1.0 ) return -1;
|
| + return (int)(r*134217728.0);
|
| +}
|
| +
|
| +/*
|
| +** This routine is callback for sqlite3WalkExpr().
|
| +**
|
| +** Resolve symbolic names into TK_COLUMN operators for the current
|
| +** node in the expression tree. Return 0 to continue the search down
|
| +** the tree or 2 to abort the tree walk.
|
| +**
|
| +** This routine also does error checking and name resolution for
|
| +** function names. The operator for aggregate functions is changed
|
| +** to TK_AGG_FUNCTION.
|
| +*/
|
| +static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
| + NameContext *pNC;
|
| + Parse *pParse;
|
| +
|
| + pNC = pWalker->u.pNC;
|
| + assert( pNC!=0 );
|
| + pParse = pNC->pParse;
|
| + assert( pParse==pWalker->pParse );
|
| +
|
| + if( ExprHasProperty(pExpr, EP_Resolved) ) return WRC_Prune;
|
| + ExprSetProperty(pExpr, EP_Resolved);
|
| +#ifndef NDEBUG
|
| + if( pNC->pSrcList && pNC->pSrcList->nAlloc>0 ){
|
| + SrcList *pSrcList = pNC->pSrcList;
|
| + int i;
|
| + for(i=0; i<pNC->pSrcList->nSrc; i++){
|
| + assert( pSrcList->a[i].iCursor>=0 && pSrcList->a[i].iCursor<pParse->nTab);
|
| + }
|
| + }
|
| +#endif
|
| + switch( pExpr->op ){
|
| +
|
| +#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
|
| + /* The special operator TK_ROW means use the rowid for the first
|
| + ** column in the FROM clause. This is used by the LIMIT and ORDER BY
|
| + ** clause processing on UPDATE and DELETE statements.
|
| + */
|
| + case TK_ROW: {
|
| + SrcList *pSrcList = pNC->pSrcList;
|
| + struct SrcList_item *pItem;
|
| + assert( pSrcList && pSrcList->nSrc==1 );
|
| + pItem = pSrcList->a;
|
| + pExpr->op = TK_COLUMN;
|
| + pExpr->pTab = pItem->pTab;
|
| + pExpr->iTable = pItem->iCursor;
|
| + pExpr->iColumn = -1;
|
| + pExpr->affinity = SQLITE_AFF_INTEGER;
|
| + break;
|
| + }
|
| +#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT)
|
| + && !defined(SQLITE_OMIT_SUBQUERY) */
|
| +
|
| + /* A lone identifier is the name of a column.
|
| + */
|
| + case TK_ID: {
|
| + return lookupName(pParse, 0, 0, pExpr->u.zToken, pNC, pExpr);
|
| + }
|
| +
|
| + /* A table name and column name: ID.ID
|
| + ** Or a database, table and column: ID.ID.ID
|
| + */
|
| + case TK_DOT: {
|
| + const char *zColumn;
|
| + const char *zTable;
|
| + const char *zDb;
|
| + Expr *pRight;
|
| +
|
| + /* if( pSrcList==0 ) break; */
|
| + notValid(pParse, pNC, "the \".\" operator", NC_IdxExpr);
|
| + /*notValid(pParse, pNC, "the \".\" operator", NC_PartIdx|NC_IsCheck, 1);*/
|
| + pRight = pExpr->pRight;
|
| + if( pRight->op==TK_ID ){
|
| + zDb = 0;
|
| + zTable = pExpr->pLeft->u.zToken;
|
| + zColumn = pRight->u.zToken;
|
| + }else{
|
| + assert( pRight->op==TK_DOT );
|
| + zDb = pExpr->pLeft->u.zToken;
|
| + zTable = pRight->pLeft->u.zToken;
|
| + zColumn = pRight->pRight->u.zToken;
|
| + }
|
| + return lookupName(pParse, zDb, zTable, zColumn, pNC, pExpr);
|
| + }
|
| +
|
| + /* Resolve function names
|
| + */
|
| + case TK_FUNCTION: {
|
| + ExprList *pList = pExpr->x.pList; /* The argument list */
|
| + int n = pList ? pList->nExpr : 0; /* Number of arguments */
|
| + int no_such_func = 0; /* True if no such function exists */
|
| + int wrong_num_args = 0; /* True if wrong number of arguments */
|
| + int is_agg = 0; /* True if is an aggregate function */
|
| + int auth; /* Authorization to use the function */
|
| + int nId; /* Number of characters in function name */
|
| + const char *zId; /* The function name. */
|
| + FuncDef *pDef; /* Information about the function */
|
| + u8 enc = ENC(pParse->db); /* The database encoding */
|
| +
|
| + assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
|
| + notValid(pParse, pNC, "functions", NC_PartIdx);
|
| + zId = pExpr->u.zToken;
|
| + nId = sqlite3Strlen30(zId);
|
| + pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0);
|
| + if( pDef==0 ){
|
| + pDef = sqlite3FindFunction(pParse->db, zId, nId, -2, enc, 0);
|
| + if( pDef==0 ){
|
| + no_such_func = 1;
|
| + }else{
|
| + wrong_num_args = 1;
|
| + }
|
| + }else{
|
| + is_agg = pDef->xFunc==0;
|
| + if( pDef->funcFlags & SQLITE_FUNC_UNLIKELY ){
|
| + ExprSetProperty(pExpr, EP_Unlikely|EP_Skip);
|
| + if( n==2 ){
|
| + pExpr->iTable = exprProbability(pList->a[1].pExpr);
|
| + if( pExpr->iTable<0 ){
|
| + sqlite3ErrorMsg(pParse,
|
| + "second argument to likelihood() must be a "
|
| + "constant between 0.0 and 1.0");
|
| + pNC->nErr++;
|
| + }
|
| + }else{
|
| + /* EVIDENCE-OF: R-61304-29449 The unlikely(X) function is
|
| + ** equivalent to likelihood(X, 0.0625).
|
| + ** EVIDENCE-OF: R-01283-11636 The unlikely(X) function is
|
| + ** short-hand for likelihood(X,0.0625).
|
| + ** EVIDENCE-OF: R-36850-34127 The likely(X) function is short-hand
|
| + ** for likelihood(X,0.9375).
|
| + ** EVIDENCE-OF: R-53436-40973 The likely(X) function is equivalent
|
| + ** to likelihood(X,0.9375). */
|
| + /* TUNING: unlikely() probability is 0.0625. likely() is 0.9375 */
|
| + pExpr->iTable = pDef->zName[0]=='u' ? 8388608 : 125829120;
|
| + }
|
| + }
|
| +#ifndef SQLITE_OMIT_AUTHORIZATION
|
| + auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0, pDef->zName, 0);
|
| + if( auth!=SQLITE_OK ){
|
| + if( auth==SQLITE_DENY ){
|
| + sqlite3ErrorMsg(pParse, "not authorized to use function: %s",
|
| + pDef->zName);
|
| + pNC->nErr++;
|
| + }
|
| + pExpr->op = TK_NULL;
|
| + return WRC_Prune;
|
| + }
|
| +#endif
|
| + if( pDef->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG) ){
|
| + /* For the purposes of the EP_ConstFunc flag, date and time
|
| + ** functions and other functions that change slowly are considered
|
| + ** constant because they are constant for the duration of one query */
|
| + ExprSetProperty(pExpr,EP_ConstFunc);
|
| + }
|
| + if( (pDef->funcFlags & SQLITE_FUNC_CONSTANT)==0 ){
|
| + /* Date/time functions that use 'now', and other functions like
|
| + ** sqlite_version() that might change over time cannot be used
|
| + ** in an index. */
|
| + notValid(pParse, pNC, "non-deterministic functions", NC_IdxExpr);
|
| + }
|
| + }
|
| + if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){
|
| + sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId);
|
| + pNC->nErr++;
|
| + is_agg = 0;
|
| + }else if( no_such_func && pParse->db->init.busy==0 ){
|
| + sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId);
|
| + pNC->nErr++;
|
| + }else if( wrong_num_args ){
|
| + sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()",
|
| + nId, zId);
|
| + pNC->nErr++;
|
| + }
|
| + if( is_agg ) pNC->ncFlags &= ~NC_AllowAgg;
|
| + sqlite3WalkExprList(pWalker, pList);
|
| + if( is_agg ){
|
| + NameContext *pNC2 = pNC;
|
| + pExpr->op = TK_AGG_FUNCTION;
|
| + pExpr->op2 = 0;
|
| + while( pNC2 && !sqlite3FunctionUsesThisSrc(pExpr, pNC2->pSrcList) ){
|
| + pExpr->op2++;
|
| + pNC2 = pNC2->pNext;
|
| + }
|
| + assert( pDef!=0 );
|
| + if( pNC2 ){
|
| + assert( SQLITE_FUNC_MINMAX==NC_MinMaxAgg );
|
| + testcase( (pDef->funcFlags & SQLITE_FUNC_MINMAX)!=0 );
|
| + pNC2->ncFlags |= NC_HasAgg | (pDef->funcFlags & SQLITE_FUNC_MINMAX);
|
| +
|
| + }
|
| + pNC->ncFlags |= NC_AllowAgg;
|
| + }
|
| + /* FIX ME: Compute pExpr->affinity based on the expected return
|
| + ** type of the function
|
| + */
|
| + return WRC_Prune;
|
| + }
|
| +#ifndef SQLITE_OMIT_SUBQUERY
|
| + case TK_SELECT:
|
| + case TK_EXISTS: testcase( pExpr->op==TK_EXISTS );
|
| +#endif
|
| + case TK_IN: {
|
| + testcase( pExpr->op==TK_IN );
|
| + if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
| + int nRef = pNC->nRef;
|
| + notValid(pParse, pNC, "subqueries", NC_IsCheck|NC_PartIdx|NC_IdxExpr);
|
| + sqlite3WalkSelect(pWalker, pExpr->x.pSelect);
|
| + assert( pNC->nRef>=nRef );
|
| + if( nRef!=pNC->nRef ){
|
| + ExprSetProperty(pExpr, EP_VarSelect);
|
| + }
|
| + }
|
| + break;
|
| + }
|
| + case TK_VARIABLE: {
|
| + notValid(pParse, pNC, "parameters", NC_IsCheck|NC_PartIdx|NC_IdxExpr);
|
| + break;
|
| + }
|
| + }
|
| + return (pParse->nErr || pParse->db->mallocFailed) ? WRC_Abort : WRC_Continue;
|
| +}
|
| +
|
| +/*
|
| +** pEList is a list of expressions which are really the result set of the
|
| +** a SELECT statement. pE is a term in an ORDER BY or GROUP BY clause.
|
| +** This routine checks to see if pE is a simple identifier which corresponds
|
| +** to the AS-name of one of the terms of the expression list. If it is,
|
| +** this routine return an integer between 1 and N where N is the number of
|
| +** elements in pEList, corresponding to the matching entry. If there is
|
| +** no match, or if pE is not a simple identifier, then this routine
|
| +** return 0.
|
| +**
|
| +** pEList has been resolved. pE has not.
|
| +*/
|
| +static int resolveAsName(
|
| + Parse *pParse, /* Parsing context for error messages */
|
| + ExprList *pEList, /* List of expressions to scan */
|
| + Expr *pE /* Expression we are trying to match */
|
| +){
|
| + int i; /* Loop counter */
|
| +
|
| + UNUSED_PARAMETER(pParse);
|
| +
|
| + if( pE->op==TK_ID ){
|
| + char *zCol = pE->u.zToken;
|
| + for(i=0; i<pEList->nExpr; i++){
|
| + char *zAs = pEList->a[i].zName;
|
| + if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
|
| + return i+1;
|
| + }
|
| + }
|
| + }
|
| + return 0;
|
| +}
|
| +
|
| +/*
|
| +** pE is a pointer to an expression which is a single term in the
|
| +** ORDER BY of a compound SELECT. The expression has not been
|
| +** name resolved.
|
| +**
|
| +** At the point this routine is called, we already know that the
|
| +** ORDER BY term is not an integer index into the result set. That
|
| +** case is handled by the calling routine.
|
| +**
|
| +** Attempt to match pE against result set columns in the left-most
|
| +** SELECT statement. Return the index i of the matching column,
|
| +** as an indication to the caller that it should sort by the i-th column.
|
| +** The left-most column is 1. In other words, the value returned is the
|
| +** same integer value that would be used in the SQL statement to indicate
|
| +** the column.
|
| +**
|
| +** If there is no match, return 0. Return -1 if an error occurs.
|
| +*/
|
| +static int resolveOrderByTermToExprList(
|
| + Parse *pParse, /* Parsing context for error messages */
|
| + Select *pSelect, /* The SELECT statement with the ORDER BY clause */
|
| + Expr *pE /* The specific ORDER BY term */
|
| +){
|
| + int i; /* Loop counter */
|
| + ExprList *pEList; /* The columns of the result set */
|
| + NameContext nc; /* Name context for resolving pE */
|
| + sqlite3 *db; /* Database connection */
|
| + int rc; /* Return code from subprocedures */
|
| + u8 savedSuppErr; /* Saved value of db->suppressErr */
|
| +
|
| + assert( sqlite3ExprIsInteger(pE, &i)==0 );
|
| + pEList = pSelect->pEList;
|
| +
|
| + /* Resolve all names in the ORDER BY term expression
|
| + */
|
| + memset(&nc, 0, sizeof(nc));
|
| + nc.pParse = pParse;
|
| + nc.pSrcList = pSelect->pSrc;
|
| + nc.pEList = pEList;
|
| + nc.ncFlags = NC_AllowAgg;
|
| + nc.nErr = 0;
|
| + db = pParse->db;
|
| + savedSuppErr = db->suppressErr;
|
| + db->suppressErr = 1;
|
| + rc = sqlite3ResolveExprNames(&nc, pE);
|
| + db->suppressErr = savedSuppErr;
|
| + if( rc ) return 0;
|
| +
|
| + /* Try to match the ORDER BY expression against an expression
|
| + ** in the result set. Return an 1-based index of the matching
|
| + ** result-set entry.
|
| + */
|
| + for(i=0; i<pEList->nExpr; i++){
|
| + if( sqlite3ExprCompare(pEList->a[i].pExpr, pE, -1)<2 ){
|
| + return i+1;
|
| + }
|
| + }
|
| +
|
| + /* If no match, return 0. */
|
| + return 0;
|
| +}
|
| +
|
| +/*
|
| +** Generate an ORDER BY or GROUP BY term out-of-range error.
|
| +*/
|
| +static void resolveOutOfRangeError(
|
| + Parse *pParse, /* The error context into which to write the error */
|
| + const char *zType, /* "ORDER" or "GROUP" */
|
| + int i, /* The index (1-based) of the term out of range */
|
| + int mx /* Largest permissible value of i */
|
| +){
|
| + sqlite3ErrorMsg(pParse,
|
| + "%r %s BY term out of range - should be "
|
| + "between 1 and %d", i, zType, mx);
|
| +}
|
| +
|
| +/*
|
| +** Analyze the ORDER BY clause in a compound SELECT statement. Modify
|
| +** each term of the ORDER BY clause is a constant integer between 1
|
| +** and N where N is the number of columns in the compound SELECT.
|
| +**
|
| +** ORDER BY terms that are already an integer between 1 and N are
|
| +** unmodified. ORDER BY terms that are integers outside the range of
|
| +** 1 through N generate an error. ORDER BY terms that are expressions
|
| +** are matched against result set expressions of compound SELECT
|
| +** beginning with the left-most SELECT and working toward the right.
|
| +** At the first match, the ORDER BY expression is transformed into
|
| +** the integer column number.
|
| +**
|
| +** Return the number of errors seen.
|
| +*/
|
| +static int resolveCompoundOrderBy(
|
| + Parse *pParse, /* Parsing context. Leave error messages here */
|
| + Select *pSelect /* The SELECT statement containing the ORDER BY */
|
| +){
|
| + int i;
|
| + ExprList *pOrderBy;
|
| + ExprList *pEList;
|
| + sqlite3 *db;
|
| + int moreToDo = 1;
|
| +
|
| + pOrderBy = pSelect->pOrderBy;
|
| + if( pOrderBy==0 ) return 0;
|
| + db = pParse->db;
|
| +#if SQLITE_MAX_COLUMN
|
| + if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
|
| + sqlite3ErrorMsg(pParse, "too many terms in ORDER BY clause");
|
| + return 1;
|
| + }
|
| +#endif
|
| + for(i=0; i<pOrderBy->nExpr; i++){
|
| + pOrderBy->a[i].done = 0;
|
| + }
|
| + pSelect->pNext = 0;
|
| + while( pSelect->pPrior ){
|
| + pSelect->pPrior->pNext = pSelect;
|
| + pSelect = pSelect->pPrior;
|
| + }
|
| + while( pSelect && moreToDo ){
|
| + struct ExprList_item *pItem;
|
| + moreToDo = 0;
|
| + pEList = pSelect->pEList;
|
| + assert( pEList!=0 );
|
| + for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
|
| + int iCol = -1;
|
| + Expr *pE, *pDup;
|
| + if( pItem->done ) continue;
|
| + pE = sqlite3ExprSkipCollate(pItem->pExpr);
|
| + if( sqlite3ExprIsInteger(pE, &iCol) ){
|
| + if( iCol<=0 || iCol>pEList->nExpr ){
|
| + resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr);
|
| + return 1;
|
| + }
|
| + }else{
|
| + iCol = resolveAsName(pParse, pEList, pE);
|
| + if( iCol==0 ){
|
| + pDup = sqlite3ExprDup(db, pE, 0);
|
| + if( !db->mallocFailed ){
|
| + assert(pDup);
|
| + iCol = resolveOrderByTermToExprList(pParse, pSelect, pDup);
|
| + }
|
| + sqlite3ExprDelete(db, pDup);
|
| + }
|
| + }
|
| + if( iCol>0 ){
|
| + /* Convert the ORDER BY term into an integer column number iCol,
|
| + ** taking care to preserve the COLLATE clause if it exists */
|
| + Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0);
|
| + if( pNew==0 ) return 1;
|
| + pNew->flags |= EP_IntValue;
|
| + pNew->u.iValue = iCol;
|
| + if( pItem->pExpr==pE ){
|
| + pItem->pExpr = pNew;
|
| + }else{
|
| + Expr *pParent = pItem->pExpr;
|
| + assert( pParent->op==TK_COLLATE );
|
| + while( pParent->pLeft->op==TK_COLLATE ) pParent = pParent->pLeft;
|
| + assert( pParent->pLeft==pE );
|
| + pParent->pLeft = pNew;
|
| + }
|
| + sqlite3ExprDelete(db, pE);
|
| + pItem->u.x.iOrderByCol = (u16)iCol;
|
| + pItem->done = 1;
|
| + }else{
|
| + moreToDo = 1;
|
| + }
|
| + }
|
| + pSelect = pSelect->pNext;
|
| + }
|
| + for(i=0; i<pOrderBy->nExpr; i++){
|
| + if( pOrderBy->a[i].done==0 ){
|
| + sqlite3ErrorMsg(pParse, "%r ORDER BY term does not match any "
|
| + "column in the result set", i+1);
|
| + return 1;
|
| + }
|
| + }
|
| + return 0;
|
| +}
|
| +
|
| +/*
|
| +** Check every term in the ORDER BY or GROUP BY clause pOrderBy of
|
| +** the SELECT statement pSelect. If any term is reference to a
|
| +** result set expression (as determined by the ExprList.a.u.x.iOrderByCol
|
| +** field) then convert that term into a copy of the corresponding result set
|
| +** column.
|
| +**
|
| +** If any errors are detected, add an error message to pParse and
|
| +** return non-zero. Return zero if no errors are seen.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(
|
| + Parse *pParse, /* Parsing context. Leave error messages here */
|
| + Select *pSelect, /* The SELECT statement containing the clause */
|
| + ExprList *pOrderBy, /* The ORDER BY or GROUP BY clause to be processed */
|
| + const char *zType /* "ORDER" or "GROUP" */
|
| +){
|
| + int i;
|
| + sqlite3 *db = pParse->db;
|
| + ExprList *pEList;
|
| + struct ExprList_item *pItem;
|
| +
|
| + if( pOrderBy==0 || pParse->db->mallocFailed ) return 0;
|
| +#if SQLITE_MAX_COLUMN
|
| + if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
|
| + sqlite3ErrorMsg(pParse, "too many terms in %s BY clause", zType);
|
| + return 1;
|
| + }
|
| +#endif
|
| + pEList = pSelect->pEList;
|
| + assert( pEList!=0 ); /* sqlite3SelectNew() guarantees this */
|
| + for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
|
| + if( pItem->u.x.iOrderByCol ){
|
| + if( pItem->u.x.iOrderByCol>pEList->nExpr ){
|
| + resolveOutOfRangeError(pParse, zType, i+1, pEList->nExpr);
|
| + return 1;
|
| + }
|
| + resolveAlias(pParse, pEList, pItem->u.x.iOrderByCol-1, pItem->pExpr,
|
| + zType,0);
|
| + }
|
| + }
|
| + return 0;
|
| +}
|
| +
|
| +/*
|
| +** pOrderBy is an ORDER BY or GROUP BY clause in SELECT statement pSelect.
|
| +** The Name context of the SELECT statement is pNC. zType is either
|
| +** "ORDER" or "GROUP" depending on which type of clause pOrderBy is.
|
| +**
|
| +** This routine resolves each term of the clause into an expression.
|
| +** If the order-by term is an integer I between 1 and N (where N is the
|
| +** number of columns in the result set of the SELECT) then the expression
|
| +** in the resolution is a copy of the I-th result-set expression. If
|
| +** the order-by term is an identifier that corresponds to the AS-name of
|
| +** a result-set expression, then the term resolves to a copy of the
|
| +** result-set expression. Otherwise, the expression is resolved in
|
| +** the usual way - using sqlite3ResolveExprNames().
|
| +**
|
| +** This routine returns the number of errors. If errors occur, then
|
| +** an appropriate error message might be left in pParse. (OOM errors
|
| +** excepted.)
|
| +*/
|
| +static int resolveOrderGroupBy(
|
| + NameContext *pNC, /* The name context of the SELECT statement */
|
| + Select *pSelect, /* The SELECT statement holding pOrderBy */
|
| + ExprList *pOrderBy, /* An ORDER BY or GROUP BY clause to resolve */
|
| + const char *zType /* Either "ORDER" or "GROUP", as appropriate */
|
| +){
|
| + int i, j; /* Loop counters */
|
| + int iCol; /* Column number */
|
| + struct ExprList_item *pItem; /* A term of the ORDER BY clause */
|
| + Parse *pParse; /* Parsing context */
|
| + int nResult; /* Number of terms in the result set */
|
| +
|
| + if( pOrderBy==0 ) return 0;
|
| + nResult = pSelect->pEList->nExpr;
|
| + pParse = pNC->pParse;
|
| + for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
|
| + Expr *pE = pItem->pExpr;
|
| + Expr *pE2 = sqlite3ExprSkipCollate(pE);
|
| + if( zType[0]!='G' ){
|
| + iCol = resolveAsName(pParse, pSelect->pEList, pE2);
|
| + if( iCol>0 ){
|
| + /* If an AS-name match is found, mark this ORDER BY column as being
|
| + ** a copy of the iCol-th result-set column. The subsequent call to
|
| + ** sqlite3ResolveOrderGroupBy() will convert the expression to a
|
| + ** copy of the iCol-th result-set expression. */
|
| + pItem->u.x.iOrderByCol = (u16)iCol;
|
| + continue;
|
| + }
|
| + }
|
| + if( sqlite3ExprIsInteger(pE2, &iCol) ){
|
| + /* The ORDER BY term is an integer constant. Again, set the column
|
| + ** number so that sqlite3ResolveOrderGroupBy() will convert the
|
| + ** order-by term to a copy of the result-set expression */
|
| + if( iCol<1 || iCol>0xffff ){
|
| + resolveOutOfRangeError(pParse, zType, i+1, nResult);
|
| + return 1;
|
| + }
|
| + pItem->u.x.iOrderByCol = (u16)iCol;
|
| + continue;
|
| + }
|
| +
|
| + /* Otherwise, treat the ORDER BY term as an ordinary expression */
|
| + pItem->u.x.iOrderByCol = 0;
|
| + if( sqlite3ResolveExprNames(pNC, pE) ){
|
| + return 1;
|
| + }
|
| + for(j=0; j<pSelect->pEList->nExpr; j++){
|
| + if( sqlite3ExprCompare(pE, pSelect->pEList->a[j].pExpr, -1)==0 ){
|
| + pItem->u.x.iOrderByCol = j+1;
|
| + }
|
| + }
|
| + }
|
| + return sqlite3ResolveOrderGroupBy(pParse, pSelect, pOrderBy, zType);
|
| +}
|
| +
|
| +/*
|
| +** Resolve names in the SELECT statement p and all of its descendants.
|
| +*/
|
| +static int resolveSelectStep(Walker *pWalker, Select *p){
|
| + NameContext *pOuterNC; /* Context that contains this SELECT */
|
| + NameContext sNC; /* Name context of this SELECT */
|
| + int isCompound; /* True if p is a compound select */
|
| + int nCompound; /* Number of compound terms processed so far */
|
| + Parse *pParse; /* Parsing context */
|
| + int i; /* Loop counter */
|
| + ExprList *pGroupBy; /* The GROUP BY clause */
|
| + Select *pLeftmost; /* Left-most of SELECT of a compound */
|
| + sqlite3 *db; /* Database connection */
|
| +
|
| +
|
| + assert( p!=0 );
|
| + if( p->selFlags & SF_Resolved ){
|
| + return WRC_Prune;
|
| + }
|
| + pOuterNC = pWalker->u.pNC;
|
| + pParse = pWalker->pParse;
|
| + db = pParse->db;
|
| +
|
| + /* Normally sqlite3SelectExpand() will be called first and will have
|
| + ** already expanded this SELECT. However, if this is a subquery within
|
| + ** an expression, sqlite3ResolveExprNames() will be called without a
|
| + ** prior call to sqlite3SelectExpand(). When that happens, let
|
| + ** sqlite3SelectPrep() do all of the processing for this SELECT.
|
| + ** sqlite3SelectPrep() will invoke both sqlite3SelectExpand() and
|
| + ** this routine in the correct order.
|
| + */
|
| + if( (p->selFlags & SF_Expanded)==0 ){
|
| + sqlite3SelectPrep(pParse, p, pOuterNC);
|
| + return (pParse->nErr || db->mallocFailed) ? WRC_Abort : WRC_Prune;
|
| + }
|
| +
|
| + isCompound = p->pPrior!=0;
|
| + nCompound = 0;
|
| + pLeftmost = p;
|
| + while( p ){
|
| + assert( (p->selFlags & SF_Expanded)!=0 );
|
| + assert( (p->selFlags & SF_Resolved)==0 );
|
| + p->selFlags |= SF_Resolved;
|
| +
|
| + /* Resolve the expressions in the LIMIT and OFFSET clauses. These
|
| + ** are not allowed to refer to any names, so pass an empty NameContext.
|
| + */
|
| + memset(&sNC, 0, sizeof(sNC));
|
| + sNC.pParse = pParse;
|
| + if( sqlite3ResolveExprNames(&sNC, p->pLimit) ||
|
| + sqlite3ResolveExprNames(&sNC, p->pOffset) ){
|
| + return WRC_Abort;
|
| + }
|
| +
|
| + /* If the SF_Converted flags is set, then this Select object was
|
| + ** was created by the convertCompoundSelectToSubquery() function.
|
| + ** In this case the ORDER BY clause (p->pOrderBy) should be resolved
|
| + ** as if it were part of the sub-query, not the parent. This block
|
| + ** moves the pOrderBy down to the sub-query. It will be moved back
|
| + ** after the names have been resolved. */
|
| + if( p->selFlags & SF_Converted ){
|
| + Select *pSub = p->pSrc->a[0].pSelect;
|
| + assert( p->pSrc->nSrc==1 && p->pOrderBy );
|
| + assert( pSub->pPrior && pSub->pOrderBy==0 );
|
| + pSub->pOrderBy = p->pOrderBy;
|
| + p->pOrderBy = 0;
|
| + }
|
| +
|
| + /* Recursively resolve names in all subqueries
|
| + */
|
| + for(i=0; i<p->pSrc->nSrc; i++){
|
| + struct SrcList_item *pItem = &p->pSrc->a[i];
|
| + if( pItem->pSelect ){
|
| + NameContext *pNC; /* Used to iterate name contexts */
|
| + int nRef = 0; /* Refcount for pOuterNC and outer contexts */
|
| + const char *zSavedContext = pParse->zAuthContext;
|
| +
|
| + /* Count the total number of references to pOuterNC and all of its
|
| + ** parent contexts. After resolving references to expressions in
|
| + ** pItem->pSelect, check if this value has changed. If so, then
|
| + ** SELECT statement pItem->pSelect must be correlated. Set the
|
| + ** pItem->fg.isCorrelated flag if this is the case. */
|
| + for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef += pNC->nRef;
|
| +
|
| + if( pItem->zName ) pParse->zAuthContext = pItem->zName;
|
| + sqlite3ResolveSelectNames(pParse, pItem->pSelect, pOuterNC);
|
| + pParse->zAuthContext = zSavedContext;
|
| + if( pParse->nErr || db->mallocFailed ) return WRC_Abort;
|
| +
|
| + for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef -= pNC->nRef;
|
| + assert( pItem->fg.isCorrelated==0 && nRef<=0 );
|
| + pItem->fg.isCorrelated = (nRef!=0);
|
| + }
|
| + }
|
| +
|
| + /* Set up the local name-context to pass to sqlite3ResolveExprNames() to
|
| + ** resolve the result-set expression list.
|
| + */
|
| + sNC.ncFlags = NC_AllowAgg;
|
| + sNC.pSrcList = p->pSrc;
|
| + sNC.pNext = pOuterNC;
|
| +
|
| + /* Resolve names in the result set. */
|
| + if( sqlite3ResolveExprListNames(&sNC, p->pEList) ) return WRC_Abort;
|
| +
|
| + /* If there are no aggregate functions in the result-set, and no GROUP BY
|
| + ** expression, do not allow aggregates in any of the other expressions.
|
| + */
|
| + assert( (p->selFlags & SF_Aggregate)==0 );
|
| + pGroupBy = p->pGroupBy;
|
| + if( pGroupBy || (sNC.ncFlags & NC_HasAgg)!=0 ){
|
| + assert( NC_MinMaxAgg==SF_MinMaxAgg );
|
| + p->selFlags |= SF_Aggregate | (sNC.ncFlags&NC_MinMaxAgg);
|
| + }else{
|
| + sNC.ncFlags &= ~NC_AllowAgg;
|
| + }
|
| +
|
| + /* If a HAVING clause is present, then there must be a GROUP BY clause.
|
| + */
|
| + if( p->pHaving && !pGroupBy ){
|
| + sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING");
|
| + return WRC_Abort;
|
| + }
|
| +
|
| + /* Add the output column list to the name-context before parsing the
|
| + ** other expressions in the SELECT statement. This is so that
|
| + ** expressions in the WHERE clause (etc.) can refer to expressions by
|
| + ** aliases in the result set.
|
| + **
|
| + ** Minor point: If this is the case, then the expression will be
|
| + ** re-evaluated for each reference to it.
|
| + */
|
| + sNC.pEList = p->pEList;
|
| + if( sqlite3ResolveExprNames(&sNC, p->pHaving) ) return WRC_Abort;
|
| + if( sqlite3ResolveExprNames(&sNC, p->pWhere) ) return WRC_Abort;
|
| +
|
| + /* Resolve names in table-valued-function arguments */
|
| + for(i=0; i<p->pSrc->nSrc; i++){
|
| + struct SrcList_item *pItem = &p->pSrc->a[i];
|
| + if( pItem->fg.isTabFunc
|
| + && sqlite3ResolveExprListNames(&sNC, pItem->u1.pFuncArg)
|
| + ){
|
| + return WRC_Abort;
|
| + }
|
| + }
|
| +
|
| + /* The ORDER BY and GROUP BY clauses may not refer to terms in
|
| + ** outer queries
|
| + */
|
| + sNC.pNext = 0;
|
| + sNC.ncFlags |= NC_AllowAgg;
|
| +
|
| + /* If this is a converted compound query, move the ORDER BY clause from
|
| + ** the sub-query back to the parent query. At this point each term
|
| + ** within the ORDER BY clause has been transformed to an integer value.
|
| + ** These integers will be replaced by copies of the corresponding result
|
| + ** set expressions by the call to resolveOrderGroupBy() below. */
|
| + if( p->selFlags & SF_Converted ){
|
| + Select *pSub = p->pSrc->a[0].pSelect;
|
| + p->pOrderBy = pSub->pOrderBy;
|
| + pSub->pOrderBy = 0;
|
| + }
|
| +
|
| + /* Process the ORDER BY clause for singleton SELECT statements.
|
| + ** The ORDER BY clause for compounds SELECT statements is handled
|
| + ** below, after all of the result-sets for all of the elements of
|
| + ** the compound have been resolved.
|
| + **
|
| + ** If there is an ORDER BY clause on a term of a compound-select other
|
| + ** than the right-most term, then that is a syntax error. But the error
|
| + ** is not detected until much later, and so we need to go ahead and
|
| + ** resolve those symbols on the incorrect ORDER BY for consistency.
|
| + */
|
| + if( isCompound<=nCompound /* Defer right-most ORDER BY of a compound */
|
| + && resolveOrderGroupBy(&sNC, p, p->pOrderBy, "ORDER")
|
| + ){
|
| + return WRC_Abort;
|
| + }
|
| + if( db->mallocFailed ){
|
| + return WRC_Abort;
|
| + }
|
| +
|
| + /* Resolve the GROUP BY clause. At the same time, make sure
|
| + ** the GROUP BY clause does not contain aggregate functions.
|
| + */
|
| + if( pGroupBy ){
|
| + struct ExprList_item *pItem;
|
| +
|
| + if( resolveOrderGroupBy(&sNC, p, pGroupBy, "GROUP") || db->mallocFailed ){
|
| + return WRC_Abort;
|
| + }
|
| + for(i=0, pItem=pGroupBy->a; i<pGroupBy->nExpr; i++, pItem++){
|
| + if( ExprHasProperty(pItem->pExpr, EP_Agg) ){
|
| + sqlite3ErrorMsg(pParse, "aggregate functions are not allowed in "
|
| + "the GROUP BY clause");
|
| + return WRC_Abort;
|
| + }
|
| + }
|
| + }
|
| +
|
| + /* If this is part of a compound SELECT, check that it has the right
|
| + ** number of expressions in the select list. */
|
| + if( p->pNext && p->pEList->nExpr!=p->pNext->pEList->nExpr ){
|
| + sqlite3SelectWrongNumTermsError(pParse, p->pNext);
|
| + return WRC_Abort;
|
| + }
|
| +
|
| + /* Advance to the next term of the compound
|
| + */
|
| + p = p->pPrior;
|
| + nCompound++;
|
| + }
|
| +
|
| + /* Resolve the ORDER BY on a compound SELECT after all terms of
|
| + ** the compound have been resolved.
|
| + */
|
| + if( isCompound && resolveCompoundOrderBy(pParse, pLeftmost) ){
|
| + return WRC_Abort;
|
| + }
|
| +
|
| + return WRC_Prune;
|
| +}
|
| +
|
| +/*
|
| +** This routine walks an expression tree and resolves references to
|
| +** table columns and result-set columns. At the same time, do error
|
| +** checking on function usage and set a flag if any aggregate functions
|
| +** are seen.
|
| +**
|
| +** To resolve table columns references we look for nodes (or subtrees) of the
|
| +** form X.Y.Z or Y.Z or just Z where
|
| +**
|
| +** X: The name of a database. Ex: "main" or "temp" or
|
| +** the symbolic name assigned to an ATTACH-ed database.
|
| +**
|
| +** Y: The name of a table in a FROM clause. Or in a trigger
|
| +** one of the special names "old" or "new".
|
| +**
|
| +** Z: The name of a column in table Y.
|
| +**
|
| +** The node at the root of the subtree is modified as follows:
|
| +**
|
| +** Expr.op Changed to TK_COLUMN
|
| +** Expr.pTab Points to the Table object for X.Y
|
| +** Expr.iColumn The column index in X.Y. -1 for the rowid.
|
| +** Expr.iTable The VDBE cursor number for X.Y
|
| +**
|
| +**
|
| +** To resolve result-set references, look for expression nodes of the
|
| +** form Z (with no X and Y prefix) where the Z matches the right-hand
|
| +** size of an AS clause in the result-set of a SELECT. The Z expression
|
| +** is replaced by a copy of the left-hand side of the result-set expression.
|
| +** Table-name and function resolution occurs on the substituted expression
|
| +** tree. For example, in:
|
| +**
|
| +** SELECT a+b AS x, c+d AS y FROM t1 ORDER BY x;
|
| +**
|
| +** The "x" term of the order by is replaced by "a+b" to render:
|
| +**
|
| +** SELECT a+b AS x, c+d AS y FROM t1 ORDER BY a+b;
|
| +**
|
| +** Function calls are checked to make sure that the function is
|
| +** defined and that the correct number of arguments are specified.
|
| +** If the function is an aggregate function, then the NC_HasAgg flag is
|
| +** set and the opcode is changed from TK_FUNCTION to TK_AGG_FUNCTION.
|
| +** If an expression contains aggregate functions then the EP_Agg
|
| +** property on the expression is set.
|
| +**
|
| +** An error message is left in pParse if anything is amiss. The number
|
| +** if errors is returned.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3ResolveExprNames(
|
| + NameContext *pNC, /* Namespace to resolve expressions in. */
|
| + Expr *pExpr /* The expression to be analyzed. */
|
| +){
|
| + u16 savedHasAgg;
|
| + Walker w;
|
| +
|
| + if( pExpr==0 ) return 0;
|
| +#if SQLITE_MAX_EXPR_DEPTH>0
|
| + {
|
| + Parse *pParse = pNC->pParse;
|
| + if( sqlite3ExprCheckHeight(pParse, pExpr->nHeight+pNC->pParse->nHeight) ){
|
| + return 1;
|
| + }
|
| + pParse->nHeight += pExpr->nHeight;
|
| + }
|
| +#endif
|
| + savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg);
|
| + pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg);
|
| + memset(&w, 0, sizeof(w));
|
| + w.xExprCallback = resolveExprStep;
|
| + w.xSelectCallback = resolveSelectStep;
|
| + w.pParse = pNC->pParse;
|
| + w.u.pNC = pNC;
|
| + sqlite3WalkExpr(&w, pExpr);
|
| +#if SQLITE_MAX_EXPR_DEPTH>0
|
| + pNC->pParse->nHeight -= pExpr->nHeight;
|
| +#endif
|
| + if( pNC->nErr>0 || w.pParse->nErr>0 ){
|
| + ExprSetProperty(pExpr, EP_Error);
|
| + }
|
| + if( pNC->ncFlags & NC_HasAgg ){
|
| + ExprSetProperty(pExpr, EP_Agg);
|
| + }
|
| + pNC->ncFlags |= savedHasAgg;
|
| + return ExprHasProperty(pExpr, EP_Error);
|
| +}
|
| +
|
| +/*
|
| +** Resolve all names for all expression in an expression list. This is
|
| +** just like sqlite3ResolveExprNames() except that it works for an expression
|
| +** list rather than a single expression.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3ResolveExprListNames(
|
| + NameContext *pNC, /* Namespace to resolve expressions in. */
|
| + ExprList *pList /* The expression list to be analyzed. */
|
| +){
|
| + int i;
|
| + if( pList ){
|
| + for(i=0; i<pList->nExpr; i++){
|
| + if( sqlite3ResolveExprNames(pNC, pList->a[i].pExpr) ) return WRC_Abort;
|
| + }
|
| + }
|
| + return WRC_Continue;
|
| +}
|
| +
|
| +/*
|
| +** Resolve all names in all expressions of a SELECT and in all
|
| +** decendents of the SELECT, including compounds off of p->pPrior,
|
| +** subqueries in expressions, and subqueries used as FROM clause
|
| +** terms.
|
| +**
|
| +** See sqlite3ResolveExprNames() for a description of the kinds of
|
| +** transformations that occur.
|
| +**
|
| +** All SELECT statements should have been expanded using
|
| +** sqlite3SelectExpand() prior to invoking this routine.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3ResolveSelectNames(
|
| + Parse *pParse, /* The parser context */
|
| + Select *p, /* The SELECT statement being coded. */
|
| + NameContext *pOuterNC /* Name context for parent SELECT statement */
|
| +){
|
| + Walker w;
|
| +
|
| + assert( p!=0 );
|
| + memset(&w, 0, sizeof(w));
|
| + w.xExprCallback = resolveExprStep;
|
| + w.xSelectCallback = resolveSelectStep;
|
| + w.pParse = pParse;
|
| + w.u.pNC = pOuterNC;
|
| + sqlite3WalkSelect(&w, p);
|
| +}
|
| +
|
| +/*
|
| +** Resolve names in expressions that can only reference a single table:
|
| +**
|
| +** * CHECK constraints
|
| +** * WHERE clauses on partial indices
|
| +**
|
| +** The Expr.iTable value for Expr.op==TK_COLUMN nodes of the expression
|
| +** is set to -1 and the Expr.iColumn value is set to the column number.
|
| +**
|
| +** Any errors cause an error message to be set in pParse.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3ResolveSelfReference(
|
| + Parse *pParse, /* Parsing context */
|
| + Table *pTab, /* The table being referenced */
|
| + int type, /* NC_IsCheck or NC_PartIdx or NC_IdxExpr */
|
| + Expr *pExpr, /* Expression to resolve. May be NULL. */
|
| + ExprList *pList /* Expression list to resolve. May be NUL. */
|
| +){
|
| + SrcList sSrc; /* Fake SrcList for pParse->pNewTable */
|
| + NameContext sNC; /* Name context for pParse->pNewTable */
|
| +
|
| + assert( type==NC_IsCheck || type==NC_PartIdx || type==NC_IdxExpr );
|
| + memset(&sNC, 0, sizeof(sNC));
|
| + memset(&sSrc, 0, sizeof(sSrc));
|
| + sSrc.nSrc = 1;
|
| + sSrc.a[0].zName = pTab->zName;
|
| + sSrc.a[0].pTab = pTab;
|
| + sSrc.a[0].iCursor = -1;
|
| + sNC.pParse = pParse;
|
| + sNC.pSrcList = &sSrc;
|
| + sNC.ncFlags = type;
|
| + if( sqlite3ResolveExprNames(&sNC, pExpr) ) return;
|
| + if( pList ) sqlite3ResolveExprListNames(&sNC, pList);
|
| +}
|
| +
|
| +/************** End of resolve.c *********************************************/
|
| +/************** Begin file expr.c ********************************************/
|
| +/*
|
| +** 2001 September 15
|
| +**
|
| +** 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.
|
| +**
|
| +*************************************************************************
|
| +** This file contains routines used for analyzing expressions and
|
| +** for generating VDBE code that evaluates expressions in SQLite.
|
| +*/
|
| +/* #include "sqliteInt.h" */
|
| +
|
| +/*
|
| +** Return the 'affinity' of the expression pExpr if any.
|
| +**
|
| +** If pExpr is a column, a reference to a column via an 'AS' alias,
|
| +** or a sub-select with a column as the return value, then the
|
| +** affinity of that column is returned. Otherwise, 0x00 is returned,
|
| +** indicating no affinity for the expression.
|
| +**
|
| +** i.e. the WHERE clause expressions in the following statements all
|
| +** have an affinity:
|
| +**
|
| +** CREATE TABLE t1(a);
|
| +** SELECT * FROM t1 WHERE a;
|
| +** SELECT a AS b FROM t1 WHERE b;
|
| +** SELECT * FROM t1 WHERE (select a from t1);
|
| +*/
|
| +SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr){
|
| + int op;
|
| + pExpr = sqlite3ExprSkipCollate(pExpr);
|
| + if( pExpr->flags & EP_Generic ) return 0;
|
| + op = pExpr->op;
|
| + if( op==TK_SELECT ){
|
| + assert( pExpr->flags&EP_xIsSelect );
|
| + return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr);
|
| + }
|
| +#ifndef SQLITE_OMIT_CAST
|
| + if( op==TK_CAST ){
|
| + assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
| + return sqlite3AffinityType(pExpr->u.zToken, 0);
|
| + }
|
| +#endif
|
| + if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER)
|
| + && pExpr->pTab!=0
|
| + ){
|
| + /* op==TK_REGISTER && pExpr->pTab!=0 happens when pExpr was originally
|
| + ** a TK_COLUMN but was previously evaluated and cached in a register */
|
| + int j = pExpr->iColumn;
|
| + if( j<0 ) return SQLITE_AFF_INTEGER;
|
| + assert( pExpr->pTab && j<pExpr->pTab->nCol );
|
| + return pExpr->pTab->aCol[j].affinity;
|
| + }
|
| + return pExpr->affinity;
|
| +}
|
| +
|
| +/*
|
| +** Set the collating sequence for expression pExpr to be the collating
|
| +** sequence named by pToken. Return a pointer to a new Expr node that
|
| +** implements the COLLATE operator.
|
| +**
|
| +** If a memory allocation error occurs, that fact is recorded in pParse->db
|
| +** and the pExpr parameter is returned unchanged.
|
| +*/
|
| +SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(
|
| + Parse *pParse, /* Parsing context */
|
| + Expr *pExpr, /* Add the "COLLATE" clause to this expression */
|
| + const Token *pCollName, /* Name of collating sequence */
|
| + int dequote /* True to dequote pCollName */
|
| +){
|
| + if( pCollName->n>0 ){
|
| + Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, dequote);
|
| + if( pNew ){
|
| + pNew->pLeft = pExpr;
|
| + pNew->flags |= EP_Collate|EP_Skip;
|
| + pExpr = pNew;
|
| + }
|
| + }
|
| + return pExpr;
|
| +}
|
| +SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, const char *zC){
|
| + Token s;
|
| + assert( zC!=0 );
|
| + s.z = zC;
|
| + s.n = sqlite3Strlen30(s.z);
|
| + return sqlite3ExprAddCollateToken(pParse, pExpr, &s, 0);
|
| +}
|
| +
|
| +/*
|
| +** Skip over any TK_COLLATE operators and any unlikely()
|
| +** or likelihood() function at the root of an expression.
|
| +*/
|
| +SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr *pExpr){
|
| + while( pExpr && ExprHasProperty(pExpr, EP_Skip) ){
|
| + if( ExprHasProperty(pExpr, EP_Unlikely) ){
|
| + assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
|
| + assert( pExpr->x.pList->nExpr>0 );
|
| + assert( pExpr->op==TK_FUNCTION );
|
| + pExpr = pExpr->x.pList->a[0].pExpr;
|
| + }else{
|
| + assert( pExpr->op==TK_COLLATE );
|
| + pExpr = pExpr->pLeft;
|
| + }
|
| + }
|
| + return pExpr;
|
| +}
|
| +
|
| +/*
|
| +** Return the collation sequence for the expression pExpr. If
|
| +** there is no defined collating sequence, return NULL.
|
| +**
|
| +** The collating sequence might be determined by a COLLATE operator
|
| +** or by the presence of a column with a defined collating sequence.
|
| +** COLLATE operators take first precedence. Left operands take
|
| +** precedence over right operands.
|
| +*/
|
| +SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
|
| + sqlite3 *db = pParse->db;
|
| + CollSeq *pColl = 0;
|
| + Expr *p = pExpr;
|
| + while( p ){
|
| + int op = p->op;
|
| + if( p->flags & EP_Generic ) break;
|
| + if( op==TK_CAST || op==TK_UPLUS ){
|
| + p = p->pLeft;
|
| + continue;
|
| + }
|
| + if( op==TK_COLLATE || (op==TK_REGISTER && p->op2==TK_COLLATE) ){
|
| + pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken);
|
| + break;
|
| + }
|
| + if( (op==TK_AGG_COLUMN || op==TK_COLUMN
|
| + || op==TK_REGISTER || op==TK_TRIGGER)
|
| + && p->pTab!=0
|
| + ){
|
| + /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally
|
| + ** a TK_COLUMN but was previously evaluated and cached in a register */
|
| + int j = p->iColumn;
|
| + if( j>=0 ){
|
| + const char *zColl = p->pTab->aCol[j].zColl;
|
| + pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0);
|
| + }
|
| + break;
|
| + }
|
| + if( p->flags & EP_Collate ){
|
| + if( p->pLeft && (p->pLeft->flags & EP_Collate)!=0 ){
|
| + p = p->pLeft;
|
| + }else{
|
| + Expr *pNext = p->pRight;
|
| + /* The Expr.x union is never used at the same time as Expr.pRight */
|
| + assert( p->x.pList==0 || p->pRight==0 );
|
| + /* p->flags holds EP_Collate and p->pLeft->flags does not. And
|
| + ** p->x.pSelect cannot. So if p->x.pLeft exists, it must hold at
|
| + ** least one EP_Collate. Thus the following two ALWAYS. */
|
| + if( p->x.pList!=0 && ALWAYS(!ExprHasProperty(p, EP_xIsSelect)) ){
|
| + int i;
|
| + for(i=0; ALWAYS(i<p->x.pList->nExpr); i++){
|
| + if( ExprHasProperty(p->x.pList->a[i].pExpr, EP_Collate) ){
|
| + pNext = p->x.pList->a[i].pExpr;
|
| + break;
|
| + }
|
| + }
|
| + }
|
| + p = pNext;
|
| + }
|
| + }else{
|
| + break;
|
| + }
|
| + }
|
| + if( sqlite3CheckCollSeq(pParse, pColl) ){
|
| + pColl = 0;
|
| + }
|
| + return pColl;
|
| +}
|
| +
|
| +/*
|
| +** pExpr is an operand of a comparison operator. aff2 is the
|
| +** type affinity of the other operand. This routine returns the
|
| +** type affinity that should be used for the comparison operator.
|
| +*/
|
| +SQLITE_PRIVATE char sqlite3CompareAffinity(Expr *pExpr, char aff2){
|
| + char aff1 = sqlite3ExprAffinity(pExpr);
|
| + if( aff1 && aff2 ){
|
| + /* Both sides of the comparison are columns. If one has numeric
|
| + ** affinity, use that. Otherwise use no affinity.
|
| + */
|
| + if( sqlite3IsNumericAffinity(aff1) || sqlite3IsNumericAffinity(aff2) ){
|
| + return SQLITE_AFF_NUMERIC;
|
| + }else{
|
| + return SQLITE_AFF_BLOB;
|
| + }
|
| + }else if( !aff1 && !aff2 ){
|
| + /* Neither side of the comparison is a column. Compare the
|
| + ** results directly.
|
| + */
|
| + return SQLITE_AFF_BLOB;
|
| + }else{
|
| + /* One side is a column, the other is not. Use the columns affinity. */
|
| + assert( aff1==0 || aff2==0 );
|
| + return (aff1 + aff2);
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** pExpr is a comparison operator. Return the type affinity that should
|
| +** be applied to both operands prior to doing the comparison.
|
| +*/
|
| +static char comparisonAffinity(Expr *pExpr){
|
| + char aff;
|
| + assert( pExpr->op==TK_EQ || pExpr->op==TK_IN || pExpr->op==TK_LT ||
|
| + pExpr->op==TK_GT || pExpr->op==TK_GE || pExpr->op==TK_LE ||
|
| + pExpr->op==TK_NE || pExpr->op==TK_IS || pExpr->op==TK_ISNOT );
|
| + assert( pExpr->pLeft );
|
| + aff = sqlite3ExprAffinity(pExpr->pLeft);
|
| + if( pExpr->pRight ){
|
| + aff = sqlite3CompareAffinity(pExpr->pRight, aff);
|
| + }else if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
| + aff = sqlite3CompareAffinity(pExpr->x.pSelect->pEList->a[0].pExpr, aff);
|
| + }else if( !aff ){
|
| + aff = SQLITE_AFF_BLOB;
|
| + }
|
| + return aff;
|
| +}
|
| +
|
| +/*
|
| +** pExpr is a comparison expression, eg. '=', '<', IN(...) etc.
|
| +** idx_affinity is the affinity of an indexed column. Return true
|
| +** if the index with affinity idx_affinity may be used to implement
|
| +** the comparison in pExpr.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity){
|
| + char aff = comparisonAffinity(pExpr);
|
| + switch( aff ){
|
| + case SQLITE_AFF_BLOB:
|
| + return 1;
|
| + case SQLITE_AFF_TEXT:
|
| + return idx_affinity==SQLITE_AFF_TEXT;
|
| + default:
|
| + return sqlite3IsNumericAffinity(idx_affinity);
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Return the P5 value that should be used for a binary comparison
|
| +** opcode (OP_Eq, OP_Ge etc.) used to compare pExpr1 and pExpr2.
|
| +*/
|
| +static u8 binaryCompareP5(Expr *pExpr1, Expr *pExpr2, int jumpIfNull){
|
| + u8 aff = (char)sqlite3ExprAffinity(pExpr2);
|
| + aff = (u8)sqlite3CompareAffinity(pExpr1, aff) | (u8)jumpIfNull;
|
| + return aff;
|
| +}
|
| +
|
| +/*
|
| +** Return a pointer to the collation sequence that should be used by
|
| +** a binary comparison operator comparing pLeft and pRight.
|
| +**
|
| +** If the left hand expression has a collating sequence type, then it is
|
| +** used. Otherwise the collation sequence for the right hand expression
|
| +** is used, or the default (BINARY) if neither expression has a collating
|
| +** type.
|
| +**
|
| +** Argument pRight (but not pLeft) may be a null pointer. In this case,
|
| +** it is not considered.
|
| +*/
|
| +SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq(
|
| + Parse *pParse,
|
| + Expr *pLeft,
|
| + Expr *pRight
|
| +){
|
| + CollSeq *pColl;
|
| + assert( pLeft );
|
| + if( pLeft->flags & EP_Collate ){
|
| + pColl = sqlite3ExprCollSeq(pParse, pLeft);
|
| + }else if( pRight && (pRight->flags & EP_Collate)!=0 ){
|
| + pColl = sqlite3ExprCollSeq(pParse, pRight);
|
| + }else{
|
| + pColl = sqlite3ExprCollSeq(pParse, pLeft);
|
| + if( !pColl ){
|
| + pColl = sqlite3ExprCollSeq(pParse, pRight);
|
| + }
|
| + }
|
| + return pColl;
|
| +}
|
| +
|
| +/*
|
| +** Generate code for a comparison operator.
|
| +*/
|
| +static int codeCompare(
|
| + Parse *pParse, /* The parsing (and code generating) context */
|
| + Expr *pLeft, /* The left operand */
|
| + Expr *pRight, /* The right operand */
|
| + int opcode, /* The comparison opcode */
|
| + int in1, int in2, /* Register holding operands */
|
| + int dest, /* Jump here if true. */
|
| + int jumpIfNull /* If true, jump if either operand is NULL */
|
| +){
|
| + int p5;
|
| + int addr;
|
| + CollSeq *p4;
|
| +
|
| + p4 = sqlite3BinaryCompareCollSeq(pParse, pLeft, pRight);
|
| + p5 = binaryCompareP5(pLeft, pRight, jumpIfNull);
|
| + addr = sqlite3VdbeAddOp4(pParse->pVdbe, opcode, in2, dest, in1,
|
| + (void*)p4, P4_COLLSEQ);
|
| + sqlite3VdbeChangeP5(pParse->pVdbe, (u8)p5);
|
| + return addr;
|
| +}
|
| +
|
| +#if SQLITE_MAX_EXPR_DEPTH>0
|
| +/*
|
| +** Check that argument nHeight is less than or equal to the maximum
|
| +** expression depth allowed. If it is not, leave an error message in
|
| +** pParse.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3ExprCheckHeight(Parse *pParse, int nHeight){
|
| + int rc = SQLITE_OK;
|
| + int mxHeight = pParse->db->aLimit[SQLITE_LIMIT_EXPR_DEPTH];
|
| + if( nHeight>mxHeight ){
|
| + sqlite3ErrorMsg(pParse,
|
| + "Expression tree is too large (maximum depth %d)", mxHeight
|
| + );
|
| + rc = SQLITE_ERROR;
|
| + }
|
| + return rc;
|
| +}
|
| +
|
| +/* The following three functions, heightOfExpr(), heightOfExprList()
|
| +** and heightOfSelect(), are used to determine the maximum height
|
| +** of any expression tree referenced by the structure passed as the
|
| +** first argument.
|
| +**
|
| +** If this maximum height is greater than the current value pointed
|
| +** to by pnHeight, the second parameter, then set *pnHeight to that
|
| +** value.
|
| +*/
|
| +static void heightOfExpr(Expr *p, int *pnHeight){
|
| + if( p ){
|
| + if( p->nHeight>*pnHeight ){
|
| + *pnHeight = p->nHeight;
|
| + }
|
| + }
|
| +}
|
| +static void heightOfExprList(ExprList *p, int *pnHeight){
|
| + if( p ){
|
| + int i;
|
| + for(i=0; i<p->nExpr; i++){
|
| + heightOfExpr(p->a[i].pExpr, pnHeight);
|
| + }
|
| + }
|
| +}
|
| +static void heightOfSelect(Select *p, int *pnHeight){
|
| + if( p ){
|
| + heightOfExpr(p->pWhere, pnHeight);
|
| + heightOfExpr(p->pHaving, pnHeight);
|
| + heightOfExpr(p->pLimit, pnHeight);
|
| + heightOfExpr(p->pOffset, pnHeight);
|
| + heightOfExprList(p->pEList, pnHeight);
|
| + heightOfExprList(p->pGroupBy, pnHeight);
|
| + heightOfExprList(p->pOrderBy, pnHeight);
|
| + heightOfSelect(p->pPrior, pnHeight);
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Set the Expr.nHeight variable in the structure passed as an
|
| +** argument. An expression with no children, Expr.pList or
|
| +** Expr.pSelect member has a height of 1. Any other expression
|
| +** has a height equal to the maximum height of any other
|
| +** referenced Expr plus one.
|
| +**
|
| +** Also propagate EP_Propagate flags up from Expr.x.pList to Expr.flags,
|
| +** if appropriate.
|
| +*/
|
| +static void exprSetHeight(Expr *p){
|
| + int nHeight = 0;
|
| + heightOfExpr(p->pLeft, &nHeight);
|
| + heightOfExpr(p->pRight, &nHeight);
|
| + if( ExprHasProperty(p, EP_xIsSelect) ){
|
| + heightOfSelect(p->x.pSelect, &nHeight);
|
| + }else if( p->x.pList ){
|
| + heightOfExprList(p->x.pList, &nHeight);
|
| + p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList);
|
| + }
|
| + p->nHeight = nHeight + 1;
|
| +}
|
| +
|
| +/*
|
| +** Set the Expr.nHeight variable using the exprSetHeight() function. If
|
| +** the height is greater than the maximum allowed expression depth,
|
| +** leave an error in pParse.
|
| +**
|
| +** Also propagate all EP_Propagate flags from the Expr.x.pList into
|
| +** Expr.flags.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){
|
| + if( pParse->nErr ) return;
|
| + exprSetHeight(p);
|
| + sqlite3ExprCheckHeight(pParse, p->nHeight);
|
| +}
|
| +
|
| +/*
|
| +** Return the maximum height of any expression tree referenced
|
| +** by the select statement passed as an argument.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3SelectExprHeight(Select *p){
|
| + int nHeight = 0;
|
| + heightOfSelect(p, &nHeight);
|
| + return nHeight;
|
| +}
|
| +#else /* ABOVE: Height enforcement enabled. BELOW: Height enforcement off */
|
| +/*
|
| +** Propagate all EP_Propagate flags from the Expr.x.pList into
|
| +** Expr.flags.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){
|
| + if( p && p->x.pList && !ExprHasProperty(p, EP_xIsSelect) ){
|
| + p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList);
|
| + }
|
| +}
|
| +#define exprSetHeight(y)
|
| +#endif /* SQLITE_MAX_EXPR_DEPTH>0 */
|
| +
|
| +/*
|
| +** This routine is the core allocator for Expr nodes.
|
| +**
|
| +** Construct a new expression node and return a pointer to it. Memory
|
| +** for this node and for the pToken argument is a single allocation
|
| +** obtained from sqlite3DbMalloc(). The calling function
|
| +** is responsible for making sure the node eventually gets freed.
|
| +**
|
| +** If dequote is true, then the token (if it exists) is dequoted.
|
| +** If dequote is false, no dequoting is performed. The deQuote
|
| +** parameter is ignored if pToken is NULL or if the token does not
|
| +** appear to be quoted. If the quotes were of the form "..." (double-quotes)
|
| +** then the EP_DblQuoted flag is set on the expression node.
|
| +**
|
| +** Special case: If op==TK_INTEGER and pToken points to a string that
|
| +** can be translated into a 32-bit integer, then the token is not
|
| +** stored in u.zToken. Instead, the integer values is written
|
| +** into u.iValue and the EP_IntValue flag is set. No extra storage
|
| +** is allocated to hold the integer text and the dequote flag is ignored.
|
| +*/
|
| +SQLITE_PRIVATE Expr *sqlite3ExprAlloc(
|
| + sqlite3 *db, /* Handle for sqlite3DbMallocZero() (may be null) */
|
| + int op, /* Expression opcode */
|
| + const Token *pToken, /* Token argument. Might be NULL */
|
| + int dequote /* True to dequote */
|
| +){
|
| + Expr *pNew;
|
| + int nExtra = 0;
|
| + int iValue = 0;
|
| +
|
| + if( pToken ){
|
| + if( op!=TK_INTEGER || pToken->z==0
|
| + || sqlite3GetInt32(pToken->z, &iValue)==0 ){
|
| + nExtra = pToken->n+1;
|
| + assert( iValue>=0 );
|
| + }
|
| + }
|
| + pNew = sqlite3DbMallocZero(db, sizeof(Expr)+nExtra);
|
| + if( pNew ){
|
| + pNew->op = (u8)op;
|
| + pNew->iAgg = -1;
|
| + if( pToken ){
|
| + if( nExtra==0 ){
|
| + pNew->flags |= EP_IntValue;
|
| + pNew->u.iValue = iValue;
|
| + }else{
|
| + int c;
|
| + pNew->u.zToken = (char*)&pNew[1];
|
| + assert( pToken->z!=0 || pToken->n==0 );
|
| + if( pToken->n ) memcpy(pNew->u.zToken, pToken->z, pToken->n);
|
| + pNew->u.zToken[pToken->n] = 0;
|
| + if( dequote && nExtra>=3
|
| + && ((c = pToken->z[0])=='\'' || c=='"' || c=='[' || c=='`') ){
|
| + sqlite3Dequote(pNew->u.zToken);
|
| + if( c=='"' ) pNew->flags |= EP_DblQuoted;
|
| + }
|
| + }
|
| + }
|
| +#if SQLITE_MAX_EXPR_DEPTH>0
|
| + pNew->nHeight = 1;
|
| +#endif
|
| + }
|
| + return pNew;
|
| +}
|
| +
|
| +/*
|
| +** Allocate a new expression node from a zero-terminated token that has
|
| +** already been dequoted.
|
| +*/
|
| +SQLITE_PRIVATE Expr *sqlite3Expr(
|
| + sqlite3 *db, /* Handle for sqlite3DbMallocZero() (may be null) */
|
| + int op, /* Expression opcode */
|
| + const char *zToken /* Token argument. Might be NULL */
|
| +){
|
| + Token x;
|
| + x.z = zToken;
|
| + x.n = zToken ? sqlite3Strlen30(zToken) : 0;
|
| + return sqlite3ExprAlloc(db, op, &x, 0);
|
| +}
|
| +
|
| +/*
|
| +** Attach subtrees pLeft and pRight to the Expr node pRoot.
|
| +**
|
| +** If pRoot==NULL that means that a memory allocation error has occurred.
|
| +** In that case, delete the subtrees pLeft and pRight.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3ExprAttachSubtrees(
|
| + sqlite3 *db,
|
| + Expr *pRoot,
|
| + Expr *pLeft,
|
| + Expr *pRight
|
| +){
|
| + if( pRoot==0 ){
|
| + assert( db->mallocFailed );
|
| + sqlite3ExprDelete(db, pLeft);
|
| + sqlite3ExprDelete(db, pRight);
|
| + }else{
|
| + if( pRight ){
|
| + pRoot->pRight = pRight;
|
| + pRoot->flags |= EP_Propagate & pRight->flags;
|
| + }
|
| + if( pLeft ){
|
| + pRoot->pLeft = pLeft;
|
| + pRoot->flags |= EP_Propagate & pLeft->flags;
|
| + }
|
| + exprSetHeight(pRoot);
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Allocate an Expr node which joins as many as two subtrees.
|
| +**
|
| +** One or both of the subtrees can be NULL. Return a pointer to the new
|
| +** Expr node. Or, if an OOM error occurs, set pParse->db->mallocFailed,
|
| +** free the subtrees and return NULL.
|
| +*/
|
| +SQLITE_PRIVATE Expr *sqlite3PExpr(
|
| + Parse *pParse, /* Parsing context */
|
| + int op, /* Expression opcode */
|
| + Expr *pLeft, /* Left operand */
|
| + Expr *pRight, /* Right operand */
|
| + const Token *pToken /* Argument token */
|
| +){
|
| + Expr *p;
|
| + if( op==TK_AND && pParse->nErr==0 ){
|
| + /* Take advantage of short-circuit false optimization for AND */
|
| + p = sqlite3ExprAnd(pParse->db, pLeft, pRight);
|
| + }else{
|
| + p = sqlite3ExprAlloc(pParse->db, op & TKFLG_MASK, pToken, 1);
|
| + sqlite3ExprAttachSubtrees(pParse->db, p, pLeft, pRight);
|
| + }
|
| + if( p ) {
|
| + sqlite3ExprCheckHeight(pParse, p->nHeight);
|
| + }
|
| + return p;
|
| +}
|
| +
|
| +/*
|
| +** If the expression is always either TRUE or FALSE (respectively),
|
| +** then return 1. If one cannot determine the truth value of the
|
| +** expression at compile-time return 0.
|
| +**
|
| +** This is an optimization. If is OK to return 0 here even if
|
| +** the expression really is always false or false (a false negative).
|
| +** But it is a bug to return 1 if the expression might have different
|
| +** boolean values in different circumstances (a false positive.)
|
| +**
|
| +** Note that if the expression is part of conditional for a
|
| +** LEFT JOIN, then we cannot determine at compile-time whether or not
|
| +** is it true or false, so always return 0.
|
| +*/
|
| +static int exprAlwaysTrue(Expr *p){
|
| + int v = 0;
|
| + if( ExprHasProperty(p, EP_FromJoin) ) return 0;
|
| + if( !sqlite3ExprIsInteger(p, &v) ) return 0;
|
| + return v!=0;
|
| +}
|
| +static int exprAlwaysFalse(Expr *p){
|
| + int v = 0;
|
| + if( ExprHasProperty(p, EP_FromJoin) ) return 0;
|
| + if( !sqlite3ExprIsInteger(p, &v) ) return 0;
|
| + return v==0;
|
| +}
|
| +
|
| +/*
|
| +** Join two expressions using an AND operator. If either expression is
|
| +** NULL, then just return the other expression.
|
| +**
|
| +** If one side or the other of the AND is known to be false, then instead
|
| +** of returning an AND expression, just return a constant expression with
|
| +** a value of false.
|
| +*/
|
| +SQLITE_PRIVATE Expr *sqlite3ExprAnd(sqlite3 *db, Expr *pLeft, Expr *pRight){
|
| + if( pLeft==0 ){
|
| + return pRight;
|
| + }else if( pRight==0 ){
|
| + return pLeft;
|
| + }else if( exprAlwaysFalse(pLeft) || exprAlwaysFalse(pRight) ){
|
| + sqlite3ExprDelete(db, pLeft);
|
| + sqlite3ExprDelete(db, pRight);
|
| + return sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[0], 0);
|
| + }else{
|
| + Expr *pNew = sqlite3ExprAlloc(db, TK_AND, 0, 0);
|
| + sqlite3ExprAttachSubtrees(db, pNew, pLeft, pRight);
|
| + return pNew;
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Construct a new expression node for a function with multiple
|
| +** arguments.
|
| +*/
|
| +SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token *pToken){
|
| + Expr *pNew;
|
| + sqlite3 *db = pParse->db;
|
| + assert( pToken );
|
| + pNew = sqlite3ExprAlloc(db, TK_FUNCTION, pToken, 1);
|
| + if( pNew==0 ){
|
| + sqlite3ExprListDelete(db, pList); /* Avoid memory leak when malloc fails */
|
| + return 0;
|
| + }
|
| + pNew->x.pList = pList;
|
| + assert( !ExprHasProperty(pNew, EP_xIsSelect) );
|
| + sqlite3ExprSetHeightAndFlags(pParse, pNew);
|
| + return pNew;
|
| +}
|
| +
|
| +/*
|
| +** Assign a variable number to an expression that encodes a wildcard
|
| +** in the original SQL statement.
|
| +**
|
| +** Wildcards consisting of a single "?" are assigned the next sequential
|
| +** variable number.
|
| +**
|
| +** Wildcards of the form "?nnn" are assigned the number "nnn". We make
|
| +** sure "nnn" is not too be to avoid a denial of service attack when
|
| +** the SQL statement comes from an external source.
|
| +**
|
| +** Wildcards of the form ":aaa", "@aaa", or "$aaa" are assigned the same number
|
| +** as the previous instance of the same wildcard. Or if this is the first
|
| +** instance of the wildcard, the next sequential variable number is
|
| +** assigned.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
|
| + sqlite3 *db = pParse->db;
|
| + const char *z;
|
| +
|
| + if( pExpr==0 ) return;
|
| + assert( !ExprHasProperty(pExpr, EP_IntValue|EP_Reduced|EP_TokenOnly) );
|
| + z = pExpr->u.zToken;
|
| + assert( z!=0 );
|
| + assert( z[0]!=0 );
|
| + if( z[1]==0 ){
|
| + /* Wildcard of the form "?". Assign the next variable number */
|
| + assert( z[0]=='?' );
|
| + pExpr->iColumn = (ynVar)(++pParse->nVar);
|
| + }else{
|
| + ynVar x = 0;
|
| + u32 n = sqlite3Strlen30(z);
|
| + if( z[0]=='?' ){
|
| + /* Wildcard of the form "?nnn". Convert "nnn" to an integer and
|
| + ** use it as the variable number */
|
| + i64 i;
|
| + int bOk = 0==sqlite3Atoi64(&z[1], &i, n-1, SQLITE_UTF8);
|
| + pExpr->iColumn = x = (ynVar)i;
|
| + testcase( i==0 );
|
| + testcase( i==1 );
|
| + testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]-1 );
|
| + testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] );
|
| + if( bOk==0 || i<1 || i>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){
|
| + sqlite3ErrorMsg(pParse, "variable number must be between ?1 and ?%d",
|
| + db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]);
|
| + x = 0;
|
| + }
|
| + if( i>pParse->nVar ){
|
| + pParse->nVar = (int)i;
|
| + }
|
| + }else{
|
| + /* Wildcards like ":aaa", "$aaa" or "@aaa". Reuse the same variable
|
| + ** number as the prior appearance of the same name, or if the name
|
| + ** has never appeared before, reuse the same variable number
|
| + */
|
| + ynVar i;
|
| + for(i=0; i<pParse->nzVar; i++){
|
| + if( pParse->azVar[i] && strcmp(pParse->azVar[i],z)==0 ){
|
| + pExpr->iColumn = x = (ynVar)i+1;
|
| + break;
|
| + }
|
| + }
|
| + if( x==0 ) x = pExpr->iColumn = (ynVar)(++pParse->nVar);
|
| + }
|
| + if( x>0 ){
|
| + if( x>pParse->nzVar ){
|
| + char **a;
|
| + a = sqlite3DbRealloc(db, pParse->azVar, x*sizeof(a[0]));
|
| + if( a==0 ) return; /* Error reported through db->mallocFailed */
|
| + pParse->azVar = a;
|
| + memset(&a[pParse->nzVar], 0, (x-pParse->nzVar)*sizeof(a[0]));
|
| + pParse->nzVar = x;
|
| + }
|
| + if( z[0]!='?' || pParse->azVar[x-1]==0 ){
|
| + sqlite3DbFree(db, pParse->azVar[x-1]);
|
| + pParse->azVar[x-1] = sqlite3DbStrNDup(db, z, n);
|
| + }
|
| + }
|
| + }
|
| + if( !pParse->nErr && pParse->nVar>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){
|
| + sqlite3ErrorMsg(pParse, "too many SQL variables");
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Recursively delete an expression tree.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3 *db, Expr *p){
|
| + if( p==0 ) return;
|
| + /* Sanity check: Assert that the IntValue is non-negative if it exists */
|
| + assert( !ExprHasProperty(p, EP_IntValue) || p->u.iValue>=0 );
|
| + if( !ExprHasProperty(p, EP_TokenOnly) ){
|
| + /* The Expr.x union is never used at the same time as Expr.pRight */
|
| + assert( p->x.pList==0 || p->pRight==0 );
|
| + sqlite3ExprDelete(db, p->pLeft);
|
| + sqlite3ExprDelete(db, p->pRight);
|
| + if( ExprHasProperty(p, EP_MemToken) ) sqlite3DbFree(db, p->u.zToken);
|
| + if( ExprHasProperty(p, EP_xIsSelect) ){
|
| + sqlite3SelectDelete(db, p->x.pSelect);
|
| + }else{
|
| + sqlite3ExprListDelete(db, p->x.pList);
|
| + }
|
| + }
|
| + if( !ExprHasProperty(p, EP_Static) ){
|
| + sqlite3DbFree(db, p);
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Return the number of bytes allocated for the expression structure
|
| +** passed as the first argument. This is always one of EXPR_FULLSIZE,
|
| +** EXPR_REDUCEDSIZE or EXPR_TOKENONLYSIZE.
|
| +*/
|
| +static int exprStructSize(Expr *p){
|
| + if( ExprHasProperty(p, EP_TokenOnly) ) return EXPR_TOKENONLYSIZE;
|
| + if( ExprHasProperty(p, EP_Reduced) ) return EXPR_REDUCEDSIZE;
|
| + return EXPR_FULLSIZE;
|
| +}
|
| +
|
| +/*
|
| +** The dupedExpr*Size() routines each return the number of bytes required
|
| +** to store a copy of an expression or expression tree. They differ in
|
| +** how much of the tree is measured.
|
| +**
|
| +** dupedExprStructSize() Size of only the Expr structure
|
| +** dupedExprNodeSize() Size of Expr + space for token
|
| +** dupedExprSize() Expr + token + subtree components
|
| +**
|
| +***************************************************************************
|
| +**
|
| +** The dupedExprStructSize() function returns two values OR-ed together:
|
| +** (1) the space required for a copy of the Expr structure only and
|
| +** (2) the EP_xxx flags that indicate what the structure size should be.
|
| +** The return values is always one of:
|
| +**
|
| +** EXPR_FULLSIZE
|
| +** EXPR_REDUCEDSIZE | EP_Reduced
|
| +** EXPR_TOKENONLYSIZE | EP_TokenOnly
|
| +**
|
| +** The size of the structure can be found by masking the return value
|
| +** of this routine with 0xfff. The flags can be found by masking the
|
| +** return value with EP_Reduced|EP_TokenOnly.
|
| +**
|
| +** Note that with flags==EXPRDUP_REDUCE, this routines works on full-size
|
| +** (unreduced) Expr objects as they or originally constructed by the parser.
|
| +** During expression analysis, extra information is computed and moved into
|
| +** later parts of teh Expr object and that extra information might get chopped
|
| +** off if the expression is reduced. Note also that it does not work to
|
| +** make an EXPRDUP_REDUCE copy of a reduced expression. It is only legal
|
| +** to reduce a pristine expression tree from the parser. The implementation
|
| +** of dupedExprStructSize() contain multiple assert() statements that attempt
|
| +** to enforce this constraint.
|
| +*/
|
| +static int dupedExprStructSize(Expr *p, int flags){
|
| + int nSize;
|
| + assert( flags==EXPRDUP_REDUCE || flags==0 ); /* Only one flag value allowed */
|
| + assert( EXPR_FULLSIZE<=0xfff );
|
| + assert( (0xfff & (EP_Reduced|EP_TokenOnly))==0 );
|
| + if( 0==(flags&EXPRDUP_REDUCE) ){
|
| + nSize = EXPR_FULLSIZE;
|
| + }else{
|
| + assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
|
| + assert( !ExprHasProperty(p, EP_FromJoin) );
|
| + assert( !ExprHasProperty(p, EP_MemToken) );
|
| + assert( !ExprHasProperty(p, EP_NoReduce) );
|
| + if( p->pLeft || p->x.pList ){
|
| + nSize = EXPR_REDUCEDSIZE | EP_Reduced;
|
| + }else{
|
| + assert( p->pRight==0 );
|
| + nSize = EXPR_TOKENONLYSIZE | EP_TokenOnly;
|
| + }
|
| + }
|
| + return nSize;
|
| +}
|
| +
|
| +/*
|
| +** This function returns the space in bytes required to store the copy
|
| +** of the Expr structure and a copy of the Expr.u.zToken string (if that
|
| +** string is defined.)
|
| +*/
|
| +static int dupedExprNodeSize(Expr *p, int flags){
|
| + int nByte = dupedExprStructSize(p, flags) & 0xfff;
|
| + if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){
|
| + nByte += sqlite3Strlen30(p->u.zToken)+1;
|
| + }
|
| + return ROUND8(nByte);
|
| +}
|
| +
|
| +/*
|
| +** Return the number of bytes required to create a duplicate of the
|
| +** expression passed as the first argument. The second argument is a
|
| +** mask containing EXPRDUP_XXX flags.
|
| +**
|
| +** The value returned includes space to create a copy of the Expr struct
|
| +** itself and the buffer referred to by Expr.u.zToken, if any.
|
| +**
|
| +** If the EXPRDUP_REDUCE flag is set, then the return value includes
|
| +** space to duplicate all Expr nodes in the tree formed by Expr.pLeft
|
| +** and Expr.pRight variables (but not for any structures pointed to or
|
| +** descended from the Expr.x.pList or Expr.x.pSelect variables).
|
| +*/
|
| +static int dupedExprSize(Expr *p, int flags){
|
| + int nByte = 0;
|
| + if( p ){
|
| + nByte = dupedExprNodeSize(p, flags);
|
| + if( flags&EXPRDUP_REDUCE ){
|
| + nByte += dupedExprSize(p->pLeft, flags) + dupedExprSize(p->pRight, flags);
|
| + }
|
| + }
|
| + return nByte;
|
| +}
|
| +
|
| +/*
|
| +** This function is similar to sqlite3ExprDup(), except that if pzBuffer
|
| +** is not NULL then *pzBuffer is assumed to point to a buffer large enough
|
| +** to store the copy of expression p, the copies of p->u.zToken
|
| +** (if applicable), and the copies of the p->pLeft and p->pRight expressions,
|
| +** if any. Before returning, *pzBuffer is set to the first byte past the
|
| +** portion of the buffer copied into by this function.
|
| +*/
|
| +static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){
|
| + Expr *pNew = 0; /* Value to return */
|
| + assert( flags==0 || flags==EXPRDUP_REDUCE );
|
| + if( p ){
|
| + const int isReduced = (flags&EXPRDUP_REDUCE);
|
| + u8 *zAlloc;
|
| + u32 staticFlag = 0;
|
| +
|
| + assert( pzBuffer==0 || isReduced );
|
| +
|
| + /* Figure out where to write the new Expr structure. */
|
| + if( pzBuffer ){
|
| + zAlloc = *pzBuffer;
|
| + staticFlag = EP_Static;
|
| + }else{
|
| + zAlloc = sqlite3DbMallocRaw(db, dupedExprSize(p, flags));
|
| + }
|
| + pNew = (Expr *)zAlloc;
|
| +
|
| + if( pNew ){
|
| + /* Set nNewSize to the size allocated for the structure pointed to
|
| + ** by pNew. This is either EXPR_FULLSIZE, EXPR_REDUCEDSIZE or
|
| + ** EXPR_TOKENONLYSIZE. nToken is set to the number of bytes consumed
|
| + ** by the copy of the p->u.zToken string (if any).
|
| + */
|
| + const unsigned nStructSize = dupedExprStructSize(p, flags);
|
| + const int nNewSize = nStructSize & 0xfff;
|
| + int nToken;
|
| + if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){
|
| + nToken = sqlite3Strlen30(p->u.zToken) + 1;
|
| + }else{
|
| + nToken = 0;
|
| + }
|
| + if( isReduced ){
|
| + assert( ExprHasProperty(p, EP_Reduced)==0 );
|
| + memcpy(zAlloc, p, nNewSize);
|
| + }else{
|
| + u32 nSize = (u32)exprStructSize(p);
|
| + memcpy(zAlloc, p, nSize);
|
| + if( nSize<EXPR_FULLSIZE ){
|
| + memset(&zAlloc[nSize], 0, EXPR_FULLSIZE-nSize);
|
| + }
|
| + }
|
| +
|
| + /* Set the EP_Reduced, EP_TokenOnly, and EP_Static flags appropriately. */
|
| + pNew->flags &= ~(EP_Reduced|EP_TokenOnly|EP_Static|EP_MemToken);
|
| + pNew->flags |= nStructSize & (EP_Reduced|EP_TokenOnly);
|
| + pNew->flags |= staticFlag;
|
| +
|
| + /* Copy the p->u.zToken string, if any. */
|
| + if( nToken ){
|
| + char *zToken = pNew->u.zToken = (char*)&zAlloc[nNewSize];
|
| + memcpy(zToken, p->u.zToken, nToken);
|
| + }
|
| +
|
| + if( 0==((p->flags|pNew->flags) & EP_TokenOnly) ){
|
| + /* Fill in the pNew->x.pSelect or pNew->x.pList member. */
|
| + if( ExprHasProperty(p, EP_xIsSelect) ){
|
| + pNew->x.pSelect = sqlite3SelectDup(db, p->x.pSelect, isReduced);
|
| + }else{
|
| + pNew->x.pList = sqlite3ExprListDup(db, p->x.pList, isReduced);
|
| + }
|
| + }
|
| +
|
| + /* Fill in pNew->pLeft and pNew->pRight. */
|
| + if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly) ){
|
| + zAlloc += dupedExprNodeSize(p, flags);
|
| + if( ExprHasProperty(pNew, EP_Reduced) ){
|
| + pNew->pLeft = exprDup(db, p->pLeft, EXPRDUP_REDUCE, &zAlloc);
|
| + pNew->pRight = exprDup(db, p->pRight, EXPRDUP_REDUCE, &zAlloc);
|
| + }
|
| + if( pzBuffer ){
|
| + *pzBuffer = zAlloc;
|
| + }
|
| + }else{
|
| + if( !ExprHasProperty(p, EP_TokenOnly) ){
|
| + pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0);
|
| + pNew->pRight = sqlite3ExprDup(db, p->pRight, 0);
|
| + }
|
| + }
|
| +
|
| + }
|
| + }
|
| + return pNew;
|
| +}
|
| +
|
| +/*
|
| +** Create and return a deep copy of the object passed as the second
|
| +** argument. If an OOM condition is encountered, NULL is returned
|
| +** and the db->mallocFailed flag set.
|
| +*/
|
| +#ifndef SQLITE_OMIT_CTE
|
| +static With *withDup(sqlite3 *db, With *p){
|
| + With *pRet = 0;
|
| + if( p ){
|
| + int nByte = sizeof(*p) + sizeof(p->a[0]) * (p->nCte-1);
|
| + pRet = sqlite3DbMallocZero(db, nByte);
|
| + if( pRet ){
|
| + int i;
|
| + pRet->nCte = p->nCte;
|
| + for(i=0; i<p->nCte; i++){
|
| + pRet->a[i].pSelect = sqlite3SelectDup(db, p->a[i].pSelect, 0);
|
| + pRet->a[i].pCols = sqlite3ExprListDup(db, p->a[i].pCols, 0);
|
| + pRet->a[i].zName = sqlite3DbStrDup(db, p->a[i].zName);
|
| + }
|
| + }
|
| + }
|
| + return pRet;
|
| +}
|
| +#else
|
| +# define withDup(x,y) 0
|
| +#endif
|
| +
|
| +/*
|
| +** The following group of routines make deep copies of expressions,
|
| +** expression lists, ID lists, and select statements. The copies can
|
| +** be deleted (by being passed to their respective ...Delete() routines)
|
| +** without effecting the originals.
|
| +**
|
| +** The expression list, ID, and source lists return by sqlite3ExprListDup(),
|
| +** sqlite3IdListDup(), and sqlite3SrcListDup() can not be further expanded
|
| +** by subsequent calls to sqlite*ListAppend() routines.
|
| +**
|
| +** Any tables that the SrcList might point to are not duplicated.
|
| +**
|
| +** The flags parameter contains a combination of the EXPRDUP_XXX flags.
|
| +** If the EXPRDUP_REDUCE flag is set, then the structure returned is a
|
| +** truncated version of the usual Expr structure that will be stored as
|
| +** part of the in-memory representation of the database schema.
|
| +*/
|
| +SQLITE_PRIVATE Expr *sqlite3ExprDup(sqlite3 *db, Expr *p, int flags){
|
| + assert( flags==0 || flags==EXPRDUP_REDUCE );
|
| + return exprDup(db, p, flags, 0);
|
| +}
|
| +SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){
|
| + ExprList *pNew;
|
| + struct ExprList_item *pItem, *pOldItem;
|
| + int i;
|
| + if( p==0 ) return 0;
|
| + pNew = sqlite3DbMallocRaw(db, sizeof(*pNew) );
|
| + if( pNew==0 ) return 0;
|
| + pNew->nExpr = i = p->nExpr;
|
| + if( (flags & EXPRDUP_REDUCE)==0 ) for(i=1; i<p->nExpr; i+=i){}
|
| + pNew->a = pItem = sqlite3DbMallocRaw(db, i*sizeof(p->a[0]) );
|
| + if( pItem==0 ){
|
| + sqlite3DbFree(db, pNew);
|
| + return 0;
|
| + }
|
| + pOldItem = p->a;
|
| + for(i=0; i<p->nExpr; i++, pItem++, pOldItem++){
|
| + Expr *pOldExpr = pOldItem->pExpr;
|
| + pItem->pExpr = sqlite3ExprDup(db, pOldExpr, flags);
|
| + pItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
|
| + pItem->zSpan = sqlite3DbStrDup(db, pOldItem->zSpan);
|
| + pItem->sortOrder = pOldItem->sortOrder;
|
| + pItem->done = 0;
|
| + pItem->bSpanIsTab = pOldItem->bSpanIsTab;
|
| + pItem->u = pOldItem->u;
|
| + }
|
| + return pNew;
|
| +}
|
| +
|
| +/*
|
| +** If cursors, triggers, views and subqueries are all omitted from
|
| +** the build, then none of the following routines, except for
|
| +** sqlite3SelectDup(), can be called. sqlite3SelectDup() is sometimes
|
| +** called with a NULL argument.
|
| +*/
|
| +#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) \
|
| + || !defined(SQLITE_OMIT_SUBQUERY)
|
| +SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p, int flags){
|
| + SrcList *pNew;
|
| + int i;
|
| + int nByte;
|
| + if( p==0 ) return 0;
|
| + nByte = sizeof(*p) + (p->nSrc>0 ? sizeof(p->a[0]) * (p->nSrc-1) : 0);
|
| + pNew = sqlite3DbMallocRaw(db, nByte );
|
| + if( pNew==0 ) return 0;
|
| + pNew->nSrc = pNew->nAlloc = p->nSrc;
|
| + for(i=0; i<p->nSrc; i++){
|
| + struct SrcList_item *pNewItem = &pNew->a[i];
|
| + struct SrcList_item *pOldItem = &p->a[i];
|
| + Table *pTab;
|
| + pNewItem->pSchema = pOldItem->pSchema;
|
| + pNewItem->zDatabase = sqlite3DbStrDup(db, pOldItem->zDatabase);
|
| + pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
|
| + pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias);
|
| + pNewItem->fg = pOldItem->fg;
|
| + pNewItem->iCursor = pOldItem->iCursor;
|
| + pNewItem->addrFillSub = pOldItem->addrFillSub;
|
| + pNewItem->regReturn = pOldItem->regReturn;
|
| + if( pNewItem->fg.isIndexedBy ){
|
| + pNewItem->u1.zIndexedBy = sqlite3DbStrDup(db, pOldItem->u1.zIndexedBy);
|
| + }
|
| + pNewItem->pIBIndex = pOldItem->pIBIndex;
|
| + if( pNewItem->fg.isTabFunc ){
|
| + pNewItem->u1.pFuncArg =
|
| + sqlite3ExprListDup(db, pOldItem->u1.pFuncArg, flags);
|
| + }
|
| + pTab = pNewItem->pTab = pOldItem->pTab;
|
| + if( pTab ){
|
| + pTab->nRef++;
|
| + }
|
| + pNewItem->pSelect = sqlite3SelectDup(db, pOldItem->pSelect, flags);
|
| + pNewItem->pOn = sqlite3ExprDup(db, pOldItem->pOn, flags);
|
| + pNewItem->pUsing = sqlite3IdListDup(db, pOldItem->pUsing);
|
| + pNewItem->colUsed = pOldItem->colUsed;
|
| + }
|
| + return pNew;
|
| +}
|
| +SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3 *db, IdList *p){
|
| + IdList *pNew;
|
| + int i;
|
| + if( p==0 ) return 0;
|
| + pNew = sqlite3DbMallocRaw(db, sizeof(*pNew) );
|
| + if( pNew==0 ) return 0;
|
| + pNew->nId = p->nId;
|
| + pNew->a = sqlite3DbMallocRaw(db, p->nId*sizeof(p->a[0]) );
|
| + if( pNew->a==0 ){
|
| + sqlite3DbFree(db, pNew);
|
| + return 0;
|
| + }
|
| + /* Note that because the size of the allocation for p->a[] is not
|
| + ** necessarily a power of two, sqlite3IdListAppend() may not be called
|
| + ** on the duplicate created by this function. */
|
| + for(i=0; i<p->nId; i++){
|
| + struct IdList_item *pNewItem = &pNew->a[i];
|
| + struct IdList_item *pOldItem = &p->a[i];
|
| + pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
|
| + pNewItem->idx = pOldItem->idx;
|
| + }
|
| + return pNew;
|
| +}
|
| +SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){
|
| + Select *pNew, *pPrior;
|
| + if( p==0 ) return 0;
|
| + pNew = sqlite3DbMallocRaw(db, sizeof(*p) );
|
| + if( pNew==0 ) return 0;
|
| + pNew->pEList = sqlite3ExprListDup(db, p->pEList, flags);
|
| + pNew->pSrc = sqlite3SrcListDup(db, p->pSrc, flags);
|
| + pNew->pWhere = sqlite3ExprDup(db, p->pWhere, flags);
|
| + pNew->pGroupBy = sqlite3ExprListDup(db, p->pGroupBy, flags);
|
| + pNew->pHaving = sqlite3ExprDup(db, p->pHaving, flags);
|
| + pNew->pOrderBy = sqlite3ExprListDup(db, p->pOrderBy, flags);
|
| + pNew->op = p->op;
|
| + pNew->pPrior = pPrior = sqlite3SelectDup(db, p->pPrior, flags);
|
| + if( pPrior ) pPrior->pNext = pNew;
|
| + pNew->pNext = 0;
|
| + pNew->pLimit = sqlite3ExprDup(db, p->pLimit, flags);
|
| + pNew->pOffset = sqlite3ExprDup(db, p->pOffset, flags);
|
| + pNew->iLimit = 0;
|
| + pNew->iOffset = 0;
|
| + pNew->selFlags = p->selFlags & ~SF_UsesEphemeral;
|
| + pNew->addrOpenEphm[0] = -1;
|
| + pNew->addrOpenEphm[1] = -1;
|
| + pNew->nSelectRow = p->nSelectRow;
|
| + pNew->pWith = withDup(db, p->pWith);
|
| + sqlite3SelectSetName(pNew, p->zSelName);
|
| + return pNew;
|
| +}
|
| +#else
|
| +SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){
|
| + assert( p==0 );
|
| + return 0;
|
| +}
|
| +#endif
|
| +
|
| +
|
| +/*
|
| +** Add a new element to the end of an expression list. If pList is
|
| +** initially NULL, then create a new expression list.
|
| +**
|
| +** If a memory allocation error occurs, the entire list is freed and
|
| +** NULL is returned. If non-NULL is returned, then it is guaranteed
|
| +** that the new entry was successfully appended.
|
| +*/
|
| +SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(
|
| + Parse *pParse, /* Parsing context */
|
| + ExprList *pList, /* List to which to append. Might be NULL */
|
| + Expr *pExpr /* Expression to be appended. Might be NULL */
|
| +){
|
| + sqlite3 *db = pParse->db;
|
| + if( pList==0 ){
|
| + pList = sqlite3DbMallocZero(db, sizeof(ExprList) );
|
| + if( pList==0 ){
|
| + goto no_mem;
|
| + }
|
| + pList->a = sqlite3DbMallocRaw(db, sizeof(pList->a[0]));
|
| + if( pList->a==0 ) goto no_mem;
|
| + }else if( (pList->nExpr & (pList->nExpr-1))==0 ){
|
| + struct ExprList_item *a;
|
| + assert( pList->nExpr>0 );
|
| + a = sqlite3DbRealloc(db, pList->a, pList->nExpr*2*sizeof(pList->a[0]));
|
| + if( a==0 ){
|
| + goto no_mem;
|
| + }
|
| + pList->a = a;
|
| + }
|
| + assert( pList->a!=0 );
|
| + if( 1 ){
|
| + struct ExprList_item *pItem = &pList->a[pList->nExpr++];
|
| + memset(pItem, 0, sizeof(*pItem));
|
| + pItem->pExpr = pExpr;
|
| + }
|
| + return pList;
|
| +
|
| +no_mem:
|
| + /* Avoid leaking memory if malloc has failed. */
|
| + sqlite3ExprDelete(db, pExpr);
|
| + sqlite3ExprListDelete(db, pList);
|
| + return 0;
|
| +}
|
| +
|
| +/*
|
| +** Set the sort order for the last element on the given ExprList.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3ExprListSetSortOrder(ExprList *p, int iSortOrder){
|
| + if( p==0 ) return;
|
| + assert( SQLITE_SO_UNDEFINED<0 && SQLITE_SO_ASC>=0 && SQLITE_SO_DESC>0 );
|
| + assert( p->nExpr>0 );
|
| + if( iSortOrder<0 ){
|
| + assert( p->a[p->nExpr-1].sortOrder==SQLITE_SO_ASC );
|
| + return;
|
| + }
|
| + p->a[p->nExpr-1].sortOrder = (u8)iSortOrder;
|
| +}
|
| +
|
| +/*
|
| +** Set the ExprList.a[].zName element of the most recently added item
|
| +** on the expression list.
|
| +**
|
| +** pList might be NULL following an OOM error. But pName should never be
|
| +** NULL. If a memory allocation fails, the pParse->db->mallocFailed flag
|
| +** is set.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3ExprListSetName(
|
| + Parse *pParse, /* Parsing context */
|
| + ExprList *pList, /* List to which to add the span. */
|
| + Token *pName, /* Name to be added */
|
| + int dequote /* True to cause the name to be dequoted */
|
| +){
|
| + assert( pList!=0 || pParse->db->mallocFailed!=0 );
|
| + if( pList ){
|
| + struct ExprList_item *pItem;
|
| + assert( pList->nExpr>0 );
|
| + pItem = &pList->a[pList->nExpr-1];
|
| + assert( pItem->zName==0 );
|
| + pItem->zName = sqlite3DbStrNDup(pParse->db, pName->z, pName->n);
|
| + if( dequote && pItem->zName ) sqlite3Dequote(pItem->zName);
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Set the ExprList.a[].zSpan element of the most recently added item
|
| +** on the expression list.
|
| +**
|
| +** pList might be NULL following an OOM error. But pSpan should never be
|
| +** NULL. If a memory allocation fails, the pParse->db->mallocFailed flag
|
| +** is set.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3ExprListSetSpan(
|
| + Parse *pParse, /* Parsing context */
|
| + ExprList *pList, /* List to which to add the span. */
|
| + ExprSpan *pSpan /* The span to be added */
|
| +){
|
| + sqlite3 *db = pParse->db;
|
| + assert( pList!=0 || db->mallocFailed!=0 );
|
| + if( pList ){
|
| + struct ExprList_item *pItem = &pList->a[pList->nExpr-1];
|
| + assert( pList->nExpr>0 );
|
| + assert( db->mallocFailed || pItem->pExpr==pSpan->pExpr );
|
| + sqlite3DbFree(db, pItem->zSpan);
|
| + pItem->zSpan = sqlite3DbStrNDup(db, (char*)pSpan->zStart,
|
| + (int)(pSpan->zEnd - pSpan->zStart));
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** If the expression list pEList contains more than iLimit elements,
|
| +** leave an error message in pParse.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3ExprListCheckLength(
|
| + Parse *pParse,
|
| + ExprList *pEList,
|
| + const char *zObject
|
| +){
|
| + int mx = pParse->db->aLimit[SQLITE_LIMIT_COLUMN];
|
| + testcase( pEList && pEList->nExpr==mx );
|
| + testcase( pEList && pEList->nExpr==mx+1 );
|
| + if( pEList && pEList->nExpr>mx ){
|
| + sqlite3ErrorMsg(pParse, "too many columns in %s", zObject);
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Delete an entire expression list.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){
|
| + int i;
|
| + struct ExprList_item *pItem;
|
| + if( pList==0 ) return;
|
| + assert( pList->a!=0 || pList->nExpr==0 );
|
| + for(pItem=pList->a, i=0; i<pList->nExpr; i++, pItem++){
|
| + sqlite3ExprDelete(db, pItem->pExpr);
|
| + sqlite3DbFree(db, pItem->zName);
|
| + sqlite3DbFree(db, pItem->zSpan);
|
| + }
|
| + sqlite3DbFree(db, pList->a);
|
| + sqlite3DbFree(db, pList);
|
| +}
|
| +
|
| +/*
|
| +** Return the bitwise-OR of all Expr.flags fields in the given
|
| +** ExprList.
|
| +*/
|
| +SQLITE_PRIVATE u32 sqlite3ExprListFlags(const ExprList *pList){
|
| + int i;
|
| + u32 m = 0;
|
| + if( pList ){
|
| + for(i=0; i<pList->nExpr; i++){
|
| + Expr *pExpr = pList->a[i].pExpr;
|
| + if( ALWAYS(pExpr) ) m |= pExpr->flags;
|
| + }
|
| + }
|
| + return m;
|
| +}
|
| +
|
| +/*
|
| +** These routines are Walker callbacks used to check expressions to
|
| +** see if they are "constant" for some definition of constant. The
|
| +** Walker.eCode value determines the type of "constant" we are looking
|
| +** for.
|
| +**
|
| +** These callback routines are used to implement the following:
|
| +**
|
| +** sqlite3ExprIsConstant() pWalker->eCode==1
|
| +** sqlite3ExprIsConstantNotJoin() pWalker->eCode==2
|
| +** sqlite3ExprIsTableConstant() pWalker->eCode==3
|
| +** sqlite3ExprIsConstantOrFunction() pWalker->eCode==4 or 5
|
| +**
|
| +** In all cases, the callbacks set Walker.eCode=0 and abort if the expression
|
| +** is found to not be a constant.
|
| +**
|
| +** The sqlite3ExprIsConstantOrFunction() is used for evaluating expressions
|
| +** in a CREATE TABLE statement. The Walker.eCode value is 5 when parsing
|
| +** an existing schema and 4 when processing a new statement. A bound
|
| +** parameter raises an error for new statements, but is silently converted
|
| +** to NULL for existing schemas. This allows sqlite_master tables that
|
| +** contain a bound parameter because they were generated by older versions
|
| +** of SQLite to be parsed by newer versions of SQLite without raising a
|
| +** malformed schema error.
|
| +*/
|
| +static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
|
| +
|
| + /* If pWalker->eCode is 2 then any term of the expression that comes from
|
| + ** the ON or USING clauses of a left join disqualifies the expression
|
| + ** from being considered constant. */
|
| + if( pWalker->eCode==2 && ExprHasProperty(pExpr, EP_FromJoin) ){
|
| + pWalker->eCode = 0;
|
| + return WRC_Abort;
|
| + }
|
| +
|
| + switch( pExpr->op ){
|
| + /* Consider functions to be constant if all their arguments are constant
|
| + ** and either pWalker->eCode==4 or 5 or the function has the
|
| + ** SQLITE_FUNC_CONST flag. */
|
| + case TK_FUNCTION:
|
| + if( pWalker->eCode>=4 || ExprHasProperty(pExpr,EP_ConstFunc) ){
|
| + return WRC_Continue;
|
| + }else{
|
| + pWalker->eCode = 0;
|
| + return WRC_Abort;
|
| + }
|
| + case TK_ID:
|
| + case TK_COLUMN:
|
| + case TK_AGG_FUNCTION:
|
| + case TK_AGG_COLUMN:
|
| + testcase( pExpr->op==TK_ID );
|
| + testcase( pExpr->op==TK_COLUMN );
|
| + testcase( pExpr->op==TK_AGG_FUNCTION );
|
| + testcase( pExpr->op==TK_AGG_COLUMN );
|
| + if( pWalker->eCode==3 && pExpr->iTable==pWalker->u.iCur ){
|
| + return WRC_Continue;
|
| + }else{
|
| + pWalker->eCode = 0;
|
| + return WRC_Abort;
|
| + }
|
| + case TK_VARIABLE:
|
| + if( pWalker->eCode==5 ){
|
| + /* Silently convert bound parameters that appear inside of CREATE
|
| + ** statements into a NULL when parsing the CREATE statement text out
|
| + ** of the sqlite_master table */
|
| + pExpr->op = TK_NULL;
|
| + }else if( pWalker->eCode==4 ){
|
| + /* A bound parameter in a CREATE statement that originates from
|
| + ** sqlite3_prepare() causes an error */
|
| + pWalker->eCode = 0;
|
| + return WRC_Abort;
|
| + }
|
| + /* Fall through */
|
| + default:
|
| + testcase( pExpr->op==TK_SELECT ); /* selectNodeIsConstant will disallow */
|
| + testcase( pExpr->op==TK_EXISTS ); /* selectNodeIsConstant will disallow */
|
| + return WRC_Continue;
|
| + }
|
| +}
|
| +static int selectNodeIsConstant(Walker *pWalker, Select *NotUsed){
|
| + UNUSED_PARAMETER(NotUsed);
|
| + pWalker->eCode = 0;
|
| + return WRC_Abort;
|
| +}
|
| +static int exprIsConst(Expr *p, int initFlag, int iCur){
|
| + Walker w;
|
| + memset(&w, 0, sizeof(w));
|
| + w.eCode = initFlag;
|
| + w.xExprCallback = exprNodeIsConstant;
|
| + w.xSelectCallback = selectNodeIsConstant;
|
| + w.u.iCur = iCur;
|
| + sqlite3WalkExpr(&w, p);
|
| + return w.eCode;
|
| +}
|
| +
|
| +/*
|
| +** Walk an expression tree. Return non-zero if the expression is constant
|
| +** and 0 if it involves variables or function calls.
|
| +**
|
| +** For the purposes of this function, a double-quoted string (ex: "abc")
|
| +** is considered a variable but a single-quoted string (ex: 'abc') is
|
| +** a constant.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3ExprIsConstant(Expr *p){
|
| + return exprIsConst(p, 1, 0);
|
| +}
|
| +
|
| +/*
|
| +** Walk an expression tree. Return non-zero if the expression is constant
|
| +** that does no originate from the ON or USING clauses of a join.
|
| +** Return 0 if it involves variables or function calls or terms from
|
| +** an ON or USING clause.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr *p){
|
| + return exprIsConst(p, 2, 0);
|
| +}
|
| +
|
| +/*
|
| +** Walk an expression tree. Return non-zero if the expression is constant
|
| +** for any single row of the table with cursor iCur. In other words, the
|
| +** expression must not refer to any non-deterministic function nor any
|
| +** table other than iCur.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3ExprIsTableConstant(Expr *p, int iCur){
|
| + return exprIsConst(p, 3, iCur);
|
| +}
|
| +
|
| +/*
|
| +** Walk an expression tree. Return non-zero if the expression is constant
|
| +** or a function call with constant arguments. Return and 0 if there
|
| +** are any variables.
|
| +**
|
| +** For the purposes of this function, a double-quoted string (ex: "abc")
|
| +** is considered a variable but a single-quoted string (ex: 'abc') is
|
| +** a constant.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr *p, u8 isInit){
|
| + assert( isInit==0 || isInit==1 );
|
| + return exprIsConst(p, 4+isInit, 0);
|
| +}
|
| +
|
| +#ifdef SQLITE_ENABLE_CURSOR_HINTS
|
| +/*
|
| +** Walk an expression tree. Return 1 if the expression contains a
|
| +** subquery of some kind. Return 0 if there are no subqueries.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3ExprContainsSubquery(Expr *p){
|
| + Walker w;
|
| + memset(&w, 0, sizeof(w));
|
| + w.eCode = 1;
|
| + w.xExprCallback = sqlite3ExprWalkNoop;
|
| + w.xSelectCallback = selectNodeIsConstant;
|
| + sqlite3WalkExpr(&w, p);
|
| + return w.eCode==0;
|
| +}
|
| +#endif
|
| +
|
| +/*
|
| +** If the expression p codes a constant integer that is small enough
|
| +** to fit in a 32-bit integer, return 1 and put the value of the integer
|
| +** in *pValue. If the expression is not an integer or if it is too big
|
| +** to fit in a signed 32-bit integer, return 0 and leave *pValue unchanged.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3ExprIsInteger(Expr *p, int *pValue){
|
| + int rc = 0;
|
| +
|
| + /* If an expression is an integer literal that fits in a signed 32-bit
|
| + ** integer, then the EP_IntValue flag will have already been set */
|
| + assert( p->op!=TK_INTEGER || (p->flags & EP_IntValue)!=0
|
| + || sqlite3GetInt32(p->u.zToken, &rc)==0 );
|
| +
|
| + if( p->flags & EP_IntValue ){
|
| + *pValue = p->u.iValue;
|
| + return 1;
|
| + }
|
| + switch( p->op ){
|
| + case TK_UPLUS: {
|
| + rc = sqlite3ExprIsInteger(p->pLeft, pValue);
|
| + break;
|
| + }
|
| + case TK_UMINUS: {
|
| + int v;
|
| + if( sqlite3ExprIsInteger(p->pLeft, &v) ){
|
| + assert( v!=(-2147483647-1) );
|
| + *pValue = -v;
|
| + rc = 1;
|
| + }
|
| + break;
|
| + }
|
| + default: break;
|
| + }
|
| + return rc;
|
| +}
|
| +
|
| +/*
|
| +** Return FALSE if there is no chance that the expression can be NULL.
|
| +**
|
| +** If the expression might be NULL or if the expression is too complex
|
| +** to tell return TRUE.
|
| +**
|
| +** This routine is used as an optimization, to skip OP_IsNull opcodes
|
| +** when we know that a value cannot be NULL. Hence, a false positive
|
| +** (returning TRUE when in fact the expression can never be NULL) might
|
| +** be a small performance hit but is otherwise harmless. On the other
|
| +** hand, a false negative (returning FALSE when the result could be NULL)
|
| +** will likely result in an incorrect answer. So when in doubt, return
|
| +** TRUE.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr *p){
|
| + u8 op;
|
| + while( p->op==TK_UPLUS || p->op==TK_UMINUS ){ p = p->pLeft; }
|
| + op = p->op;
|
| + if( op==TK_REGISTER ) op = p->op2;
|
| + switch( op ){
|
| + case TK_INTEGER:
|
| + case TK_STRING:
|
| + case TK_FLOAT:
|
| + case TK_BLOB:
|
| + return 0;
|
| + case TK_COLUMN:
|
| + assert( p->pTab!=0 );
|
| + return ExprHasProperty(p, EP_CanBeNull) ||
|
| + (p->iColumn>=0 && p->pTab->aCol[p->iColumn].notNull==0);
|
| + default:
|
| + return 1;
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Return TRUE if the given expression is a constant which would be
|
| +** unchanged by OP_Affinity with the affinity given in the second
|
| +** argument.
|
| +**
|
| +** This routine is used to determine if the OP_Affinity operation
|
| +** can be omitted. When in doubt return FALSE. A false negative
|
| +** is harmless. A false positive, however, can result in the wrong
|
| +** answer.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr *p, char aff){
|
| + u8 op;
|
| + if( aff==SQLITE_AFF_BLOB ) return 1;
|
| + while( p->op==TK_UPLUS || p->op==TK_UMINUS ){ p = p->pLeft; }
|
| + op = p->op;
|
| + if( op==TK_REGISTER ) op = p->op2;
|
| + switch( op ){
|
| + case TK_INTEGER: {
|
| + return aff==SQLITE_AFF_INTEGER || aff==SQLITE_AFF_NUMERIC;
|
| + }
|
| + case TK_FLOAT: {
|
| + return aff==SQLITE_AFF_REAL || aff==SQLITE_AFF_NUMERIC;
|
| + }
|
| + case TK_STRING: {
|
| + return aff==SQLITE_AFF_TEXT;
|
| + }
|
| + case TK_BLOB: {
|
| + return 1;
|
| + }
|
| + case TK_COLUMN: {
|
| + assert( p->iTable>=0 ); /* p cannot be part of a CHECK constraint */
|
| + return p->iColumn<0
|
| + && (aff==SQLITE_AFF_INTEGER || aff==SQLITE_AFF_NUMERIC);
|
| + }
|
| + default: {
|
| + return 0;
|
| + }
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Return TRUE if the given string is a row-id column name.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3IsRowid(const char *z){
|
| + if( sqlite3StrICmp(z, "_ROWID_")==0 ) return 1;
|
| + if( sqlite3StrICmp(z, "ROWID")==0 ) return 1;
|
| + if( sqlite3StrICmp(z, "OID")==0 ) return 1;
|
| + return 0;
|
| +}
|
| +
|
| +/*
|
| +** Return true if we are able to the IN operator optimization on a
|
| +** query of the form
|
| +**
|
| +** x IN (SELECT ...)
|
| +**
|
| +** Where the SELECT... clause is as specified by the parameter to this
|
| +** routine.
|
| +**
|
| +** The Select object passed in has already been preprocessed and no
|
| +** errors have been found.
|
| +*/
|
| +#ifndef SQLITE_OMIT_SUBQUERY
|
| +static int isCandidateForInOpt(Select *p){
|
| + SrcList *pSrc;
|
| + ExprList *pEList;
|
| + Table *pTab;
|
| + if( p==0 ) return 0; /* right-hand side of IN is SELECT */
|
| + if( p->pPrior ) return 0; /* Not a compound SELECT */
|
| + if( p->selFlags & (SF_Distinct|SF_Aggregate) ){
|
| + testcase( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct );
|
| + testcase( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Aggregate );
|
| + return 0; /* No DISTINCT keyword and no aggregate functions */
|
| + }
|
| + assert( p->pGroupBy==0 ); /* Has no GROUP BY clause */
|
| + if( p->pLimit ) return 0; /* Has no LIMIT clause */
|
| + assert( p->pOffset==0 ); /* No LIMIT means no OFFSET */
|
| + if( p->pWhere ) return 0; /* Has no WHERE clause */
|
| + pSrc = p->pSrc;
|
| + assert( pSrc!=0 );
|
| + if( pSrc->nSrc!=1 ) return 0; /* Single term in FROM clause */
|
| + if( pSrc->a[0].pSelect ) return 0; /* FROM is not a subquery or view */
|
| + pTab = pSrc->a[0].pTab;
|
| + if( NEVER(pTab==0) ) return 0;
|
| + assert( pTab->pSelect==0 ); /* FROM clause is not a view */
|
| + if( IsVirtual(pTab) ) return 0; /* FROM clause not a virtual table */
|
| + pEList = p->pEList;
|
| + if( pEList->nExpr!=1 ) return 0; /* One column in the result set */
|
| + if( pEList->a[0].pExpr->op!=TK_COLUMN ) return 0; /* Result is a column */
|
| + return 1;
|
| +}
|
| +#endif /* SQLITE_OMIT_SUBQUERY */
|
| +
|
| +/*
|
| +** Code an OP_Once instruction and allocate space for its flag. Return the
|
| +** address of the new instruction.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3CodeOnce(Parse *pParse){
|
| + Vdbe *v = sqlite3GetVdbe(pParse); /* Virtual machine being coded */
|
| + return sqlite3VdbeAddOp1(v, OP_Once, pParse->nOnce++);
|
| +}
|
| +
|
| +/*
|
| +** Generate code that checks the left-most column of index table iCur to see if
|
| +** it contains any NULL entries. Cause the register at regHasNull to be set
|
| +** to a non-NULL value if iCur contains no NULLs. Cause register regHasNull
|
| +** to be set to NULL if iCur contains one or more NULL values.
|
| +*/
|
| +static void sqlite3SetHasNullFlag(Vdbe *v, int iCur, int regHasNull){
|
| + int addr1;
|
| + sqlite3VdbeAddOp2(v, OP_Integer, 0, regHasNull);
|
| + addr1 = sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v);
|
| + sqlite3VdbeAddOp3(v, OP_Column, iCur, 0, regHasNull);
|
| + sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
|
| + VdbeComment((v, "first_entry_in(%d)", iCur));
|
| + sqlite3VdbeJumpHere(v, addr1);
|
| +}
|
| +
|
| +
|
| +#ifndef SQLITE_OMIT_SUBQUERY
|
| +/*
|
| +** The argument is an IN operator with a list (not a subquery) on the
|
| +** right-hand side. Return TRUE if that list is constant.
|
| +*/
|
| +static int sqlite3InRhsIsConstant(Expr *pIn){
|
| + Expr *pLHS;
|
| + int res;
|
| + assert( !ExprHasProperty(pIn, EP_xIsSelect) );
|
| + pLHS = pIn->pLeft;
|
| + pIn->pLeft = 0;
|
| + res = sqlite3ExprIsConstant(pIn);
|
| + pIn->pLeft = pLHS;
|
| + return res;
|
| +}
|
| +#endif
|
| +
|
| +/*
|
| +** This function is used by the implementation of the IN (...) operator.
|
| +** The pX parameter is the expression on the RHS of the IN operator, which
|
| +** might be either a list of expressions or a subquery.
|
| +**
|
| +** The job of this routine is to find or create a b-tree object that can
|
| +** be used either to test for membership in the RHS set or to iterate through
|
| +** all members of the RHS set, skipping duplicates.
|
| +**
|
| +** A cursor is opened on the b-tree object that is the RHS of the IN operator
|
| +** and pX->iTable is set to the index of that cursor.
|
| +**
|
| +** The returned value of this function indicates the b-tree type, as follows:
|
| +**
|
| +** IN_INDEX_ROWID - The cursor was opened on a database table.
|
| +** IN_INDEX_INDEX_ASC - The cursor was opened on an ascending index.
|
| +** IN_INDEX_INDEX_DESC - The cursor was opened on a descending index.
|
| +** IN_INDEX_EPH - The cursor was opened on a specially created and
|
| +** populated epheremal table.
|
| +** IN_INDEX_NOOP - No cursor was allocated. The IN operator must be
|
| +** implemented as a sequence of comparisons.
|
| +**
|
| +** An existing b-tree might be used if the RHS expression pX is a simple
|
| +** subquery such as:
|
| +**
|
| +** SELECT <column> FROM <table>
|
| +**
|
| +** If the RHS of the IN operator is a list or a more complex subquery, then
|
| +** an ephemeral table might need to be generated from the RHS and then
|
| +** pX->iTable made to point to the ephemeral table instead of an
|
| +** existing table.
|
| +**
|
| +** The inFlags parameter must contain exactly one of the bits
|
| +** IN_INDEX_MEMBERSHIP or IN_INDEX_LOOP. If inFlags contains
|
| +** IN_INDEX_MEMBERSHIP, then the generated table will be used for a
|
| +** fast membership test. When the IN_INDEX_LOOP bit is set, the
|
| +** IN index will be used to loop over all values of the RHS of the
|
| +** IN operator.
|
| +**
|
| +** When IN_INDEX_LOOP is used (and the b-tree will be used to iterate
|
| +** through the set members) then the b-tree must not contain duplicates.
|
| +** An epheremal table must be used unless the selected <column> is guaranteed
|
| +** to be unique - either because it is an INTEGER PRIMARY KEY or it
|
| +** has a UNIQUE constraint or UNIQUE index.
|
| +**
|
| +** When IN_INDEX_MEMBERSHIP is used (and the b-tree will be used
|
| +** for fast set membership tests) then an epheremal table must
|
| +** be used unless <column> is an INTEGER PRIMARY KEY or an index can
|
| +** be found with <column> as its left-most column.
|
| +**
|
| +** If the IN_INDEX_NOOP_OK and IN_INDEX_MEMBERSHIP are both set and
|
| +** if the RHS of the IN operator is a list (not a subquery) then this
|
| +** routine might decide that creating an ephemeral b-tree for membership
|
| +** testing is too expensive and return IN_INDEX_NOOP. In that case, the
|
| +** calling routine should implement the IN operator using a sequence
|
| +** of Eq or Ne comparison operations.
|
| +**
|
| +** When the b-tree is being used for membership tests, the calling function
|
| +** might need to know whether or not the RHS side of the IN operator
|
| +** contains a NULL. If prRhsHasNull is not a NULL pointer and
|
| +** if there is any chance that the (...) might contain a NULL value at
|
| +** runtime, then a register is allocated and the register number written
|
| +** to *prRhsHasNull. If there is no chance that the (...) contains a
|
| +** NULL value, then *prRhsHasNull is left unchanged.
|
| +**
|
| +** If a register is allocated and its location stored in *prRhsHasNull, then
|
| +** the value in that register will be NULL if the b-tree contains one or more
|
| +** NULL values, and it will be some non-NULL value if the b-tree contains no
|
| +** NULL values.
|
| +*/
|
| +#ifndef SQLITE_OMIT_SUBQUERY
|
| +SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, u32 inFlags, int *prRhsHasNull){
|
| + Select *p; /* SELECT to the right of IN operator */
|
| + int eType = 0; /* Type of RHS table. IN_INDEX_* */
|
| + int iTab = pParse->nTab++; /* Cursor of the RHS table */
|
| + int mustBeUnique; /* True if RHS must be unique */
|
| + Vdbe *v = sqlite3GetVdbe(pParse); /* Virtual machine being coded */
|
| +
|
| + assert( pX->op==TK_IN );
|
| + mustBeUnique = (inFlags & IN_INDEX_LOOP)!=0;
|
| +
|
| + /* Check to see if an existing table or index can be used to
|
| + ** satisfy the query. This is preferable to generating a new
|
| + ** ephemeral table.
|
| + */
|
| + p = (ExprHasProperty(pX, EP_xIsSelect) ? pX->x.pSelect : 0);
|
| + if( pParse->nErr==0 && isCandidateForInOpt(p) ){
|
| + sqlite3 *db = pParse->db; /* Database connection */
|
| + Table *pTab; /* Table <table>. */
|
| + Expr *pExpr; /* Expression <column> */
|
| + i16 iCol; /* Index of column <column> */
|
| + i16 iDb; /* Database idx for pTab */
|
| +
|
| + assert( p ); /* Because of isCandidateForInOpt(p) */
|
| + assert( p->pEList!=0 ); /* Because of isCandidateForInOpt(p) */
|
| + assert( p->pEList->a[0].pExpr!=0 ); /* Because of isCandidateForInOpt(p) */
|
| + assert( p->pSrc!=0 ); /* Because of isCandidateForInOpt(p) */
|
| + pTab = p->pSrc->a[0].pTab;
|
| + pExpr = p->pEList->a[0].pExpr;
|
| + iCol = (i16)pExpr->iColumn;
|
| +
|
| + /* Code an OP_Transaction and OP_TableLock for <table>. */
|
| + iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
| + sqlite3CodeVerifySchema(pParse, iDb);
|
| + sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
|
| +
|
| + /* This function is only called from two places. In both cases the vdbe
|
| + ** has already been allocated. So assume sqlite3GetVdbe() is always
|
| + ** successful here.
|
| + */
|
| + assert(v);
|
| + if( iCol<0 ){
|
| + int iAddr = sqlite3CodeOnce(pParse);
|
| + VdbeCoverage(v);
|
| +
|
| + sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
|
| + eType = IN_INDEX_ROWID;
|
| +
|
| + sqlite3VdbeJumpHere(v, iAddr);
|
| + }else{
|
| + Index *pIdx; /* Iterator variable */
|
| +
|
| + /* The collation sequence used by the comparison. If an index is to
|
| + ** be used in place of a temp-table, it must be ordered according
|
| + ** to this collation sequence. */
|
| + CollSeq *pReq = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pExpr);
|
| +
|
| + /* Check that the affinity that will be used to perform the
|
| + ** comparison is the same as the affinity of the column. If
|
| + ** it is not, it is not possible to use any index.
|
| + */
|
| + int affinity_ok = sqlite3IndexAffinityOk(pX, pTab->aCol[iCol].affinity);
|
| +
|
| + for(pIdx=pTab->pIndex; pIdx && eType==0 && affinity_ok; pIdx=pIdx->pNext){
|
| + if( (pIdx->aiColumn[0]==iCol)
|
| + && sqlite3FindCollSeq(db, ENC(db), pIdx->azColl[0], 0)==pReq
|
| + && (!mustBeUnique || (pIdx->nKeyCol==1 && IsUniqueIndex(pIdx)))
|
| + ){
|
| + int iAddr = sqlite3CodeOnce(pParse); VdbeCoverage(v);
|
| + sqlite3VdbeAddOp3(v, OP_OpenRead, iTab, pIdx->tnum, iDb);
|
| + sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
|
| + VdbeComment((v, "%s", pIdx->zName));
|
| + assert( IN_INDEX_INDEX_DESC == IN_INDEX_INDEX_ASC+1 );
|
| + eType = IN_INDEX_INDEX_ASC + pIdx->aSortOrder[0];
|
| +
|
| + if( prRhsHasNull && !pTab->aCol[iCol].notNull ){
|
| + *prRhsHasNull = ++pParse->nMem;
|
| + sqlite3SetHasNullFlag(v, iTab, *prRhsHasNull);
|
| + }
|
| + sqlite3VdbeJumpHere(v, iAddr);
|
| + }
|
| + }
|
| + }
|
| + }
|
| +
|
| + /* If no preexisting index is available for the IN clause
|
| + ** and IN_INDEX_NOOP is an allowed reply
|
| + ** and the RHS of the IN operator is a list, not a subquery
|
| + ** and the RHS is not contant or has two or fewer terms,
|
| + ** then it is not worth creating an ephemeral table to evaluate
|
| + ** the IN operator so return IN_INDEX_NOOP.
|
| + */
|
| + if( eType==0
|
| + && (inFlags & IN_INDEX_NOOP_OK)
|
| + && !ExprHasProperty(pX, EP_xIsSelect)
|
| + && (!sqlite3InRhsIsConstant(pX) || pX->x.pList->nExpr<=2)
|
| + ){
|
| + eType = IN_INDEX_NOOP;
|
| + }
|
| +
|
| +
|
| + if( eType==0 ){
|
| + /* Could not find an existing table or index to use as the RHS b-tree.
|
| + ** We will have to generate an ephemeral table to do the job.
|
| + */
|
| + u32 savedNQueryLoop = pParse->nQueryLoop;
|
| + int rMayHaveNull = 0;
|
| + eType = IN_INDEX_EPH;
|
| + if( inFlags & IN_INDEX_LOOP ){
|
| + pParse->nQueryLoop = 0;
|
| + if( pX->pLeft->iColumn<0 && !ExprHasProperty(pX, EP_xIsSelect) ){
|
| + eType = IN_INDEX_ROWID;
|
| + }
|
| + }else if( prRhsHasNull ){
|
| + *prRhsHasNull = rMayHaveNull = ++pParse->nMem;
|
| + }
|
| + sqlite3CodeSubselect(pParse, pX, rMayHaveNull, eType==IN_INDEX_ROWID);
|
| + pParse->nQueryLoop = savedNQueryLoop;
|
| + }else{
|
| + pX->iTable = iTab;
|
| + }
|
| + return eType;
|
| +}
|
| +#endif
|
| +
|
| +/*
|
| +** Generate code for scalar subqueries used as a subquery expression, EXISTS,
|
| +** or IN operators. Examples:
|
| +**
|
| +** (SELECT a FROM b) -- subquery
|
| +** EXISTS (SELECT a FROM b) -- EXISTS subquery
|
| +** x IN (4,5,11) -- IN operator with list on right-hand side
|
| +** x IN (SELECT a FROM b) -- IN operator with subquery on the right
|
| +**
|
| +** The pExpr parameter describes the expression that contains the IN
|
| +** operator or subquery.
|
| +**
|
| +** If parameter isRowid is non-zero, then expression pExpr is guaranteed
|
| +** to be of the form "<rowid> IN (?, ?, ?)", where <rowid> is a reference
|
| +** to some integer key column of a table B-Tree. In this case, use an
|
| +** intkey B-Tree to store the set of IN(...) values instead of the usual
|
| +** (slower) variable length keys B-Tree.
|
| +**
|
| +** If rMayHaveNull is non-zero, that means that the operation is an IN
|
| +** (not a SELECT or EXISTS) and that the RHS might contains NULLs.
|
| +** All this routine does is initialize the register given by rMayHaveNull
|
| +** to NULL. Calling routines will take care of changing this register
|
| +** value to non-NULL if the RHS is NULL-free.
|
| +**
|
| +** For a SELECT or EXISTS operator, return the register that holds the
|
| +** result. For IN operators or if an error occurs, the return value is 0.
|
| +*/
|
| +#ifndef SQLITE_OMIT_SUBQUERY
|
| +SQLITE_PRIVATE int sqlite3CodeSubselect(
|
| + Parse *pParse, /* Parsing context */
|
| + Expr *pExpr, /* The IN, SELECT, or EXISTS operator */
|
| + int rHasNullFlag, /* Register that records whether NULLs exist in RHS */
|
| + int isRowid /* If true, LHS of IN operator is a rowid */
|
| +){
|
| + int jmpIfDynamic = -1; /* One-time test address */
|
| + int rReg = 0; /* Register storing resulting */
|
| + Vdbe *v = sqlite3GetVdbe(pParse);
|
| + if( NEVER(v==0) ) return 0;
|
| + sqlite3ExprCachePush(pParse);
|
| +
|
| + /* This code must be run in its entirety every time it is encountered
|
| + ** if any of the following is true:
|
| + **
|
| + ** * The right-hand side is a correlated subquery
|
| + ** * The right-hand side is an expression list containing variables
|
| + ** * We are inside a trigger
|
| + **
|
| + ** If all of the above are false, then we can run this code just once
|
| + ** save the results, and reuse the same result on subsequent invocations.
|
| + */
|
| + if( !ExprHasProperty(pExpr, EP_VarSelect) ){
|
| + jmpIfDynamic = sqlite3CodeOnce(pParse); VdbeCoverage(v);
|
| + }
|
| +
|
| +#ifndef SQLITE_OMIT_EXPLAIN
|
| + if( pParse->explain==2 ){
|
| + char *zMsg = sqlite3MPrintf(pParse->db, "EXECUTE %s%s SUBQUERY %d",
|
| + jmpIfDynamic>=0?"":"CORRELATED ",
|
| + pExpr->op==TK_IN?"LIST":"SCALAR",
|
| + pParse->iNextSelectId
|
| + );
|
| + sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC);
|
| + }
|
| +#endif
|
| +
|
| + switch( pExpr->op ){
|
| + case TK_IN: {
|
| + char affinity; /* Affinity of the LHS of the IN */
|
| + int addr; /* Address of OP_OpenEphemeral instruction */
|
| + Expr *pLeft = pExpr->pLeft; /* the LHS of the IN operator */
|
| + KeyInfo *pKeyInfo = 0; /* Key information */
|
| +
|
| + affinity = sqlite3ExprAffinity(pLeft);
|
| +
|
| + /* Whether this is an 'x IN(SELECT...)' or an 'x IN(<exprlist>)'
|
| + ** expression it is handled the same way. An ephemeral table is
|
| + ** filled with single-field index keys representing the results
|
| + ** from the SELECT or the <exprlist>.
|
| + **
|
| + ** If the 'x' expression is a column value, or the SELECT...
|
| + ** statement returns a column value, then the affinity of that
|
| + ** column is used to build the index keys. If both 'x' and the
|
| + ** SELECT... statement are columns, then numeric affinity is used
|
| + ** if either column has NUMERIC or INTEGER affinity. If neither
|
| + ** 'x' nor the SELECT... statement are columns, then numeric affinity
|
| + ** is used.
|
| + */
|
| + pExpr->iTable = pParse->nTab++;
|
| + addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pExpr->iTable, !isRowid);
|
| + pKeyInfo = isRowid ? 0 : sqlite3KeyInfoAlloc(pParse->db, 1, 1);
|
| +
|
| + if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
| + /* Case 1: expr IN (SELECT ...)
|
| + **
|
| + ** Generate code to write the results of the select into the temporary
|
| + ** table allocated and opened above.
|
| + */
|
| + Select *pSelect = pExpr->x.pSelect;
|
| + SelectDest dest;
|
| + ExprList *pEList;
|
| +
|
| + assert( !isRowid );
|
| + sqlite3SelectDestInit(&dest, SRT_Set, pExpr->iTable);
|
| + dest.affSdst = (u8)affinity;
|
| + assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable );
|
| + pSelect->iLimit = 0;
|
| + testcase( pSelect->selFlags & SF_Distinct );
|
| + testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */
|
| + if( sqlite3Select(pParse, pSelect, &dest) ){
|
| + sqlite3KeyInfoUnref(pKeyInfo);
|
| + return 0;
|
| + }
|
| + pEList = pSelect->pEList;
|
| + assert( pKeyInfo!=0 ); /* OOM will cause exit after sqlite3Select() */
|
| + assert( pEList!=0 );
|
| + assert( pEList->nExpr>0 );
|
| + assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
|
| + pKeyInfo->aColl[0] = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft,
|
| + pEList->a[0].pExpr);
|
| + }else if( ALWAYS(pExpr->x.pList!=0) ){
|
| + /* Case 2: expr IN (exprlist)
|
| + **
|
| + ** For each expression, build an index key from the evaluation and
|
| + ** store it in the temporary table. If <expr> is a column, then use
|
| + ** that columns affinity when building index keys. If <expr> is not
|
| + ** a column, use numeric affinity.
|
| + */
|
| + int i;
|
| + ExprList *pList = pExpr->x.pList;
|
| + struct ExprList_item *pItem;
|
| + int r1, r2, r3;
|
| +
|
| + if( !affinity ){
|
| + affinity = SQLITE_AFF_BLOB;
|
| + }
|
| + if( pKeyInfo ){
|
| + assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
|
| + pKeyInfo->aColl[0] = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
|
| + }
|
| +
|
| + /* Loop through each expression in <exprlist>. */
|
| + r1 = sqlite3GetTempReg(pParse);
|
| + r2 = sqlite3GetTempReg(pParse);
|
| + if( isRowid ) sqlite3VdbeAddOp2(v, OP_Null, 0, r2);
|
| + for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){
|
| + Expr *pE2 = pItem->pExpr;
|
| + int iValToIns;
|
| +
|
| + /* If the expression is not constant then we will need to
|
| + ** disable the test that was generated above that makes sure
|
| + ** this code only executes once. Because for a non-constant
|
| + ** expression we need to rerun this code each time.
|
| + */
|
| + if( jmpIfDynamic>=0 && !sqlite3ExprIsConstant(pE2) ){
|
| + sqlite3VdbeChangeToNoop(v, jmpIfDynamic);
|
| + jmpIfDynamic = -1;
|
| + }
|
| +
|
| + /* Evaluate the expression and insert it into the temp table */
|
| + if( isRowid && sqlite3ExprIsInteger(pE2, &iValToIns) ){
|
| + sqlite3VdbeAddOp3(v, OP_InsertInt, pExpr->iTable, r2, iValToIns);
|
| + }else{
|
| + r3 = sqlite3ExprCodeTarget(pParse, pE2, r1);
|
| + if( isRowid ){
|
| + sqlite3VdbeAddOp2(v, OP_MustBeInt, r3,
|
| + sqlite3VdbeCurrentAddr(v)+2);
|
| + VdbeCoverage(v);
|
| + sqlite3VdbeAddOp3(v, OP_Insert, pExpr->iTable, r2, r3);
|
| + }else{
|
| + sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1);
|
| + sqlite3ExprCacheAffinityChange(pParse, r3, 1);
|
| + sqlite3VdbeAddOp2(v, OP_IdxInsert, pExpr->iTable, r2);
|
| + }
|
| + }
|
| + }
|
| + sqlite3ReleaseTempReg(pParse, r1);
|
| + sqlite3ReleaseTempReg(pParse, r2);
|
| + }
|
| + if( pKeyInfo ){
|
| + sqlite3VdbeChangeP4(v, addr, (void *)pKeyInfo, P4_KEYINFO);
|
| + }
|
| + break;
|
| + }
|
| +
|
| + case TK_EXISTS:
|
| + case TK_SELECT:
|
| + default: {
|
| + /* If this has to be a scalar SELECT. Generate code to put the
|
| + ** value of this select in a memory cell and record the number
|
| + ** of the memory cell in iColumn. If this is an EXISTS, write
|
| + ** an integer 0 (not exists) or 1 (exists) into a memory cell
|
| + ** and record that memory cell in iColumn.
|
| + */
|
| + Select *pSel; /* SELECT statement to encode */
|
| + SelectDest dest; /* How to deal with SELECt result */
|
| +
|
| + testcase( pExpr->op==TK_EXISTS );
|
| + testcase( pExpr->op==TK_SELECT );
|
| + assert( pExpr->op==TK_EXISTS || pExpr->op==TK_SELECT );
|
| +
|
| + assert( ExprHasProperty(pExpr, EP_xIsSelect) );
|
| + pSel = pExpr->x.pSelect;
|
| + sqlite3SelectDestInit(&dest, 0, ++pParse->nMem);
|
| + if( pExpr->op==TK_SELECT ){
|
| + dest.eDest = SRT_Mem;
|
| + dest.iSdst = dest.iSDParm;
|
| + sqlite3VdbeAddOp2(v, OP_Null, 0, dest.iSDParm);
|
| + VdbeComment((v, "Init subquery result"));
|
| + }else{
|
| + dest.eDest = SRT_Exists;
|
| + sqlite3VdbeAddOp2(v, OP_Integer, 0, dest.iSDParm);
|
| + VdbeComment((v, "Init EXISTS result"));
|
| + }
|
| + sqlite3ExprDelete(pParse->db, pSel->pLimit);
|
| + pSel->pLimit = sqlite3PExpr(pParse, TK_INTEGER, 0, 0,
|
| + &sqlite3IntTokens[1]);
|
| + pSel->iLimit = 0;
|
| + pSel->selFlags &= ~SF_MultiValue;
|
| + if( sqlite3Select(pParse, pSel, &dest) ){
|
| + return 0;
|
| + }
|
| + rReg = dest.iSDParm;
|
| + ExprSetVVAProperty(pExpr, EP_NoReduce);
|
| + break;
|
| + }
|
| + }
|
| +
|
| + if( rHasNullFlag ){
|
| + sqlite3SetHasNullFlag(v, pExpr->iTable, rHasNullFlag);
|
| + }
|
| +
|
| + if( jmpIfDynamic>=0 ){
|
| + sqlite3VdbeJumpHere(v, jmpIfDynamic);
|
| + }
|
| + sqlite3ExprCachePop(pParse);
|
| +
|
| + return rReg;
|
| +}
|
| +#endif /* SQLITE_OMIT_SUBQUERY */
|
| +
|
| +#ifndef SQLITE_OMIT_SUBQUERY
|
| +/*
|
| +** Generate code for an IN expression.
|
| +**
|
| +** x IN (SELECT ...)
|
| +** x IN (value, value, ...)
|
| +**
|
| +** The left-hand side (LHS) is a scalar expression. The right-hand side (RHS)
|
| +** is an array of zero or more values. The expression is true if the LHS is
|
| +** contained within the RHS. The value of the expression is unknown (NULL)
|
| +** if the LHS is NULL or if the LHS is not contained within the RHS and the
|
| +** RHS contains one or more NULL values.
|
| +**
|
| +** This routine generates code that jumps to destIfFalse if the LHS is not
|
| +** contained within the RHS. If due to NULLs we cannot determine if the LHS
|
| +** is contained in the RHS then jump to destIfNull. If the LHS is contained
|
| +** within the RHS then fall through.
|
| +*/
|
| +static void sqlite3ExprCodeIN(
|
| + Parse *pParse, /* Parsing and code generating context */
|
| + Expr *pExpr, /* The IN expression */
|
| + int destIfFalse, /* Jump here if LHS is not contained in the RHS */
|
| + int destIfNull /* Jump here if the results are unknown due to NULLs */
|
| +){
|
| + int rRhsHasNull = 0; /* Register that is true if RHS contains NULL values */
|
| + char affinity; /* Comparison affinity to use */
|
| + int eType; /* Type of the RHS */
|
| + int r1; /* Temporary use register */
|
| + Vdbe *v; /* Statement under construction */
|
| +
|
| + /* Compute the RHS. After this step, the table with cursor
|
| + ** pExpr->iTable will contains the values that make up the RHS.
|
| + */
|
| + v = pParse->pVdbe;
|
| + assert( v!=0 ); /* OOM detected prior to this routine */
|
| + VdbeNoopComment((v, "begin IN expr"));
|
| + eType = sqlite3FindInIndex(pParse, pExpr,
|
| + IN_INDEX_MEMBERSHIP | IN_INDEX_NOOP_OK,
|
| + destIfFalse==destIfNull ? 0 : &rRhsHasNull);
|
| +
|
| + /* Figure out the affinity to use to create a key from the results
|
| + ** of the expression. affinityStr stores a static string suitable for
|
| + ** P4 of OP_MakeRecord.
|
| + */
|
| + affinity = comparisonAffinity(pExpr);
|
| +
|
| + /* Code the LHS, the <expr> from "<expr> IN (...)".
|
| + */
|
| + sqlite3ExprCachePush(pParse);
|
| + r1 = sqlite3GetTempReg(pParse);
|
| + sqlite3ExprCode(pParse, pExpr->pLeft, r1);
|
| +
|
| + /* If sqlite3FindInIndex() did not find or create an index that is
|
| + ** suitable for evaluating the IN operator, then evaluate using a
|
| + ** sequence of comparisons.
|
| + */
|
| + if( eType==IN_INDEX_NOOP ){
|
| + ExprList *pList = pExpr->x.pList;
|
| + CollSeq *pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
|
| + int labelOk = sqlite3VdbeMakeLabel(v);
|
| + int r2, regToFree;
|
| + int regCkNull = 0;
|
| + int ii;
|
| + assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
|
| + if( destIfNull!=destIfFalse ){
|
| + regCkNull = sqlite3GetTempReg(pParse);
|
| + sqlite3VdbeAddOp3(v, OP_BitAnd, r1, r1, regCkNull);
|
| + }
|
| + for(ii=0; ii<pList->nExpr; ii++){
|
| + r2 = sqlite3ExprCodeTemp(pParse, pList->a[ii].pExpr, ®ToFree);
|
| + if( regCkNull && sqlite3ExprCanBeNull(pList->a[ii].pExpr) ){
|
| + sqlite3VdbeAddOp3(v, OP_BitAnd, regCkNull, r2, regCkNull);
|
| + }
|
| + if( ii<pList->nExpr-1 || destIfNull!=destIfFalse ){
|
| + sqlite3VdbeAddOp4(v, OP_Eq, r1, labelOk, r2,
|
| + (void*)pColl, P4_COLLSEQ);
|
| + VdbeCoverageIf(v, ii<pList->nExpr-1);
|
| + VdbeCoverageIf(v, ii==pList->nExpr-1);
|
| + sqlite3VdbeChangeP5(v, affinity);
|
| + }else{
|
| + assert( destIfNull==destIfFalse );
|
| + sqlite3VdbeAddOp4(v, OP_Ne, r1, destIfFalse, r2,
|
| + (void*)pColl, P4_COLLSEQ); VdbeCoverage(v);
|
| + sqlite3VdbeChangeP5(v, affinity | SQLITE_JUMPIFNULL);
|
| + }
|
| + sqlite3ReleaseTempReg(pParse, regToFree);
|
| + }
|
| + if( regCkNull ){
|
| + sqlite3VdbeAddOp2(v, OP_IsNull, regCkNull, destIfNull); VdbeCoverage(v);
|
| + sqlite3VdbeGoto(v, destIfFalse);
|
| + }
|
| + sqlite3VdbeResolveLabel(v, labelOk);
|
| + sqlite3ReleaseTempReg(pParse, regCkNull);
|
| + }else{
|
| +
|
| + /* If the LHS is NULL, then the result is either false or NULL depending
|
| + ** on whether the RHS is empty or not, respectively.
|
| + */
|
| + if( sqlite3ExprCanBeNull(pExpr->pLeft) ){
|
| + if( destIfNull==destIfFalse ){
|
| + /* Shortcut for the common case where the false and NULL outcomes are
|
| + ** the same. */
|
| + sqlite3VdbeAddOp2(v, OP_IsNull, r1, destIfNull); VdbeCoverage(v);
|
| + }else{
|
| + int addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, r1); VdbeCoverage(v);
|
| + sqlite3VdbeAddOp2(v, OP_Rewind, pExpr->iTable, destIfFalse);
|
| + VdbeCoverage(v);
|
| + sqlite3VdbeGoto(v, destIfNull);
|
| + sqlite3VdbeJumpHere(v, addr1);
|
| + }
|
| + }
|
| +
|
| + if( eType==IN_INDEX_ROWID ){
|
| + /* In this case, the RHS is the ROWID of table b-tree
|
| + */
|
| + sqlite3VdbeAddOp2(v, OP_MustBeInt, r1, destIfFalse); VdbeCoverage(v);
|
| + sqlite3VdbeAddOp3(v, OP_NotExists, pExpr->iTable, destIfFalse, r1);
|
| + VdbeCoverage(v);
|
| + }else{
|
| + /* In this case, the RHS is an index b-tree.
|
| + */
|
| + sqlite3VdbeAddOp4(v, OP_Affinity, r1, 1, 0, &affinity, 1);
|
| +
|
| + /* If the set membership test fails, then the result of the
|
| + ** "x IN (...)" expression must be either 0 or NULL. If the set
|
| + ** contains no NULL values, then the result is 0. If the set
|
| + ** contains one or more NULL values, then the result of the
|
| + ** expression is also NULL.
|
| + */
|
| + assert( destIfFalse!=destIfNull || rRhsHasNull==0 );
|
| + if( rRhsHasNull==0 ){
|
| + /* This branch runs if it is known at compile time that the RHS
|
| + ** cannot contain NULL values. This happens as the result
|
| + ** of a "NOT NULL" constraint in the database schema.
|
| + **
|
| + ** Also run this branch if NULL is equivalent to FALSE
|
| + ** for this particular IN operator.
|
| + */
|
| + sqlite3VdbeAddOp4Int(v, OP_NotFound, pExpr->iTable, destIfFalse, r1, 1);
|
| + VdbeCoverage(v);
|
| + }else{
|
| + /* In this branch, the RHS of the IN might contain a NULL and
|
| + ** the presence of a NULL on the RHS makes a difference in the
|
| + ** outcome.
|
| + */
|
| + int addr1;
|
| +
|
| + /* First check to see if the LHS is contained in the RHS. If so,
|
| + ** then the answer is TRUE the presence of NULLs in the RHS does
|
| + ** not matter. If the LHS is not contained in the RHS, then the
|
| + ** answer is NULL if the RHS contains NULLs and the answer is
|
| + ** FALSE if the RHS is NULL-free.
|
| + */
|
| + addr1 = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, r1, 1);
|
| + VdbeCoverage(v);
|
| + sqlite3VdbeAddOp2(v, OP_IsNull, rRhsHasNull, destIfNull);
|
| + VdbeCoverage(v);
|
| + sqlite3VdbeGoto(v, destIfFalse);
|
| + sqlite3VdbeJumpHere(v, addr1);
|
| + }
|
| + }
|
| + }
|
| + sqlite3ReleaseTempReg(pParse, r1);
|
| + sqlite3ExprCachePop(pParse);
|
| + VdbeComment((v, "end IN expr"));
|
| +}
|
| +#endif /* SQLITE_OMIT_SUBQUERY */
|
| +
|
| +#ifndef SQLITE_OMIT_FLOATING_POINT
|
| +/*
|
| +** Generate an instruction that will put the floating point
|
| +** value described by z[0..n-1] into register iMem.
|
| +**
|
| +** The z[] string will probably not be zero-terminated. But the
|
| +** z[n] character is guaranteed to be something that does not look
|
| +** like the continuation of the number.
|
| +*/
|
| +static void codeReal(Vdbe *v, const char *z, int negateFlag, int iMem){
|
| + if( ALWAYS(z!=0) ){
|
| + double value;
|
| + sqlite3AtoF(z, &value, sqlite3Strlen30(z), SQLITE_UTF8);
|
| + assert( !sqlite3IsNaN(value) ); /* The new AtoF never returns NaN */
|
| + if( negateFlag ) value = -value;
|
| + sqlite3VdbeAddOp4Dup8(v, OP_Real, 0, iMem, 0, (u8*)&value, P4_REAL);
|
| + }
|
| +}
|
| +#endif
|
| +
|
| +
|
| +/*
|
| +** Generate an instruction that will put the integer describe by
|
| +** text z[0..n-1] into register iMem.
|
| +**
|
| +** Expr.u.zToken is always UTF8 and zero-terminated.
|
| +*/
|
| +static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){
|
| + Vdbe *v = pParse->pVdbe;
|
| + if( pExpr->flags & EP_IntValue ){
|
| + int i = pExpr->u.iValue;
|
| + assert( i>=0 );
|
| + if( negFlag ) i = -i;
|
| + sqlite3VdbeAddOp2(v, OP_Integer, i, iMem);
|
| + }else{
|
| + int c;
|
| + i64 value;
|
| + const char *z = pExpr->u.zToken;
|
| + assert( z!=0 );
|
| + c = sqlite3DecOrHexToI64(z, &value);
|
| + if( c==0 || (c==2 && negFlag) ){
|
| + if( negFlag ){ value = c==2 ? SMALLEST_INT64 : -value; }
|
| + sqlite3VdbeAddOp4Dup8(v, OP_Int64, 0, iMem, 0, (u8*)&value, P4_INT64);
|
| + }else{
|
| +#ifdef SQLITE_OMIT_FLOATING_POINT
|
| + sqlite3ErrorMsg(pParse, "oversized integer: %s%s", negFlag ? "-" : "", z);
|
| +#else
|
| +#ifndef SQLITE_OMIT_HEX_INTEGER
|
| + if( sqlite3_strnicmp(z,"0x",2)==0 ){
|
| + sqlite3ErrorMsg(pParse, "hex literal too big: %s", z);
|
| + }else
|
| +#endif
|
| + {
|
| + codeReal(v, z, negFlag, iMem);
|
| + }
|
| +#endif
|
| + }
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Clear a cache entry.
|
| +*/
|
| +static void cacheEntryClear(Parse *pParse, struct yColCache *p){
|
| + if( p->tempReg ){
|
| + if( pParse->nTempReg<ArraySize(pParse->aTempReg) ){
|
| + pParse->aTempReg[pParse->nTempReg++] = p->iReg;
|
| + }
|
| + p->tempReg = 0;
|
| + }
|
| +}
|
| +
|
| +
|
| +/*
|
| +** Record in the column cache that a particular column from a
|
| +** particular table is stored in a particular register.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){
|
| + int i;
|
| + int minLru;
|
| + int idxLru;
|
| + struct yColCache *p;
|
| +
|
| + /* Unless an error has occurred, register numbers are always positive. */
|
| + assert( iReg>0 || pParse->nErr || pParse->db->mallocFailed );
|
| + assert( iCol>=-1 && iCol<32768 ); /* Finite column numbers */
|
| +
|
| + /* The SQLITE_ColumnCache flag disables the column cache. This is used
|
| + ** for testing only - to verify that SQLite always gets the same answer
|
| + ** with and without the column cache.
|
| + */
|
| + if( OptimizationDisabled(pParse->db, SQLITE_ColumnCache) ) return;
|
| +
|
| + /* First replace any existing entry.
|
| + **
|
| + ** Actually, the way the column cache is currently used, we are guaranteed
|
| + ** that the object will never already be in cache. Verify this guarantee.
|
| + */
|
| +#ifndef NDEBUG
|
| + for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
|
| + assert( p->iReg==0 || p->iTable!=iTab || p->iColumn!=iCol );
|
| + }
|
| +#endif
|
| +
|
| + /* Find an empty slot and replace it */
|
| + for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
|
| + if( p->iReg==0 ){
|
| + p->iLevel = pParse->iCacheLevel;
|
| + p->iTable = iTab;
|
| + p->iColumn = iCol;
|
| + p->iReg = iReg;
|
| + p->tempReg = 0;
|
| + p->lru = pParse->iCacheCnt++;
|
| + return;
|
| + }
|
| + }
|
| +
|
| + /* Replace the last recently used */
|
| + minLru = 0x7fffffff;
|
| + idxLru = -1;
|
| + for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
|
| + if( p->lru<minLru ){
|
| + idxLru = i;
|
| + minLru = p->lru;
|
| + }
|
| + }
|
| + if( ALWAYS(idxLru>=0) ){
|
| + p = &pParse->aColCache[idxLru];
|
| + p->iLevel = pParse->iCacheLevel;
|
| + p->iTable = iTab;
|
| + p->iColumn = iCol;
|
| + p->iReg = iReg;
|
| + p->tempReg = 0;
|
| + p->lru = pParse->iCacheCnt++;
|
| + return;
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Indicate that registers between iReg..iReg+nReg-1 are being overwritten.
|
| +** Purge the range of registers from the column cache.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3ExprCacheRemove(Parse *pParse, int iReg, int nReg){
|
| + int i;
|
| + int iLast = iReg + nReg - 1;
|
| + struct yColCache *p;
|
| + for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
|
| + int r = p->iReg;
|
| + if( r>=iReg && r<=iLast ){
|
| + cacheEntryClear(pParse, p);
|
| + p->iReg = 0;
|
| + }
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Remember the current column cache context. Any new entries added
|
| +** added to the column cache after this call are removed when the
|
| +** corresponding pop occurs.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3ExprCachePush(Parse *pParse){
|
| + pParse->iCacheLevel++;
|
| +#ifdef SQLITE_DEBUG
|
| + if( pParse->db->flags & SQLITE_VdbeAddopTrace ){
|
| + printf("PUSH to %d\n", pParse->iCacheLevel);
|
| + }
|
| +#endif
|
| +}
|
| +
|
| +/*
|
| +** Remove from the column cache any entries that were added since the
|
| +** the previous sqlite3ExprCachePush operation. In other words, restore
|
| +** the cache to the state it was in prior the most recent Push.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3ExprCachePop(Parse *pParse){
|
| + int i;
|
| + struct yColCache *p;
|
| + assert( pParse->iCacheLevel>=1 );
|
| + pParse->iCacheLevel--;
|
| +#ifdef SQLITE_DEBUG
|
| + if( pParse->db->flags & SQLITE_VdbeAddopTrace ){
|
| + printf("POP to %d\n", pParse->iCacheLevel);
|
| + }
|
| +#endif
|
| + for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
|
| + if( p->iReg && p->iLevel>pParse->iCacheLevel ){
|
| + cacheEntryClear(pParse, p);
|
| + p->iReg = 0;
|
| + }
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** When a cached column is reused, make sure that its register is
|
| +** no longer available as a temp register. ticket #3879: that same
|
| +** register might be in the cache in multiple places, so be sure to
|
| +** get them all.
|
| +*/
|
| +static void sqlite3ExprCachePinRegister(Parse *pParse, int iReg){
|
| + int i;
|
| + struct yColCache *p;
|
| + for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
|
| + if( p->iReg==iReg ){
|
| + p->tempReg = 0;
|
| + }
|
| + }
|
| +}
|
| +
|
| +/* Generate code that will load into register regOut a value that is
|
| +** appropriate for the iIdxCol-th column of index pIdx.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3ExprCodeLoadIndexColumn(
|
| + Parse *pParse, /* The parsing context */
|
| + Index *pIdx, /* The index whose column is to be loaded */
|
| + int iTabCur, /* Cursor pointing to a table row */
|
| + int iIdxCol, /* The column of the index to be loaded */
|
| + int regOut /* Store the index column value in this register */
|
| +){
|
| + i16 iTabCol = pIdx->aiColumn[iIdxCol];
|
| + if( iTabCol==XN_EXPR ){
|
| + assert( pIdx->aColExpr );
|
| + assert( pIdx->aColExpr->nExpr>iIdxCol );
|
| + pParse->iSelfTab = iTabCur;
|
| + sqlite3ExprCodeCopy(pParse, pIdx->aColExpr->a[iIdxCol].pExpr, regOut);
|
| + }else{
|
| + sqlite3ExprCodeGetColumnOfTable(pParse->pVdbe, pIdx->pTable, iTabCur,
|
| + iTabCol, regOut);
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Generate code to extract the value of the iCol-th column of a table.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(
|
| + Vdbe *v, /* The VDBE under construction */
|
| + Table *pTab, /* The table containing the value */
|
| + int iTabCur, /* The table cursor. Or the PK cursor for WITHOUT ROWID */
|
| + int iCol, /* Index of the column to extract */
|
| + int regOut /* Extract the value into this register */
|
| +){
|
| + if( iCol<0 || iCol==pTab->iPKey ){
|
| + sqlite3VdbeAddOp2(v, OP_Rowid, iTabCur, regOut);
|
| + }else{
|
| + int op = IsVirtual(pTab) ? OP_VColumn : OP_Column;
|
| + int x = iCol;
|
| + if( !HasRowid(pTab) ){
|
| + x = sqlite3ColumnOfIndex(sqlite3PrimaryKeyIndex(pTab), iCol);
|
| + }
|
| + sqlite3VdbeAddOp3(v, op, iTabCur, x, regOut);
|
| + }
|
| + if( iCol>=0 ){
|
| + sqlite3ColumnDefault(v, pTab, iCol, regOut);
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Generate code that will extract the iColumn-th column from
|
| +** table pTab and store the column value in a register.
|
| +**
|
| +** An effort is made to store the column value in register iReg. This
|
| +** is not garanteeed for GetColumn() - the result can be stored in
|
| +** any register. But the result is guaranteed to land in register iReg
|
| +** for GetColumnToReg().
|
| +**
|
| +** There must be an open cursor to pTab in iTable when this routine
|
| +** is called. If iColumn<0 then code is generated that extracts the rowid.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(
|
| + Parse *pParse, /* Parsing and code generating context */
|
| + Table *pTab, /* Description of the table we are reading from */
|
| + int iColumn, /* Index of the table column */
|
| + int iTable, /* The cursor pointing to the table */
|
| + int iReg, /* Store results here */
|
| + u8 p5 /* P5 value for OP_Column + FLAGS */
|
| +){
|
| + Vdbe *v = pParse->pVdbe;
|
| + int i;
|
| + struct yColCache *p;
|
| +
|
| + for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
|
| + if( p->iReg>0 && p->iTable==iTable && p->iColumn==iColumn ){
|
| + p->lru = pParse->iCacheCnt++;
|
| + sqlite3ExprCachePinRegister(pParse, p->iReg);
|
| + return p->iReg;
|
| + }
|
| + }
|
| + assert( v!=0 );
|
| + sqlite3ExprCodeGetColumnOfTable(v, pTab, iTable, iColumn, iReg);
|
| + if( p5 ){
|
| + sqlite3VdbeChangeP5(v, p5);
|
| + }else{
|
| + sqlite3ExprCacheStore(pParse, iTable, iColumn, iReg);
|
| + }
|
| + return iReg;
|
| +}
|
| +SQLITE_PRIVATE void sqlite3ExprCodeGetColumnToReg(
|
| + Parse *pParse, /* Parsing and code generating context */
|
| + Table *pTab, /* Description of the table we are reading from */
|
| + int iColumn, /* Index of the table column */
|
| + int iTable, /* The cursor pointing to the table */
|
| + int iReg /* Store results here */
|
| +){
|
| + int r1 = sqlite3ExprCodeGetColumn(pParse, pTab, iColumn, iTable, iReg, 0);
|
| + if( r1!=iReg ) sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, r1, iReg);
|
| +}
|
| +
|
| +
|
| +/*
|
| +** Clear all column cache entries.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3ExprCacheClear(Parse *pParse){
|
| + int i;
|
| + struct yColCache *p;
|
| +
|
| +#if SQLITE_DEBUG
|
| + if( pParse->db->flags & SQLITE_VdbeAddopTrace ){
|
| + printf("CLEAR\n");
|
| + }
|
| +#endif
|
| + for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
|
| + if( p->iReg ){
|
| + cacheEntryClear(pParse, p);
|
| + p->iReg = 0;
|
| + }
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Record the fact that an affinity change has occurred on iCount
|
| +** registers starting with iStart.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3ExprCacheAffinityChange(Parse *pParse, int iStart, int iCount){
|
| + sqlite3ExprCacheRemove(pParse, iStart, iCount);
|
| +}
|
| +
|
| +/*
|
| +** Generate code to move content from registers iFrom...iFrom+nReg-1
|
| +** over to iTo..iTo+nReg-1. Keep the column cache up-to-date.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){
|
| + assert( iFrom>=iTo+nReg || iFrom+nReg<=iTo );
|
| + sqlite3VdbeAddOp3(pParse->pVdbe, OP_Move, iFrom, iTo, nReg);
|
| + sqlite3ExprCacheRemove(pParse, iFrom, nReg);
|
| +}
|
| +
|
| +#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
|
| +/*
|
| +** Return true if any register in the range iFrom..iTo (inclusive)
|
| +** is used as part of the column cache.
|
| +**
|
| +** This routine is used within assert() and testcase() macros only
|
| +** and does not appear in a normal build.
|
| +*/
|
| +static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){
|
| + int i;
|
| + struct yColCache *p;
|
| + for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
|
| + int r = p->iReg;
|
| + if( r>=iFrom && r<=iTo ) return 1; /*NO_TEST*/
|
| + }
|
| + return 0;
|
| +}
|
| +#endif /* SQLITE_DEBUG || SQLITE_COVERAGE_TEST */
|
| +
|
| +/*
|
| +** Convert an expression node to a TK_REGISTER
|
| +*/
|
| +static void exprToRegister(Expr *p, int iReg){
|
| + p->op2 = p->op;
|
| + p->op = TK_REGISTER;
|
| + p->iTable = iReg;
|
| + ExprClearProperty(p, EP_Skip);
|
| +}
|
| +
|
| +/*
|
| +** Generate code into the current Vdbe to evaluate the given
|
| +** expression. Attempt to store the results in register "target".
|
| +** Return the register where results are stored.
|
| +**
|
| +** With this routine, there is no guarantee that results will
|
| +** be stored in target. The result might be stored in some other
|
| +** register if it is convenient to do so. The calling function
|
| +** must check the return code and move the results to the desired
|
| +** register.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
| + Vdbe *v = pParse->pVdbe; /* The VM under construction */
|
| + int op; /* The opcode being coded */
|
| + int inReg = target; /* Results stored in register inReg */
|
| + int regFree1 = 0; /* If non-zero free this temporary register */
|
| + int regFree2 = 0; /* If non-zero free this temporary register */
|
| + int r1, r2, r3, r4; /* Various register numbers */
|
| + sqlite3 *db = pParse->db; /* The database connection */
|
| + Expr tempX; /* Temporary expression node */
|
| +
|
| + assert( target>0 && target<=pParse->nMem );
|
| + if( v==0 ){
|
| + assert( pParse->db->mallocFailed );
|
| + return 0;
|
| + }
|
| +
|
| + if( pExpr==0 ){
|
| + op = TK_NULL;
|
| + }else{
|
| + op = pExpr->op;
|
| + }
|
| + switch( op ){
|
| + case TK_AGG_COLUMN: {
|
| + AggInfo *pAggInfo = pExpr->pAggInfo;
|
| + struct AggInfo_col *pCol = &pAggInfo->aCol[pExpr->iAgg];
|
| + if( !pAggInfo->directMode ){
|
| + assert( pCol->iMem>0 );
|
| + inReg = pCol->iMem;
|
| + break;
|
| + }else if( pAggInfo->useSortingIdx ){
|
| + sqlite3VdbeAddOp3(v, OP_Column, pAggInfo->sortingIdxPTab,
|
| + pCol->iSorterColumn, target);
|
| + break;
|
| + }
|
| + /* Otherwise, fall thru into the TK_COLUMN case */
|
| + }
|
| + case TK_COLUMN: {
|
| + int iTab = pExpr->iTable;
|
| + if( iTab<0 ){
|
| + if( pParse->ckBase>0 ){
|
| + /* Generating CHECK constraints or inserting into partial index */
|
| + inReg = pExpr->iColumn + pParse->ckBase;
|
| + break;
|
| + }else{
|
| + /* Coding an expression that is part of an index where column names
|
| + ** in the index refer to the table to which the index belongs */
|
| + iTab = pParse->iSelfTab;
|
| + }
|
| + }
|
| + inReg = sqlite3ExprCodeGetColumn(pParse, pExpr->pTab,
|
| + pExpr->iColumn, iTab, target,
|
| + pExpr->op2);
|
| + break;
|
| + }
|
| + case TK_INTEGER: {
|
| + codeInteger(pParse, pExpr, 0, target);
|
| + break;
|
| + }
|
| +#ifndef SQLITE_OMIT_FLOATING_POINT
|
| + case TK_FLOAT: {
|
| + assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
| + codeReal(v, pExpr->u.zToken, 0, target);
|
| + break;
|
| + }
|
| +#endif
|
| + case TK_STRING: {
|
| + assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
| + sqlite3VdbeLoadString(v, target, pExpr->u.zToken);
|
| + break;
|
| + }
|
| + case TK_NULL: {
|
| + sqlite3VdbeAddOp2(v, OP_Null, 0, target);
|
| + break;
|
| + }
|
| +#ifndef SQLITE_OMIT_BLOB_LITERAL
|
| + case TK_BLOB: {
|
| + int n;
|
| + const char *z;
|
| + char *zBlob;
|
| + assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
| + assert( pExpr->u.zToken[0]=='x' || pExpr->u.zToken[0]=='X' );
|
| + assert( pExpr->u.zToken[1]=='\'' );
|
| + z = &pExpr->u.zToken[2];
|
| + n = sqlite3Strlen30(z) - 1;
|
| + assert( z[n]=='\'' );
|
| + zBlob = sqlite3HexToBlob(sqlite3VdbeDb(v), z, n);
|
| + sqlite3VdbeAddOp4(v, OP_Blob, n/2, target, 0, zBlob, P4_DYNAMIC);
|
| + break;
|
| + }
|
| +#endif
|
| + case TK_VARIABLE: {
|
| + assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
| + assert( pExpr->u.zToken!=0 );
|
| + assert( pExpr->u.zToken[0]!=0 );
|
| + sqlite3VdbeAddOp2(v, OP_Variable, pExpr->iColumn, target);
|
| + if( pExpr->u.zToken[1]!=0 ){
|
| + assert( pExpr->u.zToken[0]=='?'
|
| + || strcmp(pExpr->u.zToken, pParse->azVar[pExpr->iColumn-1])==0 );
|
| + sqlite3VdbeChangeP4(v, -1, pParse->azVar[pExpr->iColumn-1], P4_STATIC);
|
| + }
|
| + break;
|
| + }
|
| + case TK_REGISTER: {
|
| + inReg = pExpr->iTable;
|
| + break;
|
| + }
|
| +#ifndef SQLITE_OMIT_CAST
|
| + case TK_CAST: {
|
| + /* Expressions of the form: CAST(pLeft AS token) */
|
| + inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
|
| + if( inReg!=target ){
|
| + sqlite3VdbeAddOp2(v, OP_SCopy, inReg, target);
|
| + inReg = target;
|
| + }
|
| + sqlite3VdbeAddOp2(v, OP_Cast, target,
|
| + sqlite3AffinityType(pExpr->u.zToken, 0));
|
| + testcase( usedAsColumnCache(pParse, inReg, inReg) );
|
| + sqlite3ExprCacheAffinityChange(pParse, inReg, 1);
|
| + break;
|
| + }
|
| +#endif /* SQLITE_OMIT_CAST */
|
| + case TK_LT:
|
| + case TK_LE:
|
| + case TK_GT:
|
| + case TK_GE:
|
| + case TK_NE:
|
| + case TK_EQ: {
|
| + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
| + r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
| + codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
|
| + r1, r2, inReg, SQLITE_STOREP2);
|
| + assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
|
| + assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
|
| + assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt);
|
| + assert(TK_GE==OP_Ge); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge);
|
| + assert(TK_EQ==OP_Eq); testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq);
|
| + assert(TK_NE==OP_Ne); testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne);
|
| + testcase( regFree1==0 );
|
| + testcase( regFree2==0 );
|
| + break;
|
| + }
|
| + case TK_IS:
|
| + case TK_ISNOT: {
|
| + testcase( op==TK_IS );
|
| + testcase( op==TK_ISNOT );
|
| + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
| + r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
| + op = (op==TK_IS) ? TK_EQ : TK_NE;
|
| + codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
|
| + r1, r2, inReg, SQLITE_STOREP2 | SQLITE_NULLEQ);
|
| + VdbeCoverageIf(v, op==TK_EQ);
|
| + VdbeCoverageIf(v, op==TK_NE);
|
| + testcase( regFree1==0 );
|
| + testcase( regFree2==0 );
|
| + break;
|
| + }
|
| + case TK_AND:
|
| + case TK_OR:
|
| + case TK_PLUS:
|
| + case TK_STAR:
|
| + case TK_MINUS:
|
| + case TK_REM:
|
| + case TK_BITAND:
|
| + case TK_BITOR:
|
| + case TK_SLASH:
|
| + case TK_LSHIFT:
|
| + case TK_RSHIFT:
|
| + case TK_CONCAT: {
|
| + assert( TK_AND==OP_And ); testcase( op==TK_AND );
|
| + assert( TK_OR==OP_Or ); testcase( op==TK_OR );
|
| + assert( TK_PLUS==OP_Add ); testcase( op==TK_PLUS );
|
| + assert( TK_MINUS==OP_Subtract ); testcase( op==TK_MINUS );
|
| + assert( TK_REM==OP_Remainder ); testcase( op==TK_REM );
|
| + assert( TK_BITAND==OP_BitAnd ); testcase( op==TK_BITAND );
|
| + assert( TK_BITOR==OP_BitOr ); testcase( op==TK_BITOR );
|
| + assert( TK_SLASH==OP_Divide ); testcase( op==TK_SLASH );
|
| + assert( TK_LSHIFT==OP_ShiftLeft ); testcase( op==TK_LSHIFT );
|
| + assert( TK_RSHIFT==OP_ShiftRight ); testcase( op==TK_RSHIFT );
|
| + assert( TK_CONCAT==OP_Concat ); testcase( op==TK_CONCAT );
|
| + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
| + r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
| + sqlite3VdbeAddOp3(v, op, r2, r1, target);
|
| + testcase( regFree1==0 );
|
| + testcase( regFree2==0 );
|
| + break;
|
| + }
|
| + case TK_UMINUS: {
|
| + Expr *pLeft = pExpr->pLeft;
|
| + assert( pLeft );
|
| + if( pLeft->op==TK_INTEGER ){
|
| + codeInteger(pParse, pLeft, 1, target);
|
| +#ifndef SQLITE_OMIT_FLOATING_POINT
|
| + }else if( pLeft->op==TK_FLOAT ){
|
| + assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
| + codeReal(v, pLeft->u.zToken, 1, target);
|
| +#endif
|
| + }else{
|
| + tempX.op = TK_INTEGER;
|
| + tempX.flags = EP_IntValue|EP_TokenOnly;
|
| + tempX.u.iValue = 0;
|
| + r1 = sqlite3ExprCodeTemp(pParse, &tempX, ®Free1);
|
| + r2 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free2);
|
| + sqlite3VdbeAddOp3(v, OP_Subtract, r2, r1, target);
|
| + testcase( regFree2==0 );
|
| + }
|
| + inReg = target;
|
| + break;
|
| + }
|
| + case TK_BITNOT:
|
| + case TK_NOT: {
|
| + assert( TK_BITNOT==OP_BitNot ); testcase( op==TK_BITNOT );
|
| + assert( TK_NOT==OP_Not ); testcase( op==TK_NOT );
|
| + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
| + testcase( regFree1==0 );
|
| + inReg = target;
|
| + sqlite3VdbeAddOp2(v, op, r1, inReg);
|
| + break;
|
| + }
|
| + case TK_ISNULL:
|
| + case TK_NOTNULL: {
|
| + int addr;
|
| + assert( TK_ISNULL==OP_IsNull ); testcase( op==TK_ISNULL );
|
| + assert( TK_NOTNULL==OP_NotNull ); testcase( op==TK_NOTNULL );
|
| + sqlite3VdbeAddOp2(v, OP_Integer, 1, target);
|
| + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
| + testcase( regFree1==0 );
|
| + addr = sqlite3VdbeAddOp1(v, op, r1);
|
| + VdbeCoverageIf(v, op==TK_ISNULL);
|
| + VdbeCoverageIf(v, op==TK_NOTNULL);
|
| + sqlite3VdbeAddOp2(v, OP_Integer, 0, target);
|
| + sqlite3VdbeJumpHere(v, addr);
|
| + break;
|
| + }
|
| + case TK_AGG_FUNCTION: {
|
| + AggInfo *pInfo = pExpr->pAggInfo;
|
| + if( pInfo==0 ){
|
| + assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
| + sqlite3ErrorMsg(pParse, "misuse of aggregate: %s()", pExpr->u.zToken);
|
| + }else{
|
| + inReg = pInfo->aFunc[pExpr->iAgg].iMem;
|
| + }
|
| + break;
|
| + }
|
| + case TK_FUNCTION: {
|
| + ExprList *pFarg; /* List of function arguments */
|
| + int nFarg; /* Number of function arguments */
|
| + FuncDef *pDef; /* The function definition object */
|
| + int nId; /* Length of the function name in bytes */
|
| + const char *zId; /* The function name */
|
| + u32 constMask = 0; /* Mask of function arguments that are constant */
|
| + int i; /* Loop counter */
|
| + u8 enc = ENC(db); /* The text encoding used by this database */
|
| + CollSeq *pColl = 0; /* A collating sequence */
|
| +
|
| + assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
|
| + if( ExprHasProperty(pExpr, EP_TokenOnly) ){
|
| + pFarg = 0;
|
| + }else{
|
| + pFarg = pExpr->x.pList;
|
| + }
|
| + nFarg = pFarg ? pFarg->nExpr : 0;
|
| + assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
| + zId = pExpr->u.zToken;
|
| + nId = sqlite3Strlen30(zId);
|
| + pDef = sqlite3FindFunction(db, zId, nId, nFarg, enc, 0);
|
| + if( pDef==0 || pDef->xFunc==0 ){
|
| + sqlite3ErrorMsg(pParse, "unknown function: %.*s()", nId, zId);
|
| + break;
|
| + }
|
| +
|
| + /* Attempt a direct implementation of the built-in COALESCE() and
|
| + ** IFNULL() functions. This avoids unnecessary evaluation of
|
| + ** arguments past the first non-NULL argument.
|
| + */
|
| + if( pDef->funcFlags & SQLITE_FUNC_COALESCE ){
|
| + int endCoalesce = sqlite3VdbeMakeLabel(v);
|
| + assert( nFarg>=2 );
|
| + sqlite3ExprCode(pParse, pFarg->a[0].pExpr, target);
|
| + for(i=1; i<nFarg; i++){
|
| + sqlite3VdbeAddOp2(v, OP_NotNull, target, endCoalesce);
|
| + VdbeCoverage(v);
|
| + sqlite3ExprCacheRemove(pParse, target, 1);
|
| + sqlite3ExprCachePush(pParse);
|
| + sqlite3ExprCode(pParse, pFarg->a[i].pExpr, target);
|
| + sqlite3ExprCachePop(pParse);
|
| + }
|
| + sqlite3VdbeResolveLabel(v, endCoalesce);
|
| + break;
|
| + }
|
| +
|
| + /* The UNLIKELY() function is a no-op. The result is the value
|
| + ** of the first argument.
|
| + */
|
| + if( pDef->funcFlags & SQLITE_FUNC_UNLIKELY ){
|
| + assert( nFarg>=1 );
|
| + inReg = sqlite3ExprCodeTarget(pParse, pFarg->a[0].pExpr, target);
|
| + break;
|
| + }
|
| +
|
| + for(i=0; i<nFarg; i++){
|
| + if( i<32 && sqlite3ExprIsConstant(pFarg->a[i].pExpr) ){
|
| + testcase( i==31 );
|
| + constMask |= MASKBIT32(i);
|
| + }
|
| + if( (pDef->funcFlags & SQLITE_FUNC_NEEDCOLL)!=0 && !pColl ){
|
| + pColl = sqlite3ExprCollSeq(pParse, pFarg->a[i].pExpr);
|
| + }
|
| + }
|
| + if( pFarg ){
|
| + if( constMask ){
|
| + r1 = pParse->nMem+1;
|
| + pParse->nMem += nFarg;
|
| + }else{
|
| + r1 = sqlite3GetTempRange(pParse, nFarg);
|
| + }
|
| +
|
| + /* For length() and typeof() functions with a column argument,
|
| + ** set the P5 parameter to the OP_Column opcode to OPFLAG_LENGTHARG
|
| + ** or OPFLAG_TYPEOFARG respectively, to avoid unnecessary data
|
| + ** loading.
|
| + */
|
| + if( (pDef->funcFlags & (SQLITE_FUNC_LENGTH|SQLITE_FUNC_TYPEOF))!=0 ){
|
| + u8 exprOp;
|
| + assert( nFarg==1 );
|
| + assert( pFarg->a[0].pExpr!=0 );
|
| + exprOp = pFarg->a[0].pExpr->op;
|
| + if( exprOp==TK_COLUMN || exprOp==TK_AGG_COLUMN ){
|
| + assert( SQLITE_FUNC_LENGTH==OPFLAG_LENGTHARG );
|
| + assert( SQLITE_FUNC_TYPEOF==OPFLAG_TYPEOFARG );
|
| + testcase( pDef->funcFlags & OPFLAG_LENGTHARG );
|
| + pFarg->a[0].pExpr->op2 =
|
| + pDef->funcFlags & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG);
|
| + }
|
| + }
|
| +
|
| + sqlite3ExprCachePush(pParse); /* Ticket 2ea2425d34be */
|
| + sqlite3ExprCodeExprList(pParse, pFarg, r1, 0,
|
| + SQLITE_ECEL_DUP|SQLITE_ECEL_FACTOR);
|
| + sqlite3ExprCachePop(pParse); /* Ticket 2ea2425d34be */
|
| + }else{
|
| + r1 = 0;
|
| + }
|
| +#ifndef SQLITE_OMIT_VIRTUALTABLE
|
| + /* Possibly overload the function if the first argument is
|
| + ** a virtual table column.
|
| + **
|
| + ** For infix functions (LIKE, GLOB, REGEXP, and MATCH) use the
|
| + ** second argument, not the first, as the argument to test to
|
| + ** see if it is a column in a virtual table. This is done because
|
| + ** the left operand of infix functions (the operand we want to
|
| + ** control overloading) ends up as the second argument to the
|
| + ** function. The expression "A glob B" is equivalent to
|
| + ** "glob(B,A). We want to use the A in "A glob B" to test
|
| + ** for function overloading. But we use the B term in "glob(B,A)".
|
| + */
|
| + if( nFarg>=2 && (pExpr->flags & EP_InfixFunc) ){
|
| + pDef = sqlite3VtabOverloadFunction(db, pDef, nFarg, pFarg->a[1].pExpr);
|
| + }else if( nFarg>0 ){
|
| + pDef = sqlite3VtabOverloadFunction(db, pDef, nFarg, pFarg->a[0].pExpr);
|
| + }
|
| +#endif
|
| + if( pDef->funcFlags & SQLITE_FUNC_NEEDCOLL ){
|
| + if( !pColl ) pColl = db->pDfltColl;
|
| + sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ);
|
| + }
|
| + sqlite3VdbeAddOp4(v, OP_Function0, constMask, r1, target,
|
| + (char*)pDef, P4_FUNCDEF);
|
| + sqlite3VdbeChangeP5(v, (u8)nFarg);
|
| + if( nFarg && constMask==0 ){
|
| + sqlite3ReleaseTempRange(pParse, r1, nFarg);
|
| + }
|
| + break;
|
| + }
|
| +#ifndef SQLITE_OMIT_SUBQUERY
|
| + case TK_EXISTS:
|
| + case TK_SELECT: {
|
| + testcase( op==TK_EXISTS );
|
| + testcase( op==TK_SELECT );
|
| + inReg = sqlite3CodeSubselect(pParse, pExpr, 0, 0);
|
| + break;
|
| + }
|
| + case TK_IN: {
|
| + int destIfFalse = sqlite3VdbeMakeLabel(v);
|
| + int destIfNull = sqlite3VdbeMakeLabel(v);
|
| + sqlite3VdbeAddOp2(v, OP_Null, 0, target);
|
| + sqlite3ExprCodeIN(pParse, pExpr, destIfFalse, destIfNull);
|
| + sqlite3VdbeAddOp2(v, OP_Integer, 1, target);
|
| + sqlite3VdbeResolveLabel(v, destIfFalse);
|
| + sqlite3VdbeAddOp2(v, OP_AddImm, target, 0);
|
| + sqlite3VdbeResolveLabel(v, destIfNull);
|
| + break;
|
| + }
|
| +#endif /* SQLITE_OMIT_SUBQUERY */
|
| +
|
| +
|
| + /*
|
| + ** x BETWEEN y AND z
|
| + **
|
| + ** This is equivalent to
|
| + **
|
| + ** x>=y AND x<=z
|
| + **
|
| + ** X is stored in pExpr->pLeft.
|
| + ** Y is stored in pExpr->pList->a[0].pExpr.
|
| + ** Z is stored in pExpr->pList->a[1].pExpr.
|
| + */
|
| + case TK_BETWEEN: {
|
| + Expr *pLeft = pExpr->pLeft;
|
| + struct ExprList_item *pLItem = pExpr->x.pList->a;
|
| + Expr *pRight = pLItem->pExpr;
|
| +
|
| + r1 = sqlite3ExprCodeTemp(pParse, pLeft, ®Free1);
|
| + r2 = sqlite3ExprCodeTemp(pParse, pRight, ®Free2);
|
| + testcase( regFree1==0 );
|
| + testcase( regFree2==0 );
|
| + r3 = sqlite3GetTempReg(pParse);
|
| + r4 = sqlite3GetTempReg(pParse);
|
| + codeCompare(pParse, pLeft, pRight, OP_Ge,
|
| + r1, r2, r3, SQLITE_STOREP2); VdbeCoverage(v);
|
| + pLItem++;
|
| + pRight = pLItem->pExpr;
|
| + sqlite3ReleaseTempReg(pParse, regFree2);
|
| + r2 = sqlite3ExprCodeTemp(pParse, pRight, ®Free2);
|
| + testcase( regFree2==0 );
|
| + codeCompare(pParse, pLeft, pRight, OP_Le, r1, r2, r4, SQLITE_STOREP2);
|
| + VdbeCoverage(v);
|
| + sqlite3VdbeAddOp3(v, OP_And, r3, r4, target);
|
| + sqlite3ReleaseTempReg(pParse, r3);
|
| + sqlite3ReleaseTempReg(pParse, r4);
|
| + break;
|
| + }
|
| + case TK_COLLATE:
|
| + case TK_UPLUS: {
|
| + inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
|
| + break;
|
| + }
|
| +
|
| + case TK_TRIGGER: {
|
| + /* If the opcode is TK_TRIGGER, then the expression is a reference
|
| + ** to a column in the new.* or old.* pseudo-tables available to
|
| + ** trigger programs. In this case Expr.iTable is set to 1 for the
|
| + ** new.* pseudo-table, or 0 for the old.* pseudo-table. Expr.iColumn
|
| + ** is set to the column of the pseudo-table to read, or to -1 to
|
| + ** read the rowid field.
|
| + **
|
| + ** The expression is implemented using an OP_Param opcode. The p1
|
| + ** parameter is set to 0 for an old.rowid reference, or to (i+1)
|
| + ** to reference another column of the old.* pseudo-table, where
|
| + ** i is the index of the column. For a new.rowid reference, p1 is
|
| + ** set to (n+1), where n is the number of columns in each pseudo-table.
|
| + ** For a reference to any other column in the new.* pseudo-table, p1
|
| + ** is set to (n+2+i), where n and i are as defined previously. For
|
| + ** example, if the table on which triggers are being fired is
|
| + ** declared as:
|
| + **
|
| + ** CREATE TABLE t1(a, b);
|
| + **
|
| + ** Then p1 is interpreted as follows:
|
| + **
|
| + ** p1==0 -> old.rowid p1==3 -> new.rowid
|
| + ** p1==1 -> old.a p1==4 -> new.a
|
| + ** p1==2 -> old.b p1==5 -> new.b
|
| + */
|
| + Table *pTab = pExpr->pTab;
|
| + int p1 = pExpr->iTable * (pTab->nCol+1) + 1 + pExpr->iColumn;
|
| +
|
| + assert( pExpr->iTable==0 || pExpr->iTable==1 );
|
| + assert( pExpr->iColumn>=-1 && pExpr->iColumn<pTab->nCol );
|
| + assert( pTab->iPKey<0 || pExpr->iColumn!=pTab->iPKey );
|
| + assert( p1>=0 && p1<(pTab->nCol*2+2) );
|
| +
|
| + sqlite3VdbeAddOp2(v, OP_Param, p1, target);
|
| + VdbeComment((v, "%s.%s -> $%d",
|
| + (pExpr->iTable ? "new" : "old"),
|
| + (pExpr->iColumn<0 ? "rowid" : pExpr->pTab->aCol[pExpr->iColumn].zName),
|
| + target
|
| + ));
|
| +
|
| +#ifndef SQLITE_OMIT_FLOATING_POINT
|
| + /* If the column has REAL affinity, it may currently be stored as an
|
| + ** integer. Use OP_RealAffinity to make sure it is really real.
|
| + **
|
| + ** EVIDENCE-OF: R-60985-57662 SQLite will convert the value back to
|
| + ** floating point when extracting it from the record. */
|
| + if( pExpr->iColumn>=0
|
| + && pTab->aCol[pExpr->iColumn].affinity==SQLITE_AFF_REAL
|
| + ){
|
| + sqlite3VdbeAddOp1(v, OP_RealAffinity, target);
|
| + }
|
| +#endif
|
| + break;
|
| + }
|
| +
|
| +
|
| + /*
|
| + ** Form A:
|
| + ** CASE x WHEN e1 THEN r1 WHEN e2 THEN r2 ... WHEN eN THEN rN ELSE y END
|
| + **
|
| + ** Form B:
|
| + ** CASE WHEN e1 THEN r1 WHEN e2 THEN r2 ... WHEN eN THEN rN ELSE y END
|
| + **
|
| + ** Form A is can be transformed into the equivalent form B as follows:
|
| + ** CASE WHEN x=e1 THEN r1 WHEN x=e2 THEN r2 ...
|
| + ** WHEN x=eN THEN rN ELSE y END
|
| + **
|
| + ** X (if it exists) is in pExpr->pLeft.
|
| + ** Y is in the last element of pExpr->x.pList if pExpr->x.pList->nExpr is
|
| + ** odd. The Y is also optional. If the number of elements in x.pList
|
| + ** is even, then Y is omitted and the "otherwise" result is NULL.
|
| + ** Ei is in pExpr->pList->a[i*2] and Ri is pExpr->pList->a[i*2+1].
|
| + **
|
| + ** The result of the expression is the Ri for the first matching Ei,
|
| + ** or if there is no matching Ei, the ELSE term Y, or if there is
|
| + ** no ELSE term, NULL.
|
| + */
|
| + default: assert( op==TK_CASE ); {
|
| + int endLabel; /* GOTO label for end of CASE stmt */
|
| + int nextCase; /* GOTO label for next WHEN clause */
|
| + int nExpr; /* 2x number of WHEN terms */
|
| + int i; /* Loop counter */
|
| + ExprList *pEList; /* List of WHEN terms */
|
| + struct ExprList_item *aListelem; /* Array of WHEN terms */
|
| + Expr opCompare; /* The X==Ei expression */
|
| + Expr *pX; /* The X expression */
|
| + Expr *pTest = 0; /* X==Ei (form A) or just Ei (form B) */
|
| + VVA_ONLY( int iCacheLevel = pParse->iCacheLevel; )
|
| +
|
| + assert( !ExprHasProperty(pExpr, EP_xIsSelect) && pExpr->x.pList );
|
| + assert(pExpr->x.pList->nExpr > 0);
|
| + pEList = pExpr->x.pList;
|
| + aListelem = pEList->a;
|
| + nExpr = pEList->nExpr;
|
| + endLabel = sqlite3VdbeMakeLabel(v);
|
| + if( (pX = pExpr->pLeft)!=0 ){
|
| + tempX = *pX;
|
| + testcase( pX->op==TK_COLUMN );
|
| + exprToRegister(&tempX, sqlite3ExprCodeTemp(pParse, pX, ®Free1));
|
| + testcase( regFree1==0 );
|
| + opCompare.op = TK_EQ;
|
| + opCompare.pLeft = &tempX;
|
| + pTest = &opCompare;
|
| + /* Ticket b351d95f9cd5ef17e9d9dbae18f5ca8611190001:
|
| + ** The value in regFree1 might get SCopy-ed into the file result.
|
| + ** So make sure that the regFree1 register is not reused for other
|
| + ** purposes and possibly overwritten. */
|
| + regFree1 = 0;
|
| + }
|
| + for(i=0; i<nExpr-1; i=i+2){
|
| + sqlite3ExprCachePush(pParse);
|
| + if( pX ){
|
| + assert( pTest!=0 );
|
| + opCompare.pRight = aListelem[i].pExpr;
|
| + }else{
|
| + pTest = aListelem[i].pExpr;
|
| + }
|
| + nextCase = sqlite3VdbeMakeLabel(v);
|
| + testcase( pTest->op==TK_COLUMN );
|
| + sqlite3ExprIfFalse(pParse, pTest, nextCase, SQLITE_JUMPIFNULL);
|
| + testcase( aListelem[i+1].pExpr->op==TK_COLUMN );
|
| + sqlite3ExprCode(pParse, aListelem[i+1].pExpr, target);
|
| + sqlite3VdbeGoto(v, endLabel);
|
| + sqlite3ExprCachePop(pParse);
|
| + sqlite3VdbeResolveLabel(v, nextCase);
|
| + }
|
| + if( (nExpr&1)!=0 ){
|
| + sqlite3ExprCachePush(pParse);
|
| + sqlite3ExprCode(pParse, pEList->a[nExpr-1].pExpr, target);
|
| + sqlite3ExprCachePop(pParse);
|
| + }else{
|
| + sqlite3VdbeAddOp2(v, OP_Null, 0, target);
|
| + }
|
| + assert( db->mallocFailed || pParse->nErr>0
|
| + || pParse->iCacheLevel==iCacheLevel );
|
| + sqlite3VdbeResolveLabel(v, endLabel);
|
| + break;
|
| + }
|
| +#ifndef SQLITE_OMIT_TRIGGER
|
| + case TK_RAISE: {
|
| + assert( pExpr->affinity==OE_Rollback
|
| + || pExpr->affinity==OE_Abort
|
| + || pExpr->affinity==OE_Fail
|
| + || pExpr->affinity==OE_Ignore
|
| + );
|
| + if( !pParse->pTriggerTab ){
|
| + sqlite3ErrorMsg(pParse,
|
| + "RAISE() may only be used within a trigger-program");
|
| + return 0;
|
| + }
|
| + if( pExpr->affinity==OE_Abort ){
|
| + sqlite3MayAbort(pParse);
|
| + }
|
| + assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
| + if( pExpr->affinity==OE_Ignore ){
|
| + sqlite3VdbeAddOp4(
|
| + v, OP_Halt, SQLITE_OK, OE_Ignore, 0, pExpr->u.zToken,0);
|
| + VdbeCoverage(v);
|
| + }else{
|
| + sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_TRIGGER,
|
| + pExpr->affinity, pExpr->u.zToken, 0, 0);
|
| + }
|
| +
|
| + break;
|
| + }
|
| +#endif
|
| + }
|
| + sqlite3ReleaseTempReg(pParse, regFree1);
|
| + sqlite3ReleaseTempReg(pParse, regFree2);
|
| + return inReg;
|
| +}
|
| +
|
| +/*
|
| +** Factor out the code of the given expression to initialization time.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3ExprCodeAtInit(
|
| + Parse *pParse, /* Parsing context */
|
| + Expr *pExpr, /* The expression to code when the VDBE initializes */
|
| + int regDest, /* Store the value in this register */
|
| + u8 reusable /* True if this expression is reusable */
|
| +){
|
| + ExprList *p;
|
| + assert( ConstFactorOk(pParse) );
|
| + p = pParse->pConstExpr;
|
| + pExpr = sqlite3ExprDup(pParse->db, pExpr, 0);
|
| + p = sqlite3ExprListAppend(pParse, p, pExpr);
|
| + if( p ){
|
| + struct ExprList_item *pItem = &p->a[p->nExpr-1];
|
| + pItem->u.iConstExprReg = regDest;
|
| + pItem->reusable = reusable;
|
| + }
|
| + pParse->pConstExpr = p;
|
| +}
|
| +
|
| +/*
|
| +** Generate code to evaluate an expression and store the results
|
| +** into a register. Return the register number where the results
|
| +** are stored.
|
| +**
|
| +** If the register is a temporary register that can be deallocated,
|
| +** then write its number into *pReg. If the result register is not
|
| +** a temporary, then set *pReg to zero.
|
| +**
|
| +** If pExpr is a constant, then this routine might generate this
|
| +** code to fill the register in the initialization section of the
|
| +** VDBE program, in order to factor it out of the evaluation loop.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse *pParse, Expr *pExpr, int *pReg){
|
| + int r2;
|
| + pExpr = sqlite3ExprSkipCollate(pExpr);
|
| + if( ConstFactorOk(pParse)
|
| + && pExpr->op!=TK_REGISTER
|
| + && sqlite3ExprIsConstantNotJoin(pExpr)
|
| + ){
|
| + ExprList *p = pParse->pConstExpr;
|
| + int i;
|
| + *pReg = 0;
|
| + if( p ){
|
| + struct ExprList_item *pItem;
|
| + for(pItem=p->a, i=p->nExpr; i>0; pItem++, i--){
|
| + if( pItem->reusable && sqlite3ExprCompare(pItem->pExpr,pExpr,-1)==0 ){
|
| + return pItem->u.iConstExprReg;
|
| + }
|
| + }
|
| + }
|
| + r2 = ++pParse->nMem;
|
| + sqlite3ExprCodeAtInit(pParse, pExpr, r2, 1);
|
| + }else{
|
| + int r1 = sqlite3GetTempReg(pParse);
|
| + r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
|
| + if( r2==r1 ){
|
| + *pReg = r1;
|
| + }else{
|
| + sqlite3ReleaseTempReg(pParse, r1);
|
| + *pReg = 0;
|
| + }
|
| + }
|
| + return r2;
|
| +}
|
| +
|
| +/*
|
| +** Generate code that will evaluate expression pExpr and store the
|
| +** results in register target. The results are guaranteed to appear
|
| +** in register target.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
|
| + int inReg;
|
| +
|
| + assert( target>0 && target<=pParse->nMem );
|
| + if( pExpr && pExpr->op==TK_REGISTER ){
|
| + sqlite3VdbeAddOp2(pParse->pVdbe, OP_Copy, pExpr->iTable, target);
|
| + }else{
|
| + inReg = sqlite3ExprCodeTarget(pParse, pExpr, target);
|
| + assert( pParse->pVdbe!=0 || pParse->db->mallocFailed );
|
| + if( inReg!=target && pParse->pVdbe ){
|
| + sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, inReg, target);
|
| + }
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Make a transient copy of expression pExpr and then code it using
|
| +** sqlite3ExprCode(). This routine works just like sqlite3ExprCode()
|
| +** except that the input expression is guaranteed to be unchanged.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse *pParse, Expr *pExpr, int target){
|
| + sqlite3 *db = pParse->db;
|
| + pExpr = sqlite3ExprDup(db, pExpr, 0);
|
| + if( !db->mallocFailed ) sqlite3ExprCode(pParse, pExpr, target);
|
| + sqlite3ExprDelete(db, pExpr);
|
| +}
|
| +
|
| +/*
|
| +** Generate code that will evaluate expression pExpr and store the
|
| +** results in register target. The results are guaranteed to appear
|
| +** in register target. If the expression is constant, then this routine
|
| +** might choose to code the expression at initialization time.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3ExprCodeFactorable(Parse *pParse, Expr *pExpr, int target){
|
| + if( pParse->okConstFactor && sqlite3ExprIsConstant(pExpr) ){
|
| + sqlite3ExprCodeAtInit(pParse, pExpr, target, 0);
|
| + }else{
|
| + sqlite3ExprCode(pParse, pExpr, target);
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Generate code that evaluates the given expression and puts the result
|
| +** in register target.
|
| +**
|
| +** Also make a copy of the expression results into another "cache" register
|
| +** and modify the expression so that the next time it is evaluated,
|
| +** the result is a copy of the cache register.
|
| +**
|
| +** This routine is used for expressions that are used multiple
|
| +** times. They are evaluated once and the results of the expression
|
| +** are reused.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int target){
|
| + Vdbe *v = pParse->pVdbe;
|
| + int iMem;
|
| +
|
| + assert( target>0 );
|
| + assert( pExpr->op!=TK_REGISTER );
|
| + sqlite3ExprCode(pParse, pExpr, target);
|
| + iMem = ++pParse->nMem;
|
| + sqlite3VdbeAddOp2(v, OP_Copy, target, iMem);
|
| + exprToRegister(pExpr, iMem);
|
| +}
|
| +
|
| +/*
|
| +** Generate code that pushes the value of every element of the given
|
| +** expression list into a sequence of registers beginning at target.
|
| +**
|
| +** Return the number of elements evaluated.
|
| +**
|
| +** The SQLITE_ECEL_DUP flag prevents the arguments from being
|
| +** filled using OP_SCopy. OP_Copy must be used instead.
|
| +**
|
| +** The SQLITE_ECEL_FACTOR argument allows constant arguments to be
|
| +** factored out into initialization code.
|
| +**
|
| +** The SQLITE_ECEL_REF flag means that expressions in the list with
|
| +** ExprList.a[].u.x.iOrderByCol>0 have already been evaluated and stored
|
| +** in registers at srcReg, and so the value can be copied from there.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3ExprCodeExprList(
|
| + Parse *pParse, /* Parsing context */
|
| + ExprList *pList, /* The expression list to be coded */
|
| + int target, /* Where to write results */
|
| + int srcReg, /* Source registers if SQLITE_ECEL_REF */
|
| + u8 flags /* SQLITE_ECEL_* flags */
|
| +){
|
| + struct ExprList_item *pItem;
|
| + int i, j, n;
|
| + u8 copyOp = (flags & SQLITE_ECEL_DUP) ? OP_Copy : OP_SCopy;
|
| + Vdbe *v = pParse->pVdbe;
|
| + assert( pList!=0 );
|
| + assert( target>0 );
|
| + assert( pParse->pVdbe!=0 ); /* Never gets this far otherwise */
|
| + n = pList->nExpr;
|
| + if( !ConstFactorOk(pParse) ) flags &= ~SQLITE_ECEL_FACTOR;
|
| + for(pItem=pList->a, i=0; i<n; i++, pItem++){
|
| + Expr *pExpr = pItem->pExpr;
|
| + if( (flags & SQLITE_ECEL_REF)!=0 && (j = pList->a[i].u.x.iOrderByCol)>0 ){
|
| + sqlite3VdbeAddOp2(v, copyOp, j+srcReg-1, target+i);
|
| + }else if( (flags & SQLITE_ECEL_FACTOR)!=0 && sqlite3ExprIsConstant(pExpr) ){
|
| + sqlite3ExprCodeAtInit(pParse, pExpr, target+i, 0);
|
| + }else{
|
| + int inReg = sqlite3ExprCodeTarget(pParse, pExpr, target+i);
|
| + if( inReg!=target+i ){
|
| + VdbeOp *pOp;
|
| + if( copyOp==OP_Copy
|
| + && (pOp=sqlite3VdbeGetOp(v, -1))->opcode==OP_Copy
|
| + && pOp->p1+pOp->p3+1==inReg
|
| + && pOp->p2+pOp->p3+1==target+i
|
| + ){
|
| + pOp->p3++;
|
| + }else{
|
| + sqlite3VdbeAddOp2(v, copyOp, inReg, target+i);
|
| + }
|
| + }
|
| + }
|
| + }
|
| + return n;
|
| +}
|
| +
|
| +/*
|
| +** Generate code for a BETWEEN operator.
|
| +**
|
| +** x BETWEEN y AND z
|
| +**
|
| +** The above is equivalent to
|
| +**
|
| +** x>=y AND x<=z
|
| +**
|
| +** Code it as such, taking care to do the common subexpression
|
| +** elimination of x.
|
| +*/
|
| +static void exprCodeBetween(
|
| + Parse *pParse, /* Parsing and code generating context */
|
| + Expr *pExpr, /* The BETWEEN expression */
|
| + int dest, /* Jump here if the jump is taken */
|
| + int jumpIfTrue, /* Take the jump if the BETWEEN is true */
|
| + int jumpIfNull /* Take the jump if the BETWEEN is NULL */
|
| +){
|
| + Expr exprAnd; /* The AND operator in x>=y AND x<=z */
|
| + Expr compLeft; /* The x>=y term */
|
| + Expr compRight; /* The x<=z term */
|
| + Expr exprX; /* The x subexpression */
|
| + int regFree1 = 0; /* Temporary use register */
|
| +
|
| + assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
|
| + exprX = *pExpr->pLeft;
|
| + exprAnd.op = TK_AND;
|
| + exprAnd.pLeft = &compLeft;
|
| + exprAnd.pRight = &compRight;
|
| + compLeft.op = TK_GE;
|
| + compLeft.pLeft = &exprX;
|
| + compLeft.pRight = pExpr->x.pList->a[0].pExpr;
|
| + compRight.op = TK_LE;
|
| + compRight.pLeft = &exprX;
|
| + compRight.pRight = pExpr->x.pList->a[1].pExpr;
|
| + exprToRegister(&exprX, sqlite3ExprCodeTemp(pParse, &exprX, ®Free1));
|
| + if( jumpIfTrue ){
|
| + sqlite3ExprIfTrue(pParse, &exprAnd, dest, jumpIfNull);
|
| + }else{
|
| + sqlite3ExprIfFalse(pParse, &exprAnd, dest, jumpIfNull);
|
| + }
|
| + sqlite3ReleaseTempReg(pParse, regFree1);
|
| +
|
| + /* Ensure adequate test coverage */
|
| + testcase( jumpIfTrue==0 && jumpIfNull==0 && regFree1==0 );
|
| + testcase( jumpIfTrue==0 && jumpIfNull==0 && regFree1!=0 );
|
| + testcase( jumpIfTrue==0 && jumpIfNull!=0 && regFree1==0 );
|
| + testcase( jumpIfTrue==0 && jumpIfNull!=0 && regFree1!=0 );
|
| + testcase( jumpIfTrue!=0 && jumpIfNull==0 && regFree1==0 );
|
| + testcase( jumpIfTrue!=0 && jumpIfNull==0 && regFree1!=0 );
|
| + testcase( jumpIfTrue!=0 && jumpIfNull!=0 && regFree1==0 );
|
| + testcase( jumpIfTrue!=0 && jumpIfNull!=0 && regFree1!=0 );
|
| +}
|
| +
|
| +/*
|
| +** Generate code for a boolean expression such that a jump is made
|
| +** to the label "dest" if the expression is true but execution
|
| +** continues straight thru if the expression is false.
|
| +**
|
| +** If the expression evaluates to NULL (neither true nor false), then
|
| +** take the jump if the jumpIfNull flag is SQLITE_JUMPIFNULL.
|
| +**
|
| +** This code depends on the fact that certain token values (ex: TK_EQ)
|
| +** are the same as opcode values (ex: OP_Eq) that implement the corresponding
|
| +** operation. Special comments in vdbe.c and the mkopcodeh.awk script in
|
| +** the make process cause these values to align. Assert()s in the code
|
| +** below verify that the numbers are aligned correctly.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
| + Vdbe *v = pParse->pVdbe;
|
| + int op = 0;
|
| + int regFree1 = 0;
|
| + int regFree2 = 0;
|
| + int r1, r2;
|
| +
|
| + assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 );
|
| + if( NEVER(v==0) ) return; /* Existence of VDBE checked by caller */
|
| + if( NEVER(pExpr==0) ) return; /* No way this can happen */
|
| + op = pExpr->op;
|
| + switch( op ){
|
| + case TK_AND: {
|
| + int d2 = sqlite3VdbeMakeLabel(v);
|
| + testcase( jumpIfNull==0 );
|
| + sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2,jumpIfNull^SQLITE_JUMPIFNULL);
|
| + sqlite3ExprCachePush(pParse);
|
| + sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
|
| + sqlite3VdbeResolveLabel(v, d2);
|
| + sqlite3ExprCachePop(pParse);
|
| + break;
|
| + }
|
| + case TK_OR: {
|
| + testcase( jumpIfNull==0 );
|
| + sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);
|
| + sqlite3ExprCachePush(pParse);
|
| + sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
|
| + sqlite3ExprCachePop(pParse);
|
| + break;
|
| + }
|
| + case TK_NOT: {
|
| + testcase( jumpIfNull==0 );
|
| + sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);
|
| + break;
|
| + }
|
| + case TK_LT:
|
| + case TK_LE:
|
| + case TK_GT:
|
| + case TK_GE:
|
| + case TK_NE:
|
| + case TK_EQ: {
|
| + testcase( jumpIfNull==0 );
|
| + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
| + r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
| + codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
|
| + r1, r2, dest, jumpIfNull);
|
| + assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
|
| + assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
|
| + assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt);
|
| + assert(TK_GE==OP_Ge); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge);
|
| + assert(TK_EQ==OP_Eq); testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq);
|
| + assert(TK_NE==OP_Ne); testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne);
|
| + testcase( regFree1==0 );
|
| + testcase( regFree2==0 );
|
| + break;
|
| + }
|
| + case TK_IS:
|
| + case TK_ISNOT: {
|
| + testcase( op==TK_IS );
|
| + testcase( op==TK_ISNOT );
|
| + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
| + r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
| + op = (op==TK_IS) ? TK_EQ : TK_NE;
|
| + codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
|
| + r1, r2, dest, SQLITE_NULLEQ);
|
| + VdbeCoverageIf(v, op==TK_EQ);
|
| + VdbeCoverageIf(v, op==TK_NE);
|
| + testcase( regFree1==0 );
|
| + testcase( regFree2==0 );
|
| + break;
|
| + }
|
| + case TK_ISNULL:
|
| + case TK_NOTNULL: {
|
| + assert( TK_ISNULL==OP_IsNull ); testcase( op==TK_ISNULL );
|
| + assert( TK_NOTNULL==OP_NotNull ); testcase( op==TK_NOTNULL );
|
| + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
| + sqlite3VdbeAddOp2(v, op, r1, dest);
|
| + VdbeCoverageIf(v, op==TK_ISNULL);
|
| + VdbeCoverageIf(v, op==TK_NOTNULL);
|
| + testcase( regFree1==0 );
|
| + break;
|
| + }
|
| + case TK_BETWEEN: {
|
| + testcase( jumpIfNull==0 );
|
| + exprCodeBetween(pParse, pExpr, dest, 1, jumpIfNull);
|
| + break;
|
| + }
|
| +#ifndef SQLITE_OMIT_SUBQUERY
|
| + case TK_IN: {
|
| + int destIfFalse = sqlite3VdbeMakeLabel(v);
|
| + int destIfNull = jumpIfNull ? dest : destIfFalse;
|
| + sqlite3ExprCodeIN(pParse, pExpr, destIfFalse, destIfNull);
|
| + sqlite3VdbeGoto(v, dest);
|
| + sqlite3VdbeResolveLabel(v, destIfFalse);
|
| + break;
|
| + }
|
| +#endif
|
| + default: {
|
| + if( exprAlwaysTrue(pExpr) ){
|
| + sqlite3VdbeGoto(v, dest);
|
| + }else if( exprAlwaysFalse(pExpr) ){
|
| + /* No-op */
|
| + }else{
|
| + r1 = sqlite3ExprCodeTemp(pParse, pExpr, ®Free1);
|
| + sqlite3VdbeAddOp3(v, OP_If, r1, dest, jumpIfNull!=0);
|
| + VdbeCoverage(v);
|
| + testcase( regFree1==0 );
|
| + testcase( jumpIfNull==0 );
|
| + }
|
| + break;
|
| + }
|
| + }
|
| + sqlite3ReleaseTempReg(pParse, regFree1);
|
| + sqlite3ReleaseTempReg(pParse, regFree2);
|
| +}
|
| +
|
| +/*
|
| +** Generate code for a boolean expression such that a jump is made
|
| +** to the label "dest" if the expression is false but execution
|
| +** continues straight thru if the expression is true.
|
| +**
|
| +** If the expression evaluates to NULL (neither true nor false) then
|
| +** jump if jumpIfNull is SQLITE_JUMPIFNULL or fall through if jumpIfNull
|
| +** is 0.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
| + Vdbe *v = pParse->pVdbe;
|
| + int op = 0;
|
| + int regFree1 = 0;
|
| + int regFree2 = 0;
|
| + int r1, r2;
|
| +
|
| + assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 );
|
| + if( NEVER(v==0) ) return; /* Existence of VDBE checked by caller */
|
| + if( pExpr==0 ) return;
|
| +
|
| + /* The value of pExpr->op and op are related as follows:
|
| + **
|
| + ** pExpr->op op
|
| + ** --------- ----------
|
| + ** TK_ISNULL OP_NotNull
|
| + ** TK_NOTNULL OP_IsNull
|
| + ** TK_NE OP_Eq
|
| + ** TK_EQ OP_Ne
|
| + ** TK_GT OP_Le
|
| + ** TK_LE OP_Gt
|
| + ** TK_GE OP_Lt
|
| + ** TK_LT OP_Ge
|
| + **
|
| + ** For other values of pExpr->op, op is undefined and unused.
|
| + ** The value of TK_ and OP_ constants are arranged such that we
|
| + ** can compute the mapping above using the following expression.
|
| + ** Assert()s verify that the computation is correct.
|
| + */
|
| + op = ((pExpr->op+(TK_ISNULL&1))^1)-(TK_ISNULL&1);
|
| +
|
| + /* Verify correct alignment of TK_ and OP_ constants
|
| + */
|
| + assert( pExpr->op!=TK_ISNULL || op==OP_NotNull );
|
| + assert( pExpr->op!=TK_NOTNULL || op==OP_IsNull );
|
| + assert( pExpr->op!=TK_NE || op==OP_Eq );
|
| + assert( pExpr->op!=TK_EQ || op==OP_Ne );
|
| + assert( pExpr->op!=TK_LT || op==OP_Ge );
|
| + assert( pExpr->op!=TK_LE || op==OP_Gt );
|
| + assert( pExpr->op!=TK_GT || op==OP_Le );
|
| + assert( pExpr->op!=TK_GE || op==OP_Lt );
|
| +
|
| + switch( pExpr->op ){
|
| + case TK_AND: {
|
| + testcase( jumpIfNull==0 );
|
| + sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);
|
| + sqlite3ExprCachePush(pParse);
|
| + sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
|
| + sqlite3ExprCachePop(pParse);
|
| + break;
|
| + }
|
| + case TK_OR: {
|
| + int d2 = sqlite3VdbeMakeLabel(v);
|
| + testcase( jumpIfNull==0 );
|
| + sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, jumpIfNull^SQLITE_JUMPIFNULL);
|
| + sqlite3ExprCachePush(pParse);
|
| + sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
|
| + sqlite3VdbeResolveLabel(v, d2);
|
| + sqlite3ExprCachePop(pParse);
|
| + break;
|
| + }
|
| + case TK_NOT: {
|
| + testcase( jumpIfNull==0 );
|
| + sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);
|
| + break;
|
| + }
|
| + case TK_LT:
|
| + case TK_LE:
|
| + case TK_GT:
|
| + case TK_GE:
|
| + case TK_NE:
|
| + case TK_EQ: {
|
| + testcase( jumpIfNull==0 );
|
| + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
| + r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
| + codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
|
| + r1, r2, dest, jumpIfNull);
|
| + assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
|
| + assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
|
| + assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt);
|
| + assert(TK_GE==OP_Ge); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge);
|
| + assert(TK_EQ==OP_Eq); testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq);
|
| + assert(TK_NE==OP_Ne); testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne);
|
| + testcase( regFree1==0 );
|
| + testcase( regFree2==0 );
|
| + break;
|
| + }
|
| + case TK_IS:
|
| + case TK_ISNOT: {
|
| + testcase( pExpr->op==TK_IS );
|
| + testcase( pExpr->op==TK_ISNOT );
|
| + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
| + r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
| + op = (pExpr->op==TK_IS) ? TK_NE : TK_EQ;
|
| + codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
|
| + r1, r2, dest, SQLITE_NULLEQ);
|
| + VdbeCoverageIf(v, op==TK_EQ);
|
| + VdbeCoverageIf(v, op==TK_NE);
|
| + testcase( regFree1==0 );
|
| + testcase( regFree2==0 );
|
| + break;
|
| + }
|
| + case TK_ISNULL:
|
| + case TK_NOTNULL: {
|
| + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
| + sqlite3VdbeAddOp2(v, op, r1, dest);
|
| + testcase( op==TK_ISNULL ); VdbeCoverageIf(v, op==TK_ISNULL);
|
| + testcase( op==TK_NOTNULL ); VdbeCoverageIf(v, op==TK_NOTNULL);
|
| + testcase( regFree1==0 );
|
| + break;
|
| + }
|
| + case TK_BETWEEN: {
|
| + testcase( jumpIfNull==0 );
|
| + exprCodeBetween(pParse, pExpr, dest, 0, jumpIfNull);
|
| + break;
|
| + }
|
| +#ifndef SQLITE_OMIT_SUBQUERY
|
| + case TK_IN: {
|
| + if( jumpIfNull ){
|
| + sqlite3ExprCodeIN(pParse, pExpr, dest, dest);
|
| + }else{
|
| + int destIfNull = sqlite3VdbeMakeLabel(v);
|
| + sqlite3ExprCodeIN(pParse, pExpr, dest, destIfNull);
|
| + sqlite3VdbeResolveLabel(v, destIfNull);
|
| + }
|
| + break;
|
| + }
|
| +#endif
|
| + default: {
|
| + if( exprAlwaysFalse(pExpr) ){
|
| + sqlite3VdbeGoto(v, dest);
|
| + }else if( exprAlwaysTrue(pExpr) ){
|
| + /* no-op */
|
| + }else{
|
| + r1 = sqlite3ExprCodeTemp(pParse, pExpr, ®Free1);
|
| + sqlite3VdbeAddOp3(v, OP_IfNot, r1, dest, jumpIfNull!=0);
|
| + VdbeCoverage(v);
|
| + testcase( regFree1==0 );
|
| + testcase( jumpIfNull==0 );
|
| + }
|
| + break;
|
| + }
|
| + }
|
| + sqlite3ReleaseTempReg(pParse, regFree1);
|
| + sqlite3ReleaseTempReg(pParse, regFree2);
|
| +}
|
| +
|
| +/*
|
| +** Like sqlite3ExprIfFalse() except that a copy is made of pExpr before
|
| +** code generation, and that copy is deleted after code generation. This
|
| +** ensures that the original pExpr is unchanged.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3ExprIfFalseDup(Parse *pParse, Expr *pExpr, int dest,int jumpIfNull){
|
| + sqlite3 *db = pParse->db;
|
| + Expr *pCopy = sqlite3ExprDup(db, pExpr, 0);
|
| + if( db->mallocFailed==0 ){
|
| + sqlite3ExprIfFalse(pParse, pCopy, dest, jumpIfNull);
|
| + }
|
| + sqlite3ExprDelete(db, pCopy);
|
| +}
|
| +
|
| +
|
| +/*
|
| +** Do a deep comparison of two expression trees. Return 0 if the two
|
| +** expressions are completely identical. Return 1 if they differ only
|
| +** by a COLLATE operator at the top level. Return 2 if there are differences
|
| +** other than the top-level COLLATE operator.
|
| +**
|
| +** If any subelement of pB has Expr.iTable==(-1) then it is allowed
|
| +** to compare equal to an equivalent element in pA with Expr.iTable==iTab.
|
| +**
|
| +** The pA side might be using TK_REGISTER. If that is the case and pB is
|
| +** not using TK_REGISTER but is otherwise equivalent, then still return 0.
|
| +**
|
| +** Sometimes this routine will return 2 even if the two expressions
|
| +** really are equivalent. If we cannot prove that the expressions are
|
| +** identical, we return 2 just to be safe. So if this routine
|
| +** returns 2, then you do not really know for certain if the two
|
| +** expressions are the same. But if you get a 0 or 1 return, then you
|
| +** can be sure the expressions are the same. In the places where
|
| +** this routine is used, it does not hurt to get an extra 2 - that
|
| +** just might result in some slightly slower code. But returning
|
| +** an incorrect 0 or 1 could lead to a malfunction.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3ExprCompare(Expr *pA, Expr *pB, int iTab){
|
| + u32 combinedFlags;
|
| + if( pA==0 || pB==0 ){
|
| + return pB==pA ? 0 : 2;
|
| + }
|
| + combinedFlags = pA->flags | pB->flags;
|
| + if( combinedFlags & EP_IntValue ){
|
| + if( (pA->flags&pB->flags&EP_IntValue)!=0 && pA->u.iValue==pB->u.iValue ){
|
| + return 0;
|
| + }
|
| + return 2;
|
| + }
|
| + if( pA->op!=pB->op ){
|
| + if( pA->op==TK_COLLATE && sqlite3ExprCompare(pA->pLeft, pB, iTab)<2 ){
|
| + return 1;
|
| + }
|
| + if( pB->op==TK_COLLATE && sqlite3ExprCompare(pA, pB->pLeft, iTab)<2 ){
|
| + return 1;
|
| + }
|
| + return 2;
|
| + }
|
| + if( pA->op!=TK_COLUMN && pA->op!=TK_AGG_COLUMN && pA->u.zToken ){
|
| + if( pA->op==TK_FUNCTION ){
|
| + if( sqlite3StrICmp(pA->u.zToken,pB->u.zToken)!=0 ) return 2;
|
| + }else if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){
|
| + return pA->op==TK_COLLATE ? 1 : 2;
|
| + }
|
| + }
|
| + if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2;
|
| + if( ALWAYS((combinedFlags & EP_TokenOnly)==0) ){
|
| + if( combinedFlags & EP_xIsSelect ) return 2;
|
| + if( sqlite3ExprCompare(pA->pLeft, pB->pLeft, iTab) ) return 2;
|
| + if( sqlite3ExprCompare(pA->pRight, pB->pRight, iTab) ) return 2;
|
| + if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2;
|
| + if( ALWAYS((combinedFlags & EP_Reduced)==0) && pA->op!=TK_STRING ){
|
| + if( pA->iColumn!=pB->iColumn ) return 2;
|
| + if( pA->iTable!=pB->iTable
|
| + && (pA->iTable!=iTab || NEVER(pB->iTable>=0)) ) return 2;
|
| + }
|
| + }
|
| + return 0;
|
| +}
|
| +
|
| +/*
|
| +** Compare two ExprList objects. Return 0 if they are identical and
|
| +** non-zero if they differ in any way.
|
| +**
|
| +** If any subelement of pB has Expr.iTable==(-1) then it is allowed
|
| +** to compare equal to an equivalent element in pA with Expr.iTable==iTab.
|
| +**
|
| +** This routine might return non-zero for equivalent ExprLists. The
|
| +** only consequence will be disabled optimizations. But this routine
|
| +** must never return 0 if the two ExprList objects are different, or
|
| +** a malfunction will result.
|
| +**
|
| +** Two NULL pointers are considered to be the same. But a NULL pointer
|
| +** always differs from a non-NULL pointer.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3ExprListCompare(ExprList *pA, ExprList *pB, int iTab){
|
| + int i;
|
| + if( pA==0 && pB==0 ) return 0;
|
| + if( pA==0 || pB==0 ) return 1;
|
| + if( pA->nExpr!=pB->nExpr ) return 1;
|
| + for(i=0; i<pA->nExpr; i++){
|
| + Expr *pExprA = pA->a[i].pExpr;
|
| + Expr *pExprB = pB->a[i].pExpr;
|
| + if( pA->a[i].sortOrder!=pB->a[i].sortOrder ) return 1;
|
| + if( sqlite3ExprCompare(pExprA, pExprB, iTab) ) return 1;
|
| + }
|
| + return 0;
|
| +}
|
| +
|
| +/*
|
| +** Return true if we can prove the pE2 will always be true if pE1 is
|
| +** true. Return false if we cannot complete the proof or if pE2 might
|
| +** be false. Examples:
|
| +**
|
| +** pE1: x==5 pE2: x==5 Result: true
|
| +** pE1: x>0 pE2: x==5 Result: false
|
| +** pE1: x=21 pE2: x=21 OR y=43 Result: true
|
| +** pE1: x!=123 pE2: x IS NOT NULL Result: true
|
| +** pE1: x!=?1 pE2: x IS NOT NULL Result: true
|
| +** pE1: x IS NULL pE2: x IS NOT NULL Result: false
|
| +** pE1: x IS ?2 pE2: x IS NOT NULL Reuslt: false
|
| +**
|
| +** When comparing TK_COLUMN nodes between pE1 and pE2, if pE2 has
|
| +** Expr.iTable<0 then assume a table number given by iTab.
|
| +**
|
| +** When in doubt, return false. Returning true might give a performance
|
| +** improvement. Returning false might cause a performance reduction, but
|
| +** it will always give the correct answer and is hence always safe.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3ExprImpliesExpr(Expr *pE1, Expr *pE2, int iTab){
|
| + if( sqlite3ExprCompare(pE1, pE2, iTab)==0 ){
|
| + return 1;
|
| + }
|
| + if( pE2->op==TK_OR
|
| + && (sqlite3ExprImpliesExpr(pE1, pE2->pLeft, iTab)
|
| + || sqlite3ExprImpliesExpr(pE1, pE2->pRight, iTab) )
|
| + ){
|
| + return 1;
|
| + }
|
| + if( pE2->op==TK_NOTNULL
|
| + && sqlite3ExprCompare(pE1->pLeft, pE2->pLeft, iTab)==0
|
| + && (pE1->op!=TK_ISNULL && pE1->op!=TK_IS)
|
| + ){
|
| + return 1;
|
| + }
|
| + return 0;
|
| +}
|
| +
|
| +/*
|
| +** An instance of the following structure is used by the tree walker
|
| +** to count references to table columns in the arguments of an
|
| +** aggregate function, in order to implement the
|
| +** sqlite3FunctionThisSrc() routine.
|
| +*/
|
| +struct SrcCount {
|
| + SrcList *pSrc; /* One particular FROM clause in a nested query */
|
| + int nThis; /* Number of references to columns in pSrcList */
|
| + int nOther; /* Number of references to columns in other FROM clauses */
|
| +};
|
| +
|
| +/*
|
| +** Count the number of references to columns.
|
| +*/
|
| +static int exprSrcCount(Walker *pWalker, Expr *pExpr){
|
| + /* The NEVER() on the second term is because sqlite3FunctionUsesThisSrc()
|
| + ** is always called before sqlite3ExprAnalyzeAggregates() and so the
|
| + ** TK_COLUMNs have not yet been converted into TK_AGG_COLUMN. If
|
| + ** sqlite3FunctionUsesThisSrc() is used differently in the future, the
|
| + ** NEVER() will need to be removed. */
|
| + if( pExpr->op==TK_COLUMN || NEVER(pExpr->op==TK_AGG_COLUMN) ){
|
| + int i;
|
| + struct SrcCount *p = pWalker->u.pSrcCount;
|
| + SrcList *pSrc = p->pSrc;
|
| + int nSrc = pSrc ? pSrc->nSrc : 0;
|
| + for(i=0; i<nSrc; i++){
|
| + if( pExpr->iTable==pSrc->a[i].iCursor ) break;
|
| + }
|
| + if( i<nSrc ){
|
| + p->nThis++;
|
| + }else{
|
| + p->nOther++;
|
| + }
|
| + }
|
| + return WRC_Continue;
|
| +}
|
| +
|
| +/*
|
| +** Determine if any of the arguments to the pExpr Function reference
|
| +** pSrcList. Return true if they do. Also return true if the function
|
| +** has no arguments or has only constant arguments. Return false if pExpr
|
| +** references columns but not columns of tables found in pSrcList.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3FunctionUsesThisSrc(Expr *pExpr, SrcList *pSrcList){
|
| + Walker w;
|
| + struct SrcCount cnt;
|
| + assert( pExpr->op==TK_AGG_FUNCTION );
|
| + memset(&w, 0, sizeof(w));
|
| + w.xExprCallback = exprSrcCount;
|
| + w.u.pSrcCount = &cnt;
|
| + cnt.pSrc = pSrcList;
|
| + cnt.nThis = 0;
|
| + cnt.nOther = 0;
|
| + sqlite3WalkExprList(&w, pExpr->x.pList);
|
| + return cnt.nThis>0 || cnt.nOther==0;
|
| +}
|
| +
|
| +/*
|
| +** Add a new element to the pAggInfo->aCol[] array. Return the index of
|
| +** the new element. Return a negative number if malloc fails.
|
| +*/
|
| +static int addAggInfoColumn(sqlite3 *db, AggInfo *pInfo){
|
| + int i;
|
| + pInfo->aCol = sqlite3ArrayAllocate(
|
| + db,
|
| + pInfo->aCol,
|
| + sizeof(pInfo->aCol[0]),
|
| + &pInfo->nColumn,
|
| + &i
|
| + );
|
| + return i;
|
| +}
|
| +
|
| +/*
|
| +** Add a new element to the pAggInfo->aFunc[] array. Return the index of
|
| +** the new element. Return a negative number if malloc fails.
|
| +*/
|
| +static int addAggInfoFunc(sqlite3 *db, AggInfo *pInfo){
|
| + int i;
|
| + pInfo->aFunc = sqlite3ArrayAllocate(
|
| + db,
|
| + pInfo->aFunc,
|
| + sizeof(pInfo->aFunc[0]),
|
| + &pInfo->nFunc,
|
| + &i
|
| + );
|
| + return i;
|
| +}
|
| +
|
| +/*
|
| +** This is the xExprCallback for a tree walker. It is used to
|
| +** implement sqlite3ExprAnalyzeAggregates(). See sqlite3ExprAnalyzeAggregates
|
| +** for additional information.
|
| +*/
|
| +static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
|
| + int i;
|
| + NameContext *pNC = pWalker->u.pNC;
|
| + Parse *pParse = pNC->pParse;
|
| + SrcList *pSrcList = pNC->pSrcList;
|
| + AggInfo *pAggInfo = pNC->pAggInfo;
|
| +
|
| + switch( pExpr->op ){
|
| + case TK_AGG_COLUMN:
|
| + case TK_COLUMN: {
|
| + testcase( pExpr->op==TK_AGG_COLUMN );
|
| + testcase( pExpr->op==TK_COLUMN );
|
| + /* Check to see if the column is in one of the tables in the FROM
|
| + ** clause of the aggregate query */
|
| + if( ALWAYS(pSrcList!=0) ){
|
| + struct SrcList_item *pItem = pSrcList->a;
|
| + for(i=0; i<pSrcList->nSrc; i++, pItem++){
|
| + struct AggInfo_col *pCol;
|
| + assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) );
|
| + if( pExpr->iTable==pItem->iCursor ){
|
| + /* If we reach this point, it means that pExpr refers to a table
|
| + ** that is in the FROM clause of the aggregate query.
|
| + **
|
| + ** Make an entry for the column in pAggInfo->aCol[] if there
|
| + ** is not an entry there already.
|
| + */
|
| + int k;
|
| + pCol = pAggInfo->aCol;
|
| + for(k=0; k<pAggInfo->nColumn; k++, pCol++){
|
| + if( pCol->iTable==pExpr->iTable &&
|
| + pCol->iColumn==pExpr->iColumn ){
|
| + break;
|
| + }
|
| + }
|
| + if( (k>=pAggInfo->nColumn)
|
| + && (k = addAggInfoColumn(pParse->db, pAggInfo))>=0
|
| + ){
|
| + pCol = &pAggInfo->aCol[k];
|
| + pCol->pTab = pExpr->pTab;
|
| + pCol->iTable = pExpr->iTable;
|
| + pCol->iColumn = pExpr->iColumn;
|
| + pCol->iMem = ++pParse->nMem;
|
| + pCol->iSorterColumn = -1;
|
| + pCol->pExpr = pExpr;
|
| + if( pAggInfo->pGroupBy ){
|
| + int j, n;
|
| + ExprList *pGB = pAggInfo->pGroupBy;
|
| + struct ExprList_item *pTerm = pGB->a;
|
| + n = pGB->nExpr;
|
| + for(j=0; j<n; j++, pTerm++){
|
| + Expr *pE = pTerm->pExpr;
|
| + if( pE->op==TK_COLUMN && pE->iTable==pExpr->iTable &&
|
| + pE->iColumn==pExpr->iColumn ){
|
| + pCol->iSorterColumn = j;
|
| + break;
|
| + }
|
| + }
|
| + }
|
| + if( pCol->iSorterColumn<0 ){
|
| + pCol->iSorterColumn = pAggInfo->nSortingColumn++;
|
| + }
|
| + }
|
| + /* There is now an entry for pExpr in pAggInfo->aCol[] (either
|
| + ** because it was there before or because we just created it).
|
| + ** Convert the pExpr to be a TK_AGG_COLUMN referring to that
|
| + ** pAggInfo->aCol[] entry.
|
| + */
|
| + ExprSetVVAProperty(pExpr, EP_NoReduce);
|
| + pExpr->pAggInfo = pAggInfo;
|
| + pExpr->op = TK_AGG_COLUMN;
|
| + pExpr->iAgg = (i16)k;
|
| + break;
|
| + } /* endif pExpr->iTable==pItem->iCursor */
|
| + } /* end loop over pSrcList */
|
| + }
|
| + return WRC_Prune;
|
| + }
|
| + case TK_AGG_FUNCTION: {
|
| + if( (pNC->ncFlags & NC_InAggFunc)==0
|
| + && pWalker->walkerDepth==pExpr->op2
|
| + ){
|
| + /* Check to see if pExpr is a duplicate of another aggregate
|
| + ** function that is already in the pAggInfo structure
|
| + */
|
| + struct AggInfo_func *pItem = pAggInfo->aFunc;
|
| + for(i=0; i<pAggInfo->nFunc; i++, pItem++){
|
| + if( sqlite3ExprCompare(pItem->pExpr, pExpr, -1)==0 ){
|
| + break;
|
| + }
|
| + }
|
| + if( i>=pAggInfo->nFunc ){
|
| + /* pExpr is original. Make a new entry in pAggInfo->aFunc[]
|
| + */
|
| + u8 enc = ENC(pParse->db);
|
| + i = addAggInfoFunc(pParse->db, pAggInfo);
|
| + if( i>=0 ){
|
| + assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
|
| + pItem = &pAggInfo->aFunc[i];
|
| + pItem->pExpr = pExpr;
|
| + pItem->iMem = ++pParse->nMem;
|
| + assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
| + pItem->pFunc = sqlite3FindFunction(pParse->db,
|
| + pExpr->u.zToken, sqlite3Strlen30(pExpr->u.zToken),
|
| + pExpr->x.pList ? pExpr->x.pList->nExpr : 0, enc, 0);
|
| + if( pExpr->flags & EP_Distinct ){
|
| + pItem->iDistinct = pParse->nTab++;
|
| + }else{
|
| + pItem->iDistinct = -1;
|
| + }
|
| + }
|
| + }
|
| + /* Make pExpr point to the appropriate pAggInfo->aFunc[] entry
|
| + */
|
| + assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) );
|
| + ExprSetVVAProperty(pExpr, EP_NoReduce);
|
| + pExpr->iAgg = (i16)i;
|
| + pExpr->pAggInfo = pAggInfo;
|
| + return WRC_Prune;
|
| + }else{
|
| + return WRC_Continue;
|
| + }
|
| + }
|
| + }
|
| + return WRC_Continue;
|
| +}
|
| +static int analyzeAggregatesInSelect(Walker *pWalker, Select *pSelect){
|
| + UNUSED_PARAMETER(pWalker);
|
| + UNUSED_PARAMETER(pSelect);
|
| + return WRC_Continue;
|
| +}
|
| +
|
| +/*
|
| +** Analyze the pExpr expression looking for aggregate functions and
|
| +** for variables that need to be added to AggInfo object that pNC->pAggInfo
|
| +** points to. Additional entries are made on the AggInfo object as
|
| +** necessary.
|
| +**
|
| +** This routine should only be called after the expression has been
|
| +** analyzed by sqlite3ResolveExprNames().
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){
|
| + Walker w;
|
| + memset(&w, 0, sizeof(w));
|
| + w.xExprCallback = analyzeAggregate;
|
| + w.xSelectCallback = analyzeAggregatesInSelect;
|
| + w.u.pNC = pNC;
|
| + assert( pNC->pSrcList!=0 );
|
| + sqlite3WalkExpr(&w, pExpr);
|
| +}
|
| +
|
| +/*
|
| +** Call sqlite3ExprAnalyzeAggregates() for every expression in an
|
| +** expression list. Return the number of errors.
|
| +**
|
| +** If an error is found, the analysis is cut short.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext *pNC, ExprList *pList){
|
| + struct ExprList_item *pItem;
|
| + int i;
|
| + if( pList ){
|
| + for(pItem=pList->a, i=0; i<pList->nExpr; i++, pItem++){
|
| + sqlite3ExprAnalyzeAggregates(pNC, pItem->pExpr);
|
| + }
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Allocate a single new register for use to hold some intermediate result.
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3GetTempReg(Parse *pParse){
|
| + if( pParse->nTempReg==0 ){
|
| + return ++pParse->nMem;
|
| + }
|
| + return pParse->aTempReg[--pParse->nTempReg];
|
| +}
|
| +
|
| +/*
|
| +** Deallocate a register, making available for reuse for some other
|
| +** purpose.
|
| +**
|
| +** If a register is currently being used by the column cache, then
|
| +** the deallocation is deferred until the column cache line that uses
|
| +** the register becomes stale.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3ReleaseTempReg(Parse *pParse, int iReg){
|
| + if( iReg && pParse->nTempReg<ArraySize(pParse->aTempReg) ){
|
| + int i;
|
| + struct yColCache *p;
|
| + for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
|
| + if( p->iReg==iReg ){
|
| + p->tempReg = 1;
|
| + return;
|
| + }
|
| + }
|
| + pParse->aTempReg[pParse->nTempReg++] = iReg;
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Allocate or deallocate a block of nReg consecutive registers
|
| +*/
|
| +SQLITE_PRIVATE int sqlite3GetTempRange(Parse *pParse, int nReg){
|
| + int i, n;
|
| + i = pParse->iRangeReg;
|
| + n = pParse->nRangeReg;
|
| + if( nReg<=n ){
|
| + assert( !usedAsColumnCache(pParse, i, i+n-1) );
|
| + pParse->iRangeReg += nReg;
|
| + pParse->nRangeReg -= nReg;
|
| + }else{
|
| + i = pParse->nMem+1;
|
| + pParse->nMem += nReg;
|
| + }
|
| + return i;
|
| +}
|
| +SQLITE_PRIVATE void sqlite3ReleaseTempRange(Parse *pParse, int iReg, int nReg){
|
| + sqlite3ExprCacheRemove(pParse, iReg, nReg);
|
| + if( nReg>pParse->nRangeReg ){
|
| + pParse->nRangeReg = nReg;
|
| + pParse->iRangeReg = iReg;
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** Mark all temporary registers as being unavailable for reuse.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3ClearTempRegCache(Parse *pParse){
|
| + pParse->nTempReg = 0;
|
| + pParse->nRangeReg = 0;
|
| +}
|
| +
|
| +/************** End of expr.c ************************************************/
|
| +/************** Begin file alter.c *******************************************/
|
| +/*
|
| +** 2005 February 15
|
| +**
|
| +** 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.
|
| +**
|
| +*************************************************************************
|
| +** This file contains C code routines that used to generate VDBE code
|
| +** that implements the ALTER TABLE command.
|
| +*/
|
| +/* #include "sqliteInt.h" */
|
| +
|
| +/*
|
| +** The code in this file only exists if we are not omitting the
|
| +** ALTER TABLE logic from the build.
|
| +*/
|
| +#ifndef SQLITE_OMIT_ALTERTABLE
|
| +
|
| +
|
| +/*
|
| +** This function is used by SQL generated to implement the
|
| +** ALTER TABLE command. The first argument is the text of a CREATE TABLE or
|
| +** CREATE INDEX command. The second is a table name. The table name in
|
| +** the CREATE TABLE or CREATE INDEX statement is replaced with the third
|
| +** argument and the result returned. Examples:
|
| +**
|
| +** sqlite_rename_table('CREATE TABLE abc(a, b, c)', 'def')
|
| +** -> 'CREATE TABLE def(a, b, c)'
|
| +**
|
| +** sqlite_rename_table('CREATE INDEX i ON abc(a)', 'def')
|
| +** -> 'CREATE INDEX i ON def(a, b, c)'
|
| +*/
|
| +static void renameTableFunc(
|
| + sqlite3_context *context,
|
| + int NotUsed,
|
| + sqlite3_value **argv
|
| +){
|
| + unsigned char const *zSql = sqlite3_value_text(argv[0]);
|
| + unsigned char const *zTableName = sqlite3_value_text(argv[1]);
|
| +
|
| + int token;
|
| + Token tname;
|
| + unsigned char const *zCsr = zSql;
|
| + int len = 0;
|
| + char *zRet;
|
| +
|
| + sqlite3 *db = sqlite3_context_db_handle(context);
|
| +
|
| + UNUSED_PARAMETER(NotUsed);
|
| +
|
| + /* The principle used to locate the table name in the CREATE TABLE
|
| + ** statement is that the table name is the first non-space token that
|
| + ** is immediately followed by a TK_LP or TK_USING token.
|
| + */
|
| + if( zSql ){
|
| + do {
|
| + if( !*zCsr ){
|
| + /* Ran out of input before finding an opening bracket. Return NULL. */
|
| + return;
|
| + }
|
| +
|
| + /* Store the token that zCsr points to in tname. */
|
| + tname.z = (char*)zCsr;
|
| + tname.n = len;
|
| +
|
| + /* Advance zCsr to the next token. Store that token type in 'token',
|
| + ** and its length in 'len' (to be used next iteration of this loop).
|
| + */
|
| + do {
|
| + zCsr += len;
|
| + len = sqlite3GetToken(zCsr, &token);
|
| + } while( token==TK_SPACE );
|
| + assert( len>0 );
|
| + } while( token!=TK_LP && token!=TK_USING );
|
| +
|
| + zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", (int)(((u8*)tname.z) - zSql),
|
| + zSql, zTableName, tname.z+tname.n);
|
| + sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC);
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** This C function implements an SQL user function that is used by SQL code
|
| +** generated by the ALTER TABLE ... RENAME command to modify the definition
|
| +** of any foreign key constraints that use the table being renamed as the
|
| +** parent table. It is passed three arguments:
|
| +**
|
| +** 1) The complete text of the CREATE TABLE statement being modified,
|
| +** 2) The old name of the table being renamed, and
|
| +** 3) The new name of the table being renamed.
|
| +**
|
| +** It returns the new CREATE TABLE statement. For example:
|
| +**
|
| +** sqlite_rename_parent('CREATE TABLE t1(a REFERENCES t2)', 't2', 't3')
|
| +** -> 'CREATE TABLE t1(a REFERENCES t3)'
|
| +*/
|
| +#ifndef SQLITE_OMIT_FOREIGN_KEY
|
| +static void renameParentFunc(
|
| + sqlite3_context *context,
|
| + int NotUsed,
|
| + sqlite3_value **argv
|
| +){
|
| + sqlite3 *db = sqlite3_context_db_handle(context);
|
| + char *zOutput = 0;
|
| + char *zResult;
|
| + unsigned char const *zInput = sqlite3_value_text(argv[0]);
|
| + unsigned char const *zOld = sqlite3_value_text(argv[1]);
|
| + unsigned char const *zNew = sqlite3_value_text(argv[2]);
|
| +
|
| + unsigned const char *z; /* Pointer to token */
|
| + int n; /* Length of token z */
|
| + int token; /* Type of token */
|
| +
|
| + UNUSED_PARAMETER(NotUsed);
|
| + if( zInput==0 || zOld==0 ) return;
|
| + for(z=zInput; *z; z=z+n){
|
| + n = sqlite3GetToken(z, &token);
|
| + if( token==TK_REFERENCES ){
|
| + char *zParent;
|
| + do {
|
| + z += n;
|
| + n = sqlite3GetToken(z, &token);
|
| + }while( token==TK_SPACE );
|
| +
|
| + if( token==TK_ILLEGAL ) break;
|
| + zParent = sqlite3DbStrNDup(db, (const char *)z, n);
|
| + if( zParent==0 ) break;
|
| + sqlite3Dequote(zParent);
|
| + if( 0==sqlite3StrICmp((const char *)zOld, zParent) ){
|
| + char *zOut = sqlite3MPrintf(db, "%s%.*s\"%w\"",
|
| + (zOutput?zOutput:""), (int)(z-zInput), zInput, (const char *)zNew
|
| + );
|
| + sqlite3DbFree(db, zOutput);
|
| + zOutput = zOut;
|
| + zInput = &z[n];
|
| + }
|
| + sqlite3DbFree(db, zParent);
|
| + }
|
| + }
|
| +
|
| + zResult = sqlite3MPrintf(db, "%s%s", (zOutput?zOutput:""), zInput),
|
| + sqlite3_result_text(context, zResult, -1, SQLITE_DYNAMIC);
|
| + sqlite3DbFree(db, zOutput);
|
| +}
|
| +#endif
|
| +
|
| +#ifndef SQLITE_OMIT_TRIGGER
|
| +/* This function is used by SQL generated to implement the
|
| +** ALTER TABLE command. The first argument is the text of a CREATE TRIGGER
|
| +** statement. The second is a table name. The table name in the CREATE
|
| +** TRIGGER statement is replaced with the third argument and the result
|
| +** returned. This is analagous to renameTableFunc() above, except for CREATE
|
| +** TRIGGER, not CREATE INDEX and CREATE TABLE.
|
| +*/
|
| +static void renameTriggerFunc(
|
| + sqlite3_context *context,
|
| + int NotUsed,
|
| + sqlite3_value **argv
|
| +){
|
| + unsigned char const *zSql = sqlite3_value_text(argv[0]);
|
| + unsigned char const *zTableName = sqlite3_value_text(argv[1]);
|
| +
|
| + int token;
|
| + Token tname;
|
| + int dist = 3;
|
| + unsigned char const *zCsr = zSql;
|
| + int len = 0;
|
| + char *zRet;
|
| + sqlite3 *db = sqlite3_context_db_handle(context);
|
| +
|
| + UNUSED_PARAMETER(NotUsed);
|
| +
|
| + /* The principle used to locate the table name in the CREATE TRIGGER
|
| + ** statement is that the table name is the first token that is immediately
|
| + ** preceded by either TK_ON or TK_DOT and immediately followed by one
|
| + ** of TK_WHEN, TK_BEGIN or TK_FOR.
|
| + */
|
| + if( zSql ){
|
| + do {
|
| +
|
| + if( !*zCsr ){
|
| + /* Ran out of input before finding the table name. Return NULL. */
|
| + return;
|
| + }
|
| +
|
| + /* Store the token that zCsr points to in tname. */
|
| + tname.z = (char*)zCsr;
|
| + tname.n = len;
|
| +
|
| + /* Advance zCsr to the next token. Store that token type in 'token',
|
| + ** and its length in 'len' (to be used next iteration of this loop).
|
| + */
|
| + do {
|
| + zCsr += len;
|
| + len = sqlite3GetToken(zCsr, &token);
|
| + }while( token==TK_SPACE );
|
| + assert( len>0 );
|
| +
|
| + /* Variable 'dist' stores the number of tokens read since the most
|
| + ** recent TK_DOT or TK_ON. This means that when a WHEN, FOR or BEGIN
|
| + ** token is read and 'dist' equals 2, the condition stated above
|
| + ** to be met.
|
| + **
|
| + ** Note that ON cannot be a database, table or column name, so
|
| + ** there is no need to worry about syntax like
|
| + ** "CREATE TRIGGER ... ON ON.ON BEGIN ..." etc.
|
| + */
|
| + dist++;
|
| + if( token==TK_DOT || token==TK_ON ){
|
| + dist = 0;
|
| + }
|
| + } while( dist!=2 || (token!=TK_WHEN && token!=TK_FOR && token!=TK_BEGIN) );
|
| +
|
| + /* Variable tname now contains the token that is the old table-name
|
| + ** in the CREATE TRIGGER statement.
|
| + */
|
| + zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", (int)(((u8*)tname.z) - zSql),
|
| + zSql, zTableName, tname.z+tname.n);
|
| + sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC);
|
| + }
|
| +}
|
| +#endif /* !SQLITE_OMIT_TRIGGER */
|
| +
|
| +/*
|
| +** Register built-in functions used to help implement ALTER TABLE
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3AlterFunctions(void){
|
| + static SQLITE_WSD FuncDef aAlterTableFuncs[] = {
|
| + FUNCTION(sqlite_rename_table, 2, 0, 0, renameTableFunc),
|
| +#ifndef SQLITE_OMIT_TRIGGER
|
| + FUNCTION(sqlite_rename_trigger, 2, 0, 0, renameTriggerFunc),
|
| +#endif
|
| +#ifndef SQLITE_OMIT_FOREIGN_KEY
|
| + FUNCTION(sqlite_rename_parent, 3, 0, 0, renameParentFunc),
|
| +#endif
|
| + };
|
| + int i;
|
| + FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
|
| + FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aAlterTableFuncs);
|
| +
|
| + for(i=0; i<ArraySize(aAlterTableFuncs); i++){
|
| + sqlite3FuncDefInsert(pHash, &aFunc[i]);
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** This function is used to create the text of expressions of the form:
|
| +**
|
| +** name=<constant1> OR name=<constant2> OR ...
|
| +**
|
| +** If argument zWhere is NULL, then a pointer string containing the text
|
| +** "name=<constant>" is returned, where <constant> is the quoted version
|
| +** of the string passed as argument zConstant. The returned buffer is
|
| +** allocated using sqlite3DbMalloc(). It is the responsibility of the
|
| +** caller to ensure that it is eventually freed.
|
| +**
|
| +** If argument zWhere is not NULL, then the string returned is
|
| +** "<where> OR name=<constant>", where <where> is the contents of zWhere.
|
| +** In this case zWhere is passed to sqlite3DbFree() before returning.
|
| +**
|
| +*/
|
| +static char *whereOrName(sqlite3 *db, char *zWhere, char *zConstant){
|
| + char *zNew;
|
| + if( !zWhere ){
|
| + zNew = sqlite3MPrintf(db, "name=%Q", zConstant);
|
| + }else{
|
| + zNew = sqlite3MPrintf(db, "%s OR name=%Q", zWhere, zConstant);
|
| + sqlite3DbFree(db, zWhere);
|
| + }
|
| + return zNew;
|
| +}
|
| +
|
| +#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
|
| +/*
|
| +** Generate the text of a WHERE expression which can be used to select all
|
| +** tables that have foreign key constraints that refer to table pTab (i.e.
|
| +** constraints for which pTab is the parent table) from the sqlite_master
|
| +** table.
|
| +*/
|
| +static char *whereForeignKeys(Parse *pParse, Table *pTab){
|
| + FKey *p;
|
| + char *zWhere = 0;
|
| + for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){
|
| + zWhere = whereOrName(pParse->db, zWhere, p->pFrom->zName);
|
| + }
|
| + return zWhere;
|
| +}
|
| +#endif
|
| +
|
| +/*
|
| +** Generate the text of a WHERE expression which can be used to select all
|
| +** temporary triggers on table pTab from the sqlite_temp_master table. If
|
| +** table pTab has no temporary triggers, or is itself stored in the
|
| +** temporary database, NULL is returned.
|
| +*/
|
| +static char *whereTempTriggers(Parse *pParse, Table *pTab){
|
| + Trigger *pTrig;
|
| + char *zWhere = 0;
|
| + const Schema *pTempSchema = pParse->db->aDb[1].pSchema; /* Temp db schema */
|
| +
|
| + /* If the table is not located in the temp-db (in which case NULL is
|
| + ** returned, loop through the tables list of triggers. For each trigger
|
| + ** that is not part of the temp-db schema, add a clause to the WHERE
|
| + ** expression being built up in zWhere.
|
| + */
|
| + if( pTab->pSchema!=pTempSchema ){
|
| + sqlite3 *db = pParse->db;
|
| + for(pTrig=sqlite3TriggerList(pParse, pTab); pTrig; pTrig=pTrig->pNext){
|
| + if( pTrig->pSchema==pTempSchema ){
|
| + zWhere = whereOrName(db, zWhere, pTrig->zName);
|
| + }
|
| + }
|
| + }
|
| + if( zWhere ){
|
| + char *zNew = sqlite3MPrintf(pParse->db, "type='trigger' AND (%s)", zWhere);
|
| + sqlite3DbFree(pParse->db, zWhere);
|
| + zWhere = zNew;
|
| + }
|
| + return zWhere;
|
| +}
|
| +
|
| +/*
|
| +** Generate code to drop and reload the internal representation of table
|
| +** pTab from the database, including triggers and temporary triggers.
|
| +** Argument zName is the name of the table in the database schema at
|
| +** the time the generated code is executed. This can be different from
|
| +** pTab->zName if this function is being called to code part of an
|
| +** "ALTER TABLE RENAME TO" statement.
|
| +*/
|
| +static void reloadTableSchema(Parse *pParse, Table *pTab, const char *zName){
|
| + Vdbe *v;
|
| + char *zWhere;
|
| + int iDb; /* Index of database containing pTab */
|
| +#ifndef SQLITE_OMIT_TRIGGER
|
| + Trigger *pTrig;
|
| +#endif
|
| +
|
| + v = sqlite3GetVdbe(pParse);
|
| + if( NEVER(v==0) ) return;
|
| + assert( sqlite3BtreeHoldsAllMutexes(pParse->db) );
|
| + iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
|
| + assert( iDb>=0 );
|
| +
|
| +#ifndef SQLITE_OMIT_TRIGGER
|
| + /* Drop any table triggers from the internal schema. */
|
| + for(pTrig=sqlite3TriggerList(pParse, pTab); pTrig; pTrig=pTrig->pNext){
|
| + int iTrigDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema);
|
| + assert( iTrigDb==iDb || iTrigDb==1 );
|
| + sqlite3VdbeAddOp4(v, OP_DropTrigger, iTrigDb, 0, 0, pTrig->zName, 0);
|
| + }
|
| +#endif
|
| +
|
| + /* Drop the table and index from the internal schema. */
|
| + sqlite3VdbeAddOp4(v, OP_DropTable, iDb, 0, 0, pTab->zName, 0);
|
| +
|
| + /* Reload the table, index and permanent trigger schemas. */
|
| + zWhere = sqlite3MPrintf(pParse->db, "tbl_name=%Q", zName);
|
| + if( !zWhere ) return;
|
| + sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere);
|
| +
|
| +#ifndef SQLITE_OMIT_TRIGGER
|
| + /* Now, if the table is not stored in the temp database, reload any temp
|
| + ** triggers. Don't use IN(...) in case SQLITE_OMIT_SUBQUERY is defined.
|
| + */
|
| + if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){
|
| + sqlite3VdbeAddParseSchemaOp(v, 1, zWhere);
|
| + }
|
| +#endif
|
| +}
|
| +
|
| +/*
|
| +** Parameter zName is the name of a table that is about to be altered
|
| +** (either with ALTER TABLE ... RENAME TO or ALTER TABLE ... ADD COLUMN).
|
| +** If the table is a system table, this function leaves an error message
|
| +** in pParse->zErr (system tables may not be altered) and returns non-zero.
|
| +**
|
| +** Or, if zName is not a system table, zero is returned.
|
| +*/
|
| +static int isSystemTable(Parse *pParse, const char *zName){
|
| + if( sqlite3Strlen30(zName)>6 && 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){
|
| + sqlite3ErrorMsg(pParse, "table %s may not be altered", zName);
|
| + return 1;
|
| + }
|
| + return 0;
|
| +}
|
| +
|
| +/*
|
| +** Generate code to implement the "ALTER TABLE xxx RENAME TO yyy"
|
| +** command.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3AlterRenameTable(
|
| + Parse *pParse, /* Parser context. */
|
| + SrcList *pSrc, /* The table to rename. */
|
| + Token *pName /* The new table name. */
|
| +){
|
| + int iDb; /* Database that contains the table */
|
| + char *zDb; /* Name of database iDb */
|
| + Table *pTab; /* Table being renamed */
|
| + char *zName = 0; /* NULL-terminated version of pName */
|
| + sqlite3 *db = pParse->db; /* Database connection */
|
| + int nTabName; /* Number of UTF-8 characters in zTabName */
|
| + const char *zTabName; /* Original name of the table */
|
| + Vdbe *v;
|
| +#ifndef SQLITE_OMIT_TRIGGER
|
| + char *zWhere = 0; /* Where clause to locate temp triggers */
|
| +#endif
|
| + VTable *pVTab = 0; /* Non-zero if this is a v-tab with an xRename() */
|
| + int savedDbFlags; /* Saved value of db->flags */
|
| +
|
| + savedDbFlags = db->flags;
|
| + if( NEVER(db->mallocFailed) ) goto exit_rename_table;
|
| + assert( pSrc->nSrc==1 );
|
| + assert( sqlite3BtreeHoldsAllMutexes(pParse->db) );
|
| +
|
| + pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]);
|
| + if( !pTab ) goto exit_rename_table;
|
| + iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
|
| + zDb = db->aDb[iDb].zName;
|
| + db->flags |= SQLITE_PreferBuiltin;
|
| +
|
| + /* Get a NULL terminated version of the new table name. */
|
| + zName = sqlite3NameFromToken(db, pName);
|
| + if( !zName ) goto exit_rename_table;
|
| +
|
| + /* Check that a table or index named 'zName' does not already exist
|
| + ** in database iDb. If so, this is an error.
|
| + */
|
| + if( sqlite3FindTable(db, zName, zDb) || sqlite3FindIndex(db, zName, zDb) ){
|
| + sqlite3ErrorMsg(pParse,
|
| + "there is already another table or index with this name: %s", zName);
|
| + goto exit_rename_table;
|
| + }
|
| +
|
| + /* Make sure it is not a system table being altered, or a reserved name
|
| + ** that the table is being renamed to.
|
| + */
|
| + if( SQLITE_OK!=isSystemTable(pParse, pTab->zName) ){
|
| + goto exit_rename_table;
|
| + }
|
| + if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ goto
|
| + exit_rename_table;
|
| + }
|
| +
|
| +#ifndef SQLITE_OMIT_VIEW
|
| + if( pTab->pSelect ){
|
| + sqlite3ErrorMsg(pParse, "view %s may not be altered", pTab->zName);
|
| + goto exit_rename_table;
|
| + }
|
| +#endif
|
| +
|
| +#ifndef SQLITE_OMIT_AUTHORIZATION
|
| + /* Invoke the authorization callback. */
|
| + if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){
|
| + goto exit_rename_table;
|
| + }
|
| +#endif
|
| +
|
| +#ifndef SQLITE_OMIT_VIRTUALTABLE
|
| + if( sqlite3ViewGetColumnNames(pParse, pTab) ){
|
| + goto exit_rename_table;
|
| + }
|
| + if( IsVirtual(pTab) ){
|
| + pVTab = sqlite3GetVTable(db, pTab);
|
| + if( pVTab->pVtab->pModule->xRename==0 ){
|
| + pVTab = 0;
|
| + }
|
| + }
|
| +#endif
|
| +
|
| + /* Begin a transaction for database iDb.
|
| + ** Then modify the schema cookie (since the ALTER TABLE modifies the
|
| + ** schema). Open a statement transaction if the table is a virtual
|
| + ** table.
|
| + */
|
| + v = sqlite3GetVdbe(pParse);
|
| + if( v==0 ){
|
| + goto exit_rename_table;
|
| + }
|
| + sqlite3BeginWriteOperation(pParse, pVTab!=0, iDb);
|
| + sqlite3ChangeCookie(pParse, iDb);
|
| +
|
| + /* If this is a virtual table, invoke the xRename() function if
|
| + ** one is defined. The xRename() callback will modify the names
|
| + ** of any resources used by the v-table implementation (including other
|
| + ** SQLite tables) that are identified by the name of the virtual table.
|
| + */
|
| +#ifndef SQLITE_OMIT_VIRTUALTABLE
|
| + if( pVTab ){
|
| + int i = ++pParse->nMem;
|
| + sqlite3VdbeLoadString(v, i, zName);
|
| + sqlite3VdbeAddOp4(v, OP_VRename, i, 0, 0,(const char*)pVTab, P4_VTAB);
|
| + sqlite3MayAbort(pParse);
|
| + }
|
| +#endif
|
| +
|
| + /* figure out how many UTF-8 characters are in zName */
|
| + zTabName = pTab->zName;
|
| + nTabName = sqlite3Utf8CharLen(zTabName, -1);
|
| +
|
| +#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
|
| + if( db->flags&SQLITE_ForeignKeys ){
|
| + /* If foreign-key support is enabled, rewrite the CREATE TABLE
|
| + ** statements corresponding to all child tables of foreign key constraints
|
| + ** for which the renamed table is the parent table. */
|
| + if( (zWhere=whereForeignKeys(pParse, pTab))!=0 ){
|
| + sqlite3NestedParse(pParse,
|
| + "UPDATE \"%w\".%s SET "
|
| + "sql = sqlite_rename_parent(sql, %Q, %Q) "
|
| + "WHERE %s;", zDb, SCHEMA_TABLE(iDb), zTabName, zName, zWhere);
|
| + sqlite3DbFree(db, zWhere);
|
| + }
|
| + }
|
| +#endif
|
| +
|
| + /* Modify the sqlite_master table to use the new table name. */
|
| + sqlite3NestedParse(pParse,
|
| + "UPDATE %Q.%s SET "
|
| +#ifdef SQLITE_OMIT_TRIGGER
|
| + "sql = sqlite_rename_table(sql, %Q), "
|
| +#else
|
| + "sql = CASE "
|
| + "WHEN type = 'trigger' THEN sqlite_rename_trigger(sql, %Q)"
|
| + "ELSE sqlite_rename_table(sql, %Q) END, "
|
| +#endif
|
| + "tbl_name = %Q, "
|
| + "name = CASE "
|
| + "WHEN type='table' THEN %Q "
|
| + "WHEN name LIKE 'sqlite_autoindex%%' AND type='index' THEN "
|
| + "'sqlite_autoindex_' || %Q || substr(name,%d+18) "
|
| + "ELSE name END "
|
| + "WHERE tbl_name=%Q COLLATE nocase AND "
|
| + "(type='table' OR type='index' OR type='trigger');",
|
| + zDb, SCHEMA_TABLE(iDb), zName, zName, zName,
|
| +#ifndef SQLITE_OMIT_TRIGGER
|
| + zName,
|
| +#endif
|
| + zName, nTabName, zTabName
|
| + );
|
| +
|
| +#ifndef SQLITE_OMIT_AUTOINCREMENT
|
| + /* If the sqlite_sequence table exists in this database, then update
|
| + ** it with the new table name.
|
| + */
|
| + if( sqlite3FindTable(db, "sqlite_sequence", zDb) ){
|
| + sqlite3NestedParse(pParse,
|
| + "UPDATE \"%w\".sqlite_sequence set name = %Q WHERE name = %Q",
|
| + zDb, zName, pTab->zName);
|
| + }
|
| +#endif
|
| +
|
| +#ifndef SQLITE_OMIT_TRIGGER
|
| + /* If there are TEMP triggers on this table, modify the sqlite_temp_master
|
| + ** table. Don't do this if the table being ALTERed is itself located in
|
| + ** the temp database.
|
| + */
|
| + if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){
|
| + sqlite3NestedParse(pParse,
|
| + "UPDATE sqlite_temp_master SET "
|
| + "sql = sqlite_rename_trigger(sql, %Q), "
|
| + "tbl_name = %Q "
|
| + "WHERE %s;", zName, zName, zWhere);
|
| + sqlite3DbFree(db, zWhere);
|
| + }
|
| +#endif
|
| +
|
| +#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
|
| + if( db->flags&SQLITE_ForeignKeys ){
|
| + FKey *p;
|
| + for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){
|
| + Table *pFrom = p->pFrom;
|
| + if( pFrom!=pTab ){
|
| + reloadTableSchema(pParse, p->pFrom, pFrom->zName);
|
| + }
|
| + }
|
| + }
|
| +#endif
|
| +
|
| + /* Drop and reload the internal table schema. */
|
| + reloadTableSchema(pParse, pTab, zName);
|
| +
|
| +exit_rename_table:
|
| + sqlite3SrcListDelete(db, pSrc);
|
| + sqlite3DbFree(db, zName);
|
| + db->flags = savedDbFlags;
|
| +}
|
| +
|
| +
|
| +/*
|
| +** Generate code to make sure the file format number is at least minFormat.
|
| +** The generated code will increase the file format number if necessary.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3MinimumFileFormat(Parse *pParse, int iDb, int minFormat){
|
| + Vdbe *v;
|
| + v = sqlite3GetVdbe(pParse);
|
| + /* The VDBE should have been allocated before this routine is called.
|
| + ** If that allocation failed, we would have quit before reaching this
|
| + ** point */
|
| + if( ALWAYS(v) ){
|
| + int r1 = sqlite3GetTempReg(pParse);
|
| + int r2 = sqlite3GetTempReg(pParse);
|
| + int addr1;
|
| + sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, r1, BTREE_FILE_FORMAT);
|
| + sqlite3VdbeUsesBtree(v, iDb);
|
| + sqlite3VdbeAddOp2(v, OP_Integer, minFormat, r2);
|
| + addr1 = sqlite3VdbeAddOp3(v, OP_Ge, r2, 0, r1);
|
| + sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); VdbeCoverage(v);
|
| + sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, r2);
|
| + sqlite3VdbeJumpHere(v, addr1);
|
| + sqlite3ReleaseTempReg(pParse, r1);
|
| + sqlite3ReleaseTempReg(pParse, r2);
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** This function is called after an "ALTER TABLE ... ADD" statement
|
| +** has been parsed. Argument pColDef contains the text of the new
|
| +** column definition.
|
| +**
|
| +** The Table structure pParse->pNewTable was extended to include
|
| +** the new column during parsing.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
|
| + Table *pNew; /* Copy of pParse->pNewTable */
|
| + Table *pTab; /* Table being altered */
|
| + int iDb; /* Database number */
|
| + const char *zDb; /* Database name */
|
| + const char *zTab; /* Table name */
|
| + char *zCol; /* Null-terminated column definition */
|
| + Column *pCol; /* The new column */
|
| + Expr *pDflt; /* Default value for the new column */
|
| + sqlite3 *db; /* The database connection; */
|
| +
|
| + db = pParse->db;
|
| + if( pParse->nErr || db->mallocFailed ) return;
|
| + pNew = pParse->pNewTable;
|
| + assert( pNew );
|
| +
|
| + assert( sqlite3BtreeHoldsAllMutexes(db) );
|
| + iDb = sqlite3SchemaToIndex(db, pNew->pSchema);
|
| + zDb = db->aDb[iDb].zName;
|
| + zTab = &pNew->zName[16]; /* Skip the "sqlite_altertab_" prefix on the name */
|
| + pCol = &pNew->aCol[pNew->nCol-1];
|
| + pDflt = pCol->pDflt;
|
| + pTab = sqlite3FindTable(db, zTab, zDb);
|
| + assert( pTab );
|
| +
|
| +#ifndef SQLITE_OMIT_AUTHORIZATION
|
| + /* Invoke the authorization callback. */
|
| + if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){
|
| + return;
|
| + }
|
| +#endif
|
| +
|
| + /* If the default value for the new column was specified with a
|
| + ** literal NULL, then set pDflt to 0. This simplifies checking
|
| + ** for an SQL NULL default below.
|
| + */
|
| + if( pDflt && pDflt->op==TK_NULL ){
|
| + pDflt = 0;
|
| + }
|
| +
|
| + /* Check that the new column is not specified as PRIMARY KEY or UNIQUE.
|
| + ** If there is a NOT NULL constraint, then the default value for the
|
| + ** column must not be NULL.
|
| + */
|
| + if( pCol->colFlags & COLFLAG_PRIMKEY ){
|
| + sqlite3ErrorMsg(pParse, "Cannot add a PRIMARY KEY column");
|
| + return;
|
| + }
|
| + if( pNew->pIndex ){
|
| + sqlite3ErrorMsg(pParse, "Cannot add a UNIQUE column");
|
| + return;
|
| + }
|
| + if( (db->flags&SQLITE_ForeignKeys) && pNew->pFKey && pDflt ){
|
| + sqlite3ErrorMsg(pParse,
|
| + "Cannot add a REFERENCES column with non-NULL default value");
|
| + return;
|
| + }
|
| + if( pCol->notNull && !pDflt ){
|
| + sqlite3ErrorMsg(pParse,
|
| + "Cannot add a NOT NULL column with default value NULL");
|
| + return;
|
| + }
|
| +
|
| + /* Ensure the default expression is something that sqlite3ValueFromExpr()
|
| + ** can handle (i.e. not CURRENT_TIME etc.)
|
| + */
|
| + if( pDflt ){
|
| + sqlite3_value *pVal = 0;
|
| + int rc;
|
| + rc = sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_BLOB, &pVal);
|
| + assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
|
| + if( rc!=SQLITE_OK ){
|
| + db->mallocFailed = 1;
|
| + return;
|
| + }
|
| + if( !pVal ){
|
| + sqlite3ErrorMsg(pParse, "Cannot add a column with non-constant default");
|
| + return;
|
| + }
|
| + sqlite3ValueFree(pVal);
|
| + }
|
| +
|
| + /* Modify the CREATE TABLE statement. */
|
| + zCol = sqlite3DbStrNDup(db, (char*)pColDef->z, pColDef->n);
|
| + if( zCol ){
|
| + char *zEnd = &zCol[pColDef->n-1];
|
| + int savedDbFlags = db->flags;
|
| + while( zEnd>zCol && (*zEnd==';' || sqlite3Isspace(*zEnd)) ){
|
| + *zEnd-- = '\0';
|
| + }
|
| + db->flags |= SQLITE_PreferBuiltin;
|
| + sqlite3NestedParse(pParse,
|
| + "UPDATE \"%w\".%s SET "
|
| + "sql = substr(sql,1,%d) || ', ' || %Q || substr(sql,%d) "
|
| + "WHERE type = 'table' AND name = %Q",
|
| + zDb, SCHEMA_TABLE(iDb), pNew->addColOffset, zCol, pNew->addColOffset+1,
|
| + zTab
|
| + );
|
| + sqlite3DbFree(db, zCol);
|
| + db->flags = savedDbFlags;
|
| + }
|
| +
|
| + /* If the default value of the new column is NULL, then set the file
|
| + ** format to 2. If the default value of the new column is not NULL,
|
| + ** the file format becomes 3.
|
| + */
|
| + sqlite3MinimumFileFormat(pParse, iDb, pDflt ? 3 : 2);
|
| +
|
| + /* Reload the schema of the modified table. */
|
| + reloadTableSchema(pParse, pTab, pTab->zName);
|
| +}
|
| +
|
| +/*
|
| +** This function is called by the parser after the table-name in
|
| +** an "ALTER TABLE <table-name> ADD" statement is parsed. Argument
|
| +** pSrc is the full-name of the table being altered.
|
| +**
|
| +** This routine makes a (partial) copy of the Table structure
|
| +** for the table being altered and sets Parse.pNewTable to point
|
| +** to it. Routines called by the parser as the column definition
|
| +** is parsed (i.e. sqlite3AddColumn()) add the new Column data to
|
| +** the copy. The copy of the Table structure is deleted by tokenize.c
|
| +** after parsing is finished.
|
| +**
|
| +** Routine sqlite3AlterFinishAddColumn() will be called to complete
|
| +** coding the "ALTER TABLE ... ADD" statement.
|
| +*/
|
| +SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
|
| + Table *pNew;
|
| + Table *pTab;
|
| + Vdbe *v;
|
| + int iDb;
|
| + int i;
|
| + int nAlloc;
|
| + sqlite3 *db = pParse->db;
|
| +
|
| + /* Look up the table being altered. */
|
| + assert( pParse->pNewTable==0 );
|
| + assert( sqlite3BtreeHoldsAllMutexes(db) );
|
| + if( db->mallocFailed ) goto exit_begin_add_column;
|
| + pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]);
|
| + if( !pTab ) goto exit_begin_add_column;
|
| +
|
| +#ifndef SQLITE_OMIT_VIRTUALTABLE
|
| + if( IsVirtual(pTab) ){
|
| + sqlite3ErrorMsg(pParse, "virtual tables may not be altered");
|
| + goto exit_begin_add_column;
|
| + }
|
| +#endif
|
| +
|
| + /* Make sure this is not an attempt to ALTER a view. */
|
| + if( pTab->pSelect ){
|
| + sqlite3ErrorMsg(pParse, "Cannot add a column to a view");
|
| + goto exit_begin_add_column;
|
| + }
|
| + if( SQLITE_OK!=isSystemTable(pParse, pTab->zName) ){
|
| + goto exit_begin_add_column;
|
| + }
|
| +
|
| + assert( pTab->addColOffset>0 );
|
| + iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
| +
|
| + /* Put a copy of the Table struct in Parse.pNewTable for the
|
| + ** sqlite3AddColumn() function and friends to modify. But modify
|
| + ** the name by adding an "sqlite_altertab_" prefix. By adding this
|
| + ** prefix, we insure that the name will not collide with an existing
|
| + ** table because user table are not allowed to have the "sqlite_"
|
| + ** prefix on their name.
|
| + */
|
| + pNew = (Table*)sqlite3DbMallocZero(db, sizeof(Table));
|
| + if( !pNew ) goto exit_begin_add_column;
|
| + pParse->pNewTable = pNew;
|
| + pNew->nRef = 1;
|
| + pNew->nCol = pTab->nCol;
|
| + assert( pNew->nCol>0 );
|
| + nAlloc = (((pNew->nCol-1)/8)*8)+8;
|
| + assert( nAlloc>=pNew->nCol && nAlloc%8==0 && nAlloc-pNew->nCol<8 );
|
| + pNew->aCol = (Column*)sqlite3DbMallocZero(db, sizeof(Column)*nAlloc);
|
| + pNew->zName = sqlite3MPrintf(db, "sqlite_altertab_%s", pTab->zName);
|
| + if( !pNew->aCol || !pNew->zName ){
|
| + db->mallocFailed = 1;
|
| + goto exit_begin_add_column;
|
| + }
|
| + memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*pNew->nCol);
|
| + for(i=0; i<pNew->nCol; i++){
|
| + Column *pCol = &pNew->aCol[i];
|
| + pCol->zName = sqlite3DbStrDup(db, pCol->zName);
|
| + pCol->zColl = 0;
|
| + pCol->zType = 0;
|
| + pCol->pDflt = 0;
|
| + pCol->zDflt = 0;
|
| + }
|
| + pNew->pSchema = db->aDb[iDb].pSchema;
|
| + pNew->addColOffset = pTab->addColOffset;
|
| + pNew->nRef = 1;
|
| +
|
| + /* Begin a transaction and increment the schema cookie. */
|
| + sqlite3BeginWriteOperation(pParse, 0, iDb);
|
| + v = sqlite3GetVdbe(pParse);
|
| + if( !v ) goto exit_begin_add_column;
|
| + sqlite3ChangeCookie(pParse, iDb);
|
| +
|
| +exit_begin_add_column:
|
| + sqlite3SrcListDelete(db, pSrc);
|
| + return;
|
| +}
|
| +#endif /* SQLITE_ALTER_TABLE */
|
| +
|
| +/************** End of alter.c ***********************************************/
|
| +
|
| +/* Chain include. */
|
| +#include "sqlite3.04.c"
|
|
|