mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-12 13:01:09 +03:00
When flipping ("commuting") a comparison operator, set the new EP_Commuted
bit rather than adding extra EP_Collate bits, to single later processing that the order of precedence for COLLATE operators is inverted. Fix for ticket [b47e3627ecaadbde] FossilOrigin-Name: 90f7c477354d67d22d5eb0da22dac579f384ab44743fdc19887220e32203ebc2
This commit is contained in:
38
src/expr.c
38
src/expr.c
@@ -339,6 +339,22 @@ CollSeq *sqlite3BinaryCompareCollSeq(
|
||||
return pColl;
|
||||
}
|
||||
|
||||
/* Expresssion p is a comparison operator. Return a collation sequence
|
||||
** appropriate for the comparison operator.
|
||||
**
|
||||
** This is normally just a wrapper around sqlite3BinaryCompareCollSeq().
|
||||
** However, if the OP_Commuted flag is set, then the order of the operands
|
||||
** is reversed in the sqlite3BinaryCompareCollSeq() call so that the
|
||||
** correct collating sequence is found.
|
||||
*/
|
||||
CollSeq *sqlite3ExprCompareCollSeq(Parse *pParse, Expr *p){
|
||||
if( ExprHasProperty(p, EP_Commuted) ){
|
||||
return sqlite3BinaryCompareCollSeq(pParse, p->pRight, p->pLeft);
|
||||
}else{
|
||||
return sqlite3BinaryCompareCollSeq(pParse, p->pLeft, p->pRight);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Generate code for a comparison operator.
|
||||
*/
|
||||
@@ -349,13 +365,18 @@ static int codeCompare(
|
||||
int opcode, /* The comparison opcode */
|
||||
int in1, int in2, /* Register holding operands */
|
||||
int dest, /* Jump here if true. */
|
||||
int jumpIfNull /* If true, jump if either operand is NULL */
|
||||
int jumpIfNull, /* If true, jump if either operand is NULL */
|
||||
int isCommuted /* The comparison has been commuted */
|
||||
){
|
||||
int p5;
|
||||
int addr;
|
||||
CollSeq *p4;
|
||||
|
||||
p4 = sqlite3BinaryCompareCollSeq(pParse, pLeft, pRight);
|
||||
if( isCommuted ){
|
||||
p4 = sqlite3BinaryCompareCollSeq(pParse, pRight, pLeft);
|
||||
}else{
|
||||
p4 = sqlite3BinaryCompareCollSeq(pParse, pLeft, pRight);
|
||||
}
|
||||
p5 = binaryCompareP5(pLeft, pRight, jumpIfNull);
|
||||
addr = sqlite3VdbeAddOp4(pParse->pVdbe, opcode, in2, dest, in1,
|
||||
(void*)p4, P4_COLLSEQ);
|
||||
@@ -566,6 +587,7 @@ static void codeVectorCompare(
|
||||
int regRight = 0;
|
||||
u8 opx = op;
|
||||
int addrDone = sqlite3VdbeMakeLabel(pParse);
|
||||
int isCommuted = ExprHasProperty(pExpr,EP_Commuted);
|
||||
|
||||
if( nLeft!=sqlite3ExprVectorSize(pRight) ){
|
||||
sqlite3ErrorMsg(pParse, "row value misused");
|
||||
@@ -595,7 +617,7 @@ static void codeVectorCompare(
|
||||
assert( i>=0 && i<nLeft );
|
||||
r1 = exprVectorRegister(pParse, pLeft, i, regLeft, &pL, ®Free1);
|
||||
r2 = exprVectorRegister(pParse, pRight, i, regRight, &pR, ®Free2);
|
||||
codeCompare(pParse, pL, pR, opx, r1, r2, dest, p5);
|
||||
codeCompare(pParse, pL, pR, opx, r1, r2, dest, p5, isCommuted);
|
||||
testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
|
||||
testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
|
||||
testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt);
|
||||
@@ -3665,7 +3687,8 @@ expr_code_doover:
|
||||
r1 = sqlite3ExprCodeTemp(pParse, pLeft, ®Free1);
|
||||
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
||||
codeCompare(pParse, pLeft, pExpr->pRight, op,
|
||||
r1, r2, inReg, SQLITE_STOREP2 | p5);
|
||||
r1, r2, inReg, SQLITE_STOREP2 | p5,
|
||||
ExprHasProperty(pExpr,EP_Commuted));
|
||||
assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
|
||||
assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
|
||||
assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt);
|
||||
@@ -4585,7 +4608,7 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
||||
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
||||
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
||||
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
|
||||
r1, r2, dest, jumpIfNull);
|
||||
r1, r2, dest, jumpIfNull, ExprHasProperty(pExpr,EP_Commuted));
|
||||
assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
|
||||
assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
|
||||
assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt);
|
||||
@@ -4760,7 +4783,7 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
||||
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
||||
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
||||
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
|
||||
r1, r2, dest, jumpIfNull);
|
||||
r1, r2, dest, jumpIfNull,ExprHasProperty(pExpr,EP_Commuted));
|
||||
assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
|
||||
assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
|
||||
assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt);
|
||||
@@ -4946,7 +4969,8 @@ int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTab){
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2;
|
||||
if( (pA->flags & (EP_Distinct|EP_Commuted))
|
||||
!= (pB->flags & (EP_Distinct|EP_Commuted)) ) return 2;
|
||||
if( (combinedFlags & EP_TokenOnly)==0 ){
|
||||
if( combinedFlags & EP_xIsSelect ) return 2;
|
||||
if( (combinedFlags & EP_FixedCol)==0
|
||||
|
||||
Reference in New Issue
Block a user