sequel 5.59.0 → 5.60.1
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.
- checksums.yaml +4 -4
- data/CHANGELOG +14 -0
- data/README.rdoc +1 -1
- data/bin/sequel +11 -3
- data/doc/release_notes/5.60.0.txt +22 -0
- data/lib/sequel/adapters/postgres.rb +40 -5
- data/lib/sequel/adapters/shared/postgres.rb +26 -14
- data/lib/sequel/adapters/shared/sqlite.rb +1 -1
- data/lib/sequel/extensions/date_arithmetic.rb +35 -7
- data/lib/sequel/extensions/is_distinct_from.rb +3 -1
- data/lib/sequel/extensions/symbol_aref.rb +2 -0
- data/lib/sequel/plugins/sql_comments.rb +4 -4
- data/lib/sequel/version.rb +2 -2
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: cd8695696d6b55edf6337870f3ff172aeb6fe2ef9ba4bbc23daae0af26908649
|
|
4
|
+
data.tar.gz: 2483bbb3549adbcb9f179165119051b7bb234d6e714e4afa116c0ffddf379dc6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0527cba1fcc06d8001cbd55473b3af5c23a9f5c004113fc24aa6f9e029c5ed2cf4f938bf184d79922164cdc3ea502d12860d46d64237bdbd306bf5ce50f59ffa
|
|
7
|
+
data.tar.gz: e13c17553592773e70c0e9a6753438444a5245f3cd0664c6c5a6c0a08a271d1d92180b110c7b7e5981f7ca6dc2b18d90da3feeb05a14ae863fcfd99d5673650e
|
data/CHANGELOG
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
=== 5.60.1 (2022-09-02)
|
|
2
|
+
|
|
3
|
+
* Revert conversion of respond_to? to defined?, as it breaks with unused refinements on Ruby 2 (jeremyevans) (#1919)
|
|
4
|
+
|
|
5
|
+
=== 5.60.0 (2022-09-01)
|
|
6
|
+
|
|
7
|
+
* Support arbitrary expressions for date_arithmetic interval values on PostgreSQL 9.4+ (jeremyevans)
|
|
8
|
+
|
|
9
|
+
* Support native IS DISTINCT FROM on SQLite 3.39+ instead of emulating support in the is_distinct_from extension (jeremyevans)
|
|
10
|
+
|
|
11
|
+
* Support HAVING without GROUP BY on SQLite 3.39+ (jeremyevans)
|
|
12
|
+
|
|
13
|
+
* Convert most respond_to? calls to equivalent defined? for better performance (jeremyevans)
|
|
14
|
+
|
|
1
15
|
=== 5.59.0 (2022-08-01)
|
|
2
16
|
|
|
3
17
|
* 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
|
|
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
|
-
|
|
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.
|
|
@@ -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
|
|
@@ -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,12 +252,11 @@ 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
261
|
if conn.respond_to?(:set_client_encoding)
|
|
243
262
|
conn.set_client_encoding(encoding)
|
|
@@ -245,6 +264,7 @@ module Sequel
|
|
|
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
|
|
@@ -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)
|
|
584
|
+
# :nocov:
|
|
555
585
|
if exception.respond_to?(:result) && (result = exception.result)
|
|
586
|
+
# :nocov:
|
|
556
587
|
result.error_field(PGresult::PG_DIAG_SQLSTATE)
|
|
557
588
|
end
|
|
558
589
|
end
|
|
@@ -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:
|
|
@@ -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 =
|
|
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
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
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")
|
|
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
|
|
|
@@ -32,6 +32,10 @@
|
|
|
32
32
|
#
|
|
33
33
|
# DB[:table].select(add.as(:d)).where(sub > Sequel::CURRENT_TIMESTAMP)
|
|
34
34
|
#
|
|
35
|
+
# On most databases, the values you provide for years/months/days/etc. must
|
|
36
|
+
# be numeric values and not arbitrary SQL expressions. However, on PostgreSQL
|
|
37
|
+
# 9.4+, use of arbitrary SQL expressions is supported.
|
|
38
|
+
#
|
|
35
39
|
# Related module: Sequel::SQL::DateAdd
|
|
36
40
|
|
|
37
41
|
#
|
|
@@ -54,7 +58,16 @@ module Sequel
|
|
|
54
58
|
interval = interval.parts
|
|
55
59
|
end
|
|
56
60
|
parts = {}
|
|
57
|
-
interval.each
|
|
61
|
+
interval.each do |k,v|
|
|
62
|
+
case v
|
|
63
|
+
when nil
|
|
64
|
+
# ignore
|
|
65
|
+
when Numeric
|
|
66
|
+
parts[k] = -v
|
|
67
|
+
else
|
|
68
|
+
parts[k] = Sequel::SQL::NumericExpression.new(:*, v, -1)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
58
71
|
DateAdd.new(expr, parts, opts)
|
|
59
72
|
end
|
|
60
73
|
end
|
|
@@ -68,6 +81,7 @@ module Sequel
|
|
|
68
81
|
module DatasetMethods
|
|
69
82
|
DURATION_UNITS = [:years, :months, :days, :hours, :minutes, :seconds].freeze
|
|
70
83
|
DEF_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| s.to_s.freeze}).freeze
|
|
84
|
+
POSTGRES_DURATION_UNITS = DURATION_UNITS.zip([:years, :months, :days, :hours, :mins, :secs].map{|s| s.to_s.freeze}).freeze
|
|
71
85
|
MYSQL_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s.upcase[0...-1]).freeze}).freeze
|
|
72
86
|
MSSQL_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s[0...-1]).freeze}).freeze
|
|
73
87
|
H2_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| s.to_s[0...-1].freeze}).freeze
|
|
@@ -87,14 +101,28 @@ module Sequel
|
|
|
87
101
|
|
|
88
102
|
cast = case db_type = db.database_type
|
|
89
103
|
when :postgres
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
104
|
+
casted = Sequel.cast(expr, cast_type)
|
|
105
|
+
|
|
106
|
+
if db.server_version >= 90400
|
|
107
|
+
placeholder = []
|
|
108
|
+
vals = []
|
|
109
|
+
each_valid_interval_unit(h, POSTGRES_DURATION_UNITS) do |value, sql_unit|
|
|
110
|
+
placeholder << "#{', ' unless placeholder.empty?}#{sql_unit} := "
|
|
111
|
+
vals << value
|
|
112
|
+
end
|
|
113
|
+
interval = Sequel.function(:make_interval, Sequel.lit(placeholder, *vals)) unless vals.empty?
|
|
114
|
+
else
|
|
115
|
+
parts = String.new
|
|
116
|
+
each_valid_interval_unit(h, DEF_DURATION_UNITS) do |value, sql_unit|
|
|
117
|
+
parts << "#{value} #{sql_unit} "
|
|
118
|
+
end
|
|
119
|
+
interval = Sequel.cast(parts, :interval) unless parts.empty?
|
|
93
120
|
end
|
|
94
|
-
|
|
95
|
-
|
|
121
|
+
|
|
122
|
+
if interval
|
|
123
|
+
return complex_expression_sql_append(sql, :+, [casted, interval])
|
|
96
124
|
else
|
|
97
|
-
return
|
|
125
|
+
return literal_append(sql, casted)
|
|
98
126
|
end
|
|
99
127
|
when :sqlite
|
|
100
128
|
args = [expr]
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# The is_distinct_from extension adds the ability to use the
|
|
4
4
|
# SQL standard IS DISTINCT FROM operator, which is similar to the
|
|
5
5
|
# not equals operator, except that NULL values are considered
|
|
6
|
-
# equal.
|
|
6
|
+
# equal. PostgreSQL, SQLite 3.39+, and H2 currently support this operator. On
|
|
7
7
|
# other databases, support is emulated.
|
|
8
8
|
#
|
|
9
9
|
# First, you need to load the extension into the database:
|
|
@@ -90,6 +90,8 @@ module Sequel
|
|
|
90
90
|
case db.database_type
|
|
91
91
|
when :postgres, :h2
|
|
92
92
|
true
|
|
93
|
+
when :sqlite
|
|
94
|
+
db.sqlite_version >= 33900
|
|
93
95
|
else
|
|
94
96
|
false
|
|
95
97
|
end
|
|
@@ -63,7 +63,7 @@ module Sequel
|
|
|
63
63
|
end
|
|
64
64
|
end
|
|
65
65
|
# :nocov:
|
|
66
|
-
ruby2_keywords
|
|
66
|
+
mod.send(:ruby2_keywords, meth) if mod.respond_to?(:ruby2_keywords, true)
|
|
67
67
|
# :nocov:
|
|
68
68
|
end
|
|
69
69
|
|
|
@@ -97,7 +97,7 @@ module Sequel
|
|
|
97
97
|
end
|
|
98
98
|
end
|
|
99
99
|
# :nocov:
|
|
100
|
-
ruby2_keywords(meth) if respond_to?(:ruby2_keywords,
|
|
100
|
+
ruby2_keywords(meth) if respond_to?(:ruby2_keywords, true)
|
|
101
101
|
# :nocov:
|
|
102
102
|
end
|
|
103
103
|
|
|
@@ -129,7 +129,7 @@ module Sequel
|
|
|
129
129
|
end
|
|
130
130
|
end
|
|
131
131
|
# :nocov:
|
|
132
|
-
ruby2_keywords(meth) if respond_to?(:ruby2_keywords,
|
|
132
|
+
ruby2_keywords(meth) if respond_to?(:ruby2_keywords, true)
|
|
133
133
|
# :nocov:
|
|
134
134
|
end
|
|
135
135
|
|
|
@@ -159,7 +159,7 @@ module Sequel
|
|
|
159
159
|
end
|
|
160
160
|
end
|
|
161
161
|
# :nocov:
|
|
162
|
-
ruby2_keywords(meth) if respond_to?(:ruby2_keywords,
|
|
162
|
+
ruby2_keywords(meth) if respond_to?(:ruby2_keywords, true)
|
|
163
163
|
# :nocov:
|
|
164
164
|
end
|
|
165
165
|
|
data/lib/sequel/version.rb
CHANGED
|
@@ -6,11 +6,11 @@ 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 =
|
|
9
|
+
MINOR = 60
|
|
10
10
|
|
|
11
11
|
# The tiny version of Sequel. Usually 0, only bumped for bugfix
|
|
12
12
|
# releases that fix regressions from previous versions.
|
|
13
|
-
TINY =
|
|
13
|
+
TINY = 1
|
|
14
14
|
|
|
15
15
|
# The version of Sequel you are using, as a string (e.g. "2.11.0")
|
|
16
16
|
VERSION = [MAJOR, MINOR, TINY].join('.').freeze
|
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.
|
|
4
|
+
version: 5.60.1
|
|
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-
|
|
11
|
+
date: 2022-09-02 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: minitest
|
|
@@ -191,6 +191,7 @@ extra_rdoc_files:
|
|
|
191
191
|
- doc/release_notes/5.58.0.txt
|
|
192
192
|
- doc/release_notes/5.59.0.txt
|
|
193
193
|
- doc/release_notes/5.6.0.txt
|
|
194
|
+
- doc/release_notes/5.60.0.txt
|
|
194
195
|
- doc/release_notes/5.7.0.txt
|
|
195
196
|
- doc/release_notes/5.8.0.txt
|
|
196
197
|
- doc/release_notes/5.9.0.txt
|
|
@@ -278,6 +279,7 @@ files:
|
|
|
278
279
|
- doc/release_notes/5.58.0.txt
|
|
279
280
|
- doc/release_notes/5.59.0.txt
|
|
280
281
|
- doc/release_notes/5.6.0.txt
|
|
282
|
+
- doc/release_notes/5.60.0.txt
|
|
281
283
|
- doc/release_notes/5.7.0.txt
|
|
282
284
|
- doc/release_notes/5.8.0.txt
|
|
283
285
|
- doc/release_notes/5.9.0.txt
|