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,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
@@ -0,0 +1,131 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/helper"
4
+ require "support/schema_dumping_helper"
5
+
6
+ module CockroachDB
7
+ class PostgresqlIntervalTest < ActiveRecord::PostgreSQLTestCase
8
+ include SchemaDumpingHelper
9
+
10
+ class IntervalDataType < ActiveRecord::Base
11
+ attribute :legacy_term, :string
12
+ end
13
+
14
+ class DeprecatedIntervalDataType < ActiveRecord::Base; end
15
+
16
+ def setup
17
+ @connection = ActiveRecord::Base.lease_connection
18
+ @connection.transaction do
19
+ @connection.create_table("interval_data_types") do |t|
20
+ t.interval "maximum_term"
21
+ t.interval "minimum_term", precision: 3
22
+ t.interval "default_term", default: "P3Y"
23
+ t.interval "all_terms", array: true
24
+ t.interval "legacy_term"
25
+ end
26
+ end
27
+ @column_max = IntervalDataType.columns_hash["maximum_term"]
28
+ @column_min = IntervalDataType.columns_hash["minimum_term"]
29
+ assert(@column_max.is_a?(ActiveRecord::ConnectionAdapters::PostgreSQLColumn))
30
+ assert(@column_min.is_a?(ActiveRecord::ConnectionAdapters::PostgreSQLColumn))
31
+ assert_nil @column_max.precision
32
+ assert_equal 3, @column_min.precision
33
+ end
34
+
35
+ teardown do
36
+ @connection.execute "DROP TABLE IF EXISTS interval_data_types"
37
+ end
38
+
39
+ IntervalTestCase = Struct.new(:input, :expected)
40
+ def test_postgresql_interval_parser
41
+ tests = [
42
+ IntervalTestCase.new('6 years', 6.year),
43
+ IntervalTestCase.new('6 years 5 mons', 6.year + 5.month),
44
+ IntervalTestCase.new('6 years 5 mons 4 days', 6.year + 5.month + 4.days),
45
+ IntervalTestCase.new('6 years 5 mons 4 days 03:00:00', 6.year + 5.month + 4.days + 3.hours),
46
+ IntervalTestCase.new('6 years 5 mons 4 days 03:02:00', 6.year + 5.month + 4.days + 3.hours + 2.minutes),
47
+ IntervalTestCase.new('6 years 5 mons 4 days 03:02:01',
48
+ 6.year + 5.month + 4.days + 3.hours + 2.minutes + 1.second),
49
+ IntervalTestCase.new('6 years 5 mons 4 days 03:02:01.2',
50
+ 6.year + 5.month + 4.days + 3.hours + 2.minutes + 1.2.seconds)
51
+ ]
52
+ tests.each do |test_case|
53
+ result = ActiveRecord::ConnectionAdapters::CockroachDB::PostgresqlInterval::Parser.parse(test_case.input)
54
+ assert_equal test_case.expected, result
55
+ end
56
+ end
57
+
58
+ def test_postgresql_interval_parser_error
59
+ assert_raises(ActiveRecord::ConnectionAdapters::CockroachDB::PostgresqlInterval::ParseError) do
60
+ test_str = 'This is an invalid interval'
61
+ ActiveRecord::ConnectionAdapters::CockroachDB::PostgresqlInterval::Parser.parse(test_str)
62
+ end
63
+ end
64
+
65
+ def test_column
66
+ assert_equal :interval, @column_max.type
67
+ assert_equal :interval, @column_min.type
68
+ assert_equal "interval", @column_max.sql_type
69
+ assert_equal "interval(3)", @column_min.sql_type
70
+ end
71
+
72
+ def test_simple_interval
73
+ IntervalDataType.create!(
74
+ maximum_term: 6.year + 5.month + 4.days + 3.hours + 2.minutes + 1.seconds
75
+ )
76
+ i = IntervalDataType.last!
77
+ assert_equal "P6Y5M4DT3H2M1S", i.maximum_term.iso8601
78
+ end
79
+
80
+ def test_interval_type
81
+ IntervalDataType.create!(
82
+ maximum_term: 6.year + 5.month + 4.days + 3.hours + 2.minutes + 1.seconds,
83
+ minimum_term: 1.year + 2.month + 3.days + 4.hours + 5.minutes + (6.234567).seconds,
84
+ all_terms: [1.month, 1.year, 1.hour],
85
+ legacy_term: "33 years",
86
+ )
87
+ i = IntervalDataType.last!
88
+
89
+ assert_equal "P6Y5M4DT3H2M1S", i.maximum_term.iso8601
90
+ assert_equal "P1Y2M3DT4H5M6.235S", i.minimum_term.iso8601
91
+ assert_equal "P3Y", i.default_term.iso8601
92
+ assert_equal %w[ P1M P1Y PT1H ], i.all_terms.map(&:iso8601)
93
+
94
+ assert_equal "P33Y", i.legacy_term
95
+ end
96
+
97
+ def test_interval_type_cast_from_invalid_string
98
+ i = IntervalDataType.create!(maximum_term: "1 year 2 minutes")
99
+ i.reload
100
+ assert_nil i.maximum_term
101
+ end
102
+
103
+ def test_interval_type_cast_from_numeric
104
+ i = IntervalDataType.create!(minimum_term: 36000)
105
+ i.reload
106
+ assert_equal "PT10H", i.minimum_term.iso8601
107
+ end
108
+
109
+ def test_interval_type_cast_string_and_numeric_from_user
110
+ i = IntervalDataType.new(maximum_term: "P1YT2M", minimum_term: "PT10H", legacy_term: "P1DT1H")
111
+ assert i.maximum_term.is_a?(ActiveSupport::Duration)
112
+ assert i.legacy_term.is_a?(String)
113
+ assert_equal "P1YT2M", i.maximum_term.iso8601
114
+ assert_equal "PT10H", i.minimum_term.iso8601
115
+ assert_equal "P1DT1H", i.legacy_term
116
+ end
117
+
118
+ def test_average_interval_type
119
+ IntervalDataType.create!([{ maximum_term: 6.years }, { maximum_term: 4.months }])
120
+ value = IntervalDataType.average(:maximum_term)
121
+
122
+ assert_equal 3.years + 2.months, value
123
+ assert_instance_of ActiveSupport::Duration, value
124
+ end
125
+
126
+ def test_schema_dump_with_default_value
127
+ output = dump_table_schema "interval_data_types"
128
+ assert_match %r{t\.interval "default_term", default: "3 years 0 mons 0 days 0 hours 0 minutes 0 seconds"}, output
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cases/helper_cockroachdb'
4
+
5
+ class NestedClassTest < ActiveRecord::PostgreSQLTestCase
6
+ module Foo
7
+ def self.table_name_prefix
8
+ 'foo_'
9
+ end
10
+
11
+ class Bar < ActiveRecord::Base
12
+ end
13
+ end
14
+
15
+ def test_nested_model
16
+ Foo::Bar.lease_connection.create_table(:foo_bars, force: true) do |t|
17
+ t.column 'latlon', :st_point, srid: 3785
18
+ end
19
+ assert_empty Foo::Bar.all
20
+ Foo::Bar.lease_connection.drop_table(:foo_bars)
21
+ end
22
+ end
@@ -0,0 +1,28 @@
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 PostgresqlNumberTest < ActiveRecord::PostgreSQLTestCase
8
+ include SchemaDumpingHelper
9
+
10
+ class PostgresqlNumber < ActiveRecord::Base; end
11
+
12
+ setup do
13
+ @connection = ActiveRecord::Base.lease_connection
14
+ @connection.create_table("postgresql_numbers", force: true) do |t|
15
+ t.decimal 'decimal_default'
16
+ end
17
+ end
18
+
19
+ teardown do
20
+ @connection.drop_table "postgresql_decimals", if_exists: true
21
+ end
22
+
23
+ def test_decimal_values
24
+ record = PostgresqlNumber.new(decimal_default: 111.222)
25
+ assert_equal record.decimal_default, 111.222
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,199 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/helper_cockroachdb"
4
+ require "models/building"
5
+
6
+ class PostGISTest < ActiveRecord::PostgreSQLTestCase
7
+ def setup
8
+ @connection = ActiveRecord::Base.lease_connection
9
+ end
10
+
11
+ def teardown
12
+ spatial_factory_store.default = nil
13
+ spatial_factory_store.clear
14
+ reset_memoized_spatial_factories
15
+ end
16
+
17
+ def test_postgis_available
18
+ assert_equal postgis_version, @connection.postgis_lib_version
19
+ valid_version = ["2.", "3."].any? { |major_ver| @connection.postgis_lib_version.start_with? major_ver }
20
+ assert valid_version
21
+ end
22
+
23
+ def test_arel_visitor
24
+ visitor = Arel::Visitors::CockroachDB.new(@connection)
25
+ node = RGeo::ActiveRecord::SpatialConstantNode.new("POINT (1.0 2.0)")
26
+ collector = Arel::Collectors::PlainString.new
27
+ visitor.accept(node, collector)
28
+ assert_equal "ST_GeomFromText('POINT (1.0 2.0)')", collector.value
29
+ end
30
+
31
+ def test_arel_visitor_will_not_visit_string
32
+ visitor = Arel::Visitors::CockroachDB.new(@connection)
33
+ node = "POINT (1 2)"
34
+ collector = Arel::Collectors::PlainString.new
35
+
36
+ assert_raises(Arel::Visitors::UnsupportedVisitError) do
37
+ visitor.accept(node, collector)
38
+ end
39
+ end
40
+
41
+ def test_set_and_get_point
42
+ obj = klass.new
43
+ assert_nil obj.coordinates
44
+ obj.coordinates = factory.point(1.0, 2.0)
45
+ assert_equal factory.point(1.0, 2.0), obj.coordinates
46
+ assert_equal 3857, obj.coordinates.srid
47
+ end
48
+
49
+ def test_set_and_get_point_from_wkt
50
+ obj = klass.new
51
+ assert_nil obj.coordinates
52
+ obj.coordinates = "POINT(1 2)"
53
+ assert_equal factory.point(1.0, 2.0), obj.coordinates
54
+ assert_equal 3857, obj.coordinates.srid
55
+ end
56
+
57
+ def test_save_and_load_point
58
+ obj = klass.new
59
+ obj.coordinates = factory.point(1.0, 2.0)
60
+ obj.save!
61
+ id = obj.id
62
+ obj2 = klass.find(id)
63
+ assert_equal factory.point(1.0, 2.0), obj2.coordinates
64
+ assert_equal 3857, obj2.coordinates.srid
65
+ end
66
+
67
+ def test_save_and_load_geographic_point
68
+ obj = klass.new
69
+ obj.latlon = geographic_factory.point(1.0, 2.0)
70
+ obj.save!
71
+ id = obj.id
72
+ obj2 = klass.find(id)
73
+ assert_equal geographic_factory.point(1.0, 2.0), obj2.latlon
74
+ assert_equal 4326, obj2.latlon.srid
75
+ end
76
+
77
+ def test_save_and_load_point_from_wkt
78
+ obj = klass.new
79
+ obj.coordinates = "POINT(1 2)"
80
+ obj.save!
81
+ id = obj.id
82
+ obj2 = klass.find(id)
83
+ assert_equal factory.point(1.0, 2.0), obj2.coordinates
84
+ assert_equal 3857, obj2.coordinates.srid
85
+ end
86
+
87
+ def test_set_point_bad_wkt
88
+ obj = klass.create(coordinates: "POINT (x)")
89
+ assert_nil obj.coordinates
90
+ end
91
+
92
+ def test_set_point_wkt_wrong_type
93
+ assert_raises(ActiveRecord::StatementInvalid) do
94
+ klass.create(coordinates: "LINESTRING(1 2, 3 4, 5 6)")
95
+ end
96
+ end
97
+
98
+ def test_custom_factory
99
+ custom_factory = RGeo::Cartesian.preferred_factory(buffer_resolution: 8, srid: 3857)
100
+ spatial_factory_store.register(custom_factory, geo_type: "polygon", srid: 3857)
101
+ object = klass.new
102
+ boundary = custom_factory.point(1, 2).buffer(3)
103
+ object.boundary = boundary
104
+ object.save!
105
+ object.reload
106
+ assert_equal boundary.to_s, object.boundary.to_s
107
+ end
108
+
109
+ def test_spatial_factory_attrs_parsing
110
+ factory = RGeo::Cartesian.preferred_factory(srid: 3857)
111
+ spatial_factory_store.register(factory, { srid: 3857,
112
+ sql_type: "geometry",
113
+ geo_type: "polygon",
114
+ has_z: false, has_m: false })
115
+
116
+ # wrong factory for default
117
+ spatial_factory_store.default = RGeo::Geographic.spherical_factory(srid: 4326)
118
+
119
+ object = klass.new
120
+ object.boundary = "POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))"
121
+ object.save!
122
+ object.reload
123
+ assert_equal(factory, object.boundary.factory)
124
+ end
125
+
126
+ def test_spatial_factory_retrieval
127
+ geo_factory = RGeo::Geographic.spherical_factory(srid: 4326)
128
+ spatial_factory_store.register(geo_factory, geo_type: "point", sql_type: "geography")
129
+
130
+ object = klass.new
131
+ object.latlon = "POINT(-122 47)"
132
+ point = object.latlon
133
+ assert_equal 47, point.latitude
134
+ object.shape = point
135
+
136
+ # test that shape column will not use geographic factory
137
+ object.save!
138
+ object.reload
139
+ refute_equal geo_factory, object.shape.factory
140
+ end
141
+
142
+ def test_point_to_json
143
+ obj = klass.new
144
+ assert_match(/"latlon":null/, obj.to_json)
145
+ obj.latlon = factory.point(1.1, 2.0)
146
+ # NOTE: rgeo opiniated in trimming numbers (e.g 1.0 would be trimmed to 1).
147
+ # We follow this convention here.
148
+ assert_match(/"latlon":"POINT\s\(1.1\s2\)"/, obj.to_json)
149
+ end
150
+
151
+ def test_custom_column
152
+ rec = klass.new
153
+ rec.latlon = "POINT(0 0)"
154
+ rec.save
155
+ refute_nil klass.select("CURRENT_TIMESTAMP as ts").first.ts
156
+ end
157
+
158
+ def test_multi_polygon_column
159
+ rec = klass.new
160
+ wkt = "MULTIPOLYGON (((-73.97210545302842 40.782991711401195, " \
161
+ "-73.97228912063449 40.78274091498208, " \
162
+ "-73.97235226842568 40.78276752827304, " \
163
+ "-73.97216860098405 40.783018324791776, " \
164
+ "-73.97210545302842 40.782991711401195)))"
165
+ rec.m_poly = wkt
166
+ assert rec.save
167
+ rec = klass.find(rec.id) # force reload
168
+ assert RGeo::Feature::MultiPolygon.check_type(rec.m_poly)
169
+ assert_equal wkt, rec.m_poly.to_s
170
+ end
171
+
172
+ def test_spatial_column_matching_enum
173
+ SpatialModel.lease_connection.create_enum(:point_type, ["point", "line_string", "polygon"])
174
+ SpatialModel.lease_connection.create_table(:spatial_models, force: true) do |t|
175
+ t.enum "point_type", enum_type: :point_type
176
+ t.column "latlon", :st_point, srid: 3785, geographic: true
177
+ end
178
+ SpatialModel.reset_column_information
179
+ _id, enum, geo = SpatialModel.columns
180
+ refute_predicate enum, :geographic?
181
+ refute_predicate enum, :spatial?
182
+ assert_predicate geo, :geographic?
183
+ assert_predicate geo, :spatial?
184
+ end
185
+
186
+ private
187
+
188
+ def klass
189
+ Building
190
+ end
191
+
192
+ def reset_memoized_spatial_factories
193
+ # necessary to reset the @spatial_factory variable on spatial
194
+ # OIDs, otherwise the results of early tests will be memoized
195
+ # since the table is not dropped and recreated between test cases.
196
+ klass.lease_connection.send(:reload_type_map)
197
+ klass.reset_column_information
198
+ end
199
+ end