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.
Public Instance Methods
Sets the prepared_args
to the given hash and runs the prepared statement.
# File lib/sequel/dataset/prepared_statements.rb 109 def call(bind_vars=OPTS, &block) 110 bind(bind_vars).run(&block) 111 end
Send the columns to the original dataset, as calling it on the prepared statement can cause problems.
# File lib/sequel/dataset/prepared_statements.rb 122 def columns 123 orig_dataset.columns 124 end
Disallow use of delayed evaluations in prepared statements.
# File lib/sequel/dataset/prepared_statements.rb 127 def delayed_evaluation_sql_append(sql, delay) 128 raise Error, "delayed evaluations cannot be used in prepared statements" if @opts[:no_delayed_evaluations] 129 super 130 end
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 173 def inspect 174 "<#{visible_class_name}/PreparedStatement #{prepared_sql.inspect}>" 175 end
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.
# File lib/sequel/dataset/prepared_statements.rb 157 def literal_symbol_append(sql, v) 158 if @opts[:bind_vars] and match = /\A\$(.*)\z/.match(v.to_s) 159 s = match[1].to_sym 160 if prepared_arg?(s) 161 literal_append(sql, prepared_arg(s)) 162 else 163 sql << v.to_s 164 end 165 else 166 super 167 end 168 end
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 81 def log_sql 82 @opts[:log_sql] 83 end
The dataset that created this prepared statement.
# File lib/sequel/dataset/prepared_statements.rb 97 def orig_dataset 98 @opts[:orig_dataset] 99 end
Raise an error if attempting to call prepare on an already prepared statement.
# File lib/sequel/dataset/prepared_statements.rb 115 def prepare(*) 116 raise Error, "cannot prepare an already prepared statement" unless allow_preparing_prepared_statements? 117 super 118 end
The array/hash of bound variable placeholder names.
# File lib/sequel/dataset/prepared_statements.rb 92 def prepared_args 93 @opts[:prepared_args] 94 end
The argument to supply to insert and update, which may use placeholders specified by prepared_args
# File lib/sequel/dataset/prepared_statements.rb 103 def prepared_modify_values 104 @opts[:prepared_modify_values] 105 end
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 134 def prepared_sql 135 case prepared_type 136 when :select, :all, :each 137 # Most common scenario, so listed first. 138 select_sql 139 when :first 140 clone(:limit=>1).select_sql 141 when :insert_select 142 insert_select_sql(*prepared_modify_values) 143 when :insert, :insert_pk 144 insert_sql(*prepared_modify_values) 145 when :update 146 update_sql(*prepared_modify_values) 147 when :delete 148 delete_sql 149 else 150 select_sql 151 end 152 end
The type of prepared statement, should be one of :select, :first, :insert, :update, or :delete
# File lib/sequel/dataset/prepared_statements.rb 87 def prepared_type 88 @opts[:prepared_type] 89 end
Protected Instance Methods
Run the method based on the type of prepared statement.
# File lib/sequel/dataset/prepared_statements.rb 180 def run(&block) 181 case prepared_type 182 when :select, :all 183 all(&block) 184 when :each 185 each(&block) 186 when :insert_select 187 with_sql(prepared_sql).first 188 when :first 189 first 190 when :insert, :update, :delete 191 if opts[:returning] && supports_returning?(prepared_type) 192 returning_fetch_rows(prepared_sql) 193 elsif prepared_type == :delete 194 delete 195 else 196 public_send(prepared_type, *prepared_modify_values) 197 end 198 when :insert_pk 199 fetch_rows(prepared_sql){|r| return r.values.first} 200 when Array 201 case prepared_type[0] 202 when :map, :as_hash, :to_hash, :to_hash_groups 203 public_send(*prepared_type, &block) 204 end 205 else 206 raise Error, "unsupported prepared statement type used: #{prepared_type.inspect}" 207 end 208 end
Private Instance Methods
Returns the value of the prepared_args
hash for the given key.
# File lib/sequel/dataset/prepared_statements.rb 213 def prepared_arg(k) 214 @opts[:bind_vars][k] 215 end
Whether there is a bound value for the given key.
# File lib/sequel/dataset/prepared_statements.rb 218 def prepared_arg?(k) 219 @opts[:bind_vars].has_key?(k) 220 end
The symbol cache should always be skipped, since placeholders are symbols.
# File lib/sequel/dataset/prepared_statements.rb 223 def skip_symbol_cache? 224 true 225 end
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 230 def subselect_sql_append(sql, ds) 231 ds.clone(:append_sql=>sql, :prepared_args=>prepared_args, :bind_vars=>@opts[:bind_vars]). 232 send(:to_prepared_statement, :select, nil, :extend=>prepared_statement_modules). 233 prepared_sql 234 end