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
|
@@ -20,6 +20,91 @@ module ActiveRecord
|
|
|
20
20
|
module SchemaStatements
|
|
21
21
|
include ActiveRecord::ConnectionAdapters::PostgreSQL::SchemaStatements
|
|
22
22
|
|
|
23
|
+
# OVERRIDE(v8.1.1):
|
|
24
|
+
# - prepend Utils with PostgreSQL::
|
|
25
|
+
# - handle hidden attributes
|
|
26
|
+
# Returns an array of indexes for the given table.
|
|
27
|
+
def indexes(table_name) # :nodoc:
|
|
28
|
+
scope = quoted_scope(table_name)
|
|
29
|
+
|
|
30
|
+
result = query(<<~SQL, "SCHEMA")
|
|
31
|
+
SELECT distinct i.relname, d.indisunique, d.indkey, pg_get_indexdef(d.indexrelid),
|
|
32
|
+
pg_catalog.obj_description(i.oid, 'pg_class') AS comment, d.indisvalid,
|
|
33
|
+
ARRAY(
|
|
34
|
+
SELECT pg_get_indexdef(d.indexrelid, k + 1, true)
|
|
35
|
+
FROM generate_subscripts(d.indkey, 1) AS k
|
|
36
|
+
ORDER BY k
|
|
37
|
+
) AS columns,
|
|
38
|
+
ARRAY(
|
|
39
|
+
SELECT a.attname
|
|
40
|
+
FROM pg_attribute a
|
|
41
|
+
WHERE a.attrelid = d.indexrelid AND a.attishidden
|
|
42
|
+
) AS hidden_columns
|
|
43
|
+
FROM pg_class t
|
|
44
|
+
INNER JOIN pg_index d ON t.oid = d.indrelid
|
|
45
|
+
INNER JOIN pg_class i ON d.indexrelid = i.oid
|
|
46
|
+
LEFT JOIN pg_namespace n ON n.oid = t.relnamespace
|
|
47
|
+
WHERE i.relkind IN ('i', 'I')
|
|
48
|
+
AND d.indisprimary = 'f'
|
|
49
|
+
AND t.relname = #{scope[:name]}
|
|
50
|
+
AND n.nspname = #{scope[:schema]}
|
|
51
|
+
ORDER BY i.relname
|
|
52
|
+
SQL
|
|
53
|
+
|
|
54
|
+
unquote = -> (column) {
|
|
55
|
+
PostgreSQL::Utils.unquote_identifier(column.strip.gsub('""', '"'))
|
|
56
|
+
}
|
|
57
|
+
result.map do |row|
|
|
58
|
+
index_name = row[0]
|
|
59
|
+
unique = row[1]
|
|
60
|
+
indkey = row[2].split(" ").map(&:to_i)
|
|
61
|
+
inddef = row[3]
|
|
62
|
+
comment = row[4]
|
|
63
|
+
valid = row[5]
|
|
64
|
+
columns = decode_string_array(row[6]).map(&unquote)
|
|
65
|
+
hidden_columns = decode_string_array(row[7]).map(&unquote)
|
|
66
|
+
|
|
67
|
+
using, expressions, include, nulls_not_distinct, where = inddef.scan(/ USING (\w+?) \((.+?)\)(?: INCLUDE \((.+?)\))?( NULLS NOT DISTINCT)?(?: WHERE (.+))?\z/m).flatten
|
|
68
|
+
|
|
69
|
+
orders = {}
|
|
70
|
+
opclasses = {}
|
|
71
|
+
include_columns = include ? include.split(",").map(&unquote) : []
|
|
72
|
+
|
|
73
|
+
if indkey.include?(0)
|
|
74
|
+
columns = expressions
|
|
75
|
+
else
|
|
76
|
+
# prevent INCLUDE and hidden columns from being matched
|
|
77
|
+
columns.reject! { |c| include_columns.include?(c) || hidden_columns.include?(c) }
|
|
78
|
+
|
|
79
|
+
# add info on sort order (only desc order is explicitly specified, asc is the default)
|
|
80
|
+
# and non-default opclasses
|
|
81
|
+
expressions.scan(/(?<column>\w+)"?\s?(?<opclass>\w+_ops(_\w+)?)?\s?(?<desc>DESC)?\s?(?<nulls>NULLS (?:FIRST|LAST))?/).each do |column, opclass, desc, nulls|
|
|
82
|
+
opclasses[column] = opclass.to_sym if opclass
|
|
83
|
+
if nulls
|
|
84
|
+
orders[column] = [desc, nulls].compact.join(" ")
|
|
85
|
+
else
|
|
86
|
+
orders[column] = :desc if desc
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
IndexDefinition.new(
|
|
92
|
+
table_name,
|
|
93
|
+
index_name,
|
|
94
|
+
unique,
|
|
95
|
+
columns,
|
|
96
|
+
orders: orders,
|
|
97
|
+
opclasses: opclasses,
|
|
98
|
+
where: where,
|
|
99
|
+
using: using.to_sym,
|
|
100
|
+
include: include_columns.presence,
|
|
101
|
+
nulls_not_distinct: nulls_not_distinct.present?,
|
|
102
|
+
comment: comment.presence,
|
|
103
|
+
valid: valid
|
|
104
|
+
)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
23
108
|
# OVERRIDE: We do not want to see the crdb_internal schema in the names.
|
|
24
109
|
#
|
|
25
110
|
# Returns an array of schema names.
|
|
@@ -27,16 +112,6 @@ module ActiveRecord
|
|
|
27
112
|
super - ["crdb_internal"]
|
|
28
113
|
end
|
|
29
114
|
|
|
30
|
-
def add_index(table_name, column_name, **options)
|
|
31
|
-
super
|
|
32
|
-
rescue ActiveRecord::StatementInvalid => error
|
|
33
|
-
if debugging? && error.cause.class == PG::FeatureNotSupported
|
|
34
|
-
warn "#{error}\n\nThis error will be ignored and the index will not be created.\n\n"
|
|
35
|
-
else
|
|
36
|
-
raise error
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
|
|
40
115
|
# ActiveRecord allows for tables to exist without primary keys.
|
|
41
116
|
# Databases like PostgreSQL support this behavior, but CockroachDB does
|
|
42
117
|
# not. If a table is created without a primary key, CockroachDB will add
|
|
@@ -55,34 +130,18 @@ module ActiveRecord
|
|
|
55
130
|
end
|
|
56
131
|
end
|
|
57
132
|
|
|
133
|
+
# OVERRIDE(v8.1.1): handle hidden attributes
|
|
58
134
|
def primary_keys(table_name)
|
|
59
|
-
return super unless database_version >= 24_02_02
|
|
60
|
-
|
|
61
135
|
query_values(<<~SQL, "SCHEMA")
|
|
62
136
|
SELECT a.attname
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
AND a.attnum = i.indkey[i.idx]
|
|
72
|
-
AND NOT a.attishidden
|
|
73
|
-
ORDER BY i.idx
|
|
74
|
-
SQL
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
def column_names_from_column_numbers(table_oid, column_numbers)
|
|
78
|
-
return super unless database_version >= 24_02_02
|
|
79
|
-
|
|
80
|
-
Hash[query(<<~SQL, "SCHEMA")].values_at(*column_numbers).compact
|
|
81
|
-
SELECT a.attnum, a.attname
|
|
82
|
-
FROM pg_attribute a
|
|
83
|
-
WHERE a.attrelid = #{table_oid}
|
|
84
|
-
AND a.attnum IN (#{column_numbers.join(", ")})
|
|
85
|
-
AND NOT a.attishidden
|
|
137
|
+
FROM pg_index i
|
|
138
|
+
JOIN pg_attribute a
|
|
139
|
+
ON a.attrelid = i.indrelid
|
|
140
|
+
AND a.attnum = ANY(i.indkey)
|
|
141
|
+
AND NOT a.attishidden
|
|
142
|
+
WHERE i.indrelid = #{quote(quote_table_name(table_name))}::regclass
|
|
143
|
+
AND i.indisprimary
|
|
144
|
+
ORDER BY array_position(i.indkey, a.attnum)
|
|
86
145
|
SQL
|
|
87
146
|
end
|
|
88
147
|
|
|
@@ -94,7 +153,7 @@ module ActiveRecord
|
|
|
94
153
|
options
|
|
95
154
|
end
|
|
96
155
|
|
|
97
|
-
# OVERRIDE: Added `unique_rowid` to the last line of the second query.
|
|
156
|
+
# OVERRIDE(v8.1.1): Added `unique_rowid` to the last line of the second query.
|
|
98
157
|
# This is a CockroachDB-specific function used for primary keys.
|
|
99
158
|
# Also make sure we don't consider `NOT VISIBLE` columns.
|
|
100
159
|
#
|
|
@@ -108,11 +167,7 @@ module ActiveRecord
|
|
|
108
167
|
pg_attribute attr,
|
|
109
168
|
pg_depend dep,
|
|
110
169
|
pg_constraint cons,
|
|
111
|
-
pg_namespace nsp
|
|
112
|
-
-- TODO: use the pg_catalog.pg_attribute(attishidden) column when
|
|
113
|
-
-- it is added instead of joining on crdb_internal.
|
|
114
|
-
-- See https://github.com/cockroachdb/cockroach/pull/126397
|
|
115
|
-
crdb_internal.table_columns tc
|
|
170
|
+
pg_namespace nsp
|
|
116
171
|
WHERE seq.oid = dep.objid
|
|
117
172
|
AND seq.relkind = 'S'
|
|
118
173
|
AND attr.attrelid = dep.refobjid
|
|
@@ -120,12 +175,10 @@ module ActiveRecord
|
|
|
120
175
|
AND attr.attrelid = cons.conrelid
|
|
121
176
|
AND attr.attnum = cons.conkey[1]
|
|
122
177
|
AND seq.relnamespace = nsp.oid
|
|
123
|
-
AND attr.attrelid = tc.descriptor_id
|
|
124
|
-
AND attr.attname = tc.column_name
|
|
125
|
-
AND tc.hidden = false
|
|
126
178
|
AND cons.contype = 'p'
|
|
127
179
|
AND dep.classid = 'pg_class'::regclass
|
|
128
180
|
AND dep.refobjid = #{quote(quote_table_name(table))}::regclass
|
|
181
|
+
AND not attr.attishidden
|
|
129
182
|
SQL
|
|
130
183
|
|
|
131
184
|
if result.nil? || result.empty?
|
|
@@ -143,12 +196,8 @@ module ActiveRecord
|
|
|
143
196
|
JOIN pg_attrdef def ON (adrelid = attrelid AND adnum = attnum)
|
|
144
197
|
JOIN pg_constraint cons ON (conrelid = adrelid AND adnum = conkey[1])
|
|
145
198
|
JOIN pg_namespace nsp ON (t.relnamespace = nsp.oid)
|
|
146
|
-
-- TODO: use the pg_catalog.pg_attribute(attishidden) column when
|
|
147
|
-
-- it is added instead of joining on crdb_internal.
|
|
148
|
-
-- See https://github.com/cockroachdb/cockroach/pull/126397
|
|
149
|
-
JOIN crdb_internal.table_columns tc ON (attr.attrelid = tc.descriptor_id AND attr.attname = tc.column_name)
|
|
150
199
|
WHERE t.oid = #{quote(quote_table_name(table))}::regclass
|
|
151
|
-
AND
|
|
200
|
+
AND NOT attr.attishidden
|
|
152
201
|
AND cons.contype = 'p'
|
|
153
202
|
AND pg_get_expr(def.adbin, def.adrelid) ~* 'nextval|uuid_generate|gen_random_uuid|unique_rowid'
|
|
154
203
|
SQL
|
|
@@ -164,53 +213,66 @@ module ActiveRecord
|
|
|
164
213
|
nil
|
|
165
214
|
end
|
|
166
215
|
|
|
167
|
-
#
|
|
168
|
-
#
|
|
169
|
-
#
|
|
170
|
-
#
|
|
171
|
-
#
|
|
172
|
-
#
|
|
216
|
+
# OVERRIDE(v8.1.1):
|
|
217
|
+
# - Replaces t2.oid::regclass::text with t2.relname
|
|
218
|
+
# since this is more efficient in CockroachDB.
|
|
219
|
+
# - prepend schema name to relname (see `AS to_table`)
|
|
220
|
+
# - handle hidden attributes.
|
|
221
|
+
#
|
|
222
|
+
# NOTE: If you edit this method, you'll need to edit
|
|
223
|
+
# the `#all_foreign_keys` method as well.
|
|
173
224
|
def foreign_keys(table_name)
|
|
174
225
|
scope = quoted_scope(table_name)
|
|
175
|
-
fk_info = internal_exec_query(<<~SQL, "SCHEMA")
|
|
226
|
+
fk_info = internal_exec_query(<<~SQL, "SCHEMA", allow_retry: true, materialize_transactions: false)
|
|
176
227
|
SELECT CASE
|
|
177
228
|
WHEN n2.nspname = current_schema()
|
|
178
229
|
THEN ''
|
|
179
230
|
ELSE n2.nspname || '.'
|
|
180
231
|
END || t2.relname AS to_table,
|
|
181
|
-
|
|
182
|
-
|
|
232
|
+
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,
|
|
233
|
+
(
|
|
234
|
+
SELECT array_agg(a.attname ORDER BY idx)
|
|
235
|
+
FROM (
|
|
236
|
+
SELECT idx, c.conkey[idx] AS conkey_elem
|
|
237
|
+
FROM generate_subscripts(c.conkey, 1) AS idx
|
|
238
|
+
) indexed_conkeys
|
|
239
|
+
JOIN pg_attribute a ON a.attrelid = t1.oid
|
|
240
|
+
AND a.attnum = indexed_conkeys.conkey_elem
|
|
241
|
+
AND NOT a.attishidden
|
|
242
|
+
) AS conkey_names,
|
|
243
|
+
(
|
|
244
|
+
SELECT array_agg(a.attname ORDER BY idx)
|
|
245
|
+
FROM (
|
|
246
|
+
SELECT idx, c.confkey[idx] AS confkey_elem
|
|
247
|
+
FROM generate_subscripts(c.confkey, 1) AS idx
|
|
248
|
+
) indexed_confkeys
|
|
249
|
+
JOIN pg_attribute a ON a.attrelid = t2.oid
|
|
250
|
+
AND a.attnum = indexed_confkeys.confkey_elem
|
|
251
|
+
AND NOT a.attishidden
|
|
252
|
+
) AS confkey_names
|
|
183
253
|
FROM pg_constraint c
|
|
184
254
|
JOIN pg_class t1 ON c.conrelid = t1.oid
|
|
185
255
|
JOIN pg_class t2 ON c.confrelid = t2.oid
|
|
186
|
-
JOIN
|
|
187
|
-
JOIN pg_attribute a2 ON a2.attnum = c.confkey[1] AND a2.attrelid = t2.oid
|
|
188
|
-
JOIN pg_namespace t3 ON c.connamespace = t3.oid
|
|
256
|
+
JOIN pg_namespace n1 ON t1.relnamespace = n1.oid
|
|
189
257
|
JOIN pg_namespace n2 ON t2.relnamespace = n2.oid
|
|
190
258
|
WHERE c.contype = 'f'
|
|
191
259
|
AND t1.relname = #{scope[:name]}
|
|
192
|
-
AND
|
|
260
|
+
AND n1.nspname = #{scope[:schema]}
|
|
193
261
|
ORDER BY c.conname
|
|
194
262
|
SQL
|
|
195
263
|
|
|
196
264
|
fk_info.map do |row|
|
|
197
265
|
to_table = PostgreSQL::Utils.unquote_identifier(row["to_table"])
|
|
198
|
-
conkey = row["conkey"].scan(/\d+/).map(&:to_i)
|
|
199
|
-
confkey = row["confkey"].scan(/\d+/).map(&:to_i)
|
|
200
266
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
primary_key = column_names_from_column_numbers(row["confrelid"], confkey)
|
|
204
|
-
else
|
|
205
|
-
column = PostgreSQL::Utils.unquote_identifier(row["column"])
|
|
206
|
-
primary_key = row["primary_key"]
|
|
207
|
-
end
|
|
267
|
+
column = decode_string_array(row["conkey_names"])
|
|
268
|
+
primary_key = decode_string_array(row["confkey_names"])
|
|
208
269
|
|
|
209
270
|
options = {
|
|
210
|
-
column: column,
|
|
271
|
+
column: column.size == 1 ? column.first : column,
|
|
211
272
|
name: row["name"],
|
|
212
|
-
primary_key: primary_key
|
|
273
|
+
primary_key: primary_key.size == 1 ? primary_key.first : primary_key
|
|
213
274
|
}
|
|
275
|
+
|
|
214
276
|
options[:on_delete] = extract_foreign_key_action(row["on_delete"])
|
|
215
277
|
options[:on_update] = extract_foreign_key_action(row["on_update"])
|
|
216
278
|
options[:deferrable] = extract_constraint_deferrable(row["deferrable"], row["deferred"])
|
|
@@ -228,8 +290,51 @@ module ActiveRecord
|
|
|
228
290
|
nil
|
|
229
291
|
end
|
|
230
292
|
|
|
231
|
-
#
|
|
232
|
-
#
|
|
293
|
+
# OVERRIDE(v8.1.1): handle hidden attributes
|
|
294
|
+
#
|
|
295
|
+
# Returns an array of unique constraints for the given table.
|
|
296
|
+
# The unique constraints are represented as UniqueConstraintDefinition objects.
|
|
297
|
+
def unique_constraints(table_name)
|
|
298
|
+
scope = quoted_scope(table_name)
|
|
299
|
+
|
|
300
|
+
unique_info = internal_exec_query(<<~SQL, "SCHEMA", allow_retry: true, materialize_transactions: false)
|
|
301
|
+
SELECT c.conname, c.conrelid, c.condeferrable, c.condeferred, pg_get_constraintdef(c.oid) AS constraintdef,
|
|
302
|
+
(
|
|
303
|
+
SELECT array_agg(a.attname ORDER BY idx)
|
|
304
|
+
FROM (
|
|
305
|
+
SELECT idx, c.conkey[idx] AS conkey_elem
|
|
306
|
+
FROM generate_subscripts(c.conkey, 1) AS idx
|
|
307
|
+
) indexed_conkeys
|
|
308
|
+
JOIN pg_attribute a ON a.attrelid = t.oid
|
|
309
|
+
AND a.attnum = indexed_conkeys.conkey_elem
|
|
310
|
+
AND NOT a.attishidden
|
|
311
|
+
) AS conkey_names
|
|
312
|
+
FROM pg_constraint c
|
|
313
|
+
JOIN pg_class t ON c.conrelid = t.oid
|
|
314
|
+
JOIN pg_namespace n ON n.oid = c.connamespace
|
|
315
|
+
WHERE c.contype = 'u'
|
|
316
|
+
AND t.relname = #{scope[:name]}
|
|
317
|
+
AND n.nspname = #{scope[:schema]}
|
|
318
|
+
SQL
|
|
319
|
+
|
|
320
|
+
unique_info.map do |row|
|
|
321
|
+
columns = decode_string_array(row["conkey_names"])
|
|
322
|
+
|
|
323
|
+
nulls_not_distinct = row["constraintdef"].start_with?("UNIQUE NULLS NOT DISTINCT")
|
|
324
|
+
deferrable = extract_constraint_deferrable(row["condeferrable"], row["condeferred"])
|
|
325
|
+
|
|
326
|
+
options = {
|
|
327
|
+
name: row["conname"],
|
|
328
|
+
nulls_not_distinct: nulls_not_distinct,
|
|
329
|
+
deferrable: deferrable
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
UniqueConstraintDefinition.new(table_name, columns, options)
|
|
333
|
+
end
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
# OVERRIDE(v8.1.1):
|
|
337
|
+
# - Add hidden information
|
|
233
338
|
def new_column_from_field(table_name, field, _definition)
|
|
234
339
|
column_name, type, default, notnull, oid, fmod, collation, comment, identity, attgenerated, hidden = field
|
|
235
340
|
type_metadata = fetch_type_metadata(column_name, type, oid.to_i, fmod.to_i)
|
|
@@ -245,11 +350,9 @@ module ActiveRecord
|
|
|
245
350
|
serial = sequence_name_from_parts(table_name, column_name, match[:suffix]) == match[:sequence_name]
|
|
246
351
|
end
|
|
247
352
|
|
|
248
|
-
# {:dimension=>2, :has_m=>false, :has_z=>false, :name=>"latlon", :srid=>0, :type=>"GEOMETRY"}
|
|
249
|
-
spatial = spatial_column_info(table_name).get(column_name, type_metadata.sql_type)
|
|
250
|
-
|
|
251
353
|
CockroachDB::Column.new(
|
|
252
354
|
column_name,
|
|
355
|
+
get_oid_type(oid.to_i, fmod.to_i, column_name, type),
|
|
253
356
|
default_value,
|
|
254
357
|
type_metadata,
|
|
255
358
|
!notnull,
|
|
@@ -258,7 +361,6 @@ module ActiveRecord
|
|
|
258
361
|
comment: comment.presence,
|
|
259
362
|
serial: serial,
|
|
260
363
|
identity: identity.presence,
|
|
261
|
-
spatial: spatial,
|
|
262
364
|
generated: attgenerated,
|
|
263
365
|
hidden: hidden
|
|
264
366
|
)
|
|
@@ -295,34 +397,11 @@ module ActiveRecord
|
|
|
295
397
|
sql
|
|
296
398
|
end
|
|
297
399
|
|
|
298
|
-
# override
|
|
299
|
-
def native_database_types
|
|
300
|
-
# Add spatial types
|
|
301
|
-
super.merge(
|
|
302
|
-
geography: { name: "geography" },
|
|
303
|
-
geometry: { name: "geometry" },
|
|
304
|
-
geometry_collection: { name: "geometry_collection" },
|
|
305
|
-
line_string: { name: "line_string" },
|
|
306
|
-
multi_line_string: { name: "multi_line_string" },
|
|
307
|
-
multi_point: { name: "multi_point" },
|
|
308
|
-
multi_polygon: { name: "multi_polygon" },
|
|
309
|
-
spatial: { name: "geometry" },
|
|
310
|
-
st_point: { name: "st_point" },
|
|
311
|
-
st_polygon: { name: "st_polygon" }
|
|
312
|
-
)
|
|
313
|
-
end
|
|
314
|
-
|
|
315
400
|
# override
|
|
316
401
|
def create_table_definition(*args, **kwargs)
|
|
317
402
|
CockroachDB::TableDefinition.new(self, *args, **kwargs)
|
|
318
403
|
end
|
|
319
404
|
|
|
320
|
-
# memoize hash of column infos for tables
|
|
321
|
-
def spatial_column_info(table_name)
|
|
322
|
-
@spatial_column_info ||= {}
|
|
323
|
-
@spatial_column_info[table_name.to_sym] ||= SpatialColumnInfo.new(self, table_name.to_s)
|
|
324
|
-
end
|
|
325
|
-
|
|
326
405
|
def create_schema_dumper(options)
|
|
327
406
|
CockroachDB::SchemaDumper.create(self, options)
|
|
328
407
|
end
|
|
@@ -30,7 +30,6 @@ require "active_record/connection_adapters/cockroachdb/table_definition"
|
|
|
30
30
|
require "active_record/connection_adapters/cockroachdb/quoting"
|
|
31
31
|
require "active_record/connection_adapters/cockroachdb/type"
|
|
32
32
|
require "active_record/connection_adapters/cockroachdb/column"
|
|
33
|
-
require "active_record/connection_adapters/cockroachdb/spatial_column_info"
|
|
34
33
|
require "active_record/connection_adapters/cockroachdb/setup"
|
|
35
34
|
require "active_record/connection_adapters/cockroachdb/oid/spatial"
|
|
36
35
|
require "active_record/connection_adapters/cockroachdb/oid/interval"
|
|
@@ -111,6 +110,23 @@ module ActiveRecord
|
|
|
111
110
|
SPATIAL_COLUMN_OPTIONS[key]
|
|
112
111
|
end
|
|
113
112
|
|
|
113
|
+
def self.native_database_types
|
|
114
|
+
return @native_database_types if defined?(@native_database_types)
|
|
115
|
+
# Add spatial types
|
|
116
|
+
@native_database_types = super.merge(
|
|
117
|
+
geography: { name: "geography" },
|
|
118
|
+
geometry: { name: "geometry" },
|
|
119
|
+
geometry_collection: { name: "geometry_collection" },
|
|
120
|
+
line_string: { name: "line_string" },
|
|
121
|
+
multi_line_string: { name: "multi_line_string" },
|
|
122
|
+
multi_point: { name: "multi_point" },
|
|
123
|
+
multi_polygon: { name: "multi_polygon" },
|
|
124
|
+
spatial: { name: "geometry" },
|
|
125
|
+
st_point: { name: "st_point" },
|
|
126
|
+
st_polygon: { name: "st_polygon" }
|
|
127
|
+
)
|
|
128
|
+
end
|
|
129
|
+
|
|
114
130
|
def postgis_lib_version
|
|
115
131
|
@postgis_lib_version ||= select_value("SELECT PostGIS_Lib_Version()")
|
|
116
132
|
end
|
|
@@ -128,10 +144,6 @@ module ActiveRecord
|
|
|
128
144
|
}
|
|
129
145
|
end
|
|
130
146
|
|
|
131
|
-
def debugging?
|
|
132
|
-
!!ENV["DEBUG_COCKROACHDB_ADAPTER"]
|
|
133
|
-
end
|
|
134
|
-
|
|
135
147
|
def max_transaction_retries
|
|
136
148
|
@max_transaction_retries ||= @config.fetch(:max_transaction_retries, 3)
|
|
137
149
|
end
|
|
@@ -233,6 +245,10 @@ module ActiveRecord
|
|
|
233
245
|
false
|
|
234
246
|
end
|
|
235
247
|
|
|
248
|
+
def supports_close_prepared?
|
|
249
|
+
true
|
|
250
|
+
end
|
|
251
|
+
|
|
236
252
|
def check_version # :nodoc:
|
|
237
253
|
# https://www.cockroachlabs.com/docs/releases/release-support-policy
|
|
238
254
|
if database_version < 23_01_12 # < 23.1.12
|
|
@@ -299,7 +315,7 @@ module ActiveRecord
|
|
|
299
315
|
st_polygon
|
|
300
316
|
).each do |geo_type|
|
|
301
317
|
m.register_type(geo_type) do |oid, _, sql_type|
|
|
302
|
-
CockroachDB::OID::Spatial.new(oid, sql_type)
|
|
318
|
+
CockroachDB::OID::Spatial.new(oid, sql_type).freeze
|
|
303
319
|
end
|
|
304
320
|
end
|
|
305
321
|
|
|
@@ -378,18 +394,10 @@ module ActiveRecord
|
|
|
378
394
|
nil
|
|
379
395
|
end
|
|
380
396
|
|
|
381
|
-
#
|
|
382
|
-
#
|
|
383
|
-
#
|
|
384
|
-
#
|
|
385
|
-
# as the field parameter. This data is then used to format the column
|
|
386
|
-
# objects for the model and sent to the OID for data casting.
|
|
387
|
-
#
|
|
388
|
-
# Sometimes there are differences between how data is formatted
|
|
389
|
-
# in Postgres and CockroachDB, so additional queries for certain types
|
|
390
|
-
# may be necessary to properly form the column definition.
|
|
391
|
-
#
|
|
392
|
-
# @see: https://github.com/rails/rails/blob/8695b028261bdd244e254993255c6641bdbc17a5/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb#L829
|
|
397
|
+
# OVERRIDE(v8.1.1):
|
|
398
|
+
# - comment is retrieved differently than PG for performance
|
|
399
|
+
# - gather detailed information about spatial columns. See
|
|
400
|
+
# `#crdb_column_definitions`
|
|
393
401
|
def column_definitions(table_name)
|
|
394
402
|
fields = query(<<~SQL, "SCHEMA")
|
|
395
403
|
SELECT a.attname, format_type(a.atttypid, a.atttypmod),
|
|
@@ -397,7 +405,7 @@ module ActiveRecord
|
|
|
397
405
|
c.collname, NULL AS comment,
|
|
398
406
|
attidentity,
|
|
399
407
|
attgenerated,
|
|
400
|
-
|
|
408
|
+
a.attishidden
|
|
401
409
|
FROM pg_attribute a
|
|
402
410
|
LEFT JOIN pg_attrdef d ON a.attrelid = d.adrelid AND a.attnum = d.adnum
|
|
403
411
|
LEFT JOIN pg_type t ON a.atttypid = t.oid
|
|
@@ -427,8 +435,7 @@ module ActiveRecord
|
|
|
427
435
|
fields.map do |field|
|
|
428
436
|
dtype = field[f_type]
|
|
429
437
|
field[f_type] = crdb_fields[field[f_attname]][2].downcase if re.match(dtype)
|
|
430
|
-
field[f_comment] = crdb_fields[field[f_attname]][1]
|
|
431
|
-
field[f_is_hidden] = true if crdb_fields[field[f_attname]][3]
|
|
438
|
+
field[f_comment] = crdb_fields[field[f_attname]][1]
|
|
432
439
|
field
|
|
433
440
|
end
|
|
434
441
|
fields.delete_if do |field|
|
|
@@ -444,20 +451,30 @@ module ActiveRecord
|
|
|
444
451
|
# column_definitions. This will include limit,
|
|
445
452
|
# precision, and scale information in the type.
|
|
446
453
|
# Ex. geometry -> geometry(point, 4326)
|
|
454
|
+
#
|
|
455
|
+
# The performance difference to fetch comments is very
|
|
456
|
+
# significant. On a M1 Mac, CockroachDB v25.2.2 and
|
|
457
|
+
# data from the test suite, it is 20x times faster.
|
|
458
|
+
#
|
|
459
|
+
# SELECT col_description(a.attrelid, a.attnum)
|
|
460
|
+
# FROM pg_attribute a; -- 1.052s
|
|
461
|
+
#
|
|
462
|
+
# SELECT c.column_comment
|
|
463
|
+
# FROM information_schema.columns c; -- 50ms
|
|
464
|
+
#
|
|
447
465
|
def crdb_column_definitions(table_name)
|
|
448
466
|
table_name = PostgreSQL::Utils.extract_schema_qualified_name(table_name)
|
|
449
467
|
table = table_name.identifier
|
|
450
468
|
with_schema = " AND c.table_schema = #{quote(table_name.schema)}" if table_name.schema
|
|
451
469
|
fields = \
|
|
452
470
|
query(<<~SQL, "SCHEMA")
|
|
453
|
-
SELECT c.column_name, c.column_comment, c.crdb_sql_type
|
|
471
|
+
SELECT c.column_name, c.column_comment, c.crdb_sql_type
|
|
454
472
|
FROM information_schema.columns c
|
|
455
473
|
WHERE c.table_name = #{quote(table)}#{with_schema}
|
|
456
474
|
SQL
|
|
457
475
|
|
|
458
|
-
fields.
|
|
459
|
-
|
|
460
|
-
a
|
|
476
|
+
fields.to_h do |field|
|
|
477
|
+
[field.first, field]
|
|
461
478
|
end
|
|
462
479
|
end
|
|
463
480
|
|
data/lib/version.rb
CHANGED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
require "cases/helper_cockroachdb"
|
|
2
|
+
require "models/binary"
|
|
3
|
+
require "models/developer"
|
|
4
|
+
require "models/post"
|
|
5
|
+
require "models/author"
|
|
6
|
+
|
|
7
|
+
module CockroachDB
|
|
8
|
+
class AdapterTest < ActiveRecord::TestCase
|
|
9
|
+
self.use_transactional_tests = false
|
|
10
|
+
|
|
11
|
+
def setup
|
|
12
|
+
@connection = ActiveRecord::Base.lease_connection
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# This replaces the same test that's been excluded from
|
|
16
|
+
# ActiveRecord::AdapterTest. We can run it here with
|
|
17
|
+
# use_transactional_tests set to false.
|
|
18
|
+
# See test/excludes/ActiveRecord/AdapterTest.rb.
|
|
19
|
+
def test_indexes
|
|
20
|
+
idx_name = "accounts_idx"
|
|
21
|
+
|
|
22
|
+
indexes = @connection.indexes("accounts")
|
|
23
|
+
assert_empty indexes
|
|
24
|
+
|
|
25
|
+
@connection.add_index :accounts, :firm_id, name: idx_name
|
|
26
|
+
indexes = @connection.indexes("accounts")
|
|
27
|
+
assert_equal "accounts", indexes.first.table
|
|
28
|
+
assert_equal idx_name, indexes.first.name
|
|
29
|
+
assert !indexes.first.unique
|
|
30
|
+
assert_equal ["firm_id"], indexes.first.columns
|
|
31
|
+
ensure
|
|
32
|
+
@connection.remove_index(:accounts, name: idx_name, if_exists: true)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# This replaces the same test that's been excluded from
|
|
36
|
+
# ActiveRecord::AdapterTest. We can run it here with
|
|
37
|
+
# use_transactional_tests set to false.
|
|
38
|
+
# See test/excludes/ActiveRecord/AdapterTest.rb.
|
|
39
|
+
def test_remove_index_when_name_and_wrong_column_name_specified
|
|
40
|
+
index_name = "accounts_idx"
|
|
41
|
+
|
|
42
|
+
@connection.add_index :accounts, :firm_id, name: index_name
|
|
43
|
+
assert_raises ArgumentError do
|
|
44
|
+
@connection.remove_index :accounts, name: index_name, column: :wrong_column_name
|
|
45
|
+
end
|
|
46
|
+
ensure
|
|
47
|
+
@connection.remove_index(:accounts, name: index_name)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# This replaces the same test that's been excluded from
|
|
51
|
+
# ActiveRecord::AdapterTest. We can run it here with
|
|
52
|
+
# use_transactional_tests set to false.
|
|
53
|
+
# See test/excludes/ActiveRecord/AdapterTest.rb.
|
|
54
|
+
def test_remove_index_when_name_and_wrong_column_name_specified_positional_argument
|
|
55
|
+
index_name = "accounts_idx"
|
|
56
|
+
|
|
57
|
+
@connection.add_index :accounts, :firm_id, name: index_name
|
|
58
|
+
assert_raises ArgumentError do
|
|
59
|
+
@connection.remove_index :accounts, :wrong_column_name, name: index_name
|
|
60
|
+
end
|
|
61
|
+
ensure
|
|
62
|
+
@connection.remove_index(:accounts, name: index_name)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
class AdapterTestWithoutTransaction < ActiveRecord::TestCase
|
|
68
|
+
self.use_transactional_tests = false
|
|
69
|
+
|
|
70
|
+
class Widget < ActiveRecord::Base
|
|
71
|
+
self.primary_key = "widgetid"
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def setup
|
|
75
|
+
@connection = ActiveRecord::Base.lease_connection
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
teardown do
|
|
79
|
+
@connection.drop_table :widgets, if_exists: true
|
|
80
|
+
@connection.exec_query("DROP SEQUENCE IF EXISTS widgets_seq")
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# This test replaces the excluded test_reset_empty_table_with_custom_pk. We
|
|
84
|
+
# can run the same assertions, but we have to manually create the table so
|
|
85
|
+
# it has a primary key sequence.
|
|
86
|
+
# See test/excludes/ActiveRecord/AdapterTestWithoutTransaction.rb.
|
|
87
|
+
def test_reset_empty_table_with_custom_pk_sequence
|
|
88
|
+
@connection.exec_query("CREATE SEQUENCE widgets_seq")
|
|
89
|
+
@connection.exec_query("
|
|
90
|
+
CREATE TABLE widgets (
|
|
91
|
+
widgetid INT PRIMARY KEY DEFAULT nextval('widgets_seq'),
|
|
92
|
+
name string
|
|
93
|
+
)
|
|
94
|
+
")
|
|
95
|
+
assert_equal 1, Widget.create(name: "weather").id
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|