📄 expr.c
字号:
sqlite3VdbeOp3(v, OP_Function, constMask, nExpr, (char*)pDef, P3_FUNCDEF); break; }#ifndef SQLITE_OMIT_SUBQUERY case TK_EXISTS: case TK_SELECT: { sqlite3CodeSubselect(pParse, pExpr); sqlite3VdbeAddOp(v, OP_MemLoad, pExpr->iColumn, 0); VdbeComment((v, "# load subquery result")); break; } case TK_IN: { int addr; char affinity; sqlite3CodeSubselect(pParse, pExpr); /* Figure out the affinity to use to create a key from the results ** of the expression. affinityStr stores a static string suitable for ** P3 of OP_MakeRecord. */ affinity = comparisonAffinity(pExpr); sqlite3VdbeAddOp(v, OP_Integer, 1, 0); /* Code the <expr> from "<expr> IN (...)". The temporary table ** pExpr->iTable contains the values that make up the (...) set. */ sqlite3ExprCode(pParse, pExpr->pLeft); addr = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp(v, OP_NotNull, -1, addr+4); /* addr + 0 */ sqlite3VdbeAddOp(v, OP_Pop, 2, 0); sqlite3VdbeAddOp(v, OP_Null, 0, 0); sqlite3VdbeAddOp(v, OP_Goto, 0, addr+7); sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, &affinity, 1); /* addr + 4 */ sqlite3VdbeAddOp(v, OP_Found, pExpr->iTable, addr+7); sqlite3VdbeAddOp(v, OP_AddImm, -1, 0); /* addr + 6 */ break; }#endif case TK_BETWEEN: { Expr *pLeft = pExpr->pLeft; struct ExprList_item *pLItem = pExpr->pList->a; Expr *pRight = pLItem->pExpr; sqlite3ExprCode(pParse, pLeft); sqlite3VdbeAddOp(v, OP_Dup, 0, 0); sqlite3ExprCode(pParse, pRight); codeCompare(pParse, pLeft, pRight, OP_Ge, 0, 0); sqlite3VdbeAddOp(v, OP_Pull, 1, 0); pLItem++; pRight = pLItem->pExpr; sqlite3ExprCode(pParse, pRight); codeCompare(pParse, pLeft, pRight, OP_Le, 0, 0); sqlite3VdbeAddOp(v, OP_And, 0, 0); break; } case TK_UPLUS: case TK_AS: { sqlite3ExprCode(pParse, pExpr->pLeft); break; } case TK_CASE: { int expr_end_label; int jumpInst; int nExpr; int i; ExprList *pEList; struct ExprList_item *aListelem; assert(pExpr->pList); assert((pExpr->pList->nExpr % 2) == 0); assert(pExpr->pList->nExpr > 0); pEList = pExpr->pList; aListelem = pEList->a; nExpr = pEList->nExpr; expr_end_label = sqlite3VdbeMakeLabel(v); if( pExpr->pLeft ){ sqlite3ExprCode(pParse, pExpr->pLeft); } for(i=0; i<nExpr; i=i+2){ sqlite3ExprCode(pParse, aListelem[i].pExpr); if( pExpr->pLeft ){ sqlite3VdbeAddOp(v, OP_Dup, 1, 1); jumpInst = codeCompare(pParse, pExpr->pLeft, aListelem[i].pExpr, OP_Ne, 0, 1); sqlite3VdbeAddOp(v, OP_Pop, 1, 0); }else{ jumpInst = sqlite3VdbeAddOp(v, OP_IfNot, 1, 0); } sqlite3ExprCode(pParse, aListelem[i+1].pExpr); sqlite3VdbeAddOp(v, OP_Goto, 0, expr_end_label); sqlite3VdbeJumpHere(v, jumpInst); } if( pExpr->pLeft ){ sqlite3VdbeAddOp(v, OP_Pop, 1, 0); } if( pExpr->pRight ){ sqlite3ExprCode(pParse, pExpr->pRight); }else{ sqlite3VdbeAddOp(v, OP_Null, 0, 0); } sqlite3VdbeResolveLabel(v, expr_end_label); 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 ); sqlite3DequoteExpr(pExpr); sqlite3VdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, pExpr->iColumn, pExpr->token.z, pExpr->token.n); } 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; if( pList==0 ) return 0; n = pList->nExpr; for(pItem=pList->a, i=n; i>0; 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); sqlite3VdbeJumpHere(v, addr); 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( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) 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->toke
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -