aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordrh <>2022-04-15 15:47:14 +0000
committerdrh <>2022-04-15 15:47:14 +0000
commita99e325468d0c46919cf8a88f7c0b5bb8a4987a8 (patch)
tree3d929a2ac23c4e6acd1a1aadd57ed06c39939f28 /src
parent358424aeff71bc8b38053b822091f4c6532ec5b1 (diff)
downloadsqlite-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.c25
-rw-r--r--src/expr.c16
-rw-r--r--src/insert.c9
-rw-r--r--src/sqliteInt.h18
-rw-r--r--src/treeview.c16
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);
}
}