Skip to content

Commit 0c3a695

Browse files
committed
Use consistent prepareStatement to resolve the issue
Signed-off-by: Songkan Tang <songkant@amazon.com>
1 parent e07ed44 commit 0c3a695

2 files changed

Lines changed: 31 additions & 110 deletions

File tree

core/src/main/java/org/opensearch/sql/calcite/utils/CalciteToolsHelper.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
import org.apache.calcite.plan.RelOptSchema;
6464
import org.apache.calcite.plan.RelOptTable;
6565
import org.apache.calcite.plan.RelOptTable.ViewExpander;
66+
import org.apache.calcite.plan.RelOptUtil;
6667
import org.apache.calcite.plan.hep.HepPlanner;
6768
import org.apache.calcite.plan.hep.HepProgram;
6869
import org.apache.calcite.plan.hep.HepProgramBuilder;
@@ -367,6 +368,36 @@ protected SqlToRelConverter getSqlToRelConverter(
367368
return new OpenSearchSqlToRelConverter(
368369
this, validator, catalogReader, this.cluster, convertletTable, config);
369370
}
371+
372+
@Override
373+
protected RelRoot trimUnusedFields(RelRoot root) {
374+
final SqlToRelConverter.Config config =
375+
SqlToRelConverter.config()
376+
.withTrimUnusedFields(shouldTrim(root.rel))
377+
.withExpand(THREAD_EXPAND.get())
378+
.withInSubQueryThreshold(requireNonNull(THREAD_INSUBQUERY_THRESHOLD.get()));
379+
// PPL analyzes into a pre-built RelNode before prepareStatement(rel). Reuse the incoming
380+
// RelNode's cluster here so prepare-time trimming does not create replacement nodes under a
381+
// different planner than the rest of the tree.
382+
final SqlToRelConverter converter =
383+
new OpenSearchSqlToRelConverter(
384+
this,
385+
getSqlValidator(),
386+
catalogReader,
387+
root.rel.getCluster(),
388+
convertletTable,
389+
config);
390+
final boolean ordered = !root.collation.getFieldCollations().isEmpty();
391+
final boolean dml = SqlKind.DML.contains(root.kind);
392+
return root.withRel(converter.trimUnusedFields(dml || ordered, root.rel));
393+
}
394+
395+
private static boolean shouldTrim(RelNode rootRel) {
396+
// For now, don't trim if there are more than 3 joins. The projects
397+
// near the leaves created by trim migrate past joins and seem to
398+
// prevent join-reordering.
399+
return THREAD_TRIM.get() || RelOptUtil.countJoins(rootRel) < 2;
400+
}
370401
}
371402

372403
public static class OpenSearchSqlToRelConverter extends SqlToRelConverter {

core/src/main/java/org/opensearch/sql/calcite/utils/OpenSearchRelFieldTrimmer.java

Lines changed: 0 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -5,31 +5,21 @@
55

66
package org.opensearch.sql.calcite.utils;
77

8-
import java.util.ArrayList;
98
import java.util.LinkedHashSet;
109
import java.util.List;
1110
import java.util.Set;
12-
import org.apache.calcite.linq4j.Ord;
1311
import org.apache.calcite.plan.RelOptUtil;
1412
import org.apache.calcite.rel.RelNode;
15-
import org.apache.calcite.rel.core.Aggregate;
16-
import org.apache.calcite.rel.core.CorrelationId;
17-
import org.apache.calcite.rel.core.Project;
18-
import org.apache.calcite.rel.core.Values;
1913
import org.apache.calcite.rel.type.RelDataType;
2014
import org.apache.calcite.rel.type.RelDataTypeField;
21-
import org.apache.calcite.rex.RexLiteral;
2215
import org.apache.calcite.rex.RexNode;
2316
import org.apache.calcite.rex.RexPermuteInputsShuttle;
24-
import org.apache.calcite.rex.RexSubQuery;
25-
import org.apache.calcite.rex.RexUtil;
2617
import org.apache.calcite.rex.RexVisitor;
2718
import org.apache.calcite.sql.validate.SqlValidator;
2819
import org.apache.calcite.sql2rel.RelFieldTrimmer;
2920
import org.apache.calcite.tools.RelBuilder;
3021
import org.apache.calcite.util.ImmutableBitSet;
3122
import org.apache.calcite.util.mapping.Mapping;
32-
import org.apache.calcite.util.mapping.MappingType;
3323
import org.apache.calcite.util.mapping.Mappings;
3424
import org.checkerframework.checker.nullness.qual.Nullable;
3525
import org.opensearch.sql.calcite.plan.rel.Dedup;
@@ -40,94 +30,9 @@
4030
* <p>This class extends Calcite's RelFieldTrimmer to support trimming customized operators.
4131
*/
4232
public class OpenSearchRelFieldTrimmer extends RelFieldTrimmer {
43-
private final RelBuilder openSearchRelBuilder;
4433

4534
public OpenSearchRelFieldTrimmer(@Nullable SqlValidator validator, RelBuilder relBuilder) {
4635
super(validator, relBuilder);
47-
this.openSearchRelBuilder = relBuilder;
48-
}
49-
50-
@Override
51-
public TrimResult trimFields(
52-
Project project, ImmutableBitSet fieldsUsed, Set<RelDataTypeField> extraFields) {
53-
final RelDataType rowType = project.getRowType();
54-
final int fieldCount = rowType.getFieldCount();
55-
final RelNode input = project.getInput();
56-
57-
final Set<RelDataTypeField> inputExtraFields = new LinkedHashSet<>(extraFields);
58-
RelOptUtil.InputFinder inputFinder = new RelOptUtil.InputFinder(inputExtraFields);
59-
for (Ord<RexNode> ord : Ord.zip(project.getProjects())) {
60-
if (fieldsUsed.get(ord.i)) {
61-
ord.e.accept(inputFinder);
62-
}
63-
}
64-
65-
List<RexSubQuery> subQueries = RexUtil.SubQueryCollector.collect(project);
66-
Set<CorrelationId> correlationIds = RelOptUtil.getVariablesUsed(subQueries);
67-
ImmutableBitSet requiredColumns = ImmutableBitSet.of();
68-
if (!correlationIds.isEmpty()) {
69-
assert correlationIds.size() == 1;
70-
requiredColumns = RelOptUtil.correlationColumns(correlationIds.iterator().next(), project);
71-
}
72-
73-
ImmutableBitSet finderFields = inputFinder.build();
74-
ImmutableBitSet inputFieldsUsed =
75-
ImmutableBitSet.builder().addAll(requiredColumns).addAll(finderFields).build();
76-
77-
TrimResult trimResult = trimChild(project, input, inputFieldsUsed, inputExtraFields);
78-
RelNode newInput = trimResult.left;
79-
final Mapping inputMapping = trimResult.right;
80-
81-
if (newInput == input && fieldsUsed.cardinality() == fieldCount) {
82-
return result(project, Mappings.createIdentity(fieldCount));
83-
}
84-
85-
if (fieldsUsed.cardinality() == 0) {
86-
return dummyProject(fieldCount, newInput, project);
87-
}
88-
89-
final List<RexNode> newProjects = new ArrayList<>();
90-
final RexVisitor<RexNode> shuttle;
91-
if (!correlationIds.isEmpty()) {
92-
assert correlationIds.size() == 1;
93-
shuttle =
94-
new RexPermuteInputsShuttle(inputMapping, newInput) {
95-
@Override
96-
public RexNode visitSubQuery(RexSubQuery subQuery) {
97-
subQuery = (RexSubQuery) super.visitSubQuery(subQuery);
98-
return RelOptUtil.remapCorrelatesInSuqQuery(
99-
openSearchRelBuilder.getRexBuilder(),
100-
subQuery,
101-
correlationIds.iterator().next(),
102-
newInput.getRowType(),
103-
inputMapping);
104-
}
105-
};
106-
} else {
107-
shuttle = new RexPermuteInputsShuttle(inputMapping, newInput);
108-
}
109-
110-
final Mapping mapping =
111-
Mappings.create(MappingType.INVERSE_SURJECTION, fieldCount, fieldsUsed.cardinality());
112-
for (Ord<RexNode> ord : Ord.zip(project.getProjects())) {
113-
if (fieldsUsed.get(ord.i)) {
114-
mapping.set(ord.i, newProjects.size());
115-
RexNode newProjectExpr = ord.e.accept(shuttle);
116-
newProjects.add(newProjectExpr);
117-
}
118-
}
119-
120-
final RelDataType newRowType =
121-
RelOptUtil.permute(project.getCluster().getTypeFactory(), rowType, mapping);
122-
123-
if (shouldAvoidSimplifyValues(newProjects, newInput)) {
124-
return result(
125-
project.copy(project.getTraitSet(), newInput, newProjects, newRowType), mapping, project);
126-
}
127-
128-
openSearchRelBuilder.push(newInput);
129-
openSearchRelBuilder.project(newProjects, newRowType.getFieldNames(), false, correlationIds);
130-
return result(openSearchRelBuilder.build(), mapping, project);
13136
}
13237

13338
public TrimResult trimFields(
@@ -162,19 +67,4 @@ public TrimResult trimFields(
16267
// needs them for its condition.
16368
return result(dedup.copy(newInput, newDedupFields), inputMapping);
16469
}
165-
166-
private boolean shouldAvoidSimplifyValues(List<RexNode> projects, RelNode input) {
167-
return projects.stream().allMatch(RexLiteral.class::isInstance) && isFixedRowCount(input);
168-
}
169-
170-
private boolean isFixedRowCount(RelNode input) {
171-
if (input instanceof Values) {
172-
return true;
173-
}
174-
if (input instanceof Aggregate aggregate) {
175-
return aggregate.getGroupSet().isEmpty()
176-
&& aggregate.getGroupType() == Aggregate.Group.SIMPLE;
177-
}
178-
return false;
179-
}
18070
}

0 commit comments

Comments
 (0)