You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by gv...@apache.org on 2020/04/30 14:26:46 UTC
[ignite] branch ignite-12248 updated: IGNITE-12972: Calcite
integration. Serialization refactoring. This closes #7764
This is an automated email from the ASF dual-hosted git repository.
gvvinblade pushed a commit to branch ignite-12248
in repository https://gitbox.apache.org/repos/asf/ignite.git
The following commit(s) were added to refs/heads/ignite-12248 by this push:
new 6e306e4 IGNITE-12972: Calcite integration. Serialization refactoring. This closes #7764
6e306e4 is described below
commit 6e306e416e715de454240e93e275afa083ae5bba
Author: Igor Seliverstov <gv...@gmail.com>
AuthorDate: Thu Apr 30 17:26:26 2020 +0300
IGNITE-12972: Calcite integration. Serialization refactoring. This closes #7764
---
.../query/calcite/exec/ExchangeServiceImpl.java | 4 +-
.../query/calcite/exec/ExecutionContext.java | 47 +-
.../query/calcite/exec/ExecutionServiceImpl.java | 77 +-
.../query/calcite/exec/LogicalRelImplementor.java | 46 +-
.../query/calcite/exec/PhysicalRelImplementor.java | 251 ------
.../processors/query/calcite/exec/exp/Call.java | 118 ---
.../query/calcite/exec/exp/CallOperation.java | 27 -
.../query/calcite/exec/exp/DynamicParam.java | 63 --
.../query/calcite/exec/exp/ExpToRexTranslator.java | 116 ---
.../query/calcite/exec/exp/Expression.java | 58 --
.../query/calcite/exec/exp/ExpressionFactory.java | 224 +-----
.../query/calcite/exec/exp/ExpressionVisitor.java | 51 --
.../query/calcite/exec/exp/InputRef.java | 63 --
.../processors/query/calcite/exec/exp/Literal.java | 63 --
.../query/calcite/exec/exp/RexToExpTranslator.java | 151 ----
.../query/calcite/exec/exp/agg/AggCallExp.java | 178 -----
.../calcite/exec/exp/agg/WrappersFactoryImpl.java | 4 +-
.../query/calcite/exec/exp/type/BasicType.java | 152 ----
.../calcite/exec/exp/type/CharacterDataType.java | 32 -
.../query/calcite/exec/exp/type/CharacterType.java | 142 ----
.../query/calcite/exec/exp/type/DataType.java | 89 ---
.../query/calcite/exec/exp/type/JavaType.java | 84 --
.../query/calcite/exec/exp/type/StructType.java | 100 ---
.../query/calcite/externalize/RelJson.java | 871 +++++++++++++++++++++
.../query/calcite/externalize/RelJsonReader.java | 310 ++++++++
.../query/calcite/externalize/RelJsonWriter.java | 161 ++++
.../query/calcite/message/MessageType.java | 10 +-
.../query/calcite/message/QueryStartRequest.java | 80 +-
.../query/calcite/metadata/FragmentInfo.java | 141 ----
...FragmentInfo.java => IgniteMdNodesMapping.java} | 96 ++-
.../query/calcite/metadata/IgniteMetadata.java | 14 +-
.../query/calcite/metadata/NodesMapping.java | 137 +++-
.../query/calcite/metadata/RelMetadataQueryEx.java | 14 +-
.../calcite/prepare/AbstractMultiStepPlan.java | 76 +-
.../processors/query/calcite/prepare/Cloner.java | 67 +-
.../processors/query/calcite/prepare/Fragment.java | 102 +--
.../FragmentDescription.java} | 196 ++---
.../query/calcite/prepare/FragmentSplitter.java | 336 +++-----
.../query/calcite/prepare/MultiStepDmlPlan.java | 2 +-
.../query/calcite/prepare/MultiStepPlan.java | 15 +
.../query/calcite/prepare/MultiStepQueryPlan.java | 2 +-
.../query/calcite/prepare/RelTarget.java | 42 -
.../query/calcite/prepare/RelTargetAware.java | 28 -
.../query/calcite/prepare/RelTargetImpl.java | 50 --
.../processors/query/calcite/prepare/Splitter.java | 112 ++-
.../query/calcite/rel/IgniteAggregate.java | 7 +
.../query/calcite/rel/IgniteExchange.java | 12 +
.../processors/query/calcite/rel/IgniteFilter.java | 6 +
.../processors/query/calcite/rel/IgniteJoin.java | 22 +
.../query/calcite/rel/IgniteMapAggregate.java | 6 +
.../query/calcite/rel/IgniteProject.java | 6 +
.../query/calcite/rel/IgniteReceiver.java | 61 +-
.../query/calcite/rel/IgniteReduceAggregate.java | 15 +
.../processors/query/calcite/rel/IgniteSender.java | 93 ++-
.../query/calcite/rel/IgniteTableModify.java | 33 +-
.../query/calcite/rel/IgniteTableScan.java | 7 +
.../query/calcite/rel/IgniteTrimExchange.java | 44 +-
.../query/calcite/rel/IgniteUnionAll.java | 9 +
.../processors/query/calcite/rel/IgniteValues.java | 7 +
.../calcite/rule/TableModifyConverterRule.java | 2 +-
.../calcite/serialize/AggregatePhysicalRel.java | 108 ---
.../query/calcite/serialize/FilterPhysicalRel.java | 84 --
.../query/calcite/serialize/JoinPhysicalRel.java | 94 ---
.../query/calcite/serialize/PhysicalRel.java | 33 -
.../calcite/serialize/PhysicalRelVisitor.java | 86 --
.../calcite/serialize/ProjectPhysicalRel.java | 99 ---
.../calcite/serialize/ReceiverPhysicalRel.java | 154 ----
.../calcite/serialize/RelToPhysicalConverter.java | 203 -----
.../query/calcite/serialize/SenderPhysicalRel.java | 98 ---
.../calcite/serialize/TableModifyPhysicalRel.java | 117 ---
.../calcite/serialize/TableScanPhysicalRel.java | 73 --
.../calcite/serialize/TrimExchangePhysicalRel.java | 94 ---
.../calcite/serialize/UnionAllPhysicalRel.java | 67 --
.../query/calcite/serialize/ValuesPhysicalRel.java | 79 --
.../query/calcite/trait/DistributionFunction.java | 5 +
.../query/calcite/trait/DistributionTraitDef.java | 2 +-
.../processors/query/calcite/util/Commons.java | 182 ++++-
.../query/calcite/util/IgniteMethod.java | 6 +-
.../processors/query/calcite/PlannerTest.java | 169 +++-
.../calcite/exec/ExpressionEvaluationTest.java | 73 --
.../calcite/exec/rel/AbstractExecutionTest.java | 4 +-
.../query/calcite/jdbc/JdbcQueryTest.java | 2 +
82 files changed, 2699 insertions(+), 4465 deletions(-)
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/ExchangeServiceImpl.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/ExchangeServiceImpl.java
index bac38b0..40e2ebb 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/ExchangeServiceImpl.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/ExchangeServiceImpl.java
@@ -31,6 +31,7 @@ import org.apache.ignite.internal.processors.query.calcite.message.MessageServic
import org.apache.ignite.internal.processors.query.calcite.message.MessageType;
import org.apache.ignite.internal.processors.query.calcite.message.QueryBatchAcknowledgeMessage;
import org.apache.ignite.internal.processors.query.calcite.message.QueryBatchMessage;
+import org.apache.ignite.internal.processors.query.calcite.prepare.FragmentDescription;
import org.apache.ignite.internal.processors.query.calcite.prepare.PlanningContext;
import org.apache.ignite.internal.processors.query.calcite.util.AbstractService;
import org.apache.ignite.internal.processors.query.calcite.util.Commons;
@@ -188,6 +189,7 @@ public class ExchangeServiceImpl extends AbstractService implements ExchangeServ
*/
private ExecutionContext baseInboxContext(UUID queryId, long fragmentId) {
PlanningContext ctx = PlanningContext.builder().logger(log).build();
- return new ExecutionContext(taskExecutor(), ctx, queryId, fragmentId, null, ImmutableMap.of());
+ FragmentDescription fragmentDescription = new FragmentDescription(fragmentId, null, -1, null, null);
+ return new ExecutionContext(taskExecutor(), ctx, queryId, fragmentDescription, ImmutableMap.of());
}
}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/ExecutionContext.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/ExecutionContext.java
index 6381d7f..9733bd3 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/ExecutionContext.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/ExecutionContext.java
@@ -17,12 +17,15 @@
package org.apache.ignite.internal.processors.query.calcite.exec;
+import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.apache.calcite.DataContext;
import org.apache.calcite.linq4j.QueryProvider;
import org.apache.calcite.schema.SchemaPlus;
import org.apache.ignite.internal.processors.cache.mvcc.MvccSnapshot;
+import org.apache.ignite.internal.processors.query.calcite.metadata.NodesMapping;
+import org.apache.ignite.internal.processors.query.calcite.prepare.FragmentDescription;
import org.apache.ignite.internal.processors.query.calcite.prepare.PlanningContext;
import org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeFactory;
@@ -34,13 +37,10 @@ public class ExecutionContext implements DataContext {
private final UUID queryId;
/** */
- private final long fragmentId;
-
- /** */
private final PlanningContext ctx;
/** */
- private final int[] parts;
+ private final FragmentDescription fragmentDescription;
/** */
private final Map<String, Object> params;
@@ -54,17 +54,16 @@ public class ExecutionContext implements DataContext {
/**
* @param ctx Parent context.
* @param queryId Query ID.
- * @param fragmentId Fragment ID.
- * @param parts Partitions.
+ * @param fragmentDescription Partitions information.
* @param params Parameters.
*/
- public ExecutionContext(QueryTaskExecutor executor, PlanningContext ctx, UUID queryId, long fragmentId, int[] parts, Map<String, Object> params) {
+ public ExecutionContext(QueryTaskExecutor executor, PlanningContext ctx, UUID queryId,
+ FragmentDescription fragmentDescription, Map<String, Object> params) {
this.executor = executor;
+ this.ctx = ctx;
this.queryId = queryId;
- this.fragmentId = fragmentId;
- this.parts = parts;
+ this.fragmentDescription = fragmentDescription;
this.params = params;
- this.ctx = ctx;
}
/**
@@ -85,14 +84,36 @@ public class ExecutionContext implements DataContext {
* @return Fragment ID.
*/
public long fragmentId() {
- return fragmentId;
+ return fragmentDescription.fragmentId();
}
/**
* @return Interested partitions.
*/
public int[] partitions() {
- return parts;
+ return fragmentDescription.partitions();
+ }
+
+ /** */
+ public int partitionsCount () {
+ return fragmentDescription.partitionsCount();
+ }
+
+ /**
+ * @return Target mapping.
+ */
+ public NodesMapping targetMapping() {
+ return fragmentDescription.targetMapping();
+ }
+
+ /** */
+ public List<UUID> remoteSources(long exchangeId) {
+ return fragmentDescription.remoteSources().get(exchangeId);
+ }
+
+ /** */
+ public FragmentDescription fragmentDescription() {
+ return fragmentDescription;
}
/**
@@ -157,6 +178,6 @@ public class ExecutionContext implements DataContext {
* @param task Query task.
*/
public void execute(Runnable task) {
- executor.execute(queryId, fragmentId, task);
+ executor.execute(queryId, fragmentId(), task);
}
}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/ExecutionServiceImpl.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/ExecutionServiceImpl.java
index 00c39c4..6d14305 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/ExecutionServiceImpl.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/ExecutionServiceImpl.java
@@ -74,6 +74,7 @@ import org.apache.ignite.internal.processors.query.calcite.metadata.PartitionSer
import org.apache.ignite.internal.processors.query.calcite.prepare.CacheKey;
import org.apache.ignite.internal.processors.query.calcite.prepare.CalciteQueryFieldMetadata;
import org.apache.ignite.internal.processors.query.calcite.prepare.Fragment;
+import org.apache.ignite.internal.processors.query.calcite.prepare.FragmentDescription;
import org.apache.ignite.internal.processors.query.calcite.prepare.IgnitePlanner;
import org.apache.ignite.internal.processors.query.calcite.prepare.MultiStepDmlPlan;
import org.apache.ignite.internal.processors.query.calcite.prepare.MultiStepPlan;
@@ -87,8 +88,6 @@ import org.apache.ignite.internal.processors.query.calcite.prepare.ValidationRes
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteConvention;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteRel;
import org.apache.ignite.internal.processors.query.calcite.schema.SchemaHolder;
-import org.apache.ignite.internal.processors.query.calcite.serialize.RelToPhysicalConverter;
-import org.apache.ignite.internal.processors.query.calcite.serialize.SenderPhysicalRel;
import org.apache.ignite.internal.processors.query.calcite.trait.DistributionTraitDef;
import org.apache.ignite.internal.processors.query.calcite.trait.IgniteDistributions;
import org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeFactory;
@@ -591,13 +590,11 @@ public class ExecutionServiceImpl extends AbstractService implements ExecutionSe
List<Fragment> fragments = plan.fragments();
// Local execution
- Fragment local = F.first(fragments);
+ Fragment fragment = F.first(fragments);
+ NodesMapping mapping = plan.fragmentMapping(fragment);
if (U.assertionsEnabled()) {
- assert local != null;
-
- NodesMapping mapping = local.mapping();
-
+ assert fragment != null;
assert mapping != null;
List<UUID> nodes = mapping.nodes();
@@ -605,45 +602,61 @@ public class ExecutionServiceImpl extends AbstractService implements ExecutionSe
assert nodes != null && nodes.size() == 1 && F.first(nodes).equals(pctx.localNodeId());
}
- ExecutionContext ectx = new ExecutionContext(taskExecutor(), pctx, queryId, local.fragmentId(),
- local.mapping().partitions(pctx.localNodeId()), Commons.parametersMap(pctx.parameters()));
+ FragmentDescription fragmentDescription = new FragmentDescription(
+ fragment.fragmentId(),
+ mapping.partitions(pctx.localNodeId()),
+ mapping.assignments().size(),
+ plan.targetMapping(fragment),
+ plan.remoteSources(fragment)
+ );
- Node<Object[]> node = new LogicalRelImplementor(ectx, partitionService(), mailboxRegistry(), exchangeService(), failureProcessor()).go(local.root());
+ ExecutionContext ectx = new ExecutionContext(
+ taskExecutor(),
+ pctx,
+ queryId,
+ fragmentDescription,
+ Commons.parametersMap(pctx.parameters()));
- assert !(node instanceof SenderPhysicalRel);
+ Node<Object[]> node = new LogicalRelImplementor(ectx, partitionService(), mailboxRegistry(), exchangeService(), failureProcessor()).go(fragment.root());
- QueryInfo info = new QueryInfo(ectx, fragments, node);
+ QueryInfo info = new QueryInfo(ectx, plan, node);
// register query
register(info);
// start remote execution
if (fragments.size() > 1) {
- RelToPhysicalConverter converter = new RelToPhysicalConverter(ectx.getTypeFactory());
-
for (int i = 1; i < fragments.size(); i++) {
- Fragment fragment = fragments.get(i);
+ Fragment fragment0 = fragments.get(i);
+ NodesMapping mapping0 = plan.fragmentMapping(fragment0);
boolean error = false;
- for (UUID nodeId : fragment.mapping().nodes()) {
+ for (UUID nodeId : mapping0.nodes()) {
if (error)
- info.onResponse(nodeId, fragment.fragmentId(), new QueryCancelledException());
+ info.onResponse(nodeId, fragment0.fragmentId(), new QueryCancelledException());
else {
try {
+ FragmentDescription fragmentDescription0 = new FragmentDescription(
+ fragment0.fragmentId(),
+ mapping0.partitions(nodeId),
+ mapping0.assignments().size(),
+ plan.targetMapping(fragment0),
+ plan.remoteSources(fragment0)
+ );
+
QueryStartRequest req = new QueryStartRequest(
queryId,
- fragment.fragmentId(),
pctx.schemaName(),
- converter.go(fragment.root()),
+ Commons.toJson(fragment0.root()),
pctx.topologyVersion(),
- fragment.mapping().partitions(nodeId),
+ fragmentDescription0,
pctx.parameters());
messageService().send(nodeId, req);
}
catch (Exception e) {
- info.onResponse(nodeId, fragment.fragmentId(), e);
+ info.onResponse(nodeId, fragment0.fragmentId(), e);
error = true;
}
}
@@ -725,19 +738,18 @@ public class ExecutionServiceImpl extends AbstractService implements ExecutionSe
taskExecutor(),
ctx,
msg.queryId(),
- msg.fragmentId(),
- msg.partitions(),
+ msg.fragmentDescription(),
Commons.parametersMap(msg.parameters())
);
- Node<Object[]> node = new PhysicalRelImplementor(execCtx, partitionService(),
- mailboxRegistry(), exchangeService(), failureProcessor()).go(msg.root());
+ Node<Object[]> node = new LogicalRelImplementor(execCtx, partitionService(),
+ mailboxRegistry(), exchangeService(), failureProcessor()).go(Commons.fromJson(ctx.createCluster(), msg.root()));
assert node instanceof Outbox : node;
node.context().execute(((Outbox<Object[]>) node)::init);
- messageService().send(nodeId, new QueryStartResponse(msg.queryId(), msg.fragmentId()));
+ messageService().send(nodeId, new QueryStartResponse(msg.queryId(), msg.fragmentDescription().fragmentId()));
}
catch (Throwable ex) { // TODO don't catch errors!
cancelQuery(msg.queryId());
@@ -748,7 +760,7 @@ public class ExecutionServiceImpl extends AbstractService implements ExecutionSe
U.warn(log, "Failed to start query. [nodeId=" + nodeId + ']', ex);
try {
- messageService().send(nodeId, new QueryStartResponse(msg.queryId(), msg.fragmentId(), ex));
+ messageService().send(nodeId, new QueryStartResponse(msg.queryId(), msg.fragmentDescription().fragmentId(), ex));
}
catch (IgniteCheckedException e) {
e.addSuppressed(ex);
@@ -874,7 +886,7 @@ public class ExecutionServiceImpl extends AbstractService implements ExecutionSe
private Throwable error;
/** */
- private QueryInfo(ExecutionContext ctx, List<Fragment> fragments, Node<Object[]> root) {
+ private QueryInfo(ExecutionContext ctx, MultiStepPlan plan, Node<Object[]> root) {
this.ctx = ctx;
RootNode rootNode = new RootNode(ctx, ExecutionServiceImpl.this::onCursorClose);
@@ -885,15 +897,14 @@ public class ExecutionServiceImpl extends AbstractService implements ExecutionSe
remotes = new HashSet<>();
waiting = new HashSet<>();
- for (int i = 1; i < fragments.size(); i++) {
- Fragment fragment = fragments.get(i);
- long id = fragment.fragmentId();
- List<UUID> nodes = fragment.mapping().nodes();
+ for (int i = 1; i < plan.fragments().size(); i++) {
+ Fragment fragment = plan.fragments().get(i);
+ List<UUID> nodes = plan.fragmentMapping(fragment).nodes();
remotes.addAll(nodes);
for (UUID node : nodes)
- waiting.add(new RemoteFragmentKey(node, id));
+ waiting.add(new RemoteFragmentKey(node, fragment.fragmentId()));
}
state = QueryState.RUNNING;
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/LogicalRelImplementor.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/LogicalRelImplementor.java
index 8845b16..d32644c 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/LogicalRelImplementor.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/LogicalRelImplementor.java
@@ -26,8 +26,8 @@ import org.apache.calcite.rel.RelDistribution;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.schema.ScannableTable;
-import org.apache.calcite.sql.SqlOperatorTable;
import org.apache.calcite.sql.validate.SqlConformance;
+import org.apache.calcite.util.ImmutableBitSet;
import org.apache.calcite.util.ImmutableIntList;
import org.apache.ignite.internal.processors.failure.FailureProcessor;
import org.apache.ignite.internal.processors.query.calcite.exec.exp.ExpressionFactory;
@@ -43,8 +43,6 @@ import org.apache.ignite.internal.processors.query.calcite.exec.rel.ProjectNode;
import org.apache.ignite.internal.processors.query.calcite.exec.rel.ScanNode;
import org.apache.ignite.internal.processors.query.calcite.exec.rel.UnionAllNode;
import org.apache.ignite.internal.processors.query.calcite.metadata.PartitionService;
-import org.apache.ignite.internal.processors.query.calcite.prepare.Fragment;
-import org.apache.ignite.internal.processors.query.calcite.prepare.RelTarget;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteAggregate;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteExchange;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteFilter;
@@ -103,19 +101,17 @@ public class LogicalRelImplementor implements IgniteRelVisitor<Node<Object[]>> {
final IgniteTypeFactory typeFactory = ctx.getTypeFactory();
final SqlConformance conformance = ctx.parent().conformance();
- final SqlOperatorTable opTable = ctx.parent().opTable();
- expressionFactory = new ExpressionFactory(typeFactory, conformance, opTable);
+ expressionFactory = new ExpressionFactory(typeFactory, conformance);
}
/** {@inheritDoc} */
@Override public Node<Object[]> visit(IgniteSender rel) {
- RelTarget target = rel.target();
IgniteDistribution distribution = rel.distribution();
- Destination destination = distribution.function().destination(partitionService, target.mapping(), distribution.getKeys());
+ Destination destination = distribution.function().destination(partitionService, ctx.targetMapping(), distribution.getKeys());
// Outbox fragment ID is used as exchange ID as well.
- Outbox<Object[]> outbox = new Outbox<>(ctx, exchangeService, mailboxRegistry, ctx.fragmentId(), target.fragmentId(), destination);
+ Outbox<Object[]> outbox = new Outbox<>(ctx, exchangeService, mailboxRegistry, rel.exchangeId(), rel.targetFragmentId(), destination);
outbox.register(visit(rel.getInput()));
mailboxRegistry.register(outbox);
@@ -134,13 +130,7 @@ public class LogicalRelImplementor implements IgniteRelVisitor<Node<Object[]>> {
/** {@inheritDoc} */
@Override public Node<Object[]> visit(IgniteTrimExchange rel) {
- RelTarget target = rel.target();
-
- assert target != null && target.mapping() != null && !F.isEmpty(target.mapping().assignments());
-
- Predicate<Object[]> predicate = partitionFilter(rel.distribution(), target.mapping().assignments().size());
-
- FilterNode node = new FilterNode(ctx, predicate);
+ FilterNode node = new FilterNode(ctx, partitionFilter(rel.distribution()));
node.register(visit(rel.getInput()));
return node;
@@ -172,7 +162,7 @@ public class LogicalRelImplementor implements IgniteRelVisitor<Node<Object[]>> {
/** {@inheritDoc} */
@Override public Node<Object[]> visit(IgniteValues rel) {
- return new ScanNode(ctx, expressionFactory.valuesRex(ctx, Commons.flat(Commons.cast(rel.getTuples())), rel.getRowType().getFieldCount()));
+ return new ScanNode(ctx, expressionFactory.values(ctx, Commons.flat(Commons.cast(rel.getTuples())), rel.getRowType().getFieldCount()));
}
/** {@inheritDoc} */
@@ -201,16 +191,14 @@ public class LogicalRelImplementor implements IgniteRelVisitor<Node<Object[]>> {
/** {@inheritDoc} */
@Override public Node<Object[]> visit(IgniteReceiver rel) {
- Fragment source = rel.source();
-
- // Corresponding outbox fragment ID is used as exchange ID as well.
- Inbox<Object[]> inbox = (Inbox<Object[]>) mailboxRegistry.register(new Inbox<>(ctx, exchangeService, mailboxRegistry, source.fragmentId(), source.fragmentId()));
+ Inbox<?> inbox = mailboxRegistry.register(
+ new Inbox<>(ctx, exchangeService, mailboxRegistry, rel.exchangeId(), rel.sourceFragmentId()));
// here may be an already created (to consume rows from remote nodes) inbox
// without proper context, we need to init it with a right one.
- inbox.init(ctx, source.mapping().nodes(), expressionFactory.comparator(ctx, rel.collations(), rel.getRowType()));
+ inbox.init(ctx, ctx.remoteSources(rel.exchangeId()), expressionFactory.comparator(ctx, rel.collations(), rel.getRowType()));
- return inbox;
+ return (Node<Object[]>)inbox;
}
/** {@inheritDoc} */
@@ -271,21 +259,15 @@ public class LogicalRelImplementor implements IgniteRelVisitor<Node<Object[]>> {
}
/** */
- private Predicate<Object[]> partitionFilter(IgniteDistribution distr, int partitions) {
+ private Predicate<Object[]> partitionFilter(IgniteDistribution distr) {
assert distr.getType() == RelDistribution.Type.HASH_DISTRIBUTED;
- assert !F.isEmpty(ctx.partitions());
-
- boolean[] filter = new boolean[partitions];
-
- for (int part : ctx.partitions())
- filter[part] = true;
+ ImmutableBitSet filter = ImmutableBitSet.of(ctx.partitions());
DistributionFunction function = distr.function();
ImmutableIntList keys = distr.getKeys();
+ ToIntFunction<Object> partFunction = function.partitionFunction(partitionService, ctx.partitionsCount(), keys);
- ToIntFunction<Object> partFunction = function.partitionFunction(partitionService, partitions, keys);
-
- return o -> filter[partFunction.applyAsInt(o)];
+ return o -> filter.get(partFunction.applyAsInt(o));
}
/** */
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/PhysicalRelImplementor.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/PhysicalRelImplementor.java
deleted file mode 100644
index e090b38..0000000
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/PhysicalRelImplementor.java
+++ /dev/null
@@ -1,251 +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.ignite.internal.processors.query.calcite.exec;
-
-import java.util.List;
-import java.util.function.Predicate;
-import java.util.function.Supplier;
-import java.util.function.ToIntFunction;
-import org.apache.calcite.rel.RelDistribution;
-import org.apache.calcite.schema.ScannableTable;
-import org.apache.calcite.sql.SqlOperatorTable;
-import org.apache.calcite.sql.validate.SqlConformance;
-import org.apache.calcite.util.ImmutableIntList;
-import org.apache.ignite.internal.processors.failure.FailureProcessor;
-import org.apache.ignite.internal.processors.query.calcite.exec.exp.ExpressionFactory;
-import org.apache.ignite.internal.processors.query.calcite.exec.exp.agg.AccumulatorWrapper;
-import org.apache.ignite.internal.processors.query.calcite.exec.rel.AggregateNode;
-import org.apache.ignite.internal.processors.query.calcite.exec.rel.FilterNode;
-import org.apache.ignite.internal.processors.query.calcite.exec.rel.Inbox;
-import org.apache.ignite.internal.processors.query.calcite.exec.rel.JoinNode;
-import org.apache.ignite.internal.processors.query.calcite.exec.rel.ModifyNode;
-import org.apache.ignite.internal.processors.query.calcite.exec.rel.Node;
-import org.apache.ignite.internal.processors.query.calcite.exec.rel.Outbox;
-import org.apache.ignite.internal.processors.query.calcite.exec.rel.ProjectNode;
-import org.apache.ignite.internal.processors.query.calcite.exec.rel.ScanNode;
-import org.apache.ignite.internal.processors.query.calcite.exec.rel.UnionAllNode;
-import org.apache.ignite.internal.processors.query.calcite.metadata.PartitionService;
-import org.apache.ignite.internal.processors.query.calcite.schema.TableDescriptor;
-import org.apache.ignite.internal.processors.query.calcite.serialize.AggregatePhysicalRel;
-import org.apache.ignite.internal.processors.query.calcite.serialize.FilterPhysicalRel;
-import org.apache.ignite.internal.processors.query.calcite.serialize.JoinPhysicalRel;
-import org.apache.ignite.internal.processors.query.calcite.serialize.PhysicalRel;
-import org.apache.ignite.internal.processors.query.calcite.serialize.PhysicalRelVisitor;
-import org.apache.ignite.internal.processors.query.calcite.serialize.ProjectPhysicalRel;
-import org.apache.ignite.internal.processors.query.calcite.serialize.ReceiverPhysicalRel;
-import org.apache.ignite.internal.processors.query.calcite.serialize.SenderPhysicalRel;
-import org.apache.ignite.internal.processors.query.calcite.serialize.TableModifyPhysicalRel;
-import org.apache.ignite.internal.processors.query.calcite.serialize.TableScanPhysicalRel;
-import org.apache.ignite.internal.processors.query.calcite.serialize.TrimExchangePhysicalRel;
-import org.apache.ignite.internal.processors.query.calcite.serialize.UnionAllPhysicalRel;
-import org.apache.ignite.internal.processors.query.calcite.serialize.ValuesPhysicalRel;
-import org.apache.ignite.internal.processors.query.calcite.trait.Destination;
-import org.apache.ignite.internal.processors.query.calcite.trait.DistributionFunction;
-import org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeFactory;
-import org.apache.ignite.internal.processors.query.calcite.util.Commons;
-import org.apache.ignite.internal.util.typedef.F;
-
-/**
- * Converts RelGraph to logical or physical tree.
- */
-public class PhysicalRelImplementor implements PhysicalRelVisitor<Node<Object[]>> {
- /** */
- private final ExecutionContext ctx;
-
- /** */
- private final PartitionService partitionService;
-
- /** */
- private final ExchangeService exchangeService;
-
- /** */
- private final MailboxRegistry mailboxRegistry;
-
- /** */
- private final ExpressionFactory expressionFactory;
-
- /** */
- public PhysicalRelImplementor(ExecutionContext ctx, PartitionService partitionService, MailboxRegistry mailboxRegistry, ExchangeService exchangeService, FailureProcessor failure) {
- this.ctx = ctx;
- this.partitionService = partitionService;
- this.mailboxRegistry = mailboxRegistry;
- this.exchangeService = exchangeService;
-
- IgniteTypeFactory typeFactory = ctx.getTypeFactory();
- SqlOperatorTable opTable = ctx.parent().opTable();
- SqlConformance conformance = ctx.parent().conformance();
-
- expressionFactory = new ExpressionFactory(typeFactory, conformance, opTable);
- }
-
- /** {@inheritDoc} */
- @Override public Node<Object[]> visit(TableScanPhysicalRel rel) {
- Iterable<Object[]> source = ctx
- .parent()
- .catalogReader()
- .getTable(rel.tableName())
- .unwrap(ScannableTable.class)
- .scan(ctx);
-
- return new ScanNode(ctx, source);
- }
-
- /** {@inheritDoc} */
- @Override public Node<Object[]> visit(FilterPhysicalRel rel) {
- FilterNode node = new FilterNode(ctx, expressionFactory.predicate(ctx, rel.condition(), rel.rowType()));
- node.register(visit(rel.input()));
-
- return node;
- }
-
- /** {@inheritDoc} */
- @Override public Node<Object[]> visit(TrimExchangePhysicalRel rel) {
- Predicate<Object[]> predicate = partitionFilter(rel.function(), rel.distributionKeys(), rel.partitions());
-
- FilterNode node = new FilterNode(ctx, predicate);
- node.register(visit(rel.input()));
-
- return node;
- }
-
- /** {@inheritDoc} */
- @Override public Node<Object[]> visit(ProjectPhysicalRel rel) {
- ProjectNode node = new ProjectNode(ctx, expressionFactory.project(ctx, rel.projects(), rel.rowType()));
- node.register(visit(rel.input()));
-
- return node;
- }
-
- /** {@inheritDoc} */
- @Override public Node<Object[]> visit(JoinPhysicalRel rel) {
- JoinNode node = new JoinNode(ctx, expressionFactory.predicate(ctx, rel.condition(), rel.rowType()));
- node.register(F.asList(visit(rel.left()), visit(rel.right())));
-
- return node;
- }
-
- /** {@inheritDoc} */
- @Override public Node<Object[]> visit(SenderPhysicalRel rel) {
- Destination destination = rel.distributionFunction()
- .destination(partitionService, rel.mapping(), rel.distributionKeys());
-
- Outbox<Object[]> outbox = new Outbox<>(ctx, exchangeService, mailboxRegistry,
- ctx.fragmentId(), rel.targetFragmentId(), destination);
- outbox.register(visit(rel.input()));
-
- mailboxRegistry.register(outbox);
-
- return outbox;
- }
-
- /** {@inheritDoc} */
- @Override public Node<Object[]> visit(ReceiverPhysicalRel rel) {
- Inbox<?> inbox = mailboxRegistry.register(new Inbox<>(ctx, exchangeService, mailboxRegistry, rel.sourceFragmentId(), rel.sourceFragmentId()));
-
- inbox.init(ctx, rel.sources(), expressionFactory.comparator(ctx, rel.collations(), rel.rowType()));
-
- return (Node<Object[]>) inbox;
- }
-
- /** {@inheritDoc} */
- @Override public Node<Object[]> visit(ValuesPhysicalRel rel) {
- Iterable<Object[]> source = expressionFactory.valuesExp(ctx, rel.values(), rel.rowLength());
-
- return new ScanNode(ctx, source);
- }
-
- /** {@inheritDoc} */
- @Override public Node<Object[]> visit(TableModifyPhysicalRel rel) {
- switch (rel.operation()){
- case INSERT:
- case UPDATE:
- case DELETE:
- TableDescriptor desc = ctx.parent().catalogReader().getTable(rel.tableName()).unwrap(TableDescriptor.class);
- ModifyNode node = new ModifyNode(ctx, desc, rel.operation(), rel.updateColumnList());
- node.register(visit(rel.input()));
-
- return node;
- case MERGE:
- throw new UnsupportedOperationException();
- default:
- throw new AssertionError();
- }
- }
-
- /** {@inheritDoc} */
- @Override public Node<Object[]> visit(UnionAllPhysicalRel rel) {
- UnionAllNode<Object[]> node = new UnionAllNode<>(ctx);
- node.register(Commons.transform(rel.inputs(), this::visit));
- return node;
- }
-
- /** {@inheritDoc} */
- @Override public Node<Object[]> visit(AggregatePhysicalRel rel) {
- AggregateNode.AggregateType type;
-
- switch (rel.type()) {
- case AggregatePhysicalRel.MAP:
- type = AggregateNode.AggregateType.MAP;
- break;
- case AggregatePhysicalRel.REDUCE:
- type = AggregateNode.AggregateType.REDUCE;
- break;
- case AggregatePhysicalRel.SINGLE:
- type = AggregateNode.AggregateType.SINGLE;
- break;
- default:
- throw new AssertionError();
- }
-
- RowHandler<Object[]> rowHandler = ArrayRowHandler.INSTANCE;
-
- Supplier<List<AccumulatorWrapper>> factory = expressionFactory.wrappersFactory(ctx,
- rowHandler, type, rel.calls(), rel.inputRowType());
-
- AggregateNode<Object[]> node = new AggregateNode<>(ctx, type, rel.groupSets(), factory, rowHandler);
-
- node.register(visit(rel.input()));
-
- return node;
- }
-
- /** {@inheritDoc} */
- @Override public Node<Object[]> visit(PhysicalRel rel) {
- return rel.accept(this);
- }
-
- /** */
- private Predicate<Object[]> partitionFilter(DistributionFunction function, ImmutableIntList keys, int partitions) {
- assert function.type() == RelDistribution.Type.HASH_DISTRIBUTED;
- assert !F.isEmpty(ctx.partitions());
-
- boolean[] filter = new boolean[partitions];
-
- for (int part : ctx.partitions())
- filter[part] = true;
-
- ToIntFunction<Object> partFunction = function.partitionFunction(partitionService, partitions, keys);
-
- return o -> filter[partFunction.applyAsInt(o)];
- }
-
- /** */
- public Node<Object[]> go(PhysicalRel root) {
- return visit(root);
- }
-}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/Call.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/Call.java
deleted file mode 100644
index 91573d3..0000000
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/Call.java
+++ /dev/null
@@ -1,118 +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.ignite.internal.processors.query.calcite.exec.exp;
-
-import java.util.List;
-import java.util.Objects;
-import org.apache.calcite.sql.SqlIdentifier;
-import org.apache.calcite.sql.SqlOperator;
-import org.apache.calcite.sql.SqlOperatorTable;
-import org.apache.calcite.sql.SqlSyntax;
-import org.apache.calcite.sql.parser.SqlParserPos;
-import org.apache.calcite.sql.validate.SqlConformance;
-import org.apache.calcite.sql.validate.SqlNameMatchers;
-import org.apache.ignite.internal.processors.query.calcite.exec.ExecutionContext;
-import org.apache.ignite.internal.processors.query.calcite.exec.exp.type.DataType;
-import org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeFactory;
-import org.apache.ignite.internal.util.MutableSingletonList;
-import org.apache.ignite.internal.util.typedef.F;
-
-/**
- * Describes {@link org.apache.calcite.rex.RexCall}.
- */
-public class Call implements Expression {
- /** */
- private DataType type;
-
- /** */
- private String opName;
-
- /** */
- private SqlSyntax syntax;
-
- /** */
- private List<Expression> operands;
-
- /** */
- private transient CallOperation opImpl;
-
- /**
- * @param type Result type.
- * @param operands Operands.
- */
- public Call(DataType type, String opName, SqlSyntax syntax, List<Expression> operands) {
- this.type = type;
- this.opName = opName;
- this.syntax = syntax;
- this.operands = operands;
- }
-
- /** {@inheritDoc} */
- @Override public DataType resultType() {
- return type;
- }
-
- /**
- * @param opTable Operators table.
- * @return Sql logical operator.
- */
- public SqlOperator sqlOperator(SqlOperatorTable opTable) {
- List<SqlOperator> bag = new MutableSingletonList<>();
-
- opTable.lookupOperatorOverloads(
- new SqlIdentifier(opName, SqlParserPos.ZERO), null,
- syntax, bag, SqlNameMatchers.withCaseSensitive(true));
-
- return Objects.requireNonNull(F.first(bag));
- }
-
- /** */
- public String opName() {
- return opName;
- }
-
- /** */
- public SqlSyntax syntax() {
- return syntax;
- }
-
- /**
- * @return Operands.
- */
- public List<Expression> operands() {
- return operands;
- }
-
- /** {@inheritDoc} */
- @Override public <T> T accept(ExpressionVisitor<T> visitor) {
- return visitor.visit(this);
- }
-
- /** {@inheritDoc} */
- @Override public <T> T evaluate(ExecutionContext ctx, Object... args) {
- if (opImpl == null) {
- IgniteTypeFactory typeFactory = ctx.parent().typeFactory();
- SqlConformance conformance = ctx.parent().conformance();
- SqlOperatorTable opTable = ctx.parent().opTable();
-
- opImpl = new ExpressionFactory(typeFactory, conformance, opTable).implement(this);
- }
-
- return (T) opImpl.apply(operands.stream().map(o -> o.evaluate(ctx, args)).toArray());
- }
-}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/CallOperation.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/CallOperation.java
deleted file mode 100644
index 3150bc6..0000000
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/CallOperation.java
+++ /dev/null
@@ -1,27 +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.ignite.internal.processors.query.calcite.exec.exp;
-
-import java.util.function.Function;
-
-/**
- *
- */
-public interface CallOperation extends Function<Object[], Object> {
- @Override Object apply(Object... args);
-}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/DynamicParam.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/DynamicParam.java
deleted file mode 100644
index 256609b..0000000
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/DynamicParam.java
+++ /dev/null
@@ -1,63 +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.ignite.internal.processors.query.calcite.exec.exp;
-
-import org.apache.ignite.internal.processors.query.calcite.exec.ExecutionContext;
-import org.apache.ignite.internal.processors.query.calcite.exec.exp.type.DataType;
-
-/**
- * Describes {@link org.apache.calcite.rex.RexDynamicParam}.
- */
-public class DynamicParam implements Expression {
- /** */
- private final DataType type;
-
- /** */
- private final int index;
-
- /**
- * @param type Data type.
- * @param index Index.
- */
- public DynamicParam(DataType type, int index) {
- this.type = type;
- this.index = index;
- }
-
- /** {@inheritDoc} */
- @Override public DataType resultType() {
- return type;
- }
-
- /**
- * @return Index.
- */
- public int index() {
- return index;
- }
-
- /** {@inheritDoc} */
- @Override public <T> T accept(ExpressionVisitor<T> visitor) {
- return visitor.visit(this);
- }
-
- /** {@inheritDoc} */
- @Override public <T> T evaluate(ExecutionContext ctx, Object... args) {
- return (T) ctx.get("?" + index);
- }
-}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/ExpToRexTranslator.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/ExpToRexTranslator.java
deleted file mode 100644
index d02c449..0000000
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/ExpToRexTranslator.java
+++ /dev/null
@@ -1,116 +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.ignite.internal.processors.query.calcite.exec.exp;
-
-import java.util.List;
-import org.apache.calcite.rel.RelCollations;
-import org.apache.calcite.rel.core.AggregateCall;
-import org.apache.calcite.rex.RexBuilder;
-import org.apache.calcite.rex.RexNode;
-import org.apache.calcite.sql.SqlOperatorTable;
-import org.apache.calcite.util.ImmutableIntList;
-import org.apache.ignite.internal.processors.query.calcite.exec.exp.agg.AggCallExp;
-import org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeFactory;
-import org.apache.ignite.internal.processors.query.calcite.util.Commons;
-
-/**
- * A translator of Expressions into Rex nodes.
- */
-public class ExpToRexTranslator implements ExpressionVisitor<RexNode> {
- /** */
- private final IgniteTypeFactory typeFactory;
-
- /** */
- private final SqlOperatorTable opTable;
-
- /** */
- private final RexBuilder builder;
-
- /**
- * Creates a Translator.
- *
- * @param typeFactory Ignite type factory.
- * @param opTable Operators table.
- */
- public ExpToRexTranslator(IgniteTypeFactory typeFactory, SqlOperatorTable opTable) {
- this.typeFactory = typeFactory;
- this.opTable = opTable;
-
- builder = new RexBuilder(typeFactory);
- }
-
- /**
- * Translates a list of expressions into a list of Rex nodes.
- *
- * @param exps List of expressions.
- * @return List of Rex nodes.
- */
- public List<RexNode> translate(List<Expression> exps) {
- return Commons.transform(exps, this::translate);
- }
-
- /**
- * Translates an expression into a RexNode.
- *
- * @param exp Expression.
- * @return RexNode.
- */
- public RexNode translate(Expression exp) {
- return exp.accept(this);
- }
-
- /** */
- public AggregateCall translate(AggCallExp desc) {
- return AggregateCall.create(
- desc.sqlOperator(opTable),
- desc.distinct(),
- desc.approximate(),
- desc.ignoreNulls(),
- ImmutableIntList.of(desc.args()),
- desc.filterArg(),
- RelCollations.EMPTY,
- desc.resultType().logicalType(typeFactory),
- desc.name()
- );
- }
-
- /** {@inheritDoc} */
- @Override public RexNode visit(InputRef exp) {
- return builder.makeInputRef(exp.logicalType(typeFactory), exp.index());
- }
-
- /** {@inheritDoc} */
- @Override public RexNode visit(Literal exp) {
- return builder.makeLiteral(exp.value(), exp.logicalType(typeFactory),false);
- }
-
- /** {@inheritDoc} */
- @Override public RexNode visit(DynamicParam exp) {
- return builder.makeDynamicParam(exp.logicalType(typeFactory), exp.index());
- }
-
- /** {@inheritDoc} */
- @Override public RexNode visit(Call exp) {
- return builder.makeCall(exp.logicalType(typeFactory), exp.sqlOperator(opTable), translate(exp.operands()));
- }
-
- /** {@inheritDoc} */
- @Override public RexNode visit(Expression exp) {
- return exp.accept(this);
- }
-}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/Expression.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/Expression.java
deleted file mode 100644
index ef44a80..0000000
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/Expression.java
+++ /dev/null
@@ -1,58 +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.ignite.internal.processors.query.calcite.exec.exp;
-
-import java.io.Serializable;
-import org.apache.calcite.rel.type.RelDataType;
-import org.apache.ignite.internal.processors.query.calcite.exec.ExecutionContext;
-import org.apache.ignite.internal.processors.query.calcite.exec.exp.type.DataType;
-import org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeFactory;
-
-/**
- * Describes {@link org.apache.calcite.rex.RexNode}
- */
-public interface Expression extends Serializable {
- /**
- * Accepts a visit from a visitor.
- *
- * @param visitor Expression visitor.
- * @return Visit result.
- */
- <T> T accept(ExpressionVisitor<T> visitor);
-
- /** */
- DataType resultType();
-
- /** */
- default RelDataType logicalType(IgniteTypeFactory typeFactory) {
- return resultType().logicalType(typeFactory);
- }
-
- /** */
- default Class<?> javaType(IgniteTypeFactory typeFactory) {
- return resultType().javaType(typeFactory);
- }
-
- /**
- * Evaluates expression.
- *
- * @param ctx Execution context.
- * @return Evaluated value.
- */
- <T> T evaluate(ExecutionContext ctx, Object... args);
-}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/ExpressionFactory.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/ExpressionFactory.java
index d3e30ff..1ecae37 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/ExpressionFactory.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/ExpressionFactory.java
@@ -18,9 +18,8 @@
package org.apache.ignite.internal.processors.query.calcite.exec.exp;
import com.google.common.collect.ImmutableList;
-import java.io.StringReader;
+import com.google.common.primitives.Primitives;
import java.lang.reflect.Modifier;
-import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
@@ -31,9 +30,7 @@ import java.util.function.Predicate;
import java.util.function.Supplier;
import org.apache.calcite.adapter.enumerable.JavaRowFormat;
import org.apache.calcite.adapter.enumerable.PhysTypeImpl;
-import org.apache.calcite.adapter.enumerable.RexImpTable;
import org.apache.calcite.adapter.enumerable.RexToLixTranslator;
-import org.apache.calcite.config.CalciteSystemProperty;
import org.apache.calcite.linq4j.tree.BlockBuilder;
import org.apache.calcite.linq4j.tree.Expressions;
import org.apache.calcite.linq4j.tree.MethodDeclaration;
@@ -43,31 +40,22 @@ import org.apache.calcite.rel.core.AggregateCall;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rel.type.RelDataTypeFactory;
import org.apache.calcite.rex.RexBuilder;
-import org.apache.calcite.rex.RexCall;
+import org.apache.calcite.rex.RexLiteral;
import org.apache.calcite.rex.RexNode;
import org.apache.calcite.rex.RexProgram;
import org.apache.calcite.rex.RexProgramBuilder;
-import org.apache.calcite.sql.SqlOperatorTable;
-import org.apache.calcite.sql.SqlSyntax;
import org.apache.calcite.sql.validate.SqlConformance;
import org.apache.calcite.util.Pair;
-import org.apache.calcite.util.Util;
-import org.apache.ignite.IgniteException;
import org.apache.ignite.internal.processors.query.calcite.exec.ExecutionContext;
import org.apache.ignite.internal.processors.query.calcite.exec.RowHandler;
import org.apache.ignite.internal.processors.query.calcite.exec.exp.agg.AccumulatorWrapper;
-import org.apache.ignite.internal.processors.query.calcite.exec.exp.agg.AggCallExp;
import org.apache.ignite.internal.processors.query.calcite.exec.exp.agg.WrappersFactoryImpl;
-import org.apache.ignite.internal.processors.query.calcite.exec.exp.type.DataType;
import org.apache.ignite.internal.processors.query.calcite.exec.rel.AggregateNode;
import org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeFactory;
import org.apache.ignite.internal.processors.query.calcite.util.Commons;
import org.apache.ignite.internal.processors.query.calcite.util.IgniteMethod;
import org.apache.ignite.internal.util.GridBoundedConcurrentLinkedHashMap;
import org.apache.ignite.internal.util.typedef.F;
-import org.codehaus.commons.compiler.CompilerFactoryFactory;
-import org.codehaus.commons.compiler.IClassBodyEvaluator;
-import org.codehaus.commons.compiler.ICompilerFactory;
/**
* Implements rex expression into a function object. Uses JaninoRexCompiler under the hood.
@@ -79,38 +67,23 @@ public class ExpressionFactory {
private static final Map<String, Scalar> SCALAR_CACHE = new GridBoundedConcurrentLinkedHashMap<>(1024);
/** */
- private static final Map<String, CallOperation> CALL_OP_CACHE = new GridBoundedConcurrentLinkedHashMap<>(1024);
-
- /** */
private final IgniteTypeFactory typeFactory;
/** */
private final SqlConformance conformance;
/** */
- private final SqlOperatorTable opTable;
-
- /** */
private final RexBuilder rexBuilder;
/** */
- private final ExpToRexTranslator expToRexTranslator;
-
- /** */
- private final RexToExpTranslator rexToExpTranslator;
-
- /** */
private final RelDataType emptyType;
/** */
- public ExpressionFactory(IgniteTypeFactory typeFactory, SqlConformance conformance, SqlOperatorTable opTable) {
+ public ExpressionFactory(IgniteTypeFactory typeFactory, SqlConformance conformance) {
this.typeFactory = typeFactory;
this.conformance = conformance;
- this.opTable = opTable;
rexBuilder = new RexBuilder(typeFactory);
- expToRexTranslator = new ExpToRexTranslator(typeFactory, opTable);
- rexToExpTranslator = new RexToExpTranslator(typeFactory);
emptyType = new RelDataTypeFactory.Builder(typeFactory).build();
}
@@ -125,28 +98,10 @@ public class ExpressionFactory {
}
/** */
- public ExpToRexTranslator expToRexTranslator() {
- return expToRexTranslator;
- }
-
- /** */
- public RexToExpTranslator rexToExpTranslator() {
- return rexToExpTranslator;
- }
-
- /** */
public Supplier<List<AccumulatorWrapper>> wrappersFactory(ExecutionContext root, RowHandler handler, AggregateNode.AggregateType type, List<AggregateCall> calls, RelDataType rowType) {
return new WrappersFactoryImpl(root, type, handler, calls, rowType);
}
- /** */
- public Supplier<List<AccumulatorWrapper>> wrappersFactory(ExecutionContext root, RowHandler handler, AggregateNode.AggregateType type, List<AggCallExp> calls, DataType rowType) {
- List<AggregateCall> calls0 = Commons.transform(calls, expToRexTranslator::translate);
- RelDataType rowType0 = rowType == null ? null : rowType.logicalType(typeFactory);
-
- return wrappersFactory(root, handler, type, calls0, rowType0);
- }
-
/**
* Creates a comparator for given data type and collations. Mainly used for sorted exchange.
*
@@ -161,31 +116,6 @@ public class ExpressionFactory {
}
/**
- * Creates a comparator for given data type and collations. Mainly used for sorted exchange.
- *
- * @param root Execution context, holds a planner context, query and its parameters,
- * execution specific variables (like queryId, current user, session, etc).
- * @param collations Collations.
- * @param rowType Input row type.
- * @return Row comparator.
- */
- public <T> Comparator<T> comparator(ExecutionContext root, List<RelCollation> collations, DataType rowType) {
- return null; // TODO
- }
-
- /**
- * Creates a Filter predicate.
- * @param ctx Execution context, holds a planner context, query and its parameters,
- * execution specific variables (like queryId, current user, session, etc).
- * @param filter Filter expression.
- * @param rowType Input row type.
- * @return Filter predicate.
- */
- public <T> Predicate<T> predicate(ExecutionContext ctx, Expression filter, DataType rowType) {
- return predicate(ctx, expToRexTranslator.translate(filter), rowType.logicalType(typeFactory));
- }
-
- /**
* Creates a Filter predicate.
* @param ctx Execution context, holds a planner context, query and its parameters,
* execution specific variables (like queryId, current user, session, etc).
@@ -206,19 +136,6 @@ public class ExpressionFactory {
* @param rowType Input row type.
* @return Project function.
*/
- public <T> Function<T, T> project(ExecutionContext ctx, List<Expression> projects, DataType rowType) {
- return project(ctx, expToRexTranslator.translate(projects), rowType.logicalType(typeFactory));
- }
-
- /**
- * Creates a Project function. Resulting function returns a row with different fields,
- * fields order, fields types, etc.
- * @param ctx Execution context, holds a planner context, query and its parameters,
- * execution specific variables (like queryId, current user, session, etc).
- * @param projects Projection expressions.
- * @param rowType Input row type.
- * @return Project function.
- */
public <T> Function<T, T> project(ExecutionContext ctx, List<RexNode> projects, RelDataType rowType) {
return new ProjectImpl<>(ctx, scalar(projects, rowType), projects.size());
}
@@ -232,34 +149,17 @@ public class ExpressionFactory {
* @param rowLen Row length.
* @return Values relational node rows source.
*/
- public <T> Iterable<T> valuesExp(ExecutionContext ctx, List<Expression> values, int rowLen) {
+ public <T> Iterable<T> values(ExecutionContext ctx, List<RexLiteral> values, int rowLen) {
Object[] out = new Object[values.size()];
- for (int i = 0; i < values.size(); i++)
- out[i] = values.get(i).evaluate(ctx);
+ for (int i = 0; i < values.size(); i++) {
+ RexLiteral literal = values.get(i);
+ out[i] = literal.getValueAs(Primitives.wrap((Class<?>)typeFactory.getJavaClass(literal.getType())));
+ }
return () -> new ValuesIterator<>(out, rowLen);
}
- /**
- * Creates a Values relational node rows source.
- *
- * @param ctx Execution context, holds a planner context, query and its parameters,
- * execution specific variables (like queryId, current user, session, etc).
- * @param values Values.
- * @param rowLen Row length.
- * @return Values relational node rows source.
- */
- public <T> Iterable<T> valuesRex(ExecutionContext ctx, List<RexNode> values, int rowLen) {
- // it's safe to just interpret literals
- return valuesExp(ctx, rexToExpTranslator.translate(values), rowLen);
- }
-
- /** */
- public CallOperation implement(Call call) {
- return CALL_OP_CACHE.computeIfAbsent(digest(call), k -> compile(call));
- }
-
/** */
public Scalar scalar(RexNode node, RelDataType type) {
return scalar(ImmutableList.of(node), type);
@@ -318,81 +218,7 @@ public class ExpressionFactory {
Modifier.PUBLIC, Object[].class, IgniteMethod.SCALAR_EXECUTE.method().getName(),
ImmutableList.of(context_, inputValues_, outputValues_), builder.toBlock());
- return compile(Scalar.class, Expressions.toString(F.asList(declaration), "\n", false));
- }
-
- /** */
- private CallOperation compile(Call call) {
- RexCall rexCall = rexCall(call);
-
- BlockBuilder builder = new BlockBuilder();
-
- ParameterExpression params_ =
- Expressions.parameter(Object[].class, "in");
-
- RexToLixTranslator.InputGetter inputGetter =
- new RexToLixTranslator.InputGetterImpl(
- ImmutableList.of(
- Pair.of(params_,
- PhysTypeImpl.of(typeFactory, inputType(rexCall),
- JavaRowFormat.ARRAY, false))));
-
- RexToLixTranslator translator = RexToLixTranslator.forAggregation(typeFactory,
- builder, inputGetter, conformance);
-
- builder.add(
- RexImpTable.INSTANCE.get(rexCall.op)
- .implement(translator,
- rexCall, RexImpTable.NullAs.NULL));
-
- MethodDeclaration declaration = Expressions.methodDecl(
- Modifier.PUBLIC, Object.class, IgniteMethod.CALL_APPLY.method().getName(), ImmutableList.of(params_), builder.toBlock());
-
- return compile(CallOperation.class, Expressions.toString(F.asList(declaration), "\n", true));
- }
-
- /** */
- private RexCall rexCall(Call call) {
- List<Expression> operands = call.operands();
- List<RexNode> refs = new ArrayList<>(operands.size());
-
- for (int i = 0; i < operands.size(); i++)
- refs.add(rexBuilder.makeInputRef(operands.get(i).logicalType(typeFactory), i));
-
- return (RexCall) rexBuilder.makeCall(call.logicalType(typeFactory), call.sqlOperator(opTable), refs);
- }
-
- /** */
- private RelDataType inputType(RexCall rexCall) {
- RelDataTypeFactory.Builder typeBuilder = new RelDataTypeFactory.Builder(typeFactory);
- ImmutableList<RexNode> rexNodes = rexCall.operands;
- for (int i = 0; i < rexNodes.size(); i++)
- typeBuilder.add("EXP$" + i, rexNodes.get(i).getType());
- return typeBuilder.build();
- }
-
- /** */
- private String digest(Call call) {
- List<Expression> operands = call.operands();
-
- final StringBuilder sb = new StringBuilder(call.opName());
-
- if (!operands.isEmpty() || call.syntax() != SqlSyntax.FUNCTION_ID) {
- sb.append("(");
-
- for (int i = 0; i < operands.size(); i++) {
- if (i != 0)
- sb.append(", ");
-
- sb.append("$").append(i).append(":").append(operands.get(i).resultType());
- }
-
- sb.append(")");
- }
-
- sb.append(":").append(call.resultType());
-
- return sb.toString();
+ return Commons.compile(Scalar.class, Expressions.toString(F.asList(declaration), "\n", false));
}
/** */
@@ -417,38 +243,6 @@ public class ExpressionFactory {
}
/** */
- private static <T> T compile(Class<T> interfaceType, String body) {
- final boolean debug = CalciteSystemProperty.DEBUG.value();
-
- if (debug)
- Util.debugCode(System.out, body);
-
- try {
- final ICompilerFactory compilerFactory;
-
- try {
- compilerFactory = CompilerFactoryFactory.getDefaultCompilerFactory();
- } catch (Exception e) {
- throw new IllegalStateException(
- "Unable to instantiate java compiler", e);
- }
-
- IClassBodyEvaluator cbe = compilerFactory.newClassBodyEvaluator();
-
- cbe.setImplementedInterfaces(new Class[]{ interfaceType });
- cbe.setParentClassLoader(ExpressionFactory.class.getClassLoader());
-
- if (debug)
- // Add line numbers to the generated janino class
- cbe.setDebuggingInformation(true, true, true);
-
- return (T) cbe.createInstance(new StringReader(body));
- } catch (Exception e) {
- throw new IgniteException(e);
- }
- }
-
- /** */
private static class PredicateImpl<T> implements Predicate<T> {
/** */
private final ExecutionContext ctx;
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/ExpressionVisitor.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/ExpressionVisitor.java
deleted file mode 100644
index e3d74bf..0000000
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/ExpressionVisitor.java
+++ /dev/null
@@ -1,51 +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.ignite.internal.processors.query.calcite.exec.exp;
-
-/**
- * Visitor pattern for traversing a tree of {@link Expression} objects.
- */
-public interface ExpressionVisitor<T> {
- /**
- * See {@link ExpressionVisitor#visit(Expression)}
- */
- T visit(InputRef exp);
-
- /**
- * See {@link ExpressionVisitor#visit(Expression)}
- */
- T visit(Literal exp);
-
- /**
- * See {@link ExpressionVisitor#visit(Expression)}
- */
- T visit(DynamicParam exp);
-
- /**
- * See {@link ExpressionVisitor#visit(Expression)}
- */
- T visit(Call exp);
-
- /**
- * Implements given expression.
- *
- * @param exp Expression.
- * @return Implementation result.
- */
- T visit(Expression exp);
-}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/InputRef.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/InputRef.java
deleted file mode 100644
index dfbfb18..0000000
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/InputRef.java
+++ /dev/null
@@ -1,63 +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.ignite.internal.processors.query.calcite.exec.exp;
-
-import org.apache.ignite.internal.processors.query.calcite.exec.ExecutionContext;
-import org.apache.ignite.internal.processors.query.calcite.exec.exp.type.DataType;
-
-/**
- * Describes {@link org.apache.calcite.rex.RexInputRef}.
- */
-public class InputRef implements Expression {
- /** */
- private final DataType type;
-
- /** */
- private final int index;
-
- /**
- * @param type Data type.
- * @param index Index.
- */
- public InputRef(DataType type, int index) {
- this.type = type;
- this.index = index;
- }
-
- /** {@inheritDoc} */
- @Override public DataType resultType() {
- return type;
- }
-
- /**
- * @return Index.
- */
- public int index() {
- return index;
- }
-
- /** {@inheritDoc} */
- @Override public <T> T accept(ExpressionVisitor<T> visitor) {
- return visitor.visit(this);
- }
-
- /** {@inheritDoc} */
- @Override public <T> T evaluate(ExecutionContext ctx, Object... args) {
- return (T) args[index];
- }
-}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/Literal.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/Literal.java
deleted file mode 100644
index 2108537..0000000
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/Literal.java
+++ /dev/null
@@ -1,63 +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.ignite.internal.processors.query.calcite.exec.exp;
-
-import org.apache.ignite.internal.processors.query.calcite.exec.ExecutionContext;
-import org.apache.ignite.internal.processors.query.calcite.exec.exp.type.DataType;
-
-/**
- * Describes {@link org.apache.calcite.rex.RexLiteral}.
- */
-public class Literal implements Expression {
- /** */
- private final DataType type;
-
- /** */
- private final Object value;
-
- /**
- * @param type Data type.
- * @param value Value.
- */
- public Literal(DataType type, Object value) {
- this.type = type;
- this.value = value;
- }
-
- /** {@inheritDoc} */
- @Override public DataType resultType() {
- return type;
- }
-
- /**
- * @return Value.
- */
- public Object value() {
- return value;
- }
-
- /** {@inheritDoc} */
- @Override public <T> T accept(ExpressionVisitor<T> visitor) {
- return visitor.visit(this);
- }
-
- /** {@inheritDoc} */
- @Override public <T> T evaluate(ExecutionContext ctx, Object... args) {
- return (T) value;
- }
-}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/RexToExpTranslator.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/RexToExpTranslator.java
deleted file mode 100644
index 104bb50..0000000
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/RexToExpTranslator.java
+++ /dev/null
@@ -1,151 +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.ignite.internal.processors.query.calcite.exec.exp;
-
-import java.util.List;
-import org.apache.calcite.rel.core.AggregateCall;
-import org.apache.calcite.rex.RexCall;
-import org.apache.calcite.rex.RexCorrelVariable;
-import org.apache.calcite.rex.RexDynamicParam;
-import org.apache.calcite.rex.RexFieldAccess;
-import org.apache.calcite.rex.RexInputRef;
-import org.apache.calcite.rex.RexLiteral;
-import org.apache.calcite.rex.RexLocalRef;
-import org.apache.calcite.rex.RexNode;
-import org.apache.calcite.rex.RexOver;
-import org.apache.calcite.rex.RexPatternFieldRef;
-import org.apache.calcite.rex.RexRangeRef;
-import org.apache.calcite.rex.RexSubQuery;
-import org.apache.calcite.rex.RexTableInputRef;
-import org.apache.calcite.rex.RexVisitor;
-import org.apache.calcite.sql.SqlSyntax;
-import org.apache.ignite.internal.processors.query.calcite.exec.exp.agg.AggCallExp;
-import org.apache.ignite.internal.processors.query.calcite.exec.exp.type.DataType;
-import org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeFactory;
-import org.apache.ignite.internal.processors.query.calcite.util.Commons;
-
-/**
- * A translator of Rex nodes into Expressions.
- */
-public class RexToExpTranslator implements RexVisitor<Expression> {
- /** */
- private final IgniteTypeFactory typeFactory;
-
- public RexToExpTranslator(IgniteTypeFactory typeFactory) {
- this.typeFactory = typeFactory;
- }
-
- /**
- * Translates a list of Rex nodes into a list of expressions.
- *
- * @param operands List of Rex nodes.
- * @return List of expressions.
- */
- public List<Expression> translate(List<RexNode> operands) {
- return Commons.transform(operands, this::translate);
- }
-
- /**
- * Translates a RexNode into an expression.
- *
- * @param rex RexNode.
- * @return Expression.
- */
- public Expression translate(RexNode rex) {
- return rex.accept(this);
- }
-
- /** */
- public AggCallExp translate(AggregateCall call) {
- DataType type = DataType.fromType(call.type);
- SqlSyntax syntax = call.getAggregation().getSyntax();
- String function = call.getAggregation().getName();
- String name = call.name;
- boolean distinct = call.isDistinct();
- boolean approximate = call.isApproximate();
- boolean ignoreNulls = call.ignoreNulls();
- int[] args = call.getArgList().stream()
- .mapToInt(Integer::intValue)
- .toArray();
- int filterArg = call.filterArg;
-
- return new AggCallExp(type, syntax, function,
- name, distinct, approximate, ignoreNulls, args, filterArg);
- }
-
- /** {@inheritDoc} */
- @Override public Expression visitInputRef(RexInputRef rex) {
- return new InputRef(DataType.fromType(rex.getType()), rex.getIndex());
- }
-
- /** {@inheritDoc} */
- @Override public Expression visitLiteral(RexLiteral rex) {
- final DataType type = DataType.fromType(rex.getType());
- return new Literal(type, rex.getValueAs(Commons.boxType(type.javaType(typeFactory))));
- }
-
- /** {@inheritDoc} */
- @Override public Expression visitDynamicParam(RexDynamicParam rex) {
- return new DynamicParam(DataType.fromType(rex.getType()), rex.getIndex());
- }
-
- /** {@inheritDoc} */
- @Override public Expression visitCall(RexCall rex) {
- return new Call(DataType.fromType(rex.getType()), rex.op.getName(), rex.op.getSyntax(), translate(rex.getOperands()));
- }
-
- /** {@inheritDoc} */
- @Override public Expression visitLocalRef(RexLocalRef rex) {
- throw new UnsupportedOperationException();
- }
-
- /** {@inheritDoc} */
- @Override public Expression visitOver(RexOver rex) {
- throw new UnsupportedOperationException();
- }
-
- /** {@inheritDoc} */
- @Override public Expression visitCorrelVariable(RexCorrelVariable rex) {
- throw new UnsupportedOperationException();
- }
-
- /** {@inheritDoc} */
- @Override public Expression visitRangeRef(RexRangeRef rex) {
- throw new UnsupportedOperationException();
- }
-
- /** {@inheritDoc} */
- @Override public Expression visitFieldAccess(RexFieldAccess rex) {
- throw new UnsupportedOperationException();
- }
-
- /** {@inheritDoc} */
- @Override public Expression visitSubQuery(RexSubQuery rex) {
- throw new UnsupportedOperationException();
- }
-
- /** {@inheritDoc} */
- @Override public Expression visitTableInputRef(RexTableInputRef rex) {
- throw new UnsupportedOperationException();
- }
-
- /** {@inheritDoc} */
- @Override public Expression visitPatternFieldRef(RexPatternFieldRef rex) {
- throw new UnsupportedOperationException();
- }
-}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/agg/AggCallExp.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/agg/AggCallExp.java
deleted file mode 100644
index c9227bc..0000000
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/agg/AggCallExp.java
+++ /dev/null
@@ -1,178 +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.ignite.internal.processors.query.calcite.exec.exp.agg;
-
-import java.io.Externalizable;
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import java.util.List;
-import java.util.Objects;
-import org.apache.calcite.sql.SqlAggFunction;
-import org.apache.calcite.sql.SqlIdentifier;
-import org.apache.calcite.sql.SqlOperator;
-import org.apache.calcite.sql.SqlOperatorTable;
-import org.apache.calcite.sql.SqlSyntax;
-import org.apache.calcite.sql.parser.SqlParserPos;
-import org.apache.calcite.sql.validate.SqlNameMatchers;
-import org.apache.ignite.internal.processors.query.calcite.exec.exp.type.DataType;
-import org.apache.ignite.internal.util.MutableSingletonList;
-import org.apache.ignite.internal.util.typedef.F;
-
-/**
- *
- */
-public class AggCallExp implements Externalizable {
- /** */
- private static final byte DISTINCT = 1;
-
- /** */
- private static final byte APPROXIMATE = 1 << 1;
-
- /** */
- private static final byte IGNORE_NULLS = 1 << 2;
-
- /** */
- private static final byte HAS_NAME = 1 << 3;
-
- /** */
- private DataType type;
-
- /** */
- private SqlSyntax syntax;
-
- /** */
- private String function;
-
- /** */
- private String name;
-
- /** */
- private int[] args;
-
- /** */
- private int filterArg;
-
- /** */
- private byte flags;
-
- /** */
- public AggCallExp(DataType type, SqlSyntax syntax, String function, String name,
- boolean distinct, boolean approximate, boolean ignoreNulls, int[] args, int filterArg) {
- this.type = type;
- this.syntax = syntax;
- this.function = function;
- this.name = name;
- this.args = args;
- this.filterArg = filterArg;
-
- byte flags = 0;
-
- if (distinct)
- flags |= DISTINCT;
- if (approximate)
- flags |= APPROXIMATE;
- if (ignoreNulls)
- flags |= IGNORE_NULLS;
-
- this.flags = flags;
- }
-
- public AggCallExp() {
- }
-
- /** */
- public DataType resultType() {
- return type;
- }
-
- /** */
- public SqlSyntax syntax() {
- return syntax;
- }
-
- /** */
- public String function() {
- return function;
- }
-
- /** */
- public SqlAggFunction sqlOperator(SqlOperatorTable opTable) {
- List<SqlOperator> bag = new MutableSingletonList<>();
-
- opTable.lookupOperatorOverloads(
- new SqlIdentifier(function, SqlParserPos.ZERO), null,
- syntax, bag, SqlNameMatchers.withCaseSensitive(true));
-
- return (SqlAggFunction) Objects.requireNonNull(F.first(bag));
- }
-
- /** */
- public String name() {
- return name;
- }
-
- /** */
- public boolean distinct() {
- return (flags & DISTINCT) == DISTINCT;
- }
-
- /** */
- public boolean approximate() {
- return (flags & APPROXIMATE) == APPROXIMATE;
- }
-
- /** */
- public boolean ignoreNulls() {
- return (flags & IGNORE_NULLS) == IGNORE_NULLS;
- }
-
- /** */
- public int[] args() {
- return args;
- }
-
- /** */
- public int filterArg() {
- return filterArg;
- }
-
- /** {@inheritDoc} */
- @Override public void writeExternal(ObjectOutput out) throws IOException {
- out.writeByte(flags);
- out.writeByte(syntax.ordinal());
- out.writeUTF(function);
- if ((flags & HAS_NAME) == HAS_NAME)
- out.writeUTF(name);
- out.writeObject(type);
- out.writeObject(args);
- out.writeInt(filterArg);
- }
-
- /** {@inheritDoc} */
- @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
- flags = in.readByte();
- syntax = SqlSyntax.values()[in.readByte()];
- function = in.readUTF();
- if ((flags & HAS_NAME) == HAS_NAME)
- name = in.readUTF();
- type = (DataType) in.readObject();
- args = (int[]) in.readObject();
- filterArg = in.readInt();
- }
-}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/agg/WrappersFactoryImpl.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/agg/WrappersFactoryImpl.java
index c6e7687..d2c353e 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/agg/WrappersFactoryImpl.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/agg/WrappersFactoryImpl.java
@@ -29,7 +29,6 @@ import org.apache.calcite.rel.type.RelDataTypeFactory;
import org.apache.calcite.rel.type.RelDataTypeField;
import org.apache.calcite.rex.RexBuilder;
import org.apache.calcite.rex.RexNode;
-import org.apache.calcite.sql.SqlOperatorTable;
import org.apache.calcite.sql.validate.SqlConformance;
import org.apache.ignite.internal.processors.query.calcite.exec.ExecutionContext;
import org.apache.ignite.internal.processors.query.calcite.exec.RowHandler;
@@ -295,9 +294,8 @@ public class WrappersFactoryImpl implements Supplier<List<AccumulatorWrapper>> {
IgniteTypeFactory typeFactory = ctx.parent().typeFactory();
SqlConformance conformance = ctx.parent().conformance();
- SqlOperatorTable opTable = ctx.parent().opTable();
- ExpressionFactory factory = new ExpressionFactory(typeFactory, conformance, opTable);
+ ExpressionFactory factory = new ExpressionFactory(typeFactory, conformance);
if (type != AggregateType.REDUCE && !F.isEmpty(call.getArgList()))
inAdapter = createInAdapter(accumulator, factory);
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/type/BasicType.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/type/BasicType.java
deleted file mode 100644
index e4b6aa6..0000000
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/type/BasicType.java
+++ /dev/null
@@ -1,152 +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.ignite.internal.processors.query.calcite.exec.exp.type;
-
-import java.io.Externalizable;
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import org.apache.calcite.rel.type.RelDataType;
-import org.apache.calcite.sql.type.BasicSqlType;
-import org.apache.calcite.sql.type.SqlTypeName;
-import org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeFactory;
-
-import static org.apache.calcite.rel.type.RelDataType.PRECISION_NOT_SPECIFIED;
-import static org.apache.calcite.rel.type.RelDataType.SCALE_NOT_SPECIFIED;
-
-/** */
-public class BasicType implements DataType, Externalizable {
- /** */
- private SqlTypeName typeName;
-
- /** */
- private int precision = PRECISION_NOT_SPECIFIED;
-
- /** */
- private int scale = SCALE_NOT_SPECIFIED;
-
- /** */
- private boolean nullable;
-
- /** */
- public BasicType() {
- }
-
- /**
- * @param type Source type.
- */
- public BasicType(BasicSqlType type) {
- typeName = type.getSqlTypeName();
- precision = type.getPrecision();
- scale = type.getScale();
- nullable = type.isNullable();
- }
-
- /** {@inheritDoc} */
- @Override public SqlTypeName typeName() {
- return typeName;
- }
-
- /** {@inheritDoc} */
- @Override public int precision() {
- return precision;
- }
-
- /** {@inheritDoc} */
- @Override public int scale() {
- return scale;
- }
-
- /** */
- @Override public boolean nullable() {
- return nullable;
- }
-
- /** {@inheritDoc} */
- @Override public RelDataType logicalType(IgniteTypeFactory factory) {
- RelDataType type;
-
- if (!typeName.allowsPrec())
- type = factory.createSqlType(typeName);
- else if (!typeName.allowsScale())
- type = factory.createSqlType(typeName, precision);
- else
- type = factory.createSqlType(typeName, precision, scale);
-
- return nullable ? factory.createTypeWithNullability(type, nullable) : type;
- }
-
- /** {@inheritDoc} */
- @Override public Class<?> javaType(IgniteTypeFactory typeFactory) {
- return (Class<?>) typeFactory.getJavaClass(logicalType(typeFactory));
- }
-
- /** {@inheritDoc} */
- @Override public void writeExternal(ObjectOutput out) throws IOException {
- out.writeByte(typeName.ordinal());
-
- if (typeName.allowsScale())
- out.writeInt(scale);
-
- if (typeName.allowsPrec())
- out.writeInt(precision);
-
- out.writeBoolean(nullable);
- }
-
- /** {@inheritDoc} */
- @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
- typeName = SqlTypeName.values()[in.readByte()];
-
- if (typeName.allowsScale())
- scale = in.readInt();
-
- if (typeName.allowsPrec())
- precision = in.readInt();
-
- nullable = in.readBoolean();
- }
-
- /** {@inheritDoc} */
- @Override public String toString() {
- return toString(true);
- }
-
- /** */
- protected String toString(boolean withNullability) {
- StringBuilder sb = new StringBuilder(typeName.name());
-
- boolean printPrecision = precision != PRECISION_NOT_SPECIFIED;
- boolean printScale = scale != SCALE_NOT_SPECIFIED;
-
- if (printPrecision) {
- sb.append('(');
- sb.append(precision);
- if (printScale) {
- sb.append(", ");
- sb.append(scale);
- }
- sb.append(')');
- }
-
- if (withNullability && !nullable)
- sb.append(" NOT NULL");
-
- return sb.toString();
- }
-}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/type/CharacterDataType.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/type/CharacterDataType.java
deleted file mode 100644
index 9c43998..0000000
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/type/CharacterDataType.java
+++ /dev/null
@@ -1,32 +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.ignite.internal.processors.query.calcite.exec.exp.type;
-
-import java.nio.charset.Charset;
-import org.apache.calcite.sql.SqlCollation;
-
-/**
- *
- */
-public interface CharacterDataType extends DataType {
- /** */
- Charset charset();
-
- /** */
- SqlCollation collation();
-}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/type/CharacterType.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/type/CharacterType.java
deleted file mode 100644
index bb935ee..0000000
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/type/CharacterType.java
+++ /dev/null
@@ -1,142 +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.ignite.internal.processors.query.calcite.exec.exp.type;
-
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import java.nio.charset.Charset;
-import org.apache.calcite.rel.type.RelDataType;
-import org.apache.calcite.sql.SqlCollation;
-import org.apache.calcite.sql.type.BasicSqlType;
-import org.apache.commons.codec.Charsets;
-import org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeFactory;
-
-/** */
-public class CharacterType extends BasicType implements CharacterDataType {
- /** */
- private static final int COERCIBLE_COLLATION = 0;
-
- /** */
- private static final int IMPLICIT_COLLATION = 1;
-
- /** */
- private static final int CUSTOM_COLLATION = 2;
-
- /** */
- private Charset charset;
-
- /** */
- private SqlCollation collation;
-
- /** */
- public CharacterType() {
- }
-
- /**
- * @param type Source type.
- */
- public CharacterType(BasicSqlType type) {
- super(type);
-
- charset = type.getCharset();
- collation = type.getCollation();
- }
-
- /** {@inheritDoc} */
- @Override public Charset charset() {
- return charset;
- }
-
- /** {@inheritDoc} */
- @Override public SqlCollation collation() {
- return collation;
- }
-
- /** {@inheritDoc} */
- @Override public RelDataType logicalType(IgniteTypeFactory factory) {
- return factory.createTypeWithCharsetAndCollation(super.logicalType(factory), charset, collation);
- }
-
- /** {@inheritDoc} */
- @Override public Class<?> javaType(IgniteTypeFactory typeFactory) {
- return (Class<?>)typeFactory.getJavaClass(logicalType(typeFactory));
- }
-
- /** {@inheritDoc} */
- @Override public void writeExternal(ObjectOutput out) throws IOException {
- super.writeExternal(out);
-
- if (charset == null)
- out.writeBoolean(false);
- else {
- out.writeBoolean(true);
- out.writeUTF(charset.name());
- }
-
- if (collation == SqlCollation.COERCIBLE)
- out.writeByte(COERCIBLE_COLLATION);
- else if (collation == SqlCollation.IMPLICIT)
- out.writeByte(IMPLICIT_COLLATION);
- else {
- out.writeByte(CUSTOM_COLLATION);
- out.writeUTF(collation.getCollationName());
- out.writeByte(collation.getCoercibility().ordinal());
- }
- }
-
- /** {@inheritDoc} */
- @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
- super.readExternal(in);
-
- if (in.readBoolean())
- charset = Charsets.toCharset(in.readUTF());
-
- byte collationType = in.readByte();
-
- if (collationType == COERCIBLE_COLLATION)
- collation = SqlCollation.COERCIBLE;
- else if (collationType == IMPLICIT_COLLATION)
- collation = SqlCollation.IMPLICIT;
- else if (collationType == CUSTOM_COLLATION)
- collation = new SqlCollation(in.readUTF(), SqlCollation.Coercibility.values()[in.readByte()]);
- else
- throw new AssertionError();
- }
-
- /** {@inheritDoc} */
- @Override public String toString() {
- StringBuilder sb = new StringBuilder(toString(false));
-
- if (charset != null)
- sb.append(" CHARACTER SET \"")
- .append(charset.name())
- .append("\"");
- if (collation != null
- && collation != SqlCollation.IMPLICIT
- && collation != SqlCollation.COERCIBLE)
- sb.append(" COLLATE \"")
- .append(collation.getCollationName())
- .append("\"");
-
- if (!nullable())
- sb.append(" NOT NULL");
-
- return sb.toString();
- }
-}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/type/DataType.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/type/DataType.java
deleted file mode 100644
index 21c0c9a..0000000
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/type/DataType.java
+++ /dev/null
@@ -1,89 +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.ignite.internal.processors.query.calcite.exec.exp.type;
-
-import java.io.Serializable;
-import java.util.LinkedHashMap;
-import org.apache.calcite.rel.type.RelDataType;
-import org.apache.calcite.rel.type.RelDataTypeFactoryImpl;
-import org.apache.calcite.rel.type.RelDataTypeField;
-import org.apache.calcite.sql.type.BasicSqlType;
-import org.apache.calcite.sql.type.SqlTypeName;
-import org.apache.calcite.sql.type.SqlTypeUtil;
-import org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeFactory;
-
-/**
- * Serializable RelDataType representation.
- */
-public interface DataType extends Serializable {
- /**
- * Factory method to construct data type representation from RelDataType.
- * @param type RelDataType.
- * @return DataType.
- */
- static DataType fromType(RelDataType type) {
- if (type.isStruct()) {
- assert type.isStruct();
-
- LinkedHashMap<String, DataType> fields = new LinkedHashMap<>();
-
- for (RelDataTypeField field : type.getFieldList())
- fields.put(field.getName(), fromType(field.getType()));
-
- return new StructType(fields);
- }
-
- if (type instanceof RelDataTypeFactoryImpl.JavaType)
- return new JavaType(((RelDataTypeFactoryImpl.JavaType) type).getJavaClass(), type.isNullable());
-
- assert type instanceof BasicSqlType : type;
-
- if (SqlTypeUtil.inCharFamily(type))
- return new CharacterType((BasicSqlType) type);
-
- return new BasicType((BasicSqlType) type);
- }
-
- /** */
- SqlTypeName typeName();
-
- /** */
- int precision();
-
- /** */
- int scale();
-
- /** */
- boolean nullable();
-
- /**
- * Returns logical type.
- *
- * @param factory Type factory.
- * @return Logical type.
- */
- RelDataType logicalType(IgniteTypeFactory factory);
-
- /**
- * Returns java type.
- *
- * @param factory Type factory.
- * @return Java type.
- */
- Class<?> javaType(IgniteTypeFactory factory);
-}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/type/JavaType.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/type/JavaType.java
deleted file mode 100644
index 9b9af2e..0000000
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/type/JavaType.java
+++ /dev/null
@@ -1,84 +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.ignite.internal.processors.query.calcite.exec.exp.type;
-
-import org.apache.calcite.rel.type.RelDataType;
-import org.apache.calcite.sql.type.JavaToSqlTypeConversionRules;
-import org.apache.calcite.sql.type.SqlTypeName;
-import org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeFactory;
-
-import static org.apache.calcite.rel.type.RelDataType.PRECISION_NOT_SPECIFIED;
-import static org.apache.calcite.rel.type.RelDataType.SCALE_NOT_SPECIFIED;
-
-/** */
-public class JavaType implements DataType {
- /** */
- private final Class<?> clazz;
-
- /** */
- private final boolean nullable;
-
- /** {@inheritDoc} */
- @Override public SqlTypeName typeName() {
- final SqlTypeName typeName =
- JavaToSqlTypeConversionRules.instance().lookup(clazz);
-
- return typeName == null ? SqlTypeName.OTHER : typeName;
- }
-
- /** {@inheritDoc} */
- @Override public int precision() {
- return PRECISION_NOT_SPECIFIED;
- }
-
- /** {@inheritDoc} */
- @Override public int scale() {
- return SCALE_NOT_SPECIFIED;
- }
-
- /** {@inheritDoc} */
- @Override public boolean nullable() {
- return nullable;
- }
-
- /**
- * @param clazz Value class.
- * @param nullable nullable flag.
- */
- public JavaType(Class<?> clazz, boolean nullable) {
- assert !nullable || !clazz.isPrimitive();
-
- this.clazz = clazz;
- this.nullable = nullable;
- }
-
- /** {@inheritDoc} */
- @Override public RelDataType logicalType(IgniteTypeFactory factory) {
- return factory.createJavaType(clazz);
- }
-
- /** {@inheritDoc} */
- @Override public Class<?> javaType(IgniteTypeFactory factory) {
- return clazz;
- }
-
- /** {@inheritDoc} */
- @Override public String toString() {
- return String.valueOf(clazz);
- }
-}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/type/StructType.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/type/StructType.java
deleted file mode 100644
index 97aa7c3..0000000
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/type/StructType.java
+++ /dev/null
@@ -1,100 +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.ignite.internal.processors.query.calcite.exec.exp.type;
-
-import java.util.LinkedHashMap;
-import java.util.Map;
-import org.apache.calcite.rel.type.RelDataType;
-import org.apache.calcite.rel.type.RelDataTypeFactory;
-import org.apache.calcite.sql.type.SqlTypeName;
-import org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeFactory;
-
-import static org.apache.calcite.rel.type.RelDataType.PRECISION_NOT_SPECIFIED;
-import static org.apache.calcite.rel.type.RelDataType.SCALE_NOT_SPECIFIED;
-
-/** */
-public class StructType implements DataType {
- /** */
- private final LinkedHashMap<String, DataType> fields;
-
- /**
- * @param fields Fields.
- */
- public StructType(LinkedHashMap<String, DataType> fields) {
- this.fields = fields;
- }
-
- public Map<String, DataType> fields() {
- return fields;
- }
-
- /** {@inheritDoc} */
- @Override public SqlTypeName typeName() {
- return SqlTypeName.ROW;
- }
-
- /** {@inheritDoc} */
- @Override public int precision() {
- return PRECISION_NOT_SPECIFIED;
- }
-
- /** {@inheritDoc} */
- @Override public int scale() {
- return SCALE_NOT_SPECIFIED;
- }
-
- /** {@inheritDoc} */
- @Override public boolean nullable() {
- return false;
- }
-
- /** {@inheritDoc} */
- @Override public RelDataType logicalType(IgniteTypeFactory factory) {
- RelDataTypeFactory.Builder builder = new RelDataTypeFactory.Builder(factory);
- fields.forEach((n,f) -> builder.add(n,f.logicalType(factory)));
- return builder.build();
- }
-
- /** {@inheritDoc} */
- @Override public Class<?> javaType(IgniteTypeFactory typeFactory) {
- return Object[].class; // TODO currently a row is mapped to an object array, will be changed in future.
- }
-
- /** {@inheritDoc} */
- @Override public String toString() {
- StringBuilder sb = new StringBuilder("Row(");
-
- boolean first = true;
-
- for (Map.Entry<String, DataType> field : fields.entrySet()) {
- if(first)
- first = false;
- else
- sb.append(", ");
-
- sb.append("\"")
- .append(field.getKey())
- .append("\":")
- .append(field.getValue());
- }
-
- sb.append(")");
-
- return sb.toString();
- }
-}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/externalize/RelJson.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/externalize/RelJson.java
new file mode 100644
index 0000000..5bad195
--- /dev/null
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/externalize/RelJson.java
@@ -0,0 +1,871 @@
+/*
+ * 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.ignite.internal.processors.query.calcite.externalize;
+
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Modifier;
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Function;
+import org.apache.calcite.avatica.AvaticaUtils;
+import org.apache.calcite.avatica.util.TimeUnit;
+import org.apache.calcite.avatica.util.TimeUnitRange;
+import org.apache.calcite.linq4j.tree.BlockBuilder;
+import org.apache.calcite.linq4j.tree.Expressions;
+import org.apache.calcite.linq4j.tree.MethodDeclaration;
+import org.apache.calcite.linq4j.tree.ParameterExpression;
+import org.apache.calcite.plan.RelOptCluster;
+import org.apache.calcite.rel.RelCollation;
+import org.apache.calcite.rel.RelCollationImpl;
+import org.apache.calcite.rel.RelCollations;
+import org.apache.calcite.rel.RelDistribution.Type;
+import org.apache.calcite.rel.RelFieldCollation;
+import org.apache.calcite.rel.RelFieldCollation.Direction;
+import org.apache.calcite.rel.RelFieldCollation.NullDirection;
+import org.apache.calcite.rel.RelInput;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.core.AggregateCall;
+import org.apache.calcite.rel.core.CorrelationId;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rel.type.RelDataTypeFactory;
+import org.apache.calcite.rel.type.RelDataTypeFactoryImpl.JavaType;
+import org.apache.calcite.rel.type.RelDataTypeField;
+import org.apache.calcite.rex.RexBuilder;
+import org.apache.calcite.rex.RexCall;
+import org.apache.calcite.rex.RexDynamicParam;
+import org.apache.calcite.rex.RexFieldAccess;
+import org.apache.calcite.rex.RexFieldCollation;
+import org.apache.calcite.rex.RexLiteral;
+import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.rex.RexOver;
+import org.apache.calcite.rex.RexSlot;
+import org.apache.calcite.rex.RexVariable;
+import org.apache.calcite.rex.RexWindow;
+import org.apache.calcite.rex.RexWindowBound;
+import org.apache.calcite.sql.JoinConditionType;
+import org.apache.calcite.sql.JoinType;
+import org.apache.calcite.sql.SqlAggFunction;
+import org.apache.calcite.sql.SqlExplain;
+import org.apache.calcite.sql.SqlExplainFormat;
+import org.apache.calcite.sql.SqlExplainLevel;
+import org.apache.calcite.sql.SqlFunction;
+import org.apache.calcite.sql.SqlIdentifier;
+import org.apache.calcite.sql.SqlInsertKeyword;
+import org.apache.calcite.sql.SqlIntervalQualifier;
+import org.apache.calcite.sql.SqlJsonConstructorNullClause;
+import org.apache.calcite.sql.SqlJsonQueryWrapperBehavior;
+import org.apache.calcite.sql.SqlJsonValueEmptyOrErrorBehavior;
+import org.apache.calcite.sql.SqlKind;
+import org.apache.calcite.sql.SqlMatchRecognize;
+import org.apache.calcite.sql.SqlOperator;
+import org.apache.calcite.sql.SqlSelectKeyword;
+import org.apache.calcite.sql.SqlSyntax;
+import org.apache.calcite.sql.SqlWindow;
+import org.apache.calcite.sql.fun.SqlStdOperatorTable;
+import org.apache.calcite.sql.fun.SqlTrimFunction;
+import org.apache.calcite.sql.parser.SqlParserPos;
+import org.apache.calcite.sql.type.SqlTypeName;
+import org.apache.calcite.sql.validate.SqlNameMatchers;
+import org.apache.calcite.util.ImmutableBitSet;
+import org.apache.calcite.util.Util;
+import org.apache.ignite.internal.processors.query.calcite.rel.IgniteRel;
+import org.apache.ignite.internal.processors.query.calcite.trait.DistributionFunction;
+import org.apache.ignite.internal.processors.query.calcite.trait.DistributionFunction.AffinityDistribution;
+import org.apache.ignite.internal.processors.query.calcite.trait.DistributionTrait;
+import org.apache.ignite.internal.processors.query.calcite.trait.IgniteDistribution;
+import org.apache.ignite.internal.processors.query.calcite.trait.IgniteDistributions;
+import org.apache.ignite.internal.processors.query.calcite.util.Commons;
+import org.apache.ignite.internal.util.typedef.F;
+
+/**
+ * Utilities for converting {@link RelNode} into JSON format.
+ */
+@SuppressWarnings({"rawtypes", "unchecked"})
+class RelJson {
+ /** */
+ @FunctionalInterface
+ public static interface RelFactory extends Function<RelInput, RelNode> {
+ /** {@inheritDoc} */
+ @Override RelNode apply(RelInput input);
+ }
+
+ /** */
+ private static final LoadingCache<String, RelFactory> FACTORIES_CACHE = CacheBuilder.newBuilder()
+ .build(CacheLoader.from(RelJson::relFactory));
+
+ /** */
+ private static RelFactory relFactory(String typeName) {
+ Class<?> clazz = null;
+
+ if (!typeName.contains(".")) {
+ for (String package_ : PACKAGES) {
+ if ((clazz = classForName(package_ + typeName, true)) != null)
+ break;
+ }
+ }
+
+ if (clazz == null)
+ clazz = classForName(typeName, false);
+
+ assert RelNode.class.isAssignableFrom(clazz);
+
+ Constructor<RelNode> constructor;
+
+ try {
+ constructor = (Constructor<RelNode>)clazz.getConstructor(RelInput.class);
+ }
+ catch (NoSuchMethodException e) {
+ throw new RuntimeException("class does not have required constructor, "
+ + clazz + "(RelInput)");
+ }
+
+ ParameterExpression input_ = Expressions.parameter(RelInput.class);
+ BlockBuilder builder = new BlockBuilder();
+ builder.add(Expressions.new_(constructor, input_));
+ MethodDeclaration declaration = Expressions.methodDecl(
+ Modifier.PUBLIC, RelNode.class, "apply", F.asList(input_), builder.toBlock());
+ return Commons.compile(RelFactory.class, Expressions.toString(F.asList(declaration), "\n", true));
+ }
+
+ /** */
+ private static final ImmutableMap<String, Enum<?>> ENUM_BY_NAME;
+
+ /** */
+ static {
+ // Build a mapping from enum constants (e.g. LEADING) to the enum
+ // that contains them (e.g. SqlTrimFunction.Flag). If there two
+ // enum constants have the same name, the builder will throw.
+ final ImmutableMap.Builder<String, Enum<?>> enumByName =
+ ImmutableMap.builder();
+
+ register(enumByName, JoinConditionType.class);
+ register(enumByName, JoinType.class);
+ register(enumByName, Direction.class);
+ register(enumByName, NullDirection.class);
+ register(enumByName, SqlTypeName.class);
+ register(enumByName, SqlKind.class);
+ register(enumByName, SqlSyntax.class);
+ register(enumByName, SqlExplain.Depth.class);
+ register(enumByName, SqlExplainFormat.class);
+ register(enumByName, SqlExplainLevel.class);
+ register(enumByName, SqlInsertKeyword.class);
+ register(enumByName, SqlJsonConstructorNullClause.class);
+ register(enumByName, SqlJsonQueryWrapperBehavior.class);
+ register(enumByName, SqlJsonValueEmptyOrErrorBehavior.class);
+ register(enumByName, SqlMatchRecognize.AfterOption.class);
+ register(enumByName, SqlSelectKeyword.class);
+ register(enumByName, SqlTrimFunction.Flag.class);
+ register(enumByName, TimeUnitRange.class);
+ ENUM_BY_NAME = enumByName.build();
+ }
+
+ /** */
+ private static void register(ImmutableMap.Builder<String, Enum<?>> builder, Class<? extends Enum> aClass) {
+ String preffix = aClass.getSimpleName() + "#";
+ for (Enum enumConstant : aClass.getEnumConstants())
+ builder.put(preffix + enumConstant.name(), enumConstant);
+ }
+
+ /** */
+ private static Class<?> classForName(String typeName, boolean skipNotFound) {
+ try {
+ return Class.forName(typeName);
+ }
+ catch (ClassNotFoundException e) {
+ if (skipNotFound)
+ return null;
+
+ throw new RuntimeException("unknown type " + typeName);
+ }
+ }
+
+ /** */
+ private static final List<String> PACKAGES =
+ ImmutableList.of(
+ "org.apache.ignite.internal.processors.query.calcite.rel.",
+ "org.apache.calcite.rel.",
+ "org.apache.calcite.rel.core.",
+ "org.apache.calcite.rel.logical.",
+ "org.apache.calcite.adapter.jdbc.",
+ "org.apache.calcite.adapter.jdbc.JdbcRules$");
+
+ /** */
+ Function<RelInput, RelNode> factory(String type) {
+ return FACTORIES_CACHE.getUnchecked(type);
+ }
+
+ /** */
+ String classToTypeName(Class<? extends RelNode> class_) {
+ if (IgniteRel.class.isAssignableFrom(class_))
+ return class_.getSimpleName();
+
+ String canonicalName = class_.getName();
+ for (String package_ : PACKAGES) {
+ if (canonicalName.startsWith(package_)) {
+ String remaining = canonicalName.substring(package_.length());
+ if (remaining.indexOf('.') < 0 && remaining.indexOf('$') < 0)
+ return remaining;
+ }
+ }
+ return canonicalName;
+ }
+
+ /** */
+ Object toJson(Object value) {
+ if (value == null
+ || value instanceof Number
+ || value instanceof String
+ || value instanceof Boolean)
+ return value;
+ else if (value instanceof Enum)
+ return toJson((Enum)value);
+ else if (value instanceof RexNode)
+ return toJson((RexNode)value);
+ else if (value instanceof RexWindow)
+ return toJson((RexWindow)value);
+ else if (value instanceof RexFieldCollation)
+ return toJson((RexFieldCollation)value);
+ else if (value instanceof RexWindowBound)
+ return toJson((RexWindowBound)value);
+ else if (value instanceof CorrelationId)
+ return toJson((CorrelationId)value);
+ else if (value instanceof List) {
+ List<Object> list = list();
+ for (Object o : (List)value)
+ list.add(toJson(o));
+ return list;
+ }
+ else if (value instanceof ImmutableBitSet) {
+ List<Object> list = list();
+ for (Integer integer : (ImmutableBitSet)value)
+ list.add(toJson(integer));
+ return list;
+ }
+ else if (value instanceof DistributionTrait)
+ return toJson((DistributionTrait)value);
+ else if (value instanceof AggregateCall)
+ return toJson((AggregateCall)value);
+ else if (value instanceof RelCollationImpl)
+ return toJson((RelCollationImpl)value);
+ else if (value instanceof RelDataType)
+ return toJson((RelDataType)value);
+ else if (value instanceof RelDataTypeField)
+ return toJson((RelDataTypeField)value);
+ else
+ throw new UnsupportedOperationException("type not serializable: "
+ + value + " (type " + value.getClass().getCanonicalName() + ")");
+ }
+
+ /** */
+ RelCollation toCollation(List<Map<String, Object>> jsonFieldCollations) {
+ List<RelFieldCollation> fieldCollations = new ArrayList<>();
+ for (Map<String, Object> map : jsonFieldCollations)
+ fieldCollations.add(toFieldCollation(map));
+ return RelCollations.of(fieldCollations);
+ }
+
+ /** */
+ IgniteDistribution toDistribution(Object distribution) {
+ if (distribution instanceof String) {
+ switch ((String)distribution) {
+ case "single":
+ return IgniteDistributions.single();
+ case "any":
+ return IgniteDistributions.any();
+ case "broadcast":
+ return IgniteDistributions.broadcast();
+ case "random":
+ return IgniteDistributions.random();
+ }
+ }
+
+ Map<String, Object> map = (Map<String, Object>)distribution;
+
+ assert "hash".equals(map.get("type"));
+
+ DistributionFunction function = DistributionFunction.HashDistribution.INSTANCE;
+
+ Number cacheId = (Number)map.get("cacheId");
+
+ if (cacheId != null)
+ function = new AffinityDistribution(cacheId.intValue(), cacheId);
+
+ return IgniteDistributions.hash((List<Integer>)map.get("keys"), function);
+ }
+
+ /** */
+ RelDataType toType(RelDataTypeFactory typeFactory, Object o) {
+ if (o instanceof List) {
+ List<Map<String, Object>> jsonList = (List<Map<String, Object>>)o;
+ RelDataTypeFactory.Builder builder = typeFactory.builder();
+ for (Map<String, Object> jsonMap : jsonList)
+ builder.add((String)jsonMap.get("name"), toType(typeFactory, jsonMap));
+ return builder.build();
+ }
+ else if (o instanceof Map) {
+ Map<String, Object> map = (Map<String, Object>)o;
+ String clazz = (String)map.get("class");
+
+ if (clazz != null) {
+ RelDataType type = typeFactory.createJavaType(classForName(clazz, false));
+
+ if (Boolean.TRUE == map.get("nullable"))
+ type = typeFactory.createTypeWithNullability(type, true);
+
+ return type;
+ }
+
+ Object fields = map.get("fields");
+
+ if (fields != null)
+ return toType(typeFactory, fields);
+ else {
+ SqlTypeName sqlTypeName = toEnum(map.get("type"));
+ Integer precision = (Integer)map.get("precision");
+ Integer scale = (Integer)map.get("scale");
+ if (SqlTypeName.INTERVAL_TYPES.contains(sqlTypeName)) {
+ TimeUnit startUnit = sqlTypeName.getStartUnit();
+ TimeUnit endUnit = sqlTypeName.getEndUnit();
+ return typeFactory.createSqlIntervalType(
+ new SqlIntervalQualifier(startUnit, endUnit, SqlParserPos.ZERO));
+ }
+ RelDataType type;
+ if (precision == null)
+ type = typeFactory.createSqlType(sqlTypeName);
+ else if (scale == null)
+ type = typeFactory.createSqlType(sqlTypeName, precision);
+ else
+ type = typeFactory.createSqlType(sqlTypeName, precision, scale);
+
+ if (Boolean.TRUE == map.get("nullable"))
+ type = typeFactory.createTypeWithNullability(type, true);
+
+ return type;
+ }
+ }
+ else {
+ SqlTypeName sqlTypeName = toEnum(o);
+ return typeFactory.createSqlType(sqlTypeName);
+ }
+ }
+
+ /** */
+ RexNode toRex(RelInput relInput, Object o) {
+ RelOptCluster cluster = relInput.getCluster();
+ RexBuilder rexBuilder = cluster.getRexBuilder();
+ if (o == null)
+ return null;
+ else if (o instanceof Map) {
+ Map map = (Map)o;
+ Map<String, Object> opMap = (Map)map.get("op");
+ RelDataTypeFactory typeFactory = cluster.getTypeFactory();
+ if (opMap != null) {
+ if (map.containsKey("class"))
+ opMap.put("class", map.get("class"));
+ List operands = (List)map.get("operands");
+ List<RexNode> rexOperands = toRexList(relInput, operands);
+ Object jsonType = map.get("type");
+ Map window = (Map)map.get("window");
+ if (window != null) {
+ SqlAggFunction operator = (SqlAggFunction)toOp(opMap);
+ RelDataType type = toType(typeFactory, jsonType);
+ List<RexNode> partitionKeys = new ArrayList<>();
+ if (window.containsKey("partition"))
+ partitionKeys = toRexList(relInput, (List)window.get("partition"));
+ List<RexFieldCollation> orderKeys = new ArrayList<>();
+ if (window.containsKey("order"))
+ orderKeys = toRexFieldCollationList(relInput, (List)window.get("order"));
+ RexWindowBound lowerBound;
+ RexWindowBound upperBound;
+ boolean physical;
+ if (window.get("rows-lower") != null) {
+ lowerBound = toRexWindowBound(relInput, (Map)window.get("rows-lower"));
+ upperBound = toRexWindowBound(relInput, (Map)window.get("rows-upper"));
+ physical = true;
+ }
+ else if (window.get("range-lower") != null) {
+ lowerBound = toRexWindowBound(relInput, (Map)window.get("range-lower"));
+ upperBound = toRexWindowBound(relInput, (Map)window.get("range-upper"));
+ physical = false;
+ }
+ else {
+ // No ROWS or RANGE clause
+ lowerBound = null;
+ upperBound = null;
+ physical = false;
+ }
+ boolean distinct = (Boolean)map.get("distinct");
+ return rexBuilder.makeOver(type, operator, rexOperands, partitionKeys,
+ ImmutableList.copyOf(orderKeys), lowerBound, upperBound, physical,
+ true, false, distinct, false);
+ }
+ else {
+ SqlOperator operator = toOp(opMap);
+ RelDataType type;
+ if (jsonType != null)
+ type = toType(typeFactory, jsonType);
+ else
+ type = rexBuilder.deriveReturnType(operator, rexOperands);
+ return rexBuilder.makeCall(type, operator, rexOperands);
+ }
+ }
+ Integer input = (Integer)map.get("input");
+ if (input != null) {
+ // Check if it is a local ref.
+ if (map.containsKey("type")) {
+ RelDataType type = toType(typeFactory, map.get("type"));
+ return map.get("dynamic") == Boolean.TRUE
+ ? rexBuilder.makeDynamicParam(type, input)
+ : rexBuilder.makeLocalRef(type, input);
+ }
+
+ List<RelNode> inputNodes = relInput.getInputs();
+ int i = input;
+ for (RelNode inputNode : inputNodes) {
+ RelDataType rowType = inputNode.getRowType();
+ if (i < rowType.getFieldCount()) {
+ RelDataTypeField field = rowType.getFieldList().get(i);
+ return rexBuilder.makeInputRef(field.getType(), input);
+ }
+ i -= rowType.getFieldCount();
+ }
+ throw new RuntimeException("input field " + input + " is out of range");
+ }
+
+ String field = (String)map.get("field");
+ if (field != null) {
+ Object jsonExpr = map.get("expr");
+ RexNode expr = toRex(relInput, jsonExpr);
+ return rexBuilder.makeFieldAccess(expr, field, true);
+ }
+
+ String correl = (String)map.get("correl");
+ if (correl != null) {
+ RelDataType type = toType(typeFactory, map.get("type"));
+ return rexBuilder.makeCorrel(type, new CorrelationId(correl));
+ }
+
+ if (map.containsKey("literal")) {
+ Object literal = map.get("literal");
+ RelDataType type = toType(typeFactory, map.get("type"));
+
+ if (literal == null)
+ return rexBuilder.makeNullLiteral(type);
+
+ if (type.getSqlTypeName() == SqlTypeName.SYMBOL)
+ literal = toEnum(literal);
+
+ return rexBuilder.makeLiteral(literal, type, false);
+ }
+
+ throw new UnsupportedOperationException("cannot convert to rex " + o);
+ }
+ else if (o instanceof Boolean)
+ return rexBuilder.makeLiteral((Boolean)o);
+ else if (o instanceof String)
+ return rexBuilder.makeLiteral((String)o);
+ else if (o instanceof Number) {
+ Number number = (Number)o;
+ if (number instanceof Double || number instanceof Float)
+ return rexBuilder.makeApproxLiteral(
+ BigDecimal.valueOf(number.doubleValue()));
+ else
+ return rexBuilder.makeExactLiteral(
+ BigDecimal.valueOf(number.longValue()));
+ }
+ else
+ throw new UnsupportedOperationException("cannot convert to rex " + o);
+ }
+
+ /** */
+ SqlOperator toOp(Map<String, Object> map) {
+ // in case different operator has the same kind, check with both name and kind.
+ String name = map.get("name").toString();
+ SqlKind sqlKind = toEnum(map.get("kind"));
+ SqlSyntax sqlSyntax = toEnum(map.get("syntax"));
+ List<SqlOperator> operators = new ArrayList<>();
+ SqlStdOperatorTable.instance().lookupOperatorOverloads(
+ new SqlIdentifier(name, new SqlParserPos(0, 0)),
+ null,
+ sqlSyntax,
+ operators,
+ SqlNameMatchers.liberal());
+ for (SqlOperator operator : operators)
+ if (operator.kind == sqlKind)
+ return operator;
+ String class_ = (String)map.get("class");
+ if (class_ != null)
+ return AvaticaUtils.instantiatePlugin(SqlOperator.class, class_);
+ return null;
+ }
+
+ /** */
+ <T> List<T> list() {
+ return new ArrayList<>();
+ }
+
+ /** */
+ <T> Map<String, T> map() {
+ return new LinkedHashMap<>();
+ }
+
+ /** */
+ private <T extends Enum<T>> T toEnum(Object o) {
+ if (o instanceof Map) {
+ Map<String, Object> map = (Map<String, Object>)o;
+ String class_ = (String)map.get("class");
+ String name = map.get("name").toString();
+ return Util.enumVal((Class<T>)classForName(class_, false), name);
+ }
+
+ assert o instanceof String && ENUM_BY_NAME.containsKey(o);
+
+ String name = (String)o;
+ return (T)ENUM_BY_NAME.get(name);
+ }
+
+ /** */
+ private RelFieldCollation toFieldCollation(Map<String, Object> map) {
+ Integer field = (Integer)map.get("field");
+ Direction direction = toEnum(map.get("direction"));
+ NullDirection nullDirection = toEnum(map.get("nulls"));
+ return new RelFieldCollation(field, direction, nullDirection);
+ }
+
+ /** */
+ private List<RexFieldCollation> toRexFieldCollationList(RelInput relInput, List<Map<String, Object>> order) {
+ if (order == null)
+ return null;
+
+ List<RexFieldCollation> list = new ArrayList<>();
+ for (Map<String, Object> o : order) {
+ RexNode expr = toRex(relInput, o.get("expr"));
+ Set<SqlKind> directions = new HashSet<>();
+ if (toEnum(o.get("direction")) == Direction.DESCENDING)
+ directions.add(SqlKind.DESCENDING);
+ if (toEnum(o.get("null-direction")) == NullDirection.FIRST)
+ directions.add(SqlKind.NULLS_FIRST);
+ else
+ directions.add(SqlKind.NULLS_LAST);
+ list.add(new RexFieldCollation(expr, directions));
+ }
+ return list;
+ }
+
+ /** */
+ private RexWindowBound toRexWindowBound(RelInput input, Map<String, Object> map) {
+ if (map == null)
+ return null;
+
+ String type = (String)map.get("type");
+ switch (type) {
+ case "CURRENT_ROW":
+ return RexWindowBound.create(
+ SqlWindow.createCurrentRow(SqlParserPos.ZERO), null);
+ case "UNBOUNDED_PRECEDING":
+ return RexWindowBound.create(
+ SqlWindow.createUnboundedPreceding(SqlParserPos.ZERO), null);
+ case "UNBOUNDED_FOLLOWING":
+ return RexWindowBound.create(
+ SqlWindow.createUnboundedFollowing(SqlParserPos.ZERO), null);
+ case "PRECEDING":
+ RexNode precedingOffset = toRex(input, map.get("offset"));
+ return RexWindowBound.create(null,
+ input.getCluster().getRexBuilder().makeCall(
+ SqlWindow.PRECEDING_OPERATOR, precedingOffset));
+ case "FOLLOWING":
+ RexNode followingOffset = toRex(input, map.get("offset"));
+ return RexWindowBound.create(null,
+ input.getCluster().getRexBuilder().makeCall(
+ SqlWindow.FOLLOWING_OPERATOR, followingOffset));
+ default:
+ throw new UnsupportedOperationException("cannot convert type to rex window bound " + type);
+ }
+ }
+
+ /** */
+ private List<RexNode> toRexList(RelInput relInput, List<?> operands) {
+ List<RexNode> list = new ArrayList<>();
+ for (Object operand : operands)
+ list.add(toRex(relInput, operand));
+ return list;
+ }
+
+ /** */
+ private Object toJson(Enum<?> enum0) {
+ String key = enum0.getDeclaringClass().getSimpleName() + "#" + enum0.name();
+
+ if (ENUM_BY_NAME.get(key) == enum0)
+ return key;
+
+ Map<String, Object> map = map();
+ map.put("class", enum0.getDeclaringClass().getName());
+ map.put("name", enum0.name());
+ return map;
+ }
+
+ /** */
+ private Object toJson(AggregateCall node) {
+ Map<String, Object> map = map();
+ map.put("agg", toJson(node.getAggregation()));
+ map.put("type", toJson(node.getType()));
+ map.put("distinct", node.isDistinct());
+ map.put("operands", node.getArgList());
+ map.put("name", node.getName());
+ return map;
+ }
+
+ /** */
+ private Object toJson(RelDataType node) {
+ if (node instanceof JavaType) {
+ Map<String, Object> map = map();
+ map.put("class", ((JavaType)node).getJavaClass().getName());
+ if (node.isNullable())
+ map.put("nullable", true);
+
+ return map;
+ }
+ if (node.isStruct()) {
+ List<Object> list = list();
+ for (RelDataTypeField field : node.getFieldList())
+ list.add(toJson(field));
+ return list;
+ }
+ else {
+ Map<String, Object> map = map();
+ map.put("type", toJson(node.getSqlTypeName()));
+ if (node.isNullable())
+ map.put("nullable", true);
+ if (node.getSqlTypeName().allowsPrec())
+ map.put("precision", node.getPrecision());
+ if (node.getSqlTypeName().allowsScale())
+ map.put("scale", node.getScale());
+ return map;
+ }
+ }
+
+ /** */
+ private Object toJson(RelDataTypeField node) {
+ Map<String, Object> map;
+ if (node.getType().isStruct()) {
+ map = map();
+ map.put("fields", toJson(node.getType()));
+ }
+ else
+ map = (Map<String, Object>)toJson(node.getType());
+ map.put("name", node.getName());
+ return map;
+ }
+
+ /** */
+ private Object toJson(CorrelationId node) {
+ return node.getId();
+ }
+
+ /** */
+ private Object toJson(RexNode node) {
+ Map<String, Object> map;
+ switch (node.getKind()) {
+ case FIELD_ACCESS:
+ map = map();
+ RexFieldAccess fieldAccess = (RexFieldAccess)node;
+ map.put("field", fieldAccess.getField().getName());
+ map.put("expr", toJson(fieldAccess.getReferenceExpr()));
+
+ return map;
+ case LITERAL:
+ RexLiteral literal = (RexLiteral)node;
+ Object value = literal.getValue3();
+ map = map();
+ map.put("literal", toJson(value));
+ map.put("type", toJson(node.getType()));
+
+ return map;
+ case INPUT_REF:
+ map = map();
+ map.put("input", ((RexSlot)node).getIndex());
+ map.put("name", ((RexVariable)node).getName());
+
+ return map;
+ case DYNAMIC_PARAM:
+ map = map();
+ map.put("input", ((RexDynamicParam)node).getIndex());
+ map.put("name", ((RexVariable)node).getName());
+ map.put("type", toJson(node.getType()));
+ map.put("dynamic", true);
+
+ return map;
+ case LOCAL_REF:
+ map = map();
+ map.put("input", ((RexSlot)node).getIndex());
+ map.put("name", ((RexVariable)node).getName());
+ map.put("type", toJson(node.getType()));
+
+ return map;
+ case CORREL_VARIABLE:
+ map = map();
+ map.put("correl", ((RexVariable)node).getName());
+ map.put("type", toJson(node.getType()));
+
+ return map;
+ default:
+ if (node instanceof RexCall) {
+ RexCall call = (RexCall)node;
+ map = map();
+ map.put("op", toJson(call.getOperator()));
+ List<Object> list = list();
+
+ for (RexNode operand : call.getOperands())
+ list.add(toJson(operand));
+
+ map.put("operands", list);
+
+ if (node.getKind() == SqlKind.CAST)
+ map.put("type", toJson(node.getType()));
+
+ if (call.getOperator() instanceof SqlFunction)
+ if (((SqlFunction)call.getOperator()).getFunctionType().isUserDefined()) {
+ SqlOperator op = call.getOperator();
+ map.put("class", op.getClass().getName());
+ map.put("type", toJson(node.getType()));
+ map.put("deterministic", op.isDeterministic());
+ map.put("dynamic", op.isDynamicFunction());
+ }
+
+ if (call instanceof RexOver) {
+ RexOver over = (RexOver)call;
+ map.put("distinct", over.isDistinct());
+ map.put("type", toJson(node.getType()));
+ map.put("window", toJson(over.getWindow()));
+ }
+
+ return map;
+ }
+ throw new UnsupportedOperationException("unknown rex " + node);
+ }
+ }
+
+ /** */
+ private Object toJson(RexWindow window) {
+ Map<String, Object> map = map();
+ if (!window.partitionKeys.isEmpty())
+ map.put("partition", toJson(window.partitionKeys));
+ if (!window.orderKeys.isEmpty())
+ map.put("order", toJson(window.orderKeys));
+ if (window.getLowerBound() == null) {
+ // No ROWS or RANGE clause
+ }
+ else if (window.getUpperBound() == null)
+ if (window.isRows())
+ map.put("rows-lower", toJson(window.getLowerBound()));
+ else
+ map.put("range-lower", toJson(window.getLowerBound()));
+ else if (window.isRows()) {
+ map.put("rows-lower", toJson(window.getLowerBound()));
+ map.put("rows-upper", toJson(window.getUpperBound()));
+ }
+ else {
+ map.put("range-lower", toJson(window.getLowerBound()));
+ map.put("range-upper", toJson(window.getUpperBound()));
+ }
+ return map;
+ }
+
+ /** */
+ private Object toJson(DistributionTrait distribution) {
+ Type type = distribution.getType();
+
+ switch (type) {
+ case ANY:
+ case BROADCAST_DISTRIBUTED:
+ case RANDOM_DISTRIBUTED:
+ case SINGLETON:
+
+ return type.shortName;
+ case HASH_DISTRIBUTED:
+ Map<String, Object> map = map();
+ List<Object> keys = list();
+ for (Integer key : distribution.getKeys())
+ keys.add(toJson(key));
+
+ map.put("keys", keys);
+
+ if (distribution.function() instanceof AffinityDistribution)
+ map.put("cacheId", ((AffinityDistribution)distribution.function()).cacheId());
+
+ return map;
+ default:
+ throw new AssertionError("Unexpected type: " + type);
+ }
+ }
+
+ /** */
+ private Object toJson(RelCollationImpl node) {
+ List<Object> list = list();
+ for (RelFieldCollation fieldCollation : node.getFieldCollations()) {
+ Map<String, Object> map = map();
+ map.put("field", fieldCollation.getFieldIndex());
+ map.put("direction", toJson(fieldCollation.getDirection()));
+ map.put("nulls", toJson(fieldCollation.nullDirection));
+ list.add(map);
+ }
+ return list;
+ }
+
+ /** */
+ private Object toJson(RexFieldCollation collation) {
+ Map<String, Object> map = map();
+ map.put("expr", toJson(collation.left));
+ map.put("direction", toJson(collation.getDirection()));
+ map.put("null-direction", toJson(collation.getNullDirection()));
+ return map;
+ }
+
+ /** */
+ private Object toJson(RexWindowBound windowBound) {
+ Map<String, Object> map = map();
+ if (windowBound.isCurrentRow())
+ map.put("type", "CURRENT_ROW");
+ else if (windowBound.isUnbounded())
+ map.put("type", windowBound.isPreceding() ? "UNBOUNDED_PRECEDING" : "UNBOUNDED_FOLLOWING");
+ else {
+ map.put("type", windowBound.isPreceding() ? "PRECEDING" : "FOLLOWING");
+ map.put("offset", toJson(windowBound.getOffset()));
+ }
+ return map;
+ }
+
+ /** */
+ private Object toJson(SqlOperator operator) {
+ // User-defined operators are not yet handled.
+ Map map = map();
+ map.put("name", operator.getName());
+ map.put("kind", toJson(operator.kind));
+ map.put("syntax", toJson(operator.getSyntax()));
+ return map;
+ }
+}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/externalize/RelJsonReader.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/externalize/RelJsonReader.java
new file mode 100644
index 0000000..5c000e0
--- /dev/null
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/externalize/RelJsonReader.java
@@ -0,0 +1,310 @@
+/*
+ * 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.ignite.internal.processors.query.calcite.externalize;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.collect.ImmutableList;
+import java.util.AbstractList;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.function.Function;
+import org.apache.calcite.plan.RelOptCluster;
+import org.apache.calcite.plan.RelOptSchema;
+import org.apache.calcite.plan.RelOptTable;
+import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.rel.RelCollation;
+import org.apache.calcite.rel.RelCollations;
+import org.apache.calcite.rel.RelDistribution;
+import org.apache.calcite.rel.RelInput;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.core.AggregateCall;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rex.RexLiteral;
+import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.sql.SqlAggFunction;
+import org.apache.calcite.util.ImmutableBitSet;
+import org.apache.calcite.util.Pair;
+import org.apache.calcite.util.Util;
+import org.apache.ignite.IgniteException;
+
+/** */
+@SuppressWarnings({"rawtypes", "unchecked"})
+public class RelJsonReader {
+ /** */
+ private static final TypeReference<LinkedHashMap<String, Object>> TYPE_REF =
+ new TypeReference<LinkedHashMap<String, Object>>() {};
+
+ /** */
+ private final RelOptCluster cluster;
+
+ /** */
+ private final RelOptSchema relOptSchema;
+
+ /** */
+ private final RelJson relJson = new RelJson();
+
+ /** */
+ private final Map<String, RelNode> relMap = new LinkedHashMap<>();
+
+ /** */
+ private RelNode lastRel;
+
+ /** */
+ public RelJsonReader(RelOptCluster cluster, RelOptSchema relOptSchema) {
+ this.cluster = cluster;
+ this.relOptSchema = relOptSchema;
+ }
+
+ /** */
+ public RelNode read(String s) {
+ try {
+ lastRel = null;
+ Map<String, Object> o = new ObjectMapper().readValue(s, TYPE_REF);
+ List<Map<String, Object>> rels = (List)o.get("rels");
+ readRels(rels);
+ return lastRel;
+ }
+ catch (JsonProcessingException e) {
+ throw new IgniteException(e);
+ }
+ }
+
+ /** */
+ private void readRels(List<Map<String, Object>> jsonRels) {
+ for (Map<String, Object> jsonRel : jsonRels)
+ readRel(jsonRel);
+ }
+
+ /** */
+ private void readRel(Map<String, Object> jsonRel) {
+ String id = (String)jsonRel.get("id");
+ String type = (String)jsonRel.get("relOp");
+ Function<RelInput, RelNode> factory = relJson.factory(type);
+ RelNode rel = factory.apply(new RelInputImpl(jsonRel));
+ relMap.put(id, rel);
+ lastRel = rel;
+ }
+
+ /** */
+ private class RelInputImpl implements RelInput {
+ /** */
+ private final Map<String, Object> jsonRel;
+
+ /** */
+ private RelInputImpl(Map<String, Object> jsonRel) {
+ this.jsonRel = jsonRel;
+ }
+
+ /** {@inheritDoc} */
+ @Override public RelOptCluster getCluster() {
+ return cluster;
+ }
+
+ /** {@inheritDoc} */
+ @Override public RelTraitSet getTraitSet() {
+ return cluster.traitSet();
+ }
+
+ /** {@inheritDoc} */
+ @Override public RelOptTable getTable(String table) {
+ List<String> list = getStringList(table);
+ return relOptSchema.getTableForMember(list);
+ }
+
+ /** {@inheritDoc} */
+ @Override public RelNode getInput() {
+ List<RelNode> inputs = getInputs();
+ assert inputs.size() == 1;
+ return inputs.get(0);
+ }
+
+ /** {@inheritDoc} */
+ @Override public List<RelNode> getInputs() {
+ List<String> jsonInputs = getStringList("inputs");
+ if (jsonInputs == null)
+ return ImmutableList.of(lastRel);
+ List<RelNode> inputs = new ArrayList<>();
+ for (String jsonInput : jsonInputs)
+ inputs.add(lookupInput(jsonInput));
+ return inputs;
+ }
+
+ /** {@inheritDoc} */
+ @Override public RexNode getExpression(String tag) {
+ return relJson.toRex(this, jsonRel.get(tag));
+ }
+
+ /** {@inheritDoc} */
+ @Override public ImmutableBitSet getBitSet(String tag) {
+ return ImmutableBitSet.of(getIntegerList(tag));
+ }
+
+ /** {@inheritDoc} */
+ @Override public List<ImmutableBitSet> getBitSetList(String tag) {
+ List<List<Integer>> list = getIntegerListList(tag);
+ if (list == null)
+ return null;
+ ImmutableList.Builder<ImmutableBitSet> builder =
+ ImmutableList.builder();
+ for (List<Integer> integers : list)
+ builder.add(ImmutableBitSet.of(integers));
+ return builder.build();
+ }
+
+ /** {@inheritDoc} */
+ @Override public List<String> getStringList(String tag) {
+ return (List<String>)jsonRel.get(tag);
+ }
+
+ /** {@inheritDoc} */
+ @Override public List<Integer> getIntegerList(String tag) {
+ return (List<Integer>)jsonRel.get(tag);
+ }
+
+ /** {@inheritDoc} */
+ @Override public List<List<Integer>> getIntegerListList(String tag) {
+ return (List<List<Integer>>)jsonRel.get(tag);
+ }
+
+ /** {@inheritDoc} */
+ @Override public List<AggregateCall> getAggregateCalls(String tag) {
+ List<Map<String, Object>> jsonAggs = (List)jsonRel.get(tag);
+ List<AggregateCall> inputs = new ArrayList<>();
+ for (Map<String, Object> jsonAggCall : jsonAggs)
+ inputs.add(toAggCall(jsonAggCall));
+ return inputs;
+ }
+
+ /** {@inheritDoc} */
+ @Override public Object get(String tag) {
+ return jsonRel.get(tag);
+ }
+
+ /** {@inheritDoc} */
+ @Override public String getString(String tag) {
+ return (String)jsonRel.get(tag);
+ }
+
+ /** {@inheritDoc} */
+ @Override public float getFloat(String tag) {
+ return ((Number)jsonRel.get(tag)).floatValue();
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean getBoolean(String tag, boolean default_) {
+ Boolean b = (Boolean)jsonRel.get(tag);
+ return b != null ? b : default_;
+ }
+
+ /** {@inheritDoc} */
+ @Override public <E extends Enum<E>> E getEnum(String tag, Class<E> enumClass) {
+ return Util.enumVal(enumClass,
+ getString(tag).toUpperCase(Locale.ROOT));
+ }
+
+ /** {@inheritDoc} */
+ @Override public List<RexNode> getExpressionList(String tag) {
+ List<Object> jsonNodes = (List)jsonRel.get(tag);
+ List<RexNode> nodes = new ArrayList<>();
+ for (Object jsonNode : jsonNodes)
+ nodes.add(relJson.toRex(this, jsonNode));
+ return nodes;
+ }
+
+ /** {@inheritDoc} */
+ @Override public RelDataType getRowType(String tag) {
+ Object o = jsonRel.get(tag);
+ return relJson.toType(cluster.getTypeFactory(), o);
+ }
+
+ /** {@inheritDoc} */
+ @Override public RelDataType getRowType(String expressionsTag, String fieldsTag) {
+ List<RexNode> expressionList = getExpressionList(expressionsTag);
+ List<String> names =
+ (List<String>)get(fieldsTag);
+ return cluster.getTypeFactory().createStructType(
+ new AbstractList<Map.Entry<String, RelDataType>>() {
+ @Override public Map.Entry<String, RelDataType> get(int index) {
+ return Pair.of(names.get(index),
+ expressionList.get(index).getType());
+ }
+
+ @Override public int size() {
+ return names.size();
+ }
+ });
+ }
+
+ /** {@inheritDoc} */
+ @Override public RelCollation getCollation() {
+ return relJson.toCollation((List)get("collation"));
+ }
+
+ /** {@inheritDoc} */
+ @Override public RelDistribution getDistribution() {
+ return relJson.toDistribution(get("distribution"));
+ }
+
+ /** {@inheritDoc} */
+ @Override public ImmutableList<ImmutableList<RexLiteral>> getTuples(String tag) {
+ List<List> jsonTuples = (List)get(tag);
+ ImmutableList.Builder<ImmutableList<RexLiteral>> builder =
+ ImmutableList.builder();
+ for (List jsonTuple : jsonTuples)
+ builder.add(getTuple(jsonTuple));
+ return builder.build();
+ }
+
+ /** */
+ private RelNode lookupInput(String jsonInput) {
+ RelNode node = relMap.get(jsonInput);
+ if (node == null)
+ throw new RuntimeException("unknown id " + jsonInput
+ + " for relational expression");
+ return node;
+ }
+
+ /** */
+ private ImmutableList<RexLiteral> getTuple(List jsonTuple) {
+ ImmutableList.Builder<RexLiteral> builder =
+ ImmutableList.builder();
+ for (Object jsonValue : jsonTuple)
+ builder.add((RexLiteral)relJson.toRex(this, jsonValue));
+ return builder.build();
+ }
+
+ /** */
+ private AggregateCall toAggCall(Map<String, Object> jsonAggCall) {
+ Map<String, Object> aggMap = (Map)jsonAggCall.get("agg");
+ SqlAggFunction aggregation = (SqlAggFunction)relJson.toOp(aggMap);
+ Boolean distinct = (Boolean)jsonAggCall.get("distinct");
+ List<Integer> operands = (List<Integer>)jsonAggCall.get("operands");
+ Integer filterOperand = (Integer)jsonAggCall.get("filter");
+ RelDataType type = relJson.toType(cluster.getTypeFactory(), jsonAggCall.get("type"));
+ String name = (String)jsonAggCall.get("name");
+ return AggregateCall.create(aggregation, distinct, false, false, operands,
+ filterOperand == null ? -1 : filterOperand,
+ RelCollations.EMPTY,
+ type, name);
+ }
+ }
+}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/externalize/RelJsonWriter.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/externalize/RelJsonWriter.java
new file mode 100644
index 0000000..42b5f32
--- /dev/null
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/externalize/RelJsonWriter.java
@@ -0,0 +1,161 @@
+/*
+ * 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.ignite.internal.processors.query.calcite.externalize;
+
+import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.ObjectWriter;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.IdentityHashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.RelWriter;
+import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.sql.SqlExplainLevel;
+import org.apache.calcite.util.Pair;
+import org.apache.ignite.IgniteException;
+
+/**
+ * Callback for a relational expression to dump itself as JSON.
+ *
+ * @see RelJsonReader
+ */
+public class RelJsonWriter implements RelWriter {
+ /** */
+ private final RelJson relJson = new RelJson();
+
+ /** */
+ private final List<Object> relList = new ArrayList<>();
+
+ /** */
+ private final Map<RelNode, String> relIdMap = new IdentityHashMap<>();
+
+ /** */
+ private final boolean pretty;
+
+ /** */
+ private String previousId;
+
+ /** */
+ private List<Pair<String, Object>> items = new ArrayList<>();
+
+ /** */
+ public RelJsonWriter() {
+ this(false);
+ }
+
+ /** */
+ public RelJsonWriter(boolean pretty) {
+ this.pretty = pretty;
+ }
+
+ /** {@inheritDoc} */
+ @Override public final void explain(RelNode rel, List<Pair<String, Object>> valueList) {
+ try (RexNode.Closeable ignored = withRexNormalize()) {
+ explain_(rel, valueList);
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public SqlExplainLevel getDetailLevel() {
+ return SqlExplainLevel.ALL_ATTRIBUTES;
+ }
+
+ /** {@inheritDoc} */
+ @Override public RelWriter item(String term, Object value) {
+ items.add(Pair.of(term, value));
+ return this;
+ }
+
+ /** {@inheritDoc} */
+ @Override public RelWriter done(RelNode node) {
+ List<Pair<String, Object>> current0 = items;
+ items = new ArrayList<>();
+ explain_(node, current0);
+ return this;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean nest() {
+ return true;
+ }
+
+ /** */
+ public String asString() {
+ try (RexNode.Closeable ignored = withRexNormalize()) {
+ StringWriter writer = new StringWriter();
+ ObjectMapper mapper = new ObjectMapper();
+
+ ObjectWriter writer0 = pretty
+ ? mapper.writer(new DefaultPrettyPrinter())
+ : mapper.writer();
+
+ writer0
+ .withRootName("rels")
+ .writeValue(writer, relList);
+
+ return writer.toString();
+ }
+ catch (IOException e) {
+ throw new IgniteException(e);
+ }
+ }
+
+ /** */
+ private void explain_(RelNode rel, List<Pair<String, Object>> values) {
+ final Map<String, Object> map = relJson.map();
+
+ map.put("id", null); // ensure that id is the first attribute
+ map.put("relOp", relJson.classToTypeName(rel.getClass()));
+
+ for (Pair<String, Object> value : values) {
+ if (value.right instanceof RelNode)
+ continue;
+
+ map.put(value.left, relJson.toJson(value.right));
+ }
+ // omit 'inputs: ["3"]' if "3" is the preceding rel
+ final List<Object> list = explainInputs(rel.getInputs());
+ if (list.size() != 1 || !list.get(0).equals(previousId)) {
+ map.put("inputs", list);
+ }
+
+ final String id = Integer.toString(relIdMap.size());
+ relIdMap.put(rel, id);
+ map.put("id", id);
+
+ relList.add(map);
+ previousId = id;
+ }
+
+ /** */
+ private List<Object> explainInputs(List<RelNode> inputs) {
+ final List<Object> list = relJson.list();
+ for (RelNode input : inputs) {
+ String id = relIdMap.get(input);
+ if (id == null) {
+ input.explain(this);
+ id = previousId;
+ }
+ list.add(id);
+ }
+ return list;
+ }
+}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/message/MessageType.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/message/MessageType.java
index 24ee972..0f90bfd 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/message/MessageType.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/message/MessageType.java
@@ -18,6 +18,8 @@
package org.apache.ignite.internal.processors.query.calcite.message;
import java.util.function.Supplier;
+import org.apache.ignite.internal.processors.query.calcite.metadata.NodesMapping;
+import org.apache.ignite.internal.processors.query.calcite.prepare.FragmentDescription;
/**
*
@@ -29,7 +31,9 @@ public enum MessageType {
QUERY_BATCH_MESSAGE(303, QueryBatchMessage::new),
QUERY_ACKNOWLEDGE_MESSAGE(304, QueryBatchAcknowledgeMessage::new),
QUERY_INBOX_CANCEL_MESSAGE(305, InboxCancelMessage::new),
- GENERIC_ROW_MESSAGE(306, GenericRowMessage::new);
+ GENERIC_ROW_MESSAGE(306, GenericRowMessage::new),
+ NODES_MAPPING(350, NodesMapping::new),
+ FRAGMENT_DESCRIPTION(351, FragmentDescription::new);
/** */
private final int directType;
@@ -83,6 +87,10 @@ public enum MessageType {
return QUERY_INBOX_CANCEL_MESSAGE.newMessage();
case 306:
return GENERIC_ROW_MESSAGE.newMessage();
+ case 350:
+ return NODES_MAPPING.newMessage();
+ case 351:
+ return FRAGMENT_DESCRIPTION.newMessage();
default:
return null;
}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/message/QueryStartRequest.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/message/QueryStartRequest.java
index 5d7b675..7c71cca 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/message/QueryStartRequest.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/message/QueryStartRequest.java
@@ -22,7 +22,7 @@ import java.util.UUID;
import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.internal.GridDirectTransient;
import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
-import org.apache.ignite.internal.processors.query.calcite.serialize.PhysicalRel;
+import org.apache.ignite.internal.processors.query.calcite.prepare.FragmentDescription;
import org.apache.ignite.marshaller.Marshaller;
import org.apache.ignite.plugin.extensions.communication.MessageReader;
import org.apache.ignite.plugin.extensions.communication.MessageWriter;
@@ -38,20 +38,13 @@ public class QueryStartRequest implements MarshalableMessage {
private UUID queryId;
/** */
- private long fragmentId;
-
- /** */
- private int[] partitions;
-
- /** */
private AffinityTopologyVersion version;
/** */
- @GridDirectTransient
- private PhysicalRel root;
+ private FragmentDescription fragmentDescription;
/** */
- private byte[] rootBytes;
+ private String root;
/** */
@GridDirectTransient
@@ -61,20 +54,18 @@ public class QueryStartRequest implements MarshalableMessage {
private byte[] paramsBytes;
/** */
- public QueryStartRequest(UUID queryId, long fragmentId, String schema, PhysicalRel root, AffinityTopologyVersion version, int[] partitions, Object[] params) {
+ public QueryStartRequest(UUID queryId, String schema, String root, AffinityTopologyVersion version,
+ FragmentDescription fragmentDescription, Object[] params) {
this.schema = schema;
this.queryId = queryId;
- this.fragmentId = fragmentId;
- this.partitions = partitions;
+ this.fragmentDescription = fragmentDescription;
this.version = version;
this.root = root;
this.params = params;
}
/** */
- QueryStartRequest() {
-
- }
+ QueryStartRequest() {}
/**
* @return Schema name.
@@ -91,17 +82,10 @@ public class QueryStartRequest implements MarshalableMessage {
}
/**
- * @return Fragment ID.
+ * @return Fragment description.
*/
- public long fragmentId() {
- return fragmentId;
- }
-
- /**
- * @return Partitions.
- */
- public int[] partitions() {
- return partitions;
+ public FragmentDescription fragmentDescription() {
+ return fragmentDescription;
}
/**
@@ -114,7 +98,7 @@ public class QueryStartRequest implements MarshalableMessage {
/**
* @return Fragment plan.
*/
- public PhysicalRel root() {
+ public String root() {
return root;
}
@@ -127,20 +111,18 @@ public class QueryStartRequest implements MarshalableMessage {
/** {@inheritDoc} */
@Override public void prepareMarshal(Marshaller marshaller) throws IgniteCheckedException {
- if (rootBytes == null && root != null)
- rootBytes = marshaller.marshal(root);
-
if (paramsBytes == null && params != null)
paramsBytes = marshaller.marshal(params);
+
+ fragmentDescription.prepareMarshal(marshaller);
}
/** {@inheritDoc} */
@Override public void prepareUnmarshal(Marshaller marshaller, ClassLoader loader) throws IgniteCheckedException {
- if (root == null && rootBytes != null)
- root = marshaller.unmarshal(rootBytes, loader);
-
if (params == null && paramsBytes != null)
params = marshaller.unmarshal(paramsBytes, loader);
+
+ fragmentDescription.prepareUnmarshal(marshaller, loader);
}
/** {@inheritDoc} */
@@ -156,7 +138,7 @@ public class QueryStartRequest implements MarshalableMessage {
switch (writer.state()) {
case 0:
- if (!writer.writeLong("fragmentId", fragmentId))
+ if (!writer.writeMessage("fragmentDescription", fragmentDescription))
return false;
writer.incrementState();
@@ -168,30 +150,24 @@ public class QueryStartRequest implements MarshalableMessage {
writer.incrementState();
case 2:
- if (!writer.writeIntArray("partitions", partitions))
+ if (!writer.writeUuid("queryId", queryId))
return false;
writer.incrementState();
case 3:
- if (!writer.writeByteArray("rootBytes", rootBytes))
+ if (!writer.writeString("root", root))
return false;
writer.incrementState();
case 4:
- if (!writer.writeUuid("queryId", queryId))
- return false;
-
- writer.incrementState();
-
- case 5:
if (!writer.writeString("schema", schema))
return false;
writer.incrementState();
- case 6:
+ case 5:
if (!writer.writeAffinityTopologyVersion("version", version))
return false;
@@ -211,7 +187,7 @@ public class QueryStartRequest implements MarshalableMessage {
switch (reader.state()) {
case 0:
- fragmentId = reader.readLong("fragmentId");
+ fragmentDescription = reader.readMessage("fragmentDescription");
if (!reader.isLastRead())
return false;
@@ -227,7 +203,7 @@ public class QueryStartRequest implements MarshalableMessage {
reader.incrementState();
case 2:
- partitions = reader.readIntArray("partitions");
+ queryId = reader.readUuid("queryId");
if (!reader.isLastRead())
return false;
@@ -235,7 +211,7 @@ public class QueryStartRequest implements MarshalableMessage {
reader.incrementState();
case 3:
- rootBytes = reader.readByteArray("rootBytes");
+ root = reader.readString("root");
if (!reader.isLastRead())
return false;
@@ -243,14 +219,6 @@ public class QueryStartRequest implements MarshalableMessage {
reader.incrementState();
case 4:
- queryId = reader.readUuid("queryId");
-
- if (!reader.isLastRead())
- return false;
-
- reader.incrementState();
-
- case 5:
schema = reader.readString("schema");
if (!reader.isLastRead())
@@ -258,7 +226,7 @@ public class QueryStartRequest implements MarshalableMessage {
reader.incrementState();
- case 6:
+ case 5:
version = reader.readAffinityTopologyVersion("version");
if (!reader.isLastRead())
@@ -278,6 +246,6 @@ public class QueryStartRequest implements MarshalableMessage {
/** {@inheritDoc} */
@Override public byte fieldsCount() {
- return 7;
+ return 6;
}
}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/FragmentInfo.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/FragmentInfo.java
deleted file mode 100644
index c9bc75a..0000000
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/FragmentInfo.java
+++ /dev/null
@@ -1,141 +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.ignite.internal.processors.query.calcite.metadata;
-
-import com.google.common.collect.ImmutableList;
-import org.apache.ignite.internal.processors.query.calcite.prepare.RelTargetAware;
-import org.apache.ignite.internal.processors.query.calcite.rel.IgniteFilter;
-import org.apache.ignite.internal.util.typedef.F;
-
-/**
- * Collects meta information about a query fragment, mainly it is data
- * location and a list of nodes, capable to execute the fragment on.
- */
-public class FragmentInfo {
- /** */
- private final NodesMapping mapping;
-
- /** */
- private final ImmutableList<RelTargetAware> targetAwareList;
-
- /**
- * Constructs Values leaf fragment info.
- */
- public FragmentInfo() {
- this(ImmutableList.of(), null);
- }
-
- /**
- * Constructs Receiver leaf fragment info.
- *
- * @param targetAware A node that needs target information.
- */
- public FragmentInfo(RelTargetAware targetAware) {
- this(ImmutableList.of(targetAware), null);
- }
-
- /**
- * Constructs Scan leaf fragment info.
- *
- * @param mapping Nodes mapping, describing where interested data placed.
- */
- public FragmentInfo(NodesMapping mapping) {
- this(null, mapping);
- }
-
- /**
- * Used on merge of two relational node tree edges.
- *
- * @param targetAwareList nodes that need target information.
- * @param mapping Nodes mapping, describing where interested data placed.
- */
- public FragmentInfo(ImmutableList<RelTargetAware> targetAwareList, NodesMapping mapping) {
- this.targetAwareList = targetAwareList;
- this.mapping = mapping;
- }
-
- /**
- * @return Nodes mapping, describing where interested data placed.
- */
- public NodesMapping mapping() {
- return mapping;
- }
-
- /**
- * @return {@code True} if the fragment has nodes mapping.
- */
- public boolean mapped() {
- return mapping != null;
- }
-
- /**
- * @return Nodes that need target information..
- */
- public ImmutableList<RelTargetAware> targetAwareList() {
- return targetAwareList;
- }
-
- /**
- * Merges two FragmentInfo objects.
- * @param other FragmentInfo to merge with.
- * @return Resulting FragmentInfo.
- * @throws LocationMappingException in case there is no nodes capable to execute a query fragment.
- */
- public FragmentInfo merge(FragmentInfo other) throws LocationMappingException {
- return new FragmentInfo(
- merge(targetAwareList(), other.targetAwareList()),
- merge(mapping(), other.mapping()));
- }
-
- /**
- * Prunes involved partitions (hence nodes, involved in query execution) on the basis of filter,
- * its distribution, query parameters and original nodes mapping.
- * @param filter Filter.
- * @return Resulting fragment info.
- */
- public FragmentInfo prune(IgniteFilter filter) {
- if (mapping != null) {
- NodesMapping newMapping = mapping.prune(filter);
-
- if (newMapping != mapping)
- return new FragmentInfo(targetAwareList, newMapping);
- }
-
- return this;
- }
-
- /** */
- private static NodesMapping merge(NodesMapping left, NodesMapping right) throws LocationMappingException {
- if (left == null)
- return right;
- if (right == null)
- return left;
-
- return left.mergeWith(right);
- }
-
- /** */
- private static <T> ImmutableList<T> merge(ImmutableList<T> left, ImmutableList<T> right) {
- if (F.isEmpty(left))
- return right;
- if (F.isEmpty(right))
- return left;
-
- return ImmutableList.<T>builder().addAll(left).addAll(right).build();
- }
-}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/IgniteMdFragmentInfo.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/IgniteMdNodesMapping.java
similarity index 64%
rename from modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/IgniteMdFragmentInfo.java
rename to modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/IgniteMdNodesMapping.java
index b860711..087daf8 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/IgniteMdFragmentInfo.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/IgniteMdNodesMapping.java
@@ -29,7 +29,7 @@ import org.apache.calcite.rel.metadata.MetadataHandler;
import org.apache.calcite.rel.metadata.ReflectiveRelMetadataProvider;
import org.apache.calcite.rel.metadata.RelMetadataProvider;
import org.apache.calcite.rel.metadata.RelMetadataQuery;
-import org.apache.ignite.internal.processors.query.calcite.metadata.IgniteMetadata.FragmentMetadata;
+import org.apache.ignite.internal.processors.query.calcite.metadata.IgniteMetadata.NodesMappingMetadata;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteFilter;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteReceiver;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteTableScan;
@@ -39,49 +39,48 @@ import org.apache.ignite.internal.processors.query.calcite.util.Commons;
import org.apache.ignite.internal.processors.query.calcite.util.IgniteMethod;
/**
- * Implementation class for {@link RelMetadataQueryEx#getFragmentInfo(RelNode)} method call.
+ * Implementation class for {@link RelMetadataQueryEx#nodesMapping(RelNode)} method call.
*/
-public class IgniteMdFragmentInfo implements MetadataHandler<FragmentMetadata> {
+public class IgniteMdNodesMapping implements MetadataHandler<NodesMappingMetadata> {
/**
- * Metadata provider, responsible for fragment meta information request. It uses this implementation class under the hood.
+ * Metadata provider, responsible for nodes mapping request. It uses this implementation class under the hood.
*/
public static final RelMetadataProvider SOURCE =
ReflectiveRelMetadataProvider.reflectiveSource(
- IgniteMethod.FRAGMENT_INFO.method(), new IgniteMdFragmentInfo());
+ IgniteMethod.NODES_MAPPING.method(), new IgniteMdNodesMapping());
/** {@inheritDoc} */
- @Override public MetadataDef<FragmentMetadata> getDef() {
- return FragmentMetadata.DEF;
+ @Override public MetadataDef<NodesMappingMetadata> getDef() {
+ return NodesMappingMetadata.DEF;
}
/**
- * Requests meta information about a fragment with the given relation node at the head of the fragment, mainly it is data
- * location and a list of nodes, capable to execute the fragment on.
+ * Requests meta information about nodes capable to execute a query over particular partitions.
*
* @param rel Relational node.
* @param mq Metadata query instance. Used to request appropriate metadata from node children.
- * @return Fragment meta information.
+ * @return Nodes mapping, representing a list of nodes capable to execute a query over particular partitions.
*/
- public FragmentInfo fragmentInfo(RelNode rel, RelMetadataQuery mq) {
+ public NodesMapping nodesMapping(RelNode rel, RelMetadataQuery mq) {
throw new AssertionError();
}
/**
- * See {@link IgniteMdFragmentInfo#fragmentInfo(RelNode, RelMetadataQuery)}
+ * See {@link IgniteMdNodesMapping#nodesMapping(RelNode, RelMetadataQuery)}
*/
- public FragmentInfo fragmentInfo(RelSubset rel, RelMetadataQuery mq) {
+ public NodesMapping nodesMapping(RelSubset rel, RelMetadataQuery mq) {
throw new AssertionError();
}
/**
- * See {@link IgniteMdFragmentInfo#fragmentInfo(RelNode, RelMetadataQuery)}
+ * See {@link IgniteMdNodesMapping#nodesMapping(RelNode, RelMetadataQuery)}
*/
- public FragmentInfo fragmentInfo(SingleRel rel, RelMetadataQuery mq) {
- return _fragmentInfo(rel.getInput(), mq);
+ public NodesMapping nodesMapping(SingleRel rel, RelMetadataQuery mq) {
+ return _nodesMapping(rel.getInput(), mq);
}
/**
- * See {@link IgniteMdFragmentInfo#fragmentInfo(RelNode, RelMetadataQuery)}
+ * See {@link IgniteMdNodesMapping#nodesMapping(RelNode, RelMetadataQuery)}
*
* {@link LocationMappingException} may be thrown on two children nodes locations merge. This means
* that the fragment (which part the parent node is) cannot be executed on any node and additional exchange
@@ -89,20 +88,20 @@ public class IgniteMdFragmentInfo implements MetadataHandler<FragmentMetadata> {
* exchange. After the exchange is put into the fragment and the fragment is split into two ones, fragment meta
* information will be recalculated for all fragments.
*/
- public FragmentInfo fragmentInfo(BiRel rel, RelMetadataQuery mq) {
- FragmentInfo left = _fragmentInfo(rel.getLeft(), mq);
- FragmentInfo right = _fragmentInfo(rel.getRight(), mq);
+ public NodesMapping nodesMapping(BiRel rel, RelMetadataQuery mq) {
+ NodesMapping left = _nodesMapping(rel.getLeft(), mq);
+ NodesMapping right = _nodesMapping(rel.getRight(), mq);
try {
- return left.merge(right);
+ return merge(left, right);
}
catch (LocationMappingException e) {
String msg = "Failed to calculate physical distribution";
// a replicated cache is cheaper to redistribute
- if (!left.mapping().hasPartitionedCaches())
+ if (!left.hasPartitionedCaches())
throw new OptimisticPlanningException(msg, rel.getLeft(), e);
- else if (!right.mapping().hasPartitionedCaches())
+ else if (!right.hasPartitionedCaches())
throw new OptimisticPlanningException(msg, rel.getRight(), e);
else {
// both sub-trees have partitioned sources, less cost is better
@@ -117,7 +116,7 @@ public class IgniteMdFragmentInfo implements MetadataHandler<FragmentMetadata> {
}
/**
- * See {@link IgniteMdFragmentInfo#fragmentInfo(RelNode, RelMetadataQuery)}
+ * See {@link IgniteMdNodesMapping#nodesMapping(RelNode, RelMetadataQuery)}
*
* {@link LocationMappingException} may be thrown on two children nodes locations merge. This means
* that the fragment (which part the parent node is) cannot be executed on any node and additional exchange
@@ -125,14 +124,14 @@ public class IgniteMdFragmentInfo implements MetadataHandler<FragmentMetadata> {
* exchange. After the exchange is put into the fragment and the fragment is split into two ones, fragment meta
* information will be recalculated for all fragments.
*/
- public FragmentInfo fragmentInfo(SetOp rel, RelMetadataQuery mq) {
- FragmentInfo res = new FragmentInfo();
+ public NodesMapping nodesMapping(SetOp rel, RelMetadataQuery mq) {
+ NodesMapping res = null;
for (RelNode input : rel.getInputs()) {
- FragmentInfo inputInfo = _fragmentInfo(input, mq);
+ NodesMapping inputMapping = _nodesMapping(input, mq);
try {
- res = res.merge(inputInfo);
+ res = merge(res, inputMapping);
}
catch (LocationMappingException e) {
throw new OptimisticPlanningException("Failed to calculate physical distribution", input, e);
@@ -143,33 +142,35 @@ public class IgniteMdFragmentInfo implements MetadataHandler<FragmentMetadata> {
}
/**
- * See {@link IgniteMdFragmentInfo#fragmentInfo(RelNode, RelMetadataQuery)}
+ * See {@link IgniteMdNodesMapping#nodesMapping(RelNode, RelMetadataQuery)}
*
* Prunes involved partitions (hence nodes, involved in query execution) if possible.
*/
- public FragmentInfo fragmentInfo(IgniteFilter rel, RelMetadataQuery mq) {
- return _fragmentInfo(rel.getInput(), mq).prune(rel);
+ public NodesMapping nodesMapping(IgniteFilter rel, RelMetadataQuery mq) {
+ NodesMapping mapping = _nodesMapping(rel.getInput(), mq);
+
+ return mapping == null ? null : mapping.prune(rel);
}
/**
- * See {@link IgniteMdFragmentInfo#fragmentInfo(RelNode, RelMetadataQuery)}
+ * See {@link IgniteMdNodesMapping#nodesMapping(RelNode, RelMetadataQuery)}
*/
- public FragmentInfo fragmentInfo(IgniteReceiver rel, RelMetadataQuery mq) {
- return new FragmentInfo(rel.source());
+ public NodesMapping nodesMapping(IgniteReceiver rel, RelMetadataQuery mq) {
+ return null;
}
/**
- * See {@link IgniteMdFragmentInfo#fragmentInfo(RelNode, RelMetadataQuery)}
+ * See {@link IgniteMdNodesMapping#nodesMapping(RelNode, RelMetadataQuery)}
*/
- public FragmentInfo fragmentInfo(IgniteTableScan rel, RelMetadataQuery mq) {
- return new FragmentInfo(rel.getTable().unwrap(DistributedTable.class).mapping(Commons.context(rel)));
+ public NodesMapping nodesMapping(IgniteTableScan rel, RelMetadataQuery mq) {
+ return rel.getTable().unwrap(DistributedTable.class).mapping(Commons.context(rel));
}
/**
- * See {@link IgniteMdFragmentInfo#fragmentInfo(RelNode, RelMetadataQuery)}
+ * See {@link IgniteMdNodesMapping#nodesMapping(RelNode, RelMetadataQuery)}
*/
- public FragmentInfo fragmentInfo(IgniteValues rel, RelMetadataQuery mq) {
- return new FragmentInfo();
+ public NodesMapping nodesMapping(IgniteValues rel, RelMetadataQuery mq) {
+ return null;
}
/**
@@ -178,9 +179,20 @@ public class IgniteMdFragmentInfo implements MetadataHandler<FragmentMetadata> {
* @param mq Metadata query instance.
* @return Fragment meta information.
*/
- public static FragmentInfo _fragmentInfo(RelNode rel, RelMetadataQuery mq) {
+ public static NodesMapping _nodesMapping(RelNode rel, RelMetadataQuery mq) {
assert mq instanceof RelMetadataQueryEx;
- return ((RelMetadataQueryEx) mq).getFragmentInfo(rel);
+ return ((RelMetadataQueryEx) mq).nodesMapping(rel);
+ }
+
+ /** */
+ private static NodesMapping merge(NodesMapping mapping1, NodesMapping mapping2) throws LocationMappingException {
+ if (mapping1 == null)
+ return mapping2;
+
+ if (mapping2 == null)
+ return mapping1;
+
+ return mapping1.mergeWith(mapping2);
}
}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/IgniteMetadata.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/IgniteMetadata.java
index 8437f0b..87431d3 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/IgniteMetadata.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/IgniteMetadata.java
@@ -39,19 +39,19 @@ public class IgniteMetadata {
ImmutableList.of(
IgniteMdDerivedDistribution.SOURCE,
IgniteMdDistribution.SOURCE,
- IgniteMdFragmentInfo.SOURCE,
+ IgniteMdNodesMapping.SOURCE,
DefaultRelMetadataProvider.INSTANCE));
- public interface FragmentMetadata extends Metadata {
- MetadataDef<FragmentMetadata> DEF = MetadataDef.of(FragmentMetadata.class,
- FragmentMetadata.Handler.class, IgniteMethod.FRAGMENT_INFO.method());
+ public interface NodesMappingMetadata extends Metadata {
+ MetadataDef<NodesMappingMetadata> DEF = MetadataDef.of(NodesMappingMetadata.class,
+ NodesMappingMetadata.Handler.class, IgniteMethod.NODES_MAPPING.method());
/** Determines how the rows are distributed. */
- FragmentInfo fragmentInfo();
+ NodesMapping nodesMapping();
/** Handler API. */
- interface Handler extends MetadataHandler<FragmentMetadata> {
- FragmentInfo fragmentInfo(RelNode r, RelMetadataQuery mq);
+ interface Handler extends MetadataHandler<NodesMappingMetadata> {
+ NodesMapping nodesMapping(RelNode r, RelMetadataQuery mq);
}
}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/NodesMapping.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/NodesMapping.java
index 3bb89b0..0af3792 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/NodesMapping.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/NodesMapping.java
@@ -17,24 +17,34 @@
package org.apache.ignite.internal.processors.query.calcite.metadata;
-import java.io.Serializable;
+import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.internal.GridDirectCollection;
+import org.apache.ignite.internal.GridDirectTransient;
import org.apache.ignite.internal.processors.cache.distributed.dht.topology.GridDhtPartitionState;
+import org.apache.ignite.internal.processors.query.calcite.message.MarshalableMessage;
+import org.apache.ignite.internal.processors.query.calcite.message.MessageType;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteFilter;
import org.apache.ignite.internal.processors.query.calcite.util.Commons;
import org.apache.ignite.internal.util.GridIntList;
+import org.apache.ignite.internal.util.UUIDCollectionMessage;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.marshaller.Marshaller;
+import org.apache.ignite.plugin.extensions.communication.Message;
+import org.apache.ignite.plugin.extensions.communication.MessageCollectionItemType;
+import org.apache.ignite.plugin.extensions.communication.MessageReader;
+import org.apache.ignite.plugin.extensions.communication.MessageWriter;
/**
* Represents a list of nodes capable to execute a query over particular partitions.
*/
-public class NodesMapping implements Serializable {
+public class NodesMapping implements MarshalableMessage {
/** */
public static final byte HAS_MOVING_PARTITIONS = 1;
@@ -54,13 +64,23 @@ public class NodesMapping implements Serializable {
public static final byte CLIENT = 1 << 5;
/** */
- private final List<UUID> nodes;
+ @GridDirectCollection(UUID.class)
+ private List<UUID> nodes;
/** */
- private final List<List<UUID>> assignments;
+ @GridDirectTransient
+ private List<List<UUID>> assignments;
/** */
- private final byte flags;
+ @GridDirectCollection(Message.class)
+ private List<UUIDCollectionMessage> assignments0;
+
+ /** */
+ private byte flags;
+
+ /** */
+ public NodesMapping() {
+ }
/** */
public NodesMapping(List<UUID> nodes, List<List<UUID>> assignments, byte flags) {
@@ -104,6 +124,9 @@ public class NodesMapping implements Serializable {
public NodesMapping mergeWith(NodesMapping other) throws LocationMappingException {
byte flags = (byte) (this.flags | other.flags);
+ // reset posiible set deduplicated flag
+ flags &= ~DEDUPLICATED;
+
List<UUID> nodes = intersectReplicated(this.nodes, other.nodes);
// if there is no moving partitions both assignments are identical.
@@ -259,4 +282,108 @@ public class NodesMapping implements Serializable {
return res;
}
+
+ /** {@inheritDoc} */
+ @Override public MessageType type() {
+ return MessageType.NODES_MAPPING;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean writeTo(ByteBuffer buf, MessageWriter writer) {
+ writer.setBuffer(buf);
+
+ if (!writer.isHeaderWritten()) {
+ if (!writer.writeHeader(directType(), fieldsCount()))
+ return false;
+
+ writer.onHeaderWritten();
+ }
+
+ switch (writer.state()) {
+ case 0:
+ if (!writer.writeCollection("assignments0", assignments0, MessageCollectionItemType.MSG))
+ return false;
+
+ writer.incrementState();
+
+ case 1:
+ if (!writer.writeByte("flags", flags))
+ return false;
+
+ writer.incrementState();
+
+ case 2:
+ if (!writer.writeCollection("nodes", nodes, MessageCollectionItemType.UUID))
+ return false;
+
+ writer.incrementState();
+
+ }
+
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean readFrom(ByteBuffer buf, MessageReader reader) {
+ reader.setBuffer(buf);
+
+ if (!reader.beforeMessageRead())
+ return false;
+
+ switch (reader.state()) {
+ case 0:
+ assignments0 = reader.readCollection("assignments0", MessageCollectionItemType.MSG);
+
+ if (!reader.isLastRead())
+ return false;
+
+ reader.incrementState();
+
+ case 1:
+ flags = reader.readByte("flags");
+
+ if (!reader.isLastRead())
+ return false;
+
+ reader.incrementState();
+
+ case 2:
+ nodes = reader.readCollection("nodes", MessageCollectionItemType.UUID);
+
+ if (!reader.isLastRead())
+ return false;
+
+ reader.incrementState();
+
+ }
+
+ return reader.afterMessageRead(NodesMapping.class);
+ }
+
+ /** {@inheritDoc} */
+ @Override public byte fieldsCount() {
+ return 3;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void prepareMarshal(Marshaller marshaller) {
+ if (assignments != null && assignments0 == null)
+ assignments0 = Commons.transform(assignments, this::transform);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void prepareUnmarshal(Marshaller marshaller, ClassLoader loader) {
+ if (assignments0 != null && assignments == null)
+ assignments = Commons.transform(assignments0, this::transform);
+ }
+
+ /** */
+ private List<UUID> transform(UUIDCollectionMessage message) {
+ return message.uuids() instanceof List ? (List<UUID>)message.uuids() : new ArrayList<>(message.uuids());
+ }
+
+ /** */
+ private UUIDCollectionMessage transform(List<UUID> uuids) {
+ return new UUIDCollectionMessage(uuids);
+ }
}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/RelMetadataQueryEx.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/RelMetadataQueryEx.java
index 4b4bc29..fc6e4fc 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/RelMetadataQueryEx.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/RelMetadataQueryEx.java
@@ -53,15 +53,15 @@ public class RelMetadataQueryEx extends RelMetadataQuery {
}
/** */
- private static final IgniteMetadata.FragmentMetadata.Handler SOURCE_DISTRIBUTION_INITIAL_HANDLER =
- initialHandler(IgniteMetadata.FragmentMetadata.Handler.class);
+ private static final IgniteMetadata.NodesMappingMetadata.Handler SOURCE_DISTRIBUTION_INITIAL_HANDLER =
+ initialHandler(IgniteMetadata.NodesMappingMetadata.Handler.class);
/** */
private static final IgniteMetadata.DerivedDistribution.Handler DERIVED_DISTRIBUTIONS_INITIAL_HANDLER =
initialHandler(IgniteMetadata.DerivedDistribution.Handler.class);
/** */
- private IgniteMetadata.FragmentMetadata.Handler sourceDistributionHandler;
+ private IgniteMetadata.NodesMappingMetadata.Handler sourceDistributionHandler;
/** */
private IgniteMetadata.DerivedDistribution.Handler derivedDistributionsHandler;
@@ -97,17 +97,17 @@ public class RelMetadataQueryEx extends RelMetadataQuery {
}
/**
- * Calculates fragment meta information, the given relation node is a root of.
+ * Calculates data location mapping for a query fragment the given relation node is a root of.
*
* @param rel Relational node.
* @return Fragment meta information.
*/
- public FragmentInfo getFragmentInfo(RelNode rel) {
+ public NodesMapping nodesMapping(RelNode rel) {
for (;;) {
try {
- return sourceDistributionHandler.fragmentInfo(rel, this);
+ return sourceDistributionHandler.nodesMapping(rel, this);
} catch (JaninoRelMetadataProvider.NoHandler e) {
- sourceDistributionHandler = revise(e.relClass, IgniteMetadata.FragmentMetadata.DEF);
+ sourceDistributionHandler = revise(e.relClass, IgniteMetadata.NodesMappingMetadata.DEF);
}
}
}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/AbstractMultiStepPlan.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/AbstractMultiStepPlan.java
index c759379..cc1e6e8 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/AbstractMultiStepPlan.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/AbstractMultiStepPlan.java
@@ -17,13 +17,20 @@
package org.apache.ignite.internal.processors.query.calcite.prepare;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
+import java.util.UUID;
import org.apache.calcite.rel.metadata.RelMetadataQuery;
import org.apache.ignite.internal.processors.query.GridQueryFieldMetadata;
import org.apache.ignite.internal.processors.query.IgniteSQLException;
import org.apache.ignite.internal.processors.query.calcite.metadata.MappingService;
+import org.apache.ignite.internal.processors.query.calcite.metadata.NodesMapping;
import org.apache.ignite.internal.processors.query.calcite.metadata.OptimisticPlanningException;
+import org.apache.ignite.internal.processors.query.calcite.rel.IgniteReceiver;
+import org.apache.ignite.internal.processors.query.calcite.rel.IgniteSender;
import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.internal.U;
/**
*
@@ -35,6 +42,10 @@ public abstract class AbstractMultiStepPlan implements MultiStepPlan {
/** */
protected final List<GridQueryFieldMetadata> fieldsMeta;
+ /** */
+ protected Map<Long, NodesMapping> mappings;
+
+ /** */
protected AbstractMultiStepPlan(List<Fragment> fragments, List<GridQueryFieldMetadata> fieldsMeta) {
this.fragments = fragments;
this.fieldsMeta = fieldsMeta;
@@ -51,14 +62,44 @@ public abstract class AbstractMultiStepPlan implements MultiStepPlan {
}
/** {@inheritDoc} */
+ @Override public NodesMapping fragmentMapping(Fragment fragment) {
+ return fragmentMapping(fragment.fragmentId());
+ }
+
+ /** {@inheritDoc} */
+ @Override public NodesMapping targetMapping(Fragment fragment) {
+ if (fragment.local())
+ return null;
+
+ return fragmentMapping(((IgniteSender)fragment.root()).targetFragmentId());
+ }
+
+ /** {@inheritDoc} */
+ @Override public Map<Long, List<UUID>> remoteSources(Fragment fragment) {
+ List<IgniteReceiver> remotes = fragment.remotes();
+
+ if (F.isEmpty(remotes))
+ return null;
+
+ HashMap<Long, List<UUID>> res = U.newHashMap(remotes.size());
+
+ for (IgniteReceiver remote : remotes)
+ res.put(remote.exchangeId(), fragmentMapping(remote.sourceFragmentId()).nodes());
+
+ return res;
+ }
+
+ /** {@inheritDoc} */
@Override public void init(MappingService mappingService, PlanningContext ctx) {
+ mappings = U.newHashMap(fragments.size());
+
RelMetadataQuery mq = F.first(fragments).root().getCluster().getMetadataQuery();
for (int i = 0, j = 0; i < fragments.size();) {
Fragment fragment = fragments.get(i);
try {
- fragment.init(mappingService, ctx, mq);
+ mappings.put(fragment.fragmentId(), fragment.map(mappingService, ctx, mq));
i++;
}
@@ -66,18 +107,45 @@ public abstract class AbstractMultiStepPlan implements MultiStepPlan {
if (++j > 3)
throw new IgniteSQLException("Failed to map query.", e);
- replace(fragment, new FragmentSplitter().go(fragment, e.node(), mq));
+ replace(fragment, new FragmentSplitter(e.node()).go(fragment));
- i = 0; // restart init routine.
+ // restart init routine.
+ mappings.clear();
+ i = 0;
}
}
}
/** */
+ private NodesMapping fragmentMapping(long fragmentId) {
+ return mappings == null ? null : mappings.get(fragmentId);
+ }
+
+ /** */
private void replace(Fragment fragment, List<Fragment> replacement) {
assert !F.isEmpty(replacement);
- fragments.set(fragments.indexOf(fragment), F.first(replacement));
+ Map<Long, Long> newTargets = new HashMap<>();
+
+ for (Fragment fragment0 : replacement) {
+ for (IgniteReceiver remote : fragment0.remotes())
+ newTargets.put(remote.exchangeId(), fragment0.fragmentId());
+ }
+
+ for (int i = 0; i < fragments.size(); i++) {
+ Fragment fragment0 = fragments.get(i);
+
+ if (fragment0 == fragment)
+ fragments.set(i, F.first(replacement));
+ else if (!fragment0.local()) {
+ IgniteSender sender = (IgniteSender)fragment0.root();
+ Long newTargetId = newTargets.get(sender.exchangeId());
+
+ if (newTargetId != null)
+ sender.targetFragmentId(newTargetId);
+ }
+ }
+
fragments.addAll(replacement.subList(1, replacement.size()));
}
}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/Cloner.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/Cloner.java
index b13f99a..9d2bacd 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/Cloner.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/Cloner.java
@@ -17,11 +17,10 @@
package org.apache.ignite.internal.processors.query.calcite.prepare;
+import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
import org.apache.calcite.plan.RelOptCluster;
-import org.apache.calcite.prepare.Prepare;
import org.apache.calcite.rel.RelNode;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteAggregate;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteExchange;
@@ -48,17 +47,10 @@ class Cloner implements IgniteRelVisitor<IgniteRel> {
private final RelOptCluster cluster;
/** */
- private final Prepare.CatalogReader catalogReader;
+ private FragmentProto curr;
- /** */
- private List<Fragment> fragments;
-
- /**
- * @param ctx Planner context.
- */
- Cloner(PlanningContext ctx) {
- cluster = ctx.createCluster();
- catalogReader = ctx.catalogReader();
+ Cloner(RelOptCluster cluster) {
+ this.cluster = cluster;
}
/**
@@ -70,15 +62,14 @@ class Cloner implements IgniteRelVisitor<IgniteRel> {
List<Fragment> go(List<Fragment> src) {
assert !F.isEmpty(src);
- fragments = new ArrayList<>(src.size());
+ List<Fragment> fragments = new ArrayList<>(src.size());
- Fragment first = F.first(src);
-
- fragments.add(new Fragment(first.fragmentId(), visit(first.root())));
-
- assert fragments.size() == src.size();
-
- Collections.reverse(fragments);
+ for (Fragment fragment : src) {
+ curr = new FragmentProto(fragment.fragmentId(), fragment.root());
+ curr.root = visit(curr.root);
+ fragments.add(curr.build());
+ curr = null;
+ }
return fragments;
}
@@ -87,7 +78,7 @@ class Cloner implements IgniteRelVisitor<IgniteRel> {
@Override public IgniteRel visit(IgniteSender rel) {
IgniteRel input = visit((IgniteRel) rel.getInput());
- return new IgniteSender(cluster, rel.getTraitSet(), input);
+ return new IgniteSender(cluster, rel.getTraitSet(), input, rel.exchangeId(), rel.targetFragmentId(), rel.distribution());
}
/** {@inheritDoc} */
@@ -101,7 +92,7 @@ class Cloner implements IgniteRelVisitor<IgniteRel> {
@Override public IgniteRel visit(IgniteTrimExchange rel) {
RelNode input = visit((IgniteRel) rel.getInput());
- return new IgniteTrimExchange(cluster, rel.getTraitSet(), input);
+ return new IgniteTrimExchange(cluster, rel.getTraitSet(), input, rel.distribution());
}
/** {@inheritDoc} */
@@ -115,7 +106,7 @@ class Cloner implements IgniteRelVisitor<IgniteRel> {
@Override public IgniteRel visit(IgniteTableModify rel) {
RelNode input = visit((IgniteRel) rel.getInput());
- return new IgniteTableModify(cluster, rel.getTraitSet(), rel.getTable(), catalogReader, input,
+ return new IgniteTableModify(cluster, rel.getTraitSet(), rel.getTable(), input,
rel.getOperation(), rel.getUpdateColumnList(), rel.getSourceExpressionList(), rel.isFlattened());
}
@@ -146,10 +137,12 @@ class Cloner implements IgniteRelVisitor<IgniteRel> {
/** {@inheritDoc} */
@Override public IgniteRel visit(IgniteReceiver rel) {
- Fragment fragment = rel.source();
- fragments.add(fragment = new Fragment(fragment.fragmentId(), visit(fragment.root())));
+ IgniteReceiver receiver = new IgniteReceiver(cluster, rel.getTraitSet(), rel.getRowType(),
+ rel.exchangeId(), rel.sourceFragmentId());
+
+ curr.remotes.add(receiver);
- return new IgniteReceiver(cluster, rel.getTraitSet(), fragment);
+ return receiver;
}
/** {@inheritDoc} */
@@ -187,4 +180,26 @@ class Cloner implements IgniteRelVisitor<IgniteRel> {
@Override public IgniteRel visit(IgniteRel rel) {
return rel.accept(this);
}
+
+ /** */
+ private static class FragmentProto {
+ /** */
+ private final long id;
+
+ /** */
+ private IgniteRel root;
+
+ /** */
+ private final ImmutableList.Builder<IgniteReceiver> remotes = ImmutableList.builder();
+
+ /** */
+ private FragmentProto(long id, IgniteRel root) {
+ this.id = id;
+ this.root = root;
+ }
+
+ Fragment build() {
+ return new Fragment(id, root, remotes.build());
+ }
+ }
}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/Fragment.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/Fragment.java
index 43251b1..9680f31 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/Fragment.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/Fragment.java
@@ -17,19 +17,20 @@
package org.apache.ignite.internal.processors.query.calcite.prepare;
+import com.google.common.collect.ImmutableList;
import java.util.Collections;
+import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
import org.apache.calcite.rel.RelDistribution;
import org.apache.calcite.rel.metadata.RelMetadataQuery;
-import org.apache.ignite.internal.processors.query.calcite.metadata.FragmentInfo;
-import org.apache.ignite.internal.processors.query.calcite.metadata.IgniteMdFragmentInfo;
+import org.apache.ignite.internal.processors.query.calcite.metadata.IgniteMdNodesMapping;
import org.apache.ignite.internal.processors.query.calcite.metadata.LocationMappingException;
import org.apache.ignite.internal.processors.query.calcite.metadata.MappingService;
import org.apache.ignite.internal.processors.query.calcite.metadata.NodesMapping;
import org.apache.ignite.internal.processors.query.calcite.metadata.OptimisticPlanningException;
+import org.apache.ignite.internal.processors.query.calcite.rel.IgniteReceiver;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteRel;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteSender;
-import org.apache.ignite.internal.util.typedef.F;
import static org.apache.calcite.rel.RelDistribution.Type.BROADCAST_DISTRIBUTED;
import static org.apache.calcite.rel.RelDistribution.Type.SINGLETON;
@@ -37,9 +38,9 @@ import static org.apache.calcite.rel.RelDistribution.Type.SINGLETON;
/**
* Fragment of distributed query
*/
-public class Fragment implements RelTargetAware {
+public class Fragment {
/** */
- private static final AtomicLong ID_GEN = new AtomicLong();
+ static final AtomicLong ID_GEN = new AtomicLong();
/** */
private final long id;
@@ -48,50 +49,48 @@ public class Fragment implements RelTargetAware {
private final IgniteRel root;
/** */
- private NodesMapping mapping;
-
- /**
- * @param root Root node of the fragment.
- */
- public Fragment(IgniteRel root) {
- this(ID_GEN.getAndIncrement(), root);
- }
+ private final ImmutableList<IgniteReceiver> remotes;
/**
* @param id Fragment id.
* @param root Root node of the fragment.
+ * @param remotes Remote sources of the fragment.
*/
- public Fragment(long id, IgniteRel root){
+ public Fragment(long id, IgniteRel root, List<IgniteReceiver> remotes){
this.id = id;
this.root = root;
+ this.remotes = ImmutableList.copyOf(remotes);
}
/**
- * Inits fragment and its dependencies. Mainly init process consists of data location calculation.
+ * Mapps the fragment to its data location.
*
* @param mappingService Mapping service.
* @param ctx Planner context.
- * @param mq Metadata query used for data location calculation.
+ * @param mq Metadata query.
*/
- public void init(MappingService mappingService, PlanningContext ctx, RelMetadataQuery mq) throws OptimisticPlanningException {
- FragmentInfo info = IgniteMdFragmentInfo._fragmentInfo(root, mq);
-
- mapping = fragmentMapping(mappingService, ctx, info);
+ NodesMapping map(MappingService mappingService, PlanningContext ctx, RelMetadataQuery mq) throws OptimisticPlanningException {
+ NodesMapping mapping = IgniteMdNodesMapping._nodesMapping(root, mq);
- if (F.isEmpty(info.targetAwareList()))
- return;
+ try {
+ if (mapping != null)
+ mapping = local() ? localMapping(ctx).mergeWith(mapping) : mapping;
+ else if (local())
+ mapping = localMapping(ctx);
+ else {
+ RelDistribution.Type type = ((IgniteSender)root).sourceDistribution().getType();
- RelTargetImpl target = new RelTargetImpl(id, mapping);
+ boolean single = type == SINGLETON || type == BROADCAST_DISTRIBUTED;
- for (RelTargetAware aware : info.targetAwareList())
- aware.target(target);
- }
+ // TODO selection strategy.
+ mapping = mappingService.mapBalanced(ctx.topologyVersion(), single ? 1 : 0, null);
+ }
+ }
+ catch (LocationMappingException e) {
+ throw new OptimisticPlanningException("Failed to calculate physical distribution", root, e);
+ }
- /**
- * @return Root node.
- */
- public IgniteRel root() {
- return root;
+ return mapping.deduplicate();
}
/**
@@ -102,17 +101,17 @@ public class Fragment implements RelTargetAware {
}
/**
- * @return Fragment mapping.
+ * @return Root node.
*/
- public NodesMapping mapping() {
- return mapping;
+ public IgniteRel root() {
+ return root;
}
- /** {@inheritDoc} */
- @Override public void target(RelTarget target) {
- assert root instanceof RelTargetAware;
-
- ((RelTargetAware) root).target(target);
+ /**
+ * @return Fragment remote sources.
+ */
+ public List<IgniteReceiver> remotes() {
+ return remotes;
}
/** */
@@ -121,31 +120,6 @@ public class Fragment implements RelTargetAware {
}
/** */
- private NodesMapping fragmentMapping(MappingService mappingService, PlanningContext ctx, FragmentInfo info) throws OptimisticPlanningException {
- NodesMapping mapping;
-
- try {
- if (info.mapped())
- mapping = local() ? localMapping(ctx).mergeWith(info.mapping()) : info.mapping();
- else if (local())
- mapping = localMapping(ctx);
- else {
- RelDistribution.Type type = ((IgniteSender)root).sourceDistribution().getType();
-
- boolean single = type == SINGLETON || type == BROADCAST_DISTRIBUTED;
-
- // TODO selection strategy.
- mapping = mappingService.mapBalanced(ctx.topologyVersion(), single ? 1 : 0, null);
- }
- }
- catch (LocationMappingException e) {
- throw new OptimisticPlanningException("Failed to calculate physical distribution", root, e);
- }
-
- return mapping.deduplicate();
- }
-
- /** */
private NodesMapping localMapping(PlanningContext ctx) {
return new NodesMapping(Collections.singletonList(ctx.localNodeId()), null, NodesMapping.CLIENT);
}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/message/QueryStartRequest.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/FragmentDescription.java
similarity index 54%
copy from modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/message/QueryStartRequest.java
copy to modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/FragmentDescription.java
index 5d7b675..ae9c92e 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/message/QueryStartRequest.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/FragmentDescription.java
@@ -15,28 +15,28 @@
* limitations under the License.
*/
-package org.apache.ignite.internal.processors.query.calcite.message;
+package org.apache.ignite.internal.processors.query.calcite.prepare;
import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
import java.util.UUID;
-import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.internal.GridDirectMap;
import org.apache.ignite.internal.GridDirectTransient;
-import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
-import org.apache.ignite.internal.processors.query.calcite.serialize.PhysicalRel;
+import org.apache.ignite.internal.processors.query.calcite.message.MarshalableMessage;
+import org.apache.ignite.internal.processors.query.calcite.message.MessageType;
+import org.apache.ignite.internal.processors.query.calcite.metadata.NodesMapping;
+import org.apache.ignite.internal.util.UUIDCollectionMessage;
+import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.marshaller.Marshaller;
+import org.apache.ignite.plugin.extensions.communication.Message;
+import org.apache.ignite.plugin.extensions.communication.MessageCollectionItemType;
import org.apache.ignite.plugin.extensions.communication.MessageReader;
import org.apache.ignite.plugin.extensions.communication.MessageWriter;
-/**
- *
- */
-public class QueryStartRequest implements MarshalableMessage {
- /** */
- private String schema;
-
- /** */
- private UUID queryId;
-
+/** */
+public class FragmentDescription implements MarshalableMessage {
/** */
private long fragmentId;
@@ -44,103 +44,62 @@ public class QueryStartRequest implements MarshalableMessage {
private int[] partitions;
/** */
- private AffinityTopologyVersion version;
+ private int partitionsCount;
/** */
- @GridDirectTransient
- private PhysicalRel root;
+ private NodesMapping targetMapping;
/** */
- private byte[] rootBytes;
+ @GridDirectTransient
+ private Map<Long, List<UUID>> remoteSources;
/** */
- @GridDirectTransient
- private Object[] params;
+ @GridDirectMap(keyType = Long.class, valueType = Message.class)
+ private Map<Long, UUIDCollectionMessage> remoteSources0;
/** */
- private byte[] paramsBytes;
+ public FragmentDescription() {
+ }
/** */
- public QueryStartRequest(UUID queryId, long fragmentId, String schema, PhysicalRel root, AffinityTopologyVersion version, int[] partitions, Object[] params) {
- this.schema = schema;
- this.queryId = queryId;
+ public FragmentDescription(long fragmentId, int[] partitions, int partitionsCount,
+ NodesMapping targetMapping,
+ Map<Long, List<UUID>> remoteSources) {
this.fragmentId = fragmentId;
this.partitions = partitions;
- this.version = version;
- this.root = root;
- this.params = params;
+ this.partitionsCount = partitionsCount;
+ this.targetMapping = targetMapping;
+ this.remoteSources = remoteSources;
}
/** */
- QueryStartRequest() {
-
- }
-
- /**
- * @return Schema name.
- */
- public String schema() {
- return schema;
- }
-
- /**
- * @return Query ID.
- */
- public UUID queryId() {
- return queryId;
- }
-
- /**
- * @return Fragment ID.
- */
public long fragmentId() {
return fragmentId;
}
- /**
- * @return Partitions.
- */
- public int[] partitions() {
- return partitions;
- }
-
- /**
- * @return Topology version.
- */
- public AffinityTopologyVersion topologyVersion() {
- return version;
+ /** */
+ public NodesMapping targetMapping() {
+ return targetMapping;
}
- /**
- * @return Fragment plan.
- */
- public PhysicalRel root() {
- return root;
+ /** */
+ public Map<Long, List<UUID>> remoteSources() {
+ return remoteSources;
}
- /**
- * @return Query parameters.
- */
- public Object[] parameters() {
- return params;
+ /** */
+ public int[] partitions() {
+ return partitions;
}
- /** {@inheritDoc} */
- @Override public void prepareMarshal(Marshaller marshaller) throws IgniteCheckedException {
- if (rootBytes == null && root != null)
- rootBytes = marshaller.marshal(root);
-
- if (paramsBytes == null && params != null)
- paramsBytes = marshaller.marshal(params);
+ /** */
+ public int partitionsCount() {
+ return partitionsCount;
}
/** {@inheritDoc} */
- @Override public void prepareUnmarshal(Marshaller marshaller, ClassLoader loader) throws IgniteCheckedException {
- if (root == null && rootBytes != null)
- root = marshaller.unmarshal(rootBytes, loader);
-
- if (params == null && paramsBytes != null)
- params = marshaller.unmarshal(paramsBytes, loader);
+ @Override public MessageType type() {
+ return MessageType.FRAGMENT_DESCRIPTION;
}
/** {@inheritDoc} */
@@ -162,37 +121,25 @@ public class QueryStartRequest implements MarshalableMessage {
writer.incrementState();
case 1:
- if (!writer.writeByteArray("paramsBytes", paramsBytes))
+ if (!writer.writeIntArray("partitions", partitions))
return false;
writer.incrementState();
case 2:
- if (!writer.writeIntArray("partitions", partitions))
+ if (!writer.writeInt("partitionsCount", partitionsCount))
return false;
writer.incrementState();
case 3:
- if (!writer.writeByteArray("rootBytes", rootBytes))
+ if (!writer.writeMap("remoteSources0", remoteSources0, MessageCollectionItemType.LONG, MessageCollectionItemType.MSG))
return false;
writer.incrementState();
case 4:
- if (!writer.writeUuid("queryId", queryId))
- return false;
-
- writer.incrementState();
-
- case 5:
- if (!writer.writeString("schema", schema))
- return false;
-
- writer.incrementState();
-
- case 6:
- if (!writer.writeAffinityTopologyVersion("version", version))
+ if (!writer.writeMessage("targetMapping", targetMapping))
return false;
writer.incrementState();
@@ -219,7 +166,7 @@ public class QueryStartRequest implements MarshalableMessage {
reader.incrementState();
case 1:
- paramsBytes = reader.readByteArray("paramsBytes");
+ partitions = reader.readIntArray("partitions");
if (!reader.isLastRead())
return false;
@@ -227,7 +174,7 @@ public class QueryStartRequest implements MarshalableMessage {
reader.incrementState();
case 2:
- partitions = reader.readIntArray("partitions");
+ partitionsCount = reader.readInt("partitionsCount");
if (!reader.isLastRead())
return false;
@@ -235,7 +182,7 @@ public class QueryStartRequest implements MarshalableMessage {
reader.incrementState();
case 3:
- rootBytes = reader.readByteArray("rootBytes");
+ remoteSources0 = reader.readMap("remoteSources0", MessageCollectionItemType.LONG, MessageCollectionItemType.MSG, false);
if (!reader.isLastRead())
return false;
@@ -243,41 +190,46 @@ public class QueryStartRequest implements MarshalableMessage {
reader.incrementState();
case 4:
- queryId = reader.readUuid("queryId");
+ targetMapping = reader.readMessage("targetMapping");
if (!reader.isLastRead())
return false;
reader.incrementState();
- case 5:
- schema = reader.readString("schema");
-
- if (!reader.isLastRead())
- return false;
-
- reader.incrementState();
+ }
- case 6:
- version = reader.readAffinityTopologyVersion("version");
+ return reader.afterMessageRead(FragmentDescription.class);
+ }
- if (!reader.isLastRead())
- return false;
+ /** {@inheritDoc} */
+ @Override public byte fieldsCount() {
+ return 5;
+ }
- reader.incrementState();
+ /** {@inheritDoc} */
+ @Override public void prepareMarshal(Marshaller marshaller) {
+ if (remoteSources0 == null && remoteSources != null) {
+ remoteSources0 = U.newHashMap(remoteSources.size());
+ for (Map.Entry<Long, List<UUID>> e : remoteSources.entrySet())
+ remoteSources0.put(e.getKey(), new UUIDCollectionMessage(e.getValue()));
}
- return reader.afterMessageRead(QueryStartRequest.class);
+ if (targetMapping != null)
+ targetMapping.prepareMarshal(marshaller);
}
/** {@inheritDoc} */
- @Override public MessageType type() {
- return MessageType.QUERY_START_REQUEST;
- }
+ @Override public void prepareUnmarshal(Marshaller marshaller, ClassLoader loader) {
+ if (remoteSources == null && remoteSources0 != null) {
+ remoteSources = U.newHashMap(remoteSources0.size());
- /** {@inheritDoc} */
- @Override public byte fieldsCount() {
- return 7;
+ for (Map.Entry<Long, UUIDCollectionMessage> e : remoteSources0.entrySet())
+ remoteSources.put(e.getKey(), new ArrayList<>(e.getValue().uuids()));
+ }
+
+ if (targetMapping != null)
+ targetMapping.prepareUnmarshal(marshaller, loader);
}
}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/FragmentSplitter.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/FragmentSplitter.java
index 3083feb..6ac560a 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/FragmentSplitter.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/FragmentSplitter.java
@@ -19,13 +19,13 @@ package org.apache.ignite.internal.processors.query.calcite.prepare;
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
-import java.util.Collections;
+import java.util.Deque;
+import java.util.LinkedList;
import java.util.List;
import org.apache.calcite.plan.RelOptCluster;
-import org.apache.calcite.plan.RelTrait;
import org.apache.calcite.plan.RelTraitSet;
import org.apache.calcite.rel.RelNode;
-import org.apache.calcite.rel.metadata.RelMetadataQuery;
+import org.apache.calcite.rel.type.RelDataType;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteAggregate;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteExchange;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteFilter;
@@ -42,274 +42,114 @@ import org.apache.ignite.internal.processors.query.calcite.rel.IgniteTableScan;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteTrimExchange;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteUnionAll;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteValues;
-import org.apache.ignite.internal.processors.query.calcite.trait.DistributionTrait;
-import org.apache.ignite.internal.processors.query.calcite.trait.IgniteDistribution;
-import org.apache.ignite.internal.processors.query.calcite.trait.IgniteDistributions;
import org.apache.ignite.internal.processors.query.calcite.util.Commons;
-import org.apache.ignite.internal.util.typedef.F;
-import org.apache.ignite.internal.util.typedef.internal.U;
/**
*
*/
public class FragmentSplitter implements IgniteRelVisitor<IgniteRel> {
/** */
- private RelMetadataQuery mq;
-
- /** */
- private List<Fragment> fragments;
+ private final Deque<FragmentProto> stack = new LinkedList<>();
/** */
private RelNode cutPoint;
/** */
- public List<Fragment> go(Fragment fragment, RelNode cutPoint, RelMetadataQuery mq) {
- this.cutPoint = cutPoint;
- this.mq = mq;
-
- fragments = new ArrayList<>();
-
- try {
- fragments.add(new Fragment(visit(fragment.root())));
-
- Collections.reverse(fragments);
-
- return fragments;
- }
- finally {
- this.cutPoint = null;
- this.mq = null;
+ private FragmentProto curr;
- fragments = null;
- }
+ public FragmentSplitter(RelNode cutPoint) {
+ this.cutPoint = cutPoint;
}
- /** {@inheritDoc} */
- @Override public IgniteRel visit(IgniteSender rel) {
- assert cutPoint != null;
- assert rel != cutPoint;
-
- IgniteRel input = (IgniteRel) rel.getInput();
- IgniteRel newInput = visit(input);
-
- assert input != newInput;
+ /** */
+ public List<Fragment> go(Fragment fragment) {
+ ArrayList<Fragment> res = new ArrayList<>();
- checkTraitsEqual(input, newInput);
+ stack.push(new FragmentProto(Fragment.ID_GEN.getAndIncrement(), fragment.root()));
- RelTraitSet traits = rel.getTraitSet();
+ while (!stack.isEmpty()) {
+ curr = stack.pop();
+ curr.root = visit(curr.root);
+ res.add(curr.build());
+ curr = null;
+ }
- return (IgniteRel) rel.copy(traits, F.asList(newInput));
+ return res;
}
/** {@inheritDoc} */
@Override public IgniteRel visit(IgniteFilter rel) {
- if (cutPoint == rel)
- return split(rel);
-
- IgniteRel input = (IgniteRel) rel.getInput();
- IgniteRel newInput = visit(input);
-
- if (input == newInput)
- return rel;
-
- checkTraits(input, newInput);
-
- RelTraitSet traits = rel.getTraitSet()
- .replace(newInput.distribution());
-
- return (IgniteRel) rel.copy(traits, F.asList(newInput));
+ return processNode(rel);
}
/** {@inheritDoc} */
@Override public IgniteRel visit(IgniteTrimExchange rel) {
- if (cutPoint == rel)
- return split(rel);
-
- if (cutPoint == null)
- return (IgniteRel) rel.getInput();
-
- IgniteRel input = (IgniteRel) rel.getInput();
- IgniteRel newInput = visit(input);
-
- if (input == newInput)
- return rel;
-
- checkTraitsEqual(input, newInput);
-
- RelTraitSet traits = rel.getTraitSet();
-
- return (IgniteRel) rel.copy(traits, F.asList(newInput));
+ return processNode(rel);
}
/** {@inheritDoc} */
@Override public IgniteRel visit(IgniteProject rel) {
- if (cutPoint == rel)
- return split(rel);
-
- IgniteRel input = (IgniteRel) rel.getInput();
- IgniteRel newInput = visit(input);
-
- if (input == newInput)
- return rel;
-
- checkTraits(input, newInput);
-
- RelTraitSet traits = rel.getTraitSet()
- .replace(IgniteDistributions.project(mq, newInput, rel.getProjects()));
-
- return (IgniteRel) rel.copy(traits, F.asList(newInput));
+ return processNode(rel);
}
/** {@inheritDoc} */
@Override public IgniteRel visit(IgniteJoin rel) {
- if (cutPoint == null)
- return rel; // No need to check deeper
-
- if (cutPoint == rel)
- return split(rel);
-
- IgniteRel left = (IgniteRel) rel.getLeft();
- IgniteRel newLeft = visit(left);
- IgniteRel right = (IgniteRel) rel.getRight();
- IgniteRel newRight = visit(right);
-
- if (left == newLeft && right == newRight)
- return rel;
-
- checkTraitsEqual(left, newLeft);
- checkTraitsEqual(right, newRight);
-
- RelTraitSet traits = rel.getTraitSet();
-
- return (IgniteRel) rel.copy(traits, F.asList(newLeft, newRight));
+ return processNode(rel);
}
/** {@inheritDoc} */
- @Override public IgniteRel visit(IgniteTableScan rel) {
- if (rel == cutPoint)
- return split(rel);
-
- assert cutPoint == null;
-
- return rel;
+ @Override public IgniteRel visit(IgniteTableModify rel) {
+ return processNode(rel);
}
/** {@inheritDoc} */
- @Override public IgniteRel visit(IgniteReceiver rel) {
- assert cutPoint == null;
-
- return rel;
+ @Override public IgniteRel visit(IgniteAggregate rel) {
+ return processNode(rel);
}
/** {@inheritDoc} */
- @Override public IgniteRel visit(IgniteExchange rel) {
- throw new AssertionError();
+ @Override public IgniteRel visit(IgniteMapAggregate rel) {
+ return processNode(rel);
}
/** {@inheritDoc} */
- @Override public IgniteRel visit(IgniteAggregate rel) {
- if (rel == cutPoint)
- return split(rel);
-
- IgniteRel input = (IgniteRel) rel.getInput();
- IgniteRel newInput = visit(input);
-
- if (input == newInput)
- return rel;
-
- checkTraits(input, newInput);
-
- IgniteDistribution distr = IgniteDistributions.aggregate(mq,
- newInput, rel.getGroupSet(), rel.getGroupSets(), rel.getAggCallList());
-
- assert distr != null;
-
- RelTraitSet traits = rel.getTraitSet().replace(distr);
+ @Override public IgniteRel visit(IgniteReduceAggregate rel) {
+ assert cutPoint != rel;
- return (IgniteRel) rel.copy(traits, F.asList(newInput));
+ return processNode(rel);
}
/** {@inheritDoc} */
- @Override public IgniteRel visit(IgniteMapAggregate rel) {
- assert rel != cutPoint;
-
- IgniteRel input = (IgniteRel) rel.getInput();
- IgniteRel newInput = visit(input);
-
- if (input == newInput)
- return rel;
-
- checkTraitsEqual(input, newInput);
-
- RelTraitSet traits = rel.getTraitSet();
-
- return (IgniteRel) rel.copy(traits, F.asList(newInput));
+ @Override public IgniteRel visit(IgniteUnionAll rel) {
+ return processNode(rel);
}
/** {@inheritDoc} */
- @Override public IgniteRel visit(IgniteReduceAggregate rel) {
- assert cutPoint == null;
+ @Override public IgniteRel visit(IgniteSender rel) {
+ assert cutPoint != rel;
- return rel;
+ return processNode(rel);
}
/** {@inheritDoc} */
- @Override public IgniteRel visit(IgniteTableModify rel) {
- if (cutPoint == null)
- return rel; // No need to check deeper
-
- if (rel == cutPoint)
- return split(rel);
-
- IgniteRel input = (IgniteRel) rel.getInput();
- IgniteRel newInput = visit(input);
-
- if (input == newInput)
- return rel;
-
- checkTraitsEqual(input, newInput);
-
- RelTraitSet traits = rel.getTraitSet();
-
- return (IgniteRel) rel.copy(traits, F.asList(newInput));
+ @Override public IgniteRel visit(IgniteTableScan rel) {
+ return processNode(rel);
}
/** {@inheritDoc} */
@Override public IgniteRel visit(IgniteValues rel) {
- assert cutPoint == null;
+ assert cutPoint != rel;
return rel;
}
/** {@inheritDoc} */
- @Override public IgniteRel visit(IgniteUnionAll rel) {
- if (cutPoint == null)
- return rel; // No need to check deeper
-
- if (rel == cutPoint)
- return split(rel);
-
- boolean inputChanged = false;
-
- List<IgniteRel> inputs = Commons.cast(rel.getInputs());
- List<IgniteRel> newInputs = new ArrayList<>(inputs.size());
-
- for (RelNode input : inputs) {
- IgniteRel newInput = visit(input);
-
- if (input != newInput) {
- inputChanged = true;
-
- checkTraitsEqual((IgniteRel) input, newInput);
- }
-
- newInputs.add(newInput);
- }
+ @Override public IgniteRel visit(IgniteReceiver rel) {
+ assert cutPoint != rel;
- if (!inputChanged)
- return rel;
+ curr.remotes.add(rel);
- return (IgniteRel) rel.copy(rel.getTraitSet(), Commons.cast(newInputs));
+ return rel;
}
/** {@inheritDoc} */
@@ -317,61 +157,79 @@ public class FragmentSplitter implements IgniteRelVisitor<IgniteRel> {
return rel.accept(this);
}
- /** */
- private IgniteRel visit(RelNode rel) {
- return visit((IgniteRel) rel);
+ /** {@inheritDoc} */
+ @Override public IgniteRel visit(IgniteExchange rel) {
+ throw new AssertionError();
}
- /** */
- private void checkTraits(IgniteRel orig, IgniteRel newRel) {
- if (!U.assertionsEnabled() || orig == newRel)
- return;
+ /**
+ * Visits all children of a parent.
+ */
+ private IgniteRel processNode(IgniteRel rel) {
+ if (rel == cutPoint) {
+ cutPoint = null;
- RelTraitSet origTraits = orig.getTraitSet();
- RelTraitSet newTraits = newRel.getTraitSet();
+ return split(rel);
+ }
- ImmutableList<RelTrait> difference = origTraits.difference(newTraits);
+ List<IgniteRel> inputs = Commons.cast(rel.getInputs());
- // Only distribution trait may be changed after split
- if (difference.isEmpty() || difference.size() == 1 && F.first(difference) instanceof DistributionTrait)
- return;
+ for (int i = 0; i < inputs.size(); i++)
+ visitChild(rel, i, inputs.get(i));
- assert false : difference;
+ return rel;
}
- /** */
- private void checkTraitsEqual(IgniteRel orig, IgniteRel newRel) {
- if (!U.assertionsEnabled() || orig == newRel)
- return;
-
- RelTraitSet origTraits = orig.getTraitSet();
- RelTraitSet newTraits = newRel.getTraitSet();
-
- ImmutableList<RelTrait> difference = origTraits.difference(newTraits);
-
- if (difference.isEmpty())
- return;
+ /**
+ * Visits a particular child of a parent and replaces the child if it was changed.
+ */
+ private void visitChild(IgniteRel parent, int i, IgniteRel child) {
+ IgniteRel newChild = visit(child);
- assert false : difference;
+ if (newChild != child)
+ parent.replaceInput(i, newChild);
}
/** */
private IgniteRel split(IgniteRel rel) {
- cutPoint = null;
+ RelOptCluster cluster = rel.getCluster();
+ RelTraitSet traits = rel.getTraitSet();
+ RelDataType rowType = rel.getRowType();
- IgniteRel newRel = visit(rel);
+ RelNode input = rel instanceof IgniteTrimExchange ? rel.getInput(0) : rel;
- checkTraits(rel, newRel);
+ long targetFragmentId = curr.id;
+ long sourceFragmentId = Fragment.ID_GEN.getAndIncrement();
+ long exchangeId = sourceFragmentId;
- RelOptCluster cluster = rel.getCluster();
- RelTraitSet traits = rel.getTraitSet();
+ IgniteReceiver receiver = new IgniteReceiver(cluster, traits, rowType, exchangeId, sourceFragmentId);
+ IgniteSender sender = new IgniteSender(cluster, traits, input, exchangeId, targetFragmentId, rel.distribution());
- IgniteSender sender = new IgniteSender(cluster, traits, newRel);
+ curr.remotes.add(receiver);
+ stack.push(new FragmentProto(sourceFragmentId, sender));
- Fragment fragment = new Fragment(sender);
+ return receiver;
+ }
+
+ /** */
+ private static class FragmentProto {
+ /** */
+ private final long id;
+
+ /** */
+ private IgniteRel root;
- fragments.add(fragment);
+ /** */
+ private final ImmutableList.Builder<IgniteReceiver> remotes = ImmutableList.builder();
- return new IgniteReceiver(cluster, traits, fragment);
+ /** */
+ private FragmentProto(long id, IgniteRel root) {
+ this.id = id;
+ this.root = root;
+ }
+
+ Fragment build() {
+ return new Fragment(id, root, remotes.build());
+ }
}
}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/MultiStepDmlPlan.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/MultiStepDmlPlan.java
index 553bb5f..548400b 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/MultiStepDmlPlan.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/MultiStepDmlPlan.java
@@ -48,6 +48,6 @@ public class MultiStepDmlPlan extends AbstractMultiStepPlan {
/** {@inheritDoc}
* @param ctx*/
@Override public QueryPlan clone(PlanningContext ctx) {
- return new MultiStepDmlPlan(new Cloner(ctx).go(fragments), fieldsMetadata());
+ return new MultiStepDmlPlan(new Cloner(ctx.createCluster()).go(fragments), fieldsMetadata());
}
}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/MultiStepPlan.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/MultiStepPlan.java
index 9c3fd75..1d09db0 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/MultiStepPlan.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/MultiStepPlan.java
@@ -18,8 +18,11 @@
package org.apache.ignite.internal.processors.query.calcite.prepare;
import java.util.List;
+import java.util.Map;
+import java.util.UUID;
import org.apache.ignite.internal.processors.query.GridQueryFieldMetadata;
import org.apache.ignite.internal.processors.query.calcite.metadata.MappingService;
+import org.apache.ignite.internal.processors.query.calcite.metadata.NodesMapping;
/**
* Regular query or DML
@@ -36,6 +39,18 @@ public interface MultiStepPlan extends QueryPlan {
List<GridQueryFieldMetadata> fieldsMetadata();
/**
+ * @param fragment Fragment.
+ * @return Mapping for a given fragment.
+ */
+ NodesMapping fragmentMapping(Fragment fragment);
+
+ /** */
+ NodesMapping targetMapping(Fragment fragment);
+
+ /** */
+ Map<Long, List<UUID>> remoteSources(Fragment fragment);
+
+ /**
* Inits query fragments.
*
* @param mappingService Mapping service.
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/MultiStepQueryPlan.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/MultiStepQueryPlan.java
index 9535abb..fe1f837 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/MultiStepQueryPlan.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/MultiStepQueryPlan.java
@@ -49,6 +49,6 @@ public class MultiStepQueryPlan extends AbstractMultiStepPlan {
/** {@inheritDoc}
* @param ctx*/
@Override public QueryPlan clone(PlanningContext ctx) {
- return new MultiStepQueryPlan(new Cloner(ctx).go(fragments), fieldsMetadata());
+ return new MultiStepQueryPlan(new Cloner(ctx.createCluster()).go(fragments), fieldsMetadata());
}
}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/RelTarget.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/RelTarget.java
deleted file mode 100644
index 904b468..0000000
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/RelTarget.java
+++ /dev/null
@@ -1,42 +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.ignite.internal.processors.query.calcite.prepare;
-
-import java.io.Serializable;
-import org.apache.calcite.util.ImmutableIntList;
-import org.apache.ignite.internal.processors.query.calcite.metadata.NodesMapping;
-import org.apache.ignite.internal.processors.query.calcite.metadata.PartitionService;
-import org.apache.ignite.internal.processors.query.calcite.trait.DistributionFunction;
-
-/**
- *
- */
-public interface RelTarget extends Serializable {
- /**
- * @return Target fragment ID.
- */
- long fragmentId();
-
- /**
- * Returns target mapping. It's used in calculation a nodes list, where to send a particular row to.
- * See {@link DistributionFunction#destination(PartitionService, NodesMapping, ImmutableIntList)}
- *
- * @return Target mapping.
- */
- NodesMapping mapping();
-}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/RelTargetAware.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/RelTargetAware.java
deleted file mode 100644
index a879b30..0000000
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/RelTargetAware.java
+++ /dev/null
@@ -1,28 +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.ignite.internal.processors.query.calcite.prepare;
-
-/**
- * Describes an object, that needs information about physical target distribution.
- */
-public interface RelTargetAware {
- /**
- * @param target Remote target information.
- */
- void target(RelTarget target);
-}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/RelTargetImpl.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/RelTargetImpl.java
deleted file mode 100644
index 1c27bde..0000000
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/RelTargetImpl.java
+++ /dev/null
@@ -1,50 +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.ignite.internal.processors.query.calcite.prepare;
-
-import org.apache.ignite.internal.processors.query.calcite.metadata.NodesMapping;
-
-/**
- *
- */
-public class RelTargetImpl implements RelTarget {
- /** */
- private final long fragmentId;
-
- /** */
- private final NodesMapping mapping;
-
- /**
- * @param fragmentId Target fragment ID.
- * @param mapping Target mapping.
- */
- public RelTargetImpl(long fragmentId, NodesMapping mapping) {
- this.fragmentId = fragmentId;
- this.mapping = mapping;
- }
-
- /** {@inheritDoc} */
- @Override public long fragmentId() {
- return fragmentId;
- }
-
- /** {@inheritDoc} */
- @Override public NodesMapping mapping() {
- return mapping;
- }
-}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/Splitter.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/Splitter.java
index 4cdf985..0c3344e 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/Splitter.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/Splitter.java
@@ -17,11 +17,12 @@
package org.apache.ignite.internal.processors.query.calcite.prepare;
+import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
-import java.util.Collections;
+import java.util.Deque;
+import java.util.LinkedList;
import java.util.List;
import org.apache.calcite.plan.RelOptCluster;
-import org.apache.calcite.rel.RelNode;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteAggregate;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteExchange;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteFilter;
@@ -38,131 +39,162 @@ import org.apache.ignite.internal.processors.query.calcite.rel.IgniteTableScan;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteTrimExchange;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteUnionAll;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteValues;
+import org.apache.ignite.internal.processors.query.calcite.util.Commons;
/**
* Splits a query into a list of query fragments.
*/
public class Splitter implements IgniteRelVisitor<IgniteRel> {
/** */
- private List<Fragment> fragments;
+ private final Deque<FragmentProto> stack = new LinkedList<>();
/** */
- public List<Fragment> go(IgniteRel root) {
- fragments = new ArrayList<>();
+ private FragmentProto curr;
- try {
- fragments.add(new Fragment(visit(root)));
+ /** */
+ public List<Fragment> go(IgniteRel root) {
+ ArrayList<Fragment> res = new ArrayList<>();
- Collections.reverse(fragments);
+ stack.push(new FragmentProto(Fragment.ID_GEN.getAndIncrement(), root));
- return fragments;
- }
- finally {
- fragments = null;
+ while (!stack.isEmpty()) {
+ curr = stack.pop();
+ curr.root = visit(curr.root);
+ res.add(curr.build());
+ curr = null;
}
+
+ return res;
}
/** {@inheritDoc} */
@Override public IgniteRel visit(IgniteFilter rel) {
- return visitChildren(rel);
+ return processNode(rel);
}
/** {@inheritDoc} */
@Override public IgniteRel visit(IgniteTrimExchange rel) {
- return visitChildren(rel);
+ return processNode(rel);
}
/** {@inheritDoc} */
@Override public IgniteRel visit(IgniteProject rel) {
- return visitChildren(rel);
+ return processNode(rel);
}
/** {@inheritDoc} */
@Override public IgniteRel visit(IgniteJoin rel) {
- return visitChildren(rel);
+ return processNode(rel);
}
/** {@inheritDoc} */
@Override public IgniteRel visit(IgniteTableModify rel) {
- return visitChildren(rel);
+ return processNode(rel);
}
/** {@inheritDoc} */
@Override public IgniteRel visit(IgniteAggregate rel) {
- return visitChildren(rel);
+ return processNode(rel);
}
/** {@inheritDoc} */
@Override public IgniteRel visit(IgniteMapAggregate rel) {
- return visitChildren(rel);
+ return processNode(rel);
}
/** {@inheritDoc} */
@Override public IgniteRel visit(IgniteReduceAggregate rel) {
- return visitChildren(rel);
+ return processNode(rel);
}
/** {@inheritDoc} */
- @Override public IgniteRel visit(IgniteTableScan rel) {
- return rel;
+ @Override public IgniteRel visit(IgniteUnionAll rel) {
+ return processNode(rel);
}
/** {@inheritDoc} */
- @Override public IgniteRel visit(IgniteValues rel) {
- return rel;
+ @Override public IgniteRel visit(IgniteSender rel) {
+ return processNode(rel);
}
/** {@inheritDoc} */
- @Override public IgniteRel visit(IgniteUnionAll rel) {
- return visitChildren(rel);
+ @Override public IgniteRel visit(IgniteTableScan rel) {
+ return rel;
}
/** {@inheritDoc} */
- @Override public IgniteRel visit(IgniteRel rel) {
- return rel.accept(this);
+ @Override public IgniteRel visit(IgniteValues rel) {
+ return rel;
}
/** {@inheritDoc} */
@Override public IgniteRel visit(IgniteReceiver rel) {
- throw new AssertionError("An attempt to split an already split task.");
+ throw new AssertionError();
}
/** {@inheritDoc} */
- @Override public IgniteRel visit(IgniteSender rel) {
- throw new AssertionError("An attempt to split an already split task.");
+ @Override public IgniteRel visit(IgniteRel rel) {
+ return rel.accept(this);
}
/** {@inheritDoc} */
@Override public IgniteRel visit(IgniteExchange rel) {
RelOptCluster cluster = rel.getCluster();
- IgniteRel input = visit((IgniteRel) rel.getInput());
- Fragment fragment = new Fragment(new IgniteSender(cluster, rel.getTraitSet(), input));
+ long targetFragmentId = curr.id;
+ long sourceFragmentId = Fragment.ID_GEN.getAndIncrement();
+ long exchangeId = sourceFragmentId;
+
+ IgniteReceiver receiver = new IgniteReceiver(cluster, rel.getTraitSet(), rel.getRowType(), exchangeId, sourceFragmentId);
+ IgniteSender sender = new IgniteSender(cluster, rel.getTraitSet(), rel.getInput(), exchangeId, targetFragmentId, rel.distribution());
- fragments.add(fragment);
+ curr.remotes.add(receiver);
+ stack.push(new FragmentProto(sourceFragmentId, sender));
- return new IgniteReceiver(cluster, rel.getTraitSet(), fragment);
+ return receiver;
}
/**
* Visits all children of a parent.
*/
- private <T extends RelNode> T visitChildren(RelNode rel) {
- List<RelNode> inputs = rel.getInputs();
+ private IgniteRel processNode(IgniteRel rel) {
+ List<IgniteRel> inputs = Commons.cast(rel.getInputs());
for (int i = 0; i < inputs.size(); i++)
visitChild(rel, i, inputs.get(i));
- return (T)rel;
+ return rel;
}
/**
* Visits a particular child of a parent and replaces the child if it was changed.
*/
- private void visitChild(RelNode parent, int i, RelNode child) {
- IgniteRel newChild = visit((IgniteRel) child);
+ private void visitChild(IgniteRel parent, int i, IgniteRel child) {
+ IgniteRel newChild = visit(child);
if (newChild != child)
parent.replaceInput(i, newChild);
}
+
+ /** */
+ private static class FragmentProto {
+ /** */
+ private final long id;
+
+ /** */
+ private IgniteRel root;
+
+ /** */
+ private final ImmutableList.Builder<IgniteReceiver> remotes = ImmutableList.builder();
+
+ /** */
+ private FragmentProto(long id, IgniteRel root) {
+ this.id = id;
+ this.root = root;
+ }
+
+ Fragment build() {
+ return new Fragment(id, root, remotes.build());
+ }
+ }
}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteAggregate.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteAggregate.java
index c4b507b..2380553 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteAggregate.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteAggregate.java
@@ -24,6 +24,7 @@ import org.apache.calcite.plan.RelOptCost;
import org.apache.calcite.plan.RelOptPlanner;
import org.apache.calcite.plan.RelTraitSet;
import org.apache.calcite.rel.RelDistribution;
+import org.apache.calcite.rel.RelInput;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.Aggregate;
import org.apache.calcite.rel.core.AggregateCall;
@@ -31,6 +32,7 @@ import org.apache.calcite.rel.metadata.RelMetadataQuery;
import org.apache.calcite.util.ImmutableBitSet;
import org.apache.calcite.util.mapping.MappingType;
import org.apache.calcite.util.mapping.Mappings;
+import org.apache.ignite.internal.processors.query.calcite.util.Commons;
/**
*
@@ -42,6 +44,11 @@ public class IgniteAggregate extends Aggregate implements IgniteRel {
}
/** {@inheritDoc} */
+ public IgniteAggregate(RelInput input) {
+ super(Commons.changeTraits(input, IgniteConvention.INSTANCE));
+ }
+
+ /** {@inheritDoc} */
@Override public Aggregate copy(RelTraitSet traitSet, RelNode input, ImmutableBitSet groupSet, List<ImmutableBitSet> groupSets, List<AggregateCall> aggCalls) {
return new IgniteAggregate(getCluster(), traitSet, input, groupSet, groupSets, aggCalls);
}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteExchange.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteExchange.java
index ba03867..243cd88 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteExchange.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteExchange.java
@@ -20,8 +20,11 @@ package org.apache.ignite.internal.processors.query.calcite.rel;
import org.apache.calcite.plan.RelOptCluster;
import org.apache.calcite.plan.RelTraitSet;
import org.apache.calcite.rel.RelDistribution;
+import org.apache.calcite.rel.RelInput;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.Exchange;
+import org.apache.ignite.internal.processors.query.calcite.trait.IgniteDistribution;
+import org.apache.ignite.internal.processors.query.calcite.util.Commons;
/**
* Relational expression that imposes a particular distribution on its input
@@ -40,6 +43,15 @@ public class IgniteExchange extends Exchange implements IgniteRel {
super(cluster, traitSet, input, distribution);
}
+ public IgniteExchange(RelInput input) {
+ super(Commons.changeTraits(input, IgniteConvention.INSTANCE));
+ }
+
+ /** {@inheritDoc} */
+ @Override public IgniteDistribution distribution() {
+ return (IgniteDistribution)distribution;
+ }
+
/** {@inheritDoc} */
@Override public Exchange copy(RelTraitSet traitSet, RelNode newInput, RelDistribution newDistribution) {
return new IgniteExchange(getCluster(), traitSet, newInput, newDistribution);
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteFilter.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteFilter.java
index cc5e148..40ef435 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteFilter.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteFilter.java
@@ -19,9 +19,11 @@ package org.apache.ignite.internal.processors.query.calcite.rel;
import org.apache.calcite.plan.RelOptCluster;
import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.rel.RelInput;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.Filter;
import org.apache.calcite.rex.RexNode;
+import org.apache.ignite.internal.processors.query.calcite.util.Commons;
/**
* Relational expression that iterates over its input
@@ -45,6 +47,10 @@ public class IgniteFilter extends Filter implements IgniteRel {
super(cluster, traits, input, condition);
}
+ public IgniteFilter(RelInput input) {
+ super(Commons.changeTraits(input, IgniteConvention.INSTANCE));
+ }
+
/** {@inheritDoc} */
@Override public Filter copy(RelTraitSet traitSet, RelNode input, RexNode condition) {
return new IgniteFilter(getCluster(), traitSet, input, condition);
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteJoin.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteJoin.java
index 2c0ff3a..2d25ee4 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteJoin.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteJoin.java
@@ -17,18 +17,23 @@
package org.apache.ignite.internal.processors.query.calcite.rel;
+import com.google.common.collect.ImmutableSet;
+import java.util.List;
import java.util.Set;
import org.apache.calcite.plan.RelOptCluster;
import org.apache.calcite.plan.RelOptCost;
import org.apache.calcite.plan.RelOptPlanner;
import org.apache.calcite.plan.RelTraitSet;
import org.apache.calcite.rel.RelDistribution;
+import org.apache.calcite.rel.RelInput;
import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.RelWriter;
import org.apache.calcite.rel.core.CorrelationId;
import org.apache.calcite.rel.core.Join;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.rel.metadata.RelMetadataQuery;
import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.sql.SqlExplainLevel;
/**
* Relational expression that combines two relational expressions according to
@@ -56,6 +61,17 @@ public class IgniteJoin extends Join implements IgniteRel {
super(cluster, traitSet, left, right, condition, variablesSet, joinType);
}
+ /** */
+ public IgniteJoin(RelInput input) {
+ this(input.getCluster(),
+ input.getTraitSet().replace(IgniteConvention.INSTANCE),
+ input.getInputs().get(0),
+ input.getInputs().get(1),
+ input.getExpression("condition"),
+ ImmutableSet.copyOf((List<CorrelationId>)input.get("variablesSet")),
+ input.getEnum("joinType", JoinRelType.class));
+ }
+
/** {@inheritDoc} */
@Override public Join copy(RelTraitSet traitSet, RexNode condition, RelNode left, RelNode right, JoinRelType joinType, boolean semiJoinDone) {
return new IgniteJoin(getCluster(), traitSet, left, right, condition, variablesSet, joinType);
@@ -73,4 +89,10 @@ public class IgniteJoin extends Join implements IgniteRel {
return super.computeSelfCost(planner, mq);
}
+
+ /** {@inheritDoc} */
+ @Override public RelWriter explainTerms(RelWriter pw) {
+ return super.explainTerms(pw)
+ .itemIf("variablesSet", variablesSet.asList(), pw.getDetailLevel() == SqlExplainLevel.ALL_ATTRIBUTES);
+ }
}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteMapAggregate.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteMapAggregate.java
index 39439c2..6d66aa2 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteMapAggregate.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteMapAggregate.java
@@ -20,6 +20,7 @@ package org.apache.ignite.internal.processors.query.calcite.rel;
import java.util.List;
import org.apache.calcite.plan.RelOptCluster;
import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.rel.RelInput;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.Aggregate;
import org.apache.calcite.rel.core.AggregateCall;
@@ -35,6 +36,11 @@ public class IgniteMapAggregate extends Aggregate implements IgniteRel {
super(cluster, traitSet, input, groupSet, groupSets, aggCalls);
}
+ /** */
+ public IgniteMapAggregate(RelInput input) {
+ super(Commons.changeTraits(input, IgniteConvention.INSTANCE));
+ }
+
/** {@inheritDoc} */
@Override public Aggregate copy(RelTraitSet traitSet, RelNode input, ImmutableBitSet groupSet, List<ImmutableBitSet> groupSets, List<AggregateCall> aggCalls) {
return new IgniteMapAggregate(getCluster(), traitSet, input, groupSet, groupSets, aggCalls);
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteProject.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteProject.java
index 06cee71..64b8343 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteProject.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteProject.java
@@ -20,10 +20,12 @@ package org.apache.ignite.internal.processors.query.calcite.rel;
import java.util.List;
import org.apache.calcite.plan.RelOptCluster;
import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.rel.RelInput;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.Project;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rex.RexNode;
+import org.apache.ignite.internal.processors.query.calcite.util.Commons;
/**
* Relational expression that computes a set of
@@ -43,6 +45,10 @@ public class IgniteProject extends Project implements IgniteRel {
super(cluster, traits, input, projects, rowType);
}
+ public IgniteProject(RelInput input) {
+ super(Commons.changeTraits(input, IgniteConvention.INSTANCE));
+ }
+
/** {@inheritDoc} */
@Override public Project copy(RelTraitSet traitSet, RelNode input, List<RexNode> projects, RelDataType rowType) {
return new IgniteProject(getCluster(), traitSet, input, projects, rowType);
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteReceiver.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteReceiver.java
index 46cad1d..7f6497b 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteReceiver.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteReceiver.java
@@ -21,34 +21,58 @@ import java.util.List;
import org.apache.calcite.plan.RelOptCluster;
import org.apache.calcite.plan.RelTraitSet;
import org.apache.calcite.rel.AbstractRelNode;
+import org.apache.calcite.rel.RelCollations;
+import org.apache.calcite.rel.RelInput;
import org.apache.calcite.rel.RelNode;
-import org.apache.ignite.internal.processors.query.calcite.prepare.Fragment;
+import org.apache.calcite.rel.RelWriter;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.sql.SqlExplainLevel;
/**
* Relational expression that receives elements from remote {@link IgniteSender}
*/
public class IgniteReceiver extends AbstractRelNode implements IgniteRel {
/** */
- private final Fragment source;
+ private final long exchangeId;
+
+ /** */
+ private final long sourceFragmentId;
/**
* Creates a Receiver
- *
- * @param cluster Cluster that this relational expression belongs to
- * @param traits Traits of this relational expression
- * @param source Source fragment.
*/
- public IgniteReceiver(RelOptCluster cluster, RelTraitSet traits, Fragment source) {
+ public IgniteReceiver(RelOptCluster cluster, RelTraitSet traits, RelDataType rowType, long exchangeId,
+ long sourceFragmentId) {
super(cluster, traits);
- this.source = source;
+ this.exchangeId = exchangeId;
+ this.sourceFragmentId = sourceFragmentId;
+ this.rowType = rowType;
+ }
+
+ /** */
+ public IgniteReceiver(RelInput input) {
+ this(
+ input.getCluster(),
+ input.getTraitSet().replace(IgniteConvention.INSTANCE),
+ input.getRowType("rowType"),
+ ((Number)input.get("exchangeId")).longValue(),
+ ((Number)input.get("sourceFragmentId")).longValue());
+ }
- rowType = source.root().getRowType();
+ /** */
+ public long exchangeId() {
+ return exchangeId;
+ }
+
+ /** */
+ public long sourceFragmentId() {
+ return sourceFragmentId;
}
/** {@inheritDoc} */
@Override public RelNode copy(RelTraitSet traitSet, List<RelNode> inputs) {
- return new IgniteReceiver(getCluster(), traitSet, source);
+ return new IgniteReceiver(getCluster(), traitSet, rowType, exchangeId, sourceFragmentId);
}
/** {@inheritDoc} */
@@ -56,10 +80,17 @@ public class IgniteReceiver extends AbstractRelNode implements IgniteRel {
return visitor.visit(this);
}
- /**
- * @return Source fragment.
- */
- public Fragment source() {
- return source;
+ /** {@inheritDoc} */
+ @Override public RelWriter explainTerms(RelWriter pw) {
+ RelWriter writer = super.explainTerms(pw);
+
+ if (pw.getDetailLevel() != SqlExplainLevel.ALL_ATTRIBUTES)
+ return writer;
+
+ return writer
+ .item("rowType", rowType)
+ .item("exchangeId", exchangeId)
+ .item("sourceFragmentId", sourceFragmentId)
+ .itemIf("collations", collations(), collations() != null && collations() != RelCollations.EMPTY);
}
}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteReduceAggregate.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteReduceAggregate.java
index 4c9a4ab..58b0824 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteReduceAggregate.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteReduceAggregate.java
@@ -22,12 +22,14 @@ import org.apache.calcite.linq4j.Ord;
import org.apache.calcite.plan.RelOptCluster;
import org.apache.calcite.plan.RelOptUtil;
import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.rel.RelInput;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.RelWriter;
import org.apache.calcite.rel.SingleRel;
import org.apache.calcite.rel.core.Aggregate.Group;
import org.apache.calcite.rel.core.AggregateCall;
import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.sql.SqlExplainLevel;
import org.apache.calcite.util.ImmutableBitSet;
import org.apache.calcite.util.Util;
import org.apache.ignite.internal.processors.query.calcite.trait.DistributionTraitDef;
@@ -62,6 +64,18 @@ public class IgniteReduceAggregate extends SingleRel implements IgniteRel {
this.rowType = rowType;
}
+ /** */
+ public IgniteReduceAggregate(RelInput input) {
+ this(
+ input.getCluster(),
+ input.getTraitSet().replace(IgniteConvention.INSTANCE),
+ input.getInput(),
+ input.getBitSet("group"),
+ input.getBitSetList("groups"),
+ input.getAggregateCalls("aggs"),
+ input.getRowType("rowType"));
+ }
+
/** {@inheritDoc} */
@Override protected RelDataType deriveRowType() {
throw new UnsupportedOperationException();
@@ -80,6 +94,7 @@ public class IgniteReduceAggregate extends SingleRel implements IgniteRel {
/** {@inheritDoc} */
@Override public RelWriter explainTerms(RelWriter pw) {
super.explainTerms(pw)
+ .itemIf("rowType", rowType, pw.getDetailLevel() == SqlExplainLevel.ALL_ATTRIBUTES)
.item("group", groupSet)
.itemIf("groups", groupSets, Group.induce(groupSet, groupSets) != Group.SIMPLE)
.itemIf("aggs", aggCalls, pw.nest());
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteSender.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteSender.java
index 4e4d84e..1b0e4b0 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteSender.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteSender.java
@@ -20,10 +20,12 @@ package org.apache.ignite.internal.processors.query.calcite.rel;
import java.util.List;
import org.apache.calcite.plan.RelOptCluster;
import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.rel.RelDistributions;
+import org.apache.calcite.rel.RelInput;
import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.RelWriter;
import org.apache.calcite.rel.SingleRel;
-import org.apache.ignite.internal.processors.query.calcite.prepare.RelTarget;
-import org.apache.ignite.internal.processors.query.calcite.prepare.RelTargetAware;
+import org.apache.calcite.sql.SqlExplainLevel;
import org.apache.ignite.internal.processors.query.calcite.trait.DistributionTraitDef;
import org.apache.ignite.internal.processors.query.calcite.trait.IgniteDistribution;
@@ -31,38 +33,67 @@ import org.apache.ignite.internal.processors.query.calcite.trait.IgniteDistribut
* Relational expression that iterates over its input
* and sends elements to remote {@link IgniteReceiver}
*/
-public class IgniteSender extends SingleRel implements IgniteRel, RelTargetAware {
+public class IgniteSender extends SingleRel implements IgniteRel {
/** */
- private RelTarget target;
+ private final long exchangeId;
- /**
- * Creates a Sender.
- *
- * @param cluster Cluster that this relational expression belongs to
- * @param traits Traits of this relational expression
- * @param input input relational expression
- */
- public IgniteSender(RelOptCluster cluster, RelTraitSet traits, RelNode input) {
- this(cluster, traits, input, null);
- }
+ /** */
+ private long targetFragmentId;
+
+ /** */
+ private final IgniteDistribution distribution;
/**
* Creates a Sender.
- *
* @param cluster Cluster that this relational expression belongs to
* @param traits Traits of this relational expression
* @param input input relational expression
- * @param target Remote targets information
+ * @param exchangeId Exchange ID.
+ * @param targetFragmentId Target fragment ID.
*/
- private IgniteSender(RelOptCluster cluster, RelTraitSet traits, RelNode input, RelTarget target) {
+ public IgniteSender(RelOptCluster cluster, RelTraitSet traits, RelNode input, long exchangeId,
+ long targetFragmentId, IgniteDistribution distribution) {
super(cluster, traits, input);
- this.target = target;
+ assert traitSet.containsIfApplicable(distribution)
+ : "traits=" + traitSet + ", distribution" + distribution;
+ assert distribution != RelDistributions.ANY;
+
+ this.exchangeId = exchangeId;
+ this.targetFragmentId = targetFragmentId;
+ this.distribution = distribution;
+ }
+
+ public IgniteSender(RelInput input) {
+ this(
+ input.getCluster(),
+ input.getTraitSet()
+ .replace(input.getDistribution())
+ .replace(IgniteConvention.INSTANCE),
+ input.getInput(),
+ ((Number)input.get("exchangeId")).longValue(),
+ ((Number)input.get("targetFragmentId")).longValue(),
+ (IgniteDistribution)input.getDistribution());
+ }
+
+ /** */
+ public long exchangeId() {
+ return exchangeId;
+ }
+
+ /** */
+ public long targetFragmentId() {
+ return targetFragmentId;
+ }
+
+ /** */
+ public void targetFragmentId(long targetFragmentId) {
+ this.targetFragmentId = targetFragmentId;
}
/** {@inheritDoc} */
@Override public RelNode copy(RelTraitSet traitSet, List<RelNode> inputs) {
- return new IgniteSender(getCluster(), traitSet, sole(inputs), target);
+ return new IgniteSender(getCluster(), traitSet, sole(inputs), exchangeId, targetFragmentId, distribution);
}
/** {@inheritDoc} */
@@ -71,15 +102,8 @@ public class IgniteSender extends SingleRel implements IgniteRel, RelTargetAware
}
/** {@inheritDoc} */
- @Override public void target(RelTarget target) {
- this.target = target;
- }
-
- /**
- * @return Remote targets information.
- */
- public RelTarget target() {
- return target;
+ @Override public IgniteDistribution distribution() {
+ return distribution;
}
/**
@@ -88,4 +112,17 @@ public class IgniteSender extends SingleRel implements IgniteRel, RelTargetAware
public IgniteDistribution sourceDistribution() {
return input.getTraitSet().getTrait(DistributionTraitDef.INSTANCE);
}
+
+ /** {@inheritDoc} */
+ @Override public RelWriter explainTerms(RelWriter pw) {
+ RelWriter writer = super.explainTerms(pw);
+
+ if (pw.getDetailLevel() != SqlExplainLevel.ALL_ATTRIBUTES)
+ return writer;
+
+ return writer
+ .item("exchangeId", exchangeId)
+ .item("targetFragmentId", targetFragmentId)
+ .item("distribution", distribution());
+ }
}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteTableModify.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteTableModify.java
index 817a53e..ae455de 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteTableModify.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteTableModify.java
@@ -21,10 +21,12 @@ import java.util.List;
import org.apache.calcite.plan.RelOptCluster;
import org.apache.calcite.plan.RelOptTable;
import org.apache.calcite.plan.RelTraitSet;
-import org.apache.calcite.prepare.Prepare;
+import org.apache.calcite.rel.RelInput;
import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.RelWriter;
import org.apache.calcite.rel.core.TableModify;
import org.apache.calcite.rex.RexNode;
+import org.apache.ignite.internal.processors.query.calcite.util.Commons;
/**
*
@@ -37,29 +39,39 @@ public class IgniteTableModify extends TableModify implements IgniteRel {
* <blockquote>
* <pre>UPDATE table SET iden1 = exp1, ident2 = exp2 WHERE condition</pre>
* </blockquote>
- *
- * @param cluster Cluster this relational expression belongs to
+ * @param cluster Cluster this relational expression belongs to
* @param traitSet Traits of this relational expression
* @param table Target table to modify
- * @param catalogReader accessor to the table metadata.
* @param input Sub-query or filter condition
* @param operation Modify operation (INSERT, UPDATE, DELETE)
* @param updateColumnList List of column identifiers to be updated
- * (e.g. ident1, ident2); null if not UPDATE
+* (e.g. ident1, ident2); null if not UPDATE
* @param sourceExpressionList List of value expressions to be set
- * (e.g. exp1, exp2); null if not UPDATE
+* (e.g. exp1, exp2); null if not UPDATE
* @param flattened Whether set flattens the input row type
*/
public IgniteTableModify(RelOptCluster cluster,
RelTraitSet traitSet,
RelOptTable table,
- Prepare.CatalogReader catalogReader,
RelNode input,
Operation operation,
List<String> updateColumnList,
List<RexNode> sourceExpressionList,
boolean flattened) {
- super(cluster, traitSet, table, catalogReader, input, operation, updateColumnList, sourceExpressionList, flattened);
+ super(cluster, traitSet, table, Commons.context(cluster).catalogReader(), input, operation, updateColumnList, sourceExpressionList, flattened);
+ }
+
+ public IgniteTableModify(RelInput input) {
+ this(
+ input.getCluster(),
+ input.getTraitSet().replace(IgniteConvention.INSTANCE),
+ input.getTable("table"),
+ input.getInput(),
+ input.getEnum("operation", Operation.class),
+ input.getStringList("updateColumnList"),
+ input.getExpressionList("sourceExpressionList"),
+ input.getBoolean("flattened", true)
+ );
}
/** {@inheritDoc} */
@@ -68,7 +80,6 @@ public class IgniteTableModify extends TableModify implements IgniteRel {
getCluster(),
traitSet,
getTable(),
- getCatalogReader(),
sole(inputs),
getOperation(),
getUpdateColumnList(),
@@ -76,6 +87,10 @@ public class IgniteTableModify extends TableModify implements IgniteRel {
isFlattened());
}
+ @Override public RelWriter explainTerms(RelWriter pw) {
+ return super.explainTerms(pw);
+ }
+
/** {@inheritDoc} */
@Override public <T> T accept(IgniteRelVisitor<T> visitor) {
return visitor.visit(this);
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteTableScan.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteTableScan.java
index 3ba3d35..30bb899 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteTableScan.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteTableScan.java
@@ -21,8 +21,10 @@ import java.util.List;
import org.apache.calcite.plan.RelOptCluster;
import org.apache.calcite.plan.RelOptTable;
import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.rel.RelInput;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.TableScan;
+import org.apache.ignite.internal.processors.query.calcite.util.Commons;
/**
* Relational operator that returns the contents of a table.
@@ -39,6 +41,11 @@ public class IgniteTableScan extends TableScan implements IgniteRel {
super(cluster, traits, table);
}
+ /** */
+ public IgniteTableScan(RelInput input) {
+ super(Commons.changeTraits(input, IgniteConvention.INSTANCE));
+ }
+
/** {@inheritDoc} */
@Override public RelNode copy(RelTraitSet traitSet, List<RelNode> inputs) {
assert inputs.isEmpty();
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteTrimExchange.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteTrimExchange.java
index 4126060..fb7ccdb 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteTrimExchange.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteTrimExchange.java
@@ -17,14 +17,15 @@
package org.apache.ignite.internal.processors.query.calcite.rel;
-import java.util.List;
import org.apache.calcite.plan.RelOptCluster;
import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.rel.RelDistribution;
+import org.apache.calcite.rel.RelInput;
import org.apache.calcite.rel.RelNode;
-import org.apache.calcite.rel.SingleRel;
-import org.apache.ignite.internal.processors.query.calcite.prepare.RelTarget;
-import org.apache.ignite.internal.processors.query.calcite.prepare.RelTargetAware;
+import org.apache.calcite.rel.core.Exchange;
import org.apache.ignite.internal.processors.query.calcite.trait.DistributionTraitDef;
+import org.apache.ignite.internal.processors.query.calcite.trait.IgniteDistribution;
+import org.apache.ignite.internal.processors.query.calcite.util.Commons;
import static org.apache.calcite.rel.RelDistribution.Type.BROADCAST_DISTRIBUTED;
import static org.apache.calcite.rel.RelDistribution.Type.HASH_DISTRIBUTED;
@@ -32,40 +33,31 @@ import static org.apache.calcite.rel.RelDistribution.Type.HASH_DISTRIBUTED;
/**
*
*/
-public class IgniteTrimExchange extends SingleRel implements IgniteRel, RelTargetAware {
+public class IgniteTrimExchange extends Exchange implements IgniteRel {
/** */
- private RelTarget target;
-
- /** */
- public IgniteTrimExchange(RelOptCluster cluster, RelTraitSet traits, RelNode input) {
- super(cluster, traits, input);
+ public IgniteTrimExchange(RelOptCluster cluster, RelTraitSet traits, RelNode input, RelDistribution distribution) {
+ super(cluster, traits, input, distribution);
+ assert distribution.getType() == HASH_DISTRIBUTED;
assert input.getTraitSet().getTrait(DistributionTraitDef.INSTANCE).getType() == BROADCAST_DISTRIBUTED;
- assert traits.getTrait(DistributionTraitDef.INSTANCE).getType() == HASH_DISTRIBUTED;
}
- /** */
- @Override public RelNode copy(RelTraitSet traits, List<RelNode> inputs) {
- RelNode input = sole(inputs);
-
- assert input.getTraitSet().getTrait(DistributionTraitDef.INSTANCE).getType() == BROADCAST_DISTRIBUTED;
- assert traits.getTrait(DistributionTraitDef.INSTANCE).getType() == HASH_DISTRIBUTED;
-
- return new IgniteTrimExchange(getCluster(), traits, input);
+ public IgniteTrimExchange(RelInput input) {
+ super(Commons.changeTraits(input, IgniteConvention.INSTANCE));
}
/** {@inheritDoc} */
- @Override public <T> T accept(IgniteRelVisitor<T> visitor) {
- return visitor.visit(this);
+ @Override public IgniteDistribution distribution() {
+ return (IgniteDistribution)distribution;
}
- /** */
- public RelTarget target() {
- return target;
+ /** {@inheritDoc} */
+ @Override public Exchange copy(RelTraitSet traits, RelNode input, RelDistribution distribution) {
+ return new IgniteTrimExchange(getCluster(), traits, input, distribution);
}
/** {@inheritDoc} */
- @Override public void target(RelTarget target) {
- this.target = target;
+ @Override public <T> T accept(IgniteRelVisitor<T> visitor) {
+ return visitor.visit(this);
}
}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteUnionAll.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteUnionAll.java
index b184493..30991d2 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteUnionAll.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteUnionAll.java
@@ -23,6 +23,7 @@ import org.apache.calcite.plan.RelOptCost;
import org.apache.calcite.plan.RelOptPlanner;
import org.apache.calcite.plan.RelTraitSet;
import org.apache.calcite.rel.RelDistribution;
+import org.apache.calcite.rel.RelInput;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.SetOp;
import org.apache.calcite.rel.core.Union;
@@ -37,6 +38,14 @@ public class IgniteUnionAll extends Union implements IgniteRel {
super(cluster, traits, inputs, true);
}
+ /** */
+ public IgniteUnionAll(RelInput input) {
+ this(
+ input.getCluster(),
+ input.getTraitSet().replace(IgniteConvention.INSTANCE),
+ input.getInputs());
+ }
+
/** {@inheritDoc} */
@Override public SetOp copy(RelTraitSet traitSet, List<RelNode> inputs, boolean all) {
assert all;
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteValues.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteValues.java
index f631f68..8db88a1 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteValues.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteValues.java
@@ -21,10 +21,12 @@ import com.google.common.collect.ImmutableList;
import java.util.List;
import org.apache.calcite.plan.RelOptCluster;
import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.rel.RelInput;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.Values;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rex.RexLiteral;
+import org.apache.ignite.internal.processors.query.calcite.util.Commons;
/**
*
@@ -47,6 +49,11 @@ public class IgniteValues extends Values implements IgniteRel {
super(cluster, rowType, tuples, traits);
}
+ /** */
+ public IgniteValues(RelInput input) {
+ super(Commons.changeTraits(input, IgniteConvention.INSTANCE));
+ }
+
/** {@inheritDoc} */
@Override public RelNode copy(RelTraitSet traitSet, List<RelNode> inputs) {
assert inputs.isEmpty();
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rule/TableModifyConverterRule.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rule/TableModifyConverterRule.java
index dded683..24352d2 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rule/TableModifyConverterRule.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rule/TableModifyConverterRule.java
@@ -55,7 +55,7 @@ public class TableModifyConverterRule extends RelOptRule {
.replace(IgniteDistributions.single()); // TODO move to IgniteMdDistributions
RuleUtils.transformTo(call,
- new IgniteTableModify(cluster, traits, rel.getTable(), rel.getCatalogReader(), input,
+ new IgniteTableModify(cluster, traits, rel.getTable(), input,
rel.getOperation(), rel.getUpdateColumnList(), rel.getSourceExpressionList(), rel.isFlattened()));
}
}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/serialize/AggregatePhysicalRel.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/serialize/AggregatePhysicalRel.java
deleted file mode 100644
index ef0e9ed..0000000
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/serialize/AggregatePhysicalRel.java
+++ /dev/null
@@ -1,108 +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.ignite.internal.processors.query.calcite.serialize;
-
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import java.util.List;
-import org.apache.calcite.util.ImmutableBitSet;
-import org.apache.ignite.internal.processors.query.calcite.exec.exp.agg.AggCallExp;
-import org.apache.ignite.internal.processors.query.calcite.exec.exp.type.DataType;
-
-/**
- *
- */
-public class AggregatePhysicalRel implements PhysicalRel {
- /** */
- public static final byte SINGLE = 0;
-
- /** */
- public static final byte MAP = 1;
-
- /** */
- public static final byte REDUCE = 2;
-
- /** */
- private byte type;
-
- /** */
- private List<ImmutableBitSet> groupSets;
-
- /** */
- private List<AggCallExp> calls;
-
- /** */
- private PhysicalRel input;
-
- /** */
- private DataType inputRowType;
-
- public AggregatePhysicalRel(byte type, List<ImmutableBitSet> groupSets, List<AggCallExp> calls, PhysicalRel input, DataType inputRowType) {
- this.type = type;
- this.groupSets = groupSets;
- this.calls = calls;
- this.input = input;
- this.inputRowType = inputRowType;
- }
-
- public AggregatePhysicalRel() {
- }
-
- public byte type() {
- return type;
- }
-
- public List<ImmutableBitSet> groupSets() {
- return groupSets;
- }
-
- public List<AggCallExp> calls() {
- return calls;
- }
-
- public PhysicalRel input() {
- return input;
- }
-
- public DataType inputRowType() {
- return inputRowType;
- }
-
- @Override public <T> T accept(PhysicalRelVisitor<T> visitor) {
- return visitor.visit(this);
- }
-
- @Override public void writeExternal(ObjectOutput out) throws IOException {
- out.writeByte(type);
- out.writeObject(groupSets);
- out.writeObject(calls);
- out.writeObject(input);
- if (type != REDUCE)
- out.writeObject(inputRowType);
- }
-
- @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
- type = in.readByte();
- groupSets = (List<ImmutableBitSet>) in.readObject();
- calls = (List<AggCallExp>) in.readObject();
- input = (PhysicalRel) in.readObject();
- if (type != REDUCE)
- inputRowType = (DataType) in.readObject();
- }
-}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/serialize/FilterPhysicalRel.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/serialize/FilterPhysicalRel.java
deleted file mode 100644
index 41346a6..0000000
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/serialize/FilterPhysicalRel.java
+++ /dev/null
@@ -1,84 +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.ignite.internal.processors.query.calcite.serialize;
-
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import org.apache.ignite.internal.processors.query.calcite.exec.exp.Expression;
-import org.apache.ignite.internal.processors.query.calcite.exec.exp.type.DataType;
-import org.apache.ignite.internal.processors.query.calcite.rel.IgniteFilter;
-
-/**
- * Describes {@link IgniteFilter}
- */
-public class FilterPhysicalRel implements PhysicalRel {
- /** */
- private DataType rowType;
-
- /** */
- private Expression condition;
-
- /** */
- private PhysicalRel input;
-
- /** */
- public FilterPhysicalRel() {
- }
-
- /** */
- public FilterPhysicalRel(DataType rowType, Expression condition, PhysicalRel input) {
- this.rowType = rowType;
- this.condition = condition;
- this.input = input;
- }
-
- /** */
- public DataType rowType() {
- return rowType;
- }
-
- /** */
- public Expression condition() {
- return condition;
- }
-
- /** */
- public PhysicalRel input() {
- return input;
- }
-
- /** {@inheritDoc} */
- @Override public <T> T accept(PhysicalRelVisitor<T> visitor) {
- return visitor.visit(this);
- }
-
- /** {@inheritDoc} */
- @Override public void writeExternal(ObjectOutput out) throws IOException {
- out.writeObject(rowType);
- out.writeObject(condition);
- out.writeObject(input);
- }
-
- /** {@inheritDoc} */
- @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
- rowType = (DataType) in.readObject();
- condition = (Expression) in.readObject();
- input = (PhysicalRel) in.readObject();
- }
-}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/serialize/JoinPhysicalRel.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/serialize/JoinPhysicalRel.java
deleted file mode 100644
index e1dce81..0000000
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/serialize/JoinPhysicalRel.java
+++ /dev/null
@@ -1,94 +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.ignite.internal.processors.query.calcite.serialize;
-
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import org.apache.ignite.internal.processors.query.calcite.exec.exp.Expression;
-import org.apache.ignite.internal.processors.query.calcite.exec.exp.type.DataType;
-import org.apache.ignite.internal.processors.query.calcite.rel.IgniteJoin;
-
-/**
- * Describes {@link IgniteJoin}.
- */
-public class JoinPhysicalRel implements PhysicalRel {
- /** */
- private DataType rowType;
-
- /** */
- private PhysicalRel left;
-
- /** */
- private PhysicalRel right;
-
- /** */
- private Expression condition;
-
- public JoinPhysicalRel() {
- }
-
- /** */
- public JoinPhysicalRel(DataType rowType, PhysicalRel left, PhysicalRel right, Expression condition) {
- this.rowType = rowType;
- this.left = left;
- this.right = right;
- this.condition = condition;
- }
-
- /** */
- public DataType rowType() {
- return rowType;
- }
-
- /** */
- public PhysicalRel left() {
- return left;
- }
-
- /** */
- public PhysicalRel right() {
- return right;
- }
-
- /** */
- public Expression condition() {
- return condition;
- }
-
- /** {@inheritDoc} */
- @Override public <T> T accept(PhysicalRelVisitor<T> visitor) {
- return visitor.visit(this);
- }
-
- /** {@inheritDoc} */
- @Override public void writeExternal(ObjectOutput out) throws IOException {
- out.writeObject(rowType);
- out.writeObject(left);
- out.writeObject(right);
- out.writeObject(condition);
- }
-
- /** {@inheritDoc} */
- @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
- rowType = (DataType) in.readObject();
- left = (PhysicalRel) in.readObject();
- right = (PhysicalRel) in.readObject();
- condition = (Expression) in.readObject();
- }
-}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/serialize/PhysicalRel.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/serialize/PhysicalRel.java
deleted file mode 100644
index ca0747d..0000000
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/serialize/PhysicalRel.java
+++ /dev/null
@@ -1,33 +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.ignite.internal.processors.query.calcite.serialize;
-
-import java.io.Externalizable;
-
-/**
- * A superclass of all relational nodes representations.
- */
-public interface PhysicalRel extends Externalizable {
- /**
- * Accepts a visit from a visitor.
- *
- * @param visitor Visitor.
- * @return Visit result.
- */
- <T> T accept(PhysicalRelVisitor<T> visitor);
-}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/serialize/PhysicalRelVisitor.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/serialize/PhysicalRelVisitor.java
deleted file mode 100644
index 0c1aee1..0000000
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/serialize/PhysicalRelVisitor.java
+++ /dev/null
@@ -1,86 +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.ignite.internal.processors.query.calcite.serialize;
-
-/**
- *
- */
-public interface PhysicalRelVisitor<T> {
- /**
- * See {@link PhysicalRelVisitor#visit(PhysicalRel)}
- */
- T visit(TableScanPhysicalRel rel);
-
- /**
- * See {@link PhysicalRelVisitor#visit(PhysicalRel)}
- */
- T visit(FilterPhysicalRel rel);
-
- /**
- * See {@link PhysicalRelVisitor#visit(PhysicalRel)}
- */
- T visit(TrimExchangePhysicalRel rel);
-
- /**
- * See {@link PhysicalRelVisitor#visit(PhysicalRel)}
- */
- T visit(ProjectPhysicalRel rel);
-
- /**
- * See {@link PhysicalRelVisitor#visit(PhysicalRel)}
- */
- T visit(JoinPhysicalRel rel);
-
- /**
- * See {@link PhysicalRelVisitor#visit(PhysicalRel)}
- */
- T visit(ReceiverPhysicalRel rel);
-
- /**
- * See {@link PhysicalRelVisitor#visit(PhysicalRel)}
- */
- T visit(ValuesPhysicalRel rel);
-
- /**
- * See {@link PhysicalRelVisitor#visit(PhysicalRel)}
- */
- T visit(SenderPhysicalRel rel);
-
- /**
- * See {@link PhysicalRelVisitor#visit(PhysicalRel)}
- */
- T visit(AggregatePhysicalRel rel);
-
- /**
- * See {@link PhysicalRelVisitor#visit(PhysicalRel)}
- */
- T visit(TableModifyPhysicalRel rel);
-
- /**
- * See {@link PhysicalRelVisitor#visit(PhysicalRel)}
- */
- T visit(UnionAllPhysicalRel rel);
-
- /**
- * Processes given physical rel.
- *
- * @param rel Physical rel.
- * @return Visit result.
- */
- T visit(PhysicalRel rel);
-}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/serialize/ProjectPhysicalRel.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/serialize/ProjectPhysicalRel.java
deleted file mode 100644
index cb0b1fb..0000000
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/serialize/ProjectPhysicalRel.java
+++ /dev/null
@@ -1,99 +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.ignite.internal.processors.query.calcite.serialize;
-
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import java.util.ArrayList;
-import java.util.List;
-import org.apache.ignite.internal.processors.query.calcite.exec.exp.Expression;
-import org.apache.ignite.internal.processors.query.calcite.exec.exp.type.DataType;
-import org.apache.ignite.internal.processors.query.calcite.rel.IgniteProject;
-
-/**
- * Describes {@link IgniteProject}.
- */
-public class ProjectPhysicalRel implements PhysicalRel {
- /** */
- private DataType rowType;
-
- /** */
- private List<Expression> projects;
-
- /** */
- private PhysicalRel input;
-
- public ProjectPhysicalRel() {
- }
-
- /** */
- public ProjectPhysicalRel(DataType rowType, List<Expression> projects, PhysicalRel input) {
- this.rowType = rowType;
- this.projects = projects;
- this.input = input;
- }
-
- /** */
- public DataType rowType() {
- return rowType;
- }
-
- /** */
- public List<Expression> projects() {
- return projects;
- }
-
- /** */
- public PhysicalRel input() {
- return input;
- }
-
- /** {@inheritDoc} */
- @Override public <T> T accept(PhysicalRelVisitor<T> visitor) {
- return visitor.visit(this);
- }
-
- /** {@inheritDoc} */
- @Override public void writeExternal(ObjectOutput out) throws IOException {
- out.writeObject(rowType);
-
- out.writeInt(projects.size());
-
- for (Expression project : projects)
- out.writeObject(project);
-
- out.writeObject(input);
- }
-
- /** {@inheritDoc} */
- @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
- rowType = (DataType) in.readObject();
-
- int projectsSize = in.readInt();
-
- List<Expression> projects = new ArrayList<>(projectsSize);
-
- for (int i = 0; i < projectsSize; i++)
- projects.add((Expression) in.readObject());
-
- this.projects = projects;
-
- input = (PhysicalRel) in.readObject();
- }
-}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/serialize/ReceiverPhysicalRel.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/serialize/ReceiverPhysicalRel.java
deleted file mode 100644
index b2d4894..0000000
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/serialize/ReceiverPhysicalRel.java
+++ /dev/null
@@ -1,154 +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.ignite.internal.processors.query.calcite.serialize;
-
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.UUID;
-import org.apache.calcite.rel.RelCollation;
-import org.apache.calcite.rel.RelCollationTraitDef;
-import org.apache.calcite.rel.RelCollations;
-import org.apache.calcite.rel.RelFieldCollation;
-import org.apache.ignite.internal.processors.query.calcite.exec.exp.type.DataType;
-import org.apache.ignite.internal.processors.query.calcite.rel.IgniteReceiver;
-
-/**
- * Describes {@link IgniteReceiver}.
- */
-public class ReceiverPhysicalRel implements PhysicalRel {
- /** */
- private DataType rowType;
-
- /** */
- private long sourceFragmentId;
-
- /** */
- private List<UUID> sources;
-
- /** */
- private List<RelCollation> collations;
-
- /** */
- public ReceiverPhysicalRel() {
- }
-
- /** */
- public ReceiverPhysicalRel(DataType rowType, long sourceFragmentId, List<UUID> sources, List<RelCollation> collations) {
- this.rowType = rowType;
- this.sourceFragmentId = sourceFragmentId;
- this.sources = sources;
- this.collations = collations;
- }
-
- /** */
- public DataType rowType() {
- return rowType;
- }
-
- /** */
- public long sourceFragmentId() {
- return sourceFragmentId;
- }
-
- /** */
- public Collection<UUID> sources() {
- return sources;
- }
-
- /** */
- public List<RelCollation> collations() {
- return collations;
- }
-
- /** {@inheritDoc} */
- @Override public <T> T accept(PhysicalRelVisitor<T> visitor) {
- return visitor.visit(this);
- }
-
- /** {@inheritDoc} */
- @Override public void writeExternal(ObjectOutput out) throws IOException {
- out.writeObject(rowType);
- out.writeLong(sourceFragmentId);
-
- out.writeInt(sources.size());
-
- for (UUID source : sources)
- out.writeObject(source);
-
- if (collations == null)
- out.writeInt(-1);
- else {
- out.writeInt(collations.size());
-
- for (RelCollation collation : collations) {
- List<RelFieldCollation> fields = collation.getFieldCollations();
-
- out.writeInt(fields.size());
-
- for (RelFieldCollation field : fields) {
- out.writeInt(field.getFieldIndex());
- out.writeByte(field.direction.ordinal());
- out.writeByte(field.nullDirection.ordinal());
- }
- }
- }
- }
-
- /** {@inheritDoc} */
- @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
- rowType = (DataType) in.readObject();
- sourceFragmentId = in.readLong();
-
- final int sourcesSize = in.readInt();
-
- List<UUID> sources = new ArrayList<>(sourcesSize);
-
- for (int i = 0; i < sourcesSize; i++)
- sources.add((UUID) in.readObject());
-
- this.sources = sources;
-
- int collationsSize = in.readInt();
-
- if (collationsSize == -1)
- return;
-
- List<RelCollation> collations = new ArrayList<>(collationsSize);
-
- for (int i = 0; i < collationsSize; i++) {
- int fieldsSize = in.readInt();
-
- List<RelFieldCollation> fields = new ArrayList<>(fieldsSize);
-
- for (int j = 0; j < fieldsSize; j++) {
- int fieldIndex = in.readInt();
- RelFieldCollation.Direction direction = RelFieldCollation.Direction.values()[in.readByte()];
- RelFieldCollation.NullDirection nullDirection = RelFieldCollation.NullDirection.values()[in.readByte()];
-
- fields.add(new RelFieldCollation(fieldIndex, direction, nullDirection));
- }
- collations.add(RelCollationTraitDef.INSTANCE.canonize(RelCollations.of(fields)));
- }
-
- this.collations = collations;
- }
-}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/serialize/RelToPhysicalConverter.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/serialize/RelToPhysicalConverter.java
deleted file mode 100644
index b07453f..0000000
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/serialize/RelToPhysicalConverter.java
+++ /dev/null
@@ -1,203 +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.ignite.internal.processors.query.calcite.serialize;
-
-import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.List;
-import org.apache.calcite.rel.RelDistribution;
-import org.apache.calcite.rel.RelNode;
-import org.apache.calcite.rex.RexLiteral;
-import org.apache.calcite.util.ImmutableBitSet;
-import org.apache.calcite.util.ImmutableIntList;
-import org.apache.ignite.internal.processors.query.calcite.exec.exp.Expression;
-import org.apache.ignite.internal.processors.query.calcite.exec.exp.RexToExpTranslator;
-import org.apache.ignite.internal.processors.query.calcite.exec.exp.agg.AggCallExp;
-import org.apache.ignite.internal.processors.query.calcite.exec.exp.type.DataType;
-import org.apache.ignite.internal.processors.query.calcite.metadata.NodesMapping;
-import org.apache.ignite.internal.processors.query.calcite.prepare.RelTarget;
-import org.apache.ignite.internal.processors.query.calcite.rel.IgniteAggregate;
-import org.apache.ignite.internal.processors.query.calcite.rel.IgniteExchange;
-import org.apache.ignite.internal.processors.query.calcite.rel.IgniteFilter;
-import org.apache.ignite.internal.processors.query.calcite.rel.IgniteJoin;
-import org.apache.ignite.internal.processors.query.calcite.rel.IgniteMapAggregate;
-import org.apache.ignite.internal.processors.query.calcite.rel.IgniteProject;
-import org.apache.ignite.internal.processors.query.calcite.rel.IgniteReceiver;
-import org.apache.ignite.internal.processors.query.calcite.rel.IgniteReduceAggregate;
-import org.apache.ignite.internal.processors.query.calcite.rel.IgniteRel;
-import org.apache.ignite.internal.processors.query.calcite.rel.IgniteRelVisitor;
-import org.apache.ignite.internal.processors.query.calcite.rel.IgniteSender;
-import org.apache.ignite.internal.processors.query.calcite.rel.IgniteTableModify;
-import org.apache.ignite.internal.processors.query.calcite.rel.IgniteTableScan;
-import org.apache.ignite.internal.processors.query.calcite.rel.IgniteTrimExchange;
-import org.apache.ignite.internal.processors.query.calcite.rel.IgniteUnionAll;
-import org.apache.ignite.internal.processors.query.calcite.rel.IgniteValues;
-import org.apache.ignite.internal.processors.query.calcite.trait.DistributionFunction;
-import org.apache.ignite.internal.processors.query.calcite.trait.IgniteDistribution;
-import org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeFactory;
-import org.apache.ignite.internal.processors.query.calcite.util.Commons;
-import org.apache.ignite.internal.util.typedef.F;
-
-/**
- * Converts RelNode tree to physical rel tree.
- */
-public class RelToPhysicalConverter implements IgniteRelVisitor<PhysicalRel> {
- /** */
- private final RexToExpTranslator rexTranslator;
-
- /** */
- private final IgniteTypeFactory typeFactory;
-
- /** */
- public RelToPhysicalConverter(IgniteTypeFactory typeFactory) {
- this.typeFactory = typeFactory;
-
- rexTranslator = new RexToExpTranslator(typeFactory);
- }
-
- /** */
- public PhysicalRel go(IgniteRel root) {
- return visit(root);
- }
-
- /** {@inheritDoc} */
- @Override public PhysicalRel visit(IgniteSender rel) {
- long fragmentId = rel.target().fragmentId();
- NodesMapping mapping = rel.target().mapping();
- DistributionFunction fun = rel.distribution().function();
- ImmutableIntList keys = rel.distribution().getKeys();
-
- return new SenderPhysicalRel(fragmentId, mapping, fun, keys, visit((IgniteRel) rel.getInput()));
- }
-
- /** {@inheritDoc} */
- @Override public PhysicalRel visit(IgniteFilter rel) {
- return new FilterPhysicalRel(DataType.fromType(rel.getRowType()),
- rexTranslator.translate(rel.getCondition()), visit((IgniteRel) rel.getInput()));
- }
-
- /** {@inheritDoc} */
- @Override public PhysicalRel visit(IgniteTrimExchange rel) {
- IgniteDistribution distr = rel.distribution();
- RelTarget target = rel.target();
-
- assert distr.getType() == RelDistribution.Type.HASH_DISTRIBUTED;
- assert target != null && target.mapping() != null && !F.isEmpty(target.mapping().assignments());
-
- int partitions = target.mapping().assignments().size();
-
- return new TrimExchangePhysicalRel(distr.function(), distr.getKeys(), partitions, visit((IgniteRel) rel.getInput()));
- }
-
- /** {@inheritDoc} */
- @Override public PhysicalRel visit(IgniteProject rel) {
- return new ProjectPhysicalRel(DataType.fromType(rel.getInput().getRowType()),
- rexTranslator.translate(rel.getProjects()), visit((IgniteRel) rel.getInput()));
- }
-
- /** {@inheritDoc} */
- @Override public PhysicalRel visit(IgniteJoin rel) {
- DataType dataType = DataType.fromType(
- Commons.combinedRowType(
- typeFactory, rel.getLeft().getRowType(), rel.getRight().getRowType()));
-
- return new JoinPhysicalRel(dataType, visit((IgniteRel) rel.getLeft()), visit((IgniteRel) rel.getRight()), rexTranslator.translate(rel.getCondition()));
- }
-
- /** {@inheritDoc} */
- @Override public PhysicalRel visit(IgniteAggregate rel) {
- byte type = AggregatePhysicalRel.SINGLE;
- List<ImmutableBitSet> groupSets = rel.getGroupSets();
- List<AggCallExp> calls = Commons.transform(rel.getAggCallList(), rexTranslator::translate);
- PhysicalRel input = visit((IgniteRel) rel.getInput());
- DataType inputRowType = DataType.fromType(rel.getInput().getRowType());
-
- return new AggregatePhysicalRel(type, groupSets, calls, input, inputRowType);
- }
-
- /** {@inheritDoc} */
- @Override public PhysicalRel visit(IgniteMapAggregate rel) {
- byte type = AggregatePhysicalRel.MAP;
- List<ImmutableBitSet> groupSets = rel.getGroupSets();
- List<AggCallExp> calls = Commons.transform(
- rel.getAggCallList(), rexTranslator::translate);
- PhysicalRel input = visit((IgniteRel) rel.getInput());
- DataType inputRowType = DataType.fromType(rel.getInput().getRowType());
-
- return new AggregatePhysicalRel(type, groupSets, calls, input, inputRowType);
- }
-
- /** {@inheritDoc} */
- @Override public PhysicalRel visit(IgniteReduceAggregate rel) {
- byte type = AggregatePhysicalRel.REDUCE;
- List<ImmutableBitSet> groupSets = rel.groupSets();
- List<AggCallExp> calls = Commons.transform(
- rel.aggregateCalls(), rexTranslator::translate);
- PhysicalRel input = visit((IgniteRel) rel.getInput());
- DataType inputRowType = null;
-
- return new AggregatePhysicalRel(type, groupSets, calls, input, inputRowType);
- }
-
- /** {@inheritDoc} */
- @Override public PhysicalRel visit(IgniteTableScan rel) {
- return new TableScanPhysicalRel(rel.getTable().getQualifiedName());
- }
-
- /** {@inheritDoc} */
- @Override public PhysicalRel visit(IgniteReceiver rel) {
- return new ReceiverPhysicalRel(DataType.fromType(rel.getRowType()),
- rel.source().fragmentId(), rel.source().mapping().nodes(), rel.collations());
- }
-
- /** {@inheritDoc} */
- @Override public PhysicalRel visit(IgniteTableModify rel) {
- return new TableModifyPhysicalRel(rel.getTable().getQualifiedName(),
- rel.getOperation(), rel.getUpdateColumnList(), visit((IgniteRel) rel.getInput()));
- }
-
- /** {@inheritDoc} */
- @Override public PhysicalRel visit(IgniteValues rel) {
- return new ValuesPhysicalRel(toValues(rel.getTuples()), rel.getRowType().getFieldCount());
- }
-
- /** {@inheritDoc} */
- @Override public PhysicalRel visit(IgniteUnionAll rel) {
- List<PhysicalRel> inputs = new ArrayList<>(rel.getInputs().size());
-
- for (RelNode input : rel.getInputs())
- inputs.add(visit((IgniteRel) input));
-
- return new UnionAllPhysicalRel(inputs);
- }
-
- /** {@inheritDoc} */
- @Override public PhysicalRel visit(IgniteExchange rel) {
- throw new AssertionError();
- }
-
- /** {@inheritDoc} */
- @Override public PhysicalRel visit(IgniteRel rel) {
- return rel.accept(this);
- }
-
- /** */
- private List<Expression> toValues(ImmutableList<ImmutableList<RexLiteral>> tuples) {
- return rexTranslator.translate(Commons.flat(Commons.cast(tuples)));
- }
-}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/serialize/SenderPhysicalRel.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/serialize/SenderPhysicalRel.java
deleted file mode 100644
index 22bc5be..0000000
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/serialize/SenderPhysicalRel.java
+++ /dev/null
@@ -1,98 +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.ignite.internal.processors.query.calcite.serialize;
-
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import org.apache.calcite.util.ImmutableIntList;
-import org.apache.ignite.internal.processors.query.calcite.metadata.NodesMapping;
-import org.apache.ignite.internal.processors.query.calcite.rel.IgniteSender;
-import org.apache.ignite.internal.processors.query.calcite.trait.DistributionFunction;
-
-/**
- * Describes {@link IgniteSender}.
- */
-public class SenderPhysicalRel implements PhysicalRel {
- /** */
- private long targetFragmentId;
-
- /** */
- private NodesMapping mapping;
-
- /** */
- private DistributionFunction function;
-
- /** */
- private ImmutableIntList distributionKeys;
-
- /** */
- private PhysicalRel input;
-
- public SenderPhysicalRel() {
- }
-
- /** */
- public SenderPhysicalRel(long targetFragmentId, NodesMapping mapping, DistributionFunction function, ImmutableIntList distributionKeys, PhysicalRel input) {
- this.targetFragmentId = targetFragmentId;
- this.mapping = mapping;
- this.function = function;
- this.distributionKeys = distributionKeys;
- this.input = input;
- }
-
- public long targetFragmentId() {
- return targetFragmentId;
- }
-
- public NodesMapping mapping() {
- return mapping;
- }
-
- public DistributionFunction distributionFunction() {
- return function;
- }
-
- public ImmutableIntList distributionKeys() {
- return distributionKeys;
- }
-
- public PhysicalRel input() {
- return input;
- }
-
- @Override public <T> T accept(PhysicalRelVisitor<T> visitor) {
- return visitor.visit(this);
- }
-
- @Override public void writeExternal(ObjectOutput out) throws IOException {
- out.writeLong(targetFragmentId);
- out.writeObject(mapping);
- out.writeObject(function);
- out.writeObject(distributionKeys.toIntArray());
- out.writeObject(input);
- }
-
- @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
- targetFragmentId = in.readLong();
- mapping = (NodesMapping) in.readObject();
- function = (DistributionFunction) in.readObject();
- distributionKeys = ImmutableIntList.of((int[]) in.readObject());
- input = (PhysicalRel) in.readObject();
- }
-}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/serialize/TableModifyPhysicalRel.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/serialize/TableModifyPhysicalRel.java
deleted file mode 100644
index 9ce72c3..0000000
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/serialize/TableModifyPhysicalRel.java
+++ /dev/null
@@ -1,117 +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.ignite.internal.processors.query.calcite.serialize;
-
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import java.util.ArrayList;
-import java.util.List;
-import org.apache.calcite.rel.core.TableModify;
-
-/**
- *
- */
-public class TableModifyPhysicalRel implements PhysicalRel {
- /** */
- private List<String> tableName;
-
- /** */
- private TableModify.Operation operation;
-
- /** */
- private List<String> updateColumnList;
-
- /** */
- private PhysicalRel input;
-
- public TableModifyPhysicalRel() {
- }
-
- /***/
- public TableModifyPhysicalRel(List<String> tableName, TableModify.Operation operation, List<String> updateColumnList, PhysicalRel input) {
- this.tableName = tableName;
- this.operation = operation;
- this.updateColumnList = updateColumnList;
- this.input = input;
- }
-
- public List<String> tableName() {
- return tableName;
- }
-
- public TableModify.Operation operation() {
- return operation;
- }
-
- public List<String> updateColumnList() {
- return updateColumnList;
- }
-
- public PhysicalRel input() {
- return input;
- }
-
- @Override public <T> T accept(PhysicalRelVisitor<T> visitor) {
- return visitor.visit(this);
- }
-
- @Override public void writeExternal(ObjectOutput out) throws IOException {
- out.writeInt(tableName.size());
-
- for (String name : tableName)
- out.writeUTF(name);
-
- out.writeByte(operation.ordinal());
-
- if (updateColumnList == null)
- out.writeInt(-1);
- else {
- out.writeInt(updateColumnList.size());
-
- for (String column : updateColumnList)
- out.writeUTF(column);
- }
-
- out.writeObject(input);
- }
-
- @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
- int tableNameSize = in.readInt();
-
- List<String> tableName = new ArrayList<>(tableNameSize);
-
- for (int i = 0; i < tableNameSize; i++)
- tableName.add(in.readUTF());
-
- this.tableName = tableName;
-
- operation = TableModify.Operation.values()[in.readByte()];
-
- int columnsSize = in.readInt();
-
- if (columnsSize != -1) {
- List<String> updateColumnList = new ArrayList<>(columnsSize);
-
- for (int i = 0; i < columnsSize; i++)
- updateColumnList.add(in.readUTF());
- }
-
- input = (PhysicalRel) in.readObject();
- }
-}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/serialize/TableScanPhysicalRel.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/serialize/TableScanPhysicalRel.java
deleted file mode 100644
index 92f5f1d..0000000
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/serialize/TableScanPhysicalRel.java
+++ /dev/null
@@ -1,73 +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.ignite.internal.processors.query.calcite.serialize;
-
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import java.util.ArrayList;
-import java.util.List;
-import org.apache.ignite.internal.processors.query.calcite.rel.IgniteTableScan;
-
-/**
- * Describes {@link IgniteTableScan}.
- */
-public class TableScanPhysicalRel implements PhysicalRel {
- /** */
- private List<String> tableName;
-
- /** */
- public TableScanPhysicalRel() {
- }
-
- /**
- * @param tableName Qualified table name
- */
- public TableScanPhysicalRel(List<String> tableName) {
- this.tableName = tableName;
- }
-
- public List<String> tableName() {
- return tableName;
- }
-
- /** {@inheritDoc} */
- @Override public <T> T accept(PhysicalRelVisitor<T> visitor) {
- return visitor.visit(this);
- }
-
- /** {@inheritDoc} */
- @Override public void writeExternal(ObjectOutput out) throws IOException {
- out.writeInt(tableName.size());
-
- for (String name : tableName)
- out.writeUTF(name);
- }
-
- /** {@inheritDoc} */
- @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
- int tableNameSize = in.readInt();
-
- List<String> tableName = new ArrayList<>(tableNameSize);
-
- for (int i = 0; i < tableNameSize; i++)
- tableName.add(in.readUTF());
-
- this.tableName = tableName;
- }
-}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/serialize/TrimExchangePhysicalRel.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/serialize/TrimExchangePhysicalRel.java
deleted file mode 100644
index d7cdc3a..0000000
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/serialize/TrimExchangePhysicalRel.java
+++ /dev/null
@@ -1,94 +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.ignite.internal.processors.query.calcite.serialize;
-
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import org.apache.calcite.util.ImmutableIntList;
-import org.apache.ignite.internal.processors.query.calcite.trait.DistributionFunction;
-
-/**
- *
- */
-public class TrimExchangePhysicalRel implements PhysicalRel {
- /** */
- private DistributionFunction function;
-
- /** */
- private ImmutableIntList keys;
-
- /** */
- private int partitions;
-
- /** */
- private PhysicalRel input;
-
- /** */
- public TrimExchangePhysicalRel() {
- }
-
- /** */
- public TrimExchangePhysicalRel(DistributionFunction function, ImmutableIntList keys, int partitions, PhysicalRel input) {
- this.function = function;
- this.keys = keys;
- this.partitions = partitions;
- this.input = input;
- }
-
- /** */
- public DistributionFunction function() {
- return function;
- }
-
- /** */
- public ImmutableIntList distributionKeys() {
- return keys;
- }
-
- /** */
- public int partitions() {
- return partitions;
- }
-
- /** */
- public PhysicalRel input() {
- return input;
- }
-
- /** {@inheritDoc} */
- @Override public <T> T accept(PhysicalRelVisitor<T> visitor) {
- return visitor.visit(this);
- }
-
- /** {@inheritDoc} */
- @Override public void writeExternal(ObjectOutput out) throws IOException {
- out.writeObject(function);
- out.writeObject(keys.toIntArray());
- out.writeInt(partitions);
- out.writeObject(input);
- }
-
- /** {@inheritDoc} */
- @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
- function = (DistributionFunction) in.readObject();
- keys = ImmutableIntList.of((int[]) in.readObject());
- partitions = in.readInt();
- input = (PhysicalRel) in.readObject();
- }
-}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/serialize/UnionAllPhysicalRel.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/serialize/UnionAllPhysicalRel.java
deleted file mode 100644
index ae39973..0000000
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/serialize/UnionAllPhysicalRel.java
+++ /dev/null
@@ -1,67 +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.ignite.internal.processors.query.calcite.serialize;
-
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import java.util.ArrayList;
-import java.util.List;
-
-/** */
-public class UnionAllPhysicalRel implements PhysicalRel {
- /** */
- private List<PhysicalRel> inputs;
-
- /** */
- public UnionAllPhysicalRel(List<PhysicalRel> inputs) {
- this.inputs = inputs;
- }
-
- /** */
- public UnionAllPhysicalRel() {
- }
-
- /** */
- public List<PhysicalRel> inputs() {
- return inputs;
- }
-
- /** {@inheritDoc} */
- @Override public <T> T accept(PhysicalRelVisitor<T> visitor) {
- return visitor.visit(this);
- }
-
- /** {@inheritDoc} */
- @Override public void writeExternal(ObjectOutput out) throws IOException {
- out.writeInt(inputs.size());
- for (PhysicalRel input : inputs)
- out.writeObject(input);
- }
-
- /** {@inheritDoc} */
- @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
- int size = in.readInt();
- List<PhysicalRel> inputs = new ArrayList<>(size);
-
- for (int i = 0; i < size; i++)
- inputs.add((PhysicalRel) in.readObject());
-
- this.inputs = inputs;
- }
-}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/serialize/ValuesPhysicalRel.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/serialize/ValuesPhysicalRel.java
deleted file mode 100644
index 7ad80be..0000000
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/serialize/ValuesPhysicalRel.java
+++ /dev/null
@@ -1,79 +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.ignite.internal.processors.query.calcite.serialize;
-
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import java.util.ArrayList;
-import java.util.List;
-import org.apache.ignite.internal.processors.query.calcite.exec.exp.Expression;
-
-/**
- *
- */
-public class ValuesPhysicalRel implements PhysicalRel {
- /** */
- private List<Expression> values;
-
- /** */
- private int rowLen;
-
- public ValuesPhysicalRel() {
- }
-
- /** */
- public ValuesPhysicalRel(List<Expression> values, int rowLen) {
- this.values = values;
- this.rowLen = rowLen;
- }
-
- public List<Expression> values() {
- return values;
- }
-
- public int rowLength() {
- return rowLen;
- }
-
- @Override public <T> T accept(PhysicalRelVisitor<T> visitor) {
- return visitor.visit(this);
- }
-
- @Override public void writeExternal(ObjectOutput out) throws IOException {
- out.writeInt(rowLen);
-
- out.writeInt(values.size());
-
- for (Expression value : values)
- out.writeObject(value);
- }
-
- @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
- rowLen = in.readInt();
-
- int valuesSize = in.readInt();
-
- List<Expression> values = new ArrayList<>(valuesSize);
-
- for (int i = 0; i < valuesSize; i++)
- values.add((Expression) in.readObject());
-
- this.values = values;
- }
-}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/trait/DistributionFunction.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/trait/DistributionFunction.java
index 085ce43..3c926d3 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/trait/DistributionFunction.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/trait/DistributionFunction.java
@@ -251,6 +251,11 @@ public abstract class DistributionFunction implements Serializable {
this.key = key;
}
+ /** */
+ public int cacheId() {
+ return cacheId;
+ }
+
/** {@inheritDoc} */
@Override public RelDistribution.Type type() {
return RelDistribution.Type.HASH_DISTRIBUTED;
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/trait/DistributionTraitDef.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/trait/DistributionTraitDef.java
index b55c77d..1415940 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/trait/DistributionTraitDef.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/trait/DistributionTraitDef.java
@@ -60,7 +60,7 @@ public class DistributionTraitDef extends RelTraitDef<IgniteDistribution> {
// special case
if (fromDist.getType() == RelDistribution.Type.BROADCAST_DISTRIBUTED
&& toDist.getType() == RelDistribution.Type.HASH_DISTRIBUTED) {
- newRel = planner.register(new IgniteTrimExchange(rel.getCluster(), newTraits, rel), rel);
+ newRel = planner.register(new IgniteTrimExchange(rel.getCluster(), newTraits, rel, toDist), rel);
}
else {
RelNode input = RuleUtils.convert(rel, IgniteDistributions.any()); // erasing source distribution a bit reduces search space
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/util/Commons.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/util/Commons.java
index f6e9a19..7233df6 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/util/Commons.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/util/Commons.java
@@ -17,7 +17,9 @@
package org.apache.ignite.internal.processors.query.calcite.util;
+import com.google.common.collect.ImmutableList;
import java.io.PrintWriter;
+import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collections;
@@ -29,25 +31,45 @@ import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
+import org.apache.calcite.config.CalciteSystemProperty;
import org.apache.calcite.linq4j.tree.Primitive;
import org.apache.calcite.plan.Context;
import org.apache.calcite.plan.Contexts;
+import org.apache.calcite.plan.RelOptCluster;
+import org.apache.calcite.plan.RelOptTable;
+import org.apache.calcite.plan.RelTrait;
+import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.rel.RelCollation;
+import org.apache.calcite.rel.RelDistribution;
+import org.apache.calcite.rel.RelInput;
import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.core.AggregateCall;
import org.apache.calcite.rel.externalize.RelWriterImpl;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rel.type.RelDataTypeFactory;
import org.apache.calcite.rel.type.RelDataTypeField;
+import org.apache.calcite.rex.RexLiteral;
+import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.util.ImmutableBitSet;
import org.apache.calcite.util.ImmutableIntList;
+import org.apache.calcite.util.Util;
+import org.apache.ignite.IgniteException;
import org.apache.ignite.IgniteLogger;
import org.apache.ignite.internal.GridComponent;
import org.apache.ignite.internal.GridKernalContext;
import org.apache.ignite.internal.processors.query.QueryContext;
+import org.apache.ignite.internal.processors.query.calcite.exec.exp.ExpressionFactory;
import org.apache.ignite.internal.processors.query.calcite.exec.exp.agg.Accumulator;
import org.apache.ignite.internal.processors.query.calcite.exec.exp.agg.GroupKey;
+import org.apache.ignite.internal.processors.query.calcite.externalize.RelJsonReader;
+import org.apache.ignite.internal.processors.query.calcite.externalize.RelJsonWriter;
import org.apache.ignite.internal.processors.query.calcite.prepare.PlanningContext;
import org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeFactory;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.internal.U;
+import org.codehaus.commons.compiler.CompilerFactoryFactory;
+import org.codehaus.commons.compiler.IClassBodyEvaluator;
+import org.codehaus.commons.compiler.ICompilerFactory;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -131,7 +153,14 @@ public final class Commons {
* Extracts planner context.
*/
public static PlanningContext context(RelNode rel) {
- return context(rel.getCluster().getPlanner().getContext());
+ return context(rel.getCluster());
+ }
+
+ /**
+ * Extracts planner context.
+ */
+ public static PlanningContext context(RelOptCluster cluster) {
+ return context(cluster.getPlanner().getContext());
}
/**
@@ -292,9 +321,160 @@ public final class Commons {
}
/** */
+ public static String toJson(RelNode rel) {
+ RelJsonWriter writer = new RelJsonWriter();
+ rel.explain(writer);
+
+ return writer.asString();
+ }
+
+ public static <T extends RelNode> T fromJson(RelOptCluster cluster, String json) {
+ RelJsonReader reader = new RelJsonReader(cluster, context(cluster).catalogReader());
+
+ return (T)reader.read(json);
+ }
+
+ /** */
public static String explain(RelNode rel) {
StringWriter writer = new StringWriter();
rel.explain(new RelWriterImpl(new PrintWriter(writer)));
return writer.toString();
}
+
+ /** */
+ public static <T> T compile(Class<T> interfaceType, String body) {
+ final boolean debug = CalciteSystemProperty.DEBUG.value();
+
+ if (debug)
+ Util.debugCode(System.out, body);
+
+ try {
+ final ICompilerFactory compilerFactory;
+
+ try {
+ compilerFactory = CompilerFactoryFactory.getDefaultCompilerFactory();
+ } catch (Exception e) {
+ throw new IllegalStateException(
+ "Unable to instantiate java compiler", e);
+ }
+
+ IClassBodyEvaluator cbe = compilerFactory.newClassBodyEvaluator();
+
+ cbe.setImplementedInterfaces(new Class[]{ interfaceType });
+ cbe.setParentClassLoader(ExpressionFactory.class.getClassLoader());
+
+ if (debug)
+ // Add line numbers to the generated janino class
+ cbe.setDebuggingInformation(true, true, true);
+
+ return (T) cbe.createInstance(new StringReader(body));
+ } catch (Exception e) {
+ throw new IgniteException(e);
+ }
+ }
+
+ /** */
+ public static RelInput changeTraits(RelInput input, RelTrait... traits) {
+ RelTraitSet traitSet = input.getTraitSet();
+
+ for (RelTrait trait : traits)
+ traitSet = traitSet.replace(trait);
+
+ RelTraitSet traitSet0 = traitSet;
+
+ return new RelInput() {
+ @Override public RelOptCluster getCluster() {
+ return input.getCluster();
+ }
+
+ @Override public RelTraitSet getTraitSet() {
+ return traitSet0;
+ }
+
+ @Override public RelOptTable getTable(String table) {
+ return input.getTable(table);
+ }
+
+ @Override public RelNode getInput() {
+ return input.getInput();
+ }
+
+ @Override public List<RelNode> getInputs() {
+ return input.getInputs();
+ }
+
+ @Override public RexNode getExpression(String tag) {
+ return input.getExpression(tag);
+ }
+
+ @Override public ImmutableBitSet getBitSet(String tag) {
+ return input.getBitSet(tag);
+ }
+
+ @Override public List<ImmutableBitSet> getBitSetList(String tag) {
+ return input.getBitSetList(tag);
+ }
+
+ @Override public List<AggregateCall> getAggregateCalls(String tag) {
+ return input.getAggregateCalls(tag);
+ }
+
+ @Override public Object get(String tag) {
+ return input.get(tag);
+ }
+
+ @Override public String getString(String tag) {
+ return input.getString(tag);
+ }
+
+ @Override public float getFloat(String tag) {
+ return input.getFloat(tag);
+ }
+
+ @Override public <E extends Enum<E>> E getEnum(String tag, Class<E> enumClass) {
+ return input.getEnum(tag, enumClass);
+ }
+
+ @Override public List<RexNode> getExpressionList(String tag) {
+ return input.getExpressionList(tag);
+ }
+
+ @Override public List<String> getStringList(String tag) {
+ return input.getStringList(tag);
+ }
+
+ @Override public List<Integer> getIntegerList(String tag) {
+ return input.getIntegerList(tag);
+ }
+
+ @Override public List<List<Integer>> getIntegerListList(String tag) {
+ return input.getIntegerListList(tag);
+ }
+
+ @Override public RelDataType getRowType(String tag) {
+ return input.getRowType(tag);
+ }
+
+ @Override public RelDataType getRowType(String expressionsTag, String fieldsTag) {
+ return input.getRowType(expressionsTag, fieldsTag);
+ }
+
+ @Override public RelCollation getCollation() {
+ return input.getCollation();
+ }
+
+ @Override public RelDistribution getDistribution() {
+ return input.getDistribution();
+ }
+
+ @Override public ImmutableList<ImmutableList<RexLiteral>> getTuples(
+ String tag) {
+ return input.getTuples(tag);
+ }
+
+ @Override public boolean getBoolean(String tag, boolean default_) {
+ return input.getBoolean(tag, default_);
+ }
+ };
+ }
}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/util/IgniteMethod.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/util/IgniteMethod.java
index ff8f2bd..dd6e6ff 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/util/IgniteMethod.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/util/IgniteMethod.java
@@ -20,19 +20,17 @@ package org.apache.ignite.internal.processors.query.calcite.util;
import java.lang.reflect.Method;
import org.apache.calcite.linq4j.tree.Types;
import org.apache.ignite.internal.processors.query.calcite.exec.ExecutionContext;
-import org.apache.ignite.internal.processors.query.calcite.exec.exp.CallOperation;
import org.apache.ignite.internal.processors.query.calcite.exec.exp.Scalar;
import org.apache.ignite.internal.processors.query.calcite.metadata.IgniteMetadata.DerivedDistribution;
-import org.apache.ignite.internal.processors.query.calcite.metadata.IgniteMetadata.FragmentMetadata;
+import org.apache.ignite.internal.processors.query.calcite.metadata.IgniteMetadata.NodesMappingMetadata;
/**
* Contains methods used in metadata definitions.
*/
public enum IgniteMethod {
- CALL_APPLY(CallOperation.class, "apply", Object[].class),
SCALAR_EXECUTE(Scalar.class, "execute", ExecutionContext.class, Object[].class, Object[].class),
DERIVED_DISTRIBUTIONS(DerivedDistribution.class, "deriveDistributions"),
- FRAGMENT_INFO(FragmentMetadata.class, "fragmentInfo");
+ NODES_MAPPING(NodesMappingMetadata.class, "nodesMapping");
/** */
private final Method method;
diff --git a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/PlannerTest.java b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/PlannerTest.java
index 0896669..382a5db 100644
--- a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/PlannerTest.java
+++ b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/PlannerTest.java
@@ -57,11 +57,14 @@ import org.apache.ignite.internal.processors.query.calcite.exec.QueryTaskExecuto
import org.apache.ignite.internal.processors.query.calcite.exec.rel.Node;
import org.apache.ignite.internal.processors.query.calcite.exec.rel.Outbox;
import org.apache.ignite.internal.processors.query.calcite.exec.rel.RootNode;
+import org.apache.ignite.internal.processors.query.calcite.externalize.RelJsonReader;
+import org.apache.ignite.internal.processors.query.calcite.externalize.RelJsonWriter;
import org.apache.ignite.internal.processors.query.calcite.message.CalciteMessage;
import org.apache.ignite.internal.processors.query.calcite.message.MessageServiceImpl;
import org.apache.ignite.internal.processors.query.calcite.message.TestIoManager;
import org.apache.ignite.internal.processors.query.calcite.metadata.NodesMapping;
import org.apache.ignite.internal.processors.query.calcite.prepare.Fragment;
+import org.apache.ignite.internal.processors.query.calcite.prepare.FragmentDescription;
import org.apache.ignite.internal.processors.query.calcite.prepare.IgnitePlanner;
import org.apache.ignite.internal.processors.query.calcite.prepare.MultiStepPlan;
import org.apache.ignite.internal.processors.query.calcite.prepare.MultiStepQueryPlan;
@@ -1263,7 +1266,16 @@ public class PlannerTest extends GridCommonAbstractTest {
exchangeService.mailboxRegistry(mailboxRegistry);
exchangeService.init();
- ectx = new ExecutionContext(taskExecutor, ctx, queryId, fragment.fragmentId(), null, Commons.parametersMap(ctx.parameters()));
+ ectx = new ExecutionContext(taskExecutor,
+ ctx,
+ queryId,
+ new FragmentDescription(
+ fragment.fragmentId(),
+ null,
+ 0,
+ plan.targetMapping(fragment),
+ plan.remoteSources(fragment)),
+ Commons.parametersMap(ctx.parameters()));
exec = new LogicalRelImplementor(ectx, c1 -> r1 -> 0, mailboxRegistry, exchangeService,
new TestFailureProcessor(kernal)).go(fragment.root());
@@ -1319,8 +1331,12 @@ public class PlannerTest extends GridCommonAbstractTest {
.logger(log)
.build(),
queryId,
- fragment.fragmentId(),
- null,
+ new FragmentDescription(
+ fragment.fragmentId(),
+ null,
+ 0,
+ plan.targetMapping(fragment),
+ plan.remoteSources(fragment)),
Commons.parametersMap(ctx.parameters()));
exec = new LogicalRelImplementor(ectx, c -> r -> 0, mailboxRegistry, exchangeService,
@@ -1486,7 +1502,16 @@ public class PlannerTest extends GridCommonAbstractTest {
exchangeService.mailboxRegistry(mailboxRegistry);
exchangeService.init();
- ectx = new ExecutionContext(taskExecutor, ctx, queryId, fragment.fragmentId(), null, Commons.parametersMap(ctx.parameters()));
+ ectx = new ExecutionContext(taskExecutor,
+ ctx,
+ queryId,
+ new FragmentDescription(
+ fragment.fragmentId(),
+ null,
+ 0,
+ plan.targetMapping(fragment),
+ plan.remoteSources(fragment)),
+ Commons.parametersMap(ctx.parameters()));
exec = new LogicalRelImplementor(ectx, c1 -> r1 -> 0, mailboxRegistry, exchangeService,
new TestFailureProcessor(kernal)).go(fragment.root());
@@ -1542,8 +1567,12 @@ public class PlannerTest extends GridCommonAbstractTest {
.logger(log)
.build(),
queryId,
- fragment.fragmentId(),
- null,
+ new FragmentDescription(
+ fragment.fragmentId(),
+ null,
+ -1,
+ plan.targetMapping(fragment),
+ plan.remoteSources(fragment)),
Commons.parametersMap(ctx.parameters()));
exec = new LogicalRelImplementor(ectx, c -> r -> 0, mailboxRegistry, exchangeService,
@@ -2166,6 +2195,134 @@ public class PlannerTest extends GridCommonAbstractTest {
assertEquals(2, plan.fragments().size());
}
+ @Test
+ public void testSerializationDeserialization() throws Exception {
+ IgniteTypeFactory f = new IgniteTypeFactory(IgniteTypeSystem.INSTANCE);
+
+ TestTable developer = new TestTable(
+ new RelDataTypeFactory.Builder(f)
+ .add("ID", f.createJavaType(Integer.class))
+ .add("NAME", f.createJavaType(String.class))
+ .add("PROJECTID", f.createJavaType(Integer.class))
+ .build()) {
+ @Override public IgniteDistribution distribution() {
+ return IgniteDistributions.affinity(0, "Developer", "hash");
+ }
+ };
+
+ TestTable project = new TestTable(
+ new RelDataTypeFactory.Builder(f)
+ .add("ID", f.createJavaType(Integer.class))
+ .add("NAME", f.createJavaType(String.class))
+ .add("VER", f.createJavaType(Integer.class))
+ .build()) {
+ @Override public IgniteDistribution distribution() {
+ return IgniteDistributions.affinity(0, "Project", "hash");
+ }
+ };
+
+ IgniteSchema publicSchema = new IgniteSchema("PUBLIC");
+
+ publicSchema.addTable("DEVELOPER", developer);
+ publicSchema.addTable("PROJECT", project);
+
+ SchemaPlus schema = createRootSchema(false)
+ .add("PUBLIC", publicSchema);
+
+ String sql = "SELECT d.id, d.name, d.projectId, p.id0, p.ver0 " +
+ "FROM PUBLIC.Developer d JOIN (" +
+ "SELECT pp.id as id0, pp.ver as ver0 FROM PUBLIC.Project pp" +
+ ") p " +
+ "ON d.projectId = p.id0 " +
+ "WHERE (d.projectId + 1) > ?";
+
+ RelTraitDef<?>[] traitDefs = {
+ DistributionTraitDef.INSTANCE,
+ ConventionTraitDef.INSTANCE
+ };
+
+ PlanningContext ctx = PlanningContext.builder()
+ .localNodeId(F.first(nodes))
+ .originatingNodeId(F.first(nodes))
+ .parentContext(Contexts.empty())
+ .frameworkConfig(newConfigBuilder(FRAMEWORK_CONFIG)
+ .defaultSchema(schema)
+ .traitDefs(traitDefs)
+ .build())
+ .logger(log)
+ .query(sql)
+ .parameters(new Object[]{2})
+ .topologyVersion(AffinityTopologyVersion.NONE)
+ .build();
+
+ RelNode rel;
+
+ try (IgnitePlanner planner = ctx.planner()){
+ assertNotNull(planner);
+
+ String query = ctx.query();
+
+ assertNotNull(query);
+
+ // Parse
+ SqlNode sqlNode = planner.parse(query);
+
+ // Validate
+ sqlNode = planner.validate(sqlNode);
+
+ // Convert to Relational operators graph
+ rel = planner.convert(sqlNode);
+
+ rel = planner.transform(PlannerPhase.HEURISTIC_OPTIMIZATION, rel.getTraitSet(), rel);
+
+ // Transformation chain
+ RelTraitSet desired = rel.getCluster().traitSet()
+ .replace(IgniteConvention.INSTANCE)
+ .replace(IgniteDistributions.single())
+ .simplify();
+
+ rel = planner.transform(PlannerPhase.OPTIMIZATION, desired, rel);
+ }
+
+ assertNotNull(rel);
+
+ List<Fragment> fragments = new Splitter().go((IgniteRel)rel);
+ List<String> serialized = new ArrayList<>(fragments.size());
+
+ for (Fragment fragment : fragments) {
+ RelJsonWriter writer = new RelJsonWriter();
+ fragment.root().explain(writer);
+ serialized.add(writer.asString());
+ }
+
+ assertNotNull(serialized);
+
+ ctx = PlanningContext.builder()
+ .localNodeId(F.first(nodes))
+ .originatingNodeId(F.first(nodes))
+ .parentContext(Contexts.empty())
+ .frameworkConfig(newConfigBuilder(FRAMEWORK_CONFIG)
+ .defaultSchema(schema)
+ .traitDefs(traitDefs)
+ .build())
+ .logger(log)
+ .query(sql)
+ .parameters(new Object[]{2})
+ .topologyVersion(AffinityTopologyVersion.NONE)
+ .build();
+
+ List<RelNode> nodes = new ArrayList<>();
+
+ try(IgnitePlanner ignored = ctx.planner()) {
+ for (String s : serialized) {
+ RelJsonReader reader = new RelJsonReader(ctx.createCluster(), ctx.catalogReader());
+ nodes.add(reader.read(s));
+ }
+ }
+
+ assertNotNull(nodes);
+ }
+
/** */
private NodesMapping intermediateMapping(@NotNull AffinityTopologyVersion topVer, int desiredCount, @Nullable Predicate<ClusterNode> filter) {
List<UUID> nodes = desiredCount == 1 ? select(this.nodes, 0) : select(this.nodes, 0, 1, 2, 3);
diff --git a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/exec/ExpressionEvaluationTest.java b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/exec/ExpressionEvaluationTest.java
deleted file mode 100644
index d385f6e..0000000
--- a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/exec/ExpressionEvaluationTest.java
+++ /dev/null
@@ -1,73 +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.ignite.internal.processors.query.calcite.exec;
-
-import java.util.UUID;
-import org.apache.calcite.rex.RexBuilder;
-import org.apache.calcite.rex.RexNode;
-import org.apache.calcite.sql.fun.SqlStdOperatorTable;
-import org.apache.calcite.sql.type.SqlTypeName;
-import org.apache.ignite.internal.processors.query.calcite.exec.exp.Expression;
-import org.apache.ignite.internal.processors.query.calcite.exec.exp.RexToExpTranslator;
-import org.apache.ignite.internal.processors.query.calcite.prepare.PlanningContext;
-import org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeFactory;
-import org.apache.ignite.internal.processors.query.calcite.util.Commons;
-import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
-import org.junit.Test;
-
-/**
- *
- */
-public class ExpressionEvaluationTest extends GridCommonAbstractTest {
- /** */
- private static final PlanningContext PLANNING_CONTEXT = PlanningContext.EMPTY;
-
- /** */
- private static final QueryTaskExecutor THROWING_EXECUTOR = (qid, fId, t) -> {
- throw new AssertionError();
- };
-
- /** */
- public static final IgniteTypeFactory TYPE_FACTORY = PLANNING_CONTEXT.typeFactory();
-
- @Test
- public void testCallEvaluation() throws Exception {
-
- RexBuilder builder = new RexBuilder(TYPE_FACTORY);
-
- RexNode call = builder.makeCall(
- SqlStdOperatorTable.PLUS,
- builder.makeInputRef(TYPE_FACTORY.createTypeWithNullability(TYPE_FACTORY.createSqlType(SqlTypeName.INTEGER), true), 0),
- builder.makeInputRef(TYPE_FACTORY.createTypeWithNullability(TYPE_FACTORY.createSqlType(SqlTypeName.INTEGER), false), 1));
-
- RexToExpTranslator translator = new RexToExpTranslator(TYPE_FACTORY);
-
- Expression expression = translator.translate(call);
-
- ExecutionContext ctx = context();
-
- assertEquals(3, expression.<Object>evaluate(ctx, 1, 2));
- assertEquals(4, expression.<Object>evaluate(ctx, 2, 2));
- assertEquals(1, expression.<Object>evaluate(ctx, -1, 2));
- assertEquals(null, expression.<Object>evaluate(ctx, null, 2));
- }
-
- public ExecutionContext context(Object... params) {
- return new ExecutionContext(THROWING_EXECUTOR, PLANNING_CONTEXT, UUID.randomUUID(), 0, null, Commons.parametersMap(params));
- }
-}
diff --git a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/AbstractExecutionTest.java b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/AbstractExecutionTest.java
index 70c62153..10f17b8 100644
--- a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/AbstractExecutionTest.java
+++ b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/AbstractExecutionTest.java
@@ -34,6 +34,7 @@ import org.apache.ignite.internal.processors.query.calcite.exec.QueryTaskExecuto
import org.apache.ignite.internal.processors.query.calcite.message.CalciteMessage;
import org.apache.ignite.internal.processors.query.calcite.message.MessageServiceImpl;
import org.apache.ignite.internal.processors.query.calcite.message.TestIoManager;
+import org.apache.ignite.internal.processors.query.calcite.prepare.FragmentDescription;
import org.apache.ignite.internal.processors.query.calcite.prepare.PlanningContext;
import org.apache.ignite.plugin.extensions.communication.Message;
import org.apache.ignite.testframework.junits.GridTestKernalContext;
@@ -138,10 +139,11 @@ public class AbstractExecutionTest extends GridCommonAbstractTest {
}
protected ExecutionContext executionContext(UUID nodeId, UUID queryId, long fragmentId) {
+ FragmentDescription fragmentDescription = new FragmentDescription(fragmentId, null, -1, null, null);
return new ExecutionContext(
taskExecutor(nodeId),
PlanningContext.builder().localNodeId(nodeId).logger(log()).build(),
- queryId, fragmentId, null, ImmutableMap.of());
+ queryId, fragmentDescription, ImmutableMap.of());
}
/** */
diff --git a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/jdbc/JdbcQueryTest.java b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/jdbc/JdbcQueryTest.java
index 27c8e5d..848e275 100644
--- a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/jdbc/JdbcQueryTest.java
+++ b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/jdbc/JdbcQueryTest.java
@@ -24,12 +24,14 @@ import java.sql.SQLException;
import java.sql.Statement;
import java.util.concurrent.TimeUnit;
import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
+import org.apache.ignite.testframework.junits.WithSystemProperty;
import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
import org.junit.Test;
/**
*
*/
+@WithSystemProperty(key = "calcite.debug", value = "true")
public class JdbcQueryTest extends GridCommonAbstractTest {
/** URL. */
private final String url = "jdbc:ignite:thin://127.0.0.1?useExperimentalQueryEngine=true";