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

Sign up to get free protection for your applications and to get access to all the features.
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