Open
Conversation
Bumps [sequel](https://github.com/jeremyevans/sequel) from 5.101.0 to 5.103.0. - [Changelog](https://github.com/jeremyevans/sequel/blob/master/CHANGELOG) - [Commits](jeremyevans/sequel@5.101.0...5.103.0) --- updated-dependencies: - dependency-name: sequel dependency-version: 5.103.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
Contributor
4 similar comments
Contributor
Contributor
Contributor
Contributor
Contributor
gem compare bigdecimal 4.0.1 4.1.0Compared versions: ["4.0.1", "4.1.0"]
DIFFERENT require_paths:
4.0.1: ["/opt/hostedtoolcache/Ruby/4.0.2/x64/lib/ruby/gems/4.0.0/extensions/x86_64-linux/4.0.0/bigdecimal-4.0.1", "lib"]
4.1.0: ["/opt/hostedtoolcache/Ruby/4.0.2/x64/lib/ruby/gems/4.0.0/extensions/x86_64-linux/4.0.0/bigdecimal-4.1.0", "lib"]
DIFFERENT required_ruby_version:
4.0.1: >= 2.5.0
4.1.0: >= 2.6.0
DIFFERENT version:
4.0.1: 4.0.1
4.1.0: 4.1.0
DIFFERENT files:
4.0.1->4.1.0:
* Added:
ext/bigdecimal/div.h +192/-0
ext/bigdecimal/ntt.h +191/-0
sig/big_decimal.rbs +1502/-0
sig/big_decimal_util.rbs +158/-0
sig/big_math.rbs +423/-0
* Changed:
bigdecimal.gemspec +6/-1
ext/bigdecimal/bigdecimal.c +85/-27
ext/bigdecimal/bigdecimal.h +37/-36
ext/bigdecimal/extconf.rb +1/-2
ext/bigdecimal/missing.h +4/-2
lib/bigdecimal.rb +86/-59
lib/bigdecimal/math.rb +102/-123
lib/bigdecimal/util.rb +1/-1
sample/linear.rb +73/-37
(!) Shebang probably lost: #!/usr/local/bin/ruby
sample/nlsolve.rb +47/-30
(!) Shebang probably lost: #!/usr/local/bin/ruby
sample/pi.rb +2/-7
(!) Shebang probably lost: #!/usr/local/bin/ruby |
3 similar comments
Contributor
gem compare bigdecimal 4.0.1 4.1.0Compared versions: ["4.0.1", "4.1.0"]
DIFFERENT require_paths:
4.0.1: ["/opt/hostedtoolcache/Ruby/4.0.2/x64/lib/ruby/gems/4.0.0/extensions/x86_64-linux/4.0.0/bigdecimal-4.0.1", "lib"]
4.1.0: ["/opt/hostedtoolcache/Ruby/4.0.2/x64/lib/ruby/gems/4.0.0/extensions/x86_64-linux/4.0.0/bigdecimal-4.1.0", "lib"]
DIFFERENT required_ruby_version:
4.0.1: >= 2.5.0
4.1.0: >= 2.6.0
DIFFERENT version:
4.0.1: 4.0.1
4.1.0: 4.1.0
DIFFERENT files:
4.0.1->4.1.0:
* Added:
ext/bigdecimal/div.h +192/-0
ext/bigdecimal/ntt.h +191/-0
sig/big_decimal.rbs +1502/-0
sig/big_decimal_util.rbs +158/-0
sig/big_math.rbs +423/-0
* Changed:
bigdecimal.gemspec +6/-1
ext/bigdecimal/bigdecimal.c +85/-27
ext/bigdecimal/bigdecimal.h +37/-36
ext/bigdecimal/extconf.rb +1/-2
ext/bigdecimal/missing.h +4/-2
lib/bigdecimal.rb +86/-59
lib/bigdecimal/math.rb +102/-123
lib/bigdecimal/util.rb +1/-1
sample/linear.rb +73/-37
(!) Shebang probably lost: #!/usr/local/bin/ruby
sample/nlsolve.rb +47/-30
(!) Shebang probably lost: #!/usr/local/bin/ruby
sample/pi.rb +2/-7
(!) Shebang probably lost: #!/usr/local/bin/ruby |
Contributor
gem compare bigdecimal 4.0.1 4.1.0Compared versions: ["4.0.1", "4.1.0"]
DIFFERENT require_paths:
4.0.1: ["/opt/hostedtoolcache/Ruby/4.0.2/x64/lib/ruby/gems/4.0.0/extensions/x86_64-linux/4.0.0/bigdecimal-4.0.1", "lib"]
4.1.0: ["/opt/hostedtoolcache/Ruby/4.0.2/x64/lib/ruby/gems/4.0.0/extensions/x86_64-linux/4.0.0/bigdecimal-4.1.0", "lib"]
DIFFERENT required_ruby_version:
4.0.1: >= 2.5.0
4.1.0: >= 2.6.0
DIFFERENT version:
4.0.1: 4.0.1
4.1.0: 4.1.0
DIFFERENT files:
4.0.1->4.1.0:
* Added:
ext/bigdecimal/div.h +192/-0
ext/bigdecimal/ntt.h +191/-0
sig/big_decimal.rbs +1502/-0
sig/big_decimal_util.rbs +158/-0
sig/big_math.rbs +423/-0
* Changed:
bigdecimal.gemspec +6/-1
ext/bigdecimal/bigdecimal.c +85/-27
ext/bigdecimal/bigdecimal.h +37/-36
ext/bigdecimal/extconf.rb +1/-2
ext/bigdecimal/missing.h +4/-2
lib/bigdecimal.rb +86/-59
lib/bigdecimal/math.rb +102/-123
lib/bigdecimal/util.rb +1/-1
sample/linear.rb +73/-37
(!) Shebang probably lost: #!/usr/local/bin/ruby
sample/nlsolve.rb +47/-30
(!) Shebang probably lost: #!/usr/local/bin/ruby
sample/pi.rb +2/-7
(!) Shebang probably lost: #!/usr/local/bin/ruby |
Contributor
gem compare bigdecimal 4.0.1 4.1.0Compared versions: ["4.0.1", "4.1.0"]
DIFFERENT require_paths:
4.0.1: ["/opt/hostedtoolcache/Ruby/4.0.2/x64/lib/ruby/gems/4.0.0/extensions/x86_64-linux/4.0.0/bigdecimal-4.0.1", "lib"]
4.1.0: ["/opt/hostedtoolcache/Ruby/4.0.2/x64/lib/ruby/gems/4.0.0/extensions/x86_64-linux/4.0.0/bigdecimal-4.1.0", "lib"]
DIFFERENT required_ruby_version:
4.0.1: >= 2.5.0
4.1.0: >= 2.6.0
DIFFERENT version:
4.0.1: 4.0.1
4.1.0: 4.1.0
DIFFERENT files:
4.0.1->4.1.0:
* Added:
ext/bigdecimal/div.h +192/-0
ext/bigdecimal/ntt.h +191/-0
sig/big_decimal.rbs +1502/-0
sig/big_decimal_util.rbs +158/-0
sig/big_math.rbs +423/-0
* Changed:
bigdecimal.gemspec +6/-1
ext/bigdecimal/bigdecimal.c +85/-27
ext/bigdecimal/bigdecimal.h +37/-36
ext/bigdecimal/extconf.rb +1/-2
ext/bigdecimal/missing.h +4/-2
lib/bigdecimal.rb +86/-59
lib/bigdecimal/math.rb +102/-123
lib/bigdecimal/util.rb +1/-1
sample/linear.rb +73/-37
(!) Shebang probably lost: #!/usr/local/bin/ruby
sample/nlsolve.rb +47/-30
(!) Shebang probably lost: #!/usr/local/bin/ruby
sample/pi.rb +2/-7
(!) Shebang probably lost: #!/usr/local/bin/ruby |
Contributor
|
3 similar comments
Contributor
|
Contributor
|
Contributor
|
Contributor
gem compare bigdecimal 4.0.1 4.1.0Compared versions: ["4.0.1", "4.1.0"]
DIFFERENT require_paths:
4.0.1: ["/opt/hostedtoolcache/Ruby/4.0.2/x64/lib/ruby/gems/4.0.0/extensions/x86_64-linux/4.0.0/bigdecimal-4.0.1", "lib"]
4.1.0: ["/opt/hostedtoolcache/Ruby/4.0.2/x64/lib/ruby/gems/4.0.0/extensions/x86_64-linux/4.0.0/bigdecimal-4.1.0", "lib"]
DIFFERENT required_ruby_version:
4.0.1: >= 2.5.0
4.1.0: >= 2.6.0
DIFFERENT version:
4.0.1: 4.0.1
4.1.0: 4.1.0
DIFFERENT files:
4.0.1->4.1.0:
* Added:
ext/bigdecimal/div.h +192/-0
ext/bigdecimal/ntt.h +191/-0
sig/big_decimal.rbs +1502/-0
sig/big_decimal_util.rbs +158/-0
sig/big_math.rbs +423/-0
* Changed:
bigdecimal.gemspec +6/-1
ext/bigdecimal/bigdecimal.c +85/-27
ext/bigdecimal/bigdecimal.h +37/-36
ext/bigdecimal/extconf.rb +1/-2
ext/bigdecimal/missing.h +4/-2
lib/bigdecimal.rb +86/-59
lib/bigdecimal/math.rb +102/-123
lib/bigdecimal/util.rb +1/-1
sample/linear.rb +73/-37
(!) Shebang probably lost: #!/usr/local/bin/ruby
sample/nlsolve.rb +47/-30
(!) Shebang probably lost: #!/usr/local/bin/ruby
sample/pi.rb +2/-7
(!) Shebang probably lost: #!/usr/local/bin/ruby |
Contributor
gem compare sequel 5.101.0 5.103.0Compared versions: ["5.101.0", "5.103.0"]
DIFFERENT version:
5.101.0: 5.101.0
5.103.0: 5.103.0
DIFFERENT files:
5.101.0->5.103.0:
* Added:
lib/sequel/extensions/connection_checkout_event_callback.rb +151/-0
lib/sequel/extensions/lit_require_frozen.rb +131/-0
* Changed:
MIT-LICENSE +1/-1
lib/sequel/adapters/jdbc/derby.rb +2/-0
lib/sequel/adapters/jdbc/h2.rb +2/-2
lib/sequel/adapters/postgres.rb +1/-1
lib/sequel/adapters/shared/mssql.rb +3/-3
lib/sequel/adapters/shared/mysql.rb +5/-4
lib/sequel/adapters/shared/postgres.rb +16/-16
lib/sequel/adapters/shared/sqlite.rb +3/-3
lib/sequel/adapters/sqlite.rb +1/-1
lib/sequel/adapters/tinytds.rb +1/-1
lib/sequel/connection_pool.rb +6/-0
lib/sequel/connection_pool/sharded_timed_queue.rb +36/-11
lib/sequel/connection_pool/timed_queue.rb +27/-9
lib/sequel/database/schema_generator.rb +36/-5
lib/sequel/database/schema_methods.rb +1/-1
lib/sequel/dataset/placeholder_literalizer.rb +3/-0
lib/sequel/dataset/prepared_statements.rb +7/-4
lib/sequel/dataset/query.rb +6/-3
lib/sequel/dataset/sql.rb +6/-1
lib/sequel/extensions/connection_expiration.rb +1/-1
lib/sequel/extensions/connection_validator.rb +1/-1
lib/sequel/extensions/dataset_run.rb +2/-2
lib/sequel/extensions/date_arithmetic.rb +6/-6
lib/sequel/extensions/migration.rb +14/-17
lib/sequel/extensions/pg_enum.rb +1/-1
lib/sequel/model/associations.rb +1/-1
lib/sequel/plugins/dirty.rb +5/-2
lib/sequel/plugins/mssql_optimistic_locking.rb +1/-1
lib/sequel/plugins/pg_xmin_optimistic_locking.rb +1/-1
lib/sequel/plugins/serialization.rb +10/-1
lib/sequel/version.rb +1/-1
DIFFERENT extra_rdoc_files:
5.101.0->5.103.0:
* Changed:
MIT-LICENSE +1/-1 |
3 similar comments
Contributor
gem compare sequel 5.101.0 5.103.0Compared versions: ["5.101.0", "5.103.0"]
DIFFERENT version:
5.101.0: 5.101.0
5.103.0: 5.103.0
DIFFERENT files:
5.101.0->5.103.0:
* Added:
lib/sequel/extensions/connection_checkout_event_callback.rb +151/-0
lib/sequel/extensions/lit_require_frozen.rb +131/-0
* Changed:
MIT-LICENSE +1/-1
lib/sequel/adapters/jdbc/derby.rb +2/-0
lib/sequel/adapters/jdbc/h2.rb +2/-2
lib/sequel/adapters/postgres.rb +1/-1
lib/sequel/adapters/shared/mssql.rb +3/-3
lib/sequel/adapters/shared/mysql.rb +5/-4
lib/sequel/adapters/shared/postgres.rb +16/-16
lib/sequel/adapters/shared/sqlite.rb +3/-3
lib/sequel/adapters/sqlite.rb +1/-1
lib/sequel/adapters/tinytds.rb +1/-1
lib/sequel/connection_pool.rb +6/-0
lib/sequel/connection_pool/sharded_timed_queue.rb +36/-11
lib/sequel/connection_pool/timed_queue.rb +27/-9
lib/sequel/database/schema_generator.rb +36/-5
lib/sequel/database/schema_methods.rb +1/-1
lib/sequel/dataset/placeholder_literalizer.rb +3/-0
lib/sequel/dataset/prepared_statements.rb +7/-4
lib/sequel/dataset/query.rb +6/-3
lib/sequel/dataset/sql.rb +6/-1
lib/sequel/extensions/connection_expiration.rb +1/-1
lib/sequel/extensions/connection_validator.rb +1/-1
lib/sequel/extensions/dataset_run.rb +2/-2
lib/sequel/extensions/date_arithmetic.rb +6/-6
lib/sequel/extensions/migration.rb +14/-17
lib/sequel/extensions/pg_enum.rb +1/-1
lib/sequel/model/associations.rb +1/-1
lib/sequel/plugins/dirty.rb +5/-2
lib/sequel/plugins/mssql_optimistic_locking.rb +1/-1
lib/sequel/plugins/pg_xmin_optimistic_locking.rb +1/-1
lib/sequel/plugins/serialization.rb +10/-1
lib/sequel/version.rb +1/-1
DIFFERENT extra_rdoc_files:
5.101.0->5.103.0:
* Changed:
MIT-LICENSE +1/-1 |
Contributor
gem compare sequel 5.101.0 5.103.0Compared versions: ["5.101.0", "5.103.0"]
DIFFERENT version:
5.101.0: 5.101.0
5.103.0: 5.103.0
DIFFERENT files:
5.101.0->5.103.0:
* Added:
lib/sequel/extensions/connection_checkout_event_callback.rb +151/-0
lib/sequel/extensions/lit_require_frozen.rb +131/-0
* Changed:
MIT-LICENSE +1/-1
lib/sequel/adapters/jdbc/derby.rb +2/-0
lib/sequel/adapters/jdbc/h2.rb +2/-2
lib/sequel/adapters/postgres.rb +1/-1
lib/sequel/adapters/shared/mssql.rb +3/-3
lib/sequel/adapters/shared/mysql.rb +5/-4
lib/sequel/adapters/shared/postgres.rb +16/-16
lib/sequel/adapters/shared/sqlite.rb +3/-3
lib/sequel/adapters/sqlite.rb +1/-1
lib/sequel/adapters/tinytds.rb +1/-1
lib/sequel/connection_pool.rb +6/-0
lib/sequel/connection_pool/sharded_timed_queue.rb +36/-11
lib/sequel/connection_pool/timed_queue.rb +27/-9
lib/sequel/database/schema_generator.rb +36/-5
lib/sequel/database/schema_methods.rb +1/-1
lib/sequel/dataset/placeholder_literalizer.rb +3/-0
lib/sequel/dataset/prepared_statements.rb +7/-4
lib/sequel/dataset/query.rb +6/-3
lib/sequel/dataset/sql.rb +6/-1
lib/sequel/extensions/connection_expiration.rb +1/-1
lib/sequel/extensions/connection_validator.rb +1/-1
lib/sequel/extensions/dataset_run.rb +2/-2
lib/sequel/extensions/date_arithmetic.rb +6/-6
lib/sequel/extensions/migration.rb +14/-17
lib/sequel/extensions/pg_enum.rb +1/-1
lib/sequel/model/associations.rb +1/-1
lib/sequel/plugins/dirty.rb +5/-2
lib/sequel/plugins/mssql_optimistic_locking.rb +1/-1
lib/sequel/plugins/pg_xmin_optimistic_locking.rb +1/-1
lib/sequel/plugins/serialization.rb +10/-1
lib/sequel/version.rb +1/-1
DIFFERENT extra_rdoc_files:
5.101.0->5.103.0:
* Changed:
MIT-LICENSE +1/-1 |
Contributor
gem compare sequel 5.101.0 5.103.0Compared versions: ["5.101.0", "5.103.0"]
DIFFERENT version:
5.101.0: 5.101.0
5.103.0: 5.103.0
DIFFERENT files:
5.101.0->5.103.0:
* Added:
lib/sequel/extensions/connection_checkout_event_callback.rb +151/-0
lib/sequel/extensions/lit_require_frozen.rb +131/-0
* Changed:
MIT-LICENSE +1/-1
lib/sequel/adapters/jdbc/derby.rb +2/-0
lib/sequel/adapters/jdbc/h2.rb +2/-2
lib/sequel/adapters/postgres.rb +1/-1
lib/sequel/adapters/shared/mssql.rb +3/-3
lib/sequel/adapters/shared/mysql.rb +5/-4
lib/sequel/adapters/shared/postgres.rb +16/-16
lib/sequel/adapters/shared/sqlite.rb +3/-3
lib/sequel/adapters/sqlite.rb +1/-1
lib/sequel/adapters/tinytds.rb +1/-1
lib/sequel/connection_pool.rb +6/-0
lib/sequel/connection_pool/sharded_timed_queue.rb +36/-11
lib/sequel/connection_pool/timed_queue.rb +27/-9
lib/sequel/database/schema_generator.rb +36/-5
lib/sequel/database/schema_methods.rb +1/-1
lib/sequel/dataset/placeholder_literalizer.rb +3/-0
lib/sequel/dataset/prepared_statements.rb +7/-4
lib/sequel/dataset/query.rb +6/-3
lib/sequel/dataset/sql.rb +6/-1
lib/sequel/extensions/connection_expiration.rb +1/-1
lib/sequel/extensions/connection_validator.rb +1/-1
lib/sequel/extensions/dataset_run.rb +2/-2
lib/sequel/extensions/date_arithmetic.rb +6/-6
lib/sequel/extensions/migration.rb +14/-17
lib/sequel/extensions/pg_enum.rb +1/-1
lib/sequel/model/associations.rb +1/-1
lib/sequel/plugins/dirty.rb +5/-2
lib/sequel/plugins/mssql_optimistic_locking.rb +1/-1
lib/sequel/plugins/pg_xmin_optimistic_locking.rb +1/-1
lib/sequel/plugins/serialization.rb +10/-1
lib/sequel/version.rb +1/-1
DIFFERENT extra_rdoc_files:
5.101.0->5.103.0:
* Changed:
MIT-LICENSE +1/-1 |
Contributor
|
Contributor
gem compare --diff sequel 5.101.0 5.103.0Compared versions: ["5.101.0", "5.103.0"]
DIFFERENT files:
5.101.0->5.103.0:
* Added:
lib/sequel/extensions/connection_checkout_event_callback.rb
--- /tmp/20260402-1788-vo1hb3 2026-04-02 05:27:31.338442940 +0000
+++ /tmp/d20260402-1788-zxlrvp/sequel-5.103.0/lib/sequel/extensions/connection_checkout_event_callback.rb 2026-04-02 05:27:31.307442764 +0000
@@ -0,0 +1,151 @@
+# frozen-string-literal: true
+#
+# The connection_checkout_event_callback extension modifies a database's
+# connection pool to allow for a checkout event callback. This callback is
+# called with the following arguments:
+#
+# :immediately_available :: Connection immediately available and returned
+# :not_immediately_available :: Connection not immediately available
+# :new_connection :: New connection created and returned
+# Float :: Number of seconds waiting to acquire a connection
+#
+# This is a low-level extension that allows for building telemetry
+# information. It doesn't implement any telemetry reporting itself. The
+# main reason for recording this information is to use it to determine the
+# appropriate size for the connection pool. Having too large a connection
+# pool can waste resources, while having too small a connection pool can
+# result in substantial time to check out a connection. In general, you
+# want to use as small a pool as possible while keeping the time to
+# checkout a connection low.
+#
+# To use the connection checkout event callback, you must first load the
+# extension:
+#
+# DB.extension(:connection_checkout_event_callback)
+#
+# By default, an empty proc is used as the callback so that loading the
+# support doesn't break anything. If you are using the extension, you
+# should set the callback at some point during application startup:
+#
+# DB.pool.on_checkout_event = proc do |event|
+# # ...
+# end
+#
+# When using the sharded connection pool, the callback is also
+# passed a second argument, the requested server shard (generally a
+# symbol), allowing for collection of per-shard telemetry:
+#
+# DB.pool.on_checkout_event = proc do |event, server|
+# # ...
+# end
+#
+# Note that the callback may be called currently by multiple threads.
+# You should use some form of concurrency control inside the callback,
+# such as a mutex or queue.
+#
+# Below is a brief example of usage to determine the percentage of
+# connection requests where a connection was immediately available:
+#
+# mutex = Mutex.new
+# total = immediates = 0
+#
+# DB.pool.on_checkout_event = proc do |event|
+# case event
+# when :immediately_available
+# mutex.synchronize do
+# total += 1
+# immediates += 1
+# end
+# when :not_immediately_available
+# mutex.synchronize do
+# total += 1
+# end
+# end
+# end
+#
+# immediate_percentage = lambda do
+# mutex.synchronize do
+# 100.0 * immediates / total
+# end
+# end
+#
+# Note that this extension only works with the timed_queue
+# and sharded_timed_queue connection pools (the default
+# connection pools when using Ruby 3.2+).
+#
+# Related modules: Sequel::ConnectionCheckoutEventCallbacks::TimedQueue,
+# Sequel::ConnectionCheckoutEventCallbacks::ShardedTimedQueue
+
+#
+module Sequel
+ module ConnectionCheckoutEventCallbacks
+ module TimedQueue
+ # The callback that is called with connection checkout events.
+ attr_accessor :on_checkout_event
+
+ private
+
+ def available
+ conn = super
+ @on_checkout_event.call(conn ? :immediately_available : :not_immediately_available)
+ conn
+ end
+
+ def try_make_new
+ conn = super
+ @on_checkout_event.call(:new_connection) if conn
+ conn
+ end
+
+ def wait_until_available
+ timer = Sequel.start_timer
+ conn = super
+ @on_checkout_event.call(Sequel.elapsed_seconds_since(timer))
+ conn
+ end
+ end
+
+ module ShardedTimedQueue
+ # The callback that is called with connection checkout events.
+ attr_accessor :on_checkout_event
+
+ private
+
+ def available(queue, server)
+ conn = super
+ @on_checkout_event.call(conn ? :immediately_available : :not_immediately_available, server)
+ conn
+ end
+
+ def try_make_new(server)
+ conn = super
+ @on_checkout_event.call(:new_connection, server) if conn
+ conn
+ end
+
+ def wait_until_available(queue, server)
+ timer = Sequel.start_timer
+ conn = super
+ @on_checkout_event.call(Sequel.elapsed_seconds_since(timer), server)
+ conn
+ end
+ end
+ end
+
+ default_callback = proc{}
+
+ Database.register_extension(:connection_checkout_event_callback) do |db|
+ pool = db.pool
+
+ case pool.pool_type
+ when :timed_queue
+ db.pool.extend(ConnectionCheckoutEventCallbacks::TimedQueue)
+ when :sharded_timed_queue
+ db.pool.extend(ConnectionCheckoutEventCallbacks::ShardedTimedQueue)
+ else
+ raise Error, "the connection_checkout_event_callback extension is only supported when using a timed_queue connection pool"
+ end
+
+ pool.on_checkout_event ||= default_callback
+ end
+end
lib/sequel/extensions/lit_require_frozen.rb
--- /tmp/20260402-1788-j04tp7 2026-04-02 05:27:31.341442957 +0000
+++ /tmp/d20260402-1788-zxlrvp/sequel-5.103.0/lib/sequel/extensions/lit_require_frozen.rb 2026-04-02 05:27:31.310442781 +0000
@@ -0,0 +1,131 @@
+# frozen-string-literal: true
+#
+# The lit_require_frozen extension disallows the use of unfrozen strings
+# as literal strings in database and dataset methods. If you try to use an
+# unfrozen string as a literal string for a dataset using this extension,
+# an exception will be raised.
+#
+# While this works for all Ruby versions, it is designed for use on Ruby 3+
+# where all files are using the frozen-string-literal magic comment. In this
+# case, uninterpolated literal strings are frozen, but interpolated strings
+# are not frozen. This allows you to catch potentially dangerous code:
+#
+# # Probably safe, no exception raised
+# DB["SELECT * FROM t WHERE c > :v", v: user_provided_string)
+#
+# # Potentially unsafe, raises Sequel::LitRequireFrozen::Error
+# DB["SELECT * FROM t WHERE c > '#{user_provided_string}'"]
+#
+# The assumption made is that a frozen string is unlikely to contain unsafe
+# input, while an unfrozen string has potentially been interpolated and may
+# contain unsafe input.
+#
+# This disallows the the following cases:
+#
+# * Sequel::LiteralString instances that are unfrozen and are not based on a
+# frozen string
+# * Sequel::SQL::PlaceholderLiteralString instances when the placeholder string
+# is not frozen
+# * Unfrozen strings passed to Database#<< or #[] or Dataset#with_sql
+#
+# To use this extension, load it into the database:
+#
+# DB.extension :lit_require_frozen
+#
+# It can also be loaded into individual datasets:
+#
+# ds = DB[:t].extension(:lit_require_frozen)
+#
+# Assuming you have good test coverage, it is recommended to only load
+# this extension when testing.
+#
+# Related module: Sequel::LitRequireFrozen
+
+#
+module Sequel
+ class LiteralString
+ # The string used when creating the literal string (first argument to
+ # Sequel::LiteralString.new). This may be nil if no string was provided,
+ # or if the litral string was created before this extension was required.
+ attr_reader :source
+
+ def initialize(*a)
+ @source = a.first
+ super
+ end
+ # :nocov:
+ ruby2_keywords :initialize if respond_to?(:ruby2_keywords, true)
+ # :nocov:
+ end
+
+ module LitRequireFrozen
+ # Error class raised for using unfrozen literal string.
+ class Error < Sequel::Error
+ end
+
+ module DatabaseMethods
+ def self.extended(db)
+ db.extend_datasets(DatasetMethods)
+ end
+
+ # Check given SQL is frozen before running it.
+ def run(sql, opts=OPTS)
+ @default_dataset.with_sql(sql)
+ super
+ end
+ end
+
+ module DatasetMethods
+ # Check given SQL is not an unfrozen string.
+ def with_sql(sql, *args)
+ _check_unfrozen_literal_string(sql)
+ super
+ end
+
+ # Check that placeholder string is frozen (or all entries
+ # in placeholder array are frozen).
+ def placeholder_literal_string_sql_append(sql, pls)
+ str = pls.str
+
+ if str.is_a?(Array)
+ str.each do |s|
+ _check_unfrozen_literal_string(s)
+ end
+ else
+ _check_unfrozen_literal_string(str)
+ end
+
+ super
+ end
+
+ private
+
+ # Base method that other methods used to check for whether a string should be allowed
+ # as literal SQL. Allows non-strings as well as frozen strings.
+ def _check_unfrozen_literal_string(str)
+ return if !str.is_a?(String) || str.frozen?
+
+ if str.is_a?(LiteralString)
+ _check_unfrozen_literal_string(str.source)
+ else
+ raise Error, "cannot treat unfrozen string as literal SQL: #{str.inspect}"
+ end
+ end
+
+ # Check literal strings appended to SQL.
+ def literal_literal_string_append(sql, v)
+ _check_unfrozen_literal_string(v)
+ super
+ end
+
+ # Check static SQL is not frozen.
+ def static_sql(sql)
+ _check_unfrozen_literal_string(sql)
+ super
+ end
+ end
+ end
+
+ Dataset.register_extension(:lit_require_frozen, LitRequireFrozen::DatasetMethods)
+ Database.register_extension(:lit_require_frozen, LitRequireFrozen::DatabaseMethods)
+end
* Changed:
MIT-LICENSE
--- /tmp/d20260402-1788-zxlrvp/sequel-5.101.0/MIT-LICENSE 2026-04-02 05:27:31.255442469 +0000
+++ /tmp/d20260402-1788-zxlrvp/sequel-5.103.0/MIT-LICENSE 2026-04-02 05:27:31.293442685 +0000
@@ -2 +2 @@
-Copyright (c) 2008-2023 Jeremy Evans
+Copyright (c) 2008-2026 Jeremy Evans and contributors
lib/sequel/adapters/jdbc/derby.rb
--- /tmp/d20260402-1788-zxlrvp/sequel-5.101.0/lib/sequel/adapters/jdbc/derby.rb 2026-04-02 05:27:31.257442481 +0000
+++ /tmp/d20260402-1788-zxlrvp/sequel-5.103.0/lib/sequel/adapters/jdbc/derby.rb 2026-04-02 05:27:31.295442696 +0000
@@ -2,0 +3,2 @@
+# SEQUEL6: Remove
+
lib/sequel/adapters/jdbc/h2.rb
--- /tmp/d20260402-1788-zxlrvp/sequel-5.101.0/lib/sequel/adapters/jdbc/h2.rb 2026-04-02 05:27:31.257442481 +0000
+++ /tmp/d20260402-1788-zxlrvp/sequel-5.103.0/lib/sequel/adapters/jdbc/h2.rb 2026-04-02 05:27:31.295442696 +0000
@@ -21 +21 @@
- run("COMMIT TRANSACTION #{transaction_id}", opts)
+ run("COMMIT TRANSACTION #{transaction_id}".freeze, opts)
@@ -39 +39 @@
- run("ROLLBACK TRANSACTION #{transaction_id}", opts)
+ run("ROLLBACK TRANSACTION #{transaction_id}".freeze, opts)
lib/sequel/adapters/postgres.rb
--- /tmp/d20260402-1788-zxlrvp/sequel-5.101.0/lib/sequel/adapters/postgres.rb 2026-04-02 05:27:31.260442498 +0000
+++ /tmp/d20260402-1788-zxlrvp/sequel-5.103.0/lib/sequel/adapters/postgres.rb 2026-04-02 05:27:31.297442707 +0000
@@ -730 +730 @@
- LiteralString.new("#{prepared_arg_placeholder}#{i}")
+ LiteralString.new("#{prepared_arg_placeholder}#{i}".freeze)
lib/sequel/adapters/shared/mssql.rb
--- /tmp/d20260402-1788-zxlrvp/sequel-5.101.0/lib/sequel/adapters/shared/mssql.rb 2026-04-02 05:27:31.260442498 +0000
+++ /tmp/d20260402-1788-zxlrvp/sequel-5.103.0/lib/sequel/adapters/shared/mssql.rb 2026-04-02 05:27:31.298442713 +0000
@@ -109 +109 @@
- sql = "DECLARE #{declarations.join(', ')}; EXECUTE @RC = #{name} #{values.join(', ')}; SELECT #{names.join(', ')}"
+ sql = "DECLARE #{declarations.join(', ')}; EXECUTE @RC = #{name} #{values.join(', ')}; SELECT #{names.join(', ')}".freeze
@@ -403 +403 @@
- run(ds.into(name).sql)
+ run(ds.into(name).sql.freeze)
@@ -881 +881 @@
- sql = multi_insert_sql(columns, values)[0]
+ sql = multi_insert_sql(columns, values)[0].freeze
lib/sequel/adapters/shared/mysql.rb
--- /tmp/d20260402-1788-zxlrvp/sequel-5.101.0/lib/sequel/adapters/shared/mysql.rb 2026-04-02 05:27:31.261442503 +0000
+++ /tmp/d20260402-1788-zxlrvp/sequel-5.103.0/lib/sequel/adapters/shared/mysql.rb 2026-04-02 05:27:31.298442713 +0000
@@ -43 +43 @@
- run("XA COMMIT #{literal(transaction_id)}", opts)
+ run("XA COMMIT #{literal(transaction_id)}".freeze, opts)
@@ -106 +106 @@
- metadata_dataset.with_sql(sql).each do |r|
+ metadata_dataset.with_sql(sql.freeze).each do |r|
@@ -118 +118 @@
- run("XA ROLLBACK #{literal(transaction_id)}", opts)
+ run("XA ROLLBACK #{literal(transaction_id)}".freeze, opts)
@@ -783 +783,2 @@
- ds = db.send(:metadata_dataset).with_sql(((opts[:extended] && (db.mariadb? || db.server_version < 50700)) ? 'EXPLAIN EXTENDED ' : 'EXPLAIN ') + select_sql).naked
+ sql = ((opts[:extended] && (db.mariadb? || db.server_version < 50700)) ? 'EXPLAIN EXTENDED ' : 'EXPLAIN ') + select_sql
+ ds = db.send(:metadata_dataset).with_sql(sql.freeze).naked
lib/sequel/adapters/shared/postgres.rb
--- /tmp/d20260402-1788-zxlrvp/sequel-5.101.0/lib/sequel/adapters/shared/postgres.rb 2026-04-02 05:27:31.262442509 +0000
+++ /tmp/d20260402-1788-zxlrvp/sequel-5.103.0/lib/sequel/adapters/shared/postgres.rb 2026-04-02 05:27:31.299442719 +0000
@@ -342 +342 @@
- run("COMMIT PREPARED #{literal(transaction_id)}", opts)
+ run("COMMIT PREPARED #{literal(transaction_id)}".freeze, opts)
@@ -419 +419 @@
- run("ALTER TABLE #{quote_schema_table(table)} ALTER COLUMN #{quote_identifier(column)} DROP DEFAULT", server_hash)
+ run("ALTER TABLE #{quote_schema_table(table)} ALTER COLUMN #{quote_identifier(column)} DROP DEFAULT".freeze, server_hash)
@@ -456 +456 @@
- self << create_function_sql(name, definition, opts)
+ self << create_function_sql(name, definition, opts).freeze
@@ -467 +467 @@
- self << create_language_sql(name, opts)
+ self << create_language_sql(name, opts).freeze
@@ -476 +476 @@
- self << create_schema_sql(name, opts)
+ self << create_schema_sql(name, opts).freeze
@@ -512 +512 @@
- self << create_trigger_sql(table, name, function, opts)
+ self << create_trigger_sql(table, name, function, opts).freeze
@@ -545 +545 @@
- run "DO #{"LANGUAGE #{literal(language.to_s)} " if language}#{literal(code)}"
+ run "DO #{"LANGUAGE #{literal(language.to_s)} " if language}#{literal(code)}".freeze
@@ -555 +555 @@
- self << drop_function_sql(name, opts)
+ self << drop_function_sql(name, opts).freeze
@@ -564 +564 @@
- self << drop_language_sql(name, opts)
+ self << drop_language_sql(name, opts).freeze
@@ -573 +573 @@
- self << drop_schema_sql(name, opts)
+ self << drop_schema_sql(name, opts).freeze
@@ -584 +584 @@
- self << drop_trigger_sql(table, name, opts)
+ self << drop_trigger_sql(table, name, opts).freeze
@@ -748 +748 @@
- self << rename_schema_sql(name, new_name)
+ self << rename_schema_sql(name, new_name).freeze
@@ -759 +759 @@
- run "REFRESH MATERIALIZED VIEW#{' CONCURRENTLY' if opts[:concurrently]} #{quote_schema_table(name)}"
+ run "REFRESH MATERIALIZED VIEW#{' CONCURRENTLY' if opts[:concurrently]} #{quote_schema_table(name)}".freeze
@@ -772 +772 @@
- seq_ds = metadata_dataset.from(:pg_sequence).where(:seqrelid=>regclass_oid(LiteralString.new(seq)))
+ seq_ds = metadata_dataset.from(:pg_sequence).where(:seqrelid=>regclass_oid(LiteralString.new(seq.freeze)))
@@ -787 +787 @@
- run("ROLLBACK PREPARED #{literal(transaction_id)}", opts)
+ run("ROLLBACK PREPARED #{literal(transaction_id)}".freeze, opts)
@@ -1472 +1472 @@
- cols[-1] = Sequel.lit("PERIOD #{quote_identifier(cols[-1])}")
+ cols[-1] = Sequel.lit("PERIOD #{quote_identifier(cols[-1])}".freeze)
lib/sequel/adapters/shared/sqlite.rb
--- /tmp/d20260402-1788-zxlrvp/sequel-5.101.0/lib/sequel/adapters/shared/sqlite.rb 2026-04-02 05:27:31.262442509 +0000
+++ /tmp/d20260402-1788-zxlrvp/sequel-5.103.0/lib/sequel/adapters/shared/sqlite.rb 2026-04-02 05:27:31.300442724 +0000
@@ -198 +198 @@
- metadata_dataset.with_sql("PRAGMA table_#{'x' if sqlite_version > 33100}info(?)", input_identifier_meth(opts[:dataset]).call(table_name))
+ metadata_dataset.with_sql("PRAGMA table_#{'x' if sqlite_version > 33100}info(?)".freeze, input_identifier_meth(opts[:dataset]).call(table_name))
@@ -410 +410 @@
- c[:default] = LiteralString.new(c[:default]) if c[:default]
+ c[:default] = LiteralString.new(c[:default]).freeze if c[:default]
@@ -687 +687 @@
- ds = db.send(:metadata_dataset).clone(:sql=>"EXPLAIN #{select_sql}")
+ ds = db.send(:metadata_dataset).clone(:sql=>"EXPLAIN #{select_sql}".freeze)
lib/sequel/adapters/sqlite.rb
--- /tmp/d20260402-1788-zxlrvp/sequel-5.101.0/lib/sequel/adapters/sqlite.rb 2026-04-02 05:27:31.262442509 +0000
+++ /tmp/d20260402-1788-zxlrvp/sequel-5.103.0/lib/sequel/adapters/sqlite.rb 2026-04-02 05:27:31.300442724 +0000
@@ -391 +391 @@
- LiteralString.new("#{prepared_arg_placeholder}#{k.to_s.gsub('.', '__')}")
+ LiteralString.new("#{prepared_arg_placeholder}#{k.to_s.gsub('.', '__')}".freeze)
lib/sequel/adapters/tinytds.rb
--- /tmp/d20260402-1788-zxlrvp/sequel-5.101.0/lib/sequel/adapters/tinytds.rb 2026-04-02 05:27:31.262442509 +0000
+++ /tmp/d20260402-1788-zxlrvp/sequel-5.103.0/lib/sequel/adapters/tinytds.rb 2026-04-02 05:27:31.300442724 +0000
@@ -208 +208 @@
- LiteralString.new("@#{k.to_s.gsub('.', '__')}")
+ LiteralString.new("@#{k.to_s.gsub('.', '__')}".freeze)
lib/sequel/connection_pool.rb
--- /tmp/d20260402-1788-zxlrvp/sequel-5.101.0/lib/sequel/connection_pool.rb 2026-04-02 05:27:31.264442520 +0000
+++ /tmp/d20260402-1788-zxlrvp/sequel-5.103.0/lib/sequel/connection_pool.rb 2026-04-02 05:27:31.301442730 +0000
@@ -133,0 +134,6 @@
+ # Only for use by extension that need to disconnect a connection inside acquire.
+ # Takes the connection and any arguments accepted by acquire.
+ def disconnect_acquired_connection(conn, *)
+ disconnect_connection(conn)
+ end
+
lib/sequel/connection_pool/sharded_timed_queue.rb
--- /tmp/d20260402-1788-zxlrvp/sequel-5.101.0/lib/sequel/connection_pool/sharded_timed_queue.rb 2026-04-02 05:27:31.264442520 +0000
+++ /tmp/d20260402-1788-zxlrvp/sequel-5.103.0/lib/sequel/connection_pool/sharded_timed_queue.rb 2026-04-02 05:27:31.302442736 +0000
@@ -74 +74 @@
- break unless (conn = queue.pop(timeout: 0)) && !conns[conn]
+ break unless (conn = available(queue, server)) && !conns[conn]
@@ -94 +94 @@
- # and then the method will only disconnect connectsion from those specified shards.
+ # and then the method will only disconnect connections from those specified shards.
@@ -98 +98,3 @@
- while conn = queue.pop(timeout: 0)
+ nconns = 0
+ while conn = available(queue, server)
+ nconns += 1
@@ -101 +103 @@
- fill_queue(server)
+ fill_queue(server, nconns)
@@ -135 +137 @@
- fill_queue(server)
+ fill_queue(server, 1)
@@ -170 +172 @@
- while conn = queue.pop(timeout: 0)
+ while conn = available(queue, server)
@@ -227,0 +230,6 @@
+ # Only for use by extension that need to disconnect a connection inside acquire.
+ # Takes the connection and any arguments accepted by acquire.
+ def disconnect_acquired_connection(conn, _, server)
+ disconnect_pool_connection(conn, server)
+ end
+
@@ -247 +255,4 @@
- def fill_queue(server)
+ #
+ # nconns specifies the maximum number of connections to add, which should
+ # be the number of connections that were disconnected.
+ def fill_queue(server, nconns)
@@ -249 +260 @@
- if queue.num_waiting > 0
+ if nconns > 0 && queue.num_waiting > 0
@@ -251 +262,2 @@
- while queue.num_waiting > 0 && (conn = try_make_new(server))
+ while nconns > 0 && queue.num_waiting > 0 && (conn = try_make_new(server))
+ nconns -= 1
@@ -300 +312 @@
- fill_queue(server)
+ fill_queue(server, to_disconnect.size)
@@ -314 +326 @@
- if conn = queue.pop(timeout: 0) || try_make_new(server) || queue.pop(timeout: @timeout)
+ if conn = available(queue, server) || try_make_new(server) || wait_until_available(queue, server)
@@ -319,0 +332,13 @@
+ end
+
+ # Return the next connection in the pool if there is one available. Returns nil
+ # if no connection is currently available.
+ def available(queue, _server)
+ queue.pop(timeout: 0)
+ end
+
+ # Return the next connection in the pool if there is one available. If not, wait
+ # until the timeout for a connection to become available. If there is still no
+ # available connection, return nil.
+ def wait_until_available(queue, _server)
+ queue.pop(timeout: @timeout)
lib/sequel/connection_pool/timed_queue.rb
--- /tmp/d20260402-1788-zxlrvp/sequel-5.101.0/lib/sequel/connection_pool/timed_queue.rb 2026-04-02 05:27:31.265442526 +0000
+++ /tmp/d20260402-1788-zxlrvp/sequel-5.103.0/lib/sequel/connection_pool/timed_queue.rb 2026-04-02 05:27:31.302442736 +0000
@@ -45 +45 @@
- break unless (conn = @queue.pop(timeout: 0)) && !conns[conn]
+ break unless (conn = available) && !conns[conn]
@@ -62 +62,3 @@
- while conn = @queue.pop(timeout: 0)
+ nconns = 0
+ while conn = available
+ nconns += 1
@@ -65 +67 @@
- fill_queue
+ fill_queue(nconns)
@@ -97 +99 @@
- fill_queue
+ fill_queue(1)
@@ -159,2 +161,5 @@
- def fill_queue
- if @queue.num_waiting > 0
+ #
+ # nconns specifies the maximum number of connections to add, which should
+ # be the number of connections that were disconnected.
+ def fill_queue(nconns)
+ if nconns > 0 && @queue.num_waiting > 0
@@ -162 +167 @@
- while @queue.num_waiting > 0 && (conn = try_make_new)
+ while nconns > 0 && @queue.num_waiting > 0 && (conn = try_make_new)
@@ -210 +215 @@
- fill_queue
+ fill_queue(to_disconnect.size)
@@ -223 +228 @@
- if conn = @queue.pop(timeout: 0) || try_make_new || @queue.pop(timeout: @timeout)
+ if conn = available || try_make_new || wait_until_available
@@ -228,0 +234,13 @@
+ end
+
+ # Return the next connection in the pool if there is one available. Returns nil
+ # if no connection is currently available.
+ def available
+ @queue.pop(timeout: 0)
+ end
+
+ # Return the next connection in the pool if there is one available. If not, wait
+ # until the timeout for a connection to become available. If there is still no
+ # available connection, return nil.
+ def wait_until_available
+ @queue.pop(timeout: @timeout)
lib/sequel/database/schema_generator.rb
--- /tmp/d20260402-1788-zxlrvp/sequel-5.101.0/lib/sequel/database/schema_generator.rb 2026-04-02 05:27:31.266442532 +0000
+++ /tmp/d20260402-1788-zxlrvp/sequel-5.103.0/lib/sequel/database/schema_generator.rb 2026-04-02 05:27:31.303442741 +0000
@@ -5,0 +6,27 @@
+ module ColumnOptionMerger
+ private
+
+ # Merge given options into the column's default options. For backwards compatibility,
+ # the options take priority, but in cases where the option value overrides the argument
+ # value, and the values are different, we warn as this is likely to be an error in the
+ # code.
+ def _merge_column_options(defaults, opts)
+ defaults.merge!(opts) do |k, defv, v|
+ unless defv == v
+ # :nocov:
+ if RUBY_VERSION >= "3.2"
+ # :nocov:
+ caller_loc = Thread.each_caller_location do |loc|
+ break loc unless loc.path == __FILE__
+ end
+ caller_loc &&= "#{caller_loc.path}:#{caller_loc.lineno}: "
+ end
+ warn("#{caller_loc}#{k.inspect} option value (#{v.inspect}) overrides argument value (#{defv.inspect})")
+ end
+
+ v
+ end
+ end
+ end
+ private_constant :ColumnOptionMerger
+
@@ -19,0 +47,2 @@
+ include ColumnOptionMerger
+
@@ -176 +205 @@
- columns << {:name => name, :type => type}.merge!(opts)
+ columns << _merge_column_options({:name => name, :type => type}, opts)
@@ -182 +211 @@
-
+
@@ -249 +278 @@
- column(name, Integer, opts)
+ column(name, opts.fetch(:type, Integer), opts)
@@ -431,0 +461,2 @@
+ include ColumnOptionMerger
+
@@ -457 +488 @@
- op = {:op => :add_column, :name => name, :type => type}.merge!(opts)
+ op = _merge_column_options({:op => :add_column, :name => name, :type => type}, opts)
@@ -522 +553 @@
- add_column(name, Integer, {:table=>table}.merge!(opts))
+ add_column(name, opts.fetch(:type, Integer), {:table=>table}.merge!(opts))
lib/sequel/database/schema_methods.rb
--- /tmp/d20260402-1788-zxlrvp/sequel-5.101.0/lib/sequel/database/schema_methods.rb 2026-04-02 05:27:31.266442532 +0000
+++ /tmp/d20260402-1788-zxlrvp/sequel-5.103.0/lib/sequel/database/schema_methods.rb 2026-04-02 05:27:31.304442747 +0000
@@ -822 +822 @@
- run(create_table_as_sql(name, sql, options))
+ run(create_table_as_sql(name, sql, options).freeze)
lib/sequel/dataset/placeholder_literalizer.rb
--- /tmp/d20260402-1788-zxlrvp/sequel-5.101.0/lib/sequel/dataset/placeholder_literalizer.rb 2026-04-02 05:27:31.268442543 +0000
+++ /tmp/d20260402-1788-zxlrvp/sequel-5.103.0/lib/sequel/dataset/placeholder_literalizer.rb 2026-04-02 05:27:31.305442753 +0000
@@ -119,0 +120,2 @@
+ frags.each(&:freeze)
+ frags.freeze
@@ -127,0 +130 @@
+ ds.opts[:sql].freeze
lib/sequel/dataset/prepared_statements.rb
--- /tmp/d20260402-1788-zxlrvp/sequel-5.101.0/lib/sequel/dataset/prepared_statements.rb 2026-04-02 05:27:31.268442543 +0000
+++ /tmp/d20260402-1788-zxlrvp/sequel-5.103.0/lib/sequel/dataset/prepared_statements.rb 2026-04-02 05:27:31.305442753 +0000
@@ -57 +57 @@
- sql = prepared_sql
+ sql = prepared_sql.freeze
@@ -226 +226 @@
- with_sql(prepared_sql)
+ with_sql(prepared_sql.freeze)
@@ -290 +290 @@
- sql = literal(Sequel::SQL::PlaceholderLiteralString.new(@opts[:prepared_sql_frags], @opts[:bind_arguments], false))
+ sql = literal(Sequel::SQL::PlaceholderLiteralString.new(@opts[:prepared_sql_frags], @opts[:bind_arguments], false)).freeze
@@ -322,0 +323,3 @@
+ frags.freeze
+ frags.each(&:freeze)
+ prepared_sql.freeze
@@ -412 +415 @@
- sql = ps.prepared_sql
+ sql = ps.prepared_sql.freeze
lib/sequel/dataset/query.rb
--- /tmp/d20260402-1788-zxlrvp/sequel-5.101.0/lib/sequel/dataset/query.rb 2026-04-02 05:27:31.268442543 +0000
+++ /tmp/d20260402-1788-zxlrvp/sequel-5.103.0/lib/sequel/dataset/query.rb 2026-04-02 05:27:31.305442753 +0000
@@ -1304 +1304 @@
- sql = public_send(sql, *args)
+ sql = public_send(sql, *args).freeze
@@ -1477 +1477,4 @@
-
+
+ PAREN_WRAPPER = ["(".freeze, ")".freeze].freeze
+ private_constant :PAREN_WRAPPER
+
@@ -1498 +1501 @@
- LiteralString.new("(#{expr})")
+ SQL::PlaceholderLiteralString.new(PAREN_WRAPPER, [expr])
lib/sequel/dataset/sql.rb
--- /tmp/d20260402-1788-zxlrvp/sequel-5.101.0/lib/sequel/dataset/sql.rb 2026-04-02 05:27:31.269442549 +0000
+++ /tmp/d20260402-1788-zxlrvp/sequel-5.103.0/lib/sequel/dataset/sql.rb 2026-04-02 05:27:31.306442758 +0000
@@ -56 +56 @@
- sql << v
+ literal_literal_string_append(sql, v)
@@ -1424,0 +1425,5 @@
+ end
+
+ # Append string to SQL string.
+ def literal_literal_string_append(sql, v)
+ sql << v
lib/sequel/extensions/connection_expiration.rb
--- /tmp/d20260402-1788-zxlrvp/sequel-5.101.0/lib/sequel/extensions/connection_expiration.rb 2026-04-02 05:27:31.270442554 +0000
+++ /tmp/d20260402-1788-zxlrvp/sequel-5.103.0/lib/sequel/extensions/connection_expiration.rb 2026-04-02 05:27:31.307442764 +0000
@@ -94 +94 @@
- disconnect_connection(conn)
+ disconnect_acquired_connection(conn, *a)
lib/sequel/extensions/connection_validator.rb
--- /tmp/d20260402-1788-zxlrvp/sequel-5.101.0/lib/sequel/extensions/connection_validator.rb 2026-04-02 05:27:31.270442554 +0000
+++ /tmp/d20260402-1788-zxlrvp/sequel-5.103.0/lib/sequel/extensions/connection_validator.rb 2026-04-02 05:27:31.307442764 +0000
@@ -121 +121 @@
- disconnect_connection(conn)
+ disconnect_acquired_connection(conn, *a)
lib/sequel/extensions/dataset_run.rb
--- /tmp/d20260402-1788-zxlrvp/sequel-5.101.0/lib/sequel/extensions/dataset_run.rb 2026-04-02 05:27:31.271442560 +0000
+++ /tmp/d20260402-1788-zxlrvp/sequel-5.103.0/lib/sequel/extensions/dataset_run.rb 2026-04-02 05:27:31.308442770 +0000
@@ -33 +33 @@
- db.run(sql, :server=>server)
+ db.run(sql.freeze, :server=>server)
@@ -35 +35 @@
- db.run(sql)
+ db.run(sql.freeze)
lib/sequel/extensions/date_arithmetic.rb
--- /tmp/d20260402-1788-zxlrvp/sequel-5.101.0/lib/sequel/extensions/date_arithmetic.rb 2026-04-02 05:27:31.271442560 +0000
+++ /tmp/d20260402-1788-zxlrvp/sequel-5.103.0/lib/sequel/extensions/date_arithmetic.rb 2026-04-02 05:27:31.308442770 +0000
@@ -85,2 +85,2 @@
- MYSQL_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s.upcase[0...-1]).freeze}).freeze
- MSSQL_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s[0...-1]).freeze}).freeze
+ MYSQL_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s.upcase[0...-1].freeze).freeze}).freeze
+ MSSQL_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s[0...-1].freeze).freeze}).freeze
@@ -88 +88 @@
- DERBY_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit("SQL_TSI_#{s.to_s.upcase[0...-1]}").freeze}).freeze
+ DERBY_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit("SQL_TSI_#{s.to_s.upcase[0...-1]}".freeze).freeze}).freeze
@@ -90 +90 @@
- DB2_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s).freeze}).freeze
+ DB2_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s.freeze).freeze}).freeze
@@ -110 +110 @@
- placeholder << "#{', ' unless placeholder.empty?}#{sql_unit} := "
+ placeholder << "#{', ' unless placeholder.empty?}#{sql_unit} := ".freeze
@@ -159 +159 @@
- expr = Sequel.lit(["{fn timestampadd(#{sql_unit}, ", ", timestamp(", "))}"], value, expr)
+ expr = Sequel.lit(["{fn timestampadd(#{sql_unit}, ".freeze, ", timestamp(", "))}"], value, expr)
lib/sequel/extensions/migration.rb
--- /tmp/d20260402-1788-zxlrvp/sequel-5.101.0/lib/sequel/extensions/migration.rb 2026-04-02 05:27:31.273442571 +0000
+++ /tmp/d20260402-1788-zxlrvp/sequel-5.103.0/lib/sequel/extensions/migration.rb 2026-04-02 05:27:31.310442781 +0000
@@ -189,16 +189,13 @@
- begin
- instance_exec(&block)
- rescue
- just_raise = true
- end
- if just_raise
- Proc.new{raise Sequel::Error, "irreversible migration method used in #{block.source_location.first}, you may need to write your own down method"}
- else
- actions = @actions.reverse
- Proc.new do
- actions.each do |a|
- pr = a.last.is_a?(Proc) ? a.pop : nil
- # Allow calling private methods as the reversing methods are private
- send(*a, &pr)
- end
- end
+ instance_exec(&block)
+ rescue NoMethodError => e
+ Proc.new{raise Sequel::Error, "irreversible migration method \"#{e.name}\" used in #{block.source_location.first}, you may need to write your own down method"}
+ rescue => e
+ Proc.new{raise Sequel::Error, "unable to reverse migration due to #{e.class} in #{block.source_location.first}, you may need to write your own down method"}
+ else
+ actions = @actions.reverse
+ Proc.new do
+ actions.each do |a|
+ pr = a.last.is_a?(Proc) ? a.pop : nil
+ # Allow calling private methods as the reversing methods are private
+ send(*a, &pr)
+ end
@@ -273 +270 @@
- raise if args.first.is_a?(Array)
+ super if args.first.is_a?(Array)
lib/sequel/extensions/pg_enum.rb
--- /tmp/d20260402-1788-zxlrvp/sequel-5.101.0/lib/sequel/extensions/pg_enum.rb 2026-04-02 05:27:31.274442577 +0000
+++ /tmp/d20260402-1788-zxlrvp/sequel-5.103.0/lib/sequel/extensions/pg_enum.rb 2026-04-02 05:27:31.312442792 +0000
@@ -130 +130 @@
- run(sql)
+ run(sql.freeze)
lib/sequel/model/associations.rb
--- /tmp/d20260402-1788-zxlrvp/sequel-5.101.0/lib/sequel/model/associations.rb 2026-04-02 05:27:31.280442611 +0000
+++ /tmp/d20260402-1788-zxlrvp/sequel-5.103.0/lib/sequel/model/associations.rb 2026-04-02 05:27:31.319442832 +0000
@@ -323 +323 @@
- objects.concat(ds.with_sql(sql).to_a)
+ objects.concat(ds.with_sql(sql.freeze).to_a)
lib/sequel/plugins/dirty.rb
--- /tmp/d20260402-1788-zxlrvp/sequel-5.101.0/lib/sequel/plugins/dirty.rb 2026-04-02 05:27:31.285442639 +0000
+++ /tmp/d20260402-1788-zxlrvp/sequel-5.103.0/lib/sequel/plugins/dirty.rb 2026-04-02 05:27:31.323442855 +0000
@@ -237,2 +237,5 @@
- check_missing_initial_value(column)
- iv[column] = get_column_value(column)
+ if db_schema[column]
+ check_missing_initial_value(column)
+ iv[column] = get_column_value(column)
+ end
+
lib/sequel/plugins/mssql_optimistic_locking.rb
--- /tmp/d20260402-1788-zxlrvp/sequel-5.101.0/lib/sequel/plugins/mssql_optimistic_locking.rb 2026-04-02 05:27:31.287442651 +0000
+++ /tmp/d20260402-1788-zxlrvp/sequel-5.103.0/lib/sequel/plugins/mssql_optimistic_locking.rb 2026-04-02 05:27:31.326442872 +0000
@@ -58 +58 @@
- rows = ds.clone(ds.send(:default_server_opts, :sql=>ds.output(nil, [Sequel[:inserted][lc]]).update_sql(columns))).all
+ rows = ds.clone(ds.send(:default_server_opts, :sql=>ds.output(nil, [Sequel[:inserted][lc]]).update_sql(columns).freeze)).all
lib/sequel/plugins/pg_xmin_optimistic_locking.rb
--- /tmp/d20260402-1788-zxlrvp/sequel-5.101.0/lib/sequel/plugins/pg_xmin_optimistic_locking.rb 2026-04-02 05:27:31.288442656 +0000
+++ /tmp/d20260402-1788-zxlrvp/sequel-5.103.0/lib/sequel/plugins/pg_xmin_optimistic_locking.rb 2026-04-02 05:27:31.327442878 +0000
@@ -102 +102 @@
- rows = ds.clone(ds.send(:default_server_opts, :sql=>ds.returning(:xmin).update_sql(columns))).all
+ rows = ds.clone(ds.send(:default_server_opts, :sql=>ds.returning(:xmin).update_sql(columns).freeze)).all
lib/sequel/plugins/serialization.rb
--- /tmp/d20260402-1788-zxlrvp/sequel-5.101.0/lib/sequel/plugins/serialization.rb 2026-04-02 05:27:31.289442662 +0000
+++ /tmp/d20260402-1788-zxlrvp/sequel-5.103.0/lib/sequel/plugins/serialization.rb 2026-04-02 05:27:31.328442883 +0000
@@ -32,0 +33,9 @@
+ # Note that use of an unsafe serialization method can result in an attack vector
+ # (potentially allowing remote code execution) if an attacker has the ability to
+ # store data directly in the underlying column. This would affect the marshal
+ # serialization format, and on older versions of Ruby, potentially the yaml and
+ # json serialization formats as well. It can also affect custom formats. You
+ # should ensure that attackers do not have access to store data directly in the
+ # underlying column when using this plugin (especially when using an unsafe
+ # serialization method).
+ #
@@ -100 +109 @@
- v = v.unpack('m')[0] unless v[0..1] == "\x04\x08"
+ v = v.unpack('m')[0] unless v.start_with?("\x04\x08")
lib/sequel/version.rb
--- /tmp/d20260402-1788-zxlrvp/sequel-5.101.0/lib/sequel/version.rb 2026-04-02 05:27:31.293442685 +0000
+++ /tmp/d20260402-1788-zxlrvp/sequel-5.103.0/lib/sequel/version.rb 2026-04-02 05:27:31.338442940 +0000
@@ -9 +9 @@
- MINOR = 101
+ MINOR = 103 |
Contributor
gem compare --diff sequel 5.101.0 5.103.0Compared versions: ["5.101.0", "5.103.0"]
DIFFERENT files:
5.101.0->5.103.0:
* Added:
lib/sequel/extensions/connection_checkout_event_callback.rb
--- /tmp/20260402-1780-rtz2uk 2026-04-02 05:27:33.787614807 +0000
+++ /tmp/d20260402-1780-vsixvj/sequel-5.103.0/lib/sequel/extensions/connection_checkout_event_callback.rb 2026-04-02 05:27:33.760614830 +0000
@@ -0,0 +1,151 @@
+# frozen-string-literal: true
+#
+# The connection_checkout_event_callback extension modifies a database's
+# connection pool to allow for a checkout event callback. This callback is
+# called with the following arguments:
+#
+# :immediately_available :: Connection immediately available and returned
+# :not_immediately_available :: Connection not immediately available
+# :new_connection :: New connection created and returned
+# Float :: Number of seconds waiting to acquire a connection
+#
+# This is a low-level extension that allows for building telemetry
+# information. It doesn't implement any telemetry reporting itself. The
+# main reason for recording this information is to use it to determine the
+# appropriate size for the connection pool. Having too large a connection
+# pool can waste resources, while having too small a connection pool can
+# result in substantial time to check out a connection. In general, you
+# want to use as small a pool as possible while keeping the time to
+# checkout a connection low.
+#
+# To use the connection checkout event callback, you must first load the
+# extension:
+#
+# DB.extension(:connection_checkout_event_callback)
+#
+# By default, an empty proc is used as the callback so that loading the
+# support doesn't break anything. If you are using the extension, you
+# should set the callback at some point during application startup:
+#
+# DB.pool.on_checkout_event = proc do |event|
+# # ...
+# end
+#
+# When using the sharded connection pool, the callback is also
+# passed a second argument, the requested server shard (generally a
+# symbol), allowing for collection of per-shard telemetry:
+#
+# DB.pool.on_checkout_event = proc do |event, server|
+# # ...
+# end
+#
+# Note that the callback may be called currently by multiple threads.
+# You should use some form of concurrency control inside the callback,
+# such as a mutex or queue.
+#
+# Below is a brief example of usage to determine the percentage of
+# connection requests where a connection was immediately available:
+#
+# mutex = Mutex.new
+# total = immediates = 0
+#
+# DB.pool.on_checkout_event = proc do |event|
+# case event
+# when :immediately_available
+# mutex.synchronize do
+# total += 1
+# immediates += 1
+# end
+# when :not_immediately_available
+# mutex.synchronize do
+# total += 1
+# end
+# end
+# end
+#
+# immediate_percentage = lambda do
+# mutex.synchronize do
+# 100.0 * immediates / total
+# end
+# end
+#
+# Note that this extension only works with the timed_queue
+# and sharded_timed_queue connection pools (the default
+# connection pools when using Ruby 3.2+).
+#
+# Related modules: Sequel::ConnectionCheckoutEventCallbacks::TimedQueue,
+# Sequel::ConnectionCheckoutEventCallbacks::ShardedTimedQueue
+
+#
+module Sequel
+ module ConnectionCheckoutEventCallbacks
+ module TimedQueue
+ # The callback that is called with connection checkout events.
+ attr_accessor :on_checkout_event
+
+ private
+
+ def available
+ conn = super
+ @on_checkout_event.call(conn ? :immediately_available : :not_immediately_available)
+ conn
+ end
+
+ def try_make_new
+ conn = super
+ @on_checkout_event.call(:new_connection) if conn
+ conn
+ end
+
+ def wait_until_available
+ timer = Sequel.start_timer
+ conn = super
+ @on_checkout_event.call(Sequel.elapsed_seconds_since(timer))
+ conn
+ end
+ end
+
+ module ShardedTimedQueue
+ # The callback that is called with connection checkout events.
+ attr_accessor :on_checkout_event
+
+ private
+
+ def available(queue, server)
+ conn = super
+ @on_checkout_event.call(conn ? :immediately_available : :not_immediately_available, server)
+ conn
+ end
+
+ def try_make_new(server)
+ conn = super
+ @on_checkout_event.call(:new_connection, server) if conn
+ conn
+ end
+
+ def wait_until_available(queue, server)
+ timer = Sequel.start_timer
+ conn = super
+ @on_checkout_event.call(Sequel.elapsed_seconds_since(timer), server)
+ conn
+ end
+ end
+ end
+
+ default_callback = proc{}
+
+ Database.register_extension(:connection_checkout_event_callback) do |db|
+ pool = db.pool
+
+ case pool.pool_type
+ when :timed_queue
+ db.pool.extend(ConnectionCheckoutEventCallbacks::TimedQueue)
+ when :sharded_timed_queue
+ db.pool.extend(ConnectionCheckoutEventCallbacks::ShardedTimedQueue)
+ else
+ raise Error, "the connection_checkout_event_callback extension is only supported when using a timed_queue connection pool"
+ end
+
+ pool.on_checkout_event ||= default_callback
+ end
+end
lib/sequel/extensions/lit_require_frozen.rb
--- /tmp/20260402-1780-xe8vbo 2026-04-02 05:27:33.790614805 +0000
+++ /tmp/d20260402-1780-vsixvj/sequel-5.103.0/lib/sequel/extensions/lit_require_frozen.rb 2026-04-02 05:27:33.764614827 +0000
@@ -0,0 +1,131 @@
+# frozen-string-literal: true
+#
+# The lit_require_frozen extension disallows the use of unfrozen strings
+# as literal strings in database and dataset methods. If you try to use an
+# unfrozen string as a literal string for a dataset using this extension,
+# an exception will be raised.
+#
+# While this works for all Ruby versions, it is designed for use on Ruby 3+
+# where all files are using the frozen-string-literal magic comment. In this
+# case, uninterpolated literal strings are frozen, but interpolated strings
+# are not frozen. This allows you to catch potentially dangerous code:
+#
+# # Probably safe, no exception raised
+# DB["SELECT * FROM t WHERE c > :v", v: user_provided_string)
+#
+# # Potentially unsafe, raises Sequel::LitRequireFrozen::Error
+# DB["SELECT * FROM t WHERE c > '#{user_provided_string}'"]
+#
+# The assumption made is that a frozen string is unlikely to contain unsafe
+# input, while an unfrozen string has potentially been interpolated and may
+# contain unsafe input.
+#
+# This disallows the the following cases:
+#
+# * Sequel::LiteralString instances that are unfrozen and are not based on a
+# frozen string
+# * Sequel::SQL::PlaceholderLiteralString instances when the placeholder string
+# is not frozen
+# * Unfrozen strings passed to Database#<< or #[] or Dataset#with_sql
+#
+# To use this extension, load it into the database:
+#
+# DB.extension :lit_require_frozen
+#
+# It can also be loaded into individual datasets:
+#
+# ds = DB[:t].extension(:lit_require_frozen)
+#
+# Assuming you have good test coverage, it is recommended to only load
+# this extension when testing.
+#
+# Related module: Sequel::LitRequireFrozen
+
+#
+module Sequel
+ class LiteralString
+ # The string used when creating the literal string (first argument to
+ # Sequel::LiteralString.new). This may be nil if no string was provided,
+ # or if the litral string was created before this extension was required.
+ attr_reader :source
+
+ def initialize(*a)
+ @source = a.first
+ super
+ end
+ # :nocov:
+ ruby2_keywords :initialize if respond_to?(:ruby2_keywords, true)
+ # :nocov:
+ end
+
+ module LitRequireFrozen
+ # Error class raised for using unfrozen literal string.
+ class Error < Sequel::Error
+ end
+
+ module DatabaseMethods
+ def self.extended(db)
+ db.extend_datasets(DatasetMethods)
+ end
+
+ # Check given SQL is frozen before running it.
+ def run(sql, opts=OPTS)
+ @default_dataset.with_sql(sql)
+ super
+ end
+ end
+
+ module DatasetMethods
+ # Check given SQL is not an unfrozen string.
+ def with_sql(sql, *args)
+ _check_unfrozen_literal_string(sql)
+ super
+ end
+
+ # Check that placeholder string is frozen (or all entries
+ # in placeholder array are frozen).
+ def placeholder_literal_string_sql_append(sql, pls)
+ str = pls.str
+
+ if str.is_a?(Array)
+ str.each do |s|
+ _check_unfrozen_literal_string(s)
+ end
+ else
+ _check_unfrozen_literal_string(str)
+ end
+
+ super
+ end
+
+ private
+
+ # Base method that other methods used to check for whether a string should be allowed
+ # as literal SQL. Allows non-strings as well as frozen strings.
+ def _check_unfrozen_literal_string(str)
+ return if !str.is_a?(String) || str.frozen?
+
+ if str.is_a?(LiteralString)
+ _check_unfrozen_literal_string(str.source)
+ else
+ raise Error, "cannot treat unfrozen string as literal SQL: #{str.inspect}"
+ end
+ end
+
+ # Check literal strings appended to SQL.
+ def literal_literal_string_append(sql, v)
+ _check_unfrozen_literal_string(v)
+ super
+ end
+
+ # Check static SQL is not frozen.
+ def static_sql(sql)
+ _check_unfrozen_literal_string(sql)
+ super
+ end
+ end
+ end
+
+ Dataset.register_extension(:lit_require_frozen, LitRequireFrozen::DatasetMethods)
+ Database.register_extension(:lit_require_frozen, LitRequireFrozen::DatabaseMethods)
+end
* Changed:
MIT-LICENSE
--- /tmp/d20260402-1780-vsixvj/sequel-5.101.0/MIT-LICENSE 2026-04-02 05:27:33.704614878 +0000
+++ /tmp/d20260402-1780-vsixvj/sequel-5.103.0/MIT-LICENSE 2026-04-02 05:27:33.746614842 +0000
@@ -2 +2 @@
-Copyright (c) 2008-2023 Jeremy Evans
+Copyright (c) 2008-2026 Jeremy Evans and contributors
lib/sequel/adapters/jdbc/derby.rb
--- /tmp/d20260402-1780-vsixvj/sequel-5.101.0/lib/sequel/adapters/jdbc/derby.rb 2026-04-02 05:27:33.706614876 +0000
+++ /tmp/d20260402-1780-vsixvj/sequel-5.103.0/lib/sequel/adapters/jdbc/derby.rb 2026-04-02 05:27:33.747614841 +0000
@@ -2,0 +3,2 @@
+# SEQUEL6: Remove
+
lib/sequel/adapters/jdbc/h2.rb
--- /tmp/d20260402-1780-vsixvj/sequel-5.101.0/lib/sequel/adapters/jdbc/h2.rb 2026-04-02 05:27:33.706614876 +0000
+++ /tmp/d20260402-1780-vsixvj/sequel-5.103.0/lib/sequel/adapters/jdbc/h2.rb 2026-04-02 05:27:33.747614841 +0000
@@ -21 +21 @@
- run("COMMIT TRANSACTION #{transaction_id}", opts)
+ run("COMMIT TRANSACTION #{transaction_id}".freeze, opts)
@@ -39 +39 @@
- run("ROLLBACK TRANSACTION #{transaction_id}", opts)
+ run("ROLLBACK TRANSACTION #{transaction_id}".freeze, opts)
lib/sequel/adapters/postgres.rb
--- /tmp/d20260402-1780-vsixvj/sequel-5.101.0/lib/sequel/adapters/postgres.rb 2026-04-02 05:27:33.709614873 +0000
+++ /tmp/d20260402-1780-vsixvj/sequel-5.103.0/lib/sequel/adapters/postgres.rb 2026-04-02 05:27:33.750614838 +0000
@@ -730 +730 @@
- LiteralString.new("#{prepared_arg_placeholder}#{i}")
+ LiteralString.new("#{prepared_arg_placeholder}#{i}".freeze)
lib/sequel/adapters/shared/mssql.rb
--- /tmp/d20260402-1780-vsixvj/sequel-5.101.0/lib/sequel/adapters/shared/mssql.rb 2026-04-02 05:27:33.710614873 +0000
+++ /tmp/d20260402-1780-vsixvj/sequel-5.103.0/lib/sequel/adapters/shared/mssql.rb 2026-04-02 05:27:33.750614838 +0000
@@ -109 +109 @@
- sql = "DECLARE #{declarations.join(', ')}; EXECUTE @RC = #{name} #{values.join(', ')}; SELECT #{names.join(', ')}"
+ sql = "DECLARE #{declarations.join(', ')}; EXECUTE @RC = #{name} #{values.join(', ')}; SELECT #{names.join(', ')}".freeze
@@ -403 +403 @@
- run(ds.into(name).sql)
+ run(ds.into(name).sql.freeze)
@@ -881 +881 @@
- sql = multi_insert_sql(columns, values)[0]
+ sql = multi_insert_sql(columns, values)[0].freeze
lib/sequel/adapters/shared/mysql.rb
--- /tmp/d20260402-1780-vsixvj/sequel-5.101.0/lib/sequel/adapters/shared/mysql.rb 2026-04-02 05:27:33.710614873 +0000
+++ /tmp/d20260402-1780-vsixvj/sequel-5.103.0/lib/sequel/adapters/shared/mysql.rb 2026-04-02 05:27:33.751614838 +0000
@@ -43 +43 @@
- run("XA COMMIT #{literal(transaction_id)}", opts)
+ run("XA COMMIT #{literal(transaction_id)}".freeze, opts)
@@ -106 +106 @@
- metadata_dataset.with_sql(sql).each do |r|
+ metadata_dataset.with_sql(sql.freeze).each do |r|
@@ -118 +118 @@
- run("XA ROLLBACK #{literal(transaction_id)}", opts)
+ run("XA ROLLBACK #{literal(transaction_id)}".freeze, opts)
@@ -783 +783,2 @@
- ds = db.send(:metadata_dataset).with_sql(((opts[:extended] && (db.mariadb? || db.server_version < 50700)) ? 'EXPLAIN EXTENDED ' : 'EXPLAIN ') + select_sql).naked
+ sql = ((opts[:extended] && (db.mariadb? || db.server_version < 50700)) ? 'EXPLAIN EXTENDED ' : 'EXPLAIN ') + select_sql
+ ds = db.send(:metadata_dataset).with_sql(sql.freeze).naked
lib/sequel/adapters/shared/postgres.rb
--- /tmp/d20260402-1780-vsixvj/sequel-5.101.0/lib/sequel/adapters/shared/postgres.rb 2026-04-02 05:27:33.711614872 +0000
+++ /tmp/d20260402-1780-vsixvj/sequel-5.103.0/lib/sequel/adapters/shared/postgres.rb 2026-04-02 05:27:33.752614837 +0000
@@ -342 +342 @@
- run("COMMIT PREPARED #{literal(transaction_id)}", opts)
+ run("COMMIT PREPARED #{literal(transaction_id)}".freeze, opts)
@@ -419 +419 @@
- run("ALTER TABLE #{quote_schema_table(table)} ALTER COLUMN #{quote_identifier(column)} DROP DEFAULT", server_hash)
+ run("ALTER TABLE #{quote_schema_table(table)} ALTER COLUMN #{quote_identifier(column)} DROP DEFAULT".freeze, server_hash)
@@ -456 +456 @@
- self << create_function_sql(name, definition, opts)
+ self << create_function_sql(name, definition, opts).freeze
@@ -467 +467 @@
- self << create_language_sql(name, opts)
+ self << create_language_sql(name, opts).freeze
@@ -476 +476 @@
- self << create_schema_sql(name, opts)
+ self << create_schema_sql(name, opts).freeze
@@ -512 +512 @@
- self << create_trigger_sql(table, name, function, opts)
+ self << create_trigger_sql(table, name, function, opts).freeze
@@ -545 +545 @@
- run "DO #{"LANGUAGE #{literal(language.to_s)} " if language}#{literal(code)}"
+ run "DO #{"LANGUAGE #{literal(language.to_s)} " if language}#{literal(code)}".freeze
@@ -555 +555 @@
- self << drop_function_sql(name, opts)
+ self << drop_function_sql(name, opts).freeze
@@ -564 +564 @@
- self << drop_language_sql(name, opts)
+ self << drop_language_sql(name, opts).freeze
@@ -573 +573 @@
- self << drop_schema_sql(name, opts)
+ self << drop_schema_sql(name, opts).freeze
@@ -584 +584 @@
- self << drop_trigger_sql(table, name, opts)
+ self << drop_trigger_sql(table, name, opts).freeze
@@ -748 +748 @@
- self << rename_schema_sql(name, new_name)
+ self << rename_schema_sql(name, new_name).freeze
@@ -759 +759 @@
- run "REFRESH MATERIALIZED VIEW#{' CONCURRENTLY' if opts[:concurrently]} #{quote_schema_table(name)}"
+ run "REFRESH MATERIALIZED VIEW#{' CONCURRENTLY' if opts[:concurrently]} #{quote_schema_table(name)}".freeze
@@ -772 +772 @@
- seq_ds = metadata_dataset.from(:pg_sequence).where(:seqrelid=>regclass_oid(LiteralString.new(seq)))
+ seq_ds = metadata_dataset.from(:pg_sequence).where(:seqrelid=>regclass_oid(LiteralString.new(seq.freeze)))
@@ -787 +787 @@
- run("ROLLBACK PREPARED #{literal(transaction_id)}", opts)
+ run("ROLLBACK PREPARED #{literal(transaction_id)}".freeze, opts)
@@ -1472 +1472 @@
- cols[-1] = Sequel.lit("PERIOD #{quote_identifier(cols[-1])}")
+ cols[-1] = Sequel.lit("PERIOD #{quote_identifier(cols[-1])}".freeze)
lib/sequel/adapters/shared/sqlite.rb
--- /tmp/d20260402-1780-vsixvj/sequel-5.101.0/lib/sequel/adapters/shared/sqlite.rb 2026-04-02 05:27:33.712614871 +0000
+++ /tmp/d20260402-1780-vsixvj/sequel-5.103.0/lib/sequel/adapters/shared/sqlite.rb 2026-04-02 05:27:33.752614837 +0000
@@ -198 +198 @@
- metadata_dataset.with_sql("PRAGMA table_#{'x' if sqlite_version > 33100}info(?)", input_identifier_meth(opts[:dataset]).call(table_name))
+ metadata_dataset.with_sql("PRAGMA table_#{'x' if sqlite_version > 33100}info(?)".freeze, input_identifier_meth(opts[:dataset]).call(table_name))
@@ -410 +410 @@
- c[:default] = LiteralString.new(c[:default]) if c[:default]
+ c[:default] = LiteralString.new(c[:default]).freeze if c[:default]
@@ -687 +687 @@
- ds = db.send(:metadata_dataset).clone(:sql=>"EXPLAIN #{select_sql}")
+ ds = db.send(:metadata_dataset).clone(:sql=>"EXPLAIN #{select_sql}".freeze)
lib/sequel/adapters/sqlite.rb
--- /tmp/d20260402-1780-vsixvj/sequel-5.101.0/lib/sequel/adapters/sqlite.rb 2026-04-02 05:27:33.712614871 +0000
+++ /tmp/d20260402-1780-vsixvj/sequel-5.103.0/lib/sequel/adapters/sqlite.rb 2026-04-02 05:27:33.753614836 +0000
@@ -391 +391 @@
- LiteralString.new("#{prepared_arg_placeholder}#{k.to_s.gsub('.', '__')}")
+ LiteralString.new("#{prepared_arg_placeholder}#{k.to_s.gsub('.', '__')}".freeze)
lib/sequel/adapters/tinytds.rb
--- /tmp/d20260402-1780-vsixvj/sequel-5.101.0/lib/sequel/adapters/tinytds.rb 2026-04-02 05:27:33.712614871 +0000
+++ /tmp/d20260402-1780-vsixvj/sequel-5.103.0/lib/sequel/adapters/tinytds.rb 2026-04-02 05:27:33.753614836 +0000
@@ -208 +208 @@
- LiteralString.new("@#{k.to_s.gsub('.', '__')}")
+ LiteralString.new("@#{k.to_s.gsub('.', '__')}".freeze)
lib/sequel/connection_pool.rb
--- /tmp/d20260402-1780-vsixvj/sequel-5.101.0/lib/sequel/connection_pool.rb 2026-04-02 05:27:33.713614870 +0000
+++ /tmp/d20260402-1780-vsixvj/sequel-5.103.0/lib/sequel/connection_pool.rb 2026-04-02 05:27:33.754614835 +0000
@@ -133,0 +134,6 @@
+ # Only for use by extension that need to disconnect a connection inside acquire.
+ # Takes the connection and any arguments accepted by acquire.
+ def disconnect_acquired_connection(conn, *)
+ disconnect_connection(conn)
+ end
+
lib/sequel/connection_pool/sharded_timed_queue.rb
--- /tmp/d20260402-1780-vsixvj/sequel-5.101.0/lib/sequel/connection_pool/sharded_timed_queue.rb 2026-04-02 05:27:33.714614869 +0000
+++ /tmp/d20260402-1780-vsixvj/sequel-5.103.0/lib/sequel/connection_pool/sharded_timed_queue.rb 2026-04-02 05:27:33.754614835 +0000
@@ -74 +74 @@
- break unless (conn = queue.pop(timeout: 0)) && !conns[conn]
+ break unless (conn = available(queue, server)) && !conns[conn]
@@ -94 +94 @@
- # and then the method will only disconnect connectsion from those specified shards.
+ # and then the method will only disconnect connections from those specified shards.
@@ -98 +98,3 @@
- while conn = queue.pop(timeout: 0)
+ nconns = 0
+ while conn = available(queue, server)
+ nconns += 1
@@ -101 +103 @@
- fill_queue(server)
+ fill_queue(server, nconns)
@@ -135 +137 @@
- fill_queue(server)
+ fill_queue(server, 1)
@@ -170 +172 @@
- while conn = queue.pop(timeout: 0)
+ while conn = available(queue, server)
@@ -227,0 +230,6 @@
+ # Only for use by extension that need to disconnect a connection inside acquire.
+ # Takes the connection and any arguments accepted by acquire.
+ def disconnect_acquired_connection(conn, _, server)
+ disconnect_pool_connection(conn, server)
+ end
+
@@ -247 +255,4 @@
- def fill_queue(server)
+ #
+ # nconns specifies the maximum number of connections to add, which should
+ # be the number of connections that were disconnected.
+ def fill_queue(server, nconns)
@@ -249 +260 @@
- if queue.num_waiting > 0
+ if nconns > 0 && queue.num_waiting > 0
@@ -251 +262,2 @@
- while queue.num_waiting > 0 && (conn = try_make_new(server))
+ while nconns > 0 && queue.num_waiting > 0 && (conn = try_make_new(server))
+ nconns -= 1
@@ -300 +312 @@
- fill_queue(server)
+ fill_queue(server, to_disconnect.size)
@@ -314 +326 @@
- if conn = queue.pop(timeout: 0) || try_make_new(server) || queue.pop(timeout: @timeout)
+ if conn = available(queue, server) || try_make_new(server) || wait_until_available(queue, server)
@@ -319,0 +332,13 @@
+ end
+
+ # Return the next connection in the pool if there is one available. Returns nil
+ # if no connection is currently available.
+ def available(queue, _server)
+ queue.pop(timeout: 0)
+ end
+
+ # Return the next connection in the pool if there is one available. If not, wait
+ # until the timeout for a connection to become available. If there is still no
+ # available connection, return nil.
+ def wait_until_available(queue, _server)
+ queue.pop(timeout: @timeout)
lib/sequel/connection_pool/timed_queue.rb
--- /tmp/d20260402-1780-vsixvj/sequel-5.101.0/lib/sequel/connection_pool/timed_queue.rb 2026-04-02 05:27:33.714614869 +0000
+++ /tmp/d20260402-1780-vsixvj/sequel-5.103.0/lib/sequel/connection_pool/timed_queue.rb 2026-04-02 05:27:33.755614834 +0000
@@ -45 +45 @@
- break unless (conn = @queue.pop(timeout: 0)) && !conns[conn]
+ break unless (conn = available) && !conns[conn]
@@ -62 +62,3 @@
- while conn = @queue.pop(timeout: 0)
+ nconns = 0
+ while conn = available
+ nconns += 1
@@ -65 +67 @@
- fill_queue
+ fill_queue(nconns)
@@ -97 +99 @@
- fill_queue
+ fill_queue(1)
@@ -159,2 +161,5 @@
- def fill_queue
- if @queue.num_waiting > 0
+ #
+ # nconns specifies the maximum number of connections to add, which should
+ # be the number of connections that were disconnected.
+ def fill_queue(nconns)
+ if nconns > 0 && @queue.num_waiting > 0
@@ -162 +167 @@
- while @queue.num_waiting > 0 && (conn = try_make_new)
+ while nconns > 0 && @queue.num_waiting > 0 && (conn = try_make_new)
@@ -210 +215 @@
- fill_queue
+ fill_queue(to_disconnect.size)
@@ -223 +228 @@
- if conn = @queue.pop(timeout: 0) || try_make_new || @queue.pop(timeout: @timeout)
+ if conn = available || try_make_new || wait_until_available
@@ -228,0 +234,13 @@
+ end
+
+ # Return the next connection in the pool if there is one available. Returns nil
+ # if no connection is currently available.
+ def available
+ @queue.pop(timeout: 0)
+ end
+
+ # Return the next connection in the pool if there is one available. If not, wait
+ # until the timeout for a connection to become available. If there is still no
+ # available connection, return nil.
+ def wait_until_available
+ @queue.pop(timeout: @timeout)
lib/sequel/database/schema_generator.rb
--- /tmp/d20260402-1780-vsixvj/sequel-5.101.0/lib/sequel/database/schema_generator.rb 2026-04-02 05:27:33.716614867 +0000
+++ /tmp/d20260402-1780-vsixvj/sequel-5.103.0/lib/sequel/database/schema_generator.rb 2026-04-02 05:27:33.756614833 +0000
@@ -5,0 +6,27 @@
+ module ColumnOptionMerger
+ private
+
+ # Merge given options into the column's default options. For backwards compatibility,
+ # the options take priority, but in cases where the option value overrides the argument
+ # value, and the values are different, we warn as this is likely to be an error in the
+ # code.
+ def _merge_column_options(defaults, opts)
+ defaults.merge!(opts) do |k, defv, v|
+ unless defv == v
+ # :nocov:
+ if RUBY_VERSION >= "3.2"
+ # :nocov:
+ caller_loc = Thread.each_caller_location do |loc|
+ break loc unless loc.path == __FILE__
+ end
+ caller_loc &&= "#{caller_loc.path}:#{caller_loc.lineno}: "
+ end
+ warn("#{caller_loc}#{k.inspect} option value (#{v.inspect}) overrides argument value (#{defv.inspect})")
+ end
+
+ v
+ end
+ end
+ end
+ private_constant :ColumnOptionMerger
+
@@ -19,0 +47,2 @@
+ include ColumnOptionMerger
+
@@ -176 +205 @@
- columns << {:name => name, :type => type}.merge!(opts)
+ columns << _merge_column_options({:name => name, :type => type}, opts)
@@ -182 +211 @@
-
+
@@ -249 +278 @@
- column(name, Integer, opts)
+ column(name, opts.fetch(:type, Integer), opts)
@@ -431,0 +461,2 @@
+ include ColumnOptionMerger
+
@@ -457 +488 @@
- op = {:op => :add_column, :name => name, :type => type}.merge!(opts)
+ op = _merge_column_options({:op => :add_column, :name => name, :type => type}, opts)
@@ -522 +553 @@
- add_column(name, Integer, {:table=>table}.merge!(opts))
+ add_column(name, opts.fetch(:type, Integer), {:table=>table}.merge!(opts))
lib/sequel/database/schema_methods.rb
--- /tmp/d20260402-1780-vsixvj/sequel-5.101.0/lib/sequel/database/schema_methods.rb 2026-04-02 05:27:33.716614867 +0000
+++ /tmp/d20260402-1780-vsixvj/sequel-5.103.0/lib/sequel/database/schema_methods.rb 2026-04-02 05:27:33.757614833 +0000
@@ -822 +822 @@
- run(create_table_as_sql(name, sql, options))
+ run(create_table_as_sql(name, sql, options).freeze)
lib/sequel/dataset/placeholder_literalizer.rb
--- /tmp/d20260402-1780-vsixvj/sequel-5.101.0/lib/sequel/dataset/placeholder_literalizer.rb 2026-04-02 05:27:33.718614866 +0000
+++ /tmp/d20260402-1780-vsixvj/sequel-5.103.0/lib/sequel/dataset/placeholder_literalizer.rb 2026-04-02 05:27:33.758614832 +0000
@@ -119,0 +120,2 @@
+ frags.each(&:freeze)
+ frags.freeze
@@ -127,0 +130 @@
+ ds.opts[:sql].freeze
lib/sequel/dataset/prepared_statements.rb
--- /tmp/d20260402-1780-vsixvj/sequel-5.101.0/lib/sequel/dataset/prepared_statements.rb 2026-04-02 05:27:33.718614866 +0000
+++ /tmp/d20260402-1780-vsixvj/sequel-5.103.0/lib/sequel/dataset/prepared_statements.rb 2026-04-02 05:27:33.758614832 +0000
@@ -57 +57 @@
- sql = prepared_sql
+ sql = prepared_sql.freeze
@@ -226 +226 @@
- with_sql(prepared_sql)
+ with_sql(prepared_sql.freeze)
@@ -290 +290 @@
- sql = literal(Sequel::SQL::PlaceholderLiteralString.new(@opts[:prepared_sql_frags], @opts[:bind_arguments], false))
+ sql = literal(Sequel::SQL::PlaceholderLiteralString.new(@opts[:prepared_sql_frags], @opts[:bind_arguments], false)).freeze
@@ -322,0 +323,3 @@
+ frags.freeze
+ frags.each(&:freeze)
+ prepared_sql.freeze
@@ -412 +415 @@
- sql = ps.prepared_sql
+ sql = ps.prepared_sql.freeze
lib/sequel/dataset/query.rb
--- /tmp/d20260402-1780-vsixvj/sequel-5.101.0/lib/sequel/dataset/query.rb 2026-04-02 05:27:33.718614866 +0000
+++ /tmp/d20260402-1780-vsixvj/sequel-5.103.0/lib/sequel/dataset/query.rb 2026-04-02 05:27:33.759614831 +0000
@@ -1304 +1304 @@
- sql = public_send(sql, *args)
+ sql = public_send(sql, *args).freeze
@@ -1477 +1477,4 @@
-
+
+ PAREN_WRAPPER = ["(".freeze, ")".freeze].freeze
+ private_constant :PAREN_WRAPPER
+
@@ -1498 +1501 @@
- LiteralString.new("(#{expr})")
+ SQL::PlaceholderLiteralString.new(PAREN_WRAPPER, [expr])
lib/sequel/dataset/sql.rb
--- /tmp/d20260402-1780-vsixvj/sequel-5.101.0/lib/sequel/dataset/sql.rb 2026-04-02 05:27:33.719614865 +0000
+++ /tmp/d20260402-1780-vsixvj/sequel-5.103.0/lib/sequel/dataset/sql.rb 2026-04-02 05:27:33.759614831 +0000
@@ -56 +56 @@
- sql << v
+ literal_literal_string_append(sql, v)
@@ -1424,0 +1425,5 @@
+ end
+
+ # Append string to SQL string.
+ def literal_literal_string_append(sql, v)
+ sql << v
lib/sequel/extensions/connection_expiration.rb
--- /tmp/d20260402-1780-vsixvj/sequel-5.101.0/lib/sequel/extensions/connection_expiration.rb 2026-04-02 05:27:33.721614863 +0000
+++ /tmp/d20260402-1780-vsixvj/sequel-5.103.0/lib/sequel/extensions/connection_expiration.rb 2026-04-02 05:27:33.761614829 +0000
@@ -94 +94 @@
- disconnect_connection(conn)
+ disconnect_acquired_connection(conn, *a)
lib/sequel/extensions/connection_validator.rb
--- /tmp/d20260402-1780-vsixvj/sequel-5.101.0/lib/sequel/extensions/connection_validator.rb 2026-04-02 05:27:33.721614863 +0000
+++ /tmp/d20260402-1780-vsixvj/sequel-5.103.0/lib/sequel/extensions/connection_validator.rb 2026-04-02 05:27:33.761614829 +0000
@@ -121 +121 @@
- disconnect_connection(conn)
+ disconnect_acquired_connection(conn, *a)
lib/sequel/extensions/dataset_run.rb
--- /tmp/d20260402-1780-vsixvj/sequel-5.101.0/lib/sequel/extensions/dataset_run.rb 2026-04-02 05:27:33.722614862 +0000
+++ /tmp/d20260402-1780-vsixvj/sequel-5.103.0/lib/sequel/extensions/dataset_run.rb 2026-04-02 05:27:33.762614828 +0000
@@ -33 +33 @@
- db.run(sql, :server=>server)
+ db.run(sql.freeze, :server=>server)
@@ -35 +35 @@
- db.run(sql)
+ db.run(sql.freeze)
lib/sequel/extensions/date_arithmetic.rb
--- /tmp/d20260402-1780-vsixvj/sequel-5.101.0/lib/sequel/extensions/date_arithmetic.rb 2026-04-02 05:27:33.722614862 +0000
+++ /tmp/d20260402-1780-vsixvj/sequel-5.103.0/lib/sequel/extensions/date_arithmetic.rb 2026-04-02 05:27:33.762614828 +0000
@@ -85,2 +85,2 @@
- MYSQL_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s.upcase[0...-1]).freeze}).freeze
- MSSQL_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s[0...-1]).freeze}).freeze
+ MYSQL_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s.upcase[0...-1].freeze).freeze}).freeze
+ MSSQL_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s[0...-1].freeze).freeze}).freeze
@@ -88 +88 @@
- DERBY_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit("SQL_TSI_#{s.to_s.upcase[0...-1]}").freeze}).freeze
+ DERBY_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit("SQL_TSI_#{s.to_s.upcase[0...-1]}".freeze).freeze}).freeze
@@ -90 +90 @@
- DB2_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s).freeze}).freeze
+ DB2_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s.freeze).freeze}).freeze
@@ -110 +110 @@
- placeholder << "#{', ' unless placeholder.empty?}#{sql_unit} := "
+ placeholder << "#{', ' unless placeholder.empty?}#{sql_unit} := ".freeze
@@ -159 +159 @@
- expr = Sequel.lit(["{fn timestampadd(#{sql_unit}, ", ", timestamp(", "))}"], value, expr)
+ expr = Sequel.lit(["{fn timestampadd(#{sql_unit}, ".freeze, ", timestamp(", "))}"], value, expr)
lib/sequel/extensions/migration.rb
--- /tmp/d20260402-1780-vsixvj/sequel-5.101.0/lib/sequel/extensions/migration.rb 2026-04-02 05:27:33.724614861 +0000
+++ /tmp/d20260402-1780-vsixvj/sequel-5.103.0/lib/sequel/extensions/migration.rb 2026-04-02 05:27:33.764614827 +0000
@@ -189,16 +189,13 @@
- begin
- instance_exec(&block)
- rescue
- just_raise = true
- end
- if just_raise
- Proc.new{raise Sequel::Error, "irreversible migration method used in #{block.source_location.first}, you may need to write your own down method"}
- else
- actions = @actions.reverse
- Proc.new do
- actions.each do |a|
- pr = a.last.is_a?(Proc) ? a.pop : nil
- # Allow calling private methods as the reversing methods are private
- send(*a, &pr)
- end
- end
+ instance_exec(&block)
+ rescue NoMethodError => e
+ Proc.new{raise Sequel::Error, "irreversible migration method \"#{e.name}\" used in #{block.source_location.first}, you may need to write your own down method"}
+ rescue => e
+ Proc.new{raise Sequel::Error, "unable to reverse migration due to #{e.class} in #{block.source_location.first}, you may need to write your own down method"}
+ else
+ actions = @actions.reverse
+ Proc.new do
+ actions.each do |a|
+ pr = a.last.is_a?(Proc) ? a.pop : nil
+ # Allow calling private methods as the reversing methods are private
+ send(*a, &pr)
+ end
@@ -273 +270 @@
- raise if args.first.is_a?(Array)
+ super if args.first.is_a?(Array)
lib/sequel/extensions/pg_enum.rb
--- /tmp/d20260402-1780-vsixvj/sequel-5.101.0/lib/sequel/extensions/pg_enum.rb 2026-04-02 05:27:33.725614860 +0000
+++ /tmp/d20260402-1780-vsixvj/sequel-5.103.0/lib/sequel/extensions/pg_enum.rb 2026-04-02 05:27:33.765614826 +0000
@@ -130 +130 @@
- run(sql)
+ run(sql.freeze)
lib/sequel/model/associations.rb
--- /tmp/d20260402-1780-vsixvj/sequel-5.101.0/lib/sequel/model/associations.rb 2026-04-02 05:27:33.732614854 +0000
+++ /tmp/d20260402-1780-vsixvj/sequel-5.103.0/lib/sequel/model/associations.rb 2026-04-02 05:27:33.772614820 +0000
@@ -323 +323 @@
- objects.concat(ds.with_sql(sql).to_a)
+ objects.concat(ds.with_sql(sql.freeze).to_a)
lib/sequel/plugins/dirty.rb
--- /tmp/d20260402-1780-vsixvj/sequel-5.101.0/lib/sequel/plugins/dirty.rb 2026-04-02 05:27:33.737614850 +0000
+++ /tmp/d20260402-1780-vsixvj/sequel-5.103.0/lib/sequel/plugins/dirty.rb 2026-04-02 05:27:33.778614815 +0000
@@ -237,2 +237,5 @@
- check_missing_initial_value(column)
- iv[column] = get_column_value(column)
+ if db_schema[column]
+ check_missing_initial_value(column)
+ iv[column] = get_column_value(column)
+ end
+
lib/sequel/plugins/mssql_optimistic_locking.rb
--- /tmp/d20260402-1780-vsixvj/sequel-5.101.0/lib/sequel/plugins/mssql_optimistic_locking.rb 2026-04-02 05:27:33.739614848 +0000
+++ /tmp/d20260402-1780-vsixvj/sequel-5.103.0/lib/sequel/plugins/mssql_optimistic_locking.rb 2026-04-02 05:27:33.780614813 +0000
@@ -58 +58 @@
- rows = ds.clone(ds.send(:default_server_opts, :sql=>ds.output(nil, [Sequel[:inserted][lc]]).update_sql(columns))).all
+ rows = ds.clone(ds.send(:default_server_opts, :sql=>ds.output(nil, [Sequel[:inserted][lc]]).update_sql(columns).freeze)).all
lib/sequel/plugins/pg_xmin_optimistic_locking.rb
--- /tmp/d20260402-1780-vsixvj/sequel-5.101.0/lib/sequel/plugins/pg_xmin_optimistic_locking.rb 2026-04-02 05:27:33.740614847 +0000
+++ /tmp/d20260402-1780-vsixvj/sequel-5.103.0/lib/sequel/plugins/pg_xmin_optimistic_locking.rb 2026-04-02 05:27:33.781614812 +0000
@@ -102 +102 @@
- rows = ds.clone(ds.send(:default_server_opts, :sql=>ds.returning(:xmin).update_sql(columns))).all
+ rows = ds.clone(ds.send(:default_server_opts, :sql=>ds.returning(:xmin).update_sql(columns).freeze)).all
lib/sequel/plugins/serialization.rb
--- /tmp/d20260402-1780-vsixvj/sequel-5.101.0/lib/sequel/plugins/serialization.rb 2026-04-02 05:27:33.741614846 +0000
+++ /tmp/d20260402-1780-vsixvj/sequel-5.103.0/lib/sequel/plugins/serialization.rb 2026-04-02 05:27:33.782614811 +0000
@@ -32,0 +33,9 @@
+ # Note that use of an unsafe serialization method can result in an attack vector
+ # (potentially allowing remote code execution) if an attacker has the ability to
+ # store data directly in the underlying column. This would affect the marshal
+ # serialization format, and on older versions of Ruby, potentially the yaml and
+ # json serialization formats as well. It can also affect custom formats. You
+ # should ensure that attackers do not have access to store data directly in the
+ # underlying column when using this plugin (especially when using an unsafe
+ # serialization method).
+ #
@@ -100 +109 @@
- v = v.unpack('m')[0] unless v[0..1] == "\x04\x08"
+ v = v.unpack('m')[0] unless v.start_with?("\x04\x08")
lib/sequel/version.rb
--- /tmp/d20260402-1780-vsixvj/sequel-5.101.0/lib/sequel/version.rb 2026-04-02 05:27:33.745614843 +0000
+++ /tmp/d20260402-1780-vsixvj/sequel-5.103.0/lib/sequel/version.rb 2026-04-02 05:27:33.787614807 +0000
@@ -9 +9 @@
- MINOR = 101
+ MINOR = 103 |
Contributor
gem compare sequel 5.101.0 5.103.0Compared versions: ["5.101.0", "5.103.0"]
DIFFERENT version:
5.101.0: 5.101.0
5.103.0: 5.103.0
DIFFERENT files:
5.101.0->5.103.0:
* Added:
lib/sequel/extensions/connection_checkout_event_callback.rb +151/-0
lib/sequel/extensions/lit_require_frozen.rb +131/-0
* Changed:
MIT-LICENSE +1/-1
lib/sequel/adapters/jdbc/derby.rb +2/-0
lib/sequel/adapters/jdbc/h2.rb +2/-2
lib/sequel/adapters/postgres.rb +1/-1
lib/sequel/adapters/shared/mssql.rb +3/-3
lib/sequel/adapters/shared/mysql.rb +5/-4
lib/sequel/adapters/shared/postgres.rb +16/-16
lib/sequel/adapters/shared/sqlite.rb +3/-3
lib/sequel/adapters/sqlite.rb +1/-1
lib/sequel/adapters/tinytds.rb +1/-1
lib/sequel/connection_pool.rb +6/-0
lib/sequel/connection_pool/sharded_timed_queue.rb +36/-11
lib/sequel/connection_pool/timed_queue.rb +27/-9
lib/sequel/database/schema_generator.rb +36/-5
lib/sequel/database/schema_methods.rb +1/-1
lib/sequel/dataset/placeholder_literalizer.rb +3/-0
lib/sequel/dataset/prepared_statements.rb +7/-4
lib/sequel/dataset/query.rb +6/-3
lib/sequel/dataset/sql.rb +6/-1
lib/sequel/extensions/connection_expiration.rb +1/-1
lib/sequel/extensions/connection_validator.rb +1/-1
lib/sequel/extensions/dataset_run.rb +2/-2
lib/sequel/extensions/date_arithmetic.rb +6/-6
lib/sequel/extensions/migration.rb +14/-17
lib/sequel/extensions/pg_enum.rb +1/-1
lib/sequel/model/associations.rb +1/-1
lib/sequel/plugins/dirty.rb +5/-2
lib/sequel/plugins/mssql_optimistic_locking.rb +1/-1
lib/sequel/plugins/pg_xmin_optimistic_locking.rb +1/-1
lib/sequel/plugins/serialization.rb +10/-1
lib/sequel/version.rb +1/-1
DIFFERENT extra_rdoc_files:
5.101.0->5.103.0:
* Changed:
MIT-LICENSE +1/-1 |
Contributor
gem compare --diff sequel 5.101.0 5.103.0Compared versions: ["5.101.0", "5.103.0"]
DIFFERENT files:
5.101.0->5.103.0:
* Added:
lib/sequel/extensions/connection_checkout_event_callback.rb
--- /tmp/20260402-1847-9lfsg5 2026-04-02 05:27:54.404736227 +0000
+++ /tmp/d20260402-1847-962hhc/sequel-5.103.0/lib/sequel/extensions/connection_checkout_event_callback.rb 2026-04-02 05:27:54.357736004 +0000
@@ -0,0 +1,151 @@
+# frozen-string-literal: true
+#
+# The connection_checkout_event_callback extension modifies a database's
+# connection pool to allow for a checkout event callback. This callback is
+# called with the following arguments:
+#
+# :immediately_available :: Connection immediately available and returned
+# :not_immediately_available :: Connection not immediately available
+# :new_connection :: New connection created and returned
+# Float :: Number of seconds waiting to acquire a connection
+#
+# This is a low-level extension that allows for building telemetry
+# information. It doesn't implement any telemetry reporting itself. The
+# main reason for recording this information is to use it to determine the
+# appropriate size for the connection pool. Having too large a connection
+# pool can waste resources, while having too small a connection pool can
+# result in substantial time to check out a connection. In general, you
+# want to use as small a pool as possible while keeping the time to
+# checkout a connection low.
+#
+# To use the connection checkout event callback, you must first load the
+# extension:
+#
+# DB.extension(:connection_checkout_event_callback)
+#
+# By default, an empty proc is used as the callback so that loading the
+# support doesn't break anything. If you are using the extension, you
+# should set the callback at some point during application startup:
+#
+# DB.pool.on_checkout_event = proc do |event|
+# # ...
+# end
+#
+# When using the sharded connection pool, the callback is also
+# passed a second argument, the requested server shard (generally a
+# symbol), allowing for collection of per-shard telemetry:
+#
+# DB.pool.on_checkout_event = proc do |event, server|
+# # ...
+# end
+#
+# Note that the callback may be called currently by multiple threads.
+# You should use some form of concurrency control inside the callback,
+# such as a mutex or queue.
+#
+# Below is a brief example of usage to determine the percentage of
+# connection requests where a connection was immediately available:
+#
+# mutex = Mutex.new
+# total = immediates = 0
+#
+# DB.pool.on_checkout_event = proc do |event|
+# case event
+# when :immediately_available
+# mutex.synchronize do
+# total += 1
+# immediates += 1
+# end
+# when :not_immediately_available
+# mutex.synchronize do
+# total += 1
+# end
+# end
+# end
+#
+# immediate_percentage = lambda do
+# mutex.synchronize do
+# 100.0 * immediates / total
+# end
+# end
+#
+# Note that this extension only works with the timed_queue
+# and sharded_timed_queue connection pools (the default
+# connection pools when using Ruby 3.2+).
+#
+# Related modules: Sequel::ConnectionCheckoutEventCallbacks::TimedQueue,
+# Sequel::ConnectionCheckoutEventCallbacks::ShardedTimedQueue
+
+#
+module Sequel
+ module ConnectionCheckoutEventCallbacks
+ module TimedQueue
+ # The callback that is called with connection checkout events.
+ attr_accessor :on_checkout_event
+
+ private
+
+ def available
+ conn = super
+ @on_checkout_event.call(conn ? :immediately_available : :not_immediately_available)
+ conn
+ end
+
+ def try_make_new
+ conn = super
+ @on_checkout_event.call(:new_connection) if conn
+ conn
+ end
+
+ def wait_until_available
+ timer = Sequel.start_timer
+ conn = super
+ @on_checkout_event.call(Sequel.elapsed_seconds_since(timer))
+ conn
+ end
+ end
+
+ module ShardedTimedQueue
+ # The callback that is called with connection checkout events.
+ attr_accessor :on_checkout_event
+
+ private
+
+ def available(queue, server)
+ conn = super
+ @on_checkout_event.call(conn ? :immediately_available : :not_immediately_available, server)
+ conn
+ end
+
+ def try_make_new(server)
+ conn = super
+ @on_checkout_event.call(:new_connection, server) if conn
+ conn
+ end
+
+ def wait_until_available(queue, server)
+ timer = Sequel.start_timer
+ conn = super
+ @on_checkout_event.call(Sequel.elapsed_seconds_since(timer), server)
+ conn
+ end
+ end
+ end
+
+ default_callback = proc{}
+
+ Database.register_extension(:connection_checkout_event_callback) do |db|
+ pool = db.pool
+
+ case pool.pool_type
+ when :timed_queue
+ db.pool.extend(ConnectionCheckoutEventCallbacks::TimedQueue)
+ when :sharded_timed_queue
+ db.pool.extend(ConnectionCheckoutEventCallbacks::ShardedTimedQueue)
+ else
+ raise Error, "the connection_checkout_event_callback extension is only supported when using a timed_queue connection pool"
+ end
+
+ pool.on_checkout_event ||= default_callback
+ end
+end
lib/sequel/extensions/lit_require_frozen.rb
--- /tmp/20260402-1847-9pfeuf 2026-04-02 05:27:54.406736236 +0000
+++ /tmp/d20260402-1847-962hhc/sequel-5.103.0/lib/sequel/extensions/lit_require_frozen.rb 2026-04-02 05:27:54.360736018 +0000
@@ -0,0 +1,131 @@
+# frozen-string-literal: true
+#
+# The lit_require_frozen extension disallows the use of unfrozen strings
+# as literal strings in database and dataset methods. If you try to use an
+# unfrozen string as a literal string for a dataset using this extension,
+# an exception will be raised.
+#
+# While this works for all Ruby versions, it is designed for use on Ruby 3+
+# where all files are using the frozen-string-literal magic comment. In this
+# case, uninterpolated literal strings are frozen, but interpolated strings
+# are not frozen. This allows you to catch potentially dangerous code:
+#
+# # Probably safe, no exception raised
+# DB["SELECT * FROM t WHERE c > :v", v: user_provided_string)
+#
+# # Potentially unsafe, raises Sequel::LitRequireFrozen::Error
+# DB["SELECT * FROM t WHERE c > '#{user_provided_string}'"]
+#
+# The assumption made is that a frozen string is unlikely to contain unsafe
+# input, while an unfrozen string has potentially been interpolated and may
+# contain unsafe input.
+#
+# This disallows the the following cases:
+#
+# * Sequel::LiteralString instances that are unfrozen and are not based on a
+# frozen string
+# * Sequel::SQL::PlaceholderLiteralString instances when the placeholder string
+# is not frozen
+# * Unfrozen strings passed to Database#<< or #[] or Dataset#with_sql
+#
+# To use this extension, load it into the database:
+#
+# DB.extension :lit_require_frozen
+#
+# It can also be loaded into individual datasets:
+#
+# ds = DB[:t].extension(:lit_require_frozen)
+#
+# Assuming you have good test coverage, it is recommended to only load
+# this extension when testing.
+#
+# Related module: Sequel::LitRequireFrozen
+
+#
+module Sequel
+ class LiteralString
+ # The string used when creating the literal string (first argument to
+ # Sequel::LiteralString.new). This may be nil if no string was provided,
+ # or if the litral string was created before this extension was required.
+ attr_reader :source
+
+ def initialize(*a)
+ @source = a.first
+ super
+ end
+ # :nocov:
+ ruby2_keywords :initialize if respond_to?(:ruby2_keywords, true)
+ # :nocov:
+ end
+
+ module LitRequireFrozen
+ # Error class raised for using unfrozen literal string.
+ class Error < Sequel::Error
+ end
+
+ module DatabaseMethods
+ def self.extended(db)
+ db.extend_datasets(DatasetMethods)
+ end
+
+ # Check given SQL is frozen before running it.
+ def run(sql, opts=OPTS)
+ @default_dataset.with_sql(sql)
+ super
+ end
+ end
+
+ module DatasetMethods
+ # Check given SQL is not an unfrozen string.
+ def with_sql(sql, *args)
+ _check_unfrozen_literal_string(sql)
+ super
+ end
+
+ # Check that placeholder string is frozen (or all entries
+ # in placeholder array are frozen).
+ def placeholder_literal_string_sql_append(sql, pls)
+ str = pls.str
+
+ if str.is_a?(Array)
+ str.each do |s|
+ _check_unfrozen_literal_string(s)
+ end
+ else
+ _check_unfrozen_literal_string(str)
+ end
+
+ super
+ end
+
+ private
+
+ # Base method that other methods used to check for whether a string should be allowed
+ # as literal SQL. Allows non-strings as well as frozen strings.
+ def _check_unfrozen_literal_string(str)
+ return if !str.is_a?(String) || str.frozen?
+
+ if str.is_a?(LiteralString)
+ _check_unfrozen_literal_string(str.source)
+ else
+ raise Error, "cannot treat unfrozen string as literal SQL: #{str.inspect}"
+ end
+ end
+
+ # Check literal strings appended to SQL.
+ def literal_literal_string_append(sql, v)
+ _check_unfrozen_literal_string(v)
+ super
+ end
+
+ # Check static SQL is not frozen.
+ def static_sql(sql)
+ _check_unfrozen_literal_string(sql)
+ super
+ end
+ end
+ end
+
+ Dataset.register_extension(:lit_require_frozen, LitRequireFrozen::DatasetMethods)
+ Database.register_extension(:lit_require_frozen, LitRequireFrozen::DatabaseMethods)
+end
* Changed:
MIT-LICENSE
--- /tmp/d20260402-1847-962hhc/sequel-5.101.0/MIT-LICENSE 2026-04-02 05:27:54.245735474 +0000
+++ /tmp/d20260402-1847-962hhc/sequel-5.103.0/MIT-LICENSE 2026-04-02 05:27:54.326735857 +0000
@@ -2 +2 @@
-Copyright (c) 2008-2023 Jeremy Evans
+Copyright (c) 2008-2026 Jeremy Evans and contributors
lib/sequel/adapters/jdbc/derby.rb
--- /tmp/d20260402-1847-962hhc/sequel-5.101.0/lib/sequel/adapters/jdbc/derby.rb 2026-04-02 05:27:54.248735488 +0000
+++ /tmp/d20260402-1847-962hhc/sequel-5.103.0/lib/sequel/adapters/jdbc/derby.rb 2026-04-02 05:27:54.328735867 +0000
@@ -2,0 +3,2 @@
+# SEQUEL6: Remove
+
lib/sequel/adapters/jdbc/h2.rb
--- /tmp/d20260402-1847-962hhc/sequel-5.101.0/lib/sequel/adapters/jdbc/h2.rb 2026-04-02 05:27:54.248735488 +0000
+++ /tmp/d20260402-1847-962hhc/sequel-5.103.0/lib/sequel/adapters/jdbc/h2.rb 2026-04-02 05:27:54.328735867 +0000
@@ -21 +21 @@
- run("COMMIT TRANSACTION #{transaction_id}", opts)
+ run("COMMIT TRANSACTION #{transaction_id}".freeze, opts)
@@ -39 +39 @@
- run("ROLLBACK TRANSACTION #{transaction_id}", opts)
+ run("ROLLBACK TRANSACTION #{transaction_id}".freeze, opts)
lib/sequel/adapters/postgres.rb
--- /tmp/d20260402-1847-962hhc/sequel-5.101.0/lib/sequel/adapters/postgres.rb 2026-04-02 05:27:54.251735502 +0000
+++ /tmp/d20260402-1847-962hhc/sequel-5.103.0/lib/sequel/adapters/postgres.rb 2026-04-02 05:27:54.335735900 +0000
@@ -730 +730 @@
- LiteralString.new("#{prepared_arg_placeholder}#{i}")
+ LiteralString.new("#{prepared_arg_placeholder}#{i}".freeze)
lib/sequel/adapters/shared/mssql.rb
--- /tmp/d20260402-1847-962hhc/sequel-5.101.0/lib/sequel/adapters/shared/mssql.rb 2026-04-02 05:27:54.257735531 +0000
+++ /tmp/d20260402-1847-962hhc/sequel-5.103.0/lib/sequel/adapters/shared/mssql.rb 2026-04-02 05:27:54.339735919 +0000
@@ -109 +109 @@
- sql = "DECLARE #{declarations.join(', ')}; EXECUTE @RC = #{name} #{values.join(', ')}; SELECT #{names.join(', ')}"
+ sql = "DECLARE #{declarations.join(', ')}; EXECUTE @RC = #{name} #{values.join(', ')}; SELECT #{names.join(', ')}".freeze
@@ -403 +403 @@
- run(ds.into(name).sql)
+ run(ds.into(name).sql.freeze)
@@ -881 +881 @@
- sql = multi_insert_sql(columns, values)[0]
+ sql = multi_insert_sql(columns, values)[0].freeze
lib/sequel/adapters/shared/mysql.rb
--- /tmp/d20260402-1847-962hhc/sequel-5.101.0/lib/sequel/adapters/shared/mysql.rb 2026-04-02 05:27:54.257735531 +0000
+++ /tmp/d20260402-1847-962hhc/sequel-5.103.0/lib/sequel/adapters/shared/mysql.rb 2026-04-02 05:27:54.339735919 +0000
@@ -43 +43 @@
- run("XA COMMIT #{literal(transaction_id)}", opts)
+ run("XA COMMIT #{literal(transaction_id)}".freeze, opts)
@@ -106 +106 @@
- metadata_dataset.with_sql(sql).each do |r|
+ metadata_dataset.with_sql(sql.freeze).each do |r|
@@ -118 +118 @@
- run("XA ROLLBACK #{literal(transaction_id)}", opts)
+ run("XA ROLLBACK #{literal(transaction_id)}".freeze, opts)
@@ -783 +783,2 @@
- ds = db.send(:metadata_dataset).with_sql(((opts[:extended] && (db.mariadb? || db.server_version < 50700)) ? 'EXPLAIN EXTENDED ' : 'EXPLAIN ') + select_sql).naked
+ sql = ((opts[:extended] && (db.mariadb? || db.server_version < 50700)) ? 'EXPLAIN EXTENDED ' : 'EXPLAIN ') + select_sql
+ ds = db.send(:metadata_dataset).with_sql(sql.freeze).naked
lib/sequel/adapters/shared/postgres.rb
--- /tmp/d20260402-1847-962hhc/sequel-5.101.0/lib/sequel/adapters/shared/postgres.rb 2026-04-02 05:27:54.262735554 +0000
+++ /tmp/d20260402-1847-962hhc/sequel-5.103.0/lib/sequel/adapters/shared/postgres.rb 2026-04-02 05:27:54.340735924 +0000
@@ -342 +342 @@
- run("COMMIT PREPARED #{literal(transaction_id)}", opts)
+ run("COMMIT PREPARED #{literal(transaction_id)}".freeze, opts)
@@ -419 +419 @@
- run("ALTER TABLE #{quote_schema_table(table)} ALTER COLUMN #{quote_identifier(column)} DROP DEFAULT", server_hash)
+ run("ALTER TABLE #{quote_schema_table(table)} ALTER COLUMN #{quote_identifier(column)} DROP DEFAULT".freeze, server_hash)
@@ -456 +456 @@
- self << create_function_sql(name, definition, opts)
+ self << create_function_sql(name, definition, opts).freeze
@@ -467 +467 @@
- self << create_language_sql(name, opts)
+ self << create_language_sql(name, opts).freeze
@@ -476 +476 @@
- self << create_schema_sql(name, opts)
+ self << create_schema_sql(name, opts).freeze
@@ -512 +512 @@
- self << create_trigger_sql(table, name, function, opts)
+ self << create_trigger_sql(table, name, function, opts).freeze
@@ -545 +545 @@
- run "DO #{"LANGUAGE #{literal(language.to_s)} " if language}#{literal(code)}"
+ run "DO #{"LANGUAGE #{literal(language.to_s)} " if language}#{literal(code)}".freeze
@@ -555 +555 @@
- self << drop_function_sql(name, opts)
+ self << drop_function_sql(name, opts).freeze
@@ -564 +564 @@
- self << drop_language_sql(name, opts)
+ self << drop_language_sql(name, opts).freeze
@@ -573 +573 @@
- self << drop_schema_sql(name, opts)
+ self << drop_schema_sql(name, opts).freeze
@@ -584 +584 @@
- self << drop_trigger_sql(table, name, opts)
+ self << drop_trigger_sql(table, name, opts).freeze
@@ -748 +748 @@
- self << rename_schema_sql(name, new_name)
+ self << rename_schema_sql(name, new_name).freeze
@@ -759 +759 @@
- run "REFRESH MATERIALIZED VIEW#{' CONCURRENTLY' if opts[:concurrently]} #{quote_schema_table(name)}"
+ run "REFRESH MATERIALIZED VIEW#{' CONCURRENTLY' if opts[:concurrently]} #{quote_schema_table(name)}".freeze
@@ -772 +772 @@
- seq_ds = metadata_dataset.from(:pg_sequence).where(:seqrelid=>regclass_oid(LiteralString.new(seq)))
+ seq_ds = metadata_dataset.from(:pg_sequence).where(:seqrelid=>regclass_oid(LiteralString.new(seq.freeze)))
@@ -787 +787 @@
- run("ROLLBACK PREPARED #{literal(transaction_id)}", opts)
+ run("ROLLBACK PREPARED #{literal(transaction_id)}".freeze, opts)
@@ -1472 +1472 @@
- cols[-1] = Sequel.lit("PERIOD #{quote_identifier(cols[-1])}")
+ cols[-1] = Sequel.lit("PERIOD #{quote_identifier(cols[-1])}".freeze)
lib/sequel/adapters/shared/sqlite.rb
--- /tmp/d20260402-1847-962hhc/sequel-5.101.0/lib/sequel/adapters/shared/sqlite.rb 2026-04-02 05:27:54.263735559 +0000
+++ /tmp/d20260402-1847-962hhc/sequel-5.103.0/lib/sequel/adapters/shared/sqlite.rb 2026-04-02 05:27:54.341735928 +0000
@@ -198 +198 @@
- metadata_dataset.with_sql("PRAGMA table_#{'x' if sqlite_version > 33100}info(?)", input_identifier_meth(opts[:dataset]).call(table_name))
+ metadata_dataset.with_sql("PRAGMA table_#{'x' if sqlite_version > 33100}info(?)".freeze, input_identifier_meth(opts[:dataset]).call(table_name))
@@ -410 +410 @@
- c[:default] = LiteralString.new(c[:default]) if c[:default]
+ c[:default] = LiteralString.new(c[:default]).freeze if c[:default]
@@ -687 +687 @@
- ds = db.send(:metadata_dataset).clone(:sql=>"EXPLAIN #{select_sql}")
+ ds = db.send(:metadata_dataset).clone(:sql=>"EXPLAIN #{select_sql}".freeze)
lib/sequel/adapters/sqlite.rb
--- /tmp/d20260402-1847-962hhc/sequel-5.101.0/lib/sequel/adapters/sqlite.rb 2026-04-02 05:27:54.263735559 +0000
+++ /tmp/d20260402-1847-962hhc/sequel-5.103.0/lib/sequel/adapters/sqlite.rb 2026-04-02 05:27:54.341735928 +0000
@@ -391 +391 @@
- LiteralString.new("#{prepared_arg_placeholder}#{k.to_s.gsub('.', '__')}")
+ LiteralString.new("#{prepared_arg_placeholder}#{k.to_s.gsub('.', '__')}".freeze)
lib/sequel/adapters/tinytds.rb
--- /tmp/d20260402-1847-962hhc/sequel-5.101.0/lib/sequel/adapters/tinytds.rb 2026-04-02 05:27:54.263735559 +0000
+++ /tmp/d20260402-1847-962hhc/sequel-5.103.0/lib/sequel/adapters/tinytds.rb 2026-04-02 05:27:54.341735928 +0000
@@ -208 +208 @@
- LiteralString.new("@#{k.to_s.gsub('.', '__')}")
+ LiteralString.new("@#{k.to_s.gsub('.', '__')}".freeze)
lib/sequel/connection_pool.rb
--- /tmp/d20260402-1847-962hhc/sequel-5.101.0/lib/sequel/connection_pool.rb 2026-04-02 05:27:54.264735564 +0000
+++ /tmp/d20260402-1847-962hhc/sequel-5.103.0/lib/sequel/connection_pool.rb 2026-04-02 05:27:54.344735942 +0000
@@ -133,0 +134,6 @@
+ # Only for use by extension that need to disconnect a connection inside acquire.
+ # Takes the connection and any arguments accepted by acquire.
+ def disconnect_acquired_connection(conn, *)
+ disconnect_connection(conn)
+ end
+
lib/sequel/connection_pool/sharded_timed_queue.rb
--- /tmp/d20260402-1847-962hhc/sequel-5.101.0/lib/sequel/connection_pool/sharded_timed_queue.rb 2026-04-02 05:27:54.265735569 +0000
+++ /tmp/d20260402-1847-962hhc/sequel-5.103.0/lib/sequel/connection_pool/sharded_timed_queue.rb 2026-04-02 05:27:54.344735942 +0000
@@ -74 +74 @@
- break unless (conn = queue.pop(timeout: 0)) && !conns[conn]
+ break unless (conn = available(queue, server)) && !conns[conn]
@@ -94 +94 @@
- # and then the method will only disconnect connectsion from those specified shards.
+ # and then the method will only disconnect connections from those specified shards.
@@ -98 +98,3 @@
- while conn = queue.pop(timeout: 0)
+ nconns = 0
+ while conn = available(queue, server)
+ nconns += 1
@@ -101 +103 @@
- fill_queue(server)
+ fill_queue(server, nconns)
@@ -135 +137 @@
- fill_queue(server)
+ fill_queue(server, 1)
@@ -170 +172 @@
- while conn = queue.pop(timeout: 0)
+ while conn = available(queue, server)
@@ -227,0 +230,6 @@
+ # Only for use by extension that need to disconnect a connection inside acquire.
+ # Takes the connection and any arguments accepted by acquire.
+ def disconnect_acquired_connection(conn, _, server)
+ disconnect_pool_connection(conn, server)
+ end
+
@@ -247 +255,4 @@
- def fill_queue(server)
+ #
+ # nconns specifies the maximum number of connections to add, which should
+ # be the number of connections that were disconnected.
+ def fill_queue(server, nconns)
@@ -249 +260 @@
- if queue.num_waiting > 0
+ if nconns > 0 && queue.num_waiting > 0
@@ -251 +262,2 @@
- while queue.num_waiting > 0 && (conn = try_make_new(server))
+ while nconns > 0 && queue.num_waiting > 0 && (conn = try_make_new(server))
+ nconns -= 1
@@ -300 +312 @@
- fill_queue(server)
+ fill_queue(server, to_disconnect.size)
@@ -314 +326 @@
- if conn = queue.pop(timeout: 0) || try_make_new(server) || queue.pop(timeout: @timeout)
+ if conn = available(queue, server) || try_make_new(server) || wait_until_available(queue, server)
@@ -319,0 +332,13 @@
+ end
+
+ # Return the next connection in the pool if there is one available. Returns nil
+ # if no connection is currently available.
+ def available(queue, _server)
+ queue.pop(timeout: 0)
+ end
+
+ # Return the next connection in the pool if there is one available. If not, wait
+ # until the timeout for a connection to become available. If there is still no
+ # available connection, return nil.
+ def wait_until_available(queue, _server)
+ queue.pop(timeout: @timeout)
lib/sequel/connection_pool/timed_queue.rb
--- /tmp/d20260402-1847-962hhc/sequel-5.101.0/lib/sequel/connection_pool/timed_queue.rb 2026-04-02 05:27:54.265735569 +0000
+++ /tmp/d20260402-1847-962hhc/sequel-5.103.0/lib/sequel/connection_pool/timed_queue.rb 2026-04-02 05:27:54.345735947 +0000
@@ -45 +45 @@
- break unless (conn = @queue.pop(timeout: 0)) && !conns[conn]
+ break unless (conn = available) && !conns[conn]
@@ -62 +62,3 @@
- while conn = @queue.pop(timeout: 0)
+ nconns = 0
+ while conn = available
+ nconns += 1
@@ -65 +67 @@
- fill_queue
+ fill_queue(nconns)
@@ -97 +99 @@
- fill_queue
+ fill_queue(1)
@@ -159,2 +161,5 @@
- def fill_queue
- if @queue.num_waiting > 0
+ #
+ # nconns specifies the maximum number of connections to add, which should
+ # be the number of connections that were disconnected.
+ def fill_queue(nconns)
+ if nconns > 0 && @queue.num_waiting > 0
@@ -162 +167 @@
- while @queue.num_waiting > 0 && (conn = try_make_new)
+ while nconns > 0 && @queue.num_waiting > 0 && (conn = try_make_new)
@@ -210 +215 @@
- fill_queue
+ fill_queue(to_disconnect.size)
@@ -223 +228 @@
- if conn = @queue.pop(timeout: 0) || try_make_new || @queue.pop(timeout: @timeout)
+ if conn = available || try_make_new || wait_until_available
@@ -228,0 +234,13 @@
+ end
+
+ # Return the next connection in the pool if there is one available. Returns nil
+ # if no connection is currently available.
+ def available
+ @queue.pop(timeout: 0)
+ end
+
+ # Return the next connection in the pool if there is one available. If not, wait
+ # until the timeout for a connection to become available. If there is still no
+ # available connection, return nil.
+ def wait_until_available
+ @queue.pop(timeout: @timeout)
lib/sequel/database/schema_generator.rb
--- /tmp/d20260402-1847-962hhc/sequel-5.101.0/lib/sequel/database/schema_generator.rb 2026-04-02 05:27:54.276735621 +0000
+++ /tmp/d20260402-1847-962hhc/sequel-5.103.0/lib/sequel/database/schema_generator.rb 2026-04-02 05:27:54.346735952 +0000
@@ -5,0 +6,27 @@
+ module ColumnOptionMerger
+ private
+
+ # Merge given options into the column's default options. For backwards compatibility,
+ # the options take priority, but in cases where the option value overrides the argument
+ # value, and the values are different, we warn as this is likely to be an error in the
+ # code.
+ def _merge_column_options(defaults, opts)
+ defaults.merge!(opts) do |k, defv, v|
+ unless defv == v
+ # :nocov:
+ if RUBY_VERSION >= "3.2"
+ # :nocov:
+ caller_loc = Thread.each_caller_location do |loc|
+ break loc unless loc.path == __FILE__
+ end
+ caller_loc &&= "#{caller_loc.path}:#{caller_loc.lineno}: "
+ end
+ warn("#{caller_loc}#{k.inspect} option value (#{v.inspect}) overrides argument value (#{defv.inspect})")
+ end
+
+ v
+ end
+ end
+ end
+ private_constant :ColumnOptionMerger
+
@@ -19,0 +47,2 @@
+ include ColumnOptionMerger
+
@@ -176 +205 @@
- columns << {:name => name, :type => type}.merge!(opts)
+ columns << _merge_column_options({:name => name, :type => type}, opts)
@@ -182 +211 @@
-
+
@@ -249 +278 @@
- column(name, Integer, opts)
+ column(name, opts.fetch(:type, Integer), opts)
@@ -431,0 +461,2 @@
+ include ColumnOptionMerger
+
@@ -457 +488 @@
- op = {:op => :add_column, :name => name, :type => type}.merge!(opts)
+ op = _merge_column_options({:op => :add_column, :name => name, :type => type}, opts)
@@ -522 +553 @@
- add_column(name, Integer, {:table=>table}.merge!(opts))
+ add_column(name, opts.fetch(:type, Integer), {:table=>table}.merge!(opts))
lib/sequel/database/schema_methods.rb
--- /tmp/d20260402-1847-962hhc/sequel-5.101.0/lib/sequel/database/schema_methods.rb 2026-04-02 05:27:54.276735621 +0000
+++ /tmp/d20260402-1847-962hhc/sequel-5.103.0/lib/sequel/database/schema_methods.rb 2026-04-02 05:27:54.346735952 +0000
@@ -822 +822 @@
- run(create_table_as_sql(name, sql, options))
+ run(create_table_as_sql(name, sql, options).freeze)
lib/sequel/dataset/placeholder_literalizer.rb
--- /tmp/d20260402-1847-962hhc/sequel-5.101.0/lib/sequel/dataset/placeholder_literalizer.rb 2026-04-02 05:27:54.278735630 +0000
+++ /tmp/d20260402-1847-962hhc/sequel-5.103.0/lib/sequel/dataset/placeholder_literalizer.rb 2026-04-02 05:27:54.355735994 +0000
@@ -119,0 +120,2 @@
+ frags.each(&:freeze)
+ frags.freeze
@@ -127,0 +130 @@
+ ds.opts[:sql].freeze
lib/sequel/dataset/prepared_statements.rb
--- /tmp/d20260402-1847-962hhc/sequel-5.101.0/lib/sequel/dataset/prepared_statements.rb 2026-04-02 05:27:54.278735630 +0000
+++ /tmp/d20260402-1847-962hhc/sequel-5.103.0/lib/sequel/dataset/prepared_statements.rb 2026-04-02 05:27:54.355735994 +0000
@@ -57 +57 @@
- sql = prepared_sql
+ sql = prepared_sql.freeze
@@ -226 +226 @@
- with_sql(prepared_sql)
+ with_sql(prepared_sql.freeze)
@@ -290 +290 @@
- sql = literal(Sequel::SQL::PlaceholderLiteralString.new(@opts[:prepared_sql_frags], @opts[:bind_arguments], false))
+ sql = literal(Sequel::SQL::PlaceholderLiteralString.new(@opts[:prepared_sql_frags], @opts[:bind_arguments], false)).freeze
@@ -322,0 +323,3 @@
+ frags.freeze
+ frags.each(&:freeze)
+ prepared_sql.freeze
@@ -412 +415 @@
- sql = ps.prepared_sql
+ sql = ps.prepared_sql.freeze
lib/sequel/dataset/query.rb
--- /tmp/d20260402-1847-962hhc/sequel-5.101.0/lib/sequel/dataset/query.rb 2026-04-02 05:27:54.278735630 +0000
+++ /tmp/d20260402-1847-962hhc/sequel-5.103.0/lib/sequel/dataset/query.rb 2026-04-02 05:27:54.355735994 +0000
@@ -1304 +1304 @@
- sql = public_send(sql, *args)
+ sql = public_send(sql, *args).freeze
@@ -1477 +1477,4 @@
-
+
+ PAREN_WRAPPER = ["(".freeze, ")".freeze].freeze
+ private_constant :PAREN_WRAPPER
+
@@ -1498 +1501 @@
- LiteralString.new("(#{expr})")
+ SQL::PlaceholderLiteralString.new(PAREN_WRAPPER, [expr])
lib/sequel/dataset/sql.rb
--- /tmp/d20260402-1847-962hhc/sequel-5.101.0/lib/sequel/dataset/sql.rb 2026-04-02 05:27:54.278735630 +0000
+++ /tmp/d20260402-1847-962hhc/sequel-5.103.0/lib/sequel/dataset/sql.rb 2026-04-02 05:27:54.356735999 +0000
@@ -56 +56 @@
- sql << v
+ literal_literal_string_append(sql, v)
@@ -1424,0 +1425,5 @@
+ end
+
+ # Append string to SQL string.
+ def literal_literal_string_append(sql, v)
+ sql << v
lib/sequel/extensions/connection_expiration.rb
--- /tmp/d20260402-1847-962hhc/sequel-5.101.0/lib/sequel/extensions/connection_expiration.rb 2026-04-02 05:27:54.280735639 +0000
+++ /tmp/d20260402-1847-962hhc/sequel-5.103.0/lib/sequel/extensions/connection_expiration.rb 2026-04-02 05:27:54.357736004 +0000
@@ -94 +94 @@
- disconnect_connection(conn)
+ disconnect_acquired_connection(conn, *a)
lib/sequel/extensions/connection_validator.rb
--- /tmp/d20260402-1847-962hhc/sequel-5.101.0/lib/sequel/extensions/connection_validator.rb 2026-04-02 05:27:54.280735639 +0000
+++ /tmp/d20260402-1847-962hhc/sequel-5.103.0/lib/sequel/extensions/connection_validator.rb 2026-04-02 05:27:54.357736004 +0000
@@ -121 +121 @@
- disconnect_connection(conn)
+ disconnect_acquired_connection(conn, *a)
lib/sequel/extensions/dataset_run.rb
--- /tmp/d20260402-1847-962hhc/sequel-5.101.0/lib/sequel/extensions/dataset_run.rb 2026-04-02 05:27:54.281735644 +0000
+++ /tmp/d20260402-1847-962hhc/sequel-5.103.0/lib/sequel/extensions/dataset_run.rb 2026-04-02 05:27:54.358736009 +0000
@@ -33 +33 @@
- db.run(sql, :server=>server)
+ db.run(sql.freeze, :server=>server)
@@ -35 +35 @@
- db.run(sql)
+ db.run(sql.freeze)
lib/sequel/extensions/date_arithmetic.rb
--- /tmp/d20260402-1847-962hhc/sequel-5.101.0/lib/sequel/extensions/date_arithmetic.rb 2026-04-02 05:27:54.281735644 +0000
+++ /tmp/d20260402-1847-962hhc/sequel-5.103.0/lib/sequel/extensions/date_arithmetic.rb 2026-04-02 05:27:54.358736009 +0000
@@ -85,2 +85,2 @@
- MYSQL_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s.upcase[0...-1]).freeze}).freeze
- MSSQL_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s[0...-1]).freeze}).freeze
+ MYSQL_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s.upcase[0...-1].freeze).freeze}).freeze
+ MSSQL_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s[0...-1].freeze).freeze}).freeze
@@ -88 +88 @@
- DERBY_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit("SQL_TSI_#{s.to_s.upcase[0...-1]}").freeze}).freeze
+ DERBY_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit("SQL_TSI_#{s.to_s.upcase[0...-1]}".freeze).freeze}).freeze
@@ -90 +90 @@
- DB2_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s).freeze}).freeze
+ DB2_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s.freeze).freeze}).freeze
@@ -110 +110 @@
- placeholder << "#{', ' unless placeholder.empty?}#{sql_unit} := "
+ placeholder << "#{', ' unless placeholder.empty?}#{sql_unit} := ".freeze
@@ -159 +159 @@
- expr = Sequel.lit(["{fn timestampadd(#{sql_unit}, ", ", timestamp(", "))}"], value, expr)
+ expr = Sequel.lit(["{fn timestampadd(#{sql_unit}, ".freeze, ", timestamp(", "))}"], value, expr)
lib/sequel/extensions/migration.rb
--- /tmp/d20260402-1847-962hhc/sequel-5.101.0/lib/sequel/extensions/migration.rb 2026-04-02 05:27:54.283735654 +0000
+++ /tmp/d20260402-1847-962hhc/sequel-5.103.0/lib/sequel/extensions/migration.rb 2026-04-02 05:27:54.361736023 +0000
@@ -189,16 +189,13 @@
- begin
- instance_exec(&block)
- rescue
- just_raise = true
- end
- if just_raise
- Proc.new{raise Sequel::Error, "irreversible migration method used in #{block.source_location.first}, you may need to write your own down method"}
- else
- actions = @actions.reverse
- Proc.new do
- actions.each do |a|
- pr = a.last.is_a?(Proc) ? a.pop : nil
- # Allow calling private methods as the reversing methods are private
- send(*a, &pr)
- end
- end
+ instance_exec(&block)
+ rescue NoMethodError => e
+ Proc.new{raise Sequel::Error, "irreversible migration method \"#{e.name}\" used in #{block.source_location.first}, you may need to write your own down method"}
+ rescue => e
+ Proc.new{raise Sequel::Error, "unable to reverse migration due to #{e.class} in #{block.source_location.first}, you may need to write your own down method"}
+ else
+ actions = @actions.reverse
+ Proc.new do
+ actions.each do |a|
+ pr = a.last.is_a?(Proc) ? a.pop : nil
+ # Allow calling private methods as the reversing methods are private
+ send(*a, &pr)
+ end
@@ -273 +270 @@
- raise if args.first.is_a?(Array)
+ super if args.first.is_a?(Array)
lib/sequel/extensions/pg_enum.rb
--- /tmp/d20260402-1847-962hhc/sequel-5.101.0/lib/sequel/extensions/pg_enum.rb 2026-04-02 05:27:54.284735658 +0000
+++ /tmp/d20260402-1847-962hhc/sequel-5.103.0/lib/sequel/extensions/pg_enum.rb 2026-04-02 05:27:54.364736037 +0000
@@ -130 +130 @@
- run(sql)
+ run(sql.freeze)
lib/sequel/model/associations.rb
--- /tmp/d20260402-1847-962hhc/sequel-5.101.0/lib/sequel/model/associations.rb 2026-04-02 05:27:54.296735715 +0000
+++ /tmp/d20260402-1847-962hhc/sequel-5.103.0/lib/sequel/model/associations.rb 2026-04-02 05:27:54.387736146 +0000
@@ -323 +323 @@
- objects.concat(ds.with_sql(sql).to_a)
+ objects.concat(ds.with_sql(sql.freeze).to_a)
lib/sequel/plugins/dirty.rb
--- /tmp/d20260402-1847-962hhc/sequel-5.101.0/lib/sequel/plugins/dirty.rb 2026-04-02 05:27:54.312735791 +0000
+++ /tmp/d20260402-1847-962hhc/sequel-5.103.0/lib/sequel/plugins/dirty.rb 2026-04-02 05:27:54.394736179 +0000
@@ -237,2 +237,5 @@
- check_missing_initial_value(column)
- iv[column] = get_column_value(column)
+ if db_schema[column]
+ check_missing_initial_value(column)
+ iv[column] = get_column_value(column)
+ end
+
lib/sequel/plugins/mssql_optimistic_locking.rb
--- /tmp/d20260402-1847-962hhc/sequel-5.101.0/lib/sequel/plugins/mssql_optimistic_locking.rb 2026-04-02 05:27:54.315735805 +0000
+++ /tmp/d20260402-1847-962hhc/sequel-5.103.0/lib/sequel/plugins/mssql_optimistic_locking.rb 2026-04-02 05:27:54.396736188 +0000
@@ -58 +58 @@
- rows = ds.clone(ds.send(:default_server_opts, :sql=>ds.output(nil, [Sequel[:inserted][lc]]).update_sql(columns))).all
+ rows = ds.clone(ds.send(:default_server_opts, :sql=>ds.output(nil, [Sequel[:inserted][lc]]).update_sql(columns).freeze)).all
lib/sequel/plugins/pg_xmin_optimistic_locking.rb
--- /tmp/d20260402-1847-962hhc/sequel-5.101.0/lib/sequel/plugins/pg_xmin_optimistic_locking.rb 2026-04-02 05:27:54.317735815 +0000
+++ /tmp/d20260402-1847-962hhc/sequel-5.103.0/lib/sequel/plugins/pg_xmin_optimistic_locking.rb 2026-04-02 05:27:54.398736198 +0000
@@ -102 +102 @@
- rows = ds.clone(ds.send(:default_server_opts, :sql=>ds.returning(:xmin).update_sql(columns))).all
+ rows = ds.clone(ds.send(:default_server_opts, :sql=>ds.returning(:xmin).update_sql(columns).freeze)).all
lib/sequel/plugins/serialization.rb
--- /tmp/d20260402-1847-962hhc/sequel-5.101.0/lib/sequel/plugins/serialization.rb 2026-04-02 05:27:54.317735815 +0000
+++ /tmp/d20260402-1847-962hhc/sequel-5.103.0/lib/sequel/plugins/serialization.rb 2026-04-02 05:27:54.398736198 +0000
@@ -32,0 +33,9 @@
+ # Note that use of an unsafe serialization method can result in an attack vector
+ # (potentially allowing remote code execution) if an attacker has the ability to
+ # store data directly in the underlying column. This would affect the marshal
+ # serialization format, and on older versions of Ruby, potentially the yaml and
+ # json serialization formats as well. It can also affect custom formats. You
+ # should ensure that attackers do not have access to store data directly in the
+ # underlying column when using this plugin (especially when using an unsafe
+ # serialization method).
+ #
@@ -100 +109 @@
- v = v.unpack('m')[0] unless v[0..1] == "\x04\x08"
+ v = v.unpack('m')[0] unless v.start_with?("\x04\x08")
lib/sequel/version.rb
--- /tmp/d20260402-1847-962hhc/sequel-5.101.0/lib/sequel/version.rb 2026-04-02 05:27:54.325735852 +0000
+++ /tmp/d20260402-1847-962hhc/sequel-5.103.0/lib/sequel/version.rb 2026-04-02 05:27:54.403736222 +0000
@@ -9 +9 @@
- MINOR = 101
+ MINOR = 103 |
Contributor
gem compare --diff sequel 5.101.0 5.103.0Compared versions: ["5.101.0", "5.103.0"]
DIFFERENT files:
5.101.0->5.103.0:
* Added:
lib/sequel/extensions/connection_checkout_event_callback.rb
--- /tmp/20260402-1842-47v6t9 2026-04-02 05:27:55.981692631 +0000
+++ /tmp/d20260402-1842-bf9nf9/sequel-5.103.0/lib/sequel/extensions/connection_checkout_event_callback.rb 2026-04-02 05:27:55.954692550 +0000
@@ -0,0 +1,151 @@
+# frozen-string-literal: true
+#
+# The connection_checkout_event_callback extension modifies a database's
+# connection pool to allow for a checkout event callback. This callback is
+# called with the following arguments:
+#
+# :immediately_available :: Connection immediately available and returned
+# :not_immediately_available :: Connection not immediately available
+# :new_connection :: New connection created and returned
+# Float :: Number of seconds waiting to acquire a connection
+#
+# This is a low-level extension that allows for building telemetry
+# information. It doesn't implement any telemetry reporting itself. The
+# main reason for recording this information is to use it to determine the
+# appropriate size for the connection pool. Having too large a connection
+# pool can waste resources, while having too small a connection pool can
+# result in substantial time to check out a connection. In general, you
+# want to use as small a pool as possible while keeping the time to
+# checkout a connection low.
+#
+# To use the connection checkout event callback, you must first load the
+# extension:
+#
+# DB.extension(:connection_checkout_event_callback)
+#
+# By default, an empty proc is used as the callback so that loading the
+# support doesn't break anything. If you are using the extension, you
+# should set the callback at some point during application startup:
+#
+# DB.pool.on_checkout_event = proc do |event|
+# # ...
+# end
+#
+# When using the sharded connection pool, the callback is also
+# passed a second argument, the requested server shard (generally a
+# symbol), allowing for collection of per-shard telemetry:
+#
+# DB.pool.on_checkout_event = proc do |event, server|
+# # ...
+# end
+#
+# Note that the callback may be called currently by multiple threads.
+# You should use some form of concurrency control inside the callback,
+# such as a mutex or queue.
+#
+# Below is a brief example of usage to determine the percentage of
+# connection requests where a connection was immediately available:
+#
+# mutex = Mutex.new
+# total = immediates = 0
+#
+# DB.pool.on_checkout_event = proc do |event|
+# case event
+# when :immediately_available
+# mutex.synchronize do
+# total += 1
+# immediates += 1
+# end
+# when :not_immediately_available
+# mutex.synchronize do
+# total += 1
+# end
+# end
+# end
+#
+# immediate_percentage = lambda do
+# mutex.synchronize do
+# 100.0 * immediates / total
+# end
+# end
+#
+# Note that this extension only works with the timed_queue
+# and sharded_timed_queue connection pools (the default
+# connection pools when using Ruby 3.2+).
+#
+# Related modules: Sequel::ConnectionCheckoutEventCallbacks::TimedQueue,
+# Sequel::ConnectionCheckoutEventCallbacks::ShardedTimedQueue
+
+#
+module Sequel
+ module ConnectionCheckoutEventCallbacks
+ module TimedQueue
+ # The callback that is called with connection checkout events.
+ attr_accessor :on_checkout_event
+
+ private
+
+ def available
+ conn = super
+ @on_checkout_event.call(conn ? :immediately_available : :not_immediately_available)
+ conn
+ end
+
+ def try_make_new
+ conn = super
+ @on_checkout_event.call(:new_connection) if conn
+ conn
+ end
+
+ def wait_until_available
+ timer = Sequel.start_timer
+ conn = super
+ @on_checkout_event.call(Sequel.elapsed_seconds_since(timer))
+ conn
+ end
+ end
+
+ module ShardedTimedQueue
+ # The callback that is called with connection checkout events.
+ attr_accessor :on_checkout_event
+
+ private
+
+ def available(queue, server)
+ conn = super
+ @on_checkout_event.call(conn ? :immediately_available : :not_immediately_available, server)
+ conn
+ end
+
+ def try_make_new(server)
+ conn = super
+ @on_checkout_event.call(:new_connection, server) if conn
+ conn
+ end
+
+ def wait_until_available(queue, server)
+ timer = Sequel.start_timer
+ conn = super
+ @on_checkout_event.call(Sequel.elapsed_seconds_since(timer), server)
+ conn
+ end
+ end
+ end
+
+ default_callback = proc{}
+
+ Database.register_extension(:connection_checkout_event_callback) do |db|
+ pool = db.pool
+
+ case pool.pool_type
+ when :timed_queue
+ db.pool.extend(ConnectionCheckoutEventCallbacks::TimedQueue)
+ when :sharded_timed_queue
+ db.pool.extend(ConnectionCheckoutEventCallbacks::ShardedTimedQueue)
+ else
+ raise Error, "the connection_checkout_event_callback extension is only supported when using a timed_queue connection pool"
+ end
+
+ pool.on_checkout_event ||= default_callback
+ end
+end
lib/sequel/extensions/lit_require_frozen.rb
--- /tmp/20260402-1842-78v2wg 2026-04-02 05:27:55.990692659 +0000
+++ /tmp/d20260402-1842-bf9nf9/sequel-5.103.0/lib/sequel/extensions/lit_require_frozen.rb 2026-04-02 05:27:55.957692559 +0000
@@ -0,0 +1,131 @@
+# frozen-string-literal: true
+#
+# The lit_require_frozen extension disallows the use of unfrozen strings
+# as literal strings in database and dataset methods. If you try to use an
+# unfrozen string as a literal string for a dataset using this extension,
+# an exception will be raised.
+#
+# While this works for all Ruby versions, it is designed for use on Ruby 3+
+# where all files are using the frozen-string-literal magic comment. In this
+# case, uninterpolated literal strings are frozen, but interpolated strings
+# are not frozen. This allows you to catch potentially dangerous code:
+#
+# # Probably safe, no exception raised
+# DB["SELECT * FROM t WHERE c > :v", v: user_provided_string)
+#
+# # Potentially unsafe, raises Sequel::LitRequireFrozen::Error
+# DB["SELECT * FROM t WHERE c > '#{user_provided_string}'"]
+#
+# The assumption made is that a frozen string is unlikely to contain unsafe
+# input, while an unfrozen string has potentially been interpolated and may
+# contain unsafe input.
+#
+# This disallows the the following cases:
+#
+# * Sequel::LiteralString instances that are unfrozen and are not based on a
+# frozen string
+# * Sequel::SQL::PlaceholderLiteralString instances when the placeholder string
+# is not frozen
+# * Unfrozen strings passed to Database#<< or #[] or Dataset#with_sql
+#
+# To use this extension, load it into the database:
+#
+# DB.extension :lit_require_frozen
+#
+# It can also be loaded into individual datasets:
+#
+# ds = DB[:t].extension(:lit_require_frozen)
+#
+# Assuming you have good test coverage, it is recommended to only load
+# this extension when testing.
+#
+# Related module: Sequel::LitRequireFrozen
+
+#
+module Sequel
+ class LiteralString
+ # The string used when creating the literal string (first argument to
+ # Sequel::LiteralString.new). This may be nil if no string was provided,
+ # or if the litral string was created before this extension was required.
+ attr_reader :source
+
+ def initialize(*a)
+ @source = a.first
+ super
+ end
+ # :nocov:
+ ruby2_keywords :initialize if respond_to?(:ruby2_keywords, true)
+ # :nocov:
+ end
+
+ module LitRequireFrozen
+ # Error class raised for using unfrozen literal string.
+ class Error < Sequel::Error
+ end
+
+ module DatabaseMethods
+ def self.extended(db)
+ db.extend_datasets(DatasetMethods)
+ end
+
+ # Check given SQL is frozen before running it.
+ def run(sql, opts=OPTS)
+ @default_dataset.with_sql(sql)
+ super
+ end
+ end
+
+ module DatasetMethods
+ # Check given SQL is not an unfrozen string.
+ def with_sql(sql, *args)
+ _check_unfrozen_literal_string(sql)
+ super
+ end
+
+ # Check that placeholder string is frozen (or all entries
+ # in placeholder array are frozen).
+ def placeholder_literal_string_sql_append(sql, pls)
+ str = pls.str
+
+ if str.is_a?(Array)
+ str.each do |s|
+ _check_unfrozen_literal_string(s)
+ end
+ else
+ _check_unfrozen_literal_string(str)
+ end
+
+ super
+ end
+
+ private
+
+ # Base method that other methods used to check for whether a string should be allowed
+ # as literal SQL. Allows non-strings as well as frozen strings.
+ def _check_unfrozen_literal_string(str)
+ return if !str.is_a?(String) || str.frozen?
+
+ if str.is_a?(LiteralString)
+ _check_unfrozen_literal_string(str.source)
+ else
+ raise Error, "cannot treat unfrozen string as literal SQL: #{str.inspect}"
+ end
+ end
+
+ # Check literal strings appended to SQL.
+ def literal_literal_string_append(sql, v)
+ _check_unfrozen_literal_string(v)
+ super
+ end
+
+ # Check static SQL is not frozen.
+ def static_sql(sql)
+ _check_unfrozen_literal_string(sql)
+ super
+ end
+ end
+ end
+
+ Dataset.register_extension(:lit_require_frozen, LitRequireFrozen::DatasetMethods)
+ Database.register_extension(:lit_require_frozen, LitRequireFrozen::DatabaseMethods)
+end
* Changed:
MIT-LICENSE
--- /tmp/d20260402-1842-bf9nf9/sequel-5.101.0/MIT-LICENSE 2026-04-02 05:27:55.882692332 +0000
+++ /tmp/d20260402-1842-bf9nf9/sequel-5.103.0/MIT-LICENSE 2026-04-02 05:27:55.939692505 +0000
@@ -2 +2 @@
-Copyright (c) 2008-2023 Jeremy Evans
+Copyright (c) 2008-2026 Jeremy Evans and contributors
lib/sequel/adapters/jdbc/derby.rb
--- /tmp/d20260402-1842-bf9nf9/sequel-5.101.0/lib/sequel/adapters/jdbc/derby.rb 2026-04-02 05:27:55.884692338 +0000
+++ /tmp/d20260402-1842-bf9nf9/sequel-5.103.0/lib/sequel/adapters/jdbc/derby.rb 2026-04-02 05:27:55.941692511 +0000
@@ -2,0 +3,2 @@
+# SEQUEL6: Remove
+
lib/sequel/adapters/jdbc/h2.rb
--- /tmp/d20260402-1842-bf9nf9/sequel-5.101.0/lib/sequel/adapters/jdbc/h2.rb 2026-04-02 05:27:55.884692338 +0000
+++ /tmp/d20260402-1842-bf9nf9/sequel-5.103.0/lib/sequel/adapters/jdbc/h2.rb 2026-04-02 05:27:55.941692511 +0000
@@ -21 +21 @@
- run("COMMIT TRANSACTION #{transaction_id}", opts)
+ run("COMMIT TRANSACTION #{transaction_id}".freeze, opts)
@@ -39 +39 @@
- run("ROLLBACK TRANSACTION #{transaction_id}", opts)
+ run("ROLLBACK TRANSACTION #{transaction_id}".freeze, opts)
lib/sequel/adapters/postgres.rb
--- /tmp/d20260402-1842-bf9nf9/sequel-5.101.0/lib/sequel/adapters/postgres.rb 2026-04-02 05:27:55.888692350 +0000
+++ /tmp/d20260402-1842-bf9nf9/sequel-5.103.0/lib/sequel/adapters/postgres.rb 2026-04-02 05:27:55.943692517 +0000
@@ -730 +730 @@
- LiteralString.new("#{prepared_arg_placeholder}#{i}")
+ LiteralString.new("#{prepared_arg_placeholder}#{i}".freeze)
lib/sequel/adapters/shared/mssql.rb
--- /tmp/d20260402-1842-bf9nf9/sequel-5.101.0/lib/sequel/adapters/shared/mssql.rb 2026-04-02 05:27:55.889692353 +0000
+++ /tmp/d20260402-1842-bf9nf9/sequel-5.103.0/lib/sequel/adapters/shared/mssql.rb 2026-04-02 05:27:55.944692520 +0000
@@ -109 +109 @@
- sql = "DECLARE #{declarations.join(', ')}; EXECUTE @RC = #{name} #{values.join(', ')}; SELECT #{names.join(', ')}"
+ sql = "DECLARE #{declarations.join(', ')}; EXECUTE @RC = #{name} #{values.join(', ')}; SELECT #{names.join(', ')}".freeze
@@ -403 +403 @@
- run(ds.into(name).sql)
+ run(ds.into(name).sql.freeze)
@@ -881 +881 @@
- sql = multi_insert_sql(columns, values)[0]
+ sql = multi_insert_sql(columns, values)[0].freeze
lib/sequel/adapters/shared/mysql.rb
--- /tmp/d20260402-1842-bf9nf9/sequel-5.101.0/lib/sequel/adapters/shared/mysql.rb 2026-04-02 05:27:55.889692353 +0000
+++ /tmp/d20260402-1842-bf9nf9/sequel-5.103.0/lib/sequel/adapters/shared/mysql.rb 2026-04-02 05:27:55.944692520 +0000
@@ -43 +43 @@
- run("XA COMMIT #{literal(transaction_id)}", opts)
+ run("XA COMMIT #{literal(transaction_id)}".freeze, opts)
@@ -106 +106 @@
- metadata_dataset.with_sql(sql).each do |r|
+ metadata_dataset.with_sql(sql.freeze).each do |r|
@@ -118 +118 @@
- run("XA ROLLBACK #{literal(transaction_id)}", opts)
+ run("XA ROLLBACK #{literal(transaction_id)}".freeze, opts)
@@ -783 +783,2 @@
- ds = db.send(:metadata_dataset).with_sql(((opts[:extended] && (db.mariadb? || db.server_version < 50700)) ? 'EXPLAIN EXTENDED ' : 'EXPLAIN ') + select_sql).naked
+ sql = ((opts[:extended] && (db.mariadb? || db.server_version < 50700)) ? 'EXPLAIN EXTENDED ' : 'EXPLAIN ') + select_sql
+ ds = db.send(:metadata_dataset).with_sql(sql.freeze).naked
lib/sequel/adapters/shared/postgres.rb
--- /tmp/d20260402-1842-bf9nf9/sequel-5.101.0/lib/sequel/adapters/shared/postgres.rb 2026-04-02 05:27:55.890692356 +0000
+++ /tmp/d20260402-1842-bf9nf9/sequel-5.103.0/lib/sequel/adapters/shared/postgres.rb 2026-04-02 05:27:55.945692523 +0000
@@ -342 +342 @@
- run("COMMIT PREPARED #{literal(transaction_id)}", opts)
+ run("COMMIT PREPARED #{literal(transaction_id)}".freeze, opts)
@@ -419 +419 @@
- run("ALTER TABLE #{quote_schema_table(table)} ALTER COLUMN #{quote_identifier(column)} DROP DEFAULT", server_hash)
+ run("ALTER TABLE #{quote_schema_table(table)} ALTER COLUMN #{quote_identifier(column)} DROP DEFAULT".freeze, server_hash)
@@ -456 +456 @@
- self << create_function_sql(name, definition, opts)
+ self << create_function_sql(name, definition, opts).freeze
@@ -467 +467 @@
- self << create_language_sql(name, opts)
+ self << create_language_sql(name, opts).freeze
@@ -476 +476 @@
- self << create_schema_sql(name, opts)
+ self << create_schema_sql(name, opts).freeze
@@ -512 +512 @@
- self << create_trigger_sql(table, name, function, opts)
+ self << create_trigger_sql(table, name, function, opts).freeze
@@ -545 +545 @@
- run "DO #{"LANGUAGE #{literal(language.to_s)} " if language}#{literal(code)}"
+ run "DO #{"LANGUAGE #{literal(language.to_s)} " if language}#{literal(code)}".freeze
@@ -555 +555 @@
- self << drop_function_sql(name, opts)
+ self << drop_function_sql(name, opts).freeze
@@ -564 +564 @@
- self << drop_language_sql(name, opts)
+ self << drop_language_sql(name, opts).freeze
@@ -573 +573 @@
- self << drop_schema_sql(name, opts)
+ self << drop_schema_sql(name, opts).freeze
@@ -584 +584 @@
- self << drop_trigger_sql(table, name, opts)
+ self << drop_trigger_sql(table, name, opts).freeze
@@ -748 +748 @@
- self << rename_schema_sql(name, new_name)
+ self << rename_schema_sql(name, new_name).freeze
@@ -759 +759 @@
- run "REFRESH MATERIALIZED VIEW#{' CONCURRENTLY' if opts[:concurrently]} #{quote_schema_table(name)}"
+ run "REFRESH MATERIALIZED VIEW#{' CONCURRENTLY' if opts[:concurrently]} #{quote_schema_table(name)}".freeze
@@ -772 +772 @@
- seq_ds = metadata_dataset.from(:pg_sequence).where(:seqrelid=>regclass_oid(LiteralString.new(seq)))
+ seq_ds = metadata_dataset.from(:pg_sequence).where(:seqrelid=>regclass_oid(LiteralString.new(seq.freeze)))
@@ -787 +787 @@
- run("ROLLBACK PREPARED #{literal(transaction_id)}", opts)
+ run("ROLLBACK PREPARED #{literal(transaction_id)}".freeze, opts)
@@ -1472 +1472 @@
- cols[-1] = Sequel.lit("PERIOD #{quote_identifier(cols[-1])}")
+ cols[-1] = Sequel.lit("PERIOD #{quote_identifier(cols[-1])}".freeze)
lib/sequel/adapters/shared/sqlite.rb
--- /tmp/d20260402-1842-bf9nf9/sequel-5.101.0/lib/sequel/adapters/shared/sqlite.rb 2026-04-02 05:27:55.891692360 +0000
+++ /tmp/d20260402-1842-bf9nf9/sequel-5.103.0/lib/sequel/adapters/shared/sqlite.rb 2026-04-02 05:27:55.945692523 +0000
@@ -198 +198 @@
- metadata_dataset.with_sql("PRAGMA table_#{'x' if sqlite_version > 33100}info(?)", input_identifier_meth(opts[:dataset]).call(table_name))
+ metadata_dataset.with_sql("PRAGMA table_#{'x' if sqlite_version > 33100}info(?)".freeze, input_identifier_meth(opts[:dataset]).call(table_name))
@@ -410 +410 @@
- c[:default] = LiteralString.new(c[:default]) if c[:default]
+ c[:default] = LiteralString.new(c[:default]).freeze if c[:default]
@@ -687 +687 @@
- ds = db.send(:metadata_dataset).clone(:sql=>"EXPLAIN #{select_sql}")
+ ds = db.send(:metadata_dataset).clone(:sql=>"EXPLAIN #{select_sql}".freeze)
lib/sequel/adapters/sqlite.rb
--- /tmp/d20260402-1842-bf9nf9/sequel-5.101.0/lib/sequel/adapters/sqlite.rb 2026-04-02 05:27:55.891692360 +0000
+++ /tmp/d20260402-1842-bf9nf9/sequel-5.103.0/lib/sequel/adapters/sqlite.rb 2026-04-02 05:27:55.946692526 +0000
@@ -391 +391 @@
- LiteralString.new("#{prepared_arg_placeholder}#{k.to_s.gsub('.', '__')}")
+ LiteralString.new("#{prepared_arg_placeholder}#{k.to_s.gsub('.', '__')}".freeze)
lib/sequel/adapters/tinytds.rb
--- /tmp/d20260402-1842-bf9nf9/sequel-5.101.0/lib/sequel/adapters/tinytds.rb 2026-04-02 05:27:55.892692362 +0000
+++ /tmp/d20260402-1842-bf9nf9/sequel-5.103.0/lib/sequel/adapters/tinytds.rb 2026-04-02 05:27:55.946692526 +0000
@@ -208 +208 @@
- LiteralString.new("@#{k.to_s.gsub('.', '__')}")
+ LiteralString.new("@#{k.to_s.gsub('.', '__')}".freeze)
lib/sequel/connection_pool.rb
--- /tmp/d20260402-1842-bf9nf9/sequel-5.101.0/lib/sequel/connection_pool.rb 2026-04-02 05:27:55.893692366 +0000
+++ /tmp/d20260402-1842-bf9nf9/sequel-5.103.0/lib/sequel/connection_pool.rb 2026-04-02 05:27:55.947692529 +0000
@@ -133,0 +134,6 @@
+ # Only for use by extension that need to disconnect a connection inside acquire.
+ # Takes the connection and any arguments accepted by acquire.
+ def disconnect_acquired_connection(conn, *)
+ disconnect_connection(conn)
+ end
+
lib/sequel/connection_pool/sharded_timed_queue.rb
--- /tmp/d20260402-1842-bf9nf9/sequel-5.101.0/lib/sequel/connection_pool/sharded_timed_queue.rb 2026-04-02 05:27:55.893692366 +0000
+++ /tmp/d20260402-1842-bf9nf9/sequel-5.103.0/lib/sequel/connection_pool/sharded_timed_queue.rb 2026-04-02 05:27:55.948692532 +0000
@@ -74 +74 @@
- break unless (conn = queue.pop(timeout: 0)) && !conns[conn]
+ break unless (conn = available(queue, server)) && !conns[conn]
@@ -94 +94 @@
- # and then the method will only disconnect connectsion from those specified shards.
+ # and then the method will only disconnect connections from those specified shards.
@@ -98 +98,3 @@
- while conn = queue.pop(timeout: 0)
+ nconns = 0
+ while conn = available(queue, server)
+ nconns += 1
@@ -101 +103 @@
- fill_queue(server)
+ fill_queue(server, nconns)
@@ -135 +137 @@
- fill_queue(server)
+ fill_queue(server, 1)
@@ -170 +172 @@
- while conn = queue.pop(timeout: 0)
+ while conn = available(queue, server)
@@ -227,0 +230,6 @@
+ # Only for use by extension that need to disconnect a connection inside acquire.
+ # Takes the connection and any arguments accepted by acquire.
+ def disconnect_acquired_connection(conn, _, server)
+ disconnect_pool_connection(conn, server)
+ end
+
@@ -247 +255,4 @@
- def fill_queue(server)
+ #
+ # nconns specifies the maximum number of connections to add, which should
+ # be the number of connections that were disconnected.
+ def fill_queue(server, nconns)
@@ -249 +260 @@
- if queue.num_waiting > 0
+ if nconns > 0 && queue.num_waiting > 0
@@ -251 +262,2 @@
- while queue.num_waiting > 0 && (conn = try_make_new(server))
+ while nconns > 0 && queue.num_waiting > 0 && (conn = try_make_new(server))
+ nconns -= 1
@@ -300 +312 @@
- fill_queue(server)
+ fill_queue(server, to_disconnect.size)
@@ -314 +326 @@
- if conn = queue.pop(timeout: 0) || try_make_new(server) || queue.pop(timeout: @timeout)
+ if conn = available(queue, server) || try_make_new(server) || wait_until_available(queue, server)
@@ -319,0 +332,13 @@
+ end
+
+ # Return the next connection in the pool if there is one available. Returns nil
+ # if no connection is currently available.
+ def available(queue, _server)
+ queue.pop(timeout: 0)
+ end
+
+ # Return the next connection in the pool if there is one available. If not, wait
+ # until the timeout for a connection to become available. If there is still no
+ # available connection, return nil.
+ def wait_until_available(queue, _server)
+ queue.pop(timeout: @timeout)
lib/sequel/connection_pool/timed_queue.rb
--- /tmp/d20260402-1842-bf9nf9/sequel-5.101.0/lib/sequel/connection_pool/timed_queue.rb 2026-04-02 05:27:55.893692366 +0000
+++ /tmp/d20260402-1842-bf9nf9/sequel-5.103.0/lib/sequel/connection_pool/timed_queue.rb 2026-04-02 05:27:55.948692532 +0000
@@ -45 +45 @@
- break unless (conn = @queue.pop(timeout: 0)) && !conns[conn]
+ break unless (conn = available) && !conns[conn]
@@ -62 +62,3 @@
- while conn = @queue.pop(timeout: 0)
+ nconns = 0
+ while conn = available
+ nconns += 1
@@ -65 +67 @@
- fill_queue
+ fill_queue(nconns)
@@ -97 +99 @@
- fill_queue
+ fill_queue(1)
@@ -159,2 +161,5 @@
- def fill_queue
- if @queue.num_waiting > 0
+ #
+ # nconns specifies the maximum number of connections to add, which should
+ # be the number of connections that were disconnected.
+ def fill_queue(nconns)
+ if nconns > 0 && @queue.num_waiting > 0
@@ -162 +167 @@
- while @queue.num_waiting > 0 && (conn = try_make_new)
+ while nconns > 0 && @queue.num_waiting > 0 && (conn = try_make_new)
@@ -210 +215 @@
- fill_queue
+ fill_queue(to_disconnect.size)
@@ -223 +228 @@
- if conn = @queue.pop(timeout: 0) || try_make_new || @queue.pop(timeout: @timeout)
+ if conn = available || try_make_new || wait_until_available
@@ -228,0 +234,13 @@
+ end
+
+ # Return the next connection in the pool if there is one available. Returns nil
+ # if no connection is currently available.
+ def available
+ @queue.pop(timeout: 0)
+ end
+
+ # Return the next connection in the pool if there is one available. If not, wait
+ # until the timeout for a connection to become available. If there is still no
+ # available connection, return nil.
+ def wait_until_available
+ @queue.pop(timeout: @timeout)
lib/sequel/database/schema_generator.rb
--- /tmp/d20260402-1842-bf9nf9/sequel-5.101.0/lib/sequel/database/schema_generator.rb 2026-04-02 05:27:55.895692371 +0000
+++ /tmp/d20260402-1842-bf9nf9/sequel-5.103.0/lib/sequel/database/schema_generator.rb 2026-04-02 05:27:55.950692538 +0000
@@ -5,0 +6,27 @@
+ module ColumnOptionMerger
+ private
+
+ # Merge given options into the column's default options. For backwards compatibility,
+ # the options take priority, but in cases where the option value overrides the argument
+ # value, and the values are different, we warn as this is likely to be an error in the
+ # code.
+ def _merge_column_options(defaults, opts)
+ defaults.merge!(opts) do |k, defv, v|
+ unless defv == v
+ # :nocov:
+ if RUBY_VERSION >= "3.2"
+ # :nocov:
+ caller_loc = Thread.each_caller_location do |loc|
+ break loc unless loc.path == __FILE__
+ end
+ caller_loc &&= "#{caller_loc.path}:#{caller_loc.lineno}: "
+ end
+ warn("#{caller_loc}#{k.inspect} option value (#{v.inspect}) overrides argument value (#{defv.inspect})")
+ end
+
+ v
+ end
+ end
+ end
+ private_constant :ColumnOptionMerger
+
@@ -19,0 +47,2 @@
+ include ColumnOptionMerger
+
@@ -176 +205 @@
- columns << {:name => name, :type => type}.merge!(opts)
+ columns << _merge_column_options({:name => name, :type => type}, opts)
@@ -182 +211 @@
-
+
@@ -249 +278 @@
- column(name, Integer, opts)
+ column(name, opts.fetch(:type, Integer), opts)
@@ -431,0 +461,2 @@
+ include ColumnOptionMerger
+
@@ -457 +488 @@
- op = {:op => :add_column, :name => name, :type => type}.merge!(opts)
+ op = _merge_column_options({:op => :add_column, :name => name, :type => type}, opts)
@@ -522 +553 @@
- add_column(name, Integer, {:table=>table}.merge!(opts))
+ add_column(name, opts.fetch(:type, Integer), {:table=>table}.merge!(opts))
lib/sequel/database/schema_methods.rb
--- /tmp/d20260402-1842-bf9nf9/sequel-5.101.0/lib/sequel/database/schema_methods.rb 2026-04-02 05:27:55.896692375 +0000
+++ /tmp/d20260402-1842-bf9nf9/sequel-5.103.0/lib/sequel/database/schema_methods.rb 2026-04-02 05:27:55.950692538 +0000
@@ -822 +822 @@
- run(create_table_as_sql(name, sql, options))
+ run(create_table_as_sql(name, sql, options).freeze)
lib/sequel/dataset/placeholder_literalizer.rb
--- /tmp/d20260402-1842-bf9nf9/sequel-5.101.0/lib/sequel/dataset/placeholder_literalizer.rb 2026-04-02 05:27:55.899692383 +0000
+++ /tmp/d20260402-1842-bf9nf9/sequel-5.103.0/lib/sequel/dataset/placeholder_literalizer.rb 2026-04-02 05:27:55.952692544 +0000
@@ -119,0 +120,2 @@
+ frags.each(&:freeze)
+ frags.freeze
@@ -127,0 +130 @@
+ ds.opts[:sql].freeze
lib/sequel/dataset/prepared_statements.rb
--- /tmp/d20260402-1842-bf9nf9/sequel-5.101.0/lib/sequel/dataset/prepared_statements.rb 2026-04-02 05:27:55.899692383 +0000
+++ /tmp/d20260402-1842-bf9nf9/sequel-5.103.0/lib/sequel/dataset/prepared_statements.rb 2026-04-02 05:27:55.952692544 +0000
@@ -57 +57 @@
- sql = prepared_sql
+ sql = prepared_sql.freeze
@@ -226 +226 @@
- with_sql(prepared_sql)
+ with_sql(prepared_sql.freeze)
@@ -290 +290 @@
- sql = literal(Sequel::SQL::PlaceholderLiteralString.new(@opts[:prepared_sql_frags], @opts[:bind_arguments], false))
+ sql = literal(Sequel::SQL::PlaceholderLiteralString.new(@opts[:prepared_sql_frags], @opts[:bind_arguments], false)).freeze
@@ -322,0 +323,3 @@
+ frags.freeze
+ frags.each(&:freeze)
+ prepared_sql.freeze
@@ -412 +415 @@
- sql = ps.prepared_sql
+ sql = ps.prepared_sql.freeze
lib/sequel/dataset/query.rb
--- /tmp/d20260402-1842-bf9nf9/sequel-5.101.0/lib/sequel/dataset/query.rb 2026-04-02 05:27:55.900692387 +0000
+++ /tmp/d20260402-1842-bf9nf9/sequel-5.103.0/lib/sequel/dataset/query.rb 2026-04-02 05:27:55.952692544 +0000
@@ -1304 +1304 @@
- sql = public_send(sql, *args)
+ sql = public_send(sql, *args).freeze
@@ -1477 +1477,4 @@
-
+
+ PAREN_WRAPPER = ["(".freeze, ")".freeze].freeze
+ private_constant :PAREN_WRAPPER
+
@@ -1498 +1501 @@
- LiteralString.new("(#{expr})")
+ SQL::PlaceholderLiteralString.new(PAREN_WRAPPER, [expr])
lib/sequel/dataset/sql.rb
--- /tmp/d20260402-1842-bf9nf9/sequel-5.101.0/lib/sequel/dataset/sql.rb 2026-04-02 05:27:55.902692393 +0000
+++ /tmp/d20260402-1842-bf9nf9/sequel-5.103.0/lib/sequel/dataset/sql.rb 2026-04-02 05:27:55.952692544 +0000
@@ -56 +56 @@
- sql << v
+ literal_literal_string_append(sql, v)
@@ -1424,0 +1425,5 @@
+ end
+
+ # Append string to SQL string.
+ def literal_literal_string_append(sql, v)
+ sql << v
lib/sequel/extensions/connection_expiration.rb
--- /tmp/d20260402-1842-bf9nf9/sequel-5.101.0/lib/sequel/extensions/connection_expiration.rb 2026-04-02 05:27:55.903692396 +0000
+++ /tmp/d20260402-1842-bf9nf9/sequel-5.103.0/lib/sequel/extensions/connection_expiration.rb 2026-04-02 05:27:55.954692550 +0000
@@ -94 +94 @@
- disconnect_connection(conn)
+ disconnect_acquired_connection(conn, *a)
lib/sequel/extensions/connection_validator.rb
--- /tmp/d20260402-1842-bf9nf9/sequel-5.101.0/lib/sequel/extensions/connection_validator.rb 2026-04-02 05:27:55.903692396 +0000
+++ /tmp/d20260402-1842-bf9nf9/sequel-5.103.0/lib/sequel/extensions/connection_validator.rb 2026-04-02 05:27:55.954692550 +0000
@@ -121 +121 @@
- disconnect_connection(conn)
+ disconnect_acquired_connection(conn, *a)
lib/sequel/extensions/dataset_run.rb
--- /tmp/d20260402-1842-bf9nf9/sequel-5.101.0/lib/sequel/extensions/dataset_run.rb 2026-04-02 05:27:55.904692399 +0000
+++ /tmp/d20260402-1842-bf9nf9/sequel-5.103.0/lib/sequel/extensions/dataset_run.rb 2026-04-02 05:27:55.955692553 +0000
@@ -33 +33 @@
- db.run(sql, :server=>server)
+ db.run(sql.freeze, :server=>server)
@@ -35 +35 @@
- db.run(sql)
+ db.run(sql.freeze)
lib/sequel/extensions/date_arithmetic.rb
--- /tmp/d20260402-1842-bf9nf9/sequel-5.101.0/lib/sequel/extensions/date_arithmetic.rb 2026-04-02 05:27:55.904692399 +0000
+++ /tmp/d20260402-1842-bf9nf9/sequel-5.103.0/lib/sequel/extensions/date_arithmetic.rb 2026-04-02 05:27:55.955692553 +0000
@@ -85,2 +85,2 @@
- MYSQL_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s.upcase[0...-1]).freeze}).freeze
- MSSQL_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s[0...-1]).freeze}).freeze
+ MYSQL_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s.upcase[0...-1].freeze).freeze}).freeze
+ MSSQL_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s[0...-1].freeze).freeze}).freeze
@@ -88 +88 @@
- DERBY_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit("SQL_TSI_#{s.to_s.upcase[0...-1]}").freeze}).freeze
+ DERBY_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit("SQL_TSI_#{s.to_s.upcase[0...-1]}".freeze).freeze}).freeze
@@ -90 +90 @@
- DB2_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s).freeze}).freeze
+ DB2_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s.freeze).freeze}).freeze
@@ -110 +110 @@
- placeholder << "#{', ' unless placeholder.empty?}#{sql_unit} := "
+ placeholder << "#{', ' unless placeholder.empty?}#{sql_unit} := ".freeze
@@ -159 +159 @@
- expr = Sequel.lit(["{fn timestampadd(#{sql_unit}, ", ", timestamp(", "))}"], value, expr)
+ expr = Sequel.lit(["{fn timestampadd(#{sql_unit}, ".freeze, ", timestamp(", "))}"], value, expr)
lib/sequel/extensions/migration.rb
--- /tmp/d20260402-1842-bf9nf9/sequel-5.101.0/lib/sequel/extensions/migration.rb 2026-04-02 05:27:55.906692405 +0000
+++ /tmp/d20260402-1842-bf9nf9/sequel-5.103.0/lib/sequel/extensions/migration.rb 2026-04-02 05:27:55.957692559 +0000
@@ -189,16 +189,13 @@
- begin
- instance_exec(&block)
- rescue
- just_raise = true
- end
- if just_raise
- Proc.new{raise Sequel::Error, "irreversible migration method used in #{block.source_location.first}, you may need to write your own down method"}
- else
- actions = @actions.reverse
- Proc.new do
- actions.each do |a|
- pr = a.last.is_a?(Proc) ? a.pop : nil
- # Allow calling private methods as the reversing methods are private
- send(*a, &pr)
- end
- end
+ instance_exec(&block)
+ rescue NoMethodError => e
+ Proc.new{raise Sequel::Error, "irreversible migration method \"#{e.name}\" used in #{block.source_location.first}, you may need to write your own down method"}
+ rescue => e
+ Proc.new{raise Sequel::Error, "unable to reverse migration due to #{e.class} in #{block.source_location.first}, you may need to write your own down method"}
+ else
+ actions = @actions.reverse
+ Proc.new do
+ actions.each do |a|
+ pr = a.last.is_a?(Proc) ? a.pop : nil
+ # Allow calling private methods as the reversing methods are private
+ send(*a, &pr)
+ end
@@ -273 +270 @@
- raise if args.first.is_a?(Array)
+ super if args.first.is_a?(Array)
lib/sequel/extensions/pg_enum.rb
--- /tmp/d20260402-1842-bf9nf9/sequel-5.101.0/lib/sequel/extensions/pg_enum.rb 2026-04-02 05:27:55.908692411 +0000
+++ /tmp/d20260402-1842-bf9nf9/sequel-5.103.0/lib/sequel/extensions/pg_enum.rb 2026-04-02 05:27:55.959692565 +0000
@@ -130 +130 @@
- run(sql)
+ run(sql.freeze)
lib/sequel/model/associations.rb
--- /tmp/d20260402-1842-bf9nf9/sequel-5.101.0/lib/sequel/model/associations.rb 2026-04-02 05:27:55.914692429 +0000
+++ /tmp/d20260402-1842-bf9nf9/sequel-5.103.0/lib/sequel/model/associations.rb 2026-04-02 05:27:55.966692586 +0000
@@ -323 +323 @@
- objects.concat(ds.with_sql(sql).to_a)
+ objects.concat(ds.with_sql(sql.freeze).to_a)
lib/sequel/plugins/dirty.rb
--- /tmp/d20260402-1842-bf9nf9/sequel-5.101.0/lib/sequel/plugins/dirty.rb 2026-04-02 05:27:55.927692468 +0000
+++ /tmp/d20260402-1842-bf9nf9/sequel-5.103.0/lib/sequel/plugins/dirty.rb 2026-04-02 05:27:55.971692601 +0000
@@ -237,2 +237,5 @@
- check_missing_initial_value(column)
- iv[column] = get_column_value(column)
+ if db_schema[column]
+ check_missing_initial_value(column)
+ iv[column] = get_column_value(column)
+ end
+
lib/sequel/plugins/mssql_optimistic_locking.rb
--- /tmp/d20260402-1842-bf9nf9/sequel-5.101.0/lib/sequel/plugins/mssql_optimistic_locking.rb 2026-04-02 05:27:55.931692480 +0000
+++ /tmp/d20260402-1842-bf9nf9/sequel-5.103.0/lib/sequel/plugins/mssql_optimistic_locking.rb 2026-04-02 05:27:55.973692607 +0000
@@ -58 +58 @@
- rows = ds.clone(ds.send(:default_server_opts, :sql=>ds.output(nil, [Sequel[:inserted][lc]]).update_sql(columns))).all
+ rows = ds.clone(ds.send(:default_server_opts, :sql=>ds.output(nil, [Sequel[:inserted][lc]]).update_sql(columns).freeze)).all
lib/sequel/plugins/pg_xmin_optimistic_locking.rb
--- /tmp/d20260402-1842-bf9nf9/sequel-5.101.0/lib/sequel/plugins/pg_xmin_optimistic_locking.rb 2026-04-02 05:27:55.933692486 +0000
+++ /tmp/d20260402-1842-bf9nf9/sequel-5.103.0/lib/sequel/plugins/pg_xmin_optimistic_locking.rb 2026-04-02 05:27:55.974692610 +0000
@@ -102 +102 @@
- rows = ds.clone(ds.send(:default_server_opts, :sql=>ds.returning(:xmin).update_sql(columns))).all
+ rows = ds.clone(ds.send(:default_server_opts, :sql=>ds.returning(:xmin).update_sql(columns).freeze)).all
lib/sequel/plugins/serialization.rb
--- /tmp/d20260402-1842-bf9nf9/sequel-5.101.0/lib/sequel/plugins/serialization.rb 2026-04-02 05:27:55.933692486 +0000
+++ /tmp/d20260402-1842-bf9nf9/sequel-5.103.0/lib/sequel/plugins/serialization.rb 2026-04-02 05:27:55.975692614 +0000
@@ -32,0 +33,9 @@
+ # Note that use of an unsafe serialization method can result in an attack vector
+ # (potentially allowing remote code execution) if an attacker has the ability to
+ # store data directly in the underlying column. This would affect the marshal
+ # serialization format, and on older versions of Ruby, potentially the yaml and
+ # json serialization formats as well. It can also affect custom formats. You
+ # should ensure that attackers do not have access to store data directly in the
+ # underlying column when using this plugin (especially when using an unsafe
+ # serialization method).
+ #
@@ -100 +109 @@
- v = v.unpack('m')[0] unless v[0..1] == "\x04\x08"
+ v = v.unpack('m')[0] unless v.start_with?("\x04\x08")
lib/sequel/version.rb
--- /tmp/d20260402-1842-bf9nf9/sequel-5.101.0/lib/sequel/version.rb 2026-04-02 05:27:55.938692502 +0000
+++ /tmp/d20260402-1842-bf9nf9/sequel-5.103.0/lib/sequel/version.rb 2026-04-02 05:27:55.980692628 +0000
@@ -9 +9 @@
- MINOR = 101
+ MINOR = 103 |
Contributor
gem compare --diff sequel 5.101.0 5.103.0Compared versions: ["5.101.0", "5.103.0"]
DIFFERENT files:
5.101.0->5.103.0:
* Added:
lib/sequel/extensions/connection_checkout_event_callback.rb
--- /tmp/20260402-1830-j57k14 2026-04-02 05:28:10.985196748 +0000
+++ /tmp/d20260402-1830-xiy46q/sequel-5.103.0/lib/sequel/extensions/connection_checkout_event_callback.rb 2026-04-02 05:28:10.960197010 +0000
@@ -0,0 +1,151 @@
+# frozen-string-literal: true
+#
+# The connection_checkout_event_callback extension modifies a database's
+# connection pool to allow for a checkout event callback. This callback is
+# called with the following arguments:
+#
+# :immediately_available :: Connection immediately available and returned
+# :not_immediately_available :: Connection not immediately available
+# :new_connection :: New connection created and returned
+# Float :: Number of seconds waiting to acquire a connection
+#
+# This is a low-level extension that allows for building telemetry
+# information. It doesn't implement any telemetry reporting itself. The
+# main reason for recording this information is to use it to determine the
+# appropriate size for the connection pool. Having too large a connection
+# pool can waste resources, while having too small a connection pool can
+# result in substantial time to check out a connection. In general, you
+# want to use as small a pool as possible while keeping the time to
+# checkout a connection low.
+#
+# To use the connection checkout event callback, you must first load the
+# extension:
+#
+# DB.extension(:connection_checkout_event_callback)
+#
+# By default, an empty proc is used as the callback so that loading the
+# support doesn't break anything. If you are using the extension, you
+# should set the callback at some point during application startup:
+#
+# DB.pool.on_checkout_event = proc do |event|
+# # ...
+# end
+#
+# When using the sharded connection pool, the callback is also
+# passed a second argument, the requested server shard (generally a
+# symbol), allowing for collection of per-shard telemetry:
+#
+# DB.pool.on_checkout_event = proc do |event, server|
+# # ...
+# end
+#
+# Note that the callback may be called currently by multiple threads.
+# You should use some form of concurrency control inside the callback,
+# such as a mutex or queue.
+#
+# Below is a brief example of usage to determine the percentage of
+# connection requests where a connection was immediately available:
+#
+# mutex = Mutex.new
+# total = immediates = 0
+#
+# DB.pool.on_checkout_event = proc do |event|
+# case event
+# when :immediately_available
+# mutex.synchronize do
+# total += 1
+# immediates += 1
+# end
+# when :not_immediately_available
+# mutex.synchronize do
+# total += 1
+# end
+# end
+# end
+#
+# immediate_percentage = lambda do
+# mutex.synchronize do
+# 100.0 * immediates / total
+# end
+# end
+#
+# Note that this extension only works with the timed_queue
+# and sharded_timed_queue connection pools (the default
+# connection pools when using Ruby 3.2+).
+#
+# Related modules: Sequel::ConnectionCheckoutEventCallbacks::TimedQueue,
+# Sequel::ConnectionCheckoutEventCallbacks::ShardedTimedQueue
+
+#
+module Sequel
+ module ConnectionCheckoutEventCallbacks
+ module TimedQueue
+ # The callback that is called with connection checkout events.
+ attr_accessor :on_checkout_event
+
+ private
+
+ def available
+ conn = super
+ @on_checkout_event.call(conn ? :immediately_available : :not_immediately_available)
+ conn
+ end
+
+ def try_make_new
+ conn = super
+ @on_checkout_event.call(:new_connection) if conn
+ conn
+ end
+
+ def wait_until_available
+ timer = Sequel.start_timer
+ conn = super
+ @on_checkout_event.call(Sequel.elapsed_seconds_since(timer))
+ conn
+ end
+ end
+
+ module ShardedTimedQueue
+ # The callback that is called with connection checkout events.
+ attr_accessor :on_checkout_event
+
+ private
+
+ def available(queue, server)
+ conn = super
+ @on_checkout_event.call(conn ? :immediately_available : :not_immediately_available, server)
+ conn
+ end
+
+ def try_make_new(server)
+ conn = super
+ @on_checkout_event.call(:new_connection, server) if conn
+ conn
+ end
+
+ def wait_until_available(queue, server)
+ timer = Sequel.start_timer
+ conn = super
+ @on_checkout_event.call(Sequel.elapsed_seconds_since(timer), server)
+ conn
+ end
+ end
+ end
+
+ default_callback = proc{}
+
+ Database.register_extension(:connection_checkout_event_callback) do |db|
+ pool = db.pool
+
+ case pool.pool_type
+ when :timed_queue
+ db.pool.extend(ConnectionCheckoutEventCallbacks::TimedQueue)
+ when :sharded_timed_queue
+ db.pool.extend(ConnectionCheckoutEventCallbacks::ShardedTimedQueue)
+ else
+ raise Error, "the connection_checkout_event_callback extension is only supported when using a timed_queue connection pool"
+ end
+
+ pool.on_checkout_event ||= default_callback
+ end
+end
lib/sequel/extensions/lit_require_frozen.rb
--- /tmp/20260402-1830-e2t1ac 2026-04-02 05:28:10.987196727 +0000
+++ /tmp/d20260402-1830-xiy46q/sequel-5.103.0/lib/sequel/extensions/lit_require_frozen.rb 2026-04-02 05:28:10.962196989 +0000
@@ -0,0 +1,131 @@
+# frozen-string-literal: true
+#
+# The lit_require_frozen extension disallows the use of unfrozen strings
+# as literal strings in database and dataset methods. If you try to use an
+# unfrozen string as a literal string for a dataset using this extension,
+# an exception will be raised.
+#
+# While this works for all Ruby versions, it is designed for use on Ruby 3+
+# where all files are using the frozen-string-literal magic comment. In this
+# case, uninterpolated literal strings are frozen, but interpolated strings
+# are not frozen. This allows you to catch potentially dangerous code:
+#
+# # Probably safe, no exception raised
+# DB["SELECT * FROM t WHERE c > :v", v: user_provided_string)
+#
+# # Potentially unsafe, raises Sequel::LitRequireFrozen::Error
+# DB["SELECT * FROM t WHERE c > '#{user_provided_string}'"]
+#
+# The assumption made is that a frozen string is unlikely to contain unsafe
+# input, while an unfrozen string has potentially been interpolated and may
+# contain unsafe input.
+#
+# This disallows the the following cases:
+#
+# * Sequel::LiteralString instances that are unfrozen and are not based on a
+# frozen string
+# * Sequel::SQL::PlaceholderLiteralString instances when the placeholder string
+# is not frozen
+# * Unfrozen strings passed to Database#<< or #[] or Dataset#with_sql
+#
+# To use this extension, load it into the database:
+#
+# DB.extension :lit_require_frozen
+#
+# It can also be loaded into individual datasets:
+#
+# ds = DB[:t].extension(:lit_require_frozen)
+#
+# Assuming you have good test coverage, it is recommended to only load
+# this extension when testing.
+#
+# Related module: Sequel::LitRequireFrozen
+
+#
+module Sequel
+ class LiteralString
+ # The string used when creating the literal string (first argument to
+ # Sequel::LiteralString.new). This may be nil if no string was provided,
+ # or if the litral string was created before this extension was required.
+ attr_reader :source
+
+ def initialize(*a)
+ @source = a.first
+ super
+ end
+ # :nocov:
+ ruby2_keywords :initialize if respond_to?(:ruby2_keywords, true)
+ # :nocov:
+ end
+
+ module LitRequireFrozen
+ # Error class raised for using unfrozen literal string.
+ class Error < Sequel::Error
+ end
+
+ module DatabaseMethods
+ def self.extended(db)
+ db.extend_datasets(DatasetMethods)
+ end
+
+ # Check given SQL is frozen before running it.
+ def run(sql, opts=OPTS)
+ @default_dataset.with_sql(sql)
+ super
+ end
+ end
+
+ module DatasetMethods
+ # Check given SQL is not an unfrozen string.
+ def with_sql(sql, *args)
+ _check_unfrozen_literal_string(sql)
+ super
+ end
+
+ # Check that placeholder string is frozen (or all entries
+ # in placeholder array are frozen).
+ def placeholder_literal_string_sql_append(sql, pls)
+ str = pls.str
+
+ if str.is_a?(Array)
+ str.each do |s|
+ _check_unfrozen_literal_string(s)
+ end
+ else
+ _check_unfrozen_literal_string(str)
+ end
+
+ super
+ end
+
+ private
+
+ # Base method that other methods used to check for whether a string should be allowed
+ # as literal SQL. Allows non-strings as well as frozen strings.
+ def _check_unfrozen_literal_string(str)
+ return if !str.is_a?(String) || str.frozen?
+
+ if str.is_a?(LiteralString)
+ _check_unfrozen_literal_string(str.source)
+ else
+ raise Error, "cannot treat unfrozen string as literal SQL: #{str.inspect}"
+ end
+ end
+
+ # Check literal strings appended to SQL.
+ def literal_literal_string_append(sql, v)
+ _check_unfrozen_literal_string(v)
+ super
+ end
+
+ # Check static SQL is not frozen.
+ def static_sql(sql)
+ _check_unfrozen_literal_string(sql)
+ super
+ end
+ end
+ end
+
+ Dataset.register_extension(:lit_require_frozen, LitRequireFrozen::DatasetMethods)
+ Database.register_extension(:lit_require_frozen, LitRequireFrozen::DatabaseMethods)
+end
* Changed:
MIT-LICENSE
--- /tmp/d20260402-1830-xiy46q/sequel-5.101.0/MIT-LICENSE 2026-04-02 05:28:10.907197565 +0000
+++ /tmp/d20260402-1830-xiy46q/sequel-5.103.0/MIT-LICENSE 2026-04-02 05:28:10.945197167 +0000
@@ -2 +2 @@
-Copyright (c) 2008-2023 Jeremy Evans
+Copyright (c) 2008-2026 Jeremy Evans and contributors
lib/sequel/adapters/jdbc/derby.rb
--- /tmp/d20260402-1830-xiy46q/sequel-5.101.0/lib/sequel/adapters/jdbc/derby.rb 2026-04-02 05:28:10.909197544 +0000
+++ /tmp/d20260402-1830-xiy46q/sequel-5.103.0/lib/sequel/adapters/jdbc/derby.rb 2026-04-02 05:28:10.947197146 +0000
@@ -2,0 +3,2 @@
+# SEQUEL6: Remove
+
lib/sequel/adapters/jdbc/h2.rb
--- /tmp/d20260402-1830-xiy46q/sequel-5.101.0/lib/sequel/adapters/jdbc/h2.rb 2026-04-02 05:28:10.909197544 +0000
+++ /tmp/d20260402-1830-xiy46q/sequel-5.103.0/lib/sequel/adapters/jdbc/h2.rb 2026-04-02 05:28:10.947197146 +0000
@@ -21 +21 @@
- run("COMMIT TRANSACTION #{transaction_id}", opts)
+ run("COMMIT TRANSACTION #{transaction_id}".freeze, opts)
@@ -39 +39 @@
- run("ROLLBACK TRANSACTION #{transaction_id}", opts)
+ run("ROLLBACK TRANSACTION #{transaction_id}".freeze, opts)
lib/sequel/adapters/postgres.rb
--- /tmp/d20260402-1830-xiy46q/sequel-5.101.0/lib/sequel/adapters/postgres.rb 2026-04-02 05:28:10.912197513 +0000
+++ /tmp/d20260402-1830-xiy46q/sequel-5.103.0/lib/sequel/adapters/postgres.rb 2026-04-02 05:28:10.949197125 +0000
@@ -730 +730 @@
- LiteralString.new("#{prepared_arg_placeholder}#{i}")
+ LiteralString.new("#{prepared_arg_placeholder}#{i}".freeze)
lib/sequel/adapters/shared/mssql.rb
--- /tmp/d20260402-1830-xiy46q/sequel-5.101.0/lib/sequel/adapters/shared/mssql.rb 2026-04-02 05:28:10.912197513 +0000
+++ /tmp/d20260402-1830-xiy46q/sequel-5.103.0/lib/sequel/adapters/shared/mssql.rb 2026-04-02 05:28:10.950197115 +0000
@@ -109 +109 @@
- sql = "DECLARE #{declarations.join(', ')}; EXECUTE @RC = #{name} #{values.join(', ')}; SELECT #{names.join(', ')}"
+ sql = "DECLARE #{declarations.join(', ')}; EXECUTE @RC = #{name} #{values.join(', ')}; SELECT #{names.join(', ')}".freeze
@@ -403 +403 @@
- run(ds.into(name).sql)
+ run(ds.into(name).sql.freeze)
@@ -881 +881 @@
- sql = multi_insert_sql(columns, values)[0]
+ sql = multi_insert_sql(columns, values)[0].freeze
lib/sequel/adapters/shared/mysql.rb
--- /tmp/d20260402-1830-xiy46q/sequel-5.101.0/lib/sequel/adapters/shared/mysql.rb 2026-04-02 05:28:10.913197502 +0000
+++ /tmp/d20260402-1830-xiy46q/sequel-5.103.0/lib/sequel/adapters/shared/mysql.rb 2026-04-02 05:28:10.950197115 +0000
@@ -43 +43 @@
- run("XA COMMIT #{literal(transaction_id)}", opts)
+ run("XA COMMIT #{literal(transaction_id)}".freeze, opts)
@@ -106 +106 @@
- metadata_dataset.with_sql(sql).each do |r|
+ metadata_dataset.with_sql(sql.freeze).each do |r|
@@ -118 +118 @@
- run("XA ROLLBACK #{literal(transaction_id)}", opts)
+ run("XA ROLLBACK #{literal(transaction_id)}".freeze, opts)
@@ -783 +783,2 @@
- ds = db.send(:metadata_dataset).with_sql(((opts[:extended] && (db.mariadb? || db.server_version < 50700)) ? 'EXPLAIN EXTENDED ' : 'EXPLAIN ') + select_sql).naked
+ sql = ((opts[:extended] && (db.mariadb? || db.server_version < 50700)) ? 'EXPLAIN EXTENDED ' : 'EXPLAIN ') + select_sql
+ ds = db.send(:metadata_dataset).with_sql(sql.freeze).naked
lib/sequel/adapters/shared/postgres.rb
--- /tmp/d20260402-1830-xiy46q/sequel-5.101.0/lib/sequel/adapters/shared/postgres.rb 2026-04-02 05:28:10.914197492 +0000
+++ /tmp/d20260402-1830-xiy46q/sequel-5.103.0/lib/sequel/adapters/shared/postgres.rb 2026-04-02 05:28:10.952197094 +0000
@@ -342 +342 @@
- run("COMMIT PREPARED #{literal(transaction_id)}", opts)
+ run("COMMIT PREPARED #{literal(transaction_id)}".freeze, opts)
@@ -419 +419 @@
- run("ALTER TABLE #{quote_schema_table(table)} ALTER COLUMN #{quote_identifier(column)} DROP DEFAULT", server_hash)
+ run("ALTER TABLE #{quote_schema_table(table)} ALTER COLUMN #{quote_identifier(column)} DROP DEFAULT".freeze, server_hash)
@@ -456 +456 @@
- self << create_function_sql(name, definition, opts)
+ self << create_function_sql(name, definition, opts).freeze
@@ -467 +467 @@
- self << create_language_sql(name, opts)
+ self << create_language_sql(name, opts).freeze
@@ -476 +476 @@
- self << create_schema_sql(name, opts)
+ self << create_schema_sql(name, opts).freeze
@@ -512 +512 @@
- self << create_trigger_sql(table, name, function, opts)
+ self << create_trigger_sql(table, name, function, opts).freeze
@@ -545 +545 @@
- run "DO #{"LANGUAGE #{literal(language.to_s)} " if language}#{literal(code)}"
+ run "DO #{"LANGUAGE #{literal(language.to_s)} " if language}#{literal(code)}".freeze
@@ -555 +555 @@
- self << drop_function_sql(name, opts)
+ self << drop_function_sql(name, opts).freeze
@@ -564 +564 @@
- self << drop_language_sql(name, opts)
+ self << drop_language_sql(name, opts).freeze
@@ -573 +573 @@
- self << drop_schema_sql(name, opts)
+ self << drop_schema_sql(name, opts).freeze
@@ -584 +584 @@
- self << drop_trigger_sql(table, name, opts)
+ self << drop_trigger_sql(table, name, opts).freeze
@@ -748 +748 @@
- self << rename_schema_sql(name, new_name)
+ self << rename_schema_sql(name, new_name).freeze
@@ -759 +759 @@
- run "REFRESH MATERIALIZED VIEW#{' CONCURRENTLY' if opts[:concurrently]} #{quote_schema_table(name)}"
+ run "REFRESH MATERIALIZED VIEW#{' CONCURRENTLY' if opts[:concurrently]} #{quote_schema_table(name)}".freeze
@@ -772 +772 @@
- seq_ds = metadata_dataset.from(:pg_sequence).where(:seqrelid=>regclass_oid(LiteralString.new(seq)))
+ seq_ds = metadata_dataset.from(:pg_sequence).where(:seqrelid=>regclass_oid(LiteralString.new(seq.freeze)))
@@ -787 +787 @@
- run("ROLLBACK PREPARED #{literal(transaction_id)}", opts)
+ run("ROLLBACK PREPARED #{literal(transaction_id)}".freeze, opts)
@@ -1472 +1472 @@
- cols[-1] = Sequel.lit("PERIOD #{quote_identifier(cols[-1])}")
+ cols[-1] = Sequel.lit("PERIOD #{quote_identifier(cols[-1])}".freeze)
lib/sequel/adapters/shared/sqlite.rb
--- /tmp/d20260402-1830-xiy46q/sequel-5.101.0/lib/sequel/adapters/shared/sqlite.rb 2026-04-02 05:28:10.914197492 +0000
+++ /tmp/d20260402-1830-xiy46q/sequel-5.103.0/lib/sequel/adapters/shared/sqlite.rb 2026-04-02 05:28:10.952197094 +0000
@@ -198 +198 @@
- metadata_dataset.with_sql("PRAGMA table_#{'x' if sqlite_version > 33100}info(?)", input_identifier_meth(opts[:dataset]).call(table_name))
+ metadata_dataset.with_sql("PRAGMA table_#{'x' if sqlite_version > 33100}info(?)".freeze, input_identifier_meth(opts[:dataset]).call(table_name))
@@ -410 +410 @@
- c[:default] = LiteralString.new(c[:default]) if c[:default]
+ c[:default] = LiteralString.new(c[:default]).freeze if c[:default]
@@ -687 +687 @@
- ds = db.send(:metadata_dataset).clone(:sql=>"EXPLAIN #{select_sql}")
+ ds = db.send(:metadata_dataset).clone(:sql=>"EXPLAIN #{select_sql}".freeze)
lib/sequel/adapters/sqlite.rb
--- /tmp/d20260402-1830-xiy46q/sequel-5.101.0/lib/sequel/adapters/sqlite.rb 2026-04-02 05:28:10.914197492 +0000
+++ /tmp/d20260402-1830-xiy46q/sequel-5.103.0/lib/sequel/adapters/sqlite.rb 2026-04-02 05:28:10.952197094 +0000
@@ -391 +391 @@
- LiteralString.new("#{prepared_arg_placeholder}#{k.to_s.gsub('.', '__')}")
+ LiteralString.new("#{prepared_arg_placeholder}#{k.to_s.gsub('.', '__')}".freeze)
lib/sequel/adapters/tinytds.rb
--- /tmp/d20260402-1830-xiy46q/sequel-5.101.0/lib/sequel/adapters/tinytds.rb 2026-04-02 05:28:10.914197492 +0000
+++ /tmp/d20260402-1830-xiy46q/sequel-5.103.0/lib/sequel/adapters/tinytds.rb 2026-04-02 05:28:10.952197094 +0000
@@ -208 +208 @@
- LiteralString.new("@#{k.to_s.gsub('.', '__')}")
+ LiteralString.new("@#{k.to_s.gsub('.', '__')}".freeze)
lib/sequel/connection_pool.rb
--- /tmp/d20260402-1830-xiy46q/sequel-5.101.0/lib/sequel/connection_pool.rb 2026-04-02 05:28:10.915197481 +0000
+++ /tmp/d20260402-1830-xiy46q/sequel-5.103.0/lib/sequel/connection_pool.rb 2026-04-02 05:28:10.953197083 +0000
@@ -133,0 +134,6 @@
+ # Only for use by extension that need to disconnect a connection inside acquire.
+ # Takes the connection and any arguments accepted by acquire.
+ def disconnect_acquired_connection(conn, *)
+ disconnect_connection(conn)
+ end
+
lib/sequel/connection_pool/sharded_timed_queue.rb
--- /tmp/d20260402-1830-xiy46q/sequel-5.101.0/lib/sequel/connection_pool/sharded_timed_queue.rb 2026-04-02 05:28:10.916197471 +0000
+++ /tmp/d20260402-1830-xiy46q/sequel-5.103.0/lib/sequel/connection_pool/sharded_timed_queue.rb 2026-04-02 05:28:10.954197073 +0000
@@ -74 +74 @@
- break unless (conn = queue.pop(timeout: 0)) && !conns[conn]
+ break unless (conn = available(queue, server)) && !conns[conn]
@@ -94 +94 @@
- # and then the method will only disconnect connectsion from those specified shards.
+ # and then the method will only disconnect connections from those specified shards.
@@ -98 +98,3 @@
- while conn = queue.pop(timeout: 0)
+ nconns = 0
+ while conn = available(queue, server)
+ nconns += 1
@@ -101 +103 @@
- fill_queue(server)
+ fill_queue(server, nconns)
@@ -135 +137 @@
- fill_queue(server)
+ fill_queue(server, 1)
@@ -170 +172 @@
- while conn = queue.pop(timeout: 0)
+ while conn = available(queue, server)
@@ -227,0 +230,6 @@
+ # Only for use by extension that need to disconnect a connection inside acquire.
+ # Takes the connection and any arguments accepted by acquire.
+ def disconnect_acquired_connection(conn, _, server)
+ disconnect_pool_connection(conn, server)
+ end
+
@@ -247 +255,4 @@
- def fill_queue(server)
+ #
+ # nconns specifies the maximum number of connections to add, which should
+ # be the number of connections that were disconnected.
+ def fill_queue(server, nconns)
@@ -249 +260 @@
- if queue.num_waiting > 0
+ if nconns > 0 && queue.num_waiting > 0
@@ -251 +262,2 @@
- while queue.num_waiting > 0 && (conn = try_make_new(server))
+ while nconns > 0 && queue.num_waiting > 0 && (conn = try_make_new(server))
+ nconns -= 1
@@ -300 +312 @@
- fill_queue(server)
+ fill_queue(server, to_disconnect.size)
@@ -314 +326 @@
- if conn = queue.pop(timeout: 0) || try_make_new(server) || queue.pop(timeout: @timeout)
+ if conn = available(queue, server) || try_make_new(server) || wait_until_available(queue, server)
@@ -319,0 +332,13 @@
+ end
+
+ # Return the next connection in the pool if there is one available. Returns nil
+ # if no connection is currently available.
+ def available(queue, _server)
+ queue.pop(timeout: 0)
+ end
+
+ # Return the next connection in the pool if there is one available. If not, wait
+ # until the timeout for a connection to become available. If there is still no
+ # available connection, return nil.
+ def wait_until_available(queue, _server)
+ queue.pop(timeout: @timeout)
lib/sequel/connection_pool/timed_queue.rb
--- /tmp/d20260402-1830-xiy46q/sequel-5.101.0/lib/sequel/connection_pool/timed_queue.rb 2026-04-02 05:28:10.916197471 +0000
+++ /tmp/d20260402-1830-xiy46q/sequel-5.103.0/lib/sequel/connection_pool/timed_queue.rb 2026-04-02 05:28:10.954197073 +0000
@@ -45 +45 @@
- break unless (conn = @queue.pop(timeout: 0)) && !conns[conn]
+ break unless (conn = available) && !conns[conn]
@@ -62 +62,3 @@
- while conn = @queue.pop(timeout: 0)
+ nconns = 0
+ while conn = available
+ nconns += 1
@@ -65 +67 @@
- fill_queue
+ fill_queue(nconns)
@@ -97 +99 @@
- fill_queue
+ fill_queue(1)
@@ -159,2 +161,5 @@
- def fill_queue
- if @queue.num_waiting > 0
+ #
+ # nconns specifies the maximum number of connections to add, which should
+ # be the number of connections that were disconnected.
+ def fill_queue(nconns)
+ if nconns > 0 && @queue.num_waiting > 0
@@ -162 +167 @@
- while @queue.num_waiting > 0 && (conn = try_make_new)
+ while nconns > 0 && @queue.num_waiting > 0 && (conn = try_make_new)
@@ -210 +215 @@
- fill_queue
+ fill_queue(to_disconnect.size)
@@ -223 +228 @@
- if conn = @queue.pop(timeout: 0) || try_make_new || @queue.pop(timeout: @timeout)
+ if conn = available || try_make_new || wait_until_available
@@ -228,0 +234,13 @@
+ end
+
+ # Return the next connection in the pool if there is one available. Returns nil
+ # if no connection is currently available.
+ def available
+ @queue.pop(timeout: 0)
+ end
+
+ # Return the next connection in the pool if there is one available. If not, wait
+ # until the timeout for a connection to become available. If there is still no
+ # available connection, return nil.
+ def wait_until_available
+ @queue.pop(timeout: @timeout)
lib/sequel/database/schema_generator.rb
--- /tmp/d20260402-1830-xiy46q/sequel-5.101.0/lib/sequel/database/schema_generator.rb 2026-04-02 05:28:10.918197450 +0000
+++ /tmp/d20260402-1830-xiy46q/sequel-5.103.0/lib/sequel/database/schema_generator.rb 2026-04-02 05:28:10.956197052 +0000
@@ -5,0 +6,27 @@
+ module ColumnOptionMerger
+ private
+
+ # Merge given options into the column's default options. For backwards compatibility,
+ # the options take priority, but in cases where the option value overrides the argument
+ # value, and the values are different, we warn as this is likely to be an error in the
+ # code.
+ def _merge_column_options(defaults, opts)
+ defaults.merge!(opts) do |k, defv, v|
+ unless defv == v
+ # :nocov:
+ if RUBY_VERSION >= "3.2"
+ # :nocov:
+ caller_loc = Thread.each_caller_location do |loc|
+ break loc unless loc.path == __FILE__
+ end
+ caller_loc &&= "#{caller_loc.path}:#{caller_loc.lineno}: "
+ end
+ warn("#{caller_loc}#{k.inspect} option value (#{v.inspect}) overrides argument value (#{defv.inspect})")
+ end
+
+ v
+ end
+ end
+ end
+ private_constant :ColumnOptionMerger
+
@@ -19,0 +47,2 @@
+ include ColumnOptionMerger
+
@@ -176 +205 @@
- columns << {:name => name, :type => type}.merge!(opts)
+ columns << _merge_column_options({:name => name, :type => type}, opts)
@@ -182 +211 @@
-
+
@@ -249 +278 @@
- column(name, Integer, opts)
+ column(name, opts.fetch(:type, Integer), opts)
@@ -431,0 +461,2 @@
+ include ColumnOptionMerger
+
@@ -457 +488 @@
- op = {:op => :add_column, :name => name, :type => type}.merge!(opts)
+ op = _merge_column_options({:op => :add_column, :name => name, :type => type}, opts)
@@ -522 +553 @@
- add_column(name, Integer, {:table=>table}.merge!(opts))
+ add_column(name, opts.fetch(:type, Integer), {:table=>table}.merge!(opts))
lib/sequel/database/schema_methods.rb
--- /tmp/d20260402-1830-xiy46q/sequel-5.101.0/lib/sequel/database/schema_methods.rb 2026-04-02 05:28:10.918197450 +0000
+++ /tmp/d20260402-1830-xiy46q/sequel-5.103.0/lib/sequel/database/schema_methods.rb 2026-04-02 05:28:10.956197052 +0000
@@ -822 +822 @@
- run(create_table_as_sql(name, sql, options))
+ run(create_table_as_sql(name, sql, options).freeze)
lib/sequel/dataset/placeholder_literalizer.rb
--- /tmp/d20260402-1830-xiy46q/sequel-5.101.0/lib/sequel/dataset/placeholder_literalizer.rb 2026-04-02 05:28:10.919197440 +0000
+++ /tmp/d20260402-1830-xiy46q/sequel-5.103.0/lib/sequel/dataset/placeholder_literalizer.rb 2026-04-02 05:28:10.957197041 +0000
@@ -119,0 +120,2 @@
+ frags.each(&:freeze)
+ frags.freeze
@@ -127,0 +130 @@
+ ds.opts[:sql].freeze
lib/sequel/dataset/prepared_statements.rb
--- /tmp/d20260402-1830-xiy46q/sequel-5.101.0/lib/sequel/dataset/prepared_statements.rb 2026-04-02 05:28:10.920197429 +0000
+++ /tmp/d20260402-1830-xiy46q/sequel-5.103.0/lib/sequel/dataset/prepared_statements.rb 2026-04-02 05:28:10.958197031 +0000
@@ -57 +57 @@
- sql = prepared_sql
+ sql = prepared_sql.freeze
@@ -226 +226 @@
- with_sql(prepared_sql)
+ with_sql(prepared_sql.freeze)
@@ -290 +290 @@
- sql = literal(Sequel::SQL::PlaceholderLiteralString.new(@opts[:prepared_sql_frags], @opts[:bind_arguments], false))
+ sql = literal(Sequel::SQL::PlaceholderLiteralString.new(@opts[:prepared_sql_frags], @opts[:bind_arguments], false)).freeze
@@ -322,0 +323,3 @@
+ frags.freeze
+ frags.each(&:freeze)
+ prepared_sql.freeze
@@ -412 +415 @@
- sql = ps.prepared_sql
+ sql = ps.prepared_sql.freeze
lib/sequel/dataset/query.rb
--- /tmp/d20260402-1830-xiy46q/sequel-5.101.0/lib/sequel/dataset/query.rb 2026-04-02 05:28:10.920197429 +0000
+++ /tmp/d20260402-1830-xiy46q/sequel-5.103.0/lib/sequel/dataset/query.rb 2026-04-02 05:28:10.958197031 +0000
@@ -1304 +1304 @@
- sql = public_send(sql, *args)
+ sql = public_send(sql, *args).freeze
@@ -1477 +1477,4 @@
-
+
+ PAREN_WRAPPER = ["(".freeze, ")".freeze].freeze
+ private_constant :PAREN_WRAPPER
+
@@ -1498 +1501 @@
- LiteralString.new("(#{expr})")
+ SQL::PlaceholderLiteralString.new(PAREN_WRAPPER, [expr])
lib/sequel/dataset/sql.rb
--- /tmp/d20260402-1830-xiy46q/sequel-5.101.0/lib/sequel/dataset/sql.rb 2026-04-02 05:28:10.920197429 +0000
+++ /tmp/d20260402-1830-xiy46q/sequel-5.103.0/lib/sequel/dataset/sql.rb 2026-04-02 05:28:10.958197031 +0000
@@ -56 +56 @@
- sql << v
+ literal_literal_string_append(sql, v)
@@ -1424,0 +1425,5 @@
+ end
+
+ # Append string to SQL string.
+ def literal_literal_string_append(sql, v)
+ sql << v
lib/sequel/extensions/connection_expiration.rb
--- /tmp/d20260402-1830-xiy46q/sequel-5.101.0/lib/sequel/extensions/connection_expiration.rb 2026-04-02 05:28:10.922197408 +0000
+++ /tmp/d20260402-1830-xiy46q/sequel-5.103.0/lib/sequel/extensions/connection_expiration.rb 2026-04-02 05:28:10.960197010 +0000
@@ -94 +94 @@
- disconnect_connection(conn)
+ disconnect_acquired_connection(conn, *a)
lib/sequel/extensions/connection_validator.rb
--- /tmp/d20260402-1830-xiy46q/sequel-5.101.0/lib/sequel/extensions/connection_validator.rb 2026-04-02 05:28:10.922197408 +0000
+++ /tmp/d20260402-1830-xiy46q/sequel-5.103.0/lib/sequel/extensions/connection_validator.rb 2026-04-02 05:28:10.960197010 +0000
@@ -121 +121 @@
- disconnect_connection(conn)
+ disconnect_acquired_connection(conn, *a)
lib/sequel/extensions/dataset_run.rb
--- /tmp/d20260402-1830-xiy46q/sequel-5.101.0/lib/sequel/extensions/dataset_run.rb 2026-04-02 05:28:10.922197408 +0000
+++ /tmp/d20260402-1830-xiy46q/sequel-5.103.0/lib/sequel/extensions/dataset_run.rb 2026-04-02 05:28:10.960197010 +0000
@@ -33 +33 @@
- db.run(sql, :server=>server)
+ db.run(sql.freeze, :server=>server)
@@ -35 +35 @@
- db.run(sql)
+ db.run(sql.freeze)
lib/sequel/extensions/date_arithmetic.rb
--- /tmp/d20260402-1830-xiy46q/sequel-5.101.0/lib/sequel/extensions/date_arithmetic.rb 2026-04-02 05:28:10.923197398 +0000
+++ /tmp/d20260402-1830-xiy46q/sequel-5.103.0/lib/sequel/extensions/date_arithmetic.rb 2026-04-02 05:28:10.961196999 +0000
@@ -85,2 +85,2 @@
- MYSQL_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s.upcase[0...-1]).freeze}).freeze
- MSSQL_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s[0...-1]).freeze}).freeze
+ MYSQL_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s.upcase[0...-1].freeze).freeze}).freeze
+ MSSQL_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s[0...-1].freeze).freeze}).freeze
@@ -88 +88 @@
- DERBY_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit("SQL_TSI_#{s.to_s.upcase[0...-1]}").freeze}).freeze
+ DERBY_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit("SQL_TSI_#{s.to_s.upcase[0...-1]}".freeze).freeze}).freeze
@@ -90 +90 @@
- DB2_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s).freeze}).freeze
+ DB2_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s.freeze).freeze}).freeze
@@ -110 +110 @@
- placeholder << "#{', ' unless placeholder.empty?}#{sql_unit} := "
+ placeholder << "#{', ' unless placeholder.empty?}#{sql_unit} := ".freeze
@@ -159 +159 @@
- expr = Sequel.lit(["{fn timestampadd(#{sql_unit}, ", ", timestamp(", "))}"], value, expr)
+ expr = Sequel.lit(["{fn timestampadd(#{sql_unit}, ".freeze, ", timestamp(", "))}"], value, expr)
lib/sequel/extensions/migration.rb
--- /tmp/d20260402-1830-xiy46q/sequel-5.101.0/lib/sequel/extensions/migration.rb 2026-04-02 05:28:10.924197387 +0000
+++ /tmp/d20260402-1830-xiy46q/sequel-5.103.0/lib/sequel/extensions/migration.rb 2026-04-02 05:28:10.963196978 +0000
@@ -189,16 +189,13 @@
- begin
- instance_exec(&block)
- rescue
- just_raise = true
- end
- if just_raise
- Proc.new{raise Sequel::Error, "irreversible migration method used in #{block.source_location.first}, you may need to write your own down method"}
- else
- actions = @actions.reverse
- Proc.new do
- actions.each do |a|
- pr = a.last.is_a?(Proc) ? a.pop : nil
- # Allow calling private methods as the reversing methods are private
- send(*a, &pr)
- end
- end
+ instance_exec(&block)
+ rescue NoMethodError => e
+ Proc.new{raise Sequel::Error, "irreversible migration method \"#{e.name}\" used in #{block.source_location.first}, you may need to write your own down method"}
+ rescue => e
+ Proc.new{raise Sequel::Error, "unable to reverse migration due to #{e.class} in #{block.source_location.first}, you may need to write your own down method"}
+ else
+ actions = @actions.reverse
+ Proc.new do
+ actions.each do |a|
+ pr = a.last.is_a?(Proc) ? a.pop : nil
+ # Allow calling private methods as the reversing methods are private
+ send(*a, &pr)
+ end
@@ -273 +270 @@
- raise if args.first.is_a?(Array)
+ super if args.first.is_a?(Array)
lib/sequel/extensions/pg_enum.rb
--- /tmp/d20260402-1830-xiy46q/sequel-5.101.0/lib/sequel/extensions/pg_enum.rb 2026-04-02 05:28:10.926197366 +0000
+++ /tmp/d20260402-1830-xiy46q/sequel-5.103.0/lib/sequel/extensions/pg_enum.rb 2026-04-02 05:28:10.964196968 +0000
@@ -130 +130 @@
- run(sql)
+ run(sql.freeze)
lib/sequel/model/associations.rb
--- /tmp/d20260402-1830-xiy46q/sequel-5.101.0/lib/sequel/model/associations.rb 2026-04-02 05:28:10.932197303 +0000
+++ /tmp/d20260402-1830-xiy46q/sequel-5.103.0/lib/sequel/model/associations.rb 2026-04-02 05:28:10.971196895 +0000
@@ -323 +323 @@
- objects.concat(ds.with_sql(sql).to_a)
+ objects.concat(ds.with_sql(sql.freeze).to_a)
lib/sequel/plugins/dirty.rb
--- /tmp/d20260402-1830-xiy46q/sequel-5.101.0/lib/sequel/plugins/dirty.rb 2026-04-02 05:28:10.936197261 +0000
+++ /tmp/d20260402-1830-xiy46q/sequel-5.103.0/lib/sequel/plugins/dirty.rb 2026-04-02 05:28:10.976196842 +0000
@@ -237,2 +237,5 @@
- check_missing_initial_value(column)
- iv[column] = get_column_value(column)
+ if db_schema[column]
+ check_missing_initial_value(column)
+ iv[column] = get_column_value(column)
+ end
+
lib/sequel/plugins/mssql_optimistic_locking.rb
--- /tmp/d20260402-1830-xiy46q/sequel-5.101.0/lib/sequel/plugins/mssql_optimistic_locking.rb 2026-04-02 05:28:10.939197230 +0000
+++ /tmp/d20260402-1830-xiy46q/sequel-5.103.0/lib/sequel/plugins/mssql_optimistic_locking.rb 2026-04-02 05:28:10.978196821 +0000
@@ -58 +58 @@
- rows = ds.clone(ds.send(:default_server_opts, :sql=>ds.output(nil, [Sequel[:inserted][lc]]).update_sql(columns))).all
+ rows = ds.clone(ds.send(:default_server_opts, :sql=>ds.output(nil, [Sequel[:inserted][lc]]).update_sql(columns).freeze)).all
lib/sequel/plugins/pg_xmin_optimistic_locking.rb
--- /tmp/d20260402-1830-xiy46q/sequel-5.101.0/lib/sequel/plugins/pg_xmin_optimistic_locking.rb 2026-04-02 05:28:10.940197219 +0000
+++ /tmp/d20260402-1830-xiy46q/sequel-5.103.0/lib/sequel/plugins/pg_xmin_optimistic_locking.rb 2026-04-02 05:28:10.979196811 +0000
@@ -102 +102 @@
- rows = ds.clone(ds.send(:default_server_opts, :sql=>ds.returning(:xmin).update_sql(columns))).all
+ rows = ds.clone(ds.send(:default_server_opts, :sql=>ds.returning(:xmin).update_sql(columns).freeze)).all
lib/sequel/plugins/serialization.rb
--- /tmp/d20260402-1830-xiy46q/sequel-5.101.0/lib/sequel/plugins/serialization.rb 2026-04-02 05:28:10.940197219 +0000
+++ /tmp/d20260402-1830-xiy46q/sequel-5.103.0/lib/sequel/plugins/serialization.rb 2026-04-02 05:28:10.980196800 +0000
@@ -32,0 +33,9 @@
+ # Note that use of an unsafe serialization method can result in an attack vector
+ # (potentially allowing remote code execution) if an attacker has the ability to
+ # store data directly in the underlying column. This would affect the marshal
+ # serialization format, and on older versions of Ruby, potentially the yaml and
+ # json serialization formats as well. It can also affect custom formats. You
+ # should ensure that attackers do not have access to store data directly in the
+ # underlying column when using this plugin (especially when using an unsafe
+ # serialization method).
+ #
@@ -100 +109 @@
- v = v.unpack('m')[0] unless v[0..1] == "\x04\x08"
+ v = v.unpack('m')[0] unless v.start_with?("\x04\x08")
lib/sequel/version.rb
--- /tmp/d20260402-1830-xiy46q/sequel-5.101.0/lib/sequel/version.rb 2026-04-02 05:28:10.945197167 +0000
+++ /tmp/d20260402-1830-xiy46q/sequel-5.103.0/lib/sequel/version.rb 2026-04-02 05:28:10.984196758 +0000
@@ -9 +9 @@
- MINOR = 101
+ MINOR = 103 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bumps sequel from 5.101.0 to 5.103.0.
Changelog
Sourced from sequel's changelog.
Commits
37f97a1Bump version to 5.103.08792c73Update specs to work with minitest 6.0.323634d8Have column and add_column in the generators warn if option values override a...fb3df68Simplify code in lit_require_frozen930b886Show method name causing change migration to be irreversible in exception mes...1d68f77Always call super in Model#change_column_value in dirty plugin5c48c9dMake dirty plugin handle the Model#[]= calls with keys that are not model col...e849fd3Fix doc typo: s/get get/to get/66e72a3Document potential security concerns in the serialization plugindf447b4Use start_with? in the serialization pluginDependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting
@dependabot rebase.Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR:
@dependabot rebasewill rebase this PR@dependabot recreatewill recreate this PR, overwriting any edits that have been made to it@dependabot show <dependency name> ignore conditionswill show all of the ignore conditions of the specified dependency@dependabot ignore this major versionwill close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this minor versionwill close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this dependencywill close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)