class SQLite3::Statement

Attributes

remainder[R]

This is any text that followed the first valid SQL statement in the text with which the statement was initialized. If there was no trailing text, this will be the empty string.

Public Class Methods

new(db, sql) click to toggle source
# File lib/sqlite3/statement.rb, line 10
def initialize(db, sql)
  raise TypeError, 'sql has to be a string' unless sql.is_a? String
  raise ArgumentError, 'db has to be open' if db.closed?
  @db = db
  sql = sql.strip.encode(Encoding::UTF_8)
  @prepared_stmt = Fiddle::Pointer.malloc(Fiddle::SIZEOF_VOIDP)
  remainder = Fiddle::Pointer.malloc(Fiddle::SIZEOF_VOIDP)
  @db.check Driver.sqlite3_prepare_v2(db.handle, sql, -1,
                                         @prepared_stmt.ref,
                                         remainder.ref)
  @remainder = remainder.to_s
  @sql = sql
  @done = false
  remainder.free
end

Public Instance Methods

active?() click to toggle source

Returns true if the statement is currently active, meaning it has an open result set.

# File lib/sqlite3/statement.rb, line 265
def active?
  !done?
end
bind_param(index, var) click to toggle source
# File lib/sqlite3/statement.rb, line 84
def bind_param(index, var)
  must_be_open!
  unless index.is_a? Fixnum
    name = index.to_s
    name = ":#{name}" unless name.start_with? ':'
      # if name !=~ /^[:@?$].*/
    index = Driver.sqlite3_bind_parameter_index(@prepared_stmt, name)
    if index == 0
      raise Exception, "index #{name} unknown for [#{@sql}]"
    end
  end
  @db.check case var
  when Blob
    var = var.force_encoding(Encoding::ASCII_8BIT)
    Driver.sqlite3_bind_blob(@prepared_stmt, index, var.to_s,
                                                    var.size, nil)
  when String
    # if UTF_16BE was passed we have to convert it anyway, than we use
    # the UTF-8 conversion much like the c implementation does.
    # TODO: check if this is slow because the sqlite than has to convert to?
    if var.encoding == Encoding::UTF_16LE
      Driver.sqlite3_bind_text16(@prepared_stmt, index, var, -1, nil)
    else # this string behaves like a blob, so we bind it as such
      if var.encoding == Encoding::ASCII_8BIT
        Driver.sqlite3_bind_blob(@prepared_stmt, index, var.to_s,
                                                        var.size, nil)
      else
        unless var.encoding == Encoding::UTF_8
          var = var.encode(Encoding::UTF_8)
        end
        Driver.sqlite3_bind_text(@prepared_stmt, index, var, -1, nil)
      end
    end
  when Fixnum, Bignum
    Driver.sqlite3_bind_int64(@prepared_stmt, index, var)
  when Float
    Driver.sqlite3_bind_double(@prepared_stmt, index, var)
  when NilClass
    Driver.sqlite3_bind_null(@prepared_stmt, index)
  when TrueClass, FalseClass
    Driver.sqlite3_bind_int(@prepared_stmt, index, var ? 1 : 0)
  else
    Driver.sqlite3_bind_blob(@prepared_stmt, index, var.to_s,
                                                    var.to_s.size, nil)
  end
end
bind_parameter_count() click to toggle source
# File lib/sqlite3/statement.rb, line 55
def bind_parameter_count
  Driver.sqlite3_bind_parameter_count(@prepared_stmt)
end
bind_params( *bind_vars ) click to toggle source

Binds the given variables to the corresponding placeholders in the SQL text.

See Database#execute for a description of the valid placeholder syntaxes.

Example:

stmt = db.prepare( "select * from table where a=? and b=?" )
stmt.bind_params( 15, "hello" )

See also execute, bind_param, Statement#bind_param, and Statement#bind_params.

# File lib/sqlite3/statement.rb, line 72
def bind_params( *bind_vars )
  index = 1
  bind_vars.flatten.each do |var|
    if Hash === var
      var.each { |key, val| bind_param key, val }
    else
      bind_param index, var
      index += 1
    end
  end
end
clear_bindings!() click to toggle source
# File lib/sqlite3/statement.rb, line 131
def clear_bindings!
  @db.check Driver.sqlite3_clear_bindings(@prepared_stmt)
end
close() click to toggle source
# File lib/sqlite3/statement.rb, line 237
def close
  must_be_open!
  @db.check Driver.sqlite3_finalize(@prepared_stmt)
  @prepared_stmt.free
  @prepared_stmt = nil
end
closed?() click to toggle source

Returns true if the statement has been closed.

# File lib/sqlite3/statement.rb, line 228
def closed?
  @prepared_stmt.nil?
end
column_count() click to toggle source
# File lib/sqlite3/statement.rb, line 26
def column_count
  Driver.sqlite3_column_count(@prepared_stmt)
end
column_decltype(index) click to toggle source
# File lib/sqlite3/statement.rb, line 35
def column_decltype(index)
  column = Driver.sqlite3_column_decltype(@prepared_stmt, index.to_i)
  column.to_s unless column.null?
end
column_name(index) click to toggle source
# File lib/sqlite3/statement.rb, line 30
def column_name(index)
  column = Driver.sqlite3_column_name(@prepared_stmt, index.to_i)
  column.to_s unless column.null?
end
columns() click to toggle source

Return an array of the column names for this statement. Note that this may execute the statement in order to obtain the metadata; this makes it a (potentially) expensive operation.

# File lib/sqlite3/statement.rb, line 257
def columns
  must_be_open!
  get_metadata unless @columns
  return @columns
end
database_name(index) click to toggle source
# File lib/sqlite3/statement.rb, line 40
def database_name(index)
  name = Driver.sqlite3_column_database_name(@prepared_stmt, index.to_i)
  name.to_s unless name.null?
end
done?() click to toggle source

returns true if all rows have been returned.

# File lib/sqlite3/statement.rb, line 233
def done?
  @done
end
each() { |val| ... } click to toggle source
# File lib/sqlite3/statement.rb, line 162
def each
  loop do
    val = step
    break self if done?
    yield val
  end
end
execute( *bind_vars ) { |results| ... } click to toggle source

def execute(*bind_vars, &handler)

must_be_open!
reset! if active? || done?
bind_params *bind_vars unless bind_vars.empty?
if block_given?
  each &handler
else
  ResultSet.new(@db, self)
end

end

# File lib/sqlite3/statement.rb, line 150
def execute( *bind_vars )
  reset! if active? || done?

  bind_params(*bind_vars) unless bind_vars.empty?
  @results = ResultSet.new(@db, self)

  step if 0 == column_count

  yield @results if block_given?
  @results
end
execute!( *bind_vars, &block ) click to toggle source

Execute the statement. If no block was given, this returns an array of rows returned by executing the statement. Otherwise, each row will be yielded to the block.

Any parameters will be bound to the statement using bind_params.

Example:

stmt = db.prepare( "select * from table" )
stmt.execute! do |row|
  ...
end

See also bind_params, execute.

# File lib/sqlite3/statement.rb, line 222
def execute!( *bind_vars, &block )
  execute(*bind_vars)
  block_given? ? each(&block) : to_a
end
origin_name(index) click to toggle source
# File lib/sqlite3/statement.rb, line 50
def origin_name(index)
  name = Driver.sqlite3_column_origin_name(@prepared_stmt, index.to_i)
  name.to_s unless name.null?
end
reset!() click to toggle source
# File lib/sqlite3/statement.rb, line 135
def reset!
  @db.check Driver.sqlite3_reset(@prepared_stmt)
  @done = false
end
step() click to toggle source
# File lib/sqlite3/statement.rb, line 170
def step
  must_be_open!
  case Driver.sqlite3_step(@prepared_stmt)
  when SQLITE_ROW
    row = []
    column_count.times do |i|
      case Driver.sqlite3_column_type(@prepared_stmt, i)
      when SQLITE_INTEGER
        row << Driver.sqlite3_column_int64(@prepared_stmt, i)
      when SQLITE_FLOAT
        row << Driver.sqlite3_column_double(@prepared_stmt, i)
      when SQLITE_TEXT
        text = (Driver.sqlite3_column_text(@prepared_stmt, i)[
          0, Driver.sqlite3_column_bytes(@prepared_stmt, i)
        ])
        default = Encoding.default_internal || Encoding::UTF_8
        row << text.encode(default, Encoding::UTF_8)
      when SQLITE_BLOB
        data = Driver.sqlite3_column_blob(@prepared_stmt, i)[
          0, Driver.sqlite3_column_bytes(@prepared_stmt, i)
        ]
        row << Blob.new(data.force_encoding(Encoding::ASCII_8BIT))
      when SQLITE_NULL
        row << nil
      else
        fail Exception, "bad type"
      end
    end
    return row
  when SQLITE_DONE
    @done = true
    return nil
  else
    reset!
    @done = false
  end
end
table_name(index) click to toggle source
# File lib/sqlite3/statement.rb, line 45
def table_name(index)
  name = Driver.sqlite3_column_table_name(@prepared_stmt, index.to_i)
  name.to_s unless name.null?
end
types() click to toggle source

Return an array of the data types for each column in this statement. Note that this may execute the statement in order to obtain the metadata; this makes it a (potentially) expensive operation.

# File lib/sqlite3/statement.rb, line 248
def types
  must_be_open!
  get_metadata unless @types
  @types
end

Private Instance Methods

get_metadata() click to toggle source

A convenience method for obtaining the metadata about the query. Note that this will actually execute the SQL, which means it can be a (potentially) expensive operation.

# File lib/sqlite3/statement.rb, line 281
def get_metadata
  @columns = Array.new(column_count) do |column|
    column_name column
  end
  @types = Array.new(column_count) do |column|
    column_decltype column
  end
end