Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 16 additions & 28 deletions encode_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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] /
Expand All @@ -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),
}
}
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -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=
Expand Down
4 changes: 2 additions & 2 deletions integration/pgtypeannotation/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 4 additions & 4 deletions integration/pgtypeannotation/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -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=
Expand Down