ibm_db 5.1.0-x86-mingw32 → 5.3.2-x86-mingw32

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 (624) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +9 -0
  3. data/LICENSE +55 -18
  4. data/ext/Makefile +14 -14
  5. data/ext/extconf.rb +4 -4
  6. data/ext/ibm_db.c +62 -57
  7. data/ext/ibm_db.o +0 -0
  8. data/ext/ibm_db.so +0 -0
  9. data/ext/mkmf.log +11 -11
  10. data/ext/ruby_ibm_db_cli.c +1 -0
  11. data/ext/ruby_ibm_db_cli.o +0 -0
  12. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +1463 -1279
  13. data/lib/ibm_db.so +1 -0
  14. data/lib/mswin32/ibm_db.rb +7 -3
  15. data/lib/mswin32/rb2x/i386/ruby25/ibm_db.so +0 -0
  16. data/lib/mswin32/rb3x/i386/ruby30/ibm_db.so +0 -0
  17. data/test/active_record/connection_adapters/fake_adapter.rb +5 -2
  18. data/test/activejob/destroy_association_async_test.rb +305 -0
  19. data/test/activejob/destroy_async_job_not_present_test.rb +31 -0
  20. data/test/activejob/helper.rb +15 -0
  21. data/test/assets/schema_dump_5_1.yml +345 -0
  22. data/test/cases/adapter_prevent_writes_test.rb +334 -0
  23. data/test/cases/adapter_test.rb +432 -218
  24. data/test/cases/adapters/mysql2/active_schema_test.rb +85 -75
  25. data/test/cases/adapters/mysql2/auto_increment_test.rb +34 -0
  26. data/test/cases/adapters/mysql2/bind_parameter_test.rb +5 -3
  27. data/test/cases/adapters/mysql2/boolean_test.rb +6 -4
  28. data/test/cases/adapters/mysql2/case_sensitivity_test.rb +26 -24
  29. data/test/cases/adapters/mysql2/charset_collation_test.rb +20 -17
  30. data/test/cases/adapters/mysql2/connection_test.rb +48 -50
  31. data/test/cases/adapters/mysql2/count_deleted_rows_with_lock_test.rb +28 -0
  32. data/test/cases/adapters/mysql2/datetime_precision_quoting_test.rb +23 -19
  33. data/test/cases/adapters/mysql2/enum_test.rb +32 -11
  34. data/test/cases/adapters/mysql2/explain_test.rb +13 -11
  35. data/test/cases/adapters/mysql2/json_test.rb +17 -188
  36. data/test/cases/adapters/mysql2/mysql2_adapter_prevent_writes_test.rb +208 -0
  37. data/test/cases/adapters/mysql2/mysql2_adapter_test.rb +183 -28
  38. data/test/cases/adapters/mysql2/nested_deadlock_test.rb +75 -0
  39. data/test/cases/adapters/mysql2/optimizer_hints_test.rb +69 -0
  40. data/test/cases/adapters/mysql2/schema_migrations_test.rb +26 -21
  41. data/test/cases/adapters/mysql2/schema_test.rb +24 -22
  42. data/test/cases/adapters/mysql2/set_test.rb +32 -0
  43. data/test/cases/adapters/mysql2/sp_test.rb +10 -8
  44. data/test/cases/adapters/mysql2/sql_types_test.rb +8 -6
  45. data/test/cases/adapters/mysql2/table_options_test.rb +93 -10
  46. data/test/cases/adapters/mysql2/transaction_test.rb +151 -0
  47. data/test/cases/adapters/mysql2/unsigned_type_test.rb +11 -9
  48. data/test/cases/adapters/mysql2/virtual_column_test.rb +66 -0
  49. data/test/cases/adapters/postgresql/active_schema_test.rb +40 -25
  50. data/test/cases/adapters/postgresql/array_test.rb +118 -63
  51. data/test/cases/adapters/postgresql/bit_string_test.rb +12 -10
  52. data/test/cases/adapters/postgresql/bytea_test.rb +26 -25
  53. data/test/cases/adapters/postgresql/case_insensitive_test.rb +10 -9
  54. data/test/cases/adapters/postgresql/change_schema_test.rb +7 -5
  55. data/test/cases/adapters/postgresql/cidr_test.rb +2 -0
  56. data/test/cases/adapters/postgresql/citext_test.rb +58 -58
  57. data/test/cases/adapters/postgresql/collation_test.rb +17 -15
  58. data/test/cases/adapters/postgresql/composite_test.rb +25 -23
  59. data/test/cases/adapters/postgresql/connection_test.rb +73 -85
  60. data/test/cases/adapters/postgresql/create_unlogged_tables_test.rb +74 -0
  61. data/test/cases/adapters/postgresql/datatype_test.rb +19 -22
  62. data/test/cases/adapters/postgresql/date_test.rb +42 -0
  63. data/test/cases/adapters/postgresql/domain_test.rb +9 -7
  64. data/test/cases/adapters/postgresql/enum_test.rb +12 -10
  65. data/test/cases/adapters/postgresql/explain_test.rb +10 -8
  66. data/test/cases/adapters/postgresql/extension_migration_test.rb +13 -12
  67. data/test/cases/adapters/postgresql/foreign_table_test.rb +109 -0
  68. data/test/cases/adapters/postgresql/full_text_test.rb +8 -6
  69. data/test/cases/adapters/postgresql/geometric_test.rb +57 -63
  70. data/test/cases/adapters/postgresql/hstore_test.rb +288 -280
  71. data/test/cases/adapters/postgresql/infinity_test.rb +54 -15
  72. data/test/cases/adapters/postgresql/integer_test.rb +2 -0
  73. data/test/cases/adapters/postgresql/interval_test.rb +99 -0
  74. data/test/cases/adapters/postgresql/json_test.rb +16 -201
  75. data/test/cases/adapters/postgresql/ltree_test.rb +14 -16
  76. data/test/cases/adapters/postgresql/money_test.rb +47 -16
  77. data/test/cases/adapters/postgresql/network_test.rb +36 -28
  78. data/test/cases/adapters/postgresql/numbers_test.rb +7 -5
  79. data/test/cases/adapters/postgresql/optimizer_hints_test.rb +71 -0
  80. data/test/cases/adapters/postgresql/partitions_test.rb +22 -0
  81. data/test/cases/adapters/postgresql/postgresql_adapter_prevent_writes_test.rb +205 -0
  82. data/test/cases/adapters/postgresql/postgresql_adapter_test.rb +178 -136
  83. data/test/cases/adapters/postgresql/prepared_statements_disabled_test.rb +27 -0
  84. data/test/cases/adapters/postgresql/quoting_test.rb +12 -6
  85. data/test/cases/adapters/postgresql/range_test.rb +406 -292
  86. data/test/cases/adapters/postgresql/referential_integrity_test.rb +16 -15
  87. data/test/cases/adapters/postgresql/rename_table_test.rb +9 -8
  88. data/test/cases/adapters/postgresql/schema_authorization_test.rb +14 -23
  89. data/test/cases/adapters/postgresql/schema_test.rb +207 -91
  90. data/test/cases/adapters/postgresql/serial_test.rb +9 -7
  91. data/test/cases/adapters/postgresql/statement_pool_test.rb +26 -6
  92. data/test/cases/adapters/postgresql/timestamp_test.rb +17 -15
  93. data/test/cases/adapters/postgresql/transaction_nested_test.rb +114 -0
  94. data/test/cases/adapters/postgresql/transaction_test.rb +189 -0
  95. data/test/cases/adapters/postgresql/type_lookup_test.rb +12 -10
  96. data/test/cases/adapters/postgresql/utils_test.rb +11 -9
  97. data/test/cases/adapters/postgresql/uuid_test.rb +226 -109
  98. data/test/cases/adapters/postgresql/xml_test.rb +10 -14
  99. data/test/cases/adapters/sqlite3/collation_test.rb +26 -15
  100. data/test/cases/adapters/sqlite3/copy_table_test.rb +31 -28
  101. data/test/cases/adapters/sqlite3/explain_test.rb +13 -11
  102. data/test/cases/adapters/sqlite3/json_test.rb +29 -0
  103. data/test/cases/adapters/sqlite3/quoting_test.rb +35 -57
  104. data/test/cases/adapters/sqlite3/sqlite3_adapter_prevent_writes_test.rb +186 -0
  105. data/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +318 -131
  106. data/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb +11 -11
  107. data/test/cases/adapters/sqlite3/statement_pool_test.rb +7 -6
  108. data/test/cases/adapters/sqlite3/transaction_test.rb +123 -0
  109. data/test/cases/aggregations_test.rb +14 -12
  110. data/test/cases/annotate_test.rb +46 -0
  111. data/test/cases/ar_schema_test.rb +153 -86
  112. data/test/cases/arel/attributes/attribute_test.rb +1145 -0
  113. data/test/cases/arel/attributes/math_test.rb +83 -0
  114. data/test/cases/arel/attributes_test.rb +27 -0
  115. data/test/cases/arel/collectors/bind_test.rb +40 -0
  116. data/test/cases/arel/collectors/composite_test.rb +47 -0
  117. data/test/cases/arel/collectors/sql_string_test.rb +41 -0
  118. data/test/cases/arel/collectors/substitute_bind_collector_test.rb +48 -0
  119. data/test/cases/arel/crud_test.rb +65 -0
  120. data/test/cases/arel/delete_manager_test.rb +53 -0
  121. data/test/cases/arel/factory_methods_test.rb +46 -0
  122. data/test/cases/arel/helper.rb +45 -0
  123. data/test/cases/arel/insert_manager_test.rb +241 -0
  124. data/test/cases/arel/nodes/and_test.rb +30 -0
  125. data/test/cases/arel/nodes/as_test.rb +36 -0
  126. data/test/cases/arel/nodes/ascending_test.rb +46 -0
  127. data/test/cases/arel/nodes/bin_test.rb +35 -0
  128. data/test/cases/arel/nodes/binary_test.rb +29 -0
  129. data/test/cases/arel/nodes/bind_param_test.rb +22 -0
  130. data/test/cases/arel/nodes/case_test.rb +96 -0
  131. data/test/cases/arel/nodes/casted_test.rb +18 -0
  132. data/test/cases/arel/nodes/comment_test.rb +22 -0
  133. data/test/cases/arel/nodes/count_test.rb +35 -0
  134. data/test/cases/arel/nodes/delete_statement_test.rb +36 -0
  135. data/test/cases/arel/nodes/descending_test.rb +46 -0
  136. data/test/cases/arel/nodes/distinct_test.rb +21 -0
  137. data/test/cases/arel/nodes/equality_test.rb +62 -0
  138. data/test/cases/arel/nodes/extract_test.rb +43 -0
  139. data/test/cases/arel/nodes/false_test.rb +21 -0
  140. data/test/cases/arel/nodes/grouping_test.rb +26 -0
  141. data/test/cases/arel/nodes/infix_operation_test.rb +42 -0
  142. data/test/cases/arel/nodes/insert_statement_test.rb +44 -0
  143. data/test/cases/arel/nodes/named_function_test.rb +48 -0
  144. data/test/cases/arel/nodes/node_test.rb +22 -0
  145. data/test/cases/arel/nodes/not_test.rb +31 -0
  146. data/test/cases/arel/nodes/or_test.rb +36 -0
  147. data/test/cases/arel/nodes/over_test.rb +69 -0
  148. data/test/cases/arel/nodes/select_core_test.rb +79 -0
  149. data/test/cases/arel/nodes/select_statement_test.rb +51 -0
  150. data/test/cases/arel/nodes/sql_literal_test.rb +75 -0
  151. data/test/cases/arel/nodes/sum_test.rb +35 -0
  152. data/test/cases/arel/nodes/table_alias_test.rb +29 -0
  153. data/test/cases/arel/nodes/true_test.rb +21 -0
  154. data/test/cases/arel/nodes/unary_operation_test.rb +41 -0
  155. data/test/cases/arel/nodes/update_statement_test.rb +60 -0
  156. data/test/cases/arel/nodes/window_test.rb +81 -0
  157. data/test/cases/arel/nodes_test.rb +34 -0
  158. data/test/cases/arel/select_manager_test.rb +1238 -0
  159. data/test/cases/arel/support/fake_record.rb +135 -0
  160. data/test/cases/arel/table_test.rb +216 -0
  161. data/test/cases/arel/update_manager_test.rb +126 -0
  162. data/test/cases/arel/visitors/dispatch_contamination_test.rb +78 -0
  163. data/test/cases/arel/visitors/dot_test.rb +90 -0
  164. data/test/cases/arel/visitors/mysql_test.rb +157 -0
  165. data/test/cases/arel/visitors/postgres_test.rb +366 -0
  166. data/test/cases/arel/visitors/sqlite_test.rb +75 -0
  167. data/test/cases/arel/visitors/to_sql_test.rb +750 -0
  168. data/test/cases/associations/belongs_to_associations_test.rb +510 -158
  169. data/test/cases/associations/bidirectional_destroy_dependencies_test.rb +4 -2
  170. data/test/cases/associations/callbacks_test.rb +56 -38
  171. data/test/cases/associations/cascaded_eager_loading_test.rb +118 -61
  172. data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +138 -18
  173. data/test/cases/associations/eager_load_nested_include_test.rb +38 -37
  174. data/test/cases/associations/eager_singularization_test.rb +21 -21
  175. data/test/cases/associations/eager_test.rb +559 -415
  176. data/test/cases/associations/extension_test.rb +18 -12
  177. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +234 -213
  178. data/test/cases/associations/has_many_associations_test.rb +1038 -465
  179. data/test/cases/associations/has_many_through_associations_test.rb +558 -249
  180. data/test/cases/associations/has_one_associations_test.rb +294 -129
  181. data/test/cases/associations/has_one_through_associations_test.rb +121 -75
  182. data/test/cases/associations/inner_join_association_test.rb +114 -38
  183. data/test/cases/associations/inverse_associations_test.rb +606 -398
  184. data/test/cases/associations/join_model_test.rb +158 -148
  185. data/test/cases/associations/left_outer_join_association_test.rb +59 -24
  186. data/test/cases/associations/nested_through_associations_test.rb +166 -109
  187. data/test/cases/associations/required_test.rb +35 -10
  188. data/test/cases/associations_test.rb +241 -110
  189. data/test/cases/attribute_methods/read_test.rb +11 -11
  190. data/test/cases/attribute_methods_test.rb +413 -298
  191. data/test/cases/attributes_test.rb +145 -27
  192. data/test/cases/autosave_association_test.rb +681 -436
  193. data/test/cases/base_prevent_writes_test.rb +229 -0
  194. data/test/cases/base_test.rb +599 -542
  195. data/test/cases/batches_test.rb +288 -82
  196. data/test/cases/binary_test.rb +26 -31
  197. data/test/cases/bind_parameter_test.rb +194 -21
  198. data/test/cases/boolean_test.rb +52 -0
  199. data/test/cases/cache_key_test.rb +110 -5
  200. data/test/cases/calculations_test.rb +740 -177
  201. data/test/cases/callbacks_test.rb +74 -207
  202. data/test/cases/clone_test.rb +15 -10
  203. data/test/cases/coders/json_test.rb +2 -0
  204. data/test/cases/coders/yaml_column_test.rb +16 -13
  205. data/test/cases/collection_cache_key_test.rb +177 -20
  206. data/test/cases/column_alias_test.rb +9 -7
  207. data/test/cases/column_definition_test.rb +10 -68
  208. data/test/cases/comment_test.rb +166 -107
  209. data/test/cases/connection_adapters/adapter_leasing_test.rb +14 -10
  210. data/test/cases/connection_adapters/connection_handler_test.rb +358 -51
  211. data/test/cases/connection_adapters/connection_handlers_multi_db_test.rb +400 -0
  212. data/test/cases/connection_adapters/connection_handlers_multi_pool_config_test.rb +103 -0
  213. data/test/cases/connection_adapters/connection_handlers_sharding_db_test.rb +499 -0
  214. data/test/cases/connection_adapters/connection_swapping_nested_test.rb +457 -0
  215. data/test/cases/connection_adapters/legacy_connection_handlers_multi_db_test.rb +486 -0
  216. data/test/cases/connection_adapters/legacy_connection_handlers_sharding_db_test.rb +586 -0
  217. data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +319 -138
  218. data/test/cases/connection_adapters/mysql_type_lookup_test.rb +62 -50
  219. data/test/cases/connection_adapters/schema_cache_test.rb +259 -26
  220. data/test/cases/connection_adapters/type_lookup_test.rb +96 -95
  221. data/test/cases/connection_management_test.rb +13 -11
  222. data/test/cases/connection_pool_test.rb +316 -83
  223. data/test/cases/core_test.rb +82 -58
  224. data/test/cases/counter_cache_test.rb +204 -50
  225. data/test/cases/custom_locking_test.rb +5 -3
  226. data/test/cases/database_configurations/hash_config_test.rb +74 -0
  227. data/test/cases/database_configurations/resolver_test.rb +150 -0
  228. data/test/cases/database_configurations_test.rb +145 -0
  229. data/test/cases/database_selector_test.rb +296 -0
  230. data/test/cases/database_statements_test.rb +18 -16
  231. data/test/cases/date_test.rb +8 -16
  232. data/test/cases/date_time_precision_test.rb +100 -78
  233. data/test/cases/date_time_test.rb +23 -8
  234. data/test/cases/defaults_test.rb +106 -71
  235. data/test/cases/delegated_type_test.rb +57 -0
  236. data/test/cases/dirty_test.rb +419 -223
  237. data/test/cases/disconnected_test.rb +6 -6
  238. data/test/cases/dup_test.rb +54 -27
  239. data/test/cases/enum_test.rb +461 -82
  240. data/test/cases/errors_test.rb +7 -7
  241. data/test/cases/explain_subscriber_test.rb +17 -15
  242. data/test/cases/explain_test.rb +11 -19
  243. data/test/cases/filter_attributes_test.rb +153 -0
  244. data/test/cases/finder_respond_to_test.rb +14 -14
  245. data/test/cases/finder_test.rb +669 -287
  246. data/test/cases/fixture_set/file_test.rb +34 -38
  247. data/test/cases/fixtures_test.rb +833 -176
  248. data/test/cases/forbidden_attributes_protection_test.rb +32 -67
  249. data/test/cases/habtm_destroy_order_test.rb +25 -25
  250. data/test/cases/helper.rb +78 -49
  251. data/test/cases/hot_compatibility_test.rb +33 -32
  252. data/test/cases/i18n_test.rb +18 -17
  253. data/test/cases/inheritance_test.rb +180 -115
  254. data/test/cases/insert_all_test.rb +489 -0
  255. data/test/cases/instrumentation_test.rb +101 -0
  256. data/test/cases/integration_test.rb +119 -31
  257. data/test/cases/invalid_connection_test.rb +18 -16
  258. data/test/cases/invertible_migration_test.rb +183 -43
  259. data/test/cases/json_attribute_test.rb +35 -0
  260. data/test/cases/json_serialization_test.rb +57 -58
  261. data/test/cases/json_shared_test_cases.rb +290 -0
  262. data/test/cases/locking_test.rb +413 -119
  263. data/test/cases/log_subscriber_test.rb +68 -26
  264. data/test/cases/marshal_serialization_test.rb +39 -0
  265. data/test/cases/migration/change_schema_test.rb +118 -72
  266. data/test/cases/migration/change_table_test.rb +138 -30
  267. data/test/cases/migration/check_constraint_test.rb +162 -0
  268. data/test/cases/migration/column_attributes_test.rb +45 -35
  269. data/test/cases/migration/column_positioning_test.rb +18 -6
  270. data/test/cases/migration/columns_test.rb +93 -77
  271. data/test/cases/migration/command_recorder_test.rb +121 -34
  272. data/test/cases/migration/compatibility_test.rb +578 -23
  273. data/test/cases/migration/create_join_table_test.rb +35 -25
  274. data/test/cases/migration/foreign_key_test.rb +503 -284
  275. data/test/cases/migration/helper.rb +4 -3
  276. data/test/cases/migration/index_test.rb +119 -70
  277. data/test/cases/migration/logger_test.rb +9 -6
  278. data/test/cases/migration/pending_migrations_test.rb +88 -34
  279. data/test/cases/migration/references_foreign_key_test.rb +164 -150
  280. data/test/cases/migration/references_index_test.rb +38 -19
  281. data/test/cases/migration/references_statements_test.rb +15 -14
  282. data/test/cases/migration/rename_table_test.rb +53 -30
  283. data/test/cases/migration_test.rb +637 -269
  284. data/test/cases/migrator_test.rb +191 -135
  285. data/test/cases/mixin_test.rb +7 -11
  286. data/test/cases/modules_test.rb +36 -34
  287. data/test/cases/multi_db_migrator_test.rb +223 -0
  288. data/test/cases/multiparameter_attributes_test.rb +60 -33
  289. data/test/cases/multiple_db_test.rb +16 -22
  290. data/test/cases/nested_attributes_test.rb +341 -320
  291. data/test/cases/nested_attributes_with_callbacks_test.rb +26 -24
  292. data/test/cases/null_relation_test.rb +84 -0
  293. data/test/cases/numeric_data_test.rb +93 -0
  294. data/test/cases/persistence_test.rb +361 -269
  295. data/test/cases/pooled_connections_test.rb +18 -26
  296. data/test/cases/prepared_statement_status_test.rb +48 -0
  297. data/test/cases/primary_keys_test.rb +210 -104
  298. data/test/cases/query_cache_test.rb +610 -141
  299. data/test/cases/quoting_test.rb +132 -31
  300. data/test/cases/readonly_test.rb +49 -48
  301. data/test/cases/reaper_test.rb +146 -32
  302. data/test/cases/reflection_test.rb +167 -156
  303. data/test/cases/relation/delegation_test.rb +49 -36
  304. data/test/cases/relation/delete_all_test.rb +117 -0
  305. data/test/cases/relation/merging_test.rb +319 -42
  306. data/test/cases/relation/mutation_test.rb +55 -93
  307. data/test/cases/relation/or_test.rb +129 -29
  308. data/test/cases/relation/predicate_builder_test.rb +21 -6
  309. data/test/cases/relation/record_fetch_warning_test.rb +5 -3
  310. data/test/cases/relation/select_test.rb +67 -0
  311. data/test/cases/relation/update_all_test.rb +317 -0
  312. data/test/cases/relation/where_chain_test.rb +68 -32
  313. data/test/cases/relation/where_clause_test.rb +136 -61
  314. data/test/cases/relation/where_test.rb +155 -48
  315. data/test/cases/relation_test.rb +266 -112
  316. data/test/cases/relations_test.rb +969 -744
  317. data/test/cases/reload_models_test.rb +13 -9
  318. data/test/cases/reserved_word_test.rb +141 -0
  319. data/test/cases/result_test.rb +68 -17
  320. data/test/cases/sanitize_test.rb +87 -71
  321. data/test/cases/schema_dumper_test.rb +221 -128
  322. data/test/cases/schema_loading_test.rb +3 -2
  323. data/test/cases/scoping/default_scoping_test.rb +185 -144
  324. data/test/cases/scoping/named_scoping_test.rb +177 -89
  325. data/test/cases/scoping/relation_scoping_test.rb +197 -75
  326. data/test/cases/secure_token_test.rb +18 -3
  327. data/test/cases/serialization_test.rb +30 -28
  328. data/test/cases/serialized_attribute_test.rb +133 -42
  329. data/test/cases/signed_id_test.rb +168 -0
  330. data/test/cases/statement_cache_test.rb +41 -24
  331. data/test/cases/statement_invalid_test.rb +42 -0
  332. data/test/cases/store_test.rb +180 -55
  333. data/test/cases/strict_loading_test.rb +473 -0
  334. data/test/cases/suppressor_test.rb +26 -12
  335. data/test/cases/tasks/database_tasks_test.rb +1258 -194
  336. data/test/cases/tasks/mysql_rake_test.rb +370 -298
  337. data/test/cases/tasks/postgresql_rake_test.rb +481 -251
  338. data/test/cases/tasks/sqlite_rake_test.rb +225 -178
  339. data/test/cases/test_case.rb +51 -40
  340. data/test/cases/test_databases_test.rb +79 -0
  341. data/test/cases/test_fixtures_test.rb +79 -19
  342. data/test/cases/time_precision_test.rb +98 -76
  343. data/test/cases/timestamp_test.rb +102 -99
  344. data/test/cases/touch_later_test.rb +12 -10
  345. data/test/cases/transaction_callbacks_test.rb +344 -90
  346. data/test/cases/transaction_isolation_test.rb +12 -12
  347. data/test/cases/transactions_test.rb +612 -162
  348. data/test/cases/type/adapter_specific_registry_test.rb +14 -2
  349. data/test/cases/type/date_time_test.rb +4 -2
  350. data/test/cases/type/integer_test.rb +4 -2
  351. data/test/cases/type/string_test.rb +10 -8
  352. data/test/cases/type/time_test.rb +28 -0
  353. data/test/cases/type/type_map_test.rb +29 -28
  354. data/test/cases/type/unsigned_integer_test.rb +19 -0
  355. data/test/cases/type_test.rb +2 -0
  356. data/test/cases/types_test.rb +3 -1
  357. data/test/cases/unconnected_test.rb +14 -1
  358. data/test/cases/unsafe_raw_sql_test.rb +274 -0
  359. data/test/cases/validations/absence_validation_test.rb +19 -17
  360. data/test/cases/validations/association_validation_test.rb +30 -28
  361. data/test/cases/validations/i18n_generate_message_validation_test.rb +34 -16
  362. data/test/cases/validations/i18n_validation_test.rb +22 -21
  363. data/test/cases/validations/length_validation_test.rb +34 -33
  364. data/test/cases/validations/numericality_validation_test.rb +181 -0
  365. data/test/cases/validations/presence_validation_test.rb +21 -19
  366. data/test/cases/validations/uniqueness_validation_test.rb +156 -86
  367. data/test/cases/validations_repair_helper.rb +2 -0
  368. data/test/cases/validations_test.rb +61 -26
  369. data/test/cases/view_test.rb +122 -116
  370. data/test/cases/yaml_serialization_test.rb +79 -34
  371. data/test/config.example.yml +19 -19
  372. data/test/config.rb +3 -1
  373. data/test/config.yml +16 -6
  374. data/test/fixtures/all/namespaced/accounts.yml +2 -0
  375. data/test/fixtures/author_addresses.yml +1 -8
  376. data/test/fixtures/authors.yml +1 -7
  377. data/test/fixtures/binaries.yml +4 -0
  378. data/test/fixtures/books.yml +9 -2
  379. data/test/fixtures/categories_posts.yml +3 -0
  380. data/test/fixtures/citations.yml +5 -0
  381. data/test/fixtures/comments.yml +7 -0
  382. data/test/fixtures/companies.yml +5 -0
  383. data/test/fixtures/computers.yml +2 -0
  384. data/test/fixtures/customers.yml +10 -1
  385. data/test/fixtures/developers.yml +1 -1
  386. data/test/fixtures/essays.yml +10 -0
  387. data/test/fixtures/faces.yml +3 -3
  388. data/test/fixtures/humans.yml +5 -0
  389. data/test/fixtures/interests.yml +7 -7
  390. data/test/fixtures/memberships.yml +7 -0
  391. data/test/fixtures/minimalistics.yml +3 -0
  392. data/test/fixtures/mixed_case_monkeys.yml +2 -2
  393. data/test/fixtures/naked/yml/courses_with_invalid_key.yml +3 -0
  394. data/test/fixtures/naked/yml/parrots.yml +1 -0
  395. data/test/fixtures/other_books.yml +26 -0
  396. data/test/fixtures/other_posts.yml +1 -0
  397. data/test/fixtures/parrots.yml +7 -1
  398. data/test/fixtures/pirates.yml +3 -0
  399. data/test/fixtures/posts.yml +11 -3
  400. data/test/fixtures/readers.yml +6 -0
  401. data/test/fixtures/reserved_words/values.yml +2 -2
  402. data/test/fixtures/sponsors.yml +3 -0
  403. data/test/fixtures/strict_zines.yml +2 -0
  404. data/test/fixtures/subscribers.yml +1 -1
  405. data/test/fixtures/tasks.yml +1 -1
  406. data/test/fixtures/warehouse-things.yml +3 -0
  407. data/test/migrations/10_urban/9_add_expressions.rb +2 -0
  408. data/test/migrations/decimal/1_give_me_big_numbers.rb +6 -4
  409. data/test/migrations/magic/1_currencies_have_symbols.rb +3 -2
  410. data/test/migrations/missing/1000_people_have_middle_names.rb +2 -0
  411. data/test/migrations/missing/1_people_have_last_names.rb +2 -0
  412. data/test/migrations/missing/3_we_need_reminders.rb +2 -0
  413. data/test/migrations/missing/4_innocent_jointable.rb +3 -1
  414. data/test/migrations/rename/1_we_need_things.rb +2 -0
  415. data/test/migrations/rename/2_rename_things.rb +2 -0
  416. data/test/migrations/to_copy/1_people_have_hobbies.rb +3 -1
  417. data/test/migrations/to_copy/2_people_have_descriptions.rb +3 -1
  418. data/test/migrations/to_copy2/1_create_articles.rb +2 -0
  419. data/test/migrations/to_copy2/2_create_comments.rb +3 -1
  420. data/test/migrations/to_copy_with_name_collision/1_people_have_hobbies.rb +3 -1
  421. data/test/migrations/to_copy_with_timestamps/20090101010101_people_have_hobbies.rb +3 -1
  422. data/test/migrations/to_copy_with_timestamps/20090101010202_people_have_descriptions.rb +3 -1
  423. data/test/migrations/to_copy_with_timestamps2/20090101010101_create_articles.rb +2 -0
  424. data/test/migrations/to_copy_with_timestamps2/20090101010202_create_comments.rb +2 -0
  425. data/test/migrations/valid/1_valid_people_have_last_names.rb +2 -0
  426. data/test/migrations/valid/2_we_need_reminders.rb +2 -0
  427. data/test/migrations/valid/3_innocent_jointable.rb +3 -1
  428. data/test/migrations/valid_with_subdirectories/1_valid_people_have_last_names.rb +2 -0
  429. data/test/migrations/valid_with_subdirectories/sub/2_we_need_reminders.rb +2 -0
  430. data/test/migrations/valid_with_subdirectories/sub1/3_innocent_jointable.rb +3 -1
  431. data/test/migrations/valid_with_timestamps/20100101010101_valid_with_timestamps_people_have_last_names.rb +2 -0
  432. data/test/migrations/valid_with_timestamps/20100201010101_valid_with_timestamps_we_need_reminders.rb +2 -0
  433. data/test/migrations/valid_with_timestamps/20100301010101_valid_with_timestamps_innocent_jointable.rb +3 -1
  434. data/test/migrations/version_check/20131219224947_migration_version_check.rb +2 -0
  435. data/test/models/account.rb +46 -0
  436. data/test/models/admin/account.rb +3 -1
  437. data/test/models/admin/randomly_named_c1.rb +2 -0
  438. data/test/models/admin/user.rb +16 -8
  439. data/test/models/admin.rb +4 -2
  440. data/test/models/aircraft.rb +3 -1
  441. data/test/models/arunit2_model.rb +2 -0
  442. data/test/models/author.rb +153 -102
  443. data/test/models/auto_id.rb +2 -0
  444. data/test/models/autoloadable/extra_firm.rb +2 -0
  445. data/test/models/binary.rb +3 -1
  446. data/test/models/binary_field.rb +6 -0
  447. data/test/models/bird.rb +13 -1
  448. data/test/models/book.rb +14 -4
  449. data/test/models/book_destroy_async.rb +24 -0
  450. data/test/models/boolean.rb +5 -0
  451. data/test/models/bulb.rb +13 -4
  452. data/test/models/cake_designer.rb +2 -0
  453. data/test/models/car.rb +17 -10
  454. data/test/models/carrier.rb +2 -0
  455. data/test/models/cart.rb +5 -0
  456. data/test/models/cat.rb +2 -0
  457. data/test/models/categorization.rb +8 -6
  458. data/test/models/category.rb +28 -16
  459. data/test/models/chef.rb +2 -0
  460. data/test/models/citation.rb +5 -1
  461. data/test/models/club.rb +13 -10
  462. data/test/models/college.rb +4 -2
  463. data/test/models/column.rb +2 -0
  464. data/test/models/column_name.rb +2 -0
  465. data/test/models/comment.rb +32 -10
  466. data/test/models/company.rb +102 -106
  467. data/test/models/company_in_module.rb +27 -26
  468. data/test/models/computer.rb +3 -1
  469. data/test/models/contact.rb +15 -13
  470. data/test/models/content.rb +5 -3
  471. data/test/models/contract.rb +21 -3
  472. data/test/models/country.rb +2 -4
  473. data/test/models/course.rb +3 -1
  474. data/test/models/customer.rb +10 -8
  475. data/test/models/customer_carrier.rb +2 -0
  476. data/test/models/dashboard.rb +2 -0
  477. data/test/models/default.rb +2 -0
  478. data/test/models/department.rb +2 -0
  479. data/test/models/destroy_async_parent.rb +15 -0
  480. data/test/models/destroy_async_parent_soft_delete.rb +20 -0
  481. data/test/models/developer.rb +152 -85
  482. data/test/models/dl_keyed_belongs_to.rb +13 -0
  483. data/test/models/dl_keyed_belongs_to_soft_delete.rb +19 -0
  484. data/test/models/dl_keyed_has_many.rb +5 -0
  485. data/test/models/dl_keyed_has_many_through.rb +5 -0
  486. data/test/models/dl_keyed_has_one.rb +5 -0
  487. data/test/models/dl_keyed_join.rb +10 -0
  488. data/test/models/dog.rb +2 -0
  489. data/test/models/dog_lover.rb +2 -0
  490. data/test/models/doubloon.rb +3 -1
  491. data/test/models/drink_designer.rb +17 -0
  492. data/test/models/edge.rb +4 -2
  493. data/test/models/electron.rb +2 -0
  494. data/test/models/engine.rb +3 -2
  495. data/test/models/entrant.rb +2 -0
  496. data/test/models/entry.rb +5 -0
  497. data/test/models/essay.rb +6 -3
  498. data/test/models/essay_destroy_async.rb +12 -0
  499. data/test/models/event.rb +3 -1
  500. data/test/models/eye.rb +5 -3
  501. data/test/models/face.rb +14 -6
  502. data/test/models/family.rb +6 -0
  503. data/test/models/family_tree.rb +6 -0
  504. data/test/models/friendship.rb +5 -3
  505. data/test/models/frog.rb +8 -0
  506. data/test/models/guid.rb +3 -1
  507. data/test/models/guitar.rb +2 -0
  508. data/test/models/hotel.rb +5 -3
  509. data/test/models/human.rb +39 -0
  510. data/test/models/image.rb +3 -1
  511. data/test/models/interest.rb +14 -3
  512. data/test/models/invoice.rb +4 -2
  513. data/test/models/item.rb +3 -1
  514. data/test/models/job.rb +5 -3
  515. data/test/models/joke.rb +4 -2
  516. data/test/models/keyboard.rb +3 -1
  517. data/test/models/legacy_thing.rb +2 -0
  518. data/test/models/lesson.rb +2 -0
  519. data/test/models/line_item.rb +3 -1
  520. data/test/models/liquid.rb +2 -0
  521. data/test/models/matey.rb +3 -1
  522. data/test/models/measurement.rb +4 -0
  523. data/test/models/member.rb +23 -20
  524. data/test/models/member_detail.rb +3 -0
  525. data/test/models/member_type.rb +2 -0
  526. data/test/models/membership.rb +4 -1
  527. data/test/models/mentor.rb +3 -1
  528. data/test/models/message.rb +5 -0
  529. data/test/models/minimalistic.rb +2 -0
  530. data/test/models/minivan.rb +3 -2
  531. data/test/models/mixed_case_monkey.rb +3 -1
  532. data/test/models/molecule.rb +2 -0
  533. data/test/models/mouse.rb +6 -0
  534. data/test/models/movie.rb +2 -0
  535. data/test/models/node.rb +4 -2
  536. data/test/models/non_primary_key.rb +2 -0
  537. data/test/models/notification.rb +2 -0
  538. data/test/models/numeric_data.rb +12 -0
  539. data/test/models/order.rb +4 -2
  540. data/test/models/organization.rb +9 -7
  541. data/test/models/other_dog.rb +3 -1
  542. data/test/models/owner.rb +6 -4
  543. data/test/models/parrot.rb +12 -4
  544. data/test/models/person.rb +59 -54
  545. data/test/models/personal_legacy_thing.rb +3 -1
  546. data/test/models/pet.rb +4 -2
  547. data/test/models/pet_treasure.rb +2 -0
  548. data/test/models/pirate.rb +67 -43
  549. data/test/models/possession.rb +3 -1
  550. data/test/models/post.rb +184 -86
  551. data/test/models/price_estimate.rb +11 -1
  552. data/test/models/professor.rb +3 -1
  553. data/test/models/project.rb +14 -12
  554. data/test/models/publisher/article.rb +2 -0
  555. data/test/models/publisher/magazine.rb +2 -0
  556. data/test/models/publisher.rb +2 -0
  557. data/test/models/randomly_named_c1.rb +2 -0
  558. data/test/models/rating.rb +5 -1
  559. data/test/models/reader.rb +7 -5
  560. data/test/models/recipe.rb +2 -0
  561. data/test/models/record.rb +2 -0
  562. data/test/models/reference.rb +6 -3
  563. data/test/models/reply.rb +39 -21
  564. data/test/models/room.rb +6 -0
  565. data/test/models/section.rb +6 -0
  566. data/test/models/seminar.rb +6 -0
  567. data/test/models/session.rb +6 -0
  568. data/test/models/ship.rb +12 -9
  569. data/test/models/ship_part.rb +5 -3
  570. data/test/models/shop.rb +4 -2
  571. data/test/models/shop_account.rb +2 -0
  572. data/test/models/speedometer.rb +2 -0
  573. data/test/models/sponsor.rb +8 -5
  574. data/test/models/squeak.rb +6 -0
  575. data/test/models/strict_zine.rb +7 -0
  576. data/test/models/string_key_object.rb +2 -0
  577. data/test/models/student.rb +2 -0
  578. data/test/models/subscriber.rb +4 -2
  579. data/test/models/subscription.rb +5 -1
  580. data/test/models/tag.rb +6 -3
  581. data/test/models/tagging.rb +13 -6
  582. data/test/models/task.rb +2 -0
  583. data/test/models/topic.rb +54 -19
  584. data/test/models/toy.rb +4 -0
  585. data/test/models/traffic_light.rb +2 -0
  586. data/test/models/treasure.rb +5 -3
  587. data/test/models/treaty.rb +2 -4
  588. data/test/models/tree.rb +2 -0
  589. data/test/models/tuning_peg.rb +2 -0
  590. data/test/models/tyre.rb +2 -0
  591. data/test/models/user.rb +12 -4
  592. data/test/models/uuid_child.rb +2 -0
  593. data/test/models/uuid_item.rb +2 -0
  594. data/test/models/uuid_parent.rb +2 -0
  595. data/test/models/vegetables.rb +12 -3
  596. data/test/models/vertex.rb +6 -4
  597. data/test/models/warehouse_thing.rb +2 -0
  598. data/test/models/wheel.rb +3 -1
  599. data/test/models/without_table.rb +3 -1
  600. data/test/models/zine.rb +3 -1
  601. data/test/schema/mysql2_specific_schema.rb +49 -35
  602. data/test/schema/oracle_specific_schema.rb +13 -15
  603. data/test/schema/postgresql_specific_schema.rb +51 -40
  604. data/test/schema/schema.rb +334 -154
  605. data/test/schema/sqlite_specific_schema.rb +9 -16
  606. data/test/support/config.rb +26 -26
  607. data/test/support/connection.rb +14 -8
  608. data/test/support/connection_helper.rb +3 -1
  609. data/test/support/ddl_helper.rb +2 -0
  610. data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_6_0_topic.dump +0 -0
  611. data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_6_0_topic_associations.dump +0 -0
  612. data/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_0_topic.dump +0 -0
  613. data/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_0_topic_associations.dump +0 -0
  614. data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_0_topic.dump +0 -0
  615. data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_0_topic_associations.dump +0 -0
  616. data/test/support/marshal_compatibility_fixtures/SQLite/rails_6_0_topic.dump +0 -0
  617. data/test/support/marshal_compatibility_fixtures/SQLite/rails_6_0_topic_associations.dump +0 -0
  618. data/test/support/marshal_compatibility_fixtures/legacy_6_0_record_mysql.dump +0 -0
  619. data/test/support/marshal_compatibility_fixtures/legacy_relation.dump +0 -0
  620. data/test/support/schema_dumping_helper.rb +2 -0
  621. data/test/support/stubs/strong_parameters.rb +40 -0
  622. data/test/support/yaml_compatibility_fixtures/rails_v1_mysql.yml +206 -0
  623. data/test/support/yaml_compatibility_fixtures/rails_v2.yml +55 -0
  624. metadata +196 -11
@@ -0,0 +1,489 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/helper"
4
+ require "models/author"
5
+ require "models/book"
6
+ require "models/cart"
7
+ require "models/speedometer"
8
+ require "models/subscription"
9
+ require "models/subscriber"
10
+
11
+ class ReadonlyNameBook < Book
12
+ attr_readonly :name
13
+ end
14
+
15
+ class InsertAllTest < ActiveRecord::TestCase
16
+ fixtures :books
17
+
18
+ def setup
19
+ Arel::Table.engine = nil # should not rely on the global Arel::Table.engine
20
+ end
21
+
22
+ def teardown
23
+ Arel::Table.engine = ActiveRecord::Base
24
+ end
25
+
26
+ def test_insert
27
+ skip unless supports_insert_on_duplicate_skip?
28
+
29
+ id = 1_000_000
30
+
31
+ assert_difference "Book.count", +1 do
32
+ Book.insert({ id: id, name: "Rework", author_id: 1 })
33
+ end
34
+
35
+ Book.upsert({ id: id, name: "Remote", author_id: 1 })
36
+
37
+ assert_equal "Remote", Book.find(id).name
38
+ end
39
+
40
+ def test_insert!
41
+ assert_difference "Book.count", +1 do
42
+ Book.insert!({ name: "Rework", author_id: 1 })
43
+ end
44
+ end
45
+
46
+ def test_insert_all
47
+ assert_difference "Book.count", +10 do
48
+ Book.insert_all! [
49
+ { name: "Rework", author_id: 1 },
50
+ { name: "Patterns of Enterprise Application Architecture", author_id: 1 },
51
+ { name: "Design of Everyday Things", author_id: 1 },
52
+ { name: "Practical Object-Oriented Design in Ruby", author_id: 1 },
53
+ { name: "Clean Code", author_id: 1 },
54
+ { name: "Ruby Under a Microscope", author_id: 1 },
55
+ { name: "The Principles of Product Development Flow", author_id: 1 },
56
+ { name: "Peopleware", author_id: 1 },
57
+ { name: "About Face", author_id: 1 },
58
+ { name: "Eloquent Ruby", author_id: 1 },
59
+ ]
60
+ end
61
+ end
62
+
63
+ def test_insert_all_should_handle_empty_arrays
64
+ assert_raise ArgumentError do
65
+ Book.insert_all! []
66
+ end
67
+ end
68
+
69
+ def test_insert_all_raises_on_duplicate_records
70
+ assert_raise ActiveRecord::RecordNotUnique do
71
+ Book.insert_all! [
72
+ { name: "Rework", author_id: 1 },
73
+ { name: "Patterns of Enterprise Application Architecture", author_id: 1 },
74
+ { name: "Agile Web Development with Rails", author_id: 1 },
75
+ ]
76
+ end
77
+ end
78
+
79
+ def test_insert_all_returns_ActiveRecord_Result
80
+ result = Book.insert_all! [{ name: "Rework", author_id: 1 }]
81
+ assert_kind_of ActiveRecord::Result, result
82
+ end
83
+
84
+ def test_insert_all_returns_primary_key_if_returning_is_supported
85
+ skip unless supports_insert_returning?
86
+
87
+ result = Book.insert_all! [{ name: "Rework", author_id: 1 }]
88
+ assert_equal %w[ id ], result.columns
89
+ end
90
+
91
+ def test_insert_all_returns_nothing_if_returning_is_empty
92
+ skip unless supports_insert_returning?
93
+
94
+ result = Book.insert_all! [{ name: "Rework", author_id: 1 }], returning: []
95
+ assert_equal [], result.columns
96
+ end
97
+
98
+ def test_insert_all_returns_nothing_if_returning_is_false
99
+ skip unless supports_insert_returning?
100
+
101
+ result = Book.insert_all! [{ name: "Rework", author_id: 1 }], returning: false
102
+ assert_equal [], result.columns
103
+ end
104
+
105
+ def test_insert_all_returns_requested_fields
106
+ skip unless supports_insert_returning?
107
+
108
+ result = Book.insert_all! [{ name: "Rework", author_id: 1 }], returning: [:id, :name]
109
+ assert_equal %w[ Rework ], result.pluck("name")
110
+ end
111
+
112
+ def test_insert_all_can_skip_duplicate_records
113
+ skip unless supports_insert_on_duplicate_skip?
114
+
115
+ assert_no_difference "Book.count" do
116
+ Book.insert_all [{ id: 1, name: "Agile Web Development with Rails" }]
117
+ end
118
+ end
119
+
120
+ def test_insert_all_with_skip_duplicates_and_autonumber_id_not_given
121
+ skip unless supports_insert_on_duplicate_skip?
122
+
123
+ assert_difference "Book.count", 1 do
124
+ # These two books are duplicates according to an index on %i[author_id name]
125
+ # but their IDs are not specified so they will be assigned different IDs
126
+ # by autonumber. We will get an exception from MySQL if we attempt to skip
127
+ # one of these records by assigning its ID.
128
+ Book.insert_all [
129
+ { author_id: 8, name: "Refactoring" },
130
+ { author_id: 8, name: "Refactoring" }
131
+ ]
132
+ end
133
+ end
134
+
135
+ def test_insert_all_with_skip_duplicates_and_autonumber_id_given
136
+ skip unless supports_insert_on_duplicate_skip?
137
+
138
+ assert_difference "Book.count", 1 do
139
+ Book.insert_all [
140
+ { id: 200, author_id: 8, name: "Refactoring" },
141
+ { id: 201, author_id: 8, name: "Refactoring" }
142
+ ]
143
+ end
144
+ end
145
+
146
+ def test_skip_duplicates_strategy_does_not_secretly_upsert
147
+ skip unless supports_insert_on_duplicate_skip?
148
+
149
+ book = Book.create!(author_id: 8, name: "Refactoring", format: "EXPECTED")
150
+
151
+ assert_no_difference "Book.count" do
152
+ Book.insert({ author_id: 8, name: "Refactoring", format: "UNEXPECTED" })
153
+ end
154
+
155
+ assert_equal "EXPECTED", book.reload.format
156
+ end
157
+
158
+ def test_insert_all_will_raise_if_duplicates_are_skipped_only_for_a_certain_conflict_target
159
+ skip unless supports_insert_on_duplicate_skip? && supports_insert_conflict_target?
160
+
161
+ assert_raise ActiveRecord::RecordNotUnique do
162
+ Book.insert_all [{ id: 1, name: "Agile Web Development with Rails" }],
163
+ unique_by: :index_books_on_author_id_and_name
164
+ end
165
+ end
166
+
167
+ def test_insert_all_and_upsert_all_with_index_finding_options
168
+ skip unless supports_insert_conflict_target?
169
+
170
+ assert_difference "Book.count", +4 do
171
+ Book.insert_all [{ name: "Rework", author_id: 1 }], unique_by: :isbn
172
+ Book.insert_all [{ name: "Remote", author_id: 1 }], unique_by: %i( author_id name )
173
+ Book.insert_all [{ name: "Renote", author_id: 1 }], unique_by: :index_books_on_isbn
174
+ Book.insert_all [{ name: "Recoat", author_id: 1 }], unique_by: :id
175
+ end
176
+
177
+ assert_raise ActiveRecord::RecordNotUnique do
178
+ Book.upsert_all [{ name: "Rework", author_id: 1 }], unique_by: :isbn
179
+ end
180
+ end
181
+
182
+ def test_insert_all_and_upsert_all_with_expression_index
183
+ skip unless supports_expression_index? && supports_insert_conflict_target?
184
+
185
+ book = Book.create!(external_id: "abc")
186
+
187
+ assert_no_difference "Book.count" do
188
+ Book.insert_all [{ external_id: "ABC" }], unique_by: :index_books_on_lower_external_id
189
+ end
190
+
191
+ Book.upsert_all [{ external_id: "Abc" }], unique_by: :index_books_on_lower_external_id
192
+
193
+ assert_equal "Abc", book.reload.external_id
194
+ end
195
+
196
+ def test_insert_all_and_upsert_all_raises_when_index_is_missing
197
+ skip unless supports_insert_conflict_target?
198
+
199
+ [ :cats, %i( author_id isbn ), :author_id ].each do |missing_or_non_unique_by|
200
+ error = assert_raises ArgumentError do
201
+ Book.insert_all [{ name: "Rework", author_id: 1 }], unique_by: missing_or_non_unique_by
202
+ end
203
+ assert_match "No unique index", error.message
204
+
205
+ error = assert_raises ArgumentError do
206
+ Book.upsert_all [{ name: "Rework", author_id: 1 }], unique_by: missing_or_non_unique_by
207
+ end
208
+ assert_match "No unique index", error.message
209
+ end
210
+ end
211
+
212
+ def test_insert_all_and_upsert_all_works_with_composite_primary_keys_when_unique_by_is_provided
213
+ skip unless supports_insert_conflict_target?
214
+
215
+ assert_difference "Cart.count", 2 do
216
+ Cart.insert_all [{ id: 1, shop_id: 1, title: "My cart" }], unique_by: [:shop_id, :id]
217
+
218
+ Cart.upsert_all [{ id: 3, shop_id: 2, title: "My other cart" }], unique_by: [:shop_id, :id]
219
+ end
220
+
221
+ error = assert_raises ArgumentError do
222
+ Cart.insert_all! [{ id: 2, shop_id: 1, title: "My cart" }]
223
+ end
224
+ assert_match "No unique index found for id", error.message
225
+ end
226
+
227
+ def test_insert_all_and_upsert_all_works_with_composite_primary_keys_when_unique_by_is_not_provided
228
+ skip unless supports_insert_on_duplicate_skip? && !supports_insert_conflict_target?
229
+
230
+ assert_difference "Cart.count", 3 do
231
+ Cart.insert_all [{ id: 1, shop_id: 1, title: "My cart" }]
232
+
233
+ Cart.insert_all! [{ id: 2, shop_id: 1, title: "My cart 2" }]
234
+
235
+ Cart.upsert_all [{ id: 3, shop_id: 2, title: "My other cart" }]
236
+ end
237
+ end
238
+
239
+ def test_insert_logs_message_including_model_name
240
+ skip unless supports_insert_conflict_target?
241
+
242
+ capture_log_output do |output|
243
+ Book.insert({ name: "Rework", author_id: 1 })
244
+ assert_match "Book Insert", output.string
245
+ end
246
+ end
247
+
248
+ def test_insert_all_logs_message_including_model_name
249
+ skip unless supports_insert_conflict_target?
250
+
251
+ capture_log_output do |output|
252
+ Book.insert_all [{ name: "Remote", author_id: 1 }, { name: "Renote", author_id: 1 }]
253
+ assert_match "Book Bulk Insert", output.string
254
+ end
255
+ end
256
+
257
+ def test_upsert_logs_message_including_model_name
258
+ skip unless supports_insert_on_duplicate_update?
259
+
260
+ capture_log_output do |output|
261
+ Book.upsert({ name: "Remote", author_id: 1 })
262
+ assert_match "Book Upsert", output.string
263
+ end
264
+ end
265
+
266
+ def test_upsert_all_logs_message_including_model_name
267
+ skip unless supports_insert_on_duplicate_update?
268
+
269
+ capture_log_output do |output|
270
+ Book.upsert_all [{ name: "Remote", author_id: 1 }, { name: "Renote", author_id: 1 }]
271
+ assert_match "Book Bulk Upsert", output.string
272
+ end
273
+ end
274
+
275
+ def test_upsert_all_updates_existing_records
276
+ skip unless supports_insert_on_duplicate_update?
277
+
278
+ new_name = "Agile Web Development with Rails, 4th Edition"
279
+ Book.upsert_all [{ id: 1, name: new_name }]
280
+ assert_equal new_name, Book.find(1).name
281
+ end
282
+
283
+ def test_upsert_all_updates_existing_record_by_primary_key
284
+ skip unless supports_insert_conflict_target?
285
+
286
+ Book.upsert_all [{ id: 1, name: "New edition" }], unique_by: :id
287
+
288
+ assert_equal "New edition", Book.find(1).name
289
+ end
290
+
291
+ def test_upsert_all_does_notupdates_existing_record_by_when_there_is_no_key
292
+ skip unless supports_insert_on_duplicate_update? && !supports_insert_conflict_target?
293
+
294
+ Speedometer.create!(speedometer_id: "s3", name: "Very fast")
295
+
296
+ Speedometer.upsert_all [{ speedometer_id: "s3", name: "New Speedometer" }]
297
+
298
+ assert_equal "Very fast", Speedometer.find("s3").name
299
+ end
300
+
301
+ def test_upsert_all_updates_existing_record_by_configured_primary_key_fails_when_database_supports_insert_conflict_target
302
+ skip unless supports_insert_on_duplicate_update? && supports_insert_conflict_target?
303
+
304
+ error = assert_raises ArgumentError do
305
+ Speedometer.upsert_all [{ speedometer_id: "s1", name: "New Speedometer" }]
306
+ end
307
+ assert_match "No unique index found for speedometer_id", error.message
308
+ end
309
+
310
+ def test_upsert_all_does_not_update_readonly_attributes
311
+ skip unless supports_insert_on_duplicate_update?
312
+
313
+ new_name = "Agile Web Development with Rails, 4th Edition"
314
+ ReadonlyNameBook.upsert_all [{ id: 1, name: new_name }]
315
+ assert_not_equal new_name, Book.find(1).name
316
+ end
317
+
318
+ def test_upsert_all_does_not_update_primary_keys
319
+ skip unless supports_insert_on_duplicate_update? && supports_insert_conflict_target?
320
+
321
+ Book.upsert_all [{ id: 101, name: "Perelandra", author_id: 7 }]
322
+ Book.upsert_all [{ id: 103, name: "Perelandra", author_id: 7, isbn: "1974522598" }],
323
+ unique_by: :index_books_on_author_id_and_name
324
+
325
+ book = Book.find_by(name: "Perelandra")
326
+ assert_equal 101, book.id, "Should not have updated the ID"
327
+ assert_equal "1974522598", book.isbn, "Should have updated the isbn"
328
+ end
329
+
330
+ def test_upsert_all_does_not_perform_an_upsert_if_a_partial_index_doesnt_apply
331
+ skip unless supports_insert_on_duplicate_update? && supports_insert_conflict_target? && supports_partial_index?
332
+
333
+ Book.upsert_all [{ name: "Out of the Silent Planet", author_id: 7, isbn: "1974522598", published_on: Date.new(1938, 4, 1) }]
334
+ Book.upsert_all [{ name: "Perelandra", author_id: 7, isbn: "1974522598" }],
335
+ unique_by: :index_books_on_isbn
336
+
337
+ assert_equal ["Out of the Silent Planet", "Perelandra"], Book.where(isbn: "1974522598").order(:name).pluck(:name)
338
+ end
339
+
340
+ def test_upsert_all_does_not_touch_updated_at_when_values_do_not_change
341
+ skip unless supports_insert_on_duplicate_update?
342
+
343
+ updated_at = Time.now.utc - 5.years
344
+ Book.insert_all [{ id: 101, name: "Out of the Silent Planet", published_on: Date.new(1938, 4, 1), updated_at: updated_at }]
345
+ Book.upsert_all [{ id: 101, name: "Out of the Silent Planet", published_on: Date.new(1938, 4, 1) }]
346
+
347
+ assert_in_delta updated_at, Book.find(101).updated_at, 1
348
+ end
349
+
350
+ def test_upsert_all_touches_updated_at_and_updated_on_when_values_change
351
+ skip unless supports_insert_on_duplicate_update?
352
+
353
+ Book.insert_all [{ id: 101, name: "Out of the Silent Planet", published_on: Date.new(1938, 4, 1), updated_at: 5.years.ago, updated_on: 5.years.ago }]
354
+ Book.upsert_all [{ id: 101, name: "Out of the Silent Planet", published_on: Date.new(1938, 4, 8) }]
355
+
356
+ assert_equal Time.now.year, Book.find(101).updated_at.year
357
+ assert_equal Time.now.year, Book.find(101).updated_on.year
358
+ end
359
+
360
+ def test_upsert_all_uses_given_updated_at_over_implicit_updated_at
361
+ skip unless supports_insert_on_duplicate_update?
362
+
363
+ updated_at = Time.now.utc - 1.year
364
+ Book.insert_all [{ id: 101, name: "Out of the Silent Planet", published_on: Date.new(1938, 4, 1), updated_at: 5.years.ago }]
365
+ Book.upsert_all [{ id: 101, name: "Out of the Silent Planet", published_on: Date.new(1938, 4, 8), updated_at: updated_at }]
366
+
367
+ assert_in_delta updated_at, Book.find(101).updated_at, 1
368
+ end
369
+
370
+ def test_upsert_all_uses_given_updated_on_over_implicit_updated_on
371
+ skip unless supports_insert_on_duplicate_update?
372
+
373
+ updated_on = Time.now.utc.to_date - 30
374
+ Book.insert_all [{ id: 101, name: "Out of the Silent Planet", published_on: Date.new(1938, 4, 1), updated_on: 5.years.ago }]
375
+ Book.upsert_all [{ id: 101, name: "Out of the Silent Planet", published_on: Date.new(1938, 4, 8), updated_on: updated_on }]
376
+
377
+ assert_equal updated_on, Book.find(101).updated_on
378
+ end
379
+
380
+ def test_insert_all_raises_on_unknown_attribute
381
+ assert_raise ActiveRecord::UnknownAttributeError do
382
+ Book.insert_all! [{ unknown_attribute: "Test" }]
383
+ end
384
+ end
385
+
386
+ def test_upsert_all_works_with_partitioned_indexes
387
+ skip unless supports_insert_on_duplicate_update? && supports_insert_conflict_target? && supports_partitioned_indexes?
388
+
389
+ require "models/measurement"
390
+
391
+ Measurement.upsert_all([{ city_id: "1", logdate: 1.days.ago, peaktemp: 1, unitsales: 1 },
392
+ { city_id: "2", logdate: 2.days.ago, peaktemp: 2, unitsales: 2 },
393
+ { city_id: "2", logdate: 3.days.ago, peaktemp: 0, unitsales: 0 }],
394
+ unique_by: %i[logdate city_id])
395
+ assert_equal [[1.day.ago.to_date, 1, 1]],
396
+ Measurement.where(city_id: 1).pluck(:logdate, :peaktemp, :unitsales)
397
+ assert_equal [[2.days.ago.to_date, 2, 2], [3.days.ago.to_date, 0, 0]],
398
+ Measurement.where(city_id: 2).pluck(:logdate, :peaktemp, :unitsales)
399
+ end
400
+
401
+ def test_insert_all_with_enum_values
402
+ Book.insert_all! [{ status: :published, isbn: "1234566", name: "Rework", author_id: 1 },
403
+ { status: :proposed, isbn: "1234567", name: "Remote", author_id: 2 }]
404
+ assert_equal ["published", "proposed"], Book.where(isbn: ["1234566", "1234567"]).order(:id).pluck(:status)
405
+ end
406
+
407
+ def test_insert_all_on_relation
408
+ author = Author.create!(name: "Jimmy")
409
+
410
+ assert_difference "author.books.count", +1 do
411
+ author.books.insert_all!([{ name: "My little book", isbn: "1974522598" }])
412
+ end
413
+ end
414
+
415
+ def test_insert_all_on_relation_precedence
416
+ author = Author.create!(name: "Jimmy")
417
+ second_author = Author.create!(name: "Bob")
418
+
419
+ assert_difference "author.books.count", +1 do
420
+ author.books.insert_all!([{ name: "My little book", isbn: "1974522598", author_id: second_author.id }])
421
+ end
422
+ end
423
+
424
+ def test_insert_all_create_with
425
+ assert_difference "Book.where(format: 'X').count", +2 do
426
+ Book.create_with(format: "X").insert_all!([ { name: "A" }, { name: "B" } ])
427
+ end
428
+ end
429
+
430
+ def test_insert_all_has_many_through
431
+ book = Book.first
432
+ assert_raise(ArgumentError) { book.subscribers.insert_all!([ { nick: "Jimmy" } ]) }
433
+ end
434
+
435
+ def test_upsert_all_on_relation
436
+ skip unless supports_insert_on_duplicate_update?
437
+
438
+ author = Author.create!(name: "Jimmy")
439
+
440
+ assert_difference "author.books.count", +1 do
441
+ author.books.upsert_all([{ name: "My little book", isbn: "1974522598" }])
442
+ end
443
+ end
444
+
445
+ def test_upsert_all_on_relation_precedence
446
+ skip unless supports_insert_on_duplicate_update?
447
+
448
+ author = Author.create!(name: "Jimmy")
449
+ second_author = Author.create!(name: "Bob")
450
+
451
+ assert_difference "author.books.count", +1 do
452
+ author.books.upsert_all([{ name: "My little book", isbn: "1974522598", author_id: second_author.id }])
453
+ end
454
+ end
455
+
456
+ def test_upsert_all_create_with
457
+ skip unless supports_insert_on_duplicate_update?
458
+
459
+ assert_difference "Book.where(format: 'X').count", +2 do
460
+ Book.create_with(format: "X").upsert_all([ { name: "A" }, { name: "B" } ])
461
+ end
462
+ end
463
+
464
+ def test_upsert_all_has_many_through
465
+ book = Book.first
466
+ assert_raise(ArgumentError) { book.subscribers.upsert_all([ { nick: "Jimmy" } ]) }
467
+ end
468
+
469
+ def test_upsert_all_with_unique_by_fails_cleanly_for_adapters_not_supporting_insert_conflict_target
470
+ skip if supports_insert_conflict_target?
471
+
472
+ error = assert_raises ArgumentError do
473
+ Book.upsert_all [{ name: "Rework", author_id: 1 }], unique_by: :isbn
474
+ end
475
+ assert_match "#{ActiveRecord::Base.connection.class} does not support :unique_by", error.message
476
+ end
477
+
478
+ private
479
+ def capture_log_output
480
+ output = StringIO.new
481
+ old_logger, ActiveRecord::Base.logger = ActiveRecord::Base.logger, ActiveSupport::Logger.new(output)
482
+
483
+ begin
484
+ yield output
485
+ ensure
486
+ ActiveRecord::Base.logger = old_logger
487
+ end
488
+ end
489
+ end
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/helper"
4
+ require "models/book"
5
+
6
+ module ActiveRecord
7
+ class InstrumentationTest < ActiveRecord::TestCase
8
+ def setup
9
+ ActiveRecord::Base.connection.schema_cache.add(Book.table_name)
10
+ end
11
+
12
+ def test_payload_name_on_load
13
+ Book.create(name: "test book")
14
+ subscriber = ActiveSupport::Notifications.subscribe("sql.active_record") do |*args|
15
+ event = ActiveSupport::Notifications::Event.new(*args)
16
+ if event.payload[:sql].match "SELECT"
17
+ assert_equal "Book Load", event.payload[:name]
18
+ end
19
+ end
20
+ Book.first
21
+ ensure
22
+ ActiveSupport::Notifications.unsubscribe(subscriber) if subscriber
23
+ end
24
+
25
+ def test_payload_name_on_create
26
+ subscriber = ActiveSupport::Notifications.subscribe("sql.active_record") do |*args|
27
+ event = ActiveSupport::Notifications::Event.new(*args)
28
+ if event.payload[:sql].match "INSERT"
29
+ assert_equal "Book Create", event.payload[:name]
30
+ end
31
+ end
32
+ Book.create(name: "test book")
33
+ ensure
34
+ ActiveSupport::Notifications.unsubscribe(subscriber) if subscriber
35
+ end
36
+
37
+ def test_payload_name_on_update
38
+ subscriber = ActiveSupport::Notifications.subscribe("sql.active_record") do |*args|
39
+ event = ActiveSupport::Notifications::Event.new(*args)
40
+ if event.payload[:sql].match "UPDATE"
41
+ assert_equal "Book Update", event.payload[:name]
42
+ end
43
+ end
44
+ book = Book.create(name: "test book", format: "paperback")
45
+ book.update_attribute(:format, "ebook")
46
+ ensure
47
+ ActiveSupport::Notifications.unsubscribe(subscriber) if subscriber
48
+ end
49
+
50
+ def test_payload_name_on_update_all
51
+ subscriber = ActiveSupport::Notifications.subscribe("sql.active_record") do |*args|
52
+ event = ActiveSupport::Notifications::Event.new(*args)
53
+ if event.payload[:sql].match "UPDATE"
54
+ assert_equal "Book Update All", event.payload[:name]
55
+ end
56
+ end
57
+ Book.create(name: "test book", format: "paperback")
58
+ Book.update_all(format: "ebook")
59
+ ensure
60
+ ActiveSupport::Notifications.unsubscribe(subscriber) if subscriber
61
+ end
62
+
63
+ def test_payload_name_on_destroy
64
+ subscriber = ActiveSupport::Notifications.subscribe("sql.active_record") do |*args|
65
+ event = ActiveSupport::Notifications::Event.new(*args)
66
+ if event.payload[:sql].match "DELETE"
67
+ assert_equal "Book Destroy", event.payload[:name]
68
+ end
69
+ end
70
+ book = Book.create(name: "test book")
71
+ book.destroy
72
+ ensure
73
+ ActiveSupport::Notifications.unsubscribe(subscriber) if subscriber
74
+ end
75
+
76
+ def test_payload_connection_with_query_cache_disabled
77
+ connection = Book.connection
78
+ subscriber = ActiveSupport::Notifications.subscribe("sql.active_record") do |*args|
79
+ event = ActiveSupport::Notifications::Event.new(*args)
80
+ assert_equal connection, event.payload[:connection]
81
+ end
82
+ Book.first
83
+ ensure
84
+ ActiveSupport::Notifications.unsubscribe(subscriber) if subscriber
85
+ end
86
+
87
+ def test_payload_connection_with_query_cache_enabled
88
+ connection = Book.connection
89
+ subscriber = ActiveSupport::Notifications.subscribe("sql.active_record") do |*args|
90
+ event = ActiveSupport::Notifications::Event.new(*args)
91
+ assert_equal connection, event.payload[:connection]
92
+ end
93
+ Book.cache do
94
+ Book.first
95
+ Book.first
96
+ end
97
+ ensure
98
+ ActiveSupport::Notifications.unsubscribe(subscriber) if subscriber
99
+ end
100
+ end
101
+ end