vitessio/vitess · error
unsupported qualifier for column: %v
Error message
unsupported qualifier for column: %v
What it means
When walking a CONVERT(...) USING style expression, the builder collects the single column being converted. Any column reference with a qualifier (e.g. `t.col`) is rejected because the generated plan rewrites the expression against one fixed table and qualified names would not resolve there.
Source
Thrown at go/vt/vttablet/tabletmanager/vreplication/table_plan_builder.go:458
return nil, fmt.Errorf("expression needs an alias: %v", sqlparser.String(aliased))
}
}
cexpr := &colExpr{
colName: as,
references: make(map[string]bool),
}
if expr, ok := aliased.Expr.(*sqlparser.ConvertUsingExpr); ok {
// Here we find the actual column name in the convert, in case
// this is a column rename and the AS is the new column.
// For example, in convert(c1 using utf8mb4) as c2, we want to find
// c1, because c1 exists in the current table whereas c2 is the renamed column
// in the desired table.
var colName sqlparser.IdentifierCI
err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) {
switch node := node.(type) {
case *sqlparser.ColName:
if !node.Qualifier.IsEmpty() {
return false, fmt.Errorf("unsupported qualifier for column: %v", sqlparser.String(node))
}
colName = node.Name
}
return true, nil
}, aliased.Expr)
if err != nil {
return nil, fmt.Errorf("failed to find column name for convert using expression: %v, %v", sqlparser.String(aliased.Expr), err)
}
selExpr := &sqlparser.ConvertUsingExpr{
Type: "utf8mb4",
Expr: &sqlparser.ColName{Name: colName},
}
cexpr.expr = expr
cexpr.operation = opExpr
tpb.sendSelect.AddSelectExpr(&sqlparser.AliasedExpr{Expr: selExpr, As: as})
cexpr.references[as.String()] = true
return cexpr, nil
}View on GitHub (pinned to 01a25a7d17)
Solutions
- Remove the table qualifier inside CONVERT USING: use `CONVERT(name USING utf8mb4)`
- Ensure the CONVERT USING expression references exactly one unqualified column
- Regenerate the filter rule after editing
Example fix
// before SELECT CONVERT(t.name USING utf8mb4) AS name FROM t // after SELECT CONVERT(name USING utf8mb4) AS name FROM t
Defensive patterns
Strategy: validation
Validate before calling
sqlparser.Walk(func(n sqlparser.SQLNode) (bool, error) {
if cn, ok := n.(*sqlparser.ColName); ok && !cn.Qualifier.IsEmpty() {
return false, fmt.Errorf("qualified column %v not allowed", sqlparser.String(cn))
}
return true, nil
}, aliased.Expr) Type guard
func unqualifiedOnly(expr sqlparser.Expr) bool {
err := sqlparser.Walk(func(n sqlparser.SQLNode) (bool, error) {
if cn, ok := n.(*sqlparser.ColName); ok && !cn.Qualifier.IsEmpty() {
return false, fmt.Errorf("qualified")
}
return true, nil
}, expr)
return err == nil
} Prevention
- Strip table qualifiers when authoring CONVERT USING filter expressions
- Keep filter SQL single-table so qualifiers are unnecessary
- Test filter rules against the plan builder in CI
When it happens
Trigger: A select expression like `CONVERT(t.name USING utf8mb4)` — the inner ColName carries a table qualifier.
Common situations: Copy-pasted queries from application SQL that qualify columns; generated plans where the source query used aliases.
Related errors
- failed to find column name for convert using expression: %v,
- unsupported from expression (%T)
- unsupported from source (%T)
- invalid expression: %v
- expression needs an alias: %v
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/ccfbb355c051a9a9.
Report an issue: GitHub.