Pull up literals in InputAccessor (#16033)

* Pull up literals in InputAccessor

* pull up literals in `InputAccessor`
* remove the need to pass `constants` of `Window`  operator

Fixes #15353

* update test

* enable relax_nulls
This commit is contained in:
Zoltan Haindrich 2024-03-12 17:14:31 +01:00 committed by GitHub
parent ef9637eef1
commit 8252d72e2a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 82 additions and 34 deletions

View File

@ -1268,6 +1268,7 @@ public class HllSketchSqlAggregatorTest extends BaseCalciteQueryTest
);
}
/**
* This is a test in a similar vein to {@link #testEstimateStringAndDoubleAreDifferent()} except here we are
* ensuring that float values and doubles values are considered equivalent. The expected initial inputs were
@ -1318,6 +1319,27 @@ public class HllSketchSqlAggregatorTest extends BaseCalciteQueryTest
);
}
@Test
public void testDsHllOnTopOfNested()
{
// this query was not planable: https://github.com/apache/druid/issues/15353
testBuilder()
.sql(
"SELECT d1,dim2,APPROX_COUNT_DISTINCT_DS_HLL(dim2, 18) as val"
+ " FROM (select d1,dim1,dim2 from druid.foo group by d1,dim1,dim2 order by dim1 limit 3) t "
+ " group by 1,2"
)
.expectedResults(
ResultMatchMode.RELAX_NULLS,
ImmutableList.of(
new Object[] {null, "a", 1L},
new Object[] {"1.0", "a", 1L},
new Object[] {"1.7", null, 0L}
)
)
.run();
}
private ExpressionVirtualColumn makeSketchEstimateExpression(String outputName, String field)
{
return new ExpressionVirtualColumn(

View File

@ -591,10 +591,9 @@ public class DruidQuery
virtualColumnRegistry,
rexBuilder,
InputAccessor.buildFor(
rexBuilder,
rowSignature,
aggregate,
partialQuery.getSelectProject(),
null),
rowSignature),
aggregations,
aggName,
aggCall,

View File

@ -20,12 +20,17 @@
package org.apache.druid.sql.calcite.rel;
import com.google.common.collect.ImmutableList;
import org.apache.calcite.plan.RelOptPredicateList;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.Project;
import org.apache.calcite.rel.core.Window;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rex.RexBuilder;
import org.apache.calcite.rex.RexInputRef;
import org.apache.calcite.rex.RexLiteral;
import org.apache.calcite.rex.RexNode;
import org.apache.druid.segment.column.RowSignature;
import org.apache.druid.sql.calcite.expression.Expressions;
import org.apache.druid.sql.calcite.table.RowSignatures;
import javax.annotation.Nullable;
import java.util.List;
@ -38,43 +43,67 @@ import java.util.stream.Collectors;
*/
public class InputAccessor
{
private final Project project;
private final ImmutableList<RexLiteral> constants;
private final RexBuilder rexBuilder;
private final RelNode relNode;
@Nullable
private final Project flattenedProject;
private final RowSignature inputRowSignature;
@Nullable
private final ImmutableList<RexLiteral> constants;
private final RelNode inputRelNode;
private final RelDataType inputRelRowType;
private final RelOptPredicateList predicates;
private final int inputFieldCount;
private final RelDataType inputDruidRowType;
public static InputAccessor buildFor(
RexBuilder rexBuilder,
RowSignature inputRowSignature,
@Nullable Project project,
@Nullable ImmutableList<RexLiteral> constants)
RelNode relNode,
@Nullable Project flattenedProject,
RowSignature rowSignature)
{
return new InputAccessor(rexBuilder, inputRowSignature, project, constants);
return new InputAccessor(
relNode,
flattenedProject,
rowSignature
);
}
private InputAccessor(
RexBuilder rexBuilder,
RowSignature inputRowSignature,
Project project,
ImmutableList<RexLiteral> constants)
RelNode relNode,
Project flattenedProject,
RowSignature rowSignature)
{
this.rexBuilder = rexBuilder;
this.inputRowSignature = inputRowSignature;
this.project = project;
this.constants = constants;
this.inputFieldCount = project != null ? project.getRowType().getFieldCount() : inputRowSignature.size();
this.relNode = relNode;
this.constants = getConstants(relNode);
this.inputRelNode = relNode.getInput(0).stripped();
this.flattenedProject = flattenedProject;
this.inputRowSignature = rowSignature;
this.inputRelRowType = inputRelNode.getRowType();
this.predicates = relNode.getCluster().getMetadataQuery().getPulledUpPredicates(inputRelNode);
this.inputFieldCount = inputRelRowType.getFieldCount();
this.inputDruidRowType = RowSignatures.toRelDataType(inputRowSignature, getRexBuilder().getTypeFactory());
}
private ImmutableList<RexLiteral> getConstants(RelNode relNode)
{
if (relNode instanceof Window) {
return ((Window) relNode).constants;
}
return null;
}
public RexNode getField(int argIndex)
{
if (argIndex < inputFieldCount) {
return Expressions.fromFieldAccess(
rexBuilder.getTypeFactory(),
inputRowSignature,
project,
argIndex);
RexInputRef inputRef = RexInputRef.of(argIndex, inputRelRowType);
RexNode constant = predicates.constantMap.get(inputRef);
if (constant != null) {
return constant;
}
if (flattenedProject != null) {
return flattenedProject.getProjects().get(argIndex);
} else {
return RexInputRef.of(argIndex, inputDruidRowType);
}
} else {
return constants.get(argIndex - inputFieldCount);
}
@ -90,18 +119,17 @@ public class InputAccessor
public @Nullable Project getProject()
{
return project;
return flattenedProject;
}
public RexBuilder getRexBuilder()
{
return rexBuilder;
return relNode.getCluster().getRexBuilder();
}
public RowSignature getInputRowSignature()
{
return inputRowSignature;
}
}

View File

@ -180,10 +180,9 @@ public class Windowing
virtualColumnRegistry,
rexBuilder,
InputAccessor.buildFor(
rexBuilder,
sourceRowSignature,
window,
partialQuery.getSelectProject(),
window.constants),
sourceRowSignature),
Collections.emptyList(),
aggName,
aggregateCall,