distribution/vendor/github.com/go-llsqlite/adapter/crawshaw.go

102 lines
2.9 KiB
Go

//go:build !zombiezen_sqlite
package sqlite
import (
"errors"
"fmt"
sqlite "github.com/go-llsqlite/crawshaw"
)
type (
// This is only used as a pointer type because the existing APIs expect *Conn.
Conn struct {
// This can't be embedded because the underlying libraries probably won't support it.
*sqlite.Conn
}
Stmt = sqlite.Stmt
Context = sqlite.Context
Value = sqlite.Value
OpenFlags = sqlite.OpenFlags
ResultCode sqlite.ErrorCode
Blob = sqlite.Blob
)
const (
TypeNull = sqlite.SQLITE_NULL
OpenNoMutex = sqlite.SQLITE_OPEN_NOMUTEX
OpenReadOnly = sqlite.SQLITE_OPEN_READONLY
OpenURI = sqlite.SQLITE_OPEN_URI
OpenWAL = sqlite.SQLITE_OPEN_WAL
OpenCreate = sqlite.SQLITE_OPEN_CREATE
OpenReadWrite = sqlite.SQLITE_OPEN_READWRITE
OpenSharedCache = sqlite.SQLITE_OPEN_SHAREDCACHE
ResultCodeInterrupt = ResultCode(sqlite.SQLITE_INTERRUPT)
ResultCodeBusy = ResultCode(sqlite.SQLITE_BUSY)
ResultCodeAbort = ResultCode(sqlite.SQLITE_ABORT)
ResultCodeConstraintUnique = ResultCode(sqlite.SQLITE_CONSTRAINT_UNIQUE)
ResultCodeGenericError = ResultCode(sqlite.SQLITE_ERROR)
LimitLength = sqlite.SQLITE_LIMIT_LENGTH
)
var (
ErrBlobClosed = sqlite.ErrBlobClosed
)
// GoValue is a result value for application-defined functions. crawshaw provides the context result
// API, but zombiezen expects a hybrid value-type to be returned. GoValue calls out the Go part of
// this hybrid type explicitly.
type GoValue any
func BlobValue(b []byte) GoValue {
return b
}
type FunctionImpl struct {
NArgs int
Scalar func(ctx Context, args []Value) (GoValue, error)
Deterministic bool
// This is exposed in zombiezen, but I don't think I need it for my use case. If I do I'll have
// to add it to crawshaw.
//AllowIndirect bool
}
func OpenConn(path string, flags ...OpenFlags) (*Conn, error) {
crawshawConn, err := sqlite.OpenConn(path, flags...)
return &Conn{crawshawConn}, err
}
func (c *Conn) CreateFunction(name string, impl *FunctionImpl) error {
return c.Conn.CreateFunction(name, impl.Deterministic, impl.NArgs, func(context sqlite.Context, value ...sqlite.Value) {
goResValue, err := impl.Scalar(context, value)
if err != nil {
context.ResultError(err)
return
}
switch v := goResValue.(type) {
case []byte:
context.ResultBlob(v)
default:
context.ResultError(fmt.Errorf("unhandled function result type: %T", v))
}
}, nil, nil)
}
func GetResultCode(err error) (_ ResultCode, ok bool) {
var crawshawError sqlite.Error
if !errors.As(err, &crawshawError) {
// Should we attempt to extract old pkg/error style errors like crawshaw's ErrCode does
// here?
return
}
return ResultCode(crawshawError.Code), true
}
// Deprecated. This may differ from GetResultCode in that it returns SQLITE_OK if there's no error,
// and SQLITE_ERROR if there's an error, but it can't extract a sqlite error code.
var ErrCode = sqlite.ErrCode