{"record":{"id":"3e43caead2d57a39","repo":"vitessio/vitess","slug":"expression-needs-an-alias-v-3e43ca","errorCode":null,"errorMessage":"expression needs an alias: %v","messagePattern":"expression needs an alias: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vttablet/tabletmanager/vreplication/table_plan_builder.go","lineNumber":440,"sourceCode":"\t\t\treturn err\n\t\t}\n\t\ttpb.colExprs = append(tpb.colExprs, cexpr)\n\t}\n\treturn nil\n}\n\nfunc (tpb *tablePlanBuilder) analyzeExpr(selExpr sqlparser.SelectExpr) (*colExpr, error) {\n\taliased, ok := selExpr.(*sqlparser.AliasedExpr)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"invalid expression: %v\", sqlparser.String(selExpr))\n\t}\n\tas := aliased.As\n\tif as.IsEmpty() {\n\t\t// Require all non-trivial expressions to have an alias.\n\t\tif colAs, ok := aliased.Expr.(*sqlparser.ColName); ok && colAs.Qualifier.IsEmpty() {\n\t\t\tas = colAs.Name\n\t\t} else {\n\t\t\treturn nil, fmt.Errorf(\"expression needs an alias: %v\", sqlparser.String(aliased))\n\t\t}\n\t}\n\tcexpr := &colExpr{\n\t\tcolName:    as,\n\t\treferences: make(map[string]bool),\n\t}\n\tif expr, ok := aliased.Expr.(*sqlparser.ConvertUsingExpr); ok {\n\t\t// Here we find the actual column name in the convert, in case\n\t\t// this is a column rename and the AS is the new column.\n\t\t// For example, in convert(c1 using utf8mb4) as c2, we want to find\n\t\t// c1, because c1 exists in the current table whereas c2 is the renamed column\n\t\t// in the desired table.\n\t\tvar colName sqlparser.IdentifierCI\n\t\terr := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) {\n\t\t\tswitch node := node.(type) {\n\t\t\tcase *sqlparser.ColName:\n\t\t\t\tif !node.Qualifier.IsEmpty() {\n\t\t\t\t\treturn false, fmt.Errorf(\"unsupported qualifier for column: %v\", sqlparser.String(node))","sourceCodeStart":422,"sourceCodeEnd":458,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vttablet/tabletmanager/vreplication/table_plan_builder.go#L422-L458","documentation":"Non-trivial select expressions (anything that is not a bare column reference) must carry an explicit alias so the builder can name the resulting field. An unaliased expression like `count(*)` or `upper(name)` fails with this error because the output column name would be ambiguous.","triggerScenarios":"A filter select list includes an expression such as `SELECT count(*) FROM t` or `SELECT concat(a,b) FROM t` without `AS name`.","commonSituations":"Copy-phase rules computing values without aliases; hand-written filter rules forgetting the AS clause for functions.","solutions":["Add an explicit alias: `count(*) AS row_count`","For plain columns no alias is needed, but qualify expressions only when aliased","Re-run the workflow after fixing the select list"],"exampleFix":"// before\nSELECT count(*) FROM t\n// after\nSELECT count(*) AS row_count FROM t","handlingStrategy":"validation","validationCode":"for _, e := range sel.SelectExprs {\n    ae, ok := e.(*sqlparser.AliasedExpr)\n    if !ok { continue }\n    if ae.As.IsEmpty() {\n        if _, isCol := ae.Expr.(*sqlparser.ColName); !isCol {\n            return fmt.Errorf(\"expression %v requires AS alias\", sqlparser.String(ae))\n        }\n    }\n}","typeGuard":"func hasAlias(ae *sqlparser.AliasedExpr) bool {\n    if !ae.As.IsEmpty() { return true }\n    col, ok := ae.Expr.(*sqlparser.ColName)\n    return ok && col.Qualifier.IsEmpty()\n}","tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"needs an alias\") {\n    return fmt.Errorf(\"add AS aliases to all function expressions in filter select list: %w\", err)\n}","preventionTips":["Always alias non-column expressions in filter rules","Lint filter SQL for bare function calls","Document required AS for aggregate/function expressions"],"tags":["sqlparser","vreplication","alias","select-list"],"backgroundTag":"missing-sql-alias","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}