Unprotected values.

This commit is contained in:
Nuno Cruces
2023-11-29 16:09:30 +00:00
parent 3f05115cd7
commit dbaf2d99cd
6 changed files with 51 additions and 10 deletions

View File

@@ -26,6 +26,7 @@ sqlite3_bind_text64
sqlite3_bind_blob64
sqlite3_bind_zeroblob64
sqlite3_bind_pointer_go
sqlite3_bind_value
sqlite3_column_count
sqlite3_column_name
sqlite3_column_type
@@ -34,6 +35,7 @@ sqlite3_column_double
sqlite3_column_text
sqlite3_column_blob
sqlite3_column_bytes
sqlite3_column_value
sqlite3_blob_open
sqlite3_blob_close
sqlite3_blob_reopen

Binary file not shown.

View File

@@ -133,6 +133,7 @@ func instantiateSQLite() (sqlt *sqlite, err error) {
bindBlob: getFun("sqlite3_bind_blob64"),
bindZeroBlob: getFun("sqlite3_bind_zeroblob64"),
bindPointer: getFun("sqlite3_bind_pointer_go"),
bindValue: getFun("sqlite3_bind_value"),
columnCount: getFun("sqlite3_column_count"),
columnName: getFun("sqlite3_column_name"),
columnType: getFun("sqlite3_column_type"),
@@ -141,6 +142,7 @@ func instantiateSQLite() (sqlt *sqlite, err error) {
columnText: getFun("sqlite3_column_text"),
columnBlob: getFun("sqlite3_column_blob"),
columnBytes: getFun("sqlite3_column_bytes"),
columnValue: getFun("sqlite3_column_value"),
blobOpen: getFun("sqlite3_blob_open"),
blobClose: getFun("sqlite3_blob_close"),
blobReopen: getFun("sqlite3_blob_reopen"),
@@ -367,6 +369,7 @@ type sqliteAPI struct {
bindBlob api.Function
bindZeroBlob api.Function
bindPointer api.Function
bindValue api.Function
columnCount api.Function
columnName api.Function
columnType api.Function
@@ -375,6 +378,7 @@ type sqliteAPI struct {
columnText api.Function
columnBlob api.Function
columnBytes api.Function
columnValue api.Function
blobOpen api.Function
blobClose api.Function
blobReopen api.Function

27
stmt.go
View File

@@ -297,6 +297,19 @@ func (s *Stmt) BindJSON(param int, value any) error {
return s.BindRawText(param, data)
}
// BindValue binds a copy of value to the prepared statement.
// The leftmost SQL parameter has an index of 1.
//
// https://sqlite.org/c3ref/bind_blob.html
func (s *Stmt) BindValue(param int, value Value) error {
if value.sqlite != s.c.sqlite {
return MISUSE
}
r := s.c.call(s.c.api.bindValue,
uint64(s.handle), uint64(param), uint64(value.handle))
return s.c.error(r)
}
// ColumnCount returns the number of columns in a result set.
//
// https://sqlite.org/c3ref/column_count.html
@@ -475,6 +488,20 @@ func (s *Stmt) ColumnJSON(col int, ptr any) error {
return json.Unmarshal(data, ptr)
}
// ColumnValue returns the unprotected value of the result column.
// The leftmost column of the result set has the index 0.
//
// https://sqlite.org/c3ref/column_blob.html
func (s *Stmt) ColumnValue(col int) Value {
r := s.c.call(s.c.api.columnValue,
uint64(s.handle), uint64(col))
return Value{
unprot: true,
sqlite: s.c.sqlite,
handle: uint32(r),
}
}
// Return true if stmt is an empty SQL statement.
// This is used as an optimization.
// It's OK to always return false here.

View File

@@ -15,13 +15,21 @@ import (
type Value struct {
*sqlite
handle uint32
unprot bool
}
func (v Value) protected() uint64 {
if v.unprot {
panic(util.ValueErr)
}
return uint64(v.handle)
}
// Type returns the initial [Datatype] of the value.
//
// https://sqlite.org/c3ref/value_blob.html
func (v Value) Type() Datatype {
r := v.call(v.api.valueType, uint64(v.handle))
r := v.call(v.api.valueType, v.protected())
return Datatype(r)
}
@@ -49,7 +57,7 @@ func (v Value) Int() int {
//
// https://sqlite.org/c3ref/value_blob.html
func (v Value) Int64() int64 {
r := v.call(v.api.valueInteger, uint64(v.handle))
r := v.call(v.api.valueInteger, v.protected())
return int64(r)
}
@@ -57,7 +65,7 @@ func (v Value) Int64() int64 {
//
// https://sqlite.org/c3ref/value_blob.html
func (v Value) Float() float64 {
r := v.call(v.api.valueFloat, uint64(v.handle))
r := v.call(v.api.valueFloat, v.protected())
return math.Float64frombits(r)
}
@@ -103,7 +111,7 @@ func (v Value) Blob(buf []byte) []byte {
//
// https://sqlite.org/c3ref/value_blob.html
func (v Value) RawText() []byte {
r := v.call(v.api.valueText, uint64(v.handle))
r := v.call(v.api.valueText, v.protected())
return v.rawBytes(uint32(r))
}
@@ -113,7 +121,7 @@ func (v Value) RawText() []byte {
//
// https://sqlite.org/c3ref/value_blob.html
func (v Value) RawBlob() []byte {
r := v.call(v.api.valueBlob, uint64(v.handle))
r := v.call(v.api.valueBlob, v.protected())
return v.rawBytes(uint32(r))
}
@@ -122,14 +130,14 @@ func (v Value) rawBytes(ptr uint32) []byte {
return nil
}
r := v.call(v.api.valueBytes, uint64(v.handle))
r := v.call(v.api.valueBytes, v.protected())
return util.View(v.mod, ptr, r)
}
// Pointer gets the pointer associated with this value,
// or nil if it has no associated pointer.
func (v Value) Pointer() any {
r := v.call(v.api.valuePointer, uint64(v.handle))
r := v.call(v.api.valuePointer, v.protected())
return util.GetHandle(v.ctx, uint32(r))
}

View File

@@ -254,15 +254,15 @@ type IndexConstraintUsage struct {
// if the right-hand operand is known.
//
// https://sqlite.org/c3ref/vtab_rhs_value.html
func (idx *IndexInfo) RHSValue(column int) (*Value, error) {
func (idx *IndexInfo) RHSValue(column int) (Value, error) {
defer idx.c.arena.mark()()
valPtr := idx.c.arena.new(ptrlen)
r := idx.c.call(idx.c.api.vtabRHSValue,
uint64(idx.handle), uint64(column), uint64(valPtr))
if err := idx.c.error(r); err != nil {
return nil, err
return Value{}, err
}
return &Value{
return Value{
sqlite: idx.c.sqlite,
handle: util.ReadUint32(idx.c.mod, valPtr),
}, nil