sequel 5.82.0 → 5.84.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (135) hide show
  1. checksums.yaml +4 -4
  2. data/bin/sequel +9 -17
  3. data/lib/sequel/adapters/jdbc/derby.rb +1 -1
  4. data/lib/sequel/adapters/shared/db2.rb +1 -1
  5. data/lib/sequel/adapters/shared/mssql.rb +14 -2
  6. data/lib/sequel/adapters/shared/postgres.rb +42 -4
  7. data/lib/sequel/adapters/shared/sqlite.rb +3 -1
  8. data/lib/sequel/database/connecting.rb +1 -4
  9. data/lib/sequel/database/misc.rb +27 -7
  10. data/lib/sequel/database/schema_methods.rb +17 -1
  11. data/lib/sequel/dataset/sql.rb +13 -0
  12. data/lib/sequel/extensions/pg_json_ops.rb +328 -1
  13. data/lib/sequel/extensions/stdio_logger.rb +48 -0
  14. data/lib/sequel/extensions/string_agg.rb +15 -2
  15. data/lib/sequel/plugins/defaults_setter.rb +16 -4
  16. data/lib/sequel/plugins/optimistic_locking.rb +2 -0
  17. data/lib/sequel/sql.rb +8 -5
  18. data/lib/sequel/version.rb +1 -1
  19. metadata +4 -235
  20. data/CHANGELOG +0 -1377
  21. data/README.rdoc +0 -936
  22. data/doc/advanced_associations.rdoc +0 -884
  23. data/doc/association_basics.rdoc +0 -1859
  24. data/doc/bin_sequel.rdoc +0 -146
  25. data/doc/cheat_sheet.rdoc +0 -255
  26. data/doc/code_order.rdoc +0 -104
  27. data/doc/core_extensions.rdoc +0 -405
  28. data/doc/dataset_basics.rdoc +0 -96
  29. data/doc/dataset_filtering.rdoc +0 -222
  30. data/doc/extensions.rdoc +0 -77
  31. data/doc/fork_safety.rdoc +0 -84
  32. data/doc/mass_assignment.rdoc +0 -98
  33. data/doc/migration.rdoc +0 -660
  34. data/doc/model_dataset_method_design.rdoc +0 -129
  35. data/doc/model_hooks.rdoc +0 -254
  36. data/doc/model_plugins.rdoc +0 -270
  37. data/doc/mssql_stored_procedures.rdoc +0 -43
  38. data/doc/object_model.rdoc +0 -563
  39. data/doc/opening_databases.rdoc +0 -439
  40. data/doc/postgresql.rdoc +0 -611
  41. data/doc/prepared_statements.rdoc +0 -144
  42. data/doc/querying.rdoc +0 -1070
  43. data/doc/reflection.rdoc +0 -120
  44. data/doc/release_notes/5.0.0.txt +0 -159
  45. data/doc/release_notes/5.1.0.txt +0 -31
  46. data/doc/release_notes/5.10.0.txt +0 -84
  47. data/doc/release_notes/5.11.0.txt +0 -83
  48. data/doc/release_notes/5.12.0.txt +0 -141
  49. data/doc/release_notes/5.13.0.txt +0 -27
  50. data/doc/release_notes/5.14.0.txt +0 -63
  51. data/doc/release_notes/5.15.0.txt +0 -39
  52. data/doc/release_notes/5.16.0.txt +0 -110
  53. data/doc/release_notes/5.17.0.txt +0 -31
  54. data/doc/release_notes/5.18.0.txt +0 -69
  55. data/doc/release_notes/5.19.0.txt +0 -28
  56. data/doc/release_notes/5.2.0.txt +0 -33
  57. data/doc/release_notes/5.20.0.txt +0 -89
  58. data/doc/release_notes/5.21.0.txt +0 -87
  59. data/doc/release_notes/5.22.0.txt +0 -48
  60. data/doc/release_notes/5.23.0.txt +0 -56
  61. data/doc/release_notes/5.24.0.txt +0 -56
  62. data/doc/release_notes/5.25.0.txt +0 -32
  63. data/doc/release_notes/5.26.0.txt +0 -35
  64. data/doc/release_notes/5.27.0.txt +0 -21
  65. data/doc/release_notes/5.28.0.txt +0 -16
  66. data/doc/release_notes/5.29.0.txt +0 -22
  67. data/doc/release_notes/5.3.0.txt +0 -121
  68. data/doc/release_notes/5.30.0.txt +0 -20
  69. data/doc/release_notes/5.31.0.txt +0 -148
  70. data/doc/release_notes/5.32.0.txt +0 -46
  71. data/doc/release_notes/5.33.0.txt +0 -24
  72. data/doc/release_notes/5.34.0.txt +0 -40
  73. data/doc/release_notes/5.35.0.txt +0 -56
  74. data/doc/release_notes/5.36.0.txt +0 -60
  75. data/doc/release_notes/5.37.0.txt +0 -30
  76. data/doc/release_notes/5.38.0.txt +0 -28
  77. data/doc/release_notes/5.39.0.txt +0 -19
  78. data/doc/release_notes/5.4.0.txt +0 -80
  79. data/doc/release_notes/5.40.0.txt +0 -40
  80. data/doc/release_notes/5.41.0.txt +0 -25
  81. data/doc/release_notes/5.42.0.txt +0 -136
  82. data/doc/release_notes/5.43.0.txt +0 -98
  83. data/doc/release_notes/5.44.0.txt +0 -32
  84. data/doc/release_notes/5.45.0.txt +0 -34
  85. data/doc/release_notes/5.46.0.txt +0 -87
  86. data/doc/release_notes/5.47.0.txt +0 -59
  87. data/doc/release_notes/5.48.0.txt +0 -14
  88. data/doc/release_notes/5.49.0.txt +0 -59
  89. data/doc/release_notes/5.5.0.txt +0 -61
  90. data/doc/release_notes/5.50.0.txt +0 -78
  91. data/doc/release_notes/5.51.0.txt +0 -47
  92. data/doc/release_notes/5.52.0.txt +0 -87
  93. data/doc/release_notes/5.53.0.txt +0 -23
  94. data/doc/release_notes/5.54.0.txt +0 -27
  95. data/doc/release_notes/5.55.0.txt +0 -21
  96. data/doc/release_notes/5.56.0.txt +0 -51
  97. data/doc/release_notes/5.57.0.txt +0 -23
  98. data/doc/release_notes/5.58.0.txt +0 -31
  99. data/doc/release_notes/5.59.0.txt +0 -73
  100. data/doc/release_notes/5.6.0.txt +0 -31
  101. data/doc/release_notes/5.60.0.txt +0 -22
  102. data/doc/release_notes/5.61.0.txt +0 -43
  103. data/doc/release_notes/5.62.0.txt +0 -132
  104. data/doc/release_notes/5.63.0.txt +0 -33
  105. data/doc/release_notes/5.64.0.txt +0 -50
  106. data/doc/release_notes/5.65.0.txt +0 -21
  107. data/doc/release_notes/5.66.0.txt +0 -24
  108. data/doc/release_notes/5.67.0.txt +0 -32
  109. data/doc/release_notes/5.68.0.txt +0 -61
  110. data/doc/release_notes/5.69.0.txt +0 -26
  111. data/doc/release_notes/5.7.0.txt +0 -108
  112. data/doc/release_notes/5.70.0.txt +0 -35
  113. data/doc/release_notes/5.71.0.txt +0 -21
  114. data/doc/release_notes/5.72.0.txt +0 -33
  115. data/doc/release_notes/5.73.0.txt +0 -66
  116. data/doc/release_notes/5.74.0.txt +0 -45
  117. data/doc/release_notes/5.75.0.txt +0 -35
  118. data/doc/release_notes/5.76.0.txt +0 -86
  119. data/doc/release_notes/5.77.0.txt +0 -63
  120. data/doc/release_notes/5.78.0.txt +0 -67
  121. data/doc/release_notes/5.79.0.txt +0 -28
  122. data/doc/release_notes/5.8.0.txt +0 -170
  123. data/doc/release_notes/5.80.0.txt +0 -40
  124. data/doc/release_notes/5.81.0.txt +0 -31
  125. data/doc/release_notes/5.82.0.txt +0 -61
  126. data/doc/release_notes/5.9.0.txt +0 -99
  127. data/doc/schema_modification.rdoc +0 -679
  128. data/doc/security.rdoc +0 -443
  129. data/doc/sharding.rdoc +0 -286
  130. data/doc/sql.rdoc +0 -648
  131. data/doc/testing.rdoc +0 -204
  132. data/doc/thread_safety.rdoc +0 -15
  133. data/doc/transactions.rdoc +0 -250
  134. data/doc/validations.rdoc +0 -558
  135. data/doc/virtual_rows.rdoc +0 -265
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f09a139a164322e0a0e52e9a58c79b2f463972363509c41bf50e7082c1f542b7
4
- data.tar.gz: e7222b81a79111b9853565160f81cb18c72b341f18bec839046c9b49a4b199ea
3
+ metadata.gz: 5677b07054121f55f100f0629d8102cabdd9db454263c5199a8f401bea891992
4
+ data.tar.gz: ca57e632e3e66c3a4003f988e5240da6a6eed0de9a143ac3985bd0603e0d9073
5
5
  SHA512:
6
- metadata.gz: d9f16395ad855ccbc4494bd2e1436b6b78f15ddbfd1c9b80d356040d99415a46a352f50042b2fc9ab23d29b65567dafec2fceb35c709498159b00a1402991ee6
7
- data.tar.gz: a5693c2f3c3791c0216a5af9e933edaa41b0eeb030a3523e52a6951c666e720d0b12ec48ae3f46777ce617b27857f6519d7ce98ec1768a0c8226c4b494e501c1
6
+ metadata.gz: 2ea8e58679c4ae2455588b584b959b3be691c177823cf336b77fa7b5910e716d9ca88e54024bbef44ec58d3fa8d66070acbf94e8c32a4294126ab2e618f4285e
7
+ data.tar.gz: acf4e565dd754b16ea0c07a11fe67cd21c9d5833ac1cf70c384a8da2c1b7c9ffd324358dbab9a8196d5a249365cc11870e6c807d07dbc631d359b413977f14ed
data/bin/sequel CHANGED
@@ -18,21 +18,6 @@ load_dirs = []
18
18
  exclusive_options = []
19
19
  loggers = []
20
20
 
21
- logger_class = Class.new do
22
- def initialize(device)
23
- @device = device
24
- end
25
-
26
- def debug(msg)
27
- end
28
-
29
- [:info, :warn, :error].each do |meth|
30
- define_method(meth) do |msg|
31
- @device.puts("#{Time.now.strftime('%Y-%m-%d %T')} #{meth.to_s.upcase}: #{msg}")
32
- end
33
- end
34
- end
35
-
36
21
  options = OptionParser.new do |opts|
37
22
  opts.banner = "Sequel: The Database Toolkit for Ruby"
38
23
  opts.define_head "Usage: sequel [options] <uri|path> [file]"
@@ -76,7 +61,7 @@ options = OptionParser.new do |opts|
76
61
  end
77
62
 
78
63
  opts.on("-E", "--echo", "echo SQL statements") do
79
- loggers << logger_class.new($stdout)
64
+ loggers << $stdout
80
65
  end
81
66
 
82
67
  opts.on("-I", "--include dir", "specify $LOAD_PATH directory") do |v|
@@ -84,7 +69,9 @@ options = OptionParser.new do |opts|
84
69
  end
85
70
 
86
71
  opts.on("-l", "--log logfile", "log SQL statements to log file") do |v|
87
- loggers << logger_class.new(File.open(v, 'a'))
72
+ file = File.open(v, 'a')
73
+ file.sync = true
74
+ loggers << file
88
75
  end
89
76
 
90
77
  opts.on("-L", "--load-dir DIR", "loads all *.rb under specifed directory") do |v|
@@ -168,6 +155,11 @@ begin
168
155
  end
169
156
  end
170
157
 
158
+ unless loggers.empty?
159
+ Sequel.extension :stdio_logger
160
+ loggers.map!{|io| Sequel::StdioLogger.new(io)}
161
+ end
162
+
171
163
  DB = connect_proc[db]
172
164
  load_dirs.each{|d| d.is_a?(Array) ? require(d.first) : Dir["#{d}/**/*.rb"].each{|f| load(f)}}
173
165
  if migrate_dir
@@ -115,7 +115,7 @@ module Sequel
115
115
  # Temporary table creation on Derby uses DECLARE instead of CREATE.
116
116
  def create_table_prefix_sql(name, options)
117
117
  if options[:temp]
118
- "DECLARE GLOBAL TEMPORARY TABLE #{quote_identifier(name)}"
118
+ "DECLARE GLOBAL TEMPORARY TABLE #{create_table_table_name_sql(name, options)}"
119
119
  else
120
120
  super
121
121
  end
@@ -198,7 +198,7 @@ module Sequel
198
198
  # http://www.ibm.com/developerworks/data/library/techarticle/dm-0912globaltemptable/
199
199
  def create_table_prefix_sql(name, options)
200
200
  if options[:temp]
201
- "DECLARE GLOBAL TEMPORARY TABLE #{quote_identifier(name)}"
201
+ "DECLARE GLOBAL TEMPORARY TABLE #{create_table_table_name_sql(name, options)}"
202
202
  else
203
203
  super
204
204
  end
@@ -379,9 +379,21 @@ module Sequel
379
379
  # a regular and temporary table, with temporary table names starting with
380
380
  # a #.
381
381
  def create_table_prefix_sql(name, options)
382
- "CREATE TABLE #{quote_schema_table(options[:temp] ? "##{name}" : name)}"
382
+ "CREATE TABLE #{create_table_table_name_sql(name, options)}"
383
383
  end
384
-
384
+
385
+ # The SQL to use for the table name for a temporary table.
386
+ def create_table_temp_table_name_sql(name, _options)
387
+ case name
388
+ when String, Symbol
389
+ "##{name}"
390
+ when SQL::Identifier
391
+ "##{name.value}"
392
+ else
393
+ raise Error, "temporary table names must be strings, symbols, or Sequel::SQL::Identifier instances on Microsoft SQL Server"
394
+ end
395
+ end
396
+
385
397
  # MSSQL doesn't support CREATE TABLE AS, it only supports SELECT INTO.
386
398
  # Emulating CREATE TABLE AS using SELECT INTO is only possible if a dataset
387
399
  # is given as the argument, it can't work with a string, so raise an
@@ -1429,7 +1429,7 @@ module Sequel
1429
1429
  'UNLOGGED '
1430
1430
  end
1431
1431
 
1432
- "CREATE #{prefix_sql}TABLE#{' IF NOT EXISTS' if options[:if_not_exists]} #{options[:temp] ? quote_identifier(name) : quote_schema_table(name)}"
1432
+ "CREATE #{prefix_sql}TABLE#{' IF NOT EXISTS' if options[:if_not_exists]} #{create_table_table_name_sql(name, options)}"
1433
1433
  end
1434
1434
 
1435
1435
  # SQL for creating a table with PostgreSQL specific options
@@ -2068,6 +2068,19 @@ module Sequel
2068
2068
  end
2069
2069
  end
2070
2070
 
2071
+ # Return a dataset with a WHEN NOT MATCHED BY SOURCE THEN DELETE clause added to the
2072
+ # MERGE statement. If a block is passed, treat it as a virtual row and
2073
+ # use it as additional conditions for the match.
2074
+ #
2075
+ # merge_delete_not_matched_by_source
2076
+ # # WHEN NOT MATCHED BY SOURCE THEN DELETE
2077
+ #
2078
+ # merge_delete_not_matched_by_source{a > 30}
2079
+ # # WHEN NOT MATCHED BY SOURCE AND (a > 30) THEN DELETE
2080
+ def merge_delete_when_not_matched_by_source(&block)
2081
+ _merge_when(:type=>:delete_not_matched_by_source, &block)
2082
+ end
2083
+
2071
2084
  # Return a dataset with a WHEN MATCHED THEN DO NOTHING clause added to the
2072
2085
  # MERGE statement. If a block is passed, treat it as a virtual row and
2073
2086
  # use it as additional conditions for the match.
@@ -2094,6 +2107,19 @@ module Sequel
2094
2107
  _merge_when(:type=>:not_matched, &block)
2095
2108
  end
2096
2109
 
2110
+ # Return a dataset with a WHEN NOT MATCHED BY SOURCE THEN DO NOTHING clause added to the
2111
+ # MERGE BY SOURCE statement. If a block is passed, treat it as a virtual row and
2112
+ # use it as additional conditions for the match.
2113
+ #
2114
+ # merge_do_nothing_when_not_matched_by_source
2115
+ # # WHEN NOT MATCHED BY SOURCE THEN DO NOTHING
2116
+ #
2117
+ # merge_do_nothing_when_not_matched_by_source{a > 30}
2118
+ # # WHEN NOT MATCHED BY SOURCE AND (a > 30) THEN DO NOTHING
2119
+ def merge_do_nothing_when_not_matched_by_source(&block)
2120
+ _merge_when(:type=>:not_matched_by_source, &block)
2121
+ end
2122
+
2097
2123
  # Support OVERRIDING USER|SYSTEM VALUE for MERGE INSERT.
2098
2124
  def merge_insert(*values, &block)
2099
2125
  h = {:type=>:insert, :values=>values}
@@ -2103,6 +2129,19 @@ module Sequel
2103
2129
  _merge_when(h, &block)
2104
2130
  end
2105
2131
 
2132
+ # Return a dataset with a WHEN NOT MATCHED BY SOURCE THEN UPDATE clause added to the
2133
+ # MERGE statement. If a block is passed, treat it as a virtual row and
2134
+ # use it as additional conditions for the match.
2135
+ #
2136
+ # merge_update_not_matched_by_source(i1: Sequel[:i1]+:i2+10, a: Sequel[:a]+:b+20)
2137
+ # # WHEN NOT MATCHED BY SOURCE THEN UPDATE SET i1 = (i1 + i2 + 10), a = (a + b + 20)
2138
+ #
2139
+ # merge_update_not_matched_by_source(i1: :i2){a > 30}
2140
+ # # WHEN NOT MATCHED BY SOURCE AND (a > 30) THEN UPDATE SET i1 = i2
2141
+ def merge_update_when_not_matched_by_source(values, &block)
2142
+ _merge_when(:type=>:update_not_matched_by_source, :values=>values, &block)
2143
+ end
2144
+
2106
2145
  # Use OVERRIDING USER VALUE for INSERT statements, so that identity columns
2107
2146
  # always use the user supplied value, and an error is not raised for identity
2108
2147
  # columns that are GENERATED ALWAYS.
@@ -2296,7 +2335,7 @@ module Sequel
2296
2335
 
2297
2336
  # Append the INSERT sql used in a MERGE
2298
2337
  def _merge_insert_sql(sql, data)
2299
- sql << " THEN INSERT "
2338
+ sql << " THEN INSERT"
2300
2339
  columns, values = _parse_insert_sql_args(data[:values])
2301
2340
  _insert_columns_sql(sql, columns)
2302
2341
  if override = data[:override]
@@ -2305,10 +2344,9 @@ module Sequel
2305
2344
  _insert_values_sql(sql, values)
2306
2345
  end
2307
2346
 
2308
- def _merge_matched_sql(sql, data)
2347
+ def _merge_do_nothing_sql(sql, data)
2309
2348
  sql << " THEN DO NOTHING"
2310
2349
  end
2311
- alias _merge_not_matched_sql _merge_matched_sql
2312
2350
 
2313
2351
  # Support MERGE RETURNING on PostgreSQL 17+.
2314
2352
  def _merge_when_sql(sql)
@@ -349,7 +349,7 @@ module Sequel
349
349
  ps
350
350
  end
351
351
 
352
- # Support creating STRICT AND/OR WITHOUT ROWID tables via :strict and :without_rowid options
352
+ # Support creating STRICT AND/OR WITHOUT ROWID tables via :strict and :without_rowid options, and VIRTUAL tables with :using option.
353
353
  def create_table_sql(name, generator, options)
354
354
  if options[:strict] && options[:without_rowid]
355
355
  "#{super} STRICT, WITHOUT ROWID"
@@ -357,6 +357,8 @@ module Sequel
357
357
  "#{super} STRICT"
358
358
  elsif options[:without_rowid]
359
359
  "#{super} WITHOUT ROWID"
360
+ elsif options[:using]
361
+ "CREATE VIRTUAL TABLE#{' IF NOT EXISTS' if options[:if_not_exists]} #{create_table_table_name_sql(name, options)} USING #{options[:using]}"
360
362
  else
361
363
  super
362
364
  end
@@ -34,10 +34,7 @@ module Sequel
34
34
  uri = URI.parse(conn_string)
35
35
  scheme = uri.scheme
36
36
  c = adapter_class(scheme)
37
- uri_options = c.send(:uri_to_options, uri)
38
- uri.query.split('&').map{|s| s.split('=')}.each{|k,v| uri_options[k.to_sym] = v if k && !k.empty?} unless uri.query.to_s.strip.empty?
39
- uri_options.to_a.each{|k,v| uri_options[k] = URI::DEFAULT_PARSER.unescape(v) if v.is_a?(String)}
40
- opts = uri_options.merge(opts).merge!(:orig_opts=>opts.dup, :uri=>conn_string, :adapter=>scheme)
37
+ opts = c.send(:options_from_uri, uri).merge!(opts).merge!(:orig_opts=>opts.dup, :uri=>conn_string, :adapter=>scheme)
41
38
  end
42
39
  when Hash
43
40
  opts = conn_string.merge(opts)
@@ -82,6 +82,14 @@ module Sequel
82
82
  end
83
83
  private_class_method :uri_to_options
84
84
 
85
+ def self.options_from_uri(uri)
86
+ uri_options = uri_to_options(uri)
87
+ uri.query.split('&').map{|s| s.split('=')}.each{|k,v| uri_options[k.to_sym] = v if k && !k.empty?} unless uri.query.to_s.strip.empty?
88
+ uri_options.to_a.each{|k,v| uri_options[k] = URI::DEFAULT_PARSER.unescape(v) if v.is_a?(String)}
89
+ uri_options
90
+ end
91
+ private_class_method :options_from_uri
92
+
85
93
  # The options hash for this database
86
94
  attr_reader :opts
87
95
 
@@ -253,15 +261,27 @@ module Sequel
253
261
  Sequel.convert_output_timestamp(v, timezone)
254
262
  end
255
263
 
256
- # Returns a string representation of the database object including the
257
- # class name and connection URI and options used when connecting (if any).
264
+ # Returns a string representation of the Database object, including
265
+ # the database type, host, database, and user, if present.
258
266
  def inspect
259
- a = []
260
- a << uri.inspect if uri
261
- if (oo = opts[:orig_opts]) && !oo.empty?
262
- a << oo.inspect
267
+ s = String.new
268
+ s << "#<#{self.class}"
269
+ s << " database_type=#{database_type}" if database_type && database_type != adapter_scheme
270
+
271
+ keys = [:host, :database, :user]
272
+ opts = self.opts
273
+ if !keys.any?{|k| opts[k]} && opts[:uri]
274
+ opts = self.class.send(:options_from_uri, URI.parse(opts[:uri]))
275
+ end
276
+
277
+ keys.each do |key|
278
+ val = opts[key]
279
+ if val && val != ''
280
+ s << " #{key}=#{val}"
281
+ end
263
282
  end
264
- "#<#{self.class}: #{a.join(' ')}>"
283
+
284
+ s << ">"
265
285
  end
266
286
 
267
287
  # Proxy the literal call to the dataset.
@@ -191,6 +191,8 @@ module Sequel
191
191
  # The +any+ type is treated like a SQLite column in a non-strict table,
192
192
  # allowing any type of data to be stored. This option is supported on
193
193
  # SQLite 3.37.0+.
194
+ # :using :: Create a VIRTUAL table with the given USING clause. The value should be
195
+ # a string, as it is used directly in the SQL query.
194
196
  # :without_rowid :: Create a WITHOUT ROWID table. Every row in SQLite has a special
195
197
  # 'rowid' column, that uniquely identifies that row within the table.
196
198
  # If this option is used, the 'rowid' column is omitted, which can
@@ -775,7 +777,21 @@ module Sequel
775
777
 
776
778
  # SQL fragment for initial part of CREATE TABLE statement
777
779
  def create_table_prefix_sql(name, options)
778
- "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)}"
780
+ "CREATE #{temporary_table_sql if options[:temp]}TABLE#{' IF NOT EXISTS' if options[:if_not_exists]} #{create_table_table_name_sql(name, options)}"
781
+ end
782
+
783
+ # The SQL to use for a table name when creating a table.
784
+ # Use of the :temp option can result in different SQL,
785
+ # because the rules for temp table naming can differ
786
+ # between databases, and temp tables should not use the
787
+ # default_schema.
788
+ def create_table_table_name_sql(name, options)
789
+ options[:temp] ? create_table_temp_table_name_sql(name, options) : quote_schema_table(name)
790
+ end
791
+
792
+ # The SQL to use for the table name for a temporary table.
793
+ def create_table_temp_table_name_sql(name, _options)
794
+ name.is_a?(String) ? quote_identifier(name) : literal(name)
779
795
  end
780
796
 
781
797
  # SQL fragment for initial part of CREATE VIEW statement
@@ -901,18 +901,31 @@ module Sequel
901
901
  MERGE_TYPE_SQL = {
902
902
  :insert => ' WHEN NOT MATCHED',
903
903
  :delete => ' WHEN MATCHED',
904
+ :delete_not_matched_by_source => ' WHEN NOT MATCHED BY SOURCE',
904
905
  :update => ' WHEN MATCHED',
906
+ :update_not_matched_by_source => ' WHEN NOT MATCHED BY SOURCE',
905
907
  :matched => ' WHEN MATCHED',
906
908
  :not_matched => ' WHEN NOT MATCHED',
909
+ :not_matched_by_source => ' WHEN NOT MATCHED BY SOURCE',
907
910
  }.freeze
908
911
  private_constant :MERGE_TYPE_SQL
909
912
 
913
+ MERGE_NORMALIZE_TYPE_MAP = {
914
+ :delete_not_matched_by_source => :delete,
915
+ :update_not_matched_by_source => :update,
916
+ :matched => :do_nothing,
917
+ :not_matched => :do_nothing,
918
+ :not_matched_by_source => :do_nothing,
919
+ }.freeze
920
+ private_constant :MERGE_NORMALIZE_TYPE_MAP
921
+
910
922
  # Add the WHEN clauses to the MERGE SQL
911
923
  def _merge_when_sql(sql)
912
924
  raise Error, "no WHEN [NOT] MATCHED clauses provided for MERGE" unless merge_when = @opts[:merge_when]
913
925
  merge_when.each do |data|
914
926
  type = data[:type]
915
927
  sql << MERGE_TYPE_SQL[type]
928
+ type = MERGE_NORMALIZE_TYPE_MAP[type] || type
916
929
  _merge_when_conditions_sql(sql, data)
917
930
  send(:"_merge_#{type}_sql", sql, data)
918
931
  end