Skip to content

Commit 718ec2a

Browse files
feat: add BIGNUMERIC support (#703)
Expose BIGNUMERIC type in the client cc: @MingyuZhong
1 parent f59241b commit 718ec2a

File tree

7 files changed

+193
-14
lines changed

7 files changed

+193
-14
lines changed

google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/LegacySQLTypeName.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@ public LegacySQLTypeName apply(String constant) {
6161
*/
6262
public static final LegacySQLTypeName NUMERIC =
6363
type.createAndRegister("NUMERIC").setStandardType(StandardSQLTypeName.NUMERIC);
64+
/**
65+
* A decimal value with 76+ digits of precision (the 77th digit is partial) and 38 digits of scale
66+
*/
67+
public static final LegacySQLTypeName BIGNUMERIC =
68+
type.createAndRegister("BIGNUMERIC").setStandardType(StandardSQLTypeName.BIGNUMERIC);
6469
/** A Boolean value (true or false). */
6570
public static final LegacySQLTypeName BOOLEAN =
6671
type.createAndRegister("BOOLEAN").setStandardType(StandardSQLTypeName.BOOL);

google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/QueryParameterValue.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
* <li>Double: StandardSQLTypeName.FLOAT64
6161
* <li>Float: StandardSQLTypeName.FLOAT64
6262
* <li>BigDecimal: StandardSQLTypeName.NUMERIC
63+
* <li>BigNumeric: StandardSQLTypeName.BIGNUMERIC
6364
* </ul>
6465
*
6566
* <p>No other types are supported through that entry point. The other types can be created by
@@ -197,7 +198,10 @@ public Map<String, QueryParameterValue> getStructTypes() {
197198
@Nullable
198199
abstract Map<String, QueryParameterValue> getStructTypesInner();
199200

200-
/** Creates a {@code QueryParameterValue} object with the given value and type. */
201+
/**
202+
* Creates a {@code QueryParameterValue} object with the given value and type. Note: this does not
203+
* support BigNumeric
204+
*/
201205
public static <T> QueryParameterValue of(T value, Class<T> type) {
202206
return of(value, classToType(type));
203207
}
@@ -240,6 +244,11 @@ public static QueryParameterValue numeric(BigDecimal value) {
240244
return of(value, StandardSQLTypeName.NUMERIC);
241245
}
242246

247+
/** Creates a {@code QueryParameterValue} object with a type of BIGNUMERIC. */
248+
public static QueryParameterValue bigNumeric(BigDecimal value) {
249+
return of(value, StandardSQLTypeName.BIGNUMERIC);
250+
}
251+
243252
/** Creates a {@code QueryParameterValue} object with a type of STRING. */
244253
public static QueryParameterValue string(String value) {
245254
return of(value, StandardSQLTypeName.STRING);
@@ -363,6 +372,7 @@ private static <T> String valueToStringOrNull(T value, StandardSQLTypeName type)
363372
}
364373
break;
365374
case NUMERIC:
375+
case BIGNUMERIC:
366376
if (value instanceof BigDecimal) {
367377
return value.toString();
368378
}

google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/StandardSQLTypeName.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ public enum StandardSQLTypeName {
3232
FLOAT64,
3333
/** A decimal value with 38 digits of precision and 9 digits of scale. */
3434
NUMERIC,
35+
/**
36+
* A decimal value with 76+ digits of precision (the 77th digit is partial) and 38 digits of scale
37+
*/
38+
BIGNUMERIC,
3539
/** Variable-length character (Unicode) data. */
3640
STRING,
3741
/** Variable-length binary data. */

google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/FieldValueListTest.java

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ public class FieldValueListTest {
4949
LegacySQLTypeName.RECORD,
5050
Field.of("first", LegacySQLTypeName.FLOAT),
5151
Field.of("second", LegacySQLTypeName.TIMESTAMP)),
52-
Field.of("tenth", LegacySQLTypeName.NUMERIC));
52+
Field.of("tenth", LegacySQLTypeName.NUMERIC),
53+
Field.of("eleventh", LegacySQLTypeName.BIGNUMERIC));
5354

5455
private final Map<String, String> integerPb = ImmutableMap.of("v", "1");
5556
private final Map<String, String> floatPb = ImmutableMap.of("v", "1.5");
@@ -62,6 +63,9 @@ public class FieldValueListTest {
6263
private final Map<String, Object> recordPb =
6364
ImmutableMap.<String, Object>of("f", ImmutableList.<Object>of(floatPb, timestampPb));
6465
private final Map<String, String> numericPb = ImmutableMap.of("v", "123456789.123456789");
66+
private final Map<String, String> bigNumericPb =
67+
ImmutableMap.of(
68+
"v", "99999999999999999999999999999999999999.99999999999999999999999999999999999999");
6569

6670
private final FieldValue booleanFv = FieldValue.of(Attribute.PRIMITIVE, "false");
6771
private final FieldValue integerFv = FieldValue.of(Attribute.PRIMITIVE, "1");
@@ -78,6 +82,10 @@ public class FieldValueListTest {
7882
FieldValueList.of(
7983
ImmutableList.of(floatFv, timestampFv), schema.get("ninth").getSubFields()));
8084
private final FieldValue numericFv = FieldValue.of(Attribute.PRIMITIVE, "123456789.123456789");
85+
private final FieldValue bigNumericFv =
86+
FieldValue.of(
87+
Attribute.PRIMITIVE,
88+
"99999999999999999999999999999999999999.99999999999999999999999999999999999999");
8189

8290
private final List<?> fieldValuesPb =
8391
ImmutableList.of(
@@ -90,7 +98,8 @@ public class FieldValueListTest {
9098
nullPb,
9199
repeatedPb,
92100
recordPb,
93-
numericPb);
101+
numericPb,
102+
bigNumericPb);
94103

95104
private final FieldValueList fieldValues =
96105
FieldValueList.of(
@@ -104,7 +113,8 @@ public class FieldValueListTest {
104113
nullFv,
105114
repeatedFv,
106115
recordFv,
107-
numericFv),
116+
numericFv,
117+
bigNumericFv),
108118
schema);
109119

110120
@Test
@@ -116,7 +126,7 @@ public void testFromPb() {
116126

117127
@Test
118128
public void testGetByIndex() {
119-
assertEquals(10, fieldValues.size());
129+
assertEquals(11, fieldValues.size());
120130
assertEquals(booleanFv, fieldValues.get(0));
121131
assertEquals(integerFv, fieldValues.get(1));
122132
assertEquals(floatFv, fieldValues.get(2));
@@ -133,11 +143,12 @@ public void testGetByIndex() {
133143
assertEquals(floatFv, fieldValues.get(8).getRecordValue().get(0));
134144
assertEquals(timestampFv, fieldValues.get(8).getRecordValue().get(1));
135145
assertEquals(numericFv, fieldValues.get(9));
146+
assertEquals(bigNumericFv, fieldValues.get(10));
136147
}
137148

138149
@Test
139150
public void testGetByName() {
140-
assertEquals(10, fieldValues.size());
151+
assertEquals(11, fieldValues.size());
141152
assertEquals(booleanFv, fieldValues.get("first"));
142153
assertEquals(integerFv, fieldValues.get("second"));
143154
assertEquals(floatFv, fieldValues.get("third"));
@@ -154,6 +165,7 @@ public void testGetByName() {
154165
assertEquals(floatFv, fieldValues.get("ninth").getRecordValue().get("first"));
155166
assertEquals(timestampFv, fieldValues.get("ninth").getRecordValue().get("second"));
156167
assertEquals(numericFv, fieldValues.get("tenth"));
168+
assertEquals(bigNumericFv, fieldValues.get("eleventh"));
157169
}
158170

159171
@Test
@@ -170,7 +182,8 @@ public void testNullSchema() {
170182
nullFv,
171183
repeatedFv,
172184
recordFv,
173-
numericFv));
185+
numericFv,
186+
bigNumericFv));
174187

175188
assertEquals(fieldValues, fieldValuesNoSchema);
176189

google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/QueryJobConfigurationTest.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import com.google.cloud.bigquery.TimePartitioning.Type;
2828
import com.google.common.collect.ImmutableList;
2929
import com.google.common.collect.ImmutableMap;
30+
import java.math.BigDecimal;
3031
import java.util.List;
3132
import java.util.Map;
3233
import org.junit.Test;
@@ -101,8 +102,10 @@ public class QueryJobConfigurationTest {
101102
QueryParameterValue.string("stringValue");
102103
private static final QueryParameterValue TIMESTAMP_PARAMETER =
103104
QueryParameterValue.timestamp("2014-01-01 07:00:00.000000+00:00");
105+
private static final QueryParameterValue BIGNUMERIC_PARAMETER =
106+
QueryParameterValue.bigNumeric(new BigDecimal(1 / 3));
104107
private static final List<QueryParameterValue> POSITIONAL_PARAMETER =
105-
ImmutableList.of(STRING_PARAMETER, TIMESTAMP_PARAMETER);
108+
ImmutableList.of(STRING_PARAMETER, TIMESTAMP_PARAMETER, BIGNUMERIC_PARAMETER);
106109
private static final Map<String, QueryParameterValue> NAME_PARAMETER =
107110
ImmutableMap.of("string", STRING_PARAMETER, "timestamp", TIMESTAMP_PARAMETER);
108111
private static final QueryJobConfiguration QUERY_JOB_CONFIGURATION =

google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/QueryParameterValueTest.java

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,49 @@ public void testNumeric() {
141141
assertThat(value.getArrayValues()).isNull();
142142
}
143143

144+
@Test
145+
public void testBigNumeric() {
146+
QueryParameterValue value =
147+
QueryParameterValue.bigNumeric(new BigDecimal("0.33333333333333333333333333333333333333"));
148+
QueryParameterValue value1 =
149+
QueryParameterValue.bigNumeric(new BigDecimal("0.50000000000000000000000000000000000000"));
150+
QueryParameterValue value2 =
151+
QueryParameterValue.bigNumeric(new BigDecimal("0.00000000500000000000000000000000000000"));
152+
QueryParameterValue value3 =
153+
QueryParameterValue.bigNumeric(new BigDecimal("-0.00000000500000000000000000000000000000"));
154+
QueryParameterValue value4 =
155+
QueryParameterValue.bigNumeric(
156+
new BigDecimal("0.33333333333333333333333333333333333333888888888888888"));
157+
QueryParameterValue value5 = QueryParameterValue.bigNumeric(new BigDecimal("1e-38"));
158+
QueryParameterValue value6 = QueryParameterValue.bigNumeric(new BigDecimal("-1e38"));
159+
QueryParameterValue value7 =
160+
QueryParameterValue.bigNumeric(
161+
new BigDecimal(
162+
"578960446186580977117854925043439539266.34992332820282019728792003956564819967"));
163+
QueryParameterValue value8 =
164+
QueryParameterValue.bigNumeric(
165+
new BigDecimal(
166+
"-578960446186580977117854925043439539266.34992332820282019728792003956564819968"));
167+
168+
assertThat(value.getValue()).isEqualTo("0.33333333333333333333333333333333333333");
169+
assertThat(value1.getValue()).isEqualTo("0.50000000000000000000000000000000000000");
170+
assertThat(value2.getValue()).isEqualTo("5.00000000000000000000000000000E-9");
171+
assertThat(value3.getValue()).isEqualTo("-5.00000000000000000000000000000E-9");
172+
assertThat(value4.getValue())
173+
.isEqualTo("0.33333333333333333333333333333333333333888888888888888");
174+
assertThat(value5.getValue()).isEqualTo("1E-38");
175+
assertThat(value6.getValue()).isEqualTo("-1E+38");
176+
assertThat(value7.getValue())
177+
.isEqualTo(
178+
"578960446186580977117854925043439539266.34992332820282019728792003956564819967");
179+
assertThat(value8.getValue())
180+
.isEqualTo(
181+
"-578960446186580977117854925043439539266.34992332820282019728792003956564819968");
182+
assertThat(value.getType()).isEqualTo(StandardSQLTypeName.BIGNUMERIC);
183+
assertThat(value.getArrayType()).isNull();
184+
assertThat(value.getArrayValues()).isNull();
185+
}
186+
144187
@Test
145188
public void testString() {
146189
QueryParameterValue value = QueryParameterValue.string("foo");

0 commit comments

Comments
 (0)