sequel 5.33.0 → 5.38.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 (84) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +88 -0
  3. data/README.rdoc +1 -1
  4. data/doc/association_basics.rdoc +7 -2
  5. data/doc/dataset_filtering.rdoc +2 -2
  6. data/doc/model_plugins.rdoc +1 -1
  7. data/doc/opening_databases.rdoc +5 -1
  8. data/doc/release_notes/5.34.0.txt +40 -0
  9. data/doc/release_notes/5.35.0.txt +56 -0
  10. data/doc/release_notes/5.36.0.txt +60 -0
  11. data/doc/release_notes/5.37.0.txt +30 -0
  12. data/doc/release_notes/5.38.0.txt +28 -0
  13. data/doc/transactions.rdoc +0 -8
  14. data/doc/validations.rdoc +1 -1
  15. data/lib/sequel/adapters/jdbc.rb +13 -1
  16. data/lib/sequel/adapters/jdbc/mysql.rb +4 -4
  17. data/lib/sequel/adapters/odbc.rb +4 -6
  18. data/lib/sequel/adapters/oracle.rb +2 -1
  19. data/lib/sequel/adapters/shared/mssql.rb +14 -4
  20. data/lib/sequel/adapters/shared/oracle.rb +13 -7
  21. data/lib/sequel/adapters/shared/postgres.rb +39 -1
  22. data/lib/sequel/adapters/shared/sqlite.rb +8 -2
  23. data/lib/sequel/adapters/tinytds.rb +1 -0
  24. data/lib/sequel/adapters/utils/mysql_mysql2.rb +1 -0
  25. data/lib/sequel/connection_pool/sharded_single.rb +4 -1
  26. data/lib/sequel/connection_pool/sharded_threaded.rb +10 -10
  27. data/lib/sequel/connection_pool/single.rb +1 -1
  28. data/lib/sequel/connection_pool/threaded.rb +1 -1
  29. data/lib/sequel/core.rb +5 -6
  30. data/lib/sequel/database/connecting.rb +1 -2
  31. data/lib/sequel/database/misc.rb +30 -10
  32. data/lib/sequel/database/query.rb +2 -0
  33. data/lib/sequel/database/schema_generator.rb +0 -1
  34. data/lib/sequel/database/schema_methods.rb +16 -17
  35. data/lib/sequel/database/transactions.rb +8 -5
  36. data/lib/sequel/dataset/actions.rb +10 -6
  37. data/lib/sequel/dataset/placeholder_literalizer.rb +3 -7
  38. data/lib/sequel/dataset/query.rb +5 -4
  39. data/lib/sequel/deprecated.rb +3 -1
  40. data/lib/sequel/exceptions.rb +2 -0
  41. data/lib/sequel/extensions/_pretty_table.rb +1 -2
  42. data/lib/sequel/extensions/columns_introspection.rb +1 -2
  43. data/lib/sequel/extensions/core_refinements.rb +2 -0
  44. data/lib/sequel/extensions/duplicate_columns_handler.rb +2 -0
  45. data/lib/sequel/extensions/migration.rb +8 -2
  46. data/lib/sequel/extensions/pg_array_ops.rb +4 -0
  47. data/lib/sequel/extensions/pg_enum.rb +2 -0
  48. data/lib/sequel/extensions/pg_extended_date_support.rb +1 -1
  49. data/lib/sequel/extensions/pg_hstore_ops.rb +2 -0
  50. data/lib/sequel/extensions/pg_inet.rb +2 -0
  51. data/lib/sequel/extensions/pg_json_ops.rb +46 -2
  52. data/lib/sequel/extensions/pg_range.rb +3 -7
  53. data/lib/sequel/extensions/pg_range_ops.rb +2 -0
  54. data/lib/sequel/extensions/pg_row.rb +0 -1
  55. data/lib/sequel/extensions/pg_row_ops.rb +24 -0
  56. data/lib/sequel/extensions/query.rb +1 -0
  57. data/lib/sequel/extensions/run_transaction_hooks.rb +1 -1
  58. data/lib/sequel/extensions/s.rb +2 -0
  59. data/lib/sequel/extensions/schema_dumper.rb +3 -3
  60. data/lib/sequel/extensions/symbol_aref_refinement.rb +2 -0
  61. data/lib/sequel/extensions/symbol_as_refinement.rb +2 -0
  62. data/lib/sequel/extensions/to_dot.rb +9 -3
  63. data/lib/sequel/model.rb +3 -1
  64. data/lib/sequel/model/associations.rb +36 -20
  65. data/lib/sequel/model/base.rb +13 -5
  66. data/lib/sequel/model/plugins.rb +3 -3
  67. data/lib/sequel/plugins/association_pks.rb +60 -18
  68. data/lib/sequel/plugins/association_proxies.rb +1 -0
  69. data/lib/sequel/plugins/blacklist_security.rb +1 -2
  70. data/lib/sequel/plugins/class_table_inheritance.rb +3 -8
  71. data/lib/sequel/plugins/csv_serializer.rb +2 -0
  72. data/lib/sequel/plugins/dirty.rb +44 -0
  73. data/lib/sequel/plugins/forbid_lazy_load.rb +2 -0
  74. data/lib/sequel/plugins/instance_specific_default.rb +113 -0
  75. data/lib/sequel/plugins/lazy_attributes.rb +1 -1
  76. data/lib/sequel/plugins/pg_array_associations.rb +2 -3
  77. data/lib/sequel/plugins/prepared_statements.rb +5 -11
  78. data/lib/sequel/plugins/prepared_statements_safe.rb +1 -3
  79. data/lib/sequel/plugins/rcte_tree.rb +10 -16
  80. data/lib/sequel/plugins/single_table_inheritance.rb +5 -0
  81. data/lib/sequel/plugins/string_stripper.rb +1 -1
  82. data/lib/sequel/plugins/validation_class_methods.rb +5 -1
  83. data/lib/sequel/version.rb +1 -1
  84. metadata +14 -3
@@ -92,12 +92,10 @@ module Sequel
92
92
  cols = s.columns(true).map{|c| [output_identifier(c.name), c.type, i+=1]}
93
93
  columns = cols.map{|c| c[0]}
94
94
  self.columns = columns
95
- if rows = s.fetch_all
96
- rows.each do |row|
97
- hash = {}
98
- cols.each{|n,t,j| hash[n] = convert_odbc_value(row[j], t)}
99
- yield hash
100
- end
95
+ s.each do |row|
96
+ hash = {}
97
+ cols.each{|n,t,j| hash[n] = convert_odbc_value(row[j], t)}
98
+ yield hash
101
99
  end
102
100
  end
103
101
  self
@@ -14,7 +14,8 @@ module Sequel
14
14
  # ORA-02396: exceeded maximum idle time, please connect again
15
15
  # ORA-03113: end-of-file on communication channel
16
16
  # ORA-03114: not connected to ORACLE
17
- CONNECTION_ERROR_CODES = [ 28, 1012, 2396, 3113, 3114 ].freeze
17
+ # ORA-03135: connection lost contact
18
+ CONNECTION_ERROR_CODES = [ 28, 1012, 2396, 3113, 3114, 3135 ].freeze
18
19
 
19
20
  ORACLE_TYPES = {
20
21
  :blob=>lambda{|b| Sequel::SQL::Blob.new(b.read)},
@@ -659,11 +659,11 @@ module Sequel
659
659
  # case by default, and that also adds a default order, so it's better to just
660
660
  # avoid the subquery.
661
661
  def select_sql
662
- if @opts[:offset] && !@opts[:order] && is_2012_or_later?
663
- order(1).select_sql
664
- else
665
- super
662
+ if @opts[:offset]
663
+ raise(Error, "Using with_ties is not supported with an offset on Microsoft SQL Server") if @opts[:limit_with_ties]
664
+ return order(1).select_sql if is_2012_or_later? && !@opts[:order]
666
665
  end
666
+ super
667
667
  end
668
668
 
669
669
  # The version of the database server.
@@ -755,6 +755,12 @@ module Sequel
755
755
  false
756
756
  end
757
757
 
758
+ # Use WITH TIES when limiting the result set to also include additional
759
+ # rows matching the last row.
760
+ def with_ties
761
+ clone(:limit_with_ties=>true)
762
+ end
763
+
758
764
  protected
759
765
 
760
766
  # If returned primary keys are requested, use OUTPUT unless already set on the
@@ -959,6 +965,10 @@ module Sequel
959
965
  sql << " TOP "
960
966
  literal_append(sql, l)
961
967
  end
968
+
969
+ if @opts[:limit_with_ties]
970
+ sql << " WITH TIES"
971
+ end
962
972
  end
963
973
 
964
974
  def update_limit_sql(sql)
@@ -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
 
@@ -781,7 +781,7 @@ module Sequel
781
781
  return @server_version if @server_version
782
782
  ds = dataset
783
783
  ds = ds.server(server) if server
784
- @server_version ||= ds.with_sql("SELECT CAST(current_setting('server_version_num') AS integer) AS v").single_value rescue 0
784
+ @server_version = swallow_database_error{ds.with_sql("SELECT CAST(current_setting('server_version_num') AS integer) AS v").single_value} || 0
785
785
  end
786
786
 
787
787
  # PostgreSQL supports CREATE TABLE IF NOT EXISTS on 9.1+
@@ -1885,6 +1885,13 @@ module Sequel
1885
1885
  end
1886
1886
  end
1887
1887
 
1888
+ # Use WITH TIES when limiting the result set to also include additional
1889
+ # rules that have the same results for the order column as the final row.
1890
+ # Requires PostgreSQL 13.
1891
+ def with_ties
1892
+ clone(:limit_with_ties=>true)
1893
+ end
1894
+
1888
1895
  protected
1889
1896
 
1890
1897
  # If returned primary keys are requested, use RETURNING unless already set on the
@@ -2071,6 +2078,37 @@ module Sequel
2071
2078
  false
2072
2079
  end
2073
2080
 
2081
+ # Support FETCH FIRST WITH TIES on PostgreSQL 13+.
2082
+ def select_limit_sql(sql)
2083
+ l = @opts[:limit]
2084
+ o = @opts[:offset]
2085
+
2086
+ return unless l || o
2087
+
2088
+ if @opts[:limit_with_ties]
2089
+ if o
2090
+ sql << " OFFSET "
2091
+ literal_append(sql, o)
2092
+ end
2093
+
2094
+ if l
2095
+ sql << " FETCH FIRST "
2096
+ literal_append(sql, l)
2097
+ sql << " ROWS WITH TIES"
2098
+ end
2099
+ else
2100
+ if l
2101
+ sql << " LIMIT "
2102
+ literal_append(sql, l)
2103
+ end
2104
+
2105
+ if o
2106
+ sql << " OFFSET "
2107
+ literal_append(sql, o)
2108
+ end
2109
+ end
2110
+ end
2111
+
2074
2112
  # Support FOR SHARE locking when using the :share lock style.
2075
2113
  # Use SKIP LOCKED if skipping locked rows.
2076
2114
  def select_lock_sql(sql)
@@ -269,6 +269,8 @@ module Sequel
269
269
  else
270
270
  duplicate_table(table, :no_foreign_keys=>true)
271
271
  end
272
+ when :unique
273
+ duplicate_table(table, :no_unique=>true)
272
274
  else
273
275
  duplicate_table(table)
274
276
  end
@@ -422,8 +424,12 @@ module Sequel
422
424
  skip_indexes = []
423
425
  indexes(table, :only_autocreated=>true).each do |name, h|
424
426
  skip_indexes << name
425
- if h[:columns].length == 1 && h[:unique]
426
- unique_columns.concat(h[:columns])
427
+ if h[:unique]
428
+ if h[:columns].length == 1
429
+ unique_columns.concat(h[:columns])
430
+ elsif h[:columns].map(&:to_s) != pks && !opts[:no_unique]
431
+ constraints << {:type=>:unique, :columns=>h[:columns]}
432
+ end
427
433
  end
428
434
  end
429
435
  unique_columns -= pks
@@ -16,6 +16,7 @@ module Sequel
16
16
  c = TinyTds::Client.new(opts)
17
17
  c.query_options.merge!(:cache_rows=>false)
18
18
 
19
+ # SEQUEL6: Default to ansi: true
19
20
  if opts[:ansi]
20
21
  sql = %w(
21
22
  ANSI_NULLS
@@ -18,6 +18,7 @@ module Sequel
18
18
  This connection is still waiting for a result, try again once you have the result
19
19
  closed MySQL connection
20
20
  The MySQL server is running with the --read-only option so it cannot execute this statement
21
+ Connection was killed
21
22
  END
22
23
  # Error messages for mysql and mysql2 that indicate the current connection should be disconnected
23
24
  MYSQL_DATABASE_DISCONNECT_ERRORS = /\A#{Regexp.union(disconnect_errors)}/
@@ -41,7 +41,10 @@ class Sequel::ShardedSingleConnectionPool < Sequel::ConnectionPool
41
41
  # :server :: Should be a symbol specifing the server to disconnect from,
42
42
  # or an array of symbols to specify multiple servers.
43
43
  def disconnect(opts=OPTS)
44
- (opts[:server] ? Array(opts[:server]) : servers).each{|s| disconnect_server(s)}
44
+ (opts[:server] ? Array(opts[:server]) : servers).each do |s|
45
+ raise Sequel::Error, "invalid server: #{s}" unless @servers.has_key?(s)
46
+ disconnect_server(s)
47
+ end
45
48
  end
46
49
 
47
50
  def freeze
@@ -95,9 +95,7 @@ class Sequel::ShardedThreadedConnectionPool < Sequel::ThreadedConnectionPool
95
95
  # or an array of symbols to specify multiple servers.
96
96
  def disconnect(opts=OPTS)
97
97
  (opts[:server] ? Array(opts[:server]) : sync{@servers.keys}).each do |s|
98
- if conns = sync{disconnect_server_connections(s)}
99
- disconnect_connections(conns)
100
- end
98
+ disconnect_connections(sync{disconnect_server_connections(s)})
101
99
  end
102
100
  end
103
101
 
@@ -203,9 +201,9 @@ class Sequel::ShardedThreadedConnectionPool < Sequel::ThreadedConnectionPool
203
201
 
204
202
  until conn = assign_connection(thread, server)
205
203
  elapsed = Sequel.elapsed_seconds_since(timer)
204
+ # :nocov:
206
205
  raise_pool_timeout(elapsed, server) if elapsed > timeout
207
206
 
208
- # :nocov:
209
207
  # It's difficult to get to this point, it can only happen if there is a race condition
210
208
  # where a connection cannot be acquired even after the thread is signalled by the condition variable
211
209
  sync do
@@ -278,13 +276,15 @@ class Sequel::ShardedThreadedConnectionPool < Sequel::ThreadedConnectionPool
278
276
  # Mark any allocated connections to be removed when they are checked back in. The calling
279
277
  # code should already have the mutex before calling this.
280
278
  def disconnect_server_connections(server)
281
- @connections_to_remove.concat(allocated(server).values)
279
+ remove_conns = allocated(server)
280
+ dis_conns = available_connections(server)
281
+ raise Sequel::Error, "invalid server: #{server}" unless remove_conns && dis_conns
282
282
 
283
- if dis_conns = available_connections(server)
284
- conns = dis_conns.dup
285
- dis_conns.clear
286
- @waiters[server].signal
287
- end
283
+ @connections_to_remove.concat(remove_conns.values)
284
+
285
+ conns = dis_conns.dup
286
+ dis_conns.clear
287
+ @waiters[server].signal
288
288
  conns
289
289
  end
290
290
 
@@ -11,7 +11,7 @@ class Sequel::SingleConnectionPool < Sequel::ConnectionPool
11
11
 
12
12
  # Yield the connection if one has been made.
13
13
  def all_connections
14
- yield @conn.first if @conn
14
+ yield @conn.first unless @conn.empty?
15
15
  end
16
16
 
17
17
  # Disconnect the connection from the database.
@@ -152,9 +152,9 @@ class Sequel::ThreadedConnectionPool < Sequel::ConnectionPool
152
152
 
153
153
  until conn = assign_connection(thread)
154
154
  elapsed = Sequel.elapsed_seconds_since(timer)
155
+ # :nocov:
155
156
  raise_pool_timeout(elapsed) if elapsed > timeout
156
157
 
157
- # :nocov:
158
158
  # It's difficult to get to this point, it can only happen if there is a race condition
159
159
  # where a connection cannot be acquired even after the thread is signalled by the condition variable
160
160
  sync do
@@ -52,13 +52,12 @@ module Sequel
52
52
  #
53
53
  # Sequel.datetime_class = DateTime
54
54
  #
55
- # Note that +Time+ and +DateTime+ objects
56
- # have a different API, and in cases where they implement the same methods,
57
- # they often implement them differently (e.g. + using seconds on +Time+ and
58
- # days on +DateTime+).
55
+ # Note that +Time+ and +DateTime+ objects have a different API, and in
56
+ # cases where they implement the same methods, they often implement them
57
+ # differently (e.g. + using seconds on +Time+ and days on +DateTime+).
59
58
  attr_accessor :datetime_class
60
59
 
61
- # Set whether Sequel is being used in single threaded mode. by default,
60
+ # Set whether Sequel is being used in single threaded mode. By default,
62
61
  # Sequel uses a thread-safe connection pool, which isn't as fast as the
63
62
  # single threaded connection pool, and also has some additional thread
64
63
  # safety checks. If your program will only have one thread,
@@ -67,7 +66,7 @@ module Sequel
67
66
  # Sequel.single_threaded = true
68
67
  attr_accessor :single_threaded
69
68
 
70
- # Alias of original require method, as Sequel.require is does a relative
69
+ # Alias of original require method, as Sequel.require does a relative
71
70
  # require for backwards compatibility.
72
71
  alias orig_require require
73
72
  private :orig_require
@@ -36,7 +36,7 @@ module Sequel
36
36
  c = adapter_class(scheme)
37
37
  uri_options = c.send(:uri_to_options, uri)
38
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] = (defined?(URI::DEFAULT_PARSER) ? URI::DEFAULT_PARSER : URI).unescape(v) if v.is_a?(String)}
39
+ uri_options.to_a.each{|k,v| uri_options[k] = URI::DEFAULT_PARSER.unescape(v) if v.is_a?(String)}
40
40
  opts = uri_options.merge(opts).merge!(:orig_opts=>opts.dup, :uri=>conn_string, :adapter=>scheme)
41
41
  end
42
42
  when Hash
@@ -55,7 +55,6 @@ module Sequel
55
55
 
56
56
  begin
57
57
  db = c.new(opts)
58
- db.test_connection if db.send(:typecast_value_boolean, opts.fetch(:test, true))
59
58
  if block_given?
60
59
  return yield(db)
61
60
  end
@@ -153,19 +153,24 @@ module Sequel
153
153
  reset_default_dataset
154
154
  adapter_initialize
155
155
 
156
- unless typecast_value_boolean(@opts[:keep_reference]) == false
157
- Sequel.synchronize{::Sequel::DATABASES.push(self)}
158
- end
159
- Sequel::Database.run_after_initialize(self)
156
+ keep_reference = typecast_value_boolean(@opts[:keep_reference]) != false
157
+ begin
158
+ Sequel.synchronize{::Sequel::DATABASES.push(self)} if keep_reference
159
+ Sequel::Database.run_after_initialize(self)
160
160
 
161
- initialize_load_extensions(:preconnect_extensions)
161
+ initialize_load_extensions(:preconnect_extensions)
162
162
 
163
- if typecast_value_boolean(@opts[:preconnect]) && @pool.respond_to?(:preconnect, true)
164
- concurrent = typecast_value_string(@opts[:preconnect]) == "concurrently"
165
- @pool.send(:preconnect, concurrent)
166
- end
163
+ if typecast_value_boolean(@opts[:preconnect]) && @pool.respond_to?(:preconnect, true)
164
+ concurrent = typecast_value_string(@opts[:preconnect]) == "concurrently"
165
+ @pool.send(:preconnect, concurrent)
166
+ end
167
167
 
168
- initialize_load_extensions(:extensions)
168
+ initialize_load_extensions(:extensions)
169
+ test_connection if typecast_value_boolean(@opts.fetch(:test, true)) && respond_to?(:connect, true)
170
+ rescue
171
+ Sequel.synchronize{::Sequel::DATABASES.delete(self)} if keep_reference
172
+ raise
173
+ end
169
174
  end
170
175
 
171
176
  # Freeze internal data structures for the Database instance.
@@ -185,7 +190,9 @@ module Sequel
185
190
 
186
191
  # Disallow dup/clone for Database instances
187
192
  undef_method :dup, :clone, :initialize_copy
193
+ # :nocov:
188
194
  if RUBY_VERSION >= '1.9.3'
195
+ # :nocov:
189
196
  undef_method :initialize_clone, :initialize_dup
190
197
  end
191
198
 
@@ -440,6 +447,19 @@ module Sequel
440
447
  end
441
448
  end
442
449
 
450
+ # Swallow database errors, unless they are connect/disconnect errors.
451
+ def swallow_database_error
452
+ yield
453
+ rescue Sequel::DatabaseDisconnectError, DatabaseConnectionError
454
+ # Always raise disconnect errors
455
+ raise
456
+ rescue Sequel::DatabaseError
457
+ # Don't raise other database errors.
458
+ nil
459
+ # else
460
+ # Don't rescue other exceptions, they will be raised normally.
461
+ end
462
+
443
463
  # Typecast the value to an SQL::Blob
444
464
  def typecast_value_blob(value)
445
465
  value.is_a?(Sequel::SQL::Blob) ? value : Sequel::SQL::Blob.new(value)
@@ -344,7 +344,9 @@ module Sequel
344
344
 
345
345
  # Post process the schema values.
346
346
  def schema_post_process(cols)
347
+ # :nocov:
347
348
  if RUBY_VERSION >= '2.5'
349
+ # :nocov:
348
350
  cols.each do |_, h|
349
351
  db_type = h[:db_type]
350
352
  if db_type.is_a?(String)
@@ -38,7 +38,6 @@ module Sequel
38
38
  @constraints = []
39
39
  @primary_key = nil
40
40
  instance_exec(&block) if block
41
- @columns.unshift(@primary_key) if @primary_key && !has_column?(primary_key_name)
42
41
  end
43
42
 
44
43
  # Use custom Bignum method to use :Bignum instead of Bignum class, to work
@@ -240,7 +240,7 @@ module Sequel
240
240
  if supports_create_or_replace_view?
241
241
  options = options.merge(:replace=>true)
242
242
  else
243
- drop_view(name) rescue nil
243
+ swallow_database_error{drop_view(name)}
244
244
  end
245
245
 
246
246
  create_view(name, source, options)
@@ -494,7 +494,9 @@ module Sequel
494
494
  when :drop_index
495
495
  drop_index_sql(table, op)
496
496
  else
497
- "ALTER TABLE #{quote_schema_table(table)} #{alter_table_op_sql(table, op)}"
497
+ if sql = alter_table_op_sql(table, op)
498
+ "ALTER TABLE #{quote_schema_table(table)} #{sql}"
499
+ end
498
500
  end
499
501
  end
500
502
 
@@ -811,23 +813,20 @@ module Sequel
811
813
  # Proxy the filter_expr call to the dataset, used for creating constraints.
812
814
  # Support passing Proc arguments as blocks, as well as treating plain strings
813
815
  # as literal strings, so that previous migrations that used this API do not break.
814
- def filter_expr(*args, &block)
815
- if args.length == 1
816
- arg = args.first
817
- if arg.is_a?(Proc) && !block
818
- block = args.first
819
- args = nil
820
- elsif arg.is_a?(String)
821
- args = [Sequel.lit(*args)]
822
- elsif arg.is_a?(Array)
823
- if arg.first.is_a?(String)
824
- args = [Sequel.lit(*arg)]
825
- elsif arg.length > 1
826
- args = [Sequel.&(*arg)]
827
- end
816
+ def filter_expr(arg=nil, &block)
817
+ if arg.is_a?(Proc) && !block
818
+ block = arg
819
+ arg = nil
820
+ elsif arg.is_a?(String)
821
+ arg = Sequel.lit(arg)
822
+ elsif arg.is_a?(Array)
823
+ if arg.first.is_a?(String)
824
+ arg = Sequel.lit(*arg)
825
+ elsif arg.length > 1
826
+ arg = Sequel.&(*arg)
828
827
  end
829
828
  end
830
- schema_utility_dataset.literal(schema_utility_dataset.send(:filter_expr, *args, &block))
829
+ schema_utility_dataset.literal(schema_utility_dataset.send(:filter_expr, arg, &block))
831
830
  end
832
831
 
833
832
  # SQL statement for creating an index for the table with the given name