?? expr.c
字號:
if( auth!=SQLITE_OK ){
if( auth==SQLITE_DENY ){
sqlite3ErrorMsg(pParse, "not authorized to use function: %s",
pDef->zName);
pNC->nErr++;
}
pExpr->op = TK_NULL;
return 1;
}
}
#endif
if( is_agg && !pNC->allowAgg ){
sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId);
pNC->nErr++;
is_agg = 0;
}else if( no_such_func ){
sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId);
pNC->nErr++;
}else if( wrong_num_args ){
sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()",
nId, zId);
pNC->nErr++;
}
if( is_agg ){
pExpr->op = TK_AGG_FUNCTION;
pNC->hasAgg = 1;
}
if( is_agg ) pNC->allowAgg = 0;
for(i=0; pNC->nErr==0 && i<n; i++){
walkExprTree(pList->a[i].pExpr, nameResolverStep, pNC);
}
if( is_agg ) pNC->allowAgg = 1;
/* FIX ME: Compute pExpr->affinity based on the expected return
** type of the function
*/
return is_agg;
}
#ifndef SQLITE_OMIT_SUBQUERY
case TK_SELECT:
case TK_EXISTS:
#endif
case TK_IN: {
if( pExpr->pSelect ){
int nRef = pNC->nRef;
#ifndef SQLITE_OMIT_CHECK
if( pNC->isCheck ){
sqlite3ErrorMsg(pParse,"subqueries prohibited in CHECK constraints");
}
#endif
sqlite3SelectResolve(pParse, pExpr->pSelect, pNC);
assert( pNC->nRef>=nRef );
if( nRef!=pNC->nRef ){
ExprSetProperty(pExpr, EP_VarSelect);
}
}
break;
}
#ifndef SQLITE_OMIT_CHECK
case TK_VARIABLE: {
if( pNC->isCheck ){
sqlite3ErrorMsg(pParse,"parameters prohibited in CHECK constraints");
}
break;
}
#endif
}
return 0;
}
/*
** 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.
**
** Also resolve function names and check the functions for proper
** usage. 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 the expression contains aggregate functions then set the EP_Agg
** property on the expression.
*/
int sqlite3ExprResolveNames(
NameContext *pNC, /* Namespace to resolve expressions in. */
Expr *pExpr /* The expression to be analyzed. */
){
int savedHasAgg;
if( pExpr==0 ) return 0;
savedHasAgg = pNC->hasAgg;
pNC->hasAgg = 0;
walkExprTree(pExpr, nameResolverStep, pNC);
if( pNC->nErr>0 ){
ExprSetProperty(pExpr, EP_Error);
}
if( pNC->hasAgg ){
ExprSetProperty(pExpr, EP_Agg);
}else if( savedHasAgg ){
pNC->hasAgg = 1;
}
return ExprHasProperty(pExpr, EP_Error);
}
/*
** A pointer instance of this structure is used to pass information
** through walkExprTree into codeSubqueryStep().
*/
typedef struct QueryCoder QueryCoder;
struct QueryCoder {
Parse *pParse; /* The parsing context */
NameContext *pNC; /* Namespace of first enclosing query */
};
/*
** Generate code for scalar subqueries used as an expression
** and IN operators. Examples:
**
** (SELECT a FROM b) -- subquery
** EXISTS (SELECT a FROM b) -- EXISTS subquery
** x IN (4,5,11) -- IN operator with list on right-hand side
** x IN (SELECT a FROM b) -- IN operator with subquery on the right
**
** The pExpr parameter describes the expression that contains the IN
** operator or subquery.
*/
#ifndef SQLITE_OMIT_SUBQUERY
void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
int testAddr = 0; /* One-time test address */
Vdbe *v = sqlite3GetVdbe(pParse);
if( v==0 ) return;
/* This code must be run in its entirety every time it is encountered
** if any of the following is true:
**
** * The right-hand side is a correlated subquery
** * The right-hand side is an expression list containing variables
** * We are inside a trigger
**
** If all of the above are false, then we can run this code just once
** save the results, and reuse the same result on subsequent invocations.
*/
if( !ExprHasAnyProperty(pExpr, EP_VarSelect) && !pParse->trigStack ){
int mem = pParse->nMem++;
sqlite3VdbeAddOp(v, OP_MemLoad, mem, 0);
testAddr = sqlite3VdbeAddOp(v, OP_If, 0, 0);
assert( testAddr>0 || sqlite3MallocFailed() );
sqlite3VdbeAddOp(v, OP_MemInt, 1, mem);
}
switch( pExpr->op ){
case TK_IN: {
char affinity;
KeyInfo keyInfo;
int addr; /* Address of OP_OpenEphemeral instruction */
affinity = sqlite3ExprAffinity(pExpr->pLeft);
/* Whether this is an 'x IN(SELECT...)' or an 'x IN(<exprlist>)'
** expression it is handled the same way. A virtual table is
** filled with single-field index keys representing the results
** from the SELECT or the <exprlist>.
**
** If the 'x' expression is a column value, or the SELECT...
** statement returns a column value, then the affinity of that
** column is used to build the index keys. If both 'x' and the
** SELECT... statement are columns, then numeric affinity is used
** if either column has NUMERIC or INTEGER affinity. If neither
** 'x' nor the SELECT... statement are columns, then numeric affinity
** is used.
*/
pExpr->iTable = pParse->nTab++;
addr = sqlite3VdbeAddOp(v, OP_OpenEphemeral, pExpr->iTable, 0);
memset(&keyInfo, 0, sizeof(keyInfo));
keyInfo.nField = 1;
sqlite3VdbeAddOp(v, OP_SetNumColumns, pExpr->iTable, 1);
if( pExpr->pSelect ){
/* Case 1: expr IN (SELECT ...)
**
** Generate code to write the results of the select into the temporary
** table allocated and opened above.
*/
int iParm = pExpr->iTable + (((int)affinity)<<16);
ExprList *pEList;
assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable );
sqlite3Select(pParse, pExpr->pSelect, SRT_Set, iParm, 0, 0, 0, 0);
pEList = pExpr->pSelect->pEList;
if( pEList && pEList->nExpr>0 ){
keyInfo.aColl[0] = binaryCompareCollSeq(pParse, pExpr->pLeft,
pEList->a[0].pExpr);
}
}else if( pExpr->pList ){
/* Case 2: expr IN (exprlist)
**
** For each expression, build an index key from the evaluation and
** store it in the temporary table. If <expr> is a column, then use
** that columns affinity when building index keys. If <expr> is not
** a column, use numeric affinity.
*/
int i;
ExprList *pList = pExpr->pList;
struct ExprList_item *pItem;
if( !affinity ){
affinity = SQLITE_AFF_NONE;
}
keyInfo.aColl[0] = pExpr->pLeft->pColl;
/* Loop through each expression in <exprlist>. */
for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){
Expr *pE2 = pItem->pExpr;
/* If the expression is not constant then we will need to
** disable the test that was generated above that makes sure
** this code only executes once. Because for a non-constant
** expression we need to rerun this code each time.
*/
if( testAddr>0 && !sqlite3ExprIsConstant(pE2) ){
sqlite3VdbeChangeToNoop(v, testAddr-1, 3);
testAddr = 0;
}
/* Evaluate the expression and insert it into the temp table */
sqlite3ExprCode(pParse, pE2);
sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, &affinity, 1);
sqlite3VdbeAddOp(v, OP_IdxInsert, pExpr->iTable, 0);
}
}
sqlite3VdbeChangeP3(v, addr, (void *)&keyInfo, P3_KEYINFO);
break;
}
case TK_EXISTS:
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.
*/
static const Token one = { (u8*)"1", 0, 1 };
Select *pSel;
int iMem;
int sop;
pExpr->iColumn = iMem = pParse->nMem++;
pSel = pExpr->pSelect;
if( pExpr->op==TK_SELECT ){
sop = SRT_Mem;
sqlite3VdbeAddOp(v, OP_MemNull, iMem, 0);
VdbeComment((v, "# Init subquery result"));
}else{
sop = SRT_Exists;
sqlite3VdbeAddOp(v, OP_MemInt, 0, iMem);
VdbeComment((v, "# Init EXISTS result"));
}
sqlite3ExprDelete(pSel->pLimit);
pSel->pLimit = sqlite3Expr(TK_INTEGER, 0, 0, &one);
sqlite3Select(pParse, pSel, sop, iMem, 0, 0, 0, 0);
break;
}
}
if( testAddr ){
sqlite3VdbeJumpHere(v, testAddr);
}
return;
}
#endif /* SQLITE_OMIT_SUBQUERY */
/*
** Generate an instruction that will put the integer describe by
** text z[0..n-1] on the stack.
*/
static void codeInteger(Vdbe *v, const char *z, int n){
int i;
if( sqlite3GetInt32(z, &i) ){
sqlite3VdbeAddOp(v, OP_Integer, i, 0);
}else if( sqlite3FitsIn64Bits(z) ){
sqlite3VdbeOp3(v, OP_Int64, 0, 0, z, n);
}else{
sqlite3VdbeOp3(v, OP_Real, 0, 0, z, n);
}
}
/*
** Generate code into the current Vdbe to evaluate the given
** expression and leave the result on the top of stack.
**
** This code depends on the fact that certain token values (ex: TK_EQ)
** are the same as opcode values (ex: OP_Eq) that implement the corresponding
** operation. Special comments in vdbe.c and the mkopcodeh.awk script in
** the make process cause these values to align. Assert()s in the code
** below verify that the numbers are aligned correctly.
*/
void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
Vdbe *v = pParse->pVdbe;
int op;
int stackChng = 1; /* Amount of change to stack depth */
if( v==0 ) return;
if( pExpr==0 ){
sqlite3VdbeAddOp(v, OP_Null, 0, 0);
return;
}
op = pExpr->op;
switch( op ){
case TK_AGG_COLUMN: {
AggInfo *pAggInfo = pExpr->pAggInfo;
struct AggInfo_col *pCol = &pAggInfo->aCol[pExpr->iAgg];
if( !pAggInfo->directMode ){
sqlite3VdbeAddOp(v, OP_MemLoad, pCol->iMem, 0);
break;
}else if( pAggInfo->useSortingIdx ){
sqlite3VdbeAddOp(v, OP_Column, pAggInfo->sortingIdx,
pCol->iSorterColumn);
break;
}
/* Otherwise, fall thru into the TK_COLUMN case */
}
case TK_COLUMN: {
if( pExpr->iTable<0 ){
/* This only happens when coding check constraints */
assert( pParse->ckOffset>0 );
sqlite3VdbeAddOp(v, OP_Dup, pParse->ckOffset-pExpr->iColumn-1, 1);
}else if( pExpr->iColumn>=0 ){
Table *pTab = pExpr->pTab;
int iCol = pExpr->iColumn;
int op = (pTab && IsVirtual(pTab)) ? OP_VColumn : OP_Column;
sqlite3VdbeAddOp(v, op, pExpr->iTable, iCol);
sqlite3ColumnDefault(v, pTab, iCol);
#ifndef SQLITE_OMIT_FLOATING_POINT
if( pTab && pTab->aCol[iCol].affinity==SQLITE_AFF_REAL ){
sqlite3VdbeAddOp(v, OP_RealAffinity, 0, 0);
}
#endif
}else{
Table *pTab = pExpr->pTab;
int op = (pTab && IsVirtual(pTab)) ? OP_VRowid : OP_Rowid;
sqlite3VdbeAddOp(v, op, pExpr->iTable, 0);
}
break;
}
case TK_INTEGER: {
codeInteger(v, (char*)pExpr->token.z, pExpr->token.n);
break;
}
case TK_FLOAT:
case TK_STRING: {
assert( TK_FLOAT==OP_Real );
assert( TK_STRING==OP_String8 );
sqlite3DequoteExpr(pExpr);
sqlite3VdbeOp3(v, op, 0, 0, (char*)pExpr->token.z, pExpr->token.n);
break;
}
case TK_NULL: {
sqlite3VdbeAddOp(v, OP_Null, 0, 0);
break;
}
#ifndef SQLITE_OMIT_BLOB_LITERAL
case TK_BLOB: {
int n;
const char *z;
assert( TK_BLOB==OP_HexBlob );
n = pExpr->token.n - 3;
z = (char*)pExpr->token.z + 2;
assert( n>=0 );
if( n==0 ){
z = "";
}
sqlite3VdbeOp3(v, op, 0, 0, z, n);
break;
}
#endif
case TK_VARIABLE: {
sqlite3VdbeAddOp(v, OP_Variable, pExpr->iTable, 0);
if( pExpr->token.n>1 ){
sqlite3VdbeChangeP3(v, -1, (char*)pExpr->token.z, pExpr->token.n);
}
break;
}
case TK_REGISTER: {
sqlite3VdbeAddOp(v, OP_MemLoad, pExpr->iTable, 0);
break;
}
#ifndef SQLITE_OMIT_CAST
case TK_CAST: {
/* Expressions of the form: CAST(pLeft AS token) */
int aff, to_op;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -