123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671 |
- // Copyright 2017 The Sqlite Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- //go:generate go run generator.go -full-path-comments
- package sqlite // import "modernc.org/sqlite"
- import (
- "context"
- "database/sql"
- "database/sql/driver"
- "fmt"
- "io"
- "math"
- "net/url"
- "reflect"
- "strconv"
- "strings"
- "sync"
- "sync/atomic"
- "time"
- "unsafe"
- "modernc.org/libc"
- "modernc.org/libc/sys/types"
- sqlite3 "modernc.org/sqlite/lib"
- )
- var (
- _ driver.Conn = (*conn)(nil)
- _ driver.Driver = (*Driver)(nil)
- //lint:ignore SA1019 TODO implement ExecerContext
- _ driver.Execer = (*conn)(nil)
- //lint:ignore SA1019 TODO implement QueryerContext
- _ driver.Queryer = (*conn)(nil)
- _ driver.Result = (*result)(nil)
- _ driver.Rows = (*rows)(nil)
- _ driver.RowsColumnTypeDatabaseTypeName = (*rows)(nil)
- _ driver.RowsColumnTypeLength = (*rows)(nil)
- _ driver.RowsColumnTypeNullable = (*rows)(nil)
- _ driver.RowsColumnTypePrecisionScale = (*rows)(nil)
- _ driver.RowsColumnTypeScanType = (*rows)(nil)
- _ driver.Stmt = (*stmt)(nil)
- _ driver.Tx = (*tx)(nil)
- _ error = (*Error)(nil)
- )
- const (
- driverName = "sqlite"
- ptrSize = unsafe.Sizeof(uintptr(0))
- sqliteLockedSharedcache = sqlite3.SQLITE_LOCKED | (1 << 8)
- )
- // Error represents sqlite library error code.
- type Error struct {
- msg string
- code int
- }
- // Error implements error.
- func (e *Error) Error() string { return e.msg }
- // Code returns the sqlite result code for this error.
- func (e *Error) Code() int { return e.code }
- var (
- // ErrorCodeString maps Error.Code() to its string representation.
- ErrorCodeString = map[int]string{
- sqlite3.SQLITE_ABORT: "Callback routine requested an abort (SQLITE_ABORT)",
- sqlite3.SQLITE_AUTH: "Authorization denied (SQLITE_AUTH)",
- sqlite3.SQLITE_BUSY: "The database file is locked (SQLITE_BUSY)",
- sqlite3.SQLITE_CANTOPEN: "Unable to open the database file (SQLITE_CANTOPEN)",
- sqlite3.SQLITE_CONSTRAINT: "Abort due to constraint violation (SQLITE_CONSTRAINT)",
- sqlite3.SQLITE_CORRUPT: "The database disk image is malformed (SQLITE_CORRUPT)",
- sqlite3.SQLITE_DONE: "sqlite3_step() has finished executing (SQLITE_DONE)",
- sqlite3.SQLITE_EMPTY: "Internal use only (SQLITE_EMPTY)",
- sqlite3.SQLITE_ERROR: "Generic error (SQLITE_ERROR)",
- sqlite3.SQLITE_FORMAT: "Not used (SQLITE_FORMAT)",
- sqlite3.SQLITE_FULL: "Insertion failed because database is full (SQLITE_FULL)",
- sqlite3.SQLITE_INTERNAL: "Internal logic error in SQLite (SQLITE_INTERNAL)",
- sqlite3.SQLITE_INTERRUPT: "Operation terminated by sqlite3_interrupt()(SQLITE_INTERRUPT)",
- sqlite3.SQLITE_IOERR | (1 << 8): "(SQLITE_IOERR_READ)",
- sqlite3.SQLITE_IOERR | (10 << 8): "(SQLITE_IOERR_DELETE)",
- sqlite3.SQLITE_IOERR | (11 << 8): "(SQLITE_IOERR_BLOCKED)",
- sqlite3.SQLITE_IOERR | (12 << 8): "(SQLITE_IOERR_NOMEM)",
- sqlite3.SQLITE_IOERR | (13 << 8): "(SQLITE_IOERR_ACCESS)",
- sqlite3.SQLITE_IOERR | (14 << 8): "(SQLITE_IOERR_CHECKRESERVEDLOCK)",
- sqlite3.SQLITE_IOERR | (15 << 8): "(SQLITE_IOERR_LOCK)",
- sqlite3.SQLITE_IOERR | (16 << 8): "(SQLITE_IOERR_CLOSE)",
- sqlite3.SQLITE_IOERR | (17 << 8): "(SQLITE_IOERR_DIR_CLOSE)",
- sqlite3.SQLITE_IOERR | (2 << 8): "(SQLITE_IOERR_SHORT_READ)",
- sqlite3.SQLITE_IOERR | (3 << 8): "(SQLITE_IOERR_WRITE)",
- sqlite3.SQLITE_IOERR | (4 << 8): "(SQLITE_IOERR_FSYNC)",
- sqlite3.SQLITE_IOERR | (5 << 8): "(SQLITE_IOERR_DIR_FSYNC)",
- sqlite3.SQLITE_IOERR | (6 << 8): "(SQLITE_IOERR_TRUNCATE)",
- sqlite3.SQLITE_IOERR | (7 << 8): "(SQLITE_IOERR_FSTAT)",
- sqlite3.SQLITE_IOERR | (8 << 8): "(SQLITE_IOERR_UNLOCK)",
- sqlite3.SQLITE_IOERR | (9 << 8): "(SQLITE_IOERR_RDLOCK)",
- sqlite3.SQLITE_IOERR: "Some kind of disk I/O error occurred (SQLITE_IOERR)",
- sqlite3.SQLITE_LOCKED | (1 << 8): "(SQLITE_LOCKED_SHAREDCACHE)",
- sqlite3.SQLITE_LOCKED: "A table in the database is locked (SQLITE_LOCKED)",
- sqlite3.SQLITE_MISMATCH: "Data type mismatch (SQLITE_MISMATCH)",
- sqlite3.SQLITE_MISUSE: "Library used incorrectly (SQLITE_MISUSE)",
- sqlite3.SQLITE_NOLFS: "Uses OS features not supported on host (SQLITE_NOLFS)",
- sqlite3.SQLITE_NOMEM: "A malloc() failed (SQLITE_NOMEM)",
- sqlite3.SQLITE_NOTADB: "File opened that is not a database file (SQLITE_NOTADB)",
- sqlite3.SQLITE_NOTFOUND: "Unknown opcode in sqlite3_file_control() (SQLITE_NOTFOUND)",
- sqlite3.SQLITE_NOTICE: "Notifications from sqlite3_log() (SQLITE_NOTICE)",
- sqlite3.SQLITE_PERM: "Access permission denied (SQLITE_PERM)",
- sqlite3.SQLITE_PROTOCOL: "Database lock protocol error (SQLITE_PROTOCOL)",
- sqlite3.SQLITE_RANGE: "2nd parameter to sqlite3_bind out of range (SQLITE_RANGE)",
- sqlite3.SQLITE_READONLY: "Attempt to write a readonly database (SQLITE_READONLY)",
- sqlite3.SQLITE_ROW: "sqlite3_step() has another row ready (SQLITE_ROW)",
- sqlite3.SQLITE_SCHEMA: "The database schema changed (SQLITE_SCHEMA)",
- sqlite3.SQLITE_TOOBIG: "String or BLOB exceeds size limit (SQLITE_TOOBIG)",
- sqlite3.SQLITE_WARNING: "Warnings from sqlite3_log() (SQLITE_WARNING)",
- }
- )
- func init() {
- sql.Register(driverName, newDriver())
- }
- type result struct {
- lastInsertID int64
- rowsAffected int
- }
- func newResult(c *conn) (_ *result, err error) {
- r := &result{}
- if r.rowsAffected, err = c.changes(); err != nil {
- return nil, err
- }
- if r.lastInsertID, err = c.lastInsertRowID(); err != nil {
- return nil, err
- }
- return r, nil
- }
- // LastInsertId returns the database's auto-generated ID after, for example, an
- // INSERT into a table with primary key.
- func (r *result) LastInsertId() (int64, error) {
- if r == nil {
- return 0, nil
- }
- return r.lastInsertID, nil
- }
- // RowsAffected returns the number of rows affected by the query.
- func (r *result) RowsAffected() (int64, error) {
- if r == nil {
- return 0, nil
- }
- return int64(r.rowsAffected), nil
- }
- type rows struct {
- allocs []uintptr
- c *conn
- columns []string
- pstmt uintptr
- doStep bool
- empty bool
- }
- func newRows(c *conn, pstmt uintptr, allocs []uintptr, empty bool) (r *rows, err error) {
- r = &rows{c: c, pstmt: pstmt, allocs: allocs, empty: empty}
- defer func() {
- if err != nil {
- r.Close()
- r = nil
- }
- }()
- n, err := c.columnCount(pstmt)
- if err != nil {
- return nil, err
- }
- r.columns = make([]string, n)
- for i := range r.columns {
- if r.columns[i], err = r.c.columnName(pstmt, i); err != nil {
- return nil, err
- }
- }
- return r, nil
- }
- // Close closes the rows iterator.
- func (r *rows) Close() (err error) {
- for _, v := range r.allocs {
- r.c.free(v)
- }
- r.allocs = nil
- return r.c.finalize(r.pstmt)
- }
- // Columns returns the names of the columns. The number of columns of the
- // result is inferred from the length of the slice. If a particular column name
- // isn't known, an empty string should be returned for that entry.
- func (r *rows) Columns() (c []string) {
- return r.columns
- }
- // Next is called to populate the next row of data into the provided slice. The
- // provided slice will be the same size as the Columns() are wide.
- //
- // Next should return io.EOF when there are no more rows.
- func (r *rows) Next(dest []driver.Value) (err error) {
- if r.empty {
- return io.EOF
- }
- rc := sqlite3.SQLITE_ROW
- if r.doStep {
- if rc, err = r.c.step(r.pstmt); err != nil {
- return err
- }
- }
- r.doStep = true
- switch rc {
- case sqlite3.SQLITE_ROW:
- if g, e := len(dest), len(r.columns); g != e {
- return fmt.Errorf("sqlite: Next: have %v destination values, expected %v", g, e)
- }
- for i := range dest {
- ct, err := r.c.columnType(r.pstmt, i)
- if err != nil {
- return err
- }
- switch ct {
- case sqlite3.SQLITE_INTEGER:
- v, err := r.c.columnInt64(r.pstmt, i)
- if err != nil {
- return err
- }
- dest[i] = v
- case sqlite3.SQLITE_FLOAT:
- v, err := r.c.columnDouble(r.pstmt, i)
- if err != nil {
- return err
- }
- dest[i] = v
- case sqlite3.SQLITE_TEXT:
- v, err := r.c.columnText(r.pstmt, i)
- if err != nil {
- return err
- }
- switch r.ColumnTypeDatabaseTypeName(i) {
- case "DATE", "DATETIME", "TIMESTAMP":
- dest[i], _ = r.c.parseTime(v)
- default:
- dest[i] = v
- }
- case sqlite3.SQLITE_BLOB:
- v, err := r.c.columnBlob(r.pstmt, i)
- if err != nil {
- return err
- }
- dest[i] = v
- case sqlite3.SQLITE_NULL:
- dest[i] = nil
- default:
- return fmt.Errorf("internal error: rc %d", rc)
- }
- }
- return nil
- case sqlite3.SQLITE_DONE:
- return io.EOF
- default:
- return r.c.errstr(int32(rc))
- }
- }
- // Inspired by mattn/go-sqlite3: https://github.com/mattn/go-sqlite3/blob/ab91e934/sqlite3.go#L210-L226
- //
- // These time.Parse formats handle formats 1 through 7 listed at https://www.sqlite.org/lang_datefunc.html.
- var parseTimeFormats = []string{
- "2006-01-02 15:04:05.999999999-07:00",
- "2006-01-02T15:04:05.999999999-07:00",
- "2006-01-02 15:04:05.999999999",
- "2006-01-02T15:04:05.999999999",
- "2006-01-02 15:04",
- "2006-01-02T15:04",
- "2006-01-02",
- }
- // Attempt to parse s as a time. Return (s, false) if s is not
- // recognized as a valid time encoding.
- func (c *conn) parseTime(s string) (interface{}, bool) {
- if v, ok := c.parseTimeString(s, strings.Index(s, "m=")); ok {
- return v, true
- }
- ts := strings.TrimSuffix(s, "Z")
- for _, f := range parseTimeFormats {
- t, err := time.Parse(f, ts)
- if err == nil {
- return t, true
- }
- }
- return s, false
- }
- // Attempt to parse s as a time string produced by t.String(). If x > 0 it's
- // the index of substring "m=" within s. Return (s, false) if s is
- // not recognized as a valid time encoding.
- func (c *conn) parseTimeString(s0 string, x int) (interface{}, bool) {
- s := s0
- if x > 0 {
- s = s[:x] // "2006-01-02 15:04:05.999999999 -0700 MST m=+9999" -> "2006-01-02 15:04:05.999999999 -0700 MST "
- }
- s = strings.TrimSpace(s)
- if t, err := time.Parse("2006-01-02 15:04:05.999999999 -0700 MST", s); err == nil {
- return t, true
- }
- return s0, false
- }
- // writeTimeFormats are the names and formats supported
- // by the `_time_format` DSN query param.
- var writeTimeFormats = map[string]string{
- "sqlite": parseTimeFormats[0],
- }
- func (c *conn) formatTime(t time.Time) string {
- // Before configurable write time formats were supported,
- // time.Time.String was used. Maintain that default to
- // keep existing driver users formatting times the same.
- if c.writeTimeFormat == "" {
- return t.String()
- }
- return t.Format(c.writeTimeFormat)
- }
- // RowsColumnTypeDatabaseTypeName may be implemented by Rows. It should return
- // the database system type name without the length. Type names should be
- // uppercase. Examples of returned types: "VARCHAR", "NVARCHAR", "VARCHAR2",
- // "CHAR", "TEXT", "DECIMAL", "SMALLINT", "INT", "BIGINT", "BOOL", "[]BIGINT",
- // "JSONB", "XML", "TIMESTAMP".
- func (r *rows) ColumnTypeDatabaseTypeName(index int) string {
- return strings.ToUpper(r.c.columnDeclType(r.pstmt, index))
- }
- // RowsColumnTypeLength may be implemented by Rows. It should return the length
- // of the column type if the column is a variable length type. If the column is
- // not a variable length type ok should return false. If length is not limited
- // other than system limits, it should return math.MaxInt64. The following are
- // examples of returned values for various types:
- //
- // TEXT (math.MaxInt64, true)
- // varchar(10) (10, true)
- // nvarchar(10) (10, true)
- // decimal (0, false)
- // int (0, false)
- // bytea(30) (30, true)
- func (r *rows) ColumnTypeLength(index int) (length int64, ok bool) {
- t, err := r.c.columnType(r.pstmt, index)
- if err != nil {
- return 0, false
- }
- switch t {
- case sqlite3.SQLITE_INTEGER:
- return 0, false
- case sqlite3.SQLITE_FLOAT:
- return 0, false
- case sqlite3.SQLITE_TEXT:
- return math.MaxInt64, true
- case sqlite3.SQLITE_BLOB:
- return math.MaxInt64, true
- case sqlite3.SQLITE_NULL:
- return 0, false
- default:
- return 0, false
- }
- }
- // RowsColumnTypeNullable may be implemented by Rows. The nullable value should
- // be true if it is known the column may be null, or false if the column is
- // known to be not nullable. If the column nullability is unknown, ok should be
- // false.
- func (r *rows) ColumnTypeNullable(index int) (nullable, ok bool) {
- return true, true
- }
- // RowsColumnTypePrecisionScale may be implemented by Rows. It should return
- // the precision and scale for decimal types. If not applicable, ok should be
- // false. The following are examples of returned values for various types:
- //
- // decimal(38, 4) (38, 4, true)
- // int (0, 0, false)
- // decimal (math.MaxInt64, math.MaxInt64, true)
- func (r *rows) ColumnTypePrecisionScale(index int) (precision, scale int64, ok bool) {
- return 0, 0, false
- }
- // RowsColumnTypeScanType may be implemented by Rows. It should return the
- // value type that can be used to scan types into. For example, the database
- // column type "bigint" this should return "reflect.TypeOf(int64(0))".
- func (r *rows) ColumnTypeScanType(index int) reflect.Type {
- t, err := r.c.columnType(r.pstmt, index)
- if err != nil {
- return reflect.TypeOf("")
- }
- switch t {
- case sqlite3.SQLITE_INTEGER:
- switch strings.ToLower(r.c.columnDeclType(r.pstmt, index)) {
- case "boolean":
- return reflect.TypeOf(false)
- case "date", "datetime", "time", "timestamp":
- return reflect.TypeOf(time.Time{})
- default:
- return reflect.TypeOf(int64(0))
- }
- case sqlite3.SQLITE_FLOAT:
- return reflect.TypeOf(float64(0))
- case sqlite3.SQLITE_TEXT:
- return reflect.TypeOf("")
- case sqlite3.SQLITE_BLOB:
- return reflect.SliceOf(reflect.TypeOf([]byte{}))
- case sqlite3.SQLITE_NULL:
- return reflect.TypeOf(nil)
- default:
- return reflect.TypeOf("")
- }
- }
- type stmt struct {
- c *conn
- psql uintptr
- }
- func newStmt(c *conn, sql string) (*stmt, error) {
- p, err := libc.CString(sql)
- if err != nil {
- return nil, err
- }
- stm := stmt{c: c, psql: p}
- return &stm, nil
- }
- // Close closes the statement.
- //
- // As of Go 1.1, a Stmt will not be closed if it's in use by any queries.
- func (s *stmt) Close() (err error) {
- s.c.free(s.psql)
- s.psql = 0
- return nil
- }
- // Exec executes a query that doesn't return rows, such as an INSERT or UPDATE.
- //
- //
- // Deprecated: Drivers should implement StmtExecContext instead (or
- // additionally).
- func (s *stmt) Exec(args []driver.Value) (driver.Result, error) { //TODO StmtExecContext
- return s.exec(context.Background(), toNamedValues(args))
- }
- // toNamedValues converts []driver.Value to []driver.NamedValue
- func toNamedValues(vals []driver.Value) (r []driver.NamedValue) {
- r = make([]driver.NamedValue, len(vals))
- for i, val := range vals {
- r[i] = driver.NamedValue{Value: val, Ordinal: i + 1}
- }
- return r
- }
- func (s *stmt) exec(ctx context.Context, args []driver.NamedValue) (r driver.Result, err error) {
- var pstmt uintptr
- var done int32
- if ctx != nil && ctx.Done() != nil {
- defer interruptOnDone(ctx, s.c, &done)()
- }
- for psql := s.psql; *(*byte)(unsafe.Pointer(psql)) != 0 && atomic.LoadInt32(&done) == 0; {
- if pstmt, err = s.c.prepareV2(&psql); err != nil {
- return nil, err
- }
- if pstmt == 0 {
- continue
- }
- err = func() (err error) {
- n, err := s.c.bindParameterCount(pstmt)
- if err != nil {
- return err
- }
- if n != 0 {
- allocs, err := s.c.bind(pstmt, n, args)
- if err != nil {
- return err
- }
- if len(allocs) != 0 {
- defer func() {
- for _, v := range allocs {
- s.c.free(v)
- }
- }()
- }
- }
- rc, err := s.c.step(pstmt)
- if err != nil {
- return err
- }
- switch rc & 0xff {
- case sqlite3.SQLITE_DONE, sqlite3.SQLITE_ROW:
- // nop
- default:
- return s.c.errstr(int32(rc))
- }
- return nil
- }()
- if e := s.c.finalize(pstmt); e != nil && err == nil {
- err = e
- }
- if err != nil {
- return nil, err
- }
- }
- return newResult(s.c)
- }
- // NumInput returns the number of placeholder parameters.
- //
- // If NumInput returns >= 0, the sql package will sanity check argument counts
- // from callers and return errors to the caller before the statement's Exec or
- // Query methods are called.
- //
- // NumInput may also return -1, if the driver doesn't know its number of
- // placeholders. In that case, the sql package will not sanity check Exec or
- // Query argument counts.
- func (s *stmt) NumInput() (n int) {
- return -1
- }
- // Query executes a query that may return rows, such as a
- // SELECT.
- //
- // Deprecated: Drivers should implement StmtQueryContext instead (or
- // additionally).
- func (s *stmt) Query(args []driver.Value) (driver.Rows, error) { //TODO StmtQueryContext
- return s.query(context.Background(), toNamedValues(args))
- }
- func (s *stmt) query(ctx context.Context, args []driver.NamedValue) (r driver.Rows, err error) {
- var pstmt uintptr
- var done int32
- if ctx != nil && ctx.Done() != nil {
- defer interruptOnDone(ctx, s.c, &done)()
- }
- var allocs []uintptr
- for psql := s.psql; *(*byte)(unsafe.Pointer(psql)) != 0 && atomic.LoadInt32(&done) == 0; {
- if pstmt, err = s.c.prepareV2(&psql); err != nil {
- return nil, err
- }
- if pstmt == 0 {
- continue
- }
- err = func() (err error) {
- n, err := s.c.bindParameterCount(pstmt)
- if err != nil {
- return err
- }
- if n != 0 {
- if allocs, err = s.c.bind(pstmt, n, args); err != nil {
- return err
- }
- }
- rc, err := s.c.step(pstmt)
- if err != nil {
- return err
- }
- switch rc & 0xff {
- case sqlite3.SQLITE_ROW:
- if r != nil {
- r.Close()
- }
- if r, err = newRows(s.c, pstmt, allocs, false); err != nil {
- return err
- }
- pstmt = 0
- return nil
- case sqlite3.SQLITE_DONE:
- if r == nil {
- if r, err = newRows(s.c, pstmt, allocs, true); err != nil {
- return err
- }
- pstmt = 0
- return nil
- }
- // nop
- default:
- return s.c.errstr(int32(rc))
- }
- if *(*byte)(unsafe.Pointer(psql)) == 0 {
- if r != nil {
- r.Close()
- }
- if r, err = newRows(s.c, pstmt, allocs, true); err != nil {
- return err
- }
- pstmt = 0
- }
- return nil
- }()
- if e := s.c.finalize(pstmt); e != nil && err == nil {
- err = e
- }
- if err != nil {
- return nil, err
- }
- }
- return r, err
- }
- type tx struct {
- c *conn
- }
- func newTx(c *conn, opts driver.TxOptions) (*tx, error) {
- r := &tx{c: c}
- sql := "begin"
- if !opts.ReadOnly && c.beginMode != "" {
- sql = "begin " + c.beginMode
- }
- if err := r.exec(context.Background(), sql); err != nil {
- return nil, err
- }
- return r, nil
- }
- // Commit implements driver.Tx.
- func (t *tx) Commit() (err error) {
- return t.exec(context.Background(), "commit")
- }
- // Rollback implements driver.Tx.
- func (t *tx) Rollback() (err error) {
- return t.exec(context.Background(), "rollback")
- }
- func (t *tx) exec(ctx context.Context, sql string) (err error) {
- psql, err := libc.CString(sql)
- if err != nil {
- return err
- }
- defer t.c.free(psql)
- //TODO use t.conn.ExecContext() instead
- if ctx != nil && ctx.Done() != nil {
- defer interruptOnDone(ctx, t.c, nil)()
- }
- if rc := sqlite3.Xsqlite3_exec(t.c.tls, t.c.db, psql, 0, 0, 0); rc != sqlite3.SQLITE_OK {
- return t.c.errstr(rc)
- }
- return nil
- }
- // interruptOnDone sets up a goroutine to interrupt the provided db when the
- // context is canceled, and returns a function the caller must defer so it
- // doesn't interrupt after the caller finishes.
- func interruptOnDone(
- ctx context.Context,
- c *conn,
- done *int32,
- ) func() {
- if done == nil {
- var d int32
- done = &d
- }
- donech := make(chan struct{})
- go func() {
- select {
- case <-ctx.Done():
- // don't call interrupt if we were already done: it indicates that this
- // call to exec is no longer running and we would be interrupting
- // nothing, or even possibly an unrelated later call to exec.
- if atomic.AddInt32(done, 1) == 1 {
- c.interrupt(c.db)
- }
- case <-donech:
- }
- }()
- // the caller is expected to defer this function
- return func() {
- // set the done flag so that a context cancellation right after the caller
- // returns doesn't trigger a call to interrupt for some other statement.
- atomic.AddInt32(done, 1)
- close(donech)
- }
- }
- type conn struct {
- db uintptr // *sqlite3.Xsqlite3
- tls *libc.TLS
- // Context handling can cause conn.Close and conn.interrupt to be invoked
- // concurrently.
- sync.Mutex
- writeTimeFormat string
- beginMode string
- }
- func newConn(dsn string) (*conn, error) {
- var query, vfsName string
- // Parse the query parameters from the dsn and them from the dsn if not prefixed by file:
- // https://github.com/mattn/go-sqlite3/blob/3392062c729d77820afc1f5cae3427f0de39e954/sqlite3.go#L1046
- // https://github.com/mattn/go-sqlite3/blob/3392062c729d77820afc1f5cae3427f0de39e954/sqlite3.go#L1383
- pos := strings.IndexRune(dsn, '?')
- if pos >= 1 {
- query = dsn[pos+1:]
- var err error
- vfsName, err = getVFSName(query)
- if err != nil {
- return nil, err
- }
- if !strings.HasPrefix(dsn, "file:") {
- dsn = dsn[:pos]
- }
- }
- c := &conn{tls: libc.NewTLS()}
- db, err := c.openV2(
- dsn,
- vfsName,
- sqlite3.SQLITE_OPEN_READWRITE|sqlite3.SQLITE_OPEN_CREATE|
- sqlite3.SQLITE_OPEN_FULLMUTEX|
- sqlite3.SQLITE_OPEN_URI,
- )
- if err != nil {
- return nil, err
- }
- c.db = db
- if err = c.extendedResultCodes(true); err != nil {
- c.Close()
- return nil, err
- }
- if err = applyQueryParams(c, query); err != nil {
- c.Close()
- return nil, err
- }
- return c, nil
- }
- func getVFSName(query string) (r string, err error) {
- q, err := url.ParseQuery(query)
- if err != nil {
- return "", err
- }
- for _, v := range q["vfs"] {
- if r != "" && r != v {
- return "", fmt.Errorf("conflicting vfs query parameters: %v", q["vfs"])
- }
- r = v
- }
- return r, nil
- }
- func applyQueryParams(c *conn, query string) error {
- q, err := url.ParseQuery(query)
- if err != nil {
- return err
- }
- for _, v := range q["_pragma"] {
- cmd := "pragma " + v
- _, err := c.exec(context.Background(), cmd, nil)
- if err != nil {
- return err
- }
- }
- if v := q.Get("_time_format"); v != "" {
- f, ok := writeTimeFormats[v]
- if !ok {
- return fmt.Errorf("unknown _time_format %q", v)
- }
- c.writeTimeFormat = f
- }
- if v := q.Get("_txlock"); v != "" {
- lower := strings.ToLower(v)
- if lower != "deferred" && lower != "immediate" && lower != "exclusive" {
- return fmt.Errorf("unknown _txlock %q", v)
- }
- c.beginMode = v
- }
- return nil
- }
- // const void *sqlite3_column_blob(sqlite3_stmt*, int iCol);
- func (c *conn) columnBlob(pstmt uintptr, iCol int) (v []byte, err error) {
- p := sqlite3.Xsqlite3_column_blob(c.tls, pstmt, int32(iCol))
- len, err := c.columnBytes(pstmt, iCol)
- if err != nil {
- return nil, err
- }
- if p == 0 || len == 0 {
- return nil, nil
- }
- v = make([]byte, len)
- copy(v, (*libc.RawMem)(unsafe.Pointer(p))[:len:len])
- return v, nil
- }
- // int sqlite3_column_bytes(sqlite3_stmt*, int iCol);
- func (c *conn) columnBytes(pstmt uintptr, iCol int) (_ int, err error) {
- v := sqlite3.Xsqlite3_column_bytes(c.tls, pstmt, int32(iCol))
- return int(v), nil
- }
- // const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);
- func (c *conn) columnText(pstmt uintptr, iCol int) (v string, err error) {
- p := sqlite3.Xsqlite3_column_text(c.tls, pstmt, int32(iCol))
- len, err := c.columnBytes(pstmt, iCol)
- if err != nil {
- return "", err
- }
- if p == 0 || len == 0 {
- return "", nil
- }
- b := make([]byte, len)
- copy(b, (*libc.RawMem)(unsafe.Pointer(p))[:len:len])
- return string(b), nil
- }
- // double sqlite3_column_double(sqlite3_stmt*, int iCol);
- func (c *conn) columnDouble(pstmt uintptr, iCol int) (v float64, err error) {
- v = sqlite3.Xsqlite3_column_double(c.tls, pstmt, int32(iCol))
- return v, nil
- }
- // sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol);
- func (c *conn) columnInt64(pstmt uintptr, iCol int) (v int64, err error) {
- v = sqlite3.Xsqlite3_column_int64(c.tls, pstmt, int32(iCol))
- return v, nil
- }
- // int sqlite3_column_type(sqlite3_stmt*, int iCol);
- func (c *conn) columnType(pstmt uintptr, iCol int) (_ int, err error) {
- v := sqlite3.Xsqlite3_column_type(c.tls, pstmt, int32(iCol))
- return int(v), nil
- }
- // const char *sqlite3_column_decltype(sqlite3_stmt*,int);
- func (c *conn) columnDeclType(pstmt uintptr, iCol int) string {
- return libc.GoString(sqlite3.Xsqlite3_column_decltype(c.tls, pstmt, int32(iCol)))
- }
- // const char *sqlite3_column_name(sqlite3_stmt*, int N);
- func (c *conn) columnName(pstmt uintptr, n int) (string, error) {
- p := sqlite3.Xsqlite3_column_name(c.tls, pstmt, int32(n))
- return libc.GoString(p), nil
- }
- // int sqlite3_column_count(sqlite3_stmt *pStmt);
- func (c *conn) columnCount(pstmt uintptr) (_ int, err error) {
- v := sqlite3.Xsqlite3_column_count(c.tls, pstmt)
- return int(v), nil
- }
- // sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*);
- func (c *conn) lastInsertRowID() (v int64, _ error) {
- return sqlite3.Xsqlite3_last_insert_rowid(c.tls, c.db), nil
- }
- // int sqlite3_changes(sqlite3*);
- func (c *conn) changes() (int, error) {
- v := sqlite3.Xsqlite3_changes(c.tls, c.db)
- return int(v), nil
- }
- // int sqlite3_step(sqlite3_stmt*);
- func (c *conn) step(pstmt uintptr) (int, error) {
- for {
- switch rc := sqlite3.Xsqlite3_step(c.tls, pstmt); rc {
- case sqliteLockedSharedcache:
- if err := c.retry(pstmt); err != nil {
- return sqlite3.SQLITE_LOCKED, err
- }
- case
- sqlite3.SQLITE_DONE,
- sqlite3.SQLITE_ROW:
- return int(rc), nil
- default:
- return int(rc), c.errstr(rc)
- }
- }
- }
- func (c *conn) retry(pstmt uintptr) error {
- mu := mutexAlloc(c.tls)
- (*mutex)(unsafe.Pointer(mu)).Lock()
- rc := sqlite3.Xsqlite3_unlock_notify(
- c.tls,
- c.db,
- *(*uintptr)(unsafe.Pointer(&struct {
- f func(*libc.TLS, uintptr, int32)
- }{unlockNotify})),
- mu,
- )
- if rc == sqlite3.SQLITE_LOCKED { // Deadlock, see https://www.sqlite.org/c3ref/unlock_notify.html
- (*mutex)(unsafe.Pointer(mu)).Unlock()
- mutexFree(c.tls, mu)
- return c.errstr(rc)
- }
- (*mutex)(unsafe.Pointer(mu)).Lock()
- (*mutex)(unsafe.Pointer(mu)).Unlock()
- mutexFree(c.tls, mu)
- if pstmt != 0 {
- sqlite3.Xsqlite3_reset(c.tls, pstmt)
- }
- return nil
- }
- func unlockNotify(t *libc.TLS, ppArg uintptr, nArg int32) {
- for i := int32(0); i < nArg; i++ {
- mu := *(*uintptr)(unsafe.Pointer(ppArg))
- (*mutex)(unsafe.Pointer(mu)).Unlock()
- ppArg += ptrSize
- }
- }
- func (c *conn) bind(pstmt uintptr, n int, args []driver.NamedValue) (allocs []uintptr, err error) {
- defer func() {
- if err == nil {
- return
- }
- for _, v := range allocs {
- c.free(v)
- }
- allocs = nil
- }()
- for i := 1; i <= n; i++ {
- name, err := c.bindParameterName(pstmt, i)
- if err != nil {
- return allocs, err
- }
- var found bool
- var v driver.NamedValue
- for _, v = range args {
- if name != "" {
- // For ?NNN and $NNN params, match if NNN == v.Ordinal.
- //
- // Supporting this for $NNN is a special case that makes eg
- // `select $1, $2, $3 ...` work without needing to use
- // sql.Named.
- if (name[0] == '?' || name[0] == '$') && name[1:] == strconv.Itoa(v.Ordinal) {
- found = true
- break
- }
- // sqlite supports '$', '@' and ':' prefixes for string
- // identifiers and '?' for numeric, so we cannot
- // combine different prefixes with the same name
- // because `database/sql` requires variable names
- // to start with a letter
- if name[1:] == v.Name[:] {
- found = true
- break
- }
- } else {
- if v.Ordinal == i {
- found = true
- break
- }
- }
- }
- if !found {
- if name != "" {
- return allocs, fmt.Errorf("missing named argument %q", name[1:])
- }
- return allocs, fmt.Errorf("missing argument with index %d", i)
- }
- var p uintptr
- switch x := v.Value.(type) {
- case int64:
- if err := c.bindInt64(pstmt, i, x); err != nil {
- return allocs, err
- }
- case float64:
- if err := c.bindDouble(pstmt, i, x); err != nil {
- return allocs, err
- }
- case bool:
- v := 0
- if x {
- v = 1
- }
- if err := c.bindInt(pstmt, i, v); err != nil {
- return allocs, err
- }
- case []byte:
- if p, err = c.bindBlob(pstmt, i, x); err != nil {
- return allocs, err
- }
- case string:
- if p, err = c.bindText(pstmt, i, x); err != nil {
- return allocs, err
- }
- case time.Time:
- if p, err = c.bindText(pstmt, i, c.formatTime(x)); err != nil {
- return allocs, err
- }
- case nil:
- if p, err = c.bindNull(pstmt, i); err != nil {
- return allocs, err
- }
- default:
- return allocs, fmt.Errorf("sqlite: invalid driver.Value type %T", x)
- }
- if p != 0 {
- allocs = append(allocs, p)
- }
- }
- return allocs, nil
- }
- // int sqlite3_bind_null(sqlite3_stmt*, int);
- func (c *conn) bindNull(pstmt uintptr, idx1 int) (uintptr, error) {
- if rc := sqlite3.Xsqlite3_bind_null(c.tls, pstmt, int32(idx1)); rc != sqlite3.SQLITE_OK {
- return 0, c.errstr(rc)
- }
- return 0, nil
- }
- // int sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*));
- func (c *conn) bindText(pstmt uintptr, idx1 int, value string) (uintptr, error) {
- p, err := libc.CString(value)
- if err != nil {
- return 0, err
- }
- if rc := sqlite3.Xsqlite3_bind_text(c.tls, pstmt, int32(idx1), p, int32(len(value)), 0); rc != sqlite3.SQLITE_OK {
- c.free(p)
- return 0, c.errstr(rc)
- }
- return p, nil
- }
- // int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
- func (c *conn) bindBlob(pstmt uintptr, idx1 int, value []byte) (uintptr, error) {
- if value != nil && len(value) == 0 {
- if rc := sqlite3.Xsqlite3_bind_zeroblob(c.tls, pstmt, int32(idx1), 0); rc != sqlite3.SQLITE_OK {
- return 0, c.errstr(rc)
- }
- return 0, nil
- }
- p, err := c.malloc(len(value))
- if err != nil {
- return 0, err
- }
- if len(value) != 0 {
- copy((*libc.RawMem)(unsafe.Pointer(p))[:len(value):len(value)], value)
- }
- if rc := sqlite3.Xsqlite3_bind_blob(c.tls, pstmt, int32(idx1), p, int32(len(value)), 0); rc != sqlite3.SQLITE_OK {
- c.free(p)
- return 0, c.errstr(rc)
- }
- return p, nil
- }
- // int sqlite3_bind_int(sqlite3_stmt*, int, int);
- func (c *conn) bindInt(pstmt uintptr, idx1, value int) (err error) {
- if rc := sqlite3.Xsqlite3_bind_int(c.tls, pstmt, int32(idx1), int32(value)); rc != sqlite3.SQLITE_OK {
- return c.errstr(rc)
- }
- return nil
- }
- // int sqlite3_bind_double(sqlite3_stmt*, int, double);
- func (c *conn) bindDouble(pstmt uintptr, idx1 int, value float64) (err error) {
- if rc := sqlite3.Xsqlite3_bind_double(c.tls, pstmt, int32(idx1), value); rc != 0 {
- return c.errstr(rc)
- }
- return nil
- }
- // int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64);
- func (c *conn) bindInt64(pstmt uintptr, idx1 int, value int64) (err error) {
- if rc := sqlite3.Xsqlite3_bind_int64(c.tls, pstmt, int32(idx1), value); rc != sqlite3.SQLITE_OK {
- return c.errstr(rc)
- }
- return nil
- }
- // const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int);
- func (c *conn) bindParameterName(pstmt uintptr, i int) (string, error) {
- p := sqlite3.Xsqlite3_bind_parameter_name(c.tls, pstmt, int32(i))
- return libc.GoString(p), nil
- }
- // int sqlite3_bind_parameter_count(sqlite3_stmt*);
- func (c *conn) bindParameterCount(pstmt uintptr) (_ int, err error) {
- r := sqlite3.Xsqlite3_bind_parameter_count(c.tls, pstmt)
- return int(r), nil
- }
- // int sqlite3_finalize(sqlite3_stmt *pStmt);
- func (c *conn) finalize(pstmt uintptr) error {
- if rc := sqlite3.Xsqlite3_finalize(c.tls, pstmt); rc != sqlite3.SQLITE_OK {
- return c.errstr(rc)
- }
- return nil
- }
- // int sqlite3_prepare_v2(
- // sqlite3 *db, /* Database handle */
- // const char *zSql, /* SQL statement, UTF-8 encoded */
- // int nByte, /* Maximum length of zSql in bytes. */
- // sqlite3_stmt **ppStmt, /* OUT: Statement handle */
- // const char **pzTail /* OUT: Pointer to unused portion of zSql */
- // );
- func (c *conn) prepareV2(zSQL *uintptr) (pstmt uintptr, err error) {
- var ppstmt, pptail uintptr
- defer func() {
- c.free(ppstmt)
- c.free(pptail)
- }()
- if ppstmt, err = c.malloc(int(ptrSize)); err != nil {
- return 0, err
- }
- if pptail, err = c.malloc(int(ptrSize)); err != nil {
- return 0, err
- }
- for {
- switch rc := sqlite3.Xsqlite3_prepare_v2(c.tls, c.db, *zSQL, -1, ppstmt, pptail); rc {
- case sqlite3.SQLITE_OK:
- *zSQL = *(*uintptr)(unsafe.Pointer(pptail))
- return *(*uintptr)(unsafe.Pointer(ppstmt)), nil
- case sqliteLockedSharedcache:
- if err := c.retry(0); err != nil {
- return 0, err
- }
- default:
- return 0, c.errstr(rc)
- }
- }
- }
- // void sqlite3_interrupt(sqlite3*);
- func (c *conn) interrupt(pdb uintptr) (err error) {
- c.Lock() // Defend against race with .Close invoked by context handling.
- defer c.Unlock()
- if c.tls != nil {
- sqlite3.Xsqlite3_interrupt(c.tls, pdb)
- }
- return nil
- }
- // int sqlite3_extended_result_codes(sqlite3*, int onoff);
- func (c *conn) extendedResultCodes(on bool) error {
- if rc := sqlite3.Xsqlite3_extended_result_codes(c.tls, c.db, libc.Bool32(on)); rc != sqlite3.SQLITE_OK {
- return c.errstr(rc)
- }
- return nil
- }
- // int sqlite3_open_v2(
- // const char *filename, /* Database filename (UTF-8) */
- // sqlite3 **ppDb, /* OUT: SQLite db handle */
- // int flags, /* Flags */
- // const char *zVfs /* Name of VFS module to use */
- // );
- func (c *conn) openV2(name, vfsName string, flags int32) (uintptr, error) {
- var p, s, vfs uintptr
- defer func() {
- if p != 0 {
- c.free(p)
- }
- if s != 0 {
- c.free(s)
- }
- if vfs != 0 {
- c.free(vfs)
- }
- }()
- p, err := c.malloc(int(ptrSize))
- if err != nil {
- return 0, err
- }
- if s, err = libc.CString(name); err != nil {
- return 0, err
- }
- if vfsName != "" {
- if vfs, err = libc.CString(vfsName); err != nil {
- return 0, err
- }
- }
- if rc := sqlite3.Xsqlite3_open_v2(c.tls, s, p, flags, vfs); rc != sqlite3.SQLITE_OK {
- return 0, c.errstr(rc)
- }
- return *(*uintptr)(unsafe.Pointer(p)), nil
- }
- func (c *conn) malloc(n int) (uintptr, error) {
- if p := libc.Xmalloc(c.tls, types.Size_t(n)); p != 0 || n == 0 {
- return p, nil
- }
- return 0, fmt.Errorf("sqlite: cannot allocate %d bytes of memory", n)
- }
- func (c *conn) free(p uintptr) {
- if p != 0 {
- libc.Xfree(c.tls, p)
- }
- }
- // const char *sqlite3_errstr(int);
- func (c *conn) errstr(rc int32) error {
- p := sqlite3.Xsqlite3_errstr(c.tls, rc)
- str := libc.GoString(p)
- p = sqlite3.Xsqlite3_errmsg(c.tls, c.db)
- var s string
- if rc == sqlite3.SQLITE_BUSY {
- s = " (SQLITE_BUSY)"
- }
- switch msg := libc.GoString(p); {
- case msg == str:
- return &Error{msg: fmt.Sprintf("%s (%v)%s", str, rc, s), code: int(rc)}
- default:
- return &Error{msg: fmt.Sprintf("%s: %s (%v)%s", str, msg, rc, s), code: int(rc)}
- }
- }
- // Begin starts a transaction.
- //
- // Deprecated: Drivers should implement ConnBeginTx instead (or additionally).
- func (c *conn) Begin() (driver.Tx, error) {
- return c.begin(context.Background(), driver.TxOptions{})
- }
- func (c *conn) begin(ctx context.Context, opts driver.TxOptions) (t driver.Tx, err error) {
- return newTx(c, opts)
- }
- // Close invalidates and potentially stops any current prepared statements and
- // transactions, marking this connection as no longer in use.
- //
- // Because the sql package maintains a free pool of connections and only calls
- // Close when there's a surplus of idle connections, it shouldn't be necessary
- // for drivers to do their own connection caching.
- func (c *conn) Close() error {
- c.Lock() // Defend against race with .interrupt invoked by context handling.
- defer c.Unlock()
- if c.db != 0 {
- if err := c.closeV2(c.db); err != nil {
- return err
- }
- c.db = 0
- }
- if c.tls != nil {
- c.tls.Close()
- c.tls = nil
- }
- return nil
- }
- // int sqlite3_close_v2(sqlite3*);
- func (c *conn) closeV2(db uintptr) error {
- if rc := sqlite3.Xsqlite3_close_v2(c.tls, db); rc != sqlite3.SQLITE_OK {
- return c.errstr(rc)
- }
- return nil
- }
- type userDefinedFunction struct {
- zFuncName uintptr
- nArg int32
- eTextRep int32
- xFunc func(*libc.TLS, uintptr, int32, uintptr)
- freeOnce sync.Once
- }
- func (c *conn) createFunctionInternal(fun *userDefinedFunction) error {
- if rc := sqlite3.Xsqlite3_create_function(
- c.tls,
- c.db,
- fun.zFuncName,
- fun.nArg,
- fun.eTextRep,
- 0,
- *(*uintptr)(unsafe.Pointer(&fun.xFunc)),
- 0,
- 0,
- ); rc != sqlite3.SQLITE_OK {
- return c.errstr(rc)
- }
- return nil
- }
- // Execer is an optional interface that may be implemented by a Conn.
- //
- // If a Conn does not implement Execer, the sql package's DB.Exec will first
- // prepare a query, execute the statement, and then close the statement.
- //
- // Exec may return ErrSkip.
- //
- // Deprecated: Drivers should implement ExecerContext instead.
- func (c *conn) Exec(query string, args []driver.Value) (driver.Result, error) {
- return c.exec(context.Background(), query, toNamedValues(args))
- }
- func (c *conn) exec(ctx context.Context, query string, args []driver.NamedValue) (r driver.Result, err error) {
- s, err := c.prepare(ctx, query)
- if err != nil {
- return nil, err
- }
- defer func() {
- if err2 := s.Close(); err2 != nil && err == nil {
- err = err2
- }
- }()
- return s.(*stmt).exec(ctx, args)
- }
- // Prepare returns a prepared statement, bound to this connection.
- func (c *conn) Prepare(query string) (driver.Stmt, error) {
- return c.prepare(context.Background(), query)
- }
- func (c *conn) prepare(ctx context.Context, query string) (s driver.Stmt, err error) {
- //TODO use ctx
- return newStmt(c, query)
- }
- // Queryer is an optional interface that may be implemented by a Conn.
- //
- // If a Conn does not implement Queryer, the sql package's DB.Query will first
- // prepare a query, execute the statement, and then close the statement.
- //
- // Query may return ErrSkip.
- //
- // Deprecated: Drivers should implement QueryerContext instead.
- func (c *conn) Query(query string, args []driver.Value) (driver.Rows, error) {
- return c.query(context.Background(), query, toNamedValues(args))
- }
- func (c *conn) query(ctx context.Context, query string, args []driver.NamedValue) (r driver.Rows, err error) {
- s, err := c.prepare(ctx, query)
- if err != nil {
- return nil, err
- }
- defer func() {
- if err2 := s.Close(); err2 != nil && err == nil {
- err = err2
- }
- }()
- return s.(*stmt).query(ctx, args)
- }
- // Driver implements database/sql/driver.Driver.
- type Driver struct {
- // user defined functions that are added to every new connection on Open
- udfs map[string]*userDefinedFunction
- }
- var d = &Driver{udfs: make(map[string]*userDefinedFunction)}
- func newDriver() *Driver { return d }
- // Open returns a new connection to the database. The name is a string in a
- // driver-specific format.
- //
- // Open may return a cached connection (one previously closed), but doing so is
- // unnecessary; the sql package maintains a pool of idle connections for
- // efficient re-use.
- //
- // The returned connection is only used by one goroutine at a time.
- //
- // If name contains a '?', what follows is treated as a query string. This
- // driver supports the following query parameters:
- //
- // _pragma: Each value will be run as a "PRAGMA ..." statement (with the PRAGMA
- // keyword added for you). May be specified more than once. Example:
- // "_pragma=foreign_keys(1)" will enable foreign key enforcement. More
- // information on supported PRAGMAs is available from the SQLite documentation:
- // https://www.sqlite.org/pragma.html
- //
- // _time_format: The name of a format to use when writing time values to the
- // database. Currently the only supported value is "sqlite", which corresponds
- // to format 7 from https://www.sqlite.org/lang_datefunc.html#time_values,
- // including the timezone specifier. If this parameter is not specified, then
- // the default String() format will be used.
- //
- // _txlock: The locking behavior to use when beginning a transaction. May be
- // "deferred", "immediate", or "exclusive" (case insensitive). The default is to
- // not specify one, which SQLite maps to "deferred". More information is
- // available at
- // https://www.sqlite.org/lang_transaction.html#deferred_immediate_and_exclusive_transactions
- func (d *Driver) Open(name string) (driver.Conn, error) {
- c, err := newConn(name)
- if err != nil {
- return nil, err
- }
- for _, udf := range d.udfs {
- if err = c.createFunctionInternal(udf); err != nil {
- c.Close()
- return nil, err
- }
- }
- return c, nil
- }
- // FunctionContext represents the context user defined functions execute in.
- // Fields and/or methods of this type may get addedd in the future.
- type FunctionContext struct{}
- const sqliteValPtrSize = unsafe.Sizeof(&sqlite3.Sqlite3_value{})
- // RegisterScalarFunction registers a scalar function named zFuncName with nArg
- // arguments. Passing -1 for nArg indicates the function is variadic.
- //
- // The new function will be available to all new connections opened after
- // executing RegisterScalarFunction.
- func RegisterScalarFunction(
- zFuncName string,
- nArg int32,
- xFunc func(ctx *FunctionContext, args []driver.Value) (driver.Value, error),
- ) error {
- return registerScalarFunction(zFuncName, nArg, sqlite3.SQLITE_UTF8, xFunc)
- }
- // MustRegisterScalarFunction is like RegisterScalarFunction but panics on
- // error.
- func MustRegisterScalarFunction(
- zFuncName string,
- nArg int32,
- xFunc func(ctx *FunctionContext, args []driver.Value) (driver.Value, error),
- ) {
- if err := RegisterScalarFunction(zFuncName, nArg, xFunc); err != nil {
- panic(err)
- }
- }
- // MustRegisterDeterministicScalarFunction is like
- // RegisterDeterministicScalarFunction but panics on error.
- func MustRegisterDeterministicScalarFunction(
- zFuncName string,
- nArg int32,
- xFunc func(ctx *FunctionContext, args []driver.Value) (driver.Value, error),
- ) {
- if err := RegisterDeterministicScalarFunction(zFuncName, nArg, xFunc); err != nil {
- panic(err)
- }
- }
- // RegisterDeterministicScalarFunction registers a deterministic scalar
- // function named zFuncName with nArg arguments. Passing -1 for nArg indicates
- // the function is variadic. A deterministic function means that the function
- // always gives the same output when the input parameters are the same.
- //
- // The new function will be available to all new connections opened after
- // executing RegisterDeterministicScalarFunction.
- func RegisterDeterministicScalarFunction(
- zFuncName string,
- nArg int32,
- xFunc func(ctx *FunctionContext, args []driver.Value) (driver.Value, error),
- ) error {
- return registerScalarFunction(zFuncName, nArg, sqlite3.SQLITE_UTF8|sqlite3.SQLITE_DETERMINISTIC, xFunc)
- }
- func registerScalarFunction(
- zFuncName string,
- nArg int32,
- eTextRep int32,
- xFunc func(ctx *FunctionContext, args []driver.Value) (driver.Value, error),
- ) error {
- if _, ok := d.udfs[zFuncName]; ok {
- return fmt.Errorf("a function named %q is already registered", zFuncName)
- }
- // dont free, functions registered on the driver live as long as the program
- name, err := libc.CString(zFuncName)
- if err != nil {
- return err
- }
- udf := &userDefinedFunction{
- zFuncName: name,
- nArg: nArg,
- eTextRep: eTextRep,
- xFunc: func(tls *libc.TLS, ctx uintptr, argc int32, argv uintptr) {
- setErrorResult := func(res error) {
- errmsg, cerr := libc.CString(res.Error())
- if cerr != nil {
- panic(cerr)
- }
- defer libc.Xfree(tls, errmsg)
- sqlite3.Xsqlite3_result_error(tls, ctx, errmsg, -1)
- sqlite3.Xsqlite3_result_error_code(tls, ctx, sqlite3.SQLITE_ERROR)
- }
- args := make([]driver.Value, argc)
- for i := int32(0); i < argc; i++ {
- valPtr := *(*uintptr)(unsafe.Pointer(argv + uintptr(i)*sqliteValPtrSize))
- switch valType := sqlite3.Xsqlite3_value_type(tls, valPtr); valType {
- case sqlite3.SQLITE_TEXT:
- args[i] = libc.GoString(sqlite3.Xsqlite3_value_text(tls, valPtr))
- case sqlite3.SQLITE_INTEGER:
- args[i] = sqlite3.Xsqlite3_value_int64(tls, valPtr)
- case sqlite3.SQLITE_FLOAT:
- args[i] = sqlite3.Xsqlite3_value_double(tls, valPtr)
- case sqlite3.SQLITE_NULL:
- args[i] = nil
- case sqlite3.SQLITE_BLOB:
- size := sqlite3.Xsqlite3_value_bytes(tls, valPtr)
- blobPtr := sqlite3.Xsqlite3_value_blob(tls, valPtr)
- v := make([]byte, size)
- copy(v, (*libc.RawMem)(unsafe.Pointer(blobPtr))[:size:size])
- args[i] = v
- default:
- panic(fmt.Sprintf("unexpected argument type %q passed by sqlite", valType))
- }
- }
- res, err := xFunc(&FunctionContext{}, args)
- if err != nil {
- setErrorResult(err)
- return
- }
- switch resTyped := res.(type) {
- case nil:
- sqlite3.Xsqlite3_result_null(tls, ctx)
- case int64:
- sqlite3.Xsqlite3_result_int64(tls, ctx, resTyped)
- case float64:
- sqlite3.Xsqlite3_result_double(tls, ctx, resTyped)
- case bool:
- sqlite3.Xsqlite3_result_int(tls, ctx, libc.Bool32(resTyped))
- case time.Time:
- sqlite3.Xsqlite3_result_int64(tls, ctx, resTyped.Unix())
- case string:
- size := int32(len(resTyped))
- cstr, err := libc.CString(resTyped)
- if err != nil {
- panic(err)
- }
- defer libc.Xfree(tls, cstr)
- sqlite3.Xsqlite3_result_text(tls, ctx, cstr, size, sqlite3.SQLITE_TRANSIENT)
- case []byte:
- size := int32(len(resTyped))
- if size == 0 {
- sqlite3.Xsqlite3_result_zeroblob(tls, ctx, 0)
- return
- }
- p := libc.Xmalloc(tls, types.Size_t(size))
- if p == 0 {
- panic(fmt.Sprintf("unable to allocate space for blob: %d", size))
- }
- defer libc.Xfree(tls, p)
- copy((*libc.RawMem)(unsafe.Pointer(p))[:size:size], resTyped)
- sqlite3.Xsqlite3_result_blob(tls, ctx, p, size, sqlite3.SQLITE_TRANSIENT)
- default:
- setErrorResult(fmt.Errorf("function did not return a valid driver.Value: %T", resTyped))
- return
- }
- },
- }
- d.udfs[zFuncName] = udf
- return nil
- }
|