{"record":{"id":"26f68dd268db2f2c","repo":"vitessio/vitess","slug":"unsupported-v","errorCode":null,"errorMessage":"unsupported: %v","messagePattern":"unsupported: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vttablet/tabletserver/vstreamer/planbuilder.go","lineNumber":550,"sourceCode":"\t\treturn nil, fromTable, err\n\t}\n\tsel, ok := statement.(*sqlparser.Select)\n\tif !ok {\n\t\treturn nil, fromTable, fmt.Errorf(\"unsupported: %v\", sqlparser.String(statement))\n\t}\n\tif len(sel.From) == 0 {\n\t\treturn nil, fromTable, fmt.Errorf(\"unsupported select from dual: %v\", sqlparser.String(sel))\n\t}\n\tif len(sel.From) > 1 {\n\t\treturn nil, fromTable, fmt.Errorf(\"unsupported: %v\", sqlparser.String(sel))\n\t}\n\tnode, ok := sel.From[0].(*sqlparser.AliasedTableExpr)\n\tif !ok {\n\t\treturn nil, fromTable, fmt.Errorf(\"unsupported: %v\", sqlparser.String(sel))\n\t}\n\tfromTable = sqlparser.GetTableName(node.Expr)\n\tif fromTable.IsEmpty() {\n\t\treturn nil, fromTable, fmt.Errorf(\"unsupported: %v\", sqlparser.String(sel))\n\t}\n\treturn sel, fromTable, nil\n}\n\n// isConvertColumnUsingUTF8 returns 'true' when given column needs to be converted as UTF8\n// while read from source table\nfunc (plan *Plan) isConvertColumnUsingUTF8(columnName string) bool {\n\tif plan.convertUsingUTF8Columns == nil {\n\t\treturn false\n\t}\n\treturn plan.convertUsingUTF8Columns[columnName]\n}\n\n// setConvertColumnUsingUTF8 marks given column as needs to be converted as UTF8\n// while read from source table\nfunc (plan *Plan) setConvertColumnUsingUTF8(columnName string) {\n\tif plan.convertUsingUTF8Columns == nil {\n\t\tplan.convertUsingUTF8Columns = map[string]bool{}","sourceCodeStart":532,"sourceCodeEnd":568,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vttablet/tabletserver/vstreamer/planbuilder.go#L532-L568","documentation":"The vstreamer planbuilder only supports SELECT statements whose FROM clause starts with a single plain (possibly aliased) table expression, because VStream filters translate to simple table selects. Any other first FROM item (subquery, join, parenthesized expr) or an empty/complex table name makes analyzeSelect reject the whole select as unsupported.","triggerScenarios":"A VReplication/VStream filter rule's SELECT contains a subquery, JOIN, or non-table expression as sel.From[0]; or the extracted table name is empty (e.g. FROM (SELECT ...)).","commonSituations":"Custom VStream filters with fancy SQL; users expecting vstreamer to handle joins like a full query engine; filter rules written with derived tables.","solutions":["Rewrite the filter's SELECT to reference exactly one plain table: select <cols> from <table> [where <literal-predicates>]","Remove joins/subqueries — perform them downstream in the VStream consumer","Verify GetTableName on the FROM expression yields a real table name (no derived tables)","Check planbuilder.go analyzeSelect for the currently supported grammar subset"],"exampleFix":"// before\nfilter: select t1.a, t2.b from t1 join t2 on t1.id=t2.id\n// after\nfilter: select t1.a, t1.b from t1","handlingStrategy":"validation","validationCode":"// check filter SELECT before installing\nstmt, err := sqlparser.Parse(rule.Filter)\nif err != nil { return err }\nsel, ok := stmt.(*sqlparser.Select)\nif !ok { return fmt.Errorf(\"not a select\") }\nif _, ok := sel.From[0].(*sqlparser.AliasedTableExpr); !ok || len(sel.From) != 1 {\n    return fmt.Errorf(\"filter must select from a single table\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Write filters as single-table SELECTs only","No joins, subqueries, or derived tables in filters","Do complex processing in the consumer, not the filter"],"tags":["vstreamer","planbuilder","unsupported-sql","vreplication"],"backgroundTag":"unsupported-sql-feature","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}