crawshaw.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. //go:build !zombiezen_sqlite
  2. package sqlite
  3. import (
  4. "errors"
  5. "fmt"
  6. sqlite "github.com/go-llsqlite/crawshaw"
  7. )
  8. type (
  9. // This is only used as a pointer type because the existing APIs expect *Conn.
  10. Conn struct {
  11. // This can't be embedded because the underlying libraries probably won't support it.
  12. *sqlite.Conn
  13. }
  14. Stmt = sqlite.Stmt
  15. Context = sqlite.Context
  16. Value = sqlite.Value
  17. OpenFlags = sqlite.OpenFlags
  18. ResultCode sqlite.ErrorCode
  19. Blob = sqlite.Blob
  20. )
  21. const (
  22. TypeNull = sqlite.SQLITE_NULL
  23. OpenNoMutex = sqlite.SQLITE_OPEN_NOMUTEX
  24. OpenReadOnly = sqlite.SQLITE_OPEN_READONLY
  25. OpenURI = sqlite.SQLITE_OPEN_URI
  26. OpenWAL = sqlite.SQLITE_OPEN_WAL
  27. OpenCreate = sqlite.SQLITE_OPEN_CREATE
  28. OpenReadWrite = sqlite.SQLITE_OPEN_READWRITE
  29. OpenSharedCache = sqlite.SQLITE_OPEN_SHAREDCACHE
  30. ResultCodeInterrupt = ResultCode(sqlite.SQLITE_INTERRUPT)
  31. ResultCodeBusy = ResultCode(sqlite.SQLITE_BUSY)
  32. ResultCodeAbort = ResultCode(sqlite.SQLITE_ABORT)
  33. ResultCodeConstraintUnique = ResultCode(sqlite.SQLITE_CONSTRAINT_UNIQUE)
  34. ResultCodeGenericError = ResultCode(sqlite.SQLITE_ERROR)
  35. LimitLength = sqlite.SQLITE_LIMIT_LENGTH
  36. )
  37. var (
  38. ErrBlobClosed = sqlite.ErrBlobClosed
  39. )
  40. // GoValue is a result value for application-defined functions. crawshaw provides the context result
  41. // API, but zombiezen expects a hybrid value-type to be returned. GoValue calls out the Go part of
  42. // this hybrid type explicitly.
  43. type GoValue any
  44. func BlobValue(b []byte) GoValue {
  45. return b
  46. }
  47. type FunctionImpl struct {
  48. NArgs int
  49. Scalar func(ctx Context, args []Value) (GoValue, error)
  50. Deterministic bool
  51. // This is exposed in zombiezen, but I don't think I need it for my use case. If I do I'll have
  52. // to add it to crawshaw.
  53. //AllowIndirect bool
  54. }
  55. func OpenConn(path string, flags ...OpenFlags) (*Conn, error) {
  56. crawshawConn, err := sqlite.OpenConn(path, flags...)
  57. return &Conn{crawshawConn}, err
  58. }
  59. func (c *Conn) CreateFunction(name string, impl *FunctionImpl) error {
  60. return c.Conn.CreateFunction(name, impl.Deterministic, impl.NArgs, func(context sqlite.Context, value ...sqlite.Value) {
  61. goResValue, err := impl.Scalar(context, value)
  62. if err != nil {
  63. context.ResultError(err)
  64. return
  65. }
  66. switch v := goResValue.(type) {
  67. case []byte:
  68. context.ResultBlob(v)
  69. default:
  70. context.ResultError(fmt.Errorf("unhandled function result type: %T", v))
  71. }
  72. }, nil, nil)
  73. }
  74. func GetResultCode(err error) (_ ResultCode, ok bool) {
  75. var crawshawError sqlite.Error
  76. if !errors.As(err, &crawshawError) {
  77. // Should we attempt to extract old pkg/error style errors like crawshaw's ErrCode does
  78. // here?
  79. return
  80. }
  81. return ResultCode(crawshawError.Code), true
  82. }
  83. // Deprecated. This may differ from GetResultCode in that it returns SQLITE_OK if there's no error,
  84. // and SQLITE_ERROR if there's an error, but it can't extract a sqlite error code.
  85. var ErrCode = sqlite.ErrCode