sqlite3 0.0.0 → 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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