arel 6.0.0.beta2 → 6.0.0

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.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/History.txt +1 -1
  3. data/README.markdown +5 -5
  4. data/lib/arel.rb +1 -1
  5. data/lib/arel/collectors/sql_string.rb +7 -1
  6. data/lib/arel/expressions.rb +5 -4
  7. data/lib/arel/nodes.rb +1 -0
  8. data/lib/arel/nodes/bind_param.rb +6 -0
  9. data/lib/arel/nodes/sql_literal.rb +0 -3
  10. data/lib/arel/predications.rb +2 -2
  11. data/lib/arel/visitors/depth_first.rb +6 -0
  12. data/lib/arel/visitors/oracle.rb +4 -0
  13. data/lib/arel/visitors/postgresql.rb +4 -0
  14. data/lib/arel/visitors/reduce.rb +4 -4
  15. data/lib/arel/visitors/to_sql.rb +3 -2
  16. data/lib/arel/visitors/visitor.rb +15 -15
  17. metadata +26 -69
  18. data/.gitignore +0 -9
  19. data/.travis.yml +0 -18
  20. data/Gemfile +0 -5
  21. data/Rakefile +0 -15
  22. data/arel.gemspec +0 -24
  23. data/test/attributes/test_attribute.rb +0 -910
  24. data/test/collectors/test_bind_collector.rb +0 -70
  25. data/test/collectors/test_sql_string.rb +0 -38
  26. data/test/helper.rb +0 -22
  27. data/test/nodes/test_and.rb +0 -20
  28. data/test/nodes/test_as.rb +0 -34
  29. data/test/nodes/test_ascending.rb +0 -44
  30. data/test/nodes/test_bin.rb +0 -33
  31. data/test/nodes/test_binary.rb +0 -26
  32. data/test/nodes/test_count.rb +0 -33
  33. data/test/nodes/test_delete_statement.rb +0 -34
  34. data/test/nodes/test_descending.rb +0 -44
  35. data/test/nodes/test_distinct.rb +0 -20
  36. data/test/nodes/test_equality.rb +0 -84
  37. data/test/nodes/test_extract.rb +0 -41
  38. data/test/nodes/test_false.rb +0 -20
  39. data/test/nodes/test_grouping.rb +0 -25
  40. data/test/nodes/test_infix_operation.rb +0 -40
  41. data/test/nodes/test_insert_statement.rb +0 -42
  42. data/test/nodes/test_named_function.rb +0 -46
  43. data/test/nodes/test_node.rb +0 -39
  44. data/test/nodes/test_not.rb +0 -29
  45. data/test/nodes/test_or.rb +0 -34
  46. data/test/nodes/test_over.rb +0 -67
  47. data/test/nodes/test_select_core.rb +0 -69
  48. data/test/nodes/test_select_statement.rb +0 -49
  49. data/test/nodes/test_sql_literal.rb +0 -73
  50. data/test/nodes/test_sum.rb +0 -24
  51. data/test/nodes/test_table_alias.rb +0 -36
  52. data/test/nodes/test_true.rb +0 -21
  53. data/test/nodes/test_update_statement.rb +0 -58
  54. data/test/nodes/test_window.rb +0 -79
  55. data/test/support/fake_record.rb +0 -135
  56. data/test/test_attributes.rb +0 -66
  57. data/test/test_crud.rb +0 -63
  58. data/test/test_delete_manager.rb +0 -42
  59. data/test/test_factory_methods.rb +0 -44
  60. data/test/test_insert_manager.rb +0 -171
  61. data/test/test_select_manager.rb +0 -1181
  62. data/test/test_table.rb +0 -253
  63. data/test/test_update_manager.rb +0 -124
  64. data/test/visitors/test_bind_visitor.rb +0 -60
  65. data/test/visitors/test_depth_first.rb +0 -258
  66. data/test/visitors/test_dispatch_contamination.rb +0 -22
  67. data/test/visitors/test_dot.rb +0 -76
  68. data/test/visitors/test_ibm_db.rb +0 -33
  69. data/test/visitors/test_informix.rb +0 -58
  70. data/test/visitors/test_mssql.rb +0 -70
  71. data/test/visitors/test_mysql.rb +0 -60
  72. data/test/visitors/test_oracle.rb +0 -170
  73. data/test/visitors/test_postgres.rb +0 -122
  74. data/test/visitors/test_sqlite.rb +0 -23
  75. data/test/visitors/test_to_sql.rb +0 -598
@@ -1,66 +0,0 @@
1
- require 'helper'
2
-
3
- module Arel
4
- describe 'Attributes' do
5
- it 'responds to lower' do
6
- relation = Table.new(:users)
7
- attribute = relation[:foo]
8
- node = attribute.lower
9
- assert_equal 'LOWER', node.name
10
- assert_equal [attribute], node.expressions
11
- end
12
-
13
- describe 'equality' do
14
- it 'is equal with equal ivars' do
15
- array = [Attribute.new('foo', 'bar'), Attribute.new('foo', 'bar')]
16
- assert_equal 1, array.uniq.size
17
- end
18
-
19
- it 'is not equal with different ivars' do
20
- array = [Attribute.new('foo', 'bar'), Attribute.new('foo', 'baz')]
21
- assert_equal 2, array.uniq.size
22
- end
23
- end
24
-
25
- describe 'for' do
26
- it 'deals with unknown column types' do
27
- column = Struct.new(:type).new :crazy
28
- Attributes.for(column).must_equal Attributes::Undefined
29
- end
30
-
31
- it 'returns the correct constant for strings' do
32
- [:string, :text, :binary].each do |type|
33
- column = Struct.new(:type).new type
34
- Attributes.for(column).must_equal Attributes::String
35
- end
36
- end
37
-
38
- it 'returns the correct constant for ints' do
39
- column = Struct.new(:type).new :integer
40
- Attributes.for(column).must_equal Attributes::Integer
41
- end
42
-
43
- it 'returns the correct constant for floats' do
44
- column = Struct.new(:type).new :float
45
- Attributes.for(column).must_equal Attributes::Float
46
- end
47
-
48
- it 'returns the correct constant for decimals' do
49
- column = Struct.new(:type).new :decimal
50
- Attributes.for(column).must_equal Attributes::Decimal
51
- end
52
-
53
- it 'returns the correct constant for boolean' do
54
- column = Struct.new(:type).new :boolean
55
- Attributes.for(column).must_equal Attributes::Boolean
56
- end
57
-
58
- it 'returns the correct constant for time' do
59
- [:date, :datetime, :timestamp, :time].each do |type|
60
- column = Struct.new(:type).new type
61
- Attributes.for(column).must_equal Attributes::Time
62
- end
63
- end
64
- end
65
- end
66
- end
@@ -1,63 +0,0 @@
1
- require 'helper'
2
-
3
- module Arel
4
- class FakeCrudder < SelectManager
5
- class FakeEngine
6
- attr_reader :calls, :connection_pool, :spec, :config
7
-
8
- def initialize
9
- @calls = []
10
- @connection_pool = self
11
- @spec = self
12
- @config = { :adapter => 'sqlite3' }
13
- end
14
-
15
- def connection; self end
16
-
17
- def method_missing name, *args
18
- @calls << [name, args]
19
- end
20
- end
21
-
22
- include Crud
23
-
24
- attr_reader :engine
25
- attr_accessor :ctx
26
-
27
- def initialize engine = FakeEngine.new
28
- super
29
- end
30
- end
31
-
32
- describe 'crud' do
33
- describe 'insert' do
34
- it 'should call insert on the connection' do
35
- table = Table.new :users
36
- fc = FakeCrudder.new
37
- fc.from table
38
- im = fc.compile_insert [[table[:id], 'foo']]
39
- assert_instance_of Arel::InsertManager, im
40
- end
41
- end
42
-
43
- describe 'update' do
44
- it 'should call update on the connection' do
45
- table = Table.new :users
46
- fc = FakeCrudder.new
47
- fc.from table
48
- stmt = fc.compile_update [[table[:id], 'foo']], Arel::Attributes::Attribute.new(table, 'id')
49
- assert_instance_of Arel::UpdateManager, stmt
50
- end
51
- end
52
-
53
- describe 'delete' do
54
- it 'should call delete on the connection' do
55
- table = Table.new :users
56
- fc = FakeCrudder.new
57
- fc.from table
58
- stmt = fc.compile_delete
59
- assert_instance_of Arel::DeleteManager, stmt
60
- end
61
- end
62
- end
63
- end
@@ -1,42 +0,0 @@
1
- require 'helper'
2
-
3
- module Arel
4
- describe 'delete manager' do
5
- describe 'new' do
6
- it 'takes an engine' do
7
- Arel::DeleteManager.new Table.engine
8
- end
9
- end
10
-
11
- describe 'from' do
12
- it 'uses from' do
13
- table = Table.new(:users)
14
- dm = Arel::DeleteManager.new Table.engine
15
- dm.from table
16
- dm.to_sql.must_be_like %{ DELETE FROM "users" }
17
- end
18
-
19
- it 'chains' do
20
- table = Table.new(:users)
21
- dm = Arel::DeleteManager.new Table.engine
22
- dm.from(table).must_equal dm
23
- end
24
- end
25
-
26
- describe 'where' do
27
- it 'uses where values' do
28
- table = Table.new(:users)
29
- dm = Arel::DeleteManager.new Table.engine
30
- dm.from table
31
- dm.where table[:id].eq(10)
32
- dm.to_sql.must_be_like %{ DELETE FROM "users" WHERE "users"."id" = 10}
33
- end
34
-
35
- it 'chains' do
36
- table = Table.new(:users)
37
- dm = Arel::DeleteManager.new Table.engine
38
- dm.where(table[:id].eq(10)).must_equal dm
39
- end
40
- end
41
- end
42
- end
@@ -1,44 +0,0 @@
1
- require 'helper'
2
-
3
- module Arel
4
- module FactoryMethods
5
- class TestFactoryMethods < Minitest::Test
6
- class Factory
7
- include Arel::FactoryMethods
8
- end
9
-
10
- def setup
11
- @factory = Factory.new
12
- end
13
-
14
- def test_create_join
15
- join = @factory.create_join :one, :two
16
- assert_kind_of Nodes::Join, join
17
- assert_equal :two, join.right
18
- end
19
-
20
- def test_create_on
21
- on = @factory.create_on :one
22
- assert_instance_of Nodes::On, on
23
- assert_equal :one, on.expr
24
- end
25
-
26
- def test_create_true
27
- true_node = @factory.create_true
28
- assert_instance_of Nodes::True, true_node
29
- end
30
-
31
- def test_create_false
32
- false_node = @factory.create_false
33
- assert_instance_of Nodes::False, false_node
34
- end
35
-
36
- def test_lower
37
- lower = @factory.lower :one
38
- assert_instance_of Nodes::NamedFunction, lower
39
- assert_equal 'LOWER', lower.name
40
- assert_equal [:one], lower.expressions.map(&:expr)
41
- end
42
- end
43
- end
44
- end
@@ -1,171 +0,0 @@
1
- require 'helper'
2
-
3
- module Arel
4
- describe 'insert manager' do
5
- describe 'new' do
6
- it 'takes an engine' do
7
- Arel::InsertManager.new Table.engine
8
- end
9
- end
10
-
11
- describe 'insert' do
12
- it 'can create a Values node' do
13
- manager = Arel::InsertManager.new Table.engine
14
- values = manager.create_values %w{ a b }, %w{ c d }
15
-
16
- assert_kind_of Arel::Nodes::Values, values
17
- assert_equal %w{ a b }, values.left
18
- assert_equal %w{ c d }, values.right
19
- end
20
-
21
- it 'allows sql literals' do
22
- manager = Arel::InsertManager.new Table.engine
23
- manager.into Table.new(:users)
24
- manager.values = manager.create_values [Arel.sql('*')], %w{ a }
25
- manager.to_sql.must_be_like %{
26
- INSERT INTO \"users\" VALUES (*)
27
- }
28
- end
29
-
30
- it "inserts false" do
31
- table = Table.new(:users)
32
- manager = Arel::InsertManager.new Table.engine
33
-
34
- manager.insert [[table[:bool], false]]
35
- manager.to_sql.must_be_like %{
36
- INSERT INTO "users" ("bool") VALUES ('f')
37
- }
38
- end
39
-
40
- it "inserts null" do
41
- table = Table.new(:users)
42
- manager = Arel::InsertManager.new Table.engine
43
- manager.insert [[table[:id], nil]]
44
- manager.to_sql.must_be_like %{
45
- INSERT INTO "users" ("id") VALUES (NULL)
46
- }
47
- end
48
-
49
- it "inserts time" do
50
- table = Table.new(:users)
51
- manager = Arel::InsertManager.new Table.engine
52
-
53
- time = Time.now
54
- attribute = table[:created_at]
55
-
56
- manager.insert [[attribute, time]]
57
- manager.to_sql.must_be_like %{
58
- INSERT INTO "users" ("created_at") VALUES (#{Table.engine.connection.quote time})
59
- }
60
- end
61
-
62
- it 'takes a list of lists' do
63
- table = Table.new(:users)
64
- manager = Arel::InsertManager.new Table.engine
65
- manager.into table
66
- manager.insert [[table[:id], 1], [table[:name], 'aaron']]
67
- manager.to_sql.must_be_like %{
68
- INSERT INTO "users" ("id", "name") VALUES (1, 'aaron')
69
- }
70
- end
71
-
72
- it 'defaults the table' do
73
- table = Table.new(:users)
74
- manager = Arel::InsertManager.new Table.engine
75
- manager.insert [[table[:id], 1], [table[:name], 'aaron']]
76
- manager.to_sql.must_be_like %{
77
- INSERT INTO "users" ("id", "name") VALUES (1, 'aaron')
78
- }
79
- end
80
-
81
- it 'noop for empty list' do
82
- table = Table.new(:users)
83
- manager = Arel::InsertManager.new Table.engine
84
- manager.insert [[table[:id], 1]]
85
- manager.insert []
86
- manager.to_sql.must_be_like %{
87
- INSERT INTO "users" ("id") VALUES (1)
88
- }
89
- end
90
- end
91
-
92
- describe 'into' do
93
- it 'takes a Table and chains' do
94
- manager = Arel::InsertManager.new Table.engine
95
- manager.into(Table.new(:users)).must_equal manager
96
- end
97
-
98
- it 'converts to sql' do
99
- table = Table.new :users
100
- manager = Arel::InsertManager.new Table.engine
101
- manager.into table
102
- manager.to_sql.must_be_like %{
103
- INSERT INTO "users"
104
- }
105
- end
106
- end
107
-
108
- describe 'columns' do
109
- it "converts to sql" do
110
- table = Table.new :users
111
- manager = Arel::InsertManager.new Table.engine
112
- manager.into table
113
- manager.columns << table[:id]
114
- manager.to_sql.must_be_like %{
115
- INSERT INTO "users" ("id")
116
- }
117
- end
118
- end
119
-
120
- describe "values" do
121
- it "converts to sql" do
122
- table = Table.new :users
123
- manager = Arel::InsertManager.new Table.engine
124
- manager.into table
125
-
126
- manager.values = Nodes::Values.new [1]
127
- manager.to_sql.must_be_like %{
128
- INSERT INTO "users" VALUES (1)
129
- }
130
- end
131
- end
132
-
133
- describe "combo" do
134
- it "combines columns and values list in order" do
135
- table = Table.new :users
136
- manager = Arel::InsertManager.new Table.engine
137
- manager.into table
138
-
139
- manager.values = Nodes::Values.new [1, 'aaron']
140
- manager.columns << table[:id]
141
- manager.columns << table[:name]
142
- manager.to_sql.must_be_like %{
143
- INSERT INTO "users" ("id", "name") VALUES (1, 'aaron')
144
- }
145
- end
146
- end
147
-
148
- describe "select" do
149
-
150
- it "accepts a select query in place of a VALUES clause" do
151
- table = Table.new :users
152
-
153
- manager = Arel::InsertManager.new Table.engine
154
- manager.into table
155
-
156
- select = Arel::SelectManager.new Table.engine
157
- select.project Arel.sql('1')
158
- select.project Arel.sql('"aaron"')
159
-
160
- manager.select select
161
- manager.columns << table[:id]
162
- manager.columns << table[:name]
163
- manager.to_sql.must_be_like %{
164
- INSERT INTO "users" ("id", "name") (SELECT 1, "aaron")
165
- }
166
- end
167
-
168
- end
169
-
170
- end
171
- end
@@ -1,1181 +0,0 @@
1
- require 'helper'
2
-
3
- module Arel
4
-
5
- describe 'select manager' do
6
- def test_join_sources
7
- manager = Arel::SelectManager.new Table.engine
8
- manager.join_sources << Arel::Nodes::StringJoin.new(Nodes.build_quoted('foo'))
9
- assert_equal "SELECT FROM 'foo'", manager.to_sql
10
- end
11
-
12
- def test_manager_stores_bind_values
13
- manager = Arel::SelectManager.new Table.engine
14
- assert_equal [], manager.bind_values
15
- manager.bind_values = [1]
16
- assert_equal [1], manager.bind_values
17
- end
18
-
19
- describe 'backwards compatibility' do
20
- describe 'project' do
21
- it 'accepts symbols as sql literals' do
22
- table = Table.new :users
23
- manager = Arel::SelectManager.new Table.engine
24
- manager.project :id
25
- manager.from table
26
- manager.to_sql.must_be_like %{
27
- SELECT id FROM "users"
28
- }
29
- end
30
- end
31
-
32
- describe 'order' do
33
- it 'accepts symbols' do
34
- table = Table.new :users
35
- manager = Arel::SelectManager.new Table.engine
36
- manager.project Nodes::SqlLiteral.new '*'
37
- manager.from table
38
- manager.order :foo
39
- manager.to_sql.must_be_like %{ SELECT * FROM "users" ORDER BY foo }
40
- end
41
- end
42
-
43
- describe 'group' do
44
- it 'takes a symbol' do
45
- table = Table.new :users
46
- manager = Arel::SelectManager.new Table.engine
47
- manager.from table
48
- manager.group :foo
49
- manager.to_sql.must_be_like %{ SELECT FROM "users" GROUP BY foo }
50
- end
51
- end
52
-
53
- describe 'as' do
54
- it 'makes an AS node by grouping the AST' do
55
- manager = Arel::SelectManager.new Table.engine
56
- as = manager.as(Arel.sql('foo'))
57
- assert_kind_of Arel::Nodes::Grouping, as.left
58
- assert_equal manager.ast, as.left.expr
59
- assert_equal 'foo', as.right
60
- end
61
-
62
- it 'converts right to SqlLiteral if a string' do
63
- manager = Arel::SelectManager.new Table.engine
64
- as = manager.as('foo')
65
- assert_kind_of Arel::Nodes::SqlLiteral, as.right
66
- end
67
-
68
- it 'can make a subselect' do
69
- manager = Arel::SelectManager.new Table.engine
70
- manager.project Arel.star
71
- manager.from Arel.sql('zomg')
72
- as = manager.as(Arel.sql('foo'))
73
-
74
- manager = Arel::SelectManager.new Table.engine
75
- manager.project Arel.sql('name')
76
- manager.from as
77
- manager.to_sql.must_be_like "SELECT name FROM (SELECT * FROM zomg) foo"
78
- end
79
- end
80
-
81
- describe 'from' do
82
- it 'ignores strings when table of same name exists' do
83
- table = Table.new :users
84
- manager = Arel::SelectManager.new Table.engine
85
-
86
- manager.from table
87
- manager.from 'users'
88
- manager.project table['id']
89
- manager.to_sql.must_be_like 'SELECT "users"."id" FROM users'
90
- end
91
-
92
- it 'should support any ast' do
93
- table = Table.new :users
94
- manager1 = Arel::SelectManager.new Table.engine
95
-
96
- manager2 = Arel::SelectManager.new Table.engine
97
- manager2.project(Arel.sql('*'))
98
- manager2.from table
99
-
100
- manager1.project Arel.sql('lol')
101
- as = manager2.as Arel.sql('omg')
102
- manager1.from(as)
103
-
104
- manager1.to_sql.must_be_like %{
105
- SELECT lol FROM (SELECT * FROM "users") omg
106
- }
107
- end
108
- end
109
-
110
- describe 'having' do
111
- it 'converts strings to SQLLiterals' do
112
- table = Table.new :users
113
- mgr = table.from table
114
- mgr.having 'foo'
115
- mgr.to_sql.must_be_like %{ SELECT FROM "users" HAVING foo }
116
- end
117
-
118
- it 'can have multiple items specified separately' do
119
- table = Table.new :users
120
- mgr = table.from table
121
- mgr.having 'foo'
122
- mgr.having 'bar'
123
- mgr.to_sql.must_be_like %{ SELECT FROM "users" HAVING foo AND bar }
124
- end
125
-
126
- it 'can have multiple items specified together' do
127
- table = Table.new :users
128
- mgr = table.from table
129
- mgr.having 'foo', 'bar'
130
- mgr.to_sql.must_be_like %{ SELECT FROM "users" HAVING foo AND bar }
131
- end
132
- end
133
-
134
- describe 'on' do
135
- it 'converts to sqlliterals' do
136
- table = Table.new :users
137
- right = table.alias
138
- mgr = table.from table
139
- mgr.join(right).on("omg")
140
- mgr.to_sql.must_be_like %{ SELECT FROM "users" INNER JOIN "users" "users_2" ON omg }
141
- end
142
-
143
- it 'converts to sqlliterals with multiple items' do
144
- table = Table.new :users
145
- right = table.alias
146
- mgr = table.from table
147
- mgr.join(right).on("omg", "123")
148
- mgr.to_sql.must_be_like %{ SELECT FROM "users" INNER JOIN "users" "users_2" ON omg AND 123 }
149
- end
150
- end
151
- end
152
-
153
- describe 'clone' do
154
- it 'creates new cores' do
155
- table = Table.new :users, :as => 'foo'
156
- mgr = table.from table
157
- m2 = mgr.clone
158
- m2.project "foo"
159
- mgr.to_sql.wont_equal m2.to_sql
160
- end
161
-
162
- it 'makes updates to the correct copy' do
163
- table = Table.new :users, :as => 'foo'
164
- mgr = table.from table
165
- m2 = mgr.clone
166
- m3 = m2.clone
167
- m2.project "foo"
168
- mgr.to_sql.wont_equal m2.to_sql
169
- m3.to_sql.must_equal mgr.to_sql
170
- end
171
- end
172
-
173
- describe 'initialize' do
174
- it 'uses alias in sql' do
175
- table = Table.new :users, :as => 'foo'
176
- mgr = table.from table
177
- mgr.skip 10
178
- mgr.to_sql.must_be_like %{ SELECT FROM "users" "foo" OFFSET 10 }
179
- end
180
- end
181
-
182
- describe 'skip' do
183
- it 'should add an offset' do
184
- table = Table.new :users
185
- mgr = table.from table
186
- mgr.skip 10
187
- mgr.to_sql.must_be_like %{ SELECT FROM "users" OFFSET 10 }
188
- end
189
-
190
- it 'should chain' do
191
- table = Table.new :users
192
- mgr = table.from table
193
- mgr.skip(10).to_sql.must_be_like %{ SELECT FROM "users" OFFSET 10 }
194
- end
195
- end
196
-
197
- describe 'offset' do
198
- it 'should add an offset' do
199
- table = Table.new :users
200
- mgr = table.from table
201
- mgr.offset = 10
202
- mgr.to_sql.must_be_like %{ SELECT FROM "users" OFFSET 10 }
203
- end
204
-
205
- it 'should remove an offset' do
206
- table = Table.new :users
207
- mgr = table.from table
208
- mgr.offset = 10
209
- mgr.to_sql.must_be_like %{ SELECT FROM "users" OFFSET 10 }
210
-
211
- mgr.offset = nil
212
- mgr.to_sql.must_be_like %{ SELECT FROM "users" }
213
- end
214
-
215
- it 'should return the offset' do
216
- table = Table.new :users
217
- mgr = table.from table
218
- mgr.offset = 10
219
- assert_equal 10, mgr.offset
220
- end
221
- end
222
-
223
- describe 'exists' do
224
- it 'should create an exists clause' do
225
- table = Table.new(:users)
226
- manager = Arel::SelectManager.new Table.engine, table
227
- manager.project Nodes::SqlLiteral.new '*'
228
- m2 = Arel::SelectManager.new(manager.engine)
229
- m2.project manager.exists
230
- m2.to_sql.must_be_like %{ SELECT EXISTS (#{manager.to_sql}) }
231
- end
232
-
233
- it 'can be aliased' do
234
- table = Table.new(:users)
235
- manager = Arel::SelectManager.new Table.engine, table
236
- manager.project Nodes::SqlLiteral.new '*'
237
- m2 = Arel::SelectManager.new(manager.engine)
238
- m2.project manager.exists.as('foo')
239
- m2.to_sql.must_be_like %{ SELECT EXISTS (#{manager.to_sql}) AS foo }
240
- end
241
- end
242
-
243
- describe 'union' do
244
- before do
245
- table = Table.new :users
246
- @m1 = Arel::SelectManager.new Table.engine, table
247
- @m1.project Arel.star
248
- @m1.where(table[:age].lt(18))
249
-
250
- @m2 = Arel::SelectManager.new Table.engine, table
251
- @m2.project Arel.star
252
- @m2.where(table[:age].gt(99))
253
-
254
-
255
- end
256
-
257
- it 'should union two managers' do
258
- # FIXME should this union "managers" or "statements" ?
259
- # FIXME this probably shouldn't return a node
260
- node = @m1.union @m2
261
-
262
- # maybe FIXME: decide when wrapper parens are needed
263
- node.to_sql.must_be_like %{
264
- ( SELECT * FROM "users" WHERE "users"."age" < 18 UNION SELECT * FROM "users" WHERE "users"."age" > 99 )
265
- }
266
- end
267
-
268
- it 'should union all' do
269
- node = @m1.union :all, @m2
270
-
271
- node.to_sql.must_be_like %{
272
- ( SELECT * FROM "users" WHERE "users"."age" < 18 UNION ALL SELECT * FROM "users" WHERE "users"."age" > 99 )
273
- }
274
- end
275
-
276
- end
277
-
278
- describe 'intersect' do
279
- before do
280
- table = Table.new :users
281
- @m1 = Arel::SelectManager.new Table.engine, table
282
- @m1.project Arel.star
283
- @m1.where(table[:age].gt(18))
284
-
285
- @m2 = Arel::SelectManager.new Table.engine, table
286
- @m2.project Arel.star
287
- @m2.where(table[:age].lt(99))
288
-
289
-
290
- end
291
-
292
- it 'should interect two managers' do
293
- # FIXME should this intersect "managers" or "statements" ?
294
- # FIXME this probably shouldn't return a node
295
- node = @m1.intersect @m2
296
-
297
- # maybe FIXME: decide when wrapper parens are needed
298
- node.to_sql.must_be_like %{
299
- ( SELECT * FROM "users" WHERE "users"."age" > 18 INTERSECT SELECT * FROM "users" WHERE "users"."age" < 99 )
300
- }
301
- end
302
-
303
- end
304
-
305
- describe 'except' do
306
- before do
307
- table = Table.new :users
308
- @m1 = Arel::SelectManager.new Table.engine, table
309
- @m1.project Arel.star
310
- @m1.where(table[:age].between(18..60))
311
-
312
- @m2 = Arel::SelectManager.new Table.engine, table
313
- @m2.project Arel.star
314
- @m2.where(table[:age].between(40..99))
315
- end
316
-
317
- it 'should except two managers' do
318
- # FIXME should this except "managers" or "statements" ?
319
- # FIXME this probably shouldn't return a node
320
- node = @m1.except @m2
321
-
322
- # maybe FIXME: decide when wrapper parens are needed
323
- node.to_sql.must_be_like %{
324
- ( SELECT * FROM "users" WHERE "users"."age" BETWEEN 18 AND 60 EXCEPT SELECT * FROM "users" WHERE "users"."age" BETWEEN 40 AND 99 )
325
- }
326
- end
327
-
328
- end
329
-
330
- describe 'with' do
331
- it 'should support basic WITH' do
332
- users = Table.new(:users)
333
- users_top = Table.new(:users_top)
334
- comments = Table.new(:comments)
335
-
336
- top = users.project(users[:id]).where(users[:karma].gt(100))
337
- users_as = Arel::Nodes::As.new(users_top, top)
338
- select_manager = comments.project(Arel.star).with(users_as)
339
- .where(comments[:author_id].in(users_top.project(users_top[:id])))
340
-
341
- select_manager.to_sql.must_be_like %{
342
- WITH "users_top" AS (SELECT "users"."id" FROM "users" WHERE "users"."karma" > 100) SELECT * FROM "comments" WHERE "comments"."author_id" IN (SELECT "users_top"."id" FROM "users_top")
343
- }
344
- end
345
-
346
- it "should support WITH RECURSIVE" do
347
- comments = Table.new(:comments)
348
- comments_id = comments[:id]
349
- comments_parent_id = comments[:parent_id]
350
-
351
- replies = Table.new(:replies)
352
- replies_id = replies[:id]
353
-
354
- recursive_term = Arel::SelectManager.new Table.engine
355
- recursive_term.from(comments).project(comments_id, comments_parent_id).where(comments_id.eq 42)
356
-
357
- non_recursive_term = Arel::SelectManager.new Table.engine
358
- non_recursive_term.from(comments).project(comments_id, comments_parent_id).join(replies).on(comments_parent_id.eq replies_id)
359
-
360
- union = recursive_term.union(non_recursive_term)
361
-
362
- as_statement = Arel::Nodes::As.new replies, union
363
-
364
- manager = Arel::SelectManager.new Table.engine
365
- manager.with(:recursive, as_statement).from(replies).project(Arel.star)
366
-
367
- sql = manager.to_sql
368
- sql.must_be_like %{
369
- WITH RECURSIVE "replies" AS (
370
- SELECT "comments"."id", "comments"."parent_id" FROM "comments" WHERE "comments"."id" = 42
371
- UNION
372
- SELECT "comments"."id", "comments"."parent_id" FROM "comments" INNER JOIN "replies" ON "comments"."parent_id" = "replies"."id"
373
- )
374
- SELECT * FROM "replies"
375
- }
376
- end
377
- end
378
-
379
- describe 'ast' do
380
- it 'should return the ast' do
381
- table = Table.new :users
382
- mgr = table.from table
383
- assert mgr.ast
384
- end
385
-
386
- it 'should allow orders to work when the ast is grepped' do
387
- table = Table.new :users
388
- mgr = table.from table
389
- mgr.project Arel.sql '*'
390
- mgr.from table
391
- mgr.orders << Arel::Nodes::Ascending.new(Arel.sql('foo'))
392
- mgr.ast.grep(Arel::Nodes::OuterJoin)
393
- mgr.to_sql.must_be_like %{ SELECT * FROM "users" ORDER BY foo ASC }
394
- end
395
- end
396
-
397
- describe 'taken' do
398
- it 'should return limit' do
399
- manager = Arel::SelectManager.new Table.engine
400
- manager.take 10
401
- manager.taken.must_equal 10
402
- end
403
- end
404
-
405
- describe 'lock' do
406
- # This should fail on other databases
407
- it 'adds a lock node' do
408
- table = Table.new :users
409
- mgr = table.from table
410
- mgr.lock.to_sql.must_be_like %{ SELECT FROM "users" FOR UPDATE }
411
- end
412
- end
413
-
414
- describe 'orders' do
415
- it 'returns order clauses' do
416
- table = Table.new :users
417
- manager = Arel::SelectManager.new Table.engine
418
- order = table[:id]
419
- manager.order table[:id]
420
- manager.orders.must_equal [order]
421
- end
422
- end
423
-
424
- describe 'order' do
425
- it 'generates order clauses' do
426
- table = Table.new :users
427
- manager = Arel::SelectManager.new Table.engine
428
- manager.project Nodes::SqlLiteral.new '*'
429
- manager.from table
430
- manager.order table[:id]
431
- manager.to_sql.must_be_like %{
432
- SELECT * FROM "users" ORDER BY "users"."id"
433
- }
434
- end
435
-
436
- # FIXME: I would like to deprecate this
437
- it 'takes *args' do
438
- table = Table.new :users
439
- manager = Arel::SelectManager.new Table.engine
440
- manager.project Nodes::SqlLiteral.new '*'
441
- manager.from table
442
- manager.order table[:id], table[:name]
443
- manager.to_sql.must_be_like %{
444
- SELECT * FROM "users" ORDER BY "users"."id", "users"."name"
445
- }
446
- end
447
-
448
- it 'chains' do
449
- table = Table.new :users
450
- manager = Arel::SelectManager.new Table.engine
451
- manager.order(table[:id]).must_equal manager
452
- end
453
-
454
- it 'has order attributes' do
455
- table = Table.new :users
456
- manager = Arel::SelectManager.new Table.engine
457
- manager.project Nodes::SqlLiteral.new '*'
458
- manager.from table
459
- manager.order table[:id].desc
460
- manager.to_sql.must_be_like %{
461
- SELECT * FROM "users" ORDER BY "users"."id" DESC
462
- }
463
- end
464
- end
465
-
466
- describe 'on' do
467
- it 'takes two params' do
468
- left = Table.new :users
469
- right = left.alias
470
- predicate = left[:id].eq(right[:id])
471
- manager = Arel::SelectManager.new Table.engine
472
-
473
- manager.from left
474
- manager.join(right).on(predicate, predicate)
475
- manager.to_sql.must_be_like %{
476
- SELECT FROM "users"
477
- INNER JOIN "users" "users_2"
478
- ON "users"."id" = "users_2"."id" AND
479
- "users"."id" = "users_2"."id"
480
- }
481
- end
482
-
483
- it 'takes three params' do
484
- left = Table.new :users
485
- right = left.alias
486
- predicate = left[:id].eq(right[:id])
487
- manager = Arel::SelectManager.new Table.engine
488
-
489
- manager.from left
490
- manager.join(right).on(
491
- predicate,
492
- predicate,
493
- left[:name].eq(right[:name])
494
- )
495
- manager.to_sql.must_be_like %{
496
- SELECT FROM "users"
497
- INNER JOIN "users" "users_2"
498
- ON "users"."id" = "users_2"."id" AND
499
- "users"."id" = "users_2"."id" AND
500
- "users"."name" = "users_2"."name"
501
- }
502
- end
503
- end
504
-
505
- it 'should hand back froms' do
506
- relation = Arel::SelectManager.new Table.engine
507
- assert_equal [], relation.froms
508
- end
509
-
510
- it 'should create and nodes' do
511
- relation = Arel::SelectManager.new Table.engine
512
- children = ['foo', 'bar', 'baz']
513
- clause = relation.create_and children
514
- assert_kind_of Arel::Nodes::And, clause
515
- assert_equal children, clause.children
516
- end
517
-
518
- it 'should create insert managers' do
519
- relation = Arel::SelectManager.new Table.engine
520
- insert = relation.create_insert
521
- assert_kind_of Arel::InsertManager, insert
522
- end
523
-
524
- it 'should create join nodes' do
525
- relation = Arel::SelectManager.new Table.engine
526
- join = relation.create_join 'foo', 'bar'
527
- assert_kind_of Arel::Nodes::InnerJoin, join
528
- assert_equal 'foo', join.left
529
- assert_equal 'bar', join.right
530
- end
531
-
532
- it 'should create join nodes with a full outer join klass' do
533
- relation = Arel::SelectManager.new Table.engine
534
- join = relation.create_join 'foo', 'bar', Arel::Nodes::FullOuterJoin
535
- assert_kind_of Arel::Nodes::FullOuterJoin, join
536
- assert_equal 'foo', join.left
537
- assert_equal 'bar', join.right
538
- end
539
-
540
- it 'should create join nodes with a outer join klass' do
541
- relation = Arel::SelectManager.new Table.engine
542
- join = relation.create_join 'foo', 'bar', Arel::Nodes::OuterJoin
543
- assert_kind_of Arel::Nodes::OuterJoin, join
544
- assert_equal 'foo', join.left
545
- assert_equal 'bar', join.right
546
- end
547
-
548
- it 'should create join nodes with a right outer join klass' do
549
- relation = Arel::SelectManager.new Table.engine
550
- join = relation.create_join 'foo', 'bar', Arel::Nodes::RightOuterJoin
551
- assert_kind_of Arel::Nodes::RightOuterJoin, join
552
- assert_equal 'foo', join.left
553
- assert_equal 'bar', join.right
554
- end
555
-
556
- describe 'join' do
557
- it 'responds to join' do
558
- left = Table.new :users
559
- right = left.alias
560
- predicate = left[:id].eq(right[:id])
561
- manager = Arel::SelectManager.new Table.engine
562
-
563
- manager.from left
564
- manager.join(right).on(predicate)
565
- manager.to_sql.must_be_like %{
566
- SELECT FROM "users"
567
- INNER JOIN "users" "users_2"
568
- ON "users"."id" = "users_2"."id"
569
- }
570
- end
571
-
572
- it 'takes a class' do
573
- left = Table.new :users
574
- right = left.alias
575
- predicate = left[:id].eq(right[:id])
576
- manager = Arel::SelectManager.new Table.engine
577
-
578
- manager.from left
579
- manager.join(right, Nodes::OuterJoin).on(predicate)
580
- manager.to_sql.must_be_like %{
581
- SELECT FROM "users"
582
- LEFT OUTER JOIN "users" "users_2"
583
- ON "users"."id" = "users_2"."id"
584
- }
585
- end
586
-
587
- it 'noops on nil' do
588
- manager = Arel::SelectManager.new Table.engine
589
- manager.join(nil).must_equal manager
590
- end
591
- end
592
-
593
- describe 'outer join' do
594
- it 'responds to join' do
595
- left = Table.new :users
596
- right = left.alias
597
- predicate = left[:id].eq(right[:id])
598
- manager = Arel::SelectManager.new Table.engine
599
-
600
- manager.from left
601
- manager.outer_join(right).on(predicate)
602
- manager.to_sql.must_be_like %{
603
- SELECT FROM "users"
604
- LEFT OUTER JOIN "users" "users_2"
605
- ON "users"."id" = "users_2"."id"
606
- }
607
- end
608
-
609
- it 'noops on nil' do
610
- manager = Arel::SelectManager.new Table.engine
611
- manager.outer_join(nil).must_equal manager
612
- end
613
- end
614
-
615
- describe 'joins' do
616
-
617
- it 'returns inner join sql' do
618
- table = Table.new :users
619
- aliaz = table.alias
620
- manager = Arel::SelectManager.new Table.engine
621
- manager.from Nodes::InnerJoin.new(aliaz, table[:id].eq(aliaz[:id]))
622
- assert_match 'INNER JOIN "users" "users_2" "users"."id" = "users_2"."id"',
623
- manager.to_sql
624
- end
625
-
626
- it 'returns outer join sql' do
627
- table = Table.new :users
628
- aliaz = table.alias
629
- manager = Arel::SelectManager.new Table.engine
630
- manager.from Nodes::OuterJoin.new(aliaz, table[:id].eq(aliaz[:id]))
631
- assert_match 'LEFT OUTER JOIN "users" "users_2" "users"."id" = "users_2"."id"',
632
- manager.to_sql
633
- end
634
-
635
- it 'can have a non-table alias as relation name' do
636
- users = Table.new :users
637
- comments = Table.new :comments
638
-
639
- counts = comments.from(comments).
640
- group(comments[:user_id]).
641
- project(
642
- comments[:user_id].as("user_id"),
643
- comments[:user_id].count.as("count")
644
- ).as("counts")
645
-
646
- joins = users.join(counts).on(counts[:user_id].eq(10))
647
- joins.to_sql.must_be_like %{
648
- SELECT FROM "users" INNER JOIN (SELECT "comments"."user_id" AS user_id, COUNT("comments"."user_id") AS count FROM "comments" GROUP BY "comments"."user_id") counts ON counts."user_id" = 10
649
- }
650
- end
651
-
652
- it "joins itself" do
653
- left = Table.new :users
654
- right = left.alias
655
- predicate = left[:id].eq(right[:id])
656
-
657
- mgr = left.join(right)
658
- mgr.project Nodes::SqlLiteral.new('*')
659
- mgr.on(predicate).must_equal mgr
660
-
661
- mgr.to_sql.must_be_like %{
662
- SELECT * FROM "users"
663
- INNER JOIN "users" "users_2"
664
- ON "users"."id" = "users_2"."id"
665
- }
666
- end
667
-
668
- it 'returns string join sql' do
669
- manager = Arel::SelectManager.new Table.engine
670
- manager.from Nodes::StringJoin.new(Nodes.build_quoted('hello'))
671
- assert_match "'hello'", manager.to_sql
672
- end
673
- end
674
-
675
- describe 'group' do
676
- it 'takes an attribute' do
677
- table = Table.new :users
678
- manager = Arel::SelectManager.new Table.engine
679
- manager.from table
680
- manager.group table[:id]
681
- manager.to_sql.must_be_like %{
682
- SELECT FROM "users" GROUP BY "users"."id"
683
- }
684
- end
685
-
686
- it 'chains' do
687
- table = Table.new :users
688
- manager = Arel::SelectManager.new Table.engine
689
- manager.group(table[:id]).must_equal manager
690
- end
691
-
692
- it 'takes multiple args' do
693
- table = Table.new :users
694
- manager = Arel::SelectManager.new Table.engine
695
- manager.from table
696
- manager.group table[:id], table[:name]
697
- manager.to_sql.must_be_like %{
698
- SELECT FROM "users" GROUP BY "users"."id", "users"."name"
699
- }
700
- end
701
-
702
- # FIXME: backwards compat
703
- it 'makes strings literals' do
704
- table = Table.new :users
705
- manager = Arel::SelectManager.new Table.engine
706
- manager.from table
707
- manager.group 'foo'
708
- manager.to_sql.must_be_like %{ SELECT FROM "users" GROUP BY foo }
709
- end
710
- end
711
-
712
- describe 'window definition' do
713
- it 'can be empty' do
714
- table = Table.new :users
715
- manager = Arel::SelectManager.new Table.engine
716
- manager.from table
717
- manager.window('a_window')
718
- manager.to_sql.must_be_like %{
719
- SELECT FROM "users" WINDOW "a_window" AS ()
720
- }
721
- end
722
-
723
- it 'takes an order' do
724
- table = Table.new :users
725
- manager = Arel::SelectManager.new Table.engine
726
- manager.from table
727
- manager.window('a_window').order(table['foo'].asc)
728
- manager.to_sql.must_be_like %{
729
- SELECT FROM "users" WINDOW "a_window" AS (ORDER BY "users"."foo" ASC)
730
- }
731
- end
732
-
733
- it 'takes an order with multiple columns' do
734
- table = Table.new :users
735
- manager = Arel::SelectManager.new Table.engine
736
- manager.from table
737
- manager.window('a_window').order(table['foo'].asc, table['bar'].desc)
738
- manager.to_sql.must_be_like %{
739
- SELECT FROM "users" WINDOW "a_window" AS (ORDER BY "users"."foo" ASC, "users"."bar" DESC)
740
- }
741
- end
742
-
743
- it 'takes a partition' do
744
- table = Table.new :users
745
- manager = Arel::SelectManager.new Table.engine
746
- manager.from table
747
- manager.window('a_window').partition(table['bar'])
748
- manager.to_sql.must_be_like %{
749
- SELECT FROM "users" WINDOW "a_window" AS (PARTITION BY "users"."bar")
750
- }
751
- end
752
-
753
- it 'takes a partition and an order' do
754
- table = Table.new :users
755
- manager = Arel::SelectManager.new Table.engine
756
- manager.from table
757
- manager.window('a_window').partition(table['foo']).order(table['foo'].asc)
758
- manager.to_sql.must_be_like %{
759
- SELECT FROM "users" WINDOW "a_window" AS (PARTITION BY "users"."foo"
760
- ORDER BY "users"."foo" ASC)
761
- }
762
- end
763
-
764
- it 'takes a partition with multiple columns' do
765
- table = Table.new :users
766
- manager = Arel::SelectManager.new Table.engine
767
- manager.from table
768
- manager.window('a_window').partition(table['bar'], table['baz'])
769
- manager.to_sql.must_be_like %{
770
- SELECT FROM "users" WINDOW "a_window" AS (PARTITION BY "users"."bar", "users"."baz")
771
- }
772
- end
773
-
774
- it 'takes a rows frame, unbounded preceding' do
775
- table = Table.new :users
776
- manager = Arel::SelectManager.new Table.engine
777
- manager.from table
778
- manager.window('a_window').rows(Arel::Nodes::Preceding.new)
779
- manager.to_sql.must_be_like %{
780
- SELECT FROM "users" WINDOW "a_window" AS (ROWS UNBOUNDED PRECEDING)
781
- }
782
- end
783
-
784
- it 'takes a rows frame, bounded preceding' do
785
- table = Table.new :users
786
- manager = Arel::SelectManager.new Table.engine
787
- manager.from table
788
- manager.window('a_window').rows(Arel::Nodes::Preceding.new(5))
789
- manager.to_sql.must_be_like %{
790
- SELECT FROM "users" WINDOW "a_window" AS (ROWS 5 PRECEDING)
791
- }
792
- end
793
-
794
- it 'takes a rows frame, unbounded following' do
795
- table = Table.new :users
796
- manager = Arel::SelectManager.new Table.engine
797
- manager.from table
798
- manager.window('a_window').rows(Arel::Nodes::Following.new)
799
- manager.to_sql.must_be_like %{
800
- SELECT FROM "users" WINDOW "a_window" AS (ROWS UNBOUNDED FOLLOWING)
801
- }
802
- end
803
-
804
- it 'takes a rows frame, bounded following' do
805
- table = Table.new :users
806
- manager = Arel::SelectManager.new Table.engine
807
- manager.from table
808
- manager.window('a_window').rows(Arel::Nodes::Following.new(5))
809
- manager.to_sql.must_be_like %{
810
- SELECT FROM "users" WINDOW "a_window" AS (ROWS 5 FOLLOWING)
811
- }
812
- end
813
-
814
- it 'takes a rows frame, current row' do
815
- table = Table.new :users
816
- manager = Arel::SelectManager.new Table.engine
817
- manager.from table
818
- manager.window('a_window').rows(Arel::Nodes::CurrentRow.new)
819
- manager.to_sql.must_be_like %{
820
- SELECT FROM "users" WINDOW "a_window" AS (ROWS CURRENT ROW)
821
- }
822
- end
823
-
824
- it 'takes a rows frame, between two delimiters' do
825
- table = Table.new :users
826
- manager = Arel::SelectManager.new Table.engine
827
- manager.from table
828
- window = manager.window('a_window')
829
- window.frame(
830
- Arel::Nodes::Between.new(
831
- window.rows,
832
- Nodes::And.new([
833
- Arel::Nodes::Preceding.new,
834
- Arel::Nodes::CurrentRow.new
835
- ])))
836
- manager.to_sql.must_be_like %{
837
- SELECT FROM "users" WINDOW "a_window" AS (ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
838
- }
839
- end
840
-
841
- it 'takes a range frame, unbounded preceding' do
842
- table = Table.new :users
843
- manager = Arel::SelectManager.new Table.engine
844
- manager.from table
845
- manager.window('a_window').range(Arel::Nodes::Preceding.new)
846
- manager.to_sql.must_be_like %{
847
- SELECT FROM "users" WINDOW "a_window" AS (RANGE UNBOUNDED PRECEDING)
848
- }
849
- end
850
-
851
- it 'takes a range frame, bounded preceding' do
852
- table = Table.new :users
853
- manager = Arel::SelectManager.new Table.engine
854
- manager.from table
855
- manager.window('a_window').range(Arel::Nodes::Preceding.new(5))
856
- manager.to_sql.must_be_like %{
857
- SELECT FROM "users" WINDOW "a_window" AS (RANGE 5 PRECEDING)
858
- }
859
- end
860
-
861
- it 'takes a range frame, unbounded following' do
862
- table = Table.new :users
863
- manager = Arel::SelectManager.new Table.engine
864
- manager.from table
865
- manager.window('a_window').range(Arel::Nodes::Following.new)
866
- manager.to_sql.must_be_like %{
867
- SELECT FROM "users" WINDOW "a_window" AS (RANGE UNBOUNDED FOLLOWING)
868
- }
869
- end
870
-
871
- it 'takes a range frame, bounded following' do
872
- table = Table.new :users
873
- manager = Arel::SelectManager.new Table.engine
874
- manager.from table
875
- manager.window('a_window').range(Arel::Nodes::Following.new(5))
876
- manager.to_sql.must_be_like %{
877
- SELECT FROM "users" WINDOW "a_window" AS (RANGE 5 FOLLOWING)
878
- }
879
- end
880
-
881
- it 'takes a range frame, current row' do
882
- table = Table.new :users
883
- manager = Arel::SelectManager.new Table.engine
884
- manager.from table
885
- manager.window('a_window').range(Arel::Nodes::CurrentRow.new)
886
- manager.to_sql.must_be_like %{
887
- SELECT FROM "users" WINDOW "a_window" AS (RANGE CURRENT ROW)
888
- }
889
- end
890
-
891
- it 'takes a range frame, between two delimiters' do
892
- table = Table.new :users
893
- manager = Arel::SelectManager.new Table.engine
894
- manager.from table
895
- window = manager.window('a_window')
896
- window.frame(
897
- Arel::Nodes::Between.new(
898
- window.range,
899
- Nodes::And.new([
900
- Arel::Nodes::Preceding.new,
901
- Arel::Nodes::CurrentRow.new
902
- ])))
903
- manager.to_sql.must_be_like %{
904
- SELECT FROM "users" WINDOW "a_window" AS (RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
905
- }
906
- end
907
- end
908
-
909
- describe 'delete' do
910
- it "copies from" do
911
- table = Table.new :users
912
- manager = Arel::SelectManager.new Table.engine
913
- manager.from table
914
- stmt = manager.compile_delete
915
-
916
- stmt.to_sql.must_be_like %{ DELETE FROM "users" }
917
- end
918
-
919
- it "copies where" do
920
- table = Table.new :users
921
- manager = Arel::SelectManager.new Table.engine
922
- manager.from table
923
- manager.where table[:id].eq 10
924
- stmt = manager.compile_delete
925
-
926
- stmt.to_sql.must_be_like %{
927
- DELETE FROM "users" WHERE "users"."id" = 10
928
- }
929
- end
930
- end
931
-
932
- describe 'where_sql' do
933
- it 'gives me back the where sql' do
934
- table = Table.new :users
935
- manager = Arel::SelectManager.new Table.engine
936
- manager.from table
937
- manager.where table[:id].eq 10
938
- manager.where_sql.must_be_like %{ WHERE "users"."id" = 10 }
939
- end
940
-
941
- it 'returns nil when there are no wheres' do
942
- table = Table.new :users
943
- manager = Arel::SelectManager.new Table.engine
944
- manager.from table
945
- manager.where_sql.must_be_nil
946
- end
947
- end
948
-
949
- describe 'update' do
950
-
951
- it 'creates an update statement' do
952
- table = Table.new :users
953
- manager = Arel::SelectManager.new Table.engine
954
- manager.from table
955
- stmt = manager.compile_update({table[:id] => 1}, Arel::Attributes::Attribute.new(table, 'id'))
956
-
957
- stmt.to_sql.must_be_like %{
958
- UPDATE "users" SET "id" = 1
959
- }
960
- end
961
-
962
- it 'takes a string' do
963
- table = Table.new :users
964
- manager = Arel::SelectManager.new Table.engine
965
- manager.from table
966
- stmt = manager.compile_update(Nodes::SqlLiteral.new('foo = bar'), Arel::Attributes::Attribute.new(table, 'id'))
967
-
968
- stmt.to_sql.must_be_like %{ UPDATE "users" SET foo = bar }
969
- end
970
-
971
- it 'copies limits' do
972
- table = Table.new :users
973
- manager = Arel::SelectManager.new Table.engine
974
- manager.from table
975
- manager.take 1
976
- stmt = manager.compile_update(Nodes::SqlLiteral.new('foo = bar'), Arel::Attributes::Attribute.new(table, 'id'))
977
- stmt.key = table['id']
978
-
979
- stmt.to_sql.must_be_like %{
980
- UPDATE "users" SET foo = bar
981
- WHERE "users"."id" IN (SELECT "users"."id" FROM "users" LIMIT 1)
982
- }
983
- end
984
-
985
- it 'copies order' do
986
- table = Table.new :users
987
- manager = Arel::SelectManager.new Table.engine
988
- manager.from table
989
- manager.order :foo
990
- stmt = manager.compile_update(Nodes::SqlLiteral.new('foo = bar'), Arel::Attributes::Attribute.new(table, 'id'))
991
- stmt.key = table['id']
992
-
993
- stmt.to_sql.must_be_like %{
994
- UPDATE "users" SET foo = bar
995
- WHERE "users"."id" IN (SELECT "users"."id" FROM "users" ORDER BY foo)
996
- }
997
- end
998
-
999
- it 'copies where clauses' do
1000
- table = Table.new :users
1001
- manager = Arel::SelectManager.new Table.engine
1002
- manager.where table[:id].eq 10
1003
- manager.from table
1004
- stmt = manager.compile_update({table[:id] => 1}, Arel::Attributes::Attribute.new(table, 'id'))
1005
-
1006
- stmt.to_sql.must_be_like %{
1007
- UPDATE "users" SET "id" = 1 WHERE "users"."id" = 10
1008
- }
1009
- end
1010
-
1011
- it 'copies where clauses when nesting is triggered' do
1012
- table = Table.new :users
1013
- manager = Arel::SelectManager.new Table.engine
1014
- manager.where table[:foo].eq 10
1015
- manager.take 42
1016
- manager.from table
1017
- stmt = manager.compile_update({table[:id] => 1}, Arel::Attributes::Attribute.new(table, 'id'))
1018
-
1019
- stmt.to_sql.must_be_like %{
1020
- UPDATE "users" SET "id" = 1 WHERE "users"."id" IN (SELECT "users"."id" FROM "users" WHERE "users"."foo" = 10 LIMIT 42)
1021
- }
1022
- end
1023
-
1024
- end
1025
-
1026
- describe 'project' do
1027
- it "takes sql literals" do
1028
- manager = Arel::SelectManager.new Table.engine
1029
- manager.project Nodes::SqlLiteral.new '*'
1030
- manager.to_sql.must_be_like %{ SELECT * }
1031
- end
1032
-
1033
- it 'takes multiple args' do
1034
- manager = Arel::SelectManager.new Table.engine
1035
- manager.project Nodes::SqlLiteral.new('foo'),
1036
- Nodes::SqlLiteral.new('bar')
1037
- manager.to_sql.must_be_like %{ SELECT foo, bar }
1038
- end
1039
-
1040
- it 'takes strings' do
1041
- manager = Arel::SelectManager.new Table.engine
1042
- manager.project '*'
1043
- manager.to_sql.must_be_like %{ SELECT * }
1044
- end
1045
-
1046
- end
1047
-
1048
- describe 'projections' do
1049
- it 'reads projections' do
1050
- manager = Arel::SelectManager.new Table.engine
1051
- manager.project Arel.sql('foo'), Arel.sql('bar')
1052
- manager.projections.must_equal [Arel.sql('foo'), Arel.sql('bar')]
1053
- end
1054
- end
1055
-
1056
- describe 'projections=' do
1057
- it 'overwrites projections' do
1058
- manager = Arel::SelectManager.new Table.engine
1059
- manager.project Arel.sql('foo')
1060
- manager.projections = [Arel.sql('bar')]
1061
- manager.to_sql.must_be_like %{ SELECT bar }
1062
- end
1063
- end
1064
-
1065
- describe 'take' do
1066
- it "knows take" do
1067
- table = Table.new :users
1068
- manager = Arel::SelectManager.new Table.engine
1069
- manager.from(table).project(table['id'])
1070
- manager.where(table['id'].eq(1))
1071
- manager.take 1
1072
-
1073
- manager.to_sql.must_be_like %{
1074
- SELECT "users"."id"
1075
- FROM "users"
1076
- WHERE "users"."id" = 1
1077
- LIMIT 1
1078
- }
1079
- end
1080
-
1081
- it "chains" do
1082
- manager = Arel::SelectManager.new Table.engine
1083
- manager.take(1).must_equal manager
1084
- end
1085
-
1086
- it 'removes LIMIT when nil is passed' do
1087
- manager = Arel::SelectManager.new Table.engine
1088
- manager.limit = 10
1089
- assert_match('LIMIT', manager.to_sql)
1090
-
1091
- manager.limit = nil
1092
- refute_match('LIMIT', manager.to_sql)
1093
- end
1094
- end
1095
-
1096
- describe 'where' do
1097
- it "knows where" do
1098
- table = Table.new :users
1099
- manager = Arel::SelectManager.new Table.engine
1100
- manager.from(table).project(table['id'])
1101
- manager.where(table['id'].eq(1))
1102
- manager.to_sql.must_be_like %{
1103
- SELECT "users"."id"
1104
- FROM "users"
1105
- WHERE "users"."id" = 1
1106
- }
1107
- end
1108
-
1109
- it "chains" do
1110
- table = Table.new :users
1111
- manager = Arel::SelectManager.new Table.engine
1112
- manager.from(table)
1113
- manager.project(table['id']).where(table['id'].eq 1).must_equal manager
1114
- end
1115
- end
1116
-
1117
- describe 'from' do
1118
- it "makes sql" do
1119
- table = Table.new :users
1120
- manager = Arel::SelectManager.new Table.engine
1121
-
1122
- manager.from table
1123
- manager.project table['id']
1124
- manager.to_sql.must_be_like 'SELECT "users"."id" FROM "users"'
1125
- end
1126
-
1127
- it "chains" do
1128
- table = Table.new :users
1129
- manager = Arel::SelectManager.new Table.engine
1130
- manager.from(table).project(table['id']).must_equal manager
1131
- manager.to_sql.must_be_like 'SELECT "users"."id" FROM "users"'
1132
- end
1133
- end
1134
-
1135
- describe 'source' do
1136
- it 'returns the join source of the select core' do
1137
- manager = Arel::SelectManager.new Table.engine
1138
- manager.source.must_equal manager.ast.cores.last.source
1139
- end
1140
- end
1141
-
1142
- describe 'distinct' do
1143
- it 'sets the quantifier' do
1144
- manager = Arel::SelectManager.new Table.engine
1145
-
1146
- manager.distinct
1147
- manager.ast.cores.last.set_quantifier.class.must_equal Arel::Nodes::Distinct
1148
-
1149
- manager.distinct(false)
1150
- manager.ast.cores.last.set_quantifier.must_equal nil
1151
- end
1152
-
1153
- it "chains" do
1154
- manager = Arel::SelectManager.new Table.engine
1155
- manager.distinct.must_equal manager
1156
- manager.distinct(false).must_equal manager
1157
- end
1158
- end
1159
-
1160
- describe 'distinct_on' do
1161
- it 'sets the quantifier' do
1162
- manager = Arel::SelectManager.new Table.engine
1163
- table = Table.new :users
1164
-
1165
- manager.distinct_on(table['id'])
1166
- manager.ast.cores.last.set_quantifier.must_equal Arel::Nodes::DistinctOn.new(table['id'])
1167
-
1168
- manager.distinct_on(false)
1169
- manager.ast.cores.last.set_quantifier.must_equal nil
1170
- end
1171
-
1172
- it "chains" do
1173
- manager = Arel::SelectManager.new Table.engine
1174
- table = Table.new :users
1175
-
1176
- manager.distinct_on(table['id']).must_equal manager
1177
- manager.distinct_on(false).must_equal manager
1178
- end
1179
- end
1180
- end
1181
- end