sequel 5.51.0 → 5.52.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +28 -0
- data/README.rdoc +5 -0
- data/doc/opening_databases.rdoc +1 -1
- data/doc/release_notes/5.52.0.txt +87 -0
- data/doc/testing.rdoc +3 -1
- data/lib/sequel/adapters/amalgalite.rb +3 -5
- data/lib/sequel/adapters/jdbc.rb +7 -9
- data/lib/sequel/adapters/mysql.rb +80 -67
- data/lib/sequel/adapters/mysql2.rb +41 -43
- data/lib/sequel/adapters/postgres.rb +17 -21
- data/lib/sequel/adapters/shared/mysql.rb +3 -2
- data/lib/sequel/adapters/shared/postgres.rb +2 -2
- data/lib/sequel/adapters/sqlite.rb +16 -18
- data/lib/sequel/connection_pool/sharded_single.rb +5 -7
- data/lib/sequel/connection_pool/single.rb +6 -8
- data/lib/sequel/core.rb +17 -18
- data/lib/sequel/database/query.rb +1 -1
- data/lib/sequel/extensions/core_refinements.rb +36 -11
- data/lib/sequel/extensions/date_parse_input_handler.rb +67 -0
- data/lib/sequel/extensions/datetime_parse_to_time.rb +5 -1
- data/lib/sequel/extensions/pg_array_ops.rb +1 -1
- data/lib/sequel/extensions/pg_hstore_ops.rb +1 -1
- data/lib/sequel/extensions/pg_inet_ops.rb +1 -1
- data/lib/sequel/extensions/pg_interval.rb +1 -0
- data/lib/sequel/extensions/pg_json.rb +3 -5
- data/lib/sequel/extensions/pg_json_ops.rb +1 -1
- data/lib/sequel/extensions/pg_range_ops.rb +1 -1
- data/lib/sequel/extensions/pg_row_ops.rb +1 -1
- data/lib/sequel/extensions/s.rb +2 -1
- data/lib/sequel/extensions/server_block.rb +8 -12
- data/lib/sequel/extensions/sql_comments.rb +108 -3
- data/lib/sequel/extensions/string_date_time.rb +19 -23
- data/lib/sequel/model/base.rb +8 -12
- data/lib/sequel/plugins/sql_comments.rb +189 -0
- data/lib/sequel/plugins/subclasses.rb +28 -11
- data/lib/sequel/plugins/unused_associations.rb +2 -2
- data/lib/sequel/timezones.rb +12 -14
- data/lib/sequel/version.rb +1 -1
- metadata +7 -3
@@ -0,0 +1,189 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
module Sequel
|
4
|
+
module Plugins
|
5
|
+
# The sql_comments plugin will automatically use SQL comments on
|
6
|
+
# queries for the model it is loaded into. These comments will
|
7
|
+
# show the related model, what type of method was called, and
|
8
|
+
# the method name (or association name for queries to load
|
9
|
+
# associations):
|
10
|
+
#
|
11
|
+
# album = Album[1]
|
12
|
+
# # SELECT * FROM albums WHERE (id = 1) LIMIT 1
|
13
|
+
# # -- model:Album,method_type:class,method:[]
|
14
|
+
#
|
15
|
+
# album.update(:name=>'A')
|
16
|
+
# # UPDATE albums SET name = 'baz' WHERE (id = 1)
|
17
|
+
# # -- model:Album,method_type:instance,method:update
|
18
|
+
#
|
19
|
+
# album.artist
|
20
|
+
# # SELECT * FROM artists WHERE (artists.id = 1)
|
21
|
+
# # -- model:Album,method_type:association_load,association:artist
|
22
|
+
#
|
23
|
+
# Album.eager(:artists).all
|
24
|
+
# # SELECT * FROM albums
|
25
|
+
# # SELECT * FROM artists WHERE (artists.id IN (1))
|
26
|
+
# # -- model:Album,method_type:association_eager_load,association:artist
|
27
|
+
#
|
28
|
+
# Album.where(id: 1).delete
|
29
|
+
# # DELETE FROM albums WHERE (id = 1)
|
30
|
+
# # -- model:Album,method_type:dataset,method:delete
|
31
|
+
#
|
32
|
+
# This plugin automatically supports the class, instance, and dataset
|
33
|
+
# methods are are supported by default in Sequel::Model. To support
|
34
|
+
# custom class, instance, and dataset methods, such as those added by
|
35
|
+
# other plugins, you can use the appropriate <tt>sql_comments_*_methods</tt>
|
36
|
+
# class method:
|
37
|
+
#
|
38
|
+
# Album.sql_comments_class_methods :first_by_name # example from finder plugin, with :mod option
|
39
|
+
# Album.sql_comments_instance_methods :lazy_attribute_lookup # lazy_attributes plugin
|
40
|
+
# Album.sql_comments_dataset_methods :to_csv # csv_serializer plugin
|
41
|
+
#
|
42
|
+
# In order for the sql_comments plugin to work, the sql_comments
|
43
|
+
# Database extension must be loaded into the model's database.
|
44
|
+
#
|
45
|
+
# Note that in order to make sure SQL comments are included, some
|
46
|
+
# optimizations are disabled if this plugin is loaded.
|
47
|
+
#
|
48
|
+
# Usage:
|
49
|
+
#
|
50
|
+
# # Make all model subclasses support automatic SQL comments
|
51
|
+
# # (called before loading subclasses)
|
52
|
+
# Sequel::Model.plugin :sql_comments
|
53
|
+
#
|
54
|
+
# # Make the Album class support automatic SQL comments
|
55
|
+
# Album.plugin :sql_comments
|
56
|
+
module SqlComments
|
57
|
+
# Define a method +meth+ on the given module +mod+ that will use automatic
|
58
|
+
# SQL comments with the given model, method_type, and method.
|
59
|
+
def self.def_sql_commend_method(mod, model, method_type, meth)
|
60
|
+
mod.send(:define_method, meth) do |*a, &block|
|
61
|
+
model.db.with_comments(:model=>model, :method_type=>method_type, :method=>meth) do
|
62
|
+
super(*a, &block)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
# :nocov:
|
66
|
+
ruby2_keywords(meth) if respond_to?(:ruby2_keywords, false)
|
67
|
+
# :nocov:
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.configure(model)
|
71
|
+
model.send(:reset_fast_pk_lookup_sql)
|
72
|
+
end
|
73
|
+
|
74
|
+
module ClassMethods
|
75
|
+
# Use automatic SQL comments for the given class methods.
|
76
|
+
def sql_comments_class_methods(*meths)
|
77
|
+
_sql_comments_methods(singleton_class, :class, meths)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Use automatic SQL comments for the given instance methods.
|
81
|
+
def sql_comments_instance_methods(*meths)
|
82
|
+
_sql_comments_methods(self, :instance, meths)
|
83
|
+
end
|
84
|
+
|
85
|
+
# Use automatic SQL comments for the given dataset methods.
|
86
|
+
def sql_comments_dataset_methods(*meths)
|
87
|
+
unless @_sql_comments_dataset_module
|
88
|
+
dataset_module(@_sql_comments_dataset_module = Module.new)
|
89
|
+
end
|
90
|
+
_sql_comments_methods(@_sql_comments_dataset_module, :dataset, meths)
|
91
|
+
end
|
92
|
+
|
93
|
+
[:[], :create, :find, :find_or_create, :with_pk, :with_pk!].each do |meth|
|
94
|
+
define_method(meth) do |*a, &block|
|
95
|
+
db.with_comments(:model=>self, :method_type=>:class, :method=>meth) do
|
96
|
+
super(*a, &block)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
# :nocov:
|
100
|
+
ruby2_keywords(meth) if respond_to?(:ruby2_keywords, false)
|
101
|
+
# :nocov:
|
102
|
+
end
|
103
|
+
|
104
|
+
private
|
105
|
+
|
106
|
+
# Don't optimize the fast PK lookups, as it uses static SQL that
|
107
|
+
# won't support the SQL comments.
|
108
|
+
def reset_fast_pk_lookup_sql
|
109
|
+
@fast_pk_lookup_sql = @fast_instance_delete_sql = nil
|
110
|
+
end
|
111
|
+
|
112
|
+
# Define automatic SQL comment methods in +mod+ for each method in +meths+,
|
113
|
+
# with the given +method_type+.
|
114
|
+
def _sql_comments_methods(mod, method_type, meths)
|
115
|
+
meths.each do |meth|
|
116
|
+
SqlComments.def_sql_commend_method(mod, self, method_type, meth)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
module InstanceMethods
|
122
|
+
[:delete, :destroy, :lock!, :refresh, :save, :save_changes, :update, :update_fields].each do |meth|
|
123
|
+
define_method(meth) do |*a, &block|
|
124
|
+
t = Sequel.current
|
125
|
+
return super(*a, &block) if (hash = Sequel.synchronize{db.comment_hashes[t]}) && hash[:model]
|
126
|
+
|
127
|
+
db.with_comments(:model=>model, :method_type=>:instance, :method=>meth) do
|
128
|
+
super(*a, &block)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
# :nocov:
|
132
|
+
ruby2_keywords(meth) if respond_to?(:ruby2_keywords, false)
|
133
|
+
# :nocov:
|
134
|
+
end
|
135
|
+
|
136
|
+
private
|
137
|
+
|
138
|
+
# Do not use a placeholder loader for associations.
|
139
|
+
def _associated_object_loader(opts, dynamic_opts)
|
140
|
+
nil
|
141
|
+
end
|
142
|
+
|
143
|
+
# Use SQL comments on normal association load queries, showing they are association loads.
|
144
|
+
def _load_associated_objects(opts, dynamic_opts=OPTS)
|
145
|
+
db.with_comments(:model=>model, :method_type=>:association_load, :association=>opts[:name]) do
|
146
|
+
super
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
module DatasetMethods
|
152
|
+
Dataset::ACTION_METHODS.each do |meth|
|
153
|
+
define_method(meth) do |*a, &block|
|
154
|
+
t = Sequel.current
|
155
|
+
return super(*a, &block) if (hash = Sequel.synchronize{db.comment_hashes[t]}) && hash[:model]
|
156
|
+
|
157
|
+
db.with_comments(:model=>model, :method_type=>:dataset, :method=>meth) do
|
158
|
+
super(*a, &block)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
# :nocov:
|
162
|
+
ruby2_keywords(meth) if respond_to?(:ruby2_keywords, false)
|
163
|
+
# :nocov:
|
164
|
+
end
|
165
|
+
|
166
|
+
private
|
167
|
+
|
168
|
+
# Add the association name as part of the eager load data, so
|
169
|
+
# perform_eager_load has access to it.
|
170
|
+
def prepare_eager_load(a, reflections, eager_assoc)
|
171
|
+
res = super
|
172
|
+
|
173
|
+
reflections.each do |r|
|
174
|
+
res[r[:eager_loader]][:association] = r[:name]
|
175
|
+
end
|
176
|
+
|
177
|
+
res
|
178
|
+
end
|
179
|
+
|
180
|
+
# Use SQL comments on eager load queries, showing they are eager loads.
|
181
|
+
def perform_eager_load(loader, eo)
|
182
|
+
db.with_comments(:model=>model, :method_type=>:association_eager_load, :method=>nil, :association=>eo[:association]) do
|
183
|
+
super
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
@@ -5,7 +5,7 @@ module Sequel
|
|
5
5
|
# The subclasses plugin keeps track of all subclasses of the
|
6
6
|
# current model class. Direct subclasses are available via the
|
7
7
|
# subclasses method, and all descendent classes are available via the
|
8
|
-
#
|
8
|
+
# descendants method:
|
9
9
|
#
|
10
10
|
# c = Class.new(Sequel::Model)
|
11
11
|
# c.plugin :subclasses
|
@@ -16,7 +16,7 @@ module Sequel
|
|
16
16
|
# sc1.subclasses # [ssc1]
|
17
17
|
# sc2.subclasses # []
|
18
18
|
# ssc1.subclasses # []
|
19
|
-
# c.
|
19
|
+
# c.descendants # [sc1, ssc1, sc2]
|
20
20
|
#
|
21
21
|
# You can also finalize the associations and then freeze the classes
|
22
22
|
# in all descendent classes. Doing so is a recommended practice after
|
@@ -35,9 +35,14 @@ module Sequel
|
|
35
35
|
# class B < Sequel::Model; end
|
36
36
|
# a # => [A, B]
|
37
37
|
module Subclasses
|
38
|
+
NEED_SUBCLASSES = !Object.respond_to?(:subclasses)
|
39
|
+
private_constant :NEED_SUBCLASSES
|
40
|
+
|
38
41
|
# Initialize the subclasses instance variable for the model.
|
39
42
|
def self.apply(model, &block)
|
40
|
-
|
43
|
+
# :nocov:
|
44
|
+
model.instance_variable_set(:@subclasses, []) if NEED_SUBCLASSES
|
45
|
+
# :nocov:
|
41
46
|
model.instance_variable_set(:@on_subclass, block)
|
42
47
|
end
|
43
48
|
|
@@ -46,21 +51,31 @@ module Sequel
|
|
46
51
|
# class created.
|
47
52
|
attr_reader :on_subclass
|
48
53
|
|
49
|
-
#
|
50
|
-
|
51
|
-
|
54
|
+
# :nocov:
|
55
|
+
if NEED_SUBCLASSES
|
56
|
+
# All subclasses for the current model. Does not
|
57
|
+
# include the model itself.
|
58
|
+
attr_reader :subclasses
|
59
|
+
end
|
60
|
+
# :nocov:
|
52
61
|
|
53
62
|
# All descendent classes of this model.
|
54
|
-
def
|
55
|
-
Sequel.synchronize{subclasses.dup}.map{|x| [x] + x.send(:
|
63
|
+
def descendants
|
64
|
+
Sequel.synchronize{subclasses.dup}.map{|x| [x] + x.send(:descendants)}.flatten
|
56
65
|
end
|
57
66
|
|
67
|
+
# SEQUEL6: Remove
|
68
|
+
alias descendents descendants
|
69
|
+
|
58
70
|
# Freeze all descendent classes. This also finalizes the associations for those
|
59
71
|
# classes before freezing.
|
60
|
-
def
|
61
|
-
|
72
|
+
def freeze_descendants
|
73
|
+
descendants.each(&:finalize_associations).each(&:freeze)
|
62
74
|
end
|
63
75
|
|
76
|
+
# SEQUEL6: Remove
|
77
|
+
alias freeze_descendents freeze_descendants
|
78
|
+
|
64
79
|
Plugins.inherited_instance_variables(self, :@subclasses=>lambda{|v| []}, :@on_subclass=>nil)
|
65
80
|
|
66
81
|
private
|
@@ -70,7 +85,9 @@ module Sequel
|
|
70
85
|
# in the subclass.
|
71
86
|
def inherited(subclass)
|
72
87
|
super
|
73
|
-
|
88
|
+
# :nocov:
|
89
|
+
Sequel.synchronize{subclasses << subclass} if NEED_SUBCLASSES
|
90
|
+
# :nocov:
|
74
91
|
on_subclass.call(subclass) if on_subclass
|
75
92
|
end
|
76
93
|
end
|
@@ -313,7 +313,7 @@ module Sequel
|
|
313
313
|
{}
|
314
314
|
end
|
315
315
|
|
316
|
-
([self] +
|
316
|
+
([self] + descendants).each do |sc|
|
317
317
|
next if sc.associations.empty? || !sc.name
|
318
318
|
module_mapping[sc.send(:overridable_methods_module)] = sc
|
319
319
|
cov_data = coverage_data[sc.name] ||= {''=>[]}
|
@@ -348,7 +348,7 @@ module Sequel
|
|
348
348
|
|
349
349
|
unused_associations_data = {}
|
350
350
|
|
351
|
-
([self] +
|
351
|
+
([self] + descendants).each do |sc|
|
352
352
|
next unless cov_data = coverage_data[sc.name]
|
353
353
|
reflection_data = cov_data[''] || []
|
354
354
|
|
data/lib/sequel/timezones.rb
CHANGED
@@ -82,22 +82,20 @@ module Sequel
|
|
82
82
|
# +application_timezone+ using +convert_input_timestamp+ and
|
83
83
|
# +convert_output_timestamp+.
|
84
84
|
def convert_timestamp(v, input_timezone)
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
DateTime.civil(v.year, v.month, v.day, 0, 0, 0, application_timezone == :local ? Rational(Time.local(v.year, v.month, v.day).utc_offset, 86400) : 0)
|
90
|
-
else
|
91
|
-
Time.public_send(application_timezone == :utc ? :utc : :local, v.year, v.month, v.day)
|
92
|
-
end
|
85
|
+
if v.is_a?(Date) && !v.is_a?(DateTime)
|
86
|
+
# Dates handled specially as they are assumed to already be in the application_timezone
|
87
|
+
if datetime_class == DateTime
|
88
|
+
DateTime.civil(v.year, v.month, v.day, 0, 0, 0, application_timezone == :local ? Rational(Time.local(v.year, v.month, v.day).utc_offset, 86400) : 0)
|
93
89
|
else
|
94
|
-
|
90
|
+
Time.public_send(application_timezone == :utc ? :utc : :local, v.year, v.month, v.day)
|
95
91
|
end
|
96
|
-
|
97
|
-
|
98
|
-
rescue => e
|
99
|
-
raise convert_exception_class(e, InvalidValue)
|
92
|
+
else
|
93
|
+
convert_output_timestamp(convert_input_timestamp(v, input_timezone), application_timezone)
|
100
94
|
end
|
95
|
+
rescue InvalidValue
|
96
|
+
raise
|
97
|
+
rescue => e
|
98
|
+
raise convert_exception_class(e, InvalidValue)
|
101
99
|
end
|
102
100
|
|
103
101
|
# Convert the given object into an object of <tt>Sequel.datetime_class</tt> in the
|
@@ -158,7 +156,7 @@ module Sequel
|
|
158
156
|
case v
|
159
157
|
when String
|
160
158
|
v2 = Sequel.string_to_datetime(v)
|
161
|
-
if !input_timezone ||
|
159
|
+
if !input_timezone || _date_parse(v).has_key?(:offset)
|
162
160
|
v2
|
163
161
|
else
|
164
162
|
# Correct for potentially wrong offset if string doesn't include offset
|
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 = 52
|
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.52.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:
|
11
|
+
date: 2022-01-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|
@@ -196,6 +196,7 @@ extra_rdoc_files:
|
|
196
196
|
- doc/release_notes/5.5.0.txt
|
197
197
|
- doc/release_notes/5.50.0.txt
|
198
198
|
- doc/release_notes/5.51.0.txt
|
199
|
+
- doc/release_notes/5.52.0.txt
|
199
200
|
- doc/release_notes/5.6.0.txt
|
200
201
|
- doc/release_notes/5.7.0.txt
|
201
202
|
- doc/release_notes/5.8.0.txt
|
@@ -275,6 +276,7 @@ files:
|
|
275
276
|
- doc/release_notes/5.5.0.txt
|
276
277
|
- doc/release_notes/5.50.0.txt
|
277
278
|
- doc/release_notes/5.51.0.txt
|
279
|
+
- doc/release_notes/5.52.0.txt
|
278
280
|
- doc/release_notes/5.6.0.txt
|
279
281
|
- doc/release_notes/5.7.0.txt
|
280
282
|
- doc/release_notes/5.8.0.txt
|
@@ -387,6 +389,7 @@ files:
|
|
387
389
|
- lib/sequel/extensions/current_datetime_timestamp.rb
|
388
390
|
- lib/sequel/extensions/dataset_source_alias.rb
|
389
391
|
- lib/sequel/extensions/date_arithmetic.rb
|
392
|
+
- lib/sequel/extensions/date_parse_input_handler.rb
|
390
393
|
- lib/sequel/extensions/datetime_parse_to_time.rb
|
391
394
|
- lib/sequel/extensions/duplicate_columns_handler.rb
|
392
395
|
- lib/sequel/extensions/empty_array_consider_nulls.rb
|
@@ -530,6 +533,7 @@ files:
|
|
530
533
|
- lib/sequel/plugins/skip_create_refresh.rb
|
531
534
|
- lib/sequel/plugins/skip_saving_columns.rb
|
532
535
|
- lib/sequel/plugins/split_values.rb
|
536
|
+
- lib/sequel/plugins/sql_comments.rb
|
533
537
|
- lib/sequel/plugins/static_cache.rb
|
534
538
|
- lib/sequel/plugins/static_cache_cache.rb
|
535
539
|
- lib/sequel/plugins/string_stripper.rb
|
@@ -588,7 +592,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
588
592
|
- !ruby/object:Gem::Version
|
589
593
|
version: '0'
|
590
594
|
requirements: []
|
591
|
-
rubygems_version: 3.
|
595
|
+
rubygems_version: 3.3.3
|
592
596
|
signing_key:
|
593
597
|
specification_version: 4
|
594
598
|
summary: The Database Toolkit for Ruby
|