sequel 5.56.0 → 5.59.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +32 -0
- data/README.rdoc +25 -0
- data/doc/cheat_sheet.rdoc +8 -0
- data/doc/opening_databases.rdoc +10 -6
- data/doc/release_notes/5.57.0.txt +23 -0
- data/doc/release_notes/5.58.0.txt +31 -0
- data/doc/release_notes/5.59.0.txt +73 -0
- data/doc/testing.rdoc +1 -1
- data/lib/sequel/adapters/jdbc/derby.rb +5 -0
- data/lib/sequel/adapters/jdbc/h2.rb +5 -0
- data/lib/sequel/adapters/jdbc/hsqldb.rb +6 -0
- data/lib/sequel/adapters/postgres.rb +12 -6
- data/lib/sequel/adapters/shared/db2.rb +28 -0
- data/lib/sequel/adapters/shared/mssql.rb +34 -0
- data/lib/sequel/adapters/shared/mysql.rb +12 -0
- data/lib/sequel/adapters/shared/oracle.rb +69 -0
- data/lib/sequel/adapters/shared/postgres.rb +70 -4
- data/lib/sequel/database/schema_generator.rb +4 -0
- data/lib/sequel/database/schema_methods.rb +3 -0
- data/lib/sequel/dataset/actions.rb +49 -0
- data/lib/sequel/dataset/features.rb +5 -0
- data/lib/sequel/dataset/query.rb +62 -0
- data/lib/sequel/dataset/sql.rb +112 -25
- data/lib/sequel/extensions/is_distinct_from.rb +139 -0
- data/lib/sequel/extensions/pg_hstore.rb +1 -1
- data/lib/sequel/extensions/pg_json_ops.rb +52 -0
- data/lib/sequel/model/associations.rb +12 -0
- data/lib/sequel/model/base.rb +14 -4
- data/lib/sequel/plugins/insert_conflict.rb +4 -0
- data/lib/sequel/plugins/list.rb +3 -1
- data/lib/sequel/plugins/require_valid_schema.rb +67 -0
- data/lib/sequel/plugins/tactical_eager_loading.rb +7 -0
- data/lib/sequel/version.rb +1 -1
- metadata +10 -16
@@ -123,6 +123,15 @@
|
|
123
123
|
# c = Sequel.pg_jsonb_op(:c)
|
124
124
|
# DB[:t].update(c['key1'] => 1.to_json, c['key2'] => "a".to_json)
|
125
125
|
#
|
126
|
+
# On PostgreSQL 15+, the <tt>IS [NOT] JSON</tt> operator is supported:
|
127
|
+
#
|
128
|
+
# j.is_json # j IS JSON
|
129
|
+
# j.is_json(type: :object) # j IS JSON OBJECT
|
130
|
+
# j.is_json(type: :object, unique: true) # j IS JSON OBJECT WITH UNIQUE
|
131
|
+
# j.is_not_json # j IS NOT JSON
|
132
|
+
# j.is_json(type: :array) # j IS NOT JSON ARRAY
|
133
|
+
# j.is_json(unique: true) # j IS NOT JSON WITH UNIQUE
|
134
|
+
#
|
126
135
|
# If you are also using the pg_json extension, you should load it before
|
127
136
|
# loading this extension. Doing so will allow you to use the #op method on
|
128
137
|
# JSONHash, JSONHarray, JSONBHash, and JSONBArray, allowing you to perform json/jsonb operations
|
@@ -151,6 +160,18 @@ module Sequel
|
|
151
160
|
GET_PATH = ["(".freeze, " #> ".freeze, ")".freeze].freeze
|
152
161
|
GET_PATH_TEXT = ["(".freeze, " #>> ".freeze, ")".freeze].freeze
|
153
162
|
|
163
|
+
IS_JSON = ["(".freeze, " IS JSON".freeze, "".freeze, ")".freeze].freeze
|
164
|
+
IS_NOT_JSON = ["(".freeze, " IS NOT JSON".freeze, "".freeze, ")".freeze].freeze
|
165
|
+
EMPTY_STRING = Sequel::LiteralString.new('').freeze
|
166
|
+
WITH_UNIQUE = Sequel::LiteralString.new(' WITH UNIQUE').freeze
|
167
|
+
IS_JSON_MAP = {
|
168
|
+
nil => EMPTY_STRING,
|
169
|
+
:value => Sequel::LiteralString.new(' VALUE').freeze,
|
170
|
+
:scalar => Sequel::LiteralString.new(' SCALAR').freeze,
|
171
|
+
:object => Sequel::LiteralString.new(' OBJECT').freeze,
|
172
|
+
:array => Sequel::LiteralString.new(' ARRAY').freeze
|
173
|
+
}.freeze
|
174
|
+
|
154
175
|
# Get JSON array element or object field as json. If an array is given,
|
155
176
|
# gets the object at the specified path.
|
156
177
|
#
|
@@ -233,6 +254,30 @@ module Sequel
|
|
233
254
|
end
|
234
255
|
end
|
235
256
|
|
257
|
+
# Return whether the json object can be parsed as JSON.
|
258
|
+
#
|
259
|
+
# Options:
|
260
|
+
# :type :: Check whether the json object can be parsed as a specific type
|
261
|
+
# of JSON (:value, :scalar, :object, :array).
|
262
|
+
# :unique :: Check JSON objects for unique keys.
|
263
|
+
#
|
264
|
+
# json_op.is_json # json IS JSON
|
265
|
+
# json_op.is_json(type: :object) # json IS JSON OBJECT
|
266
|
+
# json_op.is_json(unique: true) # json IS JSON WITH UNIQUE
|
267
|
+
def is_json(opts=OPTS)
|
268
|
+
_is_json(IS_JSON, opts)
|
269
|
+
end
|
270
|
+
|
271
|
+
# Return whether the json object cannot be parsed as JSON. The opposite
|
272
|
+
# of #is_json. See #is_json for options.
|
273
|
+
#
|
274
|
+
# json_op.is_not_json # json IS NOT JSON
|
275
|
+
# json_op.is_not_json(type: :object) # json IS NOT JSON OBJECT
|
276
|
+
# json_op.is_not_json(unique: true) # json IS NOT JSON WITH UNIQUE
|
277
|
+
def is_not_json(opts=OPTS)
|
278
|
+
_is_json(IS_NOT_JSON, opts)
|
279
|
+
end
|
280
|
+
|
236
281
|
# Returns a set of keys AS text in the json object.
|
237
282
|
#
|
238
283
|
# json_op.keys # json_object_keys(json)
|
@@ -286,6 +331,13 @@ module Sequel
|
|
286
331
|
|
287
332
|
private
|
288
333
|
|
334
|
+
# Internals of IS [NOT] JSON support
|
335
|
+
def _is_json(lit_array, opts)
|
336
|
+
raise Error, "invalid is_json :type option: #{opts[:type].inspect}" unless type = IS_JSON_MAP[opts[:type]]
|
337
|
+
unique = opts[:unique] ? WITH_UNIQUE : EMPTY_STRING
|
338
|
+
Sequel::SQL::BooleanExpression.new(:NOOP, Sequel::SQL::PlaceholderLiteralString.new(lit_array, [self, type, unique]))
|
339
|
+
end
|
340
|
+
|
289
341
|
# Return a placeholder literal with the given str and args, wrapped
|
290
342
|
# in an JSONOp or JSONBOp, used by operators that return json or jsonb.
|
291
343
|
def json_op(str, args)
|
@@ -1717,6 +1717,8 @@ module Sequel
|
|
1717
1717
|
# :graph_select :: A column or array of columns to select from the associated table
|
1718
1718
|
# when eagerly loading the association via +eager_graph+. Defaults to all
|
1719
1719
|
# columns in the associated table.
|
1720
|
+
# :instance_specific :: Marks the association as instance specific. Should be used if the association block
|
1721
|
+
# uses instance specific state, or transient state (accessing current date/time, etc.).
|
1720
1722
|
# :limit :: Limit the number of records to the provided value. Use
|
1721
1723
|
# an array with two elements for the value to specify a
|
1722
1724
|
# limit (first element) and an offset (second element).
|
@@ -1856,6 +1858,16 @@ module Sequel
|
|
1856
1858
|
# in certain places to disable optimizations.
|
1857
1859
|
opts[:instance_specific] = _association_instance_specific_default(name)
|
1858
1860
|
end
|
1861
|
+
if (orig_opts[:instance_specific] || orig_opts[:dataset]) && !opts.has_key?(:allow_eager) && !opts[:eager_loader]
|
1862
|
+
# For associations explicitly marked as instance specific, or that use the
|
1863
|
+
# :dataset option, where :allow_eager is not set, and no :eager_loader is
|
1864
|
+
# provided, disallow eager loading. In these cases, eager loading is
|
1865
|
+
# unlikely to work. This is not done for implicit setting of :instance_specific,
|
1866
|
+
# because implicit use is done by default for all associations with blocks,
|
1867
|
+
# and the vast majority of associations with blocks use the block for filtering
|
1868
|
+
# in a manner compatible with eager loading.
|
1869
|
+
opts[:allow_eager] = false
|
1870
|
+
end
|
1859
1871
|
opts = assoc_class.new.merge!(opts)
|
1860
1872
|
|
1861
1873
|
if opts[:clone] && !opts.cloneable?(cloned_assoc)
|
data/lib/sequel/model/base.rb
CHANGED
@@ -680,10 +680,11 @@ module Sequel
|
|
680
680
|
|
681
681
|
private
|
682
682
|
|
683
|
-
# Yield to the passed block and if do_raise is false, swallow
|
683
|
+
# Yield to the passed block and if do_raise is false, swallow Sequel::Errors other than DatabaseConnectionError
|
684
|
+
# and DatabaseDisconnectError.
|
684
685
|
def check_non_connection_error(do_raise=require_valid_table)
|
685
686
|
db.transaction(:savepoint=>:only){yield}
|
686
|
-
rescue Sequel::DatabaseConnectionError
|
687
|
+
rescue Sequel::DatabaseConnectionError, Sequel::DatabaseDisconnectError
|
687
688
|
raise
|
688
689
|
rescue Sequel::Error
|
689
690
|
raise if do_raise
|
@@ -693,9 +694,12 @@ module Sequel
|
|
693
694
|
# this model's dataset.
|
694
695
|
def convert_input_dataset(ds)
|
695
696
|
case ds
|
696
|
-
when Symbol, SQL::Identifier, SQL::QualifiedIdentifier
|
697
|
+
when Symbol, SQL::Identifier, SQL::QualifiedIdentifier
|
697
698
|
self.simple_table = db.literal(ds).freeze
|
698
699
|
ds = db.from(ds)
|
700
|
+
when SQL::AliasedExpression, LiteralString
|
701
|
+
self.simple_table = nil
|
702
|
+
ds = db.from(ds)
|
699
703
|
when Dataset
|
700
704
|
ds = ds.from_self(:alias=>ds.first_source) if ds.joined_dataset?
|
701
705
|
|
@@ -784,7 +788,7 @@ module Sequel
|
|
784
788
|
schema_hash = {}
|
785
789
|
ds_opts = dataset.opts
|
786
790
|
get_columns = proc{check_non_connection_error{columns} || []}
|
787
|
-
schema_array =
|
791
|
+
schema_array = get_db_schema_array(reload) if db.supports_schema_parsing?
|
788
792
|
if schema_array
|
789
793
|
schema_array.each{|k,v| schema_hash[k] = v}
|
790
794
|
|
@@ -821,6 +825,12 @@ module Sequel
|
|
821
825
|
schema_hash
|
822
826
|
end
|
823
827
|
|
828
|
+
# Get the array of schema information for the dataset. Returns nil if
|
829
|
+
# the schema information cannot be determined.
|
830
|
+
def get_db_schema_array(reload)
|
831
|
+
check_non_connection_error(false){db.schema(dataset, :reload=>reload)}
|
832
|
+
end
|
833
|
+
|
824
834
|
# Uncached version of setter_methods, to be overridden by plugins
|
825
835
|
# that want to modify the methods used.
|
826
836
|
def get_setter_methods
|
@@ -22,6 +22,10 @@ module Sequel
|
|
22
22
|
# for that album. See the PostgreSQL and SQLite adapter documention for
|
23
23
|
# the options you can pass to the insert_conflict method.
|
24
24
|
#
|
25
|
+
# You should not attempt to use this plugin to ignore conflicts when
|
26
|
+
# inserting, you should only use it to turn insert conflicts into updates.
|
27
|
+
# Any usage to ignore conflicts is not recommended or supported.
|
28
|
+
#
|
25
29
|
# Usage:
|
26
30
|
#
|
27
31
|
# # Make all model subclasses support insert_conflict
|
data/lib/sequel/plugins/list.rb
CHANGED
@@ -33,7 +33,9 @@ module Sequel
|
|
33
33
|
# You can provide a <tt>:scope</tt> option to scope the list. This option
|
34
34
|
# can be a symbol or array of symbols specifying column name(s), or a proc
|
35
35
|
# that accepts a model instance and returns a dataset representing the list
|
36
|
-
# the object is in.
|
36
|
+
# the object is in. You will need to provide a <tt>:scope</tt> option if
|
37
|
+
# the model's dataset uses a subquery (such as when using the class_table_inheritance
|
38
|
+
# plugin).
|
37
39
|
#
|
38
40
|
# For example, if each item has a +user_id+ field, and you want every user
|
39
41
|
# to have their own list:
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
module Sequel
|
4
|
+
module Plugins
|
5
|
+
# The require_valid_schema plugin makes Sequel raise or warn if attempting
|
6
|
+
# to set the dataset of a model class to a simple table, where the database
|
7
|
+
# supports schema parsing, but schema parsing does not work for the model's
|
8
|
+
# table.
|
9
|
+
#
|
10
|
+
# The plugin's default behavior requires that all models that select from a
|
11
|
+
# single identifier have a valid table schema, if the database supports
|
12
|
+
# schema parsing. If the schema cannot be determined for such
|
13
|
+
# a model, an error is raised:
|
14
|
+
#
|
15
|
+
# Sequel::Model.plugin :require_valid_schema
|
16
|
+
#
|
17
|
+
# If you load the plugin with an argument of :warn, Sequel will warn instead
|
18
|
+
# of raising for such tables:
|
19
|
+
#
|
20
|
+
# Sequel::Model.plugin :require_valid_schema, :warn
|
21
|
+
#
|
22
|
+
# This can catch bugs where you expect models to have valid schema, but
|
23
|
+
# they do not. This setting only affects future attempts to set datasets
|
24
|
+
# in the current class and subclasses created in the future.
|
25
|
+
#
|
26
|
+
# If you load the plugin with an argument of false, it will not require valid schema.
|
27
|
+
# This can be used in subclasses where you do not want to require valid schema,
|
28
|
+
# but the plugin must be loaded before a dataset with invalid schema is set:
|
29
|
+
#
|
30
|
+
# Sequel::Model.plugin :require_valid_schema
|
31
|
+
# InvalidSchemaAllowed = Class.new(Sequel::Model)
|
32
|
+
# InvalidSchemaAllowed.plugin :require_valid_schema, false
|
33
|
+
# class MyModel < InvalidSchemaAllowed
|
34
|
+
# end
|
35
|
+
module RequireValidSchema
|
36
|
+
# Modify the current model's dataset selection, if the model
|
37
|
+
# has a dataset.
|
38
|
+
def self.configure(model, setting=true)
|
39
|
+
model.instance_variable_set(:@require_valid_schema, setting)
|
40
|
+
end
|
41
|
+
|
42
|
+
module ClassMethods
|
43
|
+
Plugins.inherited_instance_variables(self, :@require_valid_schema=>nil)
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
# If the schema cannot be determined, the model uses a simple table,
|
48
|
+
# require_valid_schema is set, and the database supports schema parsing, raise or
|
49
|
+
# warn based on the require_valid_schema setting.
|
50
|
+
def get_db_schema_array(reload)
|
51
|
+
schema_array = super
|
52
|
+
|
53
|
+
if !schema_array && simple_table && @require_valid_schema
|
54
|
+
message = "Not able to parse schema for model: #{inspect}, table: #{simple_table}"
|
55
|
+
if @require_valid_schema == :warn
|
56
|
+
warn message
|
57
|
+
else
|
58
|
+
raise Error, message
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
schema_array
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -109,6 +109,13 @@ module Sequel
|
|
109
109
|
# to eagerly set the associated objects, and having separate threads
|
110
110
|
# modify the same model instance is not thread-safe.
|
111
111
|
#
|
112
|
+
# Because this plugin will automatically use eager loading for
|
113
|
+
# performance, it can break code that defines associations that
|
114
|
+
# do not support eager loading, without marking that they do not
|
115
|
+
# support eager loading via the <tt>allow_eager: false</tt> option.
|
116
|
+
# Make sure to set <tt>allow_eager: false</tt> on any association
|
117
|
+
# used with this plugin if the association doesn't support eager loading.
|
118
|
+
#
|
112
119
|
# Usage:
|
113
120
|
#
|
114
121
|
# # Make all model subclass instances use tactical eager loading (called before loading subclasses)
|
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 = 59
|
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.59.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: 2022-
|
11
|
+
date: 2022-08-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|
@@ -52,20 +52,6 @@ dependencies:
|
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: minitest-shared_description
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - ">="
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '0'
|
62
|
-
type: :development
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - ">="
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '0'
|
69
55
|
- !ruby/object:Gem::Dependency
|
70
56
|
name: tzinfo
|
71
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -201,6 +187,9 @@ extra_rdoc_files:
|
|
201
187
|
- doc/release_notes/5.54.0.txt
|
202
188
|
- doc/release_notes/5.55.0.txt
|
203
189
|
- doc/release_notes/5.56.0.txt
|
190
|
+
- doc/release_notes/5.57.0.txt
|
191
|
+
- doc/release_notes/5.58.0.txt
|
192
|
+
- doc/release_notes/5.59.0.txt
|
204
193
|
- doc/release_notes/5.6.0.txt
|
205
194
|
- doc/release_notes/5.7.0.txt
|
206
195
|
- doc/release_notes/5.8.0.txt
|
@@ -285,6 +274,9 @@ files:
|
|
285
274
|
- doc/release_notes/5.54.0.txt
|
286
275
|
- doc/release_notes/5.55.0.txt
|
287
276
|
- doc/release_notes/5.56.0.txt
|
277
|
+
- doc/release_notes/5.57.0.txt
|
278
|
+
- doc/release_notes/5.58.0.txt
|
279
|
+
- doc/release_notes/5.59.0.txt
|
288
280
|
- doc/release_notes/5.6.0.txt
|
289
281
|
- doc/release_notes/5.7.0.txt
|
290
282
|
- doc/release_notes/5.8.0.txt
|
@@ -414,6 +406,7 @@ files:
|
|
414
406
|
- lib/sequel/extensions/index_caching.rb
|
415
407
|
- lib/sequel/extensions/inflector.rb
|
416
408
|
- lib/sequel/extensions/integer64.rb
|
409
|
+
- lib/sequel/extensions/is_distinct_from.rb
|
417
410
|
- lib/sequel/extensions/looser_typecasting.rb
|
418
411
|
- lib/sequel/extensions/migration.rb
|
419
412
|
- lib/sequel/extensions/mssql_emulate_lateral_with_apply.rb
|
@@ -536,6 +529,7 @@ files:
|
|
536
529
|
- lib/sequel/plugins/prepared_statements.rb
|
537
530
|
- lib/sequel/plugins/prepared_statements_safe.rb
|
538
531
|
- lib/sequel/plugins/rcte_tree.rb
|
532
|
+
- lib/sequel/plugins/require_valid_schema.rb
|
539
533
|
- lib/sequel/plugins/serialization.rb
|
540
534
|
- lib/sequel/plugins/serialization_modification_detection.rb
|
541
535
|
- lib/sequel/plugins/sharding.rb
|