Repository: vitessio/vitess
Pull request #9335 (2021-12-07 18:46:14)

Allow source columns to be specified multiple times in a vreplication rule filter

## Description
This PR fixes a bug where a column cannot be referred to multiple times in a Filter. There was an incorrect optimization in vstreamer where a column was being ignored while creating the source query if it was already seen.

So a materialize `source_expression` like `select id, val, ts, dayofmonth(ts) as day from mat` would fail since `ts` was mentioned twice in the select list. 

In addition, a new test has been added that confirms that Materialize filters can contain user-defined functions: we can define a `source_expression` like `select id, val, ts, customFunc1(id, val) as x from mat`. This is more an observation rather than a new feature, since, to our query parser, a custom function looks like just a pre-defined mysql function.  It is being stated explicitly since we had earlier assumed we did not yet support custom functions because a user had earlier reported failures with such a filter. It now looks as if that report was caused by this same bug with multiple columns. 

Signed-off-by: Rohit Nayak <rohit@planetscale.com>

## Related Issue(s)
#9314 

## Checklist
- [ ] Should this PR be backported?
- [X] Tests were added or are not required
- [ ] Documentation was added or is not required



Patch:
diff --git a/MAINTAINERS.md b/MAINTAINERS.md
index 05ae3ad0ad..7e19c348d0 100644
--- a/MAINTAINERS.md
+++ b/MAINTAINERS.md
@@ -13,10 +13,10 @@ The following is the full list, alphabetically ordered.
 * Florent Poinsard ([frouioui](https://github.com/frouioui)) frouioui@planetscale.com
 * Harshit Gangal ([harshit-gangal](https://github.com/harshit-gangal)) harshit.gangal@gmail.com
 * Jon Tirsen ([tirsen](https://github.com/tirsen)) jontirsen@squareup.com
-* Mali Akmanalp ([makmanalp](https://github.com/makmanalp) makmanalp@hubspot.com
 * Manan Gupta ([GuptaManan100](https://github.com/GuptaManan100)) manan@planetscale.com
 * Michael Demmer ([demmer](https://github.com/demmer)) mdemmer@slack-corp.com
 * Michael Pawliszyn ([mpawliszyn](https://github.com/mpawliszyn)) mikepaw@squareup.com
+* Paul Hemberger ([pH14](https://github.com/pH14)) phemberger@hubspot.com
 * Rafael Chacon ([rafael](https://github.com/rafael)) rchacon@figma.com
 * Rohit Nayak ([rohit-nayak-ps](https://github.com/rohit-nayak-ps)) rohit@planetscale.com
 * Sara Bee ([doeg](https://github.com/doeg)) sarab@slack-corp.com
@@ -48,7 +48,7 @@ vmg
 deepthi, rafael, enisoc, shlomi-noach, ajm188, GuptaManan100
 
 ### Java
-mpawliszyn, makmanalp, harshit-gangal
+mpawliszyn, pH14, harshit-gangal
 
 ### Kubernetes
 derekperkins, dkhenry, enisoc
diff --git a/go/cmd/vttablet/vttablet.go b/go/cmd/vttablet/vttablet.go
index 925ae3fbf8..fa8a9b4f0a 100644
--- a/go/cmd/vttablet/vttablet.go
+++ b/go/cmd/vttablet/vttablet.go
@@ -169,12 +169,12 @@ func initConfig(tabletAlias *topodatapb.TabletAlias) (*tabletenv.TabletConfig, *
 // extractOnlineDDL extracts the gh-ost binary from this executable. gh-ost is appended
 // to vttablet executable by `make build` and via ricebox
 func extractOnlineDDL() error {
-	if binaryFileName, isOverride := onlineddl.GhostBinaryFileName(); !isOverride {
-		riceBox, err := rice.FindBox("../../../resources/bin")
-		if err != nil {
-			return err
-		}
+	riceBox, err := rice.FindBox("../../../resources/bin")
+	if err != nil {
+		return err
+	}
 
+	if binaryFileName, isOverride := onlineddl.GhostBinaryFileName(); !isOverride {
 		// there is no path override for gh-ost. We're expected to auto-extract gh-ost.
 		ghostBinary, err := riceBox.Bytes("gh-ost")
 		if err != nil {
diff --git a/go/mysql/flavor.go b/go/mysql/flavor.go
index 7204a36a91..2902308d84 100644
--- a/go/mysql/flavor.go
+++ b/go/mysql/flavor.go
@@ -315,15 +315,8 @@ func parseReplicationStatus(fields map[string]string) ReplicationStatus {
 	status.SourcePort = int(parseInt)
 	parseInt, _ = strconv.ParseInt(fields["Connect_Retry"], 10, 0)
 	status.ConnectRetry = int(parseInt)
-	parseUint, err := strconv.ParseUint(fields["Seconds_Behind_Master"], 10, 0)
-	if err != nil {
-		// we could not parse the value into a valid uint -- most commonly because the value is NULL from the
-		// database -- so let's reflect that the underlying value was unknown on our last check
-		status.ReplicationLagUnknown = true
-	} else {
-		status.ReplicationLagUnknown = false
-		status.ReplicationLagSeconds = uint(parseUint)
-	}
+	parseUint, _ := strconv.ParseUint(fields["Seconds_Behind_Master"], 10, 0)
+	status.ReplicationLagSeconds = uint(parseUint)
 	parseUint, _ = strconv.ParseUint(fields["Master_Server_Id"], 10, 0)
 	status.SourceServerID = uint(parseUint)
 
diff --git a/go/mysql/replication_status.go b/go/mysql/replication_status.go
index 2c818dcb53..801d38a680 100644
--- a/go/mysql/replication_status.go
+++ b/go/mysql/replication_status.go
@@ -30,9 +30,6 @@ type ReplicationStatus struct {
 	// were to finish executing everything that's currently in its relay log.
 	// However, some MySQL flavors don't expose this information,
 	// in which case RelayLogPosition.IsZero() will be true.
-	// If ReplicationLagUnknown is true then we should not rely on the seconds
-	// behind value and we can instead try to calculate the lag ourselves when
-	// appropriate.
 	RelayLogPosition      Position
 	FilePosition          Position
 	FileRelayLogPosition  Position
@@ -40,7 +37,6 @@ type ReplicationStatus struct {
 	IOThreadRunning       bool
 	SQLThreadRunning      bool
 	ReplicationLagSeconds uint
-	ReplicationLagUnknown bool
 	SourceHost            string
 	SourcePort            int
 	ConnectRetry          int
diff --git a/go/vt/vtgate/engine/cached_size.go b/go/vt/vtgate/engine/cached_size.go
index 5d9f440d23..28ecb36e91 100644
--- a/go/vt/vtgate/engine/cached_size.go
+++ b/go/vt/vtgate/engine/cached_size.go
@@ -666,9 +666,12 @@ func (cached *Route) CachedSize(alloc bool) int64 {
 	if cc, ok := cached.Vindex.(cachedObject); ok {
 		size += cc.CachedSize(true)
 	}
-	// field Value vitess.io/vitess/go/vt/vtgate/engine.RouteValue
-	if cc, ok := cached.Value.(cachedObject); ok {
-		size += cc.CachedSize(true)
+	// field Values []vitess.io/vitess/go/sqltypes.PlanValue
+	{
+		size += hack.RuntimeAllocSize(int64(cap(cached.Values)) * int64(88))
+		for _, elem := range cached.Values {
+			size += elem.CachedSize(false)
+		}
 	}
 	// field OrderBy []vitess.io/vitess/go/vt/vtgate/engine.OrderByParams
 	{
diff --git a/go/vt/vtgate/engine/route.go b/go/vt/vtgate/engine/route.go
index dd4cb932fd..7b6f37374f 100644
--- a/go/vt/vtgate/engine/route.go
+++ b/go/vt/vtgate/engine/route.go
@@ -76,9 +76,8 @@ type Route struct {
 
 	// Vindex specifies the vindex to be used.
 	Vindex vindexes.SingleColumn
-
-	// Value specifies the vindex value to use for routing.
-	Value RouteValue
+	// Values specifies the vindex values to use for routing.
+	Values []sqltypes.PlanValue
 
 	// OrderBy specifies the key order for merge sorting. This will be
 	// set only for scatter queries that need the results to be
@@ -107,16 +106,6 @@ type Route struct {
 	noTxNeeded
 }
 
-type RouteValue interface {
-	// ResolveValue allows for retrieval of the value we expose for public consumption
-	ResolveValue(bindVars map[string]*querypb.BindVariable) (sqltypes.Value, error)
-
-	// ResolveList allows for retrieval of the value we expose for public consumption
-	ResolveList(bindVars map[string]*querypb.BindVariable) ([]sqltypes.Value, error)
-
-	MarshalJSON() ([]byte, error)
-}
-
 // NewSimpleRoute creates a Route with the bare minimum of parameters.
 func NewSimpleRoute(opcode RouteOpcode, keyspace *vindexes.Keyspace) *Route {
 	return &Route{
@@ -599,11 +588,11 @@ func (route *Route) paramsAnyShard(vcursor VCursor, bindVars map[string]*querypb
 }
 
 func (route *Route) paramsSelectEqual(vcursor VCursor, bindVars map[string]*querypb.BindVariable) ([]*srvtopo.ResolvedShard, []map[string]*querypb.BindVariable, error) {
-	value, err := route.Value.ResolveValue(bindVars)
+	key, err := route.Values[0].ResolveValue(bindVars)
 	if err != nil {
 		return nil, nil, err
 	}
-	rss, _, err := resolveShards(vcursor, route.Vindex, route.Keyspace, []sqltypes.Value{value})
+	rss, _, err := resolveShards(vcursor, route.Vindex, route.Keyspace, []sqltypes.Value{key})
 	if err != nil {
 		return nil, nil, err
 	}
@@ -615,11 +604,11 @@ func (route *Route) paramsSelectEqual(vcursor VCursor, bindVars map[string]*quer
 }
 
 func (route *Route) paramsSelectIn(vcursor VCursor, bindVars map[string]*querypb.BindVariable) ([]*srvtopo.ResolvedShard, []map[string]*querypb.BindVariable, error) {
-	value, err := route.Value.ResolveList(bindVars)
+	keys, err := route.Values[0].ResolveList(bindVars)
 	if err != nil {
 		return nil, nil, err
 	}
-	rss, values, err := resolveShards(vcursor, route.Vindex, route.Keyspace, value)
+	rss, values, err := resolveShards(vcursor, route.Vindex, route.Keyspace, keys)
 	if err != nil {
 		return nil, nil, err
 	}
@@ -627,11 +616,11 @@ func (route *Route) paramsSelectIn(vcursor VCursor, bindVars map[string]*querypb
 }
 
 func (route *Route) paramsSelectMultiEqual(vcursor VCursor, bindVars map[string]*querypb.BindVariable) ([]*srvtopo.ResolvedShard, []map[string]*querypb.BindVariable, error) {
-	value, err := route.Value.ResolveList(bindVars)
+	keys, err := route.Values[0].ResolveList(bindVars)
 	if err != nil {
 		return nil, nil, err
 	}
-	rss, _, err := resolveShards(vcursor, route.Vindex, route.Keyspace, value)
+	rss, _, err := resolveShards(vcursor, route.Vindex, route.Keyspace, keys)
 	if err != nil {
 		return nil, nil, err
 	}
@@ -806,8 +795,8 @@ func (route *Route) description() PrimitiveDescription {
 	if route.Vindex != nil {
 		other["Vindex"] = route.Vindex.String()
 	}
-	if route.Value != nil {
-		other["Values"] = route.Value
+	if len(route.Values) > 0 {
+		other["Values"] = route.Values
 	}
 	if len(route.SysTableTableSchema) != 0 {
 		sysTabSchema := "["
diff --git a/go/vt/vtgate/evalengine/convert.go b/go/vt/vtgate/evalengine/convert.go
index 6eff58719f..ce4d479ab2 100644
--- a/go/vt/vtgate/evalengine/convert.go
+++ b/go/vt/vtgate/evalengine/convert.go
@@ -285,9 +285,6 @@ func convertExpr(e sqlparser.Expr, lookup ConverterLookup) (Expr, error) {
 	case sqlparser.Argument:
 		collation := getCollation(e, lookup)
 		return NewBindVar(string(node), collation), nil
-	case sqlparser.ListArg:
-		collation := getCollation(e, lookup)
-		return NewBindVar(string(node), collation), nil
 	case *sqlparser.Literal:
 		switch node.Type {
 		case sqlparser.IntVal:
diff --git a/go/vt/vtgate/evalengine/expressions.go b/go/vt/vtgate/evalengine/expressions.go
index 192c8160fc..734e9077ee 100644
--- a/go/vt/vtgate/evalengine/expressions.go
+++ b/go/vt/vtgate/evalengine/expressions.go
@@ -17,7 +17,6 @@ limitations under the License.
 package evalengine
 
 import (
-	"encoding/json"
 	"fmt"
 	"math"
 	"strconv"
@@ -57,10 +56,6 @@ type (
 		format(buf *strings.Builder, wrap bool)
 	}
 
-	RouteValue struct {
-		Expr Expr
-	}
-
 	Literal struct {
 		Val EvalResult
 	}
@@ -79,34 +74,6 @@ type (
 	}
 )
 
-// ResolveValue allows for retrieval of the value we expose for public consumption
-func (rv *RouteValue) ResolveValue(bindVars map[string]*querypb.BindVariable) (sqltypes.Value, error) {
-	env := &ExpressionEnv{
-		BindVars: bindVars,
-	}
-	evalResul, err := rv.Expr.Evaluate(env)
-	if err != nil {
-		return sqltypes.Value{}, err
-	}
-	return evalResul.Value(), nil
-}
-
-// ResolveList allows for retrieval of the value we expose for public consumption
-func (rv *RouteValue) ResolveList(bindVars map[string]*querypb.BindVariable) ([]sqltypes.Value, error) {
-	env := &ExpressionEnv{
-		BindVars: bindVars,
-	}
-	evalResul, err := rv.Expr.Evaluate(env)
-	if err != nil {
-		return nil, err
-	}
-	return evalResul.TupleValues(), nil
-}
-
-func (rv *RouteValue) MarshalJSON() ([]byte, error) {
-	return json.Marshal(FormatExpr(rv.Expr))
-}
-
 func (t TupleExpr) Collation() collations.TypedCollation {
 	// a Tuple does not have a collation, but an individual collation for every element of the tuple
 	return collations.TypedCollation{}
@@ -187,20 +154,6 @@ func (e EvalResult) Value() sqltypes.Value {
 	return e.toSQLValue(e.typ)
 }
 
-// TupleValues allows for retrieval of the value we expose for public consumption
-func (e EvalResult) TupleValues() []sqltypes.Value {
-	if e.tuple == nil {
-		return nil
-	}
-
-	values := *e.tuple
-	result := make([]sqltypes.Value, 0, len(values))
-	for _, val := range values {
-		result = append(result, val.Value())
-	}
-	return result
-}
-
 var collationNull = collations.TypedCollation{
 	Collation:    collations.CollationBinaryID,
 	Coercibility: collations.CoerceIgnorable,
@@ -298,8 +251,8 @@ func (t TupleExpr) Evaluate(env *ExpressionEnv) (EvalResult, error) {
 }
 
 // Evaluate implements the Expr interface
-func (bv *BindVariable) Evaluate(env *ExpressionEnv) (EvalResult, error) {
-	val, ok := env.BindVars[bv.Key]
+func (b *BindVariable) Evaluate(env *ExpressionEnv) (EvalResult, error) {
+	val, ok := env.BindVars[b.Key]
 	if !ok {
 		return EvalResult{}, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "Bind variable not found")
 	}
@@ -307,12 +260,12 @@ func (bv *BindVariable) Evaluate(env *ExpressionEnv) (EvalResult, error) {
 	if err != nil {
 		return EvalResult{}, err
 	}
-	eval.collation = bv.collation
+	eval.collation = b.collation
 	return eval, nil
 }
 
-func (bv *BindVariable) Collation() collations.TypedCollation {
-	return bv.collation
+func (b *BindVariable) Collation() collations.TypedCollation {
+	return b.collation
 }
 
 // Evaluate implements the Expr interface
@@ -328,11 +281,11 @@ func (c *Column) Collation() collations.TypedCollation {
 }
 
 // Type implements the Expr interface
-func (bv *BindVariable) Type(env *ExpressionEnv) (querypb.Type, error) {
+func (b *BindVariable) Type(env *ExpressionEnv) (querypb.Type, error) {
 	e := env.BindVars
-	v, found := e[bv.Key]
+	v, found := e[b.Key]
 	if !found {
-		return querypb.Type_NULL_TYPE, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "query arguments missing for %s", bv.Key)
+		return querypb.Type_NULL_TYPE, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "query arguments missing for %s", b.Key)
 	}
 	return v.Type, nil
 }
@@ -365,62 +318,40 @@ func mergeNumericalTypes(ltype, rtype querypb.Type) querypb.Type {
 	return ltype
 }
 
-func evaluateByTypeSingle(typ querypb.Type, value []byte) (EvalResult, error) {
-	switch typ {
+func evaluateByType(val *querypb.BindVariable) (EvalResult, error) {
+	switch val.Type {
 	case sqltypes.Int64:
-		ival, err := strconv.ParseInt(string(value), 10, 64)
+		ival, err := strconv.ParseInt(string(val.Value), 10, 64)
 		if err != nil {
 			ival = 0
 		}
 		return EvalResult{typ: sqltypes.Int64, numval: uint64(ival)}, nil
 	case sqltypes.Int32:
-		ival, err := strconv.ParseInt(string(value), 10, 32)
+		ival, err := strconv.ParseInt(string(val.Value), 10, 32)
 		if err != nil {
 			ival = 0
 		}
 		return EvalResult{typ: sqltypes.Int32, numval: uint64(ival)}, nil
 	case sqltypes.Uint64:
-		uval, err := strconv.ParseUint(string(value), 10, 64)
+		uval, err := strconv.ParseUint(string(val.Value), 10, 64)
 		if err != nil {
 			uval = 0
 		}
 		return EvalResult{typ: sqltypes.Uint64, numval: uval}, nil
 	case sqltypes.Float64:
-		fval, err := strconv.ParseFloat(string(value), 64)
+		fval, err := strconv.ParseFloat(string(val.Value), 64)
 		if err != nil {
 			fval = 0
 		}
 		return EvalResult{typ: sqltypes.Float64, numval: math.Float64bits(fval)}, nil
 	case sqltypes.VarChar, sqltypes.Text, sqltypes.VarBinary:
-		return EvalResult{typ: sqltypes.VarBinary, bytes: value}, nil
+		return EvalResult{typ: sqltypes.VarBinary, bytes: val.Value}, nil
 	case sqltypes.Time, sqltypes.Datetime, sqltypes.Timestamp, sqltypes.Date:
-		return EvalResult{typ: typ, bytes: value}, nil
+		return EvalResult{typ: val.Type, bytes: val.Value}, nil
 	case sqltypes.Null:
 		return EvalResult{typ: sqltypes.Null}, nil
-	default:
-		return EvalResult{}, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "Type is not supported: %s", typ.String())
-	}
-
-}
-func evaluateByType(val *querypb.BindVariable) (EvalResult, error) {
-	switch val.Type {
-	case querypb.Type_TUPLE:
-		tuple := make([]EvalResult, 0, len(val.Values))
-		for _, value := range val.Values {
-			single, err := evaluateByTypeSingle(value.Type, value.Value)
-			if err != nil {
-				return EvalResult{}, err
-			}
-			tuple = append(tuple, single)
-		}
-		return EvalResult{
-			typ:   querypb.Type_TUPLE,
-			tuple: &tuple,
-		}, nil
-
-	default:
-		return evaluateByTypeSingle(val.Type, val.Value)
 	}
+	return EvalResult{}, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "Type is not supported: %s", val.Type.String())
 }
 
 // debugString prints the entire EvalResult in a debug format
diff --git a/go/vt/vtgate/planbuilder/ddl.go b/go/vt/vtgate/planbuilder/ddl.go
index 210d456242..a7f6b67271 100644
--- a/go/vt/vtgate/planbuilder/ddl.go
+++ b/go/vt/vtgate/planbuilder/ddl.go
@@ -207,14 +207,14 @@ func buildAlterView(vschema ContextVSchema, ddl *sqlparser.AlterView, reservedVa
 	if err != nil {
 		return nil, nil, err
 	}
-	isRoutePlan, keyspaceName, opCode := tryToGetRoutePlan(selectPlan)
-	if !isRoutePlan {
+	routePlan := tryToGetRoutePlan(selectPlan)
+	if routePlan == nil {
 		return nil, nil, vterrors.New(vtrpcpb.Code_UNIMPLEMENTED, ViewComplex)
 	}
-	if keyspace.Name != keyspaceName {
+	if keyspace.Name != routePlan.GetKeyspaceName() {
 		return nil, nil, vterrors.New(vtrpcpb.Code_UNIMPLEMENTED, ViewDifferentKeyspace)
 	}
-	if opCode != engine.SelectUnsharded && opCode != engine.SelectEqualUnique && opCode != engine.SelectScatter {
+	if routePlan.Opcode != engine.SelectUnsharded && routePlan.Opcode != engine.SelectEqualUnique && routePlan.Opcode != engine.SelectScatter {
 		return nil, nil, vterrors.New(vtrpcpb.Code_UNIMPLEMENTED, ViewComplex)
 	}
 	_ = sqlparser.Rewrite(ddl.Select, func(cursor *sqlparser.Cursor) bool {
@@ -243,14 +243,14 @@ func buildCreateView(vschema ContextVSchema, ddl *sqlparser.CreateView, reserved
 	if err != nil {
 		return nil, nil, err
 	}
-	isRoutePlan, keyspaceName, opCode := tryToGetRoutePlan(selectPlan)
-	if !isRoutePlan {
+	routePlan := tryToGetRoutePlan(selectPlan)
+	if routePlan == nil {
 		return nil, nil, vterrors.New(vtrpcpb.Code_UNIMPLEMENTED, ViewComplex)
 	}
-	if keyspace.Name != keyspaceName {
+	if keyspace.Name != routePlan.GetKeyspaceName() {
 		return nil, nil, vterrors.New(vtrpcpb.Code_UNIMPLEMENTED, ViewDifferentKeyspace)
 	}
-	if opCode != engine.SelectUnsharded && opCode != engine.SelectEqualUnique && opCode != engine.SelectScatter {
+	if routePlan.Opcode != engine.SelectUnsharded && routePlan.Opcode != engine.SelectEqualUnique && routePlan.Opcode != engine.SelectScatter {
 		return nil, nil, vterrors.New(vtrpcpb.Code_UNIMPLEMENTED, ViewComplex)
 	}
 	_ = sqlparser.Rewrite(ddl.Select, func(cursor *sqlparser.Cursor) bool {
@@ -363,13 +363,13 @@ func buildRenameTable(vschema ContextVSchema, renameTable *sqlparser.RenameTable
 	return destination, keyspace, nil
 }
 
-func tryToGetRoutePlan(selectPlan engine.Primitive) (valid bool, keyspaceName string, opCode engine.RouteOpcode) {
-	switch plan := selectPlan.(type) {
-	case *engine.Route:
-		return true, plan.Keyspace.Name, plan.Opcode
-	case engine.Gen4Comparer:
-		return tryToGetRoutePlan(plan.GetGen4Primitive())
-	default:
-		return false, "", engine.RouteOpcode(0)
+func tryToGetRoutePlan(selectPlan engine.Primitive) *engine.Route {
+	routePlan, isRoute := selectPlan.(*engine.Route)
+	if !isRoute {
+		comparer, isComparer := selectPlan.(engine.Gen4Comparer)
+		if isComparer {
+			return tryToGetRoutePlan(comparer.GetGen4Primitive())
+		}
 	}
+	return routePlan
 }
diff --git a/go/vt/vtgate/planbuilder/from.go b/go/vt/vtgate/planbuilder/from.go
index 0d33950996..aeaa93c9c1 100644
--- a/go/vt/vtgate/planbuilder/from.go
+++ b/go/vt/vtgate/planbuilder/from.go
@@ -262,7 +262,7 @@ func (pb *primitiveBuilder) buildTablePrimitive(tableExpr *sqlparser.AliasedTabl
 		eroute = engine.NewSimpleRoute(engine.SelectEqualUnique, vschemaTable.Keyspace)
 		vindex, _ = vindexes.NewBinary("binary", nil)
 		eroute.Vindex, _ = vindex.(vindexes.SingleColumn)
-		eroute.Value = sqltypes.PlanValue{Value: sqltypes.MakeTrusted(sqltypes.VarBinary, vschemaTable.Pinned)}
+		eroute.Values = []sqltypes.PlanValue{{Value: sqltypes.MakeTrusted(sqltypes.VarBinary, vschemaTable.Pinned)}}
 	}
 	eroute.TableName = sqlparser.String(vschemaTable.Name)
 	rb.eroute = eroute
diff --git a/go/vt/vtgate/planbuilder/gen4_planner.go b/go/vt/vtgate/planbuilder/gen4_planner.go
index 76e78365b3..ca6cd6b971 100644
--- a/go/vt/vtgate/planbuilder/gen4_planner.go
+++ b/go/vt/vtgate/planbuilder/gen4_planner.go
@@ -198,7 +198,7 @@ func planLimit(limit *sqlparser.Limit, plan logicalPlan) (logicalPlan, error) {
 	if limit == nil {
 		return plan, nil
 	}
-	rb, ok := plan.(*routeGen4)
+	rb, ok := plan.(*route)
 	if ok && rb.isSingleShard() {
 		rb.SetLimit(limit)
 		return plan, nil
@@ -236,7 +236,7 @@ func planHorizon(ctx *planningContext, plan logicalPlan, in sqlparser.SelectStat
 		}
 	case *sqlparser.Union:
 		var err error
-		rb, isRoute := plan.(*routeGen4)
+		rb, isRoute := plan.(*route)
 		if !isRoute && ctx.semTable.ProjectionErr != nil {
 			return nil, ctx.semTable.ProjectionErr
 		}
@@ -285,7 +285,7 @@ func pushCommentDirectivesOnPlan(plan logicalPlan, stmt sqlparser.SelectStatemen
 	if scatterAsWarns || queryTimeout > 0 {
 		_, _ = visit(plan, func(logicalPlan logicalPlan) (bool, logicalPlan, error) {
 			switch plan := logicalPlan.(type) {
-			case *routeGen4:
+			case *route:
 				plan.eroute.ScatterErrorsAsWarnings = scatterAsWarns
 				plan.eroute.QueryTimeout = queryTimeout
 			}
diff --git a/go/vt/vtgate/planbuilder/horizon_planning.go b/go/vt/vtgate/planbuilder/horizon_planning.go
index 2911f49cbe..11e8989844 100644
--- a/go/vt/vtgate/planbuilder/horizon_planning.go
+++ b/go/vt/vtgate/planbuilder/horizon_planning.go
@@ -38,7 +38,7 @@ type horizonPlanning struct {
 }
 
 func (hp *horizonPlanning) planHorizon(ctx *planningContext, plan logicalPlan) (logicalPlan, error) {
-	rb, isRoute := plan.(*routeGen4)
+	rb, isRoute := plan.(*route)
 	if !isRoute && ctx.semTable.ProjectionErr != nil {
 		return nil, ctx.semTable.ProjectionErr
 	}
@@ -138,7 +138,7 @@ func (hp *horizonPlanning) truncateColumnsIfNeeded(plan logicalPlan) error {
 	}
 
 	switch p := plan.(type) {
-	case *routeGen4:
+	case *route:
 		p.eroute.SetTruncateColumnCount(hp.sel.GetColumnCount())
 	case *joinGen4, *semiJoin, *hashJoin:
 		// since this is a join, we can safely add extra columns and not need to truncate them
@@ -160,7 +160,7 @@ func (hp *horizonPlanning) truncateColumnsIfNeeded(plan logicalPlan) error {
 // pushProjection pushes a projection to the plan.
 func pushProjection(expr *sqlparser.AliasedExpr, plan logicalPlan, semTable *semantics.SemTable, inner, reuseCol, hasAggregation bool) (offset int, added bool, err error) {
 	switch node := plan.(type) {
-	case *routeGen4:
+	case *route:
 		value, err := makePlanValue(expr.Expr)
 		if err != nil {
 			return 0, false, err
@@ -543,7 +543,7 @@ func (hp *horizonPlanning) planAggregations(ctx *planningContext, plan logicalPl
 	}
 
 	// done with aggregation planning. let's check if we should fail the query
-	if _, planIsRoute := plan.(*routeGen4); !planIsRoute {
+	if _, planIsRoute := plan.(*route); !planIsRoute {
 		// if we had to build up additional operators around the route, we have to fail this query
 		for _, expr := range hp.qp.SelectExprs {
 			colExpr, err := expr.GetExpr()
@@ -611,7 +611,7 @@ func hasUniqueVindex(vschema ContextVSchema, semTable *semantics.SemTable, group
 
 func planGroupByGen4(groupExpr abstract.GroupBy, plan logicalPlan, semTable *semantics.SemTable, wsAdded bool) (bool, error) {
 	switch node := plan.(type) {
-	case *routeGen4:
+	case *route:
 		sel := node.Select.(*sqlparser.Select)
 		sel.GroupBy = append(sel.GroupBy, groupExpr.Inner)
 		// If a weight_string function is added to the select list,
@@ -676,7 +676,7 @@ func (hp *horizonPlanning) planGroupByUsingOrderBy(ctx *planningContext, plan lo
 
 func (hp *horizonPlanning) planOrderBy(ctx *planningContext, orderExprs []abstract.OrderBy, plan logicalPlan) (logicalPlan, error) {
 	switch plan := plan.(type) {
-	case *routeGen4:
+	case *route:
 		newPlan, truncate, err := planOrderByForRoute(orderExprs, plan, ctx.semTable, hp.qp.HasStar)
 		if err != nil {
 			return nil, err
@@ -757,7 +757,7 @@ func isSpecialOrderBy(o abstract.OrderBy) bool {
 	return isFunction && f.Name.Lowered() == "rand"
 }
 
-func planOrderByForRoute(orderExprs []abstract.OrderBy, plan *routeGen4, semTable *semantics.SemTable, hasStar bool) (logicalPlan, bool, error) {
+func planOrderByForRoute(orderExprs []abstract.OrderBy, plan *route, semTable *semantics.SemTable, hasStar bool) (logicalPlan, bool, error) {
 	origColCount := plan.Select.GetColumnCount()
 	for _, order := range orderExprs {
 		err := checkOrderExprCanBePlannedInScatter(plan, order, hasStar)
@@ -784,7 +784,7 @@ func planOrderByForRoute(orderExprs []abstract.OrderBy, plan *routeGen4, semTabl
 
 // checkOrderExprCanBePlannedInScatter verifies that the given order by expression can be planned.
 // It checks if the expression exists in the plan's select list when the query is a scatter.
-func checkOrderExprCanBePlannedInScatter(plan *routeGen4, order abstract.OrderBy, hasStar bool) error {
+func checkOrderExprCanBePlannedInScatter(plan *route, order abstract.OrderBy, hasStar bool) error {
 	if !hasStar {
 		return nil
 	}
@@ -996,7 +996,7 @@ func (hp *horizonPlanning) planDistinct(ctx *planningContext, plan logicalPlan)
 		return plan, nil
 	}
 	switch p := plan.(type) {
-	case *routeGen4:
+	case *route:
 		// we always make the underlying query distinct,
 		// and then we might also add a distinct operator on top if it is needed
 		p.Select.MakeDistinct()
@@ -1158,7 +1158,7 @@ func (hp *horizonPlanning) needDistinctHandling(ctx *planningContext, funcExpr *
 	if !ok {
 		return false, nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "syntax error: %s", sqlparser.String(funcExpr))
 	}
-	_, ok = input.(*routeGen4)
+	_, ok = input.(*route)
 	if !ok {
 		// Unreachable
 		return true, innerAliased, nil
@@ -1180,7 +1180,7 @@ func (hp *horizonPlanning) planHaving(ctx *planningContext, plan logicalPlan) (l
 
 func pushHaving(expr sqlparser.Expr, plan logicalPlan, semTable *semantics.SemTable) (logicalPlan, error) {
 	switch node := plan.(type) {
-	case *routeGen4:
+	case *route:
 		sel := sqlparser.GetFirstSelect(node.Select)
 		sel.AddHaving(expr)
 		return plan, nil
diff --git a/go/vt/vtgate/planbuilder/postprocess.go b/go/vt/vtgate/planbuilder/postprocess.go
index a965f3d82e..984cfed1f6 100644
--- a/go/vt/vtgate/planbuilder/postprocess.go
+++ b/go/vt/vtgate/planbuilder/postprocess.go
@@ -126,11 +126,6 @@ func setUpperLimit(plan logicalPlan) (bool, logicalPlan, error) {
 		// If it's a scatter query, the rows returned will be
 		// more than the upper limit, but enough for the limit
 		node.Select.SetLimit(&sqlparser.Limit{Rowcount: arg})
-	case *routeGen4:
-		// The route pushes the limit regardless of the plan.
-		// If it's a scatter query, the rows returned will be
-		// more than the upper limit, but enough for the limit
-		node.Select.SetLimit(&sqlparser.Limit{Rowcount: arg})
 	case *concatenate:
 		return false, node, nil
 	}
diff --git a/go/vt/vtgate/planbuilder/querytree_transformers.go b/go/vt/vtgate/planbuilder/querytree_transformers.go
index 6d2a05166b..bf37100169 100644
--- a/go/vt/vtgate/planbuilder/querytree_transformers.go
+++ b/go/vt/vtgate/planbuilder/querytree_transformers.go
@@ -24,6 +24,8 @@ import (
 
 	"vitess.io/vitess/go/vt/vtgate/evalengine"
 
+	"vitess.io/vitess/go/sqltypes"
+
 	vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc"
 	"vitess.io/vitess/go/vt/sqlparser"
 	"vitess.io/vitess/go/vt/vtgate/engine"
@@ -67,7 +69,7 @@ func transformCorrelatedSubquery(ctx *planningContext, tree *correlatedSubqueryT
 
 func pushDistinct(plan logicalPlan) {
 	switch n := plan.(type) {
-	case *routeGen4:
+	case *route:
 		n.Select.MakeDistinct()
 	case *concatenateGen4:
 		for _, source := range n.sources {
@@ -131,11 +133,11 @@ func transformSubqueryTree(ctx *planningContext, n *subqueryTree) (logicalPlan,
 }
 
 func mergeSubQueryPlan(ctx *planningContext, inner, outer logicalPlan, n *subqueryTree) logicalPlan {
-	iroute, ok := inner.(*routeGen4)
+	iroute, ok := inner.(*route)
 	if !ok {
 		return nil
 	}
-	oroute, ok := outer.(*routeGen4)
+	oroute, ok := outer.(*route)
 	if !ok {
 		return nil
 	}
@@ -151,7 +153,7 @@ func mergeSubQueryPlan(ctx *planningContext, inner, outer logicalPlan, n *subque
 }
 
 // mergeSystemTableInformation copies over information from the second route to the first and appends to it
-func mergeSystemTableInformation(a *routeGen4, b *routeGen4) logicalPlan {
+func mergeSystemTableInformation(a *route, b *route) logicalPlan {
 	// safe to append system table schema and system table names, since either the routing will match or either side would be throwing an error
 	// during run-time which we want to preserve. For example outer side has User in sys table schema and inner side has User and Main in sys table schema
 	// Inner might end up throwing an error at runtime, but if it doesn't then it is safe to merge.
@@ -178,7 +180,7 @@ func transformDerivedPlan(ctx *planningContext, n *derivedTree) (logicalPlan, er
 		return nil, err
 	}
 
-	rb, isRoute := plan.(*routeGen4)
+	rb, isRoute := plan.(*route)
 	if !isRoute {
 		return &simpleProjection{
 			logicalPlanCommon: newBuilderCommon(plan),
@@ -228,7 +230,7 @@ func transformConcatenatePlan(ctx *planningContext, n *concatenateTree) (logical
 	var result logicalPlan
 	if len(sources) == 1 {
 		src := sources[0]
-		if rb, isRoute := src.(*routeGen4); isRoute && rb.isSingleShard() {
+		if rb, isRoute := src.(*route); isRoute && rb.isSingleShard() {
 			// if we have a single shard route, we don't need to do anything to make it distinct
 			rb.Select.SetLimit(n.limit)
 			rb.Select.SetOrderBy(n.ordering)
@@ -326,11 +328,11 @@ func transformAndMerge(ctx *planningContext, n *concatenateTree) ([]logicalPlan,
 }
 
 func mergeUnionLogicalPlans(ctx *planningContext, left logicalPlan, right logicalPlan) logicalPlan {
-	lroute, ok := left.(*routeGen4)
+	lroute, ok := left.(*route)
 	if !ok {
 		return nil
 	}
-	rroute, ok := right.(*routeGen4)
+	rroute, ok := right.(*route)
 	if !ok {
 		return nil
 	}
@@ -359,7 +361,7 @@ func createLogicalPlan(ctx *planningContext, source queryTree, selStmt *sqlparse
 	return plan, nil
 }
 
-func transformRoutePlan(ctx *planningContext, n *routeTree) (*routeGen4, error) {
+func transformRoutePlan(ctx *planningContext, n *routeTree) (*route, error) {
 	var tablesForSelect sqlparser.TableExprs
 	tableNameMap := map[string]interface{}{}
 
@@ -428,14 +430,10 @@ func transformRoutePlan(ctx *planningContext, n *routeTree) (*routeGen4, error)
 	}
 
 	var singleColumn vindexes.SingleColumn
-	var value engine.RouteValue
+	var values []sqltypes.PlanValue
 	if n.selectedVindex() != nil {
-		vdx, ok := n.selected.foundVindex.(vindexes.SingleColumn)
-		if !ok || len(n.selected.values) != 1 {
-			return nil, vterrors.New(vtrpcpb.Code_UNIMPLEMENTED, "unsupported: multi-column values")
-		}
-		singleColumn = vdx
-		value = &evalengine.RouteValue{Expr: n.selected.values[0]}
+		singleColumn = n.selected.foundVindex.(vindexes.SingleColumn)
+		values = n.selected.values
 	}
 
 	var expressions sqlparser.SelectExprs
@@ -466,13 +464,13 @@ func transformRoutePlan(ctx *planningContext, n *routeTree) (*routeGen4, error)
 	if n.selected != nil && len(n.selected.valueExprs) > 0 {
 		condition = n.selected.valueExprs[0]
 	}
-	return &routeGen4{
+	return &route{
 		eroute: &engine.Route{
 			Opcode:              n.routeOpCode,
 			TableName:           strings.Join(tableNames, ", "),
 			Keyspace:            n.keyspace,
 			Vindex:              singleColumn,
-			Value:               value,
+			Values:              values,
 			SysTableTableName:   n.SysTableTableName,
 			SysTableTableSchema: n.SysTableTableSchema,
 		},
diff --git a/go/vt/vtgate/planbuilder/route.go b/go/vt/vtgate/planbuilder/route.go
index 851b3a9318..8561000b64 100644
--- a/go/vt/vtgate/planbuilder/route.go
+++ b/go/vt/vtgate/planbuilder/route.go
@@ -145,7 +145,7 @@ func (rb *route) WireupGen4(semTable *semantics.SemTable) error {
 	return nil
 }
 
-// ContainsTables implements the logicalPlan interface
+// Solves implements the logicalPlan interface
 func (rb *route) ContainsTables() semantics.TableSet {
 	return rb.tables
 }
@@ -153,7 +153,7 @@ func (rb *route) ContainsTables() semantics.TableSet {
 // Wireup implements the logicalPlan interface
 func (rb *route) Wireup(plan logicalPlan, jt *jointab) error {
 	// Precaution: update ERoute.Values only if it's not set already.
-	if rb.eroute.Value == nil {
+	if rb.eroute.Values == nil {
 		// Resolve values stored in the logical plan.
 		switch vals := rb.condition.(type) {
 		case *sqlparser.ComparisonExpr:
@@ -161,7 +161,7 @@ func (rb *route) Wireup(plan logicalPlan, jt *jointab) error {
 			if err != nil {
 				return err
 			}
-			rb.eroute.Value = pv
+			rb.eroute.Values = []sqltypes.PlanValue{pv}
 			vals.Right = sqlparser.ListArg(engine.ListVarName)
 		case nil:
 			// no-op.
@@ -170,7 +170,7 @@ func (rb *route) Wireup(plan logicalPlan, jt *jointab) error {
 			if err != nil {
 				return err
 			}
-			rb.eroute.Value = pv
+			rb.eroute.Values = []sqltypes.PlanValue{pv}
 		}
 	}
 
@@ -179,11 +179,11 @@ func (rb *route) Wireup(plan logicalPlan, jt *jointab) error {
 		switch node := node.(type) {
 		case *sqlparser.Select:
 			if len(node.SelectExprs) == 0 {
-				node.SelectExprs = []sqlparser.SelectExpr{
+				node.SelectExprs = sqlparser.SelectExprs([]sqlparser.SelectExpr{
 					&sqlparser.AliasedExpr{
 						Expr: sqlparser.NewIntLiteral("1"),
 					},
-				}
+				})
 			}
 		case *sqlparser.ComparisonExpr:
 			if node.Operator == sqlparser.EqualOp {
diff --git a/go/vt/vtgate/planbuilder/routeGen4.go b/go/vt/vtgate/planbuilder/routeGen4.go
deleted file mode 100644
index c0d8c0a3d1..0000000000
--- a/go/vt/vtgate/planbuilder/routeGen4.go
+++ /dev/null
@@ -1,239 +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/vterrors"
-	"vitess.io/vitess/go/vt/vtgate/semantics"
-
-	"vitess.io/vitess/go/sqltypes"
-	"vitess.io/vitess/go/vt/sqlparser"
-	"vitess.io/vitess/go/vt/vtgate/engine"
-	"vitess.io/vitess/go/vt/vtgate/vindexes"
-)
-
-var _ logicalPlan = (*routeGen4)(nil)
-
-// routeGen4 is used to build a Route primitive.
-// It's used to build one of the Select routes like
-// SelectScatter, etc. Portions of the original Select AST
-// are moved into this node, which will be used to build
-// the final SQL for this route.
-type routeGen4 struct {
-	gen4Plan
-
-	// Select is the AST for the query fragment that will be
-	// executed by this route.
-	Select sqlparser.SelectStatement
-
-	// condition stores the AST condition that will be used
-	// to resolve the ERoute Values field.
-	condition sqlparser.Expr
-
-	// eroute is the primitive being built.
-	eroute *engine.Route
-
-	// tables keeps track of which tables this route is covering
-	tables semantics.TableSet
-}
-
-// Primitive implements the logicalPlan interface
-func (rb *routeGen4) Primitive() engine.Primitive {
-	return rb.eroute
-}
-
-// SetLimit adds a LIMIT clause to the route.
-func (rb *routeGen4) SetLimit(limit *sqlparser.Limit) {
-	rb.Select.SetLimit(limit)
-}
-
-// WireupGen4 implements the logicalPlan interface
-func (rb *routeGen4) WireupGen4(_ *semantics.SemTable) error {
-	rb.prepareTheAST()
-
-	rb.eroute.Query = sqlparser.String(rb.Select)
-
-	buffer := sqlparser.NewTrackedBuffer(sqlparser.FormatImpossibleQuery)
-	node := buffer.WriteNode(rb.Select)
-	query := node.ParsedQuery()
-	rb.eroute.FieldQuery = query.Query
-	return nil
-}
-
-// ContainsTables implements the logicalPlan interface
-func (rb *routeGen4) ContainsTables() semantics.TableSet {
-	return rb.tables
-}
-
-// prepareTheAST does minor fixups of the SELECT struct before producing the query string
-func (rb *routeGen4) prepareTheAST() {
-	_ = sqlparser.Walk(func(node sqlparser.SQLNode) (bool, error) {
-		switch node := node.(type) {
-		case *sqlparser.Select:
-			if len(node.SelectExprs) == 0 {
-				node.SelectExprs = []sqlparser.SelectExpr{
-					&sqlparser.AliasedExpr{
-						Expr: sqlparser.NewIntLiteral("1"),
-					},
-				}
-			}
-		case *sqlparser.ComparisonExpr:
-			// 42 = colName -> colName = 42
-			b := node.Operator == sqlparser.EqualOp
-			value := sqlparser.IsValue(node.Left)
-			name := sqlparser.IsColName(node.Right)
-			if b &&
-				value &&
-				name {
-				node.Left, node.Right = node.Right, node.Left
-			}
-		}
-		return true, nil
-	}, rb.Select)
-}
-
-// procureValues procures and converts the input into
-// the expected types for rb.Values.
-func (rb *routeGen4) procureValues(plan logicalPlan, jt *jointab, val sqlparser.Expr) (sqltypes.PlanValue, error) {
-	switch val := val.(type) {
-	case sqlparser.ValTuple:
-		pv := sqltypes.PlanValue{}
-		for _, val := range val {
-			v, err := rb.procureValues(plan, jt, val)
-			if err != nil {
-				return pv, err
-			}
-			pv.Values = append(pv.Values, v)
-		}
-		return pv, nil
-	case *sqlparser.ColName:
-		joinVar := jt.Procure(plan, val, rb.Order())
-		return sqltypes.PlanValue{Key: joinVar}, nil
-	default:
-		return sqlparser.NewPlanValue(val)
-	}
-}
-
-func (rb *routeGen4) isLocal(col *sqlparser.ColName) bool {
-	return col.Metadata.(*column).Origin() == rb
-}
-
-// generateFieldQuery generates a query with an impossible where.
-// This will be used on the RHS node to fetch field info if the LHS
-// returns no result.
-func (rb *routeGen4) generateFieldQuery(sel sqlparser.SelectStatement, jt *jointab) string {
-	formatter := func(buf *sqlparser.TrackedBuffer, node sqlparser.SQLNode) {
-		switch node := node.(type) {
-		case *sqlparser.ColName:
-			if !rb.isLocal(node) {
-				_, joinVar := jt.Lookup(node)
-				buf.WriteArg(":", joinVar)
-				return
-			}
-		case sqlparser.TableName:
-			if !sqlparser.SystemSchema(node.Qualifier.String()) {
-				node.Name.Format(buf)
-				return
-			}
-			node.Format(buf)
-			return
-		}
-		sqlparser.FormatImpossibleQuery(buf, node)
-	}
-
-	buffer := sqlparser.NewTrackedBuffer(formatter)
-	node := buffer.WriteNode(sel)
-	query := node.ParsedQuery()
-	return query.Query
-}
-
-// Rewrite implements the logicalPlan interface
-func (rb *routeGen4) Rewrite(inputs ...logicalPlan) error {
-	if len(inputs) != 0 {
-		return vterrors.Errorf(vtrpcpb.Code_INTERNAL, "route: wrong number of inputs")
-	}
-	return nil
-}
-
-// Inputs implements the logicalPlan interface
-func (rb *routeGen4) Inputs() []logicalPlan {
-	return []logicalPlan{}
-}
-
-func (rb *routeGen4) isSingleShard() bool {
-	switch rb.eroute.Opcode {
-	case engine.SelectUnsharded, engine.SelectDBA, engine.SelectNext, engine.SelectEqualUnique, engine.SelectReference:
-		return true
-	}
-	return false
-}
-
-func (rb *routeGen4) unionCanMerge(other *routeGen4, distinct bool) bool {
-	if rb.eroute.Keyspace.Name != other.eroute.Keyspace.Name {
-		return false
-	}
-	switch rb.eroute.Opcode {
-	case engine.SelectUnsharded, 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) {
-			return true
-		}
-	case engine.SelectScatter:
-		return other.eroute.Opcode == engine.SelectScatter && !distinct
-	case engine.SelectNext:
-		return false
-	}
-	return false
-}
-
-func (rb *routeGen4) updateRoute(opcode engine.RouteOpcode, vindex vindexes.SingleColumn, condition sqlparser.Expr) {
-	rb.eroute.Opcode = opcode
-	rb.eroute.Vindex = vindex
-	rb.condition = condition
-}
-
-// computeNotInPlan looks for null values to produce a SelectNone if found
-func (rb *routeGen4) computeNotInPlan(right sqlparser.Expr) engine.RouteOpcode {
-	switch node := right.(type) {
-	case sqlparser.ValTuple:
-		for _, n := range node {
-			if sqlparser.IsNull(n) {
-				return engine.SelectNone
-			}
-		}
-	}
-
-	return engine.SelectScatter
-}
-
-// exprIsValue returns true if the expression can be treated as a value
-// for the routeOption. External references are treated as value.
-func (rb *routeGen4) exprIsValue(expr sqlparser.Expr) bool {
-	if node, ok := expr.(*sqlparser.ColName); ok {
-		return node.Metadata.(*column).Origin() != rb
-	}
-	return sqlparser.IsValue(expr)
-}
diff --git a/go/vt/vtgate/planbuilder/route_planning.go b/go/vt/vtgate/planbuilder/route_planning.go
index 7f14d84d8e..74182ce5da 100644
--- a/go/vt/vtgate/planbuilder/route_planning.go
+++ b/go/vt/vtgate/planbuilder/route_planning.go
@@ -20,8 +20,7 @@ import (
 	"io"
 	"sort"
 
-	"vitess.io/vitess/go/mysql/collations"
-
+	"vitess.io/vitess/go/sqltypes"
 	"vitess.io/vitess/go/vt/vtgate/evalengine"
 
 	"vitess.io/vitess/go/vt/vtgate/planbuilder/abstract"
@@ -412,7 +411,7 @@ func exprHasUniqueVindex(vschema ContextVSchema, semTable *semantics.SemTable, e
 	return false
 }
 
-func planSingleShardRoutePlan(sel sqlparser.SelectStatement, rb *routeGen4) error {
+func planSingleShardRoutePlan(sel sqlparser.SelectStatement, rb *route) error {
 	err := stripDownQuery(sel, rb.Select)
 	if err != nil {
 		return err
@@ -869,7 +868,7 @@ func createRoutePlan(ctx *planningContext, table *abstract.QueryTable, solves se
 		vindex, _ := vindexes.NewBinary("binary", nil)
 		plan.selected = &vindexOption{
 			ready:       true,
-			values:      []evalengine.Expr{evalengine.NewLiteralString(vschemaTable.Pinned, collations.TypedCollation{})},
+			values:      []sqltypes.PlanValue{{Value: sqltypes.MakeTrusted(sqltypes.VarBinary, vschemaTable.Pinned)}},
 			valueExprs:  nil,
 			predicates:  nil,
 			opcode:      engine.SelectEqualUnique,
@@ -970,7 +969,7 @@ func canMergeOnFilters(ctx *planningContext, a, b *routeTree, joinPredicates []s
 
 type mergeFunc func(a, b *routeTree) (*routeTree, error)
 
-func canMergeUnionPlans(ctx *planningContext, a, b *routeGen4) bool {
+func canMergeUnionPlans(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
@@ -997,7 +996,7 @@ func canMergeUnionPlans(ctx *planningContext, a, b *routeGen4) bool {
 	return false
 }
 
-func canMergeSubqueryPlans(ctx *planningContext, a, b *routeGen4) bool {
+func canMergeSubqueryPlans(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
@@ -1020,7 +1019,7 @@ func canMergeSubqueryPlans(ctx *planningContext, a, b *routeGen4) bool {
 	return false
 }
 
-func canSelectDBAMerge(a, b *routeGen4) bool {
+func canSelectDBAMerge(a, b *route) bool {
 	if a.eroute.Opcode != engine.SelectDBA {
 		return false
 	}
diff --git a/go/vt/vtgate/planbuilder/routetree.go b/go/vt/vtgate/planbuilder/routetree.go
index 18f99cc497..1245d4d46c 100644
--- a/go/vt/vtgate/planbuilder/routetree.go
+++ b/go/vt/vtgate/planbuilder/routetree.go
@@ -19,8 +19,6 @@ package planbuilder
 import (
 	"strings"
 
-	"vitess.io/vitess/go/mysql/collations"
-
 	vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc"
 	"vitess.io/vitess/go/vt/vterrors"
 
@@ -82,7 +80,7 @@ type (
 	// vindexOption stores the information needed to know if we have all the information needed to use a vindex
 	vindexOption struct {
 		ready       bool
-		values      []evalengine.Expr
+		values      []sqltypes.PlanValue
 		valueExprs  []sqlparser.Expr
 		predicates  []sqlparser.Expr
 		opcode      engine.RouteOpcode
@@ -184,7 +182,11 @@ func (rp *routeTree) removePredicate(ctx *planningContext, expr sqlparser.Expr)
 // they will improve the routeOpCode
 func (rp *routeTree) addPredicate(ctx *planningContext, predicates ...sqlparser.Expr) error {
 	if rp.canImprove() {
-		newVindexFound := rp.searchForNewVindexes(ctx, predicates)
+		newVindexFound, err := rp.searchForNewVindexes(ctx, predicates)
+		if err != nil {
+			return err
+		}
+
 		// if we didn't open up any new vindex options, no need to enter here
 		if newVindexFound {
 			rp.pickBestAvailableVindex()
@@ -202,7 +204,7 @@ func (rp *routeTree) canImprove() bool {
 	return rp.routeOpCode != engine.SelectNone
 }
 
-func (rp *routeTree) searchForNewVindexes(ctx *planningContext, predicates []sqlparser.Expr) bool {
+func (rp *routeTree) searchForNewVindexes(ctx *planningContext, predicates []sqlparser.Expr) (bool, error) {
 	newVindexFound := false
 	for _, filter := range predicates {
 		switch node := filter.(type) {
@@ -218,53 +220,66 @@ func (rp *routeTree) searchForNewVindexes(ctx *planningContext, predicates []sql
 				Right:    &sqlparser.Subquery{Select: node.Subquery.Select},
 				Operator: originalCmp.Operator,
 			}
-			found, exitEarly := rp.planComparison(ctx, cmp)
-			if exitEarly {
-				return false
+			found, exitEarly, err := rp.planComparison(ctx, cmp)
+			if err != nil || exitEarly {
+				return false, err
 			}
 			newVindexFound = newVindexFound || found
 		case *sqlparser.ComparisonExpr:
-			found, exitEarly := rp.planComparison(ctx, node)
-			if exitEarly {
-				return false
+			found, exitEarly, err := rp.planComparison(ctx, node)
+			if err != nil || exitEarly {
+				return false, err
 			}
 			newVindexFound = newVindexFound || found
 		case *sqlparser.IsExpr:
-			found := rp.planIsExpr(ctx, node)
+			found, err := rp.planIsExpr(ctx, node)
+			if err != nil {
+				return false, err
+			}
 			newVindexFound = newVindexFound || found
 		}
 	}
-	return newVindexFound
+	return newVindexFound, nil
 }
 
-func (rp *routeTree) planComparison(ctx *planningContext, node *sqlparser.ComparisonExpr) (bool, bool) {
+func (rp *routeTree) planComparison(ctx *planningContext, node *sqlparser.ComparisonExpr) (bool, bool, error) {
 	if sqlparser.IsNull(node.Left) || sqlparser.IsNull(node.Right) {
 		// we are looking at ANDed predicates in the WHERE clause.
 		// since we know that nothing returns true when compared to NULL,
 		// so we can safely bail out here
 		rp.routeOpCode = engine.SelectNone
-		return false, true
+		return false, true, nil
 	}
 
 	switch node.Operator {
 	case sqlparser.EqualOp:
-		return rp.planEqualOp(ctx, node), false
+		found, err := rp.planEqualOp(ctx, node)
+		if err != nil {
+			return false, false, err
+		}
+		return found, false, nil
 	case sqlparser.InOp:
 		if rp.isImpossibleIN(node) {
-			return false, true
+			return false, true, nil
 		}
-		found := rp.planInOp(ctx, node)
-		return found, false
+		found, err := rp.planInOp(ctx, node)
+		if err != nil {
+			return false, false, err
+		}
+		return found, false, nil
 	case sqlparser.NotInOp:
 		// NOT IN is always a scatter, except when we can be sure it would return nothing
 		if rp.isImpossibleNotIN(node) {
-			return false, true
+			return false, true, nil
 		}
 	case sqlparser.LikeOp:
-		found := rp.planLikeOp(ctx, node)
-		return found, false
+		found, err := rp.planLikeOp(ctx, node)
+		if err != nil {
+			return false, false, err
+		}
+		return found, false, nil
 	}
-	return false, false
+	return false, false, nil
 }
 
 func (rp *routeTree) isImpossibleIN(node *sqlparser.ComparisonExpr) bool {
@@ -293,7 +308,7 @@ func (rp *routeTree) isImpossibleNotIN(node *sqlparser.ComparisonExpr) bool {
 	return false
 }
 
-func (rp *routeTree) planEqualOp(ctx *planningContext, node *sqlparser.ComparisonExpr) bool {
+func (rp *routeTree) planEqualOp(ctx *planningContext, node *sqlparser.ComparisonExpr) (bool, error) {
 	column, ok := node.Left.(*sqlparser.ColName)
 	other := node.Right
 	vdValue := other
@@ -301,44 +316,44 @@ func (rp *routeTree) planEqualOp(ctx *planningContext, node *sqlparser.Compariso
 		column, ok = node.Right.(*sqlparser.ColName)
 		if !ok {
 			// either the LHS or RHS have to be a column to be useful for the vindex
-			return false
+			return false, nil
 		}
 		vdValue = node.Left
 	}
-	val := rp.makeEvalEngineExpr(ctx, vdValue)
-	if val == nil {
-		return false
+	val, err := rp.makePlanValue(ctx, vdValue)
+	if err != nil || val == nil {
+		return false, err
 	}
 
-	return rp.haveMatchingVindex(ctx, node, vdValue, column, val, equalOrEqualUnique, justTheVindex)
+	return rp.haveMatchingVindex(ctx, node, vdValue, column, *val, equalOrEqualUnique, justTheVindex), err
 }
 
-func (rp *routeTree) planSimpleInOp(ctx *planningContext, node *sqlparser.ComparisonExpr, left *sqlparser.ColName) bool {
+func (rp *routeTree) planSimpleInOp(ctx *planningContext, node *sqlparser.ComparisonExpr, left *sqlparser.ColName) (bool, error) {
 	vdValue := node.Right
-	value := rp.makeEvalEngineExpr(ctx, vdValue)
-	if value == nil {
-		return false
+	value, err := rp.makePlanValue(ctx, vdValue)
+	if err != nil || value == nil {
+		return false, err
 	}
 	switch nodeR := vdValue.(type) {
 	case sqlparser.ValTuple:
 		if len(nodeR) == 1 && sqlparser.IsNull(nodeR[0]) {
 			rp.routeOpCode = engine.SelectNone
-			return false
+			return false, nil
 		}
 	}
 	opcode := func(*vindexes.ColumnVindex) engine.RouteOpcode { return engine.SelectIN }
-	return rp.haveMatchingVindex(ctx, node, vdValue, left, value, opcode, justTheVindex)
+	return rp.haveMatchingVindex(ctx, node, vdValue, left, *value, opcode, justTheVindex), err
 }
 
-func (rp *routeTree) planCompositeInOp(ctx *planningContext, node *sqlparser.ComparisonExpr, left sqlparser.ValTuple) bool {
+func (rp *routeTree) planCompositeInOp(ctx *planningContext, node *sqlparser.ComparisonExpr, left sqlparser.ValTuple) (bool, error) {
 	right, rightIsValTuple := node.Right.(sqlparser.ValTuple)
 	if !rightIsValTuple {
-		return false
+		return false, nil
 	}
 	return rp.planCompositeInOpRecursive(ctx, node, left, right, nil)
 }
 
-func (rp *routeTree) planCompositeInOpRecursive(ctx *planningContext, node *sqlparser.ComparisonExpr, left, right sqlparser.ValTuple, coordinates []int) bool {
+func (rp *routeTree) planCompositeInOpRecursive(ctx *planningContext, node *sqlparser.ComparisonExpr, left, right sqlparser.ValTuple, coordinates []int) (bool, error) {
 	foundVindex := false
 	cindex := len(coordinates)
 	coordinates = append(coordinates, 0)
@@ -346,8 +361,11 @@ func (rp *routeTree) planCompositeInOpRecursive(ctx *planningContext, node *sqlp
 		coordinates[cindex] = i
 		switch expr := expr.(type) {
 		case sqlparser.ValTuple:
-			ok := rp.planCompositeInOpRecursive(ctx, node, expr, right, coordinates)
-			return ok || foundVindex
+			ok, err := rp.planCompositeInOpRecursive(ctx, 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) {
@@ -360,46 +378,46 @@ func (rp *routeTree) planCompositeInOpRecursive(ctx *planningContext, node *sqlp
 				case sqlparser.ValTuple:
 					val := tupleAccess(currRight, coordinates)
 					if val == nil {
-						return false
+						return false, nil
 					}
 					rightVals[j] = val
 				default:
-					return false
+					return false, nil
 				}
 			}
-			newPlanValues := rp.makeEvalEngineExpr(ctx, rightVals)
-			if newPlanValues == nil {
-				return false
+			newPlanValues, err := rp.makePlanValue(ctx, rightVals)
+			if newPlanValues == nil || err != nil {
+				return false, err
 			}
 
 			opcode := func(*vindexes.ColumnVindex) engine.RouteOpcode { return engine.SelectMultiEqual }
-			newVindex := rp.haveMatchingVindex(ctx, node, rightVals, expr, newPlanValues, opcode, justTheVindex)
+			newVindex := rp.haveMatchingVindex(ctx, node, rightVals, expr, *newPlanValues, opcode, justTheVindex)
 			foundVindex = newVindex || foundVindex
 		}
 	}
-	return foundVindex
+	return foundVindex, nil
 }
 
-func (rp *routeTree) planInOp(ctx *planningContext, node *sqlparser.ComparisonExpr) bool {
+func (rp *routeTree) planInOp(ctx *planningContext, node *sqlparser.ComparisonExpr) (bool, error) {
 	switch left := node.Left.(type) {
 	case *sqlparser.ColName:
 		return rp.planSimpleInOp(ctx, node, left)
 	case sqlparser.ValTuple:
 		return rp.planCompositeInOp(ctx, node, left)
 	}
-	return false
+	return false, nil
 }
 
-func (rp *routeTree) planLikeOp(ctx *planningContext, node *sqlparser.ComparisonExpr) bool {
+func (rp *routeTree) planLikeOp(ctx *planningContext, node *sqlparser.ComparisonExpr) (bool, error) {
 	column, ok := node.Left.(*sqlparser.ColName)
 	if !ok {
-		return false
+		return false, nil
 	}
 
 	vdValue := node.Right
-	val := rp.makeEvalEngineExpr(ctx, vdValue)
-	if val == nil {
-		return false
+	val, err := rp.makePlanValue(ctx, vdValue)
+	if err != nil || val == nil {
+		return false, err
 	}
 
 	selectEqual := func(*vindexes.ColumnVindex) engine.RouteOpcode { return engine.SelectEqual }
@@ -412,35 +430,35 @@ func (rp *routeTree) planLikeOp(ctx *planningContext, node *sqlparser.Comparison
 		return nil
 	}
 
-	return rp.haveMatchingVindex(ctx, node, vdValue, column, val, selectEqual, vdx)
+	return rp.haveMatchingVindex(ctx, node, vdValue, column, *val, selectEqual, vdx), err
 }
 
-func (rp *routeTree) planIsExpr(ctx *planningContext, node *sqlparser.IsExpr) bool {
+func (rp *routeTree) planIsExpr(ctx *planningContext, node *sqlparser.IsExpr) (bool, error) {
 	// we only handle IS NULL correct. IsExpr can contain other expressions as well
 	if node.Right != sqlparser.IsNullOp {
-		return false
+		return false, nil
 	}
 	column, ok := node.Left.(*sqlparser.ColName)
 	if !ok {
-		return false
+		return false, nil
 	}
 	vdValue := &sqlparser.NullVal{}
-	val := rp.makeEvalEngineExpr(ctx, vdValue)
-	if val == nil {
-		return false
+	val, err := rp.makePlanValue(ctx, vdValue)
+	if err != nil || val == nil {
+		return false, err
 	}
 
-	return rp.haveMatchingVindex(ctx, node, vdValue, column, val, equalOrEqualUnique, justTheVindex)
+	return rp.haveMatchingVindex(ctx, node, vdValue, column, *val, equalOrEqualUnique, justTheVindex), err
 }
 
-// makeEvalEngineExpr transforms the given sqlparser.Expr into a evalengine.Expr.
+// makePlanValue transforms the given sqlparser.Expr into a sqltypes.PlanValue.
 // If the given sqlparser.Expr is an argument and can be found in the rp.argToReplaceBySelect then the
 // method will stops and return nil values.
 // Otherwise, the method will try to apply makePlanValue for any equality the sqlparser.Expr n has.
 // The first PlanValue that is successfully produced will be returned.
-func (rp *routeTree) makeEvalEngineExpr(ctx *planningContext, n sqlparser.Expr) evalengine.Expr {
+func (rp *routeTree) makePlanValue(ctx *planningContext, n sqlparser.Expr) (*sqltypes.PlanValue, error) {
 	if ctx.isSubQueryToReplace(n) {
-		return nil
+		return nil, nil
 	}
 
 	for _, expr := range ctx.semTable.GetExprAndEqualities(n) {
@@ -456,33 +474,18 @@ func (rp *routeTree) makeEvalEngineExpr(ctx *planningContext, n sqlparser.Expr)
 				expr = sqlparser.NewArgument(extractedSubquery.GetArgName())
 			}
 		}
-		pv, _ := evalengine.Convert(expr, &noColumnLookup{semTable: ctx.semTable})
+		pv, err := makePlanValue(expr)
+		if err != nil {
+			return nil, err
+		}
 		if pv != nil {
-			return pv
+			return pv, nil
 		}
 	}
 
-	return nil
-}
-
-type noColumnLookup struct {
-	semTable *semantics.SemTable
+	return nil, nil
 }
 
-var columnNotSupportedErr = vterrors.Errorf(vtrpcpb.Code_UNIMPLEMENTED, "column access not supported here")
-
-// ColumnLookup implements the ConverterLookup interface
-func (lookup *noColumnLookup) ColumnLookup(*sqlparser.ColName) (int, error) {
-	return 0, columnNotSupportedErr
-}
-
-// CollationIDLookup implements the ConverterLookup interface
-func (lookup *noColumnLookup) CollationIDLookup(expr sqlparser.Expr) collations.ID {
-	return lookup.semTable.CollationFor(expr)
-}
-
-var _ evalengine.ConverterLookup = (*noColumnLookup)(nil)
-
 func (rp *routeTree) hasVindex(column *sqlparser.ColName) bool {
 	for _, v := range rp.vindexPreds {
 		for _, col := range v.colVindex.Columns {
@@ -499,7 +502,7 @@ func (rp *routeTree) haveMatchingVindex(
 	node sqlparser.Expr,
 	valueExpr sqlparser.Expr,
 	column *sqlparser.ColName,
-	value evalengine.Expr,
+	value sqltypes.PlanValue,
 	opcode func(*vindexes.ColumnVindex) engine.RouteOpcode,
 	vfunc func(*vindexes.ColumnVindex) vindexes.Vindex,
 ) bool {
@@ -520,7 +523,7 @@ func (rp *routeTree) haveMatchingVindex(
 			routeOpcode := opcode(v.colVindex)
 			vindex := vfunc(v.colVindex)
 			v.options = append(v.options, &vindexOption{
-				values:      []evalengine.Expr{value},
+				values:      []sqltypes.PlanValue{value},
 				valueExprs:  []sqlparser.Expr{valueExpr},
 				predicates:  []sqlparser.Expr{node},
 				opcode:      routeOpcode,
diff --git a/go/vt/vtgate/planbuilder/select.go b/go/vt/vtgate/planbuilder/select.go
index 0e583c9c3e..9d5cecb11c 100644
--- a/go/vt/vtgate/planbuilder/select.go
+++ b/go/vt/vtgate/planbuilder/select.go
@@ -90,27 +90,15 @@ func rewriteToCNFAndReplan(stmt sqlparser.Statement, getPlan func(sel *sqlparser
 }
 
 func shouldRetryWithCNFRewriting(plan logicalPlan) bool {
-	// if we have a I_S query, but have not found table_schema or table_name, let's try CNF
-	var opcode engine.RouteOpcode
-	var sysTableTableName map[string]evalengine.Expr
-	var sysTableTableSchema []evalengine.Expr
-
-	switch routePlan := plan.(type) {
-	case *routeGen4:
-		opcode = routePlan.eroute.Opcode
-		sysTableTableName = routePlan.eroute.SysTableTableName
-		sysTableTableSchema = routePlan.eroute.SysTableTableSchema
-	case *route:
-		opcode = routePlan.eroute.Opcode
-		sysTableTableName = routePlan.eroute.SysTableTableName
-		sysTableTableSchema = routePlan.eroute.SysTableTableSchema
-	default:
+	routePlan, isRoute := plan.(*route)
+	if !isRoute {
 		return false
 	}
+	// if we have a I_S query, but have not found table_schema or table_name, let's try CNF
+	return routePlan.eroute.Opcode == engine.SelectDBA &&
+		len(routePlan.eroute.SysTableTableName) == 0 &&
+		len(routePlan.eroute.SysTableTableSchema) == 0
 
-	return opcode == engine.SelectDBA &&
-		len(sysTableTableName) == 0 &&
-		len(sysTableTableSchema) == 0
 }
 
 var errSQLCalcFoundRows = vterrors.NewErrorf(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.CantUseOptionHere, "Incorrect usage/placement of 'SQL_CALC_FOUND_ROWS'")
@@ -232,15 +220,14 @@ func setMiscFunc(in logicalPlan, sel *sqlparser.Select) error {
 	_, err := visit(in, func(plan logicalPlan) (bool, logicalPlan, error) {
 		switch node := plan.(type) {
 		case *route:
-			err := copyCommentsAndLocks(node.Select, sel, node.eroute.Opcode)
-			if err != nil {
-				return false, nil, err
-			}
-			return true, node, nil
-		case *routeGen4:
-			err := copyCommentsAndLocks(node.Select, sel, node.eroute.Opcode)
-			if err != nil {
-				return false, nil, err
+			query := sqlparser.GetFirstSelect(node.Select)
+			query.Comments = sel.Comments
+			query.Lock = sel.Lock
+			if sel.Into != nil {
+				if node.eroute.Opcode != engine.SelectUnsharded {
+					return false, nil, vterrors.Errorf(vtrpcpb.Code_UNIMPLEMENTED, "INTO is not supported on sharded keyspace")
+				}
+				query.Into = sel.Into
 			}
 			return true, node, nil
 		}
@@ -253,19 +240,6 @@ func setMiscFunc(in logicalPlan, sel *sqlparser.Select) error {
 	return nil
 }
 
-func copyCommentsAndLocks(statement sqlparser.SelectStatement, sel *sqlparser.Select, opcode engine.RouteOpcode) error {
-	query := sqlparser.GetFirstSelect(statement)
-	query.Comments = sel.Comments
-	query.Lock = sel.Lock
-	if sel.Into != nil {
-		if opcode != engine.SelectUnsharded {
-			return vterrors.Errorf(vtrpcpb.Code_UNIMPLEMENTED, "INTO is not supported on sharded keyspace")
-		}
-		query.Into = sel.Into
-	}
-	return nil
-}
-
 func buildSQLCalcFoundRowsPlan(
 	originalQuery string,
 	sel *sqlparser.Select,
diff --git a/go/vt/vttablet/tabletmanager/vreplication/table_plan_builder.go b/go/vt/vttablet/tabletmanager/vreplication/table_plan_builder.go
index fdde5ed7d2..fe33f6b87a 100644
--- a/go/vt/vttablet/tabletmanager/vreplication/table_plan_builder.go
+++ b/go/vt/vttablet/tabletmanager/vreplication/table_plan_builder.go
@@ -47,7 +47,6 @@ type tablePlanBuilder struct {
 	// selColumns keeps track of the columns we want to pull from source.
 	// If Lastpk is set, we compare this list against the table's pk and
 	// add missing references.
-	selColumns        map[string]bool
 	colExprs          []*colExpr
 	onInsert          insertType
 	pkCols            []*colExpr
@@ -246,10 +245,9 @@ func buildTablePlan(tableName string, rule *binlogdatapb.Rule, colInfos []*Colum
 			From:  sel.From,
 			Where: sel.Where,
 		},
-		selColumns: make(map[string]bool),
-		lastpk:     lastpk,
-		colInfos:   colInfos,
-		stats:      stats,
+		lastpk:   lastpk,
+		colInfos: colInfos,
+		stats:    stats,
 	}
 
 	if err := tpb.analyzeExprs(sel.SelectExprs); err != nil {
@@ -493,10 +491,6 @@ func (tpb *tablePlanBuilder) analyzeExpr(selExpr sqlparser.SelectExpr) (*colExpr
 // addCol adds the specified column to the send query
 // if it's not already present.
 func (tpb *tablePlanBuilder) addCol(ident sqlparser.ColIdent) {
-	if tpb.selColumns[ident.Lowered()] {
-		return
-	}
-	tpb.selColumns[ident.Lowered()] = true
 	tpb.sendSelect.SelectExprs = append(tpb.sendSelect.SelectExprs, &sqlparser.AliasedExpr{
 		Expr: &sqlparser.ColName{Name: ident},
 	})
diff --git a/go/vt/vttablet/tabletserver/repltracker/poller.go b/go/vt/vttablet/tabletserver/repltracker/poller.go
index 5a9112be82..995223dc28 100644
--- a/go/vt/vttablet/tabletserver/repltracker/poller.go
+++ b/go/vt/vttablet/tabletserver/repltracker/poller.go
@@ -50,12 +50,7 @@ func (p *poller) Status() (time.Duration, error) {
 		return 0, err
 	}
 
-	// If replication is not currently running or we don't know what the lag is -- most commonly
-	// because the replica mysqld is in the process of trying to start replicating from its source
-	// but it hasn't yet reached the point where it can calculate the seconds_behind_master
-	// value and it's thus NULL -- then we will estimate the lag ourselves using the last seen
-	// value + the time elapsed since.
-	if !status.ReplicationRunning() || status.ReplicationLagUnknown {
+	if !status.ReplicationRunning() {
 		if p.timeRecorded.IsZero() {
 			return 0, vterrors.Errorf(vtrpcpb.Code_UNAVAILABLE, "replication is not running")
 		}


Test patch:
diff --git a/go/test/endtoend/tabletmanager/main_test.go b/go/test/endtoend/tabletmanager/main_test.go
index 9c118465ed..08770665c4 100644
--- a/go/test/endtoend/tabletmanager/main_test.go
+++ b/go/test/endtoend/tabletmanager/main_test.go
@@ -35,23 +35,21 @@ import (
 )
 
 var (
-	clusterInstance                  *cluster.LocalProcessCluster
-	tmClient                         *tmc.Client
-	primaryTabletParams              mysql.ConnParams
-	replicaTabletParams              mysql.ConnParams
-	primaryTablet                    cluster.Vttablet
-	replicaTablet                    cluster.Vttablet
-	rdonlyTablet                     cluster.Vttablet
-	hostname                         = "localhost"
-	keyspaceName                     = "ks"
-	shardName                        = "0"
-	keyspaceShard                    = "ks/" + shardName
-	dbName                           = "vt_" + keyspaceName
-	username                         = "vt_dba"
-	cell                             = "zone1"
-	tabletHealthcheckRefreshInterval = 5 * time.Second
-	tabletUnhealthyThreshold         = tabletHealthcheckRefreshInterval * 2
-	sqlSchema                        = `
+	clusterInstance     *cluster.LocalProcessCluster
+	tmClient            *tmc.Client
+	primaryTabletParams mysql.ConnParams
+	replicaTabletParams mysql.ConnParams
+	primaryTablet       cluster.Vttablet
+	replicaTablet       cluster.Vttablet
+	rdonlyTablet        cluster.Vttablet
+	hostname            = "localhost"
+	keyspaceName        = "ks"
+	shardName           = "0"
+	keyspaceShard       = "ks/" + shardName
+	dbName              = "vt_" + keyspaceName
+	username            = "vt_dba"
+	cell                = "zone1"
+	sqlSchema           = `
 	create table t1(
 		id bigint,
 		value varchar(16),
@@ -95,17 +93,12 @@ func TestMain(m *testing.M) {
 		}
 
 		// List of users authorized to execute vschema ddl operations
-		clusterInstance.VtGateExtraArgs = []string{
-			"-vschema_ddl_authorized_users=%",
-			"-discovery_low_replication_lag", tabletUnhealthyThreshold.String(),
-		}
+		clusterInstance.VtGateExtraArgs = []string{"-vschema_ddl_authorized_users=%"}
 		// Set extra tablet args for lock timeout
 		clusterInstance.VtTabletExtraArgs = []string{
 			"-lock_tables_timeout", "5s",
 			"-watch_replication_stream",
 			"-enable_replication_reporter",
-			"-health_check_interval", tabletHealthcheckRefreshInterval.String(),
-			"-unhealthy_threshold", tabletUnhealthyThreshold.String(),
 		}
 		// We do not need semiSync for this test case.
 		clusterInstance.EnableSemiSync = false
diff --git a/go/test/endtoend/tabletmanager/tablet_health_test.go b/go/test/endtoend/tabletmanager/tablet_health_test.go
index a27ab5a3d4..81946a1ede 100644
--- a/go/test/endtoend/tabletmanager/tablet_health_test.go
+++ b/go/test/endtoend/tabletmanager/tablet_health_test.go
@@ -24,7 +24,6 @@ import (
 	"strings"
 	"sync"
 	"testing"
-	"time"
 
 	"github.com/stretchr/testify/require"
 
@@ -135,7 +134,7 @@ func TestHealthCheck(t *testing.T) {
 	// make sure the health stream is updated
 	result, err := clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput("VtTabletStreamHealth", "-count", "1", rTablet.Alias)
 	require.NoError(t, err)
-	verifyStreamHealth(t, result, true)
+	verifyStreamHealth(t, result)
 
 	// then restart replication, make sure we stay healthy
 	err = clusterInstance.VtctlclientProcess.ExecuteCommand("StartReplication", rTablet.Alias)
@@ -149,48 +148,7 @@ func TestHealthCheck(t *testing.T) {
 	require.NoError(t, err)
 	scanner := bufio.NewScanner(strings.NewReader(result))
 	for scanner.Scan() {
-		verifyStreamHealth(t, scanner.Text(), true)
-	}
-
-	// stop the replica's source mysqld instance to break replication
-	// and test that the replica tablet becomes unhealthy and non-serving after crossing
-	// the tablet's -unhealthy_threshold and the gateway's -discovery_low_replication_lag
-	err = primaryTablet.MysqlctlProcess.Stop()
-	require.NoError(t, err)
-
-	time.Sleep(tabletUnhealthyThreshold + tabletHealthcheckRefreshInterval)
-
-	// now the replica's VtTabletStreamHealth should show it as unhealthy
-	result, err = clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput("VtTabletStreamHealth", "-count", "1", rTablet.Alias)
-	require.NoError(t, err)
-	scanner = bufio.NewScanner(strings.NewReader(result))
-	for scanner.Scan() {
-		verifyStreamHealth(t, scanner.Text(), false)
-	}
-
-	// start the primary tablet's mysqld back up
-	primaryTablet.MysqlctlProcess.InitMysql = false
-	err = primaryTablet.MysqlctlProcess.Start()
-	primaryTablet.MysqlctlProcess.InitMysql = true
-	require.NoError(t, err)
-
-	// explicitly start replication on all of the replicas to avoid any test flakiness as they were all
-	// replicating from the primary instance
-	err = clusterInstance.VtctlclientProcess.ExecuteCommand("StartReplication", rTablet.Alias)
-	require.NoError(t, err)
-	err = clusterInstance.VtctlclientProcess.ExecuteCommand("StartReplication", replicaTablet.Alias)
-	require.NoError(t, err)
-	err = clusterInstance.VtctlclientProcess.ExecuteCommand("StartReplication", rdonlyTablet.Alias)
-	require.NoError(t, err)
-
-	time.Sleep(tabletHealthcheckRefreshInterval)
-
-	// now the replica's VtTabletStreamHealth should show it as healthy again
-	result, err = clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput("VtTabletStreamHealth", "-count", "1", rTablet.Alias)
-	require.NoError(t, err)
-	scanner = bufio.NewScanner(strings.NewReader(result))
-	for scanner.Scan() {
-		verifyStreamHealth(t, scanner.Text(), true)
+		verifyStreamHealth(t, scanner.Text())
 	}
 
 	// Manual cleanup of processes
@@ -225,7 +183,7 @@ func checkTabletType(t *testing.T, tabletAlias string, typeWant string) {
 	assert.Equal(t, want, got)
 }
 
-func verifyStreamHealth(t *testing.T, result string, expectHealthy bool) {
+func verifyStreamHealth(t *testing.T, result string) {
 	var streamHealthResponse querypb.StreamHealthResponse
 	err := json2.Unmarshal([]byte(result), &streamHealthResponse)
 	require.NoError(t, err)
@@ -233,14 +191,10 @@ func verifyStreamHealth(t *testing.T, result string, expectHealthy bool) {
 	UID := streamHealthResponse.GetTabletAlias().GetUid()
 	realTimeStats := streamHealthResponse.GetRealtimeStats()
 	replicationLagSeconds := realTimeStats.GetReplicationLagSeconds()
+	assert.True(t, serving, "Tablet should be in serving state")
 	assert.True(t, UID > 0, "Tablet should contain uid")
-	if expectHealthy {
-		assert.True(t, serving, "Tablet should be in serving state")
-		// replicationLagSeconds varies till 7200 so setting safe limit
-		assert.True(t, replicationLagSeconds < 10000, "replica should not be behind primary")
-	} else {
-		assert.True(t, (!serving || replicationLagSeconds >= uint32(tabletUnhealthyThreshold.Seconds())), "Tablet should not be in serving and healthy state")
-	}
+	// replicationLagSeconds varies till 7200 so setting safe limit
+	assert.True(t, replicationLagSeconds < 10000, "replica should not be behind primary")
 }
 
 func TestHealthCheckDrainedStateDoesNotShutdownQueryService(t *testing.T) {
diff --git a/go/test/endtoend/vreplication/cluster.go b/go/test/endtoend/vreplication/cluster.go
index 08933943a6..37bcf4aec3 100644
--- a/go/test/endtoend/vreplication/cluster.go
+++ b/go/test/endtoend/vreplication/cluster.go
@@ -492,3 +492,21 @@ func (vc *VitessCluster) getVttabletsInKeyspace(t *testing.T, cell *Cell, ksName
 	}
 	return tablets
 }
+
+func (vc *VitessCluster) getPrimaryTablet(t *testing.T, ksName, shardName string) *cluster.VttabletProcess {
+	for _, cell := range vc.Cells {
+		keyspace := cell.Keyspaces[ksName]
+		for _, shard := range keyspace.Shards {
+			if shard.Name != shardName {
+				continue
+			}
+			for _, tablet := range shard.Tablets {
+				if tablet.Vttablet.GetTabletStatus() == "SERVING" && strings.EqualFold(tablet.Vttablet.VreplicationTabletType, "primary") {
+					return tablet.Vttablet
+				}
+			}
+		}
+	}
+	require.FailNow(t, "no primary found for %s:%s", ksName, shardName)
+	return nil
+}
diff --git a/go/test/endtoend/vreplication/helper.go b/go/test/endtoend/vreplication/helper.go
index 99756eb527..2b739d4a15 100644
--- a/go/test/endtoend/vreplication/helper.go
+++ b/go/test/endtoend/vreplication/helper.go
@@ -9,6 +9,7 @@ import (
 	"strconv"
 	"strings"
 	"testing"
+	"time"
 
 	"github.com/buger/jsonparser"
 	"github.com/stretchr/testify/require"
@@ -68,6 +69,26 @@ func checkHealth(t *testing.T, url string) bool {
 	return true
 }
 
+func waitForQueryToExecute(t *testing.T, conn *mysql.Conn, database string, query string, want string) {
+	done := false
+	ticker := time.NewTicker(10 * time.Millisecond)
+	for {
+		select {
+		case <-ticker.C:
+			if done {
+				return
+			}
+			qr := execVtgateQuery(t, conn, database, query)
+			require.NotNil(t, qr)
+			if want == fmt.Sprintf("%v", qr.Rows) {
+				done = true
+			}
+		case <-time.After(5 * time.Second):
+			require.FailNow(t, "query %s.%s did not execute in time", database, query)
+		}
+	}
+}
+
 func validateCount(t *testing.T, conn *mysql.Conn, database string, table string, want int) {
 	qr := execVtgateQuery(t, conn, database, fmt.Sprintf("select count(*) from %s", table))
 	require.NotNil(t, qr)
diff --git a/go/test/endtoend/vreplication/materialize_test.go b/go/test/endtoend/vreplication/materialize_test.go
index ffb105064d..e9d9bc7462 100644
--- a/go/test/endtoend/vreplication/materialize_test.go
+++ b/go/test/endtoend/vreplication/materialize_test.go
@@ -60,8 +60,8 @@ const smMaterializeSpec = `{"workflow": "wf1", "source_keyspace": "ks1", "target
 
 const initDataQuery = `insert into ks1.tx(id, typ, val) values (1, 1, 'abc'), (2, 1, 'def'), (3, 2, 'def'), (4, 2, 'abc'), (5, 3, 'def'), (6, 3, 'abc')`
 
-// TestShardedMaterialize tests a materialize from a sharded (single shard) using comparison filters
-func TestShardedMaterialize(t *testing.T) {
+// testShardedMaterialize tests a materialize workflow for a sharded cluster (single shard) using comparison filters
+func testShardedMaterialize(t *testing.T) {
 	defaultCellName := "zone1"
 	allCells := []string{"zone1"}
 	allCellNames = "zone1"
@@ -75,12 +75,12 @@ func TestShardedMaterialize(t *testing.T) {
 	defer vc.TearDown(t)
 
 	defaultCell = vc.Cells[defaultCellName]
-	vc.AddKeyspace(t, []*Cell{defaultCell}, ks1, "-", smVSchema, smSchema, defaultReplicas, defaultRdonly, 100)
+	vc.AddKeyspace(t, []*Cell{defaultCell}, ks1, "0", smVSchema, smSchema, defaultReplicas, defaultRdonly, 100)
 	vtgate = defaultCell.Vtgates[0]
 	require.NotNil(t, vtgate)
 	vtgate.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.primary", ks1, "0"), 1)
 
-	vc.AddKeyspace(t, []*Cell{defaultCell}, ks2, "-", smVSchema, smSchema, defaultReplicas, defaultRdonly, 200)
+	vc.AddKeyspace(t, []*Cell{defaultCell}, ks2, "0", smVSchema, smSchema, defaultReplicas, defaultRdonly, 200)
 	vtgate.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.primary", ks2, "0"), 1)
 
 	vtgateConn = getConnection(t, vc.ClusterConfig.hostname, vc.ClusterConfig.vtgateMySQLPort)
@@ -89,10 +89,150 @@ func TestShardedMaterialize(t *testing.T) {
 	_, err := vtgateConn.ExecuteFetch(initDataQuery, 0, false)
 	require.NoError(t, err)
 	materialize(t, smMaterializeSpec)
-	tab := vc.Cells[defaultCell.Name].Keyspaces[ks2].Shards["-"].Tablets["zone1-200"].Vttablet
+	tab := vc.getPrimaryTablet(t, ks2, "0")
 	catchup(t, tab, "wf1", "Materialize")
 
 	validateCount(t, vtgateConn, ks2, "tx", 2)
-	validateQuery(t, vtgateConn, "ks2:-", "select id, val from tx",
+	validateQuery(t, vtgateConn, "ks2:0", "select id, val from tx",
 		`[[INT64(3) VARBINARY("def")] [INT64(5) VARBINARY("def")]]`)
 }
+
+/*
+ * The following sections are related to testMaterialize, which is intended to test these edge cases:
+ * it tests
+ * - the case where the same column is referred to multiple times
+ * - use of mysql functions in the filter
+ * - use of a custom function in the filter
+ */
+
+const smMaterializeSchemaSource = `
+	CREATE TABLE mat (
+	id bigint NOT NULL,
+	val varbinary(10) NOT NULL,
+	ts timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+	PRIMARY KEY (id)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+`
+
+const smMaterializeVSchemaSource = `
+{
+  "sharded": true,
+  "tables": {
+      "mat": {
+          "column_vindexes": [
+              {
+                  "column": "id",
+                  "name": "hash"
+              }
+          ]
+      }
+  },
+  "vindexes": {
+      "hash": {
+          "type": "hash"
+      }
+  }
+}
+`
+const smMaterializeSchemaTarget = `
+	CREATE TABLE mat2 (
+	id bigint NOT NULL,
+	val varbinary(10) NOT NULL,
+	ts timestamp NOT NULL,
+	day int NOT NULL,
+	month int NOT NULL,
+    x int not null,
+	PRIMARY KEY (id)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+`
+
+const smMaterializeVSchemaTarget = `
+{
+  "sharded": true,
+  "tables": {
+      "mat2": {
+          "column_vindexes": [
+              {
+                  "column": "id",
+                  "name": "hash"
+              }
+          ]
+      }
+  },
+  "vindexes": {
+      "hash": {
+          "type": "hash"
+      }
+  }
+}
+`
+const smMaterializeSpec2 = `{"workflow": "wf1", "source_keyspace": "source", "target_keyspace": "target", "table_settings": [ {"target_table": "mat2", "source_expression": "select id, val, ts, dayofmonth(ts) as day, month(ts) as month, custom1(id, val) as x from mat"  }] }`
+
+const materializeInitDataQuery = `insert into mat(id, val, ts) values (1, 'abc', '2021-10-9 16:17:36'), (2, 'def', '2021-11-10 16:17:36')`
+
+const customFunc = `
+CREATE FUNCTION custom1(id int, val varbinary(10))
+RETURNS int
+DETERMINISTIC
+RETURN id * length(val);
+`
+
+func testMaterialize(t *testing.T) {
+	defaultCellName := "zone1"
+	allCells := []string{"zone1"}
+	allCellNames = "zone1"
+	vc = NewVitessCluster(t, "TestMaterialize", allCells, mainClusterConfig)
+	sourceKs := "source"
+	targetKs := "target"
+	require.NotNil(t, vc)
+	defaultReplicas = 0 // because of CI resource constraints we can only run this test with primary tablets
+	defer func() { defaultReplicas = 1 }()
+
+	defer vc.TearDown(t)
+
+	defaultCell = vc.Cells[defaultCellName]
+	vc.AddKeyspace(t, []*Cell{defaultCell}, sourceKs, "0", smMaterializeVSchemaSource, smMaterializeSchemaSource, defaultReplicas, defaultRdonly, 300)
+	vtgate = defaultCell.Vtgates[0]
+	require.NotNil(t, vtgate)
+	vtgate.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.primary", sourceKs, "0"), 1)
+
+	vc.AddKeyspace(t, []*Cell{defaultCell}, targetKs, "0", smMaterializeVSchemaTarget, smMaterializeSchemaTarget, defaultReplicas, defaultRdonly, 400)
+	vtgate.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.primary", targetKs, "0"), 1)
+
+	vtgateConn = getConnection(t, vc.ClusterConfig.hostname, vc.ClusterConfig.vtgateMySQLPort)
+	defer vtgateConn.Close()
+	verifyClusterHealth(t, vc)
+
+	_, err := vtgateConn.ExecuteFetch(materializeInitDataQuery, 0, false)
+	require.NoError(t, err)
+
+	ks2Primary := vc.getPrimaryTablet(t, targetKs, "0")
+	_, err = ks2Primary.QueryTablet(customFunc, targetKs, true)
+	require.NoError(t, err)
+
+	materialize(t, smMaterializeSpec2)
+	catchup(t, ks2Primary, "wf1", "Materialize")
+
+	// validate data after the copy phase
+	validateCount(t, vtgateConn, targetKs, "mat2", 2)
+	want := `[[INT64(1) VARBINARY("abc") TIMESTAMP("2021-10-09 16:17:36") INT32(9) INT32(10) INT32(3)] [INT64(2) VARBINARY("def") TIMESTAMP("2021-11-10 16:17:36") INT32(10) INT32(11) INT32(6)]]`
+	validateQuery(t, vtgateConn, targetKs, "select id, val, ts, day, month, x from mat2", want)
+
+	// insert data to test the replication phase
+	execVtgateQuery(t, vtgateConn, sourceKs, "insert into mat(id, val, ts) values (3, 'ghi', '2021-12-11 16:17:36')")
+
+	// validate data after the replication phase
+	waitForQueryToExecute(t, vtgateConn, targetKs, "select count(*) from mat2", "[[INT64(3)]]")
+	want = `[[INT64(1) VARBINARY("abc") TIMESTAMP("2021-10-09 16:17:36") INT32(9) INT32(10) INT32(3)] [INT64(2) VARBINARY("def") TIMESTAMP("2021-11-10 16:17:36") INT32(10) INT32(11) INT32(6)] [INT64(3) VARBINARY("ghi") TIMESTAMP("2021-12-11 16:17:36") INT32(11) INT32(12) INT32(9)]]`
+	validateQuery(t, vtgateConn, targetKs, "select id, val, ts, day, month, x from mat2", want)
+}
+
+// TestMaterialize runs all the individual materialize tests defined above
+func TestMaterialize(t *testing.T) {
+	t.Run("Materialize", func(t *testing.T) {
+		testMaterialize(t)
+	})
+	t.Run("ShardedMaterialize", func(t *testing.T) {
+		testShardedMaterialize(t)
+	})
+}
diff --git a/go/test/endtoend/vtgate/gen4/gen4_test.go b/go/test/endtoend/vtgate/gen4/gen4_test.go
index 7170d3ce5a..92e679b6ff 100644
--- a/go/test/endtoend/vtgate/gen4/gen4_test.go
+++ b/go/test/endtoend/vtgate/gen4/gen4_test.go
@@ -70,7 +70,6 @@ func TestCorrelatedExistsSubquery(t *testing.T) {
 
 	utils.AssertMatches(t, conn, `select id from t1 where exists(select 1 from t2 where t1.col = t2.tcol2)`, `[[INT64(100)]]`)
 	utils.AssertMatches(t, conn, `select id from t1 where exists(select 1 from t2 where t1.col = t2.tcol1) order by id`, `[[INT64(1)] [INT64(4)] [INT64(100)]]`)
-	utils.AssertMatches(t, conn, `select id from t1 where id in (select id from t2) order by id`, `[[INT64(1)] [INT64(100)]]`)
 }
 
 func TestGroupBy(t *testing.T) {
diff --git a/go/vt/vtgate/engine/plan_description_test.go b/go/vt/vtgate/engine/plan_description_test.go
index edf281bb44..c74b08ab50 100644
--- a/go/vt/vtgate/engine/plan_description_test.go
+++ b/go/vt/vtgate/engine/plan_description_test.go
@@ -21,6 +21,8 @@ import (
 
 	"vitess.io/vitess/go/test/utils"
 
+	"vitess.io/vitess/go/sqltypes"
+
 	"vitess.io/vitess/go/vt/key"
 	"vitess.io/vitess/go/vt/vtgate/vindexes"
 )
@@ -57,6 +59,8 @@ func createRoute() *Route {
 		TableName:         "tableName",
 		FieldQuery:        "more query",
 		Vindex:            hash.(*vindexes.Hash),
+		Values:            []sqltypes.PlanValue{},
+		OrderBy:           []OrderByParams{},
 	}
 }
 
diff --git a/go/vt/vtgate/engine/route_test.go b/go/vt/vtgate/engine/route_test.go
index fce887ca8a..54cf19b5cd 100644
--- a/go/vt/vtgate/engine/route_test.go
+++ b/go/vt/vtgate/engine/route_test.go
@@ -234,10 +234,8 @@ func TestSelectEqualUnique(t *testing.T) {
 		"dummy_select_field",
 	)
 	sel.Vindex = vindex.(vindexes.SingleColumn)
+	sel.Values = []sqltypes.PlanValue{{Value: sqltypes.NewInt64(1)}}
 
-	sel.Value = &evalengine.RouteValue{
-		Expr: evalengine.NewLiteralInt(1),
-	}
 	vc := &loggingVCursor{
 		shards:  []string{"-20", "20-"},
 		results: []*sqltypes.Result{defaultSelectResult},
@@ -272,7 +270,7 @@ func TestSelectNone(t *testing.T) {
 		"dummy_select_field",
 	)
 	sel.Vindex = vindex.(vindexes.SingleColumn)
-	sel.Value = nil
+	sel.Values = nil
 
 	vc := &loggingVCursor{
 		shards:  []string{"-20", "20-"},
@@ -307,9 +305,8 @@ func TestSelectEqualUniqueScatter(t *testing.T) {
 		"dummy_select_field",
 	)
 	sel.Vindex = vindex.(vindexes.SingleColumn)
-	sel.Value = &evalengine.RouteValue{
-		Expr: evalengine.NewLiteralInt(1),
-	}
+	sel.Values = []sqltypes.PlanValue{{Value: sqltypes.NewInt64(1)}}
+
 	vc := &loggingVCursor{
 		shards:       []string{"-20", "20-"},
 		shardForKsid: []string{"-20", "20-"},
@@ -349,9 +346,8 @@ func TestSelectEqual(t *testing.T) {
 		"dummy_select_field",
 	)
 	sel.Vindex = vindex.(vindexes.SingleColumn)
-	sel.Value = &evalengine.RouteValue{
-		Expr: evalengine.NewLiteralInt(1),
-	}
+	sel.Values = []sqltypes.PlanValue{{Value: sqltypes.NewInt64(1)}}
+
 	vc := &loggingVCursor{
 		shards: []string{"-20", "20-"},
 		results: []*sqltypes.Result{
@@ -402,9 +398,7 @@ func TestSelectEqualNoRoute(t *testing.T) {
 		"dummy_select_field",
 	)
 	sel.Vindex = vindex.(vindexes.SingleColumn)
-	sel.Value = &evalengine.RouteValue{
-		Expr: evalengine.NewLiteralInt(1),
-	}
+	sel.Values = []sqltypes.PlanValue{{Value: sqltypes.NewInt64(1)}}
 
 	vc := &loggingVCursor{shards: []string{"-20", "20-"}}
 	result, err := sel.TryExecute(vc, map[string]*querypb.BindVariable{}, false)
@@ -437,13 +431,16 @@ func TestSelectINUnique(t *testing.T) {
 		"dummy_select_field",
 	)
 	sel.Vindex = vindex.(vindexes.SingleColumn)
-	sel.Value = &evalengine.RouteValue{
-		Expr: evalengine.TupleExpr{
-			evalengine.NewLiteralInt(1),
-			evalengine.NewLiteralInt(2),
-			evalengine.NewLiteralInt(4),
-		},
-	}
+	sel.Values = []sqltypes.PlanValue{{
+		Values: []sqltypes.PlanValue{{
+			Value: sqltypes.NewInt64(1),
+		}, {
+			Value: sqltypes.NewInt64(2),
+		}, {
+			Value: sqltypes.NewInt64(4),
+		}},
+	}}
+
 	vc := &loggingVCursor{
 		shards:       []string{"-20", "20-"},
 		shardForKsid: []string{"-20", "-20", "20-"},
@@ -486,13 +483,15 @@ func TestSelectINNonUnique(t *testing.T) {
 		"dummy_select_field",
 	)
 	sel.Vindex = vindex.(vindexes.SingleColumn)
-	sel.Value = &evalengine.RouteValue{
-		Expr: evalengine.TupleExpr{
-			evalengine.NewLiteralInt(1),
-			evalengine.NewLiteralInt(2),
-			evalengine.NewLiteralInt(4),
-		},
-	}
+	sel.Values = []sqltypes.PlanValue{{
+		Values: []sqltypes.PlanValue{{
+			Value: sqltypes.NewInt64(1),
+		}, {
+			Value: sqltypes.NewInt64(2),
+		}, {
+			Value: sqltypes.NewInt64(4),
+		}},
+	}}
 
 	fields := sqltypes.MakeTestFields(
 		"fromc|toc",
@@ -549,13 +548,15 @@ func TestSelectMultiEqual(t *testing.T) {
 		"dummy_select_field",
 	)
 	sel.Vindex = vindex.(vindexes.SingleColumn)
-	sel.Value = &evalengine.RouteValue{
-		Expr: evalengine.TupleExpr{
-			evalengine.NewLiteralInt(1),
-			evalengine.NewLiteralInt(2),
-			evalengine.NewLiteralInt(4),
-		},
-	}
+	sel.Values = []sqltypes.PlanValue{{
+		Values: []sqltypes.PlanValue{{
+			Value: sqltypes.NewInt64(1),
+		}, {
+			Value: sqltypes.NewInt64(2),
+		}, {
+			Value: sqltypes.NewInt64(4),
+		}},
+	}}
 
 	vc := &loggingVCursor{
 		shards:       []string{"-20", "20-"},
@@ -600,8 +601,8 @@ func TestSelectLike(t *testing.T) {
 	)
 
 	sel.Vindex = vindex
-	sel.Value = &evalengine.RouteValue{
-		Expr: evalengine.NewLiteralString([]byte("a%"), collations.TypedCollation{}),
+	sel.Values = []sqltypes.PlanValue{
+		{Value: sqltypes.NewVarBinary("a%")},
 	}
 	// md5("a") = 0cc175b9c0f1b6a831c399e269772661
 	// keyspace id prefix for "a" is 0x0c
@@ -630,8 +631,8 @@ func TestSelectLike(t *testing.T) {
 
 	vc.Rewind()
 
-	sel.Value = &evalengine.RouteValue{
-		Expr: evalengine.NewLiteralString([]byte("ab%"), collations.TypedCollation{}),
+	sel.Values = []sqltypes.PlanValue{
+		{Value: sqltypes.NewVarBinary("ab%")},
 	}
 	// md5("b") = 92eb5ffee6ae2fec3ad71c777531578f
 	// keyspace id prefix for "ab" is 0x0c92
@@ -772,9 +773,7 @@ func TestRouteGetFields(t *testing.T) {
 		"dummy_select_field",
 	)
 	sel.Vindex = vindex.(vindexes.SingleColumn)
-	sel.Value = &evalengine.RouteValue{
-		Expr: evalengine.NewLiteralInt(1),
-	}
+	sel.Values = []sqltypes.PlanValue{{Value: sqltypes.NewInt64(1)}}
 
 	vc := &loggingVCursor{shards: []string{"-20", "20-"}}
 	result, err := sel.TryExecute(vc, map[string]*querypb.BindVariable{}, true)
@@ -1205,7 +1204,7 @@ func TestRouteStreamTruncate(t *testing.T) {
 	expectResult(t, "sel.Execute", result, wantResult)
 }
 
-func TestRouteStreamSortTruncate(t *testing.T) {
+func XTestRouteStreamSortTruncate(t *testing.T) {
 	sel := NewRoute(
 		SelectUnsharded,
 		&vindexes.Keyspace{
diff --git a/go/vt/vtgate/evalengine/convert_test.go b/go/vt/vtgate/evalengine/convert_test.go
index d5ce1c8ead..a97313656d 100644
--- a/go/vt/vtgate/evalengine/convert_test.go
+++ b/go/vt/vtgate/evalengine/convert_test.go
@@ -233,42 +233,3 @@ func TestEvaluate(t *testing.T) {
 		})
 	}
 }
-
-func TestEvaluateTuple(t *testing.T) {
-	type testCase struct {
-		expression string
-		expected   []sqltypes.Value
-	}
-
-	tests := []testCase{{
-		expression: "(1,2,4)",
-		expected:   []sqltypes.Value{sqltypes.NewInt64(1), sqltypes.NewInt64(2), sqltypes.NewInt64(4)},
-	}, {
-		expression: "(1,'2',4)",
-		expected:   []sqltypes.Value{sqltypes.NewInt64(1), sqltypes.NewVarBinary("2"), sqltypes.NewInt64(4)},
-	}, {
-		expression: "(1,'2',4.0)",
-		expected:   []sqltypes.Value{sqltypes.NewInt64(1), sqltypes.NewVarBinary("2"), sqltypes.NewFloat64(4.0)},
-	}}
-
-	for _, test := range tests {
-		t.Run(test.expression, func(t *testing.T) {
-			// Given
-			stmt, err := sqlparser.Parse("select " + test.expression)
-			require.NoError(t, err)
-			astExpr := stmt.(*sqlparser.Select).SelectExprs[0].(*sqlparser.AliasedExpr).Expr
-			sqltypesExpr, err := Convert(astExpr, dummyCollation(45))
-			require.Nil(t, err)
-			require.NotNil(t, sqltypesExpr)
-
-			// When
-			r, err := sqltypesExpr.Evaluate(nil)
-
-			// Then
-			require.NoError(t, err)
-			require.NotNil(t, r)
-			gotValues := r.TupleValues()
-			assert.Equal(t, test.expected, gotValues, "expected: %s, got: %s", test.expected, gotValues)
-		})
-	}
-}
diff --git a/go/vt/vtgate/planbuilder/testdata/aggr_cases.txt b/go/vt/vtgate/planbuilder/testdata/aggr_cases.txt
index bba259a3ce..ddba13d362 100644
--- a/go/vt/vtgate/planbuilder/testdata/aggr_cases.txt
+++ b/go/vt/vtgate/planbuilder/testdata/aggr_cases.txt
@@ -34,27 +34,13 @@ Gen4 plan same as above
     "FieldQuery": "select count(*), col from `user` where 1 != 1",
     "Query": "select count(*), col from `user` where id = 1",
     "Table": "`user`",
-    "Values": 1,
-    "Vindex": "user_index"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select count(*), col from user where id = 1",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select count(*), col from `user` where 1 != 1",
-    "Query": "select count(*), col from `user` where id = 1",
-    "Table": "`user`",
-    "Values": "INT64(1)",
+    "Values": [
+      1
+    ],
     "Vindex": "user_index"
   }
 }
+Gen4 plan same as above
 
 # Aggregate detection (non-aggregate function)
 "select fun(1), col from user"
@@ -826,7 +812,9 @@ Gen4 error: unsupported: '*' expression in cross-shard query
     "FieldQuery": "select id, count(*) as c from `user` where 1 != 1 group by id",
     "Query": "select id, count(*) as c from `user` group by id having id = 1 and c = 10",
     "Table": "`user`",
-    "Values": 1,
+    "Values": [
+      1
+    ],
     "Vindex": "user_index"
   }
 }
@@ -843,7 +831,9 @@ Gen4 error: unsupported: '*' expression in cross-shard query
     "FieldQuery": "select id, count(*) as c from `user` where 1 != 1 group by id",
     "Query": "select id, count(*) as c from `user` where id = 1 group by id having c = 10",
     "Table": "`user`",
-    "Values": "INT64(1)",
+    "Values": [
+      1
+    ],
     "Vindex": "user_index"
   }
 }
@@ -1975,27 +1965,13 @@ Gen4 plan same as above
     "FieldQuery": "select `user`.col1 as a from `user` where 1 != 1 group by a collate utf8_general_ci",
     "Query": "select `user`.col1 as a from `user` where `user`.id = 5 group by a collate utf8_general_ci",
     "Table": "`user`",
-    "Values": 5,
-    "Vindex": "user_index"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select user.col1 as a from user where user.id = 5 group by a collate utf8_general_ci",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select `user`.col1 as a from `user` where 1 != 1 group by a collate utf8_general_ci",
-    "Query": "select `user`.col1 as a from `user` where `user`.id = 5 group by a collate utf8_general_ci",
-    "Table": "`user`",
-    "Values": "INT64(5)",
+    "Values": [
+      5
+    ],
     "Vindex": "user_index"
   }
 }
+Gen4 plan same as above
 
 # routing rules for aggregates
 "select id, count(*) from route2 group by id"
@@ -2746,7 +2722,9 @@ Gen4 plan same as above
         "FieldQuery": "select 1 from user_extra where 1 != 1",
         "Query": "select 1 from user_extra where user_id = 3 and user_id \u003c :user_id",
         "Table": "user_extra",
-        "Values": "INT64(3)",
+        "Values": [
+          3
+        ],
         "Vindex": "user_index"
       }
     ]
diff --git a/go/vt/vtgate/planbuilder/testdata/filter_cases.txt b/go/vt/vtgate/planbuilder/testdata/filter_cases.txt
index 9f5c179263..29e6c03d57 100644
--- a/go/vt/vtgate/planbuilder/testdata/filter_cases.txt
+++ b/go/vt/vtgate/planbuilder/testdata/filter_cases.txt
@@ -51,27 +51,13 @@ Gen4 plan same as above
     "FieldQuery": "select id from `user` where 1 != 1",
     "Query": "select id from `user` where `user`.id = 5",
     "Table": "`user`",
-    "Values": 5,
-    "Vindex": "user_index"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select id from user where user.id = 5",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select id from `user` where 1 != 1",
-    "Query": "select id from `user` where `user`.id = 5",
-    "Table": "`user`",
-    "Values": "INT64(5)",
+    "Values": [
+      5
+    ],
     "Vindex": "user_index"
   }
 }
+Gen4 plan same as above
 
 # Single table unique vindex route, but complex expr
 "select id from user where user.id = 5+5"
@@ -90,23 +76,7 @@ Gen4 plan same as above
     "Table": "`user`"
   }
 }
-{
-  "QueryType": "SELECT",
-  "Original": "select id from user where user.id = 5+5",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select id from `user` where 1 != 1",
-    "Query": "select id from `user` where `user`.id = 5 + 5",
-    "Table": "`user`",
-    "Values": "INT64(10)",
-    "Vindex": "user_index"
-  }
-}
+Gen4 plan same as above
 
 # Single table multiple unique vindex match
 "select id from music where id = 5 and user_id = 4"
@@ -123,27 +93,13 @@ Gen4 plan same as above
     "FieldQuery": "select id from music where 1 != 1",
     "Query": "select id from music where id = 5 and user_id = 4",
     "Table": "music",
-    "Values": 4,
-    "Vindex": "user_index"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select id from music where id = 5 and user_id = 4",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select id from music where 1 != 1",
-    "Query": "select id from music where id = 5 and user_id = 4",
-    "Table": "music",
-    "Values": "INT64(4)",
+    "Values": [
+      4
+    ],
     "Vindex": "user_index"
   }
 }
+Gen4 plan same as above
 
 # Single table multiple non-unique vindex match
 "select id from user where costly = 'aa' and name = 'bb'"
@@ -160,27 +116,13 @@ Gen4 plan same as above
     "FieldQuery": "select id from `user` where 1 != 1",
     "Query": "select id from `user` where costly = 'aa' and `name` = 'bb'",
     "Table": "`user`",
-    "Values": "bb",
-    "Vindex": "name_user_map"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select id from user where costly = 'aa' and name = 'bb'",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqual",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select id from `user` where 1 != 1",
-    "Query": "select id from `user` where costly = 'aa' and `name` = 'bb'",
-    "Table": "`user`",
-    "Values": "VARBINARY(\"bb\")",
+    "Values": [
+      "bb"
+    ],
     "Vindex": "name_user_map"
   }
 }
+Gen4 plan same as above
 
 # Single table multiple non-unique vindex match for IN clause
 "select id from user where costly in ('aa', 'bb') and name in ('aa', 'bb')"
@@ -198,29 +140,15 @@ Gen4 plan same as above
     "Query": "select id from `user` where costly in ('aa', 'bb') and `name` in ::__vals",
     "Table": "`user`",
     "Values": [
-      "aa",
-      "bb"
+      [
+        "aa",
+        "bb"
+      ]
     ],
     "Vindex": "name_user_map"
   }
 }
-{
-  "QueryType": "SELECT",
-  "Original": "select id from user where costly in ('aa', 'bb') and name in ('aa', 'bb')",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectIN",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select id from `user` where 1 != 1",
-    "Query": "select id from `user` where costly in ('aa', 'bb') and `name` in ::__vals",
-    "Table": "`user`",
-    "Values": "(VARBINARY(\"aa\"), VARBINARY(\"bb\"))",
-    "Vindex": "name_user_map"
-  }
-}
+Gen4 plan same as above
 
 # Composite IN clause
 "select id from user where (name, col) in (('aa', 'bb'), ('cc', 'dd'))"
@@ -238,29 +166,15 @@ Gen4 plan same as above
     "Query": "select id from `user` where (`name`, col) in (('aa', 'bb'), ('cc', 'dd'))",
     "Table": "`user`",
     "Values": [
-      "aa",
-      "cc"
+      [
+        "aa",
+        "cc"
+      ]
     ],
     "Vindex": "name_user_map"
   }
 }
-{
-  "QueryType": "SELECT",
-  "Original": "select id from user where (name, col) in (('aa', 'bb'), ('cc', 'dd'))",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectMultiEqual",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select id from `user` where 1 != 1",
-    "Query": "select id from `user` where (`name`, col) in (('aa', 'bb'), ('cc', 'dd'))",
-    "Table": "`user`",
-    "Values": "(VARBINARY(\"aa\"), VARBINARY(\"cc\"))",
-    "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'))"
@@ -278,29 +192,15 @@ Gen4 plan same as above
     "Query": "select id from `user` where (col, `name`) in (('aa', 'bb'), ('cc', 'dd'))",
     "Table": "`user`",
     "Values": [
-      "bb",
-      "dd"
+      [
+        "bb",
+        "dd"
+      ]
     ],
     "Vindex": "name_user_map"
   }
 }
-{
-  "QueryType": "SELECT",
-  "Original": "select id from user where (col, name) in (('aa', 'bb'), ('cc', 'dd'))",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectMultiEqual",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select id from `user` where 1 != 1",
-    "Query": "select id from `user` where (col, `name`) in (('aa', 'bb'), ('cc', 'dd'))",
-    "Table": "`user`",
-    "Values": "(VARBINARY(\"bb\"), VARBINARY(\"dd\"))",
-    "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'))"
@@ -318,29 +218,15 @@ Gen4 plan same as above
     "Query": "select id from `user` where (costly, `name`) in (('aa', 'bb'), ('cc', 'dd'))",
     "Table": "`user`",
     "Values": [
-      "bb",
-      "dd"
+      [
+        "bb",
+        "dd"
+      ]
     ],
     "Vindex": "name_user_map"
   }
 }
-{
-  "QueryType": "SELECT",
-  "Original": "select id from user where (costly, name) in (('aa', 'bb'), ('cc', 'dd'))",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectMultiEqual",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select id from `user` where 1 != 1",
-    "Query": "select id from `user` where (costly, `name`) in (('aa', 'bb'), ('cc', 'dd'))",
-    "Table": "`user`",
-    "Values": "(VARBINARY(\"bb\"), VARBINARY(\"dd\"))",
-    "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'))"
@@ -358,29 +244,15 @@ Gen4 plan same as above
     "Query": "select id from `user` where (`name`, costly) in (('aa', 'bb'), ('cc', 'dd'))",
     "Table": "`user`",
     "Values": [
-      "aa",
-      "cc"
+      [
+        "aa",
+        "cc"
+      ]
     ],
     "Vindex": "name_user_map"
   }
 }
-{
-  "QueryType": "SELECT",
-  "Original": "select id from user where (name, costly) in (('aa', 'bb'), ('cc', 'dd'))",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectMultiEqual",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select id from `user` where 1 != 1",
-    "Query": "select id from `user` where (`name`, costly) in (('aa', 'bb'), ('cc', 'dd'))",
-    "Table": "`user`",
-    "Values": "(VARBINARY(\"aa\"), VARBINARY(\"cc\"))",
-    "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'))"
@@ -398,28 +270,14 @@ Gen4 plan same as above
     "Query": "select id from `user` where (col, costly) in (('aa', 'bb')) and (col, `name`) in (('cc', 'dd'))",
     "Table": "`user`",
     "Values": [
-      "dd"
+      [
+        "dd"
+      ]
     ],
     "Vindex": "name_user_map"
   }
 }
-{
-  "QueryType": "SELECT",
-  "Original": "select id from user where (col, costly) in (('aa', 'bb')) and (col, name) in (('cc', 'dd'))",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectMultiEqual",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select id from `user` where 1 != 1",
-    "Query": "select id from `user` where (col, costly) in (('aa', 'bb')) and (col, `name`) in (('cc', 'dd'))",
-    "Table": "`user`",
-    "Values": "(VARBINARY(\"dd\"))",
-    "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"
@@ -436,27 +294,13 @@ Gen4 plan same as above
     "FieldQuery": "select id from `user` where 1 != 1",
     "Query": "select id from `user` where (col, `name`) in (('aa', 'bb')) and id = 5",
     "Table": "`user`",
-    "Values": 5,
-    "Vindex": "user_index"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select id from user where (col, name) in (('aa', 'bb')) and id = 5",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select id from `user` where 1 != 1",
-    "Query": "select id from `user` where (col, `name`) in (('aa', 'bb')) and id = 5",
-    "Table": "`user`",
-    "Values": "INT64(5)",
+    "Values": [
+      5
+    ],
     "Vindex": "user_index"
   }
 }
+Gen4 plan same as above
 
 # Composite IN: multiple vindex matches
 "select id from user where (costly, name) in (('aa', 'bb'), ('cc', 'dd'))"
@@ -474,29 +318,15 @@ Gen4 plan same as above
     "Query": "select id from `user` where (costly, `name`) in (('aa', 'bb'), ('cc', 'dd'))",
     "Table": "`user`",
     "Values": [
-      "bb",
-      "dd"
+      [
+        "bb",
+        "dd"
+      ]
     ],
     "Vindex": "name_user_map"
   }
 }
-{
-  "QueryType": "SELECT",
-  "Original": "select id from user where (costly, name) in (('aa', 'bb'), ('cc', 'dd'))",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectMultiEqual",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select id from `user` where 1 != 1",
-    "Query": "select id from `user` where (costly, `name`) in (('aa', 'bb'), ('cc', 'dd'))",
-    "Table": "`user`",
-    "Values": "(VARBINARY(\"bb\"), VARBINARY(\"dd\"))",
-    "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'))"
@@ -514,29 +344,15 @@ Gen4 plan same as above
     "Query": "select id from `user` where ((col1, `name`), col2) in ((('aa', 'bb'), 'cc'), (('dd', 'ee'), 'ff'))",
     "Table": "`user`",
     "Values": [
-      "bb",
-      "ee"
+      [
+        "bb",
+        "ee"
+      ]
     ],
     "Vindex": "name_user_map"
   }
 }
-{
-  "QueryType": "SELECT",
-  "Original": "select id from user where ((col1, name), col2) in ((('aa', 'bb'), 'cc'), (('dd', 'ee'), 'ff'))",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectMultiEqual",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select id from `user` where 1 != 1",
-    "Query": "select id from `user` where ((col1, `name`), col2) in ((('aa', 'bb'), 'cc'), (('dd', 'ee'), 'ff'))",
-    "Table": "`user`",
-    "Values": "(VARBINARY(\"bb\"), VARBINARY(\"ee\"))",
-    "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')))"
@@ -554,29 +370,15 @@ Gen4 plan same as above
     "Query": "select id from `user` where (`name`, (col1, col2)) in (('aa', ('bb', 'cc')), ('dd', ('ee', 'ff')))",
     "Table": "`user`",
     "Values": [
-      "aa",
-      "dd"
+      [
+        "aa",
+        "dd"
+      ]
     ],
     "Vindex": "name_user_map"
   }
 }
-{
-  "QueryType": "SELECT",
-  "Original": "select id from user where (name, (col1, col2)) in (('aa', ('bb', 'cc')), ('dd', ('ee', 'ff')))",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectMultiEqual",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select id from `user` where 1 != 1",
-    "Query": "select id from `user` where (`name`, (col1, col2)) in (('aa', ('bb', 'cc')), ('dd', ('ee', 'ff')))",
-    "Table": "`user`",
-    "Values": "(VARBINARY(\"aa\"), VARBINARY(\"dd\"))",
-    "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'))"
@@ -633,23 +435,7 @@ Gen4 plan same as above
     "Table": "`user`"
   }
 }
-{
-  "QueryType": "SELECT",
-  "Original": "select id from user where (col1, name) in (('aa', 1+1))",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectMultiEqual",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select id from `user` where 1 != 1",
-    "Query": "select id from `user` where (col1, `name`) in (('aa', 1 + 1))",
-    "Table": "`user`",
-    "Values": "(INT64(2))",
-    "Vindex": "name_user_map"
-  }
-}
+Gen4 plan same as above
 
 # IN clause: LHS is neither column nor composite tuple
 "select Id from user where 1 in ('aa', 'bb')"
@@ -704,7 +490,9 @@ Gen4 plan same as above
     "FieldQuery": "select id from `user` where 1 != 1",
     "Query": "select id from `user` where `name` = :a",
     "Table": "`user`",
-    "Values": ":a",
+    "Values": [
+      ":a"
+    ],
     "Vindex": "name_user_map"
   }
 }
@@ -725,25 +513,13 @@ Gen4 plan same as above
     "FieldQuery": "select id from `user` where 1 != 1",
     "Query": "select id from `user` where `name` = 18446744073709551615",
     "Table": "`user`",
-    "Values": 18446744073709551615,
+    "Values": [
+      18446744073709551615
+    ],
     "Vindex": "name_user_map"
   }
 }
-{
-  "QueryType": "SELECT",
-  "Original": "select id from user where name = 18446744073709551615",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectScatter",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select id from `user` where 1 != 1",
-    "Query": "select id from `user` where `name` = 18446744073709551615",
-    "Table": "`user`"
-  }
-}
+Gen4 plan same as above
 
 # Single table in clause list arg
 "select id from user where name in ::list"
@@ -760,27 +536,13 @@ Gen4 plan same as above
     "FieldQuery": "select id from `user` where 1 != 1",
     "Query": "select id from `user` where `name` in ::__vals",
     "Table": "`user`",
-    "Values": "::list",
-    "Vindex": "name_user_map"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select id from user where name in ::list",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectIN",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select id from `user` where 1 != 1",
-    "Query": "select id from `user` where `name` in ::__vals",
-    "Table": "`user`",
-    "Values": ":list",
+    "Values": [
+      "::list"
+    ],
     "Vindex": "name_user_map"
   }
 }
+Gen4 plan same as above
 
 # Multi-table unique vindex constraint
 "select user_extra.id from user join user_extra on user.id = user_extra.user_id where user.id = 5"
@@ -797,7 +559,9 @@ Gen4 plan same as above
     "FieldQuery": "select user_extra.id from `user` join user_extra on `user`.id = user_extra.user_id where 1 != 1",
     "Query": "select user_extra.id from `user` join user_extra on `user`.id = user_extra.user_id where `user`.id = 5",
     "Table": "`user`, user_extra",
-    "Values": 5,
+    "Values": [
+      5
+    ],
     "Vindex": "user_index"
   }
 }
@@ -814,7 +578,9 @@ Gen4 plan same as above
     "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": "INT64(5)",
+    "Values": [
+      5
+    ],
     "Vindex": "user_index"
   }
 }
@@ -834,7 +600,9 @@ Gen4 plan same as above
     "FieldQuery": "select user_extra.id from `user` join user_extra on `user`.id = user_extra.user_id where 1 != 1",
     "Query": "select user_extra.id from `user` join user_extra on `user`.id = user_extra.user_id where user_extra.user_id = 5",
     "Table": "`user`, user_extra",
-    "Values": 5,
+    "Values": [
+      5
+    ],
     "Vindex": "user_index"
   }
 }
@@ -848,33 +616,18 @@ Gen4 plan same as above
       "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": "INT64(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"
-{
-  "QueryType": "SELECT",
-  "Original": "select user_extra.id from user left 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` left join user_extra on `user`.id = user_extra.user_id where 1 != 1",
-    "Query": "select user_extra.id from `user` left join user_extra on `user`.id = user_extra.user_id where `user`.id = 5",
+    "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,
+    "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"
 {
   "QueryType": "SELECT",
   "Original": "select user_extra.id from user left join user_extra on user.id = user_extra.user_id where user.id = 5",
@@ -888,10 +641,13 @@ Gen4 plan same as above
     "FieldQuery": "select user_extra.id from `user` left join user_extra on `user`.id = user_extra.user_id where 1 != 1",
     "Query": "select user_extra.id from `user` left join user_extra on `user`.id = user_extra.user_id where `user`.id = 5",
     "Table": "`user`, user_extra",
-    "Values": "INT64(5)",
+    "Values": [
+      5
+    ],
     "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"
@@ -908,7 +664,9 @@ Gen4 plan same as above
     "FieldQuery": "select user_extra.id from `user` left join user_extra on `user`.id = user_extra.user_id where 1 != 1",
     "Query": "select user_extra.id from `user` left join user_extra on `user`.id = user_extra.user_id where user_extra.user_id = 5",
     "Table": "`user`, user_extra",
-    "Values": 5,
+    "Values": [
+      5
+    ],
     "Vindex": "user_index"
   }
 }
@@ -925,7 +683,9 @@ Gen4 plan same as above
     "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": "INT64(5)",
+    "Values": [
+      5
+    ],
     "Vindex": "user_index"
   }
 }
@@ -954,7 +714,9 @@ Gen4 plan same as above
         "FieldQuery": "select `user`.col from `user` where 1 != 1",
         "Query": "select `user`.col from `user` where `user`.id = 5",
         "Table": "`user`",
-        "Values": 5,
+        "Values": [
+          5
+        ],
         "Vindex": "user_index"
       },
       {
@@ -994,7 +756,9 @@ Gen4 plan same as above
         "FieldQuery": "select `user`.col from `user` where 1 != 1",
         "Query": "select `user`.col from `user` where `user`.id = 5",
         "Table": "`user`",
-        "Values": "INT64(5)",
+        "Values": [
+          5
+        ],
         "Vindex": "user_index"
       },
       {
@@ -1036,7 +800,9 @@ Gen4 plan same as above
         "FieldQuery": "select `user`.col from `user` where 1 != 1",
         "Query": "select `user`.col from `user` where `user`.id = 5",
         "Table": "`user`",
-        "Values": 5,
+        "Values": [
+          5
+        ],
         "Vindex": "user_index"
       },
       {
@@ -1049,7 +815,9 @@ Gen4 plan same as above
         "FieldQuery": "select user_extra.id from user_extra where 1 != 1",
         "Query": "select user_extra.id from user_extra where user_extra.col = :user_col and user_extra.user_id = 5",
         "Table": "user_extra",
-        "Values": 5,
+        "Values": [
+          5
+        ],
         "Vindex": "user_index"
       }
     ]
@@ -1068,7 +836,9 @@ Gen4 plan same as above
     "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_extra.user_id = 5 and `user`.col = user_extra.col",
     "Table": "`user`, user_extra",
-    "Values": "INT64(5)",
+    "Values": [
+      5
+    ],
     "Vindex": "user_index"
   }
 }
@@ -1108,7 +878,9 @@ Gen4 plan same as above
         "FieldQuery": "select user_extra.id from user_extra where 1 != 1",
         "Query": "select user_extra.id from user_extra where user_extra.col = :user_col and user_extra.user_id = :user_col",
         "Table": "user_extra",
-        "Values": ":user_col",
+        "Values": [
+          ":user_col"
+        ],
         "Vindex": "user_index"
       }
     ]
@@ -1148,7 +920,9 @@ Gen4 plan same as above
         "FieldQuery": "select user_extra.id from user_extra where 1 != 1",
         "Query": "select user_extra.id from user_extra where user_extra.col = :user_col and user_extra.user_id = :user_col",
         "Table": "user_extra",
-        "Values": ":user_col",
+        "Values": [
+          ":user_col"
+        ],
         "Vindex": "user_index"
       }
     ]
@@ -1249,29 +1023,15 @@ Gen4 plan same as above
     "Query": "select id from `user` where `user`.col = 5 and `user`.id in ::__vals",
     "Table": "`user`",
     "Values": [
-      1,
-      2
+      [
+        1,
+        2
+      ]
     ],
     "Vindex": "user_index"
   }
 }
-{
-  "QueryType": "SELECT",
-  "Original": "select id from user where user.col = 5 and user.id in (1, 2)",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectIN",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select id from `user` where 1 != 1",
-    "Query": "select id from `user` where `user`.col = 5 and `user`.id in ::__vals",
-    "Table": "`user`",
-    "Values": "(INT64(1), INT64(2))",
-    "Vindex": "user_index"
-  }
-}
+Gen4 plan same as above
 
 # Route with multiple route constraints and boolean, SelectIN is the best constraint.
 "select id from user where user.col = case user.col when 'foo' then true else false end and user.id in (1, 2)"
@@ -1289,29 +1049,15 @@ Gen4 plan same as above
     "Query": "select id from `user` where `user`.col = case `user`.col when 'foo' then true else false end and `user`.id in ::__vals",
     "Table": "`user`",
     "Values": [
-      1,
-      2
+      [
+        1,
+        2
+      ]
     ],
     "Vindex": "user_index"
   }
 }
-{
-  "QueryType": "SELECT",
-  "Original": "select id from user where user.col = case user.col when 'foo' then true else false end and user.id in (1, 2)",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectIN",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select id from `user` where 1 != 1",
-    "Query": "select id from `user` where `user`.col = case `user`.col when 'foo' then true else false end and `user`.id in ::__vals",
-    "Table": "`user`",
-    "Values": "(INT64(1), INT64(2))",
-    "Vindex": "user_index"
-  }
-}
+Gen4 plan same as above
 
 # Route with multiple route constraints and boolean, SelectEqual is the best constraint.
 "select (id or col) as val from user where user.col = 5 and user.id in (1, 2) and user.name = 'aa'"
@@ -1328,27 +1074,13 @@ Gen4 plan same as above
     "FieldQuery": "select id or col as val from `user` where 1 != 1",
     "Query": "select id or col as val from `user` where `user`.col = 5 and `user`.id in (1, 2) and `user`.`name` = 'aa'",
     "Table": "`user`",
-    "Values": "aa",
-    "Vindex": "name_user_map"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select (id or col) as val from user where user.col = 5 and user.id in (1, 2) and user.name = 'aa'",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqual",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select id or col as val from `user` where 1 != 1",
-    "Query": "select id or col as val from `user` where `user`.col = 5 and `user`.id in (1, 2) and `user`.`name` = 'aa'",
-    "Table": "`user`",
-    "Values": "VARBINARY(\"aa\")",
+    "Values": [
+      "aa"
+    ],
     "Vindex": "name_user_map"
   }
 }
+Gen4 plan same as above
 
 # Route with multiple route constraints, SelectEqual is the best constraint.
 "select id from user where user.col = false and user.id in (1, 2) and user.name = 'aa'"
@@ -1365,27 +1097,13 @@ Gen4 plan same as above
     "FieldQuery": "select id from `user` where 1 != 1",
     "Query": "select id from `user` where `user`.col = false and `user`.id in (1, 2) and `user`.`name` = 'aa'",
     "Table": "`user`",
-    "Values": "aa",
-    "Vindex": "name_user_map"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select id from user where user.col = false and user.id in (1, 2) and user.name = 'aa'",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqual",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select id from `user` where 1 != 1",
-    "Query": "select id from `user` where `user`.col = false and `user`.id in (1, 2) and `user`.`name` = 'aa'",
-    "Table": "`user`",
-    "Values": "VARBINARY(\"aa\")",
+    "Values": [
+      "aa"
+    ],
     "Vindex": "name_user_map"
   }
 }
+Gen4 plan same as above
 
 # Route with multiple route constraints, SelectEqualUnique is the best constraint.
 "select id from user where user.col = 5 and user.id in (1, 2) and user.name = 'aa' and user.id = 1"
@@ -1402,27 +1120,13 @@ Gen4 plan same as above
     "FieldQuery": "select id from `user` where 1 != 1",
     "Query": "select id from `user` where `user`.col = 5 and `user`.id in (1, 2) and `user`.`name` = 'aa' and `user`.id = 1",
     "Table": "`user`",
-    "Values": 1,
-    "Vindex": "user_index"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select id from user where user.col = 5 and user.id in (1, 2) and user.name = 'aa' and user.id = 1",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select id from `user` where 1 != 1",
-    "Query": "select id from `user` where `user`.col = 5 and `user`.id in (1, 2) and `user`.`name` = 'aa' and `user`.id = 1",
-    "Table": "`user`",
-    "Values": "INT64(1)",
+    "Values": [
+      1
+    ],
     "Vindex": "user_index"
   }
 }
+Gen4 plan same as above
 
 # Route with multiple route constraints, SelectEqualUnique is the best constraint, order reversed.
 "select id from user where user.id = 1 and user.name = 'aa' and user.id in (1, 2) and user.col = 5"
@@ -1439,27 +1143,13 @@ Gen4 plan same as above
     "FieldQuery": "select id from `user` where 1 != 1",
     "Query": "select id from `user` where `user`.id = 1 and `user`.`name` = 'aa' and `user`.id in (1, 2) and `user`.col = 5",
     "Table": "`user`",
-    "Values": 1,
-    "Vindex": "user_index"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select id from user where user.id = 1 and user.name = 'aa' and user.id in (1, 2) and user.col = 5",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select id from `user` where 1 != 1",
-    "Query": "select id from `user` where `user`.id = 1 and `user`.`name` = 'aa' and `user`.id in (1, 2) and `user`.col = 5",
-    "Table": "`user`",
-    "Values": "INT64(1)",
+    "Values": [
+      1
+    ],
     "Vindex": "user_index"
   }
 }
+Gen4 plan same as above
 
 # Route with OR and AND clause, must parenthesize correctly.
 "select id from user where user.id = 1 or user.name = 'aa' and user.id in (1, 2)"
@@ -1553,7 +1243,9 @@ Gen4 plan same as above
         "FieldQuery": "select 1 from `user` where 1 != 1",
         "Query": "select 1 from `user` where `user`.id = :unsharded_id",
         "Table": "`user`",
-        "Values": ":unsharded_id",
+        "Values": [
+          ":unsharded_id"
+        ],
         "Vindex": "user_index"
       }
     ]
@@ -1575,27 +1267,13 @@ Gen4 plan same as above
     "FieldQuery": "select col from `user` as route1 where 1 != 1",
     "Query": "select col from `user` as route1 where id = 1",
     "Table": "`user`",
-    "Values": 1,
-    "Vindex": "user_index"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select col from route1 where id = 1",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select col from `user` as route1 where 1 != 1",
-    "Query": "select col from `user` as route1 where id = 1",
-    "Table": "`user`",
-    "Values": "INT64(1)",
+    "Values": [
+      1
+    ],
     "Vindex": "user_index"
   }
 }
+Gen4 plan same as above
 
 # 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 u.id in (user_extra.col, 1)"
@@ -1633,8 +1311,10 @@ Gen4 plan same as above
         "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 and `user`.col = :user_extra_col)",
         "Table": "`user`",
         "Values": [
-          ":user_extra_col",
-          1
+          [
+            ":user_extra_col",
+            1
+          ]
         ],
         "Vindex": "user_index"
       }
@@ -1675,7 +1355,12 @@ Gen4 plan same as above
         "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, INT64(1))",
+        "Values": [
+          [
+            ":user_extra_col",
+            1
+          ]
+        ],
         "Vindex": "user_index"
       }
     ]
@@ -1718,8 +1403,10 @@ Gen4 plan same as above
         "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
+          [
+            ":user_extra_col",
+            1
+          ]
         ],
         "Vindex": "user_index"
       }
@@ -1760,7 +1447,12 @@ Gen4 plan same as above
         "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, INT64(1))",
+        "Values": [
+          [
+            ":user_extra_col",
+            1
+          ]
+        ],
         "Vindex": "user_index"
       }
     ]
@@ -1799,7 +1491,9 @@ Gen4 plan same as above
         "FieldQuery": "select u.m from `user` as u where 1 != 1",
         "Query": "select u.m from `user` as u where u.id = 5 and u.id in (select m2 from `user` where `user`.id = 5)",
         "Table": "`user`",
-        "Values": 5,
+        "Values": [
+          5
+        ],
         "Vindex": "user_index"
       }
     ]
@@ -1835,7 +1529,9 @@ Gen4 plan same as above
         "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": "INT64(5)",
+        "Values": [
+          5
+        ],
         "Vindex": "user_index"
       }
     ]
@@ -1878,8 +1574,10 @@ Gen4 plan same as above
         "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 and `user`.col = :user_extra_col and `user`.id in (select m3 from user_extra where user_extra.user_id = `user`.id))",
         "Table": "`user`",
         "Values": [
-          ":user_extra_col",
-          1
+          [
+            ":user_extra_col",
+            1
+          ]
         ],
         "Vindex": "user_index"
       }
@@ -1920,7 +1618,12 @@ Gen4 plan same as above
         "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, INT64(1))",
+        "Values": [
+          [
+            ":user_extra_col",
+            1
+          ]
+        ],
         "Vindex": "user_index"
       }
     ]
@@ -1961,27 +1664,13 @@ Gen4 plan same as above
     "FieldQuery": "select id from `user` where 1 != 1",
     "Query": "select id from `user` where id = 5 and `user`.col in (select user_extra.col from user_extra where user_extra.user_id = 5)",
     "Table": "`user`",
-    "Values": 5,
-    "Vindex": "user_index"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select id from user where id = 5 and user.col in (select user_extra.col from user_extra where user_extra.user_id = 5)",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select id from `user` where 1 != 1",
-    "Query": "select id from `user` where id = 5 and `user`.col in (select user_extra.col from user_extra where user_extra.user_id = 5)",
-    "Table": "`user`",
-    "Values": "INT64(5)",
+    "Values": [
+      5
+    ],
     "Vindex": "user_index"
   }
 }
+Gen4 plan same as above
 
 # outer and inner subquery route by same str val
 "select id from user where id = 'aa' and user.col in (select user_extra.col from user_extra where user_extra.user_id = 'aa')"
@@ -1998,27 +1687,13 @@ Gen4 plan same as above
     "FieldQuery": "select id from `user` where 1 != 1",
     "Query": "select id from `user` where id = 'aa' and `user`.col in (select user_extra.col from user_extra where user_extra.user_id = 'aa')",
     "Table": "`user`",
-    "Values": "aa",
-    "Vindex": "user_index"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select id from user where id = 'aa' and user.col in (select user_extra.col from user_extra where user_extra.user_id = 'aa')",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select id from `user` where 1 != 1",
-    "Query": "select id from `user` where id = 'aa' and `user`.col in (select user_extra.col from user_extra where user_extra.user_id = 'aa')",
-    "Table": "`user`",
-    "Values": "VARBINARY(\"aa\")",
+    "Values": [
+      "aa"
+    ],
     "Vindex": "user_index"
   }
 }
+Gen4 plan same as above
 
 # outer and inner subquery route by same val arg
 "select id from user where id = :a and user.col in (select user_extra.col from user_extra where user_extra.user_id = :a)"
@@ -2035,7 +1710,9 @@ Gen4 plan same as above
     "FieldQuery": "select id from `user` where 1 != 1",
     "Query": "select id from `user` where id = :a and `user`.col in (select user_extra.col from user_extra where user_extra.user_id = :a)",
     "Table": "`user`",
-    "Values": ":a",
+    "Values": [
+      ":a"
+    ],
     "Vindex": "user_index"
   }
 }
@@ -2100,50 +1777,15 @@ Gen4 plan same as above
         "FieldQuery": "select id from `user` where 1 != 1",
         "Query": "select id from `user` where :__sq_has_values1 = 1 and id in ::__vals",
         "Table": "`user`",
-        "Values": "::__sq1",
-        "Vindex": "user_index"
-      }
-    ]
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select id from user where id in (select col from user)",
-  "Instructions": {
-    "OperatorType": "Subquery",
-    "Variant": "PulloutIn",
-    "PulloutVars": [
-      "__sq_has_values1",
-      "__sq1"
-    ],
-    "Inputs": [
-      {
-        "OperatorType": "Route",
-        "Variant": "SelectScatter",
-        "Keyspace": {
-          "Name": "user",
-          "Sharded": true
-        },
-        "FieldQuery": "select col from `user` where 1 != 1",
-        "Query": "select col from `user`",
-        "Table": "`user`"
-      },
-      {
-        "OperatorType": "Route",
-        "Variant": "SelectIN",
-        "Keyspace": {
-          "Name": "user",
-          "Sharded": true
-        },
-        "FieldQuery": "select id from `user` where 1 != 1",
-        "Query": "select id from `user` where :__sq_has_values1 = 1 and id in ::__vals",
-        "Table": "`user`",
-        "Values": ":__sq1",
+        "Values": [
+          "::__sq1"
+        ],
         "Vindex": "user_index"
       }
     ]
   }
 }
+Gen4 plan same as above
 
 # cross-shard subquery in NOT IN clause.
 "select id from user where id not in (select col from user)"
@@ -2293,7 +1935,9 @@ Gen4 plan same as above
         "FieldQuery": "select id from `user` where 1 != 1",
         "Query": "select id from `user` where id = :__sq1",
         "Table": "`user`",
-        "Values": ":__sq1",
+        "Values": [
+          ":__sq1"
+        ],
         "Vindex": "user_index"
       }
     ]
@@ -2356,7 +2000,9 @@ Gen4 plan same as above
         "FieldQuery": "select id1 from `user` where 1 != 1",
         "Query": "select id1 from `user` where id = :__sq2",
         "Table": "`user`",
-        "Values": ":__sq2",
+        "Values": [
+          ":__sq2"
+        ],
         "Vindex": "user_index"
       }
     ]
@@ -2415,7 +2061,9 @@ Gen4 plan same as above
         "FieldQuery": "select id1 from `user` where 1 != 1",
         "Query": "select id1 from `user` where id = :__sq1",
         "Table": "`user`",
-        "Values": ":__sq1",
+        "Values": [
+          ":__sq1"
+        ],
         "Vindex": "user_index"
       }
     ]
@@ -2475,7 +2123,9 @@ Gen4 plan same as above
         "FieldQuery": "select col from `user` where 1 != 1",
         "Query": "select col from `user` where id = :__sq1",
         "Table": "`user`",
-        "Values": ":__sq1",
+        "Values": [
+          ":__sq1"
+        ],
         "Vindex": "user_index"
       }
     ]
@@ -2498,7 +2148,9 @@ Gen4 plan same as above
     "FieldQuery": "select user_extra.Id from `user` join user_extra on `user`.iD = user_extra.User_Id where 1 != 1",
     "Query": "select user_extra.Id from `user` join user_extra on `user`.iD = user_extra.User_Id where `user`.Id = 5",
     "Table": "`user`, user_extra",
-    "Values": 5,
+    "Values": [
+      5
+    ],
     "Vindex": "user_index"
   }
 }
@@ -2515,7 +2167,9 @@ Gen4 plan same as above
     "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": "INT64(5)",
+    "Values": [
+      5
+    ],
     "Vindex": "user_index"
   }
 }
@@ -2573,27 +2227,13 @@ Gen4 plan same as above
     "FieldQuery": "select id from music where 1 != 1",
     "Query": "select id from music where id is null",
     "Table": "music",
-    "Values": null,
-    "Vindex": "music_user_map"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select id from music where id is null",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select id from music where 1 != 1",
-    "Query": "select id from music where id is null",
-    "Table": "music",
-    "Values": "NULL",
+    "Values": [
+      null
+    ],
     "Vindex": "music_user_map"
   }
 }
+Gen4 plan same as above
 
 # SELECT with IS NOT NULL
 "select id from music where id is not null"
@@ -2667,27 +2307,13 @@ Gen4 plan same as above
     "FieldQuery": "select id from music where 1 != 1",
     "Query": "select id from music where user_id = 4 and id in (null, 1, 2)",
     "Table": "music",
-    "Values": 4,
-    "Vindex": "user_index"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select id from music where user_id = 4 and id IN (null, 1, 2)",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select id from music where 1 != 1",
-    "Query": "select id from music where user_id = 4 and id in (null, 1, 2)",
-    "Table": "music",
-    "Values": "INT64(4)",
+    "Values": [
+      4
+    ],
     "Vindex": "user_index"
   }
 }
+Gen4 plan same as above
 
 # Single table with unique vindex match and NOT IN (null, 1, 2)
 "select id from music where user_id = 4 and id NOT IN (null, 1, 2)"
@@ -2750,7 +2376,9 @@ Gen4 plan same as above
         "FieldQuery": "select user_extra.col from user_extra where 1 != 1",
         "Query": "select user_extra.col from user_extra where user_extra.user_id = 42",
         "Table": "user_extra",
-        "Values": 42,
+        "Values": [
+          42
+        ],
         "Vindex": "user_index"
       },
       {
@@ -2771,7 +2399,9 @@ Gen4 plan same as above
             "FieldQuery": "select user_extra.col from user_extra where 1 != 1",
             "Query": "select user_extra.col from user_extra where user_extra.user_id = 411",
             "Table": "user_extra",
-            "Values": 411,
+            "Values": [
+              411
+            ],
             "Vindex": "user_index"
           },
           {
@@ -2784,7 +2414,9 @@ Gen4 plan same as above
             "FieldQuery": "select id from `user` where 1 != 1",
             "Query": "select id from `user` where :__sq_has_values1 = 1 and id in ::__vals and (:__sq_has_values2 = 0 or id not in ::__sq2)",
             "Table": "`user`",
-            "Values": "::__sq1",
+            "Values": [
+              "::__sq1"
+            ],
             "Vindex": "user_index"
           }
         ]
@@ -2813,7 +2445,9 @@ Gen4 plan same as above
         "FieldQuery": "select user_extra.col from user_extra where 1 != 1",
         "Query": "select user_extra.col from user_extra where user_extra.user_id = 411",
         "Table": "user_extra",
-        "Values": "INT64(411)",
+        "Values": [
+          411
+        ],
         "Vindex": "user_index"
       },
       {
@@ -2834,7 +2468,9 @@ Gen4 plan same as above
             "FieldQuery": "select user_extra.col from user_extra where 1 != 1",
             "Query": "select user_extra.col from user_extra where user_extra.user_id = 42",
             "Table": "user_extra",
-            "Values": "INT64(42)",
+            "Values": [
+              42
+            ],
             "Vindex": "user_index"
           },
           {
@@ -2847,7 +2483,9 @@ Gen4 plan same as above
             "FieldQuery": "select id from `user` where 1 != 1",
             "Query": "select id from `user` where (:__sq_has_values1 = 0 or id not in ::__sq1) and (:__sq_has_values2 = 1 and id in ::__vals)",
             "Table": "`user`",
-            "Values": ":__sq2",
+            "Values": [
+              "::__sq2"
+            ],
             "Vindex": "user_index"
           }
         ]
@@ -2871,27 +2509,13 @@ Gen4 plan same as above
     "FieldQuery": "select c2 from cfc_vindex_col where 1 != 1",
     "Query": "select c2 from cfc_vindex_col where c1 like 'A%'",
     "Table": "cfc_vindex_col",
-    "Values": "A%",
-    "Vindex": "cfc"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select c2 from cfc_vindex_col where c1 like 'A%'",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqual",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select c2 from cfc_vindex_col where 1 != 1",
-    "Query": "select c2 from cfc_vindex_col where c1 like 'A%'",
-    "Table": "cfc_vindex_col",
-    "Values": "VARBINARY(\"A%\")",
+    "Values": [
+      "A%"
+    ],
     "Vindex": "cfc"
   }
 }
+Gen4 plan same as above
 
 "select * from samecolvin where col = :col"
 {
@@ -2907,7 +2531,9 @@ Gen4 plan same as above
     "FieldQuery": "select col from samecolvin where 1 != 1",
     "Query": "select col from samecolvin where col = :col",
     "Table": "samecolvin",
-    "Values": ":col",
+    "Values": [
+      ":col"
+    ],
     "Vindex": "vindex1"
   }
 }
@@ -2985,50 +2611,15 @@ Gen4 plan same as above
         "FieldQuery": "select id from `user` where 1 != 1",
         "Query": "select id from `user` where :__sq_has_values1 = 1 and id in ::__vals",
         "Table": "`user`",
-        "Values": "::__sq1",
-        "Vindex": "user_index"
-      }
-    ]
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select id from user where id in (select col from unsharded where col = id)",
-  "Instructions": {
-    "OperatorType": "Subquery",
-    "Variant": "PulloutIn",
-    "PulloutVars": [
-      "__sq_has_values1",
-      "__sq1"
-    ],
-    "Inputs": [
-      {
-        "OperatorType": "Route",
-        "Variant": "SelectUnsharded",
-        "Keyspace": {
-          "Name": "main",
-          "Sharded": false
-        },
-        "FieldQuery": "select col from unsharded where 1 != 1",
-        "Query": "select col from unsharded where col = id",
-        "Table": "unsharded"
-      },
-      {
-        "OperatorType": "Route",
-        "Variant": "SelectIN",
-        "Keyspace": {
-          "Name": "user",
-          "Sharded": true
-        },
-        "FieldQuery": "select id from `user` where 1 != 1",
-        "Query": "select id from `user` where :__sq_has_values1 = 1 and id in ::__vals",
-        "Table": "`user`",
-        "Values": ":__sq1",
+        "Values": [
+          "::__sq1"
+        ],
         "Vindex": "user_index"
       }
     ]
   }
 }
+Gen4 plan same as above
 
 # correlated subquery with different keyspace tables involved
 "select id from user where id in (select col from unsharded where col = user.id)"
@@ -3107,27 +2698,13 @@ Gen4 plan same as above
     "FieldQuery": "select u1.col from `user` as u1 where 1 != 1",
     "Query": "select u1.col from `user` as u1 where u1.id = 5 and u1.`name` in (select u2.`name` from `user` as u2 where u2.id = 5)",
     "Table": "`user`",
-    "Values": 5,
-    "Vindex": "user_index"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select u1.col from user as u1 where u1.id = 5 and u1.name in (select u2.name from user u2 where u2.id = 5)",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select u1.col from `user` as u1 where 1 != 1",
-    "Query": "select u1.col from `user` as u1 where u1.id = 5 and u1.`name` in (select u2.`name` from `user` as u2 where u2.id = 5)",
-    "Table": "`user`",
-    "Values": "INT64(5)",
+    "Values": [
+      5
+    ],
     "Vindex": "user_index"
   }
 }
+Gen4 plan same as above
 
 # SelectEqualUnique with EXISTS uncorrelated subquery
 "select u1.col from user as u1 where u1.id = 5 and exists (select u2.name from user u2 where u2.id = 5)"
@@ -3144,27 +2721,13 @@ Gen4 plan same as above
     "FieldQuery": "select u1.col from `user` as u1 where 1 != 1",
     "Query": "select u1.col from `user` as u1 where u1.id = 5 and exists (select u2.`name` from `user` as u2 where u2.id = 5)",
     "Table": "`user`",
-    "Values": 5,
-    "Vindex": "user_index"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select u1.col from user as u1 where u1.id = 5 and exists (select u2.name from user u2 where u2.id = 5)",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select u1.col from `user` as u1 where 1 != 1",
-    "Query": "select u1.col from `user` as u1 where u1.id = 5 and exists (select u2.`name` from `user` as u2 where u2.id = 5)",
-    "Table": "`user`",
-    "Values": "INT64(5)",
+    "Values": [
+      5
+    ],
     "Vindex": "user_index"
   }
 }
+Gen4 plan same as above
 
 # SelectEqualUnique with NOT EXISTS uncorrelated subquery
 "select u1.col from user as u1 where u1.id = 5 and not exists (select u2.name from user u2 where u2.id = 5)"
@@ -3181,27 +2744,13 @@ Gen4 plan same as above
     "FieldQuery": "select u1.col from `user` as u1 where 1 != 1",
     "Query": "select u1.col from `user` as u1 where u1.id = 5 and not exists (select u2.`name` from `user` as u2 where u2.id = 5)",
     "Table": "`user`",
-    "Values": 5,
-    "Vindex": "user_index"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select u1.col from user as u1 where u1.id = 5 and not exists (select u2.name from user u2 where u2.id = 5)",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select u1.col from `user` as u1 where 1 != 1",
-    "Query": "select u1.col from `user` as u1 where u1.id = 5 and not exists (select u2.`name` from `user` as u2 where u2.id = 5)",
-    "Table": "`user`",
-    "Values": "INT64(5)",
+    "Values": [
+      5
+    ],
     "Vindex": "user_index"
   }
 }
+Gen4 plan same as above
 
 # SelectScatter with NOT EXISTS uncorrelated subquery
 "select u1.col from user as u1 where not exists (select u2.name from user u2 where u2.id = 5)"
@@ -3226,7 +2775,9 @@ Gen4 plan same as above
         "FieldQuery": "select u2.`name` from `user` as u2 where 1 != 1",
         "Query": "select u2.`name` from `user` as u2 where u2.id = 5",
         "Table": "`user`",
-        "Values": 5,
+        "Values": [
+          5
+        ],
         "Vindex": "user_index"
       },
       {
@@ -3263,7 +2814,9 @@ Gen4 plan same as above
         "FieldQuery": "select u2.`name` from `user` as u2 where 1 != 1",
         "Query": "select u2.`name` from `user` as u2 where u2.id = 5",
         "Table": "`user`",
-        "Values": "INT64(5)",
+        "Values": [
+          5
+        ],
         "Vindex": "user_index"
       },
       {
@@ -3304,7 +2857,9 @@ Gen4 plan same as above
         "FieldQuery": "select user_extra.col from user_extra where 1 != 1",
         "Query": "select user_extra.col from user_extra where user_extra.user_id = 4",
         "Table": "user_extra",
-        "Values": 4,
+        "Values": [
+          4
+        ],
         "Vindex": "user_index"
       },
       {
@@ -3317,7 +2872,9 @@ Gen4 plan same as above
         "FieldQuery": "select id from `user` where 1 != 1",
         "Query": "select id from `user` where id = 5 and :__sq_has_values1 = 1 and id in ::__sq1 and id not in (select user_extra.col from user_extra where user_extra.user_id = 5)",
         "Table": "`user`",
-        "Values": 5,
+        "Values": [
+          5
+        ],
         "Vindex": "user_index"
       }
     ]
@@ -3344,7 +2901,9 @@ Gen4 plan same as above
         "FieldQuery": "select user_extra.col from user_extra where 1 != 1",
         "Query": "select user_extra.col from user_extra where user_extra.user_id = 4",
         "Table": "user_extra",
-        "Values": "INT64(4)",
+        "Values": [
+          4
+        ],
         "Vindex": "user_index"
       },
       {
@@ -3357,7 +2916,9 @@ Gen4 plan same as above
         "FieldQuery": "select id from `user` where 1 != 1",
         "Query": "select id from `user` where id = 5 and id not in (select user_extra.col from user_extra where user_extra.user_id = 5) and (:__sq_has_values2 = 1 and id in ::__sq2)",
         "Table": "`user`",
-        "Values": "INT64(5)",
+        "Values": [
+          5
+        ],
         "Vindex": "user_index"
       }
     ]
@@ -3387,7 +2948,9 @@ Gen4 plan same as above
         "FieldQuery": "select user_extra.col from user_extra where 1 != 1",
         "Query": "select user_extra.col from user_extra where user_extra.user_id = 4",
         "Table": "user_extra",
-        "Values": 4,
+        "Values": [
+          4
+        ],
         "Vindex": "user_index"
       },
       {
@@ -3400,7 +2963,9 @@ Gen4 plan same as above
         "FieldQuery": "select id from `user` where 1 != 1",
         "Query": "select id from `user` where id = 5 and id in (select user_extra.col from user_extra where user_extra.user_id = 5) and (:__sq_has_values1 = 0 or id not in ::__sq1)",
         "Table": "`user`",
-        "Values": 5,
+        "Values": [
+          5
+        ],
         "Vindex": "user_index"
       }
     ]
@@ -3427,7 +2992,9 @@ Gen4 plan same as above
         "FieldQuery": "select user_extra.col from user_extra where 1 != 1",
         "Query": "select user_extra.col from user_extra where user_extra.user_id = 4",
         "Table": "user_extra",
-        "Values": "INT64(4)",
+        "Values": [
+          4
+        ],
         "Vindex": "user_index"
       },
       {
@@ -3440,7 +3007,9 @@ Gen4 plan same as above
         "FieldQuery": "select id from `user` where 1 != 1",
         "Query": "select id from `user` where id = 5 and (:__sq_has_values1 = 0 or id not in ::__sq1) and id in (select user_extra.col from user_extra where user_extra.user_id = 5)",
         "Table": "`user`",
-        "Values": "INT64(5)",
+        "Values": [
+          5
+        ],
         "Vindex": "user_index"
       }
     ]
@@ -3510,7 +3079,9 @@ Gen4 plan same as above
     "FieldQuery": "select id from `user` where 1 != 1",
     "Query": "select id from `user` where `user`.id = `user`.col and `user`.col = 5",
     "Table": "`user`",
-    "Values": "INT64(5)",
+    "Values": [
+      5
+    ],
     "Vindex": "user_index"
   }
 }
@@ -3643,7 +3214,9 @@ Gen4 plan same as above
         "FieldQuery": "select id from `user` where 1 != 1",
         "Query": "select id from `user` where `user`.id = :user_extra_col",
         "Table": "`user`",
-        "Values": ":user_extra_col",
+        "Values": [
+          ":user_extra_col"
+        ],
         "Vindex": "user_index"
       }
     ]
@@ -3815,27 +3388,13 @@ Gen4 plan same as above
     "FieldQuery": "select * from multicolvin where 1 != 1",
     "Query": "select * from multicolvin where column_b = 1",
     "Table": "multicolvin",
-    "Values": 1,
-    "Vindex": "colb_colc_map"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select * from multicolvin where column_b = 1",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select * from multicolvin where 1 != 1",
-    "Query": "select * from multicolvin where column_b = 1",
-    "Table": "multicolvin",
-    "Values": "INT64(1)",
+    "Values": [
+      1
+    ],
     "Vindex": "colb_colc_map"
   }
 }
+Gen4 plan same as above
 
 # should only use first column of the vindex colb_colc_map
 "select * from multicolvin where column_b = 1 and column_c = 2"
@@ -3852,27 +3411,13 @@ Gen4 plan same as above
     "FieldQuery": "select * from multicolvin where 1 != 1",
     "Query": "select * from multicolvin where column_b = 1 and column_c = 2",
     "Table": "multicolvin",
-    "Values": 1,
-    "Vindex": "colb_colc_map"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select * from multicolvin where column_b = 1 and column_c = 2",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select * from multicolvin where 1 != 1",
-    "Query": "select * from multicolvin where column_b = 1 and column_c = 2",
-    "Table": "multicolvin",
-    "Values": "INT64(1)",
+    "Values": [
+      1
+    ],
     "Vindex": "colb_colc_map"
   }
 }
+Gen4 plan same as above
 
 # uses vindex colb_colc_map
 "select * from multicolvin where column_b = 1 and column_c = 2 and column_a = 3"
@@ -3889,27 +3434,13 @@ Gen4 plan same as above
     "FieldQuery": "select * from multicolvin where 1 != 1",
     "Query": "select * from multicolvin where column_b = 1 and column_c = 2 and column_a = 3",
     "Table": "multicolvin",
-    "Values": 1,
-    "Vindex": "colb_colc_map"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select * from multicolvin where column_b = 1 and column_c = 2 and column_a = 3",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select * from multicolvin where 1 != 1",
-    "Query": "select * from multicolvin where column_b = 1 and column_c = 2 and column_a = 3",
-    "Table": "multicolvin",
-    "Values": "INT64(1)",
+    "Values": [
+      1
+    ],
     "Vindex": "colb_colc_map"
   }
 }
+Gen4 plan same as above
 
 # v3 takes cola_map, gen4 takes colb_colc_map, may be based on map key ordering
 "select * from multicolvin where column_a = 3 and column_b = 1"
@@ -3926,7 +3457,9 @@ Gen4 plan same as above
     "FieldQuery": "select * from multicolvin where 1 != 1",
     "Query": "select * from multicolvin where column_a = 3 and column_b = 1",
     "Table": "multicolvin",
-    "Values": 3,
+    "Values": [
+      3
+    ],
     "Vindex": "cola_map"
   }
 }
@@ -3943,7 +3476,9 @@ Gen4 plan same as above
     "FieldQuery": "select * from multicolvin where 1 != 1",
     "Query": "select * from multicolvin where column_a = 3 and column_b = 1",
     "Table": "multicolvin",
-    "Values": "INT64(1)",
+    "Values": [
+      1
+    ],
     "Vindex": "colb_colc_map"
   }
 }
@@ -3991,7 +3526,9 @@ Gen4 plan same as above
         "FieldQuery": "select `user`.col from `user` where 1 != 1",
         "Query": "select /*vt+ ALLOW_HASH_JOIN */ `user`.col from `user` where `user`.id = 5",
         "Table": "`user`",
-        "Values": 5,
+        "Values": [
+          5
+        ],
         "Vindex": "user_index"
       },
       {
@@ -4029,7 +3566,9 @@ Gen4 plan same as above
         "FieldQuery": "select `user`.col from `user` where 1 != 1",
         "Query": "select /*vt+ ALLOW_HASH_JOIN */ `user`.col from `user` where `user`.id = 5",
         "Table": "`user`",
-        "Values": "INT64(5)",
+        "Values": [
+          5
+        ],
         "Vindex": "user_index"
       },
       {
diff --git a/go/vt/vtgate/planbuilder/testdata/from_cases.txt b/go/vt/vtgate/planbuilder/testdata/from_cases.txt
index 105e673d3c..6d97927358 100644
--- a/go/vt/vtgate/planbuilder/testdata/from_cases.txt
+++ b/go/vt/vtgate/planbuilder/testdata/from_cases.txt
@@ -132,7 +132,9 @@ Gen4 error: Incorrect usage/placement of 'NEXT'
         "FieldQuery": "select 1 from `user` where 1 != 1",
         "Query": "select 1 from `user` where :__sq_has_values1 = 1 and id in ::__vals",
         "Table": "`user`",
-        "Values": "::__sq1",
+        "Values": [
+          "::__sq1"
+        ],
         "Vindex": "user_index"
       }
     ]
@@ -441,7 +443,9 @@ Gen4 plan same as above
         "FieldQuery": "select 1 from `user` where 1 != 1",
         "Query": "select 1 from `user` where `user`.id = :music_id",
         "Table": "`user`",
-        "Values": ":music_id",
+        "Values": [
+          ":music_id"
+        ],
         "Vindex": "user_index"
       }
     ]
@@ -481,7 +485,9 @@ Gen4 plan same as above
         "FieldQuery": "select 1 from `user` where 1 != 1",
         "Query": "select 1 from `user` where `user`.id = :music_id",
         "Table": "`user`",
-        "Values": ":music_id",
+        "Values": [
+          ":music_id"
+        ],
         "Vindex": "user_index"
       }
     ]
@@ -1425,7 +1431,9 @@ Gen4 plan same as above
     "FieldQuery": "select `user`.col from `user` join user_extra on `user`.id = 5 and `user`.id = user_extra.user_id where 1 != 1",
     "Query": "select `user`.col from `user` join user_extra on `user`.id = 5 and `user`.id = user_extra.user_id",
     "Table": "`user`, user_extra",
-    "Values": 5,
+    "Values": [
+      5
+    ],
     "Vindex": "user_index"
   }
 }
@@ -1442,7 +1450,9 @@ Gen4 plan same as above
     "FieldQuery": "select `user`.col from `user`, user_extra where 1 != 1",
     "Query": "select `user`.col from `user`, user_extra where `user`.id = 5 and `user`.id = user_extra.user_id",
     "Table": "`user`, user_extra",
-    "Values": "INT64(5)",
+    "Values": [
+      5
+    ],
     "Vindex": "user_index"
   }
 }
@@ -1546,43 +1556,9 @@ Gen4 plan same as above
         "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": "SelectScatter",
-        "Keyspace": {
-          "Name": "user",
-          "Sharded": true
-        },
-        "FieldQuery": "select 1 from user_extra where 1 != 1",
-        "Query": "select 1 from user_extra",
-        "Table": "user_extra"
-      }
-    ]
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select user.col from user join user_extra on 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": "INT64(5)",
+        "Values": [
+          5
+        ],
         "Vindex": "user_index"
       },
       {
@@ -1599,6 +1575,7 @@ Gen4 plan same as above
     ]
   }
 }
+Gen4 plan same as above
 
 # sharded join, non-col reference LHS
 "select user.col from user join user_extra on 5 = user.id"
@@ -1621,43 +1598,9 @@ Gen4 plan same as above
         "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": "SelectScatter",
-        "Keyspace": {
-          "Name": "user",
-          "Sharded": true
-        },
-        "FieldQuery": "select 1 from user_extra where 1 != 1",
-        "Query": "select 1 from user_extra",
-        "Table": "user_extra"
-      }
-    ]
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select user.col from user join user_extra on 5 = user.id",
-  "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": "INT64(5)",
+        "Values": [
+          5
+        ],
         "Vindex": "user_index"
       },
       {
@@ -1674,6 +1617,7 @@ Gen4 plan same as above
     ]
   }
 }
+Gen4 plan same as above
 
 # sharded join, non-vindex col
 "select user.col from user join user_extra on user.id = user_extra.col"
@@ -1748,7 +1692,9 @@ Gen4 plan same as above
         "FieldQuery": "select `user`.col from `user` where 1 != 1",
         "Query": "select `user`.col from `user` where `user`.id = :user_extra_col",
         "Table": "`user`",
-        "Values": ":user_extra_col",
+        "Values": [
+          ":user_extra_col"
+        ],
         "Vindex": "user_index"
       }
     ]
@@ -1790,7 +1736,9 @@ Gen4 plan same as above
         "FieldQuery": "select `user`.col from `user` where 1 != 1",
         "Query": "select `user`.col from `user` where `user`.`name` = :user_extra_user_id",
         "Table": "`user`",
-        "Values": ":user_extra_user_id",
+        "Values": [
+          ":user_extra_user_id"
+        ],
         "Vindex": "name_user_map"
       }
     ]
@@ -1830,7 +1778,9 @@ Gen4 plan same as above
         "FieldQuery": "select 1 from user_extra where 1 != 1",
         "Query": "select 1 from user_extra where user_extra.user_id = :user_name",
         "Table": "user_extra",
-        "Values": ":user_name",
+        "Values": [
+          ":user_name"
+        ],
         "Vindex": "user_index"
       }
     ]
@@ -1952,7 +1902,9 @@ Gen4 plan same as above
     "FieldQuery": "select ref.col from ref join (select aa from `user` where 1 != 1) as `user` where 1 != 1",
     "Query": "select ref.col from ref join (select aa from `user` where `user`.id = 1) as `user`",
     "Table": "`user`, ref",
-    "Values": 1,
+    "Values": [
+      1
+    ],
     "Vindex": "user_index"
   }
 }
@@ -1969,7 +1921,9 @@ Gen4 plan same as above
     "FieldQuery": "select ref.col from ref, (select aa from `user` where 1 != 1) as `user` where 1 != 1",
     "Query": "select ref.col from ref, (select aa from `user` where `user`.id = 1) as `user`",
     "Table": "`user`, ref",
-    "Values": "INT64(1)",
+    "Values": [
+      1
+    ],
     "Vindex": "user_index"
   }
 }
@@ -2027,27 +1981,13 @@ Gen4 plan same as above
     "FieldQuery": "select id from (select id, col from `user` where 1 != 1) as t where 1 != 1",
     "Query": "select id from (select id, col from `user` where id = 5) as t",
     "Table": "`user`",
-    "Values": 5,
-    "Vindex": "user_index"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select id from (select id, col from user where id = 5) as t",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select id from (select id, col from `user` where 1 != 1) as t where 1 != 1",
-    "Query": "select id from (select id, col from `user` where id = 5) as t",
-    "Table": "`user`",
-    "Values": "INT64(5)",
+    "Values": [
+      5
+    ],
     "Vindex": "user_index"
   }
 }
+Gen4 plan same as above
 
 # derived table with join
 "select t.id from (select id from user where id = 5) as t join user_extra on t.id = user_extra.user_id"
@@ -2064,7 +2004,9 @@ Gen4 plan same as above
     "FieldQuery": "select t.id from (select id from `user` where 1 != 1) as t join user_extra on t.id = user_extra.user_id where 1 != 1",
     "Query": "select t.id from (select id from `user` where id = 5) as t join user_extra on t.id = user_extra.user_id",
     "Table": "`user`, user_extra",
-    "Values": 5,
+    "Values": [
+      5
+    ],
     "Vindex": "user_index"
   }
 }
@@ -2081,7 +2023,9 @@ Gen4 plan same as above
     "FieldQuery": "select t.id from (select id from `user` where 1 != 1) as t, user_extra where 1 != 1",
     "Query": "select t.id from (select id from `user` where id = 5) as t, user_extra where t.id = user_extra.user_id",
     "Table": "`user`, user_extra",
-    "Values": "INT64(5)",
+    "Values": [
+      5
+    ],
     "Vindex": "user_index"
   }
 }
@@ -2101,7 +2045,9 @@ Gen4 plan same as above
     "FieldQuery": "select t.id from (select `user`.id from `user` where 1 != 1) as t join user_extra on t.id = user_extra.user_id where 1 != 1",
     "Query": "select t.id from (select `user`.id from `user` where `user`.id = 5) as t join user_extra on t.id = user_extra.user_id",
     "Table": "`user`, user_extra",
-    "Values": 5,
+    "Values": [
+      5
+    ],
     "Vindex": "user_index"
   }
 }
@@ -2118,7 +2064,9 @@ Gen4 plan same as above
     "FieldQuery": "select t.id from (select `user`.id from `user` where 1 != 1) as t, user_extra where 1 != 1",
     "Query": "select t.id from (select `user`.id from `user` where `user`.id = 5) as t, user_extra where t.id = user_extra.user_id",
     "Table": "`user`, user_extra",
-    "Values": "INT64(5)",
+    "Values": [
+      5
+    ],
     "Vindex": "user_index"
   }
 }
@@ -2158,7 +2106,9 @@ Gen4 error: Duplicate column name 'id'
     "FieldQuery": "select t.id from user_extra, (select id from `user` where 1 != 1) as t where 1 != 1",
     "Query": "select t.id from user_extra, (select id from `user` where id = 5) as t where t.id = user_extra.user_id",
     "Table": "`user`, user_extra",
-    "Values": "INT64(5)",
+    "Values": [
+      5
+    ],
     "Vindex": "user_index"
   }
 }
@@ -2187,7 +2137,9 @@ Gen4 error: Duplicate column name 'id'
         "FieldQuery": "select t.id from (select id from `user` where 1 != 1) as t where 1 != 1",
         "Query": "select t.id from (select id from `user` where id = 5) as t",
         "Table": "`user`",
-        "Values": 5,
+        "Values": [
+          5
+        ],
         "Vindex": "user_index"
       },
       {
@@ -2227,7 +2179,9 @@ Gen4 error: Duplicate column name 'id'
         "FieldQuery": "select t.id from (select id from `user` where 1 != 1) as t where 1 != 1",
         "Query": "select t.id from (select id from `user` where id = 5) as t",
         "Table": "`user`",
-        "Values": "INT64(5)",
+        "Values": [
+          5
+        ],
         "Vindex": "user_index"
       },
       {
@@ -2260,27 +2214,13 @@ Gen4 error: Duplicate column name 'id'
     "FieldQuery": "select id from (select id, col from `user` as route1 where 1 != 1) as t where 1 != 1",
     "Query": "select id from (select id, col from `user` as route1 where id = 5) as t",
     "Table": "`user`",
-    "Values": 5,
-    "Vindex": "user_index"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select id from (select id, col from route1 where id = 5) as t",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select id from (select id, col from `user` as route1 where 1 != 1) as t where 1 != 1",
-    "Query": "select id from (select id, col from `user` as route1 where id = 5) as t",
-    "Table": "`user`",
-    "Values": "INT64(5)",
+    "Values": [
+      5
+    ],
     "Vindex": "user_index"
   }
 }
+Gen4 plan same as above
 
 # derived table missing columns
 "select t.id from (select id from user) as t join user_extra on t.id = user_extra.user_id where t.col = 42"
@@ -2316,7 +2256,9 @@ Gen4 error: symbol t.col not found
     "FieldQuery": "select id from (select id, col from `user` as route1 where 1 != 1) as t where 1 != 1",
     "Query": "select id from (select id, col from `user` as route1) as t where id = 5",
     "Table": "`user`",
-    "Values": 5,
+    "Values": [
+      5
+    ],
     "Vindex": "user_index"
   }
 }
@@ -2333,7 +2275,9 @@ Gen4 error: symbol t.col not found
     "FieldQuery": "select id from (select id, col from `user` as route1 where 1 != 1) as t where 1 != 1",
     "Query": "select id from (select id, col from `user` as route1 where id = 5) as t",
     "Table": "`user`",
-    "Values": "INT64(5)",
+    "Values": [
+      5
+    ],
     "Vindex": "user_index"
   }
 }
@@ -2438,7 +2382,9 @@ Gen4 error: symbol id not found
     "FieldQuery": "select id from (select id from (select id from `user` where 1 != 1) as u where 1 != 1) as t where 1 != 1",
     "Query": "select id from (select id from (select id from `user`) as u) as t where id = 5",
     "Table": "`user`",
-    "Values": 5,
+    "Values": [
+      5
+    ],
     "Vindex": "user_index"
   }
 }
@@ -2455,7 +2401,9 @@ Gen4 error: symbol id not found
     "FieldQuery": "select id from (select id from (select id from `user` where 1 != 1) as u where 1 != 1) as t where 1 != 1",
     "Query": "select id from (select id from (select id from `user` where id = 5) as u) as t",
     "Table": "`user`",
-    "Values": "INT64(5)",
+    "Values": [
+      5
+    ],
     "Vindex": "user_index"
   }
 }
@@ -2475,7 +2423,9 @@ Gen4 error: symbol id not found
     "FieldQuery": "select u.col, e.col from (select col from `user` where 1 != 1) as u join (select col from user_extra where 1 != 1) as e where 1 != 1",
     "Query": "select u.col, e.col from (select col from `user` where id = 5) as u join (select col from user_extra where user_id = 5) as e",
     "Table": "`user`, user_extra",
-    "Values": 5,
+    "Values": [
+      5
+    ],
     "Vindex": "user_index"
   }
 }
@@ -2492,7 +2442,9 @@ Gen4 error: symbol id not found
     "FieldQuery": "select u.col, e.col from (select col from `user` where 1 != 1) as u, (select col from user_extra where 1 != 1) as e where 1 != 1",
     "Query": "select u.col, e.col from (select col from `user` where id = 5) as u, (select col from user_extra where user_id = 5) as e",
     "Table": "`user`, user_extra",
-    "Values": "INT64(5)",
+    "Values": [
+      5
+    ],
     "Vindex": "user_index"
   }
 }
@@ -2918,7 +2870,9 @@ Gen4 plan same as above
                 "FieldQuery": "select `user`.id, `user`.col1 from `user` where 1 != 1",
                 "Query": "select `user`.id, `user`.col1 from `user` where `user`.id = :ua_id",
                 "Table": "`user`",
-                "Values": ":ua_id",
+                "Values": [
+                  ":ua_id"
+                ],
                 "Vindex": "user_index"
               },
               {
@@ -3814,7 +3768,9 @@ Gen4 plan same as above
         "FieldQuery": "select `user`.id from `user` where 1 != 1",
         "Query": "select `user`.id from `user` where `user`.id = :user_extra_id",
         "Table": "`user`",
-        "Values": ":user_extra_id",
+        "Values": [
+          ":user_extra_id"
+        ],
         "Vindex": "user_index"
       }
     ]
@@ -3856,7 +3812,9 @@ Gen4 plan same as above
         "FieldQuery": "select 1 from user_extra where 1 != 1",
         "Query": "select 1 from user_extra where user_extra.assembly_id = :user_id and user_extra.user_id = 2",
         "Table": "user_extra",
-        "Values": 2,
+        "Values": [
+          2
+        ],
         "Vindex": "user_index"
       }
     ]
@@ -3885,7 +3843,9 @@ Gen4 plan same as above
         "FieldQuery": "select user_extra.assembly_id from user_extra where 1 != 1",
         "Query": "select user_extra.assembly_id from user_extra where user_extra.user_id = 2",
         "Table": "user_extra",
-        "Values": "INT64(2)",
+        "Values": [
+          2
+        ],
         "Vindex": "user_index"
       },
       {
@@ -3898,7 +3858,9 @@ Gen4 plan same as above
         "FieldQuery": "select `user`.id from `user` where 1 != 1",
         "Query": "select `user`.id from `user` where `user`.id = :user_extra_assembly_id",
         "Table": "`user`",
-        "Values": ":user_extra_assembly_id",
+        "Values": [
+          ":user_extra_assembly_id"
+        ],
         "Vindex": "user_index"
       }
     ]
@@ -4040,7 +4002,9 @@ Gen4 plan same as above
         "FieldQuery": "select 1 from music as m where 1 != 1",
         "Query": "select 1 from music as m where m.user_id = :ue_user_id",
         "Table": "music",
-        "Values": ":ue_user_id",
+        "Values": [
+          ":ue_user_id"
+        ],
         "Vindex": "user_index"
       }
     ]
@@ -4080,7 +4044,9 @@ Gen4 plan same as above
         "FieldQuery": "select 1 from `user` as u where 1 != 1",
         "Query": "select 1 from `user` as u where u.id = :ue_id",
         "Table": "`user`",
-        "Values": ":ue_id",
+        "Values": [
+          ":ue_id"
+        ],
         "Vindex": "user_index"
       }
     ]
@@ -4160,7 +4126,9 @@ Gen4 plan same as above
         "FieldQuery": "select u.id as uid from `user` as u where 1 != 1",
         "Query": "select u.id as uid from `user` as u where u.id = :ue_id",
         "Table": "`user`",
-        "Values": ":ue_id",
+        "Values": [
+          ":ue_id"
+        ],
         "Vindex": "user_index"
       }
     ]
@@ -4277,7 +4245,9 @@ Gen4 plan same as above
             "FieldQuery": "select `user`.id, `user`.col from `user` where 1 != 1",
             "Query": "select `user`.id, `user`.col from `user` where `user`.id = 5",
             "Table": "`user`",
-            "Values": "INT64(5)",
+            "Values": [
+              5
+            ],
             "Vindex": "user_index"
           },
           {
@@ -4359,7 +4329,9 @@ Gen4 plan same as above
     "FieldQuery": "select u.a from (select id as b, `name` from `user` where 1 != 1) as u(a, n) where 1 != 1",
     "Query": "select u.a from (select id as b, `name` from `user` where `name` = 1) as u(a, n)",
     "Table": "`user`",
-    "Values": "INT64(1)",
+    "Values": [
+      1
+    ],
     "Vindex": "name_user_map"
   }
 }
@@ -4380,7 +4352,9 @@ Gen4 plan same as above
     "FieldQuery": "select u.a from (select id as b, `name` from `user` where 1 != 1) as u(a, n) where 1 != 1",
     "Query": "select u.a from (select id as b, `name` from `user` where b = 1 and `name` = 1) as u(a, n)",
     "Table": "`user`",
-    "Values": "INT64(1)",
+    "Values": [
+      1
+    ],
     "Vindex": "name_user_map"
   }
 }
@@ -4490,7 +4464,9 @@ Gen4 plan same as above
             "FieldQuery": "select id from `user` where 1 != 1",
             "Query": "select id from `user` where col = :__sq1 and :__sq_has_values2 = 1 and id in ::__vals",
             "Table": "`user`",
-            "Values": "::__sq2",
+            "Values": [
+              "::__sq2"
+            ],
             "Vindex": "user_index"
           }
         ]
@@ -4555,7 +4531,9 @@ Gen4 plan same as above
             "FieldQuery": "select id from `user` where 1 != 1",
             "Query": "select id from `user` where :__sq_has_values1 = 1 and id in ::__vals and col = :__sq2",
             "Table": "`user`",
-            "Values": ":__sq1",
+            "Values": [
+              "::__sq1"
+            ],
             "Vindex": "user_index"
           }
         ]
diff --git a/go/vt/vtgate/planbuilder/testdata/large_cases.txt b/go/vt/vtgate/planbuilder/testdata/large_cases.txt
index b5c8be8d96..1a3974a70a 100644
--- a/go/vt/vtgate/planbuilder/testdata/large_cases.txt
+++ b/go/vt/vtgate/planbuilder/testdata/large_cases.txt
@@ -40,7 +40,9 @@
             "FieldQuery": "select user_extra.user_id from user_extra where 1 != 1",
             "Query": "select user_extra.user_id from user_extra where user_extra.user_id = :user_id",
             "Table": "user_extra",
-            "Values": ":user_id",
+            "Values": [
+              ":user_id"
+            ],
             "Vindex": "user_index"
           },
           {
@@ -58,7 +60,9 @@
                 "FieldQuery": "select 1 from user_metadata where 1 != 1",
                 "Query": "select 1 from user_metadata where user_metadata.user_id = :user_extra_user_id",
                 "Table": "user_metadata",
-                "Values": ":user_extra_user_id",
+                "Values": [
+                  ":user_extra_user_id"
+                ],
                 "Vindex": "user_index"
               },
               {
@@ -157,7 +161,9 @@
                                     "FieldQuery": "select 1 from music_extra where 1 != 1",
                                     "Query": "select 1 from music_extra where music_extra.music_id = :music_id",
                                     "Table": "music_extra",
-                                    "Values": ":music_id",
+                                    "Values": [
+                                      ":music_id"
+                                    ],
                                     "Vindex": "music_user_map"
                                   }
                                 ]
diff --git a/go/vt/vtgate/planbuilder/testdata/memory_sort_cases.txt b/go/vt/vtgate/planbuilder/testdata/memory_sort_cases.txt
index 07469024e3..62ab68ab6b 100644
--- a/go/vt/vtgate/planbuilder/testdata/memory_sort_cases.txt
+++ b/go/vt/vtgate/planbuilder/testdata/memory_sort_cases.txt
@@ -395,7 +395,9 @@ Gen4 error: Expression of SELECT list is not in GROUP BY clause and contains non
             "FieldQuery": "select `user`.col1 as a, `user`.col2 as b, `user`.id from `user` where 1 != 1",
             "Query": "select `user`.col1 as a, `user`.col2 as b, `user`.id from `user` where `user`.id = 1",
             "Table": "`user`",
-            "Values": 1,
+            "Values": [
+              1
+            ],
             "Vindex": "user_index"
           },
           {
@@ -408,7 +410,9 @@ Gen4 error: Expression of SELECT list is not in GROUP BY clause and contains non
             "FieldQuery": "select music.col3 as c, weight_string(music.col3) from music where 1 != 1",
             "Query": "select music.col3 as c, weight_string(music.col3) from music where music.id = :user_id",
             "Table": "music",
-            "Values": ":user_id",
+            "Values": [
+              ":user_id"
+            ],
             "Vindex": "music_user_map"
           }
         ]
@@ -445,7 +449,9 @@ Gen4 error: Expression of SELECT list is not in GROUP BY clause and contains non
             "FieldQuery": "select `user`.id, `user`.col1 as a, `user`.col2 as b from `user` where 1 != 1",
             "Query": "select `user`.id, `user`.col1 as a, `user`.col2 as b from `user` where `user`.id = 1",
             "Table": "`user`",
-            "Values": "INT64(1)",
+            "Values": [
+              1
+            ],
             "Vindex": "user_index"
           },
           {
@@ -458,7 +464,9 @@ Gen4 error: Expression of SELECT list is not in GROUP BY clause and contains non
             "FieldQuery": "select music.col3 as c, weight_string(music.col3) from music where 1 != 1",
             "Query": "select music.col3 as c, weight_string(music.col3) from music where music.id = :user_id",
             "Table": "music",
-            "Values": ":user_id",
+            "Values": [
+              ":user_id"
+            ],
             "Vindex": "music_user_map"
           }
         ]
@@ -497,7 +505,9 @@ Gen4 error: Expression of SELECT list is not in GROUP BY clause and contains non
             "FieldQuery": "select `user`.col1 as a, `user`.col2, weight_string(`user`.col1), weight_string(`user`.col2), `user`.id from `user` where 1 != 1",
             "Query": "select `user`.col1 as a, `user`.col2, weight_string(`user`.col1), weight_string(`user`.col2), `user`.id from `user` where `user`.id = 1",
             "Table": "`user`",
-            "Values": 1,
+            "Values": [
+              1
+            ],
             "Vindex": "user_index"
           },
           {
@@ -510,7 +520,9 @@ Gen4 error: Expression of SELECT list is not in GROUP BY clause and contains non
             "FieldQuery": "select music.col3, weight_string(music.col3) from music where 1 != 1",
             "Query": "select music.col3, weight_string(music.col3) from music where music.id = :user_id",
             "Table": "music",
-            "Values": ":user_id",
+            "Values": [
+              ":user_id"
+            ],
             "Vindex": "music_user_map"
           }
         ]
@@ -547,7 +559,9 @@ Gen4 error: Expression of SELECT list is not in GROUP BY clause and contains non
             "FieldQuery": "select `user`.id, `user`.col1 as a, `user`.col2, weight_string(`user`.col1), weight_string(`user`.col2) from `user` where 1 != 1",
             "Query": "select `user`.id, `user`.col1 as a, `user`.col2, weight_string(`user`.col1), weight_string(`user`.col2) from `user` where `user`.id = 1",
             "Table": "`user`",
-            "Values": "INT64(1)",
+            "Values": [
+              1
+            ],
             "Vindex": "user_index"
           },
           {
@@ -560,7 +574,9 @@ Gen4 error: Expression of SELECT list is not in GROUP BY clause and contains non
             "FieldQuery": "select music.col3, weight_string(music.col3) from music where 1 != 1",
             "Query": "select music.col3, weight_string(music.col3) from music where music.id = :user_id",
             "Table": "music",
-            "Values": ":user_id",
+            "Values": [
+              ":user_id"
+            ],
             "Vindex": "music_user_map"
           }
         ]
diff --git a/go/vt/vtgate/planbuilder/testdata/oltp_cases.txt b/go/vt/vtgate/planbuilder/testdata/oltp_cases.txt
index 7510afbd53..97d31bdbb1 100644
--- a/go/vt/vtgate/planbuilder/testdata/oltp_cases.txt
+++ b/go/vt/vtgate/planbuilder/testdata/oltp_cases.txt
@@ -13,27 +13,13 @@
     "FieldQuery": "select c from sbtest34 where 1 != 1",
     "Query": "select c from sbtest34 where id = 15",
     "Table": "sbtest34",
-    "Values": 15,
-    "Vindex": "hash"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "SELECT c FROM sbtest34 WHERE id=15",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "main",
-      "Sharded": true
-    },
-    "FieldQuery": "select c from sbtest34 where 1 != 1",
-    "Query": "select c from sbtest34 where id = 15",
-    "Table": "sbtest34",
-    "Values": "INT64(15)",
+    "Values": [
+      15
+    ],
     "Vindex": "hash"
   }
 }
+Gen4 plan same as above
 
 # OLTP simple range select
 "SELECT c FROM sbtest12 WHERE id BETWEEN 1 AND 10"
diff --git a/go/vt/vtgate/planbuilder/testdata/postprocess_cases.txt b/go/vt/vtgate/planbuilder/testdata/postprocess_cases.txt
index 056734427f..4746738016 100644
--- a/go/vt/vtgate/planbuilder/testdata/postprocess_cases.txt
+++ b/go/vt/vtgate/planbuilder/testdata/postprocess_cases.txt
@@ -213,7 +213,9 @@ Gen4 error: Column 'col1' in field list is ambiguous
         "FieldQuery": "select id from `user` where 1 != 1",
         "Query": "select id from `user` having :__sq_has_values1 = 1 and id in ::__vals",
         "Table": "`user`",
-        "Values": "::__sq1",
+        "Values": [
+          "::__sq1"
+        ],
         "Vindex": "user_index"
       }
     ]
@@ -251,7 +253,9 @@ Gen4 error: Column 'col1' in field list is ambiguous
         "FieldQuery": "select id from `user` where 1 != 1",
         "Query": "select id from `user` where :__sq_has_values1 = 1 and id in ::__vals",
         "Table": "`user`",
-        "Values": ":__sq1",
+        "Values": [
+          "::__sq1"
+        ],
         "Vindex": "user_index"
       }
     ]
@@ -273,27 +277,13 @@ Gen4 error: Column 'col1' in field list is ambiguous
     "FieldQuery": "select col from `user` where 1 != 1",
     "Query": "select col from `user` where id = 5 order by aa asc",
     "Table": "`user`",
-    "Values": 5,
-    "Vindex": "user_index"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select col from user where id = 5 order by aa",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select col from `user` where 1 != 1",
-    "Query": "select col from `user` where id = 5 order by aa asc",
-    "Table": "`user`",
-    "Values": "INT64(5)",
+    "Values": [
+      5
+    ],
     "Vindex": "user_index"
   }
 }
+Gen4 plan same as above
 
 # ORDER BY uses column numbers
 "select col from user where id = 1 order by 1"
@@ -310,7 +300,9 @@ Gen4 error: Column 'col1' in field list is ambiguous
     "FieldQuery": "select col from `user` where 1 != 1",
     "Query": "select col from `user` where id = 1 order by 1 asc",
     "Table": "`user`",
-    "Values": 1,
+    "Values": [
+      1
+    ],
     "Vindex": "user_index"
   }
 }
@@ -327,7 +319,9 @@ Gen4 error: Column 'col1' in field list is ambiguous
     "FieldQuery": "select col from `user` where 1 != 1",
     "Query": "select col from `user` where id = 1 order by col asc",
     "Table": "`user`",
-    "Values": "INT64(1)",
+    "Values": [
+      1
+    ],
     "Vindex": "user_index"
   }
 }
@@ -667,7 +661,9 @@ Gen4 plan same as above
         "FieldQuery": "select `user`.col1 as a, `user`.col2, `user`.id from `user` where 1 != 1",
         "Query": "select `user`.col1 as a, `user`.col2, `user`.id from `user` where `user`.id = 1 order by null",
         "Table": "`user`",
-        "Values": 1,
+        "Values": [
+          1
+        ],
         "Vindex": "user_index"
       },
       {
@@ -680,7 +676,9 @@ Gen4 plan same as above
         "FieldQuery": "select music.col3 from music where 1 != 1",
         "Query": "select music.col3 from music where music.id = :user_id order by null",
         "Table": "music",
-        "Values": ":user_id",
+        "Values": [
+          ":user_id"
+        ],
         "Vindex": "music_user_map"
       }
     ]
@@ -709,7 +707,9 @@ Gen4 plan same as above
         "FieldQuery": "select `user`.id, `user`.col1 as a, `user`.col2 from `user` where 1 != 1",
         "Query": "select `user`.id, `user`.col1 as a, `user`.col2 from `user` where `user`.id = 1 order by null",
         "Table": "`user`",
-        "Values": "INT64(1)",
+        "Values": [
+          1
+        ],
         "Vindex": "user_index"
       },
       {
@@ -722,7 +722,9 @@ Gen4 plan same as above
         "FieldQuery": "select music.col3 from music where 1 != 1",
         "Query": "select music.col3 from music where music.id = :user_id order by null",
         "Table": "music",
-        "Values": ":user_id",
+        "Values": [
+          ":user_id"
+        ],
         "Vindex": "music_user_map"
       }
     ]
@@ -753,7 +755,9 @@ Gen4 plan same as above
         "FieldQuery": "select `user`.col1 as a, `user`.col2, `user`.id from `user` where 1 != 1",
         "Query": "select `user`.col1 as a, `user`.col2, `user`.id from `user` where `user`.id = 1 order by a asc",
         "Table": "`user`",
-        "Values": 1,
+        "Values": [
+          1
+        ],
         "Vindex": "user_index"
       },
       {
@@ -766,7 +770,9 @@ Gen4 plan same as above
         "FieldQuery": "select music.col3 from music where 1 != 1",
         "Query": "select music.col3 from music where music.id = :user_id",
         "Table": "music",
-        "Values": ":user_id",
+        "Values": [
+          ":user_id"
+        ],
         "Vindex": "music_user_map"
       }
     ]
@@ -796,7 +802,9 @@ Gen4 plan same as above
         "OrderBy": "(1|3) ASC",
         "Query": "select `user`.id, `user`.col1 as a, `user`.col2, weight_string(`user`.col1) from `user` where `user`.id = 1 order by a asc",
         "Table": "`user`",
-        "Values": "INT64(1)",
+        "Values": [
+          1
+        ],
         "Vindex": "user_index"
       },
       {
@@ -809,7 +817,9 @@ Gen4 plan same as above
         "FieldQuery": "select music.col3 from music where 1 != 1",
         "Query": "select music.col3 from music where music.id = :user_id",
         "Table": "music",
-        "Values": ":user_id",
+        "Values": [
+          ":user_id"
+        ],
         "Vindex": "music_user_map"
       }
     ]
@@ -840,7 +850,9 @@ Gen4 plan same as above
         "FieldQuery": "select `user`.col1 as a, `user`.col2, `user`.id from `user` where 1 != 1",
         "Query": "select `user`.col1 as a, `user`.col2, `user`.id from `user` where `user`.id = 1 order by a asc",
         "Table": "`user`",
-        "Values": 1,
+        "Values": [
+          1
+        ],
         "Vindex": "user_index"
       },
       {
@@ -853,7 +865,9 @@ Gen4 plan same as above
         "FieldQuery": "select music.col3 from music where 1 != 1",
         "Query": "select music.col3 from music where music.id = :user_id",
         "Table": "music",
-        "Values": ":user_id",
+        "Values": [
+          ":user_id"
+        ],
         "Vindex": "music_user_map"
       }
     ]
@@ -883,7 +897,9 @@ Gen4 plan same as above
         "OrderBy": "(1|3) ASC",
         "Query": "select `user`.id, `user`.col1 as a, `user`.col2, weight_string(`user`.col1) from `user` where `user`.id = 1 order by a asc",
         "Table": "`user`",
-        "Values": "INT64(1)",
+        "Values": [
+          1
+        ],
         "Vindex": "user_index"
       },
       {
@@ -896,7 +912,9 @@ Gen4 plan same as above
         "FieldQuery": "select music.col3 from music where 1 != 1",
         "Query": "select music.col3 from music where music.id = :user_id",
         "Table": "music",
-        "Values": ":user_id",
+        "Values": [
+          ":user_id"
+        ],
         "Vindex": "music_user_map"
       }
     ]
@@ -986,7 +1004,9 @@ Gen4 plan same as above
         "FieldQuery": "select `user`.col1 as a, `user`.col2, `user`.id from `user` where 1 != 1",
         "Query": "select `user`.col1 as a, `user`.col2, `user`.id from `user` where `user`.id = 1 order by RAND()",
         "Table": "`user`",
-        "Values": 1,
+        "Values": [
+          1
+        ],
         "Vindex": "user_index"
       },
       {
@@ -999,7 +1019,9 @@ Gen4 plan same as above
         "FieldQuery": "select music.col3 from music where 1 != 1",
         "Query": "select music.col3 from music where music.id = :user_id order by RAND()",
         "Table": "music",
-        "Values": ":user_id",
+        "Values": [
+          ":user_id"
+        ],
         "Vindex": "music_user_map"
       }
     ]
@@ -1028,7 +1050,9 @@ Gen4 plan same as above
         "FieldQuery": "select `user`.id, `user`.col1 as a, `user`.col2 from `user` where 1 != 1",
         "Query": "select `user`.id, `user`.col1 as a, `user`.col2 from `user` where `user`.id = 1 order by RAND()",
         "Table": "`user`",
-        "Values": "INT64(1)",
+        "Values": [
+          1
+        ],
         "Vindex": "user_index"
       },
       {
@@ -1041,7 +1065,9 @@ Gen4 plan same as above
         "FieldQuery": "select music.col3 from music where 1 != 1",
         "Query": "select music.col3 from music where music.id = :user_id order by RAND()",
         "Table": "music",
-        "Values": ":user_id",
+        "Values": [
+          ":user_id"
+        ],
         "Vindex": "music_user_map"
       }
     ]
@@ -1103,27 +1129,13 @@ Gen4 plan same as above
     "FieldQuery": "select * from `user` where 1 != 1",
     "Query": "select * from `user` where id = 5 order by col asc",
     "Table": "`user`",
-    "Values": 5,
-    "Vindex": "user_index"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select * from user where id = 5 order by col",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select * from `user` where 1 != 1",
-    "Query": "select * from `user` where id = 5 order by col asc",
-    "Table": "`user`",
-    "Values": "INT64(5)",
+    "Values": [
+      5
+    ],
     "Vindex": "user_index"
   }
 }
+Gen4 plan same as above
 
 # Order by, qualified '*' expression
 "select user.* from user where id = 5 order by user.col"
@@ -1140,27 +1152,13 @@ Gen4 plan same as above
     "FieldQuery": "select `user`.* from `user` where 1 != 1",
     "Query": "select `user`.* from `user` where id = 5 order by `user`.col asc",
     "Table": "`user`",
-    "Values": 5,
-    "Vindex": "user_index"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select user.* from user where id = 5 order by user.col",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select `user`.* from `user` where 1 != 1",
-    "Query": "select `user`.* from `user` where id = 5 order by `user`.col asc",
-    "Table": "`user`",
-    "Values": "INT64(5)",
+    "Values": [
+      5
+    ],
     "Vindex": "user_index"
   }
 }
+Gen4 plan same as above
 
 # Order by, '*' expression with qualified reference
 "select * from user where id = 5 order by user.col"
@@ -1177,27 +1175,13 @@ Gen4 plan same as above
     "FieldQuery": "select * from `user` where 1 != 1",
     "Query": "select * from `user` where id = 5 order by `user`.col asc",
     "Table": "`user`",
-    "Values": 5,
-    "Vindex": "user_index"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select * from user where id = 5 order by user.col",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select * from `user` where 1 != 1",
-    "Query": "select * from `user` where id = 5 order by `user`.col asc",
-    "Table": "`user`",
-    "Values": "INT64(5)",
+    "Values": [
+      5
+    ],
     "Vindex": "user_index"
   }
 }
+Gen4 plan same as above
 
 # Order by, '*' expression in a subquery
 "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)"
@@ -1326,27 +1310,13 @@ Gen4 plan same as above
     "FieldQuery": "select * from `user` where 1 != 1",
     "Query": "select * from `user` where id = 5 order by `user`.col collate utf8_general_ci asc",
     "Table": "`user`",
-    "Values": 5,
-    "Vindex": "user_index"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select * from user where id = 5 order by user.col collate utf8_general_ci",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select * from `user` where 1 != 1",
-    "Query": "select * from `user` where id = 5 order by `user`.col collate utf8_general_ci asc",
-    "Table": "`user`",
-    "Values": "INT64(5)",
+    "Values": [
+      5
+    ],
     "Vindex": "user_index"
   }
 }
+Gen4 plan same as above
 
 #Order by with math functions
 "select * from user where id = 5 order by -col1"
@@ -1363,27 +1333,13 @@ Gen4 plan same as above
     "FieldQuery": "select * from `user` where 1 != 1",
     "Query": "select * from `user` where id = 5 order by -col1 asc",
     "Table": "`user`",
-    "Values": 5,
-    "Vindex": "user_index"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select * from user where id = 5 order by -col1",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select * from `user` where 1 != 1",
-    "Query": "select * from `user` where id = 5 order by -col1 asc",
-    "Table": "`user`",
-    "Values": "INT64(5)",
+    "Values": [
+      5
+    ],
     "Vindex": "user_index"
   }
 }
+Gen4 plan same as above
 
 #Order by with string operations
 "select * from user where id = 5 order by concat(col,col1) collate utf8_general_ci desc"
@@ -1400,27 +1356,13 @@ Gen4 plan same as above
     "FieldQuery": "select * from `user` where 1 != 1",
     "Query": "select * from `user` where id = 5 order by concat(col, col1) collate utf8_general_ci desc",
     "Table": "`user`",
-    "Values": 5,
-    "Vindex": "user_index"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select * from user where id = 5 order by concat(col,col1) collate utf8_general_ci desc",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select * from `user` where 1 != 1",
-    "Query": "select * from `user` where id = 5 order by concat(col, col1) collate utf8_general_ci desc",
-    "Table": "`user`",
-    "Values": "INT64(5)",
+    "Values": [
+      5
+    ],
     "Vindex": "user_index"
   }
 }
+Gen4 plan same as above
 
 #Order by with math operations
 "select * from user where id = 5 order by id+col collate utf8_general_ci desc"
@@ -1437,27 +1379,13 @@ Gen4 plan same as above
     "FieldQuery": "select * from `user` where 1 != 1",
     "Query": "select * from `user` where id = 5 order by id + col collate utf8_general_ci desc",
     "Table": "`user`",
-    "Values": 5,
-    "Vindex": "user_index"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select * from user where id = 5 order by id+col collate utf8_general_ci desc",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select * from `user` where 1 != 1",
-    "Query": "select * from `user` where id = 5 order by id + col collate utf8_general_ci desc",
-    "Table": "`user`",
-    "Values": "INT64(5)",
+    "Values": [
+      5
+    ],
     "Vindex": "user_index"
   }
 }
+Gen4 plan same as above
 
 #Order by derived table column
 "select * from user u join (select user_id from user_extra where user_id = 5) eu on u.id = eu.user_id where u.id = 5 order by eu.user_id"
@@ -1474,7 +1402,9 @@ Gen4 plan same as above
     "FieldQuery": "select * from `user` as u join (select user_id from user_extra where 1 != 1) as eu on u.id = eu.user_id where 1 != 1",
     "Query": "select * from `user` as u join (select user_id from user_extra where user_id = 5) as eu on u.id = eu.user_id where u.id = 5 order by eu.user_id asc",
     "Table": "`user`, user_extra",
-    "Values": 5,
+    "Values": [
+      5
+    ],
     "Vindex": "user_index"
   }
 }
@@ -1491,7 +1421,9 @@ Gen4 plan same as above
     "FieldQuery": "select * from `user` as u, (select user_id from user_extra where 1 != 1) as eu where 1 != 1",
     "Query": "select * from `user` as u, (select user_id from user_extra where user_id = 5) as eu where u.id = 5 and u.id = eu.user_id order by eu.user_id asc",
     "Table": "`user`, user_extra",
-    "Values": "INT64(5)",
+    "Values": [
+      5
+    ],
     "Vindex": "user_index"
   }
 }
@@ -1511,27 +1443,13 @@ Gen4 plan same as above
     "FieldQuery": "select col from `user` as route1 where 1 != 1",
     "Query": "select col from `user` as route1 where id = 1 order by col asc",
     "Table": "`user`",
-    "Values": 1,
-    "Vindex": "user_index"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select col from route1 where id = 1 order by col",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select col from `user` as route1 where 1 != 1",
-    "Query": "select col from `user` as route1 where id = 1 order by col asc",
-    "Table": "`user`",
-    "Values": "INT64(1)",
+    "Values": [
+      1
+    ],
     "Vindex": "user_index"
   }
 }
+Gen4 plan same as above
 
 # LIMIT
 "select col1 from user where id = 1 limit 1"
@@ -1548,27 +1466,13 @@ Gen4 plan same as above
     "FieldQuery": "select col1 from `user` where 1 != 1",
     "Query": "select col1 from `user` where id = 1 limit 1",
     "Table": "`user`",
-    "Values": 1,
-    "Vindex": "user_index"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select col1 from user where id = 1 limit 1",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select col1 from `user` where 1 != 1",
-    "Query": "select col1 from `user` where id = 1 limit 1",
-    "Table": "`user`",
-    "Values": "INT64(1)",
+    "Values": [
+      1
+    ],
     "Vindex": "user_index"
   }
 }
+Gen4 plan same as above
 
 # limit for joins. Can't push down the limit because result
 # counts get multiplied by join operations.
diff --git a/go/vt/vtgate/planbuilder/testdata/rails_cases.txt b/go/vt/vtgate/planbuilder/testdata/rails_cases.txt
index 2704be90ef..6414bca70b 100644
--- a/go/vt/vtgate/planbuilder/testdata/rails_cases.txt
+++ b/go/vt/vtgate/planbuilder/testdata/rails_cases.txt
@@ -60,7 +60,9 @@
                     "FieldQuery": "select book6s_order2s.order2_id from book6s_order2s where 1 != 1",
                     "Query": "select book6s_order2s.order2_id from book6s_order2s where book6s_order2s.book6_id = :book6s_id",
                     "Table": "book6s_order2s",
-                    "Values": ":book6s_id",
+                    "Values": [
+                      ":book6s_id"
+                    ],
                     "Vindex": "binary_md5"
                   }
                 ]
@@ -88,7 +90,9 @@
             "FieldQuery": "select 1 from customer2s where 1 != 1",
             "Query": "select 1 from customer2s where customer2s.id = :order2s_customer2_id",
             "Table": "customer2s",
-            "Values": ":order2s_customer2_id",
+            "Values": [
+              ":order2s_customer2_id"
+            ],
             "Vindex": "binary_md5"
           }
         ]
@@ -103,7 +107,9 @@
         "FieldQuery": "select 1 from supplier5s where 1 != 1",
         "Query": "select 1 from supplier5s where supplier5s.id = :book6s_supplier5_id",
         "Table": "supplier5s",
-        "Values": ":book6s_supplier5_id",
+        "Values": [
+          ":book6s_supplier5_id"
+        ],
         "Vindex": "binary_md5"
       }
     ]
@@ -174,7 +180,9 @@
                 "FieldQuery": "select 1 from book6s_order2s where 1 != 1",
                 "Query": "select 1 from book6s_order2s where book6s_order2s.book6_id = :book6s_id and book6s_order2s.order2_id = :order2s_id",
                 "Table": "book6s_order2s",
-                "Values": ":book6s_id",
+                "Values": [
+                  ":book6s_id"
+                ],
                 "Vindex": "binary_md5"
               }
             ]
@@ -189,7 +197,9 @@
             "FieldQuery": "select 1 from supplier5s where 1 != 1",
             "Query": "select 1 from supplier5s where supplier5s.id = :book6s_supplier5_id",
             "Table": "supplier5s",
-            "Values": ":book6s_supplier5_id",
+            "Values": [
+              ":book6s_supplier5_id"
+            ],
             "Vindex": "binary_md5"
           }
         ]
@@ -260,7 +270,9 @@
                     "FieldQuery": "select book6s_order2s.order2_id from book6s_order2s where 1 != 1",
                     "Query": "select /*vt+ ALLOW_HASH_JOIN */ book6s_order2s.order2_id from book6s_order2s where book6s_order2s.book6_id = :book6s_id",
                     "Table": "book6s_order2s",
-                    "Values": ":book6s_id",
+                    "Values": [
+                      ":book6s_id"
+                    ],
                     "Vindex": "binary_md5"
                   }
                 ]
@@ -288,7 +300,9 @@
             "FieldQuery": "select 1 from customer2s where 1 != 1",
             "Query": "select /*vt+ ALLOW_HASH_JOIN */ 1 from customer2s where customer2s.id = :order2s_customer2_id",
             "Table": "customer2s",
-            "Values": ":order2s_customer2_id",
+            "Values": [
+              ":order2s_customer2_id"
+            ],
             "Vindex": "binary_md5"
           }
         ]
@@ -303,7 +317,9 @@
         "FieldQuery": "select 1 from supplier5s where 1 != 1",
         "Query": "select /*vt+ ALLOW_HASH_JOIN */ 1 from supplier5s where supplier5s.id = :book6s_supplier5_id",
         "Table": "supplier5s",
-        "Values": ":book6s_supplier5_id",
+        "Values": [
+          ":book6s_supplier5_id"
+        ],
         "Vindex": "binary_md5"
       }
     ]
@@ -370,7 +386,9 @@
                 "FieldQuery": "select book6s_order2s.order2_id from book6s_order2s where 1 != 1",
                 "Query": "select /*vt+ ALLOW_HASH_JOIN */ book6s_order2s.order2_id from book6s_order2s where book6s_order2s.book6_id = :book6s_id",
                 "Table": "book6s_order2s",
-                "Values": ":book6s_id",
+                "Values": [
+                  ":book6s_id"
+                ],
                 "Vindex": "binary_md5"
               }
             ]
diff --git a/go/vt/vtgate/planbuilder/testdata/select_cases.txt b/go/vt/vtgate/planbuilder/testdata/select_cases.txt
index e3884db648..11c8c74225 100644
--- a/go/vt/vtgate/planbuilder/testdata/select_cases.txt
+++ b/go/vt/vtgate/planbuilder/testdata/select_cases.txt
@@ -625,27 +625,13 @@ Gen4 plan same as above
     "FieldQuery": "select * from pin_test where 1 != 1",
     "Query": "select * from pin_test",
     "Table": "pin_test",
-    "Values": "\ufffd",
-    "Vindex": "binary"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select * from pin_test",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select * from pin_test where 1 != 1",
-    "Query": "select * from pin_test",
-    "Table": "pin_test",
-    "Values": "VARBINARY(\"\\x80\")",
+    "Values": [
+      "\ufffd"
+    ],
     "Vindex": "binary"
   }
 }
+Gen4 plan same as above
 
 # select from dual on sharded keyspace
 "select @@session.auto_increment_increment from user.dual"
@@ -1040,27 +1026,13 @@ Gen4 plan same as above
     "FieldQuery": "select * from `user` where 1 != 1",
     "Query": "select * from `user` where `name` = 'abc' and id = 4 limit 5",
     "Table": "`user`",
-    "Values": 4,
-    "Vindex": "user_index"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select * from user where name ='abc' AND (id = 4) limit 5",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select * from `user` where 1 != 1",
-    "Query": "select * from `user` where `name` = 'abc' and id = 4 limit 5",
-    "Table": "`user`",
-    "Values": "INT64(4)",
+    "Values": [
+      4
+    ],
     "Vindex": "user_index"
   }
 }
+Gen4 plan same as above
 
 # Multiple parenthesized expressions
 "select * from user where (id = 4) AND (name ='abc') limit 5"
@@ -1077,27 +1049,13 @@ Gen4 plan same as above
     "FieldQuery": "select * from `user` where 1 != 1",
     "Query": "select * from `user` where id = 4 and `name` = 'abc' limit 5",
     "Table": "`user`",
-    "Values": 4,
-    "Vindex": "user_index"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select * from user where (id = 4) AND (name ='abc') limit 5",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select * from `user` where 1 != 1",
-    "Query": "select * from `user` where id = 4 and `name` = 'abc' limit 5",
-    "Table": "`user`",
-    "Values": "INT64(4)",
+    "Values": [
+      4
+    ],
     "Vindex": "user_index"
   }
 }
+Gen4 plan same as above
 
 # Multiple parenthesized expressions
 "select * from user where (id = 4 and name ='abc') limit 5"
@@ -1114,27 +1072,13 @@ Gen4 plan same as above
     "FieldQuery": "select * from `user` where 1 != 1",
     "Query": "select * from `user` where id = 4 and `name` = 'abc' limit 5",
     "Table": "`user`",
-    "Values": 4,
-    "Vindex": "user_index"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select * from user where (id = 4 and name ='abc') limit 5",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select * from `user` where 1 != 1",
-    "Query": "select * from `user` where id = 4 and `name` = 'abc' limit 5",
-    "Table": "`user`",
-    "Values": "INT64(4)",
+    "Values": [
+      4
+    ],
     "Vindex": "user_index"
   }
 }
+Gen4 plan same as above
 
 # Column Aliasing with Table.Column
 "select user0_.col as col0_ from user user0_ where id = 1 order by user0_.col desc limit 2"
@@ -1151,27 +1095,13 @@ Gen4 plan same as above
     "FieldQuery": "select user0_.col as col0_ from `user` as user0_ where 1 != 1",
     "Query": "select user0_.col as col0_ from `user` as user0_ where id = 1 order by user0_.col desc limit 2",
     "Table": "`user`",
-    "Values": 1,
-    "Vindex": "user_index"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select user0_.col as col0_ from user user0_ where id = 1 order by user0_.col desc limit 2",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select user0_.col as col0_ from `user` as user0_ where 1 != 1",
-    "Query": "select user0_.col as col0_ from `user` as user0_ where id = 1 order by user0_.col desc limit 2",
-    "Table": "`user`",
-    "Values": "INT64(1)",
+    "Values": [
+      1
+    ],
     "Vindex": "user_index"
   }
 }
+Gen4 plan same as above
 
 # Column Aliasing with Column
 "select user0_.col as col0_ from user user0_ where id = 1 order by col0_ desc limit 3"
@@ -1188,27 +1118,13 @@ Gen4 plan same as above
     "FieldQuery": "select user0_.col as col0_ from `user` as user0_ where 1 != 1",
     "Query": "select user0_.col as col0_ from `user` as user0_ where id = 1 order by col0_ desc limit 3",
     "Table": "`user`",
-    "Values": 1,
-    "Vindex": "user_index"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select user0_.col as col0_ from user user0_ where id = 1 order by col0_ desc limit 3",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select user0_.col as col0_ from `user` as user0_ where 1 != 1",
-    "Query": "select user0_.col as col0_ from `user` as user0_ where id = 1 order by col0_ desc limit 3",
-    "Table": "`user`",
-    "Values": "INT64(1)",
+    "Values": [
+      1
+    ],
     "Vindex": "user_index"
   }
 }
+Gen4 plan same as above
 
 # Booleans and parenthesis
 "select * from user where (id = 1) AND name = true limit 5"
@@ -1225,27 +1141,13 @@ Gen4 plan same as above
     "FieldQuery": "select * from `user` where 1 != 1",
     "Query": "select * from `user` where id = 1 and `name` = true limit 5",
     "Table": "`user`",
-    "Values": 1,
-    "Vindex": "user_index"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select * from user where (id = 1) AND name = true limit 5",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select * from `user` where 1 != 1",
-    "Query": "select * from `user` where id = 1 and `name` = true limit 5",
-    "Table": "`user`",
-    "Values": "INT64(1)",
+    "Values": [
+      1
+    ],
     "Vindex": "user_index"
   }
 }
+Gen4 plan same as above
 
 # Column as boolean-ish
 "select * from user where (id = 1) AND name limit 5"
@@ -1262,27 +1164,13 @@ Gen4 plan same as above
     "FieldQuery": "select * from `user` where 1 != 1",
     "Query": "select * from `user` where id = 1 and `name` limit 5",
     "Table": "`user`",
-    "Values": 1,
-    "Vindex": "user_index"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select * from user where (id = 1) AND name limit 5",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select * from `user` where 1 != 1",
-    "Query": "select * from `user` where id = 1 and `name` limit 5",
-    "Table": "`user`",
-    "Values": "INT64(1)",
+    "Values": [
+      1
+    ],
     "Vindex": "user_index"
   }
 }
+Gen4 plan same as above
 
 # PK as fake boolean, and column as boolean-ish
 "select * from user where (id = 5) AND name = true limit 5"
@@ -1299,27 +1187,13 @@ Gen4 plan same as above
     "FieldQuery": "select * from `user` where 1 != 1",
     "Query": "select * from `user` where id = 5 and `name` = true limit 5",
     "Table": "`user`",
-    "Values": 5,
-    "Vindex": "user_index"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select * from user where (id = 5) AND name = true limit 5",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select * from `user` where 1 != 1",
-    "Query": "select * from `user` where id = 5 and `name` = true limit 5",
-    "Table": "`user`",
-    "Values": "INT64(5)",
+    "Values": [
+      5
+    ],
     "Vindex": "user_index"
   }
 }
+Gen4 plan same as above
 
 # top level subquery in select
 "select a, (select col from user) from unsharded"
@@ -1541,27 +1415,13 @@ Gen4 error: symbol t.col not found
     "FieldQuery": "select * from music where 1 != 1 union select * from `user` where 1 != 1",
     "Query": "select * from music where user_id = 1 union select * from `user` where id = 1",
     "Table": "music",
-    "Values": 1,
-    "Vindex": "user_index"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select * from music where user_id = 1 union select * from user where id = 1",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select * from music where 1 != 1 union select * from `user` where 1 != 1",
-    "Query": "select * from music where user_id = 1 union select * from `user` where id = 1",
-    "Table": "music",
-    "Values": "INT64(1)",
+    "Values": [
+      1
+    ],
     "Vindex": "user_index"
   }
 }
+Gen4 plan same as above
 
 # union with the same target shard last_insert_id
 "select *, last_insert_id() from music where user_id = 1 union select * from user where id = 1"
@@ -1578,27 +1438,13 @@ Gen4 error: symbol t.col not found
     "FieldQuery": "select *, :__lastInsertId as `last_insert_id()` from music where 1 != 1 union select * from `user` where 1 != 1",
     "Query": "select *, :__lastInsertId as `last_insert_id()` from music where user_id = 1 union select * from `user` where id = 1",
     "Table": "music",
-    "Values": 1,
-    "Vindex": "user_index"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select *, last_insert_id() from music where user_id = 1 union select * from user where id = 1",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select *, :__lastInsertId as `last_insert_id()` from music where 1 != 1 union select * from `user` where 1 != 1",
-    "Query": "select *, :__lastInsertId as `last_insert_id()` from music where user_id = 1 union select * from `user` where id = 1",
-    "Table": "music",
-    "Values": "INT64(1)",
+    "Values": [
+      1
+    ],
     "Vindex": "user_index"
   }
 }
+Gen4 plan same as above
 
 # unsharded union in derived table
 "select * from (select col1, col2 from unsharded where id = 1 union select col1, col2 from unsharded where id = 3) a"
@@ -1839,27 +1685,13 @@ Gen4 plan same as above
     "FieldQuery": "select * from music where 1 != 1",
     "Query": "select * from music where user_id = 1",
     "Table": "music",
-    "Values": 1,
-    "Vindex": "user_index"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select sql_calc_found_rows * from music where user_id = 1",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select * from music where 1 != 1",
-    "Query": "select * from music where user_id = 1",
-    "Table": "music",
-    "Values": "INT64(1)",
+    "Values": [
+      1
+    ],
     "Vindex": "user_index"
   }
 }
+Gen4 plan same as above
 
 # sql_calc_found_rows with limit
 "select sql_calc_found_rows * from music limit 100"
@@ -1970,42 +1802,9 @@ Gen4 plan same as above
         "FieldQuery": "select * from music where 1 != 1",
         "Query": "select * from music where user_id = 1 limit 2",
         "Table": "music",
-        "Values": 1,
-        "Vindex": "user_index"
-      },
-      {
-        "OperatorType": "Route",
-        "Variant": "SelectEqualUnique",
-        "Keyspace": {
-          "Name": "user",
-          "Sharded": true
-        },
-        "FieldQuery": "select count(*) from music where 1 != 1",
-        "Query": "select count(*) from music where user_id = 1",
-        "Table": "music",
-        "Values": 1,
-        "Vindex": "user_index"
-      }
-    ]
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select sql_calc_found_rows * from music where user_id = 1 limit 2",
-  "Instructions": {
-    "OperatorType": "SQL_CALC_FOUND_ROWS",
-    "Inputs": [
-      {
-        "OperatorType": "Route",
-        "Variant": "SelectEqualUnique",
-        "Keyspace": {
-          "Name": "user",
-          "Sharded": true
-        },
-        "FieldQuery": "select * from music where 1 != 1",
-        "Query": "select * from music where user_id = 1 limit 2",
-        "Table": "music",
-        "Values": "INT64(1)",
+        "Values": [
+          1
+        ],
         "Vindex": "user_index"
       },
       {
@@ -2018,12 +1817,15 @@ Gen4 plan same as above
         "FieldQuery": "select count(*) from music where 1 != 1",
         "Query": "select count(*) from music where user_id = 1",
         "Table": "music",
-        "Values": "INT64(1)",
+        "Values": [
+          1
+        ],
         "Vindex": "user_index"
       }
     ]
   }
 }
+Gen4 plan same as above
 
 # sql_calc_found_rows with group by and having
 "select sql_calc_found_rows user_id, count(id) from music group by user_id having count(user_id) = 1 order by user_id limit 2"
@@ -2150,10 +1952,10 @@ Gen4 plan same as above
 Gen4 plan same as above
 
 # select from unsharded keyspace into outfile
-"select * from main.unsharded into outfile 'x.txt' character set binary fields terminated by 'term' optionally enclosed by 'c' escaped by 'e' lines starting by 'a' terminated by '\n'"
+"select * from main.unsharded into outfile 'x.txt' character set binary fields terminated by 'term' optionally enclosed by 'c' escaped by 'e' lines starting by 'a' terminated by '\\n'"
 {
   "QueryType": "SELECT",
-  "Original": "select * from main.unsharded into outfile 'x.txt' character set binary fields terminated by 'term' optionally enclosed by 'c' escaped by 'e' lines starting by 'a' terminated by '\n'",
+  "Original": "select * from main.unsharded into outfile 'x.txt' character set binary fields terminated by 'term' optionally enclosed by 'c' escaped by 'e' lines starting by 'a' terminated by '\\n'",
   "Instructions": {
     "OperatorType": "Route",
     "Variant": "SelectUnsharded",
@@ -2216,27 +2018,13 @@ Gen4 plan same as above
     "FieldQuery": "select (select u.id from `user` as u where 1 != 1), a.id from `user` as a where 1 != 1",
     "Query": "select (select u.id from `user` as u where u.id = 1), a.id from `user` as a where a.id = 1",
     "Table": "`user`",
-    "Values": 1,
-    "Vindex": "user_index"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select (select u.id from user as u where u.id = 1), a.id from user as a where a.id = 1",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select (select u.id from `user` as u where 1 != 1), a.id from `user` as a where 1 != 1",
-    "Query": "select (select u.id from `user` as u where u.id = 1), a.id from `user` as a where a.id = 1",
-    "Table": "`user`",
-    "Values": "INT64(1)",
+    "Values": [
+      1
+    ],
     "Vindex": "user_index"
   }
 }
+Gen4 plan same as above
 
 # Add two tables with the same column in a join
 "select t.id, s.id from user t join user_extra s on t.id = s.user_id join unsharded"
@@ -2784,7 +2572,9 @@ Gen4 plan same as above
         "FieldQuery": "select 1 from user_extra where 1 != 1",
         "Query": "select 1 from user_extra where user_id = 3 and user_id \u003c :user_id",
         "Table": "user_extra",
-        "Values": "INT64(3)",
+        "Values": [
+          3
+        ],
         "Vindex": "user_index"
       }
     ]
@@ -2827,7 +2617,9 @@ Gen4 plan same as above
         "FieldQuery": "select 1 from user_extra where 1 != 1",
         "Query": "select 1 from user_extra where user_id = 3 and user_id \u003c :user_id",
         "Table": "user_extra",
-        "Values": "INT64(3)",
+        "Values": [
+          3
+        ],
         "Vindex": "user_index"
       }
     ]
diff --git a/go/vt/vtgate/planbuilder/testdata/systemtables_cases.txt b/go/vt/vtgate/planbuilder/testdata/systemtables_cases.txt
index d0e93ebb33..556efbfb99 100644
--- a/go/vt/vtgate/planbuilder/testdata/systemtables_cases.txt
+++ b/go/vt/vtgate/planbuilder/testdata/systemtables_cases.txt
@@ -924,7 +924,9 @@ Gen4 plan same as above
         "FieldQuery": "select 1 from `user` where 1 != 1",
         "Query": "select 1 from `user` where `user`.id = :x_id",
         "Table": "`user`",
-        "Values": ":x_id",
+        "Values": [
+          ":x_id"
+        ],
         "Vindex": "user_index"
       }
     ]
@@ -964,7 +966,9 @@ Gen4 plan same as above
         "FieldQuery": "select 1 from `user` where 1 != 1",
         "Query": "select 1 from `user` where `user`.id = :x_id",
         "Table": "`user`",
-        "Values": ":x_id",
+        "Values": [
+          ":x_id"
+        ],
         "Vindex": "user_index"
       }
     ]
diff --git a/go/vt/vtgate/planbuilder/testdata/tpcc_cases.txt b/go/vt/vtgate/planbuilder/testdata/tpcc_cases.txt
index 853485f767..5feb186faa 100644
--- a/go/vt/vtgate/planbuilder/testdata/tpcc_cases.txt
+++ b/go/vt/vtgate/planbuilder/testdata/tpcc_cases.txt
@@ -13,7 +13,9 @@
     "FieldQuery": "select c_discount, c_last, c_credit, w_tax from customer1 as c join warehouse1 as w on c_w_id = w_id where 1 != 1",
     "Query": "select c_discount, c_last, c_credit, w_tax from customer1 as c join warehouse1 as w on c_w_id = w_id where w_id = 1 and c_d_id = 15 and c_id = 10",
     "Table": "customer1, warehouse1",
-    "Values": 1,
+    "Values": [
+      1
+    ],
     "Vindex": "hash"
   }
 }
@@ -30,7 +32,9 @@
     "FieldQuery": "select c_discount, c_last, c_credit, w_tax from customer1 as c, warehouse1 as w where 1 != 1",
     "Query": "select c_discount, c_last, c_credit, w_tax from customer1 as c, warehouse1 as w where c_d_id = 15 and c_id = 10 and w_id = 1 and c_w_id = w_id",
     "Table": "customer1, warehouse1",
-    "Values": "INT64(1)",
+    "Values": [
+      1
+    ],
     "Vindex": "hash"
   }
 }
@@ -50,27 +54,13 @@
     "FieldQuery": "select d_next_o_id, d_tax from district1 where 1 != 1",
     "Query": "select d_next_o_id, d_tax from district1 where d_w_id = 15 and d_id = 95 for update",
     "Table": "district1",
-    "Values": 15,
-    "Vindex": "hash"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "SELECT d_next_o_id, d_tax FROM district1 WHERE d_w_id = 15 AND d_id = 95 FOR UPDATE",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "main",
-      "Sharded": true
-    },
-    "FieldQuery": "select d_next_o_id, d_tax from district1 where 1 != 1",
-    "Query": "select d_next_o_id, d_tax from district1 where d_w_id = 15 and d_id = 95 for update",
-    "Table": "district1",
-    "Values": "INT64(15)",
+    "Values": [
+      15
+    ],
     "Vindex": "hash"
   }
 }
+Gen4 plan same as above
 
 # TPC-C update district1 unique
 "UPDATE district1 SET d_next_o_id = 56 WHERE d_id = 9842 AND d_w_id= 8546"
@@ -151,27 +141,13 @@ Gen4 plan same as above
     "FieldQuery": "select i_price, i_name, i_data from item1 where 1 != 1",
     "Query": "select i_price, i_name, i_data from item1 where i_id = 9654",
     "Table": "item1",
-    "Values": 9654,
-    "Vindex": "hash"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "SELECT i_price, i_name, i_data FROM item1 WHERE i_id = 9654",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "main",
-      "Sharded": true
-    },
-    "FieldQuery": "select i_price, i_name, i_data from item1 where 1 != 1",
-    "Query": "select i_price, i_name, i_data from item1 where i_id = 9654",
-    "Table": "item1",
-    "Values": "INT64(9654)",
+    "Values": [
+      9654
+    ],
     "Vindex": "hash"
   }
 }
+Gen4 plan same as above
 
 # TPC-C select stock1 for update
 "SELECT s_quantity, s_data, s_dist_01 s_dist FROM stock1 WHERE s_i_id = 2198 AND s_w_id = 89 FOR UPDATE"
@@ -188,27 +164,13 @@ Gen4 plan same as above
     "FieldQuery": "select s_quantity, s_data, s_dist_01 as s_dist from stock1 where 1 != 1",
     "Query": "select s_quantity, s_data, s_dist_01 as s_dist from stock1 where s_i_id = 2198 and s_w_id = 89 for update",
     "Table": "stock1",
-    "Values": 89,
-    "Vindex": "hash"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "SELECT s_quantity, s_data, s_dist_01 s_dist FROM stock1 WHERE s_i_id = 2198 AND s_w_id = 89 FOR UPDATE",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "main",
-      "Sharded": true
-    },
-    "FieldQuery": "select s_quantity, s_data, s_dist_01 as s_dist from stock1 where 1 != 1",
-    "Query": "select s_quantity, s_data, s_dist_01 as s_dist from stock1 where s_i_id = 2198 and s_w_id = 89 for update",
-    "Table": "stock1",
-    "Values": "INT64(89)",
+    "Values": [
+      89
+    ],
     "Vindex": "hash"
   }
 }
+Gen4 plan same as above
 
 # TPC-C update stock1
 "UPDATE stock1 SET s_quantity = 894 WHERE s_i_id = 156 AND s_w_id= 6"
@@ -293,27 +255,13 @@ Gen4 plan same as above
     "FieldQuery": "select w_street_1, w_street_2, w_city, w_state, w_zip, w_name from warehouse1 where 1 != 1",
     "Query": "select w_street_1, w_street_2, w_city, w_state, w_zip, w_name from warehouse1 where w_id = 998",
     "Table": "warehouse1",
-    "Values": 998,
-    "Vindex": "hash"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "SELECT w_street_1, w_street_2, w_city, w_state, w_zip, w_name FROM warehouse1 WHERE w_id = 998",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "main",
-      "Sharded": true
-    },
-    "FieldQuery": "select w_street_1, w_street_2, w_city, w_state, w_zip, w_name from warehouse1 where 1 != 1",
-    "Query": "select w_street_1, w_street_2, w_city, w_state, w_zip, w_name from warehouse1 where w_id = 998",
-    "Table": "warehouse1",
-    "Values": "INT64(998)",
+    "Values": [
+      998
+    ],
     "Vindex": "hash"
   }
 }
+Gen4 plan same as above
 
 # TPC-C update district1 unique
 "UPDATE district1 SET d_ytd = d_ytd + 2 WHERE d_w_id = 89 AND d_id= 9"
@@ -354,27 +302,13 @@ Gen4 plan same as above
     "FieldQuery": "select d_street_1, d_street_2, d_city, d_state, d_zip, d_name from district1 where 1 != 1",
     "Query": "select d_street_1, d_street_2, d_city, d_state, d_zip, d_name from district1 where d_w_id = 896 and d_id = 9",
     "Table": "district1",
-    "Values": 896,
-    "Vindex": "hash"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "SELECT d_street_1, d_street_2, d_city, d_state, d_zip, d_name FROM district1 WHERE d_w_id = 896 AND d_id = 9",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "main",
-      "Sharded": true
-    },
-    "FieldQuery": "select d_street_1, d_street_2, d_city, d_state, d_zip, d_name from district1 where 1 != 1",
-    "Query": "select d_street_1, d_street_2, d_city, d_state, d_zip, d_name from district1 where d_w_id = 896 and d_id = 9",
-    "Table": "district1",
-    "Values": "INT64(896)",
+    "Values": [
+      896
+    ],
     "Vindex": "hash"
   }
 }
+Gen4 plan same as above
 
 # TPC-C select aggr from customer1
 "SELECT count(c_id) namecnt FROM customer1 WHERE c_w_id = 5 AND c_d_id= 1 AND c_last='last'"
@@ -391,27 +325,13 @@ Gen4 plan same as above
     "FieldQuery": "select count(c_id) as namecnt from customer1 where 1 != 1",
     "Query": "select count(c_id) as namecnt from customer1 where c_w_id = 5 and c_d_id = 1 and c_last = 'last'",
     "Table": "customer1",
-    "Values": 5,
-    "Vindex": "hash"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "SELECT count(c_id) namecnt FROM customer1 WHERE c_w_id = 5 AND c_d_id= 1 AND c_last='last'",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "main",
-      "Sharded": true
-    },
-    "FieldQuery": "select count(c_id) as namecnt from customer1 where 1 != 1",
-    "Query": "select count(c_id) as namecnt from customer1 where c_w_id = 5 and c_d_id = 1 and c_last = 'last'",
-    "Table": "customer1",
-    "Values": "INT64(5)",
+    "Values": [
+      5
+    ],
     "Vindex": "hash"
   }
 }
+Gen4 plan same as above
 
 # TPC-C select customer1 order by
 "SELECT c_id FROM customer1 WHERE c_w_id = 8 AND c_d_id = 5 AND c_last='item_last' ORDER BY c_first"
@@ -428,27 +348,13 @@ Gen4 plan same as above
     "FieldQuery": "select c_id from customer1 where 1 != 1",
     "Query": "select c_id from customer1 where c_w_id = 8 and c_d_id = 5 and c_last = 'item_last' order by c_first asc",
     "Table": "customer1",
-    "Values": 8,
-    "Vindex": "hash"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "SELECT c_id FROM customer1 WHERE c_w_id = 8 AND c_d_id = 5 AND c_last='item_last' ORDER BY c_first",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "main",
-      "Sharded": true
-    },
-    "FieldQuery": "select c_id from customer1 where 1 != 1",
-    "Query": "select c_id from customer1 where c_w_id = 8 and c_d_id = 5 and c_last = 'item_last' order by c_first asc",
-    "Table": "customer1",
-    "Values": "INT64(8)",
+    "Values": [
+      8
+    ],
     "Vindex": "hash"
   }
 }
+Gen4 plan same as above
 
 # TPC-C select for update customer1 unique
 "SELECT c_first, c_middle, c_last, c_street_1, c_street_2, c_city, c_state, c_zip, c_phone, c_credit, c_credit_lim, c_discount, c_balance, c_ytd_payment, c_since FROM customer1 WHERE c_w_id = 8965 AND c_d_id = 1 AND c_id = 9 FOR UPDATE"
@@ -465,27 +371,13 @@ Gen4 plan same as above
     "FieldQuery": "select c_first, c_middle, c_last, c_street_1, c_street_2, c_city, c_state, c_zip, c_phone, c_credit, c_credit_lim, c_discount, c_balance, c_ytd_payment, c_since from customer1 where 1 != 1",
     "Query": "select c_first, c_middle, c_last, c_street_1, c_street_2, c_city, c_state, c_zip, c_phone, c_credit, c_credit_lim, c_discount, c_balance, c_ytd_payment, c_since from customer1 where c_w_id = 8965 and c_d_id = 1 and c_id = 9 for update",
     "Table": "customer1",
-    "Values": 8965,
-    "Vindex": "hash"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "SELECT c_first, c_middle, c_last, c_street_1, c_street_2, c_city, c_state, c_zip, c_phone, c_credit, c_credit_lim, c_discount, c_balance, c_ytd_payment, c_since FROM customer1 WHERE c_w_id = 8965 AND c_d_id = 1 AND c_id = 9 FOR UPDATE",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "main",
-      "Sharded": true
-    },
-    "FieldQuery": "select c_first, c_middle, c_last, c_street_1, c_street_2, c_city, c_state, c_zip, c_phone, c_credit, c_credit_lim, c_discount, c_balance, c_ytd_payment, c_since from customer1 where 1 != 1",
-    "Query": "select c_first, c_middle, c_last, c_street_1, c_street_2, c_city, c_state, c_zip, c_phone, c_credit, c_credit_lim, c_discount, c_balance, c_ytd_payment, c_since from customer1 where c_w_id = 8965 and c_d_id = 1 and c_id = 9 for update",
-    "Table": "customer1",
-    "Values": "INT64(8965)",
+    "Values": [
+      8965
+    ],
     "Vindex": "hash"
   }
 }
+Gen4 plan same as above
 
 # TPC-C select customer1 unique
 "SELECT c_data FROM customer1 WHERE c_w_id = 32 AND c_d_id=68 AND c_id = 5"
@@ -502,27 +394,13 @@ Gen4 plan same as above
     "FieldQuery": "select c_data from customer1 where 1 != 1",
     "Query": "select c_data from customer1 where c_w_id = 32 and c_d_id = 68 and c_id = 5",
     "Table": "customer1",
-    "Values": 32,
-    "Vindex": "hash"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "SELECT c_data FROM customer1 WHERE c_w_id = 32 AND c_d_id=68 AND c_id = 5",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "main",
-      "Sharded": true
-    },
-    "FieldQuery": "select c_data from customer1 where 1 != 1",
-    "Query": "select c_data from customer1 where c_w_id = 32 and c_d_id = 68 and c_id = 5",
-    "Table": "customer1",
-    "Values": "INT64(32)",
+    "Values": [
+      32
+    ],
     "Vindex": "hash"
   }
 }
+Gen4 plan same as above
 
 # TPC-C update customer1 unique and float value
 "UPDATE customer1 SET c_balance=508.98, c_ytd_payment=48941.980301, c_data='i am data' WHERE c_w_id = 20  AND c_d_id=387 AND c_id=98"
@@ -607,27 +485,13 @@ Gen4 plan same as above
     "FieldQuery": "select count(c_id) as namecnt from customer1 where 1 != 1",
     "Query": "select count(c_id) as namecnt from customer1 where c_w_id = 870 and c_d_id = 780 and c_last = 'last'",
     "Table": "customer1",
-    "Values": 870,
-    "Vindex": "hash"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "SELECT count(c_id) namecnt FROM customer1 WHERE c_w_id = 870 AND c_d_id= 780 AND c_last='last'",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "main",
-      "Sharded": true
-    },
-    "FieldQuery": "select count(c_id) as namecnt from customer1 where 1 != 1",
-    "Query": "select count(c_id) as namecnt from customer1 where c_w_id = 870 and c_d_id = 780 and c_last = 'last'",
-    "Table": "customer1",
-    "Values": "INT64(870)",
+    "Values": [
+      870
+    ],
     "Vindex": "hash"
   }
 }
+Gen4 plan same as above
 
 # TPC-C select order by customer1
 "SELECT c_balance, c_first, c_middle, c_id FROM customer1 WHERE c_w_id = 840 AND c_d_id= 1 AND c_last='test' ORDER BY c_first"
@@ -644,27 +508,13 @@ Gen4 plan same as above
     "FieldQuery": "select c_balance, c_first, c_middle, c_id from customer1 where 1 != 1",
     "Query": "select c_balance, c_first, c_middle, c_id from customer1 where c_w_id = 840 and c_d_id = 1 and c_last = 'test' order by c_first asc",
     "Table": "customer1",
-    "Values": 840,
-    "Vindex": "hash"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "SELECT c_balance, c_first, c_middle, c_id FROM customer1 WHERE c_w_id = 840 AND c_d_id= 1 AND c_last='test' ORDER BY c_first",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "main",
-      "Sharded": true
-    },
-    "FieldQuery": "select c_balance, c_first, c_middle, c_id from customer1 where 1 != 1",
-    "Query": "select c_balance, c_first, c_middle, c_id from customer1 where c_w_id = 840 and c_d_id = 1 and c_last = 'test' order by c_first asc",
-    "Table": "customer1",
-    "Values": "INT64(840)",
+    "Values": [
+      840
+    ],
     "Vindex": "hash"
   }
 }
+Gen4 plan same as above
 
 # TPC-C select unique customer1
 "SELECT c_balance, c_first, c_middle, c_last FROM customer1 WHERE c_w_id = 15 AND c_d_id=5169 AND c_id=1"
@@ -681,27 +531,13 @@ Gen4 plan same as above
     "FieldQuery": "select c_balance, c_first, c_middle, c_last from customer1 where 1 != 1",
     "Query": "select c_balance, c_first, c_middle, c_last from customer1 where c_w_id = 15 and c_d_id = 5169 and c_id = 1",
     "Table": "customer1",
-    "Values": 15,
-    "Vindex": "hash"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "SELECT c_balance, c_first, c_middle, c_last FROM customer1 WHERE c_w_id = 15 AND c_d_id=5169 AND c_id=1",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "main",
-      "Sharded": true
-    },
-    "FieldQuery": "select c_balance, c_first, c_middle, c_last from customer1 where 1 != 1",
-    "Query": "select c_balance, c_first, c_middle, c_last from customer1 where c_w_id = 15 and c_d_id = 5169 and c_id = 1",
-    "Table": "customer1",
-    "Values": "INT64(15)",
+    "Values": [
+      15
+    ],
     "Vindex": "hash"
   }
 }
+Gen4 plan same as above
 
 # TPC-C select order by orders1
 "SELECT o_id, o_carrier_id, o_entry_d FROM orders1 WHERE o_w_id = 9894 AND o_d_id = 3 AND o_c_id = 159 ORDER BY o_id DESC"
@@ -718,27 +554,13 @@ Gen4 plan same as above
     "FieldQuery": "select o_id, o_carrier_id, o_entry_d from orders1 where 1 != 1",
     "Query": "select o_id, o_carrier_id, o_entry_d from orders1 where o_w_id = 9894 and o_d_id = 3 and o_c_id = 159 order by o_id desc",
     "Table": "orders1",
-    "Values": 9894,
-    "Vindex": "hash"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "SELECT o_id, o_carrier_id, o_entry_d FROM orders1 WHERE o_w_id = 9894 AND o_d_id = 3 AND o_c_id = 159 ORDER BY o_id DESC",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "main",
-      "Sharded": true
-    },
-    "FieldQuery": "select o_id, o_carrier_id, o_entry_d from orders1 where 1 != 1",
-    "Query": "select o_id, o_carrier_id, o_entry_d from orders1 where o_w_id = 9894 and o_d_id = 3 and o_c_id = 159 order by o_id desc",
-    "Table": "orders1",
-    "Values": "INT64(9894)",
+    "Values": [
+      9894
+    ],
     "Vindex": "hash"
   }
 }
+Gen4 plan same as above
 
 # TPC-C select order_line1
 "SELECT ol_i_id, ol_supply_w_id, ol_quantity, ol_amount, ol_delivery_d FROM order_line1 WHERE ol_w_id = 92 AND ol_d_id = 5  AND ol_o_id = 1"
@@ -755,27 +577,13 @@ Gen4 plan same as above
     "FieldQuery": "select ol_i_id, ol_supply_w_id, ol_quantity, ol_amount, ol_delivery_d from order_line1 where 1 != 1",
     "Query": "select ol_i_id, ol_supply_w_id, ol_quantity, ol_amount, ol_delivery_d from order_line1 where ol_w_id = 92 and ol_d_id = 5 and ol_o_id = 1",
     "Table": "order_line1",
-    "Values": 92,
-    "Vindex": "hash"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "SELECT ol_i_id, ol_supply_w_id, ol_quantity, ol_amount, ol_delivery_d FROM order_line1 WHERE ol_w_id = 92 AND ol_d_id = 5  AND ol_o_id = 1",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "main",
-      "Sharded": true
-    },
-    "FieldQuery": "select ol_i_id, ol_supply_w_id, ol_quantity, ol_amount, ol_delivery_d from order_line1 where 1 != 1",
-    "Query": "select ol_i_id, ol_supply_w_id, ol_quantity, ol_amount, ol_delivery_d from order_line1 where ol_w_id = 92 and ol_d_id = 5 and ol_o_id = 1",
-    "Table": "order_line1",
-    "Values": "INT64(92)",
+    "Values": [
+      92
+    ],
     "Vindex": "hash"
   }
 }
+Gen4 plan same as above
 
 # TPC-C select for update new_orders1
 "SELECT no_o_id FROM new_orders1 WHERE no_d_id = 689 AND no_w_id = 15 ORDER BY no_o_id ASC LIMIT 1 FOR UPDATE"
@@ -792,27 +600,13 @@ Gen4 plan same as above
     "FieldQuery": "select no_o_id from new_orders1 where 1 != 1",
     "Query": "select no_o_id from new_orders1 where no_d_id = 689 and no_w_id = 15 order by no_o_id asc limit 1 for update",
     "Table": "new_orders1",
-    "Values": 15,
-    "Vindex": "hash"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "SELECT no_o_id FROM new_orders1 WHERE no_d_id = 689 AND no_w_id = 15 ORDER BY no_o_id ASC LIMIT 1 FOR UPDATE",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "main",
-      "Sharded": true
-    },
-    "FieldQuery": "select no_o_id from new_orders1 where 1 != 1",
-    "Query": "select no_o_id from new_orders1 where no_d_id = 689 and no_w_id = 15 order by no_o_id asc limit 1 for update",
-    "Table": "new_orders1",
-    "Values": "INT64(15)",
+    "Values": [
+      15
+    ],
     "Vindex": "hash"
   }
 }
+Gen4 plan same as above
 
 # TPC-C delete new_orders1
 "DELETE FROM new_orders1 WHERE no_o_id = 2218 AND no_d_id = 358 AND no_w_id = 98465"
@@ -853,27 +647,13 @@ Gen4 plan same as above
     "FieldQuery": "select o_c_id from orders1 where 1 != 1",
     "Query": "select o_c_id from orders1 where o_id = 6 and o_d_id = 1983 and o_w_id = 894605",
     "Table": "orders1",
-    "Values": 894605,
-    "Vindex": "hash"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "SELECT o_c_id FROM orders1 WHERE o_id = 6 AND o_d_id = 1983 AND o_w_id = 894605",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "main",
-      "Sharded": true
-    },
-    "FieldQuery": "select o_c_id from orders1 where 1 != 1",
-    "Query": "select o_c_id from orders1 where o_id = 6 and o_d_id = 1983 and o_w_id = 894605",
-    "Table": "orders1",
-    "Values": "INT64(894605)",
+    "Values": [
+      894605
+    ],
     "Vindex": "hash"
   }
 }
+Gen4 plan same as above
 
 # TPC-C update orders1 unique
 "UPDATE orders1 SET o_carrier_id = 9 WHERE o_id = 56 AND o_d_id = 98 AND o_w_id = 897"
@@ -938,27 +718,13 @@ Gen4 plan same as above
     "FieldQuery": "select SUM(ol_amount) as sm from order_line1 where 1 != 1",
     "Query": "select SUM(ol_amount) as sm from order_line1 where ol_o_id = 680 and ol_d_id = 201 and ol_w_id = 87",
     "Table": "order_line1",
-    "Values": 87,
-    "Vindex": "hash"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "SELECT SUM(ol_amount) sm FROM order_line1 WHERE ol_o_id = 680 AND ol_d_id = 201 AND ol_w_id = 87",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "main",
-      "Sharded": true
-    },
-    "FieldQuery": "select SUM(ol_amount) as sm from order_line1 where 1 != 1",
-    "Query": "select SUM(ol_amount) as sm from order_line1 where ol_o_id = 680 and ol_d_id = 201 and ol_w_id = 87",
-    "Table": "order_line1",
-    "Values": "INT64(87)",
+    "Values": [
+      87
+    ],
     "Vindex": "hash"
   }
 }
+Gen4 plan same as above
 
 # TPC-C update customer1
 "UPDATE customer1 SET c_balance = c_balance + 988.01, c_delivery_cnt = c_delivery_cnt + 1 WHERE c_id = 6 AND c_d_id = 5 AND c_w_id = 160"
@@ -999,27 +765,13 @@ Gen4 plan same as above
     "FieldQuery": "select d_next_o_id from district1 where 1 != 1",
     "Query": "select d_next_o_id from district1 where d_id = 6 and d_w_id = 21",
     "Table": "district1",
-    "Values": 21,
-    "Vindex": "hash"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "SELECT d_next_o_id FROM district1 WHERE d_id = 6 AND d_w_id= 21",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "main",
-      "Sharded": true
-    },
-    "FieldQuery": "select d_next_o_id from district1 where 1 != 1",
-    "Query": "select d_next_o_id from district1 where d_id = 6 and d_w_id = 21",
-    "Table": "district1",
-    "Values": "INT64(21)",
+    "Values": [
+      21
+    ],
     "Vindex": "hash"
   }
 }
+Gen4 plan same as above
 
 # TPC-C select count distinct stock1 join order_line1
 "SELECT COUNT(DISTINCT(s.s_i_id)) FROM stock1 AS s JOIN order_line1 AS ol ON ol.ol_w_id=s.s_w_id AND ol.ol_i_id=s.s_i_id WHERE ol.ol_w_id = 12 AND ol.ol_d_id = 1908 AND ol.ol_o_id < 30 AND ol.ol_o_id >= 15 AND s.s_w_id= 12 AND s.s_quantity < 10"
@@ -1036,7 +788,9 @@ Gen4 plan same as above
     "FieldQuery": "select COUNT(distinct s.s_i_id) from stock1 as s join order_line1 as ol on ol.ol_w_id = s.s_w_id and ol.ol_i_id = s.s_i_id where 1 != 1",
     "Query": "select COUNT(distinct s.s_i_id) from stock1 as s join order_line1 as ol on ol.ol_w_id = s.s_w_id and ol.ol_i_id = s.s_i_id where ol.ol_w_id = 12 and ol.ol_d_id = 1908 and ol.ol_o_id \u003c 30 and ol.ol_o_id \u003e= 15 and s.s_w_id = 12 and s.s_quantity \u003c 10",
     "Table": "stock1, order_line1",
-    "Values": 12,
+    "Values": [
+      12
+    ],
     "Vindex": "hash"
   }
 }
@@ -1053,7 +807,9 @@ Gen4 plan same as above
     "FieldQuery": "select COUNT(distinct s.s_i_id) from stock1 as s, order_line1 as ol where 1 != 1",
     "Query": "select COUNT(distinct s.s_i_id) from stock1 as s, order_line1 as ol where s.s_w_id = 12 and s.s_quantity \u003c 10 and ol.ol_w_id = 12 and ol.ol_d_id = 1908 and ol.ol_o_id \u003c 30 and ol.ol_o_id \u003e= 15 and ol.ol_w_id = s.s_w_id and ol.ol_i_id = s.s_i_id",
     "Table": "order_line1, stock1",
-    "Values": "INT64(12)",
+    "Values": [
+      12
+    ],
     "Vindex": "hash"
   }
 }
@@ -1073,27 +829,13 @@ Gen4 plan same as above
     "FieldQuery": "select ol_i_id from order_line1 where 1 != 1",
     "Query": "select distinct ol_i_id from order_line1 where ol_w_id = 1 and ol_d_id = 156 and ol_o_id \u003c 500 and ol_o_id \u003e= 56",
     "Table": "order_line1",
-    "Values": 1,
-    "Vindex": "hash"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "SELECT DISTINCT ol_i_id FROM order_line1 WHERE ol_w_id = 1 AND ol_d_id = 156 AND ol_o_id \u003c 500 AND ol_o_id \u003e= 56",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "main",
-      "Sharded": true
-    },
-    "FieldQuery": "select ol_i_id from order_line1 where 1 != 1",
-    "Query": "select distinct ol_i_id from order_line1 where ol_w_id = 1 and ol_d_id = 156 and ol_o_id \u003c 500 and ol_o_id \u003e= 56",
-    "Table": "order_line1",
-    "Values": "INT64(1)",
+    "Values": [
+      1
+    ],
     "Vindex": "hash"
   }
 }
+Gen4 plan same as above
 
 # TPC-C
 "SELECT count(*) FROM stock1 WHERE s_w_id = 1 AND s_i_id = 8 AND s_quantity < 1000"
@@ -1110,27 +852,13 @@ Gen4 plan same as above
     "FieldQuery": "select count(*) from stock1 where 1 != 1",
     "Query": "select count(*) from stock1 where s_w_id = 1 and s_i_id = 8 and s_quantity \u003c 1000",
     "Table": "stock1",
-    "Values": 1,
-    "Vindex": "hash"
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "SELECT count(*) FROM stock1 WHERE s_w_id = 1 AND s_i_id = 8 AND s_quantity \u003c 1000",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectEqualUnique",
-    "Keyspace": {
-      "Name": "main",
-      "Sharded": true
-    },
-    "FieldQuery": "select count(*) from stock1 where 1 != 1",
-    "Query": "select count(*) from stock1 where s_w_id = 1 and s_i_id = 8 and s_quantity \u003c 1000",
-    "Table": "stock1",
-    "Values": "INT64(1)",
+    "Values": [
+      1
+    ],
     "Vindex": "hash"
   }
 }
+Gen4 plan same as above
 
 # TPC-C select with subquery,aggr,distinct,having,limit
 "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 > 2100 and o_id < 11153 group by o_c_id,o_d_id,o_w_id having count( distinct o_id) > 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"
@@ -1173,7 +901,9 @@ Gen4 plan same as above
             "FieldQuery": "select 1 from (select o_c_id, o_w_id, o_d_id, count(distinct o_w_id), o_id from orders1 where 1 != 1 group by o_c_id, o_d_id, o_w_id) as t where 1 != 1",
             "Query": "select 1 from (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) 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",
             "Table": "orders1",
-            "Values": 1,
+            "Values": [
+              1
+            ],
             "Vindex": "hash"
           }
         ]
@@ -1194,7 +924,9 @@ Gen4 plan same as above
     "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": "INT64(1)",
+    "Values": [
+      1
+    ],
     "Vindex": "hash"
   }
 }
diff --git a/go/vt/vtgate/planbuilder/testdata/tpch_cases.txt b/go/vt/vtgate/planbuilder/testdata/tpch_cases.txt
index befead9ddd..badb5215aa 100644
--- a/go/vt/vtgate/planbuilder/testdata/tpch_cases.txt
+++ b/go/vt/vtgate/planbuilder/testdata/tpch_cases.txt
@@ -177,7 +177,9 @@ Gen4 error: unsupported: in scatter query: complex aggregate expression
             "FieldQuery": "select total_revenue from revenue0 where 1 != 1",
             "Query": "select total_revenue from revenue0 where supplier_no = :s_suppkey and total_revenue = :__sq1",
             "Table": "revenue0",
-            "Values": ":s_suppkey",
+            "Values": [
+              ":s_suppkey"
+            ],
             "Vindex": "hash"
           }
         ]
@@ -304,7 +306,9 @@ Gen4 error: unsupported: in scatter query: complex aggregate expression
                         "FieldQuery": "select p_brand, p_type, p_size, weight_string(p_brand), weight_string(p_type), weight_string(p_size) from part where 1 != 1",
                         "Query": "select p_brand, p_type, p_size, weight_string(p_brand), weight_string(p_type), weight_string(p_size) from part where p_brand != 'Brand#45' and p_type not like 'MEDIUM POLISHED%' and p_size in (49, 14, 23, 45, 19, 3, 36, 9) and p_partkey = :ps_partkey",
                         "Table": "part",
-                        "Values": ":ps_partkey",
+                        "Values": [
+                          ":ps_partkey"
+                        ],
                         "Vindex": "hash"
                       }
                     ]
@@ -384,7 +388,9 @@ Gen4 error: unsupported: cross-shard correlated subquery
                     "OrderBy": "(3|6) DESC, (2|5) ASC",
                     "Query": "select o_custkey, o_orderkey, o_orderdate, o_totalprice, weight_string(o_orderkey), weight_string(o_orderdate), weight_string(o_totalprice) from orders where :__sq_has_values1 = 1 and o_orderkey in ::__vals order by o_totalprice desc, o_orderdate asc",
                     "Table": "orders",
-                    "Values": ":__sq1",
+                    "Values": [
+                      "::__sq1"
+                    ],
                     "Vindex": "hash"
                   },
                   {
@@ -397,7 +403,9 @@ Gen4 error: unsupported: cross-shard correlated subquery
                     "FieldQuery": "select c_name, c_custkey, weight_string(c_name), weight_string(c_custkey) from customer where 1 != 1",
                     "Query": "select c_name, c_custkey, weight_string(c_name), weight_string(c_custkey) from customer where c_custkey = :o_custkey",
                     "Table": "customer",
-                    "Values": ":o_custkey",
+                    "Values": [
+                      ":o_custkey"
+                    ],
                     "Vindex": "hash"
                   }
                 ]
@@ -412,7 +420,9 @@ Gen4 error: unsupported: cross-shard correlated subquery
                 "FieldQuery": "select sum(l_quantity) from lineitem where 1 != 1",
                 "Query": "select sum(l_quantity) from lineitem where l_orderkey = :o_orderkey",
                 "Table": "lineitem",
-                "Values": ":o_orderkey",
+                "Values": [
+                  ":o_orderkey"
+                ],
                 "Vindex": "lineitem_map"
               }
             ]
diff --git a/go/vt/vtgate/planbuilder/testdata/union_cases.txt b/go/vt/vtgate/planbuilder/testdata/union_cases.txt
index 37dd70e0b4..f1375f268d 100644
--- a/go/vt/vtgate/planbuilder/testdata/union_cases.txt
+++ b/go/vt/vtgate/planbuilder/testdata/union_cases.txt
@@ -94,7 +94,9 @@ Gen4 plan same as above
         "FieldQuery": "select id from `user` where 1 != 1",
         "Query": "select id from `user` where id = 1",
         "Table": "`user`",
-        "Values": 1,
+        "Values": [
+          1
+        ],
         "Vindex": "user_index"
       },
       {
@@ -107,47 +109,15 @@ Gen4 plan same as above
         "FieldQuery": "select id from `user` where 1 != 1",
         "Query": "select id from `user` where id = 5",
         "Table": "`user`",
-        "Values": 5,
-        "Vindex": "user_index"
-      }
-    ]
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select id from user where id = 1 union all select id from user where id = 5",
-  "Instructions": {
-    "OperatorType": "Concatenate",
-    "Inputs": [
-      {
-        "OperatorType": "Route",
-        "Variant": "SelectEqualUnique",
-        "Keyspace": {
-          "Name": "user",
-          "Sharded": true
-        },
-        "FieldQuery": "select id from `user` where 1 != 1",
-        "Query": "select id from `user` where id = 1",
-        "Table": "`user`",
-        "Values": "INT64(1)",
-        "Vindex": "user_index"
-      },
-      {
-        "OperatorType": "Route",
-        "Variant": "SelectEqualUnique",
-        "Keyspace": {
-          "Name": "user",
-          "Sharded": true
-        },
-        "FieldQuery": "select id from `user` where 1 != 1",
-        "Query": "select id from `user` where id = 5",
-        "Table": "`user`",
-        "Values": "INT64(5)",
+        "Values": [
+          5
+        ],
         "Vindex": "user_index"
       }
     ]
   }
 }
+Gen4 plan same as above
 
 #almost dereks query - two queries with order by and limit being scattered to two different sets of tablets
 "(SELECT id FROM user ORDER BY id DESC LIMIT 1) UNION ALL (SELECT id FROM music ORDER BY id DESC LIMIT 1)"
@@ -326,40 +296,9 @@ Gen4 plan same as above
         "FieldQuery": "select id from `user` where 1 != 1 union select id from `user` where 1 != 1",
         "Query": "select id from `user` where id = 1 union select id from `user` where id = 1",
         "Table": "`user`",
-        "Values": 1,
-        "Vindex": "user_index"
-      },
-      {
-        "OperatorType": "Route",
-        "Variant": "SelectScatter",
-        "Keyspace": {
-          "Name": "user",
-          "Sharded": true
-        },
-        "FieldQuery": "select id from `user` where 1 != 1",
-        "Query": "select id from `user`",
-        "Table": "`user`"
-      }
-    ]
-  }
-}
-{
-  "QueryType": "SELECT",
-  "Original": "select id from user where id = 1 union select id from user where id = 1  union all select id from user",
-  "Instructions": {
-    "OperatorType": "Concatenate",
-    "Inputs": [
-      {
-        "OperatorType": "Route",
-        "Variant": "SelectEqualUnique",
-        "Keyspace": {
-          "Name": "user",
-          "Sharded": true
-        },
-        "FieldQuery": "select id from `user` where 1 != 1 union select id from `user` where 1 != 1",
-        "Query": "select id from `user` where id = 1 union select id from `user` where id = 1",
-        "Table": "`user`",
-        "Values": "INT64(1)",
+        "Values": [
+          1
+        ],
         "Vindex": "user_index"
       },
       {
@@ -376,6 +315,7 @@ Gen4 plan same as above
     ]
   }
 }
+Gen4 plan same as above
 
 # union of information_schema with normal table
 "select * from information_schema.a union select * from unsharded"
@@ -761,7 +701,9 @@ Gen4 error: nesting of unions at the right-hand side is not yet supported
             "FieldQuery": "select * from music where 1 != 1",
             "Query": "select * from music where id = 1",
             "Table": "music",
-            "Values": 1,
+            "Values": [
+              1
+            ],
             "Vindex": "music_user_map"
           },
           {
@@ -774,7 +716,9 @@ Gen4 error: nesting of unions at the right-hand side is not yet supported
             "FieldQuery": "select * from `user` where 1 != 1",
             "Query": "select * from `user` where id = 1",
             "Table": "`user`",
-            "Values": 1,
+            "Values": [
+              1
+            ],
             "Vindex": "user_index"
           }
         ]
@@ -801,7 +745,9 @@ Gen4 error: nesting of unions at the right-hand side is not yet supported
             "FieldQuery": "select * from music where 1 != 1",
             "Query": "select distinct * from music where id = 1",
             "Table": "music",
-            "Values": "INT64(1)",
+            "Values": [
+              1
+            ],
             "Vindex": "music_user_map"
           },
           {
@@ -814,7 +760,9 @@ Gen4 error: nesting of unions at the right-hand side is not yet supported
             "FieldQuery": "select * from `user` where 1 != 1",
             "Query": "select distinct * from `user` where id = 1",
             "Table": "`user`",
-            "Values": "INT64(1)",
+            "Values": [
+              1
+            ],
             "Vindex": "user_index"
           }
         ]
@@ -844,7 +792,9 @@ Gen4 error: nesting of unions at the right-hand side is not yet supported
             "FieldQuery": "select 1 from music where 1 != 1",
             "Query": "select 1 from music where id = 1",
             "Table": "music",
-            "Values": 1,
+            "Values": [
+              1
+            ],
             "Vindex": "music_user_map"
           },
           {
@@ -857,7 +807,9 @@ Gen4 error: nesting of unions at the right-hand side is not yet supported
             "FieldQuery": "select 1 from music where 1 != 1",
             "Query": "select 1 from music where id = 2",
             "Table": "music",
-            "Values": 2,
+            "Values": [
+              2
+            ],
             "Vindex": "music_user_map"
           }
         ]
@@ -884,7 +836,9 @@ Gen4 error: nesting of unions at the right-hand side is not yet supported
             "FieldQuery": "select 1 from music where 1 != 1",
             "Query": "select distinct 1 from music where id = 1",
             "Table": "music",
-            "Values": "INT64(1)",
+            "Values": [
+              1
+            ],
             "Vindex": "music_user_map"
           },
           {
@@ -897,7 +851,9 @@ Gen4 error: nesting of unions at the right-hand side is not yet supported
             "FieldQuery": "select 1 from music where 1 != 1",
             "Query": "select distinct 1 from music where id = 2",
             "Table": "music",
-            "Values": "INT64(2)",
+            "Values": [
+              2
+            ],
             "Vindex": "music_user_map"
           }
         ]
diff --git a/go/vt/vtgate/planbuilder/testdata/unsupported_cases.txt b/go/vt/vtgate/planbuilder/testdata/unsupported_cases.txt
index b6a8d78394..9caafc33da 100644
--- a/go/vt/vtgate/planbuilder/testdata/unsupported_cases.txt
+++ b/go/vt/vtgate/planbuilder/testdata/unsupported_cases.txt
@@ -545,7 +545,9 @@ Gen4 error: expr cannot be converted, not supported: *sqlparser.FuncExpr
     "FieldQuery": "select 1 from `user` where 1 != 1",
     "Query": "select 1 from `user` having count(id) = 10 and `name` = 'a'",
     "Table": "`user`",
-    "Values": "a",
+    "Values": [
+      "a"
+    ],
     "Vindex": "name_user_map"
   }
 }
diff --git a/go/vt/vtgate/planbuilder/testdata/wireup_cases.txt b/go/vt/vtgate/planbuilder/testdata/wireup_cases.txt
index d3e3e6b02c..f4a5180e3f 100644
--- a/go/vt/vtgate/planbuilder/testdata/wireup_cases.txt
+++ b/go/vt/vtgate/planbuilder/testdata/wireup_cases.txt
@@ -71,7 +71,9 @@
         "FieldQuery": "select u.id as uid from `user` as u where 1 != 1",
         "Query": "select u.id as uid from `user` as u where u.id = :e_id",
         "Table": "`user`",
-        "Values": ":e_id",
+        "Values": [
+          ":e_id"
+        ],
         "Vindex": "user_index"
       }
     ]
@@ -151,7 +153,9 @@
         "FieldQuery": "select u.id as uid from `user` as u where 1 != 1",
         "Query": "select u.id as uid from `user` as u where u.id = :e_id",
         "Table": "`user`",
-        "Values": ":e_id",
+        "Values": [
+          ":e_id"
+        ],
         "Vindex": "user_index"
       }
     ]
@@ -578,7 +582,9 @@
             "FieldQuery": "select 1 from `user` as u3 where 1 != 1",
             "Query": "select 1 from `user` as u3 where u3.id = :u1_col",
             "Table": "`user`",
-            "Values": ":u1_col",
+            "Values": [
+              ":u1_col"
+            ],
             "Vindex": "user_index"
           }
         ]
@@ -669,7 +675,9 @@
                 "FieldQuery": "select 1 from `user` as u3 where 1 != 1",
                 "Query": "select 1 from `user` as u3 where u3.id = :u1_col",
                 "Table": "`user`",
-                "Values": ":u1_col",
+                "Values": [
+                  ":u1_col"
+                ],
                 "Vindex": "user_index"
               }
             ]
@@ -720,7 +728,9 @@
             "FieldQuery": "select 1 from `user` as u2 where 1 != 1",
             "Query": "select 1 from `user` as u2 where u2.id = :u1_col",
             "Table": "`user`",
-            "Values": ":u1_col",
+            "Values": [
+              ":u1_col"
+            ],
             "Vindex": "user_index"
           },
           {
@@ -733,7 +743,9 @@
             "FieldQuery": "select 1 from `user` as u3 where 1 != 1",
             "Query": "select 1 from `user` as u3 where u3.id = :u1_col",
             "Table": "`user`",
-            "Values": ":u1_col",
+            "Values": [
+              ":u1_col"
+            ],
             "Vindex": "user_index"
           }
         ]
@@ -785,7 +797,9 @@
             "FieldQuery": "select 1 from `user` as u2 where 1 != 1",
             "Query": "select 1 from `user` as u2 where u2.id = :u1_col",
             "Table": "`user`",
-            "Values": ":u1_col",
+            "Values": [
+              ":u1_col"
+            ],
             "Vindex": "user_index"
           }
         ]
@@ -800,7 +814,9 @@
         "FieldQuery": "select 1 from `user` as u3 where 1 != 1",
         "Query": "select 1 from `user` as u3 where u3.id = :u1_col",
         "Table": "`user`",
-        "Values": ":u1_col",
+        "Values": [
+          ":u1_col"
+        ],
         "Vindex": "user_index"
       }
     ]
@@ -880,7 +896,9 @@
         "FieldQuery": "select `weird``name`.a from `weird``name` where 1 != 1",
         "Query": "select `weird``name`.a from `weird``name` where `weird``name`.`a``b*c` = :unsharded_id",
         "Table": "`weird``name`",
-        "Values": ":unsharded_id",
+        "Values": [
+          ":unsharded_id"
+        ],
         "Vindex": "user_index"
       }
     ]
@@ -960,7 +978,9 @@
         "FieldQuery": "select 1 from `weird``name` where 1 != 1",
         "Query": "select 1 from `weird``name` where `weird``name`.`a``b*c` = :unsharded_id",
         "Table": "`weird``name`",
-        "Values": ":unsharded_id",
+        "Values": [
+          ":unsharded_id"
+        ],
         "Vindex": "user_index"
       }
     ]
@@ -1119,7 +1139,9 @@
         "FieldQuery": "select 1 from `user` where 1 != 1",
         "Query": "select 1 from `user` where :__sq_has_values1 = 1 and id in ::__vals",
         "Table": "`user`",
-        "Values": "::__sq1",
+        "Values": [
+          "::__sq1"
+        ],
         "Vindex": "user_index"
       }
     ]
@@ -1186,7 +1208,9 @@
         "FieldQuery": "select 1 from `user` where 1 != 1",
         "Query": "select 1 from `user` where :__sq_has_values1 = 1 and id in ::__vals",
         "Table": "`user`",
-        "Values": ":__sq1",
+        "Values": [
+          "::__sq1"
+        ],
         "Vindex": "user_index"
       }
     ]
@@ -1327,94 +1351,14 @@
 # Invalid value in IN clause
 "select id from user where id in (18446744073709551616, 1)"
 "strconv.ParseUint: parsing "18446744073709551616": value out of range"
-{
-  "QueryType": "SELECT",
-  "Original": "select id from user where id in (18446744073709551616, 1)",
-  "Instructions": {
-    "OperatorType": "Route",
-    "Variant": "SelectScatter",
-    "Keyspace": {
-      "Name": "user",
-      "Sharded": true
-    },
-    "FieldQuery": "select id from `user` where 1 != 1",
-    "Query": "select id from `user` where id in (18446744073709551616, 1)",
-    "Table": "`user`"
-  }
-}
+Gen4 plan same as above
 
 # Invalid value in IN clause from LHS of join
 "select u1.id from user u1 join user u2 where u1.id = 18446744073709551616"
 "strconv.ParseUint: parsing "18446744073709551616": value out of range"
-{
-  "QueryType": "SELECT",
-  "Original": "select u1.id from user u1 join user u2 where u1.id = 18446744073709551616",
-  "Instructions": {
-    "OperatorType": "Join",
-    "Variant": "Join",
-    "JoinColumnIndexes": "-1",
-    "TableName": "`user`_`user`",
-    "Inputs": [
-      {
-        "OperatorType": "Route",
-        "Variant": "SelectScatter",
-        "Keyspace": {
-          "Name": "user",
-          "Sharded": true
-        },
-        "FieldQuery": "select u1.id from `user` as u1 where 1 != 1",
-        "Query": "select u1.id from `user` as u1 where u1.id = 18446744073709551616",
-        "Table": "`user`"
-      },
-      {
-        "OperatorType": "Route",
-        "Variant": "SelectScatter",
-        "Keyspace": {
-          "Name": "user",
-          "Sharded": true
-        },
-        "FieldQuery": "select 1 from `user` as u2 where 1 != 1",
-        "Query": "select 1 from `user` as u2",
-        "Table": "`user`"
-      }
-    ]
-  }
-}
+Gen4 plan same as above
 
 # Invalid value in IN clause from RHS of join
 "select u1.id from user u1 join user u2 where u2.id = 18446744073709551616"
 "strconv.ParseUint: parsing "18446744073709551616": value out of range"
-{
-  "QueryType": "SELECT",
-  "Original": "select u1.id from user u1 join user u2 where u2.id = 18446744073709551616",
-  "Instructions": {
-    "OperatorType": "Join",
-    "Variant": "Join",
-    "JoinColumnIndexes": "-1",
-    "TableName": "`user`_`user`",
-    "Inputs": [
-      {
-        "OperatorType": "Route",
-        "Variant": "SelectScatter",
-        "Keyspace": {
-          "Name": "user",
-          "Sharded": true
-        },
-        "FieldQuery": "select u1.id from `user` as u1 where 1 != 1",
-        "Query": "select u1.id from `user` as u1",
-        "Table": "`user`"
-      },
-      {
-        "OperatorType": "Route",
-        "Variant": "SelectScatter",
-        "Keyspace": {
-          "Name": "user",
-          "Sharded": true
-        },
-        "FieldQuery": "select 1 from `user` as u2 where 1 != 1",
-        "Query": "select 1 from `user` as u2 where u2.id = 18446744073709551616",
-        "Table": "`user`"
-      }
-    ]
-  }
-}
+Gen4 plan same as above
diff --git a/go/vt/vttablet/tabletmanager/vreplication/replicator_plan_test.go b/go/vt/vttablet/tabletmanager/vreplication/replicator_plan_test.go
index fc1736dc5b..f935dea320 100644
--- a/go/vt/vttablet/tabletmanager/vreplication/replicator_plan_test.go
+++ b/go/vt/vttablet/tabletmanager/vreplication/replicator_plan_test.go
@@ -327,7 +327,7 @@ func TestBuildPlayerPlan(t *testing.T) {
 			VStreamFilter: &binlogdatapb.Filter{
 				Rules: []*binlogdatapb.Rule{{
 					Match:  "t1",
-					Filter: "select a, b, c from t1",
+					Filter: "select a, a, b, c from t1",
 				}},
 			},
 			TargetTables: []string{"t1"},
@@ -348,7 +348,7 @@ func TestBuildPlayerPlan(t *testing.T) {
 			VStreamFilter: &binlogdatapb.Filter{
 				Rules: []*binlogdatapb.Rule{{
 					Match:  "t1",
-					Filter: "select a, b, c, pk1, pk2 from t1",
+					Filter: "select a, a, b, c, pk1, pk2 from t1",
 				}},
 			},
 			TargetTables: []string{"t1"},
diff --git a/go/vt/vttablet/tabletmanager/vreplication/vcopier_test.go b/go/vt/vttablet/tabletmanager/vreplication/vcopier_test.go
index 8e3d13ec47..2487391124 100644
--- a/go/vt/vttablet/tabletmanager/vreplication/vcopier_test.go
+++ b/go/vt/vttablet/tabletmanager/vreplication/vcopier_test.go
@@ -447,7 +447,7 @@ func TestPlayerCopyTables(t *testing.T) {
 	execStatements(t, []string{
 		"create table src1(id int, val varbinary(128), primary key(id))",
 		"insert into src1 values(2, 'bbb'), (1, 'aaa')",
-		fmt.Sprintf("create table %s.dst1(id int, val varbinary(128), primary key(id))", vrepldb),
+		fmt.Sprintf("create table %s.dst1(id int, val varbinary(128), val2 varbinary(128), primary key(id))", vrepldb),
 		"create table yes(id int, val varbinary(128), primary key(id))",
 		fmt.Sprintf("create table %s.yes(id int, val varbinary(128), primary key(id))", vrepldb),
 		"create table no(id int, val varbinary(128), primary key(id))",
@@ -464,7 +464,7 @@ func TestPlayerCopyTables(t *testing.T) {
 	filter := &binlogdatapb.Filter{
 		Rules: []*binlogdatapb.Rule{{
 			Match:  "dst1",
-			Filter: "select * from src1",
+			Filter: "select id, val, val as val2 from src1",
 		}, {
 			Match: "/yes",
 		}},
@@ -500,7 +500,7 @@ func TestPlayerCopyTables(t *testing.T) {
 		// The first fast-forward has no starting point. So, it just saves the current position.
 		"/update _vt.vreplication set pos=",
 		"begin",
-		"insert into dst1(id,val) values (1,'aaa'), (2,'bbb')",
+		"insert into dst1(id,val,val2) values (1,'aaa','aaa'), (2,'bbb','bbb')",
 		`/update _vt.copy_state set lastpk='fields:{name:\\"id\\" type:INT32} rows:{lengths:1 values:\\"2\\"}' where vrepl_id=.*`,
 		"commit",
 		// copy of dst1 is done: delete from copy_state.
@@ -515,8 +515,8 @@ func TestPlayerCopyTables(t *testing.T) {
 		"/update _vt.vreplication set state='Running'",
 	})
 	expectData(t, "dst1", [][]string{
-		{"1", "aaa"},
-		{"2", "bbb"},
+		{"1", "aaa", "aaa"},
+		{"2", "bbb", "bbb"},
 	})
 	expectData(t, "yes", [][]string{})
 	validateCopyRowCountStat(t, 2)
diff --git a/go/vt/vttablet/tabletmanager/vreplication/vplayer_flaky_test.go b/go/vt/vttablet/tabletmanager/vreplication/vplayer_flaky_test.go
index 73e9582b9a..189973afb8 100644
--- a/go/vt/vttablet/tabletmanager/vreplication/vplayer_flaky_test.go
+++ b/go/vt/vttablet/tabletmanager/vreplication/vplayer_flaky_test.go
@@ -482,7 +482,7 @@ func TestPlayerFilters(t *testing.T) {
 		"create table src5(id1 int, id2 int, val varbinary(128), primary key(id1))",
 		fmt.Sprintf("create table %s.dst5(id1 int, val varbinary(128), primary key(id1))", vrepldb),
 		"create table srcCharset(id1 int, val varchar(128) character set utf8mb4 collate utf8mb4_bin, primary key(id1))",
-		fmt.Sprintf("create table %s.dstCharset(id1 int, val varchar(128) character set utf8mb4 collate utf8mb4_bin, primary key(id1))", vrepldb),
+		fmt.Sprintf("create table %s.dstCharset(id1 int, val varchar(128) character set utf8mb4 collate utf8mb4_bin, val2 varchar(128) character set utf8mb4 collate utf8mb4_bin, primary key(id1))", vrepldb),
 	})
 	defer execStatements(t, []string{
 		"drop table src1",
@@ -527,7 +527,7 @@ func TestPlayerFilters(t *testing.T) {
 			Filter: "select id1, val from src5 where val = 'abc'",
 		}, {
 			Match:  "dstCharset",
-			Filter: "select id1, concat(substr(_utf8mb4 val collate utf8mb4_bin,1,1),'abcxyz') val from srcCharset",
+			Filter: "select id1, concat(substr(_utf8mb4 val collate utf8mb4_bin,1,1),'abcxyz') val, concat(substr(_utf8mb4 val collate utf8mb4_bin,1,1),'abcxyz') val2 from srcCharset",
 		}},
 	}
 	bls := &binlogdatapb.BinlogSource{
@@ -778,12 +778,12 @@ func TestPlayerFilters(t *testing.T) {
 		input: "insert into srcCharset values (1,'木元')",
 		output: []string{
 			"begin",
-			"insert into dstCharset(id1,val) values (1,concat(substr(_utf8mb4 '木元' collate utf8mb4_bin, 1, 1), 'abcxyz'))",
+			"insert into dstCharset(id1,val,val2) values (1,concat(substr(_utf8mb4 '木元' collate utf8mb4_bin, 1, 1), 'abcxyz'),concat(substr(_utf8mb4 '木元' collate utf8mb4_bin, 1, 1), 'abcxyz'))",
 			"/update _vt.vreplication set pos=",
 			"commit",
 		},
 		table: "dstCharset",
-		data:  [][]string{{"1", "木abcxyz"}},
+		data:  [][]string{{"1", "木abcxyz", "木abcxyz"}},
 	}}
 
 	for _, tcase := range testcases {
diff --git a/test/config.json b/test/config.json
index 2f5a69543c..1d5401ea2e 100644
--- a/test/config.json
+++ b/test/config.json
@@ -997,7 +997,7 @@
 		},
 		"vreplication_materialize": {
 			"File": "unused.go",
-			"Args": ["vitess.io/vitess/go/test/endtoend/vreplication", "-run", "ShardedMaterialize"],
+			"Args": ["vitess.io/vitess/go/test/endtoend/vreplication", "-run", "TestMaterialize"],
 			"Command": [],
 			"Manual": false,
 			"Shard": "vreplication_multicell",