vitessio/vitess · error

unsupported construct: %v

Error message

unsupported construct: %v

What it means

vexec (the wrangler's generic SQL executor for running admin DML against shards) only supports simple single-table DELETE statements. buildDeletePlan rejects DELETE statements using multi-table delete Targets, because the plan builder has no way to rewrite them for sharded execution.

Source

Thrown at go/vt/wrangler/vexec_plan.go:292

		if !match {
			return nil, fmt.Errorf("Query must match one of these templates: %s", strings.Join(templates, "; "))
		}
	}
	upd.Where = vx.addDefaultWheres(planner, upd.Where)

	buf := sqlparser.NewTrackedBuffer(nil)
	buf.Myprintf("%v", upd)

	return &vexecPlan{
		opcode:      updateQuery,
		parsedQuery: buf.ParsedQuery(),
	}, nil
}

// buildDeletePlan builds a plan for a DELETE query
func (vx *vexec) buildDeletePlan(ctx context.Context, planner vexecPlanner, del *sqlparser.Delete) (*vexecPlan, error) {
	if del.Targets != nil {
		return nil, fmt.Errorf("unsupported construct: %v", sqlparser.String(del))
	}
	if del.Partitions != nil {
		return nil, fmt.Errorf("unsupported construct: %v", sqlparser.String(del))
	}
	if del.OrderBy != nil || del.Limit != nil {
		return nil, fmt.Errorf("unsupported construct: %v", sqlparser.String(del))
	}

	del.Where = vx.addDefaultWheres(planner, del.Where)

	buf := sqlparser.NewTrackedBuffer(nil)
	buf.Myprintf("%v", del)

	return &vexecPlan{
		opcode:      deleteQuery,
		parsedQuery: buf.ParsedQuery(),
	}, nil
}

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Rewrite the query as separate single-table DELETE statements, one per table
  2. Use a subquery (e.g. `DELETE FROM t1 WHERE id IN (SELECT ...)`), keeping a single delete target
  3. Execute the multi-table DELETE directly on the shard's MySQL via mysqlctl/queryservice instead of vexec

Example fix

// before
DELETE t1, t2 FROM t1 JOIN t2 ON t1.id = t2.id WHERE t1.x = 1;
// after
DELETE FROM t1 WHERE x = 1;
DELETE FROM t2 WHERE t1_id IN (SELECT id FROM t1 WHERE x = 1);
Defensive patterns

Strategy: validation

Validate before calling

del, err := sqlparser.Parse(query)
if err != nil { return err }
d, ok := del.(*sqlparser.Delete)
if !ok || d.Targets != nil {
    return fmt.Errorf("vexec DELETE supports single-table deletes only")
}

Prevention

When it happens

Trigger: Calling vexec (e.g. via wrangler query execution helpers) with a DELETE statement that contains multiple delete targets, i.e. `DELETE t1, t2 FROM t1 JOIN t2 ...` — sqlparser.Delete.Targets is non-nil.

Common situations: Operators writing cleanup SQL adapted from MySQL multi-table delete syntax; automation scripts porting OLTP queries to vtctld/vexec admin paths.

Related errors


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