This is an automated email from the ASF dual-hosted git repository.
amashenkov pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git
The following commit(s) were added to refs/heads/main by this push:
new 0b54599735f IGNITE-25607 Sql. Invalid distribution for Exchange node
in EXPLAIN PLAN (#6001)
0b54599735f is described below
commit 0b54599735f6011a3c317b9f887b0512129f8211
Author: Andrew V. Mashenkov <[email protected]>
AuthorDate: Tue Jun 10 15:48:54 2025 +0300
IGNITE-25607 Sql. Invalid distribution for Exchange node in EXPLAIN PLAN
(#6001)
---
.../sql/engine/exec/DestinationFactory.java | 5 +-
.../exec/ExecutionDependencyResolverImpl.java | 8 +-
.../internal/sql/engine/externalize/RelJson.java | 22 ++---
.../pruning/PartitionPruningMetadataExtractor.java | 2 +-
.../sql/engine/rel/AbstractIgniteJoin.java | 17 ++--
.../internal/sql/engine/rel/IgniteProject.java | 4 +-
.../engine/rel/explain/RelTreeToTextWriter.java | 7 +-
.../sql/engine/trait/DistributionFunction.java | 70 ---------------
.../sql/engine/trait/DistributionTrait.java | 100 +++++++++++++++++++--
.../sql/engine/trait/IgniteDistribution.java | 12 +++
.../sql/engine/trait/IgniteDistributions.java | 25 +++++-
.../exec/IdentityDistributionFunctionSelfTest.java | 2 -
.../engine/exec/mapping/FragmentMappingTest.java | 3 +-
.../sql/engine/exec/mapping/FragmentPrinter.java | 6 +-
.../sql/engine/framework/TestBuilders.java | 6 +-
.../engine/planner/JoinColocationPlannerTest.java | 10 +--
.../engine/schema/SqlSchemaManagerImplTest.java | 16 ++--
17 files changed, 175 insertions(+), 140 deletions(-)
diff --git
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/DestinationFactory.java
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/DestinationFactory.java
index 834ef891ba8..00b18034cd0 100644
---
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/DestinationFactory.java
+++
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/DestinationFactory.java
@@ -32,7 +32,6 @@ import
org.apache.ignite.internal.sql.engine.schema.TableDescriptor;
import org.apache.ignite.internal.sql.engine.trait.AllNodes;
import org.apache.ignite.internal.sql.engine.trait.Destination;
import org.apache.ignite.internal.sql.engine.trait.DistributionFunction;
-import
org.apache.ignite.internal.sql.engine.trait.DistributionFunction.AffinityDistribution;
import org.apache.ignite.internal.sql.engine.trait.Identity;
import org.apache.ignite.internal.sql.engine.trait.IgniteDistribution;
import org.apache.ignite.internal.sql.engine.trait.Partitioned;
@@ -92,10 +91,10 @@ class DestinationFactory<RowT> {
return new Identity<>(rowHandler, keys.get(0),
group.nodeNames());
}
- if (function.affinity()) {
+ if (distribution.isTableDistribution()) {
assert !nullOrEmpty(group.assignments());
- int tableId = ((AffinityDistribution) function).tableId();
+ int tableId = distribution.tableId();
Supplier<PartitionCalculator> calculator =
dependencies.partitionCalculator(tableId);
TableDescriptor tableDescriptor =
dependencies.tableDescriptor(tableId);
diff --git
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ExecutionDependencyResolverImpl.java
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ExecutionDependencyResolverImpl.java
index c5344413d89..d6fb68016f7 100644
---
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ExecutionDependencyResolverImpl.java
+++
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ExecutionDependencyResolverImpl.java
@@ -29,8 +29,6 @@ import
org.apache.ignite.internal.sql.engine.rel.IgniteTableScan;
import org.apache.ignite.internal.sql.engine.rel.IgniteTrimExchange;
import org.apache.ignite.internal.sql.engine.schema.IgniteSystemView;
import org.apache.ignite.internal.sql.engine.schema.IgniteTable;
-import org.apache.ignite.internal.sql.engine.trait.DistributionFunction;
-import
org.apache.ignite.internal.sql.engine.trait.DistributionFunction.AffinityDistribution;
import org.apache.ignite.internal.sql.engine.trait.IgniteDistribution;
import org.apache.ignite.internal.sql.engine.trait.TraitUtils;
@@ -116,10 +114,8 @@ public class ExecutionDependencyResolverImpl implements
ExecutionDependencyResol
}
private void resolveDistributionFunction(IgniteDistribution
distribution) {
- DistributionFunction function = distribution.function();
-
- if (function.affinity()) {
- int tableId = ((AffinityDistribution) function).tableId();
+ if (distribution.isTableDistribution()) {
+ int tableId = distribution.tableId();
resolveTable(catalogVersion, tableId);
}
diff --git
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/externalize/RelJson.java
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/externalize/RelJson.java
index e6af5c0bdd0..e2e1af2e988 100644
---
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/externalize/RelJson.java
+++
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/externalize/RelJson.java
@@ -113,7 +113,6 @@ import
org.apache.ignite.internal.sql.engine.prepare.bounds.RangeBounds;
import org.apache.ignite.internal.sql.engine.prepare.bounds.SearchBounds;
import org.apache.ignite.internal.sql.engine.rel.IgniteRel;
import org.apache.ignite.internal.sql.engine.trait.DistributionFunction;
-import
org.apache.ignite.internal.sql.engine.trait.DistributionFunction.AffinityDistribution;
import org.apache.ignite.internal.sql.engine.trait.DistributionTrait;
import org.apache.ignite.internal.sql.engine.trait.IgniteDistribution;
import org.apache.ignite.internal.sql.engine.trait.IgniteDistributions;
@@ -540,12 +539,10 @@ class RelJson {
map.put("func", distribution.function().name());
map.put("keys", keys);
- DistributionFunction function = distribution.function();
-
- if (function.affinity()) {
- map.put("zoneId", ((AffinityDistribution)
function).zoneId());
- map.put("tableId", ((AffinityDistribution)
function).tableId());
- map.put("label", ((AffinityDistribution)
function).label());
+ if (distribution.isTableDistribution()) {
+ map.put("zoneId", distribution.zoneId());
+ map.put("tableId", distribution.tableId());
+ map.put("label", distribution.label());
}
return map;
@@ -692,10 +689,10 @@ class RelJson {
return IgniteDistributions.identity(keys.get(0));
}
- case "hash":
- return IgniteDistributions.hash(keys,
DistributionFunction.hash());
- default: {
- assert functionName.startsWith("affinity");
+ case "hash": {
+ if (map.get("tableId") == null) {
+ return IgniteDistributions.hash(keys,
DistributionFunction.hash());
+ }
int tableId = (int) map.get("tableId");
int zoneId = (int) map.get("zoneId");
@@ -703,6 +700,9 @@ class RelJson {
return IgniteDistributions.affinity(keys, tableId, zoneId,
label);
}
+ default: {
+ throw new IllegalStateException("Unsupported distribution
function: " + functionName);
+ }
}
}
diff --git
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/pruning/PartitionPruningMetadataExtractor.java
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/pruning/PartitionPruningMetadataExtractor.java
index 73935936186..759cd6d9a12 100644
---
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/pruning/PartitionPruningMetadataExtractor.java
+++
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/pruning/PartitionPruningMetadataExtractor.java
@@ -715,7 +715,7 @@ public class PartitionPruningMetadataExtractor extends
IgniteRelShuttle {
private static IntList distributionKeys(IgniteTable table) {
IgniteDistribution distribution = table.distribution();
- if (!distribution.function().affinity()) {
+ if (!distribution.isTableDistribution()) {
return IntArrayList.of();
}
diff --git
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/AbstractIgniteJoin.java
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/AbstractIgniteJoin.java
index 9cfe5f055a0..9f9eee74586 100644
---
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/AbstractIgniteJoin.java
+++
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/AbstractIgniteJoin.java
@@ -49,6 +49,7 @@ import org.apache.calcite.util.mapping.Mappings;
import org.apache.ignite.internal.sql.engine.rel.explain.IgniteRelWriter;
import org.apache.ignite.internal.sql.engine.trait.DistributionFunction;
import org.apache.ignite.internal.sql.engine.trait.IgniteDistribution;
+import org.apache.ignite.internal.sql.engine.trait.IgniteDistributions;
import org.apache.ignite.internal.sql.engine.trait.TraitUtils;
import org.apache.ignite.internal.sql.engine.trait.TraitsAwareIgniteRel;
import org.apache.ignite.internal.sql.engine.util.Commons;
@@ -200,7 +201,7 @@ public abstract class AbstractIgniteJoin extends Join
implements TraitsAwareIgni
RelTraitSet nodeTraits,
List<RelTraitSet> inputTraits
) {
- // Tere are several rules:
+ // There are several rules:
// 1) any join is possible on broadcast or single distribution
// 2) hash distributed join is possible when join keys equal to source
distribution keys
// 3) hash and broadcast distributed tables can be joined when join
keys equal to hash
@@ -230,15 +231,17 @@ public abstract class AbstractIgniteJoin extends Join
implements TraitsAwareIgni
// We cannot provide random distribution without unique
constraint on join keys,
// so, we require hash distribution (wich satisfies random
distribution) instead.
- DistributionFunction function = distrType == HASH_DISTRIBUTED
- ? distribution.function()
- : DistributionFunction.hash();
-
- IgniteDistribution outDistr = hash(joinInfo.leftKeys,
function);
+ IgniteDistribution outDistr = distrType == HASH_DISTRIBUTED
+ ? IgniteDistributions.clone(distribution,
joinInfo.leftKeys)
+ : hash(joinInfo.leftKeys);
if (distrType != HASH_DISTRIBUTED ||
outDistr.satisfies(distribution)) {
+ IgniteDistribution rightDistribution = distrType ==
HASH_DISTRIBUTED
+ ? IgniteDistributions.clone(distribution,
joinInfo.rightKeys)
+ : hash(joinInfo.rightKeys);
+
return Pair.of(nodeTraits.replace(outDistr),
- List.of(left.replace(outDistr),
right.replace(hash(joinInfo.rightKeys, function))));
+ List.of(left.replace(outDistr),
right.replace(rightDistribution)));
}
break;
diff --git
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/IgniteProject.java
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/IgniteProject.java
index 0232cd8f47f..9b5c6d599fd 100644
---
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/IgniteProject.java
+++
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/IgniteProject.java
@@ -20,7 +20,6 @@ package org.apache.ignite.internal.sql.engine.rel;
import static org.apache.calcite.rel.RelDistribution.Type.HASH_DISTRIBUTED;
import static
org.apache.ignite.internal.sql.engine.sql.fun.IgniteSqlOperatorTable.RAND_UUID;
import static
org.apache.ignite.internal.sql.engine.trait.IgniteDistributions.broadcast;
-import static
org.apache.ignite.internal.sql.engine.trait.IgniteDistributions.hash;
import static
org.apache.ignite.internal.sql.engine.trait.IgniteDistributions.single;
import static
org.apache.ignite.internal.sql.engine.trait.TraitUtils.changeTraits;
@@ -54,6 +53,7 @@ import org.apache.calcite.util.mapping.Mappings;
import org.apache.ignite.internal.sql.engine.metadata.cost.IgniteCost;
import org.apache.ignite.internal.sql.engine.rel.explain.IgniteRelWriter;
import org.apache.ignite.internal.sql.engine.trait.IgniteDistribution;
+import org.apache.ignite.internal.sql.engine.trait.IgniteDistributions;
import org.apache.ignite.internal.sql.engine.trait.TraitUtils;
import org.apache.ignite.internal.sql.engine.trait.TraitsAwareIgniteRel;
@@ -130,7 +130,7 @@ public class IgniteProject extends Project implements
TraitsAwareIgniteRel {
}
if (srcKeys.size() == keys.size()) {
- return Pair.of(nodeTraits,
List.of(in.replace(hash(ImmutableIntList.of(srcKeys.elements()),
distribution.function()))));
+ return Pair.of(nodeTraits,
List.of(in.replace(IgniteDistributions.clone(distribution, srcKeys))));
}
return Pair.of(nodeTraits.replace(single()),
List.of(in.replace(single())));
diff --git
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/explain/RelTreeToTextWriter.java
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/explain/RelTreeToTextWriter.java
index 5ff24e62a5a..a6eb1dc0dab 100644
---
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/explain/RelTreeToTextWriter.java
+++
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/explain/RelTreeToTextWriter.java
@@ -49,7 +49,6 @@ import org.apache.calcite.util.ImmutableBitSet;
import org.apache.ignite.internal.sql.engine.prepare.bounds.SearchBounds;
import org.apache.ignite.internal.sql.engine.rel.IgniteRel;
import org.apache.ignite.internal.sql.engine.schema.IgniteIndex;
-import
org.apache.ignite.internal.sql.engine.trait.DistributionFunction.AffinityDistribution;
import org.apache.ignite.internal.sql.engine.trait.IgniteDistribution;
import org.apache.ignite.internal.sql.engine.util.Commons;
import org.apache.ignite.lang.util.IgniteNameUtils;
@@ -436,11 +435,7 @@ class RelTreeToTextWriter {
private static String beautifyDistribution(IgniteDistribution
distribution, RelDataType rowType) {
StringBuilder sb = new StringBuilder();
- if (distribution.function().affinity()) {
- sb.append(((AffinityDistribution)
distribution.function()).label());
- } else {
- sb.append(distribution.function().name());
- }
+ sb.append(distribution.label());
if (!distribution.getKeys().isEmpty()) {
sb.append(" by [");
diff --git
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/trait/DistributionFunction.java
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/trait/DistributionFunction.java
index 13292655ced..980e19c8ccf 100644
---
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/trait/DistributionFunction.java
+++
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/trait/DistributionFunction.java
@@ -48,14 +48,6 @@ public abstract class DistributionFunction {
return name = name0().intern();
}
- public boolean affinity() {
- return false;
- }
-
- public static DistributionFunction affinity(int tableId, int zoneId,
String label) {
- return new AffinityDistribution(tableId, zoneId, label);
- }
-
/**
* Get function name. This name used for equality checking and in {@link
RelNode#getDigest()}.
*/
@@ -109,19 +101,6 @@ public abstract class DistributionFunction {
return IdentityDistribution.INSTANCE;
}
- /**
- * Satisfy.
- * TODO Documentation https://issues.apache.org/jira/browse/IGNITE-15859
- */
- public static boolean satisfy(DistributionFunction f0,
DistributionFunction f1) {
- if (f0 == f1 || f0.name() == f1.name()) { //
NOPMD.UseEqualsToCompareStrings
- return true;
- }
-
- return f0 instanceof AffinityDistribution && f1 instanceof
AffinityDistribution
- && Objects.equals(((AffinityDistribution) f0).zoneId(),
((AffinityDistribution) f1).zoneId());
- }
-
private static final class AnyDistribution extends DistributionFunction {
public static final DistributionFunction INSTANCE = new
AnyDistribution();
@@ -174,55 +153,6 @@ public abstract class DistributionFunction {
public RelDistribution.Type type() {
return RelDistribution.Type.HASH_DISTRIBUTED;
}
-
- }
-
- /**
- * Affinity distribution.
- */
- public static final class AffinityDistribution extends HashDistribution {
- private final int tableId;
-
- private final int zoneId;
-
- private final String label;
-
- /**
- * Constructor.
- *
- * @param tableId Table ID.
- * @param zoneId Distribution zone ID.
- * @param label Human-readable label to show in EXPLAIN printout.
- */
- private AffinityDistribution(int tableId, int zoneId, String label) {
- this.zoneId = zoneId;
- this.tableId = tableId;
- this.label = label;
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean affinity() {
- return true;
- }
-
- public int tableId() {
- return tableId;
- }
-
- public int zoneId() {
- return zoneId;
- }
-
- public String label() {
- return label;
- }
-
- /** {@inheritDoc} */
- @Override
- protected String name0() {
- return "affinity[tableId=" + tableId + ", zoneId=" + zoneId + ']';
- }
}
/**
diff --git
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/trait/DistributionTrait.java
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/trait/DistributionTrait.java
index 23be8bea2e6..cdb29d3088a 100644
---
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/trait/DistributionTrait.java
+++
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/trait/DistributionTrait.java
@@ -65,8 +65,16 @@ public final class DistributionTrait implements
IgniteDistribution {
private final ImmutableIntList keys;
+ private final boolean affinityFlag;
+
+ private final int tableId;
+
+ private final int zoneId;
+
+ private final String label;
+
/**
- * Constructor.
+ * Constructor non-hash distributions.
*
* @param function Distribution function.
*/
@@ -76,17 +84,48 @@ public final class DistributionTrait implements
IgniteDistribution {
this.function = function;
keys = ImmutableIntList.of();
+ affinityFlag = false;
+ tableId = -1;
+ zoneId = -1;
+ label = function.name();
}
/**
- * Constructor.
+ * Constructor for hash distribution.
*
* @param keys Distribution keys.
* @param function Distribution function.
*/
DistributionTrait(List<Integer> keys, DistributionFunction function) {
+ this(keys, -1, -1, function.name(), function, false);
+ }
+
+ /**
+ * Constructor for affinity distribution.
+ *
+ * @param keys Distribution keys.
+ * @param function Distribution function.
+ */
+ DistributionTrait(List<Integer> keys, int tableId, int zoneId, String
label, DistributionFunction function) {
+ this(keys, tableId, zoneId, label, function, true);
+ }
+
+ private DistributionTrait(
+ List<Integer> keys,
+ int tableId,
+ int zoneId,
+ String label,
+ DistributionFunction function,
+ boolean affinityFlag
+ ) {
+ assert function.type() == HASH_DISTRIBUTED;
+
this.keys = ImmutableIntList.copyOf(keys);
this.function = function;
+ this.tableId = tableId;
+ this.zoneId = zoneId;
+ this.label = label;
+ this.affinityFlag = affinityFlag;
}
/** {@inheritDoc} */
@@ -107,6 +146,26 @@ public final class DistributionTrait implements
IgniteDistribution {
return keys;
}
+ @Override
+ public boolean isTableDistribution() {
+ return affinityFlag;
+ }
+
+ @Override
+ public int tableId() {
+ return tableId;
+ }
+
+ @Override
+ public int zoneId() {
+ return zoneId;
+ }
+
+ @Override
+ public String label() {
+ return label;
+ }
+
/** {@inheritDoc} */
@Override
public void register(RelOptPlanner planner) {
@@ -122,7 +181,12 @@ public final class DistributionTrait implements
IgniteDistribution {
if (o instanceof DistributionTrait) {
DistributionTrait that = (DistributionTrait) o;
- return Objects.equals(function, that.function) &&
Objects.equals(keys, that.keys);
+ return Objects.equals(function, that.function)
+ && Objects.equals(keys, that.keys)
+ && affinityFlag == that.affinityFlag
+ && tableId == that.tableId
+ && zoneId == that.zoneId
+ && Objects.equals(label, that.label);
}
return false;
@@ -131,13 +195,15 @@ public final class DistributionTrait implements
IgniteDistribution {
/** {@inheritDoc} */
@Override
public int hashCode() {
- return Objects.hash(function, keys);
+ return Objects.hash(function, keys, zoneId, tableId);
}
/** {@inheritDoc} */
@Override
public String toString() {
- return function.name() + (function.type() == HASH_DISTRIBUTED ? keys :
"");
+ return function.name()
+ + (function.type() == HASH_DISTRIBUTED ? keys : "")
+ + (isTableDistribution() ? "[zoneId=" + zoneId + ", tableId="
+ tableId + ']' : "");
}
/** {@inheritDoc} */
@@ -166,7 +232,9 @@ public final class DistributionTrait implements
IgniteDistribution {
if (getType() == other.getType()) {
return getType() != HASH_DISTRIBUTED
|| (Objects.equals(keys, other.keys)
- && DistributionFunction.satisfy(function, other.function));
+ && affinityFlag == other.affinityFlag
+ && zoneId == other.zoneId
+ && Objects.equals(function, other.function));
}
if (other.getType() == RANDOM_DISTRIBUTED) {
@@ -191,7 +259,9 @@ public final class DistributionTrait implements
IgniteDistribution {
List<Integer> res = Mappings.apply2((Mapping) mapping, keys);
- return IgniteDistributions.hash(ImmutableIntList.copyOf(res),
function);
+ return affinityFlag
+ ? IgniteDistributions.affinity(res, tableId, zoneId, label)
+ : IgniteDistributions.hash(res, function);
}
/** {@inheritDoc} */
@@ -212,6 +282,22 @@ public final class DistributionTrait implements
IgniteDistribution {
cmp =
function.name().compareTo(distribution.function().name());
}
+ if (cmp == 0) {
+ cmp = Boolean.compare(affinityFlag,
distribution.isTableDistribution());
+ }
+
+ if (cmp == 0 && affinityFlag) {
+ cmp = Integer.compare(zoneId, distribution.zoneId());
+
+ if (cmp == 0) {
+ cmp = Integer.compare(tableId, distribution.tableId());
+ }
+
+ if (cmp == 0) {
+ cmp = label.compareTo(distribution.label());
+ }
+ }
+
return cmp;
}
diff --git
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/trait/IgniteDistribution.java
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/trait/IgniteDistribution.java
index f38be86972a..3ab7695f134 100644
---
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/trait/IgniteDistribution.java
+++
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/trait/IgniteDistribution.java
@@ -30,6 +30,18 @@ public interface IgniteDistribution extends RelDistribution {
*/
DistributionFunction function();
+ /** Returns {@code true} if this is table distribution, {@code false}
otherwise. */
+ boolean isTableDistribution();
+
+ /** Returns zone id of table distribution. */
+ int zoneId();
+
+ /** Returns table id of table distribution. */
+ int tableId();
+
+ /** Returns distribution function label for EXPLAIN plan purposes. */
+ String label();
+
/** {@inheritDoc} */
@Override
ImmutableIntList getKeys();
diff --git
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/trait/IgniteDistributions.java
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/trait/IgniteDistributions.java
index 4fadbfbed90..4a28b59630d 100644
---
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/trait/IgniteDistributions.java
+++
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/trait/IgniteDistributions.java
@@ -21,6 +21,7 @@ import static
org.apache.ignite.internal.util.CollectionUtils.nullOrEmpty;
import java.util.List;
import org.apache.calcite.plan.RelTraitDef;
+import org.apache.calcite.rel.RelDistribution.Type;
import org.apache.calcite.util.ImmutableIntList;
/**
@@ -75,7 +76,9 @@ public class IgniteDistributions {
* @return Affinity distribution.
*/
public static IgniteDistribution affinity(List<Integer> keys, int tableId,
int zoneId, String label) {
- return hash(keys, DistributionFunction.affinity(tableId, zoneId,
label));
+ assert !nullOrEmpty(keys) : "Hash-based distribution must have at
least one key";
+
+ return canonize(new DistributionTrait(keys, tableId, zoneId, label,
DistributionFunction.hash()));
}
/**
@@ -98,7 +101,7 @@ public class IgniteDistributions {
public static IgniteDistribution hash(List<Integer> keys,
DistributionFunction function) {
assert !nullOrEmpty(keys) : "Hash-based distribution must have at
least one key";
- return canonize(new DistributionTrait(ImmutableIntList.copyOf(keys),
function));
+ return canonize(new DistributionTrait(keys, function));
}
/**
@@ -111,6 +114,24 @@ public class IgniteDistributions {
return canonize(new DistributionTrait(ImmutableIntList.of(key),
DistributionFunction.identity()));
}
+ /**
+ * Creates a distribution trait of the same hash function with given
distribution keys.
+ *
+ * @param trait Distribution trait.
+ * @param keys Distribution keys ordinals. Should not be null or empty.
+ * @return Distribution trait.
+ */
+ public static IgniteDistribution clone(IgniteDistribution trait,
List<Integer> keys) {
+ assert !nullOrEmpty(keys) : "Hash-based distribution must have at
least one key";
+ assert trait.function().type() == Type.HASH_DISTRIBUTED;
+
+ DistributionTrait distributionTrait = trait.isTableDistribution()
+ ? new DistributionTrait(keys, trait.tableId(), trait.zoneId(),
trait.label(), trait.function())
+ : new DistributionTrait(keys, trait.function());
+
+ return canonize(distributionTrait);
+ }
+
/**
* See {@link RelTraitDef#canonize(org.apache.calcite.plan.RelTrait)}.
*/
diff --git
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/IdentityDistributionFunctionSelfTest.java
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/IdentityDistributionFunctionSelfTest.java
index 72fad396b0d..18643885bce 100644
---
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/IdentityDistributionFunctionSelfTest.java
+++
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/IdentityDistributionFunctionSelfTest.java
@@ -21,7 +21,6 @@ import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf;
-import static org.hamcrest.Matchers.is;
import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
import it.unimi.dsi.fastutil.longs.LongList;
@@ -65,7 +64,6 @@ public class IdentityDistributionFunctionSelfTest {
IdentityDistribution function = new IdentityDistribution();
assertThat(function.type(), equalTo(Type.HASH_DISTRIBUTED));
- assertThat(function.affinity(), is(false));
assertThat(function.name(), equalTo("identity"));
}
diff --git
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/mapping/FragmentMappingTest.java
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/mapping/FragmentMappingTest.java
index 7eb5c0233ea..fb8d61a3cc8 100644
---
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/mapping/FragmentMappingTest.java
+++
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/mapping/FragmentMappingTest.java
@@ -48,7 +48,6 @@ import org.apache.ignite.internal.sql.engine.rel.IgniteRel;
import org.apache.ignite.internal.sql.engine.schema.IgniteDataSource;
import org.apache.ignite.internal.sql.engine.schema.IgniteSchema;
import org.apache.ignite.internal.sql.engine.schema.IgniteTable;
-import
org.apache.ignite.internal.sql.engine.trait.DistributionFunction.AffinityDistribution;
import
org.apache.ignite.internal.sql.engine.trait.DistributionFunction.IdentityDistribution;
import org.apache.ignite.internal.sql.engine.trait.IgniteDistribution;
import org.apache.ignite.internal.sql.engine.trait.IgniteDistributions;
@@ -392,7 +391,7 @@ public class FragmentMappingTest extends
AbstractPlannerTest {
}
IgniteDistribution distributionToUse;
- if (distribution.function() instanceof AffinityDistribution) {
+ if (distribution.isTableDistribution()) {
distributionToUse = TestBuilders.affinity(0, objectId,
objectId);
} else {
distributionToUse = distribution;
diff --git
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/mapping/FragmentPrinter.java
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/mapping/FragmentPrinter.java
index f03bfc42ab0..ebda1421dad 100644
---
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/mapping/FragmentPrinter.java
+++
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/mapping/FragmentPrinter.java
@@ -45,7 +45,6 @@ import
org.apache.ignite.internal.sql.engine.rel.IgniteTableScan;
import org.apache.ignite.internal.sql.engine.schema.IgniteDataSource;
import org.apache.ignite.internal.sql.engine.schema.IgniteTable;
import org.apache.ignite.internal.sql.engine.schema.TableDescriptor;
-import
org.apache.ignite.internal.sql.engine.trait.DistributionFunction.AffinityDistribution;
import org.apache.ignite.internal.sql.engine.trait.IgniteDistribution;
/**
@@ -320,9 +319,8 @@ final class FragmentPrinter extends IgniteRelShuttle {
}
private static String formatDistribution(IgniteDistribution distribution,
TableDescriptorCollector collector) {
- if (distribution.function() instanceof AffinityDistribution) {
- AffinityDistribution f = (AffinityDistribution)
distribution.function();
- IgniteTable igniteTable = collector.tables.get(f.tableId());
+ if (distribution.isTableDistribution()) {
+ IgniteTable igniteTable =
collector.tables.get(distribution.tableId());
if (igniteTable == null) {
String error = format("Unknown tableId: {}. Existing: {}",
collector.tables.keySet());
diff --git
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/framework/TestBuilders.java
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/framework/TestBuilders.java
index fff710fe71f..4cf2692f115 100644
---
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/framework/TestBuilders.java
+++
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/framework/TestBuilders.java
@@ -132,7 +132,6 @@ import
org.apache.ignite.internal.sql.engine.schema.TableDescriptor;
import org.apache.ignite.internal.sql.engine.schema.TableDescriptorImpl;
import org.apache.ignite.internal.sql.engine.sql.ParserServiceImpl;
import org.apache.ignite.internal.sql.engine.statistic.SqlStatisticManager;
-import org.apache.ignite.internal.sql.engine.trait.DistributionFunction;
import org.apache.ignite.internal.sql.engine.trait.IgniteDistribution;
import org.apache.ignite.internal.sql.engine.trait.IgniteDistributions;
import org.apache.ignite.internal.sql.engine.util.Commons;
@@ -354,10 +353,7 @@ public class TestBuilders {
* @return Affinity distribution.
*/
public static IgniteDistribution affinity(int key, int tableId, int
zoneId) {
- return IgniteDistributions.hash(
- ImmutableIntList.of(key),
- DistributionFunction.affinity(tableId, zoneId,
affinityDistributionLabel(tableId, zoneId))
- );
+ return affinity(ImmutableIntList.of(key), tableId, zoneId);
}
/**
diff --git
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/JoinColocationPlannerTest.java
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/JoinColocationPlannerTest.java
index 60f3077b6d7..1d36e7dcdef 100644
---
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/JoinColocationPlannerTest.java
+++
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/JoinColocationPlannerTest.java
@@ -68,7 +68,7 @@ public class JoinColocationPlannerTest extends
AbstractPlannerTest {
String invalidPlanMsg = "Invalid plan:\n" + RelOptUtil.toString(phys);
assertThat(invalidPlanMsg, join, notNullValue());
- assertThat(invalidPlanMsg, join.distribution().function().affinity(),
is(true));
+ assertThat(invalidPlanMsg, join.distribution().isTableDistribution(),
is(true));
assertThat(invalidPlanMsg, join.getLeft(),
instanceOf(IgniteIndexScan.class));
assertThat(invalidPlanMsg, join.getRight(),
instanceOf(IgniteIndexScan.class));
}
@@ -96,7 +96,7 @@ public class JoinColocationPlannerTest extends
AbstractPlannerTest {
assertThat(invalidPlanMsg, joinNodes.size(), equalTo(1));
assertThat(invalidPlanMsg, join, notNullValue());
- assertThat(invalidPlanMsg, join.distribution().function().affinity(),
is(true));
+ assertThat(invalidPlanMsg, join.distribution().isTableDistribution(),
is(true));
}
/**
@@ -120,7 +120,7 @@ public class JoinColocationPlannerTest extends
AbstractPlannerTest {
String invalidPlanMsg = "Invalid plan:\n" + RelOptUtil.toString(phys);
assertThat(invalidPlanMsg, join, notNullValue());
- assertThat(invalidPlanMsg, join.distribution().function().affinity(),
is(true));
+ assertThat(invalidPlanMsg, join.distribution().isTableDistribution(),
is(true));
if (!"MergeJoinConverter".equals(disabledRule)) {
assertThat(invalidPlanMsg, join.getLeft(),
instanceOf(IgniteIndexScan.class));
@@ -150,7 +150,7 @@ public class JoinColocationPlannerTest extends
AbstractPlannerTest {
String invalidPlanMsg = "Invalid plan:\n" + RelOptUtil.toString(phys);
assertThat(invalidPlanMsg, join, notNullValue());
- assertThat(invalidPlanMsg, join.distribution().function().affinity(),
is(true));
+ assertThat(invalidPlanMsg, join.distribution().isTableDistribution(),
is(true));
if (!"MergeJoinConverter".equals(disabledRule)) {
assertThat(invalidPlanMsg, join.getLeft(),
instanceOf(IgniteIndexScan.class));
@@ -180,7 +180,7 @@ public class JoinColocationPlannerTest extends
AbstractPlannerTest {
String invalidPlanMsg = "Invalid plan:\n" + RelOptUtil.toString(phys);
assertThat(invalidPlanMsg, join, notNullValue());
- assertThat(invalidPlanMsg, join.distribution().function().affinity(),
is(false));
+ assertThat(invalidPlanMsg, join.distribution().isTableDistribution(),
is(false));
}
/**
diff --git
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/schema/SqlSchemaManagerImplTest.java
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/schema/SqlSchemaManagerImplTest.java
index 4b73b5f81ac..f1c8dc4181b 100644
---
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/schema/SqlSchemaManagerImplTest.java
+++
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/schema/SqlSchemaManagerImplTest.java
@@ -82,7 +82,6 @@ import org.apache.ignite.internal.hlc.HybridClockImpl;
import org.apache.ignite.internal.lang.IgniteInternalException;
import org.apache.ignite.internal.manager.ComponentContext;
import org.apache.ignite.internal.schema.DefaultValueGenerator;
-import org.apache.ignite.internal.sql.engine.framework.TestBuilders;
import org.apache.ignite.internal.sql.engine.schema.IgniteIndex.Type;
import org.apache.ignite.internal.sql.engine.statistic.SqlStatisticManager;
import org.apache.ignite.internal.sql.engine.trait.IgniteDistribution;
@@ -474,30 +473,33 @@ public class SqlSchemaManagerImplTest extends
BaseIgniteAbstractTest {
IgniteTable table = getTable(unwrapSchema(schemaPlus), "T1");
IgniteDistribution distribution =
table.descriptor().distribution();
- assertThat(distribution, equalTo(TestBuilders.affinity(
+ assertThat(distribution, equalTo(IgniteDistributions.affinity(
List.of(1),
table.id(),
- enabledColocation() ? table.zoneId() : table.id())));
+ enabledColocation() ? table.zoneId() : table.id(),
+ "table PUBLIC.T1 in zone \"Default\"")));
}
{
IgniteTable table = getTable(unwrapSchema(schemaPlus), "T2");
IgniteDistribution distribution =
table.descriptor().distribution();
- assertThat(distribution, equalTo(TestBuilders.affinity(
+ assertThat(distribution, equalTo(IgniteDistributions.affinity(
List.of(3, 1),
table.id(),
- enabledColocation() ? table.zoneId() : table.id())));
+ enabledColocation() ? table.zoneId() : table.id(),
+ "table PUBLIC.T2 in zone \"Default\"")));
}
{
IgniteTable table = getTable(unwrapSchema(schemaPlus), "T3");
IgniteDistribution distribution =
table.descriptor().distribution();
- assertThat(distribution, equalTo(TestBuilders.affinity(
+ assertThat(distribution, equalTo(IgniteDistributions.affinity(
List.of(2, 1, 0),
table.id(),
- enabledColocation() ? table.zoneId() : table.id())));
+ enabledColocation() ? table.zoneId() : table.id(),
+ "table PUBLIC.T3 in zone \"Default\"")));
}
}