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
@@ -0,0 +1,125 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/helper"
4
+ require "support/schema_dumping_helper"
5
+
6
+ class TableOptionsTest < ActiveRecord::AbstractMysqlTestCase
7
+ include SchemaDumpingHelper
8
+
9
+ def setup
10
+ @connection = ActiveRecord::Base.lease_connection
11
+ end
12
+
13
+ def teardown
14
+ @connection.drop_table "mysql_table_options", if_exists: true
15
+ end
16
+
17
+ test "table options with ENGINE" do
18
+ @connection.create_table "mysql_table_options", force: true, options: "ENGINE=MyISAM"
19
+ output = dump_table_schema("mysql_table_options")
20
+ expected = /create_table "mysql_table_options", charset: "utf8mb4"(?:, collation: "\w+")?, options: "ENGINE=MyISAM", force: :cascade/
21
+ assert_match expected, output
22
+ end
23
+
24
+ test "table options with ROW_FORMAT" do
25
+ @connection.create_table "mysql_table_options", force: true, options: "ROW_FORMAT=REDUNDANT"
26
+ output = dump_table_schema("mysql_table_options")
27
+ expected = /create_table "mysql_table_options", charset: "utf8mb4"(?:, collation: "\w+")?, options: "ENGINE=InnoDB ROW_FORMAT=REDUNDANT", force: :cascade/
28
+ assert_match expected, output
29
+ end
30
+
31
+ test "table options with CHARSET" do
32
+ @connection.create_table "mysql_table_options", force: true, options: "CHARSET=latin1"
33
+ output = dump_table_schema("mysql_table_options")
34
+ expected = /create_table "mysql_table_options", charset: "latin1"(?:, collation: "\w+")?, force: :cascade/
35
+ assert_match expected, output
36
+ end
37
+
38
+ test "table options with COLLATE" do
39
+ @connection.create_table "mysql_table_options", force: true, options: "COLLATE=utf8mb4_bin"
40
+ output = dump_table_schema("mysql_table_options")
41
+ expected = /create_table "mysql_table_options", charset: "utf8mb4", collation: "utf8mb4_bin", force: :cascade/
42
+ assert_match expected, output
43
+ end
44
+
45
+ test "charset and collation options" do
46
+ @connection.create_table "mysql_table_options", force: true, charset: "utf8mb4", collation: "utf8mb4_bin"
47
+ output = dump_table_schema("mysql_table_options")
48
+ expected = /create_table "mysql_table_options", charset: "utf8mb4", collation: "utf8mb4_bin"(:?, options: "ENGINE=InnoDB ROW_FORMAT=DYNAMIC")?, force: :cascade/
49
+ assert_match expected, output
50
+ end
51
+
52
+ test "charset and partitioned table options" do
53
+ @connection.create_table "mysql_table_options", primary_key: ["id", "account_id"], charset: "utf8mb4", collation: "utf8mb4_bin", options: "ENGINE=InnoDB\n/*!50100 PARTITION BY HASH (`account_id`)\nPARTITIONS 128 */", force: :cascade do |t|
54
+ t.bigint "id", null: false, auto_increment: true
55
+ t.bigint "account_id", null: false, unsigned: true
56
+ end
57
+ output = dump_table_schema("mysql_table_options")
58
+ expected = /create_table "mysql_table_options", primary_key: \["id", "account_id"\], charset: "utf8mb4", collation: "utf8mb4_bin", options: "ENGINE=InnoDB\\n(\/\*!50100)? PARTITION BY HASH \(`account_id`\)\\nPARTITIONS 128( \*\/)?", force: :cascade/
59
+ assert_match expected, output
60
+ end
61
+
62
+ test "schema dump works with NO_TABLE_OPTIONS sql mode" do
63
+ skip "As of MySQL 5.7.22, NO_TABLE_OPTIONS is deprecated. It will be removed in a future version of MySQL." if @connection.database_version >= "5.7.22"
64
+
65
+ old_sql_mode = @connection.query_value("SELECT @@SESSION.sql_mode")
66
+ new_sql_mode = old_sql_mode + ",NO_TABLE_OPTIONS"
67
+
68
+ begin
69
+ @connection.execute("SET @@SESSION.sql_mode='#{new_sql_mode}'")
70
+
71
+ @connection.create_table "mysql_table_options", force: true
72
+ output = dump_table_schema("mysql_table_options")
73
+ assert_no_match %r{options:}, output
74
+ ensure
75
+ @connection.execute("SET @@SESSION.sql_mode='#{old_sql_mode}'")
76
+ end
77
+ end
78
+ end
79
+
80
+ class DefaultEngineOptionTest < ActiveRecord::AbstractMysqlTestCase
81
+ include SchemaDumpingHelper
82
+ self.use_transactional_tests = false
83
+
84
+ def setup
85
+ @logger_was = ActiveRecord::Base.logger
86
+ @log = StringIO.new
87
+ @verbose_was = ActiveRecord::Migration.verbose
88
+ ActiveRecord::Base.logger = ActiveSupport::Logger.new(@log)
89
+ ActiveRecord::Migration.verbose = false
90
+ end
91
+
92
+ def teardown
93
+ ActiveRecord::Base.logger = @logger_was
94
+ ActiveRecord::Migration.verbose = @verbose_was
95
+ ActiveRecord::Base.lease_connection.drop_table "mysql_table_options", if_exists: true
96
+ ActiveRecord::Base.connection_pool.schema_migration.delete_all_versions rescue nil
97
+ end
98
+
99
+ test "new migrations do not contain default ENGINE=InnoDB option" do
100
+ ActiveRecord::Base.lease_connection.create_table "mysql_table_options", force: true
101
+
102
+ assert_no_match %r{ENGINE=InnoDB}, @log.string
103
+
104
+ output = dump_table_schema("mysql_table_options")
105
+ expected = /create_table "mysql_table_options", charset: "utf8mb4"(?:, collation: "\w+")?(:?, options: "ENGINE=InnoDB ROW_FORMAT=DYNAMIC")?, force: :cascade/
106
+ assert_match expected, output
107
+ end
108
+
109
+ test "legacy migrations contain default ENGINE=InnoDB option" do
110
+ migration = Class.new(ActiveRecord::Migration[5.1]) do
111
+ def migrate(x)
112
+ create_table "mysql_table_options", force: true
113
+ end
114
+ end.new
115
+
116
+ pool = ActiveRecord::Base.connection_pool
117
+ ActiveRecord::Migrator.new(:up, [migration], pool.schema_migration, pool.internal_metadata).migrate
118
+
119
+ assert_match %r{ENGINE=InnoDB}, @log.string
120
+
121
+ output = dump_table_schema("mysql_table_options")
122
+ expected = /create_table "mysql_table_options", charset: "utf8mb4"(?:, collation: "\w+")?, force: :cascade/
123
+ assert_match expected, output
124
+ end
125
+ end
@@ -0,0 +1,204 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/helper"
4
+ require "support/connection_helper"
5
+
6
+ module ActiveRecord
7
+ class TransactionTest < ActiveRecord::AbstractMysqlTestCase
8
+ self.use_transactional_tests = false
9
+
10
+ class Sample < ActiveRecord::Base
11
+ self.table_name = "samples"
12
+ end
13
+
14
+ setup do
15
+ @abort, Thread.abort_on_exception = Thread.abort_on_exception, false
16
+ Thread.report_on_exception, @original_report_on_exception = false, Thread.report_on_exception
17
+
18
+ connection = ActiveRecord::Base.lease_connection
19
+ connection.clear_cache!
20
+
21
+ connection.transaction do
22
+ connection.drop_table "samples", if_exists: true
23
+ connection.create_table("samples") do |t|
24
+ t.integer "value"
25
+ end
26
+ end
27
+
28
+ Sample.reset_column_information
29
+ end
30
+
31
+ teardown do
32
+ ActiveRecord::Base.lease_connection.drop_table "samples", if_exists: true
33
+
34
+ Thread.abort_on_exception = @abort
35
+ Thread.report_on_exception = @original_report_on_exception
36
+ end
37
+
38
+ test "raises Deadlocked when a deadlock is encountered" do
39
+ connection = Sample.lease_connection
40
+ assert_raises(ActiveRecord::Deadlocked) do
41
+ barrier = Concurrent::CyclicBarrier.new(2)
42
+
43
+ s1 = Sample.create value: 1
44
+ s2 = Sample.create value: 2
45
+
46
+ thread = Thread.new do
47
+ Sample.transaction do
48
+ s1.lock!
49
+ barrier.wait
50
+ s2.update value: 1
51
+ end
52
+ end
53
+
54
+ begin
55
+ Sample.transaction do
56
+ s2.lock!
57
+ barrier.wait
58
+ s1.update value: 2
59
+ end
60
+ ensure
61
+ thread.join
62
+ end
63
+ end
64
+ assert_predicate connection, :active?
65
+ end
66
+
67
+ test "raises LockWaitTimeout when lock wait timeout exceeded" do
68
+ assert_raises(ActiveRecord::LockWaitTimeout) do
69
+ s = Sample.create!(value: 1)
70
+ latch1 = Concurrent::CountDownLatch.new
71
+ latch2 = Concurrent::CountDownLatch.new
72
+
73
+ thread = Thread.new do
74
+ Sample.transaction do
75
+ Sample.lock.find(s.id)
76
+ latch1.count_down
77
+ latch2.wait
78
+ end
79
+ end
80
+
81
+ begin
82
+ Sample.transaction do
83
+ latch1.wait
84
+ Sample.lease_connection.execute("SET innodb_lock_wait_timeout = 1")
85
+ Sample.lock.find(s.id)
86
+ end
87
+ ensure
88
+ Sample.lease_connection.execute("SET innodb_lock_wait_timeout = DEFAULT")
89
+ latch2.count_down
90
+ thread.join
91
+ end
92
+ end
93
+ end
94
+
95
+ test "raises StatementTimeout when statement timeout exceeded" do
96
+ skip unless ActiveRecord::Base.lease_connection.show_variable("max_execution_time")
97
+ error = assert_raises(ActiveRecord::StatementTimeout) do
98
+ s = Sample.create!(value: 1)
99
+ latch1 = Concurrent::CountDownLatch.new
100
+ latch2 = Concurrent::CountDownLatch.new
101
+
102
+ thread = Thread.new do
103
+ Sample.transaction do
104
+ Sample.lock.find(s.id)
105
+ latch1.count_down
106
+ latch2.wait
107
+ end
108
+ end
109
+
110
+ begin
111
+ Sample.transaction do
112
+ latch1.wait
113
+ Sample.lease_connection.execute("SET max_execution_time = 1")
114
+ Sample.lock.find(s.id)
115
+ end
116
+ ensure
117
+ Sample.lease_connection.execute("SET max_execution_time = DEFAULT")
118
+ latch2.count_down
119
+ thread.join
120
+ end
121
+ end
122
+ assert_kind_of ActiveRecord::QueryAborted, error
123
+ end
124
+
125
+ test "raises QueryCanceled when canceling statement due to user request" do
126
+ error = assert_raises(ActiveRecord::QueryCanceled) do
127
+ s = Sample.create!(value: 1)
128
+ latch = Concurrent::CountDownLatch.new
129
+
130
+ thread = Thread.new do
131
+ Sample.transaction do
132
+ Sample.lock.find(s.id)
133
+ latch.count_down
134
+ sleep(0.5)
135
+ conn = Sample.lease_connection
136
+ pid = conn.query_value("SELECT id FROM information_schema.processlist WHERE info LIKE '% FOR UPDATE'")
137
+ conn.execute("KILL QUERY #{pid}")
138
+ end
139
+ end
140
+
141
+ begin
142
+ Sample.transaction do
143
+ latch.wait
144
+ Sample.lock.find(s.id)
145
+ end
146
+ ensure
147
+ thread.join
148
+ end
149
+ end
150
+ assert_kind_of ActiveRecord::QueryAborted, error
151
+ end
152
+
153
+ test "reconnect preserves isolation level" do
154
+ pool = Sample.connection_pool
155
+ @connection = Sample.lease_connection
156
+
157
+ Sample.transaction do
158
+ @connection.materialize_transactions
159
+ # Double check that the INSERT isn't seen with default isolation level
160
+ assert_no_difference -> { Sample.count } do
161
+ Thread.new do
162
+ Sample.create!(value: 1)
163
+ end.join
164
+ end
165
+ end
166
+
167
+ Sample.transaction(isolation: :read_committed) do
168
+ @connection.materialize_transactions
169
+ # Double check that the INSERT is seen with :read_committed
170
+ assert_difference -> { Sample.count }, +1 do
171
+ Thread.new do
172
+ Sample.create!(value: 1)
173
+ end.join
174
+ end
175
+ end
176
+
177
+ first_begin_failed = false
178
+ @connection.singleton_class.define_method(:perform_query) do |raw_connection, sql, *args, **kwargs|
179
+ # Simulates the first BEGIN attempt failing
180
+ if sql.include?("BEGIN") && !first_begin_failed
181
+ first_begin_failed = true
182
+ raise ActiveRecord::ConnectionFailed, "Simulated failure"
183
+ end
184
+ super(raw_connection, sql, *args, **kwargs)
185
+ end
186
+
187
+ Sample.transaction(isolation: :read_committed) do
188
+ @connection.materialize_transactions
189
+ # Indirectly check that the retried transaction is READ COMMITTED
190
+ assert_difference -> { Sample.count }, +1 do
191
+ Thread.new do
192
+ Sample.create!(value: 1)
193
+ end.join
194
+ end
195
+ end
196
+
197
+ assert first_begin_failed
198
+ ensure
199
+ pool.remove(@connection) # We're monkey patching the instance, we shouldn't re-use it
200
+ @connection&.disconnect!
201
+ Sample.release_connection
202
+ end
203
+ end
204
+ end
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/helper"
4
+ require "support/schema_dumping_helper"
5
+
6
+ class UnsignedTypeTest < ActiveRecord::AbstractMysqlTestCase
7
+ include SchemaDumpingHelper
8
+ self.use_transactional_tests = false
9
+
10
+ class UnsignedType < ActiveRecord::Base
11
+ end
12
+
13
+ setup do
14
+ @connection = ActiveRecord::Base.lease_connection
15
+ @connection.create_table("unsigned_types", force: true) do |t|
16
+ t.integer :unsigned_integer, unsigned: true
17
+ t.bigint :unsigned_bigint, unsigned: true
18
+ t.float :unsigned_float, unsigned: true
19
+ t.decimal :unsigned_decimal, unsigned: true, precision: 10, scale: 2
20
+ t.column :unsigned_zerofill, "int unsigned zerofill"
21
+ end
22
+ end
23
+
24
+ teardown do
25
+ @connection.drop_table "unsigned_types", if_exists: true
26
+ end
27
+
28
+ test "unsigned int max value is in range" do
29
+ assert expected = UnsignedType.create(unsigned_integer: 4294967295)
30
+ assert_equal expected, UnsignedType.find_by(unsigned_integer: 4294967295)
31
+ end
32
+
33
+ test "minus value is out of range" do
34
+ assert_raise(ActiveModel::RangeError) do
35
+ UnsignedType.create(unsigned_integer: -10)
36
+ end
37
+ assert_raise(ActiveModel::RangeError) do
38
+ UnsignedType.create(unsigned_bigint: -10)
39
+ end
40
+ assert_raise(ActiveRecord::RangeError) do
41
+ UnsignedType.create(unsigned_float: -10.0)
42
+ end
43
+ assert_raise(ActiveRecord::RangeError) do
44
+ UnsignedType.create(unsigned_decimal: -10.0)
45
+ end
46
+ end
47
+
48
+ test "schema definition can use unsigned as the type" do
49
+ @connection.change_table("unsigned_types") do |t|
50
+ t.unsigned_integer :unsigned_integer_t
51
+ t.unsigned_bigint :unsigned_bigint_t
52
+ end
53
+
54
+ @connection.columns("unsigned_types").select { |c| /^unsigned_/.match?(c.name) }.each do |column|
55
+ assert_predicate column, :unsigned?
56
+ end
57
+ end
58
+
59
+ test "deprecate unsigned_float and unsigned_decimal" do
60
+ @connection.change_table("unsigned_types") do |t|
61
+ assert_deprecated(ActiveRecord.deprecator) do
62
+ t.unsigned_float :unsigned_float_t
63
+ end
64
+ assert_deprecated(ActiveRecord.deprecator) do
65
+ t.unsigned_decimal :unsigned_decimal_t
66
+ end
67
+ end
68
+ end
69
+
70
+ test "schema dump includes unsigned option" do
71
+ schema = dump_table_schema "unsigned_types"
72
+ assert_match %r{t\.integer\s+"unsigned_integer",\s+unsigned: true$}, schema
73
+ assert_match %r{t\.bigint\s+"unsigned_bigint",\s+unsigned: true$}, schema
74
+ assert_match %r{t\.float\s+"unsigned_float",\s+unsigned: true$}, schema
75
+ assert_match %r{t\.decimal\s+"unsigned_decimal",\s+precision: 10,\s+scale: 2,\s+unsigned: true$}, schema
76
+ end
77
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/helper"
4
+ require "support/schema_dumping_helper"
5
+
6
+ if ActiveRecord::Base.lease_connection.supports_virtual_columns?
7
+ class VirtualColumnTest < ActiveRecord::AbstractMysqlTestCase
8
+ include SchemaDumpingHelper
9
+
10
+ self.use_transactional_tests = false
11
+
12
+ class VirtualColumn < ActiveRecord::Base
13
+ end
14
+
15
+ def setup
16
+ @connection = ActiveRecord::Base.lease_connection
17
+ @connection.create_table :virtual_columns, force: true do |t|
18
+ t.string :name
19
+ t.virtual :upper_name, type: :string, as: "UPPER(`name`)"
20
+ t.virtual :name_length, type: :integer, as: "LENGTH(`name`)", stored: true
21
+ t.virtual :name_octet_length, type: :integer, as: "OCTET_LENGTH(`name`)", stored: true
22
+ t.json :profile
23
+ t.virtual :profile_email, type: :string, as: "json_extract(`profile`,_utf8mb4'$.email')", stored: true
24
+ t.datetime :time
25
+ t.virtual :time_mirror, type: :datetime, as: "`time`"
26
+ end
27
+ VirtualColumn.create(name: "Rails")
28
+ end
29
+
30
+ def teardown
31
+ @connection.drop_table :virtual_columns, if_exists: true
32
+ VirtualColumn.reset_column_information
33
+ end
34
+
35
+ def test_virtual_column
36
+ column = VirtualColumn.columns_hash["upper_name"]
37
+ assert_predicate column, :virtual?
38
+ assert_match %r{\bVIRTUAL\b}, column.extra
39
+ assert_equal "RAILS", VirtualColumn.take.upper_name
40
+ end
41
+
42
+ def test_stored_column
43
+ column = VirtualColumn.columns_hash["name_length"]
44
+ assert_predicate column, :virtual?
45
+ assert_match %r{\b(?:STORED|PERSISTENT)\b}, column.extra
46
+ assert_equal 5, VirtualColumn.take.name_length
47
+ end
48
+
49
+ def test_change_table
50
+ @connection.change_table :virtual_columns do |t|
51
+ t.virtual :lower_name, type: :string, as: "LOWER(name)"
52
+ end
53
+ VirtualColumn.reset_column_information
54
+ column = VirtualColumn.columns_hash["lower_name"]
55
+ assert_predicate column, :virtual?
56
+ assert_match %r{\bVIRTUAL\b}, column.extra
57
+ assert_equal "rails", VirtualColumn.take.lower_name
58
+ end
59
+
60
+ def test_schema_dumping
61
+ output = dump_table_schema("virtual_columns")
62
+ assert_match(/t\.virtual\s+"upper_name",\s+type: :string,\s+as: "(?:UPPER|UCASE)\(`name`\)"$/i, output)
63
+ assert_match(/t\.virtual\s+"name_length",\s+type: :integer,\s+as: "(?:octet_length|length)\(`name`\)",\s+stored: true$/i, output)
64
+ assert_match(/t\.virtual\s+"name_octet_length",\s+type: :integer,\s+as: "(?:octet_length|length)\(`name`\)",\s+stored: true$/i, output)
65
+ assert_match(/t\.virtual\s+"profile_email",\s+type: :string,\s+as: "json_extract\(`profile`,\w*?'\$\.email'\)", stored: true$/i, output)
66
+ assert_match(/t\.virtual\s+"time_mirror",\s+type: :datetime,\s+as: "`time`"$/i, output[/^.*time_mirror.*$/])
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,109 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/helper"
4
+ require "active_support/error_reporter/test_helper"
5
+
6
+ class WarningsTest < ActiveRecord::AbstractMysqlTestCase
7
+ def setup
8
+ @connection = ActiveRecord::Base.lease_connection
9
+ @original_db_warnings_action = :ignore
10
+ end
11
+
12
+ test "db_warnings_action :raise on warning" do
13
+ with_db_warnings_action(:raise) do
14
+ error = assert_raises(ActiveRecord::SQLWarning) do
15
+ @connection.execute('SELECT 1 + "foo"')
16
+ end
17
+
18
+ assert_equal @connection.pool, error.connection_pool
19
+ end
20
+ end
21
+
22
+ test "db_warnings_action :ignore on warning" do
23
+ with_db_warnings_action(:ignore) do
24
+ result = @connection.execute('SELECT 1 + "foo"')
25
+ assert_equal [1], result.to_a.first
26
+ end
27
+ end
28
+
29
+ test "db_warnings_action :log on warning" do
30
+ with_db_warnings_action(:log) do
31
+ mysql_warning = "[ActiveRecord::SQLWarning] Truncated incorrect DOUBLE value: 'foo' (1292)"
32
+
33
+ assert_called_with(ActiveRecord::Base.logger, :warn, [mysql_warning]) do
34
+ @connection.execute('SELECT 1 + "foo"')
35
+ end
36
+ end
37
+ end
38
+
39
+ test "db_warnings_action :report on warning" do
40
+ with_db_warnings_action(:report) do
41
+ error_reporter = ActiveSupport::ErrorReporter.new
42
+ subscriber = ActiveSupport::ErrorReporter::TestHelper::ErrorSubscriber.new
43
+
44
+ Rails.define_singleton_method(:error) { error_reporter }
45
+ Rails.error.subscribe(subscriber)
46
+
47
+ @connection.execute('SELECT 1 + "foo"')
48
+
49
+ warning_event, * = subscriber.events.first
50
+
51
+ assert_kind_of ActiveRecord::SQLWarning, warning_event
52
+ assert_equal "Truncated incorrect DOUBLE value: 'foo'", warning_event.message
53
+ end
54
+ end
55
+
56
+ test "db_warnings_action custom proc on warning" do
57
+ warning_message = nil
58
+ warning_level = nil
59
+ warning_action = ->(warning) do
60
+ warning_message = warning.message
61
+ warning_level = warning.level
62
+ end
63
+
64
+ with_db_warnings_action(warning_action) do
65
+ @connection.execute('SELECT 1 + "foo"')
66
+
67
+ assert_equal "Truncated incorrect DOUBLE value: 'foo'", warning_message
68
+ assert_equal "Warning", warning_level
69
+ end
70
+ end
71
+
72
+ test "db_warnings_action allows a list of warnings to ignore" do
73
+ with_db_warnings_action(:raise, [/Truncated incorrect DOUBLE value/]) do
74
+ result = @connection.execute('SELECT 1 + "foo"')
75
+
76
+ assert_equal [1], result.to_a.first
77
+ end
78
+ end
79
+
80
+ test "db_warnings_action allows a list of codes to ignore" do
81
+ with_db_warnings_action(:raise, ["1292"]) do
82
+ result = @connection.execute('SELECT 1 + "foo"')
83
+
84
+ assert_equal [1], result.to_a.first
85
+ end
86
+ end
87
+
88
+ test "db_warnings_action ignores note level warnings" do
89
+ with_db_warnings_action(:raise) do
90
+ result = @connection.execute("DROP TABLE IF EXISTS non_existent_table")
91
+
92
+ assert_equal [], result.to_a
93
+ end
94
+ end
95
+
96
+ test "db_warnings_action handles when warning_count does not match returned warnings" do
97
+ with_db_warnings_action(:raise) do
98
+ # force warnings to 1, but SHOW WARNINGS will return [].
99
+ @connection.raw_connection.stub(:warning_count, 1) do
100
+ error = assert_raises(ActiveRecord::SQLWarning) do
101
+ @connection.execute('SELECT "x"')
102
+ end
103
+
104
+ expected = "Query had warning_count=1 but ‘SHOW WARNINGS’ did not return the warnings. Check MySQL logs or database configuration."
105
+ assert_equal expected, error.message
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/helper"
4
+ require "support/schema_dumping_helper"
5
+
6
+ if ActiveRecord::Base.lease_connection.supports_check_constraints?
7
+ class Mysql2CheckConstraintQuotingTest < ActiveRecord::Mysql2TestCase
8
+ include SchemaDumpingHelper
9
+
10
+ setup do
11
+ @connection = ActiveRecord::Base.lease_connection
12
+ @connection.create_table "trades", force: true do |t|
13
+ t.string :name
14
+ end
15
+ end
16
+
17
+ teardown do
18
+ @connection.drop_table "trades", if_exists: true rescue nil
19
+ end
20
+
21
+ def test_check_constraint_no_duplicate_expression_quoting
22
+ @connection.add_check_constraint :trades, "name != 'forbidden_string'"
23
+
24
+ check_constraints = @connection.check_constraints("trades")
25
+ assert_equal 1, check_constraints.size
26
+
27
+ expression = check_constraints.first.expression
28
+ if ActiveRecord::Base.lease_connection.mariadb?
29
+ assert_equal "`name` <> 'forbidden_string'", expression
30
+ else
31
+ assert_equal "`name` <> _utf8mb4'forbidden_string'", expression
32
+ end
33
+ end
34
+ end
35
+ end