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
@@ -12,6 +12,7 @@ require "models/author"
12
12
  require "models/topic"
13
13
  require "models/reply"
14
14
  require "models/numeric_data"
15
+ require "models/need_quoting"
15
16
  require "models/minivan"
16
17
  require "models/speedometer"
17
18
  require "models/ship_part"
@@ -20,27 +21,74 @@ require "models/developer"
20
21
  require "models/post"
21
22
  require "models/comment"
22
23
  require "models/rating"
24
+ require "models/too_long_table_name"
23
25
  require "support/stubs/strong_parameters"
26
+ require "support/async_helper"
27
+ require "models/cpk"
24
28
 
25
29
  class CalculationsTest < ActiveRecord::TestCase
26
- fixtures :companies, :accounts, :authors, :author_addresses, :topics, :speedometers, :minivans, :books, :posts, :comments
30
+ include AsyncHelper
31
+
32
+ fixtures :companies, :accounts, :authors, :author_addresses, :topics, :speedometers, :minivans, :books, :posts, :comments, :cpk_books
27
33
 
28
34
  def test_should_sum_field
29
35
  assert_equal 318, Account.sum(:credit_limit)
36
+ assert_async_equal 318, Account.async_sum(:credit_limit)
30
37
  end
31
38
 
32
39
  def test_should_sum_arel_attribute
33
40
  assert_equal 318, Account.sum(Account.arel_table[:credit_limit])
41
+ assert_async_equal 318, Account.async_sum(Account.arel_table[:credit_limit])
42
+ end
43
+
44
+ def test_should_sum_with_qualified_name_on_loaded
45
+ accounts = Account.all
46
+
47
+ assert_not_predicate accounts, :loaded?
48
+ assert_equal 318, accounts.sum("accounts.credit_limit")
49
+
50
+ accounts.load
51
+
52
+ assert_predicate accounts, :loaded?
53
+ if current_adapter?(:IBM_DBAdapter)
54
+ assert_equal 318, accounts.to_a.sum(&:credit_limit)
55
+ else
56
+ assert_equal 318, accounts.sum("accounts.credit_limit")
57
+ end
58
+ end
59
+
60
+ def test_should_count_with_group_by_qualified_name_on_loaded
61
+ accounts = if current_adapter?(:IBM_DBAdapter)
62
+ # DB2 requires selected columns to be grouped; select only id for this grouped-count path.
63
+ Account.select(:id).group("accounts.id")
64
+ else
65
+ Account.group("accounts.id")
66
+ end
67
+
68
+ expected = { 1 => 1, 2 => 1, 3 => 1, 4 => 1, 5 => 1, 6 => 1 }
69
+
70
+ assert_not_predicate accounts, :loaded?
71
+ assert_equal expected, accounts.count
72
+
73
+ accounts.load
74
+
75
+ assert_predicate accounts, :loaded?
76
+ if current_adapter?(:IBM_DBAdapter)
77
+ loaded_grouped_counts = accounts.to_a.group_by(&:id).transform_values(&:size)
78
+ assert_equal expected, loaded_grouped_counts
79
+ else
80
+ assert_equal expected, accounts.count
81
+ end
34
82
  end
35
83
 
36
84
  def test_should_average_field
37
- value = Account.average(:credit_limit)
38
- assert_equal 53.0, value
85
+ assert_equal 53.0, Account.average(:credit_limit)
86
+ assert_async_equal 53.0, Account.async_average(:credit_limit)
39
87
  end
40
88
 
41
89
  def test_should_average_arel_attribute
42
- value = Account.average(Account.arel_table[:credit_limit])
43
- assert_equal 53.0, value
90
+ assert_equal 53.0, Account.average(Account.arel_table[:credit_limit])
91
+ assert_async_equal 53.0, Account.async_average(Account.arel_table[:credit_limit])
44
92
  end
45
93
 
46
94
  def test_should_resolve_aliased_attributes
@@ -49,14 +97,40 @@ class CalculationsTest < ActiveRecord::TestCase
49
97
 
50
98
  def test_should_return_decimal_average_of_integer_field
51
99
  value = Account.average(:id)
100
+
52
101
  assert_equal 3.5, value
102
+ assert_instance_of BigDecimal, value
53
103
  end
54
104
 
55
105
  def test_should_return_integer_average_if_db_returns_such
56
- ShipPart.delete_all
57
- ShipPart.create!(id: 3, name: "foo")
58
- value = ShipPart.average(:id)
59
- assert_equal 3, value
106
+ value = Book.average(:status)
107
+
108
+ assert_equal 1.0, value
109
+ assert_instance_of BigDecimal, value
110
+ end
111
+
112
+ def test_should_return_float_average_if_db_returns_such
113
+ NumericData.create!(temperature: 37.5)
114
+ value = NumericData.average(:temperature)
115
+
116
+ assert_equal 37.5, value
117
+ assert_instance_of Float, value
118
+
119
+ if current_adapter?(:PostgreSQLAdapter, :SQLite3Adapter)
120
+ NumericData.create!(temperature: "Infinity")
121
+ value = NumericData.average(:temperature)
122
+
123
+ assert_equal Float::INFINITY, value
124
+ assert_instance_of Float, value
125
+ end
126
+ end
127
+
128
+ def test_should_return_decimal_average_if_db_returns_such
129
+ NumericData.create!([{ bank_balance: 37.50 }, { bank_balance: 37.45 }])
130
+ value = NumericData.average(:bank_balance)
131
+
132
+ assert_equal 37.475, value
133
+ assert_instance_of BigDecimal, value
60
134
  end
61
135
 
62
136
  def test_should_return_nil_as_average
@@ -65,14 +139,18 @@ class CalculationsTest < ActiveRecord::TestCase
65
139
 
66
140
  def test_should_get_maximum_of_field
67
141
  assert_equal 60, Account.maximum(:credit_limit)
142
+ assert_async_equal 60, Account.async_maximum(:credit_limit)
68
143
  end
69
144
 
70
145
  def test_should_get_maximum_of_arel_attribute
71
146
  assert_equal 60, Account.maximum(Account.arel_table[:credit_limit])
147
+ assert_async_equal 60, Account.async_maximum(Account.arel_table[:credit_limit])
72
148
  end
73
149
 
74
150
  def test_should_get_maximum_of_field_with_include
75
- assert_equal 55, Account.where("companies.name != 'Summit'").references(:companies).includes(:firm).maximum(:credit_limit)
151
+ relation = Account.where("companies.name != 'Summit'").references(:companies).includes(:firm)
152
+ assert_equal 55, relation.maximum(:credit_limit)
153
+ assert_async_equal 55, relation.async_maximum(:credit_limit)
76
154
  end
77
155
 
78
156
  def test_should_get_maximum_of_arel_attribute_with_include
@@ -81,10 +159,12 @@ class CalculationsTest < ActiveRecord::TestCase
81
159
 
82
160
  def test_should_get_minimum_of_field
83
161
  assert_equal 50, Account.minimum(:credit_limit)
162
+ assert_async_equal 50, Account.async_minimum(:credit_limit)
84
163
  end
85
164
 
86
165
  def test_should_get_minimum_of_arel_attribute
87
166
  assert_equal 50, Account.minimum(Account.arel_table[:credit_limit])
167
+ assert_async_equal 50, Account.async_minimum(Account.arel_table[:credit_limit])
88
168
  end
89
169
 
90
170
  def test_should_group_by_field
@@ -92,6 +172,7 @@ class CalculationsTest < ActiveRecord::TestCase
92
172
  [1, 6, 2].each do |firm_id|
93
173
  assert_includes c.keys, firm_id, "Group #{c.inspect} does not contain firm_id #{firm_id}"
94
174
  end
175
+ assert_async_equal c, Account.group(:firm_id).async_sum(:credit_limit)
95
176
  end
96
177
 
97
178
  def test_should_group_by_arel_attribute
@@ -106,6 +187,19 @@ class CalculationsTest < ActiveRecord::TestCase
106
187
  [ [nil, 50], [1, 50], [6, 50], [6, 55], [9, 53], [2, 60] ].each { |firm_and_limit| assert_includes c.keys, firm_and_limit }
107
188
  end
108
189
 
190
+ def test_should_group_by_multiple_fields_when_table_name_is_too_long
191
+ 2.times do
192
+ TooLongTableName.create!(
193
+ toooooooo_long_a_id: 1,
194
+ toooooooo_long_b_id: 2
195
+ )
196
+ end
197
+
198
+ res = TooLongTableName.group(:toooooooo_long_a_id, :toooooooo_long_b_id).count
199
+
200
+ assert_equal({ [1, 2] => 2 }, res)
201
+ end
202
+
109
203
  def test_should_group_by_multiple_fields_having_functions
110
204
  c = Topic.group(:author_name, "COALESCE(type, title)").count(:all)
111
205
  assert_equal 1, c[["Carl", "The Third Topic of the day"]]
@@ -133,36 +227,24 @@ class CalculationsTest < ActiveRecord::TestCase
133
227
  assert_equal expected, accounts.merge!(accounts).uniq!(:group).sum(:credit_limit)
134
228
 
135
229
  expected = {
136
- [nil, nil] => 50,
137
- [1, 1] => 50,
138
- [2, 2] => 60,
139
- [6, 6] => 55,
140
- [9, 9] => 53
230
+ nil => 50,
231
+ 1 => 50,
232
+ 2 => 60,
233
+ 6 => 55,
234
+ 9 => 53
141
235
  }
142
- message = <<-MSG.squish
143
- `maximum` with group by duplicated fields does no longer affect to result in Rails 7.0.
144
- To migrate to Rails 7.0's behavior, use `uniq!(:group)` to deduplicate group fields
145
- (`accounts.uniq!(:group).maximum(:credit_limit)`).
146
- MSG
147
- assert_deprecated(message) do
148
- assert_equal expected, accounts.merge!(accounts).maximum(:credit_limit)
149
- end
236
+
237
+ assert_equal expected, accounts.merge!(accounts).maximum(:credit_limit)
150
238
 
151
239
  expected = {
152
- [nil, nil, nil, nil] => 50,
153
- [1, 1, 1, 1] => 50,
154
- [2, 2, 2, 2] => 60,
155
- [6, 6, 6, 6] => 50,
156
- [9, 9, 9, 9] => 53
240
+ nil => 50,
241
+ 1 => 50,
242
+ 2 => 60,
243
+ 6 => 50,
244
+ 9 => 53
157
245
  }
158
- message = <<-MSG.squish
159
- `minimum` with group by duplicated fields does no longer affect to result in Rails 7.0.
160
- To migrate to Rails 7.0's behavior, use `uniq!(:group)` to deduplicate group fields
161
- (`accounts.uniq!(:group).minimum(:credit_limit)`).
162
- MSG
163
- assert_deprecated(message) do
164
- assert_equal expected, accounts.merge!(accounts).minimum(:credit_limit)
165
- end
246
+
247
+ assert_equal expected, accounts.merge!(accounts).minimum(:credit_limit)
166
248
  end
167
249
 
168
250
  def test_should_generate_valid_sql_with_joins_and_group
@@ -185,9 +267,14 @@ class CalculationsTest < ActiveRecord::TestCase
185
267
  end
186
268
 
187
269
  def test_should_not_use_alias_for_grouped_field
188
- assert_sql(/GROUP BY #{Regexp.escape(Account.connection.quote_table_name("accounts.firm_id"))}/i) do
270
+ if current_adapter?(:IBM_DBAdapter)
189
271
  c = Account.group(:firm_id).order("accounts_firm_id").sum(:credit_limit)
190
272
  assert_equal [1, 2, 6, 9], c.keys.compact
273
+ else
274
+ assert_queries_match(/GROUP BY #{Regexp.escape(quote_table_name("accounts.firm_id"))}/i) do
275
+ c = Account.group(:firm_id).order("accounts_firm_id").sum(:credit_limit)
276
+ assert_equal [1, 2, 6, 9], c.keys.compact
277
+ end
191
278
  end
192
279
  end
193
280
 
@@ -213,6 +300,13 @@ class CalculationsTest < ActiveRecord::TestCase
213
300
  assert_equal [2, 6], c.keys.compact
214
301
  end
215
302
 
303
+ def test_order_should_apply_before_count
304
+ accounts = Account.order(id: :desc).limit(4)
305
+
306
+ assert_equal 4, accounts.count(:firm_id)
307
+ assert_equal 4, accounts.select(:firm_id).count
308
+ end
309
+
216
310
  def test_limit_should_apply_before_count
217
311
  accounts = Account.order(:id).limit(4)
218
312
 
@@ -235,44 +329,44 @@ class CalculationsTest < ActiveRecord::TestCase
235
329
  end
236
330
 
237
331
  def test_limit_is_kept
238
- return if current_adapter?(:OracleAdapter)
239
-
240
332
  queries = capture_sql { Account.limit(1).count }
241
333
  assert_equal 1, queries.length
242
- assert_match(/FETCH FIRST/, queries.first)
334
+ assert_match(/LIMIT/, queries.first)
243
335
  end
244
336
 
245
337
  def test_offset_is_kept
246
- return if current_adapter?(:OracleAdapter)
247
-
248
338
  queries = capture_sql { Account.offset(1).count }
249
339
  assert_equal 1, queries.length
250
340
  assert_match(/OFFSET/, queries.first)
251
341
  end
252
342
 
253
343
  def test_limit_with_offset_is_kept
254
- return if current_adapter?(:OracleAdapter)
255
-
256
344
  queries = capture_sql { Account.limit(1).offset(1).count }
257
345
  assert_equal 1, queries.length
258
- assert_match(/FETCH FIRST/, queries.first)
346
+ assert_match(/LIMIT/, queries.first)
259
347
  assert_match(/OFFSET/, queries.first)
260
348
  end
261
349
 
262
350
  def test_no_limit_no_offset
263
351
  queries = capture_sql { Account.count }
264
352
  assert_equal 1, queries.length
265
- assert_no_match(/FETCH FIRST/, queries.first)
353
+ assert_no_match(/LIMIT/, queries.first)
266
354
  assert_no_match(/OFFSET/, queries.first)
267
355
  end
268
356
 
357
+ def test_no_order_by_when_counting_all
358
+ queries = capture_sql { Account.order(id: :desc).limit(10).count }
359
+ assert_equal 1, queries.length
360
+ assert_no_match(/ORDER BY/, queries.first)
361
+ end
362
+
269
363
  def test_count_on_invalid_columns_raises
270
- e = assert_raises(ActiveRecord::StatementInvalid) {
364
+ error = assert_raises(ActiveRecord::StatementInvalid) do
271
365
  Account.select("credit_limit, firm_name").count
272
- }
366
+ end
273
367
 
274
- assert_match %r{accounts}i, e.sql
275
- assert_match "credit_limit, firm_name", e.sql
368
+ assert_match %r{accounts}i, error.sql
369
+ assert_match "credit_limit, firm_name", error.sql
276
370
  end
277
371
 
278
372
  def test_apply_distinct_in_count
@@ -288,26 +382,26 @@ class CalculationsTest < ActiveRecord::TestCase
288
382
 
289
383
  def test_count_with_eager_loading_and_custom_order
290
384
  posts = Post.includes(:comments).order("comments.id")
291
- assert_queries(1) { assert_equal 11, posts.count }
292
- assert_queries(1) { assert_equal 11, posts.count(:all) }
385
+ assert_queries_count(1) { assert_equal 11, posts.count }
386
+ assert_queries_count(1) { assert_equal 11, posts.count(:all) }
293
387
  end
294
388
 
295
389
  def test_count_with_eager_loading_and_custom_select_and_order
296
390
  posts = Post.includes(:comments).order("comments.id").select(:type)
297
- assert_queries(1) { assert_equal 11, posts.count }
298
- assert_queries(1) { assert_equal 11, posts.count(:all) }
391
+ assert_queries_count(1) { assert_equal 11, posts.count }
392
+ assert_queries_count(1) { assert_equal 11, posts.count(:all) }
299
393
  end
300
394
 
301
395
  def test_count_with_eager_loading_and_custom_order_and_distinct
302
396
  posts = Post.includes(:comments).order("comments.id").distinct
303
- assert_queries(1) { assert_equal 11, posts.count }
304
- assert_queries(1) { assert_equal 11, posts.count(:all) }
397
+ assert_queries_count(1) { assert_equal 11, posts.count }
398
+ assert_queries_count(1) { assert_equal 11, posts.count(:all) }
305
399
  end
306
400
 
307
401
  def test_distinct_count_all_with_custom_select_and_order
308
402
  accounts = Account.distinct.select("credit_limit % 10").order(Arel.sql("credit_limit % 10"))
309
- assert_queries(1) { assert_equal 3, accounts.count(:all) }
310
- assert_queries(1) { assert_equal 3, accounts.load.size }
403
+ assert_queries_count(1) { assert_equal 3, accounts.count(:all) }
404
+ assert_queries_count(1) { assert_equal 3, accounts.load.size }
311
405
  end
312
406
 
313
407
  def test_distinct_count_with_order_and_limit
@@ -350,6 +444,21 @@ class CalculationsTest < ActiveRecord::TestCase
350
444
  assert_equal({ 6 => 2 }, Account.group(:firm_id).distinct.order("1 DESC").limit(1).count)
351
445
  end
352
446
 
447
+ def test_count_for_a_composite_primary_key_model
448
+ book = cpk_books(:cpk_great_author_first_book)
449
+ assert_equal(1, Cpk::Book.where(author_id: book.author_id, id: book.id).count)
450
+ end
451
+
452
+ def test_group_by_count_for_a_composite_primary_key_model
453
+ book = cpk_books(:cpk_great_author_first_book)
454
+ expected = { book.author_id => Cpk::Book.where(author_id: book.author_id).count }
455
+ assert_equal(expected, Cpk::Book.where(author_id: book.author_id).group(:author_id).count)
456
+ end
457
+
458
+ def test_count_for_a_composite_primary_key_model_with_includes_and_references
459
+ assert_equal Cpk::Book.count, Cpk::Book.includes(:chapters).references(:chapters).count
460
+ end
461
+
353
462
  def test_should_group_by_summed_field_having_condition
354
463
  c = Account.group(:firm_id).having("sum(credit_limit) > 50").sum(:credit_limit)
355
464
  assert_nil c[1]
@@ -358,7 +467,7 @@ class CalculationsTest < ActiveRecord::TestCase
358
467
  end
359
468
 
360
469
  def test_should_group_by_summed_field_having_condition_from_select
361
- skip unless current_adapter?(:Mysql2Adapter, :SQLite3Adapter)
470
+ skip unless current_adapter?(:Mysql2Adapter, :TrilogyAdapter, :SQLite3Adapter)
362
471
  c = Account.select("MIN(credit_limit) AS min_credit_limit").group(:firm_id).having("min_credit_limit > 50").sum(:credit_limit)
363
472
  assert_nil c[1]
364
473
  assert_equal 60, c[2]
@@ -398,11 +507,13 @@ class CalculationsTest < ActiveRecord::TestCase
398
507
  end
399
508
 
400
509
  def test_should_group_by_summed_field_with_conditions_and_having
401
- c = Account.where("firm_id > 1").group(:firm_id).
402
- having("sum(credit_limit) > 60").sum(:credit_limit)
510
+ relation = Account.where("firm_id > 1").group(:firm_id).having("sum(credit_limit) > 60")
511
+ c = relation.sum(:credit_limit)
403
512
  assert_nil c[1]
404
513
  assert_equal 105, c[6]
405
514
  assert_nil c[2]
515
+
516
+ assert_async_equal c, relation.async_sum(:credit_limit)
406
517
  end
407
518
 
408
519
  def test_should_group_by_fields_with_table_alias
@@ -413,7 +524,7 @@ class CalculationsTest < ActiveRecord::TestCase
413
524
  end
414
525
 
415
526
  def test_should_calculate_grouped_with_longer_field
416
- field = "a" * Account.connection.max_identifier_length
527
+ field = "a" * Account.lease_connection.max_identifier_length
417
528
 
418
529
  Account.update_all("#{field} = credit_limit")
419
530
 
@@ -477,7 +588,15 @@ class CalculationsTest < ActiveRecord::TestCase
477
588
  end
478
589
 
479
590
  def test_should_not_overshadow_enumerable_sum
591
+ some_companies = companies(:rails_core).companies.order(:id)
592
+
480
593
  assert_equal 6, [1, 2, 3].sum(&:abs)
594
+ assert_equal 15, some_companies.sum(&:id)
595
+ assert_equal 25, some_companies.sum(10, &:id)
596
+ assert_raises(TypeError) do
597
+ some_companies.sum(&:name)
598
+ end
599
+ assert_equal "companies: LeetsoftJadedpixel", some_companies.sum("companies: ", &:name)
481
600
  end
482
601
 
483
602
  def test_should_sum_scoped_field
@@ -562,6 +681,13 @@ class CalculationsTest < ActiveRecord::TestCase
562
681
  assert_equal 4, Account.distinct.select(Account.arel_table[:firm_id]).count
563
682
  end
564
683
 
684
+ def test_count_selected_arel_attributes
685
+ # Only MySQL supports COUNT with multiple columns, and only with DISTINCT.
686
+ skip unless current_adapter?(:Mysql2Adapter, :TrilogyAdapter)
687
+
688
+ assert_equal 5, Account.distinct.select(Account.arel_table[:id], Account.arel_table[:firm_id]).count
689
+ end
690
+
565
691
  def test_count_with_column_parameter
566
692
  assert_equal 5, Account.count(:firm_id)
567
693
  end
@@ -607,6 +733,14 @@ class CalculationsTest < ActiveRecord::TestCase
607
733
  [1, 6, 2, 9].each { |firm_id| assert_includes c.keys, firm_id }
608
734
  end
609
735
 
736
+ def test_should_count_field_in_joined_table_with_group_by_when_tables_share_column_names
737
+ assert Company.columns_hash.key?("status")
738
+ assert Account.columns_hash.key?("status")
739
+
740
+ counts = Company.joins(:account).group("accounts.status").count
741
+ assert_equal({ "active" => 2, "trial" => 2, "suspended" => 1 }, counts)
742
+ end
743
+
610
744
  def test_should_count_field_of_root_table_with_conflicting_group_by_column
611
745
  expected = { 1 => 2, 2 => 1, 4 => 5, 5 => 3, 7 => 1 }
612
746
  assert_equal expected, Post.joins(:comments).group(:post_id).count
@@ -615,7 +749,7 @@ class CalculationsTest < ActiveRecord::TestCase
615
749
  end
616
750
 
617
751
  def test_count_with_no_parameters_isnt_deprecated
618
- assert_not_deprecated { Account.count }
752
+ assert_not_deprecated(ActiveRecord.deprecator) { Account.count }
619
753
  end
620
754
 
621
755
  def test_count_with_too_many_parameters_raises
@@ -640,6 +774,13 @@ class CalculationsTest < ActiveRecord::TestCase
640
774
  assert_equal 4, Account.count { |account| account.credit_limit.modulo(10).zero? }
641
775
  end
642
776
 
777
+ def test_count_with_empty_in
778
+ assert_queries_count(0) do
779
+ assert_equal 0, Topic.where(id: []).count
780
+ assert_async_equal 0, Topic.where(id: []).async_count
781
+ end
782
+ end
783
+
643
784
  def test_should_sum_expression
644
785
  assert_equal 636, Account.sum("2 * credit_limit")
645
786
  end
@@ -680,6 +821,36 @@ class CalculationsTest < ActiveRecord::TestCase
680
821
  Account.where("credit_limit > 50").from("accounts").maximum(:credit_limit)
681
822
  end
682
823
 
824
+ def test_no_queries_for_empty_relation_on_count
825
+ assert_queries_count(0) do
826
+ assert_equal 0, Post.where(id: []).count
827
+ end
828
+ end
829
+
830
+ def test_no_queries_for_empty_relation_on_sum
831
+ assert_queries_count(0) do
832
+ assert_equal 0, Post.where(id: []).sum(:tags_count)
833
+ end
834
+ end
835
+
836
+ def test_no_queries_for_empty_relation_on_average
837
+ assert_queries_count(0) do
838
+ assert_nil Post.where(id: []).average(:tags_count)
839
+ end
840
+ end
841
+
842
+ def test_no_queries_for_empty_relation_on_minimum
843
+ assert_queries_count(0) do
844
+ assert_nil Account.where(id: []).minimum(:id)
845
+ end
846
+ end
847
+
848
+ def test_no_queries_for_empty_relation_on_maximum
849
+ assert_queries_count(0) do
850
+ assert_nil Account.where(id: []).maximum(:id)
851
+ end
852
+ end
853
+
683
854
  def test_maximum_with_not_auto_table_name_prefix_if_column_included
684
855
  Company.create!(name: "test", contracts: [Contract.new(developer_id: 7)])
685
856
 
@@ -698,6 +869,16 @@ class CalculationsTest < ActiveRecord::TestCase
698
869
  assert_equal 7, Company.includes(:contracts).sum(:developer_id)
699
870
  end
700
871
 
872
+ def test_sum_with_grouped_calculation
873
+ expected = { 0 => 0, 1 => 0, 3 => 0 }
874
+
875
+ if current_adapter?(:IBM_DBAdapter)
876
+ assert_equal(expected, Post.group(:tags_count).sum(Arel.sql("0")))
877
+ else
878
+ assert_equal(expected, Post.group(:tags_count).sum)
879
+ end
880
+ end
881
+
701
882
  def test_from_option_with_specified_index
702
883
  edges = Edge.from("edges /*! USE INDEX(unique_edge_index) */")
703
884
  assert_equal Edge.count(:all), edges.count(:all)
@@ -711,28 +892,35 @@ class CalculationsTest < ActiveRecord::TestCase
711
892
  def test_distinct_is_honored_when_used_with_count_operation_after_group
712
893
  # Count the number of authors for approved topics
713
894
  approved_topics_count = Topic.group(:approved).count(:author_name)[true]
714
- assert_equal approved_topics_count, 4
895
+ assert_equal 4, approved_topics_count
715
896
  # Count the number of distinct authors for approved Topics
716
897
  distinct_authors_for_approved_count = Topic.group(:approved).distinct.count(:author_name)[true]
717
- assert_equal distinct_authors_for_approved_count, 3
898
+ assert_equal 3, distinct_authors_for_approved_count
718
899
  end
719
900
 
720
901
  def test_pluck
721
902
  assert_equal [1, 2, 3, 4, 5], Topic.order(:id).pluck(:id)
903
+ assert_async_equal [1, 2, 3, 4, 5], Topic.order(:id).async_pluck(:id)
904
+ end
905
+
906
+ def test_async_pluck_on_loaded_relation
907
+ relation = Topic.order(:id).load
908
+ assert_async_equal relation.pluck(:id), relation.async_pluck(:id)
909
+ end
910
+
911
+ def test_async_pluck_none_relation
912
+ assert_async_equal [], Topic.none.async_pluck(:id)
722
913
  end
723
914
 
724
915
  def test_pluck_with_empty_in
725
- assert_queries(0) do
916
+ assert_queries_count(0) do
726
917
  assert_equal [], Topic.where(id: []).pluck(:id)
727
918
  end
919
+ assert_async_equal [], Topic.where(id: []).async_pluck(:id)
728
920
  end
729
921
 
730
922
  def test_pluck_without_column_names
731
- if current_adapter?(:OracleAdapter)
732
- assert_equal [[1, "Firm", 1, nil, "37signals", nil, 1, nil, nil]], Company.order(:id).limit(1).pluck
733
- else
734
- assert_equal [[1, "Firm", 1, nil, "37signals", nil, 1, nil, ""]], Company.order(:id).limit(1).pluck
735
- end
923
+ assert_equal [[1, "Firm", 1, nil, "37signals", nil, 1, nil, "", "active"]], Company.order(:id).limit(1).pluck
736
924
  end
737
925
 
738
926
  def test_pluck_type_cast
@@ -741,6 +929,10 @@ class CalculationsTest < ActiveRecord::TestCase
741
929
  assert_equal [ topic.approved ], relation.pluck(:approved)
742
930
  assert_equal [ topic.last_read ], relation.pluck(:last_read)
743
931
  assert_equal [ topic.written_on ], relation.pluck(:written_on)
932
+ assert_equal(
933
+ [[topic.written_on, topic.replies_count]],
934
+ relation.pluck("min(written_on)", "min(replies_count)")
935
+ )
744
936
  end
745
937
 
746
938
  def test_pluck_type_cast_with_conflict_column_names
@@ -785,7 +977,7 @@ class CalculationsTest < ActiveRecord::TestCase
785
977
  def test_pluck_with_type_cast_does_not_corrupt_the_query_cache
786
978
  topic = topics(:first)
787
979
  relation = Topic.where(id: topic.id)
788
- assert_queries 1 do
980
+ assert_queries_count 1 do
789
981
  Topic.cache do
790
982
  kind = relation.select(:written_on).load.first.read_attribute_before_type_cast(:written_on).class
791
983
  relation.pluck(:written_on)
@@ -809,8 +1001,8 @@ class CalculationsTest < ActiveRecord::TestCase
809
1001
  end
810
1002
 
811
1003
  def test_pluck_with_serialization
812
- t = Topic.create!(content: { foo: :bar })
813
- assert_equal [{ foo: :bar }], Topic.where(id: t.id).pluck(:content)
1004
+ t = Topic.create!(content: { "foo" => "bar" })
1005
+ assert_equal [{ "foo" => "bar" }], Topic.where(id: t.id).pluck(:content)
814
1006
  end
815
1007
 
816
1008
  def test_pluck_with_qualified_column_name
@@ -840,8 +1032,174 @@ class CalculationsTest < ActiveRecord::TestCase
840
1032
  assert_equal [50 + 53 + 55 + 60], Account.pluck(Arel.sql("SUM(DISTINCT(credit_limit))"))
841
1033
  end
842
1034
 
843
- def test_plucks_with_ids
844
- assert_equal Company.all.map(&:id).sort, Company.ids.sort
1035
+ def test_pluck_with_hash_argument
1036
+ expected = [
1037
+ [1, "The First Topic"],
1038
+ [2, "The Second Topic of the day"],
1039
+ [3, "The Third Topic of the day"]
1040
+ ]
1041
+ assert_equal expected, Topic.order(:id).limit(3).pluck(:id, topics: :title)
1042
+ assert_equal expected, Topic.order(:id).limit(3).pluck("id", "topics" => "title")
1043
+ assert_equal expected, Topic.order(:id).limit(3).pluck(:id, topics: [:title])
1044
+ assert_equal expected, Topic.order(:id).limit(3).pluck("id", "topics" => ["title"])
1045
+ end
1046
+
1047
+ def test_pluck_with_hash_argument_with_multiple_tables
1048
+ expected = [
1049
+ [1, 1, "Thank you for the welcome"],
1050
+ [1, 2, "Thank you again for the welcome"],
1051
+ [2, 3, "Don't think too hard"]
1052
+ ]
1053
+ assert_equal expected, Post.joins(:comments).order(posts: { id: :asc }, comments: { id: :asc }).limit(3).pluck(:id, comments: [:id, :body])
1054
+ assert_equal expected, Post.joins(:comments).order(posts: { id: :asc }, comments: { id: :asc }).limit(3).pluck(posts: :id, comments: [:id, :body])
1055
+ assert_equal expected, Post.joins(:comments).order(posts: { id: :asc }, comments: { id: :asc }).limit(3).pluck(posts: [:id], comments: [:id, :body])
1056
+ end
1057
+
1058
+ def test_pluck_with_hash_argument_containing_non_existent_field
1059
+ assert_raises(ActiveRecord::StatementInvalid) do
1060
+ Topic.pluck(topics: [:non_existent])
1061
+ end
1062
+ end
1063
+
1064
+ def test_ids
1065
+ assert_equal Company.all.map(&:id).sort, Company.all.ids.sort
1066
+ end
1067
+
1068
+ def test_ids_for_a_composite_primary_key
1069
+ assert_equal Cpk::Book.all.map(&:id).sort, Cpk::Book.all.ids.sort
1070
+ end
1071
+
1072
+ def test_pluck_for_a_composite_primary_key
1073
+ assert_equal Cpk::Book.all.pluck([:author_id, :id]).sort, Cpk::Book.all.ids.sort
1074
+ end
1075
+
1076
+ def test_ids_for_a_composite_primary_key_with_scope
1077
+ book = cpk_books(:cpk_great_author_first_book)
1078
+
1079
+ assert_equal [book.id], Cpk::Book.all.where(title: book.title).ids
1080
+ end
1081
+
1082
+ def test_ids_for_a_composite_primary_key_on_loaded_relation
1083
+ book = cpk_books(:cpk_great_author_first_book)
1084
+ relation = Cpk::Book.where(title: book.title)
1085
+ relation.to_a
1086
+
1087
+ assert_predicate relation, :loaded?
1088
+ assert_equal [book.id], relation.ids
1089
+ end
1090
+
1091
+ def test_ids_with_scope
1092
+ scoped_ids = [1, 2]
1093
+ assert_equal Company.where(id: scoped_ids).map(&:id).sort, Company.where(id: scoped_ids).ids.sort
1094
+ end
1095
+
1096
+ def test_ids_on_relation
1097
+ company = Company.first
1098
+ contract = company.contracts.create!
1099
+ assert_equal [contract.id], company.contracts.ids
1100
+ end
1101
+
1102
+ def test_ids_on_loaded_relation
1103
+ loaded_companies = Company.all.load
1104
+ company_ids = Company.all.map(&:id)
1105
+ assert_queries_count(0) do
1106
+ assert_equal company_ids.sort, loaded_companies.ids.sort
1107
+ end
1108
+ end
1109
+
1110
+ def test_ids_on_loaded_relation_with_scope
1111
+ scoped_ids = [1, 2]
1112
+ loaded_companies = Company.where(id: scoped_ids).load
1113
+ company_ids = Company.where(id: scoped_ids).map(&:id)
1114
+ assert_queries_count(0) do
1115
+ assert_equal company_ids.sort, loaded_companies.ids.sort
1116
+ end
1117
+ end
1118
+
1119
+ def test_ids_async_on_loaded_relation
1120
+ loaded_companies = Company.all.order(:id).load
1121
+ assert_async_equal loaded_companies.ids, loaded_companies.async_ids
1122
+ end
1123
+
1124
+ def test_ids_with_contradicting_scope
1125
+ empty_scope_ids = []
1126
+ company_ids = Company.where(id: empty_scope_ids).map(&:id)
1127
+ assert_predicate company_ids, :empty?
1128
+ assert_queries_count(0) do
1129
+ assert_equal company_ids, Company.where(id: empty_scope_ids).ids
1130
+ end
1131
+ end
1132
+
1133
+ def test_ids_with_join
1134
+ company = Company.first
1135
+ company.contracts.create!
1136
+ assert_equal [company.id], Company.joins(:contracts).where("contracts.id" => company.contracts.first).ids
1137
+ end
1138
+
1139
+ def test_ids_with_polymorphic_relation_join
1140
+ part = ShipPart.create!(name: "has trinket")
1141
+ part.trinkets.create!
1142
+
1143
+ assert_equal [part.id], ShipPart.joins(:trinkets).ids
1144
+ assert_async_equal [part.id], ShipPart.joins(:trinkets).async_ids
1145
+ end
1146
+
1147
+ def test_ids_with_eager_load
1148
+ company = Company.first
1149
+ 5.times { company.contracts.create! }
1150
+ assert_equal Company.all.map(&:id).sort, Company.all.eager_load(:contracts).ids.sort
1151
+ end
1152
+
1153
+ def test_ids_with_preload
1154
+ company = Company.first
1155
+ 5.times { company.contracts.create! }
1156
+ assert_equal Company.all.map(&:id).sort, Company.all.preload(:contracts).ids.sort
1157
+ end
1158
+
1159
+ def test_ids_with_includes
1160
+ company = Company.first
1161
+ 5.times { company.contracts.create! }
1162
+ assert_equal Company.all.map(&:id).sort, Company.all.includes(:contracts).ids.sort
1163
+ end
1164
+
1165
+ def test_ids_with_includes_and_non_primary_key_order
1166
+ rating = 1
1167
+ Company.all.each { |company| company.update!(rating: rating += 1) }
1168
+ relation = Company.includes(:comments).order(:rating)
1169
+ relation = relation.group(:id, :rating) if current_adapter?(:IBM_DBAdapter)
1170
+ assert_equal Company.all.sort_by(&:rating).map(&:id), relation.ids
1171
+ end
1172
+
1173
+ def test_ids_with_includes_and_scope
1174
+ scoped_ids = [1, 2]
1175
+ company = Company.where(id: scoped_ids).first
1176
+ 5.times { company.contracts.create! }
1177
+ assert_equal Company.where(id: scoped_ids).map(&:id).sort, Company.includes(:contracts).where(id: scoped_ids).ids.sort
1178
+ end
1179
+
1180
+ def test_ids_with_includes_and_table_scope
1181
+ company = Company.first
1182
+ company.contracts.create!
1183
+ assert_equal [company.id], Company.includes(:contracts).where("contracts.id" => company.contracts.first).ids
1184
+ end
1185
+
1186
+ def test_ids_on_loaded_relation_with_includes_and_table_scope
1187
+ company = Company.first
1188
+ company.contracts.create!
1189
+ loaded_companies = Company.includes(:contracts).where("contracts.id" => company.contracts.first).load
1190
+ assert_queries_count(0) do
1191
+ assert_equal [company.id], loaded_companies.ids
1192
+ end
1193
+ end
1194
+
1195
+ def test_ids_with_includes_limit_and_empty_result
1196
+ assert_equal [], Topic.includes(:replies).limit(0).ids
1197
+ assert_equal [], Topic.includes(:replies).limit(1).where("0 = 1").ids
1198
+ end
1199
+
1200
+ def test_ids_with_includes_offset
1201
+ assert_equal [5], Topic.includes(:replies).order(:id).offset(4).ids
1202
+ assert_equal [], Topic.includes(:replies).order(:id).offset(5).ids
845
1203
  end
846
1204
 
847
1205
  def test_pluck_with_includes_limit_and_empty_result
@@ -855,9 +1213,17 @@ class CalculationsTest < ActiveRecord::TestCase
855
1213
  end
856
1214
 
857
1215
  def test_pluck_with_join
1216
+ assert_equal [[2, 2], [4, 4]], Reply.includes(:topic).order(:id).pluck(:id, topics: [:id])
1217
+ assert_equal [[2, 2], [4, 4]], Reply.includes(:topic).order(:id).pluck(:id, topics: :id)
858
1218
  assert_equal [[2, 2], [4, 4]], Reply.includes(:topic).order(:id).pluck(:id, :"topics.id")
859
1219
  end
860
1220
 
1221
+ def test_pluck_with_join_alias
1222
+ assert_equal [[2, 1], [4, 3]], Reply.includes(:topic).order(:id).pluck(:id, topic: [:id])
1223
+ assert_equal [[2, 1], [4, 3]], Reply.includes(:topic).order(:id).pluck(:id, topic: :id)
1224
+ assert_equal [[2, 1], [4, 3]], Reply.includes(:topic).order(:id).pluck(:id, :"topic.id")
1225
+ end
1226
+
861
1227
  def test_group_by_with_order_by_virtual_count_attribute
862
1228
  expected = { "SpecialPost" => 1, "StiPost" => 2 }
863
1229
  actual = Post.group(:type).order(:count).limit(2).maximum(:comments_count)
@@ -883,9 +1249,9 @@ class CalculationsTest < ActiveRecord::TestCase
883
1249
  end
884
1250
 
885
1251
  def test_group_by_with_quoted_count_and_order_by_alias
886
- quoted_posts_id = Post.connection.quote_table_name("posts.id")
887
1252
  expected = { "SpecialPost" => 1, "StiPost" => 1, "Post" => 9 }
888
- actual = Post.group(:type).order("count_posts_id").count(quoted_posts_id)
1253
+ count_expression = current_adapter?(:IBM_DBAdapter) ? "posts.id" : quote_table_name("posts.id")
1254
+ actual = Post.group(:type).order("count_posts_id").count(count_expression)
889
1255
  assert_equal expected, actual
890
1256
  end
891
1257
 
@@ -914,6 +1280,11 @@ class CalculationsTest < ActiveRecord::TestCase
914
1280
  Account.order(:id).pluck("id, credit_limit")
915
1281
  end
916
1282
 
1283
+ def test_pluck_with_line_endings
1284
+ assert_equal [[1, 50], [2, 50], [3, 50], [4, 60], [5, 55], [6, 53]],
1285
+ Account.order(:id).pluck("id, credit_limit\n")
1286
+ end
1287
+
917
1288
  def test_pluck_with_multiple_columns_and_includes
918
1289
  Company.create!(name: "test", contracts: [Contract.new(developer_id: 7)])
919
1290
  companies_and_developers = Company.order("companies.id").includes(:contracts).pluck(:name, :developer_id)
@@ -930,9 +1301,21 @@ class CalculationsTest < ActiveRecord::TestCase
930
1301
  end
931
1302
 
932
1303
  def test_pluck_replaces_select_clause
933
- taks_relation = Topic.select(:approved, :id).order(:id)
934
- assert_equal [1, 2, 3, 4, 5], taks_relation.pluck(:id)
935
- assert_equal [false, true, true, true, true], taks_relation.pluck(:approved)
1304
+ takes_relation = Topic.select(:approved, :id).order(:id)
1305
+ assert_equal [1, 2, 3, 4, 5], takes_relation.pluck(:id)
1306
+ assert_equal [false, true, true, true, true], takes_relation.pluck(:approved)
1307
+ end
1308
+
1309
+ def test_pluck_with_qualified_name_on_loaded
1310
+ topics = Topic.joins(:replies).order(:id)
1311
+
1312
+ assert_not_predicate topics, :loaded?
1313
+ assert_equal [[1, 2], [3, 4]], topics.pluck("topics.id", "replies.id")
1314
+
1315
+ topics.load
1316
+
1317
+ assert_predicate topics, :loaded?
1318
+ assert_equal [[1, 2], [3, 4]], topics.pluck("topics.id", "replies.id")
936
1319
  end
937
1320
 
938
1321
  def test_pluck_columns_with_same_name
@@ -954,11 +1337,15 @@ class CalculationsTest < ActiveRecord::TestCase
954
1337
  end
955
1338
 
956
1339
  def test_pluck_functions_without_alias
957
- assert_equal [
958
- [1, "The First Topic"], [2, "The Second Topic of the day"],
959
- [3, "The Third Topic of the day"], [4, "The Fourth Topic of the day"],
1340
+ expected = [
1341
+ [1, "The First Topic"],
1342
+ [2, "The Second Topic of the day"],
1343
+ [3, "The Third Topic of the day"],
1344
+ [4, "The Fourth Topic of the day"],
960
1345
  [5, "The Fifth Topic of the day"]
961
- ], Topic.order(:id).pluck(
1346
+ ]
1347
+
1348
+ assert_equal expected, Topic.order(:id).pluck(
962
1349
  Arel.sql("COALESCE(id, 0)"),
963
1350
  Arel.sql("COALESCE(title, 'untitled')")
964
1351
  )
@@ -969,6 +1356,19 @@ class CalculationsTest < ActiveRecord::TestCase
969
1356
  part.trinkets.create!
970
1357
 
971
1358
  assert_equal part.id, ShipPart.joins(:trinkets).sum(:id)
1359
+ assert_async_equal part.id, ShipPart.joins(:trinkets).async_sum(:id)
1360
+ end
1361
+
1362
+ def test_calculation_with_query_cache
1363
+ ShipPart.cache do
1364
+ count = ShipPart.count
1365
+ assert_async_equal count, ShipPart.async_count
1366
+ end
1367
+
1368
+ ShipPart.cache do
1369
+ count = ShipPart.async_count
1370
+ assert_async_equal count.value, ShipPart.async_count
1371
+ end
972
1372
  end
973
1373
 
974
1374
  def test_pluck_joined_with_polymorphic_relation
@@ -976,12 +1376,13 @@ class CalculationsTest < ActiveRecord::TestCase
976
1376
  part.trinkets.create!
977
1377
 
978
1378
  assert_equal [part.id], ShipPart.joins(:trinkets).pluck(:id)
1379
+ assert_async_equal [part.id], ShipPart.joins(:trinkets).async_pluck(:id)
979
1380
  end
980
1381
 
981
1382
  def test_pluck_loaded_relation
982
1383
  companies = Company.order(:id).limit(3).load
983
1384
 
984
- assert_queries(0) do
1385
+ assert_queries_count(0) do
985
1386
  assert_equal ["37signals", "Summit", "Microsoft"], companies.pluck(:name)
986
1387
  end
987
1388
  end
@@ -989,7 +1390,7 @@ class CalculationsTest < ActiveRecord::TestCase
989
1390
  def test_pluck_loaded_relation_multiple_columns
990
1391
  companies = Company.order(:id).limit(3).load
991
1392
 
992
- assert_queries(0) do
1393
+ assert_queries_count(0) do
993
1394
  assert_equal [[1, "37signals"], [2, "Summit"], [3, "Microsoft"]], companies.pluck(:id, :name)
994
1395
  end
995
1396
  end
@@ -997,7 +1398,7 @@ class CalculationsTest < ActiveRecord::TestCase
997
1398
  def test_pluck_loaded_relation_sql_fragment
998
1399
  companies = Company.order(:name).limit(3).load
999
1400
 
1000
- assert_queries(1) do
1401
+ assert_queries_count(1) do
1001
1402
  assert_equal ["37signals", "Apex", "Ex Nihilo"], companies.pluck(Arel.sql("DISTINCT name"))
1002
1403
  end
1003
1404
  end
@@ -1005,7 +1406,7 @@ class CalculationsTest < ActiveRecord::TestCase
1005
1406
  def test_pluck_loaded_relation_aliased_attribute
1006
1407
  companies = Company.order(:id).limit(3).load
1007
1408
 
1008
- assert_queries(0) do
1409
+ assert_queries_count(0) do
1009
1410
  assert_equal ["37signals", "Summit", "Microsoft"], companies.pluck(:new_name)
1010
1411
  end
1011
1412
  end
@@ -1016,6 +1417,8 @@ class CalculationsTest < ActiveRecord::TestCase
1016
1417
  assert_nil Topic.none.pick(:heading)
1017
1418
  assert_nil Topic.where(id: 9999999999999999999).pick(:heading)
1018
1419
  end
1420
+
1421
+ assert_async_equal "The First Topic", Topic.order(:id).async_pick(:heading)
1019
1422
  end
1020
1423
 
1021
1424
  def test_pick_two
@@ -1024,6 +1427,8 @@ class CalculationsTest < ActiveRecord::TestCase
1024
1427
  assert_nil Topic.none.pick(:author_name, :author_email_address)
1025
1428
  assert_nil Topic.where(id: 9999999999999999999).pick(:author_name, :author_email_address)
1026
1429
  end
1430
+
1431
+ assert_async_equal ["David", "david@loudthinking.com"], Topic.order(:id).async_pick(:author_name, :author_email_address)
1027
1432
  end
1028
1433
 
1029
1434
  def test_pick_delegate_to_all
@@ -1050,7 +1455,7 @@ class CalculationsTest < ActiveRecord::TestCase
1050
1455
  def test_pick_loaded_relation_sql_fragment
1051
1456
  companies = Company.order(:name).limit(3).load
1052
1457
 
1053
- assert_queries 1 do
1458
+ assert_queries_count 1 do
1054
1459
  assert_equal "37signals", companies.pick(Arel.sql("DISTINCT name"))
1055
1460
  end
1056
1461
  end
@@ -1099,15 +1504,27 @@ class CalculationsTest < ActiveRecord::TestCase
1099
1504
  Account.group(:id).having(params)
1100
1505
  end
1101
1506
 
1102
- result = Account.group(:id, :firm_id, :firm_name, :credit_limit, :AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA).having(params.permit!)
1103
- assert_equal 50, result[0].credit_limit
1104
- assert_equal 50, result[1].credit_limit
1105
- assert_equal 50, result[2].credit_limit
1507
+ if current_adapter?(:IBM_DBAdapter)
1508
+ long_column = "a" * Account.lease_connection.max_identifier_length
1509
+
1510
+ result = Account
1511
+ .select(:id, :firm_id, :firm_name, :credit_limit, long_column)
1512
+ .group(:id, :firm_id, :firm_name, :credit_limit, long_column)
1513
+ .having(params.permit!)
1514
+ .to_a
1515
+
1516
+ assert_equal [50, 50, 50], result.map(&:credit_limit).sort
1517
+ else
1518
+ result = Account.group(:id).having(params.permit!)
1519
+ assert_equal 50, result[0].credit_limit
1520
+ assert_equal 50, result[1].credit_limit
1521
+ assert_equal 50, result[2].credit_limit
1522
+ end
1106
1523
  end
1107
1524
 
1108
1525
  def test_count_takes_attribute_type_precedence_over_database_type
1109
1526
  assert_called(
1110
- Account.connection, :select_all,
1527
+ Account.lease_connection, :select_all,
1111
1528
  returns: ActiveRecord::Result.new(["count"], [["10"]])
1112
1529
  ) do
1113
1530
  result = Account.count
@@ -1118,7 +1535,7 @@ class CalculationsTest < ActiveRecord::TestCase
1118
1535
 
1119
1536
  def test_sum_takes_attribute_type_precedence_over_database_type
1120
1537
  assert_called(
1121
- Account.connection, :select_all,
1538
+ Account.lease_connection, :select_all,
1122
1539
  returns: ActiveRecord::Result.new(["sum"], [[10.to_d]])
1123
1540
  ) do
1124
1541
  result = Account.sum(:credit_limit)
@@ -1273,7 +1690,7 @@ class CalculationsTest < ActiveRecord::TestCase
1273
1690
  INNER JOIN accounts ON companies.id = accounts.firm_id
1274
1691
  WHERE companies.id = ?
1275
1692
  GROUP BY companies.id, companies.type, companies.firm_id, companies.firm_name, companies.name, companies.client_of, companies.rating, companies.account_id,
1276
- companies.DESCRIPTION
1693
+ companies.description, companies.status
1277
1694
  LIMIT 1
1278
1695
  SQL
1279
1696
 
@@ -1294,7 +1711,7 @@ class CalculationsTest < ActiveRecord::TestCase
1294
1711
  .select("companies.*", "AVG(accounts.credit_limit) AS avg_credit_limit")
1295
1712
  .where(id: rails_core)
1296
1713
  .joins(:account)
1297
- .group(:id, :type, :firm_id, :firm_name, :name, :client_of, :rating, :account_id, :description)
1714
+ .group(:id, :type, :firm_id, :firm_name, :status, :name, :client_of, :rating, :account_id, :description)
1298
1715
  .take!
1299
1716
 
1300
1717
  # all the DependentFirm attributes should be present
@@ -1311,34 +1728,42 @@ class CalculationsTest < ActiveRecord::TestCase
1311
1728
  end
1312
1729
  end
1313
1730
 
1314
- def test_sum_with_block_and_column_name_raises_an_error
1315
- assert_raises(ArgumentError) do
1316
- Account.sum(:firm_id) { 1 }
1317
- end
1318
- end
1319
-
1320
1731
  test "#skip_query_cache! for #pluck" do
1321
1732
  Account.cache do
1322
- assert_queries(1) do
1733
+ assert_queries_count(1) do
1323
1734
  Account.pluck(:credit_limit)
1324
1735
  Account.pluck(:credit_limit)
1325
1736
  end
1326
1737
 
1327
- assert_queries(2) do
1738
+ assert_queries_count(2) do
1328
1739
  Account.all.skip_query_cache!.pluck(:credit_limit)
1329
1740
  Account.all.skip_query_cache!.pluck(:credit_limit)
1330
1741
  end
1331
1742
  end
1332
1743
  end
1333
1744
 
1745
+ test "#skip_query_cache! for #ids" do
1746
+ Account.cache do
1747
+ assert_queries_count(1) do
1748
+ Account.ids
1749
+ Account.ids
1750
+ end
1751
+
1752
+ assert_queries_count(2) do
1753
+ Account.all.skip_query_cache!.ids
1754
+ Account.all.skip_query_cache!.ids
1755
+ end
1756
+ end
1757
+ end
1758
+
1334
1759
  test "#skip_query_cache! for a simple calculation" do
1335
1760
  Account.cache do
1336
- assert_queries(1) do
1761
+ assert_queries_count(1) do
1337
1762
  Account.calculate(:sum, :credit_limit)
1338
1763
  Account.calculate(:sum, :credit_limit)
1339
1764
  end
1340
1765
 
1341
- assert_queries(2) do
1766
+ assert_queries_count(2) do
1342
1767
  Account.all.skip_query_cache!.calculate(:sum, :credit_limit)
1343
1768
  Account.all.skip_query_cache!.calculate(:sum, :credit_limit)
1344
1769
  end
@@ -1347,15 +1772,21 @@ class CalculationsTest < ActiveRecord::TestCase
1347
1772
 
1348
1773
  test "#skip_query_cache! for a grouped calculation" do
1349
1774
  Account.cache do
1350
- assert_queries(1) do
1775
+ assert_queries_count(1) do
1351
1776
  Account.group(:firm_id).calculate(:sum, :credit_limit)
1352
1777
  Account.group(:firm_id).calculate(:sum, :credit_limit)
1353
1778
  end
1354
1779
 
1355
- assert_queries(2) do
1780
+ assert_queries_count(2) do
1356
1781
  Account.all.skip_query_cache!.group(:firm_id).calculate(:sum, :credit_limit)
1357
1782
  Account.all.skip_query_cache!.group(:firm_id).calculate(:sum, :credit_limit)
1358
1783
  end
1359
1784
  end
1360
1785
  end
1786
+
1787
+ test "group alias is properly quoted" do
1788
+ assert_nothing_raised do
1789
+ NeedQuoting.group(:name).count
1790
+ end
1791
+ end
1361
1792
  end