mirror of
https://github.com/ncruces/go-sqlite3.git
synced 2026-01-11 21:49:13 +00:00
Named parameters.
This commit is contained in:
8
api.go
8
api.go
@@ -45,12 +45,14 @@ func newConn(ctx context.Context, module api.Module) (_ *Conn, err error) {
|
||||
exec: getFun("sqlite3_exec"),
|
||||
clearBindings: getFun("sqlite3_clear_bindings"),
|
||||
bindCount: getFun("sqlite3_bind_parameter_count"),
|
||||
bindIndex: getFun("sqlite3_bind_parameter_index"),
|
||||
bindName: getFun("sqlite3_bind_parameter_name"),
|
||||
bindNull: getFun("sqlite3_bind_null"),
|
||||
bindInteger: getFun("sqlite3_bind_int64"),
|
||||
bindFloat: getFun("sqlite3_bind_double"),
|
||||
bindText: getFun("sqlite3_bind_text64"),
|
||||
bindBlob: getFun("sqlite3_bind_blob64"),
|
||||
bindZeroBlob: getFun("sqlite3_bind_zeroblob64"),
|
||||
bindNull: getFun("sqlite3_bind_null"),
|
||||
columnCount: getFun("sqlite3_column_count"),
|
||||
columnName: getFun("sqlite3_column_name"),
|
||||
columnType: getFun("sqlite3_column_type"),
|
||||
@@ -86,13 +88,15 @@ type sqliteAPI struct {
|
||||
step api.Function
|
||||
exec api.Function
|
||||
clearBindings api.Function
|
||||
bindNull api.Function
|
||||
bindCount api.Function
|
||||
bindIndex api.Function
|
||||
bindName api.Function
|
||||
bindInteger api.Function
|
||||
bindFloat api.Function
|
||||
bindText api.Function
|
||||
bindBlob api.Function
|
||||
bindZeroBlob api.Function
|
||||
bindNull api.Function
|
||||
columnCount api.Function
|
||||
columnName api.Function
|
||||
columnType api.Function
|
||||
|
||||
4
conn.go
4
conn.go
@@ -236,12 +236,12 @@ func (c *Conn) error(rc uint64, sql ...string) error {
|
||||
|
||||
r, _ = c.api.errstr.Call(c.ctx, rc)
|
||||
if r != nil {
|
||||
err.str = c.mem.readString(uint32(r[0]), 512)
|
||||
err.str = c.mem.readString(uint32(r[0]), _MAX_STRING)
|
||||
}
|
||||
|
||||
r, _ = c.api.errmsg.Call(c.ctx, uint64(c.handle))
|
||||
if r != nil {
|
||||
err.msg = c.mem.readString(uint32(r[0]), 512)
|
||||
err.msg = c.mem.readString(uint32(r[0]), _MAX_STRING)
|
||||
}
|
||||
|
||||
if sql != nil {
|
||||
|
||||
1
const.go
1
const.go
@@ -9,6 +9,7 @@ const (
|
||||
|
||||
_UTF8 = 1
|
||||
|
||||
_MAX_STRING = 512 // Used for short strings: names, error messages…
|
||||
_MAX_PATHNAME = 512
|
||||
|
||||
ptrlen = 4
|
||||
|
||||
@@ -29,12 +29,14 @@ zig cc --target=wasm32-wasi -flto -g0 -Os \
|
||||
-Wl,--export=sqlite3_exec \
|
||||
-Wl,--export=sqlite3_clear_bindings \
|
||||
-Wl,--export=sqlite3_bind_parameter_count \
|
||||
-Wl,--export=sqlite3_bind_parameter_index \
|
||||
-Wl,--export=sqlite3_bind_parameter_name \
|
||||
-Wl,--export=sqlite3_bind_null \
|
||||
-Wl,--export=sqlite3_bind_int64 \
|
||||
-Wl,--export=sqlite3_bind_double \
|
||||
-Wl,--export=sqlite3_bind_text64 \
|
||||
-Wl,--export=sqlite3_bind_blob64 \
|
||||
-Wl,--export=sqlite3_bind_zeroblob64 \
|
||||
-Wl,--export=sqlite3_bind_null \
|
||||
-Wl,--export=sqlite3_column_count \
|
||||
-Wl,--export=sqlite3_column_name \
|
||||
-Wl,--export=sqlite3_column_type \
|
||||
|
||||
Binary file not shown.
37
stmt.go
37
stmt.go
@@ -94,7 +94,7 @@ func (s *Stmt) Exec() error {
|
||||
return s.Reset()
|
||||
}
|
||||
|
||||
// BindCount gets the number of SQL parameters in a prepared statement.
|
||||
// BindCount returns the number of SQL parameters in the prepared statement.
|
||||
//
|
||||
// https://www.sqlite.org/c3ref/bind_parameter_count.html
|
||||
func (s *Stmt) BindCount() int {
|
||||
@@ -106,6 +106,39 @@ func (s *Stmt) BindCount() int {
|
||||
return int(r[0])
|
||||
}
|
||||
|
||||
// BindIndex returns the index of a parameter in the prepared statement
|
||||
// given its name.
|
||||
//
|
||||
// https://www.sqlite.org/c3ref/bind_parameter_index.html
|
||||
func (s *Stmt) BindIndex(name string) int {
|
||||
defer s.c.arena.reset()
|
||||
namePtr := s.c.arena.string(name)
|
||||
r, err := s.c.api.bindIndex.Call(s.c.ctx,
|
||||
uint64(s.handle), uint64(namePtr))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return int(r[0])
|
||||
}
|
||||
|
||||
// BindName returns the name of a parameter in the prepared statement.
|
||||
// The leftmost SQL parameter has an index of 1.
|
||||
//
|
||||
// https://www.sqlite.org/c3ref/bind_parameter_name.html
|
||||
func (s *Stmt) BindName(param int) string {
|
||||
r, err := s.c.api.bindName.Call(s.c.ctx,
|
||||
uint64(s.handle), uint64(param))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
ptr := uint32(r[0])
|
||||
if ptr == 0 {
|
||||
return ""
|
||||
}
|
||||
return s.c.mem.readString(ptr, _MAX_STRING)
|
||||
}
|
||||
|
||||
// BindBool binds a bool to the prepared statement.
|
||||
// The leftmost SQL parameter has an index of 1.
|
||||
// SQLite does not have a separate boolean storage class.
|
||||
@@ -226,7 +259,7 @@ func (s *Stmt) ColumnName(col int) string {
|
||||
if ptr == 0 {
|
||||
return ""
|
||||
}
|
||||
return s.c.mem.readString(ptr, 512)
|
||||
return s.c.mem.readString(ptr, _MAX_STRING)
|
||||
}
|
||||
|
||||
// ColumnType returns the initial [Datatype] of the result column.
|
||||
|
||||
32
stmt_test.go
32
stmt_test.go
@@ -366,3 +366,35 @@ func TestStmt_Close(t *testing.T) {
|
||||
var stmt *Stmt
|
||||
stmt.Close()
|
||||
}
|
||||
|
||||
func TestStmt_BindName(t *testing.T) {
|
||||
db, err := Open(":memory:")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
want := []string{"", "", "", "", "?5", ":AAA", "@AAA", "$AAA"}
|
||||
stmt, _, err := db.Prepare(`SELECT ?, ?5, :AAA, @AAA, $AAA`)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer stmt.Close()
|
||||
|
||||
if got := stmt.BindCount(); got != len(want) {
|
||||
t.Errorf("got %d, want %d", got, len(want))
|
||||
}
|
||||
|
||||
for i, name := range want {
|
||||
id := i + 1
|
||||
if got := stmt.BindName(id); got != name {
|
||||
t.Errorf("got %q, want %q", got, name)
|
||||
}
|
||||
if name == "" {
|
||||
id = 0
|
||||
}
|
||||
if got := stmt.BindIndex(name); got != id {
|
||||
t.Errorf("got %d, want %d", got, id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user