diff options
author | drh <drh@noemail.net> | 2020-03-11 17:58:27 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2020-03-11 17:58:27 +0000 |
commit | 38dfbdae8a61dd16987d93a6a4bfe0001eab7b3d (patch) | |
tree | e42174be28df2760fcfda11a127144cbbd537046 /src/expr.c | |
parent | 8d5cea6b61c30dd839a32e253bf7ae241b5662f4 (diff) | |
download | sqlite-38dfbdae8a61dd16987d93a6a4bfe0001eab7b3d.tar.gz sqlite-38dfbdae8a61dd16987d93a6a4bfe0001eab7b3d.zip |
Do not factor out constant functions into the initialization section at the
end of the prepared statement, be cause if they throw an exception, it will
abort the statement even if the function is never called. Better to put
constant functions in an OP_Once block.
FossilOrigin-Name: 97a18a5cd701848a9660385e31bffe2c397e3cfe57ccdb876f44d08c00d1d39a
Diffstat (limited to 'src/expr.c')
-rw-r--r-- | src/expr.c | 28 |
1 files changed, 21 insertions, 7 deletions
diff --git a/src/expr.c b/src/expr.c index cf52c5c75..8c0768bb7 100644 --- a/src/expr.c +++ b/src/expr.c @@ -4532,15 +4532,29 @@ int sqlite3ExprCodeAtInit( } } } + if( regDest<0 ) regDest = ++pParse->nMem; pExpr = sqlite3ExprDup(pParse->db, pExpr, 0); - p = sqlite3ExprListAppend(pParse, p, pExpr); - if( p ){ - struct ExprList_item *pItem = &p->a[p->nExpr-1]; - pItem->reusable = regDest<0; - if( regDest<0 ) regDest = ++pParse->nMem; - pItem->u.iConstExprReg = regDest; + if( pExpr!=0 && ExprHasProperty(pExpr, EP_HasFunc) ){ + Vdbe *v = pParse->pVdbe; + int addr; + assert( v ); + addr = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); + pParse->okConstFactor = 0; + if( !pParse->db->mallocFailed ){ + sqlite3ExprCode(pParse, pExpr, regDest); + } + pParse->okConstFactor = 1; + sqlite3ExprDelete(pParse->db, pExpr); + sqlite3VdbeJumpHere(v, addr); + }else{ + p = sqlite3ExprListAppend(pParse, p, pExpr); + if( p ){ + struct ExprList_item *pItem = &p->a[p->nExpr-1]; + pItem->reusable = regDest<0; + pItem->u.iConstExprReg = regDest; + } + pParse->pConstExpr = p; } - pParse->pConstExpr = p; return regDest; } |