vitessio/vitess · error

unsupported non-column name in sum clause: %v

Error message

unsupported non-column name in sum clause: %v

What it means

SUM's single argument must be a plain column reference in vreplication table plans. Expressions like SUM(a+b), SUM(a*b) or nested aggregates are rejected because the plan builder can only count/replay values of one column (opSum stores a *sqlparser.ColName).

Source

Thrown at go/vt/vttablet/tabletmanager/vreplication/table_plan_builder.go:507

	}
	if expr, ok := aliased.Expr.(sqlparser.AggrFunc); ok {
		if sqlparser.IsDistinct(expr) {
			return nil, fmt.Errorf("unsupported distinct expression usage: %v", sqlparser.String(expr))
		}
		switch fname := expr.AggrName(); fname {
		case "count":
			if _, ok := expr.(*sqlparser.CountStar); !ok {
				return nil, fmt.Errorf("only count(*) is supported: %v", sqlparser.String(expr))
			}
			cexpr.operation = opCount
			return cexpr, nil
		case "sum":
			if len(expr.GetArgs()) != 1 {
				return nil, fmt.Errorf("unsupported multiple columns in sum clause: %v", sqlparser.String(expr))
			}
			innerCol, ok := expr.GetArg().(*sqlparser.ColName)
			if !ok {
				return nil, fmt.Errorf("unsupported non-column name in sum clause: %v", sqlparser.String(expr))
			}
			if !innerCol.Qualifier.IsEmpty() {
				return nil, fmt.Errorf("unsupported qualifier for column: %v", sqlparser.String(innerCol))
			}
			cexpr.operation = opSum
			cexpr.expr = innerCol
			tpb.addCol(innerCol.Name)
			cexpr.references[innerCol.Name.String()] = true
			return cexpr, nil
		}
	}
	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))
			}
			tpb.addCol(node.Name)

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Change SUM to take a single bare column, e.g. SUM(price).
  2. Materialize the computed value into a real column first, then SUM that column.
  3. Do the expression aggregation outside vreplication (query the materialized table with VTGate instead).

Example fix

// before
select sum(price * qty) as total from t
// after
select sum(price_times_qty) as total from t  -- with price_times_qty a stored column
Defensive patterns

Strategy: validation

Validate before calling

// Ensure SUM's argument is a bare column
func validSumArgIsColumn(e sqlparser.Expr) bool {
    ag, ok := e.(*sqlparser.AliasedExpr)
    if !ok { return true }
    sum, ok := ag.Expr.(*sqlparser.Sum)
    if !ok { return true }
    _, isCol := sum.Args[0].(*sqlparser.ColName)
    return isCol
}

Type guard

func isColName(n sqlparser.SQLNode) bool { _, ok := n.(*sqlparser.ColName); return ok }

Prevention

When it happens

Trigger: Materialize/vreplication SELECT with SUM(<non-column>), e.g. SUM(price * qty) or SUM(CONCAT(a,b)); analyzeExpr's type assertion of the arg to *sqlparser.ColName fails.

Common situations: Users porting existing reporting SQL into a Materialize workflow; computed columns needing expression aggregation that the simple materializer cannot evaluate.

Related errors


AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01). Data as JSON: /api/errors/2cbb5a7e96a3e582. Report an issue: GitHub.