sequel 5.79.0 → 5.81.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG +16 -0
- data/doc/code_order.rdoc +5 -3
- data/doc/release_notes/5.80.0.txt +40 -0
- data/doc/release_notes/5.81.0.txt +31 -0
- data/lib/sequel/adapters/shared/mysql.rb +2 -2
- data/lib/sequel/dataset/graph.rb +1 -0
- data/lib/sequel/dataset/query.rb +13 -0
- data/lib/sequel/extensions/caller_logging.rb +4 -1
- data/lib/sequel/extensions/provenance.rb +110 -0
- data/lib/sequel/extensions/temporarily_release_connection.rb +178 -0
- data/lib/sequel/plugins/column_encryption.rb +1 -1
- data/lib/sequel/plugins/input_transformer.rb +1 -1
- data/lib/sequel/version.rb +1 -1
- metadata +9 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a23afa1510b7bd1ba6918319eedce156450672520ab4798e6de56461a59660e1
|
4
|
+
data.tar.gz: bb6bbfbf0f1f82fe117fa8c725e9cf4fde49644a74b463ab8682018744a8a1de
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9e26620f8f1df2715205e9019c2012ec2e9f392d14ed427d66c76f488bccc3e5d3f27e4d626a47d54903d611695db0487f987d99191602024a1864d6c10f7bde
|
7
|
+
data.tar.gz: cd070d8c35960949039d226b5eaf8c90ebec8d0cef3f09b5dae533551bb35170ca6e2503d88f1b1512110b6617ff9c03d9cb2afb62395c4d953314aa5a5ca87c
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,19 @@
|
|
1
|
+
=== 5.81.0 (2024-06-01)
|
2
|
+
|
3
|
+
* Fix ignored block warnings in a couple plugin apply methods on Ruby 3.4 (jeremyevans)
|
4
|
+
|
5
|
+
* Skip Ruby internal caller locations when searching for caller locations in caller_logging and provenance extensions (jeremyevans)
|
6
|
+
|
7
|
+
* Add temporarily_release_connection Database extension for multithreaded transactional testing (jeremyevans)
|
8
|
+
|
9
|
+
=== 5.80.0 (2024-05-01)
|
10
|
+
|
11
|
+
* Support Dataset#skip_locked on MariaDB 10.6+ (simi) (#2150)
|
12
|
+
|
13
|
+
* Avoid allocating datasets in cases where the returned dataset would be the same as the receiver (jeremyevans)
|
14
|
+
|
15
|
+
* Add provenance dataset extension, which includes comments in queries showing how and where the dataset was built (jeremyevans)
|
16
|
+
|
1
17
|
=== 5.79.0 (2024-04-01)
|
2
18
|
|
3
19
|
* Support create_or_replace_view with :materialized option on PostgreSQL (nashby) (#2144)
|
data/doc/code_order.rdoc
CHANGED
@@ -91,9 +91,11 @@ unsafe runtime modification of the configuration:
|
|
91
91
|
model_classes.each(&:freeze)
|
92
92
|
DB.freeze
|
93
93
|
|
94
|
-
|
95
|
-
|
96
|
-
|
94
|
+
`model_classes` is not a Sequel method, it indicates an array of model
|
95
|
+
classes you defined. Instead of listing them manually, the `subclasses`
|
96
|
+
plugin can be used to keep track of all model classes that have been
|
97
|
+
setup in your application. Finalizing their associations and freezing
|
98
|
+
them can easily be achieved through the plugin:
|
97
99
|
|
98
100
|
# Register the plugin before setting up the models
|
99
101
|
Sequel::Model.plugin :subclasses
|
@@ -0,0 +1,40 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* A provenance dataset extension has been added. This extension makes
|
4
|
+
SQL queries include a comment describing how the dataset was built.
|
5
|
+
This can make debugging complex cases significantly easier. Here's
|
6
|
+
a simple example:
|
7
|
+
|
8
|
+
DB.extension :provenance
|
9
|
+
|
10
|
+
DB[:table].
|
11
|
+
select(:a).
|
12
|
+
where{b > 10}.
|
13
|
+
order(:c).
|
14
|
+
limit(10)
|
15
|
+
# SQL:
|
16
|
+
# SELECT a FROM table WHERE (b > 10) ORDER BY c LIMIT 10 --
|
17
|
+
# -- Dataset Provenance
|
18
|
+
# -- Keys:[:from] Source:(eval at bin/sequel:257):2:in `<main>'
|
19
|
+
# -- Keys:[:select] Source:(eval at bin/sequel:257):3:in `<main>'
|
20
|
+
# -- Keys:[:where] Source:(eval at bin/sequel:257):4:in `<main>'
|
21
|
+
# -- Keys:[:order] Source:(eval at bin/sequel:257):5:in `<main>'
|
22
|
+
# -- Keys:[:limit] Source:(eval at bin/sequel:257):6:in `<main>'
|
23
|
+
|
24
|
+
With the above example, it's obvious how the dataset is created, but
|
25
|
+
but in real applications, where datasets can be built from multiple
|
26
|
+
files, seeing where each dataset clone was made can be helpful.
|
27
|
+
|
28
|
+
The source listed will skip locations in the Ruby standard library
|
29
|
+
as well as Sequel itself. Other locations can be skipped by
|
30
|
+
providing a Database :provenance_caller_ignore Regexp option:
|
31
|
+
|
32
|
+
DB.opts[:provenance_caller_ignore] = /\/gems\/library_name-/
|
33
|
+
|
34
|
+
= Other Improvements
|
35
|
+
|
36
|
+
* For dataset methods where Sequel can determine that the return
|
37
|
+
value would be equivalent to the receiver, Sequel now returns the
|
38
|
+
receiver. This reduces the number of dataset allocations.
|
39
|
+
|
40
|
+
* Sequel now supports Dataset#skip_locked on MariaDB 10.6+.
|
@@ -0,0 +1,31 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* A temporarily_release_connection Database extension has been added,
|
4
|
+
designed for multithreaded transactional testing.
|
5
|
+
|
6
|
+
This allows one thread to start a transaction, and then release
|
7
|
+
the connection back for usage by the connection pool, so that
|
8
|
+
other threads can operate on the connection object safely inside
|
9
|
+
the transaction. This requires the connection pool be limited
|
10
|
+
to a single connection, to ensure that the released connection
|
11
|
+
can be reacquired. It's not perfect, because if the connection
|
12
|
+
is disconnected and removed from the pool while temporarily
|
13
|
+
released, there is no way to handle that situation correctly.
|
14
|
+
Example:
|
15
|
+
|
16
|
+
DB.transaction(rollback: :always, auto_savepoint: true) do |conn|
|
17
|
+
DB.temporarily_release_connection(conn) do
|
18
|
+
# Other threads can operate on connection safely inside
|
19
|
+
# the transaction
|
20
|
+
yield
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
= Other Improvements
|
25
|
+
|
26
|
+
* In the caller_logging and provenance extensions, Ruby internal
|
27
|
+
caller locations are skipped when trying to locate the appropriate
|
28
|
+
caller line to include.
|
29
|
+
|
30
|
+
* A couple ignored block warnings in plugin apply methods have been
|
31
|
+
fixed on Ruby 3.4.
|
@@ -926,9 +926,9 @@ module Sequel
|
|
926
926
|
(type == :insert && db.mariadb? && db.adapter_scheme != :jdbc) ? (db.server_version >= 100500) : false
|
927
927
|
end
|
928
928
|
|
929
|
-
# MySQL 8+
|
929
|
+
# MySQL 8+ and MariaDB 10.6+ support SKIP LOCKED.
|
930
930
|
def supports_skip_locked?
|
931
|
-
|
931
|
+
db.server_version >= (db.mariadb? ? 100600 : 80000)
|
932
932
|
end
|
933
933
|
|
934
934
|
# Check the database setting for whether fractional timestamps
|
data/lib/sequel/dataset/graph.rb
CHANGED
data/lib/sequel/dataset/query.rb
CHANGED
@@ -129,6 +129,7 @@ module Sequel
|
|
129
129
|
def distinct(*args, &block)
|
130
130
|
virtual_row_columns(args, block)
|
131
131
|
if args.empty?
|
132
|
+
return self if opts[:distinct] == EMPTY_ARRAY
|
132
133
|
cached_dataset(:_distinct_ds){clone(:distinct => EMPTY_ARRAY)}
|
133
134
|
else
|
134
135
|
raise(InvalidOperation, "DISTINCT ON not supported") unless supports_distinct_on?
|
@@ -230,6 +231,7 @@ module Sequel
|
|
230
231
|
#
|
231
232
|
# DB[:table].for_update # SELECT * FROM table FOR UPDATE
|
232
233
|
def for_update
|
234
|
+
return self if opts[:lock] == :update
|
233
235
|
cached_dataset(:_for_update_ds){lock_style(:update)}
|
234
236
|
end
|
235
237
|
|
@@ -641,6 +643,7 @@ module Sequel
|
|
641
643
|
# DB.from(:a, DB[:b].where(Sequel[:a][:c]=>Sequel[:b][:d]).lateral)
|
642
644
|
# # SELECT * FROM a, LATERAL (SELECT * FROM b WHERE (a.c = b.d))
|
643
645
|
def lateral
|
646
|
+
return self if opts[:lateral]
|
644
647
|
cached_dataset(:_lateral_ds){clone(:lateral=>true)}
|
645
648
|
end
|
646
649
|
|
@@ -744,6 +747,7 @@ module Sequel
|
|
744
747
|
# ds.all # => [{2=>:id}]
|
745
748
|
# ds.naked.all # => [{:id=>2}]
|
746
749
|
def naked
|
750
|
+
return self unless opts[:row_proc]
|
747
751
|
cached_dataset(:_naked_ds){with_row_proc(nil)}
|
748
752
|
end
|
749
753
|
|
@@ -753,6 +757,7 @@ module Sequel
|
|
753
757
|
# DB[:items].for_update.nowait
|
754
758
|
# # SELECT * FROM items FOR UPDATE NOWAIT
|
755
759
|
def nowait
|
760
|
+
return self if opts[:nowait]
|
756
761
|
cached_dataset(:_nowait_ds) do
|
757
762
|
raise(Error, 'This dataset does not support raises errors instead of waiting for locked rows') unless supports_nowait?
|
758
763
|
clone(:nowait=>true)
|
@@ -878,6 +883,7 @@ module Sequel
|
|
878
883
|
# end
|
879
884
|
def returning(*values)
|
880
885
|
if values.empty?
|
886
|
+
return self if opts[:returning] == EMPTY_ARRAY
|
881
887
|
cached_dataset(:_returning_ds) do
|
882
888
|
raise Error, "RETURNING is not supported on #{db.database_type}" unless supports_returning?(:insert)
|
883
889
|
clone(:returning=>EMPTY_ARRAY)
|
@@ -930,6 +936,7 @@ module Sequel
|
|
930
936
|
# DB[:items].select_all(:items, :foo) # SELECT items.*, foo.* FROM items
|
931
937
|
def select_all(*tables)
|
932
938
|
if tables.empty?
|
939
|
+
return self unless opts[:select]
|
933
940
|
cached_dataset(:_select_all_ds){clone(:select => nil)}
|
934
941
|
else
|
935
942
|
select(*tables.map{|t| i, a = split_alias(t); a || i}.map!{|t| SQL::ColumnAll.new(t)}.freeze)
|
@@ -1005,6 +1012,7 @@ module Sequel
|
|
1005
1012
|
|
1006
1013
|
# Specify that the check for limits/offsets when updating/deleting be skipped for the dataset.
|
1007
1014
|
def skip_limit_check
|
1015
|
+
return self if opts[:skip_limit_check]
|
1008
1016
|
cached_dataset(:_skip_limit_check_ds) do
|
1009
1017
|
clone(:skip_limit_check=>true)
|
1010
1018
|
end
|
@@ -1012,6 +1020,7 @@ module Sequel
|
|
1012
1020
|
|
1013
1021
|
# Skip locked rows when returning results from this dataset.
|
1014
1022
|
def skip_locked
|
1023
|
+
return self if opts[:skip_locked]
|
1015
1024
|
cached_dataset(:_skip_locked_ds) do
|
1016
1025
|
raise(Error, 'This dataset does not support skipping locked rows') unless supports_skip_locked?
|
1017
1026
|
clone(:skip_locked=>true)
|
@@ -1023,6 +1032,7 @@ module Sequel
|
|
1023
1032
|
# DB[:items].group(:a).having(a: 1).where(:b).unfiltered
|
1024
1033
|
# # SELECT * FROM items GROUP BY a
|
1025
1034
|
def unfiltered
|
1035
|
+
return self unless opts[:where] || opts[:having]
|
1026
1036
|
cached_dataset(:_unfiltered_ds){clone(:where => nil, :having => nil)}
|
1027
1037
|
end
|
1028
1038
|
|
@@ -1031,6 +1041,7 @@ module Sequel
|
|
1031
1041
|
# DB[:items].group(:a).having(a: 1).where(:b).ungrouped
|
1032
1042
|
# # SELECT * FROM items WHERE b
|
1033
1043
|
def ungrouped
|
1044
|
+
return self unless opts[:group] || opts[:having]
|
1034
1045
|
cached_dataset(:_ungrouped_ds){clone(:group => nil, :having => nil)}
|
1035
1046
|
end
|
1036
1047
|
|
@@ -1058,6 +1069,7 @@ module Sequel
|
|
1058
1069
|
#
|
1059
1070
|
# DB[:items].limit(10, 20).unlimited # SELECT * FROM items
|
1060
1071
|
def unlimited
|
1072
|
+
return self unless opts[:limit] || opts[:offset]
|
1061
1073
|
cached_dataset(:_unlimited_ds){clone(:limit=>nil, :offset=>nil)}
|
1062
1074
|
end
|
1063
1075
|
|
@@ -1065,6 +1077,7 @@ module Sequel
|
|
1065
1077
|
#
|
1066
1078
|
# DB[:items].order(:a).unordered # SELECT * FROM items
|
1067
1079
|
def unordered
|
1080
|
+
return self unless opts[:order]
|
1068
1081
|
cached_dataset(:_unordered_ds){clone(:order=>nil)}
|
1069
1082
|
end
|
1070
1083
|
|
@@ -36,6 +36,8 @@ require 'rbconfig'
|
|
36
36
|
module Sequel
|
37
37
|
module CallerLogging
|
38
38
|
SEQUEL_LIB_PATH = (File.expand_path('../../..', __FILE__) + '/').freeze
|
39
|
+
RUBY_STDLIB = RbConfig::CONFIG["rubylibdir"]
|
40
|
+
INTERNAL = '<internal'
|
39
41
|
|
40
42
|
# A regexp of caller lines to ignore, in addition to internal Sequel and Ruby code.
|
41
43
|
attr_accessor :caller_logging_ignore
|
@@ -59,7 +61,8 @@ module Sequel
|
|
59
61
|
ignore = caller_logging_ignore
|
60
62
|
c = caller.find do |line|
|
61
63
|
!(line.start_with?(SEQUEL_LIB_PATH) ||
|
62
|
-
line.start_with?(
|
64
|
+
line.start_with?(RUBY_STDLIB) ||
|
65
|
+
line.start_with?(INTERNAL) ||
|
63
66
|
(ignore && line =~ ignore))
|
64
67
|
end
|
65
68
|
|
@@ -0,0 +1,110 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
#
|
3
|
+
# The provenance dataset extension tracks the locations of all
|
4
|
+
# dataset clones that resulted in the current dataset, and includes
|
5
|
+
# the information as a comment in the dataset's SQL. This makes it
|
6
|
+
# possible to see how a query was built, which can aid debugging.
|
7
|
+
# Example:
|
8
|
+
#
|
9
|
+
# DB[:table].
|
10
|
+
# select(:a).
|
11
|
+
# where{b > 10}.
|
12
|
+
# order(:c).
|
13
|
+
# limit(10)
|
14
|
+
# # SQL:
|
15
|
+
# # SELECT a FROM table WHERE (b > 10) ORDER BY c LIMIT 10 --
|
16
|
+
# # -- Dataset Provenance
|
17
|
+
# # -- Keys:[:from] Source:(eval at bin/sequel:257):2:in `<main>'
|
18
|
+
# # -- Keys:[:select] Source:(eval at bin/sequel:257):3:in `<main>'
|
19
|
+
# # -- Keys:[:where] Source:(eval at bin/sequel:257):4:in `<main>'
|
20
|
+
# # -- Keys:[:order] Source:(eval at bin/sequel:257):5:in `<main>'
|
21
|
+
# # -- Keys:[:limit] Source:(eval at bin/sequel:257):6:in `<main>'
|
22
|
+
#
|
23
|
+
# With the above example, the source is fairly obvious and not helpful,
|
24
|
+
# but in real applications, where datasets can be built from multiple
|
25
|
+
# files, seeing where each dataset clone was made can be helpful.
|
26
|
+
#
|
27
|
+
# The Source listed will skip locations in the Ruby standard library
|
28
|
+
# as well as Sequel itself. Other locations can be skipped by
|
29
|
+
# providing a Database :provenance_caller_ignore Regexp option:
|
30
|
+
#
|
31
|
+
# DB.opts[:provenance_caller_ignore] = /\/gems\/library_name-/
|
32
|
+
#
|
33
|
+
# Related module: Sequel::Dataset::Provenance
|
34
|
+
|
35
|
+
#
|
36
|
+
module Sequel
|
37
|
+
class Dataset
|
38
|
+
module Provenance
|
39
|
+
SEQUEL_LIB_PATH = (File.expand_path('../../..', __FILE__) + '/').freeze
|
40
|
+
RUBY_STDLIB = RbConfig::CONFIG["rubylibdir"]
|
41
|
+
INTERNAL = '<internal'
|
42
|
+
|
43
|
+
if TRUE_FREEZE
|
44
|
+
# Include provenance information when cloning datasets.
|
45
|
+
def clone(opts = nil || (return self))
|
46
|
+
super(provenance_opts(opts))
|
47
|
+
end
|
48
|
+
else
|
49
|
+
# :nocov:
|
50
|
+
def clone(opts = OPTS) # :nodoc:
|
51
|
+
super(provenance_opts(opts))
|
52
|
+
end
|
53
|
+
# :nocov:
|
54
|
+
end
|
55
|
+
|
56
|
+
%w'select insert update delete'.each do |type|
|
57
|
+
# Include the provenance information as a comment when preparing dataset SQL
|
58
|
+
define_method(:"#{type}_sql") do |*a|
|
59
|
+
sql = super(*a)
|
60
|
+
|
61
|
+
if provenance = @opts[:provenance]
|
62
|
+
comment = provenance.map do |hash|
|
63
|
+
" -- Keys:#{hash[:keys].inspect} Source:#{hash[:source]}".to_s.gsub(/\s+/, ' ')
|
64
|
+
end
|
65
|
+
comment << ""
|
66
|
+
comment.unshift " -- Dataset Provenance"
|
67
|
+
comment.unshift " -- "
|
68
|
+
comment = comment.join("\n")
|
69
|
+
|
70
|
+
if sql.frozen?
|
71
|
+
sql += comment
|
72
|
+
sql.freeze
|
73
|
+
elsif @opts[:append_sql] || @opts[:placeholder_literalizer]
|
74
|
+
sql << comment
|
75
|
+
else
|
76
|
+
sql += comment
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
sql
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
# Return a copy of opts with provenance information added.
|
87
|
+
def provenance_opts(opts)
|
88
|
+
provenance = {source: provenance_source, keys: opts.keys.freeze}.freeze
|
89
|
+
opts = opts.dup
|
90
|
+
opts[:provenance] = ((@opts[:provenance] || EMPTY_ARRAY).dup << provenance).freeze
|
91
|
+
opts
|
92
|
+
end
|
93
|
+
|
94
|
+
# Return the caller line for the provenance change. This skips
|
95
|
+
# Sequel itself and the standard library. Additional locations
|
96
|
+
# can be skipped using the :provenance_caller_ignore Dataset option.
|
97
|
+
def provenance_source
|
98
|
+
ignore = db.opts[:provenance_caller_ignore]
|
99
|
+
caller.find do |line|
|
100
|
+
!(line.start_with?(SEQUEL_LIB_PATH) ||
|
101
|
+
line.start_with?(RUBY_STDLIB) ||
|
102
|
+
line.start_with?(INTERNAL) ||
|
103
|
+
(ignore && line =~ ignore))
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
register_extension(:provenance, Provenance)
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,178 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
#
|
3
|
+
# The temporarily_release_connection extension adds support for temporarily
|
4
|
+
# releasing a checked out connection back to the connection pool. It is
|
5
|
+
# designed for use in multithreaded transactional integration tests, allowing
|
6
|
+
# a connection to start a transaction in one thread, but be temporarily
|
7
|
+
# released back to the connection pool, so it can be operated on safely
|
8
|
+
# by multiple threads inside a block. For example, the main thread could be
|
9
|
+
# running tests that send web requests, and a separate thread running a web
|
10
|
+
# server that is responding to those requests, and the same connection and
|
11
|
+
# transaction would be used for both.
|
12
|
+
#
|
13
|
+
# To load the extension into the database:
|
14
|
+
#
|
15
|
+
# DB.extension :temporarily_release_connection
|
16
|
+
#
|
17
|
+
# After the extension is loaded, call the +temporarily_release_connection+
|
18
|
+
# method with the connection object to temporarily release the connection
|
19
|
+
# back to the pool. Example:
|
20
|
+
#
|
21
|
+
# DB.transaction(rollback: :always, auto_savepoint: true) do |conn|
|
22
|
+
# DB.temporarily_release_connection(conn) do
|
23
|
+
# # Other threads can operate on connection safely inside the transaction
|
24
|
+
# yield
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# For sharded connection pools, the second argument to +temporarily_release_connection+
|
29
|
+
# is respected, and specifies the server on which to temporarily release the connection.
|
30
|
+
#
|
31
|
+
# The temporarily_release_connection extension is only supported with the
|
32
|
+
# threaded and timed_queue connection pools that ship with Sequel (and the sharded
|
33
|
+
# versions of each). To make sure that same connection object can be reacquired, it
|
34
|
+
# is only supported if the maximum connection pool size is 1, so set the Database
|
35
|
+
# :max_connections option to 1 if you plan to use this extension.
|
36
|
+
#
|
37
|
+
# If the +temporarily_release_connection+ method cannot reacquire the same connection
|
38
|
+
# it released to the pool, it will raise a Sequel::UnableToReacquireConnectionError
|
39
|
+
# exception. This should only happen if the connection has been disconnected
|
40
|
+
# while it was temporarily released. If this error is raised, Database#transaction
|
41
|
+
# will not rollback the transaction, since the connection object is likely no longer
|
42
|
+
# valid, and on poorly written database drivers, that could cause the process to crash.
|
43
|
+
#
|
44
|
+
# Related modules: Sequel::TemporarilyReleaseConnection,
|
45
|
+
# Sequel::UnableToReacquireConnectionError
|
46
|
+
|
47
|
+
#
|
48
|
+
module Sequel
|
49
|
+
# Error class raised if the connection pool does not provide the same connection
|
50
|
+
# object when checking a temporarily released connection out.
|
51
|
+
class UnableToReacquireConnectionError < Error
|
52
|
+
end
|
53
|
+
|
54
|
+
module TemporarilyReleaseConnection
|
55
|
+
module DatabaseMethods
|
56
|
+
# Temporarily release the connection back to the connection pool for the
|
57
|
+
# duration of the block.
|
58
|
+
def temporarily_release_connection(conn, server=:default, &block)
|
59
|
+
pool.temporarily_release_connection(conn, server, &block)
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
# Do nothing if UnableToReacquireConnectionError is raised, as it is
|
65
|
+
# likely the connection is not in a usable state.
|
66
|
+
def rollback_transaction(conn, opts)
|
67
|
+
return if UnableToReacquireConnectionError === $!
|
68
|
+
super
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
module PoolMethods
|
73
|
+
# Temporarily release a currently checked out connection, then yield to the block. Reacquire the same
|
74
|
+
# connection upon the exit of the block.
|
75
|
+
def temporarily_release_connection(conn, server)
|
76
|
+
t = Sequel.current
|
77
|
+
raise Error, "connection not currently checked out" unless conn.equal?(trc_owned_connection(t, server))
|
78
|
+
|
79
|
+
begin
|
80
|
+
trc_release(t, conn, server)
|
81
|
+
yield
|
82
|
+
ensure
|
83
|
+
c = trc_acquire(t, server)
|
84
|
+
unless conn.equal?(c)
|
85
|
+
raise UnableToReacquireConnectionError, "reacquired connection not the same as initial connection"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
module TimedQueue
|
92
|
+
private
|
93
|
+
|
94
|
+
def trc_owned_connection(t, server)
|
95
|
+
owned_connection(t)
|
96
|
+
end
|
97
|
+
|
98
|
+
def trc_release(t, conn, server)
|
99
|
+
release(t)
|
100
|
+
end
|
101
|
+
|
102
|
+
def trc_acquire(t, server)
|
103
|
+
acquire(t)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
module ShardedTimedQueue
|
108
|
+
# Normalize the server name for sharded connection pools
|
109
|
+
def temporarily_release_connection(conn, server)
|
110
|
+
server = pick_server(server)
|
111
|
+
super
|
112
|
+
end
|
113
|
+
|
114
|
+
private
|
115
|
+
|
116
|
+
def trc_owned_connection(t, server)
|
117
|
+
owned_connection(t, server)
|
118
|
+
end
|
119
|
+
|
120
|
+
def trc_release(t, conn, server)
|
121
|
+
release(t, conn, server)
|
122
|
+
end
|
123
|
+
|
124
|
+
def trc_acquire(t, server)
|
125
|
+
acquire(t, server)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
module ThreadedBase
|
130
|
+
private
|
131
|
+
|
132
|
+
def trc_release(t, conn, server)
|
133
|
+
sync{super}
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
module Threaded
|
138
|
+
include TimedQueue
|
139
|
+
include ThreadedBase
|
140
|
+
end
|
141
|
+
|
142
|
+
module ShardedThreaded
|
143
|
+
include ShardedTimedQueue
|
144
|
+
include ThreadedBase
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
trc = TemporarilyReleaseConnection
|
149
|
+
trc_map = {
|
150
|
+
:threaded => trc::Threaded,
|
151
|
+
:sharded_threaded => trc::ShardedThreaded,
|
152
|
+
:timed_queue => trc::TimedQueue,
|
153
|
+
:sharded_timed_queue => trc::ShardedTimedQueue,
|
154
|
+
}.freeze
|
155
|
+
|
156
|
+
Database.register_extension(:temporarily_release_connection) do |db|
|
157
|
+
unless pool_mod = trc_map[db.pool.pool_type]
|
158
|
+
raise(Error, "temporarily_release_connection extension not supported for connection pool type #{db.pool.pool_type}")
|
159
|
+
end
|
160
|
+
|
161
|
+
case db.pool.pool_type
|
162
|
+
when :threaded, :sharded_threaded
|
163
|
+
if db.opts[:connection_handling] == :disconnect
|
164
|
+
raise Error, "temporarily_release_connection extension not supported with connection_handling: :disconnect option"
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
unless db.pool.max_size == 1
|
169
|
+
raise Error, "temporarily_release_connection extension not supported unless :max_connections option is 1"
|
170
|
+
end
|
171
|
+
|
172
|
+
db.extend(trc::DatabaseMethods)
|
173
|
+
db.pool.extend(trc::PoolMethods)
|
174
|
+
db.pool.extend(pool_mod)
|
175
|
+
end
|
176
|
+
|
177
|
+
private_constant :TemporarilyReleaseConnection
|
178
|
+
end
|
@@ -24,7 +24,7 @@ module Sequel
|
|
24
24
|
# # Make the Album class support input transformers
|
25
25
|
# Album.plugin :input_transformer
|
26
26
|
module InputTransformer
|
27
|
-
def self.apply(model,
|
27
|
+
def self.apply(model, *, &_)
|
28
28
|
model.instance_exec do
|
29
29
|
@input_transformers = {}
|
30
30
|
@skip_input_transformer_columns = {}
|
data/lib/sequel/version.rb
CHANGED
@@ -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 =
|
9
|
+
MINOR = 81
|
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.
|
4
|
+
version: 5.81.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: 2024-
|
11
|
+
date: 2024-06-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bigdecimal
|
@@ -227,6 +227,8 @@ extra_rdoc_files:
|
|
227
227
|
- doc/release_notes/5.78.0.txt
|
228
228
|
- doc/release_notes/5.79.0.txt
|
229
229
|
- doc/release_notes/5.8.0.txt
|
230
|
+
- doc/release_notes/5.80.0.txt
|
231
|
+
- doc/release_notes/5.81.0.txt
|
230
232
|
- doc/release_notes/5.9.0.txt
|
231
233
|
files:
|
232
234
|
- CHANGELOG
|
@@ -334,6 +336,8 @@ files:
|
|
334
336
|
- doc/release_notes/5.78.0.txt
|
335
337
|
- doc/release_notes/5.79.0.txt
|
336
338
|
- doc/release_notes/5.8.0.txt
|
339
|
+
- doc/release_notes/5.80.0.txt
|
340
|
+
- doc/release_notes/5.81.0.txt
|
337
341
|
- doc/release_notes/5.9.0.txt
|
338
342
|
- doc/schema_modification.rdoc
|
339
343
|
- doc/security.rdoc
|
@@ -496,6 +500,7 @@ files:
|
|
496
500
|
- lib/sequel/extensions/pg_static_cache_updater.rb
|
497
501
|
- lib/sequel/extensions/pg_timestamptz.rb
|
498
502
|
- lib/sequel/extensions/pretty_table.rb
|
503
|
+
- lib/sequel/extensions/provenance.rb
|
499
504
|
- lib/sequel/extensions/query.rb
|
500
505
|
- lib/sequel/extensions/round_timestamps.rb
|
501
506
|
- lib/sequel/extensions/run_transaction_hooks.rb
|
@@ -519,6 +524,7 @@ files:
|
|
519
524
|
- lib/sequel/extensions/symbol_as.rb
|
520
525
|
- lib/sequel/extensions/symbol_as_refinement.rb
|
521
526
|
- lib/sequel/extensions/synchronize_sql.rb
|
527
|
+
- lib/sequel/extensions/temporarily_release_connection.rb
|
522
528
|
- lib/sequel/extensions/thread_local_timezones.rb
|
523
529
|
- lib/sequel/extensions/to_dot.rb
|
524
530
|
- lib/sequel/extensions/transaction_connection_validator.rb
|
@@ -666,7 +672,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
666
672
|
- !ruby/object:Gem::Version
|
667
673
|
version: '0'
|
668
674
|
requirements: []
|
669
|
-
rubygems_version: 3.5.
|
675
|
+
rubygems_version: 3.5.9
|
670
676
|
signing_key:
|
671
677
|
specification_version: 4
|
672
678
|
summary: The Database Toolkit for Ruby
|