Index: third_party/sqlite/src/src/vdbemem.c |
diff --git a/third_party/sqlite/src/src/vdbemem.c b/third_party/sqlite/src/src/vdbemem.c |
index 870fb5bd891c2c83ae8c8683afa5ceca93b99649..fae69b18a4f1810092a436c44fa19b8b31ad3e6a 100644 |
--- a/third_party/sqlite/src/src/vdbemem.c |
+++ b/third_party/sqlite/src/src/vdbemem.c |
@@ -200,10 +200,11 @@ int sqlite3VdbeMemMakeWriteable(Mem *pMem){ |
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; |
+ pMem->pScopyFrom = 0; |
#endif |
- } |
return SQLITE_OK; |
} |
@@ -587,7 +588,7 @@ int sqlite3VdbeMemNumerify(Mem *pMem){ |
void sqlite3VdbeMemCast(Mem *pMem, u8 aff, u8 encoding){ |
if( pMem->flags & MEM_Null ) return; |
switch( aff ){ |
- case SQLITE_AFF_NONE: { /* Really a cast to BLOB */ |
+ 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 ); |
@@ -769,10 +770,6 @@ void sqlite3VdbeMemAboutToChange(Vdbe *pVdbe, Mem *pMem){ |
} |
#endif /* SQLITE_DEBUG */ |
-/* |
-** Size of struct Mem not including the Mem.zMalloc member. |
-*/ |
-#define MEMCELLSIZE offsetof(Mem,zMalloc) |
/* |
** Make an shallow copy of pFrom into pTo. Prior contents of |
@@ -780,10 +777,15 @@ void sqlite3VdbeMemAboutToChange(Vdbe *pVdbe, Mem *pMem){ |
** 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); |
+} |
void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){ |
assert( (pFrom->flags & MEM_RowSet)==0 ); |
assert( pTo->db==pFrom->db ); |
- if( VdbeMemDynamic(pTo) ) vdbeMemClearExternAndSetNull(pTo); |
+ 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); |
@@ -799,7 +801,10 @@ void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){ |
int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){ |
int rc = SQLITE_OK; |
- assert( pTo->db==pFrom->db ); |
+ /* 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); |
@@ -946,6 +951,32 @@ int sqlite3VdbeMemSetStr( |
** 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; |
+} |
int sqlite3VdbeMemFromBtree( |
BtCursor *pCur, /* Cursor pointing at record to retrieve. */ |
u32 offset, /* Offset from the start of data to return bytes from. */ |
@@ -975,22 +1006,7 @@ int sqlite3VdbeMemFromBtree( |
pMem->flags = MEM_Blob|MEM_Ephem; |
pMem->n = (int)amt; |
}else{ |
- 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); |
- } |
- } |
+ rc = vdbeMemFromBtreeResize(pCur, offset, amt, key, pMem); |
} |
return rc; |
@@ -1090,7 +1106,7 @@ struct ValueNewStat4Ctx { |
** 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 |
+** 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){ |
@@ -1135,6 +1151,113 @@ static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){ |
} |
/* |
+** 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(). |
@@ -1166,6 +1289,12 @@ static int valueFromExpr( |
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); |
@@ -1198,7 +1327,7 @@ static int valueFromExpr( |
if( zVal==0 ) goto no_mem; |
sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC); |
} |
- if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE_AFF_NONE ){ |
+ if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE_AFF_BLOB ){ |
sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, SQLITE_UTF8); |
}else{ |
sqlite3ValueApplyAffinity(pVal, affinity, SQLITE_UTF8); |
@@ -1242,6 +1371,12 @@ static int valueFromExpr( |
} |
#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; |
@@ -1292,17 +1427,16 @@ static void recordFunc( |
sqlite3_value **argv |
){ |
const int file_format = 1; |
- int iSerial; /* Serial type */ |
+ u32 iSerial; /* Serial type */ |
int nSerial; /* Bytes of space for iSerial as varint */ |
- int nVal; /* Bytes of space required for argv[0] */ |
+ u32 nVal; /* Bytes of space required for argv[0] */ |
int nRet; |
sqlite3 *db; |
u8 *aRet; |
UNUSED_PARAMETER( argc ); |
- iSerial = sqlite3VdbeSerialType(argv[0], file_format); |
+ iSerial = sqlite3VdbeSerialType(argv[0], file_format, &nVal); |
nSerial = sqlite3VarintLen(iSerial); |
- nVal = sqlite3VdbeSerialTypeLen(iSerial); |
db = sqlite3_context_db_handle(context); |
nRet = 1 + nSerial + nVal; |
@@ -1528,7 +1662,7 @@ void sqlite3Stat4ProbeFree(UnpackedRecord *pRec){ |
Mem *aMem = pRec->aMem; |
sqlite3 *db = aMem[0].db; |
for(i=0; i<nCol; i++){ |
- if( aMem[i].szMalloc ) sqlite3DbFree(db, aMem[i].zMalloc); |
+ sqlite3VdbeMemRelease(&aMem[i]); |
} |
sqlite3KeyInfoUnref(pRec->pKeyInfo); |
sqlite3DbFree(db, pRec); |
@@ -1559,17 +1693,26 @@ void sqlite3ValueFree(sqlite3_value *v){ |
} |
/* |
-** Return the number of bytes in the sqlite3_value object assuming |
-** that it uses the encoding "enc" |
+** 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; |
+} |
int sqlite3ValueBytes(sqlite3_value *pVal, u8 enc){ |
Mem *p = (Mem*)pVal; |
- if( (p->flags & MEM_Blob)!=0 || sqlite3ValueText(pVal, enc) ){ |
+ 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; |
} |
} |
- return 0; |
+ if( p->flags & MEM_Null ) return 0; |
+ return valueBytes(pVal, enc); |
} |