Skip to content

Commit

Permalink
Zero-value timestamp to be formatted as toDateTime(0) in bind (#1260)
Browse files Browse the repository at this point in the history
  • Loading branch information
jkaflik committed Mar 28, 2024
1 parent 6f48d52 commit dc43405
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 0 deletions.
6 changes: 6 additions & 0 deletions bind.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 8 additions & 0 deletions bind_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -268,27 +268,35 @@ 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
val, _ = format(t1.Location(), MilliSeconds, t1)
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
val, _ = format(t1.Location(), MicroSeconds, t1)
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
val, _ = format(t1.Location(), NanoSeconds, t1)
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)
}
Expand Down
27 changes: 27 additions & 0 deletions tests/issues/1016_test.go
Original file line number Diff line number Diff line change
@@ -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)
}

0 comments on commit dc43405

Please sign in to comment.