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.
Files changed (239) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +7 -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 +42 -25
  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,124 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/helper"
4
+
5
+ module ActiveRecord
6
+ module CockroachDB
7
+ class Migration
8
+ class ReferencesForeignKeyTest < ActiveRecord::TestCase
9
+ # These tests are identical to the ones found in Rails, save for the fact
10
+ # that transactions are turned off for test runs. It is necessary to disable
11
+ # transactional tests in order to assert on schema changes due to how
12
+ # CockroachDB handles transactions.
13
+ self.use_transactional_tests = false
14
+
15
+ setup do
16
+ @connection = ActiveRecord::Base.lease_connection
17
+ @connection.create_table(:testing_parents, force: true)
18
+ end
19
+
20
+ teardown do
21
+ @connection.drop_table "testings", if_exists: true
22
+ @connection.drop_table "testing_parents", if_exists: true
23
+ end
24
+
25
+ test "foreign keys can be created while changing the table" do
26
+ @connection.create_table :testings
27
+ @connection.change_table :testings do |t|
28
+ t.references :testing_parent, foreign_key: true
29
+ end
30
+
31
+ fk = @connection.foreign_keys("testings").first
32
+ assert_equal "testings", fk.from_table
33
+ assert_equal "testing_parents", fk.to_table
34
+ end
35
+
36
+ test "foreign keys accept options when changing the table" do
37
+ @connection.change_table :testing_parents do |t|
38
+ t.references :other, index: { unique: true }
39
+ end
40
+ @connection.create_table :testings
41
+ @connection.change_table :testings do |t|
42
+ t.references :testing_parent, foreign_key: { primary_key: :other_id }
43
+ end
44
+
45
+ fk = @connection.foreign_keys("testings").find { |k| k.to_table == "testing_parents" }
46
+ assert_equal "other_id", fk.primary_key
47
+ end
48
+
49
+ test "foreign key column can be removed" do
50
+ @connection.create_table :testings do |t|
51
+ t.references :testing_parent, index: true, foreign_key: true
52
+ end
53
+
54
+ assert_difference "@connection.foreign_keys('testings').size", -1 do
55
+ @connection.remove_reference :testings, :testing_parent, foreign_key: true
56
+ end
57
+ end
58
+
59
+ test "removing column removes foreign key" do
60
+ @connection.create_table :testings do |t|
61
+ t.references :testing_parent, index: true, foreign_key: true
62
+ end
63
+
64
+ assert_difference "@connection.foreign_keys('testings').size", -1 do
65
+ @connection.remove_column :testings, :testing_parent_id
66
+ end
67
+ end
68
+
69
+ test "foreign key methods respect pluralize_table_names" do
70
+ begin
71
+ original_pluralize_table_names = ActiveRecord::Base.pluralize_table_names
72
+ ActiveRecord::Base.pluralize_table_names = false
73
+ @connection.create_table :testing
74
+ @connection.change_table :testing_parents do |t|
75
+ t.references :testing, foreign_key: true
76
+ end
77
+
78
+ fk = @connection.foreign_keys("testing_parents").first
79
+ assert_equal "testing_parents", fk.from_table
80
+ assert_equal "testing", fk.to_table
81
+
82
+ assert_difference "@connection.foreign_keys('testing_parents').size", -1 do
83
+ @connection.remove_reference :testing_parents, :testing, foreign_key: true
84
+ end
85
+ ensure
86
+ ActiveRecord::Base.pluralize_table_names = original_pluralize_table_names
87
+ @connection.drop_table "testing", if_exists: true
88
+ end
89
+ end
90
+
91
+ test "multiple foreign keys can be removed to the selected one" do
92
+ @connection.create_table :testings do |t|
93
+ t.references :parent1, foreign_key: { to_table: :testing_parents }
94
+ t.references :parent2, foreign_key: { to_table: :testing_parents }
95
+ end
96
+
97
+ assert_difference "@connection.foreign_keys('testings').size", -1 do
98
+ @connection.remove_reference :testings, :parent1, foreign_key: { to_table: :testing_parents }
99
+ end
100
+
101
+ fks = @connection.foreign_keys("testings").sort_by(&:column)
102
+
103
+ fk_definitions = fks.map { |fk| [fk.from_table, fk.to_table, fk.column] }
104
+ assert_equal([["testings", "testing_parents", "parent2_id"]], fk_definitions)
105
+ end
106
+
107
+ test "multiple foreign keys can be added to the same table" do
108
+ @connection.create_table :testings do |t|
109
+ t.references :parent1, foreign_key: { to_table: :testing_parents }
110
+ t.references :parent2, foreign_key: { to_table: :testing_parents }
111
+ t.references :self_join, foreign_key: { to_table: :testings }
112
+ end
113
+
114
+ fks = @connection.foreign_keys("testings").sort_by(&:column)
115
+
116
+ fk_definitions = fks.map { |fk| [fk.from_table, fk.to_table, fk.column] }
117
+ assert_equal([["testings", "testing_parents", "parent1_id"],
118
+ ["testings", "testing_parents", "parent2_id"],
119
+ ["testings", "testings", "self_join_id"]], fk_definitions)
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,120 @@
1
+ require "cases/helper_cockroachdb"
2
+ require "models/person"
3
+ require "support/copy_cat"
4
+
5
+ class Reminder < ActiveRecord::Base; end unless Object.const_defined?(:Reminder)
6
+ class Thing < ActiveRecord::Base; end unless Object.const_defined?(:Thing)
7
+ module CockroachDB
8
+ class MigrationTest < ActiveRecord::TestCase
9
+ self.use_transactional_tests = false
10
+
11
+ fixtures :people
12
+
13
+ CopyCat.copy_methods(self, ::MigrationTest, :setup)
14
+
15
+ teardown do
16
+ ActiveRecord::Base.table_name_prefix = ""
17
+ ActiveRecord::Base.table_name_suffix = ""
18
+
19
+ @schema_migration.create_table
20
+ @schema_migration.delete_all_versions
21
+
22
+ %w(things awesome_things prefix_things_suffix p_awesome_things_s).each do |table|
23
+ Thing.lease_connection.drop_table(table, if_exists: true)
24
+ end
25
+ Thing.reset_column_information
26
+
27
+ %w(reminders people_reminders prefix_reminders_suffix).each do |table|
28
+ Reminder.lease_connection.drop_table(table, if_exists: true)
29
+ end
30
+ Reminder.reset_table_name
31
+ Reminder.reset_column_information
32
+
33
+ %w(last_name key bio age height wealth birthday favorite_day
34
+ moment_of_truth male administrator funny).each do |column|
35
+ Person.lease_connection.remove_column("people", column, if_exists: true)
36
+ end
37
+ Person.lease_connection.remove_column("people", "first_name", if_exists: true)
38
+ Person.lease_connection.remove_column("people", "middle_name", if_exists: true)
39
+ Person.lease_connection.add_column("people", "first_name", :string)
40
+ Person.reset_column_information
41
+
42
+ ActiveRecord::Migration.verbose = @verbose_was
43
+ end
44
+
45
+ def test_remove_column_with_if_not_exists_not_set
46
+ migration_a = Class.new(ActiveRecord::Migration::Current) {
47
+ def version; 100 end
48
+ def migrate(x)
49
+ add_column "people", "last_name", :string
50
+ end
51
+ }.new
52
+
53
+ migration_b = Class.new(ActiveRecord::Migration::Current) {
54
+ def version; 101 end
55
+ def migrate(x)
56
+ remove_column "people", "last_name"
57
+ end
58
+ }.new
59
+
60
+ migration_c = Class.new(ActiveRecord::Migration::Current) {
61
+ def version; 102 end
62
+ def migrate(x)
63
+ remove_column "people", "last_name"
64
+ end
65
+ }.new
66
+
67
+ ActiveRecord::Migrator.new(:up, [migration_a], @schema_migration, @internal_metadata, 100).migrate
68
+ assert_column Person, :last_name, "migration_a should have added the last_name column on people"
69
+
70
+ ActiveRecord::Migrator.new(:up, [migration_b], @schema_migration, @internal_metadata, 101).migrate
71
+ assert_no_column Person, :last_name, "migration_b should have dropped the last_name column on people"
72
+ migrator = ActiveRecord::Migrator.new(:up, [migration_c], @schema_migration, @internal_metadata, 102)
73
+
74
+ error = assert_raises do
75
+ migrator.migrate
76
+ end
77
+
78
+ assert_match(/column \"last_name\" does not exist/, error.message)
79
+ ensure
80
+ Person.reset_column_information
81
+ end
82
+ end
83
+
84
+ class BulkAlterTableMigrationsTest < ActiveRecord::TestCase
85
+ def setup
86
+ @connection = Person.lease_connection
87
+ @connection.create_table(:delete_me, force: true) { |t| }
88
+ Person.reset_column_information
89
+ Person.reset_sequence_name
90
+ end
91
+
92
+ teardown do
93
+ Person.lease_connection.drop_table(:delete_me, if_exists: true)
94
+ end
95
+
96
+ # Change expected query count from PostgreSQLAdapter to CockroachDBAdapter.
97
+ CopyCat.copy_methods(self, ::BulkAlterTableMigrationsTest,
98
+ :test_adding_indexes,
99
+ :test_removing_index,
100
+ :test_adding_multiple_columns,
101
+ :test_changing_index
102
+ ) do
103
+ def on_str(node)
104
+ return unless node in [:str, "PostgreSQLAdapter"]
105
+
106
+ replace(node.loc.expression, '"CockroachDBAdapter"')
107
+ end
108
+ end
109
+
110
+ private
111
+
112
+ CopyCat.copy_methods(self, ::BulkAlterTableMigrationsTest,
113
+ :with_bulk_change_table,
114
+ :column,
115
+ :columns,
116
+ :index,
117
+ :indexes
118
+ )
119
+ end
120
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/helper"
4
+ require "models/topic"
5
+
6
+ module CockroachDB
7
+ class PersistenceTest < ActiveRecord::TestCase
8
+ fixtures :topics
9
+
10
+ self.use_transactional_tests = false
11
+
12
+ # This test is identical to the one found in Rails, except we need to run
13
+ # it with transactions turned off in order to properly assert on the newly
14
+ # added column.
15
+ def test_reset_column_information_resets_children
16
+ child_class = Class.new(Topic)
17
+ child_class.new # force schema to load
18
+
19
+ ActiveRecord::Base.lease_connection.add_column(:topics, :foo, :string)
20
+ Topic.reset_column_information
21
+
22
+ # this should redefine attribute methods
23
+ child_class.new
24
+
25
+ assert child_class.instance_methods.include?(:foo)
26
+ assert child_class.instance_methods.include?(:foo_changed?)
27
+ assert_equal "bar", child_class.new(foo: :bar).foo
28
+ ensure
29
+ ActiveRecord::Base.lease_connection.remove_column(:topics, :foo)
30
+ Topic.reset_column_information
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,134 @@
1
+ require "cases/helper_cockroachdb"
2
+
3
+ # Load dependencies from ActiveRecord test suite
4
+ require "support/schema_dumping_helper"
5
+ require "models/topic"
6
+ require "models/mixed_case_monkey"
7
+
8
+ module CockroachDB
9
+ class PrimaryKeysTest < ActiveRecord::TestCase
10
+ fixtures :mixed_case_monkeys, :topics
11
+
12
+ # This replaces the same test that's been excluded from PrimaryKeysTest. We
13
+ # run it here without an assertion on column.default_function because it
14
+ # will always be unique_rowid() in CockroachDB.
15
+ # See test/excludes/PrimaryKeysTest.rb
16
+ def test_serial_with_quoted_sequence_name
17
+ column = MixedCaseMonkey.columns_hash[MixedCaseMonkey.primary_key]
18
+ assert_predicate column, :serial?
19
+ end
20
+
21
+ # This replaces the same test that's been excluded from PrimaryKeysTest. We
22
+ # run it here without an assertion on column.default_function because it
23
+ # will always be unique_rowid() in CockroachDB.
24
+ # See test/excludes/PrimaryKeysTest.rb
25
+ def test_serial_with_unquoted_sequence_name
26
+ column = Topic.columns_hash[Topic.primary_key]
27
+ assert_predicate column, :serial?
28
+ end
29
+ end
30
+
31
+ class PrimaryKeyIntegerTest < ActiveRecord::TestCase
32
+ include SchemaDumpingHelper
33
+
34
+ self.use_transactional_tests = false
35
+
36
+ class Widget < ActiveRecord::Base
37
+ end
38
+
39
+ setup do
40
+ @connection = ActiveRecord::Base.lease_connection
41
+ @pk_type = :serial
42
+ end
43
+
44
+ teardown do
45
+ @connection.drop_table :widgets, if_exists: true
46
+ end
47
+
48
+ # This replaces the same test that's been excluded from
49
+ # PrimaryKeyIntegerTest. In PostgreSQL, serial columns are backed by integer
50
+ # columns. They're also backed by integer columns in CockroachDB, but
51
+ # integer columns are the same size as PostgreSQL's bigints. Therefore, we
52
+ # change the final assertion to verify the serial column is a bigint.
53
+ # See test/excludes/PrimaryKeyIntegerTest.rb
54
+ test "primary key column type with serial/integer" do
55
+ @connection.create_table(:widgets, id: @pk_type, force: true)
56
+ column = @connection.columns(:widgets).find { |c| c.name == "id" }
57
+ assert_equal :integer, column.type
58
+ assert_predicate column, :bigint?
59
+ end
60
+
61
+ # This replaces the same test that's been excluded from
62
+ # PrimaryKeyIntegerTest. Although the widgets table is created with a serial
63
+ # primary key, that info will not be included in the schema dump.
64
+ # CockroachDB serial and bigserial columns are really bigserial columns, and
65
+ # ActiveRecord defaults to bigserial primary keys. Therefore, nothing about
66
+ # the id primary key will be in the widgets schema dump.
67
+ # See test/excludes/PrimaryKeyIntegerTest.rb
68
+ test "schema dump primary key with serial/integer" do
69
+ @connection.create_table(:widgets, id: @pk_type, force: true)
70
+ schema = dump_table_schema "widgets"
71
+ assert_match %r{create_table "widgets", }, schema
72
+ end
73
+ end
74
+
75
+ class PrimaryKeyIntegerNilDefaultTest < ActiveRecord::TestCase
76
+ include SchemaDumpingHelper
77
+
78
+ self.use_transactional_tests = false
79
+
80
+ def setup
81
+ @connection = ActiveRecord::Base.lease_connection
82
+ end
83
+
84
+ def teardown
85
+ @connection.drop_table :int_defaults, if_exists: true
86
+ end
87
+
88
+ # This replaces the same test that's been excluded from
89
+ # PrimaryKeyIntegerNilDefaultTest. int_defaults is created with an integer
90
+ # primary key, and integer columns are bigints in CockroachDB. Therefore,
91
+ # the schema dump will include the primary key as :bigint.
92
+ # See test/excludes/PrimaryKeyIntegerNilDefaultTest.rb
93
+ def test_schema_dump_primary_key_integer_with_default_nil
94
+ skip if current_adapter?(:SQLite3Adapter)
95
+ @connection.create_table(:int_defaults, id: :integer, default: nil, force: true)
96
+ schema = dump_table_schema "int_defaults"
97
+ assert_match %r{create_table "int_defaults", id: :bigint, default: nil}, schema
98
+ end
99
+ end
100
+
101
+ class PrimaryKeyHiddenColumnTest < ActiveRecord::TestCase
102
+ class Rocket < ActiveRecord::Base
103
+ end
104
+
105
+ def setup
106
+ connection = ActiveRecord::Base.lease_connection
107
+ connection.execute <<-SQL
108
+ CREATE TABLE rockets(
109
+ id SERIAL PRIMARY KEY USING HASH WITH (bucket_count=4)
110
+ )
111
+ SQL
112
+ end
113
+
114
+ def teardown
115
+ ActiveRecord::Base.connection.drop_table :rockets
116
+ end
117
+
118
+ def test_to_key_with_hidden_primary_key_part
119
+ rocket = Rocket.new
120
+ assert_nil rocket.to_key
121
+ rocket.save
122
+ assert_equal rocket.to_key, [rocket.id]
123
+ end
124
+
125
+ def test_read_attribute_with_hidden_primary_key_part
126
+ rocket = Rocket.create!
127
+ id = assert_not_deprecated(ActiveRecord.deprecator) do
128
+ rocket.read_attribute(:id)
129
+ end
130
+
131
+ assert_equal rocket.id, id
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/helper_cockroachdb"
4
+ require "models/post"
5
+ require "models/comment"
6
+
7
+ module CockroachDB
8
+ class AostTest < ActiveRecord::TestCase
9
+ def test_simple_aost
10
+ time = 2.days.ago
11
+ re_time = Regexp.quote(time.iso8601)
12
+ assert_match(/from "posts" as of system time '#{re_time}'/i, Post.aost(time).to_sql)
13
+ assert_match(/from "posts" as of system time '#{re_time}'/i, Post.where(name: "foo").aost(time).to_sql)
14
+ end
15
+
16
+ def test_reset_aost
17
+ time = 1.second.from_now
18
+ assert_match(/from "posts"\z/i, Post.aost(time).aost(nil).to_sql)
19
+ end
20
+
21
+ def test_aost_with_join
22
+ time = Time.now
23
+ assert_match(
24
+ /FROM "posts" INNER JOIN "comments" ON "comments"."post_id" = "posts"."id" AS OF SYSTEM TIME '#{Regexp.quote time.iso8601}'/,
25
+ Post.joins(:comments).aost(time).to_sql
26
+ )
27
+ end
28
+
29
+ def test_aost_with_subquery
30
+ time = 4.seconds.ago
31
+ assert_match(/from \(.*?\) subquery as of system time '#{Regexp.quote time.iso8601}'/i, Post.from(Post.where(name: "foo")).aost(time).to_sql)
32
+ end
33
+
34
+ def test_only_time_input
35
+ time = 1.second.ago
36
+ expected = "SELECT \"posts\".* FROM \"posts\" AS OF SYSTEM TIME '#{time.iso8601}'"
37
+ assert_equal expected, Post.aost(time).to_sql
38
+ assert_raises(ArgumentError) { Post.aost("no time") }
39
+ assert_raises(ArgumentError) { Post.aost(true) }
40
+ end
41
+ end
42
+
43
+ class AostNoTransactionTest < ActiveRecord::TestCase
44
+ # AOST per query is not compatible with transactions.
45
+ self.use_transactional_tests = false
46
+
47
+ def test_aost_with_multiple_queries
48
+ time = 1.second.ago
49
+ queries = capture_sql {
50
+ Post.aost(time).limit(2).find_each(batch_size: 1).to_a
51
+ }
52
+ queries.each do
53
+ assert_match %r(FROM "posts" AS OF SYSTEM TIME '#{Regexp.quote time.iso8601}'), _1
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,26 @@
1
+ # This test has been copied to fix a bug in the test setup. It can be removed
2
+ # once the bugfix has been released in Rails - see rails/rails#38978.
3
+ # See test/excludes/OrTest.rb
4
+
5
+ require "cases/helper_cockroachdb"
6
+
7
+ # Load dependencies from ActiveRecord test suite
8
+ require "cases/helper"
9
+ require "models/post"
10
+ require "models/author"
11
+ require "models/categorization"
12
+
13
+ module ActiveRecord
14
+ module CockroachDB
15
+ class OrTest < ActiveRecord::TestCase
16
+ fixtures :posts
17
+ fixtures :authors, :author_addresses
18
+
19
+ def test_or_when_grouping
20
+ groups = Post.where("id < 10").group("body")
21
+ expected = groups.having("COUNT(*) > 1 OR body like 'Such%'").count
22
+ assert_equal expected, groups.having("COUNT(*) > 1").or(groups.having("body like 'Such%'")).count
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,124 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/helper_cockroachdb"
4
+ require "models/post"
5
+
6
+ module CockroachDB
7
+ class TableHintsTest < ActiveRecord::TestCase
8
+ fixtures :posts
9
+
10
+ def test_add_hint
11
+ force_index = ->(q) { q.force_index("index_posts_on_author_id") }
12
+ index_hint = ->(q) { q.index_hint("NO_FULL_SCAN") }
13
+
14
+ assert_queries_match(/"posts"@\{FORCE_INDEX=index_posts_on_author_id\}/) do
15
+ Post.then(&force_index).take
16
+ end
17
+
18
+ assert_queries_match(/"posts"@\{NO_FULL_SCAN\}/) do
19
+ Post.then(&index_hint).take
20
+ end
21
+
22
+ [force_index, index_hint].permutation do |procs|
23
+ assert_queries_match(/"posts"@\{NO_FULL_SCAN,FORCE_INDEX=index_posts_on_author_id\}/) do
24
+ Post.then(&procs.reduce(:<<)).take
25
+ end
26
+ end
27
+ end
28
+
29
+ def test_choose_index_order
30
+ idx = "index_posts_on_author_id"
31
+ assert_queries_match(/"posts"@\{FORCE_INDEX=#{idx},ASC\}/) do
32
+ Post.force_index(idx, direction: "ASC").take
33
+ end
34
+ assert_queries_match(/"posts"@\{FORCE_INDEX=#{idx},DESC\}/) do
35
+ Post.force_index(idx, direction: "DESC").take
36
+ end
37
+ assert_queries_match(/"posts"@\{NO_FULL_SCAN,FORCE_INDEX=#{idx},DESC\}/) do
38
+ Post.force_index(idx, direction: "DESC").index_hint("NO_FULL_SCAN").take
39
+ end
40
+ end
41
+
42
+ def test_use_other_table
43
+ force_index = ->(q) { q.force_index("index_subscribers_on_nick") }
44
+ index_hint = ->(q) { q.index_hint("NO_FULL_SCAN") }
45
+ post_from = Post.select(:id).from("subscribers")
46
+
47
+ assert_queries_match(/subscribers@\{FORCE_INDEX=index_subscribers_on_nick\}/) do
48
+ post_from.then(&force_index).take
49
+ end
50
+
51
+ assert_queries_match(/subscribers@\{NO_FULL_SCAN\}/) do
52
+ post_from.then(&index_hint).take
53
+ end
54
+
55
+ [force_index, index_hint].permutation do |procs|
56
+ assert_queries_match(/subscribers@\{NO_FULL_SCAN,FORCE_INDEX=index_subscribers_on_nick\}/) do
57
+ post_from.then(&procs.reduce(:<<)).take
58
+ end
59
+ end
60
+ end
61
+
62
+ def test_from_with_space
63
+ ["foo\t", "foo "].each do
64
+ assert_match(/FROM foo@\{H\}/, Post.from(_1).index_hint("H").to_sql)
65
+ assert_match(
66
+ /FROM foo@\{H,FORCE_INDEX=i\}/,
67
+ Post.from(_1).index_hint("H").force_index("i").to_sql
68
+ )
69
+ end
70
+ end
71
+
72
+ def test_reset_with_from
73
+ force_index = ->(q) { q.force_index("type") }
74
+ index_hint = ->(q) { q.index_hint("NO_FULL_SCAN") }
75
+
76
+ [force_index, index_hint].permutation do
77
+ assert_match(
78
+ /FROM age\z/,
79
+ Post.then(&_1).then(&_2).from("age").to_sql
80
+ )
81
+ end
82
+ [force_index, index_hint].each do
83
+ assert_match(/FROM age\z/, Post.then(&_1).from("age").to_sql)
84
+ end
85
+
86
+ end
87
+
88
+ def test_ignore_from_multiple_tables
89
+ tables = "ta, tb"
90
+ from = ->(q) { q.from(tables) }
91
+ force_index = ->(q) { q.force_index("type") }
92
+ index_hint = ->(q) { q.index_hint("NO_FULL_SCAN") }
93
+
94
+ (
95
+ [from, force_index, index_hint].permutation +
96
+ [from, force_index].permutation +
97
+ [from, index_hint].permutation
98
+ ).each do |procs|
99
+ assert_match(
100
+ /FROM #{tables}\z/,
101
+ Post.then(&procs.reduce(:<<)).to_sql
102
+ )
103
+ end
104
+ end
105
+
106
+ def test_ignore_from_subquery
107
+ subquery = Post.where("created_at < ?", 1.year.ago)
108
+ from = ->(q) { q.from(subquery) }
109
+ force_index = ->(q) { q.force_index("safeword") }
110
+ index_hint = ->(q) { q.index_hint("NO_FULL_SCAN") }
111
+
112
+ (
113
+ [from, force_index, index_hint].permutation +
114
+ [from, force_index].permutation +
115
+ [from, index_hint].permutation
116
+ ).each do |procs|
117
+ refute_match(
118
+ /safeword|NO_FULL_SCAN|@/,
119
+ Post.then(&procs.reduce(:<<)).to_sql
120
+ )
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,26 @@
1
+ require "cases/helper_cockroachdb"
2
+
3
+ require "cases/helper"
4
+ require "models/post"
5
+ require "models/comment"
6
+ require "models/author"
7
+ require "models/rating"
8
+ require "models/categorization"
9
+
10
+ module ActiveRecord
11
+ module CockroachDB
12
+ class RelationTest < ActiveRecord::TestCase
13
+ fixtures :posts
14
+
15
+ def test_relation_with_annotation_includes_comment_in_to_sql
16
+ post_with_annotation = Post.where(id: 1).annotate("foo")
17
+ assert_match %r{= '1' /\* foo \*/}, post_with_annotation.to_sql
18
+ end
19
+
20
+ def test_relation_with_annotation_filters_sql_comment_delimiters
21
+ post_with_annotation = Post.where(id: 1).annotate("**//foo//**")
22
+ assert_includes post_with_annotation.to_sql, "= '1' /* ** //foo// ** */"
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/helper"
4
+ require "models/post"
5
+ require "models/comment"
6
+
7
+ module CockroachDB
8
+ class RelationTest < ActiveRecord::TestCase
9
+ fixtures :posts, :comments
10
+
11
+ def test_finding_with_subquery_with_eager_loading_in_from
12
+ relation = Comment.includes(:post).where("posts.type": "Post").order(:id)
13
+ assert_equal relation.to_a, Comment.select("*").from(relation).order(:id).to_a
14
+ assert_equal relation.to_a, Comment.select("subquery.*").from(relation).order(:id).to_a
15
+ assert_equal relation.to_a, Comment.select("a.*").from(relation, :a).order(:id).to_a
16
+ end
17
+
18
+ def test_finding_with_arel_sql_order
19
+ query = Tag.order(Arel.sql("field(id, ?)", [1, 3, 2])).to_sql
20
+ assert_match(/field\(id, '1', '3', '2'\)/, query)
21
+
22
+ query = Tag.order(Arel.sql("field(id, ?)", [])).to_sql
23
+ assert_match(/field\(id, NULL\)/, query)
24
+
25
+ query = Tag.order(Arel.sql("field(id, ?)", nil)).to_sql
26
+ assert_match(/field\(id, NULL\)/, query)
27
+ end
28
+ end
29
+ end