summaryrefslogtreecommitdiff
path: root/ext/sqlite/libsqlite/src/expr.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/sqlite/libsqlite/src/expr.c')
-rw-r--r--ext/sqlite/libsqlite/src/expr.c683
1 files changed, 354 insertions, 329 deletions
diff --git a/ext/sqlite/libsqlite/src/expr.c b/ext/sqlite/libsqlite/src/expr.c
index 273b3a0a01..44c0f6967a 100644
--- a/ext/sqlite/libsqlite/src/expr.c
+++ b/ext/sqlite/libsqlite/src/expr.c
@@ -26,8 +26,7 @@ Expr *sqliteExpr(int op, Expr *pLeft, Expr *pRight, Token *pToken){
Expr *pNew;
pNew = sqliteMalloc( sizeof(Expr) );
if( pNew==0 ){
- sqliteExprDelete(pLeft);
- sqliteExprDelete(pRight);
+ /* When malloc fails, we leak memory from pLeft and pRight */
return 0;
}
pNew->op = op;
@@ -38,9 +37,9 @@ Expr *sqliteExpr(int op, Expr *pLeft, Expr *pRight, Token *pToken){
pNew->token = *pToken;
pNew->span = *pToken;
}else{
- pNew->token.dyn = 0;
- pNew->token.z = 0;
- pNew->token.n = 0;
+ assert( pNew->token.dyn==0 );
+ assert( pNew->token.z==0 );
+ assert( pNew->token.n==0 );
if( pLeft && pRight ){
sqliteExprSpan(pNew, &pLeft->span, &pRight->span);
}else{
@@ -55,14 +54,15 @@ Expr *sqliteExpr(int op, Expr *pLeft, Expr *pRight, Token *pToken){
** text between the two given tokens.
*/
void sqliteExprSpan(Expr *pExpr, Token *pLeft, Token *pRight){
- if( pExpr && pRight && pRight->z && pLeft && pLeft->z ){
+ assert( pRight!=0 );
+ assert( pLeft!=0 );
+ /* Note: pExpr might be NULL due to a prior malloc failure */
+ if( pExpr && pRight->z && pLeft->z ){
if( pLeft->dyn==0 && pRight->dyn==0 ){
pExpr->span.z = pLeft->z;
pExpr->span.n = pRight->n + Addr(pRight->z) - Addr(pLeft->z);
}else{
pExpr->span.z = 0;
- pExpr->span.n = 0;
- pExpr->span.dyn = 0;
}
}
}
@@ -75,18 +75,16 @@ Expr *sqliteExprFunction(ExprList *pList, Token *pToken){
Expr *pNew;
pNew = sqliteMalloc( sizeof(Expr) );
if( pNew==0 ){
- sqliteExprListDelete(pList);
+ /* sqliteExprListDelete(pList); // Leak pList when malloc fails */
return 0;
}
pNew->op = TK_FUNCTION;
pNew->pList = pList;
- pNew->token.dyn = 0;
if( pToken ){
assert( pToken->dyn==0 );
pNew->token = *pToken;
}else{
pNew->token.z = 0;
- pNew->token.n = 0;
}
pNew->span = pNew->token;
return pNew;
@@ -97,12 +95,12 @@ Expr *sqliteExprFunction(ExprList *pList, Token *pToken){
*/
void sqliteExprDelete(Expr *p){
if( p==0 ) return;
- if( p->span.dyn && p->span.z ) sqliteFree((char*)p->span.z);
- if( p->token.dyn && p->token.z ) sqliteFree((char*)p->token.z);
- if( p->pLeft ) sqliteExprDelete(p->pLeft);
- if( p->pRight ) sqliteExprDelete(p->pRight);
- if( p->pList ) sqliteExprListDelete(p->pList);
- if( p->pSelect ) sqliteSelectDelete(p->pSelect);
+ if( p->span.dyn ) sqliteFree((char*)p->span.z);
+ if( p->token.dyn ) sqliteFree((char*)p->token.z);
+ sqliteExprDelete(p->pLeft);
+ sqliteExprDelete(p->pRight);
+ sqliteExprListDelete(p->pList);
+ sqliteSelectDelete(p->pSelect);
sqliteFree(p);
}
@@ -129,13 +127,9 @@ Expr *sqliteExprDup(Expr *p){
pNew->token.z = sqliteStrDup(p->token.z);
pNew->token.dyn = 1;
}else{
- pNew->token.z = 0;
- pNew->token.n = 0;
- pNew->token.dyn = 0;
+ assert( pNew->token.z==0 );
}
pNew->span.z = 0;
- pNew->span.n = 0;
- pNew->span.dyn = 0;
pNew->pLeft = sqliteExprDup(p->pLeft);
pNew->pRight = sqliteExprDup(p->pRight);
pNew->pList = sqliteExprListDup(p->pList);
@@ -149,23 +143,22 @@ void sqliteTokenCopy(Token *pTo, Token *pFrom){
pTo->z = sqliteStrNDup(pFrom->z, pFrom->n);
pTo->dyn = 1;
}else{
- pTo->n = 0;
pTo->z = 0;
- pTo->dyn = 0;
}
}
ExprList *sqliteExprListDup(ExprList *p){
ExprList *pNew;
+ struct ExprList_item *pItem;
int i;
if( p==0 ) return 0;
pNew = sqliteMalloc( sizeof(*pNew) );
if( pNew==0 ) return 0;
pNew->nExpr = pNew->nAlloc = p->nExpr;
- pNew->a = sqliteMalloc( p->nExpr*sizeof(p->a[0]) );
- if( pNew->a==0 ) return 0;
- for(i=0; i<p->nExpr; i++){
+ pNew->a = pItem = sqliteMalloc( p->nExpr*sizeof(p->a[0]) );
+ if( pItem==0 ) return 0; /* Leaks memory after a malloc failure */
+ for(i=0; i<p->nExpr; i++, pItem++){
Expr *pNewExpr, *pOldExpr;
- pNew->a[i].pExpr = pNewExpr = sqliteExprDup(pOldExpr = p->a[i].pExpr);
+ pItem->pExpr = pNewExpr = sqliteExprDup(pOldExpr = p->a[i].pExpr);
if( pOldExpr->span.z!=0 && pNewExpr ){
/* Always make a copy of the span for top-level expressions in the
** expression list. The logic in SELECT processing that determines
@@ -174,10 +167,10 @@ ExprList *sqliteExprListDup(ExprList *p){
}
assert( pNewExpr==0 || pNewExpr->span.z!=0
|| pOldExpr->span.z==0 || sqlite_malloc_failed );
- pNew->a[i].zName = sqliteStrDup(p->a[i].zName);
- pNew->a[i].sortOrder = p->a[i].sortOrder;
- pNew->a[i].isAgg = p->a[i].isAgg;
- pNew->a[i].done = 0;
+ pItem->zName = sqliteStrDup(p->a[i].zName);
+ pItem->sortOrder = p->a[i].sortOrder;
+ pItem->isAgg = p->a[i].isAgg;
+ pItem->done = 0;
}
return pNew;
}
@@ -187,19 +180,21 @@ SrcList *sqliteSrcListDup(SrcList *p){
int nByte;
if( p==0 ) return 0;
nByte = sizeof(*p) + (p->nSrc>0 ? sizeof(p->a[0]) * (p->nSrc-1) : 0);
- pNew = sqliteMalloc( nByte );
+ pNew = sqliteMallocRaw( nByte );
if( pNew==0 ) return 0;
pNew->nSrc = pNew->nAlloc = p->nSrc;
for(i=0; i<p->nSrc; i++){
- pNew->a[i].zDatabase = sqliteStrDup(p->a[i].zDatabase);
- pNew->a[i].zName = sqliteStrDup(p->a[i].zName);
- pNew->a[i].zAlias = sqliteStrDup(p->a[i].zAlias);
- pNew->a[i].jointype = p->a[i].jointype;
- pNew->a[i].iCursor = p->a[i].iCursor;
- pNew->a[i].pTab = 0;
- pNew->a[i].pSelect = sqliteSelectDup(p->a[i].pSelect);
- pNew->a[i].pOn = sqliteExprDup(p->a[i].pOn);
- pNew->a[i].pUsing = sqliteIdListDup(p->a[i].pUsing);
+ struct SrcList_item *pNewItem = &pNew->a[i];
+ struct SrcList_item *pOldItem = &p->a[i];
+ pNewItem->zDatabase = sqliteStrDup(pOldItem->zDatabase);
+ pNewItem->zName = sqliteStrDup(pOldItem->zName);
+ pNewItem->zAlias = sqliteStrDup(pOldItem->zAlias);
+ pNewItem->jointype = pOldItem->jointype;
+ pNewItem->iCursor = pOldItem->iCursor;
+ pNewItem->pTab = 0;
+ pNewItem->pSelect = sqliteSelectDup(pOldItem->pSelect);
+ pNewItem->pOn = sqliteExprDup(pOldItem->pOn);
+ pNewItem->pUsing = sqliteIdListDup(pOldItem->pUsing);
}
return pNew;
}
@@ -207,21 +202,23 @@ IdList *sqliteIdListDup(IdList *p){
IdList *pNew;
int i;
if( p==0 ) return 0;
- pNew = sqliteMalloc( sizeof(*pNew) );
+ pNew = sqliteMallocRaw( sizeof(*pNew) );
if( pNew==0 ) return 0;
pNew->nId = pNew->nAlloc = p->nId;
- pNew->a = sqliteMalloc( p->nId*sizeof(p->a[0]) );
+ pNew->a = sqliteMallocRaw( p->nId*sizeof(p->a[0]) );
if( pNew->a==0 ) return 0;
for(i=0; i<p->nId; i++){
- pNew->a[i].zName = sqliteStrDup(p->a[i].zName);
- pNew->a[i].idx = p->a[i].idx;
+ struct IdList_item *pNewItem = &pNew->a[i];
+ struct IdList_item *pOldItem = &p->a[i];
+ pNewItem->zName = sqliteStrDup(pOldItem->zName);
+ pNewItem->idx = pOldItem->idx;
}
return pNew;
}
Select *sqliteSelectDup(Select *p){
Select *pNew;
if( p==0 ) return 0;
- pNew = sqliteMalloc( sizeof(*p) );
+ pNew = sqliteMallocRaw( sizeof(*p) );
if( pNew==0 ) return 0;
pNew->isDistinct = p->isDistinct;
pNew->pEList = sqliteExprListDup(p->pEList);
@@ -246,32 +243,31 @@ Select *sqliteSelectDup(Select *p){
** initially NULL, then create a new expression list.
*/
ExprList *sqliteExprListAppend(ExprList *pList, Expr *pExpr, Token *pName){
- int i;
if( pList==0 ){
pList = sqliteMalloc( sizeof(ExprList) );
if( pList==0 ){
- sqliteExprDelete(pExpr);
+ /* sqliteExprDelete(pExpr); // Leak memory if malloc fails */
return 0;
}
- pList->nAlloc = 0;
+ assert( pList->nAlloc==0 );
}
if( pList->nAlloc<=pList->nExpr ){
- struct ExprList_item *a;
pList->nAlloc = pList->nAlloc*2 + 4;
- a = sqliteRealloc(pList->a, pList->nAlloc*sizeof(pList->a[0]));
- if( a==0 ){
- sqliteExprDelete(pExpr);
+ pList->a = sqliteRealloc(pList->a, pList->nAlloc*sizeof(pList->a[0]));
+ if( pList->a==0 ){
+ /* sqliteExprDelete(pExpr); // Leak memory if malloc fails */
+ pList->nExpr = pList->nAlloc = 0;
return pList;
}
- pList->a = a;
}
- if( pList->a && (pExpr || pName) ){
- i = pList->nExpr++;
- memset(&pList->a[i], 0, sizeof(pList->a[i]));
- pList->a[i].pExpr = pExpr;
+ assert( pList->a!=0 );
+ if( pExpr || pName ){
+ struct ExprList_item *pItem = &pList->a[pList->nExpr++];
+ memset(pItem, 0, sizeof(*pItem));
+ pItem->pExpr = pExpr;
if( pName ){
- sqliteSetNString(&pList->a[i].zName, pName->z, pName->n, 0);
- sqliteDequote(pList->a[i].zName);
+ sqliteSetNString(&pItem->zName, pName->z, pName->n, 0);
+ sqliteDequote(pItem->zName);
}
}
return pList;
@@ -283,6 +279,8 @@ ExprList *sqliteExprListAppend(ExprList *pList, Expr *pExpr, Token *pName){
void sqliteExprListDelete(ExprList *pList){
int i;
if( pList==0 ) return;
+ assert( pList->a!=0 || (pList->nExpr==0 && pList->nAlloc==0) );
+ assert( pList->nExpr<=pList->nAlloc );
for(i=0; i<pList->nExpr; i++){
sqliteExprDelete(pList->a[i].pExpr);
sqliteFree(pList->a[i].zName);
@@ -380,6 +378,221 @@ int sqliteIsRowid(const char *z){
}
/*
+** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up
+** that name in the set of source tables in pSrcList and make the pExpr
+** expression node refer back to that source column. The following changes
+** are made to pExpr:
+**
+** pExpr->iDb Set the index in db->aDb[] of the database holding
+** the table.
+** pExpr->iTable Set to the cursor number for the table obtained
+** from pSrcList.
+** pExpr->iColumn Set to the column number within the table.
+** pExpr->dataType Set to the appropriate data type for the column.
+** pExpr->op Set to TK_COLUMN.
+** pExpr->pLeft Any expression this points to is deleted
+** pExpr->pRight Any expression this points to is deleted.
+**
+** The pDbToken is the name of the database (the "X"). This value may be
+** NULL meaning that name is of the form Y.Z or Z. Any available database
+** can be used. The pTableToken is the name of the table (the "Y"). This
+** value can be NULL if pDbToken is also NULL. If pTableToken is NULL it
+** means that the form of the name is Z and that columns from any table
+** can be used.
+**
+** If the name cannot be resolved unambiguously, leave an error message
+** in pParse and return non-zero. Return zero on success.
+*/
+static int lookupName(
+ Parse *pParse, /* The parsing context */
+ Token *pDbToken, /* Name of the database containing table, or NULL */
+ Token *pTableToken, /* Name of table containing column, or NULL */
+ Token *pColumnToken, /* Name of the column. */
+ SrcList *pSrcList, /* List of tables used to resolve column names */
+ ExprList *pEList, /* List of expressions used to resolve "AS" */
+ Expr *pExpr /* Make this EXPR node point to the selected column */
+){
+ char *zDb = 0; /* Name of the database. The "X" in X.Y.Z */
+ char *zTab = 0; /* Name of the table. The "Y" in X.Y.Z or Y.Z */
+ char *zCol = 0; /* Name of the column. The "Z" */
+ int i, j; /* Loop counters */
+ int cnt = 0; /* Number of matching column names */
+ int cntTab = 0; /* Number of matching table names */
+ sqlite *db = pParse->db; /* The database */
+
+ assert( pColumnToken && pColumnToken->z ); /* The Z in X.Y.Z cannot be NULL */
+ if( pDbToken && pDbToken->z ){
+ zDb = sqliteStrNDup(pDbToken->z, pDbToken->n);
+ sqliteDequote(zDb);
+ }else{
+ zDb = 0;
+ }
+ if( pTableToken && pTableToken->z ){
+ zTab = sqliteStrNDup(pTableToken->z, pTableToken->n);
+ sqliteDequote(zTab);
+ }else{
+ assert( zDb==0 );
+ zTab = 0;
+ }
+ zCol = sqliteStrNDup(pColumnToken->z, pColumnToken->n);
+ sqliteDequote(zCol);
+ if( sqlite_malloc_failed ){
+ return 1; /* Leak memory (zDb and zTab) if malloc fails */
+ }
+ assert( zTab==0 || pEList==0 );
+
+ pExpr->iTable = -1;
+ for(i=0; i<pSrcList->nSrc; i++){
+ struct SrcList_item *pItem = &pSrcList->a[i];
+ Table *pTab = pItem->pTab;
+ Column *pCol;
+
+ if( pTab==0 ) continue;
+ assert( pTab->nCol>0 );
+ if( zTab ){
+ if( pItem->zAlias ){
+ char *zTabName = pItem->zAlias;
+ if( sqliteStrICmp(zTabName, zTab)!=0 ) continue;
+ }else{
+ char *zTabName = pTab->zName;
+ if( zTabName==0 || sqliteStrICmp(zTabName, zTab)!=0 ) continue;
+ if( zDb!=0 && sqliteStrICmp(db->aDb[pTab->iDb].zName, zDb)!=0 ){
+ continue;
+ }
+ }
+ }
+ if( 0==(cntTab++) ){
+ pExpr->iTable = pItem->iCursor;
+ pExpr->iDb = pTab->iDb;
+ }
+ for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
+ if( sqliteStrICmp(pCol->zName, zCol)==0 ){
+ cnt++;
+ pExpr->iTable = pItem->iCursor;
+ pExpr->iDb = pTab->iDb;
+ /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
+ pExpr->iColumn = j==pTab->iPKey ? -1 : j;
+ pExpr->dataType = pCol->sortOrder & SQLITE_SO_TYPEMASK;
+ break;
+ }
+ }
+ }
+
+ /* If we have not already resolved the name, then maybe
+ ** it is a new.* or old.* trigger argument reference
+ */
+ if( zDb==0 && zTab!=0 && cnt==0 && pParse->trigStack!=0 ){
+ TriggerStack *pTriggerStack = pParse->trigStack;
+ Table *pTab = 0;
+ if( pTriggerStack->newIdx != -1 && sqliteStrICmp("new", zTab) == 0 ){
+ pExpr->iTable = pTriggerStack->newIdx;
+ assert( pTriggerStack->pTab );
+ pTab = pTriggerStack->pTab;
+ }else if( pTriggerStack->oldIdx != -1 && sqliteStrICmp("old", zTab) == 0 ){
+ pExpr->iTable = pTriggerStack->oldIdx;
+ assert( pTriggerStack->pTab );
+ pTab = pTriggerStack->pTab;
+ }
+
+ if( pTab ){
+ int j;
+ Column *pCol = pTab->aCol;
+
+ pExpr->iDb = pTab->iDb;
+ cntTab++;
+ for(j=0; j < pTab->nCol; j++, pCol++) {
+ if( sqliteStrICmp(pCol->zName, zCol)==0 ){
+ cnt++;
+ pExpr->iColumn = j==pTab->iPKey ? -1 : j;
+ pExpr->dataType = pCol->sortOrder & SQLITE_SO_TYPEMASK;
+ break;
+ }
+ }
+ }
+ }
+
+ /*
+ ** Perhaps the name is a reference to the ROWID
+ */
+ if( cnt==0 && cntTab==1 && sqliteIsRowid(zCol) ){
+ cnt = 1;
+ pExpr->iColumn = -1;
+ pExpr->dataType = SQLITE_SO_NUM;
+ }
+
+ /*
+ ** If the input is of the form Z (not Y.Z or X.Y.Z) then the name Z
+ ** might refer to an result-set alias. This happens, for example, when
+ ** we are resolving names in the WHERE clause of the following command:
+ **
+ ** SELECT a+b AS x FROM table WHERE x<10;
+ **
+ ** In cases like this, replace pExpr with a copy of the expression that
+ ** forms the result set entry ("a+b" in the example) and return immediately.
+ ** Note that the expression in the result set should have already been
+ ** resolved by the time the WHERE clause is resolved.
+ */
+ if( cnt==0 && pEList!=0 ){
+ for(j=0; j<pEList->nExpr; j++){
+ char *zAs = pEList->a[j].zName;
+ if( zAs!=0 && sqliteStrICmp(zAs, zCol)==0 ){
+ assert( pExpr->pLeft==0 && pExpr->pRight==0 );
+ pExpr->op = TK_AS;
+ pExpr->iColumn = j;
+ pExpr->pLeft = sqliteExprDup(pEList->a[j].pExpr);
+ sqliteFree(zCol);
+ assert( zTab==0 && zDb==0 );
+ return 0;
+ }
+ }
+ }
+
+ /*
+ ** If X and Y are NULL (in other words if only the column name Z is
+ ** supplied) and the value of Z is enclosed in double-quotes, then
+ ** Z is a string literal if it doesn't match any column names. In that
+ ** case, we need to return right away and not make any changes to
+ ** pExpr.
+ */
+ if( cnt==0 && zTab==0 && pColumnToken->z[0]=='"' ){
+ sqliteFree(zCol);
+ return 0;
+ }
+
+ /*
+ ** cnt==0 means there was not match. cnt>1 means there were two or
+ ** more matches. Either way, we have an error.
+ */
+ if( cnt!=1 ){
+ char *z = 0;
+ char *zErr;
+ zErr = cnt==0 ? "no such column: %s" : "ambiguous column name: %s";
+ if( zDb ){
+ sqliteSetString(&z, zDb, ".", zTab, ".", zCol, 0);
+ }else if( zTab ){
+ sqliteSetString(&z, zTab, ".", zCol, 0);
+ }else{
+ z = sqliteStrDup(zCol);
+ }
+ sqliteErrorMsg(pParse, zErr, z);
+ sqliteFree(z);
+ }
+
+ /* Clean up and return
+ */
+ sqliteFree(zDb);
+ sqliteFree(zTab);
+ sqliteFree(zCol);
+ sqliteExprDelete(pExpr->pLeft);
+ pExpr->pLeft = 0;
+ sqliteExprDelete(pExpr->pRight);
+ pExpr->pRight = 0;
+ pExpr->op = TK_COLUMN;
+ sqliteAuthRead(pParse, pExpr, pSrcList);
+ return cnt!=1;
+}
+
+/*
** This routine walks an expression tree and resolves references to
** table columns. Nodes of the form ID.ID or ID resolve into an
** index to the table in the table list and a column offset. The
@@ -412,15 +625,15 @@ int sqliteIsRowid(const char *z){
*/
int sqliteExprResolveIds(
Parse *pParse, /* The parser context */
- SrcList *pTabList, /* List of tables used to resolve column names */
+ SrcList *pSrcList, /* List of tables used to resolve column names */
ExprList *pEList, /* List of expressions used to resolve "AS" */
Expr *pExpr /* The expression to be analyzed. */
){
int i;
- if( pExpr==0 || pTabList==0 ) return 0;
- for(i=0; i<pTabList->nSrc; i++){
- assert( pTabList->a[i].iCursor>=0 && pTabList->a[i].iCursor<pParse->nTab );
+ if( pExpr==0 || pSrcList==0 ) return 0;
+ for(i=0; i<pSrcList->nSrc; i++){
+ assert( pSrcList->a[i].iCursor>=0 && pSrcList->a[i].iCursor<pParse->nTab );
}
switch( pExpr->op ){
/* Double-quoted strings (ex: "abc") are used as identifiers if
@@ -431,79 +644,11 @@ int sqliteExprResolveIds(
if( pExpr->token.z[0]=='\'' ) break;
/* Fall thru into the TK_ID case if this is a double-quoted string */
}
- /* A lone identifier. Try and match it as follows:
- **
- ** 1. To the name of a column of one of the tables in pTabList
- **
- ** 2. To the right side of an AS keyword in the column list of
- ** a SELECT statement. (For example, match against 'x' in
- ** "SELECT a+b AS 'x' FROM t1".)
- **
- ** 3. One of the special names "ROWID", "OID", or "_ROWID_".
+ /* A lone identifier is the name of a columnd.
*/
case TK_ID: {
- int cnt = 0; /* Number of matches */
- char *z;
- int iDb = -1;
-
- assert( pExpr->token.z );
- z = sqliteStrNDup(pExpr->token.z, pExpr->token.n);
- sqliteDequote(z);
- if( z==0 ) return 1;
- for(i=0; i<pTabList->nSrc; i++){
- int j;
- Table *pTab = pTabList->a[i].pTab;
- if( pTab==0 ) continue;
- iDb = pTab->iDb;
- assert( pTab->nCol>0 );
- for(j=0; j<pTab->nCol; j++){
- if( sqliteStrICmp(pTab->aCol[j].zName, z)==0 ){
- cnt++;
- pExpr->iTable = pTabList->a[i].iCursor;
- pExpr->iDb = pTab->iDb;
- if( j==pTab->iPKey ){
- /* Substitute the record number for the INTEGER PRIMARY KEY */
- pExpr->iColumn = -1;
- pExpr->dataType = SQLITE_SO_NUM;
- }else{
- pExpr->iColumn = j;
- pExpr->dataType = pTab->aCol[j].sortOrder & SQLITE_SO_TYPEMASK;
- }
- pExpr->op = TK_COLUMN;
- }
- }
- }
- if( cnt==0 && pEList!=0 ){
- int j;
- for(j=0; j<pEList->nExpr; j++){
- char *zAs = pEList->a[j].zName;
- if( zAs!=0 && sqliteStrICmp(zAs, z)==0 ){
- cnt++;
- assert( pExpr->pLeft==0 && pExpr->pRight==0 );
- pExpr->op = TK_AS;
- pExpr->iColumn = j;
- pExpr->pLeft = sqliteExprDup(pEList->a[j].pExpr);
- }
- }
- }
- if( cnt==0 && iDb>=0 && sqliteIsRowid(z) ){
- pExpr->iColumn = -1;
- pExpr->iTable = pTabList->a[0].iCursor;
- pExpr->iDb = iDb;
- cnt = 1 + (pTabList->nSrc>1);
- pExpr->op = TK_COLUMN;
- pExpr->dataType = SQLITE_SO_NUM;
- }
- sqliteFree(z);
- if( cnt==0 && pExpr->token.z[0]!='"' ){
- sqliteErrorMsg(pParse, "no such column: %T", &pExpr->token);
+ if( lookupName(pParse, 0, 0, &pExpr->token, pSrcList, pEList, pExpr) ){
return 1;
- }else if( cnt>1 ){
- sqliteErrorMsg(pParse, "ambiguous column name: %T", &pExpr->token);
- return 1;
- }
- if( pExpr->op==TK_COLUMN ){
- sqliteAuthRead(pParse, pExpr, pTabList);
}
break;
}
@@ -512,134 +657,32 @@ int sqliteExprResolveIds(
** Or a database, table and column: ID.ID.ID
*/
case TK_DOT: {
- int cnt = 0; /* Number of matches */
- int cntTab = 0; /* Number of matching tables */
- int i; /* Loop counter */
- Expr *pLeft, *pRight; /* Left and right subbranches of the expr */
- char *zLeft, *zRight; /* Text of an identifier */
- char *zDb; /* Name of database holding table */
- sqlite *db = pParse->db;
+ Token *pColumn;
+ Token *pTable;
+ Token *pDb;
+ Expr *pRight;
pRight = pExpr->pRight;
if( pRight->op==TK_ID ){
- pLeft = pExpr->pLeft;
- zDb = 0;
+ pDb = 0;
+ pTable = &pExpr->pLeft->token;
+ pColumn = &pRight->token;
}else{
- Expr *pDb = pExpr->pLeft;
- assert( pDb && pDb->op==TK_ID && pDb->token.z );
- zDb = sqliteStrNDup(pDb->token.z, pDb->token.n);
- pLeft = pRight->pLeft;
- pRight = pRight->pRight;
+ assert( pRight->op==TK_DOT );
+ pDb = &pExpr->pLeft->token;
+ pTable = &pRight->pLeft->token;
+ pColumn = &pRight->pRight->token;
}
- assert( pLeft && pLeft->op==TK_ID && pLeft->token.z );
- assert( pRight && pRight->op==TK_ID && pRight->token.z );
- zLeft = sqliteStrNDup(pLeft->token.z, pLeft->token.n);
- zRight = sqliteStrNDup(pRight->token.z, pRight->token.n);
- if( zLeft==0 || zRight==0 ){
- sqliteFree(zLeft);
- sqliteFree(zRight);
- sqliteFree(zDb);
+ if( lookupName(pParse, pDb, pTable, pColumn, pSrcList, 0, pExpr) ){
return 1;
}
- sqliteDequote(zDb);
- sqliteDequote(zLeft);
- sqliteDequote(zRight);
- pExpr->iTable = -1;
- for(i=0; i<pTabList->nSrc; i++){
- int j;
- char *zTab;
- Table *pTab = pTabList->a[i].pTab;
- if( pTab==0 ) continue;
- assert( pTab->nCol>0 );
- if( pTabList->a[i].zAlias ){
- zTab = pTabList->a[i].zAlias;
- if( sqliteStrICmp(zTab, zLeft)!=0 ) continue;
- }else{
- zTab = pTab->zName;
- if( zTab==0 || sqliteStrICmp(zTab, zLeft)!=0 ) continue;
- if( zDb!=0 && sqliteStrICmp(db->aDb[pTab->iDb].zName, zDb)!=0 ){
- continue;
- }
- }
- if( 0==(cntTab++) ){
- pExpr->iTable = pTabList->a[i].iCursor;
- pExpr->iDb = pTab->iDb;
- }
- for(j=0; j<pTab->nCol; j++){
- if( sqliteStrICmp(pTab->aCol[j].zName, zRight)==0 ){
- cnt++;
- pExpr->iTable = pTabList->a[i].iCursor;
- pExpr->iDb = pTab->iDb;
- /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
- pExpr->iColumn = j==pTab->iPKey ? -1 : j;
- pExpr->dataType = pTab->aCol[j].sortOrder & SQLITE_SO_TYPEMASK;
- }
- }
- }
-
- /* If we have not already resolved this *.* expression, then maybe
- * it is a new.* or old.* trigger argument reference */
- if( cnt == 0 && pParse->trigStack != 0 ){
- TriggerStack *pTriggerStack = pParse->trigStack;
- int t = 0;
- if( pTriggerStack->newIdx != -1 && sqliteStrICmp("new", zLeft) == 0 ){
- pExpr->iTable = pTriggerStack->newIdx;
- assert( pTriggerStack->pTab );
- pExpr->iDb = pTriggerStack->pTab->iDb;
- cntTab++;
- t = 1;
- }
- if( pTriggerStack->oldIdx != -1 && sqliteStrICmp("old", zLeft) == 0 ){
- pExpr->iTable = pTriggerStack->oldIdx;
- assert( pTriggerStack->pTab );
- pExpr->iDb = pTriggerStack->pTab->iDb;
- cntTab++;
- t = 1;
- }
-
- if( t ){
- int j;
- Table *pTab = pTriggerStack->pTab;
- for(j=0; j < pTab->nCol; j++) {
- if( sqliteStrICmp(pTab->aCol[j].zName, zRight)==0 ){
- cnt++;
- pExpr->iColumn = j==pTab->iPKey ? -1 : j;
- pExpr->dataType = pTab->aCol[j].sortOrder & SQLITE_SO_TYPEMASK;
- }
- }
- }
- }
-
- if( cnt==0 && cntTab==1 && sqliteIsRowid(zRight) ){
- cnt = 1;
- pExpr->iColumn = -1;
- pExpr->dataType = SQLITE_SO_NUM;
- }
- sqliteFree(zDb);
- sqliteFree(zLeft);
- sqliteFree(zRight);
- if( cnt==0 ){
- sqliteErrorMsg(pParse, "no such column: %T.%T",
- &pLeft->token, &pRight->token);
- return 1;
- }else if( cnt>1 ){
- sqliteErrorMsg(pParse, "ambiguous column name: %T.%T",
- &pLeft->token, &pRight->token);
- return 1;
- }
- sqliteExprDelete(pExpr->pLeft);
- pExpr->pLeft = 0;
- sqliteExprDelete(pExpr->pRight);
- pExpr->pRight = 0;
- pExpr->op = TK_COLUMN;
- sqliteAuthRead(pParse, pExpr, pTabList);
break;
}
case TK_IN: {
Vdbe *v = sqliteGetVdbe(pParse);
if( v==0 ) return 1;
- if( sqliteExprResolveIds(pParse, pTabList, pEList, pExpr->pLeft) ){
+ if( sqliteExprResolveIds(pParse, pSrcList, pEList, pExpr->pLeft) ){
return 1;
}
if( pExpr->pSelect ){
@@ -677,9 +720,10 @@ int sqliteExprResolveIds(
case TK_FLOAT:
case TK_INTEGER:
case TK_STRING: {
- int addr = sqliteVdbeAddOp(v, OP_SetInsert, iSet, 0);
+ int addr;
assert( pE2->token.z );
- sqliteVdbeChangeP3(v, addr, pE2->token.z, pE2->token.n);
+ addr = sqliteVdbeOp3(v, OP_SetInsert, iSet, 0,
+ pE2->token.z, pE2->token.n);
sqliteVdbeDequoteP3(v, addr);
break;
}
@@ -709,11 +753,11 @@ int sqliteExprResolveIds(
/* For all else, just recursively walk the tree */
default: {
if( pExpr->pLeft
- && sqliteExprResolveIds(pParse, pTabList, pEList, pExpr->pLeft) ){
+ && sqliteExprResolveIds(pParse, pSrcList, pEList, pExpr->pLeft) ){
return 1;
}
if( pExpr->pRight
- && sqliteExprResolveIds(pParse, pTabList, pEList, pExpr->pRight) ){
+ && sqliteExprResolveIds(pParse, pSrcList, pEList, pExpr->pRight) ){
return 1;
}
if( pExpr->pList ){
@@ -721,7 +765,7 @@ int sqliteExprResolveIds(
ExprList *pList = pExpr->pList;
for(i=0; i<pList->nExpr; i++){
Expr *pArg = pList->a[i].pExpr;
- if( sqliteExprResolveIds(pParse, pTabList, pEList, pArg) ){
+ if( sqliteExprResolveIds(pParse, pSrcList, pEList, pArg) ){
return 1;
}
}
@@ -782,7 +826,6 @@ int sqliteExprCheck(Parse *pParse, Expr *pExpr, int allowAgg, int *pIsAgg){
case TK_FUNCTION: {
int n = pExpr->pList ? pExpr->pList->nExpr : 0; /* Number of arguments */
int no_such_func = 0; /* True if no such function exists */
- int is_type_of = 0; /* True if is the special TypeOf() function */
int wrong_num_args = 0; /* True if wrong number of arguments */
int is_agg = 0; /* True if is an aggregate function */
int i;
@@ -795,11 +838,7 @@ int sqliteExprCheck(Parse *pParse, Expr *pExpr, int allowAgg, int *pIsAgg){
if( pDef==0 ){
pDef = sqliteFindFunction(pParse->db, zId, nId, -1, 0);
if( pDef==0 ){
- if( n==1 && nId==6 && sqliteStrNICmp(zId, "typeof", 6)==0 ){
- is_type_of = 1;
- }else {
- no_such_func = 1;
- }
+ no_such_func = 1;
}else{
wrong_num_args = 1;
}
@@ -807,38 +846,27 @@ int sqliteExprCheck(Parse *pParse, Expr *pExpr, int allowAgg, int *pIsAgg){
is_agg = pDef->xFunc==0;
}
if( is_agg && !allowAgg ){
- sqliteSetNString(&pParse->zErrMsg, "misuse of aggregate function ", -1,
- zId, nId, "()", 2, 0);
- pParse->nErr++;
+ sqliteErrorMsg(pParse, "misuse of aggregate function %.*s()", nId, zId);
nErr++;
is_agg = 0;
}else if( no_such_func ){
- sqliteSetNString(&pParse->zErrMsg, "no such function: ", -1, zId,nId,0);
- pParse->nErr++;
+ sqliteErrorMsg(pParse, "no such function: %.*s", nId, zId);
nErr++;
}else if( wrong_num_args ){
- sqliteSetNString(&pParse->zErrMsg,
- "wrong number of arguments to function ", -1, zId, nId, "()", 2, 0);
- pParse->nErr++;
+ sqliteErrorMsg(pParse,"wrong number of arguments to function %.*s()",
+ nId, zId);
nErr++;
}
- if( is_agg ) pExpr->op = TK_AGG_FUNCTION;
- if( is_agg && pIsAgg ) *pIsAgg = 1;
+ if( is_agg ){
+ pExpr->op = TK_AGG_FUNCTION;
+ if( pIsAgg ) *pIsAgg = 1;
+ }
for(i=0; nErr==0 && i<n; i++){
nErr = sqliteExprCheck(pParse, pExpr->pList->a[i].pExpr,
allowAgg && !is_agg, pIsAgg);
}
if( pDef==0 ){
- if( is_type_of ){
- pExpr->op = TK_STRING;
- if( sqliteExprType(pExpr->pList->a[0].pExpr)==SQLITE_SO_NUM ){
- pExpr->token.z = "numeric";
- pExpr->token.n = 7;
- }else{
- pExpr->token.z = "text";
- pExpr->token.n = 4;
- }
- }
+ /* Already reported an error */
}else if( pDef->dataType>=0 ){
if( pDef->dataType<n ){
pExpr->dataType =
@@ -973,8 +1001,6 @@ int sqliteExprType(Expr *p){
return SQLITE_SO_NUM;
}
-/* Run */
-
/*
** Generate code into the current Vdbe to evaluate the given
** expression and leave the result on the top of stack.
@@ -1019,26 +1045,17 @@ void sqliteExprCode(Parse *pParse, Expr *pExpr){
}
break;
}
+ case TK_STRING:
+ case TK_FLOAT:
case TK_INTEGER: {
- if( !sqliteFitsIn32Bits(pExpr->token.z) ){
- sqliteVdbeAddOp(v, OP_String, 0, 0);
- }else{
+ if( pExpr->op==TK_INTEGER && sqliteFitsIn32Bits(pExpr->token.z) ){
sqliteVdbeAddOp(v, OP_Integer, atoi(pExpr->token.z), 0);
+ }else{
+ sqliteVdbeAddOp(v, OP_String, 0, 0);
}
- sqliteVdbeChangeP3(v, -1, pExpr->token.z, pExpr->token.n);
- break;
- }
- case TK_FLOAT: {
- sqliteVdbeAddOp(v, OP_String, 0, 0);
assert( pExpr->token.z );
sqliteVdbeChangeP3(v, -1, pExpr->token.z, pExpr->token.n);
- break;
- }
- case TK_STRING: {
- int addr = sqliteVdbeAddOp(v, OP_String, 0, 0);
- assert( pExpr->token.z );
- sqliteVdbeChangeP3(v, addr, pExpr->token.z, pExpr->token.n);
- sqliteVdbeDequoteP3(v, addr);
+ sqliteVdbeDequoteP3(v, -1);
break;
}
case TK_NULL: {
@@ -1087,23 +1104,6 @@ void sqliteExprCode(Parse *pParse, Expr *pExpr){
sqliteVdbeAddOp(v, OP_Concat, 2, 0);
break;
}
- case TK_UPLUS: {
- Expr *pLeft = pExpr->pLeft;
- if( pLeft && pLeft->op==TK_INTEGER ){
- if( sqliteFitsIn32Bits(pLeft->token.z) ){
- sqliteVdbeAddOp(v, OP_Integer, atoi(pLeft->token.z), 0);
- }else{
- sqliteVdbeAddOp(v, OP_String, 0, 0);
- }
- sqliteVdbeChangeP3(v, -1, pLeft->token.z, pLeft->token.n);
- }else if( pLeft && pLeft->op==TK_FLOAT ){
- sqliteVdbeAddOp(v, OP_String, 0, 0);
- sqliteVdbeChangeP3(v, -1, pLeft->token.z, pLeft->token.n);
- }else{
- sqliteExprCode(pParse, pExpr->pLeft);
- }
- break;
- }
case TK_UMINUS: {
assert( pExpr->pLeft );
if( pExpr->pLeft->op==TK_FLOAT || pExpr->pLeft->op==TK_INTEGER ){
@@ -1144,7 +1144,6 @@ void sqliteExprCode(Parse *pParse, Expr *pExpr){
case TK_GLOB:
case TK_LIKE:
case TK_FUNCTION: {
- int i;
ExprList *pList = pExpr->pList;
int nExpr = pList ? pList->nExpr : 0;
FuncDef *pDef;
@@ -1153,11 +1152,8 @@ void sqliteExprCode(Parse *pParse, Expr *pExpr){
getFunctionName(pExpr, &zId, &nId);
pDef = sqliteFindFunction(pParse->db, zId, nId, nExpr, 0);
assert( pDef!=0 );
- for(i=0; i<nExpr; i++){
- sqliteExprCode(pParse, pList->a[i].pExpr);
- }
- sqliteVdbeAddOp(v, OP_Function, nExpr, 0);
- sqliteVdbeChangeP3(v, -1, (char*)pDef, P3_POINTER);
+ nExpr = sqliteExprCodeExprList(pParse, pList, pDef->includeTypes);
+ sqliteVdbeOp3(v, OP_Function, nExpr, 0, (char*)pDef, P3_POINTER);
break;
}
case TK_SELECT: {
@@ -1170,7 +1166,7 @@ void sqliteExprCode(Parse *pParse, Expr *pExpr){
sqliteExprCode(pParse, pExpr->pLeft);
addr = sqliteVdbeCurrentAddr(v);
sqliteVdbeAddOp(v, OP_NotNull, -1, addr+4);
- sqliteVdbeAddOp(v, OP_Pop, 1, 0);
+ sqliteVdbeAddOp(v, OP_Pop, 2, 0);
sqliteVdbeAddOp(v, OP_String, 0, 0);
sqliteVdbeAddOp(v, OP_Goto, 0, addr+6);
if( pExpr->pSelect ){
@@ -1192,6 +1188,7 @@ void sqliteExprCode(Parse *pParse, Expr *pExpr){
sqliteVdbeAddOp(v, OP_And, 0, 0);
break;
}
+ case TK_UPLUS:
case TK_AS: {
sqliteExprCode(pParse, pExpr->pLeft);
break;
@@ -1246,15 +1243,13 @@ void sqliteExprCode(Parse *pParse, Expr *pExpr){
if( pExpr->iColumn == OE_Rollback ||
pExpr->iColumn == OE_Abort ||
pExpr->iColumn == OE_Fail ){
- char * msg = sqliteStrNDup(pExpr->token.z, pExpr->token.n);
- sqliteVdbeAddOp(v, OP_Halt, SQLITE_CONSTRAINT, pExpr->iColumn);
- sqliteDequote(msg);
- sqliteVdbeChangeP3(v, -1, msg, 0);
- sqliteFree(msg);
+ sqliteVdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, pExpr->iColumn,
+ pExpr->token.z, pExpr->token.n);
+ sqliteVdbeDequoteP3(v, -1);
} else {
assert( pExpr->iColumn == OE_Ignore );
- sqliteVdbeAddOp(v, OP_Goto, 0, pParse->trigStack->ignoreJump);
- sqliteVdbeChangeP3(v, -1, "(IGNORE jump)", 0);
+ sqliteVdbeOp3(v, OP_Goto, 0, pParse->trigStack->ignoreJump,
+ "(IGNORE jump)", 0);
}
}
break;
@@ -1262,6 +1257,36 @@ void sqliteExprCode(Parse *pParse, Expr *pExpr){
}
/*
+** Generate code that pushes the value of every element of the given
+** expression list onto the stack. If the includeTypes flag is true,
+** then also push a string that is the datatype of each element onto
+** the stack after the value.
+**
+** Return the number of elements pushed onto the stack.
+*/
+int sqliteExprCodeExprList(
+ Parse *pParse, /* Parsing context */
+ ExprList *pList, /* The expression list to be coded */
+ int includeTypes /* TRUE to put datatypes on the stack too */
+){
+ struct ExprList_item *pItem;
+ int i, n;
+ Vdbe *v;
+ if( pList==0 ) return 0;
+ v = sqliteGetVdbe(pParse);
+ n = pList->nExpr;
+ for(pItem=pList->a, i=0; i<n; i++, pItem++){
+ sqliteExprCode(pParse, pItem->pExpr);
+ if( includeTypes ){
+ sqliteVdbeOp3(v, OP_String, 0, 0,
+ sqliteExprType(pItem->pExpr)==SQLITE_SO_NUM ? "numeric" : "text",
+ P3_STATIC);
+ }
+ }
+ return includeTypes ? n*2 : n;
+}
+
+/*
** Generate code for a boolean expression such that a jump is made
** to the label "dest" if the expression is true but execution
** continues straight thru if the expression is false.