sqlite3 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
- ffi_lib "libsqlite3.so"
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
- # extern "int sqlite3_changes(db)"
53
- attach_function :sqlite3_changes, [:pointer], :int
54
-
55
- # extern "int sqlite3_total_changes(db)"
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
- # #extern "int sqlite3_bind_value(stmt,int,value)"
101
- attach_function :sqlite3_bind_value, [:pointer, :int, :pointer], :int
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
- # extern "int sqlite3_create_function(db,const char*,int,int,void*,void*,void*,void*)"
158
- attach_function :sqlite3_create_function, [:pointer, :string, :int, :int, :pointer, :pointer, :pointer, :pointer], :int
159
-
160
- # extern "int sqlite3_create_function16(db,const void*,int,int,void*,void*,void*,void*)"
161
- attach_function :sqlite3_create_function16, [:pointer, :pointer, :int, :int, :pointer, :pointer, :pointer, :pointer], :int
162
-
163
- # extern "int sqlite3_aggregate_count(context)"
164
- attach_function :sqlite3_aggregate_count, [:pointer], :int
165
-
166
- # extern "const void *sqlite3_value_blob(value)"
167
- attach_function :sqlite3_value_blob, [:pointer], :pointer
168
-
169
- # extern "int sqlite3_value_bytes(value)"
170
- attach_function :sqlite3_value_bytes, [:pointer], :int
171
-
172
- # extern "int sqlite3_value_bytes16(value)"
173
- attach_function :sqlite3_value_bytes16, [:pointer], :int
174
-
175
- # extern "double sqlite3_value_double(value)"
176
- attach_function :sqlite3_value_double, [:pointer], :double
177
-
178
- # extern "int sqlite3_value_int(value)"
179
- attach_function :sqlite3_value_int, [:pointer], :int
180
-
181
- # extern "int64 sqlite3_value_int64(value)"
182
- attach_function :sqlite3_value_int64, [:pointer], :int64
183
-
184
- # extern "const char* sqlite3_value_text(value)"
185
- attach_function :sqlite3_value_text, [:pointer], :string
186
-
187
- # extern "const void* sqlite3_value_text16(value)"
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
- STATIC = 0
9
- TRANSIENT = -1
8
+ TRANSIENT = ::FFI::Pointer.new(-1)
10
9
 
11
- def open(filename, utf16 = false)
10
+ def open(filename, utf_16 = false)
12
11
  handle = ::FFI::MemoryPointer.new(:pointer)
13
- result = API.send((utf16 ? :sqlite3_open16 : :sqlite3_open), filename, handle)
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, utf16 = false)
18
- if utf16
19
- msg = API.sqlite3_errmsg16(db)
20
- msg.free = nil
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, utf16 = false)
31
+ def prepare(db, sql)
28
32
  handle = ::FFI::MemoryPointer.new(:pointer)
29
33
  remainder = ::FFI::MemoryPointer.new(:pointer)
30
34
 
31
- result = API.send((utf16 ? :sqlite3_prepare16 : :sqlite3_prepare), db, sql, sql.length, handle, remainder)
32
-
33
- # TODO: UTF-16
34
- # args = utf16 ? [utf16_length(remainder)] : []
35
- # remainder = remainder.to_s(*args)
36
-
37
- [result, handle.get_pointer(0), remainder.get_pointer(0).get_string(0)]
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
- blob.free = nil
75
- blob.to_s(API.sqlite3_column_bytes(stmt, column))
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 create_function(db, name, args, text, cookie, func, step, final)
131
- # begin
132
- if @func_handler_callback.nil? && func
133
- @func_handler_callback = ::DL.callback("0PIP") do |context,nargs,args|
134
- args = args.to_s(nargs*4).unpack("L*").map {|i| ::FFI::MemoryPointer.new(i)}
135
- data = API.sqlite3_user_data(context).to_object
136
- data[:func].call(context, *args)
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 :aggregate_count
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 utf16_length(ptr)
244
- len = 0
245
- loop do
246
- break if ptr[len,1] == "\0"
247
- len += 2
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