use of org.apache.ignite.internal.processors.query.calcite.rel.IgniteFilter in project ignite by apache.
the class FilterSpoolMergeToSortedIndexSpoolRule method onMatch.
/**
* {@inheritDoc}
*/
@Override
public void onMatch(RelOptRuleCall call) {
final IgniteFilter filter = call.rel(0);
final IgniteTableSpool spool = call.rel(1);
RelOptCluster cluster = spool.getCluster();
RelTraitSet trait = spool.getTraitSet();
CorrelationTrait filterCorr = TraitUtils.correlation(filter);
if (filterCorr.correlated())
trait = trait.replace(filterCorr);
RelNode input = spool.getInput();
RelCollation inCollation = TraitUtils.collation(input);
IndexConditions idxCond = RexUtils.buildSortedIndexConditions(cluster, inCollation, filter.getCondition(), spool.getRowType(), null);
if (F.isEmpty(idxCond.lowerCondition()) && F.isEmpty(idxCond.upperCondition()))
return;
RelCollation traitCollation;
RelCollation searchCollation;
if (inCollation == null || inCollation.isDefault()) {
// Create collation by index condition.
List<RexNode> lowerBound = idxCond.lowerBound();
List<RexNode> upperBound = idxCond.upperBound();
assert lowerBound == null || upperBound == null || lowerBound.size() == upperBound.size();
int cardinality = lowerBound != null ? lowerBound.size() : upperBound.size();
List<Integer> equalsFields = new ArrayList<>(cardinality);
List<Integer> otherFields = new ArrayList<>(cardinality);
// First, add all equality filters to collation, then add other fields.
for (int i = 0; i < cardinality; i++) {
RexNode lowerNode = lowerBound != null ? lowerBound.get(i) : null;
RexNode upperNode = upperBound != null ? upperBound.get(i) : null;
if (RexUtils.isNotNull(lowerNode) || RexUtils.isNotNull(upperNode))
(F.eq(lowerNode, upperNode) ? equalsFields : otherFields).add(i);
}
searchCollation = traitCollation = TraitUtils.createCollation(F.concat(true, equalsFields, otherFields));
} else {
// Create search collation as a prefix of input collation.
traitCollation = inCollation;
Set<Integer> searchKeys = idxCond.keys();
List<RelFieldCollation> collationFields = inCollation.getFieldCollations().subList(0, searchKeys.size());
assert searchKeys.containsAll(collationFields.stream().map(RelFieldCollation::getFieldIndex).collect(Collectors.toSet())) : "Search condition should be a prefix of collation [searchKeys=" + searchKeys + ", collation=" + inCollation + ']';
searchCollation = RelCollations.of(collationFields);
}
RelNode res = new IgniteSortedIndexSpool(cluster, trait.replace(traitCollation), convert(input, input.getTraitSet().replace(traitCollation)), searchCollation, filter.getCondition(), idxCond);
call.transformTo(res);
}
use of org.apache.ignite.internal.processors.query.calcite.rel.IgniteFilter in project ignite by apache.
the class FilterConverterRule method convert.
/**
* {@inheritDoc}
*/
@Override
protected PhysicalNode convert(RelOptPlanner planner, RelMetadataQuery mq, LogicalFilter rel) {
RelOptCluster cluster = rel.getCluster();
RelTraitSet traits = cluster.traitSetOf(IgniteConvention.INSTANCE).replace(IgniteDistributions.single());
Set<CorrelationId> corrIds = RexUtils.extractCorrelationIds(rel.getCondition());
if (!corrIds.isEmpty()) {
traits = traits.replace(CorrelationTrait.correlations(corrIds)).replace(RewindabilityTrait.REWINDABLE);
}
return new IgniteFilter(cluster, traits, convert(rel.getInput(), traits.replace(CorrelationTrait.UNCORRELATED)), rel.getCondition());
}
use of org.apache.ignite.internal.processors.query.calcite.rel.IgniteFilter in project ignite by apache.
the class PlannerTest method testMergeFilters.
/**
* @throws Exception If failed.
*/
@Test
public void testMergeFilters() throws Exception {
IgniteTypeFactory f = new IgniteTypeFactory(IgniteTypeSystem.INSTANCE);
TestTable testTbl = new TestTable(new RelDataTypeFactory.Builder(f).add("ID", f.createJavaType(Integer.class)).add("VAL", f.createJavaType(String.class)).build()) {
@Override
public IgniteDistribution distribution() {
return IgniteDistributions.single();
}
};
IgniteSchema publicSchema = new IgniteSchema("PUBLIC");
publicSchema.addTable("TEST", testTbl);
String sql = "" + "SELECT val from (\n" + " SELECT * \n" + " FROM TEST \n" + " WHERE VAL = 10) \n" + "WHERE VAL = 10";
RelNode phys = physicalPlan(sql, publicSchema);
assertNotNull(phys);
AtomicInteger filterCnt = new AtomicInteger();
// Counts filters af the plan.
phys.childrenAccept(new RelVisitor() {
@Override
public void visit(RelNode node, int ordinal, RelNode parent) {
if (node instanceof IgniteFilter)
filterCnt.incrementAndGet();
super.visit(node, ordinal, parent);
}
});
// Checks that two filter merged into one filter.
// Expected plan:
// IgniteProject(VAL=[$1])
// IgniteProject(ID=[$0], VAL=[$1])
// IgniteFilter(condition=[=(CAST($1):INTEGER, 10)])
// IgniteTableScan(table=[[PUBLIC, TEST]])
assertEquals(0, filterCnt.get());
}
use of org.apache.ignite.internal.processors.query.calcite.rel.IgniteFilter in project ignite by apache.
the class CorrelatedSubqueryPlannerTest method test.
/**
* Test verifies the row type is consistent for correlation variable and
* node that actually puts this variable into a context.
*
* In this particular test the row type of the left input of CNLJ node should
* match the row type correlated variable in the filter was created with.
*
* @throws Exception In case of any unexpected error.
*/
@Test
public void test() throws Exception {
IgniteSchema schema = createSchema(createTable("T1", IgniteDistributions.single(), "A", Integer.class, "B", Integer.class, "C", Integer.class, "D", Integer.class, "E", Integer.class));
String sql = "" + "SELECT (SELECT count(*) FROM t1 AS x WHERE x.b<t1.b)\n" + " FROM t1\n" + " WHERE (a>e-2 AND a<e+2)\n" + " OR c>d\n" + " ORDER BY 1;";
IgniteRel rel = physicalPlan(sql, schema, "FilterTableScanMergeRule");
IgniteFilter filter = findFirstNode(rel, byClass(IgniteFilter.class).and(f -> RexUtils.hasCorrelation(((Filter) f).getCondition())));
RexFieldAccess fieldAccess = findFirst(filter.getCondition(), RexFieldAccess.class);
assertNotNull(fieldAccess);
assertEquals(RexCorrelVariable.class, fieldAccess.getReferenceExpr().getClass());
IgniteCorrelatedNestedLoopJoin join = findFirstNode(rel, byClass(IgniteCorrelatedNestedLoopJoin.class));
assertEquals(fieldAccess.getReferenceExpr().getType(), join.getLeft().getRowType());
}
use of org.apache.ignite.internal.processors.query.calcite.rel.IgniteFilter in project ignite by apache.
the class FilterSpoolMergeToHashIndexSpoolRule method onMatch.
/**
* {@inheritDoc}
*/
@Override
public void onMatch(RelOptRuleCall call) {
final IgniteFilter filter = call.rel(0);
final IgniteTableSpool spool = call.rel(1);
RelOptCluster cluster = spool.getCluster();
RelTraitSet trait = spool.getTraitSet();
CorrelationTrait filterCorr = TraitUtils.correlation(filter);
if (filterCorr.correlated())
trait = trait.replace(filterCorr);
RelNode input = spool.getInput();
List<RexNode> searchRow = RexUtils.buildHashSearchRow(cluster, filter.getCondition(), spool.getRowType(), null, false);
if (F.isEmpty(searchRow))
return;
RelNode res = new IgniteHashIndexSpool(cluster, trait.replace(RelCollations.EMPTY), input, searchRow, filter.getCondition());
call.transformTo(res);
}
Aggregations