class Sequel::SQLite::Database

ruby-sqlite3 driver.
Database class for SQLite databases used with Sequel and the

def self.uri_to_options(uri) # :nodoc:

:nodoc:
path, and 3 preceding slashes specify an absolute path.
Mimic the file:// uri, by having 2 preceding slashes specify a relative
def self.uri_to_options(uri) # :nodoc:
  { :database => (uri.host.nil? && uri.path == '/') ? nil : "#{uri.host}#{uri.path}" }
end

def _execute(type, sql, opts, &block)

any SQLite3::Exceptions and turn them into DatabaseErrors.
Yield an available connection. Rescue
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_yield(sql, log_args){conn.query(sql, args, &block)}
      when :single_value
        log_yield(sql, log_args){conn.get_first_value(sql, args)}
      when :insert
        log_yield(sql, log_args){conn.execute(sql, args)}
        conn.last_insert_row_id
      when :update
        log_yield(sql, log_args){conn.execute_batch(sql, args)}
        conn.changes
      end
    end
  rescue SQLite3::Exception => e
    raise_error(e)
  end
end

def connect(server)

be available if it is locked, given in milliseconds (default is 5000).
name), and :timeout, to specify how long to wait for the database to
the only options available are :database (to specify the database
Connect to the database. Since SQLite is a file based database,
def connect(server)
  opts = server_opts(server)
  opts[:database] = ':memory:' if blank_object?(opts[:database])
  db = ::SQLite3::Database.new(opts[:database])
  db.busy_timeout(opts.fetch(:timeout, 5000))
  
  connection_pragmas.each{|s| log_yield(s){db.execute_batch(s)}}
  
  class << db
    attr_reader :prepared_statements
  end
  db.instance_variable_set(:@prepared_statements, {})
  
  db
end

def connection_pool_default_options

used, as otherwise each connection gets a separate database.
Also, force the max connections to 1 if a memory database is being
The SQLite adapter does not need the pool to convert exceptions.
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

def database_error_classes

The main error class that SQLite3 raises
def database_error_classes
  [SQLite3::Exception]
end

def disconnect_connection(c)

Disconnect given connections from the database.
def disconnect_connection(c)
  c.prepared_statements.each_value{|v| v.first.close}
  c.close
end

def execute(sql, opts={}, &block)

Run the given SQL with the given arguments and yield each row.
def execute(sql, opts={}, &block)
  _execute(:select, sql, opts, &block)
end

def execute_ddl(sql, opts={})

table while a prepared statement that references it still exists.
prepared statements lock the table in such a way that you can't drop or alter the
Drop any prepared statements on the connection when executing DDL. This is because
def execute_ddl(sql, opts={})
  synchronize(opts[:server]) do |conn|
    conn.prepared_statements.values.each{|cps, s| cps.close}
    conn.prepared_statements.clear
    super
  end
end

def execute_dui(sql, opts={})

Run the given SQL with the given arguments and return the number of changed rows.
def execute_dui(sql, opts={})
  _execute(:update, sql, opts)
end

def execute_insert(sql, opts={})

Run the given SQL with the given arguments and return the last inserted row id.
def execute_insert(sql, opts={})
  _execute(:insert, sql, opts)
end

def execute_prepared_statement(conn, type, name, opts, &block)

Execute a prepared statement on the database using the given name.
def execute_prepared_statement(conn, type, name, opts, &block)
  ps = prepared_statements[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_yield("Preparing #{name}: #{sql}"){conn.prepare(sql)}
    conn.prepared_statements[name] = [cps, sql]
  end
  if block
    log_yield("Executing prepared statement #{name}", args){cps.execute(ps_args, &block)}
  else
    log_yield("Executing prepared statement #{name}", args){cps.execute!(ps_args){|r|}}
    case type
    when :insert
      conn.last_insert_row_id
    when :update
      conn.changes
    end
  end
end

def initialize(opts={})

def initialize(opts={})
  super
  @conversion_procs = SQLITE_TYPES.dup
  @conversion_procs['datetime'] = @conversion_procs['timestamp'] = method(:to_application_timestamp)
  set_integer_booleans
end

def prepared_statement_argument(arg)

def prepared_statement_argument(arg)
  case arg
  when Date, DateTime, Time, TrueClass, FalseClass
    literal(arg)[1...-1]
  when SQL::Blob
    arg.to_blob
  else
    arg
  end
end

def single_value(sql, opts={})

Run the given SQL with the given arguments and return the first value of the first row.
def single_value(sql, opts={})
  _execute(:single_value, sql, opts)
end

def to_application_timestamp(s)

Handle Integer and Float arguments, since SQLite can store timestamps as integers and floats.
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