mirror of
https://github.com/ncruces/go-sqlite3.git
synced 2026-01-11 21:49:13 +00:00
Better fix #249.
This commit is contained in:
@@ -279,6 +279,8 @@ func (c *Conn) WALCheckpoint(schema string, mode CheckpointMode) (nLog, nCkpt in
|
|||||||
nLogPtr := c.arena.new(ptrlen)
|
nLogPtr := c.arena.new(ptrlen)
|
||||||
nCkptPtr := c.arena.new(ptrlen)
|
nCkptPtr := c.arena.new(ptrlen)
|
||||||
schemaPtr := c.arena.string(schema)
|
schemaPtr := c.arena.string(schema)
|
||||||
|
|
||||||
|
c.checkInterrupt()
|
||||||
rc := res_t(c.call("sqlite3_wal_checkpoint_v2",
|
rc := res_t(c.call("sqlite3_wal_checkpoint_v2",
|
||||||
stk_t(c.handle), stk_t(schemaPtr), stk_t(mode),
|
stk_t(c.handle), stk_t(schemaPtr), stk_t(mode),
|
||||||
stk_t(nLogPtr), stk_t(nCkptPtr)))
|
stk_t(nLogPtr), stk_t(nCkptPtr)))
|
||||||
@@ -350,8 +352,6 @@ func (c *Conn) HardHeapLimit(n int64) int64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// EnableChecksums enables checksums on a database.
|
// EnableChecksums enables checksums on a database.
|
||||||
// If the database is in WAL mode,
|
|
||||||
// you should shutdown and reopen all database connections before continuing.
|
|
||||||
//
|
//
|
||||||
// https://sqlite.org/cksumvfs.html
|
// https://sqlite.org/cksumvfs.html
|
||||||
func (c *Conn) EnableChecksums(schema string) error {
|
func (c *Conn) EnableChecksums(schema string) error {
|
||||||
@@ -390,6 +390,6 @@ func (c *Conn) EnableChecksums(schema string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Checkpoint the WAL.
|
// Checkpoint the WAL.
|
||||||
_, _, err = c.WALCheckpoint(schema, CHECKPOINT_RESTART)
|
_, _, err = c.WALCheckpoint(schema, CHECKPOINT_FULL)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
4
conn.go
4
conn.go
@@ -185,10 +185,10 @@ func (c *Conn) Close() error {
|
|||||||
// https://sqlite.org/c3ref/exec.html
|
// https://sqlite.org/c3ref/exec.html
|
||||||
func (c *Conn) Exec(sql string) error {
|
func (c *Conn) Exec(sql string) error {
|
||||||
defer c.arena.mark()()
|
defer c.arena.mark()()
|
||||||
sqlPtr := c.arena.string(sql)
|
textPtr := c.arena.string(sql)
|
||||||
|
|
||||||
c.checkInterrupt()
|
c.checkInterrupt()
|
||||||
rc := res_t(c.call("sqlite3_exec", stk_t(c.handle), stk_t(sqlPtr), 0, 0, 0))
|
rc := res_t(c.call("sqlite3_exec", stk_t(c.handle), stk_t(textPtr), 0, 0, 0))
|
||||||
return c.error(rc, sql)
|
return c.error(rc, sql)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
24
vfs/cksm.go
24
vfs/cksm.go
@@ -49,9 +49,7 @@ func (c cksmFile) ReadAt(p []byte, off int64) (n int, err error) {
|
|||||||
n, err = c.File.ReadAt(p, off)
|
n, err = c.File.ReadAt(p, off)
|
||||||
p = p[:n]
|
p = p[:n]
|
||||||
|
|
||||||
// SQLite is reading the header of a database file.
|
if isHeader(c.isDB, p, off) {
|
||||||
if c.isDB && off == 0 && len(p) >= 100 &&
|
|
||||||
bytes.HasPrefix(p, []byte("SQLite format 3\000")) {
|
|
||||||
c.init((*[100]byte)(p))
|
c.init((*[100]byte)(p))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,9 +65,7 @@ func (c cksmFile) ReadAt(p []byte, off int64) (n int, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c cksmFile) WriteAt(p []byte, off int64) (n int, err error) {
|
func (c cksmFile) WriteAt(p []byte, off int64) (n int, err error) {
|
||||||
// SQLite is writing the first page of a database file.
|
if isHeader(c.isDB, p, off) {
|
||||||
if (!c.isDB || off == 0) && sql3util.ValidPageSize(len(p)) &&
|
|
||||||
bytes.HasPrefix(p, []byte("SQLite format 3\000")) {
|
|
||||||
c.init((*[100]byte)(p))
|
c.init((*[100]byte)(p))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,9 +112,11 @@ func (c cksmFile) fileControl(ctx context.Context, mod api.Module, op _FcntlOpco
|
|||||||
c.inCkpt = true
|
c.inCkpt = true
|
||||||
case _FCNTL_CKPT_DONE:
|
case _FCNTL_CKPT_DONE:
|
||||||
c.inCkpt = false
|
c.inCkpt = false
|
||||||
}
|
case _FCNTL_PRAGMA:
|
||||||
if rc := vfsFileControlImpl(ctx, mod, c, op, pArg); rc != _NOTFOUND {
|
rc := vfsFileControlImpl(ctx, mod, c, op, pArg)
|
||||||
return rc
|
if rc != _NOTFOUND {
|
||||||
|
return rc
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return vfsFileControlImpl(ctx, mod, c.File, op, pArg)
|
return vfsFileControlImpl(ctx, mod, c.File, op, pArg)
|
||||||
}
|
}
|
||||||
@@ -135,6 +133,14 @@ func (f *cksmFlags) init(header *[100]byte) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isHeader(isDB bool, p []byte, off int64) bool {
|
||||||
|
check := sql3util.ValidPageSize(len(p))
|
||||||
|
if isDB {
|
||||||
|
check = off == 0 && len(p) >= 100
|
||||||
|
}
|
||||||
|
return check && bytes.HasPrefix(p, []byte("SQLite format 3\000"))
|
||||||
|
}
|
||||||
|
|
||||||
func cksmCompute(a []byte) (cksm [8]byte) {
|
func cksmCompute(a []byte) (cksm [8]byte) {
|
||||||
var s1, s2 uint32
|
var s1, s2 uint32
|
||||||
for len(a) >= 8 {
|
for len(a) >= 8 {
|
||||||
|
|||||||
6
vtab.go
6
vtab.go
@@ -80,8 +80,10 @@ func implements[T any](typ reflect.Type) bool {
|
|||||||
// https://sqlite.org/c3ref/declare_vtab.html
|
// https://sqlite.org/c3ref/declare_vtab.html
|
||||||
func (c *Conn) DeclareVTab(sql string) error {
|
func (c *Conn) DeclareVTab(sql string) error {
|
||||||
defer c.arena.mark()()
|
defer c.arena.mark()()
|
||||||
sqlPtr := c.arena.string(sql)
|
textPtr := c.arena.string(sql)
|
||||||
rc := res_t(c.call("sqlite3_declare_vtab", stk_t(c.handle), stk_t(sqlPtr)))
|
|
||||||
|
c.checkInterrupt()
|
||||||
|
rc := res_t(c.call("sqlite3_declare_vtab", stk_t(c.handle), stk_t(textPtr)))
|
||||||
return c.error(rc)
|
return c.error(rc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user