Repository: vitessio/vitess
Pull request #8393 (2021-06-28 10:39:33)

Delete table reference alias support
<!--
  Thank you for your contribution to the Vitess project.
  How to contribute: https://vitess.io/docs/contributing/
  Please first make sure there is an open Issue to discuss the feature/fix suggested in this PR.
  If this is a new feature, please mark the Issue as "RFC".
 -->

<!-- if this PR is Work in Progress please create it as a Draft Pull Request -->

## Description
<!-- A few sentences describing the overall goals of the pull request's commits. -->
<!-- If this is a bug fix and you think the fix should be backported, please write so. -->

DML queries are rewritten to add a `limit` clause to protect from rogue queries. 
Delete has some special syntax that does not allow the `limit` clause.
To overcome the limitation, a special case of single table reference is rewritten to allow the `limit` clause.

## Related Issue(s)
<!-- List related issues and pull requests. If this PR fixes an issue, please add it using Fixes #????  -->

https://github.com/vitessio/vitess/issues/6854

## Checklist
- [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/mysql/sql_error.go b/go/mysql/sql_error.go
index c9265280e5..43ad76f6fe 100644
--- a/go/mysql/sql_error.go
+++ b/go/mysql/sql_error.go
@@ -179,6 +179,7 @@ var stateToMysqlCode = map[vterrors.State]struct {
 	vterrors.NetPacketTooLarge:            {num: ERNetPacketTooLarge, state: SSNetError},
 	vterrors.NonUniqError:                 {num: ERNonUniq, state: SSConstraintViolation},
 	vterrors.NonUniqTable:                 {num: ERNonUniqTable, state: SSClientError},
+	vterrors.NonUpdateableTable:           {num: ERNonUpdateableTable, state: SSUnknownSQLState},
 	vterrors.QueryInterrupted:             {num: ERQueryInterrupted, state: SSQueryInterrupted},
 	vterrors.SPDoesNotExist:               {num: ERSPDoesNotExist, state: SSClientError},
 	vterrors.SyntaxError:                  {num: ERSyntaxError, state: SSClientError},
diff --git a/go/vt/sqlparser/ast.go b/go/vt/sqlparser/ast.go
index ee4682a04e..35160dbd3c 100644
--- a/go/vt/sqlparser/ast.go
+++ b/go/vt/sqlparser/ast.go
@@ -201,17 +201,16 @@ type (
 		Distinct         bool
 		StraightJoinHint bool
 		SQLCalcFoundRows bool
-		// The From field must be the first AST element of this struct so the rewriter sees it first
-		From        []TableExpr
-		Comments    Comments
-		SelectExprs SelectExprs
-		Where       *Where
-		GroupBy     GroupBy
-		Having      *Where
-		OrderBy     OrderBy
-		Limit       *Limit
-		Lock        Lock
-		Into        *SelectInto
+		From             []TableExpr
+		Comments         Comments
+		SelectExprs      SelectExprs
+		Where            *Where
+		GroupBy          GroupBy
+		Having           *Where
+		OrderBy          OrderBy
+		Limit            *Limit
+		Lock             Lock
+		Into             *SelectInto
 	}
 
 	// SelectInto is a struct that represent the INTO part of a select query
diff --git a/go/vt/vterrors/state.go b/go/vt/vterrors/state.go
index d4ad6eea7e..d83a8b34d8 100644
--- a/go/vt/vterrors/state.go
+++ b/go/vt/vterrors/state.go
@@ -33,6 +33,7 @@ const (
 	IncorrectGlobalLocalVar
 	NonUniqError
 	NonUniqTable
+	NonUpdateableTable
 	SyntaxError
 	WrongGroupField
 	WrongTypeForVar
diff --git a/go/vt/vtgate/planbuilder/delete.go b/go/vt/vtgate/planbuilder/delete.go
index 0a15460332..f4f409dfa6 100644
--- a/go/vt/vtgate/planbuilder/delete.go
+++ b/go/vt/vtgate/planbuilder/delete.go
@@ -26,6 +26,13 @@ import (
 // buildDeletePlan builds the instructions for a DELETE statement.
 func buildDeletePlan(stmt sqlparser.Statement, reservedVars *sqlparser.ReservedVars, vschema ContextVSchema) (engine.Primitive, error) {
 	del := stmt.(*sqlparser.Delete)
+	var err error
+	if len(del.TableExprs) == 1 && len(del.Targets) == 1 {
+		del, err = rewriteSingleTbl(del)
+		if err != nil {
+			return nil, err
+		}
+	}
 	dml, ksidVindex, ksidCol, err := buildDMLPlan(vschema, "delete", del, reservedVars, del.TableExprs, del.Where, del.OrderBy, del.Limit, del.Comments, del.Targets)
 	if err != nil {
 		return nil, err
@@ -53,3 +60,39 @@ func buildDeletePlan(stmt sqlparser.Statement, reservedVars *sqlparser.ReservedV
 
 	return edel, nil
 }
+
+func rewriteSingleTbl(del *sqlparser.Delete) (*sqlparser.Delete, error) {
+	atExpr, ok := del.TableExprs[0].(*sqlparser.AliasedTableExpr)
+	if !ok {
+		return del, nil
+	}
+	if !atExpr.As.IsEmpty() && !sqlparser.EqualsTableIdent(del.Targets[0].Name, atExpr.As) {
+		//Unknown table in MULTI DELETE
+		return nil, vterrors.NewErrorf(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.UnknownTable, "Unknown table '%s' in MULTI DELETE", del.Targets[0].Name.String())
+	}
+
+	tbl, ok := atExpr.Expr.(sqlparser.TableName)
+	if !ok {
+		// derived table
+		return nil, vterrors.NewErrorf(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.NonUpdateableTable, "The target table %s of the DELETE is not updatable", atExpr.As.String())
+	}
+	if atExpr.As.IsEmpty() && !sqlparser.EqualsTableIdent(del.Targets[0].Name, tbl.Name) {
+		//Unknown table in MULTI DELETE
+		return nil, vterrors.NewErrorf(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.UnknownTable, "Unknown table '%s' in MULTI DELETE", del.Targets[0].Name.String())
+	}
+
+	del.TableExprs = sqlparser.TableExprs{&sqlparser.AliasedTableExpr{Expr: tbl}}
+	del.Targets = nil
+	if del.Where != nil {
+		_ = sqlparser.Rewrite(del.Where, func(cursor *sqlparser.Cursor) bool {
+			switch node := cursor.Node().(type) {
+			case *sqlparser.ColName:
+				if !node.Qualifier.IsEmpty() {
+					node.Qualifier = tbl
+				}
+			}
+			return true
+		}, nil)
+	}
+	return del, nil
+}
diff --git a/go/vt/vtgate/planbuilder/join.go b/go/vt/vtgate/planbuilder/join.go
index 30f79b6906..3da977b2c1 100644
--- a/go/vt/vtgate/planbuilder/join.go
+++ b/go/vt/vtgate/planbuilder/join.go
@@ -17,6 +17,8 @@ limitations under the License.
 package planbuilder
 
 import (
+	"errors"
+
 	"vitess.io/vitess/go/vt/vtgate/semantics"
 
 	vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc"
@@ -98,7 +100,7 @@ func newJoin(lpb, rpb *primitiveBuilder, ajoin *sqlparser.JoinTableExpr, reserve
 				return err
 			}
 		case ajoin.Condition.Using != nil:
-			return vterrors.New(vtrpcpb.Code_UNIMPLEMENTED, "unsupported: join with USING(column_list) clause for complex queries")
+			return errors.New("unsupported: join with USING(column_list) clause for complex queries")
 		}
 	}
 	lpb.plan = &join{
diff --git a/go/vt/vtgate/planbuilder/jointree.go b/go/vt/vtgate/planbuilder/jointree.go
index ade239ea61..49295e96c4 100644
--- a/go/vt/vtgate/planbuilder/jointree.go
+++ b/go/vt/vtgate/planbuilder/jointree.go
@@ -141,31 +141,20 @@ func (p parenTables) tableID() semantics.TableSet {
 }
 
 // visit will traverse the route tables, going inside parenTables and visiting all routeTables
-func visitTables(r relation, f func(tbl *routeTable) error) error {
-	switch r := r.(type) {
-	case *routeTable:
-		err := f(r)
-		if err != nil {
-			return err
-		}
-	case parenTables:
-		for _, r := range r {
-			err := visitTables(r, f)
+func (p parenTables) visit(f func(tbl *routeTable) error) error {
+	for _, r := range p {
+		switch r := r.(type) {
+		case *routeTable:
+			err := f(r)
+			if err != nil {
+				return err
+			}
+		case parenTables:
+			err := r.visit(f)
 			if err != nil {
 				return err
 			}
 		}
-		return nil
-	case *leJoin:
-		err := visitTables(r.lhs, f)
-		if err != nil {
-			return err
-		}
-		err = visitTables(r.rhs, f)
-		if err != nil {
-			return err
-		}
-		return nil
 	}
 	return nil
 }
@@ -366,7 +355,11 @@ func (rp *routePlan) planEqualOp(node *sqlparser.ComparisonExpr) (bool, error) {
 	return rp.haveMatchingVindex(node, column, *val, equalOrEqualUnique, justTheVindex), err
 }
 
-func (rp *routePlan) planSimpleInOp(node *sqlparser.ComparisonExpr, left *sqlparser.ColName) (bool, error) {
+func (rp *routePlan) planInOp(node *sqlparser.ComparisonExpr) (bool, error) {
+	column, ok := node.Left.(*sqlparser.ColName)
+	if !ok {
+		return false, nil
+	}
 	value, err := sqlparser.NewPlanValue(node.Right)
 	if err != nil {
 		// if we are unable to create a PlanValue, we can't use a vindex, but we don't have to fail
@@ -384,70 +377,7 @@ func (rp *routePlan) planSimpleInOp(node *sqlparser.ComparisonExpr, left *sqlpar
 		}
 	}
 	opcode := func(*vindexes.ColumnVindex) engine.RouteOpcode { return engine.SelectIN }
-	return rp.haveMatchingVindex(node, left, value, opcode, justTheVindex), err
-}
-
-func (rp *routePlan) planCompositeInOp(node *sqlparser.ComparisonExpr, left sqlparser.ValTuple) (bool, error) {
-	right, rightIsValTuple := node.Right.(sqlparser.ValTuple)
-	if !rightIsValTuple {
-		return false, nil
-	}
-	return rp.planCompositeInOpRecursive(node, left, right, nil)
-}
-
-func (rp *routePlan) planCompositeInOpRecursive(node *sqlparser.ComparisonExpr, left, right sqlparser.ValTuple, coordinates []int) (bool, error) {
-	foundVindex := false
-	cindex := len(coordinates)
-	coordinates = append(coordinates, 0)
-	for i, expr := range left {
-		coordinates[cindex] = i
-		switch expr := expr.(type) {
-		case sqlparser.ValTuple:
-			ok, err := rp.planCompositeInOpRecursive(node, expr, right, coordinates)
-			if err != nil {
-				return false, err
-			}
-			return ok || foundVindex, nil
-		case *sqlparser.ColName:
-			// check if left col is a vindex
-			if !rp.hasVindex(expr) {
-				continue
-			}
-
-			rightVals := make(sqlparser.ValTuple, len(right))
-			for j, currRight := range right {
-				switch currRight := currRight.(type) {
-				case sqlparser.ValTuple:
-					val := tupleAccess(currRight, coordinates)
-					if val == nil {
-						return false, nil
-					}
-					rightVals[j] = val
-				default:
-					return false, nil
-				}
-			}
-			newPlanValues, err := makePlanValue(rightVals)
-			if newPlanValues == nil || err != nil {
-				return false, err
-			}
-
-			opcode := func(*vindexes.ColumnVindex) engine.RouteOpcode { return engine.SelectMultiEqual }
-			newVindex := rp.haveMatchingVindex(node, expr, *newPlanValues, opcode, justTheVindex)
-			foundVindex = newVindex || foundVindex
-		}
-	}
-	return foundVindex, nil
-}
-
-func (rp *routePlan) planInOp(node *sqlparser.ComparisonExpr) (bool, error) {
-	switch left := node.Left.(type) {
-	case *sqlparser.ColName:
-		return rp.planSimpleInOp(node, left)
-	case sqlparser.ValTuple:
-		return rp.planCompositeInOp(node, left)
-	}
-	return false, nil
+	return rp.haveMatchingVindex(node, column, value, opcode, justTheVindex), err
 }
 
 func (rp *routePlan) planLikeOp(node *sqlparser.ComparisonExpr) (bool, error) {
@@ -504,17 +434,6 @@ func makePlanValue(n sqlparser.Expr) (*sqltypes.PlanValue, error) {
 	return &value, nil
 }
 
-func (rp routePlan) hasVindex(column *sqlparser.ColName) bool {
-	for _, v := range rp.vindexPreds {
-		for _, col := range v.colVindex.Columns {
-			if column.Name.Equal(col) {
-				return true
-			}
-		}
-	}
-	return false
-}
-
 func (rp *routePlan) haveMatchingVindex(
 	node sqlparser.Expr,
 	column *sqlparser.ColName,
@@ -563,12 +482,7 @@ func (rp *routePlan) pickBestAvailableVindex() {
 
 // Predicates takes all known predicates for this route and ANDs them together
 func (rp *routePlan) Predicates() sqlparser.Expr {
-	predicates := rp.predicates
-	_ = visitTables(rp.tables, func(tbl *routeTable) error {
-		predicates = append(predicates, tbl.qtable.Predicates...)
-		return nil
-	})
-	return sqlparser.AndExpressions(predicates...)
+	return sqlparser.AndExpressions(rp.predicates...)
 }
 
 func (rp *routePlan) pushOutputColumns(col []*sqlparser.ColName, _ *semantics.SemTable) []int {
diff --git a/go/vt/vtgate/planbuilder/jointree_transformers.go b/go/vt/vtgate/planbuilder/jointree_transformers.go
index d828cc0971..b2f1b93d38 100644
--- a/go/vt/vtgate/planbuilder/jointree_transformers.go
+++ b/go/vt/vtgate/planbuilder/jointree_transformers.go
@@ -83,10 +83,7 @@ func transformRoutePlan(n *routePlan) (*route, error) {
 		switch predicate := predicate.(type) {
 		case *sqlparser.ComparisonExpr:
 			if predicate.Operator == sqlparser.InOp {
-				switch predicate.Left.(type) {
-				case *sqlparser.ColName:
-					predicate.Right = sqlparser.ListArg(engine.ListVarName)
-				}
+				predicate.Right = sqlparser.ListArg(engine.ListVarName)
 			}
 		}
 	}
diff --git a/go/vt/vtgate/planbuilder/project.go b/go/vt/vtgate/planbuilder/project.go
index 3a1989cfee..71c1889ee8 100644
--- a/go/vt/vtgate/planbuilder/project.go
+++ b/go/vt/vtgate/planbuilder/project.go
@@ -20,7 +20,7 @@ import (
 	"errors"
 
 	querypb "vitess.io/vitess/go/vt/proto/query"
-	vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc"
+	"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"
@@ -46,7 +46,7 @@ func planProjection(pb *primitiveBuilder, in logicalPlan, expr *sqlparser.Aliase
 		} else {
 			// Pushing of non-trivial expressions not allowed for RHS of left joins.
 			if _, ok := expr.Expr.(*sqlparser.ColName); !ok && node.ejoin.Opcode == engine.LeftJoin {
-				return nil, nil, 0, vterrors.New(vtrpcpb.Code_UNIMPLEMENTED, "unsupported: cross-shard left join and column expressions")
+				return nil, nil, 0, errors.New("unsupported: cross-shard left join and column expressions")
 			}
 
 			newRight, col, colNumber, err := planProjection(pb, node.Right, expr, origin)
@@ -167,5 +167,5 @@ func planProjection(pb *primitiveBuilder, in logicalPlan, expr *sqlparser.Aliase
 		return node, rc, len(node.resultColumns) - 1, nil
 
 	}
-	return nil, nil, 0, vterrors.Errorf(vtrpcpb.Code_UNIMPLEMENTED, "[BUG] unreachable %T.projection", in)
+	return nil, nil, 0, vterrors.Errorf(vtrpc.Code_UNIMPLEMENTED, "[BUG] unreachable %T.projection", in)
 }
diff --git a/go/vt/vtgate/planbuilder/route.go b/go/vt/vtgate/planbuilder/route.go
index 418d083e8f..504b73c682 100644
--- a/go/vt/vtgate/planbuilder/route.go
+++ b/go/vt/vtgate/planbuilder/route.go
@@ -727,12 +727,7 @@ func (rb *route) computeCompositeINPlan(pb *primitiveBuilder, comparison *sqlpar
 // iterateCompositeIN recursively walks the LHS tuple of the IN clause looking
 // for column names. For those that match a vindex, it builds a multi-value plan
 // using the corresponding values in the RHS. It returns the best of the plans built.
-func (rb *route) iterateCompositeIN(
-	pb *primitiveBuilder,
-	comparison *sqlparser.ComparisonExpr,
-	coordinates []int,
-	tuple sqlparser.ValTuple,
-) (opcode engine.RouteOpcode, vindex vindexes.SingleColumn, values sqlparser.Expr) {
+func (rb *route) iterateCompositeIN(pb *primitiveBuilder, comparison *sqlparser.ComparisonExpr, coordinates []int, tuple sqlparser.ValTuple) (opcode engine.RouteOpcode, vindex vindexes.SingleColumn, values sqlparser.Expr) {
 	opcode = engine.SelectScatter
 
 	cindex := len(coordinates)
diff --git a/go/vt/vtgate/planbuilder/route_planning.go b/go/vt/vtgate/planbuilder/route_planning.go
index dc687c1b82..be4e7feebe 100644
--- a/go/vt/vtgate/planbuilder/route_planning.go
+++ b/go/vt/vtgate/planbuilder/route_planning.go
@@ -46,11 +46,6 @@ func gen4Planner(_ string) func(sqlparser.Statement, *sqlparser.ReservedVars, Co
 }
 
 func newBuildSelectPlan(sel *sqlparser.Select, vschema ContextVSchema) (engine.Primitive, error) {
-
-	directives := sqlparser.ExtractCommentDirectives(sel.Comments)
-	if len(directives) > 0 {
-		return nil, semantics.Gen4NotSupportedF("comment directives")
-	}
 	keyspace, err := vschema.DefaultKeyspace()
 	if err != nil {
 		return nil, err
@@ -261,10 +256,6 @@ func planLimit(limit *sqlparser.Limit, plan logicalPlan) (logicalPlan, error) {
 
 func planHorizon(sel *sqlparser.Select, plan logicalPlan, semTable *semantics.SemTable) (logicalPlan, error) {
 	rb, ok := plan.(*route)
-	if !ok && semTable.ProjectionErr != nil {
-		return nil, semTable.ProjectionErr
-	}
-
 	if ok && rb.isSingleShard() {
 		createSingleShardRoutePlan(sel, rb)
 		return plan, nil
@@ -279,7 +270,7 @@ func planHorizon(sel *sqlparser.Select, plan logicalPlan, semTable *semantics.Se
 		return nil, err
 	}
 	for _, e := range qp.selectExprs {
-		if _, err := pushProjection(e, plan, semTable, true); err != nil {
+		if _, err := pushProjection(e, plan, semTable); err != nil {
 			return nil, err
 		}
 	}
@@ -634,7 +625,7 @@ func findColumnVindex(a *routePlan, exp sqlparser.Expr, sem *semantics.SemTable)
 
 	var singCol vindexes.SingleColumn
 
-	_ = visitTables(a.tables, func(table *routeTable) error {
+	_ = a.tables.visit(func(table *routeTable) error {
 		if leftDep.IsSolvedBy(table.qtable.TableID) {
 			for _, vindex := range table.vtable.ColumnVindexes {
 				sC, isSingle := vindex.Vindex.(vindexes.SingleColumn)
diff --git a/go/vt/vtgate/planbuilder/selectGen4.go b/go/vt/vtgate/planbuilder/selectGen4.go
index 9e803d1389..aa31244a48 100644
--- a/go/vt/vtgate/planbuilder/selectGen4.go
+++ b/go/vt/vtgate/planbuilder/selectGen4.go
@@ -28,18 +28,9 @@ import (
 	"vitess.io/vitess/go/vt/vtgate/engine"
 )
 
-func pushProjection(expr *sqlparser.AliasedExpr, plan logicalPlan, semTable *semantics.SemTable, inner bool) (int, error) {
+func pushProjection(expr *sqlparser.AliasedExpr, plan logicalPlan, semTable *semantics.SemTable) (int, error) {
 	switch node := plan.(type) {
 	case *route:
-		value, err := makePlanValue(expr.Expr)
-		if err != nil {
-			return 0, err
-		}
-		_, isColName := expr.Expr.(*sqlparser.ColName)
-		badExpr := value == nil && !isColName
-		if !inner && badExpr {
-			return 0, vterrors.New(vtrpcpb.Code_UNIMPLEMENTED, "unsupported: cross-shard left join and column expressions")
-		}
 		sel := node.Select.(*sqlparser.Select)
 		i := checkIfAlreadyExists(expr, sel)
 		if i != -1 {
@@ -56,13 +47,13 @@ func pushProjection(expr *sqlparser.AliasedExpr, plan logicalPlan, semTable *sem
 		deps := semTable.Dependencies(expr.Expr)
 		switch {
 		case deps.IsSolvedBy(lhsSolves):
-			offset, err := pushProjection(expr, node.Left, semTable, inner)
+			offset, err := pushProjection(expr, node.Left, semTable)
 			if err != nil {
 				return 0, err
 			}
 			node.Cols = append(node.Cols, -(offset + 1))
 		case deps.IsSolvedBy(rhsSolves):
-			offset, err := pushProjection(expr, node.Right, semTable, inner && node.Opcode != engine.LeftJoin)
+			offset, err := pushProjection(expr, node.Right, semTable)
 			if err != nil {
 				return 0, err
 			}
@@ -103,7 +94,7 @@ func planAggregations(qp *queryProjection, plan logicalPlan, semTable *semantics
 		eaggr:          eaggr,
 	}
 	for _, e := range qp.aggrExprs {
-		offset, err := pushProjection(e, plan, semTable, true)
+		offset, err := pushProjection(e, plan, semTable)
 		if err != nil {
 			return nil, err
 		}
@@ -132,7 +123,7 @@ func planOrderBy(qp *queryProjection, plan logicalPlan, semTable *semantics.SemT
 					Expr: order.Expr,
 				}
 				var err error
-				offset, err = pushProjection(expr, plan, semTable, true)
+				offset, err = pushProjection(expr, plan, semTable)
 				if err != nil {
 					return nil, err
 				}
@@ -166,7 +157,7 @@ func planOrderBy(qp *queryProjection, plan logicalPlan, semTable *semantics.SemT
 						},
 					},
 				}
-				weightStringOffset, err = pushProjection(expr, plan, semTable, true)
+				weightStringOffset, err = pushProjection(expr, plan, semTable)
 				if err != nil {
 					return nil, err
 				}
diff --git a/go/vt/vtgate/semantics/analyzer.go b/go/vt/vtgate/semantics/analyzer.go
index 0f0c7b4981..8b4993dc1e 100644
--- a/go/vt/vtgate/semantics/analyzer.go
+++ b/go/vt/vtgate/semantics/analyzer.go
@@ -29,15 +29,13 @@ type (
 	analyzer struct {
 		si SchemaInformation
 
-		Tables       []*TableInfo
-		scopes       []*scope
-		exprDeps     map[sqlparser.Expr]TableSet
-		err          error
-		currentDb    string
-		inProjection []bool
+		Tables    []*TableInfo
+		scopes    []*scope
+		exprDeps  map[sqlparser.Expr]TableSet
+		err       error
+		currentDb string
 
 		selectScope map[*sqlparser.Select]*scope
-		projErr     error
 	}
 )
 
@@ -59,65 +57,41 @@ func Analyze(statement sqlparser.Statement, currentDb string, si SchemaInformati
 	if err != nil {
 		return nil, err
 	}
-	return &SemTable{exprDependencies: analyzer.exprDeps, Tables: analyzer.Tables, selectScope: analyzer.selectScope, ProjectionErr: analyzer.projErr}, nil
-}
-
-func (a *analyzer) setError(err error) {
-	if len(a.inProjection) > 0 && vterrors.ErrState(err) == vterrors.NonUniqError {
-		a.projErr = err
-	} else {
-		a.err = err
-	}
+	return &SemTable{exprDependencies: analyzer.exprDeps, Tables: analyzer.Tables, selectScope: analyzer.selectScope}, nil
 }
 
 // analyzeDown pushes new scopes when we encounter sub queries,
 // and resolves the table a column is using
 func (a *analyzer) analyzeDown(cursor *sqlparser.Cursor) bool {
-	// If we have an error we keep on going down the tree without checking for anything else
-	// this way we can abort when we come back up.
-	if !a.shouldContinue() {
-		return true
-	}
 	current := a.currentScope()
 	n := cursor.Node()
 	switch node := n.(type) {
-	case sqlparser.SelectExprs:
-		if isParentSelect(cursor) {
-			a.inProjection = append(a.inProjection, true)
-			fmt.Println(len(a.inProjection))
-		}
 	case *sqlparser.Select:
 		if node.Having != nil {
-			a.setError(Gen4NotSupportedF("HAVING"))
+			a.err = Gen4NotSupportedF("HAVING")
 		}
 		a.push(newScope(current))
 		a.selectScope[node] = a.currentScope()
 	case *sqlparser.DerivedTable:
-		a.setError(Gen4NotSupportedF("derived tables"))
-	case *sqlparser.Subquery:
-		a.setError(Gen4NotSupportedF("subquery"))
+		a.err = Gen4NotSupportedF("derived tables")
 	case sqlparser.TableExpr:
-		if isParentSelect(cursor) {
+		_, isSelect := cursor.Parent().(*sqlparser.Select)
+		if isSelect {
 			a.push(newScope(nil))
 		}
 		switch node := node.(type) {
 		case *sqlparser.AliasedTableExpr:
-			a.setError(a.bindTable(node, node.Expr))
-		case *sqlparser.JoinTableExpr:
-			if node.Condition.Using != nil {
-				a.setError(vterrors.New(vtrpcpb.Code_UNIMPLEMENTED, "unsupported: join with USING(column_list) clause for complex queries"))
-			}
-			if node.Join == sqlparser.NaturalJoinType || node.Join == sqlparser.NaturalRightJoinType || node.Join == sqlparser.NaturalLeftJoinType {
-				a.setError(vterrors.New(vtrpcpb.Code_UNIMPLEMENTED, "unsupported: "+node.Join.ToString()))
-			}
-
+			a.err = a.bindTable(node, node.Expr)
 		}
+
+	// we don't need to push new scope for sub queries since we do that for SELECT and UNION
+
 	case *sqlparser.Union:
 		a.push(newScope(current))
 	case *sqlparser.ColName:
 		t, err := a.resolveColumn(node, current)
 		if err != nil {
-			a.setError(err)
+			a.err = err
 		} else {
 			a.exprDeps[node] = t
 		}
@@ -125,13 +99,13 @@ func (a *analyzer) analyzeDown(cursor *sqlparser.Cursor) bool {
 		if node.Distinct {
 			err := vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "syntax error: %s", sqlparser.String(node))
 			if len(node.Exprs) != 1 {
-				a.setError(err)
+				a.err = err
 			} else if _, ok := node.Exprs[0].(*sqlparser.AliasedExpr); !ok {
-				a.setError(err)
+				a.err = err
 			}
 		}
 		if sqlparser.IsLockingFunc(node) {
-			a.setError(Gen4NotSupportedF("locking functions"))
+			a.err = Gen4NotSupportedF("locking functions")
 		}
 	}
 
@@ -141,11 +115,6 @@ func (a *analyzer) analyzeDown(cursor *sqlparser.Cursor) bool {
 	return true
 }
 
-func isParentSelect(cursor *sqlparser.Cursor) bool {
-	_, isSelect := cursor.Parent().(*sqlparser.Select)
-	return isSelect
-}
-
 func (a *analyzer) resolveColumn(colName *sqlparser.ColName, current *scope) (TableSet, error) {
 	var t *TableInfo
 	var err error
@@ -157,9 +126,6 @@ func (a *analyzer) resolveColumn(colName *sqlparser.ColName, current *scope) (Ta
 	if err != nil {
 		return 0, err
 	}
-	if t == nil {
-		return 0, vterrors.NewErrorf(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.NonUniqError, fmt.Sprintf("Column '%s' in field list is ambiguous", sqlparser.String(colName)))
-	}
 	return a.tableSetFor(t.ASTNode), nil
 }
 
@@ -190,7 +156,7 @@ func (a *analyzer) resolveUnQualifiedColumn(current *scope, expr *sqlparser.ColN
 
 	var tblInfo *TableInfo
 	for _, tbl := range current.tables {
-		if tbl.Table == nil {
+		if tbl.Table == nil || !tbl.Table.ColumnListAuthoritative {
 			return nil, vterrors.NewErrorf(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.NonUniqError, fmt.Sprintf("Column '%s' in field list is ambiguous", sqlparser.String(expr)))
 		}
 		for _, col := range tbl.Table.Columns {
@@ -258,18 +224,12 @@ func (a *analyzer) analyze(statement sqlparser.Statement) error {
 }
 
 func (a *analyzer) analyzeUp(cursor *sqlparser.Cursor) bool {
-	if !a.shouldContinue() {
-		return false
-	}
 	switch cursor.Node().(type) {
-	case sqlparser.SelectExprs:
-		if isParentSelect(cursor) {
-			a.popProjection()
-		}
 	case *sqlparser.Union, *sqlparser.Select:
 		a.popScope()
 	case sqlparser.TableExpr:
-		if isParentSelect(cursor) {
+		_, isSelect := cursor.Parent().(*sqlparser.Select)
+		if isSelect {
 			curScope := a.currentScope()
 			a.popScope()
 			earlierScope := a.currentScope()
@@ -277,7 +237,7 @@ func (a *analyzer) analyzeUp(cursor *sqlparser.Cursor) bool {
 			for _, table := range curScope.tables {
 				err := earlierScope.addTable(table)
 				if err != nil {
-					a.setError(err)
+					a.err = err
 					break
 				}
 			}
@@ -286,10 +246,6 @@ func (a *analyzer) analyzeUp(cursor *sqlparser.Cursor) bool {
 	return a.shouldContinue()
 }
 
-func (a *analyzer) popProjection() {
-	a.inProjection = a.inProjection[:len(a.inProjection)-1]
-}
-
 func (a *analyzer) shouldContinue() bool {
 	return a.err == nil
 }
diff --git a/go/vt/vtgate/semantics/semantic_state.go b/go/vt/vtgate/semantics/semantic_state.go
index 5694f80607..648ad47313 100644
--- a/go/vt/vtgate/semantics/semantic_state.go
+++ b/go/vt/vtgate/semantics/semantic_state.go
@@ -41,10 +41,7 @@ type (
 
 	// SemTable contains semantic analysis information about the query.
 	SemTable struct {
-		Tables []*TableInfo
-		// ProjectionErr stores the error that we got during the semantic analysis of the SelectExprs.
-		// This is only a real error if we are unable to plan the query as a single route
-		ProjectionErr    error
+		Tables           []*TableInfo
 		exprDependencies map[sqlparser.Expr]TableSet
 		selectScope      map[*sqlparser.Select]*scope
 	}


Test patch:
diff --git a/go/mysql/server_test.go b/go/mysql/server_test.go
index c0f9a45922..e6e9eb69cf 100644
--- a/go/mysql/server_test.go
+++ b/go/mysql/server_test.go
@@ -1274,7 +1274,7 @@ func TestServerFlush(t *testing.T) {
 	flds, err := c.Fields()
 	require.NoError(t, err)
 	if duration, want := time.Since(start), 20*time.Millisecond; duration < *mysqlServerFlushDelay || duration > want {
-		assert.Fail(t, "duration: %v, want between %v and %v", duration, *mysqlServerFlushDelay, want)
+		assert.Fail(t, "duration: %v, want between %v and %v", duration.String(), (*mysqlServerFlushDelay).String(), want.String())
 	}
 	want1 := []*querypb.Field{{
 		Name: "result",
diff --git a/go/test/endtoend/vtgate/misc_test.go b/go/test/endtoend/vtgate/misc_test.go
index d4c3d5a794..afce3631a5 100644
--- a/go/test/endtoend/vtgate/misc_test.go
+++ b/go/test/endtoend/vtgate/misc_test.go
@@ -650,6 +650,15 @@ func TestQueryAndSubQWithLimit(t *testing.T) {
 	assert.Equal(t, 10, len(result.Rows))
 }
 
+func TestDeleteAlias(t *testing.T) {
+	conn, err := mysql.Connect(context.Background(), &vtParams)
+	require.NoError(t, err)
+	defer conn.Close()
+
+	exec(t, conn, "delete t1 from t1 where id1 = 1")
+	exec(t, conn, "delete t.* from t1 t where t.id1 = 1")
+}
+
 func assertMatches(t *testing.T, conn *mysql.Conn, query, expected string) {
 	t.Helper()
 	qr := exec(t, conn, query)
diff --git a/go/test/endtoend/vtgate/unsharded/main_test.go b/go/test/endtoend/vtgate/unsharded/main_test.go
index 547b12ef2a..b5209ba3eb 100644
--- a/go/test/endtoend/vtgate/unsharded/main_test.go
+++ b/go/test/endtoend/vtgate/unsharded/main_test.go
@@ -436,6 +436,19 @@ func TestNumericPrecisionScale(t *testing.T) {
 	assert.True(t, qr.Rows[0][1].Type() == sqltypes.Uint64 || qr.Rows[0][1].Type() == sqltypes.Uint32)
 }
 
+func TestDeleteAlias(t *testing.T) {
+	vtParams := mysql.ConnParams{
+		Host: "localhost",
+		Port: clusterInstance.VtgateMySQLPort,
+	}
+	conn, err := mysql.Connect(context.Background(), &vtParams)
+	require.NoError(t, err)
+	defer conn.Close()
+
+	exec(t, conn, "delete t1 from t1 where c1 = 1")
+	exec(t, conn, "delete t.* from t1 t where t.c1 = 1")
+}
+
 func exec(t *testing.T, conn *mysql.Conn, query string) *sqltypes.Result {
 	t.Helper()
 	qr, err := conn.ExecuteFetch(query, 1000, true)
diff --git a/go/vt/sqlparser/parse_test.go b/go/vt/sqlparser/parse_test.go
index 364ccf3935..d7c64db562 100644
--- a/go/vt/sqlparser/parse_test.go
+++ b/go/vt/sqlparser/parse_test.go
@@ -800,6 +800,12 @@ var (
 		input: "delete /* order */ from a order by b desc",
 	}, {
 		input: "delete /* limit */ from a limit b",
+	}, {
+		input:  "delete /* alias where */ t.* from a as t where t.id = 2",
+		output: "delete /* alias where */ t from a as t where t.id = 2",
+	}, {
+		input:  "delete t.* from t, t1",
+		output: "delete t from t, t1",
 	}, {
 		input:  "delete a from a join b on a.id = b.id where b.name = 'test'",
 		output: "delete a from a join b on a.id = b.id where b.`name` = 'test'",
diff --git a/go/vt/vtgate/planbuilder/plan_test.go b/go/vt/vtgate/planbuilder/plan_test.go
index bd78144b73..bb4978f424 100644
--- a/go/vt/vtgate/planbuilder/plan_test.go
+++ b/go/vt/vtgate/planbuilder/plan_test.go
@@ -150,10 +150,7 @@ func init() {
 	vindexes.Register("costly", newCostlyIndex)
 }
 
-const (
-	samePlanMarker  = "Gen4 plan same as above\n"
-	gen4ErrorPrefix = "Gen4 error: "
-)
+const samePlanMarker = "Gen4 plan same as above\n"
 
 func TestPlan(t *testing.T) {
 	vschemaWrapper := &vschemaWrapper{
@@ -238,11 +235,7 @@ func TestWithDefaultKeyspaceFromFile(t *testing.T) {
 	// We are testing this separately so we can set a default keyspace
 	testOutputTempDir, err := ioutil.TempDir("", "plan_test")
 	require.NoError(t, err)
-	defer func() {
-		if !t.Failed() {
-			_ = os.RemoveAll(testOutputTempDir)
-		}
-	}()
+	defer os.RemoveAll(testOutputTempDir)
 	vschema := &vschemaWrapper{
 		v: loadSchema(t, "schema_test.json"),
 		keyspace: &vindexes.Keyspace{
@@ -614,11 +607,9 @@ func iterateExecFile(name string) (testCaseIterator chan testCase) {
 			if err != nil && err != io.EOF {
 				panic(fmt.Sprintf("error reading file %s line# %d: %s", name, lineno, err.Error()))
 			}
-			nextLine := string(binput)
-			switch {
-			case nextLine == samePlanMarker:
+			if len(binput) > 0 && string(binput) == samePlanMarker {
 				output2Planner = output
-			case strings.HasPrefix(nextLine, "{"):
+			} else if len(binput) > 0 && (binput[0] == '"' || binput[0] == '{') {
 				output2Planner = append(output2Planner, binput...)
 				for {
 					l, err := r.ReadBytes('\n')
@@ -636,9 +627,8 @@ func iterateExecFile(name string) (testCaseIterator chan testCase) {
 						break
 					}
 				}
-			case strings.HasPrefix(nextLine, gen4ErrorPrefix):
-				output2Planner = []byte(nextLine[len(gen4ErrorPrefix) : len(nextLine)-1])
 			}
+
 			testCaseIterator <- testCase{
 				file:             name,
 				lineno:           lineno,
diff --git a/go/vt/vtgate/planbuilder/testdata/alterVschema_cases.txt b/go/vt/vtgate/planbuilder/testdata/alterVschema_cases.txt
index 9c3b03523e..7fe1469ddf 100644
--- a/go/vt/vtgate/planbuilder/testdata/alterVschema_cases.txt
+++ b/go/vt/vtgate/planbuilder/testdata/alterVschema_cases.txt
@@ -12,7 +12,6 @@
     "query": "alter vschema create vindex hash_vdx using hash"
   }
 }
-Gen4 plan same as above
 
 # Create vindex with qualifier
 "alter vschema create vindex user.hash_vdx using hash"
@@ -28,7 +27,6 @@ Gen4 plan same as above
     "query": "alter vschema create vindex `user`.hash_vdx using hash"
   }
 }
-Gen4 plan same as above
 
 # Drop vindex
 "alter vschema drop vindex hash_vdx"
@@ -44,7 +42,6 @@ Gen4 plan same as above
     "query": "alter vschema drop vindex hash_vdx"
   }
 }
-Gen4 plan same as above
 
 # Add table
 "alter vschema add table a"
@@ -60,7 +57,6 @@ Gen4 plan same as above
     "query": "alter vschema add table a"
   }
 }
-Gen4 plan same as above
 
 # Add sequence
 "alter vschema add sequence a_seq"
@@ -76,7 +72,6 @@ Gen4 plan same as above
     "query": "alter vschema add sequence a_seq"
   }
 }
-Gen4 plan same as above
 
 # Add auto_increment with qualifier
 "alter vschema on user.a add auto_increment id using a_seq"
@@ -92,7 +87,6 @@ Gen4 plan same as above
     "query": "alter vschema on `user`.a add auto_increment id using a_seq"
   }
 }
-Gen4 plan same as above
 
 # Drop table
 "alter vschema drop table a"
@@ -108,7 +102,6 @@ Gen4 plan same as above
     "query": "alter vschema drop table a"
   }
 }
-Gen4 plan same as above
 
 # Add Vindex
 "alter vschema on a add vindex hash (id)"
@@ -124,7 +117,6 @@ Gen4 plan same as above
     "query": "alter vschema on a add vindex hash (id)"
   }
 }
-Gen4 plan same as above
 
 # Drop Vindex
 "alter vschema on a drop vindex hash"
@@ -140,4 +132,3 @@ Gen4 plan same as above
     "query": "alter vschema on a drop vindex hash"
   }
 }
-Gen4 plan same as above
diff --git a/go/vt/vtgate/planbuilder/testdata/call_cases.txt b/go/vt/vtgate/planbuilder/testdata/call_cases.txt
index eb9e0277c8..b70783a63c 100644
--- a/go/vt/vtgate/planbuilder/testdata/call_cases.txt
+++ b/go/vt/vtgate/planbuilder/testdata/call_cases.txt
@@ -13,7 +13,6 @@
     "Query": "call proc()"
   }
 }
-Gen4 plan same as above
 
 # call qualified keyspace
 "call main.proc()"
@@ -30,12 +29,10 @@ Gen4 plan same as above
     "Query": "call proc()"
   }
 }
-Gen4 plan same as above
 
 # CALL not allowed on sharded keyspaces
 "call user.proc()"
 "CALL is not supported for sharded database"
-Gen4 plan same as above
 
 # CALL with expressions and parameters 
 "call proc(1, 'foo', @var)"
@@ -52,4 +49,3 @@ Gen4 plan same as above
     "Query": "call proc(1, 'foo', :__vtudvvar)"
   }
 }
-Gen4 plan same as above
diff --git a/go/vt/vtgate/planbuilder/testdata/ddl_cases.txt b/go/vt/vtgate/planbuilder/testdata/ddl_cases.txt
index accb0316f3..b7b14e4ce3 100644
--- a/go/vt/vtgate/planbuilder/testdata/ddl_cases.txt
+++ b/go/vt/vtgate/planbuilder/testdata/ddl_cases.txt
@@ -12,7 +12,6 @@
     "Query": "create table t1 (\n\tid bigint,\n\tprimary key (id)\n)"
   }
 }
-Gen4 plan same as above
 
 # simple create table with keyspace
 "create table user.t1(id bigint, primary key(id))"
@@ -28,7 +27,6 @@ Gen4 plan same as above
     "Query": "create table t1 (\n\tid bigint,\n\tprimary key (id)\n)"
   }
 }
-Gen4 plan same as above
 
 # DDL
 "create table a(id int)"
@@ -44,12 +42,10 @@ Gen4 plan same as above
     "Query": "create table a (\n\tid int\n)"
   }
 }
-Gen4 plan same as above
 
 # simple create table with table qualifier that does not exists
 "create table a.b(id int)"
 "Unknown database 'a' in vschema"
-Gen4 plan same as above
 
 #Alter table
 "alter table a ADD id int"
@@ -65,7 +61,6 @@ Gen4 plan same as above
     "Query": "alter table a add column id int"
   }
 }
-Gen4 plan same as above
 
 #Alter table with qualifier
 "alter table user.user ADD id int"
@@ -81,7 +76,6 @@ Gen4 plan same as above
     "Query": "alter table `user` add column id int"
   }
 }
-Gen4 plan same as above
 
 #Alter table with qualifier and table not in vschema
 "alter table user.a ADD id int"
@@ -97,12 +91,10 @@ Gen4 plan same as above
     "Query": "alter table a add column id int"
   }
 }
-Gen4 plan same as above
 
 #Alter table with unknown qualifier
 "alter table a.b ADD id int"
 "Unknown database 'a' in vschema"
-Gen4 plan same as above
 
 # create db foo
 "create database foo"
@@ -117,12 +109,10 @@ Gen4 plan same as above
     }
   }
 }
-Gen4 plan same as above
 
 # create db main
 "create database main"
 "Can't create database 'main'; database exists"
-Gen4 plan same as above
 
 # create db if not exists main
 "create database if not exists main"
@@ -133,22 +123,18 @@ Gen4 plan same as above
     "OperatorType": "Rows"
   }
 }
-Gen4 plan same as above
 
 # alter db foo
 "alter database foo collate utf8"
 "Can't alter database 'foo'; unknown database"
-Gen4 plan same as above
 
 # alter db main
 "alter database main collate utf8"
 "alter database is not supported"
-Gen4 plan same as above
 
 # drop db foo
 "drop database foo"
 "Can't drop database 'foo'; database doesn't exists"
-Gen4 plan same as above
 
 # drop db main
 "drop database main"
@@ -163,7 +149,6 @@ Gen4 plan same as above
     }
   }
 }
-Gen4 plan same as above
 
 # drop db if exists main
 "drop database if exists main"
@@ -178,7 +163,6 @@ Gen4 plan same as above
     }
   }
 }
-Gen4 plan same as above
 
 # drop db if exists foo
 "drop schema if exists foo"
@@ -189,7 +173,6 @@ Gen4 plan same as above
     "OperatorType": "Rows"
   }
 }
-Gen4 plan same as above
 
 # DDL with qualifier
 "create index a on user.user(id)"
@@ -205,7 +188,6 @@ Gen4 plan same as above
     "Query": "alter table `user` add index a (id)"
   }
 }
-Gen4 plan same as above
 
 # DDL with qualifier for a table not in vschema of an unsharded keyspace
 "create index a on main.unknown(id)"
@@ -221,7 +203,6 @@ Gen4 plan same as above
     "Query": "alter table unknown add index a (id)"
   }
 }
-Gen4 plan same as above
 
 # create view with subquery in unsharded keyspace
 "create view view_a as select * from (select col1, col2 from unsharded where id = 1 union select col1, col2 from unsharded where id = 3) a"
@@ -267,7 +248,6 @@ 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)"
@@ -283,7 +263,6 @@ 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)"
@@ -299,7 +278,6 @@ 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"
@@ -330,7 +308,6 @@ Gen4 plan same as above
     "Query": "drop table unsharded_a"
   }
 }
-Gen4 plan same as above
 
 # Drop view
 "drop view main.a"
@@ -346,7 +323,6 @@ Gen4 plan same as above
     "Query": "drop view a"
   }
 }
-Gen4 plan same as above
 
 # Truncate table with qualifier
 "truncate user.user_extra"
@@ -362,7 +338,6 @@ Gen4 plan same as above
     "Query": "truncate table user_extra"
   }
 }
-Gen4 plan same as above
 
 # Rename table
 "rename table a to main.b"
@@ -378,7 +353,6 @@ Gen4 plan same as above
     "Query": "rename table a to b"
   }
 }
-Gen4 plan same as above
 
 # CREATE temp TABLE
 "create temporary table a(id int)"
@@ -395,7 +369,6 @@ Gen4 plan same as above
     "TempTable": true
   }
 }
-Gen4 plan same as above
 
 # DROP temp TABLE
 "drop temporary table a"
@@ -412,4 +385,3 @@ Gen4 plan same as above
     "TempTable": true
   }
 }
-Gen4 plan same as above
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 3a8f86a92c..50afcc55b8 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
@@ -225,7 +225,6 @@ Gen4 plan same as above
     "Query": "create view view_a as select col from `user` join user_extra on `user`.id = user_extra.user_id"
   }
 }
-Gen4 plan same as above
 
 # create view with join that can be solved in each shard separately
 "create view user.view_a as select user.id from user join user_extra on user.id = user_extra.user_id"
diff --git a/go/vt/vtgate/planbuilder/testdata/dml_cases.txt b/go/vt/vtgate/planbuilder/testdata/dml_cases.txt
index 20c91c6c0f..34d2742f36 100644
--- a/go/vt/vtgate/planbuilder/testdata/dml_cases.txt
+++ b/go/vt/vtgate/planbuilder/testdata/dml_cases.txt
@@ -2168,7 +2168,7 @@ Gen4 plan same as above
     "KsidVindex": "user_index",
     "MultiShardAutocommit": false,
     "OwnedVindexQuery": "select user_id, id from music where id = 1 for update",
-    "Query": "delete music from music where id = 1",
+    "Query": "delete from music where id = 1",
     "Table": "music",
     "Values": [
       1
@@ -2390,3 +2390,40 @@ Gen4 plan same as above
   }
 }
 Gen4 plan same as above
+
+# multi-table delete with single table
+"delete u.* from user u where u.id * u.col = u.foo"
+{
+  "QueryType": "DELETE",
+  "Original": "delete u.* from user u where u.id * u.col = u.foo",
+  "Instructions": {
+    "OperatorType": "Delete",
+    "Variant": "Scatter",
+    "Keyspace": {
+      "Name": "user",
+      "Sharded": true
+    },
+    "TargetTabletType": "MASTER",
+    "KsidVindex": "user_index",
+    "MultiShardAutocommit": false,
+    "OwnedVindexQuery": "select Id, `Name`, Costly from `user` where `user`.id * `user`.col = `user`.foo for update",
+    "Query": "delete from `user` where `user`.id * `user`.col = `user`.foo",
+    "Table": "user"
+  }
+}
+Gen4 plan same as above
+
+# delete with unknown reference
+"delete music from user where id = 1"
+"Unknown table 'music' in MULTI DELETE"
+Gen4 plan same as above
+
+# delete with derived tables
+"delete music from (select * from user) music where id = 1"
+"The target table music of the DELETE is not updatable"
+Gen4 plan same as above
+
+# delete with derived tables with unknown table
+"delete user from (select * from user) music where id = 1"
+"Unknown table 'user' in MULTI DELETE"
+Gen4 plan same as above
diff --git a/go/vt/vtgate/planbuilder/testdata/filter_cases.txt b/go/vt/vtgate/planbuilder/testdata/filter_cases.txt
index c7642bf536..4be2688c68 100644
--- a/go/vt/vtgate/planbuilder/testdata/filter_cases.txt
+++ b/go/vt/vtgate/planbuilder/testdata/filter_cases.txt
@@ -174,7 +174,6 @@ Gen4 plan same as above
     "Vindex": "name_user_map"
   }
 }
-Gen4 plan same as above
 
 # Composite IN clause, swapped columns
 "select id from user where (col, name) in (('aa', 'bb'), ('cc', 'dd'))"
@@ -200,7 +199,6 @@ Gen4 plan same as above
     "Vindex": "name_user_map"
   }
 }
-Gen4 plan same as above
 
 # Composite IN clause, choose cost within tuple
 "select id from user where (costly, name) in (('aa', 'bb'), ('cc', 'dd'))"
@@ -226,7 +224,6 @@ Gen4 plan same as above
     "Vindex": "name_user_map"
   }
 }
-Gen4 plan same as above
 
 # Composite IN clause, choose cost within tuple, swapped
 "select id from user where (name, costly) in (('aa', 'bb'), ('cc', 'dd'))"
@@ -252,7 +249,6 @@ Gen4 plan same as above
     "Vindex": "name_user_map"
   }
 }
-Gen4 plan same as above
 
 # Composite IN clause, choose cost
 "select id from user where (col, costly) in (('aa', 'bb')) and (col, name) in (('cc', 'dd'))"
@@ -277,7 +273,6 @@ Gen4 plan same as above
     "Vindex": "name_user_map"
   }
 }
-Gen4 plan same as above
 
 # Composite IN clause vs equality
 "select id from user where (col, name) in (('aa', 'bb')) and id = 5"
@@ -326,7 +321,6 @@ Gen4 plan same as above
     "Vindex": "name_user_map"
   }
 }
-Gen4 plan same as above
 
 # Composite IN: tuple inside tuple
 "select id from user where ((col1, name), col2) in ((('aa', 'bb'), 'cc'), (('dd', 'ee'), 'ff'))"
@@ -352,7 +346,6 @@ Gen4 plan same as above
     "Vindex": "name_user_map"
   }
 }
-Gen4 plan same as above
 
 # Composite IN: tuple inside tuple, but no match in tuple
 "select id from user where (name, (col1, col2)) in (('aa', ('bb', 'cc')), ('dd', ('ee', 'ff')))"
@@ -378,7 +371,6 @@ Gen4 plan same as above
     "Vindex": "name_user_map"
   }
 }
-Gen4 plan same as above
 
 # Composite IN: tuple inside tuple, mismiatched values
 "select id from user where ((col1, name), col2) in (('aa', 'bb', 'cc'), (('dd', 'ee'), 'ff'))"
@@ -564,25 +556,6 @@ Gen4 plan same as above
     "Vindex": "user_index"
   }
 }
-{
-  "QueryType": "SELECT",
-  "Original": "select user_extra.id from user join user_extra on user.id = user_extra.user_id where user.id = 5",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select user_extra.id from `user`, user_extra where 1 != 1",
-    "Query": "select user_extra.id from `user`, user_extra where `user`.id = 5 and `user`.id = user_extra.user_id",
-    "Table": "`user`, user_extra",
-    "Values": [
-      5
-    ],
-    "Vindex": "user_index"
-  }
-}
 
 # Multi-table unique vindex constraint on right table
 "select user_extra.id from user join user_extra on user.id = user_extra.user_id where user_extra.user_id = 5"
@@ -605,25 +578,6 @@ Gen4 plan same as above
     "Vindex": "user_index"
   }
 }
-{
-  "QueryType": "SELECT",
-  "Original": "select user_extra.id from user join user_extra on user.id = user_extra.user_id where user_extra.user_id = 5",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select user_extra.id from `user`, user_extra where 1 != 1",
-    "Query": "select user_extra.id from `user`, user_extra where user_extra.user_id = 5 and `user`.id = user_extra.user_id",
-    "Table": "`user`, user_extra",
-    "Values": [
-      5
-    ],
-    "Vindex": "user_index"
-  }
-}
 
 # Multi-table unique vindex constraint on left table of left join
 "select user_extra.id from user left join user_extra on user.id = user_extra.user_id where user.id = 5"
@@ -646,7 +600,6 @@ Gen4 plan same as above
     "Vindex": "user_index"
   }
 }
-Gen4 plan same as above
 
 # Multi-table unique vindex constraint on left-joined right table
 "select user_extra.id from user left join user_extra on user.id = user_extra.user_id where user_extra.user_id = 5"
@@ -756,48 +709,6 @@ Gen4 plan same as above
     ]
   }
 }
-{
-  "QueryType": "SELECT",
-  "Original": "select user_extra.id from user join user_extra on user.col = user_extra.col where user.id = 5 and user_extra.user_id = 5",
-  "Instructions": {
-    "OperatorType": "Join",
-    "Variant": "Join",
-    "JoinColumnIndexes": "1",
-    "TableName": "`user`_user_extra",
-    "Inputs": [
-      {
-        "OperatorType": "Route",
-        "Variant": "SelectEqualUnique",
-        "Keyspace": {
-          "Name": "user",
-          "Sharded": true
-        },
-        "FieldQuery": "select `user`.col from `user` where 1 != 1",
-        "Query": "select `user`.col from `user` where `user`.id = 5",
-        "Table": "`user`",
-        "Values": [
-          5
-        ],
-        "Vindex": "user_index"
-      },
-      {
-        "OperatorType": "Route",
-        "Variant": "SelectEqualUnique",
-        "Keyspace": {
-          "Name": "user",
-          "Sharded": true
-        },
-        "FieldQuery": "select user_extra.id from user_extra where 1 != 1",
-        "Query": "select user_extra.id from user_extra where user_extra.user_id = 5 and user_extra.col = :user_col",
-        "Table": "user_extra",
-        "Values": [
-          5
-        ],
-        "Vindex": "user_index"
-      }
-    ]
-  }
-}
 
 # Multi-route with cross-route constraint
 "select user_extra.id from user join user_extra on user.col = user_extra.col where user_extra.user_id = user.col"
@@ -877,40 +788,6 @@ Gen4 plan same as above
     ]
   }
 }
-{
-  "QueryType": "SELECT",
-  "Original": "select user_extra.id from user join user_extra on user.col = user_extra.col where 1 = 1",
-  "Instructions": {
-    "OperatorType": "Join",
-    "Variant": "Join",
-    "JoinColumnIndexes": "1",
-    "TableName": "`user`_user_extra",
-    "Inputs": [
-      {
-        "OperatorType": "Route",
-        "Variant": "SelectScatter",
-        "Keyspace": {
-          "Name": "user",
-          "Sharded": true
-        },
-        "FieldQuery": "select `user`.col from `user` where 1 != 1",
-        "Query": "select `user`.col from `user` where 1 = 1",
-        "Table": "`user`"
-      },
-      {
-        "OperatorType": "Route",
-        "Variant": "SelectScatter",
-        "Keyspace": {
-          "Name": "user",
-          "Sharded": true
-        },
-        "FieldQuery": "select user_extra.id from user_extra where 1 != 1",
-        "Query": "select user_extra.id from user_extra where 1 = 1 and user_extra.col = :user_col",
-        "Table": "user_extra"
-      }
-    ]
-  }
-}
 
 # Route with multiple route constraints, SelectIN is the best constraint.
 "select id from user where user.col = 5 and user.id in (1, 2)"
@@ -1403,6 +1280,7 @@ Gen4 plan same as above
 # unresolved symbol in inner subquery.
 "select id from user where id = :a and user.col in (select user_extra.col from user_extra where user_extra.user_id = :a and foo.id = 1)"
 "symbol foo.id not found"
+Gen4 plan same as above
 
 # outer and inner subquery route by same outermost column value
 "select id2 from user uu where id in (select id from user where id = uu.id and user.col in (select user_extra.col from user_extra where user_extra.user_id = uu.id))"
diff --git a/go/vt/vtgate/planbuilder/testdata/flush_cases.txt b/go/vt/vtgate/planbuilder/testdata/flush_cases.txt
index a2d1f0ef31..c56ffd08c4 100644
--- a/go/vt/vtgate/planbuilder/testdata/flush_cases.txt
+++ b/go/vt/vtgate/planbuilder/testdata/flush_cases.txt
@@ -13,7 +13,6 @@
     "Query": "flush tables unsharded, music"
   }
 }
-Gen4 plan same as above
 
 # Flush statement with no tables
 "flush local tables with read lock"
@@ -30,7 +29,6 @@ Gen4 plan same as above
     "Query": "flush local tables with read lock"
   }
 }
-Gen4 plan same as above
 
 # Flush statement with flush options
 "flush no_write_to_binlog hosts, logs"
@@ -47,4 +45,3 @@ Gen4 plan same as above
     "Query": "flush local hosts, logs"
   }
 }
-Gen4 plan same as above
diff --git a/go/vt/vtgate/planbuilder/testdata/migration_cases.txt b/go/vt/vtgate/planbuilder/testdata/migration_cases.txt
index 9f645bae59..3fd7671e3c 100644
--- a/go/vt/vtgate/planbuilder/testdata/migration_cases.txt
+++ b/go/vt/vtgate/planbuilder/testdata/migration_cases.txt
@@ -12,7 +12,6 @@
     "query": "revert vitess_migration 'abc'"
   }
 }
-Gen4 plan same as above
 
 # retry migration
 "alter vitess_migration 'abc' retry"
@@ -29,7 +28,6 @@ Gen4 plan same as above
     "Query": "alter vitess_migration 'abc' retry"
   }
 }
-Gen4 plan same as above
 
 # complete migration
 "alter vitess_migration 'abc' complete"
@@ -46,7 +44,6 @@ Gen4 plan same as above
     "Query": "alter vitess_migration 'abc' complete"
   }
 }
-Gen4 plan same as above
 
 # cancel migration
 "alter vitess_migration 'abc' cancel"
@@ -63,7 +60,6 @@ Gen4 plan same as above
     "Query": "alter vitess_migration 'abc' cancel"
   }
 }
-Gen4 plan same as above
 
 # cancel all migrations
 "alter vitess_migration cancel all"
@@ -80,4 +76,3 @@ Gen4 plan same as above
     "Query": "alter vitess_migration cancel all"
   }
 }
-Gen4 plan same as above
diff --git a/go/vt/vtgate/planbuilder/testdata/other_admin_cases.txt b/go/vt/vtgate/planbuilder/testdata/other_admin_cases.txt
index e5f965ee1b..583ee3d042 100644
--- a/go/vt/vtgate/planbuilder/testdata/other_admin_cases.txt
+++ b/go/vt/vtgate/planbuilder/testdata/other_admin_cases.txt
@@ -14,7 +14,6 @@
     "SingleShardOnly": true
   }
 }
-Gen4 plan same as above
 
 # Optimize statement
 "optimize table t1"
@@ -32,7 +31,6 @@ Gen4 plan same as above
     "SingleShardOnly": true
   }
 }
-Gen4 plan same as above
 
 # DO statement
 "DO 1"
@@ -50,4 +48,3 @@ Gen4 plan same as above
     "SingleShardOnly": true
   }
 }
-Gen4 plan same as above
diff --git a/go/vt/vtgate/planbuilder/testdata/other_read_cases.txt b/go/vt/vtgate/planbuilder/testdata/other_read_cases.txt
index 4b2a5bfae9..835377526b 100644
--- a/go/vt/vtgate/planbuilder/testdata/other_read_cases.txt
+++ b/go/vt/vtgate/planbuilder/testdata/other_read_cases.txt
@@ -14,7 +14,6 @@
     "SingleShardOnly": true
   }
 }
-Gen4 plan same as above
 
 # Explain Vitess statement
 "explain format=vitess select * from user"
@@ -25,7 +24,6 @@ Gen4 plan same as above
     "OperatorType": "Rows"
   }
 }
-Gen4 plan same as above
 
 # Analyze statement
 "analyze table t1"
@@ -43,7 +41,6 @@ Gen4 plan same as above
     "SingleShardOnly": true
   }
 }
-Gen4 plan same as above
 
 # Describe statement
 "describe select * from t"
@@ -61,7 +58,6 @@ Gen4 plan same as above
     "SingleShardOnly": true
   }
 }
-Gen4 plan same as above
 
 # Desc statement
 "desc select * from t"
@@ -79,4 +75,3 @@ Gen4 plan same as above
     "SingleShardOnly": true
   }
 }
-Gen4 plan same as above
diff --git a/go/vt/vtgate/planbuilder/testdata/select_cases.txt b/go/vt/vtgate/planbuilder/testdata/select_cases.txt
index 46650433ae..ea44d9954a 100644
--- a/go/vt/vtgate/planbuilder/testdata/select_cases.txt
+++ b/go/vt/vtgate/planbuilder/testdata/select_cases.txt
@@ -1356,6 +1356,7 @@ Gen4 plan same as above
     "Table": "unsharded"
   }
 }
+Gen4 plan same as above
 
 # testing SingleRow Projection
 "select 42"
diff --git a/go/vt/vtgate/planbuilder/testdata/show_cases.txt b/go/vt/vtgate/planbuilder/testdata/show_cases.txt
index 4b79891df1..f0ab459c4d 100644
--- a/go/vt/vtgate/planbuilder/testdata/show_cases.txt
+++ b/go/vt/vtgate/planbuilder/testdata/show_cases.txt
@@ -14,7 +14,6 @@
     "SingleShardOnly": true
   }
 }
-Gen4 plan same as above
 
 # Show Table status with a keyspace name
 "SHOW table StatUs from main"
@@ -32,7 +31,6 @@ Gen4 plan same as above
     "SingleShardOnly": true
   }
 }
-Gen4 plan same as above
 
 # Show Table status with a keyspace name using IN
 "SHOW table StatUs In main"
@@ -50,7 +48,6 @@ Gen4 plan same as above
     "SingleShardOnly": true
   }
 }
-Gen4 plan same as above
 
 # Show Table status with a keyspace name with a condition
 "SHOW table StatUs In user WHERE Rows > 70"
@@ -68,7 +65,6 @@ Gen4 plan same as above
     "SingleShardOnly": true
   }
 }
-Gen4 plan same as above
 
 # Show Table status with a Like condition
 "SHOW table StatUs LIKe '%a'"
@@ -86,7 +82,6 @@ Gen4 plan same as above
     "SingleShardOnly": true
   }
 }
-Gen4 plan same as above
 
 # show columns from user keyspace
 "show full columns from user.user_extra"
@@ -104,7 +99,6 @@ Gen4 plan same as above
     "SingleShardOnly": true
   }
 }
-Gen4 plan same as above
 
 # show columns from main keyspace
 "show full columns from unsharded"
@@ -122,7 +116,6 @@ Gen4 plan same as above
     "SingleShardOnly": true
   }
 }
-Gen4 plan same as above
 
 # show columns pass as dbname in from clause supersedes the qualifier
 "show full columns from user.unsharded from main"
@@ -140,17 +133,14 @@ Gen4 plan same as above
     "SingleShardOnly": true
   }
 }
-Gen4 plan same as above
 
 # show columns fails as table does not exists in user keyspace
 "show full columns from unsharded from user"
 "table unsharded not found"
-Gen4 plan same as above
 
 # show columns fails as table does not exists in user keyspace
 "show full columns from user.unsharded"
 "table unsharded not found"
-Gen4 plan same as above
 
 # show charset
 "show charset"
@@ -161,7 +151,6 @@ Gen4 plan same as above
     "OperatorType": "Rows"
   }
 }
-Gen4 plan same as above
 
 # show function
 "show function status"
@@ -179,7 +168,6 @@ Gen4 plan same as above
     "SingleShardOnly": true
   }
 }
-Gen4 plan same as above
 
 # show privileges
 "show privileges"
@@ -197,7 +185,6 @@ Gen4 plan same as above
     "SingleShardOnly": true
   }
 }
-Gen4 plan same as above
 
 # show procedure status
 "show procedure status"
@@ -215,7 +202,6 @@ Gen4 plan same as above
     "SingleShardOnly": true
   }
 }
-Gen4 plan same as above
 
 # show variables
 "show variables"
@@ -238,7 +224,6 @@ Gen4 plan same as above
     ]
   }
 }
-Gen4 plan same as above
 
 # show global variables
 "show global variables"
@@ -261,7 +246,6 @@ Gen4 plan same as above
     ]
   }
 }
-Gen4 plan same as above
 
 # show databases
 "show databases"
@@ -272,7 +256,6 @@ Gen4 plan same as above
     "OperatorType": "Rows"
   }
 }
-Gen4 plan same as above
 
 # show create database
 "show create database user"
@@ -290,7 +273,6 @@ Gen4 plan same as above
     "SingleShardOnly": true
   }
 }
-Gen4 plan same as above
 
 # show create database system_schema
 "show create database mysql"
@@ -308,7 +290,6 @@ Gen4 plan same as above
     "SingleShardOnly": true
   }
 }
-Gen4 plan same as above
 
 # show create procedure
 "show create procedure proc"
@@ -326,7 +307,6 @@ Gen4 plan same as above
     "SingleShardOnly": true
   }
 }
-Gen4 plan same as above
 
 # show create procedure from system_schema
 "show create procedure information_schema.proc"
@@ -344,7 +324,6 @@ Gen4 plan same as above
     "SingleShardOnly": true
   }
 }
-Gen4 plan same as above
 
 # show create table on table present in sharded but as unsharded is selected it goes to unsharded keyspace
 "show create table user_extra"
@@ -362,7 +341,6 @@ Gen4 plan same as above
     "SingleShardOnly": true
   }
 }
-Gen4 plan same as above
 
 # show create table with qualifier
 "show create table user.user_extra"
@@ -380,7 +358,6 @@ Gen4 plan same as above
     "SingleShardOnly": true
   }
 }
-Gen4 plan same as above
 
 # show create table with unsharded as default keyspace
 "show create table unknown"
@@ -398,12 +375,10 @@ Gen4 plan same as above
     "SingleShardOnly": true
   }
 }
-Gen4 plan same as above
 
 # show create table with table not present with qualifier
 "show create table user.unknown"
 "table unknown not found"
-Gen4 plan same as above
 
 # show create table from system_schema
 "show create table information_schema.tables"
@@ -421,7 +396,6 @@ Gen4 plan same as above
     "SingleShardOnly": true
   }
 }
-Gen4 plan same as above
 
 # show tables
 "show tables"
@@ -450,7 +424,6 @@ Gen4 plan same as above
     ]
   }
 }
-Gen4 plan same as above
 
 # show tables from db
 "show tables from user"
@@ -479,7 +452,6 @@ Gen4 plan same as above
     ]
   }
 }
-Gen4 plan same as above
 
 # show tables from system schema
 "show tables from performance_schema"
@@ -508,7 +480,6 @@ Gen4 plan same as above
     ]
   }
 }
-Gen4 plan same as above
 
 # show migrations with db and like
 "show vitess_migrations from user like '%format'"
@@ -525,7 +496,6 @@ Gen4 plan same as above
     "Query": "SELECT * FROM _vt.schema_migrations where migration_uuid LIKE '%format' OR migration_context LIKE '%format' OR migration_status LIKE '%format'"
   }
 }
-Gen4 plan same as above
 
 # show migrations with db and where
 "show vitess_migrations from user where id = 5"
@@ -542,7 +512,6 @@ Gen4 plan same as above
     "Query": "SELECT * FROM _vt.schema_migrations where id = 5"
   }
 }
-Gen4 plan same as above
 
 # show vgtid
 "show global vgtid_executed"
@@ -567,7 +536,6 @@ Gen4 plan same as above
     ]
   }
 }
-Gen4 plan same as above
 
 # show gtid
 "show global gtid_executed from user"
@@ -585,7 +553,6 @@ Gen4 plan same as above
     "ShardNameNeeded": true
   }
 }
-Gen4 plan same as above
 
 # show warnings
 "show warnings"
@@ -596,4 +563,3 @@ Gen4 plan same as above
     "OperatorType": "SHOW WARNINGS"
   }
 }
-Gen4 plan same as above
diff --git a/go/vt/vtgate/planbuilder/testdata/symtab_cases.txt b/go/vt/vtgate/planbuilder/testdata/symtab_cases.txt
index bb40820a79..24811cbc90 100644
--- a/go/vt/vtgate/planbuilder/testdata/symtab_cases.txt
+++ b/go/vt/vtgate/planbuilder/testdata/symtab_cases.txt
@@ -36,9 +36,7 @@
     ]
   }
 }
-Gen4 plan same as above
 
 # predef1 is in both user and unsharded. So, it's ambiguous.
 "select predef1, predef3 from user join unsharded on predef1 = predef3"
 "symbol predef1 not found"
-Gen4 error: Column 'predef1' in field list is ambiguous
diff --git a/go/vt/vtgate/planbuilder/testdata/unsupported_cases.txt b/go/vt/vtgate/planbuilder/testdata/unsupported_cases.txt
index 6c94261918..cb52ae2d73 100644
--- a/go/vt/vtgate/planbuilder/testdata/unsupported_cases.txt
+++ b/go/vt/vtgate/planbuilder/testdata/unsupported_cases.txt
@@ -40,37 +40,30 @@ Gen4 plan same as above
 # natural join
 "select * from user natural join user_extra"
 "unsupported: natural join"
-Gen4 plan same as above
 
 # join with USING construct
 "select * from user join user_extra using(id)"
 "unsupported: join with USING(column_list) clause for complex queries"
-Gen4 plan same as above
 
 # join with USING construct with 3 tables
 "select user.id from user join user_extra using(id) join music using(id2)"
 "unsupported: join with USING(column_list) clause for complex queries"
-Gen4 plan same as above
 
 # natural left join
 "select * from user natural left join user_extra"
 "unsupported: natural left join"
-Gen4 plan same as above
 
 # natural right join
 "select * from user natural right join user_extra"
 "unsupported: natural right join"
-Gen4 plan same as above
 
 # left join with expressions
 "select user.id, user_extra.col+1 from user left join user_extra on user.col = user_extra.col"
 "unsupported: cross-shard left join and column expressions"
-Gen4 plan same as above
 
 # left join with expressions, with three-way join (different code path)
 "select user.id, user_extra.col+1 from user left join user_extra on user.col = user_extra.col join user_extra e"
 "unsupported: cross-shard left join and column expressions"
-Gen4 plan same as above
 
 # left join where clauses
 "select user.id from user left join user_extra on user.col = user_extra.col where user_extra.col = 5"
@@ -377,11 +370,6 @@ Gen4 plan same as above
 "select func(keyspace_id) from user_index where id = :id"
 "unsupported: expression on results of a vindex function"
 
-# delete with unknown reference
-"delete music from user where id = 1"
-"Unknown table 'music' in MULTI DELETE"
-Gen4 plan same as above
-
 # delete with multi-table targets
 "delete music,user from music inner join user where music.id = user.id"
 "unsupported: multi-shard or vindex write statement"
diff --git a/go/vt/vtgate/semantics/analyzer_test.go b/go/vt/vtgate/semantics/analyzer_test.go
index ee1c2cad29..afc2d74d99 100644
--- a/go/vt/vtgate/semantics/analyzer_test.go
+++ b/go/vt/vtgate/semantics/analyzer_test.go
@@ -346,12 +346,12 @@ func TestUnknownColumnMap2(t *testing.T) {
 		{
 			name:   "non authoritative columns - one authoritative and one not",
 			schema: map[string]*vindexes.Table{"a": &nonAuthoritativeTblA, "b": &authoritativeTblB},
-			err:    false,
+			err:    true,
 		},
 		{
 			name:   "non authoritative columns - one authoritative and one not",
 			schema: map[string]*vindexes.Table{"a": &authoritativeTblA, "b": &nonAuthoritativeTblB},
-			err:    false,
+			err:    true,
 		},
 		{
 			name:   "authoritative columns",
@@ -364,43 +364,6 @@ func TestUnknownColumnMap2(t *testing.T) {
 			err:    true,
 		},
 	}
-	for _, test := range tests {
-		t.Run(test.name, func(t *testing.T) {
-			si := &FakeSI{Tables: test.schema}
-			tbl, err := Analyze(parse, "", si)
-			require.NoError(t, err)
-
-			if test.err {
-				require.Error(t, tbl.ProjectionErr)
-			} else {
-				require.NoError(t, tbl.ProjectionErr)
-			}
-		})
-	}
-}
-
-func TestUnknownPredicate(t *testing.T) {
-	query := "select 1 from a, b where col = 1"
-	authoritativeTblA := &vindexes.Table{
-		Name: sqlparser.NewTableIdent("a"),
-	}
-	authoritativeTblB := &vindexes.Table{
-		Name: sqlparser.NewTableIdent("b"),
-	}
-
-	parse, _ := sqlparser.Parse(query)
-
-	tests := []struct {
-		name   string
-		schema map[string]*vindexes.Table
-		err    bool
-	}{
-		{
-			name:   "no info about tables",
-			schema: map[string]*vindexes.Table{"a": authoritativeTblA, "b": authoritativeTblB},
-			err:    true,
-		},
-	}
 	for _, test := range tests {
 		t.Run(test.name, func(t *testing.T) {
 			si := &FakeSI{Tables: test.schema}
diff --git a/go/vt/vttablet/tabletserver/tx_pool_test.go b/go/vt/vttablet/tabletserver/tx_pool_test.go
index 5b33c96e49..b52669a98b 100644
--- a/go/vt/vttablet/tabletserver/tx_pool_test.go
+++ b/go/vt/vttablet/tabletserver/tx_pool_test.go
@@ -355,7 +355,8 @@ func TestTxPoolGetConnRecentlyRemovedTransaction(t *testing.T) {
 	txPool.Open(db.ConnParams(), db.ConnParams(), db.ConnParams())
 	defer txPool.Close()
 
-	conn1, _, _ = txPool.Begin(ctx, &querypb.ExecuteOptions{}, false, 0, nil)
+	conn1, _, err = txPool.Begin(ctx, &querypb.ExecuteOptions{}, false, 0, nil)
+	require.NoError(t, err, "unable to start transaction: %v", err)
 	conn1.Unlock()
 	id = conn1.ReservedID()
 	time.Sleep(20 * time.Millisecond)