From 7e2272c48b31328b45e9a6419454f2a3f89af5b8 Mon Sep 17 00:00:00 2001 From: Kevin Joiner <10265309+KevinJoiner@users.noreply.github.com> Date: Mon, 11 Mar 2024 10:25:41 -0400 Subject: [PATCH] Adds the ability to Append a zero valued time.Time (#1228) * Bump ch-go to v0.61.5 * Adds the ability to Append a zero valued time.Time --- go.mod | 2 +- go.sum | 8 ++--- lib/column/date_helpers.go | 2 +- lib/column/date_helpers_test.go | 53 +++++++++++++++++++++++++++++++++ tests/std/date32_test.go | 10 +++---- tests/std/date_test.go | 10 +++---- tests/std/datetime64_test.go | 30 +++++++++++-------- tests/std/datetime_test.go | 13 ++++---- 8 files changed, 94 insertions(+), 34 deletions(-) create mode 100644 lib/column/date_helpers_test.go diff --git a/go.mod b/go.mod index f1c0ece43d..35973ac2e1 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/ClickHouse/clickhouse-go/v2 go 1.21 require ( - github.com/ClickHouse/ch-go v0.61.3 + github.com/ClickHouse/ch-go v0.61.5 github.com/ClickHouse/clickhouse-go v1.5.4 github.com/andybalholm/brotli v1.1.0 github.com/docker/docker v25.0.3+incompatible diff --git a/go.sum b/go.sum index a3e584e4e2..442a8e52f1 100644 --- a/go.sum +++ b/go.sum @@ -4,8 +4,8 @@ github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9 github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= -github.com/ClickHouse/ch-go v0.61.3 h1:MmBwUhXrAOBZK7n/sWBzq6FdIQ01cuF2SaaO8KlDRzI= -github.com/ClickHouse/ch-go v0.61.3/go.mod h1:1PqXjMz/7S1ZUaKvwPA3i35W2bz2mAMFeCi6DIXgGwQ= +github.com/ClickHouse/ch-go v0.61.5 h1:zwR8QbYI0tsMiEcze/uIMK+Tz1D3XZXLdNrlaOpeEI4= +github.com/ClickHouse/ch-go v0.61.5/go.mod h1:s1LJW/F/LcFs5HJnuogFMta50kKDO0lf9zzfrbl0RQg= github.com/ClickHouse/clickhouse-go v1.5.4 h1:cKjXeYLNWVJIx2J1K6H2CqyRmfwVJVY1OV1coaaFcI0= github.com/ClickHouse/clickhouse-go v1.5.4/go.mod h1:EaI/sW7Azgz9UATzd5ZdZHRUhHgv5+JMS9NSr2smCJI= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= @@ -179,8 +179,8 @@ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMey go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU= go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= -go.opentelemetry.io/otel/sdk v1.23.1 h1:O7JmZw0h76if63LQdsBMKQDWNb5oEcOThG9IrxscV+E= -go.opentelemetry.io/otel/sdk v1.23.1/go.mod h1:LzdEVR5am1uKOOwfBWFef2DCi1nu3SA8XQxx2IerWFk= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= diff --git a/lib/column/date_helpers.go b/lib/column/date_helpers.go index 2e6691ec6d..2bf74ee610 100644 --- a/lib/column/date_helpers.go +++ b/lib/column/date_helpers.go @@ -25,7 +25,7 @@ import ( const secInDay = 24 * 60 * 60 func dateOverflow(min, max, v time.Time, format string) error { - if v.Before(min) || v.After(max) { + if !v.IsZero() && (v.Before(min) || v.After(max)) { return &DateOverflowError{ Min: min, Max: max, diff --git a/lib/column/date_helpers_test.go b/lib/column/date_helpers_test.go new file mode 100644 index 0000000000..0ed5b8f9e7 --- /dev/null +++ b/lib/column/date_helpers_test.go @@ -0,0 +1,53 @@ +package column + +import ( + "testing" + "time" +) + +func TestDateOverflow(t *testing.T) { + t.Parallel() + zeroTime := time.Time{} + tests := []struct { + v time.Time + name string + err bool + }{ + { + name: "valid date", + v: time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC), + err: false, + }, + { + name: "before min date", + v: minDate.Add(-time.Second), + err: true, + }, + { + name: "after max date", + v: maxDate.Add(time.Second), + err: true, + }, + { + name: "zero value date", + v: zeroTime, + err: false, + }, + { + name: "non-zero value equal to zero date", + v: time.UnixMilli(zeroTime.UnixMilli()), + err: false, + }, + } + + for _, test := range tests { + test := test + t.Run(test.name, func(t *testing.T) { + t.Parallel() + err := dateOverflow(minDateTime, maxDateTime, test.v, defaultDateFormatNoZone) + if (err != nil) != test.err { + t.Errorf("expected error: %v, got: %v", test.err, err) + } + }) + } +} diff --git a/tests/std/date32_test.go b/tests/std/date32_test.go index 8caf327dd7..47ae31b510 100644 --- a/tests/std/date32_test.go +++ b/tests/std/date32_test.go @@ -21,14 +21,14 @@ import ( "context" "database/sql" "fmt" - "github.com/ClickHouse/clickhouse-go/v2" - clickhouse_tests "github.com/ClickHouse/clickhouse-go/v2/tests" - "github.com/stretchr/testify/require" "strconv" "testing" "time" + "github.com/ClickHouse/clickhouse-go/v2" + clickhouse_tests "github.com/ClickHouse/clickhouse-go/v2/tests" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestStdDate32(t *testing.T) { @@ -78,7 +78,7 @@ func TestStdDate32(t *testing.T) { ) _, err = batch.Exec(uint8(1), date1, &date2, []time.Time{date2}, []*time.Time{&date2, nil, &date1}, sql.NullTime{Time: time.Time{}, Valid: false}, sql.NullTime{Time: date1, Valid: true}) require.NoError(t, err) - _, err = batch.Exec(uint8(2), date2, nil, []time.Time{date1}, []*time.Time{nil, nil, &date2}, sql.NullTime{Time: time.Time{}, Valid: false}, sql.NullTime{Time: date2, Valid: true}) + _, err = batch.Exec(uint8(2), time.Time{}, nil, []time.Time{date1}, []*time.Time{nil, nil, &date2}, sql.NullTime{Time: time.Time{}, Valid: false}, sql.NullTime{Time: date2, Valid: true}) require.NoError(t, err) require.NoError(t, scope.Commit()) var ( @@ -110,7 +110,7 @@ func TestStdDate32(t *testing.T) { &result1.Col5, &result1.Col6, )) - require.Equal(t, date2, result2.Col1) + require.Equal(t, time.Unix(0, 0).UTC(), result2.Col1) require.Equal(t, "UTC", result2.Col1.Location().String()) require.Nil(t, result2.Col2) assert.Equal(t, []time.Time{date1}, result2.Col3) diff --git a/tests/std/date_test.go b/tests/std/date_test.go index e5015f6ab0..13d780f3b5 100644 --- a/tests/std/date_test.go +++ b/tests/std/date_test.go @@ -21,14 +21,14 @@ import ( "context" "database/sql" "fmt" - "github.com/ClickHouse/clickhouse-go/v2" - clickhouse_tests "github.com/ClickHouse/clickhouse-go/v2/tests" - "github.com/stretchr/testify/require" "strconv" "testing" "time" + "github.com/ClickHouse/clickhouse-go/v2" + clickhouse_tests "github.com/ClickHouse/clickhouse-go/v2/tests" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestStdDate(t *testing.T) { @@ -72,7 +72,7 @@ func TestStdDate(t *testing.T) { require.NoError(t, err) _, err = batch.Exec(uint8(1), date, &date, []time.Time{date}, []*time.Time{&date, nil, &date}, sql.NullTime{Time: date, Valid: true}, sql.NullTime{Time: time.Time{}, Valid: false}) require.NoError(t, err) - _, err = batch.Exec(uint8(2), date, nil, []time.Time{date}, []*time.Time{nil, nil, &date}, sql.NullTime{Time: date, Valid: true}, sql.NullTime{Time: time.Time{}, Valid: false}) + _, err = batch.Exec(uint8(2), time.Time{}, nil, []time.Time{date}, []*time.Time{nil, nil, &date}, sql.NullTime{Time: date, Valid: true}, sql.NullTime{Time: time.Time{}, Valid: false}) require.NoError(t, err) require.NoError(t, scope.Commit()) var ( @@ -104,7 +104,7 @@ func TestStdDate(t *testing.T) { &result2.Col5, &result2.Col6, )) - require.Equal(t, date, result2.Col1) + require.Equal(t, time.Unix(0, 0).UTC(), result2.Col1) assert.Equal(t, "UTC", result2.Col1.Location().String()) require.Nil(t, result2.Col2) assert.Equal(t, []time.Time{date}, result2.Col3) diff --git a/tests/std/datetime64_test.go b/tests/std/datetime64_test.go index 60b48c7d48..20ba9432d3 100644 --- a/tests/std/datetime64_test.go +++ b/tests/std/datetime64_test.go @@ -20,14 +20,14 @@ package std import ( "database/sql" "fmt" - "github.com/ClickHouse/clickhouse-go/v2" - clickhouse_tests "github.com/ClickHouse/clickhouse-go/v2/tests" - "github.com/stretchr/testify/require" "strconv" "testing" "time" + "github.com/ClickHouse/clickhouse-go/v2" + clickhouse_tests "github.com/ClickHouse/clickhouse-go/v2/tests" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestStdDateTime64(t *testing.T) { @@ -53,6 +53,7 @@ func TestStdDateTime64(t *testing.T) { , Col7 DateTime64(0, 'Europe/London') , Col8 Nullable(DateTime64(3, 'Europe/Moscow')) , Col9 DateTime64(9) + , Col10 DateTime64(9) ) Engine MergeTree() ORDER BY tuple() ` defer func() { @@ -81,21 +82,23 @@ func TestStdDateTime64(t *testing.T) { sql.NullTime{Time: datetime3, Valid: true}, sql.NullTime{Time: time.Time{}, Valid: false}, expectedMinDateTime, + time.Time{}, ) require.NoError(t, err) require.NoError(t, scope.Commit()) var ( - col1 time.Time - col2 time.Time - col3 time.Time - col4 *time.Time - col5 []time.Time - col6 []*time.Time - col7 sql.NullTime - col8 sql.NullTime - col9 time.Time + col1 time.Time + col2 time.Time + col3 time.Time + col4 *time.Time + col5 []time.Time + col6 []*time.Time + col7 sql.NullTime + col8 sql.NullTime + col9 time.Time + col10 time.Time ) - require.NoError(t, conn.QueryRow("SELECT * FROM test_datetime64").Scan(&col1, &col2, &col3, &col4, &col5, &col6, &col7, &col8, &col9)) + require.NoError(t, conn.QueryRow("SELECT * FROM test_datetime64").Scan(&col1, &col2, &col3, &col4, &col5, &col6, &col7, &col8, &col9, &col10)) assert.Equal(t, datetime1.In(time.UTC), col1) assert.Equal(t, datetime2.UnixNano(), col2.UnixNano()) assert.Equal(t, datetime3.UnixNano(), col3.UnixNano()) @@ -113,6 +116,7 @@ func TestStdDateTime64(t *testing.T) { require.Equal(t, sql.NullTime{Time: datetime3.In(col7.Time.Location()), Valid: true}, col7) require.Equal(t, sql.NullTime{Time: time.Time{}, Valid: false}, col8) require.Equal(t, time.Date(1900, 01, 01, 0, 0, 0, 0, time.UTC), col9) + require.Equal(t, time.Unix(0, 0).UTC(), col10) }) } } diff --git a/tests/std/datetime_test.go b/tests/std/datetime_test.go index e506d59160..a3c71187a6 100644 --- a/tests/std/datetime_test.go +++ b/tests/std/datetime_test.go @@ -20,14 +20,14 @@ package std import ( "database/sql" "fmt" - "github.com/ClickHouse/clickhouse-go/v2" - clickhouse_tests "github.com/ClickHouse/clickhouse-go/v2/tests" - "github.com/stretchr/testify/require" "strconv" "testing" "time" + "github.com/ClickHouse/clickhouse-go/v2" + clickhouse_tests "github.com/ClickHouse/clickhouse-go/v2/tests" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestStdDateTime(t *testing.T) { @@ -48,6 +48,7 @@ func TestStdDateTime(t *testing.T) { , Col6 Array(Nullable(DateTime('Europe/Moscow'))) , Col7 DateTime , Col8 Nullable(DateTime) + ,Col9 DateTime ) Engine MergeTree() ORDER BY tuple()` defer func() { conn.Exec("DROP TABLE test_datetime") @@ -74,6 +75,7 @@ func TestStdDateTime(t *testing.T) { Time: time.Time{}, Valid: false, }, + time.Time{}, ) require.NoError(t, err) require.NoError(t, scope.Commit()) @@ -86,8 +88,9 @@ func TestStdDateTime(t *testing.T) { col6 []*time.Time col7 sql.NullTime col8 sql.NullTime + col9 time.Time ) - require.NoError(t, conn.QueryRow("SELECT * FROM test_datetime").Scan(&col1, &col2, &col3, &col4, &col5, &col6, &col7, &col8)) + require.NoError(t, conn.QueryRow("SELECT * FROM test_datetime").Scan(&col1, &col2, &col3, &col4, &col5, &col6, &col7, &col8, &col9)) assert.Equal(t, datetime.In(time.UTC), col1) assert.Equal(t, datetime.Unix(), col2.Unix()) assert.Equal(t, datetime.Unix(), col3.Unix()) @@ -120,7 +123,7 @@ func TestStdDateTime(t *testing.T) { Time: time.Time{}, Valid: false, }, col8) - + assert.Equal(t, time.Unix(0, 0).UTC(), col9) }) } }