sequel 5.60.0 → 5.61.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +16 -0
  3. data/doc/release_notes/5.61.0.txt +43 -0
  4. data/lib/sequel/adapters/jdbc/sqlite.rb +1 -1
  5. data/lib/sequel/adapters/jdbc.rb +5 -5
  6. data/lib/sequel/adapters/mock.rb +1 -1
  7. data/lib/sequel/adapters/mysql.rb +3 -3
  8. data/lib/sequel/adapters/oracle.rb +1 -1
  9. data/lib/sequel/adapters/postgres.rb +6 -6
  10. data/lib/sequel/adapters/shared/mssql.rb +1 -1
  11. data/lib/sequel/adapters/shared/oracle.rb +1 -1
  12. data/lib/sequel/adapters/shared/postgres.rb +1 -1
  13. data/lib/sequel/adapters/sqlite.rb +1 -1
  14. data/lib/sequel/ast_transformer.rb +1 -1
  15. data/lib/sequel/database/misc.rb +56 -12
  16. data/lib/sequel/dataset/sql.rb +2 -2
  17. data/lib/sequel/extensions/duplicate_columns_handler.rb +1 -1
  18. data/lib/sequel/extensions/looser_typecasting.rb +3 -0
  19. data/lib/sequel/extensions/pg_array.rb +2 -2
  20. data/lib/sequel/extensions/pg_array_ops.rb +1 -1
  21. data/lib/sequel/extensions/pg_enum.rb +1 -1
  22. data/lib/sequel/extensions/pg_extended_date_support.rb +15 -24
  23. data/lib/sequel/extensions/pg_hstore_ops.rb +3 -3
  24. data/lib/sequel/extensions/pg_inet.rb +3 -3
  25. data/lib/sequel/extensions/pg_interval.rb +2 -2
  26. data/lib/sequel/extensions/pg_json.rb +1 -1
  27. data/lib/sequel/extensions/pg_json_ops.rb +3 -55
  28. data/lib/sequel/extensions/pg_multirange.rb +2 -2
  29. data/lib/sequel/extensions/pg_range.rb +3 -3
  30. data/lib/sequel/extensions/pg_row.rb +2 -2
  31. data/lib/sequel/extensions/pg_static_cache_updater.rb +2 -2
  32. data/lib/sequel/model/associations.rb +6 -6
  33. data/lib/sequel/model/base.rb +3 -3
  34. data/lib/sequel/model/exceptions.rb +1 -1
  35. data/lib/sequel/model/inflections.rb +6 -6
  36. data/lib/sequel/plugins/auto_validations.rb +1 -1
  37. data/lib/sequel/plugins/defaults_setter.rb +1 -1
  38. data/lib/sequel/plugins/dirty.rb +1 -1
  39. data/lib/sequel/plugins/insert_conflict.rb +1 -1
  40. data/lib/sequel/plugins/json_serializer.rb +1 -1
  41. data/lib/sequel/plugins/nested_attributes.rb +1 -1
  42. data/lib/sequel/plugins/pg_auto_constraint_validations.rb +1 -1
  43. data/lib/sequel/plugins/serialization.rb +1 -1
  44. data/lib/sequel/plugins/sharding.rb +1 -1
  45. data/lib/sequel/plugins/subclasses.rb +1 -1
  46. data/lib/sequel/plugins/validation_class_methods.rb +3 -3
  47. data/lib/sequel/plugins/validation_helpers.rb +1 -1
  48. data/lib/sequel/sql.rb +1 -1
  49. data/lib/sequel/version.rb +1 -1
  50. metadata +4 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1bd9076a491b881827f095bbb1177974861448054cd73376ee76a42ed0f72ee5
4
- data.tar.gz: e2e23f283d2d9f5b29df1510f5f39c8335cc47c37d0f92c848763cd437d4e668
3
+ metadata.gz: f542d5f0e7cca642a8fccd52cb4099101f38dbd1617ff2437b8690766b5f2bdd
4
+ data.tar.gz: 79ff2215f1e38e523e7e64a5779bee695a939a03f046a5e2e9a5974a804a714c
5
5
  SHA512:
6
- metadata.gz: 309b37a25a51bc38c30c20276b7df1df4d21b6b14502b129fc363a0ac9bfc4897be03c21ec1d5b4b333eb6c1944491e4383406bb3f2cb96ba8dd1e98b513de42
7
- data.tar.gz: 58adf4e309a3bd1d921f95d168a79830cce4526767b8ee9379ce69463327b10f0db4ded44a4a8e474cd0dd31036546b120f3e38a07c3057a5290933cffd3b77a
6
+ metadata.gz: 1e0bdc80d388f1bdbf39674624522f7086ca5b0904df2bb28d7b6f3c8f6057df38eca1c0854905a87d920286e578d1e0fe269deb33c3c3f1691d2113a9f23d11
7
+ data.tar.gz: 31ebb15cc504b82c5406c2f7eb6a02a99aa035e9486ecd52698403eff7bd79a99e606229dbbf392ac3fabd1b68c9a7ebc09c127dea3970e2a083c7d781159f33
data/CHANGELOG CHANGED
@@ -1,3 +1,19 @@
1
+ === 5.61.0 (2022-10-01)
2
+
3
+ * Make Database#foreign_key_list on PostgreSQL return results for partitioned tables (jeremyevans)
4
+
5
+ * Add Database#check_string_typecast_bytesize for checking bytesize of strings before typecasting (jeremyevans)
6
+
7
+ * Treat negative hexidecimal strings similar to positive hexidecimal strings when typecasting to integer (jeremyevans)
8
+
9
+ * Remove is_json and is_not_json methods from the pg_json_ops extension, as the support was removed in PostgreSQL 15 beta 4 (jeremyevans)
10
+
11
+ * Fix handling of timestamps before the date of calendar reform when using pg_extended_date_support extension on Ruby 3.2 (jeremyevans)
12
+
13
+ === 5.60.1 (2022-09-02)
14
+
15
+ * Revert conversion of respond_to? to defined?, as it breaks with unused refinements on Ruby 2 (jeremyevans) (#1919)
16
+
1
17
  === 5.60.0 (2022-09-01)
2
18
 
3
19
  * Support arbitrary expressions for date_arithmetic interval values on PostgreSQL 9.4+ (jeremyevans)
@@ -0,0 +1,43 @@
1
+ = Improvements
2
+
3
+ * When typecasting strings to other types, Sequel::Database will now
4
+ by default not typecast strings that are much longer than expected
5
+ for the underlying type. Depending on the underlying type, there
6
+ is a limit of either 100 or 1000 bytes on the input string. This
7
+ avoids potential performance issues when trying to convert
8
+ arbitrary sized user input to specific types.
9
+
10
+ * The respond_to? to defined? change made in 5.60.0 was reverted in
11
+ 5.60.1 as it broke cases on Ruby < 3 where the object had an unused
12
+ refinement that added the method.
13
+
14
+ * When typecasting strings to integer, strings such as -0xa are now
15
+ treated as negative hexidecimal strings, similar to how 0xa is
16
+ treated as a positive hexidecimal string.
17
+
18
+ * Database#foreign_key_list now returns results for partitioned
19
+ tables on PostgreSQL 11+.
20
+
21
+ * Timestamps before the date of calendar reform are now handled
22
+ correctly by the pg_extended_date_support extension when using
23
+ Ruby 3.2 preview 2+.
24
+
25
+ = Backwards Compatibility
26
+
27
+ * The change to not typecast strings that are too long can break
28
+ backwards compatibility for applications that expect typecasting
29
+ for input beyond Sequel's limits. You can disable the string
30
+ bytesize checking by setting:
31
+
32
+ DB.check_string_typecast_bytesize = false
33
+
34
+ or by passing the check_string_typecast_bytesize: false option when
35
+ creating the Database instance.
36
+
37
+ * Code to workaround a bug in JRuby 9.2.0.0 has been removed from the
38
+ pg_extended_date_support extension. Users of the extension should
39
+ upgrade to a newer JRuby version.
40
+
41
+ * The is_json and is_not_json methods have been removed from the
42
+ pg_json_ops extension, as the underlying support was removed in
43
+ PostgreSQL 15 beta 4.
@@ -125,7 +125,7 @@ module Sequel
125
125
 
126
126
  # The result code for the exception, if the jdbc driver supports result codes for exceptions.
127
127
  def sqlite_error_code(exception)
128
- exception.resultCode.code if defined?(exception.resultCode)
128
+ exception.resultCode.code if exception.respond_to?(:resultCode)
129
129
  end
130
130
  end
131
131
  end
@@ -38,7 +38,7 @@ module Sequel
38
38
  else
39
39
  if defined?(::Jdbc) && ( ::Jdbc.const_defined?(name) rescue nil )
40
40
  jdbc_module = ::Jdbc.const_get(name) # e.g. Jdbc::SQLite3
41
- jdbc_module.load_driver if defined?(jdbc_module.load_driver)
41
+ jdbc_module.load_driver if jdbc_module.respond_to?(:load_driver)
42
42
  end
43
43
  end
44
44
 
@@ -396,9 +396,9 @@ module Sequel
396
396
 
397
397
  def database_exception_sqlstate(exception, opts)
398
398
  if database_exception_use_sqlstates?
399
- while defined?(exception.cause)
399
+ while exception.respond_to?(:cause)
400
400
  exception = exception.cause
401
- return exception.getSQLState if defined?(exception.getSQLState)
401
+ return exception.getSQLState if exception.respond_to?(:getSQLState)
402
402
  end
403
403
  end
404
404
  nil
@@ -415,8 +415,8 @@ module Sequel
415
415
 
416
416
  # Raise a disconnect error if the SQL state of the cause of the exception indicates so.
417
417
  def disconnect_error?(exception, opts)
418
- cause = defined?(exception.cause) ? exception.cause : exception
419
- super || (defined?(cause.getSQLState) && cause.getSQLState =~ /^08/)
418
+ cause = exception.respond_to?(:cause) ? exception.cause : exception
419
+ super || (cause.respond_to?(:getSQLState) && cause.getSQLState =~ /^08/)
420
420
  end
421
421
 
422
422
  # Execute the prepared statement. If the provided name is a
@@ -257,7 +257,7 @@ module Sequel
257
257
  @shared_adapter = true
258
258
  extend(mod::DatabaseMethods)
259
259
  extend_datasets(mod::DatasetMethods)
260
- if defined?(mod.mock_adapter_setup)
260
+ if mod.respond_to?(:mock_adapter_setup)
261
261
  mod.mock_adapter_setup(self)
262
262
  end
263
263
  end
@@ -72,7 +72,7 @@ module Sequel
72
72
  def connect(server)
73
73
  opts = server_opts(server)
74
74
 
75
- if defined?(Mysql.init)
75
+ if Mysql.respond_to?(:init)
76
76
  conn = Mysql.init
77
77
  conn.options(Mysql::READ_DEFAULT_GROUP, opts[:config_default_group] || "client")
78
78
  conn.options(Mysql::OPT_LOCAL_INFILE, opts[:config_local_infile]) if opts.has_key?(:config_local_infile)
@@ -186,7 +186,7 @@ module Sequel
186
186
  elsif defined?(yield)
187
187
  yield conn
188
188
  end
189
- if defined?(conn.more_results?)
189
+ if conn.respond_to?(:more_results?)
190
190
  while conn.more_results? do
191
191
  if r
192
192
  r.free
@@ -207,7 +207,7 @@ module Sequel
207
207
  ensure
208
208
  r.free if r
209
209
  # Use up all results to avoid a commands out of sync message.
210
- if defined?(conn.more_results?)
210
+ if conn.respond_to?(:more_results?)
211
211
  while conn.more_results? do
212
212
  begin
213
213
  conn.next_result
@@ -149,7 +149,7 @@ module Sequel
149
149
  end
150
150
 
151
151
  def database_specific_error_class(exception, opts)
152
- return super unless defined?(exception.code)
152
+ return super unless exception.respond_to?(:code)
153
153
  case exception.code
154
154
  when 1400, 1407
155
155
  NotNullConstraintViolation
@@ -160,7 +160,7 @@ module Sequel
160
160
  begin
161
161
  defined?(yield) ? yield(q) : q.cmd_tuples
162
162
  ensure
163
- q.clear if q && defined?(q.clear)
163
+ q.clear if q && q.respond_to?(:clear)
164
164
  end
165
165
  end
166
166
 
@@ -258,7 +258,7 @@ module Sequel
258
258
 
259
259
  # :nocov:
260
260
  if encoding = opts[:encoding] || opts[:charset]
261
- if defined?(conn.set_client_encoding)
261
+ if conn.respond_to?(:set_client_encoding)
262
262
  conn.set_client_encoding(encoding)
263
263
  else
264
264
  conn.async_exec("set client_encoding to '#{encoding}'")
@@ -492,12 +492,12 @@ module Sequel
492
492
  opts[:after_listen].call(conn) if opts[:after_listen]
493
493
  timeout = opts[:timeout]
494
494
  if timeout
495
- timeout_block = defined?(timeout.call) ? timeout : proc{timeout}
495
+ timeout_block = timeout.respond_to?(:call) ? timeout : proc{timeout}
496
496
  end
497
497
 
498
498
  if l = opts[:loop]
499
499
  raise Error, 'calling #listen with :loop requires a block' unless block
500
- loop_call = defined?(l.call)
500
+ loop_call = l.respond_to?(:call)
501
501
  catch(:stop) do
502
502
  while true
503
503
  t = timeout_block ? [timeout_block.call] : []
@@ -582,7 +582,7 @@ module Sequel
582
582
 
583
583
  def database_exception_sqlstate(exception, opts)
584
584
  # :nocov:
585
- if defined?(exception.result) && (result = exception.result)
585
+ if exception.respond_to?(:result) && (result = exception.result)
586
586
  # :nocov:
587
587
  result.error_field(PGresult::PG_DIAG_SQLSTATE)
588
588
  end
@@ -625,7 +625,7 @@ module Sequel
625
625
  begin
626
626
  defined?(yield) ? yield(q) : q.cmd_tuples
627
627
  ensure
628
- q.clear if q && defined?(q.clear)
628
+ q.clear if q && q.respond_to?(:clear)
629
629
  end
630
630
  end
631
631
 
@@ -205,7 +205,7 @@ module Sequel
205
205
  return @server_version = Integer(@opts[:server_version])
206
206
  end
207
207
  @server_version = synchronize(server) do |conn|
208
- (conn.server_version rescue nil) if defined?(conn.server_version)
208
+ (conn.server_version rescue nil) if conn.respond_to?(:server_version)
209
209
  end
210
210
  unless @server_version
211
211
  m = /^(\d+)\.(\d+)\.(\d+)/.match(fetch("SELECT CAST(SERVERPROPERTY('ProductVersion') AS varchar)").single_value.to_s)
@@ -121,7 +121,7 @@ module Sequel
121
121
  def server_version(server=nil)
122
122
  return @server_version if @server_version
123
123
  @server_version = synchronize(server) do |conn|
124
- (conn.server_version rescue nil) if defined?(conn.server_version)
124
+ (conn.server_version rescue nil) if conn.respond_to?(:server_version)
125
125
  end
126
126
  unless @server_version
127
127
  @server_version = if m = /(\d+)\.(\d+)\.?(\d+)?\.?(\d+)?/.match(fetch("select version from PRODUCT_COMPONENT_VERSION where lower(product) like 'oracle%'").single_value)
@@ -586,7 +586,7 @@ module Sequel
586
586
  join(Sequel[:pg_namespace].as(:nsp), :oid=>Sequel[:cl2][:relnamespace]).
587
587
  order{[co[:conname], cpos]}.
588
588
  where{{
589
- cl[:relkind]=>'r',
589
+ cl[:relkind]=>%w'r p',
590
590
  co[:contype]=>'f',
591
591
  cl[:oid]=>oid,
592
592
  cpos=>rpos
@@ -305,7 +305,7 @@ module Sequel
305
305
  if USE_EXTENDED_RESULT_CODES
306
306
  # Support SQLite exception codes if ruby-sqlite3 supports them.
307
307
  def sqlite_error_code(exception)
308
- exception.code if defined?(exception.code)
308
+ exception.code if exception.respond_to?(:code)
309
309
  end
310
310
  end
311
311
  end
@@ -81,7 +81,7 @@ module Sequel
81
81
  when SQL::Wrapper
82
82
  SQL::Wrapper.new(v(o.value))
83
83
  when SQL::Expression
84
- if defined?(o.sequel_ast_transform)
84
+ if o.respond_to?(:sequel_ast_transform)
85
85
  o.sequel_ast_transform(method(:v))
86
86
  else
87
87
  o
@@ -91,6 +91,11 @@ module Sequel
91
91
  # The specific default size of string columns for this Sequel::Database, usually 255 by default.
92
92
  attr_accessor :default_string_column_size
93
93
 
94
+ # Whether to check the bytesize of strings before typecasting (to avoid typecasting strings that
95
+ # would be too long for the given type), true by default. Strings that are too long will raise
96
+ # a typecasting error.
97
+ attr_accessor :check_string_typecast_bytesize
98
+
94
99
  # Constructs a new instance of a database connection with the specified
95
100
  # options hash.
96
101
  #
@@ -98,6 +103,7 @@ module Sequel
98
103
  # :before_preconnect :: Callable that runs after extensions from :preconnect_extensions are loaded,
99
104
  # but before any connections are created.
100
105
  # :cache_schema :: Whether schema should be cached for this Database instance
106
+ # :check_string_typecast_bytesize :: Whether to check the bytesize of strings before typecasting.
101
107
  # :default_string_column_size :: The default size of string columns, 255 by default.
102
108
  # :extensions :: Extensions to load into this Database instance. Can be a symbol, array of symbols,
103
109
  # or string with extensions separated by columns. These extensions are loaded after
@@ -107,7 +113,7 @@ module Sequel
107
113
  # :loggers :: An array of loggers to use.
108
114
  # :log_connection_info :: Whether connection information should be logged when logging queries.
109
115
  # :log_warn_duration :: The number of elapsed seconds after which queries should be logged at warn level.
110
- # :name :: A name to use for the Database object, displayed in PoolTimeout .
116
+ # :name :: A name to use for the Database object, displayed in PoolTimeout.
111
117
  # :preconnect :: Automatically create the maximum number of connections, so that they don't
112
118
  # need to be created as needed. This is useful when connecting takes a long time
113
119
  # and you want to avoid possible latency during runtime.
@@ -116,7 +122,7 @@ module Sequel
116
122
  # :preconnect_extensions :: Similar to the :extensions option, but loads the extensions before the
117
123
  # connections are made by the :preconnect option.
118
124
  # :quote_identifiers :: Whether to quote identifiers.
119
- # :servers :: A hash specifying a server/shard specific options, keyed by shard symbol .
125
+ # :servers :: A hash specifying a server/shard specific options, keyed by shard symbol.
120
126
  # :single_threaded :: Whether to use a single-threaded connection pool.
121
127
  # :sql_log_level :: Method to use to log SQL to a logger, :info by default.
122
128
  #
@@ -132,6 +138,7 @@ module Sequel
132
138
  @opts[:adapter_class] = self.class
133
139
  @opts[:single_threaded] = @single_threaded = typecast_value_boolean(@opts.fetch(:single_threaded, Sequel.single_threaded))
134
140
  @default_string_column_size = @opts[:default_string_column_size] || DEFAULT_STRING_COLUMN_SIZE
141
+ @check_string_typecast_bytesize = typecast_value_boolean(@opts.fetch(:check_string_typecast_bytesize, true))
135
142
 
136
143
  @schemas = {}
137
144
  @prepared_statements = {}
@@ -350,7 +357,7 @@ module Sequel
350
357
  # strings with all whitespace, and ones that respond
351
358
  # true to empty?
352
359
  def blank_object?(obj)
353
- return obj.blank? if defined?(obj.blank?)
360
+ return obj.blank? if obj.respond_to?(:blank?)
354
361
  case obj
355
362
  when NilClass, FalseClass
356
363
  true
@@ -359,7 +366,7 @@ module Sequel
359
366
  when String
360
367
  obj.strip.empty?
361
368
  else
362
- defined?(obj.empty?) ? obj.empty? : false
369
+ obj.respond_to?(:empty?) ? obj.empty? : false
363
370
  end
364
371
  end
365
372
 
@@ -465,6 +472,21 @@ module Sequel
465
472
  # Don't rescue other exceptions, they will be raised normally.
466
473
  end
467
474
 
475
+ # Check the bytesize of a string before conversion. There is no point
476
+ # trying to typecast strings that would be way too long.
477
+ def typecast_check_string_length(string, max_size)
478
+ if @check_string_typecast_bytesize && string.bytesize > max_size
479
+ raise InvalidValue, "string too long to typecast (bytesize: #{string.bytesize}, max: #{max_size})"
480
+ end
481
+ string
482
+ end
483
+
484
+ # Check the bytesize of the string value, if value is a string.
485
+ def typecast_check_length(value, max_size)
486
+ typecast_check_string_length(value, max_size) if String === value
487
+ value
488
+ end
489
+
468
490
  # Typecast the value to an SQL::Blob
469
491
  def typecast_value_blob(value)
470
492
  value.is_a?(Sequel::SQL::Blob) ? value : Sequel::SQL::Blob.new(value)
@@ -488,9 +510,9 @@ module Sequel
488
510
  when Date
489
511
  value
490
512
  when String
491
- Sequel.string_to_date(value)
513
+ Sequel.string_to_date(typecast_check_string_length(value, 100))
492
514
  when Hash
493
- Date.new(*[:year, :month, :day].map{|x| (value[x] || value[x.to_s]).to_i})
515
+ Date.new(*[:year, :month, :day].map{|x| typecast_check_length(value[x] || value[x.to_s], 100).to_i})
494
516
  else
495
517
  raise InvalidValue, "invalid value for Date: #{value.inspect}"
496
518
  end
@@ -498,7 +520,17 @@ module Sequel
498
520
 
499
521
  # Typecast the value to a DateTime or Time depending on Sequel.datetime_class
500
522
  def typecast_value_datetime(value)
501
- Sequel.typecast_to_application_timestamp(value)
523
+ case value
524
+ when String
525
+ Sequel.typecast_to_application_timestamp(typecast_check_string_length(value, 100))
526
+ when Hash
527
+ [:year, :month, :day, :hour, :minute, :second, :nanos, :offset].each do |x|
528
+ typecast_check_length(value[x] || value[x.to_s], 100)
529
+ end
530
+ Sequel.typecast_to_application_timestamp(value)
531
+ else
532
+ Sequel.typecast_to_application_timestamp(value)
533
+ end
502
534
  end
503
535
 
504
536
  if RUBY_VERSION >= '2.4'
@@ -531,18 +563,30 @@ module Sequel
531
563
  when Numeric
532
564
  BigDecimal(value.to_s)
533
565
  when String
534
- _typecast_value_string_to_decimal(value)
566
+ _typecast_value_string_to_decimal(typecast_check_string_length(value, 1000))
535
567
  else
536
568
  raise InvalidValue, "invalid value for BigDecimal: #{value.inspect}"
537
569
  end
538
570
  end
539
571
 
540
572
  # Typecast the value to a Float
541
- alias typecast_value_float Float
573
+ def typecast_value_float(value)
574
+ Float(typecast_check_length(value, 1000))
575
+ end
542
576
 
543
577
  # Typecast the value to an Integer
544
578
  def typecast_value_integer(value)
545
- (value.is_a?(String) && value =~ /\A0+(\d)/) ? Integer(value, 10) : Integer(value)
579
+ case value
580
+ when String
581
+ typecast_check_string_length(value, 100)
582
+ if value =~ /\A-?0+(\d)/
583
+ Integer(value, 10)
584
+ else
585
+ Integer(value)
586
+ end
587
+ else
588
+ Integer(value)
589
+ end
546
590
  end
547
591
 
548
592
  # Typecast the value to a String
@@ -565,9 +609,9 @@ module Sequel
565
609
  SQLTime.create(value.hour, value.min, value.sec, value.nsec/1000.0)
566
610
  end
567
611
  when String
568
- Sequel.string_to_time(value)
612
+ Sequel.string_to_time(typecast_check_string_length(value, 100))
569
613
  when Hash
570
- SQLTime.create(*[:hour, :minute, :second].map{|x| (value[x] || value[x.to_s]).to_i})
614
+ SQLTime.create(*[:hour, :minute, :second].map{|x| typecast_check_length(value[x] || value[x.to_s], 100).to_i})
571
615
  else
572
616
  raise Sequel::InvalidValue, "invalid value for Time: #{value.inspect}"
573
617
  end
@@ -1398,9 +1398,9 @@ module Sequel
1398
1398
  # don't cache SQL for a dataset that uses this.
1399
1399
  disable_sql_caching!
1400
1400
 
1401
- if defined?(v.sql_literal_append)
1401
+ if v.respond_to?(:sql_literal_append)
1402
1402
  v.sql_literal_append(self, sql)
1403
- elsif defined?(v.sql_literal)
1403
+ elsif v.respond_to?(:sql_literal)
1404
1404
  sql << v.sql_literal(self)
1405
1405
  else
1406
1406
  raise Error, "can't express #{v.inspect} as a SQL literal"
@@ -77,7 +77,7 @@ module Sequel
77
77
  def duplicate_columns_handler_type(cols)
78
78
  handler = opts.fetch(:on_duplicate_columns){db.opts.fetch(:on_duplicate_columns, :warn)}
79
79
 
80
- if defined?(handler.call)
80
+ if handler.respond_to?(:call)
81
81
  handler.call(cols)
82
82
  else
83
83
  handler
@@ -8,6 +8,9 @@
8
8
  # :decimal :: use 0.0 for unsupported strings
9
9
  # :string :: silently allow hash and array conversion to string
10
10
  #
11
+ # This also removes bytesize checks for string inputs for float, integer
12
+ # and decimal conversions.
13
+ #
11
14
  # To load the extension into the database:
12
15
  #
13
16
  # DB.extension :looser_typecasting
@@ -301,7 +301,7 @@ module Sequel
301
301
  end
302
302
  end
303
303
 
304
- unless defined?(Sequel::Postgres.parse_pg_array)
304
+ unless Sequel::Postgres.respond_to?(:parse_pg_array)
305
305
  require 'strscan'
306
306
 
307
307
  # PostgreSQL array parser that handles PostgreSQL array output format.
@@ -412,7 +412,7 @@ module Sequel
412
412
  @converter = converter
413
413
  end
414
414
 
415
- if defined?(Sequel::Postgres.parse_pg_array)
415
+ if Sequel::Postgres.respond_to?(:parse_pg_array)
416
416
  # :nocov:
417
417
  # Use sequel_pg's C-based parser if it has already been defined.
418
418
  def call(string)
@@ -158,7 +158,7 @@ module Sequel
158
158
  Sequel.function(:hstore, self, wrap_array(arg))
159
159
  end
160
160
  # :nocov:
161
- if defined?(Sequel.hstore_op)
161
+ if Sequel.respond_to?(:hstore_op)
162
162
  # :nocov:
163
163
  v = Sequel.hstore_op(v)
164
164
  end
@@ -144,7 +144,7 @@ module Sequel
144
144
  select_hash_groups(Sequel.cast(:enumtypid, Integer).as(:v), :enumlabel).freeze
145
145
  enum_labels.each_value(&:freeze)
146
146
 
147
- if defined?(register_array_type)
147
+ if respond_to?(:register_array_type)
148
148
  array_types = metadata_dataset.
149
149
  from(:pg_type).
150
150
  where(:oid=>enum_labels.keys).
@@ -29,6 +29,8 @@ module Sequel
29
29
  INFINITE_DATETIME_VALUES = ([PLUS_INFINITY, MINUS_INFINITY] + INFINITE_TIMESTAMP_STRINGS).freeze
30
30
  PLUS_DATE_INFINITY = Date::Infinity.new
31
31
  MINUS_DATE_INFINITY = -PLUS_DATE_INFINITY
32
+ RATIONAL_60 = Rational(60)
33
+ TIME_CAN_PARSE_BC = RUBY_VERSION >= '2.5'
32
34
 
33
35
  # Add dataset methods and update the conversion proces for dates and timestamps.
34
36
  def self.extended(db)
@@ -86,27 +88,18 @@ module Sequel
86
88
  if value.is_a?(String) && (m = /((?:[-+]\d\d:\d\d)(:\d\d)?)?( BC)?\z/.match(value)) && (m[2] || m[3])
87
89
  if m[3]
88
90
  value = value.sub(' BC', '').sub(' ', ' BC ')
89
- conv = defined?(JRUBY_VERSION) && JRUBY_VERSION == '9.2.0.0'
90
91
  end
91
- if m[2] || conv
92
- dt = DateTime.parse(value)
93
- if conv
94
- # :nocov:
95
- if Sequel.datetime_class == DateTime
96
- dt >>= 12
97
- else
98
- dt >>= 24
99
- end
100
- # :nocov:
101
- end
102
- unless Sequel.datetime_class == DateTime
103
- dt = dt.to_time
104
- if conv && (timezone == nil || timezone == :local) && !m[1]
105
- # :nocov:
106
- dt = Sequel.send(:convert_input_timestamp, dt.strftime("%F %T.%6N"), :local)
107
- # :nocov:
108
- end
92
+ if m[2]
93
+ dt = if Sequel.datetime_class == DateTime
94
+ DateTime.parse(value)
95
+ elsif TIME_CAN_PARSE_BC
96
+ Time.parse(value)
97
+ # :nocov:
98
+ else
99
+ DateTime.parse(value).to_time
100
+ # :nocov:
109
101
  end
102
+
110
103
  Sequel.convert_output_timestamp(dt, Sequel.application_timezone)
111
104
  else
112
105
  super(value)
@@ -223,10 +216,7 @@ module Sequel
223
216
  # Work around JRuby bug #4822 in Time#to_datetime for times before date of calendar reform
224
217
  def literal_time(time)
225
218
  if time < TIME_YEAR_1
226
- dt = DateTime.parse(super)
227
- # Work around JRuby bug #5191
228
- dt >>= 12 if JRUBY_VERSION == '9.2.0.0'
229
- literal_datetime(dt)
219
+ literal_datetime(DateTime.parse(super))
230
220
  else
231
221
  super
232
222
  end
@@ -236,7 +226,8 @@ module Sequel
236
226
  # Handle BC Time objects.
237
227
  def literal_time(time)
238
228
  if time < TIME_YEAR_1
239
- literal_datetime(time.to_datetime)
229
+ time = db.from_application_timestamp(time)
230
+ time.strftime("'#{sprintf('%04i', time.year.abs+1)}-%m-%d %H:%M:%S.%N#{format_timestamp_offset(*(time.utc_offset/RATIONAL_60).divmod(60))} BC'")
240
231
  else
241
232
  super
242
233
  end
@@ -296,7 +296,7 @@ module Sequel
296
296
 
297
297
  # Wrap argument in a PGArray if it is an array
298
298
  def wrap_input_array(obj)
299
- if obj.is_a?(Array) && defined?(Sequel.pg_array)
299
+ if obj.is_a?(Array) && Sequel.respond_to?(:pg_array)
300
300
  Sequel.pg_array(obj)
301
301
  else
302
302
  obj
@@ -305,7 +305,7 @@ module Sequel
305
305
 
306
306
  # Wrap argument in an Hstore if it is a hash
307
307
  def wrap_input_hash(obj)
308
- if obj.is_a?(Hash) && defined?(Sequel.hstore)
308
+ if obj.is_a?(Hash) && Sequel.respond_to?(:hstore)
309
309
  Sequel.hstore(obj)
310
310
  else
311
311
  obj
@@ -314,7 +314,7 @@ module Sequel
314
314
 
315
315
  # Wrap argument in a PGArrayOp if supported
316
316
  def wrap_output_array(obj)
317
- if defined?(Sequel.pg_array_op)
317
+ if Sequel.respond_to?(:pg_array_op)
318
318
  Sequel.pg_array_op(obj)
319
319
  else
320
320
  obj
@@ -49,13 +49,13 @@ module Sequel
49
49
  meth = IPAddr.method(:new)
50
50
  add_conversion_proc(869, meth)
51
51
  add_conversion_proc(650, meth)
52
- if defined?(register_array_type)
52
+ if respond_to?(:register_array_type)
53
53
  register_array_type('inet', :oid=>1041, :scalar_oid=>869)
54
54
  register_array_type('cidr', :oid=>651, :scalar_oid=>650)
55
55
  end
56
56
  end
57
57
 
58
- if defined?(register_array_type)
58
+ if respond_to?(:register_array_type)
59
59
  register_array_type('macaddr', :oid=>1040, :scalar_oid=>829)
60
60
  end
61
61
  @schema_type_classes[:ipaddr] = IPAddr
@@ -111,7 +111,7 @@ module Sequel
111
111
  when IPAddr
112
112
  value
113
113
  when String
114
- IPAddr.new(value)
114
+ IPAddr.new(typecast_check_string_length(value, 100))
115
115
  else
116
116
  raise Sequel::InvalidValue, "invalid value for inet/cidr: #{value.inspect}"
117
117
  end
@@ -144,7 +144,7 @@ module Sequel
144
144
  db.instance_exec do
145
145
  extend_datasets(IntervalDatasetMethods)
146
146
  add_conversion_proc(1186, Postgres::IntervalDatabaseMethods::PARSER)
147
- if defined?(register_array_type)
147
+ if respond_to?(:register_array_type)
148
148
  register_array_type('interval', :oid=>1187, :scalar_oid=>1186)
149
149
  end
150
150
  @schema_type_classes[:interval] = ActiveSupport::Duration
@@ -197,7 +197,7 @@ module Sequel
197
197
  when Numeric
198
198
  ActiveSupport::Duration.new(value, [[:seconds, value]])
199
199
  when String
200
- PARSER.call(value)
200
+ PARSER.call(typecast_check_string_length(value, 1000))
201
201
  else
202
202
  raise Sequel::InvalidValue, "invalid value for interval type: #{value.inspect}"
203
203
  end
@@ -227,7 +227,7 @@ module Sequel
227
227
  db.instance_exec do
228
228
  add_conversion_proc(114, method(:_db_parse_json))
229
229
  add_conversion_proc(3802, method(:_db_parse_jsonb))
230
- if defined?(register_array_type)
230
+ if respond_to?(:register_array_type)
231
231
  register_array_type('json', :oid=>199, :scalar_oid=>114)
232
232
  register_array_type('jsonb', :oid=>3807, :scalar_oid=>3802)
233
233
  end
@@ -123,15 +123,6 @@
123
123
  # c = Sequel.pg_jsonb_op(:c)
124
124
  # DB[:t].update(c['key1'] => 1.to_json, c['key2'] => "a".to_json)
125
125
  #
126
- # On PostgreSQL 15+, the <tt>IS [NOT] JSON</tt> operator is supported:
127
- #
128
- # j.is_json # j IS JSON
129
- # j.is_json(type: :object) # j IS JSON OBJECT
130
- # j.is_json(type: :object, unique: true) # j IS JSON OBJECT WITH UNIQUE
131
- # j.is_not_json # j IS NOT JSON
132
- # j.is_json(type: :array) # j IS NOT JSON ARRAY
133
- # j.is_json(unique: true) # j IS NOT JSON WITH UNIQUE
134
- #
135
126
  # If you are also using the pg_json extension, you should load it before
136
127
  # loading this extension. Doing so will allow you to use the #op method on
137
128
  # JSONHash, JSONHarray, JSONBHash, and JSONBArray, allowing you to perform json/jsonb operations
@@ -160,18 +151,6 @@ module Sequel
160
151
  GET_PATH = ["(".freeze, " #> ".freeze, ")".freeze].freeze
161
152
  GET_PATH_TEXT = ["(".freeze, " #>> ".freeze, ")".freeze].freeze
162
153
 
163
- IS_JSON = ["(".freeze, " IS JSON".freeze, "".freeze, ")".freeze].freeze
164
- IS_NOT_JSON = ["(".freeze, " IS NOT JSON".freeze, "".freeze, ")".freeze].freeze
165
- EMPTY_STRING = Sequel::LiteralString.new('').freeze
166
- WITH_UNIQUE = Sequel::LiteralString.new(' WITH UNIQUE').freeze
167
- IS_JSON_MAP = {
168
- nil => EMPTY_STRING,
169
- :value => Sequel::LiteralString.new(' VALUE').freeze,
170
- :scalar => Sequel::LiteralString.new(' SCALAR').freeze,
171
- :object => Sequel::LiteralString.new(' OBJECT').freeze,
172
- :array => Sequel::LiteralString.new(' ARRAY').freeze
173
- }.freeze
174
-
175
154
  # Get JSON array element or object field as json. If an array is given,
176
155
  # gets the object at the specified path.
177
156
  #
@@ -254,30 +233,6 @@ module Sequel
254
233
  end
255
234
  end
256
235
 
257
- # Return whether the json object can be parsed as JSON.
258
- #
259
- # Options:
260
- # :type :: Check whether the json object can be parsed as a specific type
261
- # of JSON (:value, :scalar, :object, :array).
262
- # :unique :: Check JSON objects for unique keys.
263
- #
264
- # json_op.is_json # json IS JSON
265
- # json_op.is_json(type: :object) # json IS JSON OBJECT
266
- # json_op.is_json(unique: true) # json IS JSON WITH UNIQUE
267
- def is_json(opts=OPTS)
268
- _is_json(IS_JSON, opts)
269
- end
270
-
271
- # Return whether the json object cannot be parsed as JSON. The opposite
272
- # of #is_json. See #is_json for options.
273
- #
274
- # json_op.is_not_json # json IS NOT JSON
275
- # json_op.is_not_json(type: :object) # json IS NOT JSON OBJECT
276
- # json_op.is_not_json(unique: true) # json IS NOT JSON WITH UNIQUE
277
- def is_not_json(opts=OPTS)
278
- _is_json(IS_NOT_JSON, opts)
279
- end
280
-
281
236
  # Returns a set of keys AS text in the json object.
282
237
  #
283
238
  # json_op.keys # json_object_keys(json)
@@ -331,13 +286,6 @@ module Sequel
331
286
 
332
287
  private
333
288
 
334
- # Internals of IS [NOT] JSON support
335
- def _is_json(lit_array, opts)
336
- raise Error, "invalid is_json :type option: #{opts[:type].inspect}" unless type = IS_JSON_MAP[opts[:type]]
337
- unique = opts[:unique] ? WITH_UNIQUE : EMPTY_STRING
338
- Sequel::SQL::BooleanExpression.new(:NOOP, Sequel::SQL::PlaceholderLiteralString.new(lit_array, [self, type, unique]))
339
- end
340
-
341
289
  # Return a placeholder literal with the given str and args, wrapped
342
290
  # in an JSONOp or JSONBOp, used by operators that return json or jsonb.
343
291
  def json_op(str, args)
@@ -358,7 +306,7 @@ module Sequel
358
306
  # Automatically wrap argument in a PGArray if it is a plain Array.
359
307
  # Requires that the pg_array extension has been loaded to work.
360
308
  def wrap_array(arg)
361
- if arg.instance_of?(Array) && defined?(Sequel.pg_array)
309
+ if arg.instance_of?(Array) && Sequel.respond_to?(:pg_array)
362
310
  Sequel.pg_array(arg)
363
311
  else
364
312
  arg
@@ -652,7 +600,7 @@ module Sequel
652
600
 
653
601
  # Wrap argument in a PGArray if it is an array
654
602
  def wrap_input_array(obj)
655
- if obj.is_a?(Array) && defined?(Sequel.pg_array)
603
+ if obj.is_a?(Array) && Sequel.respond_to?(:pg_array)
656
604
  Sequel.pg_array(obj)
657
605
  else
658
606
  obj
@@ -661,7 +609,7 @@ module Sequel
661
609
 
662
610
  # Wrap argument in a JSONBArray or JSONBHash if it is an array or hash.
663
611
  def wrap_input_jsonb(obj)
664
- if defined?(Sequel.pg_jsonb) && (obj.is_a?(Array) || obj.is_a?(Hash))
612
+ if Sequel.respond_to?(:pg_jsonb) && (obj.is_a?(Array) || obj.is_a?(Hash))
665
613
  Sequel.pg_jsonb(obj)
666
614
  else
667
615
  obj
@@ -124,7 +124,7 @@ module Sequel
124
124
  register_multirange_type('datemultirange', :range_oid=>3912, :oid=>4535)
125
125
  register_multirange_type('int8multirange', :range_oid=>3926, :oid=>4536)
126
126
 
127
- if defined?(register_array_type)
127
+ if respond_to?(:register_array_type)
128
128
  register_array_type('int4multirange', :oid=>6150, :scalar_oid=>4451, :scalar_typecast=>:int4multirange)
129
129
  register_array_type('nummultirange', :oid=>6151, :scalar_oid=>4532, :scalar_typecast=>:nummultirange)
130
130
  register_array_type('tsmultirange', :oid=>6152, :scalar_oid=>4533, :scalar_typecast=>:tsmultirange)
@@ -141,7 +141,7 @@ module Sequel
141
141
  add_conversion_proc(4533, PGMultiRange::Creator.new("tsmultirange", procs[3908]))
142
142
  add_conversion_proc(4534, PGMultiRange::Creator.new("tstzmultirange", procs[3910]))
143
143
 
144
- if defined?(register_array_type) && defined?(PGArray::Creator)
144
+ if respond_to?(:register_array_type) && defined?(PGArray::Creator)
145
145
  add_conversion_proc(6152, PGArray::Creator.new("tsmultirange", procs[4533]))
146
146
  add_conversion_proc(6153, PGArray::Creator.new("tstzmultirange", procs[4534]))
147
147
  end
@@ -139,7 +139,7 @@ module Sequel
139
139
  register_range_type('tstzrange', :oid=>3910, :subtype_oid=>1184)
140
140
  register_range_type('daterange', :oid=>3912, :subtype_oid=>1082)
141
141
  register_range_type('int8range', :oid=>3926, :subtype_oid=>20)
142
- if defined?(register_array_type)
142
+ if respond_to?(:register_array_type)
143
143
  register_array_type('int4range', :oid=>3905, :scalar_oid=>3904, :scalar_typecast=>:int4range)
144
144
  register_array_type('numrange', :oid=>3907, :scalar_oid=>3906, :scalar_typecast=>:numrange)
145
145
  register_array_type('tsrange', :oid=>3909, :scalar_oid=>3908, :scalar_typecast=>:tsrange)
@@ -154,7 +154,7 @@ module Sequel
154
154
  procs = conversion_procs
155
155
  add_conversion_proc(3908, Parser.new("tsrange", procs[1114]))
156
156
  add_conversion_proc(3910, Parser.new("tstzrange", procs[1184]))
157
- if defined?(register_array_type) && defined?(PGArray::Creator)
157
+ if respond_to?(:register_array_type) && defined?(PGArray::Creator)
158
158
  add_conversion_proc(3909, PGArray::Creator.new("tsrange", procs[3908]))
159
159
  add_conversion_proc(3911, PGArray::Creator.new("tstzrange", procs[3910]))
160
160
  end
@@ -282,7 +282,7 @@ module Sequel
282
282
  when Range
283
283
  PGRange.from_range(value, parser.db_type)
284
284
  when String
285
- parser.call(value)
285
+ parser.call(typecast_check_string_length(value, 100))
286
286
  else
287
287
  raise Sequel::InvalidValue, "invalid value for range type: #{value.inspect}"
288
288
  end
@@ -375,7 +375,7 @@ module Sequel
375
375
  @row_schema_types = {}
376
376
  extend(@row_type_method_module = Module.new)
377
377
  add_conversion_proc(2249, PGRow::Parser.new(:converter=>PGRow::ArrayRow))
378
- if defined?(register_array_type)
378
+ if respond_to?(:register_array_type)
379
379
  register_array_type('record', :oid=>2287, :scalar_oid=>2249)
380
380
  end
381
381
  end
@@ -464,7 +464,7 @@ module Sequel
464
464
  parser = Parser.new(parser_opts)
465
465
  add_conversion_proc(parser.oid, parser)
466
466
 
467
- if defined?(register_array_type) && array_oid && array_oid > 0
467
+ if respond_to?(:register_array_type) && array_oid && array_oid > 0
468
468
  array_type_name = if type_schema
469
469
  "#{type_schema}.#{type_name}"
470
470
  else
@@ -115,13 +115,13 @@ SQL
115
115
  # :before_thread_exit :: An object that responds to +call+ that is called before the
116
116
  # the created thread exits.
117
117
  def listen_for_static_cache_updates(models, opts=OPTS)
118
- raise Error, "this database object does not respond to listen, use the postgres adapter with the pg driver" unless defined?(listen)
118
+ raise Error, "this database object does not respond to listen, use the postgres adapter with the pg driver" unless respond_to?(:listen)
119
119
  models = [models] unless models.is_a?(Array)
120
120
  raise Error, "array of models to listen for changes cannot be empty" if models.empty?
121
121
 
122
122
  oid_map = {}
123
123
  models.each do |model|
124
- raise Error, "#{model.inspect} does not use the static_cache plugin" unless defined?(model.load_cache)
124
+ raise Error, "#{model.inspect} does not use the static_cache plugin" unless model.respond_to?(:load_cache)
125
125
  oid_map[get(regclass_oid(model.dataset.first_source_table))] = model
126
126
  end
127
127
 
@@ -3016,7 +3016,7 @@ module Sequel
3016
3016
  def complex_expression_sql_append(sql, op, args)
3017
3017
  r = args[1]
3018
3018
  if (((op == :'=' || op == :'!=') && r.is_a?(Sequel::Model)) ||
3019
- (multiple = ((op == :IN || op == :'NOT IN') && ((is_ds = r.is_a?(Sequel::Dataset)) || (defined?(r.all?) && r.all?{|x| x.is_a?(Sequel::Model)})))))
3019
+ (multiple = ((op == :IN || op == :'NOT IN') && ((is_ds = r.is_a?(Sequel::Dataset)) || (r.respond_to?(:all?) && r.all?{|x| x.is_a?(Sequel::Model)})))))
3020
3020
  l = args[0]
3021
3021
  if ar = model.association_reflections[l]
3022
3022
  raise Error, "filtering by associations is not allowed for #{ar.inspect}" if ar[:allow_filtering_by] == false
@@ -3024,7 +3024,7 @@ module Sequel
3024
3024
  if multiple
3025
3025
  klass = ar.associated_class
3026
3026
  if is_ds
3027
- if defined?(r.model)
3027
+ if r.respond_to?(:model)
3028
3028
  unless r.model <= klass
3029
3029
  # A dataset for a different model class, could be a valid regular query
3030
3030
  return super
@@ -3356,10 +3356,10 @@ module Sequel
3356
3356
  assoc_table_alias = ds.unused_table_alias(alias_base)
3357
3357
  loader = r[:eager_grapher]
3358
3358
  if !associations.empty?
3359
- if defined?(associations.first.call)
3359
+ if associations.first.respond_to?(:call)
3360
3360
  callback = associations.first
3361
3361
  associations = {}
3362
- elsif associations.length == 1 && (assocs = associations.first).is_a?(Hash) && assocs.length == 1 && (pr_assoc = assocs.to_a.first) && defined?(pr_assoc.first.call)
3362
+ elsif associations.length == 1 && (assocs = associations.first).is_a?(Hash) && assocs.length == 1 && (pr_assoc = assocs.to_a.first) && pr_assoc.first.respond_to?(:call)
3363
3363
  callback, assoc = pr_assoc
3364
3364
  associations = assoc.is_a?(Array) ? assoc : [assoc]
3365
3365
  end
@@ -3601,10 +3601,10 @@ module Sequel
3601
3601
  end
3602
3602
 
3603
3603
  associations = eager_assoc[r[:name]]
3604
- if defined?(associations.call)
3604
+ if associations.respond_to?(:call)
3605
3605
  eager_block = associations
3606
3606
  associations = OPTS
3607
- elsif associations.is_a?(Hash) && associations.length == 1 && (pr_assoc = associations.to_a.first) && defined?(pr_assoc.first.call)
3607
+ elsif associations.is_a?(Hash) && associations.length == 1 && (pr_assoc = associations.to_a.first) && pr_assoc.first.respond_to?(:call)
3608
3608
  eager_block, associations = pr_assoc
3609
3609
  end
3610
3610
 
@@ -492,13 +492,13 @@ module Sequel
492
492
  def plugin(plugin, *args, &block)
493
493
  m = plugin.is_a?(Module) ? plugin : plugin_module(plugin)
494
494
 
495
- if !defined?(m.apply) && !defined?(m.configure) && (!args.empty? || block)
495
+ if !m.respond_to?(:apply) && !m.respond_to?(:configure) && (!args.empty? || block)
496
496
  Deprecation.deprecate("Plugin #{plugin} accepts no arguments or block, and passing arguments/block to it", "Remove arguments and block when loading the plugin")
497
497
  end
498
498
 
499
499
  unless @plugins.include?(m)
500
500
  @plugins << m
501
- m.apply(self, *args, &block) if defined?(m.apply)
501
+ m.apply(self, *args, &block) if m.respond_to?(:apply)
502
502
  extend(m::ClassMethods) if m.const_defined?(:ClassMethods, false)
503
503
  include(m::InstanceMethods) if m.const_defined?(:InstanceMethods, false)
504
504
  if m.const_defined?(:DatasetMethods, false)
@@ -506,7 +506,7 @@ module Sequel
506
506
  end
507
507
  end
508
508
 
509
- m.configure(self, *args, &block) if defined?(m.configure)
509
+ m.configure(self, *args, &block) if m.respond_to?(:configure)
510
510
  end
511
511
  # :nocov:
512
512
  ruby2_keywords(:plugin) if respond_to?(:ruby2_keywords, true)
@@ -44,7 +44,7 @@ module Sequel
44
44
  errors = @model.errors
45
45
  end
46
46
 
47
- if defined?(errors.full_messages)
47
+ if errors.respond_to?(:full_messages)
48
48
  @errors = errors
49
49
  super(errors.full_messages.join(', '))
50
50
  else
@@ -99,7 +99,7 @@ module Sequel
99
99
  # Convert the given string to CamelCase. Will also convert '/' to '::' which is useful for converting paths to namespaces.
100
100
  def camelize(s)
101
101
  s = s.to_s
102
- return s.camelize if defined?(s.camelize)
102
+ return s.camelize if s.respond_to?(:camelize)
103
103
  s = s.gsub(/\/(.?)/){|x| "::#{x[-1..-1].upcase unless x == '/'}"}.gsub(/(^|_)(.)/){|x| x[-1..-1].upcase}
104
104
  s
105
105
  end
@@ -109,7 +109,7 @@ module Sequel
109
109
  # or is not initialized.
110
110
  def constantize(s)
111
111
  s = s.to_s
112
- return s.constantize if defined?(s.constantize)
112
+ return s.constantize if s.respond_to?(:constantize)
113
113
  raise(NameError, "#{s.inspect} is not a valid constant name!") unless m = /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/.match(s)
114
114
  Object.module_eval("::#{m[1]}", __FILE__, __LINE__)
115
115
  end
@@ -117,14 +117,14 @@ module Sequel
117
117
  # Removes the module part from the expression in the string
118
118
  def demodulize(s)
119
119
  s = s.to_s
120
- return s.demodulize if defined?(s.demodulize)
120
+ return s.demodulize if s.respond_to?(:demodulize)
121
121
  s.gsub(/^.*::/, '')
122
122
  end
123
123
 
124
124
  # Returns the plural form of the word in the string.
125
125
  def pluralize(s)
126
126
  s = s.to_s
127
- return s.pluralize if defined?(s.pluralize)
127
+ return s.pluralize if s.respond_to?(:pluralize)
128
128
  result = s.dup
129
129
  Inflections.plurals.each{|(rule, replacement)| break if result.gsub!(rule, replacement)} unless Inflections.uncountables.include?(s.downcase)
130
130
  result
@@ -133,7 +133,7 @@ module Sequel
133
133
  # The reverse of pluralize, returns the singular form of a word in a string.
134
134
  def singularize(s)
135
135
  s = s.to_s
136
- return s.singularize if defined?(s.singularize)
136
+ return s.singularize if s.respond_to?(:singularize)
137
137
  result = s.dup
138
138
  Inflections.singulars.each{|(rule, replacement)| break if result.gsub!(rule, replacement)} unless Inflections.uncountables.include?(s.downcase)
139
139
  result
@@ -143,7 +143,7 @@ module Sequel
143
143
  # Also changes '::' to '/' to convert namespaces to paths.
144
144
  def underscore(s)
145
145
  s = s.to_s
146
- return s.underscore if defined?(s.underscore)
146
+ return s.underscore if s.respond_to?(:underscore)
147
147
  s.gsub('::', '/').gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').
148
148
  gsub(/([a-z\d])([A-Z])/, '\1_\2').tr('-', '_').downcase
149
149
  end
@@ -252,7 +252,7 @@ module Sequel
252
252
 
253
253
  unless skip.include?(:unique)
254
254
  unique_opts = Hash[opts[:unique]]
255
- if defined?(model.sti_dataset)
255
+ if model.respond_to?(:sti_dataset)
256
256
  unique_opts[:dataset] = model.sti_dataset
257
257
  end
258
258
  model.auto_validate_unique_columns.each{|cols| validates_unique(cols, unique_opts)}
@@ -117,7 +117,7 @@ module Sequel
117
117
  def [](k)
118
118
  if new? && !values.has_key?(k)
119
119
  v = model.default_values.fetch(k){return}
120
- v = v.call if defined?(v.call)
120
+ v = v.call if v.respond_to?(:call)
121
121
  values[k] = v if model.cache_default_values?
122
122
  v
123
123
  else
@@ -203,7 +203,7 @@ module Sequel
203
203
  get_column_value(column)
204
204
  end
205
205
 
206
- initial_values[column] = if value && value != true && defined?(value.clone)
206
+ initial_values[column] = if value && value != true && value.respond_to?(:clone)
207
207
  begin
208
208
  value.clone
209
209
  rescue TypeError
@@ -36,7 +36,7 @@ module Sequel
36
36
  module InsertConflict
37
37
  def self.configure(model)
38
38
  model.instance_exec do
39
- if @dataset && !defined?(@dataset.insert_conflict)
39
+ if @dataset && !@dataset.respond_to?(:insert_conflict)
40
40
  raise Error, "#{self}'s dataset does not support insert_conflict"
41
41
  end
42
42
  end
@@ -152,7 +152,7 @@ module Sequel
152
152
  if obj.is_a?(Array)
153
153
  obj.map{|x| object_to_json_data(x, *args, &block)}
154
154
  else
155
- if defined?(obj.to_json_data)
155
+ if obj.respond_to?(:to_json_data)
156
156
  obj.to_json_data(*args, &block)
157
157
  else
158
158
  begin
@@ -259,7 +259,7 @@ module Sequel
259
259
  # specific :fields if configured.
260
260
  def nested_attributes_set_attributes(meta, obj, attributes)
261
261
  if fields = meta[:fields]
262
- fields = fields.call(obj) if defined?(fields.call)
262
+ fields = fields.call(obj) if fields.respond_to?(:call)
263
263
  obj.set_fields(attributes, fields, :missing=>:skip)
264
264
  else
265
265
  obj.set(attributes)
@@ -159,7 +159,7 @@ module Sequel
159
159
 
160
160
  case @dataset.first_source_table
161
161
  when Symbol, String, SQL::Identifier, SQL::QualifiedIdentifier
162
- convert_errors = defined?(db.error_info)
162
+ convert_errors = db.respond_to?(:error_info)
163
163
  end
164
164
 
165
165
  unless convert_errors
@@ -162,7 +162,7 @@ module Sequel
162
162
  if !cc.include?(column) && (new? || get_column_value(column) != v)
163
163
  cc << column
164
164
 
165
- will_change_column(column) if defined?(will_change_column)
165
+ will_change_column(column) if respond_to?(:will_change_column)
166
166
  end
167
167
 
168
168
  deserialized_values[column] = v
@@ -91,7 +91,7 @@ module Sequel
91
91
  # +many_to_many+ association, make sure the associated object is created on the
92
92
  # current object's shard, unless the passed object already has an assigned shard.
93
93
  def ensure_associated_primary_key(opts, o, *args)
94
- o.set_server?(@server) if defined?(o.set_server?)
94
+ o.set_server?(@server) if o.respond_to?(:set_server?)
95
95
  super
96
96
  end
97
97
 
@@ -35,7 +35,7 @@ module Sequel
35
35
  # class B < Sequel::Model; end
36
36
  # a # => [A, B]
37
37
  module Subclasses
38
- NEED_SUBCLASSES = !defined?(Object.subclasses) || Object.method(:subclasses).source_location
38
+ NEED_SUBCLASSES = !Object.respond_to?(:subclasses) || Object.method(:subclasses).source_location
39
39
  private_constant :NEED_SUBCLASSES
40
40
 
41
41
  # Initialize the subclasses instance variable for the model.
@@ -282,7 +282,7 @@ module Sequel
282
282
  o.errors.add(a, opts[:message] || opts[:wrong_length]) unless v && v.size == i
283
283
  end
284
284
  if w = opts[:within]
285
- o.errors.add(a, opts[:message] || opts[:wrong_length]) unless v && w.public_send(defined?(w.cover?) ? :cover? : :include?, v.size)
285
+ o.errors.add(a, opts[:message] || opts[:wrong_length]) unless v && w.public_send(w.respond_to?(:cover?) ? :cover? : :include?, v.size)
286
286
  end
287
287
  end
288
288
  end
@@ -337,14 +337,14 @@ module Sequel
337
337
  def validates_inclusion_of(*atts)
338
338
  opts = extract_options!(atts)
339
339
  n = opts[:in]
340
- unless n && (defined?(n.cover?) || defined?(n.include?))
340
+ unless n && (n.respond_to?(:cover?) || n.respond_to?(:include?))
341
341
  raise ArgumentError, "The :in parameter is required, and must respond to cover? or include?"
342
342
  end
343
343
  opts[:message] ||= "is not in range or set: #{n.inspect}"
344
344
  reflect_validation(:inclusion, opts, atts)
345
345
  atts << opts
346
346
  validates_each(*atts) do |o, a, v|
347
- o.errors.add(a, opts[:message]) unless n.public_send(defined?(n.cover?) ? :cover? : :include?, v)
347
+ o.errors.add(a, opts[:message]) unless n.public_send(n.respond_to?(:cover?) ? :cover? : :include?, v)
348
348
  end
349
349
  end
350
350
 
@@ -107,7 +107,7 @@ module Sequel
107
107
 
108
108
  # Check attribute value(s) is included in the given set.
109
109
  def validates_includes(set, atts, opts=OPTS)
110
- validatable_attributes_for_type(:includes, atts, opts){|a,v,m| validation_error_message(m, set) unless set.public_send(defined?(set.cover?) ? :cover? : :include?, v)}
110
+ validatable_attributes_for_type(:includes, atts, opts){|a,v,m| validation_error_message(m, set) unless set.public_send(set.respond_to?(:cover?) ? :cover? : :include?, v)}
111
111
  end
112
112
 
113
113
  # Check attribute value(s) string representation is a valid integer.
data/lib/sequel/sql.rb CHANGED
@@ -1347,7 +1347,7 @@ module Sequel
1347
1347
  # underlying callable only accepts a single argument, call it
1348
1348
  # with the given dataset.
1349
1349
  def call(ds)
1350
- if defined?(@callable.arity) && @callable.arity == 1
1350
+ if @callable.respond_to?(:arity) && @callable.arity == 1
1351
1351
  @callable.call(ds)
1352
1352
  else
1353
1353
  @callable.call
@@ -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 = 60
9
+ MINOR = 61
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,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sequel
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.60.0
4
+ version: 5.61.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Evans
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-09-01 00:00:00.000000000 Z
11
+ date: 2022-10-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -192,6 +192,7 @@ extra_rdoc_files:
192
192
  - doc/release_notes/5.59.0.txt
193
193
  - doc/release_notes/5.6.0.txt
194
194
  - doc/release_notes/5.60.0.txt
195
+ - doc/release_notes/5.61.0.txt
195
196
  - doc/release_notes/5.7.0.txt
196
197
  - doc/release_notes/5.8.0.txt
197
198
  - doc/release_notes/5.9.0.txt
@@ -280,6 +281,7 @@ files:
280
281
  - doc/release_notes/5.59.0.txt
281
282
  - doc/release_notes/5.6.0.txt
282
283
  - doc/release_notes/5.60.0.txt
284
+ - doc/release_notes/5.61.0.txt
283
285
  - doc/release_notes/5.7.0.txt
284
286
  - doc/release_notes/5.8.0.txt
285
287
  - doc/release_notes/5.9.0.txt