composite_primary_keys 14.0.6 → 14.0.7
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.
- checksums.yaml +4 -4
- data/History.rdoc +6 -0
- data/Rakefile +1 -1
- data/lib/composite_primary_keys/associations/association.rb +2 -2
- data/lib/composite_primary_keys/associations/association_scope.rb +1 -1
- data/lib/composite_primary_keys/associations/has_many_through_association.rb +19 -0
- data/lib/composite_primary_keys/connection_adapters/abstract/database_statements.rb +1 -2
- data/lib/composite_primary_keys/relation/query_methods.rb +14 -16
- data/lib/composite_primary_keys/relation.rb +199 -197
- data/lib/composite_primary_keys/version.rb +1 -1
- data/lib/composite_primary_keys.rb +117 -119
- data/scripts/console.rb +2 -2
- data/tasks/databases/trilogy.rake +23 -0
- data/test/abstract_unit.rb +124 -118
- data/test/connections/databases.ci.yml +10 -0
- data/test/fixtures/admin.rb +4 -0
- data/test/fixtures/comments.yml +6 -0
- data/test/fixtures/db_definitions/db2-create-tables.sql +34 -0
- data/test/fixtures/db_definitions/db2-drop-tables.sql +7 -1
- data/test/fixtures/db_definitions/mysql.sql +23 -0
- data/test/fixtures/db_definitions/oracle.drop.sql +4 -0
- data/test/fixtures/db_definitions/oracle.sql +21 -0
- data/test/fixtures/db_definitions/postgresql.sql +23 -0
- data/test/fixtures/db_definitions/sqlite.sql +21 -0
- data/test/fixtures/db_definitions/sqlserver.sql +23 -0
- data/test/fixtures/moderator.rb +4 -0
- data/test/fixtures/room.rb +4 -1
- data/test/fixtures/staff_room.rb +6 -0
- data/test/fixtures/staff_room_key.rb +6 -0
- data/test/fixtures/user.rb +3 -0
- data/test/fixtures/user_with_polymorphic_name.rb +9 -0
- data/test/test_associations.rb +403 -403
- data/test/test_has_one_through.rb +30 -0
- data/test/test_polymorphic.rb +6 -0
- metadata +11 -4
- data/lib/composite_primary_keys/associations/through_association.rb +0 -24
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: de97dfff0f237f22dd32a32189824739087b30c0ea0e14cdd996bd8b69359caf
|
4
|
+
data.tar.gz: 722a9e0d02b6fa8ee2010d47e5a37705a43b302df6abf7c7a6d199b0a84b0201
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e57b5330dc2b0cdb7374f14ed6c7efed22c269cf42298527efc1ec26ee2e2ea8ab9edd97e97a7f4c656662e54a1faa5da28fef365c602060878d375e4caa646a
|
7
|
+
data.tar.gz: c2981385774399cdd3e64385d9f7595dd2a3972706b04e825b604f83ed4fe59438df2f114f196ff0fb6ceb389060554259cab7132c2a75073a382101da533bd0
|
data/History.rdoc
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
== 14.0.7 (2023-11-04)
|
2
|
+
* Add support for Trilogy Adapter (Zack Mariscal)
|
3
|
+
* Add Dockerfile and Docker compose support (Zack Mariscal)
|
4
|
+
* Support polymorphic_name (Vladimir Kochnev)
|
5
|
+
* Fix HasOneThrough association (kyori19)
|
6
|
+
|
1
7
|
== 14.0.6 (2023-02-04)
|
2
8
|
* Port fix for #573 (Charlie Savage)
|
3
9
|
* Port fix for fix #577 (Charlie Savage)
|
data/Rakefile
CHANGED
@@ -23,7 +23,7 @@ Dir.glob('tasks/**/*.rake').each do |rake_file|
|
|
23
23
|
end
|
24
24
|
|
25
25
|
# Set up test tasks for each supported connection adapter
|
26
|
-
%w(mysql sqlite oracle oracle_enhanced postgresql ibm_db sqlserver).each do |adapter|
|
26
|
+
%w(mysql sqlite oracle oracle_enhanced postgresql ibm_db sqlserver trilogy).each do |adapter|
|
27
27
|
namespace adapter do
|
28
28
|
desc "Run tests using the #{adapter} adapter"
|
29
29
|
task "test" do
|
@@ -23,6 +23,25 @@ module ActiveRecord
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
end
|
26
|
+
|
27
|
+
alias :original_construct_join_attributes :construct_join_attributes
|
28
|
+
|
29
|
+
def construct_join_attributes(*records)
|
30
|
+
# CPK
|
31
|
+
if !self.source_reflection.polymorphic? && source_reflection.klass.composite?
|
32
|
+
ensure_mutable
|
33
|
+
|
34
|
+
ids = records.map do |record|
|
35
|
+
source_reflection.association_primary_key(reflection.klass).map do |key|
|
36
|
+
record.send(key)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
cpk_in_predicate(through_association.scope.klass.arel_table, source_reflection.foreign_key, ids)
|
41
|
+
else
|
42
|
+
original_construct_join_attributes(*records)
|
43
|
+
end
|
44
|
+
end
|
26
45
|
end
|
27
46
|
end
|
28
47
|
end
|
@@ -6,8 +6,7 @@ module ActiveRecord
|
|
6
6
|
value = exec_insert(sql, name, binds, pk, sequence_name)
|
7
7
|
|
8
8
|
return id_value if id_value
|
9
|
-
|
10
|
-
if pk.is_a?(Array) && !value.empty?
|
9
|
+
if pk.is_a?(Array) && value.respond_to?(:empty?) && !value.empty?
|
11
10
|
# This is a CPK model and the query result is not empty. Thus we can figure out the new ids for each
|
12
11
|
# auto incremented field
|
13
12
|
pk.map {|key| value.first[key]}
|
@@ -18,23 +18,21 @@ module CompositePrimaryKeys
|
|
18
18
|
end
|
19
19
|
|
20
20
|
order_query.flat_map do |o|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
raise IrreversibleOrderError, "Order #{o.inspect} can not be reversed automatically"
|
30
|
-
end
|
31
|
-
o.split(",").map! do |s|
|
32
|
-
s.strip!
|
33
|
-
s.gsub!(/\sasc\Z/i, " DESC") || s.gsub!(/\sdesc\Z/i, " ASC") || (s << " DESC")
|
34
|
-
end
|
35
|
-
else
|
36
|
-
o
|
21
|
+
case o
|
22
|
+
when Arel::Attribute
|
23
|
+
o.desc
|
24
|
+
when Arel::Nodes::Ordering
|
25
|
+
o.reverse
|
26
|
+
when String
|
27
|
+
if does_not_support_reverse?(o)
|
28
|
+
raise IrreversibleOrderError, "Order #{o.inspect} can not be reversed automatically"
|
37
29
|
end
|
30
|
+
o.split(",").map! do |s|
|
31
|
+
s.strip!
|
32
|
+
s.gsub!(/\sasc\Z/i, " DESC") || s.gsub!(/\sdesc\Z/i, " ASC") || (s << " DESC")
|
33
|
+
end
|
34
|
+
else
|
35
|
+
o
|
38
36
|
end
|
39
37
|
end
|
40
38
|
end
|
@@ -1,197 +1,199 @@
|
|
1
|
-
module ActiveRecord
|
2
|
-
class Relation
|
3
|
-
alias :initialize_without_cpk :initialize
|
4
|
-
def initialize(klass, table: klass.arel_table, predicate_builder: klass.predicate_builder, values: {})
|
5
|
-
initialize_without_cpk(klass, table: table, predicate_builder: predicate_builder, values: values)
|
6
|
-
add_cpk_support if klass && klass.composite?
|
7
|
-
end
|
8
|
-
|
9
|
-
alias :initialize_copy_without_cpk :initialize_copy
|
10
|
-
def initialize_copy(other)
|
11
|
-
initialize_copy_without_cpk(other)
|
12
|
-
add_cpk_support if klass.composite?
|
13
|
-
end
|
14
|
-
|
15
|
-
def add_cpk_support
|
16
|
-
extend CompositePrimaryKeys::CompositeRelation
|
17
|
-
end
|
18
|
-
|
19
|
-
def update_all(updates)
|
20
|
-
raise ArgumentError, "Empty list of attributes to change" if updates.blank?
|
21
|
-
|
22
|
-
if eager_loading?
|
23
|
-
relation = apply_join_dependency
|
24
|
-
return relation.update_all(updates)
|
25
|
-
end
|
26
|
-
|
27
|
-
stmt = Arel::UpdateManager.new
|
28
|
-
stmt.table(arel.join_sources.empty? ? table : arel.source)
|
29
|
-
stmt.key = table[primary_key]
|
30
|
-
|
31
|
-
# CPK
|
32
|
-
if @klass.composite?
|
33
|
-
stmt = Arel::UpdateManager.new
|
34
|
-
stmt.table(arel_table)
|
35
|
-
cpk_subquery(stmt)
|
36
|
-
else
|
37
|
-
stmt.wheres = arel.constraints
|
38
|
-
end
|
39
|
-
stmt.take(arel.limit)
|
40
|
-
stmt.offset(arel.offset)
|
41
|
-
stmt.order(*arel.orders)
|
42
|
-
|
43
|
-
if updates.is_a?(Hash)
|
44
|
-
if klass.locking_enabled? &&
|
45
|
-
!updates.key?(klass.locking_column) &&
|
46
|
-
!updates.key?(klass.locking_column.to_sym)
|
47
|
-
attr = table[klass.locking_column]
|
48
|
-
updates[attr.name] = _increment_attribute(attr)
|
49
|
-
end
|
50
|
-
stmt.set _substitute_values(updates)
|
51
|
-
else
|
52
|
-
stmt.set Arel.sql(klass.sanitize_sql_for_assignment(updates, table.name))
|
53
|
-
end
|
54
|
-
|
55
|
-
@klass.connection.update stmt, "#{@klass} Update All"
|
56
|
-
end
|
57
|
-
|
58
|
-
def delete_all
|
59
|
-
invalid_methods = INVALID_METHODS_FOR_DELETE_ALL.select do |method|
|
60
|
-
value = @values[method]
|
61
|
-
method == :distinct ? value : value&.any?
|
62
|
-
end
|
63
|
-
if invalid_methods.any?
|
64
|
-
raise ActiveRecordError.new("delete_all doesn't support #{invalid_methods.join(', ')}")
|
65
|
-
end
|
66
|
-
|
67
|
-
if eager_loading?
|
68
|
-
relation = apply_join_dependency
|
69
|
-
return relation.delete_all
|
70
|
-
end
|
71
|
-
|
72
|
-
stmt = Arel::DeleteManager.new
|
73
|
-
stmt.from(arel.join_sources.empty? ? table : arel.source)
|
74
|
-
stmt.key = table[primary_key]
|
75
|
-
|
76
|
-
# CPK
|
77
|
-
if @klass.composite?
|
78
|
-
stmt = Arel::DeleteManager.new
|
79
|
-
stmt.from(arel_table)
|
80
|
-
cpk_subquery(stmt)
|
81
|
-
else
|
82
|
-
stmt.wheres = arel.constraints
|
83
|
-
end
|
84
|
-
|
85
|
-
stmt.take(arel.limit)
|
86
|
-
stmt.offset(arel.offset)
|
87
|
-
stmt.order(*arel.orders)
|
88
|
-
|
89
|
-
affected = @klass.connection.delete(stmt, "#{@klass} Destroy")
|
90
|
-
|
91
|
-
reset
|
92
|
-
affected
|
93
|
-
end
|
94
|
-
|
95
|
-
# CPK
|
96
|
-
def cpk_subquery(stmt)
|
97
|
-
# For update and delete statements we need a way to specify which records should
|
98
|
-
# get updated. By default, Rails creates a nested IN subquery that uses the primary
|
99
|
-
# key. Postgresql, Sqlite, MariaDb and Oracle support IN subqueries with multiple
|
100
|
-
# columns but MySQL and SqlServer do not. Instead SQL server supports EXISTS queries
|
101
|
-
# and MySQL supports obfuscated IN queries. Thus we need to check the type of
|
102
|
-
# database adapter to decide how to proceed.
|
103
|
-
if defined?(ActiveRecord::ConnectionAdapters::Mysql2Adapter) && connection.is_a?(ActiveRecord::ConnectionAdapters::Mysql2Adapter)
|
104
|
-
cpk_mysql_subquery(stmt)
|
105
|
-
elsif defined?(ActiveRecord::ConnectionAdapters::
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
#
|
115
|
-
#
|
116
|
-
#
|
117
|
-
#
|
118
|
-
#
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
#
|
136
|
-
#
|
137
|
-
#
|
138
|
-
#
|
139
|
-
#
|
140
|
-
#
|
141
|
-
#
|
142
|
-
#
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
#
|
171
|
-
#
|
172
|
-
#
|
173
|
-
#
|
174
|
-
#
|
175
|
-
#
|
176
|
-
#
|
177
|
-
#
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
end
|
1
|
+
module ActiveRecord
|
2
|
+
class Relation
|
3
|
+
alias :initialize_without_cpk :initialize
|
4
|
+
def initialize(klass, table: klass.arel_table, predicate_builder: klass.predicate_builder, values: {})
|
5
|
+
initialize_without_cpk(klass, table: table, predicate_builder: predicate_builder, values: values)
|
6
|
+
add_cpk_support if klass && klass.composite?
|
7
|
+
end
|
8
|
+
|
9
|
+
alias :initialize_copy_without_cpk :initialize_copy
|
10
|
+
def initialize_copy(other)
|
11
|
+
initialize_copy_without_cpk(other)
|
12
|
+
add_cpk_support if klass.composite?
|
13
|
+
end
|
14
|
+
|
15
|
+
def add_cpk_support
|
16
|
+
extend CompositePrimaryKeys::CompositeRelation
|
17
|
+
end
|
18
|
+
|
19
|
+
def update_all(updates)
|
20
|
+
raise ArgumentError, "Empty list of attributes to change" if updates.blank?
|
21
|
+
|
22
|
+
if eager_loading?
|
23
|
+
relation = apply_join_dependency
|
24
|
+
return relation.update_all(updates)
|
25
|
+
end
|
26
|
+
|
27
|
+
stmt = Arel::UpdateManager.new
|
28
|
+
stmt.table(arel.join_sources.empty? ? table : arel.source)
|
29
|
+
stmt.key = table[primary_key]
|
30
|
+
|
31
|
+
# CPK
|
32
|
+
if @klass.composite?
|
33
|
+
stmt = Arel::UpdateManager.new
|
34
|
+
stmt.table(arel_table)
|
35
|
+
cpk_subquery(stmt)
|
36
|
+
else
|
37
|
+
stmt.wheres = arel.constraints
|
38
|
+
end
|
39
|
+
stmt.take(arel.limit)
|
40
|
+
stmt.offset(arel.offset)
|
41
|
+
stmt.order(*arel.orders)
|
42
|
+
|
43
|
+
if updates.is_a?(Hash)
|
44
|
+
if klass.locking_enabled? &&
|
45
|
+
!updates.key?(klass.locking_column) &&
|
46
|
+
!updates.key?(klass.locking_column.to_sym)
|
47
|
+
attr = table[klass.locking_column]
|
48
|
+
updates[attr.name] = _increment_attribute(attr)
|
49
|
+
end
|
50
|
+
stmt.set _substitute_values(updates)
|
51
|
+
else
|
52
|
+
stmt.set Arel.sql(klass.sanitize_sql_for_assignment(updates, table.name))
|
53
|
+
end
|
54
|
+
|
55
|
+
@klass.connection.update stmt, "#{@klass} Update All"
|
56
|
+
end
|
57
|
+
|
58
|
+
def delete_all
|
59
|
+
invalid_methods = INVALID_METHODS_FOR_DELETE_ALL.select do |method|
|
60
|
+
value = @values[method]
|
61
|
+
method == :distinct ? value : value&.any?
|
62
|
+
end
|
63
|
+
if invalid_methods.any?
|
64
|
+
raise ActiveRecordError.new("delete_all doesn't support #{invalid_methods.join(', ')}")
|
65
|
+
end
|
66
|
+
|
67
|
+
if eager_loading?
|
68
|
+
relation = apply_join_dependency
|
69
|
+
return relation.delete_all
|
70
|
+
end
|
71
|
+
|
72
|
+
stmt = Arel::DeleteManager.new
|
73
|
+
stmt.from(arel.join_sources.empty? ? table : arel.source)
|
74
|
+
stmt.key = table[primary_key]
|
75
|
+
|
76
|
+
# CPK
|
77
|
+
if @klass.composite?
|
78
|
+
stmt = Arel::DeleteManager.new
|
79
|
+
stmt.from(arel_table)
|
80
|
+
cpk_subquery(stmt)
|
81
|
+
else
|
82
|
+
stmt.wheres = arel.constraints
|
83
|
+
end
|
84
|
+
|
85
|
+
stmt.take(arel.limit)
|
86
|
+
stmt.offset(arel.offset)
|
87
|
+
stmt.order(*arel.orders)
|
88
|
+
|
89
|
+
affected = @klass.connection.delete(stmt, "#{@klass} Destroy")
|
90
|
+
|
91
|
+
reset
|
92
|
+
affected
|
93
|
+
end
|
94
|
+
|
95
|
+
# CPK
|
96
|
+
def cpk_subquery(stmt)
|
97
|
+
# For update and delete statements we need a way to specify which records should
|
98
|
+
# get updated. By default, Rails creates a nested IN subquery that uses the primary
|
99
|
+
# key. Postgresql, Sqlite, MariaDb and Oracle support IN subqueries with multiple
|
100
|
+
# columns but MySQL and SqlServer do not. Instead SQL server supports EXISTS queries
|
101
|
+
# and MySQL supports obfuscated IN queries. Thus we need to check the type of
|
102
|
+
# database adapter to decide how to proceed.
|
103
|
+
if defined?(ActiveRecord::ConnectionAdapters::Mysql2Adapter) && connection.is_a?(ActiveRecord::ConnectionAdapters::Mysql2Adapter)
|
104
|
+
cpk_mysql_subquery(stmt)
|
105
|
+
elsif defined?(ActiveRecord::ConnectionAdapters::TrilogyAdapter) && connection.is_a?(ActiveRecord::ConnectionAdapters::TrilogyAdapter)
|
106
|
+
cpk_mysql_subquery(stmt)
|
107
|
+
elsif defined?(ActiveRecord::ConnectionAdapters::SQLServerAdapter) && connection.is_a?(ActiveRecord::ConnectionAdapters::SQLServerAdapter)
|
108
|
+
cpk_exists_subquery(stmt)
|
109
|
+
else
|
110
|
+
cpk_in_subquery(stmt)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# Used by postgresql, sqlite, mariadb and oracle. Example query:
|
115
|
+
#
|
116
|
+
# UPDATE reference_codes
|
117
|
+
# SET ...
|
118
|
+
# WHERE (reference_codes.reference_type_id, reference_codes.reference_code) IN
|
119
|
+
# (SELECT reference_codes.reference_type_id, reference_codes.reference_code
|
120
|
+
# FROM reference_codes)
|
121
|
+
def cpk_in_subquery(stmt)
|
122
|
+
# Setup the subquery
|
123
|
+
subquery = arel.clone
|
124
|
+
subquery.projections = primary_keys.map do |key|
|
125
|
+
arel_table[key]
|
126
|
+
end
|
127
|
+
|
128
|
+
where_fields = primary_keys.map do |key|
|
129
|
+
arel_table[key]
|
130
|
+
end
|
131
|
+
where = Arel::Nodes::Grouping.new(where_fields).in(subquery)
|
132
|
+
stmt.wheres = [where]
|
133
|
+
end
|
134
|
+
|
135
|
+
# CPK. This is an alternative to IN subqueries. It is used by sqlserver.
|
136
|
+
# Example query:
|
137
|
+
#
|
138
|
+
# UPDATE reference_codes
|
139
|
+
# SET ...
|
140
|
+
# WHERE EXISTS
|
141
|
+
# (SELECT 1
|
142
|
+
# FROM reference_codes cpk_child
|
143
|
+
# WHERE reference_codes.reference_type_id = cpk_child.reference_type_id AND
|
144
|
+
# reference_codes.reference_code = cpk_child.reference_code)
|
145
|
+
def cpk_exists_subquery(stmt)
|
146
|
+
arel_attributes = primary_keys.map do |key|
|
147
|
+
table[key]
|
148
|
+
end.to_composite_keys
|
149
|
+
|
150
|
+
# Clone the query
|
151
|
+
subselect = arel.clone
|
152
|
+
|
153
|
+
# Alias the table - we assume just one table
|
154
|
+
aliased_table = subselect.froms.first
|
155
|
+
aliased_table.table_alias = "cpk_child"
|
156
|
+
|
157
|
+
# Project - really we could just set this to "1"
|
158
|
+
subselect.projections = arel_attributes
|
159
|
+
|
160
|
+
# Setup correlation to the outer query via where clauses
|
161
|
+
primary_keys.map do |key|
|
162
|
+
outer_attribute = arel_table[key]
|
163
|
+
inner_attribute = aliased_table[key]
|
164
|
+
where = outer_attribute.eq(inner_attribute)
|
165
|
+
subselect.where(where)
|
166
|
+
end
|
167
|
+
stmt.wheres = [Arel::Nodes::Exists.new(subselect)]
|
168
|
+
end
|
169
|
+
|
170
|
+
# CPK. This is the old way CPK created subqueries and is used by MySql.
|
171
|
+
# MySQL does not support referencing the same table that is being UPDATEd or
|
172
|
+
# DELETEd in a subquery so we obfuscate it. The ugly query looks like this:
|
173
|
+
#
|
174
|
+
# UPDATE `reference_codes`
|
175
|
+
# SET ...
|
176
|
+
# WHERE (reference_codes.reference_type_id, reference_codes.reference_code) IN
|
177
|
+
# (SELECT reference_type_id,reference_code
|
178
|
+
# FROM (SELECT DISTINCT `reference_codes`.`reference_type_id`, `reference_codes`.`reference_code`
|
179
|
+
# FROM `reference_codes`) __active_record_temp)
|
180
|
+
def cpk_mysql_subquery(stmt)
|
181
|
+
arel_attributes = primary_keys.map do |key|
|
182
|
+
table[key]
|
183
|
+
end.to_composite_keys
|
184
|
+
|
185
|
+
subselect = arel.clone
|
186
|
+
subselect.projections = arel_attributes
|
187
|
+
|
188
|
+
# Materialize subquery by adding distinct
|
189
|
+
# to work with MySQL 5.7.6 which sets optimizer_switch='derived_merge=on'
|
190
|
+
subselect.distinct unless arel.limit || arel.offset || arel.orders.any?
|
191
|
+
|
192
|
+
key_name = arel_attributes.map(&:name).join(',')
|
193
|
+
|
194
|
+
manager = Arel::SelectManager.new(subselect.as("__active_record_temp")).project(Arel.sql(key_name))
|
195
|
+
|
196
|
+
stmt.wheres = [Arel::Nodes::In.new(arel_attributes, manager.ast)]
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|