arel 6.0.0.beta2 → 6.0.0

Sign up to get free protection for your applications and to get access to all the features.
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