activerecord-cockroachdb-adapter 8.0.3 → 8.1.1

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 (241) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +10 -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 +69 -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 +137 -51
  12. data/lib/active_record/connection_adapters/cockroachdb/schema_statements.rb +181 -102
  13. data/lib/active_record/connection_adapters/cockroachdb_adapter.rb +78 -34
  14. data/lib/version.rb +1 -1
  15. data/test/cases/adapter_test.rb +98 -0
  16. data/test/cases/adapters/cockroachdb/cached_plan_failure_test.rb +106 -0
  17. data/test/cases/adapters/cockroachdb/referential_integrity_test.rb +91 -0
  18. data/test/cases/adapters/postgresql/active_schema_test.rb +71 -0
  19. data/test/cases/adapters/postgresql/change_schema_test.rb +75 -0
  20. data/test/cases/adapters/postgresql/connection_test.rb +46 -0
  21. data/test/cases/adapters/postgresql/ddl_test.rb +326 -0
  22. data/test/cases/adapters/postgresql/interval_test.rb +131 -0
  23. data/test/cases/adapters/postgresql/nested_class_test.rb +22 -0
  24. data/test/cases/adapters/postgresql/numeric_test.rb +28 -0
  25. data/test/cases/adapters/postgresql/postgis_test.rb +199 -0
  26. data/test/cases/adapters/postgresql/postgresql_adapter_test.rb +115 -0
  27. data/test/cases/adapters/postgresql/quoting_test.rb +30 -0
  28. data/test/cases/adapters/postgresql/schema_statements_test.rb +29 -0
  29. data/test/cases/adapters/postgresql/serial_test.rb +199 -0
  30. data/test/cases/adapters/postgresql/spatial_queries_test.rb +118 -0
  31. data/test/cases/adapters/postgresql/spatial_setup_test.rb +18 -0
  32. data/test/cases/adapters/postgresql/spatial_type_test.rb +41 -0
  33. data/test/cases/adapters/postgresql/timestamp_test.rb +58 -0
  34. data/test/cases/adapters/postgresql/virtual_column_test.rb +39 -0
  35. data/test/cases/associations/eager_load_nested_include_test.rb +111 -0
  36. data/test/cases/associations/left_outer_join_association_test.rb +30 -0
  37. data/test/cases/associations_test.rb +108 -0
  38. data/test/cases/base_test.rb +31 -0
  39. data/test/cases/comment_test.rb +75 -0
  40. data/test/cases/connection_adapters/type_test.rb +28 -0
  41. data/test/cases/database_configurations/resolver_test.rb +24 -0
  42. data/test/cases/defaults_test.rb +45 -0
  43. data/test/cases/dirty_test.rb +24 -0
  44. data/test/cases/fixtures_test.rb +541 -0
  45. data/test/cases/helper_cockroachdb.rb +232 -0
  46. data/test/cases/inheritance_test.rb +42 -0
  47. data/test/cases/invertible_migration_test.rb +73 -0
  48. data/test/cases/marshal_serialization_test.rb +45 -0
  49. data/test/cases/migration/change_schema_test.rb +140 -0
  50. data/test/cases/migration/check_constraint_test.rb +125 -0
  51. data/test/cases/migration/columns_test.rb +50 -0
  52. data/test/cases/migration/create_join_table_test.rb +66 -0
  53. data/test/cases/migration/foreign_key_test.rb +390 -0
  54. data/test/cases/migration/hidden_column_test.rb +70 -0
  55. data/test/cases/migration/references_foreign_key_test.rb +124 -0
  56. data/test/cases/migration_test.rb +120 -0
  57. data/test/cases/persistence_test.rb +33 -0
  58. data/test/cases/primary_keys_test.rb +134 -0
  59. data/test/cases/relation/aost_test.rb +57 -0
  60. data/test/cases/relation/or_test.rb +26 -0
  61. data/test/cases/relation/table_hints_test.rb +124 -0
  62. data/test/cases/relation_test.rb +26 -0
  63. data/test/cases/relations_test.rb +29 -0
  64. data/test/cases/schema_dumper_test.rb +221 -0
  65. data/test/cases/show_create_test.rb +14 -0
  66. data/test/cases/strict_loading_test.rb +34 -0
  67. data/test/cases/tasks/cockroachdb_rake_test.rb +113 -0
  68. data/test/cases/test_fixtures_test.rb +57 -0
  69. data/test/cases/transactions_test.rb +51 -0
  70. data/test/cases/unsafe_raw_sql_test.rb +22 -0
  71. data/test/config.yml +23 -0
  72. data/test/excludes/ActiveRecord/AdapterTest.rb +3 -0
  73. data/test/excludes/ActiveRecord/AdapterTestWithoutTransaction.rb +25 -0
  74. data/test/excludes/ActiveRecord/ConnectionAdapters/PoolConfig/ResolverTest.rb +1 -0
  75. data/test/excludes/ActiveRecord/ConnectionAdapters/PostgreSQLAdapter/BindParameterTest.rb +15 -0
  76. data/test/excludes/ActiveRecord/ConnectionAdapters/PostgreSQLAdapter/QuotingTest.rb +22 -0
  77. data/test/excludes/ActiveRecord/ConnectionAdapters/PostgreSQLAdapterPreventWritesLegacyTest.rb +1 -0
  78. data/test/excludes/ActiveRecord/ConnectionAdapters/PostgreSQLAdapterPreventWritesTest.rb +1 -0
  79. data/test/excludes/ActiveRecord/ConnectionAdapters/PostgreSQLAdapterTest.rb +40 -0
  80. data/test/excludes/ActiveRecord/ConnectionAdapters/RegistrationIsolatedTest.rb +14 -0
  81. data/test/excludes/ActiveRecord/Encryption/EncryptionPerformanceTest.rb +1 -0
  82. data/test/excludes/ActiveRecord/Encryption/EnvelopeEncryptionPerformanceTest.rb +1 -0
  83. data/test/excludes/ActiveRecord/Encryption/ExtendedDeterministicQueriesPerformanceTest.rb +1 -0
  84. data/test/excludes/ActiveRecord/Encryption/StoragePerformanceTest.rb +2 -0
  85. data/test/excludes/ActiveRecord/InstrumentationTest.rb +16 -0
  86. data/test/excludes/ActiveRecord/InvertibleMigrationTest.rb +2 -0
  87. data/test/excludes/ActiveRecord/Migration/ChangeSchemaTest.rb +7 -0
  88. data/test/excludes/ActiveRecord/Migration/CheckConstraintTest.rb +6 -0
  89. data/test/excludes/ActiveRecord/Migration/ColumnsTest.rb +4 -0
  90. data/test/excludes/ActiveRecord/Migration/CompatibilityTest.rb +50 -0
  91. data/test/excludes/ActiveRecord/Migration/CompositeForeignKeyTest.rb +2 -0
  92. data/test/excludes/ActiveRecord/Migration/CreateJoinTableTest.rb +2 -0
  93. data/test/excludes/ActiveRecord/Migration/ForeignKeyInCreateTest.rb +1 -0
  94. data/test/excludes/ActiveRecord/Migration/ForeignKeyTest.rb +35 -0
  95. data/test/excludes/ActiveRecord/Migration/InvalidOptionsTest.rb +14 -0
  96. data/test/excludes/ActiveRecord/Migration/PGChangeSchemaTest.rb +8 -0
  97. data/test/excludes/ActiveRecord/Migration/ReferencesForeignKeyTest.rb +7 -0
  98. data/test/excludes/ActiveRecord/Migration/ReferencesIndexTest.rb +7 -0
  99. data/test/excludes/ActiveRecord/Migration/ReferencesStatementsTest.rb +3 -0
  100. data/test/excludes/ActiveRecord/MysqlDBCreateWithInvalidPermissionsTest.rb +1 -0
  101. data/test/excludes/ActiveRecord/OrTest.rb +1 -0
  102. data/test/excludes/ActiveRecord/PostgreSQLStructureDumpTest.rb +10 -0
  103. data/test/excludes/ActiveRecord/PostgresqlConnectionTest.rb +12 -0
  104. data/test/excludes/ActiveRecord/PostgresqlTransactionNestedTest.rb +14 -0
  105. data/test/excludes/ActiveRecord/PostgresqlTransactionTest.rb +4 -0
  106. data/test/excludes/ActiveRecord/RelationTest.rb +2 -0
  107. data/test/excludes/ActiveRecord/TooManyOrTest.rb +1 -0
  108. data/test/excludes/ActiveSupportSubclassWithFixturesTest.rb +1 -0
  109. data/test/excludes/AssociationDeprecationTest/NotifyModeTest.rb +2 -0
  110. data/test/excludes/AssociationDeprecationTest/RaiseBacktraceModeTest.rb +2 -0
  111. data/test/excludes/AssociationDeprecationTest/RaiseModeTest.rb +2 -0
  112. data/test/excludes/AssociationDeprecationTest/WarnBacktraceModeTest.rb +2 -0
  113. data/test/excludes/AssociationDeprecationTest/WarnModeTest.rb +2 -0
  114. data/test/excludes/AssociationDeprecationTest/fix_backtrace_cleaner.rb +10 -0
  115. data/test/excludes/BasicsTest.rb +1 -0
  116. data/test/excludes/BulkAlterTableMigrationsTest.rb +7 -0
  117. data/test/excludes/CalculationsTest.rb +4 -0
  118. data/test/excludes/CommentTest.rb +2 -0
  119. data/test/excludes/CoreTest.rb +1 -0
  120. data/test/excludes/CreateOrFindByWithinTransactions.rb +3 -0
  121. data/test/excludes/DefaultsUsingMultipleSchemasAndDomainTest.rb +7 -0
  122. data/test/excludes/DirtyTest.rb +3 -0
  123. data/test/excludes/EachTest.rb +8 -0
  124. data/test/excludes/EagerLoadPolyAssocsTest.rb +1 -0
  125. data/test/excludes/ExplicitlyNamedIndexMigrationTest.rb +1 -0
  126. data/test/excludes/FixturesResetPkSequenceTest.rb +3 -0
  127. data/test/excludes/FixturesTest.rb +21 -0
  128. data/test/excludes/FixturesWithForeignKeyViolationsTest.rb +2 -0
  129. data/test/excludes/ForeignTableTest.rb +10 -0
  130. data/test/excludes/InheritanceComputeTypeTest.rb +1 -0
  131. data/test/excludes/LeftOuterJoinAssociationTest.rb +2 -0
  132. data/test/excludes/LegacyPrimaryKeyTest/V4_2.rb +6 -0
  133. data/test/excludes/LegacyPrimaryKeyTest/V5_0.rb +6 -0
  134. data/test/excludes/MarshalSerializationTest.rb +4 -0
  135. data/test/excludes/MaterializedViewTest.rb +13 -0
  136. data/test/excludes/MigrationTest.rb +2 -0
  137. data/test/excludes/MultiDbMigratorTest.rb +2 -0
  138. data/test/excludes/NestedRelationScopingTest.rb +1 -0
  139. data/test/excludes/OrTest.rb +1 -0
  140. data/test/excludes/PersistenceTest.rb +3 -0
  141. data/test/excludes/PessimisticLockingTest.rb +1 -0
  142. data/test/excludes/PostgreSQLExplainTest.rb +7 -0
  143. data/test/excludes/PostgreSQLGeometricLineTest.rb +3 -0
  144. data/test/excludes/PostgreSQLGeometricTypesTest.rb +7 -0
  145. data/test/excludes/PostgreSQLPartitionsTest.rb +1 -0
  146. data/test/excludes/PostgreSQLReferentialIntegrityTest.rb +14 -0
  147. data/test/excludes/PostgresqlArrayTest.rb +21 -0
  148. data/test/excludes/PostgresqlBigSerialTest.rb +7 -0
  149. data/test/excludes/PostgresqlBitStringTest.rb +2 -0
  150. data/test/excludes/PostgresqlByteaTest.rb +1 -0
  151. data/test/excludes/PostgresqlCitextTest.rb +7 -0
  152. data/test/excludes/PostgresqlCollationTest.rb +5 -0
  153. data/test/excludes/PostgresqlCompositeTest.rb +2 -0
  154. data/test/excludes/PostgresqlCompositeWithCustomOIDTest.rb +2 -0
  155. data/test/excludes/PostgresqlDataTypeTest.rb +9 -0
  156. data/test/excludes/PostgresqlDefaultExpressionTest.rb +1 -0
  157. data/test/excludes/PostgresqlDeferredConstraintsTest.rb +3 -0
  158. data/test/excludes/PostgresqlDomainTest.rb +2 -0
  159. data/test/excludes/PostgresqlExtensionMigrationTest.rb +5 -0
  160. data/test/excludes/PostgresqlFullTextTest.rb +3 -0
  161. data/test/excludes/PostgresqlGeometricTest.rb +4 -0
  162. data/test/excludes/PostgresqlHstoreTest.rb +45 -0
  163. data/test/excludes/PostgresqlInfinityTest.rb +5 -0
  164. data/test/excludes/PostgresqlIntervalTest.rb +1 -0
  165. data/test/excludes/PostgresqlJSONBTest.rb +27 -0
  166. data/test/excludes/PostgresqlJSONTest.rb +27 -0
  167. data/test/excludes/PostgresqlLtreeTest.rb +4 -0
  168. data/test/excludes/PostgresqlMoneyTest.rb +12 -0
  169. data/test/excludes/PostgresqlNetworkTest.rb +69 -0
  170. data/test/excludes/PostgresqlNumberTest.rb +1 -0
  171. data/test/excludes/PostgresqlPointTest.rb +15 -0
  172. data/test/excludes/PostgresqlRangeTest.rb +3 -0
  173. data/test/excludes/PostgresqlRenameTableTest.rb +2 -0
  174. data/test/excludes/PostgresqlSerialTest.rb +7 -0
  175. data/test/excludes/PostgresqlTimestampFixtureTest.rb +2 -0
  176. data/test/excludes/PostgresqlTimestampMigrationTest.rb +3 -0
  177. data/test/excludes/PostgresqlTypeLookupTest.rb +2 -0
  178. data/test/excludes/PostgresqlUUIDGenerationTest.rb +7 -0
  179. data/test/excludes/PostgresqlUUIDTest.rb +1 -0
  180. data/test/excludes/PostgresqlVirtualColumnTest.rb +17 -0
  181. data/test/excludes/PostgresqlXMLTest.rb +5 -0
  182. data/test/excludes/PrimaryKeyIntegerNilDefaultTest.rb +1 -0
  183. data/test/excludes/PrimaryKeyIntegerTest.rb +3 -0
  184. data/test/excludes/PrimaryKeysTest.rb +2 -0
  185. data/test/excludes/QueryCacheExpiryTest.rb +10 -0
  186. data/test/excludes/RelationMergingTest.rb +15 -0
  187. data/test/excludes/RelationTest.rb +3 -0
  188. data/test/excludes/ReservedWordsMigrationTest.rb +1 -0
  189. data/test/excludes/SameNameDifferentDatabaseFixturesTest.rb +1 -0
  190. data/test/excludes/SanitizeTest.rb +13 -0
  191. data/test/excludes/SchemaAuthorizationTest.rb +8 -0
  192. data/test/excludes/SchemaCreateTableOptionsTest.rb +2 -0
  193. data/test/excludes/SchemaDumperDefaultsTest.rb +1 -0
  194. data/test/excludes/SchemaDumperTest.rb +11 -0
  195. data/test/excludes/SchemaForeignKeyTest.rb +1 -0
  196. data/test/excludes/SchemaIndexNullsOrderTest.rb +2 -0
  197. data/test/excludes/SchemaIndexOpclassTest.rb +3 -0
  198. data/test/excludes/SchemaTest.rb +49 -0
  199. data/test/excludes/SequenceNameDetectionTestCases/CollidedSequenceNameTest.rb +1 -0
  200. data/test/excludes/SequenceNameDetectionTestCases/LongerSequenceNameDetectionTest.rb +1 -0
  201. data/test/excludes/StrictLoadingFixturesTest.rb +1 -0
  202. data/test/excludes/TestFixturesTest.rb +1 -0
  203. data/test/excludes/TransactionInstrumentationTest.rb +1 -0
  204. data/test/excludes/TransactionIsolationTest.rb +1 -0
  205. data/test/excludes/TypeTest.rb +1 -0
  206. data/test/excludes/UniquenessValidationTest.rb +2 -0
  207. data/test/excludes/UnloggedTablesTest.rb +3 -0
  208. data/test/excludes/UnsafeRawSqlTest.rb +2 -0
  209. data/test/excludes/UpdateableViewTest.rb +5 -0
  210. data/test/excludes/WithAnnotationsTest.rb +6 -0
  211. data/test/models/building.rb +4 -0
  212. data/test/models/spatial_model.rb +5 -0
  213. data/test/schema/cockroachdb_specific_schema.rb +218 -0
  214. data/test/support/copy_cat.rb +83 -0
  215. data/test/support/exclude_from_transactional_tests.rb +33 -0
  216. data/test/support/paths_cockroachdb.rb +46 -0
  217. data/test/support/rake_helpers.rb +37 -0
  218. data/test/support/sql_logger.rb +55 -0
  219. data/test/support/template_creator.rb +114 -0
  220. metadata +422 -30
  221. data/.editorconfig +0 -7
  222. data/.github/issue_template.md +0 -46
  223. data/.github/reproduction_scripts/migrations.rb +0 -60
  224. data/.github/reproduction_scripts/models_and_database.rb +0 -49
  225. data/.github/workflows/ci.yml +0 -96
  226. data/.github/workflows/docker.yml +0 -57
  227. data/.gitignore +0 -18
  228. data/.gitmodules +0 -0
  229. data/activerecord-cockroachdb-adapter.gemspec +0 -38
  230. data/bin/console +0 -36
  231. data/bin/console_schemas/default.rb +0 -11
  232. data/bin/console_schemas/schemas.rb +0 -23
  233. data/bin/setup +0 -8
  234. data/bin/start-cockroachdb +0 -33
  235. data/build/Dockerfile +0 -14
  236. data/build/config.teamcity.yml +0 -31
  237. data/build/local-test.sh +0 -32
  238. data/build/teamcity-test.sh +0 -76
  239. data/docker.sh +0 -35
  240. data/lib/active_record/connection_adapters/cockroachdb/spatial_column_info.rb +0 -60
  241. data/setup.sql +0 -18
@@ -0,0 +1,115 @@
1
+ require "cases/helper_cockroachdb"
2
+ require "cases/helper"
3
+ require "support/ddl_helper"
4
+ require "support/connection_helper"
5
+ require "support/copy_cat"
6
+
7
+ module CockroachDB
8
+ module ConnectionAdapters
9
+ class PostgreSQLAdapterTest < ActiveRecord::PostgreSQLTestCase
10
+ self.use_transactional_tests = false
11
+ include DdlHelper
12
+ include ConnectionHelper
13
+
14
+ def setup
15
+ @connection = ActiveRecord::Base.lease_connection
16
+ end
17
+
18
+ def teardown
19
+ # use connection without follower_reads and telemetry
20
+ database_config = { "adapter" => "cockroachdb", "database" => "activerecord_unittest" }
21
+ ar_config = ActiveRecord::Base.configurations.configs_for(env_name: "arunit", name: "primary")
22
+ database_config.update(ar_config.configuration_hash)
23
+
24
+ ActiveRecord::Base.establish_connection(database_config)
25
+ end
26
+
27
+ def test_database_exists_returns_false_when_the_database_does_not_exist
28
+ config_base = ActiveRecord::Base.configurations.configs_for(env_name: "arunit", name: "primary").configuration_hash
29
+ [ config_base.merge(database: "non_extant_database", adapter: "cockroachdb"),
30
+ config_base.merge(database: "non_extant_database", adapter: "postgresql")
31
+ ].each do |config|
32
+ assert_not ActiveRecord::ConnectionAdapters::CockroachDBAdapter.database_exists?(config),
33
+ "expected database #{config[:database]} to not exist"
34
+ end
35
+ end
36
+
37
+ def test_database_exists_returns_true_when_the_database_exists
38
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: "arunit", name: "primary")
39
+ assert ActiveRecord::ConnectionAdapters::CockroachDBAdapter.database_exists?(db_config.configuration_hash),
40
+ "expected database #{db_config.database} to exist"
41
+ end
42
+
43
+ def test_using_telemetry_builtin_connects_properly
44
+ database_config = { "adapter" => "cockroachdb", "database" => "activerecord_unittest" }
45
+ ar_config = ActiveRecord::Base.configurations.configs_for(env_name: "arunit", name: "primary")
46
+ database_config.update(ar_config.configuration_hash)
47
+ database_config[:disable_cockroachdb_telemetry] = false
48
+
49
+ ActiveRecord::Base.establish_connection(database_config)
50
+ conn = ActiveRecord::Base.lease_connection
51
+ conn_config = conn.instance_variable_get("@config")
52
+
53
+ assert_equal(false, conn_config[:disable_cockroachdb_telemetry])
54
+ end
55
+
56
+ def test_using_follower_reads_connects_properly
57
+ database_config = { "use_follower_reads_for_type_introspection": true, "adapter" => "cockroachdb", "database" => "activerecord_unittest" }
58
+ ar_config = ActiveRecord::Base.configurations.configs_for(env_name: "arunit", name: "primary")
59
+ database_config.update(ar_config.configuration_hash)
60
+
61
+ ActiveRecord::Base.establish_connection(database_config)
62
+ conn = ActiveRecord::Base.lease_connection
63
+ conn_config = conn.instance_variable_get("@config")
64
+
65
+ assert conn_config[:use_follower_reads_for_type_introspection]
66
+ end
67
+
68
+ # OVERRIDE: CockroachDB adds parentheses around the WHERE clause's content.
69
+ def test_partial_index_on_column_named_like_keyword
70
+ with_example_table('id serial primary key, number integer, "primary" boolean') do
71
+ @connection.add_index "ex", "id", name: "partial", where: "primary" # "primary" is a keyword
72
+ index = @connection.indexes("ex").find { |idx| idx.name == "partial" }
73
+ assert_equal '("primary")', index.where
74
+ end
75
+ end
76
+
77
+ # OVERRIDE: Different behaviour between PostgreSQL and CockroachDB.
78
+ def test_invalid_index
79
+ with_example_table do
80
+ @connection.exec_query("INSERT INTO ex (number) VALUES (1), (1)")
81
+ error = assert_raises(ActiveRecord::RecordNotUnique) do
82
+ @connection.add_index(:ex, :number, unique: true, algorithm: :concurrently, name: :invalid_index)
83
+ end
84
+ assert_match(/duplicate key value violates unique constraint/, error.message)
85
+ assert_equal @connection.pool, error.connection_pool
86
+
87
+ # In CRDB this tests won't create the index at all.
88
+ assert_not @connection.index_exists?(:ex, :number, name: :invalid_index)
89
+ end
90
+ end
91
+
92
+ # OVERRIDE: the `default_sequence_name` is `nil`, let's `to_s` it
93
+ # for a fair comparison.
94
+ CopyCat.copy_methods(self, ActiveRecord::ConnectionAdapters::PostgreSQLAdapterTest,
95
+ :test_pk_and_sequence_for,
96
+ :test_pk_and_sequence_for_with_non_standard_primary_key
97
+ ) do
98
+ attr_accessor :already_updated
99
+ def on_send(node)
100
+ return super unless node in [:send, _, :default_sequence_name, [:str, "ex"], [:str, "id"|"code"]]
101
+
102
+ raise "The source code must have changed" if already_updated
103
+ already_updated ||= :yes
104
+ insert_after(node.loc.expression, ".to_s")
105
+ end
106
+ end
107
+
108
+ private
109
+
110
+ CopyCat.copy_methods(self, ActiveRecord::ConnectionAdapters::PostgreSQLAdapterTest,
111
+ :with_example_table
112
+ )
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,30 @@
1
+ require "cases/helper_cockroachdb"
2
+
3
+ # Load dependencies from ActiveRecord test suite
4
+ require "support/schema_dumping_helper"
5
+
6
+ module CockroachDB
7
+ class PostgresqlQuotingTest < ActiveRecord::PostgreSQLTestCase
8
+ def setup
9
+ @conn = ActiveRecord::Base.lease_connection
10
+ @raise_int_wider_than_64bit = ActiveRecord.raise_int_wider_than_64bit
11
+ end
12
+
13
+ # Replace the original test since numbers are quoted.
14
+ def test_do_not_raise_when_int_is_not_wider_than_64bit
15
+ value = 9223372036854775807
16
+ assert_equal "'9223372036854775807'", @conn.quote(value)
17
+
18
+ value = -9223372036854775808
19
+ assert_equal "'-9223372036854775808'", @conn.quote(value)
20
+ end
21
+
22
+ # Replace the original test since numbers are quoted.
23
+ def test_do_not_raise_when_raise_int_wider_than_64bit_is_false
24
+ ActiveRecord.raise_int_wider_than_64bit = false
25
+ value = 9223372036854775807 + 1
26
+ assert_equal "'9223372036854775808'", @conn.quote(value)
27
+ ActiveRecord.raise_int_wider_than_64bit = @raise_int_wider_than_64bit
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cases/helper_cockroachdb'
4
+ require 'models/building'
5
+
6
+ class SchemaStatementsTest < ActiveRecord::PostgreSQLTestCase
7
+ def test_no_crdb_internal_in_schema_names
8
+ assert_not_includes Building.lease_connection.schema_names, "crdb_internal"
9
+ end
10
+
11
+ def test_initialize_type_map
12
+ initialized_types = Building.lease_connection.send(:type_map).keys
13
+
14
+ # PostGIS types must be initialized first, so
15
+ # ActiveRecord::ConnectionAdapters::PostgreSQLAdapter#load_additional_types can use them.
16
+ # https://github.com/rails/rails/blob/8d57cb39a88787bb6cfb7e1c481556ef6d8ede7a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb#L593
17
+ assert_equal initialized_types.first(9), %w[
18
+ geography
19
+ geometry
20
+ geometry_collection
21
+ line_string
22
+ multi_line_string
23
+ multi_point
24
+ multi_polygon
25
+ st_point
26
+ st_polygon
27
+ ]
28
+ end
29
+ end
@@ -0,0 +1,199 @@
1
+ require "cases/helper_cockroachdb"
2
+
3
+ # Load dependencies from ActiveRecord test suite
4
+ require "support/schema_dumping_helper"
5
+
6
+ module CockroachDB
7
+ class PostgresqlSerialTest < ActiveRecord::PostgreSQLTestCase
8
+ include SchemaDumpingHelper
9
+
10
+ class PostgresqlSerial < ActiveRecord::Base; end
11
+
12
+ setup do
13
+ @connection = ActiveRecord::Base.lease_connection
14
+ @connection.create_table "postgresql_serials", force: true do |t|
15
+ t.serial :seq
16
+
17
+ # Instead of creating this column with a sequence default, we'll create
18
+ # it with a unique_rowid() default. This better matches the behavior in
19
+ # CockroachDB.
20
+ t.integer :serials_id, default: -> { "unique_rowid()" }
21
+ end
22
+ end
23
+
24
+ teardown do
25
+ @connection.drop_table "postgresql_serials", if_exists: true
26
+ end
27
+
28
+ # This replaces the same test that's been excluded from
29
+ # PostgresqlSerialTest. The column's type is integer, but it's sql_type is
30
+ # bigint because CockroachDB's integers are bigints.
31
+ # See test/excludes/PostgresqlSerialTest.rb
32
+ def test_serial_column
33
+ column = PostgresqlSerial.columns_hash["seq"]
34
+ assert_equal :integer, column.type
35
+ assert_equal "bigint", column.sql_type
36
+ assert_predicate column, :serial?
37
+ end
38
+
39
+ # This replaces the same test that's been excluded from
40
+ # PostgresqlSerialTest. The column's type is integer, but it's sql_type is
41
+ # bigint because CockroachDB's integers are bigints. The column is also
42
+ # serial? because it uses the same default function that serial columns use.
43
+ # See test/excludes/PostgresqlSerialTest.rb
44
+ def test_not_serial_column
45
+ column = PostgresqlSerial.columns_hash["serials_id"]
46
+ assert_equal :integer, column.type
47
+ assert_equal "bigint", column.sql_type
48
+ assert_predicate column, :serial?
49
+ end
50
+
51
+ # This replaces the same test that's been excluded from
52
+ # PostgresqlSerialTest. Although the seq column was created as a serial
53
+ # column, the dump will include it as a bigserial column. That's because
54
+ # serial columns are backed by integer columns, and integer columns are
55
+ # bigints in CockroachDB.
56
+ # See test/excludes/PostgresqlSerialTest.rb
57
+ def test_schema_dump_with_shorthand
58
+ output = dump_table_schema "postgresql_serials"
59
+ assert_match %r{t\.bigserial\s+"seq",\s+null: false$}, output
60
+ end
61
+
62
+ # This replaces the same test that's been excluded from
63
+ # PostgresqlSerialTest. The serials_id column wasn't created as a serial
64
+ # column, but the dump will include it as such because it has the same
65
+ # default function has a serial column.
66
+ # See test/excludes/PostgresqlSerialTest.rb
67
+ def test_schema_dump_with_not_serial
68
+ output = dump_table_schema "postgresql_serials"
69
+ assert_match %r{t\.bigserial\s+"serials_id"$}, output
70
+ end
71
+ end
72
+
73
+ class PostgresqlBigSerialTest < ActiveRecord::PostgreSQLTestCase
74
+ include SchemaDumpingHelper
75
+
76
+ class PostgresqlBigSerial < ActiveRecord::Base; end
77
+
78
+ setup do
79
+ @connection = ActiveRecord::Base.lease_connection
80
+ @connection.create_table "postgresql_big_serials", force: true do |t|
81
+ t.bigserial :seq
82
+
83
+ # Instead of creating this column with a sequence default, we'll create
84
+ # it with a unique_rowid() default. This better matches the behavior in
85
+ # CockroachDB.
86
+ t.bigint :serials_id, default: -> { "unique_rowid()" }
87
+ end
88
+ end
89
+
90
+ teardown do
91
+ @connection.drop_table "postgresql_big_serials", if_exists: true
92
+ end
93
+
94
+ # This replaces the same test that's been excluded from
95
+ # PostgresqlBigSerialTest. We can run it here because the setup has been
96
+ # fixed.
97
+ # See test/excluded/PostgresqlBigSerialTest.rb
98
+ def test_bigserial_column
99
+ column = PostgresqlBigSerial.columns_hash["seq"]
100
+ assert_equal :integer, column.type
101
+ assert_equal "bigint", column.sql_type
102
+ assert_predicate column, :serial?
103
+ end
104
+
105
+ # This replaces the same test that's been excluded from
106
+ # PostgresqlBigSerialTest. The column is serial? because it uses the same
107
+ # default function that serial columns use.
108
+ # See test/excludes/PostgresqlBigSerialTest.rb
109
+ def test_not_bigserial_column
110
+ column = PostgresqlBigSerial.columns_hash["serials_id"]
111
+ assert_equal :integer, column.type
112
+ assert_equal "bigint", column.sql_type
113
+ assert_predicate column, :serial?
114
+ end
115
+
116
+ # This replaces the same test that's been excluded from
117
+ # PostgresqlBigSerialTest. We can run it here because the setup has been
118
+ # fixed.
119
+ # See test/excluded/PostgresqlBigSerialTest.rb
120
+ def test_schema_dump_with_shorthand
121
+ output = dump_table_schema "postgresql_big_serials"
122
+ assert_match %r{t\.bigserial\s+"seq",\s+null: false$}, output
123
+ end
124
+
125
+ # This replaces the same test that's been excluded from
126
+ # PostgresqlBigSerialTest. The serials_id column wasn't created as a serial
127
+ # column, but the dump will include it as such because it has the same
128
+ # default function has a serial column.
129
+ # See test/excluded/PostgresqlBigSerialTest.rb
130
+ def test_schema_dump_with_not_bigserial
131
+ output = dump_table_schema "postgresql_big_serials"
132
+ assert_match %r{t\.bigserial\s+"serials_id"$}, output
133
+ end
134
+ end
135
+
136
+ module SequenceNameDetectionTestCases
137
+ class CollidedSequenceNameTest < ActiveRecord::PostgreSQLTestCase
138
+ include SchemaDumpingHelper
139
+
140
+ def setup
141
+ @connection = ActiveRecord::Base.lease_connection
142
+ @connection.create_table :foo_bar, force: true do |t|
143
+ t.serial :baz_id
144
+ end
145
+ @connection.create_table :foo, force: true do |t|
146
+ t.serial :bar_id
147
+ t.bigserial :bar_baz_id
148
+ end
149
+ end
150
+
151
+ def teardown
152
+ @connection.drop_table :foo_bar, if_exists: true
153
+ @connection.drop_table :foo, if_exists: true
154
+ end
155
+
156
+ # This replaces the same test that's been excluded from
157
+ # SequenceNameDetectionTestCases::CollidedSequenceNameTest. Although
158
+ # bar_id was created as a serial column, it will get dumped as a bigserial
159
+ # column. Serial columns are backed by integer columns, and integer
160
+ # columns are bigints in CockroachDB.
161
+ # See test/excludes/SequenceNameDetectionTestCases/CollidedSequenceNameTest.rb
162
+ def test_schema_dump_with_collided_sequence_name
163
+ output = dump_table_schema "foo"
164
+ assert_match %r{t\.bigserial\s+"bar_id",\s+null: false$}, output
165
+ assert_match %r{t\.bigserial\s+"bar_baz_id",\s+null: false$}, output
166
+ end
167
+ end
168
+
169
+ class LongerSequenceNameDetectionTest < ActiveRecord::PostgreSQLTestCase
170
+ include SchemaDumpingHelper
171
+
172
+ def setup
173
+ @table_name = "long_table_name_to_test_sequence_name_detection_for_serial_cols"
174
+ @connection = ActiveRecord::Base.lease_connection
175
+ @connection.create_table @table_name, force: true do |t|
176
+ t.serial :seq
177
+ t.bigserial :bigseq
178
+ end
179
+ end
180
+
181
+ def teardown
182
+ @connection.drop_table @table_name, if_exists: true
183
+ end
184
+
185
+ # This replaces the same test that's been excluded from
186
+ # SequenceNameDetectionTestCases::LongerSequenceNameDetectionTest.
187
+ # Although seq was created as a serial column, it will get dumped as a bigserial
188
+ # column. Serial columns are backed by integer columns, and integer
189
+ # columns are bigints in CockroachDB.
190
+ # See test/excludes/SequenceNameDetectionTestCases/LongerSequenceNameDetectionTest.rb
191
+ def test_schema_dump_with_long_table_name
192
+ output = dump_table_schema @table_name
193
+ assert_match %r{create_table "#{@table_name}", force: :cascade}, output
194
+ assert_match %r{t\.bigserial\s+"seq",\s+null: false$}, output
195
+ assert_match %r{t\.bigserial\s+"bigseq",\s+null: false$}, output
196
+ end
197
+ end
198
+ end
199
+ end
@@ -0,0 +1,118 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cases/helper_cockroachdb'
4
+ require 'models/building'
5
+
6
+ class SpatialQueriesTest < ActiveSupport::TestCase
7
+ def setup
8
+ Building.delete_all
9
+ end
10
+
11
+ def test_query_point
12
+ obj = Building.create!(coordinates: factory.point(1, 2))
13
+ id = obj.id
14
+ assert_empty Building.where(coordinates: factory.point(2, 2))
15
+ obj1 = Building.find_by(coordinates: factory.point(1, 2))
16
+ refute_nil(obj1)
17
+ assert_equal id, obj1.id
18
+ end
19
+
20
+ def test_query_multi_point
21
+ obj = Building.create!(points: factory.multi_point([factory.point(1, 2)]))
22
+ id = obj.id
23
+ obj2 = Building.find_by(points: factory.multi_point([factory.point(1, 2)]))
24
+ refute_nil(obj2)
25
+ assert_equal(id, obj2.id)
26
+ end
27
+
28
+ def test_query_point_wkt
29
+ obj = Building.create!(coordinates: factory.point(1, 2))
30
+ id = obj.id
31
+ obj2 = Building.find_by(coordinates: 'SRID=3857;POINT(1 2)')
32
+ refute_nil(obj2)
33
+ assert_equal(id, obj2.id)
34
+ obj3 = Building.find_by(coordinates: 'SRID=3857;POINT(2 2)')
35
+ assert_nil(obj3)
36
+ end
37
+
38
+ def test_query_st_distance
39
+ obj = Building.create!(coordinates: factory.point(1, 2))
40
+ id = obj.id
41
+ obj2 = Building.find_by(Building.arel_table[:coordinates].st_distance('SRID=3857;POINT(2 3)').lt(2))
42
+ refute_nil(obj2)
43
+ assert_equal(id, obj2.id)
44
+ obj3 = Building.find_by(Building.arel_table[:coordinates].st_distance('SRID=3857;POINT(2 3)').gt(2))
45
+ assert_nil(obj3)
46
+ end
47
+
48
+ def test_query_st_distance_from_constant
49
+ obj = Building.create!(coordinates: factory.point(1, 2))
50
+ id = obj.id
51
+
52
+ query_point = parser.parse('SRID=3857;POINT(2 3)')
53
+ obj2 = Building.find_by(Arel.spatial(query_point).st_distance(Building.arel_table[:coordinates]).lt(2))
54
+ refute_nil(obj2)
55
+ assert_equal(id, obj2.id)
56
+ obj3 = Building.find_by(Arel.spatial(query_point).st_distance(Building.arel_table[:coordinates]).gt(2))
57
+ assert_nil(obj3)
58
+ end
59
+
60
+ def test_query_st_length
61
+ obj = Building.new
62
+ obj.path = factory.line(factory.point(1.0, 2.0), factory.point(3.0, 2.0))
63
+ obj.save!
64
+ id = obj.id
65
+ obj2 = Building.find_by(Building.arel_table[:path].st_length.eq(2))
66
+ refute_nil(obj2)
67
+ assert_equal(id, obj2.id)
68
+ obj3 = Building.find_by(Building.arel_table[:path].st_length.gt(3))
69
+ assert_nil(obj3)
70
+ end
71
+
72
+ def test_query_rgeo_feature_node
73
+ obj = Building.new
74
+ obj.path = factory.line_string([factory.point(1.0, 2.0),
75
+ factory.point(2.0, 2.0), factory.point(3.0, 2.0)])
76
+ obj.save!
77
+ id = obj.id
78
+
79
+ query_point = factory.point(2.0, 2.0)
80
+ obj2 = Building.find_by(Building.arel_table[:path].st_contains(query_point))
81
+ assert_equal(id, obj2.id)
82
+
83
+ query_point = factory.point(0.0, 2.0)
84
+ obj3 = Building.find_by(Building.arel_table[:path].st_contains(query_point))
85
+ assert_nil(obj3)
86
+ end
87
+
88
+ def test_query_rgeo_bbox_node
89
+ obj = Building.new
90
+ obj.coordinates = factory.point(1, 2)
91
+ obj.save!
92
+ id = obj.id
93
+
94
+ pt1 = factory.point(-1, -1)
95
+ pt2 = factory.point(4, 4)
96
+ bbox = RGeo::Cartesian::BoundingBox.create_from_points(pt1, pt2)
97
+ obj2 = Building.find_by(Building.arel_table[:coordinates].st_within(bbox))
98
+ assert_equal(id, obj2.id)
99
+ end
100
+
101
+ def test_ewkt_parser_query
102
+ obj = Building.create!(coordinates: factory.point(1, 2))
103
+ id = obj.id
104
+
105
+ query_point = parser.parse('SRID=3857;POINT(2 3)')
106
+ obj2 = Building.find_by(Arel.spatial(query_point).st_distance(Building.arel_table[:coordinates]).lt(2))
107
+ refute_nil(obj2)
108
+ assert_equal(id, obj2.id)
109
+ obj3 = Building.find_by(Arel.spatial(query_point).st_distance(Building.arel_table[:coordinates]).gt(2))
110
+ assert_nil(obj3)
111
+ end
112
+
113
+ private
114
+
115
+ def parser
116
+ RGeo::WKRep::WKTParser.new(nil, support_ewkt: true)
117
+ end
118
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cases/helper_cockroachdb'
4
+
5
+ class SpatialSetupTest < ActiveRecord::PostgreSQLTestCase
6
+ def test_ignore_tables
7
+ expect_to_ignore = %w[
8
+ geography_columns
9
+ geometry_columns
10
+ layer
11
+ raster_columns
12
+ raster_overviews
13
+ spatial_ref_sys
14
+ topology
15
+ ]
16
+ assert_equal expect_to_ignore, ::ActiveRecord::SchemaDumper.ignore_tables
17
+ end
18
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cases/helper_cockroachdb'
4
+
5
+ class SpatialTypeTest < ActiveRecord::PostgreSQLTestCase
6
+ def test_parse_simple_type
7
+ assert_equal ['geometry', 0, false, false], spatial.parse_sql_type('geometry')
8
+ assert_equal ['geography', 0, false, false], spatial.parse_sql_type('geography')
9
+ end
10
+
11
+ def test_parse_geo_type
12
+ assert_equal ['Point', 0, false, false], spatial.parse_sql_type('geography(Point)')
13
+ assert_equal ['Point', 0, false, true], spatial.parse_sql_type('geography(PointM)')
14
+ assert_equal ['Point', 0, true, false], spatial.parse_sql_type('geography(PointZ)')
15
+ assert_equal ['Point', 0, true, true], spatial.parse_sql_type('geography(PointZM)')
16
+ assert_equal ['Polygon', 0, false, false], spatial.parse_sql_type('geography(Polygon)')
17
+ assert_equal ['Polygon', 0, true, false], spatial.parse_sql_type('geography(PolygonZ)')
18
+ assert_equal ['Polygon', 0, false, true], spatial.parse_sql_type('geography(PolygonM)')
19
+ assert_equal ['Polygon', 0, true, true], spatial.parse_sql_type('geography(PolygonZM)')
20
+ end
21
+
22
+ def test_parse_type_with_srid
23
+ assert_equal ['Point', 4326, false, false], spatial.parse_sql_type('geography(Point,4326)')
24
+ assert_equal ['Polygon', 4327, true, false], spatial.parse_sql_type('geography(PolygonZ,4327)')
25
+ assert_equal ['Point', 4328, false, true], spatial.parse_sql_type('geography(PointM,4328)')
26
+ assert_equal ['Point', 4329, true, true], spatial.parse_sql_type('geography(PointZM,4329)')
27
+ assert_equal ['MultiPolygon', 4326, false, false], spatial.parse_sql_type('geometry(MultiPolygon,4326)')
28
+ end
29
+
30
+ def test_parse_non_geo_types
31
+ assert_equal ['x', 0, false, false], spatial.parse_sql_type('x')
32
+ assert_equal ['foo', 0, false, false], spatial.parse_sql_type('foo')
33
+ assert_equal ['foo(A,1234)', 0, false, false], spatial.parse_sql_type('foo(A,1234)')
34
+ end
35
+
36
+ private
37
+
38
+ def spatial
39
+ ActiveRecord::ConnectionAdapters::CockroachDB::OID::Spatial
40
+ end
41
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/helper_cockroachdb"
4
+ require "models/developer"
5
+ require "models/topic"
6
+
7
+ module CockroachDB
8
+ class PostgresqlTimestampMigrationTest < ActiveRecord::PostgreSQLTestCase
9
+ self.use_transactional_tests = false
10
+
11
+ class PostgresqlTimestampWithZone < ActiveRecord::Base; end
12
+
13
+ def test_adds_column_as_timestamp
14
+ original, $stdout = $stdout, StringIO.new
15
+
16
+ ActiveRecord::Migration.new.add_column :postgresql_timestamp_with_zones, :times, :datetime
17
+
18
+ assert_equal({ "data_type" => "timestamp without time zone" },
19
+ PostgresqlTimestampWithZone.lease_connection.execute("select data_type from information_schema.columns where column_name = 'times'").to_a.first)
20
+ ensure
21
+ ActiveRecord::Migration.new.remove_column :postgresql_timestamp_with_zones, :times, if_exists: true
22
+ $stdout = original
23
+ end
24
+
25
+ def test_adds_column_as_timestamptz_if_datetime_type_changed
26
+ original, $stdout = $stdout, StringIO.new
27
+
28
+ with_cockroachdb_datetime_type(:timestamptz) do
29
+ ActiveRecord::Migration.new.add_column :postgresql_timestamp_with_zones, :times, :datetime
30
+
31
+ assert_equal({ "data_type" => "timestamp with time zone" },
32
+ PostgresqlTimestampWithZone.lease_connection.execute("select data_type from information_schema.columns where column_name = 'times'").to_a.first)
33
+ end
34
+ ensure
35
+ ActiveRecord::Migration.new.remove_column :postgresql_timestamp_with_zones, :times, if_exists: true
36
+ $stdout = original
37
+ end
38
+
39
+ def test_adds_column_as_custom_type
40
+ original, $stdout = $stdout, StringIO.new
41
+
42
+ PostgresqlTimestampWithZone.lease_connection.execute("CREATE TYPE custom_time_format AS ENUM ('past', 'present', 'future');")
43
+
44
+ ActiveRecord::ConnectionAdapters::CockroachDBAdapter::NATIVE_DATABASE_TYPES[:datetimes_as_enum] = { name: "custom_time_format" }
45
+ with_cockroachdb_datetime_type(:datetimes_as_enum) do
46
+ ActiveRecord::Migration.new.add_column :postgresql_timestamp_with_zones, :times, :datetime, precision: nil
47
+
48
+ assert_equal({ "data_type" => "USER-DEFINED", "udt_name" => "custom_time_format" },
49
+ PostgresqlTimestampWithZone.lease_connection.execute("select data_type, udt_name from information_schema.columns where column_name = 'times'").to_a.first)
50
+ end
51
+ ensure
52
+ ActiveRecord::ConnectionAdapters::CockroachDBAdapter::NATIVE_DATABASE_TYPES.delete(:datetimes_as_enum)
53
+ ActiveRecord::Migration.new.remove_column :postgresql_timestamp_with_zones, :times, if_exists: true
54
+ ActiveRecord::Base.lease_connection.execute("DROP TYPE IF EXISTS custom_time_format")
55
+ $stdout = original
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/helper"
4
+ require "support/schema_dumping_helper"
5
+
6
+ module CockroachDB
7
+ if ActiveRecord::Base.lease_connection.supports_virtual_columns?
8
+ class PostgresqlVirtualColumnTest < ActiveRecord::PostgreSQLTestCase
9
+ include SchemaDumpingHelper
10
+
11
+ self.use_transactional_tests = false
12
+
13
+ class VirtualColumn < ActiveRecord::Base
14
+ end
15
+
16
+ def setup
17
+ @connection = ActiveRecord::Base.lease_connection
18
+ @connection.create_table :virtual_columns, force: true do |t|
19
+ t.string :name
20
+ t.virtual :upper_name, type: :string, as: "UPPER(name)", stored: true
21
+ t.virtual :name_length, type: :integer, as: "LENGTH(name)", stored: true
22
+ t.virtual :name_octet_length, type: :integer, as: "OCTET_LENGTH(name)", stored: true
23
+ t.integer :column1
24
+ t.virtual :column2, type: :integer, as: "column1 + 1", stored: true
25
+ end
26
+ VirtualColumn.create(name: "Rails")
27
+ end
28
+
29
+ # TODO: is this test result acceptable?
30
+ def test_schema_dumping
31
+ output = dump_table_schema("virtual_columns")
32
+ assert_match(/t\.virtual\s+"upper_name",\s+type: :string,\s+as: "upper\(name\)", stored: true$/i, output)
33
+ assert_match(/t\.virtual\s+"name_length",\s+type: :bigint,\s+as: "length\(name\)", stored: true$/i, output)
34
+ assert_match(/t\.virtual\s+"name_octet_length",\s+type: :bigint,\s+as: "octet_length\(name\)", stored: true$/i, output)
35
+ assert_match(/t\.virtual\s+"column2",\s+type: :bigint,\s+as: "column1 \+ 1", stored: true$/i, output)
36
+ end
37
+ end
38
+ end
39
+ end