ibm_db 5.2.0-x86-mingw32 → 5.3.2-x86-mingw32

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 (621) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +9 -0
  3. data/LICENSE +55 -18
  4. data/ext/Makefile +15 -13
  5. data/ext/ibm_db.c +62 -57
  6. data/ext/ibm_db.o +0 -0
  7. data/ext/ibm_db.so +0 -0
  8. data/ext/mkmf.log +26 -24
  9. data/ext/ruby_ibm_db_cli.c +1 -0
  10. data/ext/ruby_ibm_db_cli.o +0 -0
  11. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +1463 -1279
  12. data/lib/ibm_db.so +1 -0
  13. data/lib/mswin32/rb3x/i386/ruby30/ibm_db.so +0 -0
  14. data/test/active_record/connection_adapters/fake_adapter.rb +5 -2
  15. data/test/activejob/destroy_association_async_test.rb +305 -0
  16. data/test/activejob/destroy_async_job_not_present_test.rb +31 -0
  17. data/test/activejob/helper.rb +15 -0
  18. data/test/assets/schema_dump_5_1.yml +345 -0
  19. data/test/cases/adapter_prevent_writes_test.rb +334 -0
  20. data/test/cases/adapter_test.rb +432 -218
  21. data/test/cases/adapters/mysql2/active_schema_test.rb +85 -75
  22. data/test/cases/adapters/mysql2/auto_increment_test.rb +34 -0
  23. data/test/cases/adapters/mysql2/bind_parameter_test.rb +5 -3
  24. data/test/cases/adapters/mysql2/boolean_test.rb +6 -4
  25. data/test/cases/adapters/mysql2/case_sensitivity_test.rb +26 -24
  26. data/test/cases/adapters/mysql2/charset_collation_test.rb +20 -17
  27. data/test/cases/adapters/mysql2/connection_test.rb +48 -50
  28. data/test/cases/adapters/mysql2/count_deleted_rows_with_lock_test.rb +28 -0
  29. data/test/cases/adapters/mysql2/datetime_precision_quoting_test.rb +23 -19
  30. data/test/cases/adapters/mysql2/enum_test.rb +32 -11
  31. data/test/cases/adapters/mysql2/explain_test.rb +13 -11
  32. data/test/cases/adapters/mysql2/json_test.rb +17 -188
  33. data/test/cases/adapters/mysql2/mysql2_adapter_prevent_writes_test.rb +208 -0
  34. data/test/cases/adapters/mysql2/mysql2_adapter_test.rb +183 -28
  35. data/test/cases/adapters/mysql2/nested_deadlock_test.rb +75 -0
  36. data/test/cases/adapters/mysql2/optimizer_hints_test.rb +69 -0
  37. data/test/cases/adapters/mysql2/schema_migrations_test.rb +26 -21
  38. data/test/cases/adapters/mysql2/schema_test.rb +24 -22
  39. data/test/cases/adapters/mysql2/set_test.rb +32 -0
  40. data/test/cases/adapters/mysql2/sp_test.rb +10 -8
  41. data/test/cases/adapters/mysql2/sql_types_test.rb +8 -6
  42. data/test/cases/adapters/mysql2/table_options_test.rb +93 -10
  43. data/test/cases/adapters/mysql2/transaction_test.rb +151 -0
  44. data/test/cases/adapters/mysql2/unsigned_type_test.rb +11 -9
  45. data/test/cases/adapters/mysql2/virtual_column_test.rb +66 -0
  46. data/test/cases/adapters/postgresql/active_schema_test.rb +40 -25
  47. data/test/cases/adapters/postgresql/array_test.rb +118 -63
  48. data/test/cases/adapters/postgresql/bit_string_test.rb +12 -10
  49. data/test/cases/adapters/postgresql/bytea_test.rb +26 -25
  50. data/test/cases/adapters/postgresql/case_insensitive_test.rb +10 -9
  51. data/test/cases/adapters/postgresql/change_schema_test.rb +7 -5
  52. data/test/cases/adapters/postgresql/cidr_test.rb +2 -0
  53. data/test/cases/adapters/postgresql/citext_test.rb +58 -58
  54. data/test/cases/adapters/postgresql/collation_test.rb +17 -15
  55. data/test/cases/adapters/postgresql/composite_test.rb +25 -23
  56. data/test/cases/adapters/postgresql/connection_test.rb +73 -85
  57. data/test/cases/adapters/postgresql/create_unlogged_tables_test.rb +74 -0
  58. data/test/cases/adapters/postgresql/datatype_test.rb +19 -22
  59. data/test/cases/adapters/postgresql/date_test.rb +42 -0
  60. data/test/cases/adapters/postgresql/domain_test.rb +9 -7
  61. data/test/cases/adapters/postgresql/enum_test.rb +12 -10
  62. data/test/cases/adapters/postgresql/explain_test.rb +10 -8
  63. data/test/cases/adapters/postgresql/extension_migration_test.rb +13 -12
  64. data/test/cases/adapters/postgresql/foreign_table_test.rb +109 -0
  65. data/test/cases/adapters/postgresql/full_text_test.rb +8 -6
  66. data/test/cases/adapters/postgresql/geometric_test.rb +57 -63
  67. data/test/cases/adapters/postgresql/hstore_test.rb +288 -280
  68. data/test/cases/adapters/postgresql/infinity_test.rb +54 -15
  69. data/test/cases/adapters/postgresql/integer_test.rb +2 -0
  70. data/test/cases/adapters/postgresql/interval_test.rb +99 -0
  71. data/test/cases/adapters/postgresql/json_test.rb +16 -201
  72. data/test/cases/adapters/postgresql/ltree_test.rb +14 -16
  73. data/test/cases/adapters/postgresql/money_test.rb +47 -16
  74. data/test/cases/adapters/postgresql/network_test.rb +36 -28
  75. data/test/cases/adapters/postgresql/numbers_test.rb +7 -5
  76. data/test/cases/adapters/postgresql/optimizer_hints_test.rb +71 -0
  77. data/test/cases/adapters/postgresql/partitions_test.rb +22 -0
  78. data/test/cases/adapters/postgresql/postgresql_adapter_prevent_writes_test.rb +205 -0
  79. data/test/cases/adapters/postgresql/postgresql_adapter_test.rb +178 -136
  80. data/test/cases/adapters/postgresql/prepared_statements_disabled_test.rb +27 -0
  81. data/test/cases/adapters/postgresql/quoting_test.rb +12 -6
  82. data/test/cases/adapters/postgresql/range_test.rb +406 -292
  83. data/test/cases/adapters/postgresql/referential_integrity_test.rb +16 -15
  84. data/test/cases/adapters/postgresql/rename_table_test.rb +9 -8
  85. data/test/cases/adapters/postgresql/schema_authorization_test.rb +14 -23
  86. data/test/cases/adapters/postgresql/schema_test.rb +207 -91
  87. data/test/cases/adapters/postgresql/serial_test.rb +9 -7
  88. data/test/cases/adapters/postgresql/statement_pool_test.rb +26 -6
  89. data/test/cases/adapters/postgresql/timestamp_test.rb +17 -15
  90. data/test/cases/adapters/postgresql/transaction_nested_test.rb +114 -0
  91. data/test/cases/adapters/postgresql/transaction_test.rb +189 -0
  92. data/test/cases/adapters/postgresql/type_lookup_test.rb +12 -10
  93. data/test/cases/adapters/postgresql/utils_test.rb +11 -9
  94. data/test/cases/adapters/postgresql/uuid_test.rb +226 -109
  95. data/test/cases/adapters/postgresql/xml_test.rb +10 -14
  96. data/test/cases/adapters/sqlite3/collation_test.rb +26 -15
  97. data/test/cases/adapters/sqlite3/copy_table_test.rb +31 -28
  98. data/test/cases/adapters/sqlite3/explain_test.rb +13 -11
  99. data/test/cases/adapters/sqlite3/json_test.rb +29 -0
  100. data/test/cases/adapters/sqlite3/quoting_test.rb +35 -57
  101. data/test/cases/adapters/sqlite3/sqlite3_adapter_prevent_writes_test.rb +186 -0
  102. data/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +318 -131
  103. data/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb +11 -11
  104. data/test/cases/adapters/sqlite3/statement_pool_test.rb +7 -6
  105. data/test/cases/adapters/sqlite3/transaction_test.rb +123 -0
  106. data/test/cases/aggregations_test.rb +14 -12
  107. data/test/cases/annotate_test.rb +46 -0
  108. data/test/cases/ar_schema_test.rb +153 -86
  109. data/test/cases/arel/attributes/attribute_test.rb +1145 -0
  110. data/test/cases/arel/attributes/math_test.rb +83 -0
  111. data/test/cases/arel/attributes_test.rb +27 -0
  112. data/test/cases/arel/collectors/bind_test.rb +40 -0
  113. data/test/cases/arel/collectors/composite_test.rb +47 -0
  114. data/test/cases/arel/collectors/sql_string_test.rb +41 -0
  115. data/test/cases/arel/collectors/substitute_bind_collector_test.rb +48 -0
  116. data/test/cases/arel/crud_test.rb +65 -0
  117. data/test/cases/arel/delete_manager_test.rb +53 -0
  118. data/test/cases/arel/factory_methods_test.rb +46 -0
  119. data/test/cases/arel/helper.rb +45 -0
  120. data/test/cases/arel/insert_manager_test.rb +241 -0
  121. data/test/cases/arel/nodes/and_test.rb +30 -0
  122. data/test/cases/arel/nodes/as_test.rb +36 -0
  123. data/test/cases/arel/nodes/ascending_test.rb +46 -0
  124. data/test/cases/arel/nodes/bin_test.rb +35 -0
  125. data/test/cases/arel/nodes/binary_test.rb +29 -0
  126. data/test/cases/arel/nodes/bind_param_test.rb +22 -0
  127. data/test/cases/arel/nodes/case_test.rb +96 -0
  128. data/test/cases/arel/nodes/casted_test.rb +18 -0
  129. data/test/cases/arel/nodes/comment_test.rb +22 -0
  130. data/test/cases/arel/nodes/count_test.rb +35 -0
  131. data/test/cases/arel/nodes/delete_statement_test.rb +36 -0
  132. data/test/cases/arel/nodes/descending_test.rb +46 -0
  133. data/test/cases/arel/nodes/distinct_test.rb +21 -0
  134. data/test/cases/arel/nodes/equality_test.rb +62 -0
  135. data/test/cases/arel/nodes/extract_test.rb +43 -0
  136. data/test/cases/arel/nodes/false_test.rb +21 -0
  137. data/test/cases/arel/nodes/grouping_test.rb +26 -0
  138. data/test/cases/arel/nodes/infix_operation_test.rb +42 -0
  139. data/test/cases/arel/nodes/insert_statement_test.rb +44 -0
  140. data/test/cases/arel/nodes/named_function_test.rb +48 -0
  141. data/test/cases/arel/nodes/node_test.rb +22 -0
  142. data/test/cases/arel/nodes/not_test.rb +31 -0
  143. data/test/cases/arel/nodes/or_test.rb +36 -0
  144. data/test/cases/arel/nodes/over_test.rb +69 -0
  145. data/test/cases/arel/nodes/select_core_test.rb +79 -0
  146. data/test/cases/arel/nodes/select_statement_test.rb +51 -0
  147. data/test/cases/arel/nodes/sql_literal_test.rb +75 -0
  148. data/test/cases/arel/nodes/sum_test.rb +35 -0
  149. data/test/cases/arel/nodes/table_alias_test.rb +29 -0
  150. data/test/cases/arel/nodes/true_test.rb +21 -0
  151. data/test/cases/arel/nodes/unary_operation_test.rb +41 -0
  152. data/test/cases/arel/nodes/update_statement_test.rb +60 -0
  153. data/test/cases/arel/nodes/window_test.rb +81 -0
  154. data/test/cases/arel/nodes_test.rb +34 -0
  155. data/test/cases/arel/select_manager_test.rb +1238 -0
  156. data/test/cases/arel/support/fake_record.rb +135 -0
  157. data/test/cases/arel/table_test.rb +216 -0
  158. data/test/cases/arel/update_manager_test.rb +126 -0
  159. data/test/cases/arel/visitors/dispatch_contamination_test.rb +78 -0
  160. data/test/cases/arel/visitors/dot_test.rb +90 -0
  161. data/test/cases/arel/visitors/mysql_test.rb +157 -0
  162. data/test/cases/arel/visitors/postgres_test.rb +366 -0
  163. data/test/cases/arel/visitors/sqlite_test.rb +75 -0
  164. data/test/cases/arel/visitors/to_sql_test.rb +750 -0
  165. data/test/cases/associations/belongs_to_associations_test.rb +510 -158
  166. data/test/cases/associations/bidirectional_destroy_dependencies_test.rb +4 -2
  167. data/test/cases/associations/callbacks_test.rb +56 -38
  168. data/test/cases/associations/cascaded_eager_loading_test.rb +118 -61
  169. data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +138 -18
  170. data/test/cases/associations/eager_load_nested_include_test.rb +38 -37
  171. data/test/cases/associations/eager_singularization_test.rb +21 -21
  172. data/test/cases/associations/eager_test.rb +559 -415
  173. data/test/cases/associations/extension_test.rb +18 -12
  174. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +234 -213
  175. data/test/cases/associations/has_many_associations_test.rb +1038 -465
  176. data/test/cases/associations/has_many_through_associations_test.rb +558 -249
  177. data/test/cases/associations/has_one_associations_test.rb +294 -129
  178. data/test/cases/associations/has_one_through_associations_test.rb +121 -75
  179. data/test/cases/associations/inner_join_association_test.rb +114 -38
  180. data/test/cases/associations/inverse_associations_test.rb +606 -398
  181. data/test/cases/associations/join_model_test.rb +158 -148
  182. data/test/cases/associations/left_outer_join_association_test.rb +59 -24
  183. data/test/cases/associations/nested_through_associations_test.rb +166 -109
  184. data/test/cases/associations/required_test.rb +35 -10
  185. data/test/cases/associations_test.rb +241 -110
  186. data/test/cases/attribute_methods/read_test.rb +11 -11
  187. data/test/cases/attribute_methods_test.rb +413 -298
  188. data/test/cases/attributes_test.rb +145 -27
  189. data/test/cases/autosave_association_test.rb +681 -436
  190. data/test/cases/base_prevent_writes_test.rb +229 -0
  191. data/test/cases/base_test.rb +599 -542
  192. data/test/cases/batches_test.rb +288 -82
  193. data/test/cases/binary_test.rb +26 -31
  194. data/test/cases/bind_parameter_test.rb +194 -21
  195. data/test/cases/boolean_test.rb +52 -0
  196. data/test/cases/cache_key_test.rb +110 -5
  197. data/test/cases/calculations_test.rb +740 -177
  198. data/test/cases/callbacks_test.rb +74 -207
  199. data/test/cases/clone_test.rb +15 -10
  200. data/test/cases/coders/json_test.rb +2 -0
  201. data/test/cases/coders/yaml_column_test.rb +16 -13
  202. data/test/cases/collection_cache_key_test.rb +177 -20
  203. data/test/cases/column_alias_test.rb +9 -7
  204. data/test/cases/column_definition_test.rb +10 -68
  205. data/test/cases/comment_test.rb +166 -107
  206. data/test/cases/connection_adapters/adapter_leasing_test.rb +14 -10
  207. data/test/cases/connection_adapters/connection_handler_test.rb +358 -51
  208. data/test/cases/connection_adapters/connection_handlers_multi_db_test.rb +400 -0
  209. data/test/cases/connection_adapters/connection_handlers_multi_pool_config_test.rb +103 -0
  210. data/test/cases/connection_adapters/connection_handlers_sharding_db_test.rb +499 -0
  211. data/test/cases/connection_adapters/connection_swapping_nested_test.rb +457 -0
  212. data/test/cases/connection_adapters/legacy_connection_handlers_multi_db_test.rb +486 -0
  213. data/test/cases/connection_adapters/legacy_connection_handlers_sharding_db_test.rb +586 -0
  214. data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +319 -138
  215. data/test/cases/connection_adapters/mysql_type_lookup_test.rb +62 -50
  216. data/test/cases/connection_adapters/schema_cache_test.rb +259 -26
  217. data/test/cases/connection_adapters/type_lookup_test.rb +96 -95
  218. data/test/cases/connection_management_test.rb +13 -11
  219. data/test/cases/connection_pool_test.rb +316 -83
  220. data/test/cases/core_test.rb +82 -58
  221. data/test/cases/counter_cache_test.rb +204 -50
  222. data/test/cases/custom_locking_test.rb +5 -3
  223. data/test/cases/database_configurations/hash_config_test.rb +74 -0
  224. data/test/cases/database_configurations/resolver_test.rb +150 -0
  225. data/test/cases/database_configurations_test.rb +145 -0
  226. data/test/cases/database_selector_test.rb +296 -0
  227. data/test/cases/database_statements_test.rb +18 -16
  228. data/test/cases/date_test.rb +8 -16
  229. data/test/cases/date_time_precision_test.rb +100 -78
  230. data/test/cases/date_time_test.rb +23 -8
  231. data/test/cases/defaults_test.rb +106 -71
  232. data/test/cases/delegated_type_test.rb +57 -0
  233. data/test/cases/dirty_test.rb +419 -223
  234. data/test/cases/disconnected_test.rb +6 -6
  235. data/test/cases/dup_test.rb +54 -27
  236. data/test/cases/enum_test.rb +461 -82
  237. data/test/cases/errors_test.rb +7 -7
  238. data/test/cases/explain_subscriber_test.rb +17 -15
  239. data/test/cases/explain_test.rb +11 -19
  240. data/test/cases/filter_attributes_test.rb +153 -0
  241. data/test/cases/finder_respond_to_test.rb +14 -14
  242. data/test/cases/finder_test.rb +669 -287
  243. data/test/cases/fixture_set/file_test.rb +34 -38
  244. data/test/cases/fixtures_test.rb +833 -176
  245. data/test/cases/forbidden_attributes_protection_test.rb +32 -67
  246. data/test/cases/habtm_destroy_order_test.rb +25 -25
  247. data/test/cases/helper.rb +78 -49
  248. data/test/cases/hot_compatibility_test.rb +33 -32
  249. data/test/cases/i18n_test.rb +18 -17
  250. data/test/cases/inheritance_test.rb +180 -115
  251. data/test/cases/insert_all_test.rb +489 -0
  252. data/test/cases/instrumentation_test.rb +101 -0
  253. data/test/cases/integration_test.rb +119 -31
  254. data/test/cases/invalid_connection_test.rb +18 -16
  255. data/test/cases/invertible_migration_test.rb +183 -43
  256. data/test/cases/json_attribute_test.rb +35 -0
  257. data/test/cases/json_serialization_test.rb +57 -58
  258. data/test/cases/json_shared_test_cases.rb +290 -0
  259. data/test/cases/locking_test.rb +413 -119
  260. data/test/cases/log_subscriber_test.rb +68 -26
  261. data/test/cases/marshal_serialization_test.rb +39 -0
  262. data/test/cases/migration/change_schema_test.rb +118 -72
  263. data/test/cases/migration/change_table_test.rb +138 -30
  264. data/test/cases/migration/check_constraint_test.rb +162 -0
  265. data/test/cases/migration/column_attributes_test.rb +45 -35
  266. data/test/cases/migration/column_positioning_test.rb +18 -6
  267. data/test/cases/migration/columns_test.rb +93 -77
  268. data/test/cases/migration/command_recorder_test.rb +121 -34
  269. data/test/cases/migration/compatibility_test.rb +578 -23
  270. data/test/cases/migration/create_join_table_test.rb +35 -25
  271. data/test/cases/migration/foreign_key_test.rb +503 -284
  272. data/test/cases/migration/helper.rb +4 -3
  273. data/test/cases/migration/index_test.rb +119 -70
  274. data/test/cases/migration/logger_test.rb +9 -6
  275. data/test/cases/migration/pending_migrations_test.rb +88 -34
  276. data/test/cases/migration/references_foreign_key_test.rb +164 -150
  277. data/test/cases/migration/references_index_test.rb +38 -19
  278. data/test/cases/migration/references_statements_test.rb +15 -14
  279. data/test/cases/migration/rename_table_test.rb +53 -30
  280. data/test/cases/migration_test.rb +637 -269
  281. data/test/cases/migrator_test.rb +191 -135
  282. data/test/cases/mixin_test.rb +7 -11
  283. data/test/cases/modules_test.rb +36 -34
  284. data/test/cases/multi_db_migrator_test.rb +223 -0
  285. data/test/cases/multiparameter_attributes_test.rb +60 -33
  286. data/test/cases/multiple_db_test.rb +16 -22
  287. data/test/cases/nested_attributes_test.rb +341 -320
  288. data/test/cases/nested_attributes_with_callbacks_test.rb +26 -24
  289. data/test/cases/null_relation_test.rb +84 -0
  290. data/test/cases/numeric_data_test.rb +93 -0
  291. data/test/cases/persistence_test.rb +361 -269
  292. data/test/cases/pooled_connections_test.rb +18 -26
  293. data/test/cases/prepared_statement_status_test.rb +48 -0
  294. data/test/cases/primary_keys_test.rb +210 -104
  295. data/test/cases/query_cache_test.rb +610 -141
  296. data/test/cases/quoting_test.rb +132 -31
  297. data/test/cases/readonly_test.rb +49 -48
  298. data/test/cases/reaper_test.rb +146 -32
  299. data/test/cases/reflection_test.rb +167 -156
  300. data/test/cases/relation/delegation_test.rb +49 -36
  301. data/test/cases/relation/delete_all_test.rb +117 -0
  302. data/test/cases/relation/merging_test.rb +319 -42
  303. data/test/cases/relation/mutation_test.rb +55 -93
  304. data/test/cases/relation/or_test.rb +129 -29
  305. data/test/cases/relation/predicate_builder_test.rb +21 -6
  306. data/test/cases/relation/record_fetch_warning_test.rb +5 -3
  307. data/test/cases/relation/select_test.rb +67 -0
  308. data/test/cases/relation/update_all_test.rb +317 -0
  309. data/test/cases/relation/where_chain_test.rb +68 -32
  310. data/test/cases/relation/where_clause_test.rb +136 -61
  311. data/test/cases/relation/where_test.rb +155 -48
  312. data/test/cases/relation_test.rb +266 -112
  313. data/test/cases/relations_test.rb +969 -744
  314. data/test/cases/reload_models_test.rb +13 -9
  315. data/test/cases/reserved_word_test.rb +141 -0
  316. data/test/cases/result_test.rb +68 -17
  317. data/test/cases/sanitize_test.rb +87 -71
  318. data/test/cases/schema_dumper_test.rb +221 -128
  319. data/test/cases/schema_loading_test.rb +3 -2
  320. data/test/cases/scoping/default_scoping_test.rb +185 -144
  321. data/test/cases/scoping/named_scoping_test.rb +177 -89
  322. data/test/cases/scoping/relation_scoping_test.rb +197 -75
  323. data/test/cases/secure_token_test.rb +18 -3
  324. data/test/cases/serialization_test.rb +30 -28
  325. data/test/cases/serialized_attribute_test.rb +133 -42
  326. data/test/cases/signed_id_test.rb +168 -0
  327. data/test/cases/statement_cache_test.rb +41 -24
  328. data/test/cases/statement_invalid_test.rb +42 -0
  329. data/test/cases/store_test.rb +180 -55
  330. data/test/cases/strict_loading_test.rb +473 -0
  331. data/test/cases/suppressor_test.rb +26 -12
  332. data/test/cases/tasks/database_tasks_test.rb +1258 -194
  333. data/test/cases/tasks/mysql_rake_test.rb +370 -298
  334. data/test/cases/tasks/postgresql_rake_test.rb +481 -251
  335. data/test/cases/tasks/sqlite_rake_test.rb +225 -178
  336. data/test/cases/test_case.rb +51 -40
  337. data/test/cases/test_databases_test.rb +79 -0
  338. data/test/cases/test_fixtures_test.rb +79 -19
  339. data/test/cases/time_precision_test.rb +98 -76
  340. data/test/cases/timestamp_test.rb +102 -99
  341. data/test/cases/touch_later_test.rb +12 -10
  342. data/test/cases/transaction_callbacks_test.rb +344 -90
  343. data/test/cases/transaction_isolation_test.rb +12 -12
  344. data/test/cases/transactions_test.rb +612 -162
  345. data/test/cases/type/adapter_specific_registry_test.rb +14 -2
  346. data/test/cases/type/date_time_test.rb +4 -2
  347. data/test/cases/type/integer_test.rb +4 -2
  348. data/test/cases/type/string_test.rb +10 -8
  349. data/test/cases/type/time_test.rb +28 -0
  350. data/test/cases/type/type_map_test.rb +29 -28
  351. data/test/cases/type/unsigned_integer_test.rb +19 -0
  352. data/test/cases/type_test.rb +2 -0
  353. data/test/cases/types_test.rb +3 -1
  354. data/test/cases/unconnected_test.rb +14 -1
  355. data/test/cases/unsafe_raw_sql_test.rb +274 -0
  356. data/test/cases/validations/absence_validation_test.rb +19 -17
  357. data/test/cases/validations/association_validation_test.rb +30 -28
  358. data/test/cases/validations/i18n_generate_message_validation_test.rb +34 -16
  359. data/test/cases/validations/i18n_validation_test.rb +22 -21
  360. data/test/cases/validations/length_validation_test.rb +34 -33
  361. data/test/cases/validations/numericality_validation_test.rb +181 -0
  362. data/test/cases/validations/presence_validation_test.rb +21 -19
  363. data/test/cases/validations/uniqueness_validation_test.rb +156 -86
  364. data/test/cases/validations_repair_helper.rb +2 -0
  365. data/test/cases/validations_test.rb +61 -26
  366. data/test/cases/view_test.rb +122 -116
  367. data/test/cases/yaml_serialization_test.rb +79 -34
  368. data/test/config.example.yml +19 -19
  369. data/test/config.rb +3 -1
  370. data/test/config.yml +16 -6
  371. data/test/fixtures/all/namespaced/accounts.yml +2 -0
  372. data/test/fixtures/author_addresses.yml +1 -8
  373. data/test/fixtures/authors.yml +1 -7
  374. data/test/fixtures/binaries.yml +4 -0
  375. data/test/fixtures/books.yml +9 -2
  376. data/test/fixtures/categories_posts.yml +3 -0
  377. data/test/fixtures/citations.yml +5 -0
  378. data/test/fixtures/comments.yml +7 -0
  379. data/test/fixtures/companies.yml +5 -0
  380. data/test/fixtures/computers.yml +2 -0
  381. data/test/fixtures/customers.yml +10 -1
  382. data/test/fixtures/developers.yml +1 -1
  383. data/test/fixtures/essays.yml +10 -0
  384. data/test/fixtures/faces.yml +3 -3
  385. data/test/fixtures/humans.yml +5 -0
  386. data/test/fixtures/interests.yml +7 -7
  387. data/test/fixtures/memberships.yml +7 -0
  388. data/test/fixtures/minimalistics.yml +3 -0
  389. data/test/fixtures/mixed_case_monkeys.yml +2 -2
  390. data/test/fixtures/naked/yml/courses_with_invalid_key.yml +3 -0
  391. data/test/fixtures/naked/yml/parrots.yml +1 -0
  392. data/test/fixtures/other_books.yml +26 -0
  393. data/test/fixtures/other_posts.yml +1 -0
  394. data/test/fixtures/parrots.yml +7 -1
  395. data/test/fixtures/pirates.yml +3 -0
  396. data/test/fixtures/posts.yml +11 -3
  397. data/test/fixtures/readers.yml +6 -0
  398. data/test/fixtures/reserved_words/values.yml +2 -2
  399. data/test/fixtures/sponsors.yml +3 -0
  400. data/test/fixtures/strict_zines.yml +2 -0
  401. data/test/fixtures/subscribers.yml +1 -1
  402. data/test/fixtures/tasks.yml +1 -1
  403. data/test/fixtures/warehouse-things.yml +3 -0
  404. data/test/migrations/10_urban/9_add_expressions.rb +2 -0
  405. data/test/migrations/decimal/1_give_me_big_numbers.rb +6 -4
  406. data/test/migrations/magic/1_currencies_have_symbols.rb +3 -2
  407. data/test/migrations/missing/1000_people_have_middle_names.rb +2 -0
  408. data/test/migrations/missing/1_people_have_last_names.rb +2 -0
  409. data/test/migrations/missing/3_we_need_reminders.rb +2 -0
  410. data/test/migrations/missing/4_innocent_jointable.rb +3 -1
  411. data/test/migrations/rename/1_we_need_things.rb +2 -0
  412. data/test/migrations/rename/2_rename_things.rb +2 -0
  413. data/test/migrations/to_copy/1_people_have_hobbies.rb +3 -1
  414. data/test/migrations/to_copy/2_people_have_descriptions.rb +3 -1
  415. data/test/migrations/to_copy2/1_create_articles.rb +2 -0
  416. data/test/migrations/to_copy2/2_create_comments.rb +3 -1
  417. data/test/migrations/to_copy_with_name_collision/1_people_have_hobbies.rb +3 -1
  418. data/test/migrations/to_copy_with_timestamps/20090101010101_people_have_hobbies.rb +3 -1
  419. data/test/migrations/to_copy_with_timestamps/20090101010202_people_have_descriptions.rb +3 -1
  420. data/test/migrations/to_copy_with_timestamps2/20090101010101_create_articles.rb +2 -0
  421. data/test/migrations/to_copy_with_timestamps2/20090101010202_create_comments.rb +2 -0
  422. data/test/migrations/valid/1_valid_people_have_last_names.rb +2 -0
  423. data/test/migrations/valid/2_we_need_reminders.rb +2 -0
  424. data/test/migrations/valid/3_innocent_jointable.rb +3 -1
  425. data/test/migrations/valid_with_subdirectories/1_valid_people_have_last_names.rb +2 -0
  426. data/test/migrations/valid_with_subdirectories/sub/2_we_need_reminders.rb +2 -0
  427. data/test/migrations/valid_with_subdirectories/sub1/3_innocent_jointable.rb +3 -1
  428. data/test/migrations/valid_with_timestamps/20100101010101_valid_with_timestamps_people_have_last_names.rb +2 -0
  429. data/test/migrations/valid_with_timestamps/20100201010101_valid_with_timestamps_we_need_reminders.rb +2 -0
  430. data/test/migrations/valid_with_timestamps/20100301010101_valid_with_timestamps_innocent_jointable.rb +3 -1
  431. data/test/migrations/version_check/20131219224947_migration_version_check.rb +2 -0
  432. data/test/models/account.rb +46 -0
  433. data/test/models/admin/account.rb +3 -1
  434. data/test/models/admin/randomly_named_c1.rb +2 -0
  435. data/test/models/admin/user.rb +16 -8
  436. data/test/models/admin.rb +4 -2
  437. data/test/models/aircraft.rb +3 -1
  438. data/test/models/arunit2_model.rb +2 -0
  439. data/test/models/author.rb +153 -102
  440. data/test/models/auto_id.rb +2 -0
  441. data/test/models/autoloadable/extra_firm.rb +2 -0
  442. data/test/models/binary.rb +3 -1
  443. data/test/models/binary_field.rb +6 -0
  444. data/test/models/bird.rb +13 -1
  445. data/test/models/book.rb +14 -4
  446. data/test/models/book_destroy_async.rb +24 -0
  447. data/test/models/boolean.rb +5 -0
  448. data/test/models/bulb.rb +13 -4
  449. data/test/models/cake_designer.rb +2 -0
  450. data/test/models/car.rb +17 -10
  451. data/test/models/carrier.rb +2 -0
  452. data/test/models/cart.rb +5 -0
  453. data/test/models/cat.rb +2 -0
  454. data/test/models/categorization.rb +8 -6
  455. data/test/models/category.rb +28 -16
  456. data/test/models/chef.rb +2 -0
  457. data/test/models/citation.rb +5 -1
  458. data/test/models/club.rb +13 -10
  459. data/test/models/college.rb +4 -2
  460. data/test/models/column.rb +2 -0
  461. data/test/models/column_name.rb +2 -0
  462. data/test/models/comment.rb +32 -10
  463. data/test/models/company.rb +102 -106
  464. data/test/models/company_in_module.rb +27 -26
  465. data/test/models/computer.rb +3 -1
  466. data/test/models/contact.rb +15 -13
  467. data/test/models/content.rb +5 -3
  468. data/test/models/contract.rb +21 -3
  469. data/test/models/country.rb +2 -4
  470. data/test/models/course.rb +3 -1
  471. data/test/models/customer.rb +10 -8
  472. data/test/models/customer_carrier.rb +2 -0
  473. data/test/models/dashboard.rb +2 -0
  474. data/test/models/default.rb +2 -0
  475. data/test/models/department.rb +2 -0
  476. data/test/models/destroy_async_parent.rb +15 -0
  477. data/test/models/destroy_async_parent_soft_delete.rb +20 -0
  478. data/test/models/developer.rb +152 -85
  479. data/test/models/dl_keyed_belongs_to.rb +13 -0
  480. data/test/models/dl_keyed_belongs_to_soft_delete.rb +19 -0
  481. data/test/models/dl_keyed_has_many.rb +5 -0
  482. data/test/models/dl_keyed_has_many_through.rb +5 -0
  483. data/test/models/dl_keyed_has_one.rb +5 -0
  484. data/test/models/dl_keyed_join.rb +10 -0
  485. data/test/models/dog.rb +2 -0
  486. data/test/models/dog_lover.rb +2 -0
  487. data/test/models/doubloon.rb +3 -1
  488. data/test/models/drink_designer.rb +17 -0
  489. data/test/models/edge.rb +4 -2
  490. data/test/models/electron.rb +2 -0
  491. data/test/models/engine.rb +3 -2
  492. data/test/models/entrant.rb +2 -0
  493. data/test/models/entry.rb +5 -0
  494. data/test/models/essay.rb +6 -3
  495. data/test/models/essay_destroy_async.rb +12 -0
  496. data/test/models/event.rb +3 -1
  497. data/test/models/eye.rb +5 -3
  498. data/test/models/face.rb +14 -6
  499. data/test/models/family.rb +6 -0
  500. data/test/models/family_tree.rb +6 -0
  501. data/test/models/friendship.rb +5 -3
  502. data/test/models/frog.rb +8 -0
  503. data/test/models/guid.rb +3 -1
  504. data/test/models/guitar.rb +2 -0
  505. data/test/models/hotel.rb +5 -3
  506. data/test/models/human.rb +39 -0
  507. data/test/models/image.rb +3 -1
  508. data/test/models/interest.rb +14 -3
  509. data/test/models/invoice.rb +4 -2
  510. data/test/models/item.rb +3 -1
  511. data/test/models/job.rb +5 -3
  512. data/test/models/joke.rb +4 -2
  513. data/test/models/keyboard.rb +3 -1
  514. data/test/models/legacy_thing.rb +2 -0
  515. data/test/models/lesson.rb +2 -0
  516. data/test/models/line_item.rb +3 -1
  517. data/test/models/liquid.rb +2 -0
  518. data/test/models/matey.rb +3 -1
  519. data/test/models/measurement.rb +4 -0
  520. data/test/models/member.rb +23 -20
  521. data/test/models/member_detail.rb +3 -0
  522. data/test/models/member_type.rb +2 -0
  523. data/test/models/membership.rb +4 -1
  524. data/test/models/mentor.rb +3 -1
  525. data/test/models/message.rb +5 -0
  526. data/test/models/minimalistic.rb +2 -0
  527. data/test/models/minivan.rb +3 -2
  528. data/test/models/mixed_case_monkey.rb +3 -1
  529. data/test/models/molecule.rb +2 -0
  530. data/test/models/mouse.rb +6 -0
  531. data/test/models/movie.rb +2 -0
  532. data/test/models/node.rb +4 -2
  533. data/test/models/non_primary_key.rb +2 -0
  534. data/test/models/notification.rb +2 -0
  535. data/test/models/numeric_data.rb +12 -0
  536. data/test/models/order.rb +4 -2
  537. data/test/models/organization.rb +9 -7
  538. data/test/models/other_dog.rb +3 -1
  539. data/test/models/owner.rb +6 -4
  540. data/test/models/parrot.rb +12 -4
  541. data/test/models/person.rb +59 -54
  542. data/test/models/personal_legacy_thing.rb +3 -1
  543. data/test/models/pet.rb +4 -2
  544. data/test/models/pet_treasure.rb +2 -0
  545. data/test/models/pirate.rb +67 -43
  546. data/test/models/possession.rb +3 -1
  547. data/test/models/post.rb +184 -86
  548. data/test/models/price_estimate.rb +11 -1
  549. data/test/models/professor.rb +3 -1
  550. data/test/models/project.rb +14 -12
  551. data/test/models/publisher/article.rb +2 -0
  552. data/test/models/publisher/magazine.rb +2 -0
  553. data/test/models/publisher.rb +2 -0
  554. data/test/models/randomly_named_c1.rb +2 -0
  555. data/test/models/rating.rb +5 -1
  556. data/test/models/reader.rb +7 -5
  557. data/test/models/recipe.rb +2 -0
  558. data/test/models/record.rb +2 -0
  559. data/test/models/reference.rb +6 -3
  560. data/test/models/reply.rb +39 -21
  561. data/test/models/room.rb +6 -0
  562. data/test/models/section.rb +6 -0
  563. data/test/models/seminar.rb +6 -0
  564. data/test/models/session.rb +6 -0
  565. data/test/models/ship.rb +12 -9
  566. data/test/models/ship_part.rb +5 -3
  567. data/test/models/shop.rb +4 -2
  568. data/test/models/shop_account.rb +2 -0
  569. data/test/models/speedometer.rb +2 -0
  570. data/test/models/sponsor.rb +8 -5
  571. data/test/models/squeak.rb +6 -0
  572. data/test/models/strict_zine.rb +7 -0
  573. data/test/models/string_key_object.rb +2 -0
  574. data/test/models/student.rb +2 -0
  575. data/test/models/subscriber.rb +4 -2
  576. data/test/models/subscription.rb +5 -1
  577. data/test/models/tag.rb +6 -3
  578. data/test/models/tagging.rb +13 -6
  579. data/test/models/task.rb +2 -0
  580. data/test/models/topic.rb +54 -19
  581. data/test/models/toy.rb +4 -0
  582. data/test/models/traffic_light.rb +2 -0
  583. data/test/models/treasure.rb +5 -3
  584. data/test/models/treaty.rb +2 -4
  585. data/test/models/tree.rb +2 -0
  586. data/test/models/tuning_peg.rb +2 -0
  587. data/test/models/tyre.rb +2 -0
  588. data/test/models/user.rb +12 -4
  589. data/test/models/uuid_child.rb +2 -0
  590. data/test/models/uuid_item.rb +2 -0
  591. data/test/models/uuid_parent.rb +2 -0
  592. data/test/models/vegetables.rb +12 -3
  593. data/test/models/vertex.rb +6 -4
  594. data/test/models/warehouse_thing.rb +2 -0
  595. data/test/models/wheel.rb +3 -1
  596. data/test/models/without_table.rb +3 -1
  597. data/test/models/zine.rb +3 -1
  598. data/test/schema/mysql2_specific_schema.rb +49 -35
  599. data/test/schema/oracle_specific_schema.rb +13 -15
  600. data/test/schema/postgresql_specific_schema.rb +51 -40
  601. data/test/schema/schema.rb +334 -154
  602. data/test/schema/sqlite_specific_schema.rb +9 -16
  603. data/test/support/config.rb +26 -26
  604. data/test/support/connection.rb +14 -8
  605. data/test/support/connection_helper.rb +3 -1
  606. data/test/support/ddl_helper.rb +2 -0
  607. data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_6_0_topic.dump +0 -0
  608. data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_6_0_topic_associations.dump +0 -0
  609. data/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_0_topic.dump +0 -0
  610. data/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_0_topic_associations.dump +0 -0
  611. data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_0_topic.dump +0 -0
  612. data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_0_topic_associations.dump +0 -0
  613. data/test/support/marshal_compatibility_fixtures/SQLite/rails_6_0_topic.dump +0 -0
  614. data/test/support/marshal_compatibility_fixtures/SQLite/rails_6_0_topic_associations.dump +0 -0
  615. data/test/support/marshal_compatibility_fixtures/legacy_6_0_record_mysql.dump +0 -0
  616. data/test/support/marshal_compatibility_fixtures/legacy_relation.dump +0 -0
  617. data/test/support/schema_dumping_helper.rb +2 -0
  618. data/test/support/stubs/strong_parameters.rb +40 -0
  619. data/test/support/yaml_compatibility_fixtures/rails_v1_mysql.yml +206 -0
  620. data/test/support/yaml_compatibility_fixtures/rails_v2.yml +55 -0
  621. metadata +190 -14
@@ -1,32 +1,29 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "cases/helper"
2
4
  require "models/book"
3
- require 'models/club'
4
- require 'models/company'
5
+ require "models/club"
6
+ require "models/company"
5
7
  require "models/contract"
6
- require 'models/edge'
7
- require 'models/organization'
8
- require 'models/possession'
9
- require 'models/topic'
10
- require 'models/reply'
11
- require 'models/minivan'
12
- require 'models/speedometer'
13
- require 'models/ship_part'
14
- require 'models/treasure'
15
- require 'models/developer'
16
- require 'models/comment'
17
- require 'models/rating'
18
- require 'models/post'
19
-
20
- class NumericData < ActiveRecord::Base
21
- self.table_name = 'numeric_data'
22
-
23
- attribute :world_population, :integer
24
- attribute :my_house_population, :integer
25
- attribute :atoms_in_universe, :integer
26
- end
8
+ require "models/edge"
9
+ require "models/organization"
10
+ require "models/possession"
11
+ require "models/author"
12
+ require "models/topic"
13
+ require "models/reply"
14
+ require "models/numeric_data"
15
+ require "models/minivan"
16
+ require "models/speedometer"
17
+ require "models/ship_part"
18
+ require "models/treasure"
19
+ require "models/developer"
20
+ require "models/post"
21
+ require "models/comment"
22
+ require "models/rating"
23
+ require "support/stubs/strong_parameters"
27
24
 
28
25
  class CalculationsTest < ActiveRecord::TestCase
29
- fixtures :companies, :accounts, :topics, :speedometers, :minivans, :books
26
+ fixtures :companies, :accounts, :authors, :author_addresses, :topics, :speedometers, :minivans, :books, :posts, :comments
30
27
 
31
28
  def test_should_sum_field
32
29
  assert_equal 318, Account.sum(:credit_limit)
@@ -57,7 +54,7 @@ class CalculationsTest < ActiveRecord::TestCase
57
54
 
58
55
  def test_should_return_integer_average_if_db_returns_such
59
56
  ShipPart.delete_all
60
- ShipPart.create!(:id => 3, :name => 'foo')
57
+ ShipPart.create!(id: 3, name: "foo")
61
58
  value = ShipPart.average(:id)
62
59
  assert_equal 3, value
63
60
  end
@@ -92,25 +89,25 @@ class CalculationsTest < ActiveRecord::TestCase
92
89
 
93
90
  def test_should_group_by_field
94
91
  c = Account.group(:firm_id).sum(:credit_limit)
95
- [1,6,2].each do |firm_id|
96
- assert c.keys.include?(firm_id), "Group #{c.inspect} does not contain firm_id #{firm_id}"
92
+ [1, 6, 2].each do |firm_id|
93
+ assert_includes c.keys, firm_id, "Group #{c.inspect} does not contain firm_id #{firm_id}"
97
94
  end
98
95
  end
99
96
 
100
97
  def test_should_group_by_arel_attribute
101
98
  c = Account.group(Account.arel_table[:firm_id]).sum(:credit_limit)
102
- [1,6,2].each do |firm_id|
103
- assert c.keys.include?(firm_id), "Group #{c.inspect} does not contain firm_id #{firm_id}"
99
+ [1, 6, 2].each do |firm_id|
100
+ assert_includes c.keys, firm_id, "Group #{c.inspect} does not contain firm_id #{firm_id}"
104
101
  end
105
102
  end
106
103
 
107
104
  def test_should_group_by_multiple_fields
108
- c = Account.group('firm_id', :credit_limit).count(:all)
109
- [ [nil, 50], [1, 50], [6, 50], [6, 55], [9, 53], [2, 60] ].each { |firm_and_limit| assert c.keys.include?(firm_and_limit) }
105
+ c = Account.group("firm_id", :credit_limit).count(:all)
106
+ [ [nil, 50], [1, 50], [6, 50], [6, 55], [9, 53], [2, 60] ].each { |firm_and_limit| assert_includes c.keys, firm_and_limit }
110
107
  end
111
108
 
112
109
  def test_should_group_by_multiple_fields_having_functions
113
- c = Topic.group(:author_name, 'COALESCE(type, title)').count(:all)
110
+ c = Topic.group(:author_name, "COALESCE(type, title)").count(:all)
114
111
  assert_equal 1, c[["Carl", "The Third Topic of the day"]]
115
112
  assert_equal 1, c[["Mary", "Reply"]]
116
113
  assert_equal 1, c[["David", "The First Topic"]]
@@ -118,10 +115,54 @@ class CalculationsTest < ActiveRecord::TestCase
118
115
  end
119
116
 
120
117
  def test_should_group_by_summed_field
121
- c = Account.group(:firm_id).sum(:credit_limit)
122
- assert_equal 50, c[1]
123
- assert_equal 105, c[6]
124
- assert_equal 60, c[2]
118
+ expected = { nil => 50, 1 => 50, 2 => 60, 6 => 105, 9 => 53 }
119
+ assert_equal expected, Account.group(:firm_id).sum(:credit_limit)
120
+ end
121
+
122
+ def test_group_by_multiple_same_field
123
+ accounts = Account.group(:firm_id)
124
+
125
+ expected = {
126
+ nil => 50,
127
+ 1 => 50,
128
+ 2 => 60,
129
+ 6 => 105,
130
+ 9 => 53
131
+ }
132
+ assert_equal expected, accounts.sum(:credit_limit)
133
+ assert_equal expected, accounts.merge!(accounts).uniq!(:group).sum(:credit_limit)
134
+
135
+ expected = {
136
+ [nil, nil] => 50,
137
+ [1, 1] => 50,
138
+ [2, 2] => 60,
139
+ [6, 6] => 55,
140
+ [9, 9] => 53
141
+ }
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
150
+
151
+ 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
157
+ }
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
125
166
  end
126
167
 
127
168
  def test_should_generate_valid_sql_with_joins_and_group
@@ -143,6 +184,13 @@ class CalculationsTest < ActiveRecord::TestCase
143
184
  end
144
185
  end
145
186
 
187
+ 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
189
+ c = Account.group(:firm_id).order("accounts_firm_id").sum(:credit_limit)
190
+ assert_equal [1, 2, 6, 9], c.keys.compact
191
+ end
192
+ end
193
+
146
194
  def test_should_order_by_grouped_field
147
195
  c = Account.group(:firm_id).order("firm_id").sum(:credit_limit)
148
196
  assert_equal [1, 2, 6, 9], c.keys.compact
@@ -166,14 +214,14 @@ class CalculationsTest < ActiveRecord::TestCase
166
214
  end
167
215
 
168
216
  def test_limit_should_apply_before_count
169
- accounts = Account.limit(3).where('firm_id IS NOT NULL')
217
+ accounts = Account.order(:id).limit(4)
170
218
 
171
219
  assert_equal 3, accounts.count(:firm_id)
172
220
  assert_equal 3, accounts.select(:firm_id).count
173
221
  end
174
222
 
175
223
  def test_limit_should_apply_before_count_arel_attribute
176
- accounts = Account.limit(3).where('firm_id IS NOT NULL')
224
+ accounts = Account.order(:id).limit(4)
177
225
 
178
226
  firm_id_attribute = Account.arel_table[:firm_id]
179
227
  assert_equal 3, accounts.count(firm_id_attribute)
@@ -189,15 +237,15 @@ class CalculationsTest < ActiveRecord::TestCase
189
237
  def test_limit_is_kept
190
238
  return if current_adapter?(:OracleAdapter)
191
239
 
192
- queries = assert_sql { Account.limit(1).count }
240
+ queries = capture_sql { Account.limit(1).count }
193
241
  assert_equal 1, queries.length
194
- assert_match(/LIMIT/, queries.first)
242
+ assert_match(/FETCH FIRST/, queries.first)
195
243
  end
196
244
 
197
245
  def test_offset_is_kept
198
246
  return if current_adapter?(:OracleAdapter)
199
247
 
200
- queries = assert_sql { Account.offset(1).count }
248
+ queries = capture_sql { Account.offset(1).count }
201
249
  assert_equal 1, queries.length
202
250
  assert_match(/OFFSET/, queries.first)
203
251
  end
@@ -205,16 +253,16 @@ class CalculationsTest < ActiveRecord::TestCase
205
253
  def test_limit_with_offset_is_kept
206
254
  return if current_adapter?(:OracleAdapter)
207
255
 
208
- queries = assert_sql { Account.limit(1).offset(1).count }
256
+ queries = capture_sql { Account.limit(1).offset(1).count }
209
257
  assert_equal 1, queries.length
210
- assert_match(/LIMIT/, queries.first)
258
+ assert_match(/FETCH FIRST/, queries.first)
211
259
  assert_match(/OFFSET/, queries.first)
212
260
  end
213
261
 
214
262
  def test_no_limit_no_offset
215
- queries = assert_sql { Account.count }
263
+ queries = capture_sql { Account.count }
216
264
  assert_equal 1, queries.length
217
- assert_no_match(/LIMIT/, queries.first)
265
+ assert_no_match(/FETCH FIRST/, queries.first)
218
266
  assert_no_match(/OFFSET/, queries.first)
219
267
  end
220
268
 
@@ -223,12 +271,87 @@ class CalculationsTest < ActiveRecord::TestCase
223
271
  Account.select("credit_limit, firm_name").count
224
272
  }
225
273
 
226
- assert_match %r{accounts}i, e.message
227
- assert_match "credit_limit, firm_name", e.message
274
+ assert_match %r{accounts}i, e.sql
275
+ assert_match "credit_limit, firm_name", e.sql
276
+ end
277
+
278
+ def test_apply_distinct_in_count
279
+ queries = capture_sql do
280
+ Account.distinct.count
281
+ Account.group(:firm_id).distinct.count
282
+ end
283
+
284
+ queries.each do |query|
285
+ assert_match %r{\ASELECT(?! DISTINCT) COUNT\(DISTINCT\b}, query
286
+ end
287
+ end
288
+
289
+ def test_count_with_eager_loading_and_custom_order
290
+ 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) }
293
+ end
294
+
295
+ def test_count_with_eager_loading_and_custom_select_and_order
296
+ 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) }
299
+ end
300
+
301
+ def test_count_with_eager_loading_and_custom_order_and_distinct
302
+ 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) }
305
+ end
306
+
307
+ def test_distinct_count_all_with_custom_select_and_order
308
+ 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 }
311
+ end
312
+
313
+ def test_distinct_count_with_order_and_limit
314
+ assert_equal 4, Account.distinct.order(:firm_id).limit(4).count
315
+ end
316
+
317
+ def test_distinct_count_with_order_and_offset
318
+ assert_equal 4, Account.distinct.order(:firm_id).offset(2).count
319
+ end
320
+
321
+ def test_distinct_count_with_order_and_limit_and_offset
322
+ assert_equal 4, Account.distinct.order(:firm_id).limit(4).offset(2).count
323
+ end
324
+
325
+ def test_distinct_joins_count_with_order_and_limit
326
+ assert_equal 3, Account.joins(:firm).distinct.order(:firm_id).limit(3).count
327
+ end
328
+
329
+ def test_distinct_joins_count_with_order_and_offset
330
+ assert_equal 3, Account.joins(:firm).distinct.order(:firm_id).offset(2).count
331
+ end
332
+
333
+ def test_distinct_joins_count_with_order_and_limit_and_offset
334
+ assert_equal 3, Account.joins(:firm).distinct.order(:firm_id).limit(3).offset(2).count
335
+ end
336
+
337
+ def test_distinct_joins_count_with_group_by
338
+ expected = { nil => 4, 1 => 1, 2 => 1, 4 => 1, 5 => 1, 7 => 1 }
339
+ assert_equal expected, Post.left_joins(:comments).group(:post_id).distinct.count(:author_id)
340
+ assert_equal expected, Post.left_joins(:comments).group(:post_id).distinct.select(:author_id).count
341
+ assert_equal expected, Post.left_joins(:comments).group(:post_id).count("DISTINCT posts.author_id")
342
+ assert_equal expected, Post.left_joins(:comments).group(:post_id).select("DISTINCT posts.author_id").count
343
+
344
+ expected = { nil => 6, 1 => 1, 2 => 1, 4 => 1, 5 => 1, 7 => 1 }
345
+ assert_equal expected, Post.left_joins(:comments).group(:post_id).distinct.count(:all)
346
+ assert_equal expected, Post.left_joins(:comments).group(:post_id).distinct.select(:author_id).count(:all)
347
+ end
348
+
349
+ def test_distinct_count_with_group_by_and_order_and_limit
350
+ assert_equal({ 6 => 2 }, Account.group(:firm_id).distinct.order("1 DESC").limit(1).count)
228
351
  end
229
352
 
230
353
  def test_should_group_by_summed_field_having_condition
231
- c = Account.group(:firm_id).having('sum(credit_limit) > 50').sum(:credit_limit)
354
+ c = Account.group(:firm_id).having("sum(credit_limit) > 50").sum(:credit_limit)
232
355
  assert_nil c[1]
233
356
  assert_equal 105, c[6]
234
357
  assert_equal 60, c[2]
@@ -250,52 +373,63 @@ class CalculationsTest < ActiveRecord::TestCase
250
373
  end
251
374
 
252
375
  def test_should_sum_field_with_conditions
253
- assert_equal 105, Account.where('firm_id = 6').sum(:credit_limit)
376
+ assert_equal 105, Account.where("firm_id = 6").sum(:credit_limit)
254
377
  end
255
378
 
256
379
  def test_should_return_zero_if_sum_conditions_return_nothing
257
- assert_equal 0, Account.where('1 = 2').sum(:credit_limit)
258
- assert_equal 0, companies(:rails_core).companies.where('1 = 2').sum(:id)
380
+ assert_equal 0, Account.where("1 = 2").sum(:credit_limit)
381
+ assert_equal 0, companies(:rails_core).companies.where("1 = 2").sum(:id)
259
382
  end
260
383
 
261
384
  def test_sum_should_return_valid_values_for_decimals
262
- NumericData.create(:bank_balance => 19.83)
385
+ NumericData.create(bank_balance: 19.83)
263
386
  assert_equal 19.83, NumericData.sum(:bank_balance)
264
387
  end
265
388
 
266
389
  def test_should_return_type_casted_values_with_group_and_expression
267
- assert_equal 0.5, Account.group(:firm_name).sum('0.01 * credit_limit')['37signals']
390
+ assert_equal 0.5, Account.group(:firm_name).sum("0.01 * credit_limit")["37signals"]
268
391
  end
269
392
 
270
393
  def test_should_group_by_summed_field_with_conditions
271
- c = Account.where('firm_id > 1').group(:firm_id).sum(:credit_limit)
394
+ c = Account.where("firm_id > 1").group(:firm_id).sum(:credit_limit)
272
395
  assert_nil c[1]
273
396
  assert_equal 105, c[6]
274
397
  assert_equal 60, c[2]
275
398
  end
276
399
 
277
400
  def test_should_group_by_summed_field_with_conditions_and_having
278
- c = Account.where('firm_id > 1').group(:firm_id).
279
- having('sum(credit_limit) > 60').sum(:credit_limit)
401
+ c = Account.where("firm_id > 1").group(:firm_id).
402
+ having("sum(credit_limit) > 60").sum(:credit_limit)
280
403
  assert_nil c[1]
281
404
  assert_equal 105, c[6]
282
405
  assert_nil c[2]
283
406
  end
284
407
 
285
408
  def test_should_group_by_fields_with_table_alias
286
- c = Account.group('accounts.firm_id').sum(:credit_limit)
409
+ c = Account.group("accounts.firm_id").sum(:credit_limit)
410
+ assert_equal 50, c[1]
411
+ assert_equal 105, c[6]
412
+ assert_equal 60, c[2]
413
+ end
414
+
415
+ def test_should_calculate_grouped_with_longer_field
416
+ field = "a" * Account.connection.max_identifier_length
417
+
418
+ Account.update_all("#{field} = credit_limit")
419
+
420
+ c = Account.group(:firm_id).sum(field)
287
421
  assert_equal 50, c[1]
288
422
  assert_equal 105, c[6]
289
423
  assert_equal 60, c[2]
290
424
  end
291
425
 
292
426
  def test_should_calculate_with_invalid_field
293
- assert_equal 6, Account.calculate(:count, '*')
427
+ assert_equal 6, Account.calculate(:count, "*")
294
428
  assert_equal 6, Account.calculate(:count, :all)
295
429
  end
296
430
 
297
431
  def test_should_calculate_grouped_with_invalid_field
298
- c = Account.group('accounts.firm_id').count(:all)
432
+ c = Account.group("accounts.firm_id").count(:all)
299
433
  assert_equal 1, c[1]
300
434
  assert_equal 2, c[6]
301
435
  assert_equal 1, c[2]
@@ -309,8 +443,8 @@ class CalculationsTest < ActiveRecord::TestCase
309
443
  end
310
444
 
311
445
  def test_should_group_by_association_with_non_numeric_foreign_key
312
- Speedometer.create! id: 'ABC'
313
- Minivan.create! id: 'OMG', speedometer_id: 'ABC'
446
+ Speedometer.create! id: "ABC"
447
+ Minivan.create! id: "OMG", speedometer_id: "ABC"
314
448
 
315
449
  c = Minivan.group(:speedometer).count(:all)
316
450
  first_key = c.keys.first
@@ -319,7 +453,7 @@ class CalculationsTest < ActiveRecord::TestCase
319
453
  end
320
454
 
321
455
  def test_should_calculate_grouped_association_with_foreign_key_option
322
- Account.belongs_to :another_firm, :class_name => 'Firm', :foreign_key => 'firm_id'
456
+ Account.belongs_to :another_firm, class_name: "Firm", foreign_key: "firm_id"
323
457
  c = Account.group(:another_firm).count(:all)
324
458
  assert_equal 1, c[companies(:first_firm)]
325
459
  assert_equal 2, c[companies(:rails_core)]
@@ -329,17 +463,17 @@ class CalculationsTest < ActiveRecord::TestCase
329
463
  def test_should_calculate_grouped_by_function
330
464
  c = Company.group("UPPER(#{QUOTED_TYPE})").count(:all)
331
465
  assert_equal 2, c[nil]
332
- assert_equal 1, c['DEPENDENTFIRM']
333
- assert_equal 5, c['CLIENT']
334
- assert_equal 2, c['FIRM']
466
+ assert_equal 1, c["DEPENDENTFIRM"]
467
+ assert_equal 5, c["CLIENT"]
468
+ assert_equal 3, c["FIRM"]
335
469
  end
336
470
 
337
471
  def test_should_calculate_grouped_by_function_with_table_alias
338
472
  c = Company.group("UPPER(companies.#{QUOTED_TYPE})").count(:all)
339
473
  assert_equal 2, c[nil]
340
- assert_equal 1, c['DEPENDENTFIRM']
341
- assert_equal 5, c['CLIENT']
342
- assert_equal 2, c['FIRM']
474
+ assert_equal 1, c["DEPENDENTFIRM"]
475
+ assert_equal 5, c["CLIENT"]
476
+ assert_equal 3, c["FIRM"]
343
477
  end
344
478
 
345
479
  def test_should_not_overshadow_enumerable_sum
@@ -355,34 +489,36 @@ class CalculationsTest < ActiveRecord::TestCase
355
489
  end
356
490
 
357
491
  def test_should_sum_scoped_field_with_conditions
358
- assert_equal 8, companies(:rails_core).companies.where('id > 7').sum(:id)
492
+ assert_equal 8, companies(:rails_core).companies.where("id > 7").sum(:id)
359
493
  end
360
494
 
361
495
  def test_should_group_by_scoped_field
362
496
  c = companies(:rails_core).companies.group(:name).sum(:id)
363
- assert_equal 7, c['Leetsoft']
364
- assert_equal 8, c['Jadedpixel']
497
+ assert_equal 7, c["Leetsoft"]
498
+ assert_equal 8, c["Jadedpixel"]
365
499
  end
366
500
 
367
501
  def test_should_group_by_summed_field_through_association_and_having
368
- c = companies(:rails_core).companies.group(:name).having('sum(id) > 7').sum(:id)
369
- assert_nil c['Leetsoft']
370
- assert_equal 8, c['Jadedpixel']
502
+ c = companies(:rails_core).companies.group(:name).having("sum(id) > 7").sum(:id)
503
+ assert_nil c["Leetsoft"]
504
+ assert_equal 8, c["Jadedpixel"]
371
505
  end
372
506
 
373
507
  def test_should_count_selected_field_with_include
374
508
  assert_equal 6, Account.includes(:firm).distinct.count
375
509
  assert_equal 4, Account.includes(:firm).distinct.select(:credit_limit).count
510
+ assert_equal 4, Account.includes(:firm).distinct.count("DISTINCT credit_limit")
511
+ assert_equal 4, Account.includes(:firm).distinct.count("DISTINCT(credit_limit)")
376
512
  end
377
513
 
378
514
  def test_should_not_perform_joined_include_by_default
379
515
  assert_equal Account.count, Account.includes(:firm).count
380
- queries = assert_sql { Account.includes(:firm).count }
516
+ queries = capture_sql { Account.includes(:firm).count }
381
517
  assert_no_match(/join/i, queries.last)
382
518
  end
383
519
 
384
520
  def test_should_perform_joined_include_when_referencing_included_tables
385
- joined_count = Account.includes(:firm).where(:companies => {:name => '37signals'}).count
521
+ joined_count = Account.includes(:firm).where(companies: { name: "37signals" }).count
386
522
  assert_equal 1, joined_count
387
523
  end
388
524
 
@@ -393,16 +529,34 @@ class CalculationsTest < ActiveRecord::TestCase
393
529
 
394
530
  def test_should_count_scoped_select_with_options
395
531
  Account.update_all("credit_limit = NULL")
396
- Account.last.update_columns('credit_limit' => 49)
397
- Account.first.update_columns('credit_limit' => 51)
532
+ Account.last.update_columns("credit_limit" => 49)
533
+ Account.first.update_columns("credit_limit" => 51)
398
534
 
399
- assert_equal 1, Account.select("credit_limit").where('credit_limit >= 50').count
535
+ assert_equal 1, Account.select("credit_limit").where("credit_limit >= 50").count
400
536
  end
401
537
 
402
538
  def test_should_count_manual_select_with_include
403
539
  assert_equal 6, Account.select("DISTINCT accounts.id").includes(:firm).count
404
540
  end
405
541
 
542
+ def test_should_count_manual_select_with_count_all
543
+ assert_equal 5, Account.select("DISTINCT accounts.firm_id").count(:all)
544
+ end
545
+
546
+ def test_should_count_with_manual_distinct_select_and_distinct
547
+ assert_equal 4, Account.select("DISTINCT accounts.firm_id").distinct(true).count
548
+ end
549
+
550
+ def test_should_count_manual_select_with_group_with_count_all
551
+ expected = { nil => 1, 1 => 1, 2 => 1, 6 => 2, 9 => 1 }
552
+ actual = Account.select("DISTINCT accounts.firm_id").group("accounts.firm_id").count(:all)
553
+ assert_equal expected, actual
554
+ end
555
+
556
+ def test_should_count_manual_with_count_all
557
+ assert_equal 6, Account.count(:all)
558
+ end
559
+
406
560
  def test_count_selected_arel_attribute
407
561
  assert_equal 5, Account.select(Account.arel_table[:firm_id]).count
408
562
  assert_equal 4, Account.distinct.select(Account.arel_table[:firm_id]).count
@@ -422,10 +576,6 @@ class CalculationsTest < ActiveRecord::TestCase
422
576
 
423
577
  def test_count_with_distinct
424
578
  assert_equal 4, Account.select(:credit_limit).distinct.count
425
-
426
- assert_deprecated do
427
- assert_equal 4, Account.select(:credit_limit).uniq.count
428
- end
429
579
  end
430
580
 
431
581
  def test_count_with_aliased_attribute
@@ -437,8 +587,8 @@ class CalculationsTest < ActiveRecord::TestCase
437
587
  end
438
588
 
439
589
  def test_should_count_field_in_joined_table
440
- assert_equal 5, Account.joins(:firm).count('companies.id')
441
- assert_equal 4, Account.joins(:firm).distinct.count('companies.id')
590
+ assert_equal 5, Account.joins(:firm).count("companies.id")
591
+ assert_equal 4, Account.joins(:firm).distinct.count("companies.id")
442
592
  end
443
593
 
444
594
  def test_count_arel_attribute_in_joined_table_with
@@ -452,14 +602,16 @@ class CalculationsTest < ActiveRecord::TestCase
452
602
  end
453
603
 
454
604
  def test_should_count_field_in_joined_table_with_group_by
455
- c = Account.group('accounts.firm_id').joins(:firm).count('companies.id')
605
+ c = Account.group("accounts.firm_id").joins(:firm).count("companies.id")
456
606
 
457
- [1,6,2,9].each { |firm_id| assert c.keys.include?(firm_id) }
607
+ [1, 6, 2, 9].each { |firm_id| assert_includes c.keys, firm_id }
458
608
  end
459
609
 
460
610
  def test_should_count_field_of_root_table_with_conflicting_group_by_column
461
- assert_equal({ 1 => 1 }, Firm.joins(:accounts).group(:firm_id).count)
462
- assert_equal({ 1 => 1 }, Firm.joins(:accounts).group('accounts.firm_id').count)
611
+ expected = { 1 => 2, 2 => 1, 4 => 5, 5 => 3, 7 => 1 }
612
+ assert_equal expected, Post.joins(:comments).group(:post_id).count
613
+ assert_equal expected, Post.joins(:comments).group("comments.post_id").count
614
+ assert_equal expected, Post.joins(:comments).group(:post_id).select("DISTINCT posts.author_id").count(:all)
463
615
  end
464
616
 
465
617
  def test_count_with_no_parameters_isnt_deprecated
@@ -479,84 +631,81 @@ class CalculationsTest < ActiveRecord::TestCase
479
631
  end
480
632
 
481
633
  def test_count_with_where_and_order
482
- assert_equal 1, Account.where(firm_name: '37signals').count
483
- assert_equal 1, Account.where(firm_name: '37signals').order(:firm_name).count
484
- assert_equal 1, Account.where(firm_name: '37signals').order(:firm_name).reverse_order.count
634
+ assert_equal 1, Account.where(firm_name: "37signals").count
635
+ assert_equal 1, Account.where(firm_name: "37signals").order(:firm_name).count
636
+ assert_equal 1, Account.where(firm_name: "37signals").order(:firm_name).reverse_order.count
637
+ end
638
+
639
+ def test_count_with_block
640
+ assert_equal 4, Account.count { |account| account.credit_limit.modulo(10).zero? }
485
641
  end
486
642
 
487
643
  def test_should_sum_expression
488
- # Oracle adapter returns floating point value 636.0 after SUM
489
- if current_adapter?(:OracleAdapter)
490
- assert_equal 636, Account.sum("2 * credit_limit")
491
- else
492
- assert_equal 636, Account.sum("2 * credit_limit").to_i
493
- end
644
+ assert_equal 636, Account.sum("2 * credit_limit")
494
645
  end
495
646
 
496
647
  def test_sum_expression_returns_zero_when_no_records_to_sum
497
- assert_equal 0, Account.where('1 = 2').sum("2 * credit_limit")
648
+ assert_equal 0, Account.where("1 = 2").sum("2 * credit_limit")
498
649
  end
499
650
 
500
651
  def test_count_with_from_option
501
- assert_equal Company.count(:all), Company.from('companies').count(:all)
652
+ assert_equal Company.count(:all), Company.from("companies").count(:all)
502
653
  assert_equal Account.where("credit_limit = 50").count(:all),
503
- Account.from('accounts').where("credit_limit = 50").count(:all)
504
- assert_equal Company.where(:type => "Firm").count(:type),
505
- Company.where(:type => "Firm").from('companies').count(:type)
654
+ Account.from("accounts").where("credit_limit = 50").count(:all)
655
+ assert_equal Company.where(type: "Firm").count(:type),
656
+ Company.where(type: "Firm").from("companies").count(:type)
506
657
  end
507
658
 
508
659
  def test_sum_with_from_option
509
- assert_equal Account.sum(:credit_limit), Account.from('accounts').sum(:credit_limit)
660
+ assert_equal Account.sum(:credit_limit), Account.from("accounts").sum(:credit_limit)
510
661
  assert_equal Account.where("credit_limit > 50").sum(:credit_limit),
511
- Account.where("credit_limit > 50").from('accounts').sum(:credit_limit)
662
+ Account.where("credit_limit > 50").from("accounts").sum(:credit_limit)
512
663
  end
513
664
 
514
665
  def test_average_with_from_option
515
- assert_equal Account.average(:credit_limit), Account.from('accounts').average(:credit_limit)
666
+ assert_equal Account.average(:credit_limit), Account.from("accounts").average(:credit_limit)
516
667
  assert_equal Account.where("credit_limit > 50").average(:credit_limit),
517
- Account.where("credit_limit > 50").from('accounts').average(:credit_limit)
668
+ Account.where("credit_limit > 50").from("accounts").average(:credit_limit)
518
669
  end
519
670
 
520
671
  def test_minimum_with_from_option
521
- assert_equal Account.minimum(:credit_limit), Account.from('accounts').minimum(:credit_limit)
672
+ assert_equal Account.minimum(:credit_limit), Account.from("accounts").minimum(:credit_limit)
522
673
  assert_equal Account.where("credit_limit > 50").minimum(:credit_limit),
523
- Account.where("credit_limit > 50").from('accounts').minimum(:credit_limit)
674
+ Account.where("credit_limit > 50").from("accounts").minimum(:credit_limit)
524
675
  end
525
676
 
526
677
  def test_maximum_with_from_option
527
- assert_equal Account.maximum(:credit_limit), Account.from('accounts').maximum(:credit_limit)
678
+ assert_equal Account.maximum(:credit_limit), Account.from("accounts").maximum(:credit_limit)
528
679
  assert_equal Account.where("credit_limit > 50").maximum(:credit_limit),
529
- Account.where("credit_limit > 50").from('accounts').maximum(:credit_limit)
680
+ Account.where("credit_limit > 50").from("accounts").maximum(:credit_limit)
530
681
  end
531
682
 
532
683
  def test_maximum_with_not_auto_table_name_prefix_if_column_included
533
- Company.create!(:name => "test", :contracts => [Contract.new(:developer_id => 7)])
684
+ Company.create!(name: "test", contracts: [Contract.new(developer_id: 7)])
534
685
 
535
686
  assert_equal 7, Company.includes(:contracts).maximum(:developer_id)
536
687
  end
537
688
 
538
689
  def test_minimum_with_not_auto_table_name_prefix_if_column_included
539
- Company.create!(:name => "test", :contracts => [Contract.new(:developer_id => 7)])
690
+ Company.create!(name: "test", contracts: [Contract.new(developer_id: 7)])
540
691
 
541
692
  assert_equal 7, Company.includes(:contracts).minimum(:developer_id)
542
693
  end
543
694
 
544
695
  def test_sum_with_not_auto_table_name_prefix_if_column_included
545
- Company.create!(:name => "test", :contracts => [Contract.new(:developer_id => 7)])
696
+ Company.create!(name: "test", contracts: [Contract.new(developer_id: 7)])
546
697
 
547
698
  assert_equal 7, Company.includes(:contracts).sum(:developer_id)
548
699
  end
549
700
 
550
- if current_adapter?(:Mysql2Adapter)
551
- def test_from_option_with_specified_index
552
- assert_equal Edge.count(:all), Edge.from('edges USE INDEX(unique_edge_index)').count(:all)
553
- assert_equal Edge.where('sink_id < 5').count(:all),
554
- Edge.from('edges USE INDEX(unique_edge_index)').where('sink_id < 5').count(:all)
555
- end
701
+ def test_from_option_with_specified_index
702
+ edges = Edge.from("edges /*! USE INDEX(unique_edge_index) */")
703
+ assert_equal Edge.count(:all), edges.count(:all)
704
+ assert_equal Edge.where("sink_id < 5").count(:all), edges.where("sink_id < 5").count(:all)
556
705
  end
557
706
 
558
707
  def test_from_option_with_table_different_than_class
559
- assert_equal Account.count(:all), Company.from('accounts').count(:all)
708
+ assert_equal Account.count(:all), Company.from("accounts").count(:all)
560
709
  end
561
710
 
562
711
  def test_distinct_is_honored_when_used_with_count_operation_after_group
@@ -569,22 +718,82 @@ class CalculationsTest < ActiveRecord::TestCase
569
718
  end
570
719
 
571
720
  def test_pluck
572
- assert_equal [1,2,3,4,5], Topic.order(:id).pluck(:id)
721
+ assert_equal [1, 2, 3, 4, 5], Topic.order(:id).pluck(:id)
722
+ end
723
+
724
+ def test_pluck_with_empty_in
725
+ assert_queries(0) do
726
+ assert_equal [], Topic.where(id: []).pluck(:id)
727
+ end
573
728
  end
574
729
 
575
730
  def test_pluck_without_column_names
576
- assert_equal [[1, "Firm", 1, nil, "37signals", nil, 1, nil, ""]],
577
- Company.order(:id).limit(1).pluck
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
578
736
  end
579
737
 
580
738
  def test_pluck_type_cast
581
739
  topic = topics(:first)
582
- relation = Topic.where(:id => topic.id)
740
+ relation = Topic.where(id: topic.id)
583
741
  assert_equal [ topic.approved ], relation.pluck(:approved)
584
742
  assert_equal [ topic.last_read ], relation.pluck(:last_read)
585
743
  assert_equal [ topic.written_on ], relation.pluck(:written_on)
586
744
  end
587
745
 
746
+ def test_pluck_type_cast_with_conflict_column_names
747
+ expected = [
748
+ [Date.new(2004, 4, 15), "unread"],
749
+ [Date.new(2004, 4, 15), "reading"],
750
+ [Date.new(2004, 4, 15), "read"],
751
+ ]
752
+ actual = AuthorAddress.joins(author: [:topics, :books]).order(:"books.last_read")
753
+ .where("books.last_read": [:unread, :reading, :read])
754
+ .pluck(:"topics.last_read", :"books.last_read")
755
+
756
+ assert_equal expected, actual
757
+ end
758
+
759
+ def test_pluck_type_cast_with_joins_without_table_name_qualified_column
760
+ assert_pluck_type_cast_without_table_name_qualified_column(AuthorAddress.joins(author: :books))
761
+ end
762
+
763
+ def test_pluck_type_cast_with_left_joins_without_table_name_qualified_column
764
+ assert_pluck_type_cast_without_table_name_qualified_column(AuthorAddress.left_joins(author: :books))
765
+ end
766
+
767
+ def test_pluck_type_cast_with_eager_load_without_table_name_qualified_column
768
+ assert_pluck_type_cast_without_table_name_qualified_column(AuthorAddress.eager_load(author: :books))
769
+ end
770
+
771
+ def assert_pluck_type_cast_without_table_name_qualified_column(author_addresses)
772
+ expected = [
773
+ [nil, "unread"],
774
+ ["ebook", "reading"],
775
+ ["paperback", "read"],
776
+ ]
777
+ actual = author_addresses.order(:last_read)
778
+ .where("books.last_read": [:unread, :reading, :read])
779
+ .pluck(:format, :last_read)
780
+
781
+ assert_equal expected, actual
782
+ end
783
+ private :assert_pluck_type_cast_without_table_name_qualified_column
784
+
785
+ def test_pluck_with_type_cast_does_not_corrupt_the_query_cache
786
+ topic = topics(:first)
787
+ relation = Topic.where(id: topic.id)
788
+ assert_queries 1 do
789
+ Topic.cache do
790
+ kind = relation.select(:written_on).load.first.read_attribute_before_type_cast(:written_on).class
791
+ relation.pluck(:written_on)
792
+ assert_kind_of kind, relation.select(:written_on).load.first.read_attribute_before_type_cast(:written_on)
793
+ end
794
+ end
795
+ end
796
+
588
797
  def test_pluck_and_distinct
589
798
  assert_equal [50, 53, 55, 60], Account.order(:credit_limit).distinct.pluck(:credit_limit)
590
799
  end
@@ -596,42 +805,39 @@ class CalculationsTest < ActiveRecord::TestCase
596
805
  end
597
806
 
598
807
  def test_pluck_on_aliased_attribute
599
- assert_equal 'The First Topic', Topic.order(:id).pluck(:heading).first
808
+ assert_equal "The First Topic", Topic.order(:id).pluck(:heading).first
600
809
  end
601
810
 
602
811
  def test_pluck_with_serialization
603
- t = Topic.create!(:content => { :foo => :bar })
604
- assert_equal [{:foo => :bar}], Topic.where(:id => t.id).pluck(:content)
812
+ t = Topic.create!(content: { foo: :bar })
813
+ assert_equal [{ foo: :bar }], Topic.where(id: t.id).pluck(:content)
605
814
  end
606
815
 
607
816
  def test_pluck_with_qualified_column_name
608
- assert_equal [1,2,3,4,5], Topic.order(:id).pluck("topics.id")
817
+ assert_equal [1, 2, 3, 4, 5], Topic.order(:id).pluck("topics.id")
609
818
  end
610
819
 
611
820
  def test_pluck_auto_table_name_prefix
612
- c = Company.create!(:name => "test", :contracts => [Contract.new])
821
+ c = Company.create!(name: "test", contracts: [Contract.new])
613
822
  assert_equal [c.id], Company.joins(:contracts).pluck(:id)
614
823
  end
615
824
 
616
825
  def test_pluck_if_table_included
617
- c = Company.create!(:name => "test", :contracts => [Contract.new(:developer_id => 7)])
826
+ c = Company.create!(name: "test", contracts: [Contract.new(developer_id: 7)])
618
827
  assert_equal [c.id], Company.includes(:contracts).where("contracts.id" => c.contracts.first).pluck(:id)
619
828
  end
620
829
 
621
830
  def test_pluck_not_auto_table_name_prefix_if_column_joined
622
- Company.create!(:name => "test", :contracts => [Contract.new(:developer_id => 7)])
623
- assert_equal [7], Company.joins(:contracts).pluck(:developer_id)
831
+ company = Company.create!(name: "test", contracts: [Contract.new(developer_id: 7)])
832
+ metadata = company.contracts.first.metadata
833
+ assert_equal [metadata], Company.joins(:contracts).pluck(:metadata)
624
834
  end
625
835
 
626
836
  def test_pluck_with_selection_clause
627
- assert_equal [50, 53, 55, 60], Account.pluck('DISTINCT credit_limit').sort
628
- assert_equal [50, 53, 55, 60], Account.pluck('DISTINCT accounts.credit_limit').sort
629
- assert_equal [50, 53, 55, 60], Account.pluck('DISTINCT(credit_limit)').sort
630
-
631
- # MySQL returns "SUM(DISTINCT(credit_limit))" as the column name unless
632
- # an alias is provided. Without the alias, the column cannot be found
633
- # and properly typecast.
634
- assert_equal [50 + 53 + 55 + 60], Account.pluck('SUM(DISTINCT(credit_limit)) as credit_limit')
837
+ assert_equal [50, 53, 55, 60], Account.pluck(Arel.sql("DISTINCT credit_limit")).sort
838
+ assert_equal [50, 53, 55, 60], Account.pluck(Arel.sql("DISTINCT accounts.credit_limit")).sort
839
+ assert_equal [50, 53, 55, 60], Account.pluck(Arel.sql("DISTINCT(credit_limit)")).sort
840
+ assert_equal [50 + 53 + 55 + 60], Account.pluck(Arel.sql("SUM(DISTINCT(credit_limit))"))
635
841
  end
636
842
 
637
843
  def test_plucks_with_ids
@@ -640,11 +846,51 @@ class CalculationsTest < ActiveRecord::TestCase
640
846
 
641
847
  def test_pluck_with_includes_limit_and_empty_result
642
848
  assert_equal [], Topic.includes(:replies).limit(0).pluck(:id)
643
- assert_equal [], Topic.includes(:replies).limit(1).where('0 = 1').pluck(:id)
849
+ assert_equal [], Topic.includes(:replies).limit(1).where("0 = 1").pluck(:id)
850
+ end
851
+
852
+ def test_pluck_with_includes_offset
853
+ assert_equal [5], Topic.includes(:replies).order(:id).offset(4).pluck(:id)
854
+ assert_equal [], Topic.includes(:replies).order(:id).offset(5).pluck(:id)
855
+ end
856
+
857
+ def test_pluck_with_join
858
+ assert_equal [[2, 2], [4, 4]], Reply.includes(:topic).order(:id).pluck(:id, :"topics.id")
859
+ end
860
+
861
+ def test_group_by_with_order_by_virtual_count_attribute
862
+ expected = { "SpecialPost" => 1, "StiPost" => 2 }
863
+ actual = Post.group(:type).order(:count).limit(2).maximum(:comments_count)
864
+ assert_equal expected, actual
865
+ end if current_adapter?(:PostgreSQLAdapter)
866
+
867
+ def test_group_by_with_limit
868
+ expected = { "StiPost" => 3, "SpecialPost" => 1 }
869
+ actual = Post.includes(:comments).group(:type).order(type: :desc).limit(2).count("comments.id")
870
+ assert_equal expected, actual
871
+ end
872
+
873
+ def test_group_by_with_offset
874
+ expected = { "SpecialPost" => 1, "Post" => 8 }
875
+ actual = Post.includes(:comments).group(:type).order(type: :desc).offset(1).count("comments.id")
876
+ assert_equal expected, actual
877
+ end
878
+
879
+ def test_group_by_with_limit_and_offset
880
+ expected = { "SpecialPost" => 1 }
881
+ actual = Post.includes(:comments).group(:type).order(type: :desc).offset(1).limit(1).count("comments.id")
882
+ assert_equal expected, actual
883
+ end
884
+
885
+ def test_group_by_with_quoted_count_and_order_by_alias
886
+ quoted_posts_id = Post.connection.quote_table_name("posts.id")
887
+ expected = { "SpecialPost" => 1, "StiPost" => 1, "Post" => 9 }
888
+ actual = Post.group(:type).order("count_posts_id").count(quoted_posts_id)
889
+ assert_equal expected, actual
644
890
  end
645
891
 
646
892
  def test_pluck_not_auto_table_name_prefix_if_column_included
647
- Company.create!(:name => "test", :contracts => [Contract.new(:developer_id => 7)])
893
+ Company.create!(name: "test", contracts: [Contract.new(developer_id: 7)])
648
894
  ids = Company.includes(:contracts).pluck(:developer_id)
649
895
  assert_equal Company.count, ids.length
650
896
  assert_equal [7], ids.compact
@@ -665,12 +911,12 @@ class CalculationsTest < ActiveRecord::TestCase
665
911
 
666
912
  def test_pluck_with_multiple_columns_and_selection_clause
667
913
  assert_equal [[1, 50], [2, 50], [3, 50], [4, 60], [5, 55], [6, 53]],
668
- Account.pluck('id, credit_limit')
914
+ Account.order(:id).pluck("id, credit_limit")
669
915
  end
670
916
 
671
917
  def test_pluck_with_multiple_columns_and_includes
672
- Company.create!(:name => "test", :contracts => [Contract.new(:developer_id => 7)])
673
- companies_and_developers = Company.order('companies.id').includes(:contracts).pluck(:name, :developer_id)
918
+ Company.create!(name: "test", contracts: [Contract.new(developer_id: 7)])
919
+ companies_and_developers = Company.order("companies.id").includes(:contracts).pluck(:name, :developer_id)
674
920
 
675
921
  assert_equal Company.count, companies_and_developers.length
676
922
  assert_equal ["37signals", nil], companies_and_developers.first
@@ -678,24 +924,46 @@ class CalculationsTest < ActiveRecord::TestCase
678
924
  end
679
925
 
680
926
  def test_pluck_with_reserved_words
681
- Possession.create!(:where => "Over There")
927
+ Possession.create!(where: "Over There")
682
928
 
683
929
  assert_equal ["Over There"], Possession.pluck(:where)
684
930
  end
685
931
 
686
932
  def test_pluck_replaces_select_clause
687
933
  taks_relation = Topic.select(:approved, :id).order(:id)
688
- assert_equal [1,2,3,4,5], taks_relation.pluck(:id)
934
+ assert_equal [1, 2, 3, 4, 5], taks_relation.pluck(:id)
689
935
  assert_equal [false, true, true, true, true], taks_relation.pluck(:approved)
690
936
  end
691
937
 
692
938
  def test_pluck_columns_with_same_name
693
939
  expected = [["The First Topic", "The Second Topic of the day"], ["The Third Topic of the day", "The Fourth Topic of the day"]]
694
- actual = Topic.joins(:replies)
695
- .pluck('topics.title', 'replies_topics.title')
940
+ actual = Topic.joins(:replies).order(:id)
941
+ .pluck("topics.title", "replies_topics.title")
696
942
  assert_equal expected, actual
697
943
  end
698
944
 
945
+ def test_pluck_functions_with_alias
946
+ assert_equal [
947
+ [1, "The First Topic"], [2, "The Second Topic of the day"],
948
+ [3, "The Third Topic of the day"], [4, "The Fourth Topic of the day"],
949
+ [5, "The Fifth Topic of the day"]
950
+ ], Topic.order(:id).pluck(
951
+ Arel.sql("COALESCE(id, 0) id"),
952
+ Arel.sql("COALESCE(title, 'untitled') title")
953
+ )
954
+ end
955
+
956
+ 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"],
960
+ [5, "The Fifth Topic of the day"]
961
+ ], Topic.order(:id).pluck(
962
+ Arel.sql("COALESCE(id, 0)"),
963
+ Arel.sql("COALESCE(title, 'untitled')")
964
+ )
965
+ end
966
+
699
967
  def test_calculation_with_polymorphic_relation
700
968
  part = ShipPart.create!(name: "has trinket")
701
969
  part.trinkets.create!
@@ -712,22 +980,86 @@ class CalculationsTest < ActiveRecord::TestCase
712
980
 
713
981
  def test_pluck_loaded_relation
714
982
  companies = Company.order(:id).limit(3).load
715
- assert_no_queries do
716
- assert_equal ['37signals', 'Summit', 'Microsoft'], companies.pluck(:name)
983
+
984
+ assert_queries(0) do
985
+ assert_equal ["37signals", "Summit", "Microsoft"], companies.pluck(:name)
717
986
  end
718
987
  end
719
988
 
720
989
  def test_pluck_loaded_relation_multiple_columns
721
990
  companies = Company.order(:id).limit(3).load
722
- assert_no_queries do
723
- assert_equal [[1, '37signals'], [2, 'Summit'], [3, 'Microsoft']], companies.pluck(:id, :name)
991
+
992
+ assert_queries(0) do
993
+ assert_equal [[1, "37signals"], [2, "Summit"], [3, "Microsoft"]], companies.pluck(:id, :name)
724
994
  end
725
995
  end
726
996
 
727
997
  def test_pluck_loaded_relation_sql_fragment
728
998
  companies = Company.order(:name).limit(3).load
999
+
1000
+ assert_queries(1) do
1001
+ assert_equal ["37signals", "Apex", "Ex Nihilo"], companies.pluck(Arel.sql("DISTINCT name"))
1002
+ end
1003
+ end
1004
+
1005
+ def test_pluck_loaded_relation_aliased_attribute
1006
+ companies = Company.order(:id).limit(3).load
1007
+
1008
+ assert_queries(0) do
1009
+ assert_equal ["37signals", "Summit", "Microsoft"], companies.pluck(:new_name)
1010
+ end
1011
+ end
1012
+
1013
+ def test_pick_one
1014
+ assert_equal "The First Topic", Topic.order(:id).pick(:heading)
1015
+ assert_no_queries do
1016
+ assert_nil Topic.none.pick(:heading)
1017
+ assert_nil Topic.where(id: 9999999999999999999).pick(:heading)
1018
+ end
1019
+ end
1020
+
1021
+ def test_pick_two
1022
+ assert_equal ["David", "david@loudthinking.com"], Topic.order(:id).pick(:author_name, :author_email_address)
1023
+ assert_no_queries do
1024
+ assert_nil Topic.none.pick(:author_name, :author_email_address)
1025
+ assert_nil Topic.where(id: 9999999999999999999).pick(:author_name, :author_email_address)
1026
+ end
1027
+ end
1028
+
1029
+ def test_pick_delegate_to_all
1030
+ cool_first = minivans(:cool_first)
1031
+ assert_equal cool_first.color, Minivan.pick(:color)
1032
+ end
1033
+
1034
+ def test_pick_loaded_relation
1035
+ companies = Company.order(:id).limit(3).load
1036
+
1037
+ assert_no_queries do
1038
+ assert_equal "37signals", companies.pick(:name)
1039
+ end
1040
+ end
1041
+
1042
+ def test_pick_loaded_relation_multiple_columns
1043
+ companies = Company.order(:id).limit(3).load
1044
+
1045
+ assert_no_queries do
1046
+ assert_equal [1, "37signals"], companies.pick(:id, :name)
1047
+ end
1048
+ end
1049
+
1050
+ def test_pick_loaded_relation_sql_fragment
1051
+ companies = Company.order(:name).limit(3).load
1052
+
729
1053
  assert_queries 1 do
730
- assert_equal ['37signals', 'Apex', 'Ex Nihilo'], companies.pluck('DISTINCT name')
1054
+ assert_equal "37signals", companies.pick(Arel.sql("DISTINCT name"))
1055
+ end
1056
+ end
1057
+
1058
+ def test_pick_loaded_relation_aliased_attribute
1059
+ companies = Company.order(:id).limit(3).load
1060
+
1061
+ assert_no_queries do
1062
+ assert_equal "37signals", companies.pick(:new_name)
731
1063
  end
732
1064
  end
733
1065
 
@@ -745,7 +1077,7 @@ class CalculationsTest < ActiveRecord::TestCase
745
1077
 
746
1078
  def test_should_reference_correct_aliases_while_joining_tables_of_has_many_through_association
747
1079
  assert_nothing_raised do
748
- developer = Developer.create!(name: 'developer')
1080
+ developer = Developer.create!(name: "developer")
749
1081
  developer.ratings.includes(comment: :post).where(posts: { id: 1 }).count
750
1082
  end
751
1083
  end
@@ -761,38 +1093,269 @@ class CalculationsTest < ActiveRecord::TestCase
761
1093
  end
762
1094
 
763
1095
  def test_having_with_strong_parameters
764
- protected_params = Class.new do
765
- attr_reader :permitted
766
- alias :permitted? :permitted
767
-
768
- def initialize(parameters)
769
- @parameters = parameters
770
- @permitted = false
771
- end
772
-
773
- def to_h
774
- @parameters
775
- end
776
-
777
- def permit!
778
- @permitted = true
779
- self
780
- end
781
- end
782
-
783
- params = protected_params.new(credit_limit: '50')
1096
+ params = ProtectedParams.new(credit_limit: "50")
784
1097
 
785
1098
  assert_raises(ActiveModel::ForbiddenAttributesError) do
786
1099
  Account.group(:id).having(params)
787
1100
  end
788
1101
 
789
- result = Account.group(:id).having(params.permit!)
1102
+ result = Account.group(:id, :firm_id, :firm_name, :credit_limit, :AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA).having(params.permit!)
790
1103
  assert_equal 50, result[0].credit_limit
791
1104
  assert_equal 50, result[1].credit_limit
792
1105
  assert_equal 50, result[2].credit_limit
793
1106
  end
794
1107
 
1108
+ def test_count_takes_attribute_type_precedence_over_database_type
1109
+ assert_called(
1110
+ Account.connection, :select_all,
1111
+ returns: ActiveRecord::Result.new(["count"], [["10"]])
1112
+ ) do
1113
+ result = Account.count
1114
+ assert_equal 10, result
1115
+ assert_instance_of Integer, result
1116
+ end
1117
+ end
1118
+
1119
+ def test_sum_takes_attribute_type_precedence_over_database_type
1120
+ assert_called(
1121
+ Account.connection, :select_all,
1122
+ returns: ActiveRecord::Result.new(["sum"], [[10.to_d]])
1123
+ ) do
1124
+ result = Account.sum(:credit_limit)
1125
+ assert_equal 10, result
1126
+ assert_instance_of Integer, result
1127
+ end
1128
+ end
1129
+
795
1130
  def test_group_by_attribute_with_custom_type
796
1131
  assert_equal({ "proposed" => 2, "published" => 2 }, Book.group(:status).count)
797
1132
  end
1133
+
1134
+ def test_aggregate_attribute_on_enum_type
1135
+ assert_equal 4, Book.sum(:status)
1136
+ assert_equal 1, Book.sum(:difficulty)
1137
+ assert_equal 0, Book.minimum(:difficulty)
1138
+ assert_equal 1, Book.maximum(:difficulty)
1139
+ assert_equal({ "proposed" => 0, "published" => 4 }, Book.group(:status).sum(:status))
1140
+ assert_equal({ "proposed" => 0, "published" => 1 }, Book.group(:status).sum(:difficulty))
1141
+ assert_equal({ "proposed" => 0, "published" => 0 }, Book.group(:status).minimum(:difficulty))
1142
+ assert_equal({ "proposed" => 0, "published" => 1 }, Book.group(:status).maximum(:difficulty))
1143
+ end
1144
+
1145
+ def test_minimum_and_maximum_on_non_numeric_type
1146
+ assert_equal Date.new(2004, 4, 15), Topic.minimum(:last_read)
1147
+ assert_equal Date.new(2004, 4, 15), Topic.maximum(:last_read)
1148
+ assert_equal({ false => Date.new(2004, 4, 15), true => nil }, Topic.group(:approved).minimum(:last_read))
1149
+ assert_equal({ false => Date.new(2004, 4, 15), true => nil }, Topic.group(:approved).maximum(:last_read))
1150
+ end
1151
+
1152
+ def test_minimum_and_maximum_on_time_attributes
1153
+ assert_minimum_and_maximum_on_time_attributes(Time)
1154
+ end
1155
+
1156
+ def test_minimum_and_maximum_on_tz_aware_attributes
1157
+ with_timezone_config aware_attributes: true, zone: "Pacific Time (US & Canada)" do
1158
+ Topic.reset_column_information
1159
+ assert_minimum_and_maximum_on_time_attributes(ActiveSupport::TimeWithZone)
1160
+ end
1161
+ ensure
1162
+ Topic.reset_column_information
1163
+ end
1164
+
1165
+ def assert_minimum_and_maximum_on_time_attributes(time_class)
1166
+ actual = Topic.minimum(:written_on)
1167
+ assert_equal Time.utc(2003, 7, 16, 14, 28, 11, 223300), actual
1168
+ assert_instance_of time_class, actual
1169
+
1170
+ actual = Topic.maximum(:written_on)
1171
+ assert_equal Time.utc(2013, 7, 13, 11, 11, 0, 9900), actual
1172
+ assert_instance_of time_class, actual
1173
+
1174
+ expected = {
1175
+ false => Time.utc(2003, 7, 16, 14, 28, 11, 223300),
1176
+ true => Time.utc(2004, 7, 15, 14, 28, 0, 9900),
1177
+ }
1178
+ actual = Topic.group(:approved).minimum(:written_on)
1179
+ assert_equal expected, actual
1180
+ assert_instance_of time_class, actual[true]
1181
+ assert_instance_of time_class, actual[true]
1182
+
1183
+ expected = {
1184
+ false => Time.utc(2003, 7, 16, 14, 28, 11, 223300),
1185
+ true => Time.utc(2013, 7, 13, 11, 11, 0, 9900),
1186
+ }
1187
+ actual = Topic.group(:approved).maximum(:written_on)
1188
+ assert_equal expected, actual
1189
+ assert_instance_of time_class, actual[true]
1190
+ assert_instance_of time_class, actual[true]
1191
+
1192
+ assert_minimum_and_maximum_on_time_attributes_joins_with_column(time_class, :"topics.written_on")
1193
+ assert_minimum_and_maximum_on_time_attributes_joins_with_column(time_class, :written_on)
1194
+ end
1195
+ private :assert_minimum_and_maximum_on_time_attributes
1196
+
1197
+ def assert_minimum_and_maximum_on_time_attributes_joins_with_column(time_class, column)
1198
+ actual = Author.joins(:topics).maximum(column)
1199
+ assert_equal Time.utc(2004, 7, 15, 14, 28, 0, 9900), actual
1200
+ assert_instance_of time_class, actual
1201
+
1202
+ actual = Author.joins(:topics).minimum(column)
1203
+ assert_equal Time.utc(2003, 7, 16, 14, 28, 11, 223300), actual
1204
+ assert_instance_of time_class, actual
1205
+
1206
+ expected = {
1207
+ 1 => Time.utc(2003, 7, 16, 14, 28, 11, 223300),
1208
+ 2 => Time.utc(2004, 7, 15, 14, 28, 0, 9900),
1209
+ }
1210
+
1211
+ actual = Author.joins(:topics).group(:id).maximum(column)
1212
+ assert_equal expected, actual
1213
+ assert_instance_of time_class, actual[1]
1214
+ assert_instance_of time_class, actual[2]
1215
+
1216
+ actual = Author.joins(:topics).group(:id).minimum(column)
1217
+ assert_equal expected, actual
1218
+ assert_instance_of time_class, actual[1]
1219
+ assert_instance_of time_class, actual[2]
1220
+ end
1221
+ private :assert_minimum_and_maximum_on_time_attributes_joins_with_column
1222
+
1223
+ def test_select_avg_with_group_by_as_virtual_attribute_with_sql
1224
+ rails_core = companies(:rails_core)
1225
+
1226
+ sql = <<~SQL
1227
+ SELECT firm_id, AVG(credit_limit) AS avg_credit_limit
1228
+ FROM accounts
1229
+ WHERE firm_id = ?
1230
+ GROUP BY firm_id
1231
+ LIMIT 1
1232
+ SQL
1233
+
1234
+ account = Account.find_by_sql([sql, rails_core]).first
1235
+
1236
+ # id was not selected, so it should be nil
1237
+ # (cannot select id because it wasn't used in the GROUP BY clause)
1238
+ assert_nil account.id
1239
+
1240
+ # firm_id was explicitly selected, so it should be present
1241
+ assert_equal(rails_core, account.firm)
1242
+
1243
+ # avg_credit_limit should be present as a virtual attribute
1244
+ assert_equal(52.5, account.avg_credit_limit)
1245
+ end
1246
+
1247
+ def test_select_avg_with_group_by_as_virtual_attribute_with_ar
1248
+ rails_core = companies(:rails_core)
1249
+
1250
+ account = Account
1251
+ .select(:firm_id, "AVG(credit_limit) AS avg_credit_limit")
1252
+ .where(firm: rails_core)
1253
+ .group(:firm_id)
1254
+ .take!
1255
+
1256
+ # id was not selected, so it should be nil
1257
+ # (cannot select id because it wasn't used in the GROUP BY clause)
1258
+ assert_nil account.id
1259
+
1260
+ # firm_id was explicitly selected, so it should be present
1261
+ assert_equal(rails_core, account.firm)
1262
+
1263
+ # avg_credit_limit should be present as a virtual attribute
1264
+ assert_equal(52.5, account.avg_credit_limit)
1265
+ end
1266
+
1267
+ def test_select_avg_with_joins_and_group_by_as_virtual_attribute_with_sql
1268
+ rails_core = companies(:rails_core)
1269
+
1270
+ sql = <<~SQL
1271
+ SELECT companies.*, AVG(accounts.credit_limit) AS avg_credit_limit
1272
+ FROM companies
1273
+ INNER JOIN accounts ON companies.id = accounts.firm_id
1274
+ WHERE companies.id = ?
1275
+ 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
1277
+ LIMIT 1
1278
+ SQL
1279
+
1280
+ firm = DependentFirm.find_by_sql([sql, rails_core]).first
1281
+
1282
+ # all the DependentFirm attributes should be present
1283
+ assert_equal rails_core, firm
1284
+ assert_equal rails_core.name, firm.name
1285
+
1286
+ # avg_credit_limit should be present as a virtual attribute
1287
+ assert_equal(52.5, firm.avg_credit_limit)
1288
+ end
1289
+
1290
+ def test_select_avg_with_joins_and_group_by_as_virtual_attribute_with_ar
1291
+ rails_core = companies(:rails_core)
1292
+
1293
+ firm = DependentFirm
1294
+ .select("companies.*", "AVG(accounts.credit_limit) AS avg_credit_limit")
1295
+ .where(id: rails_core)
1296
+ .joins(:account)
1297
+ .group(:id, :type, :firm_id, :firm_name, :name, :client_of, :rating, :account_id, :description)
1298
+ .take!
1299
+
1300
+ # all the DependentFirm attributes should be present
1301
+ assert_equal rails_core, firm
1302
+ assert_equal rails_core.name, firm.name
1303
+
1304
+ # avg_credit_limit should be present as a virtual attribute
1305
+ assert_equal(52.5, firm.avg_credit_limit)
1306
+ end
1307
+
1308
+ def test_count_with_block_and_column_name_raises_an_error
1309
+ assert_raises(ArgumentError) do
1310
+ Account.count(:firm_id) { true }
1311
+ end
1312
+ end
1313
+
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
+ test "#skip_query_cache! for #pluck" do
1321
+ Account.cache do
1322
+ assert_queries(1) do
1323
+ Account.pluck(:credit_limit)
1324
+ Account.pluck(:credit_limit)
1325
+ end
1326
+
1327
+ assert_queries(2) do
1328
+ Account.all.skip_query_cache!.pluck(:credit_limit)
1329
+ Account.all.skip_query_cache!.pluck(:credit_limit)
1330
+ end
1331
+ end
1332
+ end
1333
+
1334
+ test "#skip_query_cache! for a simple calculation" do
1335
+ Account.cache do
1336
+ assert_queries(1) do
1337
+ Account.calculate(:sum, :credit_limit)
1338
+ Account.calculate(:sum, :credit_limit)
1339
+ end
1340
+
1341
+ assert_queries(2) do
1342
+ Account.all.skip_query_cache!.calculate(:sum, :credit_limit)
1343
+ Account.all.skip_query_cache!.calculate(:sum, :credit_limit)
1344
+ end
1345
+ end
1346
+ end
1347
+
1348
+ test "#skip_query_cache! for a grouped calculation" do
1349
+ Account.cache do
1350
+ assert_queries(1) do
1351
+ Account.group(:firm_id).calculate(:sum, :credit_limit)
1352
+ Account.group(:firm_id).calculate(:sum, :credit_limit)
1353
+ end
1354
+
1355
+ assert_queries(2) do
1356
+ Account.all.skip_query_cache!.group(:firm_id).calculate(:sum, :credit_limit)
1357
+ Account.all.skip_query_cache!.group(:firm_id).calculate(:sum, :credit_limit)
1358
+ end
1359
+ end
1360
+ end
798
1361
  end