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
@@ -7,6 +7,7 @@ require "models/project"
7
7
  require "models/company"
8
8
  require "models/ship"
9
9
  require "models/pirate"
10
+ require "models/person"
10
11
  require "models/car"
11
12
  require "models/bulb"
12
13
  require "models/author"
@@ -17,6 +18,10 @@ require "models/chef"
17
18
  require "models/department"
18
19
  require "models/club"
19
20
  require "models/membership"
21
+ require "models/parrot"
22
+ require "models/cpk"
23
+ require "models/room"
24
+ require "models/user"
20
25
 
21
26
  class HasOneAssociationsTest < ActiveRecord::TestCase
22
27
  self.use_transactional_tests = false unless supports_savepoints?
@@ -30,7 +35,7 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
30
35
  def test_has_one
31
36
  firm = companies(:first_firm)
32
37
  first_account = Account.find(1)
33
- assert_sql(/LIMIT|ROWNUM <=|FETCH FIRST/) do
38
+ assert_queries_match(/LIMIT|ROWNUM <=|FETCH FIRST/) do
34
39
  assert_equal first_account, firm.account
35
40
  assert_equal first_account.credit_limit, firm.account.credit_limit
36
41
  end
@@ -43,7 +48,7 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
43
48
 
44
49
  def test_has_one_cache_nils
45
50
  firm = companies(:another_firm)
46
- assert_queries(1) { assert_nil firm.account }
51
+ assert_queries_count(1) { assert_nil firm.account }
47
52
  assert_no_queries { assert_nil firm.account }
48
53
 
49
54
  firms = Firm.includes(:account).to_a
@@ -51,8 +56,8 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
51
56
  end
52
57
 
53
58
  def test_with_select
54
- assert_equal Firm.find(1).account_with_select.attributes.size, 2
55
- assert_equal Firm.all.merge!(includes: :account_with_select).find(1).account_with_select.attributes.size, 2
59
+ assert_equal 2, Firm.find(1).account_with_select.attributes.size
60
+ assert_equal 2, Firm.all.merge!(includes: :account_with_select).find(1).account_with_select.attributes.size
56
61
  end
57
62
 
58
63
  def test_finding_using_primary_key
@@ -140,6 +145,17 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
140
145
  assert_not_predicate developer, :persisted?
141
146
  end
142
147
 
148
+ def test_nullification_on_cpk_association
149
+ book = Cpk::Book.create!(id: [1, 2])
150
+ other_book = Cpk::Book.create!(id: [3, 4])
151
+ order = Cpk::OrderWithNullifiedBook.create!(book: book)
152
+
153
+ order.book = other_book
154
+
155
+ assert_nil book.order_id
156
+ assert_nil book.shop_id
157
+ end
158
+
143
159
  def test_natural_assignment_to_nil_after_destroy
144
160
  firm = companies(:rails_core)
145
161
  old_account_id = firm.account.id
@@ -254,7 +270,7 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
254
270
 
255
271
  def test_build_association_dont_create_transaction
256
272
  firm = Firm.new
257
- assert_queries(0) do
273
+ assert_queries_count(0) do
258
274
  firm.build_account
259
275
  end
260
276
  end
@@ -307,6 +323,19 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
307
323
  assert_equal account, firm.reload.account
308
324
  end
309
325
 
326
+ def test_clearing_an_association_clears_the_associations_inverse
327
+ author = Author.create(name: "Jimmy Tolkien")
328
+ post = author.create_post(title: "The silly medallion", body: "")
329
+ assert_equal post, author.post
330
+ assert_equal author, post.author
331
+
332
+ post.update!(author: nil)
333
+ assert_nil post.author
334
+
335
+ author.update!(name: "J.R.R. Tolkien")
336
+ assert_nil post.author
337
+ end
338
+
310
339
  def test_create_association_with_bang
311
340
  firm = Firm.create(name: "GlobalMegaCorp")
312
341
  account = firm.create_account!(credit_limit: 1000)
@@ -340,6 +369,7 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
340
369
  end
341
370
 
342
371
  assert_equal "You cannot call create unless the parent is saved", error.message
372
+ assert_equal firm, error.record
343
373
  end
344
374
 
345
375
  def test_reload_association
@@ -349,13 +379,15 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
349
379
  Account.where(id: odegy.account.id).update_all(credit_limit: 80)
350
380
  assert_equal 53, odegy.account.credit_limit
351
381
 
352
- assert_equal 80, odegy.reload_account.credit_limit
382
+ assert_queries_count(1) { odegy.reload_account }
383
+ assert_no_queries { odegy.account }
384
+ assert_equal 80, odegy.account.credit_limit
353
385
  end
354
386
 
355
387
  def test_reload_association_with_query_cache
356
388
  odegy_id = companies(:odegy).id
357
389
 
358
- connection = ActiveRecord::Base.connection
390
+ connection = ActiveRecord::Base.lease_connection
359
391
  connection.enable_query_cache!
360
392
  connection.clear_query_cache
361
393
 
@@ -367,12 +399,25 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
367
399
  assert_equal 2, connection.query_cache.size
368
400
 
369
401
  # Clear the cache and fetch the account again, populating the cache with a query
370
- assert_queries(1) { odegy.reload_account }
402
+ assert_queries_count(1) { odegy.reload_account }
371
403
 
372
404
  # This query is not cached anymore, so it should make a real SQL query
373
- assert_queries(1) { Company.find(odegy_id) }
405
+ assert_queries_count(1) { Company.find(odegy_id) }
374
406
  ensure
375
- ActiveRecord::Base.connection.disable_query_cache!
407
+ ActiveRecord::Base.lease_connection.disable_query_cache!
408
+ end
409
+
410
+ def test_reset_association
411
+ odegy = companies(:odegy)
412
+
413
+ assert_equal 53, odegy.account.credit_limit
414
+ Account.where(id: odegy.account.id).update_all(credit_limit: 80)
415
+ assert_equal 53, odegy.account.credit_limit
416
+
417
+ assert_no_queries { odegy.reset_account }
418
+
419
+ assert_queries_count(1) { odegy.account }
420
+ assert_equal 80, odegy.account.credit_limit
376
421
  end
377
422
 
378
423
  def test_build
@@ -450,8 +495,10 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
450
495
  end
451
496
 
452
497
  def test_has_one_proxy_should_respond_to_private_methods_via_send
453
- accounts(:signals37).send(:private_method)
454
- companies(:first_firm).account.send(:private_method)
498
+ assert_nothing_raised do
499
+ accounts(:signals37).send(:private_method)
500
+ companies(:first_firm).account.send(:private_method)
501
+ end
455
502
  end
456
503
 
457
504
  def test_save_of_record_with_loaded_has_one
@@ -485,10 +532,10 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
485
532
 
486
533
  def test_attributes_are_being_set_when_initialized_from_has_one_association_with_where_clause
487
534
  new_account = companies(:first_firm).build_account(firm_name: "Account")
488
- assert_equal new_account.firm_name, "Account"
535
+ assert_equal "Account", new_account.firm_name
489
536
  end
490
537
 
491
- def test_creation_failure_without_dependent_option
538
+ def test_creation_failure_replaces_existing_without_dependent_option
492
539
  pirate = pirates(:blackbeard)
493
540
  orig_ship = pirate.ship
494
541
 
@@ -497,16 +544,18 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
497
544
  assert_not_equal ships(:black_pearl), new_ship
498
545
  assert_equal new_ship, pirate.ship
499
546
  assert_predicate new_ship, :new_record?
547
+ assert_predicate new_ship, :invalid?
500
548
  assert_nil orig_ship.pirate_id
501
549
  assert_not orig_ship.changed? # check it was saved
502
550
  end
503
551
 
504
- def test_creation_failure_with_dependent_option
552
+ def test_creation_failure_replaces_existing_with_dependent_option
505
553
  pirate = pirates(:blackbeard).becomes(DestructivePirate)
506
554
  orig_ship = pirate.dependent_ship
507
555
 
508
556
  new_ship = pirate.create_dependent_ship
509
557
  assert_predicate new_ship, :new_record?
558
+ assert_predicate new_ship, :invalid?
510
559
  assert_predicate orig_ship, :destroyed?
511
560
  end
512
561
 
@@ -519,6 +568,7 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
519
568
  end
520
569
 
521
570
  assert_equal "Failed to save the new associated ship.", error.message
571
+ assert_equal new_ship, error.record
522
572
  assert_nil pirate.ship
523
573
  assert_nil new_ship.pirate_id
524
574
  end
@@ -536,6 +586,7 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
536
586
  assert_equal pirate.id, pirate.ship.pirate_id
537
587
  assert_equal "Failed to remove the existing associated ship. " \
538
588
  "The record failed to save after its foreign key was set to nil.", error.message
589
+ assert_equal pirate.ship, error.record
539
590
  end
540
591
 
541
592
  def test_replacement_failure_due_to_new_record_should_raise_error
@@ -547,6 +598,7 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
547
598
  end
548
599
 
549
600
  assert_equal "Failed to save the new associated ship.", error.message
601
+ assert_equal new_ship, error.record
550
602
  assert_equal ships(:black_pearl), pirate.ship
551
603
  assert_equal pirate.id, pirate.ship.pirate_id
552
604
  assert_equal pirate.id, ships(:black_pearl).reload.pirate_id
@@ -623,7 +675,7 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
623
675
  company.account = nil
624
676
  assert_no_queries { company.account = nil }
625
677
  account = Account.find(2)
626
- assert_queries { company.account = account }
678
+ assert_queries_count(3) { company.account = account }
627
679
 
628
680
  assert_no_queries { Firm.new.account = account }
629
681
  end
@@ -635,7 +687,7 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
635
687
 
636
688
  ship.name = "new name"
637
689
  assert_predicate ship, :changed?
638
- assert_queries(1) do
690
+ assert_queries_count(3) do
639
691
  # One query for updating name, not triggering query for updating pirate_id
640
692
  pirate.ship = ship
641
693
  end
@@ -649,7 +701,7 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
649
701
  ship.save!
650
702
 
651
703
  new_ship = Ship.create(name: "new name")
652
- assert_queries(2) do
704
+ assert_queries_count(4) do
653
705
  # One query to nullify the old ship, one query to update the new ship
654
706
  pirate.ship = new_ship
655
707
  end
@@ -705,13 +757,13 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
705
757
  end
706
758
 
707
759
  def test_has_one_with_touch_option_on_create
708
- assert_queries(3) {
709
- Club.create(name: "1000 Oaks", membership_attributes: { favourite: true })
760
+ assert_queries_count(5) {
761
+ Club.create(name: "1000 Oaks", membership_attributes: { favorite: true })
710
762
  }
711
763
  end
712
764
 
713
765
  def test_polymorphic_has_one_with_touch_option_on_create_wont_cache_association_so_fetching_after_transaction_commit_works
714
- assert_queries(4) {
766
+ assert_queries_count(6) {
715
767
  chef = Chef.create(employable: DrinkDesignerWithPolymorphicTouchChef.new)
716
768
  employable = chef.employable
717
769
 
@@ -723,7 +775,7 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
723
775
  DrinkDesignerWithPolymorphicTouchChef.create(chef: Chef.new)
724
776
  designer = DrinkDesignerWithPolymorphicTouchChef.last
725
777
 
726
- assert_queries(3) {
778
+ assert_queries_count(5) {
727
779
  designer.update(name: "foo")
728
780
  }
729
781
  end
@@ -732,21 +784,21 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
732
784
  new_club = Club.create(name: "1000 Oaks")
733
785
  new_club.create_membership
734
786
 
735
- assert_queries(2) { new_club.update(name: "Effingut") }
787
+ assert_queries_count(4) { new_club.update(name: "Effingut") }
736
788
  end
737
789
 
738
790
  def test_has_one_with_touch_option_on_touch
739
791
  new_club = Club.create(name: "1000 Oaks")
740
792
  new_club.create_membership
741
793
 
742
- assert_queries(1) { new_club.touch }
794
+ assert_queries_count(3) { new_club.touch }
743
795
  end
744
796
 
745
797
  def test_has_one_with_touch_option_on_destroy
746
798
  new_club = Club.create(name: "1000 Oaks")
747
799
  new_club.create_membership
748
800
 
749
- assert_queries(2) { new_club.destroy }
801
+ assert_queries_count(4) { new_club.destroy }
750
802
  end
751
803
 
752
804
  def test_has_one_with_touch_option_on_empty_update
@@ -756,12 +808,34 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
756
808
  assert_no_queries { new_club.save }
757
809
  end
758
810
 
811
+ def test_has_one_double_belongs_to_destroys_both_from_either_end
812
+ landlord = User.create!
813
+ tenant = User.create!
814
+ room = Room.create!(landlord: landlord, tenant: tenant)
815
+
816
+ landlord.destroy!
817
+
818
+ assert_predicate(room, :destroyed?)
819
+ assert_predicate(landlord, :destroyed?)
820
+ assert_predicate(tenant, :destroyed?)
821
+
822
+ landlord = User.create!
823
+ tenant = User.create!
824
+ room = Room.create!(landlord: landlord, tenant: tenant)
825
+
826
+ tenant.destroy!
827
+
828
+ assert_predicate(room, :destroyed?)
829
+ assert_predicate(tenant, :destroyed?)
830
+ assert_predicate(landlord, :destroyed?)
831
+ end
832
+
759
833
  class SpecialBook < ActiveRecord::Base
760
834
  self.table_name = "books"
761
835
  belongs_to :author, class_name: "SpecialAuthor"
762
- has_one :subscription, class_name: "SpecialSupscription", foreign_key: "subscriber_id"
836
+ has_one :subscription, class_name: "SpecialSubscription", foreign_key: "subscriber_id"
763
837
 
764
- enum status: [:proposed, :written, :published]
838
+ enum :status, [:proposed, :written, :published]
765
839
  end
766
840
 
767
841
  class SpecialAuthor < ActiveRecord::Base
@@ -769,7 +843,7 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
769
843
  has_one :book, class_name: "SpecialBook", foreign_key: "author_id"
770
844
  end
771
845
 
772
- class SpecialSupscription < ActiveRecord::Base
846
+ class SpecialSubscription < ActiveRecord::Base
773
847
  self.table_name = "subscriptions"
774
848
  belongs_to :book, class_name: "SpecialBook"
775
849
  end
@@ -864,9 +938,66 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
864
938
 
865
939
  def test_has_one_with_touch_option_on_nonpersisted_built_associations_doesnt_update_parent
866
940
  car = SpecialCar.create(name: "honda")
867
- assert_queries(1) do
941
+ assert_queries_count(1) do
868
942
  car.build_special_bulb
869
943
  car.build_special_bulb
870
944
  end
871
945
  end
946
+ test "composite primary key malformed association class" do
947
+ error = assert_raises(ActiveRecord::CompositePrimaryKeyMismatchError) do
948
+ order = Cpk::BrokenOrder.new(id: [1, 2], book: Cpk::Book.new(title: "Some book"))
949
+ order.save!
950
+ end
951
+
952
+ assert_equal(<<~MESSAGE.squish, error.message)
953
+ Association Cpk::BrokenOrder#book primary key ["shop_id", "status"]
954
+ doesn't match with foreign key broken_order_id. Please specify query_constraints, or primary_key and foreign_key values.
955
+ MESSAGE
956
+ end
957
+
958
+ test "composite primary key malformed association owner class" do
959
+ error = assert_raises(ActiveRecord::CompositePrimaryKeyMismatchError) do
960
+ order = Cpk::BrokenOrderWithNonCpkBooks.new(id: [1, 2], book: Cpk::NonCpkBook.new(title: "Some book"))
961
+ order.save!
962
+ end
963
+
964
+ assert_equal(<<~MESSAGE.squish, error.message)
965
+ Association Cpk::BrokenOrderWithNonCpkBooks#book primary key [\"shop_id\", \"status\"]
966
+ doesn't match with foreign key broken_order_with_non_cpk_books_id. Please specify query_constraints, or primary_key and foreign_key values.
967
+ MESSAGE
968
+ end
969
+ end
970
+
971
+ class AsyncHasOneAssociationsTest < ActiveRecord::TestCase
972
+ include WaitForAsyncTestHelper
973
+
974
+ self.use_transactional_tests = false
975
+
976
+ fixtures :companies, :accounts
977
+
978
+ unless in_memory_db?
979
+ def test_async_load_has_one
980
+ firm = companies(:first_firm)
981
+ first_account = Account.find(1)
982
+
983
+ firm.association(:account).async_load_target
984
+ wait_for_async_query
985
+
986
+ events = []
987
+ callback = -> (event) do
988
+ events << event unless event.payload[:name] == "SCHEMA"
989
+ end
990
+ ActiveSupport::Notifications.subscribed(callback, "sql.active_record") do
991
+ firm.account
992
+ end
993
+
994
+ assert_no_queries do
995
+ assert_equal first_account, firm.account
996
+ assert_equal first_account.credit_limit, firm.account.credit_limit
997
+ end
998
+
999
+ assert_equal 1, events.size
1000
+ assert_equal true, events.first.payload[:async]
1001
+ end
1002
+ end
872
1003
  end
@@ -22,6 +22,7 @@ require "models/customer"
22
22
  require "models/carrier"
23
23
  require "models/shop_account"
24
24
  require "models/customer_carrier"
25
+ require "models/cpk"
25
26
 
26
27
  class HasOneThroughAssociationsTest < ActiveRecord::TestCase
27
28
  fixtures :member_types, :members, :clubs, :memberships, :sponsors, :organizations, :minivans,
@@ -37,7 +38,7 @@ class HasOneThroughAssociationsTest < ActiveRecord::TestCase
37
38
 
38
39
  def test_has_one_through_executes_limited_query
39
40
  boring_club = clubs(:boring_club)
40
- assert_sql(/LIMIT|ROWNUM <=|FETCH FIRST/) do
41
+ assert_queries_match(/LIMIT|ROWNUM <=|FETCH FIRST/) do
41
42
  assert_equal boring_club, @member.general_club
42
43
  end
43
44
  end
@@ -49,6 +50,13 @@ class HasOneThroughAssociationsTest < ActiveRecord::TestCase
49
50
  assert_not_nil new_member.club
50
51
  end
51
52
 
53
+ def test_association_create_constructor_creates_through_record
54
+ new_member = Member.create(name: "Chris")
55
+ new_member.create_club
56
+ assert_not_nil new_member.current_membership
57
+ assert_not_nil new_member.club
58
+ end
59
+
52
60
  def test_creating_association_builds_through_record
53
61
  new_member = Member.create(name: "Chris")
54
62
  new_club = new_member.association(:club).build
@@ -61,6 +69,18 @@ class HasOneThroughAssociationsTest < ActiveRecord::TestCase
61
69
  assert_predicate new_member.current_membership, :persisted?
62
70
  end
63
71
 
72
+ def test_association_build_constructor_builds_through_record
73
+ new_member = Member.create(name: "Chris")
74
+ new_club = new_member.build_club
75
+ assert new_member.current_membership
76
+ assert_equal new_club, new_member.club
77
+ assert_predicate new_club, :new_record?
78
+ assert_predicate new_member.current_membership, :new_record?
79
+ assert new_member.save
80
+ assert_predicate new_club, :persisted?
81
+ assert_predicate new_member.current_membership, :persisted?
82
+ end
83
+
64
84
  def test_creating_association_builds_through_record_for_new
65
85
  new_member = Member.new(name: "Jane")
66
86
  new_member.club = clubs(:moustache_club)
@@ -80,6 +100,14 @@ class HasOneThroughAssociationsTest < ActiveRecord::TestCase
80
100
  assert_predicate member_detail_with_two_associations.member, :new_record?
81
101
  end
82
102
 
103
+ def test_building_works_with_has_one_through_belongs_to
104
+ new_member = Member.create!(name: "Joe")
105
+ new_member.create_current_membership!
106
+ new_club = new_member.build_club
107
+
108
+ assert_equal(new_member.club, new_club)
109
+ end
110
+
83
111
  def test_creating_multiple_associations_creates_through_record
84
112
  member_type = MemberType.create!
85
113
  member = Member.create!
@@ -137,7 +165,7 @@ class HasOneThroughAssociationsTest < ActiveRecord::TestCase
137
165
  end
138
166
 
139
167
  def test_has_one_through_eager_loading
140
- members = assert_queries(3) do # base table, through table, clubs table
168
+ members = assert_queries_count(3) do # base table, through table, clubs table
141
169
  Member.all.merge!(includes: :club, where: ["name = ?", "Groucho Marx"]).to_a
142
170
  end
143
171
  assert_equal 1, members.size
@@ -145,7 +173,7 @@ class HasOneThroughAssociationsTest < ActiveRecord::TestCase
145
173
  end
146
174
 
147
175
  def test_has_one_through_eager_loading_through_polymorphic
148
- members = assert_queries(3) do # base table, through table, clubs table
176
+ members = assert_queries_count(3) do # base table, through table, clubs table
149
177
  Member.all.merge!(includes: :sponsor_club, where: ["name = ?", "Groucho Marx"]).to_a
150
178
  end
151
179
  assert_equal 1, members.size
@@ -154,9 +182,9 @@ class HasOneThroughAssociationsTest < ActiveRecord::TestCase
154
182
 
155
183
  def test_has_one_through_with_conditions_eager_loading
156
184
  # conditions on the through table
157
- assert_equal clubs(:moustache_club), Member.all.merge!(includes: :favourite_club).find(@member.id).favourite_club
158
- memberships(:membership_of_favourite_club).update_columns(favourite: false)
159
- assert_nil Member.all.merge!(includes: :favourite_club).find(@member.id).reload.favourite_club
185
+ assert_equal clubs(:moustache_club), Member.all.merge!(includes: :favorite_club).find(@member.id).favorite_club
186
+ memberships(:membership_of_favorite_club).update_columns(favorite: false)
187
+ assert_nil Member.all.merge!(includes: :favorite_club).find(@member.id).reload.favorite_club
160
188
 
161
189
  # conditions on the source table
162
190
  assert_equal clubs(:moustache_club), Member.all.merge!(includes: :hairy_club).find(@member.id).hairy_club
@@ -175,7 +203,7 @@ class HasOneThroughAssociationsTest < ActiveRecord::TestCase
175
203
  end
176
204
 
177
205
  def test_has_one_through_nonpreload_eagerloading
178
- members = assert_queries(1) do
206
+ members = assert_queries_count(1) do
179
207
  Member.all.merge!(includes: :club, where: ["members.name = ?", "Groucho Marx"], order: "clubs.name").to_a # force fallback
180
208
  end
181
209
  assert_equal 1, members.size
@@ -183,7 +211,7 @@ class HasOneThroughAssociationsTest < ActiveRecord::TestCase
183
211
  end
184
212
 
185
213
  def test_has_one_through_nonpreload_eager_loading_through_polymorphic
186
- members = assert_queries(1) do
214
+ members = assert_queries_count(1) do
187
215
  Member.all.merge!(includes: :sponsor_club, where: ["members.name = ?", "Groucho Marx"], order: "clubs.name").to_a # force fallback
188
216
  end
189
217
  assert_equal 1, members.size
@@ -191,13 +219,13 @@ class HasOneThroughAssociationsTest < ActiveRecord::TestCase
191
219
  end
192
220
 
193
221
  def test_has_one_through_nonpreload_eager_loading_through_polymorphic_with_more_than_one_through_record
194
- Sponsor.new(sponsor_club: clubs(:crazy_club), sponsorable: members(:groucho)).save!
195
- members = assert_queries(1) do
222
+ Sponsor.new(sponsor_club: clubs(:outrageous_club), sponsorable: members(:groucho)).save!
223
+ members = assert_queries_count(1) do
196
224
  Member.all.merge!(includes: :sponsor_club, where: ["members.name = ?", "Groucho Marx"], order: "clubs.name DESC").to_a # force fallback
197
225
  end
198
226
  assert_equal 1, members.size
199
227
  assert_not_nil assert_no_queries { members[0].sponsor_club }
200
- assert_equal clubs(:crazy_club), members[0].sponsor_club
228
+ assert_equal clubs(:outrageous_club), members[0].sponsor_club
201
229
  end
202
230
 
203
231
  def test_uninitialized_has_one_through_should_return_nil_for_unsaved_record
@@ -217,7 +245,9 @@ class HasOneThroughAssociationsTest < ActiveRecord::TestCase
217
245
 
218
246
  def test_has_one_through_proxy_should_respond_to_private_methods_via_send
219
247
  clubs(:moustache_club).send(:private_method)
220
- @member.club.send(:private_method)
248
+ assert_nothing_raised do
249
+ @member.club.send(:private_method)
250
+ end
221
251
  end
222
252
 
223
253
  def test_assigning_to_has_one_through_preserves_decorated_join_record
@@ -262,7 +292,7 @@ class HasOneThroughAssociationsTest < ActiveRecord::TestCase
262
292
  @member_detail = MemberDetail.new
263
293
  @member.member_detail = @member_detail
264
294
  @member.organization = @organization
265
- @member_details = assert_queries(3) do
295
+ @member_details = assert_queries_count(3) do
266
296
  MemberDetail.all.merge!(includes: :member_type).to_a
267
297
  end
268
298
  @new_detail = @member_details[0]
@@ -294,13 +324,13 @@ class HasOneThroughAssociationsTest < ActiveRecord::TestCase
294
324
 
295
325
  assert_not_nil @member_detail.member_type
296
326
  @member_detail.destroy
297
- assert_queries(1) do
327
+ assert_queries_count(1) do
298
328
  @member_detail.association(:member_type).reload
299
329
  assert_not_nil @member_detail.member_type
300
330
  end
301
331
 
302
332
  @member_detail.member.destroy
303
- assert_queries(1) do
333
+ assert_queries_count(1) do
304
334
  @member_detail.association(:member_type).reload
305
335
  assert_nil @member_detail.member_type
306
336
  end
@@ -426,4 +456,23 @@ class HasOneThroughAssociationsTest < ActiveRecord::TestCase
426
456
  ensure
427
457
  CustomerCarrier.current_customer = nil
428
458
  end
459
+
460
+ def test_loading_cpk_association_with_unpersisted_owner
461
+ order = Cpk::Order.create!(shop_id: 1)
462
+ book = Cpk::BookWithOrderAgreements.new(id: [1, 2], order: order)
463
+ order_agreement = Cpk::OrderAgreement.create!(order: order)
464
+
465
+ assert_equal(order_agreement, book.order_agreement)
466
+ end
467
+
468
+ def test_cpk_stale_target
469
+ order = Cpk::Order.create!(shop_id: 1)
470
+ book = Cpk::BookWithOrderAgreements.create!(id: [1, 2], order: order)
471
+ Cpk::OrderAgreement.create!(order: order)
472
+
473
+ book.order_agreement
474
+ book.order = Cpk::Order.new
475
+
476
+ assert_predicate(book.association(:order_agreement), :stale_target?)
477
+ end
429
478
  end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/helper"
4
+ require "models/member"
5
+ require "models/member_detail"
6
+ require "models/organization"
7
+ require "models/project"
8
+ require "models/developer"
9
+ require "models/company"
10
+ require "models/computer"
11
+ require "models/contract"
12
+ require "models/club"
13
+ require "models/membership"
14
+
15
+ class HasOneThroughDisableJoinsAssociationsTest < ActiveRecord::TestCase
16
+ fixtures :members, :organizations, :projects, :developers, :companies, :clubs, :memberships
17
+
18
+ def setup
19
+ @member = members(:groucho)
20
+ @organization = organizations(:discordians)
21
+ @member.organization = @organization
22
+ @member.save!
23
+ @member.reload
24
+ end
25
+
26
+ def test_counting_on_disable_joins_through
27
+ no_joins = capture_sql { @member.organization_without_joins }
28
+ joins = capture_sql { @member.organization }
29
+
30
+ assert_equal @member.organization, @member.organization_without_joins
31
+ assert_equal 2, no_joins.count
32
+ assert_equal 1, joins.count
33
+ assert_match(/INNER JOIN/, joins.first)
34
+ no_joins.each do |nj|
35
+ assert_no_match(/INNER JOIN/, nj)
36
+ end
37
+ end
38
+
39
+ def test_nil_on_disable_joins_through
40
+ member = members(:blarpy_winkup)
41
+ assert_nil assert_queries_count(1) { member.organization }
42
+ assert_nil assert_queries_count(1) { member.organization_without_joins }
43
+ end
44
+
45
+ def test_preload_on_disable_joins_through
46
+ members = Member.preload(:organization, :organization_without_joins).to_a
47
+ assert_no_queries { members[0].organization }
48
+ assert_no_queries { members[0].organization_without_joins }
49
+ end
50
+
51
+ def test_has_one_through_with_belongs_to_on_disable_joins
52
+ firm = Firm.create!(name: "Adequate Holdings")
53
+ project = Project.create!(name: "Project 1", firm: firm)
54
+ Developer.create!(name: "Gorbypuff", firm: firm)
55
+
56
+ joins = capture_sql { project.lead_developer }
57
+ no_joins = capture_sql { project.lead_developer_disable_joins }
58
+
59
+ assert_equal project.lead_developer, project.lead_developer_disable_joins
60
+ assert_equal 2, no_joins.count
61
+ assert_equal 1, joins.count
62
+ assert_match(/INNER JOIN/, joins.first)
63
+ no_joins.each do |nj|
64
+ assert_no_match(/INNER JOIN/, nj)
65
+ end
66
+ end
67
+
68
+ def test_disable_joins_through_with_enum_type
69
+ joins = capture_sql { @member.club }
70
+ no_joins = capture_sql { @member.club_without_joins }
71
+
72
+ assert_equal 1, joins.size
73
+ assert_equal 2, no_joins.size
74
+
75
+ assert_match(/INNER JOIN/, joins.first)
76
+ no_joins.each do |nj|
77
+ assert_no_match(/INNER JOIN/, nj)
78
+ end
79
+
80
+ assert_match(/memberships\.type/i, no_joins.first)
81
+ end
82
+ end