From f736e5959db62bf1b55c4b1b006fbf521c4cdbd5 Mon Sep 17 00:00:00 2001 From: apstndb <803393+apstndb@users.noreply.github.com> Date: Fri, 12 Jun 2026 18:53:15 +0900 Subject: [PATCH] Adopt spancodec v0.1.2 and spanvalue v0.8.1 in EncodeOptions spancodec v0.1.2 fixed []T inference from element WithGoType registrations (apstndb/spancodec#1, filed from this package), so the slice-type registration workarounds are gone, and the new WithTypedValueEncoder collapses each encoder+type pair into one option. The PGNumericValue rounding hazard doc now points at spanvalue v0.8.1 PGNumericValueExact (apstndb/spanvalue#249, also filed from here). Behavior verified unchanged by the integration probes against the PG-dialect emulator, including the RowTypeFor annotation inference test that now exercises the fixed element-based slice inference. Co-Authored-By: Claude Fable 5 --- encode_options.go | 44 +++++++++++------------------ go.mod | 4 +-- go.sum | 8 +++--- integration/pgtypeannotation/go.mod | 4 +-- integration/pgtypeannotation/go.sum | 8 +++--- 5 files changed, 28 insertions(+), 40 deletions(-) diff --git a/encode_options.go b/encode_options.go index 525c646..77992b6 100644 --- a/encode_options.go +++ b/encode_options.go @@ -37,11 +37,14 @@ import ( // // PGNumericValue formats the wire string with the client's canonical // [cloud.google.com/go/spanner.NumericString] (9 fractional digits, silently -// rounding) even though PG numeric accepts a wider value space. Because these -// registrations override the client mirror, +// rounding) even though PG numeric accepts a wider value space — matching +// the client mirror's NUMERIC scale. Because these registrations override +// the client mirror, // [github.com/apstndb/spancodec.WithLossOfPrecisionHandling] does not apply -// to them; pass values needing more fractional digits (or NaN) as -// [cloud.google.com/go/spanner.PGNumeric] wire strings instead. +// to them. For exact wider-scale values use +// [github.com/apstndb/spanvalue/gcvctor.PGNumericValueExact] (spanvalue +// v0.8.1+) or pass [cloud.google.com/go/spanner.PGNumeric] wire strings +// (also the NaN path) directly. // - [cloud.google.com/go/spanner.NullJSON] → // [github.com/apstndb/spanvalue/gcvctor.PGJSONBValue] of Value when // Valid, typed NULL PG_JSONB otherwise. Like the client, Value is always @@ -57,14 +60,12 @@ import ( // handling for its exact dynamic type only. Named types (e.g. type MyRat // big.Rat) and other NUMERIC-capable inputs such as string-based wire values // are untouched. Per spancodec's contract a registration for T also applies -// per element of []T, and the paired WithGoType supplies the ARRAY element -// type for nil and empty slices, so []big.Rat, []*big.Rat, +// per element of []T, and the registered Spanner type supplies the ARRAY +// element type for nil and empty slices, so []big.Rat, []*big.Rat, // []spanner.NullNumeric, and []spanner.NullJSON encode as arrays of -// PG-annotated elements. The slice types themselves are additionally -// registered with WithGoType: static inference resolves an exact Go type -// (the client supports []big.Rat etc. natively) before falling back to a -// registered element type, so without the slice registrations TypeFor[[]T] -// would report un-annotated ARRAY element types. +// PG-annotated elements. Since spancodec v0.1.2 static inference also +// resolves []T from the element registration (apstndb/spancodec#1), so no +// separate slice-type registrations are needed. // // Decoding needs no counterpart: the client (and therefore // [github.com/apstndb/spancodec.Decode] / @@ -76,40 +77,27 @@ import ( // represent (the client fails with "unexpected string value"); use // [cloud.google.com/go/spanner.PGNumeric] when NaN is possible. func EncodeOptions() []spancodec.EncodeOption { - pgNumericArray := typector.ElemTypeToArrayType(typector.PGNumeric()) - pgJSONBArray := typector.ElemTypeToArrayType(typector.PGJSONB()) return []spancodec.EncodeOption{ - spancodec.WithValueEncoder(func(v big.Rat) (spanner.GenericColumnValue, error) { + spancodec.WithTypedValueEncoder(typector.PGNumeric(), func(v big.Rat) (spanner.GenericColumnValue, error) { return gcvctor.PGNumericValue(&v), nil }), - spancodec.WithGoType[big.Rat](typector.PGNumeric()), - spancodec.WithGoType[[]big.Rat](pgNumericArray), - - spancodec.WithValueEncoder(func(v *big.Rat) (spanner.GenericColumnValue, error) { + spancodec.WithTypedValueEncoder(typector.PGNumeric(), func(v *big.Rat) (spanner.GenericColumnValue, error) { if v == nil { return gcvctor.NullOf(typector.PGNumeric()), nil } return gcvctor.PGNumericValue(v), nil }), - spancodec.WithGoType[*big.Rat](typector.PGNumeric()), - spancodec.WithGoType[[]*big.Rat](pgNumericArray), - - spancodec.WithValueEncoder(func(v spanner.NullNumeric) (spanner.GenericColumnValue, error) { + spancodec.WithTypedValueEncoder(typector.PGNumeric(), func(v spanner.NullNumeric) (spanner.GenericColumnValue, error) { if !v.Valid { return gcvctor.NullOf(typector.PGNumeric()), nil } return gcvctor.PGNumericValue(&v.Numeric), nil }), - spancodec.WithGoType[spanner.NullNumeric](typector.PGNumeric()), - spancodec.WithGoType[[]spanner.NullNumeric](pgNumericArray), - - spancodec.WithValueEncoder(func(v spanner.NullJSON) (spanner.GenericColumnValue, error) { + spancodec.WithTypedValueEncoder(typector.PGJSONB(), func(v spanner.NullJSON) (spanner.GenericColumnValue, error) { if !v.Valid { return gcvctor.NullOf(typector.PGJSONB()), nil } return gcvctor.PGJSONBValue(v.Value) }), - spancodec.WithGoType[spanner.NullJSON](typector.PGJSONB()), - spancodec.WithGoType[[]spanner.NullJSON](pgJSONBArray), } } diff --git a/go.mod b/go.mod index 12c3363..9d55dd3 100644 --- a/go.mod +++ b/go.mod @@ -5,9 +5,9 @@ go 1.24.0 require ( cloud.google.com/go v0.123.0 cloud.google.com/go/spanner v1.84.1 - github.com/apstndb/spancodec v0.1.1 + github.com/apstndb/spancodec v0.1.2 github.com/apstndb/spantype v0.3.11 - github.com/apstndb/spanvalue v0.8.0 + github.com/apstndb/spanvalue v0.8.1 github.com/google/go-cmp v0.7.0 github.com/google/uuid v1.6.0 google.golang.org/protobuf v1.36.11 diff --git a/go.sum b/go.sum index 108e23f..6205868 100644 --- a/go.sum +++ b/go.sum @@ -630,12 +630,12 @@ github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kd github.com/apache/arrow/go/v10 v10.0.1/go.mod h1:YvhnlEePVnBS4+0z3fhPfUy7W1Ikj0Ih0vcRo/gZ1M0= github.com/apache/arrow/go/v11 v11.0.0/go.mod h1:Eg5OsL5H+e299f7u5ssuXsuHQVEGC4xei5aX110hRiI= github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU= -github.com/apstndb/spancodec v0.1.1 h1:26jll4gTzB18yUilmSSE1IfCF9Rht2j/+cc492hjixE= -github.com/apstndb/spancodec v0.1.1/go.mod h1:muPblFXUB5gkkvBBEM/2zzuVAOvin/dBtDsKagIcivY= +github.com/apstndb/spancodec v0.1.2 h1:QPRHmn989WV4lyzvYW7hSyzSYu5106hWDiEA1qMVdc0= +github.com/apstndb/spancodec v0.1.2/go.mod h1:muPblFXUB5gkkvBBEM/2zzuVAOvin/dBtDsKagIcivY= github.com/apstndb/spantype v0.3.11 h1:wKue4WLYGT82MH3B3TRSFn8tWIbk1Geczs+5BAEtnK4= github.com/apstndb/spantype v0.3.11/go.mod h1:9eHowE7LcJ155ukCYUyuNzVAw9Ne0GXPXpHmu+iaMyk= -github.com/apstndb/spanvalue v0.8.0 h1:wLHl/0m5C6PvRwJOJoz1nRL4qSpS17eS1tW3Pjzcvo8= -github.com/apstndb/spanvalue v0.8.0/go.mod h1:bqVJYydQf+D0Tux1LtyRlREPVwrVYNG+1usZJ489GTA= +github.com/apstndb/spanvalue v0.8.1 h1:9EHScZGDLqksF0krmc9vXGyDHhyf4G0ymTTW6n4/uG8= +github.com/apstndb/spanvalue v0.8.1/go.mod h1:bqVJYydQf+D0Tux1LtyRlREPVwrVYNG+1usZJ489GTA= github.com/apstndb/structfields v0.1.0 h1:TQbi8EpzLyDr1GOsLWJfMQrtw+cq7BQhNCHhqZTCtEg= github.com/apstndb/structfields v0.1.0/go.mod h1:iZuSnr5cvgVvMaEhm0ceB+auA+MeNmA1mtnBA05m9Qw= github.com/apstndb/structfields/spannertag v0.1.0 h1:faXv5yYgKHV4DA3V0UpL4D9cTgMM87yacNbno0p3ulM= diff --git a/integration/pgtypeannotation/go.mod b/integration/pgtypeannotation/go.mod index a2144ab..56fe503 100644 --- a/integration/pgtypeannotation/go.mod +++ b/integration/pgtypeannotation/go.mod @@ -5,11 +5,11 @@ go 1.25.0 require ( cloud.google.com/go v0.123.0 cloud.google.com/go/spanner v1.84.1 - github.com/apstndb/spancodec v0.1.1 + github.com/apstndb/spancodec v0.1.2 github.com/apstndb/spanemuboost v0.4.3 github.com/apstndb/spanpg v0.0.0 github.com/apstndb/spantype v0.3.11 - github.com/apstndb/spanvalue v0.8.0 + github.com/apstndb/spanvalue v0.8.1 github.com/google/go-cmp v0.7.0 github.com/google/uuid v1.6.0 google.golang.org/api v0.247.0 diff --git a/integration/pgtypeannotation/go.sum b/integration/pgtypeannotation/go.sum index 50026dd..5962ff8 100644 --- a/integration/pgtypeannotation/go.sum +++ b/integration/pgtypeannotation/go.sum @@ -638,14 +638,14 @@ github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kd github.com/apache/arrow/go/v10 v10.0.1/go.mod h1:YvhnlEePVnBS4+0z3fhPfUy7W1Ikj0Ih0vcRo/gZ1M0= github.com/apache/arrow/go/v11 v11.0.0/go.mod h1:Eg5OsL5H+e299f7u5ssuXsuHQVEGC4xei5aX110hRiI= github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU= -github.com/apstndb/spancodec v0.1.1 h1:26jll4gTzB18yUilmSSE1IfCF9Rht2j/+cc492hjixE= -github.com/apstndb/spancodec v0.1.1/go.mod h1:muPblFXUB5gkkvBBEM/2zzuVAOvin/dBtDsKagIcivY= +github.com/apstndb/spancodec v0.1.2 h1:QPRHmn989WV4lyzvYW7hSyzSYu5106hWDiEA1qMVdc0= +github.com/apstndb/spancodec v0.1.2/go.mod h1:muPblFXUB5gkkvBBEM/2zzuVAOvin/dBtDsKagIcivY= github.com/apstndb/spanemuboost v0.4.3 h1:LmoXNXSneb+4lysaSvRZgzFw6jh6xuYyvahP45/lo80= github.com/apstndb/spanemuboost v0.4.3/go.mod h1:5qMaU+8vWhS4jcRi9tpUhy7Z2sY3Ljrl7FbCap8nEGo= github.com/apstndb/spantype v0.3.11 h1:wKue4WLYGT82MH3B3TRSFn8tWIbk1Geczs+5BAEtnK4= github.com/apstndb/spantype v0.3.11/go.mod h1:9eHowE7LcJ155ukCYUyuNzVAw9Ne0GXPXpHmu+iaMyk= -github.com/apstndb/spanvalue v0.8.0 h1:wLHl/0m5C6PvRwJOJoz1nRL4qSpS17eS1tW3Pjzcvo8= -github.com/apstndb/spanvalue v0.8.0/go.mod h1:bqVJYydQf+D0Tux1LtyRlREPVwrVYNG+1usZJ489GTA= +github.com/apstndb/spanvalue v0.8.1 h1:9EHScZGDLqksF0krmc9vXGyDHhyf4G0ymTTW6n4/uG8= +github.com/apstndb/spanvalue v0.8.1/go.mod h1:bqVJYydQf+D0Tux1LtyRlREPVwrVYNG+1usZJ489GTA= github.com/apstndb/structfields v0.1.0 h1:TQbi8EpzLyDr1GOsLWJfMQrtw+cq7BQhNCHhqZTCtEg= github.com/apstndb/structfields v0.1.0/go.mod h1:iZuSnr5cvgVvMaEhm0ceB+auA+MeNmA1mtnBA05m9Qw= github.com/apstndb/structfields/spannertag v0.1.0 h1:faXv5yYgKHV4DA3V0UpL4D9cTgMM87yacNbno0p3ulM=