Skip to content
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: add the functional dependency for Datasource, proj, select, agg #33071

Merged
merged 29 commits into from
Mar 17, 2022
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
ed4e051
planner: add the functional dependency for Datasource, proj, select, agg
winoros Mar 15, 2022
748ba62
fix lint
winoros Mar 15, 2022
6b2043f
undo some changes
winoros Mar 15, 2022
ba60938
fix tests
winoros Mar 15, 2022
c06fc01
to https://github.com/winoros/tidb/pull/12
winoros Mar 15, 2022
39f3c78
add license header and fix check and fix import
winoros Mar 15, 2022
b357c0e
address comments
winoros Mar 15, 2022
d554d9b
address comments
winoros Mar 16, 2022
0e80bab
remove the laxUni = false case
winoros Mar 16, 2022
23f8abc
only use public index to build
winoros Mar 16, 2022
b2216e1
use isNullRejective instead
winoros Mar 16, 2022
d63eac9
Merge branch 'master' into fd-not-outer-join-and-open
winoros Mar 16, 2022
e442cb3
add sysvar to control
winoros Mar 16, 2022
0a45940
Merge branch 'master' into fd-not-outer-join-and-open
winoros Mar 16, 2022
68277c4
Merge branch 'master' into fd-not-outer-join-and-open
time-and-fate Mar 16, 2022
31d7565
use the getlatestIndexes
winoros Mar 17, 2022
faa629c
Merge remote-tracking branch 'yiding/fd-not-outer-join-and-open' into…
winoros Mar 17, 2022
27090c2
Update extract_fd_test.go
AilinKid Mar 17, 2022
eca73d8
Update extract_fd_test.go
AilinKid Mar 17, 2022
8d7613e
Update extract_fd_test.go
AilinKid Mar 17, 2022
94cfd2b
Merge branch 'master' into fd-not-outer-join-and-open
ti-chi-bot Mar 17, 2022
3b0f43d
Merge branch 'master' into fd-not-outer-join-and-open
ti-chi-bot Mar 17, 2022
cce750b
fix the variable
winoros Mar 17, 2022
c6b3568
Merge remote-tracking branch 'yiding/fd-not-outer-join-and-open' into…
winoros Mar 17, 2022
9c1d963
Merge branch 'master' into fd-not-outer-join-and-open
winoros Mar 17, 2022
91a10c2
Merge branch 'master' into fd-not-outer-join-and-open
winoros Mar 17, 2022
becf23b
Merge branch 'master' into fd-not-outer-join-and-open
winoros Mar 17, 2022
025a19f
Merge branch 'master' into fd-not-outer-join-and-open
ti-chi-bot Mar 17, 2022
195153f
Merge branch 'master' into fd-not-outer-join-and-open
ti-chi-bot Mar 17, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion executor/aggregate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -798,7 +798,7 @@ func TestOnlyFullGroupBy(t *testing.T) {
// tk.MustQuery("select * from (select * from t) as e group by a")
// tk.MustQuery("select * from (select * from t) as e group by b,d")
// err = tk.ExecToErr("select * from (select * from t) as e group by b,c")
// c.Assert(terror.ErrorEqual(err, plannercore.ErrFieldNotInGroupBy), IsTrue)
// require.Truef(t, terror.ErrorEqual(err, plannercore.ErrFieldNotInGroupBy), "err %v", err)

// test order by
tk.MustQuery("select c from t group by c,d order by d")
Expand Down
1 change: 1 addition & 0 deletions executor/prepared.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ func (e *PrepareExec) Next(ctx context.Context, req *chunk.Chunk) error {
var p plannercore.Plan
e.ctx.GetSessionVars().PlanID = 0
e.ctx.GetSessionVars().PlanColumnID = 0
e.ctx.GetSessionVars().MapHashCode2UniqueID4ExtendedCol = nil
destBuilder, _ := plannercore.NewPlanBuilder().Init(e.ctx, ret.InfoSchema, &hint.BlockHintProcessor{})
p, err = destBuilder.Build(ctx, stmt)
if err != nil {
Expand Down
2 changes: 2 additions & 0 deletions expression/column.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,8 @@ type Column struct {
InOperand bool

collationInfo

CorrelatedColUniqueID int64
}

// Equal implements Expression interface.
Expand Down
1 change: 1 addition & 0 deletions expression/function_traits.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ var unFoldableFunctions = map[string]struct{}{
ast.NextVal: {},
ast.LastVal: {},
ast.SetVal: {},
ast.AnyValue: {},
}

// DisableFoldFunctions stores functions which prevent child scope functions from being constant folded.
Expand Down
191 changes: 191 additions & 0 deletions expression/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,68 @@ func extractColumns(result []*Column, expr Expression, filter func(*Column) bool
return result
}

// ExtractEquivalenceColumns detects the equivalence from CNF exprs.
func ExtractEquivalenceColumns(result [][]Expression, exprs []Expression) [][]Expression {
// exprs are CNF expressions, EQ condition only make sense in the top level of every expr.
for _, expr := range exprs {
result = extractEquivalenceColumns(result, expr)
}
return result
}

func extractEquivalenceColumns(result [][]Expression, expr Expression) [][]Expression {
switch v := expr.(type) {
case *ScalarFunction:
// a==b, a<=>b, the latter one is evaluated to true when a,b are both null.
if v.FuncName.L == ast.EQ || v.FuncName.L == ast.NullEQ {
args := v.GetArgs()
if len(args) == 2 {
col1, ok1 := args[0].(*Column)
col2, ok2 := args[1].(*Column)
if ok1 && ok2 {
result = append(result, []Expression{col1, col2})
}
col, ok1 := args[0].(*Column)
scl, ok2 := args[1].(*ScalarFunction)
if ok1 && ok2 {
result = append(result, []Expression{col, scl})
}
col, ok1 = args[1].(*Column)
scl, ok2 = args[0].(*ScalarFunction)
if ok1 && ok2 {
result = append(result, []Expression{col, scl})
}
}
return result
}
if v.FuncName.L == ast.In {
args := v.GetArgs()
// only `col in (only 1 element)`, can we build an equivalence here.
if len(args[1:]) == 1 {
col1, ok1 := args[0].(*Column)
col2, ok2 := args[1].(*Column)
if ok1 && ok2 {
result = append(result, []Expression{col1, col2})
}
col, ok1 := args[0].(*Column)
scl, ok2 := args[1].(*ScalarFunction)
if ok1 && ok2 {
result = append(result, []Expression{col, scl})
}
col, ok1 = args[1].(*Column)
scl, ok2 = args[0].(*ScalarFunction)
if ok1 && ok2 {
result = append(result, []Expression{col, scl})
}
}
return result
}
// For Non-EQ function, we don't have to traverse down.
// eg: (a=b or c=d) doesn't make any definitely equivalence assertion.
}
return result
}

// extractColumnsAndCorColumns extracts columns and correlated columns from `expr` and append them to `result`.
func extractColumnsAndCorColumns(result []*Column, expr Expression) []*Column {
switch v := expr.(type) {
Expand All @@ -181,6 +243,99 @@ func extractColumnsAndCorColumns(result []*Column, expr Expression) []*Column {
return result
}

// ExtractConstantEqColumnsOrScalar detects the constant equal relationship from CNF exprs.
func ExtractConstantEqColumnsOrScalar(ctx sessionctx.Context, result []Expression, exprs []Expression) []Expression {
// exprs are CNF expressions, EQ condition only make sense in the top level of every expr.
for _, expr := range exprs {
result = extractConstantEqColumnsOrScalar(ctx, result, expr)
}
return result
}

func extractConstantEqColumnsOrScalar(ctx sessionctx.Context, result []Expression, expr Expression) []Expression {
switch v := expr.(type) {
case *ScalarFunction:
if v.FuncName.L == ast.EQ || v.FuncName.L == ast.NullEQ {
args := v.GetArgs()
if len(args) == 2 {
col, ok1 := args[0].(*Column)
_, ok2 := args[1].(*Constant)
if ok1 && ok2 {
result = append(result, col)
}
col, ok1 = args[1].(*Column)
_, ok2 = args[0].(*Constant)
if ok1 && ok2 {
result = append(result, col)
}
// take the correlated column as constant here.
col, ok1 = args[0].(*Column)
_, ok2 = args[1].(*CorrelatedColumn)
if ok1 && ok2 {
result = append(result, col)
}
col, ok1 = args[1].(*Column)
_, ok2 = args[0].(*CorrelatedColumn)
if ok1 && ok2 {
result = append(result, col)
}
scl, ok1 := args[0].(*ScalarFunction)
_, ok2 = args[1].(*Constant)
if ok1 && ok2 {
result = append(result, scl)
}
scl, ok1 = args[1].(*ScalarFunction)
_, ok2 = args[0].(*Constant)
if ok1 && ok2 {
result = append(result, scl)
}
// take the correlated column as constant here.
scl, ok1 = args[0].(*ScalarFunction)
_, ok2 = args[1].(*CorrelatedColumn)
if ok1 && ok2 {
result = append(result, scl)
}
scl, ok1 = args[1].(*ScalarFunction)
_, ok2 = args[0].(*CorrelatedColumn)
if ok1 && ok2 {
result = append(result, scl)
}
}
return result
}
if v.FuncName.L == ast.In {
args := v.GetArgs()
allArgsIsConst := true
// only `col in (all same const)`, can col be the constant column.
// eg: a in (1, "1") does, while a in (1, '2') doesn't.
guard := args[1]
for i, v := range args[1:] {
if _, ok := v.(*Constant); !ok {
allArgsIsConst = false
break
}
if i == 0 {
continue
}
if !guard.Equal(ctx, v) {
allArgsIsConst = false
break
}
}
if allArgsIsConst {
if col, ok := args[0].(*Column); ok {
result = append(result, col)
} else if scl, ok := args[0].(*ScalarFunction); ok {
result = append(result, scl)
}
}
return result
}
// For Non-EQ function, we don't have to traverse down.
}
return result
}

// ExtractColumnsAndCorColumnsFromExpressions extracts columns and correlated columns from expressions and append them to `result`.
func ExtractColumnsAndCorColumnsFromExpressions(result []*Column, list []Expression) []*Column {
for _, expr := range list {
Expand Down Expand Up @@ -861,6 +1016,42 @@ func IsRuntimeConstExpr(expr Expression) bool {
return false
}

// CheckNonDeterministic checks whether the current expression contains a non-deterministic func.
func CheckNonDeterministic(e Expression) bool {
switch x := e.(type) {
case *Constant, *Column, *CorrelatedColumn:
return false
case *ScalarFunction:
if _, ok := unFoldableFunctions[x.FuncName.L]; ok {
return true
}
for _, arg := range x.GetArgs() {
if CheckNonDeterministic(arg) {
return true
}
}
}
return false
}

// CheckFuncInExpr checks whether there's a given function in the expression.
func CheckFuncInExpr(e Expression, funcName string) bool {
switch x := e.(type) {
case *Constant, *Column, *CorrelatedColumn:
return false
case *ScalarFunction:
if x.FuncName.L == funcName {
return true
}
for _, arg := range x.GetArgs() {
if CheckFuncInExpr(arg, funcName) {
return true
}
}
}
return false
}

AilinKid marked this conversation as resolved.
Show resolved Hide resolved
// IsMutableEffectsExpr checks if expr contains function which is mutable or has side effects.
func IsMutableEffectsExpr(expr Expression) bool {
switch x := expr.(type) {
Expand Down
4 changes: 3 additions & 1 deletion parser/ast/dml.go
Original file line number Diff line number Diff line change
Expand Up @@ -690,7 +690,9 @@ type SelectField struct {
// Auxiliary stands for if this field is auxiliary.
// When we add a Field into SelectField list which is used for having/orderby clause but the field is not in select clause,
// we should set its Auxiliary to true. Then the TrimExec will trim the field.
Auxiliary bool
Auxiliary bool
AuxiliaryColInAgg bool
AuxiliaryColInOrderBy bool
}

// Restore implements Node interface.
Expand Down
Loading