Repository: vitessio/vitess
Pull request #8774 (2021-09-07 10:25:28)

Support for pinned tables in Gen4
<!-- if this PR is Work in Progress please create it as a Draft Pull Request -->

## Description
This PR adds support for pinned tables in Gen4

## Related Issue(s)
#7280 

## Checklist
- [ ] Should this PR be backported?
- [x] Tests were added or are not required
- [x] Documentation was added or is not required

## Deployment Notes
<!-- Notes regarding deployment of the contained body of work. These should note any db migrations, etc. -->


Patch:
diff --git a/go/vt/sqlparser/ast_funcs.go b/go/vt/sqlparser/ast_funcs.go
index 39e01dec1d..f6ff720cab 100644
--- a/go/vt/sqlparser/ast_funcs.go
+++ b/go/vt/sqlparser/ast_funcs.go
@@ -1441,16 +1441,3 @@ func IsAggregation(node SQLNode) bool {
 	}
 	return false
 }
-
-// GetFirstSelect gets the first select statement
-func GetFirstSelect(selStmt SelectStatement) *Select {
-	switch node := selStmt.(type) {
-	case *Select:
-		return node
-	case *Union:
-		return GetFirstSelect(node.FirstStatement)
-	case *ParenSelect:
-		return GetFirstSelect(node.Select)
-	}
-	panic("[BUG]: unknown type for SelectStatement")
-}
diff --git a/go/vt/vtgate/planbuilder/abstract/concatenate.go b/go/vt/vtgate/planbuilder/abstract/concatenate.go
deleted file mode 100644
index 149c12f81d..0000000000
--- a/go/vt/vtgate/planbuilder/abstract/concatenate.go
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
-Copyright 2021 The Vitess Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package abstract
-
-import (
-	"vitess.io/vitess/go/vt/sqlparser"
-	"vitess.io/vitess/go/vt/vtgate/semantics"
-)
-
-// Concatenate represents a UNION ALL.
-type Concatenate struct {
-	SelectStmts []*sqlparser.Select
-	Sources     []Operator
-}
-
-var _ Operator = (*Concatenate)(nil)
-
-// createConcatenateIfRequired creates a Concatenate operator on top of the sources if it is required
-func createConcatenateIfRequired(sources []Operator, selStmts []*sqlparser.Select) Operator {
-	if len(sources) == 1 {
-		return sources[0]
-	}
-	return &Concatenate{Sources: sources, SelectStmts: selStmts}
-}
-
-// TableID implements the Operator interface
-func (c *Concatenate) TableID() semantics.TableSet {
-	var tableSet semantics.TableSet
-	for _, source := range c.Sources {
-		tableSet |= source.TableID()
-	}
-	return tableSet
-}
-
-// PushPredicate implements the Operator interface
-func (c *Concatenate) PushPredicate(expr sqlparser.Expr, semTable *semantics.SemTable) error {
-	panic("implement me")
-}
-
-// UnsolvedPredicates implements the Operator interface
-func (c *Concatenate) UnsolvedPredicates(semTable *semantics.SemTable) []sqlparser.Expr {
-	panic("implement me")
-}
diff --git a/go/vt/vtgate/planbuilder/abstract/derived.go b/go/vt/vtgate/planbuilder/abstract/derived.go
index 1ee993754a..46dd2ea457 100644
--- a/go/vt/vtgate/planbuilder/abstract/derived.go
+++ b/go/vt/vtgate/planbuilder/abstract/derived.go
@@ -23,7 +23,7 @@ import (
 
 // Derived represents a derived table in the query
 type Derived struct {
-	Sel   sqlparser.SelectStatement
+	Sel   *sqlparser.Select
 	Inner Operator
 	Alias string
 }
diff --git a/go/vt/vtgate/planbuilder/abstract/distinct.go b/go/vt/vtgate/planbuilder/abstract/distinct.go
deleted file mode 100644
index 190f777916..0000000000
--- a/go/vt/vtgate/planbuilder/abstract/distinct.go
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
-Copyright 2021 The Vitess Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package abstract
-
-import (
-	"vitess.io/vitess/go/vt/sqlparser"
-	"vitess.io/vitess/go/vt/vtgate/semantics"
-)
-
-// Distinct eliminates duplicate rows.
-type Distinct struct {
-	Source Operator
-}
-
-var _ Operator = (*Distinct)(nil)
-
-// TableID implements the Operator interface
-func (d *Distinct) TableID() semantics.TableSet {
-	return d.Source.TableID()
-}
-
-// PushPredicate implements the Operator interface
-func (d *Distinct) PushPredicate(expr sqlparser.Expr, semTable *semantics.SemTable) error {
-	return d.Source.PushPredicate(expr, semTable)
-}
-
-// UnsolvedPredicates implements the Operator interface
-func (d *Distinct) UnsolvedPredicates(semTable *semantics.SemTable) []sqlparser.Expr {
-	return d.Source.UnsolvedPredicates(semTable)
-}
diff --git a/go/vt/vtgate/planbuilder/abstract/fuzz.go b/go/vt/vtgate/planbuilder/abstract/fuzz.go
index 9315a0cfe9..8e49ec3814 100644
--- a/go/vt/vtgate/planbuilder/abstract/fuzz.go
+++ b/go/vt/vtgate/planbuilder/abstract/fuzz.go
@@ -56,7 +56,7 @@ func FuzzAnalyse(data []byte) int {
 		if err != nil {
 			return 0
 		}
-		_, _ = createOperatorFromSelect(stmt, semTable)
+		_, _ = CreateOperatorFromSelect(stmt, semTable)
 
 	default:
 		return 0
diff --git a/go/vt/vtgate/planbuilder/abstract/operator.go b/go/vt/vtgate/planbuilder/abstract/operator.go
index eb75ebca9f..d589660a4c 100644
--- a/go/vt/vtgate/planbuilder/abstract/operator.go
+++ b/go/vt/vtgate/planbuilder/abstract/operator.go
@@ -17,9 +17,7 @@ limitations under the License.
 package abstract
 
 import (
-	vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc"
 	"vitess.io/vitess/go/vt/sqlparser"
-	"vitess.io/vitess/go/vt/vterrors"
 	"vitess.io/vitess/go/vt/vtgate/semantics"
 )
 
@@ -32,8 +30,6 @@ type (
 	//	*  LeftJoin - A left join. These can't be evaluated in any order, so we keep them separate
 	//	*  Join - A join represents inner join.
 	//  *  SubQuery - Represents a query that encapsulates one or more sub-queries (SubQueryInner).
-	//  *  Concatenate - Represents concatenation of the outputs of all the input sources
-	//  *  Distinct - Represents elimination of duplicates from the output of the input source
 	Operator interface {
 		// TableID returns a TableSet of the tables contained within
 		TableID() semantics.TableSet
@@ -63,11 +59,15 @@ func getOperatorFromTableExpr(tableExpr sqlparser.TableExpr, semTable *semantics
 			qg.Tables = append(qg.Tables, qt)
 			return qg, nil
 		case *sqlparser.DerivedTable:
-			inner, err := CreateOperatorFromAST(tbl.Select, semTable)
+			sel, isSel := tbl.Select.(*sqlparser.Select)
+			if !isSel {
+				return nil, semantics.Gen4NotSupportedF("UNION")
+			}
+			inner, err := CreateOperatorFromSelect(sel, semTable)
 			if err != nil {
 				return nil, err
 			}
-			return &Derived{Alias: tableExpr.As.String(), Inner: inner, Sel: tbl.Select}, nil
+			return &Derived{Alias: tableExpr.As.String(), Inner: inner, Sel: sel}, nil
 		default:
 			return nil, semantics.Gen4NotSupportedF("%T", tbl)
 		}
@@ -132,101 +132,14 @@ func crossJoin(exprs sqlparser.TableExprs, semTable *semantics.SemTable) (Operat
 	return output, nil
 }
 
-func getSelect(s sqlparser.SelectStatement) *sqlparser.Select {
-	switch s := s.(type) {
-	case *sqlparser.Select:
-		return s
-	case *sqlparser.ParenSelect:
-		return getSelect(s.Select)
-	default:
-		return nil
-	}
-}
-
-// CreateOperatorFromAST creates an operator tree that represents the input SELECT or UNION query
-func CreateOperatorFromAST(selStmt sqlparser.SelectStatement, semTable *semantics.SemTable) (Operator, error) {
-	switch node := selStmt.(type) {
-	case *sqlparser.Select:
-		return createOperatorFromSelect(node, semTable)
-	case *sqlparser.Union:
-		return createOperatorFromUnion(node, semTable)
-	case *sqlparser.ParenSelect:
-		return CreateOperatorFromAST(node.Select, semTable)
-	}
-	return nil, vterrors.Errorf(vtrpcpb.Code_UNIMPLEMENTED, "%T: operator not yet supported", selStmt)
-}
-
-func createOperatorFromUnion(node *sqlparser.Union, semTable *semantics.SemTable) (Operator, error) {
-	op, err := CreateOperatorFromAST(node.FirstStatement, semTable)
-	if err != nil {
-		return nil, err
-	}
-	sources := []Operator{op}
-	sel := getSelect(node.FirstStatement)
-	selectStmts := []*sqlparser.Select{sel}
-
-	var addToSource func(op Operator, sel *sqlparser.Select)
-
-	switch op := op.(type) {
-	case *Distinct:
-		switch src := op.Source.(type) {
-		case *Concatenate:
-			addToSource = func(op Operator, sel *sqlparser.Select) {
-				src.Sources = append(src.Sources, op)
-				src.SelectStmts = append(src.SelectStmts, sel)
-			}
-		}
-	}
-
-	// we only need a single DISTINCT, so we'll go over the UNION to find the last DISTINCT, and that is the one we will keep.
-	// Example: S1 UNION S2 UNION ALL S3 UNION S4 UNION ALL S5
-	// To plan this query, we can do concatenate on S1, S2, S3, and S4, and then distinct, and lastly we concatenate S5
-
-	distinctAt := lastDistinctAt(node)
-
-	for i, unionSelect := range node.UnionSelects {
-		op, err = CreateOperatorFromAST(unionSelect.Statement, semTable)
-		if err != nil {
-			return nil, err
-		}
-
-		sel = getSelect(unionSelect.Statement)
-		if addToSource != nil && i <= distinctAt {
-			// if we can, let's add it to the input instead of building up a new UNION
-			addToSource(op, sel)
-		} else {
-			sources = append(sources, op)
-			selectStmts = append(selectStmts, sel)
-
-			if i == distinctAt {
-				sources = []Operator{&Distinct{Source: &Concatenate{Sources: sources, SelectStmts: selectStmts}}}
-				selectStmts = []*sqlparser.Select{nil}
-			}
-		}
-	}
-	return createConcatenateIfRequired(sources, selectStmts), nil
-}
-
-// lastDistinctAt finds the last DISTINCT in a list of queries UNIONed together
-func lastDistinctAt(node *sqlparser.Union) int {
-	distinctAt := -1
-	for i := len(node.UnionSelects) - 1; i >= 0; i-- {
-		if node.UnionSelects[i].Distinct {
-			distinctAt = i
-			break
-		}
-	}
-	return distinctAt
-}
-
-// createOperatorFromSelect creates an operator tree that represents the input SELECT query
-func createOperatorFromSelect(sel *sqlparser.Select, semTable *semantics.SemTable) (Operator, error) {
+// CreateOperatorFromSelect creates an operator tree that represents the input SELECT query
+func CreateOperatorFromSelect(sel *sqlparser.Select, semTable *semantics.SemTable) (Operator, error) {
 	var resultantOp *SubQuery
 	if len(semTable.SubqueryMap[sel]) > 0 {
 		resultantOp = &SubQuery{}
 		for _, sq := range semTable.SubqueryMap[sel] {
 			subquerySelectStatement := sq.SubQuery.Select.(*sqlparser.Select)
-			opInner, err := createOperatorFromSelect(subquerySelectStatement, semTable)
+			opInner, err := CreateOperatorFromSelect(subquerySelectStatement, semTable)
 			if err != nil {
 				return nil, err
 			}
diff --git a/go/vt/vtgate/planbuilder/builder.go b/go/vt/vtgate/planbuilder/builder.go
index 41298c5e8f..715fa046c9 100644
--- a/go/vt/vtgate/planbuilder/builder.go
+++ b/go/vt/vtgate/planbuilder/builder.go
@@ -124,19 +124,19 @@ func BuildFromStmt(query string, stmt sqlparser.Statement, reservedVars *sqlpars
 	return plan, nil
 }
 
-func getConfiguredPlanner(vschema ContextVSchema, v3planner selectPlanner) (selectPlanner, error) {
+func getConfiguredPlanner(vschema ContextVSchema) (selectPlanner, error) {
 	switch vschema.Planner() {
 	case Gen4, Gen4Left2Right, Gen4GreedyOnly:
 		return gen4Planner, nil
 	case Gen4WithFallback:
 		fp := &fallbackPlanner{
 			primary:  gen4Planner,
-			fallback: v3planner,
+			fallback: buildSelectPlan,
 		}
 		return fp.plan, nil
 	default:
 		// default is v3 plan
-		return v3planner, nil
+		return buildSelectPlan, nil
 	}
 }
 
@@ -152,7 +152,7 @@ type selectPlanner func(query string) func(sqlparser.Statement, *sqlparser.Reser
 func createInstructionFor(query string, stmt sqlparser.Statement, reservedVars *sqlparser.ReservedVars, vschema ContextVSchema, enableOnlineDDL, enableDirectDDL bool) (engine.Primitive, error) {
 	switch stmt := stmt.(type) {
 	case *sqlparser.Select:
-		configuredPlanner, err := getConfiguredPlanner(vschema, buildSelectPlan)
+		configuredPlanner, err := getConfiguredPlanner(vschema)
 		if err != nil {
 			return nil, err
 		}
@@ -164,11 +164,7 @@ func createInstructionFor(query string, stmt sqlparser.Statement, reservedVars *
 	case *sqlparser.Delete:
 		return buildRoutePlan(stmt, reservedVars, vschema, buildDeletePlan)
 	case *sqlparser.Union:
-		configuredPlanner, err := getConfiguredPlanner(vschema, buildUnionPlan)
-		if err != nil {
-			return nil, err
-		}
-		return buildRoutePlan(stmt, reservedVars, vschema, configuredPlanner(query))
+		return buildRoutePlan(stmt, reservedVars, vschema, buildUnionPlan)
 	case sqlparser.DDLStatement:
 		return buildGeneralDDLPlan(query, stmt, reservedVars, vschema, enableOnlineDDL, enableDirectDDL)
 	case *sqlparser.AlterMigration:
diff --git a/go/vt/vtgate/planbuilder/concantenatetree.go b/go/vt/vtgate/planbuilder/concantenatetree.go
deleted file mode 100644
index 160ad1a00f..0000000000
--- a/go/vt/vtgate/planbuilder/concantenatetree.go
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
-Copyright 2021 The Vitess Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package planbuilder
-
-import (
-	"vitess.io/vitess/go/vt/proto/vtrpc"
-	"vitess.io/vitess/go/vt/sqlparser"
-	"vitess.io/vitess/go/vt/vterrors"
-	"vitess.io/vitess/go/vt/vtgate/semantics"
-)
-
-type (
-	concatenateTree struct {
-		selectStmts []*sqlparser.Select
-		sources     []queryTree
-	}
-)
-
-var _ queryTree = (*concatenateTree)(nil)
-
-func (c *concatenateTree) tableID() semantics.TableSet {
-	var tableSet semantics.TableSet
-	for _, source := range c.sources {
-		tableSet |= source.tableID()
-	}
-	return tableSet
-}
-
-func (c *concatenateTree) clone() queryTree {
-	var sourcesCopy []queryTree
-	for _, source := range c.sources {
-		sourcesCopy = append(sourcesCopy, source.clone())
-	}
-	return &concatenateTree{sources: sourcesCopy, selectStmts: c.selectStmts}
-}
-
-func (c *concatenateTree) cost() int {
-	var totalCost int
-	for _, source := range c.sources {
-		totalCost += source.cost()
-	}
-	return totalCost
-}
-
-func (c *concatenateTree) pushOutputColumns(columns []*sqlparser.ColName, semTable *semantics.SemTable) ([]int, error) {
-	return nil, vterrors.New(vtrpc.Code_INTERNAL, "pushOutputColumns should not be called on this struct")
-}
diff --git a/go/vt/vtgate/planbuilder/concatenateGen4.go b/go/vt/vtgate/planbuilder/concatenateGen4.go
deleted file mode 100644
index 70741d96ad..0000000000
--- a/go/vt/vtgate/planbuilder/concatenateGen4.go
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
-Copyright 2021 The Vitess Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package planbuilder
-
-import (
-	vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc"
-	"vitess.io/vitess/go/vt/sqlparser"
-	"vitess.io/vitess/go/vt/vterrors"
-	"vitess.io/vitess/go/vt/vtgate/engine"
-	"vitess.io/vitess/go/vt/vtgate/semantics"
-)
-
-type concatenateGen4 struct {
-	sources []logicalPlan
-}
-
-var _ logicalPlan = (*concatenateGen4)(nil)
-
-// Order implements the logicalPlan interface
-func (c *concatenateGen4) Order() int {
-	panic("implement me")
-}
-
-// ResultColumns implements the logicalPlan interface
-func (c *concatenateGen4) ResultColumns() []*resultColumn {
-	panic("implement me")
-}
-
-// Reorder implements the logicalPlan interface
-func (c *concatenateGen4) Reorder(order int) {
-	panic("implement me")
-}
-
-// Wireup implements the logicalPlan interface
-func (c *concatenateGen4) Wireup(plan logicalPlan, jt *jointab) error {
-	panic("implement me")
-}
-
-// WireupGen4 implements the logicalPlan interface
-func (c *concatenateGen4) WireupGen4(semTable *semantics.SemTable) error {
-	for _, source := range c.sources {
-		err := source.WireupGen4(semTable)
-		if err != nil {
-			return err
-		}
-	}
-	return nil
-}
-
-// SupplyVar implements the logicalPlan interface
-func (c *concatenateGen4) SupplyVar(from, to int, col *sqlparser.ColName, varname string) {
-	panic("implement me")
-}
-
-// SupplyCol implements the logicalPlan interface
-func (c *concatenateGen4) SupplyCol(col *sqlparser.ColName) (rc *resultColumn, colNumber int) {
-	panic("implement me")
-}
-
-// SupplyWeightString implements the logicalPlan interface
-func (c *concatenateGen4) SupplyWeightString(colNumber int) (weightcolNumber int, err error) {
-	panic("implement me")
-}
-
-// Primitive implements the logicalPlan interface
-func (c *concatenateGen4) Primitive() engine.Primitive {
-	var sources []engine.Primitive
-	for _, source := range c.sources {
-		sources = append(sources, source.Primitive())
-	}
-	return &engine.Concatenate{
-		Sources: sources,
-	}
-}
-
-// Rewrite implements the logicalPlan interface
-func (c *concatenateGen4) Rewrite(inputs ...logicalPlan) error {
-	if len(inputs) != len(c.sources) {
-		return vterrors.Errorf(vtrpcpb.Code_INTERNAL, "concatenateGen4: wrong number of inputs")
-	}
-	c.sources = inputs
-	return nil
-}
-
-// ContainsTables implements the logicalPlan interface
-func (c *concatenateGen4) ContainsTables() semantics.TableSet {
-	var tableSet semantics.TableSet
-	for _, source := range c.sources {
-		tableSet |= source.ContainsTables()
-	}
-	return tableSet
-}
-
-// Inputs implements the logicalPlan interface
-func (c *concatenateGen4) Inputs() []logicalPlan {
-	return c.sources
-}
diff --git a/go/vt/vtgate/planbuilder/derivedtree.go b/go/vt/vtgate/planbuilder/derivedtree.go
index 32ae9ab085..6f00866f82 100644
--- a/go/vt/vtgate/planbuilder/derivedtree.go
+++ b/go/vt/vtgate/planbuilder/derivedtree.go
@@ -24,7 +24,7 @@ import (
 )
 
 type derivedTree struct {
-	query sqlparser.SelectStatement
+	query *sqlparser.Select
 	inner queryTree
 	alias string
 }
@@ -57,7 +57,7 @@ func (d *derivedTree) pushOutputColumns(names []*sqlparser.ColName, _ *semantics
 }
 
 func (d *derivedTree) findOutputColumn(name *sqlparser.ColName) (int, error) {
-	for j, exp := range sqlparser.GetFirstSelect(d.query).SelectExprs {
+	for j, exp := range d.query.SelectExprs {
 		ae, ok := exp.(*sqlparser.AliasedExpr)
 		if !ok {
 			return 0, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "expected AliasedExpr")
diff --git a/go/vt/vtgate/planbuilder/distincttree.go b/go/vt/vtgate/planbuilder/distincttree.go
deleted file mode 100644
index e989904efe..0000000000
--- a/go/vt/vtgate/planbuilder/distincttree.go
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
-Copyright 2021 The Vitess Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package planbuilder
-
-import (
-	"vitess.io/vitess/go/vt/sqlparser"
-	"vitess.io/vitess/go/vt/vtgate/semantics"
-)
-
-type (
-	distinctTree struct {
-		source queryTree
-	}
-)
-
-var _ queryTree = (*distinctTree)(nil)
-
-func (d *distinctTree) tableID() semantics.TableSet {
-	return d.source.tableID()
-}
-
-func (d *distinctTree) clone() queryTree {
-	return &distinctTree{
-		source: d.source.clone(),
-	}
-}
-
-func (d *distinctTree) cost() int {
-	return d.source.cost()
-}
-
-func (d *distinctTree) pushOutputColumns(columns []*sqlparser.ColName, semTable *semantics.SemTable) ([]int, error) {
-	return d.source.pushOutputColumns(columns, semTable)
-}
diff --git a/go/vt/vtgate/planbuilder/from.go b/go/vt/vtgate/planbuilder/from.go
index a9b9af044b..be78964a31 100644
--- a/go/vt/vtgate/planbuilder/from.go
+++ b/go/vt/vtgate/planbuilder/from.go
@@ -350,14 +350,6 @@ func (pb *primitiveBuilder) join(rpb *primitiveBuilder, ajoin *sqlparser.JoinTab
 		lRoute.eroute.TableName = strings.Join([]string{lRoute.eroute.TableName, rRoute.eroute.TableName}, ", ")
 	}
 
-	// join sysTableNames
-	for tableName, expr := range rRoute.eroute.SysTableTableName {
-		_, ok := lRoute.eroute.SysTableTableName[tableName]
-		if !ok {
-			lRoute.eroute.SysTableTableName[tableName] = expr
-		}
-	}
-
 	// Since the routes have merged, set st.singleRoute to point at
 	// the merged route.
 	pb.st.singleRoute = lRoute
diff --git a/go/vt/vtgate/planbuilder/gen4_planner.go b/go/vt/vtgate/planbuilder/gen4_planner.go
index 3ad7b8b210..146cbb7d0c 100644
--- a/go/vt/vtgate/planbuilder/gen4_planner.go
+++ b/go/vt/vtgate/planbuilder/gen4_planner.go
@@ -29,32 +29,32 @@ var _ selectPlanner = gen4Planner
 
 func gen4Planner(_ string) func(sqlparser.Statement, *sqlparser.ReservedVars, ContextVSchema) (engine.Primitive, error) {
 	return func(stmt sqlparser.Statement, reservedVars *sqlparser.ReservedVars, vschema ContextVSchema) (engine.Primitive, error) {
-		selStatement, ok := stmt.(sqlparser.SelectStatement)
+		sel, ok := stmt.(*sqlparser.Select)
 		if !ok {
 			return nil, vterrors.Errorf(vtrpcpb.Code_UNIMPLEMENTED, "%T not yet supported", stmt)
 		}
 
-		sel, isSel := selStatement.(*sqlparser.Select)
-		if isSel {
-			// handle dual table for processing at vtgate.
-			p, err := handleDualSelects(sel, vschema)
-			if err != nil || p != nil {
-				return p, err
-			}
+		// handle dual table for processing at vtgate.
+		p, err := handleDualSelects(sel, vschema)
+		if err != nil {
+			return nil, err
+		}
+		if p != nil {
+			return p, nil
 		}
 
-		getPlan := func(selStatement sqlparser.SelectStatement) (logicalPlan, error) {
-			return newBuildSelectPlan(selStatement, reservedVars, vschema)
+		getPlan := func(sel *sqlparser.Select) (logicalPlan, error) {
+			return newBuildSelectPlan(sel, reservedVars, vschema)
 		}
 
-		plan, err := getPlan(selStatement)
+		plan, err := getPlan(sel)
 		if err != nil {
 			return nil, err
 		}
 
 		if shouldRetryWithCNFRewriting(plan) {
 			// by transforming the predicates to CNF, the planner will sometimes find better plans
-			primitive := gen4CNFRewrite(stmt, getPlan)
+			primitive := rewriteToCNFAndReplan(stmt, getPlan)
 			if primitive != nil {
 				return primitive, nil
 			}
@@ -63,37 +63,23 @@ func gen4Planner(_ string) func(sqlparser.Statement, *sqlparser.ReservedVars, Co
 	}
 }
 
-func gen4CNFRewrite(stmt sqlparser.Statement, getPlan func(selStatement sqlparser.SelectStatement) (logicalPlan, error)) engine.Primitive {
-	rewritten, isSel := sqlparser.RewriteToCNF(stmt).(sqlparser.SelectStatement)
-	if !isSel {
-		// Fail-safe code, should never happen
-		return nil
-	}
-	plan2, err := getPlan(rewritten)
-	if err == nil && !shouldRetryWithCNFRewriting(plan2) {
-		// we only use this new plan if it's better than the old one we got
-		return plan2.Primitive()
-	}
-	return nil
-}
-
-func newBuildSelectPlan(selStmt sqlparser.SelectStatement, reservedVars *sqlparser.ReservedVars, vschema ContextVSchema) (logicalPlan, error) {
+func newBuildSelectPlan(sel *sqlparser.Select, reservedVars *sqlparser.ReservedVars, vschema ContextVSchema) (logicalPlan, error) {
 	ksName := ""
 	if ks, _ := vschema.DefaultKeyspace(); ks != nil {
 		ksName = ks.Name
 	}
-	semTable, err := semantics.Analyze(selStmt, ksName, vschema, starRewrite)
+	semTable, err := semantics.Analyze(sel, ksName, vschema, starRewrite)
 	if err != nil {
 		return nil, err
 	}
 
 	ctx := newPlanningContext(reservedVars, semTable, vschema)
-	err = queryRewrite(ctx, selStmt)
+	err = queryRewrite(ctx, sel)
 	if err != nil {
 		return nil, err
 	}
 
-	opTree, err := abstract.CreateOperatorFromAST(selStmt, semTable)
+	opTree, err := abstract.CreateOperatorFromSelect(sel, semTable)
 	if err != nil {
 		return nil, err
 	}
@@ -103,30 +89,25 @@ func newBuildSelectPlan(selStmt sqlparser.SelectStatement, reservedVars *sqlpars
 		return nil, err
 	}
 
-	plan, err := transformToLogicalPlan(ctx, tree)
+	plan, err := transformToLogicalPlan(ctx, tree, semTable)
 	if err != nil {
 		return nil, err
 	}
 
-	sel, isSel := selStmt.(*sqlparser.Select)
-	// We do not need to call planHorizon for union queries.
-	// We would have already executed this for the select statements while transforming to logical plans.
-	if isSel {
-		plan, err = planHorizon(ctx, plan, sel)
-		if err != nil {
-			return nil, err
-		}
+	plan, err = planHorizon(ctx, plan, sel)
+	if err != nil {
+		return nil, err
+	}
 
-		if err := setMiscFunc(plan, sel); err != nil {
-			return nil, err
-		}
+	if err := setMiscFunc(plan, sel); err != nil {
+		return nil, err
 	}
 
 	if err := plan.WireupGen4(semTable); err != nil {
 		return nil, err
 	}
 
-	directives := sqlparser.ExtractCommentDirectives(sqlparser.GetFirstSelect(selStmt).Comments)
+	directives := sqlparser.ExtractCommentDirectives(sel.Comments)
 	if directives.IsSet(sqlparser.DirectiveScatterErrorsAsWarnings) {
 		_, _ = visit(plan, func(logicalPlan logicalPlan) (bool, logicalPlan, error) {
 			switch plan := logicalPlan.(type) {
@@ -180,25 +161,22 @@ func checkUnsupportedConstructs(sel *sqlparser.Select) error {
 	return nil
 }
 
-func planHorizon(ctx planningContext, plan logicalPlan, in sqlparser.SelectStatement) (logicalPlan, error) {
-	sel, isSel := in.(*sqlparser.Select)
-	if isSel {
-		hp := horizonPlanning{
-			sel: sel,
-		}
+func planHorizon(ctx planningContext, plan logicalPlan, sel *sqlparser.Select) (logicalPlan, error) {
+	hp := horizonPlanning{
+		sel: sel,
+	}
 
-		replaceSubQuery(ctx.sqToReplace, sel)
-		var err error
-		plan, err = hp.planHorizon(ctx, plan)
-		if err != nil {
-			return nil, err
-		}
-		plan, err = planLimit(sel.Limit, plan)
-		if err != nil {
-			return nil, err
-		}
+	replaceSubQuery(ctx.sqToReplace, sel)
+	var err error
+	plan, err = hp.planHorizon(ctx, plan)
+	if err != nil {
+		return nil, err
 	}
 
+	plan, err = planLimit(sel.Limit, plan)
+	if err != nil {
+		return nil, err
+	}
 	return plan, nil
 
 }
diff --git a/go/vt/vtgate/planbuilder/horizon_planning.go b/go/vt/vtgate/planbuilder/horizon_planning.go
index 73eb03d672..250b9616d1 100644
--- a/go/vt/vtgate/planbuilder/horizon_planning.go
+++ b/go/vt/vtgate/planbuilder/horizon_planning.go
@@ -148,7 +148,7 @@ func pushProjection(expr *sqlparser.AliasedExpr, plan logicalPlan, semTable *sem
 				return i, false, nil
 			}
 		}
-		expr = removeKeyspaceFromColName(expr)
+		expr = removeQualifierFromColName(expr)
 
 		offset := len(sel.SelectExprs)
 		sel.SelectExprs = append(sel.SelectExprs, expr)
@@ -213,14 +213,12 @@ func pushProjection(expr *sqlparser.AliasedExpr, plan logicalPlan, semTable *sem
 			}
 		}
 		return 0, false, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "cannot push projections in ordered aggregates")
-	case *limit:
-		return pushProjection(expr, node.input, semTable, inner, reuseCol)
 	default:
 		return 0, false, vterrors.Errorf(vtrpcpb.Code_UNIMPLEMENTED, "[BUG] push projection does not yet support: %T", node)
 	}
 }
 
-func removeKeyspaceFromColName(expr *sqlparser.AliasedExpr) *sqlparser.AliasedExpr {
+func removeQualifierFromColName(expr *sqlparser.AliasedExpr) *sqlparser.AliasedExpr {
 	if _, ok := expr.Expr.(*sqlparser.ColName); ok {
 		expr = sqlparser.CloneRefOfAliasedExpr(expr)
 		col := expr.Expr.(*sqlparser.ColName)
@@ -528,13 +526,6 @@ func (hp *horizonPlanning) planOrderBy(ctx planningContext, orderExprs []abstrac
 		}
 		plan.underlying = newUnderlyingPlan
 		return plan, nil
-	case *limit:
-		newUnderlyingPlan, err := hp.planOrderBy(ctx, orderExprs, plan.input)
-		if err != nil {
-			return nil, err
-		}
-		plan.input = newUnderlyingPlan
-		return plan, nil
 	default:
 		return nil, semantics.Gen4NotSupportedF("ordering on complex query %T", plan)
 	}
diff --git a/go/vt/vtgate/planbuilder/querytree.go b/go/vt/vtgate/planbuilder/querytree.go
index d877eb73d1..de2c859983 100644
--- a/go/vt/vtgate/planbuilder/querytree.go
+++ b/go/vt/vtgate/planbuilder/querytree.go
@@ -74,7 +74,7 @@ type (
 
 		alias string
 
-		query sqlparser.SelectStatement
+		query *sqlparser.Select
 	}
 )
 
diff --git a/go/vt/vtgate/planbuilder/querytree_transformers.go b/go/vt/vtgate/planbuilder/querytree_transformers.go
index 4e7f31e943..c22f2e3c56 100644
--- a/go/vt/vtgate/planbuilder/querytree_transformers.go
+++ b/go/vt/vtgate/planbuilder/querytree_transformers.go
@@ -25,47 +25,29 @@ import (
 	vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc"
 	"vitess.io/vitess/go/vt/sqlparser"
 	"vitess.io/vitess/go/vt/vtgate/engine"
+	"vitess.io/vitess/go/vt/vtgate/semantics"
 	"vitess.io/vitess/go/vt/vtgate/vindexes"
 
 	"vitess.io/vitess/go/vt/vterrors"
 )
 
-func transformToLogicalPlan(ctx planningContext, tree queryTree) (logicalPlan, error) {
+func transformToLogicalPlan(ctx planningContext, tree queryTree, semTable *semantics.SemTable) (logicalPlan, error) {
 	switch n := tree.(type) {
 	case *routeTree:
-		return transformRoutePlan(ctx, n)
+		return transformRoutePlan(n, semTable, ctx.sqToReplace)
 	case *joinTree:
-		return transformJoinPlan(ctx, n)
+		return transformJoinPlan(ctx, n, semTable)
 	case *derivedTree:
-		return transformDerivedPlan(ctx, n)
+		return transformDerivedPlan(ctx, n, semTable)
 	case *subqueryTree:
-		return transformSubqueryTree(ctx, n)
-	case *concatenateTree:
-		return transformConcatenatePlan(ctx, n)
-	case *distinctTree:
-		return transformDistinctPlan(ctx, n)
+		return transformSubqueryTree(ctx, n, semTable)
 	}
 
 	return nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "[BUG] unknown query tree encountered: %T", tree)
 }
 
-func pushDistinct(plan logicalPlan) error {
-	switch n := plan.(type) {
-	case *route:
-		n.Select.MakeDistinct()
-	case *concatenateGen4:
-		for _, source := range n.sources {
-			err := pushDistinct(source)
-			if err != nil {
-				return err
-			}
-		}
-	}
-	return nil
-}
-
-func transformSubqueryTree(ctx planningContext, n *subqueryTree) (logicalPlan, error) {
-	innerPlan, err := transformToLogicalPlan(ctx, n.inner)
+func transformSubqueryTree(ctx planningContext, n *subqueryTree, semTable *semantics.SemTable) (logicalPlan, error) {
+	innerPlan, err := transformToLogicalPlan(ctx, n.inner, semTable)
 	if err != nil {
 		return nil, err
 	}
@@ -75,7 +57,7 @@ func transformSubqueryTree(ctx planningContext, n *subqueryTree) (logicalPlan, e
 	}
 
 	plan := newPulloutSubquery(n.opcode, n.argName, "", innerPlan)
-	outerPlan, err := transformToLogicalPlan(ctx, n.outer)
+	outerPlan, err := transformToLogicalPlan(ctx, n.outer, semTable)
 	if err != nil {
 		return nil, err
 	}
@@ -83,14 +65,14 @@ func transformSubqueryTree(ctx planningContext, n *subqueryTree) (logicalPlan, e
 	return plan, err
 }
 
-func transformDerivedPlan(ctx planningContext, n *derivedTree) (logicalPlan, error) {
+func transformDerivedPlan(ctx planningContext, n *derivedTree, semTable *semantics.SemTable) (logicalPlan, error) {
 	// transforming the inner part of the derived table into a logical plan
 	// so that we can do horizon planning on the inner. If the logical plan
 	// we've produced is a Route, we set its Select.From field to be an aliased
 	// expression containing our derived table's inner select and the derived
 	// table's alias.
 
-	plan, err := transformToLogicalPlan(ctx, n.inner)
+	plan, err := transformToLogicalPlan(ctx, n.inner, semTable)
 	if err != nil {
 		return nil, err
 	}
@@ -118,81 +100,7 @@ func transformDerivedPlan(ctx planningContext, n *derivedTree) (logicalPlan, err
 	return plan, nil
 }
 
-func transformConcatenatePlan(ctx planningContext, n *concatenateTree) (logicalPlan, error) {
-	var sources []logicalPlan
-
-	for i, source := range n.sources {
-		plan, err := createLogicalPlan(ctx, source, n.selectStmts[i])
-		if err != nil {
-			return nil, err
-		}
-		if i == 0 {
-			sources = append(sources, plan)
-			continue
-		}
-		last := sources[len(sources)-1]
-		newPlan := mergeUnionLogicalPlans(ctx, last, plan)
-		if newPlan != nil {
-			sources[len(sources)-1] = newPlan
-			continue
-		}
-		sources = append(sources, plan)
-	}
-
-	if len(sources) == 1 {
-		return sources[0], nil
-	}
-
-	return &concatenateGen4{
-		sources: sources,
-	}, nil
-}
-
-func mergeUnionLogicalPlans(ctx planningContext, left logicalPlan, right logicalPlan) logicalPlan {
-	lroute, ok := left.(*route)
-	if !ok {
-		return nil
-	}
-	rroute, ok := right.(*route)
-	if !ok {
-		return nil
-	}
-
-	if canMergePlans(ctx, lroute, rroute) {
-		elem := &sqlparser.UnionSelect{
-			Distinct:  false,
-			Statement: rroute.Select,
-		}
-		switch n := lroute.Select.(type) {
-		case *sqlparser.Union:
-			n.UnionSelects = append(n.UnionSelects, elem)
-		default:
-			lroute.Select = &sqlparser.Union{FirstStatement: lroute.Select, UnionSelects: []*sqlparser.UnionSelect{elem}}
-		}
-
-		return lroute
-	}
-	return nil
-}
-
-func createLogicalPlan(ctx planningContext, source queryTree, selStmt *sqlparser.Select) (logicalPlan, error) {
-	plan, err := transformToLogicalPlan(ctx, source)
-	if err != nil {
-		return nil, err
-	}
-	if selStmt != nil {
-		plan, err = planHorizon(ctx, plan, selStmt)
-		if err != nil {
-			return nil, err
-		}
-		if err := setMiscFunc(plan, selStmt); err != nil {
-			return nil, err
-		}
-	}
-	return plan, nil
-}
-
-func transformRoutePlan(ctx planningContext, n *routeTree) (*route, error) {
+func transformRoutePlan(n *routeTree, semTable *semantics.SemTable, sqToReplace map[string]*sqlparser.Select) (*route, error) {
 	var tablesForSelect sqlparser.TableExprs
 	tableNameMap := map[string]interface{}{}
 
@@ -279,16 +187,11 @@ func transformRoutePlan(ctx planningContext, n *routeTree) (*route, error) {
 		SelectExprs: expressions,
 		From:        tablesForSelect,
 		Where:       where,
-		Comments:    ctx.semTable.Comments,
+		Comments:    semTable.Comments,
 	}
 
-	replaceSubQuery(ctx.sqToReplace, sel)
+	replaceSubQuery(sqToReplace, sel)
 
-	// TODO clean up when gen4 is the only planner
-	var condition sqlparser.Expr
-	if n.selected != nil && len(n.selected.valueExprs) > 0 {
-		condition = n.selected.valueExprs[0]
-	}
 	return &route{
 		eroute: &engine.Route{
 			Opcode:              n.routeOpCode,
@@ -299,34 +202,17 @@ func transformRoutePlan(ctx planningContext, n *routeTree) (*route, error) {
 			SysTableTableName:   n.SysTableTableName,
 			SysTableTableSchema: n.SysTableTableSchema,
 		},
-		Select:    sel,
-		tables:    n.solved,
-		condition: condition,
+		Select: sel,
+		tables: n.solved,
 	}, nil
 }
 
-func transformDistinctPlan(ctx planningContext, n *distinctTree) (logicalPlan, error) {
-	innerPlan, err := transformToLogicalPlan(ctx, n.source)
-	if err != nil {
-		return nil, err
-	}
-	err = pushDistinct(innerPlan)
-	if err != nil {
-		return nil, err
-	}
-	if rb, isRoute := innerPlan.(*route); isRoute && rb.isSingleShard() {
-		// if we have a single shard route, we don't need to do anything to make it distinct
-		return innerPlan, nil
-	}
-	return newDistinct(innerPlan), nil
-}
-
-func transformJoinPlan(ctx planningContext, n *joinTree) (logicalPlan, error) {
-	lhs, err := transformToLogicalPlan(ctx, n.lhs)
+func transformJoinPlan(ctx planningContext, n *joinTree, semTable *semantics.SemTable) (logicalPlan, error) {
+	lhs, err := transformToLogicalPlan(ctx, n.lhs, semTable)
 	if err != nil {
 		return nil, err
 	}
-	rhs, err := transformToLogicalPlan(ctx, n.rhs)
+	rhs, err := transformToLogicalPlan(ctx, n.rhs, semTable)
 	if err != nil {
 		return nil, err
 	}
@@ -395,7 +281,7 @@ func relToTableExpr(t relation) (sqlparser.TableExpr, error) {
 		tbls := innerTables.(*sqlparser.ParenTableExpr)
 
 		sel := &sqlparser.Select{
-			SelectExprs: sqlparser.GetFirstSelect(t.query).SelectExprs,
+			SelectExprs: t.query.SelectExprs,
 			From:        tbls.Exprs,
 			Where:       &sqlparser.Where{Expr: sqlparser.AndExpressions(t.predicates...)},
 		}
diff --git a/go/vt/vtgate/planbuilder/rewrite.go b/go/vt/vtgate/planbuilder/rewrite.go
index d70f9d98b8..e784568559 100644
--- a/go/vt/vtgate/planbuilder/rewrite.go
+++ b/go/vt/vtgate/planbuilder/rewrite.go
@@ -28,7 +28,6 @@ type rewriter struct {
 	err          error
 	semTable     *semantics.SemTable
 	reservedVars *sqlparser.ReservedVars
-	isInSubquery int
 }
 
 func starRewrite(statement sqlparser.SelectStatement, semTable *semantics.SemTable) error {
@@ -113,61 +112,18 @@ func queryRewrite(ctx planningContext, statement sqlparser.SelectStatement) erro
 		semTable:     ctx.semTable,
 		reservedVars: ctx.reservedVars,
 	}
-	sqlparser.Rewrite(statement, r.rewriteDown, r.rewriteUp)
+	sqlparser.Rewrite(statement, r.rewrite, nil)
 	return nil
 }
 
-func (r *rewriter) rewriteDown(cursor *sqlparser.Cursor) bool {
+func (r *rewriter) rewrite(cursor *sqlparser.Cursor) bool {
 	switch node := cursor.Node().(type) {
 	case *sqlparser.Select:
 		rewriteHavingClause(node)
 	case *sqlparser.ExistsExpr:
 		return r.rewriteExistsSubquery(cursor, node)
 	case *sqlparser.Subquery:
-		r.isInSubquery++
 		rewriteSubquery(cursor, r, node)
-	case *sqlparser.AliasedTableExpr:
-		// rewrite names of the routed tables for the subquery
-		// We only need to do this for non-derived tables and if they are in a subquery
-		if _, isDerived := node.Expr.(*sqlparser.DerivedTable); isDerived || r.isInSubquery == 0 {
-			break
-		}
-		// find the tableSet and tableInfo that this table points to
-		// tableInfo should contain the information for the original table that the routed table points to
-		tableSet := r.semTable.TableSetFor(node)
-		tableInfo, err := r.semTable.TableInfoFor(tableSet)
-		if err != nil {
-			// Fail-safe code, should never happen
-			break
-		}
-		// vindexTable is the original table
-		vindexTable := tableInfo.GetVindexTable()
-		if vindexTable == nil {
-			break
-		}
-		tableName := node.Expr.(sqlparser.TableName)
-		// if the table name matches what the original is, then we do not need to rewrite
-		if sqlparser.EqualsTableIdent(vindexTable.Name, tableName.Name) {
-			break
-		}
-		// if there is no as clause, then move the routed table to the as clause.
-		// i.e
-		// routed as x -> original as x
-		// routed -> original as routed
-		if node.As.IsEmpty() {
-			node.As = tableName.Name
-		}
-		// replace the table name with the original table
-		tableName.Name = vindexTable.Name
-		node.Expr = tableName
-	}
-	return true
-}
-
-func (r *rewriter) rewriteUp(cursor *sqlparser.Cursor) bool {
-	switch cursor.Node().(type) {
-	case *sqlparser.Subquery:
-		r.isInSubquery--
 	}
 	return true
 }
diff --git a/go/vt/vtgate/planbuilder/route.go b/go/vt/vtgate/planbuilder/route.go
index 55dcbe2c44..5b9c0d78d9 100644
--- a/go/vt/vtgate/planbuilder/route.go
+++ b/go/vt/vtgate/planbuilder/route.go
@@ -490,14 +490,8 @@ func (rb *route) unionCanMerge(other *route, distinct bool) bool {
 		return false
 	}
 	switch rb.eroute.Opcode {
-	case engine.SelectUnsharded, engine.SelectReference:
+	case engine.SelectUnsharded, engine.SelectDBA, engine.SelectReference:
 		return rb.eroute.Opcode == other.eroute.Opcode
-	case engine.SelectDBA:
-		return other.eroute.Opcode == engine.SelectDBA &&
-			len(rb.eroute.SysTableTableSchema) == 0 &&
-			len(rb.eroute.SysTableTableName) == 0 &&
-			len(other.eroute.SysTableTableSchema) == 0 &&
-			len(other.eroute.SysTableTableName) == 0
 	case engine.SelectEqualUnique:
 		// Check if they target the same shard.
 		if other.eroute.Opcode == engine.SelectEqualUnique && rb.eroute.Vindex == other.eroute.Vindex && valEqual(rb.condition, other.condition) {
diff --git a/go/vt/vtgate/planbuilder/route_planning.go b/go/vt/vtgate/planbuilder/route_planning.go
index bf7581b0b8..cfa4608886 100644
--- a/go/vt/vtgate/planbuilder/route_planning.go
+++ b/go/vt/vtgate/planbuilder/route_planning.go
@@ -21,6 +21,8 @@ import (
 	"io"
 	"sort"
 
+	"vitess.io/vitess/go/sqltypes"
+
 	"vitess.io/vitess/go/vt/vtgate/planbuilder/abstract"
 
 	vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc"
@@ -87,38 +89,11 @@ func optimizeQuery(ctx planningContext, opTree abstract.Operator) (queryTree, er
 		}, nil
 	case *abstract.SubQuery:
 		return optimizeSubQuery(ctx, op)
-	case *abstract.Concatenate:
-		return optimizeUnion(ctx, op)
-	case *abstract.Distinct:
-		qt, err := optimizeQuery(ctx, op.Source)
-		if err != nil {
-			return nil, err
-		}
-		return &distinctTree{
-			source: qt,
-		}, nil
 	default:
 		return nil, semantics.Gen4NotSupportedF("optimizeQuery")
 	}
 }
 
-func optimizeUnion(ctx planningContext, op *abstract.Concatenate) (queryTree, error) {
-	var sources []queryTree
-	for _, source := range op.Sources {
-		qt, err := optimizeQuery(ctx, source)
-		if err != nil {
-			return nil, err
-		}
-
-		sources = append(sources, qt)
-	}
-
-	return &concatenateTree{
-		selectStmts: op.SelectStmts,
-		sources:     sources,
-	}, nil
-}
-
 func optimizeSubQuery(ctx planningContext, op *abstract.SubQuery) (queryTree, error) {
 	outerTree, err := optimizeQuery(ctx, op.Outer)
 	if err != nil {
@@ -134,15 +109,20 @@ func optimizeSubQuery(ctx planningContext, op *abstract.SubQuery) (queryTree, er
 		}
 
 		preds := inner.Inner.UnsolvedPredicates(ctx.semTable)
-		merger := func(a, b *routeTree) (*routeTree, error) {
-			return mergeSubQuery(ctx, a, inner)
+		var mergeErr error
+		merger := func(a, b *routeTree) *routeTree {
+			var merged *routeTree
+			merged, mergeErr = mergeSubQuery(ctx, a, inner)
+			return merged
 		}
 
-		merged, err := tryMergeSubQuery(ctx, outerTree, treeInner, inner, preds, merger)
+		merged, err := tryMerge(ctx, outerTree, treeInner, preds, merger)
 		if err != nil {
 			return nil, err
 		}
-
+		if mergeErr != nil {
+			return nil, mergeErr
+		}
 		if merged == nil {
 			if len(preds) > 0 {
 				return nil, vterrors.Errorf(vtrpcpb.Code_UNIMPLEMENTED, "unsupported: cross-shard correlated subquery")
@@ -174,92 +154,6 @@ func optimizeSubQuery(ctx planningContext, op *abstract.SubQuery) (queryTree, er
 	return outerTree, nil
 }
 
-func tryMergeSubQuery(ctx planningContext, outer, subq queryTree, subQueryInner *abstract.SubQueryInner, joinPredicates []sqlparser.Expr, merger mergeFunc) (queryTree, error) {
-	var merged queryTree
-	var err error
-	switch outerTree := outer.(type) {
-	case *routeTree:
-		merged, err = tryMerge(ctx, outerTree, subq, joinPredicates, merger)
-		if err != nil {
-			return nil, err
-		}
-		return merged, err
-	case *joinTree:
-		if outerTree.outer {
-			return nil, nil
-		}
-		newMergefunc := func(a, b *routeTree) (*routeTree, error) {
-			rt, err := merger(a, b)
-			if err != nil {
-				return nil, err
-			}
-			return rt, rewriteSubqueryDependenciesForJoin(a, outerTree, subQueryInner, ctx)
-		}
-		merged, err = tryMergeSubQuery(ctx, outerTree.lhs, subq, subQueryInner, joinPredicates, newMergefunc)
-		if err != nil {
-			return nil, err
-		}
-		if merged != nil {
-			outerTree.lhs = merged
-			return outerTree, nil
-		}
-
-		merged, err = tryMergeSubQuery(ctx, outerTree.rhs, subq, subQueryInner, joinPredicates, newMergefunc)
-		if err != nil {
-			return nil, err
-		}
-		if merged != nil {
-			outerTree.rhs = merged
-			return outerTree, nil
-		}
-		return nil, nil
-	default:
-		return nil, nil
-	}
-}
-
-func rewriteSubqueryDependenciesForJoin(a *routeTree, outerTree *joinTree, subQueryInner *abstract.SubQueryInner, ctx planningContext) error {
-	// first we find the other side of the tree by comparing the tableIDs
-	// other side is RHS if the subquery is in the LHS, otherwise it is LHS
-	otherTree := outerTree.lhs
-	if a.tableID() == outerTree.lhs.tableID() {
-		otherTree = outerTree.rhs
-	}
-
-	var rewriteError error
-	// go over the entire where expression in the subquery
-	sqlparser.Rewrite(subQueryInner.SelectStatement.Where.Expr, func(cursor *sqlparser.Cursor) bool {
-		sqlNode := cursor.Node()
-		switch node := sqlNode.(type) {
-		case *sqlparser.ColName:
-			// check weather the column name belongs to the other side of the join tree
-			if ctx.semTable.Dependencies(node).IsSolvedBy(otherTree.tableID()) {
-				// get the bindVariable for that column name and replace it in the subquery
-				bindVar := node.CompliantName()
-				cursor.Replace(sqlparser.NewArgument(bindVar))
-				// check wether the bindVariable already exists in the joinVars of the other tree
-				_, alreadyExists := outerTree.vars[bindVar]
-				if alreadyExists {
-					return false
-				}
-				// if it does not exist, then push this as an output column there and add it to the joinVars
-				columnIndexes, err := otherTree.pushOutputColumns([]*sqlparser.ColName{node}, ctx.semTable)
-				if err != nil {
-					rewriteError = err
-					return false
-				}
-				columnIndex := columnIndexes[0]
-				outerTree.vars[bindVar] = columnIndex
-				return false
-			}
-		}
-		return true
-	}, nil)
-
-	// return any error while rewriting
-	return rewriteError
-}
-
 func mergeSubQuery(ctx planningContext, outer *routeTree, subq *abstract.SubQueryInner) (*routeTree, error) {
 	ctx.sqToReplace[subq.ArgName] = subq.SelectStatement
 	err := outer.resetRoutingSelections(ctx)
@@ -308,7 +202,7 @@ func createSingleShardRoutePlan(sel *sqlparser.Select, rb *route) {
 	ast.SelectExprs = sel.SelectExprs
 	for i, expr := range ast.SelectExprs {
 		if aliasedExpr, ok := expr.(*sqlparser.AliasedExpr); ok {
-			ast.SelectExprs[i] = removeKeyspaceFromColName(aliasedExpr)
+			ast.SelectExprs[i] = removeQualifierFromColName(aliasedExpr)
 		}
 	}
 }
@@ -423,11 +317,11 @@ func mergeOrJoinInner(ctx planningContext, lhs, rhs queryTree, joinPredicates []
 func mergeOrJoin(ctx planningContext, lhs, rhs queryTree, joinPredicates []sqlparser.Expr, inner bool) (queryTree, error) {
 	newTabletSet := lhs.tableID() | rhs.tableID()
 
-	merger := func(a, b *routeTree) (*routeTree, error) {
+	merger := func(a, b *routeTree) *routeTree {
 		if inner {
-			return createRoutePlanForInner(a, b, newTabletSet, joinPredicates), nil
+			return createRoutePlanForInner(a, b, newTabletSet, joinPredicates)
 		}
-		return createRoutePlanForOuter(ctx, a, b, newTabletSet, joinPredicates), nil
+		return createRoutePlanForOuter(ctx, a, b, newTabletSet, joinPredicates)
 	}
 
 	newPlan, _ := tryMerge(ctx, lhs, rhs, joinPredicates, merger)
@@ -656,11 +550,22 @@ func createRoutePlan(ctx planningContext, table *abstract.QueryTable, solves sem
 	case !vschemaTable.Keyspace.Sharded:
 		plan.routeOpCode = engine.SelectUnsharded
 	case vschemaTable.Pinned != nil:
-
 		// Pinned tables have their keyspace ids already assigned.
 		// Use the Binary vindex, which is the identity function
 		// for keyspace id.
 		plan.routeOpCode = engine.SelectEqualUnique
+		vindex, _ := vindexes.NewBinary("binary", nil)
+		plan.selected = &vindexOption{
+			ready:       true,
+			values:      []sqltypes.PlanValue{{Value: sqltypes.MakeTrusted(sqltypes.VarBinary, vschemaTable.Pinned)}},
+			valueExprs:  nil,
+			predicates:  nil,
+			opcode:      engine.SelectEqualUnique,
+			foundVindex: vindex,
+			cost: cost{
+				opCode: engine.SelectEqualUnique,
+			},
+		}
 	default:
 		plan.routeOpCode = engine.SelectScatter
 	}
@@ -751,41 +656,10 @@ func canMergeOnFilters(ctx planningContext, a, b *routeTree, joinPredicates []sq
 	return false
 }
 
-type mergeFunc func(a, b *routeTree) (*routeTree, error)
-
-func canMergePlans(ctx planningContext, a, b *route) bool {
-	// this method should be close to tryMerge below. it does the same thing, but on logicalPlans instead of queryTrees
-	if a.eroute.Keyspace.Name != b.eroute.Keyspace.Name {
-		return false
-	}
-	switch a.eroute.Opcode {
-	case engine.SelectUnsharded, engine.SelectReference:
-		return a.eroute.Opcode == b.eroute.Opcode
-	case engine.SelectDBA:
-		return b.eroute.Opcode == engine.SelectDBA &&
-			len(a.eroute.SysTableTableSchema) == 0 &&
-			len(a.eroute.SysTableTableName) == 0 &&
-			len(b.eroute.SysTableTableSchema) == 0 &&
-			len(b.eroute.SysTableTableName) == 0
-	case engine.SelectEqualUnique:
-		// Check if they target the same shard.
-		if b.eroute.Opcode == engine.SelectEqualUnique &&
-			a.eroute.Vindex == b.eroute.Vindex &&
-			a.condition != nil &&
-			b.condition != nil &&
-			gen4ValuesEqual(ctx, []sqlparser.Expr{a.condition}, []sqlparser.Expr{b.condition}) {
-			return true
-		}
-	case engine.SelectScatter:
-		return b.eroute.Opcode == engine.SelectScatter
-	case engine.SelectNext:
-		return false
-	}
-	return false
-}
+type mergeFunc func(a, b *routeTree) *routeTree
 
 func tryMerge(ctx planningContext, a, b queryTree, joinPredicates []sqlparser.Expr, merger mergeFunc) (queryTree, error) {
-	aRoute, bRoute := queryTreesToRoutes(a.clone(), b.clone())
+	aRoute, bRoute := joinTreesToRoutes(a.clone(), b.clone())
 	if aRoute == nil || bRoute == nil {
 		return nil, nil
 	}
@@ -793,23 +667,23 @@ func tryMerge(ctx planningContext, a, b queryTree, joinPredicates []sqlparser.Ex
 	sameKeyspace := aRoute.keyspace == bRoute.keyspace
 
 	if sameKeyspace {
-		tree, err := tryMergeReferenceTable(aRoute, bRoute, merger)
-		if tree != nil || err != nil {
-			return tree, err
+		tree := tryMergeReferenceTable(aRoute, bRoute, merger)
+		if tree != nil {
+			return tree, nil
 		}
 	}
 
 	switch aRoute.routeOpCode {
 	case engine.SelectUnsharded, engine.SelectDBA:
 		if aRoute.routeOpCode == bRoute.routeOpCode {
-			return merger(aRoute, bRoute)
+			return merger(aRoute, bRoute), nil
 		}
 	case engine.SelectEqualUnique:
 		// if they are already both being sent to the same shard, we can merge
 		if bRoute.routeOpCode == engine.SelectEqualUnique {
 			if aRoute.selectedVindex() == bRoute.selectedVindex() &&
 				gen4ValuesEqual(ctx, aRoute.vindexExpressions(), bRoute.vindexExpressions()) {
-				return merger(aRoute, bRoute)
+				return merger(aRoute, bRoute), nil
 			}
 			return nil, nil
 		}
@@ -822,21 +696,21 @@ func tryMerge(ctx planningContext, a, b queryTree, joinPredicates []sqlparser.Ex
 			return nil, nil
 		}
 		if !sameKeyspace {
-			return nil, vterrors.New(vtrpcpb.Code_UNIMPLEMENTED, "unsupported: cross-shard correlated subquery")
+			return nil, vterrors.New(vtrpcpb.Code_INTERNAL, "unsupported: cross-shard correlated subquery")
 		}
 
 		canMerge := canMergeOnFilters(ctx, aRoute, bRoute, joinPredicates)
 		if !canMerge {
 			return nil, nil
 		}
-		r, err := merger(aRoute, bRoute)
+		r := merger(aRoute, bRoute)
 		r.pickBestAvailableVindex()
-		return r, err
+		return r, nil
 	}
 	return nil, nil
 }
 
-func tryMergeReferenceTable(aRoute *routeTree, bRoute *routeTree, merger mergeFunc) (*routeTree, error) {
+func tryMergeReferenceTable(aRoute *routeTree, bRoute *routeTree, merger mergeFunc) *routeTree {
 	// if either side is a reference table, we can just merge it and use the opcode of the other side
 	var opCode engine.RouteOpcode
 	var selected *vindexOption
@@ -849,16 +723,13 @@ func tryMergeReferenceTable(aRoute *routeTree, bRoute *routeTree, merger mergeFu
 		selected = aRoute.selected
 		opCode = aRoute.routeOpCode
 	default:
-		return nil, nil
+		return nil
 	}
 
-	r, err := merger(aRoute, bRoute)
-	if err != nil {
-		return nil, err
-	}
+	r := merger(aRoute, bRoute)
 	r.routeOpCode = opCode
 	r.selected = selected
-	return r, nil
+	return r
 }
 
 func makeRoute(j queryTree) *routeTree {
@@ -892,7 +763,7 @@ func makeRoute(j queryTree) *routeTree {
 	return inner
 }
 
-func queryTreesToRoutes(a, b queryTree) (*routeTree, *routeTree) {
+func joinTreesToRoutes(a, b queryTree) (*routeTree, *routeTree) {
 	aRoute := makeRoute(a)
 	if aRoute == nil {
 		return nil, nil
diff --git a/go/vt/vtgate/planbuilder/union.go b/go/vt/vtgate/planbuilder/union.go
index 0f0065d792..82292340d1 100644
--- a/go/vt/vtgate/planbuilder/union.go
+++ b/go/vt/vtgate/planbuilder/union.go
@@ -29,19 +29,17 @@ import (
 	"vitess.io/vitess/go/vt/vtgate/engine"
 )
 
-func buildUnionPlan(string) func(sqlparser.Statement, *sqlparser.ReservedVars, ContextVSchema) (engine.Primitive, error) {
-	return func(stmt sqlparser.Statement, reservedVars *sqlparser.ReservedVars, vschema ContextVSchema) (engine.Primitive, error) {
-		union := stmt.(*sqlparser.Union)
-		// For unions, create a pb with anonymous scope.
-		pb := newPrimitiveBuilder(vschema, newJointab(reservedVars))
-		if err := pb.processUnion(union, reservedVars, nil); err != nil {
-			return nil, err
-		}
-		if err := pb.plan.Wireup(pb.plan, pb.jt); err != nil {
-			return nil, err
-		}
-		return pb.plan.Primitive(), nil
+func buildUnionPlan(stmt sqlparser.Statement, reservedVars *sqlparser.ReservedVars, vschema ContextVSchema) (engine.Primitive, error) {
+	union := stmt.(*sqlparser.Union)
+	// For unions, create a pb with anonymous scope.
+	pb := newPrimitiveBuilder(vschema, newJointab(reservedVars))
+	if err := pb.processUnion(union, reservedVars, nil); err != nil {
+		return nil, err
+	}
+	if err := pb.plan.Wireup(pb.plan, pb.jt); err != nil {
+		return nil, err
 	}
+	return pb.plan.Primitive(), nil
 }
 
 func (pb *primitiveBuilder) processUnion(union *sqlparser.Union, reservedVars *sqlparser.ReservedVars, outer *symtab) error {
diff --git a/go/vt/vtgate/semantics/scoper.go b/go/vt/vtgate/semantics/scoper.go
index 6c737e4258..ff5069143e 100644
--- a/go/vt/vtgate/semantics/scoper.go
+++ b/go/vt/vtgate/semantics/scoper.go
@@ -76,6 +76,10 @@ func (s *scoper) down(cursor *sqlparser.Cursor) {
 			s.push(nScope)
 			s.sqlNodeScope[scopeKey{node: node}] = nScope
 		}
+	case *sqlparser.Union:
+		scope := newScope(s.currentScope())
+		s.push(scope)
+		s.sqlNodeScope[scopeKey{node: node}] = scope
 	case sqlparser.SelectExprs:
 		sel, parentIsSelect := cursor.Parent().(*sqlparser.Select)
 		if !parentIsSelect {
@@ -102,7 +106,7 @@ func (s *scoper) down(cursor *sqlparser.Cursor) {
 
 func (s *scoper) up(cursor *sqlparser.Cursor) error {
 	switch node := cursor.Node().(type) {
-	case *sqlparser.Select, sqlparser.OrderBy, sqlparser.GroupBy:
+	case sqlparser.SelectStatement, sqlparser.OrderBy, sqlparser.GroupBy:
 		s.popScope()
 	case *sqlparser.Where:
 		if node.Type != sqlparser.HavingClause {
@@ -181,29 +185,23 @@ func (s *scoper) upPost(cursor *sqlparser.Cursor) error {
 }
 
 func (s *scoper) changeScopeForNode(cursor *sqlparser.Cursor, k scopeKey) {
-	switch parent := cursor.Parent().(type) {
-	case *sqlparser.Select:
-		// In ORDER BY, GROUP BY and HAVING, we can see both the scope in the FROM part of the query, and the SELECT columns created
-		// so before walking the rest of the tree, we change the scope to match this behaviour
-		incomingScope := s.currentScope()
-		nScope := newScope(incomingScope)
-		s.push(nScope)
-		s.sqlNodeScope[k] = nScope
-		wScope := s.wScope[parent]
-		nScope.tables = append(nScope.tables, wScope.tables...)
-		nScope.selectStmt = incomingScope.selectStmt
-
-		if s.rScope[parent] != incomingScope {
-			panic("BUG: scope counts did not match")
-		}
-	case *sqlparser.Union:
-		nScope := newScope(nil)
-		nScope.selectStmt = sqlparser.GetFirstSelect(parent)
-		s.push(nScope)
-		s.sqlNodeScope[k] = nScope
-	default:
+	sel, ok := cursor.Parent().(*sqlparser.Select)
+	if !ok {
 		return
 	}
+	// In ORDER BY, GROUP BY and HAVING, we can see both the scope in the FROM part of the query, and the SELECT columns created
+	// so before walking the rest of the tree, we change the scope to match this behaviour
+	incomingScope := s.currentScope()
+	nScope := newScope(incomingScope)
+	s.push(nScope)
+	s.sqlNodeScope[k] = nScope
+	wScope := s.wScope[sel]
+	nScope.tables = append(nScope.tables, wScope.tables...)
+	nScope.selectStmt = incomingScope.selectStmt
+
+	if s.rScope[sel] != incomingScope {
+		panic("BUG: scope counts did not match")
+	}
 }
 
 func (s *scoper) currentScope() *scope {
diff --git a/go/vt/vtgate/semantics/semantic_state.go b/go/vt/vtgate/semantics/semantic_state.go
index a48ff6d5ee..244ed368e1 100644
--- a/go/vt/vtgate/semantics/semantic_state.go
+++ b/go/vt/vtgate/semantics/semantic_state.go
@@ -35,7 +35,6 @@ type (
 		Authoritative() bool
 		Name() (sqlparser.TableName, error)
 		GetExpr() *sqlparser.AliasedTableExpr
-		GetVindexTable() *vindexes.Table
 		GetColumns() []ColumnInfo
 		IsActualTable() bool
 
@@ -320,11 +319,6 @@ func (v *vTableInfo) GetExpr() *sqlparser.AliasedTableExpr {
 	return v.ASTNode
 }
 
-// GetVindexTable implements the TableInfo interface
-func (v *vTableInfo) GetVindexTable() *vindexes.Table {
-	return nil
-}
-
 func (v *vTableInfo) GetColumns() []ColumnInfo {
 	cols := make([]ColumnInfo, 0, len(v.columnNames))
 	for _, col := range v.columnNames {
@@ -377,11 +371,6 @@ func (a *AliasedTable) GetExpr() *sqlparser.AliasedTableExpr {
 	return a.ASTNode
 }
 
-// GetVindexTable implements the TableInfo interface
-func (a *AliasedTable) GetVindexTable() *vindexes.Table {
-	return a.Table
-}
-
 // Name implements the TableInfo interface
 func (a *AliasedTable) Name() (sqlparser.TableName, error) {
 	return a.ASTNode.TableName()
@@ -407,11 +396,6 @@ func (r *RealTable) GetExpr() *sqlparser.AliasedTableExpr {
 	return r.ASTNode
 }
 
-// GetVindexTable implements the TableInfo interface
-func (r *RealTable) GetVindexTable() *vindexes.Table {
-	return r.Table
-}
-
 // Name implements the TableInfo interface
 func (r *RealTable) Name() (sqlparser.TableName, error) {
 	return r.ASTNode.TableName()
diff --git a/go/vt/vtgate/semantics/table_collector.go b/go/vt/vtgate/semantics/table_collector.go
index b46adf5221..ca4a4a5ebf 100644
--- a/go/vt/vtgate/semantics/table_collector.go
+++ b/go/vt/vtgate/semantics/table_collector.go
@@ -46,36 +46,22 @@ func (tc *tableCollector) up(cursor *sqlparser.Cursor) error {
 
 	switch t := node.Expr.(type) {
 	case *sqlparser.DerivedTable:
-		switch sel := t.Select.(type) {
-		case *sqlparser.Select:
-			tableInfo := createVTableInfoForExpressions(sel.SelectExprs)
-			if err := tableInfo.checkForDuplicates(); err != nil {
-				return err
-			}
-
-			tableInfo.ASTNode = node
-			tableInfo.tableName = node.As.String()
-
-			tc.Tables = append(tc.Tables, tableInfo)
-			scope := tc.scoper.currentScope()
-			return scope.addTable(tableInfo)
-
-		case *sqlparser.Union:
-			tableInfo := createVTableInfoForExpressions(sqlparser.GetFirstSelect(sel).SelectExprs)
-			if err := tableInfo.checkForDuplicates(); err != nil {
-				return err
-			}
-			tableInfo.ASTNode = node
-			tableInfo.tableName = node.As.String()
-
-			tc.Tables = append(tc.Tables, tableInfo)
-			scope := tc.scoper.currentScope()
-			return scope.addTable(tableInfo)
-
-		default:
+		sel, isSelect := t.Select.(*sqlparser.Select)
+		if !isSelect {
 			return Gen4NotSupportedF("union in derived table")
 		}
 
+		tableInfo := createVTableInfoForExpressions(sel.SelectExprs)
+		if err := tableInfo.checkForDuplicates(); err != nil {
+			return err
+		}
+
+		tableInfo.ASTNode = node
+		tableInfo.tableName = node.As.String()
+
+		tc.Tables = append(tc.Tables, tableInfo)
+		scope := tc.scoper.currentScope()
+		return scope.addTable(tableInfo)
 	case sqlparser.TableName:
 		var tbl *vindexes.Table
 		var isInfSchema bool


Test patch:
diff --git a/go/vt/vtgate/planbuilder/abstract/operator_test.go b/go/vt/vtgate/planbuilder/abstract/operator_test.go
index 8afed7a311..810b9b7c27 100644
--- a/go/vt/vtgate/planbuilder/abstract/operator_test.go
+++ b/go/vt/vtgate/planbuilder/abstract/operator_test.go
@@ -237,62 +237,6 @@ JoinPredicates:
 	JoinPredicates:
 		1:2 - u.id = (select id from user_extra where id = u.id)
 	}
-}`,
-	}, {
-		input: "select 1 from a union select 2 from b",
-		output: `Distinct {
-	Concatenate {
-		QueryGraph: {
-		Tables:
-			1:a
-		},
-		QueryGraph: {
-		Tables:
-			2:b
-		}
-	}
-}`,
-	}, {
-		input: "select 1 from a union select 2 from b union select 3 from c",
-		output: `Distinct {
-	Concatenate {
-		QueryGraph: {
-		Tables:
-			1:a
-		},
-		QueryGraph: {
-		Tables:
-			2:b
-		},
-		QueryGraph: {
-		Tables:
-			4:c
-		}
-	}
-}`,
-	}, {
-		input: "select 1 from a union select 2 from b union select 3 from c union all select 4 from d",
-		output: `Concatenate {
-	Distinct {
-		Concatenate {
-			QueryGraph: {
-			Tables:
-				1:a
-			},
-			QueryGraph: {
-			Tables:
-				2:b
-			},
-			QueryGraph: {
-			Tables:
-				4:c
-			}
-		}
-	},
-	QueryGraph: {
-	Tables:
-		8:d
-	}
 }`,
 	}}
 
@@ -301,10 +245,9 @@ JoinPredicates:
 		t.Run(fmt.Sprintf("%d %s", i, sql), func(t *testing.T) {
 			tree, err := sqlparser.Parse(sql)
 			require.NoError(t, err)
-			stmt := tree.(sqlparser.SelectStatement)
-			semTable, err := semantics.Analyze(stmt, "", &semantics.FakeSI{}, semantics.NoRewrite)
+			semTable, err := semantics.Analyze(tree.(sqlparser.SelectStatement), "", &semantics.FakeSI{}, semantics.NoRewrite)
 			require.NoError(t, err)
-			optree, err := CreateOperatorFromAST(stmt, semTable)
+			optree, err := CreateOperatorFromSelect(tree.(*sqlparser.Select), semTable)
 			require.NoError(t, err)
 			assert.Equal(t, tc.output, testString(optree))
 			if t.Failed() {
@@ -338,17 +281,8 @@ func testString(op Operator) string {
 		}
 		outer := indent(testString(op.Outer))
 		return fmt.Sprintf("SubQuery: {\n\tSubQueries: %s\n\tOuter: %s\n}", inners, outer)
-	case *Distinct:
-		inner := indent(testString(op.Source))
-		return fmt.Sprintf("Distinct {\n%s\n}", inner)
-	case *Concatenate:
-		var inners []string
-		for _, source := range op.Sources {
-			inners = append(inners, indent(testString(source)))
-		}
-		return fmt.Sprintf("Concatenate {\n%s\n}", strings.Join(inners, ",\n"))
 	}
-	return fmt.Sprintf("implement me: %T", op)
+	return "implement me"
 }
 
 func indent(s string) string {
diff --git a/go/vt/vtgate/planbuilder/plan_test.go b/go/vt/vtgate/planbuilder/plan_test.go
index 75ba90b938..0b3c400c37 100644
--- a/go/vt/vtgate/planbuilder/plan_test.go
+++ b/go/vt/vtgate/planbuilder/plan_test.go
@@ -195,7 +195,7 @@ func TestPlan(t *testing.T) {
 	testFile(t, "flush_cases_no_default_keyspace.txt", testOutputTempDir, vschemaWrapper, false)
 	testFile(t, "show_cases_no_default_keyspace.txt", testOutputTempDir, vschemaWrapper, false)
 	testFile(t, "stream_cases.txt", testOutputTempDir, vschemaWrapper, false)
-	testFile(t, "systemtables_cases.txt", testOutputTempDir, vschemaWrapper, true)
+	testFile(t, "systemtables_cases.txt", testOutputTempDir, vschemaWrapper, false)
 }
 
 func TestSysVarSetDisabled(t *testing.T) {
diff --git a/go/vt/vtgate/planbuilder/route_planning_test.go b/go/vt/vtgate/planbuilder/route_planning_test.go
index 97a6e63d70..3144478d08 100644
--- a/go/vt/vtgate/planbuilder/route_planning_test.go
+++ b/go/vt/vtgate/planbuilder/route_planning_test.go
@@ -171,8 +171,8 @@ func TestCreateRoutePlanForOuter(t *testing.T) {
 	assert.NotNil(merge)
 }
 
-func fakeMerger(a, _ *routeTree) (*routeTree, error) {
-	return a, nil
+func fakeMerger(a, _ *routeTree) *routeTree {
+	return a
 }
 
 func equals(left, right sqlparser.Expr) sqlparser.Expr {
diff --git a/go/vt/vtgate/planbuilder/testdata/ddl_cases.txt b/go/vt/vtgate/planbuilder/testdata/ddl_cases.txt
index c78ae6a352..ba1090f2f9 100644
--- a/go/vt/vtgate/planbuilder/testdata/ddl_cases.txt
+++ b/go/vt/vtgate/planbuilder/testdata/ddl_cases.txt
@@ -267,6 +267,7 @@ Gen4 plan same as above
     "Query": "create view view_a as (select id from unsharded) union (select id from unsharded_auto) order by id asc limit 5"
   }
 }
+Gen4 plan same as above
 
 # create view with subquery in unsharded keyspace with multiple UNION clauses
 "create view view_a as select id from unsharded union select id from unsharded_auto union select id from unsharded_auto where id in (132)"
@@ -282,6 +283,7 @@ Gen4 plan same as above
     "Query": "create view view_a as select id from unsharded union select id from unsharded_auto union select id from unsharded_auto where id in (132)"
   }
 }
+Gen4 plan same as above
 
 # create view with subquery in unsharded keyspace with UNION clauses in subqueries
 "create view view_a as (select id from unsharded union select id from unsharded_auto) union (select id from unsharded_auto union select name from unsharded)"
@@ -297,6 +299,7 @@ Gen4 plan same as above
     "Query": "create view view_a as (select id from unsharded union select id from unsharded_auto) union (select id from unsharded_auto union select `name` from unsharded)"
   }
 }
+Gen4 plan same as above
 
 # Alter View
 "alter view user.user_extra as select* from user.user"
diff --git a/go/vt/vtgate/planbuilder/testdata/ddl_cases_no_default_keyspace.txt b/go/vt/vtgate/planbuilder/testdata/ddl_cases_no_default_keyspace.txt
index 1c5e7a17d4..35034721d7 100644
--- a/go/vt/vtgate/planbuilder/testdata/ddl_cases_no_default_keyspace.txt
+++ b/go/vt/vtgate/planbuilder/testdata/ddl_cases_no_default_keyspace.txt
@@ -469,6 +469,7 @@ Gen4 plan same as above
     "Query": "create view view_a as select * from music where user_id = 1 union select * from `user` where id = 1"
   }
 }
+Gen4 plan same as above
 
 # create view with testing SingleRow Projection
 "create view user.view_a as select 42 from user"
diff --git a/go/vt/vtgate/planbuilder/testdata/filter_cases.txt b/go/vt/vtgate/planbuilder/testdata/filter_cases.txt
index 4f31c23bba..e466b6b101 100644
--- a/go/vt/vtgate/planbuilder/testdata/filter_cases.txt
+++ b/go/vt/vtgate/planbuilder/testdata/filter_cases.txt
@@ -1258,141 +1258,6 @@ Gen4 plan same as above
     ]
   }
 }
-{
-  "QueryType": "SELECT",
-  "Original": "select u.m from user_extra join user u where u.id in (select m2 from user where user.id = u.id and user_extra.col = user.col) and u.id in (user_extra.col, 1)",
-  "Instructions": {
-    "OperatorType": "Join",
-    "Variant": "Join",
-    "JoinColumnIndexes": "1",
-    "JoinVars": {
-      "user_extra_col": 0
-    },
-    "TableName": "user_extra_`user`",
-    "Inputs": [
-      {
-        "OperatorType": "Route",
-        "Variant": "SelectScatter",
-        "Keyspace": {
-          "Name": "user",
-          "Sharded": true
-        },
-        "FieldQuery": "select user_extra.col from user_extra where 1 != 1",
-        "Query": "select user_extra.col from user_extra",
-        "Table": "user_extra"
-      },
-      {
-        "OperatorType": "Route",
-        "Variant": "SelectIN",
-        "Keyspace": {
-          "Name": "user",
-          "Sharded": true
-        },
-        "FieldQuery": "select u.m from `user` as u where 1 != 1",
-        "Query": "select u.m from `user` as u where u.id in (select m2 from `user` where `user`.id = u.id and `user`.col = :user_extra_col) and u.id in ::__vals",
-        "Table": "`user`",
-        "Values": [
-          [
-            ":user_extra_col",
-            1
-          ]
-        ],
-        "Vindex": "user_index"
-      }
-    ]
-  }
-}
-
-# correlated subquery merge-able into a route of a join tree
-"select u.m from user_extra join user u where u.id in (select m2 from user where user.id = u.id) and u.id in (user_extra.col, 1)"
-{
-  "QueryType": "SELECT",
-  "Original": "select u.m from user_extra join user u where u.id in (select m2 from user where user.id = u.id) and u.id in (user_extra.col, 1)",
-  "Instructions": {
-    "OperatorType": "Join",
-    "Variant": "Join",
-    "JoinColumnIndexes": "1",
-    "JoinVars": {
-      "user_extra_col": 0
-    },
-    "TableName": "user_extra_`user`",
-    "Inputs": [
-      {
-        "OperatorType": "Route",
-        "Variant": "SelectScatter",
-        "Keyspace": {
-          "Name": "user",
-          "Sharded": true
-        },
-        "FieldQuery": "select user_extra.col from user_extra where 1 != 1",
-        "Query": "select user_extra.col from user_extra",
-        "Table": "user_extra"
-      },
-      {
-        "OperatorType": "Route",
-        "Variant": "SelectIN",
-        "Keyspace": {
-          "Name": "user",
-          "Sharded": true
-        },
-        "FieldQuery": "select u.m from `user` as u where 1 != 1",
-        "Query": "select u.m from `user` as u where u.id in ::__vals and u.id in (select m2 from `user` where `user`.id = u.id)",
-        "Table": "`user`",
-        "Values": [
-          [
-            ":user_extra_col",
-            1
-          ]
-        ],
-        "Vindex": "user_index"
-      }
-    ]
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select u.m from user_extra join user u where u.id in (select m2 from user where user.id = u.id) and u.id in (user_extra.col, 1)",
-  "Instructions": {
-    "OperatorType": "Join",
-    "Variant": "Join",
-    "JoinColumnIndexes": "1",
-    "JoinVars": {
-      "user_extra_col": 0
-    },
-    "TableName": "user_extra_`user`",
-    "Inputs": [
-      {
-        "OperatorType": "Route",
-        "Variant": "SelectScatter",
-        "Keyspace": {
-          "Name": "user",
-          "Sharded": true
-        },
-        "FieldQuery": "select user_extra.col from user_extra where 1 != 1",
-        "Query": "select user_extra.col from user_extra",
-        "Table": "user_extra"
-      },
-      {
-        "OperatorType": "Route",
-        "Variant": "SelectIN",
-        "Keyspace": {
-          "Name": "user",
-          "Sharded": true
-        },
-        "FieldQuery": "select u.m from `user` as u where 1 != 1",
-        "Query": "select u.m from `user` as u where u.id in (select m2 from `user` where `user`.id = u.id) and u.id in ::__vals",
-        "Table": "`user`",
-        "Values": [
-          [
-            ":user_extra_col",
-            1
-          ]
-        ],
-        "Vindex": "user_index"
-      }
-    ]
-  }
-}
 
 # ensure subquery reordering gets us a better plan
 "select u.m from user_extra join user u where u.id in (select m2 from user where user.id = 5) and u.id = 5"
@@ -1434,44 +1299,6 @@ Gen4 plan same as above
     ]
   }
 }
-{
-  "QueryType": "SELECT",
-  "Original": "select u.m from user_extra join user u where u.id in (select m2 from user where user.id = 5) and u.id = 5",
-  "Instructions": {
-    "OperatorType": "Join",
-    "Variant": "Join",
-    "JoinColumnIndexes": "1",
-    "TableName": "user_extra_`user`",
-    "Inputs": [
-      {
-        "OperatorType": "Route",
-        "Variant": "SelectScatter",
-        "Keyspace": {
-          "Name": "user",
-          "Sharded": true
-        },
-        "FieldQuery": "select 1 from user_extra where 1 != 1",
-        "Query": "select 1 from user_extra",
-        "Table": "user_extra"
-      },
-      {
-        "OperatorType": "Route",
-        "Variant": "SelectEqualUnique",
-        "Keyspace": {
-          "Name": "user",
-          "Sharded": true
-        },
-        "FieldQuery": "select u.m from `user` as u where 1 != 1",
-        "Query": "select u.m from `user` as u where u.id in (select m2 from `user` where `user`.id = 5) and u.id = 5",
-        "Table": "`user`",
-        "Values": [
-          5
-        ],
-        "Vindex": "user_index"
-      }
-    ]
-  }
-}
 
 # nested subquery
 "select u.m from user_extra join user u where u.id in (select m2 from user where user.id = u.id and user_extra.col = user.col and user.id in (select m3 from user_extra where user_extra.user_id = user.id)) and u.id in (user_extra.col, 1)"
@@ -1519,50 +1346,6 @@ Gen4 plan same as above
     ]
   }
 }
-{
-  "QueryType": "SELECT",
-  "Original": "select u.m from user_extra join user u where u.id in (select m2 from user where user.id = u.id and user_extra.col = user.col and user.id in (select m3 from user_extra where user_extra.user_id = user.id)) and u.id in (user_extra.col, 1)",
-  "Instructions": {
-    "OperatorType": "Join",
-    "Variant": "Join",
-    "JoinColumnIndexes": "1",
-    "JoinVars": {
-      "user_extra_col": 0
-    },
-    "TableName": "user_extra_`user`",
-    "Inputs": [
-      {
-        "OperatorType": "Route",
-        "Variant": "SelectScatter",
-        "Keyspace": {
-          "Name": "user",
-          "Sharded": true
-        },
-        "FieldQuery": "select user_extra.col from user_extra where 1 != 1",
-        "Query": "select user_extra.col from user_extra",
-        "Table": "user_extra"
-      },
-      {
-        "OperatorType": "Route",
-        "Variant": "SelectIN",
-        "Keyspace": {
-          "Name": "user",
-          "Sharded": true
-        },
-        "FieldQuery": "select u.m from `user` as u where 1 != 1",
-        "Query": "select u.m from `user` as u where u.id in (select m2 from `user` where `user`.id = u.id and `user`.col = :user_extra_col and `user`.id in (select m3 from user_extra where user_extra.user_id = `user`.id)) and u.id in ::__vals",
-        "Table": "`user`",
-        "Values": [
-          [
-            ":user_extra_col",
-            1
-          ]
-        ],
-        "Vindex": "user_index"
-      }
-    ]
-  }
-}
 
 # Correlated subquery in where clause
 "select id from user where user.col in (select user_extra.col from user_extra where user_extra.user_id = user.id)"
@@ -1950,59 +1733,6 @@ Gen4 plan same as above
     ]
   }
 }
-{
-  "QueryType": "SELECT",
-  "Original": "select id1 from user where id = (select id2 from user where id2 in (select id3 from user))",
-  "Instructions": {
-    "OperatorType": "Subquery",
-    "Variant": "PulloutValue",
-    "Inputs": [
-      {
-        "OperatorType": "Subquery",
-        "Variant": "PulloutIn",
-        "Inputs": [
-          {
-            "OperatorType": "Route",
-            "Variant": "SelectScatter",
-            "Keyspace": {
-              "Name": "user",
-              "Sharded": true
-            },
-            "FieldQuery": "select id3 from `user` where 1 != 1",
-            "Query": "select id3 from `user`",
-            "Table": "`user`"
-          },
-          {
-            "OperatorType": "Route",
-            "Variant": "SelectScatter",
-            "Keyspace": {
-              "Name": "user",
-              "Sharded": true
-            },
-            "FieldQuery": "select id2 from `user` where 1 != 1",
-            "Query": "select id2 from `user` where id2 in ::__sq2",
-            "Table": "`user`"
-          }
-        ]
-      },
-      {
-        "OperatorType": "Route",
-        "Variant": "SelectEqualUnique",
-        "Keyspace": {
-          "Name": "user",
-          "Sharded": true
-        },
-        "FieldQuery": "select id1 from `user` where 1 != 1",
-        "Query": "select id1 from `user` where id = :__sq1",
-        "Table": "`user`",
-        "Values": [
-          ":__sq1"
-        ],
-        "Vindex": "user_index"
-      }
-    ]
-  }
-}
 
 # routing rules subquery merge
 "select col from user where id = (select id from route1 where route1.id = user.id)"
@@ -2021,7 +1751,6 @@ Gen4 plan same as above
     "Table": "`user`"
   }
 }
-Gen4 plan same as above
 
 # routing rules subquery pullout
 "select col from user where id = (select id from route2)"
@@ -3124,22 +2853,3 @@ Gen4 plan same as above
     ]
   }
 }
-
-# routing rules subquery merge with alias
-"select col from user where id = (select id from route1 as a where a.id = user.id)"
-{
-  "QueryType": "SELECT",
-  "Original": "select col from user where id = (select id from route1 as a where a.id = user.id)",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectScatter",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select col from `user` where 1 != 1",
-    "Query": "select col from `user` where id = (select id from `user` as a where a.id = `user`.id)",
-    "Table": "`user`"
-  }
-}
-Gen4 plan same as above
diff --git a/go/vt/vtgate/planbuilder/testdata/from_cases.txt b/go/vt/vtgate/planbuilder/testdata/from_cases.txt
index 0dbd2316ad..7ab61ece1d 100644
--- a/go/vt/vtgate/planbuilder/testdata/from_cases.txt
+++ b/go/vt/vtgate/planbuilder/testdata/from_cases.txt
@@ -3954,22 +3954,3 @@ Gen4 plan same as above
     ]
   }
 }
-
-# join two routes with SysTableTableName entries in LHS and RHS
-"select a.table_name from (select * from information_schema.key_column_usage a where a.table_name = 'users') a join (select * from information_schema.referential_constraints where table_name = 'users') b"
-{
-  "QueryType": "SELECT",
-  "Original": "select a.table_name from (select * from information_schema.key_column_usage a where a.table_name = 'users') a join (select * from information_schema.referential_constraints where table_name = 'users') b",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectDBA",
-    "Keyspace": {
-      "Name": "main",
-      "Sharded": false
-    },
-    "FieldQuery": "select a.table_name from (select * from information_schema.key_column_usage as a where 1 != 1) as a join (select * from information_schema.referential_constraints where 1 != 1) as b where 1 != 1",
-    "Query": "select a.table_name from (select * from information_schema.key_column_usage as a where a.table_name = :a_table_name) as a join (select * from information_schema.referential_constraints where table_name = :table_name) as b",
-    "SysTableTableName": "[a_table_name:VARBINARY(\"users\"), table_name:VARBINARY(\"users\")]",
-    "Table": "information_schema.key_column_usage, information_schema.referential_constraints"
-  }
-}
diff --git a/go/vt/vtgate/planbuilder/testdata/postprocess_cases.txt b/go/vt/vtgate/planbuilder/testdata/postprocess_cases.txt
index 0689dd30ab..e19a91d502 100644
--- a/go/vt/vtgate/planbuilder/testdata/postprocess_cases.txt
+++ b/go/vt/vtgate/planbuilder/testdata/postprocess_cases.txt
@@ -1210,43 +1210,6 @@ Gen4 plan same as above
     ]
   }
 }
-{
-  "QueryType": "SELECT",
-  "Original": "select u.id, e.id from user u join user_extra e where u.col = e.col and u.col in (select * from user where user.id = u.id order by col)",
-  "Instructions": {
-    "OperatorType": "Join",
-    "Variant": "Join",
-    "JoinColumnIndexes": "-2,1",
-    "JoinVars": {
-      "u_col": 0
-    },
-    "TableName": "`user`_user_extra",
-    "Inputs": [
-      {
-        "OperatorType": "Route",
-        "Variant": "SelectScatter",
-        "Keyspace": {
-          "Name": "user",
-          "Sharded": true
-        },
-        "FieldQuery": "select u.col, u.id from `user` as u where 1 != 1",
-        "Query": "select u.col, u.id from `user` as u where u.col in (select * from `user` where `user`.id = u.id order by col asc)",
-        "Table": "`user`"
-      },
-      {
-        "OperatorType": "Route",
-        "Variant": "SelectScatter",
-        "Keyspace": {
-          "Name": "user",
-          "Sharded": true
-        },
-        "FieldQuery": "select e.id from user_extra as e where 1 != 1",
-        "Query": "select e.id from user_extra as e where e.col = :u_col",
-        "Table": "user_extra"
-      }
-    ]
-  }
-}
 
 # Order by, verify outer symtab is searched according to its own context.
 "select u.id from user u having u.id in (select col2 from user where user.id = u.id order by u.col)"
diff --git a/go/vt/vtgate/planbuilder/testdata/select_cases.txt b/go/vt/vtgate/planbuilder/testdata/select_cases.txt
index cf97d1c8cb..e7d04abdc3 100644
--- a/go/vt/vtgate/planbuilder/testdata/select_cases.txt
+++ b/go/vt/vtgate/planbuilder/testdata/select_cases.txt
@@ -608,6 +608,7 @@ Gen4 plan same as above
     "Vindex": "binary"
   }
 }
+Gen4 plan same as above
 
 # select from dual on sharded keyspace
 "select @@session.auto_increment_increment from user.dual"
@@ -1392,6 +1393,7 @@ Gen4 plan same as above
     "Table": "unsharded"
   }
 }
+Gen4 plan same as above
 
 "select id from unsharded union select id from unsharded_auto union select id from unsharded_auto where id in (132)"
 {
@@ -1409,6 +1411,7 @@ Gen4 plan same as above
     "Table": "unsharded"
   }
 }
+Gen4 plan same as above
 
 "(select id from unsharded union select id from unsharded_auto) union (select id from unsharded_auto union select name from unsharded)"
 {
@@ -1426,6 +1429,7 @@ Gen4 plan same as above
     "Table": "unsharded"
   }
 }
+Gen4 plan same as above
 
 "(select id from unsharded order by id asc limit 1) union (select id from unsharded order by id desc limit 1) order by id asc limit 1"
 {
@@ -1443,6 +1447,7 @@ Gen4 plan same as above
     "Table": "unsharded"
   }
 }
+Gen4 plan same as above
 
 # routing rules: ensure directives are not lost
 "select /*vt+ QUERY_TIMEOUT_MS=1000 */ * from route2"
@@ -1755,6 +1760,7 @@ Gen4 plan same as above
 # Union after into outfile is incorrect
 "select id from user into outfile 'out_file_name' union all select id from music"
 "Incorrect usage/placement of 'INTO'"
+Gen4 plan same as above
 
 # Into outfile s3 in sub-query is incorrect
 "select id from (select id from user into outfile s3 'inner_outfile') as t2"
@@ -1854,34 +1860,4 @@ Gen4 plan same as above
   }
 }
 
-"((((select 1))))"
-{
-  "QueryType": "SELECT",
-  "Original": "((((select 1))))",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectReference",
-    "Keyspace": {
-      "Name": "main",
-      "Sharded": false
-    },
-    "FieldQuery": "((((select 1 from dual where 1 != 1))))",
-    "Query": "((((select 1 from dual))))",
-    "Table": "dual"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "((((select 1))))",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectReference",
-    "Keyspace": {
-      "Name": "main",
-      "Sharded": false
-    },
-    "FieldQuery": "select 1 from dual where 1 != 1",
-    "Query": "select 1 from dual",
-    "Table": "dual"
-  }
-}
+
diff --git a/go/vt/vtgate/planbuilder/testdata/systemtables_cases.txt b/go/vt/vtgate/planbuilder/testdata/systemtables_cases.txt
index 1a145b2bfb..20efcd45f2 100644
--- a/go/vt/vtgate/planbuilder/testdata/systemtables_cases.txt
+++ b/go/vt/vtgate/planbuilder/testdata/systemtables_cases.txt
@@ -145,85 +145,6 @@ Gen4 plan same as above
 }
 Gen4 plan same as above
 
-# union between information_schema tables that should not be merged
-"select * from information_schema.tables where table_schema = 'user' union select * from information_schema.tables where table_schema = 'main'"
-{
-  "QueryType": "SELECT",
-  "Original": "select * from information_schema.tables where table_schema = 'user' union select * from information_schema.tables where table_schema = 'main'",
-  "Instructions": {
-    "OperatorType": "Distinct",
-    "Inputs": [
-      {
-        "OperatorType": "Concatenate",
-        "Inputs": [
-          {
-            "OperatorType": "Route",
-            "Variant": "SelectDBA",
-            "Keyspace": {
-              "Name": "main",
-              "Sharded": false
-            },
-            "FieldQuery": "select * from information_schema.`tables` where 1 != 1",
-            "Query": "select * from information_schema.`tables` where table_schema = :__vtschemaname",
-            "SysTableTableSchema": "[VARBINARY(\"user\")]",
-            "Table": "information_schema.`tables`"
-          },
-          {
-            "OperatorType": "Route",
-            "Variant": "SelectDBA",
-            "Keyspace": {
-              "Name": "main",
-              "Sharded": false
-            },
-            "FieldQuery": "select * from information_schema.`tables` where 1 != 1",
-            "Query": "select * from information_schema.`tables` where table_schema = :__vtschemaname",
-            "SysTableTableSchema": "[VARBINARY(\"main\")]",
-            "Table": "information_schema.`tables`"
-          }
-        ]
-      }
-    ]
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select * from information_schema.tables where table_schema = 'user' union select * from information_schema.tables where table_schema = 'main'",
-  "Instructions": {
-    "OperatorType": "Distinct",
-    "Inputs": [
-      {
-        "OperatorType": "Concatenate",
-        "Inputs": [
-          {
-            "OperatorType": "Route",
-            "Variant": "SelectDBA",
-            "Keyspace": {
-              "Name": "main",
-              "Sharded": false
-            },
-            "FieldQuery": "select * from information_schema.`tables` where 1 != 1",
-            "Query": "select distinct * from information_schema.`tables` where table_schema = :__vtschemaname",
-            "SysTableTableSchema": "[VARBINARY(\"user\")]",
-            "Table": "information_schema.`tables`"
-          },
-          {
-            "OperatorType": "Route",
-            "Variant": "SelectDBA",
-            "Keyspace": {
-              "Name": "main",
-              "Sharded": false
-            },
-            "FieldQuery": "select * from information_schema.`tables` where 1 != 1",
-            "Query": "select distinct * from information_schema.`tables` where table_schema = :__vtschemaname",
-            "SysTableTableSchema": "[VARBINARY(\"main\")]",
-            "Table": "information_schema.`tables`"
-          }
-        ]
-      }
-    ]
-  }
-}
-
 # Select from information schema query with two tables that route should be merged
 "SELECT DELETE_RULE, UPDATE_RULE FROM  INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KCU INNER JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS AS RC ON KCU.CONSTRAINT_NAME = RC.CONSTRAINT_NAME WHERE KCU.TABLE_SCHEMA = 'test' AND KCU.TABLE_NAME = 'data_type_table' AND KCU.COLUMN_NAME = 'id' AND KCU.REFERENCED_TABLE_SCHEMA = 'test' AND KCU.CONSTRAINT_NAME = 'data_type_table_id_fkey' ORDER BY KCU.CONSTRAINT_NAME, KCU.COLUMN_NAME"
 {
diff --git a/go/vt/vtgate/planbuilder/testdata/tpcc_cases.txt b/go/vt/vtgate/planbuilder/testdata/tpcc_cases.txt
index 5feb186faa..1cdc65a1b2 100644
--- a/go/vt/vtgate/planbuilder/testdata/tpcc_cases.txt
+++ b/go/vt/vtgate/planbuilder/testdata/tpcc_cases.txt
@@ -911,25 +911,6 @@ Gen4 plan same as above
     ]
   }
 }
-{
-  "QueryType": "SELECT",
-  "Original": "select o.o_id,o.o_d_id from orders1 o, (select o_c_id,o_w_id,o_d_id,count(distinct o_w_id),o_id from orders1 where o_w_id=1  and o_id \u003e 2100 and o_id \u003c 11153 group by o_c_id,o_d_id,o_w_id having count( distinct o_id) \u003e 1 limit 1) t where t.o_w_id=o.o_w_id and t.o_d_id=o.o_d_id and t.o_c_id=o.o_c_id limit 1",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "main",
-      "Sharded": true
-    },
-    "FieldQuery": "select o.o_id, o.o_d_id from orders1 as o, (select o_c_id, o_w_id, o_d_id, count(distinct o_w_id), o_id from orders1 where 1 != 1) as t where 1 != 1",
-    "Query": "select o.o_id, o.o_d_id from orders1 as o, (select o_c_id, o_w_id, o_d_id, count(distinct o_w_id), o_id from orders1 where o_w_id = 1 and o_id \u003e 2100 and o_id \u003c 11153) as t where t.o_w_id = o.o_w_id and t.o_d_id = o.o_d_id and t.o_c_id = o.o_c_id limit 1",
-    "Table": "orders1",
-    "Values": [
-      1
-    ],
-    "Vindex": "hash"
-  }
-}
 
 # TPC-C delete order_line1
 "DELETE FROM order_line1 where ol_w_id=178 AND ol_d_id=1 AND ol_o_id=84"
diff --git a/go/vt/vtgate/planbuilder/testdata/tpch_cases.txt b/go/vt/vtgate/planbuilder/testdata/tpch_cases.txt
index a4d14fe5a0..2ae36cf83d 100644
--- a/go/vt/vtgate/planbuilder/testdata/tpch_cases.txt
+++ b/go/vt/vtgate/planbuilder/testdata/tpch_cases.txt
@@ -727,7 +727,7 @@ Gen4 plan same as above
 # TPC-H query 21
 "select s_name, count(*) as numwait from supplier, lineitem l1, orders, nation where s_suppkey = l1.l_suppkey and o_orderkey = l1.l_orderkey and o_orderstatus = 'F' and l1.l_receiptdate > l1.l_commitdate and exists ( select * from lineitem l2 where l2.l_orderkey = l1.l_orderkey and l2.l_suppkey <> l1.l_suppkey ) and not exists ( select * from lineitem l3 where l3.l_orderkey = l1.l_orderkey and l3.l_suppkey <> l1.l_suppkey and l3.l_receiptdate > l3.l_commitdate ) and s_nationkey = n_nationkey and n_name = 'SAUDI ARABIA' group by s_name order by numwait desc, s_name limit 100"
 "unsupported: cross-shard query with aggregates"
-Gen4 plan same as above
+"gen4 does not yet support: *sqlparser.StarExpr in select list"
 
 # TPC-H query 22
 "select cntrycode, count(*) as numcust, sum(c_acctbal) as totacctbal from ( select substring(c_phone from 1 for 2) as cntrycode, c_acctbal from customer where substring(c_phone from 1 for 2) in ('13', '31', '23', '29', '30', '18', '17') and c_acctbal > ( select avg(c_acctbal) from customer where c_acctbal > 0.00 and substring(c_phone from 1 for 2) in ('13', '31', '23', '29', '30', '18', '17') ) and not exists ( select * from orders where o_custkey = c_custkey ) ) as custsale group by cntrycode order by cntrycode"
diff --git a/go/vt/vtgate/planbuilder/testdata/union_cases.txt b/go/vt/vtgate/planbuilder/testdata/union_cases.txt
index f2aefbad3e..a746ecba78 100644
--- a/go/vt/vtgate/planbuilder/testdata/union_cases.txt
+++ b/go/vt/vtgate/planbuilder/testdata/union_cases.txt
@@ -55,26 +55,7 @@ Gen4 plan same as above
     ]
   }
 }
-{
-  "QueryType": "SELECT",
-  "Original": "select id from user union select id from music",
-  "Instructions": {
-    "OperatorType": "Distinct",
-    "Inputs": [
-      {
-        "OperatorType": "Route",
-        "Variant": "SelectScatter",
-        "Keyspace": {
-          "Name": "user",
-          "Sharded": true
-        },
-        "FieldQuery": "select id from `user` where 1 != 1 union select id from music where 1 != 1",
-        "Query": "select id from `user` union select id from music",
-        "Table": "`user`"
-      }
-    ]
-  }
-}
+Gen4 plan same as above
 
 # union all between two SelectEqualUnique
 "select id from user where id = 1 union all select id from user where id = 5"
@@ -207,25 +188,6 @@ Gen4 plan same as above
   }
 }
 
-# union operations in derived table, without star expression (FROM)¡
-"select col1,col2 from (select col1, col2 from user union all select col1, col2 from user_extra) as t"
-{
-  "QueryType": "SELECT",
-  "Original": "select col1,col2 from (select col1, col2 from user union all select col1, col2 from user_extra) as t",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectScatter",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select col1, col2 from (select col1, col2 from `user` where 1 != 1 union all select col1, col2 from user_extra where 1 != 1) as t where 1 != 1",
-    "Query": "select col1, col2 from (select col1, col2 from `user` union all select col1, col2 from user_extra) as t",
-    "Table": "`user`"
-  }
-}
-Gen4 plan same as above
-
 # union all between two scatter selects, with order by
 "(select id from user order by id limit 5) union all (select id from music order by id desc limit 5)"
 {
@@ -354,42 +316,7 @@ Gen4 plan same as above
     ]
   }
 }
-{
-  "QueryType": "SELECT",
-  "Original": "select * from information_schema.a union select * from unsharded",
-  "Instructions": {
-    "OperatorType": "Distinct",
-    "Inputs": [
-      {
-        "OperatorType": "Concatenate",
-        "Inputs": [
-          {
-            "OperatorType": "Route",
-            "Variant": "SelectDBA",
-            "Keyspace": {
-              "Name": "main",
-              "Sharded": false
-            },
-            "FieldQuery": "select * from information_schema.a where 1 != 1",
-            "Query": "select distinct * from information_schema.a",
-            "Table": "information_schema.a"
-          },
-          {
-            "OperatorType": "Route",
-            "Variant": "SelectUnsharded",
-            "Keyspace": {
-              "Name": "main",
-              "Sharded": false
-            },
-            "FieldQuery": "select * from unsharded where 1 != 1",
-            "Query": "select distinct * from unsharded",
-            "Table": "unsharded"
-          }
-        ]
-      }
-    ]
-  }
-}
+Gen4 plan same as above
 
 # union of information_schema with normal table
 "select * from unsharded union select * from information_schema.a"
@@ -429,42 +356,7 @@ Gen4 plan same as above
     ]
   }
 }
-{
-  "QueryType": "SELECT",
-  "Original": "select * from unsharded union select * from information_schema.a",
-  "Instructions": {
-    "OperatorType": "Distinct",
-    "Inputs": [
-      {
-        "OperatorType": "Concatenate",
-        "Inputs": [
-          {
-            "OperatorType": "Route",
-            "Variant": "SelectUnsharded",
-            "Keyspace": {
-              "Name": "main",
-              "Sharded": false
-            },
-            "FieldQuery": "select * from unsharded where 1 != 1",
-            "Query": "select distinct * from unsharded",
-            "Table": "unsharded"
-          },
-          {
-            "OperatorType": "Route",
-            "Variant": "SelectDBA",
-            "Keyspace": {
-              "Name": "main",
-              "Sharded": false
-            },
-            "FieldQuery": "select * from information_schema.a where 1 != 1",
-            "Query": "select distinct * from information_schema.a",
-            "Table": "information_schema.a"
-          }
-        ]
-      }
-    ]
-  }
-}
+Gen4 plan same as above
 
 # multi-shard union
 "(select id from user union select id from music) union select 1 from dual"
@@ -525,42 +417,7 @@ Gen4 plan same as above
     ]
   }
 }
-{
-  "QueryType": "SELECT",
-  "Original": "(select id from user union select id from music) union select 1 from dual",
-  "Instructions": {
-    "OperatorType": "Distinct",
-    "Inputs": [
-      {
-        "OperatorType": "Concatenate",
-        "Inputs": [
-          {
-            "OperatorType": "Route",
-            "Variant": "SelectScatter",
-            "Keyspace": {
-              "Name": "user",
-              "Sharded": true
-            },
-            "FieldQuery": "select id from `user` where 1 != 1 union select id from music where 1 != 1",
-            "Query": "select id from `user` union select id from music",
-            "Table": "`user`"
-          },
-          {
-            "OperatorType": "Route",
-            "Variant": "SelectReference",
-            "Keyspace": {
-              "Name": "main",
-              "Sharded": false
-            },
-            "FieldQuery": "select 1 from dual where 1 != 1",
-            "Query": "select distinct 1 from dual",
-            "Table": "dual"
-          }
-        ]
-      }
-    ]
-  }
-}
+Gen4 plan same as above
 
 # multi-shard union
 "select 1 from music union (select id from user union all select name from unsharded)"
@@ -616,58 +473,7 @@ Gen4 plan same as above
     ]
   }
 }
-{
-  "QueryType": "SELECT",
-  "Original": "select 1 from music union (select id from user union all select name from unsharded)",
-  "Instructions": {
-    "OperatorType": "Distinct",
-    "Inputs": [
-      {
-        "OperatorType": "Concatenate",
-        "Inputs": [
-          {
-            "OperatorType": "Route",
-            "Variant": "SelectScatter",
-            "Keyspace": {
-              "Name": "user",
-              "Sharded": true
-            },
-            "FieldQuery": "select 1 from music where 1 != 1",
-            "Query": "select distinct 1 from music",
-            "Table": "music"
-          },
-          {
-            "OperatorType": "Concatenate",
-            "Inputs": [
-              {
-                "OperatorType": "Route",
-                "Variant": "SelectScatter",
-                "Keyspace": {
-                  "Name": "user",
-                  "Sharded": true
-                },
-                "FieldQuery": "select id from `user` where 1 != 1",
-                "Query": "select distinct id from `user`",
-                "Table": "`user`"
-              },
-              {
-                "OperatorType": "Route",
-                "Variant": "SelectUnsharded",
-                "Keyspace": {
-                  "Name": "main",
-                  "Sharded": false
-                },
-                "FieldQuery": "select `name` from unsharded where 1 != 1",
-                "Query": "select distinct `name` from unsharded",
-                "Table": "unsharded"
-              }
-            ]
-          }
-        ]
-      }
-    ]
-  }
-}
+Gen4 plan same as above
 
 # multi-shard union
 "select 1 from music union (select id from user union select name from unsharded)"
@@ -728,63 +534,7 @@ Gen4 plan same as above
     ]
   }
 }
-{
-  "QueryType": "SELECT",
-  "Original": "select 1 from music union (select id from user union select name from unsharded)",
-  "Instructions": {
-    "OperatorType": "Distinct",
-    "Inputs": [
-      {
-        "OperatorType": "Concatenate",
-        "Inputs": [
-          {
-            "OperatorType": "Route",
-            "Variant": "SelectScatter",
-            "Keyspace": {
-              "Name": "user",
-              "Sharded": true
-            },
-            "FieldQuery": "select 1 from music where 1 != 1",
-            "Query": "select distinct 1 from music",
-            "Table": "music"
-          },
-          {
-            "OperatorType": "Distinct",
-            "Inputs": [
-              {
-                "OperatorType": "Concatenate",
-                "Inputs": [
-                  {
-                    "OperatorType": "Route",
-                    "Variant": "SelectScatter",
-                    "Keyspace": {
-                      "Name": "user",
-                      "Sharded": true
-                    },
-                    "FieldQuery": "select id from `user` where 1 != 1",
-                    "Query": "select distinct id from `user`",
-                    "Table": "`user`"
-                  },
-                  {
-                    "OperatorType": "Route",
-                    "Variant": "SelectUnsharded",
-                    "Keyspace": {
-                      "Name": "main",
-                      "Sharded": false
-                    },
-                    "FieldQuery": "select `name` from unsharded where 1 != 1",
-                    "Query": "select distinct `name` from unsharded",
-                    "Table": "unsharded"
-                  }
-                ]
-              }
-            ]
-          }
-        ]
-      }
-    ]
-  }
-}
+Gen4 plan same as above
 
 # union with the same target shard because of vindex
 "select * from music where id = 1 union select * from user where id = 1"
@@ -832,9 +582,13 @@ Gen4 plan same as above
     ]
   }
 }
+Gen4 plan same as above
+
+# union with different target shards
+"select 1 from music where id = 1 union select 1 from music where id = 2"
 {
   "QueryType": "SELECT",
-  "Original": "select * from music where id = 1 union select * from user where id = 1",
+  "Original": "select 1 from music where id = 1 union select 1 from music where id = 2",
   "Instructions": {
     "OperatorType": "Distinct",
     "Inputs": [
@@ -848,8 +602,8 @@ Gen4 plan same as above
               "Name": "user",
               "Sharded": true
             },
-            "FieldQuery": "select * from music where 1 != 1",
-            "Query": "select distinct * from music where id = 1",
+            "FieldQuery": "select 1 from music where 1 != 1",
+            "Query": "select 1 from music where id = 1",
             "Table": "music",
             "Values": [
               1
@@ -863,100 +617,9 @@ Gen4 plan same as above
               "Name": "user",
               "Sharded": true
             },
-            "FieldQuery": "select * from `user` where 1 != 1",
-            "Query": "select distinct * from `user` where id = 1",
-            "Table": "`user`",
-            "Values": [
-              1
-            ],
-            "Vindex": "user_index"
-          }
-        ]
-      }
-    ]
-  }
-}
-
-# union with different target shards
-"select 1 from music where id = 1 union select 1 from music where id = 2"
-{
-  "QueryType": "SELECT",
-  "Original": "select 1 from music where id = 1 union select 1 from music where id = 2",
-  "Instructions": {
-    "OperatorType": "Distinct",
-    "Inputs": [
-      {
-        "OperatorType": "Concatenate",
-        "Inputs": [
-          {
-            "OperatorType": "Route",
-            "Variant": "SelectEqualUnique",
-            "Keyspace": {
-              "Name": "user",
-              "Sharded": true
-            },
-            "FieldQuery": "select 1 from music where 1 != 1",
-            "Query": "select 1 from music where id = 1",
-            "Table": "music",
-            "Values": [
-              1
-            ],
-            "Vindex": "music_user_map"
-          },
-          {
-            "OperatorType": "Route",
-            "Variant": "SelectEqualUnique",
-            "Keyspace": {
-              "Name": "user",
-              "Sharded": true
-            },
-            "FieldQuery": "select 1 from music where 1 != 1",
-            "Query": "select 1 from music where id = 2",
-            "Table": "music",
-            "Values": [
-              2
-            ],
-            "Vindex": "music_user_map"
-          }
-        ]
-      }
-    ]
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select 1 from music where id = 1 union select 1 from music where id = 2",
-  "Instructions": {
-    "OperatorType": "Distinct",
-    "Inputs": [
-      {
-        "OperatorType": "Concatenate",
-        "Inputs": [
-          {
-            "OperatorType": "Route",
-            "Variant": "SelectEqualUnique",
-            "Keyspace": {
-              "Name": "user",
-              "Sharded": true
-            },
-            "FieldQuery": "select 1 from music where 1 != 1",
-            "Query": "select distinct 1 from music where id = 1",
-            "Table": "music",
-            "Values": [
-              1
-            ],
-            "Vindex": "music_user_map"
-          },
-          {
-            "OperatorType": "Route",
-            "Variant": "SelectEqualUnique",
-            "Keyspace": {
-              "Name": "user",
-              "Sharded": true
-            },
-            "FieldQuery": "select 1 from music where 1 != 1",
-            "Query": "select distinct 1 from music where id = 2",
-            "Table": "music",
+            "FieldQuery": "select 1 from music where 1 != 1",
+            "Query": "select 1 from music where id = 2",
+            "Table": "music",
             "Values": [
               2
             ],
@@ -967,6 +630,7 @@ Gen4 plan same as above
     ]
   }
 }
+Gen4 plan same as above
 
 # multiple select statement have inner order by with union - TODO (systay) no need to send down ORDER BY if we are going to loose it with UNION DISTINCT
 "(select 1 from user order by 1 desc) union (select 1 from user order by 1 asc)"
@@ -1010,6 +674,7 @@ Gen4 plan same as above
     ]
   }
 }
+Gen4 plan same as above
 
 # multiple unions
 "select 1 union select null union select 1.0 union select '1' union select 2 union select 2.0 from user"
@@ -1049,6 +714,7 @@ Gen4 plan same as above
     ]
   }
 }
+Gen4 plan same as above
 
 # union distinct between a scatter query and a join (other side)
 "(select user.id, user.name from user join user_extra where user_extra.extra = 'asdf') union select 'b','c' from user"
@@ -1107,61 +773,7 @@ Gen4 plan same as above
     ]
   }
 }
-{
-  "QueryType": "SELECT",
-  "Original": "(select user.id, user.name from user join user_extra where user_extra.extra = 'asdf') union select 'b','c' from user",
-  "Instructions": {
-    "OperatorType": "Distinct",
-    "Inputs": [
-      {
-        "OperatorType": "Concatenate",
-        "Inputs": [
-          {
-            "OperatorType": "Join",
-            "Variant": "Join",
-            "JoinColumnIndexes": "-1,-2",
-            "TableName": "`user`_user_extra",
-            "Inputs": [
-              {
-                "OperatorType": "Route",
-                "Variant": "SelectScatter",
-                "Keyspace": {
-                  "Name": "user",
-                  "Sharded": true
-                },
-                "FieldQuery": "select `user`.id, `user`.`name` from `user` where 1 != 1",
-                "Query": "select `user`.id, `user`.`name` from `user`",
-                "Table": "`user`"
-              },
-              {
-                "OperatorType": "Route",
-                "Variant": "SelectScatter",
-                "Keyspace": {
-                  "Name": "user",
-                  "Sharded": true
-                },
-                "FieldQuery": "select 1 from user_extra where 1 != 1",
-                "Query": "select 1 from user_extra where user_extra.extra = 'asdf'",
-                "Table": "user_extra"
-              }
-            ]
-          },
-          {
-            "OperatorType": "Route",
-            "Variant": "SelectScatter",
-            "Keyspace": {
-              "Name": "user",
-              "Sharded": true
-            },
-            "FieldQuery": "select 'b', 'c' from `user` where 1 != 1",
-            "Query": "select distinct 'b', 'c' from `user`",
-            "Table": "`user`"
-          }
-        ]
-      }
-    ]
-  }
-}
+Gen4 plan same as above
 
 # union distinct between a scatter query and a join (other side)
 "select 'b','c' from user union (select user.id, user.name from user join user_extra where user_extra.extra = 'asdf')"
@@ -1220,169 +832,14 @@ Gen4 plan same as above
     ]
   }
 }
-{
-  "QueryType": "SELECT",
-  "Original": "select 'b','c' from user union (select user.id, user.name from user join user_extra where user_extra.extra = 'asdf')",
-  "Instructions": {
-    "OperatorType": "Distinct",
-    "Inputs": [
-      {
-        "OperatorType": "Concatenate",
-        "Inputs": [
-          {
-            "OperatorType": "Route",
-            "Variant": "SelectScatter",
-            "Keyspace": {
-              "Name": "user",
-              "Sharded": true
-            },
-            "FieldQuery": "select 'b', 'c' from `user` where 1 != 1",
-            "Query": "select distinct 'b', 'c' from `user`",
-            "Table": "`user`"
-          },
-          {
-            "OperatorType": "Join",
-            "Variant": "Join",
-            "JoinColumnIndexes": "-1,-2",
-            "TableName": "`user`_user_extra",
-            "Inputs": [
-              {
-                "OperatorType": "Route",
-                "Variant": "SelectScatter",
-                "Keyspace": {
-                  "Name": "user",
-                  "Sharded": true
-                },
-                "FieldQuery": "select `user`.id, `user`.`name` from `user` where 1 != 1",
-                "Query": "select `user`.id, `user`.`name` from `user`",
-                "Table": "`user`"
-              },
-              {
-                "OperatorType": "Route",
-                "Variant": "SelectScatter",
-                "Keyspace": {
-                  "Name": "user",
-                  "Sharded": true
-                },
-                "FieldQuery": "select 1 from user_extra where 1 != 1",
-                "Query": "select 1 from user_extra where user_extra.extra = 'asdf'",
-                "Table": "user_extra"
-              }
-            ]
-          }
-        ]
-      }
-    ]
-  }
-}
-
-# unmergable because we are using aggregation
-"select count(*) as s from user union select count(*) as s from music"
-{
-  "QueryType": "SELECT",
-  "Original": "select count(*) as s from user union select count(*) as s from music",
-  "Instructions": {
-    "OperatorType": "Distinct",
-    "Inputs": [
-      {
-        "OperatorType": "Concatenate",
-        "Inputs": [
-          {
-            "OperatorType": "Aggregate",
-            "Variant": "Ordered",
-            "Aggregates": "count(0)",
-            "Inputs": [
-              {
-                "OperatorType": "Route",
-                "Variant": "SelectScatter",
-                "Keyspace": {
-                  "Name": "user",
-                  "Sharded": true
-                },
-                "FieldQuery": "select count(*) as s from `user` where 1 != 1",
-                "Query": "select count(*) as s from `user`",
-                "Table": "`user`"
-              }
-            ]
-          },
-          {
-            "OperatorType": "Aggregate",
-            "Variant": "Ordered",
-            "Aggregates": "count(0)",
-            "Inputs": [
-              {
-                "OperatorType": "Route",
-                "Variant": "SelectScatter",
-                "Keyspace": {
-                  "Name": "user",
-                  "Sharded": true
-                },
-                "FieldQuery": "select count(*) as s from music where 1 != 1",
-                "Query": "select count(*) as s from music",
-                "Table": "music"
-              }
-            ]
-          }
-        ]
-      }
-    ]
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select count(*) as s from user union select count(*) as s from music",
-  "Instructions": {
-    "OperatorType": "Distinct",
-    "Inputs": [
-      {
-        "OperatorType": "Concatenate",
-        "Inputs": [
-          {
-            "OperatorType": "Aggregate",
-            "Variant": "Ordered",
-            "Aggregates": "count(0) AS s",
-            "Inputs": [
-              {
-                "OperatorType": "Route",
-                "Variant": "SelectScatter",
-                "Keyspace": {
-                  "Name": "user",
-                  "Sharded": true
-                },
-                "FieldQuery": "select count(*) as s from `user` where 1 != 1",
-                "Query": "select count(*) as s from `user`",
-                "Table": "`user`"
-              }
-            ]
-          },
-          {
-            "OperatorType": "Aggregate",
-            "Variant": "Ordered",
-            "Aggregates": "count(0) AS s",
-            "Inputs": [
-              {
-                "OperatorType": "Route",
-                "Variant": "SelectScatter",
-                "Keyspace": {
-                  "Name": "user",
-                  "Sharded": true
-                },
-                "FieldQuery": "select count(*) as s from music where 1 != 1",
-                "Query": "select count(*) as s from music",
-                "Table": "music"
-              }
-            ]
-          }
-        ]
-      }
-    ]
-  }
-}
+Gen4 plan same as above
 
 # ambiguous LIMIT
 "select id from user limit 1 union all select id from music limit 1"
 "Incorrect usage of UNION and LIMIT - add parens to disambiguate your query (errno 1221) (sqlstate 21000)"
+Gen4 plan same as above
 
 # different number of columns
 "select id, 42 from user where id = 1 union all select id from user where id = 5"
 "The used SELECT statements have a different number of columns (errno 1222) (sqlstate 21000) during query: select id, 42 from `user` where id = 1 union all select id from `user` where id = 5"
+Gen4 plan same as above
diff --git a/go/vt/vtgate/planbuilder/testdata/unsupported_cases.txt b/go/vt/vtgate/planbuilder/testdata/unsupported_cases.txt
index 0e2ee7b306..1cdf561574 100644
--- a/go/vt/vtgate/planbuilder/testdata/unsupported_cases.txt
+++ b/go/vt/vtgate/planbuilder/testdata/unsupported_cases.txt
@@ -360,10 +360,12 @@ Gen4 plan same as above
 # order by inside and outside parenthesis select
 "(select 1 from user order by 1 desc) order by 1 asc limit 2"
 "can't do ORDER BY on top of ORDER BY"
+Gen4 plan same as above
 
 # ambiguous ORDER BY
 "select id from user order by id union all select id from music order by id desc"
 "Incorrect usage of UNION and ORDER BY - add parens to disambiguate your query (errno 1221) (sqlstate 21000)"
+Gen4 plan same as above
 
 # select get_lock with non-dual table
 "select get_lock('xyz', 10) from user"
@@ -383,6 +385,7 @@ Gen4 plan same as above
 # union with SQL_CALC_FOUND_ROWS 
 "(select sql_calc_found_rows id from user where id = 1 limit 1) union select id from user where id = 1"
 "SQL_CALC_FOUND_ROWS not supported with union"
+Gen4 plan same as above
 
 # set with DEFAULT - vitess aware
 "set workload = default"
diff --git a/go/vt/vtgate/semantics/analyzer_test.go b/go/vt/vtgate/semantics/analyzer_test.go
index 1a33793f94..0164cd7d01 100644
--- a/go/vt/vtgate/semantics/analyzer_test.go
+++ b/go/vt/vtgate/semantics/analyzer_test.go
@@ -351,27 +351,6 @@ func TestUnion(t *testing.T) {
 	assert.Equal(t, T2, d2)
 }
 
-func TestUnionWithOrderBy(t *testing.T) {
-	query := "select col1 from tabl1 union (select col2 from tabl2) order by 1"
-
-	stmt, semTable := parseAndAnalyze(t, query, "")
-	union, _ := stmt.(*sqlparser.Union)
-	sel1 := union.FirstStatement.(*sqlparser.Select)
-	sel2 := union.UnionSelects[0].Statement.(*sqlparser.ParenSelect).Select.(*sqlparser.Select)
-
-	t1 := sel1.From[0].(*sqlparser.AliasedTableExpr)
-	t2 := sel2.From[0].(*sqlparser.AliasedTableExpr)
-	ts1 := semTable.TableSetFor(t1)
-	ts2 := semTable.TableSetFor(t2)
-	assert.EqualValues(t, 1, ts1)
-	assert.EqualValues(t, 2, ts2)
-
-	d1 := semTable.BaseTableDependencies(extract(sel1, 0))
-	d2 := semTable.BaseTableDependencies(extract(sel2, 0))
-	assert.Equal(t, T1, d1)
-	assert.Equal(t, T2, d2)
-}
-
 func TestBindingMultiTable(t *testing.T) {
 	t.Run("positive tests", func(t *testing.T) {