diff --git a/config.go b/config.go new file mode 100644 index 0000000..572fc94 --- /dev/null +++ b/config.go @@ -0,0 +1,29 @@ +package sqlite3 + +import "github.com/ncruces/go-sqlite3/internal/util" + +// Config makes configuration changes to a database connection. +// Only bool configuratiton options are supported. +// Called with no arg reads the current configuration value, +// called with one arg sets and returns the new value. +// +// https://sqlite.org/c3ref/db_config.html +func (c *Conn) Config(op DBConfig, arg ...bool) (bool, error) { + defer c.arena.mark()() + argsPtr := c.arena.new(2 * ptrlen) + + var flag int + switch { + case len(arg) == 0: + flag = -1 + case arg[0]: + flag = 1 + } + + util.WriteUint32(c.mod, argsPtr+0*ptrlen, uint32(flag)) + util.WriteUint32(c.mod, argsPtr+1*ptrlen, argsPtr) + + r := c.call("sqlite3_db_config", uint64(c.handle), + uint64(op), uint64(argsPtr)) + return util.ReadUint32(c.mod, argsPtr) != 0, c.error(r) +} diff --git a/const.go b/const.go index e10430e..49fda64 100644 --- a/const.go +++ b/const.go @@ -200,6 +200,34 @@ const ( STMTSTATUS_MEMUSED StmtStatus = 99 ) +// DBConfig are the available database connection configuration options. +// +// https://sqlite.org/c3ref/c_dbconfig_defensive.html +type DBConfig uint32 + +const ( + // DBCONFIG_MAINDBNAME DBConfig = 1000 + // DBCONFIG_LOOKASIDE DBConfig = 1001 + DBCONFIG_ENABLE_FKEY DBConfig = 1002 + DBCONFIG_ENABLE_TRIGGER DBConfig = 1003 + DBCONFIG_ENABLE_FTS3_TOKENIZER DBConfig = 1004 + DBCONFIG_ENABLE_LOAD_EXTENSION DBConfig = 1005 + DBCONFIG_NO_CKPT_ON_CLOSE DBConfig = 1006 + DBCONFIG_ENABLE_QPSG DBConfig = 1007 + DBCONFIG_TRIGGER_EQP DBConfig = 1008 + DBCONFIG_RESET_DATABASE DBConfig = 1009 + DBCONFIG_DEFENSIVE DBConfig = 1010 + DBCONFIG_WRITABLE_SCHEMA DBConfig = 1011 + DBCONFIG_LEGACY_ALTER_TABLE DBConfig = 1012 + DBCONFIG_DQS_DML DBConfig = 1013 + DBCONFIG_DQS_DDL DBConfig = 1014 + DBCONFIG_ENABLE_VIEW DBConfig = 1015 + DBCONFIG_LEGACY_FILE_FORMAT DBConfig = 1016 + DBCONFIG_TRUSTED_SCHEMA DBConfig = 1017 + DBCONFIG_STMT_SCANSTATUS DBConfig = 1018 + DBCONFIG_REVERSE_SCANORDER DBConfig = 1019 +) + // Datatype is a fundamental datatype of SQLite. // // https://sqlite.org/c3ref/c_blob.html diff --git a/embed/exports.txt b/embed/exports.txt index 0fefb37..8017168 100644 --- a/embed/exports.txt +++ b/embed/exports.txt @@ -44,6 +44,7 @@ sqlite3_create_collation_go sqlite3_create_function_go sqlite3_create_module_go sqlite3_create_window_function_go +sqlite3_db_config sqlite3_declare_vtab sqlite3_errcode sqlite3_errmsg diff --git a/embed/sqlite3.wasm b/embed/sqlite3.wasm index 1d2b2f7..b5dca1f 100755 Binary files a/embed/sqlite3.wasm and b/embed/sqlite3.wasm differ diff --git a/tests/conn_test.go b/tests/conn_test.go index cece594..8cf037b 100644 --- a/tests/conn_test.go +++ b/tests/conn_test.go @@ -289,3 +289,53 @@ func TestConn_Prepare_invalid(t *testing.T) { t.Error("got message:", got) } } + +func TestConn_Config(t *testing.T) { + t.Parallel() + + db, err := sqlite3.Open(":memory:") + if err != nil { + t.Fatal(err) + } + defer db.Close() + + o, err := db.Config(sqlite3.DBCONFIG_DEFENSIVE) + if err != nil { + t.Fatal(err) + } + if o != false { + t.Error("want false") + } + + o, err = db.Config(sqlite3.DBCONFIG_DEFENSIVE, true) + if err != nil { + t.Fatal(err) + } + if o != true { + t.Error("want true") + } + + o, err = db.Config(sqlite3.DBCONFIG_DEFENSIVE) + if err != nil { + t.Fatal(err) + } + if o != true { + t.Error("want true") + } + + o, err = db.Config(sqlite3.DBCONFIG_DEFENSIVE, false) + if err != nil { + t.Fatal(err) + } + if o != false { + t.Error("want false") + } + + o, err = db.Config(sqlite3.DBCONFIG_DEFENSIVE) + if err != nil { + t.Fatal(err) + } + if o != false { + t.Error("want false") + } +}