Skip to content

Commit

Permalink
WIP: reduce allocations due to declTypes
Browse files Browse the repository at this point in the history
  • Loading branch information
charlievieth committed Oct 18, 2023
1 parent af13bcb commit 427d249
Showing 1 changed file with 83 additions and 14 deletions.
97 changes: 83 additions & 14 deletions sqlite3.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,39 @@ _sqlite3_exec(sqlite3* db, const char* pcmd, long long* rowid, long long* change
return rv;
}
typedef enum {
GO_SQLITE3_TYPE_NONE,
GO_SQLITE3_TYPE_DATETIME,
GO_SQLITE3_TYPE_BOOLEAN
} go_sqlite3_decl_type;
go_sqlite3_decl_type _sqlite3_column_decltype_internal(sqlite3_stmt* stmt, int idx) {
const char *typ = sqlite3_column_decltype(stmt, idx);
if (typ != NULL) {
switch (typ[0]) {
case 'B':
case 'b':
if (sqlite3_stricmp(typ, "boolean") == 0) {
return GO_SQLITE3_TYPE_BOOLEAN;
}
break;
case 'D':
case 'd':
if (sqlite3_stricmp(typ, "date") == 0 || sqlite3_stricmp(typ, "datetime") == 0) {
return GO_SQLITE3_TYPE_DATETIME;
}
break;
case 'T':
case 't':
if (sqlite3_stricmp(typ, "timestamp") == 0) {
return GO_SQLITE3_TYPE_DATETIME;
}
break;
}
}
return GO_SQLITE3_TYPE_NONE;
}
#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
extern int _sqlite3_step_blocking(sqlite3_stmt *stmt);
extern int _sqlite3_step_row_blocking(sqlite3_stmt* stmt, long long* rowid, long long* changes);
Expand Down Expand Up @@ -134,7 +167,6 @@ void _sqlite3_result_blob(sqlite3_context* ctx, const void* b, int l) {
sqlite3_result_blob(ctx, b, l, SQLITE_TRANSIENT);
}
int _sqlite3_create_function(
sqlite3 *db,
const char *zFunctionName,
Expand Down Expand Up @@ -381,13 +413,14 @@ type SQLiteResult struct {

// SQLiteRows implements driver.Rows.
type SQLiteRows struct {
s *SQLiteStmt
nc int
cols []string
decltype []string
cls bool
closed bool
ctx context.Context // no better alternative to pass context into Next() method
s *SQLiteStmt
nc int
cols []string
decltype []string
xdecltype []uint8
cls bool
closed bool
ctx context.Context // no better alternative to pass context into Next() method
}

type functionInfo struct {
Expand Down Expand Up @@ -2134,6 +2167,31 @@ func (rc *SQLiteRows) Columns() []string {
return rc.cols
}

func normalizeDeclType(s string) string {
switch s {
case "BLOB", "blob":
return "blob"
case "BOOLEAN", "boolean":
return "boolean"
case "DATE", "DATETIME", "TIMESTAMP", "date", "datetime", "timestamp":
return "timestamp"
// case "TIMESTAMP", "timestamp":
// return "timestamp"
// case "DATETIME", "datetime":
// return "datetime"
case "INTEGER", "integer":
return "integer"
case "TEXT", "text":
return "text"
case "INT", "int":
return "int"
default:
return strings.ToLower(s)
}
}

// TODO: the only values that are used here are:
// columnTimestamp, columnDatetime, columnDate, "boolean"
func (rc *SQLiteRows) declTypes() []string {
if rc.s.s != nil && rc.decltype == nil {
rc.decltype = make([]string, rc.nc)
Expand All @@ -2144,6 +2202,16 @@ func (rc *SQLiteRows) declTypes() []string {
return rc.decltype
}

func (rc *SQLiteRows) xdeclTypes() []uint8 {
if rc.s.s != nil && rc.xdecltype == nil {
rc.xdecltype = make([]uint8, rc.nc)
for i := 0; i < rc.nc; i++ {
rc.xdecltype[i] = uint8(C._sqlite3_column_decltype_internal(rc.s.s, C.int(i)))
}
}
return rc.xdecltype
}

// DeclTypes return column types.
func (rc *SQLiteRows) DeclTypes() []string {
rc.s.mu.Lock()
Expand Down Expand Up @@ -2196,14 +2264,15 @@ func (rc *SQLiteRows) nextSyncLocked(dest []driver.Value) error {
return nil
}

rc.declTypes()
// rc.declTypes()
rc.xdeclTypes()

for i := range dest {
switch C.sqlite3_column_type(rc.s.s, C.int(i)) {
case C.SQLITE_INTEGER:
val := int64(C.sqlite3_column_int64(rc.s.s, C.int(i)))
switch rc.decltype[i] {
case columnTimestamp, columnDatetime, columnDate:
switch rc.xdecltype[i] {
case C.GO_SQLITE3_TYPE_DATETIME:
var t time.Time
// Assume a millisecond unix timestamp if it's 13 digits -- too
// large to be a reasonable timestamp in seconds.
Expand All @@ -2218,7 +2287,7 @@ func (rc *SQLiteRows) nextSyncLocked(dest []driver.Value) error {
t = t.In(rc.s.c.loc)
}
dest[i] = t
case "boolean":
case C.GO_SQLITE3_TYPE_BOOLEAN:
dest[i] = val > 0
default:
dest[i] = val
Expand All @@ -2242,8 +2311,8 @@ func (rc *SQLiteRows) nextSyncLocked(dest []driver.Value) error {
n := int(C.sqlite3_column_bytes(rc.s.s, C.int(i)))
s := C.GoStringN((*C.char)(unsafe.Pointer(C.sqlite3_column_text(rc.s.s, C.int(i)))), C.int(n))

switch rc.decltype[i] {
case columnTimestamp, columnDatetime, columnDate:
switch rc.xdecltype[i] {
case C.GO_SQLITE3_TYPE_DATETIME:
var t time.Time
s = strings.TrimSuffix(s, "Z")
for _, format := range SQLiteTimestampFormats {
Expand Down

0 comments on commit 427d249

Please sign in to comment.