ibm_db 4.0.0-x86-mingw32 → 5.1.0-x86-mingw32

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 (576) hide show
  1. checksums.yaml +5 -5
  2. data/MANIFEST +14 -14
  3. data/README +208 -208
  4. data/ext/Makefile +269 -0
  5. data/ext/Makefile.nt32 +181 -181
  6. data/ext/Makefile.nt32.191 +212 -212
  7. data/ext/extconf.rb +322 -291
  8. data/ext/gil_release_version.h +3 -0
  9. data/ext/ibm_db-i386-mingw32.def +2 -0
  10. data/ext/ibm_db.c +11879 -11887
  11. data/ext/ibm_db.o +0 -0
  12. data/ext/ibm_db.so +0 -0
  13. data/ext/mkmf.log +110 -0
  14. data/ext/ruby_ibm_db.h +241 -241
  15. data/ext/ruby_ibm_db_cli.c +866 -866
  16. data/ext/ruby_ibm_db_cli.h +500 -500
  17. data/ext/ruby_ibm_db_cli.o +0 -0
  18. data/ext/unicode_support_version.h +3 -0
  19. data/init.rb +41 -41
  20. data/lib/IBM_DB.rb +27 -27
  21. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +3593 -3452
  22. data/lib/active_record/connection_adapters/ibmdb_adapter.rb +5 -5
  23. data/lib/active_record/vendor/db2-i5-zOS.yaml +328 -328
  24. data/lib/mswin32/ibm_db.rb +94 -90
  25. data/lib/mswin32/rb2x/i386/ruby26/ibm_db.so +0 -0
  26. data/lib/mswin32/rb2x/i386/ruby27/ibm_db.so +0 -0
  27. data/test/active_record/connection_adapters/fake_adapter.rb +49 -49
  28. data/test/assets/example.log +1 -1
  29. data/test/assets/test.txt +1 -1
  30. data/test/cases/adapter_test.rb +351 -351
  31. data/test/cases/adapters/mysql2/active_schema_test.rb +193 -193
  32. data/test/cases/adapters/mysql2/bind_parameter_test.rb +50 -50
  33. data/test/cases/adapters/mysql2/boolean_test.rb +100 -100
  34. data/test/cases/adapters/mysql2/case_sensitivity_test.rb +63 -63
  35. data/test/cases/adapters/mysql2/charset_collation_test.rb +54 -54
  36. data/test/cases/adapters/mysql2/connection_test.rb +210 -210
  37. data/test/cases/adapters/mysql2/datetime_precision_quoting_test.rb +45 -45
  38. data/test/cases/adapters/mysql2/enum_test.rb +26 -26
  39. data/test/cases/adapters/mysql2/explain_test.rb +21 -21
  40. data/test/cases/adapters/mysql2/json_test.rb +195 -195
  41. data/test/cases/adapters/mysql2/mysql2_adapter_test.rb +83 -83
  42. data/test/cases/adapters/mysql2/reserved_word_test.rb +152 -152
  43. data/test/cases/adapters/mysql2/schema_migrations_test.rb +59 -59
  44. data/test/cases/adapters/mysql2/schema_test.rb +126 -126
  45. data/test/cases/adapters/mysql2/sp_test.rb +36 -36
  46. data/test/cases/adapters/mysql2/sql_types_test.rb +14 -14
  47. data/test/cases/adapters/mysql2/table_options_test.rb +42 -42
  48. data/test/cases/adapters/mysql2/unsigned_type_test.rb +66 -66
  49. data/test/cases/adapters/postgresql/active_schema_test.rb +98 -98
  50. data/test/cases/adapters/postgresql/array_test.rb +339 -339
  51. data/test/cases/adapters/postgresql/bit_string_test.rb +82 -82
  52. data/test/cases/adapters/postgresql/bytea_test.rb +134 -134
  53. data/test/cases/adapters/postgresql/case_insensitive_test.rb +26 -26
  54. data/test/cases/adapters/postgresql/change_schema_test.rb +38 -38
  55. data/test/cases/adapters/postgresql/cidr_test.rb +25 -25
  56. data/test/cases/adapters/postgresql/citext_test.rb +78 -78
  57. data/test/cases/adapters/postgresql/collation_test.rb +53 -53
  58. data/test/cases/adapters/postgresql/composite_test.rb +132 -132
  59. data/test/cases/adapters/postgresql/connection_test.rb +257 -257
  60. data/test/cases/adapters/postgresql/datatype_test.rb +92 -92
  61. data/test/cases/adapters/postgresql/domain_test.rb +47 -47
  62. data/test/cases/adapters/postgresql/enum_test.rb +91 -91
  63. data/test/cases/adapters/postgresql/explain_test.rb +20 -20
  64. data/test/cases/adapters/postgresql/extension_migration_test.rb +63 -63
  65. data/test/cases/adapters/postgresql/full_text_test.rb +44 -44
  66. data/test/cases/adapters/postgresql/geometric_test.rb +378 -378
  67. data/test/cases/adapters/postgresql/hstore_test.rb +382 -382
  68. data/test/cases/adapters/postgresql/infinity_test.rb +69 -69
  69. data/test/cases/adapters/postgresql/integer_test.rb +25 -25
  70. data/test/cases/adapters/postgresql/json_test.rb +237 -237
  71. data/test/cases/adapters/postgresql/ltree_test.rb +53 -53
  72. data/test/cases/adapters/postgresql/money_test.rb +96 -96
  73. data/test/cases/adapters/postgresql/network_test.rb +94 -94
  74. data/test/cases/adapters/postgresql/numbers_test.rb +49 -49
  75. data/test/cases/adapters/postgresql/postgresql_adapter_test.rb +405 -405
  76. data/test/cases/adapters/postgresql/prepared_statements_test.rb +22 -22
  77. data/test/cases/adapters/postgresql/quoting_test.rb +44 -44
  78. data/test/cases/adapters/postgresql/range_test.rb +343 -343
  79. data/test/cases/adapters/postgresql/referential_integrity_test.rb +111 -111
  80. data/test/cases/adapters/postgresql/rename_table_test.rb +34 -34
  81. data/test/cases/adapters/postgresql/schema_authorization_test.rb +119 -119
  82. data/test/cases/adapters/postgresql/schema_test.rb +597 -597
  83. data/test/cases/adapters/postgresql/serial_test.rb +154 -154
  84. data/test/cases/adapters/postgresql/statement_pool_test.rb +41 -41
  85. data/test/cases/adapters/postgresql/timestamp_test.rb +90 -90
  86. data/test/cases/adapters/postgresql/type_lookup_test.rb +33 -33
  87. data/test/cases/adapters/postgresql/utils_test.rb +62 -62
  88. data/test/cases/adapters/postgresql/uuid_test.rb +294 -294
  89. data/test/cases/adapters/postgresql/xml_test.rb +54 -54
  90. data/test/cases/adapters/sqlite3/collation_test.rb +53 -53
  91. data/test/cases/adapters/sqlite3/copy_table_test.rb +98 -98
  92. data/test/cases/adapters/sqlite3/explain_test.rb +21 -21
  93. data/test/cases/adapters/sqlite3/quoting_test.rb +101 -101
  94. data/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +441 -441
  95. data/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb +24 -24
  96. data/test/cases/adapters/sqlite3/statement_pool_test.rb +20 -20
  97. data/test/cases/aggregations_test.rb +168 -168
  98. data/test/cases/ar_schema_test.rb +146 -146
  99. data/test/cases/associations/association_scope_test.rb +16 -16
  100. data/test/cases/associations/belongs_to_associations_test.rb +1141 -1141
  101. data/test/cases/associations/bidirectional_destroy_dependencies_test.rb +41 -41
  102. data/test/cases/associations/callbacks_test.rb +190 -190
  103. data/test/cases/associations/cascaded_eager_loading_test.rb +188 -188
  104. data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +36 -36
  105. data/test/cases/associations/eager_load_nested_include_test.rb +126 -126
  106. data/test/cases/associations/eager_singularization_test.rb +148 -148
  107. data/test/cases/associations/eager_test.rb +1514 -1514
  108. data/test/cases/associations/extension_test.rb +87 -87
  109. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +1004 -1004
  110. data/test/cases/associations/has_many_associations_test.rb +2501 -2501
  111. data/test/cases/associations/has_many_through_associations_test.rb +1271 -1271
  112. data/test/cases/associations/has_one_associations_test.rb +707 -707
  113. data/test/cases/associations/has_one_through_associations_test.rb +383 -383
  114. data/test/cases/associations/inner_join_association_test.rb +139 -139
  115. data/test/cases/associations/inverse_associations_test.rb +733 -733
  116. data/test/cases/associations/join_model_test.rb +777 -777
  117. data/test/cases/associations/left_outer_join_association_test.rb +88 -88
  118. data/test/cases/associations/nested_through_associations_test.rb +579 -579
  119. data/test/cases/associations/required_test.rb +102 -102
  120. data/test/cases/associations_test.rb +385 -385
  121. data/test/cases/attribute_decorators_test.rb +126 -125
  122. data/test/cases/attribute_methods/read_test.rb +60 -60
  123. data/test/cases/attribute_methods_test.rb +1009 -1009
  124. data/test/cases/attribute_set_test.rb +270 -270
  125. data/test/cases/attribute_test.rb +246 -246
  126. data/test/cases/attributes_test.rb +253 -253
  127. data/test/cases/autosave_association_test.rb +1708 -1708
  128. data/test/cases/base_test.rb +1713 -1713
  129. data/test/cases/batches_test.rb +489 -489
  130. data/test/cases/binary_test.rb +44 -44
  131. data/test/cases/bind_parameter_test.rb +110 -110
  132. data/test/cases/cache_key_test.rb +26 -25
  133. data/test/cases/calculations_test.rb +798 -798
  134. data/test/cases/callbacks_test.rb +636 -636
  135. data/test/cases/clone_test.rb +40 -40
  136. data/test/cases/coders/json_test.rb +15 -15
  137. data/test/cases/coders/yaml_column_test.rb +63 -63
  138. data/test/cases/collection_cache_key_test.rb +115 -115
  139. data/test/cases/column_alias_test.rb +17 -17
  140. data/test/cases/column_definition_test.rb +92 -92
  141. data/test/cases/comment_test.rb +145 -143
  142. data/test/cases/connection_adapters/adapter_leasing_test.rb +56 -56
  143. data/test/cases/connection_adapters/connection_handler_test.rb +160 -160
  144. data/test/cases/connection_adapters/connection_specification_test.rb +12 -12
  145. data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +255 -255
  146. data/test/cases/connection_adapters/mysql_type_lookup_test.rb +69 -69
  147. data/test/cases/connection_adapters/quoting_test.rb +13 -13
  148. data/test/cases/connection_adapters/schema_cache_test.rb +61 -61
  149. data/test/cases/connection_adapters/type_lookup_test.rb +118 -118
  150. data/test/cases/connection_management_test.rb +112 -112
  151. data/test/cases/connection_pool_test.rb +521 -521
  152. data/test/cases/connection_specification/resolver_test.rb +131 -131
  153. data/test/cases/core_test.rb +112 -112
  154. data/test/cases/counter_cache_test.rb +214 -214
  155. data/test/cases/custom_locking_test.rb +17 -17
  156. data/test/cases/database_statements_test.rb +34 -34
  157. data/test/cases/date_test.rb +44 -44
  158. data/test/cases/date_time_precision_test.rb +107 -106
  159. data/test/cases/date_time_test.rb +61 -61
  160. data/test/cases/defaults_test.rb +219 -218
  161. data/test/cases/dirty_test.rb +763 -763
  162. data/test/cases/disconnected_test.rb +30 -30
  163. data/test/cases/dup_test.rb +157 -157
  164. data/test/cases/enum_test.rb +444 -444
  165. data/test/cases/errors_test.rb +16 -16
  166. data/test/cases/explain_subscriber_test.rb +64 -64
  167. data/test/cases/explain_test.rb +87 -87
  168. data/test/cases/finder_respond_to_test.rb +60 -60
  169. data/test/cases/finder_test.rb +1294 -1294
  170. data/test/cases/fixture_set/file_test.rb +156 -156
  171. data/test/cases/fixtures_test.rb +988 -988
  172. data/test/cases/forbidden_attributes_protection_test.rb +165 -165
  173. data/test/cases/habtm_destroy_order_test.rb +61 -61
  174. data/test/cases/helper.rb +204 -204
  175. data/test/cases/hot_compatibility_test.rb +142 -142
  176. data/test/cases/i18n_test.rb +45 -45
  177. data/test/cases/inheritance_test.rb +606 -606
  178. data/test/cases/integration_test.rb +155 -155
  179. data/test/cases/invalid_connection_test.rb +24 -24
  180. data/test/cases/invertible_migration_test.rb +387 -387
  181. data/test/cases/json_serialization_test.rb +311 -311
  182. data/test/cases/locking_test.rb +493 -493
  183. data/test/cases/log_subscriber_test.rb +225 -225
  184. data/test/cases/migration/change_schema_test.rb +458 -458
  185. data/test/cases/migration/change_table_test.rb +256 -256
  186. data/test/cases/migration/column_attributes_test.rb +176 -176
  187. data/test/cases/migration/column_positioning_test.rb +56 -56
  188. data/test/cases/migration/columns_test.rb +310 -310
  189. data/test/cases/migration/command_recorder_test.rb +350 -350
  190. data/test/cases/migration/compatibility_test.rb +118 -118
  191. data/test/cases/migration/create_join_table_test.rb +157 -157
  192. data/test/cases/migration/foreign_key_test.rb +362 -360
  193. data/test/cases/migration/helper.rb +39 -39
  194. data/test/cases/migration/index_test.rb +218 -218
  195. data/test/cases/migration/logger_test.rb +36 -36
  196. data/test/cases/migration/pending_migrations_test.rb +52 -52
  197. data/test/cases/migration/references_foreign_key_test.rb +221 -216
  198. data/test/cases/migration/references_index_test.rb +101 -101
  199. data/test/cases/migration/references_statements_test.rb +136 -136
  200. data/test/cases/migration/rename_table_test.rb +93 -93
  201. data/test/cases/migration_test.rb +1157 -1157
  202. data/test/cases/migrator_test.rb +471 -470
  203. data/test/cases/mixin_test.rb +68 -68
  204. data/test/cases/modules_test.rb +172 -172
  205. data/test/cases/multiparameter_attributes_test.rb +372 -372
  206. data/test/cases/multiple_db_test.rb +122 -122
  207. data/test/cases/nested_attributes_test.rb +1098 -1098
  208. data/test/cases/nested_attributes_with_callbacks_test.rb +144 -144
  209. data/test/cases/persistence_test.rb +1001 -1001
  210. data/test/cases/pooled_connections_test.rb +81 -81
  211. data/test/cases/primary_keys_test.rb +376 -376
  212. data/test/cases/query_cache_test.rb +446 -446
  213. data/test/cases/quoting_test.rb +202 -202
  214. data/test/cases/readonly_test.rb +119 -119
  215. data/test/cases/reaper_test.rb +85 -85
  216. data/test/cases/reflection_test.rb +509 -509
  217. data/test/cases/relation/delegation_test.rb +63 -63
  218. data/test/cases/relation/merging_test.rb +157 -157
  219. data/test/cases/relation/mutation_test.rb +183 -183
  220. data/test/cases/relation/or_test.rb +92 -92
  221. data/test/cases/relation/predicate_builder_test.rb +16 -16
  222. data/test/cases/relation/record_fetch_warning_test.rb +40 -40
  223. data/test/cases/relation/where_chain_test.rb +105 -105
  224. data/test/cases/relation/where_clause_test.rb +182 -182
  225. data/test/cases/relation/where_test.rb +322 -322
  226. data/test/cases/relation_test.rb +328 -328
  227. data/test/cases/relations_test.rb +2026 -2026
  228. data/test/cases/reload_models_test.rb +22 -22
  229. data/test/cases/result_test.rb +90 -90
  230. data/test/cases/sanitize_test.rb +176 -176
  231. data/test/cases/schema_dumper_test.rb +457 -457
  232. data/test/cases/schema_loading_test.rb +52 -52
  233. data/test/cases/scoping/default_scoping_test.rb +528 -528
  234. data/test/cases/scoping/named_scoping_test.rb +561 -561
  235. data/test/cases/scoping/relation_scoping_test.rb +400 -400
  236. data/test/cases/secure_token_test.rb +32 -32
  237. data/test/cases/serialization_test.rb +104 -104
  238. data/test/cases/serialized_attribute_test.rb +364 -364
  239. data/test/cases/statement_cache_test.rb +136 -136
  240. data/test/cases/store_test.rb +195 -195
  241. data/test/cases/suppressor_test.rb +63 -63
  242. data/test/cases/tasks/database_tasks_test.rb +462 -462
  243. data/test/cases/tasks/mysql_rake_test.rb +345 -345
  244. data/test/cases/tasks/postgresql_rake_test.rb +304 -304
  245. data/test/cases/tasks/sqlite_rake_test.rb +220 -220
  246. data/test/cases/test_case.rb +131 -131
  247. data/test/cases/test_fixtures_test.rb +36 -36
  248. data/test/cases/time_precision_test.rb +103 -102
  249. data/test/cases/timestamp_test.rb +501 -501
  250. data/test/cases/touch_later_test.rb +121 -121
  251. data/test/cases/transaction_callbacks_test.rb +518 -518
  252. data/test/cases/transaction_isolation_test.rb +106 -106
  253. data/test/cases/transactions_test.rb +835 -834
  254. data/test/cases/type/adapter_specific_registry_test.rb +133 -133
  255. data/test/cases/type/date_time_test.rb +14 -14
  256. data/test/cases/type/integer_test.rb +27 -27
  257. data/test/cases/type/string_test.rb +22 -22
  258. data/test/cases/type/type_map_test.rb +177 -177
  259. data/test/cases/type_test.rb +39 -39
  260. data/test/cases/types_test.rb +24 -24
  261. data/test/cases/unconnected_test.rb +33 -33
  262. data/test/cases/validations/absence_validation_test.rb +73 -73
  263. data/test/cases/validations/association_validation_test.rb +97 -97
  264. data/test/cases/validations/i18n_generate_message_validation_test.rb +84 -84
  265. data/test/cases/validations/i18n_validation_test.rb +86 -86
  266. data/test/cases/validations/length_validation_test.rb +79 -79
  267. data/test/cases/validations/presence_validation_test.rb +103 -103
  268. data/test/cases/validations/uniqueness_validation_test.rb +548 -548
  269. data/test/cases/validations_repair_helper.rb +19 -19
  270. data/test/cases/validations_test.rb +194 -194
  271. data/test/cases/view_test.rb +216 -216
  272. data/test/cases/yaml_serialization_test.rb +121 -121
  273. data/test/config.example.yml +97 -97
  274. data/test/config.rb +5 -5
  275. data/test/connections/native_ibm_db/connection.rb +44 -0
  276. data/test/fixtures/accounts.yml +29 -29
  277. data/test/fixtures/admin/accounts.yml +2 -2
  278. data/test/fixtures/admin/users.yml +10 -10
  279. data/test/fixtures/author_addresses.yml +17 -17
  280. data/test/fixtures/author_favorites.yml +3 -3
  281. data/test/fixtures/authors.yml +23 -23
  282. data/test/fixtures/bad_posts.yml +9 -9
  283. data/test/fixtures/binaries.yml +133 -133
  284. data/test/fixtures/books.yml +31 -31
  285. data/test/fixtures/bulbs.yml +5 -5
  286. data/test/fixtures/cars.yml +9 -9
  287. data/test/fixtures/categories.yml +19 -19
  288. data/test/fixtures/categories/special_categories.yml +9 -9
  289. data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +4 -4
  290. data/test/fixtures/categories_ordered.yml +7 -7
  291. data/test/fixtures/categories_posts.yml +31 -31
  292. data/test/fixtures/categorizations.yml +23 -23
  293. data/test/fixtures/clubs.yml +8 -8
  294. data/test/fixtures/collections.yml +3 -3
  295. data/test/fixtures/colleges.yml +3 -3
  296. data/test/fixtures/comments.yml +65 -65
  297. data/test/fixtures/companies.yml +67 -67
  298. data/test/fixtures/computers.yml +10 -10
  299. data/test/fixtures/content.yml +3 -3
  300. data/test/fixtures/content_positions.yml +3 -3
  301. data/test/fixtures/courses.yml +8 -8
  302. data/test/fixtures/customers.yml +25 -25
  303. data/test/fixtures/dashboards.yml +6 -6
  304. data/test/fixtures/dead_parrots.yml +5 -5
  305. data/test/fixtures/developers.yml +22 -22
  306. data/test/fixtures/developers_projects.yml +16 -16
  307. data/test/fixtures/dog_lovers.yml +7 -7
  308. data/test/fixtures/dogs.yml +4 -4
  309. data/test/fixtures/doubloons.yml +3 -3
  310. data/test/fixtures/edges.yml +5 -5
  311. data/test/fixtures/entrants.yml +14 -14
  312. data/test/fixtures/essays.yml +6 -6
  313. data/test/fixtures/faces.yml +11 -11
  314. data/test/fixtures/fk_test_has_fk.yml +3 -3
  315. data/test/fixtures/fk_test_has_pk.yml +1 -1
  316. data/test/fixtures/friendships.yml +4 -4
  317. data/test/fixtures/funny_jokes.yml +10 -10
  318. data/test/fixtures/interests.yml +33 -33
  319. data/test/fixtures/items.yml +3 -3
  320. data/test/fixtures/jobs.yml +7 -7
  321. data/test/fixtures/legacy_things.yml +3 -3
  322. data/test/fixtures/live_parrots.yml +4 -4
  323. data/test/fixtures/mateys.yml +4 -4
  324. data/test/fixtures/member_details.yml +8 -8
  325. data/test/fixtures/member_types.yml +6 -6
  326. data/test/fixtures/members.yml +11 -11
  327. data/test/fixtures/memberships.yml +34 -34
  328. data/test/fixtures/men.yml +5 -5
  329. data/test/fixtures/minimalistics.yml +2 -2
  330. data/test/fixtures/minivans.yml +5 -5
  331. data/test/fixtures/mixed_case_monkeys.yml +6 -6
  332. data/test/fixtures/mixins.yml +29 -29
  333. data/test/fixtures/movies.yml +7 -7
  334. data/test/fixtures/naked/yml/accounts.yml +1 -1
  335. data/test/fixtures/naked/yml/companies.yml +1 -1
  336. data/test/fixtures/naked/yml/courses.yml +1 -1
  337. data/test/fixtures/naked/yml/parrots.yml +2 -2
  338. data/test/fixtures/naked/yml/trees.yml +3 -3
  339. data/test/fixtures/nodes.yml +29 -29
  340. data/test/fixtures/organizations.yml +5 -5
  341. data/test/fixtures/other_comments.yml +6 -6
  342. data/test/fixtures/other_dogs.yml +2 -2
  343. data/test/fixtures/other_posts.yml +7 -7
  344. data/test/fixtures/other_topics.yml +42 -42
  345. data/test/fixtures/owners.yml +9 -9
  346. data/test/fixtures/parrots.yml +27 -27
  347. data/test/fixtures/parrots_pirates.yml +7 -7
  348. data/test/fixtures/people.yml +24 -24
  349. data/test/fixtures/peoples_treasures.yml +3 -3
  350. data/test/fixtures/pets.yml +19 -19
  351. data/test/fixtures/pirates.yml +12 -15
  352. data/test/fixtures/posts.yml +80 -80
  353. data/test/fixtures/price_estimates.yml +16 -16
  354. data/test/fixtures/products.yml +4 -4
  355. data/test/fixtures/projects.yml +7 -7
  356. data/test/fixtures/ratings.yml +14 -14
  357. data/test/fixtures/readers.yml +11 -11
  358. data/test/fixtures/references.yml +17 -17
  359. data/test/fixtures/reserved_words/distinct.yml +5 -5
  360. data/test/fixtures/reserved_words/distinct_select.yml +11 -11
  361. data/test/fixtures/reserved_words/group.yml +14 -14
  362. data/test/fixtures/reserved_words/select.yml +8 -8
  363. data/test/fixtures/reserved_words/values.yml +7 -7
  364. data/test/fixtures/ships.yml +6 -6
  365. data/test/fixtures/speedometers.yml +8 -8
  366. data/test/fixtures/sponsors.yml +12 -12
  367. data/test/fixtures/string_key_objects.yml +7 -7
  368. data/test/fixtures/subscribers.yml +10 -10
  369. data/test/fixtures/subscriptions.yml +12 -12
  370. data/test/fixtures/taggings.yml +78 -78
  371. data/test/fixtures/tags.yml +11 -11
  372. data/test/fixtures/tasks.yml +7 -7
  373. data/test/fixtures/teapots.yml +3 -3
  374. data/test/fixtures/to_be_linked/accounts.yml +2 -2
  375. data/test/fixtures/to_be_linked/users.yml +10 -10
  376. data/test/fixtures/topics.yml +49 -49
  377. data/test/fixtures/toys.yml +14 -14
  378. data/test/fixtures/traffic_lights.yml +9 -9
  379. data/test/fixtures/treasures.yml +10 -10
  380. data/test/fixtures/trees.yml +3 -3
  381. data/test/fixtures/uuid_children.yml +3 -3
  382. data/test/fixtures/uuid_parents.yml +2 -2
  383. data/test/fixtures/variants.yml +4 -4
  384. data/test/fixtures/vegetables.yml +19 -19
  385. data/test/fixtures/vertices.yml +3 -3
  386. data/test/fixtures/warehouse_things.yml +2 -2
  387. data/test/fixtures/zines.yml +5 -5
  388. data/test/migrations/10_urban/9_add_expressions.rb +11 -11
  389. data/test/migrations/decimal/1_give_me_big_numbers.rb +15 -15
  390. data/test/migrations/magic/1_currencies_have_symbols.rb +12 -12
  391. data/test/migrations/missing/1000_people_have_middle_names.rb +9 -9
  392. data/test/migrations/missing/1_people_have_last_names.rb +9 -9
  393. data/test/migrations/missing/3_we_need_reminders.rb +12 -12
  394. data/test/migrations/missing/4_innocent_jointable.rb +12 -12
  395. data/test/migrations/rename/1_we_need_things.rb +11 -11
  396. data/test/migrations/rename/2_rename_things.rb +9 -9
  397. data/test/migrations/to_copy/1_people_have_hobbies.rb +9 -9
  398. data/test/migrations/to_copy/2_people_have_descriptions.rb +9 -9
  399. data/test/migrations/to_copy2/1_create_articles.rb +7 -7
  400. data/test/migrations/to_copy2/2_create_comments.rb +7 -7
  401. data/test/migrations/to_copy_with_name_collision/1_people_have_hobbies.rb +9 -9
  402. data/test/migrations/to_copy_with_timestamps/20090101010101_people_have_hobbies.rb +9 -9
  403. data/test/migrations/to_copy_with_timestamps/20090101010202_people_have_descriptions.rb +9 -9
  404. data/test/migrations/to_copy_with_timestamps2/20090101010101_create_articles.rb +7 -7
  405. data/test/migrations/to_copy_with_timestamps2/20090101010202_create_comments.rb +7 -7
  406. data/test/migrations/valid/1_valid_people_have_last_names.rb +9 -9
  407. data/test/migrations/valid/2_we_need_reminders.rb +12 -12
  408. data/test/migrations/valid/3_innocent_jointable.rb +12 -12
  409. data/test/migrations/valid_with_subdirectories/1_valid_people_have_last_names.rb +9 -9
  410. data/test/migrations/valid_with_subdirectories/sub/2_we_need_reminders.rb +12 -12
  411. data/test/migrations/valid_with_subdirectories/sub1/3_innocent_jointable.rb +12 -12
  412. data/test/migrations/valid_with_timestamps/20100101010101_valid_with_timestamps_people_have_last_names.rb +9 -9
  413. data/test/migrations/valid_with_timestamps/20100201010101_valid_with_timestamps_we_need_reminders.rb +12 -12
  414. data/test/migrations/valid_with_timestamps/20100301010101_valid_with_timestamps_innocent_jointable.rb +12 -12
  415. data/test/migrations/version_check/20131219224947_migration_version_check.rb +8 -8
  416. data/test/models/admin.rb +5 -5
  417. data/test/models/admin/account.rb +3 -3
  418. data/test/models/admin/user.rb +40 -40
  419. data/test/models/aircraft.rb +5 -5
  420. data/test/models/arunit2_model.rb +3 -3
  421. data/test/models/author.rb +209 -209
  422. data/test/models/auto_id.rb +4 -4
  423. data/test/models/autoloadable/extra_firm.rb +2 -2
  424. data/test/models/binary.rb +2 -2
  425. data/test/models/bird.rb +12 -12
  426. data/test/models/book.rb +23 -23
  427. data/test/models/boolean.rb +2 -2
  428. data/test/models/bulb.rb +52 -52
  429. data/test/models/cake_designer.rb +3 -3
  430. data/test/models/car.rb +29 -29
  431. data/test/models/carrier.rb +2 -2
  432. data/test/models/cat.rb +10 -10
  433. data/test/models/categorization.rb +19 -19
  434. data/test/models/category.rb +35 -35
  435. data/test/models/chef.rb +8 -8
  436. data/test/models/citation.rb +3 -3
  437. data/test/models/club.rb +25 -25
  438. data/test/models/college.rb +10 -10
  439. data/test/models/column.rb +3 -3
  440. data/test/models/column_name.rb +3 -3
  441. data/test/models/comment.rb +76 -76
  442. data/test/models/company.rb +230 -230
  443. data/test/models/company_in_module.rb +98 -98
  444. data/test/models/computer.rb +3 -3
  445. data/test/models/contact.rb +41 -41
  446. data/test/models/content.rb +40 -40
  447. data/test/models/contract.rb +20 -20
  448. data/test/models/country.rb +7 -7
  449. data/test/models/course.rb +6 -6
  450. data/test/models/customer.rb +83 -83
  451. data/test/models/customer_carrier.rb +14 -14
  452. data/test/models/dashboard.rb +3 -3
  453. data/test/models/default.rb +2 -2
  454. data/test/models/department.rb +4 -4
  455. data/test/models/developer.rb +274 -274
  456. data/test/models/dog.rb +5 -5
  457. data/test/models/dog_lover.rb +5 -5
  458. data/test/models/doubloon.rb +12 -12
  459. data/test/models/drink_designer.rb +3 -3
  460. data/test/models/edge.rb +5 -5
  461. data/test/models/electron.rb +5 -5
  462. data/test/models/engine.rb +4 -4
  463. data/test/models/entrant.rb +3 -3
  464. data/test/models/essay.rb +5 -5
  465. data/test/models/event.rb +3 -3
  466. data/test/models/eye.rb +37 -37
  467. data/test/models/face.rb +9 -9
  468. data/test/models/friendship.rb +6 -6
  469. data/test/models/guid.rb +2 -2
  470. data/test/models/guitar.rb +4 -4
  471. data/test/models/hotel.rb +11 -11
  472. data/test/models/image.rb +3 -3
  473. data/test/models/interest.rb +5 -5
  474. data/test/models/invoice.rb +4 -4
  475. data/test/models/item.rb +7 -7
  476. data/test/models/job.rb +7 -7
  477. data/test/models/joke.rb +7 -7
  478. data/test/models/keyboard.rb +3 -3
  479. data/test/models/legacy_thing.rb +3 -3
  480. data/test/models/lesson.rb +11 -11
  481. data/test/models/line_item.rb +3 -3
  482. data/test/models/liquid.rb +4 -4
  483. data/test/models/man.rb +11 -11
  484. data/test/models/matey.rb +4 -4
  485. data/test/models/member.rb +42 -42
  486. data/test/models/member_detail.rb +8 -8
  487. data/test/models/member_type.rb +3 -3
  488. data/test/models/membership.rb +35 -35
  489. data/test/models/mentor.rb +2 -2
  490. data/test/models/minimalistic.rb +2 -2
  491. data/test/models/minivan.rb +9 -9
  492. data/test/models/mixed_case_monkey.rb +3 -3
  493. data/test/models/mocktail_designer.rb +2 -2
  494. data/test/models/molecule.rb +6 -6
  495. data/test/models/movie.rb +5 -5
  496. data/test/models/node.rb +5 -5
  497. data/test/models/non_primary_key.rb +2 -2
  498. data/test/models/notification.rb +3 -3
  499. data/test/models/order.rb +4 -4
  500. data/test/models/organization.rb +14 -14
  501. data/test/models/other_dog.rb +5 -5
  502. data/test/models/owner.rb +37 -37
  503. data/test/models/parrot.rb +28 -28
  504. data/test/models/person.rb +142 -142
  505. data/test/models/personal_legacy_thing.rb +4 -4
  506. data/test/models/pet.rb +18 -18
  507. data/test/models/pet_treasure.rb +6 -6
  508. data/test/models/pirate.rb +92 -92
  509. data/test/models/possession.rb +3 -3
  510. data/test/models/post.rb +273 -273
  511. data/test/models/price_estimate.rb +4 -4
  512. data/test/models/professor.rb +5 -5
  513. data/test/models/project.rb +40 -40
  514. data/test/models/publisher.rb +2 -2
  515. data/test/models/publisher/article.rb +4 -4
  516. data/test/models/publisher/magazine.rb +3 -3
  517. data/test/models/rating.rb +4 -4
  518. data/test/models/reader.rb +23 -23
  519. data/test/models/recipe.rb +3 -3
  520. data/test/models/record.rb +2 -2
  521. data/test/models/reference.rb +22 -22
  522. data/test/models/reply.rb +61 -61
  523. data/test/models/ship.rb +39 -39
  524. data/test/models/ship_part.rb +8 -8
  525. data/test/models/shop.rb +17 -17
  526. data/test/models/shop_account.rb +6 -6
  527. data/test/models/speedometer.rb +6 -6
  528. data/test/models/sponsor.rb +7 -7
  529. data/test/models/string_key_object.rb +3 -3
  530. data/test/models/student.rb +4 -4
  531. data/test/models/subject.rb +16 -16
  532. data/test/models/subscriber.rb +8 -8
  533. data/test/models/subscription.rb +4 -4
  534. data/test/models/tag.rb +13 -13
  535. data/test/models/tagging.rb +13 -13
  536. data/test/models/task.rb +5 -5
  537. data/test/models/topic.rb +118 -118
  538. data/test/models/toy.rb +6 -6
  539. data/test/models/traffic_light.rb +4 -4
  540. data/test/models/treasure.rb +14 -14
  541. data/test/models/treaty.rb +7 -7
  542. data/test/models/tree.rb +3 -3
  543. data/test/models/tuning_peg.rb +4 -4
  544. data/test/models/tyre.rb +11 -11
  545. data/test/models/user.rb +14 -14
  546. data/test/models/uuid_child.rb +3 -3
  547. data/test/models/uuid_item.rb +6 -6
  548. data/test/models/uuid_parent.rb +3 -3
  549. data/test/models/vegetables.rb +24 -24
  550. data/test/models/vehicle.rb +6 -6
  551. data/test/models/vertex.rb +9 -9
  552. data/test/models/warehouse_thing.rb +5 -5
  553. data/test/models/wheel.rb +3 -3
  554. data/test/models/without_table.rb +3 -3
  555. data/test/models/zine.rb +3 -3
  556. data/test/schema/i5/ibm_db_specific_schema.rb +137 -0
  557. data/test/schema/ids/ibm_db_specific_schema.rb +140 -0
  558. data/test/schema/luw/ibm_db_specific_schema.rb +137 -0
  559. data/test/schema/mysql2_specific_schema.rb +68 -68
  560. data/test/schema/oracle_specific_schema.rb +40 -40
  561. data/test/schema/postgresql_specific_schema.rb +114 -114
  562. data/test/schema/schema.rb +1057 -1057
  563. data/test/schema/schema.rb.original +1057 -1057
  564. data/test/schema/sqlite_specific_schema.rb +18 -18
  565. data/test/schema/zOS/ibm_db_specific_schema.rb +208 -0
  566. data/test/support/config.rb +43 -43
  567. data/test/support/connection.rb +23 -23
  568. data/test/support/connection_helper.rb +14 -14
  569. data/test/support/ddl_helper.rb +8 -8
  570. data/test/support/schema_dumping_helper.rb +20 -20
  571. data/test/support/yaml_compatibility_fixtures/rails_4_1.yml +22 -22
  572. data/test/support/yaml_compatibility_fixtures/rails_4_2_0.yml +182 -182
  573. metadata +30 -14
  574. data/lib/mswin32/rb2x/i386/ibm_db.so +0 -0
  575. data/test/fixtures/author_addresses.original +0 -11
  576. data/test/fixtures/authors.original +0 -17
@@ -1,93 +1,93 @@
1
- require "cases/migration/helper"
2
-
3
- module ActiveRecord
4
- class Migration
5
- class RenameTableTest < ActiveRecord::TestCase
6
- include ActiveRecord::Migration::TestHelper
7
-
8
- self.use_transactional_tests = false
9
-
10
- def setup
11
- super
12
- add_column 'test_models', :url, :string
13
- remove_column 'test_models', :created_at
14
- remove_column 'test_models', :updated_at
15
- end
16
-
17
- def teardown
18
- ActiveSupport::Deprecation.silence { rename_table :octopi, :test_models if connection.table_exists? :octopi }
19
- super
20
- end
21
-
22
- if current_adapter?(:SQLite3Adapter)
23
- def test_rename_table_for_sqlite_should_work_with_reserved_words
24
- renamed = false
25
-
26
- add_column :test_models, :url, :string
27
- connection.rename_table :references, :old_references
28
- connection.rename_table :test_models, :references
29
-
30
- renamed = true
31
-
32
- # Using explicit id in insert for compatibility across all databases
33
- connection.execute "INSERT INTO 'references' (url, created_at, updated_at) VALUES ('http://rubyonrails.com', 0, 0)"
34
- assert_equal 'http://rubyonrails.com', connection.select_value("SELECT url FROM 'references' WHERE id=1")
35
- ensure
36
- return unless renamed
37
- connection.rename_table :references, :test_models
38
- connection.rename_table :old_references, :references
39
- end
40
- end
41
-
42
- unless current_adapter?(:FbAdapter) # Firebird cannot rename tables
43
- def test_rename_table
44
- rename_table :test_models, :octopi
45
-
46
- connection.execute "INSERT INTO octopi (#{connection.quote_column_name('id')}, #{connection.quote_column_name('url')}) VALUES (1, 'http://www.foreverflying.com/octopus-black7.jpg')"
47
-
48
- assert_equal 'http://www.foreverflying.com/octopus-black7.jpg', connection.select_value("SELECT url FROM octopi WHERE id=1")
49
- end
50
-
51
- def test_rename_table_with_an_index
52
- add_index :test_models, :url
53
-
54
- rename_table :test_models, :octopi
55
-
56
- connection.execute "INSERT INTO octopi (#{connection.quote_column_name('id')}, #{connection.quote_column_name('url')}) VALUES (1, 'http://www.foreverflying.com/octopus-black7.jpg')"
57
-
58
- assert_equal 'http://www.foreverflying.com/octopus-black7.jpg', connection.select_value("SELECT url FROM octopi WHERE id=1")
59
- index = connection.indexes(:octopi).first
60
- assert index.columns.include?("url")
61
- assert_equal 'index_octopi_on_url', index.name
62
- end
63
-
64
- def test_rename_table_does_not_rename_custom_named_index
65
- add_index :test_models, :url, name: 'special_url_idx'
66
-
67
- rename_table :test_models, :octopi
68
-
69
- assert_equal ['special_url_idx'], connection.indexes(:octopi).map(&:name)
70
- end
71
- end
72
-
73
- if current_adapter?(:PostgreSQLAdapter)
74
- def test_rename_table_for_postgresql_should_also_rename_default_sequence
75
- rename_table :test_models, :octopi
76
-
77
- pk, seq = connection.pk_and_sequence_for('octopi')
78
-
79
- assert_equal ConnectionAdapters::PostgreSQL::Name.new("public", "octopi_#{pk}_seq"), seq
80
- end
81
-
82
- def test_renaming_table_doesnt_attempt_to_rename_non_existent_sequences
83
- connection.create_table :cats, id: :uuid
84
- assert_nothing_raised { rename_table :cats, :felines }
85
- ActiveSupport::Deprecation.silence { assert connection.table_exists? :felines }
86
- ensure
87
- connection.drop_table :cats, if_exists: true
88
- connection.drop_table :felines, if_exists: true
89
- end
90
- end
91
- end
92
- end
93
- end
1
+ require "cases/migration/helper"
2
+
3
+ module ActiveRecord
4
+ class Migration
5
+ class RenameTableTest < ActiveRecord::TestCase
6
+ include ActiveRecord::Migration::TestHelper
7
+
8
+ self.use_transactional_tests = false
9
+
10
+ def setup
11
+ super
12
+ add_column 'test_models', :url, :string
13
+ remove_column 'test_models', :created_at
14
+ remove_column 'test_models', :updated_at
15
+ end
16
+
17
+ def teardown
18
+ ActiveSupport::Deprecation.silence { rename_table :octopi, :test_models if connection.table_exists? :octopi }
19
+ super
20
+ end
21
+
22
+ if current_adapter?(:SQLite3Adapter)
23
+ def test_rename_table_for_sqlite_should_work_with_reserved_words
24
+ renamed = false
25
+
26
+ add_column :test_models, :url, :string
27
+ connection.rename_table :references, :old_references
28
+ connection.rename_table :test_models, :references
29
+
30
+ renamed = true
31
+
32
+ # Using explicit id in insert for compatibility across all databases
33
+ connection.execute "INSERT INTO 'references' (url, created_at, updated_at) VALUES ('http://rubyonrails.com', 0, 0)"
34
+ assert_equal 'http://rubyonrails.com', connection.select_value("SELECT url FROM 'references' WHERE id=1")
35
+ ensure
36
+ return unless renamed
37
+ connection.rename_table :references, :test_models
38
+ connection.rename_table :old_references, :references
39
+ end
40
+ end
41
+
42
+ unless current_adapter?(:FbAdapter) # Firebird cannot rename tables
43
+ def test_rename_table
44
+ rename_table :test_models, :octopi
45
+
46
+ connection.execute "INSERT INTO octopi (#{connection.quote_column_name('id')}, #{connection.quote_column_name('url')}) VALUES (1, 'http://www.foreverflying.com/octopus-black7.jpg')"
47
+
48
+ assert_equal 'http://www.foreverflying.com/octopus-black7.jpg', connection.select_value("SELECT url FROM octopi WHERE id=1")
49
+ end
50
+
51
+ def test_rename_table_with_an_index
52
+ add_index :test_models, :url
53
+
54
+ rename_table :test_models, :octopi
55
+
56
+ connection.execute "INSERT INTO octopi (#{connection.quote_column_name('id')}, #{connection.quote_column_name('url')}) VALUES (1, 'http://www.foreverflying.com/octopus-black7.jpg')"
57
+
58
+ assert_equal 'http://www.foreverflying.com/octopus-black7.jpg', connection.select_value("SELECT url FROM octopi WHERE id=1")
59
+ index = connection.indexes(:octopi).first
60
+ assert index.columns.include?("url")
61
+ assert_equal 'index_octopi_on_url', index.name
62
+ end
63
+
64
+ def test_rename_table_does_not_rename_custom_named_index
65
+ add_index :test_models, :url, name: 'special_url_idx'
66
+
67
+ rename_table :test_models, :octopi
68
+
69
+ assert_equal ['special_url_idx'], connection.indexes(:octopi).map(&:name)
70
+ end
71
+ end
72
+
73
+ if current_adapter?(:PostgreSQLAdapter)
74
+ def test_rename_table_for_postgresql_should_also_rename_default_sequence
75
+ rename_table :test_models, :octopi
76
+
77
+ pk, seq = connection.pk_and_sequence_for('octopi')
78
+
79
+ assert_equal ConnectionAdapters::PostgreSQL::Name.new("public", "octopi_#{pk}_seq"), seq
80
+ end
81
+
82
+ def test_renaming_table_doesnt_attempt_to_rename_non_existent_sequences
83
+ connection.create_table :cats, id: :uuid
84
+ assert_nothing_raised { rename_table :cats, :felines }
85
+ ActiveSupport::Deprecation.silence { assert connection.table_exists? :felines }
86
+ ensure
87
+ connection.drop_table :cats, if_exists: true
88
+ connection.drop_table :felines, if_exists: true
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
@@ -1,1157 +1,1157 @@
1
- require 'cases/helper'
2
- require 'cases/migration/helper'
3
- require 'bigdecimal/util'
4
- require 'concurrent/atomic/count_down_latch'
5
-
6
- require 'models/person'
7
- require 'models/topic'
8
- require 'models/developer'
9
- require 'models/computer'
10
-
11
- require MIGRATIONS_ROOT + "/valid/2_we_need_reminders"
12
- require MIGRATIONS_ROOT + "/rename/1_we_need_things"
13
- require MIGRATIONS_ROOT + "/rename/2_rename_things"
14
- require MIGRATIONS_ROOT + "/decimal/1_give_me_big_numbers"
15
-
16
- class BigNumber < ActiveRecord::Base
17
- unless current_adapter?(:PostgreSQLAdapter, :SQLite3Adapter)
18
- attribute :value_of_e, :integer
19
- end
20
- attribute :my_house_population, :integer
21
- end
22
-
23
- class Reminder < ActiveRecord::Base; end
24
-
25
- class Thing < ActiveRecord::Base; end
26
-
27
- class MigrationTest < ActiveRecord::TestCase
28
- self.use_transactional_tests = false
29
-
30
- fixtures :people
31
-
32
- def setup
33
- super
34
- %w(reminders people_reminders prefix_reminders_suffix p_things_s).each do |table|
35
- Reminder.connection.drop_table(table) rescue nil
36
- end
37
- Reminder.reset_column_information
38
- @verbose_was, ActiveRecord::Migration.verbose = ActiveRecord::Migration.verbose, false
39
- ActiveRecord::Base.connection.schema_cache.clear!
40
- end
41
-
42
- teardown do
43
- ActiveRecord::Base.table_name_prefix = ""
44
- ActiveRecord::Base.table_name_suffix = ""
45
-
46
- ActiveRecord::Base.connection.initialize_schema_migrations_table
47
- ActiveRecord::Base.connection.execute "DELETE FROM #{ActiveRecord::Migrator.schema_migrations_table_name}"
48
-
49
- %w(things awesome_things prefix_things_suffix p_awesome_things_s ).each do |table|
50
- Thing.connection.drop_table(table) rescue nil
51
- end
52
- Thing.reset_column_information
53
-
54
- %w(reminders people_reminders prefix_reminders_suffix).each do |table|
55
- Reminder.connection.drop_table(table) rescue nil
56
- end
57
- Reminder.reset_table_name
58
- Reminder.reset_column_information
59
-
60
- %w(last_name key bio age height wealth birthday favorite_day
61
- moment_of_truth male administrator funny).each do |column|
62
- Person.connection.remove_column('people', column) rescue nil
63
- end
64
- Person.connection.remove_column("people", "first_name") rescue nil
65
- Person.connection.remove_column("people", "middle_name") rescue nil
66
- Person.connection.add_column("people", "first_name", :string)
67
- Person.reset_column_information
68
-
69
- ActiveRecord::Migration.verbose = @verbose_was
70
- end
71
-
72
- def test_migration_version_matches_component_version
73
- assert_equal ActiveRecord::VERSION::STRING.to_f, ActiveRecord::Migration.current_version
74
- end
75
-
76
- def test_migrator_versions
77
- migrations_path = MIGRATIONS_ROOT + "/valid"
78
- old_path = ActiveRecord::Migrator.migrations_paths
79
- ActiveRecord::Migrator.migrations_paths = migrations_path
80
-
81
- ActiveRecord::Migrator.up(migrations_path)
82
- assert_equal 3, ActiveRecord::Migrator.current_version
83
- assert_equal false, ActiveRecord::Migrator.needs_migration?
84
-
85
- ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid")
86
- assert_equal 0, ActiveRecord::Migrator.current_version
87
- assert_equal true, ActiveRecord::Migrator.needs_migration?
88
-
89
- ActiveRecord::SchemaMigration.create!(version: 3)
90
- assert_equal true, ActiveRecord::Migrator.needs_migration?
91
- ensure
92
- ActiveRecord::Migrator.migrations_paths = old_path
93
- end
94
-
95
- def test_migration_detection_without_schema_migration_table
96
- ActiveRecord::Base.connection.drop_table 'schema_migrations'
97
- #, if_exists: true
98
-
99
- migrations_path = MIGRATIONS_ROOT + "/valid"
100
- old_path = ActiveRecord::Migrator.migrations_paths
101
- ActiveRecord::Migrator.migrations_paths = migrations_path
102
-
103
- assert_equal true, ActiveRecord::Migrator.needs_migration?
104
- ensure
105
- ActiveRecord::Migrator.migrations_paths = old_path
106
- end
107
-
108
- def test_any_migrations
109
- old_path = ActiveRecord::Migrator.migrations_paths
110
- ActiveRecord::Migrator.migrations_paths = MIGRATIONS_ROOT + "/valid"
111
-
112
- assert ActiveRecord::Migrator.any_migrations?
113
-
114
- ActiveRecord::Migrator.migrations_paths = MIGRATIONS_ROOT + "/empty"
115
-
116
- assert_not ActiveRecord::Migrator.any_migrations?
117
- ensure
118
- ActiveRecord::Migrator.migrations_paths = old_path
119
- end
120
-
121
- def test_migration_version
122
- assert_nothing_raised { ActiveRecord::Migrator.run(:up, MIGRATIONS_ROOT + "/version_check", 20131219224947) }
123
- end
124
-
125
- def test_create_table_with_force_true_does_not_drop_nonexisting_table
126
- # using a copy as we need the drop_table method to
127
- # continue to work for the ensure block of the test
128
- temp_conn = Person.connection.dup
129
-
130
- assert_not_equal temp_conn, Person.connection
131
-
132
- temp_conn.create_table :testings2, :force => true do |t|
133
- t.column :foo, :string
134
- end
135
- ensure
136
- Person.connection.drop_table :testings2
137
- #, if_exists: true
138
- end
139
-
140
- def test_migration_instance_has_connection
141
- migration = Class.new(ActiveRecord::Migration::Current).new
142
- assert_equal ActiveRecord::Base.connection, migration.connection
143
- end
144
-
145
- def test_method_missing_delegates_to_connection
146
- migration = Class.new(ActiveRecord::Migration::Current) {
147
- def connection
148
- Class.new {
149
- def create_table; "hi mom!"; end
150
- }.new
151
- end
152
- }.new
153
-
154
- assert_equal "hi mom!", migration.method_missing(:create_table)
155
- end
156
-
157
- def test_add_table_with_decimals
158
- Person.connection.drop_table :big_numbers rescue nil
159
-
160
- assert !BigNumber.table_exists?
161
- GiveMeBigNumbers.up
162
- BigNumber.reset_column_information
163
-
164
- assert BigNumber.create(
165
- :bank_balance => 1586.43,
166
- :big_bank_balance => BigDecimal("1000234000567.95"),
167
- :world_population => 6000000000,
168
- :my_house_population => 3,
169
- :value_of_e => BigDecimal("2.7182818284590452353602875")
170
- )
171
-
172
- b = BigNumber.first
173
- assert_not_nil b
174
-
175
- assert_not_nil b.bank_balance
176
- assert_not_nil b.big_bank_balance
177
- assert_not_nil b.world_population
178
- assert_not_nil b.my_house_population
179
- assert_not_nil b.value_of_e
180
-
181
- # TODO: set world_population >= 2**62 to cover 64-bit platforms and test
182
- # is_a?(Bignum)
183
- assert_kind_of Integer, b.world_population
184
- assert_equal 6000000000, b.world_population
185
- assert_kind_of Integer, b.my_house_population
186
- assert_equal 3, b.my_house_population
187
- assert_kind_of BigDecimal, b.bank_balance
188
- assert_equal BigDecimal("1586.43"), b.bank_balance
189
- assert_kind_of BigDecimal, b.big_bank_balance
190
- assert_equal BigDecimal("1000234000567.95"), b.big_bank_balance
191
-
192
- # This one is fun. The 'value_of_e' field is defined as 'DECIMAL' with
193
- # precision/scale explicitly left out. By the SQL standard, numbers
194
- # assigned to this field should be truncated but that's seldom respected.
195
- if current_adapter?(:PostgreSQLAdapter)
196
- # - PostgreSQL changes the SQL spec on columns declared simply as
197
- # "decimal" to something more useful: instead of being given a scale
198
- # of 0, they take on the compile-time limit for precision and scale,
199
- # so the following should succeed unless you have used really wacky
200
- # compilation options
201
- assert_kind_of BigDecimal, b.value_of_e
202
- assert_equal BigDecimal("2.7182818284590452353602875"), b.value_of_e
203
- elsif current_adapter?(:SQLite3Adapter)
204
- # - SQLite3 stores a float, in violation of SQL
205
- assert_kind_of BigDecimal, b.value_of_e
206
- assert_in_delta BigDecimal("2.71828182845905"), b.value_of_e, 0.00000000000001
207
- else
208
- # - SQL standard is an integer
209
- assert_kind_of Integer, b.value_of_e
210
- assert_equal 2, b.value_of_e
211
- end
212
-
213
- GiveMeBigNumbers.down
214
- assert_raise(ActiveRecord::StatementInvalid) { BigNumber.first }
215
- end
216
-
217
- def test_filtering_migrations
218
- assert_no_column Person, :last_name
219
- assert !Reminder.table_exists?
220
-
221
- name_filter = lambda { |migration| migration.name == "ValidPeopleHaveLastNames" }
222
- ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", &name_filter)
223
-
224
- assert_column Person, :last_name
225
- assert_raise(ActiveRecord::StatementInvalid) { Reminder.first }
226
-
227
- ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", &name_filter)
228
-
229
- assert_no_column Person, :last_name
230
- assert_raise(ActiveRecord::StatementInvalid) { Reminder.first }
231
- end
232
-
233
- class MockMigration < ActiveRecord::Migration::Current
234
- attr_reader :went_up, :went_down
235
- def initialize
236
- @went_up = false
237
- @went_down = false
238
- end
239
-
240
- def up
241
- @went_up = true
242
- super
243
- end
244
-
245
- def down
246
- @went_down = true
247
- super
248
- end
249
- end
250
-
251
- def test_instance_based_migration_up
252
- migration = MockMigration.new
253
- assert !migration.went_up, 'have not gone up'
254
- assert !migration.went_down, 'have not gone down'
255
-
256
- migration.migrate :up
257
- assert migration.went_up, 'have gone up'
258
- assert !migration.went_down, 'have not gone down'
259
- end
260
-
261
- def test_instance_based_migration_down
262
- migration = MockMigration.new
263
- assert !migration.went_up, 'have not gone up'
264
- assert !migration.went_down, 'have not gone down'
265
-
266
- migration.migrate :down
267
- assert !migration.went_up, 'have gone up'
268
- assert migration.went_down, 'have not gone down'
269
- end
270
-
271
- if ActiveRecord::Base.connection.supports_ddl_transactions?
272
- def test_migrator_one_up_with_exception_and_rollback
273
- assert_no_column Person, :last_name
274
-
275
- migration = Class.new(ActiveRecord::Migration::Current) {
276
- def version; 100 end
277
- def migrate(x)
278
- add_column "people", "last_name", :string
279
- raise 'Something broke'
280
- end
281
- }.new
282
-
283
- migrator = ActiveRecord::Migrator.new(:up, [migration], 100)
284
-
285
- e = assert_raise(StandardError) { migrator.migrate }
286
-
287
- assert_equal "An error has occurred, this and all later migrations canceled:\n\nSomething broke", e.message
288
-
289
- assert_no_column Person, :last_name,
290
- "On error, the Migrator should revert schema changes but it did not."
291
- end
292
-
293
- def test_migrator_one_up_with_exception_and_rollback_using_run
294
- assert_no_column Person, :last_name
295
-
296
- migration = Class.new(ActiveRecord::Migration::Current) {
297
- def version; 100 end
298
- def migrate(x)
299
- add_column "people", "last_name", :string
300
- raise 'Something broke'
301
- end
302
- }.new
303
-
304
- migrator = ActiveRecord::Migrator.new(:up, [migration], 100)
305
-
306
- e = assert_raise(StandardError) { migrator.run }
307
-
308
- assert_equal "An error has occurred, this and all later migrations canceled:\n\nSomething broke", e.message
309
-
310
- assert_no_column Person, :last_name,
311
- "On error, the Migrator should revert schema changes but it did not."
312
- end
313
-
314
- def test_migration_without_transaction
315
- assert_no_column Person, :last_name
316
-
317
- migration = Class.new(ActiveRecord::Migration::Current) {
318
- self.disable_ddl_transaction!
319
-
320
- def version; 101 end
321
- def migrate(x)
322
- add_column "people", "last_name", :string
323
- raise 'Something broke'
324
- end
325
- }.new
326
-
327
- migrator = ActiveRecord::Migrator.new(:up, [migration], 101)
328
- e = assert_raise(StandardError) { migrator.migrate }
329
- assert_equal "An error has occurred, all later migrations canceled:\n\nSomething broke", e.message
330
-
331
- assert_column Person, :last_name,
332
- "without ddl transactions, the Migrator should not rollback on error but it did."
333
- ensure
334
- Person.reset_column_information
335
- if Person.column_names.include?('last_name')
336
- Person.connection.remove_column('people', 'last_name')
337
- end
338
- end
339
- end
340
-
341
- def test_schema_migrations_table_name
342
- original_schema_migrations_table_name = ActiveRecord::Migrator.schema_migrations_table_name
343
-
344
- assert_equal "schema_migrations", ActiveRecord::Migrator.schema_migrations_table_name
345
- ActiveRecord::Base.table_name_prefix = "prefix_"
346
- ActiveRecord::Base.table_name_suffix = "_suffix"
347
- Reminder.reset_table_name
348
- assert_equal "prefix_schema_migrations_suffix", ActiveRecord::Migrator.schema_migrations_table_name
349
- ActiveRecord::Base.schema_migrations_table_name = "changed"
350
- Reminder.reset_table_name
351
- assert_equal "prefix_changed_suffix", ActiveRecord::Migrator.schema_migrations_table_name
352
- ActiveRecord::Base.table_name_prefix = ""
353
- ActiveRecord::Base.table_name_suffix = ""
354
- Reminder.reset_table_name
355
- assert_equal "changed", ActiveRecord::Migrator.schema_migrations_table_name
356
- ensure
357
- ActiveRecord::Base.schema_migrations_table_name = original_schema_migrations_table_name
358
- Reminder.reset_table_name
359
- end
360
-
361
- def test_internal_metadata_table_name
362
- original_internal_metadata_table_name = ActiveRecord::Base.internal_metadata_table_name
363
-
364
- assert_equal "ar_internal_metadata", ActiveRecord::InternalMetadata.table_name
365
- ActiveRecord::Base.table_name_prefix = "p_"
366
- ActiveRecord::Base.table_name_suffix = "_s"
367
- Reminder.reset_table_name
368
- assert_equal "p_ar_internal_metadata_s", ActiveRecord::InternalMetadata.table_name
369
- ActiveRecord::Base.internal_metadata_table_name = "changed"
370
- Reminder.reset_table_name
371
- assert_equal "p_changed_s", ActiveRecord::InternalMetadata.table_name
372
- ActiveRecord::Base.table_name_prefix = ""
373
- ActiveRecord::Base.table_name_suffix = ""
374
- Reminder.reset_table_name
375
- assert_equal "changed", ActiveRecord::InternalMetadata.table_name
376
- ensure
377
- ActiveRecord::Base.internal_metadata_table_name = original_internal_metadata_table_name
378
- Reminder.reset_table_name
379
- end
380
-
381
- def test_internal_metadata_stores_environment
382
- current_env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
383
- migrations_path = MIGRATIONS_ROOT + "/valid"
384
- old_path = ActiveRecord::Migrator.migrations_paths
385
- ActiveRecord::Migrator.migrations_paths = migrations_path
386
-
387
- ActiveRecord::Migrator.up(migrations_path)
388
- assert_equal current_env, ActiveRecord::InternalMetadata[:environment]
389
-
390
- original_rails_env = ENV["RAILS_ENV"]
391
- original_rack_env = ENV["RACK_ENV"]
392
- ENV["RAILS_ENV"] = ENV["RACK_ENV"] = "foofoo"
393
- new_env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
394
-
395
- refute_equal current_env, new_env
396
-
397
- sleep 1 # mysql by default does not store fractional seconds in the database
398
- ActiveRecord::Migrator.up(migrations_path)
399
- assert_equal new_env, ActiveRecord::InternalMetadata[:environment]
400
- ensure
401
- ActiveRecord::Migrator.migrations_paths = old_path
402
- ENV["RAILS_ENV"] = original_rails_env
403
- ENV["RACK_ENV"] = original_rack_env
404
- end
405
-
406
-
407
- def test_migration_sets_internal_metadata_even_when_fully_migrated
408
- current_env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
409
- migrations_path = MIGRATIONS_ROOT + "/valid"
410
- old_path = ActiveRecord::Migrator.migrations_paths
411
- ActiveRecord::Migrator.migrations_paths = migrations_path
412
-
413
- ActiveRecord::Migrator.up(migrations_path)
414
- assert_equal current_env, ActiveRecord::InternalMetadata[:environment]
415
-
416
- original_rails_env = ENV["RAILS_ENV"]
417
- original_rack_env = ENV["RACK_ENV"]
418
- ENV["RAILS_ENV"] = ENV["RACK_ENV"] = "foofoo"
419
- new_env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
420
-
421
- refute_equal current_env, new_env
422
-
423
- sleep 1 # mysql by default does not store fractional seconds in the database
424
-
425
- ActiveRecord::Migrator.up(migrations_path)
426
- assert_equal new_env, ActiveRecord::InternalMetadata[:environment]
427
- ensure
428
- ActiveRecord::Migrator.migrations_paths = old_path
429
- ENV["RAILS_ENV"] = original_rails_env
430
- ENV["RACK_ENV"] = original_rack_env
431
- end
432
-
433
- def test_internal_metadata_stores_environment_when_other_data_exists
434
- ActiveRecord::InternalMetadata.delete_all
435
- ActiveRecord::InternalMetadata[:foo] = 'bar'
436
-
437
- current_env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
438
- migrations_path = MIGRATIONS_ROOT + "/valid"
439
- old_path = ActiveRecord::Migrator.migrations_paths
440
- ActiveRecord::Migrator.migrations_paths = migrations_path
441
-
442
- current_env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
443
- ActiveRecord::Migrator.up(migrations_path)
444
- assert_equal current_env, ActiveRecord::InternalMetadata[:environment]
445
- assert_equal 'bar', ActiveRecord::InternalMetadata[:foo]
446
- ensure
447
- ActiveRecord::Migrator.migrations_paths = old_path
448
- end
449
-
450
- def test_rename_internal_metadata_table
451
- original_internal_metadata_table_name = ActiveRecord::Base.internal_metadata_table_name
452
-
453
- ActiveRecord::Base.internal_metadata_table_name = "active_record_internal_metadatas"
454
- Reminder.reset_table_name
455
-
456
- ActiveRecord::Base.internal_metadata_table_name = original_internal_metadata_table_name
457
- Reminder.reset_table_name
458
-
459
- assert_equal "ar_internal_metadata", ActiveRecord::InternalMetadata.table_name
460
- ensure
461
- ActiveRecord::Base.internal_metadata_table_name = original_internal_metadata_table_name
462
- Reminder.reset_table_name
463
- end
464
-
465
- def test_proper_table_name_on_migration
466
- reminder_class = new_isolated_reminder_class
467
- migration = ActiveRecord::Migration.new
468
- assert_equal "table", migration.proper_table_name('table')
469
- assert_equal "table", migration.proper_table_name(:table)
470
- assert_equal "reminders", migration.proper_table_name(reminder_class)
471
- reminder_class.reset_table_name
472
- assert_equal reminder_class.table_name, migration.proper_table_name(reminder_class)
473
-
474
- # Use the model's own prefix/suffix if a model is given
475
- ActiveRecord::Base.table_name_prefix = "ARprefix_"
476
- ActiveRecord::Base.table_name_suffix = "_ARsuffix"
477
- reminder_class.table_name_prefix = 'prefix_'
478
- reminder_class.table_name_suffix = '_suffix'
479
- reminder_class.reset_table_name
480
- assert_equal "prefix_reminders_suffix", migration.proper_table_name(reminder_class)
481
- reminder_class.table_name_prefix = ''
482
- reminder_class.table_name_suffix = ''
483
- reminder_class.reset_table_name
484
-
485
- # Use AR::Base's prefix/suffix if string or symbol is given
486
- ActiveRecord::Base.table_name_prefix = "prefix_"
487
- ActiveRecord::Base.table_name_suffix = "_suffix"
488
- reminder_class.reset_table_name
489
- assert_equal "prefix_table_suffix", migration.proper_table_name('table', migration.table_name_options)
490
- assert_equal "prefix_table_suffix", migration.proper_table_name(:table, migration.table_name_options)
491
- end
492
-
493
- def test_rename_table_with_prefix_and_suffix
494
- assert !Thing.table_exists?
495
- ActiveRecord::Base.table_name_prefix = 'p_'
496
- ActiveRecord::Base.table_name_suffix = '_s'
497
- Thing.reset_table_name
498
- Thing.reset_sequence_name
499
- WeNeedThings.up
500
- Thing.reset_column_information
501
-
502
- assert Thing.create("content" => "hello world")
503
- assert_equal "hello world", Thing.first.content
504
-
505
- RenameThings.up
506
- Thing.table_name = "p_awesome_things_s"
507
-
508
- assert_equal "hello world", Thing.first.content
509
- ensure
510
- Thing.reset_table_name
511
- Thing.reset_sequence_name
512
- end
513
-
514
- def test_add_drop_table_with_prefix_and_suffix
515
- assert !Reminder.table_exists?
516
- ActiveRecord::Base.table_name_prefix = 'prefix_'
517
- ActiveRecord::Base.table_name_suffix = '_suffix'
518
- Reminder.reset_table_name
519
- Reminder.reset_sequence_name
520
- Reminder.reset_column_information
521
- WeNeedReminders.up
522
- assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
523
- assert_equal "hello world", Reminder.first.content
524
-
525
- WeNeedReminders.down
526
- assert_raise(ActiveRecord::StatementInvalid) { Reminder.first }
527
- ensure
528
- Reminder.reset_sequence_name
529
- end
530
-
531
- def test_create_table_with_binary_column
532
- assert_nothing_raised {
533
- Person.connection.create_table :binary_testings do |t|
534
- t.column "data", :binary, :null => false
535
- end
536
- }
537
-
538
- columns = Person.connection.columns(:binary_testings)
539
- data_column = columns.detect { |c| c.name == "data" }
540
-
541
- assert_nil data_column.default
542
- ensure
543
- Person.connection.drop_table :binary_testings
544
- #, if_exists: true
545
- end
546
-
547
- unless mysql_enforcing_gtid_consistency?
548
- def test_create_table_with_query
549
- Person.connection.create_table(:person, force: true)
550
-
551
- Person.connection.create_table :table_from_query_testings, as: "SELECT id FROM person"
552
-
553
- columns = Person.connection.columns(:table_from_query_testings)
554
- assert_equal 1, columns.length
555
- assert_equal "id", columns.first.name
556
- ensure
557
- Person.connection.drop_table :table_from_query_testings rescue nil
558
- end
559
-
560
- def test_create_table_with_query_from_relation
561
- Person.connection.create_table(:person, force: true)
562
-
563
- Person.connection.create_table :table_from_query_testings, as: Person.select(:id)
564
-
565
- columns = Person.connection.columns(:table_from_query_testings)
566
- assert_equal 1, columns.length
567
- assert_equal "id", columns.first.name
568
- ensure
569
- Person.connection.drop_table :table_from_query_testings rescue nil
570
- end
571
- end
572
-
573
- if current_adapter?(:SQLite3Adapter)
574
- def test_allows_sqlite3_rollback_on_invalid_column_type
575
- Person.connection.create_table :something, force: true do |t|
576
- t.column :number, :integer
577
- t.column :name, :string
578
- t.column :foo, :bar
579
- end
580
- assert Person.connection.column_exists?(:something, :foo)
581
- assert_nothing_raised { Person.connection.remove_column :something, :foo, :bar }
582
- assert !Person.connection.column_exists?(:something, :foo)
583
- assert Person.connection.column_exists?(:something, :name)
584
- assert Person.connection.column_exists?(:something, :number)
585
- ensure
586
- Person.connection.drop_table :something
587
- #, if_exists: true
588
- end
589
- end
590
-
591
- if current_adapter? :OracleAdapter
592
- def test_create_table_with_custom_sequence_name
593
- # table name is 29 chars, the standard sequence name will
594
- # be 33 chars and should be shortened
595
- assert_nothing_raised do
596
- begin
597
- Person.connection.create_table :table_with_name_thats_just_ok do |t|
598
- t.column :foo, :string, :null => false
599
- end
600
- ensure
601
- Person.connection.drop_table :table_with_name_thats_just_ok rescue nil
602
- end
603
- end
604
-
605
- # should be all good w/ a custom sequence name
606
- assert_nothing_raised do
607
- begin
608
- Person.connection.create_table :table_with_name_thats_just_ok,
609
- :sequence_name => 'suitably_short_seq' do |t|
610
- t.column :foo, :string, :null => false
611
- end
612
-
613
- Person.connection.execute("select suitably_short_seq.nextval from dual")
614
-
615
- ensure
616
- Person.connection.drop_table :table_with_name_thats_just_ok,
617
- :sequence_name => 'suitably_short_seq' rescue nil
618
- end
619
- end
620
-
621
- # confirm the custom sequence got dropped
622
- assert_raise(ActiveRecord::StatementInvalid) do
623
- Person.connection.execute("select suitably_short_seq.nextval from dual")
624
- end
625
- end
626
- end
627
-
628
- if current_adapter?(:Mysql2Adapter, :PostgreSQLAdapter)
629
- def test_out_of_range_integer_limit_should_raise
630
- e = assert_raise(ActiveRecord::ActiveRecordError, "integer limit didn't raise") do
631
- Person.connection.create_table :test_integer_limits, :force => true do |t|
632
- t.column :bigone, :integer, :limit => 10
633
- end
634
- end
635
-
636
- assert_match(/No integer type has byte size 10/, e.message)
637
- ensure
638
- Person.connection.drop_table :test_integer_limits
639
- #, if_exists: true
640
- end
641
- end
642
-
643
- if current_adapter?(:Mysql2Adapter)
644
- def test_out_of_range_text_limit_should_raise
645
- e = assert_raise(ActiveRecord::ActiveRecordError, "text limit didn't raise") do
646
- Person.connection.create_table :test_text_limits, force: true do |t|
647
- t.text :bigtext, limit: 0xfffffffff
648
- end
649
- end
650
-
651
- assert_match(/No text type has byte length #{0xfffffffff}/, e.message)
652
- ensure
653
- Person.connection.drop_table :test_text_limits
654
- #, if_exists: true
655
- end
656
- end
657
-
658
- if ActiveRecord::Base.connection.supports_advisory_locks?
659
- def test_migrator_generates_valid_lock_id
660
- migration = Class.new(ActiveRecord::Migration::Current).new
661
- migrator = ActiveRecord::Migrator.new(:up, [migration], 100)
662
-
663
- lock_id = migrator.send(:generate_migrator_advisory_lock_id)
664
-
665
- assert ActiveRecord::Base.connection.get_advisory_lock(lock_id),
666
- "the Migrator should have generated a valid lock id, but it didn't"
667
- assert ActiveRecord::Base.connection.release_advisory_lock(lock_id),
668
- "the Migrator should have generated a valid lock id, but it didn't"
669
- end
670
-
671
- def test_generate_migrator_advisory_lock_id
672
- # It is important we are consistent with how we generate this so that
673
- # exclusive locking works across migrator versions
674
- migration = Class.new(ActiveRecord::Migration::Current).new
675
- migrator = ActiveRecord::Migrator.new(:up, [migration], 100)
676
-
677
- lock_id = migrator.send(:generate_migrator_advisory_lock_id)
678
-
679
- current_database = ActiveRecord::Base.connection.current_database
680
- salt = ActiveRecord::Migrator::MIGRATOR_SALT
681
- expected_id = Zlib.crc32(current_database) * salt
682
-
683
- assert lock_id == expected_id, "expected lock id generated by the migrator to be #{expected_id}, but it was #{lock_id} instead"
684
- assert lock_id.bit_length <= 63, "lock id must be a signed integer of max 63 bits magnitude"
685
- end
686
-
687
- def test_migrator_one_up_with_unavailable_lock
688
- assert_no_column Person, :last_name
689
-
690
- migration = Class.new(ActiveRecord::Migration::Current) {
691
- def version; 100 end
692
- def migrate(x)
693
- add_column "people", "last_name", :string
694
- end
695
- }.new
696
-
697
- migrator = ActiveRecord::Migrator.new(:up, [migration], 100)
698
- lock_id = migrator.send(:generate_migrator_advisory_lock_id)
699
-
700
- with_another_process_holding_lock(lock_id) do
701
- assert_raise(ActiveRecord::ConcurrentMigrationError) { migrator.migrate }
702
- end
703
-
704
- assert_no_column Person, :last_name,
705
- "without an advisory lock, the Migrator should not make any changes, but it did."
706
- end
707
-
708
- def test_migrator_one_up_with_unavailable_lock_using_run
709
- assert_no_column Person, :last_name
710
-
711
- migration = Class.new(ActiveRecord::Migration::Current) {
712
- def version; 100 end
713
- def migrate(x)
714
- add_column "people", "last_name", :string
715
- end
716
- }.new
717
-
718
- migrator = ActiveRecord::Migrator.new(:up, [migration], 100)
719
- lock_id = migrator.send(:generate_migrator_advisory_lock_id)
720
-
721
- with_another_process_holding_lock(lock_id) do
722
- assert_raise(ActiveRecord::ConcurrentMigrationError) { migrator.run }
723
- end
724
-
725
- assert_no_column Person, :last_name,
726
- "without an advisory lock, the Migrator should not make any changes, but it did."
727
- end
728
- end
729
-
730
- protected
731
- # This is needed to isolate class_attribute assignments like `table_name_prefix`
732
- # for each test case.
733
- def new_isolated_reminder_class
734
- Class.new(Reminder) {
735
- def self.name; "Reminder"; end
736
- def self.base_class; self; end
737
- }
738
- end
739
-
740
- def with_another_process_holding_lock(lock_id)
741
- thread_lock = Concurrent::CountDownLatch.new
742
- test_terminated = Concurrent::CountDownLatch.new
743
-
744
- other_process = Thread.new do
745
- begin
746
- conn = ActiveRecord::Base.connection_pool.checkout
747
- conn.get_advisory_lock(lock_id)
748
- thread_lock.count_down
749
- test_terminated.wait # hold the lock open until we tested everything
750
- ensure
751
- conn.release_advisory_lock(lock_id)
752
- ActiveRecord::Base.connection_pool.checkin(conn)
753
- end
754
- end
755
-
756
- thread_lock.wait # wait until the 'other process' has the lock
757
-
758
- yield
759
-
760
- test_terminated.count_down
761
- other_process.join
762
- end
763
- end
764
-
765
- class ReservedWordsMigrationTest < ActiveRecord::TestCase
766
- def test_drop_index_from_table_named_values
767
- connection = Person.connection
768
- connection.create_table :values, :force => true do |t|
769
- t.integer :value
770
- end
771
-
772
- assert_nothing_raised do
773
- connection.add_index :values, :value
774
- connection.remove_index :values, :column => :value
775
- end
776
- ensure
777
- connection.drop_table :values rescue nil
778
- end
779
- end
780
-
781
- class ExplicitlyNamedIndexMigrationTest < ActiveRecord::TestCase
782
- def test_drop_index_by_name
783
- connection = Person.connection
784
- connection.create_table :values, force: true do |t|
785
- t.integer :value
786
- end
787
-
788
- assert_nothing_raised do
789
- connection.add_index :values, :value, name: 'a_different_name'
790
- connection.remove_index :values, column: :value, name: 'a_different_name'
791
- end
792
- ensure
793
- connection.drop_table :values rescue nil
794
- end
795
- end
796
-
797
- if ActiveRecord::Base.connection.supports_bulk_alter?
798
- class BulkAlterTableMigrationsTest < ActiveRecord::TestCase
799
- def setup
800
- @connection = Person.connection
801
- @connection.create_table(:delete_me, :force => true) {|t| }
802
- Person.reset_column_information
803
- Person.reset_sequence_name
804
- end
805
-
806
- teardown do
807
- Person.connection.drop_table(:delete_me) rescue nil
808
- end
809
-
810
- def test_adding_multiple_columns
811
- assert_queries(1) do
812
- with_bulk_change_table do |t|
813
- t.column :name, :string
814
- t.string :qualification, :experience
815
- t.integer :age, :default => 0
816
- t.date :birthdate
817
- t.timestamps null: true
818
- end
819
- end
820
-
821
- assert_equal 8, columns.size
822
- [:name, :qualification, :experience].each {|s| assert_equal :string, column(s).type }
823
- assert_equal '0', column(:age).default
824
- end
825
-
826
- def test_removing_columns
827
- with_bulk_change_table do |t|
828
- t.string :qualification, :experience
829
- end
830
-
831
- [:qualification, :experience].each {|c| assert column(c) }
832
-
833
- assert_queries(1) do
834
- with_bulk_change_table do |t|
835
- t.remove :qualification, :experience
836
- t.string :qualification_experience
837
- end
838
- end
839
-
840
- [:qualification, :experience].each {|c| assert ! column(c) }
841
- assert column(:qualification_experience)
842
- end
843
-
844
- def test_adding_indexes
845
- with_bulk_change_table do |t|
846
- t.string :username
847
- t.string :name
848
- t.integer :age
849
- end
850
-
851
- # Adding an index fires a query every time to check if an index already exists or not
852
- assert_queries(3) do
853
- with_bulk_change_table do |t|
854
- t.index :username, :unique => true, :name => :awesome_username_index
855
- t.index [:name, :age]
856
- end
857
- end
858
-
859
- assert_equal 2, indexes.size
860
-
861
- name_age_index = index(:index_delete_me_on_name_and_age)
862
- assert_equal ['name', 'age'].sort, name_age_index.columns.sort
863
- assert ! name_age_index.unique
864
-
865
- assert index(:awesome_username_index).unique
866
- end
867
-
868
- def test_removing_index
869
- with_bulk_change_table do |t|
870
- t.string :name
871
- t.index :name
872
- end
873
-
874
- assert index(:index_delete_me_on_name)
875
-
876
- assert_queries(3) do
877
- with_bulk_change_table do |t|
878
- t.remove_index :name
879
- t.index :name, :name => :new_name_index, :unique => true
880
- end
881
- end
882
-
883
- assert ! index(:index_delete_me_on_name)
884
-
885
- new_name_index = index(:new_name_index)
886
- assert new_name_index.unique
887
- end
888
-
889
- def test_changing_columns
890
- with_bulk_change_table do |t|
891
- t.string :name
892
- t.date :birthdate
893
- end
894
-
895
- assert ! column(:name).default
896
- assert_equal :date, column(:birthdate).type
897
-
898
- # One query for columns (delete_me table)
899
- # One query for primary key (delete_me table)
900
- # One query to do the bulk change
901
- assert_queries(3, :ignore_none => true) do
902
- with_bulk_change_table do |t|
903
- t.change :name, :string, :default => 'NONAME'
904
- t.change :birthdate, :datetime
905
- end
906
- end
907
-
908
- assert_equal 'NONAME', column(:name).default
909
- assert_equal :datetime, column(:birthdate).type
910
- end
911
-
912
- protected
913
-
914
- def with_bulk_change_table
915
- # Reset columns/indexes cache as we're changing the table
916
- @columns = @indexes = nil
917
-
918
- Person.connection.change_table(:delete_me, :bulk => true) do |t|
919
- yield t
920
- end
921
- end
922
-
923
- def column(name)
924
- columns.detect {|c| c.name == name.to_s }
925
- end
926
-
927
- def columns
928
- @columns ||= Person.connection.columns('delete_me')
929
- end
930
-
931
- def index(name)
932
- indexes.detect {|i| i.name == name.to_s }
933
- end
934
-
935
- def indexes
936
- @indexes ||= Person.connection.indexes('delete_me')
937
- end
938
- end # AlterTableMigrationsTest
939
-
940
- end
941
-
942
- class CopyMigrationsTest < ActiveRecord::TestCase
943
- include ActiveSupport::Testing::Stream
944
-
945
- def setup
946
- end
947
-
948
- def clear
949
- ActiveRecord::Base.timestamped_migrations = true
950
- to_delete = Dir[@migrations_path + "/*.rb"] - @existing_migrations
951
- File.delete(*to_delete)
952
- end
953
-
954
- def test_copying_migrations_without_timestamps
955
- ActiveRecord::Base.timestamped_migrations = false
956
- @migrations_path = MIGRATIONS_ROOT + "/valid"
957
- @existing_migrations = Dir[@migrations_path + "/*.rb"]
958
-
959
- copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy"})
960
- assert File.exist?(@migrations_path + "/4_people_have_hobbies.bukkits.rb")
961
- assert File.exist?(@migrations_path + "/5_people_have_descriptions.bukkits.rb")
962
- assert_equal [@migrations_path + "/4_people_have_hobbies.bukkits.rb", @migrations_path + "/5_people_have_descriptions.bukkits.rb"], copied.map(&:filename)
963
-
964
- expected = "# This migration comes from bukkits (originally 1)"
965
- assert_equal expected, IO.readlines(@migrations_path + "/4_people_have_hobbies.bukkits.rb")[0].chomp
966
-
967
- files_count = Dir[@migrations_path + "/*.rb"].length
968
- copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy"})
969
- assert_equal files_count, Dir[@migrations_path + "/*.rb"].length
970
- assert copied.empty?
971
- ensure
972
- clear
973
- end
974
-
975
- def test_copying_migrations_without_timestamps_from_2_sources
976
- ActiveRecord::Base.timestamped_migrations = false
977
- @migrations_path = MIGRATIONS_ROOT + "/valid"
978
- @existing_migrations = Dir[@migrations_path + "/*.rb"]
979
-
980
- sources = {}
981
- sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy"
982
- sources[:omg] = MIGRATIONS_ROOT + "/to_copy2"
983
- ActiveRecord::Migration.copy(@migrations_path, sources)
984
- assert File.exist?(@migrations_path + "/4_people_have_hobbies.bukkits.rb")
985
- assert File.exist?(@migrations_path + "/5_people_have_descriptions.bukkits.rb")
986
- assert File.exist?(@migrations_path + "/6_create_articles.omg.rb")
987
- assert File.exist?(@migrations_path + "/7_create_comments.omg.rb")
988
-
989
- files_count = Dir[@migrations_path + "/*.rb"].length
990
- ActiveRecord::Migration.copy(@migrations_path, sources)
991
- assert_equal files_count, Dir[@migrations_path + "/*.rb"].length
992
- ensure
993
- clear
994
- end
995
-
996
- def test_copying_migrations_with_timestamps
997
- @migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps"
998
- @existing_migrations = Dir[@migrations_path + "/*.rb"]
999
-
1000
- travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do
1001
- copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
1002
- assert File.exist?(@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb")
1003
- assert File.exist?(@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb")
1004
- expected = [@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb",
1005
- @migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb"]
1006
- assert_equal expected, copied.map(&:filename)
1007
-
1008
- files_count = Dir[@migrations_path + "/*.rb"].length
1009
- copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
1010
- assert_equal files_count, Dir[@migrations_path + "/*.rb"].length
1011
- assert copied.empty?
1012
- end
1013
- ensure
1014
- clear
1015
- end
1016
-
1017
- def test_copying_migrations_with_timestamps_from_2_sources
1018
- @migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps"
1019
- @existing_migrations = Dir[@migrations_path + "/*.rb"]
1020
-
1021
- sources = {}
1022
- sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy_with_timestamps"
1023
- sources[:omg] = MIGRATIONS_ROOT + "/to_copy_with_timestamps2"
1024
-
1025
- travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do
1026
- copied = ActiveRecord::Migration.copy(@migrations_path, sources)
1027
- assert File.exist?(@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb")
1028
- assert File.exist?(@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb")
1029
- assert File.exist?(@migrations_path + "/20100726101012_create_articles.omg.rb")
1030
- assert File.exist?(@migrations_path + "/20100726101013_create_comments.omg.rb")
1031
- assert_equal 4, copied.length
1032
-
1033
- files_count = Dir[@migrations_path + "/*.rb"].length
1034
- ActiveRecord::Migration.copy(@migrations_path, sources)
1035
- assert_equal files_count, Dir[@migrations_path + "/*.rb"].length
1036
- end
1037
- ensure
1038
- clear
1039
- end
1040
-
1041
- def test_copying_migrations_with_timestamps_to_destination_with_timestamps_in_future
1042
- @migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps"
1043
- @existing_migrations = Dir[@migrations_path + "/*.rb"]
1044
-
1045
- travel_to(Time.utc(2010, 2, 20, 10, 10, 10)) do
1046
- ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
1047
- assert File.exist?(@migrations_path + "/20100301010102_people_have_hobbies.bukkits.rb")
1048
- assert File.exist?(@migrations_path + "/20100301010103_people_have_descriptions.bukkits.rb")
1049
-
1050
- files_count = Dir[@migrations_path + "/*.rb"].length
1051
- copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
1052
- assert_equal files_count, Dir[@migrations_path + "/*.rb"].length
1053
- assert copied.empty?
1054
- end
1055
- ensure
1056
- clear
1057
- end
1058
-
1059
- def test_copying_migrations_preserving_magic_comments
1060
- ActiveRecord::Base.timestamped_migrations = false
1061
- @migrations_path = MIGRATIONS_ROOT + "/valid"
1062
- @existing_migrations = Dir[@migrations_path + "/*.rb"]
1063
-
1064
- copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/magic"})
1065
- assert File.exist?(@migrations_path + "/4_currencies_have_symbols.bukkits.rb")
1066
- assert_equal [@migrations_path + "/4_currencies_have_symbols.bukkits.rb"], copied.map(&:filename)
1067
-
1068
- expected = "# coding: ISO-8859-15\n# This migration comes from bukkits (originally 1)"
1069
- assert_equal expected, IO.readlines(@migrations_path + "/4_currencies_have_symbols.bukkits.rb")[0..1].join.chomp
1070
-
1071
- files_count = Dir[@migrations_path + "/*.rb"].length
1072
- copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/magic"})
1073
- assert_equal files_count, Dir[@migrations_path + "/*.rb"].length
1074
- assert copied.empty?
1075
- ensure
1076
- clear
1077
- end
1078
-
1079
- def test_skipping_migrations
1080
- @migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps"
1081
- @existing_migrations = Dir[@migrations_path + "/*.rb"]
1082
-
1083
- sources = {}
1084
- sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy_with_timestamps"
1085
- sources[:omg] = MIGRATIONS_ROOT + "/to_copy_with_name_collision"
1086
-
1087
- skipped = []
1088
- on_skip = Proc.new { |name, migration| skipped << "#{name} #{migration.name}" }
1089
- copied = ActiveRecord::Migration.copy(@migrations_path, sources, :on_skip => on_skip)
1090
- assert_equal 2, copied.length
1091
-
1092
- assert_equal 1, skipped.length
1093
- assert_equal ["omg PeopleHaveHobbies"], skipped
1094
- ensure
1095
- clear
1096
- end
1097
-
1098
- def test_skip_is_not_called_if_migrations_are_from_the_same_plugin
1099
- @migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps"
1100
- @existing_migrations = Dir[@migrations_path + "/*.rb"]
1101
-
1102
- sources = {}
1103
- sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy_with_timestamps"
1104
-
1105
- skipped = []
1106
- on_skip = Proc.new { |name, migration| skipped << "#{name} #{migration.name}" }
1107
- copied = ActiveRecord::Migration.copy(@migrations_path, sources, :on_skip => on_skip)
1108
- ActiveRecord::Migration.copy(@migrations_path, sources, :on_skip => on_skip)
1109
-
1110
- assert_equal 2, copied.length
1111
- assert_equal 0, skipped.length
1112
- ensure
1113
- clear
1114
- end
1115
-
1116
- def test_copying_migrations_to_non_existing_directory
1117
- @migrations_path = MIGRATIONS_ROOT + "/non_existing"
1118
- @existing_migrations = []
1119
-
1120
- travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do
1121
- copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
1122
- assert File.exist?(@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb")
1123
- assert File.exist?(@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb")
1124
- assert_equal 2, copied.length
1125
- end
1126
- ensure
1127
- clear
1128
- Dir.delete(@migrations_path)
1129
- end
1130
-
1131
- def test_copying_migrations_to_empty_directory
1132
- @migrations_path = MIGRATIONS_ROOT + "/empty"
1133
- @existing_migrations = []
1134
-
1135
- travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do
1136
- copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
1137
- assert File.exist?(@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb")
1138
- assert File.exist?(@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb")
1139
- assert_equal 2, copied.length
1140
- end
1141
- ensure
1142
- clear
1143
- end
1144
-
1145
- def test_check_pending_with_stdlib_logger
1146
- old, ActiveRecord::Base.logger = ActiveRecord::Base.logger, ::Logger.new($stdout)
1147
- quietly do
1148
- assert_nothing_raised { ActiveRecord::Migration::CheckPending.new(Proc.new {}).call({}) }
1149
- end
1150
- ensure
1151
- ActiveRecord::Base.logger = old
1152
- end
1153
-
1154
- def test_unknown_migration_version_should_raise_an_argument_error
1155
- assert_raise(ArgumentError) { ActiveRecord::Migration[1.0] }
1156
- end
1157
- end
1
+ require 'cases/helper'
2
+ require 'cases/migration/helper'
3
+ require 'bigdecimal/util'
4
+ require 'concurrent/atomic/count_down_latch'
5
+
6
+ require 'models/person'
7
+ require 'models/topic'
8
+ require 'models/developer'
9
+ require 'models/computer'
10
+
11
+ require MIGRATIONS_ROOT + "/valid/2_we_need_reminders"
12
+ require MIGRATIONS_ROOT + "/rename/1_we_need_things"
13
+ require MIGRATIONS_ROOT + "/rename/2_rename_things"
14
+ require MIGRATIONS_ROOT + "/decimal/1_give_me_big_numbers"
15
+
16
+ class BigNumber < ActiveRecord::Base
17
+ unless current_adapter?(:PostgreSQLAdapter, :SQLite3Adapter)
18
+ attribute :value_of_e, :integer
19
+ end
20
+ attribute :my_house_population, :integer
21
+ end
22
+
23
+ class Reminder < ActiveRecord::Base; end
24
+
25
+ class Thing < ActiveRecord::Base; end
26
+
27
+ class MigrationTest < ActiveRecord::TestCase
28
+ self.use_transactional_tests = false
29
+
30
+ fixtures :people
31
+
32
+ def setup
33
+ super
34
+ %w(reminders people_reminders prefix_reminders_suffix p_things_s).each do |table|
35
+ Reminder.connection.drop_table(table) rescue nil
36
+ end
37
+ Reminder.reset_column_information
38
+ @verbose_was, ActiveRecord::Migration.verbose = ActiveRecord::Migration.verbose, false
39
+ ActiveRecord::Base.connection.schema_cache.clear!
40
+ end
41
+
42
+ teardown do
43
+ ActiveRecord::Base.table_name_prefix = ""
44
+ ActiveRecord::Base.table_name_suffix = ""
45
+
46
+ ActiveRecord::Base.connection.initialize_schema_migrations_table
47
+ ActiveRecord::Base.connection.execute "DELETE FROM #{ActiveRecord::Migrator.schema_migrations_table_name}"
48
+
49
+ %w(things awesome_things prefix_things_suffix p_awesome_things_s ).each do |table|
50
+ Thing.connection.drop_table(table) rescue nil
51
+ end
52
+ Thing.reset_column_information
53
+
54
+ %w(reminders people_reminders prefix_reminders_suffix).each do |table|
55
+ Reminder.connection.drop_table(table) rescue nil
56
+ end
57
+ Reminder.reset_table_name
58
+ Reminder.reset_column_information
59
+
60
+ %w(last_name key bio age height wealth birthday favorite_day
61
+ moment_of_truth male administrator funny).each do |column|
62
+ Person.connection.remove_column('people', column) rescue nil
63
+ end
64
+ Person.connection.remove_column("people", "first_name") rescue nil
65
+ Person.connection.remove_column("people", "middle_name") rescue nil
66
+ Person.connection.add_column("people", "first_name", :string)
67
+ Person.reset_column_information
68
+
69
+ ActiveRecord::Migration.verbose = @verbose_was
70
+ end
71
+
72
+ def test_migration_version_matches_component_version
73
+ assert_equal ActiveRecord::VERSION::STRING.to_f, ActiveRecord::Migration.current_version
74
+ end
75
+
76
+ def test_migrator_versions
77
+ migrations_path = MIGRATIONS_ROOT + "/valid"
78
+ old_path = ActiveRecord::Migrator.migrations_paths
79
+ ActiveRecord::Migrator.migrations_paths = migrations_path
80
+
81
+ ActiveRecord::Migrator.up(migrations_path)
82
+ assert_equal 3, ActiveRecord::Migrator.current_version
83
+ assert_equal false, ActiveRecord::Migrator.needs_migration?
84
+
85
+ ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid")
86
+ assert_equal 0, ActiveRecord::Migrator.current_version
87
+ assert_equal true, ActiveRecord::Migrator.needs_migration?
88
+
89
+ ActiveRecord::SchemaMigration.create!(version: 3)
90
+ assert_equal true, ActiveRecord::Migrator.needs_migration?
91
+ ensure
92
+ ActiveRecord::Migrator.migrations_paths = old_path
93
+ end
94
+
95
+ def test_migration_detection_without_schema_migration_table
96
+ ActiveRecord::Base.connection.drop_table 'schema_migrations'
97
+ #, if_exists: true
98
+
99
+ migrations_path = MIGRATIONS_ROOT + "/valid"
100
+ old_path = ActiveRecord::Migrator.migrations_paths
101
+ ActiveRecord::Migrator.migrations_paths = migrations_path
102
+
103
+ assert_equal true, ActiveRecord::Migrator.needs_migration?
104
+ ensure
105
+ ActiveRecord::Migrator.migrations_paths = old_path
106
+ end
107
+
108
+ def test_any_migrations
109
+ old_path = ActiveRecord::Migrator.migrations_paths
110
+ ActiveRecord::Migrator.migrations_paths = MIGRATIONS_ROOT + "/valid"
111
+
112
+ assert ActiveRecord::Migrator.any_migrations?
113
+
114
+ ActiveRecord::Migrator.migrations_paths = MIGRATIONS_ROOT + "/empty"
115
+
116
+ assert_not ActiveRecord::Migrator.any_migrations?
117
+ ensure
118
+ ActiveRecord::Migrator.migrations_paths = old_path
119
+ end
120
+
121
+ def test_migration_version
122
+ assert_nothing_raised { ActiveRecord::Migrator.run(:up, MIGRATIONS_ROOT + "/version_check", 20131219224947) }
123
+ end
124
+
125
+ def test_create_table_with_force_true_does_not_drop_nonexisting_table
126
+ # using a copy as we need the drop_table method to
127
+ # continue to work for the ensure block of the test
128
+ temp_conn = Person.connection.dup
129
+
130
+ assert_not_equal temp_conn, Person.connection
131
+
132
+ temp_conn.create_table :testings2, :force => true do |t|
133
+ t.column :foo, :string
134
+ end
135
+ ensure
136
+ Person.connection.drop_table :testings2
137
+ #, if_exists: true
138
+ end
139
+
140
+ def test_migration_instance_has_connection
141
+ migration = Class.new(ActiveRecord::Migration::Current).new
142
+ assert_equal ActiveRecord::Base.connection, migration.connection
143
+ end
144
+
145
+ def test_method_missing_delegates_to_connection
146
+ migration = Class.new(ActiveRecord::Migration::Current) {
147
+ def connection
148
+ Class.new {
149
+ def create_table; "hi mom!"; end
150
+ }.new
151
+ end
152
+ }.new
153
+
154
+ assert_equal "hi mom!", migration.method_missing(:create_table)
155
+ end
156
+
157
+ def test_add_table_with_decimals
158
+ Person.connection.drop_table :big_numbers rescue nil
159
+
160
+ assert !BigNumber.table_exists?
161
+ GiveMeBigNumbers.up
162
+ BigNumber.reset_column_information
163
+
164
+ assert BigNumber.create(
165
+ :bank_balance => 1586.43,
166
+ :big_bank_balance => BigDecimal("1000234000567.95"),
167
+ :world_population => 6000000000,
168
+ :my_house_population => 3,
169
+ :value_of_e => BigDecimal("2.7182818284590452353602875")
170
+ )
171
+
172
+ b = BigNumber.first
173
+ assert_not_nil b
174
+
175
+ assert_not_nil b.bank_balance
176
+ assert_not_nil b.big_bank_balance
177
+ assert_not_nil b.world_population
178
+ assert_not_nil b.my_house_population
179
+ assert_not_nil b.value_of_e
180
+
181
+ # TODO: set world_population >= 2**62 to cover 64-bit platforms and test
182
+ # is_a?(Bignum)
183
+ assert_kind_of Integer, b.world_population
184
+ assert_equal 6000000000, b.world_population
185
+ assert_kind_of Integer, b.my_house_population
186
+ assert_equal 3, b.my_house_population
187
+ assert_kind_of BigDecimal, b.bank_balance
188
+ assert_equal BigDecimal("1586.43"), b.bank_balance
189
+ assert_kind_of BigDecimal, b.big_bank_balance
190
+ assert_equal BigDecimal("1000234000567.95"), b.big_bank_balance
191
+
192
+ # This one is fun. The 'value_of_e' field is defined as 'DECIMAL' with
193
+ # precision/scale explicitly left out. By the SQL standard, numbers
194
+ # assigned to this field should be truncated but that's seldom respected.
195
+ if current_adapter?(:PostgreSQLAdapter)
196
+ # - PostgreSQL changes the SQL spec on columns declared simply as
197
+ # "decimal" to something more useful: instead of being given a scale
198
+ # of 0, they take on the compile-time limit for precision and scale,
199
+ # so the following should succeed unless you have used really wacky
200
+ # compilation options
201
+ assert_kind_of BigDecimal, b.value_of_e
202
+ assert_equal BigDecimal("2.7182818284590452353602875"), b.value_of_e
203
+ elsif current_adapter?(:SQLite3Adapter)
204
+ # - SQLite3 stores a float, in violation of SQL
205
+ assert_kind_of BigDecimal, b.value_of_e
206
+ assert_in_delta BigDecimal("2.71828182845905"), b.value_of_e, 0.00000000000001
207
+ else
208
+ # - SQL standard is an integer
209
+ assert_kind_of Integer, b.value_of_e
210
+ assert_equal 2, b.value_of_e
211
+ end
212
+
213
+ GiveMeBigNumbers.down
214
+ assert_raise(ActiveRecord::StatementInvalid) { BigNumber.first }
215
+ end
216
+
217
+ def test_filtering_migrations
218
+ assert_no_column Person, :last_name
219
+ assert !Reminder.table_exists?
220
+
221
+ name_filter = lambda { |migration| migration.name == "ValidPeopleHaveLastNames" }
222
+ ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", &name_filter)
223
+
224
+ assert_column Person, :last_name
225
+ assert_raise(ActiveRecord::StatementInvalid) { Reminder.first }
226
+
227
+ ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", &name_filter)
228
+
229
+ assert_no_column Person, :last_name
230
+ assert_raise(ActiveRecord::StatementInvalid) { Reminder.first }
231
+ end
232
+
233
+ class MockMigration < ActiveRecord::Migration::Current
234
+ attr_reader :went_up, :went_down
235
+ def initialize
236
+ @went_up = false
237
+ @went_down = false
238
+ end
239
+
240
+ def up
241
+ @went_up = true
242
+ super
243
+ end
244
+
245
+ def down
246
+ @went_down = true
247
+ super
248
+ end
249
+ end
250
+
251
+ def test_instance_based_migration_up
252
+ migration = MockMigration.new
253
+ assert !migration.went_up, 'have not gone up'
254
+ assert !migration.went_down, 'have not gone down'
255
+
256
+ migration.migrate :up
257
+ assert migration.went_up, 'have gone up'
258
+ assert !migration.went_down, 'have not gone down'
259
+ end
260
+
261
+ def test_instance_based_migration_down
262
+ migration = MockMigration.new
263
+ assert !migration.went_up, 'have not gone up'
264
+ assert !migration.went_down, 'have not gone down'
265
+
266
+ migration.migrate :down
267
+ assert !migration.went_up, 'have gone up'
268
+ assert migration.went_down, 'have not gone down'
269
+ end
270
+
271
+ if ActiveRecord::Base.connection.supports_ddl_transactions?
272
+ def test_migrator_one_up_with_exception_and_rollback
273
+ assert_no_column Person, :last_name
274
+
275
+ migration = Class.new(ActiveRecord::Migration::Current) {
276
+ def version; 100 end
277
+ def migrate(x)
278
+ add_column "people", "last_name", :string
279
+ raise 'Something broke'
280
+ end
281
+ }.new
282
+
283
+ migrator = ActiveRecord::Migrator.new(:up, [migration], 100)
284
+
285
+ e = assert_raise(StandardError) { migrator.migrate }
286
+
287
+ assert_equal "An error has occurred, this and all later migrations canceled:\n\nSomething broke", e.message
288
+
289
+ assert_no_column Person, :last_name,
290
+ "On error, the Migrator should revert schema changes but it did not."
291
+ end
292
+
293
+ def test_migrator_one_up_with_exception_and_rollback_using_run
294
+ assert_no_column Person, :last_name
295
+
296
+ migration = Class.new(ActiveRecord::Migration::Current) {
297
+ def version; 100 end
298
+ def migrate(x)
299
+ add_column "people", "last_name", :string
300
+ raise 'Something broke'
301
+ end
302
+ }.new
303
+
304
+ migrator = ActiveRecord::Migrator.new(:up, [migration], 100)
305
+
306
+ e = assert_raise(StandardError) { migrator.run }
307
+
308
+ assert_equal "An error has occurred, this and all later migrations canceled:\n\nSomething broke", e.message
309
+
310
+ assert_no_column Person, :last_name,
311
+ "On error, the Migrator should revert schema changes but it did not."
312
+ end
313
+
314
+ def test_migration_without_transaction
315
+ assert_no_column Person, :last_name
316
+
317
+ migration = Class.new(ActiveRecord::Migration::Current) {
318
+ self.disable_ddl_transaction!
319
+
320
+ def version; 101 end
321
+ def migrate(x)
322
+ add_column "people", "last_name", :string
323
+ raise 'Something broke'
324
+ end
325
+ }.new
326
+
327
+ migrator = ActiveRecord::Migrator.new(:up, [migration], 101)
328
+ e = assert_raise(StandardError) { migrator.migrate }
329
+ assert_equal "An error has occurred, all later migrations canceled:\n\nSomething broke", e.message
330
+
331
+ assert_column Person, :last_name,
332
+ "without ddl transactions, the Migrator should not rollback on error but it did."
333
+ ensure
334
+ Person.reset_column_information
335
+ if Person.column_names.include?('last_name')
336
+ Person.connection.remove_column('people', 'last_name')
337
+ end
338
+ end
339
+ end
340
+
341
+ def test_schema_migrations_table_name
342
+ original_schema_migrations_table_name = ActiveRecord::Migrator.schema_migrations_table_name
343
+
344
+ assert_equal "schema_migrations", ActiveRecord::Migrator.schema_migrations_table_name
345
+ ActiveRecord::Base.table_name_prefix = "prefix_"
346
+ ActiveRecord::Base.table_name_suffix = "_suffix"
347
+ Reminder.reset_table_name
348
+ assert_equal "prefix_schema_migrations_suffix", ActiveRecord::Migrator.schema_migrations_table_name
349
+ ActiveRecord::Base.schema_migrations_table_name = "changed"
350
+ Reminder.reset_table_name
351
+ assert_equal "prefix_changed_suffix", ActiveRecord::Migrator.schema_migrations_table_name
352
+ ActiveRecord::Base.table_name_prefix = ""
353
+ ActiveRecord::Base.table_name_suffix = ""
354
+ Reminder.reset_table_name
355
+ assert_equal "changed", ActiveRecord::Migrator.schema_migrations_table_name
356
+ ensure
357
+ ActiveRecord::Base.schema_migrations_table_name = original_schema_migrations_table_name
358
+ Reminder.reset_table_name
359
+ end
360
+
361
+ def test_internal_metadata_table_name
362
+ original_internal_metadata_table_name = ActiveRecord::Base.internal_metadata_table_name
363
+
364
+ assert_equal "ar_internal_metadata", ActiveRecord::InternalMetadata.table_name
365
+ ActiveRecord::Base.table_name_prefix = "p_"
366
+ ActiveRecord::Base.table_name_suffix = "_s"
367
+ Reminder.reset_table_name
368
+ assert_equal "p_ar_internal_metadata_s", ActiveRecord::InternalMetadata.table_name
369
+ ActiveRecord::Base.internal_metadata_table_name = "changed"
370
+ Reminder.reset_table_name
371
+ assert_equal "p_changed_s", ActiveRecord::InternalMetadata.table_name
372
+ ActiveRecord::Base.table_name_prefix = ""
373
+ ActiveRecord::Base.table_name_suffix = ""
374
+ Reminder.reset_table_name
375
+ assert_equal "changed", ActiveRecord::InternalMetadata.table_name
376
+ ensure
377
+ ActiveRecord::Base.internal_metadata_table_name = original_internal_metadata_table_name
378
+ Reminder.reset_table_name
379
+ end
380
+
381
+ def test_internal_metadata_stores_environment
382
+ current_env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
383
+ migrations_path = MIGRATIONS_ROOT + "/valid"
384
+ old_path = ActiveRecord::Migrator.migrations_paths
385
+ ActiveRecord::Migrator.migrations_paths = migrations_path
386
+
387
+ ActiveRecord::Migrator.up(migrations_path)
388
+ assert_equal current_env, ActiveRecord::InternalMetadata[:environment]
389
+
390
+ original_rails_env = ENV["RAILS_ENV"]
391
+ original_rack_env = ENV["RACK_ENV"]
392
+ ENV["RAILS_ENV"] = ENV["RACK_ENV"] = "foofoo"
393
+ new_env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
394
+
395
+ refute_equal current_env, new_env
396
+
397
+ sleep 1 # mysql by default does not store fractional seconds in the database
398
+ ActiveRecord::Migrator.up(migrations_path)
399
+ assert_equal new_env, ActiveRecord::InternalMetadata[:environment]
400
+ ensure
401
+ ActiveRecord::Migrator.migrations_paths = old_path
402
+ ENV["RAILS_ENV"] = original_rails_env
403
+ ENV["RACK_ENV"] = original_rack_env
404
+ end
405
+
406
+
407
+ def test_migration_sets_internal_metadata_even_when_fully_migrated
408
+ current_env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
409
+ migrations_path = MIGRATIONS_ROOT + "/valid"
410
+ old_path = ActiveRecord::Migrator.migrations_paths
411
+ ActiveRecord::Migrator.migrations_paths = migrations_path
412
+
413
+ ActiveRecord::Migrator.up(migrations_path)
414
+ assert_equal current_env, ActiveRecord::InternalMetadata[:environment]
415
+
416
+ original_rails_env = ENV["RAILS_ENV"]
417
+ original_rack_env = ENV["RACK_ENV"]
418
+ ENV["RAILS_ENV"] = ENV["RACK_ENV"] = "foofoo"
419
+ new_env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
420
+
421
+ refute_equal current_env, new_env
422
+
423
+ sleep 1 # mysql by default does not store fractional seconds in the database
424
+
425
+ ActiveRecord::Migrator.up(migrations_path)
426
+ assert_equal new_env, ActiveRecord::InternalMetadata[:environment]
427
+ ensure
428
+ ActiveRecord::Migrator.migrations_paths = old_path
429
+ ENV["RAILS_ENV"] = original_rails_env
430
+ ENV["RACK_ENV"] = original_rack_env
431
+ end
432
+
433
+ def test_internal_metadata_stores_environment_when_other_data_exists
434
+ ActiveRecord::InternalMetadata.delete_all
435
+ ActiveRecord::InternalMetadata[:foo] = 'bar'
436
+
437
+ current_env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
438
+ migrations_path = MIGRATIONS_ROOT + "/valid"
439
+ old_path = ActiveRecord::Migrator.migrations_paths
440
+ ActiveRecord::Migrator.migrations_paths = migrations_path
441
+
442
+ current_env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
443
+ ActiveRecord::Migrator.up(migrations_path)
444
+ assert_equal current_env, ActiveRecord::InternalMetadata[:environment]
445
+ assert_equal 'bar', ActiveRecord::InternalMetadata[:foo]
446
+ ensure
447
+ ActiveRecord::Migrator.migrations_paths = old_path
448
+ end
449
+
450
+ def test_rename_internal_metadata_table
451
+ original_internal_metadata_table_name = ActiveRecord::Base.internal_metadata_table_name
452
+
453
+ ActiveRecord::Base.internal_metadata_table_name = "active_record_internal_metadatas"
454
+ Reminder.reset_table_name
455
+
456
+ ActiveRecord::Base.internal_metadata_table_name = original_internal_metadata_table_name
457
+ Reminder.reset_table_name
458
+
459
+ assert_equal "ar_internal_metadata", ActiveRecord::InternalMetadata.table_name
460
+ ensure
461
+ ActiveRecord::Base.internal_metadata_table_name = original_internal_metadata_table_name
462
+ Reminder.reset_table_name
463
+ end
464
+
465
+ def test_proper_table_name_on_migration
466
+ reminder_class = new_isolated_reminder_class
467
+ migration = ActiveRecord::Migration.new
468
+ assert_equal "table", migration.proper_table_name('table')
469
+ assert_equal "table", migration.proper_table_name(:table)
470
+ assert_equal "reminders", migration.proper_table_name(reminder_class)
471
+ reminder_class.reset_table_name
472
+ assert_equal reminder_class.table_name, migration.proper_table_name(reminder_class)
473
+
474
+ # Use the model's own prefix/suffix if a model is given
475
+ ActiveRecord::Base.table_name_prefix = "ARprefix_"
476
+ ActiveRecord::Base.table_name_suffix = "_ARsuffix"
477
+ reminder_class.table_name_prefix = 'prefix_'
478
+ reminder_class.table_name_suffix = '_suffix'
479
+ reminder_class.reset_table_name
480
+ assert_equal "prefix_reminders_suffix", migration.proper_table_name(reminder_class)
481
+ reminder_class.table_name_prefix = ''
482
+ reminder_class.table_name_suffix = ''
483
+ reminder_class.reset_table_name
484
+
485
+ # Use AR::Base's prefix/suffix if string or symbol is given
486
+ ActiveRecord::Base.table_name_prefix = "prefix_"
487
+ ActiveRecord::Base.table_name_suffix = "_suffix"
488
+ reminder_class.reset_table_name
489
+ assert_equal "prefix_table_suffix", migration.proper_table_name('table', migration.table_name_options)
490
+ assert_equal "prefix_table_suffix", migration.proper_table_name(:table, migration.table_name_options)
491
+ end
492
+
493
+ def test_rename_table_with_prefix_and_suffix
494
+ assert !Thing.table_exists?
495
+ ActiveRecord::Base.table_name_prefix = 'p_'
496
+ ActiveRecord::Base.table_name_suffix = '_s'
497
+ Thing.reset_table_name
498
+ Thing.reset_sequence_name
499
+ WeNeedThings.up
500
+ Thing.reset_column_information
501
+
502
+ assert Thing.create("content" => "hello world")
503
+ assert_equal "hello world", Thing.first.content
504
+
505
+ RenameThings.up
506
+ Thing.table_name = "p_awesome_things_s"
507
+
508
+ assert_equal "hello world", Thing.first.content
509
+ ensure
510
+ Thing.reset_table_name
511
+ Thing.reset_sequence_name
512
+ end
513
+
514
+ def test_add_drop_table_with_prefix_and_suffix
515
+ assert !Reminder.table_exists?
516
+ ActiveRecord::Base.table_name_prefix = 'prefix_'
517
+ ActiveRecord::Base.table_name_suffix = '_suffix'
518
+ Reminder.reset_table_name
519
+ Reminder.reset_sequence_name
520
+ Reminder.reset_column_information
521
+ WeNeedReminders.up
522
+ assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
523
+ assert_equal "hello world", Reminder.first.content
524
+
525
+ WeNeedReminders.down
526
+ assert_raise(ActiveRecord::StatementInvalid) { Reminder.first }
527
+ ensure
528
+ Reminder.reset_sequence_name
529
+ end
530
+
531
+ def test_create_table_with_binary_column
532
+ assert_nothing_raised {
533
+ Person.connection.create_table :binary_testings do |t|
534
+ t.column "data", :binary, :null => false
535
+ end
536
+ }
537
+
538
+ columns = Person.connection.columns(:binary_testings)
539
+ data_column = columns.detect { |c| c.name == "data" }
540
+
541
+ assert_nil data_column.default
542
+ ensure
543
+ Person.connection.drop_table :binary_testings
544
+ #, if_exists: true
545
+ end
546
+
547
+ unless mysql_enforcing_gtid_consistency?
548
+ def test_create_table_with_query
549
+ Person.connection.create_table(:person, force: true)
550
+
551
+ Person.connection.create_table :table_from_query_testings, as: "SELECT id FROM person"
552
+
553
+ columns = Person.connection.columns(:table_from_query_testings)
554
+ assert_equal 1, columns.length
555
+ assert_equal "id", columns.first.name
556
+ ensure
557
+ Person.connection.drop_table :table_from_query_testings rescue nil
558
+ end
559
+
560
+ def test_create_table_with_query_from_relation
561
+ Person.connection.create_table(:person, force: true)
562
+
563
+ Person.connection.create_table :table_from_query_testings, as: Person.select(:id)
564
+
565
+ columns = Person.connection.columns(:table_from_query_testings)
566
+ assert_equal 1, columns.length
567
+ assert_equal "id", columns.first.name
568
+ ensure
569
+ Person.connection.drop_table :table_from_query_testings rescue nil
570
+ end
571
+ end
572
+
573
+ if current_adapter?(:SQLite3Adapter)
574
+ def test_allows_sqlite3_rollback_on_invalid_column_type
575
+ Person.connection.create_table :something, force: true do |t|
576
+ t.column :number, :integer
577
+ t.column :name, :string
578
+ t.column :foo, :bar
579
+ end
580
+ assert Person.connection.column_exists?(:something, :foo)
581
+ assert_nothing_raised { Person.connection.remove_column :something, :foo, :bar }
582
+ assert !Person.connection.column_exists?(:something, :foo)
583
+ assert Person.connection.column_exists?(:something, :name)
584
+ assert Person.connection.column_exists?(:something, :number)
585
+ ensure
586
+ Person.connection.drop_table :something
587
+ #, if_exists: true
588
+ end
589
+ end
590
+
591
+ if current_adapter? :OracleAdapter
592
+ def test_create_table_with_custom_sequence_name
593
+ # table name is 29 chars, the standard sequence name will
594
+ # be 33 chars and should be shortened
595
+ assert_nothing_raised do
596
+ begin
597
+ Person.connection.create_table :table_with_name_thats_just_ok do |t|
598
+ t.column :foo, :string, :null => false
599
+ end
600
+ ensure
601
+ Person.connection.drop_table :table_with_name_thats_just_ok rescue nil
602
+ end
603
+ end
604
+
605
+ # should be all good w/ a custom sequence name
606
+ assert_nothing_raised do
607
+ begin
608
+ Person.connection.create_table :table_with_name_thats_just_ok,
609
+ :sequence_name => 'suitably_short_seq' do |t|
610
+ t.column :foo, :string, :null => false
611
+ end
612
+
613
+ Person.connection.execute("select suitably_short_seq.nextval from dual")
614
+
615
+ ensure
616
+ Person.connection.drop_table :table_with_name_thats_just_ok,
617
+ :sequence_name => 'suitably_short_seq' rescue nil
618
+ end
619
+ end
620
+
621
+ # confirm the custom sequence got dropped
622
+ assert_raise(ActiveRecord::StatementInvalid) do
623
+ Person.connection.execute("select suitably_short_seq.nextval from dual")
624
+ end
625
+ end
626
+ end
627
+
628
+ if current_adapter?(:Mysql2Adapter, :PostgreSQLAdapter)
629
+ def test_out_of_range_integer_limit_should_raise
630
+ e = assert_raise(ActiveRecord::ActiveRecordError, "integer limit didn't raise") do
631
+ Person.connection.create_table :test_integer_limits, :force => true do |t|
632
+ t.column :bigone, :integer, :limit => 10
633
+ end
634
+ end
635
+
636
+ assert_match(/No integer type has byte size 10/, e.message)
637
+ ensure
638
+ Person.connection.drop_table :test_integer_limits
639
+ #, if_exists: true
640
+ end
641
+ end
642
+
643
+ if current_adapter?(:Mysql2Adapter)
644
+ def test_out_of_range_text_limit_should_raise
645
+ e = assert_raise(ActiveRecord::ActiveRecordError, "text limit didn't raise") do
646
+ Person.connection.create_table :test_text_limits, force: true do |t|
647
+ t.text :bigtext, limit: 0xfffffffff
648
+ end
649
+ end
650
+
651
+ assert_match(/No text type has byte length #{0xfffffffff}/, e.message)
652
+ ensure
653
+ Person.connection.drop_table :test_text_limits
654
+ #, if_exists: true
655
+ end
656
+ end
657
+
658
+ if ActiveRecord::Base.connection.supports_advisory_locks?
659
+ def test_migrator_generates_valid_lock_id
660
+ migration = Class.new(ActiveRecord::Migration::Current).new
661
+ migrator = ActiveRecord::Migrator.new(:up, [migration], 100)
662
+
663
+ lock_id = migrator.send(:generate_migrator_advisory_lock_id)
664
+
665
+ assert ActiveRecord::Base.connection.get_advisory_lock(lock_id),
666
+ "the Migrator should have generated a valid lock id, but it didn't"
667
+ assert ActiveRecord::Base.connection.release_advisory_lock(lock_id),
668
+ "the Migrator should have generated a valid lock id, but it didn't"
669
+ end
670
+
671
+ def test_generate_migrator_advisory_lock_id
672
+ # It is important we are consistent with how we generate this so that
673
+ # exclusive locking works across migrator versions
674
+ migration = Class.new(ActiveRecord::Migration::Current).new
675
+ migrator = ActiveRecord::Migrator.new(:up, [migration], 100)
676
+
677
+ lock_id = migrator.send(:generate_migrator_advisory_lock_id)
678
+
679
+ current_database = ActiveRecord::Base.connection.current_database
680
+ salt = ActiveRecord::Migrator::MIGRATOR_SALT
681
+ expected_id = Zlib.crc32(current_database) * salt
682
+
683
+ assert lock_id == expected_id, "expected lock id generated by the migrator to be #{expected_id}, but it was #{lock_id} instead"
684
+ assert lock_id.bit_length <= 63, "lock id must be a signed integer of max 63 bits magnitude"
685
+ end
686
+
687
+ def test_migrator_one_up_with_unavailable_lock
688
+ assert_no_column Person, :last_name
689
+
690
+ migration = Class.new(ActiveRecord::Migration::Current) {
691
+ def version; 100 end
692
+ def migrate(x)
693
+ add_column "people", "last_name", :string
694
+ end
695
+ }.new
696
+
697
+ migrator = ActiveRecord::Migrator.new(:up, [migration], 100)
698
+ lock_id = migrator.send(:generate_migrator_advisory_lock_id)
699
+
700
+ with_another_process_holding_lock(lock_id) do
701
+ assert_raise(ActiveRecord::ConcurrentMigrationError) { migrator.migrate }
702
+ end
703
+
704
+ assert_no_column Person, :last_name,
705
+ "without an advisory lock, the Migrator should not make any changes, but it did."
706
+ end
707
+
708
+ def test_migrator_one_up_with_unavailable_lock_using_run
709
+ assert_no_column Person, :last_name
710
+
711
+ migration = Class.new(ActiveRecord::Migration::Current) {
712
+ def version; 100 end
713
+ def migrate(x)
714
+ add_column "people", "last_name", :string
715
+ end
716
+ }.new
717
+
718
+ migrator = ActiveRecord::Migrator.new(:up, [migration], 100)
719
+ lock_id = migrator.send(:generate_migrator_advisory_lock_id)
720
+
721
+ with_another_process_holding_lock(lock_id) do
722
+ assert_raise(ActiveRecord::ConcurrentMigrationError) { migrator.run }
723
+ end
724
+
725
+ assert_no_column Person, :last_name,
726
+ "without an advisory lock, the Migrator should not make any changes, but it did."
727
+ end
728
+ end
729
+
730
+ protected
731
+ # This is needed to isolate class_attribute assignments like `table_name_prefix`
732
+ # for each test case.
733
+ def new_isolated_reminder_class
734
+ Class.new(Reminder) {
735
+ def self.name; "Reminder"; end
736
+ def self.base_class; self; end
737
+ }
738
+ end
739
+
740
+ def with_another_process_holding_lock(lock_id)
741
+ thread_lock = Concurrent::CountDownLatch.new
742
+ test_terminated = Concurrent::CountDownLatch.new
743
+
744
+ other_process = Thread.new do
745
+ begin
746
+ conn = ActiveRecord::Base.connection_pool.checkout
747
+ conn.get_advisory_lock(lock_id)
748
+ thread_lock.count_down
749
+ test_terminated.wait # hold the lock open until we tested everything
750
+ ensure
751
+ conn.release_advisory_lock(lock_id)
752
+ ActiveRecord::Base.connection_pool.checkin(conn)
753
+ end
754
+ end
755
+
756
+ thread_lock.wait # wait until the 'other process' has the lock
757
+
758
+ yield
759
+
760
+ test_terminated.count_down
761
+ other_process.join
762
+ end
763
+ end
764
+
765
+ class ReservedWordsMigrationTest < ActiveRecord::TestCase
766
+ def test_drop_index_from_table_named_values
767
+ connection = Person.connection
768
+ connection.create_table :values, :force => true do |t|
769
+ t.integer :value
770
+ end
771
+
772
+ assert_nothing_raised do
773
+ connection.add_index :values, :value
774
+ connection.remove_index :values, :column => :value
775
+ end
776
+ ensure
777
+ connection.drop_table :values rescue nil
778
+ end
779
+ end
780
+
781
+ class ExplicitlyNamedIndexMigrationTest < ActiveRecord::TestCase
782
+ def test_drop_index_by_name
783
+ connection = Person.connection
784
+ connection.create_table :values, force: true do |t|
785
+ t.integer :value
786
+ end
787
+
788
+ assert_nothing_raised do
789
+ connection.add_index :values, :value, name: 'a_different_name'
790
+ connection.remove_index :values, column: :value, name: 'a_different_name'
791
+ end
792
+ ensure
793
+ connection.drop_table :values rescue nil
794
+ end
795
+ end
796
+
797
+ if ActiveRecord::Base.connection.supports_bulk_alter?
798
+ class BulkAlterTableMigrationsTest < ActiveRecord::TestCase
799
+ def setup
800
+ @connection = Person.connection
801
+ @connection.create_table(:delete_me, :force => true) {|t| }
802
+ Person.reset_column_information
803
+ Person.reset_sequence_name
804
+ end
805
+
806
+ teardown do
807
+ Person.connection.drop_table(:delete_me) rescue nil
808
+ end
809
+
810
+ def test_adding_multiple_columns
811
+ assert_queries(1) do
812
+ with_bulk_change_table do |t|
813
+ t.column :name, :string
814
+ t.string :qualification, :experience
815
+ t.integer :age, :default => 0
816
+ t.date :birthdate
817
+ t.timestamps null: true
818
+ end
819
+ end
820
+
821
+ assert_equal 8, columns.size
822
+ [:name, :qualification, :experience].each {|s| assert_equal :string, column(s).type }
823
+ assert_equal '0', column(:age).default
824
+ end
825
+
826
+ def test_removing_columns
827
+ with_bulk_change_table do |t|
828
+ t.string :qualification, :experience
829
+ end
830
+
831
+ [:qualification, :experience].each {|c| assert column(c) }
832
+
833
+ assert_queries(1) do
834
+ with_bulk_change_table do |t|
835
+ t.remove :qualification, :experience
836
+ t.string :qualification_experience
837
+ end
838
+ end
839
+
840
+ [:qualification, :experience].each {|c| assert ! column(c) }
841
+ assert column(:qualification_experience)
842
+ end
843
+
844
+ def test_adding_indexes
845
+ with_bulk_change_table do |t|
846
+ t.string :username
847
+ t.string :name
848
+ t.integer :age
849
+ end
850
+
851
+ # Adding an index fires a query every time to check if an index already exists or not
852
+ assert_queries(3) do
853
+ with_bulk_change_table do |t|
854
+ t.index :username, :unique => true, :name => :awesome_username_index
855
+ t.index [:name, :age]
856
+ end
857
+ end
858
+
859
+ assert_equal 2, indexes.size
860
+
861
+ name_age_index = index(:index_delete_me_on_name_and_age)
862
+ assert_equal ['name', 'age'].sort, name_age_index.columns.sort
863
+ assert ! name_age_index.unique
864
+
865
+ assert index(:awesome_username_index).unique
866
+ end
867
+
868
+ def test_removing_index
869
+ with_bulk_change_table do |t|
870
+ t.string :name
871
+ t.index :name
872
+ end
873
+
874
+ assert index(:index_delete_me_on_name)
875
+
876
+ assert_queries(3) do
877
+ with_bulk_change_table do |t|
878
+ t.remove_index :name
879
+ t.index :name, :name => :new_name_index, :unique => true
880
+ end
881
+ end
882
+
883
+ assert ! index(:index_delete_me_on_name)
884
+
885
+ new_name_index = index(:new_name_index)
886
+ assert new_name_index.unique
887
+ end
888
+
889
+ def test_changing_columns
890
+ with_bulk_change_table do |t|
891
+ t.string :name
892
+ t.date :birthdate
893
+ end
894
+
895
+ assert ! column(:name).default
896
+ assert_equal :date, column(:birthdate).type
897
+
898
+ # One query for columns (delete_me table)
899
+ # One query for primary key (delete_me table)
900
+ # One query to do the bulk change
901
+ assert_queries(3, :ignore_none => true) do
902
+ with_bulk_change_table do |t|
903
+ t.change :name, :string, :default => 'NONAME'
904
+ t.change :birthdate, :datetime
905
+ end
906
+ end
907
+
908
+ assert_equal 'NONAME', column(:name).default
909
+ assert_equal :datetime, column(:birthdate).type
910
+ end
911
+
912
+ protected
913
+
914
+ def with_bulk_change_table
915
+ # Reset columns/indexes cache as we're changing the table
916
+ @columns = @indexes = nil
917
+
918
+ Person.connection.change_table(:delete_me, :bulk => true) do |t|
919
+ yield t
920
+ end
921
+ end
922
+
923
+ def column(name)
924
+ columns.detect {|c| c.name == name.to_s }
925
+ end
926
+
927
+ def columns
928
+ @columns ||= Person.connection.columns('delete_me')
929
+ end
930
+
931
+ def index(name)
932
+ indexes.detect {|i| i.name == name.to_s }
933
+ end
934
+
935
+ def indexes
936
+ @indexes ||= Person.connection.indexes('delete_me')
937
+ end
938
+ end # AlterTableMigrationsTest
939
+
940
+ end
941
+
942
+ class CopyMigrationsTest < ActiveRecord::TestCase
943
+ include ActiveSupport::Testing::Stream
944
+
945
+ def setup
946
+ end
947
+
948
+ def clear
949
+ ActiveRecord::Base.timestamped_migrations = true
950
+ to_delete = Dir[@migrations_path + "/*.rb"] - @existing_migrations
951
+ File.delete(*to_delete)
952
+ end
953
+
954
+ def test_copying_migrations_without_timestamps
955
+ ActiveRecord::Base.timestamped_migrations = false
956
+ @migrations_path = MIGRATIONS_ROOT + "/valid"
957
+ @existing_migrations = Dir[@migrations_path + "/*.rb"]
958
+
959
+ copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy"})
960
+ assert File.exist?(@migrations_path + "/4_people_have_hobbies.bukkits.rb")
961
+ assert File.exist?(@migrations_path + "/5_people_have_descriptions.bukkits.rb")
962
+ assert_equal [@migrations_path + "/4_people_have_hobbies.bukkits.rb", @migrations_path + "/5_people_have_descriptions.bukkits.rb"], copied.map(&:filename)
963
+
964
+ expected = "# This migration comes from bukkits (originally 1)"
965
+ assert_equal expected, IO.readlines(@migrations_path + "/4_people_have_hobbies.bukkits.rb")[0].chomp
966
+
967
+ files_count = Dir[@migrations_path + "/*.rb"].length
968
+ copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy"})
969
+ assert_equal files_count, Dir[@migrations_path + "/*.rb"].length
970
+ assert copied.empty?
971
+ ensure
972
+ clear
973
+ end
974
+
975
+ def test_copying_migrations_without_timestamps_from_2_sources
976
+ ActiveRecord::Base.timestamped_migrations = false
977
+ @migrations_path = MIGRATIONS_ROOT + "/valid"
978
+ @existing_migrations = Dir[@migrations_path + "/*.rb"]
979
+
980
+ sources = {}
981
+ sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy"
982
+ sources[:omg] = MIGRATIONS_ROOT + "/to_copy2"
983
+ ActiveRecord::Migration.copy(@migrations_path, sources)
984
+ assert File.exist?(@migrations_path + "/4_people_have_hobbies.bukkits.rb")
985
+ assert File.exist?(@migrations_path + "/5_people_have_descriptions.bukkits.rb")
986
+ assert File.exist?(@migrations_path + "/6_create_articles.omg.rb")
987
+ assert File.exist?(@migrations_path + "/7_create_comments.omg.rb")
988
+
989
+ files_count = Dir[@migrations_path + "/*.rb"].length
990
+ ActiveRecord::Migration.copy(@migrations_path, sources)
991
+ assert_equal files_count, Dir[@migrations_path + "/*.rb"].length
992
+ ensure
993
+ clear
994
+ end
995
+
996
+ def test_copying_migrations_with_timestamps
997
+ @migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps"
998
+ @existing_migrations = Dir[@migrations_path + "/*.rb"]
999
+
1000
+ travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do
1001
+ copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
1002
+ assert File.exist?(@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb")
1003
+ assert File.exist?(@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb")
1004
+ expected = [@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb",
1005
+ @migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb"]
1006
+ assert_equal expected, copied.map(&:filename)
1007
+
1008
+ files_count = Dir[@migrations_path + "/*.rb"].length
1009
+ copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
1010
+ assert_equal files_count, Dir[@migrations_path + "/*.rb"].length
1011
+ assert copied.empty?
1012
+ end
1013
+ ensure
1014
+ clear
1015
+ end
1016
+
1017
+ def test_copying_migrations_with_timestamps_from_2_sources
1018
+ @migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps"
1019
+ @existing_migrations = Dir[@migrations_path + "/*.rb"]
1020
+
1021
+ sources = {}
1022
+ sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy_with_timestamps"
1023
+ sources[:omg] = MIGRATIONS_ROOT + "/to_copy_with_timestamps2"
1024
+
1025
+ travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do
1026
+ copied = ActiveRecord::Migration.copy(@migrations_path, sources)
1027
+ assert File.exist?(@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb")
1028
+ assert File.exist?(@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb")
1029
+ assert File.exist?(@migrations_path + "/20100726101012_create_articles.omg.rb")
1030
+ assert File.exist?(@migrations_path + "/20100726101013_create_comments.omg.rb")
1031
+ assert_equal 4, copied.length
1032
+
1033
+ files_count = Dir[@migrations_path + "/*.rb"].length
1034
+ ActiveRecord::Migration.copy(@migrations_path, sources)
1035
+ assert_equal files_count, Dir[@migrations_path + "/*.rb"].length
1036
+ end
1037
+ ensure
1038
+ clear
1039
+ end
1040
+
1041
+ def test_copying_migrations_with_timestamps_to_destination_with_timestamps_in_future
1042
+ @migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps"
1043
+ @existing_migrations = Dir[@migrations_path + "/*.rb"]
1044
+
1045
+ travel_to(Time.utc(2010, 2, 20, 10, 10, 10)) do
1046
+ ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
1047
+ assert File.exist?(@migrations_path + "/20100301010102_people_have_hobbies.bukkits.rb")
1048
+ assert File.exist?(@migrations_path + "/20100301010103_people_have_descriptions.bukkits.rb")
1049
+
1050
+ files_count = Dir[@migrations_path + "/*.rb"].length
1051
+ copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
1052
+ assert_equal files_count, Dir[@migrations_path + "/*.rb"].length
1053
+ assert copied.empty?
1054
+ end
1055
+ ensure
1056
+ clear
1057
+ end
1058
+
1059
+ def test_copying_migrations_preserving_magic_comments
1060
+ ActiveRecord::Base.timestamped_migrations = false
1061
+ @migrations_path = MIGRATIONS_ROOT + "/valid"
1062
+ @existing_migrations = Dir[@migrations_path + "/*.rb"]
1063
+
1064
+ copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/magic"})
1065
+ assert File.exist?(@migrations_path + "/4_currencies_have_symbols.bukkits.rb")
1066
+ assert_equal [@migrations_path + "/4_currencies_have_symbols.bukkits.rb"], copied.map(&:filename)
1067
+
1068
+ expected = "# coding: ISO-8859-15\n# This migration comes from bukkits (originally 1)"
1069
+ assert_equal expected, IO.readlines(@migrations_path + "/4_currencies_have_symbols.bukkits.rb")[0..1].join.chomp
1070
+
1071
+ files_count = Dir[@migrations_path + "/*.rb"].length
1072
+ copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/magic"})
1073
+ assert_equal files_count, Dir[@migrations_path + "/*.rb"].length
1074
+ assert copied.empty?
1075
+ ensure
1076
+ clear
1077
+ end
1078
+
1079
+ def test_skipping_migrations
1080
+ @migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps"
1081
+ @existing_migrations = Dir[@migrations_path + "/*.rb"]
1082
+
1083
+ sources = {}
1084
+ sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy_with_timestamps"
1085
+ sources[:omg] = MIGRATIONS_ROOT + "/to_copy_with_name_collision"
1086
+
1087
+ skipped = []
1088
+ on_skip = Proc.new { |name, migration| skipped << "#{name} #{migration.name}" }
1089
+ copied = ActiveRecord::Migration.copy(@migrations_path, sources, :on_skip => on_skip)
1090
+ assert_equal 2, copied.length
1091
+
1092
+ assert_equal 1, skipped.length
1093
+ assert_equal ["omg PeopleHaveHobbies"], skipped
1094
+ ensure
1095
+ clear
1096
+ end
1097
+
1098
+ def test_skip_is_not_called_if_migrations_are_from_the_same_plugin
1099
+ @migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps"
1100
+ @existing_migrations = Dir[@migrations_path + "/*.rb"]
1101
+
1102
+ sources = {}
1103
+ sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy_with_timestamps"
1104
+
1105
+ skipped = []
1106
+ on_skip = Proc.new { |name, migration| skipped << "#{name} #{migration.name}" }
1107
+ copied = ActiveRecord::Migration.copy(@migrations_path, sources, :on_skip => on_skip)
1108
+ ActiveRecord::Migration.copy(@migrations_path, sources, :on_skip => on_skip)
1109
+
1110
+ assert_equal 2, copied.length
1111
+ assert_equal 0, skipped.length
1112
+ ensure
1113
+ clear
1114
+ end
1115
+
1116
+ def test_copying_migrations_to_non_existing_directory
1117
+ @migrations_path = MIGRATIONS_ROOT + "/non_existing"
1118
+ @existing_migrations = []
1119
+
1120
+ travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do
1121
+ copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
1122
+ assert File.exist?(@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb")
1123
+ assert File.exist?(@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb")
1124
+ assert_equal 2, copied.length
1125
+ end
1126
+ ensure
1127
+ clear
1128
+ Dir.delete(@migrations_path)
1129
+ end
1130
+
1131
+ def test_copying_migrations_to_empty_directory
1132
+ @migrations_path = MIGRATIONS_ROOT + "/empty"
1133
+ @existing_migrations = []
1134
+
1135
+ travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do
1136
+ copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
1137
+ assert File.exist?(@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb")
1138
+ assert File.exist?(@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb")
1139
+ assert_equal 2, copied.length
1140
+ end
1141
+ ensure
1142
+ clear
1143
+ end
1144
+
1145
+ def test_check_pending_with_stdlib_logger
1146
+ old, ActiveRecord::Base.logger = ActiveRecord::Base.logger, ::Logger.new($stdout)
1147
+ quietly do
1148
+ assert_nothing_raised { ActiveRecord::Migration::CheckPending.new(Proc.new {}).call({}) }
1149
+ end
1150
+ ensure
1151
+ ActiveRecord::Base.logger = old
1152
+ end
1153
+
1154
+ def test_unknown_migration_version_should_raise_an_argument_error
1155
+ assert_raise(ArgumentError) { ActiveRecord::Migration[1.0] }
1156
+ end
1157
+ end