chore: ⬆️ updated deps

This commit is contained in:
2026-05-20 22:52:20 +02:00
parent d9f27c1775
commit 43f4680176
374 changed files with 295527 additions and 301467 deletions
+135 -17
View File
@@ -29,7 +29,9 @@ type conn struct {
writeTimeFormat string
beginMode string
loc *time.Location
intToTime bool
textToTime bool
integerTimeFormat string
}
@@ -62,6 +64,7 @@ func newConn(dsn string) (*conn, error) {
sqlite3.SQLITE_OPEN_URI,
)
if err != nil {
c.tls.Close()
return nil, err
}
@@ -86,12 +89,18 @@ func (c *conn) parseTime(s string) (interface{}, bool) {
return v, true
}
ts := strings.TrimSuffix(s, "Z")
ts, hadZ := strings.CutSuffix(s, "Z")
for _, f := range parseTimeFormats {
t, err := time.Parse(f, ts)
var t time.Time
var err error
if c.loc != nil && !hadZ {
t, err = time.ParseInLocation(f, ts, c.loc)
} else {
t, err = time.Parse(f, ts)
}
if err == nil {
return t, true
return c.applyTimezone(t), true
}
}
@@ -101,6 +110,8 @@ func (c *conn) parseTime(s string) (interface{}, bool) {
// 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.
// This intentionally uses time.Parse, not time.ParseInLocation,
// because the format already contains timezone information (-0700 MST).
func (c *conn) parseTimeString(s0 string, x int) (interface{}, bool) {
s := s0
if x > 0 {
@@ -108,19 +119,28 @@ func (c *conn) parseTimeString(s0 string, x int) (interface{}, bool) {
}
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 c.applyTimezone(t), true
}
return s0, false
}
func (c *conn) applyTimezone(t time.Time) time.Time {
if c.loc == nil {
return t
}
return t.In(c.loc)
}
// writeTimeFormats are the names and formats supported
// by the `_time_format` DSN query param.
var writeTimeFormats = map[string]string{
"sqlite": parseTimeFormats[0],
"sqlite": parseTimeFormats[0],
"datetime": "2006-01-02 15:04:05",
}
func (c *conn) formatTime(t time.Time) string {
t = c.applyTimezone(t)
// Before configurable write time formats were supported,
// time.Time.String was used. Maintain that default to
// keep existing driver users formatting times the same.
@@ -215,6 +235,71 @@ func (c *conn) columnName(pstmt uintptr, n int) (string, error) {
return libc.GoString(p), nil
}
// ColumnInfo returns column information for query.
// It does not execute query.
//
// For output columns that are expressions, function calls, or constants —
// or otherwise do not resolve to a single column — the DatabaseName,
// TableName, and OriginName fields of the corresponding ColumnInfo are
// empty, per the sqlite3 contract.
//
// Sample usage:
//
// err := conn.Raw(func(driverConn any) error {
// ci, ok := driverConn.(interface{ ColumnInfo(query string) ([]sqlite.ColumnInfo, error) })
// if !ok {
// return fmt.Errorf("driver does not support ColumnInfo")
// }
// info, err := ci.ColumnInfo(query)
// if err != nil {
// return err
// }
// // use info
// return nil
// })
func (c *conn) ColumnInfo(query string) (_ []ColumnInfo, err error) {
p, err := libc.CString(query)
if err != nil {
return nil, err
}
defer c.free(p)
psql := p
pstmt, err := c.prepareV2(&psql)
if err != nil {
return nil, err
}
if pstmt == 0 {
// Empty or comment-only query: no columns to describe.
return nil, nil
}
defer func() {
if e := c.finalize(pstmt); err == nil {
err = e
}
}()
n, err := c.columnCount(pstmt)
if err != nil {
return nil, err
}
info := make([]ColumnInfo, n)
for i := range n {
name, err := c.columnName(pstmt, i)
if err != nil {
return nil, err
}
info[i] = ColumnInfo{
Name: name,
DeclType: c.columnDeclType(pstmt, i),
DatabaseName: libc.GoString(sqlite3.Xsqlite3_column_database_name(c.tls, pstmt, int32(i))),
TableName: libc.GoString(sqlite3.Xsqlite3_column_table_name(c.tls, pstmt, int32(i))),
OriginName: libc.GoString(sqlite3.Xsqlite3_column_origin_name(c.tls, pstmt, int32(i))),
}
}
return info, nil
}
// C documentation
//
// int sqlite3_column_count(sqlite3_stmt *pStmt);
@@ -291,9 +376,7 @@ func (c *conn) bind(pstmt uintptr, n int, args []driver.NamedValue) (allocs []ui
return
}
for _, v := range allocs {
c.free(v)
}
c.freeAllocs(allocs)
allocs = nil
}()
@@ -600,7 +683,18 @@ func (c *conn) openV2(name, vfsName string, flags int32) (uintptr, error) {
}
if rc := sqlite3.Xsqlite3_open_v2(c.tls, s, p, flags, vfs); rc != sqlite3.SQLITE_OK {
return 0, c.errstr(rc)
dbh := *(*uintptr)(unsafe.Pointer(p))
// Per SQLite docs, sqlite3_open_v2 may allocate a handle even on
// failure. The error message is stored on that handle, and it must
// be closed to avoid leaking resources.
var err error
if dbh != 0 {
err = errstrForDB(c.tls, rc, dbh)
sqlite3.Xsqlite3_close_v2(c.tls, dbh)
} else {
err = c.errstr(rc)
}
return 0, err
}
return *(*uintptr)(unsafe.Pointer(p)), nil
@@ -620,18 +714,31 @@ func (c *conn) free(p uintptr) {
}
}
func (c *conn) freeAllocs(allocs []uintptr) {
for _, v := range allocs {
c.free(v)
}
}
// C documentation
//
// 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)
return errstrForDB(c.tls, rc, c.db)
}
func errstrForDB(tls *libc.TLS, rc int32, db uintptr) error {
pStr := sqlite3.Xsqlite3_errstr(tls, rc)
str := libc.GoString(pStr)
var s string
if rc == sqlite3.SQLITE_BUSY {
s = " (SQLITE_BUSY)"
}
switch msg := libc.GoString(p); {
if db == 0 {
return &Error{msg: fmt.Sprintf("%s (%v)%s", str, rc, s), code: int(rc)}
}
pMsg := sqlite3.Xsqlite3_errmsg(tls, db)
switch msg := libc.GoString(pMsg); {
case msg == str:
return &Error{msg: fmt.Sprintf("%s (%v)%s", str, rc, s), code: int(rc)}
default:
@@ -913,15 +1020,22 @@ func (c *conn) Serialize() (v []byte, err error) {
return v, nil
}
// Deserialize restore a database from the content returned by Serialize.
// Deserialize restores a database from the content returned by Serialize.
func (c *conn) Deserialize(buf []byte) (err error) {
bufLen := len(buf)
pBuf := c.tls.Alloc(bufLen) // free will be done if it fails or on close, must not be freed here
if bufLen == 0 {
return fmt.Errorf("sqlite: empty buffer passed to Deserialize")
}
pBuf := sqlite3.Xsqlite3_malloc64(c.tls, uint64(bufLen))
if pBuf == 0 {
return fmt.Errorf("sqlite: cannot allocate %d bytes for deserialize", bufLen)
}
copy((*libc.RawMem)(unsafe.Pointer(pBuf))[:bufLen:bufLen], buf)
zSchema := sqlite3.Xsqlite3_db_name(c.tls, c.db, 0)
if zSchema == 0 {
sqlite3.Xsqlite3_free(c.tls, pBuf)
return fmt.Errorf("failed to get main db name")
}
@@ -978,8 +1092,12 @@ func (c *conn) backup(remoteConn *conn, restore bool) (_ *Backup, finalErr error
pBackup = sqlite3.Xsqlite3_backup_init(c.tls, remoteConn.db, dstSchema, c.db, srcSchema)
}
if pBackup <= 0 {
rc := sqlite3.Xsqlite3_errcode(c.tls, remoteConn.db)
return nil, c.errstr(rc)
destDb := remoteConn.db
if restore {
destDb = c.db
}
rc := sqlite3.Xsqlite3_errcode(c.tls, destDb)
return nil, errstrForDB(c.tls, rc, destDb)
}
return &Backup{srcConn: c, dstConn: remoteConn, pBackup: pBackup}, nil