com.hazelcast.jet.sql.impl.opt.physical.CreateDagVisitor Maven / Gradle / Ivy
/*
* Copyright 2021 Hazelcast Inc.
*
* Licensed under the Hazelcast Community License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://hazelcast.com/hazelcast-community-license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hazelcast.jet.sql.impl.opt.physical;
import com.hazelcast.cluster.Address;
import com.hazelcast.function.BiFunctionEx;
import com.hazelcast.function.BiPredicateEx;
import com.hazelcast.function.ComparatorEx;
import com.hazelcast.function.ConsumerEx;
import com.hazelcast.function.FunctionEx;
import com.hazelcast.jet.aggregate.AggregateOperation;
import com.hazelcast.jet.core.DAG;
import com.hazelcast.jet.core.Edge;
import com.hazelcast.jet.core.ProcessorMetaSupplier;
import com.hazelcast.jet.core.ProcessorSupplier;
import com.hazelcast.jet.core.Vertex;
import com.hazelcast.jet.core.processor.Processors;
import com.hazelcast.jet.pipeline.ServiceFactories;
import com.hazelcast.jet.sql.impl.ExpressionUtil;
import com.hazelcast.jet.sql.impl.HazelcastPhysicalScan;
import com.hazelcast.jet.sql.impl.SimpleExpressionEvalContext;
import com.hazelcast.jet.sql.impl.connector.SqlConnector.VertexWithInputConfig;
import com.hazelcast.jet.sql.impl.connector.SqlConnectorUtil;
import com.hazelcast.jet.sql.impl.connector.map.IMapSqlConnector;
import com.hazelcast.jet.sql.impl.opt.ExpressionValues;
import com.hazelcast.jet.sql.impl.schema.HazelcastTable;
import com.hazelcast.spi.impl.NodeEngine;
import com.hazelcast.sql.impl.QueryParameterMetadata;
import com.hazelcast.sql.impl.expression.ConstantExpression;
import com.hazelcast.sql.impl.expression.Expression;
import com.hazelcast.sql.impl.optimizer.PlanObjectKey;
import com.hazelcast.sql.impl.schema.Table;
import com.hazelcast.sql.impl.type.QueryDataType;
import com.hazelcast.org.apache.calcite.rel.RelNode;
import com.hazelcast.org.apache.calcite.rel.SingleRel;
import javax.annotation.Nullable;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import static com.hazelcast.function.Functions.entryKey;
import static com.hazelcast.jet.core.Edge.between;
import static com.hazelcast.jet.core.processor.Processors.filterUsingServiceP;
import static com.hazelcast.jet.core.processor.Processors.mapP;
import static com.hazelcast.jet.core.processor.Processors.mapUsingServiceP;
import static com.hazelcast.jet.core.processor.Processors.sortP;
import static com.hazelcast.jet.core.processor.SourceProcessors.convenientSourceP;
import static com.hazelcast.jet.sql.impl.connector.SqlConnectorUtil.getJetSqlConnector;
import static com.hazelcast.jet.sql.impl.processors.RootResultConsumerSink.rootResultConsumerSink;
import static java.util.Collections.singletonList;
public class CreateDagVisitor {
private final DAG dag = new DAG();
private final Set objectKeys = new HashSet<>();
private final NodeEngine nodeEngine;
private final Address localMemberAddress;
private final QueryParameterMetadata parameterMetadata;
public CreateDagVisitor(NodeEngine nodeEngine, QueryParameterMetadata parameterMetadata) {
this.nodeEngine = nodeEngine;
this.localMemberAddress = nodeEngine.getThisAddress();
this.parameterMetadata = parameterMetadata;
}
public Vertex onValues(ValuesPhysicalRel rel) {
List values = rel.values();
return dag.newUniqueVertex("Values", convenientSourceP(
SimpleExpressionEvalContext::from,
(context, buffer) -> {
values.forEach(vs -> vs.toValues(context).forEach(buffer::add));
buffer.close();
},
ctx -> null,
(ctx, states) -> {
},
ConsumerEx.noop(),
0,
true,
null)
);
}
public Vertex onInsert(InsertPhysicalRel rel) {
Table table = rel.getTable().unwrap(HazelcastTable.class).getTarget();
collectObjectKeys(table);
VertexWithInputConfig vertexWithConfig = getJetSqlConnector(table).insertProcessor(dag, table);
Vertex vertex = vertexWithConfig.vertex();
connectInput(rel.getInput(), vertex, vertexWithConfig.configureEdgeFn());
return vertex;
}
public Vertex onSink(SinkPhysicalRel rel) {
Table table = rel.getTable().unwrap(HazelcastTable.class).getTarget();
collectObjectKeys(table);
Vertex vertex = getJetSqlConnector(table).sinkProcessor(dag, table);
connectInput(rel.getInput(), vertex, null);
return vertex;
}
public Vertex onUpdate(UpdatePhysicalRel rel) {
Table table = rel.getTable().unwrap(HazelcastTable.class).getTarget();
Vertex vertex = getJetSqlConnector(table).updateProcessor(dag, table, rel.updates(parameterMetadata));
connectInput(rel.getInput(), vertex, null);
return vertex;
}
public Vertex onDelete(DeletePhysicalRel rel) {
Table table = rel.getTable().unwrap(HazelcastTable.class).getTarget();
Vertex vertex = getJetSqlConnector(table).deleteProcessor(dag, table);
connectInput(rel.getInput(), vertex, null);
return vertex;
}
public Vertex onFullScan(FullScanPhysicalRel rel) {
Table table = rel.getTable().unwrap(HazelcastTable.class).getTarget();
collectObjectKeys(table);
return getJetSqlConnector(table)
.fullScanReader(dag, table, rel.filter(parameterMetadata), rel.projection(parameterMetadata));
}
public Vertex onMapIndexScan(IndexScanMapPhysicalRel rel) {
Table table = rel.getTable().unwrap(HazelcastTable.class).getTarget();
collectObjectKeys(table);
return SqlConnectorUtil.getJetSqlConnector(table)
.indexScanReader(
dag,
localMemberAddress,
table,
rel.getIndex(),
rel.filter(parameterMetadata),
rel.projection(parameterMetadata),
rel.getIndexFilter(),
rel.getComparator(),
rel.isDescending()
);
}
public Vertex onFilter(FilterPhysicalRel rel) {
Expression filter = rel.filter(parameterMetadata);
Vertex vertex = dag.newUniqueVertex("Filter", filterUsingServiceP(
ServiceFactories.nonSharedService(ctx ->
ExpressionUtil.filterFn(filter, SimpleExpressionEvalContext.from(ctx))),
(BiPredicateEx, Object[]>) Predicate::test));
connectInputPreserveCollation(rel, vertex);
return vertex;
}
public Vertex onProject(ProjectPhysicalRel rel) {
List> projection = rel.projection(parameterMetadata);
Vertex vertex = dag.newUniqueVertex("Project", mapUsingServiceP(
ServiceFactories.nonSharedService(ctx ->
ExpressionUtil.projectionFn(projection, SimpleExpressionEvalContext.from(ctx))),
(BiFunctionEx, Object[], Object[]>) Function::apply
));
connectInputPreserveCollation(rel, vertex);
return vertex;
}
public Vertex onSort(SortPhysicalRel rel) {
ComparatorEx> comparator = ExpressionUtil.comparisonFn(rel.getCollations());
// Use 2-Phase sort for maximum parallelism
// First, construct processors for local sorting
Vertex sortVertex = dag.newUniqueVertex("Sort",
ProcessorMetaSupplier.of(sortP(comparator)));
connectInput(rel.getInput(), sortVertex, null);
// Then, combine the locally sorted inputs while preserving the ordering
Vertex combineVertex = dag.newUniqueVertex("SortCombine",
ProcessorMetaSupplier.forceTotalParallelismOne(
ProcessorSupplier.of(mapP(FunctionEx.identity())),
localMemberAddress
)
);
Edge edge = between(sortVertex, combineVertex)
.ordered(comparator)
.distributeTo(localMemberAddress)
.allToOne("");
dag.edge(edge);
return combineVertex;
}
public Vertex onAggregate(AggregatePhysicalRel rel) {
AggregateOperation, Object[]> aggregateOperation = rel.aggrOp();
Vertex vertex = dag.newUniqueVertex(
"Aggregate",
ProcessorMetaSupplier.forceTotalParallelismOne(
ProcessorSupplier.of(Processors.aggregateP(aggregateOperation)),
localMemberAddress
)
);
connectInput(rel.getInput(), vertex, edge -> edge.distributeTo(localMemberAddress).allToOne(""));
return vertex;
}
public Vertex onAccumulate(AggregateAccumulatePhysicalRel rel) {
AggregateOperation, Object[]> aggregateOperation = rel.aggrOp();
Vertex vertex = dag.newUniqueVertex(
"Accumulate",
Processors.accumulateP(aggregateOperation)
);
connectInput(rel.getInput(), vertex, null);
return vertex;
}
public Vertex onCombine(AggregateCombinePhysicalRel rel) {
AggregateOperation, Object[]> aggregateOperation = rel.aggrOp();
Vertex vertex = dag.newUniqueVertex(
"Combine",
ProcessorMetaSupplier.forceTotalParallelismOne(
ProcessorSupplier.of(Processors.combineP(aggregateOperation)),
localMemberAddress
)
);
connectInput(rel.getInput(), vertex, edge -> edge.distributeTo(localMemberAddress).allToOne(""));
return vertex;
}
public Vertex onAggregateByKey(AggregateByKeyPhysicalRel rel) {
FunctionEx
© 2015 - 2025 Weber Informatics LLC | Privacy Policy