T-SQL (and Oracle) support non-standard syntax, which is similar in
functionality to LATERAL joins in ANSI and PostgreSQL
<https://blog.jooq.org/tag/lateral-derived-table/>: it allows to use
the columns from the tables defined to the left of `APPLY` in the
"derived tables" (subqueries) to the right of `APPLY`. Unlike ANSI
LATERAL (but like Postgres' implementation), APPLY is also used with
table-valued function calls.
Despite them being similar, we represent "APPLY" joins with
`JoinOperator`s of its own (`CrossApply` and `OuterApply`). Doing
otherwise seemed like it would cause unnecessary confusion, as those
interested in dialect-specific parsing would probably not expect APPLY
being parsed as LATERAL, and those wanting to forbid non-standard SQL
would not be helped by this either.
This also renames existing JoinOperator::Cross -> CrossJoin to avoid
confusion with CrossApply.
`SELECT * FROM a OUTER JOIN b` was previously being parsed as an inner
join where table `a` was aliased to `OUTER`. This is extremely
surprising, as the user likely intended to say FULL OUTER JOIN. Since
the SQL specification lists OUTER as a keyword, we are well within our
rights to return an error here.
The SQL specification prohibits constructions like
SELECT * FROM a NATURAL JOIN (b)
where b sits alone inside parentheses. Parentheses in a FROM entry
always introduce either a derived table or a join.
This commit adds support for derived tables (i.e., subqueries) that
incorporate set operations, like:
SELECT * FROM (((SELECT 1) UNION (SELECT 2)) t1 AS NATURAL JOIN t2)
This introduces a bit of complexity around determining whether a left
paren starts a subquery, starts a nested join, or belongs to an
already-started subquery. The details are explained in a comment within
the patch.
`parse_value` handles parsing a non-integer value in expression context,
and we use parse_literal_uint() when expecting a number in other
contexts (such as `FETCH FIRST ... ROWS`)
It is useful downstream to have two separate enums, one for unary
operators and one for binary operators, so that the compiler can check
exhaustiveness. Otherwise downstream consumers need to manually encode
which operators are unary and which operators are binary when matching
on an Operator enum.
These were previously called "BinaryExpr" and "Unary"; besides being
inconsistent, it's also not correct to say "binary expression" or "unary
expression", as it's the operators that have arities, not the
expression. Adjust the naming of the variants accordingly.
SELECT * FROM (((SELECT 1))) is just as valid as
SELECT * FROM (SELECT 1). Add a test to ensure that we can parse the
first form.
Addresses a comment from #100.