ibm_db 5.6.1 → 5.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (592) hide show
  1. checksums.yaml +4 -4
  2. data/ext/Makefile +13 -9
  3. data/ext/extconf.rb +176 -110
  4. data/ext/ibm_db.c +60 -0
  5. data/ext/ibm_db.o +0 -0
  6. data/ext/ibm_db.so +0 -0
  7. data/ext/mkmf.log +6 -6
  8. data/ext/ruby_ibm_db_cli.c +14 -10
  9. data/ext/ruby_ibm_db_cli.h +4 -0
  10. data/ext/ruby_ibm_db_cli.o +0 -0
  11. data/lib/IBM_DB.rb +2 -2
  12. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +1254 -277
  13. data/test/active_record/connection_adapters/fake_legacy_adapter.rb +17 -0
  14. data/test/active_record/connection_adapters/fake_misleading_legacy_adapter.rb +8 -0
  15. data/test/activejob/destroy_association_async_job_test.rb +62 -0
  16. data/test/activejob/destroy_association_async_test.rb +147 -11
  17. data/test/activejob/job_runtime_test.rb +41 -0
  18. data/test/activejob/unloadable_base_job.rb +3 -0
  19. data/test/cases/active_record_schema_test.rb +196 -0
  20. data/test/cases/active_record_test.rb +21 -0
  21. data/test/cases/adapter_prevent_writes_test.rb +26 -202
  22. data/test/cases/adapter_test.rb +592 -82
  23. data/test/cases/adapters/abstract_mysql_adapter/active_schema_test.rb +210 -0
  24. data/test/cases/adapters/abstract_mysql_adapter/adapter_prevent_writes_test.rb +111 -0
  25. data/test/cases/adapters/abstract_mysql_adapter/auto_increment_test.rb +48 -0
  26. data/test/cases/adapters/abstract_mysql_adapter/bind_parameter_test.rb +91 -0
  27. data/test/cases/adapters/abstract_mysql_adapter/case_sensitivity_test.rb +65 -0
  28. data/test/cases/adapters/abstract_mysql_adapter/charset_collation_test.rb +85 -0
  29. data/test/cases/adapters/abstract_mysql_adapter/connection_test.rb +267 -0
  30. data/test/cases/adapters/abstract_mysql_adapter/count_deleted_rows_with_lock_test.rb +29 -0
  31. data/test/cases/adapters/abstract_mysql_adapter/json_test.rb +24 -0
  32. data/test/cases/adapters/abstract_mysql_adapter/mysql_boolean_test.rb +102 -0
  33. data/test/cases/adapters/abstract_mysql_adapter/mysql_enum_test.rb +47 -0
  34. data/test/cases/adapters/abstract_mysql_adapter/mysql_explain_test.rb +71 -0
  35. data/test/cases/adapters/abstract_mysql_adapter/nested_deadlock_test.rb +191 -0
  36. data/test/cases/adapters/abstract_mysql_adapter/optimizer_hints_test.rb +69 -0
  37. data/test/cases/adapters/abstract_mysql_adapter/quoting_test.rb +49 -0
  38. data/test/cases/adapters/abstract_mysql_adapter/schema_migrations_test.rb +68 -0
  39. data/test/cases/adapters/abstract_mysql_adapter/schema_test.rb +130 -0
  40. data/test/cases/adapters/abstract_mysql_adapter/set_test.rb +32 -0
  41. data/test/cases/adapters/abstract_mysql_adapter/sp_test.rb +39 -0
  42. data/test/cases/adapters/abstract_mysql_adapter/sql_types_test.rb +16 -0
  43. data/test/cases/adapters/abstract_mysql_adapter/table_options_test.rb +125 -0
  44. data/test/cases/adapters/abstract_mysql_adapter/transaction_test.rb +204 -0
  45. data/test/cases/adapters/abstract_mysql_adapter/unsigned_type_test.rb +77 -0
  46. data/test/cases/adapters/abstract_mysql_adapter/virtual_column_test.rb +69 -0
  47. data/test/cases/adapters/abstract_mysql_adapter/warnings_test.rb +109 -0
  48. data/test/cases/adapters/mysql2/check_constraint_quoting_test.rb +35 -0
  49. data/test/cases/adapters/mysql2/dbconsole_test.rb +87 -0
  50. data/test/cases/adapters/mysql2/mysql2_adapter_test.rb +136 -10
  51. data/test/cases/adapters/mysql2/mysql2_rake_test.rb +433 -0
  52. data/test/cases/adapters/postgresql/active_schema_test.rb +8 -4
  53. data/test/cases/adapters/postgresql/array_test.rb +6 -6
  54. data/test/cases/adapters/postgresql/bind_parameter_test.rb +52 -0
  55. data/test/cases/adapters/postgresql/bit_string_test.rb +2 -2
  56. data/test/cases/adapters/postgresql/bytea_test.rb +3 -3
  57. data/test/cases/adapters/postgresql/case_insensitive_test.rb +1 -1
  58. data/test/cases/adapters/postgresql/change_schema_test.rb +32 -1
  59. data/test/cases/adapters/postgresql/cidr_test.rb +17 -0
  60. data/test/cases/adapters/postgresql/citext_test.rb +7 -1
  61. data/test/cases/adapters/postgresql/collation_test.rb +1 -1
  62. data/test/cases/adapters/postgresql/composite_test.rb +1 -1
  63. data/test/cases/adapters/postgresql/connection_test.rb +43 -36
  64. data/test/cases/adapters/postgresql/create_unlogged_tables_test.rb +3 -2
  65. data/test/cases/adapters/postgresql/datatype_test.rb +9 -4
  66. data/test/cases/adapters/postgresql/date_test.rb +2 -2
  67. data/test/cases/adapters/postgresql/dbconsole_test.rb +109 -0
  68. data/test/cases/adapters/postgresql/deferred_constraints_test.rb +55 -0
  69. data/test/cases/adapters/postgresql/domain_test.rb +1 -1
  70. data/test/cases/adapters/postgresql/enum_test.rb +208 -8
  71. data/test/cases/adapters/postgresql/explain_test.rb +25 -6
  72. data/test/cases/adapters/postgresql/extension_migration_test.rb +51 -9
  73. data/test/cases/adapters/postgresql/foreign_table_test.rb +3 -3
  74. data/test/cases/adapters/postgresql/full_text_test.rb +1 -1
  75. data/test/cases/adapters/postgresql/geometric_test.rb +13 -6
  76. data/test/cases/adapters/postgresql/hstore_test.rb +22 -32
  77. data/test/cases/adapters/postgresql/infinity_test.rb +13 -2
  78. data/test/cases/adapters/postgresql/integer_test.rb +1 -1
  79. data/test/cases/adapters/postgresql/interval_test.rb +9 -17
  80. data/test/cases/adapters/postgresql/invertible_migration_test.rb +139 -0
  81. data/test/cases/adapters/postgresql/json_test.rb +5 -0
  82. data/test/cases/adapters/postgresql/ltree_test.rb +1 -1
  83. data/test/cases/adapters/postgresql/money_test.rb +17 -9
  84. data/test/cases/adapters/postgresql/network_test.rb +13 -1
  85. data/test/cases/adapters/postgresql/numbers_test.rb +18 -2
  86. data/test/cases/adapters/postgresql/optimizer_hints_test.rb +9 -9
  87. data/test/cases/adapters/postgresql/partitions_test.rb +5 -2
  88. data/test/cases/adapters/postgresql/postgresql_adapter_prevent_writes_test.rb +7 -110
  89. data/test/cases/adapters/postgresql/postgresql_adapter_test.rb +403 -20
  90. data/test/cases/adapters/postgresql/postgresql_rake_test.rb +637 -0
  91. data/test/cases/adapters/postgresql/prepared_statements_disabled_test.rb +1 -1
  92. data/test/cases/adapters/postgresql/quoting_test.rb +60 -1
  93. data/test/cases/adapters/postgresql/range_test.rb +185 -21
  94. data/test/cases/adapters/postgresql/referential_integrity_test.rb +29 -5
  95. data/test/cases/adapters/postgresql/rename_table_test.rb +35 -8
  96. data/test/cases/adapters/postgresql/schema_authorization_test.rb +2 -2
  97. data/test/cases/adapters/postgresql/schema_test.rb +270 -20
  98. data/test/cases/adapters/postgresql/serial_test.rb +5 -5
  99. data/test/cases/adapters/postgresql/statement_pool_test.rb +6 -2
  100. data/test/cases/adapters/postgresql/timestamp_test.rb +122 -5
  101. data/test/cases/adapters/postgresql/transaction_nested_test.rb +130 -6
  102. data/test/cases/adapters/postgresql/transaction_test.rb +37 -11
  103. data/test/cases/adapters/postgresql/type_lookup_test.rb +1 -1
  104. data/test/cases/adapters/postgresql/uuid_test.rb +77 -9
  105. data/test/cases/adapters/postgresql/virtual_column_test.rb +114 -0
  106. data/test/cases/adapters/postgresql/xml_test.rb +1 -1
  107. data/test/cases/adapters/sqlite3/bind_parameter_test.rb +52 -0
  108. data/test/cases/adapters/sqlite3/collation_test.rb +1 -1
  109. data/test/cases/adapters/sqlite3/copy_table_test.rb +28 -7
  110. data/test/cases/adapters/sqlite3/dbconsole_test.rb +81 -0
  111. data/test/cases/adapters/sqlite3/explain_test.rb +3 -3
  112. data/test/cases/adapters/sqlite3/quoting_test.rb +34 -3
  113. data/test/cases/adapters/sqlite3/sqlite3_adapter_prevent_writes_test.rb +9 -102
  114. data/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +727 -72
  115. data/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb +6 -3
  116. data/test/cases/adapters/sqlite3/sqlite_rake_test.rb +264 -0
  117. data/test/cases/adapters/sqlite3/statement_pool_test.rb +1 -1
  118. data/test/cases/adapters/sqlite3/transaction_test.rb +6 -3
  119. data/test/cases/adapters/sqlite3/virtual_column_test.rb +138 -0
  120. data/test/cases/adapters/sqlite3/virtual_table_test.rb +51 -0
  121. data/test/cases/adapters/trilogy/dbconsole_test.rb +76 -0
  122. data/test/cases/adapters/trilogy/trilogy_adapter_test.rb +473 -0
  123. data/test/cases/adapters/trilogy/trilogy_rake_test.rb +433 -0
  124. data/test/cases/aggregations_test.rb +16 -0
  125. data/test/cases/annotate_test.rb +14 -12
  126. data/test/cases/arel/attributes/attribute_test.rb +86 -47
  127. data/test/cases/arel/collectors/bind_test.rb +1 -1
  128. data/test/cases/arel/collectors/composite_test.rb +11 -1
  129. data/test/cases/arel/collectors/sql_string_test.rb +1 -1
  130. data/test/cases/arel/collectors/substitute_bind_collector_test.rb +1 -1
  131. data/test/cases/arel/delete_manager_test.rb +0 -6
  132. data/test/cases/arel/factory_methods_test.rb +45 -0
  133. data/test/cases/arel/insert_manager_test.rb +1 -7
  134. data/test/cases/arel/nodes/as_test.rb +12 -0
  135. data/test/cases/arel/nodes/ascending_test.rb +1 -1
  136. data/test/cases/arel/nodes/bin_test.rb +1 -1
  137. data/test/cases/arel/nodes/bound_sql_literal_test.rb +31 -0
  138. data/test/cases/arel/nodes/cte_test.rb +46 -0
  139. data/test/cases/arel/nodes/descending_test.rb +1 -1
  140. data/test/cases/arel/nodes/equality_test.rb +3 -3
  141. data/test/cases/arel/nodes/filter_test.rb +37 -0
  142. data/test/cases/arel/nodes/fragments_test.rb +38 -0
  143. data/test/cases/arel/nodes/homogeneous_in_test.rb +52 -0
  144. data/test/cases/arel/nodes/infix_operation_test.rb +1 -1
  145. data/test/cases/arel/nodes/node_test.rb +1 -1
  146. data/test/cases/arel/nodes/or_test.rb +2 -2
  147. data/test/cases/arel/nodes/sql_literal_test.rb +18 -1
  148. data/test/cases/arel/nodes/table_alias_test.rb +12 -0
  149. data/test/cases/arel/nodes/unary_operation_test.rb +1 -1
  150. data/test/cases/arel/nodes/update_statement_test.rb +4 -0
  151. data/test/cases/arel/nodes_test.rb +3 -2
  152. data/test/cases/arel/select_manager_test.rb +12 -12
  153. data/test/cases/arel/support/fake_record.rb +22 -17
  154. data/test/cases/arel/table_test.rb +15 -25
  155. data/test/cases/arel/update_manager_test.rb +51 -6
  156. data/test/cases/arel/visitors/dispatch_contamination_test.rb +1 -1
  157. data/test/cases/arel/visitors/dot_test.rb +177 -2
  158. data/test/cases/arel/visitors/mysql_test.rb +49 -1
  159. data/test/cases/arel/visitors/postgres_test.rb +1 -31
  160. data/test/cases/arel/visitors/sqlite_test.rb +1 -1
  161. data/test/cases/arel/visitors/to_sql_test.rb +330 -20
  162. data/test/cases/assertions/query_assertions_test.rb +136 -0
  163. data/test/cases/associations/belongs_to_associations_test.rb +502 -41
  164. data/test/cases/associations/bidirectional_destroy_dependencies_test.rb +1 -1
  165. data/test/cases/associations/cascaded_eager_loading_test.rb +26 -15
  166. data/test/cases/associations/eager_load_nested_include_test.rb +1 -1
  167. data/test/cases/associations/eager_singularization_test.rb +1 -1
  168. data/test/cases/associations/eager_test.rb +255 -93
  169. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +25 -53
  170. data/test/cases/associations/has_many_associations_test.rb +282 -72
  171. data/test/cases/associations/has_many_through_associations_test.rb +172 -45
  172. data/test/cases/associations/has_many_through_disable_joins_associations_test.rb +197 -0
  173. data/test/cases/associations/has_one_associations_test.rb +160 -29
  174. data/test/cases/associations/has_one_through_associations_test.rb +64 -15
  175. data/test/cases/associations/has_one_through_disable_joins_associations_test.rb +82 -0
  176. data/test/cases/associations/inner_join_association_test.rb +36 -6
  177. data/test/cases/associations/inverse_associations_test.rb +177 -40
  178. data/test/cases/associations/join_model_test.rb +17 -12
  179. data/test/cases/associations/left_outer_join_association_test.rb +14 -3
  180. data/test/cases/associations/nested_error_test.rb +116 -0
  181. data/test/cases/associations/nested_through_associations_test.rb +54 -19
  182. data/test/cases/associations/required_test.rb +1 -1
  183. data/test/cases/associations_test.rb +1278 -21
  184. data/test/cases/asynchronous_queries_test.rb +310 -0
  185. data/test/cases/attribute_methods/read_test.rb +6 -0
  186. data/test/cases/attribute_methods/time_zone_converter_test.rb +21 -0
  187. data/test/cases/attribute_methods_test.rb +565 -46
  188. data/test/cases/attributes_test.rb +42 -1
  189. data/test/cases/autosave_association_test.rb +645 -92
  190. data/test/cases/base_prevent_writes_test.rb +28 -159
  191. data/test/cases/base_test.rb +434 -209
  192. data/test/cases/batches_test.rb +441 -57
  193. data/test/cases/binary_test.rb +31 -0
  194. data/test/cases/bind_parameter_test.rb +107 -16
  195. data/test/cases/cache_key_test.rb +7 -7
  196. data/test/cases/calculations_test.rb +541 -110
  197. data/test/cases/callbacks_test.rb +0 -1
  198. data/test/cases/clone_test.rb +5 -4
  199. data/test/cases/coders/yaml_column_test.rb +97 -2
  200. data/test/cases/collection_cache_key_test.rb +24 -16
  201. data/test/cases/column_alias_test.rb +2 -8
  202. data/test/cases/column_definition_test.rb +12 -3
  203. data/test/cases/comment_test.rb +23 -26
  204. data/test/cases/connection_adapters/adapter_leasing_test.rb +9 -9
  205. data/test/cases/connection_adapters/connection_handler_test.rb +145 -99
  206. data/test/cases/connection_adapters/connection_handlers_multi_db_test.rb +79 -55
  207. data/test/cases/connection_adapters/connection_handlers_multi_pool_config_test.rb +17 -20
  208. data/test/cases/connection_adapters/connection_handlers_sharding_db_test.rb +146 -55
  209. data/test/cases/connection_adapters/connection_swapping_nested_test.rb +136 -23
  210. data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +96 -27
  211. data/test/cases/connection_adapters/mysql_type_lookup_test.rb +5 -5
  212. data/test/cases/connection_adapters/registration_test.rb +98 -0
  213. data/test/cases/connection_adapters/schema_cache_test.rb +288 -135
  214. data/test/cases/connection_adapters/standalone_connection_test.rb +38 -0
  215. data/test/cases/connection_adapters/statement_pool_test.rb +29 -0
  216. data/test/cases/connection_adapters/type_lookup_test.rb +12 -24
  217. data/test/cases/connection_handling_test.rb +210 -0
  218. data/test/cases/connection_management_test.rb +44 -7
  219. data/test/cases/connection_pool_test.rb +466 -99
  220. data/test/cases/core_test.rb +167 -9
  221. data/test/cases/counter_cache_test.rb +129 -2
  222. data/test/cases/custom_locking_test.rb +3 -3
  223. data/test/cases/database_configurations/hash_config_test.rb +149 -13
  224. data/test/cases/database_configurations/resolver_test.rb +14 -10
  225. data/test/cases/database_configurations/url_config_test.rb +53 -0
  226. data/test/cases/database_configurations_test.rb +86 -43
  227. data/test/cases/database_selector_test.rb +30 -8
  228. data/test/cases/database_statements_test.rb +10 -14
  229. data/test/cases/date_time_precision_test.rb +141 -11
  230. data/test/cases/date_time_test.rb +19 -1
  231. data/test/cases/defaults_test.rb +107 -41
  232. data/test/cases/delegated_type_test.rb +69 -9
  233. data/test/cases/dirty_test.rb +82 -25
  234. data/test/cases/disconnected_test.rb +10 -9
  235. data/test/cases/dup_test.rb +26 -6
  236. data/test/cases/encryption/cipher/aes256_gcm_test.rb +50 -0
  237. data/test/cases/encryption/cipher_test.rb +65 -0
  238. data/test/cases/encryption/concurrency_test.rb +27 -0
  239. data/test/cases/encryption/config_test.rb +21 -0
  240. data/test/cases/encryption/configurable_test.rb +93 -0
  241. data/test/cases/encryption/contexts_test.rb +105 -0
  242. data/test/cases/encryption/derived_secret_key_provider_test.rb +31 -0
  243. data/test/cases/encryption/deterministic_key_provider_test.rb +11 -0
  244. data/test/cases/encryption/encryptable_record_api_test.rb +175 -0
  245. data/test/cases/encryption/encryptable_record_message_pack_serialized_test.rb +42 -0
  246. data/test/cases/encryption/encryptable_record_test.rb +470 -0
  247. data/test/cases/encryption/encrypted_fixtures_test.rb +22 -0
  248. data/test/cases/encryption/encrypting_only_encryptor_test.rb +20 -0
  249. data/test/cases/encryption/encryption_schemes_test.rb +240 -0
  250. data/test/cases/encryption/encryptor_test.rb +113 -0
  251. data/test/cases/encryption/envelope_encryption_key_provider_test.rb +49 -0
  252. data/test/cases/encryption/extended_deterministic_queries_test.rb +81 -0
  253. data/test/cases/encryption/helper.rb +152 -0
  254. data/test/cases/encryption/key_generator_test.rb +55 -0
  255. data/test/cases/encryption/key_provider_test.rb +57 -0
  256. data/test/cases/encryption/key_test.rb +17 -0
  257. data/test/cases/encryption/message_pack_message_serializer_test.rb +70 -0
  258. data/test/cases/encryption/message_serializer_test.rb +82 -0
  259. data/test/cases/encryption/message_test.rb +43 -0
  260. data/test/cases/encryption/null_encryptor_test.rb +21 -0
  261. data/test/cases/encryption/properties_test.rb +69 -0
  262. data/test/cases/encryption/read_only_null_encryptor_test.rb +19 -0
  263. data/test/cases/encryption/scheme_test.rb +58 -0
  264. data/test/cases/encryption/unencrypted_attributes_test.rb +27 -0
  265. data/test/cases/encryption/uniqueness_validations_test.rb +65 -0
  266. data/test/cases/enum_test.rb +374 -72
  267. data/test/cases/errors_test.rb +7 -4
  268. data/test/cases/excluding_test.rb +116 -0
  269. data/test/cases/explain_subscriber_test.rb +6 -1
  270. data/test/cases/explain_test.rb +119 -10
  271. data/test/cases/filter_attributes_test.rb +7 -14
  272. data/test/cases/finder_respond_to_test.rb +3 -3
  273. data/test/cases/finder_test.rb +357 -72
  274. data/test/cases/fixture_set/file_test.rb +9 -0
  275. data/test/cases/fixtures_test.rb +426 -190
  276. data/test/cases/helper.rb +66 -192
  277. data/test/cases/hot_compatibility_test.rb +10 -10
  278. data/test/cases/inheritance_test.rb +51 -61
  279. data/test/cases/inherited_test.rb +40 -0
  280. data/test/cases/insert_all_test.rb +419 -9
  281. data/test/cases/instrumentation_test.rb +202 -30
  282. data/test/cases/integration_test.rb +25 -7
  283. data/test/cases/invalid_connection_test.rb +5 -5
  284. data/test/cases/invertible_migration_test.rb +108 -24
  285. data/test/cases/json_attribute_test.rb +1 -0
  286. data/test/cases/json_serialization_test.rb +5 -5
  287. data/test/cases/json_shared_test_cases.rb +5 -9
  288. data/test/cases/locking_test.rb +67 -31
  289. data/test/cases/log_subscriber_test.rb +17 -15
  290. data/test/cases/marshal_serialization_test.rb +78 -5
  291. data/test/cases/message_pack_test.rb +91 -0
  292. data/test/cases/migration/change_schema_test.rb +77 -46
  293. data/test/cases/migration/change_table_test.rb +129 -114
  294. data/test/cases/migration/check_constraint_test.rb +192 -10
  295. data/test/cases/migration/column_attributes_test.rb +4 -9
  296. data/test/cases/migration/column_positioning_test.rb +2 -2
  297. data/test/cases/migration/columns_test.rb +118 -4
  298. data/test/cases/migration/command_recorder_test.rb +181 -14
  299. data/test/cases/migration/compatibility_test.rb +883 -196
  300. data/test/cases/migration/create_join_table_test.rb +8 -1
  301. data/test/cases/migration/exclusion_constraint_test.rb +192 -0
  302. data/test/cases/migration/foreign_key_test.rb +356 -14
  303. data/test/cases/migration/helper.rb +4 -1
  304. data/test/cases/migration/index_test.rb +67 -2
  305. data/test/cases/migration/invalid_options_test.rb +129 -0
  306. data/test/cases/migration/logger_test.rb +7 -4
  307. data/test/cases/migration/pending_migrations_test.rb +103 -60
  308. data/test/cases/migration/references_foreign_key_test.rb +73 -4
  309. data/test/cases/migration/references_index_test.rb +25 -27
  310. data/test/cases/migration/references_statements_test.rb +27 -3
  311. data/test/cases/migration/rename_table_test.rb +39 -54
  312. data/test/cases/migration/schema_definitions_test.rb +109 -0
  313. data/test/cases/migration/unique_constraint_test.rb +248 -0
  314. data/test/cases/migration_test.rb +677 -220
  315. data/test/cases/migrator_test.rb +102 -75
  316. data/test/cases/multi_db_migrator_test.rb +55 -34
  317. data/test/cases/multiparameter_attributes_test.rb +26 -29
  318. data/test/cases/multiple_db_test.rb +42 -19
  319. data/test/cases/nested_attributes_test.rb +124 -6
  320. data/test/cases/nested_attributes_with_callbacks_test.rb +2 -2
  321. data/test/cases/normalized_attribute_test.rb +117 -0
  322. data/test/cases/null_relation_test.rb +35 -2
  323. data/test/cases/persistence/reload_association_cache_test.rb +20 -0
  324. data/test/cases/persistence_test.rb +629 -22
  325. data/test/cases/pooled_connections_test.rb +57 -56
  326. data/test/cases/prepared_statement_status_test.rb +8 -3
  327. data/test/cases/primary_class_test.rb +134 -0
  328. data/test/cases/primary_keys_test.rb +171 -55
  329. data/test/cases/query_cache_test.rb +558 -263
  330. data/test/cases/query_logs_test.rb +293 -0
  331. data/test/cases/quoting_test.rb +39 -72
  332. data/test/cases/readonly_test.rb +50 -12
  333. data/test/cases/reaper_test.rb +22 -6
  334. data/test/cases/reflection_test.rb +207 -9
  335. data/test/cases/relation/and_test.rb +43 -0
  336. data/test/cases/relation/delegation_test.rb +32 -5
  337. data/test/cases/relation/delete_all_test.rb +27 -6
  338. data/test/cases/relation/field_ordered_values_test.rb +128 -0
  339. data/test/cases/relation/load_async_test.rb +650 -0
  340. data/test/cases/relation/merging_test.rb +80 -109
  341. data/test/cases/relation/mutation_test.rb +12 -7
  342. data/test/cases/relation/or_test.rb +11 -8
  343. data/test/cases/relation/order_test.rb +90 -0
  344. data/test/cases/relation/predicate_builder_test.rb +21 -6
  345. data/test/cases/relation/select_test.rb +162 -3
  346. data/test/cases/relation/structural_compatibility_test.rb +38 -0
  347. data/test/cases/relation/update_all_test.rb +81 -27
  348. data/test/cases/relation/where_chain_test.rb +190 -3
  349. data/test/cases/relation/where_clause_test.rb +43 -1
  350. data/test/cases/relation/where_test.rb +95 -7
  351. data/test/cases/relation/with_test.rb +165 -0
  352. data/test/cases/relation_test.rb +42 -37
  353. data/test/cases/relations_test.rb +436 -138
  354. data/test/cases/reload_models_test.rb +18 -14
  355. data/test/cases/reserved_word_test.rb +2 -1
  356. data/test/cases/result_test.rb +14 -22
  357. data/test/cases/sanitize_test.rb +89 -27
  358. data/test/cases/schema_dumper_test.rb +535 -62
  359. data/test/cases/scoping/default_scoping_test.rb +219 -35
  360. data/test/cases/scoping/named_scoping_test.rb +25 -46
  361. data/test/cases/scoping/relation_scoping_test.rb +112 -4
  362. data/test/cases/secure_password_test.rb +108 -0
  363. data/test/cases/secure_token_test.rb +72 -0
  364. data/test/cases/serialization_test.rb +1 -1
  365. data/test/cases/serialized_attribute_test.rb +305 -60
  366. data/test/cases/shard_keys_test.rb +125 -0
  367. data/test/cases/shard_selector_test.rb +45 -0
  368. data/test/cases/signed_id_test.rb +57 -5
  369. data/test/cases/statement_cache_test.rb +31 -30
  370. data/test/cases/statement_invalid_test.rb +8 -4
  371. data/test/cases/store_test.rb +73 -9
  372. data/test/cases/strict_loading_test.rb +327 -13
  373. data/test/cases/table_metadata_test.rb +16 -0
  374. data/test/cases/tasks/database_tasks_test.rb +517 -244
  375. data/test/cases/test_case.rb +254 -60
  376. data/test/cases/test_case_test.rb +69 -0
  377. data/test/cases/test_databases_test.rb +7 -3
  378. data/test/cases/test_fixtures_test.rb +19 -40
  379. data/test/cases/time_precision_test.rb +17 -5
  380. data/test/cases/timestamp_test.rb +124 -16
  381. data/test/cases/token_for_test.rb +165 -0
  382. data/test/cases/touch_later_test.rb +43 -1
  383. data/test/cases/transaction_callbacks_test.rb +325 -8
  384. data/test/cases/transaction_instrumentation_test.rb +453 -0
  385. data/test/cases/transaction_isolation_test.rb +12 -8
  386. data/test/cases/transactions_test.rb +629 -112
  387. data/test/cases/type/date_time_test.rb +7 -1
  388. data/test/cases/type/time_test.rb +9 -0
  389. data/test/cases/type/type_map_test.rb +108 -73
  390. data/test/cases/type/unsigned_integer_test.rb +12 -0
  391. data/test/cases/type_caster/connection_test.rb +19 -0
  392. data/test/cases/type_test.rb +1 -1
  393. data/test/cases/unconnected_test.rb +7 -7
  394. data/test/cases/unsafe_raw_sql_test.rb +39 -8
  395. data/test/cases/validations/absence_validation_test.rb +1 -1
  396. data/test/cases/validations/association_validation_test.rb +25 -3
  397. data/test/cases/validations/numericality_validation_test.rb +3 -9
  398. data/test/cases/validations/presence_validation_test.rb +1 -1
  399. data/test/cases/validations/uniqueness_validation_test.rb +280 -40
  400. data/test/cases/validations_test.rb +2 -2
  401. data/test/cases/view_test.rb +33 -22
  402. data/test/cases/yaml_serialization_test.rb +23 -17
  403. data/test/config.example.yml +58 -56
  404. data/test/config.rb +1 -0
  405. data/test/fixtures/1_need_quoting.yml +2 -0
  406. data/test/fixtures/accounts.yml +5 -0
  407. data/test/fixtures/aircrafts.yml +7 -0
  408. data/test/fixtures/book_identifiers.yml +11 -0
  409. data/test/fixtures/books.yml +5 -4
  410. data/test/fixtures/cake_designers.yml +5 -0
  411. data/test/fixtures/cars.yml +6 -0
  412. data/test/fixtures/chefs.yml +5 -0
  413. data/test/fixtures/clothing_items.yml +23 -0
  414. data/test/fixtures/clubs.yml +1 -1
  415. data/test/fixtures/comments.yml +2 -1
  416. data/test/fixtures/cpk_authors.yml +8 -0
  417. data/test/fixtures/cpk_books.yml +21 -0
  418. data/test/fixtures/cpk_order_agreements.yml +13 -0
  419. data/test/fixtures/cpk_order_tags.yml +15 -0
  420. data/test/fixtures/cpk_orders.yml +11 -0
  421. data/test/fixtures/cpk_posts.yml +12 -0
  422. data/test/fixtures/cpk_reviews.yml +13 -0
  423. data/test/fixtures/cpk_tags.yml +11 -0
  424. data/test/fixtures/drink_designers.yml +5 -0
  425. data/test/fixtures/encrypted_book_that_ignores_cases.yml +4 -0
  426. data/test/fixtures/encrypted_books.yml +4 -0
  427. data/test/fixtures/fk_object_to_point_to.yml +2 -0
  428. data/test/fixtures/memberships.yml +15 -15
  429. data/test/fixtures/paragraphs.yml +5 -0
  430. data/test/fixtures/parrots.yml +4 -0
  431. data/test/fixtures/people.yml +2 -0
  432. data/test/fixtures/pirates.yml +2 -2
  433. data/test/fixtures/primary_key_error/primary_key_error.yml +6 -0
  434. data/test/fixtures/references.yml +3 -3
  435. data/test/fixtures/sharded_blog_posts.yml +14 -0
  436. data/test/fixtures/sharded_blog_posts_tags.yml +27 -0
  437. data/test/fixtures/sharded_blogs.yml +8 -0
  438. data/test/fixtures/sharded_comments.yml +22 -0
  439. data/test/fixtures/sharded_tags.yml +34 -0
  440. data/test/fixtures/sponsors.yml +2 -2
  441. data/test/fixtures/topics.yml +1 -0
  442. data/test/fixtures/treasures.yml +4 -0
  443. data/test/fixtures/virtual_columns.yml +5 -0
  444. data/test/fixtures/warehouse_things.yml +1 -1
  445. data/test/migrations/old_and_new_versions/20210716122844_add_people_description.rb +5 -0
  446. data/test/migrations/old_and_new_versions/20210716123013_add_people_number_of_legs.rb +5 -0
  447. data/test/migrations/old_and_new_versions/230_add_people_hobby.rb +5 -0
  448. data/test/migrations/old_and_new_versions/231_add_people_last_name.rb +5 -0
  449. data/test/migrations/scope/1_unscoped.rb +7 -0
  450. data/test/migrations/scope/2_mysql_only.mysql.rb +7 -0
  451. data/test/models/admin/user.rb +2 -0
  452. data/test/models/admin/user_json.rb +48 -0
  453. data/test/models/attachment.rb +7 -0
  454. data/test/models/author.rb +70 -3
  455. data/test/models/author_encrypted.rb +16 -0
  456. data/test/models/bird.rb +1 -1
  457. data/test/models/book.rb +18 -11
  458. data/test/models/book_destroy_async.rb +1 -1
  459. data/test/models/book_encrypted.rb +106 -0
  460. data/test/models/book_identifier.rb +5 -0
  461. data/test/models/branch.rb +11 -0
  462. data/test/models/bulb.rb +1 -1
  463. data/test/models/car.rb +8 -1
  464. data/test/models/cat.rb +1 -1
  465. data/test/models/category.rb +3 -1
  466. data/test/models/chat_message.rb +8 -0
  467. data/test/models/chef.rb +52 -0
  468. data/test/models/clothing_item.rb +12 -0
  469. data/test/models/club.rb +4 -1
  470. data/test/models/comment.rb +7 -4
  471. data/test/models/comment_overlapping_counter_cache.rb +15 -0
  472. data/test/models/company.rb +16 -2
  473. data/test/models/computer.rb +1 -0
  474. data/test/models/contact.rb +3 -3
  475. data/test/models/contract.rb +5 -1
  476. data/test/models/cpk/author.rb +9 -0
  477. data/test/models/cpk/book.rb +55 -0
  478. data/test/models/cpk/book_destroy_async.rb +9 -0
  479. data/test/models/cpk/car.rb +9 -0
  480. data/test/models/cpk/car_review.rb +9 -0
  481. data/test/models/cpk/chapter.rb +16 -0
  482. data/test/models/cpk/chapter_destroy_async.rb +10 -0
  483. data/test/models/cpk/comment.rb +9 -0
  484. data/test/models/cpk/order.rb +55 -0
  485. data/test/models/cpk/order_agreement.rb +10 -0
  486. data/test/models/cpk/order_tag.rb +10 -0
  487. data/test/models/cpk/post.rb +10 -0
  488. data/test/models/cpk/posts_tag.rb +10 -0
  489. data/test/models/cpk/review.rb +9 -0
  490. data/test/models/cpk/tag.rb +10 -0
  491. data/test/models/cpk.rb +15 -0
  492. data/test/models/customer.rb +3 -1
  493. data/test/models/destroy_async_parent.rb +1 -1
  494. data/test/models/developer.rb +44 -3
  495. data/test/models/discount.rb +4 -0
  496. data/test/models/drink_designer.rb +1 -0
  497. data/test/models/editor.rb +8 -0
  498. data/test/models/editorship.rb +6 -0
  499. data/test/models/entry.rb +5 -0
  500. data/test/models/essay.rb +6 -1
  501. data/test/models/essay_destroy_async.rb +1 -0
  502. data/test/models/eye.rb +87 -21
  503. data/test/models/face.rb +1 -1
  504. data/test/models/friendship.rb +3 -0
  505. data/test/models/hardback.rb +7 -0
  506. data/test/models/hotel.rb +2 -0
  507. data/test/models/human.rb +2 -2
  508. data/test/models/invoice.rb +2 -1
  509. data/test/models/invokes_an_undefined_method.rb +5 -0
  510. data/test/models/line_item.rb +6 -0
  511. data/test/models/member.rb +9 -4
  512. data/test/models/membership.rb +2 -2
  513. data/test/models/message.rb +2 -1
  514. data/test/models/need_quoting.rb +5 -0
  515. data/test/models/paragraph.rb +5 -0
  516. data/test/models/parrot.rb +6 -3
  517. data/test/models/person.rb +7 -4
  518. data/test/models/pirate.rb +4 -1
  519. data/test/models/pk_autopopulated_by_a_trigger_record.rb +5 -0
  520. data/test/models/post.rb +65 -2
  521. data/test/models/post_encrypted.rb +15 -0
  522. data/test/models/post_with_prefetched_pk.rb +15 -0
  523. data/test/models/project.rb +1 -0
  524. data/test/models/publication.rb +16 -0
  525. data/test/models/raises_argument_error.rb +5 -0
  526. data/test/models/raises_no_method_error.rb +5 -0
  527. data/test/models/recipient.rb +5 -0
  528. data/test/models/reference.rb +1 -1
  529. data/test/models/reply.rb +1 -1
  530. data/test/models/room.rb +3 -0
  531. data/test/models/sharded/blog.rb +12 -0
  532. data/test/models/sharded/blog_post.rb +17 -0
  533. data/test/models/sharded/blog_post_destroy_async.rb +14 -0
  534. data/test/models/sharded/blog_post_tag.rb +11 -0
  535. data/test/models/sharded/blog_post_with_revision.rb +11 -0
  536. data/test/models/sharded/comment.rb +12 -0
  537. data/test/models/sharded/comment_destroy_async.rb +12 -0
  538. data/test/models/sharded/tag.rb +11 -0
  539. data/test/models/sharded.rb +8 -0
  540. data/test/models/ship.rb +1 -1
  541. data/test/models/shipping_line.rb +11 -0
  542. data/test/models/subscriber.rb +1 -0
  543. data/test/models/subscription.rb +3 -1
  544. data/test/models/too_long_table_name.rb +5 -0
  545. data/test/models/topic.rb +3 -1
  546. data/test/models/traffic_light.rb +2 -2
  547. data/test/models/traffic_light_encrypted.rb +21 -0
  548. data/test/models/translation.rb +9 -0
  549. data/test/models/treasure.rb +1 -1
  550. data/test/models/tyre.rb +1 -1
  551. data/test/models/user.rb +16 -0
  552. data/test/models/user_with_invalid_relation.rb +28 -0
  553. data/test/models/uuid_comment.rb +5 -0
  554. data/test/models/uuid_entry.rb +5 -0
  555. data/test/models/uuid_message.rb +5 -0
  556. data/test/models/zine.rb +2 -1
  557. data/test/schema/mysql2_specific_schema.rb +26 -12
  558. data/test/schema/postgresql_specific_schema.rb +121 -13
  559. data/test/schema/schema.rb +361 -103
  560. data/test/schema/sqlite_specific_schema.rb +17 -6
  561. data/test/schema/trilogy_specific_schema.rb +96 -0
  562. data/test/support/adapter_helper.rb +104 -0
  563. data/test/support/async_helper.rb +15 -0
  564. data/test/support/config.rb +1 -1
  565. data/test/support/connection.rb +14 -2
  566. data/test/support/ddl_helper.rb +1 -1
  567. data/test/support/fake_adapter.rb +42 -0
  568. data/test/support/load_schema_helper.rb +22 -0
  569. data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_6_1_topic.dump +0 -0
  570. data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_6_1_topic_associations.dump +0 -0
  571. data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_7_1_topic.dump +0 -0
  572. data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_7_1_topic_associations.dump +0 -0
  573. data/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_1_topic.dump +0 -0
  574. data/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_1_topic_associations.dump +0 -0
  575. data/test/support/marshal_compatibility_fixtures/Mysql2/rails_7_1_topic.dump +0 -0
  576. data/test/support/marshal_compatibility_fixtures/Mysql2/rails_7_1_topic_associations.dump +0 -0
  577. data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_1_topic.dump +0 -0
  578. data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_1_topic_associations.dump +0 -0
  579. data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_7_1_topic.dump +0 -0
  580. data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_7_1_topic_associations.dump +0 -0
  581. data/test/support/marshal_compatibility_fixtures/SQLite/rails_6_1_topic.dump +0 -0
  582. data/test/support/marshal_compatibility_fixtures/SQLite/rails_6_1_topic_associations.dump +0 -0
  583. data/test/support/marshal_compatibility_fixtures/SQLite/rails_7_1_topic.dump +0 -0
  584. data/test/support/marshal_compatibility_fixtures/SQLite/rails_7_1_topic_associations.dump +0 -0
  585. data/test/support/marshal_compatibility_fixtures/Trilogy/rails_6_1_topic.dump +0 -0
  586. data/test/support/marshal_compatibility_fixtures/Trilogy/rails_6_1_topic_associations.dump +0 -0
  587. data/test/support/marshal_compatibility_fixtures/Trilogy/rails_7_1_topic.dump +0 -0
  588. data/test/support/marshal_compatibility_fixtures/Trilogy/rails_7_1_topic_associations.dump +0 -0
  589. data/test/support/schema_dumping_helper.rb +15 -9
  590. data/test/support/tools.rb +37 -0
  591. data/test/support/yaml_compatibility_fixtures/rails_4_1_no_symbol.yml +22 -0
  592. metadata +247 -15
@@ -9,8 +9,117 @@ module ActiveRecord
9
9
  fixtures :posts, :comments
10
10
 
11
11
  def test_select_with_nil_argument
12
- expected = Post.select(:title).to_sql
13
- assert_equal expected, Post.select(nil).select(:title).to_sql
12
+ expected = %r/\ASELECT #{Regexp.escape(quote_table_name("posts.title"))} FROM/
13
+ assert_match expected, Post.select(nil).select(:title).to_sql
14
+ end
15
+
16
+ def test_select_with_non_field_values
17
+ expected = %r/\ASELECT 1, foo\(\), #{Regexp.escape(quote_table_name("bar"))} FROM/
18
+ assert_match expected, Post.select("1", "foo()", :bar).to_sql
19
+ end
20
+
21
+ def test_select_with_non_field_hash_values
22
+ q = -> name { Regexp.escape(quote_table_name(name)) }
23
+ expected = %r/\ASELECT 1 AS #{q["a"]}, foo\(\) AS #{q["b"]}, #{q["bar"]} AS #{q["c"]} FROM/
24
+ assert_match expected, Post.select("1" => :a, "foo()" => :b, :bar => :c).to_sql
25
+ end
26
+
27
+ def test_select_with_hash_argument
28
+ post = Post.select("UPPER(title)" => :title, posts: { title: :post_title }).first
29
+
30
+ assert_equal "WELCOME TO THE WEBLOG", post.title
31
+ assert_equal "Welcome to the weblog", post.post_title
32
+ end
33
+
34
+ def test_select_with_reserved_words_aliases
35
+ post = Post.select("UPPER(title)" => :from, title: :group).first
36
+
37
+ assert_equal "WELCOME TO THE WEBLOG", post.from
38
+ assert_equal "Welcome to the weblog", post.group
39
+ end
40
+
41
+ def test_select_with_one_level_hash_argument
42
+ post = Post.select("UPPER(title)" => :title, title: :post_title).first
43
+
44
+ assert_equal "WELCOME TO THE WEBLOG", post.title
45
+ assert_equal "Welcome to the weblog", post.post_title
46
+ end
47
+
48
+ def test_select_with_not_exists_field
49
+ q = -> name { Regexp.escape(quote_table_name(name)) }
50
+ expected = %r/\ASELECT #{q["foo"]} AS #{q["post_title"]} FROM/
51
+ assert_match expected, Post.select(foo: :post_title).to_sql
52
+
53
+ skip if sqlite3_adapter_strict_strings_disabled?
54
+ skip "DB2 does not raise for unresolved projection identifiers in SELECT list" if current_adapter?(:IBM_DBAdapter)
55
+
56
+ assert_raises(ActiveRecord::StatementInvalid) do
57
+ Post.select(foo: :post_title).take
58
+ end
59
+ end
60
+
61
+ def test_select_with_hash_with_not_exists_field
62
+ q = -> name { Regexp.escape(quote_table_name(name)) }
63
+ expected = %r/\ASELECT #{q["posts.bar"]} AS #{q["post_title"]} FROM/
64
+ assert_match expected, Post.select(posts: { bar: :post_title }).to_sql
65
+
66
+ skip "DB2 does not raise for unresolved projection identifiers in SELECT list" if current_adapter?(:IBM_DBAdapter)
67
+
68
+ assert_raises(ActiveRecord::StatementInvalid) do
69
+ Post.select(posts: { boo: :post_title }).take
70
+ end
71
+ end
72
+
73
+ def test_select_with_hash_array_value_with_not_exists_field
74
+ q = -> name { Regexp.escape(quote_table_name(name)) }
75
+ expected = %r/\ASELECT #{q["posts.bar"]}, #{q["posts.id"]} FROM/
76
+ assert_match expected, Post.select(posts: [:bar, :id]).to_sql
77
+
78
+ skip "DB2 does not raise for unresolved projection identifiers in SELECT list" if current_adapter?(:IBM_DBAdapter)
79
+
80
+ assert_raises(ActiveRecord::StatementInvalid) do
81
+ Post.select(posts: [:bar, :id]).take
82
+ end
83
+ end
84
+
85
+ def test_select_with_hash_and_table_alias
86
+ post = Post.joins(:comments, :comments_with_extend)
87
+ .select(
88
+ :title,
89
+ posts: { title: :post_title },
90
+ comments: { body: :comment_body },
91
+ comments_with_extend: { body: :comment_body_2 }
92
+ )
93
+ .take
94
+
95
+ assert_equal post.title, post.post_title
96
+ assert_not_nil post.comment_body
97
+ assert_not_nil post.comment_body_2
98
+ end
99
+
100
+ def test_select_with_invalid_nested_field
101
+ skip "DB2 allows expression-like nested projection keys without raising" if current_adapter?(:IBM_DBAdapter)
102
+
103
+ assert_raises(ActiveRecord::StatementInvalid) do
104
+ Post.select(posts: { "UPPER(title)" => :post_title }).take
105
+ end
106
+ assert_raises(ActiveRecord::StatementInvalid) do
107
+ Post.select(posts: ["UPPER(title)"]).take
108
+ end
109
+ end
110
+
111
+ def test_select_with_hash_argument_without_aliases
112
+ post = Post.select(posts: [:title, "title as post_title"]).first
113
+ assert_equal "Welcome to the weblog", post.title
114
+ assert_equal "Welcome to the weblog", post.post_title
115
+ end
116
+
117
+ def test_select_with_hash_argument_with_few_tables
118
+ post = Post.joins(:comments).select(:title, posts: { title: :post_title }, comments: { body: :comment_body }).take
119
+
120
+ assert_equal post.title, post.post_title
121
+ assert_not_nil post.comment_body
122
+ assert_not_nil post.post_title
14
123
  end
15
124
 
16
125
  def test_reselect
@@ -25,6 +134,18 @@ module ActiveRecord
25
134
  assert_equal expected, actual
26
135
  end
27
136
 
137
+ def test_reselect_with_hash_argument
138
+ expected = Post.select(:title, posts: { title: :post_title }).to_sql
139
+ actual = Post.select(:title, :body).reselect(:title, posts: { title: :post_title }).to_sql
140
+ assert_equal expected, actual
141
+ end
142
+
143
+ def test_reselect_with_one_level_hash_argument
144
+ expected = Post.select(:title, title: :post_title).to_sql
145
+ actual = Post.select(:title, :body).reselect(:title, title: :post_title).to_sql
146
+ assert_equal expected, actual
147
+ end
148
+
28
149
  def test_non_select_columns_wont_be_loaded
29
150
  posts = Post.select("UPPER(title) AS title")
30
151
 
@@ -35,12 +156,26 @@ module ActiveRecord
35
156
 
36
157
  def assert_non_select_columns_wont_be_loaded(post)
37
158
  assert_equal "WELCOME TO THE WEBLOG", post.title
38
- assert_raise(ActiveModel::MissingAttributeError) do
159
+ assert_raise(ActiveModel::MissingAttributeError, match: /attribute 'body' for Post/) do
39
160
  post.body
40
161
  end
41
162
  end
42
163
  private :assert_non_select_columns_wont_be_loaded
43
164
 
165
+ def test_merging_select_from_different_model
166
+ posts = Post.select(:id, :title).joins(:comments)
167
+ comments = Comment.where(body: "Thank you for the welcome")
168
+
169
+ [
170
+ posts.merge(comments.select(:body)).first,
171
+ posts.merge(comments.select("comments.body")).first,
172
+ ].each do |post|
173
+ assert_equal 1, post.id
174
+ assert_equal "Welcome to the weblog", post.title
175
+ assert_equal "Thank you for the welcome", post.body
176
+ end
177
+ end
178
+
44
179
  def test_type_casted_extra_select_with_eager_loading
45
180
  posts = Post.select("posts.id * 1.1 AS foo").eager_load(:comments)
46
181
  assert_equal 1.1, posts.first.foo
@@ -63,5 +198,29 @@ module ActiveRecord
63
198
  tags_count indestructible_tags_count tags_with_destroy_count tags_with_nullify_count
64
199
  ), posts.first.attributes.keys
65
200
  end
201
+
202
+ def test_enumerate_columns_in_select_statements
203
+ original_value = Post.enumerate_columns_in_select_statements
204
+ Post.enumerate_columns_in_select_statements = true
205
+ sql = Post.all.to_sql
206
+ Post.column_names.each do |column_name|
207
+ assert_includes sql, column_name
208
+ end
209
+ ensure
210
+ Post.enumerate_columns_in_select_statements = original_value
211
+ end
212
+
213
+ def test_select_without_any_arguments
214
+ error = assert_raises(ArgumentError) { Post.select }
215
+ assert_equal "Call `select' with at least one field.", error.message
216
+ end
217
+
218
+ def test_select_with_block_without_any_arguments
219
+ error = assert_raises(ArgumentError) do
220
+ Post.select("invalid_argument") { }
221
+ end
222
+
223
+ assert_equal "`select' with block doesn't take arguments.", error.message
224
+ end
66
225
  end
67
226
  end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/helper"
4
+ require "models/post"
5
+
6
+ module ActiveRecord
7
+ class StructuralCompatibilityTest < ActiveRecord::TestCase
8
+ fixtures :posts
9
+
10
+ def test_compatible_values
11
+ left = Post.where(id: 1)
12
+ right = Post.where(id: 2)
13
+
14
+ assert left.structurally_compatible?(right)
15
+ end
16
+
17
+ def test_incompatible_single_value_relations
18
+ left = Post.distinct.where("id = 1")
19
+ right = Post.where(id: [2, 3])
20
+
21
+ assert_not left.structurally_compatible?(right)
22
+ end
23
+
24
+ def test_incompatible_multi_value_relations
25
+ left = Post.order("body asc").where("id = 1")
26
+ right = Post.order("id desc").where(id: [2, 3])
27
+
28
+ assert_not left.structurally_compatible?(right)
29
+ end
30
+
31
+ def test_incompatible_unscope
32
+ left = Post.order("body asc").where("id = 1").unscope(:order)
33
+ right = Post.order("body asc").where("id = 2")
34
+
35
+ assert_not left.structurally_compatible?(right)
36
+ end
37
+ end
38
+ end
@@ -14,9 +14,11 @@ require "models/topic"
14
14
  require "models/tag"
15
15
  require "models/tagging"
16
16
  require "models/warehouse_thing"
17
+ require "models/cpk"
17
18
 
18
19
  class UpdateAllTest < ActiveRecord::TestCase
19
- fixtures :authors, :author_addresses, :comments, :developers, :posts, :people, :pets, :toys, :tags, :taggings, "warehouse_things"
20
+ fixtures :authors, :author_addresses, :comments, :developers, :posts, :people, :pets, :toys, :tags,
21
+ :taggings, :warehouse_things, :cpk_orders, :cpk_order_agreements
20
22
 
21
23
  class TopicWithCallbacks < ActiveRecord::Base
22
24
  self.table_name = :topics
@@ -39,7 +41,23 @@ class UpdateAllTest < ActiveRecord::TestCase
39
41
  end
40
42
 
41
43
  def test_update_all_with_blank_argument
42
- assert_raises(ArgumentError) { Comment.update_all({}) }
44
+ error = assert_raises(ArgumentError) { Comment.update_all({}) }
45
+
46
+ assert_equal "Empty list of attributes to change", error.message
47
+ end
48
+
49
+ def test_update_all_with_group_by
50
+ minimum_comments_count = 2
51
+
52
+ Post.most_commented(minimum_comments_count).update_all(title: "ig")
53
+ posts = Post.most_commented(minimum_comments_count).all.to_a
54
+
55
+ assert_operator posts.length, :>, 0
56
+ assert posts.all? { |post| post.comments.length >= minimum_comments_count }
57
+ assert posts.all? { |post| "ig" == post.title }
58
+
59
+ post = Post.joins(:comments).group("posts.id", "posts.author_id", "posts.title", "posts.body", "posts.type", "posts.legacy_comments_count", "posts.taggings_with_delete_all_count", "posts.taggings_with_destroy_count", "posts.tags_count", "posts.indestructible_tags_count", "posts.tags_with_destroy_count", "posts.tags_with_nullify_count").having("count(comments.id) < #{minimum_comments_count}").first
60
+ assert_not_equal "ig", post.title
43
61
  end
44
62
 
45
63
  def test_update_all_with_joins
@@ -50,10 +68,10 @@ class UpdateAllTest < ActiveRecord::TestCase
50
68
  assert_equal pets.count, pets.update_all(name: "Bob")
51
69
  end
52
70
 
53
- if current_adapter?(:Mysql2Adapter)
54
- assert_no_match %r/SELECT DISTINCT #{Regexp.escape(Pet.connection.quote_table_name("pets.pet_id"))}/, sqls.last
71
+ if current_adapter?(:Mysql2Adapter, :TrilogyAdapter)
72
+ assert_no_match %r/SELECT DISTINCT #{Regexp.escape(quote_table_name("pets.pet_id"))}/, sqls.last
55
73
  else
56
- assert_match %r/SELECT #{Regexp.escape(Pet.connection.quote_table_name("pets.pet_id"))}/, sqls.last
74
+ assert_match %r/SELECT #{Regexp.escape(quote_table_name("pets.pet_id"))}/, sqls.last
57
75
  end
58
76
  end
59
77
 
@@ -117,6 +135,19 @@ class UpdateAllTest < ActiveRecord::TestCase
117
135
  assert_not_equal previously_updated_at, developer.updated_at
118
136
  end
119
137
 
138
+ def test_touch_all_with_aliased_for_update_timestamp
139
+ assert Developer.attribute_aliases.key?("updated_at")
140
+
141
+ developer = developers(:david)
142
+ previously_created_at = developer.created_at
143
+ previously_updated_at = developer.updated_at
144
+ Developer.where(name: "David").touch_all(:updated_at)
145
+ developer.reload
146
+
147
+ assert_equal previously_created_at, developer.created_at
148
+ assert_not_equal previously_updated_at, developer.updated_at
149
+ end
150
+
120
151
  def test_touch_all_with_given_time
121
152
  developer = developers(:david)
122
153
  previously_created_at = developer.created_at
@@ -171,6 +202,24 @@ class UpdateAllTest < ActiveRecord::TestCase
171
202
  end
172
203
  end
173
204
 
205
+ def test_update_bang_on_relation
206
+ topic1 = TopicWithCallbacks.create! title: "arel", author_name: nil
207
+ topic2 = TopicWithCallbacks.create! title: "activerecord", author_name: nil
208
+ topic3 = TopicWithCallbacks.create! title: "ar", author_name: nil
209
+ topics = TopicWithCallbacks.where(id: [topic1.id, topic2.id])
210
+ topics.update!(title: "adequaterecord")
211
+
212
+ assert_equal TopicWithCallbacks.count, TopicWithCallbacks.topic_count
213
+
214
+ assert_equal "adequaterecord", topic1.reload.title
215
+ assert_equal "adequaterecord", topic2.reload.title
216
+ assert_equal "ar", topic3.reload.title
217
+ # Testing that the before_update callbacks have run
218
+ assert_equal "David", topic1.reload.author_name
219
+ assert_equal "David", topic2.reload.author_name
220
+ assert_nil topic3.reload.author_name
221
+ end
222
+
174
223
  def test_update_all_cares_about_optimistic_locking
175
224
  david = people(:david)
176
225
 
@@ -266,31 +315,36 @@ class UpdateAllTest < ActiveRecord::TestCase
266
315
  end
267
316
  end
268
317
 
269
- # Oracle UPDATE does not support ORDER BY
270
- unless current_adapter?(:OracleAdapter)
271
- def test_update_all_ignores_order_without_limit_from_association
272
- author = authors(:david)
273
- assert_nothing_raised do
274
- assert_equal author.posts_with_comments_and_categories.length, author.posts_with_comments_and_categories.update_all([ "body = ?", "bulk update!" ])
275
- end
318
+ def test_update_all_composite_model_with_join_subquery
319
+ agreement = cpk_order_agreements(:order_agreement_three)
320
+ join_scope = Cpk::Order.joins(:order_agreements).where(order_agreements: { signature: agreement.signature })
321
+ assert_equal 1, join_scope.update_all(status: "shipped")
322
+ end
323
+
324
+ def test_update_all_ignores_order_without_limit_from_association
325
+ author = authors(:david)
326
+ assert_nothing_raised do
327
+ assert_equal author.posts_with_comments_and_categories.length, author.posts_with_comments_and_categories.update_all([ "body = ?", "bulk update!" ])
276
328
  end
329
+ end
277
330
 
278
- def test_update_all_doesnt_ignore_order
279
- assert_equal authors(:david).id + 1, authors(:mary).id # make sure there is going to be a duplicate PK error
280
- test_update_with_order_succeeds = lambda do |order|
281
- Author.order(order).update_all("id = id + 1")
282
- rescue ActiveRecord::ActiveRecordError
283
- false
284
- end
331
+ def test_update_all_doesnt_ignore_order
332
+ skip "DB2 enforces unique constraints at statement end, so ORDER effect is not observable" if current_adapter?(:IBM_DBAdapter)
333
+
334
+ assert_equal authors(:david).id + 1, authors(:mary).id # make sure there is going to be a duplicate PK error
335
+ test_update_with_order_succeeds = lambda do |order|
336
+ Author.order(order).update_all("id = id + 1")
337
+ rescue ActiveRecord::ActiveRecordError
338
+ false
339
+ end
285
340
 
286
- if test_update_with_order_succeeds.call("id DESC")
287
- # test that this wasn't a fluke and using an incorrect order results in an exception
288
- assert_not test_update_with_order_succeeds.call("id ASC")
289
- else
290
- # test that we're failing because the current Arel's engine doesn't support UPDATE ORDER BY queries is using subselects instead
291
- assert_sql(/\AUPDATE .+ \(SELECT .* ORDER BY id DESC\)\z/i) do
292
- test_update_with_order_succeeds.call("id DESC")
293
- end
341
+ if test_update_with_order_succeeds.call("id DESC")
342
+ # test that this wasn't a fluke and using an incorrect order results in an exception
343
+ assert_not test_update_with_order_succeeds.call("id ASC")
344
+ else
345
+ # test that we're failing because the current Arel's engine doesn't support UPDATE ORDER BY queries is using subselects instead
346
+ assert_queries_match(/\AUPDATE .+ \(SELECT .* ORDER BY id DESC\)\z/i) do
347
+ test_update_with_order_succeeds.call("id DESC")
294
348
  end
295
349
  end
296
350
 
@@ -7,21 +7,201 @@ require "models/human"
7
7
  require "models/essay"
8
8
  require "models/comment"
9
9
  require "models/categorization"
10
+ require "models/book"
11
+ require "models/cpk"
10
12
 
11
13
  module ActiveRecord
12
14
  class WhereChainTest < ActiveRecord::TestCase
13
- fixtures :posts, :comments, :authors, :humans, :essays, :author_addresses
15
+ fixtures :posts, :comments, :authors, :humans, :essays, :author_addresses, :books
16
+
17
+ def test_associated_with_association
18
+ Post.where.associated(:author).tap do |relation|
19
+ assert_includes relation, posts(:welcome)
20
+ assert_includes relation, posts(:sti_habtm)
21
+ assert_not_includes relation, posts(:authorless)
22
+ end
23
+ end
24
+
25
+ def test_associated_with_child_association
26
+ Comment.where.associated(:children).tap do |relation|
27
+ assert_includes relation, comments(:greetings)
28
+ assert_not_includes relation, comments(:more_greetings)
29
+ end
30
+ end
31
+
32
+ def test_associated_with_multiple_associations
33
+ Post.where.associated(:author, :comments).tap do |relation|
34
+ assert_includes relation, posts(:welcome)
35
+ assert_not_includes relation, posts(:sti_habtm)
36
+ assert_not_includes relation, posts(:authorless)
37
+ end
38
+ end
39
+
40
+ def test_associated_with_invalid_association_name
41
+ e = assert_raises(ArgumentError) do
42
+ Post.where.associated(:cars).to_a
43
+ end
44
+
45
+ assert_match(/An association named `:cars` does not exist on the model `Post`\./, e.message)
46
+ end
47
+
48
+ def test_associated_merged_with_scope_on_association
49
+ assert_equal Author.find(1).posts.count, Post.where.associated(:author).merge(Author.where(id: 1)).count
50
+ end
51
+
52
+ def test_associated_unscoped_merged_with_scope_on_association
53
+ assert_equal Author.find(1).posts.count, Post.unscope(:where).where.associated(:author).merge(Author.where(id: 1)).count
54
+ end
55
+
56
+ def test_associated_unscoped_merged_joined_with_scope_on_association
57
+ assert_equal Author.find(1).posts.count, Post.joins(:author).unscope(:where).where.associated(:author).merge(Author.where(id: 1)).count
58
+ end
59
+
60
+ def test_associated_unscoped_merged_joined_extended_early_with_scope_on_association
61
+ assert_equal Author.find(1).posts.count, Post.extending(Post::NamedExtension).joins(:author).unscope(:where).where.associated(:author).merge(Author.where(id: 1)).count
62
+ end
63
+
64
+ def test_associated_unscoped_merged_joined_extended_late_with_scope_on_association
65
+ assert_equal Author.find(1).posts.count, Post.joins(:author).unscope(:where).where.associated(:author).merge(Author.where(id: 1)).extending(Post::NamedExtension).count
66
+ end
67
+
68
+ def test_associated_ordered_merged_with_scope_on_association
69
+ assert_equal Author.find(1).posts.count, Post.order(created_at: :desc).where.associated(:author).merge(Author.where(id: 1)).count
70
+ end
71
+
72
+ def test_associated_ordered_merged_joined_with_scope_on_association
73
+ assert_equal Author.find(1).posts.count, Post.joins(:author).order(created_at: :desc).where.associated(:author).merge(Author.where(id: 1)).count
74
+ end
75
+
76
+ def test_associated_with_enum
77
+ assert_equal Author.find(2), Author.joins(:reading_listing).where.associated(:reading_listing).first
78
+ end
79
+
80
+ def test_associated_with_enum_ordered
81
+ assert_equal Author.find(2), Author.order(id: :desc).joins(:reading_listing).where.associated(:reading_listing).first
82
+ end
83
+
84
+ def test_associated_with_enum_unscoped
85
+ assert_equal Author.find(2), Author.unscope(:where).joins(:reading_listing).where.associated(:reading_listing).first
86
+ end
87
+
88
+ def test_associated_with_enum_extended_early
89
+ assert_equal Author.find(2), Author.extending(Author::NamedExtension).order(id: :desc).joins(:reading_listing).where.associated(:reading_listing).first
90
+ end
91
+
92
+ def test_associated_with_enum_extended_late
93
+ assert_equal Author.find(2), Author.order(id: :desc).joins(:reading_listing).where.associated(:reading_listing).extending(Author::NamedExtension).first
94
+ end
95
+
96
+ def test_associated_with_add_joins_before
97
+ Comment.joins(:children).where.associated(:children).tap do |relation|
98
+ assert_includes relation, comments(:greetings)
99
+ assert_not_includes relation, comments(:more_greetings)
100
+ end
101
+ end
102
+
103
+ def test_associated_with_add_left_joins_before
104
+ Comment.left_joins(:children).where.associated(:children).tap do |relation|
105
+ assert_includes relation, comments(:greetings)
106
+ assert_not_includes relation, comments(:more_greetings)
107
+ end
108
+ end
109
+
110
+ def test_associated_with_add_left_outer_joins_before
111
+ Comment.left_outer_joins(:children).where.associated(:children).tap do |relation|
112
+ assert_includes relation, comments(:greetings)
113
+ assert_not_includes relation, comments(:more_greetings)
114
+ end
115
+ end
116
+
117
+ def test_associated_with_composite_primary_key
118
+ author = Cpk::Author.create!(id: [1, 2])
119
+ Cpk::Book.create!(id: [author.id, 2])
120
+
121
+ assert_predicate Cpk::Author.where.associated(:books), :any?
122
+ end
14
123
 
15
124
  def test_missing_with_association
16
- assert posts(:authorless).author.blank?
125
+ assert_predicate posts(:authorless).author, :blank?
17
126
  assert_equal [posts(:authorless)], Post.where.missing(:author).to_a
18
127
  end
19
128
 
129
+ def test_missing_with_child_association
130
+ Comment.where.missing(:children).tap do |relation|
131
+ assert_includes relation, comments(:more_greetings)
132
+ assert_not_includes relation, comments(:greetings)
133
+ end
134
+ end
135
+
136
+ def test_missing_with_invalid_association_name
137
+ e = assert_raises(ArgumentError) do
138
+ Post.where.missing(:cars).to_a
139
+ end
140
+
141
+ assert_match(/An association named `:cars` does not exist on the model `Post`\./, e.message)
142
+ end
143
+
20
144
  def test_missing_with_multiple_association
21
- assert posts(:authorless).comments.empty?
145
+ assert_predicate posts(:authorless).comments, :empty?
22
146
  assert_equal [posts(:authorless)], Post.where.missing(:author, :comments).to_a
23
147
  end
24
148
 
149
+ def test_missing_merged_with_scope_on_association
150
+ # This query does not make much logical sense, but it is testing
151
+ # that the generated SQL query is valid.
152
+ assert_equal Author.find(1).posts.count, Post.where.missing(:author).merge(Author.where(id: 1)).count
153
+ end
154
+
155
+ def test_missing_unscoped_merged_with_scope_on_association
156
+ assert_equal Author.find(1).posts.count, Post.joins(:author).unscope(:where).where.missing(:author).merge(Author.where(id: 1)).count
157
+ end
158
+
159
+ def test_missing_unscoped_merged_joined_with_scope_on_association
160
+ assert_equal Author.find(1).posts.count, Post.unscope(:where).where.missing(:author).merge(Author.where(id: 1)).count
161
+ end
162
+
163
+ def test_missing_ordered_merged_with_scope_on_association
164
+ assert_equal Author.find(1).posts.count, Post.order(created_at: :desc).where.missing(:author).merge(Author.where(id: 1)).count
165
+ end
166
+
167
+ def test_missing_ordered_merged_joined_with_scope_on_association
168
+ assert_equal Author.find(1).posts.count, Post.joins(:author).order(created_at: :desc).where.missing(:author).merge(Author.where(id: 1)).count
169
+ end
170
+
171
+ def test_missing_unscoped_merged_joined_extended_early_with_scope_on_association
172
+ assert_equal Author.find(1).posts.count, Post.extending(Post::NamedExtension).joins(:author).unscope(:where).where.missing(:author).merge(Author.where(id: 1)).count
173
+ end
174
+
175
+ def test_missing_unscoped_merged_joined_extended_late_with_scope_on_association
176
+ assert_equal Author.find(1).posts.count, Post.joins(:author).unscope(:where).where.missing(:author).merge(Author.where(id: 1)).extending(Post::NamedExtension).count
177
+ end
178
+
179
+ def test_missing_with_enum
180
+ assert_equal Author.find(2), Author.joins(:reading_listing).where.missing(:unread_listing).first
181
+ end
182
+
183
+ def test_missing_with_enum_ordered
184
+ assert_equal Author.find(2), Author.order(id: :desc).joins(:reading_listing).where.missing(:unread_listing).first
185
+ end
186
+
187
+ def test_missing_with_enum_unscoped
188
+ assert_equal Author.find(2), Author.unscope(:where).joins(:reading_listing).where.missing(:unread_listing).first
189
+ end
190
+
191
+ def test_missing_with_enum_extended_early
192
+ assert_equal Author.find(2), Author.extending(Author::NamedExtension).order(id: :desc).joins(:reading_listing).where.missing(:unread_listing).first
193
+ end
194
+
195
+ def test_missing_with_enum_extended_late
196
+ assert_equal Author.find(2), Author.order(id: :desc).joins(:reading_listing).where.missing(:unread_listing).extending(Author::NamedExtension).first
197
+ end
198
+
199
+ def test_missing_with_composite_primary_key
200
+ Cpk::Book.create!(id: [1, 2])
201
+
202
+ assert_predicate Cpk::Book.where.missing(:author), :any?
203
+ end
204
+
25
205
  def test_not_inverts_where_clause
26
206
  relation = Post.where.not(title: "hello")
27
207
  expected_where_clause = Post.where(title: "hello").where_clause.invert
@@ -137,5 +317,12 @@ module ActiveRecord
137
317
 
138
318
  assert_equal expected.to_a, relation.to_a
139
319
  end
320
+
321
+ def test_rewhere_with_nil
322
+ relation = Post.where(comments_count: 16).rewhere(nil)
323
+ expected = Post.all
324
+
325
+ assert_equal expected.to_a, relation.to_a
326
+ end
140
327
  end
141
328
  end
@@ -74,6 +74,35 @@ class ActiveRecord::Relation
74
74
  assert_equal expected, a.merge(b)
75
75
  end
76
76
 
77
+ test "merge with or/and correctly handles SQL literals and attributes" do
78
+ skip "DB2 wraps SQL literal predicates differently when merging OR/AND where clauses" if current_adapter?(:IBM_DBAdapter)
79
+
80
+ a = WhereClause.new([
81
+ table["id"].eq(1),
82
+ Arel::Nodes::Grouping.new(Arel.sql("foo = bar"))
83
+ ])
84
+ b = (a + WhereClause.new([table["attr_1"].eq("val_1")])).or(
85
+ WhereClause.new([table["attr_2"].eq("val_2")])
86
+ )
87
+
88
+ expected = WhereClause.new([
89
+ table["id"].eq(1),
90
+ Arel::Nodes::Grouping.new(Arel.sql("foo = bar")),
91
+ Arel::Nodes::Grouping.new(
92
+ Arel::Nodes::Or.new([
93
+ Arel::Nodes::And.new([
94
+ table["id"].eq(1),
95
+ Arel::Nodes::Grouping.new(Arel.sql("foo = bar")),
96
+ table["attr_1"].eq("val_1")
97
+ ]),
98
+ table["attr_2"].eq("val_2")
99
+ ])
100
+ )
101
+ ])
102
+
103
+ assert_equal expected, a.merge(b)
104
+ end
105
+
77
106
  test "a clause knows if it is empty" do
78
107
  assert_empty WhereClause.empty
79
108
  assert_not_empty WhereClause.new(["anything"])
@@ -185,7 +214,7 @@ class ActiveRecord::Relation
185
214
  other_clause = WhereClause.new([table["name"].eq(bind_param("Sean"))])
186
215
  expected_ast =
187
216
  Arel::Nodes::Grouping.new(
188
- Arel::Nodes::Or.new(table["id"].eq(bind_param(1)), table["name"].eq(bind_param("Sean")))
217
+ Arel::Nodes::Or.new([table["id"].eq(bind_param(1)), table["name"].eq(bind_param("Sean"))])
189
218
  )
190
219
 
191
220
  assert_equal expected_ast.to_sql, where_clause.or(other_clause).ast.to_sql
@@ -245,6 +274,19 @@ class ActiveRecord::Relation
245
274
  assert_equal only_common, common_with_extra.or(only_common)
246
275
  end
247
276
 
277
+ test "supports hash equality" do
278
+ h = Hash.new(0)
279
+ h[WhereClause.new(["a"])] += 1
280
+ h[WhereClause.new(["a"])] += 1
281
+ h[WhereClause.new(["b"])] += 1
282
+
283
+ expected = {
284
+ WhereClause.new(["a"]) => 2,
285
+ WhereClause.new(["b"]) => 1
286
+ }
287
+ assert_equal expected, h
288
+ end
289
+
248
290
  private
249
291
  def table
250
292
  Arel::Table.new("table")