sequel 5.92.0 → 5.94.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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/lib/sequel/adapters/ado/access.rb +2 -2
  3. data/lib/sequel/adapters/ado.rb +1 -1
  4. data/lib/sequel/adapters/ibmdb.rb +1 -1
  5. data/lib/sequel/adapters/jdbc/mysql.rb +2 -2
  6. data/lib/sequel/adapters/jdbc/oracle.rb +1 -1
  7. data/lib/sequel/adapters/jdbc/sqlite.rb +1 -1
  8. data/lib/sequel/adapters/jdbc/sqlserver.rb +1 -1
  9. data/lib/sequel/adapters/jdbc.rb +21 -7
  10. data/lib/sequel/adapters/mysql.rb +1 -1
  11. data/lib/sequel/adapters/mysql2.rb +2 -2
  12. data/lib/sequel/adapters/odbc.rb +1 -1
  13. data/lib/sequel/adapters/oracle.rb +16 -0
  14. data/lib/sequel/adapters/shared/db2.rb +8 -3
  15. data/lib/sequel/adapters/shared/mssql.rb +1 -1
  16. data/lib/sequel/adapters/shared/mysql.rb +2 -2
  17. data/lib/sequel/adapters/shared/postgres.rb +206 -16
  18. data/lib/sequel/adapters/shared/sqlite.rb +3 -3
  19. data/lib/sequel/adapters/tinytds.rb +1 -1
  20. data/lib/sequel/adapters/trilogy.rb +1 -1
  21. data/lib/sequel/connection_pool/timed_queue.rb +1 -1
  22. data/lib/sequel/core.rb +1 -1
  23. data/lib/sequel/database/misc.rb +3 -3
  24. data/lib/sequel/database/query.rb +1 -1
  25. data/lib/sequel/database/schema_generator.rb +24 -10
  26. data/lib/sequel/database/schema_methods.rb +60 -26
  27. data/lib/sequel/dataset/prepared_statements.rb +68 -24
  28. data/lib/sequel/dataset/query.rb +10 -2
  29. data/lib/sequel/dataset/sql.rb +8 -5
  30. data/lib/sequel/extensions/async_thread_pool.rb +1 -1
  31. data/lib/sequel/extensions/caller_logging.rb +1 -3
  32. data/lib/sequel/extensions/eval_inspect.rb +1 -1
  33. data/lib/sequel/extensions/inflector.rb +2 -2
  34. data/lib/sequel/extensions/migration.rb +1 -1
  35. data/lib/sequel/extensions/pg_auto_parameterize.rb +5 -0
  36. data/lib/sequel/extensions/pg_hstore.rb +1 -1
  37. data/lib/sequel/extensions/provenance.rb +1 -3
  38. data/lib/sequel/extensions/schema_dumper.rb +1 -1
  39. data/lib/sequel/plugins/constraint_validations.rb +1 -1
  40. data/lib/sequel/plugins/json_serializer.rb +3 -3
  41. data/lib/sequel/plugins/unused_associations.rb +4 -2
  42. data/lib/sequel/plugins/validation_class_methods.rb +1 -1
  43. data/lib/sequel/sql.rb +7 -5
  44. data/lib/sequel/version.rb +1 -1
  45. metadata +1 -1
@@ -36,13 +36,13 @@ module Sequel
36
36
 
37
37
  # Register a hook that will be run when a new Database is instantiated. It is
38
38
  # called with the new database handle.
39
- def self.after_initialize(&block)
40
- raise Error, "must provide block to after_initialize" unless block
39
+ def self.after_initialize
40
+ raise Error, "must provide block to after_initialize" unless defined?(yield)
41
41
  Sequel.synchronize do
42
42
  previous = @initialize_hook
43
43
  @initialize_hook = proc do |db|
44
44
  previous.call(db)
45
- block.call(db)
45
+ yield(db)
46
46
  end
47
47
  end
48
48
  end
@@ -269,7 +269,7 @@ module Sequel
269
269
  def column_schema_to_ruby_default(default, type)
270
270
  return default unless default.is_a?(String)
271
271
  if COLUMN_SCHEMA_DATETIME_TYPES.include?(type)
272
- if /now|today|CURRENT|getdate|\ADate\(\)\z/i.match(default)
272
+ if /now|today|CURRENT|getdate|\ADate\(\)\z/i =~ default
273
273
  if type == :date
274
274
  return Sequel::CURRENT_DATE
275
275
  else
@@ -126,17 +126,21 @@ module Sequel
126
126
  # (:restrict, :cascade, :set_null, :set_default, :no_action).
127
127
  # :primary_key :: Make the column as a single primary key column. This should not
128
128
  # be used if you want a single autoincrementing primary key column
129
- # (use the primary_key method in that case).
130
- # :primary_key_constraint_name :: The name to give the primary key constraint
131
- # :primary_key_deferrable :: Similar to :deferrable, but for the primary key constraint
132
- # if :primary_key is used.
129
+ # (use the primary_key method in that case). Can be a hash to provide
130
+ # options for the constraint:
131
+ # :name :: The name to give the primary key constraint.
132
+ # :deferrable :: Sets whether the primary key constraint is deferrable.
133
+ # :primary_key_constraint_name :: Older option to name primary key constraint.
134
+ # :primary_key_deferrable :: Older option to set primary key constraint as deferrable.
133
135
  # :type :: Overrides the type given as the argument. Generally not used by column
134
136
  # itself, but can be passed as an option to other methods that call column.
135
137
  # :unique :: Mark the column as unique, generally has the same effect as
136
- # creating a unique index on the column.
137
- # :unique_constraint_name :: The name to give the unique key constraint
138
- # :unique_deferrable :: Similar to :deferrable, but for the unique constraint if :unique
139
- # is used.
138
+ # creating a unique index on the column. Can be a hash to provide options for
139
+ # the constraint:
140
+ # :name :: The name to give the unique constraint.
141
+ # :deferrable :: Sets whether the unique constraint is deferrable.
142
+ # :unique_constraint_name :: Older option to name unique constraint.
143
+ # :unique_deferrable :: Older option to set unique constraint as deferrable.
140
144
  #
141
145
  # PostgreSQL specific options:
142
146
  #
@@ -178,6 +182,7 @@ module Sequel
178
182
  # :deferrable :: Whether the CHECK constraint should be marked DEFERRABLE.
179
183
  #
180
184
  # PostgreSQL specific options:
185
+ # :not_enforced :: Whether the CHECK constraint should be marked NOT ENFORCED.
181
186
  # :not_valid :: Whether the CHECK constraint should be marked NOT VALID.
182
187
  def constraint(name, *args, &block)
183
188
  opts = name.is_a?(Hash) ? name : {:name=>name}
@@ -197,9 +202,18 @@ module Sequel
197
202
  #
198
203
  # :foreign_key_constraint_name :: The name to give the foreign key constraint
199
204
  #
205
+ # PostgreSQL specific options:
206
+ #
207
+ # :not_enforced :: Whether the foreign key constraint should be marked NOT ENFORCED.
208
+ #
200
209
  # If you want a foreign key constraint without adding a column (usually because it is a
201
- # composite foreign key), you can provide an array of columns as the first argument, and
202
- # you can provide the :name option to name the constraint:
210
+ # composite foreign key), you can provide an array of columns as the first argument.
211
+ # This changes the method to accept constraint options instead of column options.
212
+ # You can provide the :name option to name the constraint.
213
+ #
214
+ # PostgreSQL specific options:
215
+ #
216
+ # :not_enforced :: Whether the foreign key constraint should be marked NOT ENFORCED.
203
217
  #
204
218
  # foreign_key([:artist_name, :artist_location], :artists, name: :artist_fk)
205
219
  # # ADD CONSTRAINT artist_fk FOREIGN KEY (artist_name, artist_location) REFERENCES artists
@@ -605,36 +605,63 @@ module Sequel
605
605
  end
606
606
  end
607
607
 
608
- # Add primary key SQL fragment to column creation SQL.
608
+ # Add primary key SQL fragment to column creation SQL if column is a primary key.
609
609
  def column_definition_primary_key_sql(sql, column)
610
- if column[:primary_key]
611
- if name = column[:primary_key_constraint_name]
612
- sql << " CONSTRAINT #{quote_identifier(name)}"
613
- end
614
- sql << " " << primary_key_constraint_sql_fragment(column)
615
- constraint_deferrable_sql_append(sql, column[:primary_key_deferrable])
616
- end
610
+ column_definition_add_primary_key_sql(sql, column) if column[:primary_key]
611
+ end
612
+
613
+ # Add primary key SQL fragment to column creation SQL (column should be a primary key).
614
+ def column_definition_add_primary_key_sql(sql, column)
615
+ constraint = column_definition_constraint_hash(column, :primary_key)
616
+ append_named_constraint_prefix_sql(sql, constraint[:name])
617
+ sql << " " << primary_key_constraint_sql_fragment(constraint)
618
+ constraint_deferrable_sql_append(sql, constraint[:deferrable])
617
619
  end
618
620
 
619
- # Add foreign key reference SQL fragment to column creation SQL.
621
+ # Add foreign key reference SQL fragment to column creation SQL if column is a foreign key.
620
622
  def column_definition_references_sql(sql, column)
621
- if column[:table]
622
- if name = column[:foreign_key_constraint_name]
623
- sql << " CONSTRAINT #{quote_identifier(name)}"
624
- end
625
- sql << column_references_column_constraint_sql(column)
626
- end
623
+ column_definition_add_references_sql(sql, column) if column[:table]
624
+ end
625
+
626
+ # Add foreign key reference SQL fragment to column creation SQL (column should be a foreign key).
627
+ def column_definition_add_references_sql(sql, column)
628
+ append_named_constraint_prefix_sql(sql, column[:foreign_key_constraint_name])
629
+ sql << column_references_column_constraint_sql(column)
627
630
  end
628
631
 
629
- # Add unique constraint SQL fragment to column creation SQL.
632
+ # Add unique constraint SQL fragment to column creation SQL if column has a unique constraint.
630
633
  def column_definition_unique_sql(sql, column)
631
- if column[:unique]
632
- if name = column[:unique_constraint_name]
633
- sql << " CONSTRAINT #{quote_identifier(name)}"
634
- end
635
- sql << ' ' << unique_constraint_sql_fragment(column)
636
- constraint_deferrable_sql_append(sql, column[:unique_deferrable])
634
+ column_definition_add_unique_sql(sql, column) if column[:unique]
635
+ end
636
+
637
+ # Add unique constraint SQL fragment to column creation SQL (column should have unique constraint).
638
+ def column_definition_add_unique_sql(sql, column)
639
+ constraint = column_definition_constraint_hash(column, :unique)
640
+ append_named_constraint_prefix_sql(sql, constraint[:name])
641
+ sql << ' ' << unique_constraint_sql_fragment(constraint)
642
+ constraint_deferrable_sql_append(sql, constraint[:deferrable])
643
+ end
644
+
645
+ # Add the name of the constraint to the column creation SQL.
646
+ def append_named_constraint_prefix_sql(sql, name)
647
+ sql << " CONSTRAINT #{quote_identifier(name)}" if name
648
+ end
649
+
650
+ # Return a hash of constraint options for the primary key or column
651
+ # unique constraint.
652
+ def column_definition_constraint_hash(column, prefix)
653
+ constraint = column[prefix]
654
+ constraint = constraint.is_a?(Hash) ? constraint.dup : {}
655
+
656
+ if name = column[:"#{prefix}_constraint_name"]
657
+ constraint[:name] = name
637
658
  end
659
+
660
+ if column.has_key?(:"#{prefix}_deferrable")
661
+ constraint[:deferrable] = column[:"#{prefix}_deferrable"]
662
+ end
663
+
664
+ constraint
638
665
  end
639
666
 
640
667
  # SQL for all given columns, used inside a CREATE TABLE block.
@@ -677,7 +704,7 @@ module Sequel
677
704
  check = constraint[:check]
678
705
  check = check.first if check.is_a?(Array) && check.length == 1
679
706
  check = filter_expr(check)
680
- check = "(#{check})" unless check[0..0] == '(' && check[-1..-1] == ')'
707
+ check = "(#{check})" unless check.start_with?('(') && check.end_with?(')')
681
708
  sql << "CHECK #{check}"
682
709
  when :primary_key
683
710
  sql << "#{primary_key_constraint_sql_fragment(constraint)} #{literal(constraint[:columns])}"
@@ -733,17 +760,24 @@ module Sequel
733
760
  def create_table_sql(name, generator, options)
734
761
  unless supports_named_column_constraints?
735
762
  # Split column constraints into table constraints if they have a name
763
+ fk_opt_keys = [:key, :on_delete, :on_update, :deferrable]
736
764
  generator.columns.each do |c|
737
765
  if (constraint_name = c.delete(:foreign_key_constraint_name)) && (table = c.delete(:table))
738
766
  opts = {}
739
767
  opts[:name] = constraint_name
740
- [:key, :on_delete, :on_update, :deferrable].each{|k| opts[k] = c[k]}
768
+ fk_opt_keys.each{|k| opts[k] = c[k]}
741
769
  generator.foreign_key([c[:name]], table, opts)
742
770
  end
743
- if (constraint_name = c.delete(:unique_constraint_name)) && c.delete(:unique)
771
+
772
+ if c[:unique].is_a?(Hash) && c[:unique][:name]
773
+ generator.unique(c[:name], c.delete(:unique))
774
+ elsif (constraint_name = c.delete(:unique_constraint_name)) && c.delete(:unique)
744
775
  generator.unique(c[:name], :name=>constraint_name)
745
776
  end
746
- if (constraint_name = c.delete(:primary_key_constraint_name)) && c.delete(:primary_key)
777
+
778
+ if c[:primary_key].is_a?(Hash) && c[:primary_key][:name]
779
+ generator.primary_key([c[:name]], c.delete(:primary_key))
780
+ elsif (constraint_name = c.delete(:primary_key_constraint_name)) && c.delete(:primary_key)
747
781
  generator.primary_key([c[:name]], :name=>constraint_name)
748
782
  end
749
783
  end
@@ -91,8 +91,14 @@ module Sequel
91
91
  @opts[:log_sql]
92
92
  end
93
93
 
94
- # The type of prepared statement, should be one of :select, :first,
95
- # :insert, :update, :delete, or :single_value
94
+ # The type of SQL to generate for the prepared statement. Generally
95
+ # the same as #prepared_type, but can be different.
96
+ def prepared_sql_type
97
+ @opts[:prepared_sql_type] || prepared_type
98
+ end
99
+
100
+ # The type of prepared statement, which controls how the prepared statement
101
+ # handles results from the database.
96
102
  def prepared_type
97
103
  @opts[:prepared_type]
98
104
  end
@@ -141,7 +147,7 @@ module Sequel
141
147
  # Returns the SQL for the prepared statement, depending on
142
148
  # the type of the statement and the prepared_modify_values.
143
149
  def prepared_sql
144
- case prepared_type
150
+ case prepared_sql_type
145
151
  when :select, :all, :each
146
152
  # Most common scenario, so listed first.
147
153
  select_sql
@@ -182,34 +188,30 @@ module Sequel
182
188
 
183
189
  # Run the method based on the type of prepared statement.
184
190
  def run(&block)
185
- case prepared_type
191
+ case type = prepared_type
186
192
  when :select, :all
187
- all(&block)
193
+ with_sql_all(prepared_sql, &block)
188
194
  when :each
189
- each(&block)
190
- when :insert_select
191
- with_sql(prepared_sql).first
192
- when :first
193
- first
195
+ with_sql_each(prepared_sql, &block)
196
+ when :insert_select, :first
197
+ with_sql_first(prepared_sql)
194
198
  when :insert, :update, :delete
195
199
  if opts[:returning] && supports_returning?(prepared_type)
196
200
  returning_fetch_rows(prepared_sql)
197
- elsif prepared_type == :delete
198
- delete
201
+ elsif type == :delete
202
+ with_sql_delete(prepared_sql)
199
203
  else
200
- public_send(prepared_type, *prepared_modify_values)
204
+ force_prepared_sql.public_send(type, *prepared_modify_values)
201
205
  end
202
- when :insert_pk
203
- fetch_rows(prepared_sql){|r| return r.values.first}
206
+ when :insert_pk, :single_value
207
+ with_sql_single_value(prepared_sql)
204
208
  when Array
205
209
  # :nocov:
206
- case prepared_type[0]
210
+ case type[0]
207
211
  # :nocov:
208
212
  when :map, :as_hash, :to_hash, :to_hash_groups
209
- public_send(*prepared_type, &block)
213
+ force_prepared_sql.public_send(*type, &block)
210
214
  end
211
- when :single_value
212
- single_value
213
215
  else
214
216
  raise Error, "unsupported prepared statement type used: #{prepared_type.inspect}"
215
217
  end
@@ -217,6 +219,16 @@ module Sequel
217
219
 
218
220
  private
219
221
 
222
+ # If the prepared_sql_type does not match the prepared statement, return a clone that
223
+ # with the prepared SQL, to ensure the prepared_sql_type is respected.
224
+ def force_prepared_sql
225
+ if prepared_sql_type != prepared_type
226
+ with_sql(prepared_sql)
227
+ else
228
+ self
229
+ end
230
+ end
231
+
220
232
  # Returns the value of the prepared_args hash for the given key.
221
233
  def prepared_arg(k)
222
234
  @opts[:bind_vars][k]
@@ -294,11 +306,12 @@ module Sequel
294
306
  prepared_sql, frags = Sequel::Dataset::PlaceholderLiteralizer::Recorder.new.send(:prepared_sql_and_frags, self, prepared_args) do |pl, ds|
295
307
  ds = ds.clone(:recorder=>pl)
296
308
 
297
- case type
309
+ sql_type = prepared_sql_type || type
310
+ case sql_type
298
311
  when :first, :single_value
299
312
  ds.limit(1)
300
313
  when :update, :insert, :insert_select, :delete
301
- ds.with_sql(:"#{type}_sql", *values)
314
+ ds.with_sql(:"#{sql_type}_sql", *values)
302
315
  when :insert_pk
303
316
  ds.with_sql(:insert_sql, *values)
304
317
  else
@@ -344,13 +357,23 @@ module Sequel
344
357
  clone(:bind_vars=>bind_vars)
345
358
  end
346
359
 
347
- # For the given type (:select, :first, :insert, :insert_select, :update, :delete, or :single_value),
348
- # run the sql with the bind variables specified in the hash. +values+ is a hash passed to
349
- # insert or update (if one of those types is used), which may contain placeholders.
360
+ # For the given type, run the sql with the bind variables specified in the hash.
361
+ # +values+ is a hash passed to insert or update (if one of those types is used),
362
+ # which may contain placeholders.
363
+ #
364
+ # The following types are supported:
365
+ #
366
+ # * :select, :all, :each, :first, :single_value, :insert, :insert_select, :insert_pk, :update, :delete
367
+ # * Array where first element is :map, :as_hash, :to_hash, :to_hash_groups (remaining elements
368
+ # are passed to the related method)
350
369
  #
351
370
  # DB[:table].where(id: :$id).call(:first, id: 1)
352
371
  # # SELECT * FROM table WHERE id = ? LIMIT 1 -- (1)
353
372
  # # => {:id=>1}
373
+ #
374
+ # DB[:table].where(id: :$id).call(:update, {c: 1, id: 2}, col: :$c)
375
+ # # UPDATE table WHERE id = ? SET col = ? -- (2, 1)
376
+ # # => 1
354
377
  def call(type, bind_variables=OPTS, *values, &block)
355
378
  to_prepared_statement(type, values, :extend=>bound_variable_modules).call(bind_variables, &block)
356
379
  end
@@ -371,6 +394,14 @@ module Sequel
371
394
  # # => {:id=>1, :name=>'Blah'}
372
395
  #
373
396
  # DB.call(:select_by_name, name: 'Blah') # Same thing
397
+ #
398
+ # +values+ given are passed to +insert+ or +update+ if they are used:
399
+ #
400
+ # ps = DB[:table].where(id: :$i).prepare(:update, :update_name, name: :$n)
401
+ #
402
+ # ps.call(i: 1, n: 'Blah')
403
+ # # UPDATE table WHERE id = ? SET name = ? -- (1, 'Blah')
404
+ # # => 1
374
405
  def prepare(type, name, *values)
375
406
  ps = to_prepared_statement(type, values, :name=>name, :extend=>prepared_statement_modules, :no_delayed_evaluations=>true)
376
407
 
@@ -387,6 +418,19 @@ module Sequel
387
418
  ps
388
419
  end
389
420
 
421
+ # Set the type of SQL to use for prepared statements based on this
422
+ # dataset. Prepared statements default to using the same SQL type
423
+ # as the type that is passed to #prepare/#call, but there are cases
424
+ # where it is helpful to use a different SQL type.
425
+ #
426
+ # Available types are: :select, :first, :single_value, :update,
427
+ # :delete, :insert, :insert_select, :insert_pk
428
+ #
429
+ # Other types are treated as :select.
430
+ def prepare_sql_type(type)
431
+ clone(:prepared_sql_type => type)
432
+ end
433
+
390
434
  protected
391
435
 
392
436
  # Return a cloned copy of the current dataset extended with
@@ -231,8 +231,7 @@ module Sequel
231
231
  #
232
232
  # DB[:table].for_update # SELECT * FROM table FOR UPDATE
233
233
  def for_update
234
- return self if opts[:lock] == :update
235
- cached_dataset(:_for_update_ds){lock_style(:update)}
234
+ cached_lock_style_dataset(:_for_update_ds, :update)
236
235
  end
237
236
 
238
237
  # Returns a copy of the dataset with the source changed. If no
@@ -1462,6 +1461,15 @@ module Sequel
1462
1461
  end
1463
1462
  end
1464
1463
 
1464
+ # Internals of for_update and adapter-specific lock methods.
1465
+ # Returns receiver if it already uses this lock style, and a cached
1466
+ # dataset using the given key otherwise. The key could be derived from
1467
+ # the style, but doing so would require allocation, so pass it in as
1468
+ # an argument.
1469
+ def cached_lock_style_dataset(key, style)
1470
+ opts[:lock] == style ? self : cached_dataset(key){lock_style(style)}
1471
+ end
1472
+
1465
1473
  # The default :qualify option to use for join tables if one is not specified.
1466
1474
  def default_join_table_qualification
1467
1475
  :symbol
@@ -685,10 +685,10 @@ module Sequel
685
685
  # being quoted, returns name as a string. If identifiers are being quoted
686
686
  # quote the name with quoted_identifier.
687
687
  def quote_identifier_append(sql, name)
688
+ name = name.value if name.is_a?(SQL::Identifier)
688
689
  if name.is_a?(LiteralString)
689
690
  sql << name
690
691
  else
691
- name = name.value if name.is_a?(SQL::Identifier)
692
692
  name = input_identifier(name)
693
693
  if quote_identifiers?
694
694
  quoted_identifier_append(sql, name)
@@ -700,11 +700,14 @@ module Sequel
700
700
 
701
701
  # Append literalization of identifier or unqualified identifier to SQL string.
702
702
  def quote_schema_table_append(sql, table)
703
- schema, table = schema_and_table(table)
704
- if schema
705
- quote_identifier_append(sql, schema)
703
+ qualifiers = split_qualifiers(table)
704
+ table = qualifiers.pop
705
+
706
+ qualifiers.each do |q|
707
+ quote_identifier_append(sql, q)
706
708
  sql << '.'
707
709
  end
710
+
708
711
  quote_identifier_append(sql, table)
709
712
  end
710
713
 
@@ -1336,7 +1339,7 @@ module Sequel
1336
1339
  # SQL fragment specifying a JOIN type, converts underscores to
1337
1340
  # spaces and upcases.
1338
1341
  def join_type_sql(join_type)
1339
- "#{join_type.to_s.gsub('_', ' ').upcase} JOIN"
1342
+ "#{join_type.to_s.tr('_', ' ').upcase} JOIN"
1340
1343
  end
1341
1344
 
1342
1345
  # Append USING clause for JOIN USING
@@ -357,7 +357,7 @@ module Sequel
357
357
  define_singleton_method(:async_job_class){proxy_klass}
358
358
 
359
359
  queue = @async_thread_queue = Queue.new
360
- pool = @async_thread_pool = num_async_threads.times.map{JobProcessor.new(queue)}
360
+ pool = @async_thread_pool = Array.new(num_async_threads){JobProcessor.new(queue)}
361
361
  ObjectSpace.define_finalizer(db, JobProcessor.create_finalizer(queue, pool))
362
362
 
363
363
  extend_datasets(DatasetMethods)
@@ -60,9 +60,7 @@ module Sequel
60
60
  def external_caller_for_log
61
61
  ignore = caller_logging_ignore
62
62
  c = caller.find do |line|
63
- !(line.start_with?(SEQUEL_LIB_PATH) ||
64
- line.start_with?(RUBY_STDLIB) ||
65
- line.start_with?(INTERNAL) ||
63
+ !(line.start_with?(SEQUEL_LIB_PATH, RUBY_STDLIB, INTERNAL) ||
66
64
  (ignore && line =~ ignore))
67
65
  end
68
66
 
@@ -66,7 +66,7 @@ module Sequel
66
66
  # in the order they were defined.
67
67
  klass = self.class
68
68
  args = inspect_args.map do |arg|
69
- if arg.is_a?(String) && arg =~ /\A\*/
69
+ if arg.is_a?(String) && arg.start_with?('*')
70
70
  # Special case string arguments starting with *, indicating that
71
71
  # they should return an array to be splatted as the remaining arguments.
72
72
  # Allow calling private methods to get inspect output.
@@ -159,7 +159,7 @@ class String
159
159
  # Example
160
160
  # "puni_puni".dasherize #=> "puni-puni"
161
161
  def dasherize
162
- gsub('_', '-')
162
+ tr('_', '-')
163
163
  end
164
164
 
165
165
  # Removes the module part from the expression in the string
@@ -189,7 +189,7 @@ class String
189
189
  # "employee_salary" #=> "Employee salary"
190
190
  # "author_id" #=> "Author"
191
191
  def humanize
192
- gsub(/_id$/, "").gsub('_', " ").capitalize
192
+ gsub(/_id$/, "").tr('_', " ").capitalize
193
193
  end
194
194
 
195
195
  # Returns the plural form of the word in the string.
@@ -845,7 +845,7 @@ module Sequel
845
845
  begin
846
846
  db.create_table(table){String c, :primary_key=>true}
847
847
  rescue Sequel::DatabaseError => e
848
- if db.database_type == :mysql && e.message =~ /max key length/
848
+ if db.database_type == :mysql && e.message.include?('max key length')
849
849
  # Handle case where MySQL is used with utf8mb4 charset default, which
850
850
  # only allows a maximum length of about 190 characters for string
851
851
  # primary keys due to InnoDB limitations.
@@ -463,6 +463,11 @@ module Sequel
463
463
  @opts[:no_auto_parameterize] ? super : QueryString.new
464
464
  end
465
465
 
466
+ # A mutable string used as the prefix when explaining a query.
467
+ def explain_sql_string_origin(opts)
468
+ @opts[:no_auto_parameterize] ? super : (QueryString.new << super)
469
+ end
470
+
466
471
  # If subquery uses with_sql with a method name symbol, get the dataset
467
472
  # with_sql was called on, and use that as the subquery, recording the
468
473
  # arguments to with_sql that will be used to calculate the sql.
@@ -136,7 +136,7 @@ module Sequel
136
136
  module DatabaseMethods
137
137
  def self.extended(db)
138
138
  db.instance_exec do
139
- add_named_conversion_proc(:hstore, &HStore.method(:parse))
139
+ add_named_conversion_proc(:hstore){|v| HStore.parse(v)}
140
140
  @schema_type_classes[:hstore] = HStore
141
141
  end
142
142
  end
@@ -97,9 +97,7 @@ module Sequel
97
97
  def provenance_source
98
98
  ignore = db.opts[:provenance_caller_ignore]
99
99
  caller.find do |line|
100
- !(line.start_with?(SEQUEL_LIB_PATH) ||
101
- line.start_with?(RUBY_STDLIB) ||
102
- line.start_with?(INTERNAL) ||
100
+ !(line.start_with?(SEQUEL_LIB_PATH, RUBY_STDLIB, INTERNAL) ||
103
101
  (ignore && line =~ ignore))
104
102
  end
105
103
  end
@@ -221,7 +221,7 @@ END_MIG
221
221
  else
222
222
  col_opts = if options[:same_db]
223
223
  h = {:type=>schema[:db_type]}
224
- if database_type == :mysql && h[:type] =~ /\Atimestamp/
224
+ if database_type == :mysql && h[:type].start_with?("timestamp")
225
225
  h[:null] = true
226
226
  end
227
227
  if database_type == :mssql && schema[:max_length]
@@ -164,7 +164,7 @@ module Sequel
164
164
  arg = constraint_validation_int_range(arg)
165
165
  type = :includes
166
166
  when *OPERATOR_MAP.keys
167
- arg = arg.to_i if type.to_s =~ /\Aint_/
167
+ arg = arg.to_i if type.to_s.start_with?('int_')
168
168
  operator = OPERATOR_MAP[type]
169
169
  type = :operator
170
170
  end
@@ -370,9 +370,9 @@ module Sequel
370
370
  end
371
371
 
372
372
  # Convert the receiver to a JSON data structure using the given arguments.
373
- def to_json_data(*args, &block)
374
- if block
375
- to_json(*args){|x| return block.call(x)}
373
+ def to_json_data(*args)
374
+ if defined?(yield)
375
+ to_json(*args){|x| return yield(x)}
376
376
  else
377
377
  to_json(*args){|x| return x}
378
378
  end
@@ -347,6 +347,8 @@ module Sequel
347
347
  coverage_data = options[:coverage_data] || Sequel.parse_json(File.binread(@unused_associations_coverage_file))
348
348
 
349
349
  unused_associations_data = {}
350
+ to_many_modification_methods = [:adder, :remover, :clearer]
351
+ modification_methods = [:setter, :adder, :remover, :clearer]
350
352
 
351
353
  ([self] + descendants).each do |sc|
352
354
  next unless cov_data = coverage_data[sc.name]
@@ -383,8 +385,8 @@ module Sequel
383
385
  if !info[:used]
384
386
  (unused_associations_data[sc.name] ||= {})[assoc.to_s] = 'unused'
385
387
  elsif unused = info[:unused]
386
- if unused.include?(:setter) || [:adder, :remover, :clearer].all?{|k| unused.include?(k)}
387
- [:setter, :adder, :remover, :clearer].each do |k|
388
+ if unused.include?(:setter) || to_many_modification_methods.all?{|k| unused.include?(k)}
389
+ modification_methods.each do |k|
388
390
  unused.delete(k)
389
391
  end
390
392
  unused << :read_only
@@ -208,7 +208,7 @@ module Sequel
208
208
  next if an && Array(v).all?(&:nil?)
209
209
  next if ab && Array(v).all?(&blank_meth)
210
210
  next if am && Array(a).all?{|x| !o.values.has_key?(x)}
211
- block.call(o,a,v)
211
+ yield(o, a, v)
212
212
  end
213
213
  else
214
214
  block
data/lib/sequel/sql.rb CHANGED
@@ -1733,12 +1733,11 @@ module Sequel
1733
1733
 
1734
1734
  # Automatically convert SQL::Identifiers to strings
1735
1735
  def convert_identifier(identifier)
1736
- case identifier
1737
- when SQL::Identifier
1738
- identifier.value.to_s
1739
- else
1740
- identifier
1736
+ if identifier.is_a?(SQL::Identifier)
1737
+ identifier = identifier.value
1738
+ identifier = identifier.to_s unless identifier.is_a?(LiteralString)
1741
1739
  end
1740
+ identifier
1742
1741
  end
1743
1742
  end
1744
1743
 
@@ -2053,6 +2052,9 @@ module Sequel
2053
2052
  end
2054
2053
  end
2055
2054
 
2055
+ SQL::Constants::OLD = SQL::Identifier.new(LiteralString.new("OLD").freeze)
2056
+ SQL::Constants::NEW = SQL::Identifier.new(LiteralString.new("NEW").freeze)
2057
+
2056
2058
  include SQL::Constants
2057
2059
  extend SQL::Builders
2058
2060
  extend SQL::OperatorBuilders
@@ -6,7 +6,7 @@ module Sequel
6
6
 
7
7
  # The minor version of Sequel. Bumped for every non-patch level
8
8
  # release, generally around once a month.
9
- MINOR = 92
9
+ MINOR = 94
10
10
 
11
11
  # The tiny version of Sequel. Usually 0, only bumped for bugfix
12
12
  # releases that fix regressions from previous versions.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sequel
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.92.0
4
+ version: 5.94.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Evans