-
Notifications
You must be signed in to change notification settings - Fork 5.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
planner: reject invalid conversion from like to = #11320
Conversation
Codecov Report
@@ Coverage Diff @@
## master #11320 +/- ##
===========================================
Coverage 81.3711% 81.3711%
===========================================
Files 424 424
Lines 90730 90730
===========================================
Hits 73828 73828
Misses 11589 11589
Partials 5313 5313 |
planner/core/expression_rewriter.go
Outdated
@@ -1237,7 +1237,7 @@ func (er *expressionRewriter) patternLikeToExpression(v *ast.PatternLikeExpr) { | |||
} | |||
if !isNull { | |||
patValue, patTypes := stringutil.CompilePattern(patString, v.Escape) | |||
if stringutil.IsExactMatch(patTypes) { | |||
if stringutil.IsExactMatch(patTypes) && er.ctxStack[l-2].GetType().EvalType().IsStringKind() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it seems that we should not call IsStringKind()
but check .EvalType() == ETString
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it seems that we should not call
IsStringKind()
but check.EvalType() == ETString
here?
It seems that IsStringKind() is enough, If the val's type is String, they will be compared as string.
tidb/expression/builtin_compare.go
Lines 958 to 978 in 5aef053
func getBaseCmpType(lhs, rhs types.EvalType, lft, rft *types.FieldType) types.EvalType { | |
if lft.Tp == mysql.TypeUnspecified || rft.Tp == mysql.TypeUnspecified { | |
if lft.Tp == rft.Tp { | |
return types.ETString | |
} | |
if lft.Tp == mysql.TypeUnspecified { | |
lhs = rhs | |
} else { | |
rhs = lhs | |
} | |
} | |
if lhs.IsStringKind() && rhs.IsStringKind() { | |
return types.ETString | |
} else if (lhs == types.ETInt || lft.Hybrid()) && (rhs == types.ETInt || rft.Hybrid()) { | |
return types.ETInt | |
} else if ((lhs == types.ETInt || lft.Hybrid()) || lhs == types.ETDecimal) && | |
((rhs == types.ETInt || rft.Hybrid()) || rhs == types.ETDecimal) { | |
return types.ETDecimal | |
} | |
return types.ETReal | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IsStringKind contains ETDatetime, etc.
func (et EvalType) IsStringKind() bool {
return et == ETString || et == ETDatetime ||
et == ETTimestamp || et == ETDuration || et == ETJson
}
If the val's type is String, they will be compared as string
Noop, getBaseCmpType
gets a basic comparison type, the final comparison type may change later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Though not related to this patch, looks like I found another compatibility issue:
In MySQL:
mysql> create table tbl(id int primary key, a date);
Query OK, 0 rows affected (0.03 sec)
mysql> set sql_mode = '';
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> insert tbl values(0, '0000-00-00');
Query OK, 1 row affected (0.02 sec)
mysql> select a like 'a' from tbl;
+------------+
| a like 'a' |
+------------+
| 0 |
+------------+
1 row in set, 1 warning (0.00 sec)
mysql> show warnings;
+---------+------+---------------------------------------------------+
| Level | Code | Message |
+---------+------+---------------------------------------------------+
| Warning | 1292 | Incorrect date value: 'a' for column 'a' at row 1 |
+---------+------+---------------------------------------------------+
while in TiDB (even with this patch):
mysql> select a like 'a' from tbl;
+------------+
| a like 'a' |
+------------+
| NULL |
+------------+
1 row in set, 1 warning (0.00 sec)
mysql> show warnings;
+---------+------+-------------------------------+
| Level | Code | Message |
+---------+------+-------------------------------+
| Warning | 1292 | Incorrect datetime value: 'a' |
+---------+------+-------------------------------+
@wjhuang2016 are you interested to fix this as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IsStringKind contains ETDatetime, etc.
func (et EvalType) IsStringKind() bool { return et == ETString || et == ETDatetime || et == ETTimestamp || et == ETDuration || et == ETJson }If the val's type is String, they will be compared as string
Noop,
getBaseCmpType
gets a basic comparison type, the final comparison type may change later.
I got it. If the lhs is a datatime, the rhs may be converted to a datatime.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
planner/core/expression_rewriter.go
Outdated
@@ -1237,7 +1237,7 @@ func (er *expressionRewriter) patternLikeToExpression(v *ast.PatternLikeExpr) { | |||
} | |||
if !isNull { | |||
patValue, patTypes := stringutil.CompilePattern(patString, v.Escape) | |||
if stringutil.IsExactMatch(patTypes) { | |||
if stringutil.IsExactMatch(patTypes) && er.ctxStack[l-2].GetType().EvalType().IsStringKind() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Though not related to this patch, looks like I found another compatibility issue:
In MySQL:
mysql> create table tbl(id int primary key, a date);
Query OK, 0 rows affected (0.03 sec)
mysql> set sql_mode = '';
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> insert tbl values(0, '0000-00-00');
Query OK, 1 row affected (0.02 sec)
mysql> select a like 'a' from tbl;
+------------+
| a like 'a' |
+------------+
| 0 |
+------------+
1 row in set, 1 warning (0.00 sec)
mysql> show warnings;
+---------+------+---------------------------------------------------+
| Level | Code | Message |
+---------+------+---------------------------------------------------+
| Warning | 1292 | Incorrect date value: 'a' for column 'a' at row 1 |
+---------+------+---------------------------------------------------+
while in TiDB (even with this patch):
mysql> select a like 'a' from tbl;
+------------+
| a like 'a' |
+------------+
| NULL |
+------------+
1 row in set, 1 warning (0.00 sec)
mysql> show warnings;
+---------+------+-------------------------------+
| Level | Code | Message |
+---------+------+-------------------------------+
| Warning | 1292 | Incorrect datetime value: 'a' |
+---------+------+-------------------------------+
@wjhuang2016 are you interested to fix this as well?
planner/core/physical_plan_test.go
Outdated
@@ -1170,11 +1170,10 @@ func (s *testPlanSuite) TestRefine(c *C) { | |||
sql: `select a from t where c_str like 123`, | |||
best: "IndexReader(Index(t.c_d_e_str)[[\"123\",\"123\"]])->Projection", | |||
}, | |||
// c is type int which will be added cast to specified type when building function signature, | |||
// and rewrite predicate like to predicate '=' when exact match , index still can be used. | |||
// c is type int which will be added cast to specified type when building function signature, no index can be used. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can simply remove this test now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@eurekaka Yeah, I will fix it.
@wjhuang2016 OK, can you file GitHub issues for those 2 compatibility problems found? Then for this PR, we can focus on the correction of the query result. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
cherry pick to release-2.1 failed |
cherry pick to release-3.0 in PR #11411 |
It seems that, not for sure, we failed to cherry-pick this commit to release-2.1. Please comment '/run-cherry-picker' to try to trigger the cherry-picker if we did fail to cherry-pick this commit before. @wjhuang2016 PTAL. |
What problem does this PR solve?
Fix #11171
What is changed and how it works?
Reject invalid conversion from like to =
0 like "a"
should not convert to0 = "a"
,if so, it will further become
0 = 0
and returntrue
After this pr,
t.col like "a"
can't use indexscan when col isn't a string.If the col isn't a string, the sql maybe wrong and is ok not to use indexsacn.
Check List
Tests
Code changes
Side effects
Related changes