diff options
Diffstat (limited to 'vendor/github.com/ncruces/go-sqlite3/conn.go')
| -rw-r--r-- | vendor/github.com/ncruces/go-sqlite3/conn.go | 79 |
1 files changed, 28 insertions, 51 deletions
diff --git a/vendor/github.com/ncruces/go-sqlite3/conn.go b/vendor/github.com/ncruces/go-sqlite3/conn.go index 9f9251e9f..7e88d8c85 100644 --- a/vendor/github.com/ncruces/go-sqlite3/conn.go +++ b/vendor/github.com/ncruces/go-sqlite3/conn.go @@ -25,7 +25,6 @@ type Conn struct { *sqlite interrupt context.Context - pending *Stmt stmts []*Stmt busy func(context.Context, int) bool log func(xErrorCode, string) @@ -41,6 +40,7 @@ type Conn struct { busylst time.Time arena arena handle ptr_t + gosched uint8 } // Open calls [OpenFlags] with [OPEN_READWRITE], [OPEN_CREATE] and [OPEN_URI]. @@ -49,7 +49,7 @@ func Open(filename string) (*Conn, error) { } // OpenContext is like [Open] but includes a context, -// which is used to interrupt the process of opening the connectiton. +// which is used to interrupt the process of opening the connection. func OpenContext(ctx context.Context, filename string) (*Conn, error) { return newConn(ctx, filename, OPEN_READWRITE|OPEN_CREATE|OPEN_URI) } @@ -92,6 +92,9 @@ func newConn(ctx context.Context, filename string, flags OpenFlag) (ret *Conn, _ }() c.ctx = context.WithValue(c.ctx, connKey{}, c) + if logger := defaultLogger.Load(); logger != nil { + c.ConfigLog(*logger) + } c.arena = c.newArena() c.handle, err = c.openDB(filename, flags) if err == nil { @@ -117,7 +120,7 @@ func (c *Conn) openDB(filename string, flags OpenFlag) (ptr_t, error) { return 0, err } - c.call("sqlite3_progress_handler_go", stk_t(handle), 100) + c.call("sqlite3_progress_handler_go", stk_t(handle), 1000) if flags|OPEN_URI != 0 && strings.HasPrefix(filename, "file:") { var pragmas strings.Builder if _, after, ok := strings.Cut(filename, "?"); ok { @@ -129,7 +132,6 @@ func (c *Conn) openDB(filename string, flags OpenFlag) (ptr_t, error) { } } if pragmas.Len() != 0 { - c.checkInterrupt(handle) pragmaPtr := c.arena.string(pragmas.String()) rc := res_t(c.call("sqlite3_exec", stk_t(handle), stk_t(pragmaPtr), 0, 0, 0)) if err := c.sqlite.error(rc, handle, pragmas.String()); err != nil { @@ -163,9 +165,6 @@ func (c *Conn) Close() error { return nil } - c.pending.Close() - c.pending = nil - rc := res_t(c.call("sqlite3_close", stk_t(c.handle))) if err := c.error(rc); err != nil { return err @@ -180,11 +179,16 @@ func (c *Conn) Close() error { // // https://sqlite.org/c3ref/exec.html func (c *Conn) Exec(sql string) error { - defer c.arena.mark()() - sqlPtr := c.arena.string(sql) + if c.interrupt.Err() != nil { + return INTERRUPT + } + return c.exec(sql) +} - c.checkInterrupt(c.handle) - rc := res_t(c.call("sqlite3_exec", stk_t(c.handle), stk_t(sqlPtr), 0, 0, 0)) +func (c *Conn) exec(sql string) error { + defer c.arena.mark()() + textPtr := c.arena.string(sql) + rc := res_t(c.call("sqlite3_exec", stk_t(c.handle), stk_t(textPtr), 0, 0, 0)) return c.error(rc, sql) } @@ -203,20 +207,22 @@ func (c *Conn) PrepareFlags(sql string, flags PrepareFlag) (stmt *Stmt, tail str if len(sql) > _MAX_SQL_LENGTH { return nil, "", TOOBIG } + if c.interrupt.Err() != nil { + return nil, "", INTERRUPT + } defer c.arena.mark()() stmtPtr := c.arena.new(ptrlen) tailPtr := c.arena.new(ptrlen) - sqlPtr := c.arena.string(sql) + textPtr := c.arena.string(sql) - c.checkInterrupt(c.handle) rc := res_t(c.call("sqlite3_prepare_v3", stk_t(c.handle), - stk_t(sqlPtr), stk_t(len(sql)+1), stk_t(flags), + stk_t(textPtr), stk_t(len(sql)+1), stk_t(flags), stk_t(stmtPtr), stk_t(tailPtr))) - stmt = &Stmt{c: c} + stmt = &Stmt{c: c, sql: sql} stmt.handle = util.Read32[ptr_t](c.mod, stmtPtr) - if sql := sql[util.Read32[ptr_t](c.mod, tailPtr)-sqlPtr:]; sql != "" { + if sql := sql[util.Read32[ptr_t](c.mod, tailPtr)-textPtr:]; sql != "" { tail = sql } @@ -337,43 +343,17 @@ func (c *Conn) GetInterrupt() context.Context { // // https://sqlite.org/c3ref/interrupt.html func (c *Conn) SetInterrupt(ctx context.Context) (old context.Context) { + if ctx == nil { + panic("nil Context") + } old = c.interrupt c.interrupt = ctx - - if ctx == old || ctx.Done() == old.Done() { - return old - } - - // A busy SQL statement prevents SQLite from ignoring an interrupt - // that comes before any other statements are started. - if c.pending == nil { - defer c.arena.mark()() - stmtPtr := c.arena.new(ptrlen) - loopPtr := c.arena.string(`WITH RECURSIVE c(x) AS (VALUES(0) UNION ALL SELECT x FROM c) SELECT x FROM c`) - c.call("sqlite3_prepare_v3", stk_t(c.handle), stk_t(loopPtr), math.MaxUint64, - stk_t(PREPARE_PERSISTENT), stk_t(stmtPtr), 0) - c.pending = &Stmt{c: c} - c.pending.handle = util.Read32[ptr_t](c.mod, stmtPtr) - } - - if old.Done() != nil && ctx.Err() == nil { - c.pending.Reset() - } - if ctx.Done() != nil { - c.pending.Step() - } return old } -func (c *Conn) checkInterrupt(handle ptr_t) { - if c.interrupt.Err() != nil { - c.call("sqlite3_interrupt", stk_t(handle)) - } -} - func progressCallback(ctx context.Context, mod api.Module, _ ptr_t) (interrupt int32) { if c, ok := ctx.Value(connKey{}).(*Conn); ok { - if c.interrupt.Done() != nil { + if c.gosched++; c.gosched%16 == 0 { runtime.Gosched() } if c.interrupt.Err() != nil { @@ -429,11 +409,8 @@ func (c *Conn) BusyHandler(cb func(ctx context.Context, count int) (retry bool)) func busyCallback(ctx context.Context, mod api.Module, pDB ptr_t, count int32) (retry int32) { if c, ok := ctx.Value(connKey{}).(*Conn); ok && c.handle == pDB && c.busy != nil { - interrupt := c.interrupt - if interrupt == nil { - interrupt = context.Background() - } - if interrupt.Err() == nil && c.busy(interrupt, int(count)) { + if interrupt := c.interrupt; interrupt.Err() == nil && + c.busy(interrupt, int(count)) { retry = 1 } } |
