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,191 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/helper"
4
+ require "support/connection_helper"
5
+
6
+ module ActiveRecord
7
+ class NestedDeadlockTest < 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.create_table("samples", force: true) do |t|
22
+ t.integer "value"
23
+ end
24
+
25
+ Sample.reset_column_information
26
+ end
27
+
28
+ teardown do
29
+ ActiveRecord::Base.connection_handler.clear_active_connections!(:all)
30
+ ActiveRecord::Base.lease_connection.drop_table "samples", if_exists: true
31
+
32
+ Thread.abort_on_exception = @abort
33
+ Thread.report_on_exception = @original_report_on_exception
34
+ end
35
+
36
+ test "deadlock correctly raises Deadlocked inside nested SavepointTransaction" do
37
+ connection = Sample.lease_connection
38
+ assert_raises(ActiveRecord::Deadlocked) do
39
+ barrier = Concurrent::CyclicBarrier.new(2)
40
+
41
+ s1 = Sample.create value: 1
42
+ s2 = Sample.create value: 2
43
+
44
+ begin
45
+ thread = Thread.new do
46
+ Sample.transaction(requires_new: false) do
47
+ make_parent_transaction_dirty
48
+ Sample.transaction(requires_new: true) do
49
+ assert_current_transaction_is_savepoint_transaction
50
+ s1.lock!
51
+ barrier.wait
52
+ s2.update value: 1
53
+ end
54
+ end
55
+ end
56
+
57
+ begin
58
+ Sample.transaction(requires_new: false) do
59
+ make_parent_transaction_dirty
60
+ Sample.transaction(requires_new: true) do
61
+ assert_current_transaction_is_savepoint_transaction
62
+ s2.lock!
63
+ barrier.wait
64
+ s1.update value: 2
65
+ end
66
+ end
67
+ ensure
68
+ thread.join
69
+ end
70
+ rescue ActiveRecord::StatementInvalid => e
71
+ if /SAVEPOINT active_record_. does not exist/ =~ e.to_s
72
+ flunk "ROLLBACK TO SAVEPOINT query issued for savepoint that no longer exists due to deadlock: #{e}"
73
+ else
74
+ raise e
75
+ end
76
+ end
77
+ end
78
+ assert_predicate connection, :active?
79
+ end
80
+
81
+ test "rollback exception is swallowed after a rollback" do
82
+ barrier = Concurrent::CyclicBarrier.new(2)
83
+ deadlocks = 0
84
+
85
+ s1 = Sample.create value: 1
86
+ s2 = Sample.create value: 2
87
+
88
+ thread = Thread.new do
89
+ Sample.transaction(requires_new: false) do
90
+ make_parent_transaction_dirty
91
+ Sample.transaction(requires_new: true) do
92
+ assert_current_transaction_is_savepoint_transaction
93
+ s1.lock!
94
+ barrier.wait
95
+ s2.update value: 4
96
+
97
+ rescue ActiveRecord::Deadlocked
98
+ deadlocks += 1
99
+
100
+ # This rollback is actually wrong as mysql automatically rollbacks the transaction
101
+ # which means we have nothing to rollback on the db side
102
+ # but we expect the framework to handle our mistake gracefully
103
+ raise ActiveRecord::Rollback
104
+ end
105
+
106
+ s2.update value: 10
107
+ end
108
+ end
109
+
110
+ begin
111
+ Sample.transaction(requires_new: false) do
112
+ make_parent_transaction_dirty
113
+ Sample.transaction(requires_new: true) do
114
+ assert_current_transaction_is_savepoint_transaction
115
+ s2.lock!
116
+ barrier.wait
117
+ s1.update value: 3
118
+ rescue ActiveRecord::Deadlocked
119
+ deadlocks += 1
120
+ raise ActiveRecord::Rollback
121
+ end
122
+ s1.update value: 10
123
+ end
124
+ ensure
125
+ thread.join
126
+ end
127
+
128
+ assert_equal 1, deadlocks, "deadlock is required for the test setup"
129
+ assert_equal [10, 10], Sample.pluck(:value)
130
+ end
131
+
132
+ test "deadlock inside nested SavepointTransaction is recoverable" do
133
+ barrier = Concurrent::CyclicBarrier.new(2)
134
+ deadlocks = 0
135
+
136
+ s1 = Sample.create value: 1
137
+ s2 = Sample.create value: 2
138
+
139
+ thread = Thread.new do
140
+ Sample.transaction(requires_new: false) do
141
+ make_parent_transaction_dirty
142
+ begin
143
+ Sample.transaction(requires_new: true) do
144
+ assert_current_transaction_is_savepoint_transaction
145
+ s1.lock!
146
+ barrier.wait
147
+ s2.update value: 4
148
+ end
149
+ rescue ActiveRecord::Deadlocked
150
+ deadlocks += 1
151
+ end
152
+ s2.update value: 10
153
+ end
154
+ end
155
+
156
+ begin
157
+ Sample.transaction(requires_new: false) do
158
+ make_parent_transaction_dirty
159
+ begin
160
+ Sample.transaction(requires_new: true) do
161
+ assert_current_transaction_is_savepoint_transaction
162
+ s2.lock!
163
+ barrier.wait
164
+ s1.update value: 3
165
+ end
166
+ rescue ActiveRecord::Deadlocked
167
+ deadlocks += 1
168
+ end
169
+ s1.update value: 10
170
+ end
171
+ ensure
172
+ thread.join
173
+ end
174
+ assert_equal 1, deadlocks
175
+ assert_equal [10, 10], Sample.pluck(:value)
176
+ end
177
+
178
+ private
179
+ # This should cause the next nested transaction to be a savepoint transaction.
180
+ def make_parent_transaction_dirty
181
+ Sample.take
182
+ end
183
+
184
+ def assert_current_transaction_is_savepoint_transaction
185
+ current_transaction = Sample.lease_connection.current_transaction
186
+ unless current_transaction.is_a?(ActiveRecord::ConnectionAdapters::SavepointTransaction)
187
+ flunk("current transaction is not a savepoint transaction")
188
+ end
189
+ end
190
+ end
191
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/helper"
4
+ require "models/post"
5
+
6
+ class OptimizerHintsTest < ActiveRecord::AbstractMysqlTestCase
7
+ if supports_optimizer_hints?
8
+ fixtures :posts
9
+
10
+ def test_optimizer_hints
11
+ assert_queries_match(%r{\ASELECT /\*\+ NO_RANGE_OPTIMIZATION\(posts index_posts_on_author_id\) \*/}) do
12
+ posts = Post.optimizer_hints("NO_RANGE_OPTIMIZATION(posts index_posts_on_author_id)")
13
+ posts = posts.select(:id).where(author_id: [0, 1])
14
+ assert_includes posts.explain.inspect, "index_posts_on_author_id"
15
+ end
16
+ end
17
+
18
+ def test_optimizer_hints_with_count_subquery
19
+ assert_queries_match(%r{\ASELECT /\*\+ NO_RANGE_OPTIMIZATION\(posts index_posts_on_author_id\) \*/}) do
20
+ posts = Post.optimizer_hints("NO_RANGE_OPTIMIZATION(posts index_posts_on_author_id)")
21
+ posts = posts.select(:id).where(author_id: [0, 1]).limit(5)
22
+ assert_equal 5, posts.count
23
+ end
24
+ end
25
+
26
+ def test_optimizer_hints_is_sanitized
27
+ assert_queries_match(%r{\ASELECT /\*\+ NO_RANGE_OPTIMIZATION\(posts index_posts_on_author_id\) \*/}) do
28
+ posts = Post.optimizer_hints("/*+ NO_RANGE_OPTIMIZATION(posts index_posts_on_author_id) */")
29
+ posts = posts.select(:id).where(author_id: [0, 1])
30
+ assert_includes posts.explain.inspect, "index_posts_on_author_id"
31
+ end
32
+
33
+ assert_queries_match(%r{\ASELECT /\*\+ \*\* // `posts`\.\*, // \*\* \*/}) do
34
+ posts = Post.optimizer_hints("**// `posts`.*, //**")
35
+ posts = posts.select(:id).where(author_id: [0, 1])
36
+ assert_equal({ "id" => 1 }, posts.first.as_json)
37
+ end
38
+ end
39
+
40
+ def test_optimizer_hints_with_unscope
41
+ assert_queries_match(%r{\ASELECT `posts`\.`id`}) do
42
+ posts = Post.optimizer_hints("/*+ NO_RANGE_OPTIMIZATION(posts index_posts_on_author_id) */")
43
+ posts = posts.select(:id).where(author_id: [0, 1])
44
+ posts.unscope(:optimizer_hints).load
45
+ end
46
+ end
47
+
48
+ def test_optimizer_hints_with_or
49
+ assert_queries_match(%r{\ASELECT /\*\+ NO_RANGE_OPTIMIZATION\(posts index_posts_on_author_id\) \*/}) do
50
+ Post.optimizer_hints("NO_RANGE_OPTIMIZATION(posts index_posts_on_author_id)")
51
+ .or(Post.all).load
52
+ end
53
+
54
+ queries = capture_sql do
55
+ Post.optimizer_hints("NO_RANGE_OPTIMIZATION(posts index_posts_on_author_id)")
56
+ .or(Post.optimizer_hints("NO_ICP(posts)")).load
57
+ end
58
+ assert_equal 1, queries.length
59
+ assert_includes queries.first, "NO_RANGE_OPTIMIZATION(posts index_posts_on_author_id)"
60
+ assert_not_includes queries.first, "NO_ICP(posts)"
61
+
62
+ queries = capture_sql do
63
+ Post.all.or(Post.optimizer_hints("NO_ICP(posts)")).load
64
+ end
65
+ assert_equal 1, queries.length
66
+ assert_not_includes queries.first, "NO_ICP(posts)"
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/helper"
4
+
5
+ class QuotingTest < ActiveRecord::AbstractMysqlTestCase
6
+ def setup
7
+ super
8
+ @conn = ActiveRecord::Base.lease_connection
9
+ end
10
+
11
+ def test_cast_bound_integer
12
+ assert_equal "42", @conn.cast_bound_value(42)
13
+ end
14
+
15
+ def test_cast_bound_big_decimal
16
+ assert_equal "4.2", @conn.cast_bound_value(BigDecimal("4.2"))
17
+ end
18
+
19
+ def test_cast_bound_rational
20
+ assert_equal "0.75", @conn.cast_bound_value(Rational(3, 4))
21
+ end
22
+
23
+ def test_cast_bound_true
24
+ assert_equal "1", @conn.cast_bound_value(true)
25
+ end
26
+
27
+ def test_cast_bound_false
28
+ assert_equal "0", @conn.cast_bound_value(false)
29
+ end
30
+
31
+ def test_quote_string
32
+ assert_equal "\\'", @conn.quote_string("'")
33
+ end
34
+
35
+ def test_quote_column_name
36
+ [@conn, @conn.class].each do |adapter|
37
+ assert_equal "`foo`", adapter.quote_column_name("foo")
38
+ assert_equal '`hel"lo`', adapter.quote_column_name(%{hel"lo})
39
+ end
40
+ end
41
+
42
+ def test_quote_table_name
43
+ [@conn, @conn.class].each do |adapter|
44
+ assert_equal "`foo`", adapter.quote_table_name("foo")
45
+ assert_equal "`foo`.`bar`", adapter.quote_table_name("foo.bar")
46
+ assert_equal '`hel"lo.wol\\d`', adapter.quote_column_name('hel"lo.wol\\d')
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/helper"
4
+
5
+ class SchemaMigrationsTest < ActiveRecord::AbstractMysqlTestCase
6
+ def setup
7
+ @pool = ActiveRecord::Base.connection_pool
8
+ @schema_migration = @pool.schema_migration
9
+ end
10
+
11
+ def test_renaming_index_on_foreign_key
12
+ connection.add_index "engines", "car_id"
13
+ connection.add_foreign_key :engines, :cars, name: "fk_engines_cars"
14
+
15
+ connection.rename_index("engines", "index_engines_on_car_id", "idx_renamed")
16
+ assert_equal ["idx_renamed"], connection.indexes("engines").map(&:name)
17
+ ensure
18
+ connection.remove_foreign_key :engines, name: "fk_engines_cars"
19
+ end
20
+
21
+ def test_initializes_schema_migrations_for_encoding_utf8mb4
22
+ with_encoding_utf8mb4 do
23
+ table_name = @schema_migration.table_name
24
+ connection.drop_table table_name, if_exists: true
25
+
26
+ @schema_migration.create_table
27
+
28
+ assert connection.column_exists?(table_name, :version, :string)
29
+ end
30
+ end
31
+
32
+ def test_initializes_internal_metadata_for_encoding_utf8mb4
33
+ with_encoding_utf8mb4 do
34
+ internal_metadata = @pool.internal_metadata
35
+ table_name = internal_metadata.table_name
36
+ connection.drop_table table_name, if_exists: true
37
+
38
+ internal_metadata.create_table
39
+
40
+ assert connection.column_exists?(table_name, :key, :string)
41
+ end
42
+ ensure
43
+ @pool.internal_metadata[:environment] = @pool.migration_context.current_environment
44
+ end
45
+
46
+ private
47
+ def with_encoding_utf8mb4
48
+ database_name = connection.current_database
49
+ database_info = connection.select_one("SELECT * FROM information_schema.schemata WHERE schema_name = '#{database_name}'")
50
+
51
+ original_charset = database_info["DEFAULT_CHARACTER_SET_NAME"]
52
+ original_collation = database_info["DEFAULT_COLLATION_NAME"]
53
+
54
+ execute("ALTER DATABASE #{database_name} DEFAULT CHARACTER SET utf8mb4")
55
+
56
+ yield
57
+ ensure
58
+ execute("ALTER DATABASE #{database_name} DEFAULT CHARACTER SET #{original_charset} COLLATE #{original_collation}")
59
+ end
60
+
61
+ def connection
62
+ @connection ||= ActiveRecord::Base.lease_connection
63
+ end
64
+
65
+ def execute(sql)
66
+ connection.execute(sql)
67
+ end
68
+ end
@@ -0,0 +1,130 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/helper"
4
+ require "models/post"
5
+ require "models/comment"
6
+
7
+ module ActiveRecord
8
+ module ConnectionAdapters
9
+ class SchemaTest < ActiveRecord::AbstractMysqlTestCase
10
+ fixtures :posts
11
+
12
+ def setup
13
+ @connection = ActiveRecord::Base.lease_connection
14
+ db = Post.connection_pool.db_config.database
15
+ table = Post.table_name
16
+ @db_name = db
17
+
18
+ @omgpost = Class.new(ActiveRecord::Base) do
19
+ self.inheritance_column = :disabled
20
+ self.table_name = "#{db}.#{table}"
21
+ def self.name; "Post"; end
22
+ end
23
+ end
24
+
25
+ def test_float_limits
26
+ @connection.create_table :mysql_doubles do |t|
27
+ t.float :float_no_limit
28
+ t.float :float_short, limit: 5
29
+ t.float :float_long, limit: 53
30
+
31
+ t.float :float_23, limit: 23
32
+ t.float :float_24, limit: 24
33
+ t.float :float_25, limit: 25
34
+ end
35
+
36
+ column_no_limit = @connection.columns(:mysql_doubles).find { |c| c.name == "float_no_limit" }
37
+ column_short = @connection.columns(:mysql_doubles).find { |c| c.name == "float_short" }
38
+ column_long = @connection.columns(:mysql_doubles).find { |c| c.name == "float_long" }
39
+
40
+ column_23 = @connection.columns(:mysql_doubles).find { |c| c.name == "float_23" }
41
+ column_24 = @connection.columns(:mysql_doubles).find { |c| c.name == "float_24" }
42
+ column_25 = @connection.columns(:mysql_doubles).find { |c| c.name == "float_25" }
43
+
44
+ # MySQL floats are precision 0..24, MySQL doubles are precision 25..53
45
+ assert_equal 24, column_no_limit.limit
46
+ assert_equal 24, column_short.limit
47
+ assert_equal 53, column_long.limit
48
+
49
+ assert_equal 24, column_23.limit
50
+ assert_equal 24, column_24.limit
51
+ assert_equal 53, column_25.limit
52
+ ensure
53
+ @connection.drop_table "mysql_doubles", if_exists: true
54
+ end
55
+
56
+ def test_schema
57
+ assert @omgpost.first
58
+ end
59
+
60
+ def test_primary_key
61
+ assert_equal "id", @omgpost.primary_key
62
+ end
63
+
64
+ def test_data_source_exists?
65
+ name = @omgpost.table_name
66
+ assert @connection.data_source_exists?(name), "#{name} data_source should exist"
67
+ end
68
+
69
+ def test_data_source_exists_wrong_schema
70
+ assert_not(@connection.data_source_exists?("#{@db_name}.zomg"), "data_source should not exist")
71
+ end
72
+
73
+ def test_dump_indexes
74
+ index_a_name = "index_key_tests_on_snack"
75
+ index_b_name = "index_key_tests_on_pizza"
76
+ index_c_name = "index_key_tests_on_awesome"
77
+
78
+ table = "key_tests"
79
+
80
+ indexes = @connection.indexes(table).sort_by(&:name)
81
+ assert_equal 3, indexes.size
82
+
83
+ index_a = indexes.select { |i| i.name == index_a_name }[0]
84
+ index_b = indexes.select { |i| i.name == index_b_name }[0]
85
+ index_c = indexes.select { |i| i.name == index_c_name }[0]
86
+ assert_equal :btree, index_a.using
87
+ assert_nil index_a.type
88
+ assert_equal :btree, index_b.using
89
+ assert_nil index_b.type
90
+
91
+ assert_nil index_c.using
92
+ assert_equal :fulltext, index_c.type
93
+ end
94
+
95
+ unless mysql_enforcing_gtid_consistency?
96
+ def test_drop_temporary_table
97
+ @connection.transaction do
98
+ @connection.create_table(:temp_table, temporary: true)
99
+ assert_nothing_raised do
100
+ # if it doesn't properly say DROP TEMPORARY TABLE, the transaction commit
101
+ # will complain that no transaction is active
102
+ @connection.drop_table(:temp_table, temporary: true)
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
110
+
111
+ class MysqlAnsiQuotesTest < ActiveRecord::AbstractMysqlTestCase
112
+ def setup
113
+ @connection = ActiveRecord::Base.lease_connection
114
+ @connection.execute("SET SESSION sql_mode='ANSI_QUOTES'")
115
+ end
116
+
117
+ def teardown
118
+ @connection.reconnect!
119
+ end
120
+
121
+ def test_primary_key_method_with_ansi_quotes
122
+ assert_equal "id", @connection.primary_key("topics")
123
+ end
124
+
125
+ def test_foreign_keys_method_with_ansi_quotes
126
+ fks = @connection.foreign_keys("lessons_students")
127
+ assert_equal([["lessons_students", "students", :cascade]],
128
+ fks.map { |fk| [fk.from_table, fk.to_table, fk.on_delete] })
129
+ end
130
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/helper"
4
+ require "support/schema_dumping_helper"
5
+
6
+ class SetTest < ActiveRecord::AbstractMysqlTestCase
7
+ include SchemaDumpingHelper
8
+
9
+ class SetTest < ActiveRecord::Base
10
+ end
11
+
12
+ def setup
13
+ SetTest.lease_connection.create_table :set_tests, id: false, force: true do |t|
14
+ t.column :set_column, "set('text','blob','tiny','medium','long','unsigned','bigint')"
15
+ end
16
+ end
17
+
18
+ def test_should_not_be_unsigned
19
+ column = SetTest.columns_hash["set_column"]
20
+ assert_not_predicate column, :unsigned?
21
+ end
22
+
23
+ def test_should_not_be_bigint
24
+ column = SetTest.columns_hash["set_column"]
25
+ assert_not_predicate column, :bigint?
26
+ end
27
+
28
+ def test_schema_dumping
29
+ schema = dump_table_schema "set_tests"
30
+ assert_match %r{t\.column "set_column", "set\('text','blob','tiny','medium','long','unsigned','bigint'\)"$}, schema
31
+ end
32
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/helper"
4
+ require "models/topic"
5
+ require "models/reply"
6
+
7
+ class StoredProcedureTest < ActiveRecord::AbstractMysqlTestCase
8
+ fixtures :topics
9
+
10
+ def setup
11
+ @connection = ActiveRecord::Base.lease_connection
12
+ unless ActiveRecord::Base.lease_connection.database_version >= "5.6.0"
13
+ skip("no stored procedure support")
14
+ end
15
+ end
16
+
17
+ # Test that MySQL allows multiple results for stored procedures
18
+ #
19
+ # In MySQL 5.6, CLIENT_MULTI_RESULTS is enabled by default.
20
+ # https://dev.mysql.com/doc/refman/en/call.html
21
+ def test_multi_results
22
+ rows = @connection.select_rows("CALL ten();")
23
+ assert_equal 10, rows[0][0].to_i, "ten() did not return 10 as expected: #{rows.inspect}"
24
+
25
+ assert_predicate @connection, :active?, "Bad connection use by '#{@connection.class}.select_rows'"
26
+ end
27
+
28
+ def test_multi_results_from_select_one
29
+ row = @connection.select_one("CALL topics(1);")
30
+ assert_equal "David", row["author_name"]
31
+ assert_predicate @connection, :active?, "Bad connection use by '#{@connection.class}.select_one'"
32
+ end
33
+
34
+ def test_multi_results_from_find_by_sql
35
+ topics = Topic.find_by_sql "CALL topics(3);"
36
+ assert_equal 3, topics.size
37
+ assert_predicate @connection, :active?, "Bad connection use by '#{@connection.class}.select'"
38
+ end
39
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/helper"
4
+
5
+ class SqlTypesTest < ActiveRecord::AbstractMysqlTestCase
6
+ def test_binary_types
7
+ assert_equal "varbinary(64)", type_to_sql(:binary, 64)
8
+ assert_equal "varbinary(4095)", type_to_sql(:binary, 4095)
9
+ assert_equal "blob", type_to_sql(:binary, 4096)
10
+ assert_equal "blob", type_to_sql(:binary)
11
+ end
12
+
13
+ def type_to_sql(type, limit = nil)
14
+ ActiveRecord::Base.lease_connection.type_to_sql(type, limit: limit)
15
+ end
16
+ end