diff --git a/.github/workflows/run-tests-cloud.yml b/.github/workflows/run-tests-cloud.yml index 7d273afe1d..d7db86e48c 100644 --- a/.github/workflows/run-tests-cloud.yml +++ b/.github/workflows/run-tests-cloud.yml @@ -18,6 +18,7 @@ jobs: shell: bash strategy: fail-fast: true + max-parallel: 1 matrix: go: - "1.22" diff --git a/.github/workflows/run-tests-head.yml b/.github/workflows/run-tests-head.yml index 20530c498e..8d9ed69ab3 100644 --- a/.github/workflows/run-tests-head.yml +++ b/.github/workflows/run-tests-head.yml @@ -15,6 +15,7 @@ jobs: runs-on: ubuntu-latest strategy: fail-fast: true + max-parallel: 1 matrix: go: - "1.20" diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index a35e324bbe..a1dac80bed 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -15,6 +15,7 @@ jobs: runs-on: ubuntu-latest strategy: fail-fast: true + max-parallel: 1 matrix: go: - "1.22" diff --git a/bind.go b/bind.go index 1d4f55e2f3..f6373078f1 100644 --- a/bind.go +++ b/bind.go @@ -247,6 +247,12 @@ func bindNamed(tz *time.Location, query string, args ...any) (_ string, err erro func formatTime(tz *time.Location, scale TimeUnit, value time.Time) (string, error) { switch value.Location().String() { case "Local", "": + // It's required to pass timestamp as string due to decimal overflow for higher precision, + // but zero-value string "toDateTime('0')" will be not parsed by ClickHouse. + if value.Unix() == 0 { + return "toDateTime(0)", nil + } + switch scale { case Seconds: return fmt.Sprintf("toDateTime('%d')", value.Unix()), nil diff --git a/bind_test.go b/bind_test.go index 9d75ca2f1f..29f70692e1 100644 --- a/bind_test.go +++ b/bind_test.go @@ -268,6 +268,8 @@ func TestFormatScaledTime(t *testing.T) { require.Equal(t, "toDateTime('2022-01-12 15:00:00')", val) val, _ = format(t1.Location(), Seconds, t1.In(time.Now().Location())) require.Equal(t, "toDateTime('1641999600')", val) + val, _ = format(t1.Location(), Seconds, time.Unix(0, 0)) + require.Equal(t, "toDateTime(0)", val) val, _ = format(tz, Seconds, t1) require.Equal(t, "toDateTime('2022-01-12 15:00:00', 'UTC')", val) // milliseconds @@ -275,6 +277,8 @@ func TestFormatScaledTime(t *testing.T) { require.Equal(t, "toDateTime64('2022-01-12 15:00:00.123', 3)", val) val, _ = format(t1.Location(), MilliSeconds, t1.In(time.Now().Location())) require.Equal(t, "toDateTime64('1641999600123', 3)", val) + val, _ = format(t1.Location(), MilliSeconds, time.Unix(0, 0)) + require.Equal(t, "toDateTime(0)", val) val, _ = format(tz, MilliSeconds, t1) require.Equal(t, "toDateTime64('2022-01-12 15:00:00.123', 3, 'UTC')", val) // microseconds @@ -282,6 +286,8 @@ func TestFormatScaledTime(t *testing.T) { require.Equal(t, "toDateTime64('2022-01-12 15:00:00.123456', 6)", val) val, _ = format(t1.Location(), MicroSeconds, t1.In(time.Now().Location())) require.Equal(t, "toDateTime64('1641999600123456', 6)", val) + val, _ = format(t1.Location(), MicroSeconds, time.Unix(0, 0)) + require.Equal(t, "toDateTime(0)", val) val, _ = format(tz, MicroSeconds, t1) require.Equal(t, "toDateTime64('2022-01-12 15:00:00.123456', 6, 'UTC')", val) // nanoseconds @@ -289,6 +295,8 @@ func TestFormatScaledTime(t *testing.T) { require.Equal(t, "toDateTime64('2022-01-12 15:00:00.123456789', 9)", val) val, _ = format(t1.Location(), NanoSeconds, t1.In(time.Now().Location())) require.Equal(t, "toDateTime64('1641999600123456789', 9)", val) + val, _ = format(t1.Location(), NanoSeconds, time.Unix(0, 0)) + require.Equal(t, "toDateTime(0)", val) val, _ = format(tz, NanoSeconds, t1) require.Equal(t, "toDateTime64('2022-01-12 15:00:00.123456789', 9, 'UTC')", val) } diff --git a/go.mod b/go.mod index 1792a31889..7b86dde938 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( 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 + github.com/docker/docker v26.0.0+incompatible github.com/docker/go-connections v0.5.0 github.com/docker/go-units v0.5.0 github.com/google/uuid v1.6.0 @@ -47,6 +47,7 @@ require ( github.com/klauspost/compress v1.17.7 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/magiconair/properties v1.8.7 // indirect + github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/patternmatcher v0.6.0 // indirect github.com/moby/sys/sequential v0.5.0 // indirect github.com/moby/sys/user v0.1.0 // indirect diff --git a/go.sum b/go.sum index d45da47e96..877c1addf9 100644 --- a/go.sum +++ b/go.sum @@ -34,8 +34,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v25.0.3+incompatible h1:D5fy/lYmY7bvZa0XTZ5/UJPljor41F+vdyJG5luQLfQ= -github.com/docker/docker v25.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v26.0.0+incompatible h1:Ng2qi+gdKADUa/VM+6b6YaY2nlZhk/lVJiKR/2bMudU= +github.com/docker/docker v26.0.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= @@ -95,6 +95,8 @@ github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3v github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mkevac/debugcharts v0.0.0-20191222103121-ae1c48aa8615 h1:/mD+ABZyXD39BzJI2XyRJlqdZG11gXFo0SSynL+OFeU= github.com/mkevac/debugcharts v0.0.0-20191222103121-ae1c48aa8615/go.mod h1:Ad7oeElCZqA1Ufj0U9/liOF4BtVepxRcTvr2ey7zTvM= +github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= +github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= diff --git a/tests/issues/1016_test.go b/tests/issues/1016_test.go new file mode 100644 index 0000000000..052cc06601 --- /dev/null +++ b/tests/issues/1016_test.go @@ -0,0 +1,27 @@ +package issues + +import ( + "context" + "testing" + "time" + + clickhouse_tests "github.com/ClickHouse/clickhouse-go/v2/tests" + "github.com/stretchr/testify/require" +) + +func Test1016(t *testing.T) { + testEnv, err := clickhouse_tests.GetTestEnvironment("issues") + require.NoError(t, err) + conn, err := clickhouse_tests.TestClientWithDefaultSettings(testEnv) + require.NoError(t, err) + + rows, err := conn.Query(context.Background(), "SELECT ?;", time.Unix(0, 0).UTC()) + require.NoError(t, err) + defer rows.Close() + + require.True(t, rows.Next()) + var v time.Time + err = rows.Scan(&v) + require.NoError(t, err) + require.Equal(t, time.Unix(0, 0).UTC(), v) +}