aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2019-12-12 22:11:33 +0000
committerdrh <drh@noemail.net>2019-12-12 22:11:33 +0000
commitcbb9da337e7f8dc4e6bea59399a0394ec390f1f2 (patch)
tree9e2fc1883495a5eeb3e2ad2e5167486fd567afed /src
parentc947d6a4dcdfe6f0185a22464cf97153cabb8052 (diff)
downloadsqlite-cbb9da337e7f8dc4e6bea59399a0394ec390f1f2.tar.gz
sqlite-cbb9da337e7f8dc4e6bea59399a0394ec390f1f2.zip
Work toward reducing the incremental size of an ExprList object to 24-byte
per entry, from 32-bytes (on a 64-bit machine). This helps the new mini-lookaside allocator to run better by avoiding excessive reallocs. The current change mostly works, but still has a few loose ends to tie up. This check-in is merely a snapshot to save my work. FossilOrigin-Name: fdda76cfb01bf2b19522ac4558b443634d28a69b0828677c42682b645eae1f3b
Diffstat (limited to 'src')
-rw-r--r--src/expr.c10
-rw-r--r--src/resolve.c2
-rw-r--r--src/select.c26
-rw-r--r--src/sqliteInt.h30
4 files changed, 40 insertions, 28 deletions
diff --git a/src/expr.c b/src/expr.c
index f9c57baa9..0ca1d0407 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -1437,11 +1437,10 @@ ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){
}
}
pItem->zEName = sqlite3DbStrDup(db, pOldItem->zEName);
- pItem->zSpan = sqlite3DbStrDup(db, pOldItem->zSpan);
pItem->sortFlags = pOldItem->sortFlags;
+ pItem->eEName = pOldItem->eEName;
pItem->done = 0;
pItem->bNulls = pOldItem->bNulls;
- pItem->bSpanIsTab = pOldItem->bSpanIsTab;
pItem->bSorterRef = pOldItem->bSorterRef;
pItem->u = pOldItem->u;
}
@@ -1773,8 +1772,10 @@ void sqlite3ExprListSetSpan(
if( pList ){
struct ExprList_item *pItem = &pList->a[pList->nExpr-1];
assert( pList->nExpr>0 );
- sqlite3DbFree(db, pItem->zSpan);
- pItem->zSpan = sqlite3DbSpanDup(db, zStart, zEnd);
+ if( pItem->zEName==0 ){
+ pItem->zEName = sqlite3DbSpanDup(db, zStart, zEnd);
+ pItem->eEName = ENAME_SPAN;
+ }
}
}
@@ -1805,7 +1806,6 @@ static SQLITE_NOINLINE void exprListDeleteNN(sqlite3 *db, ExprList *pList){
do{
sqlite3ExprDelete(db, pItem->pExpr);
sqlite3DbFree(db, pItem->zEName);
- sqlite3DbFree(db, pItem->zSpan);
pItem++;
}while( --i>0 );
sqlite3DbFreeNN(db, pList);
diff --git a/src/resolve.c b/src/resolve.c
index b3c331535..cce921031 100644
--- a/src/resolve.c
+++ b/src/resolve.c
@@ -267,7 +267,7 @@ static int lookupName(
int hit = 0;
pEList = pItem->pSelect->pEList;
for(j=0; j<pEList->nExpr; j++){
- if( sqlite3MatchSpanName(pEList->a[j].zSpan, zCol, zTab, zDb) ){
+ if( sqlite3MatchSpanName(pEList->a[j].zEName, zCol, zTab, zDb) ){
cnt++;
cntTab = 2;
pMatch = pItem;
diff --git a/src/select.c b/src/select.c
index b99b1459b..57bf685ed 100644
--- a/src/select.c
+++ b/src/select.c
@@ -1539,7 +1539,7 @@ static void generateSortTail(
iRead = iCol--;
}
sqlite3VdbeAddOp3(v, OP_Column, iSortTab, iRead, regRow+i);
- VdbeComment((v, "%s", aOutEx[i].zEName?aOutEx[i].zEName:aOutEx[i].zSpan));
+ VdbeComment((v, "%s", aOutEx[i].zEName));
}
}
switch( eDest ){
@@ -1873,7 +1873,7 @@ static void generateColumnNames(
assert( p!=0 );
assert( p->op!=TK_AGG_COLUMN ); /* Agg processing has not run yet */
assert( p->op!=TK_COLUMN || p->y.pTab!=0 ); /* Covering idx not yet coded */
- if( pEList->a[i].zEName ){
+ if( pEList->a[i].zEName && pEList->a[i].eEName==ENAME_NAME ){
/* An AS clause always takes first priority */
char *zName = pEList->a[i].zEName;
sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_TRANSIENT);
@@ -1897,7 +1897,7 @@ static void generateColumnNames(
sqlite3VdbeSetColName(v, i, COLNAME_NAME, zCol, SQLITE_TRANSIENT);
}
}else{
- const char *z = pEList->a[i].zSpan;
+ const char *z = pEList->a[i].zEName;
z = z==0 ? sqlite3MPrintf(db, "column%d", i+1) : sqlite3DbStrDup(db, z);
sqlite3VdbeSetColName(v, i, COLNAME_NAME, z, SQLITE_DYNAMIC);
}
@@ -1959,7 +1959,7 @@ int sqlite3ColumnsFromExprList(
for(i=0, pCol=aCol; i<nCol && !db->mallocFailed; i++, pCol++){
/* Get an appropriate name for the column
*/
- if( (zName = pEList->a[i].zEName)!=0 ){
+ if( (zName = pEList->a[i].zEName)!=0 && pEList->a[i].eEName==ENAME_NAME ){
/* If the column contains an "AS <name>" phrase, use <name> as the name */
}else{
Expr *pColExpr = sqlite3ExprSkipCollateAndLikely(pEList->a[i].pExpr);
@@ -1979,7 +1979,7 @@ int sqlite3ColumnsFromExprList(
zName = pColExpr->u.zToken;
}else{
/* Use the original text of the column expression as its name */
- zName = pEList->a[i].zSpan;
+ zName = pEList->a[i].zEName;
}
}
if( zName ){
@@ -5004,9 +5004,8 @@ static int selectExpander(Walker *pWalker, Select *p){
pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr);
if( pNew ){
pNew->a[pNew->nExpr-1].zEName = a[k].zEName;
- pNew->a[pNew->nExpr-1].zSpan = a[k].zSpan;
+ pNew->a[pNew->nExpr-1].eEName = a[k].eEName;
a[k].zEName = 0;
- a[k].zSpan = 0;
}
a[k].pExpr = 0;
}else{
@@ -5045,7 +5044,7 @@ static int selectExpander(Walker *pWalker, Select *p){
assert( zName );
if( zTName && pSub
- && sqlite3MatchSpanName(pSub->pEList->a[j].zSpan, 0, zTName, 0)==0
+ && sqlite3MatchSpanName(pSub->pEList->a[j].zEName, 0, zTName, 0)==0
){
continue;
}
@@ -5098,15 +5097,16 @@ static int selectExpander(Walker *pWalker, Select *p){
sqlite3ExprListSetName(pParse, pNew, &sColname, 0);
if( pNew && (p->selFlags & SF_NestedFrom)!=0 ){
struct ExprList_item *pX = &pNew->a[pNew->nExpr-1];
+ sqlite3DbFree(db, pX->zEName);
if( pSub ){
- pX->zSpan = sqlite3DbStrDup(db, pSub->pEList->a[j].zSpan);
- testcase( pX->zSpan==0 );
+ pX->zEName = sqlite3DbStrDup(db, pSub->pEList->a[j].zEName);
+ testcase( pX->zEName==0 );
}else{
- pX->zSpan = sqlite3MPrintf(db, "%s.%s.%s",
+ pX->zEName = sqlite3MPrintf(db, "%s.%s.%s",
zSchemaName, zTabName, zColname);
- testcase( pX->zSpan==0 );
+ testcase( pX->zEName==0 );
}
- pX->bSpanIsTab = 1;
+ pX->eEName = ENAME_TAB;
}
sqlite3DbFree(db, zToFree);
}
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 3de659f79..7425b2988 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -2650,23 +2650,28 @@ struct Expr {
** also be used as the argument to a function, in which case the a.zName
** field is not used.
**
-** By default the Expr.zSpan field holds a human-readable description of
-** the expression that is used in the generation of error messages and
-** column labels. In this case, Expr.zSpan is typically the text of a
-** column expression as it exists in a SELECT statement. However, if
-** the bSpanIsTab flag is set, then zSpan is overloaded to mean the name
-** of the result column in the form: DATABASE.TABLE.COLUMN. This later
-** form is used for name resolution with nested FROM clauses.
+** In order to try to keep memory usage down, the Expr.a.zEName field
+** is used for multiple purposes:
+**
+** bNameIsTab bNameIsSpan Usage
+** ---------- ----------- -------------------------
+** false false (1) the AS of result set column
+** (2) COLUMN= of an UPDATE
+**
+** true false DB.TABLE.NAME used to resolve names
+** of subqueries
+**
+** false true Text of the original result set
+** expression.
*/
struct ExprList {
int nExpr; /* Number of expressions on the list */
struct ExprList_item { /* For each expression in the list */
Expr *pExpr; /* The parse tree for this expression */
char *zEName; /* Token associated with this expression */
- char *zSpan; /* Original text of the expression */
u8 sortFlags; /* Mask of KEYINFO_ORDER_* flags */
+ unsigned eEName :2; /* Meaning of zEName */
unsigned done :1; /* A flag to indicate when processing is finished */
- unsigned bSpanIsTab :1; /* zSpan holds DB.TABLE.COLUMN */
unsigned reusable :1; /* Constant expression is reusable */
unsigned bSorterRef :1; /* Defer evaluation until after sorting */
unsigned bNulls: 1; /* True if explicit "NULLS FIRST/LAST" */
@@ -2681,6 +2686,13 @@ struct ExprList {
};
/*
+** Allowed values for Expr.a.eEName
+*/
+#define ENAME_NAME 0 /* The AS clause of a result set */
+#define ENAME_SPAN 1 /* Complete text of the result set expression */
+#define ENAME_TAB 2 /* "DB.TABLE.NAME" for the result set */
+
+/*
** An instance of this structure can hold a simple list of identifiers,
** such as the list "a,b,c" in the following statements:
**