Allow typedIn to run in replace-with-default mode. (#16233)

* Allow typedIn to run in replace-with-default mode.

Useful when data servers, like Historicals, are running in replace-with-default
mode and the Broker is running in SQL-compatible mode, which can happen during
a rolling update that is applying a mode change.
This commit is contained in:
Gian Merlino 2024-04-04 15:45:42 -07:00 committed by GitHub
parent 64433eb2ff
commit a319b44545
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 31 additions and 34 deletions

View File

@ -223,7 +223,9 @@ public class TypedInFilter extends AbstractOptimizableDimFilter implements Filte
@Override @Override
public DimFilter optimize(final boolean mayIncludeUnknown) public DimFilter optimize(final boolean mayIncludeUnknown)
{ {
checkSqlCompatible(); if (NullHandling.replaceWithDefault()) {
return convertToLegacy().optimize(mayIncludeUnknown);
}
final List<?> matchValues = this.sortedMatchValues.get(); final List<?> matchValues = this.sortedMatchValues.get();
if (matchValues.isEmpty()) { if (matchValues.isEmpty()) {
return FalseDimFilter.instance(); return FalseDimFilter.instance();
@ -244,7 +246,9 @@ public class TypedInFilter extends AbstractOptimizableDimFilter implements Filte
@Override @Override
public Filter toFilter() public Filter toFilter()
{ {
checkSqlCompatible(); if (NullHandling.replaceWithDefault()) {
return convertToLegacy().toFilter();
}
return this; return this;
} }
@ -417,13 +421,14 @@ public class TypedInFilter extends AbstractOptimizableDimFilter implements Filte
.build(); .build();
} }
private void checkSqlCompatible() private InDimFilter convertToLegacy()
{ {
if (NullHandling.replaceWithDefault()) { return new InDimFilter(
throw InvalidInput.exception( column,
"Invalid IN filter, typed in filter only supports SQL compatible null handling mode, set druid.generic.useDefaultValue=false to use this filter" InDimFilter.ValuesSet.copyOf(sortedMatchValues.get().stream().map(Evals::asString).iterator()),
); null,
} filterTuning
);
} }
private static boolean checkSorted(List<?> unsortedValues, ColumnType matchValueType) private static boolean checkSorted(List<?> unsortedValues, ColumnType matchValueType)

View File

@ -627,25 +627,16 @@ public class InFilterTests
private void assertTypedFilterMatches(DimFilter filter, List<String> expectedRows) private void assertTypedFilterMatches(DimFilter filter, List<String> expectedRows)
{ {
// this filter only tests in sql compatible mode super.assertFilterMatches(filter, expectedRows);
if (NullHandling.sqlCompatible()) { try {
super.assertFilterMatches(filter, expectedRows); // make sure round trip json serde is cool
try { super.assertFilterMatches(
// make sure round trip json serde is cool jsonMapper.readValue(jsonMapper.writeValueAsString(filter), DimFilter.class),
super.assertFilterMatches( expectedRows
jsonMapper.readValue(jsonMapper.writeValueAsString(filter), DimFilter.class),
expectedRows
);
}
catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
} else {
Throwable t = Assert.assertThrows(
DruidException.class,
() -> super.assertFilterMatches(filter, expectedRows)
); );
Assert.assertEquals("Invalid IN filter, typed in filter only supports SQL compatible null handling mode, set druid.generic.useDefaultValue=false to use this filter", t.getMessage()); }
catch (JsonProcessingException e) {
throw new RuntimeException(e);
} }
} }
@ -718,6 +709,15 @@ public class InFilterTests
Assert.assertEquals(filter, mapper.readValue(s, TypedInFilter.class)); Assert.assertEquals(filter, mapper.readValue(s, TypedInFilter.class));
} }
@Test
public void testConvertToLegacy()
{
Assume.assumeTrue(NullHandling.replaceWithDefault());
TypedInFilter aFilter = new TypedInFilter("column", ColumnType.STRING, Arrays.asList("a", "b", "c"), null, null);
Assert.assertTrue(aFilter.optimize(false) instanceof InDimFilter);
Assert.assertTrue(aFilter.toFilter() instanceof InDimFilter);
}
@Test @Test
public void testGetCacheKey() public void testGetCacheKey()
{ {
@ -786,14 +786,6 @@ public class InFilterTests
@Test @Test
public void testInvalidParameters() public void testInvalidParameters()
{ {
if (NullHandling.replaceWithDefault()) {
Throwable t = Assert.assertThrows(
DruidException.class,
() -> new TypedInFilter("column", ColumnType.STRING, Collections.emptyList(), null, null).toFilter()
);
Assert.assertEquals("Invalid IN filter, typed in filter only supports SQL compatible null handling mode, set druid.generic.useDefaultValue=false to use this filter", t.getMessage());
}
Assume.assumeTrue(NullHandling.sqlCompatible()); Assume.assumeTrue(NullHandling.sqlCompatible());
Throwable t = Assert.assertThrows( Throwable t = Assert.assertThrows(
DruidException.class, DruidException.class,