arel 3.0.2 → 3.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +4 -3
- data/History.txt +51 -0
- data/Manifest.txt +6 -0
- data/README.markdown +1 -1
- data/arel.gemspec +27 -19
- data/lib/arel.rb +2 -1
- data/lib/arel/expressions.rb +4 -0
- data/lib/arel/nodes.rb +5 -0
- data/lib/arel/nodes/extract.rb +23 -0
- data/lib/arel/nodes/function.rb +1 -0
- data/lib/arel/nodes/over.rb +15 -0
- data/lib/arel/nodes/select_core.rb +3 -1
- data/lib/arel/nodes/window.rb +78 -0
- data/lib/arel/select_manager.rb +6 -0
- data/lib/arel/visitors/depth_first.rb +3 -0
- data/lib/arel/visitors/dot.rb +25 -0
- data/lib/arel/visitors/informix.rb +1 -1
- data/lib/arel/visitors/oracle.rb +2 -1
- data/lib/arel/visitors/to_sql.rb +68 -2
- data/lib/arel/window_predications.rb +9 -0
- data/test/nodes/test_extract.rb +19 -0
- data/test/nodes/test_over.rb +49 -0
- data/test/test_select_manager.rb +156 -0
- data/test/visitors/test_depth_first.rb +10 -2
- data/test/visitors/test_informix.rb +10 -0
- data/test/visitors/test_oracle.rb +2 -1
- data/test/visitors/test_to_sql.rb +4 -8
- metadata +88 -54
data/Gemfile
CHANGED
@@ -2,10 +2,11 @@
|
|
2
2
|
|
3
3
|
# DO NOT EDIT THIS FILE. Instead, edit Rakefile, and run `rake bundler:gemfile`.
|
4
4
|
|
5
|
-
source
|
5
|
+
source "https://rubygems.org/"
|
6
6
|
|
7
7
|
|
8
|
-
gem "minitest", "~>
|
9
|
-
gem "
|
8
|
+
gem "minitest", "~>4.7", :group => [:development, :test]
|
9
|
+
gem "rdoc", "~>4.0", :group => [:development, :test]
|
10
|
+
gem "hoe", "~>3.6", :group => [:development, :test]
|
10
11
|
|
11
12
|
# vim: syntax=ruby
|
data/History.txt
CHANGED
@@ -1,3 +1,54 @@
|
|
1
|
+
== 3.0.3 / 2013-11-12
|
2
|
+
|
3
|
+
* Enhancements
|
4
|
+
|
5
|
+
* Support ANSI 2003 window functions
|
6
|
+
|
7
|
+
* Bug Fixes
|
8
|
+
|
9
|
+
* Fix joins in Informix
|
10
|
+
|
11
|
+
== 3.0.2 / 2012-02-21
|
12
|
+
|
13
|
+
* Enhancements
|
14
|
+
|
15
|
+
* Added a module for visiting and transforming bind values
|
16
|
+
* Fix in [] to be false, not in [] to be true
|
17
|
+
|
18
|
+
* Bug Fixes
|
19
|
+
|
20
|
+
* Revert fix for LIMIT / OFFSET when query is ordered in Oracle
|
21
|
+
|
22
|
+
== 3.0.1 / 2012-02-17
|
23
|
+
|
24
|
+
* Bug Fixes
|
25
|
+
|
26
|
+
* Fixed LIMIT / OFFSET when query is ordered in Oracle
|
27
|
+
|
28
|
+
== 3.0.0 / 2012-01-12
|
29
|
+
|
30
|
+
* Enhancements
|
31
|
+
|
32
|
+
* Support connection pool and schema cache
|
33
|
+
|
34
|
+
* Bug Fixes
|
35
|
+
|
36
|
+
* Conditions with no column can be followed by other conditions in Postgres
|
37
|
+
|
38
|
+
== 2.2.3 / 2012-02-21
|
39
|
+
|
40
|
+
* Enhancements
|
41
|
+
|
42
|
+
* Added a module for visiting and transforming bind values
|
43
|
+
|
44
|
+
== 2.2.2 / 2012-02-20
|
45
|
+
|
46
|
+
* Enhancements
|
47
|
+
|
48
|
+
* Support LOCK
|
49
|
+
* Allow using non-table alias as a right-hand relation name
|
50
|
+
* Added SelectManager#distinct
|
51
|
+
|
1
52
|
== 2.2.1 / 2011-09-15
|
2
53
|
|
3
54
|
* Enhancements
|
data/Manifest.txt
CHANGED
@@ -29,6 +29,7 @@ lib/arel/nodes/count.rb
|
|
29
29
|
lib/arel/nodes/delete_statement.rb
|
30
30
|
lib/arel/nodes/descending.rb
|
31
31
|
lib/arel/nodes/equality.rb
|
32
|
+
lib/arel/nodes/extract.rb
|
32
33
|
lib/arel/nodes/false.rb
|
33
34
|
lib/arel/nodes/function.rb
|
34
35
|
lib/arel/nodes/in.rb
|
@@ -40,6 +41,7 @@ lib/arel/nodes/named_function.rb
|
|
40
41
|
lib/arel/nodes/node.rb
|
41
42
|
lib/arel/nodes/ordering.rb
|
42
43
|
lib/arel/nodes/outer_join.rb
|
44
|
+
lib/arel/nodes/over.rb
|
43
45
|
lib/arel/nodes/select_core.rb
|
44
46
|
lib/arel/nodes/select_statement.rb
|
45
47
|
lib/arel/nodes/sql_literal.rb
|
@@ -51,6 +53,7 @@ lib/arel/nodes/unary.rb
|
|
51
53
|
lib/arel/nodes/unqualified_column.rb
|
52
54
|
lib/arel/nodes/update_statement.rb
|
53
55
|
lib/arel/nodes/values.rb
|
56
|
+
lib/arel/nodes/window.rb
|
54
57
|
lib/arel/nodes/with.rb
|
55
58
|
lib/arel/order_predications.rb
|
56
59
|
lib/arel/predications.rb
|
@@ -77,6 +80,7 @@ lib/arel/visitors/sqlite.rb
|
|
77
80
|
lib/arel/visitors/to_sql.rb
|
78
81
|
lib/arel/visitors/visitor.rb
|
79
82
|
lib/arel/visitors/where_sql.rb
|
83
|
+
lib/arel/window_predications.rb
|
80
84
|
test/attributes/test_attribute.rb
|
81
85
|
test/helper.rb
|
82
86
|
test/nodes/test_as.rb
|
@@ -86,12 +90,14 @@ test/nodes/test_count.rb
|
|
86
90
|
test/nodes/test_delete_statement.rb
|
87
91
|
test/nodes/test_descending.rb
|
88
92
|
test/nodes/test_equality.rb
|
93
|
+
test/nodes/test_extract.rb
|
89
94
|
test/nodes/test_infix_operation.rb
|
90
95
|
test/nodes/test_insert_statement.rb
|
91
96
|
test/nodes/test_named_function.rb
|
92
97
|
test/nodes/test_node.rb
|
93
98
|
test/nodes/test_not.rb
|
94
99
|
test/nodes/test_or.rb
|
100
|
+
test/nodes/test_over.rb
|
95
101
|
test/nodes/test_select_core.rb
|
96
102
|
test/nodes/test_select_statement.rb
|
97
103
|
test/nodes/test_sql_literal.rb
|
data/README.markdown
CHANGED
@@ -83,7 +83,7 @@ The examples above are fairly simple and other libraries match or come close to
|
|
83
83
|
|
84
84
|
#### Inline math operations
|
85
85
|
|
86
|
-
Suppose we have a table `products` with prices in different currencies. And we have a table currency_rates
|
86
|
+
Suppose we have a table `products` with prices in different currencies. And we have a table `currency_rates`, of constantly changing currency rates. In Arel:
|
87
87
|
|
88
88
|
products = Arel::Table.new(:products)
|
89
89
|
products.columns # => [products[:id], products[:name], products[:price], products[:currency_id]]
|
data/arel.gemspec
CHANGED
@@ -1,39 +1,47 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
|
-
s.name =
|
5
|
-
s.version = "3.0.
|
4
|
+
s.name = %q{arel}
|
5
|
+
s.version = "3.0.3.20131114190737"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Aaron Patterson", "Bryan Halmkamp", "Emilio Tagua", "Nick Kallen"]
|
9
|
-
s.date =
|
10
|
-
s.description =
|
9
|
+
s.date = %q{2013-11-14}
|
10
|
+
s.description = %q{Arel is a SQL AST manager for Ruby. It
|
11
|
+
|
12
|
+
1. Simplifies the generation of complex SQL queries
|
13
|
+
2. Adapts to various RDBMS systems
|
14
|
+
|
15
|
+
It is intended to be a framework framework; that is, you can build your own ORM
|
16
|
+
with it, focusing on innovative object and collection modeling as opposed to
|
17
|
+
database compatibility and query generation.}
|
11
18
|
s.email = ["aaron@tenderlovemaking.com", "bryan@brynary.com", "miloops@gmail.com", "nick@example.org"]
|
12
19
|
s.extra_rdoc_files = ["History.txt", "MIT-LICENSE.txt", "Manifest.txt", "README.markdown"]
|
13
|
-
s.files = [".autotest", ".gemtest", ".travis.yml", "Gemfile", "History.txt", "MIT-LICENSE.txt", "Manifest.txt", "README.markdown", "Rakefile", "arel.gemspec", "lib/arel.rb", "lib/arel/alias_predication.rb", "lib/arel/attributes.rb", "lib/arel/attributes/attribute.rb", "lib/arel/compatibility/wheres.rb", "lib/arel/crud.rb", "lib/arel/delete_manager.rb", "lib/arel/deprecated.rb", "lib/arel/expression.rb", "lib/arel/expressions.rb", "lib/arel/factory_methods.rb", "lib/arel/insert_manager.rb", "lib/arel/math.rb", "lib/arel/nodes.rb", "lib/arel/nodes/and.rb", "lib/arel/nodes/ascending.rb", "lib/arel/nodes/binary.rb", "lib/arel/nodes/count.rb", "lib/arel/nodes/delete_statement.rb", "lib/arel/nodes/descending.rb", "lib/arel/nodes/equality.rb", "lib/arel/nodes/false.rb", "lib/arel/nodes/function.rb", "lib/arel/nodes/in.rb", "lib/arel/nodes/infix_operation.rb", "lib/arel/nodes/inner_join.rb", "lib/arel/nodes/insert_statement.rb", "lib/arel/nodes/join_source.rb", "lib/arel/nodes/named_function.rb", "lib/arel/nodes/node.rb", "lib/arel/nodes/ordering.rb", "lib/arel/nodes/outer_join.rb", "lib/arel/nodes/select_core.rb", "lib/arel/nodes/select_statement.rb", "lib/arel/nodes/sql_literal.rb", "lib/arel/nodes/string_join.rb", "lib/arel/nodes/table_alias.rb", "lib/arel/nodes/terminal.rb", "lib/arel/nodes/true.rb", "lib/arel/nodes/unary.rb", "lib/arel/nodes/unqualified_column.rb", "lib/arel/nodes/update_statement.rb", "lib/arel/nodes/values.rb", "lib/arel/nodes/with.rb", "lib/arel/order_predications.rb", "lib/arel/predications.rb", "lib/arel/relation.rb", "lib/arel/select_manager.rb", "lib/arel/sql/engine.rb", "lib/arel/sql_literal.rb", "lib/arel/table.rb", "lib/arel/tree_manager.rb", "lib/arel/update_manager.rb", "lib/arel/visitors.rb", "lib/arel/visitors/bind_visitor.rb", "lib/arel/visitors/depth_first.rb", "lib/arel/visitors/dot.rb", "lib/arel/visitors/ibm_db.rb", "lib/arel/visitors/informix.rb", "lib/arel/visitors/join_sql.rb", "lib/arel/visitors/mssql.rb", "lib/arel/visitors/mysql.rb", "lib/arel/visitors/oracle.rb", "lib/arel/visitors/order_clauses.rb", "lib/arel/visitors/postgresql.rb", "lib/arel/visitors/sqlite.rb", "lib/arel/visitors/to_sql.rb", "lib/arel/visitors/visitor.rb", "lib/arel/visitors/where_sql.rb", "test/attributes/test_attribute.rb", "test/helper.rb", "test/nodes/test_as.rb", "test/nodes/test_ascending.rb", "test/nodes/test_bin.rb", "test/nodes/test_count.rb", "test/nodes/test_delete_statement.rb", "test/nodes/test_descending.rb", "test/nodes/test_equality.rb", "test/nodes/test_infix_operation.rb", "test/nodes/test_insert_statement.rb", "test/nodes/test_named_function.rb", "test/nodes/test_node.rb", "test/nodes/test_not.rb", "test/nodes/test_or.rb", "test/nodes/test_select_core.rb", "test/nodes/test_select_statement.rb", "test/nodes/test_sql_literal.rb", "test/nodes/test_sum.rb", "test/nodes/test_update_statement.rb", "test/support/fake_record.rb", "test/test_activerecord_compat.rb", "test/test_attributes.rb", "test/test_crud.rb", "test/test_delete_manager.rb", "test/test_factory_methods.rb", "test/test_insert_manager.rb", "test/test_select_manager.rb", "test/test_table.rb", "test/test_update_manager.rb", "test/visitors/test_bind_visitor.rb", "test/visitors/test_depth_first.rb", "test/visitors/test_dot.rb", "test/visitors/test_ibm_db.rb", "test/visitors/test_informix.rb", "test/visitors/test_join_sql.rb", "test/visitors/test_mssql.rb", "test/visitors/test_mysql.rb", "test/visitors/test_oracle.rb", "test/visitors/test_postgres.rb", "test/visitors/test_sqlite.rb", "test/visitors/test_to_sql.rb"]
|
14
|
-
s.homepage =
|
20
|
+
s.files = [".autotest", ".gemtest", ".travis.yml", "Gemfile", "History.txt", "MIT-LICENSE.txt", "Manifest.txt", "README.markdown", "Rakefile", "arel.gemspec", "lib/arel.rb", "lib/arel/alias_predication.rb", "lib/arel/attributes.rb", "lib/arel/attributes/attribute.rb", "lib/arel/compatibility/wheres.rb", "lib/arel/crud.rb", "lib/arel/delete_manager.rb", "lib/arel/deprecated.rb", "lib/arel/expression.rb", "lib/arel/expressions.rb", "lib/arel/factory_methods.rb", "lib/arel/insert_manager.rb", "lib/arel/math.rb", "lib/arel/nodes.rb", "lib/arel/nodes/and.rb", "lib/arel/nodes/ascending.rb", "lib/arel/nodes/binary.rb", "lib/arel/nodes/count.rb", "lib/arel/nodes/delete_statement.rb", "lib/arel/nodes/descending.rb", "lib/arel/nodes/equality.rb", "lib/arel/nodes/extract.rb", "lib/arel/nodes/false.rb", "lib/arel/nodes/function.rb", "lib/arel/nodes/in.rb", "lib/arel/nodes/infix_operation.rb", "lib/arel/nodes/inner_join.rb", "lib/arel/nodes/insert_statement.rb", "lib/arel/nodes/join_source.rb", "lib/arel/nodes/named_function.rb", "lib/arel/nodes/node.rb", "lib/arel/nodes/ordering.rb", "lib/arel/nodes/outer_join.rb", "lib/arel/nodes/over.rb", "lib/arel/nodes/select_core.rb", "lib/arel/nodes/select_statement.rb", "lib/arel/nodes/sql_literal.rb", "lib/arel/nodes/string_join.rb", "lib/arel/nodes/table_alias.rb", "lib/arel/nodes/terminal.rb", "lib/arel/nodes/true.rb", "lib/arel/nodes/unary.rb", "lib/arel/nodes/unqualified_column.rb", "lib/arel/nodes/update_statement.rb", "lib/arel/nodes/values.rb", "lib/arel/nodes/window.rb", "lib/arel/nodes/with.rb", "lib/arel/order_predications.rb", "lib/arel/predications.rb", "lib/arel/relation.rb", "lib/arel/select_manager.rb", "lib/arel/sql/engine.rb", "lib/arel/sql_literal.rb", "lib/arel/table.rb", "lib/arel/tree_manager.rb", "lib/arel/update_manager.rb", "lib/arel/visitors.rb", "lib/arel/visitors/bind_visitor.rb", "lib/arel/visitors/depth_first.rb", "lib/arel/visitors/dot.rb", "lib/arel/visitors/ibm_db.rb", "lib/arel/visitors/informix.rb", "lib/arel/visitors/join_sql.rb", "lib/arel/visitors/mssql.rb", "lib/arel/visitors/mysql.rb", "lib/arel/visitors/oracle.rb", "lib/arel/visitors/order_clauses.rb", "lib/arel/visitors/postgresql.rb", "lib/arel/visitors/sqlite.rb", "lib/arel/visitors/to_sql.rb", "lib/arel/visitors/visitor.rb", "lib/arel/visitors/where_sql.rb", "lib/arel/window_predications.rb", "test/attributes/test_attribute.rb", "test/helper.rb", "test/nodes/test_as.rb", "test/nodes/test_ascending.rb", "test/nodes/test_bin.rb", "test/nodes/test_count.rb", "test/nodes/test_delete_statement.rb", "test/nodes/test_descending.rb", "test/nodes/test_equality.rb", "test/nodes/test_extract.rb", "test/nodes/test_infix_operation.rb", "test/nodes/test_insert_statement.rb", "test/nodes/test_named_function.rb", "test/nodes/test_node.rb", "test/nodes/test_not.rb", "test/nodes/test_or.rb", "test/nodes/test_over.rb", "test/nodes/test_select_core.rb", "test/nodes/test_select_statement.rb", "test/nodes/test_sql_literal.rb", "test/nodes/test_sum.rb", "test/nodes/test_update_statement.rb", "test/support/fake_record.rb", "test/test_activerecord_compat.rb", "test/test_attributes.rb", "test/test_crud.rb", "test/test_delete_manager.rb", "test/test_factory_methods.rb", "test/test_insert_manager.rb", "test/test_select_manager.rb", "test/test_table.rb", "test/test_update_manager.rb", "test/visitors/test_bind_visitor.rb", "test/visitors/test_depth_first.rb", "test/visitors/test_dot.rb", "test/visitors/test_ibm_db.rb", "test/visitors/test_informix.rb", "test/visitors/test_join_sql.rb", "test/visitors/test_mssql.rb", "test/visitors/test_mysql.rb", "test/visitors/test_oracle.rb", "test/visitors/test_postgres.rb", "test/visitors/test_sqlite.rb", "test/visitors/test_to_sql.rb"]
|
21
|
+
s.homepage = %q{http://github.com/rails/arel}
|
22
|
+
s.licenses = ["MIT"]
|
15
23
|
s.rdoc_options = ["--main", "README.markdown"]
|
16
24
|
s.require_paths = ["lib"]
|
17
|
-
s.rubyforge_project =
|
18
|
-
s.rubygems_version =
|
19
|
-
s.summary =
|
20
|
-
s.test_files = ["test/attributes/test_attribute.rb", "test/nodes/test_as.rb", "test/nodes/test_ascending.rb", "test/nodes/test_bin.rb", "test/nodes/test_count.rb", "test/nodes/test_delete_statement.rb", "test/nodes/test_descending.rb", "test/nodes/test_equality.rb", "test/nodes/test_infix_operation.rb", "test/nodes/test_insert_statement.rb", "test/nodes/test_named_function.rb", "test/nodes/test_node.rb", "test/nodes/test_not.rb", "test/nodes/test_or.rb", "test/nodes/test_select_core.rb", "test/nodes/test_select_statement.rb", "test/nodes/test_sql_literal.rb", "test/nodes/test_sum.rb", "test/nodes/test_update_statement.rb", "test/test_activerecord_compat.rb", "test/test_attributes.rb", "test/test_crud.rb", "test/test_delete_manager.rb", "test/test_factory_methods.rb", "test/test_insert_manager.rb", "test/test_select_manager.rb", "test/test_table.rb", "test/test_update_manager.rb", "test/visitors/test_bind_visitor.rb", "test/visitors/test_depth_first.rb", "test/visitors/test_dot.rb", "test/visitors/test_ibm_db.rb", "test/visitors/test_informix.rb", "test/visitors/test_join_sql.rb", "test/visitors/test_mssql.rb", "test/visitors/test_mysql.rb", "test/visitors/test_oracle.rb", "test/visitors/test_postgres.rb", "test/visitors/test_sqlite.rb", "test/visitors/test_to_sql.rb"]
|
25
|
+
s.rubyforge_project = %q{arel}
|
26
|
+
s.rubygems_version = %q{1.6.2}
|
27
|
+
s.summary = %q{Arel is a SQL AST manager for Ruby}
|
28
|
+
s.test_files = ["test/attributes/test_attribute.rb", "test/nodes/test_as.rb", "test/nodes/test_ascending.rb", "test/nodes/test_bin.rb", "test/nodes/test_count.rb", "test/nodes/test_delete_statement.rb", "test/nodes/test_descending.rb", "test/nodes/test_equality.rb", "test/nodes/test_extract.rb", "test/nodes/test_infix_operation.rb", "test/nodes/test_insert_statement.rb", "test/nodes/test_named_function.rb", "test/nodes/test_node.rb", "test/nodes/test_not.rb", "test/nodes/test_or.rb", "test/nodes/test_over.rb", "test/nodes/test_select_core.rb", "test/nodes/test_select_statement.rb", "test/nodes/test_sql_literal.rb", "test/nodes/test_sum.rb", "test/nodes/test_update_statement.rb", "test/test_activerecord_compat.rb", "test/test_attributes.rb", "test/test_crud.rb", "test/test_delete_manager.rb", "test/test_factory_methods.rb", "test/test_insert_manager.rb", "test/test_select_manager.rb", "test/test_table.rb", "test/test_update_manager.rb", "test/visitors/test_bind_visitor.rb", "test/visitors/test_depth_first.rb", "test/visitors/test_dot.rb", "test/visitors/test_ibm_db.rb", "test/visitors/test_informix.rb", "test/visitors/test_join_sql.rb", "test/visitors/test_mssql.rb", "test/visitors/test_mysql.rb", "test/visitors/test_oracle.rb", "test/visitors/test_postgres.rb", "test/visitors/test_sqlite.rb", "test/visitors/test_to_sql.rb"]
|
21
29
|
|
22
30
|
if s.respond_to? :specification_version then
|
23
31
|
s.specification_version = 3
|
24
32
|
|
25
33
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
26
|
-
s.add_development_dependency(%q<minitest>, ["~>
|
27
|
-
s.add_development_dependency(%q<rdoc>, ["~>
|
28
|
-
s.add_development_dependency(%q<hoe>, ["~>
|
34
|
+
s.add_development_dependency(%q<minitest>, ["~> 4.7"])
|
35
|
+
s.add_development_dependency(%q<rdoc>, ["~> 4.0"])
|
36
|
+
s.add_development_dependency(%q<hoe>, ["~> 3.7"])
|
29
37
|
else
|
30
|
-
s.add_dependency(%q<minitest>, ["~>
|
31
|
-
s.add_dependency(%q<rdoc>, ["~>
|
32
|
-
s.add_dependency(%q<hoe>, ["~>
|
38
|
+
s.add_dependency(%q<minitest>, ["~> 4.7"])
|
39
|
+
s.add_dependency(%q<rdoc>, ["~> 4.0"])
|
40
|
+
s.add_dependency(%q<hoe>, ["~> 3.7"])
|
33
41
|
end
|
34
42
|
else
|
35
|
-
s.add_dependency(%q<minitest>, ["~>
|
36
|
-
s.add_dependency(%q<rdoc>, ["~>
|
37
|
-
s.add_dependency(%q<hoe>, ["~>
|
43
|
+
s.add_dependency(%q<minitest>, ["~> 4.7"])
|
44
|
+
s.add_dependency(%q<rdoc>, ["~> 4.0"])
|
45
|
+
s.add_dependency(%q<hoe>, ["~> 3.7"])
|
38
46
|
end
|
39
47
|
end
|
data/lib/arel.rb
CHANGED
@@ -3,6 +3,7 @@ require 'arel/factory_methods'
|
|
3
3
|
|
4
4
|
require 'arel/expressions'
|
5
5
|
require 'arel/predications'
|
6
|
+
require 'arel/window_predications'
|
6
7
|
require 'arel/math'
|
7
8
|
require 'arel/alias_predication'
|
8
9
|
require 'arel/order_predications'
|
@@ -33,7 +34,7 @@ require 'arel/sql_literal'
|
|
33
34
|
####
|
34
35
|
|
35
36
|
module Arel
|
36
|
-
VERSION = '3.0.
|
37
|
+
VERSION = '3.0.3'
|
37
38
|
|
38
39
|
def self.sql raw_sql
|
39
40
|
Arel::Nodes::SqlLiteral.new raw_sql
|
data/lib/arel/expressions.rb
CHANGED
data/lib/arel/nodes.rb
CHANGED
@@ -26,6 +26,7 @@ require 'arel/nodes/join_source'
|
|
26
26
|
require 'arel/nodes/delete_statement'
|
27
27
|
require 'arel/nodes/table_alias'
|
28
28
|
require 'arel/nodes/infix_operation'
|
29
|
+
require 'arel/nodes/over'
|
29
30
|
|
30
31
|
# nary
|
31
32
|
require 'arel/nodes/and'
|
@@ -35,9 +36,13 @@ require 'arel/nodes/and'
|
|
35
36
|
# We should make Function a Unary node and deprecate the use of "aliaz"
|
36
37
|
require 'arel/nodes/function'
|
37
38
|
require 'arel/nodes/count'
|
39
|
+
require 'arel/nodes/extract'
|
38
40
|
require 'arel/nodes/values'
|
39
41
|
require 'arel/nodes/named_function'
|
40
42
|
|
43
|
+
# windows
|
44
|
+
require 'arel/nodes/window'
|
45
|
+
|
41
46
|
# joins
|
42
47
|
require 'arel/nodes/inner_join'
|
43
48
|
require 'arel/nodes/outer_join'
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Arel
|
2
|
+
module Nodes
|
3
|
+
|
4
|
+
class Extract < Arel::Nodes::Unary
|
5
|
+
include Arel::Expression
|
6
|
+
include Arel::Predications
|
7
|
+
|
8
|
+
attr_accessor :field
|
9
|
+
attr_accessor :alias
|
10
|
+
|
11
|
+
def initialize expr, field, aliaz = nil
|
12
|
+
super(expr)
|
13
|
+
@field = field
|
14
|
+
@alias = aliaz && SqlLiteral.new(aliaz)
|
15
|
+
end
|
16
|
+
|
17
|
+
def as aliaz
|
18
|
+
self.alias = SqlLiteral.new(aliaz)
|
19
|
+
self
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/arel/nodes/function.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Arel
|
2
2
|
module Nodes
|
3
3
|
class SelectCore < Arel::Nodes::Node
|
4
|
-
attr_accessor :top, :projections, :wheres, :groups
|
4
|
+
attr_accessor :top, :projections, :wheres, :groups, :windows
|
5
5
|
attr_accessor :having, :source, :set_quantifier
|
6
6
|
|
7
7
|
def initialize
|
@@ -14,6 +14,7 @@ module Arel
|
|
14
14
|
@wheres = []
|
15
15
|
@groups = []
|
16
16
|
@having = nil
|
17
|
+
@windows = []
|
17
18
|
end
|
18
19
|
|
19
20
|
def from
|
@@ -34,6 +35,7 @@ module Arel
|
|
34
35
|
@wheres = @wheres.clone
|
35
36
|
@groups = @groups.clone
|
36
37
|
@having = @having.clone if @having
|
38
|
+
@windows = @windows.clone
|
37
39
|
end
|
38
40
|
end
|
39
41
|
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module Arel
|
2
|
+
module Nodes
|
3
|
+
class Window < Arel::Nodes::Node
|
4
|
+
include Arel::Expression
|
5
|
+
attr_accessor :orders, :framing
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@orders = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def order *expr
|
12
|
+
# FIXME: We SHOULD NOT be converting these to SqlLiteral automatically
|
13
|
+
@orders.concat expr.map { |x|
|
14
|
+
String === x || Symbol === x ? Nodes::SqlLiteral.new(x.to_s) : x
|
15
|
+
}
|
16
|
+
self
|
17
|
+
end
|
18
|
+
|
19
|
+
def frame(expr)
|
20
|
+
raise ArgumentError, "Window frame cannot be set more than once" if @frame
|
21
|
+
@framing = expr
|
22
|
+
end
|
23
|
+
|
24
|
+
def rows(expr = nil)
|
25
|
+
frame(Rows.new(expr))
|
26
|
+
end
|
27
|
+
|
28
|
+
def range(expr = nil)
|
29
|
+
frame(Range.new(expr))
|
30
|
+
end
|
31
|
+
|
32
|
+
def initialize_copy other
|
33
|
+
super
|
34
|
+
@orders = @orders.map { |x| x.clone }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class NamedWindow < Window
|
39
|
+
attr_accessor :name
|
40
|
+
|
41
|
+
def initialize name
|
42
|
+
super()
|
43
|
+
@name = name
|
44
|
+
end
|
45
|
+
|
46
|
+
def initialize_copy other
|
47
|
+
super
|
48
|
+
@name = other.name.clone
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class Rows < Unary
|
53
|
+
def initialize(expr = nil)
|
54
|
+
super(expr)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
class Range < Unary
|
59
|
+
def initialize(expr = nil)
|
60
|
+
super(expr)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
class CurrentRow < Arel::Nodes::Node; end
|
65
|
+
|
66
|
+
class Preceding < Unary
|
67
|
+
def initialize(expr = nil)
|
68
|
+
super(expr)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
class Following < Unary
|
73
|
+
def initialize(expr = nil)
|
74
|
+
super(expr)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
data/lib/arel/select_manager.rb
CHANGED
@@ -126,6 +126,12 @@ module Arel
|
|
126
126
|
self
|
127
127
|
end
|
128
128
|
|
129
|
+
def window name
|
130
|
+
window = Nodes::NamedWindow.new(name)
|
131
|
+
@ctx.windows.push window
|
132
|
+
window
|
133
|
+
end
|
134
|
+
|
129
135
|
def project *projections
|
130
136
|
# FIXME: converting these to SQLLiterals is probably not good, but
|
131
137
|
# rails tests require it.
|
@@ -70,6 +70,7 @@ module Arel
|
|
70
70
|
alias :visit_Arel_Nodes_GreaterThan :binary
|
71
71
|
alias :visit_Arel_Nodes_GreaterThanOrEqual :binary
|
72
72
|
alias :visit_Arel_Nodes_In :binary
|
73
|
+
alias :visit_Arel_Nodes_InfixOperation :binary
|
73
74
|
alias :visit_Arel_Nodes_JoinSource :binary
|
74
75
|
alias :visit_Arel_Nodes_InnerJoin :binary
|
75
76
|
alias :visit_Arel_Nodes_LessThan :binary
|
@@ -110,6 +111,7 @@ module Arel
|
|
110
111
|
alias :visit_Arel_Nodes_Node :terminal
|
111
112
|
alias :visit_Arel_Nodes_SqlLiteral :terminal
|
112
113
|
alias :visit_Arel_Nodes_BindParam :terminal
|
114
|
+
alias :visit_Arel_Nodes_Window :terminal
|
113
115
|
alias :visit_Arel_SqlLiteral :terminal
|
114
116
|
alias :visit_BigDecimal :terminal
|
115
117
|
alias :visit_Bignum :terminal
|
@@ -136,6 +138,7 @@ module Arel
|
|
136
138
|
visit o.source
|
137
139
|
visit o.wheres
|
138
140
|
visit o.groups
|
141
|
+
visit o.windows
|
139
142
|
visit o.having
|
140
143
|
end
|
141
144
|
|
data/lib/arel/visitors/dot.rb
CHANGED
@@ -74,6 +74,23 @@ module Arel
|
|
74
74
|
alias :visit_Arel_Nodes_On :unary
|
75
75
|
alias :visit_Arel_Nodes_Top :unary
|
76
76
|
alias :visit_Arel_Nodes_UnqualifiedColumn :unary
|
77
|
+
alias :visit_Arel_Nodes_Preceding :unary
|
78
|
+
alias :visit_Arel_Nodes_Following :unary
|
79
|
+
alias :visit_Arel_Nodes_Rows :unary
|
80
|
+
alias :visit_Arel_Nodes_Range :unary
|
81
|
+
|
82
|
+
def window o
|
83
|
+
visit_edge o, "orders"
|
84
|
+
visit_edge o, "framing"
|
85
|
+
end
|
86
|
+
alias :visit_Arel_Nodes_Window :window
|
87
|
+
|
88
|
+
def named_window o
|
89
|
+
visit_edge o, "orders"
|
90
|
+
visit_edge o, "framing"
|
91
|
+
visit_edge o, "name"
|
92
|
+
end
|
93
|
+
alias :visit_Arel_Nodes_NamedWindow :named_window
|
77
94
|
|
78
95
|
def function o
|
79
96
|
visit_edge o, "expressions"
|
@@ -86,6 +103,12 @@ module Arel
|
|
86
103
|
alias :visit_Arel_Nodes_Avg :function
|
87
104
|
alias :visit_Arel_Nodes_Sum :function
|
88
105
|
|
106
|
+
def extract o
|
107
|
+
visit_edge o, "expressions"
|
108
|
+
visit_edge o, "alias"
|
109
|
+
end
|
110
|
+
alias :visit_Arel_Nodes_Extract :extract
|
111
|
+
|
89
112
|
def visit_Arel_Nodes_NamedFunction o
|
90
113
|
visit_edge o, "name"
|
91
114
|
visit_edge o, "expressions"
|
@@ -103,6 +126,7 @@ module Arel
|
|
103
126
|
visit_edge o, "source"
|
104
127
|
visit_edge o, "projections"
|
105
128
|
visit_edge o, "wheres"
|
129
|
+
visit_edge o, "windows"
|
106
130
|
end
|
107
131
|
|
108
132
|
def visit_Arel_Nodes_SelectStatement o
|
@@ -159,6 +183,7 @@ module Arel
|
|
159
183
|
alias :visit_Arel_Nodes_NotEqual :binary
|
160
184
|
alias :visit_Arel_Nodes_NotIn :binary
|
161
185
|
alias :visit_Arel_Nodes_Or :binary
|
186
|
+
alias :visit_Arel_Nodes_Over :binary
|
162
187
|
|
163
188
|
def visit_String o
|
164
189
|
@node_stack.last.fields << o
|
@@ -15,7 +15,7 @@ module Arel
|
|
15
15
|
def visit_Arel_Nodes_SelectCore o
|
16
16
|
[
|
17
17
|
"#{o.projections.map { |x| visit x }.join ', '}",
|
18
|
-
("FROM #{visit
|
18
|
+
("FROM #{visit(o.source)}" if o.source && !o.source.empty?),
|
19
19
|
("WHERE #{o.wheres.map { |x| visit x }.join ' AND ' }" unless o.wheres.empty?),
|
20
20
|
("GROUP BY #{o.groups.map { |x| visit x }.join ', ' }" unless o.groups.empty?),
|
21
21
|
(visit(o.having) if o.having),
|
data/lib/arel/visitors/oracle.rb
CHANGED
@@ -25,8 +25,9 @@ module Arel
|
|
25
25
|
SELECT * FROM (
|
26
26
|
SELECT raw_sql_.*, rownum raw_rnum_
|
27
27
|
FROM (#{sql}) raw_sql_
|
28
|
+
WHERE rownum <= #{offset.expr.to_i + limit}
|
28
29
|
)
|
29
|
-
WHERE
|
30
|
+
WHERE #{visit offset}
|
30
31
|
eosql
|
31
32
|
end
|
32
33
|
|
data/lib/arel/visitors/to_sql.rb
CHANGED
@@ -136,6 +136,7 @@ key on UpdateManager using UpdateManager#key=
|
|
136
136
|
("WHERE #{o.wheres.map { |x| visit x }.join ' AND ' }" unless o.wheres.empty?),
|
137
137
|
("GROUP BY #{o.groups.map { |x| visit x }.join ', ' }" unless o.groups.empty?),
|
138
138
|
(visit(o.having) if o.having),
|
139
|
+
("WINDOW #{o.windows.map { |x| visit x }.join ', ' }" unless o.windows.empty?)
|
139
140
|
].compact.join ' '
|
140
141
|
end
|
141
142
|
|
@@ -175,6 +176,59 @@ key on UpdateManager using UpdateManager#key=
|
|
175
176
|
"( #{visit o.left} EXCEPT #{visit o.right} )"
|
176
177
|
end
|
177
178
|
|
179
|
+
def visit_Arel_Nodes_NamedWindow o
|
180
|
+
"#{quote_column_name o.name} AS #{visit_Arel_Nodes_Window o}"
|
181
|
+
end
|
182
|
+
|
183
|
+
def visit_Arel_Nodes_Window o
|
184
|
+
s = [
|
185
|
+
("ORDER BY #{o.orders.map { |x| visit(x) }.join(', ')}" unless o.orders.empty?),
|
186
|
+
(visit o.framing if o.framing)
|
187
|
+
].compact.join ' '
|
188
|
+
"(#{s})"
|
189
|
+
end
|
190
|
+
|
191
|
+
def visit_Arel_Nodes_Rows o
|
192
|
+
if o.expr
|
193
|
+
"ROWS #{visit o.expr}"
|
194
|
+
else
|
195
|
+
"ROWS"
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
def visit_Arel_Nodes_Range o
|
200
|
+
if o.expr
|
201
|
+
"RANGE #{visit o.expr}"
|
202
|
+
else
|
203
|
+
"RANGE"
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
def visit_Arel_Nodes_Preceding o
|
208
|
+
"#{o.expr ? visit(o.expr) : 'UNBOUNDED'} PRECEDING"
|
209
|
+
end
|
210
|
+
|
211
|
+
def visit_Arel_Nodes_Following o
|
212
|
+
"#{o.expr ? visit(o.expr) : 'UNBOUNDED'} FOLLOWING"
|
213
|
+
end
|
214
|
+
|
215
|
+
def visit_Arel_Nodes_CurrentRow o
|
216
|
+
"CURRENT ROW"
|
217
|
+
end
|
218
|
+
|
219
|
+
def visit_Arel_Nodes_Over o
|
220
|
+
case o.right
|
221
|
+
when nil
|
222
|
+
"#{visit o.left} OVER ()"
|
223
|
+
when Arel::Nodes::SqlLiteral
|
224
|
+
"#{visit o.left} OVER #{visit o.right}"
|
225
|
+
when String, Symbol
|
226
|
+
"#{visit o.left} OVER #{quote_column_name o.right.to_s}"
|
227
|
+
else
|
228
|
+
"#{visit o.left} OVER #{visit o.right}"
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
178
232
|
def visit_Arel_Nodes_Having o
|
179
233
|
"HAVING #{visit o.expr}"
|
180
234
|
end
|
@@ -218,6 +272,10 @@ key on UpdateManager using UpdateManager#key=
|
|
218
272
|
}.join(', ')})#{o.alias ? " AS #{visit o.alias}" : ''}"
|
219
273
|
end
|
220
274
|
|
275
|
+
def visit_Arel_Nodes_Extract o
|
276
|
+
"EXTRACT(#{o.field.to_s.upcase} FROM #{visit o.expr})#{o.alias ? " AS #{visit o.alias}" : ''}"
|
277
|
+
end
|
278
|
+
|
221
279
|
def visit_Arel_Nodes_Count o
|
222
280
|
"COUNT(#{o.distinct ? 'DISTINCT ' : ''}#{o.expressions.map { |x|
|
223
281
|
visit x
|
@@ -312,11 +370,19 @@ key on UpdateManager using UpdateManager#key=
|
|
312
370
|
end
|
313
371
|
|
314
372
|
def visit_Arel_Nodes_In o
|
315
|
-
|
373
|
+
if Array === o.right && o.right.empty?
|
374
|
+
'1=0'
|
375
|
+
else
|
376
|
+
"#{visit o.left} IN (#{visit o.right})"
|
377
|
+
end
|
316
378
|
end
|
317
379
|
|
318
380
|
def visit_Arel_Nodes_NotIn o
|
319
|
-
|
381
|
+
if Array === o.right && o.right.empty?
|
382
|
+
'1=1'
|
383
|
+
else
|
384
|
+
"#{visit o.left} NOT IN (#{visit o.right})"
|
385
|
+
end
|
320
386
|
end
|
321
387
|
|
322
388
|
def visit_Arel_Nodes_And o
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe Arel::Nodes::Extract do
|
4
|
+
it "should extract field" do
|
5
|
+
table = Arel::Table.new :users
|
6
|
+
table[:timestamp].extract('date').to_sql.must_be_like %{
|
7
|
+
EXTRACT(DATE FROM "users"."timestamp")
|
8
|
+
}
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "as" do
|
12
|
+
it 'should alias the extract' do
|
13
|
+
table = Arel::Table.new :users
|
14
|
+
table[:timestamp].extract('date').as('foo').to_sql.must_be_like %{
|
15
|
+
EXTRACT(DATE FROM "users"."timestamp") AS foo
|
16
|
+
}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe Arel::Nodes::Over do
|
4
|
+
describe 'as' do
|
5
|
+
it 'should alias the expression' do
|
6
|
+
table = Arel::Table.new :users
|
7
|
+
table[:id].count.over.as('foo').to_sql.must_be_like %{
|
8
|
+
COUNT("users"."id") OVER () AS foo
|
9
|
+
}
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe 'with literal' do
|
14
|
+
it 'should reference the window definition by name' do
|
15
|
+
table = Arel::Table.new :users
|
16
|
+
table[:id].count.over('foo').to_sql.must_be_like %{
|
17
|
+
COUNT("users"."id") OVER "foo"
|
18
|
+
}
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe 'with SQL literal' do
|
23
|
+
it 'should reference the window definition by name' do
|
24
|
+
table = Arel::Table.new :users
|
25
|
+
table[:id].count.over(Arel.sql('foo')).to_sql.must_be_like %{
|
26
|
+
COUNT("users"."id") OVER foo
|
27
|
+
}
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe 'with no expression' do
|
32
|
+
it 'should use empty definition' do
|
33
|
+
table = Arel::Table.new :users
|
34
|
+
table[:id].count.over.to_sql.must_be_like %{
|
35
|
+
COUNT("users"."id") OVER ()
|
36
|
+
}
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe 'with expression' do
|
41
|
+
it 'should use definition in sub-expression' do
|
42
|
+
table = Arel::Table.new :users
|
43
|
+
window = Arel::Nodes::Window.new.order(table['foo'])
|
44
|
+
table[:id].count.over(window).to_sql.must_be_like %{
|
45
|
+
COUNT("users"."id") OVER (ORDER BY \"users\".\"foo\")
|
46
|
+
}
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/test/test_select_manager.rb
CHANGED
@@ -731,6 +731,162 @@ module Arel
|
|
731
731
|
end
|
732
732
|
end
|
733
733
|
|
734
|
+
describe 'window definition' do
|
735
|
+
it 'can be empty' do
|
736
|
+
table = Table.new :users
|
737
|
+
manager = Arel::SelectManager.new Table.engine
|
738
|
+
manager.from table
|
739
|
+
manager.window('a_window')
|
740
|
+
manager.to_sql.must_be_like %{
|
741
|
+
SELECT FROM "users" WINDOW "a_window" AS ()
|
742
|
+
}
|
743
|
+
end
|
744
|
+
|
745
|
+
it 'takes an order' do
|
746
|
+
table = Table.new :users
|
747
|
+
manager = Arel::SelectManager.new Table.engine
|
748
|
+
manager.from table
|
749
|
+
manager.window('a_window').order(table['foo'].asc)
|
750
|
+
manager.to_sql.must_be_like %{
|
751
|
+
SELECT FROM "users" WINDOW "a_window" AS (ORDER BY "users"."foo" ASC)
|
752
|
+
}
|
753
|
+
end
|
754
|
+
|
755
|
+
it 'takes a rows frame, unbounded preceding' do
|
756
|
+
table = Table.new :users
|
757
|
+
manager = Arel::SelectManager.new Table.engine
|
758
|
+
manager.from table
|
759
|
+
manager.window('a_window').rows(Arel::Nodes::Preceding.new)
|
760
|
+
manager.to_sql.must_be_like %{
|
761
|
+
SELECT FROM "users" WINDOW "a_window" AS (ROWS UNBOUNDED PRECEDING)
|
762
|
+
}
|
763
|
+
end
|
764
|
+
|
765
|
+
it 'takes a rows frame, bounded preceding' do
|
766
|
+
table = Table.new :users
|
767
|
+
manager = Arel::SelectManager.new Table.engine
|
768
|
+
manager.from table
|
769
|
+
manager.window('a_window').rows(Arel::Nodes::Preceding.new(5))
|
770
|
+
manager.to_sql.must_be_like %{
|
771
|
+
SELECT FROM "users" WINDOW "a_window" AS (ROWS 5 PRECEDING)
|
772
|
+
}
|
773
|
+
end
|
774
|
+
|
775
|
+
it 'takes a rows frame, unbounded following' do
|
776
|
+
table = Table.new :users
|
777
|
+
manager = Arel::SelectManager.new Table.engine
|
778
|
+
manager.from table
|
779
|
+
manager.window('a_window').rows(Arel::Nodes::Following.new)
|
780
|
+
manager.to_sql.must_be_like %{
|
781
|
+
SELECT FROM "users" WINDOW "a_window" AS (ROWS UNBOUNDED FOLLOWING)
|
782
|
+
}
|
783
|
+
end
|
784
|
+
|
785
|
+
it 'takes a rows frame, bounded following' do
|
786
|
+
table = Table.new :users
|
787
|
+
manager = Arel::SelectManager.new Table.engine
|
788
|
+
manager.from table
|
789
|
+
manager.window('a_window').rows(Arel::Nodes::Following.new(5))
|
790
|
+
manager.to_sql.must_be_like %{
|
791
|
+
SELECT FROM "users" WINDOW "a_window" AS (ROWS 5 FOLLOWING)
|
792
|
+
}
|
793
|
+
end
|
794
|
+
|
795
|
+
it 'takes a rows frame, current row' do
|
796
|
+
table = Table.new :users
|
797
|
+
manager = Arel::SelectManager.new Table.engine
|
798
|
+
manager.from table
|
799
|
+
manager.window('a_window').rows(Arel::Nodes::CurrentRow.new)
|
800
|
+
manager.to_sql.must_be_like %{
|
801
|
+
SELECT FROM "users" WINDOW "a_window" AS (ROWS CURRENT ROW)
|
802
|
+
}
|
803
|
+
end
|
804
|
+
|
805
|
+
it 'takes a rows frame, between two delimiters' do
|
806
|
+
table = Table.new :users
|
807
|
+
manager = Arel::SelectManager.new Table.engine
|
808
|
+
manager.from table
|
809
|
+
window = manager.window('a_window')
|
810
|
+
window.frame(
|
811
|
+
Arel::Nodes::Between.new(
|
812
|
+
window.rows,
|
813
|
+
Nodes::And.new([
|
814
|
+
Arel::Nodes::Preceding.new,
|
815
|
+
Arel::Nodes::CurrentRow.new
|
816
|
+
])))
|
817
|
+
manager.to_sql.must_be_like %{
|
818
|
+
SELECT FROM "users" WINDOW "a_window" AS (ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
|
819
|
+
}
|
820
|
+
end
|
821
|
+
|
822
|
+
it 'takes a range frame, unbounded preceding' do
|
823
|
+
table = Table.new :users
|
824
|
+
manager = Arel::SelectManager.new Table.engine
|
825
|
+
manager.from table
|
826
|
+
manager.window('a_window').range(Arel::Nodes::Preceding.new)
|
827
|
+
manager.to_sql.must_be_like %{
|
828
|
+
SELECT FROM "users" WINDOW "a_window" AS (RANGE UNBOUNDED PRECEDING)
|
829
|
+
}
|
830
|
+
end
|
831
|
+
|
832
|
+
it 'takes a range frame, bounded preceding' do
|
833
|
+
table = Table.new :users
|
834
|
+
manager = Arel::SelectManager.new Table.engine
|
835
|
+
manager.from table
|
836
|
+
manager.window('a_window').range(Arel::Nodes::Preceding.new(5))
|
837
|
+
manager.to_sql.must_be_like %{
|
838
|
+
SELECT FROM "users" WINDOW "a_window" AS (RANGE 5 PRECEDING)
|
839
|
+
}
|
840
|
+
end
|
841
|
+
|
842
|
+
it 'takes a range frame, unbounded following' do
|
843
|
+
table = Table.new :users
|
844
|
+
manager = Arel::SelectManager.new Table.engine
|
845
|
+
manager.from table
|
846
|
+
manager.window('a_window').range(Arel::Nodes::Following.new)
|
847
|
+
manager.to_sql.must_be_like %{
|
848
|
+
SELECT FROM "users" WINDOW "a_window" AS (RANGE UNBOUNDED FOLLOWING)
|
849
|
+
}
|
850
|
+
end
|
851
|
+
|
852
|
+
it 'takes a range frame, bounded following' do
|
853
|
+
table = Table.new :users
|
854
|
+
manager = Arel::SelectManager.new Table.engine
|
855
|
+
manager.from table
|
856
|
+
manager.window('a_window').range(Arel::Nodes::Following.new(5))
|
857
|
+
manager.to_sql.must_be_like %{
|
858
|
+
SELECT FROM "users" WINDOW "a_window" AS (RANGE 5 FOLLOWING)
|
859
|
+
}
|
860
|
+
end
|
861
|
+
|
862
|
+
it 'takes a range frame, current row' do
|
863
|
+
table = Table.new :users
|
864
|
+
manager = Arel::SelectManager.new Table.engine
|
865
|
+
manager.from table
|
866
|
+
manager.window('a_window').range(Arel::Nodes::CurrentRow.new)
|
867
|
+
manager.to_sql.must_be_like %{
|
868
|
+
SELECT FROM "users" WINDOW "a_window" AS (RANGE CURRENT ROW)
|
869
|
+
}
|
870
|
+
end
|
871
|
+
|
872
|
+
it 'takes a range frame, between two delimiters' do
|
873
|
+
table = Table.new :users
|
874
|
+
manager = Arel::SelectManager.new Table.engine
|
875
|
+
manager.from table
|
876
|
+
window = manager.window('a_window')
|
877
|
+
window.frame(
|
878
|
+
Arel::Nodes::Between.new(
|
879
|
+
window.range,
|
880
|
+
Nodes::And.new([
|
881
|
+
Arel::Nodes::Preceding.new,
|
882
|
+
Arel::Nodes::CurrentRow.new
|
883
|
+
])))
|
884
|
+
manager.to_sql.must_be_like %{
|
885
|
+
SELECT FROM "users" WINDOW "a_window" AS (RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
|
886
|
+
}
|
887
|
+
end
|
888
|
+
end
|
889
|
+
|
734
890
|
describe 'delete' do
|
735
891
|
it "copies from" do
|
736
892
|
engine = EngineProxy.new Table.engine
|
@@ -114,6 +114,12 @@ module Arel
|
|
114
114
|
end
|
115
115
|
end
|
116
116
|
|
117
|
+
def test_Arel_Nodes_InfixOperation
|
118
|
+
binary = Arel::Nodes::InfixOperation.new(:o, :a, :b)
|
119
|
+
@visitor.accept binary
|
120
|
+
assert_equal [:a, :b, binary], @collector.calls
|
121
|
+
end
|
122
|
+
|
117
123
|
# N-ary
|
118
124
|
[
|
119
125
|
Arel::Nodes::And,
|
@@ -179,7 +185,8 @@ module Arel
|
|
179
185
|
core.froms = :b
|
180
186
|
core.wheres << :c
|
181
187
|
core.groups << :d
|
182
|
-
core.
|
188
|
+
core.windows << :e
|
189
|
+
core.having = :f
|
183
190
|
|
184
191
|
@visitor.accept core
|
185
192
|
assert_equal [
|
@@ -188,7 +195,8 @@ module Arel
|
|
188
195
|
core.source,
|
189
196
|
:c, core.wheres,
|
190
197
|
:d, core.groups,
|
191
|
-
:e,
|
198
|
+
:e, core.windows,
|
199
|
+
:f,
|
192
200
|
core], @collector.calls
|
193
201
|
end
|
194
202
|
|
@@ -37,6 +37,16 @@ module Arel
|
|
37
37
|
sql.must_be_like "SELECT SKIP 1 LIMIT 1"
|
38
38
|
end
|
39
39
|
|
40
|
+
it 'uses INNER JOIN to perform joins' do
|
41
|
+
core = Nodes::SelectCore.new
|
42
|
+
table = Table.new(:posts)
|
43
|
+
core.source = Nodes::JoinSource.new(table, [table.create_join(Table.new(:comments))])
|
44
|
+
|
45
|
+
stmt = Nodes::SelectStatement.new([core])
|
46
|
+
sql = @visitor.accept(stmt)
|
47
|
+
sql.must_be_like 'SELECT FROM "posts" INNER JOIN "comments"'
|
48
|
+
end
|
49
|
+
|
40
50
|
end
|
41
51
|
end
|
42
52
|
end
|
@@ -167,11 +167,9 @@ module Arel
|
|
167
167
|
}
|
168
168
|
end
|
169
169
|
|
170
|
-
it "should
|
170
|
+
it "should return 1=0 when empty right which is always false" do
|
171
171
|
node = @attr.in []
|
172
|
-
@visitor.accept(node).
|
173
|
-
"users"."id" IN (NULL)
|
174
|
-
}
|
172
|
+
@visitor.accept(node).must_equal '1=0'
|
175
173
|
end
|
176
174
|
|
177
175
|
it 'can handle two dot ranges' do
|
@@ -255,11 +253,9 @@ module Arel
|
|
255
253
|
}
|
256
254
|
end
|
257
255
|
|
258
|
-
it "should
|
256
|
+
it "should return 1=1 when empty right which is always true" do
|
259
257
|
node = @attr.not_in []
|
260
|
-
@visitor.accept(node).
|
261
|
-
"users"."id" NOT IN (NULL)
|
262
|
-
}
|
258
|
+
@visitor.accept(node).must_equal '1=1'
|
263
259
|
end
|
264
260
|
|
265
261
|
it 'can handle two dot ranges' do
|
metadata
CHANGED
@@ -1,10 +1,15 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: arel
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 1
|
5
5
|
prerelease:
|
6
|
+
segments:
|
7
|
+
- 3
|
8
|
+
- 0
|
9
|
+
- 3
|
10
|
+
version: 3.0.3
|
6
11
|
platform: ruby
|
7
|
-
authors:
|
12
|
+
authors:
|
8
13
|
- Aaron Patterson
|
9
14
|
- Bryan Halmkamp
|
10
15
|
- Emilio Tagua
|
@@ -12,67 +17,79 @@ authors:
|
|
12
17
|
autorequire:
|
13
18
|
bindir: bin
|
14
19
|
cert_chain: []
|
15
|
-
|
16
|
-
|
17
|
-
|
20
|
+
|
21
|
+
date: 2013-11-14 00:00:00 -02:00
|
22
|
+
default_executable:
|
23
|
+
dependencies:
|
24
|
+
- !ruby/object:Gem::Dependency
|
18
25
|
name: minitest
|
19
|
-
|
26
|
+
prerelease: false
|
27
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
20
28
|
none: false
|
21
|
-
requirements:
|
29
|
+
requirements:
|
22
30
|
- - ~>
|
23
|
-
- !ruby/object:Gem::Version
|
24
|
-
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
hash: 21
|
33
|
+
segments:
|
34
|
+
- 4
|
35
|
+
- 7
|
36
|
+
version: "4.7"
|
25
37
|
type: :development
|
26
|
-
|
27
|
-
|
28
|
-
- !ruby/object:Gem::Dependency
|
38
|
+
version_requirements: *id001
|
39
|
+
- !ruby/object:Gem::Dependency
|
29
40
|
name: rdoc
|
30
|
-
|
41
|
+
prerelease: false
|
42
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
31
43
|
none: false
|
32
|
-
requirements:
|
44
|
+
requirements:
|
33
45
|
- - ~>
|
34
|
-
- !ruby/object:Gem::Version
|
35
|
-
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
hash: 27
|
48
|
+
segments:
|
49
|
+
- 4
|
50
|
+
- 0
|
51
|
+
version: "4.0"
|
36
52
|
type: :development
|
37
|
-
|
38
|
-
|
39
|
-
- !ruby/object:Gem::Dependency
|
53
|
+
version_requirements: *id002
|
54
|
+
- !ruby/object:Gem::Dependency
|
40
55
|
name: hoe
|
41
|
-
|
56
|
+
prerelease: false
|
57
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
42
58
|
none: false
|
43
|
-
requirements:
|
59
|
+
requirements:
|
44
60
|
- - ~>
|
45
|
-
- !ruby/object:Gem::Version
|
46
|
-
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
hash: 9
|
63
|
+
segments:
|
64
|
+
- 3
|
65
|
+
- 7
|
66
|
+
version: "3.7"
|
47
67
|
type: :development
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
68
|
+
version_requirements: *id003
|
69
|
+
description: |-
|
70
|
+
Arel is a SQL AST manager for Ruby. It
|
71
|
+
|
53
72
|
1. Simplifies the generation of complex SQL queries
|
54
|
-
|
55
73
|
2. Adapts to various RDBMS systems
|
56
|
-
|
57
|
-
|
74
|
+
|
58
75
|
It is intended to be a framework framework; that is, you can build your own ORM
|
59
|
-
|
60
76
|
with it, focusing on innovative object and collection modeling as opposed to
|
61
|
-
|
62
|
-
|
63
|
-
email:
|
77
|
+
database compatibility and query generation.
|
78
|
+
email:
|
64
79
|
- aaron@tenderlovemaking.com
|
65
80
|
- bryan@brynary.com
|
66
81
|
- miloops@gmail.com
|
67
82
|
- nick@example.org
|
68
83
|
executables: []
|
84
|
+
|
69
85
|
extensions: []
|
70
|
-
|
86
|
+
|
87
|
+
extra_rdoc_files:
|
71
88
|
- History.txt
|
72
89
|
- MIT-LICENSE.txt
|
73
90
|
- Manifest.txt
|
74
91
|
- README.markdown
|
75
|
-
files:
|
92
|
+
files:
|
76
93
|
- .autotest
|
77
94
|
- .gemtest
|
78
95
|
- .travis.yml
|
@@ -104,6 +121,7 @@ files:
|
|
104
121
|
- lib/arel/nodes/delete_statement.rb
|
105
122
|
- lib/arel/nodes/descending.rb
|
106
123
|
- lib/arel/nodes/equality.rb
|
124
|
+
- lib/arel/nodes/extract.rb
|
107
125
|
- lib/arel/nodes/false.rb
|
108
126
|
- lib/arel/nodes/function.rb
|
109
127
|
- lib/arel/nodes/in.rb
|
@@ -115,6 +133,7 @@ files:
|
|
115
133
|
- lib/arel/nodes/node.rb
|
116
134
|
- lib/arel/nodes/ordering.rb
|
117
135
|
- lib/arel/nodes/outer_join.rb
|
136
|
+
- lib/arel/nodes/over.rb
|
118
137
|
- lib/arel/nodes/select_core.rb
|
119
138
|
- lib/arel/nodes/select_statement.rb
|
120
139
|
- lib/arel/nodes/sql_literal.rb
|
@@ -126,6 +145,7 @@ files:
|
|
126
145
|
- lib/arel/nodes/unqualified_column.rb
|
127
146
|
- lib/arel/nodes/update_statement.rb
|
128
147
|
- lib/arel/nodes/values.rb
|
148
|
+
- lib/arel/nodes/window.rb
|
129
149
|
- lib/arel/nodes/with.rb
|
130
150
|
- lib/arel/order_predications.rb
|
131
151
|
- lib/arel/predications.rb
|
@@ -152,6 +172,7 @@ files:
|
|
152
172
|
- lib/arel/visitors/to_sql.rb
|
153
173
|
- lib/arel/visitors/visitor.rb
|
154
174
|
- lib/arel/visitors/where_sql.rb
|
175
|
+
- lib/arel/window_predications.rb
|
155
176
|
- test/attributes/test_attribute.rb
|
156
177
|
- test/helper.rb
|
157
178
|
- test/nodes/test_as.rb
|
@@ -161,12 +182,14 @@ files:
|
|
161
182
|
- test/nodes/test_delete_statement.rb
|
162
183
|
- test/nodes/test_descending.rb
|
163
184
|
- test/nodes/test_equality.rb
|
185
|
+
- test/nodes/test_extract.rb
|
164
186
|
- test/nodes/test_infix_operation.rb
|
165
187
|
- test/nodes/test_insert_statement.rb
|
166
188
|
- test/nodes/test_named_function.rb
|
167
189
|
- test/nodes/test_node.rb
|
168
190
|
- test/nodes/test_not.rb
|
169
191
|
- test/nodes/test_or.rb
|
192
|
+
- test/nodes/test_over.rb
|
170
193
|
- test/nodes/test_select_core.rb
|
171
194
|
- test/nodes/test_select_statement.rb
|
172
195
|
- test/nodes/test_sql_literal.rb
|
@@ -194,33 +217,42 @@ files:
|
|
194
217
|
- test/visitors/test_postgres.rb
|
195
218
|
- test/visitors/test_sqlite.rb
|
196
219
|
- test/visitors/test_to_sql.rb
|
220
|
+
has_rdoc: true
|
197
221
|
homepage: http://github.com/rails/arel
|
198
|
-
licenses:
|
222
|
+
licenses:
|
223
|
+
- MIT
|
199
224
|
post_install_message:
|
200
|
-
rdoc_options:
|
225
|
+
rdoc_options:
|
201
226
|
- --main
|
202
227
|
- README.markdown
|
203
|
-
require_paths:
|
228
|
+
require_paths:
|
204
229
|
- lib
|
205
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
230
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
206
231
|
none: false
|
207
|
-
requirements:
|
208
|
-
- -
|
209
|
-
- !ruby/object:Gem::Version
|
210
|
-
|
211
|
-
|
232
|
+
requirements:
|
233
|
+
- - ">="
|
234
|
+
- !ruby/object:Gem::Version
|
235
|
+
hash: 3
|
236
|
+
segments:
|
237
|
+
- 0
|
238
|
+
version: "0"
|
239
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
212
240
|
none: false
|
213
|
-
requirements:
|
214
|
-
- -
|
215
|
-
- !ruby/object:Gem::Version
|
216
|
-
|
241
|
+
requirements:
|
242
|
+
- - ">="
|
243
|
+
- !ruby/object:Gem::Version
|
244
|
+
hash: 3
|
245
|
+
segments:
|
246
|
+
- 0
|
247
|
+
version: "0"
|
217
248
|
requirements: []
|
249
|
+
|
218
250
|
rubyforge_project: arel
|
219
|
-
rubygems_version: 1.
|
251
|
+
rubygems_version: 1.6.2
|
220
252
|
signing_key:
|
221
253
|
specification_version: 3
|
222
254
|
summary: Arel is a SQL AST manager for Ruby
|
223
|
-
test_files:
|
255
|
+
test_files:
|
224
256
|
- test/attributes/test_attribute.rb
|
225
257
|
- test/nodes/test_as.rb
|
226
258
|
- test/nodes/test_ascending.rb
|
@@ -229,12 +261,14 @@ test_files:
|
|
229
261
|
- test/nodes/test_delete_statement.rb
|
230
262
|
- test/nodes/test_descending.rb
|
231
263
|
- test/nodes/test_equality.rb
|
264
|
+
- test/nodes/test_extract.rb
|
232
265
|
- test/nodes/test_infix_operation.rb
|
233
266
|
- test/nodes/test_insert_statement.rb
|
234
267
|
- test/nodes/test_named_function.rb
|
235
268
|
- test/nodes/test_node.rb
|
236
269
|
- test/nodes/test_not.rb
|
237
270
|
- test/nodes/test_or.rb
|
271
|
+
- test/nodes/test_over.rb
|
238
272
|
- test/nodes/test_select_core.rb
|
239
273
|
- test/nodes/test_select_statement.rb
|
240
274
|
- test/nodes/test_sql_literal.rb
|