diff --git a/go/cmd/vtexplain/vtexplain.go b/go/cmd/vtexplain/vtexplain.go index f2f1ea4bf42..ba87015a739 100644 --- a/go/cmd/vtexplain/vtexplain.go +++ b/go/cmd/vtexplain/vtexplain.go @@ -17,7 +17,6 @@ limitations under the License. package main import ( - "flag" "fmt" "os" @@ -28,62 +27,50 @@ import ( "vitess.io/vitess/go/vt/vtexplain" "vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext" + "github.com/spf13/pflag" + querypb "vitess.io/vitess/go/vt/proto/query" - // Include deprecation warnings for soon-to-be-unsupported flag invocations. - _flag "vitess.io/vitess/go/internal/flag" ) var ( - sqlFlag = flag.String("sql", "", "A list of semicolon-delimited SQL commands to analyze") - sqlFileFlag = flag.String("sql-file", "", "Identifies the file that contains the SQL commands to analyze") - schemaFlag = flag.String("schema", "", "The SQL table schema") - schemaFileFlag = flag.String("schema-file", "", "Identifies the file that contains the SQL table schema") - vschemaFlag = flag.String("vschema", "", "Identifies the VTGate routing schema") - vschemaFileFlag = flag.String("vschema-file", "", "Identifies the VTGate routing schema file") - ksShardMapFlag = flag.String("ks-shard-map", "", "JSON map of keyspace name -> shard name -> ShardReference object. The inner map is the same as the output of FindAllShardsInKeyspace") - ksShardMapFileFlag = flag.String("ks-shard-map-file", "", "File containing json blob of keyspace name -> shard name -> ShardReference object") - numShards = flag.Int("shards", 2, "Number of shards per keyspace. Passing --ks-shard-map/--ks-shard-map-file causes this flag to be ignored.") - executionMode = flag.String("execution-mode", "multi", "The execution mode to simulate -- must be set to multi, legacy-autocommit, or twopc") - replicationMode = flag.String("replication-mode", "ROW", "The replication mode to simulate -- must be set to either ROW or STATEMENT") - 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", "", "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", - "schema", - "schema-file", - "sql", - "sql-file", - "vschema", - "vschema-file", - "ks-shard-map", - "ks-shard-map-file", - "dbname", - "queryserver-config-passthrough-dmls", - } + sqlFlag string + sqlFileFlag string + schemaFlag string + schemaFileFlag string + vschemaFlag string + vschemaFileFlag string + ksShardMapFlag string + ksShardMapFileFlag string + normalize bool + dbName string + plannerVersionStr string + + numShards = 2 + replicationMode = "ROW" + executionMode = "multi" + outputMode = "text" ) +func registerFlags(fs *pflag.FlagSet) { + fs.StringVar(&sqlFlag, "sql", sqlFlag, "A list of semicolon-delimited SQL commands to analyze") + fs.StringVar(&sqlFileFlag, "sql-file", sqlFileFlag, "Identifies the file that contains the SQL commands to analyze") + fs.StringVar(&schemaFlag, "schema", schemaFlag, "The SQL table schema") + fs.StringVar(&schemaFileFlag, "schema-file", schemaFileFlag, "Identifies the file that contains the SQL table schema") + fs.StringVar(&vschemaFlag, "vschema", vschemaFlag, "Identifies the VTGate routing schema") + fs.StringVar(&vschemaFileFlag, "vschema-file", vschemaFileFlag, "Identifies the VTGate routing schema file") + fs.StringVar(&ksShardMapFlag, "ks-shard-map", ksShardMapFlag, "JSON map of keyspace name -> shard name -> ShardReference object. The inner map is the same as the output of FindAllShardsInKeyspace") + fs.StringVar(&ksShardMapFileFlag, "ks-shard-map-file", ksShardMapFileFlag, "File containing json blob of keyspace name -> shard name -> ShardReference object") + fs.StringVar(&replicationMode, "replication-mode", replicationMode, "The replication mode to simulate -- must be set to either ROW or STATEMENT") + fs.BoolVar(&normalize, "normalize", normalize, "Whether to enable vtgate normalization") + fs.StringVar(&dbName, "dbname", dbName, "Optional database target to override normal routing") + fs.StringVar(&plannerVersionStr, "planner-version", plannerVersionStr, "Sets the query planner version to use when generating the explain output. Valid values are V3 and Gen4") + fs.IntVar(&numShards, "shards", numShards, "Number of shards per keyspace. Passing --ks-shard-map/--ks-shard-map-file causes this flag to be ignored.") + fs.StringVar(&executionMode, "execution-mode", executionMode, "The execution mode to simulate -- must be set to multi, legacy-autocommit, or twopc") + fs.StringVar(&outputMode, "output-mode", outputMode, "Output in human-friendly text or json") +} + func init() { - logger := logutil.NewConsoleLogger() - flag.CommandLine.SetOutput(logutil.NewLoggerWriter(logger)) - _flag.SetUsage(flag.CommandLine, _flag.UsageOptions{ - FlagFilter: func(f *flag.Flag) bool { - for _, name := range vtexplainFlags { - if f.Name == name { - return true - } - } - - return false - }, - }) + servenv.OnParse(registerFlags) } // getFileParam returns a string containing either flag is not "", @@ -123,38 +110,38 @@ func main() { } func parseAndRun() error { - plannerVersion, _ := plancontext.PlannerNameToVersion(*plannerVersionStr) + plannerVersion, _ := plancontext.PlannerNameToVersion(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) + return fmt.Errorf("invalid value specified for planner-version of '%s' -- valid values are V3 and Gen4", plannerVersionStr) } - sql, err := getFileParam(*sqlFlag, *sqlFileFlag, "sql", true) + sql, err := getFileParam(sqlFlag, sqlFileFlag, "sql", true) if err != nil { return err } - schema, err := getFileParam(*schemaFlag, *schemaFileFlag, "schema", true) + schema, err := getFileParam(schemaFlag, schemaFileFlag, "schema", true) if err != nil { return err } - vschema, err := getFileParam(*vschemaFlag, *vschemaFileFlag, "vschema", true) + vschema, err := getFileParam(vschemaFlag, vschemaFileFlag, "vschema", true) if err != nil { return err } - ksShardMap, err := getFileParam(*ksShardMapFlag, *ksShardMapFileFlag, "ks-shard-map", false) + ksShardMap, err := getFileParam(ksShardMapFlag, ksShardMapFileFlag, "ks-shard-map", false) if err != nil { return err } opts := &vtexplain.Options{ - ExecutionMode: *executionMode, + ExecutionMode: executionMode, PlannerVersion: plannerVersion, - ReplicationMode: *replicationMode, - NumShards: *numShards, - Normalize: *normalize, - Target: *dbName, + ReplicationMode: replicationMode, + NumShards: numShards, + Normalize: normalize, + Target: dbName, } log.V(100).Infof("sql %s\n", sql) @@ -172,7 +159,7 @@ func parseAndRun() error { return err } - if *outputMode == "text" { + if outputMode == "text" { fmt.Print(vte.ExplainsAsText(plans)) } else { fmt.Print(vtexplain.ExplainsAsJSON(plans))