composite_primary_keys 12.0.2 → 12.0.10
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 +880 -841
- data/README.rdoc +180 -179
- data/lib/composite_primary_keys/active_model/attribute_assignment.rb +19 -0
- data/lib/composite_primary_keys/arel/sqlserver.rb +1 -3
- data/lib/composite_primary_keys/associations/association_scope.rb +68 -68
- data/lib/composite_primary_keys/associations/join_dependency.rb +103 -103
- data/lib/composite_primary_keys/associations/through_association.rb +2 -1
- data/lib/composite_primary_keys/attribute_methods/primary_key.rb +13 -0
- data/lib/composite_primary_keys/attribute_methods/read.rb +30 -30
- data/lib/composite_primary_keys/attribute_methods/write.rb +35 -35
- data/lib/composite_primary_keys/attribute_methods.rb +9 -9
- data/lib/composite_primary_keys/base.rb +141 -130
- data/lib/composite_primary_keys/composite_arrays.rb +0 -8
- data/lib/composite_primary_keys/connection_adapters/abstract/database_statements.rb +37 -17
- data/lib/composite_primary_keys/connection_adapters/sqlserver/database_statements.rb +44 -23
- data/lib/composite_primary_keys/core.rb +48 -48
- data/lib/composite_primary_keys/persistence.rb +82 -81
- data/lib/composite_primary_keys/reflection.rb +29 -29
- data/lib/composite_primary_keys/relation/batches.rb +1 -1
- data/lib/composite_primary_keys/relation/calculations.rb +81 -81
- data/lib/composite_primary_keys/relation/finder_methods.rb +235 -235
- data/lib/composite_primary_keys/relation/predicate_builder/association_query_value.rb +20 -20
- data/lib/composite_primary_keys/relation/query_methods.rb +42 -42
- data/lib/composite_primary_keys/relation/where_clause.rb +23 -23
- data/lib/composite_primary_keys/relation.rb +193 -118
- data/lib/composite_primary_keys/version.rb +8 -8
- data/lib/composite_primary_keys.rb +117 -118
- data/test/abstract_unit.rb +114 -113
- data/test/connections/databases.ci.yml +22 -19
- data/test/fixtures/article.rb +4 -0
- data/test/fixtures/articles.yml +4 -3
- data/test/fixtures/comment.rb +1 -3
- data/test/fixtures/comments.yml +10 -9
- data/test/fixtures/db_definitions/db2-create-tables.sql +112 -126
- data/test/fixtures/db_definitions/db2-drop-tables.sql +17 -19
- data/test/fixtures/db_definitions/mysql.sql +180 -217
- data/test/fixtures/db_definitions/oracle.drop.sql +42 -48
- data/test/fixtures/db_definitions/oracle.sql +200 -236
- data/test/fixtures/db_definitions/postgresql.sql +183 -220
- data/test/fixtures/db_definitions/sqlite.sql +170 -206
- data/test/fixtures/db_definitions/sqlserver.sql +176 -212
- data/test/fixtures/department.rb +16 -11
- data/test/fixtures/departments.yml +15 -15
- data/test/fixtures/employees.yml +27 -27
- data/test/fixtures/readings.yml +2 -2
- data/test/fixtures/restaurants_suburbs.yml +11 -11
- data/test/fixtures/streets.yml +16 -16
- data/test/fixtures/suburbs.yml +14 -14
- data/test/fixtures/user.rb +11 -10
- data/test/test_associations.rb +358 -351
- data/test/test_attributes.rb +60 -60
- data/test/test_calculations.rb +42 -42
- data/test/test_create.rb +218 -183
- data/test/test_delete.rb +182 -179
- data/test/test_exists.rb +39 -39
- data/test/test_find.rb +164 -145
- data/test/test_habtm.rb +2 -2
- data/test/test_ids.rb +112 -116
- data/test/test_nested_attributes.rb +67 -124
- data/test/test_polymorphic.rb +29 -13
- data/test/test_preload.rb +4 -3
- data/test/test_serialize.rb +2 -2
- data/test/test_update.rb +96 -78
- metadata +4 -19
- data/test/fixtures/hack.rb +0 -5
- data/test/fixtures/hacks.yml +0 -3
- data/test/fixtures/pk_called_id.rb +0 -5
- data/test/fixtures/pk_called_ids.yml +0 -11
- data/test/fixtures/reference_code_using_composite_key_alias.rb +0 -8
- data/test/fixtures/reference_code_using_simple_key_alias.rb +0 -8
- data/test/fixtures/seat.rb +0 -5
- data/test/fixtures/seats.yml +0 -9
- data/test/fixtures/topic.rb +0 -6
- data/test/fixtures/topic_source.rb +0 -7
- data/test/test_aliases.rb +0 -18
- data/test/test_enum.rb +0 -21
- data/test/test_suite.rb +0 -35
@@ -1,235 +1,235 @@
|
|
1
|
-
module CompositePrimaryKeys
|
2
|
-
module ActiveRecord
|
3
|
-
module FinderMethods
|
4
|
-
def apply_join_dependency(eager_loading: group_values.empty?)
|
5
|
-
join_dependency = construct_join_dependency(eager_load_values + includes_values, Arel::Nodes::OuterJoin)
|
6
|
-
relation = except(:includes, :eager_load, :preload).joins!(join_dependency)
|
7
|
-
|
8
|
-
if eager_loading && !using_limitable_reflections?(join_dependency.reflections)
|
9
|
-
if has_limit_or_offset?
|
10
|
-
limited_ids = limited_ids_for(relation)
|
11
|
-
|
12
|
-
# CPK
|
13
|
-
# limited_ids.empty? ? relation.none! : relation.where!(primary_key => limited_ids)
|
14
|
-
limited_ids.empty? ? relation.none! : relation.where!(cpk_in_predicate(table, self.primary_keys, limited_ids))
|
15
|
-
end
|
16
|
-
relation.limit_value = relation.offset_value = nil
|
17
|
-
end
|
18
|
-
|
19
|
-
if block_given?
|
20
|
-
yield relation, join_dependency
|
21
|
-
else
|
22
|
-
relation
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
def limited_ids_for(relation)
|
27
|
-
# CPK
|
28
|
-
# values = @klass.connection.columns_for_distinct(
|
29
|
-
# connection.column_name_from_arel_node(arel_attribute(primary_key)),
|
30
|
-
# relation.order_values
|
31
|
-
# )
|
32
|
-
|
33
|
-
columns = @klass.primary_keys.map do |key|
|
34
|
-
connection.visitor.compile(arel_attribute(key))
|
35
|
-
end
|
36
|
-
values = @klass.connection.columns_for_distinct(columns, relation.order_values)
|
37
|
-
|
38
|
-
relation = relation.except(:select).select(values).distinct!
|
39
|
-
|
40
|
-
id_rows = skip_query_cache_if_necessary { @klass.connection.select_all(relation.arel, "SQL") }
|
41
|
-
# CPK
|
42
|
-
#id_rows.map { |row| row[primary_key] }
|
43
|
-
id_rows.map do |row|
|
44
|
-
@klass.primary_keys.map do |key|
|
45
|
-
row[key]
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
def construct_relation_for_exists(conditions)
|
51
|
-
conditions = sanitize_forbidden_attributes(conditions)
|
52
|
-
|
53
|
-
if distinct_value && offset_value
|
54
|
-
relation = except(:order).limit!(1)
|
55
|
-
else
|
56
|
-
relation = except(:select, :distinct, :order)._select!(::ActiveRecord::FinderMethods::ONE_AS_ONE).limit!(1)
|
57
|
-
end
|
58
|
-
|
59
|
-
case conditions
|
60
|
-
# CPK
|
61
|
-
when CompositePrimaryKeys::CompositeKeys
|
62
|
-
relation = relation.where(cpk_id_predicate(table, primary_key, conditions))
|
63
|
-
# CPK
|
64
|
-
when Array
|
65
|
-
pk_length = @klass.primary_keys.length
|
66
|
-
|
67
|
-
if conditions.length == pk_length # E.g. conditions = ['France', 'Paris']
|
68
|
-
return self.construct_relation_for_exists(conditions.to_composite_keys)
|
69
|
-
else # Assume that conditions contains where relation
|
70
|
-
relation = relation.where(conditions)
|
71
|
-
end
|
72
|
-
when Array, Hash
|
73
|
-
relation.where!(conditions) unless conditions.empty?
|
74
|
-
else
|
75
|
-
relation.where!(primary_key => conditions) unless conditions == :none
|
76
|
-
end
|
77
|
-
|
78
|
-
relation
|
79
|
-
end
|
80
|
-
|
81
|
-
def find_with_ids(*ids)
|
82
|
-
raise UnknownPrimaryKey.new(@klass) if primary_key.nil?
|
83
|
-
|
84
|
-
# CPK
|
85
|
-
# expects_array = ids.first.kind_of?(Array)
|
86
|
-
ids = CompositePrimaryKeys.normalize(ids, @klass.primary_keys.length)
|
87
|
-
expects_array = ids.flatten != ids.flatten(1)
|
88
|
-
return ids.first if expects_array && ids.first.empty?
|
89
|
-
|
90
|
-
# CPK
|
91
|
-
# ids = ids.flatten.compact.uniq
|
92
|
-
ids = expects_array ? ids.first : ids
|
93
|
-
|
94
|
-
model_name = @klass.name
|
95
|
-
|
96
|
-
case ids.size
|
97
|
-
when 0
|
98
|
-
error_message = "Couldn't find #{model_name} without an ID"
|
99
|
-
raise RecordNotFound.new(error_message, model_name, primary_key)
|
100
|
-
when 1
|
101
|
-
result = find_one(ids.first)
|
102
|
-
expects_array ? [ result ] : result
|
103
|
-
else
|
104
|
-
find_some(ids)
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
# def last(limit = nil)
|
109
|
-
# return find_last(limit) if loaded? || has_limit_or_offset?
|
110
|
-
#
|
111
|
-
# result = limit(limit || 1)
|
112
|
-
# # CPK
|
113
|
-
# # result.order!(arel_attribute(primary_key)) if order_values.empty? && primary_key
|
114
|
-
# if order_values.empty? && primary_key
|
115
|
-
# if composite?
|
116
|
-
# result.order!(primary_keys.map { |pk| arel_attribute(pk).asc })
|
117
|
-
# elsif
|
118
|
-
# result.order!(arel_attribute(primary_key))
|
119
|
-
# end
|
120
|
-
# end
|
121
|
-
#
|
122
|
-
# result = result.reverse_order!
|
123
|
-
#
|
124
|
-
# limit ? result.reverse : result.first
|
125
|
-
# rescue ::ActiveRecord::IrreversibleOrderError
|
126
|
-
# ActiveSupport::Deprecation.warn(<<-WARNING.squish)
|
127
|
-
# Finding a last element by loading the relation when SQL ORDER
|
128
|
-
# can not be reversed is deprecated.
|
129
|
-
# Rails 5.1 will raise ActiveRecord::IrreversibleOrderError in this case.
|
130
|
-
# Please call `to_a.last` if you still want to load the relation.
|
131
|
-
# WARNING
|
132
|
-
# find_last(limit)
|
133
|
-
# end
|
134
|
-
|
135
|
-
def find_one(id)
|
136
|
-
if ::ActiveRecord::Base === id
|
137
|
-
raise ArgumentError, <<-MSG.squish
|
138
|
-
You are passing an instance of ActiveRecord::Base to `find`.
|
139
|
-
Please pass the id of the object by calling `.id`.
|
140
|
-
MSG
|
141
|
-
end
|
142
|
-
|
143
|
-
# CPK
|
144
|
-
#relation = where(primary_key => id)
|
145
|
-
relation = where(cpk_id_predicate(table, primary_keys, id))
|
146
|
-
record = relation.take
|
147
|
-
|
148
|
-
raise_record_not_found_exception!(id, 0, 1) unless record
|
149
|
-
|
150
|
-
record
|
151
|
-
end
|
152
|
-
|
153
|
-
def find_some(ids)
|
154
|
-
# CPK
|
155
|
-
if composite?
|
156
|
-
ids = if ids.length == 1
|
157
|
-
CompositePrimaryKeys::CompositeKeys.parse(ids.first)
|
158
|
-
else
|
159
|
-
ids.to_composite_keys
|
160
|
-
end
|
161
|
-
end
|
162
|
-
|
163
|
-
return find_some_ordered(ids) unless order_values.present?
|
164
|
-
|
165
|
-
# CPK
|
166
|
-
# result = where(primary_key => ids).to_a
|
167
|
-
result = if composite?
|
168
|
-
result = where(cpk_in_predicate(table, primary_keys, ids)).to_a
|
169
|
-
else
|
170
|
-
result = where(primary_key => ids).to_a
|
171
|
-
end
|
172
|
-
|
173
|
-
expected_size =
|
174
|
-
if limit_value && ids.size > limit_value
|
175
|
-
limit_value
|
176
|
-
else
|
177
|
-
ids.size
|
178
|
-
end
|
179
|
-
|
180
|
-
# 11 ids with limit 3, offset 9 should give 2 results.
|
181
|
-
if offset_value && (ids.size - offset_value < expected_size)
|
182
|
-
expected_size = ids.size - offset_value
|
183
|
-
end
|
184
|
-
|
185
|
-
if result.size == expected_size
|
186
|
-
result
|
187
|
-
else
|
188
|
-
raise_record_not_found_exception!(ids, result.size, expected_size)
|
189
|
-
end
|
190
|
-
end
|
191
|
-
|
192
|
-
def find_some_ordered(ids)
|
193
|
-
ids = ids.slice(offset_value || 0, limit_value || ids.size) || []
|
194
|
-
|
195
|
-
# CPK
|
196
|
-
# result = except(:limit, :offset).where(primary_key => ids).records
|
197
|
-
result = if composite?
|
198
|
-
except(:limit, :offset).where(cpk_in_predicate(table, primary_keys, ids)).records
|
199
|
-
else
|
200
|
-
except(:limit, :offset).where(primary_key => ids).records
|
201
|
-
end
|
202
|
-
|
203
|
-
if result.size == ids.size
|
204
|
-
pk_type = @klass.type_for_attribute(primary_key)
|
205
|
-
|
206
|
-
records_by_id = result.index_by(&:id)
|
207
|
-
# CPK
|
208
|
-
# ids.map { |id| records_by_id.fetch(pk_type.cast(id)) }
|
209
|
-
if composite?
|
210
|
-
ids.map do |id|
|
211
|
-
typecasted_id = primary_keys.zip(id).map do |col, val|
|
212
|
-
@klass.type_for_attribute(col).cast(val)
|
213
|
-
end
|
214
|
-
records_by_id.fetch(typecasted_id)
|
215
|
-
end
|
216
|
-
else
|
217
|
-
ids.map { |id| records_by_id.fetch(pk_type.cast(id)) }
|
218
|
-
end
|
219
|
-
else
|
220
|
-
raise_record_not_found_exception!(ids, result.size, ids.size)
|
221
|
-
end
|
222
|
-
end
|
223
|
-
|
224
|
-
def ordered_relation
|
225
|
-
if order_values.empty? && (implicit_order_column || primary_key)
|
226
|
-
# CPK
|
227
|
-
# order(arel_attribute(implicit_order_column || primary_key).asc)
|
228
|
-
order(Array(implicit_order_column || primary_key).map {|key| arel_attribute(key).asc})
|
229
|
-
else
|
230
|
-
self
|
231
|
-
end
|
232
|
-
end
|
233
|
-
end
|
234
|
-
end
|
235
|
-
end
|
1
|
+
module CompositePrimaryKeys
|
2
|
+
module ActiveRecord
|
3
|
+
module FinderMethods
|
4
|
+
def apply_join_dependency(eager_loading: group_values.empty?)
|
5
|
+
join_dependency = construct_join_dependency(eager_load_values + includes_values, Arel::Nodes::OuterJoin)
|
6
|
+
relation = except(:includes, :eager_load, :preload).joins!(join_dependency)
|
7
|
+
|
8
|
+
if eager_loading && !using_limitable_reflections?(join_dependency.reflections)
|
9
|
+
if has_limit_or_offset?
|
10
|
+
limited_ids = limited_ids_for(relation)
|
11
|
+
|
12
|
+
# CPK
|
13
|
+
# limited_ids.empty? ? relation.none! : relation.where!(primary_key => limited_ids)
|
14
|
+
limited_ids.empty? ? relation.none! : relation.where!(cpk_in_predicate(table, self.primary_keys, limited_ids))
|
15
|
+
end
|
16
|
+
relation.limit_value = relation.offset_value = nil
|
17
|
+
end
|
18
|
+
|
19
|
+
if block_given?
|
20
|
+
yield relation, join_dependency
|
21
|
+
else
|
22
|
+
relation
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def limited_ids_for(relation)
|
27
|
+
# CPK
|
28
|
+
# values = @klass.connection.columns_for_distinct(
|
29
|
+
# connection.column_name_from_arel_node(arel_attribute(primary_key)),
|
30
|
+
# relation.order_values
|
31
|
+
# )
|
32
|
+
|
33
|
+
columns = @klass.primary_keys.map do |key|
|
34
|
+
connection.visitor.compile(arel_attribute(key))
|
35
|
+
end
|
36
|
+
values = @klass.connection.columns_for_distinct(columns, relation.order_values)
|
37
|
+
|
38
|
+
relation = relation.except(:select).select(values).distinct!
|
39
|
+
|
40
|
+
id_rows = skip_query_cache_if_necessary { @klass.connection.select_all(relation.arel, "SQL") }
|
41
|
+
# CPK
|
42
|
+
#id_rows.map { |row| row[primary_key] }
|
43
|
+
id_rows.map do |row|
|
44
|
+
@klass.primary_keys.map do |key|
|
45
|
+
row[key]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def construct_relation_for_exists(conditions)
|
51
|
+
conditions = sanitize_forbidden_attributes(conditions)
|
52
|
+
|
53
|
+
if distinct_value && offset_value
|
54
|
+
relation = except(:order).limit!(1)
|
55
|
+
else
|
56
|
+
relation = except(:select, :distinct, :order)._select!(::ActiveRecord::FinderMethods::ONE_AS_ONE).limit!(1)
|
57
|
+
end
|
58
|
+
|
59
|
+
case conditions
|
60
|
+
# CPK
|
61
|
+
when CompositePrimaryKeys::CompositeKeys
|
62
|
+
relation = relation.where(cpk_id_predicate(table, primary_key, conditions))
|
63
|
+
# CPK
|
64
|
+
when Array
|
65
|
+
pk_length = @klass.primary_keys.length
|
66
|
+
|
67
|
+
if conditions.length == pk_length # E.g. conditions = ['France', 'Paris']
|
68
|
+
return self.construct_relation_for_exists(conditions.to_composite_keys)
|
69
|
+
else # Assume that conditions contains where relation
|
70
|
+
relation = relation.where(conditions)
|
71
|
+
end
|
72
|
+
when Array, Hash
|
73
|
+
relation.where!(conditions) unless conditions.empty?
|
74
|
+
else
|
75
|
+
relation.where!(primary_key => conditions) unless conditions == :none
|
76
|
+
end
|
77
|
+
|
78
|
+
relation
|
79
|
+
end
|
80
|
+
|
81
|
+
def find_with_ids(*ids)
|
82
|
+
raise UnknownPrimaryKey.new(@klass) if primary_key.nil?
|
83
|
+
|
84
|
+
# CPK
|
85
|
+
# expects_array = ids.first.kind_of?(Array)
|
86
|
+
ids = CompositePrimaryKeys.normalize(ids, @klass.primary_keys.length)
|
87
|
+
expects_array = ids.flatten != ids.flatten(1)
|
88
|
+
return ids.first if expects_array && ids.first.empty?
|
89
|
+
|
90
|
+
# CPK
|
91
|
+
# ids = ids.flatten.compact.uniq
|
92
|
+
ids = expects_array ? ids.first : ids
|
93
|
+
|
94
|
+
model_name = @klass.name
|
95
|
+
|
96
|
+
case ids.size
|
97
|
+
when 0
|
98
|
+
error_message = "Couldn't find #{model_name} without an ID"
|
99
|
+
raise ::ActiveRecord::RecordNotFound.new(error_message, model_name, primary_key)
|
100
|
+
when 1
|
101
|
+
result = find_one(ids.first)
|
102
|
+
expects_array ? [ result ] : result
|
103
|
+
else
|
104
|
+
find_some(ids)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# def last(limit = nil)
|
109
|
+
# return find_last(limit) if loaded? || has_limit_or_offset?
|
110
|
+
#
|
111
|
+
# result = limit(limit || 1)
|
112
|
+
# # CPK
|
113
|
+
# # result.order!(arel_attribute(primary_key)) if order_values.empty? && primary_key
|
114
|
+
# if order_values.empty? && primary_key
|
115
|
+
# if composite?
|
116
|
+
# result.order!(primary_keys.map { |pk| arel_attribute(pk).asc })
|
117
|
+
# elsif
|
118
|
+
# result.order!(arel_attribute(primary_key))
|
119
|
+
# end
|
120
|
+
# end
|
121
|
+
#
|
122
|
+
# result = result.reverse_order!
|
123
|
+
#
|
124
|
+
# limit ? result.reverse : result.first
|
125
|
+
# rescue ::ActiveRecord::IrreversibleOrderError
|
126
|
+
# ActiveSupport::Deprecation.warn(<<-WARNING.squish)
|
127
|
+
# Finding a last element by loading the relation when SQL ORDER
|
128
|
+
# can not be reversed is deprecated.
|
129
|
+
# Rails 5.1 will raise ActiveRecord::IrreversibleOrderError in this case.
|
130
|
+
# Please call `to_a.last` if you still want to load the relation.
|
131
|
+
# WARNING
|
132
|
+
# find_last(limit)
|
133
|
+
# end
|
134
|
+
|
135
|
+
def find_one(id)
|
136
|
+
if ::ActiveRecord::Base === id
|
137
|
+
raise ArgumentError, <<-MSG.squish
|
138
|
+
You are passing an instance of ActiveRecord::Base to `find`.
|
139
|
+
Please pass the id of the object by calling `.id`.
|
140
|
+
MSG
|
141
|
+
end
|
142
|
+
|
143
|
+
# CPK
|
144
|
+
#relation = where(primary_key => id)
|
145
|
+
relation = where(cpk_id_predicate(table, primary_keys, id))
|
146
|
+
record = relation.take
|
147
|
+
|
148
|
+
raise_record_not_found_exception!(id, 0, 1) unless record
|
149
|
+
|
150
|
+
record
|
151
|
+
end
|
152
|
+
|
153
|
+
def find_some(ids)
|
154
|
+
# CPK
|
155
|
+
if composite?
|
156
|
+
ids = if ids.length == 1
|
157
|
+
CompositePrimaryKeys::CompositeKeys.parse(ids.first)
|
158
|
+
else
|
159
|
+
ids.to_composite_keys
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
return find_some_ordered(ids) unless order_values.present?
|
164
|
+
|
165
|
+
# CPK
|
166
|
+
# result = where(primary_key => ids).to_a
|
167
|
+
result = if composite?
|
168
|
+
result = where(cpk_in_predicate(table, primary_keys, ids)).to_a
|
169
|
+
else
|
170
|
+
result = where(primary_key => ids).to_a
|
171
|
+
end
|
172
|
+
|
173
|
+
expected_size =
|
174
|
+
if limit_value && ids.size > limit_value
|
175
|
+
limit_value
|
176
|
+
else
|
177
|
+
ids.size
|
178
|
+
end
|
179
|
+
|
180
|
+
# 11 ids with limit 3, offset 9 should give 2 results.
|
181
|
+
if offset_value && (ids.size - offset_value < expected_size)
|
182
|
+
expected_size = ids.size - offset_value
|
183
|
+
end
|
184
|
+
|
185
|
+
if result.size == expected_size
|
186
|
+
result
|
187
|
+
else
|
188
|
+
raise_record_not_found_exception!(ids, result.size, expected_size)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
def find_some_ordered(ids)
|
193
|
+
ids = ids.slice(offset_value || 0, limit_value || ids.size) || []
|
194
|
+
|
195
|
+
# CPK
|
196
|
+
# result = except(:limit, :offset).where(primary_key => ids).records
|
197
|
+
result = if composite?
|
198
|
+
except(:limit, :offset).where(cpk_in_predicate(table, primary_keys, ids)).records
|
199
|
+
else
|
200
|
+
except(:limit, :offset).where(primary_key => ids).records
|
201
|
+
end
|
202
|
+
|
203
|
+
if result.size == ids.size
|
204
|
+
pk_type = @klass.type_for_attribute(primary_key)
|
205
|
+
|
206
|
+
records_by_id = result.index_by(&:id)
|
207
|
+
# CPK
|
208
|
+
# ids.map { |id| records_by_id.fetch(pk_type.cast(id)) }
|
209
|
+
if composite?
|
210
|
+
ids.map do |id|
|
211
|
+
typecasted_id = primary_keys.zip(id).map do |col, val|
|
212
|
+
@klass.type_for_attribute(col).cast(val)
|
213
|
+
end
|
214
|
+
records_by_id.fetch(typecasted_id)
|
215
|
+
end
|
216
|
+
else
|
217
|
+
ids.map { |id| records_by_id.fetch(pk_type.cast(id)) }
|
218
|
+
end
|
219
|
+
else
|
220
|
+
raise_record_not_found_exception!(ids, result.size, ids.size)
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
def ordered_relation
|
225
|
+
if order_values.empty? && (implicit_order_column || primary_key)
|
226
|
+
# CPK
|
227
|
+
# order(arel_attribute(implicit_order_column || primary_key).asc)
|
228
|
+
order(Array(implicit_order_column || primary_key).map {|key| arel_attribute(key).asc})
|
229
|
+
else
|
230
|
+
self
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
@@ -1,20 +1,20 @@
|
|
1
|
-
module ActiveRecord
|
2
|
-
class PredicateBuilder
|
3
|
-
class AssociationQueryValue
|
4
|
-
def queries
|
5
|
-
# CPK
|
6
|
-
if associated_table.association_join_foreign_key.is_a?(Array)
|
7
|
-
if ids.is_a?(ActiveRecord::Relation)
|
8
|
-
ids.map do |id|
|
9
|
-
id.
|
10
|
-
end
|
11
|
-
else
|
12
|
-
[associated_table.association_join_foreign_key.zip(ids).to_h]
|
13
|
-
end
|
14
|
-
else
|
15
|
-
[associated_table.association_join_foreign_key.to_s => ids]
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
1
|
+
module ActiveRecord
|
2
|
+
class PredicateBuilder
|
3
|
+
class AssociationQueryValue
|
4
|
+
def queries
|
5
|
+
# CPK
|
6
|
+
if associated_table.association_join_foreign_key.is_a?(Array)
|
7
|
+
if ids.is_a?(ActiveRecord::Relation)
|
8
|
+
ids.map do |id|
|
9
|
+
associated_table.association_join_foreign_key.zip(id.id).to_h
|
10
|
+
end
|
11
|
+
else
|
12
|
+
[associated_table.association_join_foreign_key.zip(ids).to_h]
|
13
|
+
end
|
14
|
+
else
|
15
|
+
[associated_table.association_join_foreign_key.to_s => ids]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -1,43 +1,43 @@
|
|
1
|
-
module CompositePrimaryKeys
|
2
|
-
module ActiveRecord
|
3
|
-
module QueryMethods
|
4
|
-
def reverse_sql_order(order_query)
|
5
|
-
if order_query.empty?
|
6
|
-
# CPK
|
7
|
-
# return [arel_attribute(primary_key).desc] if primary_key
|
8
|
-
|
9
|
-
if primary_key
|
10
|
-
# break apart CPKs
|
11
|
-
return primary_key.map do |key|
|
12
|
-
arel_attribute(key).desc
|
13
|
-
end
|
14
|
-
else
|
15
|
-
raise IrreversibleOrderError,
|
16
|
-
"Relation has no current order and table has no primary key to be used as default order"
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
order_query.flat_map do |o|
|
21
|
-
order_query.flat_map do |o|
|
22
|
-
case o
|
23
|
-
when Arel::Attribute
|
24
|
-
o.desc
|
25
|
-
when Arel::Nodes::Ordering
|
26
|
-
o.reverse
|
27
|
-
when String
|
28
|
-
if does_not_support_reverse?(o)
|
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
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
1
|
+
module CompositePrimaryKeys
|
2
|
+
module ActiveRecord
|
3
|
+
module QueryMethods
|
4
|
+
def reverse_sql_order(order_query)
|
5
|
+
if order_query.empty?
|
6
|
+
# CPK
|
7
|
+
# return [arel_attribute(primary_key).desc] if primary_key
|
8
|
+
|
9
|
+
if primary_key
|
10
|
+
# break apart CPKs
|
11
|
+
return primary_key.map do |key|
|
12
|
+
arel_attribute(key).desc
|
13
|
+
end
|
14
|
+
else
|
15
|
+
raise IrreversibleOrderError,
|
16
|
+
"Relation has no current order and table has no primary key to be used as default order"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
order_query.flat_map do |o|
|
21
|
+
order_query.flat_map do |o|
|
22
|
+
case o
|
23
|
+
when Arel::Attribute
|
24
|
+
o.desc
|
25
|
+
when Arel::Nodes::Ordering
|
26
|
+
o.reverse
|
27
|
+
when String
|
28
|
+
if does_not_support_reverse?(o)
|
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
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
43
|
end
|
@@ -1,24 +1,24 @@
|
|
1
|
-
module ActiveRecord
|
2
|
-
class Relation
|
3
|
-
class WhereClause
|
4
|
-
def to_h(table_name = nil)
|
5
|
-
equalities = equalities(predicates)
|
6
|
-
|
7
|
-
# CPK Adds this line, because ours are coming in with AND->{EQUALITY, EQUALITY}
|
8
|
-
equalities = predicates.grep(Arel::Nodes::And).map(&:children).flatten.grep(Arel::Nodes::Equality) if equalities.empty?
|
9
|
-
|
10
|
-
if table_name
|
11
|
-
equalities = equalities.select do |node|
|
12
|
-
node.left.relation.name == table_name
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
equalities.map { |node|
|
17
|
-
name = node.left.name.to_s
|
18
|
-
value = extract_node_value(node.right)
|
19
|
-
[name, value]
|
20
|
-
}.to_h
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
1
|
+
module ActiveRecord
|
2
|
+
class Relation
|
3
|
+
class WhereClause
|
4
|
+
def to_h(table_name = nil)
|
5
|
+
equalities = equalities(predicates)
|
6
|
+
|
7
|
+
# CPK Adds this line, because ours are coming in with AND->{EQUALITY, EQUALITY}
|
8
|
+
equalities = predicates.grep(Arel::Nodes::And).map(&:children).flatten.grep(Arel::Nodes::Equality) if equalities.empty?
|
9
|
+
|
10
|
+
if table_name
|
11
|
+
equalities = equalities.select do |node|
|
12
|
+
node.left.relation.name == table_name
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
equalities.map { |node|
|
17
|
+
name = node.left.name.to_s
|
18
|
+
value = extract_node_value(node.right)
|
19
|
+
[name, value]
|
20
|
+
}.to_h
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
24
|
end
|