diff options
author | Ville Lautanala <lautis@gmail.com> | 2017-04-25 07:41:52 +0300 |
---|---|---|
committer | Ville Lautanala <lautis@gmail.com> | 2017-04-25 07:56:26 +0300 |
commit | d8f463a3b87ff9f69eef2a3ed5718b198c2072a1 (patch) | |
tree | 2bb34207722f3f9d23275a4c1c827fa019f45850 /lib/arel | |
parent | 6a9f79ad876b930ab8cb17acf70b95c1cc800f8d (diff) | |
download | rails-d8f463a3b87ff9f69eef2a3ed5718b198c2072a1.tar.gz rails-d8f463a3b87ff9f69eef2a3ed5718b198c2072a1.tar.bz2 rails-d8f463a3b87ff9f69eef2a3ed5718b198c2072a1.zip |
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.
Diffstat (limited to 'lib/arel')
-rw-r--r-- | lib/arel/nodes/unary.rb | 1 | ||||
-rw-r--r-- | lib/arel/select_manager.rb | 5 | ||||
-rw-r--r-- | lib/arel/visitors/depth_first.rb | 1 | ||||
-rw-r--r-- | lib/arel/visitors/postgresql.rb | 18 |
4 files changed, 25 insertions, 0 deletions
diff --git a/lib/arel/nodes/unary.rb b/lib/arel/nodes/unary.rb index a42744b1d5..60cff1defe 100644 --- a/lib/arel/nodes/unary.rb +++ b/lib/arel/nodes/unary.rb @@ -28,6 +28,7 @@ module Arel Group GroupingElement GroupingSet + Lateral Limit Lock Not diff --git a/lib/arel/select_manager.rb b/lib/arel/select_manager.rb index 0b35176842..73fa5da6ed 100644 --- a/lib/arel/select_manager.rb +++ b/lib/arel/select_manager.rb @@ -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}") diff --git a/lib/arel/visitors/depth_first.rb b/lib/arel/visitors/depth_first.rb index 5416a285f5..b3bbc9bd40 100644 --- a/lib/arel/visitors/depth_first.rb +++ b/lib/arel/visitors/depth_first.rb @@ -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 diff --git a/lib/arel/visitors/postgresql.rb b/lib/arel/visitors/postgresql.rb index f0991a2f11..bd4421bd58 100644 --- a/lib/arel/visitors/postgresql.rb +++ b/lib/arel/visitors/postgresql.rb @@ -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 |