sequel 5.81.0 → 5.83.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +30 -0
- data/bin/sequel +9 -4
- data/doc/opening_databases.rdoc +3 -0
- data/doc/release_notes/5.82.0.txt +61 -0
- data/doc/release_notes/5.83.0.txt +56 -0
- data/doc/testing.rdoc +14 -0
- data/lib/sequel/adapters/jdbc/derby.rb +1 -1
- data/lib/sequel/adapters/shared/db2.rb +1 -1
- data/lib/sequel/adapters/shared/mssql.rb +14 -2
- data/lib/sequel/adapters/shared/postgres.rb +66 -7
- data/lib/sequel/adapters/shared/sqlite.rb +1 -1
- data/lib/sequel/connection_pool/sharded_threaded.rb +26 -10
- data/lib/sequel/connection_pool/threaded.rb +26 -10
- data/lib/sequel/database/connecting.rb +20 -26
- data/lib/sequel/database/misc.rb +26 -8
- data/lib/sequel/database/schema_methods.rb +15 -1
- data/lib/sequel/dataset/sql.rb +13 -0
- data/lib/sequel/extensions/stdio_logger.rb +48 -0
- data/lib/sequel/extensions/string_agg.rb +15 -2
- data/lib/sequel/plugins/association_pks.rb +1 -1
- data/lib/sequel/plugins/defaults_setter.rb +16 -4
- data/lib/sequel/plugins/optimistic_locking.rb +2 -0
- data/lib/sequel/plugins/tactical_eager_loading.rb +6 -2
- data/lib/sequel/plugins/validate_associated.rb +1 -1
- data/lib/sequel/version.rb +1 -1
- metadata +8 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 66956ac28806c0389a6c809b0aa70d2746a7aff47fd5b039d238c08f621cdbff
|
4
|
+
data.tar.gz: d2b8d3f88b13432c60e6164fda3577725300e18a0dfa03682871405d074d7ba0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 55d45f7c3cb7154f275ddf5ea3649d78a38f147abdb49f1286358d8dbec9f607e3bf43c9ebe1dc31276d28820f455fc82dcce7b4c9808b325288380acf90edf4
|
7
|
+
data.tar.gz: b8301c7880dcb598ca027d225f5be791200ac1f13f4efe5351222d351b218019351a8efa1f485d499a0650cd4213ba0a148c3f10f0a67aa0b3c04f4ee611b074
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,33 @@
|
|
1
|
+
=== 5.83.0 (2024-08-01)
|
2
|
+
|
3
|
+
* Make optimistic_locking plugin not keep lock column in changed_columns after updating instance (jeremyevans) (#2196)
|
4
|
+
|
5
|
+
* Have defaults_setter plugin pass model instance to default_values callable if it has arity 1 (pedrocarmona) (#2195)
|
6
|
+
|
7
|
+
* Support string_agg extension on SQLite 3.44+ (segiddins) (#2191)
|
8
|
+
|
9
|
+
* Support schema-qualified table names when using create_table :temp with a Sequel::SQL::QualifiedIdentifier (jeremyevans) (#2185)
|
10
|
+
|
11
|
+
* Support MERGE WHEN NOT MATCHED BY SOURCE on PostgreSQL 17+ (jeremyevans)
|
12
|
+
|
13
|
+
* Add stdio_logger extension for a minimal logger that Sequel::Database can use (jeremyevans)
|
14
|
+
|
15
|
+
* Simplify Database#inspect output to database_type, host, database, and user (jeremyevans)
|
16
|
+
|
17
|
+
=== 5.82.0 (2024-07-01)
|
18
|
+
|
19
|
+
* Limit tactically eager loading to objects that have the same association reflection (jeremyevans) (#2181)
|
20
|
+
|
21
|
+
* Fix race condition in threaded/sharded_threaded connection pools that could cause stalls (jeremyevans)
|
22
|
+
|
23
|
+
* Emulate dropping a unique column or a column that is part of an index on SQLite 3.35.0+ (jeremyevans) (#2176)
|
24
|
+
|
25
|
+
* Support MERGE RETURNING on PostgreSQL 17+ (jeremyevans)
|
26
|
+
|
27
|
+
* Remove use of logger library in bin/sequel (jeremyevans)
|
28
|
+
|
29
|
+
* Support :connect_opts_proc Database option for late binding options (jeremyevans) (#2164)
|
30
|
+
|
1
31
|
=== 5.81.0 (2024-06-01)
|
2
32
|
|
3
33
|
* Fix ignored block warnings in a couple plugin apply methods on Ruby 3.4 (jeremyevans)
|
data/bin/sequel
CHANGED
@@ -61,8 +61,7 @@ options = OptionParser.new do |opts|
|
|
61
61
|
end
|
62
62
|
|
63
63
|
opts.on("-E", "--echo", "echo SQL statements") do
|
64
|
-
|
65
|
-
loggers << Logger.new($stdout)
|
64
|
+
loggers << $stdout
|
66
65
|
end
|
67
66
|
|
68
67
|
opts.on("-I", "--include dir", "specify $LOAD_PATH directory") do |v|
|
@@ -70,8 +69,9 @@ options = OptionParser.new do |opts|
|
|
70
69
|
end
|
71
70
|
|
72
71
|
opts.on("-l", "--log logfile", "log SQL statements to log file") do |v|
|
73
|
-
|
74
|
-
|
72
|
+
file = File.open(v, 'a')
|
73
|
+
file.sync = true
|
74
|
+
loggers << file
|
75
75
|
end
|
76
76
|
|
77
77
|
opts.on("-L", "--load-dir DIR", "loads all *.rb under specifed directory") do |v|
|
@@ -155,6 +155,11 @@ begin
|
|
155
155
|
end
|
156
156
|
end
|
157
157
|
|
158
|
+
unless loggers.empty?
|
159
|
+
Sequel.extension :stdio_logger
|
160
|
+
loggers.map!{|io| Sequel::StdioLogger.new(io)}
|
161
|
+
end
|
162
|
+
|
158
163
|
DB = connect_proc[db]
|
159
164
|
load_dirs.each{|d| d.is_a?(Array) ? require(d.first) : Dir["#{d}/**/*.rb"].each{|f| load(f)}}
|
160
165
|
if migrate_dir
|
data/doc/opening_databases.rdoc
CHANGED
@@ -79,6 +79,9 @@ These options are shared by all adapters unless otherwise noted.
|
|
79
79
|
or string with extensions separated by columns. These extensions are loaded after
|
80
80
|
connections are made by the :preconnect option.
|
81
81
|
:cache_schema :: Whether schema should be cached for this database (true by default)
|
82
|
+
:connect_opts_proc :: Callable object for modifying options hash used when connecting, designed for
|
83
|
+
cases where the option values (e.g. password) are automatically rotated on
|
84
|
+
a regular basis without involvement from the application using Sequel.
|
82
85
|
:default_string_column_size :: The default size for string columns (255 by default)
|
83
86
|
:host :: The hostname of the database server to which to connect
|
84
87
|
:keep_reference :: Whether to keep a reference to the database in Sequel::DATABASES (true by default)
|
@@ -0,0 +1,61 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* MERGE RETURNING is now supported when using PostgreSQL 17+. For
|
4
|
+
datasets supporting RETURNING, calling merge with a block
|
5
|
+
will yield each returned row:
|
6
|
+
|
7
|
+
DB[:table1].
|
8
|
+
returning.
|
9
|
+
merge_using(:table2, column1: :column2).
|
10
|
+
merge_insert(column3: :column4).
|
11
|
+
merge do |row|
|
12
|
+
# ...
|
13
|
+
end
|
14
|
+
# MERGE INTO "table1" USING "table2"
|
15
|
+
# ON ("column1" = "column2")
|
16
|
+
# WHEN NOT MATCHED THEN
|
17
|
+
# INSERT ("column3") VALUES ("column3")
|
18
|
+
# RETURNING *
|
19
|
+
|
20
|
+
* A :connect_opts_proc Database option is now supported, to allow
|
21
|
+
support for late-binding Database options. If provided, this
|
22
|
+
should be a callable object that is called with the options
|
23
|
+
used for connecting, and can modify the options. This makes
|
24
|
+
it simple to support authentication schemes that rotate
|
25
|
+
passwords automatically without user involvement:
|
26
|
+
|
27
|
+
Sequel.connect('postgres://user@host/database',
|
28
|
+
connect_opts_proc: lambda do |opts|
|
29
|
+
opts[:password] = SomeAuthLibrary.get_current_password(opts[:user])
|
30
|
+
end)
|
31
|
+
|
32
|
+
Note that the jdbc adapter relies on URIs and not option hashes,
|
33
|
+
so when using the jdbc adapter with this feature, you'll generally
|
34
|
+
need to set the :uri option.
|
35
|
+
|
36
|
+
= Other Improvements
|
37
|
+
|
38
|
+
* A race condition in the threaded connection pools that could result
|
39
|
+
in a delay or timeout error in checking out connections in low-traffic
|
40
|
+
environments has been fixed.
|
41
|
+
|
42
|
+
* Sequel now supports dropping a unique column or a column that is
|
43
|
+
part of an index on SQLite 3.35.0+, with the same emulation approach
|
44
|
+
it uses in earlier SQLite versions.
|
45
|
+
|
46
|
+
* The tactical_eager_loading plugin now handles cases where inheritance
|
47
|
+
is used and the objects used include associations with the same name
|
48
|
+
but different definitions. Sequel will now only eager load the
|
49
|
+
association for objects that use the same association definition as
|
50
|
+
the receiver.
|
51
|
+
|
52
|
+
= Backwards Compatibility
|
53
|
+
|
54
|
+
* bin/sequel no longer requires logger if passed the -E or -l options.
|
55
|
+
Instead, it uses a simple implementation that supports only
|
56
|
+
debug/warn/info/error methods. If you are using bin/sequel and
|
57
|
+
depending on the log format produced by the logger library, or
|
58
|
+
calling methods on the logger object other than
|
59
|
+
debug/warn/info/error, you'll need to update your code. This change
|
60
|
+
was made because logger is moving out of stdlib in a future Ruby
|
61
|
+
version.
|
@@ -0,0 +1,56 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* MERGE WHEN NOT MATCHED BY SOURCE is now supported when using
|
4
|
+
PostgreSQL 17+. You can use this SQL syntax via the following
|
5
|
+
Dataset methods:
|
6
|
+
|
7
|
+
* merge_delete_when_not_matched_by_source
|
8
|
+
* merge_update_when_not_matched_by_source
|
9
|
+
* merge_do_nothing_when_not_matched_by_source
|
10
|
+
|
11
|
+
These are similar to the existing merge_delete, merge_update,
|
12
|
+
and merge_do_nothing_when_matched, except they use
|
13
|
+
WHEN NOT MATCHED BY SOURCE instead of WHEN MATCHED.
|
14
|
+
|
15
|
+
* An stdio_logger extension has been added. This adds the
|
16
|
+
Sequel::StdioLogger class, which is a minimal logger implementation
|
17
|
+
that is compatible for usage with Sequel::Database. Example:
|
18
|
+
|
19
|
+
Sequel.extension :stdio_logger
|
20
|
+
DB.loggers << Sequel::StdioLogger.new($stdout)
|
21
|
+
|
22
|
+
= Other Improvements
|
23
|
+
|
24
|
+
* Database#inspect now only displays the database type, host, database
|
25
|
+
name, and user. In addition to being easier to read, this also
|
26
|
+
prevents displaying the password, enhancing security.
|
27
|
+
|
28
|
+
* The string_agg extension now supports SQLite 3.44+.
|
29
|
+
|
30
|
+
* The defaults_setter plugin now passes the model instance to a
|
31
|
+
default_values proc if the proc has arity 1. This allows default
|
32
|
+
values to depend on model instance state.
|
33
|
+
|
34
|
+
* The optimistic_locking plugin no longer adds the lock column to
|
35
|
+
changed_columns after updating the model instance.
|
36
|
+
|
37
|
+
* Database#create_temp with :temp option and an
|
38
|
+
SQL::QualifiedIdentifier table name will now attempt to create a
|
39
|
+
schema qualified table. Note that schema qualified temporary
|
40
|
+
tables are not supported by many (any?) databases, but this
|
41
|
+
change prevents the CREATE TABLE statement from succeeding with
|
42
|
+
an unexpected table name.
|
43
|
+
|
44
|
+
= Backwards Compatibility
|
45
|
+
|
46
|
+
* The Database.uri_to_options private class method now handles
|
47
|
+
conversion of URI parameters to options. Previously, this was
|
48
|
+
handled by callers of this method.
|
49
|
+
|
50
|
+
* The _merge_matched_sql and _merge_not_matched_sql private Dataset
|
51
|
+
methods in PostgreSQL have been replaced with
|
52
|
+
_merge_do_nothing_sql.
|
53
|
+
|
54
|
+
* An unnecessary space in submitted SQL has been removed when using
|
55
|
+
MERGE INSERT on PostgreSQL. This should only affect your code if
|
56
|
+
you are explicitly checking the produced SQL.
|
data/doc/testing.rdoc
CHANGED
@@ -47,6 +47,20 @@ These run each test in its own transaction, the recommended way to test.
|
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
|
+
== Transactional testing with multiple threads
|
51
|
+
|
52
|
+
Some tests may require executing code across multiple threads. The most common example are browser tests with Capybara, where the web server is running in a separate thread. For transactional tests to work in this case, the main thread needs to allow other threads to use its database connection while the transaction is in progress. This can be achieved with the temporarily_release_connection extension:
|
53
|
+
|
54
|
+
DB.extension :temporarily_release_connection
|
55
|
+
DB.transaction(rollback: :always, auto_savepoint: true) do |conn|
|
56
|
+
DB.temporarily_release_connection(conn) do
|
57
|
+
# Other threads can operate on connection safely inside the transaction
|
58
|
+
yield
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
This requires maximum connection pool size to be 1, so make sure to set the Database +:max_connections+ option to 1 in tests.
|
63
|
+
|
50
64
|
== Transactional testing with multiple databases
|
51
65
|
|
52
66
|
You can use the Sequel.transaction method to run a transaction on multiple databases, rolling all of them back. Instead of:
|
@@ -115,7 +115,7 @@ module Sequel
|
|
115
115
|
# Temporary table creation on Derby uses DECLARE instead of CREATE.
|
116
116
|
def create_table_prefix_sql(name, options)
|
117
117
|
if options[:temp]
|
118
|
-
"DECLARE GLOBAL TEMPORARY TABLE #{
|
118
|
+
"DECLARE GLOBAL TEMPORARY TABLE #{create_table_table_name_sql(name, options)}"
|
119
119
|
else
|
120
120
|
super
|
121
121
|
end
|
@@ -198,7 +198,7 @@ module Sequel
|
|
198
198
|
# http://www.ibm.com/developerworks/data/library/techarticle/dm-0912globaltemptable/
|
199
199
|
def create_table_prefix_sql(name, options)
|
200
200
|
if options[:temp]
|
201
|
-
"DECLARE GLOBAL TEMPORARY TABLE #{
|
201
|
+
"DECLARE GLOBAL TEMPORARY TABLE #{create_table_table_name_sql(name, options)}"
|
202
202
|
else
|
203
203
|
super
|
204
204
|
end
|
@@ -379,9 +379,21 @@ module Sequel
|
|
379
379
|
# a regular and temporary table, with temporary table names starting with
|
380
380
|
# a #.
|
381
381
|
def create_table_prefix_sql(name, options)
|
382
|
-
"CREATE TABLE #{
|
382
|
+
"CREATE TABLE #{create_table_table_name_sql(name, options)}"
|
383
383
|
end
|
384
|
-
|
384
|
+
|
385
|
+
# The SQL to use for the table name for a temporary table.
|
386
|
+
def create_table_temp_table_name_sql(name, _options)
|
387
|
+
case name
|
388
|
+
when String, Symbol
|
389
|
+
"##{name}"
|
390
|
+
when SQL::Identifier
|
391
|
+
"##{name.value}"
|
392
|
+
else
|
393
|
+
raise Error, "temporary table names must be strings, symbols, or Sequel::SQL::Identifier instances on Microsoft SQL Server"
|
394
|
+
end
|
395
|
+
end
|
396
|
+
|
385
397
|
# MSSQL doesn't support CREATE TABLE AS, it only supports SELECT INTO.
|
386
398
|
# Emulating CREATE TABLE AS using SELECT INTO is only possible if a dataset
|
387
399
|
# is given as the argument, it can't work with a string, so raise an
|
@@ -1429,7 +1429,7 @@ module Sequel
|
|
1429
1429
|
'UNLOGGED '
|
1430
1430
|
end
|
1431
1431
|
|
1432
|
-
"CREATE #{prefix_sql}TABLE#{' IF NOT EXISTS' if options[:if_not_exists]} #{
|
1432
|
+
"CREATE #{prefix_sql}TABLE#{' IF NOT EXISTS' if options[:if_not_exists]} #{create_table_table_name_sql(name, options)}"
|
1433
1433
|
end
|
1434
1434
|
|
1435
1435
|
# SQL for creating a table with PostgreSQL specific options
|
@@ -2058,6 +2058,29 @@ module Sequel
|
|
2058
2058
|
nil
|
2059
2059
|
end
|
2060
2060
|
|
2061
|
+
# Support MERGE RETURNING on PostgreSQL 17+.
|
2062
|
+
def merge(&block)
|
2063
|
+
sql = merge_sql
|
2064
|
+
if uses_returning?(:merge)
|
2065
|
+
returning_fetch_rows(sql, &block)
|
2066
|
+
else
|
2067
|
+
execute_ddl(sql)
|
2068
|
+
end
|
2069
|
+
end
|
2070
|
+
|
2071
|
+
# Return a dataset with a WHEN NOT MATCHED BY SOURCE THEN DELETE clause added to the
|
2072
|
+
# MERGE statement. If a block is passed, treat it as a virtual row and
|
2073
|
+
# use it as additional conditions for the match.
|
2074
|
+
#
|
2075
|
+
# merge_delete_not_matched_by_source
|
2076
|
+
# # WHEN NOT MATCHED BY SOURCE THEN DELETE
|
2077
|
+
#
|
2078
|
+
# merge_delete_not_matched_by_source{a > 30}
|
2079
|
+
# # WHEN NOT MATCHED BY SOURCE AND (a > 30) THEN DELETE
|
2080
|
+
def merge_delete_when_not_matched_by_source(&block)
|
2081
|
+
_merge_when(:type=>:delete_not_matched_by_source, &block)
|
2082
|
+
end
|
2083
|
+
|
2061
2084
|
# Return a dataset with a WHEN MATCHED THEN DO NOTHING clause added to the
|
2062
2085
|
# MERGE statement. If a block is passed, treat it as a virtual row and
|
2063
2086
|
# use it as additional conditions for the match.
|
@@ -2084,15 +2107,41 @@ module Sequel
|
|
2084
2107
|
_merge_when(:type=>:not_matched, &block)
|
2085
2108
|
end
|
2086
2109
|
|
2110
|
+
# Return a dataset with a WHEN NOT MATCHED BY SOURCE THEN DO NOTHING clause added to the
|
2111
|
+
# MERGE BY SOURCE statement. If a block is passed, treat it as a virtual row and
|
2112
|
+
# use it as additional conditions for the match.
|
2113
|
+
#
|
2114
|
+
# merge_do_nothing_when_not_matched_by_source
|
2115
|
+
# # WHEN NOT MATCHED BY SOURCE THEN DO NOTHING
|
2116
|
+
#
|
2117
|
+
# merge_do_nothing_when_not_matched_by_source{a > 30}
|
2118
|
+
# # WHEN NOT MATCHED BY SOURCE AND (a > 30) THEN DO NOTHING
|
2119
|
+
def merge_do_nothing_when_not_matched_by_source(&block)
|
2120
|
+
_merge_when(:type=>:not_matched_by_source, &block)
|
2121
|
+
end
|
2122
|
+
|
2087
2123
|
# Support OVERRIDING USER|SYSTEM VALUE for MERGE INSERT.
|
2088
2124
|
def merge_insert(*values, &block)
|
2089
2125
|
h = {:type=>:insert, :values=>values}
|
2090
|
-
if
|
2126
|
+
if @opts[:override]
|
2091
2127
|
h[:override] = insert_override_sql(String.new)
|
2092
2128
|
end
|
2093
2129
|
_merge_when(h, &block)
|
2094
2130
|
end
|
2095
2131
|
|
2132
|
+
# Return a dataset with a WHEN NOT MATCHED BY SOURCE THEN UPDATE clause added to the
|
2133
|
+
# MERGE statement. If a block is passed, treat it as a virtual row and
|
2134
|
+
# use it as additional conditions for the match.
|
2135
|
+
#
|
2136
|
+
# merge_update_not_matched_by_source(i1: Sequel[:i1]+:i2+10, a: Sequel[:a]+:b+20)
|
2137
|
+
# # WHEN NOT MATCHED BY SOURCE THEN UPDATE SET i1 = (i1 + i2 + 10), a = (a + b + 20)
|
2138
|
+
#
|
2139
|
+
# merge_update_not_matched_by_source(i1: :i2){a > 30}
|
2140
|
+
# # WHEN NOT MATCHED BY SOURCE AND (a > 30) THEN UPDATE SET i1 = i2
|
2141
|
+
def merge_update_when_not_matched_by_source(values, &block)
|
2142
|
+
_merge_when(:type=>:update_not_matched_by_source, :values=>values, &block)
|
2143
|
+
end
|
2144
|
+
|
2096
2145
|
# Use OVERRIDING USER VALUE for INSERT statements, so that identity columns
|
2097
2146
|
# always use the user supplied value, and an error is not raised for identity
|
2098
2147
|
# columns that are GENERATED ALWAYS.
|
@@ -2170,9 +2219,14 @@ module Sequel
|
|
2170
2219
|
true
|
2171
2220
|
end
|
2172
2221
|
|
2173
|
-
#
|
2222
|
+
# MERGE RETURNING is supported on PostgreSQL 17+. Other RETURNING is supported
|
2223
|
+
# on all supported PostgreSQL versions.
|
2174
2224
|
def supports_returning?(type)
|
2175
|
-
|
2225
|
+
if type == :merge
|
2226
|
+
server_version >= 170000
|
2227
|
+
else
|
2228
|
+
true
|
2229
|
+
end
|
2176
2230
|
end
|
2177
2231
|
|
2178
2232
|
# PostgreSQL supports pattern matching via regular expressions
|
@@ -2281,7 +2335,7 @@ module Sequel
|
|
2281
2335
|
|
2282
2336
|
# Append the INSERT sql used in a MERGE
|
2283
2337
|
def _merge_insert_sql(sql, data)
|
2284
|
-
sql << " THEN INSERT
|
2338
|
+
sql << " THEN INSERT"
|
2285
2339
|
columns, values = _parse_insert_sql_args(data[:values])
|
2286
2340
|
_insert_columns_sql(sql, columns)
|
2287
2341
|
if override = data[:override]
|
@@ -2290,10 +2344,15 @@ module Sequel
|
|
2290
2344
|
_insert_values_sql(sql, values)
|
2291
2345
|
end
|
2292
2346
|
|
2293
|
-
def
|
2347
|
+
def _merge_do_nothing_sql(sql, data)
|
2294
2348
|
sql << " THEN DO NOTHING"
|
2295
2349
|
end
|
2296
|
-
|
2350
|
+
|
2351
|
+
# Support MERGE RETURNING on PostgreSQL 17+.
|
2352
|
+
def _merge_when_sql(sql)
|
2353
|
+
super
|
2354
|
+
insert_returning_sql(sql) if uses_returning?(:merge)
|
2355
|
+
end
|
2297
2356
|
|
2298
2357
|
# Format TRUNCATE statement with PostgreSQL specific options.
|
2299
2358
|
def _truncate_sql(table)
|
@@ -245,7 +245,7 @@ module Sequel
|
|
245
245
|
super
|
246
246
|
end
|
247
247
|
when :drop_column
|
248
|
-
if sqlite_version >= 33500
|
248
|
+
if sqlite_version >= 33500 && !indexes(table).any?{|_, h| h[:columns].include?(op[:name])}
|
249
249
|
super
|
250
250
|
else
|
251
251
|
ocp = lambda{|oc| oc.delete_if{|c| c.to_s == op[:name].to_s}}
|
@@ -197,11 +197,8 @@ class Sequel::ShardedThreadedConnectionPool < Sequel::ThreadedConnectionPool
|
|
197
197
|
timeout = @timeout
|
198
198
|
timer = Sequel.start_timer
|
199
199
|
|
200
|
-
|
201
|
-
|
202
|
-
if conn = next_available(server)
|
203
|
-
return(allocated(server)[thread] = conn)
|
204
|
-
end
|
200
|
+
if conn = acquire_available(thread, server, timeout)
|
201
|
+
return conn
|
205
202
|
end
|
206
203
|
|
207
204
|
until conn = assign_connection(thread, server)
|
@@ -211,11 +208,8 @@ class Sequel::ShardedThreadedConnectionPool < Sequel::ThreadedConnectionPool
|
|
211
208
|
|
212
209
|
# It's difficult to get to this point, it can only happen if there is a race condition
|
213
210
|
# where a connection cannot be acquired even after the thread is signalled by the condition variable
|
214
|
-
|
215
|
-
|
216
|
-
if conn = next_available(server)
|
217
|
-
return(allocated(server)[thread] = conn)
|
218
|
-
end
|
211
|
+
if conn = acquire_available(thread, server, timeout - elapsed)
|
212
|
+
return conn
|
219
213
|
end
|
220
214
|
# :nocov:
|
221
215
|
end
|
@@ -223,6 +217,28 @@ class Sequel::ShardedThreadedConnectionPool < Sequel::ThreadedConnectionPool
|
|
223
217
|
conn
|
224
218
|
end
|
225
219
|
|
220
|
+
# Acquire a connection if one is already available, or waiting until it becomes available.
|
221
|
+
def acquire_available(thread, server, timeout)
|
222
|
+
sync do
|
223
|
+
# Check if connection was checked in between when assign_connection failed and now.
|
224
|
+
# This is very unlikely, but necessary to prevent a situation where the waiter
|
225
|
+
# will wait for a connection even though one has already been checked in.
|
226
|
+
# :nocov:
|
227
|
+
if conn = next_available(server)
|
228
|
+
return(allocated(server)[thread] = conn)
|
229
|
+
end
|
230
|
+
# :nocov:
|
231
|
+
|
232
|
+
@waiters[server].wait(@mutex, timeout)
|
233
|
+
|
234
|
+
# Connection still not available, could be because a connection was disconnected,
|
235
|
+
# may have to retry assign_connection to see if a new connection can be made.
|
236
|
+
if conn = next_available(server)
|
237
|
+
return(allocated(server)[thread] = conn)
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
226
242
|
# Assign a connection to the thread, or return nil if one cannot be assigned.
|
227
243
|
# The caller should NOT have the mutex before calling this.
|
228
244
|
def assign_connection(thread, server)
|
@@ -143,11 +143,8 @@ class Sequel::ThreadedConnectionPool < Sequel::ConnectionPool
|
|
143
143
|
timeout = @timeout
|
144
144
|
timer = Sequel.start_timer
|
145
145
|
|
146
|
-
|
147
|
-
|
148
|
-
if conn = next_available
|
149
|
-
return(@allocated[thread] = conn)
|
150
|
-
end
|
146
|
+
if conn = acquire_available(thread, timeout)
|
147
|
+
return conn
|
151
148
|
end
|
152
149
|
|
153
150
|
until conn = assign_connection(thread)
|
@@ -157,11 +154,8 @@ class Sequel::ThreadedConnectionPool < Sequel::ConnectionPool
|
|
157
154
|
|
158
155
|
# It's difficult to get to this point, it can only happen if there is a race condition
|
159
156
|
# where a connection cannot be acquired even after the thread is signalled by the condition variable
|
160
|
-
|
161
|
-
|
162
|
-
if conn = next_available
|
163
|
-
return(@allocated[thread] = conn)
|
164
|
-
end
|
157
|
+
if conn = acquire_available(thread, timeout - elapsed)
|
158
|
+
return conn
|
165
159
|
end
|
166
160
|
# :nocov:
|
167
161
|
end
|
@@ -169,6 +163,28 @@ class Sequel::ThreadedConnectionPool < Sequel::ConnectionPool
|
|
169
163
|
conn
|
170
164
|
end
|
171
165
|
|
166
|
+
# Acquire a connection if one is already available, or waiting until it becomes available.
|
167
|
+
def acquire_available(thread, timeout)
|
168
|
+
sync do
|
169
|
+
# Check if connection was checked in between when assign_connection failed and now.
|
170
|
+
# This is very unlikely, but necessary to prevent a situation where the waiter
|
171
|
+
# will wait for a connection even though one has already been checked in.
|
172
|
+
# :nocov:
|
173
|
+
if conn = next_available
|
174
|
+
return(@allocated[thread] = conn)
|
175
|
+
end
|
176
|
+
# :nocov:
|
177
|
+
|
178
|
+
@waiter.wait(@mutex, timeout)
|
179
|
+
|
180
|
+
# Connection still not available, could be because a connection was disconnected,
|
181
|
+
# may have to retry assign_connection to see if a new connection can be made.
|
182
|
+
if conn = next_available
|
183
|
+
return(@allocated[thread] = conn)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
172
188
|
# Assign a connection to the thread, or return nil if one cannot be assigned.
|
173
189
|
# The caller should NOT have the mutex before calling this.
|
174
190
|
def assign_connection(thread)
|
@@ -34,10 +34,7 @@ module Sequel
|
|
34
34
|
uri = URI.parse(conn_string)
|
35
35
|
scheme = uri.scheme
|
36
36
|
c = adapter_class(scheme)
|
37
|
-
|
38
|
-
uri.query.split('&').map{|s| s.split('=')}.each{|k,v| uri_options[k.to_sym] = v if k && !k.empty?} unless uri.query.to_s.strip.empty?
|
39
|
-
uri_options.to_a.each{|k,v| uri_options[k] = URI::DEFAULT_PARSER.unescape(v) if v.is_a?(String)}
|
40
|
-
opts = uri_options.merge(opts).merge!(:orig_opts=>opts.dup, :uri=>conn_string, :adapter=>scheme)
|
37
|
+
opts = c.send(:uri_to_options, uri).merge!(opts).merge!(:orig_opts=>opts.dup, :uri=>conn_string, :adapter=>scheme)
|
41
38
|
end
|
42
39
|
when Hash
|
43
40
|
opts = conn_string.merge(opts)
|
@@ -270,28 +267,20 @@ module Sequel
|
|
270
267
|
@single_threaded
|
271
268
|
end
|
272
269
|
|
273
|
-
|
274
|
-
#
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
#
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
# server, instead of the :default server.
|
288
|
-
#
|
289
|
-
# DB.synchronize do |conn|
|
290
|
-
# # ...
|
291
|
-
# end
|
292
|
-
def synchronize(server=nil, &block)
|
293
|
-
@pool.hold(server || :default, &block)
|
294
|
-
end
|
270
|
+
# Acquires a database connection, yielding it to the passed block. This is
|
271
|
+
# useful if you want to make sure the same connection is used for all
|
272
|
+
# database queries in the block. It is also useful if you want to gain
|
273
|
+
# direct access to the underlying connection object if you need to do
|
274
|
+
# something Sequel does not natively support.
|
275
|
+
#
|
276
|
+
# If a server option is given, acquires a connection for that specific
|
277
|
+
# server, instead of the :default server.
|
278
|
+
#
|
279
|
+
# DB.synchronize do |conn|
|
280
|
+
# # ...
|
281
|
+
# end
|
282
|
+
def synchronize(server=nil, &block)
|
283
|
+
@pool.hold(server || :default, &block)
|
295
284
|
end
|
296
285
|
|
297
286
|
# Attempts to acquire a database connection. Returns true if successful.
|
@@ -343,6 +332,11 @@ module Sequel
|
|
343
332
|
else
|
344
333
|
@opts.dup
|
345
334
|
end
|
335
|
+
|
336
|
+
if pr = opts[:connect_opts_proc]
|
337
|
+
pr.call(opts)
|
338
|
+
end
|
339
|
+
|
346
340
|
opts.delete(:servers)
|
347
341
|
opts
|
348
342
|
end
|
data/lib/sequel/database/misc.rb
CHANGED
@@ -72,13 +72,16 @@ module Sequel
|
|
72
72
|
# Converts a uri to an options hash. These options are then passed
|
73
73
|
# to a newly created database object.
|
74
74
|
def self.uri_to_options(uri)
|
75
|
-
{
|
75
|
+
uri_options = {
|
76
76
|
:user => uri.user,
|
77
77
|
:password => uri.password,
|
78
78
|
:port => uri.port,
|
79
79
|
:host => uri.hostname,
|
80
80
|
:database => (m = /\/(.*)/.match(uri.path)) && (m[1])
|
81
81
|
}
|
82
|
+
uri.query.split('&').map{|s| s.split('=')}.each{|k,v| uri_options[k.to_sym] = v if k && !k.empty?} unless uri.query.to_s.strip.empty?
|
83
|
+
uri_options.to_a.each{|k,v| uri_options[k] = URI::DEFAULT_PARSER.unescape(v) if v.is_a?(String)}
|
84
|
+
uri_options
|
82
85
|
end
|
83
86
|
private_class_method :uri_to_options
|
84
87
|
|
@@ -108,6 +111,9 @@ module Sequel
|
|
108
111
|
# :cache_schema :: Whether schema should be cached for this Database instance
|
109
112
|
# :check_string_typecast_bytesize :: Whether to check the bytesize of strings before typecasting.
|
110
113
|
# :connect_sqls :: An array of sql strings to execute on each new connection, after :after_connect runs.
|
114
|
+
# :connect_opts_proc :: Callable object for modifying options hash used when connecting, designed for
|
115
|
+
# cases where the option values (e.g. password) are automatically rotated on
|
116
|
+
# a regular basis without involvement from the application using Sequel.
|
111
117
|
# :default_string_column_size :: The default size of string columns, 255 by default.
|
112
118
|
# :extensions :: Extensions to load into this Database instance. Can be a symbol, array of symbols,
|
113
119
|
# or string with extensions separated by columns. These extensions are loaded after
|
@@ -250,15 +256,27 @@ module Sequel
|
|
250
256
|
Sequel.convert_output_timestamp(v, timezone)
|
251
257
|
end
|
252
258
|
|
253
|
-
# Returns a string representation of the
|
254
|
-
#
|
259
|
+
# Returns a string representation of the Database object, including
|
260
|
+
# the database type, host, database, and user, if present.
|
255
261
|
def inspect
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
262
|
+
s = String.new
|
263
|
+
s << "#<#{self.class}"
|
264
|
+
s << " database_type=#{database_type}" if database_type && database_type != adapter_scheme
|
265
|
+
|
266
|
+
keys = [:host, :database, :user]
|
267
|
+
opts = self.opts
|
268
|
+
if !keys.any?{|k| opts[k]} && opts[:uri]
|
269
|
+
opts = self.class.send(:uri_to_options, URI.parse(opts[:uri]))
|
260
270
|
end
|
261
|
-
|
271
|
+
|
272
|
+
keys.each do |key|
|
273
|
+
val = opts[key]
|
274
|
+
if val && val != ''
|
275
|
+
s << " #{key}=#{val}"
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
s << ">"
|
262
280
|
end
|
263
281
|
|
264
282
|
# Proxy the literal call to the dataset.
|
@@ -775,7 +775,21 @@ module Sequel
|
|
775
775
|
|
776
776
|
# SQL fragment for initial part of CREATE TABLE statement
|
777
777
|
def create_table_prefix_sql(name, options)
|
778
|
-
"CREATE #{temporary_table_sql if options[:temp]}TABLE#{' IF NOT EXISTS' if options[:if_not_exists]} #{
|
778
|
+
"CREATE #{temporary_table_sql if options[:temp]}TABLE#{' IF NOT EXISTS' if options[:if_not_exists]} #{create_table_table_name_sql(name, options)}"
|
779
|
+
end
|
780
|
+
|
781
|
+
# The SQL to use for a table name when creating a table.
|
782
|
+
# Use of the :temp option can result in different SQL,
|
783
|
+
# because the rules for temp table naming can differ
|
784
|
+
# between databases, and temp tables should not use the
|
785
|
+
# default_schema.
|
786
|
+
def create_table_table_name_sql(name, options)
|
787
|
+
options[:temp] ? create_table_temp_table_name_sql(name, options) : quote_schema_table(name)
|
788
|
+
end
|
789
|
+
|
790
|
+
# The SQL to use for the table name for a temporary table.
|
791
|
+
def create_table_temp_table_name_sql(name, _options)
|
792
|
+
name.is_a?(String) ? quote_identifier(name) : literal(name)
|
779
793
|
end
|
780
794
|
|
781
795
|
# SQL fragment for initial part of CREATE VIEW statement
|
data/lib/sequel/dataset/sql.rb
CHANGED
@@ -901,18 +901,31 @@ module Sequel
|
|
901
901
|
MERGE_TYPE_SQL = {
|
902
902
|
:insert => ' WHEN NOT MATCHED',
|
903
903
|
:delete => ' WHEN MATCHED',
|
904
|
+
:delete_not_matched_by_source => ' WHEN NOT MATCHED BY SOURCE',
|
904
905
|
:update => ' WHEN MATCHED',
|
906
|
+
:update_not_matched_by_source => ' WHEN NOT MATCHED BY SOURCE',
|
905
907
|
:matched => ' WHEN MATCHED',
|
906
908
|
:not_matched => ' WHEN NOT MATCHED',
|
909
|
+
:not_matched_by_source => ' WHEN NOT MATCHED BY SOURCE',
|
907
910
|
}.freeze
|
908
911
|
private_constant :MERGE_TYPE_SQL
|
909
912
|
|
913
|
+
MERGE_NORMALIZE_TYPE_MAP = {
|
914
|
+
:delete_not_matched_by_source => :delete,
|
915
|
+
:update_not_matched_by_source => :update,
|
916
|
+
:matched => :do_nothing,
|
917
|
+
:not_matched => :do_nothing,
|
918
|
+
:not_matched_by_source => :do_nothing,
|
919
|
+
}.freeze
|
920
|
+
private_constant :MERGE_NORMALIZE_TYPE_MAP
|
921
|
+
|
910
922
|
# Add the WHEN clauses to the MERGE SQL
|
911
923
|
def _merge_when_sql(sql)
|
912
924
|
raise Error, "no WHEN [NOT] MATCHED clauses provided for MERGE" unless merge_when = @opts[:merge_when]
|
913
925
|
merge_when.each do |data|
|
914
926
|
type = data[:type]
|
915
927
|
sql << MERGE_TYPE_SQL[type]
|
928
|
+
type = MERGE_NORMALIZE_TYPE_MAP[type] || type
|
916
929
|
_merge_when_conditions_sql(sql, data)
|
917
930
|
send(:"_merge_#{type}_sql", sql, data)
|
918
931
|
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
#
|
3
|
+
# The stdio_logger extension exposes a Sequel::StdioLogger class that
|
4
|
+
# can be used for logging with Sequel, as a minimal alternative to
|
5
|
+
# the logger library. It exposes debug/info/warn/error methods for the
|
6
|
+
# different warning levels. The debug method is a no-op, so that setting
|
7
|
+
# the Database sql_log_level to debug will result in no output for normal
|
8
|
+
# queries. The info/warn/error methods log the current time, log level,
|
9
|
+
# and the given message.
|
10
|
+
#
|
11
|
+
# To use this extension:
|
12
|
+
#
|
13
|
+
# Sequel.extension :stdio_logger
|
14
|
+
#
|
15
|
+
# Then you you can use Sequel::StdioLogger to wrap IO objects that you
|
16
|
+
# would like Sequel to log to:
|
17
|
+
#
|
18
|
+
# DB.loggers << Sequel::StdioLogger.new($stdout)
|
19
|
+
#
|
20
|
+
# log_file = File.open("db_queries.log", 'a')
|
21
|
+
# log_file.sync = true
|
22
|
+
# DB.loggers << Sequel::StdioLogger.new(log_file)
|
23
|
+
#
|
24
|
+
# This is implemented as a global extension instead of a Database extension
|
25
|
+
# because Database loggers must be set before Database extensions are loaded.
|
26
|
+
#
|
27
|
+
# Related module: Sequel::StdioLogger
|
28
|
+
|
29
|
+
#
|
30
|
+
module Sequel
|
31
|
+
class StdioLogger
|
32
|
+
def initialize(device)
|
33
|
+
@device = device
|
34
|
+
end
|
35
|
+
|
36
|
+
# Do not log debug messages. This is so setting the Database
|
37
|
+
# sql_log_level to debug will result in no output.
|
38
|
+
def debug(msg)
|
39
|
+
end
|
40
|
+
|
41
|
+
[:info, :warn, :error].each do |meth|
|
42
|
+
define_method(meth) do |msg|
|
43
|
+
@device.write("#{Time.now.strftime('%F %T')} #{meth.to_s.upcase}: #{msg}\n")
|
44
|
+
nil
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -54,6 +54,7 @@
|
|
54
54
|
# * MySQL
|
55
55
|
# * HSQLDB
|
56
56
|
# * H2
|
57
|
+
# * SQLite 3.44+ (distinct only works when separator is ',')
|
57
58
|
#
|
58
59
|
# Related module: Sequel::SQL::StringAgg
|
59
60
|
|
@@ -94,6 +95,19 @@ module Sequel
|
|
94
95
|
distinct = sa.is_distinct?
|
95
96
|
|
96
97
|
case db_type = db.database_type
|
98
|
+
when :sqlite
|
99
|
+
raise Error, "string_agg(DISTINCT) is not supported with a non-comma separator on #{db.database_type}" if distinct && separator != ","
|
100
|
+
|
101
|
+
args = [expr]
|
102
|
+
args << separator unless distinct
|
103
|
+
f = Function.new(:group_concat, *args)
|
104
|
+
if order
|
105
|
+
f = f.order(*order)
|
106
|
+
end
|
107
|
+
if distinct
|
108
|
+
f = f.distinct
|
109
|
+
end
|
110
|
+
literal_append(sql, f)
|
97
111
|
when :postgres, :sqlanywhere
|
98
112
|
f = Function.new(db_type == :postgres ? :string_agg : :list, expr, separator)
|
99
113
|
if order
|
@@ -151,7 +165,7 @@ module Sequel
|
|
151
165
|
freeze
|
152
166
|
end
|
153
167
|
|
154
|
-
# Whether the current expression uses distinct expressions
|
168
|
+
# Whether the current expression uses distinct expressions
|
155
169
|
def is_distinct?
|
156
170
|
@distinct == true
|
157
171
|
end
|
@@ -178,4 +192,3 @@ module Sequel
|
|
178
192
|
|
179
193
|
Dataset.register_extension(:string_agg, SQL::StringAgg::DatasetMethods)
|
180
194
|
end
|
181
|
-
|
@@ -294,7 +294,7 @@ module Sequel
|
|
294
294
|
sch = klass.db_schema
|
295
295
|
|
296
296
|
if primary_key.is_a?(Array)
|
297
|
-
if (cols = sch.values_at(*klass.primary_key)).all? && (
|
297
|
+
if (cols = sch.values_at(*klass.primary_key)).all? && (cols.map{|c| c[:type] == :integer}).all?
|
298
298
|
db = model.db
|
299
299
|
pks.map do |cpk|
|
300
300
|
cpk.map do |pk|
|
@@ -26,6 +26,12 @@ module Sequel
|
|
26
26
|
# Album.default_values[:a] = lambda{Date.today}
|
27
27
|
# Album.new.a # => Date.today
|
28
28
|
#
|
29
|
+
# If the proc accepts a single argument, it is passed the instance, allowing
|
30
|
+
# default values to depend on instance-specific state:
|
31
|
+
#
|
32
|
+
# Album.default_values[:a] = lambda{|album| album.b + 1}
|
33
|
+
# Album.new(b: 10).a # => 11
|
34
|
+
#
|
29
35
|
# By default, default values returned are not cached:
|
30
36
|
#
|
31
37
|
# Album.new.a.equal?(Album.new.a) # => false
|
@@ -43,13 +49,13 @@ module Sequel
|
|
43
49
|
# album.values # => {}
|
44
50
|
# album.a
|
45
51
|
# album.values # => {:a => Date.today}
|
46
|
-
#
|
52
|
+
#
|
47
53
|
# Usage:
|
48
54
|
#
|
49
55
|
# # Make all model subclass instances set defaults (called before loading subclasses)
|
50
56
|
# Sequel::Model.plugin :defaults_setter
|
51
57
|
#
|
52
|
-
# # Make the Album class set defaults
|
58
|
+
# # Make the Album class set defaults
|
53
59
|
# Album.plugin :defaults_setter
|
54
60
|
module DefaultsSetter
|
55
61
|
# Set the default values based on the model schema. Options:
|
@@ -76,7 +82,7 @@ module Sequel
|
|
76
82
|
def cache_default_values?
|
77
83
|
@cache_default_values
|
78
84
|
end
|
79
|
-
|
85
|
+
|
80
86
|
# Freeze default values when freezing model class
|
81
87
|
def freeze
|
82
88
|
@default_values.freeze
|
@@ -133,7 +139,13 @@ module Sequel
|
|
133
139
|
def [](k)
|
134
140
|
if new? && !values.has_key?(k)
|
135
141
|
v = model.default_values.fetch(k){return}
|
136
|
-
|
142
|
+
if v.respond_to?(:call)
|
143
|
+
v = if v.respond_to?(:arity) && v.arity == 1
|
144
|
+
v.call(self)
|
145
|
+
else
|
146
|
+
v.call
|
147
|
+
end
|
148
|
+
end
|
137
149
|
values[k] = v if model.cache_default_values?
|
138
150
|
v
|
139
151
|
else
|
@@ -158,15 +158,19 @@ module Sequel
|
|
158
158
|
end
|
159
159
|
|
160
160
|
# Filter the objects used when tactical eager loading.
|
161
|
-
# By default, this removes frozen objects and objects that alreayd have the association loaded
|
161
|
+
# By default, this removes frozen objects and objects that alreayd have the association loaded,
|
162
|
+
# as well as objects where the reflection for the association is not the same as the receiver's
|
163
|
+
# reflection for the association.
|
162
164
|
def _filter_tactical_eager_load_objects(opts)
|
163
165
|
objects = defined?(super) ? super : retrieved_with.dup
|
166
|
+
name = opts[:name]
|
164
167
|
if opts[:eager_reload]
|
165
168
|
objects.reject!(&:frozen?)
|
166
169
|
else
|
167
|
-
name = opts[:name]
|
168
170
|
objects.reject!{|x| x.frozen? || x.associations.include?(name)}
|
169
171
|
end
|
172
|
+
reflection = self.class.association_reflection(name)
|
173
|
+
objects.select!{|x| x.class.association_reflection(name).equal?(reflection)}
|
170
174
|
objects
|
171
175
|
end
|
172
176
|
end
|
@@ -53,7 +53,7 @@ module Sequel
|
|
53
53
|
def validate_associated_object(reflection, obj)
|
54
54
|
return if reflection[:validate] == false
|
55
55
|
association = reflection[:name]
|
56
|
-
if (reflection[:type] == :one_to_many || reflection[:type] == :one_to_one) && (key = reflection[:key]).is_a?(Symbol) && !(
|
56
|
+
if (reflection[:type] == :one_to_many || reflection[:type] == :one_to_one) && (key = reflection[:key]).is_a?(Symbol) && !(obj.values[key])
|
57
57
|
p_key = pk unless pk.is_a?(Array)
|
58
58
|
if p_key
|
59
59
|
obj.values[key] = p_key
|
data/lib/sequel/version.rb
CHANGED
@@ -6,7 +6,7 @@ module Sequel
|
|
6
6
|
|
7
7
|
# The minor version of Sequel. Bumped for every non-patch level
|
8
8
|
# release, generally around once a month.
|
9
|
-
MINOR =
|
9
|
+
MINOR = 83
|
10
10
|
|
11
11
|
# The tiny version of Sequel. Usually 0, only bumped for bugfix
|
12
12
|
# releases that fix regressions from previous versions.
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sequel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.
|
4
|
+
version: 5.83.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeremy Evans
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-08-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bigdecimal
|
@@ -229,6 +229,8 @@ extra_rdoc_files:
|
|
229
229
|
- doc/release_notes/5.8.0.txt
|
230
230
|
- doc/release_notes/5.80.0.txt
|
231
231
|
- doc/release_notes/5.81.0.txt
|
232
|
+
- doc/release_notes/5.82.0.txt
|
233
|
+
- doc/release_notes/5.83.0.txt
|
232
234
|
- doc/release_notes/5.9.0.txt
|
233
235
|
files:
|
234
236
|
- CHANGELOG
|
@@ -338,6 +340,8 @@ files:
|
|
338
340
|
- doc/release_notes/5.8.0.txt
|
339
341
|
- doc/release_notes/5.80.0.txt
|
340
342
|
- doc/release_notes/5.81.0.txt
|
343
|
+
- doc/release_notes/5.82.0.txt
|
344
|
+
- doc/release_notes/5.83.0.txt
|
341
345
|
- doc/release_notes/5.9.0.txt
|
342
346
|
- doc/schema_modification.rdoc
|
343
347
|
- doc/security.rdoc
|
@@ -517,6 +521,7 @@ files:
|
|
517
521
|
- lib/sequel/extensions/sql_expr.rb
|
518
522
|
- lib/sequel/extensions/sql_log_normalizer.rb
|
519
523
|
- lib/sequel/extensions/sqlite_json_ops.rb
|
524
|
+
- lib/sequel/extensions/stdio_logger.rb
|
520
525
|
- lib/sequel/extensions/string_agg.rb
|
521
526
|
- lib/sequel/extensions/string_date_time.rb
|
522
527
|
- lib/sequel/extensions/symbol_aref.rb
|
@@ -672,7 +677,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
672
677
|
- !ruby/object:Gem::Version
|
673
678
|
version: '0'
|
674
679
|
requirements: []
|
675
|
-
rubygems_version: 3.5.
|
680
|
+
rubygems_version: 3.5.11
|
676
681
|
signing_key:
|
677
682
|
specification_version: 4
|
678
683
|
summary: The Database Toolkit for Ruby
|