github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/mattn/go-sqlite3/callback.go (about) 1 // Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>. 2 // 3 // Use of this source code is governed by an MIT-style 4 // license that can be found in the LICENSE file. 5 6 package sqlite3 7 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. 12 13 /* 14 #include <sqlite3-binding.h> 15 #include <stdlib.h> 16 17 void _sqlite3_result_text(sqlite3_context* ctx, const char* s); 18 void _sqlite3_result_blob(sqlite3_context* ctx, const void* b, int l); 19 */ 20 import "C" 21 22 import ( 23 "errors" 24 "fmt" 25 "math" 26 "reflect" 27 "sync" 28 "unsafe" 29 ) 30 31 //export callbackTrampoline 32 func callbackTrampoline(ctx *C.sqlite3_context, argc int, argv **C.sqlite3_value) { 33 args := (*[(math.MaxInt32 - 1) / unsafe.Sizeof((*C.sqlite3_value)(nil))]*C.sqlite3_value)(unsafe.Pointer(argv))[:argc:argc] 34 fi := lookupHandle(uintptr(C.sqlite3_user_data(ctx))).(*functionInfo) 35 fi.Call(ctx, args) 36 } 37 38 //export stepTrampoline 39 func stepTrampoline(ctx *C.sqlite3_context, argc int, argv **C.sqlite3_value) { 40 args := (*[(math.MaxInt32 - 1) / unsafe.Sizeof((*C.sqlite3_value)(nil))]*C.sqlite3_value)(unsafe.Pointer(argv))[:argc:argc] 41 ai := lookupHandle(uintptr(C.sqlite3_user_data(ctx))).(*aggInfo) 42 ai.Step(ctx, args) 43 } 44 45 //export doneTrampoline 46 func doneTrampoline(ctx *C.sqlite3_context) { 47 handle := uintptr(C.sqlite3_user_data(ctx)) 48 ai := lookupHandle(handle).(*aggInfo) 49 ai.Done(ctx) 50 } 51 52 // Use handles to avoid passing Go pointers to C. 53 54 type handleVal struct { 55 db *SQLiteConn 56 val interface{} 57 } 58 59 var handleLock sync.Mutex 60 var handleVals = make(map[uintptr]handleVal) 61 var handleIndex uintptr = 100 62 63 func newHandle(db *SQLiteConn, v interface{}) uintptr { 64 handleLock.Lock() 65 defer handleLock.Unlock() 66 i := handleIndex 67 handleIndex++ 68 handleVals[i] = handleVal{db, v} 69 return i 70 } 71 72 func lookupHandle(handle uintptr) interface{} { 73 handleLock.Lock() 74 defer handleLock.Unlock() 75 r, ok := handleVals[handle] 76 if !ok { 77 if handle >= 100 && handle < handleIndex { 78 panic("deleted handle") 79 } else { 80 panic("invalid handle") 81 } 82 } 83 return r.val 84 } 85 86 func deleteHandles(db *SQLiteConn) { 87 handleLock.Lock() 88 defer handleLock.Unlock() 89 for handle, val := range handleVals { 90 if val.db == db { 91 delete(handleVals, handle) 92 } 93 } 94 } 95 96 // This is only here so that tests can refer to it. 97 type callbackArgRaw C.sqlite3_value 98 99 type callbackArgConverter func(*C.sqlite3_value) (reflect.Value, error) 100 101 type callbackArgCast struct { 102 f callbackArgConverter 103 typ reflect.Type 104 } 105 106 func (c callbackArgCast) Run(v *C.sqlite3_value) (reflect.Value, error) { 107 val, err := c.f(v) 108 if err != nil { 109 return reflect.Value{}, err 110 } 111 if !val.Type().ConvertibleTo(c.typ) { 112 return reflect.Value{}, fmt.Errorf("cannot convert %s to %s", val.Type(), c.typ) 113 } 114 return val.Convert(c.typ), nil 115 } 116 117 func callbackArgInt64(v *C.sqlite3_value) (reflect.Value, error) { 118 if C.sqlite3_value_type(v) != C.SQLITE_INTEGER { 119 return reflect.Value{}, fmt.Errorf("argument must be an INTEGER") 120 } 121 return reflect.ValueOf(int64(C.sqlite3_value_int64(v))), nil 122 } 123 124 func callbackArgBool(v *C.sqlite3_value) (reflect.Value, error) { 125 if C.sqlite3_value_type(v) != C.SQLITE_INTEGER { 126 return reflect.Value{}, fmt.Errorf("argument must be an INTEGER") 127 } 128 i := int64(C.sqlite3_value_int64(v)) 129 val := false 130 if i != 0 { 131 val = true 132 } 133 return reflect.ValueOf(val), nil 134 } 135 136 func callbackArgFloat64(v *C.sqlite3_value) (reflect.Value, error) { 137 if C.sqlite3_value_type(v) != C.SQLITE_FLOAT { 138 return reflect.Value{}, fmt.Errorf("argument must be a FLOAT") 139 } 140 return reflect.ValueOf(float64(C.sqlite3_value_double(v))), nil 141 } 142 143 func callbackArgBytes(v *C.sqlite3_value) (reflect.Value, error) { 144 switch C.sqlite3_value_type(v) { 145 case C.SQLITE_BLOB: 146 l := C.sqlite3_value_bytes(v) 147 p := C.sqlite3_value_blob(v) 148 return reflect.ValueOf(C.GoBytes(p, l)), nil 149 case C.SQLITE_TEXT: 150 l := C.sqlite3_value_bytes(v) 151 c := unsafe.Pointer(C.sqlite3_value_text(v)) 152 return reflect.ValueOf(C.GoBytes(c, l)), nil 153 default: 154 return reflect.Value{}, fmt.Errorf("argument must be BLOB or TEXT") 155 } 156 } 157 158 func callbackArgString(v *C.sqlite3_value) (reflect.Value, error) { 159 switch C.sqlite3_value_type(v) { 160 case C.SQLITE_BLOB: 161 l := C.sqlite3_value_bytes(v) 162 p := (*C.char)(C.sqlite3_value_blob(v)) 163 return reflect.ValueOf(C.GoStringN(p, l)), nil 164 case C.SQLITE_TEXT: 165 c := (*C.char)(unsafe.Pointer(C.sqlite3_value_text(v))) 166 return reflect.ValueOf(C.GoString(c)), nil 167 default: 168 return reflect.Value{}, fmt.Errorf("argument must be BLOB or TEXT") 169 } 170 } 171 172 func callbackArgGeneric(v *C.sqlite3_value) (reflect.Value, error) { 173 switch C.sqlite3_value_type(v) { 174 case C.SQLITE_INTEGER: 175 return callbackArgInt64(v) 176 case C.SQLITE_FLOAT: 177 return callbackArgFloat64(v) 178 case C.SQLITE_TEXT: 179 return callbackArgString(v) 180 case C.SQLITE_BLOB: 181 return callbackArgBytes(v) 182 case C.SQLITE_NULL: 183 // Interpret NULL as a nil byte slice. 184 var ret []byte 185 return reflect.ValueOf(ret), nil 186 default: 187 panic("unreachable") 188 } 189 } 190 191 func callbackArg(typ reflect.Type) (callbackArgConverter, error) { 192 switch typ.Kind() { 193 case reflect.Interface: 194 if typ.NumMethod() != 0 { 195 return nil, errors.New("the only supported interface type is interface{}") 196 } 197 return callbackArgGeneric, nil 198 case reflect.Slice: 199 if typ.Elem().Kind() != reflect.Uint8 { 200 return nil, errors.New("the only supported slice type is []byte") 201 } 202 return callbackArgBytes, nil 203 case reflect.String: 204 return callbackArgString, nil 205 case reflect.Bool: 206 return callbackArgBool, nil 207 case reflect.Int64: 208 return callbackArgInt64, nil 209 case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Int, reflect.Uint: 210 c := callbackArgCast{callbackArgInt64, typ} 211 return c.Run, nil 212 case reflect.Float64: 213 return callbackArgFloat64, nil 214 case reflect.Float32: 215 c := callbackArgCast{callbackArgFloat64, typ} 216 return c.Run, nil 217 default: 218 return nil, fmt.Errorf("don't know how to convert to %s", typ) 219 } 220 } 221 222 func callbackConvertArgs(argv []*C.sqlite3_value, converters []callbackArgConverter, variadic callbackArgConverter) ([]reflect.Value, error) { 223 var args []reflect.Value 224 225 if len(argv) < len(converters) { 226 return nil, fmt.Errorf("function requires at least %d arguments", len(converters)) 227 } 228 229 for i, arg := range argv[:len(converters)] { 230 v, err := converters[i](arg) 231 if err != nil { 232 return nil, err 233 } 234 args = append(args, v) 235 } 236 237 if variadic != nil { 238 for _, arg := range argv[len(converters):] { 239 v, err := variadic(arg) 240 if err != nil { 241 return nil, err 242 } 243 args = append(args, v) 244 } 245 } 246 return args, nil 247 } 248 249 type callbackRetConverter func(*C.sqlite3_context, reflect.Value) error 250 251 func callbackRetInteger(ctx *C.sqlite3_context, v reflect.Value) error { 252 switch v.Type().Kind() { 253 case reflect.Int64: 254 case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Int, reflect.Uint: 255 v = v.Convert(reflect.TypeOf(int64(0))) 256 case reflect.Bool: 257 b := v.Interface().(bool) 258 if b { 259 v = reflect.ValueOf(int64(1)) 260 } else { 261 v = reflect.ValueOf(int64(0)) 262 } 263 default: 264 return fmt.Errorf("cannot convert %s to INTEGER", v.Type()) 265 } 266 267 C.sqlite3_result_int64(ctx, C.sqlite3_int64(v.Interface().(int64))) 268 return nil 269 } 270 271 func callbackRetFloat(ctx *C.sqlite3_context, v reflect.Value) error { 272 switch v.Type().Kind() { 273 case reflect.Float64: 274 case reflect.Float32: 275 v = v.Convert(reflect.TypeOf(float64(0))) 276 default: 277 return fmt.Errorf("cannot convert %s to FLOAT", v.Type()) 278 } 279 280 C.sqlite3_result_double(ctx, C.double(v.Interface().(float64))) 281 return nil 282 } 283 284 func callbackRetBlob(ctx *C.sqlite3_context, v reflect.Value) error { 285 if v.Type().Kind() != reflect.Slice || v.Type().Elem().Kind() != reflect.Uint8 { 286 return fmt.Errorf("cannot convert %s to BLOB", v.Type()) 287 } 288 i := v.Interface() 289 if i == nil || len(i.([]byte)) == 0 { 290 C.sqlite3_result_null(ctx) 291 } else { 292 bs := i.([]byte) 293 C._sqlite3_result_blob(ctx, unsafe.Pointer(&bs[0]), C.int(len(bs))) 294 } 295 return nil 296 } 297 298 func callbackRetText(ctx *C.sqlite3_context, v reflect.Value) error { 299 if v.Type().Kind() != reflect.String { 300 return fmt.Errorf("cannot convert %s to TEXT", v.Type()) 301 } 302 C._sqlite3_result_text(ctx, C.CString(v.Interface().(string))) 303 return nil 304 } 305 306 func callbackRet(typ reflect.Type) (callbackRetConverter, error) { 307 switch typ.Kind() { 308 case reflect.Slice: 309 if typ.Elem().Kind() != reflect.Uint8 { 310 return nil, errors.New("the only supported slice type is []byte") 311 } 312 return callbackRetBlob, nil 313 case reflect.String: 314 return callbackRetText, nil 315 case reflect.Bool, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Int, reflect.Uint: 316 return callbackRetInteger, nil 317 case reflect.Float32, reflect.Float64: 318 return callbackRetFloat, nil 319 default: 320 return nil, fmt.Errorf("don't know how to convert to %s", typ) 321 } 322 } 323 324 func callbackError(ctx *C.sqlite3_context, err error) { 325 cstr := C.CString(err.Error()) 326 defer C.free(unsafe.Pointer(cstr)) 327 C.sqlite3_result_error(ctx, cstr, -1) 328 } 329 330 // Test support code. Tests are not allowed to import "C", so we can't 331 // declare any functions that use C.sqlite3_value. 332 func callbackSyntheticForTests(v reflect.Value, err error) callbackArgConverter { 333 return func(*C.sqlite3_value) (reflect.Value, error) { 334 return v, err 335 } 336 }