1 // Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
3 // Use of this source code is governed by an MIT-style
4 // license that can be found in the LICENSE file.
8 // You can't export a Go function to C and have definitions in the C
9 // preamble in the same file, so we have to have callbackTrampoline in
10 // its own file. Because we need a separate file anyway, the support
11 // code for SQLite custom functions is in here.
14 #ifndef USE_LIBSQLITE3
15 #include <sqlite3-binding.h>
21 void _sqlite3_result_text(sqlite3_context* ctx, const char* s);
22 void _sqlite3_result_blob(sqlite3_context* ctx, const void* b, int l);
35 //export callbackTrampoline
36 func callbackTrampoline(ctx *C.sqlite3_context, argc int, argv **C.sqlite3_value) {
37 args := (*[(math.MaxInt32 - 1) / unsafe.Sizeof((*C.sqlite3_value)(nil))]*C.sqlite3_value)(unsafe.Pointer(argv))[:argc:argc]
38 fi := lookupHandle(uintptr(C.sqlite3_user_data(ctx))).(*functionInfo)
42 //export stepTrampoline
43 func stepTrampoline(ctx *C.sqlite3_context, argc C.int, argv **C.sqlite3_value) {
44 args := (*[(math.MaxInt32 - 1) / unsafe.Sizeof((*C.sqlite3_value)(nil))]*C.sqlite3_value)(unsafe.Pointer(argv))[:int(argc):int(argc)]
45 ai := lookupHandle(uintptr(C.sqlite3_user_data(ctx))).(*aggInfo)
49 //export doneTrampoline
50 func doneTrampoline(ctx *C.sqlite3_context) {
51 handle := uintptr(C.sqlite3_user_data(ctx))
52 ai := lookupHandle(handle).(*aggInfo)
56 //export compareTrampoline
57 func compareTrampoline(handlePtr uintptr, la C.int, a *C.char, lb C.int, b *C.char) C.int {
58 cmp := lookupHandle(handlePtr).(func(string, string) int)
59 return C.int(cmp(C.GoStringN(a, la), C.GoStringN(b, lb)))
62 //export commitHookTrampoline
63 func commitHookTrampoline(handle uintptr) int {
64 callback := lookupHandle(handle).(func() int)
68 //export rollbackHookTrampoline
69 func rollbackHookTrampoline(handle uintptr) {
70 callback := lookupHandle(handle).(func())
74 //export updateHookTrampoline
75 func updateHookTrampoline(handle uintptr, op int, db *C.char, table *C.char, rowid int64) {
76 callback := lookupHandle(handle).(func(int, string, string, int64))
77 callback(op, C.GoString(db), C.GoString(table), rowid)
80 //export authorizerTrampoline
81 func authorizerTrampoline(handle uintptr, op int, arg1 *C.char, arg2 *C.char, arg3 *C.char) int {
82 callback := lookupHandle(handle).(func(int, string, string, string) int)
83 return callback(op, C.GoString(arg1), C.GoString(arg2), C.GoString(arg3))
86 // Use handles to avoid passing Go pointers to C.
88 type handleVal struct {
93 var handleLock sync.Mutex
94 var handleVals = make(map[uintptr]handleVal)
95 var handleIndex uintptr = 100
97 func newHandle(db *SQLiteConn, v interface{}) uintptr {
99 defer handleLock.Unlock()
102 handleVals[i] = handleVal{db, v}
106 func lookupHandle(handle uintptr) interface{} {
108 defer handleLock.Unlock()
109 r, ok := handleVals[handle]
111 if handle >= 100 && handle < handleIndex {
112 panic("deleted handle")
114 panic("invalid handle")
120 func deleteHandles(db *SQLiteConn) {
122 defer handleLock.Unlock()
123 for handle, val := range handleVals {
125 delete(handleVals, handle)
130 // This is only here so that tests can refer to it.
131 type callbackArgRaw C.sqlite3_value
133 type callbackArgConverter func(*C.sqlite3_value) (reflect.Value, error)
135 type callbackArgCast struct {
136 f callbackArgConverter
140 func (c callbackArgCast) Run(v *C.sqlite3_value) (reflect.Value, error) {
143 return reflect.Value{}, err
145 if !val.Type().ConvertibleTo(c.typ) {
146 return reflect.Value{}, fmt.Errorf("cannot convert %s to %s", val.Type(), c.typ)
148 return val.Convert(c.typ), nil
151 func callbackArgInt64(v *C.sqlite3_value) (reflect.Value, error) {
152 if C.sqlite3_value_type(v) != C.SQLITE_INTEGER {
153 return reflect.Value{}, fmt.Errorf("argument must be an INTEGER")
155 return reflect.ValueOf(int64(C.sqlite3_value_int64(v))), nil
158 func callbackArgBool(v *C.sqlite3_value) (reflect.Value, error) {
159 if C.sqlite3_value_type(v) != C.SQLITE_INTEGER {
160 return reflect.Value{}, fmt.Errorf("argument must be an INTEGER")
162 i := int64(C.sqlite3_value_int64(v))
167 return reflect.ValueOf(val), nil
170 func callbackArgFloat64(v *C.sqlite3_value) (reflect.Value, error) {
171 if C.sqlite3_value_type(v) != C.SQLITE_FLOAT {
172 return reflect.Value{}, fmt.Errorf("argument must be a FLOAT")
174 return reflect.ValueOf(float64(C.sqlite3_value_double(v))), nil
177 func callbackArgBytes(v *C.sqlite3_value) (reflect.Value, error) {
178 switch C.sqlite3_value_type(v) {
180 l := C.sqlite3_value_bytes(v)
181 p := C.sqlite3_value_blob(v)
182 return reflect.ValueOf(C.GoBytes(p, l)), nil
184 l := C.sqlite3_value_bytes(v)
185 c := unsafe.Pointer(C.sqlite3_value_text(v))
186 return reflect.ValueOf(C.GoBytes(c, l)), nil
188 return reflect.Value{}, fmt.Errorf("argument must be BLOB or TEXT")
192 func callbackArgString(v *C.sqlite3_value) (reflect.Value, error) {
193 switch C.sqlite3_value_type(v) {
195 l := C.sqlite3_value_bytes(v)
196 p := (*C.char)(C.sqlite3_value_blob(v))
197 return reflect.ValueOf(C.GoStringN(p, l)), nil
199 c := (*C.char)(unsafe.Pointer(C.sqlite3_value_text(v)))
200 return reflect.ValueOf(C.GoString(c)), nil
202 return reflect.Value{}, fmt.Errorf("argument must be BLOB or TEXT")
206 func callbackArgGeneric(v *C.sqlite3_value) (reflect.Value, error) {
207 switch C.sqlite3_value_type(v) {
208 case C.SQLITE_INTEGER:
209 return callbackArgInt64(v)
211 return callbackArgFloat64(v)
213 return callbackArgString(v)
215 return callbackArgBytes(v)
217 // Interpret NULL as a nil byte slice.
219 return reflect.ValueOf(ret), nil
225 func callbackArg(typ reflect.Type) (callbackArgConverter, error) {
227 case reflect.Interface:
228 if typ.NumMethod() != 0 {
229 return nil, errors.New("the only supported interface type is interface{}")
231 return callbackArgGeneric, nil
233 if typ.Elem().Kind() != reflect.Uint8 {
234 return nil, errors.New("the only supported slice type is []byte")
236 return callbackArgBytes, nil
238 return callbackArgString, nil
240 return callbackArgBool, nil
242 return callbackArgInt64, nil
243 case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Int, reflect.Uint:
244 c := callbackArgCast{callbackArgInt64, typ}
246 case reflect.Float64:
247 return callbackArgFloat64, nil
248 case reflect.Float32:
249 c := callbackArgCast{callbackArgFloat64, typ}
252 return nil, fmt.Errorf("don't know how to convert to %s", typ)
256 func callbackConvertArgs(argv []*C.sqlite3_value, converters []callbackArgConverter, variadic callbackArgConverter) ([]reflect.Value, error) {
257 var args []reflect.Value
259 if len(argv) < len(converters) {
260 return nil, fmt.Errorf("function requires at least %d arguments", len(converters))
263 for i, arg := range argv[:len(converters)] {
264 v, err := converters[i](arg)
268 args = append(args, v)
272 for _, arg := range argv[len(converters):] {
273 v, err := variadic(arg)
277 args = append(args, v)
283 type callbackRetConverter func(*C.sqlite3_context, reflect.Value) error
285 func callbackRetInteger(ctx *C.sqlite3_context, v reflect.Value) error {
286 switch v.Type().Kind() {
288 case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Int, reflect.Uint:
289 v = v.Convert(reflect.TypeOf(int64(0)))
291 b := v.Interface().(bool)
293 v = reflect.ValueOf(int64(1))
295 v = reflect.ValueOf(int64(0))
298 return fmt.Errorf("cannot convert %s to INTEGER", v.Type())
301 C.sqlite3_result_int64(ctx, C.sqlite3_int64(v.Interface().(int64)))
305 func callbackRetFloat(ctx *C.sqlite3_context, v reflect.Value) error {
306 switch v.Type().Kind() {
307 case reflect.Float64:
308 case reflect.Float32:
309 v = v.Convert(reflect.TypeOf(float64(0)))
311 return fmt.Errorf("cannot convert %s to FLOAT", v.Type())
314 C.sqlite3_result_double(ctx, C.double(v.Interface().(float64)))
318 func callbackRetBlob(ctx *C.sqlite3_context, v reflect.Value) error {
319 if v.Type().Kind() != reflect.Slice || v.Type().Elem().Kind() != reflect.Uint8 {
320 return fmt.Errorf("cannot convert %s to BLOB", v.Type())
323 if i == nil || len(i.([]byte)) == 0 {
324 C.sqlite3_result_null(ctx)
327 C._sqlite3_result_blob(ctx, unsafe.Pointer(&bs[0]), C.int(len(bs)))
332 func callbackRetText(ctx *C.sqlite3_context, v reflect.Value) error {
333 if v.Type().Kind() != reflect.String {
334 return fmt.Errorf("cannot convert %s to TEXT", v.Type())
336 C._sqlite3_result_text(ctx, C.CString(v.Interface().(string)))
340 func callbackRetNil(ctx *C.sqlite3_context, v reflect.Value) error {
344 func callbackRet(typ reflect.Type) (callbackRetConverter, error) {
346 case reflect.Interface:
347 errorInterface := reflect.TypeOf((*error)(nil)).Elem()
348 if typ.Implements(errorInterface) {
349 return callbackRetNil, nil
353 if typ.Elem().Kind() != reflect.Uint8 {
354 return nil, errors.New("the only supported slice type is []byte")
356 return callbackRetBlob, nil
358 return callbackRetText, nil
359 case reflect.Bool, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Int, reflect.Uint:
360 return callbackRetInteger, nil
361 case reflect.Float32, reflect.Float64:
362 return callbackRetFloat, nil
364 return nil, fmt.Errorf("don't know how to convert to %s", typ)
368 func callbackError(ctx *C.sqlite3_context, err error) {
369 cstr := C.CString(err.Error())
370 defer C.free(unsafe.Pointer(cstr))
371 C.sqlite3_result_error(ctx, cstr, C.int(-1))
374 // Test support code. Tests are not allowed to import "C", so we can't
375 // declare any functions that use C.sqlite3_value.
376 func callbackSyntheticForTests(v reflect.Value, err error) callbackArgConverter {
377 return func(*C.sqlite3_value) (reflect.Value, error) {