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
plan,table: fix select null value for table partition #7452
Conversation
/run-all-tests tidb-test=pr/606 |
} | ||
} | ||
if column == nil { | ||
log.Warnf("partition pruning won't work on this expr:%s", pi.Expr) |
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.
I think we don't need to log a warning.
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.
Without partition pruning, a query need to scan all partitions, we'd better warn the user about this.
For example,
create table t (id int) partition by range (mod(id, 5)) (partition ... )
The warning log is not frequent, it's happen when creating table, and normal expression will not print the warning.
Check if the expression is null is more complex, the expression may be anything:
Change partition expression range is much easier, for partition 1 and others:
while partition 0 condition is actually
|
/run-common-test tidb-test=pr/606 |
table/tables/partition.go
Outdated
fmt.Fprintf(&buf, " or ((%s) is null)", pi.Expr) | ||
|
||
// Extracts the column of the partition expression, it will be used by partition prunning. | ||
if tmp, err1 := expression.ParseSimpleExprWithTableInfo(ctx, pi.Expr, tblInfo); err1 == nil { |
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.
err1
is not logged.
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.
If expression.ParseSimpleExprWithTableInfo(ctx, pi.Expr, tblInfo)
meets error,
expression.ParseSimpleExprWithTableInfo(ctx, pi.Expr < xxx, tblInfo)
will also meets error, and the error will be logged.
The err1
is not important, we just need to get a *expression.Column
from a (maybe) string.
LGTM |
PTAL @zz-jason |
PTAL @zz-jason |
@@ -538,6 +538,17 @@ func (s *testPlanSuite) TestTablePartition(c *C) { | |||
best: "Dual->Projection", | |||
is: is1, | |||
}, | |||
{ |
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.
these kind of tests can not show the detail about the filters, it's better to add some explain tests.
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.
I'll port this one https://github.com/twitter/mysql/blob/master/mysql-test/t/partition_pruning.test
It will certainly cover more cases, but it's a file and I could not do it in this PR.
// UpperBounds: (x < y1); (x < y2); (x < y3) | ||
type PartitionExpr struct { | ||
Column *expression.Column | ||
Ranges []expression.Expression | ||
UpperBounds []expression.Expression | ||
} | ||
|
||
func generatePartitionExpr(tblInfo *model.TableInfo) (*PartitionExpr, error) { |
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.
It's better to add some ut for this function.
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.
Done
table/tables/partition.go
Outdated
@@ -129,6 +131,19 @@ func generatePartitionExpr(tblInfo *model.TableInfo) (*PartitionExpr, error) { | |||
|
|||
if i > 0 { | |||
fmt.Fprintf(&buf, " and ((%s) >= (%s))", pi.Expr, pi.Definitions[i-1].LessThan[0]) | |||
} else { | |||
// NULL will locates in the first partition, so its expression is (expr < value or expr is null). |
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.
s/locates/locate/
table/tables/partition.go
Outdated
// UpperBounds: (x < y1); (x < y2); (x < y3) | ||
type PartitionExpr struct { | ||
Column *expression.Column |
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.
Add a comment for the newly added attribute.
ee42cde
to
78d356f
Compare
PTAL @zz-jason |
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
/run-all-tests |
What problem does this PR solve?
should get
But we get an empty result.
The reason is that partition pruning works incorrectly, it prunes all the partitions.
What is changed and how it works?
The partition pruning condition of partition[0] is changed from
expr < value
to
expr < value or expr is null
Before this change, the partition pruning conditions in the failed example are:
The pruning result is an empty set.
After this change, the partition pruning conditions are:
The first partition remains, so we get the correct result.
Check List
Tests
@zz-jason @coocood