aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/alter.c5
-rw-r--r--src/func.c4
-rw-r--r--src/vdbeapi.c35
-rw-r--r--src/vdbemem.c117
4 files changed, 151 insertions, 10 deletions
diff --git a/src/alter.c b/src/alter.c
index dd060248b..03605b25a 100644
--- a/src/alter.c
+++ b/src/alter.c
@@ -690,7 +690,10 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
*/
if( pDflt ){
sqlite3_value *pVal = 0;
- if( sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_NONE, &pVal) ){
+ int rc;
+ rc = sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_NONE, &pVal);
+ assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
+ if( rc!=SQLITE_OK ){
db->mallocFailed = 1;
return;
}
diff --git a/src/func.c b/src/func.c
index d917bdbec..782a24088 100644
--- a/src/func.c
+++ b/src/func.c
@@ -22,7 +22,9 @@
** Return the collating function associated with a function.
*/
static CollSeq *sqlite3GetFuncCollSeq(sqlite3_context *context){
- VdbeOp *pOp = &context->pVdbe->aOp[context->iOp-1];
+ VdbeOp *pOp;
+ assert( context->pVdbe!=0 );
+ pOp = &context->pVdbe->aOp[context->iOp-1];
assert( pOp->opcode==OP_CollSeq );
assert( pOp->p4type==P4_COLLSEQ );
return pOp->p4.pColl;
diff --git a/src/vdbeapi.c b/src/vdbeapi.c
index 8c0038e4e..ae53d9300 100644
--- a/src/vdbeapi.c
+++ b/src/vdbeapi.c
@@ -370,7 +370,7 @@ void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){
pCtx->isError = errCode;
pCtx->fErrorOrAux = 1;
#ifdef SQLITE_DEBUG
- pCtx->pVdbe->rcApp = errCode;
+ if( pCtx->pVdbe ) pCtx->pVdbe->rcApp = errCode;
#endif
if( pCtx->pOut->flags & MEM_Null ){
sqlite3VdbeMemSetStr(pCtx->pOut, sqlite3ErrStr(errCode), -1,
@@ -633,16 +633,27 @@ sqlite3 *sqlite3_context_db_handle(sqlite3_context *p){
}
/*
-** Return the current time for a statement
+** 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.
*/
sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context *p){
- Vdbe *v = p->pVdbe;
int rc;
- if( v->iCurrentTime==0 ){
- rc = sqlite3OsCurrentTimeInt64(p->pOut->db->pVfs, &v->iCurrentTime);
- if( rc ) v->iCurrentTime = 0;
+ sqlite3_int64 iTime = 0;
+#ifndef SQLITE_ENABLE_STAT3_OR_STAT4
+ sqlite3_int64 *piTime = &iTime;
+ assert( p->pVdbe!=0 );
+#else
+ sqlite3_int64 *piTime = p->pVdbe!=0 ? &p->pVdbe->iCurrentTime : &iTime;
+ if( *piTime==0 )
+#endif
+ {
+ rc = sqlite3OsCurrentTimeInt64(p->pOut->db->pVfs, piTime);
+ if( rc ) *piTime = 0;
}
- return v->iCurrentTime;
+ return *piTime;
}
/*
@@ -712,6 +723,11 @@ void *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;
}
@@ -735,6 +751,11 @@ void sqlite3_set_auxdata(
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;
diff --git a/src/vdbemem.c b/src/vdbemem.c
index 870fb5bd8..0e9bb873a 100644
--- a/src/vdbemem.c
+++ b/src/vdbemem.c
@@ -1090,7 +1090,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 +1135,111 @@ 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,
+** * the SQLITE_FUNC_CONSTANT function flag 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)==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;
+ }
+
+ 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));
+ pCtx->pParse->rc = rc;
+ }else{
+ sqlite3ValueApplyAffinity(pVal, aff, SQLITE_UTF8);
+ assert( rc==SQLITE_OK );
+ rc = sqlite3VdbeChangeEncoding(pVal, enc);
+ if( rc==SQLITE_OK && sqlite3VdbeMemTooBig(pVal) ){
+ rc = SQLITE_TOOBIG;
+ }
+ }
+
+ 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 +1271,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);
@@ -1242,6 +1353,10 @@ static int valueFromExpr(
}
#endif
+ else if( op==TK_FUNCTION && pCtx!=0 ){
+ rc = valueFromFunction(db, pExpr, enc, affinity, &pVal, pCtx);
+ }
+
*ppVal = pVal;
return rc;