Skip to content

Interpolate: keep ClickHouse whole-number floats and non-finite values typed correctly - #244

Open
youdie006 wants to merge 1 commit into
huandu:masterfrom
youdie006:fix/243-clickhouse-float-literal
Open

Interpolate: keep ClickHouse whole-number floats and non-finite values typed correctly#244
youdie006 wants to merge 1 commit into
huandu:masterfrom
youdie006:fix/243-clickhouse-float-literal

Conversation

@youdie006

Copy link
Copy Markdown

Fixes #243.

Problem

In encodeValue (interpolate.go), the reflect.Float32/reflect.Float64 cases rendered floats with strconv.AppendFloat(..., 'g', -1, N) and ignored flavor, unlike the adjacent flavor-aware String and byte-slice cases. Two symptoms result for ClickHouse:

  1. Silent Float-column narrowing. A whole-number float such as float64(1) renders as the bare literal 1. ClickHouse's SQL parser infers a bare 1 as an integer type (e.g. UInt8), so a value the caller intended as Float64 is sent typed as an integer. The narrowing only surfaces downstream -- a scan-back type mismatch, or changed arithmetic/promotion in the query itself.
  2. Non-finite case-sensitivity. NaN/+Inf/-Inf render in Go's default mixed case. ClickHouse only accepts the lowercase nan/inf/-inf and rejects the mixed-case spelling as an unknown identifier.

The same bug was fixed in the official ClickHouse/clickhouse-go driver in v2.48.0 (issue #1862 / PR #1894).

Fix

Both float cases now route through a new encodeFloat(buf, f, bitSize, flavor) helper. For ClickHouse only it emits lowercase nan/inf/-inf, and appends .0 when strconv produced a bare integer -- detected via bytes.ContainsAny(rendered, ".eE"), so a scientific-notation rendering like 1e+21 is left untouched. Every other flavor keeps its exact existing rendering. Existing ClickHouse interpolate tests use fractional floats and are unaffected.

Note on approach: this widens whole numbers to the 2.0 form rather than the clickhouse-go v2.48.0 cast(N, 'Float64') wrapper. 2.0 is a lighter, parser-native float literal, but if you'd prefer the explicit cast(...) form for parity with the sibling driver I'm happy to switch -- let me know your preference.

Test

Added TestClickHouseFloatLiteral covering float64(1)->SELECT 1.0, float32(2)->SELECT 2.0, NaN/+Inf/-Inf lowercasing, a fractional control (1.5->SELECT 1.5), and a non-ClickHouse control (MySQL float64(1) unchanged = SELECT 1).

Red/green (reverting the fix): the whole-number and non-finite cases fail with e.g. got "SELECT 1", want "SELECT 1.0"; with the fix go test ./... passes. gofmt and go vet ./... are clean.


This contribution was prepared with AI assistance.

…s typed correctly

In encodeValue the Float32/Float64 cases rendered floats with
strconv.AppendFloat(..., 'g', -1, N) and ignored flavor, unlike the adjacent
flavor-aware String/Slice cases. For ClickHouse this had two symptoms: a
whole-number float such as float64(1) rendered as bare '1' (ClickHouse infers an
integer type and silently narrows a Float column), and NaN/+Inf/-Inf rendered in
Go's mixed case (ClickHouse only accepts lowercase nan/inf/-inf).

Route both cases through a new encodeFloat helper that, for ClickHouse only,
emits lowercase non-finite spellings and appends '.0' when strconv produced a
bare integer (detected via bytes.ContainsAny(rendered, ".eE") so 1e+21 is left
untouched). Every other flavor keeps its exact existing rendering.

Fixes huandu#243
Copilot AI lite review requested due to automatic review settings August 18, 2026 00:54

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request fixes ClickHouse-specific float literal interpolation so float arguments remain typed as floats (avoiding whole-number narrowing) and non-finite values parse correctly in ClickHouse SQL.

Changes:

  • Route float interpolation through a new encodeFloat helper that is flavor-aware.
  • For ClickHouse only: emit lowercase nan/inf/-inf and append .0 to whole-number float renderings.
  • Add targeted tests validating ClickHouse float literal behavior and a non-ClickHouse control.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
interpolate.go Adds encodeFloat and updates float cases in encodeValue to preserve ClickHouse float typing and non-finite parsing.
interpolate_ch_float_test.go Adds regression tests for ClickHouse whole-number floats and non-finite float literals, plus a MySQL control case.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Interpolate: float64/float32 render as bare integer literals for whole numbers, silently narrowing ClickHouse Float columns

2 participants