Skip to content

Commit 60c1ef8

Browse files
committed
fix: with in scalar subquery
1 parent afb11c8 commit 60c1ef8

File tree

9 files changed

+69
-23
lines changed

9 files changed

+69
-23
lines changed

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/Analysis.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Table;
7070
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.TableFunctionInvocation;
7171
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.WindowFrame;
72+
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.With;
7273
import org.apache.iotdb.db.queryengine.plan.statement.component.FillPolicy;
7374

7475
import com.google.common.collect.ArrayListMultimap;
@@ -123,6 +124,8 @@ public class Analysis implements IAnalysis {
123124

124125
private final Map<NodeRef<Table>, Query> namedQueries = new LinkedHashMap<>();
125126

127+
private With with;
128+
126129
// map expandable query to the node being the inner recursive reference
127130
private final Map<NodeRef<Query>, Node> expandableNamedQueries = new LinkedHashMap<>();
128131

@@ -282,6 +285,14 @@ public Map<NodeRef<Table>, Query> getNamedQueries() {
282285
return namedQueries;
283286
}
284287

288+
public With getWith() {
289+
return with;
290+
}
291+
292+
public void setWith(With with) {
293+
this.with = with;
294+
}
295+
285296
public boolean isAnalyzed(Expression expression) {
286297
return expression instanceof DataType || types.containsKey(NodeRef.of(expression));
287298
}

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/ExpressionAnalyzer.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1717,12 +1717,12 @@ private Type analyzePredicateWithSubquery(
17171717
return subqueryType;
17181718
}
17191719

1720-
private Type analyzeSubquery(
1721-
SubqueryExpression node, StackableAstVisitorContext<Context> context) {
1720+
private Type analyzeSubquery(SubqueryExpression node, StackableAstVisitorContext<Context> ctx) {
17221721
StatementAnalyzer analyzer =
1723-
statementAnalyzerFactory.apply(node, context.getContext().getCorrelationSupport());
1724-
Scope subqueryScope = Scope.builder().withParent(context.getContext().getScope()).build();
1722+
statementAnalyzerFactory.apply(node, ctx.getContext().getCorrelationSupport());
1723+
Scope subqueryScope = Scope.builder().withParent(ctx.getContext().getScope()).build();
17251724
Scope queryScope = analyzer.analyze(node.getQuery(), subqueryScope);
1725+
context.getSubQueryTables().put(node.getQuery(), queryScope.getTables());
17261726

17271727
ImmutableList.Builder<RowType.Field> fields = ImmutableList.builder();
17281728
for (int i = 0; i < queryScope.getRelationType().getAllFieldCount(); i++) {

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -920,6 +920,7 @@ private Scope analyzeWith(Query node, Optional<Scope> scope) {
920920

921921
// analyze WITH clause
922922
With with = node.getWith().get();
923+
analysis.setWith(with);
923924
Scope.Builder withScopeBuilder = scopeBuilder(scope);
924925

925926
for (WithQuery withQuery : with.getQueries()) {
@@ -4455,11 +4456,10 @@ private Scope createAndAssignScope(Node node, Optional<Scope> parentScope, List<
44554456

44564457
private Scope createAndAssignScope(
44574458
Node node, Optional<Scope> parentScope, RelationType relationType) {
4458-
Scope scope =
4459-
scopeBuilder(parentScope)
4460-
.withRelationType(RelationId.of(node), relationType)
4461-
.withTables(parentScope.get().getTables())
4462-
.build();
4459+
Scope.Builder scopeBuilder =
4460+
scopeBuilder(parentScope).withRelationType(RelationId.of(node), relationType);
4461+
parentScope.ifPresent(scope -> scopeBuilder.withTables(scope.getTables()));
4462+
Scope scope = scopeBuilder.build();
44634463

44644464
analysis.setScope(node, scope);
44654465
return scope;

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/CteMaterializer.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,15 +74,15 @@ public class CteMaterializer {
7474

7575
private static final Coordinator coordinator = Coordinator.getInstance();
7676

77-
public void materializeCTE(MPPQueryContext context, Analysis analysis, Query mainQuery) {
77+
public void materializeCTE(Analysis analysis, MPPQueryContext context) {
7878
analysis
7979
.getNamedQueries()
8080
.forEach(
8181
(tableRef, query) -> {
8282
Table table = tableRef.getNode();
8383
if (query.isMaterialized() && !query.isDone()) {
8484
CteDataStore dataStore =
85-
fetchCteQueryResult(context, table, query, mainQuery.getWith().orElse(null));
85+
fetchCteQueryResult(context, table, query, analysis.getWith());
8686
if (dataStore == null) {
8787
// CTE query execution failed. Use inline instead of materialization
8888
// in the outer query

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/SubqueryPlanner.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ public PlanBuilder handleSubqueries(
158158
private void tryFoldUncorrelatedScalarSubqueryInPredicate(
159159
Expression expression, MPPQueryContext context) {
160160
PredicateWithUncorrelatedScalarSubqueryReconstructor.getInstance()
161-
.reconstructPredicateWithUncorrelatedScalarSubquery(expression, context);
161+
.reconstructPredicateWithUncorrelatedScalarSubquery(context, analysis, expression);
162162
}
163163

164164
/**

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/TableLogicalPlanner.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@ private RelationPlan createRelationPlan(Analysis analysis, PipeEnriched pipeEnri
374374
private RelationPlan createRelationPlan(Analysis analysis, Query query) {
375375
// materialize cte if needed
376376
if (!queryContext.isSubquery()) {
377-
CteMaterializer.getInstance().materializeCTE(queryContext, analysis, query);
377+
CteMaterializer.getInstance().materializeCTE(analysis, queryContext);
378378
}
379379
return getRelationPlanner(analysis).process(query, null);
380380
}

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/PredicateWithUncorrelatedScalarSubqueryReconstructor.java

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.apache.iotdb.db.queryengine.plan.Coordinator;
2929
import org.apache.iotdb.db.queryengine.plan.execution.ExecutionResult;
3030
import org.apache.iotdb.db.queryengine.plan.planner.LocalExecutionPlanner;
31+
import org.apache.iotdb.db.queryengine.plan.relational.analyzer.Analysis;
3132
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.BinaryLiteral;
3233
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.BooleanLiteral;
3334
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ComparisonExpression;
@@ -38,17 +39,22 @@
3839
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.LogicalExpression;
3940
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.LongLiteral;
4041
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.NotExpression;
42+
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Query;
4143
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.StringLiteral;
4244
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.SubqueryExpression;
45+
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.With;
46+
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.WithQuery;
4347
import org.apache.iotdb.db.queryengine.plan.relational.sql.parser.SqlParser;
4448
import org.apache.iotdb.rpc.TSStatusCode;
4549

50+
import com.google.common.collect.ImmutableList;
4651
import org.apache.tsfile.block.column.Column;
4752
import org.apache.tsfile.enums.TSDataType;
4853
import org.apache.tsfile.read.common.block.TsBlock;
4954

5055
import java.util.List;
5156
import java.util.Optional;
57+
import java.util.stream.Collectors;
5258

5359
import static com.google.common.base.Preconditions.checkArgument;
5460

@@ -59,29 +65,32 @@ public class PredicateWithUncorrelatedScalarSubqueryReconstructor {
5965
private static final Coordinator coordinator = Coordinator.getInstance();
6066

6167
public void reconstructPredicateWithUncorrelatedScalarSubquery(
62-
Expression expression, MPPQueryContext context) {
68+
MPPQueryContext context, Analysis analysis, Expression expression) {
6369
if (expression instanceof LogicalExpression) {
6470
LogicalExpression logicalExpression = (LogicalExpression) expression;
6571
for (Expression term : logicalExpression.getTerms()) {
66-
reconstructPredicateWithUncorrelatedScalarSubquery(term, context);
72+
reconstructPredicateWithUncorrelatedScalarSubquery(context, analysis, term);
6773
}
6874
} else if (expression instanceof NotExpression) {
6975
NotExpression notExpression = (NotExpression) expression;
70-
reconstructPredicateWithUncorrelatedScalarSubquery(notExpression.getValue(), context);
76+
reconstructPredicateWithUncorrelatedScalarSubquery(
77+
context, analysis, notExpression.getValue());
7178
} else if (expression instanceof ComparisonExpression) {
7279
ComparisonExpression comparisonExpression = (ComparisonExpression) expression;
7380
Expression left = comparisonExpression.getLeft();
7481
Expression right = comparisonExpression.getRight();
7582
if (left instanceof Identifier && right instanceof SubqueryExpression) {
7683
Optional<Literal> result =
77-
fetchUncorrelatedSubqueryResultForPredicate((SubqueryExpression) right, context);
84+
fetchUncorrelatedSubqueryResultForPredicate(
85+
context, (SubqueryExpression) right, analysis.getWith());
7886
// If the subquery result is not present, we cannot reconstruct the predicate.
7987
if (result.isPresent()) {
8088
right = result.get();
8189
}
8290
} else if (right instanceof Identifier && left instanceof SubqueryExpression) {
8391
Optional<Literal> result =
84-
fetchUncorrelatedSubqueryResultForPredicate((SubqueryExpression) left, context);
92+
fetchUncorrelatedSubqueryResultForPredicate(
93+
context, (SubqueryExpression) left, analysis.getWith());
8594
if (result.isPresent()) {
8695
left = result.get();
8796
}
@@ -97,14 +106,40 @@ public void reconstructPredicateWithUncorrelatedScalarSubquery(
97106
* valid result.
98107
*/
99108
public Optional<Literal> fetchUncorrelatedSubqueryResultForPredicate(
100-
SubqueryExpression subqueryExpression, MPPQueryContext context) {
109+
MPPQueryContext context, SubqueryExpression subqueryExpression, With with) {
101110
final long queryId = SessionManager.getInstance().requestQueryId();
102111
Throwable t = null;
103112

104113
try {
114+
Query query = subqueryExpression.getQuery();
115+
Query q = query;
116+
if (with != null) {
117+
List<Identifier> tables =
118+
context.getSubQueryTables().getOrDefault(query, ImmutableList.of());
119+
List<WithQuery> withQueries =
120+
with.getQueries().stream()
121+
.filter(
122+
x ->
123+
tables.contains(x.getName())
124+
&& !x.getQuery().isMaterialized()
125+
&& !x.getQuery().isDone())
126+
.collect(Collectors.toList());
127+
128+
if (!withQueries.isEmpty()) {
129+
With w = new With(with.getLocation().orElse(null), with.isRecursive(), withQueries);
130+
q =
131+
new Query(
132+
Optional.of(w),
133+
query.getQueryBody(),
134+
query.getFill(),
135+
query.getOrderBy(),
136+
query.getOffset(),
137+
query.getLimit());
138+
}
139+
}
105140
final ExecutionResult executionResult =
106141
coordinator.executeForTableModel(
107-
subqueryExpression.getQuery(),
142+
q,
108143
relationSqlParser,
109144
SessionManager.getInstance().getCurrSession(),
110145
queryId,

iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/planner/CteMaterializerTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,8 @@ private void mockSubquery() {
105105

106106
Mockito.doAnswer(
107107
(InvocationOnMock invocation) -> {
108-
Table table = invocation.getArgument(0);
109-
Query query = invocation.getArgument(1);
108+
Table table = invocation.getArgument(1);
109+
Query query = invocation.getArgument(2);
110110
List<SelectItem> selectItems =
111111
((QuerySpecification) query.getQueryBody()).getSelect().getSelectItems();
112112
List<ColumnSchema> columnsSchemas =

iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/planner/UncorrelatedSubqueryTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ private void mockPredicateWithUncorrelatedScalarSubquery() {
7575
Mockito.spy(new PredicateWithUncorrelatedScalarSubqueryReconstructor());
7676
Mockito.when(
7777
predicateWithUncorrelatedScalarSubquery.fetchUncorrelatedSubqueryResultForPredicate(
78-
Mockito.any(), Mockito.any()))
78+
Mockito.any(), Mockito.any(), Mockito.any()))
7979
.thenReturn(Optional.of(new LongLiteral("1")));
8080
PredicateWithUncorrelatedScalarSubqueryReconstructor.setInstance(
8181
predicateWithUncorrelatedScalarSubquery);

0 commit comments

Comments
 (0)