sequel 5.33.0 → 5.58.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 (191) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +318 -0
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +40 -9
  5. data/doc/association_basics.rdoc +77 -13
  6. data/doc/cheat_sheet.rdoc +13 -5
  7. data/doc/code_order.rdoc +0 -12
  8. data/doc/dataset_filtering.rdoc +2 -2
  9. data/doc/fork_safety.rdoc +84 -0
  10. data/doc/migration.rdoc +12 -6
  11. data/doc/model_plugins.rdoc +1 -1
  12. data/doc/opening_databases.rdoc +15 -3
  13. data/doc/postgresql.rdoc +9 -1
  14. data/doc/querying.rdoc +7 -5
  15. data/doc/release_notes/5.34.0.txt +40 -0
  16. data/doc/release_notes/5.35.0.txt +56 -0
  17. data/doc/release_notes/5.36.0.txt +60 -0
  18. data/doc/release_notes/5.37.0.txt +30 -0
  19. data/doc/release_notes/5.38.0.txt +28 -0
  20. data/doc/release_notes/5.39.0.txt +19 -0
  21. data/doc/release_notes/5.40.0.txt +40 -0
  22. data/doc/release_notes/5.41.0.txt +25 -0
  23. data/doc/release_notes/5.42.0.txt +136 -0
  24. data/doc/release_notes/5.43.0.txt +98 -0
  25. data/doc/release_notes/5.44.0.txt +32 -0
  26. data/doc/release_notes/5.45.0.txt +34 -0
  27. data/doc/release_notes/5.46.0.txt +87 -0
  28. data/doc/release_notes/5.47.0.txt +59 -0
  29. data/doc/release_notes/5.48.0.txt +14 -0
  30. data/doc/release_notes/5.49.0.txt +59 -0
  31. data/doc/release_notes/5.50.0.txt +78 -0
  32. data/doc/release_notes/5.51.0.txt +47 -0
  33. data/doc/release_notes/5.52.0.txt +87 -0
  34. data/doc/release_notes/5.53.0.txt +23 -0
  35. data/doc/release_notes/5.54.0.txt +27 -0
  36. data/doc/release_notes/5.55.0.txt +21 -0
  37. data/doc/release_notes/5.56.0.txt +51 -0
  38. data/doc/release_notes/5.57.0.txt +23 -0
  39. data/doc/release_notes/5.58.0.txt +31 -0
  40. data/doc/sql.rdoc +14 -2
  41. data/doc/testing.rdoc +10 -1
  42. data/doc/transactions.rdoc +0 -8
  43. data/doc/validations.rdoc +1 -1
  44. data/doc/virtual_rows.rdoc +1 -1
  45. data/lib/sequel/adapters/ado/access.rb +1 -1
  46. data/lib/sequel/adapters/ado.rb +17 -17
  47. data/lib/sequel/adapters/amalgalite.rb +3 -5
  48. data/lib/sequel/adapters/ibmdb.rb +2 -2
  49. data/lib/sequel/adapters/jdbc/derby.rb +8 -0
  50. data/lib/sequel/adapters/jdbc/h2.rb +60 -10
  51. data/lib/sequel/adapters/jdbc/hsqldb.rb +6 -0
  52. data/lib/sequel/adapters/jdbc/mysql.rb +4 -4
  53. data/lib/sequel/adapters/jdbc/postgresql.rb +4 -4
  54. data/lib/sequel/adapters/jdbc.rb +29 -19
  55. data/lib/sequel/adapters/mysql.rb +80 -67
  56. data/lib/sequel/adapters/mysql2.rb +54 -49
  57. data/lib/sequel/adapters/odbc.rb +8 -6
  58. data/lib/sequel/adapters/oracle.rb +5 -4
  59. data/lib/sequel/adapters/postgres.rb +27 -29
  60. data/lib/sequel/adapters/shared/access.rb +2 -0
  61. data/lib/sequel/adapters/shared/db2.rb +30 -0
  62. data/lib/sequel/adapters/shared/mssql.rb +84 -7
  63. data/lib/sequel/adapters/shared/mysql.rb +33 -2
  64. data/lib/sequel/adapters/shared/oracle.rb +82 -7
  65. data/lib/sequel/adapters/shared/postgres.rb +158 -20
  66. data/lib/sequel/adapters/shared/sqlanywhere.rb +3 -0
  67. data/lib/sequel/adapters/shared/sqlite.rb +102 -10
  68. data/lib/sequel/adapters/sqlanywhere.rb +1 -1
  69. data/lib/sequel/adapters/sqlite.rb +60 -18
  70. data/lib/sequel/adapters/tinytds.rb +2 -1
  71. data/lib/sequel/adapters/utils/columns_limit_1.rb +22 -0
  72. data/lib/sequel/adapters/utils/mysql_mysql2.rb +2 -1
  73. data/lib/sequel/ast_transformer.rb +6 -0
  74. data/lib/sequel/connection_pool/sharded_single.rb +9 -8
  75. data/lib/sequel/connection_pool/sharded_threaded.rb +10 -10
  76. data/lib/sequel/connection_pool/single.rb +7 -9
  77. data/lib/sequel/connection_pool/threaded.rb +1 -1
  78. data/lib/sequel/core.rb +33 -24
  79. data/lib/sequel/database/connecting.rb +3 -4
  80. data/lib/sequel/database/misc.rb +37 -12
  81. data/lib/sequel/database/query.rb +3 -1
  82. data/lib/sequel/database/schema_generator.rb +50 -53
  83. data/lib/sequel/database/schema_methods.rb +45 -23
  84. data/lib/sequel/database/transactions.rb +9 -6
  85. data/lib/sequel/dataset/actions.rb +61 -8
  86. data/lib/sequel/dataset/features.rb +15 -0
  87. data/lib/sequel/dataset/placeholder_literalizer.rb +3 -7
  88. data/lib/sequel/dataset/prepared_statements.rb +2 -0
  89. data/lib/sequel/dataset/query.rb +114 -11
  90. data/lib/sequel/dataset/sql.rb +172 -46
  91. data/lib/sequel/deprecated.rb +3 -1
  92. data/lib/sequel/exceptions.rb +2 -0
  93. data/lib/sequel/extensions/_pretty_table.rb +1 -2
  94. data/lib/sequel/extensions/any_not_empty.rb +1 -1
  95. data/lib/sequel/extensions/async_thread_pool.rb +438 -0
  96. data/lib/sequel/extensions/blank.rb +8 -0
  97. data/lib/sequel/extensions/columns_introspection.rb +1 -2
  98. data/lib/sequel/extensions/core_refinements.rb +38 -11
  99. data/lib/sequel/extensions/date_arithmetic.rb +36 -24
  100. data/lib/sequel/extensions/date_parse_input_handler.rb +67 -0
  101. data/lib/sequel/extensions/datetime_parse_to_time.rb +5 -1
  102. data/lib/sequel/extensions/duplicate_columns_handler.rb +3 -1
  103. data/lib/sequel/extensions/eval_inspect.rb +2 -0
  104. data/lib/sequel/extensions/inflector.rb +9 -1
  105. data/lib/sequel/extensions/is_distinct_from.rb +139 -0
  106. data/lib/sequel/extensions/migration.rb +13 -2
  107. data/lib/sequel/extensions/named_timezones.rb +5 -1
  108. data/lib/sequel/extensions/pagination.rb +1 -1
  109. data/lib/sequel/extensions/pg_array.rb +1 -0
  110. data/lib/sequel/extensions/pg_array_ops.rb +6 -2
  111. data/lib/sequel/extensions/pg_enum.rb +3 -1
  112. data/lib/sequel/extensions/pg_extended_date_support.rb +2 -2
  113. data/lib/sequel/extensions/pg_hstore.rb +1 -1
  114. data/lib/sequel/extensions/pg_hstore_ops.rb +55 -3
  115. data/lib/sequel/extensions/pg_inet.rb +2 -0
  116. data/lib/sequel/extensions/pg_inet_ops.rb +1 -1
  117. data/lib/sequel/extensions/pg_interval.rb +35 -8
  118. data/lib/sequel/extensions/pg_json.rb +3 -5
  119. data/lib/sequel/extensions/pg_json_ops.rb +119 -4
  120. data/lib/sequel/extensions/pg_loose_count.rb +3 -1
  121. data/lib/sequel/extensions/pg_multirange.rb +372 -0
  122. data/lib/sequel/extensions/pg_range.rb +7 -19
  123. data/lib/sequel/extensions/pg_range_ops.rb +39 -9
  124. data/lib/sequel/extensions/pg_row.rb +1 -1
  125. data/lib/sequel/extensions/pg_row_ops.rb +25 -1
  126. data/lib/sequel/extensions/query.rb +3 -0
  127. data/lib/sequel/extensions/run_transaction_hooks.rb +1 -1
  128. data/lib/sequel/extensions/s.rb +4 -1
  129. data/lib/sequel/extensions/schema_dumper.rb +16 -5
  130. data/lib/sequel/extensions/server_block.rb +8 -12
  131. data/lib/sequel/extensions/sql_comments.rb +110 -3
  132. data/lib/sequel/extensions/sql_log_normalizer.rb +108 -0
  133. data/lib/sequel/extensions/sqlite_json_ops.rb +255 -0
  134. data/lib/sequel/extensions/string_agg.rb +1 -1
  135. data/lib/sequel/extensions/string_date_time.rb +19 -23
  136. data/lib/sequel/extensions/symbol_aref_refinement.rb +2 -0
  137. data/lib/sequel/extensions/symbol_as_refinement.rb +2 -0
  138. data/lib/sequel/extensions/to_dot.rb +9 -3
  139. data/lib/sequel/model/associations.rb +342 -114
  140. data/lib/sequel/model/base.rb +45 -24
  141. data/lib/sequel/model/errors.rb +10 -1
  142. data/lib/sequel/model/inflections.rb +1 -1
  143. data/lib/sequel/model/plugins.rb +8 -3
  144. data/lib/sequel/model.rb +3 -1
  145. data/lib/sequel/plugins/association_pks.rb +60 -18
  146. data/lib/sequel/plugins/association_proxies.rb +3 -0
  147. data/lib/sequel/plugins/async_thread_pool.rb +39 -0
  148. data/lib/sequel/plugins/auto_restrict_eager_graph.rb +62 -0
  149. data/lib/sequel/plugins/auto_validations.rb +39 -5
  150. data/lib/sequel/plugins/auto_validations_constraint_validations_presence_message.rb +68 -0
  151. data/lib/sequel/plugins/blacklist_security.rb +1 -2
  152. data/lib/sequel/plugins/class_table_inheritance.rb +3 -8
  153. data/lib/sequel/plugins/column_encryption.rb +728 -0
  154. data/lib/sequel/plugins/composition.rb +8 -2
  155. data/lib/sequel/plugins/concurrent_eager_loading.rb +174 -0
  156. data/lib/sequel/plugins/constraint_validations.rb +2 -1
  157. data/lib/sequel/plugins/csv_serializer.rb +2 -0
  158. data/lib/sequel/plugins/dataset_associations.rb +4 -1
  159. data/lib/sequel/plugins/dirty.rb +44 -0
  160. data/lib/sequel/plugins/enum.rb +124 -0
  161. data/lib/sequel/plugins/forbid_lazy_load.rb +2 -0
  162. data/lib/sequel/plugins/insert_conflict.rb +4 -0
  163. data/lib/sequel/plugins/instance_specific_default.rb +113 -0
  164. data/lib/sequel/plugins/json_serializer.rb +39 -24
  165. data/lib/sequel/plugins/lazy_attributes.rb +4 -1
  166. data/lib/sequel/plugins/many_through_many.rb +108 -9
  167. data/lib/sequel/plugins/nested_attributes.rb +8 -3
  168. data/lib/sequel/plugins/pg_array_associations.rb +58 -41
  169. data/lib/sequel/plugins/pg_auto_constraint_validations.rb +2 -0
  170. data/lib/sequel/plugins/prepared_statements.rb +15 -12
  171. data/lib/sequel/plugins/prepared_statements_safe.rb +1 -3
  172. data/lib/sequel/plugins/rcte_tree.rb +37 -35
  173. data/lib/sequel/plugins/serialization.rb +9 -3
  174. data/lib/sequel/plugins/serialization_modification_detection.rb +2 -1
  175. data/lib/sequel/plugins/single_table_inheritance.rb +7 -0
  176. data/lib/sequel/plugins/sql_comments.rb +189 -0
  177. data/lib/sequel/plugins/static_cache.rb +1 -1
  178. data/lib/sequel/plugins/string_stripper.rb +1 -1
  179. data/lib/sequel/plugins/subclasses.rb +28 -11
  180. data/lib/sequel/plugins/tactical_eager_loading.rb +8 -2
  181. data/lib/sequel/plugins/timestamps.rb +1 -1
  182. data/lib/sequel/plugins/tree.rb +9 -4
  183. data/lib/sequel/plugins/unused_associations.rb +521 -0
  184. data/lib/sequel/plugins/update_or_create.rb +1 -1
  185. data/lib/sequel/plugins/validation_class_methods.rb +5 -1
  186. data/lib/sequel/plugins/validation_helpers.rb +18 -11
  187. data/lib/sequel/plugins/xml_serializer.rb +1 -1
  188. data/lib/sequel/sql.rb +1 -1
  189. data/lib/sequel/timezones.rb +20 -17
  190. data/lib/sequel/version.rb +1 -1
  191. metadata +93 -39
@@ -1,6 +1,7 @@
1
1
  # frozen-string-literal: true
2
2
 
3
3
  require_relative '../utils/emulate_offset_with_row_number'
4
+ require_relative '../utils/columns_limit_1'
4
5
 
5
6
  module Sequel
6
7
  module DB2
@@ -273,6 +274,7 @@ module Sequel
273
274
 
274
275
  module DatasetMethods
275
276
  include EmulateOffsetWithRowNumber
277
+ include ::Sequel::Dataset::ColumnsLimit1
276
278
 
277
279
  BITWISE_METHOD_MAP = {:& =>:BITAND, :| => :BITOR, :^ => :BITXOR, :'B~'=>:BITNOT}.freeze
278
280
 
@@ -336,6 +338,11 @@ module Sequel
336
338
  true
337
339
  end
338
340
 
341
+ # DB2 supports MERGE
342
+ def supports_merge?
343
+ true
344
+ end
345
+
339
346
  # DB2 does not support multiple columns in IN.
340
347
  def supports_multiple_column_in?
341
348
  false
@@ -358,6 +365,29 @@ module Sequel
358
365
 
359
366
  private
360
367
 
368
+ # Normalize conditions for MERGE WHEN.
369
+ def _merge_when_conditions_sql(sql, data)
370
+ if data.has_key?(:conditions)
371
+ sql << " AND "
372
+ literal_append(sql, _normalize_merge_when_conditions(data[:conditions]))
373
+ end
374
+ end
375
+
376
+ # Handle nil, false, and true MERGE WHEN conditions to avoid non-boolean
377
+ # type error.
378
+ def _normalize_merge_when_conditions(conditions)
379
+ case conditions
380
+ when nil, false
381
+ {1=>0}
382
+ when true
383
+ {1=>1}
384
+ when Sequel::SQL::DelayedEvaluation
385
+ Sequel.delay{_normalize_merge_when_conditions(conditions.call(self))}
386
+ else
387
+ conditions
388
+ end
389
+ end
390
+
361
391
  def empty_from_sql
362
392
  ' FROM "SYSIBM"."SYSDUMMY1"'
363
393
  end
@@ -24,6 +24,10 @@ module Sequel
24
24
  # Database object.
25
25
  attr_accessor :mssql_unicode_strings
26
26
 
27
+ # Whether to use LIKE without COLLATE Latin1_General_CS_AS. Skipping the COLLATE
28
+ # can significantly increase performance in some cases.
29
+ attr_accessor :like_without_collate
30
+
27
31
  # Execute the given stored procedure with the given name.
28
32
  #
29
33
  # Options:
@@ -244,6 +248,16 @@ module Sequel
244
248
 
245
249
  private
246
250
 
251
+ # Add CLUSTERED or NONCLUSTERED as needed
252
+ def add_clustered_sql_fragment(sql, opts)
253
+ clustered = opts[:clustered]
254
+ unless clustered.nil?
255
+ sql += " #{'NON' unless clustered}CLUSTERED"
256
+ end
257
+
258
+ sql
259
+ end
260
+
247
261
  # Add dropping of the default constraint to the list of SQL queries.
248
262
  # This is necessary before dropping the column or changing its type.
249
263
  def add_drop_default_constraint_sql(sqls, table, column)
@@ -284,7 +298,7 @@ module Sequel
284
298
  when :set_column_null
285
299
  sch = schema(table).find{|k,v| k.to_s == op[:name].to_s}.last
286
300
  type = sch[:db_type]
287
- if [:string, :decimal].include?(sch[:type]) && !["text", "ntext"].include?(type) && (size = (sch[:max_chars] || sch[:column_size]))
301
+ if [:string, :decimal, :blob].include?(sch[:type]) && !["text", "ntext"].include?(type) && (size = (sch[:max_chars] || sch[:column_size]))
288
302
  size = "MAX" if size == -1
289
303
  type += "(#{size}#{", #{sch[:scale]}" if sch[:scale] && sch[:scale].to_i > 0})"
290
304
  end
@@ -396,6 +410,11 @@ module Sequel
396
410
  super.with_quote_identifiers(true)
397
411
  end
398
412
 
413
+ # Handle clustered and nonclustered primary keys
414
+ def primary_key_constraint_sql_fragment(opts)
415
+ add_clustered_sql_fragment(super, opts)
416
+ end
417
+
399
418
  # Use sp_rename to rename the table
400
419
  def rename_table_sql(name, new_name)
401
420
  "sp_rename #{literal(quote_schema_table(name))}, #{quote_identifier(schema_and_table(new_name).pop)}"
@@ -492,6 +511,11 @@ module Sequel
492
511
  :'varbinary(max)'
493
512
  end
494
513
 
514
+ # Handle clustered and nonclustered unique constraints
515
+ def unique_constraint_sql_fragment(opts)
516
+ add_clustered_sql_fragment(super, opts)
517
+ end
518
+
495
519
  # MSSQL supports views with check option, but not local.
496
520
  def view_with_check_option_support
497
521
  true
@@ -528,9 +552,9 @@ module Sequel
528
552
  when :'||'
529
553
  super(sql, :+, args)
530
554
  when :LIKE, :"NOT LIKE"
531
- super(sql, op, args.map{|a| Sequel.lit(["(", " COLLATE Latin1_General_CS_AS)"], a)})
555
+ super(sql, op, complex_expression_sql_like_args(args, " COLLATE Latin1_General_CS_AS)"))
532
556
  when :ILIKE, :"NOT ILIKE"
533
- super(sql, (op == :ILIKE ? :LIKE : :"NOT LIKE"), args.map{|a| Sequel.lit(["(", " COLLATE Latin1_General_CI_AS)"], a)})
557
+ super(sql, (op == :ILIKE ? :LIKE : :"NOT LIKE"), complex_expression_sql_like_args(args, " COLLATE Latin1_General_CI_AS)"))
534
558
  when :<<, :>>
535
559
  complex_expression_emulate_append(sql, op, args)
536
560
  when :extract
@@ -659,11 +683,11 @@ module Sequel
659
683
  # case by default, and that also adds a default order, so it's better to just
660
684
  # avoid the subquery.
661
685
  def select_sql
662
- if @opts[:offset] && !@opts[:order] && is_2012_or_later?
663
- order(1).select_sql
664
- else
665
- super
686
+ if @opts[:offset]
687
+ raise(Error, "Using with_ties is not supported with an offset on Microsoft SQL Server") if @opts[:limit_with_ties]
688
+ return order(1).select_sql if is_2012_or_later? && !@opts[:order]
666
689
  end
690
+ super
667
691
  end
668
692
 
669
693
  # The version of the database server.
@@ -710,6 +734,11 @@ module Sequel
710
734
  false
711
735
  end
712
736
 
737
+ # MSSQL 2008+ supports MERGE
738
+ def supports_merge?
739
+ is_2008_or_later?
740
+ end
741
+
713
742
  # MSSQL 2005+ supports modifying joined datasets
714
743
  def supports_modifying_joins?
715
744
  is_2005_or_later?
@@ -755,6 +784,12 @@ module Sequel
755
784
  false
756
785
  end
757
786
 
787
+ # Use WITH TIES when limiting the result set to also include additional
788
+ # rows matching the last row.
789
+ def with_ties
790
+ clone(:limit_with_ties=>true)
791
+ end
792
+
758
793
  protected
759
794
 
760
795
  # If returned primary keys are requested, use OUTPUT unless already set on the
@@ -794,6 +829,35 @@ module Sequel
794
829
 
795
830
  private
796
831
 
832
+ # Normalize conditions for MERGE WHEN.
833
+ def _merge_when_conditions_sql(sql, data)
834
+ if data.has_key?(:conditions)
835
+ sql << " AND "
836
+ literal_append(sql, _normalize_merge_when_conditions(data[:conditions]))
837
+ end
838
+ end
839
+
840
+ # Handle nil, false, and true MERGE WHEN conditions to avoid non-boolean
841
+ # type error.
842
+ def _normalize_merge_when_conditions(conditions)
843
+ case conditions
844
+ when nil, false
845
+ {1=>0}
846
+ when true
847
+ {1=>1}
848
+ when Sequel::SQL::DelayedEvaluation
849
+ Sequel.delay{_normalize_merge_when_conditions(conditions.call(self))}
850
+ else
851
+ conditions
852
+ end
853
+ end
854
+
855
+ # MSSQL requires a semicolon at the end of MERGE.
856
+ def _merge_when_sql(sql)
857
+ super
858
+ sql << ';'
859
+ end
860
+
797
861
  # MSSQL does not allow ordering in sub-clauses unless TOP (limit) is specified
798
862
  def aggregate_dataset
799
863
  (options_overlap(Sequel::Dataset::COUNT_FROM_SELF_OPTS) && !options_overlap([:limit])) ? unordered.from_self : super
@@ -821,6 +885,15 @@ module Sequel
821
885
  server_version >= 11000000
822
886
  end
823
887
 
888
+ # Determine whether to add the COLLATE for LIKE arguments, based on the Database setting.
889
+ def complex_expression_sql_like_args(args, collation)
890
+ if db.like_without_collate
891
+ args
892
+ else
893
+ args.map{|a| Sequel.lit(["(", collation], a)}
894
+ end
895
+ end
896
+
824
897
  # Use strict ISO-8601 format with T between date and time,
825
898
  # since that is the format that is multilanguage and not
826
899
  # DATEFORMAT dependent.
@@ -959,6 +1032,10 @@ module Sequel
959
1032
  sql << " TOP "
960
1033
  literal_append(sql, l)
961
1034
  end
1035
+
1036
+ if @opts[:limit_with_ties]
1037
+ sql << " WITH TIES"
1038
+ end
962
1039
  end
963
1040
 
964
1041
  def update_limit_sql(sql)
@@ -187,6 +187,15 @@ module Sequel
187
187
  def views(opts=OPTS)
188
188
  full_tables('VIEW', opts)
189
189
  end
190
+
191
+ # Renames multiple tables in a single call.
192
+ #
193
+ # DB.rename_tables [:items, :old_items], [:other_items, :old_other_items]
194
+ # # RENAME TABLE items TO old_items, other_items TO old_other_items
195
+ def rename_tables(*renames)
196
+ execute_ddl(rename_tables_sql(renames))
197
+ renames.each{|from,| remove_cached_schema(from)}
198
+ end
190
199
 
191
200
  private
192
201
 
@@ -324,6 +333,12 @@ module Sequel
324
333
  sqls << "SET sql_mode = '#{sql_mode}'"
325
334
  end
326
335
 
336
+ # Disable the use of split_materialized in the optimizer. This is
337
+ # needed to pass association tests on MariaDB 10.5+.
338
+ if opts[:disable_split_materialized] && typecast_value_boolean(opts[:disable_split_materialized])
339
+ sqls << "SET SESSION optimizer_switch='split_materialized=off'"
340
+ end
341
+
327
342
  sqls
328
343
  end
329
344
 
@@ -347,6 +362,12 @@ module Sequel
347
362
  end
348
363
  end
349
364
 
365
+ # Support :on_update_current_timestamp option.
366
+ def column_definition_default_sql(sql, column)
367
+ super
368
+ sql << " ON UPDATE CURRENT_TIMESTAMP" if column[:on_update_current_timestamp]
369
+ end
370
+
350
371
  # Add generation clause SQL fragment to column creation SQL.
351
372
  def column_definition_generated_sql(sql, column)
352
373
  if (generated_expression = column[:generated_always_as])
@@ -473,6 +494,14 @@ module Sequel
473
494
  schema(table).select{|a| a[1][:primary_key]}.map{|a| a[0]}
474
495
  end
475
496
 
497
+ # SQL statement for renaming multiple tables.
498
+ def rename_tables_sql(renames)
499
+ rename_tos = renames.map do |from, to|
500
+ "#{quote_schema_table(from)} TO #{quote_schema_table(to)}"
501
+ end.join(', ')
502
+ "RENAME TABLE #{rename_tos}"
503
+ end
504
+
476
505
  # Rollback the currently open XA transaction
477
506
  def rollback_transaction(conn, opts=OPTS)
478
507
  if (s = opts[:prepare]) && savepoint_level(conn) <= 1
@@ -516,6 +545,7 @@ module Sequel
516
545
  row[:default] = row.delete(:Default)
517
546
  row[:db_type] = row.delete(:Type)
518
547
  row[:type] = schema_column_type(row[:db_type])
548
+ row[:extra] = extra
519
549
  [m.call(row.delete(:Field)), row]
520
550
  end
521
551
  end
@@ -526,9 +556,10 @@ module Sequel
526
556
  server_version >= 50600 && (op[:op] == :drop_index || (op[:op] == :drop_constraint && op[:type] == :unique))
527
557
  end
528
558
 
529
- # Whether the database supports CHECK constraints
559
+ # CHECK constraints only supported on MariaDB 10.2+ and MySQL 8.0.19+
560
+ # (at least MySQL documents DROP CONSTRAINT was supported in 8.0.19+).
530
561
  def supports_check_constraints?
531
- mariadb? && server_version >= 100200
562
+ server_version >= (mariadb? ? 100200 : 80019)
532
563
  end
533
564
 
534
565
  # MySQL can combine multiple alter table ops into a single query.
@@ -103,12 +103,18 @@ module Sequel
103
103
  map{|r| m.call(r[:view_name])}
104
104
  end
105
105
 
106
- def view_exists?(name)
107
- m = input_identifier_meth
108
- metadata_dataset.from(:all_views).
109
- exclude(:owner=>IGNORE_OWNERS).
110
- where(:view_name=>m.call(name)).
111
- count > 0
106
+ # Whether a view with a given name exists. By default, looks in all schemas other than system
107
+ # schemas. If the :current_schema option is given, looks in the schema for the current user.
108
+ def view_exists?(name, opts=OPTS)
109
+ ds = metadata_dataset.from(:all_views).where(:view_name=>input_identifier_meth.call(name))
110
+
111
+ if opts[:current_schema]
112
+ ds = ds.where(:owner=>Sequel.function(:SYS_CONTEXT, 'userenv', 'current_schema'))
113
+ else
114
+ ds = ds.exclude(:owner=>IGNORE_OWNERS)
115
+ end
116
+
117
+ ds.count > 0
112
118
  end
113
119
 
114
120
  # The version of the Oracle server, used for determining capability.
@@ -178,7 +184,7 @@ module Sequel
178
184
 
179
185
  def create_table_from_generator(name, generator, options)
180
186
  drop_statement, create_statements = create_table_sql_list(name, generator, options)
181
- (execute_ddl(drop_statement) rescue nil) if drop_statement
187
+ swallow_database_error{execute_ddl(drop_statement)} if drop_statement
182
188
  create_statements.each{|sql| execute_ddl(sql)}
183
189
  end
184
190
 
@@ -472,6 +478,11 @@ module Sequel
472
478
  false
473
479
  end
474
480
 
481
+ # Oracle supports MERGE
482
+ def supports_merge?
483
+ true
484
+ end
485
+
475
486
  # Oracle supports NOWAIT.
476
487
  def supports_nowait?
477
488
  true
@@ -519,6 +530,70 @@ module Sequel
519
530
 
520
531
  private
521
532
 
533
+ # Handle nil, false, and true MERGE WHEN conditions to avoid non-boolean
534
+ # type error.
535
+ def _normalize_merge_when_conditions(conditions)
536
+ case conditions
537
+ when nil, false
538
+ {1=>0}
539
+ when true
540
+ {1=>1}
541
+ when Sequel::SQL::DelayedEvaluation
542
+ Sequel.delay{_normalize_merge_when_conditions(conditions.call(self))}
543
+ else
544
+ conditions
545
+ end
546
+ end
547
+
548
+ # Handle Oracle's non standard MERGE syntax
549
+ def _merge_when_sql(sql)
550
+ raise Error, "no WHEN [NOT] MATCHED clauses provided for MERGE" unless merge_when = @opts[:merge_when]
551
+ insert = update = delete = nil
552
+ types = merge_when.map{|d| d[:type]}
553
+ raise Error, "Oracle does not support multiple INSERT, UPDATE, or DELETE clauses in MERGE" if types != types.uniq
554
+
555
+ merge_when.each do |data|
556
+ case data[:type]
557
+ when :insert
558
+ insert = data
559
+ when :update
560
+ update = data
561
+ else # when :delete
562
+ delete = data
563
+ end
564
+ end
565
+
566
+ if delete
567
+ raise Error, "Oracle does not support DELETE without UPDATE clause in MERGE" unless update
568
+ raise Error, "Oracle does not support DELETE without conditions clause in MERGE" unless delete.has_key?(:conditions)
569
+ end
570
+
571
+ if update
572
+ sql << " WHEN MATCHED"
573
+ _merge_update_sql(sql, update)
574
+ _merge_when_conditions_sql(sql, update)
575
+
576
+ if delete
577
+ sql << " DELETE"
578
+ _merge_when_conditions_sql(sql, delete)
579
+ end
580
+ end
581
+
582
+ if insert
583
+ sql << " WHEN NOT MATCHED"
584
+ _merge_insert_sql(sql, insert)
585
+ _merge_when_conditions_sql(sql, insert)
586
+ end
587
+ end
588
+
589
+ # Handle Oracle's non-standard MERGE WHEN condition syntax.
590
+ def _merge_when_conditions_sql(sql, data)
591
+ if data.has_key?(:conditions)
592
+ sql << " WHERE "
593
+ literal_append(sql, _normalize_merge_when_conditions(data[:conditions]))
594
+ end
595
+ end
596
+
522
597
  # Allow preparing prepared statements, since determining the prepared sql to use for
523
598
  # a prepared statement requires calling prepare on that statement.
524
599
  def allow_preparing_prepared_statements?