sequel 5.108.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/lib/sequel/adapters/amalgalite.rb +34 -8
- data/lib/sequel/adapters/jdbc/mssql.rb +28 -5
- data/lib/sequel/adapters/jdbc/postgresql.rb +14 -3
- data/lib/sequel/adapters/jdbc.rb +2 -1
- data/lib/sequel/adapters/postgres.rb +5 -2
- data/lib/sequel/adapters/shared/db2.rb +3 -0
- data/lib/sequel/adapters/shared/mssql.rb +7 -1
- data/lib/sequel/adapters/shared/postgres.rb +19 -990
- data/lib/sequel/adapters/shared/sqlanywhere.rb +0 -32
- data/lib/sequel/adapters/sqlite.rb +13 -9
- data/lib/sequel/adapters/trilogy.rb +2 -1
- data/lib/sequel/core.rb +14 -2
- data/lib/sequel/database/misc.rb +1 -6
- data/lib/sequel/database/transactions.rb +1 -3
- data/lib/sequel/dataset/actions.rb +1 -1
- data/lib/sequel/dataset/sql.rb +14 -3
- data/lib/sequel/extensions/core_refinements.rb +1 -4
- data/lib/sequel/extensions/duplicate_columns_handler.rb +1 -3
- data/lib/sequel/extensions/lit_require_frozen.rb +17 -1
- data/lib/sequel/extensions/named_timezones.rb +1 -1
- data/lib/sequel/extensions/pg_array.rb +1 -0
- data/lib/sequel/extensions/pg_json_ops.rb +4 -2
- data/lib/sequel/extensions/s.rb +4 -8
- data/lib/sequel/extensions/schema_dumper.rb +6 -2
- data/lib/sequel/extensions/symbol_aref.rb +11 -31
- data/lib/sequel/extensions/symbol_aref_refinement.rb +1 -4
- data/lib/sequel/extensions/symbol_as.rb +1 -2
- data/lib/sequel/extensions/symbol_as_refinement.rb +1 -5
- data/lib/sequel/model/base.rb +1 -6
- data/lib/sequel/plugins/caching.rb +27 -2
- data/lib/sequel/plugins/csv_serializer.rb +9 -20
- data/lib/sequel/plugins/instance_filters.rb +8 -0
- data/lib/sequel/plugins/instance_hooks.rb +19 -0
- 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_xmin_optimistic_locking.rb +11 -2
- data/lib/sequel/plugins/select_on_skipped_update.rb +63 -0
- data/lib/sequel/plugins/single_table_inheritance.rb +20 -2
- data/lib/sequel/plugins/subset_conditions.rb +5 -16
- data/lib/sequel/plugins/throw_failures.rb +1 -1
- data/lib/sequel/plugins/validate_associated.rb +7 -1
- data/lib/sequel/plugins/validate_associated_context.rb +52 -0
- data/lib/sequel/sql.rb +109 -105
- data/lib/sequel/version.rb +1 -1
- metadata +5 -3
|
@@ -305,38 +305,6 @@ module Sequel
|
|
|
305
305
|
super(sql, :+, args)
|
|
306
306
|
when :<<, :>>
|
|
307
307
|
complex_expression_emulate_append(sql, op, args)
|
|
308
|
-
when :LIKE, :"NOT LIKE"
|
|
309
|
-
sql << '('
|
|
310
|
-
literal_append(sql, args[0])
|
|
311
|
-
sql << (op == :LIKE ? ' REGEXP ' : ' NOT REGEXP ')
|
|
312
|
-
pattern = String.new
|
|
313
|
-
last_c = ''
|
|
314
|
-
args[1].each_char do |c|
|
|
315
|
-
if c == '_' and not pattern.end_with?('\\') and last_c != '\\'
|
|
316
|
-
pattern << '.'
|
|
317
|
-
elsif c == '%' and not pattern.end_with?('\\') and last_c != '\\'
|
|
318
|
-
pattern << '.*'
|
|
319
|
-
elsif c == '[' and not pattern.end_with?('\\') and last_c != '\\'
|
|
320
|
-
pattern << '\['
|
|
321
|
-
elsif c == ']' and not pattern.end_with?('\\') and last_c != '\\'
|
|
322
|
-
pattern << '\]'
|
|
323
|
-
elsif c == '*' and not pattern.end_with?('\\') and last_c != '\\'
|
|
324
|
-
pattern << '\*'
|
|
325
|
-
elsif c == '?' and not pattern.end_with?('\\') and last_c != '\\'
|
|
326
|
-
pattern << '\?'
|
|
327
|
-
else
|
|
328
|
-
pattern << c
|
|
329
|
-
end
|
|
330
|
-
if c == '\\' and last_c == '\\'
|
|
331
|
-
last_c = ''
|
|
332
|
-
else
|
|
333
|
-
last_c = c
|
|
334
|
-
end
|
|
335
|
-
end
|
|
336
|
-
literal_append(sql, pattern)
|
|
337
|
-
sql << " ESCAPE "
|
|
338
|
-
literal_append(sql, "\\")
|
|
339
|
-
sql << ')'
|
|
340
308
|
when :ILIKE, :"NOT ILIKE"
|
|
341
309
|
super(sql, (op == :ILIKE ? :LIKE : :"NOT LIKE"), args)
|
|
342
310
|
when :extract
|
|
@@ -336,16 +336,20 @@ module Sequel
|
|
|
336
336
|
log_sql << sql
|
|
337
337
|
log_sql << ")"
|
|
338
338
|
end
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
339
|
+
begin
|
|
340
|
+
if block
|
|
341
|
+
log_connection_yield(log_sql, conn, args){cps.execute(ps_args, &block)}
|
|
342
|
+
else
|
|
343
|
+
log_connection_yield(log_sql, conn, args){cps.execute!(ps_args){|r|}}
|
|
344
|
+
case type
|
|
345
|
+
when :insert
|
|
346
|
+
conn.last_insert_row_id
|
|
347
|
+
when :update
|
|
348
|
+
conn.changes
|
|
349
|
+
end
|
|
348
350
|
end
|
|
351
|
+
ensure
|
|
352
|
+
cps.clear_bindings!
|
|
349
353
|
end
|
|
350
354
|
end
|
|
351
355
|
|
data/lib/sequel/core.rb
CHANGED
|
@@ -156,7 +156,15 @@ module Sequel
|
|
|
156
156
|
# Sequel.extension(:blank)
|
|
157
157
|
# Sequel.extension(:core_extensions, :named_timezones)
|
|
158
158
|
def extension(*extensions)
|
|
159
|
-
extensions.each
|
|
159
|
+
extensions.each do |e|
|
|
160
|
+
e = e.to_s
|
|
161
|
+
|
|
162
|
+
if %r{..[/\\]} =~ e
|
|
163
|
+
raise Error, "cannot use extension with ../ for security reasons"
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
orig_require("sequel/extensions/#{e}")
|
|
167
|
+
end
|
|
160
168
|
end
|
|
161
169
|
|
|
162
170
|
# The exception classed raised if there is an error parsing JSON.
|
|
@@ -203,7 +211,11 @@ module Sequel
|
|
|
203
211
|
# Parse the string as JSON and return the result.
|
|
204
212
|
# This can be overridden to use an alternative json implementation.
|
|
205
213
|
def parse_json(json)
|
|
206
|
-
JSON
|
|
214
|
+
if JSON::VERSION >= '3'
|
|
215
|
+
JSON.parse(json)
|
|
216
|
+
else
|
|
217
|
+
JSON.parse(json, :create_additions=>false)
|
|
218
|
+
end
|
|
207
219
|
end
|
|
208
220
|
|
|
209
221
|
# If a mutex is given, synchronize access using it. If nil is given, just
|
data/lib/sequel/database/misc.rb
CHANGED
|
@@ -229,12 +229,7 @@ module Sequel
|
|
|
229
229
|
end
|
|
230
230
|
|
|
231
231
|
# Disallow dup/clone for Database instances
|
|
232
|
-
undef_method :dup, :clone, :initialize_copy
|
|
233
|
-
# simplecov:disable
|
|
234
|
-
if RUBY_VERSION >= '1.9.3'
|
|
235
|
-
# simplecov:enable
|
|
236
|
-
undef_method :initialize_clone, :initialize_dup
|
|
237
|
-
end
|
|
232
|
+
undef_method :dup, :clone, :initialize_copy, :initialize_clone, :initialize_dup
|
|
238
233
|
|
|
239
234
|
# Cast the given type to a literal type
|
|
240
235
|
#
|
|
@@ -374,9 +374,7 @@ module Sequel
|
|
|
374
374
|
|
|
375
375
|
# Whether to commit the current transaction. Thread.current.status is
|
|
376
376
|
# checked because Thread#kill skips rescue blocks (so exception would be
|
|
377
|
-
# nil), but the transaction should still be rolled back.
|
|
378
|
-
# not 2.0+), the thread status will still be "run", so Thread#kill
|
|
379
|
-
# will erroneously commit the transaction, and there isn't a workaround.
|
|
377
|
+
# nil), but the transaction should still be rolled back.
|
|
380
378
|
def commit_or_rollback_transaction(exception, conn, opts)
|
|
381
379
|
if exception
|
|
382
380
|
false
|
data/lib/sequel/dataset/sql.rb
CHANGED
|
@@ -1346,10 +1346,21 @@ module Sequel
|
|
|
1346
1346
|
alias delete_returning_sql insert_returning_sql
|
|
1347
1347
|
alias update_returning_sql insert_returning_sql
|
|
1348
1348
|
|
|
1349
|
-
|
|
1350
|
-
|
|
1349
|
+
JOIN_TYPE_SQL = {}
|
|
1350
|
+
(CONDITIONED_JOIN_TYPES + UNCONDITIONED_JOIN_TYPES + %i[natural_inner natural_left_outer natural_right_outer natural_full_outer]).each do |join_type|
|
|
1351
|
+
JOIN_TYPE_SQL[join_type] = "#{join_type.to_s.tr('_', ' ').upcase} JOIN".freeze
|
|
1352
|
+
end
|
|
1353
|
+
JOIN_TYPE_SQL[nil] = "JOIN"
|
|
1354
|
+
JOIN_TYPE_SQL.freeze
|
|
1355
|
+
private_constant :JOIN_TYPE_SQL
|
|
1356
|
+
|
|
1357
|
+
# SQL fragment for join type
|
|
1351
1358
|
def join_type_sql(join_type)
|
|
1352
|
-
|
|
1359
|
+
JOIN_TYPE_SQL.fetch(join_type) do
|
|
1360
|
+
# SEQUEL6: Raise error
|
|
1361
|
+
Sequel::Deprecation.deprecate("Unrecognized join type used: #{join_type.inspect}. This will raise an error starting in Sequel 6.")
|
|
1362
|
+
"#{join_type.to_s.tr('_', ' ').upcase} JOIN"
|
|
1363
|
+
end
|
|
1353
1364
|
end
|
|
1354
1365
|
|
|
1355
1366
|
# Append USING clause for JOIN USING
|
|
@@ -10,10 +10,7 @@
|
|
|
10
10
|
#
|
|
11
11
|
# using Sequel::CoreRefinements
|
|
12
12
|
|
|
13
|
-
#
|
|
14
|
-
raise(Sequel::Error, "Refinements require ruby 2.0.0 or greater") unless RUBY_VERSION >= '2.0.0'
|
|
15
|
-
# simplecov:enable
|
|
16
|
-
|
|
13
|
+
#
|
|
17
14
|
module Sequel::CoreRefinements
|
|
18
15
|
# simplecov:disable
|
|
19
16
|
include_meth = RUBY_VERSION >= '3.1' ? :import_methods : :include
|
|
@@ -40,9 +40,7 @@
|
|
|
40
40
|
|
|
41
41
|
module Sequel
|
|
42
42
|
module DuplicateColumnsHandler
|
|
43
|
-
|
|
44
|
-
CALLER_ARGS = (RUBY_VERSION >= '2.0' ? [0,1] : [0]).freeze
|
|
45
|
-
# simplecov:enable
|
|
43
|
+
CALLER_ARGS = [0,1].freeze
|
|
46
44
|
|
|
47
45
|
# Customize handling of duplicate columns for this dataset.
|
|
48
46
|
def on_duplicate_columns(handler = (raise Error, "Must provide either an argument or a block to on_duplicate_columns" unless defined?(yield); nil), &block)
|
|
@@ -63,6 +63,20 @@ module Sequel
|
|
|
63
63
|
class Error < Sequel::Error
|
|
64
64
|
end
|
|
65
65
|
|
|
66
|
+
module BooleanExpressionClassMethods
|
|
67
|
+
private
|
|
68
|
+
|
|
69
|
+
# Do not freeze literal strings in value pairs, so they don't skip
|
|
70
|
+
# the frozen checks.
|
|
71
|
+
def from_value_pair(l, r)
|
|
72
|
+
if LiteralString === r
|
|
73
|
+
new(:'=', l, r)
|
|
74
|
+
else
|
|
75
|
+
super
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
66
80
|
module DatabaseMethods
|
|
67
81
|
def self.extended(db)
|
|
68
82
|
db.extend_datasets(DatasetMethods)
|
|
@@ -105,7 +119,7 @@ module Sequel
|
|
|
105
119
|
def _check_unfrozen_literal_string(str)
|
|
106
120
|
return if !str.is_a?(String) || str.frozen?
|
|
107
121
|
|
|
108
|
-
if str.is_a?(LiteralString)
|
|
122
|
+
if str.is_a?(LiteralString) && str == str.source
|
|
109
123
|
_check_unfrozen_literal_string(str.source)
|
|
110
124
|
else
|
|
111
125
|
raise Error, "cannot treat unfrozen string as literal SQL: #{str.inspect}"
|
|
@@ -126,6 +140,8 @@ module Sequel
|
|
|
126
140
|
end
|
|
127
141
|
end
|
|
128
142
|
|
|
143
|
+
SQL::BooleanExpression.extend(LitRequireFrozen::BooleanExpressionClassMethods)
|
|
144
|
+
|
|
129
145
|
Dataset.register_extension(:lit_require_frozen, LitRequireFrozen::DatasetMethods)
|
|
130
146
|
Database.register_extension(:lit_require_frozen, LitRequireFrozen::DatabaseMethods)
|
|
131
147
|
end
|
|
@@ -69,7 +69,7 @@ module Sequel
|
|
|
69
69
|
|
|
70
70
|
if RUBY_VERSION >= '2.6'
|
|
71
71
|
# Whether Time.at with :nsec and :in is broken. True on JRuby < 9.3.9.0.
|
|
72
|
-
BROKEN_TIME_AT_WITH_NSEC = defined?(JRUBY_VERSION) && (JRUBY_VERSION < '9.3' || (JRUBY_VERSION < '9.4' && JRUBY_VERSION.split('.')[2].to_i < 9))
|
|
72
|
+
BROKEN_TIME_AT_WITH_NSEC = defined?(JRUBY_VERSION) && (JRUBY_VERSION.to_r < Rational('9.3') || (JRUBY_VERSION.to_r < Rational('9.4') && JRUBY_VERSION.split('.')[2].to_i < 9))
|
|
73
73
|
private_constant :BROKEN_TIME_AT_WITH_NSEC
|
|
74
74
|
|
|
75
75
|
# Convert the given input Time (which must be in UTC) to the given input timezone,
|
|
@@ -390,6 +390,7 @@ module Sequel
|
|
|
390
390
|
elsif char == '{'
|
|
391
391
|
raise Sequel::Error, "invalid array, opening brace with existing recorded data" unless @recorded.empty?
|
|
392
392
|
|
|
393
|
+
raise Sequel::Error, "cannot parse array with more than 6 dimensions" if @stack.length >= 6
|
|
393
394
|
# Start of new array, add it to the stack
|
|
394
395
|
new = []
|
|
395
396
|
@stack.last << new
|
|
@@ -984,7 +984,8 @@ module Sequel
|
|
|
984
984
|
comma = true
|
|
985
985
|
end
|
|
986
986
|
ds.literal_append(sql, v)
|
|
987
|
-
sql << " AS "
|
|
987
|
+
sql << " AS "
|
|
988
|
+
ds.send(:identifier_append, sql, k)
|
|
988
989
|
end
|
|
989
990
|
end
|
|
990
991
|
end
|
|
@@ -1254,7 +1255,8 @@ module Sequel
|
|
|
1254
1255
|
comma = true
|
|
1255
1256
|
end
|
|
1256
1257
|
ds.literal_append(sql, v)
|
|
1257
|
-
sql << " AS "
|
|
1258
|
+
sql << " AS "
|
|
1259
|
+
ds.send(:identifier_append, sql, k)
|
|
1258
1260
|
end
|
|
1259
1261
|
end
|
|
1260
1262
|
|
data/lib/sequel/extensions/s.rb
CHANGED
|
@@ -29,8 +29,7 @@
|
|
|
29
29
|
#
|
|
30
30
|
# Object.send(:include, Sequel::S)
|
|
31
31
|
#
|
|
32
|
-
#
|
|
33
|
-
# can use Sequel::S as a refinement, in which case the private #S method
|
|
32
|
+
# You can use also Sequel::S as a refinement, in which case the private #S method
|
|
34
33
|
# will be available on all objects while the refinement is active.
|
|
35
34
|
#
|
|
36
35
|
# using Sequel::S
|
|
@@ -39,7 +38,6 @@
|
|
|
39
38
|
#
|
|
40
39
|
# Related module: Sequel::S
|
|
41
40
|
|
|
42
|
-
|
|
43
41
|
#
|
|
44
42
|
module Sequel::S
|
|
45
43
|
private
|
|
@@ -50,11 +48,9 @@ module Sequel::S
|
|
|
50
48
|
end
|
|
51
49
|
|
|
52
50
|
# simplecov:disable
|
|
53
|
-
|
|
54
|
-
include_meth = RUBY_VERSION >= '3.1' ? :import_methods : :include
|
|
51
|
+
include_meth = RUBY_VERSION >= '3.1' ? :import_methods : :include
|
|
55
52
|
# simplecov:enable
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
end
|
|
53
|
+
refine Object do
|
|
54
|
+
send include_meth, Sequel::S
|
|
59
55
|
end
|
|
60
56
|
end
|
|
@@ -200,8 +200,12 @@ END_MIG
|
|
|
200
200
|
|
|
201
201
|
# Recreate the column in the passed Schema::CreateTableGenerator from the given name and parsed database schema.
|
|
202
202
|
def recreate_column(name, schema, gen, options)
|
|
203
|
+
db_type = schema[:db_type]
|
|
204
|
+
db_type = literal(db_type) if options[:same_db] && database_type == :sqlite
|
|
205
|
+
|
|
203
206
|
if options[:single_pk] && schema_autoincrementing_primary_key?(schema)
|
|
204
|
-
type_hash = options[:same_db] ? {:type=>
|
|
207
|
+
type_hash = options[:same_db] ? {:type=>db_type} : column_schema_to_ruby_type(schema)
|
|
208
|
+
|
|
205
209
|
[:table, :key, :on_delete, :on_update, :deferrable].each{|f| type_hash[f] = schema[f] if schema[f]}
|
|
206
210
|
if type_hash == {:type=>Integer} || type_hash == {:type=>"integer"} || type_hash == {:type=>"INTEGER"}
|
|
207
211
|
type_hash.delete(:type)
|
|
@@ -220,7 +224,7 @@ END_MIG
|
|
|
220
224
|
end
|
|
221
225
|
else
|
|
222
226
|
col_opts = if options[:same_db]
|
|
223
|
-
h = {:type=>
|
|
227
|
+
h = {:type=>db_type}
|
|
224
228
|
if database_type == :mysql && h[:type].start_with?("timestamp")
|
|
225
229
|
h[:null] = true
|
|
226
230
|
end
|
|
@@ -15,41 +15,21 @@
|
|
|
15
15
|
#
|
|
16
16
|
# Sequel.extension :symbol_aref
|
|
17
17
|
#
|
|
18
|
-
#
|
|
19
|
-
# is a refinement version of this in the symbol_aref_refinement extension.
|
|
18
|
+
# There is a refinement version of this in the symbol_aref_refinement extension.
|
|
20
19
|
#
|
|
21
20
|
# Related module: Sequel::SymbolAref
|
|
22
21
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
super
|
|
31
|
-
end
|
|
22
|
+
module Sequel::SymbolAref
|
|
23
|
+
def [](v)
|
|
24
|
+
case v
|
|
25
|
+
when Symbol, Sequel::SQL::Identifier, Sequel::SQL::QualifiedIdentifier
|
|
26
|
+
Sequel::SQL::QualifiedIdentifier.new(self, v)
|
|
27
|
+
else
|
|
28
|
+
super
|
|
32
29
|
end
|
|
33
30
|
end
|
|
31
|
+
end
|
|
34
32
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
end
|
|
38
|
-
# simplecov:disable
|
|
39
|
-
else
|
|
40
|
-
class Symbol
|
|
41
|
-
if method_defined?(:[])
|
|
42
|
-
alias_method :aref_before_sequel, :[]
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def [](v)
|
|
46
|
-
case v
|
|
47
|
-
when Symbol, Sequel::SQL::Identifier, Sequel::SQL::QualifiedIdentifier
|
|
48
|
-
Sequel::SQL::QualifiedIdentifier.new(self, v)
|
|
49
|
-
else
|
|
50
|
-
aref_before_sequel(v)
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
end
|
|
33
|
+
class Symbol
|
|
34
|
+
prepend Sequel::SymbolAref
|
|
54
35
|
end
|
|
55
|
-
# simplecov:enable
|
|
@@ -25,10 +25,7 @@
|
|
|
25
25
|
#
|
|
26
26
|
# Related module: Sequel::SymbolAref
|
|
27
27
|
|
|
28
|
-
#
|
|
29
|
-
raise(Sequel::Error, "Refinements require ruby 2.0.0 or greater") unless RUBY_VERSION >= '2.0.0'
|
|
30
|
-
# simplecov:enable
|
|
31
|
-
|
|
28
|
+
#
|
|
32
29
|
module Sequel::SymbolAref
|
|
33
30
|
refine Symbol do
|
|
34
31
|
def [](v)
|
|
@@ -14,8 +14,7 @@
|
|
|
14
14
|
#
|
|
15
15
|
# Sequel.extension :symbol_as
|
|
16
16
|
#
|
|
17
|
-
#
|
|
18
|
-
# is a refinement version of this in the symbol_as_refinement extension.
|
|
17
|
+
# There is a refinement version of this in the symbol_as_refinement extension.
|
|
19
18
|
|
|
20
19
|
#
|
|
21
20
|
class Symbol
|
|
@@ -23,10 +23,7 @@
|
|
|
23
23
|
#
|
|
24
24
|
# Related module: Sequel::SymbolAs
|
|
25
25
|
|
|
26
|
-
#
|
|
27
|
-
raise(Sequel::Error, "Refinements require ruby 2.0.0 or greater") unless RUBY_VERSION >= '2.0.0'
|
|
28
|
-
# simplecov:enable
|
|
29
|
-
|
|
26
|
+
#
|
|
30
27
|
module Sequel::SymbolAs
|
|
31
28
|
refine Symbol do
|
|
32
29
|
def as(aliaz, columns=nil)
|
|
@@ -34,4 +31,3 @@ module Sequel::SymbolAs
|
|
|
34
31
|
end
|
|
35
32
|
end
|
|
36
33
|
end
|
|
37
|
-
|
data/lib/sequel/model/base.rb
CHANGED
|
@@ -2433,12 +2433,7 @@ END
|
|
|
2433
2433
|
plugin self
|
|
2434
2434
|
def_initialize_nil_instance_variables
|
|
2435
2435
|
|
|
2436
|
-
singleton_class.send(:undef_method, :dup, :clone, :initialize_copy)
|
|
2437
|
-
# simplecov:disable
|
|
2438
|
-
if RUBY_VERSION >= '1.9.3'
|
|
2439
|
-
# simplecov:enable
|
|
2440
|
-
singleton_class.send(:undef_method, :initialize_clone, :initialize_dup)
|
|
2441
|
-
end
|
|
2436
|
+
singleton_class.send(:undef_method, :dup, :clone, :initialize_copy, :initialize_clone, :initialize_dup)
|
|
2442
2437
|
|
|
2443
2438
|
# simplecov:disable
|
|
2444
2439
|
if defined?(Sequel::Postgres::SEQUEL_PG_VERSION_INTEGER) && Sequel::Postgres::SEQUEL_PG_VERSION_INTEGER >= 11800
|
|
@@ -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
|
#
|
|
@@ -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)
|
|
@@ -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
|
-
# simplecov:disable
|
|
86
|
-
# :nodoc:
|
|
87
|
-
def self.csv_call(*args, opts, &block)
|
|
88
|
-
CSV.send(*args, opts, &block)
|
|
89
|
-
end
|
|
90
|
-
# :nodoc:
|
|
91
|
-
# simplecov:enable
|
|
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
|
|
@@ -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
|
|
@@ -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
|