use of org.apache.calcite.rel.core.CorrelationId in project ignite by apache.
the class LogicalRelImplementorTest method testIndexScanRewriter.
/**
*/
@Test
public void testIndexScanRewriter() {
IgniteTypeFactory tf = Commons.typeFactory();
RelDataTypeFactory.Builder b = new RelDataTypeFactory.Builder(tf);
RelDataType sqlTypeInt = tf.createSqlType(SqlTypeName.INTEGER);
RelDataType sqlTypeVarchar = tf.createSqlType(SqlTypeName.VARCHAR);
b.add("_KEY", tf.createJavaType(Object.class));
b.add("_VAL", tf.createJavaType(Object.class));
b.add("ID", sqlTypeInt);
b.add("VAL", sqlTypeVarchar);
RelDataType rowType = b.build();
ScanAwareTable tbl = new ScanAwareTable(rowType);
tbl.addIndex("IDX", 2);
IgniteSchema publicSchema = new IgniteSchema("PUBLIC");
publicSchema.addTable("TBL", tbl);
BaseQueryContext qctx = BaseQueryContext.builder().frameworkConfig(newConfigBuilder(FRAMEWORK_CONFIG).defaultSchema(createRootSchema(false).add(publicSchema.getName(), publicSchema)).build()).logger(log).build();
UUID nodeId = UUID.randomUUID();
ExecutionContext<Object[]> ectx = new ExecutionContext<Object[]>(qctx, null, null, nodeId, nodeId, null, null, ArrayRowHandler.INSTANCE, null) {
@Override
public ColocationGroup group(long srcId) {
return ColocationGroup.forNodes(Collections.singletonList(nodeId));
}
};
LogicalRelImplementor<Object[]> relImplementor = new LogicalRelImplementor<>(ectx, null, null, null, null);
// Construct relational operator corresponding to SQL: "SELECT val, id, id + 1 FROM TBL WHERE id = 1"
RelOptCluster cluster = Commons.emptyCluster();
RexBuilder rexBuilder = cluster.getRexBuilder();
// Projects, filters and required columns.
List<RexNode> project = F.asList(rexBuilder.makeLocalRef(sqlTypeVarchar, 1), rexBuilder.makeLocalRef(sqlTypeInt, 0), rexBuilder.makeCall(SqlStdOperatorTable.PLUS, rexBuilder.makeLocalRef(sqlTypeInt, 0), rexBuilder.makeLiteral(1, sqlTypeInt)));
RexNode filter = rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, rexBuilder.makeLocalRef(sqlTypeInt, 0), rexBuilder.makeLiteral(1, sqlTypeInt));
ImmutableBitSet requiredColumns = ImmutableBitSet.of(2, 3);
// Collations.
RelCollation idxCollation = tbl.getIndex("IDX").collation();
RelCollation colCollation = idxCollation.apply(Mappings.target(requiredColumns.asList(), tbl.getRowType(tf).getFieldCount()));
RelCollation projCollation = TraitUtils.projectCollation(colCollation, RexUtils.replaceLocalRefs(project), tbl.getRowType(tf, requiredColumns));
RelCollation emptyCollation = RelCollations.of();
// Correlated projects and filters.
RexShuttle replaceLiteralToCorr = new RexShuttle() {
@Override
public RexNode visitLiteral(RexLiteral literal) {
return rexBuilder.makeFieldAccess(rexBuilder.makeCorrel(tbl.getRowType(tf), new CorrelationId(0)), "ID", false);
}
};
RexNode corrFilter = replaceLiteralToCorr.apply(filter);
List<RexNode> corrProject = F.asList(project.get(0), project.get(1), replaceLiteralToCorr.apply(project.get(2)));
tbl.markIndexRebuildInProgress(true);
Predicate<Node<Object[]>> isScanNoFilterNoProject = node -> node instanceof ScanNode && !tbl.lastScanHasFilter && !tbl.lastScanHasProject;
Predicate<Node<Object[]>> isScanWithFilterNoProject = node -> node instanceof ScanNode && tbl.lastScanHasFilter && !tbl.lastScanHasProject;
Predicate<Node<Object[]>> isScanWithProjectNoFilter = node -> node instanceof ScanNode && !tbl.lastScanHasFilter && tbl.lastScanHasProject;
Predicate<Node<Object[]>> isScanWithFilterWithProject = node -> node instanceof ScanNode && tbl.lastScanHasFilter && tbl.lastScanHasProject;
Predicate<Node<Object[]>> isSort = node -> node instanceof SortNode;
Predicate<Node<Object[]>> isSpool = node -> node instanceof IndexSpoolNode;
Predicate<Node<Object[]>> isProj = node -> node instanceof ProjectNode;
IgniteIndexScan templateScan = new IgniteIndexScan(cluster, cluster.traitSet(), qctx.catalogReader().getTable(F.asList("PUBLIC", "TBL")), "IDX", project, filter, RexUtils.buildSortedIndexConditions(cluster, idxCollation, filter, rowType, requiredColumns), requiredColumns, idxCollation);
IgniteIndexScan scan;
// IndexScan without filters and projects transforms to scan and sort.
scan = createScan(templateScan, idxCollation, null, null, null);
checkNodesChain(relImplementor, scan, isSort, isScanNoFilterNoProject);
scan = createScan(templateScan, projCollation, null, null, requiredColumns);
checkNodesChain(relImplementor, scan, isSort, isScanNoFilterNoProject);
// IndexScan with simple filters and projects transforms to scan and sort.
scan = createScan(templateScan, projCollation, project, filter, requiredColumns);
checkNodesChain(relImplementor, scan, isSort, isScanWithFilterWithProject);
scan = createScan(templateScan, colCollation, null, filter, requiredColumns);
checkNodesChain(relImplementor, scan, isSort, isScanWithFilterNoProject);
scan = createScan(templateScan, projCollation, project, null, requiredColumns);
checkNodesChain(relImplementor, scan, isSort, isScanWithProjectNoFilter);
// IndexScan with correlated filter without project transforms to scan, sort and spool.
scan = createScan(templateScan, projCollation, null, corrFilter, requiredColumns);
checkNodesChain(relImplementor, scan, isSpool, isSort, isScanNoFilterNoProject);
// IndexScan with correlated filter without project transforms to scan, sort and spool.
scan = createScan(templateScan, idxCollation, null, corrFilter, requiredColumns);
checkNodesChain(relImplementor, scan, isSpool, isSort, isScanNoFilterNoProject);
// IndexScan with correlated filter with project transforms to scan, sort, spool and project.
scan = createScan(templateScan, projCollation, project, corrFilter, requiredColumns);
checkNodesChain(relImplementor, scan, isProj, isSpool, isSort, isScanNoFilterNoProject);
// IndexScan with correlated project transforms to scan, sort, spool and project.
scan = createScan(templateScan, projCollation, corrProject, null, requiredColumns);
checkNodesChain(relImplementor, scan, isProj, isSpool, isSort, isScanNoFilterNoProject);
scan = createScan(templateScan, projCollation, corrProject, filter, requiredColumns);
checkNodesChain(relImplementor, scan, isProj, isSpool, isSort, isScanWithFilterNoProject);
scan = createScan(templateScan, projCollation, corrProject, corrFilter, requiredColumns);
checkNodesChain(relImplementor, scan, isProj, isSpool, isSort, isScanNoFilterNoProject);
// IndexScan with simple project without collation transforms to scan.
List<RexNode> unknownCollationProject = new ArrayList<>(1);
// Field "val".
unknownCollationProject.add(corrProject.get(0));
scan = createScan(templateScan, emptyCollation, unknownCollationProject, filter, requiredColumns);
checkNodesChain(relImplementor, scan, isScanWithFilterWithProject);
scan = createScan(templateScan, emptyCollation, unknownCollationProject, null, requiredColumns);
checkNodesChain(relImplementor, scan, isScanWithProjectNoFilter);
// IndexScan with correlated project without collation transforms to scan, sort, spool and project.
List<RexNode> unknownCollationCorrProject = new ArrayList<>(1);
// Field "id + $cor0.id".
unknownCollationCorrProject.add(corrProject.get(2));
scan = createScan(templateScan, emptyCollation, unknownCollationCorrProject, filter, requiredColumns);
checkNodesChain(relImplementor, scan, isProj, isSpool, isSort, isScanWithFilterNoProject);
scan = createScan(templateScan, emptyCollation, unknownCollationCorrProject, corrFilter, requiredColumns);
checkNodesChain(relImplementor, scan, isProj, isSpool, isSort, isScanNoFilterNoProject);
scan = createScan(templateScan, emptyCollation, unknownCollationCorrProject, null, requiredColumns);
checkNodesChain(relImplementor, scan, isProj, isSpool, isSort, isScanNoFilterNoProject);
}
use of org.apache.calcite.rel.core.CorrelationId in project ignite by apache.
the class ExecutionTest method testCorrelatedNestedLoopJoin.
/**
*/
@Test
public void testCorrelatedNestedLoopJoin() {
ExecutionContext<Object[]> ctx = executionContext(F.first(nodes()), UUID.randomUUID(), 0);
IgniteTypeFactory tf = ctx.getTypeFactory();
RelDataType rowType = TypeUtils.createRowType(tf, int.class, String.class, int.class);
int[] leftSizes = { 1, 99, 100, 101, 512, 513, 2000 };
int[] rightSizes = { 1, 99, 100, 101, 512, 513, 2000 };
int[] rightBufSizes = { 1, 100, 512 };
JoinRelType[] joinTypes = { INNER, LEFT };
for (JoinRelType joinType : joinTypes) {
for (int rightBufSize : rightBufSizes) {
for (int leftSize : leftSizes) {
for (int rightSize : rightSizes) {
log.info("Check: joinType=" + joinType + ", rightBufSize=" + rightBufSize + ", leftSize=" + leftSize + ", rightSize=" + rightSize);
ScanNode<Object[]> left = new ScanNode<>(ctx, rowType, new TestTable(leftSize, rowType));
ScanNode<Object[]> right = new ScanNode<>(ctx, rowType, new TestTable(rightSize, rowType));
RelDataType joinRowType = TypeUtils.createRowType(tf, int.class, String.class, int.class, int.class, String.class, int.class);
RowHandler<Object[]> hnd = ctx.rowHandler();
CorrelatedNestedLoopJoinNode<Object[]> join = new CorrelatedNestedLoopJoinNode<>(ctx, joinRowType, (r1, r2) -> getFieldFromBiRows(hnd, 0, r1, r2).equals(getFieldFromBiRows(hnd, 3, r1, r2)), ImmutableSet.of(new CorrelationId(0)), joinType);
GridTestUtils.setFieldValue(join, "rightInBufferSize", rightBufSize);
join.register(Arrays.asList(left, right));
RootNode<Object[]> root = new RootNode<>(ctx, joinRowType);
root.register(join);
int cnt = 0;
while (root.hasNext()) {
root.next();
cnt++;
}
assertEquals("Invalid result size. [left=" + leftSize + ", right=" + rightSize + ", results=" + cnt, joinType == INNER ? min(leftSize, rightSize) : leftSize, cnt);
}
}
}
}
}
use of org.apache.calcite.rel.core.CorrelationId in project hive by apache.
the class HiveRelDecorrelator method createCopyHook.
private Function2<RelNode, RelNode, Void> createCopyHook() {
return new Function2<RelNode, RelNode, Void>() {
@Override
public Void apply(RelNode oldNode, RelNode newNode) {
if (cm.mapRefRelToCorRef.containsKey(oldNode)) {
final CorelMap corelMap = new CorelMapBuilder().build(newNode);
// to figure out new cor refs and put that into map
if (!corelMap.mapRefRelToCorRef.isEmpty()) {
cm.mapRefRelToCorRef.putAll(newNode, corelMap.mapRefRelToCorRef.get(newNode));
}
}
if (oldNode instanceof LogicalCorrelate && newNode instanceof LogicalCorrelate) {
LogicalCorrelate oldCor = (LogicalCorrelate) oldNode;
CorrelationId c = oldCor.getCorrelationId();
if (cm.mapCorToCorRel.get(c) == oldNode) {
cm.mapCorToCorRel.put(c, newNode);
}
if (generatedCorRels.contains(oldNode)) {
generatedCorRels.add((LogicalCorrelate) newNode);
}
}
return null;
}
};
}
use of org.apache.calcite.rel.core.CorrelationId in project ignite by apache.
the class CorrelatedNestedLoopJoinRule method convert.
/**
* {@inheritDoc}
*/
@Override
protected PhysicalNode convert(RelOptPlanner planner, RelMetadataQuery mq, LogicalJoin rel) {
final int leftFieldCount = rel.getLeft().getRowType().getFieldCount();
final RelOptCluster cluster = rel.getCluster();
final RexBuilder rexBuilder = cluster.getRexBuilder();
final RelBuilder relBuilder = relBuilderFactory.create(rel.getCluster(), null);
final Set<CorrelationId> correlationIds = new HashSet<>();
final ArrayList<RexNode> corrVar = new ArrayList<>();
if (corrVar.isEmpty()) {
for (int i = 0; i < batchSize; i++) {
CorrelationId correlationId = cluster.createCorrel();
correlationIds.add(correlationId);
corrVar.add(rexBuilder.makeCorrel(rel.getLeft().getRowType(), correlationId));
}
}
// Generate first condition
final RexNode condition = rel.getCondition().accept(new RexShuttle() {
@Override
public RexNode visitInputRef(RexInputRef input) {
int field = input.getIndex();
if (field >= leftFieldCount)
return rexBuilder.makeInputRef(input.getType(), input.getIndex() - leftFieldCount);
return rexBuilder.makeFieldAccess(corrVar.get(0), field);
}
});
List<RexNode> conditionList = new ArrayList<>();
conditionList.add(condition);
// Add batchSize-1 other conditions
for (int i = 1; i < batchSize; i++) {
final int corrIndex = i;
final RexNode condition2 = condition.accept(new RexShuttle() {
@Override
public RexNode visitCorrelVariable(RexCorrelVariable variable) {
return corrVar.get(corrIndex);
}
});
conditionList.add(condition2);
}
RelTraitSet filterInTraits = rel.getRight().getTraitSet();
// Push a filter with batchSize disjunctions
relBuilder.push(rel.getRight().copy(filterInTraits, rel.getRight().getInputs())).filter(relBuilder.or(conditionList));
RelNode right = relBuilder.build();
JoinRelType joinType = rel.getJoinType();
RelTraitSet outTraits = cluster.traitSetOf(IgniteConvention.INSTANCE);
RelTraitSet leftInTraits = cluster.traitSetOf(IgniteConvention.INSTANCE);
CorrelationTrait corrTrait = CorrelationTrait.correlations(correlationIds);
RelTraitSet rightInTraits = cluster.traitSetOf(IgniteConvention.INSTANCE).replace(RewindabilityTrait.REWINDABLE).replace(corrTrait);
RelNode left = convert(rel.getLeft(), leftInTraits);
right = convert(right, rightInTraits);
return new IgniteCorrelatedNestedLoopJoin(cluster, outTraits, left, right, rel.getCondition(), correlationIds, joinType);
}
use of org.apache.calcite.rel.core.CorrelationId in project ignite by apache.
the class TableFunctionScanConverterRule method convert.
/**
* {@inheritDoc}
*/
@Override
protected PhysicalNode convert(RelOptPlanner planner, RelMetadataQuery mq, LogicalTableFunctionScan rel) {
assert F.isEmpty(rel.getInputs());
RelTraitSet traitSet = rel.getTraitSet().replace(IgniteConvention.INSTANCE).replace(RewindabilityTrait.REWINDABLE).replace(IgniteDistributions.broadcast());
Set<CorrelationId> corrIds = RexUtils.extractCorrelationIds(rel.getCall());
if (!corrIds.isEmpty())
traitSet = traitSet.replace(CorrelationTrait.correlations(corrIds));
return new IgniteTableFunctionScan(rel.getCluster(), traitSet, rel.getCall(), rel.getRowType());
}
Aggregations