This is an automated email from the ASF dual-hosted git repository.
yiguolei pushed a commit to branch branch-2.1
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/branch-2.1 by this push:
new 9997911ec93 [feat](Nereids) support nereids hint position detaction
(#39113) (#39417)
9997911ec93 is described below
commit 9997911ec9302e96432e4980e22c7460134eea9e
Author: LiBinfeng <[email protected]>
AuthorDate: Sat Aug 24 23:59:54 2024 +0800
[feat](Nereids) support nereids hint position detaction (#39113) (#39417)
cherry-pick: #39113
When use hint in wrong position or use unsupport hint, use channel(2) to
filter it out
## Proposed changes
Issue Number: close #xxx
<!--Describe your changes.-->
---
.../antlr4/org/apache/doris/nereids/DorisLexer.g4 | 20 +----
.../antlr4/org/apache/doris/nereids/DorisParser.g4 | 5 +-
.../doris/nereids/parser/LogicalPlanBuilder.java | 90 +++++++++++++---------
.../parser/LogicalPlanBuilderForCreateView.java | 5 ++
.../apache/doris/nereids/parser/NereidsParser.java | 30 +++++++-
.../parser/plsql/PLSqlLogicalPlanBuilder.java | 4 +
.../doris/nereids/parser/NereidsParserTest.java | 8 --
regression-test/data/nereids_p0/hint/test_hint.out | 81 +++++++++++++++++++
.../data/nereids_p0/hint/test_leading.out | 4 +-
.../suites/nereids_p0/hint/test_hint.groovy | 60 +++++++++++++++
.../suites/nereids_p0/hint/test_leading.groovy | 2 +-
11 files changed, 242 insertions(+), 67 deletions(-)
diff --git a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisLexer.g4
b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisLexer.g4
index 72542ba0874..3ed51ca8fbf 100644
--- a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisLexer.g4
+++ b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisLexer.g4
@@ -47,22 +47,6 @@ lexer grammar DorisLexer;
}
}
- /**
- * This method will be called when we see '/*' and try to match it as a
bracketed comment.
- * If the next character is '+', it should be parsed as hint later, and we
cannot match
- * it as a bracketed comment.
- *
- * Returns true if the next character is '+'.
- */
- public boolean isHint() {
- int nextChar = _input.LA(1);
- if (nextChar == '+') {
- return true;
- } else {
- return false;
- }
- }
-
/**
* This method will be called when the character stream ends and try to find
out the
* unclosed bracketed comment.
@@ -599,6 +583,7 @@ COLON: ':';
ARROW: '->';
HINT_START: '/*+';
HINT_END: '*/';
+COMMENT_START: '/*';
ATSIGN: '@';
DOUBLEATSIGN: '@@';
@@ -678,9 +663,10 @@ SIMPLE_COMMENT
;
BRACKETED_COMMENT
- : '/*' {!isHint()}? ( BRACKETED_COMMENT | . )*? ('*/' |
{markUnclosedComment();} EOF) -> channel(HIDDEN)
+ : COMMENT_START ( BRACKETED_COMMENT | . )*? ('*/' |
{markUnclosedComment();} EOF) -> channel(2)
;
+
FROM_DUAL
: 'FROM' WS+ 'DUAL' -> channel(HIDDEN);
diff --git a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4
b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4
index 33d04fb8550..d94a0f4f680 100644
--- a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4
+++ b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4
@@ -457,7 +457,7 @@ havingClause
: HAVING booleanExpression
;
-selectHint: HINT_START hintStatements+=hintStatement (COMMA?
hintStatements+=hintStatement)* HINT_END;
+selectHint: hintStatements+=hintStatement (COMMA?
hintStatements+=hintStatement)* HINT_END;
hintStatement
: hintName=identifier (LEFT_PAREN parameters+=hintAssignment (COMMA?
parameters+=hintAssignment)* RIGHT_PAREN)?
@@ -1065,6 +1065,7 @@ nonReserved
| COLOCATE
| COLUMNS
| COMMENT
+ | COMMENT_START
| COMMIT
| COMMITTED
| COMPACT
@@ -1147,6 +1148,8 @@ nonReserved
| HASH
| HDFS
| HELP
+ | HINT_END
+ | HINT_START
| HISTOGRAM
| HLL_UNION
| HOSTNAME
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java
index ad2aa783307..c4403a98bd0 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java
@@ -499,6 +499,12 @@ public class LogicalPlanBuilder extends
DorisParserBaseVisitor<Object> {
return pos1.getCharPositionInLine() - pos2.getCharPositionInLine();
});
+ private final Map<Integer, ParserRuleContext> selectHintMap;
+
+ public LogicalPlanBuilder(Map<Integer, ParserRuleContext> selectHintMap) {
+ this.selectHintMap = selectHintMap;
+ }
+
@SuppressWarnings("unchecked")
protected <T> T typedVisit(ParseTree ctx) {
return (T) ctx.accept(this);
@@ -1331,7 +1337,16 @@ public class LogicalPlanBuilder extends
DorisParserBaseVisitor<Object> {
Optional.ofNullable(ctx.aggClause()),
Optional.ofNullable(ctx.havingClause()));
selectPlan = withQueryOrganization(selectPlan,
ctx.queryOrganization());
- return withSelectHint(selectPlan, selectCtx.selectHint());
+ if ((selectHintMap == null) || selectHintMap.isEmpty()) {
+ return selectPlan;
+ }
+ List<ParserRuleContext> selectHintContexts = Lists.newArrayList();
+ for (Integer key : selectHintMap.keySet()) {
+ if (key > selectCtx.getStart().getStopIndex() && key <
selectCtx.getStop().getStartIndex()) {
+ selectHintContexts.add(selectHintMap.get(key));
+ }
+ }
+ return withSelectHint(selectPlan, selectHintContexts);
});
}
@@ -3068,47 +3083,50 @@ public class LogicalPlanBuilder extends
DorisParserBaseVisitor<Object> {
return last;
}
- private LogicalPlan withSelectHint(LogicalPlan logicalPlan,
SelectHintContext hintContext) {
- if (hintContext == null) {
+ private LogicalPlan withSelectHint(LogicalPlan logicalPlan,
List<ParserRuleContext> hintContexts) {
+ if (hintContexts.isEmpty()) {
return logicalPlan;
}
Map<String, SelectHint> hints = Maps.newLinkedHashMap();
- for (HintStatementContext hintStatement : hintContext.hintStatements) {
- String hintName =
hintStatement.hintName.getText().toLowerCase(Locale.ROOT);
- switch (hintName) {
- case "set_var":
- Map<String, Optional<String>> parameters =
Maps.newLinkedHashMap();
- for (HintAssignmentContext kv : hintStatement.parameters) {
- if (kv.key != null) {
- String parameterName =
visitIdentifierOrText(kv.key);
- Optional<String> value = Optional.empty();
- if (kv.constantValue != null) {
- Literal literal = (Literal)
visit(kv.constantValue);
- value =
Optional.ofNullable(literal.toLegacyLiteral().getStringValue());
- } else if (kv.identifierValue != null) {
- // maybe we should throw exception when the
identifierValue is quoted identifier
- value =
Optional.ofNullable(kv.identifierValue.getText());
+ for (ParserRuleContext hintContext : hintContexts) {
+ SelectHintContext selectHintContext = (SelectHintContext)
hintContext;
+ for (HintStatementContext hintStatement :
selectHintContext.hintStatements) {
+ String hintName =
hintStatement.hintName.getText().toLowerCase(Locale.ROOT);
+ switch (hintName) {
+ case "set_var":
+ Map<String, Optional<String>> parameters =
Maps.newLinkedHashMap();
+ for (HintAssignmentContext kv :
hintStatement.parameters) {
+ if (kv.key != null) {
+ String parameterName =
visitIdentifierOrText(kv.key);
+ Optional<String> value = Optional.empty();
+ if (kv.constantValue != null) {
+ Literal literal = (Literal)
visit(kv.constantValue);
+ value =
Optional.ofNullable(literal.toLegacyLiteral().getStringValue());
+ } else if (kv.identifierValue != null) {
+ // maybe we should throw exception when
the identifierValue is quoted identifier
+ value =
Optional.ofNullable(kv.identifierValue.getText());
+ }
+ parameters.put(parameterName, value);
}
- parameters.put(parameterName, value);
}
- }
- hints.put(hintName, new SelectHintSetVar(hintName,
parameters));
- break;
- case "leading":
- List<String> leadingParameters = new ArrayList<String>();
- for (HintAssignmentContext kv : hintStatement.parameters) {
- if (kv.key != null) {
- String parameterName =
visitIdentifierOrText(kv.key);
- leadingParameters.add(parameterName);
+ hints.put(hintName, new SelectHintSetVar(hintName,
parameters));
+ break;
+ case "leading":
+ List<String> leadingParameters = new
ArrayList<String>();
+ for (HintAssignmentContext kv :
hintStatement.parameters) {
+ if (kv.key != null) {
+ String parameterName =
visitIdentifierOrText(kv.key);
+ leadingParameters.add(parameterName);
+ }
}
- }
- hints.put(hintName, new SelectHintLeading(hintName,
leadingParameters));
- break;
- case "ordered":
- hints.put(hintName, new SelectHintOrdered(hintName));
- break;
- default:
- break;
+ hints.put(hintName, new SelectHintLeading(hintName,
leadingParameters));
+ break;
+ case "ordered":
+ hints.put(hintName, new SelectHintOrdered(hintName));
+ break;
+ default:
+ break;
+ }
}
}
return new LogicalSelectHint<>(hints, logicalPlan);
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilderForCreateView.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilderForCreateView.java
index 3989a8f8988..12c206dc084 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilderForCreateView.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilderForCreateView.java
@@ -52,10 +52,15 @@ import org.apache.doris.qe.ConnectContext;
import com.google.common.collect.ImmutableList;
import org.antlr.v4.runtime.ParserRuleContext;
+import java.util.Map;
import java.util.Optional;
/**LogicalPlanBuilderForCreateView*/
public class LogicalPlanBuilderForCreateView extends LogicalPlanBuilder {
+ public LogicalPlanBuilderForCreateView(Map<Integer, ParserRuleContext>
selectHintMap) {
+ super(selectHintMap);
+ }
+
@Override
protected LogicalPlan withGenerate(LogicalPlan plan, LateralViewContext
ctx) {
ConnectContext.get().getStatementContext().addIndexInSqlToString(
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/NereidsParser.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/NereidsParser.java
index 58854b1a293..edcbb76ad84 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/NereidsParser.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/NereidsParser.java
@@ -36,6 +36,7 @@ import org.apache.doris.qe.ConnectContext;
import org.apache.doris.qe.SessionVariable;
import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.ParserRuleContext;
@@ -273,16 +274,41 @@ public class NereidsParser {
Function<DorisParser, ParserRuleContext>
parseFunction) {
ParserRuleContext tree = toAst(sql, parseFunction);
LogicalPlanBuilder realLogicalPlanBuilder = logicalPlanBuilder == null
- ? new LogicalPlanBuilder() : logicalPlanBuilder;
+ ? new LogicalPlanBuilder(getHintMap(sql,
DorisParser::selectHint)) : logicalPlanBuilder;
return (T) realLogicalPlanBuilder.visit(tree);
}
public LogicalPlan parseForCreateView(String sql) {
ParserRuleContext tree = toAst(sql, DorisParser::singleStatement);
- LogicalPlanBuilder realLogicalPlanBuilder = new
LogicalPlanBuilderForCreateView();
+ LogicalPlanBuilder realLogicalPlanBuilder = new
LogicalPlanBuilderForCreateView(
+ getHintMap(sql, DorisParser::selectHint));
return (LogicalPlan) realLogicalPlanBuilder.visit(tree);
}
+ /** get hint map */
+ public static Map<Integer, ParserRuleContext> getHintMap(String sql,
+
Function<DorisParser, ParserRuleContext> parseFunction) {
+ // parse hint first round
+ DorisLexer hintLexer = new DorisLexer(new
CaseInsensitiveStream(CharStreams.fromString(sql)));
+ CommonTokenStream hintTokenStream = new CommonTokenStream(hintLexer);
+
+ Map<Integer, ParserRuleContext> selectHintMap = Maps.newHashMap();
+
+ Token hintToken = hintTokenStream.getTokenSource().nextToken();
+ while (hintToken != null && hintToken.getType() != DorisLexer.EOF) {
+ if (hintToken.getChannel() == 2 &&
sql.charAt(hintToken.getStartIndex() + 2) == '+') {
+ String hintSql = sql.substring(hintToken.getStartIndex() + 3,
hintToken.getStopIndex() + 1);
+ DorisLexer newHintLexer = new DorisLexer(new
CaseInsensitiveStream(CharStreams.fromString(hintSql)));
+ CommonTokenStream newHintTokenStream = new
CommonTokenStream(newHintLexer);
+ DorisParser hintParser = new DorisParser(newHintTokenStream);
+ ParserRuleContext hintContext =
parseFunction.apply(hintParser);
+ selectHintMap.put(hintToken.getStartIndex(), hintContext);
+ }
+ hintToken = hintTokenStream.getTokenSource().nextToken();
+ }
+ return selectHintMap;
+ }
+
/** toAst */
public static ParserRuleContext toAst(String sql, Function<DorisParser,
ParserRuleContext> parseFunction) {
DorisLexer lexer = new DorisLexer(new
CaseInsensitiveStream(CharStreams.fromString(sql)));
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/plsql/PLSqlLogicalPlanBuilder.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/plsql/PLSqlLogicalPlanBuilder.java
index 5841c451dd1..8825f5abd93 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/plsql/PLSqlLogicalPlanBuilder.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/plsql/PLSqlLogicalPlanBuilder.java
@@ -36,6 +36,10 @@ import java.util.List;
*/
public class PLSqlLogicalPlanBuilder extends LogicalPlanBuilder {
+ public PLSqlLogicalPlanBuilder() {
+ super(null);
+ }
+
public List<String> visitMultipartIdentifier(MultipartIdentifierContext
ctx) {
return ctx.parts.stream()
.map(RuleContext::getText)
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/nereids/parser/NereidsParserTest.java
b/fe/fe-core/src/test/java/org/apache/doris/nereids/parser/NereidsParserTest.java
index 2bbcbc4290d..aa6ff756b20 100644
---
a/fe/fe-core/src/test/java/org/apache/doris/nereids/parser/NereidsParserTest.java
+++
b/fe/fe-core/src/test/java/org/apache/doris/nereids/parser/NereidsParserTest.java
@@ -351,16 +351,10 @@ public class NereidsParserTest extends ParserTestBase {
parsePlan("select * from t1 join [broadcast] t2 on t1.keyy=t2.keyy")
.matches(logicalJoin().when(j ->
j.getDistributeHint().distributeType == DistributeType.BROADCAST_RIGHT));
- parsePlan("select * from t1 join /*+ broadcast */ t2 on
t1.keyy=t2.keyy")
- .matches(logicalJoin().when(j ->
j.getDistributeHint().distributeType == DistributeType.BROADCAST_RIGHT));
-
// invalid hint position
parsePlan("select * from [shuffle] t1 join t2 on t1.keyy=t2.keyy")
.assertThrowsExactly(ParseException.class);
- parsePlan("select * from /*+ shuffle */ t1 join t2 on t1.keyy=t2.keyy")
- .assertThrowsExactly(ParseException.class);
-
// invalid hint content
parsePlan("select * from t1 join [bucket] t2 on t1.keyy=t2.keyy")
.assertThrowsExactly(ParseException.class)
@@ -371,8 +365,6 @@ public class NereidsParserTest extends ParserTestBase {
+ "----------------------^^^");
// invalid multiple hints
- parsePlan("select * from t1 join /*+ shuffle , broadcast */ t2 on
t1.keyy=t2.keyy")
- .assertThrowsExactly(ParseException.class);
parsePlan("select * from t1 join [shuffle,broadcast] t2 on
t1.keyy=t2.keyy")
.assertThrowsExactly(ParseException.class);
diff --git a/regression-test/data/nereids_p0/hint/test_hint.out
b/regression-test/data/nereids_p0/hint/test_hint.out
new file mode 100644
index 00000000000..2145d4edae6
--- /dev/null
+++ b/regression-test/data/nereids_p0/hint/test_hint.out
@@ -0,0 +1,81 @@
+-- This file is automatically generated. You should know what you did if you
want to edit this
+-- !select1_1 --
+PhysicalResultSink
+--hashAgg[GLOBAL]
+----PhysicalDistribute[DistributionSpecGather]
+------hashAgg[LOCAL]
+--------hashJoin[INNER_JOIN] hashCondition=((t1.c1 = t2.c2)) otherCondition=()
+----------PhysicalOlapScan[t2]
+----------PhysicalDistribute[DistributionSpecReplicated]
+------------PhysicalOlapScan[t1]
+
+Hint log:
+Used: leading(t2 broadcast t1 )
+UnUsed:
+SyntaxError:
+
+-- !select1_2 --
+PhysicalResultSink
+--hashAgg[GLOBAL]
+----PhysicalDistribute[DistributionSpecGather]
+------hashAgg[LOCAL]
+--------PhysicalStorageLayerAggregate[t1]
+
+-- !select1_3 --
+PhysicalResultSink
+--hashAgg[GLOBAL]
+----PhysicalDistribute[DistributionSpecGather]
+------hashAgg[LOCAL]
+--------PhysicalStorageLayerAggregate[t1]
+
+-- !select1_4 --
+PhysicalResultSink
+--hashAgg[GLOBAL]
+----PhysicalDistribute[DistributionSpecGather]
+------hashAgg[LOCAL]
+--------PhysicalStorageLayerAggregate[t1]
+
+-- !select1_5 --
+PhysicalResultSink
+--hashAgg[GLOBAL]
+----PhysicalDistribute[DistributionSpecGather]
+------hashAgg[LOCAL]
+--------hashJoin[INNER_JOIN] hashCondition=((t1.c1 = t2.c2)) otherCondition=()
+----------PhysicalOlapScan[t2]
+----------PhysicalDistribute[DistributionSpecReplicated]
+------------PhysicalOlapScan[t1]
+
+Hint log:
+Used: leading(t2 broadcast t1 )
+UnUsed:
+SyntaxError:
+
+-- !select1_6 --
+PhysicalResultSink
+--hashAgg[GLOBAL]
+----PhysicalDistribute[DistributionSpecGather]
+------hashAgg[LOCAL]
+--------hashJoin[INNER_JOIN] hashCondition=((t1.c1 = t2.c2)) otherCondition=()
+----------PhysicalOlapScan[t2]
+----------PhysicalDistribute[DistributionSpecReplicated]
+------------PhysicalOlapScan[t1]
+
+Hint log:
+Used: leading(t2 broadcast t1 )
+UnUsed:
+SyntaxError:
+
+-- !select1_7 --
+PhysicalResultSink
+--hashAgg[GLOBAL]
+----PhysicalDistribute[DistributionSpecGather]
+------hashAgg[LOCAL]
+--------PhysicalStorageLayerAggregate[t1]
+
+-- !select1_8 --
+PhysicalResultSink
+--hashAgg[GLOBAL]
+----PhysicalDistribute[DistributionSpecGather]
+------hashAgg[LOCAL]
+--------PhysicalStorageLayerAggregate[t1]
+
diff --git a/regression-test/data/nereids_p0/hint/test_leading.out
b/regression-test/data/nereids_p0/hint/test_leading.out
index 470dc086812..07cc7c16284 100644
--- a/regression-test/data/nereids_p0/hint/test_leading.out
+++ b/regression-test/data/nereids_p0/hint/test_leading.out
@@ -2538,8 +2538,8 @@ PhysicalResultSink
------------PhysicalOlapScan[t3]
Hint log:
-Used: leading(t1 broadcast t2 t3 )
-UnUsed:
+Used: leading(t1 broadcast t2 broadcast t3 )
+UnUsed:
SyntaxError:
-- !select95_4 --
diff --git a/regression-test/suites/nereids_p0/hint/test_hint.groovy
b/regression-test/suites/nereids_p0/hint/test_hint.groovy
new file mode 100644
index 00000000000..d847f17fe64
--- /dev/null
+++ b/regression-test/suites/nereids_p0/hint/test_hint.groovy
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+suite("test_hint") {
+ // create database and tables
+ sql 'DROP DATABASE IF EXISTS test_hint'
+ sql 'CREATE DATABASE IF NOT EXISTS test_hint'
+ sql 'use test_hint'
+
+ // setting planner to nereids
+ sql 'set exec_mem_limit=21G'
+ sql 'set be_number_for_test=1'
+ sql 'set parallel_pipeline_task_num=1'
+ sql "set disable_nereids_rules=PRUNE_EMPTY_PARTITION"
+ sql 'set enable_nereids_planner=true'
+ sql "set ignore_shape_nodes='PhysicalProject'"
+ sql 'set enable_fallback_to_original_planner=false'
+ sql 'set runtime_filter_mode=OFF'
+
+ // create tables
+ sql """drop table if exists t1;"""
+ sql """drop table if exists t2;"""
+
+ sql """create table t1 (c1 int, c11 int) distributed by hash(c1) buckets 3
properties('replication_num' = '1');"""
+ sql """create table t2 (c2 int, c22 int) distributed by hash(c2) buckets 3
properties('replication_num' = '1');"""
+
+// test hint positions, remove join in order to make sure shape stable when no
use hint
+ qt_select1_1 """explain shape plan select /*+ leading(t2 broadcast t1) */
count(*) from t1 join t2 on c1 = c2;"""
+
+ qt_select1_2 """explain shape plan /*+ leading(t2 broadcast t1) */ select
count(*) from t1;"""
+
+ qt_select1_3 """explain shape plan select /*+DBP: ROUTE={GROUP_ID(zjaq)}*/
count(*) from t1;"""
+
+ qt_select1_4 """explain shape plan/*+DBP: ROUTE={GROUP_ID(zjaq)}*/ select
count(*) from t1;"""
+
+ qt_select1_5 """explain shape plan /*+ leading(t2 broadcast t1) */ select
/*+ leading(t2 broadcast t1) */ count(*) from t1 join t2 on c1 = c2;"""
+
+ qt_select1_6 """explain shape plan/*+DBP: ROUTE={GROUP_ID(zjaq)}*/ select
/*+ leading(t2 broadcast t1) */ count(*) from t1 join t2 on c1 = c2;"""
+
+ qt_select1_7 """explain shape plan /*+ leading(t2 broadcast t1) */ select
/*+DBP: ROUTE={GROUP_ID(zjaq)}*/ count(*) from t1;"""
+
+ qt_select1_8 """explain shape plan /*+DBP: ROUTE={GROUP_ID(zjaq)}*/ select
/*+DBP: ROUTE={GROUP_ID(zjaq)}*/ count(*) from t1;"""
+
+}
diff --git a/regression-test/suites/nereids_p0/hint/test_leading.groovy
b/regression-test/suites/nereids_p0/hint/test_leading.groovy
index cbbff148c3a..ec7d568362e 100644
--- a/regression-test/suites/nereids_p0/hint/test_leading.groovy
+++ b/regression-test/suites/nereids_p0/hint/test_leading.groovy
@@ -1000,7 +1000,7 @@ suite("test_leading") {
qt_select94_2 """explain shape plan select /*+ leading(t2 shuffle {t3 t1})
*/ count(*) from t1 join t2 on c1 = c2 join t3 on c2 = c3;"""
// outer join
- qt_select95_1 """explain shape plan select /*+ leading(t1 broadcast t2 t3)
*/ count(*) from t1 left outer join t2 on c1 = c2 join t3 on c2 = c3;"""
+ qt_select95_1 """explain shape plan select /*+ leading(t1 broadcast t2
broadcast t3) */ count(*) from t1 left outer join t2 on c1 = c2 join t3 on c2 =
c3;"""
explain {
sql """shape plan select /*+ leading(t1 broadcast {t2 t3}) */ count(*)
from t1 left outer join t2 on c1 = c2 join t3 on c2 = c3;"""
contains("UnUsed: leading(t1 broadcast { t2 t3 })")
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]