Skip to content

Commit

Permalink
Collect all sqlite3 column types for a query in one CGO call.
Browse files Browse the repository at this point in the history
This improves performance by ~25% when the queries that have 10 columns
by reducing the number of CGO calls that we need to make. This
performance improvement will scale with the number of columns a query
returns.
  • Loading branch information
charlievieth committed Oct 25, 2024
1 parent 9ac6cbb commit 9257a5c
Showing 1 changed file with 16 additions and 2 deletions.
18 changes: 16 additions & 2 deletions sqlite3.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,13 @@ error:
return rc;
}
// _sqlite3_column_types get all column types in once C function call
static void _sqlite3_column_types(sqlite3_stmt *stmt, int column_count, uint8_t *typs) {
for (int i = 0; i < column_count; i++) {
typs[i] = (uint8_t)sqlite3_column_type(stmt, i);
}
}
int _sqlite3_create_function(
sqlite3 *db,
const char *zFunctionName,
Expand Down Expand Up @@ -440,7 +447,8 @@ type SQLiteRows struct {
nc int
cols []string
decltype []string
cls bool
coltype []uint8 // sqlite3 column types
cls bool // TODO: document this field
closed bool
ctx context.Context // no better alternative to pass context into Next() method
}
Expand Down Expand Up @@ -2251,9 +2259,15 @@ func (rc *SQLiteRows) nextSyncLocked(dest []driver.Value) error {
}

rc.declTypes()
if rc.coltype == nil {
rc.coltype = make([]uint8, len(dest))
}
// Must call this each time since types can change.
C._sqlite3_column_types(rc.s.s, C.int(len(rc.coltype)),
(*C.uint8_t)(unsafe.Pointer(&rc.coltype[0])))

for i := range dest {
switch C.sqlite3_column_type(rc.s.s, C.int(i)) {
switch rc.coltype[i] {
case C.SQLITE_INTEGER:
val := int64(C.sqlite3_column_int64(rc.s.s, C.int(i)))
switch rc.decltype[i] {
Expand Down

0 comments on commit 9257a5c

Please sign in to comment.