Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 28 additions & 20 deletions lib/active_record/connection_adapters/cockroachdb_adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,17 @@ def supports_exclusion_constraints?
false
end

# OVERRIDE: UNIQUE CONSTRAINTS will create indexes anyway, so we only consider
# then as indexes.
# See https://github.com/cockroachdb/activerecord-cockroachdb-adapter/issues/347.
# See https://www.cockroachlabs.com/docs/stable/unique.
#
# NOTE: support is actually partial, one can still use the `#unique_constraints`
# method to get the unique constraints.
def supports_unique_constraints?
false
end

def supports_expression_index?
# Expression indexes are partially supported by CockroachDB v21.2,
# but activerecord requires "ON CONFLICT expression" support.
Expand Down Expand Up @@ -393,32 +404,29 @@ def column_definitions(table_name)
# have [] appended to the end of it.
re = /\A(?:geometry|geography|interval|numeric)/

# 0: attname
# 1: type
# 2: default
# 3: attnotnull
# 4: atttypid
# 5: atttypmod
# 6: collname
# 7: comment
# 8: attidentity
# 9: attgenerated
# 10: is_hidden
f_attname = 0
f_type = 1
# f_default = 2
# f_attnotnull = 3
# f_atttypid = 4
# f_atttypmod = 5
# f_collname = 6
f_comment = 7
# f_attidentity = 8
# f_attgenerated = 9
f_is_hidden = 10
fields.map do |field|
dtype = field[1]
field[1] = crdb_fields[field[0]][2].downcase if re.match(dtype)
field[7] = crdb_fields[field[0]][1]&.gsub!(/^\'|\'?$/, '')
field[10] = true if crdb_fields[field[0]][3]
dtype = field[f_type]
field[f_type] = crdb_fields[field[f_attname]][2].downcase if re.match(dtype)
field[f_comment] = crdb_fields[field[f_attname]][1]&.gsub!(/^\'|\'?$/, '')
field[f_is_hidden] = true if crdb_fields[field[f_attname]][3]
field
end
fields.delete_if do |field|
# Don't include rowid column if it is hidden and the primary key
# is not defined (meaning CRDB implicitly created it).
if field[0] == CockroachDBAdapter::DEFAULT_PRIMARY_KEY
field[10] && !primary_key(table_name)
else
false # Keep this entry.
end
field[f_attname] == CockroachDBAdapter::DEFAULT_PRIMARY_KEY &&
field[f_is_hidden] && !primary_key(table_name)
end
end

Expand Down
51 changes: 0 additions & 51 deletions test/cases/migration/unique_constraint_test.rb

This file was deleted.

34 changes: 25 additions & 9 deletions test/cases/schema_dumper_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,31 @@ def perform_schema_dump
dump_all_table_schema []
end

# OVERRIDE: we removed the 'deferrable' part in `assert_match`
def test_schema_dumps_unique_constraints
output = dump_table_schema("test_unique_constraints")
constraint_definitions = output.split(/\n/).grep(/t\.unique_constraint/)

assert_equal 3, constraint_definitions.size
assert_match 't.unique_constraint ["position_1"], name: "test_unique_constraints_position_1"', output
assert_match 't.unique_constraint ["position_2"], name: "test_unique_constraints_position_2"', output
assert_match 't.unique_constraint ["position_3"], name: "test_unique_constraints_position_3"', output
# See https://github.com/cockroachdb/activerecord-cockroachdb-adapter/issues/347
def test_dump_index_rather_than_unique_constraints
ActiveRecord::Base.with_connection do |conn|
conn.create_table :payments, force: true do |t|
t.text "name"
t.integer "value"
t.unique_constraint ["name", "value"], name: "as_unique_constraint" # Will be ignored
t.index "lower(name::STRING) ASC", name: "simple_unique", unique: true
t.index "name", name: "unique_with_where", where: "name IS NOT NULL", unique: true
end
end

stream = StringIO.new
ActiveRecord::Base.connection_pool.with_connection do |conn|
dumper = conn.create_schema_dumper({})
dumper.send(:table, "payments", stream)
end
stream.rewind
index_lines = stream.each_line.select { _1[/simple_unique|unique_with_where|as_unique_constraint/] }
assert_equal 2, index_lines.size
index_lines.each do |line|
assert_match(/t.index/, line)
end
ensure
ActiveRecord::Base.with_connection { _1.drop_table :payments, if_exists: true }
end

def test_schema_dump_with_timestamptz_datetime_format
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,5 @@
exclude :test_warnings_behaviour_can_be_customized_with_a_proc, plpgsql_needed
exclude :test_allowlist_of_warnings_to_ignore, plpgsql_needed
exclude :test_allowlist_of_warning_codes_to_ignore, plpgsql_needed

exclude :test_translate_no_connection_exception_to_not_established, "CRDB doesn't implement pg_terminate_backend()"
16 changes: 0 additions & 16 deletions test/excludes/ActiveRecord/Migration/UniqueConstraintTest.rb

This file was deleted.

1 change: 0 additions & 1 deletion test/excludes/SchemaDumperTest.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,3 @@
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."
exclude :test_schema_dump_when_changing_datetime_type_for_an_existing_app, "Re-implementing ourselves because we need CockroachDB specific methods."
exclude :test_schema_dumps_check_constraints, "Re-implementing because some constraints are now written in parenthesis"
exclude :test_schema_dumps_unique_constraints, "Re-implementing because DEFERRABLE is not supported by CockroachDB"