Skip to content

Commit 7064053

Browse files
authored
fix: Avoid dumping unique_constraint when attisdropped (#349)
Fixes #347 * fix: ignore unique constraints in favor of indexes * fix: do not support unique_constraints * clarity refactor * ignore new failing test
1 parent 356e7b4 commit 7064053

File tree

6 files changed

+55
-97
lines changed

6 files changed

+55
-97
lines changed

lib/active_record/connection_adapters/cockroachdb_adapter.rb

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,17 @@ def supports_exclusion_constraints?
181181
false
182182
end
183183

184+
# OVERRIDE: UNIQUE CONSTRAINTS will create indexes anyway, so we only consider
185+
# then as indexes.
186+
# See https://github.com/cockroachdb/activerecord-cockroachdb-adapter/issues/347.
187+
# See https://www.cockroachlabs.com/docs/stable/unique.
188+
#
189+
# NOTE: support is actually partial, one can still use the `#unique_constraints`
190+
# method to get the unique constraints.
191+
def supports_unique_constraints?
192+
false
193+
end
194+
184195
def supports_expression_index?
185196
# Expression indexes are partially supported by CockroachDB v21.2,
186197
# but activerecord requires "ON CONFLICT expression" support.
@@ -393,32 +404,29 @@ def column_definitions(table_name)
393404
# have [] appended to the end of it.
394405
re = /\A(?:geometry|geography|interval|numeric)/
395406

396-
# 0: attname
397-
# 1: type
398-
# 2: default
399-
# 3: attnotnull
400-
# 4: atttypid
401-
# 5: atttypmod
402-
# 6: collname
403-
# 7: comment
404-
# 8: attidentity
405-
# 9: attgenerated
406-
# 10: is_hidden
407+
f_attname = 0
408+
f_type = 1
409+
# f_default = 2
410+
# f_attnotnull = 3
411+
# f_atttypid = 4
412+
# f_atttypmod = 5
413+
# f_collname = 6
414+
f_comment = 7
415+
# f_attidentity = 8
416+
# f_attgenerated = 9
417+
f_is_hidden = 10
407418
fields.map do |field|
408-
dtype = field[1]
409-
field[1] = crdb_fields[field[0]][2].downcase if re.match(dtype)
410-
field[7] = crdb_fields[field[0]][1]&.gsub!(/^\'|\'?$/, '')
411-
field[10] = true if crdb_fields[field[0]][3]
419+
dtype = field[f_type]
420+
field[f_type] = crdb_fields[field[f_attname]][2].downcase if re.match(dtype)
421+
field[f_comment] = crdb_fields[field[f_attname]][1]&.gsub!(/^\'|\'?$/, '')
422+
field[f_is_hidden] = true if crdb_fields[field[f_attname]][3]
412423
field
413424
end
414425
fields.delete_if do |field|
415426
# Don't include rowid column if it is hidden and the primary key
416427
# is not defined (meaning CRDB implicitly created it).
417-
if field[0] == CockroachDBAdapter::DEFAULT_PRIMARY_KEY
418-
field[10] && !primary_key(table_name)
419-
else
420-
false # Keep this entry.
421-
end
428+
field[f_attname] == CockroachDBAdapter::DEFAULT_PRIMARY_KEY &&
429+
field[f_is_hidden] && !primary_key(table_name)
422430
end
423431
end
424432

test/cases/migration/unique_constraint_test.rb

Lines changed: 0 additions & 51 deletions
This file was deleted.

test/cases/schema_dumper_test.rb

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,31 @@ def perform_schema_dump
2323
dump_all_table_schema []
2424
end
2525

26-
# OVERRIDE: we removed the 'deferrable' part in `assert_match`
27-
def test_schema_dumps_unique_constraints
28-
output = dump_table_schema("test_unique_constraints")
29-
constraint_definitions = output.split(/\n/).grep(/t\.unique_constraint/)
30-
31-
assert_equal 3, constraint_definitions.size
32-
assert_match 't.unique_constraint ["position_1"], name: "test_unique_constraints_position_1"', output
33-
assert_match 't.unique_constraint ["position_2"], name: "test_unique_constraints_position_2"', output
34-
assert_match 't.unique_constraint ["position_3"], name: "test_unique_constraints_position_3"', output
26+
# See https://github.com/cockroachdb/activerecord-cockroachdb-adapter/issues/347
27+
def test_dump_index_rather_than_unique_constraints
28+
ActiveRecord::Base.with_connection do |conn|
29+
conn.create_table :payments, force: true do |t|
30+
t.text "name"
31+
t.integer "value"
32+
t.unique_constraint ["name", "value"], name: "as_unique_constraint" # Will be ignored
33+
t.index "lower(name::STRING) ASC", name: "simple_unique", unique: true
34+
t.index "name", name: "unique_with_where", where: "name IS NOT NULL", unique: true
35+
end
36+
end
37+
38+
stream = StringIO.new
39+
ActiveRecord::Base.connection_pool.with_connection do |conn|
40+
dumper = conn.create_schema_dumper({})
41+
dumper.send(:table, "payments", stream)
42+
end
43+
stream.rewind
44+
index_lines = stream.each_line.select { _1[/simple_unique|unique_with_where|as_unique_constraint/] }
45+
assert_equal 2, index_lines.size
46+
index_lines.each do |line|
47+
assert_match(/t.index/, line)
48+
end
49+
ensure
50+
ActiveRecord::Base.with_connection { _1.drop_table :payments, if_exists: true }
3551
end
3652

3753
def test_schema_dump_with_timestamptz_datetime_format

test/excludes/ActiveRecord/ConnectionAdapters/PostgreSQLAdapterTest.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,5 @@
3131
exclude :test_warnings_behaviour_can_be_customized_with_a_proc, plpgsql_needed
3232
exclude :test_allowlist_of_warnings_to_ignore, plpgsql_needed
3333
exclude :test_allowlist_of_warning_codes_to_ignore, plpgsql_needed
34+
35+
exclude :test_translate_no_connection_exception_to_not_established, "CRDB doesn't implement pg_terminate_backend()"

test/excludes/ActiveRecord/Migration/UniqueConstraintTest.rb

Lines changed: 0 additions & 16 deletions
This file was deleted.

test/excludes/SchemaDumperTest.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,3 @@
99
exclude :test_schema_dump_with_correct_timestamp_types_via_add_column_before_rails_7_with_timestamptz_setting, "Re-implementing ourselves because we need CockroachDB specific methods."
1010
exclude :test_schema_dump_when_changing_datetime_type_for_an_existing_app, "Re-implementing ourselves because we need CockroachDB specific methods."
1111
exclude :test_schema_dumps_check_constraints, "Re-implementing because some constraints are now written in parenthesis"
12-
exclude :test_schema_dumps_unique_constraints, "Re-implementing because DEFERRABLE is not supported by CockroachDB"

0 commit comments

Comments
 (0)