sqlite3-ffi 0.1.7 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/lib/sqlite3/database.rb +1 -5
- data/lib/sqlite3/ffi/c_api.rb +22 -2
- data/lib/sqlite3/ffi/database.rb +81 -3
- data/lib/sqlite3/ffi/exception.rb +2 -2
- data/lib/sqlite3/ffi/functions.rb +1 -1
- data/lib/sqlite3/ffi/sqlite3.rb +1 -1
- data/lib/sqlite3/ffi/statement.rb +16 -3
- data/lib/sqlite3/ffi/utils.rb +13 -1
- data/lib/sqlite3/ffi/version.rb +1 -1
- data/lib/sqlite3/resultset.rb +10 -4
- data/lib/sqlite3/statement.rb +29 -10
- data/lib/sqlite3/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 402ba8b0d0f49fd0f6229dba55575c8c5c22e460a2c2883095782f7f0f370ae6
|
|
4
|
+
data.tar.gz: 22c9aad92904a410a4a697aa8dddcb84519e4669cb8976c57ba6d1f2c04c37d4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9ef8d936ee00247132f2d0c632491bffc4802915b539267ffc8131c13dfcee6cb85eb568d68d439894eed3a511813cb9e7f19baf82cbeff9fd7d896bdc4b8845
|
|
7
|
+
data.tar.gz: 0a454150d3d90edbf20cd59f3eb69c75d0825bb406efb290aded8b4376e32ea14e45e6317252134c691fddbb1e065a00f9ae8981d852861131ad1a4c80e0bf16
|
data/CHANGELOG.md
CHANGED
data/lib/sqlite3/database.rb
CHANGED
|
@@ -171,8 +171,6 @@ module SQLite3
|
|
|
171
171
|
end
|
|
172
172
|
end
|
|
173
173
|
|
|
174
|
-
@tracefunc = nil
|
|
175
|
-
@authorizer = nil
|
|
176
174
|
@progress_handler = nil
|
|
177
175
|
@collations = {}
|
|
178
176
|
@functions = []
|
|
@@ -458,9 +456,7 @@ module SQLite3
|
|
|
458
456
|
#
|
|
459
457
|
# See also #create_aggregate_handler for a more object-oriented approach to
|
|
460
458
|
# aggregate functions.
|
|
461
|
-
def create_aggregate(name, arity, step = nil, finalize = nil,
|
|
462
|
-
text_rep = Constants::TextRep::ANY, &block)
|
|
463
|
-
|
|
459
|
+
def create_aggregate(name, arity, step = nil, finalize = nil, text_rep = Constants::TextRep::ANY, &block)
|
|
464
460
|
proxy = Class.new do
|
|
465
461
|
def self.step(&block)
|
|
466
462
|
define_method(:step_with_ctx, &block)
|
data/lib/sqlite3/ffi/c_api.rb
CHANGED
|
@@ -90,6 +90,9 @@ module SQLite3
|
|
|
90
90
|
SQLITE_DBCONFIG_ENABLE_COMMENTS = 1022
|
|
91
91
|
SQLITE_DBCONFIG_MAX = 1022
|
|
92
92
|
|
|
93
|
+
SQLITE_DESERIALIZE_FREEONCLOSE = 1
|
|
94
|
+
SQLITE_DESERIALIZE_RESIZEABLE = 2
|
|
95
|
+
|
|
93
96
|
SQLITE_OPEN_READONLY = 0x00000001
|
|
94
97
|
SQLITE_OPEN_READWRITE = 0x00000002
|
|
95
98
|
SQLITE_OPEN_CREATE = 0x00000004
|
|
@@ -145,7 +148,7 @@ module SQLite3
|
|
|
145
148
|
attach_function :sqlite3_bind_parameter_count, [:pointer], :int
|
|
146
149
|
attach_function :sqlite3_bind_parameter_index, [:pointer, :string], :int
|
|
147
150
|
attach_function :sqlite3_bind_parameter_name, [:pointer, :int], :string
|
|
148
|
-
attach_function :sqlite3_bind_text, [:pointer, :int, :
|
|
151
|
+
attach_function :sqlite3_bind_text, [:pointer, :int, :pointer, :int, :pointer], :int
|
|
149
152
|
attach_function :sqlite3_bind_text16, [:pointer, :int, :pointer, :int, :pointer], :int
|
|
150
153
|
attach_function :sqlite3_busy_handler, [:pointer, :pointer, :pointer], :int
|
|
151
154
|
attach_function :sqlite3_busy_timeout, [:pointer, :int], :int
|
|
@@ -182,8 +185,10 @@ module SQLite3
|
|
|
182
185
|
attach_function :sqlite3_last_insert_rowid, [:pointer], :int64
|
|
183
186
|
attach_function :sqlite3_libversion, [], :string
|
|
184
187
|
attach_function :sqlite3_libversion_number, [], :int
|
|
188
|
+
attach_function :sqlite3_malloc64, [:int64], :pointer
|
|
189
|
+
attach_function :sqlite3_mprintf, [:string, :varargs], :pointer
|
|
185
190
|
attach_function :sqlite3_open16, [:pointer, :pointer], :int
|
|
186
|
-
attach_function :sqlite3_open_v2, [:string, :pointer, :int, :
|
|
191
|
+
attach_function :sqlite3_open_v2, [:string, :pointer, :int, :string], :int
|
|
187
192
|
attach_function :sqlite3_prepare_v2, [:pointer, :string, :int, :pointer, :pointer], :int
|
|
188
193
|
attach_function :sqlite3_progress_handler, [:pointer, :int, :pointer, :pointer], :void
|
|
189
194
|
attach_function :sqlite3_reset, [:pointer], :int
|
|
@@ -196,6 +201,7 @@ module SQLite3
|
|
|
196
201
|
attach_function :sqlite3_sql, [:pointer], :string
|
|
197
202
|
attach_function :sqlite3_status64, [:int, :pointer, :pointer, :int], :int
|
|
198
203
|
attach_function :sqlite3_step, [:pointer], :int
|
|
204
|
+
attach_function :sqlite3_stmt_busy, [:pointer], :int
|
|
199
205
|
attach_function :sqlite3_stmt_status, [:pointer, :int, :int], :int
|
|
200
206
|
attach_function :sqlite3_threadsafe, [], :int
|
|
201
207
|
attach_function :sqlite3_total_changes, [:pointer], :int
|
|
@@ -215,6 +221,13 @@ module SQLite3
|
|
|
215
221
|
false
|
|
216
222
|
end
|
|
217
223
|
|
|
224
|
+
HAVE_SQLITE3_DESERIALIZE = begin
|
|
225
|
+
attach_function :sqlite3_deserialize, [:pointer, :string, :pointer, :int64, :int64, :uint], :int
|
|
226
|
+
true
|
|
227
|
+
rescue ::FFI::NotFoundError
|
|
228
|
+
false
|
|
229
|
+
end
|
|
230
|
+
|
|
218
231
|
HAVE_SQLITE3_ENABLE_LOAD_EXTENSION = begin
|
|
219
232
|
attach_function :sqlite3_enable_load_extension, [:pointer, :int], :int
|
|
220
233
|
true
|
|
@@ -228,6 +241,13 @@ module SQLite3
|
|
|
228
241
|
rescue ::FFI::NotFoundError
|
|
229
242
|
false
|
|
230
243
|
end
|
|
244
|
+
|
|
245
|
+
HAVE_SQLITE3_SERIALIZE = begin
|
|
246
|
+
attach_function :sqlite3_serialize, [:pointer, :string, :pointer, :uint], :pointer
|
|
247
|
+
true
|
|
248
|
+
rescue ::FFI::NotFoundError
|
|
249
|
+
false
|
|
250
|
+
end
|
|
231
251
|
end
|
|
232
252
|
end
|
|
233
253
|
end
|
data/lib/sqlite3/ffi/database.rb
CHANGED
|
@@ -144,6 +144,8 @@ module SQLite3
|
|
|
144
144
|
def exec_batch(sql, results_as_hash)
|
|
145
145
|
require_open_db
|
|
146
146
|
|
|
147
|
+
@stmt_deadline = nil
|
|
148
|
+
|
|
147
149
|
callback_ary = []
|
|
148
150
|
err_msg = ::FFI::MemoryPointer.new(:pointer)
|
|
149
151
|
callback = results_as_hash == true ? FFI::HASH_CALLBACK : FFI::REGULAR_CALLBACK
|
|
@@ -159,6 +161,52 @@ module SQLite3
|
|
|
159
161
|
fname.null? ? nil : fname.read_string.force_encoding(Encoding::UTF_8)
|
|
160
162
|
end
|
|
161
163
|
|
|
164
|
+
if FFI::CApi::HAVE_SQLITE3_SERIALIZE
|
|
165
|
+
def serialize(db_name = nil)
|
|
166
|
+
require_open_db
|
|
167
|
+
|
|
168
|
+
z_schema = db_name.nil? ? nil : FFI.string_value_cstr(db_name)
|
|
169
|
+
|
|
170
|
+
size = ::FFI::MemoryPointer.new(:int64)
|
|
171
|
+
data = FFI::CApi.sqlite3_serialize(@db, z_schema, size, 0)
|
|
172
|
+
size = size.read_int64
|
|
173
|
+
|
|
174
|
+
if data.null? && size < 0
|
|
175
|
+
raise SQLite3::Exception, "unable to serialize database \"%s\"" % [z_schema || "main"]
|
|
176
|
+
end
|
|
177
|
+
if data.null? && size > 0
|
|
178
|
+
raise NoMemoryError, "failed to allocate %d bytes for serialization" % [size]
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
result = data.read_bytes(size)
|
|
182
|
+
FFI::CApi.sqlite3_free(data)
|
|
183
|
+
result
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
if FFI::CApi::HAVE_SQLITE3_DESERIALIZE && FFI::CApi.sqlite3_libversion_number >= 3054000
|
|
188
|
+
def deserialize(data, db_name = nil)
|
|
189
|
+
require_open_db
|
|
190
|
+
|
|
191
|
+
data = FFI.string_value(data)
|
|
192
|
+
z_schema = db_name.nil? ? nil : FFI.string_value_cstr(db_name)
|
|
193
|
+
sz_db = data.bytesize
|
|
194
|
+
|
|
195
|
+
sz_buf = sz_db + 20
|
|
196
|
+
p_data = FFI::CApi.sqlite3_malloc64(sz_buf)
|
|
197
|
+
if p_data.null?
|
|
198
|
+
raise NoMemoryError, "failed to allocate %d bytes for deserialization" % [sz_buf]
|
|
199
|
+
end
|
|
200
|
+
p_data.put_bytes(0, data)
|
|
201
|
+
p_data.put_bytes(sz_db, "\x00"*(sz_buf - sz_db))
|
|
202
|
+
|
|
203
|
+
status = FFI::CApi.sqlite3_deserialize(@db, z_schema, p_data, sz_db, sz_db, FFI::CApi::SQLITE_DESERIALIZE_FREEONCLOSE | FFI::CApi::SQLITE_DESERIALIZE_RESIZEABLE)
|
|
204
|
+
|
|
205
|
+
FFI.check(@db, status)
|
|
206
|
+
self
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
|
|
162
210
|
private
|
|
163
211
|
|
|
164
212
|
def require_open_db
|
|
@@ -167,6 +215,12 @@ module SQLite3
|
|
|
167
215
|
end
|
|
168
216
|
end
|
|
169
217
|
|
|
218
|
+
def require_closed_db
|
|
219
|
+
if !@db.nil?
|
|
220
|
+
raise SQLite3::Exception, "cannot open a database that is already open"
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
|
|
170
224
|
def discard_db
|
|
171
225
|
sfile = ::FFI::MemoryPointer.new(:pointer)
|
|
172
226
|
|
|
@@ -209,13 +263,28 @@ module SQLite3
|
|
|
209
263
|
end
|
|
210
264
|
|
|
211
265
|
def utf16_string_value_ptr(str)
|
|
212
|
-
str
|
|
266
|
+
str = FFI.string_value(str)
|
|
267
|
+
|
|
268
|
+
utf16str = str.dup
|
|
269
|
+
if utf16str.encoding != Encoding::UTF_16LE && utf16str.encoding != Encoding::UTF_16BE
|
|
270
|
+
utf16str.force_encoding(Encoding::UTF_16LE)
|
|
271
|
+
end
|
|
272
|
+
codepoints = utf16str.codepoints
|
|
273
|
+
if codepoints.include?(0)
|
|
274
|
+
raise ArgumentError, "string contains null char"
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
str = str.dup
|
|
278
|
+
str << 0
|
|
279
|
+
str << 0
|
|
280
|
+
str
|
|
213
281
|
end
|
|
214
282
|
|
|
215
283
|
def open_v2(file, flags, zvfs)
|
|
284
|
+
require_closed_db
|
|
216
285
|
@owner = Process.pid
|
|
217
286
|
db = ::FFI::MemoryPointer.new(:pointer)
|
|
218
|
-
status = FFI::CApi.sqlite3_open_v2(FFI.
|
|
287
|
+
status = FFI::CApi.sqlite3_open_v2(FFI.string_value_cstr(file), db, flags, zvfs.nil? ? nil : FFI.string_value_cstr(zvfs))
|
|
219
288
|
@db = db.read_pointer
|
|
220
289
|
@db = ::FFI::AutoPointer.new(db.read_pointer, FFI::CApi.method(:sqlite3_close_v2))
|
|
221
290
|
FFI.check(@db, status)
|
|
@@ -250,11 +319,20 @@ module SQLite3
|
|
|
250
319
|
end
|
|
251
320
|
|
|
252
321
|
def open16(file)
|
|
322
|
+
require_closed_db
|
|
253
323
|
@owner = Process.pid
|
|
254
324
|
db = ::FFI::MemoryPointer.new(:pointer)
|
|
255
325
|
status = FFI::CApi.sqlite3_open16(utf16_string_value_ptr(file), db)
|
|
256
326
|
@db = ::FFI::AutoPointer.new(db.read_pointer, FFI::CApi.method(:sqlite3_close_v2))
|
|
257
|
-
|
|
327
|
+
if status != FFI::CApi::SQLITE_OK
|
|
328
|
+
# https://github.com/ffi/ffi/issues/1121
|
|
329
|
+
# msg = FFI::CApi.sqlite3_mprintf("%s", :string, FFI::CApi.sqlite3_errmsg(@db))
|
|
330
|
+
# msg = ::FFI::MemoryPointer.new(:pointer).write_pointer(msg)
|
|
331
|
+
msg = FFI::CApi.sqlite3_errmsg(@db)
|
|
332
|
+
@db.free
|
|
333
|
+
@db = nil
|
|
334
|
+
FFI.check_msg(@db, status, msg)
|
|
335
|
+
end
|
|
258
336
|
status
|
|
259
337
|
end
|
|
260
338
|
|
|
@@ -87,9 +87,9 @@ module SQLite3
|
|
|
87
87
|
klass = status2klass(status)
|
|
88
88
|
return if klass.nil?
|
|
89
89
|
|
|
90
|
-
exception = klass.new(msg.read_pointer.read_string)
|
|
90
|
+
exception = klass.new(msg.is_a?(String) ? msg : msg.read_pointer.read_string)
|
|
91
91
|
exception.instance_variable_set(:@code, status)
|
|
92
|
-
CApi.sqlite3_free(msg.read_pointer)
|
|
92
|
+
CApi.sqlite3_free(msg.read_pointer) unless msg.is_a?(String)
|
|
93
93
|
|
|
94
94
|
raise exception
|
|
95
95
|
end
|
|
@@ -55,7 +55,7 @@ module SQLite3
|
|
|
55
55
|
ctx = unwrap(ctx)
|
|
56
56
|
current_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
57
57
|
if ctx.instance_variable_get(:@stmt_deadline).nil?
|
|
58
|
-
ctx.instance_variable_set(:@stmt_deadline, current_time)
|
|
58
|
+
ctx.instance_variable_set(:@stmt_deadline, current_time + ctx.instance_variable_get(:@stmt_timeout).to_i / 1000.0)
|
|
59
59
|
0
|
|
60
60
|
elsif current_time >= ctx.instance_variable_get(:@stmt_deadline)
|
|
61
61
|
1
|
data/lib/sqlite3/ffi/sqlite3.rb
CHANGED
|
@@ -4,6 +4,7 @@ module SQLite3
|
|
|
4
4
|
sql = FFI.string_value(sql)
|
|
5
5
|
|
|
6
6
|
@db = db # so can check if discarded
|
|
7
|
+
@db.instance_variable_set(:@stmt_deadline, nil)
|
|
7
8
|
db = db.instance_variable_get(:@db)
|
|
8
9
|
stmt = ::FFI::MemoryPointer.new(:pointer)
|
|
9
10
|
tail = ::FFI::MemoryPointer.new(:pointer)
|
|
@@ -11,7 +12,6 @@ module SQLite3
|
|
|
11
12
|
FFI.check_prepare(db, status, sql)
|
|
12
13
|
|
|
13
14
|
@stmt = ::FFI::AutoPointer.new(stmt.read_pointer, FFI::CApi.method(:sqlite3_finalize))
|
|
14
|
-
@db.instance_variable_set(:@stmt_deadline, nil)
|
|
15
15
|
|
|
16
16
|
tail.read_pointer.read_string.force_encoding(Encoding::UTF_8)
|
|
17
17
|
end
|
|
@@ -35,6 +35,10 @@ module SQLite3
|
|
|
35
35
|
|
|
36
36
|
stmt = @stmt
|
|
37
37
|
|
|
38
|
+
if FFI::CApi.sqlite3_stmt_busy(stmt) == 0
|
|
39
|
+
@db.instance_variable_set(:@stmt_deadline, nil)
|
|
40
|
+
end
|
|
41
|
+
|
|
38
42
|
value = FFI::CApi.sqlite3_step(stmt)
|
|
39
43
|
if FFI.rb_errinfo
|
|
40
44
|
exception = FFI.rb_errinfo
|
|
@@ -111,7 +115,7 @@ module SQLite3
|
|
|
111
115
|
if value.encoding != Encoding::UTF_8 && value.encoding != Encoding::US_ASCII
|
|
112
116
|
value = value.encode(Encoding::UTF_8)
|
|
113
117
|
end
|
|
114
|
-
status = FFI::CApi.sqlite3_bind_text(@stmt, index, value, value.bytesize, FFI::CApi::SQLITE_TRANSIENT)
|
|
118
|
+
status = FFI::CApi.sqlite3_bind_text(@stmt, index, +value, value.bytesize, FFI::CApi::SQLITE_TRANSIENT)
|
|
115
119
|
end
|
|
116
120
|
when Float
|
|
117
121
|
status = FFI::CApi.sqlite3_bind_double(@stmt, index, value)
|
|
@@ -168,7 +172,16 @@ module SQLite3
|
|
|
168
172
|
require_live_db
|
|
169
173
|
require_open_stmt
|
|
170
174
|
|
|
171
|
-
FFI::CApi.sqlite3_column_decltype(@stmt, index)
|
|
175
|
+
name = FFI::CApi.sqlite3_column_decltype(@stmt, index)
|
|
176
|
+
name ? name.force_encoding(Encoding::UTF_8) : nil
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def column_decltype_downcased(index)
|
|
180
|
+
require_live_db
|
|
181
|
+
require_open_stmt
|
|
182
|
+
|
|
183
|
+
name = FFI::CApi.sqlite3_column_decltype(@stmt, index)
|
|
184
|
+
name ? FFI.interned_downcased_utf8_cstr(name) : nil
|
|
172
185
|
end
|
|
173
186
|
|
|
174
187
|
def bind_parameter_count
|
data/lib/sqlite3/ffi/utils.rb
CHANGED
|
@@ -39,7 +39,11 @@ module SQLite3
|
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
def self.interned_utf8_cstr(str)
|
|
42
|
-
-str
|
|
42
|
+
-str.force_encoding(Encoding::UTF_8)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def self.interned_downcased_utf8_cstr(str)
|
|
46
|
+
-str.force_encoding(Encoding::UTF_8).downcase(:ascii)
|
|
43
47
|
end
|
|
44
48
|
|
|
45
49
|
def self.string_value(obj)
|
|
@@ -58,6 +62,14 @@ module SQLite3
|
|
|
58
62
|
obj.to_str
|
|
59
63
|
end
|
|
60
64
|
|
|
65
|
+
def self.string_value_cstr(obj)
|
|
66
|
+
obj = string_value(obj)
|
|
67
|
+
if obj.include?("\x00")
|
|
68
|
+
raise ArgumentError, "string contains null byte"
|
|
69
|
+
end
|
|
70
|
+
obj
|
|
71
|
+
end
|
|
72
|
+
|
|
61
73
|
RB_ERRINFO = :sqlite3_ffi_rb_errinfo
|
|
62
74
|
|
|
63
75
|
def self.rb_errinfo
|
data/lib/sqlite3/ffi/version.rb
CHANGED
data/lib/sqlite3/resultset.rb
CHANGED
|
@@ -43,20 +43,26 @@ module SQLite3
|
|
|
43
43
|
@stmt.step
|
|
44
44
|
end
|
|
45
45
|
|
|
46
|
-
#
|
|
47
|
-
#
|
|
46
|
+
# With a block given, iterates over the rows of the result set, passing each
|
|
47
|
+
# to the block. Returns self.
|
|
48
|
+
# With no block given, returns a new Enumerator.
|
|
48
49
|
def each
|
|
50
|
+
return enum_for(__method__) unless block_given?
|
|
49
51
|
while (node = self.next)
|
|
50
52
|
yield node
|
|
51
53
|
end
|
|
54
|
+
self
|
|
52
55
|
end
|
|
53
56
|
|
|
54
|
-
#
|
|
55
|
-
#
|
|
57
|
+
# With a block given, iterates over the rows of the result set, passing each
|
|
58
|
+
# to the block as a hash. Returns self.
|
|
59
|
+
# With no block given, returns a new Enumerator.
|
|
56
60
|
def each_hash
|
|
61
|
+
return enum_for(__method__) unless block_given?
|
|
57
62
|
while (node = next_hash)
|
|
58
63
|
yield node
|
|
59
64
|
end
|
|
65
|
+
self
|
|
60
66
|
end
|
|
61
67
|
|
|
62
68
|
# Closes the statement that spawned this result set.
|
data/lib/sqlite3/statement.rb
CHANGED
|
@@ -42,6 +42,24 @@ module SQLite3
|
|
|
42
42
|
# See Database#execute for a description of the valid placeholder
|
|
43
43
|
# syntaxes.
|
|
44
44
|
#
|
|
45
|
+
# Type mapping from Ruby to SQLite3:
|
|
46
|
+
# - +nil+ → NULL
|
|
47
|
+
# - Integer → INTEGER (or REAL when outside the signed int64 range)
|
|
48
|
+
# - Float → REAL
|
|
49
|
+
# - SQLite3::Blob → BLOB
|
|
50
|
+
# - String with Encoding::ASCII_8BIT
|
|
51
|
+
# (a.k.a. BINARY) → BLOB
|
|
52
|
+
# - String with Encoding::UTF_16LE
|
|
53
|
+
# or Encoding::UTF_16BE → TEXT (bound as UTF-16)
|
|
54
|
+
# - String (all other encodings) → TEXT (re-encoded to UTF-8 if needed)
|
|
55
|
+
# - Any other type → raises RuntimeError
|
|
56
|
+
#
|
|
57
|
+
# Note: a String with Encoding::ASCII_8BIT (BINARY) is always bound as a
|
|
58
|
+
# BLOB, even when its bytes are all valid ASCII. If you want such a string
|
|
59
|
+
# compared or stored as TEXT, re-encode it before binding:
|
|
60
|
+
#
|
|
61
|
+
# stmt.bind_params(my_binary_str.encode(Encoding::UTF_8))
|
|
62
|
+
#
|
|
45
63
|
# Example:
|
|
46
64
|
#
|
|
47
65
|
# stmt = db.prepare( "select * from table where a=? and b=?" )
|
|
@@ -112,9 +130,9 @@ module SQLite3
|
|
|
112
130
|
!done?
|
|
113
131
|
end
|
|
114
132
|
|
|
115
|
-
# Return
|
|
116
|
-
# may execute the statement in order to
|
|
117
|
-
# a (potentially) expensive operation.
|
|
133
|
+
# Return a frozen array of the column names for this statement, as frozen
|
|
134
|
+
# UTF-8 strings. Note that this may execute the statement in order to
|
|
135
|
+
# obtain the metadata; this makes it a (potentially) expensive operation.
|
|
118
136
|
def columns
|
|
119
137
|
get_metadata unless @columns
|
|
120
138
|
@columns
|
|
@@ -128,9 +146,11 @@ module SQLite3
|
|
|
128
146
|
end
|
|
129
147
|
end
|
|
130
148
|
|
|
131
|
-
# Return
|
|
132
|
-
#
|
|
133
|
-
#
|
|
149
|
+
# Return a frozen array of the declared types of the columns in this
|
|
150
|
+
# statement, as frozen UTF-8 strings with ASCII letters downcased. A column
|
|
151
|
+
# with no declared type, such as an expression, has a +nil+ type. Note that
|
|
152
|
+
# this may execute the statement in order to obtain the metadata; this makes
|
|
153
|
+
# it a (potentially) expensive operation.
|
|
134
154
|
def types
|
|
135
155
|
must_be_open!
|
|
136
156
|
get_metadata unless @types
|
|
@@ -180,11 +200,10 @@ module SQLite3
|
|
|
180
200
|
def get_metadata
|
|
181
201
|
@columns = Array.new(column_count) do |column|
|
|
182
202
|
column_name column
|
|
183
|
-
end
|
|
203
|
+
end.freeze
|
|
184
204
|
@types = Array.new(column_count) do |column|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
end
|
|
205
|
+
column_decltype_downcased(column)
|
|
206
|
+
end.freeze
|
|
188
207
|
end
|
|
189
208
|
end
|
|
190
209
|
end
|
data/lib/sqlite3/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: sqlite3-ffi
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jamis Buck
|
|
@@ -70,14 +70,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
70
70
|
requirements:
|
|
71
71
|
- - ">="
|
|
72
72
|
- !ruby/object:Gem::Version
|
|
73
|
-
version: '3.
|
|
73
|
+
version: '3.2'
|
|
74
74
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
75
75
|
requirements:
|
|
76
76
|
- - ">="
|
|
77
77
|
- !ruby/object:Gem::Version
|
|
78
78
|
version: '0'
|
|
79
79
|
requirements: []
|
|
80
|
-
rubygems_version: 4.0.
|
|
80
|
+
rubygems_version: 4.0.20
|
|
81
81
|
specification_version: 4
|
|
82
82
|
summary: A drop-in replacement for the sqlite3 gem for JRuby
|
|
83
83
|
test_files: []
|