Skip to content

refactor: Removing duplicated code to handle array values #2143

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

Merged
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import javax.annotation.Nullable;

/** Implementation of {@link ResultSet}. */
Expand Down Expand Up @@ -547,88 +546,24 @@ private static Struct decodeStructValue(Type structType, ListValue structValue)

static Object decodeArrayValue(Type elementType, ListValue listValue) {
switch (elementType.getCode()) {
case BOOL:
// Use a view: element conversion is virtually free.
return Lists.transform(
listValue.getValuesList(),
input -> input.getKindCase() == KindCase.NULL_VALUE ? null : input.getBoolValue());
case INT64:
// For int64/float64 types, use custom containers. These avoid wrapper object
// creation for non-null arrays.
return new Int64Array(listValue);
case FLOAT64:
return new Float64Array(listValue);
case BOOL:
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 PG_NUMERIC:
case STRING:
case JSON:
case PG_JSONB:
return listValue.getValuesList().stream()
.map(
input ->
input.getKindCase() == KindCase.NULL_VALUE ? null : input.getStringValue())
.collect(Collectors.toList());
case BYTES:
{
// 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
: ByteArray.fromBase64(value.getStringValue()));
}
return list;
}
case TIMESTAMP:
{
// 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
: Timestamp.parseTimestamp(value.getStringValue()));
}
return list;
}
case DATE:
{
// 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
: Date.parseDate(value.getStringValue()));
}
return list;
}

case STRUCT:
{
ArrayList<Struct> list = new ArrayList<>(listValue.getValuesCount());
for (com.google.protobuf.Value value : listValue.getValuesList()) {
if (value.getKindCase() == KindCase.NULL_VALUE) {
list.add(null);
} else {
ListValue structValue = value.getListValue();
list.add(decodeStructValue(elementType, structValue));
}
}
return list;
}
return Lists.transform(
listValue.getValuesList(), input -> decodeValue(elementType, input));
default:
throw new AssertionError("Unhandled type code: " + elementType.getCode());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,10 +178,18 @@ default Value getValue(String columnName) {
*/
boolean[] getBooleanArray(String columnName);

/** Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.bool())}. */
/**
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.bool())}. The
* list returned by this method is lazily constructed. Create a copy of it if you intend to access
* each element in the list multiple times.
*/
List<Boolean> getBooleanList(int columnIndex);

/** Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.bool())}. */
/**
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.bool())}. The
* list returned by this method is lazily constructed. Create a copy of it if you intend to access
* each element in the list multiple times.
*/
List<Boolean> getBooleanList(String columnName);

/**
Expand All @@ -200,10 +208,18 @@ default Value getValue(String columnName) {
*/
long[] getLongArray(String columnName);

/** Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.int64())}. */
/**
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.int64())}. The
* list returned by this method is lazily constructed. Create a copy of it if you intend to access
* each element in the list multiple times.
*/
List<Long> getLongList(int columnIndex);

/** Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.int64())}. */
/**
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.int64())}. The
* list returned by this method is lazily constructed. Create a copy of it if you intend to access
* each element in the list multiple times.
*/
List<Long> getLongList(String columnName);

/**
Expand All @@ -223,84 +239,136 @@ default Value getValue(String columnName) {
double[] getDoubleArray(String columnName);

/**
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.float64())}.
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.float64())} The
* list returned by this method is lazily constructed. Create a copy of it if you intend to access
* each element in the list multiple times.
*/
List<Double> getDoubleList(int columnIndex);

/**
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.float64())}.
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.float64())} The
* list returned by this method is lazily constructed. Create a copy of it if you intend to access
* each element in the list multiple times.
*/
List<Double> getDoubleList(String columnName);

/**
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.numeric())}.
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.numeric())} The
* list returned by this method is lazily constructed. Create a copy of it if you intend to access
* each element in the list multiple times.
*/
List<BigDecimal> getBigDecimalList(int columnIndex);

/**
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.numeric())}.
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.numeric())} The
* list returned by this method is lazily constructed. Create a copy of it if you intend to access
* each element in the list multiple times.
*/
List<BigDecimal> getBigDecimalList(String columnName);

/** Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.string())}. */
/**
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.string())}. The
* list returned by this method is lazily constructed. Create a copy of it if you intend to access
* each element in the list multiple times.
*/
List<String> getStringList(int columnIndex);

/** Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.string())}. */
/**
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.string())}. The
* list returned by this method is lazily constructed. Create a copy of it if you intend to access
* each element in the list multiple times.
*/
List<String> getStringList(String columnName);

/** Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.json())}. */
/**
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.json())}. The
* list returned by this method is lazily constructed. Create a copy of it if you intend to access
* each element in the list multiple times.
*/
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.json())}. */
/**
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.json())}. The
* list returned by this method is lazily constructed. Create a copy of it if you intend to access
* each element in the list multiple times.
*/
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.pgJsonb())}.
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.pgJsonb())} The
* list returned by this method is lazily constructed. Create a copy of it if you intend to access
* each element in the list multiple times.
*/
default List<String> getPgJsonbList(int columnIndex) {
throw new UnsupportedOperationException("method should be overwritten");
};

/**
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.pgJsonb())}.
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.pgJsonb())} The
* list returned by this method is lazily constructed. Create a copy of it if you intend to access
* each element in the list multiple times.
*/
default List<String> getPgJsonbList(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())}. */
/**
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.bytes())}. The
* list returned by this method is lazily constructed. Create a copy of it if you intend to access
* each element in the list multiple times.
*/
List<ByteArray> getBytesList(int columnIndex);

/** Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.bytes())}. */
/**
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.bytes())}. The
* list returned by this method is lazily constructed. Create a copy of it if you intend to access
* each element in the list multiple times.
*/
List<ByteArray> getBytesList(String columnName);

/**
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.timestamp())}.
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.timestamp())}
* The list returned by this method is lazily constructed. Create a copy of it if you intend to
* access each element in the list multiple times.
*/
List<Timestamp> getTimestampList(int columnIndex);

/**
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.timestamp())}.
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.timestamp())}
* The list returned by this method is lazily constructed. Create a copy of it if you intend to
* access each element in the list multiple times.
*/
List<Timestamp> getTimestampList(String columnName);

/** Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.date())}. */
/**
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.date())}. The
* list returned by this method is lazily constructed. Create a copy of it if you intend to access
* each element in the list multiple times.
*/
List<Date> getDateList(int columnIndex);

/** Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.date())}. */
/**
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.date())}. The
* list returned by this method is lazily constructed. Create a copy of it if you intend to access
* each element in the list multiple times.
*/
List<Date> getDateList(String columnName);

/**
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.struct(...))}.
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.struct(...))}
* The list returned by this method is lazily constructed. Create a copy of it if you intend to
* access each element in the list multiple times.
*/
List<Struct> getStructList(int columnIndex);

/**
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.struct(...))}.
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.struct(...))}
* The list returned by this method is lazily constructed. Create a copy of it if you intend to
* access each element in the list multiple times.
*/
List<Struct> getStructList(String columnName);
}