@@ -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