This is an automated email from the ASF dual-hosted git repository.
morrysnow pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push:
new 5a7454e8ab0 [fix](Nerieds) using join bugs (#48030)
5a7454e8ab0 is described below
commit 5a7454e8ab0452967ed6eb9f735b4e5dffac05a0
Author: morrySnow <[email protected]>
AuthorDate: Fri Feb 21 20:17:42 2025 +0800
[fix](Nerieds) using join bugs (#48030)
### What problem does this PR solve?
Related PR: #15311
Problem Summary:
1. select * should only return using columns from left relation
2. bind expression on using join should not do distinct slot by name on
using join's output
### Release note
change the return columns when select asterisk from using join.
before return key column from both side. now only return key column
from left side.
---
.../org/apache/doris/nereids/analyzer/Scope.java | 40 +++-
.../doris/nereids/parser/LogicalPlanBuilder.java | 5 +-
.../nereids/properties/LogicalProperties.java | 37 +++-
.../nereids/rules/analysis/BindExpression.java | 44 +++--
.../nereids/rules/analysis/ExpressionAnalyzer.java | 10 +-
.../nereids/rules/analysis/SubExprAnalyzer.java | 3 +-
.../doris/nereids/trees/plans/AbstractPlan.java | 9 +-
.../nereids/trees/plans/DiffOutputInAsterisk.java | 39 ++++
.../apache/doris/nereids/trees/plans/FakePlan.java | 2 +-
.../org/apache/doris/nereids/trees/plans/Plan.java | 8 +
.../trees/plans/logical/LogicalAssertNumRows.java | 9 +-
.../nereids/trees/plans/logical/LogicalFilter.java | 9 +-
.../trees/plans/logical/LogicalGenerate.java | 12 +-
.../nereids/trees/plans/logical/LogicalJoin.java | 111 +++++++----
.../trees/plans/logical/LogicalSelectHint.java | 8 +-
.../trees/plans/logical/LogicalSubQueryAlias.java | 15 +-
.../trees/plans/logical/LogicalUsingJoin.java | 149 ++++++++++++++
.../nereids/trees/plans/logical/UsingJoin.java | 217 ---------------------
.../trees/plans/physical/PhysicalSqlCache.java | 2 +-
.../org/apache/doris/nereids/util/JoinUtils.java | 36 +++-
.../org/apache/doris/nereids/util/PlanUtils.java | 24 +++
.../rules/analysis/BindSlotReferenceTest.java | 19 +-
.../data/nereids_p0/join/test_join2.out | Bin 1907 -> 1697 bytes
.../data/nereids_p0/join/test_join3.out | Bin 408 -> 351 bytes
.../data/nereids_syntax_p0/test_join3.out | Bin 408 -> 351 bytes
.../data/nereids_syntax_p0/using_join.out | Bin 127 -> 2193 bytes
regression-test/data/query_p0/join/test_join2.out | Bin 1907 -> 1697 bytes
regression-test/data/query_p0/join/test_join3.out | Bin 408 -> 351 bytes
.../suites/nereids_p0/join/test_join2.groovy | 20 +-
.../suites/nereids_syntax_p0/using_join.groovy | 150 ++++++++++----
30 files changed, 608 insertions(+), 370 deletions(-)
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/Scope.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/Scope.java
index 7c77c680ff2..cb74698a62b 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/Scope.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/Scope.java
@@ -61,27 +61,44 @@ public class Scope {
private final Optional<Scope> outerScope;
private final List<Slot> slots;
+ private final List<Slot> asteriskSlots;
private final Set<Slot> correlatedSlots;
private final boolean buildNameToSlot;
private final Supplier<ListMultimap<String, Slot>> nameToSlot;
+ private final Supplier<ListMultimap<String, Slot>> nameToAsteriskSlot;
- public Scope(List<? extends Slot> slots) {
+ public Scope(List<Slot> slots) {
this(Optional.empty(), slots);
}
+ public Scope(Optional<Scope> outerScope, List<Slot> slots) {
+ this(outerScope, slots, slots);
+ }
+
+ public Scope(List<Slot> slots, List<Slot> asteriskSlots) {
+ this(Optional.empty(), slots, asteriskSlots);
+ }
+
/** Scope */
- public Scope(Optional<Scope> outerScope, List<? extends Slot> slots) {
+ public Scope(Optional<Scope> outerScope, List<Slot> slots, List<Slot>
asteriskSlots) {
this.outerScope = Objects.requireNonNull(outerScope, "outerScope can
not be null");
this.slots = Utils.fastToImmutableList(Objects.requireNonNull(slots,
"slots can not be null"));
this.correlatedSlots = Sets.newLinkedHashSet();
this.buildNameToSlot = slots.size() > 500;
this.nameToSlot = buildNameToSlot ?
Suppliers.memoize(this::buildNameToSlot) : null;
+ this.nameToAsteriskSlot = buildNameToSlot ?
Suppliers.memoize(this::buildNameToAsteriskSlot) : null;
+ this.asteriskSlots = Utils.fastToImmutableList(
+ Objects.requireNonNull(asteriskSlots, "asteriskSlots can not
be null"));
}
public List<Slot> getSlots() {
return slots;
}
+ public List<Slot> getAsteriskSlots() {
+ return asteriskSlots;
+ }
+
public Optional<Scope> getOuterScope() {
return outerScope;
}
@@ -91,17 +108,18 @@ public class Scope {
}
/** findSlotIgnoreCase */
- public List<Slot> findSlotIgnoreCase(String slotName) {
+ public List<Slot> findSlotIgnoreCase(String slotName, boolean all) {
+ List<Slot> slots = all ? this.slots : this.asteriskSlots;
+ Supplier<ListMultimap<String, Slot>> nameToSlot = all ?
this.nameToSlot : this.nameToAsteriskSlot;
if (!buildNameToSlot) {
- Object[] array = new Object[slots.size()];
+ Slot[] array = new Slot[slots.size()];
int filterIndex = 0;
- for (int i = 0; i < slots.size(); i++) {
- Slot slot = slots.get(i);
+ for (Slot slot : slots) {
if (slot.getName().equalsIgnoreCase(slotName)) {
array[filterIndex++] = slot;
}
}
- return (List) Arrays.asList(array).subList(0, filterIndex);
+ return Arrays.asList(array).subList(0, filterIndex);
} else {
return nameToSlot.get().get(slotName.toUpperCase(Locale.ROOT));
}
@@ -114,4 +132,12 @@ public class Scope {
}
return map;
}
+
+ private ListMultimap<String, Slot> buildNameToAsteriskSlot() {
+ ListMultimap<String, Slot> map =
LinkedListMultimap.create(asteriskSlots.size());
+ for (Slot slot : asteriskSlots) {
+ map.put(slot.getName().toUpperCase(Locale.ROOT), slot);
+ }
+ return map;
+ }
}
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 c0ff406794a..0b56260042a 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
@@ -786,7 +786,7 @@ import
org.apache.doris.nereids.trees.plans.logical.LogicalSink;
import org.apache.doris.nereids.trees.plans.logical.LogicalSort;
import org.apache.doris.nereids.trees.plans.logical.LogicalSubQueryAlias;
import org.apache.doris.nereids.trees.plans.logical.LogicalUnion;
-import org.apache.doris.nereids.trees.plans.logical.UsingJoin;
+import org.apache.doris.nereids.trees.plans.logical.LogicalUsingJoin;
import org.apache.doris.nereids.types.AggStateType;
import org.apache.doris.nereids.types.ArrayType;
import org.apache.doris.nereids.types.BigIntType;
@@ -3604,8 +3604,7 @@ public class LogicalPlanBuilder extends
DorisParserBaseVisitor<Object> {
last,
plan(join.relationPrimary()), null);
} else {
- last = new UsingJoin<>(joinType, last,
- plan(join.relationPrimary()), ImmutableList.of(), ids,
distributeHint);
+ last = new LogicalUsingJoin<>(joinType, last,
plan(join.relationPrimary()), ids, distributeHint);
}
if (distributeHint.distributeType != DistributeType.NONE
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/properties/LogicalProperties.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/properties/LogicalProperties.java
index 3ac5a38c914..6383918ced7 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/properties/LogicalProperties.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/properties/LogicalProperties.java
@@ -37,27 +37,38 @@ import java.util.Set;
*/
public class LogicalProperties {
protected final Supplier<List<Slot>> outputSupplier;
- protected final Supplier<List<Id>> outputExprIdsSupplier;
+ protected final Supplier<List<Id<?>>> outputExprIdsSupplier;
protected final Supplier<Set<Slot>> outputSetSupplier;
protected final Supplier<Map<Slot, Slot>> outputMapSupplier;
protected final Supplier<Set<ExprId>> outputExprIdSetSupplier;
+ protected final Supplier<List<Slot>> asteriskOutputSupplier;
protected final Supplier<DataTrait> dataTraitSupplier;
private Integer hashCode = null;
+ /**
+ * constructor when output same as asterisk's output.
+ */
+ public LogicalProperties(Supplier<List<Slot>> outputSupplier,
Supplier<DataTrait> dataTraitSupplier) {
+ // the second parameters should be null to reuse memorized output
supplier
+ this(outputSupplier, null, dataTraitSupplier);
+ }
+
/**
* constructor of LogicalProperties.
*
* @param outputSupplier provide the output. Supplier can lazy compute
output without
* throw exception for which children have
UnboundRelation
+ * @param asteriskOutputSupplier provide the output when do select *.
+ * @param dataTraitSupplier provide the data trait.
*/
- public LogicalProperties(Supplier<List<Slot>> outputSupplier,
+ public LogicalProperties(Supplier<List<Slot>> outputSupplier,
Supplier<List<Slot>> asteriskOutputSupplier,
Supplier<DataTrait> dataTraitSupplier) {
this.outputSupplier = Suppliers.memoize(
Objects.requireNonNull(outputSupplier, "outputSupplier can not
be null")
);
this.outputExprIdsSupplier = Suppliers.memoize(() -> {
List<Slot> output = this.outputSupplier.get();
- ImmutableList.Builder<Id> exprIdSet
+ ImmutableList.Builder<Id<?>> exprIdSet
= ImmutableList.builderWithExpectedSize(output.size());
for (Slot slot : output) {
exprIdSet.add(slot.getExprId());
@@ -65,7 +76,7 @@ public class LogicalProperties {
return exprIdSet.build();
});
this.outputSetSupplier = Suppliers.memoize(() -> {
- List<Slot> output = outputSupplier.get();
+ List<Slot> output = this.outputSupplier.get();
ImmutableSet.Builder<Slot> slots =
ImmutableSet.builderWithExpectedSize(output.size());
for (Slot slot : output) {
slots.add(slot);
@@ -73,7 +84,7 @@ public class LogicalProperties {
return slots.build();
});
this.outputMapSupplier = Suppliers.memoize(() -> {
- Set<Slot> slots = outputSetSupplier.get();
+ Set<Slot> slots = this.outputSetSupplier.get();
ImmutableMap.Builder<Slot, Slot> map =
ImmutableMap.builderWithExpectedSize(slots.size());
for (Slot slot : slots) {
map.put(slot, slot);
@@ -89,6 +100,9 @@ public class LogicalProperties {
}
return exprIdSet.build();
});
+ this.asteriskOutputSupplier = asteriskOutputSupplier == null ?
this.outputSupplier : Suppliers.memoize(
+ Objects.requireNonNull(asteriskOutputSupplier,
"asteriskOutputSupplier can not be null")
+ );
this.dataTraitSupplier = Suppliers.memoize(
Objects.requireNonNull(dataTraitSupplier, "Data Trait can not
be null")
);
@@ -110,12 +124,16 @@ public class LogicalProperties {
return outputExprIdSetSupplier.get();
}
- public DataTrait getTrait() {
- return dataTraitSupplier.get();
+ public List<Id<?>> getOutputExprIds() {
+ return outputExprIdsSupplier.get();
}
- public List<Id> getOutputExprIds() {
- return outputExprIdsSupplier.get();
+ public List<Slot> getAsteriskOutput() {
+ return asteriskOutputSupplier.get();
+ }
+
+ public DataTrait getTrait() {
+ return dataTraitSupplier.get();
}
@Override
@@ -126,6 +144,7 @@ public class LogicalProperties {
+ "\noutputSetSupplier=" + outputSetSupplier.get()
+ "\noutputMapSupplier=" + outputMapSupplier.get()
+ "\noutputExprIdSetSupplier=" + outputExprIdSetSupplier.get()
+ + "\nasteriskOutputSupplier=" + asteriskOutputSupplier.get()
+ "\nhashCode=" + hashCode
+ '}';
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindExpression.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindExpression.java
index c308a1e7e79..029d44b8ed7 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindExpression.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindExpression.java
@@ -21,7 +21,6 @@ import org.apache.doris.catalog.Env;
import org.apache.doris.catalog.FunctionRegistry;
import org.apache.doris.common.Pair;
import org.apache.doris.nereids.CascadesContext;
-import org.apache.doris.nereids.NereidsPlanner;
import org.apache.doris.nereids.SqlCacheContext;
import org.apache.doris.nereids.StatementContext;
import org.apache.doris.nereids.analyzer.MappingSlot;
@@ -88,7 +87,7 @@ import
org.apache.doris.nereids.trees.plans.logical.LogicalSink;
import org.apache.doris.nereids.trees.plans.logical.LogicalSort;
import org.apache.doris.nereids.trees.plans.logical.LogicalSubQueryAlias;
import org.apache.doris.nereids.trees.plans.logical.LogicalTVFRelation;
-import org.apache.doris.nereids.trees.plans.logical.UsingJoin;
+import org.apache.doris.nereids.trees.plans.logical.LogicalUsingJoin;
import org.apache.doris.nereids.trees.plans.visitor.InferPlanOutputAlias;
import org.apache.doris.nereids.types.BooleanType;
import org.apache.doris.nereids.types.StructField;
@@ -130,7 +129,7 @@ import java.util.stream.Collectors;
*/
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
public class BindExpression implements AnalysisRuleFactory {
- public static final Logger LOG =
LogManager.getLogger(NereidsPlanner.class);
+ public static final Logger LOG =
LogManager.getLogger(BindExpression.class);
@Override
public List<Rule> buildRules() {
@@ -161,7 +160,7 @@ public class BindExpression implements AnalysisRuleFactory {
logicalFilter().thenApply(this::bindFilter)
),
RuleType.BINDING_USING_JOIN_SLOT.build(
- usingJoin().thenApply(this::bindUsingJoin)
+ logicalUsingJoin().thenApply(this::bindUsingJoin)
),
RuleType.BINDING_JOIN_SLOT.build(
logicalJoin().thenApply(this::bindJoin)
@@ -546,7 +545,7 @@ public class BindExpression implements AnalysisRuleFactory {
return new LogicalJoin<>(join.getJoinType(),
hashJoinConjuncts.build(), otherJoinConjuncts.build(),
- join.getDistributeHint(), join.getMarkJoinSlotReference(),
+ join.getDistributeHint(), join.getMarkJoinSlotReference(),
join.getExceptAsteriskOutputs(),
join.children(), null);
}
@@ -591,16 +590,17 @@ public class BindExpression implements
AnalysisRuleFactory {
}
}
- private LogicalJoin<Plan, Plan>
bindUsingJoin(MatchingContext<UsingJoin<Plan, Plan>> ctx) {
- UsingJoin<Plan, Plan> using = ctx.root;
+ private LogicalPlan bindUsingJoin(MatchingContext<LogicalUsingJoin<Plan,
Plan>> ctx) {
+ LogicalUsingJoin<Plan, Plan> using = ctx.root;
CascadesContext cascadesContext = ctx.cascadesContext;
- List<Expression> unboundHashJoinConjunct =
using.getHashJoinConjuncts();
+ List<Expression> unboundHashJoinConjunct = using.getUsingSlots();
- Scope leftScope = toScope(cascadesContext,
ExpressionUtils.distinctSlotByName(using.left().getOutput()));
- Scope rightScope = toScope(cascadesContext,
ExpressionUtils.distinctSlotByName(using.right().getOutput()));
+ Scope leftScope = toScope(cascadesContext, using.left().getOutput(),
using.left().getAsteriskOutput());
+ Scope rightScope = toScope(cascadesContext, using.right().getOutput(),
using.right().getAsteriskOutput());
ExpressionRewriteContext rewriteContext = new
ExpressionRewriteContext(cascadesContext);
Builder<Expression> hashEqExprs =
ImmutableList.builderWithExpectedSize(unboundHashJoinConjunct.size());
+ List<Slot> rightConjunctsSlots = Lists.newArrayList();
for (Expression usingColumn : unboundHashJoinConjunct) {
ExpressionAnalyzer leftExprAnalyzer = new ExpressionAnalyzer(
using, leftScope, cascadesContext, true, false);
@@ -609,13 +609,14 @@ public class BindExpression implements
AnalysisRuleFactory {
ExpressionAnalyzer rightExprAnalyzer = new ExpressionAnalyzer(
using, rightScope, cascadesContext, true, false);
Expression usingRightSlot = rightExprAnalyzer.analyze(usingColumn,
rewriteContext);
+ rightConjunctsSlots.add((Slot) usingRightSlot);
hashEqExprs.add(new EqualTo(usingLeftSlot, usingRightSlot));
}
return new LogicalJoin<>(
using.getJoinType() == JoinType.CROSS_JOIN ?
JoinType.INNER_JOIN : using.getJoinType(),
- hashEqExprs.build(), using.getOtherJoinConjuncts(),
- using.getDistributeHint(), using.getMarkJoinSlotReference(),
+ hashEqExprs.build(), ImmutableList.of(),
+ using.getDistributeHint(), Optional.empty(),
rightConjunctsSlots,
using.children(), null);
}
@@ -1035,11 +1036,11 @@ public class BindExpression implements
AnalysisRuleFactory {
private Supplier<Scope> buildAggOutputScopeWithoutAggFun(
List<? extends NamedExpression> boundAggOutput, CascadesContext
cascadesContext) {
return Suppliers.memoize(() -> {
- Builder<MappingSlot> nonAggFunOutput =
ImmutableList.builderWithExpectedSize(boundAggOutput.size());
+ Builder<Slot> nonAggFunOutput =
ImmutableList.builderWithExpectedSize(boundAggOutput.size());
for (NamedExpression output : boundAggOutput) {
if (!output.containsType(AggregateFunction.class)) {
Slot outputSlot = output.toSlot();
- MappingSlot mappingSlot = new MappingSlot(outputSlot,
+ Slot mappingSlot = new MappingSlot(outputSlot,
output instanceof Alias ? output.child(0) :
output);
nonAggFunOutput.add(mappingSlot);
}
@@ -1226,7 +1227,7 @@ public class BindExpression implements
AnalysisRuleFactory {
return expression;
}
- private Scope toScope(CascadesContext cascadesContext, List<? extends
Slot> slots) {
+ private Scope toScope(CascadesContext cascadesContext, List<Slot> slots) {
Optional<Scope> outerScope = cascadesContext.getOuterScope();
if (outerScope.isPresent()) {
return new Scope(outerScope, slots);
@@ -1235,11 +1236,20 @@ public class BindExpression implements
AnalysisRuleFactory {
}
}
+ private Scope toScope(CascadesContext cascadesContext, List<Slot> slots,
List<Slot> asteriskSlots) {
+ Optional<Scope> outerScope = cascadesContext.getOuterScope();
+ if (outerScope.isPresent()) {
+ return new Scope(outerScope, slots, asteriskSlots);
+ } else {
+ return new Scope(slots, asteriskSlots);
+ }
+ }
+
private SimpleExprAnalyzer buildSimpleExprAnalyzer(
Plan currentPlan, CascadesContext cascadesContext, List<Plan>
children,
boolean enableExactMatch, boolean bindSlotInOuterScope) {
- List<Slot> childrenOutputs =
PlanUtils.fastGetChildrenOutputs(children);
- Scope scope = toScope(cascadesContext, childrenOutputs);
+ Scope scope = toScope(cascadesContext,
PlanUtils.fastGetChildrenOutputs(children),
+ PlanUtils.fastGetChildrenAsteriskOutputs(children));
return buildSimpleExprAnalyzer(currentPlan, cascadesContext, scope,
enableExactMatch, bindSlotInOuterScope);
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/ExpressionAnalyzer.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/ExpressionAnalyzer.java
index 05d3804df2b..d7f0f637250 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/ExpressionAnalyzer.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/ExpressionAnalyzer.java
@@ -345,7 +345,7 @@ public class ExpressionAnalyzer extends
SubExprAnalyzer<ExpressionRewriteContext
public Expression visitUnboundStar(UnboundStar unboundStar,
ExpressionRewriteContext context) {
List<String> qualifier = unboundStar.getQualifier();
boolean showHidden = Util.showHiddenColumns();
- List<Slot> slots = getScope().getSlots()
+ List<Slot> slots = getScope().getAsteriskSlots()
.stream()
.filter(slot -> !(slot instanceof SlotReference)
|| (((SlotReference) slot).isVisible()) || showHidden)
@@ -920,7 +920,7 @@ public class ExpressionAnalyzer extends
SubExprAnalyzer<ExpressionRewriteContext
private List<Slot> bindSingleSlotByName(String name, Scope scope) {
int namePartSize = 1;
Builder<Slot> usedSlots = ImmutableList.builderWithExpectedSize(1);
- for (Slot boundSlot : scope.findSlotIgnoreCase(name)) {
+ for (Slot boundSlot : scope.findSlotIgnoreCase(name, false)) {
if (!shouldBindSlotBy(namePartSize, boundSlot)) {
continue;
}
@@ -933,7 +933,7 @@ public class ExpressionAnalyzer extends
SubExprAnalyzer<ExpressionRewriteContext
private List<Slot> bindSingleSlotByTable(String table, String name, Scope
scope) {
int namePartSize = 2;
Builder<Slot> usedSlots = ImmutableList.builderWithExpectedSize(1);
- for (Slot boundSlot : scope.findSlotIgnoreCase(name)) {
+ for (Slot boundSlot : scope.findSlotIgnoreCase(name, true)) {
if (!shouldBindSlotBy(namePartSize, boundSlot)) {
continue;
}
@@ -951,7 +951,7 @@ public class ExpressionAnalyzer extends
SubExprAnalyzer<ExpressionRewriteContext
private List<Slot> bindSingleSlotByDb(String db, String table, String
name, Scope scope) {
int namePartSize = 3;
Builder<Slot> usedSlots = ImmutableList.builderWithExpectedSize(1);
- for (Slot boundSlot : scope.findSlotIgnoreCase(name)) {
+ for (Slot boundSlot : scope.findSlotIgnoreCase(name, true)) {
if (!shouldBindSlotBy(namePartSize, boundSlot)) {
continue;
}
@@ -970,7 +970,7 @@ public class ExpressionAnalyzer extends
SubExprAnalyzer<ExpressionRewriteContext
private List<Slot> bindSingleSlotByCatalog(String catalog, String db,
String table, String name, Scope scope) {
int namePartSize = 4;
Builder<Slot> usedSlots = ImmutableList.builderWithExpectedSize(1);
- for (Slot boundSlot : scope.findSlotIgnoreCase(name)) {
+ for (Slot boundSlot : scope.findSlotIgnoreCase(name, true)) {
if (!shouldBindSlotBy(namePartSize, boundSlot)) {
continue;
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/SubExprAnalyzer.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/SubExprAnalyzer.java
index 9a70ce24afb..3d6ff95f809 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/SubExprAnalyzer.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/SubExprAnalyzer.java
@@ -206,7 +206,8 @@ class SubExprAnalyzer<T> extends
DefaultExpressionRewriter<T> {
cascadesContext, expr.getQueryPlan(),
cascadesContext.getCteContext());
// don't use `getScope()` because we only need
`getScope().getOuterScope()` and `getScope().getSlots()`
// otherwise unexpected errors may occur
- Scope subqueryScope = new Scope(getScope().getOuterScope(),
getScope().getSlots());
+ Scope subqueryScope = new Scope(getScope().getOuterScope(),
+ getScope().getSlots(), getScope().getAsteriskSlots());
subqueryContext.setOuterScope(subqueryScope);
subqueryContext.newAnalyzer().analyze();
return new AnalyzedResult((LogicalPlan)
subqueryContext.getRewritePlan(),
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/AbstractPlan.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/AbstractPlan.java
index 5b08bdd2e5b..0436f1c3182 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/AbstractPlan.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/AbstractPlan.java
@@ -19,7 +19,6 @@ package org.apache.doris.nereids.trees.plans;
import org.apache.doris.nereids.analyzer.Unbound;
import org.apache.doris.nereids.memo.GroupExpression;
-import org.apache.doris.nereids.properties.DataTrait;
import org.apache.doris.nereids.properties.LogicalProperties;
import org.apache.doris.nereids.properties.UnboundLogicalProperties;
import org.apache.doris.nereids.trees.AbstractTreeNode;
@@ -200,9 +199,11 @@ public abstract class AbstractPlan extends
AbstractTreeNode<Plan> implements Pla
if (hasUnboundChild || hasUnboundExpression()) {
return UnboundLogicalProperties.INSTANCE;
} else {
- Supplier<List<Slot>> outputSupplier =
Suppliers.memoize(this::computeOutput);
- Supplier<DataTrait> fdSupplier = () -> computeDataTrait();
- return new LogicalProperties(outputSupplier, fdSupplier);
+ if (this instanceof DiffOutputInAsterisk) {
+ return new LogicalProperties(this::computeOutput,
this::computeAsteriskOutput, this::computeDataTrait);
+ } else {
+ return new LogicalProperties(this::computeOutput,
this::computeDataTrait);
+ }
}
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/DiffOutputInAsterisk.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/DiffOutputInAsterisk.java
new file mode 100644
index 00000000000..ddce0226e64
--- /dev/null
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/DiffOutputInAsterisk.java
@@ -0,0 +1,39 @@
+// 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.
+
+package org.apache.doris.nereids.trees.plans;
+
+import org.apache.doris.nereids.trees.expressions.Slot;
+
+import java.util.List;
+
+/**
+ * trait for plan that output in Asterisk does not contain all slot which
could output, such as, UsingJoin.
+ */
+public interface DiffOutputInAsterisk extends Plan {
+ @Override
+ default List<Slot> getAsteriskOutput() {
+ boolean outputMayDiff = false;
+ for (Plan child : children()) {
+ if (child instanceof DiffOutputInAsterisk) {
+ outputMayDiff = true;
+ break;
+ }
+ }
+ return outputMayDiff ? getLogicalProperties().getAsteriskOutput() :
getLogicalProperties().getOutput();
+ }
+}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/FakePlan.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/FakePlan.java
index 39c546cdb19..ae17a9719bf 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/FakePlan.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/FakePlan.java
@@ -82,7 +82,7 @@ public class FakePlan implements Plan,
BlockFuncDepsPropagation {
@Override
public LogicalProperties getLogicalProperties() {
- return new LogicalProperties(ArrayList::new, () ->
DataTrait.EMPTY_TRAIT);
+ return new LogicalProperties(ImmutableList::of, () ->
DataTrait.EMPTY_TRAIT);
}
@Override
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/Plan.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/Plan.java
index 402ad046d91..5336cf5478c 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/Plan.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/Plan.java
@@ -98,6 +98,10 @@ public interface Plan extends TreeNode<Plan> {
*/
List<Slot> getOutput();
+ default List<Slot> getAsteriskOutput() {
+ return getOutput();
+ }
+
/**
* Get output slot set of the plan.
*/
@@ -159,6 +163,10 @@ public interface Plan extends TreeNode<Plan> {
throw new IllegalStateException("Not support compute output for " +
getClass().getName());
}
+ default List<Slot> computeAsteriskOutput() {
+ throw new IllegalStateException("Not support compute output for " +
getClass().getName());
+ }
+
/**
* Get the input relation ids set of the plan.
* @return The result is collected from all inputs relations
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalAssertNumRows.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalAssertNumRows.java
index ca2a9ff7c7d..f78b41d7bdd 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalAssertNumRows.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalAssertNumRows.java
@@ -25,6 +25,7 @@ import
org.apache.doris.nereids.trees.expressions.AssertNumRowsElement;
import
org.apache.doris.nereids.trees.expressions.AssertNumRowsElement.Assertion;
import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.expressions.Slot;
+import org.apache.doris.nereids.trees.plans.DiffOutputInAsterisk;
import org.apache.doris.nereids.trees.plans.Plan;
import org.apache.doris.nereids.trees.plans.PlanType;
import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor;
@@ -44,7 +45,8 @@ import java.util.stream.Collectors;
* If the number of rows is more than the desired num of rows, the query will
be cancelled.
* The cancelled reason will be reported by Backend and displayed back to the
user.
*/
-public class LogicalAssertNumRows<CHILD_TYPE extends Plan> extends
LogicalUnary<CHILD_TYPE> {
+public class LogicalAssertNumRows<CHILD_TYPE extends Plan> extends
LogicalUnary<CHILD_TYPE>
+ implements DiffOutputInAsterisk {
private final AssertNumRowsElement assertNumRowsElement;
@@ -120,6 +122,11 @@ public class LogicalAssertNumRows<CHILD_TYPE extends Plan>
extends LogicalUnary<
return child().getOutput().stream().map(o ->
o.withNullable(true)).collect(Collectors.toList());
}
+ @Override
+ public List<Slot> computeAsteriskOutput() {
+ return child().getAsteriskOutput().stream().map(o ->
o.withNullable(true)).collect(Collectors.toList());
+ }
+
@Override
public void computeUnique(Builder builder) {
if (assertNumRowsElement.getDesiredNumOfRows() == 1
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalFilter.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalFilter.java
index efd7e90c136..d502f8c5a2a 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalFilter.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalFilter.java
@@ -24,6 +24,7 @@ import org.apache.doris.nereids.properties.LogicalProperties;
import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.expressions.Slot;
import org.apache.doris.nereids.trees.expressions.SubqueryExpr;
+import org.apache.doris.nereids.trees.plans.DiffOutputInAsterisk;
import org.apache.doris.nereids.trees.plans.Plan;
import org.apache.doris.nereids.trees.plans.PlanType;
import org.apache.doris.nereids.trees.plans.algebra.Filter;
@@ -47,7 +48,8 @@ import java.util.stream.Stream;
/**
* Logical filter plan.
*/
-public class LogicalFilter<CHILD_TYPE extends Plan> extends
LogicalUnary<CHILD_TYPE> implements Filter {
+public class LogicalFilter<CHILD_TYPE extends Plan> extends
LogicalUnary<CHILD_TYPE>
+ implements Filter, DiffOutputInAsterisk {
private final Set<Expression> conjuncts;
@@ -86,6 +88,11 @@ public class LogicalFilter<CHILD_TYPE extends Plan> extends
LogicalUnary<CHILD_T
return child().getOutput();
}
+ @Override
+ public List<Slot> computeAsteriskOutput() {
+ return child().getAsteriskOutput();
+ }
+
@Override
public String toString() {
return Utils.toSqlString("LogicalFilter[" + id.asInt() + "]",
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalGenerate.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalGenerate.java
index 3dc0577779c..6856f4a129d 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalGenerate.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalGenerate.java
@@ -24,6 +24,7 @@ import org.apache.doris.nereids.properties.LogicalProperties;
import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.expressions.Slot;
import org.apache.doris.nereids.trees.expressions.functions.Function;
+import org.apache.doris.nereids.trees.plans.DiffOutputInAsterisk;
import org.apache.doris.nereids.trees.plans.Plan;
import org.apache.doris.nereids.trees.plans.PlanType;
import org.apache.doris.nereids.trees.plans.algebra.Generate;
@@ -41,7 +42,8 @@ import java.util.Optional;
/**
* plan for table generator, the statement like: SELECT * FROM tbl LATERAL
VIEW EXPLODE(c1) g as (gc1);
*/
-public class LogicalGenerate<CHILD_TYPE extends Plan> extends
LogicalUnary<CHILD_TYPE> implements Generate {
+public class LogicalGenerate<CHILD_TYPE extends Plan> extends
LogicalUnary<CHILD_TYPE>
+ implements Generate, DiffOutputInAsterisk {
private final List<Function> generators;
private final List<Slot> generatorOutput;
@@ -128,6 +130,14 @@ public class LogicalGenerate<CHILD_TYPE extends Plan>
extends LogicalUnary<CHILD
.build();
}
+ @Override
+ public List<Slot> computeAsteriskOutput() {
+ return ImmutableList.<Slot>builder()
+ .addAll(child().getAsteriskOutput())
+ .addAll(generatorOutput)
+ .build();
+ }
+
@Override
public String toString() {
return Utils.toSqlString("LogicalGenerate",
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalJoin.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalJoin.java
index c583360c3d8..fe4f1eed64f 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalJoin.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalJoin.java
@@ -30,6 +30,7 @@ import org.apache.doris.nereids.trees.expressions.ExprId;
import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.expressions.MarkJoinSlotReference;
import org.apache.doris.nereids.trees.expressions.Slot;
+import org.apache.doris.nereids.trees.plans.DiffOutputInAsterisk;
import org.apache.doris.nereids.trees.plans.DistributeType;
import org.apache.doris.nereids.trees.plans.JoinType;
import org.apache.doris.nereids.trees.plans.Plan;
@@ -60,12 +61,13 @@ import javax.annotation.Nullable;
* Logical join plan.
*/
public class LogicalJoin<LEFT_CHILD_TYPE extends Plan, RIGHT_CHILD_TYPE
extends Plan>
- extends LogicalBinary<LEFT_CHILD_TYPE, RIGHT_CHILD_TYPE> implements
Join {
+ extends LogicalBinary<LEFT_CHILD_TYPE, RIGHT_CHILD_TYPE> implements
Join, DiffOutputInAsterisk {
private final JoinType joinType;
private final List<Expression> otherJoinConjuncts;
private final List<Expression> hashJoinConjuncts;
private final List<Expression> markJoinConjuncts;
+ private final List<Slot> exceptAsteriskOutputs;
// When the predicate condition contains subqueries and disjunctions, the
join will be marked as MarkJoin.
private final Optional<MarkJoinSlotReference> markJoinSlotReference;
@@ -134,6 +136,15 @@ public class LogicalJoin<LEFT_CHILD_TYPE extends Plan,
RIGHT_CHILD_TYPE extends
markJoinSlotReference, Optional.empty(), Optional.empty(),
children, otherJoinReorderContext);
}
+ public LogicalJoin(JoinType joinType, List<Expression> hashJoinConjuncts,
+ List<Expression> otherJoinConjuncts, DistributeHint hint,
+ Optional<MarkJoinSlotReference> markJoinSlotReference, List<Slot>
exceptAsteriskOutputs,
+ List<Plan> children, JoinReorderContext otherJoinReorderContext) {
+ this(joinType, hashJoinConjuncts, otherJoinConjuncts,
ExpressionUtils.EMPTY_CONDITION, hint,
+ markJoinSlotReference, exceptAsteriskOutputs,
+ Optional.empty(), Optional.empty(), children,
otherJoinReorderContext);
+ }
+
public LogicalJoin(JoinType joinType, List<Expression> hashJoinConjuncts,
List<Expression> otherJoinConjuncts, List<Expression>
markJoinConjuncts, DistributeHint hint,
Optional<MarkJoinSlotReference> markJoinSlotReference,
List<Plan> children,
@@ -148,6 +159,18 @@ public class LogicalJoin<LEFT_CHILD_TYPE extends Plan,
RIGHT_CHILD_TYPE extends
Optional<GroupExpression> groupExpression,
Optional<LogicalProperties> logicalProperties, List<Plan> children,
JoinReorderContext joinReorderContext) {
+ this(joinType, hashJoinConjuncts, otherJoinConjuncts,
markJoinConjuncts, hint,
+ markJoinSlotReference, ImmutableList.of(),
+ groupExpression, logicalProperties, children,
joinReorderContext);
+ }
+
+ private LogicalJoin(JoinType joinType, List<Expression> hashJoinConjuncts,
+ List<Expression> otherJoinConjuncts, List<Expression>
markJoinConjuncts,
+ DistributeHint hint, Optional<MarkJoinSlotReference>
markJoinSlotReference,
+ List<Slot> exceptAsteriskOutputs,
+ Optional<GroupExpression> groupExpression,
+ Optional<LogicalProperties> logicalProperties, List<Plan> children,
+ JoinReorderContext joinReorderContext) {
// Just use in withXXX method. Don't need check/copyOf()
super(PlanType.LOGICAL_JOIN, groupExpression, logicalProperties,
children);
this.joinType = Objects.requireNonNull(joinType, "joinType can not be
null");
@@ -159,6 +182,7 @@ public class LogicalJoin<LEFT_CHILD_TYPE extends Plan,
RIGHT_CHILD_TYPE extends
this.joinReorderContext.copyFrom(joinReorderContext);
}
this.markJoinSlotReference = markJoinSlotReference;
+ this.exceptAsteriskOutputs = exceptAsteriskOutputs;
}
public LogicalJoin<? extends Plan, ? extends Plan> swap() {
@@ -257,6 +281,23 @@ public class LogicalJoin<LEFT_CHILD_TYPE extends Plan,
RIGHT_CHILD_TYPE extends
.build();
}
+ @Override
+ public List<Slot> computeAsteriskOutput() {
+ List<Slot> output =
Lists.newArrayList(JoinUtils.getJoinOutput(joinType, left(), right(), true));
+ if (isMarkJoin()) {
+ output.add(markJoinSlotReference.get());
+ }
+ output.removeAll(exceptAsteriskOutputs);
+ return output;
+ }
+
+ @Override
+ public List<Slot> getAsteriskOutput() {
+ boolean outputIsDiff = !exceptAsteriskOutputs.isEmpty();
+ return outputIsDiff ? getLogicalProperties().getAsteriskOutput()
+ : DiffOutputInAsterisk.super.getAsteriskOutput();
+ }
+
@Override
public String toString() {
List<Object> args = Lists.newArrayList(
@@ -286,12 +327,14 @@ public class LogicalJoin<LEFT_CHILD_TYPE extends Plan,
RIGHT_CHILD_TYPE extends
&& hashJoinConjuncts.equals(that.hashJoinConjuncts)
&& otherJoinConjuncts.equals(that.otherJoinConjuncts)
&& markJoinConjuncts.equals(that.markJoinConjuncts)
+ && exceptAsteriskOutputs.equals(that.exceptAsteriskOutputs)
&& Objects.equals(markJoinSlotReference,
that.markJoinSlotReference);
}
@Override
public int hashCode() {
- return Objects.hash(joinType, hashJoinConjuncts, otherJoinConjuncts,
markJoinConjuncts, markJoinSlotReference);
+ return Objects.hash(joinType, hashJoinConjuncts, otherJoinConjuncts,
+ markJoinConjuncts, markJoinSlotReference,
exceptAsteriskOutputs);
}
@Override
@@ -312,6 +355,10 @@ public class LogicalJoin<LEFT_CHILD_TYPE extends Plan,
RIGHT_CHILD_TYPE extends
return markJoinSlotReference;
}
+ public List<Slot> getExceptAsteriskOutputs() {
+ return exceptAsteriskOutputs;
+ }
+
public long getBitmap() {
return bitmap;
}
@@ -334,15 +381,15 @@ public class LogicalJoin<LEFT_CHILD_TYPE extends Plan,
RIGHT_CHILD_TYPE extends
public LogicalJoin<Plan, Plan> withChildren(List<Plan> children) {
Preconditions.checkArgument(children.size() == 2);
return new LogicalJoin<>(joinType, hashJoinConjuncts,
otherJoinConjuncts, markJoinConjuncts,
- hint, markJoinSlotReference, Optional.empty(),
Optional.empty(), children,
- joinReorderContext);
+ hint, markJoinSlotReference, exceptAsteriskOutputs,
+ Optional.empty(), Optional.empty(), children,
joinReorderContext);
}
@Override
public LogicalJoin<Plan, Plan>
withGroupExpression(Optional<GroupExpression> groupExpression) {
return new LogicalJoin<>(joinType, hashJoinConjuncts,
otherJoinConjuncts, markJoinConjuncts,
- hint, markJoinSlotReference, groupExpression,
Optional.of(getLogicalProperties()),
- children, joinReorderContext);
+ hint, markJoinSlotReference, exceptAsteriskOutputs,
+ groupExpression, Optional.of(getLogicalProperties()),
children, joinReorderContext);
}
@Override
@@ -350,15 +397,15 @@ public class LogicalJoin<LEFT_CHILD_TYPE extends Plan,
RIGHT_CHILD_TYPE extends
Optional<LogicalProperties> logicalProperties, List<Plan>
children) {
Preconditions.checkArgument(children.size() == 2);
return new LogicalJoin<>(joinType, hashJoinConjuncts,
otherJoinConjuncts, markJoinConjuncts,
- hint, markJoinSlotReference, groupExpression,
logicalProperties, children,
- joinReorderContext);
+ hint, markJoinSlotReference, exceptAsteriskOutputs,
+ groupExpression, logicalProperties, children,
joinReorderContext);
}
public LogicalJoin<Plan, Plan> withChildrenNoContext(Plan left, Plan right,
JoinReorderContext
otherJoinReorderContext) {
return new LogicalJoin<>(joinType, hashJoinConjuncts,
otherJoinConjuncts, markJoinConjuncts,
- hint, markJoinSlotReference, Optional.empty(),
Optional.empty(),
- ImmutableList.of(left, right), otherJoinReorderContext);
+ hint, markJoinSlotReference, exceptAsteriskOutputs,
+ Optional.empty(), Optional.empty(), ImmutableList.of(left,
right), otherJoinReorderContext);
}
/**
@@ -367,61 +414,59 @@ public class LogicalJoin<LEFT_CHILD_TYPE extends Plan,
RIGHT_CHILD_TYPE extends
public LogicalJoin<Plan, Plan> withJoinConjuncts(List<Expression>
hashJoinConjuncts,
List<Expression> otherJoinConjuncts, JoinReorderContext
otherJoinReorderContext) {
return new LogicalJoin<>(joinType, hashJoinConjuncts,
otherJoinConjuncts, markJoinConjuncts,
- hint, markJoinSlotReference, Optional.empty(),
Optional.empty(),
- children, otherJoinReorderContext);
+ hint, markJoinSlotReference, exceptAsteriskOutputs,
+ Optional.empty(), Optional.empty(), children,
otherJoinReorderContext);
}
public LogicalJoin<Plan, Plan> withJoinConjuncts(List<Expression>
hashJoinConjuncts,
- List<Expression>
otherJoinConjuncts,
- List<Expression>
markJoinConjuncts,
- JoinReorderContext
otherJoinReorderContext) {
+ List<Expression> otherJoinConjuncts, List<Expression>
markJoinConjuncts,
+ JoinReorderContext otherJoinReorderContext) {
return new LogicalJoin<>(joinType, hashJoinConjuncts,
otherJoinConjuncts, markJoinConjuncts,
- hint, markJoinSlotReference, Optional.empty(),
Optional.of(getLogicalProperties()),
- children, otherJoinReorderContext);
+ hint, markJoinSlotReference, exceptAsteriskOutputs,
+ Optional.empty(), Optional.of(getLogicalProperties()),
children, otherJoinReorderContext);
}
public LogicalJoin<Plan, Plan> withHashJoinConjunctsAndChildren(
List<Expression> hashJoinConjuncts, Plan left, Plan right,
JoinReorderContext otherJoinReorderContext) {
Preconditions.checkArgument(children.size() == 2);
return new LogicalJoin<>(joinType, hashJoinConjuncts,
otherJoinConjuncts, markJoinConjuncts,
- hint, markJoinSlotReference, Optional.empty(),
Optional.empty(),
- ImmutableList.of(left, right), otherJoinReorderContext);
+ hint, markJoinSlotReference, exceptAsteriskOutputs,
+ Optional.empty(), Optional.empty(), ImmutableList.of(left,
right), otherJoinReorderContext);
}
public LogicalJoin<Plan, Plan> withConjunctsChildren(List<Expression>
hashJoinConjuncts,
List<Expression> otherJoinConjuncts, Plan left, Plan right,
JoinReorderContext otherJoinReorderContext) {
return new LogicalJoin<>(joinType, hashJoinConjuncts,
otherJoinConjuncts, markJoinConjuncts,
- hint, markJoinSlotReference, Optional.empty(),
Optional.empty(),
- ImmutableList.of(left, right), otherJoinReorderContext);
+ hint, markJoinSlotReference, exceptAsteriskOutputs,
+ Optional.empty(), Optional.empty(), ImmutableList.of(left,
right), otherJoinReorderContext);
}
public LogicalJoin<Plan, Plan> withConjunctsChildren(List<Expression>
hashJoinConjuncts,
- List<Expression>
otherJoinConjuncts,
- List<Expression>
markJoinConjuncts, Plan left, Plan right,
- JoinReorderContext
otherJoinReorderContext) {
+ List<Expression> otherJoinConjuncts, List<Expression>
markJoinConjuncts, Plan left, Plan right,
+ JoinReorderContext otherJoinReorderContext) {
return new LogicalJoin<>(joinType, hashJoinConjuncts,
otherJoinConjuncts, markJoinConjuncts,
- hint, markJoinSlotReference, Optional.empty(),
Optional.empty(),
- ImmutableList.of(left, right), otherJoinReorderContext);
+ hint, markJoinSlotReference, exceptAsteriskOutputs,
+ Optional.empty(), Optional.empty(), ImmutableList.of(left,
right), otherJoinReorderContext);
}
public LogicalJoin<Plan, Plan> withJoinType(JoinType joinType) {
return new LogicalJoin<>(joinType, hashJoinConjuncts,
otherJoinConjuncts, markJoinConjuncts,
- hint, markJoinSlotReference, groupExpression,
Optional.of(getLogicalProperties()),
- children, joinReorderContext);
+ hint, markJoinSlotReference, exceptAsteriskOutputs,
+ groupExpression, Optional.of(getLogicalProperties()),
children, joinReorderContext);
}
public LogicalJoin<Plan, Plan> withJoinTypeAndContext(JoinType joinType,
JoinReorderContext otherJoinReorderContext) {
return new LogicalJoin<>(joinType, hashJoinConjuncts,
otherJoinConjuncts, markJoinConjuncts,
- hint, markJoinSlotReference, Optional.empty(),
Optional.empty(),
- children, otherJoinReorderContext);
+ hint, markJoinSlotReference, exceptAsteriskOutputs,
+ Optional.empty(), Optional.empty(), children,
otherJoinReorderContext);
}
public LogicalJoin<Plan, Plan> withTypeChildren(JoinType joinType, Plan
left, Plan right,
- JoinReorderContext
otherJoinReorderContext) {
+ JoinReorderContext otherJoinReorderContext) {
return new LogicalJoin<>(joinType, hashJoinConjuncts,
otherJoinConjuncts, markJoinConjuncts,
- hint, markJoinSlotReference, Optional.empty(),
Optional.empty(),
- ImmutableList.of(left, right), otherJoinReorderContext);
+ hint, markJoinSlotReference, exceptAsteriskOutputs,
+ Optional.empty(), Optional.empty(), ImmutableList.of(left,
right), otherJoinReorderContext);
}
/**
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalSelectHint.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalSelectHint.java
index a33e2194131..10b67a84f4e 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalSelectHint.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalSelectHint.java
@@ -23,6 +23,7 @@ import org.apache.doris.nereids.properties.SelectHint;
import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.expressions.Slot;
import org.apache.doris.nereids.trees.plans.BlockFuncDepsPropagation;
+import org.apache.doris.nereids.trees.plans.DiffOutputInAsterisk;
import org.apache.doris.nereids.trees.plans.Plan;
import org.apache.doris.nereids.trees.plans.PlanType;
import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor;
@@ -40,7 +41,7 @@ import java.util.stream.Collectors;
* e.g. LogicalSelectHint (set_var(query_timeout='1800',
exec_mem_limit='2147483648'))
*/
public class LogicalSelectHint<CHILD_TYPE extends Plan> extends
LogicalUnary<CHILD_TYPE>
- implements BlockFuncDepsPropagation {
+ implements BlockFuncDepsPropagation, DiffOutputInAsterisk {
private final ImmutableList<SelectHint> hints;
@@ -113,6 +114,11 @@ public class LogicalSelectHint<CHILD_TYPE extends Plan>
extends LogicalUnary<CHI
return child().getOutput();
}
+ @Override
+ public List<Slot> computeAsteriskOutput() {
+ return child().getAsteriskOutput();
+ }
+
@Override
public String toString() {
String hintStr = this.hints
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalSubQueryAlias.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalSubQueryAlias.java
index 331ceda3159..adedc0343a8 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalSubQueryAlias.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalSubQueryAlias.java
@@ -22,6 +22,7 @@ import org.apache.doris.nereids.properties.DataTrait;
import org.apache.doris.nereids.properties.LogicalProperties;
import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.expressions.Slot;
+import org.apache.doris.nereids.trees.plans.DiffOutputInAsterisk;
import org.apache.doris.nereids.trees.plans.Plan;
import org.apache.doris.nereids.trees.plans.PlanType;
import org.apache.doris.nereids.trees.plans.RelationId;
@@ -47,7 +48,8 @@ import java.util.Set;
*
* @param <CHILD_TYPE> param
*/
-public class LogicalSubQueryAlias<CHILD_TYPE extends Plan> extends
LogicalUnary<CHILD_TYPE> {
+public class LogicalSubQueryAlias<CHILD_TYPE extends Plan> extends
LogicalUnary<CHILD_TYPE>
+ implements DiffOutputInAsterisk {
protected RelationId relationId;
private final List<String> qualifier;
@@ -79,7 +81,16 @@ public class LogicalSubQueryAlias<CHILD_TYPE extends Plan>
extends LogicalUnary<
@Override
public List<Slot> computeOutput() {
- List<Slot> childOutput = child().getOutput();
+ return computeOutputInternal(false);
+ }
+
+ @Override
+ public List<Slot> computeAsteriskOutput() {
+ return computeOutputInternal(true);
+ }
+
+ private List<Slot> computeOutputInternal(boolean asteriskOutput) {
+ List<Slot> childOutput = asteriskOutput ? child().getAsteriskOutput()
: child().getOutput();
List<String> columnAliases =
this.columnAliases.orElseGet(ImmutableList::of);
ImmutableList.Builder<Slot> currentOutput = ImmutableList.builder();
for (int i = 0; i < childOutput.size(); i++) {
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalUsingJoin.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalUsingJoin.java
new file mode 100644
index 00000000000..1d2b3c077df
--- /dev/null
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalUsingJoin.java
@@ -0,0 +1,149 @@
+// 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.
+
+package org.apache.doris.nereids.trees.plans.logical;
+
+import org.apache.doris.nereids.hint.DistributeHint;
+import org.apache.doris.nereids.memo.GroupExpression;
+import org.apache.doris.nereids.properties.LogicalProperties;
+import org.apache.doris.nereids.trees.expressions.Expression;
+import org.apache.doris.nereids.trees.expressions.Slot;
+import org.apache.doris.nereids.trees.plans.BlockFuncDepsPropagation;
+import org.apache.doris.nereids.trees.plans.DistributeType;
+import org.apache.doris.nereids.trees.plans.JoinType;
+import org.apache.doris.nereids.trees.plans.Plan;
+import org.apache.doris.nereids.trees.plans.PlanType;
+import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor;
+import org.apache.doris.nereids.util.ExpressionUtils;
+import org.apache.doris.nereids.util.JoinUtils;
+import org.apache.doris.nereids.util.Utils;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+
+/**
+ * select col1 from t1 join t2 using(col1);
+ */
+public class LogicalUsingJoin<LEFT_CHILD_TYPE extends Plan, RIGHT_CHILD_TYPE
extends Plan>
+ extends LogicalBinary<LEFT_CHILD_TYPE, RIGHT_CHILD_TYPE> implements
BlockFuncDepsPropagation {
+
+ private final JoinType joinType;
+ private final ImmutableList<Expression> usingSlots;
+ private final DistributeHint hint;
+
+ public LogicalUsingJoin(JoinType joinType, LEFT_CHILD_TYPE leftChild,
RIGHT_CHILD_TYPE rightChild,
+ List<Expression> usingSlots, DistributeHint hint) {
+ this(joinType, leftChild, rightChild, usingSlots, Optional.empty(),
Optional.empty(), hint);
+ }
+
+ /**
+ * Constructor.
+ */
+ public LogicalUsingJoin(JoinType joinType, LEFT_CHILD_TYPE leftChild,
RIGHT_CHILD_TYPE rightChild,
+ List<Expression> usingSlots, Optional<GroupExpression>
groupExpression,
+ Optional<LogicalProperties> logicalProperties, DistributeHint
hint) {
+ super(PlanType.LOGICAL_USING_JOIN, groupExpression, logicalProperties,
leftChild, rightChild);
+ this.joinType = joinType;
+ this.usingSlots = ImmutableList.copyOf(usingSlots);
+ this.hint = hint;
+ }
+
+ @Override
+ public List<Slot> computeOutput() {
+ return JoinUtils.getJoinOutput(joinType, left(), right());
+ }
+
+ @Override
+ public Plan withGroupExpression(Optional<GroupExpression> groupExpression)
{
+ return new LogicalUsingJoin<>(joinType, child(0), child(1),
+ usingSlots, groupExpression,
Optional.of(getLogicalProperties()), hint);
+ }
+
+ @Override
+ public Plan withGroupExprLogicalPropChildren(Optional<GroupExpression>
groupExpression,
+ Optional<LogicalProperties> logicalProperties, List<Plan>
children) {
+ return new LogicalUsingJoin<>(joinType, children.get(0),
children.get(1),
+ usingSlots, groupExpression, logicalProperties, hint);
+ }
+
+ @Override
+ public Plan withChildren(List<Plan> children) {
+ return new LogicalUsingJoin<>(joinType, children.get(0),
children.get(1),
+ usingSlots, groupExpression,
Optional.of(getLogicalProperties()), hint);
+ }
+
+ @Override
+ public <R, C> R accept(PlanVisitor<R, C> visitor, C context) {
+ return visitor.visit(this, context);
+ }
+
+ @Override
+ public List<? extends Expression> getExpressions() {
+ return usingSlots;
+ }
+
+ public JoinType getJoinType() {
+ return joinType;
+ }
+
+ public List<Expression> getUsingSlots() {
+ return usingSlots;
+ }
+
+ public DistributeHint getDistributeHint() {
+ return hint;
+ }
+
+ public List<Expression> getMarkJoinConjuncts() {
+ return ExpressionUtils.EMPTY_CONDITION;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ LogicalUsingJoin<?, ?> usingJoin = (LogicalUsingJoin<?, ?>) o;
+ return joinType == usingJoin.joinType
+ && Objects.equals(usingSlots, usingJoin.usingSlots)
+ && Objects.equals(hint, usingJoin.hint);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(joinType, usingSlots, hint);
+ }
+
+ @Override
+ public String toString() {
+ List<Object> args = Lists.newArrayList(
+ "type", joinType,
+ "usingSlots", usingSlots);
+ if (hint.distributeType != DistributeType.NONE) {
+ args.add("hint");
+ args.add(hint.getExplainString());
+ }
+ return Utils.toSqlString("UsingJoin[" + id.asInt() + "]",
args.toArray());
+ }
+}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/UsingJoin.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/UsingJoin.java
deleted file mode 100644
index 62cb542e78a..00000000000
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/UsingJoin.java
+++ /dev/null
@@ -1,217 +0,0 @@
-// 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.
-
-package org.apache.doris.nereids.trees.plans.logical;
-
-import org.apache.doris.nereids.hint.DistributeHint;
-import org.apache.doris.nereids.memo.GroupExpression;
-import org.apache.doris.nereids.properties.LogicalProperties;
-import org.apache.doris.nereids.trees.expressions.Expression;
-import org.apache.doris.nereids.trees.expressions.MarkJoinSlotReference;
-import org.apache.doris.nereids.trees.expressions.Slot;
-import org.apache.doris.nereids.trees.plans.BlockFuncDepsPropagation;
-import org.apache.doris.nereids.trees.plans.DistributeType;
-import org.apache.doris.nereids.trees.plans.JoinType;
-import org.apache.doris.nereids.trees.plans.Plan;
-import org.apache.doris.nereids.trees.plans.PlanType;
-import org.apache.doris.nereids.trees.plans.algebra.Join;
-import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor;
-import org.apache.doris.nereids.util.ExpressionUtils;
-import org.apache.doris.nereids.util.Utils;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableList.Builder;
-import com.google.common.collect.Lists;
-
-import java.util.List;
-import java.util.Objects;
-import java.util.Optional;
-
-/**
- * select col1 from t1 join t2 using(col1);
- */
-public class UsingJoin<LEFT_CHILD_TYPE extends Plan, RIGHT_CHILD_TYPE extends
Plan>
- extends LogicalBinary<LEFT_CHILD_TYPE, RIGHT_CHILD_TYPE> implements
Join, BlockFuncDepsPropagation {
-
- private final JoinType joinType;
- private final ImmutableList<Expression> otherJoinConjuncts;
- private final ImmutableList<Expression> hashJoinConjuncts;
- private final DistributeHint hint;
-
- public UsingJoin(JoinType joinType, LEFT_CHILD_TYPE leftChild,
RIGHT_CHILD_TYPE rightChild,
- List<Expression> expressions, List<Expression> hashJoinConjuncts,
- DistributeHint hint) {
- this(joinType, leftChild, rightChild, expressions,
- hashJoinConjuncts, Optional.empty(), Optional.empty(), hint);
- }
-
- /**
- * Constructor.
- */
- public UsingJoin(JoinType joinType, LEFT_CHILD_TYPE leftChild,
RIGHT_CHILD_TYPE rightChild,
- List<Expression> expressions, List<Expression> hashJoinConjuncts,
Optional<GroupExpression> groupExpression,
- Optional<LogicalProperties> logicalProperties,
- DistributeHint hint) {
- super(PlanType.LOGICAL_USING_JOIN, groupExpression, logicalProperties,
leftChild, rightChild);
- this.joinType = joinType;
- this.otherJoinConjuncts = ImmutableList.copyOf(expressions);
- this.hashJoinConjuncts = ImmutableList.copyOf(hashJoinConjuncts);
- this.hint = hint;
- }
-
- @Override
- public List<Slot> computeOutput() {
-
- List<Slot> newLeftOutput = left().getOutput().stream().map(o ->
o.withNullable(true))
- .collect(ImmutableList.toImmutableList());
-
- List<Slot> newRightOutput = right().getOutput().stream().map(o ->
o.withNullable(true))
- .collect(ImmutableList.toImmutableList());
-
- switch (joinType) {
- case LEFT_SEMI_JOIN:
- case LEFT_ANTI_JOIN:
- return ImmutableList.copyOf(left().getOutput());
- case RIGHT_SEMI_JOIN:
- case RIGHT_ANTI_JOIN:
- return ImmutableList.copyOf(right().getOutput());
- case LEFT_OUTER_JOIN:
- return ImmutableList.<Slot>builder()
- .addAll(left().getOutput())
- .addAll(newRightOutput)
- .build();
- case RIGHT_OUTER_JOIN:
- return ImmutableList.<Slot>builder()
- .addAll(newLeftOutput)
- .addAll(right().getOutput())
- .build();
- case FULL_OUTER_JOIN:
- return ImmutableList.<Slot>builder()
- .addAll(newLeftOutput)
- .addAll(newRightOutput)
- .build();
- default:
- return ImmutableList.<Slot>builder()
- .addAll(left().getOutput())
- .addAll(right().getOutput())
- .build();
- }
- }
-
- @Override
- public Plan withGroupExpression(Optional<GroupExpression> groupExpression)
{
- return new UsingJoin(joinType, child(0), child(1), otherJoinConjuncts,
- hashJoinConjuncts, groupExpression,
Optional.of(getLogicalProperties()), hint);
- }
-
- @Override
- public Plan withGroupExprLogicalPropChildren(Optional<GroupExpression>
groupExpression,
- Optional<LogicalProperties> logicalProperties, List<Plan>
children) {
- return new UsingJoin(joinType, children.get(0), children.get(1),
otherJoinConjuncts,
- hashJoinConjuncts, groupExpression, logicalProperties, hint);
- }
-
- @Override
- public Plan withChildren(List<Plan> children) {
- return new UsingJoin(joinType, children.get(0), children.get(1),
otherJoinConjuncts,
- hashJoinConjuncts, groupExpression,
Optional.of(getLogicalProperties()), hint);
- }
-
- @Override
- public <R, C> R accept(PlanVisitor<R, C> visitor, C context) {
- return visitor.visit(this, context);
- }
-
- @Override
- public List<? extends Expression> getExpressions() {
- return new Builder<Expression>()
- .addAll(hashJoinConjuncts)
- .addAll(otherJoinConjuncts)
- .build();
- }
-
- public JoinType getJoinType() {
- return joinType;
- }
-
- public List<Expression> getOtherJoinConjuncts() {
- return otherJoinConjuncts;
- }
-
- public List<Expression> getHashJoinConjuncts() {
- return hashJoinConjuncts;
- }
-
- public DistributeHint getDistributeHint() {
- return hint;
- }
-
- public boolean isMarkJoin() {
- return false;
- }
-
- public Optional<MarkJoinSlotReference> getMarkJoinSlotReference() {
- return Optional.empty();
- }
-
- public List<Expression> getMarkJoinConjuncts() {
- return ExpressionUtils.EMPTY_CONDITION;
- }
-
- @Override
- public Optional<Expression> getOnClauseCondition() {
- return ExpressionUtils.optionalAnd(hashJoinConjuncts,
otherJoinConjuncts);
- }
-
- @Override
- public boolean hasDistributeHint() {
- return hint != null;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
- UsingJoin<?, ?> usingJoin = (UsingJoin<?, ?>) o;
- return joinType == usingJoin.joinType
- && Objects.equals(otherJoinConjuncts,
usingJoin.otherJoinConjuncts)
- && Objects.equals(hashJoinConjuncts,
usingJoin.hashJoinConjuncts)
- && Objects.equals(hint, usingJoin.hint);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(joinType, otherJoinConjuncts, hashJoinConjuncts,
hint);
- }
-
- @Override
- public String toString() {
- List<Object> args = Lists.newArrayList(
- "type", joinType,
- "hashJoinConjuncts", hashJoinConjuncts,
- "otherJoinConjuncts", otherJoinConjuncts);
- if (hint.distributeType != DistributeType.NONE) {
- args.add("hint");
- args.add(hint.getExplainString());
- }
- return Utils.toSqlString("UsingJoin[" + id.asInt() + "]",
args.toArray());
- }
-}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalSqlCache.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalSqlCache.java
index 2b2c7ac0428..afba3add8d7 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalSqlCache.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalSqlCache.java
@@ -66,7 +66,7 @@ public class PhysicalSqlCache extends PhysicalLeaf
Optional<ResultSet> resultSet, List<InternalService.PCacheValue>
cacheValues,
String backendAddress, String planBody) {
super(PlanType.PHYSICAL_SQL_CACHE, Optional.empty(),
- new LogicalProperties(() -> ImmutableList.of(), () ->
DataTrait.EMPTY_TRAIT));
+ new LogicalProperties(ImmutableList::of, () ->
DataTrait.EMPTY_TRAIT));
this.queryId = Objects.requireNonNull(queryId, "queryId can not be
null");
this.columnLabels = Objects.requireNonNull(columnLabels, "colNames can
not be null");
this.fieldInfos = Objects.requireNonNull(fieldInfos, "fieldInfos can
not be null");
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/JoinUtils.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/JoinUtils.java
index 770905bf199..863f9f92ab2 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/JoinUtils.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/JoinUtils.java
@@ -420,33 +420,49 @@ public class JoinUtils {
* @return return the output slots
*/
public static List<Slot> getJoinOutput(JoinType joinType, Plan left, Plan
right) {
+ return getJoinOutput(joinType, left, right, false);
+ }
+
+ /**
+ * calculate the output slot of a join operator according join type and
its children
+ *
+ * @param joinType the type of join operator
+ * @param left left child
+ * @param right right child
+ * @param asteriskOutput when true, return output for asterisk
+ *
+ * @return return the output slots
+ */
+ public static List<Slot> getJoinOutput(JoinType joinType, Plan left, Plan
right, boolean asteriskOutput) {
+ List<Slot> leftOutput = asteriskOutput ? left.getAsteriskOutput() :
left.getOutput();
+ List<Slot> rightOutput = asteriskOutput ? right.getAsteriskOutput() :
right.getOutput();
switch (joinType) {
case LEFT_SEMI_JOIN:
case LEFT_ANTI_JOIN:
case NULL_AWARE_LEFT_ANTI_JOIN:
- return ImmutableList.copyOf(left.getOutput());
+ return ImmutableList.copyOf(leftOutput);
case RIGHT_SEMI_JOIN:
case RIGHT_ANTI_JOIN:
- return ImmutableList.copyOf(right.getOutput());
+ return ImmutableList.copyOf(rightOutput);
case LEFT_OUTER_JOIN:
return ImmutableList.<Slot>builder()
- .addAll(left.getOutput())
- .addAll(applyNullable(right.getOutput(), true))
+ .addAll(leftOutput)
+ .addAll(applyNullable(rightOutput, true))
.build();
case RIGHT_OUTER_JOIN:
return ImmutableList.<Slot>builder()
- .addAll(applyNullable(left.getOutput(), true))
- .addAll(right.getOutput())
+ .addAll(applyNullable(leftOutput, true))
+ .addAll(rightOutput)
.build();
case FULL_OUTER_JOIN:
return ImmutableList.<Slot>builder()
- .addAll(applyNullable(left.getOutput(), true))
- .addAll(applyNullable(right.getOutput(), true))
+ .addAll(applyNullable(leftOutput, true))
+ .addAll(applyNullable(rightOutput, true))
.build();
default:
return ImmutableList.<Slot>builder()
- .addAll(left.getOutput())
- .addAll(right.getOutput())
+ .addAll(leftOutput)
+ .addAll(rightOutput)
.build();
}
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/PlanUtils.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/PlanUtils.java
index 28f7cda427e..7438e46ddc7 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/PlanUtils.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/PlanUtils.java
@@ -179,6 +179,30 @@ public class PlanUtils {
return output.build();
}
+ /** fastGetChildrenOutput */
+ public static List<Slot> fastGetChildrenAsteriskOutputs(List<Plan>
children) {
+ switch (children.size()) {
+ case 1: return children.get(0).getAsteriskOutput();
+ case 0: return ImmutableList.of();
+ default: {
+ }
+ }
+
+ int outputNum = 0;
+ // child.output is cached by AbstractPlan.logicalProperties,
+ // we can compute output num without the overhead of re-compute output
+ for (Plan child : children) {
+ List<Slot> output = child.getAsteriskOutput();
+ outputNum += output.size();
+ }
+ // generate output list only copy once and without resize the list
+ Builder<Slot> output =
ImmutableList.builderWithExpectedSize(outputNum);
+ for (Plan child : children) {
+ output.addAll(child.getAsteriskOutput());
+ }
+ return output.build();
+ }
+
/** fastGetInputSlots */
public static Set<Slot> fastGetInputSlots(List<? extends Expression>
expressions) {
switch (expressions.size()) {
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/BindSlotReferenceTest.java
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/BindSlotReferenceTest.java
index 8e790dcf0e7..63fa700f23c 100644
---
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/BindSlotReferenceTest.java
+++
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/BindSlotReferenceTest.java
@@ -34,7 +34,7 @@ import
org.apache.doris.nereids.trees.plans.logical.LogicalOlapScan;
import org.apache.doris.nereids.trees.plans.logical.LogicalPlan;
import org.apache.doris.nereids.trees.plans.logical.LogicalProject;
import org.apache.doris.nereids.trees.plans.logical.LogicalSubQueryAlias;
-import org.apache.doris.nereids.trees.plans.logical.UsingJoin;
+import org.apache.doris.nereids.trees.plans.logical.LogicalUsingJoin;
import org.apache.doris.nereids.util.MemoPatternMatchSupported;
import org.apache.doris.nereids.util.MemoTestUtils;
import org.apache.doris.nereids.util.PlanChecker;
@@ -159,15 +159,14 @@ class BindSlotReferenceTest implements
MemoPatternMatchSupported {
LogicalSubQueryAlias<LogicalOlapScan> sub3 = new
LogicalSubQueryAlias<>("t3", scan3);
DistributeHint hint = new DistributeHint(DistributeType.NONE);
- UsingJoin<LogicalSubQueryAlias<LogicalOlapScan>,
LogicalSubQueryAlias<LogicalOlapScan>>
- using1 = new UsingJoin<>(JoinType.LEFT_OUTER_JOIN, sub1,
- sub2, ImmutableList.of(), ImmutableList.of(new
UnboundSlot("id")), hint);
-
- UsingJoin<UsingJoin<LogicalSubQueryAlias<LogicalOlapScan>,
LogicalSubQueryAlias<LogicalOlapScan>>,
- LogicalSubQueryAlias<LogicalOlapScan>> using2
- = new UsingJoin<>(
- JoinType.LEFT_OUTER_JOIN, using1, sub3,
ImmutableList.of(),
- ImmutableList.of(new UnboundSlot("id")), hint);
+ LogicalUsingJoin<LogicalSubQueryAlias<LogicalOlapScan>,
LogicalSubQueryAlias<LogicalOlapScan>>
+ using1 = new LogicalUsingJoin<>(JoinType.LEFT_OUTER_JOIN, sub1,
+ sub2, ImmutableList.of(new UnboundSlot("id")), hint);
+
+
LogicalUsingJoin<LogicalUsingJoin<LogicalSubQueryAlias<LogicalOlapScan>,
LogicalSubQueryAlias<LogicalOlapScan>>,
+ LogicalSubQueryAlias<LogicalOlapScan>> using2 =
new LogicalUsingJoin<>(
+ JoinType.LEFT_OUTER_JOIN, using1, sub3,
+ ImmutableList.of(new UnboundSlot("id")), hint);
PlanChecker.from(MemoTestUtils.createConnectContext())
.analyze(using2)
diff --git a/regression-test/data/nereids_p0/join/test_join2.out
b/regression-test/data/nereids_p0/join/test_join2.out
index 13b0f74dc79..23b5592ae72 100644
Binary files a/regression-test/data/nereids_p0/join/test_join2.out and
b/regression-test/data/nereids_p0/join/test_join2.out differ
diff --git a/regression-test/data/nereids_p0/join/test_join3.out
b/regression-test/data/nereids_p0/join/test_join3.out
index 54eb521e21f..a85be3f68b7 100644
Binary files a/regression-test/data/nereids_p0/join/test_join3.out and
b/regression-test/data/nereids_p0/join/test_join3.out differ
diff --git a/regression-test/data/nereids_syntax_p0/test_join3.out
b/regression-test/data/nereids_syntax_p0/test_join3.out
index 54eb521e21f..a85be3f68b7 100644
Binary files a/regression-test/data/nereids_syntax_p0/test_join3.out and
b/regression-test/data/nereids_syntax_p0/test_join3.out differ
diff --git a/regression-test/data/nereids_syntax_p0/using_join.out
b/regression-test/data/nereids_syntax_p0/using_join.out
index 577c514b37d..4b034542dc5 100644
Binary files a/regression-test/data/nereids_syntax_p0/using_join.out and
b/regression-test/data/nereids_syntax_p0/using_join.out differ
diff --git a/regression-test/data/query_p0/join/test_join2.out
b/regression-test/data/query_p0/join/test_join2.out
index 13b0f74dc79..23b5592ae72 100644
Binary files a/regression-test/data/query_p0/join/test_join2.out and
b/regression-test/data/query_p0/join/test_join2.out differ
diff --git a/regression-test/data/query_p0/join/test_join3.out
b/regression-test/data/query_p0/join/test_join3.out
index 54eb521e21f..a85be3f68b7 100644
Binary files a/regression-test/data/query_p0/join/test_join3.out and
b/regression-test/data/query_p0/join/test_join3.out differ
diff --git a/regression-test/suites/nereids_p0/join/test_join2.groovy
b/regression-test/suites/nereids_p0/join/test_join2.groovy
index 2e17d5c8db1..abb1744430d 100644
--- a/regression-test/suites/nereids_p0/join/test_join2.groovy
+++ b/regression-test/suites/nereids_p0/join/test_join2.groovy
@@ -70,14 +70,14 @@ suite("test_join2", "query,p0") {
SELECT '' AS "xxx", *
FROM ${TBname1}
INNER JOIN ${TBname2} USING (i)
- ORDER BY 1,2,3,4,5,6;
+ ORDER BY 1,2,3,4,5;
"""
qt_join2 """
SELECT '' AS "xxx", *
FROM ${TBname1}
JOIN ${TBname2} USING (i)
- ORDER BY 1,2,3,4,5,6;
+ ORDER BY 1,2,3,4,5;
"""
test {
@@ -116,52 +116,52 @@ suite("test_join2", "query,p0") {
qt_join6 """
SELECT '' AS "xxx", *
FROM ${TBname1} LEFT OUTER JOIN ${TBname2} USING (i)
- ORDER BY 1,2,3,4,5,6;
+ ORDER BY 1,2,3,4,5;
"""
qt_join7 """
SELECT '' AS "xxx", *
FROM ${TBname1} LEFT JOIN ${TBname2} USING (i)
- ORDER BY 1,2,3,4,5,6;
+ ORDER BY 1,2,3,4,5;
"""
qt_join8 """
SELECT '' AS "xxx", *
FROM ${TBname1} RIGHT
OUTER JOIN ${TBname2} USING (i)
- ORDER BY 1,2,3,4,5,6;
+ ORDER BY 1,2,3,4,5;
"""
qt_join9 """
SELECT '' AS "xxx", *
FROM ${TBname1}
RIGHT JOIN ${TBname2} USING (i)
- ORDER BY 1,2,3,4,5,6;
+ ORDER BY 1,2,3,4,5;
"""
qt_join10 """
SELECT '' AS "xxx", *
FROM ${TBname1} FULL OUTER JOIN ${TBname2} USING (i)
- ORDER BY 1,2,3,4,5,6;
+ ORDER BY 1,2,3,4,5;
"""
qt_join11 """
SELECT '' AS "xxx", *
FROM ${TBname1} FULL JOIN ${TBname2} USING (i)
- ORDER BY 1,2,3,4,5,6;
+ ORDER BY 1,2,3,4,5;
"""
qt_join12 """
SELECT '' AS "xxx", *
FROM ${TBname1} LEFT JOIN ${TBname2} USING (i)
WHERE (k = 1)
- ORDER BY 1,2,3,4,5,6;
+ ORDER BY 1,2,3,4,5;
"""
qt_join13 """
SELECT '' AS "xxx", *
FROM ${TBname1} LEFT JOIN ${TBname2} USING (i)
WHERE (${TBname1}.i = 1)
- ORDER BY 1,2,3,4,5,6;
+ ORDER BY 1,2,3,4,5;
"""
sql "DROP TABLE IF EXISTS ${TBname1};"
diff --git a/regression-test/suites/nereids_syntax_p0/using_join.groovy
b/regression-test/suites/nereids_syntax_p0/using_join.groovy
index 795dc07b483..bb9d1500f60 100644
--- a/regression-test/suites/nereids_syntax_p0/using_join.groovy
+++ b/regression-test/suites/nereids_syntax_p0/using_join.groovy
@@ -16,62 +16,140 @@
// under the License.
suite("nereids_using_join") {
+ sql """DROP TABLE IF EXISTS nereids_using_join_t1"""
+ sql """DROP TABLE IF EXISTS nereids_using_join_t2"""
+ sql """DROP TABLE IF EXISTS nereids_using_join_t3"""
+ sql """DROP TABLE IF EXISTS nereids_using_join_t4"""
+
sql """
- SET enable_fallback_to_original_planner=false
+ CREATE TABLE `nereids_using_join_t1` (
+ `c1` int,
+ `c2` int,
+ `c3` int,
+ `c4` array<int>,
+ `v1` int
+ )
+ PROPERTIES (
+ "replication_allocation" = "tag.location.default: 1"
+ );
"""
sql """
- SET enable_nereids_planner=true
+ CREATE TABLE `nereids_using_join_t2` (
+ `c1` int,
+ `c2` int,
+ `v2` int
+ )
+ PROPERTIES (
+ "replication_allocation" = "tag.location.default: 1"
+ );
"""
- sql """DROP TABLE IF EXISTS nereids_using_join_t1"""
-
sql """
- CREATE TABLE `nereids_using_join_t1` (
- `col1` varchar(4) NULL,
- `col2` int(11) NULL,
- `col3` int(11) NULL
- ) ENGINE=OLAP
- DUPLICATE KEY(`col1`)
- COMMENT 'OLAP'
- DISTRIBUTED BY HASH(`col3`) BUCKETS 1
+ CREATE TABLE `nereids_using_join_t3` (
+ `c1` int,
+ `v3` int
+ )
PROPERTIES (
- "replication_allocation" = "tag.location.default: 1"
+ "replication_allocation" = "tag.location.default: 1"
);
"""
- sql """DROP TABLE IF EXISTS nereids_using_join_t2"""
-
sql """
- CREATE TABLE `nereids_using_join_t2` (
- `col1` varchar(4) NULL,
- `col2` int(11) NULL,
- `col3` int(11) NULL
- ) ENGINE=OLAP
- DUPLICATE KEY(`col1`)
- COMMENT 'OLAP'
- DISTRIBUTED BY HASH(`col3`) BUCKETS 1
+ CREATE TABLE `nereids_using_join_t4` (
+ `c1` int,
+ `c5` int,
+ `v4` int
+ )
PROPERTIES (
- "replication_allocation" = "tag.location.default: 1"
+ "replication_allocation" = "tag.location.default: 1"
);
"""
- sql """INSERT INTO nereids_using_join_t1 VALUES('1', 1, 1)"""
- sql """INSERT INTO nereids_using_join_t1 VALUES('2', 2, 1)"""
- sql """INSERT INTO nereids_using_join_t1 VALUES('3', 3, 1)"""
- sql """INSERT INTO nereids_using_join_t1 VALUES('4', 4, 1)"""
+ sql """INSERT INTO nereids_using_join_t1 VALUES(1, 1, 1, [1, 2, 3, 4],
11)"""
+ sql """INSERT INTO nereids_using_join_t1 VALUES(2, 3, 4, [5, 6, 7, 8],
12)"""
+ sql """INSERT INTO nereids_using_join_t2 VALUES(1, 1, 21)"""
+ sql """INSERT INTO nereids_using_join_t2 VALUES(1, 2, 22)"""
+ sql """INSERT INTO nereids_using_join_t2 VALUES(1, 3, 23)"""
+ sql """INSERT INTO nereids_using_join_t3 VALUES(1, 31)"""
+ sql """INSERT INTO nereids_using_join_t3 VALUES(2, 32)"""
+ sql """INSERT INTO nereids_using_join_t3 VALUES(3, 33)"""
+ sql """INSERT INTO nereids_using_join_t3 VALUES(4, 34)"""
+ sql """INSERT INTO nereids_using_join_t4 VALUES(1, 1, 41)"""
+ sql """INSERT INTO nereids_using_join_t4 VALUES(1, 2, 42)"""
+ sql """INSERT INTO nereids_using_join_t4 VALUES(1, 3, 43)"""
+ sql """INSERT INTO nereids_using_join_t4 VALUES(1, 4, 44)"""
+ sql """INSERT INTO nereids_using_join_t4 VALUES(1, 5, 45)"""
+ sql """INSERT INTO nereids_using_join_t4 VALUES(1, 6, 46)"""
+ sql """INSERT INTO nereids_using_join_t4 VALUES(1, 7, 47)"""
+ sql """INSERT INTO nereids_using_join_t4 VALUES(1, 8, 48)"""
+
+ order_qt_two_relations """
+ select * from nereids_using_join_t1 join nereids_using_join_t2 using
(c1);
+ """
+
+ order_qt_two_relations_by_two_slot """
+ select * from nereids_using_join_t1 join nereids_using_join_t2 using
(c1, c2);
+ """
+
+ order_qt_two_relations_with_right_slot """
+ select *, nereids_using_join_t2.c1 from nereids_using_join_t1 join
nereids_using_join_t2 using (c1);
+ """
+
+ order_qt_two_relations_with_alias """
+ select * from nereids_using_join_t1 a join nereids_using_join_t2 b
using (c1);
+ """
+
+ order_qt_three_relations """
+ select * from nereids_using_join_t1 join nereids_using_join_t3 using
(c1) join nereids_using_join_t2 using (c2);
+ """
+
+ order_qt_one_plus_two_relations """
+ select * from nereids_using_join_t2 join (nereids_using_join_t1 join
nereids_using_join_t3 using (c1)) using (c1);
+ """
+
+ order_qt_one_plus_two_cross_join """
+ select * from nereids_using_join_t1 join (nereids_using_join_t2,
nereids_using_join_t3) using (c2);
+ """
+
+ order_qt_one_cross_join_with_two """
+ select * from nereids_using_join_t1, nereids_using_join_t2 join
nereids_using_join_t3 using (c1);
+ """
+
+ order_qt_with_lateral_view """
+ select * from nereids_using_join_t1 lateral view explode(c4) tmp as c5
join nereids_using_join_t3 using (c1) join nereids_using_join_t2 using (c2)
join nereids_using_join_t4 using(c5);
+ """
- sql """INSERT INTO nereids_using_join_t2 VALUES('1', 1, 1)"""
- sql """INSERT INTO nereids_using_join_t2 VALUES('2', 2, 1)"""
- sql """INSERT INTO nereids_using_join_t2 VALUES('6', 3, 1)"""
- sql """INSERT INTO nereids_using_join_t2 VALUES('7', 4, 1)"""
+ order_qt_with_aggregate_project """
+ select * from (select c3, sum(nereids_using_join_t2.c2) from
nereids_using_join_t1 join nereids_using_join_t2 using (c1) group by c3) t
+ """
+
+ order_qt_with_aggregate_by_right_slot_project """
+ select * from (select nereids_using_join_t2.c1,
sum(nereids_using_join_t2.c2) from nereids_using_join_t1 join
nereids_using_join_t2 using (c1) group by nereids_using_join_t2.c1) t
+ """
+
+ order_qt_with_project_aggregate """
+ select c1, sum(c3) from (select * from nereids_using_join_t1 join
nereids_using_join_t3 using (c1)) t group by c1
+ """
+
+ order_qt_with_extend_aggregate """
+ select c1, c2, c3, sum(c3) from (select * from nereids_using_join_t1
join nereids_using_join_t3 using (c1)) t group by grouping sets ((c1), (c2),
(c3))
+ """
+
+ order_qt_with_order_by """
+ select * from (select * from nereids_using_join_t1 join
nereids_using_join_t3 using (c1) order by c1) t join nereids_using_join_t2
using (c1) order by c1;
+ """
+
+ order_qt_with_limit """
+ select * from (select * from nereids_using_join_t1 join
nereids_using_join_t3 using (c1) limit 10) t join nereids_using_join_t2 using
(c1) limit 5;
+ """
- order_qt_sql """
- SELECT nereids_using_join_t1.col1 FROM nereids_using_join_t1 JOIN
nereids_using_join_t2 USING (col1)
+ order_qt_with_union_all """
+ select * from (select * from nereids_using_join_t1 join
nereids_using_join_t3 using (c1) union all select * from nereids_using_join_t1
join nereids_using_join_t3 using (c1)) t
"""
- order_qt_sql """
- SELECT nereids_using_join_t1.col1 FROM nereids_using_join_t1 JOIN
nereids_using_join_t2 USING (col1, col2)
+ order_qt_with_filter """
+ select * from nereids_using_join_t1 join nereids_using_join_t2 using
(c1) where c1 < 3;
"""
}
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]