composite_primary_keys 1.0.8 → 1.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.
- data/History.txt +10 -0
- data/lib/composite_primary_keys/association_preload.rb +67 -61
- data/lib/composite_primary_keys/associations.rb +428 -409
- data/lib/composite_primary_keys/attribute_methods.rb +3 -3
- data/lib/composite_primary_keys/base.rb +128 -110
- data/lib/composite_primary_keys/calculations.rb +8 -8
- data/lib/composite_primary_keys/composite_arrays.rb +6 -5
- data/lib/composite_primary_keys/connection_adapters/postgresql_adapter.rb +44 -2
- data/lib/composite_primary_keys/fixtures.rb +2 -3
- data/lib/composite_primary_keys/version.rb +1 -1
- data/scripts/console.rb +34 -11
- data/test/fixtures/db_definitions/db2-create-tables.sql +2 -2
- data/test/fixtures/db_definitions/mysql.sql +156 -155
- data/test/fixtures/db_definitions/oracle.drop.sql +4 -1
- data/test/fixtures/db_definitions/oracle.sql +117 -119
- data/test/fixtures/db_definitions/postgresql.sql +164 -98
- data/test/fixtures/db_definitions/sqlite.sql +74 -73
- data/test/fixtures/street.rb +2 -2
- data/test/fixtures/streets.yml +14 -14
- data/test/test_associations.rb +0 -5
- data/test/test_attribute_methods.rb +2 -2
- data/test/test_create.rb +68 -68
- data/test/test_delete.rb +19 -10
- data/test/test_ids.rb +7 -0
- data/tmp/test.db +0 -0
- data/website/template.js +3 -3
- metadata +2 -2
@@ -5,7 +5,7 @@ module CompositePrimaryKeys
|
|
5
5
|
super
|
6
6
|
base.send(:extend, ClassMethods)
|
7
7
|
end
|
8
|
-
|
8
|
+
|
9
9
|
module ClassMethods
|
10
10
|
# Define an attribute reader method. Cope with nil column.
|
11
11
|
def define_read_method(symbol, attr_name, column)
|
@@ -16,7 +16,7 @@ module CompositePrimaryKeys
|
|
16
16
|
unless self.primary_keys.include?(attr_name.to_sym)
|
17
17
|
access_code = access_code.insert(0, "missing_attribute('#{attr_name}', caller) unless @attributes.has_key?('#{attr_name}'); ")
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
if cache_attribute?(attr_name)
|
21
21
|
access_code = "@attributes_cache['#{attr_name}'] ||= (#{access_code})"
|
22
22
|
end
|
@@ -81,4 +81,4 @@ module CompositePrimaryKeys
|
|
81
81
|
end
|
82
82
|
end
|
83
83
|
end
|
84
|
-
end
|
84
|
+
end
|
@@ -2,72 +2,70 @@ module CompositePrimaryKeys
|
|
2
2
|
module ActiveRecord #:nodoc:
|
3
3
|
class CompositeKeyError < StandardError #:nodoc:
|
4
4
|
end
|
5
|
-
|
5
|
+
|
6
6
|
module Base #:nodoc:
|
7
|
-
|
7
|
+
|
8
8
|
INVALID_FOR_COMPOSITE_KEYS = 'Not appropriate for composite primary keys'
|
9
|
-
NOT_IMPLEMENTED_YET
|
10
|
-
|
9
|
+
NOT_IMPLEMENTED_YET = 'Not implemented for composite primary keys yet'
|
10
|
+
|
11
11
|
def self.append_features(base)
|
12
12
|
super
|
13
13
|
base.send(:include, InstanceMethods)
|
14
14
|
base.extend(ClassMethods)
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
17
|
module ClassMethods
|
18
18
|
def set_primary_keys(*keys)
|
19
19
|
keys = keys.first if keys.first.is_a?(Array)
|
20
|
-
keys = keys.map {|k| k.to_sym }
|
21
|
-
cattr_accessor :primary_keys
|
20
|
+
keys = keys.map { |k| k.to_sym }
|
21
|
+
cattr_accessor :primary_keys
|
22
22
|
self.primary_keys = keys.to_composite_keys
|
23
|
-
|
23
|
+
|
24
24
|
class_eval <<-EOV
|
25
25
|
extend CompositeClassMethods
|
26
26
|
include CompositeInstanceMethods
|
27
|
-
|
27
|
+
|
28
28
|
include CompositePrimaryKeys::ActiveRecord::Associations
|
29
29
|
include CompositePrimaryKeys::ActiveRecord::AssociationPreload
|
30
30
|
include CompositePrimaryKeys::ActiveRecord::Calculations
|
31
31
|
include CompositePrimaryKeys::ActiveRecord::AttributeMethods
|
32
32
|
EOV
|
33
33
|
end
|
34
|
-
|
34
|
+
|
35
35
|
def composite?
|
36
36
|
false
|
37
37
|
end
|
38
38
|
end
|
39
|
-
|
39
|
+
|
40
40
|
module InstanceMethods
|
41
41
|
def composite?; self.class.composite?; end
|
42
42
|
end
|
43
|
-
|
44
|
-
module CompositeInstanceMethods
|
45
|
-
|
43
|
+
|
44
|
+
module CompositeInstanceMethods
|
45
|
+
|
46
46
|
# A model instance's primary keys is always available as model.ids
|
47
47
|
# whether you name it the default 'id' or set it to something else.
|
48
48
|
def id
|
49
49
|
attr_names = self.class.primary_keys
|
50
|
-
CompositeIds.new(
|
51
|
-
attr_names.map {|attr_name| read_attribute(attr_name)}
|
52
|
-
)
|
50
|
+
CompositeIds.new(attr_names.map { |attr_name| read_attribute(attr_name) })
|
53
51
|
end
|
54
52
|
alias_method :ids, :id
|
55
|
-
|
53
|
+
|
56
54
|
def to_param
|
57
55
|
id.to_s
|
58
56
|
end
|
59
|
-
|
57
|
+
|
60
58
|
def id_before_type_cast #:nodoc:
|
61
59
|
raise CompositeKeyError, CompositePrimaryKeys::ActiveRecord::Base::NOT_IMPLEMENTED_YET
|
62
60
|
end
|
63
|
-
|
61
|
+
|
64
62
|
def quoted_id #:nodoc:
|
65
63
|
[self.class.primary_keys, ids].
|
66
64
|
transpose.
|
67
65
|
map {|attr_name,id| quote_value(id, column_for_attribute(attr_name))}.
|
68
66
|
to_composite_ids
|
69
67
|
end
|
70
|
-
|
68
|
+
|
71
69
|
# Sets the primary ID.
|
72
70
|
def id=(ids)
|
73
71
|
ids = ids.split(ID_SEP) if ids.is_a?(String)
|
@@ -78,7 +76,7 @@ module CompositePrimaryKeys
|
|
78
76
|
[primary_keys, ids].transpose.each {|key, an_id| write_attribute(key , an_id)}
|
79
77
|
id
|
80
78
|
end
|
81
|
-
|
79
|
+
|
82
80
|
# Returns a clone of the record that hasn't been assigned an id yet and
|
83
81
|
# is treated as a new record. Note that this is a "shallow" clone:
|
84
82
|
# it copies the object's attributes only, not its associations.
|
@@ -91,21 +89,22 @@ module CompositePrimaryKeys
|
|
91
89
|
record.send :instance_variable_set, '@attributes', attrs
|
92
90
|
end
|
93
91
|
end
|
94
|
-
|
95
|
-
|
92
|
+
|
93
|
+
|
96
94
|
private
|
97
95
|
# The xx_without_callbacks methods are overwritten as that is the end of the alias chain
|
98
|
-
|
96
|
+
|
99
97
|
# Creates a new record with values matching those of the instance attributes.
|
100
98
|
def create_without_callbacks
|
101
99
|
unless self.id
|
102
100
|
raise CompositeKeyError, "Composite keys do not generated ids from sequences, you must provide id values"
|
103
101
|
end
|
104
102
|
attributes_minus_pks = attributes_with_quotes(false)
|
105
|
-
|
103
|
+
quoted_pk_columns = self.class.primary_key.map { |col| connection.quote_column_name(col) }
|
104
|
+
cols = quoted_column_names(attributes_minus_pks) << quoted_pk_columns
|
106
105
|
vals = attributes_minus_pks.values << quoted_id
|
107
106
|
connection.insert(
|
108
|
-
"INSERT INTO #{self.class.
|
107
|
+
"INSERT INTO #{self.class.quoted_table_name} " +
|
109
108
|
"(#{cols.join(', ')}) " +
|
110
109
|
"VALUES (#{vals.join(', ')})",
|
111
110
|
"#{self.class.name} Create",
|
@@ -115,74 +114,93 @@ module CompositePrimaryKeys
|
|
115
114
|
@new_record = false
|
116
115
|
return true
|
117
116
|
end
|
118
|
-
|
119
|
-
|
117
|
+
|
120
118
|
# Updates the associated record with values matching those of the instance attributes.
|
121
119
|
def update_without_callbacks
|
122
|
-
|
120
|
+
where_clause_terms = [self.class.primary_key, quoted_id].transpose.map do |pair|
|
121
|
+
"(#{connection.quote_column_name(pair[0])} = #{pair[1]})"
|
122
|
+
end
|
123
|
+
where_clause = where_clause_terms.join(" AND ")
|
123
124
|
connection.update(
|
124
|
-
"UPDATE #{self.class.
|
125
|
+
"UPDATE #{self.class.quoted_table_name} " +
|
125
126
|
"SET #{quoted_comma_pair_list(connection, attributes_with_quotes(false))} " +
|
126
|
-
"WHERE #{
|
127
|
+
"WHERE #{where_clause}",
|
127
128
|
"#{self.class.name} Update"
|
128
129
|
)
|
129
130
|
return true
|
130
131
|
end
|
131
|
-
|
132
|
+
|
132
133
|
# Deletes the record in the database and freezes this instance to reflect that no changes should
|
133
134
|
# be made (since they can't be persisted).
|
134
135
|
def destroy_without_callbacks
|
135
|
-
|
136
|
-
"(#{pair[0]} = #{pair[1]})"
|
137
|
-
end
|
136
|
+
where_clause_terms = [self.class.primary_key, quoted_id].transpose.map do |pair|
|
137
|
+
"(#{connection.quote_column_name(pair[0])} = #{pair[1]})"
|
138
|
+
end
|
139
|
+
where_clause = where_clause_terms.join(" AND ")
|
138
140
|
unless new_record?
|
139
141
|
connection.delete(
|
140
|
-
"DELETE FROM #{self.class.
|
141
|
-
"WHERE #{
|
142
|
+
"DELETE FROM #{self.class.quoted_table_name} " +
|
143
|
+
"WHERE #{where_clause}",
|
142
144
|
"#{self.class.name} Destroy"
|
143
145
|
)
|
144
146
|
end
|
145
147
|
freeze
|
146
148
|
end
|
147
|
-
|
148
149
|
end
|
149
|
-
|
150
|
+
|
150
151
|
module CompositeClassMethods
|
151
152
|
def primary_key; primary_keys; end
|
152
153
|
def primary_key=(keys); primary_keys = keys; end
|
153
|
-
|
154
|
+
|
154
155
|
def composite?
|
155
156
|
true
|
156
157
|
end
|
157
|
-
|
158
|
+
|
158
159
|
#ids_to_s([[1,2],[7,3]]) -> "(1,2),(7,3)"
|
159
160
|
#ids_to_s([[1,2],[7,3]], ',', ';') -> "1,2;7,3"
|
160
161
|
def ids_to_s(many_ids, id_sep = CompositePrimaryKeys::ID_SEP, list_sep = ',', left_bracket = '(', right_bracket = ')')
|
161
162
|
many_ids.map {|ids| "#{left_bracket}#{ids}#{right_bracket}"}.join(list_sep)
|
162
163
|
end
|
163
164
|
|
165
|
+
# Creates WHERE condition from list of composited ids
|
166
|
+
# User.update_all({:role => 'admin'}, :conditions => composite_where_clause([[1, 2], [2, 2]])) #=> UPDATE admins SET admin.role='admin' WHERE (admin.type=1 AND admin.type2=2) OR (admin.type=2 AND admin.type2=2)
|
167
|
+
# User.find(:all, :conditions => composite_where_clause([[1, 2], [2, 2]])) #=> SELECT * FROM admins WHERE (admin.type=1 AND admin.type2=2) OR (admin.type=2 AND admin.type2=2)
|
168
|
+
def composite_where_clause(ids)
|
169
|
+
if ids.is_a?(String)
|
170
|
+
ids = [[ids]]
|
171
|
+
elsif not ids.first.is_a?(Array) # if single comp key passed, turn into an array of 1
|
172
|
+
ids = [ids.to_composite_ids]
|
173
|
+
end
|
174
|
+
|
175
|
+
ids.map do |id_set|
|
176
|
+
[primary_keys, id_set].transpose.map do |key, id|
|
177
|
+
"#{table_name}.#{key.to_s}=#{sanitize(id)}"
|
178
|
+
end.join(" AND ")
|
179
|
+
end.join(") OR (")
|
180
|
+
end
|
181
|
+
|
164
182
|
# Returns true if the given +ids+ represents the primary keys of a record in the database, false otherwise.
|
165
183
|
# Example:
|
166
184
|
# Person.exists?(5,7)
|
167
185
|
def exists?(ids)
|
168
186
|
obj = find(ids) rescue false
|
169
|
-
|
187
|
+
!obj.nil? and obj.is_a?(self)
|
170
188
|
end
|
171
|
-
|
189
|
+
|
172
190
|
# Deletes the record with the given +ids+ without instantiating an object first, e.g. delete(1,2)
|
173
191
|
# If an array of ids is provided (e.g. delete([1,2], [3,4]), all of them
|
174
192
|
# are deleted.
|
175
193
|
def delete(*ids)
|
176
194
|
unless ids.is_a?(Array); raise "*ids must be an Array"; end
|
177
195
|
ids = [ids.to_composite_ids] if not ids.first.is_a?(Array)
|
178
|
-
|
196
|
+
where_clause = ids.map do |id_set|
|
179
197
|
[primary_keys, id_set].transpose.map do |key, id|
|
180
|
-
"#{
|
198
|
+
"#{quoted_table_name}.#{connection.quote_column_name(key.to_s)}=#{sanitize(id)}"
|
181
199
|
end.join(" AND ")
|
182
200
|
end.join(") OR (")
|
183
|
-
delete_all([ "(#{
|
201
|
+
delete_all([ "(#{where_clause})" ])
|
184
202
|
end
|
185
|
-
|
203
|
+
|
186
204
|
# Destroys the record with the given +ids+ by instantiating the object and calling #destroy (all the callbacks are the triggered).
|
187
205
|
# If an array of ids is provided, all of them are destroyed.
|
188
206
|
def destroy(*ids)
|
@@ -194,7 +212,7 @@ module CompositePrimaryKeys
|
|
194
212
|
end
|
195
213
|
ids.first.is_a?(CompositeIds) ? ids.each { |id_set| find(id_set).destroy } : find(ids).destroy
|
196
214
|
end
|
197
|
-
|
215
|
+
|
198
216
|
# Returns an array of column objects for the table associated with this class.
|
199
217
|
# Each column that matches to one of the primary keys has its
|
200
218
|
# primary attribute set to true
|
@@ -205,7 +223,7 @@ module CompositePrimaryKeys
|
|
205
223
|
end
|
206
224
|
@columns
|
207
225
|
end
|
208
|
-
|
226
|
+
|
209
227
|
## DEACTIVATED METHODS ##
|
210
228
|
public
|
211
229
|
# Lazy-set the sequence name to the connection's default. This method
|
@@ -213,24 +231,24 @@ module CompositePrimaryKeys
|
|
213
231
|
def sequence_name #:nodoc:
|
214
232
|
raise CompositeKeyError, CompositePrimaryKeys::ActiveRecord::Base::INVALID_FOR_COMPOSITE_KEYS
|
215
233
|
end
|
216
|
-
|
234
|
+
|
217
235
|
def reset_sequence_name #:nodoc:
|
218
236
|
raise CompositeKeyError, CompositePrimaryKeys::ActiveRecord::Base::INVALID_FOR_COMPOSITE_KEYS
|
219
237
|
end
|
220
|
-
|
238
|
+
|
221
239
|
def set_primary_key(value = nil, &block)
|
222
240
|
raise CompositeKeyError, CompositePrimaryKeys::ActiveRecord::Base::INVALID_FOR_COMPOSITE_KEYS
|
223
241
|
end
|
224
|
-
|
242
|
+
|
225
243
|
private
|
226
244
|
def find_one(id, options)
|
227
245
|
raise CompositeKeyError, CompositePrimaryKeys::ActiveRecord::Base::INVALID_FOR_COMPOSITE_KEYS
|
228
246
|
end
|
229
|
-
|
247
|
+
|
230
248
|
def find_some(ids, options)
|
231
249
|
raise CompositeKeyError, CompositePrimaryKeys::ActiveRecord::Base::INVALID_FOR_COMPOSITE_KEYS
|
232
250
|
end
|
233
|
-
|
251
|
+
|
234
252
|
def find_from_ids(ids, options)
|
235
253
|
ids = ids.first if ids.last == nil
|
236
254
|
conditions = " AND (#{sanitize_sql(options[:conditions])})" if options[:conditions]
|
@@ -243,7 +261,7 @@ module CompositePrimaryKeys
|
|
243
261
|
# find '2,1;7,3' -> ids = [['2','1'],['7','3']], inner [] are CompositeIds
|
244
262
|
end
|
245
263
|
ids = [ids.to_composite_ids] if not ids.first.kind_of?(Array)
|
246
|
-
ids.each do |id_set|
|
264
|
+
ids.each do |id_set|
|
247
265
|
unless id_set.is_a?(Array)
|
248
266
|
raise "Ids must be in an Array, instead received: #{id_set.inspect}"
|
249
267
|
end
|
@@ -251,69 +269,69 @@ module CompositePrimaryKeys
|
|
251
269
|
raise "#{id_set.inspect}: Incorrect number of primary keys for #{class_name}: #{primary_keys.inspect}"
|
252
270
|
end
|
253
271
|
end
|
254
|
-
|
272
|
+
|
255
273
|
# Let keys = [:a, :b]
|
256
274
|
# If ids = [[10, 50], [11, 51]], then :conditions =>
|
257
|
-
# "(#{
|
258
|
-
|
275
|
+
# "(#{quoted_table_name}.a, #{quoted_table_name}.b) IN ((10, 50), (11, 51))"
|
276
|
+
|
259
277
|
conditions = ids.map do |id_set|
|
260
278
|
[primary_keys, id_set].transpose.map do |key, id|
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
end.join(") OR (")
|
267
|
-
options.update :conditions => "(#{conditions})"
|
268
|
-
|
269
|
-
result = find_every(options)
|
279
|
+
col = columns_hash[key.to_s]
|
280
|
+
val = quote_value(id, col)
|
281
|
+
"#{quoted_table_name}.#{connection.quote_column_name(key.to_s)}=#{val}"
|
282
|
+
end.join(" AND ")
|
283
|
+
end.join(") OR (")
|
270
284
|
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
285
|
+
options.update :conditions => "(#{conditions})"
|
286
|
+
|
287
|
+
result = find_every(options)
|
288
|
+
|
289
|
+
if result.size == ids.size
|
290
|
+
ids.size == 1 ? result[0] : result
|
291
|
+
else
|
292
|
+
raise ::ActiveRecord::RecordNotFound, "Couldn't find all #{name.pluralize} with IDs (#{ids.inspect})#{conditions}"
|
278
293
|
end
|
279
294
|
end
|
280
295
|
end
|
281
296
|
end
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
write_attribute(attr_name, value)
|
315
|
-
end
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
|
301
|
+
module ActiveRecord
|
302
|
+
ID_SEP = ','
|
303
|
+
ID_SET_SEP = ';'
|
304
|
+
|
305
|
+
class Base
|
306
|
+
# Allows +attr_name+ to be the list of primary_keys, and returns the id
|
307
|
+
# of the object
|
308
|
+
# e.g. @object[@object.class.primary_key] => [1,1]
|
309
|
+
def [](attr_name)
|
310
|
+
if attr_name.is_a?(String) and attr_name != attr_name.split(ID_SEP).first
|
311
|
+
attr_name = attr_name.split(ID_SEP)
|
312
|
+
end
|
313
|
+
attr_name.is_a?(Array) ?
|
314
|
+
attr_name.map {|name| read_attribute(name)} :
|
315
|
+
read_attribute(attr_name)
|
316
|
+
end
|
317
|
+
|
318
|
+
# Updates the attribute identified by <tt>attr_name</tt> with the specified +value+.
|
319
|
+
# (Alias for the protected write_attribute method).
|
320
|
+
def []=(attr_name, value)
|
321
|
+
if attr_name.is_a?(String) and attr_name != attr_name.split(ID_SEP).first
|
322
|
+
attr_name = attr_name.split(ID_SEP)
|
323
|
+
end
|
324
|
+
|
325
|
+
if attr_name.is_a? Array
|
326
|
+
value = value.split(ID_SEP) if value.is_a? String
|
327
|
+
unless value.length == attr_name.length
|
328
|
+
raise "Number of attr_names and values do not match"
|
316
329
|
end
|
317
|
-
|
330
|
+
#breakpoint
|
331
|
+
[attr_name, value].transpose.map {|name,val| write_attribute(name.to_s, val)}
|
332
|
+
else
|
333
|
+
write_attribute(attr_name, value)
|
318
334
|
end
|
319
335
|
end
|
336
|
+
end
|
337
|
+
end
|
@@ -5,7 +5,7 @@ module CompositePrimaryKeys
|
|
5
5
|
super
|
6
6
|
base.send(:extend, ClassMethods)
|
7
7
|
end
|
8
|
-
|
8
|
+
|
9
9
|
module ClassMethods
|
10
10
|
def construct_calculation_sql(operation, column_name, options) #:nodoc:
|
11
11
|
operation = operation.to_s.downcase
|
@@ -20,7 +20,7 @@ module CompositePrimaryKeys
|
|
20
20
|
if merged_includes.any? && operation.to_s.downcase == 'count'
|
21
21
|
options[:distinct] = true
|
22
22
|
use_workaround = !connection.supports_count_distinct?
|
23
|
-
column_name = options[:select] || primary_key.map{ |part| "#{
|
23
|
+
column_name = options[:select] || primary_key.map{ |part| "#{quoted_table_name}.#{connection.quote_column_name(part)}"}.join(',')
|
24
24
|
end
|
25
25
|
|
26
26
|
sql = "SELECT #{operation}(#{'DISTINCT ' if options[:distinct]}#{column_name}) AS #{aggregate_alias}"
|
@@ -28,9 +28,9 @@ module CompositePrimaryKeys
|
|
28
28
|
# A (slower) workaround if we're using a backend, like sqlite, that doesn't support COUNT DISTINCT.
|
29
29
|
sql = "SELECT COUNT(*) AS #{aggregate_alias}" if use_workaround
|
30
30
|
|
31
|
-
sql << ", #{options[:group_field]} AS #{options[:group_alias]}" if options[:group]
|
31
|
+
sql << ", #{connection.quote_column_name(options[:group_field])} AS #{options[:group_alias]}" if options[:group]
|
32
32
|
sql << " FROM (SELECT DISTINCT #{column_name}" if use_workaround
|
33
|
-
sql << " FROM #{
|
33
|
+
sql << " FROM #{quoted_table_name} "
|
34
34
|
if merged_includes.any?
|
35
35
|
join_dependency = ::ActiveRecord::Associations::ClassMethods::JoinDependency.new(self, merged_includes, options[:joins])
|
36
36
|
sql << join_dependency.join_associations.collect{|join| join.association_join }.join
|
@@ -38,13 +38,13 @@ module CompositePrimaryKeys
|
|
38
38
|
add_joins!(sql, options, scope)
|
39
39
|
add_conditions!(sql, options[:conditions], scope)
|
40
40
|
add_limited_ids_condition!(sql, options, join_dependency) if \
|
41
|
-
join_dependency &&
|
42
|
-
!using_limitable_reflections?(join_dependency.reflections) &&
|
41
|
+
join_dependency &&
|
42
|
+
!using_limitable_reflections?(join_dependency.reflections) &&
|
43
43
|
((scope && scope[:limit]) || options[:limit])
|
44
44
|
|
45
45
|
if options[:group]
|
46
46
|
group_key = connection.adapter_name == 'FrontBase' ? :group_alias : :group_field
|
47
|
-
sql << " GROUP BY #{options[group_key]} "
|
47
|
+
sql << " GROUP BY #{connection.quote_column_name(options[group_key])} "
|
48
48
|
end
|
49
49
|
|
50
50
|
if options[:group] && options[:having]
|
@@ -57,7 +57,7 @@ module CompositePrimaryKeys
|
|
57
57
|
sql << " HAVING #{options[:having]} "
|
58
58
|
end
|
59
59
|
|
60
|
-
sql << " ORDER BY #{options[:order]} "
|
60
|
+
sql << " ORDER BY #{options[:order]} " if options[:order]
|
61
61
|
add_limit!(sql, options, scope)
|
62
62
|
sql << ') w1' if use_workaround # assign a dummy table name as required for postgresql
|
63
63
|
sql
|