ArrayOfDoublesSketchBuildAggregator: Fix NPE in get() for empty sketch. (#16330)

Fixes a bug introduced in #16296, where the sketch might not be
initialized if get() is called without calling aggregate(). Also adds
a test for this case.
This commit is contained in:
Gian Merlino 2024-04-24 21:59:59 -07:00 committed by GitHub
parent e74da6a6b6
commit 8a5cc976a9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 47 additions and 5 deletions

View File

@ -84,11 +84,6 @@ public class ArrayOfDoublesSketchBuildAggregator implements Aggregator
values = new double[valueSelectors.length];
}
if (sketch == null) {
sketch = new ArrayOfDoublesUpdatableSketchBuilder().setNominalEntries(nominalEntries)
.setNumberOfValues(valueSelectors.length).build();
}
final IndexedInts keys = keySelector.getRow();
for (int i = 0; i < valueSelectors.length; i++) {
if (valueSelectors[i].isNull()) {
@ -113,6 +108,7 @@ public class ArrayOfDoublesSketchBuildAggregator implements Aggregator
key.get(bytes);
key.reset();
initializeSketchIfNeeded();
sketch.update(bytes, values);
}
}
@ -125,6 +121,7 @@ public class ArrayOfDoublesSketchBuildAggregator implements Aggregator
key = keySelector.lookupName(keys.get(i));
}
initializeSketchIfNeeded();
sketch.update(key, values);
}
}
@ -142,6 +139,7 @@ public class ArrayOfDoublesSketchBuildAggregator implements Aggregator
@Override
public synchronized Object get()
{
initializeSketchIfNeeded();
return sketch.compact();
}
@ -164,4 +162,14 @@ public class ArrayOfDoublesSketchBuildAggregator implements Aggregator
values = null;
}
/**
* Initialize {@link #sketch} if it is null.
*/
private void initializeSketchIfNeeded()
{
if (sketch == null) {
sketch = new ArrayOfDoublesUpdatableSketchBuilder().setNominalEntries(nominalEntries)
.setNumberOfValues(valueSelectors.length).build();
}
}
}

View File

@ -427,6 +427,40 @@ public class ArrayOfDoublesSketchSqlAggregatorTest extends BaseCalciteQueryTest
);
}
@Test
public void testNoInputGroupByAll()
{
cannotVectorize();
final String sql = "SELECT\n"
+ " DS_TUPLE_DOUBLES(tuplesketch_dim2),\n"
+ " DS_TUPLE_DOUBLES(dim2, m1)\n"
+ "FROM druid.foo\n"
+ "WHERE dim2 = 'nonexistent'\n"
+ "GROUP BY ()";
testQuery(
sql,
ImmutableList.of(
Druids.newTimeseriesQueryBuilder()
.dataSource(CalciteTests.DATASOURCE1)
.intervals(querySegmentSpec(Filtration.eternity()))
.virtualColumns(expressionVirtualColumn("v0", "'nonexistent'", ColumnType.STRING))
.filters(equality("dim2", "nonexistent", ColumnType.STRING))
.granularity(Granularities.ALL)
.aggregators(
new ArrayOfDoublesSketchAggregatorFactory("a0", "tuplesketch_dim2", null, null, 1),
new ArrayOfDoublesSketchAggregatorFactory("a1", "v0", null, ImmutableList.of("m1"), 1)
)
.context(QUERY_CONTEXT_DEFAULT)
.build()
),
ImmutableList.of(
new Object[]{"0.0", "0.0"}
)
);
}
@Test
public void testArrayOfDoublesSketchIntersectOnScalarExpression()
{