sqlite3 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +7 -4
- data/VERSION +1 -1
- data/lib/sqlite3.rb +15 -0
- data/lib/sqlite3/database.rb +16 -339
- data/lib/sqlite3/driver/ffi/api.rb +65 -218
- data/lib/sqlite3/driver/ffi/driver.rb +141 -194
- data/lib/sqlite3/encoding.rb +43 -0
- data/lib/sqlite3/errors.rb +0 -2
- data/lib/sqlite3/pragmas.rb +0 -2
- data/lib/sqlite3/resultset.rb +8 -8
- data/lib/sqlite3/statement.rb +4 -18
- data/lib/sqlite3/translator.rb +0 -3
- data/lib/sqlite3/value.rb +0 -2
- data/test/fixtures/SQLite.gif +0 -0
- data/test/test_database_initialization.rb +25 -0
- data/test/test_database_queries_utf_16.rb +80 -0
- data/test/test_database_queries_utf_8.rb +80 -0
- metadata +18 -10
- data/test/test_database_queries.rb +0 -29
@@ -1,260 +1,107 @@
|
|
1
|
-
require "ffi"
|
2
|
-
|
3
1
|
module SQLite3
|
4
2
|
module Driver
|
5
3
|
module FFI
|
6
4
|
|
7
5
|
module API
|
8
|
-
|
9
6
|
extend ::FFI::Library
|
10
7
|
|
11
|
-
|
8
|
+
# TODO: cleanup
|
9
|
+
ffi_lib case RUBY_PLATFORM.downcase
|
10
|
+
when /darwin/
|
11
|
+
"libsqlite3.dylib"
|
12
|
+
when /linux|freebsd|netbsd|openbsd|dragonfly|solaris/
|
13
|
+
"libsqlite3.so"
|
14
|
+
when /win32/
|
15
|
+
"sqlite3.dll"
|
16
|
+
else
|
17
|
+
abort <<-EOF
|
18
|
+
==== UNSUPPORTED PLATFORM ======================================================
|
19
|
+
The platform '#{RUBY_PLATFORM}' is unsupported. Please help the author by
|
20
|
+
editing the following file to allow your sqlite3 library to be found, and
|
21
|
+
submitting a patch to qoobaa@gmail.com. Thanks!
|
22
|
+
|
23
|
+
#{__FILE__}
|
24
|
+
================================================================================
|
25
|
+
EOF
|
26
|
+
end
|
12
27
|
|
13
|
-
# extern "const char *sqlite3_libversion()"
|
14
28
|
attach_function :sqlite3_libversion, [], :string
|
15
|
-
|
16
|
-
# extern "int sqlite3_open(const char*,db*)"
|
17
29
|
attach_function :sqlite3_open, [:string, :pointer], :int
|
18
|
-
|
19
|
-
# extern "int sqlite3_open16(const void*,db*)"
|
20
30
|
attach_function :sqlite3_open16, [:pointer, :pointer], :int
|
21
|
-
|
22
|
-
# extern "int sqlite3_close(db)"
|
23
31
|
attach_function :sqlite3_close, [:pointer], :int
|
24
|
-
|
25
|
-
# extern "const char* sqlite3_errmsg(db)"
|
26
32
|
attach_function :sqlite3_errmsg, [:pointer], :string
|
27
|
-
|
28
|
-
# extern "void* sqlite3_errmsg16(db)"
|
29
33
|
attach_function :sqlite3_errmsg16, [:pointer], :pointer
|
30
|
-
|
31
|
-
# extern "int sqlite3_errcode(db)"
|
32
34
|
attach_function :sqlite3_errcode, [:pointer], :int
|
33
|
-
|
34
|
-
# extern "int sqlite3_prepare(db,const char*,int,stmt*,const char**)"
|
35
35
|
attach_function :sqlite3_prepare, [:pointer, :string, :int, :pointer, :pointer], :int
|
36
|
-
|
37
|
-
# extern "int sqlite3_prepare16(db,const void*,int,stmt*,const void**)"
|
38
|
-
attach_function :sqlite3_prepare16, [:pointer, :pointer, :int, :pointer, :pointer], :int
|
39
|
-
|
40
|
-
# extern "int sqlite3_finalize(stmt)"
|
36
|
+
# attach_function :sqlite3_prepare16, [:pointer, :pointer, :int, :pointer, :pointer], :int
|
41
37
|
attach_function :sqlite3_finalize, [:pointer], :int
|
42
|
-
|
43
|
-
# extern "int sqlite3_reset(stmt)"
|
44
|
-
attach_function :sqlite3_reset, [:pointer], :int
|
45
|
-
|
46
|
-
# extern "int sqlite3_step(stmt)"
|
38
|
+
# attach_function :sqlite3_reset, [:pointer], :int
|
47
39
|
attach_function :sqlite3_step, [:pointer], :int
|
48
|
-
|
49
|
-
# extern "int64 sqlite3_last_insert_rowid(db)"
|
50
40
|
attach_function :sqlite3_last_insert_rowid, [:pointer], :int64
|
51
|
-
|
52
|
-
#
|
53
|
-
attach_function :
|
54
|
-
|
55
|
-
#
|
56
|
-
attach_function :sqlite3_total_changes, [:pointer], :int
|
57
|
-
|
58
|
-
# extern "void sqlite3_interrupt(db)"
|
59
|
-
attach_function :sqlite3_interrupt, [:pointer], :void
|
60
|
-
|
61
|
-
# extern "ibool sqlite3_complete(const char*)"
|
62
|
-
attach_function :sqlite3_complete, [:string], :int
|
63
|
-
|
64
|
-
# extern "ibool sqlite3_complete16(const void*)"
|
65
|
-
attach_function :sqlite3_complete16, [:pointer], :int
|
66
|
-
|
67
|
-
# extern "int sqlite3_busy_handler(db,void*,void*)"
|
68
|
-
attach_function :sqlite3_busy_handler, [:pointer, :pointer, :pointer], :int
|
69
|
-
|
70
|
-
# extern "int sqlite3_busy_timeout(db,int)"
|
41
|
+
# attach_function :sqlite3_changes, [:pointer], :int
|
42
|
+
# attach_function :sqlite3_total_changes, [:pointer], :int
|
43
|
+
# attach_function :sqlite3_interrupt, [:pointer], :void
|
44
|
+
# attach_function :sqlite3_complete, [:string], :int
|
45
|
+
# attach_function :sqlite3_complete16, [:pointer], :int
|
71
46
|
attach_function :sqlite3_busy_timeout, [:pointer, :int], :int
|
72
|
-
|
73
|
-
# extern "int sqlite3_set_authorizer(db,void*,void*)"
|
74
|
-
attach_function :sqlite3_set_authorizer, [:pointer, :pointer, :pointer], :int
|
75
|
-
|
76
|
-
# extern "void* sqlite3_trace(db,void*,void*)"
|
77
|
-
attach_function :sqlite3_trace, [:pointer, :pointer, :pointer], :pointer
|
78
|
-
|
79
|
-
# extern "int sqlite3_bind_blob(stmt,int,const void*,int,void*)"
|
80
47
|
attach_function :sqlite3_bind_blob, [:pointer, :int, :pointer, :int, :pointer], :int
|
81
|
-
|
82
|
-
# extern "int sqlite3_bind_double(stmt,int,double)"
|
83
48
|
attach_function :sqlite3_bind_double, [:pointer, :int, :double], :int
|
84
|
-
|
85
|
-
# extern "int sqlite3_bind_int(stmt,int,int)"
|
86
49
|
attach_function :sqlite3_bind_int, [:pointer, :int, :int], :int
|
87
|
-
|
88
|
-
# extern "int sqlite3_bind_int64(stmt,int,int64)"
|
89
50
|
attach_function :sqlite3_bind_int64, [:pointer, :int, :int64], :int
|
90
|
-
|
91
|
-
# extern "int sqlite3_bind_null(stmt,int)"
|
92
51
|
attach_function :sqlite3_bind_null, [:pointer, :int], :int
|
93
|
-
|
94
|
-
# extern "int sqlite3_bind_text(stmt,int,const char*,int,void*)"
|
95
52
|
attach_function :sqlite3_bind_text, [:pointer, :int, :string, :int, :pointer], :int
|
96
|
-
|
97
|
-
# extern "int sqlite3_bind_text16(stmt,int,const void*,int,void*)"
|
98
53
|
attach_function :sqlite3_bind_text16, [:pointer, :int, :pointer, :int, :pointer], :int
|
99
|
-
|
100
|
-
#
|
101
|
-
attach_function :
|
102
|
-
|
103
|
-
# extern "int sqlite3_bind_parameter_count(stmt)"
|
104
|
-
attach_function :sqlite3_bind_parameter_count, [:pointer], :int
|
105
|
-
|
106
|
-
# extern "const char* sqlite3_bind_parameter_name(stmt,int)"
|
107
|
-
attach_function :sqlite3_bind_parameter_name, [:pointer, :int], :string
|
108
|
-
|
109
|
-
# extern "int sqlite3_bind_parameter_index(stmt,const char*)"
|
110
|
-
attach_function :sqlite3_bind_parameter_index, [:pointer, :string], :int
|
111
|
-
|
112
|
-
# extern "int sqlite3_column_count(stmt)"
|
54
|
+
# attach_function :sqlite3_bind_value, [:pointer, :int, :pointer], :int
|
55
|
+
# attach_function :sqlite3_bind_parameter_count, [:pointer], :int
|
56
|
+
# attach_function :sqlite3_bind_parameter_name, [:pointer, :int], :string
|
57
|
+
# attach_function :sqlite3_bind_parameter_index, [:pointer, :string], :int
|
113
58
|
attach_function :sqlite3_column_count, [:pointer], :int
|
114
|
-
|
115
|
-
# extern "int sqlite3_data_count(stmt)"
|
116
59
|
attach_function :sqlite3_data_count, [:pointer], :int
|
117
|
-
|
118
|
-
# extern "const void *sqlite3_column_blob(stmt,int)"
|
119
60
|
attach_function :sqlite3_column_blob, [:pointer, :int], :pointer
|
120
|
-
|
121
|
-
# extern "int sqlite3_column_bytes(stmt,int)"
|
122
61
|
attach_function :sqlite3_column_bytes, [:pointer, :int], :int
|
123
|
-
|
124
|
-
# extern "int sqlite3_column_bytes16(stmt,int)"
|
125
62
|
attach_function :sqlite3_column_bytes16, [:pointer, :int], :int
|
126
|
-
|
127
|
-
# extern "const char *sqlite3_column_decltype(stmt,int)"
|
128
63
|
attach_function :sqlite3_column_decltype, [:pointer, :int], :string
|
129
|
-
|
130
|
-
# extern "void *sqlite3_column_decltype16(stmt,int)"
|
131
|
-
attach_function :sqlite3_column_decltype16, [:pointer, :int], :pointer
|
132
|
-
|
133
|
-
# extern "double sqlite3_column_double(stmt,int)"
|
64
|
+
# attach_function :sqlite3_column_decltype16, [:pointer, :int], :pointer
|
134
65
|
attach_function :sqlite3_column_double, [:pointer, :int], :double
|
135
|
-
|
136
|
-
# extern "int sqlite3_column_int(stmt,int)"
|
137
|
-
attach_function :sqlite3_column_int, [:pointer, :int], :int
|
138
|
-
|
139
|
-
# extern "int64 sqlite3_column_int64(stmt,int)"
|
66
|
+
# attach_function :sqlite3_column_int, [:pointer, :int], :int
|
140
67
|
attach_function :sqlite3_column_int64, [:pointer, :int], :int64
|
141
|
-
|
142
|
-
# extern "const char *sqlite3_column_name(stmt,int)"
|
143
68
|
attach_function :sqlite3_column_name, [:pointer, :int], :string
|
144
|
-
|
145
|
-
# extern "const void *sqlite3_column_name16(stmt,int)"
|
146
|
-
attach_function :sqlite3_column_name16, [:pointer, :int], :pointer
|
147
|
-
|
148
|
-
# extern "const char *sqlite3_column_text(stmt,int)"
|
69
|
+
# attach_function :sqlite3_column_name16, [:pointer, :int], :pointer
|
149
70
|
attach_function :sqlite3_column_text, [:pointer, :int], :string
|
150
|
-
|
151
|
-
# extern "const void *sqlite3_column_text16(stmt,int)"
|
152
71
|
attach_function :sqlite3_column_text16, [:pointer, :int], :pointer
|
153
|
-
|
154
|
-
# extern "int sqlite3_column_type(stmt,int)"
|
155
72
|
attach_function :sqlite3_column_type, [:pointer, :int], :int
|
156
|
-
|
157
|
-
#
|
158
|
-
attach_function :
|
159
|
-
|
160
|
-
#
|
161
|
-
attach_function :
|
162
|
-
|
163
|
-
#
|
164
|
-
attach_function :
|
165
|
-
|
166
|
-
#
|
167
|
-
attach_function :
|
168
|
-
|
169
|
-
#
|
170
|
-
attach_function :
|
171
|
-
|
172
|
-
#
|
173
|
-
attach_function :
|
174
|
-
|
175
|
-
#
|
176
|
-
attach_function :
|
177
|
-
|
178
|
-
#
|
179
|
-
attach_function :
|
180
|
-
|
181
|
-
#
|
182
|
-
attach_function :
|
183
|
-
|
184
|
-
#
|
185
|
-
attach_function :
|
186
|
-
|
187
|
-
#
|
188
|
-
attach_function :sqlite3_value_text16, [:pointer], :pointer
|
189
|
-
|
190
|
-
# extern "const void* sqlite3_value_text16le(value)"
|
191
|
-
attach_function :sqlite3_value_text16le, [:pointer], :pointer
|
192
|
-
|
193
|
-
# extern "const void* sqlite3_value_text16be(value)"
|
194
|
-
attach_function :sqlite3_value_text16be, [:pointer], :pointer
|
195
|
-
|
196
|
-
# extern "int sqlite3_value_type(value)"
|
197
|
-
attach_function :sqlite3_value_type, [:pointer], :int
|
198
|
-
|
199
|
-
# extern "void *sqlite3_aggregate_context(context,int)"
|
200
|
-
attach_function :sqlite3_aggregate_context, [:pointer, :int], :pointer
|
201
|
-
|
202
|
-
# extern "void *sqlite3_user_data(context)"
|
203
|
-
attach_function :sqlite3_user_data, [:pointer], :pointer
|
204
|
-
|
205
|
-
# extern "void *sqlite3_get_auxdata(context,int)"
|
206
|
-
attach_function :sqlite3_get_auxdata, [:pointer, :int], :pointer
|
207
|
-
|
208
|
-
# extern "void sqlite3_set_auxdata(context,int,void*,void*)"
|
209
|
-
attach_function :sqlite3_set_auxdata, [:pointer, :int, :pointer, :pointer], :void
|
210
|
-
|
211
|
-
# extern "void sqlite3_result_blob(context,const void*,int,void*)"
|
212
|
-
attach_function :sqlite3_result_blob, [:pointer, :pointer, :int, :pointer], :void
|
213
|
-
|
214
|
-
# extern "void sqlite3_result_double(context,double)"
|
215
|
-
attach_function :sqlite3_result_double, [:pointer, :double], :void
|
216
|
-
|
217
|
-
# extern "void sqlite3_result_error(context,const char*,int)"
|
218
|
-
attach_function :sqlite3_result_error, [:pointer, :string, :int], :void
|
219
|
-
|
220
|
-
# extern "void sqlite3_result_error16(context,const void*,int)"
|
221
|
-
attach_function :sqlite3_result_error16, [:pointer, :pointer, :int], :void
|
222
|
-
|
223
|
-
# extern "void sqlite3_result_int(context,int)"
|
224
|
-
attach_function :sqlite3_result_int, [:pointer, :int], :void
|
225
|
-
|
226
|
-
# extern "void sqlite3_result_int64(context,int64)"
|
227
|
-
attach_function :sqlite3_result_int64, [:pointer, :int64], :void
|
228
|
-
|
229
|
-
# extern "void sqlite3_result_null(context)"
|
230
|
-
attach_function :sqlite3_result_null, [:pointer], :void
|
231
|
-
|
232
|
-
# extern "void sqlite3_result_text(context,const char*,int,void*)"
|
233
|
-
attach_function :sqlite3_result_text, [:pointer, :string, :int, :pointer], :void
|
234
|
-
|
235
|
-
# extern "void sqlite3_result_text16(context,const void*,int,void*)"
|
236
|
-
attach_function :sqlite3_result_text16, [:pointer, :pointer, :int, :pointer], :void
|
237
|
-
|
238
|
-
# extern "void sqlite3_result_text16le(context,const void*,int,void*)"
|
239
|
-
attach_function :sqlite3_result_text16le, [:pointer, :pointer, :int, :pointer], :void
|
240
|
-
|
241
|
-
# extern "void sqlite3_result_text16be(context,const void*,int,void*)"
|
242
|
-
attach_function :sqlite3_result_text16be, [:pointer, :pointer, :int, :pointer], :void
|
243
|
-
|
244
|
-
# extern "void sqlite3_result_value(context,value)"
|
245
|
-
attach_function :sqlite3_result_value, [:pointer, :pointer], :void
|
246
|
-
|
247
|
-
# extern "int sqlite3_create_collation(db,const char*,int,void*,void*)"
|
248
|
-
attach_function :sqlite3_create_collation, [:pointer, :string, :int, :pointer, :pointer], :int
|
249
|
-
|
250
|
-
# extern "int sqlite3_create_collation16(db,const char*,int,void*,void*)"
|
251
|
-
attach_function :sqlite3_create_collation16, [:pointer, :string, :int, :pointer, :pointer], :int
|
252
|
-
|
253
|
-
# extern "int sqlite3_collation_needed(db,void*,void*)"
|
254
|
-
attach_function :sqlite3_collation_needed, [:pointer, :pointer, :pointer], :int
|
255
|
-
|
256
|
-
# extern "int sqlite3_collation_needed16(db,void*,void*)"
|
257
|
-
attach_function :sqlite3_collation_needed16, [:pointer, :pointer, :pointer], :int
|
73
|
+
# attach_function :sqlite3_aggregate_count, [:pointer], :int
|
74
|
+
# attach_function :sqlite3_value_blob, [:pointer], :pointer
|
75
|
+
# attach_function :sqlite3_value_bytes, [:pointer], :int
|
76
|
+
# attach_function :sqlite3_value_bytes16, [:pointer], :int
|
77
|
+
# attach_function :sqlite3_value_double, [:pointer], :double
|
78
|
+
# attach_function :sqlite3_value_int, [:pointer], :int
|
79
|
+
# attach_function :sqlite3_value_int64, [:pointer], :int64
|
80
|
+
# attach_function :sqlite3_value_text, [:pointer], :string
|
81
|
+
# attach_function :sqlite3_value_text16, [:pointer], :pointer
|
82
|
+
# attach_function :sqlite3_value_text16le, [:pointer], :pointer
|
83
|
+
# attach_function :sqlite3_value_text16be, [:pointer], :pointer
|
84
|
+
# attach_function :sqlite3_value_type, [:pointer], :int
|
85
|
+
# attach_function :sqlite3_aggregate_context, [:pointer, :int], :pointer
|
86
|
+
# attach_function :sqlite3_user_data, [:pointer], :pointer
|
87
|
+
# attach_function :sqlite3_get_auxdata, [:pointer, :int], :pointer
|
88
|
+
# attach_function :sqlite3_set_auxdata, [:pointer, :int, :pointer, :pointer], :void
|
89
|
+
# attach_function :sqlite3_result_blob, [:pointer, :pointer, :int, :pointer], :void
|
90
|
+
# attach_function :sqlite3_result_double, [:pointer, :double], :void
|
91
|
+
# attach_function :sqlite3_result_error, [:pointer, :string, :int], :void
|
92
|
+
# attach_function :sqlite3_result_error16, [:pointer, :pointer, :int], :void
|
93
|
+
# attach_function :sqlite3_result_int, [:pointer, :int], :void
|
94
|
+
# attach_function :sqlite3_result_int64, [:pointer, :int64], :void
|
95
|
+
# attach_function :sqlite3_result_null, [:pointer], :void
|
96
|
+
# attach_function :sqlite3_result_text, [:pointer, :string, :int, :pointer], :void
|
97
|
+
# attach_function :sqlite3_result_text16, [:pointer, :pointer, :int, :pointer], :void
|
98
|
+
# attach_function :sqlite3_result_text16le, [:pointer, :pointer, :int, :pointer], :void
|
99
|
+
# attach_function :sqlite3_result_text16be, [:pointer, :pointer, :int, :pointer], :void
|
100
|
+
# attach_function :sqlite3_result_value, [:pointer, :pointer], :void
|
101
|
+
# attach_function :sqlite3_create_collation, [:pointer, :string, :int, :pointer, :pointer], :int
|
102
|
+
# attach_function :sqlite3_create_collation16, [:pointer, :string, :int, :pointer, :pointer], :int
|
103
|
+
# attach_function :sqlite3_collation_needed, [:pointer, :pointer, :pointer], :int
|
104
|
+
# attach_function :sqlite3_collation_needed16, [:pointer, :pointer, :pointer], :int
|
258
105
|
end
|
259
106
|
|
260
107
|
end
|
@@ -5,206 +5,140 @@ module SQLite3
|
|
5
5
|
module FFI
|
6
6
|
|
7
7
|
class Driver
|
8
|
-
|
9
|
-
TRANSIENT = -1
|
8
|
+
TRANSIENT = ::FFI::Pointer.new(-1)
|
10
9
|
|
11
|
-
def open(filename,
|
10
|
+
def open(filename, utf_16 = false)
|
12
11
|
handle = ::FFI::MemoryPointer.new(:pointer)
|
13
|
-
|
12
|
+
if utf_16
|
13
|
+
filename = filename.encode(Encoding.utf_16native)
|
14
|
+
result = API.sqlite3_open16(c_string(filename), handle)
|
15
|
+
else
|
16
|
+
filename = filename.encode(Encoding.utf_8)
|
17
|
+
result = API.sqlite3_open(filename, handle)
|
18
|
+
end
|
14
19
|
[result, handle.get_pointer(0)]
|
15
20
|
end
|
16
21
|
|
17
|
-
def errmsg(db,
|
18
|
-
if
|
19
|
-
|
20
|
-
|
21
|
-
msg.to_s(utf16_length(msg))
|
22
|
+
def errmsg(db, utf_16 = false)
|
23
|
+
if utf_16
|
24
|
+
ptr = API.sqlite3_errmsg16(db)
|
25
|
+
get_string_utf_16(ptr).force_encoding(Encoding.utf_16native)
|
22
26
|
else
|
23
|
-
API.sqlite3_errmsg(db)
|
27
|
+
API.sqlite3_errmsg(db).force_encoding(Encoding.utf_8)
|
24
28
|
end
|
25
29
|
end
|
26
30
|
|
27
|
-
def prepare(db, sql
|
31
|
+
def prepare(db, sql)
|
28
32
|
handle = ::FFI::MemoryPointer.new(:pointer)
|
29
33
|
remainder = ::FFI::MemoryPointer.new(:pointer)
|
30
34
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
end
|
39
|
-
|
40
|
-
def complete?(sql, utf16 = false)
|
41
|
-
API.send(utf16 ? :sqlite3_complete16 : :sqlite3_complete, sql)
|
42
|
-
end
|
43
|
-
|
44
|
-
def value_blob(value)
|
45
|
-
blob = API.sqlite3_value_blob(value)
|
46
|
-
blob.free = nil
|
47
|
-
blob.to_s(API.sqlite3_value_bytes(value))
|
48
|
-
end
|
49
|
-
|
50
|
-
def value_text(value, utf16 = false)
|
51
|
-
method = case utf16
|
52
|
-
when nil, false
|
53
|
-
:sqlite3_value_text
|
54
|
-
when :le
|
55
|
-
:sqlite3_value_text16le
|
56
|
-
when :be
|
57
|
-
:sqlite3_value_text16be
|
58
|
-
else
|
59
|
-
:sqlite3_value_text16
|
60
|
-
end
|
61
|
-
|
62
|
-
result = API.send(method, value)
|
63
|
-
if utf16
|
64
|
-
result.free = nil
|
65
|
-
size = API.sqlite3_value_bytes(value)
|
66
|
-
result = result.to_s(size)
|
35
|
+
if Encoding.utf_16?(sql)
|
36
|
+
str = c_string(sql)
|
37
|
+
result = API.sqlite3_prepare16(db, str, str.bytesize, handle, remainder)
|
38
|
+
remainder_string = get_string_utf_16(remainder.get_pointer(0))
|
39
|
+
else
|
40
|
+
result = API.sqlite3_prepare(db, sql, sql.bytesize, handle, remainder)
|
41
|
+
remainder_string = remainder.get_pointer(0).get_string(0)
|
67
42
|
end
|
68
43
|
|
69
|
-
result
|
44
|
+
[result, handle.get_pointer(0), remainder_string]
|
45
|
+
end
|
46
|
+
|
47
|
+
# def complete?(sql)
|
48
|
+
# API.send(utf16?(string) ? :sqlite3_complete16 : :sqlite3_complete, sql)
|
49
|
+
# end
|
50
|
+
|
51
|
+
# def value_blob(value)
|
52
|
+
# blob = API.sqlite3_value_blob(value)
|
53
|
+
# # blob.free = nil
|
54
|
+
# blob.to_s(API.sqlite3_value_bytes(value))
|
55
|
+
# end
|
56
|
+
|
57
|
+
# def value_text(value)
|
58
|
+
# method = case utf16
|
59
|
+
# when nil, false
|
60
|
+
# :sqlite3_value_text
|
61
|
+
# when :le
|
62
|
+
# :sqlite3_value_text16le
|
63
|
+
# when :be
|
64
|
+
# :sqlite3_value_text16be
|
65
|
+
# else
|
66
|
+
# :sqlite3_value_text16
|
67
|
+
# end
|
68
|
+
|
69
|
+
# result = API.send(method, value)
|
70
|
+
|
71
|
+
# if utf16
|
72
|
+
# # result.free = nil
|
73
|
+
# size = API.sqlite3_value_bytes(value)
|
74
|
+
# result = result.to_s(size)
|
75
|
+
# end
|
76
|
+
|
77
|
+
# result
|
78
|
+
# end
|
79
|
+
|
80
|
+
# def result_text(func, text)
|
81
|
+
# method = case utf16
|
82
|
+
# when false, nil
|
83
|
+
# :sqlite3_result_text
|
84
|
+
# when :le
|
85
|
+
# :sqlite3_result_text16le
|
86
|
+
# when :be
|
87
|
+
# :sqlite3_result_text16be
|
88
|
+
# else
|
89
|
+
# :sqlite3_result_text16
|
90
|
+
# end
|
91
|
+
|
92
|
+
# s = text.to_s
|
93
|
+
# API.send(method, func, s, s.length, TRANSIENT)
|
94
|
+
# end
|
95
|
+
|
96
|
+
# def aggregate_context(context)
|
97
|
+
# ptr = API.sqlite3_aggregate_context(context, 4)
|
98
|
+
# ptr.free = nil
|
99
|
+
# obj = (ptr ? ptr.to_object : nil)
|
100
|
+
# if obj.nil?
|
101
|
+
# obj = Hash.new
|
102
|
+
# ptr.set_object obj
|
103
|
+
# end
|
104
|
+
# obj
|
105
|
+
# end
|
106
|
+
|
107
|
+
def bind_string(stmt, index, value)
|
108
|
+
case value.encoding
|
109
|
+
when Encoding.utf_8, Encoding.us_ascii
|
110
|
+
API.sqlite3_bind_text(stmt, index, value, value.bytesize, TRANSIENT)
|
111
|
+
when Encoding.utf_16le, Encoding.utf_16be
|
112
|
+
value = add_byte_order_mask(value)
|
113
|
+
API.sqlite3_bind_text16(stmt, index, value, value.bytesize, TRANSIENT)
|
114
|
+
else
|
115
|
+
API.sqlite3_bind_blob(stmt, index, value, value.bytesize, TRANSIENT)
|
116
|
+
end
|
70
117
|
end
|
71
118
|
|
72
119
|
def column_blob(stmt, column)
|
73
120
|
blob = API.sqlite3_column_blob(stmt, column)
|
74
|
-
|
75
|
-
blob.
|
76
|
-
end
|
77
|
-
|
78
|
-
def result_text(func, text, utf16 = false)
|
79
|
-
method = case utf16
|
80
|
-
when false, nil
|
81
|
-
:sqlite3_result_text
|
82
|
-
when :le
|
83
|
-
:sqlite3_result_text16le
|
84
|
-
when :be
|
85
|
-
:sqlite3_result_text16be
|
86
|
-
else
|
87
|
-
:sqlite3_result_text16
|
88
|
-
end
|
89
|
-
|
90
|
-
s = text.to_s
|
91
|
-
API.send(method, func, s, s.length, TRANSIENT)
|
92
|
-
end
|
93
|
-
|
94
|
-
def busy_handler(db, data = nil, &block)
|
95
|
-
@busy_handler = block
|
96
|
-
|
97
|
-
unless @busy_handler_callback
|
98
|
-
@busy_handler_callback = ::DL.callback("IPI") do |cookie, timeout|
|
99
|
-
@busy_handler.call(cookie, timeout) || 0
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
API.sqlite3_busy_handler(db, block&&@busy_handler_callback, data)
|
104
|
-
end
|
105
|
-
|
106
|
-
def set_authorizer(db, data = nil, &block)
|
107
|
-
@authorizer_handler = block
|
108
|
-
|
109
|
-
unless @authorizer_handler_callback
|
110
|
-
@authorizer_handler_callback = ::DL.callback("IPIPPPP") do |cookie,mode,a,b,c,d|
|
111
|
-
@authorizer_handler.call(cookie, mode, a&&a.to_s, b&&b.to_s, c&&c.to_s, d&&d.to_s) || 0
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
API.sqlite3_set_authorizer(db, block&&@authorizer_handler_callback, data)
|
116
|
-
end
|
117
|
-
|
118
|
-
def trace(db, data = nil, &block)
|
119
|
-
@trace_handler = block
|
120
|
-
|
121
|
-
unless @trace_handler_callback
|
122
|
-
@trace_handler_callback = ::DL.callback("IPS") do |cookie,sql|
|
123
|
-
@trace_handler.call(cookie ? cookie.to_object : nil, sql) || 0
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
API.sqlite3_trace(db, block&&@trace_handler_callback, data)
|
121
|
+
length = API.sqlite3_column_bytes(stmt, column)
|
122
|
+
blob.get_bytes(0, length) # free?
|
128
123
|
end
|
129
124
|
|
130
|
-
def
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
if @step_handler_callback.nil? && step
|
141
|
-
@step_handler_callback = ::DL.callback("0PIP") do |context,nargs,args|
|
142
|
-
args = args.to_s(nargs*4).unpack("L*").map {|i| ::FFI::MemoryPointer.new(i)}
|
143
|
-
data = API.sqlite3_user_data(context).to_object
|
144
|
-
data[:step].call(context, *args)
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
if @final_handler_callback.nil? && final
|
149
|
-
@final_handler_callback = ::DL.callback("0P") do |context|
|
150
|
-
data = API.sqlite3_user_data(context).to_object
|
151
|
-
data[:final].call(context)
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
data = {
|
156
|
-
:cookie => cookie,
|
157
|
-
:name => name,
|
158
|
-
:func => func,
|
159
|
-
:step => step,
|
160
|
-
:final => final
|
161
|
-
}
|
162
|
-
|
163
|
-
API.sqlite3_create_function(db, name, args, text, data, (func ? @func_handler_callback : nil), (step ? @step_handler_callback : nil), (final ? @final_handler_callback : nil))
|
164
|
-
end
|
165
|
-
|
166
|
-
def aggregate_context(context)
|
167
|
-
ptr = API.sqlite3_aggregate_context(context, 4)
|
168
|
-
ptr.free = nil
|
169
|
-
obj = (ptr ? ptr.to_object : nil)
|
170
|
-
if obj.nil?
|
171
|
-
obj = Hash.new
|
172
|
-
ptr.set_object obj
|
125
|
+
def column_text(stmt, column, utf_16 = false)
|
126
|
+
if utf_16
|
127
|
+
ptr = API.sqlite3_column_text16(stmt, column)
|
128
|
+
length = API.sqlite3_column_bytes16(stmt, column)
|
129
|
+
ptr.get_bytes(0, length).force_encoding(Encoding.utf_16native) # free?
|
130
|
+
else
|
131
|
+
API.sqlite3_column_text(stmt, column).force_encoding(Encoding.utf_8)
|
173
132
|
end
|
174
|
-
obj
|
175
|
-
end
|
176
|
-
|
177
|
-
def bind_blob(stmt, index, value)
|
178
|
-
s = value.to_s
|
179
|
-
API.sqlite3_bind_blob(stmt, index, s, s.length, TRANSIENT)
|
180
|
-
end
|
181
|
-
|
182
|
-
def bind_text(stmt, index, value, utf16 = false)
|
183
|
-
s = value.to_s
|
184
|
-
method = (utf16 ? :sqlite3_bind_text16 : :sqlite3_bind_text)
|
185
|
-
API.send(method, stmt, index, s, s.length, TRANSIENT)
|
186
|
-
end
|
187
|
-
|
188
|
-
def column_text(stmt, column)
|
189
|
-
result = API.sqlite3_column_text(stmt, column)
|
190
|
-
result ? result.to_s : nil
|
191
|
-
end
|
192
|
-
|
193
|
-
def column_name(stmt, column)
|
194
|
-
result = API.sqlite3_column_name(stmt, column)
|
195
|
-
result ? result.to_s : nil
|
196
|
-
end
|
197
|
-
|
198
|
-
def column_decltype(stmt, column)
|
199
|
-
result = API.sqlite3_column_decltype(stmt, column)
|
200
|
-
result ? result.to_s : nil
|
201
133
|
end
|
202
134
|
|
203
135
|
def self.api_delegate(name)
|
204
136
|
define_method(name) { |*args| API.send("sqlite3_#{name}", *args) }
|
205
137
|
end
|
206
138
|
|
207
|
-
api_delegate :
|
139
|
+
api_delegate :column_name
|
140
|
+
api_delegate :column_decltype
|
141
|
+
# api_delegate :aggregate_count
|
208
142
|
api_delegate :bind_double
|
209
143
|
api_delegate :bind_int
|
210
144
|
api_delegate :bind_int64
|
@@ -212,44 +146,57 @@ module SQLite3
|
|
212
146
|
api_delegate :bind_parameter_index
|
213
147
|
api_delegate :bind_parameter_name
|
214
148
|
api_delegate :busy_timeout
|
215
|
-
api_delegate :changes
|
149
|
+
# api_delegate :changes
|
216
150
|
api_delegate :close
|
217
|
-
api_delegate :column_bytes
|
218
|
-
api_delegate :column_bytes16
|
151
|
+
# api_delegate :column_bytes
|
152
|
+
# api_delegate :column_bytes16
|
219
153
|
api_delegate :column_count
|
220
154
|
api_delegate :column_double
|
221
|
-
api_delegate :column_int
|
155
|
+
# api_delegate :column_int
|
222
156
|
api_delegate :column_int64
|
223
157
|
api_delegate :column_type
|
224
158
|
api_delegate :data_count
|
225
159
|
api_delegate :errcode
|
226
160
|
api_delegate :finalize
|
227
|
-
api_delegate :interrupt
|
161
|
+
# api_delegate :interrupt
|
228
162
|
api_delegate :last_insert_rowid
|
229
163
|
api_delegate :libversion
|
230
|
-
api_delegate :reset
|
231
|
-
api_delegate :result_error
|
164
|
+
# api_delegate :reset
|
165
|
+
# api_delegate :result_error
|
232
166
|
api_delegate :step
|
233
|
-
api_delegate :total_changes
|
234
|
-
api_delegate :value_bytes
|
235
|
-
api_delegate :value_bytes16
|
236
|
-
api_delegate :value_double
|
237
|
-
api_delegate :value_int
|
238
|
-
api_delegate :value_int64
|
239
|
-
api_delegate :value_type
|
167
|
+
# api_delegate :total_changes
|
168
|
+
# api_delegate :value_bytes
|
169
|
+
# api_delegate :value_bytes16
|
170
|
+
# api_delegate :value_double
|
171
|
+
# api_delegate :value_int
|
172
|
+
# api_delegate :value_int64
|
173
|
+
# api_delegate :value_type
|
240
174
|
|
241
175
|
private
|
242
176
|
|
243
|
-
def
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
177
|
+
def c_string(string)
|
178
|
+
if Encoding.utf_16?(string)
|
179
|
+
result = add_byte_order_mask(string)
|
180
|
+
terminate_string!(result)
|
181
|
+
else
|
182
|
+
string # FFI does the job
|
248
183
|
end
|
249
|
-
len
|
250
184
|
end
|
251
|
-
end
|
252
185
|
|
186
|
+
def add_byte_order_mask(string)
|
187
|
+
"\uFEFF".encode(string.encoding) + string
|
188
|
+
end
|
189
|
+
|
190
|
+
def terminate_string!(string)
|
191
|
+
string << "\0\0".force_encoding(string.encoding)
|
192
|
+
end
|
193
|
+
|
194
|
+
def get_string_utf_16(ptr)
|
195
|
+
length = 0
|
196
|
+
length += 2 until ptr.get_bytes(length, 2) == "\0\0"
|
197
|
+
ptr.get_bytes(0, length)
|
198
|
+
end
|
199
|
+
end
|
253
200
|
end
|
254
201
|
end
|
255
202
|
end
|