bytebase/bytebase · error
pseudo constant select: expected SelectStmt, got %T
Error message
pseudo constant select: expected SelectStmt, got %T
What it means
wtPseudoConstantSelect parses a SQL string meant to be a 'pseudo constant' (a plain SELECT) and expects the top-level statement to be a SelectStmt. After unwrapping the RawStmt wrapper, the first statement's concrete AST node type did not match *ast.SelectStmt. This is an internal contract violation: the caller passed SQL whose statement kind is not a simple SELECT, so the loader cannot safely continue walking the AST.
Source
Thrown at backend/plugin/schema/pg/walk_through_loader.go:1068
}
if len(targets) == 0 {
targets = []string{"NULL::text"}
}
sql := "SELECT " + strings.Join(targets, ", ")
nodes, err := omniparser.Parse(sql)
if err != nil {
return nil, errors.Wrap(err, "parse pseudo constant select")
}
if nodes == nil || len(nodes.Items) != 1 {
return nil, errors.New("pseudo constant select: expected 1 statement")
}
node := nodes.Items[0]
if raw, ok := node.(*ast.RawStmt); ok {
node = raw.Stmt
}
sel, ok := node.(*ast.SelectStmt)
if !ok {
return nil, errors.Errorf("pseudo constant select: expected SelectStmt, got %T", node)
}
return sel, nil
}
// ---- column name helpers ----
func wtColNames(tbl *storepb.TableMetadata) []string {
if tbl == nil {
return nil
}
seen := make(map[string]bool, len(tbl.Columns))
out := make([]string, 0, len(tbl.Columns))
for _, col := range tbl.Columns {
if col.Name == "" || seen[col.Name] {
continue
}
seen[col.Name] = true
out = append(out, col.Name)View on GitHub (pinned to 1870550677)
Solutions
- Inspect the SQL string passed in and ensure the first statement is exactly one plain SELECT statement.
- Strip wrapper statements (semicolons, EXPLAIN, extra statements) so only the SELECT body remains.
- Log the offending %T value from the error to see which AST node actually arrived and adjust the caller accordingly.
- If non-SELECT pseudo constants must be supported, extend wtPseudoConstantSelect to handle that node type instead of erroring.
Example fix
// before return wtPseudoConstantSelect(ctx, "CREATE VIEW v AS SELECT 1") // after return wtPseudoConstantSelect(ctx, "SELECT 1")
Defensive patterns
Strategy: validation
Validate before calling
func isSingleSelect(sql string) bool {
trimmed := strings.TrimSpace(strings.TrimSuffix(strings.TrimSpace(sql), ";"))
return strings.HasPrefix(strings.ToLower(trimmed), "select ") && !strings.Contains(trimmed, ";")
}
// call wtPseudoConstantSelect only if isSingleSelect(sql) Type guard
sel, ok := node.(*ast.SelectStmt)
if !ok { return fmt.Errorf("unexpected node %T", node) } Try / catch
sel, err := wtPseudoConstantSelect(ctx, sql)
if err != nil {
return fmt.Errorf("pseudo constant %q: %w", sql, err)
} Prevention
- Only pass bare SELECT bodies (view definitions, not CREATE VIEW statements) to this loader.
- Strip trailing semicolons and extra statements before invoking walkthrough loaders.
- Log the offending AST node type whenever this family of errors fires.
When it happens
Trigger: Calling wtPseudoConstantSelect (directly or via wtPseudoViewStmt/wtPseudoMatViewStmt) with SQL that parses to a non-SELECT statement, e.g. an INSERT, a utility statement (SET, VACUUM), a multi-statement string where the first item is not a SELECT, or empty/placeholder text that the parser still returns as some other node type.
Common situations: A walkthrough definition file contains a view body or materialized-view definition stored in a non-SELECT form; a typo or edited fixture replaced the SELECT with another statement; a multi-statement SQL blob was passed where only the SELECT body was expected.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- type %q: expected SelectStmt, got %T
- type %q: expected ResTarget, got %T
- type %q: expected TypeCast, got %T
- default %q: expected SelectStmt
- statement yielded no parse tree
AI-assisted analysis of bytebase/bytebase@1870550677 (2026-09-06).
Data as JSON: /api/errors/484b0e40b3d7ebf0.
Report an issue: GitHub.