From 00bef5d48c25abbe87dfbae1248a05c693bf82f7 Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Thu, 25 Jan 2024 13:24:45 +0100 Subject: [PATCH 1/7] Cherry-pick of https://github.com/vitessio/vitess/pull/14935 Signed-off-by: Andres Taylor --- .../operators/aggregation_pushing.go | 15 +- .../vtgate/planbuilder/operators/distinct.go | 11 +- .../planbuilder/operators/queryprojection.go | 147 +----- .../planbuilder/testdata/aggr_cases.json | 44 +- .../planbuilder/testdata/ddl_cases.json | 2 +- .../ddl_cases_no_default_keyspace.json | 4 +- .../planbuilder/testdata/filter_cases.json | 4 +- .../planbuilder/testdata/from_cases.json | 12 +- .../testdata/info_schema57_cases.json | 14 +- .../testdata/info_schema80_cases.json | 14 +- .../testdata/memory_sort_cases.json | 4 +- .../testdata/postprocess_cases.json | 20 +- .../planbuilder/testdata/select_cases.json | 102 +---- .../testdata/sysschema_default.json | 4 +- .../planbuilder/testdata/union_cases.json | 14 +- go/vt/vtgate/semantics/binder.go | 2 +- go/vt/vtgate/semantics/early_rewriter.go | 430 ++++++++++++------ go/vt/vtgate/semantics/early_rewriter_test.go | 81 +++- 18 files changed, 485 insertions(+), 439 deletions(-) diff --git a/go/vt/vtgate/planbuilder/operators/aggregation_pushing.go b/go/vt/vtgate/planbuilder/operators/aggregation_pushing.go index 657d8d129fc..184e3f947c3 100644 --- a/go/vt/vtgate/planbuilder/operators/aggregation_pushing.go +++ b/go/vt/vtgate/planbuilder/operators/aggregation_pushing.go @@ -432,17 +432,12 @@ var errAbortAggrPushing = fmt.Errorf("abort aggregation pushing") func addColumnsFromLHSInJoinPredicates(ctx *plancontext.PlanningContext, rootAggr *Aggregator, join *ApplyJoin, lhs *joinPusher) error { for _, pred := range join.JoinPredicates { for _, bve := range pred.LHSExprs { - expr := bve.Expr - wexpr, err := rootAggr.QP.GetSimplifiedExpr(ctx, expr) - if err != nil { - return err - } - idx, found := canReuseColumn(ctx, lhs.pushed.Columns, expr, extractExpr) + idx, found := canReuseColumn(ctx, lhs.pushed.Columns, bve.Expr, extractExpr) if !found { idx = len(lhs.pushed.Columns) - lhs.pushed.Columns = append(lhs.pushed.Columns, aeWrap(expr)) + lhs.pushed.Columns = append(lhs.pushed.Columns, aeWrap(bve.Expr)) } - _, found = canReuseColumn(ctx, lhs.pushed.Grouping, wexpr, func(by GroupBy) sqlparser.Expr { + _, found = canReuseColumn(ctx, lhs.pushed.Grouping, bve.Expr, func(by GroupBy) sqlparser.Expr { return by.SimplifiedExpr }) @@ -451,8 +446,8 @@ func addColumnsFromLHSInJoinPredicates(ctx *plancontext.PlanningContext, rootAgg } lhs.pushed.Grouping = append(lhs.pushed.Grouping, GroupBy{ - Inner: expr, - SimplifiedExpr: wexpr, + Inner: bve.Expr, + SimplifiedExpr: bve.Expr, ColOffset: idx, WSOffset: -1, }) diff --git a/go/vt/vtgate/planbuilder/operators/distinct.go b/go/vt/vtgate/planbuilder/operators/distinct.go index 158d327c19c..a521f12c8db 100644 --- a/go/vt/vtgate/planbuilder/operators/distinct.go +++ b/go/vt/vtgate/planbuilder/operators/distinct.go @@ -52,16 +52,11 @@ func (d *Distinct) planOffsets(ctx *plancontext.PlanningContext) error { return err } for idx, col := range columns { - e, err := d.QP.GetSimplifiedExpr(ctx, col.Expr) - if err != nil { - // ambiguous columns are not a problem for DISTINCT - e = col.Expr - } var wsCol *int - typ, coll, _ := ctx.SemTable.TypeForExpr(e) + typ, coll, _ := ctx.SemTable.TypeForExpr(col.Expr) - if ctx.SemTable.NeedsWeightString(e) { - offset, err := d.Source.AddColumn(ctx, true, false, aeWrap(weightStringFor(e))) + if ctx.SemTable.NeedsWeightString(col.Expr) { + offset, err := d.Source.AddColumn(ctx, true, false, aeWrap(weightStringFor(col.Expr))) if err != nil { return err } diff --git a/go/vt/vtgate/planbuilder/operators/queryprojection.go b/go/vt/vtgate/planbuilder/operators/queryprojection.go index 2bcba2fc0a2..0630b09d459 100644 --- a/go/vt/vtgate/planbuilder/operators/queryprojection.go +++ b/go/vt/vtgate/planbuilder/operators/queryprojection.go @@ -21,7 +21,6 @@ import ( "fmt" "io" "slices" - "sort" "strings" "vitess.io/vitess/go/mysql/collations" @@ -216,9 +215,7 @@ func createQPFromSelect(ctx *plancontext.PlanningContext, sel *sqlparser.Select) if err := qp.addGroupBy(ctx, sel.GroupBy); err != nil { return nil, err } - if err := qp.addOrderBy(ctx, sel.OrderBy); err != nil { - return nil, err - } + qp.addOrderBy(ctx, sel.OrderBy) if !qp.HasAggr && sel.Having != nil { qp.HasAggr = containsAggr(sel.Having.Expr) } @@ -340,10 +337,7 @@ func createQPFromUnion(ctx *plancontext.PlanningContext, union *sqlparser.Union) return nil, err } - err = qp.addOrderBy(ctx, union.OrderBy) - if err != nil { - return nil, err - } + qp.addOrderBy(ctx, union.OrderBy) return qp, nil } @@ -365,29 +359,24 @@ func (es *expressionSet) add(ctx *plancontext.PlanningContext, e sqlparser.Expr) return true } -func (qp *QueryProjection) addOrderBy(ctx *plancontext.PlanningContext, orderBy sqlparser.OrderBy) error { +func (qp *QueryProjection) addOrderBy(ctx *plancontext.PlanningContext, orderBy sqlparser.OrderBy) { canPushSorting := true es := &expressionSet{} for _, order := range orderBy { - simpleExpr, err := qp.GetSimplifiedExpr(ctx, order.Expr) - if err != nil { - return err - } - if sqlparser.IsNull(simpleExpr) { + if sqlparser.IsNull(order.Expr) { // ORDER BY null can safely be ignored continue } - if !es.add(ctx, simpleExpr) { + if !es.add(ctx, order.Expr) { continue } qp.OrderExprs = append(qp.OrderExprs, ops.OrderBy{ Inner: sqlparser.CloneRefOfOrder(order), - SimplifiedExpr: simpleExpr, + SimplifiedExpr: order.Expr, }) - canPushSorting = canPushSorting && !containsAggr(simpleExpr) + canPushSorting = canPushSorting && !containsAggr(order.Expr) } qp.CanPushSorting = canPushSorting - return nil } func (qp *QueryProjection) calculateDistinct(ctx *plancontext.PlanningContext) error { @@ -436,20 +425,16 @@ func (qp *QueryProjection) addGroupBy(ctx *plancontext.PlanningContext, groupBy es := &expressionSet{} for _, group := range groupBy { selectExprIdx, aliasExpr := qp.FindSelectExprIndexForExpr(ctx, group) - simpleExpr, err := qp.GetSimplifiedExpr(ctx, group) - if err != nil { - return err - } - if err = checkForInvalidGroupingExpressions(simpleExpr); err != nil { + if err := checkForInvalidGroupingExpressions(group); err != nil { return err } - if !es.add(ctx, simpleExpr) { + if !es.add(ctx, group) { continue } - groupBy := NewGroupBy(group, simpleExpr, aliasExpr) + groupBy := NewGroupBy(group, group, aliasExpr) groupBy.InnerIndex = selectExprIdx qp.groupByExprs = append(qp.groupByExprs, groupBy) @@ -471,64 +456,6 @@ func (qp *QueryProjection) isExprInGroupByExprs(ctx *plancontext.PlanningContext return false } -// GetSimplifiedExpr takes an expression used in ORDER BY or GROUP BY, and returns an expression that is simpler to evaluate -func (qp *QueryProjection) GetSimplifiedExpr(ctx *plancontext.PlanningContext, e sqlparser.Expr) (found sqlparser.Expr, err error) { - if qp == nil { - return e, nil - } - // If the ORDER BY is against a column alias, we need to remember the expression - // behind the alias. The weightstring(.) calls needs to be done against that expression and not the alias. - // Eg - select music.foo as bar, weightstring(music.foo) from music order by bar - - in, isColName := e.(*sqlparser.ColName) - if !(isColName && in.Qualifier.IsEmpty()) { - // we are only interested in unqualified column names. if it's not a column name and not unqualified, we're done - return e, nil - } - - check := func(e sqlparser.Expr) error { - if found != nil && !ctx.SemTable.EqualsExprWithDeps(found, e) { - return &semantics.AmbiguousColumnError{Column: sqlparser.String(in)} - } - found = e - return nil - } - - for _, selectExpr := range qp.SelectExprs { - ae, ok := selectExpr.Col.(*sqlparser.AliasedExpr) - if !ok { - continue - } - aliased := !ae.As.IsEmpty() - if aliased { - if in.Name.Equal(ae.As) { - err = check(ae.Expr) - if err != nil { - return nil, err - } - } - } else { - seCol, ok := ae.Expr.(*sqlparser.ColName) - if !ok { - continue - } - if seCol.Name.Equal(in.Name) { - // If the column name matches, we have a match, even if the table name is not listed - err = check(ae.Expr) - if err != nil { - return nil, err - } - } - } - } - - if found == nil { - found = e - } - - return found, nil -} - // toString should only be used for tests func (qp *QueryProjection) toString() string { type output struct { @@ -794,46 +721,6 @@ func (qp *QueryProjection) FindSelectExprIndexForExpr(ctx *plancontext.PlanningC return nil, nil } -// OldAlignGroupByAndOrderBy TODO Remove once all of horizon planning is done on the operators -func (qp *QueryProjection) OldAlignGroupByAndOrderBy(ctx *plancontext.PlanningContext) { - // The ORDER BY can be performed before the OA - - var newGrouping []GroupBy - if len(qp.OrderExprs) == 0 { - // The query didn't ask for any particular order, so we are free to add arbitrary ordering. - // We'll align the grouping and ordering by the output columns - newGrouping = qp.GetGrouping() - SortGrouping(newGrouping) - for _, groupBy := range newGrouping { - qp.OrderExprs = append(qp.OrderExprs, groupBy.AsOrderBy()) - } - } else { - // Here we align the GROUP BY and ORDER BY. - // First step is to make sure that the GROUP BY is in the same order as the ORDER BY - used := make([]bool, len(qp.groupByExprs)) - for _, orderExpr := range qp.OrderExprs { - for i, groupingExpr := range qp.groupByExprs { - if !used[i] && ctx.SemTable.EqualsExpr(groupingExpr.SimplifiedExpr, orderExpr.SimplifiedExpr) { - newGrouping = append(newGrouping, groupingExpr) - used[i] = true - } - } - } - if len(newGrouping) != len(qp.groupByExprs) { - // we are missing some groupings. We need to add them both to the new groupings list, but also to the ORDER BY - for i, added := range used { - if !added { - groupBy := qp.groupByExprs[i] - newGrouping = append(newGrouping, groupBy) - qp.OrderExprs = append(qp.OrderExprs, groupBy.AsOrderBy()) - } - } - } - } - - qp.groupByExprs = newGrouping -} - // AlignGroupByAndOrderBy aligns the group by and order by columns, so they are in the same order // The GROUP BY clause is a set - the order between the elements does not make any difference, // so we can simply re-arrange the column order @@ -903,18 +790,14 @@ func (qp *QueryProjection) useGroupingOverDistinct(ctx *plancontext.PlanningCont // not an alias Expr, cannot continue forward. return false, nil } - sExpr, err := qp.GetSimplifiedExpr(ctx, ae.Expr) - if err != nil { - return false, err - } // check if the grouping already exists on that column. found := slices.IndexFunc(qp.groupByExprs, func(gb GroupBy) bool { - return ctx.SemTable.EqualsExprWithDeps(gb.SimplifiedExpr, sExpr) + return ctx.SemTable.EqualsExprWithDeps(gb.SimplifiedExpr, ae.Expr) }) if found != -1 { continue } - groupBy := NewGroupBy(ae.Expr, sExpr, ae) + groupBy := NewGroupBy(ae.Expr, ae.Expr, ae) selectExprIdx := idx groupBy.InnerIndex = &selectExprIdx @@ -938,12 +821,6 @@ func checkForInvalidGroupingExpressions(expr sqlparser.Expr) error { }, expr) } -func SortGrouping(a []GroupBy) { - sort.Slice(a, func(i, j int) bool { - return CompareRefInt(a[i].InnerIndex, a[j].InnerIndex) - }) -} - // CompareRefInt compares two references of integers. // In case either one is nil, it is considered to be smaller func CompareRefInt(a *int, b *int) bool { diff --git a/go/vt/vtgate/planbuilder/testdata/aggr_cases.json b/go/vt/vtgate/planbuilder/testdata/aggr_cases.json index 70f50e1f3f7..a59e289a7e9 100644 --- a/go/vt/vtgate/planbuilder/testdata/aggr_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/aggr_cases.json @@ -1054,8 +1054,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select `user`.col1 as a from `user` where 1 != 1 group by a collate utf8_general_ci", - "Query": "select `user`.col1 as a from `user` where `user`.id = 5 group by a collate utf8_general_ci", + "FieldQuery": "select `user`.col1 as a from `user` where 1 != 1 group by `user`.col1 collate utf8_general_ci", + "Query": "select `user`.col1 as a from `user` where `user`.id = 5 group by `user`.col1 collate utf8_general_ci", "Table": "`user`", "Values": [ "INT64(5)" @@ -1602,9 +1602,9 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select lower(textcol1) as v, count(*), weight_string(lower(textcol1)) from `user` where 1 != 1 group by v, weight_string(lower(textcol1))", + "FieldQuery": "select lower(textcol1) as v, count(*), weight_string(lower(textcol1)) from `user` where 1 != 1 group by lower(textcol1), weight_string(lower(textcol1))", "OrderBy": "(0|2) ASC", - "Query": "select lower(textcol1) as v, count(*), weight_string(lower(textcol1)) from `user` group by v, weight_string(lower(textcol1)) order by v asc", + "Query": "select lower(textcol1) as v, count(*), weight_string(lower(textcol1)) from `user` group by lower(textcol1), weight_string(lower(textcol1)) order by lower(textcol1) asc", "Table": "`user`" } ] @@ -1634,9 +1634,9 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select char_length(texcol1) as a, count(*), weight_string(char_length(texcol1)) from `user` where 1 != 1 group by a, weight_string(char_length(texcol1))", + "FieldQuery": "select char_length(texcol1) as a, count(*), weight_string(char_length(texcol1)) from `user` where 1 != 1 group by char_length(texcol1), weight_string(char_length(texcol1))", "OrderBy": "(0|2) ASC", - "Query": "select char_length(texcol1) as a, count(*), weight_string(char_length(texcol1)) from `user` group by a, weight_string(char_length(texcol1)) order by a asc", + "Query": "select char_length(texcol1) as a, count(*), weight_string(char_length(texcol1)) from `user` group by char_length(texcol1), weight_string(char_length(texcol1)) order by char_length(texcol1) asc", "Table": "`user`" } ] @@ -2638,9 +2638,9 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select ascii(val1) as a, count(*), weight_string(ascii(val1)) from `user` where 1 != 1 group by a, weight_string(ascii(val1))", + "FieldQuery": "select ascii(val1) as a, count(*), weight_string(ascii(val1)) from `user` where 1 != 1 group by ascii(val1), weight_string(ascii(val1))", "OrderBy": "(0|2) ASC", - "Query": "select ascii(val1) as a, count(*), weight_string(ascii(val1)) from `user` group by a, weight_string(ascii(val1)) order by a asc", + "Query": "select ascii(val1) as a, count(*), weight_string(ascii(val1)) from `user` group by ascii(val1), weight_string(ascii(val1)) order by ascii(val1) asc", "Table": "`user`" } ] @@ -3356,9 +3356,9 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select `user`.id, weight_string(`user`.id) from `user` where 1 != 1 group by id, weight_string(`user`.id)", + "FieldQuery": "select `user`.id, weight_string(`user`.id) from `user` where 1 != 1 group by `user`.id, weight_string(`user`.id)", "OrderBy": "(0|1) ASC", - "Query": "select `user`.id, weight_string(`user`.id) from `user` group by id, weight_string(`user`.id) order by id asc", + "Query": "select `user`.id, weight_string(`user`.id) from `user` group by `user`.id, weight_string(`user`.id) order by `user`.id asc", "Table": "`user`" }, { @@ -6371,5 +6371,29 @@ "user.user" ] } + }, + { + "comment": "valid but slightly confusing query should work - col in the order by should not get expanded to the column alias col", + "query": "select id, from_unixtime(min(col)) as col from user group by id order by min(col)", + "plan": { + "QueryType": "SELECT", + "Original": "select id, from_unixtime(min(col)) as col from user group by id order by min(col)", + "Instructions": { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, from_unixtime(min(col)) as col, min(col) from `user` where 1 != 1 group by id", + "OrderBy": "2 ASC", + "Query": "select id, from_unixtime(min(col)) as col, min(col) from `user` group by id order by min(col) asc", + "ResultColumns": 2, + "Table": "`user`" + }, + "TablesUsed": [ + "user.user" + ] + } } ] diff --git a/go/vt/vtgate/planbuilder/testdata/ddl_cases.json b/go/vt/vtgate/planbuilder/testdata/ddl_cases.json index eec1a0ce101..c6dad1ab946 100644 --- a/go/vt/vtgate/planbuilder/testdata/ddl_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/ddl_cases.json @@ -260,7 +260,7 @@ "Name": "main", "Sharded": false }, - "Query": "create view view_a as select a.col1, a.col2 from (select col1, col2 from unsharded where id = 1 union select col1, col2 from unsharded where id = 3) as a" + "Query": "create view view_a as select col1, col2 from (select col1, col2 from unsharded where id = 1 union select col1, col2 from unsharded where id = 3) as a" }, "TablesUsed": [ "main.view_a" diff --git a/go/vt/vtgate/planbuilder/testdata/ddl_cases_no_default_keyspace.json b/go/vt/vtgate/planbuilder/testdata/ddl_cases_no_default_keyspace.json index d05631cbff5..b0d77d0062e 100644 --- a/go/vt/vtgate/planbuilder/testdata/ddl_cases_no_default_keyspace.json +++ b/go/vt/vtgate/planbuilder/testdata/ddl_cases_no_default_keyspace.json @@ -163,7 +163,7 @@ "Name": "user", "Sharded": true }, - "Query": "create view view_a as select a.user_id, a.col1, a.col2 from authoritative as a" + "Query": "create view view_a as select user_id, col1, col2 from authoritative as a" }, "TablesUsed": [ "user.view_a" @@ -472,7 +472,7 @@ "Name": "user", "Sharded": true }, - "Query": "create view view_a as select user0_.col as col0_ from `user` as user0_ where id = 1 order by col0_ desc" + "Query": "create view view_a as select user0_.col as col0_ from `user` as user0_ where id = 1 order by user0_.col desc" }, "TablesUsed": [ "user.view_a" diff --git a/go/vt/vtgate/planbuilder/testdata/filter_cases.json b/go/vt/vtgate/planbuilder/testdata/filter_cases.json index 7cf1e830447..86ee2638515 100644 --- a/go/vt/vtgate/planbuilder/testdata/filter_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/filter_cases.json @@ -4018,7 +4018,7 @@ "Sharded": true }, "FieldQuery": "select a + 2 as a from `user` where 1 != 1", - "Query": "select a + 2 as a from `user` where a + 2 = 42", + "Query": "select a + 2 as a from `user` where a + 2 + 2 = 42", "Table": "`user`" }, "TablesUsed": [ @@ -4062,7 +4062,7 @@ "Sharded": false }, "FieldQuery": "select col + 2 as a from unsharded where 1 != 1", - "Query": "select col + 2 as a from unsharded having a = 42", + "Query": "select col + 2 as a from unsharded having col + 2 = 42", "Table": "unsharded" }, "TablesUsed": [ diff --git a/go/vt/vtgate/planbuilder/testdata/from_cases.json b/go/vt/vtgate/planbuilder/testdata/from_cases.json index f8cf7dd032e..d3df710b909 100644 --- a/go/vt/vtgate/planbuilder/testdata/from_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/from_cases.json @@ -3796,8 +3796,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select t3.push_it from (select bar as push_it from (select foo as bar from (select id as foo from `user` where 1 != 1) as t1 where 1 != 1) as t2 where 1 != 1) as t3 where 1 != 1", - "Query": "select t3.push_it from (select bar as push_it from (select foo as bar from (select id as foo from `user` where id = 12) as t1) as t2) as t3", + "FieldQuery": "select push_it from (select bar as push_it from (select foo as bar from (select id as foo from `user` where 1 != 1) as t1 where 1 != 1) as t2 where 1 != 1) as t3 where 1 != 1", + "Query": "select push_it from (select bar as push_it from (select foo as bar from (select id as foo from `user` where id = 12) as t1) as t2) as t3", "Table": "`user`", "Values": [ "INT64(12)" @@ -3822,8 +3822,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select user_details_view.id, user_details_view.col from (select `user`.id, user_extra.col from `user`, user_extra where 1 != 1) as user_details_view where 1 != 1", - "Query": "select user_details_view.id, user_details_view.col from (select `user`.id, user_extra.col from `user`, user_extra where `user`.id = user_extra.user_id) as user_details_view", + "FieldQuery": "select id, col from (select `user`.id, user_extra.col from `user`, user_extra where 1 != 1) as user_details_view where 1 != 1", + "Query": "select id, col from (select `user`.id, user_extra.col from `user`, user_extra where `user`.id = user_extra.user_id) as user_details_view", "Table": "`user`, user_extra" }, "TablesUsed": [ @@ -3845,8 +3845,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select user_details_view.id, user_details_view.col from (select `user`.id, user_extra.col from `user`, user_extra where 1 != 1) as user_details_view where 1 != 1", - "Query": "select user_details_view.id, user_details_view.col from (select `user`.id, user_extra.col from `user`, user_extra where `user`.id = user_extra.user_id) as user_details_view", + "FieldQuery": "select id, col from (select `user`.id, user_extra.col from `user`, user_extra where 1 != 1) as user_details_view where 1 != 1", + "Query": "select id, col from (select `user`.id, user_extra.col from `user`, user_extra where `user`.id = user_extra.user_id) as user_details_view", "Table": "`user`, user_extra" }, "TablesUsed": [ diff --git a/go/vt/vtgate/planbuilder/testdata/info_schema57_cases.json b/go/vt/vtgate/planbuilder/testdata/info_schema57_cases.json index 7380b203cdd..e374794627f 100644 --- a/go/vt/vtgate/planbuilder/testdata/info_schema57_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/info_schema57_cases.json @@ -307,7 +307,7 @@ "Sharded": false }, "FieldQuery": "select kcu.constraint_name as constraint_name, kcu.column_name as column_name, kcu.referenced_table_name as referenced_table_name, kcu.referenced_column_name as referenced_column_name, kcu.ordinal_position as ordinal_position, kcu.table_name as table_name from information_schema.key_column_usage as kcu where 1 != 1", - "Query": "select kcu.constraint_name as constraint_name, kcu.column_name as column_name, kcu.referenced_table_name as referenced_table_name, kcu.referenced_column_name as referenced_column_name, kcu.ordinal_position as ordinal_position, kcu.table_name as table_name from information_schema.key_column_usage as kcu where kcu.table_schema = :__vtschemaname /* VARCHAR */ and kcu.referenced_column_name is not null order by ordinal_position asc", + "Query": "select kcu.constraint_name as constraint_name, kcu.column_name as column_name, kcu.referenced_table_name as referenced_table_name, kcu.referenced_column_name as referenced_column_name, kcu.ordinal_position as ordinal_position, kcu.table_name as table_name from information_schema.key_column_usage as kcu where kcu.table_schema = :__vtschemaname /* VARCHAR */ and kcu.referenced_column_name is not null order by kcu.ordinal_position asc", "SysTableTableSchema": "[:v1]", "Table": "information_schema.key_column_usage" }, @@ -683,8 +683,8 @@ "Name": "main", "Sharded": false }, - "FieldQuery": "select x.table_name from (select a.CONSTRAINT_CATALOG, a.CONSTRAINT_SCHEMA, a.CONSTRAINT_NAME, a.TABLE_CATALOG, a.TABLE_SCHEMA, a.TABLE_NAME, a.COLUMN_NAME, a.ORDINAL_POSITION, a.POSITION_IN_UNIQUE_CONSTRAINT, a.REFERENCED_TABLE_SCHEMA, a.REFERENCED_TABLE_NAME, a.REFERENCED_COLUMN_NAME from information_schema.key_column_usage as a where 1 != 1) as x where 1 != 1", - "Query": "select x.table_name from (select a.CONSTRAINT_CATALOG, a.CONSTRAINT_SCHEMA, a.CONSTRAINT_NAME, a.TABLE_CATALOG, a.TABLE_SCHEMA, a.TABLE_NAME, a.COLUMN_NAME, a.ORDINAL_POSITION, a.POSITION_IN_UNIQUE_CONSTRAINT, a.REFERENCED_TABLE_SCHEMA, a.REFERENCED_TABLE_NAME, a.REFERENCED_COLUMN_NAME from information_schema.key_column_usage as a) as x", + "FieldQuery": "select x.table_name from (select CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA, CONSTRAINT_NAME, TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, ORDINAL_POSITION, POSITION_IN_UNIQUE_CONSTRAINT, REFERENCED_TABLE_SCHEMA, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME from information_schema.key_column_usage as a where 1 != 1) as x where 1 != 1", + "Query": "select x.table_name from (select CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA, CONSTRAINT_NAME, TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, ORDINAL_POSITION, POSITION_IN_UNIQUE_CONSTRAINT, REFERENCED_TABLE_SCHEMA, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME from information_schema.key_column_usage as a) as x", "Table": "information_schema.key_column_usage" } } @@ -711,8 +711,8 @@ "Name": "main", "Sharded": false }, - "FieldQuery": "select x.table_name, x.COLUMN_NAME from (select a.CONSTRAINT_CATALOG, a.CONSTRAINT_SCHEMA, a.CONSTRAINT_NAME, a.TABLE_CATALOG, a.TABLE_SCHEMA, a.TABLE_NAME, a.COLUMN_NAME, a.ORDINAL_POSITION, a.POSITION_IN_UNIQUE_CONSTRAINT, a.REFERENCED_TABLE_SCHEMA, a.REFERENCED_TABLE_NAME, a.REFERENCED_COLUMN_NAME from information_schema.key_column_usage as a where 1 != 1) as x where 1 != 1", - "Query": "select x.table_name, x.COLUMN_NAME from (select a.CONSTRAINT_CATALOG, a.CONSTRAINT_SCHEMA, a.CONSTRAINT_NAME, a.TABLE_CATALOG, a.TABLE_SCHEMA, a.TABLE_NAME, a.COLUMN_NAME, a.ORDINAL_POSITION, a.POSITION_IN_UNIQUE_CONSTRAINT, a.REFERENCED_TABLE_SCHEMA, a.REFERENCED_TABLE_NAME, a.REFERENCED_COLUMN_NAME from information_schema.key_column_usage as a) as x", + "FieldQuery": "select x.table_name, x.COLUMN_NAME from (select CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA, CONSTRAINT_NAME, TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, ORDINAL_POSITION, POSITION_IN_UNIQUE_CONSTRAINT, REFERENCED_TABLE_SCHEMA, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME from information_schema.key_column_usage as a where 1 != 1) as x where 1 != 1", + "Query": "select x.table_name, x.COLUMN_NAME from (select CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA, CONSTRAINT_NAME, TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, ORDINAL_POSITION, POSITION_IN_UNIQUE_CONSTRAINT, REFERENCED_TABLE_SCHEMA, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME from information_schema.key_column_usage as a) as x", "Table": "information_schema.key_column_usage" }, { @@ -769,8 +769,8 @@ "Name": "main", "Sharded": false }, - "FieldQuery": "select a.table_name from (select a.CONSTRAINT_CATALOG, a.CONSTRAINT_SCHEMA, a.CONSTRAINT_NAME, a.TABLE_CATALOG, a.TABLE_SCHEMA, a.TABLE_NAME, a.COLUMN_NAME, a.ORDINAL_POSITION, a.POSITION_IN_UNIQUE_CONSTRAINT, a.REFERENCED_TABLE_SCHEMA, a.REFERENCED_TABLE_NAME, a.REFERENCED_COLUMN_NAME from information_schema.key_column_usage as a where 1 != 1) as a, (select CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA, CONSTRAINT_NAME, UNIQUE_CONSTRAINT_CATALOG, UNIQUE_CONSTRAINT_SCHEMA, UNIQUE_CONSTRAINT_NAME, MATCH_OPTION, UPDATE_RULE, DELETE_RULE, TABLE_NAME, REFERENCED_TABLE_NAME from information_schema.referential_constraints where 1 != 1) as b where 1 != 1", - "Query": "select a.table_name from (select a.CONSTRAINT_CATALOG, a.CONSTRAINT_SCHEMA, a.CONSTRAINT_NAME, a.TABLE_CATALOG, a.TABLE_SCHEMA, a.TABLE_NAME, a.COLUMN_NAME, a.ORDINAL_POSITION, a.POSITION_IN_UNIQUE_CONSTRAINT, a.REFERENCED_TABLE_SCHEMA, a.REFERENCED_TABLE_NAME, a.REFERENCED_COLUMN_NAME from information_schema.key_column_usage as a where a.table_name = :a_table_name /* VARCHAR */) as a, (select CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA, CONSTRAINT_NAME, UNIQUE_CONSTRAINT_CATALOG, UNIQUE_CONSTRAINT_SCHEMA, UNIQUE_CONSTRAINT_NAME, MATCH_OPTION, UPDATE_RULE, DELETE_RULE, TABLE_NAME, REFERENCED_TABLE_NAME from information_schema.referential_constraints where table_name = :table_name /* VARCHAR */) as b", + "FieldQuery": "select a.table_name from (select CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA, CONSTRAINT_NAME, TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, ORDINAL_POSITION, POSITION_IN_UNIQUE_CONSTRAINT, REFERENCED_TABLE_SCHEMA, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME from information_schema.key_column_usage as a where 1 != 1) as a, (select CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA, CONSTRAINT_NAME, UNIQUE_CONSTRAINT_CATALOG, UNIQUE_CONSTRAINT_SCHEMA, UNIQUE_CONSTRAINT_NAME, MATCH_OPTION, UPDATE_RULE, DELETE_RULE, TABLE_NAME, REFERENCED_TABLE_NAME from information_schema.referential_constraints where 1 != 1) as b where 1 != 1", + "Query": "select a.table_name from (select CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA, CONSTRAINT_NAME, TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, ORDINAL_POSITION, POSITION_IN_UNIQUE_CONSTRAINT, REFERENCED_TABLE_SCHEMA, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME from information_schema.key_column_usage as a where a.table_name = :a_table_name /* VARCHAR */) as a, (select CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA, CONSTRAINT_NAME, UNIQUE_CONSTRAINT_CATALOG, UNIQUE_CONSTRAINT_SCHEMA, UNIQUE_CONSTRAINT_NAME, MATCH_OPTION, UPDATE_RULE, DELETE_RULE, TABLE_NAME, REFERENCED_TABLE_NAME from information_schema.referential_constraints where table_name = :table_name /* VARCHAR */) as b", "SysTableTableName": "[a_table_name:VARCHAR(\"users\"), table_name:VARCHAR(\"users\")]", "Table": "information_schema.key_column_usage, information_schema.referential_constraints" } diff --git a/go/vt/vtgate/planbuilder/testdata/info_schema80_cases.json b/go/vt/vtgate/planbuilder/testdata/info_schema80_cases.json index 7322b1a4ad2..f05ad3be125 100644 --- a/go/vt/vtgate/planbuilder/testdata/info_schema80_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/info_schema80_cases.json @@ -307,7 +307,7 @@ "Sharded": false }, "FieldQuery": "select kcu.constraint_name as constraint_name, kcu.column_name as column_name, kcu.referenced_table_name as referenced_table_name, kcu.referenced_column_name as referenced_column_name, kcu.ordinal_position as ordinal_position, kcu.table_name as table_name from information_schema.key_column_usage as kcu where 1 != 1", - "Query": "select kcu.constraint_name as constraint_name, kcu.column_name as column_name, kcu.referenced_table_name as referenced_table_name, kcu.referenced_column_name as referenced_column_name, kcu.ordinal_position as ordinal_position, kcu.table_name as table_name from information_schema.key_column_usage as kcu where kcu.table_schema = :__vtschemaname /* VARCHAR */ and kcu.referenced_column_name is not null order by ordinal_position asc", + "Query": "select kcu.constraint_name as constraint_name, kcu.column_name as column_name, kcu.referenced_table_name as referenced_table_name, kcu.referenced_column_name as referenced_column_name, kcu.ordinal_position as ordinal_position, kcu.table_name as table_name from information_schema.key_column_usage as kcu where kcu.table_schema = :__vtschemaname /* VARCHAR */ and kcu.referenced_column_name is not null order by kcu.ordinal_position asc", "SysTableTableSchema": "[:v1]", "Table": "information_schema.key_column_usage" }, @@ -748,8 +748,8 @@ "Name": "main", "Sharded": false }, - "FieldQuery": "select x.table_name from (select a.CONSTRAINT_CATALOG, a.CONSTRAINT_SCHEMA, a.CONSTRAINT_NAME, a.TABLE_CATALOG, a.TABLE_SCHEMA, a.TABLE_NAME, a.COLUMN_NAME, a.ORDINAL_POSITION, a.POSITION_IN_UNIQUE_CONSTRAINT, a.REFERENCED_TABLE_SCHEMA, a.REFERENCED_TABLE_NAME, a.REFERENCED_COLUMN_NAME from information_schema.key_column_usage as a where 1 != 1) as x where 1 != 1", - "Query": "select x.table_name from (select a.CONSTRAINT_CATALOG, a.CONSTRAINT_SCHEMA, a.CONSTRAINT_NAME, a.TABLE_CATALOG, a.TABLE_SCHEMA, a.TABLE_NAME, a.COLUMN_NAME, a.ORDINAL_POSITION, a.POSITION_IN_UNIQUE_CONSTRAINT, a.REFERENCED_TABLE_SCHEMA, a.REFERENCED_TABLE_NAME, a.REFERENCED_COLUMN_NAME from information_schema.key_column_usage as a) as x", + "FieldQuery": "select x.table_name from (select CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA, CONSTRAINT_NAME, TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, ORDINAL_POSITION, POSITION_IN_UNIQUE_CONSTRAINT, REFERENCED_TABLE_SCHEMA, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME from information_schema.key_column_usage as a where 1 != 1) as x where 1 != 1", + "Query": "select x.table_name from (select CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA, CONSTRAINT_NAME, TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, ORDINAL_POSITION, POSITION_IN_UNIQUE_CONSTRAINT, REFERENCED_TABLE_SCHEMA, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME from information_schema.key_column_usage as a) as x", "Table": "information_schema.key_column_usage" } } @@ -776,8 +776,8 @@ "Name": "main", "Sharded": false }, - "FieldQuery": "select x.table_name, x.COLUMN_NAME from (select a.CONSTRAINT_CATALOG, a.CONSTRAINT_SCHEMA, a.CONSTRAINT_NAME, a.TABLE_CATALOG, a.TABLE_SCHEMA, a.TABLE_NAME, a.COLUMN_NAME, a.ORDINAL_POSITION, a.POSITION_IN_UNIQUE_CONSTRAINT, a.REFERENCED_TABLE_SCHEMA, a.REFERENCED_TABLE_NAME, a.REFERENCED_COLUMN_NAME from information_schema.key_column_usage as a where 1 != 1) as x where 1 != 1", - "Query": "select x.table_name, x.COLUMN_NAME from (select a.CONSTRAINT_CATALOG, a.CONSTRAINT_SCHEMA, a.CONSTRAINT_NAME, a.TABLE_CATALOG, a.TABLE_SCHEMA, a.TABLE_NAME, a.COLUMN_NAME, a.ORDINAL_POSITION, a.POSITION_IN_UNIQUE_CONSTRAINT, a.REFERENCED_TABLE_SCHEMA, a.REFERENCED_TABLE_NAME, a.REFERENCED_COLUMN_NAME from information_schema.key_column_usage as a) as x", + "FieldQuery": "select x.table_name, x.COLUMN_NAME from (select CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA, CONSTRAINT_NAME, TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, ORDINAL_POSITION, POSITION_IN_UNIQUE_CONSTRAINT, REFERENCED_TABLE_SCHEMA, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME from information_schema.key_column_usage as a where 1 != 1) as x where 1 != 1", + "Query": "select x.table_name, x.COLUMN_NAME from (select CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA, CONSTRAINT_NAME, TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, ORDINAL_POSITION, POSITION_IN_UNIQUE_CONSTRAINT, REFERENCED_TABLE_SCHEMA, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME from information_schema.key_column_usage as a) as x", "Table": "information_schema.key_column_usage" }, { @@ -834,8 +834,8 @@ "Name": "main", "Sharded": false }, - "FieldQuery": "select a.table_name from (select a.CONSTRAINT_CATALOG, a.CONSTRAINT_SCHEMA, a.CONSTRAINT_NAME, a.TABLE_CATALOG, a.TABLE_SCHEMA, a.TABLE_NAME, a.COLUMN_NAME, a.ORDINAL_POSITION, a.POSITION_IN_UNIQUE_CONSTRAINT, a.REFERENCED_TABLE_SCHEMA, a.REFERENCED_TABLE_NAME, a.REFERENCED_COLUMN_NAME from information_schema.key_column_usage as a where 1 != 1) as a, (select CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA, CONSTRAINT_NAME, UNIQUE_CONSTRAINT_CATALOG, UNIQUE_CONSTRAINT_SCHEMA, UNIQUE_CONSTRAINT_NAME, MATCH_OPTION, UPDATE_RULE, DELETE_RULE, TABLE_NAME, REFERENCED_TABLE_NAME from information_schema.referential_constraints where 1 != 1) as b where 1 != 1", - "Query": "select a.table_name from (select a.CONSTRAINT_CATALOG, a.CONSTRAINT_SCHEMA, a.CONSTRAINT_NAME, a.TABLE_CATALOG, a.TABLE_SCHEMA, a.TABLE_NAME, a.COLUMN_NAME, a.ORDINAL_POSITION, a.POSITION_IN_UNIQUE_CONSTRAINT, a.REFERENCED_TABLE_SCHEMA, a.REFERENCED_TABLE_NAME, a.REFERENCED_COLUMN_NAME from information_schema.key_column_usage as a where a.table_name = :a_table_name /* VARCHAR */) as a, (select CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA, CONSTRAINT_NAME, UNIQUE_CONSTRAINT_CATALOG, UNIQUE_CONSTRAINT_SCHEMA, UNIQUE_CONSTRAINT_NAME, MATCH_OPTION, UPDATE_RULE, DELETE_RULE, TABLE_NAME, REFERENCED_TABLE_NAME from information_schema.referential_constraints where table_name = :table_name /* VARCHAR */) as b", + "FieldQuery": "select a.table_name from (select CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA, CONSTRAINT_NAME, TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, ORDINAL_POSITION, POSITION_IN_UNIQUE_CONSTRAINT, REFERENCED_TABLE_SCHEMA, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME from information_schema.key_column_usage as a where 1 != 1) as a, (select CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA, CONSTRAINT_NAME, UNIQUE_CONSTRAINT_CATALOG, UNIQUE_CONSTRAINT_SCHEMA, UNIQUE_CONSTRAINT_NAME, MATCH_OPTION, UPDATE_RULE, DELETE_RULE, TABLE_NAME, REFERENCED_TABLE_NAME from information_schema.referential_constraints where 1 != 1) as b where 1 != 1", + "Query": "select a.table_name from (select CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA, CONSTRAINT_NAME, TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, ORDINAL_POSITION, POSITION_IN_UNIQUE_CONSTRAINT, REFERENCED_TABLE_SCHEMA, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME from information_schema.key_column_usage as a where a.table_name = :a_table_name /* VARCHAR */) as a, (select CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA, CONSTRAINT_NAME, UNIQUE_CONSTRAINT_CATALOG, UNIQUE_CONSTRAINT_SCHEMA, UNIQUE_CONSTRAINT_NAME, MATCH_OPTION, UPDATE_RULE, DELETE_RULE, TABLE_NAME, REFERENCED_TABLE_NAME from information_schema.referential_constraints where table_name = :table_name /* VARCHAR */) as b", "SysTableTableName": "[a_table_name:VARCHAR(\"users\"), table_name:VARCHAR(\"users\")]", "Table": "information_schema.key_column_usage, information_schema.referential_constraints" } diff --git a/go/vt/vtgate/planbuilder/testdata/memory_sort_cases.json b/go/vt/vtgate/planbuilder/testdata/memory_sort_cases.json index 58e6744f1a6..4589bebdc50 100644 --- a/go/vt/vtgate/planbuilder/testdata/memory_sort_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/memory_sort_cases.json @@ -585,9 +585,9 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select u.a, convert(a, binary), weight_string(convert(a, binary)) from `user` as u where 1 != 1", + "FieldQuery": "select u.a, convert(u.a, binary), weight_string(convert(u.a, binary)) from `user` as u where 1 != 1", "OrderBy": "(1|2) DESC", - "Query": "select u.a, convert(a, binary), weight_string(convert(a, binary)) from `user` as u order by convert(a, binary) desc", + "Query": "select u.a, convert(u.a, binary), weight_string(convert(u.a, binary)) from `user` as u order by convert(u.a, binary) desc", "Table": "`user`" }, { diff --git a/go/vt/vtgate/planbuilder/testdata/postprocess_cases.json b/go/vt/vtgate/planbuilder/testdata/postprocess_cases.json index 01810134c13..622eda14832 100644 --- a/go/vt/vtgate/planbuilder/testdata/postprocess_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/postprocess_cases.json @@ -320,7 +320,7 @@ }, "FieldQuery": "select a, `user`.textcol1, b, weight_string(a), weight_string(b) from `user` where 1 != 1", "OrderBy": "(0|3) ASC, 1 ASC COLLATE latin1_swedish_ci, (2|4) ASC", - "Query": "select a, `user`.textcol1, b, weight_string(a), weight_string(b) from `user` order by a asc, textcol1 asc, b asc", + "Query": "select a, `user`.textcol1, b, weight_string(a), weight_string(b) from `user` order by a asc, `user`.textcol1 asc, b asc", "ResultColumns": 3, "Table": "`user`" }, @@ -373,7 +373,7 @@ }, "FieldQuery": "select id as foo, weight_string(id) from music where 1 != 1", "OrderBy": "(0|1) ASC", - "Query": "select id as foo, weight_string(id) from music order by foo asc", + "Query": "select id as foo, weight_string(id) from music order by id asc", "ResultColumns": 1, "Table": "music" }, @@ -526,7 +526,7 @@ "Sharded": true }, "FieldQuery": "select `user`.col1 as a, `user`.col2, `user`.id from `user` where 1 != 1", - "Query": "select `user`.col1 as a, `user`.col2, `user`.id from `user` where `user`.id = 1 order by a asc", + "Query": "select `user`.col1 as a, `user`.col2, `user`.id from `user` where `user`.id = 1 order by `user`.col1 asc", "Table": "`user`", "Values": [ "INT64(1)" @@ -579,7 +579,7 @@ "Sharded": true }, "FieldQuery": "select `user`.col1 as a, `user`.col2, `user`.id from `user` where 1 != 1", - "Query": "select `user`.col1 as a, `user`.col2, `user`.id from `user` where `user`.id = 1 order by a asc", + "Query": "select `user`.col1 as a, `user`.col2, `user`.id from `user` where `user`.id = 1 order by `user`.col1 asc", "Table": "`user`", "Values": [ "INT64(1)" @@ -1365,7 +1365,7 @@ }, "FieldQuery": "select id as foo, weight_string(id) from music where 1 != 1", "OrderBy": "(0|1) ASC", - "Query": "select id as foo, weight_string(id) from music order by foo asc", + "Query": "select id as foo, weight_string(id) from music order by id asc", "ResultColumns": 1, "Table": "music" }, @@ -1389,7 +1389,7 @@ }, "FieldQuery": "select id as foo, id2 as id, weight_string(id2) from music where 1 != 1", "OrderBy": "(1|2) ASC", - "Query": "select id as foo, id2 as id, weight_string(id2) from music order by id asc", + "Query": "select id as foo, id2 as id, weight_string(id2) from music order by id2 asc", "ResultColumns": 2, "Table": "music" }, @@ -1902,9 +1902,9 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select `user`.col1 as a, a collate utf8_general_ci, weight_string(a collate utf8_general_ci) from `user` where 1 != 1", + "FieldQuery": "select `user`.col1 as a, `user`.col1 collate utf8_general_ci, weight_string(`user`.col1 collate utf8_general_ci) from `user` where 1 != 1", "OrderBy": "(1|2) ASC", - "Query": "select `user`.col1 as a, a collate utf8_general_ci, weight_string(a collate utf8_general_ci) from `user` order by a collate utf8_general_ci asc", + "Query": "select `user`.col1 as a, `user`.col1 collate utf8_general_ci, weight_string(`user`.col1 collate utf8_general_ci) from `user` order by `user`.col1 collate utf8_general_ci asc", "ResultColumns": 1, "Table": "`user`" }, @@ -1950,9 +1950,9 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select `user`.col1 as a, a collate utf8_general_ci, weight_string(a collate utf8_general_ci) from `user` where 1 != 1", + "FieldQuery": "select `user`.col1 as a, `user`.col1 collate utf8_general_ci, weight_string(`user`.col1 collate utf8_general_ci) from `user` where 1 != 1", "OrderBy": "(1|2) ASC", - "Query": "select `user`.col1 as a, a collate utf8_general_ci, weight_string(a collate utf8_general_ci) from `user` order by a collate utf8_general_ci asc", + "Query": "select `user`.col1 as a, `user`.col1 collate utf8_general_ci, weight_string(`user`.col1 collate utf8_general_ci) from `user` order by `user`.col1 collate utf8_general_ci asc", "ResultColumns": 1, "Table": "`user`" }, diff --git a/go/vt/vtgate/planbuilder/testdata/select_cases.json b/go/vt/vtgate/planbuilder/testdata/select_cases.json index 34ceadfa181..2deab3e0aaf 100644 --- a/go/vt/vtgate/planbuilder/testdata/select_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/select_cases.json @@ -388,8 +388,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select a.user_id, a.col1, a.col2 from authoritative as a where 1 != 1", - "Query": "select a.user_id, a.col1, a.col2 from authoritative as a", + "FieldQuery": "select user_id, col1, col2 from authoritative as a where 1 != 1", + "Query": "select user_id, col1, col2 from authoritative as a", "Table": "authoritative" }, "TablesUsed": [ @@ -1129,7 +1129,7 @@ "Sharded": true }, "FieldQuery": "select user0_.col as col0_ from `user` as user0_ where 1 != 1", - "Query": "select user0_.col as col0_ from `user` as user0_ where id = 1 order by col0_ desc limit 3", + "Query": "select user0_.col as col0_ from `user` as user0_ where id = 1 order by user0_.col desc limit 3", "Table": "`user`", "Values": [ "INT64(1)" @@ -1328,8 +1328,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select t.id1 from (select `user`.id as id1 from `user` where 1 != 1) as t where 1 != 1", - "Query": "select t.id1 from (select `user`.id as id1 from `user`) as t", + "FieldQuery": "select id1 from (select `user`.id as id1 from `user` where 1 != 1) as t where 1 != 1", + "Query": "select id1 from (select `user`.id as id1 from `user`) as t", "Table": "`user`" }, { @@ -1339,8 +1339,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select t.id2 from (select user_extra.id as id2 from user_extra where 1 != 1) as t where 1 != 1", - "Query": "select t.id2 from (select user_extra.id as id2 from user_extra) as t", + "FieldQuery": "select id2 from (select user_extra.id as id2 from user_extra where 1 != 1) as t where 1 != 1", + "Query": "select id2 from (select user_extra.id as id2 from user_extra) as t", "Table": "user_extra" } ] @@ -1428,8 +1428,8 @@ "Name": "main", "Sharded": false }, - "FieldQuery": "select a.col1, a.col2 from (select col1, col2 from unsharded where 1 != 1 union select col1, col2 from unsharded where 1 != 1) as a where 1 != 1", - "Query": "select a.col1, a.col2 from (select col1, col2 from unsharded where id = 1 union select col1, col2 from unsharded where id = 3) as a", + "FieldQuery": "select col1, col2 from (select col1, col2 from unsharded where 1 != 1 union select col1, col2 from unsharded where 1 != 1) as a where 1 != 1", + "Query": "select col1, col2 from (select col1, col2 from unsharded where id = 1 union select col1, col2 from unsharded where id = 3) as a", "Table": "unsharded" }, "TablesUsed": [ @@ -2023,73 +2023,7 @@ { "comment": "select (select col from user limit 1) as a from user join user_extra order by a", "query": "select (select col from user limit 1) as a from user join user_extra order by a", - "plan": { - "QueryType": "SELECT", - "Original": "select (select col from user limit 1) as a from user join user_extra order by a", - "Instructions": { - "OperatorType": "Join", - "Variant": "Join", - "JoinColumnIndexes": "L:0", - "TableName": "`user`_user_extra", - "Inputs": [ - { - "OperatorType": "UncorrelatedSubquery", - "Variant": "PulloutValue", - "PulloutVars": [ - "__sq1" - ], - "Inputs": [ - { - "InputName": "SubQuery", - "OperatorType": "Limit", - "Count": "INT64(1)", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select col from `user` where 1 != 1", - "Query": "select col from `user` limit :__upper_limit", - "Table": "`user`" - } - ] - }, - { - "InputName": "Outer", - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select :__sq1 as a, weight_string(:__sq1) from `user` where 1 != 1", - "OrderBy": "(0|1) ASC", - "Query": "select :__sq1 as a, weight_string(:__sq1) from `user` order by a asc", - "Table": "`user`" - } - ] - }, - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select 1 from user_extra where 1 != 1", - "Query": "select 1 from user_extra", - "Table": "user_extra" - } - ] - }, - "TablesUsed": [ - "user.user", - "user.user_extra" - ] - } + "plan": "VT13002: unexpected AST struct for query: (select col from `user` limit 1)" }, { "comment": "select t.a from (select (select col from user limit 1) as a from user join user_extra) t", @@ -3381,7 +3315,7 @@ "Sharded": true }, "FieldQuery": "select music.id from music where 1 != 1", - "Query": "select music.id from music where music.id in (select _inner.id from (select music.id from music where music.user_id in (1, 2, 3)) as _inner)", + "Query": "select music.id from music where music.id in (select id from (select music.id from music where music.user_id in (1, 2, 3)) as _inner)", "Table": "music", "Values": [ "(INT64(1), INT64(2), INT64(3))" @@ -3901,7 +3835,7 @@ "Sharded": true }, "FieldQuery": "select music.id from music where 1 != 1", - "Query": "select music.id from music where music.id in (select subquery_for_limit.id from (select subquery_for_limit.id from (select music.id from music where music.user_id = 5 limit 10) as subquery_for_limit) as subquery_for_limit)", + "Query": "select music.id from music where music.id in (select id from (select id from (select music.id from music where music.user_id = 5 limit 10) as subquery_for_limit) as subquery_for_limit)", "Table": "music", "Values": [ "INT64(5)" @@ -3927,7 +3861,7 @@ "Sharded": true }, "FieldQuery": "select music.id from music where 1 != 1", - "Query": "select music.id from music where music.id in (select subquery_for_limit.id from (select subquery_for_limit.id from (select music.id from music where music.user_id in (5) limit 10) as subquery_for_limit) as subquery_for_limit)", + "Query": "select music.id from music where music.id in (select id from (select id from (select music.id from music where music.user_id in (5) limit 10) as subquery_for_limit) as subquery_for_limit)", "Table": "music", "Values": [ "INT64(5)" @@ -3965,8 +3899,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select subquery_for_limit.id from (select subquery_for_limit.id from (select music.id from music where 1 != 1) as subquery_for_limit where 1 != 1) as subquery_for_limit where 1 != 1", - "Query": "select subquery_for_limit.id from (select subquery_for_limit.id from (select music.id from music where music.user_id in ::__vals) as subquery_for_limit limit :__upper_limit) as subquery_for_limit limit :__upper_limit", + "FieldQuery": "select id from (select id from (select music.id from music where 1 != 1) as subquery_for_limit where 1 != 1) as subquery_for_limit where 1 != 1", + "Query": "select id from (select id from (select music.id from music where music.user_id in ::__vals) as subquery_for_limit limit :__upper_limit) as subquery_for_limit limit :__upper_limit", "Table": "music", "Values": [ "(INT64(5), INT64(6))" @@ -4024,8 +3958,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select subquery_for_limit.id from (select subquery_for_limit.id from (select music.id from music where 1 != 1) as subquery_for_limit where 1 != 1) as subquery_for_limit where 1 != 1", - "Query": "select subquery_for_limit.id from (select subquery_for_limit.id from (select music.id from music) as subquery_for_limit limit :__upper_limit) as subquery_for_limit limit :__upper_limit", + "FieldQuery": "select id from (select id from (select music.id from music where 1 != 1) as subquery_for_limit where 1 != 1) as subquery_for_limit where 1 != 1", + "Query": "select id from (select id from (select music.id from music) as subquery_for_limit limit :__upper_limit) as subquery_for_limit limit :__upper_limit", "Table": "music" } ] @@ -4787,7 +4721,7 @@ }, "FieldQuery": "select u.foo, weight_string(u.foo) from `user` as u where 1 != 1", "OrderBy": "(0|1) ASC", - "Query": "select u.foo, weight_string(u.foo) from `user` as u order by foo asc", + "Query": "select u.foo, weight_string(u.foo) from `user` as u order by u.foo asc", "Table": "`user`" }, { diff --git a/go/vt/vtgate/planbuilder/testdata/sysschema_default.json b/go/vt/vtgate/planbuilder/testdata/sysschema_default.json index 1d25f0f60af..cb633955f22 100644 --- a/go/vt/vtgate/planbuilder/testdata/sysschema_default.json +++ b/go/vt/vtgate/planbuilder/testdata/sysschema_default.json @@ -77,8 +77,8 @@ "Name": "main", "Sharded": false }, - "FieldQuery": "select x.`1` from (select 1 from information_schema.schemata where 1 != 1) as x where 1 != 1", - "Query": "select x.`1` from (select 1 from information_schema.schemata where schema_name = :__vtschemaname /* VARCHAR */ limit 1) as x", + "FieldQuery": "select `1` from (select 1 from information_schema.schemata where 1 != 1) as x where 1 != 1", + "Query": "select `1` from (select 1 from information_schema.schemata where schema_name = :__vtschemaname /* VARCHAR */ limit 1) as x", "SysTableTableSchema": "[VARCHAR(\"MyDatabase\")]", "Table": "information_schema.schemata" } diff --git a/go/vt/vtgate/planbuilder/testdata/union_cases.json b/go/vt/vtgate/planbuilder/testdata/union_cases.json index baea31d84bd..d09ca309241 100644 --- a/go/vt/vtgate/planbuilder/testdata/union_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/union_cases.json @@ -882,7 +882,7 @@ "Sharded": false }, "FieldQuery": "(select 1 from unsharded where 1 != 1 union select 1 from unsharded where 1 != 1 union all select 1 from unsharded where 1 != 1) union select 1 from unsharded where 1 != 1 union all select 1 from unsharded where 1 != 1", - "Query": "(select 1 from unsharded union select 1 from unsharded union all select 1 from unsharded order by 1 asc) union select 1 from unsharded union all select 1 from unsharded order by 1 asc", + "Query": "(select 1 from unsharded union select 1 from unsharded union all select 1 from unsharded order by `1` asc) union select 1 from unsharded union all select 1 from unsharded order by `1` asc", "Table": "unsharded" }, "TablesUsed": [ @@ -1212,8 +1212,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select X.`name`, X.foo from (select `name`, id as foo from `user` where 1 != 1 union select 'extra', user_id from user_extra where 1 != 1) as X where 1 != 1", - "Query": "select X.`name`, X.foo from (select `name`, id as foo from `user` where id = 3 union select 'extra', user_id from user_extra where user_id = 3) as X", + "FieldQuery": "select `name`, foo from (select `name`, id as foo from `user` where 1 != 1 union select 'extra', user_id from user_extra where 1 != 1) as X where 1 != 1", + "Query": "select `name`, foo from (select `name`, id as foo from `user` where id = 3 union select 'extra', user_id from user_extra where user_id = 3) as X", "Table": "`user`, user_extra", "Values": [ "INT64(3)" @@ -1263,8 +1263,8 @@ "Name": "main", "Sharded": false }, - "FieldQuery": "select kcu.CONSTRAINT_CATALOG, kcu.CONSTRAINT_SCHEMA, kcu.CONSTRAINT_NAME, kcu.TABLE_CATALOG, kcu.TABLE_SCHEMA, kcu.TABLE_NAME, kcu.COLUMN_NAME, kcu.ORDINAL_POSITION, kcu.POSITION_IN_UNIQUE_CONSTRAINT, kcu.REFERENCED_TABLE_SCHEMA, kcu.REFERENCED_TABLE_NAME, kcu.REFERENCED_COLUMN_NAME from information_schema.key_column_usage as kcu where 1 != 1", - "Query": "select distinct kcu.CONSTRAINT_CATALOG, kcu.CONSTRAINT_SCHEMA, kcu.CONSTRAINT_NAME, kcu.TABLE_CATALOG, kcu.TABLE_SCHEMA, kcu.TABLE_NAME, kcu.COLUMN_NAME, kcu.ORDINAL_POSITION, kcu.POSITION_IN_UNIQUE_CONSTRAINT, kcu.REFERENCED_TABLE_SCHEMA, kcu.REFERENCED_TABLE_NAME, kcu.REFERENCED_COLUMN_NAME from information_schema.key_column_usage as kcu where kcu.table_schema = :__vtschemaname /* VARCHAR */ and kcu.table_name = :kcu_table_name /* VARCHAR */", + "FieldQuery": "select CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA, CONSTRAINT_NAME, TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, ORDINAL_POSITION, POSITION_IN_UNIQUE_CONSTRAINT, REFERENCED_TABLE_SCHEMA, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME from information_schema.key_column_usage as kcu where 1 != 1", + "Query": "select distinct CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA, CONSTRAINT_NAME, TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, ORDINAL_POSITION, POSITION_IN_UNIQUE_CONSTRAINT, REFERENCED_TABLE_SCHEMA, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME from information_schema.key_column_usage as kcu where kcu.table_schema = :__vtschemaname /* VARCHAR */ and kcu.table_name = :kcu_table_name /* VARCHAR */", "SysTableTableName": "[kcu_table_name:VARCHAR(\"user_extra\")]", "SysTableTableSchema": "[VARCHAR(\"user\")]", "Table": "information_schema.key_column_usage" @@ -1276,8 +1276,8 @@ "Name": "main", "Sharded": false }, - "FieldQuery": "select kcu.CONSTRAINT_CATALOG, kcu.CONSTRAINT_SCHEMA, kcu.CONSTRAINT_NAME, kcu.TABLE_CATALOG, kcu.TABLE_SCHEMA, kcu.TABLE_NAME, kcu.COLUMN_NAME, kcu.ORDINAL_POSITION, kcu.POSITION_IN_UNIQUE_CONSTRAINT, kcu.REFERENCED_TABLE_SCHEMA, kcu.REFERENCED_TABLE_NAME, kcu.REFERENCED_COLUMN_NAME from information_schema.key_column_usage as kcu where 1 != 1", - "Query": "select distinct kcu.CONSTRAINT_CATALOG, kcu.CONSTRAINT_SCHEMA, kcu.CONSTRAINT_NAME, kcu.TABLE_CATALOG, kcu.TABLE_SCHEMA, kcu.TABLE_NAME, kcu.COLUMN_NAME, kcu.ORDINAL_POSITION, kcu.POSITION_IN_UNIQUE_CONSTRAINT, kcu.REFERENCED_TABLE_SCHEMA, kcu.REFERENCED_TABLE_NAME, kcu.REFERENCED_COLUMN_NAME from information_schema.key_column_usage as kcu where kcu.table_schema = :__vtschemaname /* VARCHAR */ and kcu.table_name = :kcu_table_name1 /* VARCHAR */", + "FieldQuery": "select CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA, CONSTRAINT_NAME, TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, ORDINAL_POSITION, POSITION_IN_UNIQUE_CONSTRAINT, REFERENCED_TABLE_SCHEMA, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME from information_schema.key_column_usage as kcu where 1 != 1", + "Query": "select distinct CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA, CONSTRAINT_NAME, TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, ORDINAL_POSITION, POSITION_IN_UNIQUE_CONSTRAINT, REFERENCED_TABLE_SCHEMA, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME from information_schema.key_column_usage as kcu where kcu.table_schema = :__vtschemaname /* VARCHAR */ and kcu.table_name = :kcu_table_name1 /* VARCHAR */", "SysTableTableName": "[kcu_table_name1:VARCHAR(\"music\")]", "SysTableTableSchema": "[VARCHAR(\"user\")]", "Table": "information_schema.key_column_usage" diff --git a/go/vt/vtgate/semantics/binder.go b/go/vt/vtgate/semantics/binder.go index e3fed7e5a68..764a8e41501 100644 --- a/go/vt/vtgate/semantics/binder.go +++ b/go/vt/vtgate/semantics/binder.go @@ -239,7 +239,7 @@ func (b *binder) resolveColumn(colName *sqlparser.ColName, current *scope, allow func (b *binder) resolveColumnInScope(current *scope, expr *sqlparser.ColName, allowMulti bool) (dependencies, error) { var deps dependencies = ¬hing{} for _, table := range current.tables { - if !expr.Qualifier.IsEmpty() && !table.matches(expr.Qualifier) { + if !expr.Qualifier.IsEmpty() && !table.matches(expr.Qualifier) && !current.isUnion { continue } thisDeps, err := table.dependencies(expr.Name.String(), b.org) diff --git a/go/vt/vtgate/semantics/early_rewriter.go b/go/vt/vtgate/semantics/early_rewriter.go index d11d12023c4..68f663b29db 100644 --- a/go/vt/vtgate/semantics/early_rewriter.go +++ b/go/vt/vtgate/semantics/early_rewriter.go @@ -38,23 +38,30 @@ type earlyRewriter struct { func (r *earlyRewriter) down(cursor *sqlparser.Cursor) error { switch node := cursor.Node().(type) { case *sqlparser.Where: - handleWhereClause(node, cursor.Parent()) + return r.handleWhereClause(node, cursor.Parent()) case sqlparser.SelectExprs: - return handleSelectExprs(r, cursor, node) + return r.handleSelectExprs(cursor, node) case *sqlparser.JoinTableExpr: - handleJoinTableExpr(r, node) + r.handleJoinTableExpr(node) case sqlparser.OrderBy: - handleOrderBy(r, cursor, node) + r.clause = "order clause" + iter := &orderByIterator{ + node: node, + idx: -1, + } + + return r.handleOrderByAndGroupBy(cursor.Parent(), iter) case *sqlparser.OrExpr: rewriteOrExpr(cursor, node) case *sqlparser.NotExpr: rewriteNotExpr(cursor, node) case sqlparser.GroupBy: r.clause = "group statement" - case *sqlparser.Literal: - return handleLiteral(r, cursor, node) - case *sqlparser.CollateExpr: - return handleCollateExpr(r, node) + iter := &exprIterator{ + node: node, + idx: -1, + } + return r.handleOrderByAndGroupBy(cursor.Parent(), iter) case *sqlparser.ComparisonExpr: return handleComparisonExpr(cursor, node) } @@ -67,6 +74,11 @@ func rewriteNotExpr(cursor *sqlparser.Cursor, node *sqlparser.NotExpr) { return } + // There is no inverse operator for NullSafeEqualOp. + // There doesn't exist a null safe non-equality. + if cmp.Operator == sqlparser.NullSafeEqualOp { + return + } cmp.Operator = sqlparser.Inverse(cmp.Operator) cursor.Replace(cmp) } @@ -84,7 +96,7 @@ func (r *earlyRewriter) up(cursor *sqlparser.Cursor) error { return err } - // since the binder has already been over the join, we need to invoke it again so it + // since the binder has already been over the join, we need to invoke it again, so it // can bind columns to the right tables sqlparser.Rewrite(node.Condition.On, nil, func(cursor *sqlparser.Cursor) bool { innerErr := r.binder.up(cursor) @@ -99,15 +111,25 @@ func (r *earlyRewriter) up(cursor *sqlparser.Cursor) error { } // handleWhereClause processes WHERE clauses, specifically the HAVING clause. -func handleWhereClause(node *sqlparser.Where, parent sqlparser.SQLNode) { +func (r *earlyRewriter) handleWhereClause(node *sqlparser.Where, parent sqlparser.SQLNode) error { + sel, ok := parent.(*sqlparser.Select) + if !ok { + return nil + } if node.Type != sqlparser.HavingClause { - return + return nil + } + expr, err := r.rewriteAliasesInOrderByHavingAndGroupBy(node.Expr, sel) + if err != nil { + return err } - rewriteHavingAndOrderBy(node, parent) + + node.Expr = expr + return nil } // handleSelectExprs expands * in SELECT expressions. -func handleSelectExprs(r *earlyRewriter, cursor *sqlparser.Cursor, node sqlparser.SelectExprs) error { +func (r *earlyRewriter) handleSelectExprs(cursor *sqlparser.Cursor, node sqlparser.SelectExprs) error { _, isSel := cursor.Parent().(*sqlparser.Select) if !isSel { return nil @@ -116,7 +138,7 @@ func handleSelectExprs(r *earlyRewriter, cursor *sqlparser.Cursor, node sqlparse } // handleJoinTableExpr processes JOIN table expressions and handles the Straight Join type. -func handleJoinTableExpr(r *earlyRewriter, node *sqlparser.JoinTableExpr) { +func (r *earlyRewriter) handleJoinTableExpr(node *sqlparser.JoinTableExpr) { if node.Join != sqlparser.StraightJoinType { return } @@ -124,93 +146,138 @@ func handleJoinTableExpr(r *earlyRewriter, node *sqlparser.JoinTableExpr) { r.warning = "straight join is converted to normal join" } -// handleOrderBy processes the ORDER BY clause. -func handleOrderBy(r *earlyRewriter, cursor *sqlparser.Cursor, node sqlparser.OrderBy) { - r.clause = "order clause" - rewriteHavingAndOrderBy(node, cursor.Parent()) +type orderByIterator struct { + node sqlparser.OrderBy + idx int } -// rewriteOrExpr rewrites OR expressions when the right side is FALSE. -func rewriteOrExpr(cursor *sqlparser.Cursor, node *sqlparser.OrExpr) { - newNode := rewriteOrFalse(*node) - if newNode != nil { - cursor.ReplaceAndRevisit(newNode) +func (it *orderByIterator) next() sqlparser.Expr { + it.idx++ + + if it.idx >= len(it.node) { + return nil } + + return it.node[it.idx].Expr } -// handleLiteral processes literals within the context of ORDER BY expressions. -func handleLiteral(r *earlyRewriter, cursor *sqlparser.Cursor, node *sqlparser.Literal) error { - newNode, err := r.rewriteOrderByExpr(node) - if err != nil { - return err - } - if newNode != nil { - cursor.Replace(newNode) +func (it *orderByIterator) replace(e sqlparser.Expr) error { + if it.idx >= len(it.node) { + return vterrors.VT13001("went past the last item") } + it.node[it.idx].Expr = e return nil } -// handleCollateExpr processes COLLATE expressions. -func handleCollateExpr(r *earlyRewriter, node *sqlparser.CollateExpr) error { - lit, ok := node.Expr.(*sqlparser.Literal) - if !ok { +type exprIterator struct { + node []sqlparser.Expr + idx int +} + +func (it *exprIterator) next() sqlparser.Expr { + it.idx++ + + if it.idx >= len(it.node) { return nil } - newNode, err := r.rewriteOrderByExpr(lit) - if err != nil { - return err - } - if newNode != nil { - node.Expr = newNode + + return it.node[it.idx] +} + +func (it *exprIterator) replace(e sqlparser.Expr) error { + if it.idx >= len(it.node) { + return vterrors.VT13001("went past the last item") } + it.node[it.idx] = e return nil } -// handleComparisonExpr processes Comparison expressions, specifically for tuples with equal length and EqualOp operator. -func handleComparisonExpr(cursor *sqlparser.Cursor, node *sqlparser.ComparisonExpr) error { - lft, lftOK := node.Left.(sqlparser.ValTuple) - rgt, rgtOK := node.Right.(sqlparser.ValTuple) - if !lftOK || !rgtOK || len(lft) != len(rgt) || node.Operator != sqlparser.EqualOp { +type iterator interface { + next() sqlparser.Expr + replace(e sqlparser.Expr) error +} + +func (r *earlyRewriter) replaceLiteralsInOrderByGroupBy(e sqlparser.Expr, iter iterator) (bool, error) { + lit := getIntLiteral(e) + if lit == nil { + return false, nil + } + + newExpr, err := r.rewriteOrderByExpr(lit) + if err != nil { + return false, err + } + + if getIntLiteral(newExpr) == nil { + coll, ok := e.(*sqlparser.CollateExpr) + if ok { + coll.Expr = newExpr + newExpr = coll + } + } else { + // the expression is still a literal int. that means that we don't really need to sort by it. + // we'll just replace the number with a string instead, just like mysql would do in this situation + // mysql> explain select 1 as foo from user group by 1; + // + // mysql> show warnings; + // +-------+------+-----------------------------------------------------------------+ + // | Level | Code | Message | + // +-------+------+-----------------------------------------------------------------+ + // | Note | 1003 | /* select#1 */ select 1 AS `foo` from `test`.`user` group by '' | + // +-------+------+-----------------------------------------------------------------+ + newExpr = sqlparser.NewStrLiteral("") + } + + err = iter.replace(newExpr) + return true, err +} + +func getIntLiteral(e sqlparser.Expr) *sqlparser.Literal { + var lit *sqlparser.Literal + switch node := e.(type) { + case *sqlparser.Literal: + lit = node + case *sqlparser.CollateExpr: + expr, ok := node.Expr.(*sqlparser.Literal) + if !ok { + return nil + } + lit = expr + default: return nil } - var predicates []sqlparser.Expr - for i, l := range lft { - r := rgt[i] - predicates = append(predicates, &sqlparser.ComparisonExpr{ - Operator: sqlparser.EqualOp, - Left: l, - Right: r, - Escape: node.Escape, - }) + if lit.Type != sqlparser.IntVal { + return nil } - cursor.Replace(sqlparser.AndExpressions(predicates...)) - return nil + return lit } -func (r *earlyRewriter) expandStar(cursor *sqlparser.Cursor, node sqlparser.SelectExprs) error { - currentScope := r.scoper.currentScope() - var selExprs sqlparser.SelectExprs - changed := false - for _, selectExpr := range node { - starExpr, isStarExpr := selectExpr.(*sqlparser.StarExpr) - if !isStarExpr { - selExprs = append(selExprs, selectExpr) +// handleOrderBy processes the ORDER BY clause. +func (r *earlyRewriter) handleOrderByAndGroupBy(parent sqlparser.SQLNode, iter iterator) error { + stmt, ok := parent.(sqlparser.SelectStatement) + if !ok { + return nil + } + + sel := sqlparser.GetFirstSelect(stmt) + for e := iter.next(); e != nil; e = iter.next() { + lit, err := r.replaceLiteralsInOrderByGroupBy(e, iter) + if err != nil { + return err + } + if lit { continue } - starExpanded, colNames, err := r.expandTableColumns(starExpr, currentScope.tables, r.binder.usingJoinInfo, r.scoper.org) + expr, err := r.rewriteAliasesInOrderByHavingAndGroupBy(e, sel) if err != nil { return err } - if !starExpanded || colNames == nil { - selExprs = append(selExprs, selectExpr) - continue + err = iter.replace(expr) + if err != nil { + return err } - selExprs = append(selExprs, colNames...) - changed = true - } - if changed { - cursor.ReplaceAndRevisit(selExprs) } + return nil } @@ -220,88 +287,121 @@ func (r *earlyRewriter) expandStar(cursor *sqlparser.Cursor, node sqlparser.Sele // in SELECT points to that expression, not any table column. // - However, if the aliased expression is an aggregation and the column identifier in // the HAVING/ORDER BY clause is inside an aggregation function, the rule does not apply. -func rewriteHavingAndOrderBy(node, parent sqlparser.SQLNode) { - sel, isSel := parent.(*sqlparser.Select) - if !isSel { - return +func (r *earlyRewriter) rewriteAliasesInOrderByHavingAndGroupBy(node sqlparser.Expr, sel *sqlparser.Select) (expr sqlparser.Expr, err error) { + type ExprContainer struct { + expr sqlparser.Expr + ambiguous bool } - sqlparser.SafeRewrite(node, avoidSubqueries, - func(cursor *sqlparser.Cursor) bool { - col, ok := cursor.Node().(*sqlparser.ColName) - if !ok || !col.Qualifier.IsEmpty() { - // we are only interested in columns not qualified by table names - return true - } - - _, parentIsAggr := cursor.Parent().(sqlparser.AggrFunc) + aliases := map[string]ExprContainer{} + for _, e := range sel.SelectExprs { + ae, ok := e.(*sqlparser.AliasedExpr) + if !ok { + continue + } - // Iterate through SELECT expressions. - for _, e := range sel.SelectExprs { - ae, ok := e.(*sqlparser.AliasedExpr) - if !ok || !ae.As.Equal(col.Name) { - // we are searching for aliased expressions that match the column we have found - continue - } + var alias string - expr := ae.Expr - if parentIsAggr { - if _, aliasPointsToAggr := expr.(sqlparser.AggrFunc); aliasPointsToAggr { - return false - } - } + item := ExprContainer{expr: ae.Expr} + if !ae.As.IsEmpty() { + alias = ae.As.Lowered() + } else if col, ok := ae.Expr.(*sqlparser.ColName); ok { + alias = col.Name.Lowered() + } - if isSafeToRewrite(expr) { - cursor.Replace(expr) - } - } - return true - }) -} + if old, alreadyExists := aliases[alias]; alreadyExists && !sqlparser.Equals.Expr(old.expr, item.expr) { + item.ambiguous = true + } -func avoidSubqueries(node, _ sqlparser.SQLNode) bool { - _, isSubQ := node.(*sqlparser.Subquery) - return !isSubQ -} + aliases[alias] = item + } -func isSafeToRewrite(e sqlparser.Expr) bool { - safeToRewrite := true - _ = sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + insideAggr := false + downF := func(node, _ sqlparser.SQLNode) bool { switch node.(type) { - case *sqlparser.ColName: - safeToRewrite = false - return false, nil + case *sqlparser.Subquery: + return false case sqlparser.AggrFunc: - return false, nil + insideAggr = true } - return true, nil - }, e) - return safeToRewrite + + return true + } + + output := sqlparser.CopyOnRewrite(node, downF, func(cursor *sqlparser.CopyOnWriteCursor) { + switch col := cursor.Node().(type) { + case sqlparser.AggrFunc: + insideAggr = false + case *sqlparser.ColName: + if !col.Qualifier.IsEmpty() { + // we are only interested in columns not qualified by table names + break + } + + item, found := aliases[col.Name.Lowered()] + if !found { + break + } + + if item.ambiguous { + err = &AmbiguousColumnError{Column: sqlparser.String(col)} + cursor.StopTreeWalk() + return + } + + if insideAggr && sqlparser.ContainsAggregation(item.expr) { + // I'm not sure about this, but my experiments point to this being the behaviour mysql has + // mysql> select min(name) as name from user order by min(name); + // 1 row in set (0.00 sec) + // + // mysql> select id % 2, min(name) as name from user group by id % 2 order by min(name); + // 2 rows in set (0.00 sec) + // + // mysql> select id % 2, 'foobar' as name from user group by id % 2 order by min(name); + // 2 rows in set (0.00 sec) + // + // mysql> select id % 2 from user group by id % 2 order by min(min(name)); + // ERROR 1111 (HY000): Invalid use of group function + // + // mysql> select id % 2, min(name) as k from user group by id % 2 order by min(k); + // ERROR 1111 (HY000): Invalid use of group function + // + // mysql> select id % 2, -id as name from user group by id % 2, -id order by min(name); + // 6 rows in set (0.01 sec) + break + } + + cursor.Replace(sqlparser.CloneExpr(item.expr)) + } + }, nil) + + expr = output.(sqlparser.Expr) + return } func (r *earlyRewriter) rewriteOrderByExpr(node *sqlparser.Literal) (sqlparser.Expr, error) { - currScope, found := r.scoper.specialExprScopes[node] + scope, found := r.scoper.specialExprScopes[node] if !found { - return nil, nil + return node, nil } num, err := strconv.Atoi(node.Val) if err != nil { return nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "error parsing column number: %s", node.Val) } - stmt, isSel := currScope.stmt.(*sqlparser.Select) + + stmt, isSel := scope.stmt.(*sqlparser.Select) if !isSel { - return nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "error invalid statement type, expect Select, got: %T", currScope.stmt) + return nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "error invalid statement type, expect Select, got: %T", scope.stmt) } if num < 1 || num > len(stmt.SelectExprs) { return nil, vterrors.NewErrorf(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.BadFieldError, "Unknown column '%d' in '%s'", num, r.clause) } + // We loop like this instead of directly accessing the offset, to make sure there are no unexpanded `*` before for i := 0; i < num; i++ { - expr := stmt.SelectExprs[i] - _, ok := expr.(*sqlparser.AliasedExpr) - if !ok { - return nil, vterrors.Errorf(vtrpcpb.Code_UNIMPLEMENTED, "cannot use column offsets in %s when using `%s`", r.clause, sqlparser.String(expr)) + if _, ok := stmt.SelectExprs[i].(*sqlparser.AliasedExpr); !ok { + return nil, vterrors.Errorf(vtrpcpb.Code_UNIMPLEMENTED, "cannot use column offsets in %s when using `%s`", r.clause, sqlparser.String(stmt.SelectExprs[i])) } } @@ -310,12 +410,73 @@ func (r *earlyRewriter) rewriteOrderByExpr(node *sqlparser.Literal) (sqlparser.E return nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "don't know how to handle %s", sqlparser.String(node)) } - if !aliasedExpr.As.IsEmpty() { - return sqlparser.NewColName(aliasedExpr.As.String()), nil + if scope.isUnion { + col, isCol := aliasedExpr.Expr.(*sqlparser.ColName) + + if aliasedExpr.As.IsEmpty() && isCol { + return sqlparser.NewColName(col.Name.String()), nil + } + + return sqlparser.NewColName(aliasedExpr.ColumnName()), nil } - expr := realCloneOfColNames(aliasedExpr.Expr, currScope.isUnion) - return expr, nil + return realCloneOfColNames(aliasedExpr.Expr, false), nil +} + +// rewriteOrExpr rewrites OR expressions when the right side is FALSE. +func rewriteOrExpr(cursor *sqlparser.Cursor, node *sqlparser.OrExpr) { + newNode := rewriteOrFalse(*node) + if newNode != nil { + cursor.ReplaceAndRevisit(newNode) + } +} + +// handleComparisonExpr processes Comparison expressions, specifically for tuples with equal length and EqualOp operator. +func handleComparisonExpr(cursor *sqlparser.Cursor, node *sqlparser.ComparisonExpr) error { + lft, lftOK := node.Left.(sqlparser.ValTuple) + rgt, rgtOK := node.Right.(sqlparser.ValTuple) + if !lftOK || !rgtOK || len(lft) != len(rgt) || node.Operator != sqlparser.EqualOp { + return nil + } + var predicates []sqlparser.Expr + for i, l := range lft { + r := rgt[i] + predicates = append(predicates, &sqlparser.ComparisonExpr{ + Operator: sqlparser.EqualOp, + Left: l, + Right: r, + Escape: node.Escape, + }) + } + cursor.Replace(sqlparser.AndExpressions(predicates...)) + return nil +} + +func (r *earlyRewriter) expandStar(cursor *sqlparser.Cursor, node sqlparser.SelectExprs) error { + currentScope := r.scoper.currentScope() + var selExprs sqlparser.SelectExprs + changed := false + for _, selectExpr := range node { + starExpr, isStarExpr := selectExpr.(*sqlparser.StarExpr) + if !isStarExpr { + selExprs = append(selExprs, selectExpr) + continue + } + starExpanded, colNames, err := r.expandTableColumns(starExpr, currentScope.tables, r.binder.usingJoinInfo, r.scoper.org) + if err != nil { + return err + } + if !starExpanded || colNames == nil { + selExprs = append(selExprs, selectExpr) + continue + } + selExprs = append(selExprs, colNames...) + changed = true + } + if changed { + cursor.ReplaceAndRevisit(selExprs) + } + return nil } // realCloneOfColNames clones all the expressions including ColName. @@ -610,8 +771,7 @@ type expanderState struct { // addColumn adds columns to the expander state. If we have vschema info about the query, // we also store which columns were expanded func (e *expanderState) addColumn(col ColumnInfo, tbl TableInfo, tblName sqlparser.TableName) { - tableAliased := !tbl.GetExpr().As.IsEmpty() - withQualifier := e.needsQualifier || tableAliased + withQualifier := e.needsQualifier var colName *sqlparser.ColName var alias sqlparser.IdentifierCI if withQualifier { diff --git a/go/vt/vtgate/semantics/early_rewriter_test.go b/go/vt/vtgate/semantics/early_rewriter_test.go index bd919fe9201..b2cf9cddd66 100644 --- a/go/vt/vtgate/semantics/early_rewriter_test.go +++ b/go/vt/vtgate/semantics/early_rewriter_test.go @@ -166,20 +166,20 @@ func TestExpandStar(t *testing.T) { expanded: "main.t1.a, main.t1.b, main.t1.c, main.t5.a", }, { sql: "select * from t1 join t5 using (b) having b = 12", - expSQL: "select t1.b as b, t1.a as a, t1.c as c, t5.a as a from t1 join t5 on t1.b = t5.b having b = 12", + expSQL: "select t1.b as b, t1.a as a, t1.c as c, t5.a as a from t1 join t5 on t1.b = t5.b having t1.b = 12", }, { sql: "select 1 from t1 join t5 using (b) having b = 12", expSQL: "select 1 from t1 join t5 on t1.b = t5.b having t1.b = 12", }, { sql: "select * from (select 12) as t", - expSQL: "select t.`12` from (select 12 from dual) as t", + expSQL: "select `12` from (select 12 from dual) as t", }, { sql: "SELECT * FROM (SELECT *, 12 AS foo FROM t3) as results", expSQL: "select * from (select *, 12 as foo from t3) as results", }, { // if we are only star-expanding authoritative tables, we don't need to stop the expansion sql: "SELECT * FROM (SELECT t2.*, 12 AS foo FROM t3, t2) as results", - expSQL: "select results.c1, results.c2, results.foo from (select t2.c1 as c1, t2.c2 as c2, 12 as foo from t3, t2) as results", + expSQL: "select c1, c2, foo from (select t2.c1 as c1, t2.c2 as c2, 12 as foo from t3, t2) as results", }} for _, tcase := range tcases { t.Run(tcase.sql, func(t *testing.T) { @@ -311,22 +311,31 @@ func TestOrderByGroupByLiteral(t *testing.T) { expErr string }{{ sql: "select 1 as id from t1 order by 1", - expSQL: "select 1 as id from t1 order by id asc", + expSQL: "select 1 as id from t1 order by '' asc", }, { sql: "select t1.col from t1 order by 1", expSQL: "select t1.col from t1 order by t1.col asc", + }, { + sql: "select t1.col from t1 order by 1.0", + expSQL: "select t1.col from t1 order by 1.0 asc", + }, { + sql: "select t1.col from t1 order by 'fubick'", + expSQL: "select t1.col from t1 order by 'fubick' asc", + }, { + sql: "select t1.col as foo from t1 order by 1", + expSQL: "select t1.col as foo from t1 order by t1.col asc", }, { sql: "select t1.col from t1 group by 1", expSQL: "select t1.col from t1 group by t1.col", }, { sql: "select t1.col as xyz from t1 group by 1", - expSQL: "select t1.col as xyz from t1 group by xyz", + expSQL: "select t1.col as xyz from t1 group by t1.col", }, { sql: "select t1.col as xyz, count(*) from t1 group by 1 order by 2", - expSQL: "select t1.col as xyz, count(*) from t1 group by xyz order by count(*) asc", + expSQL: "select t1.col as xyz, count(*) from t1 group by t1.col order by count(*) asc", }, { sql: "select id from t1 group by 2", - expErr: "Unknown column '2' in 'group statement'", + expErr: "Unknown column '2' in 'group clause'", }, { sql: "select id from t1 order by 2", expErr: "Unknown column '2' in 'order clause'", @@ -335,16 +344,22 @@ func TestOrderByGroupByLiteral(t *testing.T) { expErr: "cannot use column offsets in order clause when using `*`", }, { sql: "select *, id from t1 group by 2", - expErr: "cannot use column offsets in group statement when using `*`", + expErr: "cannot use column offsets in group clause when using `*`", }, { sql: "select id from t1 order by 1 collate utf8_general_ci", expSQL: "select id from t1 order by id collate utf8_general_ci asc", + }, { + sql: "select a.id from `user` union select 1 from dual order by 1", + expSQL: "select a.id from `user` union select 1 from dual order by id asc", + }, { + sql: "select a.id, b.id from user as a, user_extra as b union select 1, 2 order by 1", + expErr: "Column 'id' in field list is ambiguous", }} for _, tcase := range tcases { t.Run(tcase.sql, func(t *testing.T) { ast, err := sqlparser.Parse(tcase.sql) require.NoError(t, err) - selectStatement := ast.(*sqlparser.Select) + selectStatement := ast.(sqlparser.SelectStatement) _, err = Analyze(selectStatement, cDB, schemaInfo) if tcase.expErr == "" { require.NoError(t, err) @@ -374,12 +389,28 @@ func TestHavingAndOrderByColumnName(t *testing.T) { }, { sql: "select id, sum(foo) as foo from t1 having sum(foo) > 1", expSQL: "select id, sum(foo) as foo from t1 having sum(foo) > 1", + }, { + sql: "select id, lower(min(foo)) as foo from t1 order by min(foo)", + expSQL: "select id, lower(min(foo)) as foo from t1 order by min(foo) asc", + }, { + // invalid according to group by rules, but still accepted by mysql + sql: "select id, t1.bar as foo from t1 group by id order by min(foo)", + expSQL: "select id, t1.bar as foo from t1 group by id order by min(t1.bar) asc", + }, { + sql: "select foo + 2 as foo from t1 having foo = 42", + expSQL: "select foo + 2 as foo from t1 having foo + 2 = 42", + }, { + sql: "select id, b as id, count(*) from t1 order by id", + expErr: "Column 'id' in field list is ambiguous", + }, { + sql: "select id, id, count(*) from t1 order by id", + expSQL: "select id, id, count(*) from t1 order by id asc", }} for _, tcase := range tcases { t.Run(tcase.sql, func(t *testing.T) { ast, err := sqlparser.Parse(tcase.sql) require.NoError(t, err) - selectStatement := ast.(*sqlparser.Select) + selectStatement := ast.(sqlparser.SelectStatement) _, err = Analyze(selectStatement, cDB, schemaInfo) if tcase.expErr == "" { require.NoError(t, err) @@ -542,3 +573,33 @@ func TestConstantFolding(t *testing.T) { }) } } + +// TestDeleteTargetTableRewrite checks that delete target rewrite is done correctly. +func TestDeleteTargetTableRewrite(t *testing.T) { + cDB := "db" + tcases := []struct { + sql string + target string + }{{ + sql: "delete from t", + target: "t", + }, { + sql: "delete from t t1", + target: "t1", + }, { + sql: "delete t2 from t t1, t t2", + target: "t2", + }, { + sql: "delete t2,t1 from t t1, t t2", + target: "t2, t1", + }} + for _, tcase := range tcases { + t.Run(tcase.sql, func(t *testing.T) { + ast, err := sqlparser.Parse(tcase.sql) + require.NoError(t, err) + _, err = Analyze(ast, cDB, fakeSchemaInfo()) + require.NoError(t, err) + require.Equal(t, tcase.target, sqlparser.String(ast.(*sqlparser.Delete).Targets)) + }) + } +} From ac0893a44ae4f23bee3b9e199d0613f3da156636 Mon Sep 17 00:00:00 2001 From: Florent Poinsard Date: Thu, 25 Jan 2024 08:40:26 -0600 Subject: [PATCH 2/7] remove unwanted test case, will fix it up on main Signed-off-by: Florent Poinsard --- go/vt/vtgate/planbuilder/testdata/select_cases.json | 5 ----- 1 file changed, 5 deletions(-) diff --git a/go/vt/vtgate/planbuilder/testdata/select_cases.json b/go/vt/vtgate/planbuilder/testdata/select_cases.json index 2deab3e0aaf..8d7c902ded3 100644 --- a/go/vt/vtgate/planbuilder/testdata/select_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/select_cases.json @@ -2020,11 +2020,6 @@ ] } }, - { - "comment": "select (select col from user limit 1) as a from user join user_extra order by a", - "query": "select (select col from user limit 1) as a from user join user_extra order by a", - "plan": "VT13002: unexpected AST struct for query: (select col from `user` limit 1)" - }, { "comment": "select t.a from (select (select col from user limit 1) as a from user join user_extra) t", "query": "select t.a from (select (select col from user limit 1) as a from user join user_extra) t", From 7ef222aa605f45c362fe06d79f48a32c3cfaa2d3 Mon Sep 17 00:00:00 2001 From: Florent Poinsard Date: Fri, 26 Jan 2024 08:27:05 -0600 Subject: [PATCH 3/7] fix plan tests Signed-off-by: Florent Poinsard --- .../planbuilder/operators/queryprojection_test.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/go/vt/vtgate/planbuilder/operators/queryprojection_test.go b/go/vt/vtgate/planbuilder/operators/queryprojection_test.go index 7c92b716d7c..2d32bd3385c 100644 --- a/go/vt/vtgate/planbuilder/operators/queryprojection_test.go +++ b/go/vt/vtgate/planbuilder/operators/queryprojection_test.go @@ -47,7 +47,7 @@ func TestQP(t *testing.T) { { sql: "select 1, count(1) from user order by 1", expOrder: []ops.OrderBy{ - {Inner: &sqlparser.Order{Expr: sqlparser.NewIntLiteral("1")}, SimplifiedExpr: sqlparser.NewIntLiteral("1")}, + {Inner: &sqlparser.Order{Expr: sqlparser.NewStrLiteral("")}, SimplifiedExpr: sqlparser.NewStrLiteral("")}, }, }, { @@ -61,7 +61,14 @@ func TestQP(t *testing.T) { sql: "SELECT CONCAT(last_name,', ',first_name) AS full_name FROM mytable ORDER BY full_name", // alias in order not supported expOrder: []ops.OrderBy{ { - Inner: &sqlparser.Order{Expr: sqlparser.NewColName("full_name")}, + Inner: &sqlparser.Order{Expr: &sqlparser.FuncExpr{ + Name: sqlparser.NewIdentifierCI("CONCAT"), + Exprs: sqlparser.SelectExprs{ + &sqlparser.AliasedExpr{Expr: sqlparser.NewColName("last_name")}, + &sqlparser.AliasedExpr{Expr: sqlparser.NewStrLiteral(", ")}, + &sqlparser.AliasedExpr{Expr: sqlparser.NewColName("first_name")}, + }, + }}, SimplifiedExpr: &sqlparser.FuncExpr{ Name: sqlparser.NewIdentifierCI("CONCAT"), Exprs: sqlparser.SelectExprs{ From de7fdb9b4f022a09996d760eb789ee2f6ffa23ec Mon Sep 17 00:00:00 2001 From: Florent Poinsard Date: Fri, 26 Jan 2024 12:09:05 -0600 Subject: [PATCH 4/7] fix early_rewritter_test.go Signed-off-by: Florent Poinsard --- go/vt/vtgate/semantics/early_rewriter_test.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/go/vt/vtgate/semantics/early_rewriter_test.go b/go/vt/vtgate/semantics/early_rewriter_test.go index b2cf9cddd66..561d6a149da 100644 --- a/go/vt/vtgate/semantics/early_rewriter_test.go +++ b/go/vt/vtgate/semantics/early_rewriter_test.go @@ -581,12 +581,6 @@ func TestDeleteTargetTableRewrite(t *testing.T) { sql string target string }{{ - sql: "delete from t", - target: "t", - }, { - sql: "delete from t t1", - target: "t1", - }, { sql: "delete t2 from t t1, t t2", target: "t2", }, { From 19edf6f057d00e41b919eba25fe7636fc762692a Mon Sep 17 00:00:00 2001 From: Florent Poinsard Date: Fri, 26 Jan 2024 12:31:11 -0600 Subject: [PATCH 5/7] fix early_rewritter_test.go Signed-off-by: Florent Poinsard --- go/vt/vtgate/semantics/early_rewriter_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/go/vt/vtgate/semantics/early_rewriter_test.go b/go/vt/vtgate/semantics/early_rewriter_test.go index 561d6a149da..771d5081c02 100644 --- a/go/vt/vtgate/semantics/early_rewriter_test.go +++ b/go/vt/vtgate/semantics/early_rewriter_test.go @@ -335,7 +335,7 @@ func TestOrderByGroupByLiteral(t *testing.T) { expSQL: "select t1.col as xyz, count(*) from t1 group by t1.col order by count(*) asc", }, { sql: "select id from t1 group by 2", - expErr: "Unknown column '2' in 'group clause'", + expErr: "Unknown column '2' in 'group statement'", }, { sql: "select id from t1 order by 2", expErr: "Unknown column '2' in 'order clause'", @@ -344,7 +344,7 @@ func TestOrderByGroupByLiteral(t *testing.T) { expErr: "cannot use column offsets in order clause when using `*`", }, { sql: "select *, id from t1 group by 2", - expErr: "cannot use column offsets in group clause when using `*`", + expErr: "cannot use column offsets in group statement when using `*`", }, { sql: "select id from t1 order by 1 collate utf8_general_ci", expSQL: "select id from t1 order by id collate utf8_general_ci asc", From 780b76d27963dc5ea9a4f001c081548da776fa13 Mon Sep 17 00:00:00 2001 From: Florent Poinsard Date: Fri, 26 Jan 2024 13:48:30 -0600 Subject: [PATCH 6/7] fix executor test Signed-off-by: Florent Poinsard --- go/vt/vtgate/executor_select_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/go/vt/vtgate/executor_select_test.go b/go/vt/vtgate/executor_select_test.go index 43df08b0f9c..bfe5a8dda5b 100644 --- a/go/vt/vtgate/executor_select_test.go +++ b/go/vt/vtgate/executor_select_test.go @@ -4121,7 +4121,7 @@ func TestSelectView(t *testing.T) { _, err = executor.Execute(context.Background(), nil, "TestSelectView", session, "select * from user_details_view", nil) require.NoError(t, err) wantQueries := []*querypb.BoundQuery{{ - Sql: "select user_details_view.id, user_details_view.col from (select `user`.id, user_extra.col from `user`, user_extra where `user`.id = user_extra.user_id) as user_details_view", + Sql: "select id, col from (select `user`.id, user_extra.col from `user`, user_extra where `user`.id = user_extra.user_id) as user_details_view", BindVariables: map[string]*querypb.BindVariable{}, }} utils.MustMatch(t, wantQueries, sbc.Queries) @@ -4130,7 +4130,7 @@ func TestSelectView(t *testing.T) { _, err = executor.Execute(context.Background(), nil, "TestSelectView", session, "select * from user_details_view where id = 2", nil) require.NoError(t, err) wantQueries = []*querypb.BoundQuery{{ - Sql: "select user_details_view.id, user_details_view.col from (select `user`.id, user_extra.col from `user`, user_extra where `user`.id = :id /* INT64 */ and `user`.id = user_extra.user_id) as user_details_view", + Sql: "select id, col from (select `user`.id, user_extra.col from `user`, user_extra where `user`.id = :id /* INT64 */ and `user`.id = user_extra.user_id) as user_details_view", BindVariables: map[string]*querypb.BindVariable{ "id": sqltypes.Int64BindVariable(2), }, @@ -4143,7 +4143,7 @@ func TestSelectView(t *testing.T) { bvtg1, _ := sqltypes.BuildBindVariable([]int64{1, 2, 3, 4, 5}) bvals, _ := sqltypes.BuildBindVariable([]int64{1, 2}) wantQueries = []*querypb.BoundQuery{{ - Sql: "select user_details_view.id, user_details_view.col from (select `user`.id, user_extra.col from `user`, user_extra where `user`.id in ::__vals and `user`.id = user_extra.user_id) as user_details_view", + Sql: "select id, col from (select `user`.id, user_extra.col from `user`, user_extra where `user`.id in ::__vals and `user`.id = user_extra.user_id) as user_details_view", BindVariables: map[string]*querypb.BindVariable{ "vtg1": bvtg1, "__vals": bvals, From 12a9708889a0bed93e4729b52194c1ba0cdf5399 Mon Sep 17 00:00:00 2001 From: Florent Poinsard Date: Fri, 26 Jan 2024 15:44:22 -0600 Subject: [PATCH 7/7] fix executor test Signed-off-by: Florent Poinsard --- go/vt/vtgate/executor_select_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go/vt/vtgate/executor_select_test.go b/go/vt/vtgate/executor_select_test.go index bfe5a8dda5b..a1512b55b92 100644 --- a/go/vt/vtgate/executor_select_test.go +++ b/go/vt/vtgate/executor_select_test.go @@ -1026,7 +1026,7 @@ func TestLastInsertIDInVirtualTable(t *testing.T) { _, err := executorExec(ctx, executor, session, "select * from (select last_insert_id()) as t", nil) require.NoError(t, err) wantQueries := []*querypb.BoundQuery{{ - Sql: "select t.`last_insert_id()` from (select :__lastInsertId as `last_insert_id()` from dual) as t", + Sql: "select `last_insert_id()` from (select :__lastInsertId as `last_insert_id()` from dual) as t", BindVariables: map[string]*querypb.BindVariable{"__lastInsertId": sqltypes.Uint64BindVariable(0)}, }}