arel 0.1.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.
- data/.gitignore +6 -0
- data/README.markdown +184 -0
- data/Rakefile +60 -0
- data/VERSION +1 -0
- data/arel.gemspec +233 -0
- data/doc/CONVENTIONS +17 -0
- data/doc/TODO +118 -0
- data/lib/arel.rb +10 -0
- data/lib/arel/algebra.rb +4 -0
- data/lib/arel/algebra/extensions.rb +4 -0
- data/lib/arel/algebra/extensions/class.rb +32 -0
- data/lib/arel/algebra/extensions/hash.rb +11 -0
- data/lib/arel/algebra/extensions/object.rb +17 -0
- data/lib/arel/algebra/extensions/symbol.rb +9 -0
- data/lib/arel/algebra/predicates.rb +41 -0
- data/lib/arel/algebra/primitives.rb +5 -0
- data/lib/arel/algebra/primitives/attribute.rb +150 -0
- data/lib/arel/algebra/primitives/expression.rb +43 -0
- data/lib/arel/algebra/primitives/ordering.rb +23 -0
- data/lib/arel/algebra/primitives/value.rb +14 -0
- data/lib/arel/algebra/relations.rb +14 -0
- data/lib/arel/algebra/relations/operations/alias.rb +7 -0
- data/lib/arel/algebra/relations/operations/group.rb +12 -0
- data/lib/arel/algebra/relations/operations/join.rb +64 -0
- data/lib/arel/algebra/relations/operations/order.rb +18 -0
- data/lib/arel/algebra/relations/operations/project.rb +20 -0
- data/lib/arel/algebra/relations/operations/skip.rb +6 -0
- data/lib/arel/algebra/relations/operations/take.rb +10 -0
- data/lib/arel/algebra/relations/operations/where.rb +16 -0
- data/lib/arel/algebra/relations/relation.rb +136 -0
- data/lib/arel/algebra/relations/row.rb +26 -0
- data/lib/arel/algebra/relations/utilities/compound.rb +30 -0
- data/lib/arel/algebra/relations/utilities/externalization.rb +24 -0
- data/lib/arel/algebra/relations/utilities/nil.rb +7 -0
- data/lib/arel/algebra/relations/writes.rb +36 -0
- data/lib/arel/engines.rb +2 -0
- data/lib/arel/engines/memory.rb +4 -0
- data/lib/arel/engines/memory/engine.rb +16 -0
- data/lib/arel/engines/memory/predicates.rb +35 -0
- data/lib/arel/engines/memory/primitives.rb +27 -0
- data/lib/arel/engines/memory/relations.rb +5 -0
- data/lib/arel/engines/memory/relations/array.rb +25 -0
- data/lib/arel/engines/memory/relations/compound.rb +9 -0
- data/lib/arel/engines/memory/relations/operations.rb +61 -0
- data/lib/arel/engines/memory/relations/writes.rb +7 -0
- data/lib/arel/engines/sql.rb +7 -0
- data/lib/arel/engines/sql/christener.rb +13 -0
- data/lib/arel/engines/sql/engine.rb +37 -0
- data/lib/arel/engines/sql/extensions.rb +4 -0
- data/lib/arel/engines/sql/extensions/array.rb +16 -0
- data/lib/arel/engines/sql/extensions/nil_class.rb +11 -0
- data/lib/arel/engines/sql/extensions/object.rb +15 -0
- data/lib/arel/engines/sql/extensions/range.rb +15 -0
- data/lib/arel/engines/sql/formatters.rb +113 -0
- data/lib/arel/engines/sql/predicates.rb +51 -0
- data/lib/arel/engines/sql/primitives.rb +85 -0
- data/lib/arel/engines/sql/relations.rb +9 -0
- data/lib/arel/engines/sql/relations/operations/alias.rb +5 -0
- data/lib/arel/engines/sql/relations/operations/join.rb +33 -0
- data/lib/arel/engines/sql/relations/relation.rb +50 -0
- data/lib/arel/engines/sql/relations/table.rb +52 -0
- data/lib/arel/engines/sql/relations/utilities/compound.rb +10 -0
- data/lib/arel/engines/sql/relations/utilities/externalization.rb +14 -0
- data/lib/arel/engines/sql/relations/utilities/nil.rb +6 -0
- data/lib/arel/engines/sql/relations/utilities/recursion.rb +13 -0
- data/lib/arel/engines/sql/relations/writes.rb +39 -0
- data/lib/arel/session.rb +48 -0
- data/spec/arel/algebra/unit/predicates/binary_spec.rb +33 -0
- data/spec/arel/algebra/unit/predicates/equality_spec.rb +27 -0
- data/spec/arel/algebra/unit/predicates/in_spec.rb +10 -0
- data/spec/arel/algebra/unit/primitives/attribute_spec.rb +183 -0
- data/spec/arel/algebra/unit/primitives/expression_spec.rb +45 -0
- data/spec/arel/algebra/unit/primitives/value_spec.rb +15 -0
- data/spec/arel/algebra/unit/relations/alias_spec.rb +16 -0
- data/spec/arel/algebra/unit/relations/delete_spec.rb +9 -0
- data/spec/arel/algebra/unit/relations/group_spec.rb +10 -0
- data/spec/arel/algebra/unit/relations/insert_spec.rb +9 -0
- data/spec/arel/algebra/unit/relations/join_spec.rb +26 -0
- data/spec/arel/algebra/unit/relations/order_spec.rb +21 -0
- data/spec/arel/algebra/unit/relations/project_spec.rb +34 -0
- data/spec/arel/algebra/unit/relations/relation_spec.rb +188 -0
- data/spec/arel/algebra/unit/relations/skip_spec.rb +10 -0
- data/spec/arel/algebra/unit/relations/table_spec.rb +39 -0
- data/spec/arel/algebra/unit/relations/take_spec.rb +10 -0
- data/spec/arel/algebra/unit/relations/update_spec.rb +9 -0
- data/spec/arel/algebra/unit/relations/where_spec.rb +18 -0
- data/spec/arel/algebra/unit/session/session_spec.rb +84 -0
- data/spec/arel/engines/memory/integration/joins/cross_engine_spec.rb +48 -0
- data/spec/arel/engines/memory/unit/relations/array_spec.rb +32 -0
- data/spec/arel/engines/memory/unit/relations/insert_spec.rb +28 -0
- data/spec/arel/engines/memory/unit/relations/join_spec.rb +31 -0
- data/spec/arel/engines/memory/unit/relations/order_spec.rb +27 -0
- data/spec/arel/engines/memory/unit/relations/project_spec.rb +27 -0
- data/spec/arel/engines/memory/unit/relations/skip_spec.rb +26 -0
- data/spec/arel/engines/memory/unit/relations/take_spec.rb +26 -0
- data/spec/arel/engines/memory/unit/relations/where_spec.rb +39 -0
- data/spec/arel/engines/sql/integration/joins/with_adjacency_spec.rb +209 -0
- data/spec/arel/engines/sql/integration/joins/with_aggregations_spec.rb +167 -0
- data/spec/arel/engines/sql/integration/joins/with_compounds_spec.rb +107 -0
- data/spec/arel/engines/sql/unit/engine_spec.rb +45 -0
- data/spec/arel/engines/sql/unit/predicates/binary_spec.rb +117 -0
- data/spec/arel/engines/sql/unit/predicates/equality_spec.rb +46 -0
- data/spec/arel/engines/sql/unit/predicates/in_spec.rb +86 -0
- data/spec/arel/engines/sql/unit/predicates/predicates_spec.rb +65 -0
- data/spec/arel/engines/sql/unit/primitives/attribute_spec.rb +32 -0
- data/spec/arel/engines/sql/unit/primitives/expression_spec.rb +24 -0
- data/spec/arel/engines/sql/unit/primitives/literal_spec.rb +23 -0
- data/spec/arel/engines/sql/unit/primitives/value_spec.rb +29 -0
- data/spec/arel/engines/sql/unit/relations/alias_spec.rb +43 -0
- data/spec/arel/engines/sql/unit/relations/delete_spec.rb +63 -0
- data/spec/arel/engines/sql/unit/relations/group_spec.rb +56 -0
- data/spec/arel/engines/sql/unit/relations/insert_spec.rb +107 -0
- data/spec/arel/engines/sql/unit/relations/join_spec.rb +57 -0
- data/spec/arel/engines/sql/unit/relations/order_spec.rb +113 -0
- data/spec/arel/engines/sql/unit/relations/project_spec.rb +110 -0
- data/spec/arel/engines/sql/unit/relations/skip_spec.rb +32 -0
- data/spec/arel/engines/sql/unit/relations/table_spec.rb +69 -0
- data/spec/arel/engines/sql/unit/relations/take_spec.rb +32 -0
- data/spec/arel/engines/sql/unit/relations/update_spec.rb +151 -0
- data/spec/arel/engines/sql/unit/relations/where_spec.rb +56 -0
- data/spec/connections/mysql_connection.rb +16 -0
- data/spec/connections/postgresql_connection.rb +15 -0
- data/spec/connections/sqlite3_connection.rb +25 -0
- data/spec/doubles/hash.rb +23 -0
- data/spec/matchers/be_like.rb +24 -0
- data/spec/matchers/disambiguate_attributes.rb +28 -0
- data/spec/matchers/hash_the_same_as.rb +26 -0
- data/spec/schemas/mysql_schema.rb +18 -0
- data/spec/schemas/postgresql_schema.rb +18 -0
- data/spec/schemas/sqlite3_schema.rb +18 -0
- data/spec/spec_helper.rb +47 -0
- metadata +250 -0
@@ -0,0 +1,209 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
|
2
|
+
|
3
|
+
module Arel
|
4
|
+
describe Join do
|
5
|
+
before do
|
6
|
+
@relation1 = Table(:users)
|
7
|
+
@relation2 = @relation1.alias
|
8
|
+
@predicate = @relation1[:id].eq(@relation2[:id])
|
9
|
+
end
|
10
|
+
|
11
|
+
describe 'when joining a relation to itself' do
|
12
|
+
describe '#to_sql' do
|
13
|
+
it 'manufactures sql aliasing the table and attributes properly in the join predicate and the where clause' do
|
14
|
+
sql = @relation1.join(@relation2).on(@predicate).to_sql
|
15
|
+
|
16
|
+
adapter_is :mysql do
|
17
|
+
sql.should be_like(%Q{
|
18
|
+
SELECT `users`.`id`, `users`.`name`, `users_2`.`id`, `users_2`.`name`
|
19
|
+
FROM `users`
|
20
|
+
INNER JOIN `users` AS `users_2`
|
21
|
+
ON `users`.`id` = `users_2`.`id`
|
22
|
+
})
|
23
|
+
end
|
24
|
+
|
25
|
+
adapter_is_not :mysql do
|
26
|
+
sql.should be_like(%Q{
|
27
|
+
SELECT "users"."id", "users"."name", "users_2"."id", "users_2"."name"
|
28
|
+
FROM "users"
|
29
|
+
INNER JOIN "users" AS "users_2"
|
30
|
+
ON "users"."id" = "users_2"."id"
|
31
|
+
})
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe 'when joining with a where on the same relation' do
|
36
|
+
it 'manufactures sql aliasing the tables properly' do
|
37
|
+
sql = @relation1 \
|
38
|
+
.join(@relation2.where(@relation2[:id].eq(1))) \
|
39
|
+
.on(@predicate) \
|
40
|
+
.to_sql
|
41
|
+
|
42
|
+
adapter_is :mysql do
|
43
|
+
sql.should be_like(%Q{
|
44
|
+
SELECT `users`.`id`, `users`.`name`, `users_2`.`id`, `users_2`.`name`
|
45
|
+
FROM `users`
|
46
|
+
INNER JOIN `users` AS `users_2`
|
47
|
+
ON `users`.`id` = `users_2`.`id` AND `users_2`.`id` = 1
|
48
|
+
})
|
49
|
+
end
|
50
|
+
|
51
|
+
adapter_is_not :mysql do
|
52
|
+
sql.should be_like(%Q{
|
53
|
+
SELECT "users"."id", "users"."name", "users_2"."id", "users_2"."name"
|
54
|
+
FROM "users"
|
55
|
+
INNER JOIN "users" AS "users_2"
|
56
|
+
ON "users"."id" = "users_2"."id" AND "users_2"."id" = 1
|
57
|
+
})
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe 'when the where occurs before the alias' do
|
62
|
+
it 'manufactures sql aliasing the predicates properly' do
|
63
|
+
relation2 = @relation1.where(@relation1[:id].eq(1)).alias
|
64
|
+
|
65
|
+
sql = @relation1 \
|
66
|
+
.join(relation2) \
|
67
|
+
.on(relation2[:id].eq(@relation1[:id])) \
|
68
|
+
.to_sql
|
69
|
+
|
70
|
+
adapter_is :mysql do
|
71
|
+
sql.should be_like(%Q{
|
72
|
+
SELECT `users`.`id`, `users`.`name`, `users_2`.`id`, `users_2`.`name`
|
73
|
+
FROM `users`
|
74
|
+
INNER JOIN `users` AS `users_2`
|
75
|
+
ON `users_2`.`id` = `users`.`id` AND `users_2`.`id` = 1
|
76
|
+
})
|
77
|
+
end
|
78
|
+
|
79
|
+
adapter_is_not :mysql do
|
80
|
+
sql.should be_like(%Q{
|
81
|
+
SELECT "users"."id", "users"."name", "users_2"."id", "users_2"."name"
|
82
|
+
FROM "users"
|
83
|
+
INNER JOIN "users" AS "users_2"
|
84
|
+
ON "users_2"."id" = "users"."id" AND "users_2"."id" = 1
|
85
|
+
})
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe 'when joining the relation to itself multiple times' do
|
92
|
+
before do
|
93
|
+
@relation3 = @relation1.alias
|
94
|
+
end
|
95
|
+
|
96
|
+
describe 'when joining left-associatively' do
|
97
|
+
it 'manufactures sql aliasing the tables properly' do
|
98
|
+
sql = @relation1 \
|
99
|
+
.join(@relation2 \
|
100
|
+
.join(@relation3) \
|
101
|
+
.on(@relation2[:id].eq(@relation3[:id]))) \
|
102
|
+
.on(@relation1[:id].eq(@relation2[:id])) \
|
103
|
+
.to_sql
|
104
|
+
|
105
|
+
adapter_is :mysql do
|
106
|
+
sql.should be_like(%Q{
|
107
|
+
SELECT `users`.`id`, `users`.`name`, `users_2`.`id`, `users_2`.`name`, `users_3`.`id`, `users_3`.`name`
|
108
|
+
FROM `users`
|
109
|
+
INNER JOIN `users` AS `users_2`
|
110
|
+
ON `users`.`id` = `users_2`.`id`
|
111
|
+
INNER JOIN `users` AS `users_3`
|
112
|
+
ON `users_2`.`id` = `users_3`.`id`
|
113
|
+
})
|
114
|
+
end
|
115
|
+
|
116
|
+
adapter_is_not :mysql do
|
117
|
+
sql.should be_like(%Q{
|
118
|
+
SELECT "users"."id", "users"."name", "users_2"."id", "users_2"."name", "users_3"."id", "users_3"."name"
|
119
|
+
FROM "users"
|
120
|
+
INNER JOIN "users" AS "users_2"
|
121
|
+
ON "users"."id" = "users_2"."id"
|
122
|
+
INNER JOIN "users" AS "users_3"
|
123
|
+
ON "users_2"."id" = "users_3"."id"
|
124
|
+
})
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
describe 'when joining right-associatively' do
|
130
|
+
it 'manufactures sql aliasing the tables properly' do
|
131
|
+
sql = @relation1 \
|
132
|
+
.join(@relation2).on(@relation1[:id].eq(@relation2[:id])) \
|
133
|
+
.join(@relation3).on(@relation2[:id].eq(@relation3[:id])) \
|
134
|
+
.to_sql
|
135
|
+
|
136
|
+
adapter_is :mysql do
|
137
|
+
sql.should be_like(%Q{
|
138
|
+
SELECT `users`.`id`, `users`.`name`, `users_2`.`id`, `users_2`.`name`, `users_3`.`id`, `users_3`.`name`
|
139
|
+
FROM `users`
|
140
|
+
INNER JOIN `users` AS `users_2`
|
141
|
+
ON `users`.`id` = `users_2`.`id`
|
142
|
+
INNER JOIN `users` AS `users_3`
|
143
|
+
ON `users_2`.`id` = `users_3`.`id`
|
144
|
+
})
|
145
|
+
end
|
146
|
+
|
147
|
+
adapter_is_not :mysql do
|
148
|
+
sql.should be_like(%Q{
|
149
|
+
SELECT "users"."id", "users"."name", "users_2"."id", "users_2"."name", "users_3"."id", "users_3"."name"
|
150
|
+
FROM "users"
|
151
|
+
INNER JOIN "users" AS "users_2"
|
152
|
+
ON "users"."id" = "users_2"."id"
|
153
|
+
INNER JOIN "users" AS "users_3"
|
154
|
+
ON "users_2"."id" = "users_3"."id"
|
155
|
+
})
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
describe '[]' do
|
163
|
+
describe 'when given an attribute belonging to both sub-relations' do
|
164
|
+
it 'disambiguates the relation that serves as the ancestor to the attribute' do
|
165
|
+
@relation1 \
|
166
|
+
.join(@relation2) \
|
167
|
+
.on(@predicate) \
|
168
|
+
.should disambiguate_attributes(@relation1[:id], @relation2[:id])
|
169
|
+
end
|
170
|
+
|
171
|
+
describe 'when both relations are compound and only one is an alias' do
|
172
|
+
it 'disambiguates the relation that serves as the ancestor to the attribute' do
|
173
|
+
compound1 = @relation1.where(@predicate)
|
174
|
+
compound2 = compound1.alias
|
175
|
+
compound1 \
|
176
|
+
.join(compound2) \
|
177
|
+
.on(@predicate) \
|
178
|
+
.should disambiguate_attributes(compound1[:id], compound2[:id])
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
describe 'when the left relation is extremely compound' do
|
183
|
+
it 'disambiguates the relation that serves as the ancestor to the attribute' do
|
184
|
+
@relation1 \
|
185
|
+
.where(@predicate) \
|
186
|
+
.where(@predicate) \
|
187
|
+
.join(@relation2) \
|
188
|
+
.on(@predicate) \
|
189
|
+
.should disambiguate_attributes(@relation1[:id], @relation2[:id])
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
describe 'when the right relation is extremely compound' do
|
194
|
+
it 'disambiguates the relation that serves as the ancestor to the attribute' do
|
195
|
+
@relation1 \
|
196
|
+
.join( \
|
197
|
+
@relation2 \
|
198
|
+
.where(@predicate) \
|
199
|
+
.where(@predicate) \
|
200
|
+
.where(@predicate)) \
|
201
|
+
.on(@predicate) \
|
202
|
+
.should disambiguate_attributes(@relation1[:id], @relation2[:id])
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
@@ -0,0 +1,167 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
|
2
|
+
|
3
|
+
module Arel
|
4
|
+
describe Join do
|
5
|
+
before do
|
6
|
+
@relation1 = Table(:users)
|
7
|
+
@relation2 = Table(:photos)
|
8
|
+
@predicate = @relation1[:id].eq(@relation2[:user_id])
|
9
|
+
end
|
10
|
+
|
11
|
+
describe 'when joining aggregated relations' do
|
12
|
+
before do
|
13
|
+
@aggregation = @relation2 \
|
14
|
+
.group(@relation2[:user_id]) \
|
15
|
+
.project(@relation2[:user_id], @relation2[:id].count.as(:cnt)) \
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#to_sql' do
|
19
|
+
# CLEANUP
|
20
|
+
it '' do
|
21
|
+
sql = @relation1.join(@relation2.take(3)).on(@predicate).to_sql
|
22
|
+
|
23
|
+
adapter_is :mysql do
|
24
|
+
sql.should be_like(%Q{
|
25
|
+
SELECT `users`.`id`, `users`.`name`, `photos_external`.`id`, `photos_external`.`user_id`, `photos_external`.`camera_id`
|
26
|
+
FROM `users`
|
27
|
+
INNER JOIN (SELECT `photos`.`id`, `photos`.`user_id`, `photos`.`camera_id` FROM `photos` LIMIT 3) AS `photos_external`
|
28
|
+
ON `users`.`id` = `photos_external`.`user_id`
|
29
|
+
})
|
30
|
+
end
|
31
|
+
|
32
|
+
adapter_is_not :mysql do
|
33
|
+
sql.should be_like(%Q{
|
34
|
+
SELECT "users"."id", "users"."name", "photos_external"."id", "photos_external"."user_id", "photos_external"."camera_id"
|
35
|
+
FROM "users"
|
36
|
+
INNER JOIN (SELECT "photos"."id", "photos"."user_id", "photos"."camera_id" FROM "photos" LIMIT 3) AS "photos_external"
|
37
|
+
ON "users"."id" = "photos_external"."user_id"
|
38
|
+
})
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe 'with the aggregation on the right' do
|
43
|
+
it 'manufactures sql joining the left table to a derived table' do
|
44
|
+
sql = @relation1.join(@aggregation).on(@predicate).to_sql
|
45
|
+
|
46
|
+
adapter_is :mysql do
|
47
|
+
sql.should be_like(%Q{
|
48
|
+
SELECT `users`.`id`, `users`.`name`, `photos_external`.`user_id`, `photos_external`.`cnt`
|
49
|
+
FROM `users`
|
50
|
+
INNER JOIN (SELECT `photos`.`user_id`, COUNT(`photos`.`id`) AS `cnt` FROM `photos` GROUP BY `photos`.`user_id`) AS `photos_external`
|
51
|
+
ON `users`.`id` = `photos_external`.`user_id`
|
52
|
+
})
|
53
|
+
end
|
54
|
+
|
55
|
+
adapter_is_not :mysql do
|
56
|
+
sql.should be_like(%Q{
|
57
|
+
SELECT "users"."id", "users"."name", "photos_external"."user_id", "photos_external"."cnt"
|
58
|
+
FROM "users"
|
59
|
+
INNER JOIN (SELECT "photos"."user_id", COUNT("photos"."id") AS "cnt" FROM "photos" GROUP BY "photos"."user_id") AS "photos_external"
|
60
|
+
ON "users"."id" = "photos_external"."user_id"
|
61
|
+
})
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe 'with the aggregation on the left' do
|
67
|
+
it 'manufactures sql joining the right table to a derived table' do
|
68
|
+
sql = @aggregation.join(@relation1).on(@predicate).to_sql
|
69
|
+
|
70
|
+
adapter_is :mysql do
|
71
|
+
sql.should be_like(%Q{
|
72
|
+
SELECT `photos_external`.`user_id`, `photos_external`.`cnt`, `users`.`id`, `users`.`name`
|
73
|
+
FROM (SELECT `photos`.`user_id`, COUNT(`photos`.`id`) AS `cnt` FROM `photos` GROUP BY `photos`.`user_id`) AS `photos_external`
|
74
|
+
INNER JOIN `users`
|
75
|
+
ON `users`.`id` = `photos_external`.`user_id`
|
76
|
+
})
|
77
|
+
end
|
78
|
+
|
79
|
+
adapter_is_not :mysql do
|
80
|
+
sql.should be_like(%Q{
|
81
|
+
SELECT "photos_external"."user_id", "photos_external"."cnt", "users"."id", "users"."name"
|
82
|
+
FROM (SELECT "photos"."user_id", COUNT("photos"."id") AS "cnt" FROM "photos" GROUP BY "photos"."user_id") AS "photos_external"
|
83
|
+
INNER JOIN "users"
|
84
|
+
ON "users"."id" = "photos_external"."user_id"
|
85
|
+
})
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe 'with the aggregation on both sides' do
|
91
|
+
it 'it properly aliases the aggregations' do
|
92
|
+
aggregation2 = @aggregation.alias
|
93
|
+
sql = @aggregation.join(aggregation2).on(aggregation2[:user_id].eq(@aggregation[:user_id])).to_sql
|
94
|
+
|
95
|
+
adapter_is :mysql do
|
96
|
+
sql.should be_like(%Q{
|
97
|
+
SELECT `photos_external`.`user_id`, `photos_external`.`cnt`, `photos_external_2`.`user_id`, `photos_external_2`.`cnt`
|
98
|
+
FROM (SELECT `photos`.`user_id`, COUNT(`photos`.`id`) AS `cnt` FROM `photos` GROUP BY `photos`.`user_id`) AS `photos_external`
|
99
|
+
INNER JOIN (SELECT `photos`.`user_id`, COUNT(`photos`.`id`) AS `cnt` FROM `photos` GROUP BY `photos`.`user_id`) AS `photos_external_2`
|
100
|
+
ON `photos_external_2`.`user_id` = `photos_external`.`user_id`
|
101
|
+
})
|
102
|
+
end
|
103
|
+
|
104
|
+
adapter_is_not :mysql do
|
105
|
+
sql.should be_like(%Q{
|
106
|
+
SELECT "photos_external"."user_id", "photos_external"."cnt", "photos_external_2"."user_id", "photos_external_2"."cnt"
|
107
|
+
FROM (SELECT "photos"."user_id", COUNT("photos"."id") AS "cnt" FROM "photos" GROUP BY "photos"."user_id") AS "photos_external"
|
108
|
+
INNER JOIN (SELECT "photos"."user_id", COUNT("photos"."id") AS "cnt" FROM "photos" GROUP BY "photos"."user_id") AS "photos_external_2"
|
109
|
+
ON "photos_external_2"."user_id" = "photos_external"."user_id"
|
110
|
+
})
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
describe 'when the aggration has a where' do
|
116
|
+
describe 'with the aggregation on the left' do
|
117
|
+
it "manufactures sql keeping wheres on the aggregation within the derived table" do
|
118
|
+
sql = @relation1.join(@aggregation.where(@aggregation[:user_id].eq(1))).on(@predicate).to_sql
|
119
|
+
|
120
|
+
adapter_is :mysql do
|
121
|
+
sql.should be_like(%Q{
|
122
|
+
SELECT `users`.`id`, `users`.`name`, `photos_external`.`user_id`, `photos_external`.`cnt`
|
123
|
+
FROM `users`
|
124
|
+
INNER JOIN (SELECT `photos`.`user_id`, COUNT(`photos`.`id`) AS `cnt` FROM `photos` WHERE `photos`.`user_id` = 1 GROUP BY `photos`.`user_id`) AS `photos_external`
|
125
|
+
ON `users`.`id` = `photos_external`.`user_id`
|
126
|
+
})
|
127
|
+
end
|
128
|
+
|
129
|
+
adapter_is_not :mysql do
|
130
|
+
sql.should be_like(%Q{
|
131
|
+
SELECT "users"."id", "users"."name", "photos_external"."user_id", "photos_external"."cnt"
|
132
|
+
FROM "users"
|
133
|
+
INNER JOIN (SELECT "photos"."user_id", COUNT("photos"."id") AS "cnt" FROM "photos" WHERE "photos"."user_id" = 1 GROUP BY "photos"."user_id") AS "photos_external"
|
134
|
+
ON "users"."id" = "photos_external"."user_id"
|
135
|
+
})
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
describe 'with the aggregation on the right' do
|
141
|
+
it "manufactures sql keeping wheres on the aggregation within the derived table" do
|
142
|
+
sql = @aggregation.where(@aggregation[:user_id].eq(1)).join(@relation1).on(@predicate).to_sql
|
143
|
+
|
144
|
+
adapter_is :mysql do
|
145
|
+
sql.should be_like(%Q{
|
146
|
+
SELECT `photos_external`.`user_id`, `photos_external`.`cnt`, `users`.`id`, `users`.`name`
|
147
|
+
FROM (SELECT `photos`.`user_id`, COUNT(`photos`.`id`) AS `cnt` FROM `photos` WHERE `photos`.`user_id` = 1 GROUP BY `photos`.`user_id`) AS `photos_external`
|
148
|
+
INNER JOIN `users`
|
149
|
+
ON `users`.`id` = `photos_external`.`user_id`
|
150
|
+
})
|
151
|
+
end
|
152
|
+
|
153
|
+
adapter_is_not :mysql do
|
154
|
+
sql.should be_like(%Q{
|
155
|
+
SELECT "photos_external"."user_id", "photos_external"."cnt", "users"."id", "users"."name"
|
156
|
+
FROM (SELECT "photos"."user_id", COUNT("photos"."id") AS "cnt" FROM "photos" WHERE "photos"."user_id" = 1 GROUP BY "photos"."user_id") AS "photos_external"
|
157
|
+
INNER JOIN "users"
|
158
|
+
ON "users"."id" = "photos_external"."user_id"
|
159
|
+
})
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
|
2
|
+
|
3
|
+
module Arel
|
4
|
+
describe Join do
|
5
|
+
before do
|
6
|
+
@relation1 = Table(:users)
|
7
|
+
@relation2 = Table(:photos)
|
8
|
+
@predicate = @relation1[:id].eq(@relation2[:user_id])
|
9
|
+
end
|
10
|
+
|
11
|
+
describe '#to_sql' do
|
12
|
+
describe 'when the join contains a where' do
|
13
|
+
describe 'and the where is given a string' do
|
14
|
+
it 'does not escape the string' do
|
15
|
+
sql = @relation1 \
|
16
|
+
.join(@relation2.where("asdf")) \
|
17
|
+
.on(@predicate) \
|
18
|
+
.to_sql
|
19
|
+
|
20
|
+
adapter_is :mysql do
|
21
|
+
sql.should be_like(%Q{
|
22
|
+
SELECT `users`.`id`, `users`.`name`, `photos`.`id`, `photos`.`user_id`, `photos`.`camera_id`
|
23
|
+
FROM `users`
|
24
|
+
INNER JOIN `photos`
|
25
|
+
ON `users`.`id` = `photos`.`user_id` AND asdf
|
26
|
+
})
|
27
|
+
end
|
28
|
+
|
29
|
+
adapter_is_not :mysql do
|
30
|
+
sql.should be_like(%Q{
|
31
|
+
SELECT "users"."id", "users"."name", "photos"."id", "photos"."user_id", "photos"."camera_id"
|
32
|
+
FROM "users"
|
33
|
+
INNER JOIN "photos"
|
34
|
+
ON "users"."id" = "photos"."user_id" AND asdf
|
35
|
+
})
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe 'when a compound contains a join' do
|
42
|
+
describe 'and the compound is a where' do
|
43
|
+
it 'manufactures sql disambiguating the tables' do
|
44
|
+
sql = @relation1 \
|
45
|
+
.where(@relation1[:id].eq(1)) \
|
46
|
+
.join(@relation2) \
|
47
|
+
.on(@predicate) \
|
48
|
+
.where(@relation1[:id].eq(1)) \
|
49
|
+
.to_sql
|
50
|
+
|
51
|
+
adapter_is :mysql do
|
52
|
+
sql.should be_like(%Q{
|
53
|
+
SELECT `users`.`id`, `users`.`name`, `photos`.`id`, `photos`.`user_id`, `photos`.`camera_id`
|
54
|
+
FROM `users`
|
55
|
+
INNER JOIN `photos`
|
56
|
+
ON `users`.`id` = `photos`.`user_id`
|
57
|
+
WHERE `users`.`id` = 1
|
58
|
+
AND `users`.`id` = 1
|
59
|
+
})
|
60
|
+
end
|
61
|
+
|
62
|
+
adapter_is_not :mysql do
|
63
|
+
sql.should be_like(%Q{
|
64
|
+
SELECT "users"."id", "users"."name", "photos"."id", "photos"."user_id", "photos"."camera_id"
|
65
|
+
FROM "users"
|
66
|
+
INNER JOIN "photos"
|
67
|
+
ON "users"."id" = "photos"."user_id"
|
68
|
+
WHERE "users"."id" = 1
|
69
|
+
AND "users"."id" = 1
|
70
|
+
})
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe 'and the compound is a group' do
|
76
|
+
it 'manufactures sql disambiguating the tables' do
|
77
|
+
sql = @relation1 \
|
78
|
+
.join(@relation2) \
|
79
|
+
.on(@predicate) \
|
80
|
+
.group(@relation1[:id]) \
|
81
|
+
.to_sql
|
82
|
+
|
83
|
+
adapter_is :mysql do
|
84
|
+
sql.should be_like(%Q{
|
85
|
+
SELECT `users`.`id`, `users`.`name`, `photos`.`id`, `photos`.`user_id`, `photos`.`camera_id`
|
86
|
+
FROM `users`
|
87
|
+
INNER JOIN `photos`
|
88
|
+
ON `users`.`id` = `photos`.`user_id`
|
89
|
+
GROUP BY `users`.`id`
|
90
|
+
})
|
91
|
+
end
|
92
|
+
|
93
|
+
adapter_is_not :mysql do
|
94
|
+
sql.should be_like(%Q{
|
95
|
+
SELECT "users"."id", "users"."name", "photos"."id", "photos"."user_id", "photos"."camera_id"
|
96
|
+
FROM "users"
|
97
|
+
INNER JOIN "photos"
|
98
|
+
ON "users"."id" = "photos"."user_id"
|
99
|
+
GROUP BY "users"."id"
|
100
|
+
})
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|