}
if (allCountStar) {
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;
}
// An index count or table count can replace an index scan only if it has no (post-)predicates
// 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) {
// An indexed query without a where clause can fall back to a plain old table count.
// This can only happen when a confused query like
// "select count(*) from table order by index_key;"
// meets a naive planner that doesn't just cull the no-op ORDER BY. Who, us?
return new TableCountPlanNode(isp, aggplan);
}
// check for the index's support for counting
Index idx = isp.getCatalogIndex();
if ( ! idx.getCountable()) {