class Sequel::Dataset::PlaceholderLiteralizer

PlaceholderLiteralizer allows you to record the application of arbitrary changes to a dataset with placeholder arguments, recording where those placeholder arguments are used in the query. When running the query, the literalization process is much faster as Sequel can skip most of the work it normally has to do when literalizing a dataset.

Basically, this enables optimizations that allow Sequel to cache the SQL produced for a given dataset, so that it doesn’t need to recompute that information every time.

Example:

loader = Sequel::Dataset::PlaceholderLiteralizer.loader(DB[:items]) do |pl, ds|
  ds.where(id: pl.arg).exclude(name: pl.arg).limit(1)
end
loader.first(1, "foo")
# SELECT * FROM items WHERE ((id = 1) AND (name != 'foo')) LIMIT 1
loader.first(2, "bar")
# SELECT * FROM items WHERE ((id = 2) AND (name != 'bar')) LIMIT 1

Caveats:

Note that this method does not handle all possible cases. For example:

loader = Sequel::Dataset::PlaceholderLiteralizer.loader(DB[:items]) do |pl, ds|
  ds.join(pl.arg, item_id: :id)
end
loader.all(:cart_items)

Will not qualify the item_id column with cart_items. In this type of situation it’s best to add a table alias when joining:

loader = Sequel::Dataset::PlaceholderLiteralizer.loader(DB[:items]) do |pl, ds|
  ds.join(Sequel.as(pl.arg, :t), item_id: :id)
end
loader.all(:cart_items)

There are other similar cases that are not handled, mainly when Sequel changes the SQL produced depending on the types of the arguments.

Public Class Methods

loader(dataset, &block) click to toggle source

Create a PlaceholderLiteralizer by yielding a Recorder and dataset to the given block, recording the offsets at which the recorders arguments are used in the query.

    # File lib/sequel/dataset/placeholder_literalizer.rb
147 def self.loader(dataset, &block)
148   Recorder.new.loader(self, dataset, &block)
149 end
new(dataset, fragments, final_sql, arity) click to toggle source

Save the dataset, array of SQL fragments, and ending SQL string.

    # File lib/sequel/dataset/placeholder_literalizer.rb
152 def initialize(dataset, fragments, final_sql, arity)
153   @dataset = dataset
154   @fragments = fragments
155   @final_sql = final_sql
156   @arity = arity
157   freeze
158 end

Public Instance Methods

all(*args, &block) click to toggle source

Return an array of all objects by running the SQL query for the given arguments. If a block is given, yields all objects to the block after loading them.

    # File lib/sequel/dataset/placeholder_literalizer.rb
179 def all(*args, &block)
180   @dataset.with_sql_all(sql(*args), &block)
181 end
append_sql(sql, *args) click to toggle source

Append the SQL query to use for the given arguments to the given SQL string.

    # File lib/sequel/dataset/placeholder_literalizer.rb
207 def append_sql(sql, *args)
208   ds = @dataset
209   @fragments.each do |s, i, transformer|
210     sql << s
211     if i.is_a?(Integer)
212       v = args.fetch(i)
213       v = transformer.call(v) if transformer
214     else
215       v = i.call
216     end
217     ds.literal_append(sql, v)
218   end
219   sql << @final_sql
220   sql
221 end
each(*args, &block) click to toggle source

Run the SQL query for the given arguments, yielding each returned row to the block.

    # File lib/sequel/dataset/placeholder_literalizer.rb
184 def each(*args, &block)
185   @dataset.with_sql_each(sql(*args), &block)
186 end
first(*args) click to toggle source

Run the SQL query for the given arguments, returning the first row.

    # File lib/sequel/dataset/placeholder_literalizer.rb
189 def first(*args)
190   @dataset.with_sql_first(sql(*args))
191 end
freeze() click to toggle source

Freeze the fragments and final SQL when freezing the literalizer.

Calls superclass method
    # File lib/sequel/dataset/placeholder_literalizer.rb
161 def freeze
162   @fragments.freeze
163   @final_sql.freeze
164   super
165 end
get(*args) click to toggle source

Run the SQL query for the given arguments, returning the first value. For this to make sense, the dataset should return a single row with a single value (or no rows).

    # File lib/sequel/dataset/placeholder_literalizer.rb
195 def get(*args)
196   @dataset.with_sql_single_value(sql(*args))
197 end
sql(*args) click to toggle source

Return the SQL query to use for the given arguments.

    # File lib/sequel/dataset/placeholder_literalizer.rb
200 def sql(*args)
201   raise Error, "wrong number of arguments (#{args.length} for #{@arity})" unless args.length == @arity
202   s = sql_origin
203   append_sql(s, *args)
204 end
with_dataset() { |dataset| ... } click to toggle source

Return a new PlaceholderLiteralizer with a modified dataset. This yields the receiver’s dataset to the block, and the block should return the new dataset to use.

    # File lib/sequel/dataset/placeholder_literalizer.rb
170 def with_dataset
171   dataset = yield @dataset
172   other = dup
173   other.instance_variable_set(:@dataset, dataset)
174   other.freeze
175 end

Private Instance Methods

sql_origin() click to toggle source
    # File lib/sequel/dataset/placeholder_literalizer.rb
225 def sql_origin
226   String.new
227 end