From 83352c475681f596e0f1e811f8c2056aef6179b2 Mon Sep 17 00:00:00 2001 From: Alvaro Viebrantz Date: Tue, 29 Oct 2024 17:12:26 -0400 Subject: [PATCH] fix(bigquery): parse negative NUMERIC from arrow (#11052) The `big.Int.SetBytes` method interprets input as an unsigned number, so we lose sign information when parsing using. So Arrow decimal parsing code is simplified by just relying on `big.Rat.SetString` method for parsing. Towards internal b/376149769 --- bigquery/arrow.go | 12 ++++-------- bigquery/integration_test.go | 8 ++++++++ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/bigquery/arrow.go b/bigquery/arrow.go index 825256dec0b4..041edf8d96a3 100644 --- a/bigquery/arrow.go +++ b/bigquery/arrow.go @@ -241,18 +241,14 @@ func convertArrowValue(col arrow.Array, i int, ft arrow.DataType, fs *FieldSchem case *arrow.Decimal128Type: dft := ft.(*arrow.Decimal128Type) v := col.(*array.Decimal128).Value(i) - rat := big.NewRat(1, 1) - rat.Num().SetBytes(v.BigInt().Bytes()) - d := rat.Denom() - d.Exp(big.NewInt(10), big.NewInt(int64(dft.Scale)), nil) + rat := new(big.Rat) + rat.SetString(v.ToString(dft.Scale)) return Value(rat), nil case *arrow.Decimal256Type: dft := ft.(*arrow.Decimal256Type) v := col.(*array.Decimal256).Value(i) - rat := big.NewRat(1, 1) - rat.Num().SetBytes(v.BigInt().Bytes()) - d := rat.Denom() - d.Exp(big.NewInt(10), big.NewInt(int64(dft.Scale)), nil) + rat := new(big.Rat) + rat.SetString(v.ToString(dft.Scale)) return Value(rat), nil case *arrow.ListType: arr := col.(*array.List) diff --git a/bigquery/integration_test.go b/bigquery/integration_test.go index df26585fa6f8..649790b2814f 100644 --- a/bigquery/integration_test.go +++ b/bigquery/integration_test.go @@ -2167,6 +2167,7 @@ func initQueryParameterTestCases() { dtm := civil.DateTime{Date: d, Time: tm} ts := time.Date(2016, 3, 20, 15, 04, 05, 0, time.UTC) rat := big.NewRat(13, 10) + nrat := big.NewRat(-13, 10) bigRat := big.NewRat(12345, 10e10) rangeTimestamp1 := &RangeValue{ Start: time.Date(2016, 3, 20, 15, 04, 05, 0, time.UTC), @@ -2208,6 +2209,13 @@ func initQueryParameterTestCases() { []Value{rat}, rat, }, + { + "NegativeBigRatParam", + "SELECT @val", + []QueryParameter{{Name: "val", Value: nrat}}, + []Value{nrat}, + nrat, + }, { "BoolParam", "SELECT @val",