sequel 5.63.0 → 5.65.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: abbe367cded9066a40aee5dd911a9b915f580264d00e6b668fad956bb94e38ef
4
- data.tar.gz: 40ab8f35b0129177b550469f5ce9b6b6fccbcc97bdcfb3b06a2d8528bca37432
3
+ metadata.gz: 24bfe7c123337539140b0385dd9a828fe0fec4d6ad4e39e5fd8f150258ae7a03
4
+ data.tar.gz: d820be46e60ba7b08b1129f0a6b67a24a550a27d5b682a84730172bc256f4118
5
5
  SHA512:
6
- metadata.gz: 87a17fc09f790b81df75fb7d170f851c9607a0f45abf6fc50c21f50243e418362fe7c804521bfe06a12e32656e234c7e79469d40d365436edad0a2e9c176a335
7
- data.tar.gz: ee366f061a808d7983c2996dd969f834b74815e2a1ed77410f0bdc32f822dad72dee3c48a9ad22b6f77d791d8dc43de8bc0b4619929ac5870976495774959a7b
6
+ metadata.gz: bd5c7dacdf48f8ada7c34c88210ac804faa1b47741f946ca16cd6f645c1f86055eb85ac6b601e9cef2ab4aa8a5cba3dc444e3005d6ed61d324c1158f2e03a70e
7
+ data.tar.gz: d17eb580a3f50f4b0c33561aed320c2ea3089044b905f4dc845ea8682afe1cdbf2798c6cd202f1233b1d168d06c9686a94728d41e0f47264245a33da5a99b251
data/CHANGELOG CHANGED
@@ -1,3 +1,21 @@
1
+ === 5.65.0 (2023-02-01)
2
+
3
+ * Allow pg_auto_parameterize extension to use placeholder loaders (jeremyevans)
4
+
5
+ * Do not include :min_value and :max_value schema entries for decimal/numeric columns on MySQL versions not supporting check constraints (jeremyevans)
6
+
7
+ * Make Database#indexes return indexes for partitioned tables on PostgreSQL 11+ (jeremyevans)
8
+
9
+ === 5.64.0 (2023-01-01)
10
+
11
+ * Make :db_type column schema entries on SQLAnywhere include precision/scale information (jeremyevans)
12
+
13
+ * Include :min_value and :max_value schema entries for decimal/numeric columns on most databases (rolftimmermans, jeremyevans) (#1975)
14
+
15
+ * Support :graph_use_association_block association option to make eager_graph use the association block (jeremyevans)
16
+
17
+ * Make many_through_many and many_through_one associations support eager_graph callbacks (jeremyevans)
18
+
1
19
  === 5.63.0 (2022-12-01)
2
20
 
3
21
  * Make validates_associated plugin avoid database type errors for non-integer association keys (jeremyevans) (#1968)
data/MIT-LICENSE CHANGED
@@ -1,5 +1,5 @@
1
1
  Copyright (c) 2007-2008 Sharon Rosner
2
- Copyright (c) 2008-2022 Jeremy Evans
2
+ Copyright (c) 2008-2023 Jeremy Evans
3
3
 
4
4
  Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  of this software and associated documentation files (the "Software"), to
@@ -864,14 +864,14 @@ You can set this to +nil+ to not create a remove_all_<i>association</i> method.
864
864
 
865
865
  === :no_dataset_method
866
866
 
867
- Setting this to true will not result in the <i>association</i>_dataset method
867
+ Setting this to true will result in the <i>association</i>_dataset method
868
868
  not being defined. This can save memory if you only use the <i>association</i>
869
869
  method and do not call the <i>association</i>_dataset method directly or
870
870
  indirectly.
871
871
 
872
872
  === :no_association_method
873
873
 
874
- Setting this to true will not result in the <i>association</i> method
874
+ Setting this to true will result in the <i>association</i> method
875
875
  not being defined. This can save memory if you only use the
876
876
  <i>association</i>_dataset method and do not call the <i>association</i> method
877
877
  directly or indirectly.
@@ -1498,6 +1498,36 @@ as the qualifiers may not match the aliases automatically used by eager_graph.
1498
1498
  This should contain unqualified identifiers, and eager_graph will automatically
1499
1499
  qualify them with the appropriate alias.
1500
1500
 
1501
+ ==== :graph_use_association_block
1502
+
1503
+ Setting this to true makes eager_graph apply the association block to the
1504
+ associated dataset before graphing the associated dataset into the receiver.
1505
+ In most cases when this option is used and the association has a block, the
1506
+ dataset returned by eager_graph will contain a JOIN to a subquery.
1507
+
1508
+ By default (when this option is not used), the association block will be ignored
1509
+ when using eager_graph:
1510
+
1511
+ Artist.one_to_many :tracks do |ds|
1512
+ ds.where(foo: 3)
1513
+ end
1514
+ Artist.eager_graph(:tracks)
1515
+ # SELECT albums.id, tracks.id AS tracks_id, tracks.album_id
1516
+ # FROM albums
1517
+ # LEFT OUTER JOIN tracks
1518
+ # ON (tracks.album_id = albums.id)
1519
+
1520
+ When this option is used, the block will be respected:
1521
+
1522
+ Artist.one_to_many :tracks, graph_use_association_block: true do |ds|
1523
+ ds.where(foo: 3)
1524
+ end
1525
+ Artist.eager_graph(:tracks)
1526
+ # SELECT albums.id, tracks.id AS tracks_id, tracks.album_id
1527
+ # FROM albums
1528
+ # LEFT OUTER JOIN (SELECT * FROM tracks WHERE (foo = 3)) AS tracks
1529
+ # ON (tracks.album_id = albums.id)
1530
+
1501
1531
  ==== :graph_join_table_conditions [+many_to_many+, +one_through_one+]
1502
1532
 
1503
1533
  The additional conditions to use on the SQL join for the join table when
@@ -0,0 +1,50 @@
1
+ = New Features
2
+
3
+ * A :graph_use_association_block association option has been added,
4
+ which makes eager_graph use the association block (as eager does),
5
+ generally resulting in a JOIN to a subquery:
6
+
7
+ Artist.one_to_many :tracks, graph_use_association_block: true do |ds|
8
+ ds.where(foo: 3)
9
+ end
10
+ Artist.eager_graph(:tracks)
11
+ # SELECT albums.id, tracks.id AS tracks_id, tracks.album_id
12
+ # FROM albums
13
+ # LEFT OUTER JOIN (SELECT * FROM tracks WHERE (foo = 3)) AS tracks
14
+ # ON (tracks.album_id = albums.id)
15
+
16
+ Assuming that the database can optimize the query correctly, using
17
+ the :graph_use_association_block option is probably simpler than
18
+ than using other :graph_* options to duplicate the conditions added
19
+ by the association block.
20
+
21
+ * Numeric/Decimal column schema entries now include :min_value and
22
+ :max_value entries on most databases, indicating the minimum and
23
+ maximum values supported for the column. Similar to the support
24
+ for integer columns added in 5.62.0, this allows the
25
+ auto_validations plugin to automatically validate the values of
26
+ the columns are in the allowed range.
27
+
28
+ = Other Improvements
29
+
30
+ * many_through_{one,many} associations now support eager_graph
31
+ callbacks.
32
+
33
+ * The :db_type column schema entries on SQLAnywhere now include
34
+ precision/scale information, to work with the numeric/decimal
35
+ column min_value/max_value support.
36
+
37
+ * The oracle adapter now includes a :column_size column schema
38
+ entry containing the precision of the columns, to work with the
39
+ numeric/decimal column min_value/max_value support.
40
+
41
+ = Backwards Compatibility
42
+
43
+ * The private Database#column_schema_integer_min_max_values method
44
+ added in 5.62.0 now takes a column schema hash instead of a
45
+ database type string.
46
+
47
+ * Code that previously looked at the :db_type column schema entry on
48
+ SQLAnywhere should be updated to look at the :domain_name entry, and
49
+ code that looked at the :domain_name_with_size entry should be
50
+ updated to look at the :db_type entry.
@@ -0,0 +1,21 @@
1
+ = Improvements
2
+
3
+ * The pg_auto_parameterize extension now uses a modified placeholder
4
+ literalizer for speeding up the generation of SQL queries in the same
5
+ cases where a standard dataset would use a placeholder literalizer.
6
+ This can provide a 4% speedup for simple queries, with greater
7
+ speedups for more complex queries.
8
+
9
+ * Database#indexes now returns indexes for partitioned tables on
10
+ PostgreSQL 11+.
11
+
12
+ * MySQL versions not supporting CHECK constraints no longer include
13
+ :min_value/:max_value schema entries for decimal/numeric columns.
14
+
15
+ = Backwards Compatibility
16
+
17
+ * The Dataset::PlaceholderLiterlizer::Record.loader API has changed,
18
+ it now accepts the Dataset::PlaceholderLiterlizer class to use as
19
+ the first argument. This makes it easier to create
20
+ Dataset::PlaceholderLiterlizer subclasses, such as the one now used
21
+ by the pg_auto_parameterize extension.
data/doc/sql.rdoc CHANGED
@@ -59,7 +59,7 @@ Then, you call the +insert+, +update+, or +delete+ method on the returned datase
59
59
  update_ds.update
60
60
  delete_ds.delete
61
61
 
62
- +update+ and +delete+ should return the number of rows affected, and +insert+ should return the autogenerated primary key integer for the row inserted (if any).
62
+ +update+ and +delete+ generally return the number of rows affected, and +insert+ generally returns the autogenerated primary key integer for the row inserted (if any), but not all adapters/databases support this behavior for datasets using custom SQL (notably it is not supported for +insert+ on PostgreSQL).
63
63
 
64
64
  === Other Queries
65
65
 
@@ -312,6 +312,7 @@ module Sequel
312
312
  :char_used => column.char_used?,
313
313
  :char_size => column.char_size,
314
314
  :data_size => column.data_size,
315
+ :column_size => column.precision,
315
316
  :precision => column.precision,
316
317
  :scale => column.scale,
317
318
  :fsprecision => column.fsprecision,
@@ -60,8 +60,8 @@ module Sequel
60
60
  # Access's Byte type will accept much larger values,
61
61
  # even though it only stores 0-255. Do not set min/max
62
62
  # values for the Byte type.
63
- def column_schema_integer_min_max_values(db_type)
64
- return if /byte/i =~ db_type
63
+ def column_schema_integer_min_max_values(column)
64
+ return if /byte/i =~ column[:db_type]
65
65
  super
66
66
  end
67
67
 
@@ -553,7 +553,14 @@ module Sequel
553
553
  # Return nil if CHECK constraints are not supported, because
554
554
  # versions that don't support check constraints don't raise
555
555
  # errors for values outside of range.
556
- def column_schema_integer_min_max_values(db_type)
556
+ def column_schema_integer_min_max_values(column)
557
+ super if supports_check_constraints?
558
+ end
559
+
560
+ # Return nil if CHECK constraints are not supported, because
561
+ # versions that don't support check constraints don't raise
562
+ # errors for values outside of range.
563
+ def column_schema_decimal_min_max_values(column)
557
564
  super if supports_check_constraints?
558
565
  end
559
566
 
@@ -178,11 +178,11 @@ module Sequel
178
178
  ''
179
179
  end
180
180
 
181
- # Do not support min/max integer values on Oracle, since
182
- # Oracle uses a number type, and integer just adds a
183
- # constaint on the number type.
184
- def column_schema_integer_min_max_values(db_type)
185
- nil
181
+ # Support min/max integer values on Oracle only if
182
+ # they use a NUMBER column with a fixed precision
183
+ # and no scale.
184
+ def column_schema_integer_min_max_values(column)
185
+ super if column[:db_type] =~ /NUMBER\(\d+\)/i || (column[:db_type] == 'NUMBER' && column[:column_size].is_a?(Integer) && column[:scale] == 0)
186
186
  end
187
187
 
188
188
  def create_sequence_sql(name, opts=OPTS)
@@ -919,7 +919,7 @@ module Sequel
919
919
  join(Sequel[:pg_attribute].as(:att), :attrelid=>Sequel[:tab][:oid], :attnum=>attnums).
920
920
  left_join(Sequel[:pg_constraint].as(:con), :conname=>Sequel[:indc][:relname]).
921
921
  where{{
922
- indc[:relkind]=>'i',
922
+ indc[:relkind]=>%w'i I',
923
923
  ind[:indisprimary]=>false,
924
924
  :indexprs=>nil,
925
925
  :indisvalid=>true}}.
@@ -37,7 +37,7 @@ module Sequel
37
37
  row[:auto_increment] = auto_increment == 1 || auto_increment == true
38
38
  row[:primary_key] = row.delete(:pkey) == 'Y'
39
39
  row[:allow_null] = row[:nulls_allowed].is_a?(Integer) ? row.delete(:nulls_allowed) == 1 : row.delete(:nulls_allowed)
40
- row[:db_type] = row.delete(:domain_name)
40
+ row[:db_type] = row.delete(:domain_name_with_size)
41
41
  row[:type] = if row[:db_type] =~ /numeric/i and (row[:scale].is_a?(Integer) ? row[:scale] == 0 : !row[:scale])
42
42
  :integer
43
43
  else
@@ -320,10 +320,11 @@ module Sequel
320
320
  end
321
321
  end
322
322
 
323
- # SQLite does not restrict the integer type to a specific range.
324
- def column_schema_integer_min_max_values(db_type)
323
+ # SQLite does not restrict the integer or decimal type to a specific range.
324
+ def column_schema_integer_min_max_values(column)
325
325
  nil
326
326
  end
327
+ alias column_schema_decimal_min_max_values column_schema_integer_min_max_values
327
328
 
328
329
  # Array of PRAGMA SQL statements based on the Database options that should be applied to
329
330
  # new connections.
@@ -175,8 +175,14 @@ module Sequel
175
175
  if !c[:max_length] && c[:type] == :string && (max_length = column_schema_max_length(c[:db_type]))
176
176
  c[:max_length] = max_length
177
177
  end
178
- if !c[:max_value] && !c[:min_value] && c[:type] == :integer && (min_max = column_schema_integer_min_max_values(c[:db_type]))
179
- c[:min_value], c[:max_value] = min_max
178
+ if !c[:max_value] && !c[:min_value]
179
+ min_max = case c[:type]
180
+ when :integer
181
+ column_schema_integer_min_max_values(c)
182
+ when :decimal
183
+ column_schema_decimal_min_max_values(c)
184
+ end
185
+ c[:min_value], c[:max_value] = min_max if min_max
180
186
  end
181
187
  end
182
188
  schema_post_process(cols)
@@ -288,7 +294,15 @@ module Sequel
288
294
 
289
295
  # Look at the db_type and guess the minimum and maximum integer values for
290
296
  # the column.
291
- def column_schema_integer_min_max_values(db_type)
297
+ def column_schema_integer_min_max_values(column)
298
+ db_type = column[:db_type]
299
+ if /decimal|numeric|number/i =~ db_type
300
+ if min_max = column_schema_decimal_min_max_values(column)
301
+ min_max.map!(&:to_i)
302
+ end
303
+ return min_max
304
+ end
305
+
292
306
  unsigned = /unsigned/i =~ db_type
293
307
  case db_type
294
308
  when /big|int8/i
@@ -304,6 +318,26 @@ module Sequel
304
318
  end
305
319
  end
306
320
 
321
+ # Look at the db_type and guess the minimum and maximum decimal values for
322
+ # the column.
323
+ def column_schema_decimal_min_max_values(column)
324
+ if column[:column_size] && column[:scale]
325
+ precision = column[:column_size]
326
+ scale = column[:scale]
327
+ elsif /\((\d+)(?:,\s*(-?\d+))?\)/ =~ column[:db_type]
328
+ precision = $1.to_i
329
+ scale = $2.to_i if $2
330
+ end
331
+
332
+ if precision
333
+ limit = BigDecimal("9" * precision)
334
+ if scale
335
+ limit /= 10**(scale)
336
+ end
337
+ [-limit, limit]
338
+ end
339
+ end
340
+
307
341
  # Whether the tinyint type (if supported by the database) is unsigned by default.
308
342
  def column_schema_tinyint_type_is_unsigned?
309
343
  false
@@ -370,7 +404,7 @@ module Sequel
370
404
  :boolean
371
405
  when /\A(real|float( unsigned)?|double( precision)?|double\(\d+,\d+\)( unsigned)?)\z/io
372
406
  :float
373
- when /\A(?:(?:(?:num(?:ber|eric)?|decimal)(?:\(\d+,\s*(\d+|false|true)\))?))\z/io
407
+ when /\A(?:(?:(?:num(?:ber|eric)?|decimal)(?:\(\d+,\s*(-?\d+|false|true)\))?))\z/io
374
408
  $1 && ['0', 'false'].include?($1) ? :integer : :decimal
375
409
  when /bytea|blob|image|(var)?binary/io
376
410
  :blob
@@ -158,6 +158,16 @@ module Sequel
158
158
  !!((opts[:from].is_a?(Array) && opts[:from].size > 1) || opts[:join])
159
159
  end
160
160
 
161
+ # The class to use for placeholder literalizers for the current dataset.
162
+ def placeholder_literalizer_class
163
+ ::Sequel::Dataset::PlaceholderLiteralizer
164
+ end
165
+
166
+ # A placeholder literalizer loader for the current dataset.
167
+ def placeholder_literalizer_loader(&block)
168
+ placeholder_literalizer_class.loader(self, &block)
169
+ end
170
+
161
171
  # The alias to use for the row_number column, used when emulating OFFSET
162
172
  # support and for eager limit strategies
163
173
  def row_number_column
@@ -296,7 +306,7 @@ module Sequel
296
306
  loader += 1
297
307
 
298
308
  if loader >= 3
299
- loader = Sequel::Dataset::PlaceholderLiteralizer.loader(self){|pl, _| yield pl}
309
+ loader = placeholder_literalizer_loader{|pl, _| yield pl}
300
310
  cache_set(key, loader)
301
311
  else
302
312
  cache_set(key, loader + 1)
@@ -77,8 +77,8 @@ module Sequel
77
77
  # Yields the receiver and the dataset to the block, which should
78
78
  # call #arg on the receiver for each placeholder argument, and
79
79
  # return the dataset that you want to load.
80
- def loader(dataset, &block)
81
- PlaceholderLiteralizer.new(*process(dataset, &block))
80
+ def loader(pl, dataset, &block)
81
+ pl.new(*process(dataset, &block))
82
82
  end
83
83
 
84
84
  # Return an Argument with the specified position, or the next position. In
@@ -145,7 +145,7 @@ module Sequel
145
145
  # given block, recording the offsets at which the recorders arguments
146
146
  # are used in the query.
147
147
  def self.loader(dataset, &block)
148
- Recorder.new.loader(dataset, &block)
148
+ Recorder.new.loader(self, dataset, &block)
149
149
  end
150
150
 
151
151
  # Save the dataset, array of SQL fragments, and ending SQL string.
@@ -199,20 +199,31 @@ module Sequel
199
199
  # Return the SQL query to use for the given arguments.
200
200
  def sql(*args)
201
201
  raise Error, "wrong number of arguments (#{args.length} for #{@arity})" unless args.length == @arity
202
- s = String.new
202
+ s = sql_origin
203
+ append_sql(s, *args)
204
+ end
205
+
206
+ # Append the SQL query to use for the given arguments to the given SQL string.
207
+ def append_sql(sql, *args)
203
208
  ds = @dataset
204
- @fragments.each do |sql, i, transformer|
205
- s << sql
209
+ @fragments.each do |s, i, transformer|
210
+ sql << s
206
211
  if i.is_a?(Integer)
207
212
  v = args.fetch(i)
208
213
  v = transformer.call(v) if transformer
209
214
  else
210
215
  v = i.call
211
216
  end
212
- ds.literal_append(s, v)
217
+ ds.literal_append(sql, v)
213
218
  end
214
- s << @final_sql
215
- s
219
+ sql << @final_sql
220
+ sql
221
+ end
222
+
223
+ private
224
+
225
+ def sql_origin
226
+ String.new
216
227
  end
217
228
  end
218
229
  end
@@ -148,7 +148,10 @@ module Sequel
148
148
 
149
149
  # Freeze the stored arguments when freezing the query string.
150
150
  def freeze
151
- @args.freeze if @args
151
+ if @args
152
+ @args.freeze
153
+ @arg_map.freeze
154
+ end
152
155
  super
153
156
  end
154
157
 
@@ -156,6 +159,14 @@ module Sequel
156
159
  def inspect
157
160
  @args ? "#{self}; #{@args.inspect}".inspect : super
158
161
  end
162
+
163
+ def initialize_copy(other)
164
+ super
165
+ if args = other.instance_variable_get(:@args)
166
+ @args = args.dup
167
+ @arg_map = other.instance_variable_get(:@arg_map).dup
168
+ end
169
+ end
159
170
  end
160
171
 
161
172
  # Wrapper class that skips auto parameterization for the wrapped object.
@@ -169,6 +180,22 @@ module Sequel
169
180
  end
170
181
  end
171
182
 
183
+ # PlacholderLiteralizer subclass with support for stored auto parameters.
184
+ class PlaceholderLiteralizer < ::Sequel::Dataset::PlaceholderLiteralizer
185
+ def initialize(dataset, fragments, final_sql, arity)
186
+ s = dataset.sql.dup
187
+ s.clear
188
+ @sql_origin = s.freeze
189
+ super
190
+ end
191
+
192
+ private
193
+
194
+ def sql_origin
195
+ @sql_origin.dup
196
+ end
197
+ end
198
+
172
199
  module DatabaseMethods
173
200
  def self.extended(db)
174
201
  unless (db.adapter_scheme == :postgres && USES_PG) || (db.adapter_scheme == :mock && db.database_type == :postgres)
@@ -282,9 +309,13 @@ module Sequel
282
309
  end
283
310
  end
284
311
 
285
- # Placeholder literalizers are not supported supported when using automatic parameterization.
286
- def supports_placeholder_literalizer?
287
- @opts[:no_auto_parameterize]
312
+ # The class to use for placeholder literalizers.
313
+ def placeholder_literalizer_class
314
+ if @opts[:no_auto_parameterize]
315
+ super
316
+ else
317
+ PlaceholderLiteralizer
318
+ end
288
319
  end
289
320
 
290
321
  # Disable automatic parameterization when using a cursor.
@@ -310,7 +310,17 @@ module Sequel
310
310
  loader = union_eager_loader
311
311
  joiner = " UNION ALL "
312
312
  ids.each_slice(subqueries_per_union).each do |slice|
313
- objects.concat(ds.with_sql(slice.map{|k| loader.sql(*k)}.join(joiner)).to_a)
313
+ sql = loader.send(:sql_origin)
314
+ join = false
315
+ slice.each do |k|
316
+ if join
317
+ sql << joiner
318
+ else
319
+ join = true
320
+ end
321
+ loader.append_sql(sql, *k)
322
+ end
323
+ objects.concat(ds.with_sql(sql).to_a)
314
324
  end
315
325
  ds = ds.eager(cascade) if cascade
316
326
  ds.send(:post_load, objects)
@@ -446,7 +456,7 @@ module Sequel
446
456
  def placeholder_loader
447
457
  if use_placeholder_loader?
448
458
  cached_fetch(:placeholder_loader) do
449
- Sequel::Dataset::PlaceholderLiteralizer.loader(associated_dataset) do |pl, ds|
459
+ associated_dataset.placeholder_literalizer_loader do |pl, ds|
450
460
  ds = ds.where(Sequel.&(*predicate_keys.map{|k| SQL::BooleanExpression.new(:'=', k, pl.arg)}))
451
461
  if self[:block]
452
462
  ds = self[:block].call(ds)
@@ -748,8 +758,8 @@ module Sequel
748
758
  # A placeholder literalizer used to speed up eager loading.
749
759
  def placeholder_eager_loader
750
760
  cached_fetch(:placeholder_eager_loader) do
751
- Sequel::Dataset::PlaceholderLiteralizer.loader(associated_dataset) do |pl, ds|
752
- apply_eager_limit_strategy(eager_loading_dataset.where(predicate_key=>pl.arg), eager_limit_strategy)
761
+ eager_loading_dataset.placeholder_literalizer_loader do |pl, ds|
762
+ apply_eager_limit_strategy(ds.where(predicate_key=>pl.arg), eager_limit_strategy)
753
763
  end
754
764
  end
755
765
  end
@@ -808,7 +818,7 @@ module Sequel
808
818
  # loading a limited association.
809
819
  def union_eager_loader
810
820
  cached_fetch(:union_eager_loader) do
811
- Sequel::Dataset::PlaceholderLiteralizer.loader(associated_dataset) do |pl, ds|
821
+ associated_dataset.placeholder_literalizer_loader do |pl, ds|
812
822
  ds = self[:eager_block].call(ds) if self[:eager_block]
813
823
  keys = predicate_keys
814
824
  ds = ds.where(keys.map{pl.arg}.zip(keys))
@@ -1722,6 +1732,8 @@ module Sequel
1722
1732
  # :graph_select :: A column or array of columns to select from the associated table
1723
1733
  # when eagerly loading the association via +eager_graph+. Defaults to all
1724
1734
  # columns in the associated table.
1735
+ # :graph_use_association_block :: Makes eager_graph consider the association block. Without this, eager_graph
1736
+ # ignores the bock and only use the :graph_* options.
1725
1737
  # :instance_specific :: Marks the association as instance specific. Should be used if the association block
1726
1738
  # uses instance specific state, or transient state (accessing current date/time, etc.).
1727
1739
  # :limit :: Limit the number of records to the provided value. Use
@@ -2461,6 +2473,9 @@ module Sequel
2461
2473
  # Return dataset to graph into given the association reflection, applying the :callback option if set.
2462
2474
  def eager_graph_dataset(opts, eager_options)
2463
2475
  ds = opts.associated_class.dataset
2476
+ if opts[:graph_use_association_block] && (b = opts[:block])
2477
+ ds = b.call(ds)
2478
+ end
2464
2479
  if cb = eager_options[:callback]
2465
2480
  ds = cb.call(ds)
2466
2481
  end
@@ -151,7 +151,7 @@ module Sequel
151
151
  ds
152
152
  end
153
153
 
154
- Sequel::Dataset::PlaceholderLiteralizer.loader(model, &block)
154
+ model.dataset.placeholder_literalizer_class.loader(model, &block)
155
155
  end
156
156
  end
157
157
 
@@ -385,7 +385,7 @@ module Sequel
385
385
  iq = nil
386
386
  end
387
387
  fe = opts.final_edge
388
- ds.graph(opts.associated_class.dataset, use_only_conditions ? only_conditions : (Array(opts.right_primary_key).zip(Array(fe[:left])) + conditions), :select=>select, :table_alias=>eo[:table_alias], :qualify=>:deep, :join_type=>eo[:join_type]||join_type, :join_only=>eo[:join_only], &graph_block)
388
+ ds.graph(eager_graph_dataset(opts, eo), use_only_conditions ? only_conditions : (Array(opts.right_primary_key).zip(Array(fe[:left])) + conditions), :select=>select, :table_alias=>eo[:table_alias], :qualify=>:deep, :join_type=>eo[:join_type]||join_type, :join_only=>eo[:join_only], &graph_block)
389
389
  end
390
390
  end
391
391
  end
@@ -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 = 63
9
+ MINOR = 65
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.63.0
4
+ version: 5.65.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Evans
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-12-01 00:00:00.000000000 Z
11
+ date: 2023-02-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -195,6 +195,8 @@ extra_rdoc_files:
195
195
  - doc/release_notes/5.61.0.txt
196
196
  - doc/release_notes/5.62.0.txt
197
197
  - doc/release_notes/5.63.0.txt
198
+ - doc/release_notes/5.64.0.txt
199
+ - doc/release_notes/5.65.0.txt
198
200
  - doc/release_notes/5.7.0.txt
199
201
  - doc/release_notes/5.8.0.txt
200
202
  - doc/release_notes/5.9.0.txt
@@ -286,6 +288,8 @@ files:
286
288
  - doc/release_notes/5.61.0.txt
287
289
  - doc/release_notes/5.62.0.txt
288
290
  - doc/release_notes/5.63.0.txt
291
+ - doc/release_notes/5.64.0.txt
292
+ - doc/release_notes/5.65.0.txt
289
293
  - doc/release_notes/5.7.0.txt
290
294
  - doc/release_notes/5.8.0.txt
291
295
  - doc/release_notes/5.9.0.txt
@@ -609,7 +613,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
609
613
  - !ruby/object:Gem::Version
610
614
  version: '0'
611
615
  requirements: []
612
- rubygems_version: 3.3.26
616
+ rubygems_version: 3.4.1
613
617
  signing_key:
614
618
  specification_version: 4
615
619
  summary: The Database Toolkit for Ruby