composite_primary_keys 8.1.8 → 9.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/History.rdoc +3 -25
- data/README.rdoc +1 -0
- data/README_DB2.rdoc +33 -33
- data/Rakefile +34 -34
- data/lib/composite_primary_keys.rb +4 -11
- data/lib/composite_primary_keys/associations/association.rb +14 -12
- data/lib/composite_primary_keys/associations/association_scope.rb +27 -54
- data/lib/composite_primary_keys/associations/collection_association.rb +22 -8
- data/lib/composite_primary_keys/associations/has_many_association.rb +16 -54
- data/lib/composite_primary_keys/associations/has_many_through_association.rb +58 -58
- data/lib/composite_primary_keys/associations/join_dependency.rb +74 -56
- data/lib/composite_primary_keys/associations/join_dependency/join_association.rb +13 -11
- data/lib/composite_primary_keys/associations/preloader/association.rb +75 -72
- data/lib/composite_primary_keys/associations/singular_association.rb +8 -12
- data/lib/composite_primary_keys/attribute_methods.rb +6 -4
- data/lib/composite_primary_keys/attribute_methods/primary_key.rb +13 -11
- data/lib/composite_primary_keys/attribute_methods/read.rb +16 -15
- data/lib/composite_primary_keys/attribute_methods/write.rb +21 -19
- data/lib/composite_primary_keys/attribute_set/builder.rb +13 -11
- data/lib/composite_primary_keys/base.rb +5 -69
- data/lib/composite_primary_keys/composite_arrays.rb +8 -51
- data/lib/composite_primary_keys/composite_predicates.rb +7 -16
- data/lib/composite_primary_keys/connection_adapters/abstract_adapter.rb +10 -10
- data/lib/composite_primary_keys/connection_adapters/postgresql_adapter.rb +42 -11
- data/lib/composite_primary_keys/core.rb +46 -45
- data/lib/composite_primary_keys/dirty.rb +19 -19
- data/lib/composite_primary_keys/fixtures.rb +19 -17
- data/lib/composite_primary_keys/locking/optimistic.rb +48 -44
- data/lib/composite_primary_keys/nested_attributes.rb +64 -53
- data/lib/composite_primary_keys/persistence.rb +49 -41
- data/lib/composite_primary_keys/relation.rb +22 -47
- data/lib/composite_primary_keys/relation/batches.rb +33 -30
- data/lib/composite_primary_keys/relation/calculations.rb +3 -7
- data/lib/composite_primary_keys/relation/finder_methods.rb +123 -56
- data/lib/composite_primary_keys/relation/predicate_builder.rb +18 -29
- data/lib/composite_primary_keys/relation/where_clause.rb +33 -0
- data/lib/composite_primary_keys/sanitization.rb +45 -38
- data/lib/composite_primary_keys/validations/uniqueness.rb +37 -37
- data/lib/composite_primary_keys/version.rb +4 -4
- data/scripts/console.rb +48 -48
- data/scripts/txt2html +76 -76
- data/scripts/txt2js +65 -65
- data/tasks/databases/mysql.rake +42 -42
- data/tasks/databases/postgresql.rake +47 -47
- data/tasks/databases/sqlite3.rake +27 -27
- data/tasks/website.rake +18 -18
- data/test/README_tests.rdoc +56 -56
- data/test/abstract_unit.rb +10 -9
- data/test/connections/connection_spec.rb +18 -18
- data/test/connections/databases.yml +9 -39
- data/test/connections/native_ibm_db/connection.rb +18 -18
- data/test/connections/native_mysql/connection.rb +17 -17
- data/test/connections/native_postgresql/connection.rb +12 -12
- data/test/connections/native_sqlite3/connection.rb +9 -9
- data/test/db_test.rb +52 -52
- data/test/fixtures/article.rb +5 -5
- data/test/fixtures/articles.yml +6 -6
- data/test/fixtures/capitol.rb +3 -3
- data/test/fixtures/capitols.yml +16 -16
- data/test/fixtures/comments.yml +15 -15
- data/test/fixtures/db_definitions/mysql.sql +2 -12
- data/test/fixtures/db_definitions/oracle.sql +1 -2
- data/test/fixtures/db_definitions/postgresql.sql +0 -10
- data/test/fixtures/db_definitions/sqlite.sql +0 -9
- data/test/fixtures/db_definitions/sqlserver.sql +1 -2
- data/test/fixtures/department.rb +5 -5
- data/test/fixtures/departments.yml +15 -15
- data/test/fixtures/dorms.yml +4 -4
- data/test/fixtures/employee.rb +1 -2
- data/test/fixtures/employees.yml +19 -23
- data/test/fixtures/group.rb +2 -2
- data/test/fixtures/groups.yml +6 -6
- data/test/fixtures/hack.rb +4 -4
- data/test/fixtures/hacks.yml +2 -2
- data/test/fixtures/membership_status.rb +2 -2
- data/test/fixtures/product.rb +9 -9
- data/test/fixtures/product_tariff.rb +5 -5
- data/test/fixtures/products.yml +11 -11
- data/test/fixtures/reading.rb +4 -4
- data/test/fixtures/readings.yml +10 -10
- data/test/fixtures/reference_code_using_composite_key_alias.rb +8 -8
- data/test/fixtures/reference_code_using_simple_key_alias.rb +8 -8
- data/test/fixtures/reference_codes.yml +28 -28
- data/test/fixtures/reference_type.rb +1 -1
- data/test/fixtures/reference_types.yml +9 -9
- data/test/fixtures/restaurant.rb +9 -9
- data/test/fixtures/restaurants.yml +14 -14
- data/test/fixtures/restaurants_suburbs.yml +10 -10
- data/test/fixtures/room.rb +11 -11
- data/test/fixtures/room_assignment.rb +13 -13
- data/test/fixtures/room_assignments.yml +24 -24
- data/test/fixtures/room_attribute.rb +2 -2
- data/test/fixtures/room_attribute_assignment.rb +4 -4
- data/test/fixtures/room_attribute_assignments.yml +4 -4
- data/test/fixtures/room_attributes.yml +2 -2
- data/test/fixtures/rooms.yml +12 -12
- data/test/fixtures/seat.rb +5 -5
- data/test/fixtures/seats.yml +8 -8
- data/test/fixtures/street.rb +2 -2
- data/test/fixtures/streets.yml +16 -16
- data/test/fixtures/student.rb +3 -3
- data/test/fixtures/students.yml +15 -15
- data/test/fixtures/suburbs.yml +14 -14
- data/test/fixtures/tariff.rb +5 -5
- data/test/fixtures/tariffs.yml +14 -14
- data/test/fixtures/user.rb +0 -1
- data/test/plugins/pagination.rb +405 -405
- data/test/plugins/pagination_helper.rb +135 -135
- data/test/setup.rb +50 -50
- data/test/test_aliases.rb +18 -18
- data/test/test_associations.rb +7 -18
- data/test/test_composite_arrays.rb +24 -38
- data/test/test_counter_cache.rb +30 -30
- data/test/test_create.rb +5 -5
- data/test/test_delete_all.rb +7 -13
- data/test/test_dup.rb +37 -37
- data/test/test_exists.rb +39 -39
- data/test/test_find.rb +16 -12
- data/test/test_habtm.rb +26 -2
- data/test/test_ids.rb +109 -116
- data/test/test_miscellaneous.rb +32 -32
- data/test/test_pagination.rb +35 -35
- data/test/test_polymorphic.rb +0 -7
- data/test/test_predicates.rb +9 -28
- data/test/test_update.rb +3 -5
- data/test/test_validations.rb +13 -13
- metadata +24 -32
- data/lib/composite_primary_keys/arel/visitors/to_sql.rb +0 -36
- data/lib/composite_primary_keys/attribute_methods/dirty.rb +0 -29
- data/lib/composite_primary_keys/autosave_association.rb +0 -67
- data/lib/composite_primary_keys/connection_adapters/abstract_mysql_adapter.rb +0 -23
- data/test/fixtures/pk_called_id.rb +0 -5
- data/test/fixtures/pk_called_ids.yml +0 -11
- data/test/test_find_in_batches.rb +0 -30
- data/test/test_update_all.rb +0 -17
@@ -1,18 +1,14 @@
|
|
1
1
|
module CompositePrimaryKeys
|
2
2
|
module SingularAssociation
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
return scope.limit(1).to_a if cpk_applies
|
11
|
-
get_records_without_cpk_support
|
12
|
-
end
|
13
|
-
alias_method_chain :get_records, :cpk_support
|
3
|
+
def get_records
|
4
|
+
cpk_applies = (target && target.composite?) ||
|
5
|
+
(owner && owner.composite?) ||
|
6
|
+
(options[:primary_key] && options[:primary_key].kind_of?(Array)) ||
|
7
|
+
(options[:foreign_key] && options[:foreign_key].kind_of?(Array))
|
8
|
+
return scope.limit(1).to_a if cpk_applies
|
9
|
+
super
|
14
10
|
end
|
15
11
|
end
|
16
12
|
end
|
17
13
|
|
18
|
-
ActiveRecord::Associations::SingularAssociation.
|
14
|
+
ActiveRecord::Associations::SingularAssociation.prepend CompositePrimaryKeys::SingularAssociation
|
@@ -1,9 +1,11 @@
|
|
1
1
|
module ActiveRecord
|
2
2
|
module AttributeMethods
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
silence_warnings do
|
4
|
+
def has_attribute?(attr_name)
|
5
|
+
# CPK
|
6
|
+
# @attributes.key?(attr_name.to_s)
|
7
|
+
Array(attr_name).all?{|single_attr| @attributes.key?(single_attr.to_s) }
|
8
|
+
end
|
7
9
|
end
|
8
10
|
end
|
9
11
|
end
|
@@ -1,19 +1,21 @@
|
|
1
1
|
module ActiveRecord
|
2
2
|
module AttributeMethods
|
3
3
|
module PrimaryKey
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
self.
|
11
|
-
|
4
|
+
silence_warnings do
|
5
|
+
# Returns the primary key previous value.
|
6
|
+
def id_was
|
7
|
+
sync_with_transaction_state
|
8
|
+
# CPK
|
9
|
+
# attribute_was(self.class.primary_key)
|
10
|
+
if self.composite?
|
11
|
+
self.class.primary_keys.map do |key_attr|
|
12
|
+
attribute_changed?(key_attr) ? changed_attributes[key_attr] : self.ids_hash[key_attr]
|
13
|
+
end
|
14
|
+
else
|
15
|
+
attribute_was(self.class.primary_key)
|
12
16
|
end
|
13
|
-
else
|
14
|
-
attribute_was(self.class.primary_key)
|
15
|
-
end
|
16
17
|
|
18
|
+
end
|
17
19
|
end
|
18
20
|
end
|
19
21
|
end
|
@@ -1,24 +1,25 @@
|
|
1
1
|
module ActiveRecord
|
2
2
|
module AttributeMethods
|
3
3
|
module Read
|
4
|
-
|
5
|
-
|
6
|
-
if attr_name.kind_of?(Array)
|
7
|
-
_read_attribute(attr_name, &block)
|
8
|
-
else
|
9
|
-
name = attr_name.to_s
|
4
|
+
silence_warnings do
|
5
|
+
def read_attribute(attr_name, &block)
|
10
6
|
# CPK
|
11
|
-
|
12
|
-
|
7
|
+
if attr_name.kind_of?(Array) || attr_name.to_s == 'id'.freeze && @attributes.key?('id')
|
8
|
+
_read_attribute(attr_name, &block)
|
9
|
+
else
|
10
|
+
name = attr_name.to_s
|
11
|
+
name = self.class.primary_key if name == 'id'.freeze
|
12
|
+
_read_attribute(name, &block)
|
13
|
+
end
|
13
14
|
end
|
14
|
-
end
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
16
|
+
def _read_attribute(attr_name)
|
17
|
+
# CPK
|
18
|
+
if attr_name.kind_of?(Array)
|
19
|
+
attr_name.map {|name| @attributes.fetch_value(name.to_s)}
|
20
|
+
else
|
21
|
+
@attributes.fetch_value(attr_name.to_s) { |n| yield n if block_given? }
|
22
|
+
end
|
22
23
|
end
|
23
24
|
end
|
24
25
|
end
|
@@ -1,28 +1,30 @@
|
|
1
1
|
module ActiveRecord
|
2
2
|
module AttributeMethods
|
3
3
|
module Write
|
4
|
-
|
5
|
-
|
6
|
-
if attr_name.kind_of?(Array)
|
7
|
-
value = [nil]*attr_name.length if value.nil?
|
8
|
-
unless value.length == attr_name.length
|
9
|
-
raise "Number of attr_names #{attr_name.inspect} and values #{value.inspect} do not match"
|
10
|
-
end
|
11
|
-
[attr_name, value].transpose.map {|name,val| write_attribute(name, val)}
|
12
|
-
value
|
13
|
-
else
|
14
|
-
attr_name = attr_name.to_s
|
4
|
+
silence_warnings do
|
5
|
+
def write_attribute_with_type_cast(attr_name, value, should_type_cast)
|
15
6
|
# CPK
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
7
|
+
if attr_name.kind_of?(Array)
|
8
|
+
value = [nil]*attr_name.length if value.nil?
|
9
|
+
unless value.length == attr_name.length
|
10
|
+
raise "Number of attr_names #{attr_name.inspect} and values #{value.inspect} do not match"
|
11
|
+
end
|
12
|
+
[attr_name, value].transpose.map {|name,val| write_attribute(name, val)}
|
13
|
+
value
|
21
14
|
else
|
22
|
-
|
23
|
-
|
15
|
+
attr_name = attr_name.to_s
|
16
|
+
# CPK
|
17
|
+
# attr_name = self.class.primary_key if attr_name == 'id' && self.class.primary_key
|
18
|
+
attr_name = self.class.primary_key if attr_name == 'id' && self.class.primary_key && !self.composite?
|
24
19
|
|
25
|
-
|
20
|
+
if should_type_cast
|
21
|
+
@attributes.write_from_user(attr_name, value)
|
22
|
+
else
|
23
|
+
@attributes.write_cast_value(attr_name, value)
|
24
|
+
end
|
25
|
+
|
26
|
+
value
|
27
|
+
end
|
26
28
|
end
|
27
29
|
end
|
28
30
|
end
|
@@ -1,19 +1,21 @@
|
|
1
1
|
module ActiveRecord
|
2
2
|
class AttributeSet # :nodoc:
|
3
3
|
class Builder # :nodoc:
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
4
|
+
silence_warnings do
|
5
|
+
def build_from_database(values = {}, additional_types = {})
|
6
|
+
# CPK
|
7
|
+
# if always_initialized && !values.key?(always_initialized)
|
8
|
+
# values[always_initialized] = nil
|
9
|
+
# end
|
10
|
+
Array(always_initialized).each do |always_initialized_attribute|
|
11
|
+
if always_initialized_attribute && !values.key?(always_initialized_attribute)
|
12
|
+
values[always_initialized_attribute] = nil
|
13
|
+
end
|
12
14
|
end
|
15
|
+
|
16
|
+
attributes = LazyAttributeHash.new(types, values, additional_types)
|
17
|
+
AttributeSet.new(attributes)
|
13
18
|
end
|
14
|
-
|
15
|
-
attributes = LazyAttributeHash.new(types, values, additional_types)
|
16
|
-
AttributeSet.new(attributes)
|
17
19
|
end
|
18
20
|
end
|
19
21
|
end
|
@@ -21,7 +21,8 @@ module ActiveRecord
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
-
|
24
|
+
alias_method :primary_key_without_composite_key_support=, :primary_key=
|
25
|
+
def primary_key=(keys)
|
25
26
|
unless keys.kind_of?(Array)
|
26
27
|
self.primary_key_without_composite_key_support = keys
|
27
28
|
return
|
@@ -34,7 +35,6 @@ module ActiveRecord
|
|
34
35
|
include CompositeInstanceMethods
|
35
36
|
EOV
|
36
37
|
end
|
37
|
-
alias_method_chain :primary_key=, :composite_key_support
|
38
38
|
alias_method :primary_keys=, :primary_key=
|
39
39
|
|
40
40
|
def set_primary_keys(*keys)
|
@@ -48,75 +48,11 @@ module ActiveRecord
|
|
48
48
|
else
|
49
49
|
self.primary_keys = keys
|
50
50
|
end
|
51
|
-
|
51
|
+
end
|
52
52
|
|
53
53
|
def composite?
|
54
54
|
false
|
55
55
|
end
|
56
|
-
|
57
|
-
def find_in_batches(options = {})
|
58
|
-
return super unless primary_key.is_a?(Array)
|
59
|
-
|
60
|
-
# Unfortunately .count uses a subquery temp table, which is a big problem when your table is large
|
61
|
-
number_of_rows = count(primary_key.first)
|
62
|
-
batch_size = options[:batch_size] || 100000
|
63
|
-
row_number = 0
|
64
|
-
|
65
|
-
while row_number < number_of_rows
|
66
|
-
end_row_number = row_number + batch_size - 1
|
67
|
-
end_row_number = number_of_rows - 1 if end_row_number > number_of_rows - 1
|
68
|
-
|
69
|
-
# Force the necessary sorting; AR as is will sort a PK table incorrectly
|
70
|
-
start_key = order(*primary_key).
|
71
|
-
offset(row_number).
|
72
|
-
first.
|
73
|
-
attributes.
|
74
|
-
slice(*primary_key)
|
75
|
-
|
76
|
-
end_key = order(*(primary_key.map { |k| "#{k} ASC" })).
|
77
|
-
offset(end_row_number).
|
78
|
-
first.
|
79
|
-
attributes.
|
80
|
-
slice(*primary_key)
|
81
|
-
|
82
|
-
relation = self
|
83
|
-
lower_bounds = []
|
84
|
-
upper_bounds = []
|
85
|
-
|
86
|
-
# Iterate through the PKs positionally; when we have found a discrepancy between start and end
|
87
|
-
# then we know that's where the boundaries are
|
88
|
-
primary_key.each do |col|
|
89
|
-
if start_key[col] == end_key[col]
|
90
|
-
relation = relation.where("#{col} = '#{start_key[col]}'")
|
91
|
-
else
|
92
|
-
lower_bounds << [col, start_key[col]]
|
93
|
-
upper_bounds << [col, end_key[col]]
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
relation = relation.where(build_batch_case(lower_bounds, '>')) unless lower_bounds.empty?
|
98
|
-
relation = relation.where(build_batch_case(upper_bounds, '<')) unless upper_bounds.empty?
|
99
|
-
|
100
|
-
yield(relation.order(*primary_key))
|
101
|
-
|
102
|
-
row_number = end_row_number + 1
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
private
|
107
|
-
|
108
|
-
def build_batch_case(bounds, operator)
|
109
|
-
bounds = bounds.dup
|
110
|
-
bound = bounds.shift
|
111
|
-
if bounds.empty?
|
112
|
-
"#{bound[0]} #{operator}= '#{bound[1]}' "
|
113
|
-
else
|
114
|
-
sql_case = "CASE WHEN #{bound[0]} = '#{bound[1]}' THEN "
|
115
|
-
sql_case += build_batch_case(bounds, operator)
|
116
|
-
sql_case += "ELSE #{bound[0]} #{operator} '#{bound[1]}' END "
|
117
|
-
sql_case
|
118
|
-
end
|
119
|
-
end
|
120
56
|
end
|
121
57
|
|
122
58
|
def composite?
|
@@ -129,7 +65,7 @@ module ActiveRecord
|
|
129
65
|
end
|
130
66
|
|
131
67
|
def primary_key=(keys)
|
132
|
-
primary_keys = keys
|
68
|
+
self.primary_keys = keys
|
133
69
|
end
|
134
70
|
|
135
71
|
def composite?
|
@@ -186,7 +122,7 @@ module ActiveRecord
|
|
186
122
|
end
|
187
123
|
|
188
124
|
def to_param
|
189
|
-
persisted? ? to_key.
|
125
|
+
persisted? ? to_key.join(CompositePrimaryKeys::ID_SEP) : nil
|
190
126
|
end
|
191
127
|
end
|
192
128
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
module CompositePrimaryKeys
|
2
2
|
ID_SEP = ','
|
3
3
|
ID_SET_SEP = ';'
|
4
|
-
ESCAPE_CHAR = '^'
|
5
4
|
|
6
5
|
module ArrayExtension
|
7
6
|
def to_composite_keys
|
@@ -9,27 +8,12 @@ module CompositePrimaryKeys
|
|
9
8
|
end
|
10
9
|
end
|
11
10
|
|
12
|
-
|
13
|
-
# representation (just by arrays).
|
14
|
-
#
|
15
|
-
# `ids` is Array that may contain:
|
16
|
-
# 1. A CPK represented by an array or a string.
|
17
|
-
# 2. An array of CPKs represented by arrays or strings.
|
18
|
-
#
|
19
|
-
# There is an issue. Let `ids` contain an array with serveral strings. We can't distinguish case 1
|
20
|
-
# from case 2 there in general. E.g. the item can be an array containing appropriate number of strings,
|
21
|
-
# and each string can contain appropriate number of commas. We consider case 2 to win there.
|
22
|
-
def self.normalize(ids, cpk_size)
|
11
|
+
def self.normalize(ids)
|
23
12
|
ids.map do |id|
|
24
|
-
if
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
# An array of CPKs - case 2
|
29
|
-
normalize(id, cpk_size)
|
30
|
-
elsif id.is_a?(String)
|
31
|
-
# CPK as a string - case 1
|
32
|
-
CompositeKeys.parse(id)
|
13
|
+
if id.is_a?(Array)
|
14
|
+
normalize(id)
|
15
|
+
elsif id.is_a?(String) && id.index(ID_SEP)
|
16
|
+
id.split(ID_SEP)
|
33
17
|
else
|
34
18
|
id
|
35
19
|
end
|
@@ -38,12 +22,12 @@ module CompositePrimaryKeys
|
|
38
22
|
|
39
23
|
class CompositeKeys < Array
|
40
24
|
|
41
|
-
|
25
|
+
def self.parse(value)
|
42
26
|
case value
|
43
27
|
when Array
|
44
28
|
value.to_composite_keys
|
45
29
|
when String
|
46
|
-
value.split(ID_SEP)
|
30
|
+
self.new(value.split(ID_SEP))
|
47
31
|
else
|
48
32
|
raise(ArgumentError, "Unsupported type: #{value}")
|
49
33
|
end
|
@@ -51,36 +35,9 @@ module CompositePrimaryKeys
|
|
51
35
|
|
52
36
|
def to_s
|
53
37
|
# Doing this makes it easier to parse Base#[](attr_name)
|
54
|
-
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
module Utils
|
59
|
-
class << self
|
60
|
-
def escape_string_key(key)
|
61
|
-
key.gsub(Regexp.union(ESCAPE_CHAR, ID_SEP)) do |unsafe|
|
62
|
-
"#{ESCAPE_CHAR}#{unsafe.ord.to_s(16).upcase}"
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
def unescape_string_key(key)
|
67
|
-
key.gsub(/#{Regexp.escape(ESCAPE_CHAR)}[0-9a-fA-F]{2}/) do |escaped|
|
68
|
-
char = escaped.slice(1, 2).hex.chr
|
69
|
-
(char == ESCAPE_CHAR || char == ID_SEP) ? char : escaped
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
def cpk_as_array?(value, pk_size)
|
74
|
-
# We don't permit Array to be an element of CPK.
|
75
|
-
value.is_a?(Array) && value.size == pk_size && value.none? { |item| item.is_a?(Array) }
|
76
|
-
end
|
77
|
-
|
78
|
-
def cpk_as_string?(value, pk_size)
|
79
|
-
value.is_a?(String) && value.count(ID_SEP) == pk_size - 1
|
80
|
-
end
|
38
|
+
join(ID_SEP)
|
81
39
|
end
|
82
40
|
end
|
83
|
-
private_constant :Utils
|
84
41
|
end
|
85
42
|
|
86
43
|
Array.send(:include, CompositePrimaryKeys::ArrayExtension)
|
@@ -8,23 +8,13 @@ module CompositePrimaryKeys
|
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
|
-
def cpk_or_predicate(predicates
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
predicates_first_half = predicates[0...split_point]
|
17
|
-
predicates_second_half = predicates[split_point..-1]
|
18
|
-
|
19
|
-
or_predicate = ::Arel::Nodes::Or.new(cpk_or_predicate(predicates_first_half, false),
|
20
|
-
cpk_or_predicate(predicates_second_half, false))
|
21
|
-
|
22
|
-
if group
|
23
|
-
::Arel::Nodes::Grouping.new(or_predicate)
|
24
|
-
else
|
25
|
-
or_predicate
|
26
|
-
end
|
11
|
+
def cpk_or_predicate(predicates)
|
12
|
+
or_predicate = predicates.map do |predicate|
|
13
|
+
::Arel::Nodes::Grouping.new(predicate)
|
14
|
+
end.inject do |memo, node|
|
15
|
+
::Arel::Nodes::Or.new(memo, node)
|
27
16
|
end
|
17
|
+
::Arel::Nodes::Grouping.new(or_predicate)
|
28
18
|
end
|
29
19
|
|
30
20
|
def cpk_id_predicate(table, keys, values)
|
@@ -39,6 +29,7 @@ module CompositePrimaryKeys
|
|
39
29
|
key2_fields = Array(key2).map {|key| table2[key]}
|
40
30
|
|
41
31
|
eq_predicates = key1_fields.zip(key2_fields).map do |key_field1, key_field2|
|
32
|
+
key_field2 = Arel::Nodes::Quoted.new(key_field2) unless Arel::Attributes::Attribute === key_field2
|
42
33
|
key_field1.eq(key_field2)
|
43
34
|
end
|
44
35
|
cpk_and_predicate(eq_predicates)
|
@@ -1,11 +1,11 @@
|
|
1
|
-
module ActiveRecord
|
2
|
-
module ConnectionAdapters
|
3
|
-
class AbstractAdapter
|
4
|
-
def quote_column_names(name)
|
5
|
-
Array(name).map do |col|
|
6
|
-
quote_column_name(col.to_s)
|
7
|
-
end.
|
8
|
-
end
|
9
|
-
end
|
10
|
-
end
|
1
|
+
module ActiveRecord
|
2
|
+
module ConnectionAdapters
|
3
|
+
class AbstractAdapter
|
4
|
+
def quote_column_names(name)
|
5
|
+
Array(name).map do |col|
|
6
|
+
quote_column_name(col.to_s)
|
7
|
+
end.join(CompositePrimaryKeys::ID_SEP)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
11
|
end
|