本站源代码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

381 lines
11KB

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