From e2bae492fe5a70a562c18c86f7346b0508ec5c3b Mon Sep 17 00:00:00 2001 From: Jonathan Stacks Date: Fri, 22 Nov 2024 13:11:48 -0600 Subject: [PATCH] Add ability to a int64 file control --- sqlite3.go | 28 ++++++++++++++++++++++++++++ sqlite3_test.go | 29 +++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/sqlite3.go b/sqlite3.go index ce985ec8..4a7eb4e6 100644 --- a/sqlite3.go +++ b/sqlite3.go @@ -1893,6 +1893,34 @@ func (c *SQLiteConn) SetFileControlInt(dbName string, op int, arg int) error { return nil } +// SetFileControlInt invokes the xFileControl method on a given database. The +// dbName is the name of the database. It will default to "main" if left blank. +// The op is one of the opcodes prefixed by "SQLITE_FCNTL_". The arg argument +// and return code are both opcode-specific. Please see the SQLite documentation. +// +// This method is not thread-safe as the returned error code can be changed by +// another call if invoked concurrently. +// +// Prefer this method over SetFileControlInt when the argument to the underlying +// SQLite function is an int64. +// +// See: sqlite3_file_control, https://www.sqlite.org/c3ref/file_control.html +func (c *SQLiteConn) SetFileControlInt64(dbName string, op int, arg int64) error { + if dbName == "" { + dbName = "main" + } + + cDBName := C.CString(dbName) + defer C.free(unsafe.Pointer(cDBName)) + + cArg := C.sqlite3_int64(arg) + rv := C.sqlite3_file_control(c.db, cDBName, C.int(op), unsafe.Pointer(&cArg)) + if rv != C.SQLITE_OK { + return c.lastError() + } + return nil +} + // Close the statement. func (s *SQLiteStmt) Close() error { s.mu.Lock() diff --git a/sqlite3_test.go b/sqlite3_test.go index 63c939d3..e3356c09 100644 --- a/sqlite3_test.go +++ b/sqlite3_test.go @@ -1864,6 +1864,35 @@ func TestSetFileControlInt(t *testing.T) { }) } +func TestSetFileControlInt64(t *testing.T) { + const GiB = 1024 * 1024 * 1024 + + t.Run("", func(t *testing.T) { + + sql.Register("sqlite3_FCNTL_SIZE_LIMIT", &SQLiteDriver{ + ConnectHook: func(conn *SQLiteConn) error { + if err := conn.SetFileControlInt64("", SQLITE_FCNTL_SIZE_LIMIT, 4*GiB); err != nil { + return fmt.Errorf("Unexpected error from SetFileControlInt64(): %w", err) + } + return nil + }, + }) + + db, err := sql.Open("sqlite3", "file:/dbname?vfs=memdb") + if err != nil { + t.Fatal("Failed to open database:", err) + } + if err != nil { + t.Fatal("Failed to open", err) + } + err = db.Ping() + if err != nil { + t.Fatal("Failed to ping", err) + } + db.Close() + }) +} + func TestNonColumnString(t *testing.T) { db, err := sql.Open("sqlite3", ":memory:") if err != nil {