class Sequel::SQLite::Database
Attributes
The conversion procs to use for this database
Public Class Methods
Sequel::Database::new
# File lib/sequel/adapters/sqlite.rb 101 def initialize(opts = OPTS) 102 super 103 @allow_regexp = typecast_value_boolean(opts[:setup_regexp_function]) 104 end
Public Instance Methods
Connect to the database. Since SQLite
is a file based database, available options are limited:
- :database
-
database name (filename or ‘:memory:’ or file: URI)
- :readonly
-
open database in read-only mode; useful for reading static data that you do not want to modify
- :timeout
-
how long to wait for the database to be available if it is locked, given in milliseconds (default is 5000)
# File lib/sequel/adapters/sqlite.rb 114 def connect(server) 115 opts = server_opts(server) 116 opts[:database] = ':memory:' if blank_object?(opts[:database]) 117 sqlite3_opts = {} 118 sqlite3_opts[:readonly] = typecast_value_boolean(opts[:readonly]) if opts.has_key?(:readonly) 119 db = ::SQLite3::Database.new(opts[:database].to_s, sqlite3_opts) 120 db.busy_timeout(typecast_value_integer(opts.fetch(:timeout, 5000))) 121 122 if USE_EXTENDED_RESULT_CODES 123 db.extended_result_codes = true 124 end 125 126 connection_pragmas.each{|s| log_connection_yield(s, db){db.execute_batch(s)}} 127 128 if typecast_value_boolean(opts[:setup_regexp_function]) 129 db.create_function("regexp", 2) do |func, regexp_str, string| 130 func.result = Regexp.new(regexp_str).match(string) ? 1 : 0 131 end 132 end 133 134 class << db 135 attr_reader :prepared_statements 136 end 137 db.instance_variable_set(:@prepared_statements, {}) 138 139 db 140 end
Disconnect given connections from the database.
# File lib/sequel/adapters/sqlite.rb 149 def disconnect_connection(c) 150 c.prepared_statements.each_value{|v| v.first.close} 151 c.close 152 end
Run the given SQL
with the given arguments and yield each row.
# File lib/sequel/adapters/sqlite.rb 155 def execute(sql, opts=OPTS, &block) 156 _execute(:select, sql, opts, &block) 157 end
Drop any prepared statements on the connection when executing DDL. This is because prepared statements lock the table in such a way that you can’t drop or alter the table while a prepared statement that references it still exists.
Sequel::Database#execute_ddl
# File lib/sequel/adapters/sqlite.rb 167 def execute_ddl(sql, opts=OPTS) 168 synchronize(opts[:server]) do |conn| 169 conn.prepared_statements.values.each{|cps, s| cps.close} 170 conn.prepared_statements.clear 171 super 172 end 173 end
Run the given SQL
with the given arguments and return the number of changed rows.
# File lib/sequel/adapters/sqlite.rb 160 def execute_dui(sql, opts=OPTS) 161 _execute(:update, sql, opts) 162 end
# File lib/sequel/adapters/sqlite.rb 175 def execute_insert(sql, opts=OPTS) 176 _execute(:insert, sql, opts) 177 end
Sequel::SQLite::DatabaseMethods#freeze
# File lib/sequel/adapters/sqlite.rb 179 def freeze 180 @conversion_procs.freeze 181 super 182 end
Handle Integer and Float arguments, since SQLite
can store timestamps as integers and floats.
Sequel::Database#to_application_timestamp
# File lib/sequel/adapters/sqlite.rb 185 def to_application_timestamp(s) 186 case s 187 when String 188 super 189 when Integer 190 super(Time.at(s).to_s) 191 when Float 192 super(DateTime.jd(s).to_s) 193 else 194 raise Sequel::Error, "unhandled type when converting to : #{s.inspect} (#{s.class.inspect})" 195 end 196 end
Private Instance Methods
Yield an available connection. Rescue any SQLite3::Exceptions and turn them into DatabaseErrors.
# File lib/sequel/adapters/sqlite.rb 208 def _execute(type, sql, opts, &block) 209 synchronize(opts[:server]) do |conn| 210 return execute_prepared_statement(conn, type, sql, opts, &block) if sql.is_a?(Symbol) 211 log_args = opts[:arguments] 212 args = {} 213 opts.fetch(:arguments, OPTS).each{|k, v| args[k] = prepared_statement_argument(v)} 214 case type 215 when :select 216 log_connection_yield(sql, conn, log_args){conn.query(sql, args, &block)} 217 when :insert 218 log_connection_yield(sql, conn, log_args){conn.execute(sql, args)} 219 conn.last_insert_row_id 220 when :update 221 log_connection_yield(sql, conn, log_args){conn.execute_batch(sql, args)} 222 conn.changes 223 end 224 end 225 rescue SQLite3::Exception => e 226 raise_error(e) 227 end
# File lib/sequel/adapters/sqlite.rb 200 def adapter_initialize 201 @conversion_procs = SQLITE_TYPES.dup 202 @conversion_procs['datetime'] = @conversion_procs['timestamp'] = method(:to_application_timestamp) 203 set_integer_booleans 204 end
The SQLite
adapter does not need the pool to convert exceptions. Also, force the max connections to 1 if a memory database is being used, as otherwise each connection gets a separate database.
Sequel::Database#connection_pool_default_options
# File lib/sequel/adapters/sqlite.rb 232 def connection_pool_default_options 233 o = super.dup 234 # Default to only a single connection if a memory database is used, 235 # because otherwise each connection will get a separate database 236 o[:max_connections] = 1 if @opts[:database] == ':memory:' || blank_object?(@opts[:database]) 237 o 238 end
SQLite3 raises ArgumentError in addition to SQLite3::Exception in some cases, such as operations on a closed database.
# File lib/sequel/adapters/sqlite.rb 297 def database_error_classes 298 [SQLite3::Exception, ArgumentError] 299 end
# File lib/sequel/adapters/sqlite.rb 301 def dataset_class_default 302 Dataset 303 end
Execute a prepared statement on the database using the given name.
# File lib/sequel/adapters/sqlite.rb 258 def execute_prepared_statement(conn, type, name, opts, &block) 259 ps = prepared_statement(name) 260 sql = ps.prepared_sql 261 args = opts[:arguments] 262 ps_args = {} 263 args.each{|k, v| ps_args[k] = prepared_statement_argument(v)} 264 if cpsa = conn.prepared_statements[name] 265 cps, cps_sql = cpsa 266 if cps_sql != sql 267 cps.close 268 cps = nil 269 end 270 end 271 unless cps 272 cps = log_connection_yield("PREPARE #{name}: #{sql}", conn){conn.prepare(sql)} 273 conn.prepared_statements[name] = [cps, sql] 274 end 275 log_sql = String.new 276 log_sql << "EXECUTE #{name}" 277 if ps.log_sql 278 log_sql << " (" 279 log_sql << sql 280 log_sql << ")" 281 end 282 if block 283 log_connection_yield(log_sql, conn, args){cps.execute(ps_args, &block)} 284 else 285 log_connection_yield(log_sql, conn, args){cps.execute!(ps_args){|r|}} 286 case type 287 when :insert 288 conn.last_insert_row_id 289 when :update 290 conn.changes 291 end 292 end 293 end
# File lib/sequel/adapters/sqlite.rb 240 def prepared_statement_argument(arg) 241 case arg 242 when Date, DateTime, Time 243 literal(arg)[1...-1] 244 when SQL::Blob 245 arg.to_blob 246 when true, false 247 if integer_booleans 248 arg ? 1 : 0 249 else 250 literal(arg)[1...-1] 251 end 252 else 253 arg 254 end 255 end
Support SQLite
exception codes if ruby-sqlite3 supports them.
# File lib/sequel/adapters/sqlite.rb 307 def sqlite_error_code(exception) 308 exception.code if exception.respond_to?(:code) 309 end