composite_primary_keys 13.0.8 → 14.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8604d48445aede0e7f6d39ad32090ea2ed0f8d7cd58ab633a3d0c013ee1ab3b8
4
- data.tar.gz: a71f857e9125065b7c635170c341ce4a9285f6942c8989dac9cfa201f428a062
3
+ metadata.gz: 4310258f29b867cf484cb8dbebfe1f7a7d41810f2dac5f90049c534f1c0a908b
4
+ data.tar.gz: 970906ceae8ac95925d5ee694541b09844f3104309eaed5864f9b1faff7fb43e
5
5
  SHA512:
6
- metadata.gz: fb13f66165419e9ca60e9b1b3283ff174947d3d2d07d1b7e29a62cb0feae97bbe5abc3179d41f330f76d2837d27c837875a01039f1c9e2969769293c4617b7d2
7
- data.tar.gz: 14790bef238c5f4e6360a5613db1bd22e3333bc06a062bc6047212b077d02828bb6d1acdda436f8a4106bc1e82dc6fe4ef96d2e05f5f3dd72beb86bf0c4ae0a1
6
+ metadata.gz: 78878c2b2fa9612e8e141b5b1d39679a03046aed63e7c19e7ad71b6b8372327cfcb9a5bb659d88fda5cbb405e5bf7199c742b0468041a9509406ce54764d4e10
7
+ data.tar.gz: 79e78cb7cf9a336821cb02dad8d1cf43aece81e25b18c4ebadac1b584be1d6bd06a7a43b7840c918323efb69d8b0c9783c215595f04a37dc083079ba4e0cc50e
data/History.rdoc CHANGED
@@ -1,34 +1,15 @@
1
- == 13.0.8 (2023-11-24)
2
- Fix `polymorphic_name` support (Vladimir Kochnev)
1
+ == 14.0.1 (2022-01-9)
2
+ * Fix mistake in Gemfile (Charlie Savage)
3
3
 
4
- == 13.0.7 (2023-02-04)
5
- * Fix #573 (Charlie Savage)
6
-
7
- == 13.0.6 (2023-02-04)
8
- * Fix #577 (Charlie Savage)
9
-
10
- == 13.0.5 (2023-02-04)
11
- * Improve query generation for cpk_in_predicate. This reduces the length of
12
- queries when loading many keys and enables Postgres to use index scans
13
- more frequently. (Andrew Kiellor)
14
-
15
- == 13.0.4 (2022-12-05)
16
- * Fix previously_new_record? not being set to true after create
17
-
18
- == 13.0.3 (2022-01-09)
19
- * Remove override on ActiveRecord::Base#to_param. That method has moved to Integration
20
- so no longer works. #541. (Charlie Savage)
21
- * Check if an assocation is polymorhpic. Fixes #558.
22
-
23
- == 13.0.2 (2022-01-09)
24
- * Fix scoped associations take #2 (Charlie Savage)
4
+ == 14.0.0 (2022-01-9)
5
+ * Update to ActiveRecord 7.0 (Sammy Larbi)
25
6
 
26
7
  == 13.0.1 (2021-11-14)
27
8
  * Fix invalid sql generation for some cases of scoped associations (Ryan Mulligan)
28
9
  * Fix unintentional connection to database (Kazuhiro Masuda)
29
10
  * Zip values then keys - fixes #548 (Charlie Savage)
30
11
 
31
- == 13.0.0 (2021-05-09)
12
+ == 13.0.0 (2021-5-9)
32
13
  * Update to ActiveRecord 6.1 (Javier Julio, Charlie Savage, Sammy Larbi)
33
14
 
34
15
  == 12.0.10 (2021-05-09)
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 14.x is designed to work with ActiveRecord 7.0.x
23
24
  Version 13.x is designed to work with ActiveRecord 6.1.x
24
25
  Version 12.x is designed to work with ActiveRecord 6.0.x
25
26
  Version 11.x is designed to work with ActiveRecord 5.2.x
@@ -11,8 +11,8 @@ module ActiveRecord
11
11
  attributes[key1] = owner[key2]
12
12
  end
13
13
 
14
- if reflection.type
15
- attributes[reflection.type] = owner.class.polymorphic_name
14
+ if reflection.options[:as]
15
+ attributes[reflection.type] = owner.class.base_class.name
16
16
  end
17
17
  end
18
18
 
@@ -64,4 +64,4 @@ module ActiveRecord
64
64
  end
65
65
  end
66
66
  end
67
- end
67
+ end
@@ -1,137 +1,137 @@
1
- module ActiveRecord
2
- module Associations
3
- class JoinDependency
4
-
5
- class JoinAssociation < JoinPart # :nodoc:
6
- private
7
- def append_constraints(join, constraints)
8
- if join.is_a?(Arel::Nodes::StringJoin)
9
- join_string = Arel::Nodes::And.new(constraints.unshift join.left)
10
- join.left = Arel.sql(base_klass.connection.visitor.compile(join_string))
11
- else
12
- right = join.right
13
- # CPK
14
- if right.expr.is_a?(Arel::Nodes::And) && right.expr.children.empty?
15
- right.expr = Arel::Nodes::And.new(constraints)
16
- else
17
- right.expr = Arel::Nodes::And.new(constraints.unshift right.expr)
18
- end
19
- end
20
- end
21
- end
22
-
23
- class Aliases # :nodoc:
24
- def column_alias(node, column)
25
- # CPK
26
- #@alias_cache[node][column]
27
- if column.kind_of?(Array)
28
- column.map do |a_column|
29
- @alias_cache[node][a_column]
30
- end
31
- else
32
- @alias_cache[node][column]
33
- end
34
- end
35
- end
36
-
37
- def instantiate(result_set, strict_loading_value, &block)
38
- primary_key = aliases.column_alias(join_root, join_root.primary_key)
39
-
40
- seen = Hash.new { |i, parent|
41
- i[parent] = Hash.new { |j, child_class|
42
- j[child_class] = {}
43
- }
44
- }.compare_by_identity
45
-
46
- model_cache = Hash.new { |h, klass| h[klass] = {} }
47
- parents = model_cache[join_root]
48
-
49
- column_aliases = aliases.column_aliases(join_root)
50
- column_names = []
51
-
52
- result_set.columns.each do |name|
53
- column_names << name unless /\At\d+_r\d+\z/.match?(name)
54
- end
55
-
56
- if column_names.empty?
57
- column_types = {}
58
- else
59
- column_types = result_set.column_types
60
- unless column_types.empty?
61
- attribute_types = join_root.attribute_types
62
- column_types = column_types.slice(*column_names).delete_if { |k, _| attribute_types.key?(k) }
63
- end
64
- column_aliases += column_names.map! { |name| Aliases::Column.new(name, name) }
65
- end
66
-
67
- message_bus = ActiveSupport::Notifications.instrumenter
68
-
69
- payload = {
70
- record_count: result_set.length,
71
- class_name: join_root.base_klass.name
72
- }
73
-
74
- message_bus.instrument("instantiation.active_record", payload) do
75
- result_set.each { |row_hash|
76
- # CPK
77
- # parent_key = primary_key ? row_hash[primary_key] : row_hash
78
- parent_key = if primary_key.kind_of?(Array)
79
- primary_key.map {|key| row_hash[key]}
80
- else
81
- primary_key ? row_hash[primary_key] : row_hash
82
- end
83
-
84
- parent = parents[parent_key] ||= join_root.instantiate(row_hash, column_aliases, column_types, &block)
85
- construct(parent, join_root, row_hash, seen, model_cache, strict_loading_value)
86
- }
87
- end
88
-
89
- parents.values
90
- end
91
-
92
- def construct(ar_parent, parent, row, seen, model_cache, strict_loading_value)
93
- return if ar_parent.nil?
94
-
95
- parent.children.each do |node|
96
- if node.reflection.collection?
97
- other = ar_parent.association(node.reflection.name)
98
- other.loaded!
99
- elsif ar_parent.association_cached?(node.reflection.name)
100
- model = ar_parent.association(node.reflection.name).target
101
- construct(model, node, row, seen, model_cache, strict_loading_value)
102
- next
103
- end
104
-
105
- key = aliases.column_alias(node, node.primary_key)
106
- # CPK
107
- if key.is_a?(Array)
108
- id = Array(key).map do |column_alias|
109
- row[column_alias]
110
- end
111
- # At least the first value in the key has to be set. Should we require all values to be set?
112
- id = nil if id.first.nil?
113
- else # original
114
- id = row[key]
115
- end
116
-
117
- if id.nil?
118
- nil_association = ar_parent.association(node.reflection.name)
119
- nil_association.loaded!
120
- next
121
- end
122
-
123
- model = seen[ar_parent][node][id]
124
-
125
- if model
126
- construct(model, node, row, seen, model_cache, strict_loading_value)
127
- else
128
- model = construct_model(ar_parent, node, row, model_cache, id, strict_loading_value)
129
-
130
- seen[ar_parent][node][id] = model
131
- construct(model, node, row, seen, model_cache, strict_loading_value)
132
- end
133
- end
134
- end
135
- end
136
- end
137
- end
1
+ module ActiveRecord
2
+ module Associations
3
+ class JoinDependency
4
+
5
+ class JoinAssociation < JoinPart # :nodoc:
6
+ private
7
+ def append_constraints(join, constraints)
8
+ if join.is_a?(Arel::Nodes::StringJoin)
9
+ join_string = Arel::Nodes::And.new(constraints.unshift join.left)
10
+ join.left = Arel.sql(base_klass.connection.visitor.compile(join_string))
11
+ else
12
+ right = join.right
13
+ # CPK
14
+ if right.expr.children.empty?
15
+ right.expr = Arel::Nodes::And.new(constraints)
16
+ else
17
+ right.expr = Arel::Nodes::And.new(constraints.unshift right.expr)
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ class Aliases # :nodoc:
24
+ def column_alias(node, column)
25
+ # CPK
26
+ #@alias_cache[node][column]
27
+ if column.kind_of?(Array)
28
+ column.map do |a_column|
29
+ @alias_cache[node][a_column]
30
+ end
31
+ else
32
+ @alias_cache[node][column]
33
+ end
34
+ end
35
+ end
36
+
37
+ def instantiate(result_set, strict_loading_value, &block)
38
+ primary_key = aliases.column_alias(join_root, join_root.primary_key)
39
+
40
+ seen = Hash.new { |i, parent|
41
+ i[parent] = Hash.new { |j, child_class|
42
+ j[child_class] = {}
43
+ }
44
+ }.compare_by_identity
45
+
46
+ model_cache = Hash.new { |h, klass| h[klass] = {} }
47
+ parents = model_cache[join_root]
48
+
49
+ column_aliases = aliases.column_aliases(join_root)
50
+ column_names = []
51
+
52
+ result_set.columns.each do |name|
53
+ column_names << name unless /\At\d+_r\d+\z/.match?(name)
54
+ end
55
+
56
+ if column_names.empty?
57
+ column_types = {}
58
+ else
59
+ column_types = result_set.column_types
60
+ unless column_types.empty?
61
+ attribute_types = join_root.attribute_types
62
+ column_types = column_types.slice(*column_names).delete_if { |k, _| attribute_types.key?(k) }
63
+ end
64
+ column_aliases += column_names.map! { |name| Aliases::Column.new(name, name) }
65
+ end
66
+
67
+ message_bus = ActiveSupport::Notifications.instrumenter
68
+
69
+ payload = {
70
+ record_count: result_set.length,
71
+ class_name: join_root.base_klass.name
72
+ }
73
+
74
+ message_bus.instrument("instantiation.active_record", payload) do
75
+ result_set.each { |row_hash|
76
+ # CPK
77
+ # parent_key = primary_key ? row_hash[primary_key] : row_hash
78
+ parent_key = if primary_key.kind_of?(Array)
79
+ primary_key.map {|key| row_hash[key]}
80
+ else
81
+ primary_key ? row_hash[primary_key] : row_hash
82
+ end
83
+
84
+ parent = parents[parent_key] ||= join_root.instantiate(row_hash, column_aliases, column_types, &block)
85
+ construct(parent, join_root, row_hash, seen, model_cache, strict_loading_value)
86
+ }
87
+ end
88
+
89
+ parents.values
90
+ end
91
+
92
+ def construct(ar_parent, parent, row, seen, model_cache, strict_loading_value)
93
+ return if ar_parent.nil?
94
+
95
+ parent.children.each do |node|
96
+ if node.reflection.collection?
97
+ other = ar_parent.association(node.reflection.name)
98
+ other.loaded!
99
+ elsif ar_parent.association_cached?(node.reflection.name)
100
+ model = ar_parent.association(node.reflection.name).target
101
+ construct(model, node, row, seen, model_cache, strict_loading_value)
102
+ next
103
+ end
104
+
105
+ key = aliases.column_alias(node, node.primary_key)
106
+ # CPK
107
+ if key.is_a?(Array)
108
+ id = Array(key).map do |column_alias|
109
+ row[column_alias]
110
+ end
111
+ # At least the first value in the key has to be set. Should we require all values to be set?
112
+ id = nil if id.first.nil?
113
+ else # original
114
+ id = row[key]
115
+ end
116
+
117
+ if id.nil?
118
+ nil_association = ar_parent.association(node.reflection.name)
119
+ nil_association.loaded!
120
+ next
121
+ end
122
+
123
+ model = seen[ar_parent][node][id]
124
+
125
+ if model
126
+ construct(model, node, row, seen, model_cache, strict_loading_value)
127
+ else
128
+ model = construct_model(ar_parent, node, row, model_cache, id, strict_loading_value)
129
+
130
+ seen[ar_parent][node][id] = model
131
+ construct(model, node, row, seen, model_cache, strict_loading_value)
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end
137
+ end
@@ -2,6 +2,20 @@ module ActiveRecord
2
2
  module Associations
3
3
  class Preloader
4
4
  class Association
5
+
6
+ class LoaderQuery
7
+ def load_records_for_keys(keys, &block)
8
+ # CPK
9
+ if association_key_name.is_a?(Array)
10
+ predicate = cpk_in_predicate(scope.klass.arel_table, association_key_name, keys)
11
+ scope.where(predicate).load(&block)
12
+ else
13
+ scope.where(association_key_name => keys).load(&block)
14
+ end
15
+ end
16
+ end
17
+
18
+ # TODO: is records_for needed anymore? Rails' implementation has changed significantly
5
19
  def records_for(ids)
6
20
  records = if association_key_name.is_a?(Array)
7
21
  predicate = cpk_in_predicate(klass.arel_table, association_key_name, ids)
@@ -33,28 +47,21 @@ module ActiveRecord
33
47
  end
34
48
  end
35
49
 
36
- def load_records
37
- # owners can be duplicated when a relation has a collection association join
38
- # #compare_by_identity makes such owners different hash keys
39
- @records_by_owner = {}.compare_by_identity
40
- raw_records = owner_keys.empty? ? [] : records_for(owner_keys)
41
-
42
- @preloaded_records = raw_records.select do |record|
43
- assignments = false
44
-
45
- owners_by_key[convert_key(record[association_key_name])].each do |owner|
46
- entries = (@records_by_owner[owner] ||= [])
47
-
48
- if reflection.collection? || entries.empty?
49
- entries << record
50
- assignments = true
51
- end
50
+ # TODO: is records_by_owner needed anymore? Rails' implementation has changed significantly
51
+ def records_by_owner
52
+ @records_by_owner ||= preloaded_records.each_with_object({}) do |record, result|
53
+ key = if association_key_name.is_a?(Array)
54
+ Array(record[association_key_name]).map do |key|
55
+ convert_key(key)
56
+ end
57
+ else
58
+ convert_key(record[association_key_name])
59
+ end
60
+ owners_by_key[key].each do |owner|
61
+ (result[owner] ||= []) << record
52
62
  end
53
-
54
- assignments
55
63
  end
56
64
  end
57
-
58
65
  end
59
66
  end
60
67
  end
@@ -5,7 +5,8 @@ module ActiveRecord
5
5
 
6
6
  def construct_join_attributes(*records)
7
7
  # CPK
8
- if !self.source_reflection.polymorphic? && source_reflection.klass.composite?
8
+ is_composite = self.source_reflection.polymorphic? ? source_reflection.active_record.composite? : source_reflection.klass.composite?
9
+ if is_composite
9
10
  ensure_mutable
10
11
 
11
12
  ids = records.map do |record|