activerecord-cockroachdb-adapter 8.0.3 → 8.1.0
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 +4 -4
- data/CHANGELOG.md +3 -0
- data/CONTRIBUTING.md +10 -17
- data/Gemfile +2 -1
- data/Rakefile +0 -19
- data/lib/active_record/connection_adapters/cockroachdb/column.rb +66 -24
- data/lib/active_record/connection_adapters/cockroachdb/database_statements.rb +13 -3
- data/lib/active_record/connection_adapters/cockroachdb/database_tasks.rb +1 -1
- data/lib/active_record/connection_adapters/cockroachdb/oid/spatial.rb +34 -19
- data/lib/active_record/connection_adapters/cockroachdb/quoting.rb +19 -3
- data/lib/active_record/connection_adapters/cockroachdb/referential_integrity.rb +87 -55
- data/lib/active_record/connection_adapters/cockroachdb/schema_statements.rb +181 -102
- data/lib/active_record/connection_adapters/cockroachdb_adapter.rb +39 -21
- data/lib/version.rb +1 -1
- data/test/cases/adapter_test.rb +98 -0
- data/test/cases/adapters/cockroachdb/referential_integrity_test.rb +51 -0
- data/test/cases/adapters/postgresql/active_schema_test.rb +71 -0
- data/test/cases/adapters/postgresql/change_schema_test.rb +75 -0
- data/test/cases/adapters/postgresql/connection_test.rb +46 -0
- data/test/cases/adapters/postgresql/ddl_test.rb +326 -0
- data/test/cases/adapters/postgresql/interval_test.rb +131 -0
- data/test/cases/adapters/postgresql/nested_class_test.rb +22 -0
- data/test/cases/adapters/postgresql/numeric_test.rb +28 -0
- data/test/cases/adapters/postgresql/postgis_test.rb +185 -0
- data/test/cases/adapters/postgresql/postgresql_adapter_test.rb +115 -0
- data/test/cases/adapters/postgresql/quoting_test.rb +30 -0
- data/test/cases/adapters/postgresql/schema_statements_test.rb +29 -0
- data/test/cases/adapters/postgresql/serial_test.rb +199 -0
- data/test/cases/adapters/postgresql/spatial_queries_test.rb +118 -0
- data/test/cases/adapters/postgresql/spatial_setup_test.rb +18 -0
- data/test/cases/adapters/postgresql/spatial_type_test.rb +41 -0
- data/test/cases/adapters/postgresql/timestamp_test.rb +58 -0
- data/test/cases/adapters/postgresql/virtual_column_test.rb +39 -0
- data/test/cases/associations/eager_load_nested_include_test.rb +111 -0
- data/test/cases/associations/left_outer_join_association_test.rb +30 -0
- data/test/cases/associations_test.rb +108 -0
- data/test/cases/base_test.rb +31 -0
- data/test/cases/comment_test.rb +75 -0
- data/test/cases/connection_adapters/type_test.rb +28 -0
- data/test/cases/database_configurations/resolver_test.rb +24 -0
- data/test/cases/defaults_test.rb +45 -0
- data/test/cases/dirty_test.rb +24 -0
- data/test/cases/fixtures_test.rb +541 -0
- data/test/cases/helper_cockroachdb.rb +232 -0
- data/test/cases/inheritance_test.rb +42 -0
- data/test/cases/invertible_migration_test.rb +73 -0
- data/test/cases/marshal_serialization_test.rb +45 -0
- data/test/cases/migration/change_schema_test.rb +140 -0
- data/test/cases/migration/check_constraint_test.rb +125 -0
- data/test/cases/migration/columns_test.rb +50 -0
- data/test/cases/migration/create_join_table_test.rb +66 -0
- data/test/cases/migration/foreign_key_test.rb +390 -0
- data/test/cases/migration/hidden_column_test.rb +70 -0
- data/test/cases/migration/references_foreign_key_test.rb +124 -0
- data/test/cases/migration_test.rb +120 -0
- data/test/cases/persistence_test.rb +33 -0
- data/test/cases/primary_keys_test.rb +134 -0
- data/test/cases/relation/aost_test.rb +57 -0
- data/test/cases/relation/or_test.rb +26 -0
- data/test/cases/relation/table_hints_test.rb +124 -0
- data/test/cases/relation_test.rb +26 -0
- data/test/cases/relations_test.rb +29 -0
- data/test/cases/schema_dumper_test.rb +221 -0
- data/test/cases/show_create_test.rb +14 -0
- data/test/cases/strict_loading_test.rb +34 -0
- data/test/cases/tasks/cockroachdb_rake_test.rb +113 -0
- data/test/cases/test_fixtures_test.rb +57 -0
- data/test/cases/transactions_test.rb +51 -0
- data/test/cases/unsafe_raw_sql_test.rb +22 -0
- data/test/config.yml +23 -0
- data/test/excludes/ActiveRecord/AdapterTest.rb +3 -0
- data/test/excludes/ActiveRecord/AdapterTestWithoutTransaction.rb +25 -0
- data/test/excludes/ActiveRecord/ConnectionAdapters/PoolConfig/ResolverTest.rb +1 -0
- data/test/excludes/ActiveRecord/ConnectionAdapters/PostgreSQLAdapter/BindParameterTest.rb +15 -0
- data/test/excludes/ActiveRecord/ConnectionAdapters/PostgreSQLAdapter/QuotingTest.rb +22 -0
- data/test/excludes/ActiveRecord/ConnectionAdapters/PostgreSQLAdapterPreventWritesLegacyTest.rb +1 -0
- data/test/excludes/ActiveRecord/ConnectionAdapters/PostgreSQLAdapterPreventWritesTest.rb +1 -0
- data/test/excludes/ActiveRecord/ConnectionAdapters/PostgreSQLAdapterTest.rb +40 -0
- data/test/excludes/ActiveRecord/ConnectionAdapters/RegistrationIsolatedTest.rb +14 -0
- data/test/excludes/ActiveRecord/Encryption/EncryptionPerformanceTest.rb +1 -0
- data/test/excludes/ActiveRecord/Encryption/EnvelopeEncryptionPerformanceTest.rb +1 -0
- data/test/excludes/ActiveRecord/Encryption/ExtendedDeterministicQueriesPerformanceTest.rb +1 -0
- data/test/excludes/ActiveRecord/Encryption/StoragePerformanceTest.rb +2 -0
- data/test/excludes/ActiveRecord/InstrumentationTest.rb +16 -0
- data/test/excludes/ActiveRecord/InvertibleMigrationTest.rb +2 -0
- data/test/excludes/ActiveRecord/Migration/ChangeSchemaTest.rb +7 -0
- data/test/excludes/ActiveRecord/Migration/CheckConstraintTest.rb +6 -0
- data/test/excludes/ActiveRecord/Migration/ColumnsTest.rb +4 -0
- data/test/excludes/ActiveRecord/Migration/CompatibilityTest.rb +50 -0
- data/test/excludes/ActiveRecord/Migration/CompositeForeignKeyTest.rb +2 -0
- data/test/excludes/ActiveRecord/Migration/CreateJoinTableTest.rb +2 -0
- data/test/excludes/ActiveRecord/Migration/ForeignKeyInCreateTest.rb +1 -0
- data/test/excludes/ActiveRecord/Migration/ForeignKeyTest.rb +35 -0
- data/test/excludes/ActiveRecord/Migration/InvalidOptionsTest.rb +14 -0
- data/test/excludes/ActiveRecord/Migration/PGChangeSchemaTest.rb +8 -0
- data/test/excludes/ActiveRecord/Migration/ReferencesForeignKeyTest.rb +7 -0
- data/test/excludes/ActiveRecord/Migration/ReferencesIndexTest.rb +7 -0
- data/test/excludes/ActiveRecord/Migration/ReferencesStatementsTest.rb +3 -0
- data/test/excludes/ActiveRecord/MysqlDBCreateWithInvalidPermissionsTest.rb +1 -0
- data/test/excludes/ActiveRecord/OrTest.rb +1 -0
- data/test/excludes/ActiveRecord/PostgreSQLStructureDumpTest.rb +10 -0
- data/test/excludes/ActiveRecord/PostgresqlConnectionTest.rb +12 -0
- data/test/excludes/ActiveRecord/PostgresqlTransactionNestedTest.rb +14 -0
- data/test/excludes/ActiveRecord/PostgresqlTransactionTest.rb +4 -0
- data/test/excludes/ActiveRecord/RelationTest.rb +2 -0
- data/test/excludes/ActiveRecord/TooManyOrTest.rb +1 -0
- data/test/excludes/ActiveSupportSubclassWithFixturesTest.rb +1 -0
- data/test/excludes/AssociationDeprecationTest/NotifyModeTest.rb +2 -0
- data/test/excludes/AssociationDeprecationTest/RaiseBacktraceModeTest.rb +2 -0
- data/test/excludes/AssociationDeprecationTest/RaiseModeTest.rb +2 -0
- data/test/excludes/AssociationDeprecationTest/WarnBacktraceModeTest.rb +2 -0
- data/test/excludes/AssociationDeprecationTest/WarnModeTest.rb +2 -0
- data/test/excludes/AssociationDeprecationTest/fix_backtrace_cleaner.rb +10 -0
- data/test/excludes/BasicsTest.rb +1 -0
- data/test/excludes/BulkAlterTableMigrationsTest.rb +7 -0
- data/test/excludes/CalculationsTest.rb +4 -0
- data/test/excludes/CommentTest.rb +2 -0
- data/test/excludes/CoreTest.rb +1 -0
- data/test/excludes/CreateOrFindByWithinTransactions.rb +3 -0
- data/test/excludes/DefaultsUsingMultipleSchemasAndDomainTest.rb +7 -0
- data/test/excludes/DirtyTest.rb +3 -0
- data/test/excludes/EachTest.rb +8 -0
- data/test/excludes/EagerLoadPolyAssocsTest.rb +1 -0
- data/test/excludes/ExplicitlyNamedIndexMigrationTest.rb +1 -0
- data/test/excludes/FixturesResetPkSequenceTest.rb +3 -0
- data/test/excludes/FixturesTest.rb +21 -0
- data/test/excludes/FixturesWithForeignKeyViolationsTest.rb +2 -0
- data/test/excludes/ForeignTableTest.rb +10 -0
- data/test/excludes/InheritanceComputeTypeTest.rb +1 -0
- data/test/excludes/LeftOuterJoinAssociationTest.rb +2 -0
- data/test/excludes/LegacyPrimaryKeyTest/V4_2.rb +6 -0
- data/test/excludes/LegacyPrimaryKeyTest/V5_0.rb +6 -0
- data/test/excludes/MarshalSerializationTest.rb +4 -0
- data/test/excludes/MaterializedViewTest.rb +13 -0
- data/test/excludes/MigrationTest.rb +2 -0
- data/test/excludes/MultiDbMigratorTest.rb +2 -0
- data/test/excludes/NestedRelationScopingTest.rb +1 -0
- data/test/excludes/OrTest.rb +1 -0
- data/test/excludes/PersistenceTest.rb +3 -0
- data/test/excludes/PessimisticLockingTest.rb +1 -0
- data/test/excludes/PostgreSQLExplainTest.rb +7 -0
- data/test/excludes/PostgreSQLGeometricLineTest.rb +3 -0
- data/test/excludes/PostgreSQLGeometricTypesTest.rb +7 -0
- data/test/excludes/PostgreSQLPartitionsTest.rb +1 -0
- data/test/excludes/PostgreSQLReferentialIntegrityTest.rb +14 -0
- data/test/excludes/PostgresqlArrayTest.rb +21 -0
- data/test/excludes/PostgresqlBigSerialTest.rb +7 -0
- data/test/excludes/PostgresqlBitStringTest.rb +2 -0
- data/test/excludes/PostgresqlByteaTest.rb +1 -0
- data/test/excludes/PostgresqlCitextTest.rb +7 -0
- data/test/excludes/PostgresqlCollationTest.rb +5 -0
- data/test/excludes/PostgresqlCompositeTest.rb +2 -0
- data/test/excludes/PostgresqlCompositeWithCustomOIDTest.rb +2 -0
- data/test/excludes/PostgresqlDataTypeTest.rb +9 -0
- data/test/excludes/PostgresqlDefaultExpressionTest.rb +1 -0
- data/test/excludes/PostgresqlDeferredConstraintsTest.rb +3 -0
- data/test/excludes/PostgresqlDomainTest.rb +2 -0
- data/test/excludes/PostgresqlExtensionMigrationTest.rb +5 -0
- data/test/excludes/PostgresqlFullTextTest.rb +3 -0
- data/test/excludes/PostgresqlGeometricTest.rb +4 -0
- data/test/excludes/PostgresqlHstoreTest.rb +45 -0
- data/test/excludes/PostgresqlInfinityTest.rb +5 -0
- data/test/excludes/PostgresqlIntervalTest.rb +1 -0
- data/test/excludes/PostgresqlJSONBTest.rb +27 -0
- data/test/excludes/PostgresqlJSONTest.rb +27 -0
- data/test/excludes/PostgresqlLtreeTest.rb +4 -0
- data/test/excludes/PostgresqlMoneyTest.rb +12 -0
- data/test/excludes/PostgresqlNetworkTest.rb +69 -0
- data/test/excludes/PostgresqlNumberTest.rb +1 -0
- data/test/excludes/PostgresqlPointTest.rb +15 -0
- data/test/excludes/PostgresqlRangeTest.rb +3 -0
- data/test/excludes/PostgresqlRenameTableTest.rb +2 -0
- data/test/excludes/PostgresqlSerialTest.rb +7 -0
- data/test/excludes/PostgresqlTimestampFixtureTest.rb +2 -0
- data/test/excludes/PostgresqlTimestampMigrationTest.rb +3 -0
- data/test/excludes/PostgresqlTypeLookupTest.rb +2 -0
- data/test/excludes/PostgresqlUUIDGenerationTest.rb +7 -0
- data/test/excludes/PostgresqlUUIDTest.rb +1 -0
- data/test/excludes/PostgresqlVirtualColumnTest.rb +17 -0
- data/test/excludes/PostgresqlXMLTest.rb +5 -0
- data/test/excludes/PrimaryKeyIntegerNilDefaultTest.rb +1 -0
- data/test/excludes/PrimaryKeyIntegerTest.rb +3 -0
- data/test/excludes/PrimaryKeysTest.rb +2 -0
- data/test/excludes/RelationMergingTest.rb +15 -0
- data/test/excludes/RelationTest.rb +3 -0
- data/test/excludes/ReservedWordsMigrationTest.rb +1 -0
- data/test/excludes/SameNameDifferentDatabaseFixturesTest.rb +1 -0
- data/test/excludes/SanitizeTest.rb +13 -0
- data/test/excludes/SchemaAuthorizationTest.rb +8 -0
- data/test/excludes/SchemaCreateTableOptionsTest.rb +2 -0
- data/test/excludes/SchemaDumperDefaultsTest.rb +1 -0
- data/test/excludes/SchemaDumperTest.rb +11 -0
- data/test/excludes/SchemaForeignKeyTest.rb +1 -0
- data/test/excludes/SchemaIndexNullsOrderTest.rb +2 -0
- data/test/excludes/SchemaIndexOpclassTest.rb +3 -0
- data/test/excludes/SchemaTest.rb +49 -0
- data/test/excludes/SequenceNameDetectionTestCases/CollidedSequenceNameTest.rb +1 -0
- data/test/excludes/SequenceNameDetectionTestCases/LongerSequenceNameDetectionTest.rb +1 -0
- data/test/excludes/StrictLoadingFixturesTest.rb +1 -0
- data/test/excludes/TestFixturesTest.rb +1 -0
- data/test/excludes/TransactionInstrumentationTest.rb +1 -0
- data/test/excludes/TransactionIsolationTest.rb +1 -0
- data/test/excludes/TypeTest.rb +1 -0
- data/test/excludes/UniquenessValidationTest.rb +2 -0
- data/test/excludes/UnloggedTablesTest.rb +3 -0
- data/test/excludes/UnsafeRawSqlTest.rb +2 -0
- data/test/excludes/UpdateableViewTest.rb +5 -0
- data/test/excludes/WithAnnotationsTest.rb +6 -0
- data/test/models/building.rb +4 -0
- data/test/models/spatial_model.rb +5 -0
- data/test/schema/cockroachdb_specific_schema.rb +218 -0
- data/test/support/copy_cat.rb +83 -0
- data/test/support/exclude_from_transactional_tests.rb +33 -0
- data/test/support/paths_cockroachdb.rb +46 -0
- data/test/support/rake_helpers.rb +37 -0
- data/test/support/sql_logger.rb +55 -0
- data/test/support/template_creator.rb +114 -0
- metadata +422 -34
- data/.editorconfig +0 -7
- data/.github/issue_template.md +0 -46
- data/.github/reproduction_scripts/migrations.rb +0 -60
- data/.github/reproduction_scripts/models_and_database.rb +0 -49
- data/.github/workflows/ci.yml +0 -96
- data/.github/workflows/docker.yml +0 -57
- data/.gitignore +0 -18
- data/.gitmodules +0 -0
- data/activerecord-cockroachdb-adapter.gemspec +0 -38
- data/bin/console +0 -36
- data/bin/console_schemas/default.rb +0 -11
- data/bin/console_schemas/schemas.rb +0 -23
- data/bin/setup +0 -8
- data/bin/start-cockroachdb +0 -33
- data/build/Dockerfile +0 -14
- data/build/config.teamcity.yml +0 -31
- data/build/local-test.sh +0 -32
- data/build/teamcity-test.sh +0 -76
- data/docker.sh +0 -35
- data/lib/active_record/connection_adapters/cockroachdb/spatial_column_info.rb +0 -60
- data/setup.sql +0 -18
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "cases/migration/helper"
|
|
4
|
+
|
|
5
|
+
module ActiveRecord
|
|
6
|
+
module CockroachDB
|
|
7
|
+
class Migration
|
|
8
|
+
class ColumnsTest < ActiveRecord::TestCase
|
|
9
|
+
include ActiveRecord::Migration::TestHelper
|
|
10
|
+
|
|
11
|
+
self.use_transactional_tests = false
|
|
12
|
+
|
|
13
|
+
# This file replaces the same tests that have been excluded from ColumnsTest
|
|
14
|
+
# (see test/excludes/ActiveRecord/Migration/ColumnsTest.rb). New, unsaved
|
|
15
|
+
# records won't have string default values if the default has been changed
|
|
16
|
+
# in the database. This happens because once a column default is changed
|
|
17
|
+
# in CockroachDB, the type information on the value is missing.
|
|
18
|
+
# We can still verify the desired behavior by persisting the test records.
|
|
19
|
+
# When ActiveRecord fetches the records from the database, they'll have
|
|
20
|
+
# their default values.
|
|
21
|
+
|
|
22
|
+
def test_change_column_default
|
|
23
|
+
add_column "test_models", "first_name", :string
|
|
24
|
+
connection.change_column_default "test_models", "first_name", "Tester"
|
|
25
|
+
TestModel.reset_column_information
|
|
26
|
+
|
|
27
|
+
# Instead of using an unsaved TestModel record, persist one and fetch
|
|
28
|
+
# it from the database to get the new default value for type.
|
|
29
|
+
|
|
30
|
+
TestModel.create!
|
|
31
|
+
test_model = TestModel.last
|
|
32
|
+
assert_equal "Tester", test_model.first_name
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def test_change_column_default_with_from_and_to
|
|
36
|
+
add_column "test_models", "first_name", :string
|
|
37
|
+
connection.change_column_default "test_models", "first_name", from: nil, to: "Tester"
|
|
38
|
+
TestModel.reset_column_information
|
|
39
|
+
|
|
40
|
+
# Instead of using an unsaved TestModel record, persist one and fetch
|
|
41
|
+
# it from the database to get the new default value for type.
|
|
42
|
+
|
|
43
|
+
TestModel.create!
|
|
44
|
+
test_model = TestModel.last
|
|
45
|
+
assert_equal "Tester", test_model.first_name
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "cases/helper"
|
|
4
|
+
|
|
5
|
+
module ActiveRecord
|
|
6
|
+
module CockroachDB
|
|
7
|
+
class Migration
|
|
8
|
+
class CreateJoinTableTest < ActiveRecord::TestCase
|
|
9
|
+
attr_reader :connection
|
|
10
|
+
|
|
11
|
+
self.use_transactional_tests = false
|
|
12
|
+
|
|
13
|
+
def setup
|
|
14
|
+
super
|
|
15
|
+
@connection = ActiveRecord::Base.lease_connection
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
teardown do
|
|
19
|
+
%w(artists_musics musics_videos catalog).each do |table_name|
|
|
20
|
+
connection.drop_table table_name, if_exists: true
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# This test is identical to the one found in Rails, save for the fact
|
|
25
|
+
# that transactions are turned off for test runs. It is necessary to disable
|
|
26
|
+
# transactional tests in order to assert on schema changes due to how
|
|
27
|
+
# CockroachDB handles transactions.
|
|
28
|
+
def test_create_join_table_with_index
|
|
29
|
+
connection.create_join_table :artists, :musics do |t|
|
|
30
|
+
t.index [:artist_id, :music_id]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
assert_equal [%w(artist_id music_id)], connection.indexes(:artists_musics).map(&:columns)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# This test is identical to the one found in Rails, save for the fact
|
|
37
|
+
# that transactions are turned off for test runs. It is necessary to disable
|
|
38
|
+
# transactional tests in order to assert on schema changes due to how
|
|
39
|
+
# CockroachDB handles transactions.
|
|
40
|
+
def test_create_and_drop_join_table_with_common_prefix
|
|
41
|
+
with_table_cleanup do
|
|
42
|
+
connection.create_join_table "audio_artists", "audio_musics"
|
|
43
|
+
assert connection.table_exists?("audio_artists_musics")
|
|
44
|
+
|
|
45
|
+
connection.drop_join_table "audio_artists", "audio_musics"
|
|
46
|
+
assert !connection.table_exists?("audio_artists_musics"), "Should have dropped join table, but didn't"
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
private
|
|
51
|
+
|
|
52
|
+
def with_table_cleanup
|
|
53
|
+
tables_before = connection.data_sources
|
|
54
|
+
|
|
55
|
+
yield
|
|
56
|
+
ensure
|
|
57
|
+
tables_after = connection.data_sources - tables_before
|
|
58
|
+
|
|
59
|
+
tables_after.each do |table|
|
|
60
|
+
connection.drop_table table
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "cases/helper"
|
|
4
|
+
require "support/schema_dumping_helper"
|
|
5
|
+
|
|
6
|
+
module ActiveRecord
|
|
7
|
+
module CockroachDB
|
|
8
|
+
class Migration
|
|
9
|
+
class ForeignKeyTest < ActiveRecord::TestCase
|
|
10
|
+
include SchemaDumpingHelper
|
|
11
|
+
include ActiveSupport::Testing::Stream
|
|
12
|
+
|
|
13
|
+
# All of the following test cases are identical to the ones found in
|
|
14
|
+
# Rails, the only difference being that we have turned off transactional
|
|
15
|
+
# tests in the following line in order to properly assert on the various
|
|
16
|
+
# changes being tested.
|
|
17
|
+
self.use_transactional_tests = false
|
|
18
|
+
|
|
19
|
+
class Rocket < ActiveRecord::Base
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class Astronaut < ActiveRecord::Base
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
setup do
|
|
26
|
+
@connection = ActiveRecord::Base.lease_connection
|
|
27
|
+
@connection.create_table "rockets", force: true do |t|
|
|
28
|
+
t.string :name
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
@connection.create_table "astronauts", force: true do |t|
|
|
32
|
+
t.string :name
|
|
33
|
+
t.references :rocket
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
teardown do
|
|
38
|
+
@connection.drop_table "astronauts", if_exists: true
|
|
39
|
+
@connection.drop_table "rockets", if_exists: true
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def test_add_foreign_key_inferes_column
|
|
43
|
+
@connection.add_foreign_key :astronauts, :rockets
|
|
44
|
+
|
|
45
|
+
foreign_keys = @connection.foreign_keys("astronauts")
|
|
46
|
+
assert_equal 1, foreign_keys.size
|
|
47
|
+
|
|
48
|
+
fk = foreign_keys.first
|
|
49
|
+
assert_equal "astronauts", fk.from_table
|
|
50
|
+
assert_equal "rockets", fk.to_table
|
|
51
|
+
assert_equal "rocket_id", fk.column
|
|
52
|
+
assert_equal "id", fk.primary_key
|
|
53
|
+
assert_equal("fk_rails_78146ddd2e", fk.name)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def test_add_foreign_key_with_column
|
|
57
|
+
@connection.add_foreign_key :astronauts, :rockets, column: "rocket_id"
|
|
58
|
+
|
|
59
|
+
foreign_keys = @connection.foreign_keys("astronauts")
|
|
60
|
+
assert_equal 1, foreign_keys.size
|
|
61
|
+
|
|
62
|
+
fk = foreign_keys.first
|
|
63
|
+
assert_equal "astronauts", fk.from_table
|
|
64
|
+
assert_equal "rockets", fk.to_table
|
|
65
|
+
assert_equal "rocket_id", fk.column
|
|
66
|
+
assert_equal "id", fk.primary_key
|
|
67
|
+
assert_equal("fk_rails_78146ddd2e", fk.name)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def test_add_on_delete_restrict_foreign_key
|
|
71
|
+
@connection.add_foreign_key :astronauts, :rockets, column: "rocket_id", on_delete: :restrict
|
|
72
|
+
|
|
73
|
+
foreign_keys = @connection.foreign_keys("astronauts")
|
|
74
|
+
assert_equal 1, foreign_keys.size
|
|
75
|
+
|
|
76
|
+
fk = foreign_keys.first
|
|
77
|
+
assert_equal :restrict, fk.on_delete
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def test_add_on_delete_cascade_foreign_key
|
|
81
|
+
@connection.add_foreign_key :astronauts, :rockets, column: "rocket_id", on_delete: :cascade
|
|
82
|
+
|
|
83
|
+
foreign_keys = @connection.foreign_keys("astronauts")
|
|
84
|
+
assert_equal 1, foreign_keys.size
|
|
85
|
+
|
|
86
|
+
fk = foreign_keys.first
|
|
87
|
+
assert_equal :cascade, fk.on_delete
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def test_add_on_delete_nullify_foreign_key
|
|
91
|
+
@connection.add_foreign_key :astronauts, :rockets, column: "rocket_id", on_delete: :nullify
|
|
92
|
+
|
|
93
|
+
foreign_keys = @connection.foreign_keys("astronauts")
|
|
94
|
+
assert_equal 1, foreign_keys.size
|
|
95
|
+
|
|
96
|
+
fk = foreign_keys.first
|
|
97
|
+
assert_equal :nullify, fk.on_delete
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def test_add_foreign_key_with_on_update
|
|
101
|
+
@connection.add_foreign_key :astronauts, :rockets, column: "rocket_id", on_update: :nullify
|
|
102
|
+
|
|
103
|
+
foreign_keys = @connection.foreign_keys("astronauts")
|
|
104
|
+
assert_equal 1, foreign_keys.size
|
|
105
|
+
|
|
106
|
+
fk = foreign_keys.first
|
|
107
|
+
assert_equal :nullify, fk.on_update
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def test_foreign_key_exists
|
|
111
|
+
@connection.add_foreign_key :astronauts, :rockets
|
|
112
|
+
|
|
113
|
+
assert @connection.foreign_key_exists?(:astronauts, :rockets)
|
|
114
|
+
assert_not @connection.foreign_key_exists?(:astronauts, :stars)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def test_foreign_key_exists_by_column
|
|
118
|
+
@connection.add_foreign_key :astronauts, :rockets, column: "rocket_id"
|
|
119
|
+
|
|
120
|
+
assert @connection.foreign_key_exists?(:astronauts, column: "rocket_id")
|
|
121
|
+
assert_not @connection.foreign_key_exists?(:astronauts, column: "star_id")
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def test_foreign_key_exists_by_name
|
|
125
|
+
@connection.add_foreign_key :astronauts, :rockets, column: "rocket_id", name: "fancy_named_fk"
|
|
126
|
+
|
|
127
|
+
assert @connection.foreign_key_exists?(:astronauts, name: "fancy_named_fk")
|
|
128
|
+
assert_not @connection.foreign_key_exists?(:astronauts, name: "other_fancy_named_fk")
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def test_remove_foreign_key_inferes_column
|
|
132
|
+
@connection.add_foreign_key :astronauts, :rockets
|
|
133
|
+
|
|
134
|
+
assert_equal 1, @connection.foreign_keys("astronauts").size
|
|
135
|
+
@connection.remove_foreign_key :astronauts, :rockets
|
|
136
|
+
assert_equal [], @connection.foreign_keys("astronauts")
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def test_remove_foreign_key_by_column
|
|
140
|
+
@connection.add_foreign_key :astronauts, :rockets, column: "rocket_id"
|
|
141
|
+
|
|
142
|
+
assert_equal 1, @connection.foreign_keys("astronauts").size
|
|
143
|
+
@connection.remove_foreign_key :astronauts, column: "rocket_id"
|
|
144
|
+
assert_equal [], @connection.foreign_keys("astronauts")
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def test_remove_foreign_key_by_symbol_column
|
|
148
|
+
@connection.add_foreign_key :astronauts, :rockets, column: :rocket_id
|
|
149
|
+
|
|
150
|
+
assert_equal 1, @connection.foreign_keys("astronauts").size
|
|
151
|
+
@connection.remove_foreign_key :astronauts, column: :rocket_id
|
|
152
|
+
assert_equal [], @connection.foreign_keys("astronauts")
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def test_remove_foreign_key_by_name
|
|
156
|
+
@connection.add_foreign_key :astronauts, :rockets, column: "rocket_id", name: "fancy_named_fk"
|
|
157
|
+
|
|
158
|
+
assert_equal 1, @connection.foreign_keys("astronauts").size
|
|
159
|
+
@connection.remove_foreign_key :astronauts, name: "fancy_named_fk"
|
|
160
|
+
assert_equal [], @connection.foreign_keys("astronauts")
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def test_remove_foreign_key_by_the_select_one_on_the_same_table
|
|
164
|
+
@connection.add_foreign_key :astronauts, :rockets
|
|
165
|
+
@connection.add_reference :astronauts, :myrocket, foreign_key: { to_table: :rockets }
|
|
166
|
+
|
|
167
|
+
assert_equal 2, @connection.foreign_keys("astronauts").size
|
|
168
|
+
|
|
169
|
+
@connection.remove_foreign_key :astronauts, :rockets, column: "myrocket_id"
|
|
170
|
+
|
|
171
|
+
assert_equal [["astronauts", "rockets", "rocket_id"]],
|
|
172
|
+
@connection.foreign_keys("astronauts").map { |fk| [fk.from_table, fk.to_table, fk.column] }
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def test_add_invalid_foreign_key
|
|
176
|
+
@connection.add_foreign_key :astronauts, :rockets, column: "rocket_id", validate: false
|
|
177
|
+
|
|
178
|
+
foreign_keys = @connection.foreign_keys("astronauts")
|
|
179
|
+
assert_equal 1, foreign_keys.size
|
|
180
|
+
|
|
181
|
+
fk = foreign_keys.first
|
|
182
|
+
assert_not_predicate fk, :validated?
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def test_validate_foreign_key_infers_column
|
|
186
|
+
@connection.add_foreign_key :astronauts, :rockets, validate: false
|
|
187
|
+
assert_not_predicate @connection.foreign_keys("astronauts").first, :validated?
|
|
188
|
+
|
|
189
|
+
@connection.validate_foreign_key :astronauts, :rockets
|
|
190
|
+
assert_predicate @connection.foreign_keys("astronauts").first, :validated?
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def test_validate_foreign_key_by_column
|
|
194
|
+
@connection.add_foreign_key :astronauts, :rockets, column: "rocket_id", validate: false
|
|
195
|
+
assert_not_predicate @connection.foreign_keys("astronauts").first, :validated?
|
|
196
|
+
|
|
197
|
+
@connection.validate_foreign_key :astronauts, column: "rocket_id"
|
|
198
|
+
assert_predicate @connection.foreign_keys("astronauts").first, :validated?
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def test_validate_foreign_key_by_symbol_column
|
|
202
|
+
@connection.add_foreign_key :astronauts, :rockets, column: :rocket_id, validate: false
|
|
203
|
+
assert_not_predicate @connection.foreign_keys("astronauts").first, :validated?
|
|
204
|
+
|
|
205
|
+
@connection.validate_foreign_key :astronauts, column: :rocket_id
|
|
206
|
+
assert_predicate @connection.foreign_keys("astronauts").first, :validated?
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def test_validate_foreign_key_by_name
|
|
210
|
+
@connection.add_foreign_key :astronauts, :rockets, column: "rocket_id", name: "fancy_named_fk", validate: false
|
|
211
|
+
assert_not_predicate @connection.foreign_keys("astronauts").first, :validated?
|
|
212
|
+
|
|
213
|
+
@connection.validate_foreign_key :astronauts, name: "fancy_named_fk"
|
|
214
|
+
assert_predicate @connection.foreign_keys("astronauts").first, :validated?
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def test_validate_constraint_by_name
|
|
218
|
+
@connection.add_foreign_key :astronauts, :rockets, column: "rocket_id", name: "fancy_named_fk", validate: false
|
|
219
|
+
|
|
220
|
+
@connection.validate_constraint :astronauts, "fancy_named_fk"
|
|
221
|
+
assert_predicate @connection.foreign_keys("astronauts").first, :validated?
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
def test_schema_dumping
|
|
225
|
+
@connection.add_foreign_key :astronauts, :rockets
|
|
226
|
+
output = dump_table_schema "astronauts"
|
|
227
|
+
assert_match %r{\s+add_foreign_key "astronauts", "rockets"$}, output
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
class CreateCitiesAndHousesMigration < ActiveRecord::Migration::Current
|
|
231
|
+
def change
|
|
232
|
+
create_table("cities") { |t| }
|
|
233
|
+
|
|
234
|
+
create_table("houses") do |t|
|
|
235
|
+
t.references :city
|
|
236
|
+
end
|
|
237
|
+
add_foreign_key :houses, :cities, column: "city_id"
|
|
238
|
+
|
|
239
|
+
# remove and re-add to test that schema is updated and not accidentally cached
|
|
240
|
+
remove_foreign_key :houses, :cities
|
|
241
|
+
add_foreign_key :houses, :cities, column: "city_id", on_delete: :cascade
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
def test_add_foreign_key_is_reversible
|
|
246
|
+
migration = CreateCitiesAndHousesMigration.new
|
|
247
|
+
silence_stream($stdout) { migration.migrate(:up) }
|
|
248
|
+
assert_equal 1, @connection.foreign_keys("houses").size
|
|
249
|
+
ensure
|
|
250
|
+
silence_stream($stdout) { migration.migrate(:down) }
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
def test_foreign_key_constraint_is_not_cached_incorrectly
|
|
254
|
+
migration = CreateCitiesAndHousesMigration.new
|
|
255
|
+
silence_stream($stdout) { migration.migrate(:up) }
|
|
256
|
+
output = dump_table_schema "houses"
|
|
257
|
+
assert_match %r{\s+add_foreign_key "houses",.+on_delete: :cascade$}, output
|
|
258
|
+
ensure
|
|
259
|
+
silence_stream($stdout) { migration.migrate(:down) }
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
class CreateSchoolsAndClassesMigration < ActiveRecord::Migration::Current
|
|
263
|
+
def change
|
|
264
|
+
create_table(:schools)
|
|
265
|
+
|
|
266
|
+
create_table(:classes) do |t|
|
|
267
|
+
t.references :school
|
|
268
|
+
end
|
|
269
|
+
add_foreign_key :classes, :schools
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
def test_add_foreign_key_with_prefix
|
|
274
|
+
ActiveRecord::Base.table_name_prefix = "p_"
|
|
275
|
+
migration = CreateSchoolsAndClassesMigration.new
|
|
276
|
+
silence_stream($stdout) { migration.migrate(:up) }
|
|
277
|
+
assert_equal 1, @connection.foreign_keys("p_classes").size
|
|
278
|
+
ensure
|
|
279
|
+
silence_stream($stdout) { migration.migrate(:down) }
|
|
280
|
+
ActiveRecord::Base.table_name_prefix = nil
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
def test_add_foreign_key_with_suffix
|
|
284
|
+
ActiveRecord::Base.table_name_suffix = "_s"
|
|
285
|
+
migration = CreateSchoolsAndClassesMigration.new
|
|
286
|
+
silence_stream($stdout) { migration.migrate(:up) }
|
|
287
|
+
assert_equal 1, @connection.foreign_keys("classes_s").size
|
|
288
|
+
ensure
|
|
289
|
+
silence_stream($stdout) { migration.migrate(:down) }
|
|
290
|
+
ActiveRecord::Base.table_name_suffix = nil
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
def test_remove_foreign_key_with_if_exists_not_set
|
|
294
|
+
@connection.add_foreign_key :astronauts, :rockets
|
|
295
|
+
assert_equal 1, @connection.foreign_keys("astronauts").size
|
|
296
|
+
|
|
297
|
+
@connection.remove_foreign_key :astronauts, :rockets
|
|
298
|
+
assert_equal [], @connection.foreign_keys("astronauts")
|
|
299
|
+
|
|
300
|
+
error = assert_raises do
|
|
301
|
+
@connection.remove_foreign_key :astronauts, :rockets
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
assert_equal("Table 'astronauts' has no foreign key for rockets", error.message)
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
def test_remove_foreign_key_with_if_exists_set
|
|
308
|
+
@connection.add_foreign_key :astronauts, :rockets
|
|
309
|
+
assert_equal 1, @connection.foreign_keys("astronauts").size
|
|
310
|
+
|
|
311
|
+
@connection.remove_foreign_key :astronauts, :rockets
|
|
312
|
+
assert_equal [], @connection.foreign_keys("astronauts")
|
|
313
|
+
|
|
314
|
+
assert_nothing_raised do
|
|
315
|
+
@connection.remove_foreign_key :astronauts, :rockets, if_exists: true
|
|
316
|
+
end
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
def test_add_foreign_key_with_if_not_exists_not_set
|
|
320
|
+
@connection.add_foreign_key :astronauts, :rockets
|
|
321
|
+
assert_equal 1, @connection.foreign_keys("astronauts").size
|
|
322
|
+
|
|
323
|
+
if current_adapter?(:SQLite3Adapter)
|
|
324
|
+
assert_nothing_raised do
|
|
325
|
+
@connection.add_foreign_key :astronauts, :rockets
|
|
326
|
+
end
|
|
327
|
+
else
|
|
328
|
+
error = assert_raises do
|
|
329
|
+
@connection.add_foreign_key :astronauts, :rockets
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
if current_adapter?(:Mysql2Adapter)
|
|
333
|
+
if ActiveRecord::Base.lease_connection.mariadb?
|
|
334
|
+
assert_match(/Duplicate key on write or update/, error.message)
|
|
335
|
+
elsif ActiveRecord::Base.lease_connection.database_version < "5.6"
|
|
336
|
+
assert_match(/Can't create table/, error.message)
|
|
337
|
+
else
|
|
338
|
+
assert_match(/Duplicate foreign key constraint name/, error.message)
|
|
339
|
+
end
|
|
340
|
+
else
|
|
341
|
+
assert_match(/PG::DuplicateObject: ERROR: duplicate constraint name:*./, error.message)
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
end
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
def test_add_foreign_key_with_if_not_exists_set
|
|
348
|
+
@connection.add_foreign_key :astronauts, :rockets
|
|
349
|
+
assert_equal 1, @connection.foreign_keys("astronauts").size
|
|
350
|
+
|
|
351
|
+
assert_nothing_raised do
|
|
352
|
+
@connection.add_foreign_key :astronauts, :rockets, if_not_exists: true
|
|
353
|
+
end
|
|
354
|
+
end
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
class CompositeForeignKeyTest < ActiveRecord::TestCase
|
|
358
|
+
include SchemaDumpingHelper
|
|
359
|
+
|
|
360
|
+
self.use_transactional_tests = false
|
|
361
|
+
|
|
362
|
+
setup do
|
|
363
|
+
@connection = ActiveRecord::Base.lease_connection
|
|
364
|
+
@connection.create_table :rockets, primary_key: [:tenant_id, :id], force: true do |t|
|
|
365
|
+
t.integer :tenant_id
|
|
366
|
+
t.integer :id
|
|
367
|
+
end
|
|
368
|
+
@connection.create_table :astronauts, force: true do |t|
|
|
369
|
+
t.integer :rocket_id
|
|
370
|
+
t.integer :rocket_tenant_id
|
|
371
|
+
end
|
|
372
|
+
end
|
|
373
|
+
|
|
374
|
+
teardown do
|
|
375
|
+
@connection.drop_table :astronauts, if_exists: true
|
|
376
|
+
@connection.drop_table :rockets, if_exists: true
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
# OVERRIDE: CockroachDB does not quote the table name.
|
|
380
|
+
def test_add_composite_foreign_key_raises_without_options
|
|
381
|
+
error = assert_raises(ActiveRecord::StatementInvalid) do
|
|
382
|
+
@connection.add_foreign_key :astronauts, :rockets
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
assert_match(/there is no unique constraint matching given keys for referenced table rockets/, error.message)
|
|
386
|
+
end
|
|
387
|
+
end
|
|
388
|
+
end
|
|
389
|
+
end
|
|
390
|
+
end
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "cases/helper"
|
|
4
|
+
require "support/schema_dumping_helper"
|
|
5
|
+
|
|
6
|
+
module ActiveRecord
|
|
7
|
+
module CockroachDB
|
|
8
|
+
class Migration
|
|
9
|
+
class HiddenColumnTest < ActiveRecord::TestCase
|
|
10
|
+
include SchemaDumpingHelper
|
|
11
|
+
include ActiveSupport::Testing::Stream
|
|
12
|
+
|
|
13
|
+
self.use_transactional_tests = false
|
|
14
|
+
|
|
15
|
+
class Rocket < ActiveRecord::Base
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
class Astronaut < ActiveRecord::Base
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
setup do
|
|
22
|
+
@connection = ActiveRecord::Base.lease_connection
|
|
23
|
+
@connection.create_table "rockets", force: true do |t|
|
|
24
|
+
t.string :name
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
@connection.create_table "astronauts", force: true do |t|
|
|
28
|
+
t.string :name
|
|
29
|
+
t.bigint :secret_id, hidden: true
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
teardown do
|
|
34
|
+
@connection.drop_table "astronauts", if_exists: true
|
|
35
|
+
@connection.drop_table "rockets", if_exists: true
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# rowid is a special hidden column. CRDB implicitly adds it, so it should
|
|
39
|
+
# not appear in the schema dump.
|
|
40
|
+
def test_rowid_not_in_dump
|
|
41
|
+
output = dump_table_schema "rockets"
|
|
42
|
+
assert_match %r{create_table "rockets", id: false, force: :cascade do |t|"$}, output
|
|
43
|
+
assert_no_match %r{rowid}, output
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def test_hidden_column
|
|
47
|
+
output = dump_table_schema "astronauts"
|
|
48
|
+
assert_match %r{t.bigint "secret_id", hidden: true$}, output
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def test_add_hidden_column
|
|
52
|
+
@connection.add_column :rockets, :new_col, :uuid, hidden: true
|
|
53
|
+
output = dump_table_schema "rockets"
|
|
54
|
+
assert_match %r{t.uuid "new_col", hidden: true$}, output
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Since 24.2.2, hash sharded indexes add a hidden column to the table.
|
|
58
|
+
# This tests ensure that the user can still drop the index even if they
|
|
59
|
+
# call `#remove_index` with the column name rather than the index name.
|
|
60
|
+
def test_remove_index_with_a_hidden_column
|
|
61
|
+
@connection.execute <<-SQL
|
|
62
|
+
CREATE INDEX hash_idx ON rockets (name) USING HASH WITH (bucket_count=8);
|
|
63
|
+
SQL
|
|
64
|
+
@connection.remove_index :rockets, :name
|
|
65
|
+
assert :ok
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|