diff --git a/go/cmd/vtexplain/vtexplain.go b/go/cmd/vtexplain/vtexplain.go index 8e29126f648..49b840458ef 100644 --- a/go/cmd/vtexplain/vtexplain.go +++ b/go/cmd/vtexplain/vtexplain.go @@ -26,6 +26,8 @@ import ( "vitess.io/vitess/go/vt/logutil" "vitess.io/vitess/go/vt/servenv" "vitess.io/vitess/go/vt/vtexplain" + + querypb "vitess.io/vitess/go/vt/proto/query" ) var ( @@ -43,10 +45,12 @@ var ( normalize = flag.Bool("normalize", false, "Whether to enable vtgate normalization") outputMode = flag.String("output-mode", "text", "Output in human-friendly text or json") dbName = flag.String("dbname", "", "Optional database target to override normal routing") + plannerVersionStr = flag.String("planner-version", "V3", "Sets the query planner version to use when generating the explain output. Valid values are V3 and Gen4") // vtexplainFlags lists all the flags that should show in usage vtexplainFlags = []string{ "output-mode", + "planner-version", "normalize", "shards", "replication-mode", @@ -165,8 +169,14 @@ func parseAndRun() error { return err } + plannerVersion := querypb.ExecuteOptions_PlannerVersion(querypb.ExecuteOptions_PlannerVersion_value[*plannerVersionStr]) + if plannerVersion != querypb.ExecuteOptions_V3 && plannerVersion != querypb.ExecuteOptions_Gen4 { + return fmt.Errorf("invalid value specified for planner-version of '%s' -- valid values are V3 and Gen4", *plannerVersionStr) + } + opts := &vtexplain.Options{ ExecutionMode: *executionMode, + PlannerVersion: plannerVersion, ReplicationMode: *replicationMode, NumShards: *numShards, Normalize: *normalize, diff --git a/go/vt/vtexplain/vtexplain.go b/go/vt/vtexplain/vtexplain.go index 3dee8d40515..ecc7711f259 100644 --- a/go/vt/vtexplain/vtexplain.go +++ b/go/vt/vtexplain/vtexplain.go @@ -58,6 +58,9 @@ type Options struct { // NumShards indicates the number of shards in the topology NumShards int + // PlannerVersion indicates whether or not we should use the Gen4 planner + PlannerVersion querypb.ExecuteOptions_PlannerVersion + // ReplicationMode must be set to either "ROW" or "STATEMENT" before // initialization ReplicationMode string diff --git a/go/vt/vtexplain/vtexplain_vtgate.go b/go/vt/vtexplain/vtexplain_vtgate.go index 01fb342ae74..52a287f153a 100644 --- a/go/vt/vtexplain/vtexplain_vtgate.go +++ b/go/vt/vtexplain/vtexplain_vtgate.go @@ -38,6 +38,7 @@ import ( "vitess.io/vitess/go/vt/vtgate/engine" "vitess.io/vitess/go/vt/vttablet/queryservice" + querypb "vitess.io/vitess/go/vt/proto/query" topodatapb "vitess.io/vitess/go/vt/proto/topodata" vschemapb "vitess.io/vitess/go/vt/proto/vschema" vtgatepb "vitess.io/vitess/go/vt/proto/vtgate" @@ -68,6 +69,13 @@ func initVtgateExecutor(vSchemaStr, ksShardMapStr string, opts *Options) error { vtgateSession.TargetString = opts.Target + if opts.PlannerVersion != querypb.ExecuteOptions_DEFAULT_PLANNER { + if vtgateSession.Options == nil { + vtgateSession.Options = &querypb.ExecuteOptions{} + } + vtgateSession.Options.PlannerVersion = opts.PlannerVersion + } + streamSize := 10 var schemaTracker vtgate.SchemaInfo // no schema tracker for these tests vtgateExecutor = vtgate.NewExecutor(context.Background(), explainTopo, vtexplainCell, resolver, opts.Normalize, false /*do not warn for sharded only*/, streamSize, cache.DefaultConfig, schemaTracker, false /*no-scatter*/) diff --git a/go/vt/vtexplain/vtexplain_vttablet.go b/go/vt/vtexplain/vtexplain_vttablet.go index 348b6334a97..eec4c06b263 100644 --- a/go/vt/vtexplain/vtexplain_vttablet.go +++ b/go/vt/vtexplain/vtexplain_vttablet.go @@ -506,11 +506,12 @@ func (t *explainTablet) HandleQuery(c *mysql.Conn, query string, callback func(* return fmt.Errorf("vtexplain: unsupported statement type +%v", reflect.TypeOf(stmt)) } - if len(selStmt.From) != 1 { - return fmt.Errorf("unsupported select with multiple from clauses") + // Gen4 supports more complex queries so we now need to + // handle multiple FROM clauses + tables := make([]sqlparser.TableIdent, len(selStmt.From)) + for _, from := range selStmt.From { + tables = append(tables, getTables(from)...) } - - tables := getTables(selStmt.From[0]) colTypeMap := map[string]querypb.Type{} for _, table := range tables { tableName := sqlparser.String(table)