fix nested field virtual column array column element vector object selector (#14729)

Fixes a case I missed in #14688 when the return type is STRING but its coming from a top level array typed column instead of a nested array column while making a vector object selector.

Also while here I noticed that the internal JSON_VALUE functions for array types were named inconsistently with the non-array functions, so I renamed them. These are not documented so it should not be disruptive in any way, since they are only used internally for rewrites while planning to make the correctly virtual column.

JSON_VALUE_RETURNING_ARRAY_VARCHAR -> JSON_VALUE_ARRAY_VARCHAR
JSON_VALUE_RETURNING_ARRAY_BIGINT -> JSON_VALUE_ARRAY_BIGINT
JSON_VALUE_RETURNING_ARRAY_DOUBLE -> JSON_VALUE_ARRAY_DOUBLE
The internal non-array functions are JSON_VALUE_VARCHAR, JSON_VALUE_BIGINT, and JSON_VALUE_DOUBLE.
This commit is contained in:
Clint Wylie 2023-08-02 04:38:24 -07:00 committed by GitHub
parent c1c2435aee
commit 94fb41a4df
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 64 additions and 5 deletions

View File

@ -535,7 +535,11 @@ public class NestedFieldVirtualColumn implements VirtualColumn
);
}
final VectorObjectSelector objectSelector = complexColumn.makeVectorObjectSelector(parts, offset);
if (leastRestrictiveType != null && leastRestrictiveType.isArray() && !expectedType.isArray()) {
if (leastRestrictiveType != null &&
leastRestrictiveType.isArray() &&
expectedType != null &&
!expectedType.isArray()
) {
final ExpressionType elementType = ExpressionType.fromColumnTypeStrict(leastRestrictiveType.getElementType());
final ExpressionType castTo = ExpressionType.fromColumnTypeStrict(expectedType);
return makeVectorArrayToScalarObjectSelector(offset, objectSelector, elementType, castTo);
@ -575,6 +579,12 @@ public class NestedFieldVirtualColumn implements VirtualColumn
if (parts.size() == 1 && parts.get(0) instanceof NestedPathArrayElement && column instanceof VariantColumn) {
final VariantColumn<?> arrayColumn = (VariantColumn<?>) column;
final ExpressionType elementType = ExpressionType.fromColumnTypeStrict(
arrayColumn.getLogicalType().isArray() ? arrayColumn.getLogicalType().getElementType() : arrayColumn.getLogicalType()
);
final ExpressionType castTo = expectedType == null
? ExpressionType.STRING
: ExpressionType.fromColumnTypeStrict(expectedType);
VectorObjectSelector arraySelector = arrayColumn.makeVectorObjectSelector(offset);
final int elementNumber = ((NestedPathArrayElement) parts.get(0)).getIndex();
if (elementNumber < 0) {
@ -595,7 +605,7 @@ public class NestedFieldVirtualColumn implements VirtualColumn
if (maybeArray instanceof Object[]) {
Object[] anArray = (Object[]) maybeArray;
if (elementNumber < anArray.length) {
elements[i] = anArray[elementNumber];
elements[i] = ExprEval.ofType(elementType, anArray[elementNumber]).castTo(castTo).value();
} else {
elements[i] = null;
}

View File

@ -287,6 +287,55 @@ public class NestedDataTimeseriesQueryTest extends InitializedNullHandlingTest
);
}
@Test
public void testFilterLongArrayElementFilters()
{
TimeseriesQuery query = Druids.newTimeseriesQueryBuilder()
.dataSource("test_datasource")
.intervals(Collections.singletonList(Intervals.ETERNITY))
.filters(
new AndDimFilter(
NullFilter.forColumn("v0"),
NullFilter.forColumn("v1"),
NullFilter.forColumn("v2")
)
)
.virtualColumns(
new NestedFieldVirtualColumn(
"arrayLongNulls",
"$[1]",
"v0",
ColumnType.STRING
),
new NestedFieldVirtualColumn(
"arrayLongNulls",
"$[1]",
"v1",
ColumnType.LONG
),
new NestedFieldVirtualColumn(
"arrayStringNulls",
"$[1]",
"v2",
ColumnType.LONG
)
)
.aggregators(new CountAggregatorFactory("count"))
.context(getContext())
.build();
runResults(
query,
ImmutableList.of(
new Result<>(
DateTimes.of("2023-01-01T00:00:00.000Z"),
new TimeseriesResultValue(
ImmutableMap.of("count", 8L)
)
)
)
);
}
@Test
public void testFilterVariantAsString()
{

View File

@ -557,7 +557,7 @@ public class NestedDataOperatorConversions
public static class JsonValueReturningArrayBigIntOperatorConversion extends JsonValueReturningArrayTypeOperatorConversion
{
static final SqlFunction FUNCTION = buildArrayFunction("JSON_VALUE_RETURNING_ARRAY_BIGINT", SqlTypeName.BIGINT);
static final SqlFunction FUNCTION = buildArrayFunction("JSON_VALUE_ARRAY_BIGINT", SqlTypeName.BIGINT);
public JsonValueReturningArrayBigIntOperatorConversion()
{
@ -567,7 +567,7 @@ public class NestedDataOperatorConversions
public static class JsonValueReturningArrayDoubleOperatorConversion extends JsonValueReturningArrayTypeOperatorConversion
{
static final SqlFunction FUNCTION = buildArrayFunction("JSON_VALUE_RETURNING_ARRAY_DOUBLE", SqlTypeName.DOUBLE);
static final SqlFunction FUNCTION = buildArrayFunction("JSON_VALUE_ARRAY_DOUBLE", SqlTypeName.DOUBLE);
public JsonValueReturningArrayDoubleOperatorConversion()
{
@ -577,7 +577,7 @@ public class NestedDataOperatorConversions
public static class JsonValueReturningArrayVarcharOperatorConversion extends JsonValueReturningArrayTypeOperatorConversion
{
static final SqlFunction FUNCTION = buildArrayFunction("JSON_VALUE_RETURNING_ARRAY_VARCHAR", SqlTypeName.VARCHAR);
static final SqlFunction FUNCTION = buildArrayFunction("JSON_VALUE_ARRAY_VARCHAR", SqlTypeName.VARCHAR);
public JsonValueReturningArrayVarcharOperatorConversion()
{