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
@@ -10,14 +10,14 @@ require "models/event"
10
10
  module ActiveRecord
11
11
  class AdapterTest < ActiveRecord::TestCase
12
12
  def setup
13
- @connection = ActiveRecord::Base.connection
13
+ @connection = ActiveRecord::Base.lease_connection
14
14
  @connection.materialize_transactions
15
15
  end
16
16
 
17
17
  ##
18
18
  # PostgreSQL does not support null bytes in strings
19
19
  unless current_adapter?(:PostgreSQLAdapter) ||
20
- (current_adapter?(:SQLite3Adapter) && !ActiveRecord::Base.connection.prepared_statements)
20
+ (current_adapter?(:SQLite3Adapter) && !ActiveRecord::Base.lease_connection.prepared_statements)
21
21
  def test_update_prepared_statement
22
22
  b = Book.create(name: "my \x00 book")
23
23
  b.reload
@@ -92,6 +92,10 @@ module ActiveRecord
92
92
  @connection.remove_index(:accounts, name: idx_name) rescue nil
93
93
  end
94
94
 
95
+ def test_returns_empty_indexes_for_non_existing_table
96
+ assert_equal [], @connection.indexes("nonexistingtable")
97
+ end
98
+
95
99
  def test_remove_index_when_name_and_wrong_column_name_specified
96
100
  index_name = "accounts_idx"
97
101
 
@@ -117,15 +121,26 @@ module ActiveRecord
117
121
  def test_current_database
118
122
  if @connection.respond_to?(:current_database)
119
123
  assert_equal ARTest.test_configuration_hashes["arunit"]["database"], @connection.current_database
124
+ else
125
+ skip
120
126
  end
121
127
  end
122
128
 
123
- def test_exec_query_returns_an_empty_result
129
+ test "#exec_query queries with no result set return an empty ActiveRecord::Result" do
124
130
  result = @connection.exec_query "INSERT INTO subscribers(nick) VALUES('me')"
125
131
  assert_instance_of(ActiveRecord::Result, result)
132
+ assert_empty result.rows
133
+ assert_empty result.columns
134
+ end
135
+
136
+ test "#exec_query queries with an empty result set still return the columns" do
137
+ result = @connection.exec_query "SELECT * FROM subscribers WHERE 1=0"
138
+ assert_instance_of(ActiveRecord::Result, result)
139
+ assert_empty result.rows
140
+ assert_not_empty result.columns
126
141
  end
127
142
 
128
- if current_adapter?(:Mysql2Adapter)
143
+ if current_adapter?(:Mysql2Adapter, :TrilogyAdapter)
129
144
  def test_charset
130
145
  assert_not_nil @connection.charset
131
146
  assert_not_equal "character_set_database", @connection.charset
@@ -148,7 +163,7 @@ module ActiveRecord
148
163
  ActiveRecord::Base.establish_connection(db_config.configuration_hash.except(:database))
149
164
 
150
165
  config = ARTest.test_configuration_hashes
151
- ActiveRecord::Base.connection.execute(
166
+ ActiveRecord::Base.lease_connection.execute(
152
167
  "SELECT #{config['arunit']['database']}.pirates.*, #{config['arunit2']['database']}.courses.* " \
153
168
  "FROM #{config['arunit']['database']}.pirates, #{config['arunit2']['database']}.courses"
154
169
  )
@@ -158,6 +173,23 @@ module ActiveRecord
158
173
  end
159
174
  end
160
175
 
176
+ unless in_memory_db? || current_adapter?(:TrilogyAdapter)
177
+ def test_disable_prepared_statements
178
+ original_prepared_statements = ActiveRecord.disable_prepared_statements
179
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: "arunit", name: "primary")
180
+ ActiveRecord::Base.establish_connection(db_config.configuration_hash.merge(prepared_statements: true))
181
+
182
+ assert_predicate ActiveRecord::Base.lease_connection, :prepared_statements?
183
+
184
+ ActiveRecord.disable_prepared_statements = true
185
+ ActiveRecord::Base.establish_connection(db_config.configuration_hash.merge(prepared_statements: true))
186
+ assert_not_predicate ActiveRecord::Base.lease_connection, :prepared_statements?
187
+ ensure
188
+ ActiveRecord.disable_prepared_statements = original_prepared_statements
189
+ ActiveRecord::Base.establish_connection :arunit
190
+ end
191
+ end
192
+
161
193
  def test_table_alias
162
194
  def @connection.test_table_alias_length() 10; end
163
195
  class << @connection
@@ -203,7 +235,7 @@ module ActiveRecord
203
235
 
204
236
  def test_numeric_value_out_of_ranges_are_translated_to_specific_exception
205
237
  error = assert_raises(ActiveRecord::RangeError) do
206
- Book.connection.create("INSERT INTO books(author_id) VALUES (9223372036854775808)")
238
+ Book.lease_connection.create("INSERT INTO books(author_id) VALUES (9223372036854775808)")
207
239
  end
208
240
 
209
241
  assert_not_nil error.cause
@@ -216,7 +248,6 @@ module ActiveRecord
216
248
  actual_error = assert_raises(StandardError) do
217
249
  @connection.execute("SELECT * FROM posts")
218
250
  end
219
-
220
251
  assert_equal original_error, actual_error
221
252
 
222
253
  ensure
@@ -237,37 +268,7 @@ module ActiveRecord
237
268
  assert result.is_a?(ActiveRecord::Result)
238
269
  end
239
270
 
240
- if ActiveRecord::Base.connection.prepared_statements
241
- def test_select_all_insert_update_delete_with_legacy_binds
242
- binds = [[Event.column_for_attribute("id"), 1]]
243
- bind_param = Arel::Nodes::BindParam.new(nil)
244
-
245
- assert_deprecated do
246
- id = @connection.insert("INSERT INTO events(id) VALUES (#{bind_param.to_sql})", nil, nil, nil, nil, binds)
247
- assert_equal 1, id
248
- end
249
-
250
- assert_deprecated do
251
- updated = @connection.update("UPDATE events SET title = 'foo' WHERE id = #{bind_param.to_sql}", nil, binds)
252
- assert_equal 1, updated
253
- end
254
-
255
- assert_deprecated do
256
- result = @connection.select_all("SELECT * FROM events WHERE id = #{bind_param.to_sql}", nil, binds)
257
- assert_equal({ "id" => 1, "title" => "foo" }, result.first)
258
- end
259
-
260
- assert_deprecated do
261
- deleted = @connection.delete("DELETE FROM events WHERE id = #{bind_param.to_sql}", nil, binds)
262
- assert_equal 1, deleted
263
- end
264
-
265
- assert_deprecated do
266
- result = @connection.select_all("SELECT * FROM events WHERE id = #{bind_param.to_sql}", nil, binds)
267
- assert_nil result.first
268
- end
269
- end
270
-
271
+ if ActiveRecord::Base.lease_connection.prepared_statements
271
272
  def test_select_all_insert_update_delete_with_casted_binds
272
273
  binds = [Event.type_for_attribute("id").serialize(1)]
273
274
  bind_param = Arel::Nodes::BindParam.new(nil)
@@ -332,14 +333,10 @@ module ActiveRecord
332
333
  assert_equal "special_db_type", @connection.type_to_sql(:special_db_type)
333
334
  end
334
335
 
335
- def test_allowed_index_name_length_is_deprecated
336
- assert_deprecated { @connection.allowed_index_name_length }
337
- end
336
+ test "inspect does not show secrets" do
337
+ output = @connection.inspect
338
338
 
339
- unless current_adapter?(:OracleAdapter)
340
- def test_in_clause_length_is_deprecated
341
- assert_deprecated { @connection.in_clause_length }
342
- end
339
+ assert_match(/ActiveRecord::ConnectionAdapters::\w+:0x[\da-f]+ env_name="\w+" role=:writing>/, output)
343
340
  end
344
341
  end
345
342
 
@@ -349,7 +346,7 @@ module ActiveRecord
349
346
  fixtures :fk_test_has_pk
350
347
 
351
348
  def setup
352
- @connection = ActiveRecord::Base.connection
349
+ @connection = ActiveRecord::Base.lease_connection
353
350
  end
354
351
 
355
352
  def test_foreign_key_violations_are_translated_to_specific_exception_with_validate_false
@@ -413,33 +410,7 @@ module ActiveRecord
413
410
  fixtures :posts, :authors, :author_addresses
414
411
 
415
412
  def setup
416
- @connection = ActiveRecord::Base.connection
417
- end
418
-
419
- unless in_memory_db?
420
- test "reconnect after a disconnect" do
421
- assert_predicate @connection, :active?
422
- @connection.disconnect!
423
- assert_not_predicate @connection, :active?
424
- @connection.reconnect!
425
- assert_predicate @connection, :active?
426
- end
427
-
428
- test "transaction state is reset after a reconnect" do
429
- @connection.begin_transaction
430
- assert_predicate @connection, :transaction_open?
431
- @connection.reconnect!
432
- assert_not_predicate @connection, :transaction_open?
433
- end
434
-
435
- test "transaction state is reset after a disconnect" do
436
- @connection.begin_transaction
437
- assert_predicate @connection, :transaction_open?
438
- @connection.disconnect!
439
- assert_not_predicate @connection, :transaction_open?
440
- ensure
441
- @connection.reconnect!
442
- end
413
+ @connection = ActiveRecord::Base.lease_connection
443
414
  end
444
415
 
445
416
  def test_create_with_query_cache
@@ -510,19 +481,19 @@ module ActiveRecord
510
481
  end
511
482
 
512
483
  # test resetting sequences in odd tables in PostgreSQL
513
- if ActiveRecord::Base.connection.respond_to?(:reset_pk_sequence!)
484
+ if ActiveRecord::Base.lease_connection.respond_to?(:reset_pk_sequence!)
514
485
  require "models/movie"
515
486
  require "models/subscriber"
516
487
 
517
488
  def test_reset_empty_table_with_custom_pk
518
489
  Movie.delete_all
519
- Movie.connection.reset_pk_sequence! "movies"
490
+ Movie.lease_connection.reset_pk_sequence! "movies"
520
491
  assert_equal 1, Movie.create(name: "fight club").id
521
492
  end
522
493
 
523
494
  def test_reset_table_with_non_integer_pk
524
495
  Subscriber.delete_all
525
- Subscriber.connection.reset_pk_sequence! "subscribers"
496
+ Subscriber.lease_connection.reset_pk_sequence! "subscribers"
526
497
  sub = Subscriber.new(name: "robert drake")
527
498
  sub.id = "bob drake"
528
499
  assert_nothing_raised { sub.save! }
@@ -533,33 +504,572 @@ module ActiveRecord
533
504
  def reset_fixtures(*fixture_names)
534
505
  ActiveRecord::FixtureSet.reset_cache
535
506
 
536
- fixture_names.each do |fixture_name|
537
- ActiveRecord::FixtureSet.create_fixtures(FIXTURES_ROOT, fixture_name)
507
+ if current_adapter?(:IBM_DBAdapter)
508
+ ActiveRecord::FixtureSet.create_fixtures(FIXTURES_ROOT, fixture_names)
509
+ else
510
+ fixture_names.each do |fixture_name|
511
+ ActiveRecord::FixtureSet.create_fixtures(FIXTURES_ROOT, fixture_name)
512
+ end
513
+ end
514
+ end
515
+ end
516
+
517
+ class AdapterConnectionTest < ActiveRecord::TestCase
518
+ unless in_memory_db?
519
+ self.use_transactional_tests = false
520
+
521
+ fixtures :posts, :authors, :author_addresses
522
+
523
+ def setup
524
+ @connection = ActiveRecord::Base.lease_connection
525
+ assert_predicate @connection, :active?
526
+ end
527
+
528
+ def teardown
529
+ @connection.reconnect!
530
+ assert_predicate @connection, :active?
531
+ assert_not_predicate @connection, :transaction_open?
532
+ assert_not raw_transaction_open?(@connection)
533
+ end
534
+
535
+ test "reconnect after a disconnect" do
536
+ @connection.disconnect!
537
+ assert_not_predicate @connection, :active?
538
+ @connection.reconnect!
539
+ assert_predicate @connection, :active?
540
+ end
541
+
542
+ test "materialized transaction state is reset after a reconnect" do
543
+ @connection.begin_transaction
544
+ assert_predicate @connection, :transaction_open?
545
+ @connection.materialize_transactions
546
+ assert raw_transaction_open?(@connection)
547
+ @connection.reconnect!
548
+ assert_not_predicate @connection, :transaction_open?
549
+ assert_not raw_transaction_open?(@connection)
550
+ end
551
+
552
+ test "materialized transaction state can be restored after a reconnect" do
553
+ @connection.begin_transaction
554
+ assert_predicate @connection, :transaction_open?
555
+ @connection.materialize_transactions
556
+ assert raw_transaction_open?(@connection)
557
+ @connection.reconnect!(restore_transactions: true)
558
+ assert_predicate @connection, :transaction_open?
559
+ assert raw_transaction_open?(@connection)
560
+ end
561
+
562
+ test "materialized transaction state is reset after a disconnect" do
563
+ @connection.begin_transaction
564
+ assert_predicate @connection, :transaction_open?
565
+ @connection.materialize_transactions
566
+ assert raw_transaction_open?(@connection)
567
+ @connection.disconnect!
568
+ assert_not_predicate @connection, :transaction_open?
569
+ end
570
+
571
+ test "unmaterialized transaction state is reset after a reconnect" do
572
+ @connection.begin_transaction
573
+ assert_predicate @connection, :transaction_open?
574
+ assert_not raw_transaction_open?(@connection)
575
+ @connection.reconnect!
576
+ assert_not_predicate @connection, :transaction_open?
577
+ assert_not raw_transaction_open?(@connection)
578
+ @connection.materialize_transactions
579
+ assert_not raw_transaction_open?(@connection)
580
+ end
581
+
582
+ test "unmaterialized transaction state can be restored after a reconnect" do
583
+ @connection.begin_transaction
584
+ assert_predicate @connection, :transaction_open?
585
+ assert_not raw_transaction_open?(@connection)
586
+ @connection.reconnect!(restore_transactions: true)
587
+ assert_predicate @connection, :transaction_open?
588
+ assert_not raw_transaction_open?(@connection)
589
+ @connection.materialize_transactions
590
+ assert raw_transaction_open?(@connection)
591
+ end
592
+
593
+ test "unmaterialized transaction state is reset after a disconnect" do
594
+ @connection.begin_transaction
595
+ assert_predicate @connection, :transaction_open?
596
+ assert_not raw_transaction_open?(@connection)
597
+ @connection.disconnect!
598
+ assert_not_predicate @connection, :transaction_open?
599
+ end
600
+
601
+ test "active? detects remote disconnection" do
602
+ remote_disconnect @connection
603
+ assert_not_predicate @connection, :active?
604
+ end
605
+
606
+ test "verify! restores after remote disconnection" do
607
+ remote_disconnect @connection
608
+ @connection.verify!
609
+ assert_predicate @connection, :active?
610
+ end
611
+
612
+ test "reconnect! restores after remote disconnection" do
613
+ remote_disconnect @connection
614
+ @connection.reconnect!
615
+ assert_predicate @connection, :active?
616
+ end
617
+
618
+ test "querying a 'clean' long-failed connection restores and succeeds" do
619
+ remote_disconnect @connection
620
+
621
+ @connection.clean! # this simulates a fresh checkout from the pool
622
+
623
+ # Backdate last activity to simulate a connection we haven't used in a while
624
+ @connection.instance_variable_set(:@last_activity, Process.clock_gettime(Process::CLOCK_MONOTONIC) - 5.minutes)
625
+
626
+ # Clean did not verify / fix the connection
627
+ assert_not_predicate @connection, :active?
628
+
629
+ # Because the connection hasn't been verified since checkout,
630
+ # and the query cannot safely be retried, the connection will be
631
+ # verified before querying.
632
+ Post.delete_all
633
+
634
+ assert_predicate @connection, :active?
635
+ end
636
+
637
+ test "querying a 'clean' recently-used but now-failed connection skips verification" do
638
+ remote_disconnect @connection
639
+
640
+ @connection.clean! # this simulates a fresh checkout from the pool
641
+
642
+ # Clean did not verify / fix the connection
643
+ assert_not_predicate @connection, :active?
644
+
645
+ # Because the query cannot be retried, and we (mistakenly) believe the
646
+ # connection is still good, the query will fail. This is what we want,
647
+ # because the alternative would be excessive reverification.
648
+ assert_raises(ActiveRecord::AdapterError) do
649
+ Post.delete_all
650
+ end
651
+ end
652
+
653
+ test "quoting a string on a 'clean' failed connection will not prevent reconnecting" do
654
+ remote_disconnect @connection
655
+
656
+ @connection.clean! # this simulates a fresh checkout from the pool
657
+
658
+ # Backdate last activity to simulate a connection we haven't used in a while
659
+ @connection.instance_variable_set(:@last_activity, Process.clock_gettime(Process::CLOCK_MONOTONIC) - 5.minutes)
660
+
661
+ # Clean did not verify / fix the connection
662
+ assert_not_predicate @connection, :active?
663
+
664
+ # Quote string will not verify a broken connection (although it may
665
+ # reconnect in some cases)
666
+ Post.lease_connection.quote_string("")
667
+
668
+ # Because the connection hasn't been verified since checkout,
669
+ # and the query cannot safely be retried, the connection will be
670
+ # verified before querying.
671
+ Post.delete_all
672
+
673
+ assert_predicate @connection, :active?
674
+ end
675
+
676
+ test "querying after a failed non-retryable query restores and succeeds" do
677
+ Post.first # Connection verified (and prepared statement pool populated if enabled)
678
+
679
+ remote_disconnect @connection
680
+
681
+ assert_raises(ActiveRecord::ConnectionFailed) do
682
+ @connection.execute("INSERT INTO posts(title, body) VALUES ('foo', 'bar')")
683
+ end
684
+
685
+ assert Post.first # Verifying the connection causes a reconnect and the query succeeds
686
+ assert_predicate @connection, :active?
687
+ end
688
+
689
+ test "idempotent SELECT queries are retried and result in a reconnect" do
690
+ Post.first
691
+
692
+ remote_disconnect @connection
693
+
694
+ assert Post.first
695
+ assert_predicate @connection, :active?
696
+
697
+ remote_disconnect @connection
698
+
699
+ assert Post.where(id: [1, 2]).first
700
+ assert_predicate @connection, :active?
701
+ end
702
+
703
+ test "#find and #find_by queries with known attributes are retried and result in a reconnect" do
704
+ Post.first
705
+
706
+ remote_disconnect @connection
707
+
708
+ assert Post.find(1)
709
+ assert_predicate @connection, :active?
710
+
711
+ remote_disconnect @connection
712
+
713
+ assert Post.find_by(title: "Welcome to the weblog")
714
+ assert_predicate @connection, :active?
715
+ end
716
+
717
+ test "queries containing SQL fragments are not retried" do
718
+ Post.first
719
+
720
+ remote_disconnect @connection
721
+
722
+ assert_raises(ActiveRecord::ConnectionFailed) { Post.where("1 = 1").to_a }
723
+ assert_not_predicate @connection, :active?
724
+
725
+ remote_disconnect @connection
726
+
727
+ assert_raises(ActiveRecord::ConnectionFailed) { Post.select("title AS custom_title").first }
728
+ assert_not_predicate @connection, :active?
729
+
730
+ remote_disconnect @connection
731
+
732
+ assert_raises(ActiveRecord::ConnectionFailed) { Post.find_by("updated_at < ?", 2.weeks.ago) }
733
+ assert_not_predicate @connection, :active?
734
+ end
735
+
736
+ test "queries containing SQL functions are not retried" do
737
+ Post.first
738
+
739
+ remote_disconnect @connection
740
+
741
+ tags_count_attr = Post.arel_table[:tags_count]
742
+ abs_tags_count = Arel::Nodes::NamedFunction.new("ABS", [tags_count_attr])
743
+
744
+ assert_raises(ActiveRecord::ConnectionFailed) do
745
+ Post.where(abs_tags_count.eq(2)).first
746
+ end
747
+ assert_not_predicate @connection, :active?
748
+ end
749
+
750
+ test "transaction restores after remote disconnection" do
751
+ remote_disconnect @connection
752
+ Post.transaction do
753
+ Post.count
754
+ end
755
+ assert_predicate @connection, :active?
756
+ end
757
+
758
+ test "active transaction is restored after remote disconnection" do
759
+ assert_operator Post.count, :>, 0
760
+ Post.transaction do
761
+ @connection.materialize_transactions
762
+ remote_disconnect @connection
763
+
764
+ # Regular queries are not retryable, so the only abstract operation we can
765
+ # perform here is a direct verify. The outer transaction means using another
766
+ # here would just be a ResetParent.
767
+ @connection.verify!
768
+
769
+ Post.delete_all
770
+
771
+ assert_equal 0, Post.count
772
+ raise ActiveRecord::Rollback
773
+ end
774
+
775
+ # The deletion occurred within the outer transaction (which was then rolled
776
+ # back), and not directly on the freshly-reestablished connection, so the
777
+ # posts are still there:
778
+ assert_operator Post.count, :>, 0
779
+ end
780
+
781
+ test "dirty transaction cannot be restored after remote disconnection" do
782
+ invocations = 0
783
+ assert_raises ActiveRecord::ConnectionFailed do
784
+ Post.transaction do
785
+ invocations += 1
786
+ Post.delete_all
787
+ remote_disconnect @connection
788
+ Post.count
789
+ end
790
+ end
791
+
792
+ assert_equal 1, invocations # the whole transaction block is not retried
793
+
794
+ # After the (outermost) transaction block failed, the connection is
795
+ # ready to reconnect on next use, but hasn't done so yet
796
+ assert_not_predicate @connection, :active?
797
+ assert_operator Post.count, :>, 0
798
+ end
799
+
800
+ test "can reconnect and retry queries under limit when retry deadline is set" do
801
+ attempts = 0
802
+ @connection.stub(:retry_deadline, 0.1) do
803
+ @connection.send(:with_raw_connection, allow_retry: true) do
804
+ if attempts == 0
805
+ attempts += 1
806
+ raise ActiveRecord::ConnectionFailed.new("Something happened to the connection")
807
+ end
808
+ end
809
+ end
810
+ end
811
+
812
+ test "does not reconnect and retry queries when retries are disabled" do
813
+ assert_raises(ActiveRecord::ConnectionFailed) do
814
+ attempts = 0
815
+ @connection.send(:with_raw_connection) do
816
+ if attempts == 0
817
+ attempts += 1
818
+ raise ActiveRecord::ConnectionFailed.new("Something happened to the connection")
819
+ end
820
+ end
821
+ end
822
+ end
823
+
824
+ test "does not reconnect and retry queries that exceed retry deadline" do
825
+ assert_raises(ActiveRecord::ConnectionFailed) do
826
+ attempts = 0
827
+ @connection.stub(:retry_deadline, 0.1) do
828
+ @connection.send(:with_raw_connection, allow_retry: true) do
829
+ if attempts == 0
830
+ sleep(0.2)
831
+ attempts += 1
832
+ raise ActiveRecord::ConnectionFailed.new("Something happened to the connection")
833
+ end
834
+ end
835
+ end
836
+ end
837
+ end
838
+
839
+ test "#execute is retryable" do
840
+ select_one_sql = current_adapter?(:IBM_DBAdapter) ? "SELECT 1 FROM SYSIBM.SYSDUMMY1" : "SELECT 1"
841
+
842
+ conn_id = case @connection.adapter_name
843
+ when "Mysql2"
844
+ @connection.execute("SELECT CONNECTION_ID()").to_a[0][0]
845
+ when "Trilogy"
846
+ @connection.execute("SELECT CONNECTION_ID() as connection_id").to_a[0][0]
847
+ when "PostgreSQL"
848
+ @connection.execute("SELECT pg_backend_pid()").to_a[0]["pg_backend_pid"]
849
+ else
850
+ skip("kill_connection_from_server unsupported")
851
+ end
852
+
853
+ kill_connection_from_server(conn_id)
854
+
855
+ @connection.execute(select_one_sql, allow_retry: true)
856
+ end
857
+
858
+ test "disconnect and recover on #configure_connection failure" do
859
+ connection = ActiveRecord::Base.connection_pool.send(:new_connection)
860
+ select_one_sql = current_adapter?(:IBM_DBAdapter) ? "SELECT 1 FROM SYSIBM.SYSDUMMY1" : "SELECT 1"
861
+
862
+ failures = [ActiveRecord::ConnectionFailed.new("Oops"), ActiveRecord::ConnectionFailed.new("Oops 2")]
863
+ connection.singleton_class.define_method(:configure_connection) do
864
+ if error = failures.pop
865
+ raise error
866
+ else
867
+ super()
868
+ end
869
+ end
870
+ if current_adapter?(:IBM_DBAdapter)
871
+ assert_nothing_raised do
872
+ connection.exec_query(select_one_sql)
873
+ end
874
+ else
875
+ assert_raises ActiveRecord::ConnectionFailed do
876
+ connection.exec_query(select_one_sql)
877
+ end
878
+ end
879
+
880
+ assert_equal [[1]], connection.exec_query(select_one_sql).rows
881
+ assert_empty failures unless current_adapter?(:IBM_DBAdapter)
882
+ ensure
883
+ connection&.disconnect!
884
+ end
885
+
886
+ test "disconnect and recover on #configure_connection timeout" do
887
+ connection = ActiveRecord::Base.connection_pool.send(:new_connection)
888
+ select_one_sql = current_adapter?(:IBM_DBAdapter) ? "SELECT 1 FROM SYSIBM.SYSDUMMY1" : "SELECT 1"
889
+
890
+ slow = [5]
891
+ connection.singleton_class.define_method(:configure_connection) do
892
+ if duration = slow.pop
893
+ sleep duration
894
+ end
895
+ super()
896
+ end
897
+
898
+ if current_adapter?(:IBM_DBAdapter)
899
+ assert_nothing_raised do
900
+ Timeout.timeout(0.2) do
901
+ connection.exec_query(select_one_sql)
902
+ end
903
+ end
904
+ else
905
+ assert_raises Timeout::Error do
906
+ Timeout.timeout(0.2) do
907
+ connection.exec_query(select_one_sql)
908
+ end
909
+ end
910
+ end
911
+
912
+ assert_equal [[1]], connection.exec_query(select_one_sql).rows
913
+ if current_adapter?(:IBM_DBAdapter)
914
+ assert_equal [5], slow
915
+ else
916
+ assert_empty slow
917
+ end
918
+ ensure
919
+ connection&.disconnect!
920
+ end
921
+
922
+ private
923
+ def raw_transaction_open?(connection)
924
+ case connection.adapter_name
925
+ when "PostgreSQL"
926
+ connection.instance_variable_get(:@raw_connection).transaction_status == ::PG::PQTRANS_INTRANS
927
+ when "Mysql2", "Trilogy"
928
+ begin
929
+ connection.instance_variable_get(:@raw_connection).query("SAVEPOINT transaction_test")
930
+ connection.instance_variable_get(:@raw_connection).query("RELEASE SAVEPOINT transaction_test")
931
+
932
+ true
933
+ rescue
934
+ false
935
+ end
936
+ when "SQLite"
937
+ begin
938
+ connection.instance_variable_get(:@raw_connection).transaction { nil }
939
+ false
940
+ rescue
941
+ true
942
+ end
943
+ else
944
+ skip("kill_connection_from_server unsupported")
945
+ end
946
+ end
947
+
948
+ def remote_disconnect(connection)
949
+ case connection.adapter_name
950
+ when "PostgreSQL"
951
+ # Connection was left in a bad state, need to reconnect to simulate fresh disconnect
952
+ connection.verify! if connection.instance_variable_get(:@raw_connection).status == ::PG::CONNECTION_BAD
953
+ unless connection.instance_variable_get(:@raw_connection).transaction_status == ::PG::PQTRANS_INTRANS
954
+ connection.instance_variable_get(:@raw_connection).async_exec("begin")
955
+ end
956
+ connection.instance_variable_get(:@raw_connection).async_exec("set idle_in_transaction_session_timeout = '10ms'")
957
+ sleep 0.05
958
+ when "Mysql2", "Trilogy"
959
+ connection.send(:internal_execute, "set @@wait_timeout=1", materialize_transactions: false)
960
+ sleep 1.2
961
+ else
962
+ skip("remote_disconnect unsupported")
963
+ end
964
+ end
965
+
966
+ def kill_connection_from_server(connection_id)
967
+ conn = @connection.pool.checkout
968
+ case conn.adapter_name
969
+ when "Mysql2", "Trilogy"
970
+ conn.execute("KILL #{connection_id}")
971
+ when "PostgreSQL"
972
+ conn.execute("SELECT pg_cancel_backend(#{connection_id})")
973
+ else
974
+ skip("kill_connection_from_server unsupported")
975
+ end
976
+
977
+ conn.close
978
+ end
979
+ end
980
+ end
981
+
982
+ class AdapterThreadSafetyTest < ActiveRecord::TestCase
983
+ setup do
984
+ @threads = []
985
+ @connection = ActiveRecord::Base.connection_pool.checkout
986
+ end
987
+
988
+ teardown do
989
+ @threads.each(&:kill)
990
+ end
991
+
992
+ unless in_memory_db?
993
+ test "#active? is synchronized" do
994
+ threads(2, 25) { @connection.select_all(current_adapter?(:IBM_DBAdapter) ? "SELECT 1 FROM SYSIBM.SYSDUMMY1" : "SELECT 1") }
995
+ threads(2, 25) { @connection.verify! }
996
+ threads(2, 25) { @connection.disconnect! }
997
+
998
+ join
999
+ pass
1000
+ end
1001
+
1002
+ test "#verify! is synchronized" do
1003
+ threads(2, 25) { @connection.verify! }
1004
+ threads(2, 25) { @connection.disconnect! }
1005
+
1006
+ join
1007
+ pass
1008
+ end
1009
+ end
1010
+
1011
+ private
1012
+ def join
1013
+ @threads.shuffle.each(&:join)
1014
+ end
1015
+
1016
+ def threads(count, times)
1017
+ @threads += count.times.map do
1018
+ Thread.new do
1019
+ times.times do
1020
+ yield
1021
+ Thread.pass
1022
+ end
1023
+ end
538
1024
  end
539
1025
  end
540
1026
  end
541
1027
  end
542
1028
 
543
- if ActiveRecord::Base.connection.supports_advisory_locks?
1029
+ if ActiveRecord::Base.lease_connection.supports_advisory_locks?
544
1030
  class AdvisoryLocksEnabledTest < ActiveRecord::TestCase
545
1031
  include ConnectionHelper
546
1032
 
547
1033
  def test_advisory_locks_enabled?
548
- assert ActiveRecord::Base.connection.advisory_locks_enabled?
1034
+ assert_predicate ActiveRecord::Base.lease_connection, :advisory_locks_enabled?
549
1035
 
550
1036
  run_without_connection do |orig_connection|
551
1037
  ActiveRecord::Base.establish_connection(
552
1038
  orig_connection.merge(advisory_locks: false)
553
1039
  )
554
1040
 
555
- assert_not ActiveRecord::Base.connection.advisory_locks_enabled?
1041
+ assert_not ActiveRecord::Base.lease_connection.advisory_locks_enabled?
556
1042
 
557
1043
  ActiveRecord::Base.establish_connection(
558
1044
  orig_connection.merge(advisory_locks: true)
559
1045
  )
560
1046
 
561
- assert ActiveRecord::Base.connection.advisory_locks_enabled?
1047
+ assert_predicate ActiveRecord::Base.lease_connection, :advisory_locks_enabled?
1048
+ end
1049
+ end
1050
+ end
1051
+ end
1052
+
1053
+ if ActiveRecord::Base.lease_connection.savepoint_errors_invalidate_transactions?
1054
+ class InvalidateTransactionTest < ActiveRecord::TestCase
1055
+ def test_invalidates_transaction_on_rollback_error
1056
+ @invalidated = false
1057
+ connection = ActiveRecord::Base.lease_connection
1058
+
1059
+ connection.transaction do
1060
+ connection.send(:with_raw_connection) do
1061
+ raise ActiveRecord::Deadlocked, "made-up deadlock"
1062
+ end
1063
+
1064
+ rescue ActiveRecord::Deadlocked => error
1065
+ flunk("Rescuing wrong error") unless error.message == "made-up deadlock"
1066
+
1067
+ @invalidated = connection.current_transaction.invalidated?
562
1068
  end
1069
+
1070
+ # asserting outside of the transaction to make sure we actually reach the end of the test
1071
+ # and perform the assertion
1072
+ assert @invalidated
563
1073
  end
564
1074
  end
565
1075
  end