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:
parent
6a9f79ad87
commit
d8f463a3b8
5 changed files with 39 additions and 0 deletions
|
@ -28,6 +28,7 @@ module Arel
|
|||
Group
|
||||
GroupingElement
|
||||
GroupingSet
|
||||
Lateral
|
||||
Limit
|
||||
Lock
|
||||
Not
|
||||
|
|
|
@ -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}")
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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%')
|
||||
|
|
Loading…
Reference in a new issue