sequel 5.106.0 → 5.109.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/bin/sequel +5 -5
- data/lib/sequel/adapters/ado.rb +1 -1
- data/lib/sequel/adapters/amalgalite.rb +34 -8
- data/lib/sequel/adapters/ibmdb.rb +2 -2
- data/lib/sequel/adapters/jdbc/hsqldb.rb +1 -1
- data/lib/sequel/adapters/jdbc/mssql.rb +28 -5
- data/lib/sequel/adapters/jdbc/mysql.rb +1 -1
- data/lib/sequel/adapters/jdbc/postgresql.rb +14 -3
- data/lib/sequel/adapters/jdbc.rb +4 -3
- data/lib/sequel/adapters/mock.rb +1 -1
- data/lib/sequel/adapters/mysql.rb +7 -2
- data/lib/sequel/adapters/mysql2.rb +5 -4
- data/lib/sequel/adapters/postgres.rb +42 -39
- data/lib/sequel/adapters/shared/db2.rb +5 -2
- data/lib/sequel/adapters/shared/mssql.rb +11 -5
- data/lib/sequel/adapters/shared/mysql.rb +2 -2
- data/lib/sequel/adapters/shared/postgres.rb +80 -92
- data/lib/sequel/adapters/shared/sqlanywhere.rb +0 -32
- data/lib/sequel/adapters/shared/sqlite.rb +8 -7
- data/lib/sequel/adapters/sqlite.rb +13 -9
- data/lib/sequel/adapters/trilogy.rb +2 -1
- data/lib/sequel/adapters/utils/emulate_offset_with_reverse_and_count.rb +1 -1
- data/lib/sequel/adapters/utils/mysql_mysql2.rb +11 -1
- data/lib/sequel/connection_pool/sharded_single.rb +1 -1
- data/lib/sequel/connection_pool/sharded_threaded.rb +7 -5
- data/lib/sequel/connection_pool/sharded_timed_queue.rb +3 -3
- data/lib/sequel/connection_pool/threaded.rb +9 -7
- data/lib/sequel/connection_pool/timed_queue.rb +2 -2
- data/lib/sequel/connection_pool.rb +3 -3
- data/lib/sequel/core.rb +44 -24
- data/lib/sequel/database/connecting.rb +1 -1
- data/lib/sequel/database/features.rb +1 -1
- data/lib/sequel/database/misc.rb +6 -11
- data/lib/sequel/database/query.rb +2 -2
- data/lib/sequel/database/schema_generator.rb +7 -5
- data/lib/sequel/database/schema_methods.rb +2 -2
- data/lib/sequel/database/transactions.rb +5 -7
- data/lib/sequel/dataset/actions.rb +2 -2
- data/lib/sequel/dataset/features.rb +4 -4
- data/lib/sequel/dataset/graph.rb +1 -1
- data/lib/sequel/dataset/misc.rb +3 -3
- data/lib/sequel/dataset/prepared_statements.rb +2 -2
- data/lib/sequel/dataset/query.rb +8 -8
- data/lib/sequel/dataset/sql.rb +32 -13
- data/lib/sequel/dataset.rb +2 -2
- data/lib/sequel/deprecated.rb +2 -2
- data/lib/sequel/exceptions.rb +2 -2
- data/lib/sequel/extensions/_pretty_table.rb +1 -1
- data/lib/sequel/extensions/async_thread_pool.rb +3 -3
- data/lib/sequel/extensions/auto_cast_date_and_time.rb +2 -2
- data/lib/sequel/extensions/blank.rb +2 -2
- data/lib/sequel/extensions/constraint_validations.rb +1 -1
- data/lib/sequel/extensions/core_refinements.rb +7 -10
- data/lib/sequel/extensions/date_arithmetic.rb +1 -1
- data/lib/sequel/extensions/datetime_parse_to_time.rb +2 -2
- data/lib/sequel/extensions/duplicate_columns_handler.rb +1 -3
- data/lib/sequel/extensions/graph_each.rb +1 -1
- data/lib/sequel/extensions/index_caching.rb +1 -1
- data/lib/sequel/extensions/inflector.rb +5 -5
- data/lib/sequel/extensions/is_distinct_from.rb +2 -2
- data/lib/sequel/extensions/lit_require_frozen.rb +20 -4
- data/lib/sequel/extensions/migration.rb +21 -7
- data/lib/sequel/extensions/named_timezones.rb +9 -9
- data/lib/sequel/extensions/pg_array.rb +10 -8
- data/lib/sequel/extensions/pg_array_ops.rb +69 -14
- data/lib/sequel/extensions/pg_auto_parameterize.rb +2 -2
- data/lib/sequel/extensions/pg_auto_parameterize_in_array.rb +3 -3
- data/lib/sequel/extensions/pg_enum.rb +2 -2
- data/lib/sequel/extensions/pg_extended_date_support.rb +5 -5
- data/lib/sequel/extensions/pg_extended_integer_support.rb +1 -1
- data/lib/sequel/extensions/pg_hstore.rb +2 -2
- data/lib/sequel/extensions/pg_hstore_ops.rb +5 -5
- data/lib/sequel/extensions/pg_inet.rb +2 -2
- data/lib/sequel/extensions/pg_inet_ops.rb +2 -2
- data/lib/sequel/extensions/pg_interval.rb +6 -6
- data/lib/sequel/extensions/pg_json.rb +4 -4
- data/lib/sequel/extensions/pg_json_ops.rb +15 -13
- data/lib/sequel/extensions/pg_range.rb +6 -6
- data/lib/sequel/extensions/pg_range_ops.rb +7 -7
- data/lib/sequel/extensions/pg_row.rb +4 -4
- data/lib/sequel/extensions/pg_row_ops.rb +6 -6
- data/lib/sequel/extensions/provenance.rb +2 -2
- data/lib/sequel/extensions/query.rb +2 -2
- data/lib/sequel/extensions/s.rb +6 -10
- data/lib/sequel/extensions/schema_dumper.rb +10 -6
- data/lib/sequel/extensions/sequel_4_dataset_methods.rb +2 -0
- data/lib/sequel/extensions/sql_comments.rb +1 -1
- data/lib/sequel/extensions/sql_log_normalizer.rb +1 -1
- data/lib/sequel/extensions/sqlite_json_ops.rb +2 -2
- data/lib/sequel/extensions/string_agg.rb +5 -5
- data/lib/sequel/extensions/symbol_aref.rb +12 -32
- data/lib/sequel/extensions/symbol_aref_refinement.rb +2 -5
- data/lib/sequel/extensions/symbol_as.rb +1 -2
- data/lib/sequel/extensions/symbol_as_refinement.rb +1 -5
- data/lib/sequel/extensions/transaction_connection_validator.rb +1 -1
- data/lib/sequel/model/associations.rb +17 -17
- data/lib/sequel/model/base.rb +18 -15
- data/lib/sequel/model/inflections.rb +1 -1
- data/lib/sequel/model/plugins.rb +2 -2
- data/lib/sequel/model.rb +2 -2
- data/lib/sequel/plugins/association_pks.rb +1 -1
- data/lib/sequel/plugins/association_proxies.rb +4 -4
- data/lib/sequel/plugins/auto_restrict_eager_graph.rb +2 -0
- data/lib/sequel/plugins/caching.rb +28 -3
- data/lib/sequel/plugins/class_table_inheritance.rb +1 -1
- data/lib/sequel/plugins/column_encryption.rb +10 -10
- data/lib/sequel/plugins/concurrent_eager_loading.rb +2 -2
- data/lib/sequel/plugins/csv_serializer.rb +9 -20
- data/lib/sequel/plugins/deprecated_associations.rb +2 -2
- data/lib/sequel/plugins/eager_each.rb +1 -1
- data/lib/sequel/plugins/finder.rb +1 -1
- data/lib/sequel/plugins/forbid_lazy_load.rb +3 -3
- data/lib/sequel/plugins/insert_conflict.rb +1 -1
- data/lib/sequel/plugins/insert_returning_select.rb +1 -1
- data/lib/sequel/plugins/instance_filters.rb +8 -0
- data/lib/sequel/plugins/instance_hooks.rb +19 -0
- data/lib/sequel/plugins/json_serializer.rb +4 -4
- data/lib/sequel/plugins/lazy_attributes.rb +1 -1
- data/lib/sequel/plugins/many_through_many.rb +1 -1
- data/lib/sequel/plugins/mssql_optimistic_locking.rb +9 -0
- data/lib/sequel/plugins/optimistic_locking.rb +12 -2
- data/lib/sequel/plugins/optimistic_locking_base.rb +14 -0
- data/lib/sequel/plugins/pg_array_associations.rb +4 -4
- data/lib/sequel/plugins/pg_auto_constraint_validations.rb +3 -3
- data/lib/sequel/plugins/pg_eager_any_typed_array.rb +2 -2
- data/lib/sequel/plugins/pg_xmin_optimistic_locking.rb +11 -2
- data/lib/sequel/plugins/prepared_statements.rb +2 -2
- data/lib/sequel/plugins/select_on_skipped_update.rb +63 -0
- data/lib/sequel/plugins/serialization.rb +1 -1
- data/lib/sequel/plugins/sharding.rb +1 -1
- data/lib/sequel/plugins/single_table_inheritance.rb +21 -3
- data/lib/sequel/plugins/skip_saving_columns.rb +2 -2
- data/lib/sequel/plugins/split_values.rb +1 -1
- data/lib/sequel/plugins/sql_comments.rb +8 -8
- data/lib/sequel/plugins/subclasses.rb +6 -6
- data/lib/sequel/plugins/subset_conditions.rb +5 -16
- data/lib/sequel/plugins/tactical_eager_loading.rb +1 -1
- data/lib/sequel/plugins/throw_failures.rb +3 -3
- data/lib/sequel/plugins/unused_associations.rb +5 -5
- data/lib/sequel/plugins/validate_associated.rb +7 -1
- data/lib/sequel/plugins/validate_associated_context.rb +52 -0
- data/lib/sequel/plugins/validation_helpers.rb +1 -1
- data/lib/sequel/plugins/xml_serializer.rb +2 -0
- data/lib/sequel/sql.rb +120 -116
- data/lib/sequel/version.rb +1 -1
- metadata +5 -3
|
@@ -64,7 +64,7 @@ module Sequel
|
|
|
64
64
|
array = [].freeze
|
|
65
65
|
|
|
66
66
|
if RUBY_VERSION < '2.6'
|
|
67
|
-
# :
|
|
67
|
+
# simplecov:disable
|
|
68
68
|
|
|
69
69
|
# Default proc used to determine whether to send the method to the dataset.
|
|
70
70
|
# If the array would respond to it, sends it to the array instead of the dataset.
|
|
@@ -75,7 +75,7 @@ module Sequel
|
|
|
75
75
|
end
|
|
76
76
|
!array_method
|
|
77
77
|
end
|
|
78
|
-
# :
|
|
78
|
+
# simplecov:enable
|
|
79
79
|
else
|
|
80
80
|
DEFAULT_PROXY_TO_DATASET = proc{|opts| !array.respond_to?(opts[:method])}
|
|
81
81
|
end
|
|
@@ -99,9 +99,9 @@ module Sequel
|
|
|
99
99
|
end
|
|
100
100
|
v.public_send(meth, *args, &block)
|
|
101
101
|
end
|
|
102
|
-
# :
|
|
102
|
+
# simplecov:disable
|
|
103
103
|
ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
|
|
104
|
-
# :
|
|
104
|
+
# simplecov:enable
|
|
105
105
|
end
|
|
106
106
|
|
|
107
107
|
module ClassMethods
|
|
@@ -29,6 +29,13 @@ module Sequel
|
|
|
29
29
|
#
|
|
30
30
|
# You should not use this plugin if you are using sharding and there are different
|
|
31
31
|
# rows for the same primary key on different shards.
|
|
32
|
+
#
|
|
33
|
+
# Note that if you are using a composite key, and multiple columns in the composite
|
|
34
|
+
# key could potentially contain the character ",", you should override the
|
|
35
|
+
# +composite_cache_key+ class method to return an an unambiguous string identifying
|
|
36
|
+
# the specific primary key argument given. For consistency, if you would like to
|
|
37
|
+
# modify the cache key string used for scalar primary keys, you can override the
|
|
38
|
+
# +scalar_cache_key+ class method.
|
|
32
39
|
#
|
|
33
40
|
# Usage:
|
|
34
41
|
#
|
|
@@ -53,7 +60,7 @@ module Sequel
|
|
|
53
60
|
end
|
|
54
61
|
|
|
55
62
|
module ClassMethods
|
|
56
|
-
# If true, ignores exceptions when
|
|
63
|
+
# If true, ignores exceptions when getting cached records (the memcached API).
|
|
57
64
|
attr_reader :cache_ignore_exceptions
|
|
58
65
|
|
|
59
66
|
# The cache store object for the model, which should implement the
|
|
@@ -81,8 +88,26 @@ module Sequel
|
|
|
81
88
|
|
|
82
89
|
# Return a key string for the given primary key.
|
|
83
90
|
def cache_key(pk)
|
|
84
|
-
|
|
85
|
-
|
|
91
|
+
case pk
|
|
92
|
+
when Array
|
|
93
|
+
raise(Error, 'no primary key for this record') unless pk.all?
|
|
94
|
+
"#{cache_key_prefix}:#{composite_cache_key(pk)}"
|
|
95
|
+
else
|
|
96
|
+
raise(Error, 'no primary key for this record') unless pk
|
|
97
|
+
"#{cache_key_prefix}:#{scalar_cache_key(pk)}"
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Return an appropriate cache key string for a valid scalar primary key.
|
|
102
|
+
# By default, converts the primary key to a string.
|
|
103
|
+
def scalar_cache_key(pk)
|
|
104
|
+
pk.to_s
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Return an appropriate cache key string for a valid composite primary key.
|
|
108
|
+
# By default, joins with the parts of the compsite key with ",".
|
|
109
|
+
def composite_cache_key(pk)
|
|
110
|
+
pk.join(',')
|
|
86
111
|
end
|
|
87
112
|
|
|
88
113
|
Plugins.inherited_instance_variables(self, :@cache_store=>nil, :@cache_ttl=>nil, :@cache_ignore_exceptions=>nil)
|
|
@@ -79,7 +79,7 @@ module Sequel
|
|
|
79
79
|
# subclass instances that only have column entries for the columns in the
|
|
80
80
|
# superclass table. Calling the column method on the subclass instance for
|
|
81
81
|
# a column not in the superclass table will cause a query to the database
|
|
82
|
-
# to get the value for that column. If the subclass instance was
|
|
82
|
+
# to get the value for that column. If the subclass instance was retrieved
|
|
83
83
|
# using Dataset#all, the query to the database will attempt to load the column
|
|
84
84
|
# values for all subclass instances that were retrieved. For example:
|
|
85
85
|
#
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# frozen-string-literal: true
|
|
2
2
|
|
|
3
|
-
# :
|
|
3
|
+
# simplecov:disable
|
|
4
4
|
raise(Sequel::Error, "Sequel column_encryption plugin requires ruby 2.3 or greater") unless RUBY_VERSION >= '2.3'
|
|
5
|
-
# :
|
|
5
|
+
# simplecov:enable
|
|
6
6
|
|
|
7
7
|
require 'openssl'
|
|
8
8
|
|
|
@@ -22,13 +22,13 @@ begin
|
|
|
22
22
|
cipher.key = '1'*32
|
|
23
23
|
cipher.auth_data = ''
|
|
24
24
|
cipher.auth_tag = auth_tag
|
|
25
|
-
# :
|
|
25
|
+
# simplecov:disable
|
|
26
26
|
unless (cipher.update(cipher_text) << cipher.final) == '2'
|
|
27
27
|
raise OpenSSL::Cipher::CipherError
|
|
28
28
|
end
|
|
29
29
|
rescue RuntimeError, OpenSSL::Cipher::CipherError
|
|
30
30
|
raise LoadError, "Sequel column_encryption plugin requires a working aes-256-gcm cipher"
|
|
31
|
-
# :
|
|
31
|
+
# simplecov:enable
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
require 'securerandom'
|
|
@@ -279,7 +279,7 @@ module Sequel
|
|
|
279
279
|
#
|
|
280
280
|
# = Unsupported Features
|
|
281
281
|
#
|
|
282
|
-
# The following features are
|
|
282
|
+
# The following features are deliberately not supported:
|
|
283
283
|
#
|
|
284
284
|
# == Compression
|
|
285
285
|
#
|
|
@@ -475,12 +475,12 @@ module Sequel
|
|
|
475
475
|
def decode64(str)
|
|
476
476
|
str.unpack1("m0")
|
|
477
477
|
end
|
|
478
|
-
# :
|
|
478
|
+
# simplecov:disable
|
|
479
479
|
else
|
|
480
480
|
def decode64(str)
|
|
481
481
|
str.unpack("m0")[0]
|
|
482
482
|
end
|
|
483
|
-
# :
|
|
483
|
+
# simplecov:enable
|
|
484
484
|
end
|
|
485
485
|
|
|
486
486
|
def urlsafe_encode64(bin)
|
|
@@ -493,7 +493,7 @@ module Sequel
|
|
|
493
493
|
decode64(str.tr("-_", "+/"))
|
|
494
494
|
end
|
|
495
495
|
|
|
496
|
-
# An array of strings, one for each configured encryption key, to find
|
|
496
|
+
# An array of strings, one for each configured encryption key, to find encrypted values matching
|
|
497
497
|
# the given data and search format.
|
|
498
498
|
def _search_prefixes(data, search_type)
|
|
499
499
|
@key_map.map do |key_id, (key, _)|
|
|
@@ -610,7 +610,7 @@ module Sequel
|
|
|
610
610
|
end
|
|
611
611
|
end
|
|
612
612
|
|
|
613
|
-
# This stores four callables for handling
|
|
613
|
+
# This stores four callables for handling encryption, decryption, data searching,
|
|
614
614
|
# and key searching. One of these is created for each encrypted column.
|
|
615
615
|
ColumnEncryptionMetadata = Struct.new(:encryptor, :decryptor, :data_searcher, :key_searcher) # :nodoc:
|
|
616
616
|
|
|
@@ -702,7 +702,7 @@ module Sequel
|
|
|
702
702
|
|
|
703
703
|
module InstanceMethods
|
|
704
704
|
# Reencrypt the model if needed. Looks at all of the models encrypted columns
|
|
705
|
-
# and if any were
|
|
705
|
+
# and if any were encrypted with older keys or a different format, reencrypt
|
|
706
706
|
# with the current key and format and save the object. Returns the object
|
|
707
707
|
# if reencryption was needed, or nil if reencryption was not needed.
|
|
708
708
|
def reencrypt
|
|
@@ -69,8 +69,8 @@ module Sequel
|
|
|
69
69
|
# To keep things simple, you can use +Sequel.synchronize_with+ to only
|
|
70
70
|
# use this mutex if it is available. You want to use the mutex around the
|
|
71
71
|
# code that initializes the associations (usually to +nil+ or <tt>[]</tt>),
|
|
72
|
-
# and also around the code that sets the
|
|
73
|
-
# after they have been
|
|
72
|
+
# and also around the code that sets the associated objects appropriately
|
|
73
|
+
# after they have been retrieved. You do not want to use the mutex around
|
|
74
74
|
# the code that loads the objects, since that will prevent concurrent loading.
|
|
75
75
|
# So after the changes, the custom eager loader would look like this:
|
|
76
76
|
#
|
|
@@ -73,23 +73,12 @@ module Sequel
|
|
|
73
73
|
end
|
|
74
74
|
end
|
|
75
75
|
|
|
76
|
-
#
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
def self.csv_call(*args, opts, &block)
|
|
81
|
-
CSV.send(*args, **opts, &block)
|
|
82
|
-
end
|
|
83
|
-
END
|
|
84
|
-
else
|
|
85
|
-
# :nocov:
|
|
86
|
-
# :nodoc:
|
|
87
|
-
def self.csv_call(*args, opts, &block)
|
|
88
|
-
CSV.send(*args, opts, &block)
|
|
89
|
-
end
|
|
90
|
-
# :nodoc:
|
|
91
|
-
# :nocov:
|
|
76
|
+
# simplecov:disable
|
|
77
|
+
def self.csv_call(*args, opts, &block)
|
|
78
|
+
Sequel::Deprecation.deprecate("Sequel::Plugins::CsvSerializer.csv_call will be removed in Sequel 6.")
|
|
79
|
+
CSV.send(*args, **opts, &block)
|
|
92
80
|
end
|
|
81
|
+
# simplecov:enable
|
|
93
82
|
|
|
94
83
|
module ClassMethods
|
|
95
84
|
# The default opts to use when serializing model objects to CSV
|
|
@@ -97,7 +86,7 @@ module Sequel
|
|
|
97
86
|
|
|
98
87
|
# Attempt to parse an array of instances from the given CSV string
|
|
99
88
|
def array_from_csv(csv, opts = OPTS)
|
|
100
|
-
|
|
89
|
+
CSV.parse(csv, **process_csv_serializer_opts(opts)).map do |row|
|
|
101
90
|
row = row.to_hash
|
|
102
91
|
row.delete(nil)
|
|
103
92
|
new(row)
|
|
@@ -147,7 +136,7 @@ module Sequel
|
|
|
147
136
|
# :headers :: The headers to use for the CSV line. Use nil for a header
|
|
148
137
|
# to specify the column should be ignored.
|
|
149
138
|
def from_csv(csv, opts = OPTS)
|
|
150
|
-
row =
|
|
139
|
+
row = CSV.parse_line(csv, **model.process_csv_serializer_opts(opts)).to_hash
|
|
151
140
|
row.delete(nil)
|
|
152
141
|
set(row)
|
|
153
142
|
end
|
|
@@ -165,7 +154,7 @@ module Sequel
|
|
|
165
154
|
opts = model.process_csv_serializer_opts(opts)
|
|
166
155
|
headers = opts[:headers]
|
|
167
156
|
|
|
168
|
-
|
|
157
|
+
CSV.generate(**model.process_csv_serializer_opts(opts)) do |csv|
|
|
169
158
|
csv << headers.map{|k| public_send(k)}
|
|
170
159
|
end
|
|
171
160
|
end
|
|
@@ -184,7 +173,7 @@ module Sequel
|
|
|
184
173
|
items = opts.delete(:array) || self
|
|
185
174
|
headers = opts[:headers]
|
|
186
175
|
|
|
187
|
-
|
|
176
|
+
CSV.generate(**opts) do |csv|
|
|
188
177
|
items.each do |object|
|
|
189
178
|
csv << headers.map{|header| object.public_send(header)}
|
|
190
179
|
end
|
|
@@ -77,7 +77,7 @@ module Sequel
|
|
|
77
77
|
|
|
78
78
|
private
|
|
79
79
|
|
|
80
|
-
#
|
|
80
|
+
# Whether to use all when each is called, true when eager loading
|
|
81
81
|
# unless the flag has already been set.
|
|
82
82
|
def use_eager_all?
|
|
83
83
|
(opts[:eager] || opts[:eager_graph]) && !opts[:all_called]
|
|
@@ -237,7 +237,7 @@ module Sequel
|
|
|
237
237
|
end
|
|
238
238
|
end
|
|
239
239
|
|
|
240
|
-
# Clear any finders when
|
|
240
|
+
# Clear any finders when resetting the instance dataset
|
|
241
241
|
def reset_instance_dataset
|
|
242
242
|
Sequel.synchronize{@finders.clear} if @finders && !@finders.frozen?
|
|
243
243
|
super
|
|
@@ -9,7 +9,7 @@ module Sequel
|
|
|
9
9
|
# The main reason for doing this is it makes it easier to detect
|
|
10
10
|
# N+1 query issues. Note that Sequel also offers a
|
|
11
11
|
# tactical_eager_loading plugin which will automatically eagerly
|
|
12
|
-
# load associations for all objects
|
|
12
|
+
# load associations for all objects retrieved in the same query
|
|
13
13
|
# if any object would attempt to lazily load an association. That
|
|
14
14
|
# approach may be simpler if you are trying to prevent N+1 issues,
|
|
15
15
|
# though it does retain more objects in memory.
|
|
@@ -125,9 +125,9 @@ module Sequel
|
|
|
125
125
|
# an association, allow lazy loading that association, since the
|
|
126
126
|
# lazy association load will use a hash table lookup and not a query.
|
|
127
127
|
def allow_lazy_load_for_static_cache_associations
|
|
128
|
-
# :
|
|
128
|
+
# simplecov:disable
|
|
129
129
|
if defined?(::Sequel::Plugins::StaticCache::ClassMethods)
|
|
130
|
-
# :
|
|
130
|
+
# simplecov:enable
|
|
131
131
|
@association_reflections.each_value do |ref|
|
|
132
132
|
if ref.associated_class.is_a?(::Sequel::Plugins::StaticCache::ClassMethods)
|
|
133
133
|
ref[:forbid_lazy_load] = false
|
|
@@ -19,7 +19,7 @@ module Sequel
|
|
|
19
19
|
#
|
|
20
20
|
# This example will try to insert the album, but if there is an existing
|
|
21
21
|
# album with the name 'Foo', this will update the copies_sold attribute
|
|
22
|
-
# for that album. See the PostgreSQL and SQLite adapter
|
|
22
|
+
# for that album. See the PostgreSQL and SQLite adapter documentation for
|
|
23
23
|
# the options you can pass to the insert_conflict method.
|
|
24
24
|
#
|
|
25
25
|
# You should not attempt to use this plugin to ignore conflicts when
|
|
@@ -32,7 +32,7 @@ module Sequel
|
|
|
32
32
|
|
|
33
33
|
private
|
|
34
34
|
|
|
35
|
-
# When
|
|
35
|
+
# When resetting the instance dataset, also reset the instance_insert_dataset.
|
|
36
36
|
def reset_instance_dataset
|
|
37
37
|
ret = super
|
|
38
38
|
return unless ds = @instance_dataset
|
|
@@ -80,6 +80,14 @@ module Sequel
|
|
|
80
80
|
instance_filters << [args, block]
|
|
81
81
|
end
|
|
82
82
|
|
|
83
|
+
# Clear instance filters when saving changes even if the
|
|
84
|
+
# object wasn't modified.
|
|
85
|
+
def save_changes(opts=OPTS)
|
|
86
|
+
ret = super
|
|
87
|
+
clear_instance_filters if ret.nil?
|
|
88
|
+
ret
|
|
89
|
+
end
|
|
90
|
+
|
|
83
91
|
private
|
|
84
92
|
|
|
85
93
|
# If there are any instance filters, make sure not to use the
|
|
@@ -93,6 +93,25 @@ module Sequel
|
|
|
93
93
|
super
|
|
94
94
|
end
|
|
95
95
|
|
|
96
|
+
# Run and clear save/update/validation hooks when saving changes even if the
|
|
97
|
+
# object wasn't modified.
|
|
98
|
+
def save_changes(opts=OPTS)
|
|
99
|
+
ret = super
|
|
100
|
+
if ret.nil? && @instance_hooks
|
|
101
|
+
run_before_instance_hooks(:before_validation)
|
|
102
|
+
run_before_instance_hooks(:after_validation)
|
|
103
|
+
run_before_instance_hooks(:before_save)
|
|
104
|
+
run_before_instance_hooks(:before_update)
|
|
105
|
+
ret = super
|
|
106
|
+
run_before_instance_hooks(:after_update)
|
|
107
|
+
run_before_instance_hooks(:after_save)
|
|
108
|
+
[:before_validation, :after_validation, :before_save, :before_update, :after_update, :after_save].each do |type|
|
|
109
|
+
@instance_hooks.delete(type)
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
ret
|
|
113
|
+
end
|
|
114
|
+
|
|
96
115
|
private
|
|
97
116
|
|
|
98
117
|
# Add the block as an instance level hook. For before hooks, add it to
|
|
@@ -128,7 +128,7 @@ module Sequel
|
|
|
128
128
|
end
|
|
129
129
|
|
|
130
130
|
# SEQUEL6: Remove
|
|
131
|
-
# :
|
|
131
|
+
# simplecov:disable
|
|
132
132
|
class Literal
|
|
133
133
|
def initialize(json)
|
|
134
134
|
@json = json
|
|
@@ -138,7 +138,7 @@ module Sequel
|
|
|
138
138
|
@json
|
|
139
139
|
end
|
|
140
140
|
end
|
|
141
|
-
# :
|
|
141
|
+
# simplecov:enable
|
|
142
142
|
Sequel::Deprecation.deprecate_constant(self, :Literal)
|
|
143
143
|
|
|
144
144
|
# Convert the given object to a JSON data structure using the given arguments.
|
|
@@ -151,11 +151,11 @@ module Sequel
|
|
|
151
151
|
else
|
|
152
152
|
begin
|
|
153
153
|
Sequel.parse_json(Sequel.object_to_json(obj, *args, &block))
|
|
154
|
-
# :
|
|
154
|
+
# simplecov:disable
|
|
155
155
|
rescue Sequel.json_parser_error_class
|
|
156
156
|
# Support for old Ruby code that only supports parsing JSON object/array
|
|
157
157
|
Sequel.parse_json(Sequel.object_to_json([obj], *args, &block))[0]
|
|
158
|
-
# :
|
|
158
|
+
# simplecov:enable
|
|
159
159
|
end
|
|
160
160
|
end
|
|
161
161
|
end
|
|
@@ -5,7 +5,7 @@ module Sequel
|
|
|
5
5
|
# The lazy_attributes plugin allows users to easily set that some attributes
|
|
6
6
|
# should not be loaded by default when loading model objects. If the attribute
|
|
7
7
|
# is needed after the instance has been retrieved, a database query is made to
|
|
8
|
-
#
|
|
8
|
+
# retrieve the value of the attribute.
|
|
9
9
|
#
|
|
10
10
|
# This plugin depends on the tactical_eager_loading plugin, and allows you to
|
|
11
11
|
# eagerly load lazy attributes for all objects retrieved with the current object.
|
|
@@ -243,7 +243,7 @@ module Sequel
|
|
|
243
243
|
# :conditions :: Extra conditions to add to the JOIN ON clause. Must be a hash or array of two pairs.
|
|
244
244
|
# :join_type :: The join type to use for the join, defaults to :left_outer.
|
|
245
245
|
# :only_conditions :: Conditions to use for the join instead of the ones specified by the keys.
|
|
246
|
-
# opts :: The options for the
|
|
246
|
+
# opts :: The options for the association. Takes the same options as many_to_many.
|
|
247
247
|
def many_through_many(name, through, opts=OPTS, &block)
|
|
248
248
|
associate(:many_through_many, name, opts.merge(through.is_a?(Hash) ? through : {:through=>through}), &block)
|
|
249
249
|
end
|
|
@@ -22,6 +22,13 @@ module Sequel
|
|
|
22
22
|
#
|
|
23
23
|
# plugin :mssql_optimistic_locking, lock_column: :column_name
|
|
24
24
|
#
|
|
25
|
+
# By default, the plugin allows using the lock column setter method to
|
|
26
|
+
# either increase or decrease the lock column value. To prevent increases,
|
|
27
|
+
# which could potentially be used to skip an update when it update should
|
|
28
|
+
# be made, you can use the +:prevent_increase+ plugin option:
|
|
29
|
+
#
|
|
30
|
+
# plugin :mssql_optimistic_locking, prevent_increase: true
|
|
31
|
+
#
|
|
25
32
|
# This plugin relies on the instance_filters plugin.
|
|
26
33
|
module MssqlOptimisticLocking
|
|
27
34
|
# Load the instance_filters plugin into the model.
|
|
@@ -32,6 +39,8 @@ module Sequel
|
|
|
32
39
|
# Set the lock column
|
|
33
40
|
def self.configure(model, opts=OPTS)
|
|
34
41
|
model.lock_column = opts[:lock_column] || model.lock_column || :timestamp
|
|
42
|
+
# SEQUEL6: Make prevent_increase true by default
|
|
43
|
+
model.send(:prevent_lock_column_increase!) if opts[:prevent_increase]
|
|
35
44
|
end
|
|
36
45
|
|
|
37
46
|
module InstanceMethods
|
|
@@ -20,6 +20,13 @@ module Sequel
|
|
|
20
20
|
#
|
|
21
21
|
# plugin :optimistic_locking, lock_column: :version
|
|
22
22
|
#
|
|
23
|
+
# By default, the plugin allows using the lock column setter method to
|
|
24
|
+
# either increase or decrease the lock column value. To prevent increases,
|
|
25
|
+
# which could potentially be used to skip an update when it update should
|
|
26
|
+
# be made, you can use the +:prevent_increase+ plugin option:
|
|
27
|
+
#
|
|
28
|
+
# plugin :optimistic_locking, prevent_increase: true
|
|
29
|
+
#
|
|
23
30
|
# This plugin relies on the instance_filters plugin.
|
|
24
31
|
module OptimisticLocking
|
|
25
32
|
# Exception class raised when trying to update or destroy a stale object.
|
|
@@ -32,6 +39,8 @@ module Sequel
|
|
|
32
39
|
# Set the lock column
|
|
33
40
|
def self.configure(model, opts=OPTS)
|
|
34
41
|
model.lock_column = opts[:lock_column] || model.lock_column || :lock_version
|
|
42
|
+
# SEQUEL6: Make prevent_increase true by default
|
|
43
|
+
model.send(:prevent_lock_column_increase!) if opts[:prevent_increase]
|
|
35
44
|
end
|
|
36
45
|
|
|
37
46
|
module InstanceMethods
|
|
@@ -42,9 +51,10 @@ module Sequel
|
|
|
42
51
|
def _update_columns(columns)
|
|
43
52
|
lc = model.lock_column
|
|
44
53
|
lcv = get_column_value(lc)
|
|
45
|
-
columns[lc] = lcv + 1
|
|
54
|
+
new_lcv = columns[lc] = lcv + 1
|
|
46
55
|
super
|
|
47
|
-
set_column_value("#{lc}=",
|
|
56
|
+
set_column_value("#{lc}=", nil)
|
|
57
|
+
set_column_value("#{lc}=", new_lcv)
|
|
48
58
|
changed_columns.delete(lc)
|
|
49
59
|
nil
|
|
50
60
|
end
|
|
@@ -12,6 +12,20 @@ module Sequel
|
|
|
12
12
|
module ClassMethods
|
|
13
13
|
# The column holding the version of the lock
|
|
14
14
|
attr_accessor :lock_column
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
# Prevent increasing the value of the lock column. If the lock column
|
|
19
|
+
# has an existing value, do not allow setting a value that is higher
|
|
20
|
+
# than it.
|
|
21
|
+
def prevent_lock_column_increase!
|
|
22
|
+
lc = lock_column
|
|
23
|
+
define_method(:"#{lc}=") do |v|
|
|
24
|
+
unless v && (lv = send(lc)) && v > lv
|
|
25
|
+
super(v)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
15
29
|
|
|
16
30
|
Plugins.inherited_instance_variables(self, :@lock_column=>nil)
|
|
17
31
|
end
|
|
@@ -534,9 +534,9 @@ module Sequel
|
|
|
534
534
|
def many_to_pg_array_association_filter_expression(op, ref, obj)
|
|
535
535
|
pk = ref.qualify(model.table_name, ref.primary_key)
|
|
536
536
|
key = ref[:key]
|
|
537
|
-
# :
|
|
537
|
+
# simplecov:disable
|
|
538
538
|
expr = case obj
|
|
539
|
-
# :
|
|
539
|
+
# simplecov:enable
|
|
540
540
|
when Sequel::Model
|
|
541
541
|
if (assoc_pks = obj.get_column_value(key)) && !assoc_pks.empty?
|
|
542
542
|
Sequel[pk=>assoc_pks.to_a]
|
|
@@ -556,9 +556,9 @@ module Sequel
|
|
|
556
556
|
# Support filtering by pg_array_to_many associations using a subquery.
|
|
557
557
|
def pg_array_to_many_association_filter_expression(op, ref, obj)
|
|
558
558
|
key = ref.qualify(model.table_name, ref[:key_column])
|
|
559
|
-
# :
|
|
559
|
+
# simplecov:disable
|
|
560
560
|
expr = case obj
|
|
561
|
-
# :
|
|
561
|
+
# simplecov:enable
|
|
562
562
|
when Sequel::Model
|
|
563
563
|
if pkv = obj.get_column_value(ref.primary_key_method)
|
|
564
564
|
Sequel.pg_array_op(key).contains(Sequel.pg_array([pkv], ref.array_type))
|
|
@@ -261,9 +261,9 @@ module Sequel
|
|
|
261
261
|
messages = model.pg_auto_constraint_validations_messages
|
|
262
262
|
|
|
263
263
|
unless override
|
|
264
|
-
# :
|
|
264
|
+
# simplecov:disable
|
|
265
265
|
case e
|
|
266
|
-
# :
|
|
266
|
+
# simplecov:enable
|
|
267
267
|
when Sequel::NotNullConstraintViolation
|
|
268
268
|
if column = info[:column]
|
|
269
269
|
add_pg_constraint_validation_error([m.call(column)], messages[:not_null])
|
|
@@ -297,7 +297,7 @@ module Sequel
|
|
|
297
297
|
end
|
|
298
298
|
end
|
|
299
299
|
rescue
|
|
300
|
-
# If there is an error trying to
|
|
300
|
+
# If there is an error trying to convert the constraint violation
|
|
301
301
|
# into a validation failure, it's best to just raise the constraint
|
|
302
302
|
# violation. This can make debugging the above block of code more
|
|
303
303
|
# difficult.
|
|
@@ -45,7 +45,7 @@ module Sequel
|
|
|
45
45
|
key = key.column
|
|
46
46
|
end
|
|
47
47
|
|
|
48
|
-
# :
|
|
48
|
+
# simplecov:disable
|
|
49
49
|
# many_to_pg_array association type does not need changes, as it
|
|
50
50
|
# already converts the values to a typed postgres array, it does
|
|
51
51
|
# not call the code that uses :eager_loading_predicate_transform.
|
|
@@ -54,7 +54,7 @@ module Sequel
|
|
|
54
54
|
# unless it is one of these types, but external association types
|
|
55
55
|
# could potentially reach it.
|
|
56
56
|
sch = case ref[:type]
|
|
57
|
-
# :
|
|
57
|
+
# simplecov:enable
|
|
58
58
|
when :many_to_one, :one_to_one, :one_to_many, :pg_array_to_many
|
|
59
59
|
ref.associated_class.db_schema
|
|
60
60
|
when :many_to_many, :one_through_one
|
|
@@ -21,6 +21,13 @@ module Sequel
|
|
|
21
21
|
# optimistic locking. The disadvantage is that testing can be
|
|
22
22
|
# more difficult if you are modifying the underlying row between
|
|
23
23
|
# when a model is retrieved and when it is saved.
|
|
24
|
+
|
|
25
|
+
# By default, the plugin allows using the +xmin=+ setter method to
|
|
26
|
+
# either increase or decrease the lock value. To prevent increases,
|
|
27
|
+
# which could potentially be used to skip an update when it update should
|
|
28
|
+
# be made, you can use the +:prevent_increase+ plugin argument:
|
|
29
|
+
#
|
|
30
|
+
# plugin :pg_xmin_optimistic_locking, prevent_increase: true
|
|
24
31
|
#
|
|
25
32
|
# This plugin may not work with the class_table_inheritance plugin.
|
|
26
33
|
#
|
|
@@ -29,7 +36,7 @@ module Sequel
|
|
|
29
36
|
WILDCARD = LiteralString.new('*').freeze
|
|
30
37
|
|
|
31
38
|
# Define the xmin column accessor
|
|
32
|
-
def self.apply(model)
|
|
39
|
+
def self.apply(model, prevent_increase: false)
|
|
33
40
|
model.instance_exec do
|
|
34
41
|
plugin(:optimistic_locking_base)
|
|
35
42
|
@lock_column = :xmin
|
|
@@ -39,9 +46,11 @@ module Sequel
|
|
|
39
46
|
|
|
40
47
|
# Update the dataset to append the xmin column if it is usable
|
|
41
48
|
# and there is a dataset for the model.
|
|
42
|
-
def self.configure(model)
|
|
49
|
+
def self.configure(model, prevent_increase: false)
|
|
43
50
|
model.instance_exec do
|
|
44
51
|
set_dataset(@dataset) if @dataset
|
|
52
|
+
# SEQUEL6: Make prevent_increase true by default
|
|
53
|
+
prevent_lock_column_increase! if prevent_increase
|
|
45
54
|
end
|
|
46
55
|
end
|
|
47
56
|
|
|
@@ -181,11 +181,11 @@ module Sequel
|
|
|
181
181
|
# Disabling usage of prepared statements for insert_select on SQLite seems to be the
|
|
182
182
|
# simplest way to workaround the problem.
|
|
183
183
|
db.database_type != :sqlite
|
|
184
|
-
# :
|
|
184
|
+
# simplecov:disable
|
|
185
185
|
when :delete, :refresh
|
|
186
186
|
Sequel::Deprecation.deprecate("The :delete and :refresh prepared statement types", "There should be no need to check if these types are supported")
|
|
187
187
|
false
|
|
188
|
-
# :
|
|
188
|
+
# simplecov:enable
|
|
189
189
|
else
|
|
190
190
|
raise Error, "unsupported type used: #{type.inspect}"
|
|
191
191
|
end
|