Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add support for NUMERIC data type #193

Merged
merged 7 commits into from Jul 15, 2020
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
44 changes: 43 additions & 1 deletion google-cloud-spanner/clirr-ignored-differences.xml
Expand Up @@ -256,11 +256,53 @@
<className>com/google/cloud/spanner/spi/v1/SpannerRpc</className>
<method>com.google.api.gax.retrying.RetrySettings getPartitionedDmlRetrySettings()</method>
</difference>

<!-- Streaming PDML -->
<difference>
<differenceType>7012</differenceType>
<className>com/google/cloud/spanner/spi/v1/SpannerRpc</className>
<method>com.google.api.gax.rpc.ServerStream executeStreamingPartitionedDml(com.google.spanner.v1.ExecuteSqlRequest, java.util.Map, org.threeten.bp.Duration)</method>
</difference>

<!-- Add support for NUMERIC data type -->
<difference>
<differenceType>7013</differenceType>
<className>com/google/cloud/spanner/AbstractStructReader</className>
<method>java.math.BigDecimal getBigDecimalInternal(int)</method>
</difference>
<difference>
<differenceType>7013</differenceType>
<className>com/google/cloud/spanner/AbstractStructReader</className>
<method>java.util.List getBigDecimalListInternal(int)</method>
</difference>
<difference>
<differenceType>7012</differenceType>
<className>com/google/cloud/spanner/StructReader</className>
<method>java.math.BigDecimal getBigDecimal(int)</method>
</difference>
<difference>
<differenceType>7012</differenceType>
<className>com/google/cloud/spanner/StructReader</className>
<method>java.math.BigDecimal getBigDecimal(java.lang.String)</method>
</difference>
<difference>
<differenceType>7012</differenceType>
<className>com/google/cloud/spanner/StructReader</className>
<method>java.util.List getBigDecimalList(int)</method>
</difference>
<difference>
<differenceType>7012</differenceType>
<className>com/google/cloud/spanner/StructReader</className>
<method>java.util.List getBigDecimalList(java.lang.String)</method>
</difference>
<difference>
<differenceType>7013</differenceType>
<className>com/google/cloud/spanner/Value</className>
<method>java.math.BigDecimal getNumeric()</method>
</difference>
<difference>
<differenceType>7013</differenceType>
<className>com/google/cloud/spanner/Value</className>
<method>java.util.List getNumericArray()</method>
</difference>
</differences>
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -381,6 +385,9 @@ private Object writeReplace() {
case FLOAT64:
builder.set(fieldName).toFloat64Array((Iterable<Double>) value);
break;
case NUMERIC:
builder.set(fieldName).toNumericArray((Iterable<BigDecimal>) value);
break;
case STRING:
builder.set(fieldName).toStringArray((Iterable<String>) value);
break;
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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<Object> list = new ArrayList<>(listValue.getValuesCount());
for (com.google.protobuf.Value value : listValue.getValuesList()) {
list.add(
value.getKindCase() == KindCase.NULL_VALUE
? null
: new BigDecimal(value.getStringValue()));
}
return list;
}
case STRING:
return Lists.transform(
listValue.getValuesList(),
Expand Down Expand Up @@ -620,6 +641,11 @@ protected double getDoubleInternal(int columnIndex) {
return (Double) rowData.get(columnIndex);
}

@Override
protected BigDecimal getBigDecimalInternal(int columnIndex) {
return (BigDecimal) rowData.get(columnIndex);
}

@Override
protected String getStringInternal(int columnIndex) {
return (String) rowData.get(columnIndex);
Expand Down Expand Up @@ -685,6 +711,12 @@ protected Float64Array getDoubleListInternal(int columnIndex) {
return (Float64Array) rowData.get(columnIndex);
}

@Override
@SuppressWarnings("unchecked") // We know ARRAY<NUMERIC> produces a List<BigDecimal>.
protected List<BigDecimal> getBigDecimalListInternal(int columnIndex) {
return (List<BigDecimal>) rowData.get(columnIndex);
}

@Override
@SuppressWarnings("unchecked") // We know ARRAY<STRING> produces a List<String>.
protected List<String> getStringListInternal(int columnIndex) {
Expand Down Expand Up @@ -1176,6 +1208,11 @@ protected double getDoubleInternal(int columnIndex) {
return currRow().getDoubleInternal(columnIndex);
}

@Override
protected BigDecimal getBigDecimalInternal(int columnIndex) {
return currRow().getBigDecimalInternal(columnIndex);
}

@Override
protected String getStringInternal(int columnIndex) {
return currRow().getStringInternal(columnIndex);
Expand Down Expand Up @@ -1226,6 +1263,11 @@ protected List<Double> getDoubleListInternal(int columnIndex) {
return currRow().getDoubleListInternal(columnIndex);
}

@Override
protected List<BigDecimal> getBigDecimalListInternal(int columnIndex) {
return currRow().getBigDecimalListInternal(columnIndex);
}

@Override
protected List<String> getStringListInternal(int columnIndex) {
return currRow().getStringListInternal(columnIndex);
Expand Down
Expand Up @@ -21,6 +21,7 @@
import com.google.cloud.ByteArray;
import com.google.cloud.Date;
import com.google.cloud.Timestamp;
import java.math.BigDecimal;
import java.util.List;

/**
Expand All @@ -38,6 +39,8 @@ public abstract class AbstractStructReader implements StructReader {

protected abstract double getDoubleInternal(int columnIndex);

protected abstract BigDecimal getBigDecimalInternal(int columnIndex);

protected abstract String getStringInternal(int columnIndex);

protected abstract ByteArray getBytesInternal(int columnIndex);
Expand All @@ -58,6 +61,8 @@ public abstract class AbstractStructReader implements StructReader {

protected abstract List<Double> getDoubleListInternal(int columnIndex);

protected abstract List<BigDecimal> getBigDecimalListInternal(int columnIndex);

protected abstract List<String> getStringListInternal(int columnIndex);

protected abstract List<ByteArray> getBytesListInternal(int columnIndex);
Expand Down Expand Up @@ -127,6 +132,19 @@ public double getDouble(String columnName) {
return getDoubleInternal(columnIndex);
}

@Override
public BigDecimal getBigDecimal(int columnIndex) {
checkNonNullOfType(columnIndex, Type.numeric(), columnIndex);
return getBigDecimalInternal(columnIndex);
}

@Override
public BigDecimal getBigDecimal(String columnName) {
int columnIndex = getColumnIndex(columnName);
checkNonNullOfType(columnIndex, Type.numeric(), columnName);
return getBigDecimalInternal(columnIndex);
}

@Override
public String getString(int columnIndex) {
checkNonNullOfType(columnIndex, Type.string(), columnIndex);
Expand Down Expand Up @@ -257,6 +275,19 @@ public List<Double> getDoubleList(String columnName) {
return getDoubleListInternal(columnIndex);
}

@Override
public List<BigDecimal> getBigDecimalList(int columnIndex) {
checkNonNullOfType(columnIndex, Type.array(Type.numeric()), columnIndex);
return getBigDecimalListInternal(columnIndex);
}

@Override
public List<BigDecimal> getBigDecimalList(String columnName) {
int columnIndex = getColumnIndex(columnName);
checkNonNullOfType(columnIndex, Type.array(Type.numeric()), columnName);
return getBigDecimalListInternal(columnIndex);
}

@Override
public List<String> getStringList(int columnIndex) {
checkNonNullOfType(columnIndex, Type.array(Type.string()), columnIndex);
Expand Down
Expand Up @@ -22,6 +22,7 @@
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import java.math.BigDecimal;
import java.util.List;

/** Forwarding implements of StructReader */
Expand Down Expand Up @@ -133,6 +134,16 @@ public double getDouble(String columnName) {
return delegate.get().getDouble(columnName);
}

@Override
public BigDecimal getBigDecimal(int columnIndex) {
return delegate.get().getBigDecimal(columnIndex);
}

@Override
public BigDecimal getBigDecimal(String columnName) {
return delegate.get().getBigDecimal(columnName);
}

@Override
public String getString(int columnIndex) {
checkValidState();
Expand Down Expand Up @@ -253,6 +264,16 @@ public List<Double> getDoubleList(String columnName) {
return delegate.get().getDoubleList(columnName);
}

@Override
public List<BigDecimal> getBigDecimalList(int columnIndex) {
return delegate.get().getBigDecimalList(columnIndex);
}

@Override
public List<BigDecimal> getBigDecimalList(String columnName) {
return delegate.get().getBigDecimalList(columnName);
}

@Override
public List<String> getStringList(int columnIndex) {
checkValidState();
Expand Down
Expand Up @@ -26,6 +26,7 @@
import com.google.protobuf.NullValue;
import com.google.protobuf.Value;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
Expand Down Expand Up @@ -131,6 +132,11 @@ public Builder append(@Nullable Double value) {
buffer.add(value);
return this;
}
/** Appends a {@code NUMERIC} value to the key. */
public Builder append(@Nullable BigDecimal value) {
buffer.add(value);
return this;
}
/** Appends a {@code STRING} value to the key. */
public Builder append(@Nullable String value) {
buffer.add(value);
Expand Down Expand Up @@ -172,6 +178,8 @@ public Builder appendObject(@Nullable Object value) {
append((Float) value);
} else if (value instanceof Double) {
append((Double) value);
} else if (value instanceof BigDecimal) {
append((BigDecimal) value);
} else if (value instanceof String) {
append((String) value);
} else if (value instanceof ByteArray) {
Expand Down Expand Up @@ -215,6 +223,7 @@ public int size() {
* <li>{@code BOOL} is represented by {@code Boolean}
* <li>{@code INT64} is represented by {@code Long}
* <li>{@code FLOAT64} is represented by {@code Double}
* <li>{@code NUMERIC} is represented by {@code BigDecimal}
* <li>{@code STRING} is represented by {@code String}
* <li>{@code BYTES} is represented by {@link ByteArray}
* <li>{@code TIMESTAMP} is represented by {@link Timestamp}
Expand Down Expand Up @@ -276,6 +285,8 @@ ListValue toProto() {
builder.addValuesBuilder().setStringValue(part.toString());
} else if (part instanceof Double) {
builder.addValuesBuilder().setNumberValue((Double) part);
} else if (part instanceof BigDecimal) {
builder.addValuesBuilder().setStringValue(part.toString());
} else if (part instanceof String) {
builder.addValuesBuilder().setStringValue((String) part);
} else if (part instanceof ByteArray) {
Expand Down
Expand Up @@ -27,6 +27,7 @@
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.google.spanner.v1.ResultSetStats;
import java.math.BigDecimal;
import java.util.List;

/** Utility methods for working with {@link com.google.cloud.spanner.ResultSet}. */
Expand Down Expand Up @@ -186,6 +187,16 @@ public double getDouble(String columnName) {
return getCurrentRowAsStruct().getDouble(columnName);
}

@Override
public BigDecimal getBigDecimal(int columnIndex) {
return getCurrentRowAsStruct().getBigDecimal(columnIndex);
}

@Override
public BigDecimal getBigDecimal(String columnName) {
return getCurrentRowAsStruct().getBigDecimal(columnName);
}

@Override
public String getString(int columnIndex) {
return getCurrentRowAsStruct().getString(columnIndex);
Expand Down Expand Up @@ -286,6 +297,16 @@ public List<Double> getDoubleList(String columnName) {
return getCurrentRowAsStruct().getDoubleList(columnName);
}

@Override
public List<BigDecimal> getBigDecimalList(int columnIndex) {
return getCurrentRowAsStruct().getBigDecimalList(columnIndex);
}

@Override
public List<BigDecimal> getBigDecimalList(String columnName) {
return getCurrentRowAsStruct().getBigDecimalList(columnName);
}

@Override
public List<String> getStringList(int columnIndex) {
return getCurrentRowAsStruct().getStringList(columnIndex);
Expand Down