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
@@ -4,6 +4,8 @@ require "cases/helper"
4
4
  require "support/ddl_helper"
5
5
  require "support/connection_helper"
6
6
 
7
+ require "active_support/error_reporter/test_helper"
8
+
7
9
  module ActiveRecord
8
10
  module ConnectionAdapters
9
11
  class PostgreSQLAdapterTest < ActiveRecord::PostgreSQLTestCase
@@ -12,14 +14,15 @@ module ActiveRecord
12
14
  include ConnectionHelper
13
15
 
14
16
  def setup
15
- @connection = ActiveRecord::Base.connection
16
- @connection_handler = ActiveRecord::Base.connection_handler
17
+ @connection = ActiveRecord::Base.lease_connection
18
+ @original_db_warnings_action = :ignore
17
19
  end
18
20
 
19
21
  def test_connection_error
20
- assert_raises ActiveRecord::ConnectionNotEstablished do
21
- ActiveRecord::Base.postgresql_connection(host: File::NULL)
22
+ error = assert_raises ActiveRecord::ConnectionNotEstablished do
23
+ ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.new(host: File::NULL).connect!
22
24
  end
25
+ assert_kind_of ActiveRecord::ConnectionAdapters::NullPool, error.connection_pool
23
26
  end
24
27
 
25
28
  def test_reconnection_error
@@ -38,8 +41,12 @@ module ActiveRecord
38
41
  {}
39
42
  end
40
43
 
44
+ def escape(query)
45
+ PG::Connection.escape(query)
46
+ end
47
+
41
48
  def reset
42
- raise PG::ConnectionBad
49
+ raise PG::ConnectionBad, "I'll be rescued by the reconnect method"
43
50
  end
44
51
 
45
52
  def close
@@ -53,8 +60,14 @@ module ActiveRecord
53
60
  { host: File::NULL }
54
61
  )
55
62
 
56
- assert_raises ActiveRecord::ConnectionNotEstablished do
57
- @conn.reconnect!
63
+ connect_raises_error = proc { |**_conn_params| raise(PG::ConnectionBad, "actual bad connection error") }
64
+ PG.stub(:connect, connect_raises_error) do
65
+ error = assert_raises ActiveRecord::ConnectionNotEstablished do
66
+ @conn.reconnect!
67
+ end
68
+
69
+ assert_equal("actual bad connection error", error.message)
70
+ assert_equal @conn.pool, error.connection_pool
58
71
  end
59
72
  end
60
73
 
@@ -62,11 +75,103 @@ module ActiveRecord
62
75
  assert_raise ActiveRecord::NoDatabaseError do
63
76
  db_config = ActiveRecord::Base.configurations.configs_for(env_name: "arunit", name: "primary")
64
77
  configuration = db_config.configuration_hash.merge(database: "should_not_exist-cinco-dog-db")
65
- connection = ActiveRecord::Base.postgresql_connection(configuration)
78
+ connection = ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.new(configuration)
66
79
  connection.exec_query("SELECT 1")
67
80
  end
68
81
  end
69
82
 
83
+ def test_bad_connection_to_postgres_database
84
+ connect_raises_error = proc { |**_conn_params| raise(PG::ConnectionBad, 'FATAL: database "postgres" does not exist') }
85
+ PG.stub(:connect, connect_raises_error) do
86
+ connection = nil
87
+ error = assert_raises ActiveRecord::ConnectionNotEstablished do
88
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: "arunit", name: "primary")
89
+ configuration = db_config.configuration_hash.merge(database: "postgres")
90
+ connection = ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.new(configuration)
91
+ connection.exec_query("SELECT 1")
92
+ end
93
+ assert_not_nil connection
94
+ assert_equal connection.pool, error.connection_pool
95
+ end
96
+ end
97
+
98
+ def test_reconnect_after_bad_connection_on_check_version
99
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: "arunit", name: "primary")
100
+ connection = ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.new(db_config.configuration_hash.merge(connection_retries: 0))
101
+ connection.connect!
102
+
103
+ # mimic a connection that hasn't checked and cached the server version yet i.e. without a raw_connection
104
+ connection.pool.instance_variable_set(:@server_version, nil)
105
+ connection.raw_connection.stub(:server_version, 0) do
106
+ error = assert_raises ActiveRecord::ConnectionFailed do
107
+ connection.reconnect!
108
+ end
109
+ assert_equal "Could not determine PostgreSQL version", error.message
110
+ end
111
+
112
+ # can reconnect after a bad connection
113
+ assert_nothing_raised do
114
+ connection.reconnect!
115
+ end
116
+ end
117
+
118
+ def test_reconnect_after_bad_connection_on_check_version_with_native_exception
119
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: "arunit", name: "primary")
120
+ connection = ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.new(db_config.configuration_hash.merge(connection_retries: 0))
121
+ connection.connect!
122
+
123
+ # mimic a connection that hasn't checked and cached the server version yet i.e. without a raw_connection
124
+ connection.pool.instance_variable_set(:@server_version, nil)
125
+ # https://github.com/ged/ruby-pg/commit/a565e153d4d05955342ad24d4845378eee956935
126
+ connection.raw_connection.stub(:server_version, -> { raise PG::ConnectionBad, "PQserverVersion() can't get server version" }) do
127
+ error = assert_raises ActiveRecord::ConnectionNotEstablished do
128
+ connection.reconnect!
129
+ end
130
+ assert_equal "PQserverVersion() can't get server version", error.message
131
+ end
132
+
133
+ # can reconnect after a bad connection
134
+ assert_nothing_raised do
135
+ connection.reconnect!
136
+ end
137
+ end
138
+
139
+ def test_schema_search_path_is_reapplied_after_reconnect
140
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: "arunit", name: "primary")
141
+
142
+ connection = ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.new(
143
+ db_config.configuration_hash.merge(schema_search_path: "public,foo")
144
+ )
145
+
146
+ connection.connect!
147
+
148
+ assert_equal "public, foo", connection.select_value("SHOW search_path")
149
+
150
+ connection.reconnect!
151
+
152
+ assert_equal "public, foo", connection.select_value("SHOW search_path")
153
+ ensure
154
+ connection&.disconnect!
155
+ end
156
+
157
+ def test_schema_search_path_is_reapplied_after_reset
158
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: "arunit", name: "primary")
159
+
160
+ connection = ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.new(
161
+ db_config.configuration_hash.merge(schema_search_path: "public,foo")
162
+ )
163
+
164
+ connection.connect!
165
+
166
+ assert_equal "public, foo", connection.select_value("SHOW search_path")
167
+
168
+ connection.reset!
169
+
170
+ assert_equal "public, foo", connection.select_value("SHOW search_path")
171
+ ensure
172
+ connection&.disconnect!
173
+ end
174
+
70
175
  def test_database_exists_returns_false_when_the_database_does_not_exist
71
176
  config = { database: "non_extant_database", adapter: "postgresql" }
72
177
  assert_not ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.database_exists?(config),
@@ -133,9 +238,11 @@ module ActiveRecord
133
238
  assert_equal "public.accounts_id_seq",
134
239
  @connection.serial_sequence("accounts", "id")
135
240
 
136
- assert_raises(ActiveRecord::StatementInvalid) do
241
+ error = assert_raises(ActiveRecord::StatementInvalid) do
137
242
  @connection.serial_sequence("zomg", "id")
138
243
  end
244
+
245
+ assert_equal @connection.pool, error.connection_pool
139
246
  end
140
247
 
141
248
  def test_default_sequence_name
@@ -292,6 +399,48 @@ module ActiveRecord
292
399
  end
293
400
  end
294
401
 
402
+ def test_partial_index_on_column_named_like_keyword
403
+ with_example_table('id serial primary key, number integer, "primary" boolean') do
404
+ @connection.add_index "ex", "id", name: "partial", where: "primary" # "primary" is a keyword
405
+ index = @connection.indexes("ex").find { |idx| idx.name == "partial" }
406
+ assert_equal '"primary"', index.where
407
+ end
408
+ end
409
+
410
+ if supports_index_include?
411
+ def test_include_index
412
+ with_example_table do
413
+ @connection.add_index "ex", %w{ id }, name: "include", include: :number
414
+ index = @connection.indexes("ex").find { |idx| idx.name == "include" }
415
+ assert_equal ["number"], index.include
416
+ end
417
+ end
418
+
419
+ def test_include_multiple_columns_index
420
+ with_example_table do
421
+ @connection.add_index "ex", %w{ id }, name: "include", include: [:number, :data]
422
+ index = @connection.indexes("ex").find { |idx| idx.name == "include" }
423
+ assert_equal ["number", "data"], index.include
424
+ end
425
+ end
426
+
427
+ def test_include_keyword_column_name
428
+ with_example_table("id integer, timestamp integer") do
429
+ @connection.add_index "ex", :id, name: "include", include: [:timestamp]
430
+ index = @connection.indexes("ex").find { |idx| idx.name == "include" }
431
+ assert_equal ["timestamp"], index.include
432
+ end
433
+ end
434
+
435
+ def test_include_escaped_quotes_column_name
436
+ with_example_table(%{id integer, "I""like""quotes" integer}) do
437
+ @connection.add_index "ex", :id, name: "include", include: [:"I\"like\"quotes"]
438
+ index = @connection.indexes("ex").find { |idx| idx.name == "include" }
439
+ assert_equal ["I\"like\"quotes"], index.include
440
+ end
441
+ end
442
+ end
443
+
295
444
  def test_expression_index
296
445
  with_example_table do
297
446
  expr = "mod(id, 10), abs(number)"
@@ -313,6 +462,35 @@ module ActiveRecord
313
462
  end
314
463
  end
315
464
 
465
+ def test_invalid_index
466
+ with_example_table do
467
+ @connection.exec_query("INSERT INTO ex (number) VALUES (1), (1)")
468
+ error = assert_raises(ActiveRecord::RecordNotUnique) do
469
+ @connection.add_index(:ex, :number, unique: true, algorithm: :concurrently, name: :invalid_index)
470
+ end
471
+ assert_match(/could not create unique index/, error.message)
472
+ assert_equal @connection.pool, error.connection_pool
473
+
474
+ assert @connection.index_exists?(:ex, :number, name: :invalid_index)
475
+ assert_not @connection.index_exists?(:ex, :number, name: :invalid_index, valid: true)
476
+ assert @connection.index_exists?(:ex, :number, name: :invalid_index, valid: false)
477
+ end
478
+ end
479
+
480
+ def test_index_with_not_distinct_nulls
481
+ skip("current adapter doesn't support nulls not distinct") unless supports_nulls_not_distinct?
482
+
483
+ with_example_table do
484
+ @connection.execute(<<~SQL)
485
+ CREATE UNIQUE INDEX index_ex_on_data ON ex (data) NULLS NOT DISTINCT WHERE number > 0
486
+ SQL
487
+
488
+ index = @connection.indexes(:ex).first
489
+ assert_equal true, index.unique
490
+ assert_match("number", index.where)
491
+ end
492
+ end
493
+
316
494
  def test_columns_for_distinct_zero_orders
317
495
  assert_equal "posts.id",
318
496
  @connection.columns_for_distinct("posts.id", [])
@@ -373,28 +551,53 @@ module ActiveRecord
373
551
  end
374
552
  end
375
553
 
554
+ def test_translate_no_connection_exception_to_not_established
555
+ pid = @connection.execute("SELECT pg_backend_pid()").to_a[0]["pg_backend_pid"]
556
+ @connection.pool.checkout.execute("SELECT pg_terminate_backend(#{pid})")
557
+ # If you run `@connection.execute` after the backend process has been terminated,
558
+ # you will get the "server closed the connection unexpectedly" rather than "no connection to the server".
559
+ # Because what we want to test here is an error that occurs during `send_query`,
560
+ # which is called internally by `@connection.execute`, we will call it explicitly.
561
+ # The `send_query` changes the internal `PG::Connection#status` to `CONNECTION_BAD`,
562
+ # so any subsequent queries will get the "no connection to the server" error.
563
+ # https://github.com/postgres/postgres/blob/REL_17_0/src/interfaces/libpq/fe-exec.c#L1686-L1691
564
+ @connection.instance_variable_get(:@raw_connection).send_query("SELECT 1")
565
+
566
+ assert_raise ActiveRecord::ConnectionNotEstablished do
567
+ @connection.execute("SELECT 1")
568
+ end
569
+ end
570
+
376
571
  def test_reload_type_map_for_newly_defined_types
377
- @connection.execute "CREATE TYPE feeling AS ENUM ('good', 'bad')"
378
- result = @connection.select_all "SELECT 'good'::feeling"
379
- assert_instance_of(PostgreSQLAdapter::OID::Enum,
380
- result.column_types["feeling"])
572
+ @connection.create_enum "feeling", ["good", "bad"]
573
+
574
+ # Runs only SELECT, no type map reloading.
575
+ assert_queries_count(1, include_schema: true) do
576
+ result = @connection.select_all "SELECT 'good'::feeling"
577
+ assert_instance_of(PostgreSQLAdapter::OID::Enum,
578
+ result.column_types["feeling"])
579
+ end
381
580
  ensure
382
- @connection.execute "DROP TYPE IF EXISTS feeling"
581
+ # Reloads type map.
582
+ assert_queries_match(/from pg_type/i, include_schema: true) do
583
+ @connection.drop_enum "feeling", if_exists: true
584
+ end
383
585
  reset_connection
384
586
  end
385
587
 
386
588
  def test_only_reload_type_map_once_for_every_unrecognized_type
387
589
  reset_connection
388
- connection = ActiveRecord::Base.connection
590
+ connection = ActiveRecord::Base.lease_connection
591
+ connection.select_all "SELECT 1" # eagerly initialize the connection
389
592
 
390
593
  silence_warnings do
391
- assert_queries 2, ignore_none: true do
594
+ assert_queries_count(2, include_schema: true) do
392
595
  connection.select_all "select 'pg_catalog.pg_class'::regclass"
393
596
  end
394
- assert_queries 1, ignore_none: true do
597
+ assert_queries_count(1, include_schema: true) do
395
598
  connection.select_all "select 'pg_catalog.pg_class'::regclass"
396
599
  end
397
- assert_queries 2, ignore_none: true do
600
+ assert_queries_count(2, include_schema: true) do
398
601
  connection.select_all "SELECT NULL::anyarray"
399
602
  end
400
603
  end
@@ -404,7 +607,7 @@ module ActiveRecord
404
607
 
405
608
  def test_only_warn_on_first_encounter_of_unrecognized_oid
406
609
  reset_connection
407
- connection = ActiveRecord::Base.connection
610
+ connection = ActiveRecord::Base.lease_connection
408
611
 
409
612
  warning = capture(:stderr) {
410
613
  connection.select_all "select 'pg_catalog.pg_class'::regclass"
@@ -433,14 +636,194 @@ module ActiveRecord
433
636
  end
434
637
  end
435
638
 
639
+ def test_only_check_for_insensitive_comparison_capability_once
640
+ @connection.execute("CREATE DOMAIN example_type AS integer")
641
+
642
+ with_example_table "id SERIAL PRIMARY KEY, number example_type" do
643
+ number_klass = Class.new(ActiveRecord::Base) do
644
+ self.table_name = "ex"
645
+ end
646
+ attribute = number_klass.arel_table[:number]
647
+ assert_queries_count(include_schema: true) do
648
+ @connection.case_insensitive_comparison(attribute, "foo")
649
+ end
650
+ assert_no_queries do
651
+ @connection.case_insensitive_comparison(attribute, "foo")
652
+ end
653
+ end
654
+ ensure
655
+ @connection.execute("DROP DOMAIN example_type")
656
+ end
657
+
658
+ def test_extensions_omits_current_schema_name
659
+ @connection.execute("DROP EXTENSION IF EXISTS hstore")
660
+ @connection.execute("CREATE SCHEMA customschema")
661
+ @connection.execute("CREATE EXTENSION hstore SCHEMA customschema")
662
+ assert_includes @connection.extensions, "customschema.hstore"
663
+ ensure
664
+ @connection.execute("DROP SCHEMA IF EXISTS customschema CASCADE")
665
+ @connection.execute("DROP EXTENSION IF EXISTS hstore")
666
+ end
667
+
668
+ def test_extensions_includes_non_current_schema_name
669
+ @connection.execute("DROP EXTENSION IF EXISTS hstore")
670
+ @connection.execute("CREATE EXTENSION hstore")
671
+ assert_includes @connection.extensions, "hstore"
672
+ ensure
673
+ @connection.execute("DROP EXTENSION IF EXISTS hstore")
674
+ end
675
+
676
+ def test_ignores_warnings_when_behaviour_ignore
677
+ with_db_warnings_action(:ignore) do
678
+ # libpq prints a warning to stderr from C, so we need to stub
679
+ # the whole file descriptors, not just Ruby's $stdout/$stderr.
680
+ _out, err = capture_subprocess_io do
681
+ result = @connection.execute("do $$ BEGIN RAISE WARNING 'foo'; END; $$")
682
+ assert_equal [], result.to_a
683
+ end
684
+ assert_match(/WARNING: foo/, err)
685
+ end
686
+ end
687
+
688
+ def test_logs_warnings_when_behaviour_log
689
+ with_db_warnings_action(:log) do
690
+ sql_warning = "[ActiveRecord::SQLWarning] PostgreSQL SQL warning (01000)"
691
+
692
+ assert_called_with(ActiveRecord::Base.logger, :warn, [sql_warning]) do
693
+ @connection.execute("do $$ BEGIN RAISE WARNING 'PostgreSQL SQL warning'; END; $$")
694
+ end
695
+ end
696
+ end
697
+
698
+ def test_raises_warnings_when_behaviour_raise
699
+ with_db_warnings_action(:raise) do
700
+ error = assert_raises(ActiveRecord::SQLWarning) do
701
+ @connection.execute("do $$ BEGIN RAISE WARNING 'PostgreSQL SQL warning'; END; $$")
702
+ end
703
+ assert_equal @connection.pool, error.connection_pool
704
+ end
705
+ end
706
+
707
+ def test_reports_when_behaviour_report
708
+ with_db_warnings_action(:report) do
709
+ error_reporter = ActiveSupport::ErrorReporter.new
710
+ subscriber = ActiveSupport::ErrorReporter::TestHelper::ErrorSubscriber.new
711
+
712
+ Rails.define_singleton_method(:error) { error_reporter }
713
+ Rails.error.subscribe(subscriber)
714
+
715
+ @connection.execute("do $$ BEGIN RAISE WARNING 'PostgreSQL SQL warning'; END; $$")
716
+ warning_event, * = subscriber.events.first
717
+
718
+ assert_kind_of ActiveRecord::SQLWarning, warning_event
719
+ assert_equal "PostgreSQL SQL warning", warning_event.message
720
+ end
721
+ end
722
+
723
+ def test_warnings_behaviour_can_be_customized_with_a_proc
724
+ warning_message = nil
725
+ warning_level = nil
726
+ warning_action = ->(warning) do
727
+ warning_message = warning.message
728
+ warning_level = warning.level
729
+ end
730
+
731
+ with_db_warnings_action(warning_action) do
732
+ @connection.execute("do $$ BEGIN RAISE WARNING 'PostgreSQL SQL warning'; END; $$")
733
+
734
+ assert_equal "PostgreSQL SQL warning", warning_message
735
+ assert_equal "WARNING", warning_level
736
+ end
737
+ end
738
+
739
+ def test_allowlist_of_warnings_to_ignore
740
+ with_db_warnings_action(:raise, [/PostgreSQL SQL warning/]) do
741
+ result = @connection.execute("do $$ BEGIN RAISE WARNING 'PostgreSQL SQL warning'; END; $$")
742
+
743
+ assert_equal [], result.to_a
744
+ end
745
+ end
746
+
747
+ def test_allowlist_of_warning_codes_to_ignore
748
+ with_example_table do
749
+ with_db_warnings_action(:raise, ["01000"]) do
750
+ result = @connection.execute("do $$ BEGIN RAISE WARNING 'PostgreSQL SQL warning'; END; $$")
751
+ assert_equal [], result.to_a
752
+ end
753
+ end
754
+ end
755
+
756
+ def test_does_not_raise_notice_level_warnings
757
+ with_db_warnings_action(:raise, [/PostgreSQL SQL warning/]) do
758
+ result = @connection.execute("DROP TABLE IF EXISTS non_existent_table")
759
+
760
+ assert_equal [], result.to_a
761
+ end
762
+ end
763
+
764
+ def test_date_decoding_enabled
765
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: "arunit", name: "primary")
766
+ connection = ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.new(db_config.configuration_hash)
767
+
768
+ with_postgresql_apdater_decode_dates do
769
+ date = connection.select_value("select '2024-01-01'::date")
770
+ assert_equal Date.new(2024, 01, 01), date
771
+ assert_equal Date, date.class
772
+ end
773
+ end
774
+
775
+ def test_date_decoding_disabled
776
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: "arunit", name: "primary")
777
+ connection = ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.new(db_config.configuration_hash)
778
+
779
+ date = connection.select_value("select '2024-01-01'::date")
780
+ assert_equal "2024-01-01", date
781
+ assert_equal String, date.class
782
+ end
783
+
784
+ def test_disable_extension_with_schema
785
+ @connection.execute("CREATE SCHEMA custom_schema")
786
+ @connection.execute("DROP EXTENSION IF EXISTS hstore")
787
+ @connection.execute("CREATE EXTENSION hstore SCHEMA custom_schema")
788
+ result = @connection.query("SELECT extname FROM pg_extension WHERE extnamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'custom_schema')")
789
+ assert_equal [["hstore"]], result.to_a
790
+
791
+ @connection.disable_extension "custom_schema.hstore"
792
+ result = @connection.query("SELECT extname FROM pg_extension WHERE extnamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'custom_schema')")
793
+ assert_equal [], result.to_a
794
+ ensure
795
+ @connection.execute("DROP EXTENSION IF EXISTS hstore")
796
+ @connection.execute("DROP SCHEMA IF EXISTS custom_schema CASCADE")
797
+ end
798
+
799
+ def test_disable_extension_without_schema
800
+ @connection.execute("DROP EXTENSION IF EXISTS hstore")
801
+ @connection.execute("CREATE EXTENSION hstore")
802
+ result = @connection.query("SELECT extname FROM pg_extension")
803
+ assert_includes result.to_a, ["hstore"]
804
+
805
+ @connection.disable_extension "hstore"
806
+ result = @connection.query("SELECT extname FROM pg_extension")
807
+ assert_not_includes result.to_a, ["hstore"]
808
+ ensure
809
+ @connection.execute("DROP EXTENSION IF EXISTS hstore")
810
+ end
811
+
436
812
  private
813
+ def with_postgresql_apdater_decode_dates
814
+ PostgreSQLAdapter.decode_dates = true
815
+ yield
816
+ ensure
817
+ PostgreSQLAdapter.decode_dates = false
818
+ end
819
+
437
820
  def with_example_table(definition = "id serial primary key, number integer, data character varying(255)", &block)
438
821
  super(@connection, "ex", definition, &block)
439
822
  end
440
823
 
441
824
  def connection_without_insert_returning
442
825
  db_config = ActiveRecord::Base.configurations.configs_for(env_name: "arunit", name: "primary")
443
- ActiveRecord::Base.postgresql_connection(db_config.configuration_hash.merge(insert_returning: false))
826
+ ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.new(db_config.configuration_hash.merge(insert_returning: false))
444
827
  end
445
828
  end
446
829
  end