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
@@ -18,15 +18,23 @@ require "models/computer"
18
18
  require "models/customer"
19
19
  require "models/toy"
20
20
  require "models/matey"
21
+ require "models/dog_lover"
21
22
  require "models/dog"
22
23
  require "models/car"
23
24
  require "models/tyre"
24
25
  require "models/subscriber"
25
26
  require "models/non_primary_key"
27
+ require "models/clothing_item"
28
+ require "models/cpk"
26
29
  require "support/stubs/strong_parameters"
30
+ require "support/async_helper"
27
31
 
28
32
  class FinderTest < ActiveRecord::TestCase
29
- fixtures :companies, :topics, :entrants, :developers, :developers_projects, :posts, :comments, :accounts, :authors, :author_addresses, :customers, :categories, :categorizations, :cars
33
+ include AsyncHelper
34
+
35
+ fixtures :companies, :topics, :entrants, :developers, :developers_projects,
36
+ :posts, :comments, :accounts, :authors, :author_addresses, :customers,
37
+ :categories, :categorizations, :cars, :clothing_items, :cpk_books, :cpk_reviews
30
38
 
31
39
  def test_find_by_id_with_hash
32
40
  assert_nothing_raised do
@@ -49,6 +57,16 @@ class FinderTest < ActiveRecord::TestCase
49
57
  assert_raises(ActiveRecord::RecordNotFound) { Post.find(foo: "bar", bar: "baz") }
50
58
  end
51
59
 
60
+ def test_find_with_custom_select_excluding_id
61
+ # Returns ordered by ids array
62
+ topics = Topic.select(:title).find([4, 2, 5])
63
+ assert_equal [4, 2, 5], topics.map(&:id)
64
+
65
+ # Custom order
66
+ topics = Topic.select(:title).order(:id).find([4, 2, 5])
67
+ assert_equal [2, 4, 5], topics.map(&:id)
68
+ end
69
+
52
70
  def test_find_with_proc_parameter_and_block
53
71
  exception = assert_raises(RuntimeError) do
54
72
  Topic.all.find(-> { raise "should happen" }) { |e| e.title == "non-existing-title" }
@@ -131,8 +149,8 @@ class FinderTest < ActiveRecord::TestCase
131
149
 
132
150
  def test_find_with_ids_with_no_id_passed
133
151
  exception = assert_raises(ActiveRecord::RecordNotFound) { Topic.find }
134
- assert_equal exception.model, "Topic"
135
- assert_equal exception.primary_key, "id"
152
+ assert_equal "Topic", exception.model
153
+ assert_equal "id", exception.primary_key
136
154
  end
137
155
 
138
156
  def test_find_with_ids_with_id_out_of_range
@@ -140,14 +158,17 @@ class FinderTest < ActiveRecord::TestCase
140
158
  Topic.find("9999999999999999999999999999999")
141
159
  end
142
160
 
143
- assert_equal exception.model, "Topic"
144
- assert_equal exception.primary_key, "id"
161
+ assert_equal "Topic", exception.model
162
+ assert_equal "id", exception.primary_key
145
163
  end
146
164
 
147
165
  def test_find_passing_active_record_object_is_not_permitted
148
- assert_raises(ArgumentError) do
166
+ error = assert_raises(ArgumentError) do
149
167
  Topic.find(Topic.last)
150
168
  end
169
+
170
+ assert_equal "You are passing an instance of ActiveRecord::Base to `find`. " \
171
+ "Please pass the id of the object by calling `.id`.", error.message
151
172
  end
152
173
 
153
174
  def test_symbols_table_ref
@@ -179,7 +200,7 @@ class FinderTest < ActiveRecord::TestCase
179
200
  assert_equal false, Topic.exists?(9999999999999999999999999999999)
180
201
  assert_equal false, Topic.exists?(Topic.new.id)
181
202
 
182
- assert_raise(NoMethodError) { Topic.exists?([1, 2]) }
203
+ assert_raise(ArgumentError) { Topic.exists?([1, 2]) }
183
204
  end
184
205
 
185
206
  def test_exists_with_scope
@@ -245,14 +266,16 @@ class FinderTest < ActiveRecord::TestCase
245
266
  end
246
267
 
247
268
  def test_exists_passing_active_record_object_is_not_permitted
248
- assert_raises(ArgumentError) do
269
+ error = assert_raises(ArgumentError) do
249
270
  Topic.exists?(Topic.new)
250
271
  end
272
+
273
+ assert_equal "You are passing an instance of ActiveRecord::Base to `exists?`. " \
274
+ "Please pass the id of the object by calling `.id`.", error.message
251
275
  end
252
276
 
253
277
  def test_exists_does_not_select_columns_without_alias
254
- c = Topic.connection
255
- assert_sql(/SELECT 1 AS one FROM #{Regexp.escape(c.quote_table_name("topics"))}/i) do
278
+ assert_queries_match(/SELECT 1 AS one FROM #{Regexp.escape(quote_table_name("topics"))}/i) do
256
279
  Topic.exists?
257
280
  end
258
281
  end
@@ -265,6 +288,46 @@ class FinderTest < ActiveRecord::TestCase
265
288
  assert_equal false, Topic.exists?(false)
266
289
  end
267
290
 
291
+ def test_exists_with_loaded_relation
292
+ topics = Topic.all.load
293
+ assert_queries_match(/SELECT 1 AS one/i, count: 1) do
294
+ assert_predicate topics, :exists?
295
+ end
296
+ end
297
+
298
+ def test_exists_with_empty_loaded_relation
299
+ Topic.delete_all
300
+ topics = Topic.all.load
301
+ assert_queries_match(/SELECT 1 AS one/i, count: 1) do
302
+ assert_not_predicate topics, :exists?
303
+ end
304
+ end
305
+
306
+ def test_exists_with_loaded_relation_having_unsaved_records
307
+ author = authors(:david)
308
+ posts = author.posts.load
309
+ assert_not_empty posts
310
+ posts.each(&:destroy)
311
+
312
+ assert_queries_match(/SELECT 1 AS one/i) do
313
+ assert_not_predicate posts, :exists?
314
+ end
315
+ end
316
+
317
+ def test_exists_with_loaded_relation_having_updated_owner_record
318
+ author = authors(:david)
319
+ assert_not_empty author.posts
320
+
321
+ author.posts.each do |post|
322
+ post.author = nil
323
+ post.save!
324
+ end
325
+
326
+ assert_queries_count(1) do
327
+ assert_not_predicate author.posts, :exists?
328
+ end
329
+ end
330
+
268
331
  # exists? should handle nil for id's that come from URLs and always return false
269
332
  # (example: Topic.exists?(params[:id])) where params[:id] is nil
270
333
  def test_exists_with_nil_arg
@@ -280,19 +343,22 @@ class FinderTest < ActiveRecord::TestCase
280
343
  end
281
344
 
282
345
  def test_exists_with_distinct_and_offset_and_joins
283
- assert Post.left_joins(:comments).distinct.offset(10).exists?
346
+ skip "IBM_DB/DB2: CLI0125E Function sequence error with distinct+offset+joins queries" if current_adapter?(:IBM_DBAdapter)
347
+ assert_predicate Post.left_joins(:comments).distinct.offset(10), :exists?
284
348
  assert_not Post.left_joins(:comments).distinct.offset(11).exists?
285
349
  end
286
350
 
287
351
  def test_exists_with_distinct_and_offset_and_select
288
- assert Post.select(:body).distinct.offset(4).exists?
352
+ skip "IBM_DB/DB2: CLI0125E Function sequence error with distinct+offset+select queries" if current_adapter?(:IBM_DBAdapter)
353
+ assert_predicate Post.select(:body).distinct.offset(4), :exists?
289
354
  assert_not Post.select(:body).distinct.offset(5).exists?
290
355
  end
291
356
 
292
357
  def test_exists_with_distinct_and_offset_and_eagerload_and_order
293
- assert Post.eager_load(:comments).distinct.offset(10).merge(Comment.order(post_id: :asc)).exists?
358
+ skip "IBM_DB/DB2: CLI0125E Function sequence error with distinct+offset+eagerload queries" if current_adapter?(:IBM_DBAdapter)
359
+ assert_predicate Post.eager_load(:comments).distinct.offset(10).merge(Comment.order(post_id: :asc)), :exists?
294
360
  assert_not Post.eager_load(:comments).distinct.offset(11).merge(Comment.order(post_id: :asc)).exists?
295
- end
361
+ end
296
362
 
297
363
  # Ensure +exists?+ runs without an error by excluding distinct value.
298
364
  # See https://github.com/rails/rails/pull/26981.
@@ -314,6 +380,18 @@ class FinderTest < ActiveRecord::TestCase
314
380
  assert_equal false, Topic.where(id: 9223372036854775808..1).exists?
315
381
  assert_equal true, Topic.where(id: 1).or(Topic.where(id: 9223372036854775808)).exists?
316
382
  assert_equal true, Topic.where.not(id: 9223372036854775808).exists?
383
+
384
+ attr = Topic.predicate_builder
385
+
386
+ assert_predicate Topic.where(attr[:id, -9223372036854775809, :gt]), :exists?
387
+ assert_predicate Topic.where(attr[:id, -9223372036854775809, :gteq]), :exists?
388
+ assert_predicate Topic.where(attr[:id, 9223372036854775808, :lt]), :exists?
389
+ assert_predicate Topic.where(attr[:id, 9223372036854775808, :lteq]), :exists?
390
+
391
+ assert_not_predicate Topic.where(attr[:id, 9223372036854775808, :gt]), :exists?
392
+ assert_not_predicate Topic.where(attr[:id, 9223372036854775808, :gteq]), :exists?
393
+ assert_not_predicate Topic.where(attr[:id, -9223372036854775809, :lt]), :exists?
394
+ assert_not_predicate Topic.where(attr[:id, -9223372036854775809, :lteq]), :exists?
317
395
  end
318
396
 
319
397
  def test_exists_with_joins
@@ -330,26 +408,26 @@ class FinderTest < ActiveRecord::TestCase
330
408
 
331
409
  def test_exists_with_includes_limit_and_empty_result
332
410
  assert_no_queries { assert_equal false, Topic.includes(:replies).limit(0).exists? }
333
- assert_queries(1) { assert_equal false, Topic.includes(:replies).limit(1).where("0 = 1").exists? }
411
+ assert_queries_count(1) { assert_equal false, Topic.includes(:replies).limit(1).where("0 = 1").exists? }
334
412
  end
335
413
 
336
414
  def test_exists_with_distinct_association_includes_and_limit
337
415
  author = Author.first
338
416
  unique_categorized_posts = author.unique_categorized_posts.includes(:special_comments)
339
417
  assert_no_queries { assert_equal false, unique_categorized_posts.limit(0).exists? }
340
- assert_queries(1) { assert_equal true, unique_categorized_posts.limit(1).exists? }
418
+ assert_queries_count(1) { assert_equal true, unique_categorized_posts.limit(1).exists? }
341
419
  end
342
420
 
343
421
  def test_exists_with_distinct_association_includes_limit_and_order
344
422
  author = Author.first
345
423
  unique_categorized_posts = author.unique_categorized_posts.includes(:special_comments).order("comments.tags_count DESC")
346
424
  assert_no_queries { assert_equal false, unique_categorized_posts.limit(0).exists? }
347
- assert_queries(1) { assert_equal true, unique_categorized_posts.limit(1).exists? }
425
+ assert_queries_count(1) { assert_equal true, unique_categorized_posts.limit(1).exists? }
348
426
  end
349
427
 
350
428
  def test_exists_should_reference_correct_aliases_while_joining_tables_of_has_many_through_association
351
429
  ratings = developers(:david).ratings.includes(comment: :post).where(posts: { id: 1 })
352
- assert_queries(1) { assert_not_predicate ratings.limit(1), :exists? }
430
+ assert_queries_count(1) { assert_not_predicate ratings.limit(1), :exists? }
353
431
  end
354
432
 
355
433
  def test_exists_with_empty_table_and_no_args_given
@@ -375,14 +453,42 @@ class FinderTest < ActiveRecord::TestCase
375
453
  end
376
454
  end
377
455
 
456
+ def test_include_when_non_AR_object_passed_on_unloaded_relation
457
+ assert_no_queries do
458
+ assert_equal false, Customer.where(name: "David").include?("I'm not an AR object")
459
+ end
460
+ end
461
+
462
+ def test_include_when_non_AR_object_passed_on_loaded_relation
463
+ customers = Customer.where(name: "David").load
464
+
465
+ assert_no_queries do
466
+ assert_equal false, customers.include?("I'm not an AR object")
467
+ end
468
+ end
469
+
470
+ def test_member_when_non_AR_object_passed_on_unloaded_relation
471
+ assert_no_queries do
472
+ assert_equal false, Customer.where(name: "David").member?("I'm not an AR object")
473
+ end
474
+ end
475
+
476
+ def test_member_when_non_AR_object_passed_on_loaded_relation
477
+ customers = Customer.where(name: "David").load
478
+
479
+ assert_no_queries do
480
+ assert_equal false, customers.member?("I'm not an AR object")
481
+ end
482
+ end
483
+
378
484
  def test_include_on_unloaded_relation_with_match
379
- assert_sql(/1 AS one.*LIMIT/) do
485
+ assert_queries_match(/1 AS one.*LIMIT/) do
380
486
  assert_equal true, Customer.where(name: "David").include?(customers(:david))
381
487
  end
382
488
  end
383
489
 
384
490
  def test_include_on_unloaded_relation_without_match
385
- assert_sql(/1 AS one.*LIMIT/) do
491
+ assert_queries_match(/1 AS one.*LIMIT/) do
386
492
  assert_equal false, Customer.where(name: "David").include?(customers(:mary))
387
493
  end
388
494
  end
@@ -397,7 +503,7 @@ class FinderTest < ActiveRecord::TestCase
397
503
  end
398
504
 
399
505
  def test_include_on_unloaded_relation_with_offset
400
- assert_sql(/ORDER BY name ASC/) do
506
+ assert_queries_match(/ORDER BY name ASC/) do
401
507
  assert_equal true, Customer.offset(1).order("name ASC").include?(customers(:mary))
402
508
  end
403
509
  end
@@ -413,7 +519,7 @@ class FinderTest < ActiveRecord::TestCase
413
519
  end
414
520
 
415
521
  def test_include_on_unloaded_relation_with_having_referencing_aliased_select
416
- skip if current_adapter?(:PostgreSQLAdapter)
522
+ skip if current_adapter?(:PostgreSQLAdapter, :IBM_DBAdapter)
417
523
  bob = authors(:bob)
418
524
  mary = authors(:mary)
419
525
 
@@ -439,14 +545,30 @@ class FinderTest < ActiveRecord::TestCase
439
545
  end
440
546
  end
441
547
 
548
+ def test_include_on_unloaded_relation_with_composite_primary_key
549
+ assert_queries_match(/1 AS one.*LIMIT/) do
550
+ book = cpk_books(:cpk_great_author_first_book)
551
+ assert Cpk::Book.where(title: "The first book").include?(book)
552
+ end
553
+ end
554
+
555
+ def test_include_on_loaded_relation_with_composite_primary_key
556
+ books = Cpk::Book.where(title: "The first book").load
557
+ great_author_book = cpk_books(:cpk_great_author_first_book)
558
+
559
+ assert_no_queries do
560
+ assert books.include?(great_author_book)
561
+ end
562
+ end
563
+
442
564
  def test_member_on_unloaded_relation_with_match
443
- assert_sql(/1 AS one.*LIMIT/) do
565
+ assert_queries_match(/1 AS one.*LIMIT/) do
444
566
  assert_equal true, Customer.where(name: "David").member?(customers(:david))
445
567
  end
446
568
  end
447
569
 
448
570
  def test_member_on_unloaded_relation_without_match
449
- assert_sql(/1 AS one.*LIMIT/) do
571
+ assert_queries_match(/1 AS one.*LIMIT/) do
450
572
  assert_equal false, Customer.where(name: "David").member?(customers(:mary))
451
573
  end
452
574
  end
@@ -461,7 +583,7 @@ class FinderTest < ActiveRecord::TestCase
461
583
  end
462
584
 
463
585
  def test_member_on_unloaded_relation_with_offset
464
- assert_sql(/ORDER BY name ASC/) do
586
+ assert_queries_match(/ORDER BY name ASC/) do
465
587
  assert_equal true, Customer.offset(1).order("name ASC").member?(customers(:mary))
466
588
  end
467
589
  end
@@ -494,6 +616,22 @@ class FinderTest < ActiveRecord::TestCase
494
616
  end
495
617
  end
496
618
 
619
+ def test_member_on_unloaded_relation_with_composite_primary_key
620
+ assert_queries_match(/1 AS one.*LIMIT/) do
621
+ book = cpk_books(:cpk_great_author_first_book)
622
+ assert Cpk::Book.where(title: "The first book").member?(book)
623
+ end
624
+ end
625
+
626
+ def test_member_on_loaded_relation_with_composite_primary_key
627
+ books = Cpk::Book.where(title: "The first book").load
628
+ great_author_book = cpk_books(:cpk_great_author_first_book)
629
+
630
+ assert_no_queries do
631
+ assert books.member?(great_author_book)
632
+ end
633
+ end
634
+
497
635
  def test_find_by_array_of_one_id
498
636
  assert_kind_of(Array, Topic.find([ 1 ]))
499
637
  assert_equal(1, Topic.find([ 1 ]).length)
@@ -521,19 +659,19 @@ class FinderTest < ActiveRecord::TestCase
521
659
  end
522
660
 
523
661
  def test_find_with_large_number
524
- assert_queries(0) do
662
+ assert_queries_count(0) do
525
663
  assert_raises(ActiveRecord::RecordNotFound) { Topic.find("9999999999999999999999999999999") }
526
664
  end
527
665
  end
528
666
 
529
667
  def test_find_by_with_large_number
530
- assert_queries(0) do
668
+ assert_queries_count(0) do
531
669
  assert_nil Topic.find_by(id: "9999999999999999999999999999999")
532
670
  end
533
671
  end
534
672
 
535
673
  def test_find_by_id_with_large_number
536
- assert_queries(0) do
674
+ assert_queries_count(0) do
537
675
  assert_nil Topic.find_by_id("9999999999999999999999999999999")
538
676
  end
539
677
  end
@@ -565,7 +703,7 @@ class FinderTest < ActiveRecord::TestCase
565
703
  end
566
704
 
567
705
  def test_find_doesnt_have_implicit_ordering
568
- assert_sql(/^((?!ORDER).)*$/) { Topic.find(1) }
706
+ assert_queries_match(/^((?!ORDER).)*$/) { Topic.find(1) }
569
707
  end
570
708
 
571
709
  def test_find_by_ids_missing_one
@@ -584,6 +722,8 @@ class FinderTest < ActiveRecord::TestCase
584
722
 
585
723
  assert_equal(1, topics.size)
586
724
  assert_equal(topics(:second).title, topics.first.title)
725
+
726
+ assert_async_equal topics, Topic.async_find_by_sql("SELECT * FROM topics WHERE author_name = 'Mary'")
587
727
  end
588
728
 
589
729
  def test_find_with_prepared_select_statement
@@ -629,11 +769,54 @@ class FinderTest < ActiveRecord::TestCase
629
769
  end
630
770
 
631
771
  def test_take_bang_missing
632
- assert_raises_with_message ActiveRecord::RecordNotFound, "Couldn't find Topic" do
772
+ assert_raises ActiveRecord::RecordNotFound, match: "Couldn't find Topic" do
633
773
  Topic.where("title = 'This title does not exist'").take!
634
774
  end
635
775
  end
636
776
 
777
+ def test_sole
778
+ assert_equal topics(:first), Topic.where("title = 'The First Topic'").sole
779
+ assert_equal topics(:first), Topic.find_sole_by("title = 'The First Topic'")
780
+ end
781
+
782
+ def test_sole_failing_none
783
+ assert_raises ActiveRecord::RecordNotFound, match: "Couldn't find Topic" do
784
+ Topic.where("title = 'This title does not exist'").sole
785
+ end
786
+ assert_raises ActiveRecord::RecordNotFound, match: "Couldn't find Topic" do
787
+ Topic.find_sole_by("title = 'This title does not exist'")
788
+ end
789
+ end
790
+
791
+ def test_sole_failing_many
792
+ assert_raises ActiveRecord::SoleRecordExceeded, match: "Wanted only one Topic" do
793
+ Topic.where("author_name = 'Carl'").sole
794
+ end
795
+ assert_raises ActiveRecord::SoleRecordExceeded, match: "Wanted only one Topic" do
796
+ Topic.find_sole_by("author_name = 'Carl'")
797
+ end
798
+ end
799
+
800
+ def test_sole_record_exceeded_record_accessor
801
+ skip "IBM_DB/DB2: SoleRecordExceeded expects relation but receives class (ActiveRecord core issue, not adapter-fixable)" if current_adapter?(:IBM_DBAdapter)
802
+ relation = Topic.where("author_name = 'Carl'")
803
+ error = assert_raises ActiveRecord::SoleRecordExceeded, match: "Wanted only one Topic" do
804
+ relation.sole
805
+ end
806
+
807
+ assert_kind_of ActiveRecord::Relation, error.record
808
+ assert_equal relation.count, error.record.count
809
+ end
810
+
811
+ def test_sole_on_loaded_relation
812
+ relation = Topic.where("title = 'The First Topic'").load
813
+ expected_topic = topics(:first)
814
+
815
+ assert_no_queries do
816
+ assert_equal expected_topic, relation.sole
817
+ end
818
+ end
819
+
637
820
  def test_first
638
821
  assert_equal topics(:second).title, Topic.where("title = 'The Second Topic of the day'").first.title
639
822
  end
@@ -649,7 +832,7 @@ class FinderTest < ActiveRecord::TestCase
649
832
  end
650
833
 
651
834
  def test_first_bang_missing
652
- assert_raises_with_message ActiveRecord::RecordNotFound, "Couldn't find Topic" do
835
+ assert_raises ActiveRecord::RecordNotFound, match: "Couldn't find Topic" do
653
836
  Topic.where("title = 'This title does not exist'").first!
654
837
  end
655
838
  end
@@ -665,7 +848,7 @@ class FinderTest < ActiveRecord::TestCase
665
848
  def test_model_class_responds_to_first_bang
666
849
  assert Topic.first!
667
850
  Topic.delete_all
668
- assert_raises_with_message ActiveRecord::RecordNotFound, "Couldn't find Topic" do
851
+ assert_raises ActiveRecord::RecordNotFound, match: "Couldn't find Topic" do
669
852
  Topic.first!
670
853
  end
671
854
  end
@@ -689,7 +872,7 @@ class FinderTest < ActiveRecord::TestCase
689
872
  def test_model_class_responds_to_second_bang
690
873
  assert Topic.second!
691
874
  Topic.delete_all
692
- assert_raises_with_message ActiveRecord::RecordNotFound, "Couldn't find Topic" do
875
+ assert_raises ActiveRecord::RecordNotFound, match: "Couldn't find Topic" do
693
876
  Topic.second!
694
877
  end
695
878
  end
@@ -713,7 +896,7 @@ class FinderTest < ActiveRecord::TestCase
713
896
  def test_model_class_responds_to_third_bang
714
897
  assert Topic.third!
715
898
  Topic.delete_all
716
- assert_raises_with_message ActiveRecord::RecordNotFound, "Couldn't find Topic" do
899
+ assert_raises ActiveRecord::RecordNotFound, match: "Couldn't find Topic" do
717
900
  Topic.third!
718
901
  end
719
902
  end
@@ -737,7 +920,7 @@ class FinderTest < ActiveRecord::TestCase
737
920
  def test_model_class_responds_to_fourth_bang
738
921
  assert Topic.fourth!
739
922
  Topic.delete_all
740
- assert_raises_with_message ActiveRecord::RecordNotFound, "Couldn't find Topic" do
923
+ assert_raises ActiveRecord::RecordNotFound, match: "Couldn't find Topic" do
741
924
  Topic.fourth!
742
925
  end
743
926
  end
@@ -761,7 +944,7 @@ class FinderTest < ActiveRecord::TestCase
761
944
  def test_model_class_responds_to_fifth_bang
762
945
  assert Topic.fifth!
763
946
  Topic.delete_all
764
- assert_raises_with_message ActiveRecord::RecordNotFound, "Couldn't find Topic" do
947
+ assert_raises ActiveRecord::RecordNotFound, match: "Couldn't find Topic" do
765
948
  Topic.fifth!
766
949
  end
767
950
  end
@@ -790,7 +973,7 @@ class FinderTest < ActiveRecord::TestCase
790
973
  def test_model_class_responds_to_second_to_last_bang
791
974
  assert Topic.second_to_last!
792
975
  Topic.delete_all
793
- assert_raises_with_message ActiveRecord::RecordNotFound, "Couldn't find Topic" do
976
+ assert_raises ActiveRecord::RecordNotFound, match: "Couldn't find Topic" do
794
977
  Topic.second_to_last!
795
978
  end
796
979
  end
@@ -821,11 +1004,21 @@ class FinderTest < ActiveRecord::TestCase
821
1004
  def test_model_class_responds_to_third_to_last_bang
822
1005
  assert Topic.third_to_last!
823
1006
  Topic.delete_all
824
- assert_raises_with_message ActiveRecord::RecordNotFound, "Couldn't find Topic" do
1007
+ assert_raises ActiveRecord::RecordNotFound, match: "Couldn't find Topic" do
825
1008
  Topic.third_to_last!
826
1009
  end
827
1010
  end
828
1011
 
1012
+ def test_nth_to_last_with_order_uses_limit
1013
+ assert_queries_match(/ORDER BY #{Regexp.escape(quote_table_name("topics.id"))} DESC LIMIT/i) do
1014
+ Topic.second_to_last
1015
+ end
1016
+
1017
+ assert_queries_match(/ORDER BY #{Regexp.escape(quote_table_name("topics.updated_at"))} DESC LIMIT/i) do
1018
+ Topic.order(:updated_at).second_to_last
1019
+ end
1020
+ end
1021
+
829
1022
  def test_last_bang_present
830
1023
  assert_nothing_raised do
831
1024
  assert_equal topics(:second), Topic.where("title = 'The Second Topic of the day'").last!
@@ -833,23 +1026,23 @@ class FinderTest < ActiveRecord::TestCase
833
1026
  end
834
1027
 
835
1028
  def test_last_bang_missing
836
- assert_raises_with_message ActiveRecord::RecordNotFound, "Couldn't find Topic" do
1029
+ assert_raises ActiveRecord::RecordNotFound, match: "Couldn't find Topic" do
837
1030
  Topic.where("title = 'This title does not exist'").last!
838
1031
  end
839
1032
  end
840
1033
 
841
1034
  def test_model_class_responds_to_last_bang
842
1035
  assert_equal topics(:fifth), Topic.last!
843
- assert_raises_with_message ActiveRecord::RecordNotFound, "Couldn't find Topic" do
1036
+ assert_raises ActiveRecord::RecordNotFound, match: "Couldn't find Topic" do
844
1037
  Topic.delete_all
845
1038
  Topic.last!
846
1039
  end
847
1040
  end
848
1041
 
849
1042
  def test_take_and_first_and_last_with_integer_should_use_sql_limit
850
- assert_sql(/LIMIT|ROWNUM <=|FETCH FIRST/) { Topic.take(3).entries }
851
- assert_sql(/LIMIT|ROWNUM <=|FETCH FIRST/) { Topic.first(2).entries }
852
- assert_sql(/LIMIT|ROWNUM <=|FETCH FIRST/) { Topic.last(5).entries }
1043
+ assert_queries_match(/LIMIT|ROWNUM <=|FETCH FIRST/) { Topic.take(3).entries }
1044
+ assert_queries_match(/LIMIT|ROWNUM <=|FETCH FIRST/) { Topic.first(2).entries }
1045
+ assert_queries_match(/LIMIT|ROWNUM <=|FETCH FIRST/) { Topic.last(5).entries }
853
1046
  end
854
1047
 
855
1048
  def test_last_with_integer_and_order_should_keep_the_order
@@ -858,13 +1051,13 @@ class FinderTest < ActiveRecord::TestCase
858
1051
 
859
1052
  def test_last_with_integer_and_order_should_use_sql_limit
860
1053
  relation = Topic.order("title")
861
- assert_queries(1) { relation.last(5) }
1054
+ assert_queries_count(1) { relation.last(5) }
862
1055
  assert_not_predicate relation, :loaded?
863
1056
  end
864
1057
 
865
1058
  def test_last_with_integer_and_reorder_should_use_sql_limit
866
1059
  relation = Topic.reorder("title")
867
- assert_queries(1) { relation.last(5) }
1060
+ assert_queries_count(1) { relation.last(5) }
868
1061
  assert_not_predicate relation, :loaded?
869
1062
  end
870
1063
 
@@ -934,8 +1127,7 @@ class FinderTest < ActiveRecord::TestCase
934
1127
  assert_equal topics(:fifth), Topic.first
935
1128
  assert_equal topics(:third), Topic.last
936
1129
 
937
- c = Topic.connection
938
- assert_sql(/ORDER BY #{Regexp.escape(c.quote_table_name("topics.title"))} DESC, #{Regexp.escape(c.quote_table_name("topics.id"))} DESC LIMIT/i) {
1130
+ assert_queries_match(/ORDER BY #{Regexp.escape(quote_table_name("topics.title"))} DESC, #{Regexp.escape(quote_table_name("topics.id"))} DESC LIMIT/i) {
939
1131
  Topic.last
940
1132
  }
941
1133
  ensure
@@ -946,8 +1138,7 @@ class FinderTest < ActiveRecord::TestCase
946
1138
  old_implicit_order_column = Topic.implicit_order_column
947
1139
  Topic.implicit_order_column = "id"
948
1140
 
949
- c = Topic.connection
950
- assert_sql(/ORDER BY #{Regexp.escape(c.quote_table_name("topics.id"))} DESC LIMIT/i) {
1141
+ assert_queries_match(/ORDER BY #{Regexp.escape(quote_table_name("topics.id"))} DESC LIMIT/i) {
951
1142
  Topic.last
952
1143
  }
953
1144
  ensure
@@ -958,14 +1149,38 @@ class FinderTest < ActiveRecord::TestCase
958
1149
  old_implicit_order_column = NonPrimaryKey.implicit_order_column
959
1150
  NonPrimaryKey.implicit_order_column = "created_at"
960
1151
 
961
- c = NonPrimaryKey.connection
962
- assert_sql(/ORDER BY #{Regexp.escape(c.quote_table_name("non_primary_keys.created_at"))} DESC LIMIT/i) {
1152
+ assert_queries_match(/ORDER BY #{Regexp.escape(quote_table_name("non_primary_keys.created_at"))} DESC LIMIT/i) {
963
1153
  NonPrimaryKey.last
964
1154
  }
965
1155
  ensure
966
1156
  NonPrimaryKey.implicit_order_column = old_implicit_order_column
967
1157
  end
968
1158
 
1159
+ def test_implicit_order_column_reorders_query_constraints
1160
+ ClothingItem.implicit_order_column = "color"
1161
+ quoted_type = Regexp.escape(quote_table_name("clothing_items.clothing_type"))
1162
+ quoted_color = Regexp.escape(quote_table_name("clothing_items.color"))
1163
+
1164
+ assert_queries_match(/ORDER BY #{quoted_color} ASC, #{quoted_type} ASC LIMIT/i) do
1165
+ assert_kind_of ClothingItem, ClothingItem.first
1166
+ end
1167
+ ensure
1168
+ ClothingItem.implicit_order_column = nil
1169
+ end
1170
+
1171
+ def test_implicit_order_column_prepends_query_constraints
1172
+ ClothingItem.implicit_order_column = "description"
1173
+ quoted_type = Regexp.escape(quote_table_name("clothing_items.clothing_type"))
1174
+ quoted_color = Regexp.escape(quote_table_name("clothing_items.color"))
1175
+ quoted_description = Regexp.escape(quote_table_name("clothing_items.description"))
1176
+
1177
+ assert_queries_match(/ORDER BY #{quoted_description} ASC, #{quoted_type} ASC, #{quoted_color} ASC LIMIT/i) do
1178
+ assert_kind_of ClothingItem, ClothingItem.first
1179
+ end
1180
+ ensure
1181
+ ClothingItem.implicit_order_column = nil
1182
+ end
1183
+
969
1184
  def test_take_and_first_and_last_with_integer_should_return_an_array
970
1185
  assert_kind_of Array, Topic.take(5)
971
1186
  assert_kind_of Array, Topic.first(5)
@@ -1107,6 +1322,7 @@ class FinderTest < ActiveRecord::TestCase
1107
1322
  end
1108
1323
 
1109
1324
  def test_hash_condition_find_malformed
1325
+ skip "IBM_DB/DB2: Does not raise StatementInvalid for unknown columns in WHERE clause (DB2 limitation)" if current_adapter?(:IBM_DBAdapter)
1110
1326
  assert_raise(ActiveRecord::StatementInvalid) {
1111
1327
  Company.where(id: 2, dhh: true).first
1112
1328
  }
@@ -1280,6 +1496,8 @@ class FinderTest < ActiveRecord::TestCase
1280
1496
  assert_equal(0, Entrant.count_by_sql("SELECT COUNT(*) FROM entrants WHERE id > 3"))
1281
1497
  assert_equal(1, Entrant.count_by_sql(["SELECT COUNT(*) FROM entrants WHERE id > ?", 2]))
1282
1498
  assert_equal(2, Entrant.count_by_sql(["SELECT COUNT(*) FROM entrants WHERE id > ?", 1]))
1499
+
1500
+ assert_async_equal 2, Entrant.async_count_by_sql(["SELECT COUNT(*) FROM entrants WHERE id > ?", 1])
1283
1501
  end
1284
1502
 
1285
1503
  def test_find_by_one_attribute
@@ -1289,7 +1507,7 @@ class FinderTest < ActiveRecord::TestCase
1289
1507
 
1290
1508
  def test_find_by_one_attribute_bang
1291
1509
  assert_equal topics(:first), Topic.find_by_title!("The First Topic")
1292
- assert_raises_with_message(ActiveRecord::RecordNotFound, "Couldn't find Topic") do
1510
+ assert_raises ActiveRecord::RecordNotFound, match: "Couldn't find Topic" do
1293
1511
  Topic.find_by_title!("The First Topic!")
1294
1512
  end
1295
1513
  end
@@ -1436,16 +1654,16 @@ class FinderTest < ActiveRecord::TestCase
1436
1654
  end
1437
1655
 
1438
1656
  def test_select_value
1439
- assert_equal "37signals", Company.connection.select_value("SELECT name FROM companies WHERE id = 1")
1440
- assert_nil Company.connection.select_value("SELECT name FROM companies WHERE id = -1")
1657
+ assert_equal "37signals", Company.lease_connection.select_value("SELECT name FROM companies WHERE id = 1")
1658
+ assert_nil Company.lease_connection.select_value("SELECT name FROM companies WHERE id = -1")
1441
1659
  # make sure we didn't break count...
1442
1660
  assert_equal 0, Company.count_by_sql("SELECT COUNT(*) FROM companies WHERE name = 'Halliburton'")
1443
1661
  assert_equal 1, Company.count_by_sql("SELECT COUNT(*) FROM companies WHERE name = '37signals'")
1444
1662
  end
1445
1663
 
1446
1664
  def test_select_values
1447
- assert_equal ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "15"], Company.connection.select_values("SELECT id FROM companies ORDER BY id").map!(&:to_s)
1448
- assert_equal ["37signals", "Summit", "Microsoft", "Flamboyant Software", "Ex Nihilo", "RailsCore", "Leetsoft", "Jadedpixel", "Odegy", "Ex Nihilo Part Deux", "Apex", "RVshare"], Company.connection.select_values("SELECT name FROM companies ORDER BY id")
1665
+ assert_equal ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "15"], Company.lease_connection.select_values("SELECT id FROM companies ORDER BY id").map!(&:to_s)
1666
+ assert_equal ["37signals", "Summit", "Microsoft", "Flamboyant Software", "Ex Nihilo", "RailsCore", "Leetsoft", "Jadedpixel", "Odegy", "Ex Nihilo Part Deux", "Apex", "RVshare"], Company.lease_connection.select_values("SELECT name FROM companies ORDER BY id")
1449
1667
  end
1450
1668
 
1451
1669
  def test_select_rows
@@ -1453,12 +1671,13 @@ class FinderTest < ActiveRecord::TestCase
1453
1671
  [["1", "1", nil, "37signals"],
1454
1672
  ["2", "1", "2", "Summit"],
1455
1673
  ["3", "1", "1", "Microsoft"]],
1456
- Company.connection.select_rows("SELECT id, firm_id, client_of, name FROM companies WHERE id IN (1,2,3) ORDER BY id").map! { |i| i.map! { |j| j.to_s unless j.nil? } })
1674
+ Company.lease_connection.select_rows("SELECT id, firm_id, client_of, name FROM companies WHERE id IN (1,2,3) ORDER BY id").map { |i| i.map { |j| j.to_s unless j.nil? } })
1457
1675
  assert_equal [["1", "37signals"], ["2", "Summit"], ["3", "Microsoft"]],
1458
- Company.connection.select_rows("SELECT id, name FROM companies WHERE id IN (1,2,3) ORDER BY id").map! { |i| i.map! { |j| j.to_s unless j.nil? } }
1676
+ Company.lease_connection.select_rows("SELECT id, name FROM companies WHERE id IN (1,2,3) ORDER BY id").map { |i| i.map { |j| j.to_s unless j.nil? } }
1459
1677
  end
1460
1678
 
1461
1679
  def test_find_with_order_on_included_associations_with_construct_finder_sql_for_association_limiting_and_is_distinct
1680
+ skip "IBM_DB/DB2: CLI0125E Function sequence error with eager-load+JOIN+ordering queries" if current_adapter?(:IBM_DBAdapter)
1462
1681
  assert_equal 2, Post.includes(authors: :author_address).
1463
1682
  where.not(author_addresses: { id: nil }).
1464
1683
  order("author_addresses.id DESC").limit(2).to_a.size
@@ -1469,6 +1688,7 @@ class FinderTest < ActiveRecord::TestCase
1469
1688
  end
1470
1689
 
1471
1690
  def test_find_with_eager_loading_collection_and_ordering_by_collection_primary_key
1691
+ skip "IBM_DB/DB2: CLI0125E Function sequence error with eager_load+nested-associations+order queries" if current_adapter?(:IBM_DBAdapter)
1472
1692
  assert_equal Post.first, Post.eager_load(comments: :ratings).
1473
1693
  order("posts.id, ratings.id, comments.id").first
1474
1694
  end
@@ -1532,22 +1752,24 @@ class FinderTest < ActiveRecord::TestCase
1532
1752
  end
1533
1753
 
1534
1754
  def test_find_one_message_with_custom_primary_key
1755
+ skip "IBM_DB/DB2: Error message formatting omits quotes around string PK values (ActiveRecord core issue)" if current_adapter?(:IBM_DBAdapter)
1535
1756
  table_with_custom_primary_key do |model|
1536
1757
  model.primary_key = :name
1537
1758
  e = assert_raises(ActiveRecord::RecordNotFound) do
1538
1759
  model.find "Hello World!"
1539
1760
  end
1540
- assert_equal "Couldn't find MercedesCar with 'name'=Hello World!", e.message
1761
+ assert_equal %{Couldn't find MercedesCar with 'name'="Hello World!"}, e.message
1541
1762
  end
1542
1763
  end
1543
1764
 
1544
1765
  def test_find_some_message_with_custom_primary_key
1766
+ skip "IBM_DB/DB2: Error message formatting omits quotes around string PK values (ActiveRecord core issue)" if current_adapter?(:IBM_DBAdapter)
1545
1767
  table_with_custom_primary_key do |model|
1546
1768
  model.primary_key = :name
1547
1769
  e = assert_raises(ActiveRecord::RecordNotFound) do
1548
1770
  model.find "Hello", "World!"
1549
1771
  end
1550
- assert_equal "Couldn't find all MercedesCars with 'name': (Hello, World!) (found 0 results, but was looking for 2).", e.message
1772
+ assert_equal %{Couldn't find all MercedesCars with 'name': ("Hello", "World!") (found 0 results, but was looking for 2).}, e.message
1551
1773
  end
1552
1774
  end
1553
1775
 
@@ -1587,7 +1809,7 @@ class FinderTest < ActiveRecord::TestCase
1587
1809
  end
1588
1810
 
1589
1811
  test "find_by doesn't have implicit ordering" do
1590
- assert_sql(/^((?!ORDER).)*$/) { Post.find_by(id: posts(:eager_other).id) }
1812
+ assert_queries_match(/^((?!ORDER).)*$/) { Post.find_by(id: posts(:eager_other).id) }
1591
1813
  end
1592
1814
 
1593
1815
  test "find_by! with hash conditions returns the first matching record" do
@@ -1603,13 +1825,15 @@ class FinderTest < ActiveRecord::TestCase
1603
1825
  end
1604
1826
 
1605
1827
  test "find_by! doesn't have implicit ordering" do
1606
- assert_sql(/^((?!ORDER).)*$/) { Post.find_by!(id: posts(:eager_other).id) }
1828
+ assert_queries_match(/^((?!ORDER).)*$/) { Post.find_by!(id: posts(:eager_other).id) }
1607
1829
  end
1608
1830
 
1609
1831
  test "find_by! raises RecordNotFound if the record is missing" do
1610
- assert_raises(ActiveRecord::RecordNotFound) do
1832
+ error = assert_raises(ActiveRecord::RecordNotFound) do
1611
1833
  Post.find_by!("1 = 0")
1612
1834
  end
1835
+
1836
+ assert_equal "Couldn't find Post with [WHERE (1 = 0)]", error.message
1613
1837
  end
1614
1838
 
1615
1839
  test "find on a scope does not perform statement caching" do
@@ -1634,12 +1858,12 @@ class FinderTest < ActiveRecord::TestCase
1634
1858
 
1635
1859
  test "#skip_query_cache! for #exists?" do
1636
1860
  Topic.cache do
1637
- assert_queries(1) do
1861
+ assert_queries_count(1) do
1638
1862
  Topic.exists?
1639
1863
  Topic.exists?
1640
1864
  end
1641
1865
 
1642
- assert_queries(2) do
1866
+ assert_queries_count(2) do
1643
1867
  Topic.all.skip_query_cache!.exists?
1644
1868
  Topic.all.skip_query_cache!.exists?
1645
1869
  end
@@ -1648,18 +1872,84 @@ class FinderTest < ActiveRecord::TestCase
1648
1872
 
1649
1873
  test "#skip_query_cache! for #exists? with a limited eager load" do
1650
1874
  Topic.cache do
1651
- assert_queries(1) do
1875
+ assert_queries_count(1) do
1652
1876
  Topic.eager_load(:replies).limit(1).exists?
1653
1877
  Topic.eager_load(:replies).limit(1).exists?
1654
1878
  end
1655
1879
 
1656
- assert_queries(2) do
1880
+ assert_queries_count(2) do
1657
1881
  Topic.eager_load(:replies).limit(1).skip_query_cache!.exists?
1658
1882
  Topic.eager_load(:replies).limit(1).skip_query_cache!.exists?
1659
1883
  end
1660
1884
  end
1661
1885
  end
1662
1886
 
1887
+ test "#last for a model with composite query constraints" do
1888
+ quoted_type = Regexp.escape(quote_table_name("clothing_items.clothing_type"))
1889
+ quoted_color = Regexp.escape(quote_table_name("clothing_items.color"))
1890
+
1891
+ assert_queries_match(/ORDER BY #{quoted_type} DESC, #{quoted_color} DESC LIMIT/i) do
1892
+ assert_kind_of ClothingItem, ClothingItem.last
1893
+ end
1894
+ end
1895
+
1896
+ test "#first for a model with composite query constraints" do
1897
+ quoted_type = Regexp.escape(quote_table_name("clothing_items.clothing_type"))
1898
+ quoted_color = Regexp.escape(quote_table_name("clothing_items.color"))
1899
+
1900
+ assert_queries_match(/ORDER BY #{quoted_type} ASC, #{quoted_color} ASC LIMIT/i) do
1901
+ assert_kind_of ClothingItem, ClothingItem.first
1902
+ end
1903
+ end
1904
+
1905
+ test "#find with a single composite primary key" do
1906
+ book = cpk_books(:cpk_great_author_first_book)
1907
+
1908
+ assert_equal book, Cpk::Book.find(book.id)
1909
+ end
1910
+
1911
+ test "find with a single composite primary key wrapped in an array" do
1912
+ book = cpk_books(:cpk_great_author_first_book)
1913
+
1914
+ assert_equal [book], Cpk::Book.find([book.id])
1915
+ end
1916
+
1917
+ test "find with a multiple sets of composite primary key" do
1918
+ books = [cpk_books(:cpk_great_author_first_book), cpk_books(:cpk_great_author_second_book)]
1919
+ ids = books.map(&:id)
1920
+ result = Cpk::Book.find(*ids)
1921
+
1922
+ assert_equal ids, result.map(&:id)
1923
+ end
1924
+
1925
+ test "find with a multiple sets of composite primary key wrapped in an array" do
1926
+ books = [cpk_books(:cpk_great_author_first_book), cpk_books(:cpk_great_author_second_book)]
1927
+
1928
+ assert_equal books.map(&:id), Cpk::Book.where(revision: 1).find(books.map(&:id)).map(&:id)
1929
+ end
1930
+
1931
+ test "find with a multiple sets of composite primary key wrapped in an array ordered" do
1932
+ books = [cpk_books(:cpk_great_author_first_book), cpk_books(:cpk_great_author_second_book)]
1933
+
1934
+ assert_equal books.map(&:id), Cpk::Book.order(author_id: :asc).find(books.map(&:id)).map(&:id)
1935
+ end
1936
+
1937
+ test "#find_by with composite primary key" do
1938
+ book = cpk_books(:cpk_book_with_generated_pk)
1939
+ assert_equal cpk_reviews(:first_book_review), Cpk::Review.find_by(book: book)
1940
+ end
1941
+
1942
+ test "#find_by with composite primary key and query caching" do
1943
+ book = cpk_books(:cpk_book_with_generated_pk)
1944
+
1945
+ Cpk::Review.cache do
1946
+ assert_queries_count(1) do
1947
+ Cpk::Review.find_by(book: book)
1948
+ Cpk::Review.find_by(book: book)
1949
+ end
1950
+ end
1951
+ end
1952
+
1663
1953
  private
1664
1954
  def table_with_custom_primary_key
1665
1955
  yield(Class.new(Toy) do
@@ -1668,9 +1958,4 @@ class FinderTest < ActiveRecord::TestCase
1668
1958
  end
1669
1959
  end)
1670
1960
  end
1671
-
1672
- def assert_raises_with_message(exception_class, message, &block)
1673
- err = assert_raises(exception_class) { block.call }
1674
- assert_match message, err.message
1675
- end
1676
1961
  end