Merge pull request #1383 from mattn/codex/next-row-batch-fetch
[codex] batch row column fetches in Next
This commit is contained in:
73
sqlite3.go
73
sqlite3.go
@@ -78,6 +78,42 @@ _sqlite3_bind_blob(sqlite3_stmt *stmt, int n, void *p, int np) {
|
|||||||
return sqlite3_bind_blob(stmt, n, p, np, SQLITE_TRANSIENT);
|
return sqlite3_bind_blob(stmt, n, p, np, SQLITE_TRANSIENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int typ;
|
||||||
|
sqlite3_int64 i64;
|
||||||
|
double f64;
|
||||||
|
const void *ptr;
|
||||||
|
int n;
|
||||||
|
} sqlite3_go_col;
|
||||||
|
|
||||||
|
static void
|
||||||
|
_sqlite3_column_values(sqlite3_stmt *stmt, int ncol, sqlite3_go_col *cols) {
|
||||||
|
for (int i = 0; i < ncol; i++) {
|
||||||
|
sqlite3_go_col *col = &cols[i];
|
||||||
|
col->typ = sqlite3_column_type(stmt, i);
|
||||||
|
col->ptr = 0;
|
||||||
|
col->n = 0;
|
||||||
|
switch (col->typ) {
|
||||||
|
case SQLITE_INTEGER:
|
||||||
|
col->i64 = sqlite3_column_int64(stmt, i);
|
||||||
|
break;
|
||||||
|
case SQLITE_FLOAT:
|
||||||
|
col->f64 = sqlite3_column_double(stmt, i);
|
||||||
|
break;
|
||||||
|
case SQLITE_BLOB:
|
||||||
|
col->ptr = sqlite3_column_blob(stmt, i);
|
||||||
|
col->n = sqlite3_column_bytes(stmt, i);
|
||||||
|
break;
|
||||||
|
case SQLITE_TEXT:
|
||||||
|
col->ptr = sqlite3_column_text(stmt, i);
|
||||||
|
col->n = sqlite3_column_bytes(stmt, i);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
@@ -210,6 +246,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"math"
|
||||||
"net/url"
|
"net/url"
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
@@ -397,6 +434,7 @@ type SQLiteRows struct {
|
|||||||
cls bool // True if we need to close the parent statement in Close
|
cls bool // True if we need to close the parent statement in Close
|
||||||
cols []string
|
cols []string
|
||||||
decltype []string
|
decltype []string
|
||||||
|
colvals *C.sqlite3_go_col
|
||||||
ctx context.Context // no better alternative to pass context into Next() method
|
ctx context.Context // no better alternative to pass context into Next() method
|
||||||
closemu sync.Mutex
|
closemu sync.Mutex
|
||||||
}
|
}
|
||||||
@@ -2107,8 +2145,15 @@ func (s *SQLiteStmt) query(ctx context.Context, args []driver.NamedValue) (drive
|
|||||||
cls: s.cls,
|
cls: s.cls,
|
||||||
cols: nil,
|
cols: nil,
|
||||||
decltype: nil,
|
decltype: nil,
|
||||||
|
colvals: nil,
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
}
|
}
|
||||||
|
if rows.nc > 0 {
|
||||||
|
rows.colvals = (*C.sqlite3_go_col)(C.malloc(C.size_t(rows.nc) * C.size_t(unsafe.Sizeof(C.sqlite3_go_col{}))))
|
||||||
|
if rows.colvals == nil {
|
||||||
|
return nil, errors.New("sqlite3: failed to allocate row buffer")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return rows, nil
|
return rows, nil
|
||||||
}
|
}
|
||||||
@@ -2209,9 +2254,17 @@ func (rc *SQLiteRows) Close() error {
|
|||||||
defer rc.closemu.Unlock()
|
defer rc.closemu.Unlock()
|
||||||
s := rc.s
|
s := rc.s
|
||||||
if s == nil {
|
if s == nil {
|
||||||
|
if rc.colvals != nil {
|
||||||
|
C.free(unsafe.Pointer(rc.colvals))
|
||||||
|
rc.colvals = nil
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
rc.s = nil // remove reference to SQLiteStmt
|
rc.s = nil // remove reference to SQLiteStmt
|
||||||
|
if rc.colvals != nil {
|
||||||
|
C.free(unsafe.Pointer(rc.colvals))
|
||||||
|
rc.colvals = nil
|
||||||
|
}
|
||||||
s.mu.Lock()
|
s.mu.Lock()
|
||||||
if s.closed {
|
if s.closed {
|
||||||
s.mu.Unlock()
|
s.mu.Unlock()
|
||||||
@@ -2307,13 +2360,19 @@ func (rc *SQLiteRows) nextSyncLocked(dest []driver.Value) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
rc.declTypes()
|
rc.declTypes()
|
||||||
|
if len(dest) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
C._sqlite3_column_values(rc.s.s, C.int(len(dest)), rc.colvals)
|
||||||
|
colvals := (*[(math.MaxInt32 - 1) / unsafe.Sizeof(C.sqlite3_go_col{})]C.sqlite3_go_col)(unsafe.Pointer(rc.colvals))[:len(dest):len(dest)]
|
||||||
|
|
||||||
decltype := rc.decltype
|
decltype := rc.decltype
|
||||||
_ = decltype[len(dest)-1]
|
_ = decltype[len(dest)-1]
|
||||||
for i := range dest {
|
for i := range dest {
|
||||||
switch C.sqlite3_column_type(rc.s.s, C.int(i)) {
|
col := &colvals[i]
|
||||||
|
switch col.typ {
|
||||||
case C.SQLITE_INTEGER:
|
case C.SQLITE_INTEGER:
|
||||||
val := int64(C.sqlite3_column_int64(rc.s.s, C.int(i)))
|
val := int64(col.i64)
|
||||||
switch decltype[i] {
|
switch decltype[i] {
|
||||||
case columnTimestamp, columnDatetime, columnDate:
|
case columnTimestamp, columnDatetime, columnDate:
|
||||||
var t time.Time
|
var t time.Time
|
||||||
@@ -2336,14 +2395,14 @@ func (rc *SQLiteRows) nextSyncLocked(dest []driver.Value) error {
|
|||||||
dest[i] = val
|
dest[i] = val
|
||||||
}
|
}
|
||||||
case C.SQLITE_FLOAT:
|
case C.SQLITE_FLOAT:
|
||||||
dest[i] = float64(C.sqlite3_column_double(rc.s.s, C.int(i)))
|
dest[i] = float64(col.f64)
|
||||||
case C.SQLITE_BLOB:
|
case C.SQLITE_BLOB:
|
||||||
p := C.sqlite3_column_blob(rc.s.s, C.int(i))
|
p := col.ptr
|
||||||
if p == nil {
|
if p == nil {
|
||||||
dest[i] = []byte{}
|
dest[i] = []byte{}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
n := C.sqlite3_column_bytes(rc.s.s, C.int(i))
|
n := col.n
|
||||||
dest[i] = C.GoBytes(p, n)
|
dest[i] = C.GoBytes(p, n)
|
||||||
case C.SQLITE_NULL:
|
case C.SQLITE_NULL:
|
||||||
dest[i] = nil
|
dest[i] = nil
|
||||||
@@ -2351,8 +2410,8 @@ func (rc *SQLiteRows) nextSyncLocked(dest []driver.Value) error {
|
|||||||
var err error
|
var err error
|
||||||
var timeVal time.Time
|
var timeVal time.Time
|
||||||
|
|
||||||
n := int(C.sqlite3_column_bytes(rc.s.s, C.int(i)))
|
n := int(col.n)
|
||||||
s := C.GoStringN((*C.char)(unsafe.Pointer(C.sqlite3_column_text(rc.s.s, C.int(i)))), C.int(n))
|
s := C.GoStringN((*C.char)(unsafe.Pointer(col.ptr)), C.int(n))
|
||||||
|
|
||||||
switch decltype[i] {
|
switch decltype[i] {
|
||||||
case columnTimestamp, columnDatetime, columnDate:
|
case columnTimestamp, columnDatetime, columnDate:
|
||||||
|
|||||||
Reference in New Issue
Block a user