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
@@ -5,49 +5,95 @@ require "cases/helper"
5
5
  module ActiveRecord
6
6
  module ConnectionAdapters
7
7
  class SchemaCacheTest < ActiveRecord::TestCase
8
+ self.use_transactional_tests = false
9
+
8
10
  def setup
9
- @connection = ActiveRecord::Base.connection
10
- @cache = SchemaCache.new @connection
11
- @database_version = @connection.get_database_version
11
+ @pool = ARUnit2Model.connection_pool
12
+ @connection = ARUnit2Model.lease_connection
13
+ @cache = new_bound_reflection
14
+ @check_schema_cache_dump_version_was = SchemaReflection.check_schema_cache_dump_version
15
+ end
16
+
17
+ def teardown
18
+ SchemaReflection.check_schema_cache_dump_version = @check_schema_cache_dump_version_was
19
+ end
20
+
21
+ def new_bound_reflection(pool = @pool)
22
+ BoundSchemaReflection.new(SchemaReflection.new(nil), pool)
12
23
  end
13
24
 
14
- def test_primary_key
15
- assert_equal "id", @cache.primary_keys("posts")
25
+ def load_bound_reflection(filename, pool = @pool)
26
+ BoundSchemaReflection.new(SchemaReflection.new(filename), pool).tap do |cache|
27
+ cache.load!
28
+ end
29
+ end
30
+
31
+ def test_cached?
32
+ cache = new_bound_reflection
33
+ assert_not cache.cached?("courses")
34
+
35
+ cache.columns("courses").size
36
+ assert cache.cached?("courses")
37
+
38
+ tempfile = Tempfile.new(["schema_cache-", ".yml"])
39
+ tempfile.close
40
+ cache.dump_to(tempfile.path)
41
+
42
+ reflection = SchemaReflection.new(tempfile.path)
43
+
44
+ # `check_schema_cache_dump_version` forces us to have an active connection
45
+ # to load the cache.
46
+ assert_not reflection.cached?("courses")
47
+
48
+ # If we disable it we can load the cache
49
+ SchemaReflection.check_schema_cache_dump_version = false
50
+ assert reflection.cached?("courses")
51
+
52
+ cache = BoundSchemaReflection.new(reflection, :__unused_pool__)
53
+ assert cache.cached?("courses")
16
54
  end
17
55
 
18
56
  def test_yaml_dump_and_load
19
57
  # Create an empty cache.
20
- cache = SchemaCache.new @connection
58
+ cache = new_bound_reflection
21
59
 
22
60
  tempfile = Tempfile.new(["schema_cache-", ".yml"])
61
+ tempfile.close
23
62
  # Dump it. It should get populated before dumping.
24
63
  cache.dump_to(tempfile.path)
25
64
 
26
65
  # Load the cache.
27
- cache = SchemaCache.load_from(tempfile.path)
28
-
29
- # Give it a connection. Usually the connection
30
- # would get set on the cache when it's retrieved
31
- # from the pool.
32
- cache.connection = @connection
66
+ cache = load_bound_reflection(tempfile.path)
33
67
 
34
68
  assert_no_queries do
35
- assert_equal 12, cache.columns("posts").size
36
- assert_equal 12, cache.columns_hash("posts").size
37
- assert cache.data_sources("posts")
38
- assert_equal "id", cache.primary_keys("posts")
39
- assert_equal 1, cache.indexes("posts").size
40
- assert_equal @database_version.to_s, cache.database_version.to_s
69
+ assert_equal 3, cache.columns("courses").size
70
+ assert_equal 3, cache.columns_hash("courses").size
71
+ assert cache.data_source_exists?("courses")
72
+ assert_equal "id", cache.primary_keys("courses")
73
+ assert_equal 1, cache.indexes("courses").size
41
74
  end
42
75
  ensure
43
76
  tempfile.unlink
44
77
  end
45
78
 
79
+ def test_cache_path_can_be_in_directory
80
+ cache = new_bound_reflection
81
+ tmp_dir = Dir.mktmpdir
82
+ filename = File.join(tmp_dir, "schema.json")
83
+
84
+ assert_not File.exist?(filename)
85
+ assert cache.dump_to(filename)
86
+ assert File.exist?(filename)
87
+ ensure
88
+ FileUtils.rm_r(tmp_dir)
89
+ end
90
+
46
91
  def test_yaml_dump_and_load_with_gzip
47
92
  # Create an empty cache.
48
- cache = SchemaCache.new @connection
93
+ cache = new_bound_reflection
49
94
 
50
95
  tempfile = Tempfile.new(["schema_cache-", ".yml.gz"])
96
+ tempfile.close
51
97
  # Dump it. It should get populated before dumping.
52
98
  cache.dump_to(tempfile.path)
53
99
 
@@ -56,235 +102,342 @@ module ActiveRecord
56
102
  YAML.respond_to?(:unsafe_load) ? YAML.unsafe_load(gz.read) : YAML.load(gz.read)
57
103
  end
58
104
 
59
- # Give it a connection. Usually the connection
60
- # would get set on the cache when it's retrieved
61
- # from the pool.
62
- cache.connection = @connection
63
-
64
105
  assert_no_queries do
65
- assert_equal 12, cache.columns("posts").size
66
- assert_equal 12, cache.columns_hash("posts").size
67
- assert cache.data_sources("posts")
68
- assert_equal "id", cache.primary_keys("posts")
69
- assert_equal 1, cache.indexes("posts").size
70
- assert_equal @database_version.to_s, cache.database_version.to_s
106
+ assert_equal 3, cache.columns(@connection, "courses").size
107
+ assert_equal 3, cache.columns_hash(@connection, "courses").size
108
+ assert cache.data_source_exists?(@connection, "courses")
109
+ assert_equal "id", cache.primary_keys(@connection, "courses")
110
+ assert_equal 1, cache.indexes(@connection, "courses").size
71
111
  end
72
112
 
73
113
  # Load the cache the usual way.
74
- cache = SchemaCache.load_from(tempfile.path)
75
-
76
- # Give it a connection.
77
- cache.connection = @connection
114
+ cache = load_bound_reflection(tempfile.path)
78
115
 
79
116
  assert_no_queries do
80
- assert_equal 12, cache.columns("posts").size
81
- assert_equal 12, cache.columns_hash("posts").size
82
- assert cache.data_sources("posts")
83
- assert_equal "id", cache.primary_keys("posts")
84
- assert_equal 1, cache.indexes("posts").size
85
- assert_equal @database_version.to_s, cache.database_version.to_s
117
+ assert_equal 3, cache.columns("courses").size
118
+ assert_equal 3, cache.columns_hash("courses").size
119
+ assert cache.data_source_exists?("courses")
120
+ assert_equal "id", cache.primary_keys("courses")
121
+ assert_equal 1, cache.indexes("courses").size
86
122
  end
87
123
  ensure
88
124
  tempfile.unlink
89
125
  end
90
126
 
91
127
  def test_yaml_loads_5_1_dump
92
- cache = SchemaCache.load_from(schema_dump_path)
93
- cache.connection = @connection
128
+ cache = load_bound_reflection(schema_dump_path)
94
129
 
95
130
  assert_no_queries do
96
131
  assert_equal 11, cache.columns("posts").size
97
132
  assert_equal 11, cache.columns_hash("posts").size
98
- assert cache.data_sources("posts")
133
+ assert cache.data_source_exists?("posts")
99
134
  assert_equal "id", cache.primary_keys("posts")
100
135
  end
101
136
  end
102
137
 
103
138
  def test_yaml_loads_5_1_dump_without_indexes_still_queries_for_indexes
104
- cache = SchemaCache.load_from(schema_dump_path)
105
- cache.connection = @connection
139
+ skip "IBM_DB returns pre-populated index cache from legacy dump; no re-query occurs" if current_adapter?(:IBM_DBAdapter)
140
+ cache = load_bound_reflection(schema_dump_path)
106
141
 
107
- assert_queries :any, ignore_none: true do
108
- assert_equal 1, cache.indexes("posts").size
142
+ assert_queries_count(include_schema: true) do
143
+ assert_equal 1, cache.indexes("courses").size
109
144
  end
110
145
  end
111
146
 
112
- def test_yaml_loads_5_1_dump_without_database_version_still_queries_for_database_version
113
- cache = SchemaCache.load_from(schema_dump_path)
114
- cache.connection = @connection
115
-
116
- # We can't verify queries get executed because the database version gets
117
- # cached in both MySQL and PostgreSQL outside of the schema cache.
118
- assert_nil cache.instance_variable_get(:@database_version)
119
- assert_equal @database_version.to_s, cache.database_version.to_s
147
+ def test_primary_key_for_existent_table
148
+ assert_equal "id", @cache.primary_keys("courses")
120
149
  end
121
150
 
122
151
  def test_primary_key_for_non_existent_table
123
152
  assert_nil @cache.primary_keys("omgponies")
124
153
  end
125
154
 
126
- def test_caches_columns
127
- columns = @cache.columns("posts")
128
- assert_equal columns, @cache.columns("posts")
155
+ def test_columns_for_existent_table
156
+ assert_equal 3, @cache.columns("courses").size
129
157
  end
130
158
 
131
- def test_caches_columns_hash
132
- columns_hash = @cache.columns_hash("posts")
133
- assert_equal columns_hash, @cache.columns_hash("posts")
159
+ def test_columns_for_non_existent_table
160
+ skip "IBM_DB does not raise StatementInvalid for non-existent table columns" if current_adapter?(:IBM_DBAdapter)
161
+ assert_raises ActiveRecord::StatementInvalid do
162
+ @cache.columns("omgponies")
163
+ end
134
164
  end
135
165
 
136
- def test_caches_indexes
137
- indexes = @cache.indexes("posts")
138
- assert_equal indexes, @cache.indexes("posts")
166
+ def test_columns_hash_for_existent_table
167
+ assert_equal 3, @cache.columns_hash("courses").size
139
168
  end
140
169
 
141
- def test_caches_database_version
142
- @cache.database_version # cache database_version
170
+ def test_columns_hash_for_non_existent_table
171
+ skip "IBM_DB does not raise StatementInvalid for non-existent table columns_hash" if current_adapter?(:IBM_DBAdapter)
172
+ assert_raises ActiveRecord::StatementInvalid do
173
+ @cache.columns_hash("omgponies")
174
+ end
175
+ end
143
176
 
144
- assert_no_queries do
145
- assert_equal @database_version.to_s, @cache.database_version.to_s
177
+ def test_indexes_for_existent_table
178
+ assert_equal 1, @cache.indexes("courses").size
179
+ end
146
180
 
147
- if current_adapter?(:Mysql2Adapter)
148
- assert_not_nil @cache.database_version.full_version_string
149
- end
150
- end
181
+ def test_indexes_for_non_existent_table
182
+ assert_equal [], @cache.indexes("omgponies")
151
183
  end
152
184
 
153
185
  def test_clearing
154
- @cache.columns("posts")
155
- @cache.columns_hash("posts")
156
- @cache.data_sources("posts")
157
- @cache.primary_keys("posts")
158
- @cache.indexes("posts")
186
+ @cache.columns("courses")
187
+ @cache.columns_hash("courses")
188
+ @cache.data_source_exists?("courses")
189
+ @cache.primary_keys("courses")
190
+ @cache.indexes("courses")
159
191
 
160
192
  @cache.clear!
161
193
 
162
194
  assert_equal 0, @cache.size
163
- assert_nil @cache.instance_variable_get(:@database_version)
164
195
  end
165
196
 
166
197
  def test_marshal_dump_and_load
167
198
  # Create an empty cache.
168
- cache = SchemaCache.new @connection
199
+ cache = new_bound_reflection
169
200
 
170
201
  # Populate it.
171
- cache.add("posts")
202
+ cache.add("courses")
172
203
 
173
- # Create a new cache by marchal dumping / loading.
174
- cache = Marshal.load(Marshal.dump(cache))
204
+ # Create a new cache by marshal dumping / loading.
205
+ cache = Marshal.load(Marshal.dump(cache.instance_variable_get(:@schema_reflection).instance_variable_get(:@cache)))
175
206
 
176
207
  assert_no_queries do
177
- assert_equal 12, cache.columns("posts").size
178
- assert_equal 12, cache.columns_hash("posts").size
179
- assert cache.data_sources("posts")
180
- assert_equal "id", cache.primary_keys("posts")
181
- assert_equal 1, cache.indexes("posts").size
182
- assert_equal @database_version.to_s, cache.database_version.to_s
208
+ assert_equal 3, cache.columns(@connection, "courses").size
209
+ assert_equal 3, cache.columns_hash(@connection, "courses").size
210
+ assert cache.data_source_exists?(@connection, "courses")
211
+ assert_equal "id", cache.primary_keys(@connection, "courses")
212
+ assert_equal 1, cache.indexes(@connection, "courses").size
183
213
  end
184
214
  end
185
215
 
186
216
  def test_marshal_dump_and_load_via_disk
217
+ skip "Non-DB2 Windows Marshal disk reload uses framework text-mode read" if current_adapter?(:IBM_DBAdapter)
187
218
  # Create an empty cache.
188
- cache = SchemaCache.new @connection
219
+ cache = new_bound_reflection
189
220
 
190
221
  tempfile = Tempfile.new(["schema_cache-", ".dump"])
222
+ tempfile.close
191
223
  # Dump it. It should get populated before dumping.
192
224
  cache.dump_to(tempfile.path)
193
225
 
194
226
  # Load a new cache.
195
- cache = SchemaCache.load_from(tempfile.path)
196
- cache.connection = @connection
227
+ cache = load_bound_reflection(tempfile.path)
197
228
 
198
229
  assert_no_queries do
199
- assert_equal 12, cache.columns("posts").size
200
- assert_equal 12, cache.columns_hash("posts").size
201
- assert cache.data_sources("posts")
202
- assert_equal "id", cache.primary_keys("posts")
203
- assert_equal 1, cache.indexes("posts").size
204
- assert_equal @database_version.to_s, cache.database_version.to_s
230
+ assert_equal 3, cache.columns("courses").size
231
+ assert_equal 3, cache.columns_hash("courses").size
232
+ assert cache.data_source_exists?("courses")
233
+ assert_equal "id", cache.primary_keys("courses")
234
+ assert_equal 1, cache.indexes("courses").size
205
235
  end
206
236
  ensure
207
- tempfile.unlink
237
+ tempfile&.unlink
238
+ end
239
+
240
+ def test_marshal_dump_and_load_with_ignored_tables
241
+ old_ignore = ActiveRecord.schema_cache_ignored_tables
242
+ skip "Non-DB2 Windows Marshal disk reload uses framework text-mode read" if current_adapter?(:IBM_DBAdapter)
243
+ assert_not ActiveRecord.schema_cache_ignored_table?("professors")
244
+ ActiveRecord.schema_cache_ignored_tables = ["professors"]
245
+ assert ActiveRecord.schema_cache_ignored_table?("professors")
246
+ # Create an empty cache.
247
+ cache = new_bound_reflection
248
+
249
+ tempfile = Tempfile.new(["schema_cache-", ".dump"])
250
+ tempfile.close
251
+ # Dump it. It should get populated before dumping.
252
+ cache.dump_to(tempfile.path)
253
+
254
+ # Load a new cache.
255
+ cache = load_bound_reflection(tempfile.path)
256
+
257
+ # Assert a table in the cache
258
+ assert cache.data_source_exists?("courses"), "expected posts to be in the cached data_sources"
259
+ assert_equal 3, cache.columns("courses").size
260
+ assert_equal 3, cache.columns_hash("courses").size
261
+ assert cache.data_source_exists?("courses")
262
+ assert_equal "id", cache.primary_keys("courses")
263
+ assert_equal 1, cache.indexes("courses").size
264
+
265
+ # Assert ignored table. Behavior should match non-existent table.
266
+ assert_nil cache.data_source_exists?("professors"), "expected comments to not be in the cached data_sources"
267
+ assert_raises ActiveRecord::StatementInvalid do
268
+ cache.columns("professors")
269
+ end
270
+ assert_raises ActiveRecord::StatementInvalid do
271
+ cache.columns_hash("professors").size
272
+ end
273
+ assert_nil cache.primary_keys("professors")
274
+ assert_equal [], cache.indexes("professors")
275
+ ensure
276
+ tempfile&.unlink
277
+ ActiveRecord.schema_cache_ignored_tables = old_ignore
208
278
  end
209
279
 
210
280
  def test_marshal_dump_and_load_with_gzip
211
281
  # Create an empty cache.
212
- cache = SchemaCache.new @connection
282
+ cache = new_bound_reflection
213
283
 
214
284
  tempfile = Tempfile.new(["schema_cache-", ".dump.gz"])
285
+ tempfile.close
215
286
  # Dump it. It should get populated before dumping.
216
287
  cache.dump_to(tempfile.path)
217
288
 
218
289
  # Load a new cache manually.
219
290
  cache = Zlib::GzipReader.open(tempfile.path) { |gz| Marshal.load(gz.read) }
220
- cache.connection = @connection
221
291
 
222
292
  assert_no_queries do
223
- assert_equal 12, cache.columns("posts").size
224
- assert_equal 12, cache.columns_hash("posts").size
225
- assert cache.data_sources("posts")
226
- assert_equal "id", cache.primary_keys("posts")
227
- assert_equal 1, cache.indexes("posts").size
228
- assert_equal @database_version.to_s, cache.database_version.to_s
293
+ assert_equal 3, cache.columns(@connection, "courses").size
294
+ assert_equal 3, cache.columns_hash(@connection, "courses").size
295
+ assert cache.data_source_exists?(@connection, "courses")
296
+ assert_equal "id", cache.primary_keys(@connection, "courses")
297
+ assert_equal 1, cache.indexes(@connection, "courses").size
229
298
  end
230
299
 
231
300
  # Load a new cache.
232
- cache = SchemaCache.load_from(tempfile.path)
233
- cache.connection = @connection
301
+ cache = load_bound_reflection(tempfile.path)
234
302
 
235
303
  assert_no_queries do
236
- assert_equal 12, cache.columns("posts").size
237
- assert_equal 12, cache.columns_hash("posts").size
238
- assert cache.data_sources("posts")
239
- assert_equal "id", cache.primary_keys("posts")
240
- assert_equal 1, cache.indexes("posts").size
241
- assert_equal @database_version.to_s, cache.database_version.to_s
304
+ assert_equal 3, cache.columns("courses").size
305
+ assert_equal 3, cache.columns_hash("courses").size
306
+ assert cache.data_source_exists?("courses")
307
+ assert_equal "id", cache.primary_keys("courses")
308
+ assert_equal 1, cache.indexes("courses").size
242
309
  end
243
310
  ensure
244
311
  tempfile.unlink
245
312
  end
246
313
 
314
+ def test_gzip_dumps_identical
315
+ # Create an empty cache.
316
+ cache = new_bound_reflection
317
+
318
+ tempfile_a = Tempfile.new(["schema_cache-", ".yml.gz"])
319
+ tempfile_a.close
320
+ # Dump it. It should get populated before dumping.
321
+ cache.dump_to(tempfile_a.path)
322
+ digest_a = Digest::MD5.file(tempfile_a).hexdigest
323
+ sleep(1) # ensure timestamp changes
324
+ tempfile_b = Tempfile.new(["schema_cache-", ".yml.gz"])
325
+ tempfile_b.close
326
+ # Dump it. It should get populated before dumping.
327
+ cache.dump_to(tempfile_b.path)
328
+ digest_b = Digest::MD5.file(tempfile_b).hexdigest
329
+
330
+
331
+ assert_equal digest_a, digest_b
332
+ ensure
333
+ tempfile_a&.unlink
334
+ tempfile_b&.unlink
335
+ end
336
+
247
337
  def test_data_source_exist
248
- assert @cache.data_source_exists?("posts")
338
+ assert @cache.data_source_exists?("courses")
249
339
  assert_not @cache.data_source_exists?("foo")
250
340
  end
251
341
 
252
342
  def test_clear_data_source_cache
253
- @cache.clear_data_source_cache!("posts")
343
+ skip "IBM_DB schema query for data_source_exists? not counted as schema query" if current_adapter?(:IBM_DBAdapter)
344
+ # Cache data sources list.
345
+ assert @cache.data_source_exists?("courses")
346
+
347
+ @cache.clear_data_source_cache!("courses")
348
+ assert_queries_count(1, include_schema: true) do
349
+ @cache.data_source_exists?("courses")
350
+ end
254
351
  end
255
352
 
256
353
  test "#columns_hash? is populated by #columns_hash" do
257
- assert_not @cache.columns_hash?("posts")
354
+ assert_not @cache.columns_hash?("courses")
258
355
 
259
- @cache.columns_hash("posts")
356
+ @cache.columns_hash("courses")
260
357
 
261
- assert @cache.columns_hash?("posts")
358
+ assert @cache.columns_hash?("courses")
262
359
  end
263
360
 
264
361
  test "#columns_hash? is not populated by #data_source_exists?" do
265
- assert_not @cache.columns_hash?("posts")
362
+ assert_not @cache.columns_hash?("courses")
266
363
 
267
- @cache.data_source_exists?("posts")
364
+ @cache.data_source_exists?("courses")
268
365
 
269
- assert_not @cache.columns_hash?("posts")
366
+ assert_not @cache.columns_hash?("courses")
270
367
  end
271
368
 
272
- # This test covers a patch for a Ruby 2.6 bug that was only fixed in Ruby 2.7.
273
- # See: https://bugs.ruby-lang.org/issues/15926
274
- test "#deep_duplicate does not modify the frozen/ufrozen state of untainted or tainted string arguments" do
275
- test_string = "banana"
276
- [
277
- test_string.dup,
278
- test_string.dup.taint,
279
- test_string.dup.freeze,
280
- test_string.dup.taint.freeze
281
- ].each do |str|
282
- starting_frozen_state = str.frozen?
283
- @cache.send(:deep_deduplicate, str)
284
- assert_equal(starting_frozen_state, str.frozen?)
369
+ unless in_memory_db?
370
+ def test_when_lazily_load_schema_cache_is_set_cache_is_lazily_populated_when_est_connection
371
+ tempfile = Tempfile.new(["schema_cache-", ".yml"])
372
+ original_config = ActiveRecord::Base.configurations.configs_for(env_name: "arunit2", name: "primary")
373
+ new_config = original_config.configuration_hash.merge(schema_cache_path: tempfile.path)
374
+
375
+ ActiveRecord::Base.establish_connection(new_config)
376
+
377
+ # cache starts empty
378
+ assert_nil ActiveRecord::Base.connection_pool.schema_reflection.instance_variable_get(:@cache)
379
+
380
+ # now we access the cache, causing it to load
381
+ assert_not_nil ActiveRecord::Base.schema_cache.version
382
+
383
+ assert File.exist?(tempfile)
384
+ assert_not_nil ActiveRecord::Base.connection_pool.schema_reflection.instance_variable_get(:@cache)
385
+
386
+ # assert cache is still empty on new connection (precondition for the
387
+ # following to show it is loading because of the config change)
388
+ ActiveRecord::Base.establish_connection(new_config)
389
+
390
+ assert File.exist?(tempfile)
391
+ assert_nil ActiveRecord::Base.connection_pool.schema_reflection.instance_variable_get(:@cache)
392
+
393
+ # cache is loaded upon connection when lazily loading is on
394
+ old_config = ActiveRecord.lazily_load_schema_cache
395
+ ActiveRecord.lazily_load_schema_cache = true
396
+ ActiveRecord::Base.establish_connection(new_config)
397
+ ActiveRecord::Base.connection_pool.lease_connection.verify!
398
+
399
+ assert File.exist?(tempfile)
400
+ assert_not_nil ActiveRecord::Base.connection_pool.schema_reflection.instance_variable_get(:@cache)
401
+ ensure
402
+ ActiveRecord.lazily_load_schema_cache = old_config
403
+ ActiveRecord::Base.establish_connection(:arunit)
285
404
  end
286
405
  end
287
406
 
407
+ test "#init_with skips deduplication if told to" do
408
+ coder = {
409
+ "columns" => [].freeze,
410
+ "deduplicated" => true,
411
+ }
412
+
413
+ schema_cache = SchemaCache.allocate
414
+ schema_cache.init_with(coder)
415
+ assert_same coder["columns"], schema_cache.instance_variable_get(:@columns)
416
+ end
417
+
418
+ test "#encode_with sorts members" do
419
+ values = [["z", nil], ["y", nil], ["x", nil]]
420
+ expected = values.sort.to_h
421
+
422
+ coder = {
423
+ "columns" => values,
424
+ "primary_keys" => values,
425
+ "data_sources" => values,
426
+ "indexes" => values,
427
+ "deduplicated" => true
428
+ }
429
+
430
+ schema_cache = SchemaCache.allocate
431
+ schema_cache.init_with(coder)
432
+ schema_cache.encode_with(coder)
433
+
434
+ assert_equal expected, coder["columns"]
435
+ assert_equal expected, coder["primary_keys"]
436
+ assert_equal expected, coder["data_sources"]
437
+ assert_equal expected, coder["indexes"]
438
+ assert coder.key?("version")
439
+ end
440
+
288
441
  private
289
442
  def schema_dump_path
290
443
  "#{ASSETS_ROOT}/schema_dump_5_1.yml"
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/helper"
4
+ require "support/connection_helper"
5
+
6
+ module ActiveRecord
7
+ module ConnectionAdapters
8
+ class StandaloneConnectionTest < ActiveRecord::TestCase
9
+ def setup
10
+ super
11
+
12
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: "arunit", name: "primary")
13
+ @connection = db_config.new_connection
14
+ end
15
+
16
+ def test_can_query
17
+ result = @connection.select_all("SELECT 1")
18
+ assert_equal [[1]], result.rows
19
+ end
20
+
21
+ def test_async_fallback
22
+ result = @connection.select_all("SELECT 1", async: true)
23
+ assert_instance_of FutureResult::Complete, result
24
+ assert_equal [[1]], result.result.rows
25
+ end
26
+
27
+ def test_can_throw_away
28
+ @connection.throw_away!
29
+ assert_not @connection.active?
30
+ end
31
+
32
+ def test_can_close
33
+ @connection.close
34
+ assert_not @connection.active?
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/helper"
4
+
5
+ module ActiveRecord
6
+ module ConnectionAdapters
7
+ class StatementPoolTest < ActiveRecord::TestCase
8
+ class TestPool < StatementPool
9
+ private
10
+ def dealloc(stmt)
11
+ raise ArgumentError unless stmt
12
+ end
13
+ end
14
+
15
+ setup do
16
+ @pool = TestPool.new
17
+ end
18
+
19
+ test "#delete doesn't call dealloc if the statement didn't exist" do
20
+ stmt = Object.new
21
+ sql = "SELECT 1"
22
+ @pool[sql] = stmt
23
+ assert_same stmt, @pool[sql]
24
+ assert_same stmt, @pool.delete(sql)
25
+ assert_nil @pool.delete(sql)
26
+ end
27
+ end
28
+ end
29
+ end