aboutsummaryrefslogtreecommitdiff
path: root/src/expr.c
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2017-09-15 15:17:48 +0000
committerdrh <drh@noemail.net>2017-09-15 15:17:48 +0000
commita19543fe703823a434d5d0702db9e45075958be1 (patch)
tree02a59ed6529ca3bb7bdbfbfad3e80783e90a6472 /src/expr.c
parent154896e8d243bf895775707a1741950dc39567fd (diff)
downloadsqlite-a19543fe703823a434d5d0702db9e45075958be1.tar.gz
sqlite-a19543fe703823a434d5d0702db9e45075958be1.zip
Optimization to the ExprList object to make it slightly smaller and faster.
FossilOrigin-Name: 4da49a95c0f07ed7790169e8833c3e2dacda504a3d997f567572020148abe30b
Diffstat (limited to 'src/expr.c')
-rw-r--r--src/expr.c21
1 files changed, 16 insertions, 5 deletions
diff --git a/src/expr.c b/src/expr.c
index 0c3b608de..38c799c6b 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -1305,7 +1305,11 @@ ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){
pNew = sqlite3DbMallocRawNN(db,
sizeof(*pNew)+sizeof(pNew->a[0])*(p->nExpr-1) );
if( pNew==0 ) return 0;
- pNew->nAlloc = pNew->nExpr = p->nExpr;
+ pNew->nExpr = p->nExpr;
+ /* After being duplicated, the ExprList may not be expanded again using
+ ** Append() because Append() assumes that the number of slots in
+ ** ExprList.a[] is a power of 2 */
+ VVA_ONLY( pNew->bFixedSize = 1 );
pItem = pNew->a;
pOldItem = p->a;
for(i=0; i<p->nExpr; i++, pItem++, pOldItem++){
@@ -1459,6 +1463,13 @@ Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){
** Add a new element to the end of an expression list. If pList is
** initially NULL, then create a new expression list.
**
+** The pList argument must be either NULL or a pointer to an ExprList
+** obtained from a prior call to sqlite3ExprListAppend(). This routine
+** may not be used with an ExprList obtained from sqlite3ExprListDup().
+** Reason: This routine assumes that the number of slots in pList->a[]
+** is a power of two. That is true for sqlite3ExprListAppend() returns
+** but is not necessarily true from the return value of sqlite3ExprListDup().
+**
** If a memory allocation error occurs, the entire list is freed and
** NULL is returned. If non-NULL is returned, then it is guaranteed
** that the new entry was successfully appended.
@@ -1471,22 +1482,22 @@ ExprList *sqlite3ExprListAppend(
struct ExprList_item *pItem;
sqlite3 *db = pParse->db;
assert( db!=0 );
+ assert( pList==0 || pList->bFixedSize==0 );
if( pList==0 ){
pList = sqlite3DbMallocRawNN(db, sizeof(ExprList) );
if( pList==0 ){
goto no_mem;
}
pList->nExpr = 0;
- pList->nAlloc = 1;
- }else if( pList->nExpr==pList->nAlloc ){
+ VVA_ONLY( pList->bFixedSize = 0 );
+ }else if( (pList->nExpr & (pList->nExpr-1))==0 ){
ExprList *pNew;
pNew = sqlite3DbRealloc(db, pList,
- sizeof(*pList)+(2*pList->nAlloc - 1)*sizeof(pList->a[0]));
+ sizeof(*pList)+(2*pList->nExpr - 1)*sizeof(pList->a[0]));
if( pNew==0 ){
goto no_mem;
}
pList = pNew;
- pList->nAlloc *= 2;
}
pItem = &pList->a[pList->nExpr++];
assert( offsetof(struct ExprList_item,zName)==sizeof(pItem->pExpr) );