New APIs.

This commit is contained in:
Nuno Cruces
2024-01-17 15:39:13 +00:00
parent bce66299ab
commit 35bbd8a0b0
8 changed files with 161 additions and 2 deletions

52
conn.go
View File

@@ -194,6 +194,32 @@ func (c *Conn) PrepareFlags(sql string, flags PrepareFlag) (stmt *Stmt, tail str
return stmt, tail, nil
}
// DBName returns the schema name for n-th database on the database connection.
//
// https://sqlite.org/c3ref/db_name.html
func (c *Conn) DBName(n int) string {
r := c.call("sqlite3_db_name", uint64(c.handle), uint64(n))
ptr := uint32(r)
if ptr == 0 {
return ""
}
return util.ReadString(c.mod, ptr, _MAX_NAME)
}
// ReadOnly determines if a database is read-only.
//
// https://sqlite.org/c3ref/db_readonly.html
func (c *Conn) ReadOnly(schema string) (ro bool, ok bool) {
var ptr uint32
if schema != "" {
defer c.arena.mark()()
ptr = c.arena.string(schema)
}
r := c.call("sqlite3_db_readonly", uint64(c.handle), uint64(ptr))
return int8(r) > 0, int8(r) < 0
}
// GetAutocommit tests the connection for auto-commit mode.
//
// https://sqlite.org/c3ref/get_autocommit.html
@@ -211,6 +237,14 @@ func (c *Conn) LastInsertRowID() int64 {
return int64(r)
}
// SetLastInsertRowID allows the application to set the value returned by
// [Conn.LastInsertRowID].
//
// https://sqlite.org/c3ref/set_last_insert_rowid.html
func (c *Conn) SetLastInsertRowID(id int64) {
c.call("sqlite3_set_last_insert_rowid", uint64(c.handle), uint64(id))
}
// Changes returns the number of rows modified, inserted or deleted
// by the most recently completed INSERT, UPDATE or DELETE statement
// on the database connection.
@@ -221,6 +255,24 @@ func (c *Conn) Changes() int64 {
return int64(r)
}
// TotalChanges returns the number of rows modified, inserted or deleted
// by all INSERT, UPDATE or DELETE statements completed
// since the database connection was opened.
//
// https://sqlite.org/c3ref/total_changes.html
func (c *Conn) TotalChanges() int64 {
r := c.call("sqlite3_total_changes64", uint64(c.handle))
return int64(r)
}
// ReleaseMemory frees memory used by a database connection.
//
// https://sqlite.org/c3ref/db_release_memory.html
func (c *Conn) ReleaseMemory() error {
r := c.call("sqlite3_db_release_memory", uint64(c.handle))
return c.error(r)
}
// SetInterrupt interrupts a long-running query when a context is done.
//
// Subsequent uses of the connection will return [INTERRUPT]

View File

@@ -229,6 +229,17 @@ const (
DBCONFIG_REVERSE_SCANORDER DBConfig = 1019
)
// TxnState are the allowed return values from [Conn.TxnState].
//
// https://sqlite.org/c3ref/c_txn_none.html
type TxnState uint32
const (
TXN_NONE TxnState = 0
TXN_READ TxnState = 1
TXN_WRITE TxnState = 2
)
// Datatype is a fundamental datatype of SQLite.
//
// https://sqlite.org/c3ref/c_blob.html

View File

@@ -1,7 +1,6 @@
free
malloc
malloc_destructor
sqlite3_aggregate_context
sqlite3_anycollseq_init
sqlite3_backup_finish
sqlite3_backup_init
@@ -47,6 +46,9 @@ sqlite3_create_function_go
sqlite3_create_module_go
sqlite3_create_window_function_go
sqlite3_db_config
sqlite3_db_name
sqlite3_db_readonly
sqlite3_db_release_memory
sqlite3_declare_vtab
sqlite3_errcode
sqlite3_errmsg
@@ -58,6 +60,7 @@ sqlite3_get_autocommit
sqlite3_get_auxdata
sqlite3_interrupt
sqlite3_last_insert_rowid
sqlite3_limit
sqlite3_open_v2
sqlite3_overload_function
sqlite3_prepare_v3
@@ -76,13 +79,15 @@ sqlite3_result_text64
sqlite3_result_value
sqlite3_result_zeroblob64
sqlite3_set_auxdata_go
sqlite3_set_last_insert_rowid
sqlite3_step
sqlite3_stmt_busy
sqlite3_stmt_readonly
sqlite3_stmt_status
sqlite3_total_changes64
sqlite3_txn_state
sqlite3_uri_key
sqlite3_uri_parameter
sqlite3_user_data
sqlite3_value_blob
sqlite3_value_bytes
sqlite3_value_double

Binary file not shown.

View File

@@ -371,6 +371,12 @@ func TestBlob_Reopen(t *testing.T) {
}
rowids = append(rowids, db.LastInsertRowID())
}
if changes := db.Changes(); changes != 1 {
t.Errorf("got %d want 1", changes)
}
if changes := db.TotalChanges(); changes != 100 {
t.Errorf("got %d want 100", changes)
}
var blob *sqlite3.Blob

View File

@@ -364,3 +364,71 @@ func TestConn_ConfigLog(t *testing.T) {
t.Error("want sqlite3.ERROR")
}
}
func TestConn_ReleaseMemory(t *testing.T) {
t.Parallel()
db, err := sqlite3.Open(":memory:")
if err != nil {
t.Fatal(err)
}
defer db.Close()
err = db.ReleaseMemory()
if err != nil {
t.Fatal(err)
}
}
func TestConn_SetLastInsertRowID(t *testing.T) {
t.Parallel()
db, err := sqlite3.Open(":memory:")
if err != nil {
t.Fatal(err)
}
defer db.Close()
db.SetLastInsertRowID(42)
got := db.LastInsertRowID()
if got != 42 {
t.Errorf("got %d, want 42", got)
}
}
func TestConn_ReadOnly(t *testing.T) {
t.Parallel()
db, err := sqlite3.Open(":memory:")
if err != nil {
t.Fatal(err)
}
defer db.Close()
if ro, ok := db.ReadOnly(""); ro != false || ok != false {
t.Errorf("got %v,%v", ro, ok)
}
if ro, ok := db.ReadOnly("xpto"); ro != false || ok != true {
t.Errorf("got %v,%v", ro, ok)
}
}
func TestConn_DBName(t *testing.T) {
t.Parallel()
db, err := sqlite3.Open(":memory:")
if err != nil {
t.Fatal(err)
}
defer db.Close()
if name := db.DBName(0); name != "main" {
t.Errorf("got %s", name)
}
if name := db.DBName(5); name != "" {
t.Errorf("got %s", name)
}
}

View File

@@ -47,6 +47,10 @@ func TestConn_Transaction_exec(t *testing.T) {
t.Fatal(err)
}
if s := db.TxnState("main"); s != sqlite3.TXN_WRITE {
t.Errorf("got %d", s)
}
if succeed {
return nil
}

13
tx.go
View File

@@ -213,3 +213,16 @@ func (c *Conn) txExecInterrupted(sql string) error {
}
return err
}
// TxnState starts a deferred transaction.
//
// https://sqlite.org/c3ref/txn_state.html
func (c *Conn) TxnState(schema string) TxnState {
var ptr uint32
if schema != "" {
defer c.arena.mark()()
ptr = c.arena.string(schema)
}
r := c.call("sqlite3_txn_state", uint64(c.handle), uint64(ptr))
return TxnState(r)
}