DBD-SQLite2
view release on metacpan or search on metacpan
/*
** If the given expression codes a constant integer that is small enough
** to fit in a 32-bit integer, return 1 and put the value of the integer
** in *pValue. If the expression is not an integer or if it is too big
** to fit in a signed 32-bit integer, return 0 and leave *pValue unchanged.
*/
int sqliteExprIsInteger(Expr *p, int *pValue){
switch( p->op ){
case TK_INTEGER: {
if( sqliteFitsIn32Bits(p->token.z) ){
*pValue = atoi(p->token.z);
return 1;
}
break;
}
case TK_STRING: {
const char *z = p->token.z;
int n = p->token.n;
if( n>0 && z[0]=='-' ){ z++; n--; }
while( n>0 && *z && isdigit(*z) ){ z++; n--; }
if( n==0 && sqliteFitsIn32Bits(p->token.z) ){
*pValue = atoi(p->token.z);
return 1;
}
break;
}
case TK_UPLUS: {
return sqliteExprIsInteger(p->pLeft, pValue);
}
case TK_UMINUS: {
int v;
if( sqliteExprIsInteger(p->pLeft, &v) ){
*pValue = -v;
return 1;
}
break;
}
default: break;
}
return 0;
}
/*
** Return TRUE if the given string is a row-id column name.
*/
int sqliteIsRowid(const char *z){
if( sqliteStrICmp(z, "_ROWID_")==0 ) return 1;
if( sqliteStrICmp(z, "ROWID")==0 ) return 1;
if( sqliteStrICmp(z, "OID")==0 ) return 1;
return 0;
}
/*
** 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;
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
** Expr.opcode for such nodes is changed to TK_COLUMN. The Expr.iTable
** value is changed to the index of the referenced table in pTabList
** plus the "base" value. The base value will ultimately become the
** VDBE cursor number for a cursor that is pointing into the referenced
** table. The Expr.iColumn value is changed to the index of the column
** of the referenced table. The Expr.iColumn value for the special
** ROWID column is -1. Any INTEGER PRIMARY KEY column is tried as an
** alias for ROWID.
**
** We also check for instances of the IN operator. IN comes in two
** forms:
**
** expr IN (exprlist)
** and
** expr IN (SELECT ...)
**
** The first form is handled by creating a set holding the list
** of allowed values. The second form causes the SELECT to generate
** a temporary table.
**
** This routine also looks for scalar SELECTs that are part of an expression.
** If it finds any, it generates code to write the value of that select
** into a memory cell.
**
** Unknown columns or tables provoke an error. The function returns
** the number of errors seen and leaves an error message on pParse->zErrMsg.
*/
int sqliteExprResolveIds(
Parse *pParse, /* The parser context */
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 || 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
** possible. Otherwise they remain as strings. Single-quoted
** strings (ex: 'abc') are always string literals.
*/
case TK_STRING: {
if( pExpr->token.z[0]=='\'' ) break;
/* Fall thru into the TK_ID case if this is a double-quoted string */
}
/* A lone identifier is the name of a columnd.
*/
case TK_ID: {
if( lookupName(pParse, 0, 0, &pExpr->token, pSrcList, pEList, pExpr) ){
return 1;
}
break;
}
/* A table name and column name: ID.ID
** Or a database, table and column: ID.ID.ID
*/
case TK_DOT: {
Token *pColumn;
Token *pTable;
Token *pDb;
Expr *pRight;
pRight = pExpr->pRight;
if( pRight->op==TK_ID ){
pDb = 0;
pTable = &pExpr->pLeft->token;
pColumn = &pRight->token;
}else{
assert( pRight->op==TK_DOT );
pDb = &pExpr->pLeft->token;
pTable = &pRight->pLeft->token;
pColumn = &pRight->pRight->token;
}
if( lookupName(pParse, pDb, pTable, pColumn, pSrcList, 0, pExpr) ){
return 1;
}
break;
}
case TK_IN: {
Vdbe *v = sqliteGetVdbe(pParse);
if( v==0 ) return 1;
if( sqliteExprResolveIds(pParse, pSrcList, pEList, pExpr->pLeft) ){
return 1;
}
if( pExpr->pSelect ){
/* Case 1: expr IN (SELECT ...)
**
** Generate code to write the results of the select into a temporary
** table. The cursor number of the temporary table has already
** been put in iTable by sqliteExprResolveInSelect().
*/
pExpr->iTable = pParse->nTab++;
sqliteVdbeAddOp(v, OP_OpenTemp, pExpr->iTable, 1);
sqliteSelect(pParse, pExpr->pSelect, SRT_Set, pExpr->iTable, 0,0,0);
}else if( pExpr->pList ){
/* Case 2: expr IN (exprlist)
**
** Create a set to put the exprlist values in. The Set id is stored
** in iTable.
*/
int i, iSet;
for(i=0; i<pExpr->pList->nExpr; i++){
Expr *pE2 = pExpr->pList->a[i].pExpr;
if( !sqliteExprIsConstant(pE2) ){
sqliteErrorMsg(pParse,
"right-hand side of IN operator must be constant");
return 1;
}
if( sqliteExprCheck(pParse, pE2, 0, 0) ){
return 1;
}
}
iSet = pExpr->iTable = pParse->nSet++;
for(i=0; i<pExpr->pList->nExpr; i++){
Expr *pE2 = pExpr->pList->a[i].pExpr;
switch( pE2->op ){
case TK_FLOAT:
case TK_INTEGER:
case TK_STRING: {
int addr;
assert( pE2->token.z );
addr = sqliteVdbeOp3(v, OP_SetInsert, iSet, 0,
pE2->token.z, pE2->token.n);
sqliteVdbeDequoteP3(v, addr);
break;
}
default: {
sqliteExprCode(pParse, pE2);
sqliteVdbeAddOp(v, OP_SetInsert, iSet, 0);
break;
}
}
}
}
break;
}
case TK_SELECT: {
/* This has to be a scalar SELECT. Generate code to put the
** value of this select in a memory cell and record the number
** of the memory cell in iColumn.
*/
pExpr->iColumn = pParse->nMem++;
if( sqliteSelect(pParse, pExpr->pSelect, SRT_Mem, pExpr->iColumn,0,0,0) ){
return 1;
}
break;
}
( run in 0.935 second using v1.01-cache-2.11-cpan-13bb782fe5a )