{"record":{"id":"4220bacbb8c367bf","repo":"vitessio/vitess","slug":"found-target-selectexpr-which-was-neither-colname","errorCode":null,"errorMessage":"found target SelectExpr which was neither ColName nor FuncExpr: %+v","messagePattern":"found target SelectExpr which was neither ColName nor FuncExpr: %\\+v","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vttablet/tabletmanager/vdiff/table_differ.go","lineNumber":1071,"sourceCode":"\t\tif _, ok := sourcePKColumns[pkc]; ok {\n\t\t\ttd.tablePlan.sourcePkCols = append(td.tablePlan.sourcePkCols, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc getColumnNameForSelectExpr(selectExpression sqlparser.SelectExpr) (string, error) {\n\taliasedExpr := selectExpression.(*sqlparser.AliasedExpr)\n\texpr := aliasedExpr.Expr\n\tvar colname string\n\tswitch t := expr.(type) {\n\tcase *sqlparser.ColName:\n\t\tcolname = t.Name.Lowered()\n\tcase *sqlparser.FuncExpr: // only in case datetime was converted using convert_tz()\n\t\tcolname = aliasedExpr.As.Lowered()\n\tdefault:\n\t\treturn \"\", fmt.Errorf(\"found target SelectExpr which was neither ColName nor FuncExpr: %+v\", aliasedExpr)\n\t}\n\treturn colname, nil\n}\n","sourceCodeStart":1053,"sourceCodeEnd":1075,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vttablet/tabletmanager/vdiff/table_differ.go#L1053-L1075","documentation":"During VDiff table plan construction, getColumnNameForSelectExpr derives the column name for each target SELECT expression. Only plain column references (ColName) and function expressions with an alias (e.g. convert_tz() results) are supported; any other SelectExpr shape throws this error.","triggerScenarios":"The target select list for a table contains an expression that is neither a bare column name nor a (aliased) FuncExpr — e.g. a subquery, CASE expression, arithmetic like (a+b), CastExpr, or a FuncExpr missing an As alias when getColumnNameForSelectExpr reaches the FuncExpr path with empty As.","commonSituations":"Running VDiff after the workflow's filter/rule select list was hand-edited to include computed columns; MoveTables with a custom keyrange filter producing unusual select expressions; schema drifted between source and target so the reconstructed target select no longer matches expectations.","solutions":["Ensure every non-trivial expression in the workflow select/rule has an explicit `AS alias` so it maps to a target column name","Simplify the vdiff/migration filter rules to select plain columns; run the diff on base columns instead of computed expressions","If a new sqlparser expression type is legitimately needed, extend the switch in getColumnNameForSelectExpr to handle it and regenerate/rebuild","Verify source and target schemas match for the table so the target select list is regenerated as plain ColNames"],"exampleFix":"// before (filter rule with computed expr, no alias)\nselect id, price * quantity from orders\n// after\nselect id, (price * quantity) as line_total from orders","handlingStrategy":"validation","validationCode":"// before starting vdiff, verify each selected expression is a plain column or an aliased function\nfor _, expr := range selectExprs {\n  ae, ok := expr.(*sqlparser.AliasedExpr)\n  if !ok { return fmt.Errorf(\"unsupported select expr\") }\n  switch ae.Expr.(type) {\n  case *sqlparser.ColName:\n  case *sqlparser.FuncExpr:\n    if ae.As.IsEmpty() { return fmt.Errorf(\"func expr needs alias\") }\n  default:\n    return fmt.Errorf(\"unsupported expression type in select list\")\n  }\n}","typeGuard":"func isSimpleSelectExpr(e sqlparser.SelectExpr) bool {\n  ae, ok := e.(*sqlparser.AliasedExpr)\n  if !ok { return false }\n  switch ae.Expr.(type) {\n  case *sqlparser.ColName:\n    return true\n  case *sqlparser.FuncExpr:\n    return !ae.As.IsEmpty()\n  }\n  return false\n}","tryCatchPattern":"colname, err := getColumnNameForSelectExpr(expr)\nif err != nil {\n  return fmt.Errorf(\"table %s has unsupported target select expr: %w\", tableName, err)\n}","preventionTips":["Keep vreplication filter rules to plain column selects","Always alias computed expressions (convert_tz etc.)","Diff base columns, not derived values","Validate rules with sqlparser before saving the workflow"],"tags":["vdiff","sqlparser","vdiff-plan"],"backgroundTag":"vdiff-unsupported-select-expression","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}