ibm_db 3.0.0-x86-mingw32 → 3.0.1-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 (465) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +4 -0
  3. data/MANIFEST +14 -14
  4. data/README +225 -225
  5. data/ext/Makefile.nt32 +181 -181
  6. data/ext/Makefile.nt32.191 +212 -212
  7. data/ext/OLD/extconf.rb +264 -0
  8. data/ext/{extconf_MacOS.rb → OLD/extconf_MacOS.rb} +269 -269
  9. data/ext/extconf.rb +291 -264
  10. data/ext/ibm_db.c +2 -2
  11. data/ext/ruby_ibm_db.h +241 -241
  12. data/ext/ruby_ibm_db_cli.h +500 -500
  13. data/init.rb +41 -41
  14. data/lib/IBM_DB.rb +27 -27
  15. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +4 -4
  16. data/lib/active_record/connection_adapters/ibmdb_adapter.rb +1 -1
  17. data/lib/active_record/vendor/db2-i5-zOS.yaml +328 -328
  18. data/lib/mswin32/ibm_db.rb +115 -115
  19. data/test/active_record/connection_adapters/fake_adapter.rb +46 -0
  20. data/test/assets/example.log +1 -0
  21. data/test/assets/flowers.jpg +0 -0
  22. data/test/assets/test.txt +1 -0
  23. data/test/cases/adapter_test.rb +261 -207
  24. data/test/cases/aggregations_test.rb +158 -0
  25. data/test/cases/ar_schema_test.rb +161 -0
  26. data/test/cases/associations/association_scope_test.rb +21 -0
  27. data/test/cases/associations/belongs_to_associations_test.rb +1029 -711
  28. data/test/cases/associations/callbacks_test.rb +192 -0
  29. data/test/cases/associations/cascaded_eager_loading_test.rb +188 -181
  30. data/test/cases/associations/deprecated_counter_cache_on_has_many_through_test.rb +26 -0
  31. data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +36 -0
  32. data/test/cases/associations/eager_load_nested_include_test.rb +128 -0
  33. data/test/cases/associations/eager_singularization_test.rb +148 -0
  34. data/test/cases/associations/eager_test.rb +1411 -0
  35. data/test/cases/associations/extension_test.rb +82 -0
  36. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +932 -851
  37. data/test/cases/associations/has_many_associations_test.rb +2162 -0
  38. data/test/cases/associations/has_many_through_associations_test.rb +1204 -0
  39. data/test/cases/associations/has_one_associations_test.rb +610 -0
  40. data/test/cases/associations/has_one_through_associations_test.rb +380 -0
  41. data/test/cases/associations/inner_join_association_test.rb +139 -0
  42. data/test/cases/associations/inverse_associations_test.rb +693 -0
  43. data/test/cases/associations/join_model_test.rb +754 -743
  44. data/test/cases/associations/nested_through_associations_test.rb +579 -0
  45. data/test/cases/associations/required_test.rb +82 -0
  46. data/test/cases/associations_test.rb +380 -0
  47. data/test/cases/attribute_decorators_test.rb +125 -0
  48. data/test/cases/attribute_methods/read_test.rb +60 -0
  49. data/test/cases/attribute_methods/serialization_test.rb +29 -0
  50. data/test/cases/attribute_methods_test.rb +952 -822
  51. data/test/cases/attribute_set_test.rb +200 -0
  52. data/test/cases/attribute_test.rb +180 -0
  53. data/test/cases/attributes_test.rb +136 -0
  54. data/test/cases/autosave_association_test.rb +1595 -0
  55. data/test/cases/base_test.rb +1638 -2133
  56. data/test/cases/batches_test.rb +212 -0
  57. data/test/cases/binary_test.rb +52 -0
  58. data/test/cases/bind_parameter_test.rb +100 -0
  59. data/test/cases/calculations_test.rb +646 -482
  60. data/test/cases/callbacks_test.rb +543 -0
  61. data/test/cases/clone_test.rb +40 -0
  62. data/test/cases/coders/yaml_column_test.rb +63 -0
  63. data/test/cases/column_alias_test.rb +17 -0
  64. data/test/cases/column_definition_test.rb +123 -0
  65. data/test/cases/connection_adapters/adapter_leasing_test.rb +54 -0
  66. data/test/cases/connection_adapters/connection_handler_test.rb +53 -0
  67. data/test/cases/connection_adapters/connection_specification_test.rb +12 -0
  68. data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +293 -0
  69. data/test/cases/connection_adapters/mysql_type_lookup_test.rb +65 -0
  70. data/test/cases/connection_adapters/quoting_test.rb +13 -0
  71. data/test/cases/connection_adapters/schema_cache_test.rb +56 -0
  72. data/test/cases/connection_adapters/type_lookup_test.rb +110 -0
  73. data/test/cases/connection_management_test.rb +122 -0
  74. data/test/cases/connection_pool_test.rb +346 -0
  75. data/test/cases/connection_specification/resolver_test.rb +116 -0
  76. data/test/cases/core_test.rb +112 -0
  77. data/test/cases/counter_cache_test.rb +209 -0
  78. data/test/cases/custom_locking_test.rb +17 -0
  79. data/test/cases/database_statements_test.rb +19 -0
  80. data/test/cases/date_time_test.rb +61 -0
  81. data/test/cases/defaults_test.rb +223 -0
  82. data/test/cases/dirty_test.rb +775 -0
  83. data/test/cases/disconnected_test.rb +28 -0
  84. data/test/cases/dup_test.rb +157 -0
  85. data/test/cases/enum_test.rb +290 -0
  86. data/test/cases/explain_subscriber_test.rb +64 -0
  87. data/test/cases/explain_test.rb +76 -0
  88. data/test/cases/finder_respond_to_test.rb +60 -0
  89. data/test/cases/finder_test.rb +1166 -0
  90. data/test/cases/fixture_set/file_test.rb +138 -0
  91. data/test/cases/fixtures_test.rb +897 -0
  92. data/test/cases/forbidden_attributes_protection_test.rb +99 -0
  93. data/test/cases/habtm_destroy_order_test.rb +61 -0
  94. data/test/cases/helper.rb +210 -0
  95. data/test/cases/hot_compatibility_test.rb +54 -0
  96. data/test/cases/i18n_test.rb +45 -0
  97. data/test/cases/inheritance_test.rb +375 -0
  98. data/test/cases/integration_test.rb +139 -0
  99. data/test/cases/invalid_connection_test.rb +22 -0
  100. data/test/cases/invalid_date_test.rb +32 -0
  101. data/test/cases/invertible_migration_test.rb +295 -0
  102. data/test/cases/json_serialization_test.rb +302 -0
  103. data/test/cases/locking_test.rb +477 -0
  104. data/test/cases/log_subscriber_test.rb +136 -0
  105. data/test/cases/migration/change_schema_test - Copy.rb +448 -0
  106. data/test/cases/migration/change_schema_test.rb +472 -0
  107. data/test/cases/migration/change_table_test.rb +224 -0
  108. data/test/cases/migration/column_attributes_test.rb +192 -0
  109. data/test/cases/migration/column_positioning_test.rb +56 -0
  110. data/test/cases/migration/columns_test.rb +304 -0
  111. data/test/cases/migration/command_recorder_test.rb +305 -0
  112. data/test/cases/migration/create_join_table_test.rb +148 -0
  113. data/test/cases/migration/foreign_key_test - Changed.rb +325 -0
  114. data/test/cases/migration/foreign_key_test.rb +360 -0
  115. data/test/cases/migration/helper.rb +39 -0
  116. data/test/cases/migration/index_test.rb +216 -0
  117. data/test/cases/migration/logger_test.rb +36 -0
  118. data/test/cases/migration/pending_migrations_test.rb +53 -0
  119. data/test/cases/migration/references_foreign_key_test.rb +214 -0
  120. data/test/cases/migration/references_index_test.rb +101 -0
  121. data/test/cases/migration/references_statements_test.rb +116 -0
  122. data/test/cases/migration/rename_table_test.rb +93 -0
  123. data/test/cases/migration/table_and_index_test.rb +24 -0
  124. data/test/cases/migration_test.rb +959 -2408
  125. data/test/cases/migrator_test.rb +388 -0
  126. data/test/cases/mixin_test.rb +70 -0
  127. data/test/cases/modules_test.rb +173 -0
  128. data/test/cases/multiparameter_attributes_test.rb +350 -0
  129. data/test/cases/multiple_db_test.rb +115 -0
  130. data/test/cases/nested_attributes_test.rb +1057 -0
  131. data/test/cases/nested_attributes_with_callbacks_test.rb +144 -0
  132. data/test/cases/persistence_test.rb +909 -642
  133. data/test/cases/pooled_connections_test.rb +81 -0
  134. data/test/cases/primary_keys_test.rb +237 -0
  135. data/test/cases/query_cache_test.rb +326 -257
  136. data/test/cases/quoting_test.rb +156 -0
  137. data/test/cases/readonly_test.rb +118 -0
  138. data/test/cases/reaper_test.rb +85 -0
  139. data/test/cases/reflection_test.rb +454 -0
  140. data/test/cases/relation/delegation_test.rb +68 -0
  141. data/test/cases/relation/merging_test.rb +161 -0
  142. data/test/cases/relation/mutation_test.rb +165 -0
  143. data/test/cases/relation/predicate_builder_test.rb +14 -0
  144. data/test/cases/relation/where_chain_test.rb +181 -0
  145. data/test/cases/relation/where_test.rb +300 -0
  146. data/test/cases/relation/where_test2.rb +36 -0
  147. data/test/cases/relation_test.rb +297 -0
  148. data/test/cases/relations_test.rb +1815 -1182
  149. data/test/cases/reload_models_test.rb +22 -0
  150. data/test/cases/result_test.rb +80 -0
  151. data/test/cases/sanitize_test.rb +83 -0
  152. data/test/cases/schema_dumper_test.rb +463 -256
  153. data/test/cases/scoping/default_scoping_test.rb +454 -0
  154. data/test/cases/scoping/named_scoping_test.rb +524 -0
  155. data/test/cases/scoping/relation_scoping_test.rb +357 -0
  156. data/test/cases/serialization_test.rb +104 -0
  157. data/test/cases/serialized_attribute_test.rb +277 -0
  158. data/test/cases/statement_cache_test.rb +98 -0
  159. data/test/cases/store_test.rb +194 -0
  160. data/test/cases/tasks/database_tasks_test.rb +396 -0
  161. data/test/cases/tasks/mysql_rake_test.rb +311 -0
  162. data/test/cases/tasks/postgresql_rake_test.rb +245 -0
  163. data/test/cases/tasks/sqlite_rake_test.rb +193 -0
  164. data/test/cases/test_case.rb +123 -0
  165. data/test/cases/timestamp_test.rb +468 -0
  166. data/test/cases/transaction_callbacks_test.rb +452 -300
  167. data/test/cases/transaction_isolation_test.rb +106 -0
  168. data/test/cases/transactions_test.rb +817 -0
  169. data/test/cases/type/decimal_test.rb +51 -0
  170. data/test/cases/type/integer_test.rb +121 -0
  171. data/test/cases/type/string_test.rb +36 -0
  172. data/test/cases/type/type_map_test.rb +177 -0
  173. data/test/cases/type/unsigned_integer_test.rb +18 -0
  174. data/test/cases/types_test.rb +141 -0
  175. data/test/cases/unconnected_test.rb +33 -0
  176. data/test/cases/validations/association_validation_test.rb +86 -0
  177. data/test/cases/validations/i18n_generate_message_validation_test.rb +84 -0
  178. data/test/cases/validations/i18n_validation_test.rb +90 -0
  179. data/test/cases/validations/length_validation_test.rb +47 -0
  180. data/test/cases/validations/presence_validation_test.rb +68 -0
  181. data/test/cases/validations/uniqueness_validation_test.rb +434 -299
  182. data/test/cases/validations_repair_helper.rb +23 -0
  183. data/test/cases/validations_test.rb +165 -0
  184. data/test/cases/view_test.rb +113 -0
  185. data/test/cases/xml_serialization_test.rb +457 -408
  186. data/test/cases/yaml_serialization_test.rb +86 -0
  187. data/test/config.rb +5 -0
  188. data/test/config.yml +154 -154
  189. data/test/connections/native_ibm_db/connection.rb +43 -43
  190. data/test/fixtures/accounts.yml +29 -0
  191. data/test/fixtures/admin/accounts.yml +2 -0
  192. data/test/fixtures/admin/randomly_named_a9.yml +7 -0
  193. data/test/fixtures/admin/randomly_named_b0.yml +7 -0
  194. data/test/fixtures/admin/users.yml +10 -0
  195. data/test/fixtures/all/admin +1 -0
  196. data/test/fixtures/all/developers.yml +0 -0
  197. data/test/fixtures/all/people.yml +0 -0
  198. data/test/fixtures/all/tasks.yml +0 -0
  199. data/test/fixtures/author_addresses.yml +18 -0
  200. data/test/fixtures/author_favorites.yml +4 -0
  201. data/test/fixtures/authors.yml +23 -0
  202. data/test/fixtures/binaries.yml +133 -0
  203. data/test/fixtures/books.yml +11 -0
  204. data/test/fixtures/bulbs.yml +5 -0
  205. data/test/fixtures/cars.yml +9 -0
  206. data/test/fixtures/categories.yml +19 -0
  207. data/test/fixtures/categories/special_categories.yml +9 -0
  208. data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +4 -0
  209. data/test/fixtures/categories_ordered.yml +7 -0
  210. data/test/fixtures/categories_posts.yml +31 -0
  211. data/test/fixtures/categorizations.yml +23 -0
  212. data/test/fixtures/clubs.yml +8 -0
  213. data/test/fixtures/collections.yml +3 -0
  214. data/test/fixtures/colleges.yml +3 -0
  215. data/test/fixtures/comments.yml +65 -0
  216. data/test/fixtures/companies.yml +67 -0
  217. data/test/fixtures/computers.yml +10 -0
  218. data/test/fixtures/courses.yml +8 -0
  219. data/test/fixtures/customers.yml +26 -0
  220. data/test/fixtures/dashboards.yml +6 -0
  221. data/test/fixtures/developers.yml +22 -0
  222. data/test/fixtures/developers_projects.yml +17 -0
  223. data/test/fixtures/dog_lovers.yml +7 -0
  224. data/test/fixtures/dogs.yml +4 -0
  225. data/test/fixtures/doubloons.yml +3 -0
  226. data/test/fixtures/edges.yml +5 -0
  227. data/test/fixtures/entrants.yml +14 -0
  228. data/test/fixtures/essays.yml +6 -0
  229. data/test/fixtures/faces.yml +11 -0
  230. data/test/fixtures/fk_test_has_fk.yml +3 -0
  231. data/test/fixtures/fk_test_has_pk.yml +2 -0
  232. data/test/fixtures/friendships.yml +4 -0
  233. data/test/fixtures/funny_jokes.yml +10 -0
  234. data/test/fixtures/interests.yml +33 -0
  235. data/test/fixtures/items.yml +3 -0
  236. data/test/fixtures/jobs.yml +7 -0
  237. data/test/fixtures/legacy_things.yml +3 -0
  238. data/test/fixtures/mateys.yml +4 -0
  239. data/test/fixtures/member_details.yml +8 -0
  240. data/test/fixtures/member_types.yml +6 -0
  241. data/test/fixtures/members.yml +11 -0
  242. data/test/fixtures/memberships.yml +34 -0
  243. data/test/fixtures/men.yml +5 -0
  244. data/test/fixtures/minimalistics.yml +2 -0
  245. data/test/fixtures/minivans.yml +5 -0
  246. data/test/fixtures/mixed_case_monkeys.yml +6 -0
  247. data/test/fixtures/mixins.yml +29 -0
  248. data/test/fixtures/movies.yml +7 -0
  249. data/test/fixtures/naked/csv/accounts.csv +1 -0
  250. data/test/fixtures/naked/yml/accounts.yml +1 -0
  251. data/test/fixtures/naked/yml/companies.yml +1 -0
  252. data/test/fixtures/naked/yml/courses.yml +1 -0
  253. data/test/fixtures/organizations.yml +5 -0
  254. data/test/fixtures/other_topics.yml +42 -0
  255. data/test/fixtures/owners.yml +9 -0
  256. data/test/fixtures/parrots.yml +27 -0
  257. data/test/fixtures/parrots_pirates.yml +7 -0
  258. data/test/fixtures/people.yml +24 -0
  259. data/test/fixtures/peoples_treasures.yml +3 -0
  260. data/test/fixtures/pets.yml +19 -0
  261. data/test/fixtures/pirates.yml +12 -0
  262. data/test/fixtures/posts.yml +80 -0
  263. data/test/fixtures/price_estimates.yml +7 -0
  264. data/test/fixtures/products.yml +4 -0
  265. data/test/fixtures/projects.yml +7 -0
  266. data/test/fixtures/randomly_named_a9.yml +7 -0
  267. data/test/fixtures/ratings.yml +14 -0
  268. data/test/fixtures/readers.yml +11 -0
  269. data/test/fixtures/references.yml +17 -0
  270. data/test/fixtures/reserved_words/distinct.yml +5 -0
  271. data/test/fixtures/reserved_words/distinct_select.yml +11 -0
  272. data/test/fixtures/reserved_words/group.yml +14 -0
  273. data/test/fixtures/reserved_words/select.yml +8 -0
  274. data/test/fixtures/reserved_words/values.yml +7 -0
  275. data/test/fixtures/ships.yml +6 -0
  276. data/test/fixtures/speedometers.yml +8 -0
  277. data/test/fixtures/sponsors.yml +12 -0
  278. data/test/fixtures/string_key_objects.yml +7 -0
  279. data/test/fixtures/subscribers.yml +11 -0
  280. data/test/fixtures/subscriptions.yml +12 -0
  281. data/test/fixtures/taggings.yml +78 -0
  282. data/test/fixtures/tags.yml +11 -0
  283. data/test/fixtures/tasks.yml +7 -0
  284. data/test/fixtures/teapots.yml +3 -0
  285. data/test/fixtures/to_be_linked/accounts.yml +2 -0
  286. data/test/fixtures/to_be_linked/users.yml +10 -0
  287. data/test/fixtures/topics.yml +49 -0
  288. data/test/fixtures/toys.yml +14 -0
  289. data/test/fixtures/traffic_lights.yml +10 -0
  290. data/test/fixtures/treasures.yml +10 -0
  291. data/test/fixtures/uuid_children.yml +3 -0
  292. data/test/fixtures/uuid_parents.yml +2 -0
  293. data/test/fixtures/variants.yml +4 -0
  294. data/test/fixtures/vegetables.yml +20 -0
  295. data/test/fixtures/vertices.yml +4 -0
  296. data/test/fixtures/warehouse_things.yml +3 -0
  297. data/test/fixtures/zines.yml +5 -0
  298. data/test/ibm_db_test.rb +24 -24
  299. data/test/migrations/10_urban/9_add_expressions.rb +11 -0
  300. data/test/migrations/decimal/1_give_me_big_numbers.rb +15 -0
  301. data/test/migrations/magic/1_currencies_have_symbols.rb +12 -0
  302. data/test/migrations/missing/1000_people_have_middle_names.rb +9 -0
  303. data/test/migrations/missing/1_people_have_last_names.rb +9 -0
  304. data/test/migrations/missing/3_we_need_reminders.rb +12 -0
  305. data/test/migrations/missing/4_innocent_jointable.rb +12 -0
  306. data/test/migrations/rename/1_we_need_things.rb +11 -0
  307. data/test/migrations/rename/2_rename_things.rb +9 -0
  308. data/test/migrations/to_copy/1_people_have_hobbies.rb +9 -0
  309. data/test/migrations/to_copy/2_people_have_descriptions.rb +9 -0
  310. data/test/migrations/to_copy2/1_create_articles.rb +7 -0
  311. data/test/migrations/to_copy2/2_create_comments.rb +7 -0
  312. data/test/migrations/to_copy_with_name_collision/1_people_have_hobbies.rb +9 -0
  313. data/test/migrations/to_copy_with_timestamps/20090101010101_people_have_hobbies.rb +9 -0
  314. data/test/migrations/to_copy_with_timestamps/20090101010202_people_have_descriptions.rb +9 -0
  315. data/test/migrations/to_copy_with_timestamps2/20090101010101_create_articles.rb +7 -0
  316. data/test/migrations/to_copy_with_timestamps2/20090101010202_create_comments.rb +7 -0
  317. data/test/migrations/valid/1_valid_people_have_last_names.rb +9 -0
  318. data/test/migrations/valid/2_we_need_reminders.rb +12 -0
  319. data/test/migrations/valid/3_innocent_jointable.rb +12 -0
  320. data/test/migrations/valid_with_subdirectories/1_valid_people_have_last_names.rb +9 -0
  321. data/test/migrations/valid_with_subdirectories/sub/2_we_need_reminders.rb +12 -0
  322. data/test/migrations/valid_with_subdirectories/sub1/3_innocent_jointable.rb +12 -0
  323. data/test/migrations/valid_with_timestamps/20100101010101_valid_with_timestamps_people_have_last_names.rb +9 -0
  324. data/test/migrations/valid_with_timestamps/20100201010101_valid_with_timestamps_we_need_reminders.rb +12 -0
  325. data/test/migrations/valid_with_timestamps/20100301010101_valid_with_timestamps_innocent_jointable.rb +12 -0
  326. data/test/migrations/version_check/20131219224947_migration_version_check.rb +8 -0
  327. data/test/models/admin.rb +5 -0
  328. data/test/models/admin/account.rb +3 -0
  329. data/test/models/admin/randomly_named_c1.rb +3 -0
  330. data/test/models/admin/user.rb +40 -0
  331. data/test/models/aircraft.rb +4 -0
  332. data/test/models/arunit2_model.rb +3 -0
  333. data/test/models/author.rb +212 -0
  334. data/test/models/auto_id.rb +4 -0
  335. data/test/models/autoloadable/extra_firm.rb +2 -0
  336. data/test/models/binary.rb +2 -0
  337. data/test/models/bird.rb +12 -0
  338. data/test/models/book.rb +18 -0
  339. data/test/models/boolean.rb +2 -0
  340. data/test/models/bulb.rb +51 -0
  341. data/test/models/cake_designer.rb +3 -0
  342. data/test/models/car.rb +26 -0
  343. data/test/models/carrier.rb +2 -0
  344. data/test/models/categorization.rb +19 -0
  345. data/test/models/category.rb +35 -0
  346. data/test/models/chef.rb +3 -0
  347. data/test/models/citation.rb +3 -0
  348. data/test/models/club.rb +23 -0
  349. data/test/models/college.rb +10 -0
  350. data/test/models/column.rb +3 -0
  351. data/test/models/column_name.rb +3 -0
  352. data/test/models/comment.rb +64 -0
  353. data/test/models/company.rb +225 -0
  354. data/test/models/company_in_module.rb +98 -0
  355. data/test/models/computer.rb +3 -0
  356. data/test/models/contact.rb +41 -0
  357. data/test/models/contract.rb +20 -0
  358. data/test/models/country.rb +7 -0
  359. data/test/models/course.rb +6 -0
  360. data/test/models/customer.rb +77 -0
  361. data/test/models/customer_carrier.rb +14 -0
  362. data/test/models/dashboard.rb +3 -0
  363. data/test/models/default.rb +2 -0
  364. data/test/models/department.rb +4 -0
  365. data/test/models/developer.rb +252 -0
  366. data/test/models/dog.rb +5 -0
  367. data/test/models/dog_lover.rb +5 -0
  368. data/test/models/doubloon.rb +12 -0
  369. data/test/models/drink_designer.rb +3 -0
  370. data/test/models/edge.rb +5 -0
  371. data/test/models/electron.rb +5 -0
  372. data/test/models/engine.rb +4 -0
  373. data/test/models/entrant.rb +3 -0
  374. data/test/models/essay.rb +5 -0
  375. data/test/models/event.rb +3 -0
  376. data/test/models/eye.rb +37 -0
  377. data/test/models/face.rb +9 -0
  378. data/test/models/friendship.rb +6 -0
  379. data/test/models/guid.rb +2 -0
  380. data/test/models/hotel.rb +6 -0
  381. data/test/models/image.rb +3 -0
  382. data/test/models/interest.rb +5 -0
  383. data/test/models/invoice.rb +4 -0
  384. data/test/models/item.rb +7 -0
  385. data/test/models/job.rb +7 -0
  386. data/test/models/joke.rb +7 -0
  387. data/test/models/keyboard.rb +3 -0
  388. data/test/models/legacy_thing.rb +3 -0
  389. data/test/models/lesson.rb +11 -0
  390. data/test/models/line_item.rb +3 -0
  391. data/test/models/liquid.rb +4 -0
  392. data/test/models/man.rb +11 -0
  393. data/test/models/matey.rb +4 -0
  394. data/test/models/member.rb +41 -0
  395. data/test/models/member_detail.rb +7 -0
  396. data/test/models/member_type.rb +3 -0
  397. data/test/models/membership.rb +35 -0
  398. data/test/models/minimalistic.rb +2 -0
  399. data/test/models/minivan.rb +9 -0
  400. data/test/models/mixed_case_monkey.rb +3 -0
  401. data/test/models/molecule.rb +6 -0
  402. data/test/models/movie.rb +5 -0
  403. data/test/models/order.rb +4 -0
  404. data/test/models/organization.rb +14 -0
  405. data/test/models/owner.rb +34 -0
  406. data/test/models/parrot.rb +29 -0
  407. data/test/models/person.rb +143 -0
  408. data/test/models/personal_legacy_thing.rb +4 -0
  409. data/test/models/pet.rb +15 -0
  410. data/test/models/pirate.rb +92 -0
  411. data/test/models/possession.rb +3 -0
  412. data/test/models/post.rb +264 -0
  413. data/test/models/price_estimate.rb +4 -0
  414. data/test/models/professor.rb +5 -0
  415. data/test/models/project.rb +29 -0
  416. data/test/models/publisher.rb +2 -0
  417. data/test/models/publisher/article.rb +4 -0
  418. data/test/models/publisher/magazine.rb +3 -0
  419. data/test/models/randomly_named_c1.rb +3 -0
  420. data/test/models/rating.rb +4 -0
  421. data/test/models/reader.rb +23 -0
  422. data/test/models/record.rb +2 -0
  423. data/test/models/reference.rb +22 -0
  424. data/test/models/reply.rb +61 -0
  425. data/test/models/ship.rb +33 -0
  426. data/test/models/ship_part.rb +8 -0
  427. data/test/models/shop.rb +17 -0
  428. data/test/models/shop_account.rb +6 -0
  429. data/test/models/speedometer.rb +6 -0
  430. data/test/models/sponsor.rb +7 -0
  431. data/test/models/string_key_object.rb +3 -0
  432. data/test/models/student.rb +4 -0
  433. data/test/models/subject.rb +16 -0
  434. data/test/models/subscriber.rb +8 -0
  435. data/test/models/subscription.rb +4 -0
  436. data/test/models/tag.rb +7 -0
  437. data/test/models/tagging.rb +13 -0
  438. data/test/models/task.rb +5 -0
  439. data/test/models/topic.rb +124 -0
  440. data/test/models/toy.rb +6 -0
  441. data/test/models/traffic_light.rb +4 -0
  442. data/test/models/treasure.rb +14 -0
  443. data/test/models/treaty.rb +7 -0
  444. data/test/models/tyre.rb +11 -0
  445. data/test/models/uuid_child.rb +3 -0
  446. data/test/models/uuid_parent.rb +3 -0
  447. data/test/models/vegetables.rb +24 -0
  448. data/test/models/vehicle.rb +7 -0
  449. data/test/models/vertex.rb +9 -0
  450. data/test/models/warehouse_thing.rb +5 -5
  451. data/test/models/wheel.rb +3 -0
  452. data/test/models/without_table.rb +3 -0
  453. data/test/models/zine.rb +3 -0
  454. data/test/schema/mysql2_specific_schema.rb +58 -0
  455. data/test/schema/mysql_specific_schema.rb +70 -0
  456. data/test/schema/oracle_specific_schema.rb +43 -0
  457. data/test/schema/postgresql_specific_schema.rb +202 -0
  458. data/test/schema/schema.rb +938 -751
  459. data/test/schema/sqlite_specific_schema.rb +22 -0
  460. data/test/support/config.rb +43 -0
  461. data/test/support/connection.rb +22 -0
  462. data/test/support/connection_helper.rb +14 -0
  463. data/test/support/ddl_helper.rb +8 -0
  464. data/test/support/schema_dumping_helper.rb +20 -0
  465. metadata +444 -18
@@ -0,0 +1,212 @@
1
+ require 'cases/helper'
2
+ require 'models/post'
3
+ require 'models/subscriber'
4
+
5
+ class EachTest < ActiveRecord::TestCase
6
+ fixtures :posts, :subscribers
7
+
8
+ def setup
9
+ @posts = Post.order("id asc")
10
+ @total = Post.count
11
+ Post.count('id') # preheat arel's table cache
12
+ end
13
+
14
+ def test_each_should_execute_one_query_per_batch
15
+ assert_queries(@total + 1) do
16
+ Post.find_each(:batch_size => 1) do |post|
17
+ assert_kind_of Post, post
18
+ end
19
+ end
20
+ end
21
+
22
+ def test_each_should_not_return_query_chain_and_execute_only_one_query
23
+ assert_queries(1) do
24
+ result = Post.find_each(:batch_size => 100000){ }
25
+ assert_nil result
26
+ end
27
+ end
28
+
29
+ def test_each_should_return_an_enumerator_if_no_block_is_present
30
+ assert_queries(1) do
31
+ Post.find_each(:batch_size => 100000).with_index do |post, index|
32
+ assert_kind_of Post, post
33
+ assert_kind_of Integer, index
34
+ end
35
+ end
36
+ end
37
+
38
+ if Enumerator.method_defined? :size
39
+ def test_each_should_return_a_sized_enumerator
40
+ assert_equal 11, Post.find_each(:batch_size => 1).size
41
+ assert_equal 5, Post.find_each(:batch_size => 2, :start => 7).size
42
+ assert_equal 11, Post.find_each(:batch_size => 10_000).size
43
+ end
44
+ end
45
+
46
+ def test_each_enumerator_should_execute_one_query_per_batch
47
+ assert_queries(@total + 1) do
48
+ Post.find_each(:batch_size => 1).with_index do |post, index|
49
+ assert_kind_of Post, post
50
+ assert_kind_of Integer, index
51
+ end
52
+ end
53
+ end
54
+
55
+ def test_each_should_raise_if_select_is_set_without_id
56
+ assert_raise(RuntimeError) do
57
+ Post.select(:title).find_each(batch_size: 1) { |post|
58
+ flunk "should not call this block"
59
+ }
60
+ end
61
+ end
62
+
63
+ def test_each_should_execute_if_id_is_in_select
64
+ assert_queries(6) do
65
+ Post.select("id, title, type").find_each(:batch_size => 2) do |post|
66
+ assert_kind_of Post, post
67
+ end
68
+ end
69
+ end
70
+
71
+ def test_warn_if_limit_scope_is_set
72
+ ActiveRecord::Base.logger.expects(:warn)
73
+ Post.limit(1).find_each { |post| post }
74
+ end
75
+
76
+ def test_warn_if_order_scope_is_set
77
+ ActiveRecord::Base.logger.expects(:warn)
78
+ Post.order("title").find_each { |post| post }
79
+ end
80
+
81
+ def test_logger_not_required
82
+ previous_logger = ActiveRecord::Base.logger
83
+ ActiveRecord::Base.logger = nil
84
+ assert_nothing_raised do
85
+ Post.limit(1).find_each { |post| post }
86
+ end
87
+ ensure
88
+ ActiveRecord::Base.logger = previous_logger
89
+ end
90
+
91
+ def test_find_in_batches_should_return_batches
92
+ assert_queries(@total + 1) do
93
+ Post.find_in_batches(:batch_size => 1) do |batch|
94
+ assert_kind_of Array, batch
95
+ assert_kind_of Post, batch.first
96
+ end
97
+ end
98
+ end
99
+
100
+ def test_find_in_batches_should_start_from_the_start_option
101
+ assert_queries(@total) do
102
+ Post.find_in_batches(:batch_size => 1, :start => 2) do |batch|
103
+ assert_kind_of Array, batch
104
+ assert_kind_of Post, batch.first
105
+ end
106
+ end
107
+ end
108
+
109
+ def test_find_in_batches_shouldnt_execute_query_unless_needed
110
+ assert_queries(2) do
111
+ Post.find_in_batches(:batch_size => @total) {|batch| assert_kind_of Array, batch }
112
+ end
113
+
114
+ assert_queries(1) do
115
+ Post.find_in_batches(:batch_size => @total + 1) {|batch| assert_kind_of Array, batch }
116
+ end
117
+ end
118
+
119
+ def test_find_in_batches_should_quote_batch_order
120
+ c = Post.connection
121
+ assert_sql(/ORDER BY #{c.quote_table_name('posts')}.#{c.quote_column_name('id')}/) do
122
+ Post.find_in_batches(:batch_size => 1) do |batch|
123
+ assert_kind_of Array, batch
124
+ assert_kind_of Post, batch.first
125
+ end
126
+ end
127
+ end
128
+
129
+ def test_find_in_batches_should_not_use_records_after_yielding_them_in_case_original_array_is_modified
130
+ not_a_post = "not a post"
131
+ not_a_post.stubs(:id).raises(StandardError, "not_a_post had #id called on it")
132
+
133
+ assert_nothing_raised do
134
+ Post.find_in_batches(:batch_size => 1) do |batch|
135
+ assert_kind_of Array, batch
136
+ assert_kind_of Post, batch.first
137
+
138
+ batch.map! { not_a_post }
139
+ end
140
+ end
141
+ end
142
+
143
+ def test_find_in_batches_should_ignore_the_order_default_scope
144
+ # First post is with title scope
145
+ first_post = PostWithDefaultScope.first
146
+ posts = []
147
+ PostWithDefaultScope.find_in_batches do |batch|
148
+ posts.concat(batch)
149
+ end
150
+ # posts.first will be ordered using id only. Title order scope should not apply here
151
+ assert_not_equal first_post, posts.first
152
+ assert_equal posts(:welcome), posts.first
153
+ end
154
+
155
+ def test_find_in_batches_should_not_ignore_the_default_scope_if_it_is_other_then_order
156
+ special_posts_ids = SpecialPostWithDefaultScope.all.map(&:id).sort
157
+ posts = []
158
+ SpecialPostWithDefaultScope.find_in_batches do |batch|
159
+ posts.concat(batch)
160
+ end
161
+ assert_equal special_posts_ids, posts.map(&:id)
162
+ end
163
+
164
+ def test_find_in_batches_should_not_modify_passed_options
165
+ assert_nothing_raised do
166
+ Post.find_in_batches({ batch_size: 42, start: 1 }.freeze){}
167
+ end
168
+ end
169
+
170
+ def test_find_in_batches_should_use_any_column_as_primary_key
171
+ nick_order_subscribers = Subscriber.order('nick asc')
172
+ start_nick = nick_order_subscribers.second.nick
173
+
174
+ subscribers = []
175
+ Subscriber.find_in_batches(:batch_size => 1, :start => start_nick) do |batch|
176
+ subscribers.concat(batch)
177
+ end
178
+
179
+ assert_equal nick_order_subscribers[1..-1].map(&:id), subscribers.map(&:id)
180
+ end
181
+
182
+ def test_find_in_batches_should_use_any_column_as_primary_key_when_start_is_not_specified
183
+ assert_queries(Subscriber.count + 1) do
184
+ Subscriber.find_each(:batch_size => 1) do |subscriber|
185
+ assert_kind_of Subscriber, subscriber
186
+ end
187
+ end
188
+ end
189
+
190
+ def test_find_in_batches_should_return_an_enumerator
191
+ enum = nil
192
+ assert_queries(0) do
193
+ enum = Post.find_in_batches(:batch_size => 1)
194
+ end
195
+ assert_queries(4) do
196
+ enum.first(4) do |batch|
197
+ assert_kind_of Array, batch
198
+ assert_kind_of Post, batch.first
199
+ end
200
+ end
201
+ end
202
+
203
+ if Enumerator.method_defined? :size
204
+ def test_find_in_batches_should_return_a_sized_enumerator
205
+ assert_equal 11, Post.find_in_batches(:batch_size => 1).size
206
+ assert_equal 6, Post.find_in_batches(:batch_size => 2).size
207
+ assert_equal 4, Post.find_in_batches(:batch_size => 2, :start => 4).size
208
+ assert_equal 4, Post.find_in_batches(:batch_size => 3).size
209
+ assert_equal 1, Post.find_in_batches(:batch_size => 10_000).size
210
+ end
211
+ end
212
+ end
@@ -0,0 +1,52 @@
1
+ # encoding: utf-8
2
+ require "cases/helper"
3
+
4
+ # Without using prepared statements, it makes no sense to test
5
+ # BLOB data with DB2, because the length of a statement
6
+ # is limited to 32KB.
7
+ unless current_adapter?(:DB2Adapter)
8
+ require 'models/binary'
9
+
10
+ class BinaryTest < ActiveRecord::TestCase
11
+ FIXTURES = %w(flowers.jpg example.log test.txt)
12
+
13
+ def test_mixed_encoding
14
+ str = "\x80"
15
+ str.force_encoding('ASCII-8BIT')
16
+
17
+ binary = Binary.new :name => 'いただきます!', :data => str
18
+ binary.save!
19
+ binary.reload
20
+ assert_equal str, binary.data
21
+
22
+ name = binary.name
23
+
24
+ # MySQL adapter doesn't properly encode things, so we have to do it
25
+ if current_adapter?(:MysqlAdapter, :DB2Adapter)
26
+ name.force_encoding(Encoding::UTF_8)
27
+ end
28
+ assert_equal 'いただきます!', name
29
+ end
30
+
31
+ def test_load_save
32
+ Binary.delete_all
33
+
34
+ FIXTURES.each do |filename|
35
+ data = File.read(ASSETS_ROOT + "/#{filename}")
36
+ data.force_encoding('ASCII-8BIT')
37
+ if current_adapter?(:DB2Adapter)
38
+ data.force_encoding(Encoding::UTF_8)
39
+ end
40
+ data.freeze
41
+
42
+ bin = Binary.new(:data => data)
43
+ assert_equal data, bin.data, 'Newly assigned data differs from original'
44
+
45
+ bin.save!
46
+ assert_equal data, bin.data, 'Data differs from original after save'
47
+
48
+ assert_equal data, bin.reload.data, 'Reloaded data differs from original'
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,100 @@
1
+ require 'cases/helper'
2
+ require 'models/topic'
3
+ require 'models/author'
4
+ require 'models/post'
5
+
6
+ module ActiveRecord
7
+ class BindParameterTest < ActiveRecord::TestCase
8
+ fixtures :topics, :authors, :posts
9
+
10
+ class LogListener
11
+ attr_accessor :calls
12
+
13
+ def initialize
14
+ @calls = []
15
+ end
16
+
17
+ def call(*args)
18
+ calls << args
19
+ end
20
+ end
21
+
22
+ def setup
23
+ super
24
+ @connection = ActiveRecord::Base.connection
25
+ @subscriber = LogListener.new
26
+ @pk = Topic.columns_hash[Topic.primary_key]
27
+ @subscription = ActiveSupport::Notifications.subscribe('sql.active_record', @subscriber)
28
+ end
29
+
30
+ teardown do
31
+ ActiveSupport::Notifications.unsubscribe(@subscription)
32
+ end
33
+
34
+ if ActiveRecord::Base.connection.supports_statement_cache?
35
+ def test_bind_from_join_in_subquery
36
+ subquery = Author.joins(:thinking_posts).where(name: 'David')
37
+ scope = Author.from(subquery, 'authors').where(id: 1)
38
+ assert_equal 1, scope.count
39
+ end
40
+
41
+ def test_binds_are_logged
42
+ sub = @connection.substitute_at(@pk)
43
+ binds = [[@pk, 1]]
44
+ sql = "select * from topics where id = #{sub.to_sql}"
45
+
46
+ @connection.exec_query(sql, 'SQL', binds)
47
+
48
+ message = @subscriber.calls.find { |args| args[4][:sql] == sql }
49
+ assert_equal binds, message[4][:binds]
50
+ end
51
+
52
+ def test_binds_are_logged_after_type_cast
53
+ sub = @connection.substitute_at(@pk)
54
+ binds = [[@pk, "3"]]
55
+ sql = "select * from topics where id = #{sub.to_sql}"
56
+
57
+ @connection.exec_query(sql, 'SQL', binds)
58
+
59
+ message = @subscriber.calls.find { |args| args[4][:sql] == sql }
60
+ assert_equal [[@pk, 3]], message[4][:binds]
61
+ end
62
+
63
+ def test_find_one_uses_binds
64
+ Topic.find(1)
65
+ binds = [[@pk, 1]]
66
+ message = @subscriber.calls.find { |args| args[4][:binds] == binds }
67
+ assert message, 'expected a message with binds'
68
+ end
69
+
70
+ def test_logs_bind_vars
71
+ payload = {
72
+ :name => 'SQL',
73
+ :sql => 'select * from topics where id = ?',
74
+ :binds => [[@pk, 10]]
75
+ }
76
+ event = ActiveSupport::Notifications::Event.new(
77
+ 'foo',
78
+ Time.now,
79
+ Time.now,
80
+ 123,
81
+ payload)
82
+
83
+ logger = Class.new(ActiveRecord::LogSubscriber) {
84
+ attr_reader :debugs
85
+ def initialize
86
+ super
87
+ @debugs = []
88
+ end
89
+
90
+ def debug str
91
+ @debugs << str
92
+ end
93
+ }.new
94
+
95
+ logger.sql event
96
+ assert_match([[@pk.name, 10]].inspect, logger.debugs.first)
97
+ end
98
+ end
99
+ end
100
+ end
@@ -1,482 +1,646 @@
1
- require "cases/helper"
2
- require 'models/company'
3
- require "models/contract"
4
- require 'models/topic'
5
- require 'models/edge'
6
- require 'models/club'
7
- require 'models/organization'
8
-
9
- Company.has_many :accounts
10
-
11
- class NumericData < ActiveRecord::Base
12
- self.table_name = 'numeric_data'
13
- end
14
-
15
- class CalculationsTest < ActiveRecord::TestCase
16
- fixtures :companies, :accounts, :topics
17
-
18
- def test_should_sum_field
19
- assert_equal 318, Account.sum(:credit_limit)
20
- end
21
-
22
- def test_should_average_field
23
- value = Account.average(:credit_limit)
24
- assert_equal 53.0, value
25
- end
26
-
27
- def test_should_return_decimal_average_of_integer_field
28
- return if current_adapter?(:IBM_DBAdapter) #average cannot be a decimal value when applied on integer field
29
- value = Account.average(:id)
30
- assert_equal 3.5, value
31
- end
32
-
33
- def test_should_return_integer_average_if_db_returns_such
34
- Account.connection.stubs :select_value => 3
35
- value = Account.average(:id)
36
- assert_equal 3, value
37
- end
38
-
39
- def test_should_return_nil_as_average
40
- assert_nil NumericData.average(:bank_balance)
41
- end
42
-
43
- def test_type_cast_calculated_value_should_convert_db_averages_of_fixnum_class_to_decimal
44
- assert_equal 0, NumericData.scoped.send(:type_cast_calculated_value, 0, nil, 'avg')
45
- assert_equal 53.0, NumericData.scoped.send(:type_cast_calculated_value, 53, nil, 'avg')
46
- end
47
-
48
- def test_should_get_maximum_of_field
49
- assert_equal 60, Account.maximum(:credit_limit)
50
- end
51
-
52
- def test_should_get_maximum_of_field_with_include
53
- assert_equal 55, Account.maximum(:credit_limit, :include => :firm, :conditions => "companies.name != 'Summit'")
54
- end
55
-
56
- def test_should_get_maximum_of_field_with_scoped_include
57
- Account.send :with_scope, :find => { :include => :firm, :conditions => "companies.name != 'Summit'" } do
58
- assert_equal 55, Account.maximum(:credit_limit)
59
- end
60
- end
61
-
62
- def test_should_get_minimum_of_field
63
- assert_equal 50, Account.minimum(:credit_limit)
64
- end
65
-
66
- def test_should_group_by_field
67
- c = Account.sum(:credit_limit, :group => :firm_id)
68
- [1,6,2].each { |firm_id| assert c.keys.include?(firm_id) }
69
- end
70
-
71
- def test_should_group_by_multiple_fields
72
- c = Account.count(:all, :group => ['firm_id', :credit_limit])
73
- [ [nil, 50], [1, 50], [6, 50], [6, 55], [9, 53], [2, 60] ].each { |firm_and_limit| assert c.keys.include?(firm_and_limit) }
74
- end
75
-
76
- def test_should_group_by_multiple_fields_having_functions
77
- c = Topic.group(:author_name, 'COALESCE(type, title)').count(:all)
78
- assert_equal 1, c[["Carl", "The Third Topic of the day"]]
79
- assert_equal 1, c[["Mary", "Reply"]]
80
- assert_equal 1, c[["David", "The First Topic"]]
81
- assert_equal 1, c[["Carl", "Reply"]]
82
- end
83
-
84
- def test_should_group_by_summed_field
85
- c = Account.sum(:credit_limit, :group => :firm_id)
86
- assert_equal 50, c[1]
87
- assert_equal 105, c[6]
88
- assert_equal 60, c[2]
89
- end
90
-
91
- def test_should_order_by_grouped_field
92
- c = Account.sum(:credit_limit, :group => :firm_id, :order => "firm_id")
93
- assert_equal [1, 2, 6, 9], c.keys.compact
94
- end
95
-
96
- def test_should_order_by_calculation
97
- c = Account.sum(:credit_limit, :group => :firm_id, :order => "sum_credit_limit desc, firm_id")
98
- assert_equal [105, 60, 53, 50, 50], c.keys.collect { |k| c[k] }
99
- assert_equal [6, 2, 9, 1], c.keys.compact
100
- end
101
-
102
- def test_should_limit_calculation
103
- c = Account.sum(:credit_limit, :conditions => "firm_id IS NOT NULL",
104
- :group => :firm_id, :order => "firm_id", :limit => 2)
105
- assert_equal [1, 2], c.keys.compact
106
- end
107
-
108
- def test_should_limit_calculation_with_offset
109
- c = Account.sum(:credit_limit, :conditions => "firm_id IS NOT NULL",
110
- :group => :firm_id, :order => "firm_id", :limit => 2, :offset => 1)
111
- assert_equal [2, 6], c.keys.compact
112
- end
113
-
114
- def test_limit_should_apply_before_count
115
- accounts = Account.limit(3).where('firm_id IS NOT NULL')
116
-
117
- assert_equal 3, accounts.count(:firm_id)
118
- assert_equal 3, accounts.select(:firm_id).count
119
- end
120
-
121
- def test_count_should_shortcut_with_limit_zero
122
- accounts = Account.limit(0)
123
-
124
- assert_no_queries { assert_equal 0, accounts.count }
125
- end
126
-
127
- def test_limit_is_kept
128
- return if current_adapter?(:OracleAdapter, :IBM_DBAdapter)
129
-
130
- queries = assert_sql { Account.limit(1).count }
131
- assert_equal 1, queries.length
132
- assert_match(/LIMIT/, queries.first)
133
- end
134
-
135
- def test_offset_is_kept
136
- return if current_adapter?(:OracleAdapter,:IBM_DBAdapter)
137
-
138
- queries = assert_sql { Account.offset(1).count }
139
- assert_equal 1, queries.length
140
- assert_match(/OFFSET/, queries.first)
141
- end
142
-
143
- def test_limit_with_offset_is_kept
144
- return if current_adapter?(:OracleAdapter,:IBM_DBAdapter)
145
-
146
- queries = assert_sql { Account.limit(1).offset(1).count }
147
- assert_equal 1, queries.length
148
- assert_match(/LIMIT/, queries.first)
149
- assert_match(/OFFSET/, queries.first)
150
- end
151
-
152
- def test_no_limit_no_offset
153
- queries = assert_sql { Account.count }
154
- assert_equal 1, queries.length
155
- assert_no_match(/LIMIT/, queries.first)
156
- assert_no_match(/OFFSET/, queries.first)
157
- end
158
-
159
- def test_should_group_by_summed_field_having_condition
160
- c = Account.sum(:credit_limit, :group => :firm_id,
161
- :having => 'sum(credit_limit) > 50')
162
- assert_nil c[1]
163
- assert_equal 105, c[6]
164
- assert_equal 60, c[2]
165
- end
166
-
167
- def test_should_group_by_summed_field_having_sanitized_condition
168
- c = Account.sum(:credit_limit, :group => :firm_id,
169
- :having => ['sum(credit_limit) > ?', 50])
170
- assert_nil c[1]
171
- assert_equal 105, c[6]
172
- assert_equal 60, c[2]
173
- end
174
-
175
- def test_should_group_by_summed_field_having_condition_from_select
176
- c = Account.select("MIN(credit_limit) AS min_credit_limit").group(:firm_id).having("MIN(credit_limit) > 50").sum(:credit_limit)
177
- assert_nil c[1]
178
- assert_equal 60, c[2]
179
- assert_equal 53, c[9]
180
- end
181
-
182
- def test_should_group_by_summed_association
183
- c = Account.sum(:credit_limit, :group => :firm)
184
- assert_equal 50, c[companies(:first_firm)]
185
- assert_equal 105, c[companies(:rails_core)]
186
- assert_equal 60, c[companies(:first_client)]
187
- end
188
-
189
- def test_should_sum_field_with_conditions
190
- assert_equal 105, Account.sum(:credit_limit, :conditions => 'firm_id = 6')
191
- end
192
-
193
- def test_should_return_zero_if_sum_conditions_return_nothing
194
- assert_equal 0, Account.sum(:credit_limit, :conditions => '1 = 2')
195
- assert_equal 0, companies(:rails_core).companies.sum(:id, :conditions => '1 = 2')
196
- end
197
-
198
- def test_sum_should_return_valid_values_for_decimals
199
- NumericData.create(:bank_balance => 19.83)
200
- assert_equal 19.83, NumericData.sum(:bank_balance)
201
- end
202
-
203
- def test_should_group_by_summed_field_with_conditions
204
- c = Account.sum(:credit_limit, :conditions => 'firm_id > 1',
205
- :group => :firm_id)
206
- assert_nil c[1]
207
- assert_equal 105, c[6]
208
- assert_equal 60, c[2]
209
- end
210
-
211
- def test_should_group_by_summed_field_with_conditions_and_having
212
- c = Account.sum(:credit_limit, :conditions => 'firm_id > 1',
213
- :group => :firm_id,
214
- :having => 'sum(credit_limit) > 60')
215
- assert_nil c[1]
216
- assert_equal 105, c[6]
217
- assert_nil c[2]
218
- end
219
-
220
- def test_should_group_by_fields_with_table_alias
221
- c = Account.sum(:credit_limit, :group => 'accounts.firm_id')
222
- assert_equal 50, c[1]
223
- assert_equal 105, c[6]
224
- assert_equal 60, c[2]
225
- end
226
-
227
- def test_should_calculate_with_invalid_field
228
- assert_equal 6, Account.calculate(:count, '*')
229
- assert_equal 6, Account.calculate(:count, :all)
230
- end
231
-
232
- def test_should_calculate_grouped_with_invalid_field
233
- c = Account.count(:all, :group => 'accounts.firm_id')
234
- assert_equal 1, c[1]
235
- assert_equal 2, c[6]
236
- assert_equal 1, c[2]
237
- end
238
-
239
- def test_should_calculate_grouped_association_with_invalid_field
240
- c = Account.count(:all, :group => :firm)
241
- assert_equal 1, c[companies(:first_firm)]
242
- assert_equal 2, c[companies(:rails_core)]
243
- assert_equal 1, c[companies(:first_client)]
244
- end
245
-
246
- def test_should_group_by_association_with_non_numeric_foreign_key
247
- ActiveRecord::Base.connection.expects(:select_all).returns([{"count_all" => 1, "firm_id" => "ABC"}])
248
-
249
- firm = mock()
250
- firm.expects(:id).returns("ABC")
251
- firm.expects(:class).returns(Firm)
252
- Company.expects(:find).with(["ABC"]).returns([firm])
253
-
254
- column = mock()
255
- column.expects(:name).at_least_once.returns(:firm_id)
256
- column.expects(:type_cast).with("ABC").returns("ABC")
257
- Account.expects(:columns).at_least_once.returns([column])
258
-
259
- c = Account.count(:all, :group => :firm)
260
- first_key = c.keys.first
261
- assert_equal Firm, first_key.class
262
- assert_equal 1, c[first_key]
263
- end
264
-
265
- def test_should_calculate_grouped_association_with_foreign_key_option
266
- Account.belongs_to :another_firm, :class_name => 'Firm', :foreign_key => 'firm_id'
267
- c = Account.count(:all, :group => :another_firm)
268
- assert_equal 1, c[companies(:first_firm)]
269
- assert_equal 2, c[companies(:rails_core)]
270
- assert_equal 1, c[companies(:first_client)]
271
- end
272
-
273
- def test_should_not_modify_options_when_using_includes
274
- options = {:conditions => 'companies.id > 1', :include => :firm}
275
- options_copy = options.dup
276
-
277
- Account.count(:all, options)
278
- assert_equal options_copy, options
279
- end
280
-
281
- def test_should_calculate_grouped_by_function
282
- c = Company.count(:all, :group => "UPPER(#{QUOTED_TYPE})")
283
- assert_equal 2, c[nil]
284
- assert_equal 1, c['DEPENDENTFIRM']
285
- assert_equal 4, c['CLIENT']
286
- assert_equal 2, c['FIRM']
287
- end
288
-
289
- def test_should_calculate_grouped_by_function_with_table_alias
290
- c = Company.count(:all, :group => "UPPER(companies.#{QUOTED_TYPE})")
291
- assert_equal 2, c[nil]
292
- assert_equal 1, c['DEPENDENTFIRM']
293
- assert_equal 4, c['CLIENT']
294
- assert_equal 2, c['FIRM']
295
- end
296
-
297
- def test_should_not_overshadow_enumerable_sum
298
- assert_equal 6, [1, 2, 3].sum(&:abs)
299
- end
300
-
301
- def test_should_sum_scoped_field
302
- assert_equal 15, companies(:rails_core).companies.sum(:id)
303
- end
304
-
305
- def test_should_sum_scoped_field_with_from
306
- assert_equal Club.count, Organization.clubs.count
307
- end
308
-
309
- def test_should_sum_scoped_field_with_conditions
310
- assert_equal 8, companies(:rails_core).companies.sum(:id, :conditions => 'id > 7')
311
- end
312
-
313
- def test_should_group_by_scoped_field
314
- c = companies(:rails_core).companies.sum(:id, :group => :name)
315
- assert_equal 7, c['Leetsoft']
316
- assert_equal 8, c['Jadedpixel']
317
- end
318
-
319
- def test_should_group_by_summed_field_through_association_and_having
320
- c = companies(:rails_core).companies.sum(:id, :group => :name,
321
- :having => 'sum(id) > 7')
322
- assert_nil c['Leetsoft']
323
- assert_equal 8, c['Jadedpixel']
324
- end
325
-
326
- def test_should_count_selected_field_with_include
327
- assert_equal 6, Account.count(:distinct => true, :include => :firm)
328
- assert_equal 4, Account.count(:distinct => true, :include => :firm, :select => :credit_limit)
329
- end
330
-
331
- def test_should_not_perform_joined_include_by_default
332
- assert_equal Account.count, Account.includes(:firm).count
333
- queries = assert_sql { Account.includes(:firm).count }
334
- assert_no_match(/join/i, queries.last)
335
- end
336
-
337
- def test_should_perform_joined_include_when_referencing_included_tables
338
- joined_count = Account.includes(:firm).where(:companies => {:name => '37signals'}).count
339
- assert_equal 1, joined_count
340
- end
341
-
342
- def test_should_count_scoped_select
343
- Account.update_all("credit_limit = NULL")
344
- assert_equal 0, Account.scoped(:select => "credit_limit").count
345
- end
346
-
347
- def test_should_count_scoped_select_with_options
348
- Account.update_all("credit_limit = NULL")
349
- Account.last.update_column('credit_limit', 49)
350
- Account.first.update_column('credit_limit', 51)
351
-
352
- assert_equal 1, Account.scoped(:select => "credit_limit").count(:conditions => ['credit_limit >= 50'])
353
- end
354
-
355
- def test_should_count_manual_select_with_include
356
- assert_equal 6, Account.count(:select => "DISTINCT accounts.id", :include => :firm)
357
- end
358
-
359
- def test_count_with_column_parameter
360
- assert_equal 5, Account.count(:firm_id)
361
- end
362
-
363
- def test_count_with_column_and_options_parameter
364
- assert_equal 2, Account.count(:firm_id, :conditions => "credit_limit = 50 AND firm_id IS NOT NULL")
365
- end
366
-
367
- def test_should_count_field_in_joined_table
368
- assert_equal 5, Account.count('companies.id', :joins => :firm)
369
- assert_equal 4, Account.count('companies.id', :joins => :firm, :distinct => true)
370
- end
371
-
372
- def test_should_count_field_in_joined_table_with_group_by
373
- c = Account.count('companies.id', :group => 'accounts.firm_id', :joins => :firm)
374
-
375
- [1,6,2,9].each { |firm_id| assert c.keys.include?(firm_id) }
376
- end
377
-
378
- def test_count_with_no_parameters_isnt_deprecated
379
- assert_not_deprecated { Account.count }
380
- end
381
-
382
- def test_count_with_too_many_parameters_raises
383
- assert_raise(ArgumentError) { Account.count(1, 2, 3) }
384
- end
385
-
386
- def test_should_sum_expression
387
- # Oracle adapter returns floating point value 636.0 after SUM
388
- if current_adapter?(:OracleAdapter)
389
- assert_equal 636, Account.sum("2 * credit_limit")
390
- else
391
- assert_equal 636, Account.sum("2 * credit_limit").to_i
392
- end
393
- end
394
-
395
- def test_count_with_from_option
396
- assert_equal Company.count(:all), Company.count(:all, :from => 'companies')
397
- assert_equal Account.count(:all, :conditions => "credit_limit = 50"),
398
- Account.count(:all, :from => 'accounts', :conditions => "credit_limit = 50")
399
- assert_equal Company.count(:type, :conditions => {:type => "Firm"}),
400
- Company.count(:type, :conditions => {:type => "Firm"}, :from => 'companies')
401
- end
402
-
403
- def test_sum_with_from_option
404
- assert_equal Account.sum(:credit_limit), Account.sum(:credit_limit, :from => 'accounts')
405
- assert_equal Account.sum(:credit_limit, :conditions => "credit_limit > 50"),
406
- Account.sum(:credit_limit, :from => 'accounts', :conditions => "credit_limit > 50")
407
- end
408
-
409
- def test_sum_array_compatibility
410
- assert_equal Account.sum(:credit_limit), Account.sum(&:credit_limit)
411
- end
412
-
413
- def test_average_with_from_option
414
- assert_equal Account.average(:credit_limit), Account.average(:credit_limit, :from => 'accounts')
415
- assert_equal Account.average(:credit_limit, :conditions => "credit_limit > 50"),
416
- Account.average(:credit_limit, :from => 'accounts', :conditions => "credit_limit > 50")
417
- end
418
-
419
- def test_minimum_with_from_option
420
- assert_equal Account.minimum(:credit_limit), Account.minimum(:credit_limit, :from => 'accounts')
421
- assert_equal Account.minimum(:credit_limit, :conditions => "credit_limit > 50"),
422
- Account.minimum(:credit_limit, :from => 'accounts', :conditions => "credit_limit > 50")
423
- end
424
-
425
- def test_maximum_with_from_option
426
- assert_equal Account.maximum(:credit_limit), Account.maximum(:credit_limit, :from => 'accounts')
427
- assert_equal Account.maximum(:credit_limit, :conditions => "credit_limit > 50"),
428
- Account.maximum(:credit_limit, :from => 'accounts', :conditions => "credit_limit > 50")
429
- end
430
-
431
- def test_from_option_with_specified_index
432
- if Edge.connection.adapter_name == 'MySQL' or Edge.connection.adapter_name == 'Mysql2'
433
- assert_equal Edge.count(:all), Edge.count(:all, :from => 'edges USE INDEX(unique_edge_index)')
434
- assert_equal Edge.count(:all, :conditions => 'sink_id < 5'),
435
- Edge.count(:all, :from => 'edges USE INDEX(unique_edge_index)', :conditions => 'sink_id < 5')
436
- end
437
- end
438
-
439
- def test_from_option_with_table_different_than_class
440
- assert_equal Account.count(:all), Company.count(:all, :from => 'accounts')
441
- end
442
-
443
- def test_distinct_is_honored_when_used_with_count_operation_after_group
444
- # Count the number of authors for approved topics
445
- approved_topics_count = Topic.group(:approved).count(:author_name)[true]
446
- assert_equal approved_topics_count, 3
447
- # Count the number of distinct authors for approved Topics
448
- distinct_authors_for_approved_count = Topic.group(:approved).count(:author_name, :distinct => true)[true]
449
- assert_equal distinct_authors_for_approved_count, 2
450
- end
451
-
452
- def test_pluck
453
- assert_equal [1,2,3,4], Topic.order(:id).pluck(:id)
454
- end
455
-
456
- def test_pluck_type_cast
457
- topic = topics(:first)
458
- relation = Topic.where(:id => topic.id)
459
- assert_equal [ topic.approved ], relation.pluck(:approved)
460
- assert_equal [ topic.last_read ], relation.pluck(:last_read)
461
- assert_equal [ topic.written_on ], relation.pluck(:written_on)
462
- end
463
-
464
- def test_pluck_and_uniq
465
- assert_equal [50, 53, 55, 60], Account.order(:credit_limit).uniq.pluck(:credit_limit)
466
- end
467
-
468
- def test_pluck_in_relation
469
- company = Company.first
470
- contract = company.contracts.create!
471
- assert_equal [contract.id], company.contracts.pluck(:id)
472
- end
473
-
474
- def test_pluck_with_serialization
475
- t = Topic.create!(:content => { :foo => :bar })
476
- assert_equal [{:foo => :bar}], Topic.where(:id => t.id).pluck(:content)
477
- end
478
-
479
- def test_pluck_with_qualified_column_name
480
- assert_equal [1,2,3,4], Topic.order(:id).pluck("topics.id")
481
- end
482
- end
1
+ require "cases/helper"
2
+ require 'models/club'
3
+ require 'models/company'
4
+ require "models/contract"
5
+ require 'models/edge'
6
+ require 'models/organization'
7
+ require 'models/possession'
8
+ require 'models/topic'
9
+ require 'models/reply'
10
+ require 'models/minivan'
11
+ require 'models/speedometer'
12
+ require 'models/ship_part'
13
+ require 'models/treasure'
14
+ require 'models/developer'
15
+ require 'models/comment'
16
+ require 'models/rating'
17
+ require 'models/post'
18
+
19
+ class NumericData < ActiveRecord::Base
20
+ self.table_name = 'numeric_data'
21
+
22
+ attribute :world_population, Type::Integer.new
23
+ attribute :my_house_population, Type::Integer.new
24
+ attribute :atoms_in_universe, Type::Integer.new
25
+ end
26
+
27
+ class CalculationsTest < ActiveRecord::TestCase
28
+ fixtures :companies, :accounts, :topics, :speedometers, :minivans
29
+
30
+ def test_should_sum_field
31
+ assert_equal 318, Account.sum(:credit_limit)
32
+ end
33
+
34
+ def test_should_average_field
35
+ value = Account.average(:credit_limit)
36
+ assert_equal 53.0, value
37
+ end
38
+
39
+ def test_should_resolve_aliased_attributes
40
+ assert_equal 318, Account.sum(:available_credit)
41
+ end
42
+
43
+ def test_should_return_decimal_average_of_integer_field
44
+ return if current_adapter?(:IBM_DBAdapter) #average cannot be a decimal value when applied on integer field
45
+ value = Account.average(:id)
46
+ assert_equal 3.5, value
47
+ end
48
+
49
+ def test_should_return_integer_average_if_db_returns_such
50
+ ShipPart.delete_all
51
+ ShipPart.create!(:id => 3, :name => 'foo')
52
+ value = ShipPart.average(:id)
53
+ assert_equal 3, value
54
+ end
55
+
56
+ def test_should_return_nil_as_average
57
+ assert_nil NumericData.average(:bank_balance)
58
+ end
59
+
60
+ def test_should_get_maximum_of_field
61
+ assert_equal 60, Account.maximum(:credit_limit)
62
+ end
63
+
64
+ def test_should_get_maximum_of_field_with_include
65
+ assert_equal 55, Account.where("companies.name != 'Summit'").references(:companies).includes(:firm).maximum(:credit_limit)
66
+ end
67
+
68
+ def test_should_get_minimum_of_field
69
+ assert_equal 50, Account.minimum(:credit_limit)
70
+ end
71
+
72
+ def test_should_group_by_field
73
+ c = Account.group(:firm_id).sum(:credit_limit)
74
+ [1,6,2].each do |firm_id|
75
+ assert c.keys.include?(firm_id), "Group #{c.inspect} does not contain firm_id #{firm_id}"
76
+ end
77
+ end
78
+
79
+ def test_should_group_by_arel_attribute
80
+ c = Account.group(Account.arel_table[:firm_id]).sum(:credit_limit)
81
+ [1,6,2].each do |firm_id|
82
+ assert c.keys.include?(firm_id), "Group #{c.inspect} does not contain firm_id #{firm_id}"
83
+ end
84
+ end
85
+
86
+ def test_should_group_by_multiple_fields
87
+ c = Account.group('firm_id', :credit_limit).count(:all)
88
+ [ [nil, 50], [1, 50], [6, 50], [6, 55], [9, 53], [2, 60] ].each { |firm_and_limit| assert c.keys.include?(firm_and_limit) }
89
+ end
90
+
91
+ def test_should_group_by_multiple_fields_having_functions
92
+ c = Topic.group(:author_name, 'COALESCE(type, title)').count(:all)
93
+ assert_equal 1, c[["Carl", "The Third Topic of the day"]]
94
+ assert_equal 1, c[["Mary", "Reply"]]
95
+ assert_equal 1, c[["David", "The First Topic"]]
96
+ assert_equal 1, c[["Carl", "Reply"]]
97
+ end
98
+
99
+ def test_should_group_by_summed_field
100
+ c = Account.group(:firm_id).sum(:credit_limit)
101
+ assert_equal 50, c[1]
102
+ assert_equal 105, c[6]
103
+ assert_equal 60, c[2]
104
+ end
105
+
106
+ def test_should_order_by_grouped_field
107
+ c = Account.group(:firm_id).order("firm_id").sum(:credit_limit)
108
+ assert_equal [1, 2, 6, 9], c.keys.compact
109
+ end
110
+
111
+ def test_should_order_by_calculation
112
+ c = Account.group(:firm_id).order("sum_credit_limit desc, firm_id").sum(:credit_limit)
113
+ assert_equal [105, 60, 53, 50, 50], c.keys.collect { |k| c[k] }
114
+ assert_equal [6, 2, 9, 1], c.keys.compact
115
+ end
116
+
117
+ def test_should_limit_calculation
118
+ c = Account.where("firm_id IS NOT NULL").group(:firm_id).order("firm_id").limit(2).sum(:credit_limit)
119
+ assert_equal [1, 2], c.keys.compact
120
+ end
121
+
122
+ def test_should_limit_calculation_with_offset
123
+ c = Account.where("firm_id IS NOT NULL").group(:firm_id).order("firm_id").
124
+ limit(2).offset(1).sum(:credit_limit)
125
+ assert_equal [2, 6], c.keys.compact
126
+ end
127
+
128
+ def test_limit_should_apply_before_count
129
+ accounts = Account.limit(3).where('firm_id IS NOT NULL')
130
+
131
+ assert_equal 3, accounts.count(:firm_id)
132
+ assert_equal 3, accounts.select(:firm_id).count
133
+ end
134
+
135
+ def test_count_should_shortcut_with_limit_zero
136
+ accounts = Account.limit(0)
137
+
138
+ assert_no_queries { assert_equal 0, accounts.count }
139
+ end
140
+
141
+ def test_limit_is_kept
142
+ return if current_adapter?(:OracleAdapter) || current_adapter?(:IBM_DBAdapter)
143
+
144
+ queries = assert_sql { Account.limit(1).count }
145
+ assert_equal 1, queries.length
146
+ assert_match(/LIMIT/, queries.first)
147
+ end
148
+
149
+ def test_offset_is_kept
150
+ return if current_adapter?(:OracleAdapter) || current_adapter?(:IBM_DBAdapter)
151
+
152
+ queries = assert_sql { Account.offset(1).count }
153
+ assert_equal 1, queries.length
154
+ assert_match(/OFFSET/, queries.first)
155
+ end
156
+
157
+ def test_limit_with_offset_is_kept
158
+ return if current_adapter?(:OracleAdapter) || current_adapter?(:IBM_DBAdapter)
159
+
160
+ queries = assert_sql { Account.limit(1).offset(1).count }
161
+ assert_equal 1, queries.length
162
+ assert_match(/LIMIT/, queries.first)
163
+ assert_match(/OFFSET/, queries.first)
164
+ end
165
+
166
+ def test_no_limit_no_offset
167
+ queries = assert_sql { Account.count }
168
+ assert_equal 1, queries.length
169
+ assert_no_match(/LIMIT/, queries.first)
170
+ assert_no_match(/OFFSET/, queries.first)
171
+ end
172
+
173
+ def test_count_on_invalid_columns_raises
174
+ e = assert_raises(ActiveRecord::StatementInvalid) {
175
+ Account.select("credit_limit, firm_name").count
176
+ }
177
+
178
+ assert_match %r{accounts}i, e.message
179
+ assert_match "credit_limit, firm_name", e.message
180
+ end
181
+
182
+ def test_should_group_by_summed_field_having_condition
183
+ c = Account.group(:firm_id).having('sum(credit_limit) > 50').sum(:credit_limit)
184
+ assert_nil c[1]
185
+ assert_equal 105, c[6]
186
+ assert_equal 60, c[2]
187
+ end
188
+
189
+ def test_should_group_by_summed_field_having_condition_from_select
190
+ c = Account.select("MIN(credit_limit) AS min_credit_limit").group(:firm_id).having("MIN(credit_limit) > 50").sum(:credit_limit)
191
+ assert_nil c[1]
192
+ assert_equal 60, c[2]
193
+ assert_equal 53, c[9]
194
+ end
195
+
196
+ def test_should_group_by_summed_association
197
+ c = Account.group(:firm).sum(:credit_limit)
198
+ assert_equal 50, c[companies(:first_firm)]
199
+ assert_equal 105, c[companies(:rails_core)]
200
+ assert_equal 60, c[companies(:first_client)]
201
+ end
202
+
203
+ def test_should_sum_field_with_conditions
204
+ assert_equal 105, Account.where('firm_id = 6').sum(:credit_limit)
205
+ end
206
+
207
+ def test_should_return_zero_if_sum_conditions_return_nothing
208
+ assert_equal 0, Account.where('1 = 2').sum(:credit_limit)
209
+ assert_equal 0, companies(:rails_core).companies.where('1 = 2').sum(:id)
210
+ end
211
+
212
+ def test_sum_should_return_valid_values_for_decimals
213
+ NumericData.create(:bank_balance => 19.83)
214
+ assert_equal 19.83, NumericData.sum(:bank_balance)
215
+ end
216
+
217
+ def test_should_return_type_casted_values_with_group_and_expression
218
+ assert_equal 0.5, Account.group(:firm_name).sum('0.01 * credit_limit')['37signals']
219
+ end
220
+
221
+ def test_should_group_by_summed_field_with_conditions
222
+ c = Account.where('firm_id > 1').group(:firm_id).sum(:credit_limit)
223
+ assert_nil c[1]
224
+ assert_equal 105, c[6]
225
+ assert_equal 60, c[2]
226
+ end
227
+
228
+ def test_should_group_by_summed_field_with_conditions_and_having
229
+ c = Account.where('firm_id > 1').group(:firm_id).
230
+ having('sum(credit_limit) > 60').sum(:credit_limit)
231
+ assert_nil c[1]
232
+ assert_equal 105, c[6]
233
+ assert_nil c[2]
234
+ end
235
+
236
+ def test_should_group_by_fields_with_table_alias
237
+ c = Account.group('accounts.firm_id').sum(:credit_limit)
238
+ assert_equal 50, c[1]
239
+ assert_equal 105, c[6]
240
+ assert_equal 60, c[2]
241
+ end
242
+
243
+ def test_should_calculate_with_invalid_field
244
+ assert_equal 6, Account.calculate(:count, '*')
245
+ assert_equal 6, Account.calculate(:count, :all)
246
+ end
247
+
248
+ def test_should_calculate_grouped_with_invalid_field
249
+ c = Account.group('accounts.firm_id').count(:all)
250
+ assert_equal 1, c[1]
251
+ assert_equal 2, c[6]
252
+ assert_equal 1, c[2]
253
+ end
254
+
255
+ def test_should_calculate_grouped_association_with_invalid_field
256
+ c = Account.group(:firm).count(:all)
257
+ assert_equal 1, c[companies(:first_firm)]
258
+ assert_equal 2, c[companies(:rails_core)]
259
+ assert_equal 1, c[companies(:first_client)]
260
+ end
261
+
262
+ def test_should_group_by_association_with_non_numeric_foreign_key
263
+ Speedometer.create! id: 'ABC'
264
+ Minivan.create! id: 'OMG', speedometer_id: 'ABC'
265
+
266
+ c = Minivan.group(:speedometer).count(:all)
267
+ first_key = c.keys.first
268
+ assert_equal Speedometer, first_key.class
269
+ assert_equal 1, c[first_key]
270
+ end
271
+
272
+ def test_should_calculate_grouped_association_with_foreign_key_option
273
+ Account.belongs_to :another_firm, :class_name => 'Firm', :foreign_key => 'firm_id'
274
+ c = Account.group(:another_firm).count(:all)
275
+ assert_equal 1, c[companies(:first_firm)]
276
+ assert_equal 2, c[companies(:rails_core)]
277
+ assert_equal 1, c[companies(:first_client)]
278
+ end
279
+
280
+ def test_should_calculate_grouped_by_function
281
+ c = Company.group("UPPER(#{QUOTED_TYPE})").count(:all)
282
+ assert_equal 2, c[nil]
283
+ assert_equal 1, c['DEPENDENTFIRM']
284
+ assert_equal 5, c['CLIENT']
285
+ assert_equal 2, c['FIRM']
286
+ end
287
+
288
+ def test_should_calculate_grouped_by_function_with_table_alias
289
+ c = Company.group("UPPER(companies.#{QUOTED_TYPE})").count(:all)
290
+ assert_equal 2, c[nil]
291
+ assert_equal 1, c['DEPENDENTFIRM']
292
+ assert_equal 5, c['CLIENT']
293
+ assert_equal 2, c['FIRM']
294
+ end
295
+
296
+ def test_should_not_overshadow_enumerable_sum
297
+ assert_equal 6, [1, 2, 3].sum(&:abs)
298
+ end
299
+
300
+ def test_should_sum_scoped_field
301
+ assert_equal 15, companies(:rails_core).companies.sum(:id)
302
+ end
303
+
304
+ def test_should_sum_scoped_field_with_from
305
+ assert_equal Club.count, Organization.clubs.count
306
+ end
307
+
308
+ def test_should_sum_scoped_field_with_conditions
309
+ assert_equal 8, companies(:rails_core).companies.where('id > 7').sum(:id)
310
+ end
311
+
312
+ def test_should_group_by_scoped_field
313
+ c = companies(:rails_core).companies.group(:name).sum(:id)
314
+ assert_equal 7, c['Leetsoft']
315
+ assert_equal 8, c['Jadedpixel']
316
+ end
317
+
318
+ def test_should_group_by_summed_field_through_association_and_having
319
+ c = companies(:rails_core).companies.group(:name).having('sum(id) > 7').sum(:id)
320
+ assert_nil c['Leetsoft']
321
+ assert_equal 8, c['Jadedpixel']
322
+ end
323
+
324
+ def test_should_count_selected_field_with_include
325
+ assert_equal 6, Account.includes(:firm).distinct.count
326
+ assert_equal 4, Account.includes(:firm).distinct.select(:credit_limit).count
327
+ end
328
+
329
+ def test_should_not_perform_joined_include_by_default
330
+ assert_equal Account.count, Account.includes(:firm).count
331
+ queries = assert_sql { Account.includes(:firm).count }
332
+ assert_no_match(/join/i, queries.last)
333
+ end
334
+
335
+ def test_should_perform_joined_include_when_referencing_included_tables
336
+ joined_count = Account.includes(:firm).where(:companies => {:name => '37signals'}).count
337
+ assert_equal 1, joined_count
338
+ end
339
+
340
+ def test_should_count_scoped_select
341
+ Account.update_all("credit_limit = NULL")
342
+ assert_equal 0, Account.select("credit_limit").count
343
+ end
344
+
345
+ def test_should_count_scoped_select_with_options
346
+ Account.update_all("credit_limit = NULL")
347
+ Account.last.update_columns('credit_limit' => 49)
348
+ Account.first.update_columns('credit_limit' => 51)
349
+
350
+ assert_equal 1, Account.select("credit_limit").where('credit_limit >= 50').count
351
+ end
352
+
353
+ def test_should_count_manual_select_with_include
354
+ assert_equal 6, Account.select("DISTINCT accounts.id").includes(:firm).count
355
+ end
356
+
357
+ def test_count_with_column_parameter
358
+ assert_equal 5, Account.count(:firm_id)
359
+ end
360
+
361
+ def test_count_with_distinct
362
+ assert_equal 4, Account.select(:credit_limit).distinct.count
363
+ assert_equal 4, Account.select(:credit_limit).uniq.count
364
+ end
365
+
366
+ def test_count_with_aliased_attribute
367
+ assert_equal 6, Account.count(:available_credit)
368
+ end
369
+
370
+ def test_count_with_column_and_options_parameter
371
+ assert_equal 2, Account.where("credit_limit = 50 AND firm_id IS NOT NULL").count(:firm_id)
372
+ end
373
+
374
+ def test_should_count_field_in_joined_table
375
+ assert_equal 5, Account.joins(:firm).count('companies.id')
376
+ assert_equal 4, Account.joins(:firm).distinct.count('companies.id')
377
+ end
378
+
379
+ def test_should_count_field_in_joined_table_with_group_by
380
+ c = Account.group('accounts.firm_id').joins(:firm).count('companies.id')
381
+
382
+ [1,6,2,9].each { |firm_id| assert c.keys.include?(firm_id) }
383
+ end
384
+
385
+ def test_count_with_no_parameters_isnt_deprecated
386
+ assert_not_deprecated { Account.count }
387
+ end
388
+
389
+ def test_count_with_too_many_parameters_raises
390
+ assert_raise(ArgumentError) { Account.count(1, 2, 3) }
391
+ end
392
+
393
+ def test_count_with_order
394
+ assert_equal 6, Account.order(:credit_limit).count
395
+ end
396
+
397
+ def test_count_with_reverse_order
398
+ assert_equal 6, Account.order(:credit_limit).reverse_order.count
399
+ end
400
+
401
+ def test_count_with_where_and_order
402
+ assert_equal 1, Account.where(firm_name: '37signals').count
403
+ assert_equal 1, Account.where(firm_name: '37signals').order(:firm_name).count
404
+ assert_equal 1, Account.where(firm_name: '37signals').order(:firm_name).reverse_order.count
405
+ end
406
+
407
+ def test_should_sum_expression
408
+ # Oracle adapter returns floating point value 636.0 after SUM
409
+ if current_adapter?(:OracleAdapter)
410
+ assert_equal 636, Account.sum("2 * credit_limit")
411
+ else
412
+ assert_equal 636, Account.sum("2 * credit_limit").to_i
413
+ end
414
+ end
415
+
416
+ def test_sum_expression_returns_zero_when_no_records_to_sum
417
+ assert_equal 0, Account.where('1 = 2').sum("2 * credit_limit")
418
+ end
419
+
420
+ def test_count_with_from_option
421
+ assert_equal Company.count(:all), Company.from('companies').count(:all)
422
+ assert_equal Account.where("credit_limit = 50").count(:all),
423
+ Account.from('accounts').where("credit_limit = 50").count(:all)
424
+ assert_equal Company.where(:type => "Firm").count(:type),
425
+ Company.where(:type => "Firm").from('companies').count(:type)
426
+ end
427
+
428
+ def test_sum_with_from_option
429
+ assert_equal Account.sum(:credit_limit), Account.from('accounts').sum(:credit_limit)
430
+ assert_equal Account.where("credit_limit > 50").sum(:credit_limit),
431
+ Account.where("credit_limit > 50").from('accounts').sum(:credit_limit)
432
+ end
433
+
434
+ def test_average_with_from_option
435
+ assert_equal Account.average(:credit_limit), Account.from('accounts').average(:credit_limit)
436
+ assert_equal Account.where("credit_limit > 50").average(:credit_limit),
437
+ Account.where("credit_limit > 50").from('accounts').average(:credit_limit)
438
+ end
439
+
440
+ def test_minimum_with_from_option
441
+ assert_equal Account.minimum(:credit_limit), Account.from('accounts').minimum(:credit_limit)
442
+ assert_equal Account.where("credit_limit > 50").minimum(:credit_limit),
443
+ Account.where("credit_limit > 50").from('accounts').minimum(:credit_limit)
444
+ end
445
+
446
+ def test_maximum_with_from_option
447
+ assert_equal Account.maximum(:credit_limit), Account.from('accounts').maximum(:credit_limit)
448
+ assert_equal Account.where("credit_limit > 50").maximum(:credit_limit),
449
+ Account.where("credit_limit > 50").from('accounts').maximum(:credit_limit)
450
+ end
451
+
452
+ def test_maximum_with_not_auto_table_name_prefix_if_column_included
453
+ Company.create!(:name => "test", :contracts => [Contract.new(:developer_id => 7)])
454
+
455
+ assert_equal 7, Company.includes(:contracts).maximum(:developer_id)
456
+ end
457
+
458
+ def test_minimum_with_not_auto_table_name_prefix_if_column_included
459
+ Company.create!(:name => "test", :contracts => [Contract.new(:developer_id => 7)])
460
+
461
+ assert_equal 7, Company.includes(:contracts).minimum(:developer_id)
462
+ end
463
+
464
+ def test_sum_with_not_auto_table_name_prefix_if_column_included
465
+ Company.create!(:name => "test", :contracts => [Contract.new(:developer_id => 7)])
466
+
467
+ assert_equal 7, Company.includes(:contracts).sum(:developer_id)
468
+ end
469
+
470
+ def test_from_option_with_specified_index
471
+ if Edge.connection.adapter_name == 'MySQL' or Edge.connection.adapter_name == 'Mysql2'
472
+ assert_equal Edge.count(:all), Edge.from('edges USE INDEX(unique_edge_index)').count(:all)
473
+ assert_equal Edge.where('sink_id < 5').count(:all),
474
+ Edge.from('edges USE INDEX(unique_edge_index)').where('sink_id < 5').count(:all)
475
+ end
476
+ end
477
+
478
+ def test_from_option_with_table_different_than_class
479
+ assert_equal Account.count(:all), Company.from('accounts').count(:all)
480
+ end
481
+
482
+ def test_distinct_is_honored_when_used_with_count_operation_after_group
483
+ # Count the number of authors for approved topics
484
+ approved_topics_count = Topic.group(:approved).count(:author_name)[true]
485
+ assert_equal approved_topics_count, 4
486
+ # Count the number of distinct authors for approved Topics
487
+ distinct_authors_for_approved_count = Topic.group(:approved).distinct.count(:author_name)[true]
488
+ assert_equal distinct_authors_for_approved_count, 3
489
+ end
490
+
491
+ def test_pluck
492
+ assert_equal [1,2,3,4,5], Topic.order(:id).pluck(:id)
493
+ end
494
+
495
+ def test_pluck_without_column_names
496
+ assert_equal [[1, "Firm", 1, nil, "37signals", nil, 1, nil, ""]],
497
+ Company.order(:id).limit(1).pluck
498
+ end
499
+
500
+ def test_pluck_type_cast
501
+ topic = topics(:first)
502
+ relation = Topic.where(:id => topic.id)
503
+ assert_equal [ topic.approved ], relation.pluck(:approved)
504
+ assert_equal [ topic.last_read ], relation.pluck(:last_read)
505
+ assert_equal [ topic.written_on ], relation.pluck(:written_on)
506
+ end
507
+
508
+ def test_pluck_and_uniq
509
+ assert_equal [50, 53, 55, 60], Account.order(:credit_limit).uniq.pluck(:credit_limit)
510
+ end
511
+
512
+ def test_pluck_in_relation
513
+ company = Company.first
514
+ contract = company.contracts.create!
515
+ assert_equal [contract.id], company.contracts.pluck(:id)
516
+ end
517
+
518
+ def test_pluck_on_aliased_attribute
519
+ assert_equal 'The First Topic', Topic.order(:id).pluck(:heading).first
520
+ end
521
+
522
+ def test_pluck_with_serialization
523
+ t = Topic.create!(:content => { :foo => :bar })
524
+ assert_equal [{:foo => :bar}], Topic.where(:id => t.id).pluck(:content)
525
+ end
526
+
527
+ def test_pluck_with_qualified_column_name
528
+ assert_equal [1,2,3,4,5], Topic.order(:id).pluck("topics.id")
529
+ end
530
+
531
+ def test_pluck_auto_table_name_prefix
532
+ c = Company.create!(:name => "test", :contracts => [Contract.new])
533
+ assert_equal [c.id], Company.joins(:contracts).pluck(:id)
534
+ end
535
+
536
+ def test_pluck_if_table_included
537
+ c = Company.create!(:name => "test", :contracts => [Contract.new(:developer_id => 7)])
538
+ assert_equal [c.id], Company.includes(:contracts).where("contracts.id" => c.contracts.first).pluck(:id)
539
+ end
540
+
541
+ def test_pluck_not_auto_table_name_prefix_if_column_joined
542
+ Company.create!(:name => "test", :contracts => [Contract.new(:developer_id => 7)])
543
+ assert_equal [7], Company.joins(:contracts).pluck(:developer_id)
544
+ end
545
+
546
+ def test_pluck_with_selection_clause
547
+ assert_equal [50, 53, 55, 60], Account.pluck('DISTINCT credit_limit').sort
548
+ assert_equal [50, 53, 55, 60], Account.pluck('DISTINCT accounts.credit_limit').sort
549
+ assert_equal [50, 53, 55, 60], Account.pluck('DISTINCT(credit_limit)').sort
550
+
551
+ # MySQL returns "SUM(DISTINCT(credit_limit))" as the column name unless
552
+ # an alias is provided. Without the alias, the column cannot be found
553
+ # and properly typecast.
554
+ assert_equal [50 + 53 + 55 + 60], Account.pluck('SUM(DISTINCT(credit_limit)) as credit_limit')
555
+ end
556
+
557
+ def test_plucks_with_ids
558
+ assert_equal Company.all.map(&:id).sort, Company.ids.sort
559
+ end
560
+
561
+ def test_pluck_with_includes_limit_and_empty_result
562
+ assert_equal [], Topic.includes(:replies).limit(0).pluck(:id)
563
+ assert_equal [], Topic.includes(:replies).limit(1).where('0 = 1').pluck(:id)
564
+ end
565
+
566
+ def test_pluck_not_auto_table_name_prefix_if_column_included
567
+ Company.create!(:name => "test", :contracts => [Contract.new(:developer_id => 7)])
568
+ ids = Company.includes(:contracts).pluck(:developer_id)
569
+ assert_equal Company.count, ids.length
570
+ assert_equal [7], ids.compact
571
+ end
572
+
573
+ def test_pluck_multiple_columns
574
+ assert_equal [
575
+ [1, "The First Topic"], [2, "The Second Topic of the day"],
576
+ [3, "The Third Topic of the day"], [4, "The Fourth Topic of the day"],
577
+ [5, "The Fifth Topic of the day"]
578
+ ], Topic.order(:id).pluck(:id, :title)
579
+ assert_equal [
580
+ [1, "The First Topic", "David"], [2, "The Second Topic of the day", "Mary"],
581
+ [3, "The Third Topic of the day", "Carl"], [4, "The Fourth Topic of the day", "Carl"],
582
+ [5, "The Fifth Topic of the day", "Jason"]
583
+ ], Topic.order(:id).pluck(:id, :title, :author_name)
584
+ end
585
+
586
+ def test_pluck_with_multiple_columns_and_selection_clause
587
+ assert_equal [[1, 50], [2, 50], [3, 50], [4, 60], [5, 55], [6, 53]],
588
+ Account.pluck('id, credit_limit')
589
+ end
590
+
591
+ def test_pluck_with_multiple_columns_and_includes
592
+ Company.create!(:name => "test", :contracts => [Contract.new(:developer_id => 7)])
593
+ companies_and_developers = Company.order('companies.id').includes(:contracts).pluck(:name, :developer_id)
594
+
595
+ assert_equal Company.count, companies_and_developers.length
596
+ assert_equal ["37signals", nil], companies_and_developers.first
597
+ assert_equal ["test", 7], companies_and_developers.last
598
+ end
599
+
600
+ def test_pluck_with_reserved_words
601
+ Possession.create!(:where => "Over There")
602
+
603
+ assert_equal ["Over There"], Possession.pluck(:where)
604
+ end
605
+
606
+ def test_pluck_replaces_select_clause
607
+ taks_relation = Topic.select(:approved, :id).order(:id)
608
+ assert_equal [1,2,3,4,5], taks_relation.pluck(:id)
609
+ assert_equal [false, true, true, true, true], taks_relation.pluck(:approved)
610
+ end
611
+
612
+ def test_pluck_columns_with_same_name
613
+ expected = [["The First Topic", "The Second Topic of the day"], ["The Third Topic of the day", "The Fourth Topic of the day"]]
614
+ actual = Topic.joins(:replies)
615
+ .pluck('topics.title', 'replies_topics.title')
616
+ assert_equal expected, actual
617
+ end
618
+
619
+ def test_calculation_with_polymorphic_relation
620
+ part = ShipPart.create!(name: "has trinket")
621
+ part.trinkets.create!
622
+
623
+ assert_equal part.id, ShipPart.joins(:trinkets).sum(:id)
624
+ end
625
+
626
+ def test_pluck_joined_with_polymorphic_relation
627
+ part = ShipPart.create!(name: "has trinket")
628
+ part.trinkets.create!
629
+
630
+ assert_equal [part.id], ShipPart.joins(:trinkets).pluck(:id)
631
+ end
632
+
633
+ def test_grouped_calculation_with_polymorphic_relation
634
+ part = ShipPart.create!(name: "has trinket")
635
+ part.trinkets.create!
636
+
637
+ assert_equal({ "has trinket" => part.id }, ShipPart.joins(:trinkets).group("ship_parts.name").sum(:id))
638
+ end
639
+
640
+ def test_should_reference_correct_aliases_while_joining_tables_of_has_many_through_association
641
+ assert_nothing_raised ActiveRecord::StatementInvalid do
642
+ developer = Developer.create!(name: 'developer')
643
+ developer.ratings.includes(comment: :post).where(posts: { id: 1 }).count
644
+ end
645
+ end
646
+ end