diff --git a/go/vt/vtgate/engine/join.go b/go/vt/vtgate/engine/join.go index a20c4d54a90..cbdb8d58151 100644 --- a/go/vt/vtgate/engine/join.go +++ b/go/vt/vtgate/engine/join.go @@ -82,7 +82,7 @@ func (jn *Join) Execute(vcursor VCursor, bindVars map[string]*querypb.BindVariab for _, rrow := range rresult.Rows { result.Rows = append(result.Rows, joinRows(lrow, rrow, jn.Cols)) } - if jn.Opcode == OuterJoin && len(rresult.Rows) == 0 { + if jn.Opcode == LeftJoin && len(rresult.Rows) == 0 { result.Rows = append(result.Rows, joinRows(lrow, nil, jn.Cols)) } if vcursor.ExceedsMaxMemoryRows(len(result.Rows)) { @@ -121,7 +121,7 @@ func (jn *Join) StreamExecute(vcursor VCursor, bindVars map[string]*querypb.Bind if err != nil { return err } - if jn.Opcode == OuterJoin && !rowSent { + if jn.Opcode == LeftJoin && !rowSent { result := &sqltypes.Result{} result.Rows = [][]sqltypes.Value{joinRows( lrow, @@ -207,7 +207,7 @@ type JoinOpcode int // This is the list of JoinOpcode values. const ( InnerJoin = JoinOpcode(iota) - OuterJoin + LeftJoin ) func (code JoinOpcode) String() string { diff --git a/go/vt/vtgate/engine/join_test.go b/go/vt/vtgate/engine/join_test.go index c6946d55aee..67c0973b9d1 100644 --- a/go/vt/vtgate/engine/join_test.go +++ b/go/vt/vtgate/engine/join_test.go @@ -102,7 +102,7 @@ func TestJoinExecute(t *testing.T) { // Left Join leftPrim.rewind() rightPrim.rewind() - jn.Opcode = OuterJoin + jn.Opcode = LeftJoin r, err = jn.Execute(&noopVCursor{}, bv, true) if err != nil { t.Fatal(err) @@ -404,7 +404,7 @@ func TestJoinStreamExecute(t *testing.T) { // Left Join leftPrim.rewind() rightPrim.rewind() - jn.Opcode = OuterJoin + jn.Opcode = LeftJoin r, err = wrapStreamExecute(jn, nil, map[string]*querypb.BindVariable{}, true) if err != nil { t.Fatal(err) diff --git a/go/vt/vtgate/planbuilder/abstract/operator.go b/go/vt/vtgate/planbuilder/abstract/operator.go index b5213bad993..455a0f9eeec 100644 --- a/go/vt/vtgate/planbuilder/abstract/operator.go +++ b/go/vt/vtgate/planbuilder/abstract/operator.go @@ -26,7 +26,7 @@ type ( // An operator can be: // * QueryGraph - which represents a group of tables and predicates that can be evaluated in any order // while still preserving the results - // * OuterJoin - A left/right join. These can't be evaluated in any order, so we keep them separate + // * LeftJoin - A left join. These can't be evaluated in any order, so we keep them separate Operator interface { // TableID returns a TableSet of the tables contained within TableID() semantics.TableSet @@ -73,9 +73,9 @@ func getOperatorFromTableExpr(tableExpr sqlparser.TableExpr, semTable *semantics if tableExpr.Join == sqlparser.RightJoinType { inner, outer = outer, inner } - op := &OuterJoin{ - Inner: inner, - Outer: outer, + op := &LeftJoin{ + Left: inner, + Right: outer, Predicate: tableExpr.Condition.On, } return op, nil diff --git a/go/vt/vtgate/planbuilder/abstract/operator_test.go b/go/vt/vtgate/planbuilder/abstract/operator_test.go index 92fe34edd2b..5eedf851c55 100644 --- a/go/vt/vtgate/planbuilder/abstract/operator_test.go +++ b/go/vt/vtgate/planbuilder/abstract/operator_test.go @@ -182,9 +182,9 @@ func testString(op Operator) string { leftStr := indent(testString(op.LHS)) rightStr := indent(testString(op.RHS)) return fmt.Sprintf("Join: {\n\tLHS: %s\n\tRHS: %s\n\tPredicate: %s\n}", leftStr, rightStr, sqlparser.String(op.Exp)) - case *OuterJoin: - leftStr := indent(testString(op.Inner)) - rightStr := indent(testString(op.Outer)) + case *LeftJoin: + leftStr := indent(testString(op.Left)) + rightStr := indent(testString(op.Right)) return fmt.Sprintf("OuterJoin: {\n\tInner: %s\n\tOuter: %s\n\tPredicate: %s\n}", leftStr, rightStr, sqlparser.String(op.Predicate)) } return "implement me" diff --git a/go/vt/vtgate/planbuilder/abstract/outerjoin.go b/go/vt/vtgate/planbuilder/abstract/outerjoin.go index 8aaa293d9fb..ba75e40c838 100644 --- a/go/vt/vtgate/planbuilder/abstract/outerjoin.go +++ b/go/vt/vtgate/planbuilder/abstract/outerjoin.go @@ -21,25 +21,23 @@ import ( "vitess.io/vitess/go/vt/vtgate/semantics" ) -// OuterJoin represents an outerjoin. -type OuterJoin struct { - Inner, Outer Operator - Predicate sqlparser.Expr +// LeftJoin represents an outerjoin. +type LeftJoin struct { + Left, Right Operator + Predicate sqlparser.Expr } // PushPredicate implements the Operator interface -func (oj *OuterJoin) PushPredicate(expr sqlparser.Expr, semTable *semantics.SemTable) error { +func (oj *LeftJoin) PushPredicate(expr sqlparser.Expr, semTable *semantics.SemTable) error { deps := semTable.Dependencies(expr) - if deps.IsSolvedBy(oj.Inner.TableID()) { - return oj.Inner.PushPredicate(expr, semTable) - } else if deps.IsSolvedBy(oj.Outer.TableID()) { - return oj.Outer.PushPredicate(expr, semTable) - } else { - return semantics.Gen4NotSupportedF("what the what!?") + if deps.IsSolvedBy(oj.Left.TableID()) { + return oj.Left.PushPredicate(expr, semTable) } + + return semantics.Gen4NotSupportedF("cannot push predicates to the RHS of an outer join") } // TableID implements the Operator interface -func (oj *OuterJoin) TableID() semantics.TableSet { - return oj.Outer.TableID().Merge(oj.Inner.TableID()) +func (oj *LeftJoin) TableID() semantics.TableSet { + return oj.Right.TableID().Merge(oj.Left.TableID()) } diff --git a/go/vt/vtgate/planbuilder/filtering.go b/go/vt/vtgate/planbuilder/filtering.go index 959e6fa02ce..4621cf169a8 100644 --- a/go/vt/vtgate/planbuilder/filtering.go +++ b/go/vt/vtgate/planbuilder/filtering.go @@ -35,7 +35,7 @@ func planFilter(pb *primitiveBuilder, input logicalPlan, filter sqlparser.Expr, if node.isOnLeft(origin.Order()) { in = node.Left } else { - if node.ejoin.Opcode == engine.OuterJoin { + if node.ejoin.Opcode == engine.LeftJoin { return nil, errors.New("unsupported: cross-shard left join and where clause") } isLeft = false diff --git a/go/vt/vtgate/planbuilder/join.go b/go/vt/vtgate/planbuilder/join.go index 0f3fbe94c5c..3da977b2c1c 100644 --- a/go/vt/vtgate/planbuilder/join.go +++ b/go/vt/vtgate/planbuilder/join.go @@ -85,7 +85,7 @@ func newJoin(lpb, rpb *primitiveBuilder, ajoin *sqlparser.JoinTableExpr, reserve if ajoin != nil { switch { case ajoin.Join == sqlparser.LeftJoinType: - opcode = engine.OuterJoin + opcode = engine.LeftJoin // For left joins, we have to push the ON clause into the RHS. // We do this before creating the join primitive. @@ -113,7 +113,7 @@ func newJoin(lpb, rpb *primitiveBuilder, ajoin *sqlparser.JoinTableExpr, reserve }, } lpb.plan.Reorder(0) - if ajoin == nil || opcode == engine.OuterJoin { + if ajoin == nil || opcode == engine.LeftJoin { return nil } return lpb.pushFilter(ajoin.Condition.On, sqlparser.WhereStr, reservedVars) diff --git a/go/vt/vtgate/planbuilder/jointree.go b/go/vt/vtgate/planbuilder/jointree.go index ad73d0fd5ac..6400b9b1665 100644 --- a/go/vt/vtgate/planbuilder/jointree.go +++ b/go/vt/vtgate/planbuilder/jointree.go @@ -47,8 +47,8 @@ type ( } leJoin struct { - a, b relation - pred sqlparser.Expr + lhs, rhs relation + pred sqlparser.Expr } routeTable struct { @@ -114,10 +114,10 @@ var _ relation = (parenTables)(nil) func (rp *routeTable) tableID() semantics.TableSet { return rp.qtable.TableID } -func (rp *leJoin) tableID() semantics.TableSet { return rp.a.tableID().Merge(rp.b.tableID()) } +func (rp *leJoin) tableID() semantics.TableSet { return rp.lhs.tableID().Merge(rp.rhs.tableID()) } func (rp *leJoin) tableNames() []string { - return append(rp.a.tableNames(), rp.b.tableNames()...) + return append(rp.lhs.tableNames(), rp.rhs.tableNames()...) } func (rp *routeTable) tableNames() []string { diff --git a/go/vt/vtgate/planbuilder/jointree_transformers.go b/go/vt/vtgate/planbuilder/jointree_transformers.go index f06ef1a09e4..b6c73780e26 100644 --- a/go/vt/vtgate/planbuilder/jointree_transformers.go +++ b/go/vt/vtgate/planbuilder/jointree_transformers.go @@ -52,7 +52,7 @@ func transformJoinPlan(n *joinPlan, semTable *semantics.SemTable) (logicalPlan, } opCode := engine.InnerJoin if n.outer { - opCode = engine.OuterJoin + opCode = engine.LeftJoin } return &joinGen4{ Left: lhs, @@ -168,9 +168,9 @@ func relToTableExpr(t relation) sqlparser.TableExpr { return &sqlparser.ParenTableExpr{Exprs: tables} case *leJoin: return &sqlparser.JoinTableExpr{ - LeftExpr: relToTableExpr(t.a), + LeftExpr: relToTableExpr(t.lhs), Join: sqlparser.NormalJoinType, - RightExpr: relToTableExpr(t.b), + RightExpr: relToTableExpr(t.rhs), Condition: sqlparser.JoinCondition{ On: t.pred, }, diff --git a/go/vt/vtgate/planbuilder/project.go b/go/vt/vtgate/planbuilder/project.go index e9375ba4951..71c1889ee84 100644 --- a/go/vt/vtgate/planbuilder/project.go +++ b/go/vt/vtgate/planbuilder/project.go @@ -45,7 +45,7 @@ func planProjection(pb *primitiveBuilder, in logicalPlan, expr *sqlparser.Aliase node.Left = newLeft } else { // Pushing of non-trivial expressions not allowed for RHS of left joins. - if _, ok := expr.Expr.(*sqlparser.ColName); !ok && node.ejoin.Opcode == engine.OuterJoin { + if _, ok := expr.Expr.(*sqlparser.ColName); !ok && node.ejoin.Opcode == engine.LeftJoin { return nil, nil, 0, errors.New("unsupported: cross-shard left join and column expressions") } diff --git a/go/vt/vtgate/planbuilder/route_planning.go b/go/vt/vtgate/planbuilder/route_planning.go index 04360ecd07e..23d8af41f85 100644 --- a/go/vt/vtgate/planbuilder/route_planning.go +++ b/go/vt/vtgate/planbuilder/route_planning.go @@ -100,12 +100,12 @@ func optimizeQuery(opTree abstract.Operator, semTable *semantics.SemTable, vsche default: return greedySolve(op, semTable, vschema) } - case *abstract.OuterJoin: - treeInner, err := optimizeQuery(op.Inner, semTable, vschema) + case *abstract.LeftJoin: + treeInner, err := optimizeQuery(op.Left, semTable, vschema) if err != nil { return nil, err } - treeOuter, err := optimizeQuery(op.Outer, semTable, vschema) + treeOuter, err := optimizeQuery(op.Right, semTable, vschema) if err != nil { return nil, err } @@ -308,7 +308,7 @@ func createSingleShardRoutePlan(sel *sqlparser.Select, rb *route) { } } -func pushPredicate2(exprs []sqlparser.Expr, tree joinTree, semTable *semantics.SemTable) (joinTree, error) { +func pushJoinPredicate(exprs []sqlparser.Expr, tree joinTree, semTable *semantics.SemTable) (joinTree, error) { switch node := tree.(type) { case *routePlan: plan := node.clone().(*routePlan) @@ -334,7 +334,7 @@ func pushPredicate2(exprs []sqlparser.Expr, tree joinTree, semTable *semantics.S rhsPreds = append(rhsPreds, predicate) } node.pushOutputColumns(lhsColumns, semTable) - rhsPlan, err := pushPredicate2(rhsPreds, node.rhs, semTable) + rhsPlan, err := pushJoinPredicate(rhsPreds, node.rhs, semTable) if err != nil { return nil, err } @@ -385,7 +385,7 @@ func mergeOrJoin(lhs, rhs joinTree, joinPredicates []sqlparser.Expr, semTable *s } tree := &joinPlan{lhs: lhs.clone(), rhs: rhs.clone(), outer: !inner} - return pushPredicate2(joinPredicates, tree, semTable) + return pushJoinPredicate(joinPredicates, tree, semTable) } type ( @@ -757,8 +757,8 @@ func createRoutePlanForOuter(aRoute, bRoute *routePlan, semTable *semantics.SemT tables = newTables if aTbl != nil && bTbl != nil { tables = append(tables, &leJoin{ - a: aTbl, - b: bTbl, + lhs: aTbl, + rhs: bTbl, pred: predicate, }) }