{"record":{"id":"ad22c3e8f67ab03d","repo":"vitessio/vitess","slug":"only-count-is-supported-v","errorCode":null,"errorMessage":"only count(*) is supported: %v","messagePattern":"only count\\(\\*\\) is supported: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vttablet/tabletmanager/vreplication/table_plan_builder.go","lineNumber":497,"sourceCode":"\t\tcase \"keyspace_id\":\n\t\t\tif len(expr.Exprs) != 0 {\n\t\t\t\treturn nil, fmt.Errorf(\"unsupported multiple keyspace_id expressions: %v\", sqlparser.String(expr))\n\t\t\t}\n\n\t\t\ttpb.sendSelect.AddSelectExpr(&sqlparser.AliasedExpr{Expr: aliased.Expr})\n\t\t\t// The vstreamer responds with \"keyspace_id\" as the field name for this request.\n\t\t\tcexpr.expr = &sqlparser.ColName{Name: sqlparser.NewIdentifierCI(\"keyspace_id\")}\n\t\t\treturn cexpr, nil\n\t\t}\n\t}\n\tif expr, ok := aliased.Expr.(sqlparser.AggrFunc); ok {\n\t\tif sqlparser.IsDistinct(expr) {\n\t\t\treturn nil, fmt.Errorf(\"unsupported distinct expression usage: %v\", sqlparser.String(expr))\n\t\t}\n\t\tswitch fname := expr.AggrName(); fname {\n\t\tcase \"count\":\n\t\t\tif _, ok := expr.(*sqlparser.CountStar); !ok {\n\t\t\t\treturn nil, fmt.Errorf(\"only count(*) is supported: %v\", sqlparser.String(expr))\n\t\t\t}\n\t\t\tcexpr.operation = opCount\n\t\t\treturn cexpr, nil\n\t\tcase \"sum\":\n\t\t\tif len(expr.GetArgs()) != 1 {\n\t\t\t\treturn nil, fmt.Errorf(\"unsupported multiple columns in sum clause: %v\", sqlparser.String(expr))\n\t\t\t}\n\t\t\tinnerCol, ok := expr.GetArg().(*sqlparser.ColName)\n\t\t\tif !ok {\n\t\t\t\treturn nil, fmt.Errorf(\"unsupported non-column name in sum clause: %v\", sqlparser.String(expr))\n\t\t\t}\n\t\t\tif !innerCol.Qualifier.IsEmpty() {\n\t\t\t\treturn nil, fmt.Errorf(\"unsupported qualifier for column: %v\", sqlparser.String(innerCol))\n\t\t\t}\n\t\t\tcexpr.operation = opSum\n\t\t\tcexpr.expr = innerCol\n\t\t\ttpb.addCol(innerCol.Name)\n\t\t\tcexpr.references[innerCol.Name.String()] = true","sourceCodeStart":479,"sourceCodeEnd":515,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vttablet/tabletmanager/vreplication/table_plan_builder.go#L479-L515","documentation":"VReplication's table plan builder only supports the simplest form of COUNT in a filtered replication SELECT: COUNT(*). Any argumented count, e.g. COUNT(col) or COUNT(DISTINCT col), is rejected because the generated materialization logic cannot evaluate per-row counting. The error is returned by analyzeExpr when an aggregate named 'count' is not a *sqlparser.CountStar.","triggerScenarios":"Running a Materialize / vreplication workflow whose SELECT list contains COUNT(col), COUNT(1), COUNT(DISTINCT x), or COUNT(*) with any non-star argument; analyzeExpr is called via analyzeExprs while building the table plan.","commonSituations":"Users copying a hand-written analytics query into a Materialize source; upgrading a workflow that previously used a plain count and someone changed it to count a column; tools generating 'SELECT COUNT(id) FROM t' as a convenience.","solutions":["Rewrite the select list to use COUNT(*) instead of COUNT(col) or COUNT(DISTINCT col).","If you need per-column counts, compute them outside vreplication (e.g. via a separate query or aggregation engine).","Remove DISTINCT from the aggregate — distinct usage is rejected separately.","Check that the query you passed to MoveTables/Materialize only uses supported aggregates (count(*) and single-column sum)."],"exampleFix":"// before\nselect count(user_id) as cnt from t\n// after\nselect count(*) as cnt from t","handlingStrategy":"validation","validationCode":"// Go: reject argumented COUNT before submitting to the workflow\nfunc validCount(e sqlparser.Expr) bool {\n    ag, ok := e.(*sqlparser.AliasedExpr)\n    if !ok { return true }\n    cs, ok := ag.Expr.(*sqlparser.CountStar)\n    return ok && cs != nil\n}","typeGuard":"func isCountStar(n sqlparser.SQLNode) bool { _, ok := n.(*sqlparser.CountStar); return ok }","tryCatchPattern":null,"preventionTips":["Only use COUNT(*) in materialize/vreplication select lists.","Never apply DISTINCT to count in workflow queries.","Keep workflow queries minimal; do complex analytics with VTGate afterward."],"tags":["vreplication","sql","aggregation","vttablet"],"backgroundTag":"unsupported-aggregate-expression","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}