Index: src/build.c ================================================================== --- src/build.c +++ src/build.c @@ -166,11 +166,11 @@ ** set for each database that is used. Generate code to start a ** transaction on each used database and to verify the schema cookie ** on each used database. */ if( db->mallocFailed==0 - && (DbMaskNonZero(pParse->cookieMask) || pParse->pConstExpr) + && (DbMaskNonZero(pParse->cookieMask) || pParse->pAuxExpr) ){ int iDb, i; assert( sqlite3VdbeGetOp(v, 0)->opcode==OP_Init ); sqlite3VdbeJumpHere(v, 0); for(iDb=0; iDbnDb; iDb++){ @@ -205,21 +205,29 @@ /* Initialize any AUTOINCREMENT data structures required. */ sqlite3AutoincrementBegin(pParse); - /* Code constant expressions that where factored out of inner loops */ - if( pParse->pConstExpr ){ - ExprList *pEL = pParse->pConstExpr; + if( pParse->pAuxExpr ){ + ExprList *pEL = pParse->pAuxExpr; + struct ExprList_item *pX; pParse->okConstFactor = 0; - for(i=0; inExpr; i++){ - sqlite3ExprCode(pParse, pEL->a[i].pExpr, pEL->a[i].u.iConstExprReg); + /* Code constant expressions that where factored out of inner loops */ + for(pX=pEL->a, i=pEL->nExpr; i>0; i--, pX++){ + if( pX->bAuxSubrtn ) continue; + sqlite3ExprCode(pParse, pX->pExpr, pX->u.iConstExprReg); + } + sqlite3VdbeGoto(v, 1); /* Jump back to the main code */ + /* Code subroutines factored out from main */ + for(pX=pEL->a, i=pEL->nExpr; i>0; i--, pX++){ + if( !pX->bAuxSubrtn ) continue; + /* sqlite3ExprCode(pParse, pX->pExpr, pX->u.iConstExprReg); */ } + }else{ + /* Jump back to the beginning of main */ + sqlite3VdbeGoto(v, 1); } - - /* Finally, jump back to the beginning of the executable code. */ - sqlite3VdbeGoto(v, 1); } } /* Get the VDBE program ready for execution Index: src/expr.c ================================================================== --- src/expr.c +++ src/expr.c @@ -1948,11 +1948,11 @@ ** of a LEFT JOIN, and ** (3) the expression does not contain any EP_FixedCol TK_COLUMN ** operands created by the constant propagation optimization. ** ** When this routine returns true, it indicates that the expression -** can be added to the pParse->pConstExpr list and evaluated once when +** can be added to the pParse->pAuxExpr list and evaluated once when ** the prepared statement starts up. See sqlite3ExprCodeAtInit(). */ int sqlite3ExprIsConstantNotJoin(Expr *p){ return exprIsConst(p, 2, 0); } @@ -4136,11 +4136,11 @@ Expr *pExpr, /* The expression to code when the VDBE initializes */ int regDest /* Store the value in this register */ ){ ExprList *p; assert( ConstFactorOk(pParse) ); - p = pParse->pConstExpr; + p = pParse->pAuxExpr; if( regDest<0 && p ){ struct ExprList_item *pItem; int i; for(pItem=p->a, i=p->nExpr; i>0; pItem++, i--){ if( pItem->reusable && sqlite3ExprCompare(0,pItem->pExpr,pExpr,-1)==0 ){ @@ -4154,11 +4154,11 @@ struct ExprList_item *pItem = &p->a[p->nExpr-1]; pItem->reusable = regDest<0; if( regDest<0 ) regDest = ++pParse->nMem; pItem->u.iConstExprReg = regDest; } - pParse->pConstExpr = p; + pParse->pAuxExpr = p; return regDest; } /* ** Generate code to evaluate an expression and store the results @@ -4392,11 +4392,11 @@ if( xJump ){ xJump(pParse, &exprAnd, dest, jumpIfNull); }else{ /* Mark the expression is being from the ON or USING clause of a join ** so that the sqlite3ExprCodeTarget() routine will not attempt to move - ** it into the Parse.pConstExpr list. We should use a new bit for this, + ** it into the Parse.pAuxExpr list. We should use a new bit for this, ** for clarity, but we are out of bits in the Expr.flags field so we ** have to reuse the EP_FromJoin bit. Bummer. */ exprX.flags |= EP_FromJoin; sqlite3ExprCodeTarget(pParse, &exprAnd, dest); } Index: src/prepare.c ================================================================== --- src/prepare.c +++ src/prepare.c @@ -504,11 +504,11 @@ ** Free all memory allocations in the pParse object */ void sqlite3ParserReset(Parse *pParse){ sqlite3 *db = pParse->db; sqlite3DbFree(db, pParse->aLabel); - sqlite3ExprListDelete(db, pParse->pConstExpr); + sqlite3ExprListDelete(db, pParse->pAuxExpr); if( db ){ assert( db->lookaside.bDisable >= pParse->disableLookaside ); db->lookaside.bDisable -= pParse->disableLookaside; } pParse->disableLookaside = 0; Index: src/sqliteInt.h ================================================================== --- src/sqliteInt.h +++ src/sqliteInt.h @@ -2585,12 +2585,13 @@ char *zName; /* Token associated with this expression */ char *zSpan; /* Original text of the expression */ u8 sortOrder; /* 1 for DESC or 0 for ASC */ unsigned done :1; /* A flag to indicate when processing is finished */ unsigned bSpanIsTab :1; /* zSpan holds DB.TABLE.COLUMN */ - unsigned reusable :1; /* Constant expression is reusable */ + unsigned reusable :1; /* Constant expression is reusable */ unsigned bSorterRef :1; /* Defer evaluation until after sorting */ + unsigned bAuxSubrtn :1; /* Member of pAuxExpr to be coded as a subroutine */ union { struct { u16 iOrderByCol; /* For ORDER BY, column number in result set */ u16 iAlias; /* Index into Parse.aAlias[] for zName */ } x; @@ -3073,11 +3074,11 @@ int szOpAlloc; /* Bytes of memory space allocated for Vdbe.aOp[] */ int iSelfTab; /* Table associated with an index on expr, or negative ** of the base register during check-constraint eval */ int nLabel; /* Number of labels used */ int *aLabel; /* Space to hold the labels */ - ExprList *pConstExpr;/* Constant expressions */ + ExprList *pAuxExpr; /* Exprs coded at initialization or as subroutines */ Token constraintName;/* Name of the constraint currently being parsed */ yDbMask writeMask; /* Start a write transaction on these databases */ yDbMask cookieMask; /* Bitmask of schema verified databases */ int regRowid; /* Register holding rowid of CREATE TABLE entry */ int regRoot; /* Register holding root page number for new objects */