RelationParser { static Parser<Relation> join(Parser<Relation> rel, Parser<Expression> cond) { Parser.Reference<Relation> ref = Parser.newReference(); Parser<Relation> lazy = ref.lazy(); Parser<Relation> atom = aliasable(ExpressionParser.paren(lazy).or(rel)); Parser<UnaryOperator<Relation>> crossJoin = TerminalParser.phrase("cross join").next(atom).map(r -> l -> new CrossJoinRelation(l, r)); Parser<Relation> parser = atom.postfix(Parsers.or( joinOn(INNER_JOIN, lazy, cond), joinOn(LEFT_JOIN, lazy, cond), joinOn(RIGHT_JOIN, lazy, cond), joinOn(FULL_JOIN, lazy, cond), crossJoin)); ref.set(parser); return parser; }  static Parser<Relation> query();  }
@Test public void testJoin() { Parser<Relation> parser = RelationParser.join(TABLE, ExpressionParser.NUMBER); TerminalParserTest.assertParser(parser, "a", table("a")); TerminalParserTest.assertParser(parser, "a cross join table2 as b", new CrossJoinRelation(table("a"), new AliasedRelation(table("table2"), "b"))); TerminalParserTest.assertParser(parser, "a inner join b on 1", new JoinRelation(table("a"), JoinType.INNER, table("b"), ExpressionParserTest.number(1))); TerminalParserTest.assertParser(parser, "a inner join b on 1 left join c on 2 cross join d", new CrossJoinRelation( new JoinRelation( new JoinRelation(table("a"), JoinType.INNER, table("b"), ExpressionParserTest.number(1)) , JoinType.LEFT, table("c"), ExpressionParserTest.number(2)), table("d"))); TerminalParserTest.assertParser(parser, "a cross join b inner join c right join d on 1 on 2", new JoinRelation(new CrossJoinRelation(table("a"), table("b")), JoinType.INNER, new JoinRelation(table("c"), JoinType.RIGHT, table("d"), ExpressionParserTest.number(1)), ExpressionParserTest.number(2))); TerminalParserTest.assertParser(parser, "a cross join (b FULL join c on 1)", new CrossJoinRelation(table("a"), new JoinRelation(table("b"), JoinType.FULL, table("c"), ExpressionParserTest.number(1)))); }