use of org.voltdb.plannodes.IndexCountPlanNode in project voltdb by VoltDB.
the class ReplaceWithIndexCounter method recursivelyApply.
@Override
protected AbstractPlanNode recursivelyApply(AbstractPlanNode plan) {
assert (plan != null);
// depth first:
// find AggregatePlanNode with exactly one child
// where that child is an AbstractScanPlanNode.
// Replace any qualifying AggregatePlanNode / AbstractScanPlanNode pair
// with an IndexCountPlanNode or TableCountPlanNode
ArrayList<AbstractPlanNode> children = new ArrayList<AbstractPlanNode>();
for (int i = 0; i < plan.getChildCount(); i++) children.add(plan.getChild(i));
for (AbstractPlanNode child : children) {
// TODO this will break when children feed multiple parents
AbstractPlanNode newChild = recursivelyApply(child);
// Do a graft into the (parent) plan only if a replacement for a child was found.
if (newChild == child) {
continue;
}
boolean replaced = plan.replaceChild(child, newChild);
assert (true == replaced);
}
// check for an aggregation of the right form
if ((plan instanceof AggregatePlanNode) == false)
return plan;
assert (plan.getChildCount() == 1);
AggregatePlanNode aggplan = (AggregatePlanNode) plan;
// ENG-6131 fixed here.
if (!(aggplan.isTableCountStar() || aggplan.isTableNonDistinctCountConstant() || aggplan.isTableCountNonDistinctNullableColumn())) {
return plan;
}
AbstractPlanNode child = plan.getChild(0);
// A table count can replace a seq scan only if it has no predicates.
if (child instanceof SeqScanPlanNode) {
if (((SeqScanPlanNode) child).getPredicate() != null) {
return plan;
}
AbstractExpression postPredicate = aggplan.getPostPredicate();
if (postPredicate != null) {
List<AbstractExpression> aggList = postPredicate.findAllAggregateSubexpressions();
boolean allCountStar = true;
for (AbstractExpression expr : aggList) {
if (expr.getExpressionType() != ExpressionType.AGGREGATE_COUNT_STAR) {
allCountStar = false;
break;
}
}
if (allCountStar) {
return plan;
}
}
if (hasInlineLimit(aggplan)) {
// table count EE executor does not handle inline limit stuff
return plan;
}
return new TableCountPlanNode((AbstractScanPlanNode) child, aggplan);
}
// Otherwise, optimized counts only replace particular cases of index scan.
if ((child instanceof IndexScanPlanNode) == false)
return plan;
IndexScanPlanNode isp = (IndexScanPlanNode) child;
// Guard against (possible future?) cases of indexable subquery.
if (((IndexScanPlanNode) child).isSubQuery()) {
return plan;
}
// except those (post-)predicates are artifact predicates we added for reverse scan purpose only
if (isp.getPredicate() != null && !isp.isPredicatesOptimizableForAggregate()) {
return plan;
}
// With no start or end keys, there's not much a counting index can do.
if (isp.getEndExpression() == null && isp.getSearchKeyExpressions().size() == 0) {
if (hasInlineLimit(aggplan)) {
return plan;
}
return new TableCountPlanNode(isp, aggplan);
}
// check for the index's support for counting
Index idx = isp.getCatalogIndex();
if (!idx.getCountable()) {
return plan;
}
// The core idea is that counting index needs to know the start key and end key to
// jump to to get counts instead of actually doing any scanning.
// Options to be determined are:
// - whether each of the start/end keys is missing, partial (a prefix of a compund key), or complete,
// - whether the count should include or exclude entries exactly matching each of the start/end keys.
// Not all combinations of these options are supported;
// unsupportable cases cause the factory method to return null.
IndexCountPlanNode countingPlan = IndexCountPlanNode.createOrNull(isp, aggplan);
if (countingPlan == null) {
return plan;
}
return countingPlan;
}
use of org.voltdb.plannodes.IndexCountPlanNode in project voltdb by VoltDB.
the class TestPlansCount method testCountStar26.
// test with FLOAT type
public void testCountStar26() {
List<AbstractPlanNode> pn = compileToFragments("SELECT count(*) from P1 WHERE NUM = 1 AND RATIO >= ?");
for (AbstractPlanNode nd : pn) System.out.println("PlanNode Explain string:\n" + nd.toExplainPlanString());
AbstractPlanNode p = pn.get(0).getChild(0);
assertTrue(p instanceof AggregatePlanNode);
p = pn.get(1).getChild(0);
assertTrue(p instanceof IndexCountPlanNode);
pn = compileToFragments("SELECT count(1) from P1 WHERE NUM = 1 AND RATIO >= ?");
for (AbstractPlanNode nd : pn) System.out.println("PlanNode Explain string:\n" + nd.toExplainPlanString());
p = pn.get(0).getChild(0);
assertTrue(p instanceof AggregatePlanNode);
p = pn.get(1).getChild(0);
assertTrue(p instanceof IndexCountPlanNode);
}
use of org.voltdb.plannodes.IndexCountPlanNode in project voltdb by VoltDB.
the class TestPlansCount method checkIndexCounter.
/**
* Check Whether or not the original plan is replaced with CountingIndexPlanNode.
*
* @param pn
* The generated plan
* @param isReplaceable
* Whether or not the original plan is replaced with CountingIndexPlanNode
*/
private void checkIndexCounter(List<AbstractPlanNode> pn, boolean isReplaceable) {
assertTrue(pn.size() > 0);
for (AbstractPlanNode nd : pn) {
System.out.println("PlanNode Explain string:\n" + nd.toExplainPlanString());
}
AbstractPlanNode p = pn.get(0).getChild(0);
if (isReplaceable)
assertTrue(p instanceof IndexCountPlanNode);
else
assertTrue((p instanceof IndexCountPlanNode) == false);
}
use of org.voltdb.plannodes.IndexCountPlanNode in project voltdb by VoltDB.
the class TestPlansCount method testCountStar19.
// Planner bug with Constant value overflow
public void testCountStar19() {
List<AbstractPlanNode> pn = compileToFragments("SELECT count(*) from T2 WHERE USERNAME ='XIN' AND POINTS >= 3 AND POINTS <= 600000000000000000000000000");
AbstractPlanNode p = pn.get(0).getChild(0);
assertTrue((p instanceof IndexCountPlanNode) == false);
pn = compileToFragments("SELECT count(1) from T2 WHERE USERNAME ='XIN' AND POINTS >= 3 AND POINTS <= 600000000000000000000000000");
p = pn.get(0).getChild(0);
assertTrue((p instanceof IndexCountPlanNode) == false);
}
use of org.voltdb.plannodes.IndexCountPlanNode in project voltdb by VoltDB.
the class TestPlansCount method testCountStar22.
// Test counting index feature with partitioned table
public void testCountStar22() {
List<AbstractPlanNode> pn = compileToFragments("SELECT count(*) from P1 WHERE NUM < ?");
for (AbstractPlanNode nd : pn) System.out.println("PlanNode Explain string:\n" + nd.toExplainPlanString());
AbstractPlanNode p = pn.get(0).getChild(0);
assertTrue(p instanceof AggregatePlanNode);
p = pn.get(1).getChild(0);
assertTrue(p instanceof IndexCountPlanNode);
pn = compileToFragments("SELECT count(1) from P1 WHERE NUM < ?");
for (AbstractPlanNode nd : pn) System.out.println("PlanNode Explain string:\n" + nd.toExplainPlanString());
p = pn.get(0).getChild(0);
assertTrue(p instanceof AggregatePlanNode);
p = pn.get(1).getChild(0);
assertTrue(p instanceof IndexCountPlanNode);
}
Aggregations