{"record":{"id":"cf4b9b8800e775fe","repo":"vitessio/vitess","slug":"unsupported-construct-v-cf4b9b","errorCode":null,"errorMessage":"unsupported construct: %v","messagePattern":"unsupported construct: (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/wrangler/vexec_plan.go","lineNumber":292,"sourceCode":"\t\tif !match {\n\t\t\treturn nil, fmt.Errorf(\"Query must match one of these templates: %s\", strings.Join(templates, \"; \"))\n\t\t}\n\t}\n\tupd.Where = vx.addDefaultWheres(planner, upd.Where)\n\n\tbuf := sqlparser.NewTrackedBuffer(nil)\n\tbuf.Myprintf(\"%v\", upd)\n\n\treturn &vexecPlan{\n\t\topcode:      updateQuery,\n\t\tparsedQuery: buf.ParsedQuery(),\n\t}, nil\n}\n\n// buildDeletePlan builds a plan for a DELETE query\nfunc (vx *vexec) buildDeletePlan(ctx context.Context, planner vexecPlanner, del *sqlparser.Delete) (*vexecPlan, error) {\n\tif del.Targets != nil {\n\t\treturn nil, fmt.Errorf(\"unsupported construct: %v\", sqlparser.String(del))\n\t}\n\tif del.Partitions != nil {\n\t\treturn nil, fmt.Errorf(\"unsupported construct: %v\", sqlparser.String(del))\n\t}\n\tif del.OrderBy != nil || del.Limit != nil {\n\t\treturn nil, fmt.Errorf(\"unsupported construct: %v\", sqlparser.String(del))\n\t}\n\n\tdel.Where = vx.addDefaultWheres(planner, del.Where)\n\n\tbuf := sqlparser.NewTrackedBuffer(nil)\n\tbuf.Myprintf(\"%v\", del)\n\n\treturn &vexecPlan{\n\t\topcode:      deleteQuery,\n\t\tparsedQuery: buf.ParsedQuery(),\n\t}, nil\n}","sourceCodeStart":274,"sourceCodeEnd":310,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/wrangler/vexec_plan.go#L274-L310","documentation":"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.","triggerScenarios":"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.","commonSituations":"Operators writing cleanup SQL adapted from MySQL multi-table delete syntax; automation scripts porting OLTP queries to vtctld/vexec admin paths.","solutions":["Rewrite the query as separate single-table DELETE statements, one per table","Use a subquery (e.g. `DELETE FROM t1 WHERE id IN (SELECT ...)`), keeping a single delete target","Execute the multi-table DELETE directly on the shard's MySQL via mysqlctl/queryservice instead of vexec"],"exampleFix":"// before\nDELETE t1, t2 FROM t1 JOIN t2 ON t1.id = t2.id WHERE t1.x = 1;\n// after\nDELETE FROM t1 WHERE x = 1;\nDELETE FROM t2 WHERE t1_id IN (SELECT id FROM t1 WHERE x = 1);","handlingStrategy":"validation","validationCode":"del, err := sqlparser.Parse(query)\nif err != nil { return err }\nd, ok := del.(*sqlparser.Delete)\nif !ok || d.Targets != nil {\n    return fmt.Errorf(\"vexec DELETE supports single-table deletes only\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Avoid MySQL multi-table DELETE syntax in admin scripts","Split cleanup logic into per-table statements","Prefer subquery-based deletes over join-based deletes"],"tags":["sql","delete","unsupported-construct"],"backgroundTag":"unsupported-sql-construct","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}