{"record":{"id":"3edb52bada81843c","repo":"bytebase/bytebase","slug":"unsupported-statement-in-query-span-extractor-t","errorCode":null,"errorMessage":"unsupported statement in query span extractor: %T","messagePattern":"unsupported statement in query span extractor: %T","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/plugin/parser/plsql/query_span_extractor_omni.go","lineNumber":434,"sourceCode":"\t\t\tcolumns = next\n\t\t}\n\t\treturn &base.PseudoTable{Name: name, Columns: columns}, nil\n\t}\n\n\tchild := q.clone()\n\ttableSource, err := child.extractOmniStmt(cte.Query)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tcolumns := cloneQuerySpanResults(tableSource.GetQuerySpanResult())\n\tapplyOmniColumnAliases(columns, columnNames)\n\treturn &base.PseudoTable{Name: name, Columns: columns}, nil\n}\n\nfunc (q *omniQuerySpanExtractor) extractOmniStmt(stmt oracleast.StmtNode) (base.TableSource, error) {\n\tselectStmt, ok := stmt.(*oracleast.SelectStmt)\n\tif !ok {\n\t\treturn nil, errors.Errorf(\"unsupported statement in query span extractor: %T\", stmt)\n\t}\n\treturn q.extractOmniSelect(selectStmt)\n}\n\nfunc (q *omniQuerySpanExtractor) extractOmniTargetList(list *oracleast.List) ([]base.QuerySpanResult, error) {\n\tif list == nil || list.Len() == 0 {\n\t\treturn q.expandOmniAsterisk(\"\", \"\")\n\t}\n\n\tvar results []base.QuerySpanResult\n\tfor _, node := range listItems(list) {\n\t\ttarget, ok := node.(*oracleast.ResTarget)\n\t\tif !ok || target.Expr == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif isOmniStar(target.Expr) {\n\t\t\texpanded, err := q.expandOmniAsterisk(\"\", \"\")\n\t\t\tif err != nil {","sourceCodeStart":416,"sourceCodeEnd":452,"githubUrl":"https://github.com/bytebase/bytebase/blob/1870550677fe08f0d2a78c07acd27541464eb945/backend/plugin/parser/plsql/query_span_extractor_omni.go#L416-L452","documentation":"extractOmniStmt is the generic statement dispatch for the span extractor and only accepts *oracleast.SelectStmt; any other StmtNode type hits this error naming the concrete type. It signals an internal capability gap rather than a syntax problem — the SQL parsed fine.","triggerScenarios":"A subquery/statement node that is not a SelectStmt (e.g. another statement wrapper type) reaches extractOmniStmt during span extraction, typically from CTE bodies, derived tables, or sub-selects parsed into a different node type.","commonSituations":"Grammar changes reclassifying constructs into new AST node types without updating the extractor; nested DML-with-RETURNING or cursor expressions hitting the extractor; callers passing whole scripts whose first node is not a plain SELECT.","solutions":["Add a case for the offending AST type in extractOmniStmt (or unwrap it to its inner SelectStmt)","Confirm the construct should really be a SELECT; if it is a new wrapper node, extend the extractor to dereference it","Report/fix the grammar-to-extractor mismatch in the omni parser package"],"exampleFix":"// before\nselectStmt, ok := stmt.(*oracleast.SelectStmt)\nif !ok { return nil, errors.Errorf(...) }\n// after\nswitch s := stmt.(type) {\ncase *oracleast.SelectStmt:\n    return q.extractOmniSelect(s)\ncase *oracleast.SubqueryWrapper:\n    return q.extractOmniStmt(s.Stmt)\ndefault:\n    return nil, errors.Errorf(\"unsupported statement in query span extractor: %T\", stmt)\n}","handlingStrategy":"type-guard","validationCode":"list, _ := ParsePLSQLOmni(stmt)\nraw := list.Items[0].(*oracleast.RawStmt)\nif _, ok := raw.Stmt.(*oracleast.SelectStmt); !ok { /* skip extraction */ }","typeGuard":"func asSelectStmt(node oracleast.StmtNode) (*oracleast.SelectStmt, bool) {\n    s, ok := node.(*oracleast.SelectStmt)\n    return s, ok\n}","tryCatchPattern":"src, err := extractor.GetQuerySpan(ctx, stmt)\nif err != nil && strings.Contains(err.Error(), \"unsupported statement in query span extractor\") {\n    return nil, errUnsupportedStatementType\n}","preventionTips":["Keep the extractor's dispatch switch in sync with grammar node types","Add switch-case tests for every AST statement type","Unwrap wrapper nodes to their inner SELECT before dispatch"],"tags":["plsql","parser","unsupported-node"],"backgroundTag":"unsupported-operation","analyzedSha":"1870550677fe08f0d2a78c07acd27541464eb945","analyzedAt":"2026-09-06T21:16:13.665Z","contentChangedAt":"2026-09-06T21:16:13.665Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}