ibm_db 5.6.1 → 5.7.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 (592) hide show
  1. checksums.yaml +4 -4
  2. data/ext/Makefile +13 -9
  3. data/ext/extconf.rb +176 -110
  4. data/ext/ibm_db.c +60 -0
  5. data/ext/ibm_db.o +0 -0
  6. data/ext/ibm_db.so +0 -0
  7. data/ext/mkmf.log +6 -6
  8. data/ext/ruby_ibm_db_cli.c +14 -10
  9. data/ext/ruby_ibm_db_cli.h +4 -0
  10. data/ext/ruby_ibm_db_cli.o +0 -0
  11. data/lib/IBM_DB.rb +2 -2
  12. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +1254 -277
  13. data/test/active_record/connection_adapters/fake_legacy_adapter.rb +17 -0
  14. data/test/active_record/connection_adapters/fake_misleading_legacy_adapter.rb +8 -0
  15. data/test/activejob/destroy_association_async_job_test.rb +62 -0
  16. data/test/activejob/destroy_association_async_test.rb +147 -11
  17. data/test/activejob/job_runtime_test.rb +41 -0
  18. data/test/activejob/unloadable_base_job.rb +3 -0
  19. data/test/cases/active_record_schema_test.rb +196 -0
  20. data/test/cases/active_record_test.rb +21 -0
  21. data/test/cases/adapter_prevent_writes_test.rb +26 -202
  22. data/test/cases/adapter_test.rb +592 -82
  23. data/test/cases/adapters/abstract_mysql_adapter/active_schema_test.rb +210 -0
  24. data/test/cases/adapters/abstract_mysql_adapter/adapter_prevent_writes_test.rb +111 -0
  25. data/test/cases/adapters/abstract_mysql_adapter/auto_increment_test.rb +48 -0
  26. data/test/cases/adapters/abstract_mysql_adapter/bind_parameter_test.rb +91 -0
  27. data/test/cases/adapters/abstract_mysql_adapter/case_sensitivity_test.rb +65 -0
  28. data/test/cases/adapters/abstract_mysql_adapter/charset_collation_test.rb +85 -0
  29. data/test/cases/adapters/abstract_mysql_adapter/connection_test.rb +267 -0
  30. data/test/cases/adapters/abstract_mysql_adapter/count_deleted_rows_with_lock_test.rb +29 -0
  31. data/test/cases/adapters/abstract_mysql_adapter/json_test.rb +24 -0
  32. data/test/cases/adapters/abstract_mysql_adapter/mysql_boolean_test.rb +102 -0
  33. data/test/cases/adapters/abstract_mysql_adapter/mysql_enum_test.rb +47 -0
  34. data/test/cases/adapters/abstract_mysql_adapter/mysql_explain_test.rb +71 -0
  35. data/test/cases/adapters/abstract_mysql_adapter/nested_deadlock_test.rb +191 -0
  36. data/test/cases/adapters/abstract_mysql_adapter/optimizer_hints_test.rb +69 -0
  37. data/test/cases/adapters/abstract_mysql_adapter/quoting_test.rb +49 -0
  38. data/test/cases/adapters/abstract_mysql_adapter/schema_migrations_test.rb +68 -0
  39. data/test/cases/adapters/abstract_mysql_adapter/schema_test.rb +130 -0
  40. data/test/cases/adapters/abstract_mysql_adapter/set_test.rb +32 -0
  41. data/test/cases/adapters/abstract_mysql_adapter/sp_test.rb +39 -0
  42. data/test/cases/adapters/abstract_mysql_adapter/sql_types_test.rb +16 -0
  43. data/test/cases/adapters/abstract_mysql_adapter/table_options_test.rb +125 -0
  44. data/test/cases/adapters/abstract_mysql_adapter/transaction_test.rb +204 -0
  45. data/test/cases/adapters/abstract_mysql_adapter/unsigned_type_test.rb +77 -0
  46. data/test/cases/adapters/abstract_mysql_adapter/virtual_column_test.rb +69 -0
  47. data/test/cases/adapters/abstract_mysql_adapter/warnings_test.rb +109 -0
  48. data/test/cases/adapters/mysql2/check_constraint_quoting_test.rb +35 -0
  49. data/test/cases/adapters/mysql2/dbconsole_test.rb +87 -0
  50. data/test/cases/adapters/mysql2/mysql2_adapter_test.rb +136 -10
  51. data/test/cases/adapters/mysql2/mysql2_rake_test.rb +433 -0
  52. data/test/cases/adapters/postgresql/active_schema_test.rb +8 -4
  53. data/test/cases/adapters/postgresql/array_test.rb +6 -6
  54. data/test/cases/adapters/postgresql/bind_parameter_test.rb +52 -0
  55. data/test/cases/adapters/postgresql/bit_string_test.rb +2 -2
  56. data/test/cases/adapters/postgresql/bytea_test.rb +3 -3
  57. data/test/cases/adapters/postgresql/case_insensitive_test.rb +1 -1
  58. data/test/cases/adapters/postgresql/change_schema_test.rb +32 -1
  59. data/test/cases/adapters/postgresql/cidr_test.rb +17 -0
  60. data/test/cases/adapters/postgresql/citext_test.rb +7 -1
  61. data/test/cases/adapters/postgresql/collation_test.rb +1 -1
  62. data/test/cases/adapters/postgresql/composite_test.rb +1 -1
  63. data/test/cases/adapters/postgresql/connection_test.rb +43 -36
  64. data/test/cases/adapters/postgresql/create_unlogged_tables_test.rb +3 -2
  65. data/test/cases/adapters/postgresql/datatype_test.rb +9 -4
  66. data/test/cases/adapters/postgresql/date_test.rb +2 -2
  67. data/test/cases/adapters/postgresql/dbconsole_test.rb +109 -0
  68. data/test/cases/adapters/postgresql/deferred_constraints_test.rb +55 -0
  69. data/test/cases/adapters/postgresql/domain_test.rb +1 -1
  70. data/test/cases/adapters/postgresql/enum_test.rb +208 -8
  71. data/test/cases/adapters/postgresql/explain_test.rb +25 -6
  72. data/test/cases/adapters/postgresql/extension_migration_test.rb +51 -9
  73. data/test/cases/adapters/postgresql/foreign_table_test.rb +3 -3
  74. data/test/cases/adapters/postgresql/full_text_test.rb +1 -1
  75. data/test/cases/adapters/postgresql/geometric_test.rb +13 -6
  76. data/test/cases/adapters/postgresql/hstore_test.rb +22 -32
  77. data/test/cases/adapters/postgresql/infinity_test.rb +13 -2
  78. data/test/cases/adapters/postgresql/integer_test.rb +1 -1
  79. data/test/cases/adapters/postgresql/interval_test.rb +9 -17
  80. data/test/cases/adapters/postgresql/invertible_migration_test.rb +139 -0
  81. data/test/cases/adapters/postgresql/json_test.rb +5 -0
  82. data/test/cases/adapters/postgresql/ltree_test.rb +1 -1
  83. data/test/cases/adapters/postgresql/money_test.rb +17 -9
  84. data/test/cases/adapters/postgresql/network_test.rb +13 -1
  85. data/test/cases/adapters/postgresql/numbers_test.rb +18 -2
  86. data/test/cases/adapters/postgresql/optimizer_hints_test.rb +9 -9
  87. data/test/cases/adapters/postgresql/partitions_test.rb +5 -2
  88. data/test/cases/adapters/postgresql/postgresql_adapter_prevent_writes_test.rb +7 -110
  89. data/test/cases/adapters/postgresql/postgresql_adapter_test.rb +403 -20
  90. data/test/cases/adapters/postgresql/postgresql_rake_test.rb +637 -0
  91. data/test/cases/adapters/postgresql/prepared_statements_disabled_test.rb +1 -1
  92. data/test/cases/adapters/postgresql/quoting_test.rb +60 -1
  93. data/test/cases/adapters/postgresql/range_test.rb +185 -21
  94. data/test/cases/adapters/postgresql/referential_integrity_test.rb +29 -5
  95. data/test/cases/adapters/postgresql/rename_table_test.rb +35 -8
  96. data/test/cases/adapters/postgresql/schema_authorization_test.rb +2 -2
  97. data/test/cases/adapters/postgresql/schema_test.rb +270 -20
  98. data/test/cases/adapters/postgresql/serial_test.rb +5 -5
  99. data/test/cases/adapters/postgresql/statement_pool_test.rb +6 -2
  100. data/test/cases/adapters/postgresql/timestamp_test.rb +122 -5
  101. data/test/cases/adapters/postgresql/transaction_nested_test.rb +130 -6
  102. data/test/cases/adapters/postgresql/transaction_test.rb +37 -11
  103. data/test/cases/adapters/postgresql/type_lookup_test.rb +1 -1
  104. data/test/cases/adapters/postgresql/uuid_test.rb +77 -9
  105. data/test/cases/adapters/postgresql/virtual_column_test.rb +114 -0
  106. data/test/cases/adapters/postgresql/xml_test.rb +1 -1
  107. data/test/cases/adapters/sqlite3/bind_parameter_test.rb +52 -0
  108. data/test/cases/adapters/sqlite3/collation_test.rb +1 -1
  109. data/test/cases/adapters/sqlite3/copy_table_test.rb +28 -7
  110. data/test/cases/adapters/sqlite3/dbconsole_test.rb +81 -0
  111. data/test/cases/adapters/sqlite3/explain_test.rb +3 -3
  112. data/test/cases/adapters/sqlite3/quoting_test.rb +34 -3
  113. data/test/cases/adapters/sqlite3/sqlite3_adapter_prevent_writes_test.rb +9 -102
  114. data/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +727 -72
  115. data/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb +6 -3
  116. data/test/cases/adapters/sqlite3/sqlite_rake_test.rb +264 -0
  117. data/test/cases/adapters/sqlite3/statement_pool_test.rb +1 -1
  118. data/test/cases/adapters/sqlite3/transaction_test.rb +6 -3
  119. data/test/cases/adapters/sqlite3/virtual_column_test.rb +138 -0
  120. data/test/cases/adapters/sqlite3/virtual_table_test.rb +51 -0
  121. data/test/cases/adapters/trilogy/dbconsole_test.rb +76 -0
  122. data/test/cases/adapters/trilogy/trilogy_adapter_test.rb +473 -0
  123. data/test/cases/adapters/trilogy/trilogy_rake_test.rb +433 -0
  124. data/test/cases/aggregations_test.rb +16 -0
  125. data/test/cases/annotate_test.rb +14 -12
  126. data/test/cases/arel/attributes/attribute_test.rb +86 -47
  127. data/test/cases/arel/collectors/bind_test.rb +1 -1
  128. data/test/cases/arel/collectors/composite_test.rb +11 -1
  129. data/test/cases/arel/collectors/sql_string_test.rb +1 -1
  130. data/test/cases/arel/collectors/substitute_bind_collector_test.rb +1 -1
  131. data/test/cases/arel/delete_manager_test.rb +0 -6
  132. data/test/cases/arel/factory_methods_test.rb +45 -0
  133. data/test/cases/arel/insert_manager_test.rb +1 -7
  134. data/test/cases/arel/nodes/as_test.rb +12 -0
  135. data/test/cases/arel/nodes/ascending_test.rb +1 -1
  136. data/test/cases/arel/nodes/bin_test.rb +1 -1
  137. data/test/cases/arel/nodes/bound_sql_literal_test.rb +31 -0
  138. data/test/cases/arel/nodes/cte_test.rb +46 -0
  139. data/test/cases/arel/nodes/descending_test.rb +1 -1
  140. data/test/cases/arel/nodes/equality_test.rb +3 -3
  141. data/test/cases/arel/nodes/filter_test.rb +37 -0
  142. data/test/cases/arel/nodes/fragments_test.rb +38 -0
  143. data/test/cases/arel/nodes/homogeneous_in_test.rb +52 -0
  144. data/test/cases/arel/nodes/infix_operation_test.rb +1 -1
  145. data/test/cases/arel/nodes/node_test.rb +1 -1
  146. data/test/cases/arel/nodes/or_test.rb +2 -2
  147. data/test/cases/arel/nodes/sql_literal_test.rb +18 -1
  148. data/test/cases/arel/nodes/table_alias_test.rb +12 -0
  149. data/test/cases/arel/nodes/unary_operation_test.rb +1 -1
  150. data/test/cases/arel/nodes/update_statement_test.rb +4 -0
  151. data/test/cases/arel/nodes_test.rb +3 -2
  152. data/test/cases/arel/select_manager_test.rb +12 -12
  153. data/test/cases/arel/support/fake_record.rb +22 -17
  154. data/test/cases/arel/table_test.rb +15 -25
  155. data/test/cases/arel/update_manager_test.rb +51 -6
  156. data/test/cases/arel/visitors/dispatch_contamination_test.rb +1 -1
  157. data/test/cases/arel/visitors/dot_test.rb +177 -2
  158. data/test/cases/arel/visitors/mysql_test.rb +49 -1
  159. data/test/cases/arel/visitors/postgres_test.rb +1 -31
  160. data/test/cases/arel/visitors/sqlite_test.rb +1 -1
  161. data/test/cases/arel/visitors/to_sql_test.rb +330 -20
  162. data/test/cases/assertions/query_assertions_test.rb +136 -0
  163. data/test/cases/associations/belongs_to_associations_test.rb +502 -41
  164. data/test/cases/associations/bidirectional_destroy_dependencies_test.rb +1 -1
  165. data/test/cases/associations/cascaded_eager_loading_test.rb +26 -15
  166. data/test/cases/associations/eager_load_nested_include_test.rb +1 -1
  167. data/test/cases/associations/eager_singularization_test.rb +1 -1
  168. data/test/cases/associations/eager_test.rb +255 -93
  169. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +25 -53
  170. data/test/cases/associations/has_many_associations_test.rb +282 -72
  171. data/test/cases/associations/has_many_through_associations_test.rb +172 -45
  172. data/test/cases/associations/has_many_through_disable_joins_associations_test.rb +197 -0
  173. data/test/cases/associations/has_one_associations_test.rb +160 -29
  174. data/test/cases/associations/has_one_through_associations_test.rb +64 -15
  175. data/test/cases/associations/has_one_through_disable_joins_associations_test.rb +82 -0
  176. data/test/cases/associations/inner_join_association_test.rb +36 -6
  177. data/test/cases/associations/inverse_associations_test.rb +177 -40
  178. data/test/cases/associations/join_model_test.rb +17 -12
  179. data/test/cases/associations/left_outer_join_association_test.rb +14 -3
  180. data/test/cases/associations/nested_error_test.rb +116 -0
  181. data/test/cases/associations/nested_through_associations_test.rb +54 -19
  182. data/test/cases/associations/required_test.rb +1 -1
  183. data/test/cases/associations_test.rb +1278 -21
  184. data/test/cases/asynchronous_queries_test.rb +310 -0
  185. data/test/cases/attribute_methods/read_test.rb +6 -0
  186. data/test/cases/attribute_methods/time_zone_converter_test.rb +21 -0
  187. data/test/cases/attribute_methods_test.rb +565 -46
  188. data/test/cases/attributes_test.rb +42 -1
  189. data/test/cases/autosave_association_test.rb +645 -92
  190. data/test/cases/base_prevent_writes_test.rb +28 -159
  191. data/test/cases/base_test.rb +434 -209
  192. data/test/cases/batches_test.rb +441 -57
  193. data/test/cases/binary_test.rb +31 -0
  194. data/test/cases/bind_parameter_test.rb +107 -16
  195. data/test/cases/cache_key_test.rb +7 -7
  196. data/test/cases/calculations_test.rb +541 -110
  197. data/test/cases/callbacks_test.rb +0 -1
  198. data/test/cases/clone_test.rb +5 -4
  199. data/test/cases/coders/yaml_column_test.rb +97 -2
  200. data/test/cases/collection_cache_key_test.rb +24 -16
  201. data/test/cases/column_alias_test.rb +2 -8
  202. data/test/cases/column_definition_test.rb +12 -3
  203. data/test/cases/comment_test.rb +23 -26
  204. data/test/cases/connection_adapters/adapter_leasing_test.rb +9 -9
  205. data/test/cases/connection_adapters/connection_handler_test.rb +145 -99
  206. data/test/cases/connection_adapters/connection_handlers_multi_db_test.rb +79 -55
  207. data/test/cases/connection_adapters/connection_handlers_multi_pool_config_test.rb +17 -20
  208. data/test/cases/connection_adapters/connection_handlers_sharding_db_test.rb +146 -55
  209. data/test/cases/connection_adapters/connection_swapping_nested_test.rb +136 -23
  210. data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +96 -27
  211. data/test/cases/connection_adapters/mysql_type_lookup_test.rb +5 -5
  212. data/test/cases/connection_adapters/registration_test.rb +98 -0
  213. data/test/cases/connection_adapters/schema_cache_test.rb +288 -135
  214. data/test/cases/connection_adapters/standalone_connection_test.rb +38 -0
  215. data/test/cases/connection_adapters/statement_pool_test.rb +29 -0
  216. data/test/cases/connection_adapters/type_lookup_test.rb +12 -24
  217. data/test/cases/connection_handling_test.rb +210 -0
  218. data/test/cases/connection_management_test.rb +44 -7
  219. data/test/cases/connection_pool_test.rb +466 -99
  220. data/test/cases/core_test.rb +167 -9
  221. data/test/cases/counter_cache_test.rb +129 -2
  222. data/test/cases/custom_locking_test.rb +3 -3
  223. data/test/cases/database_configurations/hash_config_test.rb +149 -13
  224. data/test/cases/database_configurations/resolver_test.rb +14 -10
  225. data/test/cases/database_configurations/url_config_test.rb +53 -0
  226. data/test/cases/database_configurations_test.rb +86 -43
  227. data/test/cases/database_selector_test.rb +30 -8
  228. data/test/cases/database_statements_test.rb +10 -14
  229. data/test/cases/date_time_precision_test.rb +141 -11
  230. data/test/cases/date_time_test.rb +19 -1
  231. data/test/cases/defaults_test.rb +107 -41
  232. data/test/cases/delegated_type_test.rb +69 -9
  233. data/test/cases/dirty_test.rb +82 -25
  234. data/test/cases/disconnected_test.rb +10 -9
  235. data/test/cases/dup_test.rb +26 -6
  236. data/test/cases/encryption/cipher/aes256_gcm_test.rb +50 -0
  237. data/test/cases/encryption/cipher_test.rb +65 -0
  238. data/test/cases/encryption/concurrency_test.rb +27 -0
  239. data/test/cases/encryption/config_test.rb +21 -0
  240. data/test/cases/encryption/configurable_test.rb +93 -0
  241. data/test/cases/encryption/contexts_test.rb +105 -0
  242. data/test/cases/encryption/derived_secret_key_provider_test.rb +31 -0
  243. data/test/cases/encryption/deterministic_key_provider_test.rb +11 -0
  244. data/test/cases/encryption/encryptable_record_api_test.rb +175 -0
  245. data/test/cases/encryption/encryptable_record_message_pack_serialized_test.rb +42 -0
  246. data/test/cases/encryption/encryptable_record_test.rb +470 -0
  247. data/test/cases/encryption/encrypted_fixtures_test.rb +22 -0
  248. data/test/cases/encryption/encrypting_only_encryptor_test.rb +20 -0
  249. data/test/cases/encryption/encryption_schemes_test.rb +240 -0
  250. data/test/cases/encryption/encryptor_test.rb +113 -0
  251. data/test/cases/encryption/envelope_encryption_key_provider_test.rb +49 -0
  252. data/test/cases/encryption/extended_deterministic_queries_test.rb +81 -0
  253. data/test/cases/encryption/helper.rb +152 -0
  254. data/test/cases/encryption/key_generator_test.rb +55 -0
  255. data/test/cases/encryption/key_provider_test.rb +57 -0
  256. data/test/cases/encryption/key_test.rb +17 -0
  257. data/test/cases/encryption/message_pack_message_serializer_test.rb +70 -0
  258. data/test/cases/encryption/message_serializer_test.rb +82 -0
  259. data/test/cases/encryption/message_test.rb +43 -0
  260. data/test/cases/encryption/null_encryptor_test.rb +21 -0
  261. data/test/cases/encryption/properties_test.rb +69 -0
  262. data/test/cases/encryption/read_only_null_encryptor_test.rb +19 -0
  263. data/test/cases/encryption/scheme_test.rb +58 -0
  264. data/test/cases/encryption/unencrypted_attributes_test.rb +27 -0
  265. data/test/cases/encryption/uniqueness_validations_test.rb +65 -0
  266. data/test/cases/enum_test.rb +374 -72
  267. data/test/cases/errors_test.rb +7 -4
  268. data/test/cases/excluding_test.rb +116 -0
  269. data/test/cases/explain_subscriber_test.rb +6 -1
  270. data/test/cases/explain_test.rb +119 -10
  271. data/test/cases/filter_attributes_test.rb +7 -14
  272. data/test/cases/finder_respond_to_test.rb +3 -3
  273. data/test/cases/finder_test.rb +357 -72
  274. data/test/cases/fixture_set/file_test.rb +9 -0
  275. data/test/cases/fixtures_test.rb +426 -190
  276. data/test/cases/helper.rb +66 -192
  277. data/test/cases/hot_compatibility_test.rb +10 -10
  278. data/test/cases/inheritance_test.rb +51 -61
  279. data/test/cases/inherited_test.rb +40 -0
  280. data/test/cases/insert_all_test.rb +419 -9
  281. data/test/cases/instrumentation_test.rb +202 -30
  282. data/test/cases/integration_test.rb +25 -7
  283. data/test/cases/invalid_connection_test.rb +5 -5
  284. data/test/cases/invertible_migration_test.rb +108 -24
  285. data/test/cases/json_attribute_test.rb +1 -0
  286. data/test/cases/json_serialization_test.rb +5 -5
  287. data/test/cases/json_shared_test_cases.rb +5 -9
  288. data/test/cases/locking_test.rb +67 -31
  289. data/test/cases/log_subscriber_test.rb +17 -15
  290. data/test/cases/marshal_serialization_test.rb +78 -5
  291. data/test/cases/message_pack_test.rb +91 -0
  292. data/test/cases/migration/change_schema_test.rb +77 -46
  293. data/test/cases/migration/change_table_test.rb +129 -114
  294. data/test/cases/migration/check_constraint_test.rb +192 -10
  295. data/test/cases/migration/column_attributes_test.rb +4 -9
  296. data/test/cases/migration/column_positioning_test.rb +2 -2
  297. data/test/cases/migration/columns_test.rb +118 -4
  298. data/test/cases/migration/command_recorder_test.rb +181 -14
  299. data/test/cases/migration/compatibility_test.rb +883 -196
  300. data/test/cases/migration/create_join_table_test.rb +8 -1
  301. data/test/cases/migration/exclusion_constraint_test.rb +192 -0
  302. data/test/cases/migration/foreign_key_test.rb +356 -14
  303. data/test/cases/migration/helper.rb +4 -1
  304. data/test/cases/migration/index_test.rb +67 -2
  305. data/test/cases/migration/invalid_options_test.rb +129 -0
  306. data/test/cases/migration/logger_test.rb +7 -4
  307. data/test/cases/migration/pending_migrations_test.rb +103 -60
  308. data/test/cases/migration/references_foreign_key_test.rb +73 -4
  309. data/test/cases/migration/references_index_test.rb +25 -27
  310. data/test/cases/migration/references_statements_test.rb +27 -3
  311. data/test/cases/migration/rename_table_test.rb +39 -54
  312. data/test/cases/migration/schema_definitions_test.rb +109 -0
  313. data/test/cases/migration/unique_constraint_test.rb +248 -0
  314. data/test/cases/migration_test.rb +677 -220
  315. data/test/cases/migrator_test.rb +102 -75
  316. data/test/cases/multi_db_migrator_test.rb +55 -34
  317. data/test/cases/multiparameter_attributes_test.rb +26 -29
  318. data/test/cases/multiple_db_test.rb +42 -19
  319. data/test/cases/nested_attributes_test.rb +124 -6
  320. data/test/cases/nested_attributes_with_callbacks_test.rb +2 -2
  321. data/test/cases/normalized_attribute_test.rb +117 -0
  322. data/test/cases/null_relation_test.rb +35 -2
  323. data/test/cases/persistence/reload_association_cache_test.rb +20 -0
  324. data/test/cases/persistence_test.rb +629 -22
  325. data/test/cases/pooled_connections_test.rb +57 -56
  326. data/test/cases/prepared_statement_status_test.rb +8 -3
  327. data/test/cases/primary_class_test.rb +134 -0
  328. data/test/cases/primary_keys_test.rb +171 -55
  329. data/test/cases/query_cache_test.rb +558 -263
  330. data/test/cases/query_logs_test.rb +293 -0
  331. data/test/cases/quoting_test.rb +39 -72
  332. data/test/cases/readonly_test.rb +50 -12
  333. data/test/cases/reaper_test.rb +22 -6
  334. data/test/cases/reflection_test.rb +207 -9
  335. data/test/cases/relation/and_test.rb +43 -0
  336. data/test/cases/relation/delegation_test.rb +32 -5
  337. data/test/cases/relation/delete_all_test.rb +27 -6
  338. data/test/cases/relation/field_ordered_values_test.rb +128 -0
  339. data/test/cases/relation/load_async_test.rb +650 -0
  340. data/test/cases/relation/merging_test.rb +80 -109
  341. data/test/cases/relation/mutation_test.rb +12 -7
  342. data/test/cases/relation/or_test.rb +11 -8
  343. data/test/cases/relation/order_test.rb +90 -0
  344. data/test/cases/relation/predicate_builder_test.rb +21 -6
  345. data/test/cases/relation/select_test.rb +162 -3
  346. data/test/cases/relation/structural_compatibility_test.rb +38 -0
  347. data/test/cases/relation/update_all_test.rb +81 -27
  348. data/test/cases/relation/where_chain_test.rb +190 -3
  349. data/test/cases/relation/where_clause_test.rb +43 -1
  350. data/test/cases/relation/where_test.rb +95 -7
  351. data/test/cases/relation/with_test.rb +165 -0
  352. data/test/cases/relation_test.rb +42 -37
  353. data/test/cases/relations_test.rb +436 -138
  354. data/test/cases/reload_models_test.rb +18 -14
  355. data/test/cases/reserved_word_test.rb +2 -1
  356. data/test/cases/result_test.rb +14 -22
  357. data/test/cases/sanitize_test.rb +89 -27
  358. data/test/cases/schema_dumper_test.rb +535 -62
  359. data/test/cases/scoping/default_scoping_test.rb +219 -35
  360. data/test/cases/scoping/named_scoping_test.rb +25 -46
  361. data/test/cases/scoping/relation_scoping_test.rb +112 -4
  362. data/test/cases/secure_password_test.rb +108 -0
  363. data/test/cases/secure_token_test.rb +72 -0
  364. data/test/cases/serialization_test.rb +1 -1
  365. data/test/cases/serialized_attribute_test.rb +305 -60
  366. data/test/cases/shard_keys_test.rb +125 -0
  367. data/test/cases/shard_selector_test.rb +45 -0
  368. data/test/cases/signed_id_test.rb +57 -5
  369. data/test/cases/statement_cache_test.rb +31 -30
  370. data/test/cases/statement_invalid_test.rb +8 -4
  371. data/test/cases/store_test.rb +73 -9
  372. data/test/cases/strict_loading_test.rb +327 -13
  373. data/test/cases/table_metadata_test.rb +16 -0
  374. data/test/cases/tasks/database_tasks_test.rb +517 -244
  375. data/test/cases/test_case.rb +254 -60
  376. data/test/cases/test_case_test.rb +69 -0
  377. data/test/cases/test_databases_test.rb +7 -3
  378. data/test/cases/test_fixtures_test.rb +19 -40
  379. data/test/cases/time_precision_test.rb +17 -5
  380. data/test/cases/timestamp_test.rb +124 -16
  381. data/test/cases/token_for_test.rb +165 -0
  382. data/test/cases/touch_later_test.rb +43 -1
  383. data/test/cases/transaction_callbacks_test.rb +325 -8
  384. data/test/cases/transaction_instrumentation_test.rb +453 -0
  385. data/test/cases/transaction_isolation_test.rb +12 -8
  386. data/test/cases/transactions_test.rb +629 -112
  387. data/test/cases/type/date_time_test.rb +7 -1
  388. data/test/cases/type/time_test.rb +9 -0
  389. data/test/cases/type/type_map_test.rb +108 -73
  390. data/test/cases/type/unsigned_integer_test.rb +12 -0
  391. data/test/cases/type_caster/connection_test.rb +19 -0
  392. data/test/cases/type_test.rb +1 -1
  393. data/test/cases/unconnected_test.rb +7 -7
  394. data/test/cases/unsafe_raw_sql_test.rb +39 -8
  395. data/test/cases/validations/absence_validation_test.rb +1 -1
  396. data/test/cases/validations/association_validation_test.rb +25 -3
  397. data/test/cases/validations/numericality_validation_test.rb +3 -9
  398. data/test/cases/validations/presence_validation_test.rb +1 -1
  399. data/test/cases/validations/uniqueness_validation_test.rb +280 -40
  400. data/test/cases/validations_test.rb +2 -2
  401. data/test/cases/view_test.rb +33 -22
  402. data/test/cases/yaml_serialization_test.rb +23 -17
  403. data/test/config.example.yml +58 -56
  404. data/test/config.rb +1 -0
  405. data/test/fixtures/1_need_quoting.yml +2 -0
  406. data/test/fixtures/accounts.yml +5 -0
  407. data/test/fixtures/aircrafts.yml +7 -0
  408. data/test/fixtures/book_identifiers.yml +11 -0
  409. data/test/fixtures/books.yml +5 -4
  410. data/test/fixtures/cake_designers.yml +5 -0
  411. data/test/fixtures/cars.yml +6 -0
  412. data/test/fixtures/chefs.yml +5 -0
  413. data/test/fixtures/clothing_items.yml +23 -0
  414. data/test/fixtures/clubs.yml +1 -1
  415. data/test/fixtures/comments.yml +2 -1
  416. data/test/fixtures/cpk_authors.yml +8 -0
  417. data/test/fixtures/cpk_books.yml +21 -0
  418. data/test/fixtures/cpk_order_agreements.yml +13 -0
  419. data/test/fixtures/cpk_order_tags.yml +15 -0
  420. data/test/fixtures/cpk_orders.yml +11 -0
  421. data/test/fixtures/cpk_posts.yml +12 -0
  422. data/test/fixtures/cpk_reviews.yml +13 -0
  423. data/test/fixtures/cpk_tags.yml +11 -0
  424. data/test/fixtures/drink_designers.yml +5 -0
  425. data/test/fixtures/encrypted_book_that_ignores_cases.yml +4 -0
  426. data/test/fixtures/encrypted_books.yml +4 -0
  427. data/test/fixtures/fk_object_to_point_to.yml +2 -0
  428. data/test/fixtures/memberships.yml +15 -15
  429. data/test/fixtures/paragraphs.yml +5 -0
  430. data/test/fixtures/parrots.yml +4 -0
  431. data/test/fixtures/people.yml +2 -0
  432. data/test/fixtures/pirates.yml +2 -2
  433. data/test/fixtures/primary_key_error/primary_key_error.yml +6 -0
  434. data/test/fixtures/references.yml +3 -3
  435. data/test/fixtures/sharded_blog_posts.yml +14 -0
  436. data/test/fixtures/sharded_blog_posts_tags.yml +27 -0
  437. data/test/fixtures/sharded_blogs.yml +8 -0
  438. data/test/fixtures/sharded_comments.yml +22 -0
  439. data/test/fixtures/sharded_tags.yml +34 -0
  440. data/test/fixtures/sponsors.yml +2 -2
  441. data/test/fixtures/topics.yml +1 -0
  442. data/test/fixtures/treasures.yml +4 -0
  443. data/test/fixtures/virtual_columns.yml +5 -0
  444. data/test/fixtures/warehouse_things.yml +1 -1
  445. data/test/migrations/old_and_new_versions/20210716122844_add_people_description.rb +5 -0
  446. data/test/migrations/old_and_new_versions/20210716123013_add_people_number_of_legs.rb +5 -0
  447. data/test/migrations/old_and_new_versions/230_add_people_hobby.rb +5 -0
  448. data/test/migrations/old_and_new_versions/231_add_people_last_name.rb +5 -0
  449. data/test/migrations/scope/1_unscoped.rb +7 -0
  450. data/test/migrations/scope/2_mysql_only.mysql.rb +7 -0
  451. data/test/models/admin/user.rb +2 -0
  452. data/test/models/admin/user_json.rb +48 -0
  453. data/test/models/attachment.rb +7 -0
  454. data/test/models/author.rb +70 -3
  455. data/test/models/author_encrypted.rb +16 -0
  456. data/test/models/bird.rb +1 -1
  457. data/test/models/book.rb +18 -11
  458. data/test/models/book_destroy_async.rb +1 -1
  459. data/test/models/book_encrypted.rb +106 -0
  460. data/test/models/book_identifier.rb +5 -0
  461. data/test/models/branch.rb +11 -0
  462. data/test/models/bulb.rb +1 -1
  463. data/test/models/car.rb +8 -1
  464. data/test/models/cat.rb +1 -1
  465. data/test/models/category.rb +3 -1
  466. data/test/models/chat_message.rb +8 -0
  467. data/test/models/chef.rb +52 -0
  468. data/test/models/clothing_item.rb +12 -0
  469. data/test/models/club.rb +4 -1
  470. data/test/models/comment.rb +7 -4
  471. data/test/models/comment_overlapping_counter_cache.rb +15 -0
  472. data/test/models/company.rb +16 -2
  473. data/test/models/computer.rb +1 -0
  474. data/test/models/contact.rb +3 -3
  475. data/test/models/contract.rb +5 -1
  476. data/test/models/cpk/author.rb +9 -0
  477. data/test/models/cpk/book.rb +55 -0
  478. data/test/models/cpk/book_destroy_async.rb +9 -0
  479. data/test/models/cpk/car.rb +9 -0
  480. data/test/models/cpk/car_review.rb +9 -0
  481. data/test/models/cpk/chapter.rb +16 -0
  482. data/test/models/cpk/chapter_destroy_async.rb +10 -0
  483. data/test/models/cpk/comment.rb +9 -0
  484. data/test/models/cpk/order.rb +55 -0
  485. data/test/models/cpk/order_agreement.rb +10 -0
  486. data/test/models/cpk/order_tag.rb +10 -0
  487. data/test/models/cpk/post.rb +10 -0
  488. data/test/models/cpk/posts_tag.rb +10 -0
  489. data/test/models/cpk/review.rb +9 -0
  490. data/test/models/cpk/tag.rb +10 -0
  491. data/test/models/cpk.rb +15 -0
  492. data/test/models/customer.rb +3 -1
  493. data/test/models/destroy_async_parent.rb +1 -1
  494. data/test/models/developer.rb +44 -3
  495. data/test/models/discount.rb +4 -0
  496. data/test/models/drink_designer.rb +1 -0
  497. data/test/models/editor.rb +8 -0
  498. data/test/models/editorship.rb +6 -0
  499. data/test/models/entry.rb +5 -0
  500. data/test/models/essay.rb +6 -1
  501. data/test/models/essay_destroy_async.rb +1 -0
  502. data/test/models/eye.rb +87 -21
  503. data/test/models/face.rb +1 -1
  504. data/test/models/friendship.rb +3 -0
  505. data/test/models/hardback.rb +7 -0
  506. data/test/models/hotel.rb +2 -0
  507. data/test/models/human.rb +2 -2
  508. data/test/models/invoice.rb +2 -1
  509. data/test/models/invokes_an_undefined_method.rb +5 -0
  510. data/test/models/line_item.rb +6 -0
  511. data/test/models/member.rb +9 -4
  512. data/test/models/membership.rb +2 -2
  513. data/test/models/message.rb +2 -1
  514. data/test/models/need_quoting.rb +5 -0
  515. data/test/models/paragraph.rb +5 -0
  516. data/test/models/parrot.rb +6 -3
  517. data/test/models/person.rb +7 -4
  518. data/test/models/pirate.rb +4 -1
  519. data/test/models/pk_autopopulated_by_a_trigger_record.rb +5 -0
  520. data/test/models/post.rb +65 -2
  521. data/test/models/post_encrypted.rb +15 -0
  522. data/test/models/post_with_prefetched_pk.rb +15 -0
  523. data/test/models/project.rb +1 -0
  524. data/test/models/publication.rb +16 -0
  525. data/test/models/raises_argument_error.rb +5 -0
  526. data/test/models/raises_no_method_error.rb +5 -0
  527. data/test/models/recipient.rb +5 -0
  528. data/test/models/reference.rb +1 -1
  529. data/test/models/reply.rb +1 -1
  530. data/test/models/room.rb +3 -0
  531. data/test/models/sharded/blog.rb +12 -0
  532. data/test/models/sharded/blog_post.rb +17 -0
  533. data/test/models/sharded/blog_post_destroy_async.rb +14 -0
  534. data/test/models/sharded/blog_post_tag.rb +11 -0
  535. data/test/models/sharded/blog_post_with_revision.rb +11 -0
  536. data/test/models/sharded/comment.rb +12 -0
  537. data/test/models/sharded/comment_destroy_async.rb +12 -0
  538. data/test/models/sharded/tag.rb +11 -0
  539. data/test/models/sharded.rb +8 -0
  540. data/test/models/ship.rb +1 -1
  541. data/test/models/shipping_line.rb +11 -0
  542. data/test/models/subscriber.rb +1 -0
  543. data/test/models/subscription.rb +3 -1
  544. data/test/models/too_long_table_name.rb +5 -0
  545. data/test/models/topic.rb +3 -1
  546. data/test/models/traffic_light.rb +2 -2
  547. data/test/models/traffic_light_encrypted.rb +21 -0
  548. data/test/models/translation.rb +9 -0
  549. data/test/models/treasure.rb +1 -1
  550. data/test/models/tyre.rb +1 -1
  551. data/test/models/user.rb +16 -0
  552. data/test/models/user_with_invalid_relation.rb +28 -0
  553. data/test/models/uuid_comment.rb +5 -0
  554. data/test/models/uuid_entry.rb +5 -0
  555. data/test/models/uuid_message.rb +5 -0
  556. data/test/models/zine.rb +2 -1
  557. data/test/schema/mysql2_specific_schema.rb +26 -12
  558. data/test/schema/postgresql_specific_schema.rb +121 -13
  559. data/test/schema/schema.rb +361 -103
  560. data/test/schema/sqlite_specific_schema.rb +17 -6
  561. data/test/schema/trilogy_specific_schema.rb +96 -0
  562. data/test/support/adapter_helper.rb +104 -0
  563. data/test/support/async_helper.rb +15 -0
  564. data/test/support/config.rb +1 -1
  565. data/test/support/connection.rb +14 -2
  566. data/test/support/ddl_helper.rb +1 -1
  567. data/test/support/fake_adapter.rb +42 -0
  568. data/test/support/load_schema_helper.rb +22 -0
  569. data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_6_1_topic.dump +0 -0
  570. data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_6_1_topic_associations.dump +0 -0
  571. data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_7_1_topic.dump +0 -0
  572. data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_7_1_topic_associations.dump +0 -0
  573. data/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_1_topic.dump +0 -0
  574. data/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_1_topic_associations.dump +0 -0
  575. data/test/support/marshal_compatibility_fixtures/Mysql2/rails_7_1_topic.dump +0 -0
  576. data/test/support/marshal_compatibility_fixtures/Mysql2/rails_7_1_topic_associations.dump +0 -0
  577. data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_1_topic.dump +0 -0
  578. data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_1_topic_associations.dump +0 -0
  579. data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_7_1_topic.dump +0 -0
  580. data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_7_1_topic_associations.dump +0 -0
  581. data/test/support/marshal_compatibility_fixtures/SQLite/rails_6_1_topic.dump +0 -0
  582. data/test/support/marshal_compatibility_fixtures/SQLite/rails_6_1_topic_associations.dump +0 -0
  583. data/test/support/marshal_compatibility_fixtures/SQLite/rails_7_1_topic.dump +0 -0
  584. data/test/support/marshal_compatibility_fixtures/SQLite/rails_7_1_topic_associations.dump +0 -0
  585. data/test/support/marshal_compatibility_fixtures/Trilogy/rails_6_1_topic.dump +0 -0
  586. data/test/support/marshal_compatibility_fixtures/Trilogy/rails_6_1_topic_associations.dump +0 -0
  587. data/test/support/marshal_compatibility_fixtures/Trilogy/rails_7_1_topic.dump +0 -0
  588. data/test/support/marshal_compatibility_fixtures/Trilogy/rails_7_1_topic_associations.dump +0 -0
  589. data/test/support/schema_dumping_helper.rb +15 -9
  590. data/test/support/tools.rb +37 -0
  591. data/test/support/yaml_compatibility_fixtures/rails_4_1_no_symbol.yml +22 -0
  592. metadata +247 -15
@@ -3,7 +3,7 @@
3
3
  require "cases/helper"
4
4
  require "support/schema_dumping_helper"
5
5
 
6
- if ActiveRecord::Base.connection.supports_check_constraints?
6
+ if ActiveRecord::Base.lease_connection.supports_check_constraints?
7
7
  module ActiveRecord
8
8
  class Migration
9
9
  class CheckConstraintTest < ActiveRecord::TestCase
@@ -13,15 +13,31 @@ if ActiveRecord::Base.connection.supports_check_constraints?
13
13
  end
14
14
 
15
15
  setup do
16
- @connection = ActiveRecord::Base.connection
16
+ @connection = ActiveRecord::Base.lease_connection
17
17
  @connection.create_table "trades", force: true do |t|
18
18
  t.integer :price
19
19
  t.integer :quantity
20
20
  end
21
+
22
+ @connection.create_table "purchases", force: true do |t|
23
+ t.integer :price
24
+ t.integer :quantity
25
+ end
26
+
27
+ if current_adapter?(:Mysql2Adapter, :TrilogyAdapter)
28
+ @connection.create_table "constraint_test", force: true do |t|
29
+ t.json :options, default: nil
30
+ end
31
+ end
21
32
  end
22
33
 
23
34
  teardown do
24
35
  @connection.drop_table "trades", if_exists: true rescue nil
36
+ @connection.drop_table "purchases", if_exists: true rescue nil
37
+
38
+ if current_adapter?(:Mysql2Adapter, :TrilogyAdapter)
39
+ @connection.drop_table "constraint_test", if_exists: true rescue nil
40
+ end
25
41
  end
26
42
 
27
43
  def test_check_constraints
@@ -32,11 +48,55 @@ if ActiveRecord::Base.connection.supports_check_constraints?
32
48
  assert_equal "products", constraint.table_name
33
49
  assert_equal "products_price_check", constraint.name
34
50
 
35
- if current_adapter?(:Mysql2Adapter)
51
+ if current_adapter?(:Mysql2Adapter, :TrilogyAdapter)
36
52
  assert_equal "`price` > `discounted_price`", constraint.expression
37
53
  else
38
54
  assert_equal "price > discounted_price", constraint.expression
39
55
  end
56
+
57
+ if current_adapter?(:Mysql2Adapter, :TrilogyAdapter)
58
+ begin
59
+ @connection.add_check_constraint(:constraint_test, <<~SQL,
60
+ json_schema_valid(_utf8mb4'\n {\n "oneOf": [\n {\n "type": "null"\n },\n {\n "type": "array",\n "minItems": 1,\n "items": {\n "type": "integer",\n "minimum": 0\n }\n }\n ]\n }',`options`)
61
+ SQL
62
+ name: "non_empty_test_array")
63
+
64
+ constraint = @connection.check_constraints("constraint_test").find { |c| c.name == "non_empty_test_array" }
65
+ assert_includes constraint.expression, "json_schema_valid"
66
+ assert_equal(%q[json_schema_valid(_utf8mb4' { "oneOf": [ { "type": "null" }, { "type": "array", "minItems": 1, "items": { "type": "integer", "minimum": 0 } } ] }',`options`)], constraint.expression)
67
+ ensure
68
+ @connection.remove_check_constraint(:constraint_test, name: "non_empty_test_array", if_exists: true)
69
+ end
70
+ end
71
+
72
+ if current_adapter?(:PostgreSQLAdapter)
73
+ begin
74
+ # Test that complex expression is correctly parsed from the database
75
+ @connection.add_check_constraint(:trades,
76
+ "CASE WHEN price IS NOT NULL THEN true ELSE false END", name: "price_is_required")
77
+
78
+ constraint = @connection.check_constraints("trades").find { |c| c.name == "price_is_required" }
79
+ assert_includes constraint.expression, "WHEN price IS NOT NULL"
80
+ ensure
81
+ @connection.remove_check_constraint(:trades, name: "price_is_required")
82
+ end
83
+ end
84
+ end
85
+
86
+ if current_adapter?(:PostgreSQLAdapter)
87
+ def test_check_constraints_scoped_to_schemas
88
+ @connection.add_check_constraint :trades, "quantity > 0"
89
+
90
+ assert_no_changes -> { @connection.check_constraints("trades").size } do
91
+ @connection.create_schema "test_schema"
92
+ @connection.create_table "test_schema.trades" do |t|
93
+ t.integer :quantity
94
+ end
95
+ @connection.add_check_constraint "test_schema.trades", "quantity > 0"
96
+ end
97
+ ensure
98
+ @connection.drop_schema "test_schema"
99
+ end
40
100
  end
41
101
 
42
102
  def test_add_check_constraint
@@ -49,13 +109,40 @@ if ActiveRecord::Base.connection.supports_check_constraints?
49
109
  assert_equal "trades", constraint.table_name
50
110
  assert_equal "chk_rails_2189e9f96c", constraint.name
51
111
 
52
- if current_adapter?(:Mysql2Adapter)
112
+ if current_adapter?(:Mysql2Adapter, :TrilogyAdapter)
53
113
  assert_equal "`quantity` > 0", constraint.expression
54
114
  else
55
115
  assert_equal "quantity > 0", constraint.expression
56
116
  end
57
117
  end
58
118
 
119
+ def test_add_check_constraint_with_if_not_exists_options
120
+ @connection.add_check_constraint :trades, "quantity > 0"
121
+
122
+ assert_nothing_raised do
123
+ @connection.add_check_constraint :trades, "quantity > 0", if_not_exists: true
124
+ end
125
+ end
126
+
127
+ if supports_non_unique_constraint_name?
128
+ def test_add_constraint_with_same_name_to_different_table
129
+ @connection.add_check_constraint :trades, "quantity > 0", name: "greater_than_zero"
130
+ @connection.add_check_constraint :purchases, "quantity > 0", name: "greater_than_zero"
131
+
132
+ trades_check_constraints = @connection.check_constraints("trades")
133
+ assert_equal 1, trades_check_constraints.size
134
+ trade_constraint = trades_check_constraints.first
135
+ assert_equal "trades", trade_constraint.table_name
136
+ assert_equal "greater_than_zero", trade_constraint.name
137
+
138
+ purchases_check_constraints = @connection.check_constraints("purchases")
139
+ assert_equal 1, purchases_check_constraints.size
140
+ purchase_constraint = purchases_check_constraints.first
141
+ assert_equal "purchases", purchase_constraint.table_name
142
+ assert_equal "greater_than_zero", purchase_constraint.name
143
+ end
144
+ end
145
+
59
146
  def test_add_check_constraint_with_non_existent_table_raises
60
147
  e = assert_raises(ActiveRecord::StatementInvalid) do
61
148
  @connection.add_check_constraint :refunds, "quantity > 0", name: "quantity_check"
@@ -71,7 +158,7 @@ if ActiveRecord::Base.connection.supports_check_constraints?
71
158
  end
72
159
  end
73
160
 
74
- if ActiveRecord::Base.connection.supports_validate_constraints?
161
+ if ActiveRecord::Base.lease_connection.supports_validate_constraints?
75
162
  def test_not_valid_check_constraint
76
163
  Trade.create(quantity: -1)
77
164
 
@@ -90,11 +177,35 @@ if ActiveRecord::Base.connection.supports_check_constraints?
90
177
  assert_predicate @connection.check_constraints("trades").first, :validated?
91
178
  end
92
179
 
180
+ def test_validated_check_constraint_exists
181
+ @connection.add_check_constraint :trades, "quantity > 0", name: "quantity_check", validate: false
182
+ assert_not @connection.check_constraint_exists?(:trades, name: "quantity_check", validate: true)
183
+
184
+ @connection.validate_check_constraint :trades, name: "quantity_check"
185
+ assert @connection.check_constraint_exists?(:trades, name: "quantity_check", validate: true)
186
+ end
187
+
93
188
  def test_validate_non_existing_check_constraint_raises
94
189
  assert_raises ArgumentError do
95
190
  @connection.validate_check_constraint :trades, name: "quantity_check"
96
191
  end
97
192
  end
193
+
194
+ def test_schema_dumping_with_validate_false
195
+ @connection.add_check_constraint :trades, "quantity > 0", name: "quantity_check", validate: false
196
+
197
+ output = dump_table_schema "trades"
198
+
199
+ assert_match %r{\s+add_check_constraint "trades", "quantity > 0", name: "quantity_check", validate: false$}, output
200
+ end
201
+
202
+ def test_schema_dumping_with_validate_true
203
+ @connection.add_check_constraint :trades, "quantity > 0", name: "quantity_check", validate: true
204
+
205
+ output = dump_table_schema "trades"
206
+
207
+ assert_match %r{\s+t.check_constraint "quantity > 0", name: "quantity_check"$}, output
208
+ end
98
209
  else
99
210
  # Check constraint should still be created, but should not be invalid
100
211
  def test_add_invalid_check_constraint
@@ -108,6 +219,32 @@ if ActiveRecord::Base.connection.supports_check_constraints?
108
219
  end
109
220
  end
110
221
 
222
+ def test_check_constraint_exists
223
+ @connection.add_check_constraint :trades, "quantity > 0", name: "quantity_check"
224
+
225
+ assert @connection.check_constraint_exists?(:trades, name: "quantity_check")
226
+ assert_not @connection.check_constraint_exists?(:non_trades, name: "quantity_check")
227
+ assert_not @connection.check_constraint_exists?(:trades, name: "other_check")
228
+ end
229
+
230
+ def test_check_constraint_exists_ensures_required_options
231
+ @connection.add_check_constraint :trades, "quantity > 0", name: "quantity_check"
232
+ error = assert_raises(ArgumentError) do
233
+ @connection.check_constraint_exists?(:trades, something: true)
234
+ end
235
+ assert_equal "At least one of :name or :expression must be supplied", error.message
236
+ end
237
+
238
+ if supports_sql_standard_drop_constraint?
239
+ def test_remove_constraint
240
+ @connection.add_check_constraint :trades, "quantity > 0", name: "quantity_check"
241
+
242
+ assert_equal 1, @connection.check_constraints("trades").size
243
+ @connection.remove_constraint :trades, "quantity_check"
244
+ assert_equal 0, @connection.check_constraints("trades").size
245
+ end
246
+ end
247
+
111
248
  def test_remove_check_constraint
112
249
  @connection.add_check_constraint :trades, "price > 0", name: "price_check"
113
250
  @connection.add_check_constraint :trades, "quantity > 0", name: "quantity_check"
@@ -120,11 +257,32 @@ if ActiveRecord::Base.connection.supports_check_constraints?
120
257
  assert_equal "trades", constraint.table_name
121
258
  assert_equal "price_check", constraint.name
122
259
 
123
- if current_adapter?(:Mysql2Adapter)
260
+ if current_adapter?(:Mysql2Adapter, :TrilogyAdapter)
124
261
  assert_equal "`price` > 0", constraint.expression
125
262
  else
126
263
  assert_equal "price > 0", constraint.expression
127
264
  end
265
+
266
+ @connection.remove_check_constraint :trades, name: :price_check # name as a symbol
267
+ assert_empty @connection.check_constraints("trades")
268
+ end
269
+
270
+ def test_removing_check_constraint_with_if_exists_option
271
+ @connection.add_check_constraint :trades, "quantity > 0", name: "quantity_check"
272
+
273
+ assert_nothing_raised do
274
+ @connection.remove_check_constraint :trades, name: "quantity_check", if_exists: true
275
+ end
276
+
277
+ error = assert_raises ArgumentError do
278
+ @connection.remove_check_constraint :trades, name: "quantity_check"
279
+ end
280
+
281
+ assert_equal "Table 'trades' has no check constraint for #{{ name: "quantity_check" }}", error.message
282
+
283
+ assert_nothing_raised do
284
+ @connection.remove_check_constraint :trades, name: "quantity_check", if_exists: true
285
+ end
128
286
  end
129
287
 
130
288
  def test_remove_non_existing_check_constraint
@@ -132,23 +290,47 @@ if ActiveRecord::Base.connection.supports_check_constraints?
132
290
  @connection.remove_check_constraint :trades, name: "nonexistent"
133
291
  end
134
292
  end
293
+
294
+ def test_add_constraint_from_change_table_with_options
295
+ @connection.change_table :trades do |t|
296
+ t.check_constraint "price > 0", name: "price_check"
297
+ end
298
+
299
+ constraint = @connection.check_constraints("trades").first
300
+ assert_equal "trades", constraint.table_name
301
+ assert_equal "price_check", constraint.name
302
+ end
303
+
304
+ def test_remove_constraint_from_change_table_with_options
305
+ @connection.add_check_constraint :trades, "price > 0", name: "price_check"
306
+
307
+ @connection.change_table :trades do |t|
308
+ t.remove_check_constraint "price > 0", name: "price_check"
309
+ end
310
+
311
+ assert_equal 0, @connection.check_constraints("trades").size
312
+ end
135
313
  end
136
314
  end
137
315
  end
138
316
  else
139
317
  module ActiveRecord
140
318
  class Migration
141
- class NoForeignKeySupportTest < ActiveRecord::TestCase
319
+ class NoCheckConstraintSupportTest < ActiveRecord::TestCase
142
320
  setup do
143
- @connection = ActiveRecord::Base.connection
321
+ @connection = ActiveRecord::Base.lease_connection
144
322
  end
145
323
 
146
324
  def test_add_check_constraint_should_be_noop
147
- @connection.add_check_constraint :products, "discounted_price > 0", name: "discounted_price_check"
325
+ assert_nothing_raised do
326
+ @connection.add_check_constraint :products, "discounted_price > 0", name: "discounted_price_check"
327
+ end
148
328
  end
149
329
 
150
330
  def test_remove_check_constraint_should_be_noop
151
- @connection.remove_check_constraint :products, name: "price_check"
331
+ assert_nothing_raised do
332
+ @connection.remove_check_constraint :products, name: "price_check"
333
+ end
152
334
  end
153
335
 
154
336
  def test_check_constraints_should_raise_not_implemented
@@ -39,13 +39,13 @@ module ActiveRecord
39
39
 
40
40
  def test_add_column_without_limit
41
41
  # TODO: limit: nil should work with all adapters.
42
- skip "MySQL wrongly enforces a limit of 255" if current_adapter?(:Mysql2Adapter)
42
+ skip "MySQL wrongly enforces a limit of 255" if current_adapter?(:Mysql2Adapter, :TrilogyAdapter)
43
43
  add_column :test_models, :description, :string, limit: nil
44
44
  TestModel.reset_column_information
45
45
  assert_nil TestModel.columns_hash["description"].limit
46
46
  end
47
47
 
48
- if current_adapter?(:Mysql2Adapter, :PostgreSQLAdapter)
48
+ if current_adapter?(:Mysql2Adapter, :TrilogyAdapter, :PostgreSQLAdapter)
49
49
  def test_unabstracted_database_dependent_types
50
50
  add_column :test_models, :intelligence_quotient, :smallint
51
51
  TestModel.reset_column_information
@@ -62,12 +62,7 @@ module ActiveRecord
62
62
 
63
63
  connection.add_column "test_models", "wealth", :decimal, precision: "30", scale: "10"
64
64
 
65
- # Do a manual insertion
66
- if current_adapter?(:OracleAdapter)
67
- connection.execute "insert into test_models (id, wealth) values (people_seq.nextval, 12345678901234567890.0123456789)"
68
- else
69
- connection.execute "insert into test_models (wealth) values (12345678901234567890.0123456789)"
70
- end
65
+ connection.execute "insert into test_models (wealth) values (12345678901234567890.0123456789)"
71
66
 
72
67
  # SELECT
73
68
  row = TestModel.first
@@ -174,7 +169,7 @@ module ActiveRecord
174
169
  end
175
170
  end
176
171
 
177
- if current_adapter?(:Mysql2Adapter, :PostgreSQLAdapter)
172
+ if current_adapter?(:Mysql2Adapter, :TrilogyAdapter, :PostgreSQLAdapter)
178
173
  def test_out_of_range_limit_should_raise
179
174
  assert_raise(ArgumentError) { add_column :test_models, :integer_too_big, :integer, limit: 10 }
180
175
  assert_raise(ArgumentError) { add_column :test_models, :text_too_big, :text, limit: 0xfffffffff }
@@ -11,7 +11,7 @@ module ActiveRecord
11
11
  def setup
12
12
  super
13
13
 
14
- @connection = ActiveRecord::Base.connection
14
+ @connection = ActiveRecord::Base.lease_connection
15
15
 
16
16
  connection.create_table :testings, id: false do |t|
17
17
  t.column :first, :integer
@@ -25,7 +25,7 @@ module ActiveRecord
25
25
  ActiveRecord::Base.primary_key_prefix_type = nil
26
26
  end
27
27
 
28
- if current_adapter?(:Mysql2Adapter)
28
+ if current_adapter?(:Mysql2Adapter, :TrilogyAdapter)
29
29
  def test_column_positioning
30
30
  assert_equal %w(first second third), conn.columns(:testings).map(&:name)
31
31
  end
@@ -64,7 +64,7 @@ module ActiveRecord
64
64
  assert_equal "70000", default_after
65
65
  end
66
66
 
67
- if current_adapter?(:Mysql2Adapter)
67
+ if current_adapter?(:Mysql2Adapter, :TrilogyAdapter)
68
68
  def test_mysql_rename_column_preserves_auto_increment
69
69
  rename_column "test_models", "id", "id_test"
70
70
  assert_predicate connection.columns("test_models").find { |c| c.name == "id_test" }, :auto_increment?
@@ -75,7 +75,7 @@ module ActiveRecord
75
75
  end
76
76
 
77
77
  def test_rename_nonexistent_column
78
- exception = if current_adapter?(:PostgreSQLAdapter, :OracleAdapter)
78
+ exception = if current_adapter?(:PostgreSQLAdapter)
79
79
  ActiveRecord::StatementInvalid
80
80
  else
81
81
  ActiveRecord::ActiveRecordError
@@ -136,7 +136,7 @@ module ActiveRecord
136
136
  def test_remove_column_with_multi_column_index
137
137
  # MariaDB starting with 10.2.8
138
138
  # Dropping a column that is part of a multi-column UNIQUE constraint is not permitted.
139
- skip if current_adapter?(:Mysql2Adapter) && connection.mariadb? && connection.database_version >= "10.2.8"
139
+ skip if current_adapter?(:Mysql2Adapter, :TrilogyAdapter) && connection.mariadb? && connection.database_version >= "10.2.8"
140
140
 
141
141
  add_column "test_models", :hat_size, :integer
142
142
  add_column "test_models", :hat_style, :string, limit: 100
@@ -147,7 +147,7 @@ module ActiveRecord
147
147
 
148
148
  # Every database and/or database adapter has their own behavior
149
149
  # if it drops the multi-column index when any of the indexed columns dropped by remove_column.
150
- if current_adapter?(:PostgreSQLAdapter, :OracleAdapter, :IBM_DBAdapter)
150
+ if current_adapter?(:PostgreSQLAdapter)
151
151
  assert_equal [], connection.indexes("test_models").map(&:name)
152
152
  else
153
153
  assert_equal ["index_test_models_on_hat_style_and_hat_size"], connection.indexes("test_models").map(&:name)
@@ -273,7 +273,21 @@ module ActiveRecord
273
273
  def test_change_column_default_to_null
274
274
  add_column "test_models", "first_name", :string
275
275
  connection.change_column_default "test_models", "first_name", nil
276
+
277
+ assert_nil TestModel.new.first_name
278
+ end
279
+
280
+ def test_change_column_default_to_null_with_not_null
281
+ add_column "test_models", "first_name", :string, null: false
282
+ add_column "test_models", "age", :integer, null: false
283
+
284
+ connection.change_column_default "test_models", "first_name", nil
285
+
276
286
  assert_nil TestModel.new.first_name
287
+
288
+ connection.change_column_default "test_models", "age", nil
289
+
290
+ assert_nil TestModel.new.age
277
291
  end
278
292
 
279
293
  def test_change_column_default_with_from_and_to
@@ -283,6 +297,69 @@ module ActiveRecord
283
297
  assert_equal "Tester", TestModel.new.first_name
284
298
  end
285
299
 
300
+ def test_change_column_default_preserves_existing_column_default_function
301
+ skip unless current_adapter?(:SQLite3Adapter)
302
+
303
+ connection.change_column_default "test_models", "created_at", -> { "CURRENT_TIMESTAMP" }
304
+ TestModel.reset_column_information
305
+ assert_equal "CURRENT_TIMESTAMP", TestModel.columns_hash["created_at"].default_function
306
+
307
+ add_column "test_models", "edited_at", :datetime
308
+ connection.change_column_default "test_models", "edited_at", -> { "CURRENT_TIMESTAMP" }
309
+ TestModel.reset_column_information
310
+ assert_equal "CURRENT_TIMESTAMP", TestModel.columns_hash["created_at"].default_function
311
+ assert_equal "CURRENT_TIMESTAMP", TestModel.columns_hash["edited_at"].default_function
312
+ end
313
+
314
+ def test_change_column_default_supports_default_function_with_concatenation_operator
315
+ skip unless current_adapter?(:SQLite3Adapter)
316
+
317
+ add_column "test_models", "ruby_on_rails", :string
318
+ connection.change_column_default "test_models", "ruby_on_rails", -> { "('Ruby ' || 'on ' || 'Rails')" }
319
+ TestModel.reset_column_information
320
+ assert_equal "'Ruby ' || 'on ' || 'Rails'", TestModel.columns_hash["ruby_on_rails"].default_function
321
+ end
322
+
323
+ def test_change_column_null_false
324
+ add_column "test_models", "first_name", :string
325
+ connection.change_column_null "test_models", "first_name", false
326
+
327
+ assert_raise(ActiveRecord::NotNullViolation) do
328
+ TestModel.create!(first_name: nil)
329
+ end
330
+ end
331
+
332
+ def test_change_column_null_true
333
+ add_column "test_models", "first_name", :string
334
+ connection.change_column_null "test_models", "first_name", true
335
+
336
+ assert_difference("TestModel.count" => 1) do
337
+ TestModel.create!(first_name: nil)
338
+ end
339
+ end
340
+
341
+ def test_change_column_null_with_non_boolean_arguments_raises
342
+ add_column "test_models", "first_name", :string
343
+ e = assert_raise(ArgumentError) do
344
+ connection.change_column_null "test_models", "first_name", from: true, to: false
345
+ end
346
+ assert_equal "change_column_null expects a boolean value (true for NULL, false for NOT NULL). Got: #{{ from: true, to: false }}", e.message
347
+ end
348
+
349
+ def test_change_column_null_does_not_change_default_functions
350
+ skip unless current_adapter?(:Mysql2Adapter, :TrilogyAdapter) && supports_default_expression?
351
+
352
+ function = connection.mariadb? ? "current_timestamp(6)" : "(now())"
353
+
354
+ connection.change_column_default "test_models", "created_at", -> { function }
355
+ TestModel.reset_column_information
356
+ assert_equal function, TestModel.columns_hash["created_at"].default_function
357
+
358
+ connection.change_column_null "test_models", "created_at", true
359
+ TestModel.reset_column_information
360
+ assert_equal function, TestModel.columns_hash["created_at"].default_function
361
+ end
362
+
286
363
  def test_remove_column_no_second_parameter_raises_exception
287
364
  assert_raise(ArgumentError) { connection.remove_column("funny") }
288
365
  end
@@ -321,6 +398,43 @@ module ActiveRecord
321
398
  ensure
322
399
  connection.drop_table :my_table, if_exists: true
323
400
  end
401
+
402
+ def test_remove_columns_single_statement
403
+ connection.create_table "my_table" do |t|
404
+ t.integer "col_one"
405
+ t.integer "col_two"
406
+ end
407
+
408
+ # SQLite3's ALTER TABLE statement has several limitations. To manage
409
+ # this, the adapter creates a temporary table, copies the data, drops
410
+ # the old table, creates the new table, then copies the data back.
411
+ expected_query_count = current_adapter?(:SQLite3Adapter) ? 14 : 1
412
+ assert_queries_count(expected_query_count) do
413
+ connection.remove_columns("my_table", "col_one", "col_two")
414
+ end
415
+
416
+ columns = connection.columns("my_table").map(&:name)
417
+ assert_equal ["id"], columns
418
+ ensure
419
+ connection.drop_table :my_table, if_exists: true
420
+ end
421
+
422
+ def test_add_timestamps_single_statement
423
+ connection.create_table "my_table"
424
+
425
+ # SQLite3's ALTER TABLE statement has several limitations. To manage
426
+ # this, the adapter creates a temporary table, copies the data, drops
427
+ # the old table, creates the new table, then copies the data back.
428
+ expected_query_count = current_adapter?(:SQLite3Adapter) ? 14 : 1
429
+ assert_queries_count(expected_query_count) do
430
+ connection.add_timestamps("my_table")
431
+ end
432
+
433
+ columns = connection.columns("my_table").map(&:name)
434
+ assert_equal ["id", "created_at", "updated_at"], columns
435
+ ensure
436
+ connection.drop_table :my_table, if_exists: true
437
+ end
324
438
  end
325
439
  end
326
440
  end