From cf328f8d98b5f5da92a8d3cc5d7bdff5331bc0e7 Mon Sep 17 00:00:00 2001 From: Florent Poinsard Date: Thu, 31 Oct 2024 15:28:20 -0600 Subject: [PATCH 01/10] wip - add join predicates to vexplain output Signed-off-by: Florent Poinsard --- go/vt/vtgate/planbuilder/operators/keys.go | 23 ++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/go/vt/vtgate/planbuilder/operators/keys.go b/go/vt/vtgate/planbuilder/operators/keys.go index f5b592b2291..d4fab7d0bb9 100644 --- a/go/vt/vtgate/planbuilder/operators/keys.go +++ b/go/vt/vtgate/planbuilder/operators/keys.go @@ -36,13 +36,18 @@ type ( Column Column Uses sqlparser.ComparisonExprOperator } + JoinPredicate struct { + Cols []Column + Uses sqlparser.ComparisonExprOperator + } VExplainKeys struct { - StatementType string `json:"statementType"` - TableName []string `json:"tableName,omitempty"` - GroupingColumns []Column `json:"groupingColumns,omitempty"` - JoinColumns []ColumnUse `json:"joinColumns,omitempty"` - FilterColumns []ColumnUse `json:"filterColumns,omitempty"` - SelectColumns []Column `json:"selectColumns,omitempty"` + StatementType string `json:"statementType"` + TableName []string `json:"tableName,omitempty"` + GroupingColumns []Column `json:"groupingColumns,omitempty"` + JoinColumns []ColumnUse `json:"joinColumns,omitempty"` + FilterColumns []ColumnUse `json:"filterColumns,omitempty"` + SelectColumns []Column `json:"selectColumns,omitempty"` + JoinPredicates []JoinPredicate `json:"joinPredicates,omitempty"` } ) @@ -127,6 +132,7 @@ type columnUse struct { func GetVExplainKeys(ctx *plancontext.PlanningContext, stmt sqlparser.Statement) (result VExplainKeys) { var groupingColumns, selectColumns []*sqlparser.ColName var filterColumns, joinColumns []columnUse + var joinPredicates []JoinPredicate addPredicate := func(predicate sqlparser.Expr) { predicates := sqlparser.SplitAndExpression(nil, predicate) @@ -140,6 +146,10 @@ func GetVExplainKeys(ctx *plancontext.PlanningContext, stmt sqlparser.Statement) if lhsOK && rhsOK && ctx.SemTable.RecursiveDeps(lhs) != ctx.SemTable.RecursiveDeps(rhs) { // If the columns are from different tables, they are considered join columns output = &joinColumns + joinPredicates = append(joinPredicates, JoinPredicate{ + Cols: []Column{*createColumn(ctx, lhs), *createColumn(ctx, rhs)}, + Uses: cmp.Operator, + }) } if lhsOK { @@ -192,6 +202,7 @@ func GetVExplainKeys(ctx *plancontext.PlanningContext, stmt sqlparser.Statement) JoinColumns: getUniqueColUsages(ctx, joinColumns), FilterColumns: getUniqueColUsages(ctx, filterColumns), StatementType: sqlparser.ASTToStatementType(stmt).String(), + JoinPredicates: joinPredicates, } } From 65ee93e3d9653f812734f2278eca1ca07e4ac81d Mon Sep 17 00:00:00 2001 From: Florent Poinsard Date: Thu, 31 Oct 2024 15:59:36 -0600 Subject: [PATCH 02/10] improve how we filter duplicated join predicates Signed-off-by: Florent Poinsard --- go/vt/vtgate/planbuilder/operators/keys.go | 58 +++++++++++++++++++--- 1 file changed, 50 insertions(+), 8 deletions(-) diff --git a/go/vt/vtgate/planbuilder/operators/keys.go b/go/vt/vtgate/planbuilder/operators/keys.go index d4fab7d0bb9..f0d85e7c4c8 100644 --- a/go/vt/vtgate/planbuilder/operators/keys.go +++ b/go/vt/vtgate/planbuilder/operators/keys.go @@ -37,8 +37,8 @@ type ( Uses sqlparser.ComparisonExprOperator } JoinPredicate struct { - Cols []Column - Uses sqlparser.ComparisonExprOperator + LHS, RHS Column + Uses sqlparser.ComparisonExprOperator } VExplainKeys struct { StatementType string `json:"statementType"` @@ -129,10 +129,16 @@ type columnUse struct { use sqlparser.ComparisonExprOperator } +type joinPredicate struct { + lhs *sqlparser.ColName + rhs *sqlparser.ColName + use sqlparser.ComparisonExprOperator +} + func GetVExplainKeys(ctx *plancontext.PlanningContext, stmt sqlparser.Statement) (result VExplainKeys) { var groupingColumns, selectColumns []*sqlparser.ColName var filterColumns, joinColumns []columnUse - var joinPredicates []JoinPredicate + var jps []joinPredicate addPredicate := func(predicate sqlparser.Expr) { predicates := sqlparser.SplitAndExpression(nil, predicate) @@ -146,10 +152,7 @@ func GetVExplainKeys(ctx *plancontext.PlanningContext, stmt sqlparser.Statement) if lhsOK && rhsOK && ctx.SemTable.RecursiveDeps(lhs) != ctx.SemTable.RecursiveDeps(rhs) { // If the columns are from different tables, they are considered join columns output = &joinColumns - joinPredicates = append(joinPredicates, JoinPredicate{ - Cols: []Column{*createColumn(ctx, lhs), *createColumn(ctx, rhs)}, - Uses: cmp.Operator, - }) + jps = append(jps, joinPredicate{lhs: lhs, rhs: rhs, use: cmp.Operator}) } if lhsOK { @@ -202,8 +205,47 @@ func GetVExplainKeys(ctx *plancontext.PlanningContext, stmt sqlparser.Statement) JoinColumns: getUniqueColUsages(ctx, joinColumns), FilterColumns: getUniqueColUsages(ctx, filterColumns), StatementType: sqlparser.ASTToStatementType(stmt).String(), - JoinPredicates: joinPredicates, + JoinPredicates: getUniqueJoinPredicates(ctx, jps), + } +} + +func getUniqueJoinPredicates(ctx *plancontext.PlanningContext, joinPredicates []joinPredicate) []JoinPredicate { + isEqual := func(a, b joinPredicate) bool { + if a.use != b.use { + return false + } + // if (A.LHS = B.LHS and A.RHS = B.RHS) or (A.LHS = B.RHS and A.RHS = B.LHS) then equal + if a.lhs.Equal(b.lhs) && a.rhs.Equal(b.rhs) || a.lhs.Equal(b.rhs) && !a.rhs.Equal(b.lhs) { + return true + } + return false } + + var result []JoinPredicate + var seenJoinPredicates []joinPredicate +outer: + for _, predicate := range joinPredicates { + // check if this join predicate already exists + for _, newJoinPredicate := range seenJoinPredicates { + if isEqual(predicate, newJoinPredicate) { + continue outer + } + } + + seenJoinPredicates = append(seenJoinPredicates, predicate) + lhs := createColumn(ctx, predicate.lhs) + rhs := createColumn(ctx, predicate.rhs) + if lhs == nil || rhs == nil { + continue + } + result = append(result, JoinPredicate{ + LHS: *lhs, + RHS: *rhs, + Uses: predicate.use, + }) + } + + return result } func getUniqueColNames(ctx *plancontext.PlanningContext, inCols []*sqlparser.ColName) (columns []Column) { From f7f01e60896ed82a75c34b2aa71d74eed6e17b1d Mon Sep 17 00:00:00 2001 From: Florent Poinsard Date: Thu, 31 Oct 2024 16:31:50 -0600 Subject: [PATCH 03/10] unmarshal and marshal JoinPredicate Signed-off-by: Florent Poinsard --- go/vt/vtgate/planbuilder/operators/keys.go | 33 +++++++++++++++++++ .../vtgate/planbuilder/operators/keys_test.go | 3 ++ 2 files changed, 36 insertions(+) diff --git a/go/vt/vtgate/planbuilder/operators/keys.go b/go/vt/vtgate/planbuilder/operators/keys.go index f0d85e7c4c8..4dfdc3dcda6 100644 --- a/go/vt/vtgate/planbuilder/operators/keys.go +++ b/go/vt/vtgate/planbuilder/operators/keys.go @@ -116,6 +116,35 @@ func (cu *ColumnUse) UnmarshalJSON(data []byte) error { return nil } +func (jp *JoinPredicate) MarshalJSON() ([]byte, error) { + return json.Marshal(jp.String()) +} + +func (jp *JoinPredicate) UnmarshalJSON(data []byte) error { + var s string + if err := json.Unmarshal(data, &s); err != nil { + return err + } + subStrings := strings.Split(s, " ") + if len(subStrings) != 3 { + return fmt.Errorf("invalid JoinPredicate format: %s", s) + } + + op, err := sqlparser.ComparisonExprOperatorFromJson(subStrings[1]) + if err != nil { + return fmt.Errorf("invalid comparison operator: %w", err) + } + jp.Uses = op + + if err = jp.LHS.UnmarshalJSON([]byte(`"` + subStrings[0] + `"`)); err != nil { + return err + } + if err = jp.RHS.UnmarshalJSON([]byte(`"` + subStrings[2] + `"`)); err != nil { + return err + } + return nil +} + func (c Column) String() string { return fmt.Sprintf("%s.%s", c.Table, c.Name) } @@ -124,6 +153,10 @@ func (cu ColumnUse) String() string { return fmt.Sprintf("%s %s", cu.Column, cu.Uses.JSONString()) } +func (jp JoinPredicate) String() string { + return fmt.Sprintf("%s %s %s", jp.LHS.String(), jp.Uses.JSONString(), jp.RHS.String()) +} + type columnUse struct { col *sqlparser.ColName use sqlparser.ComparisonExprOperator diff --git a/go/vt/vtgate/planbuilder/operators/keys_test.go b/go/vt/vtgate/planbuilder/operators/keys_test.go index 5c60e62c70c..6f65d517fd0 100644 --- a/go/vt/vtgate/planbuilder/operators/keys_test.go +++ b/go/vt/vtgate/planbuilder/operators/keys_test.go @@ -49,6 +49,9 @@ func TestMarshalUnmarshal(t *testing.T) { {Table: "users", Name: "email"}, {Table: "orders", Name: "amount"}, }, + JoinPredicates: []JoinPredicate{ + {LHS: Column{Table: "users", Name: "id"}, RHS: Column{Table: "orders", Name: "user_id"}, Uses: sqlparser.EqualOp}, + }, } jsonData, err := json.Marshal(original) From 7e8269ca707e0bd72f5493a1d247d9cf1ae6d32c Mon Sep 17 00:00:00 2001 From: Florent Poinsard Date: Thu, 31 Oct 2024 16:46:11 -0600 Subject: [PATCH 04/10] better unique check for JoinPredicate Signed-off-by: Florent Poinsard --- go/vt/vtgate/planbuilder/operators/keys.go | 38 +++++++++++----------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/go/vt/vtgate/planbuilder/operators/keys.go b/go/vt/vtgate/planbuilder/operators/keys.go index 4dfdc3dcda6..4c572975dfa 100644 --- a/go/vt/vtgate/planbuilder/operators/keys.go +++ b/go/vt/vtgate/planbuilder/operators/keys.go @@ -163,9 +163,9 @@ type columnUse struct { } type joinPredicate struct { - lhs *sqlparser.ColName - rhs *sqlparser.ColName - use sqlparser.ComparisonExprOperator + lhs *sqlparser.ColName + rhs *sqlparser.ColName + uses sqlparser.ComparisonExprOperator } func GetVExplainKeys(ctx *plancontext.PlanningContext, stmt sqlparser.Statement) (result VExplainKeys) { @@ -185,7 +185,7 @@ func GetVExplainKeys(ctx *plancontext.PlanningContext, stmt sqlparser.Statement) if lhsOK && rhsOK && ctx.SemTable.RecursiveDeps(lhs) != ctx.SemTable.RecursiveDeps(rhs) { // If the columns are from different tables, they are considered join columns output = &joinColumns - jps = append(jps, joinPredicate{lhs: lhs, rhs: rhs, use: cmp.Operator}) + jps = append(jps, joinPredicate{lhs: lhs, rhs: rhs, uses: cmp.Operator}) } if lhsOK { @@ -243,39 +243,39 @@ func GetVExplainKeys(ctx *plancontext.PlanningContext, stmt sqlparser.Statement) } func getUniqueJoinPredicates(ctx *plancontext.PlanningContext, joinPredicates []joinPredicate) []JoinPredicate { - isEqual := func(a, b joinPredicate) bool { - if a.use != b.use { + isEqual := func(a, b JoinPredicate) bool { + if a.Uses != b.Uses { return false } // if (A.LHS = B.LHS and A.RHS = B.RHS) or (A.LHS = B.RHS and A.RHS = B.LHS) then equal - if a.lhs.Equal(b.lhs) && a.rhs.Equal(b.rhs) || a.lhs.Equal(b.rhs) && !a.rhs.Equal(b.lhs) { + if a == b || a.LHS.String() == b.RHS.String() && a.RHS.String() == b.LHS.String() { return true } return false } var result []JoinPredicate - var seenJoinPredicates []joinPredicate outer: for _, predicate := range joinPredicates { - // check if this join predicate already exists - for _, newJoinPredicate := range seenJoinPredicates { - if isEqual(predicate, newJoinPredicate) { - continue outer - } - } - - seenJoinPredicates = append(seenJoinPredicates, predicate) lhs := createColumn(ctx, predicate.lhs) rhs := createColumn(ctx, predicate.rhs) if lhs == nil || rhs == nil { continue } - result = append(result, JoinPredicate{ + newJp := JoinPredicate{ LHS: *lhs, RHS: *rhs, - Uses: predicate.use, - }) + Uses: predicate.uses, + } + + // check if this join predicate already exists + for _, oldJp := range result { + if isEqual(newJp, oldJp) { + continue outer + } + } + + result = append(result, newJp) } return result From 0282feba4bdc6e0aa3005fb414dfbec00c204e4a Mon Sep 17 00:00:00 2001 From: Florent Poinsard Date: Thu, 31 Oct 2024 16:51:46 -0600 Subject: [PATCH 05/10] add Equal method to JoinPredicate Signed-off-by: Florent Poinsard --- go/vt/vtgate/planbuilder/operators/keys.go | 24 +++++++++++----------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/go/vt/vtgate/planbuilder/operators/keys.go b/go/vt/vtgate/planbuilder/operators/keys.go index 4c572975dfa..2e5935db737 100644 --- a/go/vt/vtgate/planbuilder/operators/keys.go +++ b/go/vt/vtgate/planbuilder/operators/keys.go @@ -145,6 +145,17 @@ func (jp *JoinPredicate) UnmarshalJSON(data []byte) error { return nil } +func (jp JoinPredicate) Equal(other JoinPredicate) bool { + if jp.Uses != other.Uses { + return false + } + // if (A.LHS = B.LHS and A.RHS = B.RHS) or (A.LHS = B.RHS and A.RHS = B.LHS) then equal + if jp == other || jp.LHS.String() == other.RHS.String() && jp.RHS.String() == other.LHS.String() { + return true + } + return false +} + func (c Column) String() string { return fmt.Sprintf("%s.%s", c.Table, c.Name) } @@ -243,17 +254,6 @@ func GetVExplainKeys(ctx *plancontext.PlanningContext, stmt sqlparser.Statement) } func getUniqueJoinPredicates(ctx *plancontext.PlanningContext, joinPredicates []joinPredicate) []JoinPredicate { - isEqual := func(a, b JoinPredicate) bool { - if a.Uses != b.Uses { - return false - } - // if (A.LHS = B.LHS and A.RHS = B.RHS) or (A.LHS = B.RHS and A.RHS = B.LHS) then equal - if a == b || a.LHS.String() == b.RHS.String() && a.RHS.String() == b.LHS.String() { - return true - } - return false - } - var result []JoinPredicate outer: for _, predicate := range joinPredicates { @@ -270,7 +270,7 @@ outer: // check if this join predicate already exists for _, oldJp := range result { - if isEqual(newJp, oldJp) { + if newJp.Equal(oldJp) { continue outer } } From 20fb2eab87db83b3cfe2e94f37742902e6c198ec Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Mon, 4 Nov 2024 10:04:14 +0100 Subject: [PATCH 06/10] refactor: remove duplicate information Signed-off-by: Andres Taylor --- go/vt/vtgate/planbuilder/operators/keys.go | 2 -- go/vt/vtgate/planbuilder/operators/keys_test.go | 4 ---- 2 files changed, 6 deletions(-) diff --git a/go/vt/vtgate/planbuilder/operators/keys.go b/go/vt/vtgate/planbuilder/operators/keys.go index 2e5935db737..0db065e3b82 100644 --- a/go/vt/vtgate/planbuilder/operators/keys.go +++ b/go/vt/vtgate/planbuilder/operators/keys.go @@ -44,7 +44,6 @@ type ( StatementType string `json:"statementType"` TableName []string `json:"tableName,omitempty"` GroupingColumns []Column `json:"groupingColumns,omitempty"` - JoinColumns []ColumnUse `json:"joinColumns,omitempty"` FilterColumns []ColumnUse `json:"filterColumns,omitempty"` SelectColumns []Column `json:"selectColumns,omitempty"` JoinPredicates []JoinPredicate `json:"joinPredicates,omitempty"` @@ -246,7 +245,6 @@ func GetVExplainKeys(ctx *plancontext.PlanningContext, stmt sqlparser.Statement) return VExplainKeys{ SelectColumns: getUniqueColNames(ctx, selectColumns), GroupingColumns: getUniqueColNames(ctx, groupingColumns), - JoinColumns: getUniqueColUsages(ctx, joinColumns), FilterColumns: getUniqueColUsages(ctx, filterColumns), StatementType: sqlparser.ASTToStatementType(stmt).String(), JoinPredicates: getUniqueJoinPredicates(ctx, jps), diff --git a/go/vt/vtgate/planbuilder/operators/keys_test.go b/go/vt/vtgate/planbuilder/operators/keys_test.go index 6f65d517fd0..3fcd69f0b5b 100644 --- a/go/vt/vtgate/planbuilder/operators/keys_test.go +++ b/go/vt/vtgate/planbuilder/operators/keys_test.go @@ -35,10 +35,6 @@ func TestMarshalUnmarshal(t *testing.T) { {Table: "orders", Name: "category"}, {Table: "users", Name: "department"}, }, - JoinColumns: []ColumnUse{ - {Column: Column{Table: "users", Name: "id"}, Uses: sqlparser.EqualOp}, - {Column: Column{Table: "orders", Name: "user_id"}, Uses: sqlparser.EqualOp}, - }, FilterColumns: []ColumnUse{ {Column: Column{Table: "users", Name: "age"}, Uses: sqlparser.GreaterThanOp}, {Column: Column{Table: "orders", Name: "total"}, Uses: sqlparser.LessThanOp}, From 3f631e20f4c9f9848d611e0f1fc5c07cbaf38fa0 Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Mon, 4 Nov 2024 10:41:20 +0100 Subject: [PATCH 07/10] refactor: clean up code Signed-off-by: Andres Taylor --- go/vt/vtgate/planbuilder/operators/keys.go | 33 +++++++--------------- 1 file changed, 10 insertions(+), 23 deletions(-) diff --git a/go/vt/vtgate/planbuilder/operators/keys.go b/go/vt/vtgate/planbuilder/operators/keys.go index 0db065e3b82..b22ed95794a 100644 --- a/go/vt/vtgate/planbuilder/operators/keys.go +++ b/go/vt/vtgate/planbuilder/operators/keys.go @@ -144,17 +144,6 @@ func (jp *JoinPredicate) UnmarshalJSON(data []byte) error { return nil } -func (jp JoinPredicate) Equal(other JoinPredicate) bool { - if jp.Uses != other.Uses { - return false - } - // if (A.LHS = B.LHS and A.RHS = B.RHS) or (A.LHS = B.RHS and A.RHS = B.LHS) then equal - if jp == other || jp.LHS.String() == other.RHS.String() && jp.RHS.String() == other.LHS.String() { - return true - } - return false -} - func (c Column) String() string { return fmt.Sprintf("%s.%s", c.Table, c.Name) } @@ -253,30 +242,28 @@ func GetVExplainKeys(ctx *plancontext.PlanningContext, stmt sqlparser.Statement) func getUniqueJoinPredicates(ctx *plancontext.PlanningContext, joinPredicates []joinPredicate) []JoinPredicate { var result []JoinPredicate -outer: for _, predicate := range joinPredicates { lhs := createColumn(ctx, predicate.lhs) rhs := createColumn(ctx, predicate.rhs) if lhs == nil || rhs == nil { continue } - newJp := JoinPredicate{ + + result = append(result, JoinPredicate{ LHS: *lhs, RHS: *rhs, Uses: predicate.uses, - } + }) + } - // check if this join predicate already exists - for _, oldJp := range result { - if newJp.Equal(oldJp) { - continue outer - } + sort.Slice(result, func(i, j int) bool { + if result[i].LHS.Name == result[j].LHS.Name { + return result[i].RHS.Name < result[j].RHS.Name } + return result[i].LHS.Name < result[j].LHS.Name + }) - result = append(result, newJp) - } - - return result + return slices.Compact(result) } func getUniqueColNames(ctx *plancontext.PlanningContext, inCols []*sqlparser.ColName) (columns []Column) { From 74f4e989326f31ed7381c5fd6b7d960d960cc3bb Mon Sep 17 00:00:00 2001 From: Florent Poinsard Date: Mon, 4 Nov 2024 13:11:52 -0600 Subject: [PATCH 08/10] Fix unit tests Signed-off-by: Florent Poinsard --- go/vt/vtgate/testdata/executor_vexplain.json | 21 +++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/go/vt/vtgate/testdata/executor_vexplain.json b/go/vt/vtgate/testdata/executor_vexplain.json index 5b70354f158..280d4d0dd91 100644 --- a/go/vt/vtgate/testdata/executor_vexplain.json +++ b/go/vt/vtgate/testdata/executor_vexplain.json @@ -15,13 +15,12 @@ "query": "select * from user u join user_extra ue on u.id = ue.user_id where u.col1 \u003e 100 and ue.noLimit = 'foo'", "expected": { "statementType": "SELECT", - "joinColumns": [ - "`user`.id =", - "user_extra.user_id =" - ], "filterColumns": [ "`user`.col1 gt", "user_extra.noLimit =" + ], + "joinPredicates": [ + "`user`.id = user_extra.user_id" ] } }, @@ -29,13 +28,12 @@ "query": "select * from user_extra ue, user u where ue.noLimit = 'foo' and u.col1 \u003e 100 and ue.user_id = u.id", "expected": { "statementType": "SELECT", - "joinColumns": [ - "`user`.id =", - "user_extra.user_id =" - ], "filterColumns": [ "`user`.col1 gt", "user_extra.noLimit =" + ], + "joinPredicates": [ + "user_extra.user_id = `user`.id" ] } }, @@ -47,16 +45,15 @@ "`user`.foo", "user_extra.bar" ], - "joinColumns": [ - "`user`.id =", - "user_extra.user_id =" - ], "filterColumns": [ "`user`.`name` =" ], "selectColumns": [ "`user`.foo", "user_extra.bar" + ], + "joinPredicates": [ + "`user`.id = user_extra.user_id" ] } }, From 48f52b77a97b288df7a36affd82bf564bfa72980 Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Tue, 5 Nov 2024 14:19:47 +0100 Subject: [PATCH 09/10] feat: store join predicates same way no matter how they were written Signed-off-by: Andres Taylor --- go/vt/vtgate/planbuilder/operators/keys.go | 18 +++++++++++++----- go/vt/vtgate/testdata/executor_vexplain.json | 2 +- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/go/vt/vtgate/planbuilder/operators/keys.go b/go/vt/vtgate/planbuilder/operators/keys.go index b22ed95794a..8d75b260aeb 100644 --- a/go/vt/vtgate/planbuilder/operators/keys.go +++ b/go/vt/vtgate/planbuilder/operators/keys.go @@ -50,6 +50,18 @@ type ( } ) +func newJoinPredicate(lhs, rhs Column, op sqlparser.ComparisonExprOperator) JoinPredicate { + // we want to try to keep the columns in the same order, no matter how the query was written + if lhs.String() > rhs.String() { + var success bool + op, success = op.SwitchSides() + if success { + lhs, rhs = rhs, lhs + } + } + return JoinPredicate{LHS: lhs, RHS: rhs, Uses: op} +} + func (c Column) MarshalJSON() ([]byte, error) { if c.Table != "" { return json.Marshal(fmt.Sprintf("%s.%s", c.Table, c.Name)) @@ -249,11 +261,7 @@ func getUniqueJoinPredicates(ctx *plancontext.PlanningContext, joinPredicates [] continue } - result = append(result, JoinPredicate{ - LHS: *lhs, - RHS: *rhs, - Uses: predicate.uses, - }) + result = append(result, newJoinPredicate(*lhs, *rhs, predicate.uses)) } sort.Slice(result, func(i, j int) bool { diff --git a/go/vt/vtgate/testdata/executor_vexplain.json b/go/vt/vtgate/testdata/executor_vexplain.json index 280d4d0dd91..b1e5999b83f 100644 --- a/go/vt/vtgate/testdata/executor_vexplain.json +++ b/go/vt/vtgate/testdata/executor_vexplain.json @@ -33,7 +33,7 @@ "user_extra.noLimit =" ], "joinPredicates": [ - "user_extra.user_id = `user`.id" + "`user`.id = user_extra.user_id" ] } }, From cb8ee86b1116d4b464758fd3db72326b0c851f91 Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Tue, 5 Nov 2024 14:22:12 +0100 Subject: [PATCH 10/10] refactor: reformat Signed-off-by: Andres Taylor --- go/vt/vtgate/testdata/executor_vexplain.json | 254 +++++++++---------- 1 file changed, 127 insertions(+), 127 deletions(-) diff --git a/go/vt/vtgate/testdata/executor_vexplain.json b/go/vt/vtgate/testdata/executor_vexplain.json index b1e5999b83f..2b893588aa5 100644 --- a/go/vt/vtgate/testdata/executor_vexplain.json +++ b/go/vt/vtgate/testdata/executor_vexplain.json @@ -1,129 +1,129 @@ [ - { - "query": "select count(*), col2 from music group by col2", - "expected": { - "statementType": "SELECT", - "groupingColumns": [ - "music.col2" - ], - "selectColumns": [ - "music.col2" - ] - } - }, - { - "query": "select * from user u join user_extra ue on u.id = ue.user_id where u.col1 \u003e 100 and ue.noLimit = 'foo'", - "expected": { - "statementType": "SELECT", - "filterColumns": [ - "`user`.col1 gt", - "user_extra.noLimit =" - ], - "joinPredicates": [ - "`user`.id = user_extra.user_id" - ] - } - }, - { - "query": "select * from user_extra ue, user u where ue.noLimit = 'foo' and u.col1 \u003e 100 and ue.user_id = u.id", - "expected": { - "statementType": "SELECT", - "filterColumns": [ - "`user`.col1 gt", - "user_extra.noLimit =" - ], - "joinPredicates": [ - "`user`.id = user_extra.user_id" - ] - } - }, - { - "query": "select u.foo, ue.bar, count(*) from user u join user_extra ue on u.id = ue.user_id where u.name = 'John Doe' group by 1, 2", - "expected": { - "statementType": "SELECT", - "groupingColumns": [ - "`user`.foo", - "user_extra.bar" - ], - "filterColumns": [ - "`user`.`name` =" - ], - "selectColumns": [ - "`user`.foo", - "user_extra.bar" - ], - "joinPredicates": [ - "`user`.id = user_extra.user_id" - ] - } - }, - { - "query": "select * from (select * from user) as derived where derived.amount \u003e 1000", - "expected": { - "statementType": "SELECT" - } - }, - { - "query": "select name, sum(amount) from user group by name", - "expected": { - "statementType": "SELECT", - "groupingColumns": [ - "`user`.`name`" - ], - "selectColumns": [ - "`user`.`name`", - "`user`.amount" - ] - } - }, - { - "query": "select name from user where age \u003e 30", - "expected": { - "statementType": "SELECT", - "filterColumns": [ - "`user`.age gt" - ], - "selectColumns": [ - "`user`.`name`" - ] - } - }, - { - "query": "select * from user where name = 'apa' union select * from user_extra where name = 'monkey'", - "expected": { - "statementType": "SELECT", - "filterColumns": [ - "`user`.`name` =", - "user_extra.`name` =" - ] - } - }, - { - "query": "update user set name = 'Jane Doe' where id = 1", - "expected": { - "statementType": "UPDATE", - "filterColumns": [ - "`user`.id =" - ] - } - }, - { - "query": "delete from user where order_date \u003c '2023-01-01'", - "expected": { - "statementType": "DELETE", - "filterColumns": [ - "`user`.order_date lt" - ] - } - }, - { - "query": "select * from user where name between 'A' and 'C'", - "expected": { - "statementType": "SELECT", - "filterColumns": [ - "`user`.`name` ge", - "`user`.`name` le" - ] - } - } + { + "query": "select count(*), col2 from music group by col2", + "expected": { + "statementType": "SELECT", + "groupingColumns": [ + "music.col2" + ], + "selectColumns": [ + "music.col2" + ] + } + }, + { + "query": "select * from user u join user_extra ue on u.id = ue.user_id where u.col1 \u003e 100 and ue.noLimit = 'foo'", + "expected": { + "statementType": "SELECT", + "filterColumns": [ + "`user`.col1 gt", + "user_extra.noLimit =" + ], + "joinPredicates": [ + "`user`.id = user_extra.user_id" + ] + } + }, + { + "query": "select * from user_extra ue, user u where ue.noLimit = 'foo' and u.col1 \u003e 100 and ue.user_id = u.id", + "expected": { + "statementType": "SELECT", + "filterColumns": [ + "`user`.col1 gt", + "user_extra.noLimit =" + ], + "joinPredicates": [ + "`user`.id = user_extra.user_id" + ] + } + }, + { + "query": "select u.foo, ue.bar, count(*) from user u join user_extra ue on u.id = ue.user_id where u.name = 'John Doe' group by 1, 2", + "expected": { + "statementType": "SELECT", + "groupingColumns": [ + "`user`.foo", + "user_extra.bar" + ], + "filterColumns": [ + "`user`.`name` =" + ], + "selectColumns": [ + "`user`.foo", + "user_extra.bar" + ], + "joinPredicates": [ + "`user`.id = user_extra.user_id" + ] + } + }, + { + "query": "select * from (select * from user) as derived where derived.amount \u003e 1000", + "expected": { + "statementType": "SELECT" + } + }, + { + "query": "select name, sum(amount) from user group by name", + "expected": { + "statementType": "SELECT", + "groupingColumns": [ + "`user`.`name`" + ], + "selectColumns": [ + "`user`.`name`", + "`user`.amount" + ] + } + }, + { + "query": "select name from user where age \u003e 30", + "expected": { + "statementType": "SELECT", + "filterColumns": [ + "`user`.age gt" + ], + "selectColumns": [ + "`user`.`name`" + ] + } + }, + { + "query": "select * from user where name = 'apa' union select * from user_extra where name = 'monkey'", + "expected": { + "statementType": "SELECT", + "filterColumns": [ + "`user`.`name` =", + "user_extra.`name` =" + ] + } + }, + { + "query": "update user set name = 'Jane Doe' where id = 1", + "expected": { + "statementType": "UPDATE", + "filterColumns": [ + "`user`.id =" + ] + } + }, + { + "query": "delete from user where order_date \u003c '2023-01-01'", + "expected": { + "statementType": "DELETE", + "filterColumns": [ + "`user`.order_date lt" + ] + } + }, + { + "query": "select * from user where name between 'A' and 'C'", + "expected": { + "statementType": "SELECT", + "filterColumns": [ + "`user`.`name` ge", + "`user`.`name` le" + ] + } + } ] \ No newline at end of file