code0-zero_track 0.0.9 → 0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5af11d8b9714d7d557f46cfe5ea9dbd6702d3bc85f5aa67e9ce09e44c6963238
4
- data.tar.gz: 5fc99a08521c502aec93ebe725d9c82c18d9b49e6a7120fba5127db9bb620f6b
3
+ metadata.gz: b7bc699d8f0bb3f1237eeb8ff75493624930bc8cce4b97ba1666709c494d4d04
4
+ data.tar.gz: aac0a33b9d880e0fd9f5a6297b76f0dd32c5f42f6beccad0afeea412caa78bd9
5
5
  SHA512:
6
- metadata.gz: fded2cb69f93aff4704e89b6c3094a0c9dd47a9891748ddd40af68e72eb2d432c150ecd62bf104cd864ceee65a5e782b3eef656fd7ac69ea338898f2cae713a7
7
- data.tar.gz: db2a0b2c23fa93a22442e7f8e0c956ddae670a05bf4105c0a77ea98968c5827541b442b119331bdfb6f8b564b151ccedb9b1418cf45a8dd2fe243c7402748bb8
6
+ metadata.gz: 60edef2bb7d288aeb3127068d6d58099cb409b659a5401a62db2844317cd4aa7048f7b8146ae59234f0e2c3c20e4af1a2e94ef91ac0561c62987f9977193e1c6
7
+ data.tar.gz: 02f209d8121437c829735e11bb9896c0991f2927d484da5c5f8f1f52c1cb7dd6d2363581f4d9886f285052339685ae942972666d497db6e03e6f25a0ed5b0c86
data/README.md CHANGED
@@ -189,6 +189,9 @@ When tables have foreign key relationships, registration order and retention con
189
189
  - A child table's `retain_for` must be less than or equal to the parent table's `retain_for`.
190
190
  If a child retains partitions longer than its parent, dropping the parent partition will
191
191
  fail because the child's foreign key still references it.
192
+ - Foreign keys between the partitioned tables must be declared with `drop_foreign_keys_on_detach`
193
+ on the model. Otherwise, the foreign key of a detached partition will block detaching partitions
194
+ of the referenced table.
192
195
 
193
196
  #### Schema Cleaner Integration
194
197
 
@@ -64,6 +64,8 @@ module Code0
64
64
  model.partitioning_strategy.partitions_to_detach.each do |partition|
65
65
  detach_partition(partition, connection)
66
66
  end
67
+
68
+ drop_declared_foreign_keys_from_detached_partitions(connection)
67
69
  end
68
70
  end
69
71
 
@@ -109,6 +111,73 @@ module Code0
109
111
  )
110
112
  end
111
113
 
114
+ def drop_declared_foreign_keys_from_detached_partitions(connection)
115
+ constraint_names = model.foreign_keys_to_drop_on_detach || []
116
+ return if constraint_names.empty?
117
+
118
+ warn_about_unknown_foreign_keys(constraint_names, connection)
119
+
120
+ detached_foreign_keys(constraint_names, connection).each do |qualified_table, constraint_name|
121
+ connection.execute(
122
+ "ALTER TABLE #{qualified_table} " \
123
+ "DROP CONSTRAINT #{connection.quote_column_name(constraint_name)}"
124
+ )
125
+
126
+ logger.info(
127
+ message: 'Dropped foreign key from detached partition',
128
+ table_name: model.table_name,
129
+ partition_name: qualified_table,
130
+ constraint_name: constraint_name
131
+ )
132
+ end
133
+ end
134
+
135
+ # We check the parent table because we drop the FK from the partition
136
+ # when detaching. A missing FK on the detached partition is an expected state
137
+ def warn_about_unknown_foreign_keys(constraint_names, connection)
138
+ existing = parent_foreign_key_names(connection)
139
+ unknown = constraint_names - existing
140
+ return if unknown.empty?
141
+
142
+ logger.warn(
143
+ message: 'Configured foreign keys to drop on detach do not exist on the partitioned table',
144
+ table_name: model.table_name,
145
+ constraint_names: unknown
146
+ )
147
+ end
148
+
149
+ def parent_foreign_key_names(connection)
150
+ connection.select_values(<<~SQL.squish)
151
+ SELECT con.conname
152
+ FROM pg_catalog.pg_constraint con
153
+ WHERE con.contype = 'f'
154
+ AND con.conrelid = #{connection.quote(model.table_name)}::regclass
155
+ SQL
156
+ end
157
+
158
+ def detached_foreign_keys(constraint_names, connection)
159
+ schema = Rails.application.config.zero_track.db_partitioning.dynamic_partition_schema
160
+ quoted_names = constraint_names.map { |name| connection.quote(name) }.join(', ')
161
+
162
+ rows = connection.select_rows(<<~SQL.squish)
163
+ SELECT (quote_ident(n.nspname) || '.' || quote_ident(c.relname)) AS qualified_table,
164
+ con.conname AS constraint_name
165
+ FROM pg_catalog.pg_constraint con
166
+ JOIN pg_catalog.pg_class c ON c.oid = con.conrelid
167
+ JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
168
+ WHERE con.contype = 'f'
169
+ AND con.conname IN (#{quoted_names})
170
+ AND n.nspname = #{connection.quote(schema)}
171
+ AND c.relkind = 'r'
172
+ AND NOT c.relispartition
173
+ AND NOT EXISTS (
174
+ SELECT 1 FROM pg_catalog.pg_inherits i WHERE i.inhrelid = c.oid
175
+ )
176
+ SQL
177
+
178
+ rows.map { |qualified_table, constraint_name| [qualified_table, constraint_name] }
179
+ end
180
+
112
181
  def drop_partition(detached_partition, connection)
113
182
  schema_name = connection.quote_table_name(detached_partition.schema)
114
183
  partition_name = connection.quote_table_name(detached_partition.name)
@@ -25,6 +25,16 @@ module Code0
25
25
 
26
26
  @partitioning_strategy = strategy_class.new(self, column, **kwargs)
27
27
  end
28
+
29
+ def drop_foreign_keys_on_detach(*constraint_names)
30
+ @foreign_keys_to_drop_on_detach ||= []
31
+ @foreign_keys_to_drop_on_detach.concat(constraint_names.flatten.map(&:to_s))
32
+ @foreign_keys_to_drop_on_detach
33
+ end
34
+
35
+ def foreign_keys_to_drop_on_detach
36
+ @foreign_keys_to_drop_on_detach || []
37
+ end
28
38
  end
29
39
  end
30
40
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Code0
4
4
  module ZeroTrack
5
- VERSION = '0.0.9'
5
+ VERSION = '0.0.10'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: code0-zero_track
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
4
+ version: 0.0.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Niklas van Schrick