arel-compat 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (164) hide show
  1. data/History.txt +25 -0
  2. data/README.markdown +182 -0
  3. data/lib/arel.rb +13 -0
  4. data/lib/arel/algebra.rb +10 -0
  5. data/lib/arel/algebra/attributes.rb +7 -0
  6. data/lib/arel/algebra/attributes/attribute.rb +270 -0
  7. data/lib/arel/algebra/attributes/boolean.rb +21 -0
  8. data/lib/arel/algebra/attributes/decimal.rb +9 -0
  9. data/lib/arel/algebra/attributes/float.rb +9 -0
  10. data/lib/arel/algebra/attributes/integer.rb +10 -0
  11. data/lib/arel/algebra/attributes/string.rb +10 -0
  12. data/lib/arel/algebra/attributes/time.rb +6 -0
  13. data/lib/arel/algebra/core_extensions.rb +4 -0
  14. data/lib/arel/algebra/core_extensions/class.rb +32 -0
  15. data/lib/arel/algebra/core_extensions/hash.rb +11 -0
  16. data/lib/arel/algebra/core_extensions/object.rb +30 -0
  17. data/lib/arel/algebra/core_extensions/symbol.rb +9 -0
  18. data/lib/arel/algebra/expression.rb +43 -0
  19. data/lib/arel/algebra/header.rb +67 -0
  20. data/lib/arel/algebra/ordering.rb +23 -0
  21. data/lib/arel/algebra/predicates.rb +190 -0
  22. data/lib/arel/algebra/relations.rb +17 -0
  23. data/lib/arel/algebra/relations/operations/alias.rb +7 -0
  24. data/lib/arel/algebra/relations/operations/from.rb +6 -0
  25. data/lib/arel/algebra/relations/operations/group.rb +12 -0
  26. data/lib/arel/algebra/relations/operations/having.rb +17 -0
  27. data/lib/arel/algebra/relations/operations/join.rb +69 -0
  28. data/lib/arel/algebra/relations/operations/lock.rb +12 -0
  29. data/lib/arel/algebra/relations/operations/order.rb +19 -0
  30. data/lib/arel/algebra/relations/operations/project.rb +20 -0
  31. data/lib/arel/algebra/relations/operations/skip.rb +7 -0
  32. data/lib/arel/algebra/relations/operations/take.rb +11 -0
  33. data/lib/arel/algebra/relations/operations/where.rb +17 -0
  34. data/lib/arel/algebra/relations/relation.rb +136 -0
  35. data/lib/arel/algebra/relations/row.rb +26 -0
  36. data/lib/arel/algebra/relations/utilities/compound.rb +54 -0
  37. data/lib/arel/algebra/relations/utilities/externalization.rb +24 -0
  38. data/lib/arel/algebra/relations/utilities/nil.rb +7 -0
  39. data/lib/arel/algebra/relations/writes.rb +36 -0
  40. data/lib/arel/algebra/value.rb +14 -0
  41. data/lib/arel/engines.rb +2 -0
  42. data/lib/arel/engines/memory.rb +4 -0
  43. data/lib/arel/engines/memory/engine.rb +16 -0
  44. data/lib/arel/engines/memory/predicates.rb +99 -0
  45. data/lib/arel/engines/memory/primitives.rb +27 -0
  46. data/lib/arel/engines/memory/relations.rb +5 -0
  47. data/lib/arel/engines/memory/relations/array.rb +35 -0
  48. data/lib/arel/engines/memory/relations/compound.rb +9 -0
  49. data/lib/arel/engines/memory/relations/operations.rb +67 -0
  50. data/lib/arel/engines/memory/relations/writes.rb +7 -0
  51. data/lib/arel/engines/sql.rb +8 -0
  52. data/lib/arel/engines/sql/attributes.rb +40 -0
  53. data/lib/arel/engines/sql/christener.rb +14 -0
  54. data/lib/arel/engines/sql/compilers/ibm_db_compiler.rb +48 -0
  55. data/lib/arel/engines/sql/compilers/mysql_compiler.rb +11 -0
  56. data/lib/arel/engines/sql/compilers/oracle_compiler.rb +95 -0
  57. data/lib/arel/engines/sql/compilers/postgresql_compiler.rb +42 -0
  58. data/lib/arel/engines/sql/compilers/sqlite_compiler.rb +9 -0
  59. data/lib/arel/engines/sql/core_extensions.rb +4 -0
  60. data/lib/arel/engines/sql/core_extensions/array.rb +24 -0
  61. data/lib/arel/engines/sql/core_extensions/nil_class.rb +15 -0
  62. data/lib/arel/engines/sql/core_extensions/object.rb +19 -0
  63. data/lib/arel/engines/sql/core_extensions/range.rb +19 -0
  64. data/lib/arel/engines/sql/engine.rb +55 -0
  65. data/lib/arel/engines/sql/formatters.rb +122 -0
  66. data/lib/arel/engines/sql/predicates.rb +103 -0
  67. data/lib/arel/engines/sql/primitives.rb +97 -0
  68. data/lib/arel/engines/sql/relations.rb +10 -0
  69. data/lib/arel/engines/sql/relations/compiler.rb +118 -0
  70. data/lib/arel/engines/sql/relations/operations/alias.rb +5 -0
  71. data/lib/arel/engines/sql/relations/operations/join.rb +33 -0
  72. data/lib/arel/engines/sql/relations/relation.rb +65 -0
  73. data/lib/arel/engines/sql/relations/table.rb +88 -0
  74. data/lib/arel/engines/sql/relations/utilities/compound.rb +10 -0
  75. data/lib/arel/engines/sql/relations/utilities/externalization.rb +14 -0
  76. data/lib/arel/engines/sql/relations/utilities/nil.rb +6 -0
  77. data/lib/arel/engines/sql/relations/utilities/recursion.rb +13 -0
  78. data/lib/arel/engines/sql/relations/writes.rb +19 -0
  79. data/lib/arel/session.rb +51 -0
  80. data/lib/arel/version.rb +3 -0
  81. data/spec/algebra/unit/predicates/binary_spec.rb +35 -0
  82. data/spec/algebra/unit/predicates/equality_spec.rb +29 -0
  83. data/spec/algebra/unit/predicates/in_spec.rb +12 -0
  84. data/spec/algebra/unit/primitives/attribute_spec.rb +181 -0
  85. data/spec/algebra/unit/primitives/expression_spec.rb +45 -0
  86. data/spec/algebra/unit/primitives/value_spec.rb +15 -0
  87. data/spec/algebra/unit/relations/alias_spec.rb +16 -0
  88. data/spec/algebra/unit/relations/delete_spec.rb +9 -0
  89. data/spec/algebra/unit/relations/group_spec.rb +10 -0
  90. data/spec/algebra/unit/relations/insert_spec.rb +9 -0
  91. data/spec/algebra/unit/relations/join_spec.rb +25 -0
  92. data/spec/algebra/unit/relations/order_spec.rb +21 -0
  93. data/spec/algebra/unit/relations/project_spec.rb +34 -0
  94. data/spec/algebra/unit/relations/relation_spec.rb +187 -0
  95. data/spec/algebra/unit/relations/skip_spec.rb +10 -0
  96. data/spec/algebra/unit/relations/table_spec.rb +38 -0
  97. data/spec/algebra/unit/relations/take_spec.rb +10 -0
  98. data/spec/algebra/unit/relations/update_spec.rb +9 -0
  99. data/spec/algebra/unit/relations/where_spec.rb +19 -0
  100. data/spec/algebra/unit/session/session_spec.rb +84 -0
  101. data/spec/attributes/boolean_spec.rb +57 -0
  102. data/spec/attributes/float_spec.rb +119 -0
  103. data/spec/attributes/header_spec.rb +42 -0
  104. data/spec/attributes/integer_spec.rb +119 -0
  105. data/spec/attributes/string_spec.rb +43 -0
  106. data/spec/attributes/time_spec.rb +24 -0
  107. data/spec/engines/memory/integration/joins/cross_engine_spec.rb +51 -0
  108. data/spec/engines/memory/unit/relations/array_spec.rb +32 -0
  109. data/spec/engines/memory/unit/relations/insert_spec.rb +28 -0
  110. data/spec/engines/memory/unit/relations/join_spec.rb +31 -0
  111. data/spec/engines/memory/unit/relations/order_spec.rb +27 -0
  112. data/spec/engines/memory/unit/relations/project_spec.rb +27 -0
  113. data/spec/engines/memory/unit/relations/skip_spec.rb +26 -0
  114. data/spec/engines/memory/unit/relations/take_spec.rb +26 -0
  115. data/spec/engines/memory/unit/relations/where_spec.rb +39 -0
  116. data/spec/engines/sql/integration/joins/with_adjacency_spec.rb +258 -0
  117. data/spec/engines/sql/integration/joins/with_aggregations_spec.rb +221 -0
  118. data/spec/engines/sql/integration/joins/with_compounds_spec.rb +137 -0
  119. data/spec/engines/sql/unit/engine_spec.rb +45 -0
  120. data/spec/engines/sql/unit/predicates/binary_spec.rb +140 -0
  121. data/spec/engines/sql/unit/predicates/equality_spec.rb +75 -0
  122. data/spec/engines/sql/unit/predicates/in_spec.rb +179 -0
  123. data/spec/engines/sql/unit/predicates/noteq_spec.rb +75 -0
  124. data/spec/engines/sql/unit/predicates/predicates_spec.rb +79 -0
  125. data/spec/engines/sql/unit/primitives/attribute_spec.rb +36 -0
  126. data/spec/engines/sql/unit/primitives/expression_spec.rb +28 -0
  127. data/spec/engines/sql/unit/primitives/literal_spec.rb +43 -0
  128. data/spec/engines/sql/unit/primitives/value_spec.rb +29 -0
  129. data/spec/engines/sql/unit/relations/alias_spec.rb +53 -0
  130. data/spec/engines/sql/unit/relations/delete_spec.rb +83 -0
  131. data/spec/engines/sql/unit/relations/from_spec.rb +64 -0
  132. data/spec/engines/sql/unit/relations/group_spec.rb +72 -0
  133. data/spec/engines/sql/unit/relations/having_spec.rb +78 -0
  134. data/spec/engines/sql/unit/relations/insert_spec.rb +143 -0
  135. data/spec/engines/sql/unit/relations/join_spec.rb +180 -0
  136. data/spec/engines/sql/unit/relations/lock_spec.rb +86 -0
  137. data/spec/engines/sql/unit/relations/order_spec.rb +161 -0
  138. data/spec/engines/sql/unit/relations/project_spec.rb +143 -0
  139. data/spec/engines/sql/unit/relations/skip_spec.rb +41 -0
  140. data/spec/engines/sql/unit/relations/table_spec.rb +129 -0
  141. data/spec/engines/sql/unit/relations/take_spec.rb +49 -0
  142. data/spec/engines/sql/unit/relations/update_spec.rb +203 -0
  143. data/spec/engines/sql/unit/relations/where_spec.rb +72 -0
  144. data/spec/relations/join_spec.rb +42 -0
  145. data/spec/relations/relation_spec.rb +31 -0
  146. data/spec/shared/relation_spec.rb +255 -0
  147. data/spec/spec_helper.rb +36 -0
  148. data/spec/support/check.rb +6 -0
  149. data/spec/support/connections/mysql_connection.rb +14 -0
  150. data/spec/support/connections/oracle_connection.rb +17 -0
  151. data/spec/support/connections/postgresql_connection.rb +13 -0
  152. data/spec/support/connections/sqlite3_connection.rb +24 -0
  153. data/spec/support/guards.rb +28 -0
  154. data/spec/support/matchers.rb +4 -0
  155. data/spec/support/matchers/be_like.rb +24 -0
  156. data/spec/support/matchers/disambiguate_attributes.rb +28 -0
  157. data/spec/support/matchers/hash_the_same_as.rb +26 -0
  158. data/spec/support/matchers/have_rows.rb +18 -0
  159. data/spec/support/model.rb +62 -0
  160. data/spec/support/schemas/mysql_schema.rb +26 -0
  161. data/spec/support/schemas/oracle_schema.rb +20 -0
  162. data/spec/support/schemas/postgresql_schema.rb +26 -0
  163. data/spec/support/schemas/sqlite3_schema.rb +26 -0
  164. metadata +258 -0
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ module Arel
4
+ describe Array do
5
+ before do
6
+ @relation = Array.new([
7
+ [1, 'duck' ],
8
+ [2, 'duck' ],
9
+ [3, 'goose']
10
+ ], [[:id, Attributes::Integer], [:name, Attributes::String]])
11
+ end
12
+
13
+ describe '#attributes' do
14
+ it 'manufactures attributes corresponding to the names given on construction' do
15
+ @relation.attributes.should == [
16
+ Attribute.new(@relation, :id),
17
+ Attribute.new(@relation, :name)
18
+ ]
19
+ end
20
+ end
21
+
22
+ describe '#call' do
23
+ it "manufactures an array of hashes of attributes to values" do
24
+ @relation.call.should == [
25
+ Row.new(@relation, [1, 'duck']),
26
+ Row.new(@relation, [2, 'duck']),
27
+ Row.new(@relation, [3, 'goose'])
28
+ ]
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ module Arel
4
+ describe Insert do
5
+ before do
6
+ @relation = Array.new([
7
+ [1, 'duck' ],
8
+ [2, 'duck' ],
9
+ [3, 'goose']
10
+ ], [[:id, Attributes::Integer], [:name, Attributes::String]])
11
+ end
12
+
13
+ describe '#call' do
14
+ it "manufactures an array of hashes of attributes to values" do
15
+ @relation \
16
+ .insert(@relation[:id] => 4, @relation[:name] => 'guinea fowl') \
17
+ do |relation|
18
+ relation.should == [
19
+ Row.new(relation, [1, 'duck']),
20
+ Row.new(relation, [2, 'duck']),
21
+ Row.new(relation, [3, 'goose']),
22
+ Row.new(relation, [4, 'guinea fowl'])
23
+ ]
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+ module Arel
4
+ describe Join do
5
+ before do
6
+ @relation1 = Array.new([
7
+ [1, 'duck' ],
8
+ [2, 'duck' ],
9
+ [3, 'goose']
10
+ ], [[:id, Attributes::Integer], [:name, Attributes::String]])
11
+ @relation2 = @relation1.alias
12
+ end
13
+
14
+ describe InnerJoin do
15
+ describe '#call' do
16
+ it 'combines the two tables where the predicate obtains' do
17
+ @relation1 \
18
+ .join(@relation2) \
19
+ .on(@relation1[:id].eq(@relation2[:id])) \
20
+ .let do |relation|
21
+ relation.call.should == [
22
+ Row.new(relation, [1, 'duck', 1, 'duck' ]),
23
+ Row.new(relation, [2, 'duck', 2, 'duck' ]),
24
+ Row.new(relation, [3, 'goose', 3, 'goose'])
25
+ ]
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ module Arel
4
+ describe Order do
5
+ before do
6
+ @relation = Array.new([
7
+ [1, 'duck' ],
8
+ [2, 'duck' ],
9
+ [3, 'goose']
10
+ ], [[:id, Attributes::Integer], [:name, Attributes::String]])
11
+ end
12
+
13
+ describe '#call' do
14
+ it 'sorts the relation with the provided ordering' do
15
+ @relation \
16
+ .order(@relation[:id].desc) \
17
+ .let do |relation|
18
+ relation.call.should == [
19
+ Row.new(relation, [3, 'goose']),
20
+ Row.new(relation, [2, 'duck' ]),
21
+ Row.new(relation, [1, 'duck' ])
22
+ ]
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ module Arel
4
+ describe Project do
5
+ before do
6
+ @relation = Array.new([
7
+ [1, 'duck' ],
8
+ [2, 'duck' ],
9
+ [3, 'goose']
10
+ ], [[:id, Attributes::Integer], [:name, Attributes::String]])
11
+ end
12
+
13
+ describe '#call' do
14
+ it 'retains only the attributes that are provided' do
15
+ @relation \
16
+ .project(@relation[:id]) \
17
+ .let do |relation|
18
+ relation.call.should == [
19
+ Row.new(relation, [1]),
20
+ Row.new(relation, [2]),
21
+ Row.new(relation, [3])
22
+ ]
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ module Arel
4
+ describe Skip do
5
+ before do
6
+ @relation = Array.new([
7
+ [1, 'duck' ],
8
+ [2, 'duck' ],
9
+ [3, 'goose']
10
+ ], [[:id, Attributes::Integer], [:name, Attributes::String]])
11
+ end
12
+
13
+ describe '#call' do
14
+ it 'removes the first n rows' do
15
+ @relation \
16
+ .skip(1) \
17
+ .let do |relation|
18
+ relation.call.should == [
19
+ Row.new(relation, [2, 'duck']),
20
+ Row.new(relation, [3, 'goose']),
21
+ ]
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ module Arel
4
+ describe Take do
5
+ before do
6
+ @relation = Array.new([
7
+ [1, 'duck' ],
8
+ [2, 'duck' ],
9
+ [3, 'goose']
10
+ ], [[:id, Attributes::Integer], [:name, Attributes::String]])
11
+ end
12
+
13
+ describe '#call' do
14
+ it 'removes the rows after the first n' do
15
+ @relation \
16
+ .take(2) \
17
+ .let do |relation|
18
+ relation.call.should == [
19
+ Row.new(relation, [1, 'duck']),
20
+ Row.new(relation, [2, 'duck']),
21
+ ]
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ module Arel
4
+ describe Where do
5
+ before do
6
+ @relation = Array.new([
7
+ [1, 'duck' ],
8
+ [2, 'duck' ],
9
+ [3, 'goose']
10
+ ], [[:id, Attributes::Integer], [:name, Attributes::String]])
11
+ end
12
+
13
+ describe '#call' do
14
+ it 'filters the relation with the provided predicate' do
15
+ @relation \
16
+ .where(@relation[:id].lt(3)) \
17
+ .let do |relation|
18
+ relation.call.should == [
19
+ Row.new(relation, [1, 'duck']),
20
+ Row.new(relation, [2, 'duck']),
21
+ ]
22
+ end
23
+ end
24
+
25
+ describe 'when filtering a where relation' do
26
+ it 'further filters the already-filtered relation with the provided predicate' do
27
+ @relation \
28
+ .where(@relation[:id].gt(1)) \
29
+ .where(@relation[:id].lt(3)) \
30
+ .let do |relation|
31
+ relation.call.should == [
32
+ Row.new(relation, [2, 'duck'])
33
+ ]
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,258 @@
1
+ require '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` `users_2`
21
+ ON `users`.`id` = `users_2`.`id`
22
+ })
23
+ end
24
+
25
+ adapter_is :oracle 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" "USERS_2"
30
+ ON "USERS"."ID" = "USERS_2"."ID"
31
+ })
32
+ end
33
+
34
+ adapter_is_not :mysql, :oracle do
35
+ sql.should be_like(%Q{
36
+ SELECT "users"."id", "users"."name", "users_2"."id", "users_2"."name"
37
+ FROM "users"
38
+ INNER JOIN "users" "users_2"
39
+ ON "users"."id" = "users_2"."id"
40
+ })
41
+ end
42
+ end
43
+
44
+ describe 'when joining with a where on the same relation' do
45
+ it 'manufactures sql aliasing the tables properly' do
46
+ sql = @relation1 \
47
+ .join(@relation2.where(@relation2[:id].eq(1))) \
48
+ .on(@predicate) \
49
+ .to_sql
50
+
51
+ adapter_is :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` `users_2`
56
+ ON `users`.`id` = `users_2`.`id` AND `users_2`.`id` = 1
57
+ })
58
+ end
59
+
60
+ adapter_is :oracle do
61
+ sql.should be_like(%Q{
62
+ SELECT "USERS"."ID", "USERS"."NAME", "USERS_2"."ID", "USERS_2"."NAME"
63
+ FROM "USERS"
64
+ INNER JOIN "USERS" "USERS_2"
65
+ ON "USERS"."ID" = "USERS_2"."ID" AND "USERS_2"."ID" = 1
66
+ })
67
+ end
68
+
69
+ adapter_is_not :mysql, :oracle do
70
+ sql.should be_like(%Q{
71
+ SELECT "users"."id", "users"."name", "users_2"."id", "users_2"."name"
72
+ FROM "users"
73
+ INNER JOIN "users" "users_2"
74
+ ON "users"."id" = "users_2"."id" AND "users_2"."id" = 1
75
+ })
76
+ end
77
+ end
78
+
79
+ describe 'when the where occurs before the alias' do
80
+ it 'manufactures sql aliasing the predicates properly' do
81
+ relation2 = @relation1.where(@relation1[:id].eq(1)).alias
82
+
83
+ sql = @relation1 \
84
+ .join(relation2) \
85
+ .on(relation2[:id].eq(@relation1[:id])) \
86
+ .to_sql
87
+
88
+ adapter_is :mysql do
89
+ sql.should be_like(%Q{
90
+ SELECT `users`.`id`, `users`.`name`, `users_2`.`id`, `users_2`.`name`
91
+ FROM `users`
92
+ INNER JOIN `users` `users_2`
93
+ ON `users_2`.`id` = `users`.`id` AND `users_2`.`id` = 1
94
+ })
95
+ end
96
+
97
+ adapter_is :oracle do
98
+ sql.should be_like(%Q{
99
+ SELECT "USERS"."ID", "USERS"."NAME", "USERS_2"."ID", "USERS_2"."NAME"
100
+ FROM "USERS"
101
+ INNER JOIN "USERS" "USERS_2"
102
+ ON "USERS_2"."ID" = "USERS"."ID" AND "USERS_2"."ID" = 1
103
+ })
104
+ end
105
+
106
+ adapter_is_not :mysql, :oracle do
107
+ sql.should be_like(%Q{
108
+ SELECT "users"."id", "users"."name", "users_2"."id", "users_2"."name"
109
+ FROM "users"
110
+ INNER JOIN "users" "users_2"
111
+ ON "users_2"."id" = "users"."id" AND "users_2"."id" = 1
112
+ })
113
+ end
114
+ end
115
+ end
116
+ end
117
+
118
+ describe 'when joining the relation to itself multiple times' do
119
+ before do
120
+ @relation3 = @relation1.alias
121
+ end
122
+
123
+ describe 'when joining left-associatively' do
124
+ it 'manufactures sql aliasing the tables properly' do
125
+ sql = @relation1 \
126
+ .join(@relation2 \
127
+ .join(@relation3) \
128
+ .on(@relation2[:id].eq(@relation3[:id]))) \
129
+ .on(@relation1[:id].eq(@relation2[:id])) \
130
+ .to_sql
131
+
132
+ adapter_is :mysql do
133
+ sql.should be_like(%Q{
134
+ SELECT `users`.`id`, `users`.`name`, `users_2`.`id`, `users_2`.`name`, `users_3`.`id`, `users_3`.`name`
135
+ FROM `users`
136
+ INNER JOIN `users` `users_2`
137
+ ON `users`.`id` = `users_2`.`id`
138
+ INNER JOIN `users` `users_3`
139
+ ON `users_2`.`id` = `users_3`.`id`
140
+ })
141
+ end
142
+
143
+ adapter_is :oracle do
144
+ sql.should be_like(%Q{
145
+ SELECT "USERS"."ID", "USERS"."NAME", "USERS_2"."ID", "USERS_2"."NAME", "USERS_3"."ID", "USERS_3"."NAME"
146
+ FROM "USERS"
147
+ INNER JOIN "USERS" "USERS_2"
148
+ ON "USERS"."ID" = "USERS_2"."ID"
149
+ INNER JOIN "USERS" "USERS_3"
150
+ ON "USERS_2"."ID" = "USERS_3"."ID"
151
+ })
152
+ end
153
+
154
+ adapter_is_not :mysql, :oracle do
155
+ sql.should be_like(%Q{
156
+ SELECT "users"."id", "users"."name", "users_2"."id", "users_2"."name", "users_3"."id", "users_3"."name"
157
+ FROM "users"
158
+ INNER JOIN "users" "users_2"
159
+ ON "users"."id" = "users_2"."id"
160
+ INNER JOIN "users" "users_3"
161
+ ON "users_2"."id" = "users_3"."id"
162
+ })
163
+ end
164
+ end
165
+ end
166
+
167
+ describe 'when joining right-associatively' do
168
+ it 'manufactures sql aliasing the tables properly' do
169
+ sql = @relation1 \
170
+ .join(@relation2).on(@relation1[:id].eq(@relation2[:id])) \
171
+ .join(@relation3).on(@relation2[:id].eq(@relation3[:id])) \
172
+ .to_sql
173
+
174
+ adapter_is :mysql do
175
+ sql.should be_like(%Q{
176
+ SELECT `users`.`id`, `users`.`name`, `users_2`.`id`, `users_2`.`name`, `users_3`.`id`, `users_3`.`name`
177
+ FROM `users`
178
+ INNER JOIN `users` `users_2`
179
+ ON `users`.`id` = `users_2`.`id`
180
+ INNER JOIN `users` `users_3`
181
+ ON `users_2`.`id` = `users_3`.`id`
182
+ })
183
+ end
184
+
185
+ adapter_is :oracle do
186
+ sql.should be_like(%Q{
187
+ SELECT "USERS"."ID", "USERS"."NAME", "USERS_2"."ID", "USERS_2"."NAME", "USERS_3"."ID", "USERS_3"."NAME"
188
+ FROM "USERS"
189
+ INNER JOIN "USERS" "USERS_2"
190
+ ON "USERS"."ID" = "USERS_2"."ID"
191
+ INNER JOIN "USERS" "USERS_3"
192
+ ON "USERS_2"."ID" = "USERS_3"."ID"
193
+ })
194
+ end
195
+
196
+ adapter_is_not :mysql, :oracle do
197
+ sql.should be_like(%Q{
198
+ SELECT "users"."id", "users"."name", "users_2"."id", "users_2"."name", "users_3"."id", "users_3"."name"
199
+ FROM "users"
200
+ INNER JOIN "users" "users_2"
201
+ ON "users"."id" = "users_2"."id"
202
+ INNER JOIN "users" "users_3"
203
+ ON "users_2"."id" = "users_3"."id"
204
+ })
205
+ end
206
+ end
207
+ end
208
+ end
209
+ end
210
+
211
+ describe '[]' do
212
+ describe 'when given an attribute belonging to both sub-relations' do
213
+ it 'disambiguates the relation that serves as the ancestor to the attribute' do
214
+ @relation1 \
215
+ .join(@relation2) \
216
+ .on(@predicate) \
217
+ .should disambiguate_attributes(@relation1[:id], @relation2[:id])
218
+ end
219
+
220
+ describe 'when both relations are compound and only one is an alias' do
221
+ it 'disambiguates the relation that serves as the ancestor to the attribute' do
222
+ compound1 = @relation1.where(@predicate)
223
+ compound2 = compound1.alias
224
+ compound1 \
225
+ .join(compound2) \
226
+ .on(@predicate) \
227
+ .should disambiguate_attributes(compound1[:id], compound2[:id])
228
+ end
229
+ end
230
+
231
+ describe 'when the left relation is extremely compound' do
232
+ it 'disambiguates the relation that serves as the ancestor to the attribute' do
233
+ @relation1 \
234
+ .where(@predicate) \
235
+ .where(@predicate) \
236
+ .join(@relation2) \
237
+ .on(@predicate) \
238
+ .should disambiguate_attributes(@relation1[:id], @relation2[:id])
239
+ end
240
+ end
241
+
242
+ describe 'when the right relation is extremely compound' do
243
+ it 'disambiguates the relation that serves as the ancestor to the attribute' do
244
+ @relation1 \
245
+ .join( \
246
+ @relation2 \
247
+ .where(@predicate) \
248
+ .where(@predicate) \
249
+ .where(@predicate)) \
250
+ .on(@predicate) \
251
+ .should disambiguate_attributes(@relation1[:id], @relation2[:id])
252
+ end
253
+ end
254
+ end
255
+ end
256
+ end
257
+ end
258
+ end