composite_primary_keys 11.3.1 → 12.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/History.rdoc +17 -7
- data/README.rdoc +1 -0
- data/lib/composite_primary_keys.rb +1 -6
- data/lib/composite_primary_keys/arel/to_sql.rb +13 -13
- data/lib/composite_primary_keys/associations/association_scope.rb +4 -4
- data/lib/composite_primary_keys/associations/has_many_association.rb +2 -1
- data/lib/composite_primary_keys/associations/has_many_through_association.rb +0 -2
- data/lib/composite_primary_keys/associations/join_dependency.rb +9 -8
- data/lib/composite_primary_keys/associations/preloader/association.rb +28 -36
- data/lib/composite_primary_keys/attribute_methods.rb +2 -2
- data/lib/composite_primary_keys/attribute_methods/read.rb +11 -14
- data/lib/composite_primary_keys/attribute_methods/write.rb +8 -11
- data/lib/composite_primary_keys/base.rb +2 -2
- data/lib/composite_primary_keys/composite_arrays.rb +7 -50
- data/lib/composite_primary_keys/connection_adapters/abstract_adapter.rb +1 -1
- data/lib/composite_primary_keys/connection_adapters/postgresql/database_statements.rb +1 -1
- data/lib/composite_primary_keys/core.rb +10 -14
- data/lib/composite_primary_keys/counter_cache.rb +4 -22
- data/lib/composite_primary_keys/fixtures.rb +5 -10
- data/lib/composite_primary_keys/nested_attributes.rb +6 -6
- data/lib/composite_primary_keys/persistence.rb +8 -8
- data/lib/composite_primary_keys/reflection.rb +3 -3
- data/lib/composite_primary_keys/relation.rb +39 -27
- data/lib/composite_primary_keys/relation/calculations.rb +15 -18
- data/lib/composite_primary_keys/relation/finder_methods.rb +56 -58
- data/lib/composite_primary_keys/relation/query_methods.rb +4 -3
- data/lib/composite_primary_keys/relation/where_clause.rb +2 -2
- data/lib/composite_primary_keys/sanitization.rb +37 -37
- data/lib/composite_primary_keys/validations/uniqueness.rb +2 -2
- data/lib/composite_primary_keys/version.rb +4 -4
- data/tasks/databases/mysql.rake +1 -1
- data/test/abstract_unit.rb +1 -5
- data/test/connections/databases.ci.yml +3 -0
- data/test/db_test.rb +53 -0
- data/test/fixtures/db_definitions/mysql.sql +1 -7
- data/test/fixtures/db_definitions/oracle.drop.sql +1 -3
- data/test/fixtures/db_definitions/oracle.sql +0 -8
- data/test/fixtures/db_definitions/postgresql.sql +0 -6
- data/test/fixtures/db_definitions/sqlite.sql +0 -6
- data/test/fixtures/db_definitions/sqlserver.sql +1 -8
- data/test/test_associations.rb +1 -1
- data/test/test_composite_arrays.rb +0 -14
- data/test/test_create.rb +12 -26
- data/test/test_find.rb +0 -8
- data/test/test_ids.rb +0 -3
- data/test/test_nested_attributes.rb +10 -10
- data/test/test_update.rb +1 -1
- metadata +9 -11
- data/lib/composite_primary_keys/connection_adapters/abstract_mysql_adapter.rb +0 -20
- data/lib/composite_primary_keys/connection_adapters/sqlite3_adapter.rb +0 -23
- data/test/fixtures/cpk_with_default_value.rb +0 -3
- data/test/fixtures/cpk_with_default_values.yml +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 540c65209855565625538300ca62ea930ad91494d7a307dbd4db0419a17e576f
|
4
|
+
data.tar.gz: 9bd63c5ffb21a79abb6f4159ddc0245144406e33f1969801f1d9d3176fdf1e2f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 627e469ec7fe07987605b21f156dc042611af0a31282bc711b078479617c5eebeae770f27ec5de3158f686cb7dd4b175b1729dc0116f46e87894d19dc5482292
|
7
|
+
data.tar.gz: 5038fb2ff8282164c9daf3f5b8123d441c3ea50a126222619f12cdaed9118112a7c2f469b90ffb20b482d5e0a1467e3aabf7b5e14e39208a5972ce3b73717633
|
data/History.rdoc
CHANGED
@@ -1,10 +1,6 @@
|
|
1
|
-
==
|
2
|
-
*
|
3
|
-
*
|
4
|
-
* Fixed incorrect SQL condition for joining by CPK (Sergey Semyonov)
|
5
|
-
* Update travis.yml file (Sergey Semyonov)
|
6
|
-
* Add tests for composite keys with default values (Daniel Wiklund)
|
7
|
-
* Fix create record where one or more of the primary keys has a default value (Daniel Wiklund)
|
1
|
+
== 12.0.0 (?)
|
2
|
+
* Update to ActiveRecord 6.0 (Hiroshi Kajisha, Alexandru Anca, Charlie Savage)
|
3
|
+
* Update travis setup (Olle Jonsson)
|
8
4
|
|
9
5
|
== 11.2.0 (2019-03-16)
|
10
6
|
* When creating new records, honor composite key autoincrementing fields if possible (Antti Pitkänen)
|
@@ -146,6 +142,20 @@
|
|
146
142
|
== 9.0.0.beta1 (2016-04-16)
|
147
143
|
* Rails 5 beta support (Sammy Larbi)
|
148
144
|
|
145
|
+
== 8.1.7 (2019-05-04)
|
146
|
+
|
147
|
+
Fix key not being an array in subquery on has_many :through (Eric Proulx)
|
148
|
+
Convert batches to arrays before continuing loop (Jeremy Mickelson)
|
149
|
+
|
150
|
+
== 8.1.6 (2017-05-20)
|
151
|
+
|
152
|
+
Query cache with bind params (ttw)
|
153
|
+
Fix TestIds#test_set_ids_string. Sqlite's serial and integer are a bit different (Boris Peterbarg)
|
154
|
+
Associations with inverse fix (Boris Peterbarg)
|
155
|
+
Fix save_has_one_association and add a test for it (Boris Peterbarg)
|
156
|
+
Fix save_belongs_to_association override (Boris Peterbarg)
|
157
|
+
Extend approach from #344 to fix autosave for has_one associations as well (Cameron Finucane)
|
158
|
+
|
149
159
|
== 8.1.5 (2017-01-01)
|
150
160
|
|
151
161
|
* Don't nest PK twice when looking up id, fixes #319 (Kerey Roper)
|
data/README.rdoc
CHANGED
@@ -20,6 +20,7 @@ Every major version of ActiveRecord has included numerous internal changes. As
|
|
20
20
|
CPK has to be rewritten for each version of ActiveRecord. To help keep
|
21
21
|
things straight, here is the mapping:
|
22
22
|
|
23
|
+
Version 12.x is designed to work with ActiveRecord 6.0.x
|
23
24
|
Version 11.x is designed to work with ActiveRecord 5.2.x
|
24
25
|
Version 10.x is designed to work with ActiveRecord 5.1.x
|
25
26
|
Version 9.x is designed to work with ActiveRecord 5.0.x
|
@@ -26,7 +26,7 @@ $:.unshift(File.dirname(__FILE__)) unless
|
|
26
26
|
|
27
27
|
unless defined?(ActiveRecord)
|
28
28
|
require 'rubygems'
|
29
|
-
gem 'activerecord', '
|
29
|
+
gem 'activerecord', '6.0.0.rc1'
|
30
30
|
require 'active_record'
|
31
31
|
end
|
32
32
|
|
@@ -59,13 +59,9 @@ require 'active_record/nested_attributes'
|
|
59
59
|
|
60
60
|
require 'active_record/connection_adapters/abstract/database_statements'
|
61
61
|
require 'active_record/connection_adapters/abstract_adapter'
|
62
|
-
require 'active_record/connection_adapters/abstract_mysql_adapter'
|
63
62
|
require 'active_record/connection_adapters/postgresql/database_statements'
|
64
63
|
|
65
64
|
require 'active_record/relation/where_clause'
|
66
|
-
require 'active_record/relation/predicate_builder/association_query_value'
|
67
|
-
|
68
|
-
require 'active_record/validations/uniqueness'
|
69
65
|
|
70
66
|
# CPK files
|
71
67
|
require 'composite_primary_keys/persistence'
|
@@ -99,7 +95,6 @@ require 'composite_primary_keys/nested_attributes'
|
|
99
95
|
|
100
96
|
require 'composite_primary_keys/connection_adapters/abstract/database_statements'
|
101
97
|
require 'composite_primary_keys/connection_adapters/abstract_adapter'
|
102
|
-
require 'composite_primary_keys/connection_adapters/abstract_mysql_adapter'
|
103
98
|
require 'composite_primary_keys/connection_adapters/postgresql/database_statements'
|
104
99
|
require 'composite_primary_keys/connection_adapters/sqlserver/database_statements'
|
105
100
|
|
@@ -1,19 +1,19 @@
|
|
1
1
|
module Arel
|
2
2
|
module Visitors
|
3
3
|
class ToSql
|
4
|
-
def visit_Arel_Nodes_In o, collector
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
end
|
4
|
+
# def visit_Arel_Nodes_In o, collector
|
5
|
+
# if Array === o.right && o.right.empty?
|
6
|
+
# collector << '1=0'
|
7
|
+
# else
|
8
|
+
# # CPK
|
9
|
+
# collector << "("
|
10
|
+
# collector = visit o.left, collector
|
11
|
+
# # CPK
|
12
|
+
# collector << ")"
|
13
|
+
# collector << " IN ("
|
14
|
+
# visit(o.right, collector) << ")"
|
15
|
+
# end
|
16
|
+
# end
|
17
17
|
|
18
18
|
def visit_CompositePrimaryKeys_CompositeKeys o, collector
|
19
19
|
values = o.map do |key|
|
@@ -11,12 +11,12 @@ module ActiveRecord
|
|
11
11
|
binds += Array(values)
|
12
12
|
|
13
13
|
if last_reflection.type
|
14
|
-
binds << owner.class.
|
14
|
+
binds << owner.class.polymorphic_name
|
15
15
|
end
|
16
16
|
|
17
17
|
chain.each_cons(2).each do |reflection, next_reflection|
|
18
18
|
if reflection.type
|
19
|
-
binds << next_reflection.klass.
|
19
|
+
binds << next_reflection.klass.polymorphic_name
|
20
20
|
end
|
21
21
|
end
|
22
22
|
binds
|
@@ -38,7 +38,7 @@ module ActiveRecord
|
|
38
38
|
end
|
39
39
|
|
40
40
|
if reflection.type
|
41
|
-
polymorphic_type = transform_value(owner.class.
|
41
|
+
polymorphic_type = transform_value(owner.class.polymorphic_name)
|
42
42
|
scope = apply_scope(scope, table, reflection.type, polymorphic_type)
|
43
43
|
end
|
44
44
|
|
@@ -58,7 +58,7 @@ module ActiveRecord
|
|
58
58
|
constraint = cpk_join_predicate(table, key, foreign_table, foreign_key)
|
59
59
|
|
60
60
|
if reflection.type
|
61
|
-
value = transform_value(next_reflection.klass.
|
61
|
+
value = transform_value(next_reflection.klass.polymorphic_name)
|
62
62
|
scope = apply_scope(scope, table, reflection.type, value)
|
63
63
|
end
|
64
64
|
|
@@ -21,11 +21,12 @@ module ActiveRecord
|
|
21
21
|
scope.delete_all
|
22
22
|
else
|
23
23
|
# CPK
|
24
|
-
# scope.update_all(
|
24
|
+
# scope.update_all(nullified_owner_attributes)
|
25
25
|
conds = Array(reflection.foreign_key).inject(Hash.new) do |mem, key|
|
26
26
|
mem[key] = nil
|
27
27
|
mem
|
28
28
|
end
|
29
|
+
conds[reflection.type] = nil if reflection.type.present?
|
29
30
|
scope.update_all(conds)
|
30
31
|
end
|
31
32
|
end
|
@@ -47,14 +47,14 @@ module ActiveRecord
|
|
47
47
|
end
|
48
48
|
|
49
49
|
parent = parents[parent_key] ||= join_root.instantiate(row_hash, column_aliases, &block)
|
50
|
-
construct(parent, join_root, row_hash,
|
50
|
+
construct(parent, join_root, row_hash, seen, model_cache)
|
51
51
|
}
|
52
52
|
end
|
53
53
|
|
54
54
|
parents.values
|
55
55
|
end
|
56
56
|
|
57
|
-
def construct(ar_parent, parent, row,
|
57
|
+
def construct(ar_parent, parent, row, seen, model_cache)
|
58
58
|
return if ar_parent.nil?
|
59
59
|
|
60
60
|
parent.children.each do |node|
|
@@ -63,7 +63,7 @@ module ActiveRecord
|
|
63
63
|
other.loaded!
|
64
64
|
elsif ar_parent.association_cached?(node.reflection.name)
|
65
65
|
model = ar_parent.association(node.reflection.name).target
|
66
|
-
construct(model, node, row,
|
66
|
+
construct(model, node, row, seen, model_cache)
|
67
67
|
next
|
68
68
|
end
|
69
69
|
|
@@ -86,14 +86,15 @@ module ActiveRecord
|
|
86
86
|
next
|
87
87
|
end
|
88
88
|
|
89
|
-
model = seen[ar_parent.object_id][node
|
89
|
+
model = seen[ar_parent.object_id][node][id]
|
90
90
|
|
91
91
|
if model
|
92
|
-
construct(model, node, row,
|
92
|
+
construct(model, node, row, seen, model_cache)
|
93
93
|
else
|
94
|
-
model = construct_model(ar_parent, node, row, model_cache, id
|
95
|
-
|
96
|
-
|
94
|
+
model = construct_model(ar_parent, node, row, model_cache, id)
|
95
|
+
|
96
|
+
seen[ar_parent.object_id][node][id] = model
|
97
|
+
construct(model, node, row, seen, model_cache)
|
97
98
|
end
|
98
99
|
end
|
99
100
|
end
|
@@ -2,42 +2,39 @@ module ActiveRecord
|
|
2
2
|
module Associations
|
3
3
|
class Preloader
|
4
4
|
class Association
|
5
|
-
def records_for(ids
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
5
|
+
def records_for(ids)
|
6
|
+
records = if association_key_name.is_a?(Array)
|
7
|
+
predicate = cpk_in_predicate(klass.arel_table, association_key_name, ids)
|
8
|
+
scope.where(predicate)
|
9
|
+
else
|
10
|
+
scope.where(association_key_name => ids)
|
11
|
+
end
|
12
|
+
records.load do |record|
|
13
|
+
# Processing only the first owner
|
14
|
+
# because the record is modified but not an owner
|
15
|
+
owner = owners_by_key[convert_key(record[association_key_name])].first
|
16
|
+
association = owner.association(reflection.name)
|
17
|
+
association.set_inverse_instance(record)
|
14
18
|
end
|
15
19
|
end
|
16
20
|
|
17
21
|
def owners_by_key
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
convert_key(owner[key_name])
|
25
|
-
end
|
26
|
-
else
|
27
|
-
convert_key(owner[owner_key_name])
|
22
|
+
@owners_by_key ||= owners.each_with_object({}) do |owner, result|
|
23
|
+
# CPK
|
24
|
+
# key = convert_key(owner[owner_key_name])
|
25
|
+
key = if owner_key_name.is_a?(Array)
|
26
|
+
Array(owner_key_name).map do |key_name|
|
27
|
+
convert_key(owner[key_name])
|
28
28
|
end
|
29
|
-
|
30
|
-
|
31
|
-
|
29
|
+
else
|
30
|
+
convert_key(owner[owner_key_name])
|
31
|
+
end
|
32
|
+
(result[key] ||= []) << owner if key
|
32
33
|
end
|
33
|
-
@owners_by_key
|
34
34
|
end
|
35
35
|
|
36
|
-
def
|
37
|
-
|
38
|
-
# CPK
|
39
|
-
#owner = owners_by_key[convert_key(record[association_key_name])]
|
40
|
-
|
36
|
+
def records_by_owner
|
37
|
+
@records_by_owner ||= preloaded_records.each_with_object({}) do |record, result|
|
41
38
|
key = if association_key_name.is_a?(Array)
|
42
39
|
Array(record[association_key_name]).map do |key|
|
43
40
|
convert_key(key)
|
@@ -45,14 +42,9 @@ module ActiveRecord
|
|
45
42
|
else
|
46
43
|
convert_key(record[association_key_name])
|
47
44
|
end
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
association.set_inverse_instance(record)
|
52
|
-
end
|
53
|
-
|
54
|
-
owners.each do |owner|
|
55
|
-
associate_records_to_owner(owner, records[convert_key(owner[owner_key_name])] || [])
|
45
|
+
owners_by_key[key].each do |owner|
|
46
|
+
(result[owner] ||= []) << record
|
47
|
+
end
|
56
48
|
end
|
57
49
|
end
|
58
50
|
end
|
@@ -2,8 +2,8 @@ module ActiveRecord
|
|
2
2
|
module AttributeMethods
|
3
3
|
def has_attribute?(attr_name)
|
4
4
|
# CPK
|
5
|
-
#
|
6
|
-
Array(attr_name).all?{|single_attr|
|
5
|
+
# attributes.key?(attr_name)
|
6
|
+
Array(attr_name).all? {|single_attr| attributes.key?(single_attr) }
|
7
7
|
end
|
8
8
|
end
|
9
9
|
end
|
@@ -2,30 +2,27 @@ module ActiveRecord
|
|
2
2
|
module AttributeMethods
|
3
3
|
module Read
|
4
4
|
def read_attribute(attr_name, &block)
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
# attr_name.to_s
|
12
|
-
attr_name
|
13
|
-
end
|
5
|
+
# CPK
|
6
|
+
# name = attr_name.to_s
|
7
|
+
name = attr_name
|
8
|
+
if self.class.attribute_alias?(name)
|
9
|
+
name = self.class.attribute_alias(name)
|
10
|
+
end
|
14
11
|
|
15
12
|
primary_key = self.class.primary_key
|
16
13
|
# CPK
|
17
|
-
# name = primary_key if name == "id"
|
18
|
-
name = primary_key if name == "id"
|
14
|
+
# name = primary_key if name == "id" && primary_key
|
15
|
+
name = primary_key if name == "id" && primary_key && !composite?
|
19
16
|
sync_with_transaction_state if name == primary_key
|
20
17
|
_read_attribute(name, &block)
|
21
18
|
end
|
22
19
|
|
23
|
-
def _read_attribute(attr_name)
|
20
|
+
def _read_attribute(attr_name, &block) # :nodoc
|
24
21
|
# CPK
|
25
22
|
if attr_name.kind_of?(Array)
|
26
|
-
attr_name.map {|name| @attributes.fetch_value(name.to_s)}
|
23
|
+
attr_name.map {|name| @attributes.fetch_value(name.to_s, &block)}
|
27
24
|
else
|
28
|
-
@attributes.fetch_value(attr_name.to_s)
|
25
|
+
@attributes.fetch_value(attr_name.to_s, &block)
|
29
26
|
end
|
30
27
|
end
|
31
28
|
end
|
@@ -2,20 +2,17 @@ module ActiveRecord
|
|
2
2
|
module AttributeMethods
|
3
3
|
module Write
|
4
4
|
def write_attribute(attr_name, value)
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
# attr_name.to_s
|
12
|
-
attr_name
|
13
|
-
end
|
5
|
+
# CPK
|
6
|
+
#name = attr_name.to_s
|
7
|
+
name = attr_name
|
8
|
+
if self.class.attribute_alias?(name)
|
9
|
+
name = self.class.attribute_alias(name)
|
10
|
+
end
|
14
11
|
|
15
12
|
primary_key = self.class.primary_key
|
16
13
|
# CPK
|
17
|
-
# name = primary_key if name == "id"
|
18
|
-
name = primary_key if name == "id"
|
14
|
+
# name = primary_key if name == "id" && primary_key
|
15
|
+
name = primary_key if name == "id" && primary_key && !composite?
|
19
16
|
sync_with_transaction_state if name == primary_key
|
20
17
|
_write_attribute(name, value)
|
21
18
|
end
|
@@ -52,7 +52,7 @@ module ActiveRecord
|
|
52
52
|
end
|
53
53
|
|
54
54
|
# Don't like this method name, but its modeled after how AR does it
|
55
|
-
|
55
|
+
def reset_primary_keys #:nodoc:
|
56
56
|
if self == base_class
|
57
57
|
# CPK
|
58
58
|
self.primary_keys = get_primary_key(base_class.name)
|
@@ -123,7 +123,7 @@ module ActiveRecord
|
|
123
123
|
end
|
124
124
|
|
125
125
|
def to_param
|
126
|
-
persisted? ? to_key.
|
126
|
+
persisted? ? to_key.join(CompositePrimaryKeys::ID_SEP) : nil
|
127
127
|
end
|
128
128
|
end
|
129
129
|
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 several 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
|
@@ -43,7 +27,7 @@ module CompositePrimaryKeys
|
|
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
|
@@ -59,36 +43,9 @@ module CompositePrimaryKeys
|
|
59
43
|
|
60
44
|
def to_s
|
61
45
|
# Doing this makes it easier to parse Base#[](attr_name)
|
62
|
-
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
module Utils
|
67
|
-
class << self
|
68
|
-
def escape_string_key(key)
|
69
|
-
key.gsub(Regexp.union(ESCAPE_CHAR, ID_SEP)) do |unsafe|
|
70
|
-
"#{ESCAPE_CHAR}#{unsafe.ord.to_s(16).upcase}"
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
def unescape_string_key(key)
|
75
|
-
key.gsub(/#{Regexp.escape(ESCAPE_CHAR)}[0-9a-fA-F]{2}/) do |escaped|
|
76
|
-
char = escaped.slice(1, 2).hex.chr
|
77
|
-
(char == ESCAPE_CHAR || char == ID_SEP) ? char : escaped
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
def cpk_as_array?(value, pk_size)
|
82
|
-
# We don't permit Array to be an element of CPK.
|
83
|
-
value.is_a?(Array) && value.size == pk_size && value.none? { |item| item.is_a?(Array) }
|
84
|
-
end
|
85
|
-
|
86
|
-
def cpk_as_string?(value, pk_size)
|
87
|
-
value.is_a?(String) && value.count(ID_SEP) == pk_size - 1
|
88
|
-
end
|
46
|
+
join(ID_SEP)
|
89
47
|
end
|
90
48
|
end
|
91
|
-
private_constant :Utils
|
92
49
|
end
|
93
50
|
|
94
51
|
Array.send(:include, CompositePrimaryKeys::ArrayExtension)
|