Skip to content

Commit b0f8ff4

Browse files
committed
Support subtype.
1 parent f37bca6 commit b0f8ff4

File tree

12 files changed

+84
-76
lines changed

12 files changed

+84
-76
lines changed

const.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -185,12 +185,12 @@ const (
185185
type FunctionFlag uint32
186186

187187
const (
188-
DETERMINISTIC FunctionFlag = 0x000000800
189-
DIRECTONLY FunctionFlag = 0x000080000
190-
INNOCUOUS FunctionFlag = 0x000200000
191-
SELFORDER1 FunctionFlag = 0x002000000
192-
// SUBTYPE FunctionFlag = 0x000100000
193-
// RESULT_SUBTYPE FunctionFlag = 0x001000000
188+
DETERMINISTIC FunctionFlag = 0x000000800
189+
DIRECTONLY FunctionFlag = 0x000080000
190+
SUBTYPE FunctionFlag = 0x000100000
191+
INNOCUOUS FunctionFlag = 0x000200000
192+
RESULT_SUBTYPE FunctionFlag = 0x001000000
193+
SELFORDER1 FunctionFlag = 0x002000000
194194
)
195195

196196
// StmtStatus name counter values associated with the [Stmt.Status] method.

context.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,14 @@ func (ctx Context) ResultError(err error) {
227227
}
228228
}
229229

230+
// ResultSubtype sets the subtype of the result of the function.
231+
//
232+
// https://sqlite.org/c3ref/result_subtype.html
233+
func (ctx Context) ResultSubtype(t uint) {
234+
ctx.c.call("sqlite3_result_subtype",
235+
stk_t(ctx.handle), stk_t(uint32(t)))
236+
}
237+
230238
// VTabNoChange may return true if a column is being fetched as part
231239
// of an update during which the column value will not change.
232240
//

embed/bcw2/bcw2.wasm

176 Bytes
Binary file not shown.

embed/exports.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ sqlite3_result_error_toobig
9898
sqlite3_result_int64
9999
sqlite3_result_null
100100
sqlite3_result_pointer_go
101+
sqlite3_result_subtype
101102
sqlite3_result_text_go
102103
sqlite3_result_value
103104
sqlite3_result_zeroblob64
@@ -126,6 +127,7 @@ sqlite3_value_int64
126127
sqlite3_value_nochange
127128
sqlite3_value_numeric_type
128129
sqlite3_value_pointer_go
130+
sqlite3_value_subtype
129131
sqlite3_value_text
130132
sqlite3_value_type
131133
sqlite3_vtab_collation

embed/sqlite3.wasm

176 Bytes
Binary file not shown.

ext/stats/stats.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,11 @@ import (
5858

5959
// Register registers statistics functions.
6060
func Register(db *sqlite3.Conn) error {
61-
const flags = sqlite3.DETERMINISTIC | sqlite3.INNOCUOUS
62-
const order = sqlite3.SELFORDER1 | flags
61+
const (
62+
flags = sqlite3.DETERMINISTIC | sqlite3.INNOCUOUS
63+
json = sqlite3.RESULT_SUBTYPE | flags
64+
order = sqlite3.SELFORDER1 | flags
65+
)
6366
return errors.Join(
6467
db.CreateWindowFunction("var_pop", 1, flags, newVariance(var_pop)),
6568
db.CreateWindowFunction("var_samp", 1, flags, newVariance(var_samp)),
@@ -81,7 +84,7 @@ func Register(db *sqlite3.Conn) error {
8184
db.CreateWindowFunction("regr_slope", 2, flags, newCovariance(regr_slope)),
8285
db.CreateWindowFunction("regr_intercept", 2, flags, newCovariance(regr_intercept)),
8386
db.CreateWindowFunction("regr_count", 2, flags, newCovariance(regr_count)),
84-
db.CreateWindowFunction("regr_json", 2, flags, newCovariance(regr_json)),
87+
db.CreateWindowFunction("regr_json", 2, json, newCovariance(regr_json)),
8588
db.CreateWindowFunction("median", 1, order, newPercentile(median)),
8689
db.CreateWindowFunction("percentile", 2, order, newPercentile(percentile_100)),
8790
db.CreateWindowFunction("percentile_cont", 2, order, newPercentile(percentile_cont)),
@@ -227,6 +230,7 @@ func (fn *covariance) Value(ctx sqlite3.Context) {
227230
case regr_json:
228231
var buf [128]byte
229232
ctx.ResultRawText(fn.regr_json(buf[:0]))
233+
ctx.ResultSubtype('J')
230234
return
231235
}
232236
ctx.ResultFloat(r)

ext/stats/stats_test.go

Lines changed: 44 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -156,49 +156,50 @@ func TestRegister_covariance(t *testing.T) {
156156
if err != nil {
157157
t.Fatal(err)
158158
}
159-
if stmt.Step() {
160-
if got := stmt.ColumnFloat(0); got != 0.9881049293224639 {
161-
t.Errorf("got %v, want 0.9881049293224639", got)
162-
}
163-
if got := stmt.ColumnFloat(1); got != 21.25 {
164-
t.Errorf("got %v, want 21.25", got)
165-
}
166-
if got := stmt.ColumnFloat(2); got != 17 {
167-
t.Errorf("got %v, want 17", got)
168-
}
169-
if got := stmt.ColumnFloat(3); got != 4.2 {
170-
t.Errorf("got %v, want 4.2", got)
171-
}
172-
if got := stmt.ColumnFloat(4); got != 75 {
173-
t.Errorf("got %v, want 75", got)
174-
}
175-
if got := stmt.ColumnFloat(5); got != 14.8 {
176-
t.Errorf("got %v, want 14.8", got)
177-
}
178-
if got := stmt.ColumnFloat(6); got != 500 {
179-
t.Errorf("got %v, want 500", got)
180-
}
181-
if got := stmt.ColumnFloat(7); got != 85 {
182-
t.Errorf("got %v, want 85", got)
183-
}
184-
if got := stmt.ColumnFloat(8); got != 0.17 {
185-
t.Errorf("got %v, want 0.17", got)
186-
}
187-
if got := stmt.ColumnFloat(9); got != -8.55 {
188-
t.Errorf("got %v, want -8.55", got)
189-
}
190-
if got := stmt.ColumnFloat(10); got != 0.9763513513513513 {
191-
t.Errorf("got %v, want 0.9763513513513513", got)
192-
}
193-
if got := stmt.ColumnInt(11); got != 5 {
194-
t.Errorf("got %v, want 5", got)
195-
}
196-
var a map[string]float64
197-
if err := stmt.ColumnJSON(12, &a); err != nil {
198-
t.Error(err)
199-
} else if got := a["count"]; got != 5 {
200-
t.Errorf("got %v, want 5", got)
201-
}
159+
if !stmt.Step() {
160+
t.Fatal(stmt.Err())
161+
}
162+
if got := stmt.ColumnFloat(0); got != 0.9881049293224639 {
163+
t.Errorf("got %v, want 0.9881049293224639", got)
164+
}
165+
if got := stmt.ColumnFloat(1); got != 21.25 {
166+
t.Errorf("got %v, want 21.25", got)
167+
}
168+
if got := stmt.ColumnFloat(2); got != 17 {
169+
t.Errorf("got %v, want 17", got)
170+
}
171+
if got := stmt.ColumnFloat(3); got != 4.2 {
172+
t.Errorf("got %v, want 4.2", got)
173+
}
174+
if got := stmt.ColumnFloat(4); got != 75 {
175+
t.Errorf("got %v, want 75", got)
176+
}
177+
if got := stmt.ColumnFloat(5); got != 14.8 {
178+
t.Errorf("got %v, want 14.8", got)
179+
}
180+
if got := stmt.ColumnFloat(6); got != 500 {
181+
t.Errorf("got %v, want 500", got)
182+
}
183+
if got := stmt.ColumnFloat(7); got != 85 {
184+
t.Errorf("got %v, want 85", got)
185+
}
186+
if got := stmt.ColumnFloat(8); got != 0.17 {
187+
t.Errorf("got %v, want 0.17", got)
188+
}
189+
if got := stmt.ColumnFloat(9); got != -8.55 {
190+
t.Errorf("got %v, want -8.55", got)
191+
}
192+
if got := stmt.ColumnFloat(10); got != 0.9763513513513513 {
193+
t.Errorf("got %v, want 0.9763513513513513", got)
194+
}
195+
if got := stmt.ColumnInt(11); got != 5 {
196+
t.Errorf("got %v, want 5", got)
197+
}
198+
var a map[string]float64
199+
if err := stmt.ColumnJSON(12, &a); err != nil {
200+
t.Error(err)
201+
} else if got := a["count"]; got != 5 {
202+
t.Errorf("got %v, want 5", got)
202203
}
203204
stmt.Close()
204205

stmt.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -631,7 +631,6 @@ func (s *Stmt) ColumnValue(col int) Value {
631631
stk_t(s.handle), stk_t(col)))
632632
return Value{
633633
c: s.c,
634-
unprot: true,
635634
handle: ptr,
636635
}
637636
}
-9 Bytes
Binary file not shown.

value.go

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,6 @@ import (
1515
type Value struct {
1616
c *Conn
1717
handle ptr_t
18-
unprot bool
19-
copied bool
20-
}
21-
22-
func (v Value) protected() stk_t {
23-
if v.unprot {
24-
panic(util.ValueErr)
25-
}
26-
return stk_t(v.handle)
2718
}
2819

2920
// Dup makes a copy of the SQL value and returns a pointer to that copy.
@@ -33,7 +24,6 @@ func (v Value) Dup() *Value {
3324
ptr := ptr_t(v.c.call("sqlite3_value_dup", stk_t(v.handle)))
3425
return &Value{
3526
c: v.c,
36-
copied: true,
3727
handle: ptr,
3828
}
3929
}
@@ -42,9 +32,6 @@ func (v Value) Dup() *Value {
4232
//
4333
// https://sqlite.org/c3ref/value_dup.html
4434
func (dup *Value) Close() error {
45-
if !dup.copied {
46-
panic(util.ValueErr)
47-
}
4835
dup.c.call("sqlite3_value_free", stk_t(dup.handle))
4936
dup.handle = 0
5037
return nil
@@ -54,14 +41,21 @@ func (dup *Value) Close() error {
5441
//
5542
// https://sqlite.org/c3ref/value_blob.html
5643
func (v Value) Type() Datatype {
57-
return Datatype(v.c.call("sqlite3_value_type", v.protected()))
44+
return Datatype(v.c.call("sqlite3_value_type", stk_t(v.handle)))
45+
}
46+
47+
// Subtype returns the subtype of the value.
48+
//
49+
// https://sqlite.org/c3ref/value_subtype.html
50+
func (v Value) Subtype() uint {
51+
return uint(uint32(v.c.call("sqlite3_value_subtype", stk_t(v.handle))))
5852
}
5953

6054
// NumericType returns the numeric datatype of the value.
6155
//
6256
// https://sqlite.org/c3ref/value_blob.html
6357
func (v Value) NumericType() Datatype {
64-
return Datatype(v.c.call("sqlite3_value_numeric_type", v.protected()))
58+
return Datatype(v.c.call("sqlite3_value_numeric_type", stk_t(v.handle)))
6559
}
6660

6761
// Bool returns the value as a bool.
@@ -85,14 +79,14 @@ func (v Value) Int() int {
8579
//
8680
// https://sqlite.org/c3ref/value_blob.html
8781
func (v Value) Int64() int64 {
88-
return int64(v.c.call("sqlite3_value_int64", v.protected()))
82+
return int64(v.c.call("sqlite3_value_int64", stk_t(v.handle)))
8983
}
9084

9185
// Float returns the value as a float64.
9286
//
9387
// https://sqlite.org/c3ref/value_blob.html
9488
func (v Value) Float() float64 {
95-
f := uint64(v.c.call("sqlite3_value_double", v.protected()))
89+
f := uint64(v.c.call("sqlite3_value_double", stk_t(v.handle)))
9690
return math.Float64frombits(f)
9791
}
9892

@@ -138,7 +132,7 @@ func (v Value) Blob(buf []byte) []byte {
138132
//
139133
// https://sqlite.org/c3ref/value_blob.html
140134
func (v Value) RawText() []byte {
141-
ptr := ptr_t(v.c.call("sqlite3_value_text", v.protected()))
135+
ptr := ptr_t(v.c.call("sqlite3_value_text", stk_t(v.handle)))
142136
return v.rawBytes(ptr, 1)
143137
}
144138

@@ -148,7 +142,7 @@ func (v Value) RawText() []byte {
148142
//
149143
// https://sqlite.org/c3ref/value_blob.html
150144
func (v Value) RawBlob() []byte {
151-
ptr := ptr_t(v.c.call("sqlite3_value_blob", v.protected()))
145+
ptr := ptr_t(v.c.call("sqlite3_value_blob", stk_t(v.handle)))
152146
return v.rawBytes(ptr, 0)
153147
}
154148

@@ -157,14 +151,14 @@ func (v Value) rawBytes(ptr ptr_t, nul int32) []byte {
157151
return nil
158152
}
159153

160-
n := int32(v.c.call("sqlite3_value_bytes", v.protected()))
154+
n := int32(v.c.call("sqlite3_value_bytes", stk_t(v.handle)))
161155
return util.View(v.c.mod, ptr, int64(n+nul))[:n]
162156
}
163157

164158
// Pointer gets the pointer associated with this value,
165159
// or nil if it has no associated pointer.
166160
func (v Value) Pointer() any {
167-
ptr := ptr_t(v.c.call("sqlite3_value_pointer_go", v.protected()))
161+
ptr := ptr_t(v.c.call("sqlite3_value_pointer_go", stk_t(v.handle)))
168162
return util.GetHandle(v.c.ctx, ptr)
169163
}
170164

@@ -194,15 +188,15 @@ func (v Value) JSON(ptr any) error {
194188
//
195189
// https://sqlite.org/c3ref/value_blob.html
196190
func (v Value) NoChange() bool {
197-
b := int32(v.c.call("sqlite3_value_nochange", v.protected()))
191+
b := int32(v.c.call("sqlite3_value_nochange", stk_t(v.handle)))
198192
return b != 0
199193
}
200194

201195
// FromBind returns true if value originated from a bound parameter.
202196
//
203197
// https://sqlite.org/c3ref/value_blob.html
204198
func (v Value) FromBind() bool {
205-
b := int32(v.c.call("sqlite3_value_frombind", v.protected()))
199+
b := int32(v.c.call("sqlite3_value_frombind", stk_t(v.handle)))
206200
return b != 0
207201
}
208202

0 commit comments

Comments
 (0)