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
@@ -0,0 +1,293 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/helper"
4
+ require "models/dashboard"
5
+
6
+ class QueryLogsTest < ActiveRecord::TestCase
7
+ fixtures :dashboards
8
+
9
+ def setup
10
+ # ActiveSupport::ExecutionContext context is automatically reset in Rails app via an executor hooks set in railtie
11
+ # But not in Active Record's own test suite.
12
+ ActiveSupport::ExecutionContext.clear
13
+
14
+ # Enable the query tags logging
15
+ @original_transformers = ActiveRecord.query_transformers
16
+ @original_prepend = ActiveRecord::QueryLogs.prepend_comment
17
+ @original_tags = ActiveRecord::QueryLogs.tags
18
+ @original_taggings = ActiveRecord::QueryLogs.taggings
19
+ ActiveRecord.query_transformers += [ActiveRecord::QueryLogs]
20
+ ActiveRecord::QueryLogs.prepend_comment = false
21
+ ActiveRecord::QueryLogs.cache_query_log_tags = false
22
+ ActiveRecord::QueryLogs.cached_comment = nil
23
+ ActiveRecord::QueryLogs.taggings = {
24
+ application: -> { "active_record" }
25
+ }
26
+ end
27
+
28
+ def teardown
29
+ ActiveRecord.query_transformers = @original_transformers
30
+ ActiveRecord::QueryLogs.prepend_comment = @original_prepend
31
+ ActiveRecord::QueryLogs.tags = @original_tags
32
+ ActiveRecord::QueryLogs.taggings = @original_taggings
33
+ ActiveRecord::QueryLogs.prepend_comment = false
34
+ ActiveRecord::QueryLogs.cache_query_log_tags = false
35
+ ActiveRecord::QueryLogs.clear_cache
36
+ ActiveRecord::QueryLogs.tags_formatter = :legacy
37
+
38
+ # ActiveSupport::ExecutionContext context is automatically reset in Rails app via an executor hooks set in railtie
39
+ # But not in Active Record's own test suite.
40
+ ActiveSupport::ExecutionContext.clear
41
+ end
42
+
43
+ def test_escaping_good_comment
44
+ assert_equal "app:foo", ActiveRecord::QueryLogs.send(:escape_sql_comment, "app:foo")
45
+ end
46
+
47
+ def test_escaping_good_comment_with_custom_separator
48
+ ActiveRecord::QueryLogs.tags_formatter = :sqlcommenter
49
+
50
+ assert_equal "app='foo'", ActiveRecord::QueryLogs.send(:escape_sql_comment, "app='foo'")
51
+ end
52
+
53
+ def test_escaping_bad_comments
54
+ assert_equal "* /; DROP TABLE USERS;/ *", ActiveRecord::QueryLogs.send(:escape_sql_comment, "*/; DROP TABLE USERS;/*")
55
+ assert_equal "** //; DROP TABLE USERS;/ *", ActiveRecord::QueryLogs.send(:escape_sql_comment, "**//; DROP TABLE USERS;/*")
56
+ assert_equal "* * //; DROP TABLE USERS;// * *", ActiveRecord::QueryLogs.send(:escape_sql_comment, "* *//; DROP TABLE USERS;//* *")
57
+ end
58
+
59
+ def test_basic_commenting
60
+ ActiveRecord::QueryLogs.tags = [ :application ]
61
+
62
+ assert_queries_match(%r{select id from posts /\*application:active_record\*/$}) do
63
+ ActiveRecord::Base.lease_connection.execute "select id from posts"
64
+ end
65
+ end
66
+
67
+ def test_add_comments_to_beginning_of_query
68
+ ActiveRecord::QueryLogs.tags = [ :application ]
69
+ ActiveRecord::QueryLogs.prepend_comment = true
70
+
71
+ assert_queries_match(%r{/\*application:active_record\*/ select id from posts$}) do
72
+ ActiveRecord::Base.lease_connection.execute "select id from posts"
73
+ end
74
+ end
75
+
76
+ def test_exists_is_commented
77
+ ActiveRecord::QueryLogs.tags = [ :application ]
78
+ assert_queries_match(%r{/\*application:active_record\*/}) do
79
+ Dashboard.exists?
80
+ end
81
+ end
82
+
83
+ def test_delete_is_commented
84
+ ActiveRecord::QueryLogs.tags = [ :application ]
85
+ record = Dashboard.first
86
+
87
+ assert_queries_match(%r{/\*application:active_record\*/}) do
88
+ record.destroy
89
+ end
90
+ end
91
+
92
+ def test_update_is_commented
93
+ ActiveRecord::QueryLogs.tags = [ :application ]
94
+
95
+ assert_queries_match(%r{/\*application:active_record\*/}) do
96
+ dash = Dashboard.first
97
+ dash.name = "New name"
98
+ dash.save
99
+ end
100
+ end
101
+
102
+ def test_create_is_commented
103
+ ActiveRecord::QueryLogs.tags = [ :application ]
104
+
105
+ assert_queries_match(%r{/\*application:active_record\*/}) do
106
+ Dashboard.create(name: "Another dashboard")
107
+ end
108
+ end
109
+
110
+ def test_select_is_commented
111
+ ActiveRecord::QueryLogs.tags = [ :application ]
112
+
113
+ assert_queries_match(%r{/\*application:active_record\*/}) do
114
+ Dashboard.all.to_a
115
+ end
116
+ end
117
+
118
+ def test_retrieves_comment_from_cache_when_enabled_and_set
119
+ ActiveRecord::QueryLogs.cache_query_log_tags = true
120
+ i = 0
121
+ ActiveRecord::QueryLogs.tags = [ { query_counter: -> { i += 1 } } ]
122
+
123
+ assert_queries_match(select_one_with_comment("/*query_counter:1*/")) do
124
+ ActiveRecord::Base.lease_connection.execute "SELECT 1"
125
+ end
126
+
127
+ assert_queries_match(select_one_with_comment("/*query_counter:1*/")) do
128
+ ActiveRecord::Base.lease_connection.execute "SELECT 1"
129
+ end
130
+ end
131
+
132
+ def test_resets_cache_on_context_update
133
+ ActiveRecord::QueryLogs.cache_query_log_tags = true
134
+ ActiveSupport::ExecutionContext[:temporary] = "value"
135
+ ActiveRecord::QueryLogs.tags = [ temporary_tag: ->(context) { context[:temporary] } ]
136
+
137
+ assert_queries_match(select_one_with_comment("/*temporary_tag:value*/")) do
138
+ ActiveRecord::Base.lease_connection.execute "SELECT 1"
139
+ end
140
+
141
+ ActiveSupport::ExecutionContext[:temporary] = "new_value"
142
+
143
+ assert_queries_match(select_one_with_comment("/*temporary_tag:new_value*/")) do
144
+ ActiveRecord::Base.lease_connection.execute "SELECT 1"
145
+ end
146
+ end
147
+
148
+ def test_default_tag_behavior
149
+ ActiveRecord::QueryLogs.tags = [:application, :foo]
150
+ ActiveSupport::ExecutionContext.set(foo: "bar") do
151
+ assert_queries_match(%r{/\*application:active_record,foo:bar\*/}) do
152
+ Dashboard.first
153
+ end
154
+ end
155
+ assert_queries_match(%r{/\*application:active_record\*/}) do
156
+ Dashboard.first
157
+ end
158
+ end
159
+
160
+ def test_connection_is_passed_to_tagging_proc
161
+ connection = ActiveRecord::Base.lease_connection
162
+ ActiveRecord::QueryLogs.tags = [ same_connection: ->(context) { context[:connection] == connection } ]
163
+
164
+ assert_queries_match(select_one_with_comment("/*same_connection:true*/")) do
165
+ connection.execute "SELECT 1"
166
+ end
167
+ end
168
+
169
+ def test_connection_does_not_override_already_existing_connection_in_context
170
+ fake_connection = Object.new
171
+ ActiveSupport::ExecutionContext[:connection] = fake_connection
172
+ ActiveRecord::QueryLogs.tags = [ fake_connection: ->(context) { context[:connection] == fake_connection } ]
173
+
174
+ assert_queries_match(select_one_with_comment("/*fake_connection:true*/")) do
175
+ ActiveRecord::Base.lease_connection.execute "SELECT 1"
176
+ end
177
+ end
178
+
179
+ def test_empty_comments_are_not_added
180
+ ActiveRecord::QueryLogs.tags = [ empty: -> { nil } ]
181
+ assert_queries_match(%r{select id from posts$}) do
182
+ ActiveRecord::Base.lease_connection.execute "select id from posts"
183
+ end
184
+ end
185
+
186
+ def test_sql_commenter_format
187
+ ActiveRecord::QueryLogs.tags_formatter = :sqlcommenter
188
+ ActiveRecord::QueryLogs.tags = [:application]
189
+
190
+ assert_queries_match(%r{/\*application='active_record'\*/}) do
191
+ Dashboard.first
192
+ end
193
+ end
194
+
195
+ def test_custom_basic_tags
196
+ ActiveRecord::QueryLogs.tags = [ :application, { custom_string: "test content" } ]
197
+
198
+ assert_queries_match(%r{/\*application:active_record,custom_string:test content\*/}) do
199
+ Dashboard.first
200
+ end
201
+ end
202
+
203
+ def test_custom_proc_tags
204
+ ActiveRecord::QueryLogs.tags = [ :application, { custom_proc: -> { "test content" } } ]
205
+
206
+ assert_queries_match(%r{/\*application:active_record,custom_proc:test content\*/}) do
207
+ Dashboard.first
208
+ end
209
+ end
210
+
211
+ def test_multiple_custom_tags
212
+ ActiveRecord::QueryLogs.tags = [
213
+ :application,
214
+ { custom_proc: -> { "test content" }, another_proc: -> { "more test content" } },
215
+ ]
216
+
217
+ assert_queries_match(%r{/\*another_proc:more test content,application:active_record,custom_proc:test content\*/}) do
218
+ Dashboard.first
219
+ end
220
+ end
221
+
222
+ def test_sqlcommenter_format_value
223
+ ActiveRecord::QueryLogs.tags_formatter = :sqlcommenter
224
+
225
+ ActiveRecord::QueryLogs.tags = [
226
+ :application,
227
+ { tracestate: "congo=t61rcWkgMzE,rojo=00f067aa0ba902b7", custom_proc: -> { "Joe's Shack" } },
228
+ ]
229
+
230
+ assert_queries_match(%r{custom_proc='Joe%27s%20Shack',tracestate='congo%3Dt61rcWkgMzE%2Crojo%3D00f067aa0ba902b7'\*/}) do
231
+ Dashboard.first
232
+ end
233
+ end
234
+
235
+ def test_sqlcommenter_format_allows_string_keys
236
+ ActiveRecord::QueryLogs.tags_formatter = :sqlcommenter
237
+
238
+ ActiveRecord::QueryLogs.tags = [
239
+ :application,
240
+ {
241
+ "string" => "value",
242
+ tracestate: "congo=t61rcWkgMzE,rojo=00f067aa0ba902b7",
243
+ custom_proc: -> { "Joe's Shack" }
244
+ },
245
+ ]
246
+
247
+ assert_queries_match(%r{custom_proc='Joe%27s%20Shack',string='value',tracestate='congo%3Dt61rcWkgMzE%2Crojo%3D00f067aa0ba902b7'\*/}) do
248
+ Dashboard.first
249
+ end
250
+ end
251
+
252
+ def test_sqlcommenter_format_value_string_coercible
253
+ ActiveRecord::QueryLogs.tags_formatter = :sqlcommenter
254
+
255
+ ActiveRecord::QueryLogs.tags = [
256
+ :application,
257
+ { custom_proc: -> { 1234 } },
258
+ ]
259
+
260
+ assert_queries_match(%r{custom_proc='1234'\*/}) do
261
+ Dashboard.first
262
+ end
263
+ end
264
+
265
+ # PostgreSQL does validate the query encoding. Other adapters don't care.
266
+ # IBM_DB adapter also does not support encoding validation
267
+ unless current_adapter?(:PostgreSQLAdapter) || current_adapter?(:IBM_DBAdapter)
268
+ def test_invalid_encoding_query
269
+ ActiveRecord::QueryLogs.tags = [ :application ]
270
+ assert_nothing_raised do
271
+ ActiveRecord::Base.lease_connection.execute "select 1 as '\xFF'"
272
+ end
273
+ end
274
+ end
275
+
276
+ def test_custom_proc_context_tags
277
+ ActiveSupport::ExecutionContext[:foo] = "bar"
278
+ ActiveRecord::QueryLogs.tags = [ :application, { custom_context_proc: ->(context) { context[:foo] } } ]
279
+
280
+ assert_queries_match(%r{/\*application:active_record,custom_context_proc:bar\*/}) do
281
+ Dashboard.first
282
+ end
283
+ end
284
+
285
+ private
286
+ def select_one_with_comment(comment)
287
+ if current_adapter?(:IBM_DBAdapter)
288
+ "SELECT 1 FROM SYSIBM.SYSDUMMY1 #{comment}"
289
+ else
290
+ "SELECT 1 #{comment}"
291
+ end
292
+ end
293
+ end
@@ -6,7 +6,13 @@ module ActiveRecord
6
6
  module ConnectionAdapters
7
7
  class QuotingTest < ActiveRecord::TestCase
8
8
  def setup
9
- @quoter = Class.new { include Quoting }.new
9
+ @quoter = Class.new {
10
+ include Quoting
11
+
12
+ def default_timezone
13
+ ActiveRecord.default_timezone
14
+ end
15
+ }.new
10
16
  end
11
17
 
12
18
  def test_quoted_true
@@ -18,15 +24,22 @@ module ActiveRecord
18
24
  end
19
25
 
20
26
  def test_quote_column_name
21
- assert_equal "foo", @quoter.quote_column_name("foo")
27
+ skip "IBM_DB adapter defines quote_column_name" if current_adapter?(:IBM_DBAdapter)
28
+ assert_raises NotImplementedError do
29
+ @quoter.quote_column_name("foo")
30
+ end
22
31
  end
23
32
 
24
33
  def test_quote_table_name
25
- assert_equal "foo", @quoter.quote_table_name("foo")
34
+ skip "IBM_DB adapter defines quote_table_name" if current_adapter?(:IBM_DBAdapter)
35
+ assert_raises NotImplementedError do
36
+ @quoter.quote_table_name("foo")
37
+ end
26
38
  end
27
39
 
28
40
  def test_quote_table_name_calls_quote_column_name
29
- @quoter.extend(Module.new {
41
+ skip "IBM_DB adapter overrides quote_table_name behavior" if current_adapter?(:IBM_DBAdapter)
42
+ @quoter.class.extend(Module.new {
30
43
  def quote_column_name(string)
31
44
  "lol"
32
45
  end
@@ -43,27 +56,20 @@ module ActiveRecord
43
56
 
44
57
  def test_quoted_date
45
58
  t = Date.today
46
- assert_equal t.to_s(:db), @quoter.quoted_date(t)
59
+ assert_equal t.to_fs(:db), @quoter.quoted_date(t)
47
60
  end
48
61
 
49
62
  def test_quoted_timestamp_utc
50
63
  with_timezone_config default: :utc do
51
64
  t = Time.now.change(usec: 0)
52
- assert_equal t.getutc.to_s(:db), @quoter.quoted_date(t)
65
+ assert_equal t.getutc.to_fs(:db), @quoter.quoted_date(t)
53
66
  end
54
67
  end
55
68
 
56
69
  def test_quoted_timestamp_local
57
70
  with_timezone_config default: :local do
58
71
  t = Time.now.change(usec: 0)
59
- assert_equal t.getlocal.to_s(:db), @quoter.quoted_date(t)
60
- end
61
- end
62
-
63
- def test_quoted_timestamp_crazy
64
- with_timezone_config default: :asdfasdf do
65
- t = Time.now.change(usec: 0)
66
- assert_equal t.getlocal.to_s(:db), @quoter.quoted_date(t)
72
+ assert_equal t.getlocal.to_fs(:db), @quoter.quoted_date(t)
67
73
  end
68
74
  end
69
75
 
@@ -72,7 +78,7 @@ module ActiveRecord
72
78
  t = Time.now.change(usec: 0)
73
79
 
74
80
  expected = t.change(year: 2000, month: 1, day: 1)
75
- expected = expected.getutc.to_s(:db).slice(11..-1)
81
+ expected = expected.getutc.to_fs(:db).slice(11..-1)
76
82
 
77
83
  assert_equal expected, @quoter.quoted_time(t)
78
84
  end
@@ -83,7 +89,7 @@ module ActiveRecord
83
89
  t = Time.now.change(usec: 0)
84
90
 
85
91
  expected = t.change(year: 2000, month: 1, day: 1)
86
- expected = expected.getlocal.to_s(:db).sub("2000-01-01 ", "")
92
+ expected = expected.getlocal.to_fs(:db).sub("2000-01-01 ", "")
87
93
 
88
94
  assert_equal expected, @quoter.quoted_time(t)
89
95
  end
@@ -95,7 +101,7 @@ module ActiveRecord
95
101
  t = Time.new(2000, 7, 1, 0, 0, 0, "+04:30")
96
102
 
97
103
  expected = t.change(year: 2000, month: 1, day: 1)
98
- expected = expected.getutc.to_s(:db).slice(11..-1)
104
+ expected = expected.getutc.to_fs(:db).slice(11..-1)
99
105
 
100
106
  assert_equal expected, @quoter.quoted_time(t)
101
107
  end
@@ -108,28 +114,17 @@ module ActiveRecord
108
114
  t = Time.new(2000, 7, 1, 0, 0, 0, "+04:30")
109
115
 
110
116
  expected = t.change(year: 2000, month: 1, day: 1)
111
- expected = expected.getlocal.to_s(:db).slice(11..-1)
117
+ expected = expected.getlocal.to_fs(:db).slice(11..-1)
112
118
 
113
119
  assert_equal expected, @quoter.quoted_time(t)
114
120
  end
115
121
  end
116
122
  end
117
123
 
118
- def test_quoted_time_crazy
119
- with_timezone_config default: :asdfasdf do
120
- t = Time.now.change(usec: 0)
121
-
122
- expected = t.change(year: 2000, month: 1, day: 1)
123
- expected = expected.getlocal.to_s(:db).sub("2000-01-01 ", "")
124
-
125
- assert_equal expected, @quoter.quoted_time(t)
126
- end
127
- end
128
-
129
124
  def test_quoted_datetime_utc
130
125
  with_timezone_config default: :utc do
131
126
  t = Time.now.change(usec: 0).to_datetime
132
- assert_equal t.getutc.to_s(:db), @quoter.quoted_date(t)
127
+ assert_equal t.getutc.to_fs(:db), @quoter.quoted_date(t)
133
128
  end
134
129
  end
135
130
 
@@ -138,7 +133,7 @@ module ActiveRecord
138
133
  def test_quoted_datetime_local
139
134
  with_timezone_config default: :local do
140
135
  t = Time.now.change(usec: 0).to_datetime
141
- assert_equal t.to_s(:db), @quoter.quoted_date(t)
136
+ assert_equal t.to_fs(:db), @quoter.quoted_date(t)
142
137
  end
143
138
  end
144
139
 
@@ -185,10 +180,10 @@ module ActiveRecord
185
180
  assert_equal "'Object'", @quoter.quote(Object)
186
181
  end
187
182
 
188
- def test_crazy_object
189
- crazy = Object.new
183
+ def test_quote_object_instance
184
+ object = Object.new
190
185
  e = assert_raises(TypeError) do
191
- @quoter.quote(crazy)
186
+ @quoter.quote(object)
192
187
  end
193
188
  assert_equal "can't quote Object", e.message
194
189
  end
@@ -203,13 +198,14 @@ module ActiveRecord
203
198
  end
204
199
 
205
200
  def test_quote_duration
206
- assert_equal "1800", @quoter.quote(30.minutes)
201
+ exception = assert_raises(TypeError) { @quoter.quote(30.minutes) }
202
+ assert_equal "can't quote ActiveSupport::Duration", exception.message
207
203
  end
208
204
  end
209
205
 
210
206
  class TypeCastingTest < ActiveRecord::TestCase
211
207
  def setup
212
- @conn = ActiveRecord::Base.connection
208
+ @conn = ActiveRecord::Base.lease_connection
213
209
  end
214
210
 
215
211
  def test_type_cast_symbol
@@ -218,7 +214,7 @@ module ActiveRecord
218
214
 
219
215
  def test_type_cast_date
220
216
  date = Date.today
221
- if current_adapter?(:Mysql2Adapter)
217
+ if current_adapter?(:Mysql2Adapter, :TrilogyAdapter)
222
218
  expected = date
223
219
  else
224
220
  expected = @conn.quoted_date(date)
@@ -228,7 +224,7 @@ module ActiveRecord
228
224
 
229
225
  def test_type_cast_time
230
226
  time = Time.now
231
- if current_adapter?(:Mysql2Adapter)
227
+ if current_adapter?(:Mysql2Adapter, :TrilogyAdapter)
232
228
  expected = time
233
229
  else
234
230
  expected = @conn.quoted_date(time)
@@ -249,11 +245,15 @@ module ActiveRecord
249
245
  obj = Class.new.new
250
246
  assert_raise(TypeError) { @conn.type_cast(obj) }
251
247
  end
248
+
249
+ def test_type_cast_duration_should_raise_error
250
+ assert_raise(TypeError) { @conn.type_cast(1.hour) }
251
+ end
252
252
  end
253
253
 
254
254
  class QuoteBooleanTest < ActiveRecord::TestCase
255
255
  def setup
256
- @connection = ActiveRecord::Base.connection
256
+ @connection = ActiveRecord::Base.lease_connection
257
257
  end
258
258
 
259
259
  def test_quote_returns_frozen_string
@@ -266,38 +266,5 @@ module ActiveRecord
266
266
  assert_predicate @connection.type_cast(false), :frozen?
267
267
  end
268
268
  end
269
-
270
- if supports_datetime_with_precision?
271
- class QuoteARBaseTest < ActiveRecord::TestCase
272
- class DatetimePrimaryKey < ActiveRecord::Base
273
- end
274
-
275
- def setup
276
- @time = ::Time.utc(2017, 2, 14, 12, 34, 56, 789999)
277
- @connection = ActiveRecord::Base.connection
278
- @connection.create_table :datetime_primary_keys, id: :datetime, precision: 3, force: true
279
- end
280
-
281
- def teardown
282
- @connection.drop_table :datetime_primary_keys, if_exists: true
283
- end
284
-
285
- def test_quote_ar_object
286
- value = DatetimePrimaryKey.new(id: @time)
287
- expected = "'2017-02-14 12:34:56.789000'"
288
- assert_deprecated do
289
- assert_equal expected, @connection.quote(value)
290
- end
291
- end
292
-
293
- def test_type_cast_ar_object
294
- value = DatetimePrimaryKey.new(id: @time)
295
- expected = @connection.type_cast(value.id)
296
- assert_deprecated do
297
- assert_equal expected, @connection.type_cast(value)
298
- end
299
- end
300
- end
301
- end
302
269
  end
303
270
  end
@@ -37,19 +37,61 @@ class ReadOnlyTest < ActiveRecord::TestCase
37
37
  assert_equal "Developer is marked as readonly", e.message
38
38
  end
39
39
 
40
+ def test_cant_touch_readonly_record
41
+ dev = Developer.find(1)
42
+ assert_not_predicate dev, :readonly?
43
+
44
+ dev.readonly!
45
+ assert_predicate dev, :readonly?
46
+
47
+ e = assert_raise(ActiveRecord::ReadOnlyRecord) { dev.touch }
48
+ assert_equal "Developer is marked as readonly", e.message
49
+ end
50
+
51
+ def test_cant_touch_readonly_column
52
+ person = Person.find(1)
53
+
54
+ e = assert_raise(ActiveRecord::ActiveRecordError) { person.touch(:born_at) }
55
+ assert_equal "born_at is marked as readonly", e.message
56
+ end
57
+
58
+ def test_cant_update_column_readonly_record
59
+ dev = Developer.find(1)
60
+ assert_not_predicate dev, :readonly?
61
+
62
+ dev.readonly!
63
+ assert_predicate dev, :readonly?
64
+
65
+ e = assert_raise(ActiveRecord::ReadOnlyRecord) { dev.update_column(:name, "New name") }
66
+ assert_equal "Developer is marked as readonly", e.message
67
+ end
68
+
69
+ def test_cant_update_columns_readonly_record
70
+ dev = Developer.find(1)
71
+ assert_not_predicate dev, :readonly?
72
+
73
+ dev.readonly!
74
+ assert_predicate dev, :readonly?
75
+
76
+ e = assert_raise(ActiveRecord::ReadOnlyRecord) { dev.update_columns(name: "New name") }
77
+ assert_equal "Developer is marked as readonly", e.message
78
+ end
79
+
40
80
  def test_find_with_readonly_option
41
81
  Developer.all.each { |d| assert_not d.readonly? }
82
+ Developer.all.tap { |rel| assert_not rel.readonly? }
42
83
  Developer.readonly(false).each { |d| assert_not d.readonly? }
43
- Developer.readonly(true).each { |d| assert d.readonly? }
44
- Developer.readonly.each { |d| assert d.readonly? }
84
+ Developer.readonly(true).each { |d| assert_predicate d, :readonly? }
85
+ Developer.readonly.each { |d| assert_predicate d, :readonly? }
86
+ Developer.readonly.tap { |rel| assert_predicate rel, :readonly? }
45
87
  end
46
88
 
47
89
  def test_find_with_joins_option_does_not_imply_readonly
48
90
  Developer.joins(" ").each { |d| assert_not d.readonly? }
49
- Developer.joins(" ").readonly(true).each { |d| assert d.readonly? }
91
+ Developer.joins(" ").readonly(true).each { |d| assert_predicate d, :readonly? }
50
92
 
51
93
  Developer.joins(", projects").each { |d| assert_not d.readonly? }
52
- Developer.joins(", projects").readonly(true).each { |d| assert d.readonly? }
94
+ Developer.joins(", projects").readonly(true).each { |d| assert_predicate d, :readonly? }
53
95
  end
54
96
 
55
97
  def test_has_many_find_readonly
@@ -90,14 +132,10 @@ class ReadOnlyTest < ActiveRecord::TestCase
90
132
  assert_not_predicate Post.readonly(false).find(1), :readonly?
91
133
  end
92
134
 
93
- # Oracle barfs on this because the join includes unqualified and
94
- # conflicting column names
95
- unless current_adapter?(:OracleAdapter)
96
- Post.joins(", developers").scoping do
97
- assert_not_predicate Post.find(1), :readonly?
98
- assert_predicate Post.readonly.find(1), :readonly?
99
- assert_not_predicate Post.readonly(false).find(1), :readonly?
100
- end
135
+ Post.joins(", developers").scoping do
136
+ assert_not_predicate Post.find(1), :readonly?
137
+ assert_predicate Post.readonly.find(1), :readonly?
138
+ assert_not_predicate Post.readonly(false).find(1), :readonly?
101
139
  end
102
140
 
103
141
  Post.readonly(true).scoping do
@@ -59,7 +59,7 @@ module ActiveRecord
59
59
 
60
60
  def test_pool_has_reaper
61
61
  config = ActiveRecord::Base.configurations.configs_for(env_name: "arunit", name: "primary")
62
- pool_config = PoolConfig.new(ActiveRecord::Base, config)
62
+ pool_config = PoolConfig.new(ActiveRecord::Base, config, :writing, :default)
63
63
  pool = ConnectionPool.new(pool_config)
64
64
 
65
65
  assert pool.reaper
@@ -118,8 +118,10 @@ module ActiveRecord
118
118
  pool = ConnectionPool.new(pool_config)
119
119
 
120
120
  pool.discard!
121
- pool.reap
122
- pool.flush
121
+ assert_nothing_raised do
122
+ pool.reap
123
+ pool.flush
124
+ end
123
125
  end
124
126
 
125
127
  if Process.respond_to?(:fork)
@@ -128,13 +130,20 @@ module ActiveRecord
128
130
  pool = ConnectionPool.new(pool_config)
129
131
  pool.checkout
130
132
 
133
+ # We currently have a bug somewhere which leads for this test case to be deadlocked
134
+ # and timeout after 30 minutes on the CI. Until that bug is fixed, this test is made
135
+ # to timeout after a short period of time to reduce the damage.
136
+ reader, writer = IO.pipe
137
+
131
138
  pid = fork do
139
+ reader.close
132
140
  pool = ConnectionPool.new(pool_config)
133
141
 
134
142
  conn, child = new_conn_in_thread(pool)
135
143
  child.terminate
136
144
 
137
145
  wait_for_conn_idle(conn)
146
+ writer.close
138
147
  if conn.in_use?
139
148
  exit!(1)
140
149
  else
@@ -142,8 +151,14 @@ module ActiveRecord
142
151
  end
143
152
  end
144
153
 
145
- Process.waitpid(pid)
146
- assert $?.success?
154
+ writer.close
155
+ completed = reader.wait_readable(20)
156
+ reader.close
157
+ unless completed
158
+ Process.kill("ABRT", pid)
159
+ end
160
+ _, status = Process.wait2(pid)
161
+ assert_predicate status, :success?
147
162
  ensure
148
163
  pool.discard!
149
164
  end
@@ -171,7 +186,7 @@ module ActiveRecord
171
186
  def duplicated_pool_config(merge_config_options = {})
172
187
  old_config = ActiveRecord::Base.connection_pool.db_config.configuration_hash.merge(merge_config_options)
173
188
  db_config = ActiveRecord::DatabaseConfigurations::HashConfig.new("arunit", "primary", old_config.dup)
174
- PoolConfig.new(ActiveRecord::Base, db_config)
189
+ PoolConfig.new(ActiveRecord::Base, db_config, :writing, :default)
175
190
  end
176
191
 
177
192
  def new_conn_in_thread(pool)
@@ -180,6 +195,7 @@ module ActiveRecord
180
195
 
181
196
  child = Thread.new do
182
197
  conn = pool.checkout
198
+ conn.query("SELECT 1") # ensure connected
183
199
  event.set
184
200
  Thread.stop
185
201
  end