use of org.voltdb.planner.parseinfo.StmtTableScan in project voltdb by VoltDB.
the class AbstractParsedStmt method toString.
@Override
public String toString() {
String retval = "SQL:\n\t" + m_sql + "\n";
retval += "PARAMETERS:\n\t";
for (Map.Entry<Integer, ParameterValueExpression> paramEntry : m_paramsByIndex.entrySet()) {
retval += paramEntry.getValue().toString() + " ";
}
retval += "\nTABLE SOURCES:\n\t";
for (Table table : m_tableList) {
retval += table.getTypeName() + " ";
}
retval += "\nSCAN COLUMNS:\n";
boolean hasAll = true;
for (StmtTableScan tableScan : m_tableAliasMap.values()) {
List<SchemaColumn> scanColumns = tableScan.getScanColumns();
if (scanColumns.isEmpty()) {
continue;
}
hasAll = false;
retval += "\tTable Alias: " + tableScan.getTableAlias() + ":\n";
for (SchemaColumn col : scanColumns) {
retval += "\t\tColumn: " + col.getColumnName() + ": ";
retval += col.getExpression().toString() + "\n";
}
}
if (hasAll) {
retval += "\tALL\n";
}
retval += "\nJOIN TREE :\n";
if (m_joinTree != null) {
retval += m_joinTree.toString();
}
retval += "NO TABLE SELECTION LIST:\n";
int i = 0;
for (AbstractExpression expr : m_noTableSelectionList) {
retval += "\t(" + String.valueOf(i++) + ") " + expr.toString() + "\n";
}
return retval;
}
use of org.voltdb.planner.parseinfo.StmtTableScan in project voltdb by VoltDB.
the class PlanAssembler method connectChildrenBestPlans.
/**
* For each Subquery node in the plan tree attach the subquery plan to the parent node.
* @param initial plan
* @return A complete plan tree for the entire SQl.
*/
private AbstractPlanNode connectChildrenBestPlans(AbstractPlanNode parentPlan) {
if (parentPlan instanceof AbstractScanPlanNode) {
AbstractScanPlanNode scanNode = (AbstractScanPlanNode) parentPlan;
StmtTableScan tableScan = scanNode.getTableScan();
if (tableScan instanceof StmtSubqueryScan) {
CompiledPlan bestCostPlan = ((StmtSubqueryScan) tableScan).getBestCostPlan();
assert (bestCostPlan != null);
AbstractPlanNode subQueryRoot = bestCostPlan.rootPlanGraph;
subQueryRoot.disconnectParents();
scanNode.clearChildren();
scanNode.addAndLinkChild(subQueryRoot);
}
} else {
for (int i = 0; i < parentPlan.getChildCount(); ++i) {
connectChildrenBestPlans(parentPlan.getChild(i));
}
}
return parentPlan;
}
use of org.voltdb.planner.parseinfo.StmtTableScan in project voltdb by VoltDB.
the class PlanAssembler method canPushDownDistinctAggregation.
private boolean canPushDownDistinctAggregation(AggregateExpression aggExpr) {
assert (m_parsedSelect != null);
assert (aggExpr != null);
assert (aggExpr.isDistinct());
if (aggExpr.getExpressionType() == ExpressionType.AGGREGATE_COUNT_STAR) {
return true;
}
AbstractExpression aggArg = aggExpr.getLeft();
// constant
if (aggArg instanceof ConstantValueExpression || aggArg instanceof ParameterValueExpression) {
return true;
}
if (!(aggArg instanceof TupleValueExpression)) {
return false;
}
TupleValueExpression tve = (TupleValueExpression) aggArg;
String tableAlias = tve.getTableAlias();
StmtTableScan scanTable = m_parsedSelect.getStmtTableScanByAlias(tableAlias);
// table alias may be from AbstractParsedStmt.TEMP_TABLE_NAME.
if (scanTable == null || scanTable.getPartitioningColumns() == null) {
return false;
}
for (SchemaColumn pcol : scanTable.getPartitioningColumns()) {
if (pcol != null && pcol.getColumnName().equals(tve.getColumnName())) {
return true;
}
}
return false;
}
use of org.voltdb.planner.parseinfo.StmtTableScan in project voltdb by VoltDB.
the class TestPlansSubQueries method checkSubqueryNoSimplification.
private void checkSubqueryNoSimplification(String sql) {
AbstractPlanNode pn = compile(sql);
pn = pn.getChild(0);
assertEquals(PlanNodeType.SEQSCAN, pn.getPlanNodeType());
StmtTableScan tableScan = ((SeqScanPlanNode) pn).getTableScan();
assertTrue(tableScan instanceof StmtSubqueryScan);
}
use of org.voltdb.planner.parseinfo.StmtTableScan in project voltdb by VoltDB.
the class SelectSubPlanAssembler method nextPlan.
/**
* Pull a join order out of the join orders deque, compute all possible plans
* for that join order, then append them to the computed plans deque.
*/
@Override
protected AbstractPlanNode nextPlan() {
// or no more plans can be created
while (m_plans.size() == 0) {
// get the join order for us to make plans out of
JoinNode joinTree = m_joinOrders.poll();
// no more join orders => no more plans to generate
if (joinTree == null) {
return null;
}
// Analyze join and filter conditions
joinTree.analyzeJoinExpressions(m_parsedStmt.m_noTableSelectionList);
// a query that is a little too quirky or complicated.
if (!m_parsedStmt.m_noTableSelectionList.isEmpty()) {
throw new PlanningErrorException("Join with filters that do not depend on joined tables is not supported in VoltDB");
}
if (!m_partitioning.wasSpecifiedAsSingle()) {
// Now that analyzeJoinExpressions has done its job of properly categorizing
// and placing the various filters that the HSQL parser tends to leave in the strangest
// configuration, this is the first opportunity to analyze WHERE and JOIN filters'
// effects on statement partitioning.
// But this causes the analysis to be run based on a particular join order.
// Which join orders does this analysis actually need to be run on?
// Can it be run on the first join order and be assumed to hold for all join orders?
// If there is a join order that fails to generate a single viable plan, is its
// determination of partitioning (or partitioning failure) always valid for other
// join orders, or should the analysis be repeated on a viable join order
// in that case?
// For now, analyze each join order independently and when an invalid partitioning is
// detected, skip the plan generation for that particular ordering.
// If this causes all plans to be skipped, commonly the case, the PlanAssembler
// should propagate an error message identifying partitioning as the problem.
HashMap<AbstractExpression, Set<AbstractExpression>> valueEquivalence = joinTree.getAllEquivalenceFilters();
Collection<StmtTableScan> scans = m_parsedStmt.allScans();
m_partitioning.analyzeForMultiPartitionAccess(scans, valueEquivalence);
if (!m_partitioning.isJoinValid()) {
// The case of more than one independent partitioned table
// would result in an illegal plan with more than two fragments.
// Don't throw a planning error here, in case the problem is just with this
// particular join order, but do leave a hint to the PlanAssembler in case
// the failure is unanimous -- a common case.
m_recentErrorMsg = m_partitioning.getJoinInvalidReason();
// This join order, at least, is not worth trying to plan.
continue;
}
}
generateMorePlansForJoinTree(joinTree);
}
return m_plans.poll();
}
Aggregations