fix: bind Int128/UInt128/Int256/UInt256 (big.Int) params as numeric values#1922
Open
polyglotAI-bot wants to merge 2 commits into
Open
fix: bind Int128/UInt128/Int256/UInt256 (big.Int) params as numeric values#1922polyglotAI-bot wants to merge 2 commits into
polyglotAI-bot wants to merge 2 commits into
Conversation
…alues
A *big.Int (the Go type behind Int128/UInt128/Int256/UInt256) implements
fmt.Stringer, so client-side binding matched the `case fmt.Stringer:` arm in
formatValue and emitted the value as a quoted string literal. The server then
saw a String -- `toTypeName(?)` returned `String`, and server-side
`{name:Int128}` parameters failed to parse the quoted value.
Emitting the bare decimal instead is not enough: ClickHouse reads a bare decimal
literal wider than 64 bits as Float64, losing precision (a WHERE on an Int128
column would match nothing). So in SQL mode the value is wrapped in the narrowest
wide-integer conversion that holds it exactly -- toInt128/toUInt128/toInt256/
toUInt256('<decimal>') -- mirroring how times bind as toDateTime(...) and floats
as cast(..., 'Float64'). In query-parameter text mode the {name:Type} placeholder
already declares the type, so the bare decimal is sent as-is.
Also fixes a nil *big.Int binding as '<nil>' instead of NULL.
Fixes: #1917
Add a tests/std regression test that drives a big.Int bind parameter through the database/sql surface (rebind -> bind) on both Native and HTTP, and add tuple and map nesting cases to the unit test, so every entry point and container type that reaches the big.Int bind path in issue #1917 is asserted.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Fixes #1917.
*big.Int/big.Intare the Go types behind ClickHouseInt128,UInt128,Int256andUInt256. In the client-side SQL bind rewrite (?,$1,@name),formatValue()matched*big.Inton thecase fmt.Stringer:arm and emitted it as a quoted string literal ('170141183460469231731687303715884105727'). The server then saw aString—toTypeName(?)returnedStringinstead of a number — so type-inference contexts (arithmetic, function dispatch,toTypeName) broke. Abig.Intpassed by value was worse still: it fell through tofmt.Sprintand produced garbage struct text.Emitting a bare decimal is not enough: ClickHouse infers an integer literal wider than 64 bits as
Float64, losing precision (aWHEREon anInt128column then matches nothing). The fix instead wraps the exact decimal in the narrowest wide-integer conversion that holds it —toInt128('..'),toUInt128('..'),toInt256('..')ortoUInt256('..')— mirroring how the driver already binds times astoDateTime(...)and floats ascast(..., 'Float64'). This keeps both the exact value and an integer type. Server-side{name:Type}query parameters already declare the type, so there the bare decimal is sent unchanged.Changes
bind.go: handlebig.Intand*big.IntinformatValue()before thefmt.Stringerarm. New helpersformatBigInt/bigIntConvFuncpick the narrowest ofInt128/UInt128/Int256/UInt256that holds the value, or return an actionable error if it fits none.nil *big.Int→NULL.bind_test.go:TestFormatBigInt(magnitudes, spill boundaries, out-of-range, both format modes, value + pointer),TestBindBigInt(all three placeholder styles, arrays, tuples, maps, nil, and contrast cases that must stay quoted:string, anotherfmt.Stringer,decimal.Decimal),TestBindBigIntQueryParameter(server-side{name:Type}path).tests/issues/1917_test.go: integration test over Native + HTTP — parameter binds as a wide integer, round-trips exactly, matches anInt128column, and works via server-side query parameters.tests/std/1917_test.go: the same round-trip through thedatabase/sqlsurface on both protocols.Test
Verified against ClickHouse 26.5 that the new tests fail on
main(*big.Int→'…'→String;big.Intvalue →fmt.Sprintgarbage) and pass with the fix.toInt128('…')etc. confirmed to yield the exact value and the expected wide-integer type on the server.gofmt/go vetclean on changed files; full root-package unit suite green.Pre-PR validation gate
bind.go, pass with fix)CHANGELOG.mdis auto-generated, not hand-edited; regression test undertests/issues/;t.Cleanup+ version-gated server-side subtest)