{"record":{"id":"5475cb52156e255a","repo":"vitessio/vitess","slug":"unsupported-from-expression-t","errorCode":null,"errorMessage":"unsupported from expression (%T)","messagePattern":"unsupported from expression \\(%T\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vttablet/tabletmanager/vreplication/table_plan_builder.go","lineNumber":409,"sourceCode":"\tif err != nil {\n\t\treturn nil, \"\", err\n\t}\n\tsel, ok := statement.(*sqlparser.Select)\n\tif !ok {\n\t\treturn nil, \"\", errors.New(\"unsupported non-select statement\")\n\t}\n\tif sel.Distinct {\n\t\treturn nil, \"\", errors.New(\"unsupported distinct clause\")\n\t}\n\tif len(sel.From) == 0 {\n\t\treturn nil, \"\", errors.New(\"unsupported select from dual\")\n\t}\n\tif len(sel.From) > 1 {\n\t\treturn nil, \"\", errors.New(\"unsupported multi-table usage\")\n\t}\n\tnode, ok := sel.From[0].(*sqlparser.AliasedTableExpr)\n\tif !ok {\n\t\treturn nil, \"\", fmt.Errorf(\"unsupported from expression (%T)\", sel.From[0])\n\t}\n\tfromTable := sqlparser.GetTableName(node.Expr)\n\tif fromTable.IsEmpty() {\n\t\treturn nil, \"\", fmt.Errorf(\"unsupported from source (%T)\", node.Expr)\n\t}\n\treturn sel, fromTable.String(), nil\n}\n\nfunc (tpb *tablePlanBuilder) analyzeExprs(selExprs []sqlparser.SelectExpr) error {\n\tfor _, selExpr := range selExprs {\n\t\tcexpr, err := tpb.analyzeExpr(selExpr)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\ttpb.colExprs = append(tpb.colExprs, cexpr)\n\t}\n\treturn nil\n}","sourceCodeStart":391,"sourceCodeEnd":427,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vttablet/tabletmanager/vreplication/table_plan_builder.go#L391-L427","documentation":"analyzeSelectFrom validates that the SELECT's FROM clause is a single simple table expression before generating a vstream filter plan. If the FROM element is not an *sqlparser.AliasedTableExpr (e.g. a derived table/subquery or join), the planner rejects it because vstreaming can only replicate from plain tables.","triggerScenarios":"A filter/plan input whose FROM clause contains a subquery `(SELECT ...)` , a JOIN expression, or any non-AliasedTableExpr node as the first FROM item.","commonSituations":"Hand-edited or generated replication plans embedding joins; tooling that passes query templates instead of plain table selects into the vreplication plan builder.","solutions":["Rewrite the FROM clause to reference a single base table by name","Compute joins upstream and replicate from the resulting materialized table","If a derived table is needed, create a real table and point the plan at it"],"exampleFix":"// before\nsel.From = \"(SELECT * FROM t JOIN u ON ...)\"\n// after\nsel.From = \"t\"","handlingStrategy":"validation","validationCode":"stmt, err := sqlparser.Parse(selSQL)\nif err != nil { return err }\nsel := stmt.(*sqlparser.Select)\nif len(sel.From) != 1 { return errors.New(\"plan requires a single FROM table\") }\nif _, ok := sel.From[0].(*sqlparser.AliasedTableExpr); !ok {\n    return errors.New(\"FROM must be a plain table expression\")\n}","typeGuard":"func isSimpleFrom(sel *sqlparser.Select) bool {\n    if len(sel.From) != 1 { return false }\n    _, ok := sel.From[0].(*sqlparser.AliasedTableExpr)\n    return ok\n}","tryCatchPattern":"plan, err := buildReplicatorPlan(...)\nif err != nil && strings.Contains(err.Error(), \"unsupported\") {\n    // fall back to plain table-to-table select\n}","preventionTips":["Keep vreplication filter SELECTs limited to single-table queries","Never feed JOIN/subquery SQL into plan generation","Review generated plans for unexpected FROM shapes"],"tags":["sqlparser","vreplication","unsupported-sql","from-clause"],"backgroundTag":"unsupported-sql-construct","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}