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,27 +1,30 @@
1
1
  module Sequel
2
2
  class Database
3
3
  # ---------------------
4
- # :section: Methods that modify the database schema
4
+ # :section: 2 - Methods that modify the database schema
5
5
  # These methods execute code on the database that modifies the database's schema.
6
6
  # ---------------------
7
7
 
8
8
  AUTOINCREMENT = 'AUTOINCREMENT'.freeze
9
- CASCADE = 'CASCADE'.freeze
10
9
  COMMA_SEPARATOR = ', '.freeze
11
- NO_ACTION = 'NO ACTION'.freeze
12
10
  NOT_NULL = ' NOT NULL'.freeze
13
11
  NULL = ' NULL'.freeze
14
12
  PRIMARY_KEY = ' PRIMARY KEY'.freeze
15
- RESTRICT = 'RESTRICT'.freeze
16
- SET_DEFAULT = 'SET DEFAULT'.freeze
17
- SET_NULL = 'SET NULL'.freeze
18
13
  TEMPORARY = 'TEMPORARY '.freeze
19
14
  UNDERSCORE = '_'.freeze
20
15
  UNIQUE = ' UNIQUE'.freeze
21
16
  UNSIGNED = ' UNSIGNED'.freeze
22
17
 
23
18
  # The order of column modifiers to use when defining a column.
24
- COLUMN_DEFINITION_ORDER = [:default, :null, :unique, :primary_key, :auto_increment, :references]
19
+ COLUMN_DEFINITION_ORDER = [:collate, :default, :null, :unique, :primary_key, :auto_increment, :references]
20
+
21
+ # The default options for join table columns.
22
+ DEFAULT_JOIN_TABLE_COLUMN_OPTIONS = {:null=>false}
23
+
24
+ # The alter table operations that are combinable.
25
+ COMBINABLE_ALTER_TABLE_OPS = [:add_column, :drop_column, :rename_column,
26
+ :set_column_type, :set_column_default, :set_column_null,
27
+ :add_constraint, :drop_constraint]
25
28
 
26
29
  # Adds a column to the specified table. This method expects a column name,
27
30
  # a datatype and optionally a hash with additional constraints and options:
@@ -29,7 +32,7 @@ module Sequel
29
32
  # DB.add_column :items, :name, :text, :unique => true, :null => false
30
33
  # DB.add_column :items, :category, :text, :default => 'ruby'
31
34
  #
32
- # See alter_table.
35
+ # See <tt>alter_table</tt>.
33
36
  def add_column(table, *args)
34
37
  alter_table(table) {add_column(*args)}
35
38
  end
@@ -40,9 +43,9 @@ module Sequel
40
43
  # DB.add_index :posts, [:author, :title], :unique => true
41
44
  #
42
45
  # Options:
43
- # * :ignore_errors - Ignore any DatabaseErrors that are raised
46
+ # :ignore_errors :: Ignore any DatabaseErrors that are raised
44
47
  #
45
- # See alter_table.
48
+ # See <tt>alter_table</tt>.
46
49
  def add_index(table, columns, options={})
47
50
  e = options[:ignore_errors]
48
51
  begin
@@ -65,17 +68,71 @@ module Sequel
65
68
  # end
66
69
  #
67
70
  # Note that +add_column+ accepts all the options available for column
68
- # definitions using create_table, and +add_index+ accepts all the options
71
+ # definitions using <tt>create_table</tt>, and +add_index+ accepts all the options
69
72
  # available for index definition.
70
73
  #
71
- # See Schema::AlterTableGenerator and the {"Migrations and Schema Modification" guide}[link:files/doc/migration_rdoc.html].
74
+ # See <tt>Schema::AlterTableGenerator</tt> and the {"Migrations and Schema Modification" guide}[link:files/doc/migration_rdoc.html].
72
75
  def alter_table(name, generator=nil, &block)
73
- generator ||= Schema::AlterTableGenerator.new(self, &block)
74
- alter_table_sql_list(name, generator.operations).flatten.each {|sql| execute_ddl(sql)}
76
+ generator ||= alter_table_generator(&block)
75
77
  remove_cached_schema(name)
78
+ apply_alter_table_generator(name, generator)
76
79
  nil
77
80
  end
78
-
81
+
82
+ # Return a new Schema::AlterTableGenerator instance with the receiver as
83
+ # the database and the given block.
84
+ def alter_table_generator(&block)
85
+ alter_table_generator_class.new(self, &block)
86
+ end
87
+
88
+ # Create a join table using a hash of foreign keys to referenced
89
+ # table names. Example:
90
+ #
91
+ # create_join_table(:cat_id=>:cats, :dog_id=>:dogs)
92
+ # # CREATE TABLE cats_dogs (
93
+ # # cat_id integer NOT NULL REFERENCES cats,
94
+ # # dog_id integer NOT NULL REFERENCES dogs,
95
+ # # PRIMARY KEY (cat_id, dog_id)
96
+ # # )
97
+ # # CREATE INDEX cats_dogs_dog_id_cat_id_index ON cats_dogs(dog_id, cat_id)
98
+ #
99
+ # The primary key and index are used so that almost all operations
100
+ # on the table can benefit from one of the two indexes, and the primary
101
+ # key ensures that entries in the table are unique, which is the typical
102
+ # desire for a join table.
103
+ #
104
+ # You can provide column options by making the values in the hash
105
+ # be option hashes, so long as the option hashes have a :table
106
+ # entry giving the table referenced:
107
+ #
108
+ # create_join_table(:cat_id=>{:table=>:cats, :type=>Bignum}, :dog_id=>:dogs)
109
+ #
110
+ # You can provide a second argument which is a table options hash:
111
+ #
112
+ # create_join_table({:cat_id=>:cats, :dog_id=>:dogs}, :temp=>true)
113
+ #
114
+ # Some table options are handled specially:
115
+ #
116
+ # :index_options :: The options to pass to the index
117
+ # :name :: The name of the table to create
118
+ # :no_index :: Set to true not to create the second index.
119
+ # :no_primary_key :: Set to true to not create the primary key.
120
+ def create_join_table(hash, options={})
121
+ keys = hash.keys.sort_by{|k| k.to_s}
122
+ create_table(join_table_name(hash, options), options) do
123
+ keys.each do |key|
124
+ v = hash[key]
125
+ unless v.is_a?(Hash)
126
+ v = {:table=>v}
127
+ end
128
+ v = DEFAULT_JOIN_TABLE_COLUMN_OPTIONS.merge(v)
129
+ foreign_key(key, v)
130
+ end
131
+ primary_key(keys) unless options[:no_primary_key]
132
+ index(keys.reverse, options[:index_options] || {}) unless options[:no_index]
133
+ end
134
+ end
135
+
79
136
  # Creates a table with the columns given in the provided block:
80
137
  #
81
138
  # DB.create_table :posts do
@@ -85,33 +142,64 @@ module Sequel
85
142
  # index :title
86
143
  # end
87
144
  #
88
- # Options:
89
- # :temp :: Create the table as a temporary table.
145
+ # General options:
146
+ # :as :: Create the table using the value, which should be either a
147
+ # dataset or a literal SQL string. If this option is used,
148
+ # a block should not be given to the method.
90
149
  # :ignore_index_errors :: Ignore any errors when creating indexes.
150
+ # :temp :: Create the table as a temporary table.
151
+ #
152
+ # MySQL specific options:
153
+ # :charset :: The character set to use for the table.
154
+ # :collate :: The collation to use for the table.
155
+ # :engine :: The table engine to use for the table.
156
+ #
157
+ # PostgreSQL specific options:
158
+ # :unlogged :: Create the table as an unlogged table.
91
159
  #
92
- # See Schema::Generator and the {"Migrations and Schema Modification" guide}[link:files/doc/migration_rdoc.html].
160
+ # See <tt>Schema::Generator</tt> and the {"Schema Modification" guide}[link:files/doc/schema_modification_rdoc.html].
93
161
  def create_table(name, options={}, &block)
94
162
  remove_cached_schema(name)
95
- options = {:generator=>options} if options.is_a?(Schema::Generator)
96
- generator = options[:generator] || Schema::Generator.new(self, &block)
97
- create_table_from_generator(name, generator, options)
98
- create_table_indexes_from_generator(name, generator, options)
99
- nil
163
+ options = {:generator=>options} if options.is_a?(Schema::CreateTableGenerator)
164
+ if sql = options[:as]
165
+ raise(Error, "can't provide both :as option and block to create_table") if block
166
+ create_table_as(name, sql, options)
167
+ else
168
+ generator = options[:generator] || create_table_generator(&block)
169
+ create_table_from_generator(name, generator, options)
170
+ create_table_indexes_from_generator(name, generator, options)
171
+ nil
172
+ end
100
173
  end
101
-
102
- # Forcibly creates a table, attempting to drop it unconditionally (and catching any errors), then creating it.
174
+
175
+ # Forcibly create a table, attempting to drop it if it already exists, then creating it.
103
176
  #
104
177
  # DB.create_table!(:a){Integer :a}
105
- # # DROP TABLE a
178
+ # # SELECT NULL FROM a LIMIT 1 -- check existence
179
+ # # DROP TABLE a -- drop table if already exists
106
180
  # # CREATE TABLE a (a integer)
107
181
  def create_table!(name, options={}, &block)
108
- drop_table(name) rescue nil
182
+ drop_table?(name)
109
183
  create_table(name, options, &block)
110
184
  end
111
185
 
112
- # Creates the table unless the table already exists
186
+ # Creates the table unless the table already exists.
187
+ #
188
+ # DB.create_table?(:a){Integer :a}
189
+ # # SELECT NULL FROM a LIMIT 1 -- check existence
190
+ # # CREATE TABLE a (a integer) -- if it doesn't already exist
113
191
  def create_table?(name, options={}, &block)
114
- create_table(name, options, &block) unless table_exists?(name)
192
+ if supports_create_table_if_not_exists?
193
+ create_table(name, options.merge(:if_not_exists=>true), &block)
194
+ elsif !table_exists?(name)
195
+ create_table(name, options, &block)
196
+ end
197
+ end
198
+
199
+ # Return a new Schema::CreateTableGenerator instance with the receiver as
200
+ # the database and the given block.
201
+ def create_table_generator(&block)
202
+ create_table_generator_class.new(self, &block)
115
203
  end
116
204
 
117
205
  # Creates a view, replacing it if it already exists:
@@ -138,7 +226,7 @@ module Sequel
138
226
  #
139
227
  # DB.drop_column :items, :category
140
228
  #
141
- # See alter_table.
229
+ # See <tt>alter_table</tt>.
142
230
  def drop_column(table, *args)
143
231
  alter_table(table) {drop_column(*args)}
144
232
  end
@@ -148,28 +236,63 @@ module Sequel
148
236
  # DB.drop_index :posts, :title
149
237
  # DB.drop_index :posts, [:author, :title]
150
238
  #
151
- # See alter_table.
239
+ # See <tt>alter_table</tt>.
152
240
  def drop_index(table, columns, options={})
153
241
  alter_table(table){drop_index(columns, options)}
154
242
  end
243
+
244
+ # Drop the join table that would have been created with the
245
+ # same arguments to create_join_table:
246
+ #
247
+ # drop_join_table(:cat_id=>:cats, :dog_id=>:dogs)
248
+ # # DROP TABLE cats_dogs
249
+ def drop_join_table(hash, options={})
250
+ drop_table(join_table_name(hash, options), options)
251
+ end
155
252
 
156
253
  # Drops one or more tables corresponding to the given names:
157
254
  #
255
+ # DB.drop_table(:posts) # DROP TABLE posts
158
256
  # DB.drop_table(:posts, :comments)
257
+ # DB.drop_table(:posts, :comments, :cascade=>true)
159
258
  def drop_table(*names)
259
+ options = names.last.is_a?(Hash) ? names.pop : {}
160
260
  names.each do |n|
161
- execute_ddl(drop_table_sql(n))
261
+ execute_ddl(drop_table_sql(n, options))
162
262
  remove_cached_schema(n)
163
263
  end
164
264
  nil
165
265
  end
166
266
 
267
+ # Drops the table if it already exists. If it doesn't exist,
268
+ # does nothing.
269
+ #
270
+ # DB.drop_table?(:a)
271
+ # # SELECT NULL FROM a LIMIT 1 -- check existence
272
+ # # DROP TABLE a -- if it already exists
273
+ def drop_table?(*names)
274
+ options = names.last.is_a?(Hash) ? names.pop : {}
275
+ if supports_drop_table_if_exists?
276
+ options = options.merge(:if_exists=>true)
277
+ names.each do |name|
278
+ drop_table(name, options)
279
+ end
280
+ else
281
+ names.each do |name|
282
+ drop_table(name, options) if table_exists?(name)
283
+ end
284
+ end
285
+ end
286
+
167
287
  # Drops one or more views corresponding to the given names:
168
288
  #
169
289
  # DB.drop_view(:cheap_items)
290
+ # DB.drop_view(:cheap_items, :pricey_items)
291
+ # DB.drop_view(:cheap_items, :pricey_items, :cascade=>true)
170
292
  def drop_view(*names)
293
+ options = names.last.is_a?(Hash) ? names.pop : {}
171
294
  names.each do |n|
172
- execute_ddl("DROP VIEW #{quote_schema_table(n)}")
295
+ execute_ddl(drop_view_sql(n, options))
173
296
  remove_cached_schema(n)
174
297
  end
175
298
  nil
@@ -191,7 +314,7 @@ module Sequel
191
314
  #
192
315
  # DB.rename_column :items, :cntr, :counter
193
316
  #
194
- # See alter_table.
317
+ # See <tt>alter_table</tt>.
195
318
  def rename_column(table, *args)
196
319
  alter_table(table) {rename_column(*args)}
197
320
  end
@@ -200,7 +323,7 @@ module Sequel
200
323
  #
201
324
  # DB.set_column_default :items, :category, 'perl!'
202
325
  #
203
- # See alter_table.
326
+ # See <tt>alter_table</tt>.
204
327
  def set_column_default(table, *args)
205
328
  alter_table(table) {set_column_default(*args)}
206
329
  end
@@ -209,22 +332,36 @@ module Sequel
209
332
  #
210
333
  # DB.set_column_type :items, :price, :float
211
334
  #
212
- # See alter_table.
335
+ # See <tt>alter_table</tt>.
213
336
  def set_column_type(table, *args)
214
337
  alter_table(table) {set_column_type(*args)}
215
338
  end
216
339
 
217
340
  private
218
341
 
219
- # The SQL to execute to modify the DDL for the given table name. op
220
- # should be one of the operations returned by the AlterTableGenerator.
221
- def alter_table_sql(table, op)
342
+ # Apply the changes in the given alter table ops to the table given by name.
343
+ def apply_alter_table(name, ops)
344
+ alter_table_sql_list(name, ops).each{|sql| execute_ddl(sql)}
345
+ end
346
+
347
+ # Apply the operations in the given generator to the table given by name.
348
+ def apply_alter_table_generator(name, generator)
349
+ apply_alter_table(name, generator.operations)
350
+ end
351
+
352
+ # The class used for alter_table generators.
353
+ def alter_table_generator_class
354
+ Schema::AlterTableGenerator
355
+ end
356
+
357
+ # SQL fragment for given alter table operation.
358
+ def alter_table_op_sql(table, op)
222
359
  quoted_name = quote_identifier(op[:name]) if op[:name]
223
- alter_table_op = case op[:op]
360
+ case op[:op]
224
361
  when :add_column
225
362
  "ADD COLUMN #{column_definition_sql(op)}"
226
363
  when :drop_column
227
- "DROP COLUMN #{quoted_name}"
364
+ "DROP COLUMN #{quoted_name}#{' CASCADE' if op[:cascade]}"
228
365
  when :rename_column
229
366
  "RENAME COLUMN #{quoted_name} TO #{quote_identifier(op[:new_name])}"
230
367
  when :set_column_type
@@ -233,24 +370,56 @@ module Sequel
233
370
  "ALTER COLUMN #{quoted_name} SET DEFAULT #{literal(op[:default])}"
234
371
  when :set_column_null
235
372
  "ALTER COLUMN #{quoted_name} #{op[:null] ? 'DROP' : 'SET'} NOT NULL"
236
- when :add_index
237
- return index_definition_sql(table, op)
238
- when :drop_index
239
- return drop_index_sql(table, op)
240
373
  when :add_constraint
241
374
  "ADD #{constraint_definition_sql(op)}"
242
375
  when :drop_constraint
243
- "DROP CONSTRAINT #{quoted_name}"
376
+ "DROP CONSTRAINT #{quoted_name}#{' CASCADE' if op[:cascade]}"
244
377
  else
245
- raise Error, "Unsupported ALTER TABLE operation"
378
+ raise Error, "Unsupported ALTER TABLE operation: #{op[:op]}"
379
+ end
380
+ end
381
+
382
+ # The SQL to execute to modify the DDL for the given table name. op
383
+ # should be one of the operations returned by the AlterTableGenerator.
384
+ def alter_table_sql(table, op)
385
+ case op[:op]
386
+ when :add_index
387
+ index_definition_sql(table, op)
388
+ when :drop_index
389
+ drop_index_sql(table, op)
390
+ else
391
+ "ALTER TABLE #{quote_schema_table(table)} #{alter_table_op_sql(table, op)}"
246
392
  end
247
- "ALTER TABLE #{quote_schema_table(table)} #{alter_table_op}"
248
393
  end
249
394
 
250
395
  # Array of SQL DDL modification statements for the given table,
251
396
  # corresponding to the DDL changes specified by the operations.
252
397
  def alter_table_sql_list(table, operations)
253
- operations.map{|op| alter_table_sql(table, op)}
398
+ if supports_combining_alter_table_ops?
399
+ grouped_ops = []
400
+ last_combinable = false
401
+ operations.each do |op|
402
+ if combinable_alter_table_op?(op)
403
+ if sql = alter_table_op_sql(table, op)
404
+ grouped_ops << [] unless last_combinable
405
+ grouped_ops.last << sql
406
+ last_combinable = true
407
+ end
408
+ elsif sql = alter_table_sql(table, op)
409
+ grouped_ops << sql
410
+ last_combinable = false
411
+ end
412
+ end
413
+ grouped_ops.map do |gop|
414
+ if gop.is_a?(Array)
415
+ "ALTER TABLE #{quote_schema_table(table)} #{gop.join(', ')}"
416
+ else
417
+ gop
418
+ end
419
+ end
420
+ else
421
+ operations.map{|op| alter_table_sql(table, op)}.flatten.compact
422
+ end
254
423
  end
255
424
 
256
425
  # The SQL string specify the autoincrement property, generally used by
@@ -275,7 +444,12 @@ module Sequel
275
444
  def column_definition_auto_increment_sql(sql, column)
276
445
  sql << " #{auto_increment_sql}" if column[:auto_increment]
277
446
  end
278
-
447
+
448
+ # Add collate SQL fragment to column creation SQL.
449
+ def column_definition_collate_sql(sql, column)
450
+ sql << " COLLATE #{column[:collate]}" if column[:collate]
451
+ end
452
+
279
453
  # Add default SQL fragment to column creation SQL.
280
454
  def column_definition_default_sql(sql, column)
281
455
  sql << " DEFAULT #{literal(column[:default])}" if column.include?(:default)
@@ -318,7 +492,7 @@ module Sequel
318
492
  sql = " REFERENCES #{quote_schema_table(column[:table])}"
319
493
  sql << "(#{Array(column[:key]).map{|x| quote_identifier(x)}.join(COMMA_SEPARATOR)})" if column[:key]
320
494
  sql << " ON DELETE #{on_delete_clause(column[:on_delete])}" if column[:on_delete]
321
- sql << " ON UPDATE #{on_delete_clause(column[:on_update])}" if column[:on_update]
495
+ sql << " ON UPDATE #{on_update_clause(column[:on_update])}" if column[:on_update]
322
496
  sql << " DEFERRABLE INITIALLY DEFERRED" if column[:deferrable]
323
497
  sql
324
498
  end
@@ -328,6 +502,12 @@ module Sequel
328
502
  "FOREIGN KEY #{literal(constraint[:columns])}#{column_references_sql(constraint)}"
329
503
  end
330
504
 
505
+ # Whether the given alter table operation is combinable.
506
+ def combinable_alter_table_op?(op)
507
+ # Use a dynamic lookup for easier overriding in adapters
508
+ COMBINABLE_ALTER_TABLE_OPS.include?(op[:op])
509
+ end
510
+
331
511
  # SQL DDL fragment specifying a constraint on a table.
332
512
  def constraint_definition_sql(constraint)
333
513
  sql = constraint[:name] ? "CONSTRAINT #{quote_identifier(constraint[:name])} " : ""
@@ -352,9 +532,14 @@ module Sequel
352
532
  execute_ddl(create_table_sql(name, generator, options))
353
533
  end
354
534
 
535
+ # The class used for create_table generators.
536
+ def create_table_generator_class
537
+ Schema::CreateTableGenerator
538
+ end
539
+
355
540
  # Execute the create index statements using the generator.
356
541
  def create_table_indexes_from_generator(name, generator, options)
357
- e = options[:ignore_index_errors]
542
+ e = options[:ignore_index_errors] || options[:if_not_exists]
358
543
  generator.indexes.each do |index|
359
544
  begin
360
545
  index_sql_list(name, [index]).each{|sql| execute_ddl(sql)}
@@ -366,7 +551,25 @@ module Sequel
366
551
 
367
552
  # DDL statement for creating a table with the given name, columns, and options
368
553
  def create_table_sql(name, generator, options)
369
- "CREATE #{temporary_table_sql if options[:temp]}TABLE #{quote_schema_table(name)} (#{column_list_sql(generator)})"
554
+ "#{create_table_prefix_sql(name, options)} (#{column_list_sql(generator)})"
555
+ end
556
+
557
+ # Run a command to create the table with the given name from the given
558
+ # SELECT sql statement.
559
+ def create_table_as(name, sql, options)
560
+ sql = sql.sql if sql.is_a?(Sequel::Dataset)
561
+ run(create_table_as_sql(name, sql, options))
562
+ end
563
+
564
+ # DDL statement for creating a table from the result of a SELECT statement.
565
+ # +sql+ should be a string representing a SELECT query.
566
+ def create_table_as_sql(name, sql, options)
567
+ "#{create_table_prefix_sql(name, options)} AS #{sql}"
568
+ end
569
+
570
+ # DDL statement for creating a table with the given name, columns, and options
571
+ def create_table_prefix_sql(name, options)
572
+ "CREATE #{temporary_table_sql if options[:temp]}TABLE#{' IF NOT EXISTS' if options[:if_not_exists]} #{options[:temp] ? quote_identifier(name) : quote_schema_table(name)}"
370
573
  end
371
574
 
372
575
  # Default index name for the table and columns, may be too long
@@ -382,10 +585,15 @@ module Sequel
382
585
  end
383
586
 
384
587
  # SQL DDL statement to drop the table with the given name.
385
- def drop_table_sql(name)
386
- "DROP TABLE #{quote_schema_table(name)}"
588
+ def drop_table_sql(name, options)
589
+ "DROP TABLE#{' IF EXISTS' if options[:if_exists]} #{quote_schema_table(name)}#{' CASCADE' if options[:cascade]}"
387
590
  end
388
591
 
592
+ # SQL DDL statement to drop a view with the given name.
593
+ def drop_view_sql(name, options)
594
+ "DROP VIEW #{quote_schema_table(name)}#{' CASCADE' if options[:cascade]}"
595
+ end
596
+
389
597
  # Proxy the filter_expr call to the dataset, used for creating constraints.
390
598
  def filter_expr(*args, &block)
391
599
  schema_utility_dataset.literal(schema_utility_dataset.send(:filter_expr, *args, &block))
@@ -410,6 +618,32 @@ module Sequel
410
618
  indexes.map{|i| index_definition_sql(table_name, i)}
411
619
  end
412
620
 
621
+ # Extract the join table name from the arguments given to create_join_table.
622
+ # Also does argument validation for the create_join_table method.
623
+ def join_table_name(hash, options)
624
+ entries = hash.values
625
+ raise Error, "must have 2 entries in hash given to (create|drop)_join_table" unless entries.length == 2
626
+ if options[:name]
627
+ options[:name]
628
+ else
629
+ table_names = entries.map{|e| join_table_name_extract(e)}
630
+ table_names.map{|t| t.to_s}.sort.join('_')
631
+ end
632
+ end
633
+
634
+ # Extract an individual join table name, which should either be a string
635
+ # or symbol, or a hash containing one of those as the value for :table.
636
+ def join_table_name_extract(entry)
637
+ case entry
638
+ when Symbol, String
639
+ entry
640
+ when Hash
641
+ join_table_name_extract(entry[:table])
642
+ else
643
+ raise Error, "can't extract table name from #{entry.inspect}"
644
+ end
645
+ end
646
+
413
647
  # SQL DDL ON DELETE fragment to use, based on the given action.
414
648
  # The following actions are recognized:
415
649
  #
@@ -420,19 +654,15 @@ module Sequel
420
654
  # but do not allow deferring the integrity check.
421
655
  # * :set_default - Set columns referencing this row to their default value.
422
656
  # * :set_null - Set columns referencing this row to NULL.
657
+ #
658
+ # Any other object given is just converted to a string, with "_" converted to " " and upcased.
423
659
  def on_delete_clause(action)
424
- case action
425
- when :restrict
426
- RESTRICT
427
- when :cascade
428
- CASCADE
429
- when :set_null
430
- SET_NULL
431
- when :set_default
432
- SET_DEFAULT
433
- else
434
- NO_ACTION
435
- end
660
+ action.to_s.gsub("_", " ").upcase
661
+ end
662
+
663
+ # Alias of #on_delete_clause, since the two usually behave the same.
664
+ def on_update_clause(action)
665
+ on_delete_clause(action)
436
666
  end
437
667
 
438
668
  # Proxy the quote_schema_table method to the dataset
@@ -463,7 +693,7 @@ module Sequel
463
693
 
464
694
  # Return true if the given column schema represents an autoincrementing primary key.
465
695
  def schema_autoincrementing_primary_key?(schema)
466
- !!schema[:primary_key]
696
+ !!(schema[:primary_key] && schema[:db_type] =~ /int/io)
467
697
  end
468
698
 
469
699
  # The dataset to use for proxying certain schema methods.
@@ -471,6 +701,12 @@ module Sequel
471
701
  @schema_utility_dataset ||= dataset
472
702
  end
473
703
 
704
+ # Whether the database supports combining multiple alter table
705
+ # operations into a single query, false by default.
706
+ def supports_combining_alter_table_ops?
707
+ false
708
+ end
709
+
474
710
  # SQL DDL fragment for temporary table
475
711
  def temporary_table_sql
476
712
  self.class.const_get(:TEMPORARY)
@@ -550,7 +786,7 @@ module Sequel
550
786
  # :text option is used, Sequel uses the :text type.
551
787
  def type_literal_generic_string(column)
552
788
  if column[:text]
553
- :text
789
+ uses_clob_for_text? ? :clob : :text
554
790
  elsif column[:fixed]
555
791
  "char(#{column[:size]||255})"
556
792
  else
@@ -578,5 +814,10 @@ module Sequel
578
814
  elements = column[:size] || column[:elements]
579
815
  "#{type}#{literal(Array(elements)) if elements}#{UNSIGNED if column[:unsigned]}"
580
816
  end
817
+
818
+ # Whether clob should be used for String :text=>true columns.
819
+ def uses_clob_for_text?
820
+ false
821
+ end
581
822
  end
582
823
  end