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 JSON data type #872

Merged
merged 6 commits into from Aug 24, 2021
Merged
Show file tree
Hide file tree
Changes from 4 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
42 changes: 42 additions & 0 deletions google-cloud-spanner/clirr-ignored-differences.xml
Expand Up @@ -637,4 +637,46 @@
<method>void setOptimizerStatisticsPackage(java.lang.String)</method>
</difference>

<!-- Add support for JSON data type -->
<difference>
<differenceType>7013</differenceType>
<className>com/google/cloud/spanner/AbstractStructReader</className>
<method>java.lang.String getJsonInternal(int)</method>
</difference>
<difference>
<differenceType>7013</differenceType>
<className>com/google/cloud/spanner/AbstractStructReader</className>
<method>java.util.List getJsonListInternal(int)</method>
</difference>
<difference>
<differenceType>7012</differenceType>
<className>com/google/cloud/spanner/StructReader</className>
<method>java.lang.String getJson(int)</method>
</difference>
<difference>
<differenceType>7012</differenceType>
<className>com/google/cloud/spanner/StructReader</className>
<method>java.lang.String getJson(java.lang.String)</method>
</difference>
<difference>
<differenceType>7012</differenceType>
<className>com/google/cloud/spanner/StructReader</className>
<method>java.util.List getJsonList(int)</method>
</difference>
<difference>
<differenceType>7012</differenceType>
<className>com/google/cloud/spanner/StructReader</className>
<method>java.util.List getJsonList(java.lang.String)</method>
</difference>
<difference>
<differenceType>7013</differenceType>
<className>com/google/cloud/spanner/Value</className>
<method>java.lang.String getJson()</method>
</difference>
<difference>
<differenceType>7013</differenceType>
<className>com/google/cloud/spanner/Value</className>
<method>java.util.List getJsonArray()</method>
</difference>

</differences>
Expand Up @@ -378,6 +378,9 @@ private Object writeReplace() {
case STRING:
builder.set(fieldName).to((String) value);
zoercai marked this conversation as resolved.
Show resolved Hide resolved
break;
case JSON:
builder.set(fieldName).to(Value.json((String) value));
break;
case BYTES:
builder.set(fieldName).to((ByteArray) value);
break;
Expand All @@ -404,6 +407,9 @@ private Object writeReplace() {
case STRING:
builder.set(fieldName).toStringArray((Iterable<String>) value);
break;
case JSON:
builder.set(fieldName).toJsonArray((Iterable<String>) value);
break;
case BYTES:
builder.set(fieldName).toBytesArray((Iterable<ByteArray>) value);
break;
Expand Down Expand Up @@ -480,6 +486,7 @@ private static Object decodeValue(Type fieldType, com.google.protobuf.Value prot
case NUMERIC:
return new BigDecimal(proto.getStringValue());
case STRING:
case JSON:
checkType(fieldType, proto, KindCase.STRING_VALUE);
return proto.getStringValue();
case BYTES:
Expand Down Expand Up @@ -543,6 +550,7 @@ static Object decodeArrayValue(Type elementType, ListValue listValue) {
return list;
}
case STRING:
case JSON:
return Lists.transform(
listValue.getValuesList(),
input -> input.getKindCase() == KindCase.NULL_VALUE ? null : input.getStringValue());
Expand Down Expand Up @@ -654,6 +662,11 @@ protected String getStringInternal(int columnIndex) {
return (String) rowData.get(columnIndex);
}

@Override
protected String getJsonInternal(int columnIndex) {
return (String) rowData.get(columnIndex);
}

@Override
protected ByteArray getBytesInternal(int columnIndex) {
return (ByteArray) rowData.get(columnIndex);
Expand Down Expand Up @@ -782,6 +795,12 @@ protected List<String> getStringListInternal(int columnIndex) {
return Collections.unmodifiableList((List<String>) rowData.get(columnIndex));
}

@Override
@SuppressWarnings("unchecked") // We know ARRAY<String> produces a List<String>.
protected List<String> getJsonListInternal(int columnIndex) {
return Collections.unmodifiableList((List<String>) rowData.get(columnIndex));
}

@Override
@SuppressWarnings("unchecked") // We know ARRAY<BYTES> produces a List<ByteArray>.
protected List<ByteArray> getBytesListInternal(int columnIndex) {
Expand Down Expand Up @@ -1308,6 +1327,11 @@ protected String getStringInternal(int columnIndex) {
return currRow().getStringInternal(columnIndex);
}

@Override
protected String getJsonInternal(int columnIndex) {
return currRow().getJsonInternal(columnIndex);
}

@Override
protected ByteArray getBytesInternal(int columnIndex) {
return currRow().getBytesInternal(columnIndex);
Expand Down Expand Up @@ -1368,6 +1392,11 @@ protected List<String> getStringListInternal(int columnIndex) {
return currRow().getStringListInternal(columnIndex);
}

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

@Override
protected List<ByteArray> getBytesListInternal(int columnIndex) {
return currRow().getBytesListInternal(columnIndex);
Expand Down
Expand Up @@ -43,6 +43,8 @@ public abstract class AbstractStructReader implements StructReader {

protected abstract String getStringInternal(int columnIndex);

protected abstract String getJsonInternal(int columnIndex);
zoercai marked this conversation as resolved.
Show resolved Hide resolved

protected abstract ByteArray getBytesInternal(int columnIndex);

protected abstract Timestamp getTimestampInternal(int columnIndex);
Expand All @@ -69,6 +71,8 @@ protected Value getValueInternal(int columnIndex) {

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

protected abstract List<String> getJsonListInternal(int columnIndex);
zoercai marked this conversation as resolved.
Show resolved Hide resolved

protected abstract List<ByteArray> getBytesListInternal(int columnIndex);

protected abstract List<Timestamp> getTimestampListInternal(int columnIndex);
Expand Down Expand Up @@ -162,6 +166,19 @@ public String getString(String columnName) {
return getStringInternal(columnIndex);
}

@Override
public String getJson(int columnIndex) {
checkNonNullOfType(columnIndex, Type.json(), columnIndex);
return getJsonInternal(columnIndex);
}

@Override
public String getJson(String columnName) {
int columnIndex = getColumnIndex(columnName);
checkNonNullOfType(columnIndex, Type.json(), columnName);
return getJsonInternal(columnIndex);
}

@Override
public ByteArray getBytes(int columnIndex) {
checkNonNullOfType(columnIndex, Type.bytes(), columnIndex);
Expand Down Expand Up @@ -317,6 +334,19 @@ public List<String> getStringList(String columnName) {
return getStringListInternal(columnIndex);
}

@Override
public List<String> getJsonList(int columnIndex) {
checkNonNullOfType(columnIndex, Type.array(Type.json()), columnIndex);
return getJsonListInternal(columnIndex);
}

@Override
public List<String> getJsonList(String columnName) {
int columnIndex = getColumnIndex(columnName);
checkNonNullOfType(columnIndex, Type.array(Type.json()), columnName);
return getJsonListInternal(columnIndex);
}

@Override
public List<ByteArray> getBytesList(int columnIndex) {
checkNonNullOfType(columnIndex, Type.array(Type.bytes()), columnIndex);
Expand Down
Expand Up @@ -156,6 +156,18 @@ public String getString(String columnName) {
return delegate.get().getString(columnName);
}

@Override
public String getJson(int columnIndex) {
checkValidState();
return delegate.get().getJson(columnIndex);
}

@Override
public String getJson(String columnName) {
checkValidState();
return delegate.get().getJson(columnName);
}

@Override
public ByteArray getBytes(int columnIndex) {
checkValidState();
Expand Down Expand Up @@ -286,6 +298,18 @@ public List<String> getStringList(String columnName) {
return delegate.get().getStringList(columnName);
}

@Override
public List<String> getJsonList(int columnIndex) {
checkValidState();
return delegate.get().getJsonList(columnIndex);
}

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

@Override
public List<ByteArray> getBytesList(int columnIndex) {
checkValidState();
Expand Down
Expand Up @@ -65,6 +65,7 @@ private Key(List<Object> parts) {
* <li>{@code Float}, {@code Double} for the {@code FLOAT64} Cloud Spanner type
* <li>{@code BigDecimal} for the {@code NUMERIC} Cloud Spanner type
* <li>{@code String} for the {@code STRING} Cloud Spanner type
* <li>{@code String} for the {@code JSON} Cloud Spanner type
* <li>{@link ByteArray} for the {@code BYTES} Cloud Spanner type
* <li>{@link Timestamp} for the {@code TIMESTAMP} Cloud Spanner type
* <li>{@link Date} for the {@code DATE} Cloud Spanner type
Expand Down Expand Up @@ -228,6 +229,7 @@ public int size() {
* <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 JSON} is represented by {@code String}
* <li>{@code BYTES} is represented by {@link ByteArray}
* <li>{@code TIMESTAMP} is represented by {@link Timestamp}
* <li>{@code DATE} is represented by {@link Date}
Expand Down
Expand Up @@ -243,6 +243,16 @@ public String getString(String columnName) {
return getCurrentRowAsStruct().getString(columnName);
}

@Override
public String getJson(int columnIndex) {
return getCurrentRowAsStruct().getJson(columnIndex);
}

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

@Override
public ByteArray getBytes(int columnIndex) {
return getCurrentRowAsStruct().getBytes(columnIndex);
Expand Down Expand Up @@ -363,6 +373,16 @@ public List<String> getStringList(String columnName) {
return getCurrentRowAsStruct().getStringList(columnName);
}

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

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

@Override
public List<ByteArray> getBytesList(int columnIndex) {
return getCurrentRowAsStruct().getBytesList(columnIndex);
Expand Down
Expand Up @@ -192,6 +192,11 @@ protected String getStringInternal(int columnIndex) {
return values.get(columnIndex).getString();
}

@Override
protected String getJsonInternal(int columnIndex) {
return values.get(columnIndex).getJson();
}

@Override
protected ByteArray getBytesInternal(int columnIndex) {
return values.get(columnIndex).getBytes();
Expand Down Expand Up @@ -257,6 +262,11 @@ protected List<String> getStringListInternal(int columnIndex) {
return values.get(columnIndex).getStringArray();
}

@Override
protected List<String> getJsonListInternal(int columnIndex) {
return values.get(columnIndex).getJsonArray();
}

@Override
protected List<ByteArray> getBytesListInternal(int columnIndex) {
return values.get(columnIndex).getBytesArray();
Expand Down Expand Up @@ -341,6 +351,8 @@ private Object getAsObject(int columnIndex) {
return getBigDecimalInternal(columnIndex);
case STRING:
return getStringInternal(columnIndex);
case JSON:
return getJsonInternal(columnIndex);
case BYTES:
return getBytesInternal(columnIndex);
case TIMESTAMP:
Expand All @@ -361,6 +373,8 @@ private Object getAsObject(int columnIndex) {
return getBigDecimalListInternal(columnIndex);
case STRING:
return getStringListInternal(columnIndex);
case JSON:
return getJsonListInternal(columnIndex);
case BYTES:
return getBytesListInternal(columnIndex);
case TIMESTAMP:
Expand Down
Expand Up @@ -114,6 +114,16 @@ public interface StructReader {
/** Returns the value of a non-{@code NULL} column with type {@link Type#string()}. */
String getString(String columnName);

/** Returns the value of a non-{@code NULL} column with type {@link Type#string()}. */
default String getJson(int columnIndex) {
throw new UnsupportedOperationException("method should be overwritten");
}

/** Returns the value of a non-{@code NULL} column with type {@link Type#string()}. */
default String getJson(String columnName) {
throw new UnsupportedOperationException("method should be overwritten");
}

/** Returns the value of a non-{@code NULL} column with type {@link Type#bytes()}. */
ByteArray getBytes(int columnIndex);

Expand Down Expand Up @@ -228,6 +238,16 @@ default Value getValue(String columnName) {
/** Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.string())}. */
List<String> getStringList(String columnName);

/** Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.string())}. */
default List<String> getJsonList(int columnIndex) {
throw new UnsupportedOperationException("method should be overwritten");
};

/** Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.string())}. */
default List<String> getJsonList(String columnName) {
throw new UnsupportedOperationException("method should be overwritten");
};

/** Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.bytes())}. */
List<ByteArray> getBytesList(int columnIndex);

Expand Down