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.
Files changed (239) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +3 -0
  3. data/CONTRIBUTING.md +10 -17
  4. data/Gemfile +2 -1
  5. data/Rakefile +0 -19
  6. data/lib/active_record/connection_adapters/cockroachdb/column.rb +66 -24
  7. data/lib/active_record/connection_adapters/cockroachdb/database_statements.rb +13 -3
  8. data/lib/active_record/connection_adapters/cockroachdb/database_tasks.rb +1 -1
  9. data/lib/active_record/connection_adapters/cockroachdb/oid/spatial.rb +34 -19
  10. data/lib/active_record/connection_adapters/cockroachdb/quoting.rb +19 -3
  11. data/lib/active_record/connection_adapters/cockroachdb/referential_integrity.rb +87 -55
  12. data/lib/active_record/connection_adapters/cockroachdb/schema_statements.rb +181 -102
  13. data/lib/active_record/connection_adapters/cockroachdb_adapter.rb +39 -21
  14. data/lib/version.rb +1 -1
  15. data/test/cases/adapter_test.rb +98 -0
  16. data/test/cases/adapters/cockroachdb/referential_integrity_test.rb +51 -0
  17. data/test/cases/adapters/postgresql/active_schema_test.rb +71 -0
  18. data/test/cases/adapters/postgresql/change_schema_test.rb +75 -0
  19. data/test/cases/adapters/postgresql/connection_test.rb +46 -0
  20. data/test/cases/adapters/postgresql/ddl_test.rb +326 -0
  21. data/test/cases/adapters/postgresql/interval_test.rb +131 -0
  22. data/test/cases/adapters/postgresql/nested_class_test.rb +22 -0
  23. data/test/cases/adapters/postgresql/numeric_test.rb +28 -0
  24. data/test/cases/adapters/postgresql/postgis_test.rb +185 -0
  25. data/test/cases/adapters/postgresql/postgresql_adapter_test.rb +115 -0
  26. data/test/cases/adapters/postgresql/quoting_test.rb +30 -0
  27. data/test/cases/adapters/postgresql/schema_statements_test.rb +29 -0
  28. data/test/cases/adapters/postgresql/serial_test.rb +199 -0
  29. data/test/cases/adapters/postgresql/spatial_queries_test.rb +118 -0
  30. data/test/cases/adapters/postgresql/spatial_setup_test.rb +18 -0
  31. data/test/cases/adapters/postgresql/spatial_type_test.rb +41 -0
  32. data/test/cases/adapters/postgresql/timestamp_test.rb +58 -0
  33. data/test/cases/adapters/postgresql/virtual_column_test.rb +39 -0
  34. data/test/cases/associations/eager_load_nested_include_test.rb +111 -0
  35. data/test/cases/associations/left_outer_join_association_test.rb +30 -0
  36. data/test/cases/associations_test.rb +108 -0
  37. data/test/cases/base_test.rb +31 -0
  38. data/test/cases/comment_test.rb +75 -0
  39. data/test/cases/connection_adapters/type_test.rb +28 -0
  40. data/test/cases/database_configurations/resolver_test.rb +24 -0
  41. data/test/cases/defaults_test.rb +45 -0
  42. data/test/cases/dirty_test.rb +24 -0
  43. data/test/cases/fixtures_test.rb +541 -0
  44. data/test/cases/helper_cockroachdb.rb +232 -0
  45. data/test/cases/inheritance_test.rb +42 -0
  46. data/test/cases/invertible_migration_test.rb +73 -0
  47. data/test/cases/marshal_serialization_test.rb +45 -0
  48. data/test/cases/migration/change_schema_test.rb +140 -0
  49. data/test/cases/migration/check_constraint_test.rb +125 -0
  50. data/test/cases/migration/columns_test.rb +50 -0
  51. data/test/cases/migration/create_join_table_test.rb +66 -0
  52. data/test/cases/migration/foreign_key_test.rb +390 -0
  53. data/test/cases/migration/hidden_column_test.rb +70 -0
  54. data/test/cases/migration/references_foreign_key_test.rb +124 -0
  55. data/test/cases/migration_test.rb +120 -0
  56. data/test/cases/persistence_test.rb +33 -0
  57. data/test/cases/primary_keys_test.rb +134 -0
  58. data/test/cases/relation/aost_test.rb +57 -0
  59. data/test/cases/relation/or_test.rb +26 -0
  60. data/test/cases/relation/table_hints_test.rb +124 -0
  61. data/test/cases/relation_test.rb +26 -0
  62. data/test/cases/relations_test.rb +29 -0
  63. data/test/cases/schema_dumper_test.rb +221 -0
  64. data/test/cases/show_create_test.rb +14 -0
  65. data/test/cases/strict_loading_test.rb +34 -0
  66. data/test/cases/tasks/cockroachdb_rake_test.rb +113 -0
  67. data/test/cases/test_fixtures_test.rb +57 -0
  68. data/test/cases/transactions_test.rb +51 -0
  69. data/test/cases/unsafe_raw_sql_test.rb +22 -0
  70. data/test/config.yml +23 -0
  71. data/test/excludes/ActiveRecord/AdapterTest.rb +3 -0
  72. data/test/excludes/ActiveRecord/AdapterTestWithoutTransaction.rb +25 -0
  73. data/test/excludes/ActiveRecord/ConnectionAdapters/PoolConfig/ResolverTest.rb +1 -0
  74. data/test/excludes/ActiveRecord/ConnectionAdapters/PostgreSQLAdapter/BindParameterTest.rb +15 -0
  75. data/test/excludes/ActiveRecord/ConnectionAdapters/PostgreSQLAdapter/QuotingTest.rb +22 -0
  76. data/test/excludes/ActiveRecord/ConnectionAdapters/PostgreSQLAdapterPreventWritesLegacyTest.rb +1 -0
  77. data/test/excludes/ActiveRecord/ConnectionAdapters/PostgreSQLAdapterPreventWritesTest.rb +1 -0
  78. data/test/excludes/ActiveRecord/ConnectionAdapters/PostgreSQLAdapterTest.rb +40 -0
  79. data/test/excludes/ActiveRecord/ConnectionAdapters/RegistrationIsolatedTest.rb +14 -0
  80. data/test/excludes/ActiveRecord/Encryption/EncryptionPerformanceTest.rb +1 -0
  81. data/test/excludes/ActiveRecord/Encryption/EnvelopeEncryptionPerformanceTest.rb +1 -0
  82. data/test/excludes/ActiveRecord/Encryption/ExtendedDeterministicQueriesPerformanceTest.rb +1 -0
  83. data/test/excludes/ActiveRecord/Encryption/StoragePerformanceTest.rb +2 -0
  84. data/test/excludes/ActiveRecord/InstrumentationTest.rb +16 -0
  85. data/test/excludes/ActiveRecord/InvertibleMigrationTest.rb +2 -0
  86. data/test/excludes/ActiveRecord/Migration/ChangeSchemaTest.rb +7 -0
  87. data/test/excludes/ActiveRecord/Migration/CheckConstraintTest.rb +6 -0
  88. data/test/excludes/ActiveRecord/Migration/ColumnsTest.rb +4 -0
  89. data/test/excludes/ActiveRecord/Migration/CompatibilityTest.rb +50 -0
  90. data/test/excludes/ActiveRecord/Migration/CompositeForeignKeyTest.rb +2 -0
  91. data/test/excludes/ActiveRecord/Migration/CreateJoinTableTest.rb +2 -0
  92. data/test/excludes/ActiveRecord/Migration/ForeignKeyInCreateTest.rb +1 -0
  93. data/test/excludes/ActiveRecord/Migration/ForeignKeyTest.rb +35 -0
  94. data/test/excludes/ActiveRecord/Migration/InvalidOptionsTest.rb +14 -0
  95. data/test/excludes/ActiveRecord/Migration/PGChangeSchemaTest.rb +8 -0
  96. data/test/excludes/ActiveRecord/Migration/ReferencesForeignKeyTest.rb +7 -0
  97. data/test/excludes/ActiveRecord/Migration/ReferencesIndexTest.rb +7 -0
  98. data/test/excludes/ActiveRecord/Migration/ReferencesStatementsTest.rb +3 -0
  99. data/test/excludes/ActiveRecord/MysqlDBCreateWithInvalidPermissionsTest.rb +1 -0
  100. data/test/excludes/ActiveRecord/OrTest.rb +1 -0
  101. data/test/excludes/ActiveRecord/PostgreSQLStructureDumpTest.rb +10 -0
  102. data/test/excludes/ActiveRecord/PostgresqlConnectionTest.rb +12 -0
  103. data/test/excludes/ActiveRecord/PostgresqlTransactionNestedTest.rb +14 -0
  104. data/test/excludes/ActiveRecord/PostgresqlTransactionTest.rb +4 -0
  105. data/test/excludes/ActiveRecord/RelationTest.rb +2 -0
  106. data/test/excludes/ActiveRecord/TooManyOrTest.rb +1 -0
  107. data/test/excludes/ActiveSupportSubclassWithFixturesTest.rb +1 -0
  108. data/test/excludes/AssociationDeprecationTest/NotifyModeTest.rb +2 -0
  109. data/test/excludes/AssociationDeprecationTest/RaiseBacktraceModeTest.rb +2 -0
  110. data/test/excludes/AssociationDeprecationTest/RaiseModeTest.rb +2 -0
  111. data/test/excludes/AssociationDeprecationTest/WarnBacktraceModeTest.rb +2 -0
  112. data/test/excludes/AssociationDeprecationTest/WarnModeTest.rb +2 -0
  113. data/test/excludes/AssociationDeprecationTest/fix_backtrace_cleaner.rb +10 -0
  114. data/test/excludes/BasicsTest.rb +1 -0
  115. data/test/excludes/BulkAlterTableMigrationsTest.rb +7 -0
  116. data/test/excludes/CalculationsTest.rb +4 -0
  117. data/test/excludes/CommentTest.rb +2 -0
  118. data/test/excludes/CoreTest.rb +1 -0
  119. data/test/excludes/CreateOrFindByWithinTransactions.rb +3 -0
  120. data/test/excludes/DefaultsUsingMultipleSchemasAndDomainTest.rb +7 -0
  121. data/test/excludes/DirtyTest.rb +3 -0
  122. data/test/excludes/EachTest.rb +8 -0
  123. data/test/excludes/EagerLoadPolyAssocsTest.rb +1 -0
  124. data/test/excludes/ExplicitlyNamedIndexMigrationTest.rb +1 -0
  125. data/test/excludes/FixturesResetPkSequenceTest.rb +3 -0
  126. data/test/excludes/FixturesTest.rb +21 -0
  127. data/test/excludes/FixturesWithForeignKeyViolationsTest.rb +2 -0
  128. data/test/excludes/ForeignTableTest.rb +10 -0
  129. data/test/excludes/InheritanceComputeTypeTest.rb +1 -0
  130. data/test/excludes/LeftOuterJoinAssociationTest.rb +2 -0
  131. data/test/excludes/LegacyPrimaryKeyTest/V4_2.rb +6 -0
  132. data/test/excludes/LegacyPrimaryKeyTest/V5_0.rb +6 -0
  133. data/test/excludes/MarshalSerializationTest.rb +4 -0
  134. data/test/excludes/MaterializedViewTest.rb +13 -0
  135. data/test/excludes/MigrationTest.rb +2 -0
  136. data/test/excludes/MultiDbMigratorTest.rb +2 -0
  137. data/test/excludes/NestedRelationScopingTest.rb +1 -0
  138. data/test/excludes/OrTest.rb +1 -0
  139. data/test/excludes/PersistenceTest.rb +3 -0
  140. data/test/excludes/PessimisticLockingTest.rb +1 -0
  141. data/test/excludes/PostgreSQLExplainTest.rb +7 -0
  142. data/test/excludes/PostgreSQLGeometricLineTest.rb +3 -0
  143. data/test/excludes/PostgreSQLGeometricTypesTest.rb +7 -0
  144. data/test/excludes/PostgreSQLPartitionsTest.rb +1 -0
  145. data/test/excludes/PostgreSQLReferentialIntegrityTest.rb +14 -0
  146. data/test/excludes/PostgresqlArrayTest.rb +21 -0
  147. data/test/excludes/PostgresqlBigSerialTest.rb +7 -0
  148. data/test/excludes/PostgresqlBitStringTest.rb +2 -0
  149. data/test/excludes/PostgresqlByteaTest.rb +1 -0
  150. data/test/excludes/PostgresqlCitextTest.rb +7 -0
  151. data/test/excludes/PostgresqlCollationTest.rb +5 -0
  152. data/test/excludes/PostgresqlCompositeTest.rb +2 -0
  153. data/test/excludes/PostgresqlCompositeWithCustomOIDTest.rb +2 -0
  154. data/test/excludes/PostgresqlDataTypeTest.rb +9 -0
  155. data/test/excludes/PostgresqlDefaultExpressionTest.rb +1 -0
  156. data/test/excludes/PostgresqlDeferredConstraintsTest.rb +3 -0
  157. data/test/excludes/PostgresqlDomainTest.rb +2 -0
  158. data/test/excludes/PostgresqlExtensionMigrationTest.rb +5 -0
  159. data/test/excludes/PostgresqlFullTextTest.rb +3 -0
  160. data/test/excludes/PostgresqlGeometricTest.rb +4 -0
  161. data/test/excludes/PostgresqlHstoreTest.rb +45 -0
  162. data/test/excludes/PostgresqlInfinityTest.rb +5 -0
  163. data/test/excludes/PostgresqlIntervalTest.rb +1 -0
  164. data/test/excludes/PostgresqlJSONBTest.rb +27 -0
  165. data/test/excludes/PostgresqlJSONTest.rb +27 -0
  166. data/test/excludes/PostgresqlLtreeTest.rb +4 -0
  167. data/test/excludes/PostgresqlMoneyTest.rb +12 -0
  168. data/test/excludes/PostgresqlNetworkTest.rb +69 -0
  169. data/test/excludes/PostgresqlNumberTest.rb +1 -0
  170. data/test/excludes/PostgresqlPointTest.rb +15 -0
  171. data/test/excludes/PostgresqlRangeTest.rb +3 -0
  172. data/test/excludes/PostgresqlRenameTableTest.rb +2 -0
  173. data/test/excludes/PostgresqlSerialTest.rb +7 -0
  174. data/test/excludes/PostgresqlTimestampFixtureTest.rb +2 -0
  175. data/test/excludes/PostgresqlTimestampMigrationTest.rb +3 -0
  176. data/test/excludes/PostgresqlTypeLookupTest.rb +2 -0
  177. data/test/excludes/PostgresqlUUIDGenerationTest.rb +7 -0
  178. data/test/excludes/PostgresqlUUIDTest.rb +1 -0
  179. data/test/excludes/PostgresqlVirtualColumnTest.rb +17 -0
  180. data/test/excludes/PostgresqlXMLTest.rb +5 -0
  181. data/test/excludes/PrimaryKeyIntegerNilDefaultTest.rb +1 -0
  182. data/test/excludes/PrimaryKeyIntegerTest.rb +3 -0
  183. data/test/excludes/PrimaryKeysTest.rb +2 -0
  184. data/test/excludes/RelationMergingTest.rb +15 -0
  185. data/test/excludes/RelationTest.rb +3 -0
  186. data/test/excludes/ReservedWordsMigrationTest.rb +1 -0
  187. data/test/excludes/SameNameDifferentDatabaseFixturesTest.rb +1 -0
  188. data/test/excludes/SanitizeTest.rb +13 -0
  189. data/test/excludes/SchemaAuthorizationTest.rb +8 -0
  190. data/test/excludes/SchemaCreateTableOptionsTest.rb +2 -0
  191. data/test/excludes/SchemaDumperDefaultsTest.rb +1 -0
  192. data/test/excludes/SchemaDumperTest.rb +11 -0
  193. data/test/excludes/SchemaForeignKeyTest.rb +1 -0
  194. data/test/excludes/SchemaIndexNullsOrderTest.rb +2 -0
  195. data/test/excludes/SchemaIndexOpclassTest.rb +3 -0
  196. data/test/excludes/SchemaTest.rb +49 -0
  197. data/test/excludes/SequenceNameDetectionTestCases/CollidedSequenceNameTest.rb +1 -0
  198. data/test/excludes/SequenceNameDetectionTestCases/LongerSequenceNameDetectionTest.rb +1 -0
  199. data/test/excludes/StrictLoadingFixturesTest.rb +1 -0
  200. data/test/excludes/TestFixturesTest.rb +1 -0
  201. data/test/excludes/TransactionInstrumentationTest.rb +1 -0
  202. data/test/excludes/TransactionIsolationTest.rb +1 -0
  203. data/test/excludes/TypeTest.rb +1 -0
  204. data/test/excludes/UniquenessValidationTest.rb +2 -0
  205. data/test/excludes/UnloggedTablesTest.rb +3 -0
  206. data/test/excludes/UnsafeRawSqlTest.rb +2 -0
  207. data/test/excludes/UpdateableViewTest.rb +5 -0
  208. data/test/excludes/WithAnnotationsTest.rb +6 -0
  209. data/test/models/building.rb +4 -0
  210. data/test/models/spatial_model.rb +5 -0
  211. data/test/schema/cockroachdb_specific_schema.rb +218 -0
  212. data/test/support/copy_cat.rb +83 -0
  213. data/test/support/exclude_from_transactional_tests.rb +33 -0
  214. data/test/support/paths_cockroachdb.rb +46 -0
  215. data/test/support/rake_helpers.rb +37 -0
  216. data/test/support/sql_logger.rb +55 -0
  217. data/test/support/template_creator.rb +114 -0
  218. metadata +422 -34
  219. data/.editorconfig +0 -7
  220. data/.github/issue_template.md +0 -46
  221. data/.github/reproduction_scripts/migrations.rb +0 -60
  222. data/.github/reproduction_scripts/models_and_database.rb +0 -49
  223. data/.github/workflows/ci.yml +0 -96
  224. data/.github/workflows/docker.yml +0 -57
  225. data/.gitignore +0 -18
  226. data/.gitmodules +0 -0
  227. data/activerecord-cockroachdb-adapter.gemspec +0 -38
  228. data/bin/console +0 -36
  229. data/bin/console_schemas/default.rb +0 -11
  230. data/bin/console_schemas/schemas.rb +0 -23
  231. data/bin/setup +0 -8
  232. data/bin/start-cockroachdb +0 -33
  233. data/build/Dockerfile +0 -14
  234. data/build/config.teamcity.yml +0 -31
  235. data/build/local-test.sh +0 -32
  236. data/build/teamcity-test.sh +0 -76
  237. data/docker.sh +0 -35
  238. data/lib/active_record/connection_adapters/cockroachdb/spatial_column_info.rb +0 -60
  239. data/setup.sql +0 -18
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/helper_cockroachdb"
4
+ require "support/connection_helper" # for #reset_connection
5
+ require "support/copy_cat"
6
+
7
+ class CockroachDBReferentialIntegrityTest < ActiveRecord::PostgreSQLTestCase
8
+ include ConnectionHelper
9
+
10
+ module ProgrammerMistake
11
+ def execute_batch(sql, name = nil)
12
+ raise ArgumentError, "something is not right." if name.match?(/referential integrity/)
13
+ super
14
+ end
15
+ end
16
+
17
+ def setup
18
+ @connection = ActiveRecord::Base.lease_connection
19
+ end
20
+
21
+ def teardown
22
+ reset_connection
23
+ end
24
+
25
+ exclude_from_transactional_tests :test_only_catch_active_record_errors_others_bubble_up
26
+ CopyCat.copy_methods(self, ::PostgreSQLReferentialIntegrityTest, :test_only_catch_active_record_errors_others_bubble_up)
27
+
28
+ def test_should_reraise_invalid_foreign_key_exception_and_show_warning
29
+ warning = capture(:stderr) do
30
+ e = assert_raises(ActiveRecord::InvalidForeignKey) do
31
+ @connection.disable_referential_integrity do
32
+ @connection.execute("INSERT INTO authors (name, author_address_id) VALUES ('Mona Chollet', 42)")
33
+ end
34
+ end
35
+ assert_match (/Key \(author_address_id\)=\(42\) is not present in table/), e.message
36
+ end
37
+ assert_match (/WARNING: Rails was not able to disable referential integrity/), warning
38
+ assert_match (/autocommit_before_ddl/), warning
39
+ end
40
+
41
+ def test_no_warning_nor_error_with_autocommit_before_ddl
42
+ @connection.execute("SET SESSION autocommit_before_ddl = 'on'")
43
+ warning = capture(:stderr) do
44
+ @connection.disable_referential_integrity do
45
+ @connection.execute("INSERT INTO authors (name, author_address_id) VALUES ('Mona Chollet', 42)")
46
+ @connection.truncate(:authors)
47
+ end
48
+ end
49
+ assert_predicate warning, :blank?, "expected no warnings but got:\n#{warning}"
50
+ end
51
+ end
@@ -0,0 +1,71 @@
1
+ require "cases/helper_cockroachdb"
2
+
3
+ module CockroachDB
4
+ class PostgresqlActiveSchemaTest < ActiveRecord::PostgreSQLTestCase
5
+ def setup
6
+ ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.class_eval do
7
+ def execute(sql, name = nil) sql end
8
+ end
9
+ end
10
+
11
+ teardown do
12
+ ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.class_eval do
13
+ remove_method :execute
14
+ end
15
+ end
16
+
17
+ # This replaces the same test that's been excluded from
18
+ # PostgresqlActiveSchemaTest. It is almost exactly the same, but it excludes
19
+ # assertions against partial indexes because they're not supported in
20
+ # CockroachDB.
21
+ # See test/excludes/PostgresqlActiveSchemaTest.rb
22
+ def test_add_index
23
+ # add_index calls index_name_exists? which can't work since execute is stubbed
24
+ ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.send(:define_method, :index_name_exists?) { |*| false }
25
+
26
+ expected = %(CREATE UNIQUE INDEX "index_people_on_lower_last_name" ON "people" (lower(last_name)))
27
+ assert_equal expected, add_index(:people, "lower(last_name)", unique: true)
28
+
29
+ expected = %(CREATE UNIQUE INDEX "index_people_on_last_name_varchar_pattern_ops" ON "people" (last_name varchar_pattern_ops))
30
+ assert_equal expected, add_index(:people, "last_name varchar_pattern_ops", unique: true)
31
+
32
+ expected = %(CREATE INDEX CONCURRENTLY "index_people_on_last_name" ON "people" ("last_name"))
33
+ assert_equal expected, add_index(:people, :last_name, algorithm: :concurrently)
34
+
35
+ expected = %(CREATE INDEX "index_people_on_last_name_and_first_name" ON "people" ("last_name" DESC, "first_name" ASC))
36
+ assert_equal expected, add_index(:people, [:last_name, :first_name], order: { last_name: :desc, first_name: :asc })
37
+ assert_equal expected, add_index(:people, ["last_name", :first_name], order: { last_name: :desc, "first_name" => :asc })
38
+
39
+ %w(gin gist hash btree).each do |type|
40
+ expected = %(CREATE INDEX "index_people_on_last_name" ON "people" USING #{type} ("last_name"))
41
+ assert_equal expected, add_index(:people, :last_name, using: type)
42
+
43
+ expected = %(CREATE INDEX CONCURRENTLY "index_people_on_last_name" ON "people" USING #{type} ("last_name"))
44
+ assert_equal expected, add_index(:people, :last_name, using: type, algorithm: :concurrently)
45
+
46
+ expected = %(CREATE UNIQUE INDEX "index_people_on_lower_last_name" ON "people" USING #{type} (lower(last_name)))
47
+ assert_equal expected, add_index(:people, "lower(last_name)", using: type, unique: true)
48
+ end
49
+
50
+ expected = %(CREATE INDEX "index_people_on_last_name" ON "people" USING gist ("last_name" bpchar_pattern_ops))
51
+ assert_equal expected, add_index(:people, :last_name, using: :gist, opclass: { last_name: :bpchar_pattern_ops })
52
+
53
+ expected = %(CREATE INDEX "index_people_on_last_name_and_first_name" ON "people" ("last_name" DESC NULLS LAST, "first_name" ASC))
54
+ assert_equal expected, add_index(:people, [:last_name, :first_name], order: { last_name: "DESC NULLS LAST", first_name: :asc })
55
+
56
+ expected = %(CREATE INDEX "index_people_on_last_name" ON "people" ("last_name" NULLS FIRST))
57
+ assert_equal expected, add_index(:people, :last_name, order: "NULLS FIRST")
58
+
59
+ assert_raise ArgumentError do
60
+ add_index(:people, :last_name, algorithm: :copy)
61
+ end
62
+
63
+ ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.send :remove_method, :index_name_exists?
64
+ end
65
+
66
+ private
67
+ def method_missing(...)
68
+ ActiveRecord::Base.lease_connection.send(...)
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/helper"
4
+ require "cases/helper_cockroachdb"
5
+
6
+ module ActiveRecord
7
+ module CockroachDB
8
+ class Migration
9
+ class PGChangeSchemaTest < ActiveRecord::PostgreSQLTestCase
10
+ self.use_transactional_tests = false
11
+ attr_reader :connection
12
+
13
+ def setup
14
+ super
15
+ @connection = ActiveRecord::Base.lease_connection
16
+ connection.create_table(:strings) do |t|
17
+ t.string :somedate
18
+ end
19
+ end
20
+
21
+ def teardown
22
+ connection.drop_table :strings
23
+ end
24
+
25
+ def test_change_string_to_date
26
+ connection.change_column :strings, :somedate, :timestamp, using: 'CAST("somedate" AS timestamp)'
27
+ assert_equal :datetime, connection.columns(:strings).find { |c| c.name == "somedate" }.type
28
+ end
29
+
30
+ def test_change_type_with_symbol
31
+ connection.change_column :strings, :somedate, :timestamp, cast_as: :timestamp
32
+ assert_equal :datetime, connection.columns(:strings).find { |c| c.name == "somedate" }.type
33
+ end
34
+
35
+ def test_change_type_with_symbol_with_timestamptz
36
+ connection.change_column :strings, :somedate, :timestamptz, cast_as: :timestamptz
37
+ assert_equal :timestamptz, connection.columns(:strings).find { |c| c.name == "somedate" }.type
38
+ end
39
+
40
+ def test_change_type_with_symbol_using_datetime
41
+ connection.change_column :strings, :somedate, :datetime, cast_as: :datetime
42
+ assert_equal :datetime, connection.columns(:strings).find { |c| c.name == "somedate" }.type
43
+ end
44
+
45
+ def test_change_type_with_symbol_using_timestamp_with_timestamptz_as_default
46
+ with_cockroachdb_datetime_type(:timestamptz) do
47
+ connection.change_column :strings, :somedate, :timestamp, cast_as: :timestamp
48
+ assert_equal :timestamp, connection.columns(:strings).find { |c| c.name == "somedate" }.type
49
+ end
50
+ end
51
+
52
+ def test_change_type_with_symbol_with_timestamptz_as_default
53
+ with_cockroachdb_datetime_type(:timestamptz) do
54
+ connection.change_column :strings, :somedate, :timestamptz, cast_as: :timestamptz
55
+ assert_equal :datetime, connection.columns(:strings).find { |c| c.name == "somedate" }.type
56
+ end
57
+ end
58
+
59
+ def test_change_type_with_symbol_using_datetime_with_timestamptz_as_default
60
+ with_cockroachdb_datetime_type(:timestamptz) do
61
+ connection.change_column :strings, :somedate, :datetime, cast_as: :datetime
62
+ assert_equal :datetime, connection.columns(:strings).find { |c| c.name == "somedate" }.type
63
+ end
64
+ end
65
+
66
+ def test_change_type_with_array
67
+ connection.change_column :strings, :somedate, :timestamp, array: true, cast_as: :timestamp
68
+ column = connection.columns(:strings).find { |c| c.name == "somedate" }
69
+ assert_equal :datetime, column.type
70
+ assert_predicate column, :array?
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/helper_cockroachdb"
4
+
5
+
6
+ module ActiveRecord
7
+ module CockroachDB
8
+ class PostgresqlConnectionTest < ActiveRecord::PostgreSQLTestCase
9
+ include ConnectionHelper
10
+
11
+ def test_set_session_variable_true
12
+ run_without_connection do |orig_connection|
13
+ ActiveRecord::Base.establish_connection(orig_connection.deep_merge(variables: { null_ordered_last: true }))
14
+ set_true = ActiveRecord::Base.lease_connection.exec_query "SHOW NULL_ORDERED_LAST"
15
+ assert_equal [["on"]], set_true.rows
16
+ end
17
+ end
18
+
19
+ def test_set_session_variable_false
20
+ run_without_connection do |orig_connection|
21
+ ActiveRecord::Base.establish_connection(orig_connection.deep_merge(variables: { null_ordered_last: false }))
22
+ set_false = ActiveRecord::Base.lease_connection.exec_query "SHOW NULL_ORDERED_LAST"
23
+ assert_equal [["off"]], set_false.rows
24
+ end
25
+ end
26
+
27
+ def test_set_session_variable_nil
28
+ run_without_connection do |orig_connection|
29
+ # This should be a no-op that does not raise an error
30
+ assert_nothing_raised do
31
+ ActiveRecord::Base.establish_connection(orig_connection.deep_merge(variables: { null_ordered_last: nil }))
32
+ end
33
+ end
34
+ end
35
+
36
+ def test_set_session_variable_default
37
+ run_without_connection do |orig_connection|
38
+ # This should execute a query that does not raise an error
39
+ assert_nothing_raised do
40
+ ActiveRecord::Base.establish_connection(orig_connection.deep_merge(variables: { null_ordered_last: :default }))
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,326 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cases/helper_cockroachdb'
4
+ require 'models/spatial_model'
5
+
6
+ class DDLTest < ActiveSupport::TestCase
7
+ def test_spatial_column_options
8
+ %i[
9
+ geography
10
+ geometry
11
+ geometry_collection
12
+ line_string
13
+ multi_line_string
14
+ multi_point
15
+ multi_polygon
16
+ st_point
17
+ st_polygon
18
+ ].each do |type|
19
+ assert ActiveRecord::ConnectionAdapters::CockroachDBAdapter.spatial_column_options(type), type
20
+ end
21
+ end
22
+
23
+ def test_type_to_sql
24
+ adapter = SpatialModel.lease_connection
25
+ assert_equal 'geometry(point,4326)', adapter.type_to_sql(:geometry, limit: 'point,4326')
26
+ end
27
+
28
+ def test_create_simple_geometry
29
+ klass.lease_connection.create_table(:spatial_models, force: true) do |t|
30
+ t.column 'latlon', :geometry
31
+ end
32
+ klass.reset_column_information
33
+ assert_equal 1, count_geometry_columns
34
+ col = klass.columns.last
35
+ assert_equal RGeo::Feature::Geometry, col.geometric_type
36
+ assert_equal true, col.spatial?
37
+ assert_equal false, col.geographic?
38
+ assert_equal 0, col.srid
39
+ klass.lease_connection.drop_table(:spatial_models)
40
+ assert_equal 0, count_geometry_columns
41
+ end
42
+
43
+ def test_create_simple_geography
44
+ klass.lease_connection.create_table(:spatial_models, force: true) do |t|
45
+ t.column 'latlon', :geometry, geographic: true
46
+ end
47
+ klass.reset_column_information
48
+
49
+ col = klass.columns.last
50
+ assert_equal RGeo::Feature::Geometry, col.geometric_type
51
+ assert_equal true, col.spatial?
52
+ assert_equal true, col.geographic?
53
+ assert_equal 4326, col.srid
54
+ assert_equal 0, count_geometry_columns
55
+ end
56
+
57
+ def test_create_point_geometry
58
+ klass.lease_connection.create_table(:spatial_models, force: true) do |t|
59
+ t.column 'latlon', :st_point
60
+ end
61
+ klass.reset_column_information
62
+ assert_equal RGeo::Feature::Point, klass.columns.last.geometric_type
63
+ end
64
+
65
+ def test_create_geometry_with_index
66
+ klass.lease_connection.create_table(:spatial_models, force: true) do |t|
67
+ t.column 'latlon', :geometry
68
+ end
69
+ klass.lease_connection.change_table(:spatial_models) do |t|
70
+ t.index([:latlon], using: :gist)
71
+ end
72
+ klass.reset_column_information
73
+
74
+ # CockroachDB returns gin for spatial indexes
75
+ assert_equal :gin, klass.lease_connection.indexes(:spatial_models).last.using
76
+ end
77
+
78
+ def test_add_geometry_column
79
+ klass.lease_connection.create_table(:spatial_models, force: true) do |t|
80
+ t.column('latlon', :geometry)
81
+ end
82
+ klass.lease_connection.change_table(:spatial_models) do |t|
83
+ t.column('geom2', :st_point, srid: 4326)
84
+ t.column('name', :string)
85
+ end
86
+ klass.reset_column_information
87
+ assert_equal 2, count_geometry_columns
88
+ columns = klass.columns
89
+ assert_equal RGeo::Feature::Geometry, columns[-3].geometric_type
90
+ assert_equal 0, columns[-3].srid
91
+ assert_equal true, columns[-3].spatial?
92
+ assert_equal RGeo::Feature::Point, columns[-2].geometric_type
93
+ assert_equal 4326, columns[-2].srid
94
+ assert_equal false, columns[-2].geographic?
95
+ assert_equal true, columns[-2].spatial?
96
+ assert_nil columns[-1].geometric_type
97
+ assert_equal false, columns[-1].spatial?
98
+ end
99
+
100
+ def test_add_geometry_column_null_false
101
+ klass.lease_connection.create_table(:spatial_models, force: true) do |t|
102
+ t.column('latlon_null', :geometry, null: false)
103
+ t.column('latlon', :geometry)
104
+ end
105
+ klass.reset_column_information
106
+ null_false_column = klass.columns[1]
107
+ null_true_column = klass.columns[2]
108
+
109
+ refute null_false_column.null, 'Column should be null: false'
110
+ assert null_true_column.null, 'Column should be null: true'
111
+ end
112
+
113
+ def test_add_geography_column
114
+ klass.lease_connection.create_table(:spatial_models, force: true) do |t|
115
+ t.column('latlon', :geometry)
116
+ end
117
+ klass.lease_connection.change_table(:spatial_models) do |t|
118
+ t.st_point('geom3', srid: 4326, geographic: true)
119
+ t.column('geom2', :st_point, srid: 4326, geographic: true)
120
+ t.column('name', :string)
121
+ end
122
+ klass.reset_column_information
123
+ assert_equal 1, count_geometry_columns
124
+ cols = klass.columns
125
+ # latlon
126
+ assert_equal RGeo::Feature::Geometry, cols[-4].geometric_type
127
+ assert_equal 0, cols[-4].srid
128
+ assert_equal true, cols[-4].spatial?
129
+ # geom3
130
+ assert_equal RGeo::Feature::Point, cols[-3].geometric_type
131
+ assert_equal 4326, cols[-3].srid
132
+ assert_equal true, cols[-3].geographic?
133
+ assert_equal true, cols[-3].spatial?
134
+ # geom2
135
+ assert_equal RGeo::Feature::Point, cols[-2].geometric_type
136
+ assert_equal 4326, cols[-2].srid
137
+ assert_equal true, cols[-2].geographic?
138
+ assert_equal true, cols[-2].spatial?
139
+ # name
140
+ assert_nil cols[-1].geometric_type
141
+ assert_equal false, cols[-1].spatial?
142
+ end
143
+
144
+ def test_drop_geometry_column
145
+ klass.lease_connection.create_table(:spatial_models, force: true) do |t|
146
+ t.column('latlon', :geometry)
147
+ t.column('geom2', :st_point, srid: 4326)
148
+ end
149
+ klass.lease_connection.change_table(:spatial_models) do |t|
150
+ t.remove('geom2')
151
+ end
152
+ klass.reset_column_information
153
+ assert_equal 1, count_geometry_columns
154
+ cols = klass.columns
155
+ assert_equal RGeo::Feature::Geometry, cols[-1].geometric_type
156
+ assert_equal 'latlon', cols[-1].name
157
+ assert_equal 0, cols[-1].srid
158
+ assert_equal false, cols[-1].geographic?
159
+ end
160
+
161
+ def test_drop_geography_column
162
+ klass.lease_connection.create_table(:spatial_models, force: true) do |t|
163
+ t.column('latlon', :geometry)
164
+ t.column('geom2', :st_point, srid: 4326, geographic: true)
165
+ t.column('geom3', :st_point, srid: 4326)
166
+ end
167
+ klass.lease_connection.change_table(:spatial_models) do |t|
168
+ t.remove('geom2')
169
+ end
170
+ klass.reset_column_information
171
+ assert_equal 2, count_geometry_columns
172
+ columns = klass.columns
173
+ assert_equal RGeo::Feature::Point, columns[-1].geometric_type
174
+ assert_equal 'geom3', columns[-1].name
175
+ assert_equal false, columns[-1].geographic?
176
+ assert_equal RGeo::Feature::Geometry, columns[-2].geometric_type
177
+ assert_equal 'latlon', columns[-2].name
178
+ assert_equal false, columns[-2].geographic?
179
+ end
180
+
181
+ def test_create_simple_geometry_using_shortcut
182
+ klass.lease_connection.create_table(:spatial_models, force: true) do |t|
183
+ t.geometry 'latlon'
184
+ end
185
+ klass.reset_column_information
186
+ assert_equal 1, count_geometry_columns
187
+ col = klass.columns.last
188
+ assert_equal RGeo::Feature::Geometry, col.geometric_type
189
+ assert_equal false, col.geographic?
190
+ assert_equal 0, col.srid
191
+ klass.lease_connection.drop_table(:spatial_models)
192
+ assert_equal 0, count_geometry_columns
193
+ end
194
+
195
+ def test_create_simple_geography_using_shortcut
196
+ klass.lease_connection.create_table(:spatial_models, force: true) do |t|
197
+ t.geometry 'latlon', geographic: true
198
+ end
199
+ klass.reset_column_information
200
+ col = klass.columns.last
201
+ assert_equal RGeo::Feature::Geometry, col.geometric_type
202
+ assert_equal true, col.geographic?
203
+ assert_equal 4326, col.srid
204
+ assert_equal 0, count_geometry_columns
205
+ end
206
+
207
+ def test_create_point_geometry_using_shortcut
208
+ klass.lease_connection.create_table(:spatial_models, force: true) do |t|
209
+ t.st_point 'latlon'
210
+ end
211
+ klass.reset_column_information
212
+ assert_equal RGeo::Feature::Point, klass.columns.last.geometric_type
213
+ end
214
+
215
+ def test_create_geometry_using_shortcut_with_srid
216
+ klass.lease_connection.create_table(:spatial_models, force: true) do |t|
217
+ t.geometry 'latlon', srid: 4326
218
+ end
219
+ klass.reset_column_information
220
+ col = klass.columns.last
221
+ assert_equal RGeo::Feature::Geometry, col.geometric_type
222
+ assert_equal({ srid: 4326, type: 'geometry' }, col.limit)
223
+ end
224
+
225
+ def test_create_polygon_with_options
226
+ klass.lease_connection.create_table(:spatial_models, force: true) do |t|
227
+ t.column 'region', :st_polygon, has_m: true, srid: 3785
228
+ end
229
+ klass.reset_column_information
230
+ assert_equal 1, count_geometry_columns
231
+ col = klass.columns.last
232
+ assert_equal RGeo::Feature::Polygon, col.geometric_type
233
+ assert_equal false, col.geographic?
234
+ assert_equal false, col.has_z?
235
+ assert_equal true, col.has_m?
236
+ assert_equal 3785, col.srid
237
+ assert_equal({ has_m: true, type: 'st_polygon', srid: 3785 }, col.limit)
238
+ klass.lease_connection.drop_table(:spatial_models)
239
+ assert_equal 0, count_geometry_columns
240
+ end
241
+
242
+ # Ensure that null contraints info is getting captured like the
243
+ # normal adapter.
244
+ def test_null_constraints
245
+ klass.lease_connection.create_table(:spatial_models, force: true) do |t|
246
+ t.column 'nulls_allowed', :string, null: true
247
+ t.column 'nulls_disallowed', :string, null: false
248
+ end
249
+ klass.reset_column_information
250
+ assert_equal true, klass.columns[-2].null
251
+ assert_equal false, klass.columns[-1].null
252
+ end
253
+
254
+ # Ensure column default value works like the Postgres adapter.
255
+ def test_column_defaults
256
+ klass.lease_connection.create_table(:spatial_models, force: true) do |t|
257
+ t.column 'sample_integer', :integer, default: -1
258
+ end
259
+ klass.reset_column_information
260
+ assert_equal(-1, klass.new.sample_integer)
261
+ end
262
+
263
+ def test_column_types
264
+ klass.lease_connection.create_table(:spatial_models, force: true) do |t|
265
+ t.column 'sample_integer', :integer
266
+ t.column 'sample_string', :string
267
+ t.column 'latlon', :st_point
268
+ end
269
+ klass.reset_column_information
270
+ assert_equal :integer, klass.columns[-3].type
271
+ assert_equal :string, klass.columns[-2].type
272
+ assert_equal :geometry, klass.columns[-1].type
273
+ end
274
+
275
+ def test_array_columns
276
+ klass.lease_connection.create_table(:spatial_models, force: true) do |t|
277
+ t.column 'sample_array', :string, array: true
278
+ t.column 'sample_non_array', :string
279
+ end
280
+ klass.reset_column_information
281
+
282
+ assert_equal true, klass.columns[-2].array
283
+ assert_equal false, klass.columns[-1].array
284
+ end
285
+
286
+ def test_reload_dumped_schema
287
+ klass.lease_connection.create_table(:spatial_models, force: true) do |t|
288
+ t.geography 'latlon1', limit: { srid: 4326, type: 'point', geographic: true }
289
+ end
290
+ klass.reset_column_information
291
+ col = klass.columns.last
292
+ assert_equal 4326, col.srid
293
+ end
294
+
295
+ def test_non_spatial_column_limits
296
+ klass.lease_connection.create_table(:spatial_models, force: true) do |t|
297
+ t.string :foo, limit: 123
298
+ end
299
+ klass.reset_column_information
300
+ col = klass.columns.last
301
+ assert_equal 123, col.limit
302
+ end
303
+
304
+ def test_column_comments
305
+ klass.lease_connection.create_table(:spatial_models, force: true) do |t|
306
+ t.string :sample_comment, comment: 'Comment test'
307
+ end
308
+ klass.reset_column_information
309
+ col = klass.columns.last
310
+ assert_equal 'Comment test', col.comment
311
+ end
312
+
313
+ private
314
+
315
+ def klass
316
+ SpatialModel
317
+ end
318
+
319
+ def count_geometry_columns
320
+ klass.lease_connection.select_value(geo_column_sql('geometry_columns', klass.table_name)).to_i
321
+ end
322
+
323
+ def geo_column_sql(postgis_view, table_name)
324
+ "SELECT COUNT(*) FROM #{postgis_view} WHERE f_table_name='#{table_name}'"
325
+ end
326
+ end