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" |