module Sequel::Dataset::PreparedStatementMethods

Backbone of the prepared statement support. Grafts bind variable support into datasets by hijacking literal and using placeholders. By default, emulates prepared statements and bind variables by taking the hash of bind variables and directly substituting them into the query, which works on all databases, as it is no different from using the dataset without bind variables.

Constants

PLACEHOLDER_RE

Public Instance Methods

call(bind_vars={}, &block) click to toggle source

Sets the #prepared_args to the given hash and runs the prepared statement.

# File lib/sequel/dataset/prepared_statements.rb, line 126
def call(bind_vars={}, &block)
  bind(bind_vars).run(&block)
end
columns() click to toggle source

Send the columns to the original dataset, as calling it on the prepared statement can cause problems.

# File lib/sequel/dataset/prepared_statements.rb, line 139
def columns
  orig_dataset.columns
end
inspect() click to toggle source

Programmer friendly string showing this is a prepared statement, with the prepared SQL it represents (which in general won't have substituted variables).

# File lib/sequel/dataset/prepared_statements.rb, line 184
def inspect
  "<#{visible_class_name}/PreparedStatement #{prepared_sql.inspect}>"
end
literal_symbol_append(sql, v) click to toggle source

Changes the values of symbols if they start with $ and #prepared_args is present. If so, they are considered placeholders, and they are substituted using prepared_arg.

Calls superclass method
# File lib/sequel/dataset/prepared_statements.rb, line 168
def literal_symbol_append(sql, v)
  if @opts[:bind_vars] and match = PLACEHOLDER_RE.match(v.to_s)
    s = match[1].to_sym
    if prepared_arg?(s)
      literal_append(sql, prepared_arg(s))
    else
      sql << v.to_s
    end
  else
    super
  end
end
log_sql() click to toggle source

Whether to log the full SQL query. By default, just the prepared statement name is generally logged on adapters that support native prepared statements.

# File lib/sequel/dataset/prepared_statements.rb, line 98
def log_sql
  @opts[:log_sql]
end
orig_dataset() click to toggle source

The dataset that created this prepared statement.

# File lib/sequel/dataset/prepared_statements.rb, line 114
def orig_dataset
  @opts[:orig_dataset]
end
prepare(*) click to toggle source

Raise an error if attempting to call prepare on an already prepared statement.

Calls superclass method
# File lib/sequel/dataset/prepared_statements.rb, line 132
def prepare(*)
  raise Error, "cannot prepare an already prepared statement" unless allow_preparing_prepared_statements?
  super
end
prepared_args() click to toggle source

The array/hash of bound variable placeholder names.

# File lib/sequel/dataset/prepared_statements.rb, line 109
def prepared_args
  @opts[:prepared_args]
end
prepared_modify_values() click to toggle source

The argument to supply to insert and update, which may use placeholders specified by #prepared_args

# File lib/sequel/dataset/prepared_statements.rb, line 120
def prepared_modify_values
  @opts[:prepared_modify_values]
end
prepared_sql() click to toggle source

Returns the SQL for the prepared statement, depending on the type of the statement and the prepared_modify_values.

# File lib/sequel/dataset/prepared_statements.rb, line 145
def prepared_sql
  case prepared_type
  when :select, :all, :each
    # Most common scenario, so listed first.
    select_sql
  when :first
    clone(:limit=>1).select_sql
  when :insert_select
    insert_select_sql(*prepared_modify_values)
  when :insert, :insert_pk
    insert_sql(*prepared_modify_values)
  when :update
    update_sql(*prepared_modify_values)
  when :delete
    delete_sql
  else
    select_sql
  end
end
prepared_type() click to toggle source

The type of prepared statement, should be one of :select, :first, :insert, :update, or :delete

# File lib/sequel/dataset/prepared_statements.rb, line 104
def prepared_type
  @opts[:prepared_type]
end

Protected Instance Methods

run(&block) click to toggle source

Run the method based on the type of prepared statement, with :select running all to get all of the rows, and the other types running the method with the same name as the type.

# File lib/sequel/dataset/prepared_statements.rb, line 193
def run(&block)
  case prepared_type
  when :select, :all
    # Most common scenario, so listed first
    all(&block)
  when :each
    each(&block)
  when :insert_select
    with_sql(prepared_sql).first
  when :first
    first
  when :insert, :update, :delete
    if opts[:returning] && supports_returning?(prepared_type)
      returning_fetch_rows(prepared_sql)
    elsif prepared_type == :delete
      delete
    else
      send(prepared_type, *prepared_modify_values)
    end
  when :insert_pk
    fetch_rows(prepared_sql){|r| return r.values.first}
  when Array
    case prepared_type.at(0)
    when :map, :to_hash, :to_hash_groups
      send(*prepared_type, &block) 
    end
  else
    Sequel::Deprecation.deprecate("Using an unsupported prepared statement type (#{prepared_type.inspect})", 'Switch to using :select as the prepared statement type')
    all(&block)
  end
end

Private Instance Methods

prepared_arg(k) click to toggle source

Returns the value of the #prepared_args hash for the given key.

# File lib/sequel/dataset/prepared_statements.rb, line 228
def prepared_arg(k)
  @opts[:bind_vars][k]
end
prepared_arg?(k) click to toggle source

Whether there is a bound value for the given key.

# File lib/sequel/dataset/prepared_statements.rb, line 233
def prepared_arg?(k)
  @opts[:bind_vars].has_key?(k)
end
skip_symbol_cache?() click to toggle source

The symbol cache should always be skipped, since placeholders are symbols.

# File lib/sequel/dataset/prepared_statements.rb, line 239
def skip_symbol_cache?
  true
end
subselect_sql_append(sql, ds) click to toggle source

Use a clone of the dataset extended with prepared statement support and using the same argument hash so that you can use bind variables/prepared arguments in subselects.

# File lib/sequel/dataset/prepared_statements.rb, line 246
def subselect_sql_append(sql, ds)
  ds.clone(:append_sql=>sql, :prepared_args=>prepared_args, :bind_vars=>@opts[:bind_vars]).
    send(:to_prepared_statement, :select, nil, :extend=>prepared_statement_modules).
    prepared_sql
end