📄 expr.c
字号:
sqliteVdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, pExpr->iColumn, pExpr->token.z, pExpr->token.n); sqliteVdbeDequoteP3(v, -1); } else { assert( pExpr->iColumn == OE_Ignore ); sqliteVdbeOp3(v, OP_Goto, 0, pParse->trigStack->ignoreJump, "(IGNORE jump)", 0); } } break; }}/*** Generate code that pushes the value of every element of the given** expression list onto the stack. If the includeTypes flag is true,** then also push a string that is the datatype of each element onto** the stack after the value.**** Return the number of elements pushed onto the stack.*/int sqliteExprCodeExprList( Parse *pParse, /* Parsing context */ ExprList *pList, /* The expression list to be coded */ int includeTypes /* TRUE to put datatypes on the stack too */){ struct ExprList_item *pItem; int i, n; Vdbe *v; if( pList==0 ) return 0; v = sqliteGetVdbe(pParse); n = pList->nExpr; for(pItem=pList->a, i=0; i<n; i++, pItem++){ sqliteExprCode(pParse, pItem->pExpr); if( includeTypes ){ sqliteVdbeOp3(v, OP_String, 0, 0, sqliteExprType(pItem->pExpr)==SQLITE_SO_NUM ? "numeric" : "text", P3_STATIC); } } return includeTypes ? n*2 : 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.*/void sqliteExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ Vdbe *v = pParse->pVdbe; int op = 0; if( v==0 || pExpr==0 ) return; switch( pExpr->op ){ case TK_LT: op = OP_Lt; break; case TK_LE: op = OP_Le; break; case TK_GT: op = OP_Gt; break; case TK_GE: op = OP_Ge; break; case TK_NE: op = OP_Ne; break; case TK_EQ: op = OP_Eq; break; case TK_ISNULL: op = OP_IsNull; break; case TK_NOTNULL: op = OP_NotNull; break; default: break; } switch( pExpr->op ){ case TK_AND: { int d2 = sqliteVdbeMakeLabel(v); sqliteExprIfFalse(pParse, pExpr->pLeft, d2, !jumpIfNull); sqliteExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); sqliteVdbeResolveLabel(v, d2); break; } case TK_OR: { sqliteExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); sqliteExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); break; } case TK_NOT: { sqliteExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); break; } case TK_LT: case TK_LE: case TK_GT: case TK_GE: case TK_NE: case TK_EQ: { sqliteExprCode(pParse, pExpr->pLeft); sqliteExprCode(pParse, pExpr->pRight); if( pParse->db->file_format>=4 && sqliteExprType(pExpr)==SQLITE_SO_TEXT ){ op += 6; /* Convert numeric opcodes to text opcodes */ } sqliteVdbeAddOp(v, op, jumpIfNull, dest); break; } case TK_ISNULL: case TK_NOTNULL: { sqliteExprCode(pParse, pExpr->pLeft); sqliteVdbeAddOp(v, op, 1, dest); break; } case TK_IN: { int addr; sqliteExprCode(pParse, pExpr->pLeft); addr = sqliteVdbeCurrentAddr(v); sqliteVdbeAddOp(v, OP_NotNull, -1, addr+3); sqliteVdbeAddOp(v, OP_Pop, 1, 0); sqliteVdbeAddOp(v, OP_Goto, 0, jumpIfNull ? dest : addr+4); if( pExpr->pSelect ){ sqliteVdbeAddOp(v, OP_Found, pExpr->iTable, dest); }else{ sqliteVdbeAddOp(v, OP_SetFound, pExpr->iTable, dest); } break; } case TK_BETWEEN: { int addr; sqliteExprCode(pParse, pExpr->pLeft); sqliteVdbeAddOp(v, OP_Dup, 0, 0); sqliteExprCode(pParse, pExpr->pList->a[0].pExpr); addr = sqliteVdbeAddOp(v, OP_Lt, !jumpIfNull, 0); sqliteExprCode(pParse, pExpr->pList->a[1].pExpr); sqliteVdbeAddOp(v, OP_Le, jumpIfNull, dest); sqliteVdbeAddOp(v, OP_Integer, 0, 0); sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v)); sqliteVdbeAddOp(v, OP_Pop, 1, 0); break; } default: { sqliteExprCode(pParse, pExpr); sqliteVdbeAddOp(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 sqliteExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ Vdbe *v = pParse->pVdbe; int op = 0; if( v==0 || pExpr==0 ) return; switch( pExpr->op ){ case TK_LT: op = OP_Ge; break; case TK_LE: op = OP_Gt; break; case TK_GT: op = OP_Le; break; case TK_GE: op = OP_Lt; break; case TK_NE: op = OP_Eq; break; case TK_EQ: op = OP_Ne; break; case TK_ISNULL: op = OP_NotNull; break; case TK_NOTNULL: op = OP_IsNull; break; default: break; } switch( pExpr->op ){ case TK_AND: { sqliteExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); sqliteExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); break; } case TK_OR: { int d2 = sqliteVdbeMakeLabel(v); sqliteExprIfTrue(pParse, pExpr->pLeft, d2, !jumpIfNull); sqliteExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); sqliteVdbeResolveLabel(v, d2); break; } case TK_NOT: { sqliteExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); break; } case TK_LT: case TK_LE: case TK_GT: case TK_GE: case TK_NE: case TK_EQ: { if( pParse->db->file_format>=4 && sqliteExprType(pExpr)==SQLITE_SO_TEXT ){ /* Convert numeric comparison opcodes into text comparison opcodes. ** This step depends on the fact that the text comparision opcodes are ** always 6 greater than their corresponding numeric comparison ** opcodes. */ assert( OP_Eq+6 == OP_StrEq ); op += 6; } sqliteExprCode(pParse, pExpr->pLeft); sqliteExprCode(pParse, pExpr->pRight); sqliteVdbeAddOp(v, op, jumpIfNull, dest); break; } case TK_ISNULL: case TK_NOTNULL: { sqliteExprCode(pParse, pExpr->pLeft); sqliteVdbeAddOp(v, op, 1, dest); break; } case TK_IN: { int addr; sqliteExprCode(pParse, pExpr->pLeft); addr = sqliteVdbeCurrentAddr(v); sqliteVdbeAddOp(v, OP_NotNull, -1, addr+3); sqliteVdbeAddOp(v, OP_Pop, 1, 0); sqliteVdbeAddOp(v, OP_Goto, 0, jumpIfNull ? dest : addr+4); if( pExpr->pSelect ){ sqliteVdbeAddOp(v, OP_NotFound, pExpr->iTable, dest); }else{ sqliteVdbeAddOp(v, OP_SetNotFound, pExpr->iTable, dest); } break; } case TK_BETWEEN: { int addr; sqliteExprCode(pParse, pExpr->pLeft); sqliteVdbeAddOp(v, OP_Dup, 0, 0); sqliteExprCode(pParse, pExpr->pList->a[0].pExpr); addr = sqliteVdbeCurrentAddr(v); sqliteVdbeAddOp(v, OP_Ge, !jumpIfNull, addr+3); sqliteVdbeAddOp(v, OP_Pop, 1, 0); sqliteVdbeAddOp(v, OP_Goto, 0, dest); sqliteExprCode(pParse, pExpr->pList->a[1].pExpr); sqliteVdbeAddOp(v, OP_Gt, jumpIfNull, dest); break; } default: { sqliteExprCode(pParse, pExpr); sqliteVdbeAddOp(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 sqliteExprCompare(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( !sqliteExprCompare(pA->pLeft, pB->pLeft) ) return 0; if( !sqliteExprCompare(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( !sqliteExprCompare(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( sqliteStrNICmp(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.*/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++;}/*** 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 sqliteExprResolveIds() and sqliteExprCheck().**** If errors are seen, leave an error message in zErrMsg and return** the number of errors.*/int sqliteExprAnalyzeAggregates(Parse *pParse, Expr *pExpr){ int i; AggExpr *aAgg; int nErr = 0; if( pExpr==0 ) return 0; switch( pExpr->op ){ case TK_COLUMN: { 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; break; } case TK_AGG_FUNCTION: { aAgg = pParse->aAgg; for(i=0; i<pParse->nAgg; i++){ if( !aAgg[i].isAgg ) continue; if( sqliteExprCompare(aAgg[i].pExpr, pExpr) ){ break; } } if( i>=pParse->nAgg ){ i = appendAggInfo(pParse); if( i<0 ) return 1; pParse->aAgg[i].isAgg = 1; pParse->aAgg[i].pExpr = pExpr; pParse->aAgg[i].pFunc = sqliteFindFunction(pParse->db, pExpr->token.z, pExpr->token.n, pExpr->pList ? pExpr->pList->nExpr : 0, 0); } pExpr->iAgg = i; break; } default: { if( pExpr->pLeft ){ nErr = sqliteExprAnalyzeAggregates(pParse, pExpr->pLeft); } if( nErr==0 && pExpr->pRight ){ nErr = sqliteExprAnalyzeAggregates(pParse, pExpr->pRight); } if( nErr==0 && pExpr->pList ){ int n = pExpr->pList->nExpr; int i; for(i=0; nErr==0 && i<n; i++){ nErr = sqliteExprAnalyzeAggregates(pParse, pExpr->pList->a[i].pExpr); } } break; } } return nErr;}/*** Locate a user function given a name and a number of arguments.** Return a pointer to the FuncDef structure that defines that** function, or return NULL if the function does not exist.**** If the createFlag argument is true, then a new (blank) FuncDef** structure is created and liked into the "db" structure if a** no matching function previously existed. When createFlag is true** and the nArg parameter is -1, then only a function that accepts** any number of arguments will be returned.**** If createFlag is false and nArg is -1, then the first valid** function found is returned. A function is valid if either xFunc** or xStep is non-zero.*/FuncDef *sqliteFindFunction( sqlite *db, /* An open database */ const char *zName, /* Name of the function. Not null-terminated */ int nName, /* Number of characters in the name */ int nArg, /* Number of arguments. -1 means any number */ int createFlag /* Create new entry if true and does not otherwise exist */){ FuncDef *pFirst, *p, *pMaybe; pFirst = p = (FuncDef*)sqliteHashFind(&db->aFunc, zName, nName); if( p && !createFlag && nArg<0 ){ while( p && p->xFunc==0 && p->xStep==0 ){ p = p->pNext; } return p; } pMaybe = 0; while( p && p->nArg!=nArg ){ if( p->nArg<0 && !createFlag && (p->xFunc || p->xStep) ) pMaybe = p; p = p->pNext; } if( p && !createFlag && p->xFunc==0 && p->xStep==0 ){ return 0; } if( p==0 && pMaybe ){ assert( createFlag==0 ); return pMaybe; } if( p==0 && createFlag && (p = sqliteMalloc(sizeof(*p)))!=0 ){ p->nArg = nArg; p->pNext = pFirst; p->dataType = pFirst ? pFirst->dataType : SQLITE_NUMERIC; sqliteHashInsert(&db->aFunc, zName, nName, (void*)p); } return p;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -