The conversion procs to use for this database
Connect to the database. Since SQLite is a file based database, available options are limited:
database name (filename or ':memory:' or file: URI)
open database in read-only mode; useful for reading static data that you do not want to modify
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, line 100 def connect(server) opts = server_opts(server) opts[:database] = ':memory:' if blank_object?(opts[:database]) sqlite3_opts = {} sqlite3_opts[:readonly] = typecast_value_boolean(opts[:readonly]) if opts.has_key?(:readonly) db = ::SQLite3::Database.new(opts[:database].to_s, sqlite3_opts) db.busy_timeout(opts.fetch(:timeout, 5000)) connection_pragmas.each{|s| log_connection_yield(s, db){db.execute_batch(s)}} class << db attr_reader :prepared_statements end db.instance_variable_set(:@prepared_statements, {}) db end
Disconnect given connections from the database.
# File lib/sequel/adapters/sqlite.rb, line 119 def disconnect_connection(c) c.prepared_statements.each_value{|v| v.first.close} c.close end
Run the given SQL with the given arguments and yield each row.
# File lib/sequel/adapters/sqlite.rb, line 125 def execute(sql, opts=OPTS, &block) _execute(:select, sql, opts, &block) 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.
# File lib/sequel/adapters/sqlite.rb, line 137 def execute_ddl(sql, opts=OPTS) synchronize(opts[:server]) do |conn| conn.prepared_statements.values.each{|cps, s| cps.close} conn.prepared_statements.clear super end end
Run the given SQL with the given arguments and return the number of changed rows.
# File lib/sequel/adapters/sqlite.rb, line 130 def execute_dui(sql, opts=OPTS) _execute(:update, sql, opts) end
# File lib/sequel/adapters/sqlite.rb, line 145 def execute_insert(sql, opts=OPTS) _execute(:insert, sql, opts) end
# File lib/sequel/adapters/sqlite.rb, line 149 def freeze @conversion_procs.freeze super end
Handle Integer and Float arguments, since SQLite can store timestamps as integers and floats.
# File lib/sequel/adapters/sqlite.rb, line 155 def to_application_timestamp(s) case s when String super when Integer super(Time.at(s).to_s) when Float super(DateTime.jd(s).to_s) else raise Sequel::Error, "unhandled type when converting to : #{s.inspect} (#{s.class.inspect})" end end
Yield an available connection. Rescue any SQLite3::Exceptions and turn them into DatabaseErrors.
# File lib/sequel/adapters/sqlite.rb, line 178 def _execute(type, sql, opts, &block) begin synchronize(opts[:server]) do |conn| return execute_prepared_statement(conn, type, sql, opts, &block) if sql.is_a?(Symbol) log_args = opts[:arguments] args = {} opts.fetch(:arguments, {}).each{|k, v| args[k] = prepared_statement_argument(v)} case type when :select log_connection_yield(sql, conn, log_args){conn.query(sql, args, &block)} when :insert log_connection_yield(sql, conn, log_args){conn.execute(sql, args)} conn.last_insert_row_id when :update log_connection_yield(sql, conn, log_args){conn.execute_batch(sql, args)} conn.changes end end rescue SQLite3::Exception => e raise_error(e) end end
# File lib/sequel/adapters/sqlite.rb, line 170 def adapter_initialize @conversion_procs = SQLITE_TYPES.dup @conversion_procs['datetime'] = @conversion_procs['timestamp'] = method(:to_application_timestamp) set_integer_booleans 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.
# File lib/sequel/adapters/sqlite.rb, line 204 def connection_pool_default_options o = super.dup # Default to only a single connection if a memory database is used, # because otherwise each connection will get a separate database o[:max_connections] = 1 if @opts[:database] == ':memory:' || blank_object?(@opts[:database]) o 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, line 269 def database_error_classes [SQLite3::Exception, ArgumentError] end
# File lib/sequel/adapters/sqlite.rb, line 273 def dataset_class_default Dataset end
Execute a prepared statement on the database using the given name.
# File lib/sequel/adapters/sqlite.rb, line 230 def execute_prepared_statement(conn, type, name, opts, &block) ps = prepared_statement(name) sql = ps.prepared_sql args = opts[:arguments] ps_args = {} args.each{|k, v| ps_args[k] = prepared_statement_argument(v)} if cpsa = conn.prepared_statements[name] cps, cps_sql = cpsa if cps_sql != sql cps.close cps = nil end end unless cps cps = log_connection_yield("PREPARE #{name}: #{sql}", conn){conn.prepare(sql)} conn.prepared_statements[name] = [cps, sql] end log_sql = String.new log_sql << "EXECUTE #{name}" if ps.log_sql log_sql << " (" log_sql << sql log_sql << ")" end if block log_connection_yield(log_sql, conn, args){cps.execute(ps_args, &block)} else log_connection_yield(log_sql, conn, args){cps.execute!(ps_args){|r|}} case type when :insert conn.last_insert_row_id when :update conn.changes end end end
# File lib/sequel/adapters/sqlite.rb, line 212 def prepared_statement_argument(arg) case arg when Date, DateTime, Time literal(arg)[1...-1] when SQL::Blob arg.to_blob when true, false if integer_booleans arg ? 1 : 0 else literal(arg)[1...-1] end else arg end end