diff options
author | drh <> | 2023-10-20 15:47:30 +0000 |
---|---|---|
committer | drh <> | 2023-10-20 15:47:30 +0000 |
commit | 90e4a3b7fcdf63035d6f35eb44d11ff58ff4b068 (patch) | |
tree | 647950e3cc7a98d4e5d1e4dac11566fe2c499510 /src/expr.c | |
parent | 0a261eb4bbee272038551bde16633092c491880b (diff) | |
download | sqlite-90e4a3b7fcdf63035d6f35eb44d11ff58ff4b068.tar.gz sqlite-90e4a3b7fcdf63035d6f35eb44d11ff58ff4b068.zip |
Simplifications and optimizations to the Expr object duplication logic.
The 5x multiplier crutch from [f371e4c0f8ea73ae] is still present. More
fixes are still needed.
FossilOrigin-Name: 56142a78163b755f16afc05201f623a7a19d9a4b0620a67f7fa20d2a965a288d
Diffstat (limited to 'src/expr.c')
-rw-r--r-- | src/expr.c | 45 |
1 files changed, 28 insertions, 17 deletions
diff --git a/src/expr.c b/src/expr.c index 35c797ac8..aa43c9be7 100644 --- a/src/expr.c +++ b/src/expr.c @@ -1529,25 +1529,21 @@ static int dupedExprNodeSize(const Expr *p, int flags){ /* ** 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. +** expression passed as the first argument. ** ** 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). +** The return value includes space to duplicate all Expr nodes in the +** tree formed by Expr.pLeft and Expr.pRight, but not any other +** substructure such as Expr.x.pList, Expr.x.pSelect, and Expr.y.pWin. */ -static int dupedExprSize(const 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); - } - } +static int dupedExprSize(const Expr *p){ + int nByte; + assert( p!=0 ); + nByte = dupedExprNodeSize(p, EXPRDUP_REDUCE); + if( p->pLeft ) nByte += dupedExprSize(p->pLeft); + if( p->pRight ) nByte += dupedExprSize(p->pRight); return nByte; } @@ -1564,6 +1560,13 @@ static Expr *exprDup(sqlite3 *db, const Expr *p, int dupFlags, u8 **pzBuffer){ u8 *zAlloc; /* Memory space from which to build Expr object */ u32 staticFlag; /* EP_Static if space not obtained from malloc */ +#ifdef SQLITE_DEBUG + /* If zEnd is not NULL, then it is the first byte past the end of the + ** zAlloc buffer allocated by this routine. Used inside assert() + ** to ensure that sufficient space was allocated for zAlloc */ + u8 *zEnd = 0; +#endif + assert( db!=0 ); assert( p ); assert( dupFlags==0 || dupFlags==EXPRDUP_REDUCE ); @@ -1574,8 +1577,13 @@ static Expr *exprDup(sqlite3 *db, const Expr *p, int dupFlags, u8 **pzBuffer){ zAlloc = *pzBuffer; staticFlag = EP_Static; assert( zAlloc!=0 ); + assert( dupFlags==EXPRDUP_REDUCE ); }else{ - zAlloc = sqlite3DbMallocRawNN(db, dupedExprSize(p, dupFlags)*5); + int nAlloc = dupFlags ? dupedExprSize(p) : dupedExprNodeSize(p, 0); + zAlloc = sqlite3DbMallocRawNN(db, nAlloc*5); +#ifdef SQLITE_DEBUG + zEnd = zAlloc ? zAlloc+nAlloc : 0; +#endif staticFlag = 0; } pNew = (Expr *)zAlloc; @@ -1597,12 +1605,14 @@ static Expr *exprDup(sqlite3 *db, const Expr *p, int dupFlags, u8 **pzBuffer){ if( dupFlags ){ assert( ExprHasProperty(p, EP_Reduced)==0 ); memcpy(zAlloc, p, nNewSize); + zAlloc += nNewSize; }else{ u32 nSize = (u32)exprStructSize(p); memcpy(zAlloc, p, nSize); if( nSize<EXPR_FULLSIZE ){ memset(&zAlloc[nSize], 0, EXPR_FULLSIZE-nSize); } + zAlloc += EXPR_FULLSIZE; } /* Set the EP_Reduced, EP_TokenOnly, and EP_Static flags appropriately. */ @@ -1616,8 +1626,9 @@ static Expr *exprDup(sqlite3 *db, const Expr *p, int dupFlags, u8 **pzBuffer){ /* Copy the p->u.zToken string, if any. */ if( nToken ){ - char *zToken = pNew->u.zToken = (char*)&zAlloc[nNewSize]; + char *zToken = pNew->u.zToken = (char*)zAlloc; memcpy(zToken, p->u.zToken, nToken); + zAlloc += nToken; } if( 0==((p->flags|pNew->flags) & (EP_TokenOnly|EP_Leaf)) ){ @@ -1632,7 +1643,6 @@ static Expr *exprDup(sqlite3 *db, const Expr *p, int dupFlags, u8 **pzBuffer){ /* Fill in pNew->pLeft and pNew->pRight. */ if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly|EP_WinFunc) ){ - zAlloc += dupedExprNodeSize(p, dupFlags); if( !ExprHasProperty(pNew, EP_TokenOnly|EP_Leaf) ){ pNew->pLeft = p->pLeft ? exprDup(db, p->pLeft, EXPRDUP_REDUCE, &zAlloc) : 0; @@ -1661,6 +1671,7 @@ static Expr *exprDup(sqlite3 *db, const Expr *p, int dupFlags, u8 **pzBuffer){ } } } + assert( zEnd==0 || zAlloc<=zEnd ); return pNew; } |