2007-01-22 14:43:50 +01:00
|
|
|
require 'sqlite3/errors'
|
|
|
|
require 'sqlite3/resultset'
|
|
|
|
|
|
|
|
class String
|
|
|
|
def to_blob
|
|
|
|
SQLite3::Blob.new( self )
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
module SQLite3
|
|
|
|
# A statement represents a prepared-but-unexecuted SQL query. It will rarely
|
|
|
|
# (if ever) be instantiated directly by a client, and is most often obtained
|
|
|
|
# via the Database#prepare method.
|
|
|
|
class Statement
|
2010-06-11 05:42:33 +02:00
|
|
|
include Enumerable
|
2007-01-22 14:43:50 +01:00
|
|
|
|
|
|
|
# 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.
|
|
|
|
attr_reader :remainder
|
|
|
|
|
|
|
|
# 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.
|
|
|
|
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
|
|
|
|
|
|
|
|
# Execute the statement. This creates a new ResultSet object for the
|
|
|
|
# statement's virtual machine. If a block was given, the new ResultSet will
|
|
|
|
# be yielded to it; otherwise, the ResultSet will be returned.
|
|
|
|
#
|
|
|
|
# Any parameters will be bound to the statement using #bind_params.
|
|
|
|
#
|
|
|
|
# Example:
|
|
|
|
#
|
|
|
|
# stmt = db.prepare( "select * from table" )
|
|
|
|
# stmt.execute do |result|
|
|
|
|
# ...
|
|
|
|
# end
|
|
|
|
#
|
|
|
|
# See also #bind_params, #execute!.
|
|
|
|
def execute( *bind_vars )
|
2010-06-11 05:42:33 +02:00
|
|
|
reset! if active? || done?
|
2007-01-22 14:43:50 +01:00
|
|
|
|
|
|
|
bind_params(*bind_vars) unless bind_vars.empty?
|
2010-06-11 05:42:33 +02:00
|
|
|
@results = ResultSet.new(@connection, self)
|
2007-01-22 14:43:50 +01:00
|
|
|
|
2010-07-21 03:36:17 +02:00
|
|
|
step if 0 == column_count
|
|
|
|
|
2010-06-11 05:42:33 +02:00
|
|
|
yield @results if block_given?
|
|
|
|
@results
|
2007-01-22 14:43:50 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
# 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.
|
2010-06-11 05:42:33 +02:00
|
|
|
def execute!( *bind_vars, &block )
|
|
|
|
execute(*bind_vars)
|
|
|
|
block_given? ? each(&block) : to_a
|
2007-01-22 14:43:50 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
# Returns true if the statement is currently active, meaning it has an
|
|
|
|
# open result set.
|
|
|
|
def active?
|
2010-06-11 05:42:33 +02:00
|
|
|
!done?
|
2007-01-22 14:43:50 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
# 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.
|
|
|
|
def columns
|
|
|
|
get_metadata unless @columns
|
|
|
|
return @columns
|
|
|
|
end
|
|
|
|
|
2010-06-11 05:42:33 +02:00
|
|
|
def each
|
|
|
|
loop do
|
|
|
|
val = step
|
|
|
|
break self if done?
|
|
|
|
yield val
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2007-01-22 14:43:50 +01:00
|
|
|
# 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.
|
|
|
|
def types
|
2010-06-11 05:42:33 +02:00
|
|
|
must_be_open!
|
|
|
|
get_metadata unless @types
|
2009-12-23 03:48:32 +01:00
|
|
|
@types
|
2007-01-22 14:43:50 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
# 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.
|
|
|
|
def get_metadata
|
|
|
|
@columns = []
|
|
|
|
@types = []
|
|
|
|
|
|
|
|
column_count.times do |column|
|
2010-06-11 05:42:33 +02:00
|
|
|
@columns << column_name(column)
|
|
|
|
@types << column_decltype(column)
|
2007-01-22 14:43:50 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
@columns.freeze
|
|
|
|
@types.freeze
|
|
|
|
end
|
|
|
|
private :get_metadata
|
|
|
|
|
|
|
|
# Performs a sanity check to ensure that the statement is not
|
|
|
|
# closed. If it is, an exception is raised.
|
|
|
|
def must_be_open! # :nodoc:
|
2010-06-11 05:42:33 +02:00
|
|
|
if closed?
|
2007-01-22 14:43:50 +01:00
|
|
|
raise SQLite3::Exception, "cannot use a closed statement"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|