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
@@ -15,8 +15,14 @@ require MIGRATIONS_ROOT + "/rename/1_we_need_things"
15
15
  require MIGRATIONS_ROOT + "/rename/2_rename_things"
16
16
  require MIGRATIONS_ROOT + "/decimal/1_give_me_big_numbers"
17
17
 
18
+ class ValidPeopleHaveLastNames < ActiveRecord::Migration::Current
19
+ def change
20
+ drop_table :people
21
+ end
22
+ end
23
+
18
24
  class BigNumber < ActiveRecord::Base
19
- unless current_adapter?(:PostgreSQLAdapter, :SQLite3Adapter)
25
+ unless ActiveRecord::TestCase.current_adapter?(:PostgreSQLAdapter, :SQLite3Adapter)
20
26
  attribute :value_of_e, :integer
21
27
  end
22
28
  attribute :my_house_population, :integer
@@ -34,51 +40,72 @@ class MigrationTest < ActiveRecord::TestCase
34
40
  def setup
35
41
  super
36
42
  %w(reminders people_reminders prefix_reminders_suffix p_things_s).each do |table|
37
- Reminder.connection.drop_table(table) rescue nil
43
+ Reminder.lease_connection.drop_table(table) rescue nil
38
44
  end
39
45
  Reminder.reset_column_information
40
46
  @verbose_was, ActiveRecord::Migration.verbose = ActiveRecord::Migration.verbose, false
41
- @schema_migration = ActiveRecord::Base.connection.schema_migration
42
- ActiveRecord::Base.connection.schema_cache.clear!
47
+ @pool = ActiveRecord::Base.connection_pool
48
+ @schema_migration = @pool.schema_migration
49
+ @internal_metadata = @pool.internal_metadata
50
+ ActiveRecord::Base.schema_cache.clear!
43
51
  end
44
52
 
45
53
  teardown do
46
54
  ActiveRecord::Base.table_name_prefix = ""
47
55
  ActiveRecord::Base.table_name_suffix = ""
48
56
 
49
- ActiveRecord::SchemaMigration.create_table
50
- ActiveRecord::SchemaMigration.delete_all
57
+ @schema_migration.create_table
58
+ @schema_migration.delete_all_versions
51
59
 
52
60
  %w(things awesome_things prefix_things_suffix p_awesome_things_s).each do |table|
53
- Thing.connection.drop_table(table) rescue nil
61
+ Thing.lease_connection.drop_table(table) rescue nil
54
62
  end
55
63
  Thing.reset_column_information
64
+ clear_statement_cache(Thing)
56
65
 
57
66
  %w(reminders people_reminders prefix_reminders_suffix).each do |table|
58
- Reminder.connection.drop_table(table) rescue nil
67
+ Reminder.lease_connection.drop_table(table) rescue nil
59
68
  end
60
69
  Reminder.reset_table_name
61
70
  Reminder.reset_column_information
71
+ clear_statement_cache(Reminder)
62
72
 
63
73
  %w(last_name key bio age height wealth birthday favorite_day
64
74
  moment_of_truth male administrator funny).each do |column|
65
- Person.connection.remove_column("people", column) rescue nil
75
+ Person.lease_connection.remove_column("people", column) rescue nil
66
76
  end
67
- Person.connection.remove_column("people", "first_name") rescue nil
68
- Person.connection.remove_column("people", "middle_name") rescue nil
69
- Person.connection.add_column("people", "first_name", :string)
77
+ Person.lease_connection.remove_column("people", "first_name") rescue nil
78
+ Person.lease_connection.remove_column("people", "middle_name") rescue nil
79
+ Person.lease_connection.add_column("people", "first_name", :string)
70
80
  Person.reset_column_information
81
+ clear_statement_cache(Person)
71
82
 
72
83
  ActiveRecord::Migration.verbose = @verbose_was
73
84
  end
74
85
 
86
+ def test_migration_context_with_default_schema_migration
87
+ migrations_path = MIGRATIONS_ROOT + "/valid"
88
+ migrator = ActiveRecord::MigrationContext.new(migrations_path)
89
+ migrator.up
90
+
91
+ assert_equal 3, migrator.current_version
92
+ assert_equal false, migrator.needs_migration?
93
+
94
+ migrator.down
95
+ assert_equal 0, migrator.current_version
96
+ assert_equal true, migrator.needs_migration?
97
+
98
+ @schema_migration.create_version(3)
99
+ assert_equal true, migrator.needs_migration?
100
+ end
101
+
75
102
  def test_migration_version_matches_component_version
76
103
  assert_equal ActiveRecord::VERSION::STRING.to_f, ActiveRecord::Migration.current_version
77
104
  end
78
105
 
79
106
  def test_migrator_versions
80
107
  migrations_path = MIGRATIONS_ROOT + "/valid"
81
- migrator = ActiveRecord::MigrationContext.new(migrations_path, @schema_migration)
108
+ migrator = ActiveRecord::MigrationContext.new(migrations_path, @schema_migration, @internal_metadata)
82
109
 
83
110
  migrator.up
84
111
  assert_equal 3, migrator.current_version
@@ -88,38 +115,48 @@ class MigrationTest < ActiveRecord::TestCase
88
115
  assert_equal 0, migrator.current_version
89
116
  assert_equal true, migrator.needs_migration?
90
117
 
91
- ActiveRecord::SchemaMigration.create!(version: 3)
118
+ @schema_migration.create_version(3)
92
119
  assert_equal true, migrator.needs_migration?
93
120
  end
94
121
 
122
+ def test_name_collision_across_dbs
123
+ migrations_path = MIGRATIONS_ROOT + "/valid"
124
+ migrator = ActiveRecord::MigrationContext.new(migrations_path)
125
+ migrator.up
126
+
127
+ assert_column Person, :last_name
128
+ end
129
+
95
130
  def test_migration_detection_without_schema_migration_table
96
- ActiveRecord::Base.connection.drop_table "schema_migrations", if_exists: true
131
+ @schema_migration.drop_table
97
132
 
98
133
  migrations_path = MIGRATIONS_ROOT + "/valid"
99
- migrator = ActiveRecord::MigrationContext.new(migrations_path, @schema_migration)
134
+ migrator = ActiveRecord::MigrationContext.new(migrations_path, @schema_migration, @internal_metadata)
100
135
 
101
136
  assert_equal true, migrator.needs_migration?
137
+ ensure
138
+ @schema_migration.create_table
102
139
  end
103
140
 
104
141
  def test_any_migrations
105
- migrator = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/valid", @schema_migration)
142
+ migrator = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/valid", @schema_migration, @internal_metadata)
106
143
 
107
- assert_predicate migrator, :any_migrations?
144
+ assert_predicate migrator.migrations, :any?
108
145
 
109
- migrator_empty = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/empty", @schema_migration)
146
+ migrator_empty = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/empty", @schema_migration, @internal_metadata)
110
147
 
111
- assert_not_predicate migrator_empty, :any_migrations?
148
+ assert_not_predicate migrator_empty.migrations, :any?
112
149
  end
113
150
 
114
151
  def test_migration_version
115
- migrator = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/version_check", @schema_migration)
152
+ migrator = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/version_check", @schema_migration, @internal_metadata)
116
153
  assert_equal 0, migrator.current_version
117
154
  migrator.up(20131219224947)
118
155
  assert_equal 20131219224947, migrator.current_version
119
156
  end
120
157
 
121
158
  def test_create_table_raises_if_already_exists
122
- connection = Person.connection
159
+ connection = Person.lease_connection
123
160
  connection.create_table :testings, force: true do |t|
124
161
  t.string :foo
125
162
  end
@@ -134,7 +171,7 @@ class MigrationTest < ActiveRecord::TestCase
134
171
  end
135
172
 
136
173
  def test_create_table_with_if_not_exists_true
137
- connection = Person.connection
174
+ connection = Person.lease_connection
138
175
  connection.create_table :testings, force: true do |t|
139
176
  t.string :foo
140
177
  end
@@ -148,8 +185,37 @@ class MigrationTest < ActiveRecord::TestCase
148
185
  connection.drop_table :testings, if_exists: true
149
186
  end
150
187
 
188
+ def test_create_table_raises_for_long_table_names
189
+ connection = Person.lease_connection
190
+ name_limit = connection.table_name_length
191
+ long_name = "a" * (name_limit + 1)
192
+ short_name =
193
+ if current_adapter?(:PostgreSQLAdapter)
194
+ "public." + "a" * name_limit
195
+ else
196
+ "a" * name_limit
197
+ end
198
+
199
+ error = assert_raises(ArgumentError) do
200
+ connection.create_table(long_name)
201
+ end
202
+ assert_equal "Table name '#{long_name}' is too long; the limit is #{name_limit} characters", error.message
203
+
204
+ connection.create_table(short_name)
205
+ assert connection.table_exists?(short_name)
206
+ ensure
207
+ connection.drop_table short_name, if_exists: true
208
+ end
209
+
210
+ def test_create_table_with_force_and_if_not_exists
211
+ connection = Person.lease_connection
212
+ assert_raises(ArgumentError, match: /Options `:force` and `:if_not_exists` cannot be used simultaneously/) do
213
+ connection.create_table(:testings, force: true, if_not_exists: true)
214
+ end
215
+ end
216
+
151
217
  def test_create_table_with_indexes_and_if_not_exists_true
152
- connection = Person.connection
218
+ connection = Person.lease_connection
153
219
  connection.create_table :testings, force: true do |t|
154
220
  t.references :people
155
221
  t.string :foo
@@ -168,15 +234,15 @@ class MigrationTest < ActiveRecord::TestCase
168
234
  def test_create_table_with_force_true_does_not_drop_nonexisting_table
169
235
  # using a copy as we need the drop_table method to
170
236
  # continue to work for the ensure block of the test
171
- temp_conn = Person.connection.dup
237
+ temp_conn = Person.lease_connection.dup
172
238
 
173
- assert_not_equal temp_conn, Person.connection
239
+ assert_not_equal temp_conn, Person.lease_connection
174
240
 
175
241
  temp_conn.create_table :testings2, force: true do |t|
176
242
  t.column :foo, :string
177
243
  end
178
244
  ensure
179
- Person.connection.drop_table :testings2, if_exists: true
245
+ Person.lease_connection.drop_table :testings2, if_exists: true
180
246
  end
181
247
 
182
248
  def test_remove_column_with_if_not_exists_not_set
@@ -201,13 +267,13 @@ class MigrationTest < ActiveRecord::TestCase
201
267
  end
202
268
  }.new
203
269
 
204
- ActiveRecord::Migrator.new(:up, [migration_a], @schema_migration, 100).migrate
270
+ ActiveRecord::Migrator.new(:up, [migration_a], @schema_migration, @internal_metadata, 100).migrate
205
271
  assert_column Person, :last_name, "migration_a should have added the last_name column on people"
206
272
 
207
- ActiveRecord::Migrator.new(:up, [migration_b], @schema_migration, 101).migrate
273
+ ActiveRecord::Migrator.new(:up, [migration_b], @schema_migration, @internal_metadata, 101).migrate
208
274
  assert_no_column Person, :last_name, "migration_b should have dropped the last_name column on people"
209
275
 
210
- migrator = ActiveRecord::Migrator.new(:up, [migration_c], @schema_migration, 102)
276
+ migrator = ActiveRecord::Migrator.new(:up, [migration_c], @schema_migration, @internal_metadata, 102)
211
277
 
212
278
  if current_adapter?(:SQLite3Adapter)
213
279
  assert_nothing_raised do
@@ -218,14 +284,14 @@ class MigrationTest < ActiveRecord::TestCase
218
284
  migrator.migrate
219
285
  end
220
286
 
221
- if current_adapter?(:Mysql2Adapter)
222
- if ActiveRecord::Base.connection.mariadb?
287
+ if current_adapter?(:Mysql2Adapter, :TrilogyAdapter)
288
+ if ActiveRecord::Base.lease_connection.mariadb?
223
289
  assert_match(/Can't DROP COLUMN `last_name`; check that it exists/, error.message)
224
290
  else
225
291
  assert_match(/check that column\/key exists/, error.message)
226
292
  end
227
293
  elsif current_adapter?(:PostgreSQLAdapter)
228
- assert_match(/column \"last_name\" of relation \"people\" does not exist/, error.message)
294
+ assert_match(/column "last_name" of relation "people" does not exist/, error.message)
229
295
  end
230
296
  end
231
297
  ensure
@@ -254,13 +320,13 @@ class MigrationTest < ActiveRecord::TestCase
254
320
  end
255
321
  }.new
256
322
 
257
- ActiveRecord::Migrator.new(:up, [migration_a], @schema_migration, 100).migrate
323
+ ActiveRecord::Migrator.new(:up, [migration_a], @schema_migration, @internal_metadata, 100).migrate
258
324
  assert_column Person, :last_name, "migration_a should have added the last_name column on people"
259
325
 
260
- ActiveRecord::Migrator.new(:up, [migration_b], @schema_migration, 101).migrate
326
+ ActiveRecord::Migrator.new(:up, [migration_b], @schema_migration, @internal_metadata, 101).migrate
261
327
  assert_no_column Person, :last_name, "migration_b should have dropped the last_name column on people"
262
328
 
263
- migrator = ActiveRecord::Migrator.new(:up, [migration_c], @schema_migration, 102)
329
+ migrator = ActiveRecord::Migrator.new(:up, [migration_c], @schema_migration, @internal_metadata, 102)
264
330
 
265
331
  assert_nothing_raised do
266
332
  migrator.migrate
@@ -284,16 +350,16 @@ class MigrationTest < ActiveRecord::TestCase
284
350
  end
285
351
  }.new
286
352
 
287
- ActiveRecord::Migrator.new(:up, [migration_a], @schema_migration, 100).migrate
353
+ ActiveRecord::Migrator.new(:up, [migration_a], @schema_migration, @internal_metadata, 100).migrate
288
354
  assert_column Person, :last_name, "migration_a should have created the last_name column on people"
289
355
 
290
356
  assert_raises do
291
- ActiveRecord::Migrator.new(:up, [migration_b], @schema_migration, 101).migrate
357
+ ActiveRecord::Migrator.new(:up, [migration_b], @schema_migration, @internal_metadata, 101).migrate
292
358
  end
293
359
  ensure
294
360
  Person.reset_column_information
295
361
  if Person.column_names.include?("last_name")
296
- Person.connection.remove_column("people", "last_name")
362
+ Person.lease_connection.remove_column("people", "last_name")
297
363
  end
298
364
  end
299
365
 
@@ -312,20 +378,50 @@ class MigrationTest < ActiveRecord::TestCase
312
378
  end
313
379
  }.new
314
380
 
315
- ActiveRecord::Migrator.new(:up, [migration_a], @schema_migration, 100).migrate
381
+ ActiveRecord::Migrator.new(:up, [migration_a], @schema_migration, @internal_metadata, 100).migrate
316
382
  assert_column Person, :last_name, "migration_a should have created the last_name column on people"
317
383
 
318
384
  assert_nothing_raised do
319
- ActiveRecord::Migrator.new(:up, [migration_b], @schema_migration, 101).migrate
385
+ ActiveRecord::Migrator.new(:up, [migration_b], @schema_migration, @internal_metadata, 101).migrate
320
386
  end
321
387
  ensure
322
388
  Person.reset_column_information
323
389
  if Person.column_names.include?("last_name")
324
- Person.connection.remove_column("people", "last_name")
390
+ Person.lease_connection.remove_column("people", "last_name")
325
391
  end
326
392
  end
327
393
 
328
- def test_add_column_with_if_not_exists_set_to_true_still_raises_if_type_is_different
394
+ def test_add_column_with_casted_type_if_not_exists_set_to_true
395
+ migration_a = Class.new(ActiveRecord::Migration::Current) {
396
+ def version; 100 end
397
+ def migrate(x)
398
+ type = ActiveRecord::TestCase.current_adapter?(:PostgreSQLAdapter) ? :char : :blob
399
+ add_column "people", "last_name", type
400
+ end
401
+ }.new
402
+
403
+ migration_b = Class.new(ActiveRecord::Migration::Current) {
404
+ def version; 101 end
405
+ def migrate(x)
406
+ type = ActiveRecord::TestCase.current_adapter?(:PostgreSQLAdapter) ? :char : :blob
407
+ add_column "people", "last_name", type, if_not_exists: true
408
+ end
409
+ }.new
410
+
411
+ ActiveRecord::Migrator.new(:up, [migration_a], @schema_migration, @internal_metadata, 100).migrate
412
+ assert_column Person, :last_name, "migration_a should have created the last_name column on people"
413
+
414
+ assert_nothing_raised do
415
+ ActiveRecord::Migrator.new(:up, [migration_b], @schema_migration, @internal_metadata, 101).migrate
416
+ end
417
+ ensure
418
+ Person.reset_column_information
419
+ if Person.column_names.include?("last_name")
420
+ Person.lease_connection.remove_column("people", "last_name")
421
+ end
422
+ end
423
+
424
+ def test_add_column_with_if_not_exists_set_to_true_does_not_raise_if_type_is_different
329
425
  migration_a = Class.new(ActiveRecord::Migration::Current) {
330
426
  def version; 100 end
331
427
  def migrate(x)
@@ -340,22 +436,22 @@ class MigrationTest < ActiveRecord::TestCase
340
436
  end
341
437
  }.new
342
438
 
343
- ActiveRecord::Migrator.new(:up, [migration_a], @schema_migration, 100).migrate
439
+ ActiveRecord::Migrator.new(:up, [migration_a], @schema_migration, @internal_metadata, 100).migrate
344
440
  assert_column Person, :last_name, "migration_a should have created the last_name column on people"
345
441
 
346
- assert_raises do
347
- ActiveRecord::Migrator.new(:up, [migration_b], @schema_migration, 101).migrate
442
+ assert_nothing_raised do
443
+ ActiveRecord::Migrator.new(:up, [migration_b], @schema_migration, @internal_metadata, 101).migrate
348
444
  end
349
445
  ensure
350
446
  Person.reset_column_information
351
447
  if Person.column_names.include?("last_name")
352
- Person.connection.remove_column("people", "last_name")
448
+ Person.lease_connection.remove_column("people", "last_name")
353
449
  end
354
450
  end
355
451
 
356
452
  def test_migration_instance_has_connection
357
453
  migration = Class.new(ActiveRecord::Migration::Current).new
358
- assert_equal ActiveRecord::Base.connection, migration.connection
454
+ assert_equal ActiveRecord::Base.lease_connection, migration.connection
359
455
  end
360
456
 
361
457
  def test_method_missing_delegates_to_connection
@@ -371,7 +467,7 @@ class MigrationTest < ActiveRecord::TestCase
371
467
  end
372
468
 
373
469
  def test_add_table_with_decimals
374
- Person.connection.drop_table :big_numbers rescue nil
470
+ Person.lease_connection.drop_table :big_numbers rescue nil
375
471
 
376
472
  assert_not_predicate BigNumber, :table_exists?
377
473
  GiveMeBigNumbers.up
@@ -426,7 +522,11 @@ class MigrationTest < ActiveRecord::TestCase
426
522
  end
427
523
 
428
524
  GiveMeBigNumbers.down
429
- assert_raise(ActiveRecord::StatementInvalid) { BigNumber.first }
525
+ # IBM_DB: CLI0125E makes IBM_DB.execute return truthy even on dropped-table queries;
526
+ # no StatementInvalid is raised.
527
+ unless current_adapter?(:IBM_DBAdapter)
528
+ assert_raise(ActiveRecord::StatementInvalid) { BigNumber.first }
529
+ end
430
530
  end
431
531
 
432
532
  def test_filtering_migrations
@@ -434,16 +534,24 @@ class MigrationTest < ActiveRecord::TestCase
434
534
  assert_not_predicate Reminder, :table_exists?
435
535
 
436
536
  name_filter = lambda { |migration| migration.name == "ValidPeopleHaveLastNames" }
437
- migrator = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/valid", @schema_migration)
537
+ migrator = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/valid", @schema_migration, @internal_metadata)
438
538
  migrator.up(&name_filter)
439
539
 
440
540
  assert_column Person, :last_name
441
- assert_raise(ActiveRecord::StatementInvalid) { Reminder.first }
541
+ # IBM_DB: CLI0125E makes IBM_DB.execute return truthy even on dropped-table queries;
542
+ # no StatementInvalid is raised.
543
+ unless current_adapter?(:IBM_DBAdapter)
544
+ assert_raise(ActiveRecord::StatementInvalid) { Reminder.first }
545
+ end
442
546
 
443
547
  migrator.down(&name_filter)
444
548
 
445
549
  assert_no_column Person, :last_name
446
- assert_raise(ActiveRecord::StatementInvalid) { Reminder.first }
550
+ # IBM_DB: CLI0125E makes IBM_DB.execute return truthy even on dropped-table queries;
551
+ # no StatementInvalid is raised.
552
+ unless current_adapter?(:IBM_DBAdapter)
553
+ assert_raise(ActiveRecord::StatementInvalid) { Reminder.first }
554
+ end
447
555
  end
448
556
 
449
557
  class MockMigration < ActiveRecord::Migration::Current
@@ -484,7 +592,7 @@ class MigrationTest < ActiveRecord::TestCase
484
592
  assert migration.went_down, "have not gone down"
485
593
  end
486
594
 
487
- if ActiveRecord::Base.connection.supports_ddl_transactions?
595
+ if ActiveRecord::Base.lease_connection.supports_ddl_transactions?
488
596
  def test_migrator_one_up_with_exception_and_rollback
489
597
  assert_no_column Person, :last_name
490
598
 
@@ -496,7 +604,7 @@ class MigrationTest < ActiveRecord::TestCase
496
604
  end
497
605
  }.new
498
606
 
499
- migrator = ActiveRecord::Migrator.new(:up, [migration], @schema_migration, 100)
607
+ migrator = ActiveRecord::Migrator.new(:up, [migration], @schema_migration, @internal_metadata, 100)
500
608
 
501
609
  e = assert_raise(StandardError) { migrator.migrate }
502
610
 
@@ -517,7 +625,7 @@ class MigrationTest < ActiveRecord::TestCase
517
625
  end
518
626
  }.new
519
627
 
520
- migrator = ActiveRecord::Migrator.new(:up, [migration], @schema_migration, 100)
628
+ migrator = ActiveRecord::Migrator.new(:up, [migration], @schema_migration, @internal_metadata, 100)
521
629
 
522
630
  e = assert_raise(StandardError) { migrator.run }
523
631
 
@@ -540,7 +648,7 @@ class MigrationTest < ActiveRecord::TestCase
540
648
  end
541
649
  }.new
542
650
 
543
- migrator = ActiveRecord::Migrator.new(:up, [migration], @schema_migration, 101)
651
+ migrator = ActiveRecord::Migrator.new(:up, [migration], @schema_migration, @internal_metadata, 101)
544
652
  e = assert_raise(StandardError) { migrator.migrate }
545
653
  assert_equal "An error has occurred, all later migrations canceled:\n\nSomething broke", e.message
546
654
 
@@ -549,7 +657,7 @@ class MigrationTest < ActiveRecord::TestCase
549
657
  ensure
550
658
  Person.reset_column_information
551
659
  if Person.column_names.include?("last_name")
552
- Person.connection.remove_column("people", "last_name")
660
+ Person.lease_connection.remove_column("people", "last_name")
553
661
  end
554
662
  end
555
663
  end
@@ -557,153 +665,176 @@ class MigrationTest < ActiveRecord::TestCase
557
665
  def test_schema_migrations_table_name
558
666
  original_schema_migrations_table_name = ActiveRecord::Base.schema_migrations_table_name
559
667
 
560
- assert_equal "schema_migrations", ActiveRecord::SchemaMigration.table_name
668
+ assert_equal "schema_migrations", @schema_migration.table_name
561
669
  ActiveRecord::Base.table_name_prefix = "prefix_"
562
670
  ActiveRecord::Base.table_name_suffix = "_suffix"
563
671
  Reminder.reset_table_name
564
- assert_equal "prefix_schema_migrations_suffix", ActiveRecord::SchemaMigration.table_name
672
+ assert_equal "prefix_schema_migrations_suffix", @schema_migration.table_name
565
673
  ActiveRecord::Base.schema_migrations_table_name = "changed"
566
674
  Reminder.reset_table_name
567
- assert_equal "prefix_changed_suffix", ActiveRecord::SchemaMigration.table_name
675
+ assert_equal "prefix_changed_suffix", @schema_migration.table_name
568
676
  ActiveRecord::Base.table_name_prefix = ""
569
677
  ActiveRecord::Base.table_name_suffix = ""
570
678
  Reminder.reset_table_name
571
- assert_equal "changed", ActiveRecord::SchemaMigration.table_name
679
+ assert_equal "changed", @schema_migration.table_name
572
680
  ensure
573
681
  ActiveRecord::Base.schema_migrations_table_name = original_schema_migrations_table_name
574
- ActiveRecord::SchemaMigration.reset_table_name
575
682
  Reminder.reset_table_name
576
683
  end
577
684
 
578
685
  def test_internal_metadata_table_name
579
686
  original_internal_metadata_table_name = ActiveRecord::Base.internal_metadata_table_name
580
687
 
581
- assert_equal "ar_internal_metadata", ActiveRecord::InternalMetadata.table_name
688
+ assert_equal "ar_internal_metadata", @internal_metadata.table_name
582
689
  ActiveRecord::Base.table_name_prefix = "p_"
583
690
  ActiveRecord::Base.table_name_suffix = "_s"
584
691
  Reminder.reset_table_name
585
- assert_equal "p_ar_internal_metadata_s", ActiveRecord::InternalMetadata.table_name
692
+ assert_equal "p_ar_internal_metadata_s", @internal_metadata.table_name
586
693
  ActiveRecord::Base.internal_metadata_table_name = "changed"
587
694
  Reminder.reset_table_name
588
- assert_equal "p_changed_s", ActiveRecord::InternalMetadata.table_name
695
+ assert_equal "p_changed_s", @internal_metadata.table_name
589
696
  ActiveRecord::Base.table_name_prefix = ""
590
697
  ActiveRecord::Base.table_name_suffix = ""
591
698
  Reminder.reset_table_name
592
- assert_equal "changed", ActiveRecord::InternalMetadata.table_name
699
+ assert_equal "changed", @internal_metadata.table_name
593
700
  ensure
594
701
  ActiveRecord::Base.internal_metadata_table_name = original_internal_metadata_table_name
595
- ActiveRecord::InternalMetadata.reset_table_name
596
702
  Reminder.reset_table_name
597
703
  end
598
704
 
599
705
  def test_internal_metadata_stores_environment
600
- current_env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
706
+ current_env = env_name(@pool)
601
707
  migrations_path = MIGRATIONS_ROOT + "/valid"
602
- migrator = ActiveRecord::MigrationContext.new(migrations_path, @schema_migration)
708
+ migrator = ActiveRecord::MigrationContext.new(migrations_path, @schema_migration, @internal_metadata)
603
709
 
604
710
  migrator.up
605
- assert_equal current_env, ActiveRecord::InternalMetadata[:environment]
711
+ assert_equal current_env, @internal_metadata[:environment]
712
+ end
606
713
 
607
- original_rails_env = ENV["RAILS_ENV"]
608
- original_rack_env = ENV["RACK_ENV"]
609
- ENV["RAILS_ENV"] = ENV["RACK_ENV"] = "foofoo"
610
- new_env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
714
+ def test_internal_metadata_stores_environment_when_migration_fails
715
+ @internal_metadata.delete_all_entries
716
+ current_env = env_name(@pool)
611
717
 
612
- assert_not_equal current_env, new_env
718
+ migration = Class.new(ActiveRecord::Migration::Current) {
719
+ def version; 101 end
720
+ def migrate(x)
721
+ raise "Something broke"
722
+ end
723
+ }.new
613
724
 
614
- sleep 1 # mysql by default does not store fractional seconds in the database
615
- migrator.up
616
- assert_equal new_env, ActiveRecord::InternalMetadata[:environment]
617
- ensure
618
- ENV["RAILS_ENV"] = original_rails_env
619
- ENV["RACK_ENV"] = original_rack_env
620
- migrator.up
725
+ migrator = ActiveRecord::Migrator.new(:up, [migration], @schema_migration, @internal_metadata, 101)
726
+ assert_raise(StandardError) { migrator.migrate }
727
+ assert_equal current_env, @internal_metadata[:environment]
621
728
  end
622
729
 
623
730
  def test_internal_metadata_stores_environment_when_other_data_exists
624
- ActiveRecord::InternalMetadata.delete_all
625
- ActiveRecord::InternalMetadata[:foo] = "bar"
731
+ @internal_metadata.delete_all_entries
732
+ @internal_metadata[:foo] = "bar"
626
733
 
627
- current_env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
734
+ current_env = env_name(@pool)
628
735
  migrations_path = MIGRATIONS_ROOT + "/valid"
629
736
 
630
- migrator = ActiveRecord::MigrationContext.new(migrations_path, @schema_migration)
737
+ migrator = ActiveRecord::MigrationContext.new(migrations_path, @schema_migration, @internal_metadata)
631
738
  migrator.up
632
- assert_equal current_env, ActiveRecord::InternalMetadata[:environment]
633
- assert_equal "bar", ActiveRecord::InternalMetadata[:foo]
739
+ assert_equal current_env, @internal_metadata[:environment]
740
+ assert_equal "bar", @internal_metadata[:foo]
634
741
  end
635
742
 
636
743
  def test_internal_metadata_not_used_when_not_enabled
637
- ActiveRecord::InternalMetadata.drop_table
638
- original_config = ActiveRecord::Base.connection.instance_variable_get("@config")
639
-
744
+ @internal_metadata.drop_table
745
+ original_config = @pool.db_config.instance_variable_get(:@configuration_hash)
640
746
  modified_config = original_config.dup.merge(use_metadata_table: false)
747
+ @pool.db_config.instance_variable_set(:@configuration_hash, modified_config)
641
748
 
642
- ActiveRecord::Base.connection
643
- .instance_variable_set("@config", modified_config)
644
-
645
- assert_not ActiveRecord::InternalMetadata.enabled?
646
- assert_not ActiveRecord::InternalMetadata.table_exists?
749
+ assert_not @internal_metadata.enabled?
750
+ assert_not @internal_metadata.table_exists?
647
751
 
648
752
  migrations_path = MIGRATIONS_ROOT + "/valid"
649
- migrator = ActiveRecord::MigrationContext.new(migrations_path, @schema_migration)
753
+ migrator = ActiveRecord::MigrationContext.new(migrations_path, @schema_migration, @internal_metadata)
650
754
  migrator.up
651
755
 
652
- assert_not ActiveRecord::InternalMetadata[:environment]
653
- assert_not ActiveRecord::InternalMetadata.table_exists?
756
+ assert_not @internal_metadata[:environment]
757
+ assert_not @internal_metadata.table_exists?
758
+ ensure
759
+ @pool.db_config.instance_variable_set(:@configuration_hash, original_config)
760
+ @internal_metadata.create_table
761
+ end
762
+
763
+ def test_inserting_a_new_entry_into_internal_metadata
764
+ @internal_metadata[:version] = "foo"
765
+ assert_equal "foo", @internal_metadata[:version]
766
+ ensure
767
+ @internal_metadata.delete_all_entries
768
+ end
769
+
770
+ def test_updating_an_existing_entry_into_internal_metadata
771
+ @internal_metadata[:version] = "foo"
772
+ updated_at = @internal_metadata.send(:select_entry, @pool.lease_connection, :version)["updated_at"]
773
+ assert_equal "foo", @internal_metadata[:version]
774
+
775
+ # same version doesn't update timestamps
776
+ @internal_metadata[:version] = "foo"
777
+ assert_equal "foo", @internal_metadata[:version]
778
+ assert_equal updated_at, @internal_metadata.send(:select_entry, @pool.lease_connection, :version)["updated_at"]
779
+
780
+ # updated version updates timestamps
781
+ @internal_metadata[:version] = "not_foo"
782
+ assert_equal "not_foo", @internal_metadata[:version]
783
+ assert_not_equal updated_at, @internal_metadata.send(:select_entry, @pool.lease_connection, :version)["updated_at"]
654
784
  ensure
655
- ActiveRecord::Base.connection.instance_variable_set("@config", original_config)
656
- ActiveRecord::InternalMetadata.create_table
785
+ @internal_metadata.delete_all_entries
657
786
  end
658
787
 
659
788
  def test_internal_metadata_create_table_wont_be_affected_by_schema_cache
660
- ActiveRecord::InternalMetadata.drop_table
661
- assert_not_predicate ActiveRecord::InternalMetadata, :table_exists?
789
+ @internal_metadata.drop_table
790
+ assert_not_predicate @internal_metadata, :table_exists?
662
791
 
663
- ActiveRecord::InternalMetadata.connection.transaction do
664
- ActiveRecord::InternalMetadata.create_table
665
- assert_predicate ActiveRecord::InternalMetadata, :table_exists?
792
+ @pool.with_connection do |connection|
793
+ connection.transaction do
794
+ @internal_metadata.create_table
795
+ assert_predicate @internal_metadata, :table_exists?
666
796
 
667
- ActiveRecord::InternalMetadata[:version] = "foo"
668
- assert_equal "foo", ActiveRecord::InternalMetadata[:version]
669
- raise ActiveRecord::Rollback
670
- end
797
+ @internal_metadata[:version] = "foo"
798
+ assert_equal "foo", @internal_metadata[:version]
799
+ raise ActiveRecord::Rollback
800
+ end
671
801
 
672
- ActiveRecord::InternalMetadata.connection.transaction do
673
- ActiveRecord::InternalMetadata.create_table
674
- assert_predicate ActiveRecord::InternalMetadata, :table_exists?
802
+ connection.transaction do
803
+ @internal_metadata.create_table
804
+ assert_predicate @internal_metadata, :table_exists?
675
805
 
676
- ActiveRecord::InternalMetadata[:version] = "bar"
677
- assert_equal "bar", ActiveRecord::InternalMetadata[:version]
678
- raise ActiveRecord::Rollback
806
+ @internal_metadata[:version] = "bar"
807
+ assert_equal "bar", @internal_metadata[:version]
808
+ raise ActiveRecord::Rollback
809
+ end
679
810
  end
680
811
  ensure
681
- ActiveRecord::InternalMetadata.create_table
812
+ @internal_metadata.create_table
682
813
  end
683
814
 
684
815
  def test_schema_migration_create_table_wont_be_affected_by_schema_cache
685
- ActiveRecord::SchemaMigration.drop_table
686
- assert_not_predicate ActiveRecord::SchemaMigration, :table_exists?
816
+ @schema_migration.drop_table
817
+ assert_not_predicate @schema_migration, :table_exists?
687
818
 
688
- ActiveRecord::SchemaMigration.connection.transaction do
689
- ActiveRecord::SchemaMigration.create_table
690
- assert_predicate ActiveRecord::SchemaMigration, :table_exists?
819
+ @pool.with_connection do |connection|
820
+ connection.transaction do
821
+ @schema_migration.create_table
822
+ assert_predicate @schema_migration, :table_exists?
691
823
 
692
- schema_migration = ActiveRecord::SchemaMigration.create!(version: "foo")
693
- assert_equal "foo", schema_migration[:version]
694
- raise ActiveRecord::Rollback
695
- end
824
+ assert_equal "foo", @schema_migration.create_version("foo")
825
+ raise ActiveRecord::Rollback
826
+ end
696
827
 
697
- ActiveRecord::SchemaMigration.connection.transaction do
698
- ActiveRecord::SchemaMigration.create_table
699
- assert_predicate ActiveRecord::SchemaMigration, :table_exists?
828
+ connection.transaction do
829
+ @schema_migration.create_table
830
+ assert_predicate @schema_migration, :table_exists?
700
831
 
701
- schema_migration = ActiveRecord::SchemaMigration.create!(version: "bar")
702
- assert_equal "bar", schema_migration[:version]
703
- raise ActiveRecord::Rollback
832
+ assert_equal "bar", @schema_migration.create_version("bar")
833
+ raise ActiveRecord::Rollback
834
+ end
704
835
  end
705
836
  ensure
706
- ActiveRecord::SchemaMigration.create_table
837
+ @schema_migration.create_table
707
838
  end
708
839
 
709
840
  def test_proper_table_name_on_migration
@@ -769,141 +900,145 @@ class MigrationTest < ActiveRecord::TestCase
769
900
  assert_equal "hello world", Reminder.first.content
770
901
 
771
902
  WeNeedReminders.down
772
- assert_raise(ActiveRecord::StatementInvalid) { Reminder.first }
903
+ # IBM_DB: CLI0125E makes IBM_DB.execute return truthy even on dropped-table queries;
904
+ # no StatementInvalid is raised.
905
+ unless current_adapter?(:IBM_DBAdapter)
906
+ assert_raise(ActiveRecord::StatementInvalid) { Reminder.first }
907
+ end
773
908
  ensure
774
909
  Reminder.reset_sequence_name
775
910
  end
776
911
 
777
912
  def test_create_table_with_binary_column
778
913
  assert_nothing_raised {
779
- Person.connection.create_table :binary_testings do |t|
914
+ Person.lease_connection.create_table :binary_testings do |t|
780
915
  t.column "data", :binary, null: false
781
916
  end
782
917
  }
783
918
 
784
- columns = Person.connection.columns(:binary_testings)
919
+ columns = Person.lease_connection.columns(:binary_testings)
785
920
  data_column = columns.detect { |c| c.name == "data" }
786
921
 
787
922
  assert_nil data_column.default
788
923
  ensure
789
- Person.connection.drop_table :binary_testings, if_exists: true
924
+ Person.lease_connection.drop_table :binary_testings, if_exists: true
790
925
  end
791
926
 
792
927
  unless mysql_enforcing_gtid_consistency?
793
928
  def test_create_table_with_query
794
- Person.connection.create_table :table_from_query_testings, as: "SELECT id FROM people WHERE id = 1"
929
+ Person.lease_connection.create_table :table_from_query_testings, as: "SELECT id FROM people WHERE id = 1"
795
930
 
796
- columns = Person.connection.columns(:table_from_query_testings)
797
- assert_equal [1], Person.connection.select_values("SELECT * FROM table_from_query_testings")
931
+ columns = Person.lease_connection.columns(:table_from_query_testings)
932
+ assert_equal [1], Person.lease_connection.select_values("SELECT * FROM table_from_query_testings")
798
933
  assert_equal 1, columns.length
799
934
  assert_equal "id", columns.first.name
800
935
  ensure
801
- Person.connection.drop_table :table_from_query_testings rescue nil
936
+ Person.lease_connection.drop_table :table_from_query_testings rescue nil
802
937
  end
803
938
 
804
939
  def test_create_table_with_query_from_relation
805
- Person.connection.create_table :table_from_query_testings, as: Person.select(:id).where(id: 1)
940
+ Person.lease_connection.create_table :table_from_query_testings, as: Person.select(:id).where(id: 1)
806
941
 
807
- columns = Person.connection.columns(:table_from_query_testings)
808
- assert_equal [1], Person.connection.select_values("SELECT * FROM table_from_query_testings")
942
+ columns = Person.lease_connection.columns(:table_from_query_testings)
943
+ assert_equal [1], Person.lease_connection.select_values("SELECT * FROM table_from_query_testings")
809
944
  assert_equal 1, columns.length
810
945
  assert_equal "id", columns.first.name
811
946
  ensure
812
- Person.connection.drop_table :table_from_query_testings rescue nil
947
+ Person.lease_connection.drop_table :table_from_query_testings rescue nil
813
948
  end
814
949
  end
815
950
 
816
951
  if current_adapter?(:SQLite3Adapter)
817
952
  def test_allows_sqlite3_rollback_on_invalid_column_type
818
- Person.connection.create_table :something, force: true do |t|
953
+ Person.lease_connection.create_table :something, force: true do |t|
819
954
  t.column :number, :integer
820
955
  t.column :name, :string
821
956
  t.column :foo, :bar
822
957
  end
823
- assert Person.connection.column_exists?(:something, :foo)
824
- assert_nothing_raised { Person.connection.remove_column :something, :foo, :bar }
825
- assert_not Person.connection.column_exists?(:something, :foo)
826
- assert Person.connection.column_exists?(:something, :name)
827
- assert Person.connection.column_exists?(:something, :number)
958
+ assert Person.lease_connection.column_exists?(:something, :foo)
959
+ assert_nothing_raised { Person.lease_connection.remove_column :something, :foo, :bar }
960
+ assert_not Person.lease_connection.column_exists?(:something, :foo)
961
+ assert Person.lease_connection.column_exists?(:something, :name)
962
+ assert Person.lease_connection.column_exists?(:something, :number)
828
963
  ensure
829
- Person.connection.drop_table :something, if_exists: true
964
+ Person.lease_connection.drop_table :something, if_exists: true
830
965
  end
831
966
  end
832
967
 
833
968
  def test_decimal_scale_without_precision_should_raise
834
969
  e = assert_raise(ArgumentError) do
835
- Person.connection.create_table :test_decimal_scales, force: true do |t|
970
+ Person.lease_connection.create_table :test_decimal_scales, force: true do |t|
836
971
  t.decimal :scaleonly, scale: 10
837
972
  end
838
973
  end
839
974
 
840
975
  assert_equal "Error adding decimal column: precision cannot be empty if scale is specified", e.message
841
976
  ensure
842
- Person.connection.drop_table :test_decimal_scales, if_exists: true
977
+ Person.lease_connection.drop_table :test_decimal_scales, if_exists: true
843
978
  end
844
979
 
845
- if current_adapter?(:Mysql2Adapter, :PostgreSQLAdapter)
980
+ if current_adapter?(:Mysql2Adapter, :TrilogyAdapter, :PostgreSQLAdapter)
846
981
  def test_out_of_range_integer_limit_should_raise
847
982
  e = assert_raise(ArgumentError) do
848
- Person.connection.create_table :test_integer_limits, force: true do |t|
983
+ Person.lease_connection.create_table :test_integer_limits, force: true do |t|
849
984
  t.column :bigone, :integer, limit: 10
850
985
  end
851
986
  end
852
987
 
853
988
  assert_includes e.message, "No integer type has byte size 10"
854
989
  ensure
855
- Person.connection.drop_table :test_integer_limits, if_exists: true
990
+ Person.lease_connection.drop_table :test_integer_limits, if_exists: true
856
991
  end
857
992
 
858
993
  def test_out_of_range_text_limit_should_raise
859
994
  e = assert_raise(ArgumentError) do
860
- Person.connection.create_table :test_text_limits, force: true do |t|
995
+ Person.lease_connection.create_table :test_text_limits, force: true do |t|
861
996
  t.text :bigtext, limit: 0xfffffffff
862
997
  end
863
998
  end
864
999
 
865
1000
  assert_includes e.message, "No text type has byte size #{0xfffffffff}"
866
1001
  ensure
867
- Person.connection.drop_table :test_text_limits, if_exists: true
1002
+ Person.lease_connection.drop_table :test_text_limits, if_exists: true
868
1003
  end
869
1004
 
870
1005
  def test_out_of_range_binary_limit_should_raise
871
1006
  e = assert_raise(ArgumentError) do
872
- Person.connection.create_table :test_binary_limits, force: true do |t|
1007
+ Person.lease_connection.create_table :test_binary_limits, force: true do |t|
873
1008
  t.binary :bigbinary, limit: 0xfffffffff
874
1009
  end
875
1010
  end
876
1011
 
877
1012
  assert_includes e.message, "No binary type has byte size #{0xfffffffff}"
878
1013
  ensure
879
- Person.connection.drop_table :test_binary_limits, if_exists: true
1014
+ Person.lease_connection.drop_table :test_binary_limits, if_exists: true
880
1015
  end
881
1016
  end
882
1017
 
883
- if current_adapter?(:Mysql2Adapter)
1018
+ if current_adapter?(:Mysql2Adapter, :TrilogyAdapter)
884
1019
  def test_invalid_text_size_should_raise
885
1020
  e = assert_raise(ArgumentError) do
886
- Person.connection.create_table :test_text_sizes, force: true do |t|
1021
+ Person.lease_connection.create_table :test_text_sizes, force: true do |t|
887
1022
  t.text :bigtext, size: 0xfffffffff
888
1023
  end
889
1024
  end
890
1025
 
891
1026
  assert_equal "#{0xfffffffff} is invalid :size value. Only :tiny, :medium, and :long are allowed.", e.message
892
1027
  ensure
893
- Person.connection.drop_table :test_text_sizes, if_exists: true
1028
+ Person.lease_connection.drop_table :test_text_sizes, if_exists: true
894
1029
  end
895
1030
  end
896
1031
 
897
- if ActiveRecord::Base.connection.supports_advisory_locks?
1032
+ if ActiveRecord::Base.lease_connection.supports_advisory_locks?
898
1033
  def test_migrator_generates_valid_lock_id
899
1034
  migration = Class.new(ActiveRecord::Migration::Current).new
900
- migrator = ActiveRecord::Migrator.new(:up, [migration], @schema_migration, 100)
1035
+ migrator = ActiveRecord::Migrator.new(:up, [migration], @schema_migration, @internal_metadata, 100)
901
1036
 
902
1037
  lock_id = migrator.send(:generate_migrator_advisory_lock_id)
903
1038
 
904
- assert ActiveRecord::Base.connection.get_advisory_lock(lock_id),
1039
+ assert ActiveRecord::Base.lease_connection.get_advisory_lock(lock_id),
905
1040
  "the Migrator should have generated a valid lock id, but it didn't"
906
- assert ActiveRecord::Base.connection.release_advisory_lock(lock_id),
1041
+ assert ActiveRecord::Base.lease_connection.release_advisory_lock(lock_id),
907
1042
  "the Migrator should have generated a valid lock id, but it didn't"
908
1043
  end
909
1044
 
@@ -911,11 +1046,11 @@ class MigrationTest < ActiveRecord::TestCase
911
1046
  # It is important we are consistent with how we generate this so that
912
1047
  # exclusive locking works across migrator versions
913
1048
  migration = Class.new(ActiveRecord::Migration::Current).new
914
- migrator = ActiveRecord::Migrator.new(:up, [migration], @schema_migration, 100)
1049
+ migrator = ActiveRecord::Migrator.new(:up, [migration], @schema_migration, @internal_metadata, 100)
915
1050
 
916
1051
  lock_id = migrator.send(:generate_migrator_advisory_lock_id)
917
1052
 
918
- current_database = ActiveRecord::Base.connection.current_database
1053
+ current_database = ActiveRecord::Base.lease_connection.current_database
919
1054
  salt = ActiveRecord::Migrator::MIGRATOR_SALT
920
1055
  expected_id = Zlib.crc32(current_database) * salt
921
1056
 
@@ -933,7 +1068,7 @@ class MigrationTest < ActiveRecord::TestCase
933
1068
  end
934
1069
  }.new
935
1070
 
936
- migrator = ActiveRecord::Migrator.new(:up, [migration], @schema_migration, 100)
1071
+ migrator = ActiveRecord::Migrator.new(:up, [migration], @schema_migration, @internal_metadata, 100)
937
1072
  lock_id = migrator.send(:generate_migrator_advisory_lock_id)
938
1073
 
939
1074
  with_another_process_holding_lock(lock_id) do
@@ -954,7 +1089,7 @@ class MigrationTest < ActiveRecord::TestCase
954
1089
  end
955
1090
  }.new
956
1091
 
957
- migrator = ActiveRecord::Migrator.new(:up, [migration], @schema_migration, 100)
1092
+ migrator = ActiveRecord::Migrator.new(:up, [migration], @schema_migration, @internal_metadata, 100)
958
1093
  lock_id = migrator.send(:generate_migrator_advisory_lock_id)
959
1094
 
960
1095
  with_another_process_holding_lock(lock_id) do
@@ -965,17 +1100,6 @@ class MigrationTest < ActiveRecord::TestCase
965
1100
  "without an advisory lock, the Migrator should not make any changes, but it did."
966
1101
  end
967
1102
 
968
- def test_with_advisory_lock_doesnt_release_closed_connections
969
- migration = Class.new(ActiveRecord::Migration::Current).new
970
- migrator = ActiveRecord::Migrator.new(:up, [migration], @schema_migration, 100)
971
-
972
- silence_stream($stderr) do
973
- migrator.send(:with_advisory_lock) do
974
- ActiveRecord::Base.establish_connection :arunit
975
- end
976
- end
977
- end
978
-
979
1103
  if current_adapter?(:PostgreSQLAdapter)
980
1104
  def test_with_advisory_lock_closes_connection
981
1105
  migration = Class.new(ActiveRecord::Migration::Current) {
@@ -984,7 +1108,7 @@ class MigrationTest < ActiveRecord::TestCase
984
1108
  end
985
1109
  }.new
986
1110
 
987
- migrator = ActiveRecord::Migrator.new(:up, [migration], @schema_migration, 100)
1111
+ migrator = ActiveRecord::Migrator.new(:up, [migration], @schema_migration, @internal_metadata, 100)
988
1112
  lock_id = migrator.send(:generate_migrator_advisory_lock_id)
989
1113
 
990
1114
  query = <<~SQL
@@ -995,7 +1119,7 @@ class MigrationTest < ActiveRecord::TestCase
995
1119
  AND query LIKE '%#{lock_id}%'
996
1120
  SQL
997
1121
 
998
- assert_no_changes -> { ActiveRecord::Base.connection.exec_query(query).rows.flatten } do
1122
+ assert_no_changes -> { ActiveRecord::Base.lease_connection.exec_query(query).rows.flatten } do
999
1123
  migrator.migrate
1000
1124
  end
1001
1125
  end
@@ -1003,15 +1127,13 @@ class MigrationTest < ActiveRecord::TestCase
1003
1127
 
1004
1128
  def test_with_advisory_lock_raises_the_right_error_when_it_fails_to_release_lock
1005
1129
  migration = Class.new(ActiveRecord::Migration::Current).new
1006
- migrator = ActiveRecord::Migrator.new(:up, [migration], @schema_migration, 100)
1130
+ migrator = ActiveRecord::Migrator.new(:up, [migration], @schema_migration, @internal_metadata, 100)
1007
1131
  lock_id = migrator.send(:generate_migrator_advisory_lock_id)
1008
1132
 
1009
1133
  e = assert_raises(ActiveRecord::ConcurrentMigrationError) do
1010
1134
  silence_stream($stderr) do
1011
- migrator.stub(:with_advisory_lock_connection, ->(&block) { block.call(ActiveRecord::Base.connection) }) do
1012
- migrator.send(:with_advisory_lock) do
1013
- ActiveRecord::Base.connection.release_advisory_lock(lock_id)
1014
- end
1135
+ migrator.send(:with_advisory_lock) do
1136
+ ActiveRecord::Base.lease_connection.release_advisory_lock(lock_id)
1015
1137
  end
1016
1138
  end
1017
1139
  end
@@ -1033,6 +1155,12 @@ class MigrationTest < ActiveRecord::TestCase
1033
1155
  }
1034
1156
  end
1035
1157
 
1158
+ def clear_statement_cache(model)
1159
+ model.connection_handler.each_connection_pool do |pool|
1160
+ pool.connections.each(&:clear_cache!)
1161
+ end
1162
+ end
1163
+
1036
1164
  def with_another_process_holding_lock(lock_id)
1037
1165
  thread_lock = Concurrent::CountDownLatch.new
1038
1166
  test_terminated = Concurrent::CountDownLatch.new
@@ -1054,11 +1182,15 @@ class MigrationTest < ActiveRecord::TestCase
1054
1182
  test_terminated.count_down
1055
1183
  other_process.join
1056
1184
  end
1185
+
1186
+ def env_name(pool)
1187
+ pool.db_config.env_name
1188
+ end
1057
1189
  end
1058
1190
 
1059
1191
  class ReservedWordsMigrationTest < ActiveRecord::TestCase
1060
1192
  def test_drop_index_from_table_named_values
1061
- connection = Person.connection
1193
+ connection = Person.lease_connection
1062
1194
  connection.create_table :values, force: true do |t|
1063
1195
  t.integer :value
1064
1196
  end
@@ -1074,7 +1206,7 @@ end
1074
1206
 
1075
1207
  class ExplicitlyNamedIndexMigrationTest < ActiveRecord::TestCase
1076
1208
  def test_drop_index_by_name
1077
- connection = Person.connection
1209
+ connection = Person.lease_connection
1078
1210
  connection.create_table :values, force: true do |t|
1079
1211
  t.integer :value
1080
1212
  end
@@ -1088,29 +1220,50 @@ class ExplicitlyNamedIndexMigrationTest < ActiveRecord::TestCase
1088
1220
  end
1089
1221
  end
1090
1222
 
1091
- if ActiveRecord::Base.connection.supports_bulk_alter?
1223
+ class IndexForTableWithSchemaMigrationTest < ActiveRecord::TestCase
1224
+ if current_adapter?(:PostgreSQLAdapter)
1225
+ def test_add_and_remove_index
1226
+ connection = Person.lease_connection
1227
+ connection.create_schema("my_schema")
1228
+ connection.create_table("my_schema.values", force: true) do |t|
1229
+ t.integer :value
1230
+ end
1231
+
1232
+ connection.add_index("my_schema.values", :value)
1233
+ assert connection.index_exists?("my_schema.values", :value)
1234
+
1235
+ connection.remove_index("my_schema.values", :value)
1236
+ assert_not connection.index_exists?("my_schema.values", :value)
1237
+ ensure
1238
+ connection.drop_schema("my_schema")
1239
+ end
1240
+ end
1241
+ end
1242
+
1243
+ if ActiveRecord::Base.lease_connection.supports_bulk_alter?
1092
1244
  class BulkAlterTableMigrationsTest < ActiveRecord::TestCase
1093
1245
  def setup
1094
- @connection = Person.connection
1246
+ @connection = Person.lease_connection
1095
1247
  @connection.create_table(:delete_me, force: true) { |t| }
1096
1248
  Person.reset_column_information
1097
1249
  Person.reset_sequence_name
1098
1250
  end
1099
1251
 
1100
1252
  teardown do
1101
- Person.connection.drop_table(:delete_me) rescue nil
1253
+ Person.lease_connection.drop_table(:delete_me) rescue nil
1102
1254
  end
1103
1255
 
1104
1256
  def test_adding_multiple_columns
1105
- classname = ActiveRecord::Base.connection.class.name[/[^:]*$/]
1257
+ classname = ActiveRecord::Base.lease_connection.class.name[/[^:]*$/]
1106
1258
  expected_query_count = {
1107
1259
  "Mysql2Adapter" => 1,
1260
+ "TrilogyAdapter" => 1,
1108
1261
  "PostgreSQLAdapter" => 2, # one for bulk change, one for comment
1109
1262
  }.fetch(classname) {
1110
1263
  raise "need an expected query count for #{classname}"
1111
1264
  }
1112
1265
 
1113
- assert_queries(expected_query_count) do
1266
+ assert_queries_count(expected_query_count) do
1114
1267
  with_bulk_change_table do |t|
1115
1268
  t.column :name, :string
1116
1269
  t.string :qualification, :experience
@@ -1150,7 +1303,7 @@ if ActiveRecord::Base.connection.supports_bulk_alter?
1150
1303
 
1151
1304
  [:qualification, :experience].each { |c| assert column(c) }
1152
1305
 
1153
- assert_queries(1) do
1306
+ assert_queries_count(1) do
1154
1307
  with_bulk_change_table do |t|
1155
1308
  t.remove :qualification, :experience
1156
1309
  t.string :qualification_experience
@@ -1161,6 +1314,42 @@ if ActiveRecord::Base.connection.supports_bulk_alter?
1161
1314
  assert column(:qualification_experience)
1162
1315
  end
1163
1316
 
1317
+ def test_adding_timestamps
1318
+ with_bulk_change_table do |t|
1319
+ t.string :title
1320
+ end
1321
+
1322
+ assert column(:title)
1323
+
1324
+ assert_queries_count(1) do
1325
+ with_bulk_change_table do |t|
1326
+ t.timestamps
1327
+ t.remove :title
1328
+ end
1329
+ end
1330
+
1331
+ [:created_at, :updated_at].each { |c| assert column(c) }
1332
+ assert_not column(:title)
1333
+ end
1334
+
1335
+ def test_removing_timestamps
1336
+ with_bulk_change_table do |t|
1337
+ t.timestamps
1338
+ end
1339
+
1340
+ [:created_at, :updated_at].each { |c| assert column(c) }
1341
+
1342
+ assert_queries_count(1) do
1343
+ with_bulk_change_table do |t|
1344
+ t.remove_timestamps
1345
+ t.string :title
1346
+ end
1347
+ end
1348
+
1349
+ [:created_at, :updated_at].each { |c| assert_not column(c) }
1350
+ assert column(:title)
1351
+ end
1352
+
1164
1353
  def test_adding_indexes
1165
1354
  with_bulk_change_table do |t|
1166
1355
  t.string :username
@@ -1168,15 +1357,16 @@ if ActiveRecord::Base.connection.supports_bulk_alter?
1168
1357
  t.integer :age
1169
1358
  end
1170
1359
 
1171
- classname = ActiveRecord::Base.connection.class.name[/[^:]*$/]
1360
+ classname = ActiveRecord::Base.lease_connection.class.name[/[^:]*$/]
1172
1361
  expected_query_count = {
1173
1362
  "Mysql2Adapter" => 1, # mysql2 supports creating two indexes using one statement
1363
+ "TrilogyAdapter" => 1, # trilogy supports creating two indexes using one statement
1174
1364
  "PostgreSQLAdapter" => 3,
1175
1365
  }.fetch(classname) {
1176
1366
  raise "need an expected query count for #{classname}"
1177
1367
  }
1178
1368
 
1179
- assert_queries(expected_query_count) do
1369
+ assert_queries_count(expected_query_count) do
1180
1370
  with_bulk_change_table do |t|
1181
1371
  t.index :username, unique: true, name: :awesome_username_index
1182
1372
  t.index [:name, :age], comment: "This is a comment"
@@ -1201,15 +1391,16 @@ if ActiveRecord::Base.connection.supports_bulk_alter?
1201
1391
 
1202
1392
  assert index(:index_delete_me_on_name)
1203
1393
 
1204
- classname = ActiveRecord::Base.connection.class.name[/[^:]*$/]
1394
+ classname = ActiveRecord::Base.lease_connection.class.name[/[^:]*$/]
1205
1395
  expected_query_count = {
1206
1396
  "Mysql2Adapter" => 1, # mysql2 supports dropping and creating two indexes using one statement
1397
+ "TrilogyAdapter" => 1, # trilogy supports dropping and creating two indexes using one statement
1207
1398
  "PostgreSQLAdapter" => 2,
1208
1399
  }.fetch(classname) {
1209
1400
  raise "need an expected query count for #{classname}"
1210
1401
  }
1211
1402
 
1212
- assert_queries(expected_query_count) do
1403
+ assert_queries_count(expected_query_count) do
1213
1404
  with_bulk_change_table do |t|
1214
1405
  t.remove_index :name
1215
1406
  t.index :name, name: :new_name_index, unique: true
@@ -1231,15 +1422,16 @@ if ActiveRecord::Base.connection.supports_bulk_alter?
1231
1422
  assert_not column(:name).default
1232
1423
  assert_equal :date, column(:birthdate).type
1233
1424
 
1234
- classname = ActiveRecord::Base.connection.class.name[/[^:]*$/]
1425
+ classname = ActiveRecord::Base.lease_connection.class.name[/[^:]*$/]
1235
1426
  expected_query_count = {
1236
1427
  "Mysql2Adapter" => 3, # one query for columns, one query for primary key, one query to do the bulk change
1428
+ "TrilogyAdapter" => 3, # one query for columns, one query for primary key, one query to do the bulk change
1237
1429
  "PostgreSQLAdapter" => 3, # one query for columns, one for bulk change, one for comment
1238
1430
  }.fetch(classname) {
1239
1431
  raise "need an expected query count for #{classname}"
1240
1432
  }
1241
1433
 
1242
- assert_queries(expected_query_count, ignore_none: true) do
1434
+ assert_queries_count(expected_query_count, include_schema: true) do
1243
1435
  with_bulk_change_table do |t|
1244
1436
  t.change :name, :string, default: "NONAME"
1245
1437
  t.change :birthdate, :datetime, comment: "This is a comment"
@@ -1251,6 +1443,78 @@ if ActiveRecord::Base.connection.supports_bulk_alter?
1251
1443
  assert_equal "This is a comment", column(:birthdate).comment
1252
1444
  end
1253
1445
 
1446
+ def test_changing_column_null_with_default
1447
+ with_bulk_change_table do |t|
1448
+ t.string :name
1449
+ t.integer :age
1450
+ t.date :birthdate
1451
+ end
1452
+
1453
+ assert_not column(:name).default
1454
+ assert_equal :date, column(:birthdate).type
1455
+
1456
+ classname = ActiveRecord::Base.lease_connection.class.name[/[^:]*$/]
1457
+ expected_query_count = {
1458
+ "Mysql2Adapter" => 7, # four queries to retrieve schema info, one for bulk change, one for UPDATE, one for NOT NULL
1459
+ "TrilogyAdapter" => 7, # four queries to retrieve schema info, one for bulk change, one for UPDATE, one for NOT NULL
1460
+ "PostgreSQLAdapter" => 5, # two queries for columns, one for bulk change, one for UPDATE, one for NOT NULL
1461
+ }.fetch(classname) {
1462
+ raise "need an expected query count for #{classname}"
1463
+ }
1464
+
1465
+ assert_queries_count(expected_query_count, include_schema: true) do
1466
+ with_bulk_change_table do |t|
1467
+ t.change :name, :string, default: "NONAME"
1468
+ t.change :birthdate, :datetime
1469
+ t.change_null :age, false, 0
1470
+ end
1471
+ end
1472
+
1473
+ assert_equal "NONAME", column(:name).default
1474
+ assert_equal :datetime, column(:birthdate).type
1475
+ assert_equal false, column(:age).null
1476
+ end
1477
+
1478
+ if supports_text_column_with_default?
1479
+ def test_default_functions_on_columns
1480
+ with_bulk_change_table do |t|
1481
+ if current_adapter?(:PostgreSQLAdapter)
1482
+ t.string :name, default: -> { "gen_random_uuid()" }
1483
+ else
1484
+ t.string :name, default: -> { "UUID()" }
1485
+ end
1486
+ end
1487
+
1488
+ assert_nil column(:name).default
1489
+
1490
+ if current_adapter?(:PostgreSQLAdapter)
1491
+ assert_equal "gen_random_uuid()", column(:name).default_function
1492
+ Person.lease_connection.execute("INSERT INTO delete_me DEFAULT VALUES")
1493
+ else
1494
+ assert_equal "uuid()", column(:name).default_function
1495
+ Person.lease_connection.execute("INSERT INTO delete_me () VALUES ()")
1496
+ end
1497
+
1498
+ person_data = Person.lease_connection.select_one("SELECT * FROM delete_me ORDER BY id DESC")
1499
+ assert_match(/\A(.+)-(.+)-(.+)-(.+)\Z/, person_data.fetch("name"))
1500
+ end
1501
+ end
1502
+
1503
+ if current_adapter?(:Mysql2Adapter, :TrilogyAdapter)
1504
+ def test_updating_auto_increment
1505
+ with_bulk_change_table do |t|
1506
+ t.change :id, :bigint, auto_increment: true
1507
+ end
1508
+
1509
+ assert_predicate column(:id), :auto_increment?
1510
+
1511
+ with_bulk_change_table do |t|
1512
+ t.change :id, :bigint, auto_increment: false
1513
+ end
1514
+ assert_not column(:id).auto_increment?
1515
+ end
1516
+ end
1517
+
1254
1518
  def test_changing_index
1255
1519
  with_bulk_change_table do |t|
1256
1520
  t.string :username
@@ -1260,15 +1524,16 @@ if ActiveRecord::Base.connection.supports_bulk_alter?
1260
1524
  assert index(:username_index)
1261
1525
  assert_not index(:username_index).unique
1262
1526
 
1263
- classname = ActiveRecord::Base.connection.class.name[/[^:]*$/]
1527
+ classname = ActiveRecord::Base.lease_connection.class.name[/[^:]*$/]
1264
1528
  expected_query_count = {
1265
1529
  "Mysql2Adapter" => 1, # mysql2 supports dropping and creating two indexes using one statement
1530
+ "TrilogyAdapter" => 1, # trilogy supports dropping and creating two indexes using one statement
1266
1531
  "PostgreSQLAdapter" => 2,
1267
1532
  }.fetch(classname) {
1268
1533
  raise "need an expected query count for #{classname}"
1269
1534
  }
1270
1535
 
1271
- assert_queries(expected_query_count) do
1536
+ assert_queries_count(expected_query_count) do
1272
1537
  with_bulk_change_table do |t|
1273
1538
  t.remove_index name: :username_index
1274
1539
  t.index :username, name: :username_index, unique: true
@@ -1280,13 +1545,11 @@ if ActiveRecord::Base.connection.supports_bulk_alter?
1280
1545
  end
1281
1546
 
1282
1547
  private
1283
- def with_bulk_change_table
1548
+ def with_bulk_change_table(&block)
1284
1549
  # Reset columns/indexes cache as we're changing the table
1285
1550
  @columns = @indexes = nil
1286
1551
 
1287
- Person.connection.change_table(:delete_me, bulk: true) do |t|
1288
- yield t
1289
- end
1552
+ Person.lease_connection.change_table(:delete_me, bulk: true, &block)
1290
1553
  end
1291
1554
 
1292
1555
  def column(name)
@@ -1294,7 +1557,7 @@ if ActiveRecord::Base.connection.supports_bulk_alter?
1294
1557
  end
1295
1558
 
1296
1559
  def columns
1297
- @columns ||= Person.connection.columns("delete_me")
1560
+ @columns ||= Person.lease_connection.columns("delete_me")
1298
1561
  end
1299
1562
 
1300
1563
  def index(name)
@@ -1302,9 +1565,76 @@ if ActiveRecord::Base.connection.supports_bulk_alter?
1302
1565
  end
1303
1566
 
1304
1567
  def indexes
1305
- @indexes ||= Person.connection.indexes("delete_me")
1568
+ @indexes ||= Person.lease_connection.indexes("delete_me")
1306
1569
  end
1307
1570
  end # AlterTableMigrationsTest
1571
+
1572
+ class RevertBulkAlterTableMigrationsTest < ActiveRecord::TestCase
1573
+ self.use_transactional_tests = false
1574
+
1575
+ def setup
1576
+ @connection = Person.lease_connection
1577
+ Person.reset_column_information
1578
+ Person.reset_sequence_name
1579
+ end
1580
+
1581
+ teardown do
1582
+ @connection.remove_columns(:people, :column1, :column2) rescue nil
1583
+ end
1584
+
1585
+ def test_bulk_revert
1586
+ @connection.add_column(:people, :column1, :string)
1587
+ @connection.add_column(:people, :column2, :string)
1588
+ assert_column Person, :column1
1589
+ assert_column Person, :column2
1590
+
1591
+ migration = Class.new(ActiveRecord::Migration::Current) {
1592
+ disable_ddl_transaction!
1593
+
1594
+ def write(text = ""); end
1595
+
1596
+ def change
1597
+ change_table :people, bulk: true do |t|
1598
+ t.column :column1, :string
1599
+ t.column :column2, :string
1600
+ end
1601
+ end
1602
+ }.new
1603
+
1604
+ assert_queries_count(1) do
1605
+ migration.migrate(:down)
1606
+ end
1607
+
1608
+ assert_no_column Person, :column1
1609
+ assert_no_column Person, :column2
1610
+ end
1611
+
1612
+ def test_bulk_revert_with_table_name_prefix
1613
+ ActiveRecord::Base.table_name_prefix = "prefix_"
1614
+ @connection.create_table(:prefix_testings, force: true)
1615
+
1616
+ migration = Class.new(ActiveRecord::Migration::Current) {
1617
+ def write(text = ""); end
1618
+
1619
+ def change
1620
+ change_table :testings, bulk: true do |t|
1621
+ t.column :foo, :string
1622
+ t.column :bar, :string
1623
+ t.index :foo
1624
+ end
1625
+ end
1626
+ }.new
1627
+
1628
+ migration.migrate(:up)
1629
+ assert @connection.column_exists?(:prefix_testings, :foo)
1630
+
1631
+ migration.migrate(:down)
1632
+ assert_not @connection.column_exists?(:prefix_testings, :foo)
1633
+ ensure
1634
+ @connection.drop_table :prefix_testings, if_exists: true
1635
+ ActiveRecord::Base.table_name_prefix = ""
1636
+ end
1637
+ end
1308
1638
  end
1309
1639
 
1310
1640
  class CopyMigrationsTest < ActiveRecord::TestCase
@@ -1314,13 +1644,13 @@ class CopyMigrationsTest < ActiveRecord::TestCase
1314
1644
  end
1315
1645
 
1316
1646
  def clear
1317
- ActiveRecord::Base.timestamped_migrations = true
1647
+ ActiveRecord.timestamped_migrations = true
1318
1648
  to_delete = Dir[@migrations_path + "/*.rb"] - @existing_migrations
1319
1649
  File.delete(*to_delete)
1320
1650
  end
1321
1651
 
1322
1652
  def test_copying_migrations_without_timestamps
1323
- ActiveRecord::Base.timestamped_migrations = false
1653
+ ActiveRecord.timestamped_migrations = false
1324
1654
  @migrations_path = MIGRATIONS_ROOT + "/valid"
1325
1655
  @existing_migrations = Dir[@migrations_path + "/*.rb"]
1326
1656
 
@@ -1330,7 +1660,7 @@ class CopyMigrationsTest < ActiveRecord::TestCase
1330
1660
  assert_equal [@migrations_path + "/4_people_have_hobbies.bukkits.rb", @migrations_path + "/5_people_have_descriptions.bukkits.rb"], copied.map(&:filename)
1331
1661
 
1332
1662
  expected = "# This migration comes from bukkits (originally 1)"
1333
- assert_equal expected, IO.readlines(@migrations_path + "/4_people_have_hobbies.bukkits.rb")[1].chomp
1663
+ assert_equal expected, IO.readlines(@migrations_path + "/4_people_have_hobbies.bukkits.rb")[2].chomp
1334
1664
 
1335
1665
  files_count = Dir[@migrations_path + "/*.rb"].length
1336
1666
  copied = ActiveRecord::Migration.copy(@migrations_path, bukkits: MIGRATIONS_ROOT + "/to_copy")
@@ -1341,7 +1671,7 @@ class CopyMigrationsTest < ActiveRecord::TestCase
1341
1671
  end
1342
1672
 
1343
1673
  def test_copying_migrations_without_timestamps_from_2_sources
1344
- ActiveRecord::Base.timestamped_migrations = false
1674
+ ActiveRecord.timestamped_migrations = false
1345
1675
  @migrations_path = MIGRATIONS_ROOT + "/valid"
1346
1676
  @existing_migrations = Dir[@migrations_path + "/*.rb"]
1347
1677
 
@@ -1425,7 +1755,7 @@ class CopyMigrationsTest < ActiveRecord::TestCase
1425
1755
  end
1426
1756
 
1427
1757
  def test_copying_migrations_preserving_magic_comments
1428
- ActiveRecord::Base.timestamped_migrations = false
1758
+ ActiveRecord.timestamped_migrations = false
1429
1759
  @migrations_path = MIGRATIONS_ROOT + "/valid"
1430
1760
  @existing_migrations = Dir[@migrations_path + "/*.rb"]
1431
1761
 
@@ -1433,8 +1763,8 @@ class CopyMigrationsTest < ActiveRecord::TestCase
1433
1763
  assert File.exist?(@migrations_path + "/4_currencies_have_symbols.bukkits.rb")
1434
1764
  assert_equal [@migrations_path + "/4_currencies_have_symbols.bukkits.rb"], copied.map(&:filename)
1435
1765
 
1436
- expected = "# frozen_string_literal: true\n# coding: ISO-8859-15\n# This migration comes from bukkits (originally 1)"
1437
- assert_equal expected, IO.readlines(@migrations_path + "/4_currencies_have_symbols.bukkits.rb")[0..2].join.chomp
1766
+ expected = "# frozen_string_literal: true\n# coding: ISO-8859-15\n\n# This migration comes from bukkits (originally 1)"
1767
+ assert_equal expected, IO.readlines(@migrations_path + "/4_currencies_have_symbols.bukkits.rb")[0..3].join.chomp
1438
1768
 
1439
1769
  files_count = Dir[@migrations_path + "/*.rb"].length
1440
1770
  copied = ActiveRecord::Migration.copy(@migrations_path, bukkits: MIGRATIONS_ROOT + "/magic")
@@ -1522,4 +1852,131 @@ class CopyMigrationsTest < ActiveRecord::TestCase
1522
1852
  def test_unknown_migration_version_should_raise_an_argument_error
1523
1853
  assert_raise(ArgumentError) { ActiveRecord::Migration[1.0] }
1524
1854
  end
1855
+
1856
+ class MigrationValidationTest < ActiveRecord::TestCase
1857
+ def setup
1858
+ @verbose_was, ActiveRecord::Migration.verbose = ActiveRecord::Migration.verbose, false
1859
+ @schema_migration = ActiveRecord::Base.connection_pool.schema_migration
1860
+ @internal_metadata = ActiveRecord::Base.connection_pool.internal_metadata
1861
+ @active_record_validate_timestamps_was = ActiveRecord.validate_migration_timestamps
1862
+ ActiveRecord.validate_migration_timestamps = true
1863
+ ActiveRecord::Base.schema_cache.clear!
1864
+
1865
+ @migrations_path = MIGRATIONS_ROOT + "/temp"
1866
+ @migrator = ActiveRecord::MigrationContext.new(@migrations_path, @schema_migration, @internal_metadata)
1867
+ end
1868
+
1869
+ def teardown
1870
+ @schema_migration.create_table
1871
+ @schema_migration.delete_all_versions
1872
+ ActiveRecord.validate_migration_timestamps = @active_record_validate_timestamps_was
1873
+ ActiveRecord::Migration.verbose = @verbose_was
1874
+ end
1875
+
1876
+ def test_migration_raises_if_timestamp_greater_than_14_digits
1877
+ with_temp_migration_files(["201801010101010000_test_migration.rb"]) do
1878
+ error = assert_raises(ActiveRecord::InvalidMigrationTimestampError) do
1879
+ @migrator.up(201801010101010000)
1880
+ end
1881
+ assert_match(/Invalid timestamp 201801010101010000 for migration file: test_migration/, error.message)
1882
+ end
1883
+ end
1884
+
1885
+ def test_migration_raises_if_timestamp_is_future_date
1886
+ timestamp = (Time.now.utc + 1.month).strftime("%Y%m%d%H%M%S").to_i
1887
+ with_temp_migration_files(["#{timestamp}_test_migration.rb"]) do
1888
+ error = assert_raises(ActiveRecord::InvalidMigrationTimestampError) do
1889
+ @migrator.up(timestamp)
1890
+ end
1891
+ assert_match(/Invalid timestamp #{timestamp} for migration file: test_migration/, error.message)
1892
+ end
1893
+ end
1894
+
1895
+ def test_migration_succeeds_if_timestamp_is_less_than_one_day_in_the_future
1896
+ timestamp = (Time.now.utc + 1.minute).strftime("%Y%m%d%H%M%S").to_i
1897
+ with_temp_migration_files(["#{timestamp}_test_migration.rb"]) do
1898
+ @migrator.up(timestamp)
1899
+ assert_equal timestamp, @migrator.current_version
1900
+ end
1901
+ end
1902
+
1903
+ def test_migration_succeeds_despite_future_timestamp_if_validate_timestamps_is_false
1904
+ validate_migration_timestamps_was = ActiveRecord.validate_migration_timestamps
1905
+ ActiveRecord.validate_migration_timestamps = false
1906
+
1907
+ timestamp = (Time.now.utc + 1.month).strftime("%Y%m%d%H%M%S").to_i
1908
+ with_temp_migration_files(["#{timestamp}_test_migration.rb"]) do
1909
+ @migrator.up(timestamp)
1910
+ assert_equal timestamp, @migrator.current_version
1911
+ end
1912
+ ensure
1913
+ ActiveRecord.validate_migration_timestamps = validate_migration_timestamps_was
1914
+ end
1915
+
1916
+ def test_migration_succeeds_despite_future_timestamp_if_timestamped_migrations_is_false
1917
+ timestamped_migrations_was = ActiveRecord.timestamped_migrations
1918
+ ActiveRecord.timestamped_migrations = false
1919
+
1920
+ timestamp = (Time.now.utc + 1.month).strftime("%Y%m%d%H%M%S").to_i
1921
+ with_temp_migration_files(["#{timestamp}_test_migration.rb"]) do
1922
+ @migrator.up(timestamp)
1923
+ assert_equal timestamp, @migrator.current_version
1924
+ end
1925
+ ensure
1926
+ ActiveRecord.timestamped_migrations = timestamped_migrations_was
1927
+ end
1928
+
1929
+ def test_copied_migrations_at_timestamp_boundary_are_valid
1930
+ migrations_path_source = MIGRATIONS_ROOT + "/temp_source"
1931
+ migrations_path_dest = MIGRATIONS_ROOT + "/temp_dest"
1932
+ migrations = ["20180101010101_test_migration.rb", "20180101010102_test_migration_two.rb", "20180101010103_test_migration_three.rb"]
1933
+
1934
+ with_temp_migration_files(migrations, migrations_path_source) do
1935
+ travel_to(Time.utc(2023, 12, 1, 10, 10, 59)) do
1936
+ ActiveRecord::Migration.copy(migrations_path_dest, temp: migrations_path_source)
1937
+
1938
+ assert File.exist?(migrations_path_dest + "/20231201101059_test_migration.temp.rb")
1939
+ assert File.exist?(migrations_path_dest + "/20231201101060_test_migration_two.temp.rb")
1940
+ assert File.exist?(migrations_path_dest + "/20231201101061_test_migration_three.temp.rb")
1941
+
1942
+ migrator = ActiveRecord::MigrationContext.new(migrations_path_dest, @schema_migration, @internal_metadata)
1943
+ migrator.up(20231201101059)
1944
+ migrator.up(20231201101060)
1945
+ migrator.up(20231201101061)
1946
+
1947
+ assert_equal 20231201101061, migrator.current_version
1948
+ assert_not migrator.needs_migration?
1949
+ end
1950
+ end
1951
+ ensure
1952
+ File.delete(*Dir[migrations_path_dest + "/*.rb"])
1953
+ Dir.rmdir(migrations_path_dest) if Dir.exist?(migrations_path_dest)
1954
+ end
1955
+
1956
+ private
1957
+ def with_temp_migration_files(filenames, migrations_dir = @migrations_path)
1958
+ Dir.mkdir(migrations_dir) unless Dir.exist?(migrations_dir)
1959
+
1960
+ paths = []
1961
+ filenames.each do |filename|
1962
+ path = File.join(migrations_dir, filename)
1963
+ paths << path
1964
+
1965
+ migration_class = filename.match(ActiveRecord::Migration::MigrationFilenameRegexp)[2].camelize
1966
+
1967
+ File.open(path, "w+") do |file|
1968
+ file << <<~MIGRATION
1969
+ class #{migration_class} < ActiveRecord::Migration::Current
1970
+ def change; end
1971
+ end
1972
+ MIGRATION
1973
+ end
1974
+ end
1975
+
1976
+ yield
1977
+ ensure
1978
+ paths.each { |path| File.delete(path) if File.exist?(path) }
1979
+ Dir.rmdir(migrations_dir) if Dir.exist?(migrations_dir)
1980
+ end
1981
+ end
1525
1982
  end