sequel 3.21.0 → 3.41.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (363) hide show
  1. data/CHANGELOG +1131 -3
  2. data/MIT-LICENSE +1 -1
  3. data/README.rdoc +106 -65
  4. data/Rakefile +59 -27
  5. data/bin/sequel +50 -26
  6. data/doc/active_record.rdoc +68 -52
  7. data/doc/advanced_associations.rdoc +201 -75
  8. data/doc/association_basics.rdoc +327 -79
  9. data/doc/bin_sequel.rdoc +144 -0
  10. data/doc/cheat_sheet.rdoc +21 -21
  11. data/doc/core_extensions.rdoc +374 -0
  12. data/doc/dataset_basics.rdoc +10 -10
  13. data/doc/dataset_filtering.rdoc +54 -42
  14. data/doc/mass_assignment.rdoc +56 -0
  15. data/doc/migration.rdoc +89 -557
  16. data/doc/model_hooks.rdoc +80 -29
  17. data/doc/object_model.rdoc +576 -0
  18. data/doc/opening_databases.rdoc +121 -53
  19. data/doc/prepared_statements.rdoc +41 -15
  20. data/doc/querying.rdoc +137 -56
  21. data/doc/reflection.rdoc +36 -10
  22. data/doc/release_notes/3.22.0.txt +39 -0
  23. data/doc/release_notes/3.23.0.txt +172 -0
  24. data/doc/release_notes/3.24.0.txt +420 -0
  25. data/doc/release_notes/3.25.0.txt +88 -0
  26. data/doc/release_notes/3.26.0.txt +88 -0
  27. data/doc/release_notes/3.27.0.txt +82 -0
  28. data/doc/release_notes/3.28.0.txt +304 -0
  29. data/doc/release_notes/3.29.0.txt +459 -0
  30. data/doc/release_notes/3.30.0.txt +135 -0
  31. data/doc/release_notes/3.31.0.txt +146 -0
  32. data/doc/release_notes/3.32.0.txt +202 -0
  33. data/doc/release_notes/3.33.0.txt +157 -0
  34. data/doc/release_notes/3.34.0.txt +671 -0
  35. data/doc/release_notes/3.35.0.txt +144 -0
  36. data/doc/release_notes/3.36.0.txt +245 -0
  37. data/doc/release_notes/3.37.0.txt +338 -0
  38. data/doc/release_notes/3.38.0.txt +234 -0
  39. data/doc/release_notes/3.39.0.txt +237 -0
  40. data/doc/release_notes/3.40.0.txt +73 -0
  41. data/doc/release_notes/3.41.0.txt +155 -0
  42. data/doc/schema_modification.rdoc +585 -0
  43. data/doc/sharding.rdoc +99 -8
  44. data/doc/sql.rdoc +154 -112
  45. data/doc/testing.rdoc +169 -0
  46. data/doc/thread_safety.rdoc +17 -0
  47. data/doc/transactions.rdoc +137 -0
  48. data/doc/validations.rdoc +1 -1
  49. data/doc/virtual_rows.rdoc +78 -43
  50. data/lib/sequel/adapters/ado/access.rb +334 -0
  51. data/lib/sequel/adapters/ado/mssql.rb +18 -12
  52. data/lib/sequel/adapters/ado.rb +69 -21
  53. data/lib/sequel/adapters/amalgalite.rb +17 -14
  54. data/lib/sequel/adapters/cubrid.rb +143 -0
  55. data/lib/sequel/adapters/db2.rb +178 -85
  56. data/lib/sequel/adapters/dbi.rb +19 -21
  57. data/lib/sequel/adapters/do/mysql.rb +17 -11
  58. data/lib/sequel/adapters/do/postgres.rb +2 -61
  59. data/lib/sequel/adapters/do/sqlite.rb +0 -10
  60. data/lib/sequel/adapters/do.rb +20 -39
  61. data/lib/sequel/adapters/firebird.rb +33 -210
  62. data/lib/sequel/adapters/ibmdb.rb +452 -0
  63. data/lib/sequel/adapters/informix.rb +6 -29
  64. data/lib/sequel/adapters/jdbc/as400.rb +16 -34
  65. data/lib/sequel/adapters/jdbc/cubrid.rb +52 -0
  66. data/lib/sequel/adapters/jdbc/db2.rb +78 -0
  67. data/lib/sequel/adapters/jdbc/derby.rb +325 -0
  68. data/lib/sequel/adapters/jdbc/firebird.rb +24 -0
  69. data/lib/sequel/adapters/jdbc/h2.rb +68 -31
  70. data/lib/sequel/adapters/jdbc/hsqldb.rb +189 -0
  71. data/lib/sequel/adapters/jdbc/informix.rb +21 -0
  72. data/lib/sequel/adapters/jdbc/jtds.rb +40 -0
  73. data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
  74. data/lib/sequel/adapters/jdbc/mysql.rb +16 -28
  75. data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
  76. data/lib/sequel/adapters/jdbc/postgresql.rb +77 -52
  77. data/lib/sequel/adapters/jdbc/progress.rb +21 -0
  78. data/lib/sequel/adapters/jdbc/sqlite.rb +20 -10
  79. data/lib/sequel/adapters/jdbc/sqlserver.rb +72 -0
  80. data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
  81. data/lib/sequel/adapters/jdbc.rb +308 -114
  82. data/lib/sequel/adapters/mock.rb +372 -0
  83. data/lib/sequel/adapters/mysql.rb +130 -230
  84. data/lib/sequel/adapters/mysql2.rb +64 -63
  85. data/lib/sequel/adapters/odbc/mssql.rb +17 -9
  86. data/lib/sequel/adapters/odbc.rb +29 -10
  87. data/lib/sequel/adapters/openbase.rb +7 -11
  88. data/lib/sequel/adapters/oracle.rb +364 -57
  89. data/lib/sequel/adapters/postgres.rb +379 -145
  90. data/lib/sequel/adapters/shared/access.rb +236 -11
  91. data/lib/sequel/adapters/shared/cubrid.rb +216 -0
  92. data/lib/sequel/adapters/shared/db2.rb +353 -0
  93. data/lib/sequel/adapters/shared/firebird.rb +231 -0
  94. data/lib/sequel/adapters/shared/informix.rb +53 -0
  95. data/lib/sequel/adapters/shared/mssql.rb +412 -116
  96. data/lib/sequel/adapters/shared/mysql.rb +396 -89
  97. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +166 -0
  98. data/lib/sequel/adapters/shared/oracle.rb +262 -45
  99. data/lib/sequel/adapters/shared/postgres.rb +688 -279
  100. data/lib/sequel/adapters/shared/progress.rb +5 -8
  101. data/lib/sequel/adapters/shared/sqlite.rb +317 -96
  102. data/lib/sequel/adapters/sqlite.rb +109 -46
  103. data/lib/sequel/adapters/swift/mysql.rb +10 -12
  104. data/lib/sequel/adapters/swift/postgres.rb +13 -79
  105. data/lib/sequel/adapters/swift/sqlite.rb +9 -6
  106. data/lib/sequel/adapters/swift.rb +31 -27
  107. data/lib/sequel/adapters/tinytds.rb +177 -25
  108. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +77 -0
  109. data/lib/sequel/adapters/utils/pg_types.rb +81 -0
  110. data/lib/sequel/adapters/utils/split_alter_table.rb +36 -0
  111. data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
  112. data/lib/sequel/ast_transformer.rb +194 -0
  113. data/lib/sequel/connection_pool/sharded_single.rb +23 -13
  114. data/lib/sequel/connection_pool/sharded_threaded.rb +64 -13
  115. data/lib/sequel/connection_pool/single.rb +11 -3
  116. data/lib/sequel/connection_pool/threaded.rb +69 -20
  117. data/lib/sequel/connection_pool.rb +20 -18
  118. data/lib/sequel/core.rb +143 -11
  119. data/lib/sequel/database/connecting.rb +66 -29
  120. data/lib/sequel/database/dataset.rb +4 -4
  121. data/lib/sequel/database/dataset_defaults.rb +63 -2
  122. data/lib/sequel/database/logging.rb +7 -2
  123. data/lib/sequel/database/misc.rb +192 -51
  124. data/lib/sequel/database/query.rb +299 -114
  125. data/lib/sequel/database/schema_generator.rb +103 -36
  126. data/lib/sequel/database/schema_methods.rb +310 -69
  127. data/lib/sequel/dataset/actions.rb +344 -90
  128. data/lib/sequel/dataset/features.rb +101 -8
  129. data/lib/sequel/dataset/graph.rb +42 -15
  130. data/lib/sequel/dataset/misc.rb +52 -25
  131. data/lib/sequel/dataset/mutation.rb +12 -7
  132. data/lib/sequel/dataset/prepared_statements.rb +68 -30
  133. data/lib/sequel/dataset/query.rb +322 -68
  134. data/lib/sequel/dataset/sql.rb +716 -293
  135. data/lib/sequel/dataset.rb +8 -0
  136. data/lib/sequel/exceptions.rb +4 -0
  137. data/lib/sequel/extensions/_pretty_table.rb +83 -0
  138. data/lib/sequel/extensions/arbitrary_servers.rb +109 -0
  139. data/lib/sequel/extensions/blank.rb +4 -0
  140. data/lib/sequel/extensions/columns_introspection.rb +72 -0
  141. data/lib/sequel/extensions/connection_validator.rb +109 -0
  142. data/lib/sequel/extensions/constraint_validations.rb +451 -0
  143. data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +30 -46
  144. data/lib/sequel/extensions/eval_inspect.rb +173 -0
  145. data/lib/sequel/extensions/inflector.rb +4 -0
  146. data/lib/sequel/extensions/looser_typecasting.rb +5 -4
  147. data/lib/sequel/extensions/migration.rb +100 -11
  148. data/lib/sequel/extensions/named_timezones.rb +9 -0
  149. data/lib/sequel/extensions/null_dataset.rb +94 -0
  150. data/lib/sequel/extensions/pagination.rb +4 -0
  151. data/lib/sequel/extensions/pg_array.rb +539 -0
  152. data/lib/sequel/extensions/pg_array_ops.rb +263 -0
  153. data/lib/sequel/extensions/pg_auto_parameterize.rb +175 -0
  154. data/lib/sequel/extensions/pg_hstore.rb +334 -0
  155. data/lib/sequel/extensions/pg_hstore_ops.rb +293 -0
  156. data/lib/sequel/extensions/pg_inet.rb +113 -0
  157. data/lib/sequel/extensions/pg_interval.rb +191 -0
  158. data/lib/sequel/extensions/pg_json.rb +212 -0
  159. data/lib/sequel/extensions/pg_range.rb +513 -0
  160. data/lib/sequel/extensions/pg_range_ops.rb +150 -0
  161. data/lib/sequel/extensions/pg_row.rb +576 -0
  162. data/lib/sequel/extensions/pg_row_ops.rb +182 -0
  163. data/lib/sequel/extensions/pg_statement_cache.rb +317 -0
  164. data/lib/sequel/extensions/pretty_table.rb +17 -72
  165. data/lib/sequel/extensions/query.rb +8 -4
  166. data/lib/sequel/extensions/query_literals.rb +79 -0
  167. data/lib/sequel/extensions/schema_caching.rb +76 -0
  168. data/lib/sequel/extensions/schema_dumper.rb +282 -76
  169. data/lib/sequel/extensions/select_remove.rb +39 -0
  170. data/lib/sequel/extensions/server_block.rb +140 -0
  171. data/lib/sequel/extensions/split_array_nil.rb +65 -0
  172. data/lib/sequel/extensions/sql_expr.rb +8 -110
  173. data/lib/sequel/extensions/string_date_time.rb +4 -0
  174. data/lib/sequel/extensions/thread_local_timezones.rb +10 -4
  175. data/lib/sequel/extensions/to_dot.rb +99 -83
  176. data/lib/sequel/model/associations.rb +1263 -409
  177. data/lib/sequel/model/base.rb +624 -171
  178. data/lib/sequel/model/errors.rb +1 -1
  179. data/lib/sequel/model/exceptions.rb +24 -2
  180. data/lib/sequel/model/inflections.rb +1 -1
  181. data/lib/sequel/model.rb +30 -11
  182. data/lib/sequel/no_core_ext.rb +2 -0
  183. data/lib/sequel/plugins/active_model.rb +13 -1
  184. data/lib/sequel/plugins/association_pks.rb +137 -16
  185. data/lib/sequel/plugins/caching.rb +25 -18
  186. data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
  187. data/lib/sequel/plugins/composition.rb +44 -12
  188. data/lib/sequel/plugins/constraint_validations.rb +198 -0
  189. data/lib/sequel/plugins/dataset_associations.rb +100 -0
  190. data/lib/sequel/plugins/defaults_setter.rb +72 -0
  191. data/lib/sequel/plugins/dirty.rb +214 -0
  192. data/lib/sequel/plugins/eager_each.rb +59 -0
  193. data/lib/sequel/plugins/force_encoding.rb +6 -6
  194. data/lib/sequel/plugins/hook_class_methods.rb +1 -1
  195. data/lib/sequel/plugins/identity_map.rb +134 -15
  196. data/lib/sequel/plugins/instance_filters.rb +10 -0
  197. data/lib/sequel/plugins/instance_hooks.rb +1 -1
  198. data/lib/sequel/plugins/json_serializer.rb +77 -6
  199. data/lib/sequel/plugins/list.rb +13 -2
  200. data/lib/sequel/plugins/many_through_many.rb +103 -51
  201. data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
  202. data/lib/sequel/plugins/nested_attributes.rb +150 -66
  203. data/lib/sequel/plugins/optimistic_locking.rb +8 -0
  204. data/lib/sequel/plugins/pg_row.rb +121 -0
  205. data/lib/sequel/plugins/pg_typecast_on_load.rb +65 -0
  206. data/lib/sequel/plugins/prepared_statements.rb +168 -0
  207. data/lib/sequel/plugins/prepared_statements_associations.rb +87 -0
  208. data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
  209. data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
  210. data/lib/sequel/plugins/rcte_tree.rb +31 -17
  211. data/lib/sequel/plugins/schema.rb +8 -3
  212. data/lib/sequel/plugins/serialization.rb +98 -49
  213. data/lib/sequel/plugins/serialization_modification_detection.rb +63 -0
  214. data/lib/sequel/plugins/sharding.rb +21 -54
  215. data/lib/sequel/plugins/single_table_inheritance.rb +57 -12
  216. data/lib/sequel/plugins/static_cache.rb +99 -0
  217. data/lib/sequel/plugins/subclasses.rb +29 -3
  218. data/lib/sequel/plugins/tactical_eager_loading.rb +7 -7
  219. data/lib/sequel/plugins/timestamps.rb +1 -1
  220. data/lib/sequel/plugins/touch.rb +18 -6
  221. data/lib/sequel/plugins/tree.rb +3 -3
  222. data/lib/sequel/plugins/typecast_on_load.rb +9 -12
  223. data/lib/sequel/plugins/update_primary_key.rb +2 -2
  224. data/lib/sequel/plugins/validation_class_methods.rb +2 -1
  225. data/lib/sequel/plugins/validation_helpers.rb +57 -4
  226. data/lib/sequel/plugins/xml_serializer.rb +15 -4
  227. data/lib/sequel/sql.rb +721 -141
  228. data/lib/sequel/timezones.rb +67 -40
  229. data/lib/sequel/version.rb +1 -1
  230. data/spec/adapters/db2_spec.rb +146 -0
  231. data/spec/adapters/firebird_spec.rb +53 -39
  232. data/spec/adapters/mssql_spec.rb +261 -66
  233. data/spec/adapters/mysql_spec.rb +597 -352
  234. data/spec/adapters/oracle_spec.rb +92 -117
  235. data/spec/adapters/postgres_spec.rb +2103 -341
  236. data/spec/adapters/spec_helper.rb +16 -6
  237. data/spec/adapters/sqlite_spec.rb +237 -76
  238. data/spec/core/connection_pool_spec.rb +270 -141
  239. data/spec/core/database_spec.rb +980 -524
  240. data/spec/core/dataset_spec.rb +1658 -1243
  241. data/spec/core/expression_filters_spec.rb +741 -334
  242. data/spec/core/mock_adapter_spec.rb +453 -0
  243. data/spec/core/object_graph_spec.rb +88 -129
  244. data/spec/core/schema_generator_spec.rb +4 -4
  245. data/spec/core/schema_spec.rb +556 -53
  246. data/spec/core/spec_helper.rb +7 -48
  247. data/spec/core_extensions_spec.rb +626 -0
  248. data/spec/extensions/active_model_spec.rb +13 -0
  249. data/spec/extensions/arbitrary_servers_spec.rb +110 -0
  250. data/spec/extensions/association_autoreloading_spec.rb +18 -10
  251. data/spec/extensions/association_dependencies_spec.rb +15 -25
  252. data/spec/extensions/association_pks_spec.rb +227 -33
  253. data/spec/extensions/association_proxies_spec.rb +4 -4
  254. data/spec/extensions/boolean_readers_spec.rb +25 -25
  255. data/spec/extensions/caching_spec.rb +47 -51
  256. data/spec/extensions/class_table_inheritance_spec.rb +31 -83
  257. data/spec/extensions/columns_introspection_spec.rb +91 -0
  258. data/spec/extensions/composition_spec.rb +18 -13
  259. data/spec/extensions/connection_validator_spec.rb +118 -0
  260. data/spec/extensions/constraint_validations_plugin_spec.rb +196 -0
  261. data/spec/extensions/constraint_validations_spec.rb +316 -0
  262. data/spec/extensions/dataset_associations_spec.rb +199 -0
  263. data/spec/extensions/defaults_setter_spec.rb +88 -0
  264. data/spec/extensions/dirty_spec.rb +155 -0
  265. data/spec/extensions/eager_each_spec.rb +34 -0
  266. data/spec/extensions/eval_inspect_spec.rb +67 -0
  267. data/spec/extensions/force_encoding_spec.rb +4 -2
  268. data/spec/extensions/hook_class_methods_spec.rb +97 -128
  269. data/spec/extensions/identity_map_spec.rb +142 -24
  270. data/spec/extensions/inflector_spec.rb +0 -4
  271. data/spec/extensions/instance_filters_spec.rb +11 -21
  272. data/spec/extensions/instance_hooks_spec.rb +72 -0
  273. data/spec/extensions/json_serializer_spec.rb +49 -12
  274. data/spec/extensions/lazy_attributes_spec.rb +16 -20
  275. data/spec/extensions/list_spec.rb +49 -40
  276. data/spec/extensions/looser_typecasting_spec.rb +7 -7
  277. data/spec/extensions/many_through_many_spec.rb +368 -254
  278. data/spec/extensions/many_to_one_pk_lookup_spec.rb +140 -0
  279. data/spec/extensions/migration_spec.rb +140 -35
  280. data/spec/extensions/named_timezones_spec.rb +29 -11
  281. data/spec/extensions/nested_attributes_spec.rb +268 -89
  282. data/spec/extensions/null_dataset_spec.rb +85 -0
  283. data/spec/extensions/optimistic_locking_spec.rb +24 -21
  284. data/spec/extensions/pg_array_ops_spec.rb +112 -0
  285. data/spec/extensions/pg_array_spec.rb +324 -0
  286. data/spec/extensions/pg_auto_parameterize_spec.rb +65 -0
  287. data/spec/extensions/pg_hstore_ops_spec.rb +140 -0
  288. data/spec/extensions/pg_hstore_spec.rb +200 -0
  289. data/spec/extensions/pg_inet_spec.rb +47 -0
  290. data/spec/extensions/pg_interval_spec.rb +72 -0
  291. data/spec/extensions/pg_json_spec.rb +99 -0
  292. data/spec/extensions/pg_range_ops_spec.rb +56 -0
  293. data/spec/extensions/pg_range_spec.rb +395 -0
  294. data/spec/extensions/pg_row_ops_spec.rb +58 -0
  295. data/spec/extensions/pg_row_plugin_spec.rb +49 -0
  296. data/spec/extensions/pg_row_spec.rb +340 -0
  297. data/spec/extensions/pg_statement_cache_spec.rb +208 -0
  298. data/spec/extensions/pg_typecast_on_load_spec.rb +58 -0
  299. data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
  300. data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
  301. data/spec/extensions/prepared_statements_spec.rb +87 -0
  302. data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
  303. data/spec/extensions/pretty_table_spec.rb +7 -6
  304. data/spec/extensions/query_literals_spec.rb +167 -0
  305. data/spec/extensions/query_spec.rb +9 -3
  306. data/spec/extensions/rcte_tree_spec.rb +50 -43
  307. data/spec/extensions/schema_caching_spec.rb +41 -0
  308. data/spec/extensions/schema_dumper_spec.rb +434 -49
  309. data/spec/extensions/schema_spec.rb +30 -49
  310. data/spec/extensions/select_remove_spec.rb +38 -0
  311. data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
  312. data/spec/extensions/serialization_spec.rb +86 -48
  313. data/spec/extensions/server_block_spec.rb +90 -0
  314. data/spec/extensions/sharding_spec.rb +69 -143
  315. data/spec/extensions/single_table_inheritance_spec.rb +65 -29
  316. data/spec/extensions/skip_create_refresh_spec.rb +1 -1
  317. data/spec/extensions/spec_helper.rb +34 -67
  318. data/spec/extensions/split_array_nil_spec.rb +24 -0
  319. data/spec/extensions/sql_expr_spec.rb +29 -60
  320. data/spec/extensions/static_cache_spec.rb +145 -0
  321. data/spec/extensions/subclasses_spec.rb +14 -0
  322. data/spec/extensions/tactical_eager_loading_spec.rb +17 -19
  323. data/spec/extensions/thread_local_timezones_spec.rb +22 -2
  324. data/spec/extensions/timestamps_spec.rb +6 -6
  325. data/spec/extensions/to_dot_spec.rb +8 -11
  326. data/spec/extensions/touch_spec.rb +53 -14
  327. data/spec/extensions/tree_spec.rb +11 -26
  328. data/spec/extensions/typecast_on_load_spec.rb +9 -6
  329. data/spec/extensions/update_primary_key_spec.rb +30 -24
  330. data/spec/extensions/validation_class_methods_spec.rb +77 -68
  331. data/spec/extensions/validation_helpers_spec.rb +48 -37
  332. data/spec/extensions/xml_serializer_spec.rb +29 -4
  333. data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +4 -0
  334. data/spec/files/transaction_specified_migrations/002_create_basic.rb +4 -0
  335. data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +3 -0
  336. data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +3 -0
  337. data/spec/integration/associations_test.rb +659 -21
  338. data/spec/integration/database_test.rb +25 -5
  339. data/spec/integration/dataset_test.rb +729 -141
  340. data/spec/integration/eager_loader_test.rb +38 -54
  341. data/spec/integration/migrator_test.rb +2 -3
  342. data/spec/integration/model_test.rb +81 -2
  343. data/spec/integration/plugin_test.rb +871 -160
  344. data/spec/integration/prepared_statement_test.rb +272 -128
  345. data/spec/integration/schema_test.rb +377 -57
  346. data/spec/integration/spec_helper.rb +49 -32
  347. data/spec/integration/timezone_test.rb +38 -12
  348. data/spec/integration/transaction_test.rb +183 -8
  349. data/spec/integration/type_test.rb +40 -8
  350. data/spec/model/association_reflection_spec.rb +207 -8
  351. data/spec/model/associations_spec.rb +1206 -693
  352. data/spec/model/base_spec.rb +334 -100
  353. data/spec/model/dataset_methods_spec.rb +45 -27
  354. data/spec/model/eager_loading_spec.rb +828 -692
  355. data/spec/model/hooks_spec.rb +355 -67
  356. data/spec/model/model_spec.rb +251 -179
  357. data/spec/model/plugins_spec.rb +24 -13
  358. data/spec/model/record_spec.rb +506 -232
  359. data/spec/model/spec_helper.rb +16 -77
  360. data/spec/model/validations_spec.rb +38 -2
  361. data/spec/rcov.opts +2 -0
  362. metadata +223 -81
  363. data/spec/core/core_sql_spec.rb +0 -451
@@ -1,5 +1,6 @@
1
1
  require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper')
2
2
 
3
+
3
4
  describe "Sequel::Schema::Generator dump methods" do
4
5
  before do
5
6
  @d = Sequel::Database.new
@@ -43,19 +44,17 @@ describe "Sequel::Schema::Generator dump methods" do
43
44
  index [:b, :c], :unique=>true
44
45
  end
45
46
 
46
- t = <<END_CODE
47
+ g.dump_indexes(:add_index=>:t).should == (<<END_CODE).strip
47
48
  add_index :t, [:a]
48
49
  add_index :t, [:c, :e], :name=>:blah
49
50
  add_index :t, [:b, :c], :unique=>true
50
51
  END_CODE
51
- g.dump_indexes(:add_index=>:t).should == t.strip
52
52
 
53
- t = <<END_CODE
54
- drop_index :t, [:a]
55
- drop_index :t, [:c, :e], :name=>:blah
53
+ g.dump_indexes(:drop_index=>:t).should == (<<END_CODE).strip
56
54
  drop_index :t, [:b, :c], :unique=>true
55
+ drop_index :t, [:c, :e], :name=>:blah
56
+ drop_index :t, [:a]
57
57
  END_CODE
58
- g.dump_indexes(:drop_index=>:t).should == t.strip
59
58
  end
60
59
 
61
60
  it "should raise an error if you try to dump a Generator that uses a constraint with a proc" do
@@ -69,21 +68,14 @@ describe "Sequel::Database dump methods" do
69
68
  @d.meta_def(:tables){|o| [:t1, :t2]}
70
69
  @d.meta_def(:schema) do |t, *o|
71
70
  case t
72
- when :t1, 't__t1', :t__t1.identifier
71
+ when :t1, 't__t1', Sequel.identifier(:t__t1)
73
72
  [[:c1, {:db_type=>'integer', :primary_key=>true, :allow_null=>false}],
74
73
  [:c2, {:db_type=>'varchar(20)', :allow_null=>true}]]
75
74
  when :t2
76
75
  [[:c1, {:db_type=>'integer', :primary_key=>true, :allow_null=>false}],
77
76
  [:c2, {:db_type=>'numeric', :primary_key=>true, :allow_null=>false}]]
78
- when :t3
79
- [[:c1, {:db_type=>'date', :default=>"'now()'", :allow_null=>true}],
80
- [:c2, {:db_type=>'datetime', :allow_null=>false}]]
81
77
  when :t5
82
78
  [[:c1, {:db_type=>'blahblah', :allow_null=>true}]]
83
- when :t6
84
- [[:c1, {:db_type=>'bigint', :primary_key=>true, :allow_null=>true}]]
85
- when :t7
86
- [[:c1, {:db_type=>'somedbspecifictype', :primary_key=>true, :allow_null=>false}]]
87
79
  end
88
80
  end
89
81
  end
@@ -97,21 +89,90 @@ describe "Sequel::Database dump methods" do
97
89
  end
98
90
 
99
91
  it "should support dumping table schemas when given an identifier" do
100
- @d.dump_table_schema(:t__t1.identifier).should == "create_table(\"t__t1\") do\n primary_key :c1\n String :c2, :size=>20\nend"
92
+ @d.dump_table_schema(Sequel.identifier(:t__t1)).should == "create_table(\"t__t1\") do\n primary_key :c1\n String :c2, :size=>20\nend"
101
93
  end
102
94
 
103
95
  it "should dump non-Integer primary key columns with explicit :type" do
96
+ @d.meta_def(:schema){|*s| [[:c1, {:db_type=>'bigint', :primary_key=>true, :allow_null=>true}]]}
104
97
  @d.dump_table_schema(:t6).should == "create_table(:t6) do\n primary_key :c1, :type=>Bignum\nend"
105
98
  end
106
99
 
107
- it "should dump primary key columns with explicit :type equal to the database type when :same_db option is passed" do
108
- @d.dump_table_schema(:t7, :same_db => true).should == "create_table(:t7) do\n primary_key :c1, :type=>\"somedbspecifictype\"\nend"
100
+ it "should handle foreign keys" do
101
+ @d.meta_def(:schema){|*s| [[:c1, {:db_type=>'integer', :allow_null=>true}]]}
102
+ @d.meta_def(:foreign_key_list){|*s| [{:columns=>[:c1], :table=>:t2, :key=>[:c2]}]}
103
+ @d.dump_table_schema(:t6).should == "create_table(:t6) do\n foreign_key :c1, :t2, :key=>[:c2]\nend"
104
+ end
105
+
106
+ it "should handle primary keys that are also foreign keys" do
107
+ @d.meta_def(:schema){|*s| [[:c1, {:db_type=>'integer', :primary_key=>true, :allow_null=>true}]]}
108
+ @d.meta_def(:foreign_key_list){|*s| [{:columns=>[:c1], :table=>:t2, :key=>[:c2]}]}
109
+ s = @d.dump_table_schema(:t6)
110
+ s.should =~ /create_table\(:t6\) do\n primary_key :c1, /
111
+ s.should =~ /:table=>:t2/
112
+ s.should =~ /:key=>\[:c2\]/
113
+ end
114
+
115
+ it "should handle foreign key options" do
116
+ @d.meta_def(:schema){|*s| [[:c1, {:db_type=>'integer', :allow_null=>true}]]}
117
+ @d.meta_def(:foreign_key_list){|*s| [{:columns=>[:c1], :table=>:t2, :key=>[:c2], :on_delete=>:restrict, :on_update=>:set_null, :deferrable=>true}]}
118
+ s = @d.dump_table_schema(:t6)
119
+ s.should =~ /create_table\(:t6\) do\n foreign_key :c1, :t2, /
120
+ s.should =~ /:key=>\[:c2\]/
121
+ s.should =~ /:on_delete=>:restrict/
122
+ s.should =~ /:on_update=>:set_null/
123
+ s.should =~ /:deferrable=>true/
124
+ end
125
+
126
+ it "should handle foreign key options in the primary key" do
127
+ @d.meta_def(:schema){|*s| [[:c1, {:db_type=>'integer', :primary_key=>true, :allow_null=>true}]]}
128
+ @d.meta_def(:foreign_key_list){|*s| [{:columns=>[:c1], :table=>:t2, :key=>[:c2], :on_delete=>:restrict, :on_update=>:set_null, :deferrable=>true}]}
129
+ s = @d.dump_table_schema(:t6)
130
+ s.should =~ /create_table\(:t6\) do\n primary_key :c1, /
131
+ s.should =~ /:table=>:t2/
132
+ s.should =~ /:key=>\[:c2\]/
133
+ s.should =~ /:on_delete=>:restrict/
134
+ s.should =~ /:on_update=>:set_null/
135
+ s.should =~ /:deferrable=>true/
136
+ end
137
+
138
+ it "should omit foreign key options that are the same as defaults" do
139
+ @d.meta_def(:schema){|*s| [[:c1, {:db_type=>'integer', :allow_null=>true}]]}
140
+ @d.meta_def(:foreign_key_list){|*s| [{:columns=>[:c1], :table=>:t2, :key=>[:c2], :on_delete=>:no_action, :on_update=>:no_action, :deferrable=>false}]}
141
+ s = @d.dump_table_schema(:t6)
142
+ s.should =~ /create_table\(:t6\) do\n foreign_key :c1, :t2, /
143
+ s.should =~ /:key=>\[:c2\]/
144
+ s.should_not =~ /:on_delete/
145
+ s.should_not =~ /:on_update/
146
+ s.should_not =~ /:deferrable/
147
+ end
148
+
149
+ it "should omit foreign key options that are the same as defaults in the primary key" do
150
+ @d.meta_def(:schema){|*s| [[:c1, {:db_type=>'integer', :primary_key=>true, :allow_null=>true}]]}
151
+ @d.meta_def(:foreign_key_list){|*s| [{:columns=>[:c1], :table=>:t2, :key=>[:c2], :on_delete=>:no_action, :on_update=>:no_action, :deferrable=>false}]}
152
+ s = @d.dump_table_schema(:t6)
153
+ s.should =~ /create_table\(:t6\) do\n primary_key :c1, /
154
+ s.should =~ /:table=>:t2/
155
+ s.should =~ /:key=>\[:c2\]/
156
+ s.should_not =~ /:on_delete/
157
+ s.should_not =~ /:on_update/
158
+ s.should_not =~ /:deferrable/
159
+ end
160
+
161
+ it "should dump primary key columns with explicit type equal to the database type when :same_db option is passed" do
162
+ @d.meta_def(:schema){|*s| [[:c1, {:db_type=>'somedbspecifictype', :primary_key=>true, :allow_null=>false}]]}
163
+ @d.dump_table_schema(:t7, :same_db => true).should == "create_table(:t7) do\n column :c1, \"somedbspecifictype\", :null=>false\n \n primary_key [:c1]\nend"
109
164
  end
110
165
 
111
166
  it "should use a composite primary_key calls if there is a composite primary key" do
112
167
  @d.dump_table_schema(:t2).should == "create_table(:t2) do\n Integer :c1, :null=>false\n BigDecimal :c2, :null=>false\n \n primary_key [:c1, :c2]\nend"
113
168
  end
114
169
 
170
+ it "should use a composite foreign_key calls if there is a composite foreign key" do
171
+ @d.meta_def(:schema){|*s| [[:c1, {:db_type=>'integer'}], [:c2, {:db_type=>'integer'}]]}
172
+ @d.meta_def(:foreign_key_list){|*s| [{:columns=>[:c1, :c2], :table=>:t2, :key=>[:c3, :c4]}]}
173
+ @d.dump_table_schema(:t1).should == "create_table(:t1) do\n Integer :c1\n Integer :c2\n \n foreign_key [:c1, :c2], :t2, :key=>[:c3, :c4]\nend"
174
+ end
175
+
115
176
  it "should include index information if available" do
116
177
  @d.meta_def(:indexes) do |t|
117
178
  {:i1=>{:columns=>[:c1], :unique=>false},
@@ -123,7 +184,7 @@ describe "Sequel::Database dump methods" do
123
184
  it "should support dumping the whole database as a migration" do
124
185
  @d.dump_schema_migration.should == <<-END_MIG
125
186
  Sequel.migration do
126
- up do
187
+ change do
127
188
  create_table(:t1) do
128
189
  primary_key :c1
129
190
  String :c2, :size=>20
@@ -136,10 +197,6 @@ Sequel.migration do
136
197
  primary_key [:c1, :c2]
137
198
  end
138
199
  end
139
-
140
- down do
141
- drop_table(:t1, :t2)
142
- end
143
200
  end
144
201
  END_MIG
145
202
  end
@@ -148,7 +205,7 @@ END_MIG
148
205
  @d.meta_def(:tables){|o| [:t2, :t1]}
149
206
  @d.dump_schema_migration.should == <<-END_MIG
150
207
  Sequel.migration do
151
- up do
208
+ change do
152
209
  create_table(:t1) do
153
210
  primary_key :c1
154
211
  String :c2, :size=>20
@@ -161,9 +218,79 @@ Sequel.migration do
161
218
  primary_key [:c1, :c2]
162
219
  end
163
220
  end
164
-
165
- down do
166
- drop_table(:t1, :t2)
221
+ end
222
+ END_MIG
223
+ end
224
+
225
+ it "should sort table names topologically when dumping a migration with foreign keys" do
226
+ @d.meta_def(:tables){|o| [:t1, :t2]}
227
+ @d.meta_def(:schema) do |t|
228
+ t == :t1 ? [[:c2, {:db_type=>'integer'}]] : [[:c1, {:db_type=>'integer', :primary_key=>true}]]
229
+ end
230
+ @d.meta_def(:foreign_key_list) do |t|
231
+ t == :t1 ? [{:columns=>[:c2], :table=>:t2, :key=>[:c1]}] : []
232
+ end
233
+ @d.dump_schema_migration.should == <<-END_MIG
234
+ Sequel.migration do
235
+ change do
236
+ create_table(:t2) do
237
+ primary_key :c1
238
+ end
239
+
240
+ create_table(:t1) do
241
+ foreign_key :c2, :t2, :key=>[:c1]
242
+ end
243
+ end
244
+ end
245
+ END_MIG
246
+ end
247
+
248
+ it "should handle circular dependencies when dumping a migration with foreign keys" do
249
+ @d.meta_def(:tables){|o| [:t1, :t2]}
250
+ @d.meta_def(:schema) do |t|
251
+ t == :t1 ? [[:c2, {:db_type=>'integer'}]] : [[:c1, {:db_type=>'integer'}]]
252
+ end
253
+ @d.meta_def(:foreign_key_list) do |t|
254
+ t == :t1 ? [{:columns=>[:c2], :table=>:t2, :key=>[:c1]}] : [{:columns=>[:c1], :table=>:t1, :key=>[:c2]}]
255
+ end
256
+ @d.dump_schema_migration.should == <<-END_MIG
257
+ Sequel.migration do
258
+ change do
259
+ create_table(:t1) do
260
+ Integer :c2
261
+ end
262
+
263
+ create_table(:t2) do
264
+ foreign_key :c1, :t1, :key=>[:c2]
265
+ end
266
+
267
+ alter_table(:t1) do
268
+ add_foreign_key [:c2], :t2, :key=>[:c1]
269
+ end
270
+ end
271
+ end
272
+ END_MIG
273
+ end
274
+
275
+ it "should sort topologically even if the database raises an error when trying to parse foreign keys for a non-existent table" do
276
+ @d.meta_def(:tables){|o| [:t1, :t2]}
277
+ @d.meta_def(:schema) do |t|
278
+ t == :t1 ? [[:c2, {:db_type=>'integer'}]] : [[:c1, {:db_type=>'integer', :primary_key=>true}]]
279
+ end
280
+ @d.meta_def(:foreign_key_list) do |t|
281
+ raise Sequel::DatabaseError unless [:t1, :t2].include?(t)
282
+ t == :t1 ? [{:columns=>[:c2], :table=>:t2, :key=>[:c1]}] : []
283
+ end
284
+ @d.dump_schema_migration.should == <<-END_MIG
285
+ Sequel.migration do
286
+ change do
287
+ create_table(:t2) do
288
+ primary_key :c1
289
+ end
290
+
291
+ create_table(:t1) do
292
+ foreign_key :c2, :t2, :key=>[:c1]
293
+ end
167
294
  end
168
295
  end
169
296
  END_MIG
@@ -173,7 +300,7 @@ END_MIG
173
300
  @d.dump_table_schema(:t1, :same_db=>true).should == "create_table(:t1) do\n primary_key :c1\n column :c2, \"varchar(20)\"\nend"
174
301
  @d.dump_schema_migration(:same_db=>true).should == <<-END_MIG
175
302
  Sequel.migration do
176
- up do
303
+ change do
177
304
  create_table(:t1) do
178
305
  primary_key :c1
179
306
  column :c2, "varchar(20)"
@@ -186,9 +313,99 @@ Sequel.migration do
186
313
  primary_key [:c1, :c2]
187
314
  end
188
315
  end
316
+ end
317
+ END_MIG
318
+ end
319
+
320
+ it "should honor the :index_names => false option to not include names of indexes" do
321
+ @d.meta_def(:indexes) do |t|
322
+ {:i1=>{:columns=>[:c1], :unique=>false},
323
+ :t1_c2_c1_index=>{:columns=>[:c2, :c1], :unique=>true}}
324
+ end
325
+ @d.dump_table_schema(:t1, :index_names=>false).should == "create_table(:t1, :ignore_index_errors=>true) do\n primary_key :c1\n String :c2, :size=>20\n \n index [:c1]\n index [:c2, :c1], :unique=>true\nend"
326
+ @d.dump_schema_migration(:index_names=>false).should == <<-END_MIG
327
+ Sequel.migration do
328
+ change do
329
+ create_table(:t1, :ignore_index_errors=>true) do
330
+ primary_key :c1
331
+ String :c2, :size=>20
332
+
333
+ index [:c1]
334
+ index [:c2, :c1], :unique=>true
335
+ end
336
+
337
+ create_table(:t2, :ignore_index_errors=>true) do
338
+ Integer :c1, :null=>false
339
+ BigDecimal :c2, :null=>false
340
+
341
+ primary_key [:c1, :c2]
342
+
343
+ index [:c1]
344
+ index [:c2, :c1], :unique=>true
345
+ end
346
+ end
347
+ end
348
+ END_MIG
349
+ end
189
350
 
190
- down do
191
- drop_table(:t1, :t2)
351
+ it "should make :index_names => :namespace option a noop if there is a global index namespace" do
352
+ @d.meta_def(:indexes) do |t|
353
+ {:i1=>{:columns=>[:c1], :unique=>false},
354
+ :t1_c2_c1_index=>{:columns=>[:c2, :c1], :unique=>false}}
355
+ end
356
+ @d.dump_table_schema(:t1, :index_names=>:namespace).should == "create_table(:t1, :ignore_index_errors=>true) do\n primary_key :c1\n String :c2, :size=>20\n \n index [:c1], :name=>:i1\n index [:c2, :c1]\nend"
357
+ @d.dump_schema_migration(:index_names=>:namespace).should == <<-END_MIG
358
+ Sequel.migration do
359
+ change do
360
+ create_table(:t1, :ignore_index_errors=>true) do
361
+ primary_key :c1
362
+ String :c2, :size=>20
363
+
364
+ index [:c1], :name=>:i1
365
+ index [:c2, :c1]
366
+ end
367
+
368
+ create_table(:t2, :ignore_index_errors=>true) do
369
+ Integer :c1, :null=>false
370
+ BigDecimal :c2, :null=>false
371
+
372
+ primary_key [:c1, :c2]
373
+
374
+ index [:c1], :name=>:i1
375
+ index [:c2, :c1], :name=>:t1_c2_c1_index
376
+ end
377
+ end
378
+ end
379
+ END_MIG
380
+ end
381
+
382
+ it "should honor the :index_names => :namespace option to include names of indexes with prepended table name if there is no global index namespace" do
383
+ @d.meta_def(:global_index_namespace?){false}
384
+ @d.meta_def(:indexes) do |t|
385
+ {:i1=>{:columns=>[:c1], :unique=>false},
386
+ :t1_c2_c1_index=>{:columns=>[:c2, :c1], :unique=>false}}
387
+ end
388
+ @d.dump_table_schema(:t1, :index_names=>:namespace).should == "create_table(:t1, :ignore_index_errors=>true) do\n primary_key :c1\n String :c2, :size=>20\n \n index [:c1], :name=>:t1_i1\n index [:c2, :c1]\nend"
389
+ @d.dump_schema_migration(:index_names=>:namespace).should == <<-END_MIG
390
+ Sequel.migration do
391
+ change do
392
+ create_table(:t1, :ignore_index_errors=>true) do
393
+ primary_key :c1
394
+ String :c2, :size=>20
395
+
396
+ index [:c1], :name=>:t1_i1
397
+ index [:c2, :c1]
398
+ end
399
+
400
+ create_table(:t2, :ignore_index_errors=>true) do
401
+ Integer :c1, :null=>false
402
+ BigDecimal :c2, :null=>false
403
+
404
+ primary_key [:c1, :c2]
405
+
406
+ index [:c1], :name=>:t2_i1
407
+ index [:c2, :c1], :name=>:t2_t1_c2_c1_index
408
+ end
192
409
  end
193
410
  end
194
411
  END_MIG
@@ -202,7 +419,7 @@ END_MIG
202
419
  @d.dump_table_schema(:t1, :indexes=>false).should == "create_table(:t1) do\n primary_key :c1\n String :c2, :size=>20\nend"
203
420
  @d.dump_schema_migration(:indexes=>false).should == <<-END_MIG
204
421
  Sequel.migration do
205
- up do
422
+ change do
206
423
  create_table(:t1) do
207
424
  primary_key :c1
208
425
  String :c2, :size=>20
@@ -215,14 +432,24 @@ Sequel.migration do
215
432
  primary_key [:c1, :c2]
216
433
  end
217
434
  end
218
-
219
- down do
220
- drop_table(:t1, :t2)
221
- end
222
435
  end
223
436
  END_MIG
224
437
  end
225
438
 
439
+ it "should have :indexes => false option disable foreign keys as well when dumping a whole migration" do
440
+ @d.meta_def(:foreign_key_list) do |t|
441
+ t == :t1 ? [{:columns=>[:c2], :table=>:t2, :key=>[:c1]}] : []
442
+ end
443
+ @d.dump_schema_migration(:indexes=>false).should_not =~ /foreign_key/
444
+ end
445
+
446
+ it "should have :foreign_keys option override :indexes => false disabling of foreign keys" do
447
+ @d.meta_def(:foreign_key_list) do |t|
448
+ t == :t1 ? [{:columns=>[:c2], :table=>:t2, :key=>[:c1]}] : []
449
+ end
450
+ @d.dump_schema_migration(:indexes=>false, :foreign_keys=>true).should =~ /foreign_key/
451
+ end
452
+
226
453
  it "should support dumping just indexes as a migration" do
227
454
  @d.meta_def(:tables){|o| [:t1]}
228
455
  @d.meta_def(:indexes) do |t|
@@ -231,20 +458,123 @@ END_MIG
231
458
  end
232
459
  @d.dump_indexes_migration.should == <<-END_MIG
233
460
  Sequel.migration do
234
- up do
461
+ change do
235
462
  add_index :t1, [:c1], :ignore_errors=>true, :name=>:i1
236
463
  add_index :t1, [:c2, :c1], :ignore_errors=>true, :unique=>true
237
464
  end
238
-
239
- down do
240
- drop_index :t1, [:c1], :ignore_errors=>true, :name=>:i1
241
- drop_index :t1, [:c2, :c1], :ignore_errors=>true, :unique=>true
465
+ end
466
+ END_MIG
467
+ end
468
+
469
+ it "should honor the :index_names => false option to not include names of indexes when dumping just indexes as a migration" do
470
+ @d.meta_def(:tables){|o| [:t1]}
471
+ @d.meta_def(:indexes) do |t|
472
+ {:i1=>{:columns=>[:c1], :unique=>false},
473
+ :t1_c2_c1_index=>{:columns=>[:c2, :c1], :unique=>true}}
474
+ end
475
+ @d.dump_indexes_migration(:index_names=>false).should == <<-END_MIG
476
+ Sequel.migration do
477
+ change do
478
+ add_index :t1, [:c1], :ignore_errors=>true
479
+ add_index :t1, [:c2, :c1], :ignore_errors=>true, :unique=>true
480
+ end
481
+ end
482
+ END_MIG
483
+ end
484
+
485
+ it "should honor the :index_names => :namespace option be a noop if there is a global index namespace" do
486
+ @d.meta_def(:tables){|o| [:t1, :t2]}
487
+ @d.meta_def(:indexes) do |t|
488
+ {:i1=>{:columns=>[:c1], :unique=>false},
489
+ :t1_c2_c1_index=>{:columns=>[:c2, :c1], :unique=>false}}
490
+ end
491
+ @d.dump_indexes_migration(:index_names=>:namespace).should == <<-END_MIG
492
+ Sequel.migration do
493
+ change do
494
+ add_index :t1, [:c1], :ignore_errors=>true, :name=>:i1
495
+ add_index :t1, [:c2, :c1], :ignore_errors=>true
496
+
497
+ add_index :t2, [:c1], :ignore_errors=>true, :name=>:i1
498
+ add_index :t2, [:c2, :c1], :ignore_errors=>true, :name=>:t1_c2_c1_index
499
+ end
500
+ end
501
+ END_MIG
502
+ end
503
+
504
+ it "should honor the :index_names => :namespace option to include names of indexes with prepended table name when dumping just indexes as a migration if there is no global index namespace" do
505
+ @d.meta_def(:global_index_namespace?){false}
506
+ @d.meta_def(:tables){|o| [:t1, :t2]}
507
+ @d.meta_def(:indexes) do |t|
508
+ {:i1=>{:columns=>[:c1], :unique=>false},
509
+ :t1_c2_c1_index=>{:columns=>[:c2, :c1], :unique=>false}}
510
+ end
511
+ @d.dump_indexes_migration(:index_names=>:namespace).should == <<-END_MIG
512
+ Sequel.migration do
513
+ change do
514
+ add_index :t1, [:c1], :ignore_errors=>true, :name=>:t1_i1
515
+ add_index :t1, [:c2, :c1], :ignore_errors=>true
516
+
517
+ add_index :t2, [:c1], :ignore_errors=>true, :name=>:t2_i1
518
+ add_index :t2, [:c2, :c1], :ignore_errors=>true, :name=>:t2_t1_c2_c1_index
519
+ end
520
+ end
521
+ END_MIG
522
+ end
523
+
524
+ it "should handle missing index parsing support when dumping index migration" do
525
+ @d.meta_def(:tables){|o| [:t1]}
526
+ @d.dump_indexes_migration.should == <<-END_MIG
527
+ Sequel.migration do
528
+ change do
529
+
530
+ end
531
+ end
532
+ END_MIG
533
+ end
534
+
535
+ it "should handle missing foreign key parsing support when dumping foreign key migration" do
536
+ @d.meta_def(:tables){|o| [:t1]}
537
+ @d.dump_foreign_key_migration.should == <<-END_MIG
538
+ Sequel.migration do
539
+ change do
540
+
541
+ end
542
+ end
543
+ END_MIG
544
+ end
545
+
546
+ it "should support dumping just foreign_keys as a migration" do
547
+ @d.meta_def(:tables){|o| [:t1, :t2, :t3]}
548
+ @d.meta_def(:schema) do |t|
549
+ t == :t1 ? [[:c2, {:db_type=>'integer'}]] : [[:c1, {:db_type=>'integer'}]]
550
+ end
551
+ @d.meta_def(:foreign_key_list) do |t, *a|
552
+ case t
553
+ when :t1
554
+ [{:columns=>[:c2], :table=>:t2, :key=>[:c1]}]
555
+ when :t2
556
+ [{:columns=>[:c1, :c3], :table=>:t1, :key=>[:c2, :c4]}]
557
+ else
558
+ []
559
+ end
560
+ end
561
+ @d.dump_foreign_key_migration.should == <<-END_MIG
562
+ Sequel.migration do
563
+ change do
564
+ alter_table(:t1) do
565
+ add_foreign_key [:c2], :t2, :key=>[:c1]
566
+ end
567
+
568
+ alter_table(:t2) do
569
+ add_foreign_key [:c1, :c3], :t1, :key=>[:c2, :c4]
570
+ end
242
571
  end
243
572
  end
244
573
  END_MIG
245
574
  end
246
575
 
247
576
  it "should handle not null values and defaults" do
577
+ @d.meta_def(:schema){|*s| [[:c1, {:db_type=>'date', :default=>"'now()'", :allow_null=>true}], [:c2, {:db_type=>'datetime', :allow_null=>false}]]}
248
578
  @d.dump_table_schema(:t3).should == "create_table(:t3) do\n Date :c1\n DateTime :c2, :null=>false\nend"
249
579
  end
250
580
 
@@ -259,22 +589,24 @@ END_MIG
259
589
  [:c7, {:db_type=>'date', :default=>"'2008-10-29'", :type=>:date, :allow_null=>true}],
260
590
  [:c8, {:db_type=>'datetime', :default=>"'2008-10-29 10:20:30'", :type=>:datetime, :allow_null=>true}],
261
591
  [:c9, {:db_type=>'time', :default=>"'10:20:30'", :type=>:time, :allow_null=>true}],
262
- [:c10, {:db_type=>'interval', :default=>"'6 weeks'", :type=>:interval, :allow_null=>true}]]
592
+ [:c10, {:db_type=>'foo', :default=>"'6 weeks'", :type=>nil, :allow_null=>true}],
593
+ [:c11, {:db_type=>'date', :default=>"CURRENT_DATE", :type=>:date, :allow_null=>true}],
594
+ [:c12, {:db_type=>'timestamp', :default=>"now()", :type=>:datetime, :allow_null=>true}]]
263
595
  s.each{|_, c| c[:ruby_default] = column_schema_to_ruby_default(c[:default], c[:type])}
264
596
  s
265
597
  end
266
- @d.dump_table_schema(:t4).gsub(/[+-]\d\d:\d\d"\)/, '")').should == "create_table(:t4) do\n TrueClass :c1, :default=>false\n String :c2, :default=>\"blah\"\n Integer :c3, :default=>-1\n Float :c4, :default=>1.0\n BigDecimal :c5, :default=>BigDecimal.new(\"0.1005E3\")\n File :c6, :default=>Sequel::SQL::Blob.new(\"blah\")\n Date :c7, :default=>Date.parse(\"2008-10-29\")\n DateTime :c8, :default=>DateTime.parse(\"2008-10-29T10:20:30\")\n Time :c9, :default=>Time.parse(\"10:20:30\"), :only_time=>true\n String :c10\nend"
267
- @d.dump_table_schema(:t4, :same_db=>true).gsub(/[+-]\d\d:\d\d"\)/, '")').should == "create_table(:t4) do\n column :c1, \"boolean\", :default=>false\n column :c2, \"varchar\", :default=>\"blah\"\n column :c3, \"integer\", :default=>-1\n column :c4, \"float\", :default=>1.0\n column :c5, \"decimal\", :default=>BigDecimal.new(\"0.1005E3\")\n column :c6, \"blob\", :default=>Sequel::SQL::Blob.new(\"blah\")\n column :c7, \"date\", :default=>Date.parse(\"2008-10-29\")\n column :c8, \"datetime\", :default=>DateTime.parse(\"2008-10-29T10:20:30\")\n column :c9, \"time\", :default=>Time.parse(\"10:20:30\")\n column :c10, \"interval\", :default=>\"'6 weeks'\".lit\nend"
598
+ @d.dump_table_schema(:t4).gsub(/[+-]\d\d\d\d"\)/, '")').gsub(/\.0+/, '.0').should == "create_table(:t4) do\n TrueClass :c1, :default=>false\n String :c2, :default=>\"blah\"\n Integer :c3, :default=>-1\n Float :c4, :default=>1.0\n BigDecimal :c5, :default=>BigDecimal.new(\"0.1005E3\")\n File :c6, :default=>Sequel::SQL::Blob.new(\"blah\")\n Date :c7, :default=>Date.new(2008, 10, 29)\n DateTime :c8, :default=>DateTime.parse(\"2008-10-29T10:20:30.0\")\n Time :c9, :default=>Sequel::SQLTime.parse(\"10:20:30.0\"), :only_time=>true\n String :c10\n Date :c11, :default=>Sequel::CURRENT_DATE\n DateTime :c12, :default=>Sequel::CURRENT_TIMESTAMP\nend"
599
+ @d.dump_table_schema(:t4, :same_db=>true).gsub(/[+-]\d\d\d\d"\)/, '")').gsub(/\.0+/, '.0').should == "create_table(:t4) do\n column :c1, \"boolean\", :default=>false\n column :c2, \"varchar\", :default=>\"blah\"\n column :c3, \"integer\", :default=>-1\n column :c4, \"float\", :default=>1.0\n column :c5, \"decimal\", :default=>BigDecimal.new(\"0.1005E3\")\n column :c6, \"blob\", :default=>Sequel::SQL::Blob.new(\"blah\")\n column :c7, \"date\", :default=>Date.new(2008, 10, 29)\n column :c8, \"datetime\", :default=>DateTime.parse(\"2008-10-29T10:20:30.0\")\n column :c9, \"time\", :default=>Sequel::SQLTime.parse(\"10:20:30.0\")\n column :c10, \"foo\", :default=>Sequel::LiteralString.new(\"'6 weeks'\")\n column :c11, \"date\", :default=>Sequel::CURRENT_DATE\n column :c12, \"timestamp\", :default=>Sequel::CURRENT_TIMESTAMP\nend"
268
600
  end
269
601
 
270
- it "should not use a '...'.lit as a fallback if using MySQL with the :same_db option" do
602
+ it "should not use a literal string as a fallback if using MySQL with the :same_db option" do
271
603
  @d.meta_def(:database_type){:mysql}
272
604
  @d.meta_def(:schema) do |t, *os|
273
- s = [[:c10, {:db_type=>'interval', :default=>"'6 weeks'", :type=>:interval, :allow_null=>true}]]
605
+ s = [[:c10, {:db_type=>'foo', :default=>"'6 weeks'", :type=>nil, :allow_null=>true}]]
274
606
  s.each{|_, c| c[:ruby_default] = column_schema_to_ruby_default(c[:default], c[:type])}
275
607
  s
276
608
  end
277
- @d.dump_table_schema(:t5, :same_db=>true).should == "create_table(:t5) do\n column :c10, \"interval\"\nend"
609
+ @d.dump_table_schema(:t5, :same_db=>true).should == "create_table(:t5) do\n column :c10, \"foo\"\nend"
278
610
  end
279
611
 
280
612
  it "should convert unknown database types to strings" do
@@ -291,12 +623,14 @@ END_MIG
291
623
  ["double precision", "timestamp with time zone", "timestamp without time zone",
292
624
  "time with time zone", "time without time zone", "character varying(20)"] +
293
625
  %w"nvarchar ntext smalldatetime smallmoney binary varbinary nchar" +
294
- ["timestamp(6) without time zone", "timestamp(6) with time zone", "int(12) unsigned", 'bigint unsigned']
626
+ ["timestamp(6) without time zone", "timestamp(6) with time zone", 'mediumint(10) unsigned', 'int(9) unsigned',
627
+ 'int(10) unsigned', "int(12) unsigned", 'bigint unsigned', 'tinyint(3) unsigned', 'identity', 'int identity'] +
628
+ %w"integer(10)"
295
629
  @d.meta_def(:schema) do |t, *o|
296
630
  i = 0
297
631
  types.map{|x| [:"c#{i+=1}", {:db_type=>x, :allow_null=>true}]}
298
632
  end
299
- table = <<END_MIG
633
+ @d.dump_table_schema(:x).should == (<<END_MIG).chomp
300
634
  create_table(:x) do
301
635
  Integer :c1
302
636
  Integer :c2
@@ -362,9 +696,60 @@ create_table(:x) do
362
696
  DateTime :c62, :size=>6
363
697
  DateTime :c63, :size=>6
364
698
  Integer :c64
365
- Bignum :c65
699
+ Integer :c65
700
+ Bignum :c66
701
+ Bignum :c67
702
+ Bignum :c68
703
+ Integer :c69
704
+ Integer :c70
705
+ Integer :c71
706
+ Integer :c72
707
+
708
+ check Sequel::SQL::BooleanExpression.new(:>=, Sequel::SQL::Identifier.new(:c64), 0)
709
+ check Sequel::SQL::BooleanExpression.new(:>=, Sequel::SQL::Identifier.new(:c65), 0)
710
+ check Sequel::SQL::BooleanExpression.new(:>=, Sequel::SQL::Identifier.new(:c66), 0)
711
+ check Sequel::SQL::BooleanExpression.new(:>=, Sequel::SQL::Identifier.new(:c67), 0)
712
+ check Sequel::SQL::BooleanExpression.new(:>=, Sequel::SQL::Identifier.new(:c68), 0)
713
+ check Sequel::SQL::BooleanExpression.new(:>=, Sequel::SQL::Identifier.new(:c69), 0)
366
714
  end
367
715
  END_MIG
368
- @d.dump_table_schema(:x).should == table.chomp
716
+ end
717
+
718
+ it "should convert mysql types to ruby types" do
719
+ types = ['double(15,2)', 'double(7,1) unsigned']
720
+ @d.meta_def(:schema) do |t, *o|
721
+ i = 0
722
+ types.map{|x| [:"c#{i+=1}", {:db_type=>x, :allow_null=>true}]}
723
+ end
724
+ @d.dump_table_schema(:x).should == (<<END_MIG).chomp
725
+ create_table(:x) do
726
+ Float :c1
727
+ Float :c2
728
+
729
+ check Sequel::SQL::BooleanExpression.new(:>=, Sequel::SQL::Identifier.new(:c2), 0)
730
+ end
731
+ END_MIG
732
+ end
733
+
734
+ it "should use separate primary_key call with non autoincrementable types" do
735
+ @d.meta_def(:schema){|*s| [[:c1, {:db_type=>'varchar(8)', :primary_key=>true}]]}
736
+ @d.dump_table_schema(:t3).should == "create_table(:t3) do\n String :c1, :size=>8\n \n primary_key [:c1]\nend"
737
+ @d.dump_table_schema(:t3, :same_db=>true).should == "create_table(:t3) do\n column :c1, \"varchar(8)\"\n \n primary_key [:c1]\nend"
738
+ end
739
+
740
+ it "should use explicit type for non integer foreign_key types" do
741
+ @d.meta_def(:schema){|*s| [[:c1, {:db_type=>'date', :primary_key=>true}]]}
742
+ @d.meta_def(:foreign_key_list){|t, *a| [{:columns=>[:c1], :table=>:t3, :key=>[:c1]}] if t == :t4}
743
+ ["create_table(:t4) do\n foreign_key :c1, :t3, :type=>Date, :key=>[:c1]\n \n primary_key [:c1]\nend",
744
+ "create_table(:t4) do\n foreign_key :c1, :t3, :key=>[:c1], :type=>Date\n \n primary_key [:c1]\nend"].should include(@d.dump_table_schema(:t4))
745
+ ["create_table(:t4) do\n foreign_key :c1, :t3, :type=>\"date\", :key=>[:c1]\n \n primary_key [:c1]\nend",
746
+ "create_table(:t4) do\n foreign_key :c1, :t3, :key=>[:c1], :type=>\"date\"\n \n primary_key [:c1]\nend"].should include(@d.dump_table_schema(:t4, :same_db=>true))
747
+ end
748
+
749
+ it "should correctly handing autoincrementing primary keys that are also foreign keys" do
750
+ @d.meta_def(:schema){|*s| [[:c1, {:db_type=>'integer', :primary_key=>true}]]}
751
+ @d.meta_def(:foreign_key_list){|t, *a| [{:columns=>[:c1], :table=>:t3, :key=>[:c1]}] if t == :t4}
752
+ ["create_table(:t4) do\n primary_key :c1, :table=>:t3, :key=>[:c1]\nend",
753
+ "create_table(:t4) do\n primary_key :c1, :key=>[:c1], :table=>:t3\nend"].should include(@d.dump_table_schema(:t4))
369
754
  end
370
755
  end