diff options
author | drh <> | 2022-04-15 15:47:14 +0000 |
---|---|---|
committer | drh <> | 2022-04-15 15:47:14 +0000 |
commit | a99e325468d0c46919cf8a88f7c0b5bb8a4987a8 (patch) | |
tree | 3d929a2ac23c4e6acd1a1aadd57ed06c39939f28 /src | |
parent | 358424aeff71bc8b38053b822091f4c6532ec5b1 (diff) | |
download | sqlite-a99e325468d0c46919cf8a88f7c0b5bb8a4987a8.tar.gz sqlite-a99e325468d0c46919cf8a88f7c0b5bb8a4987a8.zip |
Enhance the IdList object to exist in a single memory allocation (rather than
a separate allocate for the base object and the array of IDs). Also permit
an IdList object to store an Expr pointer together with each name.
FossilOrigin-Name: 40f3c95871e6f40f287ef2756abafb8fc56dffdd0af69436e5c7d8e95022d94e
Diffstat (limited to 'src')
-rw-r--r-- | src/build.c | 25 | ||||
-rw-r--r-- | src/expr.c | 16 | ||||
-rw-r--r-- | src/insert.c | 9 | ||||
-rw-r--r-- | src/sqliteInt.h | 18 | ||||
-rw-r--r-- | src/treeview.c | 16 |
5 files changed, 54 insertions, 30 deletions
diff --git a/src/build.c b/src/build.c index 22f7a79e0..30908500a 100644 --- a/src/build.c +++ b/src/build.c @@ -4672,18 +4672,17 @@ IdList *sqlite3IdListAppend(Parse *pParse, IdList *pList, Token *pToken){ if( pList==0 ){ pList = sqlite3DbMallocZero(db, sizeof(IdList) ); if( pList==0 ) return 0; + }else{ + IdList *pNew; + pNew = sqlite3DbRealloc(db, pList, + sizeof(IdList) + pList->nId*sizeof(pList->a)); + if( pNew==0 ){ + sqlite3IdListDelete(db, pList); + return 0; + } + pList = pNew; } - pList->a = sqlite3ArrayAllocate( - db, - pList->a, - sizeof(pList->a[0]), - &pList->nId, - &i - ); - if( i<0 ){ - sqlite3IdListDelete(db, pList); - return 0; - } + i = pList->nId++; pList->a[i].zName = sqlite3NameFromToken(db, pToken); if( IN_RENAME_OBJECT && pList->a[i].zName ){ sqlite3RenameTokenMap(pParse, (void*)pList->a[i].zName, pToken); @@ -4696,11 +4695,13 @@ IdList *sqlite3IdListAppend(Parse *pParse, IdList *pList, Token *pToken){ */ void sqlite3IdListDelete(sqlite3 *db, IdList *pList){ int i; + int delExpr; if( pList==0 ) return; + delExpr = pList->eU4==EU4_EXPR; for(i=0; i<pList->nId; i++){ sqlite3DbFree(db, pList->a[i].zName); + if( delExpr ) sqlite3ExprDelete(db, pList->a[i].u4.pExpr); } - sqlite3DbFree(db, pList->a); sqlite3DbFreeNN(db, pList); } diff --git a/src/expr.c b/src/expr.c index e6d7f9e69..4e036c934 100644 --- a/src/expr.c +++ b/src/expr.c @@ -1698,22 +1698,16 @@ IdList *sqlite3IdListDup(sqlite3 *db, const IdList *p){ int i; assert( db!=0 ); if( p==0 ) return 0; - pNew = sqlite3DbMallocRawNN(db, sizeof(*pNew) ); + assert( p->eU4!=EU4_EXPR ); + pNew = sqlite3DbMallocRawNN(db, sizeof(*pNew)+(p->nId-1)*sizeof(p->a[0]) ); if( pNew==0 ) return 0; pNew->nId = p->nId; - pNew->a = sqlite3DbMallocRawNN(db, p->nId*sizeof(p->a[0]) ); - if( pNew->a==0 ){ - sqlite3DbFreeNN(db, pNew); - return 0; - } - /* Note that because the size of the allocation for p->a[] is not - ** necessarily a power of two, sqlite3IdListAppend() may not be called - ** on the duplicate created by this function. */ + pNew->eU4 = p->eU4; for(i=0; i<p->nId; i++){ struct IdList_item *pNewItem = &pNew->a[i]; - struct IdList_item *pOldItem = &p->a[i]; + const struct IdList_item *pOldItem = &p->a[i]; pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName); - pNewItem->idx = pOldItem->idx; + pNewItem->u4 = pOldItem->u4; } return pNew; } diff --git a/src/insert.c b/src/insert.c index 2593f353b..9b97b99a3 100644 --- a/src/insert.c +++ b/src/insert.c @@ -851,13 +851,15 @@ void sqlite3Insert( */ bIdListInOrder = (pTab->tabFlags & (TF_OOOHidden|TF_HasStored))==0; if( pColumn ){ + assert( pColumn->eU4!=EU4_EXPR ); + pColumn->eU4 = EU4_IDX; for(i=0; i<pColumn->nId; i++){ - pColumn->a[i].idx = -1; + pColumn->a[i].u4.idx = -1; } for(i=0; i<pColumn->nId; i++){ for(j=0; j<pTab->nCol; j++){ if( sqlite3StrICmp(pColumn->a[i].zName, pTab->aCol[j].zCnName)==0 ){ - pColumn->a[i].idx = j; + pColumn->a[i].u4.idx = j; if( i!=j ) bIdListInOrder = 0; if( j==pTab->iPKey ){ ipkColumn = i; assert( !withoutRowid ); @@ -1159,7 +1161,8 @@ void sqlite3Insert( } } if( pColumn ){ - for(j=0; j<pColumn->nId && pColumn->a[j].idx!=i; j++){} + assert( pColumn->eU4==EU4_IDX ); + for(j=0; j<pColumn->nId && pColumn->a[j].u4.idx!=i; j++){} if( j>=pColumn->nId ){ /* A column not named in the insert column list gets its ** default value */ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 1cd3e75b4..3a9d8b8a0 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3038,14 +3038,26 @@ struct ExprList { ** If "a" is the k-th column of table "t", then IdList.a[0].idx==k. */ struct IdList { + int nId; /* Number of identifiers on the list */ + u8 eU4; /* Which element of a.u4 is valid */ struct IdList_item { char *zName; /* Name of the identifier */ - int idx; /* Index in some Table.aCol[] of a column named zName */ - } *a; - int nId; /* Number of identifiers on the list */ + union { + int idx; /* Index in some Table.aCol[] of a column named zName */ + Expr *pExpr; /* Expr to implement a USING variable */ + } u4; + } a[1]; }; /* +** Allowed values for IdList.eType, which determines which value of the a.u4 +** is valid. +*/ +#define EU4_NONE 0 /* Does not use IdList.a.u4 */ +#define EU4_IDX 1 /* Uses IdList.a.u4.idx */ +#define EU4_EXPR 2 /* Uses IdList.a.u4.pExpr */ + +/* ** The SrcItem object represents a single term in the FROM clause of a query. ** The SrcList object is mostly an array of SrcItems. ** diff --git a/src/treeview.c b/src/treeview.c index 0a3f94267..ff5558aca 100644 --- a/src/treeview.c +++ b/src/treeview.c @@ -846,7 +846,21 @@ void sqlite3TreeViewBareIdList( if( zName==0 ) zName = "(null)"; sqlite3TreeViewPush(&pView, moreToFollow); sqlite3TreeViewLine(pView, 0); - fprintf(stdout, "%s (%d)\n", zName, pList->a[i].idx); + if( pList->eU4==EU4_NONE ){ + fprintf(stdout, "%s\n", zName); + }else if( pList->eU4==EU4_IDX ){ + fprintf(stdout, "%s (%d)\n", zName, pList->a[i].u4.idx); + }else{ + assert( pList->eU4==EU4_EXPR ); + if( pList->a[i].u4.pExpr==0 ){ + fprintf(stdout, "%s (pExpr=NULL)\n", zName); + }else{ + fprintf(stdout, "%s\n", zName); + sqlite3TreeViewPush(&pView, i<pList->nId-1); + sqlite3TreeViewExpr(pView, pList->a[i].u4.pExpr, 0); + sqlite3TreeViewPop(&pView); + } + } sqlite3TreeViewPop(&pView); } } |