sequel 5.33.0 → 5.35.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/CHANGELOG +42 -0
- data/doc/association_basics.rdoc +7 -2
- data/doc/dataset_filtering.rdoc +2 -2
- data/doc/release_notes/5.34.0.txt +40 -0
- data/doc/release_notes/5.35.0.txt +56 -0
- data/lib/sequel/adapters/oracle.rb +2 -1
- data/lib/sequel/adapters/shared/sqlite.rb +8 -2
- data/lib/sequel/adapters/tinytds.rb +1 -0
- data/lib/sequel/connection_pool/sharded_single.rb +4 -1
- data/lib/sequel/connection_pool/sharded_threaded.rb +10 -10
- data/lib/sequel/connection_pool/single.rb +1 -1
- data/lib/sequel/connection_pool/threaded.rb +1 -1
- data/lib/sequel/database/connecting.rb +1 -1
- data/lib/sequel/database/misc.rb +16 -10
- data/lib/sequel/database/query.rb +2 -0
- data/lib/sequel/database/schema_generator.rb +0 -1
- data/lib/sequel/database/schema_methods.rb +15 -16
- data/lib/sequel/database/transactions.rb +7 -4
- data/lib/sequel/dataset/placeholder_literalizer.rb +3 -7
- data/lib/sequel/dataset/query.rb +5 -4
- data/lib/sequel/deprecated.rb +3 -1
- data/lib/sequel/exceptions.rb +2 -0
- data/lib/sequel/extensions/_pretty_table.rb +1 -2
- data/lib/sequel/extensions/columns_introspection.rb +1 -2
- data/lib/sequel/extensions/core_refinements.rb +2 -0
- data/lib/sequel/extensions/duplicate_columns_handler.rb +2 -0
- data/lib/sequel/extensions/migration.rb +0 -1
- data/lib/sequel/extensions/pg_array_ops.rb +4 -0
- data/lib/sequel/extensions/pg_enum.rb +2 -0
- data/lib/sequel/extensions/pg_extended_date_support.rb +1 -1
- data/lib/sequel/extensions/pg_hstore_ops.rb +2 -0
- data/lib/sequel/extensions/pg_inet.rb +2 -0
- data/lib/sequel/extensions/pg_json_ops.rb +2 -0
- data/lib/sequel/extensions/pg_range.rb +3 -7
- data/lib/sequel/extensions/pg_range_ops.rb +2 -0
- data/lib/sequel/extensions/pg_row.rb +0 -1
- data/lib/sequel/extensions/run_transaction_hooks.rb +1 -1
- data/lib/sequel/extensions/s.rb +2 -0
- data/lib/sequel/extensions/symbol_aref_refinement.rb +2 -0
- data/lib/sequel/extensions/symbol_as_refinement.rb +2 -0
- data/lib/sequel/extensions/to_dot.rb +9 -3
- data/lib/sequel/model.rb +2 -0
- data/lib/sequel/model/associations.rb +36 -20
- data/lib/sequel/model/base.rb +11 -5
- data/lib/sequel/model/plugins.rb +2 -3
- data/lib/sequel/plugins/association_pks.rb +60 -18
- data/lib/sequel/plugins/blacklist_security.rb +1 -2
- data/lib/sequel/plugins/class_table_inheritance.rb +3 -3
- data/lib/sequel/plugins/csv_serializer.rb +2 -0
- data/lib/sequel/plugins/forbid_lazy_load.rb +2 -0
- data/lib/sequel/plugins/instance_specific_default.rb +113 -0
- data/lib/sequel/plugins/lazy_attributes.rb +1 -1
- data/lib/sequel/plugins/pg_array_associations.rb +2 -3
- data/lib/sequel/plugins/prepared_statements.rb +5 -11
- data/lib/sequel/plugins/prepared_statements_safe.rb +1 -3
- data/lib/sequel/plugins/rcte_tree.rb +10 -16
- data/lib/sequel/plugins/string_stripper.rb +1 -1
- data/lib/sequel/plugins/validation_class_methods.rb +5 -1
- data/lib/sequel/version.rb +1 -1
- metadata +7 -2
@@ -114,10 +114,8 @@ module Sequel
|
|
114
114
|
prepared_sql << sql
|
115
115
|
prepared_sql << "$#{prepared_args[i]}"
|
116
116
|
end
|
117
|
-
|
118
|
-
|
119
|
-
prepared_sql << final_sql
|
120
|
-
end
|
117
|
+
frags << final_sql
|
118
|
+
prepared_sql << final_sql
|
121
119
|
|
122
120
|
[prepared_sql, frags]
|
123
121
|
end
|
@@ -213,9 +211,7 @@ module Sequel
|
|
213
211
|
end
|
214
212
|
ds.literal_append(s, v)
|
215
213
|
end
|
216
|
-
|
217
|
-
s << sql
|
218
|
-
end
|
214
|
+
s << @final_sql
|
219
215
|
s
|
220
216
|
end
|
221
217
|
end
|
data/lib/sequel/dataset/query.rb
CHANGED
@@ -81,7 +81,7 @@ module Sequel
|
|
81
81
|
# If the options changed include options in COLUMN_CHANGE_OPTS, the cached
|
82
82
|
# columns are deleted. This method should generally not be called
|
83
83
|
# directly by user code.
|
84
|
-
def clone(opts = (return self
|
84
|
+
def clone(opts = nil || (return self))
|
85
85
|
# return self used above because clone is called by almost all
|
86
86
|
# other query methods, and it is the fastest approach
|
87
87
|
c = super(:freeze=>false)
|
@@ -330,16 +330,17 @@ module Sequel
|
|
330
330
|
# # SELECT * FROM a WHERE ((a LIKE '%foo%' ESCAPE '\') AND (b LIKE '%foo%' ESCAPE '\')
|
331
331
|
# # AND (a LIKE '%bar%' ESCAPE '\') AND (b LIKE '%bar%' ESCAPE '\'))
|
332
332
|
def grep(columns, patterns, opts=OPTS)
|
333
|
+
column_op = opts[:all_columns] ? :AND : :OR
|
333
334
|
if opts[:all_patterns]
|
334
335
|
conds = Array(patterns).map do |pat|
|
335
|
-
SQL::BooleanExpression.new(
|
336
|
+
SQL::BooleanExpression.new(column_op, *Array(columns).map{|c| SQL::StringExpression.like(c, pat, opts)})
|
336
337
|
end
|
337
|
-
where(SQL::BooleanExpression.new(
|
338
|
+
where(SQL::BooleanExpression.new(:AND, *conds))
|
338
339
|
else
|
339
340
|
conds = Array(columns).map do |c|
|
340
341
|
SQL::BooleanExpression.new(:OR, *Array(patterns).map{|pat| SQL::StringExpression.like(c, pat, opts)})
|
341
342
|
end
|
342
|
-
where(SQL::BooleanExpression.new(
|
343
|
+
where(SQL::BooleanExpression.new(column_op, *conds))
|
343
344
|
end
|
344
345
|
end
|
345
346
|
|
data/lib/sequel/deprecated.rb
CHANGED
@@ -39,7 +39,7 @@ module Sequel
|
|
39
39
|
# Print the message and possibly backtrace to the output.
|
40
40
|
def self.deprecate(method, instead=nil)
|
41
41
|
return unless output
|
42
|
-
message = instead ? "#{method} is deprecated and will be removed in Sequel
|
42
|
+
message = instead ? "#{method} is deprecated and will be removed in Sequel 6. #{instead}." : method
|
43
43
|
message = "#{prefix}#{message}" if prefix
|
44
44
|
output.puts(message)
|
45
45
|
case b = backtrace_filter
|
@@ -60,7 +60,9 @@ module Sequel
|
|
60
60
|
# If using ruby 2.3+, use Module#deprecate_constant to deprecate the constant,
|
61
61
|
# otherwise do nothing as the ruby implementation does not support constant deprecation.
|
62
62
|
def self.deprecate_constant(mod, constant)
|
63
|
+
# :nocov:
|
63
64
|
if RUBY_VERSION > '2.3'
|
65
|
+
# :nocov:
|
64
66
|
mod.deprecate_constant(constant)
|
65
67
|
end
|
66
68
|
end
|
data/lib/sequel/exceptions.rb
CHANGED
@@ -75,8 +75,7 @@ module Sequel
|
|
75
75
|
when SQL::Identifier
|
76
76
|
c.value.to_sym
|
77
77
|
when SQL::QualifiedIdentifier
|
78
|
-
|
79
|
-
col.is_a?(SQL::Identifier) ? col.value.to_sym : col.to_sym
|
78
|
+
c.column.to_sym
|
80
79
|
when SQL::AliasedExpression
|
81
80
|
a = c.alias
|
82
81
|
a.is_a?(SQL::Identifier) ? a.value.to_sym : a.to_sym
|
@@ -39,7 +39,9 @@
|
|
39
39
|
|
40
40
|
module Sequel
|
41
41
|
module DuplicateColumnsHandler
|
42
|
+
# :nocov:
|
42
43
|
CALLER_ARGS = (RUBY_VERSION >= '2.0' ? [0,1] : [0]).freeze
|
44
|
+
# :nocov:
|
43
45
|
|
44
46
|
# Customize handling of duplicate columns for this dataset.
|
45
47
|
def on_duplicate_columns(handler = (raise Error, "Must provide either an argument or a block to on_duplicate_columns" unless block_given?; nil), &block)
|
@@ -518,7 +518,6 @@ module Sequel
|
|
518
518
|
def initialize(db, directory, opts=OPTS)
|
519
519
|
super
|
520
520
|
@current = opts[:current] || current_migration_version
|
521
|
-
raise(Error, "No current version available") unless current
|
522
521
|
|
523
522
|
latest_version = latest_migration_version
|
524
523
|
@target = if opts[:target]
|
@@ -157,7 +157,9 @@ module Sequel
|
|
157
157
|
else
|
158
158
|
Sequel.function(:hstore, self, wrap_array(arg))
|
159
159
|
end
|
160
|
+
# :nocov:
|
160
161
|
if Sequel.respond_to?(:hstore_op)
|
162
|
+
# :nocov:
|
161
163
|
v = Sequel.hstore_op(v)
|
162
164
|
end
|
163
165
|
v
|
@@ -283,7 +285,9 @@ module Sequel
|
|
283
285
|
end
|
284
286
|
end
|
285
287
|
|
288
|
+
# :nocov:
|
286
289
|
if defined?(PGArray)
|
290
|
+
# :nocov:
|
287
291
|
class PGArray
|
288
292
|
# Wrap the PGArray instance in an ArrayOp, allowing you to easily use
|
289
293
|
# the PostgreSQL array functions and operators with literal arrays.
|
@@ -189,7 +189,7 @@ module Sequel
|
|
189
189
|
if date < DATETIME_YEAR_1
|
190
190
|
date <<= ((date.year) * 24 - 12)
|
191
191
|
date = db.from_application_timestamp(date)
|
192
|
-
minutes = (date.
|
192
|
+
minutes = (date.offset * 1440).to_i
|
193
193
|
date.strftime("'%Y-%m-%d %H:%M:%S.%N#{format_timestamp_offset(*minutes.divmod(60))} BC'")
|
194
194
|
else
|
195
195
|
super
|
@@ -41,7 +41,9 @@ module Sequel
|
|
41
41
|
db.instance_exec do
|
42
42
|
extend_datasets(InetDatasetMethods)
|
43
43
|
|
44
|
+
# :nocov:
|
44
45
|
if !defined?(SEQUEL_PG_VERSION_INTEGER) || SEQUEL_PG_VERSION_INTEGER >= 11300
|
46
|
+
# :nocov:
|
45
47
|
# sequel_pg 1.13.0+ will use inet/cidr conversion procs, but doing so is
|
46
48
|
# slower, so don't add the conversion procs if using sequel_pg 1.13.0+.
|
47
49
|
meth = IPAddr.method(:new)
|
@@ -554,7 +554,9 @@ module Sequel
|
|
554
554
|
end
|
555
555
|
end
|
556
556
|
|
557
|
+
# :nocov:
|
557
558
|
if defined?(JSONArray)
|
559
|
+
# :nocov:
|
558
560
|
class JSONArray
|
559
561
|
# Wrap the JSONArray instance in an JSONOp, allowing you to easily use
|
560
562
|
# the PostgreSQL json functions and operators with literal jsons.
|
@@ -158,7 +158,7 @@ module Sequel
|
|
158
158
|
procs = conversion_procs
|
159
159
|
add_conversion_proc(3908, Parser.new("tsrange", procs[1114]))
|
160
160
|
add_conversion_proc(3910, Parser.new("tstzrange", procs[1184]))
|
161
|
-
if defined?(PGArray::Creator)
|
161
|
+
if respond_to?(:register_array_type) && defined?(PGArray::Creator)
|
162
162
|
add_conversion_proc(3909, PGArray::Creator.new("tsrange", procs[3908]))
|
163
163
|
add_conversion_proc(3911, PGArray::Creator.new("tstzrange", procs[3910]))
|
164
164
|
end
|
@@ -215,12 +215,6 @@ module Sequel
|
|
215
215
|
|
216
216
|
db_type = db_type.to_s.dup.freeze
|
217
217
|
|
218
|
-
if converter = opts[:converter]
|
219
|
-
raise Error, "can't provide both a block and :converter option to register" if block
|
220
|
-
else
|
221
|
-
converter = block
|
222
|
-
end
|
223
|
-
|
224
218
|
if soid
|
225
219
|
raise Error, "can't provide both a converter and :subtype_oid option to register" if has_converter
|
226
220
|
raise Error, "no conversion proc for :subtype_oid=>#{soid.inspect} in conversion_procs" unless converter = conversion_procs[soid]
|
@@ -471,8 +465,10 @@ module Sequel
|
|
471
465
|
return @range if @range
|
472
466
|
raise(Error, "cannot create ruby range for an empty PostgreSQL range") if empty?
|
473
467
|
raise(Error, "cannot create ruby range when PostgreSQL range excludes beginning element") if exclude_begin?
|
468
|
+
# :nocov:
|
474
469
|
raise(Error, "cannot create ruby range when PostgreSQL range has unbounded beginning") if STARTLESS_RANGE_NOT_SUPPORTED && !self.begin
|
475
470
|
raise(Error, "cannot create ruby range when PostgreSQL range has unbounded ending") if ENDLESS_RANGE_NOT_SUPPORTED && !self.end
|
471
|
+
# :nocov:
|
476
472
|
@range = Range.new(self.begin, self.end, exclude_end?)
|
477
473
|
end
|
478
474
|
|
@@ -116,7 +116,9 @@ module Sequel
|
|
116
116
|
end
|
117
117
|
end
|
118
118
|
|
119
|
+
# :nocov:
|
119
120
|
if defined?(PGRange)
|
121
|
+
# :nocov:
|
120
122
|
class PGRange
|
121
123
|
# Wrap the PGRange instance in an RangeOp, allowing you to easily use
|
122
124
|
# the PostgreSQL range functions and operators with literal ranges.
|
@@ -48,7 +48,7 @@ class Sequel::Database
|
|
48
48
|
def _run_transaction_hooks(type, opts)
|
49
49
|
synchronize(opts[:server]) do |conn|
|
50
50
|
unless h = _trans(conn)
|
51
|
-
raise Error, "Cannot call run_#{type}_hooks outside of a transaction"
|
51
|
+
raise Sequel::Error, "Cannot call run_#{type}_hooks outside of a transaction"
|
52
52
|
end
|
53
53
|
|
54
54
|
if hooks = h[type]
|
data/lib/sequel/extensions/s.rb
CHANGED
@@ -53,7 +53,13 @@ module Sequel
|
|
53
53
|
# is given, it is used directly as the node or transition. Otherwise
|
54
54
|
# a node is created for the current object.
|
55
55
|
def dot(label, j=nil)
|
56
|
-
|
56
|
+
label = case label
|
57
|
+
when nil
|
58
|
+
"<nil>"
|
59
|
+
else
|
60
|
+
label.to_s
|
61
|
+
end
|
62
|
+
@dot << "#{j||@i} [label=#{label.inspect}];"
|
57
63
|
end
|
58
64
|
|
59
65
|
# Recursive method that parses all of Sequel's internal datastructures,
|
@@ -61,7 +67,7 @@ module Sequel
|
|
61
67
|
# structure.
|
62
68
|
def v(e, l)
|
63
69
|
@i += 1
|
64
|
-
dot(l, "#{@stack.last} -> #{@i}")
|
70
|
+
dot(l, "#{@stack.last} -> #{@i}")
|
65
71
|
@stack.push(@i)
|
66
72
|
case e
|
67
73
|
when LiteralString
|
@@ -144,7 +150,7 @@ module Sequel
|
|
144
150
|
dot "Dataset"
|
145
151
|
TO_DOT_OPTIONS.each do |k|
|
146
152
|
if val = e.opts[k]
|
147
|
-
v(val, k
|
153
|
+
v(val, k)
|
148
154
|
end
|
149
155
|
end
|
150
156
|
else
|
data/lib/sequel/model.rb
CHANGED
@@ -69,7 +69,9 @@ module Sequel
|
|
69
69
|
require_relative "model/base"
|
70
70
|
require_relative "model/exceptions"
|
71
71
|
require_relative "model/errors"
|
72
|
+
# :nocov:
|
72
73
|
if !defined?(::SEQUEL_NO_ASSOCIATIONS) && !ENV.has_key?('SEQUEL_NO_ASSOCIATIONS')
|
74
|
+
# :nocov:
|
73
75
|
require_relative 'model/associations'
|
74
76
|
plugin Model::Associations
|
75
77
|
end
|
@@ -164,11 +164,11 @@ module Sequel
|
|
164
164
|
# range to return the object(s) at the correct offset/limit.
|
165
165
|
def apply_ruby_eager_limit_strategy(rows, limit_and_offset = limit_and_offset())
|
166
166
|
name = self[:name]
|
167
|
+
return unless range = slice_range(limit_and_offset)
|
167
168
|
if returns_array?
|
168
|
-
range = slice_range(limit_and_offset)
|
169
169
|
rows.each{|o| o.associations[name] = o.associations[name][range] || []}
|
170
|
-
|
171
|
-
offset =
|
170
|
+
else
|
171
|
+
offset = range.begin
|
172
172
|
rows.each{|o| o.associations[name] = o.associations[name][offset]}
|
173
173
|
end
|
174
174
|
end
|
@@ -356,7 +356,7 @@ module Sequel
|
|
356
356
|
def finalize
|
357
357
|
return unless cache = self[:cache]
|
358
358
|
|
359
|
-
|
359
|
+
finalizer = proc do |meth, key|
|
360
360
|
next if has_key?(key)
|
361
361
|
|
362
362
|
# Allow calling private methods to make sure caching is done appropriately
|
@@ -364,6 +364,13 @@ module Sequel
|
|
364
364
|
self[key] = cache.delete(key) if cache.has_key?(key)
|
365
365
|
end
|
366
366
|
|
367
|
+
finalize_settings.each(&finalizer)
|
368
|
+
|
369
|
+
unless self[:instance_specific]
|
370
|
+
finalizer.call(:associated_eager_dataset, :associated_eager_dataset)
|
371
|
+
finalizer.call(:filter_by_associations_conditions_dataset, :filter_by_associations_conditions_dataset)
|
372
|
+
end
|
373
|
+
|
367
374
|
nil
|
368
375
|
end
|
369
376
|
|
@@ -371,9 +378,7 @@ module Sequel
|
|
371
378
|
FINALIZE_SETTINGS = {
|
372
379
|
:associated_class=>:class,
|
373
380
|
:associated_dataset=>:_dataset,
|
374
|
-
:associated_eager_dataset=>:associated_eager_dataset,
|
375
381
|
:eager_limit_strategy=>:_eager_limit_strategy,
|
376
|
-
:filter_by_associations_conditions_dataset=>:filter_by_associations_conditions_dataset,
|
377
382
|
:placeholder_loader=>:placeholder_loader,
|
378
383
|
:predicate_key=>:predicate_key,
|
379
384
|
:predicate_keys=>:predicate_keys,
|
@@ -432,7 +437,11 @@ module Sequel
|
|
432
437
|
if use_placeholder_loader?
|
433
438
|
cached_fetch(:placeholder_loader) do
|
434
439
|
Sequel::Dataset::PlaceholderLiteralizer.loader(associated_dataset) do |pl, ds|
|
435
|
-
ds.where(Sequel.&(*predicate_keys.map{|k| SQL::BooleanExpression.new(:'=', k, pl.arg)}))
|
440
|
+
ds = ds.where(Sequel.&(*predicate_keys.map{|k| SQL::BooleanExpression.new(:'=', k, pl.arg)}))
|
441
|
+
if self[:block]
|
442
|
+
ds = self[:block].call(ds)
|
443
|
+
end
|
444
|
+
ds
|
436
445
|
end
|
437
446
|
end
|
438
447
|
end
|
@@ -796,7 +805,7 @@ module Sequel
|
|
796
805
|
|
797
806
|
# Whether the placeholder loader can be used to load the association.
|
798
807
|
def use_placeholder_loader?
|
799
|
-
|
808
|
+
self[:use_placeholder_loader]
|
800
809
|
end
|
801
810
|
end
|
802
811
|
|
@@ -1244,7 +1253,9 @@ module Sequel
|
|
1244
1253
|
else
|
1245
1254
|
assoc_record.values.delete(left_key_alias)
|
1246
1255
|
end
|
1247
|
-
|
1256
|
+
|
1257
|
+
objects = h[hash_key]
|
1258
|
+
|
1248
1259
|
if assign_singular
|
1249
1260
|
objects.each do |object|
|
1250
1261
|
object.associations[name] ||= assoc_record
|
@@ -1791,11 +1802,12 @@ module Sequel
|
|
1791
1802
|
opts.merge!(:type => type, :name => name, :cache=>({} if cache_associations), :model => self)
|
1792
1803
|
|
1793
1804
|
opts[:block] = block if block
|
1794
|
-
|
1805
|
+
opts[:instance_specific] = true if orig_opts[:dataset]
|
1806
|
+
if !opts.has_key?(:instance_specific) && (block || orig_opts[:block])
|
1795
1807
|
# It's possible the association is instance specific, in that it depends on
|
1796
1808
|
# values other than the foreign key value. This needs to be checked for
|
1797
1809
|
# in certain places to disable optimizations.
|
1798
|
-
opts[:instance_specific] =
|
1810
|
+
opts[:instance_specific] = _association_instance_specific_default(name)
|
1799
1811
|
end
|
1800
1812
|
opts = assoc_class.new.merge!(opts)
|
1801
1813
|
|
@@ -1803,6 +1815,7 @@ module Sequel
|
|
1803
1815
|
raise(Error, "cannot clone an association to an association of different type (association #{name} with type #{type} cloning #{opts[:clone]} with type #{cloned_assoc[:type]})")
|
1804
1816
|
end
|
1805
1817
|
|
1818
|
+
opts[:use_placeholder_loader] = !opts[:instance_specific] && !opts[:eager_graph]
|
1806
1819
|
opts[:eager_block] = opts[:block] unless opts.include?(:eager_block)
|
1807
1820
|
opts[:graph_join_type] ||= :left_outer
|
1808
1821
|
opts[:order_eager_graph] = true unless opts.include?(:order_eager_graph)
|
@@ -1899,6 +1912,12 @@ module Sequel
|
|
1899
1912
|
Plugins.def_dataset_methods(self, [:eager, :eager_graph, :eager_graph_with_options, :association_join, :association_full_join, :association_inner_join, :association_left_join, :association_right_join])
|
1900
1913
|
|
1901
1914
|
private
|
1915
|
+
|
1916
|
+
# The default value for the instance_specific option, if the association
|
1917
|
+
# could be instance specific and the :instance_specific option is not specified.
|
1918
|
+
def _association_instance_specific_default(_)
|
1919
|
+
true
|
1920
|
+
end
|
1902
1921
|
|
1903
1922
|
# The module to use for the association's methods. Defaults to
|
1904
1923
|
# the overridable_methods_module.
|
@@ -1948,10 +1967,8 @@ module Sequel
|
|
1948
1967
|
if opts[:block]
|
1949
1968
|
opts[:block_method] = Plugins.def_sequel_method(association_module(opts), "#{opts[:name]}_block", 1, &opts[:block])
|
1950
1969
|
end
|
1951
|
-
|
1952
|
-
|
1953
|
-
opts[:dataset_opt_method] = Plugins.def_sequel_method(association_module(opts), "#{opts[:name]}_dataset_opt", opts[:dataset_opt_arity], &opts[:dataset])
|
1954
|
-
end
|
1970
|
+
opts[:dataset_opt_arity] = opts[:dataset].arity == 0 ? 0 : 1
|
1971
|
+
opts[:dataset_opt_method] = Plugins.def_sequel_method(association_module(opts), "#{opts[:name]}_dataset_opt", opts[:dataset_opt_arity], &opts[:dataset])
|
1955
1972
|
def_association_method(opts)
|
1956
1973
|
|
1957
1974
|
return if opts[:read_only]
|
@@ -2122,9 +2139,7 @@ module Sequel
|
|
2122
2139
|
|
2123
2140
|
eager_load_results(opts, eo) do |assoc_record|
|
2124
2141
|
hash_key = uses_cks ? pk_meths.map{|k| assoc_record.get_column_value(k)} : assoc_record.get_column_value(opts.primary_key_method)
|
2125
|
-
|
2126
|
-
objects.each{|object| object.associations[name] = assoc_record}
|
2127
|
-
end
|
2142
|
+
h[hash_key].each{|object| object.associations[name] = assoc_record}
|
2128
2143
|
end
|
2129
2144
|
end
|
2130
2145
|
|
@@ -2171,7 +2186,7 @@ module Sequel
|
|
2171
2186
|
eager_load_results(opts, eo) do |assoc_record|
|
2172
2187
|
assoc_record.values.delete(delete_rn) if delete_rn
|
2173
2188
|
hash_key = uses_cks ? km.map{|k| assoc_record.get_column_value(k)} : assoc_record.get_column_value(km)
|
2174
|
-
|
2189
|
+
objects = h[hash_key]
|
2175
2190
|
if assign_singular
|
2176
2191
|
objects.each do |object|
|
2177
2192
|
unless object.associations[name]
|
@@ -3064,6 +3079,8 @@ module Sequel
|
|
3064
3079
|
# significantly slower in some cases (perhaps even the majority of cases), so you should
|
3065
3080
|
# only use this if you have benchmarked that it is faster for your use cases.
|
3066
3081
|
def eager_graph_with_options(associations, opts=OPTS)
|
3082
|
+
return self if associations.empty?
|
3083
|
+
|
3067
3084
|
opts = opts.dup unless opts.frozen?
|
3068
3085
|
associations = [associations] unless associations.is_a?(Array)
|
3069
3086
|
ds = if eg = @opts[:eager_graph]
|
@@ -3190,7 +3207,6 @@ module Sequel
|
|
3190
3207
|
# requirements :: an array, used as a stack for requirements
|
3191
3208
|
# *associations :: the associations to add to the graph
|
3192
3209
|
def eager_graph_associations(ds, model, ta, requirements, *associations)
|
3193
|
-
return ds if associations.empty?
|
3194
3210
|
associations.flatten.each do |association|
|
3195
3211
|
ds = case association
|
3196
3212
|
when Symbol, SQL::AliasedExpression
|