sequel 5.59.0 → 5.60.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +10 -0
  3. data/README.rdoc +1 -1
  4. data/bin/sequel +11 -3
  5. data/doc/release_notes/5.60.0.txt +22 -0
  6. data/lib/sequel/adapters/jdbc/sqlite.rb +1 -1
  7. data/lib/sequel/adapters/jdbc.rb +5 -5
  8. data/lib/sequel/adapters/mock.rb +1 -1
  9. data/lib/sequel/adapters/mysql.rb +3 -3
  10. data/lib/sequel/adapters/oracle.rb +1 -1
  11. data/lib/sequel/adapters/postgres.rb +46 -11
  12. data/lib/sequel/adapters/shared/mssql.rb +1 -1
  13. data/lib/sequel/adapters/shared/oracle.rb +1 -1
  14. data/lib/sequel/adapters/shared/postgres.rb +26 -14
  15. data/lib/sequel/adapters/shared/sqlite.rb +1 -1
  16. data/lib/sequel/adapters/sqlite.rb +1 -1
  17. data/lib/sequel/ast_transformer.rb +1 -1
  18. data/lib/sequel/database/misc.rb +2 -2
  19. data/lib/sequel/dataset/sql.rb +2 -2
  20. data/lib/sequel/extensions/date_arithmetic.rb +35 -7
  21. data/lib/sequel/extensions/duplicate_columns_handler.rb +1 -1
  22. data/lib/sequel/extensions/is_distinct_from.rb +3 -1
  23. data/lib/sequel/extensions/pg_array.rb +2 -2
  24. data/lib/sequel/extensions/pg_array_ops.rb +1 -1
  25. data/lib/sequel/extensions/pg_enum.rb +1 -1
  26. data/lib/sequel/extensions/pg_hstore_ops.rb +3 -3
  27. data/lib/sequel/extensions/pg_inet.rb +2 -2
  28. data/lib/sequel/extensions/pg_interval.rb +1 -1
  29. data/lib/sequel/extensions/pg_json.rb +1 -1
  30. data/lib/sequel/extensions/pg_json_ops.rb +3 -3
  31. data/lib/sequel/extensions/pg_multirange.rb +2 -2
  32. data/lib/sequel/extensions/pg_range.rb +2 -2
  33. data/lib/sequel/extensions/pg_row.rb +2 -2
  34. data/lib/sequel/extensions/pg_static_cache_updater.rb +2 -2
  35. data/lib/sequel/extensions/symbol_aref.rb +2 -0
  36. data/lib/sequel/model/associations.rb +6 -6
  37. data/lib/sequel/model/base.rb +3 -3
  38. data/lib/sequel/model/exceptions.rb +1 -1
  39. data/lib/sequel/model/inflections.rb +6 -6
  40. data/lib/sequel/plugins/auto_validations.rb +1 -1
  41. data/lib/sequel/plugins/defaults_setter.rb +1 -1
  42. data/lib/sequel/plugins/dirty.rb +1 -1
  43. data/lib/sequel/plugins/insert_conflict.rb +1 -1
  44. data/lib/sequel/plugins/json_serializer.rb +1 -1
  45. data/lib/sequel/plugins/nested_attributes.rb +1 -1
  46. data/lib/sequel/plugins/pg_auto_constraint_validations.rb +1 -1
  47. data/lib/sequel/plugins/serialization.rb +1 -1
  48. data/lib/sequel/plugins/sharding.rb +1 -1
  49. data/lib/sequel/plugins/sql_comments.rb +4 -4
  50. data/lib/sequel/plugins/subclasses.rb +1 -1
  51. data/lib/sequel/plugins/validation_class_methods.rb +3 -3
  52. data/lib/sequel/plugins/validation_helpers.rb +1 -1
  53. data/lib/sequel/sql.rb +1 -1
  54. data/lib/sequel/version.rb +1 -1
  55. metadata +4 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 47d7144911d61be13cc600fc3153c8e30eb384476ea7fb94ce61bd0f2f627c36
4
- data.tar.gz: fa763e2f24d5b6b26feecb405b5a43d8bbf30d2b727590e8fd98031640dfef2a
3
+ metadata.gz: 1bd9076a491b881827f095bbb1177974861448054cd73376ee76a42ed0f72ee5
4
+ data.tar.gz: e2e23f283d2d9f5b29df1510f5f39c8335cc47c37d0f92c848763cd437d4e668
5
5
  SHA512:
6
- metadata.gz: 3855f6fbb47f26bfd0e9570ed8b7e908815bc7de3752751b92708c3e88948719f62dafe26cc1ea83b598c73e1ee84e4dbf12f01437dd1b087eed68ca4281b33d
7
- data.tar.gz: 932fa5c97bc8dcf077a50961b2da7ecd59ae0c077409c2b0c3111d875fe468d5fbb4030f155faf17d3ba3ed0392e264d8e5ebaa11ad04db3ab98c209e2199440
6
+ metadata.gz: 309b37a25a51bc38c30c20276b7df1df4d21b6b14502b129fc363a0ac9bfc4897be03c21ec1d5b4b333eb6c1944491e4383406bb3f2cb96ba8dd1e98b513de42
7
+ data.tar.gz: 58adf4e309a3bd1d921f95d168a79830cce4526767b8ee9379ce69463327b10f0db4ded44a4a8e474cd0dd31036546b120f3e38a07c3057a5290933cffd3b77a
data/CHANGELOG CHANGED
@@ -1,3 +1,13 @@
1
+ === 5.60.0 (2022-09-01)
2
+
3
+ * Support arbitrary expressions for date_arithmetic interval values on PostgreSQL 9.4+ (jeremyevans)
4
+
5
+ * Support native IS DISTINCT FROM on SQLite 3.39+ instead of emulating support in the is_distinct_from extension (jeremyevans)
6
+
7
+ * Support HAVING without GROUP BY on SQLite 3.39+ (jeremyevans)
8
+
9
+ * Convert most respond_to? calls to equivalent defined? for better performance (jeremyevans)
10
+
1
11
  === 5.59.0 (2022-08-01)
2
12
 
3
13
  * Set :allow_eager association option to false for instance specific associations without eager loaders (jeremyevans)
data/README.rdoc CHANGED
@@ -416,7 +416,7 @@ As with +delete+, +update+ affects all rows in the dataset, so +where+ first,
416
416
 
417
417
  === Merging records
418
418
 
419
- Merging records using the SQL MERGE statment is done using <tt>merge*</tt> methods.
419
+ Merging records using the SQL MERGE statement is done using <tt>merge*</tt> methods.
420
420
  You use +merge_using+ to specify the merge source and join conditions.
421
421
  You can use +merge_insert+, +merge_delete+, and/or +merge_update+ to set the
422
422
  INSERT, DELETE, and UPDATE clauses for the merge. +merge_insert+ takes the same
data/bin/sequel CHANGED
@@ -194,7 +194,11 @@ begin
194
194
  TO_DB = connect_proc[db2]
195
195
  same_db = DB.database_type==TO_DB.database_type
196
196
  index_opts = {:same_db=>same_db}
197
+
198
+ # :nocov:
197
199
  index_opts[:index_names] = :namespace if !DB.global_index_namespace? && TO_DB.global_index_namespace?
200
+ # :nocov:
201
+
198
202
  if DB.database_type == :sqlite && !same_db
199
203
  # SQLite integer types allows 64-bit integers
200
204
  TO_DB.extension :integer64
@@ -212,18 +216,20 @@ begin
212
216
  puts "Begin copying data"
213
217
  DB.transaction do
214
218
  TO_DB.transaction do
219
+ all_status_lines = ENV['SEQUEL_BIN_STATUS_ALL_LINES']
220
+
215
221
  DB.tables.each do |table|
216
222
  puts "Begin copying records for table: #{table}"
217
223
  time = Time.now
218
224
  to_ds = TO_DB.from(table)
219
225
  j = 0
220
226
  DB.from(table).each do |record|
221
- if Time.now - time > 5
227
+ to_ds.insert(record)
228
+ j += 1
229
+ if Time.now - time > 5 || all_status_lines
222
230
  puts "Status: #{j} records copied"
223
231
  time = Time.now
224
232
  end
225
- to_ds.insert(record)
226
- j += 1
227
233
  end
228
234
  puts "Finished copying #{j} records for table: #{table}"
229
235
  end
@@ -260,8 +266,10 @@ if !ARGV.empty?
260
266
  ARGV.each{|v| load(v)}
261
267
  elsif !$stdin.isatty
262
268
  eval($stdin.read)
269
+ # :nocov:
263
270
  else
264
271
  require 'irb'
265
272
  puts "Your database is stored in DB..."
266
273
  IRB.start
267
274
  end
275
+ # :nocov:
@@ -0,0 +1,22 @@
1
+ = New Features
2
+
3
+ * The date_arithmetic extension now supports arbitrary expressions
4
+ as interval values on PostgreSQL 9.4+. Previously, only integers
5
+ were supported for the interval values.
6
+
7
+ = Other Improvements
8
+
9
+ * Most Kernel#respond_to? calls have been converted to equivalent
10
+ defined? calls for better performance. defined? is a keyword
11
+ and is about 50% faster for the same behavior.
12
+
13
+ * The is_distinct_from extension now supports the IS DISTINCT FROM
14
+ syntax natively on SQLite 3.39+, instead of emulating it.
15
+
16
+ * HAVING without GROUP BY is now supported on SQLite 3.39+.
17
+
18
+ * Coverage testing has been significantly expanded. Previously,
19
+ the core, model, plugin, and extension code had 100% line/branch
20
+ coverage. 100% line/branch coverage has been added for the
21
+ core extensions, bin/sequel, and the postgres adapter with the
22
+ pg driver.
@@ -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 exception.respond_to?(:resultCode)
128
+ exception.resultCode.code if defined?(exception.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 jdbc_module.respond_to?(:load_driver)
41
+ jdbc_module.load_driver if defined?(jdbc_module.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 exception.respond_to?(:cause)
399
+ while defined?(exception.cause)
400
400
  exception = exception.cause
401
- return exception.getSQLState if exception.respond_to?(:getSQLState)
401
+ return exception.getSQLState if defined?(exception.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 = exception.respond_to?(:cause) ? exception.cause : exception
419
- super || (cause.respond_to?(:getSQLState) && cause.getSQLState =~ /^08/)
418
+ cause = defined?(exception.cause) ? exception.cause : exception
419
+ super || (defined?(cause.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 mod.respond_to?(:mock_adapter_setup)
260
+ if defined?(mod.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 Mysql.respond_to?(:init)
75
+ if defined?(Mysql.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 conn.respond_to?(:more_results?)
189
+ if defined?(conn.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 conn.respond_to?(:more_results?)
210
+ if defined?(conn.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 exception.respond_to?(:code)
152
+ return super unless defined?(exception.code)
153
153
  case exception.code
154
154
  when 1400, 1407
155
155
  NotNullConstraintViolation
@@ -5,6 +5,7 @@ require_relative 'shared/postgres'
5
5
  begin
6
6
  require 'pg'
7
7
 
8
+ # :nocov:
8
9
  Sequel::Postgres::PGError = PG::Error if defined?(PG::Error)
9
10
  Sequel::Postgres::PGconn = PG::Connection if defined?(PG::Connection)
10
11
  Sequel::Postgres::PGresult = PG::Result if defined?(PG::Result)
@@ -14,14 +15,17 @@ begin
14
15
  raise LoadError unless defined?(PGconn::CONNECTION_OK)
15
16
  end
16
17
 
17
- Sequel::Postgres::USES_PG = true
18
18
  if defined?(PG::TypeMapByClass)
19
+ # :nocov:
19
20
  type_map = Sequel::Postgres::PG_QUERY_TYPE_MAP = PG::TypeMapByClass.new
20
21
  type_map[Integer] = PG::TextEncoder::Integer.new
21
22
  type_map[FalseClass] = type_map[TrueClass] = PG::TextEncoder::Boolean.new
22
23
  type_map[Float] = PG::TextEncoder::Float.new
23
24
  end
25
+
26
+ Sequel::Postgres::USES_PG = true
24
27
  rescue LoadError => e
28
+ # :nocov:
25
29
  begin
26
30
  require 'sequel/postgres-pr'
27
31
  rescue LoadError
@@ -32,16 +36,19 @@ rescue LoadError => e
32
36
  end
33
37
  end
34
38
  Sequel::Postgres::USES_PG = false
39
+ # :nocov:
35
40
  end
36
41
 
37
42
  module Sequel
38
43
  module Postgres
44
+ # :nocov:
39
45
  if USES_PG
40
46
  # Whether the given sequel_pg version integer is supported.
41
47
  def self.sequel_pg_version_supported?(version)
42
48
  version >= 10617
43
49
  end
44
50
  end
51
+ # :nocov:
45
52
 
46
53
  # PGconn subclass for connection specific methods used with the
47
54
  # pg or postgres-pr driver.
@@ -49,7 +56,9 @@ module Sequel
49
56
  # The underlying exception classes to reraise as disconnect errors
50
57
  # instead of regular database errors.
51
58
  DISCONNECT_ERROR_CLASSES = [IOError, Errno::EPIPE, Errno::ECONNRESET]
59
+ # :nocov:
52
60
  if defined?(::PG::ConnectionBad)
61
+ # :nocov:
53
62
  DISCONNECT_ERROR_CLASSES << ::PG::ConnectionBad
54
63
  end
55
64
  DISCONNECT_ERROR_CLASSES.freeze
@@ -75,6 +84,7 @@ module Sequel
75
84
  # are SQL strings.
76
85
  attr_reader :prepared_statements
77
86
 
87
+ # :nocov:
78
88
  unless public_method_defined?(:async_exec_params)
79
89
  alias async_exec_params async_exec
80
90
  end
@@ -117,6 +127,7 @@ module Sequel
117
127
  alias cmd_tuples cmdtuples
118
128
  end
119
129
  end
130
+ # :nocov:
120
131
 
121
132
  # Raise a Sequel::DatabaseDisconnectError if a one of the disconnect
122
133
  # error classes is raised, or a PGError is raised and the connection
@@ -149,7 +160,7 @@ module Sequel
149
160
  begin
150
161
  defined?(yield) ? yield(q) : q.cmd_tuples
151
162
  ensure
152
- q.clear if q && q.respond_to?(:clear)
163
+ q.clear if q && defined?(q.clear)
153
164
  end
154
165
  end
155
166
 
@@ -210,7 +221,9 @@ module Sequel
210
221
  :sslmode => opts[:sslmode],
211
222
  :sslrootcert => opts[:sslrootcert]
212
223
  }.delete_if { |key, value| blank_object?(value) }
224
+ # :nocov:
213
225
  connection_params.merge!(opts[:driver_options]) if opts[:driver_options]
226
+ # :nocov:
214
227
  conn = Adapter.connect(opts[:conn_str] || connection_params)
215
228
 
216
229
  conn.instance_variable_set(:@prepared_statements, {})
@@ -218,6 +231,13 @@ module Sequel
218
231
  if receiver = opts[:notice_receiver]
219
232
  conn.set_notice_receiver(&receiver)
220
233
  end
234
+
235
+ # :nocov:
236
+ if conn.respond_to?(:type_map_for_queries=) && defined?(PG_QUERY_TYPE_MAP)
237
+ # :nocov:
238
+ conn.type_map_for_queries = PG_QUERY_TYPE_MAP
239
+ end
240
+ # :nocov:
221
241
  else
222
242
  unless typecast_value_boolean(@opts.fetch(:force_standard_strings, true))
223
243
  raise Error, "Cannot create connection using postgres-pr unless force_standard_strings is set"
@@ -232,19 +252,19 @@ module Sequel
232
252
  opts[:password]
233
253
  )
234
254
  end
255
+ # :nocov:
235
256
 
236
257
  conn.instance_variable_set(:@db, self)
237
- if USES_PG && conn.respond_to?(:type_map_for_queries=) && defined?(PG_QUERY_TYPE_MAP)
238
- conn.type_map_for_queries = PG_QUERY_TYPE_MAP
239
- end
240
258
 
259
+ # :nocov:
241
260
  if encoding = opts[:encoding] || opts[:charset]
242
- if conn.respond_to?(:set_client_encoding)
261
+ if defined?(conn.set_client_encoding)
243
262
  conn.set_client_encoding(encoding)
244
263
  else
245
264
  conn.async_exec("set client_encoding to '#{encoding}'")
246
265
  end
247
266
  end
267
+ # :nocov:
248
268
 
249
269
  connection_configuration_sqls(opts).each{|sql| conn.execute(sql)}
250
270
  conn
@@ -271,7 +291,9 @@ module Sequel
271
291
  nil
272
292
  end
273
293
 
294
+ # :nocov:
274
295
  if USES_PG && Object.const_defined?(:PG) && ::PG.const_defined?(:Constants) && ::PG::Constants.const_defined?(:PG_DIAG_SCHEMA_NAME)
296
+ # :nocov:
275
297
  # Return a hash of information about the related PGError (or Sequel::DatabaseError that
276
298
  # wraps a PGError), with the following entries (any of which may be +nil+):
277
299
  #
@@ -322,7 +344,9 @@ module Sequel
322
344
  synchronize(opts[:server]){|conn| check_database_errors{_execute(conn, sql, opts, &block)}}
323
345
  end
324
346
 
347
+ # :nocov:
325
348
  if USES_PG
349
+ # :nocov:
326
350
  # +copy_table+ uses PostgreSQL's +COPY TO STDOUT+ SQL statement to return formatted
327
351
  # results directly to the caller. This method is only supported if pg is the
328
352
  # underlying ruby driver. This method should only be called if you want
@@ -468,12 +492,12 @@ module Sequel
468
492
  opts[:after_listen].call(conn) if opts[:after_listen]
469
493
  timeout = opts[:timeout]
470
494
  if timeout
471
- timeout_block = timeout.respond_to?(:call) ? timeout : proc{timeout}
495
+ timeout_block = defined?(timeout.call) ? timeout : proc{timeout}
472
496
  end
473
497
 
474
498
  if l = opts[:loop]
475
499
  raise Error, 'calling #listen with :loop requires a block' unless block
476
- loop_call = l.respond_to?(:call)
500
+ loop_call = defined?(l.call)
477
501
  catch(:stop) do
478
502
  while true
479
503
  t = timeout_block ? [timeout_block.call] : []
@@ -515,8 +539,10 @@ module Sequel
515
539
  def adapter_initialize
516
540
  @use_iso_date_format = typecast_value_boolean(@opts.fetch(:use_iso_date_format, true))
517
541
  initialize_postgres_adapter
542
+ # :nocov:
518
543
  add_conversion_proc(17, method(:unescape_bytea)) if USES_PG
519
544
  add_conversion_proc(1082, TYPE_TRANSLATOR_DATE) if @use_iso_date_format
545
+ # :nocov:
520
546
  self.convert_infinite_timestamps = @opts[:convert_infinite_timestamps]
521
547
  end
522
548
 
@@ -526,19 +552,22 @@ module Sequel
526
552
  rescue => e
527
553
  raise_error(e, :classes=>database_error_classes)
528
554
  end
529
-
530
555
  # Set the DateStyle to ISO if configured, for faster date parsing.
531
556
  def connection_configuration_sqls(opts=@opts)
532
557
  sqls = super
558
+ # :nocov:
533
559
  sqls << "SET DateStyle = 'ISO'" if @use_iso_date_format
560
+ # :nocov:
534
561
  sqls
535
562
  end
536
563
 
564
+ # :nocov:
537
565
  if USES_PG
538
566
  def unescape_bytea(s)
539
567
  ::Sequel::SQL::Blob.new(Adapter.unescape_bytea(s))
540
568
  end
541
569
  end
570
+ # :nocov:
542
571
 
543
572
  DATABASE_ERROR_CLASSES = [PGError].freeze
544
573
  def database_error_classes
@@ -552,7 +581,9 @@ module Sequel
552
581
  end
553
582
 
554
583
  def database_exception_sqlstate(exception, opts)
555
- if exception.respond_to?(:result) && (result = exception.result)
584
+ # :nocov:
585
+ if defined?(exception.result) && (result = exception.result)
586
+ # :nocov:
556
587
  result.error_field(PGresult::PG_DIAG_SQLSTATE)
557
588
  end
558
589
  end
@@ -594,7 +625,7 @@ module Sequel
594
625
  begin
595
626
  defined?(yield) ? yield(q) : q.cmd_tuples
596
627
  ensure
597
- q.clear if q && q.respond_to?(:clear)
628
+ q.clear if q && defined?(q.clear)
598
629
  end
599
630
  end
600
631
 
@@ -662,7 +693,9 @@ module Sequel
662
693
  clone(:where=>Sequel.lit(['CURRENT OF '], Sequel.identifier(cursor_name)))
663
694
  end
664
695
 
696
+ # :nocov:
665
697
  if USES_PG
698
+ # :nocov:
666
699
  PREPARED_ARG_PLACEHOLDER = LiteralString.new('$').freeze
667
700
 
668
701
  # PostgreSQL specific argument mapper used for mapping the named
@@ -809,6 +842,7 @@ module Sequel
809
842
  end
810
843
  end
811
844
 
845
+ # :nocov:
812
846
  if Sequel::Postgres::USES_PG && !ENV['NO_SEQUEL_PG']
813
847
  begin
814
848
  require 'sequel_pg'
@@ -820,3 +854,4 @@ if Sequel::Postgres::USES_PG && !ENV['NO_SEQUEL_PG']
820
854
  rescue LoadError
821
855
  end
822
856
  end
857
+ # :nocov:
@@ -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 conn.respond_to?(:server_version)
208
+ (conn.server_version rescue nil) if defined?(conn.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 conn.respond_to?(:server_version)
124
+ (conn.server_version rescue nil) if defined?(conn.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)
@@ -230,7 +230,6 @@ module Sequel
230
230
  module DatabaseMethods
231
231
  include UnmodifiedIdentifiers::DatabaseMethods
232
232
 
233
- PREPARED_ARG_PLACEHOLDER = LiteralString.new('$').freeze
234
233
  FOREIGN_KEY_LIST_ON_DELETE_MAP = {'a'=>:no_action, 'r'=>:restrict, 'c'=>:cascade, 'n'=>:set_null, 'd'=>:set_default}.freeze
235
234
  ON_COMMIT = {:drop => 'DROP', :delete_rows => 'DELETE ROWS', :preserve_rows => 'PRESERVE ROWS'}.freeze
236
235
  ON_COMMIT.each_value(&:freeze)
@@ -365,9 +364,10 @@ module Sequel
365
364
 
366
365
  table_oid = regclass_oid(table)
367
366
  im = input_identifier_meth
368
- unless column = im.call(opts[:column] || ((sch = schema(table).find{|_, sc| sc[:primary_key] && sc[:auto_increment]}) && sch[0]))
367
+ unless column = (opts[:column] || ((sch = schema(table).find{|_, sc| sc[:primary_key] && sc[:auto_increment]}) && sch[0]))
369
368
  raise Error, "could not determine column to convert from serial to identity automatically"
370
369
  end
370
+ column = im.call(column)
371
371
 
372
372
  column_num = ds.from(:pg_attribute).
373
373
  where(:attrelid=>table_oid, :attname=>column).
@@ -569,10 +569,12 @@ module Sequel
569
569
  if server_version >= 90500
570
570
  cpos = Sequel.expr{array_position(co[:conkey], ctable[:attnum])}
571
571
  rpos = Sequel.expr{array_position(co[:confkey], rtable[:attnum])}
572
+ # :nocov:
572
573
  else
573
574
  range = 0...32
574
575
  cpos = Sequel.expr{SQL::CaseExpression.new(range.map{|x| [SQL::Subscript.new(co[:conkey], [x]), x]}, 32, ctable[:attnum])}
575
576
  rpos = Sequel.expr{SQL::CaseExpression.new(range.map{|x| [SQL::Subscript.new(co[:confkey], [x]), x]}, 32, rtable[:attnum])}
577
+ # :nocov:
576
578
  end
577
579
 
578
580
  ds = metadata_dataset.
@@ -653,9 +655,11 @@ module Sequel
653
655
 
654
656
  if server_version >= 90500
655
657
  order = [Sequel[:indc][:relname], Sequel.function(:array_position, Sequel[:ind][:indkey], Sequel[:att][:attnum])]
658
+ # :nocov:
656
659
  else
657
660
  range = 0...32
658
661
  order = [Sequel[:indc][:relname], SQL::CaseExpression.new(range.map{|x| [SQL::Subscript.new(Sequel[:ind][:indkey], [x]), x]}, 32, Sequel[:att][:attnum])]
662
+ # :nocov:
659
663
  end
660
664
 
661
665
  attnums = SQL::Function.new(:ANY, Sequel[:ind][:indkey])
@@ -676,8 +680,10 @@ module Sequel
676
680
  select{[indc[:relname].as(:name), ind[:indisunique].as(:unique), att[:attname].as(:column), con[:condeferrable].as(:deferrable)]}
677
681
 
678
682
  ds = ds.where(:indpred=>nil) unless opts[:include_partial]
683
+ # :nocov:
679
684
  ds = ds.where(:indisready=>true) if server_version >= 80300
680
685
  ds = ds.where(:indislive=>true) if server_version >= 90300
686
+ # :nocov:
681
687
 
682
688
  indexes = {}
683
689
  ds.each do |r|
@@ -758,10 +764,12 @@ module Sequel
758
764
  seq_ds = metadata_dataset.from(:pg_sequence).where(:seqrelid=>regclass_oid(LiteralString.new(seq)))
759
765
  increment_by = :seqincrement
760
766
  min_value = :seqmin
767
+ # :nocov:
761
768
  else
762
769
  seq_ds = metadata_dataset.from(LiteralString.new(seq))
763
770
  increment_by = :increment_by
764
771
  min_value = :min_value
772
+ # :nocov:
765
773
  end
766
774
 
767
775
  get{setval(seq, db[table].select(coalesce(max(pk)+seq_ds.select(increment_by), seq_ds.select(min_value))), false)}
@@ -774,7 +782,9 @@ module Sequel
774
782
  # PostgreSQL uses SERIAL psuedo-type instead of AUTOINCREMENT for
775
783
  # managing incrementing primary keys.
776
784
  def serial_primary_key_options
785
+ # :nocov:
777
786
  auto_increment_key = server_version >= 100002 ? :identity : :serial
787
+ # :nocov:
778
788
  {:primary_key => true, auto_increment_key => true, :type=>Integer}
779
789
  end
780
790
 
@@ -1152,7 +1162,7 @@ module Sequel
1152
1162
  when :hash
1153
1163
  mod, remainder = generator.hash_values
1154
1164
  sql << " FOR VALUES WITH (MODULUS #{literal(mod)}, REMAINDER #{literal(remainder)})"
1155
- when :default
1165
+ else # when :default
1156
1166
  sql << " DEFAULT"
1157
1167
  end
1158
1168
 
@@ -1356,11 +1366,6 @@ module Sequel
1356
1366
  end
1357
1367
  end
1358
1368
 
1359
- # Use a dollar sign instead of question mark for the argument placeholder.
1360
- def prepared_arg_placeholder
1361
- PREPARED_ARG_PLACEHOLDER
1362
- end
1363
-
1364
1369
  # Return an expression the oid for the table expr. Used by the metadata parsing
1365
1370
  # code to disambiguate unqualified tables.
1366
1371
  def regclass_oid(expr, opts=OPTS)
@@ -1434,10 +1439,14 @@ module Sequel
1434
1439
  where{{pg_class[:oid]=>oid}}.
1435
1440
  order{pg_attribute[:attnum]}
1436
1441
 
1442
+ # :nocov:
1437
1443
  if server_version > 100000
1444
+ # :nocov:
1438
1445
  ds = ds.select_append{pg_attribute[:attidentity]}
1439
1446
 
1447
+ # :nocov:
1440
1448
  if server_version > 120000
1449
+ # :nocov:
1441
1450
  ds = ds.select_append{Sequel.~(pg_attribute[:attgenerated]=>'').as(:generated)}
1442
1451
  end
1443
1452
  end
@@ -1525,7 +1534,9 @@ module Sequel
1525
1534
 
1526
1535
  # PostgreSQL 9.4+ supports views with check option.
1527
1536
  def view_with_check_option_support
1537
+ # :nocov:
1528
1538
  :local if server_version >= 90400
1539
+ # :nocov:
1529
1540
  end
1530
1541
  end
1531
1542
 
@@ -1921,6 +1932,8 @@ module Sequel
1921
1932
  server_version >= 90000
1922
1933
  when :groups, :exclude
1923
1934
  server_version >= 110000
1935
+ else
1936
+ false
1924
1937
  end
1925
1938
  end
1926
1939
 
@@ -2067,12 +2080,11 @@ module Sequel
2067
2080
 
2068
2081
  # Return the primary key to use for RETURNING in an INSERT statement
2069
2082
  def insert_pk
2070
- if (f = opts[:from]) && !f.empty?
2071
- case t = f.first
2072
- when Symbol, String, SQL::Identifier, SQL::QualifiedIdentifier
2073
- if pk = db.primary_key(t)
2074
- Sequel::SQL::Identifier.new(pk)
2075
- end
2083
+ (f = opts[:from]) && !f.empty? && (t = f.first)
2084
+ case t
2085
+ when Symbol, String, SQL::Identifier, SQL::QualifiedIdentifier
2086
+ if pk = db.primary_key(t)
2087
+ Sequel::SQL::Identifier.new(pk)
2076
2088
  end
2077
2089
  end
2078
2090
  end
@@ -663,7 +663,7 @@ module Sequel
663
663
 
664
664
  # HAVING requires GROUP BY on SQLite
665
665
  def having(*cond)
666
- raise(InvalidOperation, "Can only specify a HAVING clause on a grouped dataset") unless @opts[:group]
666
+ raise(InvalidOperation, "Can only specify a HAVING clause on a grouped dataset") if !@opts[:group] && db.sqlite_version < 33900
667
667
  super
668
668
  end
669
669
 
@@ -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 exception.respond_to?(:code)
308
+ exception.code if defined?(exception.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 o.respond_to?(:sequel_ast_transform)
84
+ if defined?(o.sequel_ast_transform)
85
85
  o.sequel_ast_transform(method(:v))
86
86
  else
87
87
  o
@@ -350,7 +350,7 @@ module Sequel
350
350
  # strings with all whitespace, and ones that respond
351
351
  # true to empty?
352
352
  def blank_object?(obj)
353
- return obj.blank? if obj.respond_to?(:blank?)
353
+ return obj.blank? if defined?(obj.blank?)
354
354
  case obj
355
355
  when NilClass, FalseClass
356
356
  true
@@ -359,7 +359,7 @@ module Sequel
359
359
  when String
360
360
  obj.strip.empty?
361
361
  else
362
- obj.respond_to?(:empty?) ? obj.empty? : false
362
+ defined?(obj.empty?) ? obj.empty? : false
363
363
  end
364
364
  end
365
365
 
@@ -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 v.respond_to?(:sql_literal_append)
1401
+ if defined?(v.sql_literal_append)
1402
1402
  v.sql_literal_append(self, sql)
1403
- elsif v.respond_to?(:sql_literal)
1403
+ elsif defined?(v.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"