Skip to content

Commit 62e1871

Browse files
committed
Fix dumping declaratively partitioned tables in PostgreSQL
1 parent 7645f01 commit 62e1871

File tree

3 files changed

+39
-5
lines changed

3 files changed

+39
-5
lines changed

activerecord/lib/active_record/connection_adapters/postgresql/schema_dumper.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,17 @@ def schemas(stream)
3939
end
4040
end
4141

42+
def table(table, stream)
43+
super
44+
45+
partition_bound_definition = @connection.table_partition_bound_definition(table)
46+
if partition_bound_definition
47+
partition_table = @connection.inherited_table_names(table).first
48+
49+
stream.puts " execute \"ALTER TABLE ONLY #{partition_table} ATTACH PARTITION #{table} #{partition_bound_definition}\""
50+
end
51+
end
52+
4253
def exclusion_constraints_in_create(table, stream)
4354
if (exclusion_constraints = @connection.exclusion_constraints(table)).any?
4455
exclusion_constraint_statements = exclusion_constraints.map do |exclusion_constraint|

activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -162,11 +162,14 @@ def table_options(table_name) # :nodoc:
162162

163163
options[:comment] = comment if comment
164164

165+
partition_bound_definition = table_partition_bound_definition(table_name)
165166
inherited_table_names = inherited_table_names(table_name).presence
166167

167-
options[:options] = "INHERITS (#{inherited_table_names.join(", ")})" if inherited_table_names
168-
169-
if !options[:options] && supports_native_partitioning?
168+
# Can't use :options for declarative partitioning. Partition will be attached
169+
# via a separate 'ALTER TABLE ... ATTACH PARTITION ...' call.
170+
if inherited_table_names && !partition_bound_definition
171+
options[:options] = "INHERITS (#{inherited_table_names.join(", ")})"
172+
elsif supports_native_partitioning?
170173
partition_definition = table_partition_definition(table_name)
171174

172175
options[:options] = "PARTITION BY #{partition_definition}" if partition_definition
@@ -190,7 +193,7 @@ def table_comment(table_name) # :nodoc:
190193
end
191194
end
192195

193-
# Returns the partition definition of a given table
196+
# Returns the partitioned table definition of a given table
194197
def table_partition_definition(table_name) # :nodoc:
195198
scope = quoted_scope(table_name, type: "BASE TABLE")
196199

@@ -220,6 +223,21 @@ def inherited_table_names(table_name) # :nodoc:
220223
SQL
221224
end
222225

226+
# Returns the partition definition of a given table
227+
def table_partition_bound_definition(table_name) # :nodoc:
228+
scope = quoted_scope(table_name, type: "BASE TABLE")
229+
230+
query_value(<<~SQL, "SCHEMA")
231+
SELECT pg_catalog.pg_get_expr(c.relpartbound, c.oid)
232+
FROM pg_catalog.pg_class c
233+
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
234+
WHERE c.relname = #{scope[:name]}
235+
AND c.relkind IN (#{scope[:type]})
236+
AND n.nspname = #{scope[:schema]}
237+
AND c.relispartition
238+
SQL
239+
end
240+
223241
# Returns the current database name.
224242
def current_database
225243
query_value("SELECT current_database()", "SCHEMA")

activerecord/test/cases/adapters/postgresql/schema_test.rb

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -895,9 +895,14 @@ def test_list_partition_options_is_dumped
895895
t.string :kind
896896
end
897897

898-
output = dump_table_schema "trains"
898+
@connection.create_table "trains_a", id: false, options: "PARTITION OF trains FOR VALUES IN ('a')"
899+
@connection.create_table "trains_b", id: false, options: "PARTITION OF trains FOR VALUES IN ('b')"
900+
901+
output = dump_table_schema "trains", "trains_a", "trains_b"
899902

900903
assert_match("options: \"#{options}\"", output)
904+
assert_match(/execute "ALTER TABLE ONLY trains ATTACH PARTITION trains_a FOR VALUES IN \('a'\)"/, output)
905+
assert_match(/execute "ALTER TABLE ONLY trains ATTACH PARTITION trains_b FOR VALUES IN \('b'\)"/, output)
901906
end
902907

903908
def test_range_partition_options_is_dumped

0 commit comments

Comments
 (0)