1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

PostgreSQL lateral expressions

Support for PostgreSQL lateral expressions. This is treated as an unary
function applied to a query expression.

Lateral is a separate function to provide interoperability with aliases
and unions. These are also separate node types that wrap
SelectStatements. The lateral option would need to be implemented in
these nodes separately if lateral was an option of SelectStatement.

When building the query, an alias can be given as an argument. This
enables building a lateral query with an table alias without using
either Nodes::TableAlias or Nodes::Lateral directly.
This commit is contained in:
Ville Lautanala 2017-04-25 07:41:52 +03:00
parent 6a9f79ad87
commit d8f463a3b8
5 changed files with 39 additions and 0 deletions

View file

@ -28,6 +28,7 @@ module Arel
Group
GroupingElement
GroupingSet
Lateral
Limit
Lock
Not

View file

@ -204,6 +204,11 @@ module Arel
end
alias :minus :except
def lateral table_name = nil
base = table_name.nil? ? ast : as(table_name)
Nodes::Lateral.new(base)
end
def with *subqueries
if subqueries.first.is_a? Symbol
node_class = Nodes.const_get("With#{subqueries.shift.to_s.capitalize}")

View file

@ -25,6 +25,7 @@ module Arel
alias :visit_Arel_Nodes_GroupingElement :unary
alias :visit_Arel_Nodes_Grouping :unary
alias :visit_Arel_Nodes_Having :unary
alias :visit_Arel_Nodes_Lateral :unary
alias :visit_Arel_Nodes_Limit :unary
alias :visit_Arel_Nodes_Not :unary
alias :visit_Arel_Nodes_Offset :unary

View file

@ -5,6 +5,7 @@ module Arel
CUBE = 'CUBE'
ROLLUP = 'ROLLUP'
GROUPING_SET = 'GROUPING SET'
LATERAL = 'LATERAL'
private
@ -69,6 +70,23 @@ module Arel
grouping_array_or_grouping_element o, collector
end
def visit_Arel_Nodes_Lateral o, collector
collector << LATERAL
collector << SPACE
grouping_parentheses o, collector
end
# Used by Lateral visitor to enclose select queries in parentheses
def grouping_parentheses o, collector
if o.expr.is_a? Nodes::SelectStatement
collector << "("
visit o.expr, collector
collector << ")"
else
visit o.expr, collector
end
end
# Utilized by GroupingSet, Cube & RollUp visitors to
# handle grouping aggregation semantics
def grouping_array_or_grouping_element o, collector

View file

@ -51,6 +51,20 @@ module Arel
assert_equal 'SELECT DISTINCT', compile(core)
end
it 'encloses LATERAL queries in parens' do
subquery = @table.project(:id).where(@table[:name].matches('foo%'))
compile(subquery.lateral).must_be_like %{
LATERAL (SELECT id FROM "users" WHERE "users"."name" ILIKE 'foo%')
}
end
it 'produces LATERAL queries with alias' do
subquery = @table.project(:id).where(@table[:name].matches('foo%'))
compile(subquery.lateral('bar')).must_be_like %{
LATERAL (SELECT id FROM "users" WHERE "users"."name" ILIKE 'foo%') bar
}
end
describe "Nodes::Matches" do
it "should know how to visit" do
node = @table[:name].matches('foo%')