Class: SQLite3::Statement

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/sqlite3/statement.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(db, sql) ⇒ Statement

Returns a new instance of Statement.

Raises:

  • (TypeError)


10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 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

Instance Attribute Details

#remainderObject (readonly)

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.



8
9
10
# File 'lib/sqlite3/statement.rb', line 8

def remainder
  @remainder
end

Instance Method Details

#active?Boolean

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

Returns:

  • (Boolean)


265
266
267
# File 'lib/sqlite3/statement.rb', line 265

def active?
  !done?
end

#bind_param(index, var) ⇒ Object



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# 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_countObject



55
56
57
# File 'lib/sqlite3/statement.rb', line 55

def bind_parameter_count
  Driver.sqlite3_bind_parameter_count(@prepared_stmt)
end

#bind_params(*bind_vars) ⇒ Object

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.



72
73
74
75
76
77
78
79
80
81
82
# 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!Object



131
132
133
# File 'lib/sqlite3/statement.rb', line 131

def clear_bindings!
  @db.check Driver.sqlite3_clear_bindings(@prepared_stmt)
end

#closeObject



237
238
239
240
241
242
# 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?Boolean

Returns true if the statement has been closed.

Returns:

  • (Boolean)


228
229
230
# File 'lib/sqlite3/statement.rb', line 228

def closed?
  @prepared_stmt.nil?
end

#column_countObject



26
27
28
# File 'lib/sqlite3/statement.rb', line 26

def column_count
  Driver.sqlite3_column_count(@prepared_stmt)
end

#column_decltype(index) ⇒ Object



35
36
37
38
# 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) ⇒ Object



30
31
32
33
# 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

#columnsObject

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.



257
258
259
260
261
# File 'lib/sqlite3/statement.rb', line 257

def columns
  must_be_open!
   unless @columns
  return @columns
end

#database_name(index) ⇒ Object



40
41
42
43
# 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?Boolean

returns true if all rows have been returned.

Returns:

  • (Boolean)


233
234
235
# File 'lib/sqlite3/statement.rb', line 233

def done?
  @done
end

#eachObject



162
163
164
165
166
167
168
# 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| ... } ⇒ Object

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

Yields:

  • (@results)


150
151
152
153
154
155
156
157
158
159
160
# 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) ⇒ Object

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.



222
223
224
225
# File 'lib/sqlite3/statement.rb', line 222

def execute!( *bind_vars, &block )
  execute(*bind_vars)
  block_given? ? each(&block) : to_a
end

#must_be_open!Object

Performs a sanity check to ensure that the statement is not closed. If it is, an exception is raised.



271
272
273
274
275
# File 'lib/sqlite3/statement.rb', line 271

def must_be_open! # :nodoc:
  if closed?
    raise Exception, "cannot use a closed statement"
  end
end

#origin_name(index) ⇒ Object



50
51
52
53
# 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!Object



135
136
137
138
# File 'lib/sqlite3/statement.rb', line 135

def reset!
  @db.check Driver.sqlite3_reset(@prepared_stmt)
  @done = false
end

#stepObject



170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
# 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) ⇒ Object



45
46
47
48
# 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

#typesObject

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.



248
249
250
251
252
# File 'lib/sqlite3/statement.rb', line 248

def types
  must_be_open!
   unless @types
  @types
end