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
@@ -7,6 +7,7 @@ require "models/developer"
7
7
  require "models/project"
8
8
  require "models/computer"
9
9
  require "models/cat"
10
+ require "models/mentor"
10
11
  require "concurrent/atomic/cyclic_barrier"
11
12
 
12
13
  class DefaultScopingTest < ActiveRecord::TestCase
@@ -79,6 +80,174 @@ class DefaultScopingTest < ActiveRecord::TestCase
79
80
  assert_equal 50000, wheres["salary"]
80
81
  end
81
82
 
83
+ def test_combined_default_scope_without_and_with_all_queries_works
84
+ Mentor.create!
85
+ klass = DeveloperWithIncludedMentorDefaultScopeNotAllQueriesAndDefaultScopeFirmWithAllQueries
86
+
87
+ create_sql = capture_sql { klass.create!(name: "Steve") }.second
88
+
89
+ assert_match(/mentor_id/, create_sql)
90
+ assert_match(/firm_id/, create_sql)
91
+
92
+ developer = klass.find_by!(name: "Steve")
93
+
94
+ update_sql = capture_sql { developer.update(name: "Stephen") }.second
95
+
96
+ assert_no_match(/mentor_id/, update_sql)
97
+ assert_match(/firm_id/, update_sql)
98
+ end
99
+
100
+ def test_default_scope_runs_on_create
101
+ Mentor.create!
102
+ create_sql = capture_sql { DeveloperwithDefaultMentorScopeNot.create!(name: "Eileen") }.second
103
+
104
+ assert_match(/mentor_id/, create_sql)
105
+ end
106
+
107
+ def test_default_scope_with_all_queries_runs_on_create
108
+ Mentor.create!
109
+ create_sql = capture_sql { DeveloperWithDefaultMentorScopeAllQueries.create!(name: "Eileen") }.second
110
+
111
+ assert_match(/mentor_id/, create_sql)
112
+ end
113
+
114
+ def test_nilable_default_scope_with_all_queries_runs_on_create
115
+ create_sql = capture_sql { DeveloperWithDefaultNilableFirmScopeAllQueries.create!(name: "Nikita") }.first
116
+
117
+ assert_no_match(/AND$/, create_sql)
118
+ end
119
+
120
+ def test_default_scope_runs_on_select
121
+ Mentor.create!
122
+ DeveloperwithDefaultMentorScopeNot.create!(name: "Eileen")
123
+ select_sql = capture_sql { DeveloperwithDefaultMentorScopeNot.find_by(name: "Eileen") }.first
124
+
125
+ assert_match(/mentor_id/, select_sql)
126
+ end
127
+
128
+ def test_default_scope_with_all_queries_runs_on_select
129
+ Mentor.create!
130
+ DeveloperWithDefaultMentorScopeAllQueries.create!(name: "Eileen")
131
+ select_sql = capture_sql { DeveloperWithDefaultMentorScopeAllQueries.find_by(name: "Eileen") }.first
132
+
133
+ assert_match(/mentor_id/, select_sql)
134
+ end
135
+
136
+ def test_nilable_default_scope_with_all_queries_runs_on_select
137
+ DeveloperWithDefaultNilableFirmScopeAllQueries.create!(name: "Nikita")
138
+ select_sql = capture_sql { DeveloperWithDefaultNilableFirmScopeAllQueries.find_by(name: "Nikita") }.first
139
+
140
+ assert_no_match(/AND$/, select_sql)
141
+ end
142
+
143
+ def test_default_scope_doesnt_run_on_update
144
+ Mentor.create!
145
+ dev = DeveloperwithDefaultMentorScopeNot.create!(name: "Eileen")
146
+ update_sql = capture_sql { dev.update!(name: "Not Eileen") }.first
147
+
148
+ assert_no_match(/mentor_id/, update_sql)
149
+ end
150
+
151
+ def test_default_scope_with_all_queries_runs_on_update
152
+ Mentor.create!
153
+ dev = DeveloperWithDefaultMentorScopeAllQueries.create!(name: "Eileen")
154
+ update_sql = capture_sql { dev.update!(name: "Not Eileen") }.second
155
+
156
+ assert_match(/mentor_id/, update_sql)
157
+ end
158
+
159
+ def test_nilable_default_scope_with_all_queries_runs_on_update
160
+ dev = DeveloperWithDefaultNilableFirmScopeAllQueries.create!(name: "Nikita")
161
+ update_sql = capture_sql { dev.update!(name: "Not Nikita") }.first
162
+
163
+ assert_no_match(/AND$/, update_sql)
164
+ end
165
+
166
+ def test_default_scope_doesnt_run_on_update_columns
167
+ Mentor.create!
168
+ dev = DeveloperwithDefaultMentorScopeNot.create!(name: "Eileen")
169
+ update_sql = capture_sql { dev.update_columns(name: "Not Eileen") }.first
170
+
171
+ assert_no_match(/mentor_id/, update_sql)
172
+ end
173
+
174
+ def test_default_scope_with_all_queries_runs_on_update_columns
175
+ Mentor.create!
176
+ dev = DeveloperWithDefaultMentorScopeAllQueries.create!(name: "Eileen")
177
+ update_sql = capture_sql { dev.update_columns(name: "Not Eileen") }.first
178
+
179
+ assert_match(/mentor_id/, update_sql)
180
+ end
181
+
182
+ def test_nilable_default_scope_with_all_queries_runs_on_update_columns
183
+ dev = DeveloperWithDefaultNilableFirmScopeAllQueries.create!(name: "Nikita")
184
+ update_sql = capture_sql { dev.update_columns(name: "Not Nikita") }.first
185
+
186
+ assert_no_match(/AND$/, update_sql)
187
+ end
188
+
189
+ def test_default_scope_doesnt_run_on_destroy
190
+ Mentor.create!
191
+ dev = DeveloperwithDefaultMentorScopeNot.create!(name: "Eileen")
192
+ destroy_sql = capture_sql { dev.destroy }.first
193
+
194
+ assert_no_match(/mentor_id/, destroy_sql)
195
+ end
196
+
197
+ def test_default_scope_with_all_queries_runs_on_destroy
198
+ Mentor.create!
199
+ dev = DeveloperWithDefaultMentorScopeAllQueries.create!(name: "Eileen")
200
+ destroy_sql = capture_sql { dev.destroy }.second
201
+
202
+ assert_match(/mentor_id/, destroy_sql)
203
+ end
204
+
205
+ def test_nilable_default_scope_with_all_queries_runs_on_destroy
206
+ dev = DeveloperWithDefaultNilableFirmScopeAllQueries.create!(name: "Nikita")
207
+ destroy_sql = capture_sql { dev.destroy }.first
208
+
209
+ assert_no_match(/AND$/, destroy_sql)
210
+ end
211
+
212
+ def test_default_scope_doesnt_run_on_reload
213
+ Mentor.create!
214
+ dev = DeveloperwithDefaultMentorScopeNot.create!(name: "Eileen")
215
+ reload_sql = capture_sql { dev.reload }.first
216
+
217
+ assert_no_match(/mentor_id/, reload_sql)
218
+ end
219
+
220
+ def test_default_scope_with_all_queries_runs_on_reload
221
+ Mentor.create!
222
+ dev = DeveloperWithDefaultMentorScopeAllQueries.create!(name: "Eileen")
223
+ reload_sql = capture_sql { dev.reload }.first
224
+
225
+ assert_match(/mentor_id/, reload_sql)
226
+ end
227
+
228
+ def test_default_scope_with_all_queries_runs_on_reload_but_default_scope_without_all_queries_does_not
229
+ Mentor.create!
230
+ dev = DeveloperWithIncludedMentorDefaultScopeNotAllQueriesAndDefaultScopeFirmWithAllQueries.create!(name: "Eileen")
231
+ reload_sql = capture_sql { dev.reload }.first
232
+
233
+ assert_no_match(/mentor_id/, reload_sql)
234
+ assert_match(/firm_id/, reload_sql)
235
+ end
236
+
237
+ def test_nilable_default_scope_with_all_queries_runs_on_reload
238
+ dev = DeveloperWithDefaultNilableFirmScopeAllQueries.create!(name: "Nikita")
239
+ reload_sql = capture_sql { dev.reload }.first
240
+
241
+ assert_no_match(/AND$/, reload_sql)
242
+ end
243
+
244
+ def test_default_scope_with_all_queries_doesnt_run_on_destroy_when_unscoped
245
+ dev = DeveloperWithDefaultMentorScopeAllQueries.create!(name: "Eileen", mentor_id: 2)
246
+ reload_sql = capture_sql { dev.reload({ unscoped: true }) }.first
247
+
248
+ assert_no_match(/mentor_id/, reload_sql)
249
+ end
250
+
82
251
  def test_scope_overwrites_default
83
252
  expected = Developer.all.merge!(order: "salary DESC, name DESC").to_a.collect(&:name)
84
253
  received = DeveloperOrderedBySalary.by_name.to_a.collect(&:name)
@@ -242,6 +411,20 @@ class DefaultScopingTest < ActiveRecord::TestCase
242
411
  assert_equal expected, received
243
412
  end
244
413
 
414
+ def test_unscope_eager_load
415
+ expected = Developer.all.collect(&:name)
416
+ received = Developer.eager_load(:projects).select(:id).unscope(:eager_load, :select)
417
+ assert_equal expected, received.collect(&:name)
418
+ assert_equal false, received.first.projects.loaded?
419
+ end
420
+
421
+ def test_unscope_preloads
422
+ expected = Developer.all.collect(&:name)
423
+ received = Developer.preload(:projects).select(:id).unscope(:preload, :select)
424
+ assert_equal expected, received.collect(&:name)
425
+ assert_equal false, received.first.projects.loaded?
426
+ end
427
+
245
428
  def test_unscope_having
246
429
  expected = DeveloperOrderedBySalary.all.collect(&:name)
247
430
  received = DeveloperOrderedBySalary.having("name IN ('Jamis', 'David')").unscope(:having).collect(&:name)
@@ -260,7 +443,7 @@ class DefaultScopingTest < ActiveRecord::TestCase
260
443
 
261
444
  def test_unscope_errors_with_invalid_value
262
445
  assert_raises(ArgumentError) do
263
- Developer.includes(:projects).where(name: "Jamis").unscope(:stupidly_incorrect_value)
446
+ Developer.includes(:projects).where(name: "Jamis").unscope(:incorrect_value)
264
447
  end
265
448
 
266
449
  assert_raises(ArgumentError) do
@@ -522,48 +705,49 @@ class DefaultScopingTest < ActiveRecord::TestCase
522
705
  end
523
706
 
524
707
  def test_with_abstract_class_scope_should_be_executed_in_correct_context
525
- vegetarian_pattern = /#{Regexp.escape(Lion.connection.quote_table_name("lions.is_vegetarian"))}/i
526
- gender_pattern = /#{Regexp.escape(Lion.connection.quote_table_name("lions.gender"))}/i
527
-
528
- assert_match vegetarian_pattern, Lion.all.to_sql
529
- assert_match gender_pattern, Lion.female.to_sql
708
+ assert_match %r/#{Regexp.escape(quote_table_name("lions.is_vegetarian"))}/i, Lion.all.to_sql
709
+ assert_match %r/#{Regexp.escape(quote_table_name("lions.gender"))}/i, Lion.female.to_sql
530
710
  end
531
711
  end
532
712
 
533
713
  class DefaultScopingWithThreadTest < ActiveRecord::TestCase
534
- self.use_transactional_tests = false
535
-
536
- def test_default_scoping_with_threads
537
- 2.times do
538
- Thread.new {
539
- assert_includes DeveloperOrderedBySalary.all.to_sql, "salary DESC"
540
- DeveloperOrderedBySalary.connection.close
541
- }.join
714
+ unless in_memory_db?
715
+ self.use_transactional_tests = false
716
+
717
+ def test_default_scoping_with_threads
718
+ 2.times do
719
+ Thread.new {
720
+ assert_includes DeveloperOrderedBySalary.all.to_sql, "salary DESC"
721
+ DeveloperOrderedBySalary.lease_connection.close
722
+ }.join
723
+ end
542
724
  end
543
- end
544
725
 
545
- def test_default_scope_is_threadsafe
546
- 2.times { ThreadsafeDeveloper.unscoped.create! }
726
+ def test_default_scope_is_threadsafe
727
+ skip "DB2 IBM_DB adapter has a threading race condition in INSERT statement generation (SQL0117N column count mismatch)" if ActiveRecord::Base.lease_connection.adapter_name == "IBM_DB"
728
+
729
+ 2.times { ThreadsafeDeveloper.unscoped.create! }
547
730
 
548
- threads = []
549
- assert_not_equal 1, ThreadsafeDeveloper.unscoped.count
731
+ threads = []
732
+ assert_not_equal 1, ThreadsafeDeveloper.unscoped.count
550
733
 
551
- barrier_1 = Concurrent::CyclicBarrier.new(2)
552
- barrier_2 = Concurrent::CyclicBarrier.new(2)
734
+ barrier_1 = Concurrent::CyclicBarrier.new(2)
735
+ barrier_2 = Concurrent::CyclicBarrier.new(2)
553
736
 
554
- threads << Thread.new do
555
- Thread.current[:default_scope_delay] = -> { barrier_1.wait; barrier_2.wait }
556
- assert_equal 1, ThreadsafeDeveloper.all.to_a.count
557
- ThreadsafeDeveloper.connection.close
558
- end
559
- threads << Thread.new do
560
- Thread.current[:default_scope_delay] = -> { barrier_2.wait }
561
- barrier_1.wait
562
- assert_equal 1, ThreadsafeDeveloper.all.to_a.count
563
- ThreadsafeDeveloper.connection.close
737
+ threads << Thread.new do
738
+ Thread.current[:default_scope_delay] = -> { barrier_1.wait; barrier_2.wait }
739
+ assert_equal 1, ThreadsafeDeveloper.all.to_a.count
740
+ ThreadsafeDeveloper.lease_connection.close
741
+ end
742
+ threads << Thread.new do
743
+ Thread.current[:default_scope_delay] = -> { barrier_2.wait }
744
+ barrier_1.wait
745
+ assert_equal 1, ThreadsafeDeveloper.all.to_a.count
746
+ ThreadsafeDeveloper.lease_connection.close
747
+ end
748
+ threads.each(&:join)
749
+ ensure
750
+ ThreadsafeDeveloper.unscoped.destroy_all
564
751
  end
565
- threads.each(&:join)
566
- ensure
567
- ThreadsafeDeveloper.unscoped.destroy_all
568
752
  end
569
- end unless in_memory_db?
753
+ end
@@ -24,7 +24,7 @@ class NamedScopingTest < ActiveRecord::TestCase
24
24
  def test_found_items_are_cached
25
25
  all_posts = Topic.base
26
26
 
27
- assert_queries(1) do
27
+ assert_queries_count(1) do
28
28
  all_posts.collect { true }
29
29
  all_posts.collect { true }
30
30
  end
@@ -194,7 +194,7 @@ class NamedScopingTest < ActiveRecord::TestCase
194
194
  e = assert_raises ArgumentError do
195
195
  Class.new(Post).class_eval { scope name, -> { where(approved: true) } }
196
196
  end
197
- assert_match(/You tried to define a scope named \"#{name}\" on the model/, e.message)
197
+ assert_match(/You tried to define a scope named "#{name}" on the model/, e.message)
198
198
  end
199
199
  end
200
200
 
@@ -227,7 +227,7 @@ class NamedScopingTest < ActiveRecord::TestCase
227
227
 
228
228
  def test_empty_should_not_load_results
229
229
  topics = Topic.base
230
- assert_queries(2) do
230
+ assert_queries_count(2) do
231
231
  topics.empty? # use count query
232
232
  topics.load # force load
233
233
  topics.empty? # use loaded (no query)
@@ -236,7 +236,7 @@ class NamedScopingTest < ActiveRecord::TestCase
236
236
 
237
237
  def test_any_should_not_load_results
238
238
  topics = Topic.base
239
- assert_queries(2) do
239
+ assert_queries_count(2) do
240
240
  topics.any? # use count query
241
241
  topics.load # force load
242
242
  topics.any? # use loaded (no query)
@@ -245,7 +245,7 @@ class NamedScopingTest < ActiveRecord::TestCase
245
245
 
246
246
  def test_any_should_call_proxy_found_if_using_a_block
247
247
  topics = Topic.base
248
- assert_queries(1) do
248
+ assert_queries_count(1) do
249
249
  assert_not_called(topics, :empty?) do
250
250
  topics.any? { true }
251
251
  end
@@ -255,7 +255,7 @@ class NamedScopingTest < ActiveRecord::TestCase
255
255
  def test_any_should_not_fire_query_if_scope_loaded
256
256
  topics = Topic.base
257
257
  topics.load # force load
258
- assert_no_queries { assert topics.any? }
258
+ assert_no_queries { assert_predicate topics, :any? }
259
259
  end
260
260
 
261
261
  def test_model_class_should_respond_to_any
@@ -266,7 +266,7 @@ class NamedScopingTest < ActiveRecord::TestCase
266
266
 
267
267
  def test_many_should_not_load_results
268
268
  topics = Topic.base
269
- assert_queries(2) do
269
+ assert_queries_count(2) do
270
270
  topics.many? # use count query
271
271
  topics.load # force load
272
272
  topics.many? # use loaded (no query)
@@ -275,7 +275,7 @@ class NamedScopingTest < ActiveRecord::TestCase
275
275
 
276
276
  def test_many_should_call_proxy_found_if_using_a_block
277
277
  topics = Topic.base
278
- assert_queries(1) do
278
+ assert_queries_count(1) do
279
279
  assert_not_called(topics, :size) do
280
280
  topics.many? { true }
281
281
  end
@@ -285,7 +285,7 @@ class NamedScopingTest < ActiveRecord::TestCase
285
285
  def test_many_should_not_fire_query_if_scope_loaded
286
286
  topics = Topic.base
287
287
  topics.load # force load
288
- assert_no_queries { assert topics.many? }
288
+ assert_no_queries { assert_predicate topics, :many? }
289
289
  end
290
290
 
291
291
  def test_many_should_return_false_if_none_or_one
@@ -363,7 +363,6 @@ class NamedScopingTest < ActiveRecord::TestCase
363
363
  :protected,
364
364
  :private,
365
365
  :name,
366
- :parent,
367
366
  :superclass
368
367
  ]
369
368
 
@@ -380,12 +379,12 @@ class NamedScopingTest < ActiveRecord::TestCase
380
379
  e = assert_raises(ArgumentError, "scope `#{name}` should not be allowed") do
381
380
  klass.class_eval { scope name, -> { where(approved: true) } }
382
381
  end
383
- assert_match(/You tried to define a scope named \"#{name}\" on the model/, e.message)
382
+ assert_match(/You tried to define a scope named "#{name}" on the model/, e.message)
384
383
 
385
384
  e = assert_raises(ArgumentError, "scope `#{name}` should not be allowed") do
386
385
  subklass.class_eval { scope name, -> { where(approved: true) } }
387
386
  end
388
- assert_match(/You tried to define a scope named \"#{name}\" on the model/, e.message)
387
+ assert_match(/You tried to define a scope named "#{name}" on the model/, e.message)
389
388
  end
390
389
 
391
390
  non_conflicts.each do |name|
@@ -428,8 +427,8 @@ class NamedScopingTest < ActiveRecord::TestCase
428
427
 
429
428
  def test_size_should_use_count_when_results_are_not_loaded
430
429
  topics = Topic.base
431
- assert_queries(1) do
432
- assert_sql(/COUNT/i) { topics.size }
430
+ assert_queries_count(1) do
431
+ assert_queries_match(/COUNT/i) { topics.size }
433
432
  end
434
433
  end
435
434
 
@@ -495,13 +494,13 @@ class NamedScopingTest < ActiveRecord::TestCase
495
494
  def test_scopes_batch_finders
496
495
  assert_equal 4, Topic.approved.count
497
496
 
498
- assert_queries(5) do
499
- Topic.approved.find_each(batch_size: 1) { |t| assert t.approved? }
497
+ assert_queries_count(5) do
498
+ Topic.approved.find_each(batch_size: 1) { |t| assert_predicate t, :approved? }
500
499
  end
501
500
 
502
- assert_queries(3) do
501
+ assert_queries_count(3) do
503
502
  Topic.approved.find_in_batches(batch_size: 2) do |group|
504
- group.each { |t| assert t.approved? }
503
+ group.each { |t| assert_predicate t, :approved? }
505
504
  end
506
505
  end
507
506
  end
@@ -512,26 +511,6 @@ class NamedScopingTest < ActiveRecord::TestCase
512
511
  end
513
512
  end
514
513
 
515
- def test_scopes_with_reserved_names
516
- class << Topic
517
- def public_method; end
518
- public :public_method
519
-
520
- def protected_method; end
521
- protected :protected_method
522
-
523
- def private_method; end
524
- private :private_method
525
- end
526
-
527
- [:public_method, :protected_method, :private_method].each do |reserved_method|
528
- assert Topic.respond_to?(reserved_method, true)
529
- assert_called(ActiveRecord::Base.logger, :warn) do
530
- silence_warnings { Topic.scope(reserved_method, -> { }) }
531
- end
532
- end
533
- end
534
-
535
514
  def test_scopes_on_relations
536
515
  # Topic.replied
537
516
  approved_topics = Topic.all.approved.order("id DESC")
@@ -548,19 +527,19 @@ class NamedScopingTest < ActiveRecord::TestCase
548
527
  end
549
528
 
550
529
  def test_nested_scopes_queries_size
551
- assert_queries(1) do
530
+ assert_queries_count(1) do
552
531
  Topic.approved.by_lifo.replied.written_before(Time.now).to_a
553
532
  end
554
533
  end
555
534
 
556
535
  # Note: these next two are kinda odd because they are essentially just testing that the
557
- # query cache works as it should, but they are here for legacy reasons as they was previously
536
+ # query cache works as it should, but they are here for legacy reasons as there was previously
558
537
  # a separate cache on association proxies, and these show that that is not necessary.
559
538
  def test_scopes_are_cached_on_associations
560
539
  post = posts(:welcome)
561
540
 
562
541
  Post.cache do
563
- assert_queries(1) { post.comments.containing_the_letter_e.to_a }
542
+ assert_queries_count(1) { post.comments.containing_the_letter_e.to_a }
564
543
  assert_no_queries { post.comments.containing_the_letter_e.to_a }
565
544
  end
566
545
  end
@@ -569,10 +548,10 @@ class NamedScopingTest < ActiveRecord::TestCase
569
548
  post = posts(:welcome)
570
549
 
571
550
  Post.cache do
572
- one = assert_queries(1) { post.comments.limit_by(1).to_a }
551
+ one = assert_queries_count(1) { post.comments.limit_by(1).to_a }
573
552
  assert_equal 1, one.size
574
553
 
575
- two = assert_queries(1) { post.comments.limit_by(2).to_a }
554
+ two = assert_queries_count(1) { post.comments.limit_by(2).to_a }
576
555
  assert_equal 2, two.size
577
556
 
578
557
  assert_no_queries { post.comments.limit_by(1).to_a }
@@ -614,7 +593,7 @@ class NamedScopingTest < ActiveRecord::TestCase
614
593
  end
615
594
 
616
595
  def test_subclass_merges_scopes_properly
617
- assert_equal 1, SpecialComment.where(body: "go crazy").created.count
596
+ assert_equal 1, SpecialComment.where(body: "go wild").created.count
618
597
  end
619
598
 
620
599
  def test_model_class_should_respond_to_extending
@@ -642,8 +621,8 @@ class NamedScopingTest < ActiveRecord::TestCase
642
621
  scope :including_annotate_in_scope, Proc.new { annotate("from-scope") }
643
622
  end
644
623
 
645
- assert_sql(%r{/\* from-scope \*/}) do
646
- assert Topic.including_annotate_in_scope.to_a, Topic.all.to_a
624
+ assert_queries_match(%r{/\* from-scope \*/}) do
625
+ assert_equal Topic.including_annotate_in_scope.to_a, Topic.all.to_a
647
626
  end
648
627
  end
649
628
  end
@@ -42,15 +42,24 @@ class RelationScopingTest < ActiveRecord::TestCase
42
42
  assert_equal Developer.order("id DESC").to_a.reverse, Developer.order("id DESC").reverse_order
43
43
  end
44
44
 
45
- def test_reverse_order_with_arel_node
45
+ def test_reverse_order_with_arel_attribute
46
46
  assert_equal Developer.order("id DESC").to_a.reverse, Developer.order(Developer.arel_table[:id].desc).reverse_order
47
47
  end
48
48
 
49
- def test_reverse_order_with_multiple_arel_nodes
49
+ def test_reverse_order_with_arel_attribute_as_hash
50
+ assert_equal Developer.order("id DESC").to_a.reverse, Developer.order(Developer.arel_table[:id] => :desc).reverse_order
51
+ end
52
+
53
+ def test_reverse_order_with_arel_node_as_hash
54
+ node = Developer.arel_table[:id] + 0 # converts to Arel::Nodes::Grouping
55
+ assert_equal Developer.order("id DESC").to_a.reverse, Developer.order(node => :desc).reverse_order
56
+ end
57
+
58
+ def test_reverse_order_with_multiple_arel_attributes
50
59
  assert_equal Developer.order("id DESC").order("name DESC").to_a.reverse, Developer.order(Developer.arel_table[:id].desc).order(Developer.arel_table[:name].desc).reverse_order
51
60
  end
52
61
 
53
- def test_reverse_order_with_arel_nodes_and_strings
62
+ def test_reverse_order_with_arel_attributes_and_strings
54
63
  assert_equal Developer.order("id DESC").order("name DESC").to_a.reverse, Developer.order("id DESC").order(Developer.arel_table[:name].desc).reverse_order
55
64
  end
56
65
 
@@ -147,7 +156,7 @@ class RelationScopingTest < ActiveRecord::TestCase
147
156
  def test_scoped_find_with_annotation
148
157
  Developer.annotate("scoped").scoping do
149
158
  developer = nil
150
- assert_sql(%r{/\* scoped \*/}) do
159
+ assert_queries_match(%r{/\* scoped \*/}) do
151
160
  developer = Developer.where("name = 'David'").first
152
161
  end
153
162
  assert_equal "David", developer.name
@@ -349,6 +358,90 @@ class RelationScopingTest < ActiveRecord::TestCase
349
358
  end
350
359
  assert_equal posts, Post.left_joins(comments: :post).first(10)
351
360
  end
361
+
362
+ def test_scoping_applies_to_update_with_all_queries
363
+ Author.all.limit(5).update_all(organization_id: 1)
364
+
365
+ dev = Author.where(organization_id: 1).first
366
+
367
+ Author.where(organization_id: 1).scoping do
368
+ update_sql = capture_sql { dev.update(name: "Eileen") }.first
369
+ assert_no_match(/organization_id/, update_sql)
370
+ end
371
+
372
+ Author.where(organization_id: 1).scoping(all_queries: true) do
373
+ update_scoped_sql = capture_sql { dev.update(name: "Not Eileen") }.second
374
+ assert_match(/organization_id/, update_scoped_sql)
375
+ end
376
+ end
377
+
378
+ def test_scoping_applies_to_delete_with_all_queries
379
+ Author.all.limit(5).update_all(organization_id: 1)
380
+
381
+ dev1 = Author.where(organization_id: 1).first
382
+ dev2 = Author.where(organization_id: 1).last
383
+
384
+ Author.where(organization_id: 1).scoping do
385
+ delete_sql = capture_sql { dev1.delete }.first
386
+ assert_no_match(/organization_id/, delete_sql)
387
+ end
388
+
389
+ Author.where(organization_id: 1).scoping(all_queries: true) do
390
+ delete_scoped_sql = capture_sql { dev2.delete }.first
391
+ assert_match(/organization_id/, delete_scoped_sql)
392
+ end
393
+ end
394
+
395
+ def test_scoping_applies_to_reload_with_all_queries
396
+ Author.all.limit(5).update_all(organization_id: 1)
397
+
398
+ dev1 = Author.where(organization_id: 1).first
399
+
400
+ Author.where(organization_id: 1).scoping do
401
+ reload_sql = capture_sql { dev1.reload }.first
402
+ assert_no_match(/organization_id/, reload_sql)
403
+ end
404
+
405
+ Author.where(organization_id: 1).scoping(all_queries: true) do
406
+ scoped_reload_sql = capture_sql { dev1.reload }.first
407
+ assert_match(/organization_id/, scoped_reload_sql)
408
+ end
409
+ end
410
+
411
+ def test_nested_scoping_applies_with_all_queries_set
412
+ Author.all.limit(5).update_all(organization_id: 1)
413
+
414
+ Author.where(organization_id: 1).scoping(all_queries: true) do
415
+ select_sql = capture_sql { Author.first }.first
416
+ assert_match(/organization_id/, select_sql)
417
+
418
+ Author.where(owned_essay_id: nil).scoping do
419
+ second_select_sql = capture_sql { Author.first }.first
420
+ assert_match(/organization_id/, second_select_sql)
421
+ assert_match(/owned_essay_id/, second_select_sql)
422
+ end
423
+
424
+ third_select_sql = capture_sql { Author.first }.first
425
+ assert_match(/organization_id/, third_select_sql)
426
+ assert_no_match(/owned_essay_id/, third_select_sql)
427
+ end
428
+ end
429
+
430
+ def test_raises_error_if_all_queries_is_set_to_false_while_nested
431
+ Author.all.limit(5).update_all(organization_id: 1)
432
+
433
+ Author.where(organization_id: 1).scoping(all_queries: true) do
434
+ select_sql = capture_sql { Author.first }.first
435
+ assert_match(/organization_id/, select_sql)
436
+
437
+ error = assert_raises ArgumentError do
438
+ Author.where(organization_id: 1).scoping(all_queries: false) { }
439
+ end
440
+
441
+ assert_equal "Scoping is set to apply to all queries and cannot be " \
442
+ "unset in a nested block.", error.message
443
+ end
444
+ end
352
445
  end
353
446
 
354
447
  class NestedRelationScopingTest < ActiveRecord::TestCase
@@ -482,6 +575,21 @@ class HasManyScopingTest < ActiveRecord::TestCase
482
575
  magician = BadReference.find(1)
483
576
  assert_equal [magician], michael.bad_references
484
577
  end
578
+
579
+ def test_scoping_applies_to_all_queries_on_has_many_when_set
580
+ @welcome.comments.update_all(author_id: 1)
581
+
582
+ comments_sql = capture_sql { @welcome.comments.to_a }.last
583
+ assert_no_match(/author_id/, comments_sql)
584
+
585
+ Comment.where(author_id: 1).scoping(all_queries: true) do
586
+ scoped_comments_sql = capture_sql { @welcome.comments.reload.to_a }.last
587
+ assert_match(/author_id/, scoped_comments_sql)
588
+ end
589
+
590
+ unscoped_comments_sql = capture_sql { @welcome.comments.reload.to_a }.last
591
+ assert_no_match(/author_id/, unscoped_comments_sql)
592
+ end
485
593
  end
486
594
 
487
595
  class HasAndBelongsToManyScopingTest < ActiveRecord::TestCase