activerecord-cockroachdb-adapter 8.0.2 → 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 +7 -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 +42 -25
- 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
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f24596dd159836cb67f7a9f181e32e8370d01420cdb574a96bdf901e802b2669
|
|
4
|
+
data.tar.gz: 126991cc6c0e158ee27386132fc6cc046566720006b020df28cb5495e38d0a08
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ceab189ddbb6c54dbf586c2f3b70c520076c727447304d244924d75029d545fab8c4ebd6864ed00016c8c5cd04476141c64eb1758466cac6762162ce5fbf199e
|
|
7
|
+
data.tar.gz: 1a4fb49e5189772b207e1633c4375943fdee80f3cf8350372d53cf0f1f34a3e7e425a99ae504be585868e2f5565c4a5703bd428692de8d2cf8d0658c42b035d5
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
## Ongoing
|
|
4
4
|
|
|
5
|
+
## 8.01 - 2025-11-25
|
|
6
|
+
- Add support for Rails 8.1 ([#386](https://github.com/cockroachdb/activerecord-cockroachdb-adapter/pull/386))
|
|
7
|
+
|
|
8
|
+
## 8.0.3 - 2025-08-19
|
|
9
|
+
|
|
10
|
+
- Fixed the handling of column comments that end in a single quote ([#382](https://github.com/cockroachdb/activerecord-cockroachdb-adapter/pull/382))
|
|
11
|
+
|
|
5
12
|
## 8.0.2 - 2025-07-14
|
|
6
13
|
|
|
7
14
|
- Fixed the `db:migrate` command by removing usage of `execute_and_clear` function ([#377](https://github.com/cockroachdb/activerecord-cockroachdb-adapter/pull/377))
|
data/CONTRIBUTING.md
CHANGED
|
@@ -61,23 +61,16 @@ Only do it if you know the schema was left in a correct state.
|
|
|
61
61
|
|
|
62
62
|
### Run Tests from a Backup
|
|
63
63
|
|
|
64
|
-
Loading the full test schema every time a test runs can take
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
To load from the template, use the `COCKROACH_LOAD_FROM_TEMPLATE` flag.
|
|
75
|
-
|
|
76
|
-
```bash
|
|
77
|
-
COCKROACH_LOAD_FROM_TEMPLATE=1 TEST_FILES="test/cases/adapters/postgresql/ddl_test.rb" bundle exec rake test
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
And the `activerecord_unittest` database will use the `RESTORE` command to load the schema from the template database.
|
|
64
|
+
Loading the full test schema every time a test runs can take
|
|
65
|
+
a while, so for cases where loading the schema sequentially
|
|
66
|
+
is unimportant, it is possible to use a backup to set up the
|
|
67
|
+
database. This is significantly faster than the standard
|
|
68
|
+
method and is provided to run individual tests faster, but
|
|
69
|
+
should not be used to validate a build.
|
|
70
|
+
|
|
71
|
+
To do so, just set the env variable `COCKROACH_LOAD_FROM_TEMPLATE`.
|
|
72
|
+
First run will generate and cache a template, latter runs will use
|
|
73
|
+
it.
|
|
81
74
|
|
|
82
75
|
# Improvements
|
|
83
76
|
|
data/Gemfile
CHANGED
|
@@ -52,10 +52,11 @@ group :development, :test do
|
|
|
52
52
|
gem "msgpack", ">= 1.7.0"
|
|
53
53
|
gem "mutex_m", "~> 0.2.0"
|
|
54
54
|
|
|
55
|
+
gem "tracer"
|
|
55
56
|
gem "rake"
|
|
56
57
|
gem "debug"
|
|
58
|
+
gem "minitest-bisect", github: "BuonOmo/minitest-bisect", branch: "main"
|
|
57
59
|
gem "minitest-excludes", "~> 2.0.1"
|
|
58
|
-
gem "minitest-github_action_reporter", github: "BuonOmo/minitest-github_action_reporter", require: "minitest/github_action_reporter_plugin"
|
|
59
60
|
gem "ostruct", "~> 0.6"
|
|
60
61
|
|
|
61
62
|
# Gems used for tests meta-programming.
|
data/Rakefile
CHANGED
|
@@ -2,28 +2,9 @@ require "bundler/gem_tasks"
|
|
|
2
2
|
require "rake/testtask"
|
|
3
3
|
require_relative 'test/support/paths_cockroachdb'
|
|
4
4
|
require_relative 'test/support/rake_helpers'
|
|
5
|
-
require_relative 'test/support/template_creator'
|
|
6
5
|
|
|
7
6
|
task default: [:test]
|
|
8
7
|
|
|
9
|
-
namespace :db do
|
|
10
|
-
task "create_test_template" do
|
|
11
|
-
ENV['DEBUG_COCKROACHDB_ADAPTER'] = "1"
|
|
12
|
-
ENV['COCKROACH_SKIP_LOAD_SCHEMA'] = "1"
|
|
13
|
-
|
|
14
|
-
TemplateCreator.connect
|
|
15
|
-
require_relative 'test/cases/helper'
|
|
16
|
-
|
|
17
|
-
# TODO: look into this more, but for some reason the blob alias
|
|
18
|
-
# is not defined while running this task.
|
|
19
|
-
ActiveRecord::ConnectionAdapters::CockroachDB::TableDefinition.class_eval do
|
|
20
|
-
alias :blob :binary
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
TemplateCreator.create_test_template
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
|
|
27
8
|
Rake::TestTask.new do |t|
|
|
28
9
|
t.libs = ARTest::CockroachDB.test_load_paths
|
|
29
10
|
t.test_files = RakeHelpers.test_files
|
|
@@ -20,33 +20,29 @@ module ActiveRecord
|
|
|
20
20
|
class Column < PostgreSQL::Column
|
|
21
21
|
# most functions taken from activerecord-postgis-adapter spatial_column
|
|
22
22
|
# https://github.com/rgeo/activerecord-postgis-adapter/blob/master/lib/active_record/connection_adapters/postgis/spatial_column.rb
|
|
23
|
-
def initialize(name, default, sql_type_metadata = nil, null = true,
|
|
23
|
+
def initialize(name, cast_type, default, sql_type_metadata = nil, null = true,
|
|
24
24
|
default_function = nil, collation: nil, comment: nil, identity: nil,
|
|
25
|
-
serial: nil,
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
serial: nil, generated: nil, hidden: nil)
|
|
26
|
+
|
|
27
|
+
super(name, cast_type, default, sql_type_metadata, null, default_function,
|
|
28
|
+
collation: collation, comment: comment, serial: serial, generated: generated, identity: identity)
|
|
29
|
+
|
|
30
|
+
@geographic = sql_type_metadata.sql_type.match?(/geography\(/i)
|
|
28
31
|
@hidden = hidden
|
|
29
32
|
|
|
30
|
-
if
|
|
31
|
-
# This case comes from an entry in the geometry_columns table
|
|
32
|
-
set_geometric_type_from_name(spatial[:type])
|
|
33
|
-
@srid = spatial[:srid].to_i
|
|
34
|
-
@has_z = !!spatial[:has_z]
|
|
35
|
-
@has_m = !!spatial[:has_m]
|
|
36
|
-
elsif @geographic
|
|
33
|
+
if @geographic
|
|
37
34
|
# Geographic type information is embedded in the SQL type
|
|
38
35
|
@srid = 4326
|
|
39
36
|
@has_z = @has_m = false
|
|
40
37
|
build_from_sql_type(sql_type_metadata.sql_type)
|
|
41
|
-
elsif sql_type
|
|
38
|
+
elsif sql_type.match?(/geography|geometry|point|linestring|polygon/i)
|
|
42
39
|
build_from_sql_type(sql_type_metadata.sql_type)
|
|
43
|
-
elsif sql_type_metadata.sql_type
|
|
40
|
+
elsif sql_type_metadata.sql_type.match?(/geography|geometry|point|linestring|polygon/i)
|
|
44
41
|
# A geometry column with no geometry_columns entry.
|
|
45
42
|
# @geometric_type = geo_type_from_sql_type(sql_type)
|
|
46
43
|
build_from_sql_type(sql_type_metadata.sql_type)
|
|
47
44
|
end
|
|
48
|
-
|
|
49
|
-
collation: collation, comment: comment, serial: serial, generated: generated, identity: identity)
|
|
45
|
+
|
|
50
46
|
if spatial? && @srid
|
|
51
47
|
@limit = { srid: @srid, type: to_type_name(geometric_type) }
|
|
52
48
|
@limit[:has_z] = true if @has_z
|
|
@@ -59,20 +55,18 @@ module ActiveRecord
|
|
|
59
55
|
:geometric_type,
|
|
60
56
|
:has_m,
|
|
61
57
|
:has_z,
|
|
62
|
-
:srid
|
|
58
|
+
:srid,
|
|
59
|
+
:hidden
|
|
63
60
|
|
|
64
61
|
alias geographic? geographic
|
|
65
62
|
alias has_z? has_z
|
|
66
63
|
alias has_m? has_m
|
|
64
|
+
alias hidden? hidden
|
|
67
65
|
|
|
68
66
|
def limit
|
|
69
67
|
spatial? ? @limit : super
|
|
70
68
|
end
|
|
71
69
|
|
|
72
|
-
def hidden?
|
|
73
|
-
@hidden
|
|
74
|
-
end
|
|
75
|
-
|
|
76
70
|
def spatial?
|
|
77
71
|
%i[geometry geography].include?(@sql_type_metadata.type)
|
|
78
72
|
end
|
|
@@ -81,15 +75,63 @@ module ActiveRecord
|
|
|
81
75
|
default_function == 'unique_rowid()'
|
|
82
76
|
end
|
|
83
77
|
|
|
84
|
-
|
|
78
|
+
# TODO: add tests (see #390)
|
|
79
|
+
def init_with(coder)
|
|
80
|
+
@geographic = coder["geographic"]
|
|
81
|
+
@geometric_type = coder["geometric_type"]
|
|
82
|
+
@has_m = coder["has_m"]
|
|
83
|
+
@has_z = coder["has_z"]
|
|
84
|
+
@srid = coder["srid"]
|
|
85
|
+
@hidden = coder["hidden"]
|
|
86
|
+
@limit = coder["limit"]
|
|
87
|
+
super
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# TODO: add tests (see #390)
|
|
91
|
+
def encode_with(coder)
|
|
92
|
+
coder["geographic"] = @geographic
|
|
93
|
+
coder["geometric_type"] = @geometric_type
|
|
94
|
+
coder["has_m"] = @has_m
|
|
95
|
+
coder["has_z"] = @has_z
|
|
96
|
+
coder["srid"] = @srid
|
|
97
|
+
coder["hidden"] = @hidden
|
|
98
|
+
coder["limit"] = @limit
|
|
99
|
+
super
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# TODO: add tests (see #390)
|
|
103
|
+
def ==(other)
|
|
104
|
+
other.is_a?(Column) &&
|
|
105
|
+
super &&
|
|
106
|
+
other.geographic == geographic &&
|
|
107
|
+
other.geometric_type == geometric_type &&
|
|
108
|
+
other.has_m == has_m &&
|
|
109
|
+
other.has_z == has_z &&
|
|
110
|
+
other.srid == srid &&
|
|
111
|
+
other.hidden == hidden &&
|
|
112
|
+
other.limit == limit
|
|
85
113
|
|
|
86
|
-
def set_geometric_type_from_name(name)
|
|
87
|
-
@geometric_type = RGeo::ActiveRecord.geometric_type_from_name(name) || RGeo::Feature::Geometry
|
|
88
114
|
end
|
|
115
|
+
alias :eql? :==
|
|
116
|
+
|
|
117
|
+
# TODO: add tests (see #390)
|
|
118
|
+
def hash
|
|
119
|
+
Column.hash ^
|
|
120
|
+
super.hash ^
|
|
121
|
+
geographic.hash ^
|
|
122
|
+
geometric_type.hash ^
|
|
123
|
+
has_m.hash ^
|
|
124
|
+
has_z.hash ^
|
|
125
|
+
srid.hash ^
|
|
126
|
+
hidden.hash ^
|
|
127
|
+
limit.hash
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
private
|
|
89
131
|
|
|
90
132
|
def build_from_sql_type(sql_type)
|
|
91
133
|
geo_type, @srid, @has_z, @has_m = OID::Spatial.parse_sql_type(sql_type)
|
|
92
|
-
|
|
134
|
+
@geometric_type = RGeo::ActiveRecord.geometric_type_from_name(geo_type) || RGeo::Feature::Geometry
|
|
93
135
|
end
|
|
94
136
|
|
|
95
137
|
def to_type_name(geometric_type)
|
|
@@ -22,15 +22,25 @@ module ActiveRecord
|
|
|
22
22
|
def insert_fixtures_set(fixture_set, tables_to_delete = [])
|
|
23
23
|
fixture_inserts = build_fixture_statements(fixture_set)
|
|
24
24
|
table_deletes = tables_to_delete.map { |table| "DELETE FROM #{quote_table_name(table)}" }
|
|
25
|
-
statements = table_deletes + fixture_inserts
|
|
25
|
+
statements = (table_deletes + fixture_inserts).join(";")
|
|
26
26
|
|
|
27
|
+
# Since [rails pull request #52428][1], `#execute_batch` does not
|
|
28
|
+
# trigger a cache clear anymore. However, `#insert_fixtures_set`
|
|
29
|
+
# relies on that clear to ensure consistency. In the postgresql
|
|
30
|
+
# adapter, this is ensured by a call to `#execute` rather than
|
|
31
|
+
# `#execute_batch` in `#disable_referential_integrity`. Since
|
|
32
|
+
# we are not always calling `#disable_referential_integrity`,
|
|
33
|
+
# we need to ensure that the cache is cleared when running
|
|
34
|
+
# our statements by calling `#execute` instead of `#execute_batch`.
|
|
35
|
+
#
|
|
36
|
+
# [1]: https://github.com/rails/rails/pull/52428
|
|
27
37
|
begin # much faster without disabling referential integrity, worth trying.
|
|
28
38
|
transaction(requires_new: true) do
|
|
29
|
-
|
|
39
|
+
execute(statements, "Fixtures Load")
|
|
30
40
|
end
|
|
31
41
|
rescue
|
|
32
42
|
disable_referential_integrity do
|
|
33
|
-
|
|
43
|
+
execute(statements, "Fixtures Load")
|
|
34
44
|
end
|
|
35
45
|
end
|
|
36
46
|
end
|
|
@@ -74,7 +74,7 @@ module ActiveRecord
|
|
|
74
74
|
"https://github.com/cockroachdb/activerecord-cockroachdb-adapter/issues/new"
|
|
75
75
|
end
|
|
76
76
|
|
|
77
|
-
run_cmd("cockroach",
|
|
77
|
+
run_cmd("cockroach", "sql", "--set", "errexit=false", "--file", filename)
|
|
78
78
|
end
|
|
79
79
|
|
|
80
80
|
private
|
|
@@ -26,9 +26,22 @@ module ActiveRecord
|
|
|
26
26
|
# "geometry(Polygon,4326) NOT NULL"
|
|
27
27
|
# "geometry(Geography,4326)"
|
|
28
28
|
def initialize(oid, sql_type)
|
|
29
|
-
|
|
30
|
-
@
|
|
29
|
+
super()
|
|
30
|
+
@sql_type = sql_type.freeze
|
|
31
|
+
@factory_attrs = self.class
|
|
32
|
+
.parse_sql_type(sql_type)
|
|
33
|
+
.then { |geo_type, srid, has_z, has_m|
|
|
34
|
+
{
|
|
35
|
+
geo_type: geo_type.underscore.freeze,
|
|
36
|
+
srid: srid.freeze,
|
|
37
|
+
has_z: has_z.freeze,
|
|
38
|
+
has_m: has_m.freeze,
|
|
39
|
+
sql_type: type.to_s.freeze
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
.freeze
|
|
31
43
|
end
|
|
44
|
+
protected attr_reader :sql_type, :factory_attrs
|
|
32
45
|
|
|
33
46
|
# sql_type: geometry, geometry(Point), geometry(Point,4326), ...
|
|
34
47
|
#
|
|
@@ -59,15 +72,8 @@ module ActiveRecord
|
|
|
59
72
|
[geo_type, srid, has_z, has_m]
|
|
60
73
|
end
|
|
61
74
|
|
|
62
|
-
def spatial_factory
|
|
63
|
-
@spatial_factory ||=
|
|
64
|
-
RGeo::ActiveRecord::SpatialFactoryStore.instance.factory(
|
|
65
|
-
factory_attrs
|
|
66
|
-
)
|
|
67
|
-
end
|
|
68
|
-
|
|
69
75
|
def geographic?
|
|
70
|
-
@sql_type
|
|
76
|
+
@sql_type.start_with?("geography")
|
|
71
77
|
end
|
|
72
78
|
|
|
73
79
|
def spatial?
|
|
@@ -92,6 +98,19 @@ module ActiveRecord
|
|
|
92
98
|
.generate(geo_value)
|
|
93
99
|
end
|
|
94
100
|
|
|
101
|
+
# TODO: add tests (see #390)
|
|
102
|
+
def ==(other)
|
|
103
|
+
super &&
|
|
104
|
+
@sql_type == other.sql_type &&
|
|
105
|
+
@factory_attrs == other.factory_attrs
|
|
106
|
+
end
|
|
107
|
+
alias eql? ==
|
|
108
|
+
|
|
109
|
+
# TODO: add tests (see #390)
|
|
110
|
+
def hash
|
|
111
|
+
super ^ [@sql_type, @factory_attrs].hash
|
|
112
|
+
end
|
|
113
|
+
|
|
95
114
|
private
|
|
96
115
|
|
|
97
116
|
def cast_value(value)
|
|
@@ -108,7 +127,7 @@ module ActiveRecord
|
|
|
108
127
|
end
|
|
109
128
|
|
|
110
129
|
def binary_string?(string)
|
|
111
|
-
string[0] == "\x00" || string[0] == "\x01" || string[0, 4]
|
|
130
|
+
string[0] == "\x00" || string[0] == "\x01" || string[0, 4].match?(/[0-9a-fA-F]{4}/)
|
|
112
131
|
end
|
|
113
132
|
|
|
114
133
|
def wkt_parser(string)
|
|
@@ -119,14 +138,10 @@ module ActiveRecord
|
|
|
119
138
|
end
|
|
120
139
|
end
|
|
121
140
|
|
|
122
|
-
def
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
has_z: @has_z,
|
|
127
|
-
srid: @srid,
|
|
128
|
-
sql_type: type.to_s
|
|
129
|
-
}
|
|
141
|
+
def spatial_factory
|
|
142
|
+
RGeo::ActiveRecord::SpatialFactoryStore.instance.factory(
|
|
143
|
+
factory_attrs
|
|
144
|
+
)
|
|
130
145
|
end
|
|
131
146
|
end
|
|
132
147
|
end
|
|
@@ -34,7 +34,8 @@ module ActiveRecord
|
|
|
34
34
|
# but when creating objects, using RGeo features is more convenient than
|
|
35
35
|
# converting to WKB, so this does it automatically.
|
|
36
36
|
def quote(value)
|
|
37
|
-
|
|
37
|
+
case value
|
|
38
|
+
when Numeric
|
|
38
39
|
# NOTE: The fact that integers are quoted is important and helps
|
|
39
40
|
# mitigate a potential vulnerability.
|
|
40
41
|
#
|
|
@@ -42,9 +43,9 @@ module ActiveRecord
|
|
|
42
43
|
# - https://nvd.nist.gov/vuln/detail/CVE-2022-44566
|
|
43
44
|
# - https://github.com/cockroachdb/activerecord-cockroachdb-adapter/pull/280#discussion_r1288692977
|
|
44
45
|
"'#{quote_string(value.to_s)}'"
|
|
45
|
-
|
|
46
|
+
when RGeo::Feature::Geometry
|
|
46
47
|
"'#{RGeo::WKRep::WKBGenerator.new(hex_format: true, type_format: :ewkb, emit_ewkb_srid: true).generate(value)}'"
|
|
47
|
-
|
|
48
|
+
when RGeo::Cartesian::BoundingBox
|
|
48
49
|
"'#{value.min_x},#{value.min_y},#{value.max_x},#{value.max_y}'::box"
|
|
49
50
|
else
|
|
50
51
|
super
|
|
@@ -58,6 +59,21 @@ module ActiveRecord
|
|
|
58
59
|
# This is tested by `BasicsTest#test_default_in_local_time`.
|
|
59
60
|
super + value.strftime("%z")
|
|
60
61
|
end
|
|
62
|
+
|
|
63
|
+
# NOTE: This method should be private in future rails versions.
|
|
64
|
+
# Hence we should also make it private then.
|
|
65
|
+
#
|
|
66
|
+
# See https://github.com/rails/rails/blob/v8.1.1/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb#L190
|
|
67
|
+
def lookup_cast_type(sql_type)
|
|
68
|
+
type_map.lookup(
|
|
69
|
+
# oid
|
|
70
|
+
query_value("SELECT #{quote(sql_type)}::regtype::oid", "SCHEMA").to_i,
|
|
71
|
+
# fmod, not needed.
|
|
72
|
+
nil,
|
|
73
|
+
# details needed for `..::CockroachDB::OID::Spatial` (e.g. `geometry(point,3857)`)
|
|
74
|
+
sql_type
|
|
75
|
+
)
|
|
76
|
+
end
|
|
61
77
|
end
|
|
62
78
|
end
|
|
63
79
|
end
|
|
@@ -34,8 +34,47 @@ module ActiveRecord
|
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
def disable_referential_integrity
|
|
37
|
-
|
|
37
|
+
if transaction_open? && query_value("SHOW autocommit_before_ddl") == "off"
|
|
38
|
+
begin
|
|
39
|
+
yield
|
|
40
|
+
rescue ActiveRecord::InvalidForeignKey => e
|
|
41
|
+
warn <<-WARNING
|
|
42
|
+
WARNING: Rails was not able to disable referential integrity.
|
|
43
|
+
|
|
44
|
+
This is due to CockroachDB's need of committing transactions
|
|
45
|
+
before a schema change occurs. To bypass this, you can set
|
|
46
|
+
`autocommit_before_ddl: "on"` in your database configuration.
|
|
47
|
+
WARNING
|
|
48
|
+
raise e
|
|
49
|
+
end
|
|
50
|
+
else
|
|
51
|
+
foreign_keys = all_foreign_keys
|
|
52
|
+
|
|
53
|
+
remove_foreign_keys(foreign_keys)
|
|
54
|
+
|
|
55
|
+
# Prefixes and suffixes are added in add_foreign_key
|
|
56
|
+
# in AR7+ so we need to temporarily disable them here,
|
|
57
|
+
# otherwise prefixes/suffixes will be erroneously added.
|
|
58
|
+
old_prefix = ActiveRecord::Base.table_name_prefix
|
|
59
|
+
old_suffix = ActiveRecord::Base.table_name_suffix
|
|
60
|
+
|
|
61
|
+
begin
|
|
62
|
+
yield
|
|
63
|
+
ensure
|
|
64
|
+
ActiveRecord::Base.table_name_prefix = ""
|
|
65
|
+
ActiveRecord::Base.table_name_suffix = ""
|
|
66
|
+
|
|
67
|
+
add_foreign_keys(foreign_keys) # Never raises.
|
|
68
|
+
|
|
69
|
+
ActiveRecord::Base.table_name_prefix = old_prefix if defined?(old_prefix)
|
|
70
|
+
ActiveRecord::Base.table_name_suffix = old_suffix if defined?(old_suffix)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
38
74
|
|
|
75
|
+
private
|
|
76
|
+
|
|
77
|
+
def remove_foreign_keys(foreign_keys)
|
|
39
78
|
statements = foreign_keys.map do |foreign_key|
|
|
40
79
|
# We do not use the `#remove_foreign_key` method here because it
|
|
41
80
|
# checks for foreign keys existance in the schema cache. This method
|
|
@@ -46,47 +85,30 @@ module ActiveRecord
|
|
|
46
85
|
schema_creation.accept(at)
|
|
47
86
|
end
|
|
48
87
|
execute_batch(statements, "Disable referential integrity -> remove foreign keys")
|
|
88
|
+
end
|
|
49
89
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
#
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
# We avoid using `foreign_key_exists?` here because it checks the schema cache
|
|
67
|
-
# for every key. This method is performance critical for the test suite, hence
|
|
68
|
-
# we use the `#all_foreign_keys` method that only make one query to the database.
|
|
69
|
-
already_inserted_foreign_keys = all_foreign_keys
|
|
70
|
-
statements = foreign_keys.map do |foreign_key|
|
|
71
|
-
next if already_inserted_foreign_keys.any? { |fk| fk.from_table == foreign_key.from_table && fk.options[:name] == foreign_key.options[:name] }
|
|
72
|
-
|
|
73
|
-
options = foreign_key_options(foreign_key.from_table, foreign_key.to_table, foreign_key.options)
|
|
74
|
-
at = create_alter_table foreign_key.from_table
|
|
75
|
-
at.add_foreign_key foreign_key.to_table, options
|
|
76
|
-
|
|
77
|
-
schema_creation.accept(at)
|
|
78
|
-
end
|
|
79
|
-
execute_batch(statements.compact, "Disable referential integrity -> add foreign keys")
|
|
80
|
-
ensure
|
|
81
|
-
ActiveRecord::Base.table_name_prefix = old_prefix
|
|
82
|
-
ActiveRecord::Base.table_name_suffix = old_suffix
|
|
90
|
+
# NOTE: This method should never raise, otherwise we risk polluting table name
|
|
91
|
+
# prefixes and suffixes. The good thing is: if this happens, tests will crash
|
|
92
|
+
# hard, no way we miss it.
|
|
93
|
+
def add_foreign_keys(foreign_keys)
|
|
94
|
+
# We avoid using `foreign_key_exists?` here because it checks the schema cache
|
|
95
|
+
# for every key. This method is performance critical for the test suite, hence
|
|
96
|
+
# we use the `#all_foreign_keys` method that only make one query to the database.
|
|
97
|
+
already_inserted_foreign_keys = all_foreign_keys
|
|
98
|
+
statements = foreign_keys.map do |foreign_key|
|
|
99
|
+
next if already_inserted_foreign_keys.any? { |fk| fk.from_table == foreign_key.from_table && fk.options[:name] == foreign_key.options[:name] }
|
|
100
|
+
|
|
101
|
+
options = foreign_key_options(foreign_key.from_table, foreign_key.to_table, foreign_key.options)
|
|
102
|
+
at = create_alter_table foreign_key.from_table
|
|
103
|
+
at.add_foreign_key foreign_key.to_table, options
|
|
104
|
+
|
|
105
|
+
schema_creation.accept(at)
|
|
83
106
|
end
|
|
107
|
+
execute_batch(statements.compact, "Disable referential integrity -> add foreign keys")
|
|
84
108
|
end
|
|
85
109
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
# Copy/paste of the `#foreign_keys(table)` method adapted to return every single
|
|
89
|
-
# foreign key in the database.
|
|
110
|
+
# NOTE: Copy/paste of the `#foreign_keys(table)` method adapted
|
|
111
|
+
# to return every single foreign key in the database.
|
|
90
112
|
def all_foreign_keys
|
|
91
113
|
fk_info = internal_exec_query(<<~SQL, "SCHEMA")
|
|
92
114
|
SELECT CASE
|
|
@@ -99,14 +121,30 @@ module ActiveRecord
|
|
|
99
121
|
THEN ''
|
|
100
122
|
ELSE n2.nspname || '.'
|
|
101
123
|
END || t2.relname AS to_table,
|
|
102
|
-
|
|
103
|
-
|
|
124
|
+
c.conname AS name, c.confupdtype AS on_update, c.confdeltype AS on_delete, c.convalidated AS valid, c.condeferrable AS deferrable, c.condeferred AS deferred, c.conrelid, c.confrelid,
|
|
125
|
+
(
|
|
126
|
+
SELECT array_agg(a.attname ORDER BY idx)
|
|
127
|
+
FROM (
|
|
128
|
+
SELECT idx, c.conkey[idx] AS conkey_elem
|
|
129
|
+
FROM generate_subscripts(c.conkey, 1) AS idx
|
|
130
|
+
) indexed_conkeys
|
|
131
|
+
JOIN pg_attribute a ON a.attrelid = t1.oid
|
|
132
|
+
AND a.attnum = indexed_conkeys.conkey_elem
|
|
133
|
+
AND NOT a.attishidden
|
|
134
|
+
) AS conkey_names,
|
|
135
|
+
(
|
|
136
|
+
SELECT array_agg(a.attname ORDER BY idx)
|
|
137
|
+
FROM (
|
|
138
|
+
SELECT idx, c.confkey[idx] AS confkey_elem
|
|
139
|
+
FROM generate_subscripts(c.confkey, 1) AS idx
|
|
140
|
+
) indexed_confkeys
|
|
141
|
+
JOIN pg_attribute a ON a.attrelid = t2.oid
|
|
142
|
+
AND a.attnum = indexed_confkeys.confkey_elem
|
|
143
|
+
AND NOT a.attishidden
|
|
144
|
+
) AS confkey_names
|
|
104
145
|
FROM pg_constraint c
|
|
105
146
|
JOIN pg_class t1 ON c.conrelid = t1.oid
|
|
106
147
|
JOIN pg_class t2 ON c.confrelid = t2.oid
|
|
107
|
-
JOIN pg_attribute a1 ON a1.attnum = c.conkey[1] AND a1.attrelid = t1.oid
|
|
108
|
-
JOIN pg_attribute a2 ON a2.attnum = c.confkey[1] AND a2.attrelid = t2.oid
|
|
109
|
-
JOIN pg_namespace t3 ON c.connamespace = t3.oid
|
|
110
148
|
JOIN pg_namespace n1 ON t1.relnamespace = n1.oid
|
|
111
149
|
JOIN pg_namespace n2 ON t2.relnamespace = n2.oid
|
|
112
150
|
WHERE c.contype = 'f'
|
|
@@ -116,22 +154,16 @@ module ActiveRecord
|
|
|
116
154
|
fk_info.map do |row|
|
|
117
155
|
from_table = PostgreSQL::Utils.unquote_identifier(row["from_table"])
|
|
118
156
|
to_table = PostgreSQL::Utils.unquote_identifier(row["to_table"])
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
if conkey.size > 1
|
|
123
|
-
column = column_names_from_column_numbers(row["conrelid"], conkey)
|
|
124
|
-
primary_key = column_names_from_column_numbers(row["confrelid"], confkey)
|
|
125
|
-
else
|
|
126
|
-
column = PostgreSQL::Utils.unquote_identifier(row["column"])
|
|
127
|
-
primary_key = row["primary_key"]
|
|
128
|
-
end
|
|
157
|
+
|
|
158
|
+
column = decode_string_array(row["conkey_names"])
|
|
159
|
+
primary_key = decode_string_array(row["confkey_names"])
|
|
129
160
|
|
|
130
161
|
options = {
|
|
131
|
-
column: column,
|
|
162
|
+
column: column.size == 1 ? column.first : column,
|
|
132
163
|
name: row["name"],
|
|
133
|
-
primary_key: primary_key
|
|
164
|
+
primary_key: primary_key.size == 1 ? primary_key.first : primary_key
|
|
134
165
|
}
|
|
166
|
+
|
|
135
167
|
options[:on_delete] = extract_foreign_key_action(row["on_delete"])
|
|
136
168
|
options[:on_update] = extract_foreign_key_action(row["on_update"])
|
|
137
169
|
options[:deferrable] = extract_constraint_deferrable(row["deferrable"], row["deferred"])
|