?? expr.c
字號:
break; }#ifndef SQLITE_OMIT_TRIGGER case TK_RAISE: { if( !pParse->trigStack ){ sqlite3ErrorMsg(pParse, "RAISE() may only be used within a trigger-program"); return; } if( pExpr->iColumn!=OE_Ignore ){ assert( pExpr->iColumn==OE_Rollback || pExpr->iColumn == OE_Abort || pExpr->iColumn == OE_Fail ); sqlite3VdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, pExpr->iColumn, pExpr->token.z, pExpr->token.n); sqlite3VdbeDequoteP3(v, -1); } else { assert( pExpr->iColumn == OE_Ignore ); sqlite3VdbeAddOp(v, OP_ContextPop, 0, 0); sqlite3VdbeAddOp(v, OP_Goto, 0, pParse->trigStack->ignoreJump); VdbeComment((v, "# raise(IGNORE)")); } }#endif break; }}#ifndef SQLITE_OMIT_TRIGGER/*** Generate code that evalutes the given expression and leaves the result** on the stack. See also sqlite3ExprCode().**** This routine might also cache the result and modify the pExpr tree** so that it will make use of the cached result on subsequent evaluations** rather than evaluate the whole expression again. Trivial expressions are** not cached. If the expression is cached, its result is stored in a ** memory location.*/void sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr){ Vdbe *v = pParse->pVdbe; int iMem; int addr1, addr2; if( v==0 ) return; addr1 = sqlite3VdbeCurrentAddr(v); sqlite3ExprCode(pParse, pExpr); addr2 = sqlite3VdbeCurrentAddr(v); if( addr2>addr1+1 || sqlite3VdbeGetOp(v, addr1)->opcode==OP_Function ){ iMem = pExpr->iTable = pParse->nMem++; sqlite3VdbeAddOp(v, OP_MemStore, iMem, 0); pExpr->op = TK_REGISTER; }}#endif/*** Generate code that pushes the value of every element of the given** expression list onto the stack.**** Return the number of elements pushed onto the stack.*/int sqlite3ExprCodeExprList( Parse *pParse, /* Parsing context */ ExprList *pList /* The expression list to be coded */){ struct ExprList_item *pItem; int i, n; Vdbe *v; if( pList==0 ) return 0; v = sqlite3GetVdbe(pParse); n = pList->nExpr; for(pItem=pList->a, i=0; i<n; i++, pItem++){ sqlite3ExprCode(pParse, pItem->pExpr); } return 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.**** If the expression evaluates to NULL (neither true nor false), then** take the jump if the jumpIfNull flag is true.**** 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 sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ Vdbe *v = pParse->pVdbe; int op = 0; if( v==0 || pExpr==0 ) return; op = pExpr->op; switch( op ){ case TK_AND: { int d2 = sqlite3VdbeMakeLabel(v); sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2, !jumpIfNull); sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); sqlite3VdbeResolveLabel(v, d2); break; case TK_OR: { sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); break; } case TK_NOT: { sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); break; } case TK_LT: case TK_LE: case TK_GT: case TK_GE: case TK_NE: case TK_EQ: { assert( TK_LT==OP_Lt ); assert( TK_LE==OP_Le ); assert( TK_GT==OP_Gt ); assert( TK_GE==OP_Ge ); assert( TK_EQ==OP_Eq ); assert( TK_NE==OP_Ne ); sqlite3ExprCode(pParse, pExpr->pLeft); sqlite3ExprCode(pParse, pExpr->pRight); codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, dest, jumpIfNull); break; } case TK_ISNULL: case TK_NOTNULL: { assert( TK_ISNULL==OP_IsNull ); assert( TK_NOTNULL==OP_NotNull ); sqlite3ExprCode(pParse, pExpr->pLeft); sqlite3VdbeAddOp(v, op, 1, dest); break; } case TK_BETWEEN: { /* The expression "x BETWEEN y AND z" is implemented as: ** ** 1 IF (x < y) GOTO 3 ** 2 IF (x <= z) GOTO <dest> ** 3 ... */ int addr; Expr *pLeft = pExpr->pLeft; Expr *pRight = pExpr->pList->a[0].pExpr; sqlite3ExprCode(pParse, pLeft); sqlite3VdbeAddOp(v, OP_Dup, 0, 0); sqlite3ExprCode(pParse, pRight); addr = codeCompare(pParse, pLeft, pRight, OP_Lt, 0, !jumpIfNull); pRight = pExpr->pList->a[1].pExpr; sqlite3ExprCode(pParse, pRight); codeCompare(pParse, pLeft, pRight, OP_Le, dest, jumpIfNull); sqlite3VdbeAddOp(v, OP_Integer, 0, 0); sqlite3VdbeChangeP2(v, addr, sqlite3VdbeCurrentAddr(v)); sqlite3VdbeAddOp(v, OP_Pop, 1, 0); break; } default: { sqlite3ExprCode(pParse, pExpr); sqlite3VdbeAddOp(v, OP_If, jumpIfNull, dest); break; } }}/*** Generate code for a boolean expression such that a jump is made** to the label "dest" if the expression is false but execution** continues straight thru if the expression is true.**** If the expression evaluates to NULL (neither true nor false) then** jump if jumpIfNull is true or fall through if jumpIfNull is false.*/void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ Vdbe *v = pParse->pVdbe; int op = 0; if( v==0 || pExpr==0 ) return; /* The value of pExpr->op and op are related as follows: ** ** pExpr->op op ** --------- ---------- ** TK_ISNULL OP_NotNull ** TK_NOTNULL OP_IsNull ** TK_NE OP_Eq ** TK_EQ OP_Ne ** TK_GT OP_Le ** TK_LE OP_Gt ** TK_GE OP_Lt ** TK_LT OP_Ge ** ** For other values of pExpr->op, op is undefined and unused. ** The value of TK_ and OP_ constants are arranged such that we ** can compute the mapping above using the following expression. ** Assert()s verify that the computation is correct. */ op = ((pExpr->op+(TK_ISNULL&1))^1)-(TK_ISNULL&1); /* Verify correct alignment of TK_ and OP_ constants */ assert( pExpr->op!=TK_ISNULL || op==OP_NotNull ); assert( pExpr->op!=TK_NOTNULL || op==OP_IsNull ); assert( pExpr->op!=TK_NE || op==OP_Eq ); assert( pExpr->op!=TK_EQ || op==OP_Ne ); assert( pExpr->op!=TK_LT || op==OP_Ge ); assert( pExpr->op!=TK_LE || op==OP_Gt ); assert( pExpr->op!=TK_GT || op==OP_Le ); assert( pExpr->op!=TK_GE || op==OP_Lt ); switch( pExpr->op ){ case TK_AND: { sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); break; } case TK_OR: { int d2 = sqlite3VdbeMakeLabel(v); sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, !jumpIfNull); sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); sqlite3VdbeResolveLabel(v, d2); break; } case TK_NOT: { sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); break; } case TK_LT: case TK_LE: case TK_GT: case TK_GE: case TK_NE: case TK_EQ: { sqlite3ExprCode(pParse, pExpr->pLeft); sqlite3ExprCode(pParse, pExpr->pRight); codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, dest, jumpIfNull); break; } case TK_ISNULL: case TK_NOTNULL: { sqlite3ExprCode(pParse, pExpr->pLeft); sqlite3VdbeAddOp(v, op, 1, dest); break; } case TK_BETWEEN: { /* The expression is "x BETWEEN y AND z". It is implemented as: ** ** 1 IF (x >= y) GOTO 3 ** 2 GOTO <dest> ** 3 IF (x > z) GOTO <dest> */ int addr; Expr *pLeft = pExpr->pLeft; Expr *pRight = pExpr->pList->a[0].pExpr; sqlite3ExprCode(pParse, pLeft); sqlite3VdbeAddOp(v, OP_Dup, 0, 0); sqlite3ExprCode(pParse, pRight); addr = sqlite3VdbeCurrentAddr(v); codeCompare(pParse, pLeft, pRight, OP_Ge, addr+3, !jumpIfNull); sqlite3VdbeAddOp(v, OP_Pop, 1, 0); sqlite3VdbeAddOp(v, OP_Goto, 0, dest); pRight = pExpr->pList->a[1].pExpr; sqlite3ExprCode(pParse, pRight); codeCompare(pParse, pLeft, pRight, OP_Gt, dest, jumpIfNull); break; } default: { sqlite3ExprCode(pParse, pExpr); sqlite3VdbeAddOp(v, OP_IfNot, jumpIfNull, dest); break; } }}/*** Do a deep comparison of two expression trees. Return TRUE (non-zero)** if they are identical and return FALSE if they differ in any way.*/int sqlite3ExprCompare(Expr *pA, Expr *pB){ int i; if( pA==0 ){ return pB==0; }else if( pB==0 ){ return 0; } if( pA->op!=pB->op ) return 0; if( !sqlite3ExprCompare(pA->pLeft, pB->pLeft) ) return 0; if( !sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 0; if( pA->pList ){ if( pB->pList==0 ) return 0; if( pA->pList->nExpr!=pB->pList->nExpr ) return 0; for(i=0; i<pA->pList->nExpr; i++){ if( !sqlite3ExprCompare(pA->pList->a[i].pExpr, pB->pList->a[i].pExpr) ){ return 0; } } }else if( pB->pList ){ return 0; } if( pA->pSelect || pB->pSelect ) return 0; if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 0; if( pA->token.z ){ if( pB->token.z==0 ) return 0; if( pB->token.n!=pA->token.n ) return 0; if( sqlite3StrNICmp(pA->token.z, pB->token.z, pB->token.n)!=0 ) return 0; } return 1;}/*** Add a new element to the pParse->aAgg[] array and return its index.** The new element is initialized to zero. The calling function is** expected to fill it in.*/static int appendAggInfo(Parse *pParse){ if( (pParse->nAgg & 0x7)==0 ){ int amt = pParse->nAgg + 8; AggExpr *aAgg = sqliteRealloc(pParse->aAgg, amt*sizeof(pParse->aAgg[0])); if( aAgg==0 ){ return -1; } pParse->aAgg = aAgg; } memset(&pParse->aAgg[pParse->nAgg], 0, sizeof(pParse->aAgg[0])); return pParse->nAgg++;}/*** This is an xFunc for walkExprTree() used to implement ** sqlite3ExprAnalyzeAggregates(). See sqlite3ExprAnalyzeAggregates** for additional information.**** This routine analyzes the aggregate function at pExpr.*/static int analyzeAggregate(void *pArg, Expr *pExpr){ int i; AggExpr *aAgg; NameContext *pNC = (NameContext *)pArg; Parse *pParse = pNC->pParse; SrcList *pSrcList = pNC->pSrcList; switch( pExpr->op ){ case TK_COLUMN: { for(i=0; pSrcList && i<pSrcList->nSrc; i++){ if( pExpr->iTable==pSrcList->a[i].iCursor ){ aAgg = pParse->aAgg; for(i=0; i<pParse->nAgg; i++){ if( aAgg[i].isAgg ) continue; if( aAgg[i].pExpr->iTable==pExpr->iTable && aAgg[i].pExpr->iColumn==pExpr->iColumn ){ break; } } if( i>=pParse->nAgg ){ i = appendAggInfo(pParse); if( i<0 ) return 1; pParse->aAgg[i].isAgg = 0; pParse->aAgg[i].pExpr = pExpr; } pExpr->iAgg = i; pExpr->iAggCtx = pNC->nDepth; return 1; } } return 1; } case TK_AGG_FUNCTION: { if( pNC->nDepth==0 ){ aAgg = pParse->aAgg; for(i=0; i<pParse->nAgg; i++){ if( !aAgg[i].isAgg ) continue; if( sqlite3ExprCompare(aAgg[i].pExpr, pExpr) ){ break; } } if( i>=pParse->nAgg ){ u8 enc = pParse->db->enc; i = appendAggInfo(pParse); if( i<0 ) return 1; pParse->aAgg[i].isAgg = 1; pParse->aAgg[i].pExpr = pExpr; pParse->aAgg[i].pFunc = sqlite3FindFunction(pParse->db, pExpr->token.z, pExpr->token.n, pExpr->pList ? pExpr->pList->nExpr : 0, enc, 0); } pExpr->iAgg = i; return 1; } } } if( pExpr->pSelect ){ pNC->nDepth++; walkSelectExpr(pExpr->pSelect, analyzeAggregate, pNC); pNC->nDepth--; } return 0;}/*** Analyze the given expression looking for aggregate functions and** for variables that need to be added to the pParse->aAgg[] array.** Make additional entries to the pParse->aAgg[] array as necessary.**** This routine should only be called after the expression has been** analyzed by sqlite3ExprResolveNames().**
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -