diff --git a/google-cloud-spanner/clirr-ignored-differences.xml b/google-cloud-spanner/clirr-ignored-differences.xml
index 13462a986c..ca6ae666a2 100644
--- a/google-cloud-spanner/clirr-ignored-differences.xml
+++ b/google-cloud-spanner/clirr-ignored-differences.xml
@@ -256,11 +256,53 @@
com/google/cloud/spanner/spi/v1/SpannerRpc
com.google.api.gax.retrying.RetrySettings getPartitionedDmlRetrySettings()
-
+
7012
com/google/cloud/spanner/spi/v1/SpannerRpc
com.google.api.gax.rpc.ServerStream executeStreamingPartitionedDml(com.google.spanner.v1.ExecuteSqlRequest, java.util.Map, org.threeten.bp.Duration)
+
+
+
+ 7013
+ com/google/cloud/spanner/AbstractStructReader
+ java.math.BigDecimal getBigDecimalInternal(int)
+
+
+ 7013
+ com/google/cloud/spanner/AbstractStructReader
+ java.util.List getBigDecimalListInternal(int)
+
+
+ 7012
+ com/google/cloud/spanner/StructReader
+ java.math.BigDecimal getBigDecimal(int)
+
+
+ 7012
+ com/google/cloud/spanner/StructReader
+ java.math.BigDecimal getBigDecimal(java.lang.String)
+
+
+ 7012
+ com/google/cloud/spanner/StructReader
+ java.util.List getBigDecimalList(int)
+
+
+ 7012
+ com/google/cloud/spanner/StructReader
+ java.util.List getBigDecimalList(java.lang.String)
+
+
+ 7013
+ com/google/cloud/spanner/Value
+ java.math.BigDecimal getNumeric()
+
+
+ 7013
+ com/google/cloud/spanner/Value
+ java.util.List getNumericArray()
+
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/AbstractResultSet.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/AbstractResultSet.java
index 1dfea318e0..11f36f4a92 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/AbstractResultSet.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/AbstractResultSet.java
@@ -52,6 +52,7 @@
import io.opencensus.trace.Tracing;
import java.io.IOException;
import java.io.Serializable;
+import java.math.BigDecimal;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.BitSet;
@@ -358,6 +359,9 @@ private Object writeReplace() {
case FLOAT64:
builder.set(fieldName).to((Double) value);
break;
+ case NUMERIC:
+ builder.set(fieldName).to((BigDecimal) value);
+ break;
case STRING:
builder.set(fieldName).to((String) value);
break;
@@ -381,6 +385,9 @@ private Object writeReplace() {
case FLOAT64:
builder.set(fieldName).toFloat64Array((Iterable) value);
break;
+ case NUMERIC:
+ builder.set(fieldName).toNumericArray((Iterable) value);
+ break;
case STRING:
builder.set(fieldName).toStringArray((Iterable) value);
break;
@@ -457,6 +464,8 @@ private static Object decodeValue(Type fieldType, com.google.protobuf.Value prot
return Long.parseLong(proto.getStringValue());
case FLOAT64:
return valueProtoToFloat64(proto);
+ case NUMERIC:
+ return new BigDecimal(proto.getStringValue());
case STRING:
checkType(fieldType, proto, KindCase.STRING_VALUE);
return proto.getStringValue();
@@ -513,6 +522,18 @@ public Boolean apply(com.google.protobuf.Value input) {
return new Int64Array(listValue);
case FLOAT64:
return new Float64Array(listValue);
+ case NUMERIC:
+ {
+ // Materialize list: element conversion is expensive and should happen only once.
+ ArrayList