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
@@ -1,20 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "cases/helper"
4
+ require "models/author"
4
5
  require "models/book"
6
+ require "models/clothing_item"
5
7
 
6
8
  module ActiveRecord
7
9
  class InstrumentationTest < ActiveRecord::TestCase
8
10
  def setup
9
- ActiveRecord::Base.connection.schema_cache.add(Book.table_name)
11
+ ActiveRecord::Base.schema_cache.add(Book.table_name)
10
12
  end
11
13
 
12
14
  def test_payload_name_on_load
13
15
  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]
16
+ subscriber = ActiveSupport::Notifications.subscribe("sql.active_record") do |_, _, _, _, payload|
17
+ if payload[:sql].match?("SELECT")
18
+ assert_equal "Book Load", payload[:name]
18
19
  end
19
20
  end
20
21
  Book.first
@@ -23,10 +24,9 @@ module ActiveRecord
23
24
  end
24
25
 
25
26
  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]
27
+ subscriber = ActiveSupport::Notifications.subscribe("sql.active_record") do |_, _, _, _, payload|
28
+ if payload[:sql].match?("INSERT")
29
+ assert_equal "Book Create", payload[:name]
30
30
  end
31
31
  end
32
32
  Book.create(name: "test book")
@@ -35,10 +35,9 @@ module ActiveRecord
35
35
  end
36
36
 
37
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]
38
+ subscriber = ActiveSupport::Notifications.subscribe("sql.active_record") do |_, _, _, _, payload|
39
+ if payload[:sql].match?("UPDATE")
40
+ assert_equal "Book Update", payload[:name]
42
41
  end
43
42
  end
44
43
  book = Book.create(name: "test book", format: "paperback")
@@ -48,23 +47,20 @@ module ActiveRecord
48
47
  end
49
48
 
50
49
  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]
50
+ subscriber = ActiveSupport::Notifications.subscribe("sql.active_record") do |_, _, _, _, payload|
51
+ if payload[:sql].match?("UPDATE")
52
+ assert_equal "Book Update All", payload[:name]
55
53
  end
56
54
  end
57
- Book.create(name: "test book", format: "paperback")
58
55
  Book.update_all(format: "ebook")
59
56
  ensure
60
57
  ActiveSupport::Notifications.unsubscribe(subscriber) if subscriber
61
58
  end
62
59
 
63
60
  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]
61
+ subscriber = ActiveSupport::Notifications.subscribe("sql.active_record") do |_, _, _, _, payload|
62
+ if payload[:sql].match?("DELETE")
63
+ assert_equal "Book Destroy", payload[:name]
68
64
  end
69
65
  end
70
66
  book = Book.create(name: "test book")
@@ -73,11 +69,122 @@ module ActiveRecord
73
69
  ActiveSupport::Notifications.unsubscribe(subscriber) if subscriber
74
70
  end
75
71
 
72
+ def test_payload_name_on_delete_all
73
+ subscriber = ActiveSupport::Notifications.subscribe("sql.active_record") do |_, _, _, _, payload|
74
+ if payload[:sql].match?("DELETE")
75
+ assert_equal "Book Delete All", payload[:name]
76
+ end
77
+ end
78
+ Book.delete_all
79
+ ensure
80
+ ActiveSupport::Notifications.unsubscribe(subscriber) if subscriber
81
+ end
82
+
83
+ def test_payload_name_on_pluck
84
+ subscriber = ActiveSupport::Notifications.subscribe("sql.active_record") do |_, _, _, _, payload|
85
+ if payload[:sql].match?("SELECT")
86
+ assert_equal "Book Pluck", payload[:name]
87
+ end
88
+ end
89
+ Book.pluck(:name)
90
+ ensure
91
+ ActiveSupport::Notifications.unsubscribe(subscriber) if subscriber
92
+ end
93
+
94
+ def test_payload_name_on_count
95
+ subscriber = ActiveSupport::Notifications.subscribe("sql.active_record") do |_, _, _, _, payload|
96
+ if payload[:sql].match?("SELECT")
97
+ assert_equal "Book Count", payload[:name]
98
+ end
99
+ end
100
+ Book.count
101
+ ensure
102
+ ActiveSupport::Notifications.unsubscribe(subscriber) if subscriber
103
+ end
104
+
105
+ def test_payload_name_on_grouped_count
106
+ subscriber = ActiveSupport::Notifications.subscribe("sql.active_record") do |_, _, _, _, payload|
107
+ if payload[:sql].match?("SELECT")
108
+ assert_equal "Book Count", payload[:name]
109
+ end
110
+ end
111
+ Book.group(:status).count
112
+ ensure
113
+ ActiveSupport::Notifications.unsubscribe(subscriber) if subscriber
114
+ end
115
+
116
+ def test_payload_row_count_on_select_all
117
+ # DB2 composite unique index (author_id, name) treats (NULL, 'row count book 1') as duplicate on 2nd insert
118
+ skip if current_adapter?(:IBM_DBAdapter)
119
+ 10.times { Book.create(name: "row count book 1") }
120
+ subscriber = ActiveSupport::Notifications.subscribe("sql.active_record") do |_, _, _, _, payload|
121
+ if payload[:sql].match?("SELECT")
122
+ assert_equal 10, payload[:row_count]
123
+ end
124
+ end
125
+ Book.where(name: "row count book 1").to_a
126
+ ensure
127
+ ActiveSupport::Notifications.unsubscribe(subscriber) if subscriber
128
+ end
129
+
130
+ def test_payload_row_count_on_pluck
131
+ # DB2 composite unique index (author_id, name) treats (NULL, 'row count book 2') as duplicate on 2nd insert
132
+ skip if current_adapter?(:IBM_DBAdapter)
133
+ 10.times { Book.create(name: "row count book 2") }
134
+ subscriber = ActiveSupport::Notifications.subscribe("sql.active_record") do |_, _, _, _, payload|
135
+ if payload[:sql].match?("SELECT")
136
+ assert_equal 10, payload[:row_count]
137
+ end
138
+ end
139
+ Book.where(name: "row count book 2").pluck(:name)
140
+ ensure
141
+ ActiveSupport::Notifications.unsubscribe(subscriber) if subscriber
142
+ end
143
+
144
+ def test_payload_row_count_on_raw_sql
145
+ # DB2 composite unique index (author_id, name) treats (NULL, 'row count book 3') as duplicate on 2nd insert
146
+ skip if current_adapter?(:IBM_DBAdapter)
147
+ 10.times { Book.create(name: "row count book 3") }
148
+ subscriber = ActiveSupport::Notifications.subscribe("sql.active_record") do |_, _, _, _, payload|
149
+ if payload[:sql].match?("SELECT")
150
+ assert_equal 10, payload[:row_count]
151
+ end
152
+ end
153
+ ActiveRecord::Base.lease_connection.execute("SELECT * FROM books WHERE name='row count book 3';")
154
+ ensure
155
+ ActiveSupport::Notifications.unsubscribe(subscriber) if subscriber
156
+ end
157
+
158
+ def test_payload_row_count_on_cache
159
+ # IBM_DB adapter logs row_count: 0 by default (no post-fetch notification update);
160
+ # skip since this is an adapter feature gap, not a DB2 incompatibility
161
+ skip if current_adapter?(:IBM_DBAdapter)
162
+ events = []
163
+ callback = -> (event) do
164
+ payload = event.payload
165
+ events << payload if payload[:sql].include?("SELECT")
166
+ end
167
+
168
+ Book.create!(name: "row count book")
169
+ ActiveSupport::Notifications.subscribed(callback, "sql.active_record") do
170
+ Book.cache do
171
+ Book.first
172
+ Book.first
173
+ end
174
+ end
175
+
176
+ assert_equal 2, events.size
177
+ assert_not events[0][:cached]
178
+ assert events[1][:cached]
179
+
180
+ assert_equal 1, events[0][:row_count]
181
+ assert_equal 1, events[1][:row_count]
182
+ end
183
+
76
184
  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]
185
+ connection = ClothingItem.lease_connection
186
+ subscriber = ActiveSupport::Notifications.subscribe("sql.active_record") do |_, _, _, _, payload|
187
+ assert_equal connection, payload[:connection]
81
188
  end
82
189
  Book.first
83
190
  ensure
@@ -85,10 +192,9 @@ module ActiveRecord
85
192
  end
86
193
 
87
194
  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]
195
+ connection = ClothingItem.lease_connection
196
+ subscriber = ActiveSupport::Notifications.subscribe("sql.active_record") do |_, _, _, _, payload|
197
+ assert_equal connection, payload[:connection]
92
198
  end
93
199
  Book.cache do
94
200
  Book.first
@@ -97,5 +203,71 @@ module ActiveRecord
97
203
  ensure
98
204
  ActiveSupport::Notifications.unsubscribe(subscriber) if subscriber
99
205
  end
206
+
207
+ def test_no_instantiation_notification_when_no_records
208
+ author = Author.create!(id: 100, name: "David")
209
+
210
+ called = false
211
+ subscriber = ActiveSupport::Notifications.subscribe("instantiation.active_record") do
212
+ called = true
213
+ end
214
+
215
+ Author.where(id: 0).to_a
216
+ author.books.to_a
217
+
218
+ assert_equal false, called
219
+ ensure
220
+ ActiveSupport::Notifications.unsubscribe(subscriber) if subscriber
221
+ end
222
+ end
223
+
224
+ module TransactionInSqlActiveRecordPayloadTests
225
+ def test_payload_without_an_open_transaction
226
+ asserted = false
227
+
228
+ subscriber = ActiveSupport::Notifications.subscribe("sql.active_record") do |event|
229
+ if event.payload.fetch(:name) == "Book Count"
230
+ assert_nil event.payload.fetch(:transaction)
231
+ asserted = true
232
+ end
233
+ end
234
+
235
+ Book.count
236
+
237
+ assert asserted
238
+ ensure
239
+ ActiveSupport::Notifications.unsubscribe(subscriber)
240
+ end
241
+
242
+ def test_payload_with_an_open_transaction
243
+ asserted = false
244
+ expected_transaction = nil
245
+
246
+ subscriber = ActiveSupport::Notifications.subscribe("sql.active_record") do |event|
247
+ if event.payload.fetch(:name) == "Book Count"
248
+ assert_same expected_transaction, event.payload.fetch(:transaction)
249
+ asserted = true
250
+ end
251
+ end
252
+
253
+ Book.transaction do |transaction|
254
+ expected_transaction = transaction
255
+ Book.count
256
+ end
257
+
258
+ assert asserted
259
+ ensure
260
+ ActiveSupport::Notifications.unsubscribe(subscriber)
261
+ end
262
+ end
263
+
264
+ class TransactionInSqlActiveRecordPayloadTest < ActiveRecord::TestCase
265
+ include TransactionInSqlActiveRecordPayloadTests
266
+ end
267
+
268
+ class TransactionInSqlActiveRecordPayloadNonTransactionalTest < ActiveRecord::TestCase
269
+ include TransactionInSqlActiveRecordPayloadTests
270
+
271
+ self.use_transactional_tests = false
100
272
  end
101
273
  end
@@ -6,6 +6,7 @@ require "models/developer"
6
6
  require "models/computer"
7
7
  require "models/owner"
8
8
  require "models/pet"
9
+ require "models/cpk"
9
10
 
10
11
  class IntegrationTest < ActiveRecord::TestCase
11
12
  fixtures :companies, :developers, :owners, :pets
@@ -97,6 +98,25 @@ class IntegrationTest < ActiveRecord::TestCase
97
98
  assert_equal "Firm", Firm.to_param
98
99
  end
99
100
 
101
+ def test_to_param_for_a_composite_primary_key_model
102
+ assert_equal "1_123", Cpk::Order.new(id: [1, 123]).to_param
103
+ end
104
+
105
+ def test_param_delimiter_changes_delimiter_used_in_to_param
106
+ Cpk::Order.stub(:param_delimiter, ",") do
107
+ assert_equal("1,123", Cpk::Order.new(id: [1, 123]).to_param)
108
+ end
109
+ end
110
+
111
+ def test_param_delimiter_is_defined_per_class
112
+ Cpk::Order.stub(:param_delimiter, ",") do
113
+ Cpk::Book.stub(:param_delimiter, ";") do
114
+ assert_equal("1,123", Cpk::Order.new(id: [1, 123]).to_param)
115
+ assert_equal("1;123", Cpk::Book.new(id: [1, 123]).to_param)
116
+ end
117
+ end
118
+ end
119
+
100
120
  def test_cache_key_for_existing_record_is_not_timezone_dependent
101
121
  utc_key = Developer.first.cache_key
102
122
 
@@ -108,12 +128,12 @@ class IntegrationTest < ActiveRecord::TestCase
108
128
 
109
129
  def test_cache_key_format_for_existing_record_with_updated_at
110
130
  dev = Developer.first
111
- assert_equal "developers/#{dev.id}-#{dev.updated_at.utc.to_s(:usec)}", dev.cache_key
131
+ assert_equal "developers/#{dev.id}-#{dev.updated_at.utc.to_fs(:usec)}", dev.cache_key
112
132
  end
113
133
 
114
134
  def test_cache_key_format_for_existing_record_with_updated_at_and_custom_cache_timestamp_format
115
135
  dev = CachedDeveloper.first
116
- assert_equal "cached_developers/#{dev.id}-#{dev.updated_at.utc.to_s(:number)}", dev.cache_key
136
+ assert_equal "cached_developers/#{dev.id}-#{dev.updated_at.utc.to_fs(:number)}", dev.cache_key
117
137
  end
118
138
 
119
139
  def test_cache_key_changes_when_child_touched
@@ -138,23 +158,22 @@ class IntegrationTest < ActiveRecord::TestCase
138
158
  def test_cache_key_for_updated_on
139
159
  dev = Developer.first
140
160
  dev.updated_at = nil
141
- assert_equal "developers/#{dev.id}-#{dev.updated_on.utc.to_s(:usec)}", dev.cache_key
161
+ assert_equal "developers/#{dev.id}-#{dev.updated_on.utc.to_fs(:usec)}", dev.cache_key
142
162
  end
143
163
 
144
164
  def test_cache_key_for_newer_updated_at
145
165
  dev = Developer.first
146
166
  dev.updated_at += 3600
147
- assert_equal "developers/#{dev.id}-#{dev.updated_at.utc.to_s(:usec)}", dev.cache_key
167
+ assert_equal "developers/#{dev.id}-#{dev.updated_at.utc.to_fs(:usec)}", dev.cache_key
148
168
  end
149
169
 
150
170
  def test_cache_key_for_newer_updated_on
151
171
  dev = Developer.first
152
172
  dev.updated_on += 3600
153
- assert_equal "developers/#{dev.id}-#{dev.updated_on.utc.to_s(:usec)}", dev.cache_key
173
+ assert_equal "developers/#{dev.id}-#{dev.updated_on.utc.to_fs(:usec)}", dev.cache_key
154
174
  end
155
175
 
156
176
  def test_cache_key_format_is_precise_enough
157
- skip("Subsecond precision is not supported") unless supports_datetime_with_precision?
158
177
  dev = Developer.first
159
178
  key = dev.cache_key
160
179
  travel_to dev.updated_at + 0.000001 do
@@ -171,7 +190,6 @@ class IntegrationTest < ActiveRecord::TestCase
171
190
  end
172
191
 
173
192
  def test_cache_version_format_is_precise_enough
174
- skip("Subsecond precision is not supported") unless supports_datetime_with_precision?
175
193
  with_cache_versioning do
176
194
  dev = Developer.first
177
195
  version = dev.cache_version.to_param
@@ -2,17 +2,17 @@
2
2
 
3
3
  require "cases/helper"
4
4
 
5
- if current_adapter?(:Mysql2Adapter) or current_adapter?(:IBM_DBAdapter)
6
- class TestAdapterWithInvalidConnection < ActiveRecord::TestCase
7
- self.use_transactional_tests = false
5
+ class TestAdapterWithInvalidConnection < ActiveRecord::TestCase
6
+ self.use_transactional_tests = false
8
7
 
8
+ if current_adapter?(:Mysql2Adapter, :TrilogyAdapter)
9
9
  class Bird < ActiveRecord::Base
10
10
  end
11
11
 
12
12
  def setup
13
13
  # Can't just use current adapter; sqlite3 will create a database
14
14
  # file on the fly.
15
- Bird.establish_connection adapter: "ibm_db", database: "i_do_not_exist"
15
+ Bird.establish_connection adapter: ARTest.connection_name, database: "i_do_not_exist", host: "127.0.0.1", port: 12, username: "invalid"
16
16
  end
17
17
 
18
18
  teardown do
@@ -20,7 +20,7 @@ if current_adapter?(:Mysql2Adapter) or current_adapter?(:IBM_DBAdapter)
20
20
  end
21
21
 
22
22
  test "inspect on Model class does not raise" do
23
- assert_equal "#{Bird.name} (call '#{Bird.name}.connection' to establish a connection)", Bird.inspect
23
+ assert_equal "#{Bird.name} (call '#{Bird.name}.load_schema' to load schema informations)", Bird.inspect
24
24
  end
25
25
  end
26
26
  end
@@ -19,6 +19,7 @@ module ActiveRecord
19
19
  t.column :content, :text
20
20
  t.column :remind_at, :datetime
21
21
  t.column :place_id, :integer
22
+ t.column :parent_id, :bigint
22
23
  end
23
24
  end
24
25
  end
@@ -96,7 +97,7 @@ module ActiveRecord
96
97
  def change
97
98
  change_table("horses") do |t|
98
99
  t.remove_index [:name, :color]
99
- t.remove_index [:color], if_exists: true
100
+ t.remove_index [:color] if t.index_exists?(:color)
100
101
  end
101
102
  end
102
103
  end
@@ -149,7 +150,15 @@ module ActiveRecord
149
150
 
150
151
  class DisableExtension2 < SilentMigration
151
152
  def change
152
- disable_extension "hstore"
153
+ disable_extension "hstore", force: :cascade
154
+ end
155
+ end
156
+
157
+ class DropTableMigration < SilentMigration
158
+ def change
159
+ drop_table("horses") do |t|
160
+ t.string :name
161
+ end
153
162
  end
154
163
  end
155
164
 
@@ -220,6 +229,24 @@ module ActiveRecord
220
229
  end
221
230
  end
222
231
 
232
+ class RevertUniqueConstraintWithInvalidOption < SilentMigration
233
+ def change
234
+ add_unique_constraint :horses, :place_id, invalid: :option
235
+ end
236
+ end
237
+
238
+ class RevertForeignKeyWithInvalidOption < SilentMigration
239
+ def change
240
+ add_foreign_key :horses, :horses, column: :parent_id, invalid: :option
241
+ end
242
+ end
243
+
244
+ class RevertCheckConstraintWithInvalidOption < SilentMigration
245
+ def change
246
+ add_check_constraint :horses, "place_id > 0", invalid: :option
247
+ end
248
+ end
249
+
223
250
  self.use_transactional_tests = false
224
251
 
225
252
  setup do
@@ -228,8 +255,8 @@ module ActiveRecord
228
255
 
229
256
  teardown do
230
257
  %w[horses new_horses].each do |table|
231
- if ActiveRecord::Base.connection.table_exists?(table)
232
- ActiveRecord::Base.connection.drop_table(table)
258
+ if ActiveRecord::Base.lease_connection.table_exists?(table)
259
+ ActiveRecord::Base.lease_connection.drop_table(table)
233
260
  end
234
261
  end
235
262
  ActiveRecord::Migration.verbose = @verbose_was
@@ -356,7 +383,7 @@ module ActiveRecord
356
383
  assert_equal "Sekitoba", Horse.new.name
357
384
  end
358
385
 
359
- if ActiveRecord::Base.connection.supports_comments?
386
+ if ActiveRecord::Base.lease_connection.supports_comments?
360
387
  def test_migrate_revert_change_column_comment
361
388
  migration1 = ChangeColumnComment1.new
362
389
  migration1.migrate(:up)
@@ -374,7 +401,7 @@ module ActiveRecord
374
401
  end
375
402
 
376
403
  def test_migrate_revert_change_table_comment
377
- connection = ActiveRecord::Base.connection
404
+ connection = ActiveRecord::Base.lease_connection
378
405
  migration1 = ChangeTableComment1.new
379
406
  migration1.migrate(:up)
380
407
  assert_equal "Sekitoba", connection.table_comment("horses")
@@ -390,32 +417,48 @@ module ActiveRecord
390
417
 
391
418
  if current_adapter?(:PostgreSQLAdapter)
392
419
  def test_migrate_enable_and_disable_extension
420
+ connection = Horse.lease_connection
393
421
  migration1 = InvertibleMigration.new
394
422
  migration2 = DisableExtension1.new
395
423
  migration3 = DisableExtension2.new
396
424
 
397
- assert_equal true, Horse.connection.extension_available?("hstore")
425
+ assert_equal true, connection.extension_available?("hstore")
398
426
 
399
427
  migration1.migrate(:up)
400
428
  migration2.migrate(:up)
401
- assert_equal true, Horse.connection.extension_enabled?("hstore")
429
+ assert_equal true, connection.extension_enabled?("hstore")
402
430
 
403
431
  migration3.migrate(:up)
404
- assert_equal false, Horse.connection.extension_enabled?("hstore")
432
+ assert_equal false, connection.extension_enabled?("hstore")
405
433
 
406
434
  migration3.migrate(:down)
407
- assert_equal true, Horse.connection.extension_enabled?("hstore")
435
+ assert_equal true, connection.extension_enabled?("hstore")
408
436
 
409
437
  migration2.migrate(:down)
410
- assert_equal false, Horse.connection.extension_enabled?("hstore")
438
+ assert_equal false, connection.extension_enabled?("hstore")
411
439
  ensure
412
- enable_extension!("hstore", ActiveRecord::Base.connection)
440
+ enable_extension!("hstore", ActiveRecord::Base.lease_connection)
413
441
  end
414
442
  end
415
443
 
444
+ def test_migrate_revert_drop_table
445
+ skip if current_adapter?(:IBM_DBAdapter) # Ruby 4.0: invert_drop_table pushes {} as positional arg; create_table(table_name, **options) rejects 2 positional args
446
+ connection = ActiveRecord::Base.lease_connection
447
+ migration1 = InvertibleMigration.new
448
+ migration1.migrate(:up)
449
+ assert connection.table_exists?("horses")
450
+
451
+ migration2 = DropTableMigration.new
452
+ migration2.migrate(:up)
453
+ assert_not connection.table_exists?("horses")
454
+
455
+ migration2.migrate(:down)
456
+ assert connection.table_exists?("horses")
457
+ end
458
+
416
459
  def test_revert_order
417
460
  block = Proc.new { |t| t.string :name }
418
- recorder = ActiveRecord::Migration::CommandRecorder.new(ActiveRecord::Base.connection)
461
+ recorder = ActiveRecord::Migration::CommandRecorder.new(ActiveRecord::Base.lease_connection)
419
462
  recorder.instance_eval do
420
463
  create_table("apples", &block)
421
464
  revert do
@@ -439,24 +482,24 @@ module ActiveRecord
439
482
 
440
483
  def test_legacy_up
441
484
  LegacyMigration.migrate :up
442
- assert ActiveRecord::Base.connection.table_exists?("horses"), "horses should exist"
485
+ assert ActiveRecord::Base.lease_connection.table_exists?("horses"), "horses should exist"
443
486
  end
444
487
 
445
488
  def test_legacy_down
446
489
  LegacyMigration.migrate :up
447
490
  LegacyMigration.migrate :down
448
- assert_not ActiveRecord::Base.connection.table_exists?("horses"), "horses should not exist"
491
+ assert_not ActiveRecord::Base.lease_connection.table_exists?("horses"), "horses should not exist"
449
492
  end
450
493
 
451
494
  def test_up
452
495
  LegacyMigration.up
453
- assert ActiveRecord::Base.connection.table_exists?("horses"), "horses should exist"
496
+ assert ActiveRecord::Base.lease_connection.table_exists?("horses"), "horses should exist"
454
497
  end
455
498
 
456
499
  def test_down
457
500
  LegacyMigration.up
458
501
  LegacyMigration.down
459
- assert_not ActiveRecord::Base.connection.table_exists?("horses"), "horses should not exist"
502
+ assert_not ActiveRecord::Base.lease_connection.table_exists?("horses"), "horses should not exist"
460
503
  end
461
504
 
462
505
  def test_migrate_down_with_table_name_prefix
@@ -465,7 +508,7 @@ module ActiveRecord
465
508
  migration = InvertibleMigration.new
466
509
  migration.migrate(:up)
467
510
  assert_nothing_raised { migration.migrate(:down) }
468
- assert_not ActiveRecord::Base.connection.table_exists?("p_horses_s"), "p_horses_s should not exist"
511
+ assert_not ActiveRecord::Base.lease_connection.table_exists?("p_horses_s"), "p_horses_s should not exist"
469
512
  ensure
470
513
  ActiveRecord::Base.table_name_prefix = ActiveRecord::Base.table_name_suffix = ""
471
514
  end
@@ -474,17 +517,20 @@ module ActiveRecord
474
517
  migration = RevertCustomForeignKeyTable.new
475
518
  InvertibleMigration.migrate(:up)
476
519
  migration.migrate(:up)
520
+ assert ActiveRecord::Base.lease_connection.column_exists?(:horses, :owner_id)
477
521
  migration.migrate(:down)
522
+ assert_not ActiveRecord::Base.lease_connection.column_exists?(:horses, :owner_id)
478
523
  end
479
524
 
480
525
  # MySQL 5.7 and Oracle do not allow to create duplicate indexes on the same columns
481
- unless current_adapter?(:Mysql2Adapter, :OracleAdapter, :IBM_DBAdapter)
526
+ # IBM_DB/DB2 also raises SQL0605W when a duplicate matching index exists
527
+ unless current_adapter?(:Mysql2Adapter, :TrilogyAdapter, :IBM_DBAdapter)
482
528
  def test_migrate_revert_add_index_with_name
483
529
  RevertNamedIndexMigration1.new.migrate(:up)
484
530
  RevertNamedIndexMigration2.new.migrate(:up)
485
531
  RevertNamedIndexMigration2.new.migrate(:down)
486
532
 
487
- connection = ActiveRecord::Base.connection
533
+ connection = ActiveRecord::Base.lease_connection
488
534
  assert connection.index_exists?(:horses, :content),
489
535
  "index on content should exist"
490
536
  assert_not connection.index_exists?(:horses, :content, name: "horses_index_named"),
@@ -496,7 +542,7 @@ module ActiveRecord
496
542
  InvertibleMigration.new.migrate(:up)
497
543
  RevertNonNamedExpressionIndexMigration.new.migrate(:up)
498
544
 
499
- connection = ActiveRecord::Base.connection
545
+ connection = ActiveRecord::Base.lease_connection
500
546
  assert connection.index_exists?(:horses, [:remind_at, :place_id]),
501
547
  "index on remind_at and place_id should exist"
502
548
 
@@ -515,13 +561,51 @@ module ActiveRecord
515
561
  horse1.reload
516
562
  horse2 = Horse.create
517
563
 
518
- assert 1, horse1.oldie # created before migration
519
- assert 0, horse2.oldie # created after migration
564
+ assert_equal 1, horse1.oldie # created before migration
565
+ assert_equal 0, horse2.oldie # created after migration
520
566
 
521
567
  UpOnlyMigration.new.migrate(:down) # should be no error
522
- connection = ActiveRecord::Base.connection
568
+ connection = ActiveRecord::Base.lease_connection
523
569
  assert_not connection.column_exists?(:horses, :oldie)
524
570
  Horse.reset_column_information
525
571
  end
572
+
573
+ if ActiveRecord::Base.lease_connection.supports_unique_constraints?
574
+ def test_migrate_revert_add_unique_constraint_with_invalid_option
575
+ skip if current_adapter?(:IBM_DBAdapter) # DB2 SQL0542N: unique constraint columns must be NOT NULL
576
+ InvertibleMigration.new.migrate(:up)
577
+ RevertUniqueConstraintWithInvalidOption.new.migrate(:up)
578
+
579
+ connection = ActiveRecord::Base.lease_connection
580
+ assert_equal 1, connection.unique_constraints(:horses).count
581
+
582
+ RevertUniqueConstraintWithInvalidOption.new.migrate(:down)
583
+ assert_empty connection.unique_constraints(:horses)
584
+ end
585
+ end
586
+
587
+ def test_migrate_revert_add_foreign_key_with_invalid_option
588
+ InvertibleMigration.new.migrate(:up)
589
+ RevertForeignKeyWithInvalidOption.new.migrate(:up)
590
+
591
+ connection = ActiveRecord::Base.lease_connection
592
+ assert_equal 1, connection.foreign_keys(:horses).count
593
+
594
+ RevertForeignKeyWithInvalidOption.new.migrate(:down)
595
+ assert_empty connection.foreign_keys(:horses)
596
+ end
597
+
598
+ if ActiveRecord::Base.lease_connection.supports_check_constraints?
599
+ def test_migrate_revert_add_check_constraint_with_invalid_option
600
+ InvertibleMigration.new.migrate(:up)
601
+ RevertCheckConstraintWithInvalidOption.new.migrate(:up)
602
+
603
+ connection = ActiveRecord::Base.lease_connection
604
+ assert_equal 1, connection.check_constraints(:horses).count
605
+
606
+ RevertCheckConstraintWithInvalidOption.new.migrate(:down)
607
+ assert_empty connection.check_constraints(:horses)
608
+ end
609
+ end
526
610
  end
527
611
  end
@@ -18,6 +18,7 @@ class JsonAttributeTest < ActiveRecord::TestCase
18
18
 
19
19
  def setup
20
20
  super
21
+ @connection.drop_table("json_data_type", if_exists: true)
21
22
  @connection.create_table("json_data_type") do |t|
22
23
  t.string "payload"
23
24
  t.string "settings"