⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 expr.c

📁 sqlite数据库管理系统开放源码
💻 C
📖 第 1 页 / 共 4 页
字号:
){  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 ** 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;    }    /* For all else, just recursively walk the tree */    default: {      if( pExpr->pLeft      && sqliteExprResolveIds(pParse, pSrcList, pEList, pExpr->pLeft) ){        return 1;      }      if( pExpr->pRight       && sqliteExprResolveIds(pParse, pSrcList, pEList, pExpr->pRight) ){        return 1;      }      if( pExpr->pList ){        int i;        ExprList *pList = pExpr->pList;        for(i=0; i<pList->nExpr; i++){          Expr *pArg = pList->a[i].pExpr;          if( sqliteExprResolveIds(pParse, pSrcList, pEList, pArg) ){            return 1;          }        }      }    }  }  return 0;}/*** pExpr is a node that defines a function of some kind.  It might** be a syntactic function like "count(x)" or it might be a function** that implements an operator, like "a LIKE b".  **** This routine makes *pzName point to the name of the function and ** *pnName hold the number of characters in the function name.*/static void getFunctionName(Expr *pExpr, const char **pzName, int *pnName){  switch( pExpr->op ){    case TK_FUNCTION: {      *pzName = pExpr->token.z;      *pnName = pExpr->token.n;      break;    }    case TK_LIKE: {      *pzName = "like";      *pnName = 4;      break;    }    case TK_GLOB: {      *pzName = "glob";      *pnName = 4;      break;    }    default: {      *pzName = "can't happen";      *pnName = 12;      break;    }  }}/*** Error check the functions in an expression.  Make sure all** function names are recognized and all functions have the correct** number of arguments.  Leave an error message in pParse->zErrMsg** if anything is amiss.  Return the number of errors.**** if pIsAgg is not null and this expression is an aggregate function** (like count(*) or max(value)) then write a 1 into *pIsAgg.*/int sqliteExprCheck(Parse *pParse, Expr *pExpr, int allowAgg, int *pIsAgg){  int nErr = 0;  if( pExpr==0 ) return 0;  switch( pExpr->op ){    case TK_GLOB:    case TK_LIKE:    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 wrong_num_args = 0;     /* True if wrong number of arguments */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -