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
@@ -16,6 +16,7 @@ require "models/price_estimate"
16
16
  require "models/topic"
17
17
  require "models/treasure"
18
18
  require "models/vertex"
19
+ require "models/cpk"
19
20
  require "support/stubs/strong_parameters"
20
21
 
21
22
  module ActiveRecord
@@ -33,10 +34,6 @@ module ActiveRecord
33
34
  assert_equal [authors(:bob)], Author.joins(:categories).where(categories: categories(:technology))
34
35
  end
35
36
 
36
- def test_where_with_aliased_association
37
- assert_equal [comments(:does_it_hurt)], Comment.where(entry: posts(:thinking))
38
- end
39
-
40
37
  def test_type_cast_is_not_evaluated_at_relation_build_time
41
38
  posts = nil
42
39
 
@@ -95,6 +92,74 @@ module ActiveRecord
95
92
  assert_equal posts(:welcome), Post.rewhere(title: "Welcome to the weblog").first
96
93
  end
97
94
 
95
+ def test_where_with_tuple_syntax
96
+ first_topic = topics(:first)
97
+ third_topic = topics(:third)
98
+
99
+ key = [:title, :author_name]
100
+
101
+ conditions = [
102
+ [first_topic.title, first_topic.author_name],
103
+ [third_topic.title, third_topic.author_name],
104
+ ]
105
+
106
+ assert_equal [first_topic], Topic.where([:id] => [[first_topic.id]])
107
+ assert_equal [first_topic, third_topic].sort, Topic.where(key => conditions).sort
108
+ end
109
+
110
+ def test_where_with_tuple_syntax_on_composite_models
111
+ book_one = Cpk::Book.create!(id: [1, 2])
112
+ book_two = Cpk::Book.create!(id: [3, 4])
113
+
114
+ assert_equal [book_one], Cpk::Book.where([:author_id, :id] => [[1, 2]])
115
+ assert_equal [book_one, book_two].sort, Cpk::Book.where(Cpk::Book.primary_key => [[1, 2], [3, 4]]).sort
116
+ assert_empty Cpk::Book.where([:author_id, :id] => [[1, 4], [3, 2]])
117
+ end
118
+
119
+ def test_where_with_tuple_syntax_with_incorrect_arity
120
+ error = assert_raise ArgumentError do
121
+ Cpk::Book.where([:one, :two, :three] => [1, 2, 3])
122
+ end
123
+
124
+ assert_match(/Expected corresponding value for.*to be an Array/, error.message)
125
+
126
+ error = assert_raise ArgumentError do
127
+ Cpk::Book.where([:one, :two] => 1)
128
+ end
129
+
130
+ assert_match(/Expected corresponding value for.*to be an Array/, error.message)
131
+ end
132
+
133
+ def test_where_with_tuple_syntax_and_regular_syntax_combined
134
+ book_one = Cpk::Book.create!(id: [1, 2], title: "The Alchemist")
135
+ book_two = Cpk::Book.create!(id: [3, 4], title: "The Alchemist")
136
+
137
+ assert_equal [book_one, book_two].sort, Cpk::Book.where(title: "The Alchemist").sort
138
+ assert_equal [book_one, book_two].sort, Cpk::Book.where(title: "The Alchemist", [:author_id, :id] => [[1, 2], [3, 4]]).sort
139
+ assert_equal [book_two], Cpk::Book.where(title: "The Alchemist", [:author_id, :id] => [[3, 4]])
140
+ end
141
+
142
+ def test_with_tuple_syntax_and_large_values_list
143
+ # sqlite3 raises "Expression tree is too large (maximum depth 1000)"
144
+ skip if current_adapter?(:SQLite3Adapter)
145
+
146
+ assert_nothing_raised do
147
+ ids = [[1, 2]] * 1500
148
+ Cpk::Book.where([:author_id, :id] => ids).to_sql
149
+ end
150
+ end
151
+
152
+ def test_where_with_nil_cpk_association
153
+ skip "DB2 CPK association nil predicate expansion is not supported in this environment" if current_adapter?(:IBM_DBAdapter)
154
+
155
+ order = Cpk::Order.create!(id: [1, 2])
156
+ book = order.books.create!(id: [3, 4])
157
+ assert_includes Cpk::Book.where(order: order), book
158
+
159
+ book.update!(order: nil)
160
+ assert_includes Cpk::Book.where(order: nil), book
161
+ end
162
+
98
163
  def test_belongs_to_shallow_where
99
164
  author = Author.new
100
165
  author.id = 1
@@ -265,8 +330,8 @@ module ActiveRecord
265
330
  model.is_a?(klass)
266
331
  end
267
332
 
268
- def method_missing(method, *args, &block)
269
- model.send(method, *args, &block)
333
+ def method_missing(...)
334
+ model.send(...)
270
335
  end
271
336
  end
272
337
 
@@ -336,6 +401,11 @@ module ActiveRecord
336
401
  assert_equal 0, count
337
402
  end
338
403
 
404
+ def test_where_with_rational_for_string_column
405
+ count = Post.where(title: Rational(0)).count
406
+ assert_equal 0, count
407
+ end
408
+
339
409
  def test_where_with_duration_for_string_column
340
410
  count = Post.where(title: 0.seconds).count
341
411
  assert_equal 0, count
@@ -369,7 +439,7 @@ module ActiveRecord
369
439
  def test_where_on_association_with_relation_performs_subselect_not_two_queries
370
440
  author = authors(:david)
371
441
 
372
- assert_queries(1) do
442
+ assert_queries_count(1) do
373
443
  Essay.where(writer: Author.where(id: author.id)).to_a
374
444
  end
375
445
  end
@@ -405,6 +475,11 @@ module ActiveRecord
405
475
  assert_equal essays(:david_modest_proposal), essay
406
476
  end
407
477
 
478
+ def test_where_on_association_with_collection_polymorphic_relation
479
+ treasures = Treasure.where(name: ["diamond", "emerald"], price_estimates: PriceEstimate.all)
480
+ assert_equal [treasures(:diamond)], treasures
481
+ end
482
+
408
483
  def test_where_with_strong_parameters
409
484
  author = authors(:david)
410
485
  params = ProtectedParams.new(name: author.name)
@@ -425,5 +500,18 @@ module ActiveRecord
425
500
  def test_where_with_unsupported_arguments
426
501
  assert_raises(ArgumentError) { Author.where(42) }
427
502
  end
503
+
504
+ def test_invert_where
505
+ author = authors(:david)
506
+ posts = author.posts.where.not(id: 1)
507
+
508
+ assert_equal 1, posts.invert_where.first.id
509
+ end
510
+
511
+ def test_nested_conditional_on_enum
512
+ post = Post.first
513
+ Comment.create!(label: :default, post: post, body: "Nice weather today")
514
+ assert_equal [post], Post.joins(:comments).where(comments: { label: :default, body: "Nice weather today" }).to_a
515
+ end
428
516
  end
429
517
  end
@@ -0,0 +1,165 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/helper"
4
+ require "models/comment"
5
+ require "models/post"
6
+ require "models/company"
7
+
8
+ module ActiveRecord
9
+ class WithTest < ActiveRecord::TestCase
10
+ fixtures :comments, :posts, :companies
11
+
12
+ SPECIAL_POSTS = [2].freeze
13
+ POSTS_WITH_TAGS = [1, 2, 7, 8, 9, 10, 11].freeze
14
+ POSTS_WITH_COMMENTS = [1, 2, 4, 5, 7].freeze
15
+ POSTS_WITH_MULTIPLE_COMMENTS = [1, 4, 5].freeze
16
+ POSTS_WITH_TAGS_AND_COMMENTS = (POSTS_WITH_COMMENTS & POSTS_WITH_TAGS).sort.freeze
17
+ POSTS_WITH_TAGS_AND_MULTIPLE_COMMENTS = (POSTS_WITH_MULTIPLE_COMMENTS & POSTS_WITH_TAGS).sort.freeze
18
+
19
+ if ActiveRecord::Base.lease_connection.supports_common_table_expressions?
20
+ def test_with_when_hash_is_passed_as_an_argument
21
+ relation = Post
22
+ .with(posts_with_comments: Post.where("legacy_comments_count > 0"))
23
+ .from("posts_with_comments AS posts")
24
+
25
+ assert_equal POSTS_WITH_COMMENTS, relation.order(:id).pluck(:id)
26
+ end
27
+
28
+ def test_with_when_hash_with_multiple_elements_of_different_type_is_passed_as_an_argument
29
+ skip "DB2 does not support BoundSqlLiteral values in WITH hash expressions" if current_adapter?(:IBM_DBAdapter)
30
+
31
+ cte_options = {
32
+ posts_with_tags: Post.arel_table.project(Arel.star).where(Post.arel_table[:tags_count].gt(0)),
33
+ posts_with_tags_and_truthy: Arel.sql("SELECT * FROM posts_with_tags WHERE 1=1"),
34
+ posts_with_tags_and_comments: Arel.sql("SELECT * FROM posts_with_tags_and_truthy WHERE tags_count > ?", 0),
35
+ "posts_with_tags_and_multiple_comments" => Post.where("legacy_comments_count > 1").from("posts_with_tags_and_comments AS posts")
36
+ }
37
+ relation = Post.with(cte_options).from("posts_with_tags_and_multiple_comments AS posts")
38
+
39
+ assert_equal POSTS_WITH_TAGS_AND_MULTIPLE_COMMENTS, relation.order(:id).pluck(:id)
40
+ end
41
+
42
+ def test_with_when_invalid_argument_is_passed
43
+ assert_raises ArgumentError, match: /\AUnsupported argument type: #<Post:0x[0-9a-f]+> Post\z/ do
44
+ Post.with(Post.where(type: "Post"))
45
+ end
46
+ end
47
+
48
+ def test_multiple_with_calls
49
+ relation = Post
50
+ .with(posts_with_tags: Post.where("tags_count > 0"))
51
+ .from("posts_with_tags_and_comments AS posts")
52
+ .with(posts_with_tags_and_comments: Arel.sql("SELECT * FROM posts_with_tags WHERE legacy_comments_count > 0"))
53
+
54
+ assert_equal POSTS_WITH_TAGS_AND_COMMENTS, relation.order(:id).pluck(:id)
55
+ end
56
+
57
+ def test_multiple_dupicate_with_calls
58
+ posts_with_tags = Post.where("tags_count > 0")
59
+ relation = Post
60
+ .with(posts_with_tags: posts_with_tags, one_more_posts_with_tags: posts_with_tags)
61
+ .with(posts_with_tags: posts_with_tags)
62
+ .from("posts_with_tags AS posts")
63
+
64
+ assert_equal POSTS_WITH_TAGS, relation.order(:id).pluck(:id)
65
+ end
66
+
67
+ def test_count_after_with_call
68
+ relation = Post.with(posts_with_comments: Post.where("legacy_comments_count > 0"))
69
+
70
+ assert_equal Post.count, relation.count
71
+ assert_equal POSTS_WITH_COMMENTS.size, relation.from("posts_with_comments AS posts").count
72
+ assert_equal POSTS_WITH_COMMENTS.size, relation.joins("JOIN posts_with_comments ON posts_with_comments.id = posts.id").count
73
+ end
74
+
75
+ def test_with_when_called_from_active_record_scope
76
+ assert_equal POSTS_WITH_TAGS, Post.with_tags_cte.order(:id).pluck(:id)
77
+ end
78
+
79
+ def test_with_when_invalid_params_are_passed
80
+ assert_raise(ArgumentError) { Post.with(posts_with_tags: nil).load }
81
+ assert_raise(ArgumentError) { Post.with(posts_with_tags: [Post.where("tags_count > 0"), 5]).load }
82
+ end
83
+
84
+ def test_with_when_passing_arrays
85
+ relation = Post
86
+ .with(posts_with_special_type_or_tags_or_comments: [
87
+ Post.where(type: "SpecialPost"),
88
+ Arel.sql("SELECT * FROM posts WHERE tags_count > 0"), # arel node on purpose
89
+ Post.where("legacy_comments_count > 0")
90
+ ])
91
+ .from("posts_with_special_type_or_tags_or_comments AS posts")
92
+
93
+ assert_equal (SPECIAL_POSTS + POSTS_WITH_TAGS + POSTS_WITH_COMMENTS).sort, relation.order(:id).pluck(:id)
94
+ end
95
+
96
+ def test_with_when_passing_single_item_array
97
+ relation = Post
98
+ .with(posts_with_special_type_or_tags_or_comments: [Post.where(type: "SpecialPost")])
99
+ .from("posts_with_special_type_or_tags_or_comments AS posts")
100
+
101
+ assert_equal SPECIAL_POSTS.sort, relation.order(:id).pluck(:id)
102
+ end
103
+
104
+ def test_with_recursive
105
+ skip "DB2 does not support this RECURSIVE CTE syntax form" if current_adapter?(:IBM_DBAdapter)
106
+
107
+ top_companies = Company.where(firm_id: nil).to_a
108
+ child_companies = Company.where(firm_id: top_companies).to_a
109
+ top_companies_and_children = (top_companies.map(&:id) + child_companies.map(&:id)).sort
110
+
111
+ relation = Company.with_recursive(
112
+ top_companies_and_children: [
113
+ Company.where(firm_id: nil),
114
+ Company.joins("JOIN top_companies_and_children ON companies.firm_id = top_companies_and_children.id"),
115
+ ]
116
+ ).from("top_companies_and_children AS companies")
117
+
118
+ assert_equal top_companies_and_children, relation.order(:id).pluck(:id)
119
+ assert_match "WITH RECURSIVE", relation.to_sql
120
+ end
121
+
122
+ def test_with_joins
123
+ relation = Post
124
+ .with(commented_posts: Comment.select(:post_id).distinct)
125
+ .joins(:commented_posts)
126
+
127
+ assert_equal POSTS_WITH_COMMENTS, relation.order(:id).pluck(:id)
128
+ end
129
+
130
+ def test_with_left_joins
131
+ relation = Post
132
+ .with(commented_posts: Comment.select(:post_id).distinct)
133
+ .left_outer_joins(:commented_posts)
134
+ .select("posts.*, commented_posts.post_id as has_comments")
135
+
136
+ records = relation.order(:id).to_a
137
+
138
+ # Make sure we load all records (thus, left outer join is used)
139
+ assert_equal Post.count, records.size
140
+ assert_equal POSTS_WITH_COMMENTS, records.filter_map { _1.id if _1.has_comments }
141
+ end
142
+
143
+ def test_raises_when_using_block
144
+ assert_raises(ArgumentError, match: "does not accept a block") do
145
+ Post.with(attributes_for_inspect: :id) { }
146
+ end
147
+ end
148
+
149
+ def test_unscoping
150
+ relation = Post.with(posts_with_comments: Post.where("legacy_comments_count > 0"))
151
+
152
+ assert_equal true, relation.values[:with].flat_map(&:keys).include?(:posts_with_comments)
153
+ relation = relation.unscope(:with)
154
+ assert_nil relation.values[:with]
155
+ assert_equal Post.count, relation.count
156
+ end
157
+ else
158
+ def test_common_table_expressions_are_unsupported
159
+ assert_raises ActiveRecord::StatementInvalid do
160
+ Post.with_tags_cte.order(:id).pluck(:id)
161
+ end
162
+ end
163
+ end
164
+ end
165
+ end
@@ -13,7 +13,7 @@ module ActiveRecord
13
13
 
14
14
  def test_construction
15
15
  relation = Relation.new(FakeKlass, table: :b)
16
- assert_equal FakeKlass, relation.klass
16
+ assert_equal FakeKlass, relation.model
17
17
  assert_equal :b, relation.table
18
18
  assert_not relation.loaded, "relation is not loaded"
19
19
  end
@@ -204,7 +204,7 @@ module ActiveRecord
204
204
 
205
205
  relation = Relation.new(klass)
206
206
  relation.merge!(where: ["foo = ?", "bar"])
207
- assert_equal Relation::WhereClause.new(["foo = bar"]), relation.where_clause
207
+ assert_equal Relation::WhereClause.new([Arel.sql("(foo = ?)", "bar")]), relation.where_clause
208
208
  end
209
209
 
210
210
  def test_merging_readonly_false
@@ -247,8 +247,13 @@ module ActiveRecord
247
247
  nb_inner_join = queries.sum { |sql| sql.scan(/INNER\s+JOIN/i).size }
248
248
  assert_equal 3, nb_inner_join, "Wrong amount of INNER JOIN in query"
249
249
 
250
- # using `\W` as the column separator
251
- assert queries.any? { |sql| %r[INNER\s+JOIN\s+#{Regexp.escape(Author.quoted_table_name)}\s+authors_categorizations]i.match?(sql) }, "Should be aliasing the child INNER JOINs in query"
250
+ alias_pattern = if current_adapter?(:IBM_DBAdapter)
251
+ %r[INNER\s+JOIN\s+#{Regexp.escape(Author.quoted_table_name)}\s+authors_categorizations\W]i
252
+ else
253
+ # using `\W` as the column separator
254
+ %r[INNER\s+JOIN\s+#{Regexp.escape(Author.quoted_table_name)}\s+\Wauthors_categorizations\W]i
255
+ end
256
+ assert queries.any? { |sql| alias_pattern.match?(sql) }, "Should be aliasing the child INNER JOINs in query"
252
257
  end
253
258
 
254
259
  def test_relation_with_merged_joins_aliased_works
@@ -256,9 +261,9 @@ module ActiveRecord
256
261
  posts_with_joins_and_merges = Post.joins(:author, :categorizations)
257
262
  .merge(Author.select(:id)).merge(categorizations_with_authors)
258
263
 
259
- author_with_posts = Author.joins(:posts).ids
260
- categorizations_with_author = Categorization.joins(:author).ids
261
- posts_with_author_and_categorizations = Post.joins(:categorizations).where(author_id: author_with_posts, categorizations: { id: categorizations_with_author }).ids
264
+ author_with_posts = Author.joins(:posts).pluck(:id)
265
+ categorizations_with_author = Categorization.joins(:author).pluck(:id)
266
+ posts_with_author_and_categorizations = Post.joins(:categorizations).where(author_id: author_with_posts, categorizations: { id: categorizations_with_author }).pluck(:id)
262
267
 
263
268
  assert_equal posts_with_author_and_categorizations.size, posts_with_joins_and_merges.count
264
269
  assert_equal posts_with_author_and_categorizations.size, posts_with_joins_and_merges.to_a.size
@@ -291,9 +296,8 @@ module ActiveRecord
291
296
 
292
297
  def test_select_quotes_when_using_from_clause
293
298
  skip_if_sqlite3_version_includes_quoting_bug
294
- quoted_join = ActiveRecord::Base.connection.quote_table_name("join")
295
- selected = Post.select(:join).from(Post.select("id as #{quoted_join}")).map(&:join)
296
- assert_equal Post.pluck(:id), selected
299
+ selected = Post.select(:join).from(Post.select("id as #{quote_table_name("join")}")).map(&:join)
300
+ assert_equal Post.pluck(:id).sort, selected.sort
297
301
  end
298
302
 
299
303
  def test_selecting_aliased_attribute_quotes_column_name_when_from_is_used
@@ -331,31 +335,47 @@ module ActiveRecord
331
335
 
332
336
  def test_relation_with_annotation_includes_comment_in_sql
333
337
  post_with_annotation = Post.where(id: 1).annotate("foo")
334
- assert_sql(%r{/\* foo \*/}) do
338
+ assert_queries_match(%r{/\* foo \*/}) do
335
339
  assert post_with_annotation.first, "record should be found"
336
340
  end
337
341
  end
338
342
 
339
343
  def test_relation_with_annotation_chains_sql_comments
340
344
  post_with_annotation = Post.where(id: 1).annotate("foo").annotate("bar")
341
- assert_sql(%r{/\* foo \*/ /\* bar \*/}) do
345
+ assert_queries_match(%r{/\* foo \*/ /\* bar \*/}) do
342
346
  assert post_with_annotation.first, "record should be found"
343
347
  end
344
348
  end
345
349
 
346
350
  def test_relation_with_annotation_filters_sql_comment_delimiters
347
351
  post_with_annotation = Post.where(id: 1).annotate("**//foo//**")
348
- assert_match %r{= 1 /\* foo \*/}, post_with_annotation.to_sql
352
+ assert_includes post_with_annotation.to_sql, "= 1 /* ** //foo// ** */"
349
353
  end
350
354
 
351
355
  def test_relation_with_annotation_includes_comment_in_count_query
352
356
  post_with_annotation = Post.annotate("foo")
353
357
  all_count = Post.all.to_a.count
354
- assert_sql(%r{/\* foo \*/}) do
358
+ assert_queries_match(%r{/\* foo \*/}) do
355
359
  assert_equal all_count, post_with_annotation.count
356
360
  end
357
361
  end
358
362
 
363
+ def test_relation_with_annotation_includes_comment_in_update_all_query
364
+ post_with_annotation = Post.annotate("foo")
365
+ all_count = Post.all.to_a.count
366
+ assert_queries_match(%r{/\* foo \*/}) do
367
+ assert_equal all_count, post_with_annotation.update_all(title: "Same title")
368
+ end
369
+ end
370
+
371
+ def test_relation_with_annotation_includes_comment_in_delete_all_query
372
+ post_with_annotation = Post.annotate("foo")
373
+ all_count = Post.all.to_a.count
374
+ assert_queries_match(%r{/\* foo \*/}) do
375
+ assert_equal all_count, post_with_annotation.delete_all
376
+ end
377
+ end
378
+
359
379
  def test_relation_without_annotation_does_not_include_an_empty_comment
360
380
  log = capture_sql do
361
381
  Post.where(id: 1).first
@@ -367,22 +387,15 @@ module ActiveRecord
367
387
 
368
388
  def test_relation_with_optimizer_hints_filters_sql_comment_delimiters
369
389
  post_with_hint = Post.where(id: 1).optimizer_hints("**//BADHINT//**")
370
- assert_match %r{BADHINT}, post_with_hint.to_sql
371
- assert_no_match %r{\*/BADHINT}, post_with_hint.to_sql
372
- assert_no_match %r{\*//BADHINT}, post_with_hint.to_sql
373
- assert_no_match %r{BADHINT/\*}, post_with_hint.to_sql
374
- assert_no_match %r{BADHINT//\*}, post_with_hint.to_sql
390
+ assert_includes post_with_hint.to_sql, "/*+ ** //BADHINT// ** */"
375
391
  post_with_hint = Post.where(id: 1).optimizer_hints("/*+ BADHINT */")
376
- assert_match %r{/\*\+ BADHINT \*/}, post_with_hint.to_sql
392
+ assert_includes post_with_hint.to_sql, "/*+ BADHINT */"
377
393
  end
378
394
 
379
395
  def test_does_not_duplicate_optimizer_hints_on_merge
380
- puts "test_does_not_duplicate_optimizer_hints_on_merge"
381
- escaped_table = Post.connection.quote_table_name("posts")
396
+ escaped_table = quote_table_name("posts")
382
397
  expected = "SELECT /*+ OMGHINT */ #{escaped_table}.* FROM #{escaped_table}"
383
398
  query = Post.optimizer_hints("OMGHINT").merge(Post.optimizer_hints("OMGHINT")).to_sql
384
- puts "Expected = #{expected}"
385
- puts "Query = #{query}"
386
399
  assert_equal expected, query
387
400
  end
388
401
 
@@ -427,34 +440,26 @@ module ActiveRecord
427
440
  end
428
441
  end
429
442
 
430
- def test_marshal_load_legacy_relation
431
- path = File.expand_path(
432
- "support/marshal_compatibility_fixtures/legacy_relation.dump",
433
- TEST_ROOT
434
- )
435
- assert_equal 11, Marshal.load(File.read(path)).size
436
- end
437
-
438
443
  test "no queries on empty IN" do
439
- assert_queries(0) do
444
+ assert_queries_count(0) do
440
445
  Post.where(id: []).load
441
446
  end
442
447
  end
443
448
 
444
449
  test "can unscope empty IN" do
445
- assert_queries(1) do
450
+ assert_queries_count(1) do
446
451
  Post.where(id: []).unscope(where: :id).load
447
452
  end
448
453
  end
449
454
 
450
455
  test "no queries on empty relation exists?" do
451
- assert_queries(0) do
456
+ assert_queries_count(0) do
452
457
  Post.where(id: []).exists?(123)
453
458
  end
454
459
  end
455
460
 
456
461
  test "no queries on empty condition exists?" do
457
- assert_queries(0) do
462
+ assert_queries_count(0) do
458
463
  Post.all.exists?(id: [])
459
464
  end
460
465
  end
@@ -472,7 +477,7 @@ module ActiveRecord
472
477
 
473
478
  def sqlite3_version_includes_quoting_bug?
474
479
  if current_adapter?(:SQLite3Adapter)
475
- selected_quoted_column_names = ActiveRecord::Base.connection.exec_query(
480
+ selected_quoted_column_names = ActiveRecord::Base.lease_connection.exec_query(
476
481
  'SELECT "join" FROM (SELECT id AS "join" FROM posts) subquery'
477
482
  ).columns
478
483
  ["join"] != selected_quoted_column_names