callback.go 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  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. #include <sqlite3-binding.h>
  12. void _sqlite3_result_text(sqlite3_context* ctx, const char* s);
  13. void _sqlite3_result_blob(sqlite3_context* ctx, const void* b, int l);
  14. */
  15. import "C"
  16. import (
  17. "errors"
  18. "fmt"
  19. "reflect"
  20. "unsafe"
  21. )
  22. //export callbackTrampoline
  23. func callbackTrampoline(ctx *C.sqlite3_context, argc int, argv **C.sqlite3_value) {
  24. args := (*[1 << 30]*C.sqlite3_value)(unsafe.Pointer(argv))[:argc:argc]
  25. fi := (*functionInfo)(unsafe.Pointer(C.sqlite3_user_data(ctx)))
  26. fi.Call(ctx, args)
  27. }
  28. // This is only here so that tests can refer to it.
  29. type callbackArgRaw C.sqlite3_value
  30. type callbackArgConverter func(*C.sqlite3_value) (reflect.Value, error)
  31. type callbackArgCast struct {
  32. f callbackArgConverter
  33. typ reflect.Type
  34. }
  35. func (c callbackArgCast) Run(v *C.sqlite3_value) (reflect.Value, error) {
  36. val, err := c.f(v)
  37. if err != nil {
  38. return reflect.Value{}, err
  39. }
  40. if !val.Type().ConvertibleTo(c.typ) {
  41. return reflect.Value{}, fmt.Errorf("cannot convert %s to %s", val.Type(), c.typ)
  42. }
  43. return val.Convert(c.typ), nil
  44. }
  45. func callbackArgInt64(v *C.sqlite3_value) (reflect.Value, error) {
  46. if C.sqlite3_value_type(v) != C.SQLITE_INTEGER {
  47. return reflect.Value{}, fmt.Errorf("argument must be an INTEGER")
  48. }
  49. return reflect.ValueOf(int64(C.sqlite3_value_int64(v))), nil
  50. }
  51. func callbackArgBool(v *C.sqlite3_value) (reflect.Value, error) {
  52. if C.sqlite3_value_type(v) != C.SQLITE_INTEGER {
  53. return reflect.Value{}, fmt.Errorf("argument must be an INTEGER")
  54. }
  55. i := int64(C.sqlite3_value_int64(v))
  56. val := false
  57. if i != 0 {
  58. val = true
  59. }
  60. return reflect.ValueOf(val), nil
  61. }
  62. func callbackArgFloat64(v *C.sqlite3_value) (reflect.Value, error) {
  63. if C.sqlite3_value_type(v) != C.SQLITE_FLOAT {
  64. return reflect.Value{}, fmt.Errorf("argument must be a FLOAT")
  65. }
  66. return reflect.ValueOf(float64(C.sqlite3_value_double(v))), nil
  67. }
  68. func callbackArgBytes(v *C.sqlite3_value) (reflect.Value, error) {
  69. switch C.sqlite3_value_type(v) {
  70. case C.SQLITE_BLOB:
  71. l := C.sqlite3_value_bytes(v)
  72. p := C.sqlite3_value_blob(v)
  73. return reflect.ValueOf(C.GoBytes(p, l)), nil
  74. case C.SQLITE_TEXT:
  75. l := C.sqlite3_value_bytes(v)
  76. c := unsafe.Pointer(C.sqlite3_value_text(v))
  77. return reflect.ValueOf(C.GoBytes(c, l)), nil
  78. default:
  79. return reflect.Value{}, fmt.Errorf("argument must be BLOB or TEXT")
  80. }
  81. }
  82. func callbackArgString(v *C.sqlite3_value) (reflect.Value, error) {
  83. switch C.sqlite3_value_type(v) {
  84. case C.SQLITE_BLOB:
  85. l := C.sqlite3_value_bytes(v)
  86. p := (*C.char)(C.sqlite3_value_blob(v))
  87. return reflect.ValueOf(C.GoStringN(p, l)), nil
  88. case C.SQLITE_TEXT:
  89. c := (*C.char)(unsafe.Pointer(C.sqlite3_value_text(v)))
  90. return reflect.ValueOf(C.GoString(c)), nil
  91. default:
  92. return reflect.Value{}, fmt.Errorf("argument must be BLOB or TEXT")
  93. }
  94. }
  95. func callbackArg(typ reflect.Type) (callbackArgConverter, error) {
  96. switch typ.Kind() {
  97. case reflect.Slice:
  98. if typ.Elem().Kind() != reflect.Uint8 {
  99. return nil, errors.New("the only supported slice type is []byte")
  100. }
  101. return callbackArgBytes, nil
  102. case reflect.String:
  103. return callbackArgString, nil
  104. case reflect.Bool:
  105. return callbackArgBool, nil
  106. case reflect.Int64:
  107. return callbackArgInt64, nil
  108. case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Int, reflect.Uint:
  109. c := callbackArgCast{callbackArgInt64, typ}
  110. return c.Run, nil
  111. case reflect.Float64:
  112. return callbackArgFloat64, nil
  113. case reflect.Float32:
  114. c := callbackArgCast{callbackArgFloat64, typ}
  115. return c.Run, nil
  116. default:
  117. return nil, fmt.Errorf("don't know how to convert to %s", typ)
  118. }
  119. }
  120. type callbackRetConverter func(*C.sqlite3_context, reflect.Value) error
  121. func callbackRetInteger(ctx *C.sqlite3_context, v reflect.Value) error {
  122. switch v.Type().Kind() {
  123. case reflect.Int64:
  124. case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Int, reflect.Uint:
  125. v = v.Convert(reflect.TypeOf(int64(0)))
  126. case reflect.Bool:
  127. b := v.Interface().(bool)
  128. if b {
  129. v = reflect.ValueOf(int64(1))
  130. } else {
  131. v = reflect.ValueOf(int64(0))
  132. }
  133. default:
  134. return fmt.Errorf("cannot convert %s to INTEGER", v.Type())
  135. }
  136. C.sqlite3_result_int64(ctx, C.sqlite3_int64(v.Interface().(int64)))
  137. return nil
  138. }
  139. func callbackRetFloat(ctx *C.sqlite3_context, v reflect.Value) error {
  140. switch v.Type().Kind() {
  141. case reflect.Float64:
  142. case reflect.Float32:
  143. v = v.Convert(reflect.TypeOf(float64(0)))
  144. default:
  145. return fmt.Errorf("cannot convert %s to FLOAT", v.Type())
  146. }
  147. C.sqlite3_result_double(ctx, C.double(v.Interface().(float64)))
  148. return nil
  149. }
  150. func callbackRetBlob(ctx *C.sqlite3_context, v reflect.Value) error {
  151. if v.Type().Kind() != reflect.Slice || v.Type().Elem().Kind() != reflect.Uint8 {
  152. return fmt.Errorf("cannot convert %s to BLOB", v.Type())
  153. }
  154. i := v.Interface()
  155. if i == nil || len(i.([]byte)) == 0 {
  156. C.sqlite3_result_null(ctx)
  157. } else {
  158. bs := i.([]byte)
  159. C._sqlite3_result_blob(ctx, unsafe.Pointer(&bs[0]), C.int(len(bs)))
  160. }
  161. return nil
  162. }
  163. func callbackRetText(ctx *C.sqlite3_context, v reflect.Value) error {
  164. if v.Type().Kind() != reflect.String {
  165. return fmt.Errorf("cannot convert %s to TEXT", v.Type())
  166. }
  167. C._sqlite3_result_text(ctx, C.CString(v.Interface().(string)))
  168. return nil
  169. }
  170. func callbackRet(typ reflect.Type) (callbackRetConverter, error) {
  171. switch typ.Kind() {
  172. case reflect.Slice:
  173. if typ.Elem().Kind() != reflect.Uint8 {
  174. return nil, errors.New("the only supported slice type is []byte")
  175. }
  176. return callbackRetBlob, nil
  177. case reflect.String:
  178. return callbackRetText, nil
  179. case reflect.Bool, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Int, reflect.Uint:
  180. return callbackRetInteger, nil
  181. case reflect.Float32, reflect.Float64:
  182. return callbackRetFloat, nil
  183. default:
  184. return nil, fmt.Errorf("don't know how to convert to %s", typ)
  185. }
  186. }
  187. // Test support code. Tests are not allowed to import "C", so we can't
  188. // declare any functions that use C.sqlite3_value.
  189. func callbackSyntheticForTests(v reflect.Value, err error) callbackArgConverter {
  190. return func(*C.sqlite3_value) (reflect.Value, error) {
  191. return v, err
  192. }
  193. }