diff options
author | drh <drh@noemail.net> | 2017-09-15 15:17:48 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2017-09-15 15:17:48 +0000 |
commit | a19543fe703823a434d5d0702db9e45075958be1 (patch) | |
tree | 02a59ed6529ca3bb7bdbfbfad3e80783e90a6472 /src/expr.c | |
parent | 154896e8d243bf895775707a1741950dc39567fd (diff) | |
download | sqlite-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.c | 21 |
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) ); |