Skip to content

Commit e1557be

Browse files
committed
batch row column fetches in Next
1 parent cc39db7 commit e1557be

1 file changed

Lines changed: 66 additions & 7 deletions

File tree

sqlite3.go

Lines changed: 66 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,42 @@ _sqlite3_bind_blob(sqlite3_stmt *stmt, int n, void *p, int np) {
7878
return sqlite3_bind_blob(stmt, n, p, np, SQLITE_TRANSIENT);
7979
}
8080
81+
typedef struct {
82+
int typ;
83+
sqlite3_int64 i64;
84+
double f64;
85+
const void *ptr;
86+
int n;
87+
} sqlite3_go_col;
88+
89+
static void
90+
_sqlite3_column_values(sqlite3_stmt *stmt, int ncol, sqlite3_go_col *cols) {
91+
for (int i = 0; i < ncol; i++) {
92+
sqlite3_go_col *col = &cols[i];
93+
col->typ = sqlite3_column_type(stmt, i);
94+
col->ptr = 0;
95+
col->n = 0;
96+
switch (col->typ) {
97+
case SQLITE_INTEGER:
98+
col->i64 = sqlite3_column_int64(stmt, i);
99+
break;
100+
case SQLITE_FLOAT:
101+
col->f64 = sqlite3_column_double(stmt, i);
102+
break;
103+
case SQLITE_BLOB:
104+
col->ptr = sqlite3_column_blob(stmt, i);
105+
col->n = sqlite3_column_bytes(stmt, i);
106+
break;
107+
case SQLITE_TEXT:
108+
col->ptr = sqlite3_column_text(stmt, i);
109+
col->n = sqlite3_column_bytes(stmt, i);
110+
break;
111+
default:
112+
break;
113+
}
114+
}
115+
}
116+
81117
#include <stdio.h>
82118
#include <stdint.h>
83119
@@ -210,6 +246,7 @@ import (
210246
"errors"
211247
"fmt"
212248
"io"
249+
"math"
213250
"net/url"
214251
"reflect"
215252
"runtime"
@@ -397,6 +434,7 @@ type SQLiteRows struct {
397434
cls bool // True if we need to close the parent statement in Close
398435
cols []string
399436
decltype []string
437+
colvals *C.sqlite3_go_col
400438
ctx context.Context // no better alternative to pass context into Next() method
401439
closemu sync.Mutex
402440
}
@@ -2107,8 +2145,15 @@ func (s *SQLiteStmt) query(ctx context.Context, args []driver.NamedValue) (drive
21072145
cls: s.cls,
21082146
cols: nil,
21092147
decltype: nil,
2148+
colvals: nil,
21102149
ctx: ctx,
21112150
}
2151+
if rows.nc > 0 {
2152+
rows.colvals = (*C.sqlite3_go_col)(C.malloc(C.size_t(rows.nc) * C.size_t(unsafe.Sizeof(C.sqlite3_go_col{}))))
2153+
if rows.colvals == nil {
2154+
return nil, errors.New("sqlite3: failed to allocate row buffer")
2155+
}
2156+
}
21122157

21132158
return rows, nil
21142159
}
@@ -2209,9 +2254,17 @@ func (rc *SQLiteRows) Close() error {
22092254
defer rc.closemu.Unlock()
22102255
s := rc.s
22112256
if s == nil {
2257+
if rc.colvals != nil {
2258+
C.free(unsafe.Pointer(rc.colvals))
2259+
rc.colvals = nil
2260+
}
22122261
return nil
22132262
}
22142263
rc.s = nil // remove reference to SQLiteStmt
2264+
if rc.colvals != nil {
2265+
C.free(unsafe.Pointer(rc.colvals))
2266+
rc.colvals = nil
2267+
}
22152268
s.mu.Lock()
22162269
if s.closed {
22172270
s.mu.Unlock()
@@ -2307,13 +2360,19 @@ func (rc *SQLiteRows) nextSyncLocked(dest []driver.Value) error {
23072360
}
23082361

23092362
rc.declTypes()
2363+
if len(dest) == 0 {
2364+
return nil
2365+
}
2366+
C._sqlite3_column_values(rc.s.s, C.int(len(dest)), rc.colvals)
2367+
colvals := (*[(math.MaxInt32 - 1) / unsafe.Sizeof(C.sqlite3_go_col{})]C.sqlite3_go_col)(unsafe.Pointer(rc.colvals))[:len(dest):len(dest)]
23102368

23112369
decltype := rc.decltype
23122370
_ = decltype[len(dest)-1]
23132371
for i := range dest {
2314-
switch C.sqlite3_column_type(rc.s.s, C.int(i)) {
2372+
col := &colvals[i]
2373+
switch col.typ {
23152374
case C.SQLITE_INTEGER:
2316-
val := int64(C.sqlite3_column_int64(rc.s.s, C.int(i)))
2375+
val := int64(col.i64)
23172376
switch decltype[i] {
23182377
case columnTimestamp, columnDatetime, columnDate:
23192378
var t time.Time
@@ -2336,23 +2395,23 @@ func (rc *SQLiteRows) nextSyncLocked(dest []driver.Value) error {
23362395
dest[i] = val
23372396
}
23382397
case C.SQLITE_FLOAT:
2339-
dest[i] = float64(C.sqlite3_column_double(rc.s.s, C.int(i)))
2398+
dest[i] = float64(col.f64)
23402399
case C.SQLITE_BLOB:
2341-
p := C.sqlite3_column_blob(rc.s.s, C.int(i))
2400+
p := col.ptr
23422401
if p == nil {
23432402
dest[i] = []byte{}
23442403
continue
23452404
}
2346-
n := C.sqlite3_column_bytes(rc.s.s, C.int(i))
2405+
n := col.n
23472406
dest[i] = C.GoBytes(p, n)
23482407
case C.SQLITE_NULL:
23492408
dest[i] = nil
23502409
case C.SQLITE_TEXT:
23512410
var err error
23522411
var timeVal time.Time
23532412

2354-
n := int(C.sqlite3_column_bytes(rc.s.s, C.int(i)))
2355-
s := C.GoStringN((*C.char)(unsafe.Pointer(C.sqlite3_column_text(rc.s.s, C.int(i)))), C.int(n))
2413+
n := int(col.n)
2414+
s := C.GoStringN((*C.char)(unsafe.Pointer(col.ptr)), C.int(n))
23562415

23572416
switch decltype[i] {
23582417
case columnTimestamp, columnDatetime, columnDate:

0 commit comments

Comments
 (0)