sqlite3 0.0.0 → 0.0.1

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.
@@ -0,0 +1,262 @@
1
+ require "ffi"
2
+
3
+ module SQLite3
4
+ module Driver
5
+ module FFI
6
+
7
+ module API
8
+
9
+ extend ::FFI::Library
10
+
11
+ ffi_lib "libsqlite3.so"
12
+
13
+ # extern "const char *sqlite3_libversion()"
14
+ attach_function :sqlite3_libversion, [], :string
15
+
16
+ # extern "int sqlite3_open(const char*,db*)"
17
+ attach_function :sqlite3_open, [:string, :pointer], :int
18
+
19
+ # extern "int sqlite3_open16(const void*,db*)"
20
+ attach_function :sqlite3_open16, [:pointer, :pointer], :int
21
+
22
+ # extern "int sqlite3_close(db)"
23
+ attach_function :sqlite3_close, [:pointer], :int
24
+
25
+ # extern "const char* sqlite3_errmsg(db)"
26
+ attach_function :sqlite3_errmsg, [:pointer], :string
27
+
28
+ # extern "void* sqlite3_errmsg16(db)"
29
+ attach_function :sqlite3_errmsg16, [:pointer], :pointer
30
+
31
+ # extern "int sqlite3_errcode(db)"
32
+ attach_function :sqlite3_errcode, [:pointer], :int
33
+
34
+ # extern "int sqlite3_prepare(db,const char*,int,stmt*,const char**)"
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)"
41
+ 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)"
47
+ attach_function :sqlite3_step, [:pointer], :int
48
+
49
+ # extern "int64 sqlite3_last_insert_rowid(db)"
50
+ 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)"
71
+ 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
+ attach_function :sqlite3_bind_blob, [:pointer, :int, :pointer, :int, :pointer], :int
81
+
82
+ # extern "int sqlite3_bind_double(stmt,int,double)"
83
+ attach_function :sqlite3_bind_double, [:pointer, :int, :double], :int
84
+
85
+ # extern "int sqlite3_bind_int(stmt,int,int)"
86
+ attach_function :sqlite3_bind_int, [:pointer, :int, :int], :int
87
+
88
+ # extern "int sqlite3_bind_int64(stmt,int,int64)"
89
+ attach_function :sqlite3_bind_int64, [:pointer, :int, :int64], :int
90
+
91
+ # extern "int sqlite3_bind_null(stmt,int)"
92
+ attach_function :sqlite3_bind_null, [:pointer, :int], :int
93
+
94
+ # extern "int sqlite3_bind_text(stmt,int,const char*,int,void*)"
95
+ 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
+ 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)"
113
+ attach_function :sqlite3_column_count, [:pointer], :int
114
+
115
+ # extern "int sqlite3_data_count(stmt)"
116
+ attach_function :sqlite3_data_count, [:pointer], :int
117
+
118
+ # extern "const void *sqlite3_column_blob(stmt,int)"
119
+ attach_function :sqlite3_column_blob, [:pointer, :int], :pointer
120
+
121
+ # extern "int sqlite3_column_bytes(stmt,int)"
122
+ attach_function :sqlite3_column_bytes, [:pointer, :int], :int
123
+
124
+ # extern "int sqlite3_column_bytes16(stmt,int)"
125
+ attach_function :sqlite3_column_bytes16, [:pointer, :int], :int
126
+
127
+ # extern "const char *sqlite3_column_decltype(stmt,int)"
128
+ 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)"
134
+ 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)"
140
+ attach_function :sqlite3_column_int64, [:pointer, :int], :int64
141
+
142
+ # extern "const char *sqlite3_column_name(stmt,int)"
143
+ 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)"
149
+ attach_function :sqlite3_column_text, [:pointer, :int], :string
150
+
151
+ # extern "const void *sqlite3_column_text16(stmt,int)"
152
+ attach_function :sqlite3_column_text16, [:pointer, :int], :pointer
153
+
154
+ # extern "int sqlite3_column_type(stmt,int)"
155
+ 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
258
+ end
259
+
260
+ end
261
+ end
262
+ end
@@ -0,0 +1,255 @@
1
+ require 'sqlite3/driver/ffi/api'
2
+
3
+ module SQLite3
4
+ module Driver
5
+ module FFI
6
+
7
+ class Driver
8
+ STATIC = 0
9
+ TRANSIENT = -1
10
+
11
+ def open(filename, utf16 = false)
12
+ handle = ::FFI::MemoryPointer.new(:pointer)
13
+ result = API.send((utf16 ? :sqlite3_open16 : :sqlite3_open), filename, handle)
14
+ [result, handle.get_pointer(0)]
15
+ end
16
+
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
+ else
23
+ API.sqlite3_errmsg(db)
24
+ end
25
+ end
26
+
27
+ def prepare(db, sql, utf16 = false)
28
+ handle = ::FFI::MemoryPointer.new(:pointer)
29
+ remainder = ::FFI::MemoryPointer.new(:pointer)
30
+
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)
67
+ end
68
+
69
+ result
70
+ end
71
+
72
+ def column_blob(stmt, column)
73
+ 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)
128
+ end
129
+
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
173
+ 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
+ end
202
+
203
+ def self.api_delegate(name)
204
+ define_method(name) { |*args| API.send("sqlite3_#{name}", *args) }
205
+ end
206
+
207
+ api_delegate :aggregate_count
208
+ api_delegate :bind_double
209
+ api_delegate :bind_int
210
+ api_delegate :bind_int64
211
+ api_delegate :bind_null
212
+ api_delegate :bind_parameter_index
213
+ api_delegate :bind_parameter_name
214
+ api_delegate :busy_timeout
215
+ api_delegate :changes
216
+ api_delegate :close
217
+ api_delegate :column_bytes
218
+ api_delegate :column_bytes16
219
+ api_delegate :column_count
220
+ api_delegate :column_double
221
+ api_delegate :column_int
222
+ api_delegate :column_int64
223
+ api_delegate :column_type
224
+ api_delegate :data_count
225
+ api_delegate :errcode
226
+ api_delegate :finalize
227
+ api_delegate :interrupt
228
+ api_delegate :last_insert_rowid
229
+ api_delegate :libversion
230
+ api_delegate :reset
231
+ api_delegate :result_error
232
+ 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
240
+
241
+ private
242
+
243
+ def utf16_length(ptr)
244
+ len = 0
245
+ loop do
246
+ break if ptr[len,1] == "\0"
247
+ len += 2
248
+ end
249
+ len
250
+ end
251
+ end
252
+
253
+ end
254
+ end
255
+ end