Skip to content

Add ability to set an int64 file control #1298

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Apr 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions sqlite3.go
Original file line number Diff line number Diff line change
Expand Up @@ -1876,6 +1876,9 @@ func (c *SQLiteConn) SetLimit(id int, newVal int) int {
// This method is not thread-safe as the returned error code can be changed by
// another call if invoked concurrently.
//
// Use SetFileControlInt64 instead if the argument for the opcode is documented
// as a pointer to a sqlite3_int64.
//
// See: sqlite3_file_control, https://www.sqlite.org/c3ref/file_control.html
func (c *SQLiteConn) SetFileControlInt(dbName string, op int, arg int) error {
if dbName == "" {
Expand All @@ -1893,6 +1896,34 @@ func (c *SQLiteConn) SetFileControlInt(dbName string, op int, arg int) error {
return nil
}

// SetFileControlInt64 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.
//
// Only use this method if the argument for the opcode is documented as a pointer
// to a sqlite3_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()
Expand Down
26 changes: 26 additions & 0 deletions sqlite3_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1864,6 +1864,32 @@ 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)
}
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 {
Expand Down