{"record":{"id":"41075b01d9c76393","repo":"vitessio/vitess","slug":"vtexplain-unsupported-statement-type-v","errorCode":null,"errorMessage":"vtexplain: unsupported statement type +%v","messagePattern":"vtexplain: unsupported statement type \\+(.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vtexplain/vtexplain_vttablet.go","lineNumber":628,"sourceCode":"\t// Parse the select statement to figure out the table and columns\n\t// that were referenced so that the synthetic response has the\n\t// expected field names and types.\n\tstmt, err := t.vte.env.Parser().Parse(query)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar selStmt *sqlparser.Select\n\tswitch stmt := stmt.(type) {\n\tcase *sqlparser.Select:\n\t\tselStmt = stmt\n\tcase *sqlparser.Union:\n\t\tselStmt, err = sqlparser.GetFirstSelect(stmt)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"vtexplain: unsupported statement type +%v\", reflect.TypeOf(stmt))\n\t}\n\n\t// Gen4 supports more complex queries so we now need to\n\t// handle multiple FROM clauses\n\ttables := make([]*sqlparser.AliasedTableExpr, 0, len(selStmt.From))\n\tfor _, from := range selStmt.From {\n\t\ttables = append(tables, getTables(from)...)\n\t}\n\n\ttableColumnMap := map[sqlparser.IdentifierCS]map[string]querypb.Type{}\n\tfor _, table := range tables {\n\t\tif table == nil {\n\t\t\tcontinue\n\t\t}\n\n\t\ttableName := sqlparser.String(sqlparser.GetTableName(table.Expr))\n\t\tcolumns, exists := t.vte.getGlobalTabletEnv().tableColumns[tableName]\n\t\tif !exists && tableName != \"\" {","sourceCodeStart":610,"sourceCodeEnd":646,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vtexplain/vtexplain_vttablet.go#L610-L646","documentation":"In handleSelect, vtexplain accepts only *sqlparser.Select, *sqlparser.ParenSelect and *sqlparser.Union as the statement to analyze; any other AST node type falls into the default branch and is rejected with this message including the reflect type. It is an internal guard for the select-explaining path.","triggerScenarios":"A statement typed as select-like but whose AST is none of Select/ParenSelect/Union (e.g. a SHOW or other statement that reached handleSelect), producing reflect type output in the error.","commonSituations":"Routing bugs in tools built on vtexplain; newer parser statement kinds not yet handled; passing arbitrary statements into the explain-select path programmatically.","solutions":["Ensure only SELECT/UNION statements reach handleSelect.","Update vtexplain to handle the new statement AST type in the switch.","Use HandleQuery which routes by statement type instead of calling handleSelect directly."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"switch stmt.(type) {\ncase *sqlparser.Select, *sqlparser.ParenSelect, *sqlparser.Union:\n    // safe to pass to handleSelect\ndefault:\n    return fmt.Errorf(\"not a select: %T\", stmt)\n}","typeGuard":"func isExplainableSelect(stmt sqlparser.Statement) bool {\n    switch stmt.(type) {\n    case *sqlparser.Select, *sqlparser.ParenSelect, *sqlparser.Union:\n        return true\n    }\n    return false\n}","tryCatchPattern":"res, err := tablet.handleSelect(query)\nif err != nil {\n    if strings.Contains(err.Error(), \"unsupported statement type\") {\n        // route to a different handler or skip\n    }\n}","preventionTips":["Route statements by sqlparser.Preview before invoking handleSelect.","Handle new parser statement types when upgrading Vitess.","Only call handleSelect via HandleQuery routing."],"tags":["vtexplain","sqlparser","unsupported-statement"],"backgroundTag":"unsupported-statement-type","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}