Skip to content

Commit 8b4a056

Browse files
add DATE support to the appender (marcboeker#209)
1 parent e0c5b9b commit 8b4a056

File tree

3 files changed

+46
-3
lines changed

3 files changed

+46
-3
lines changed

appender_test.go

+19-1
Original file line numberDiff line numberDiff line change
@@ -663,6 +663,24 @@ func TestAppenderTime(t *testing.T) {
663663
cleanupAppender(t, c, con, a)
664664
}
665665

666+
func TestAppenderDate(t *testing.T) {
667+
c, con, a := prepareAppender(t, `CREATE TABLE test (date DATE)`)
668+
669+
ts := time.Date(1996, time.July, 23, 11, 42, 23, 0, time.UTC)
670+
require.NoError(t, a.AppendRow(ts))
671+
require.NoError(t, a.Flush())
672+
673+
// Verify results.
674+
row := sql.OpenDB(c).QueryRowContext(context.Background(), `SELECT date FROM test`)
675+
676+
var res time.Time
677+
require.NoError(t, row.Scan(&res))
678+
require.Equal(t, ts.Year(), res.Year())
679+
require.Equal(t, ts.Month(), res.Month())
680+
require.Equal(t, ts.Day(), res.Day())
681+
cleanupAppender(t, c, con, a)
682+
}
683+
666684
func TestAppenderBlob(t *testing.T) {
667685
c, con, a := prepareAppender(t, `CREATE TABLE test (data BLOB)`)
668686

@@ -824,6 +842,6 @@ func TestAppenderWithJSON(t *testing.T) {
824842

825843
require.Equal(t, len(jsonInputs), i)
826844

827-
require.NoError(t, res.Close())
845+
require.NoError(t, res.Close())
828846
cleanupAppender(t, c, con, a)
829847
}

appender_vector.go

+27-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ import (
1313
"unsafe"
1414
)
1515

16+
// secondsPerDay to calculate the days since 1970-01-01.
17+
const secondsPerDay = 24 * 60 * 60
18+
1619
// vector storage of a DuckDB column.
1720
type vector struct {
1821
// The underlying DuckDB vector.
@@ -63,7 +66,7 @@ func (vec *vector) tryCast(val any) (any, error) {
6366
case C.DUCKDB_TYPE_BLOB:
6467
return tryPrimitiveCast[[]byte](val, reflect.TypeOf([]byte{}).String())
6568
case C.DUCKDB_TYPE_TIMESTAMP, C.DUCKDB_TYPE_TIMESTAMP_S, C.DUCKDB_TYPE_TIMESTAMP_MS,
66-
C.DUCKDB_TYPE_TIMESTAMP_NS, C.DUCKDB_TYPE_TIMESTAMP_TZ:
69+
C.DUCKDB_TYPE_TIMESTAMP_NS, C.DUCKDB_TYPE_TIMESTAMP_TZ, C.DUCKDB_TYPE_DATE:
6770
return tryPrimitiveCast[time.Time](val, reflect.TypeOf(time.Time{}).String())
6871
case C.DUCKDB_TYPE_UUID:
6972
return tryPrimitiveCast[UUID](val, reflect.TypeOf(UUID{}).String())
@@ -215,6 +218,8 @@ func (vec *vector) init(logicalType C.duckdb_logical_type, colIdx int) error {
215218
vec.initTS(duckdbType)
216219
case C.DUCKDB_TYPE_UUID:
217220
vec.initUUID()
221+
case C.DUCKDB_TYPE_DATE:
222+
vec.initDate()
218223
case C.DUCKDB_TYPE_LIST:
219224
return vec.initList(logicalType, colIdx)
220225
case C.DUCKDB_TYPE_STRUCT:
@@ -295,6 +300,12 @@ func (vec *vector) setTime(rowIdx C.idx_t, ticks int64) {
295300
setPrimitive[C.duckdb_timestamp](vec, rowIdx, ts)
296301
}
297302

303+
func (vec *vector) setDate(rowIdx C.idx_t, days int32) {
304+
var date C.duckdb_date
305+
date.days = C.int32_t(days)
306+
setPrimitive[C.duckdb_date](vec, rowIdx, date)
307+
}
308+
298309
func (vec *vector) setList(rowIdx C.idx_t, val any) {
299310
if val == nil {
300311
vec.setNull(rowIdx)
@@ -384,6 +395,21 @@ func (vec *vector) initUUID() {
384395
vec.duckdbType = C.DUCKDB_TYPE_UUID
385396
}
386397

398+
func (vec *vector) initDate() {
399+
vec.fn = func(vec *vector, rowIdx C.idx_t, val any) {
400+
if val == nil {
401+
vec.setNull(rowIdx)
402+
return
403+
}
404+
405+
v := val.(time.Time)
406+
// Days since 1970-01-01.
407+
days := int32(v.UTC().Unix() / secondsPerDay)
408+
vec.setDate(rowIdx, days)
409+
}
410+
vec.duckdbType = C.DUCKDB_TYPE_DATE
411+
}
412+
387413
func (vec *vector) initList(logicalType C.duckdb_logical_type, colIdx int) error {
388414
// Get the child vector type.
389415
childType := C.duckdb_list_type_child_type(logicalType)

types.go

-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import (
1515

1616
var unsupportedAppenderTypeMap = map[C.duckdb_type]string{
1717
C.DUCKDB_TYPE_INVALID: "INVALID",
18-
C.DUCKDB_TYPE_DATE: "DATE",
1918
C.DUCKDB_TYPE_TIME: "TIME",
2019
C.DUCKDB_TYPE_INTERVAL: "INTERVAL",
2120
C.DUCKDB_TYPE_HUGEINT: "HUGEINT",

0 commit comments

Comments
 (0)