package edu.brown.optimizer;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.voltdb.benchmark.tpcc.procedures.neworder;
import org.voltdb.benchmark.tpcc.procedures.slev;
import org.voltdb.catalog.Column;
import org.voltdb.catalog.Procedure;
import org.voltdb.catalog.Statement;
import org.voltdb.catalog.Table;
import org.voltdb.planner.PlanColumn;
import org.voltdb.planner.PlannerContext;
import org.voltdb.plannodes.AbstractPlanNode;
import org.voltdb.plannodes.AbstractScanPlanNode;
import org.voltdb.plannodes.DistinctPlanNode;
import org.voltdb.plannodes.IndexScanPlanNode;
import org.voltdb.plannodes.ProjectionPlanNode;
import org.voltdb.types.PlanNodeType;
import edu.brown.plannodes.PlanNodeUtil;
import edu.brown.utils.CollectionUtil;
import edu.brown.utils.ProjectType;
/**
*
* @author pavlo
*/
public class TestPlanOptimizerTPCC extends BasePlanOptimizerTestCase {
@Override
protected void setUp() throws Exception {
super.setUp(ProjectType.TPCC);
}
/**
* testProjectionPushdownDistinctOffset
*/
public void testProjectionPushdownDistinctOffset() throws Exception {
Procedure catalog_proc = this.getProcedure(slev.class);
Statement catalog_stmt = this.getStatement(catalog_proc, "GetStockCount");
// Grab the root node of the multi-partition query plan tree for this Statement
AbstractPlanNode root = PlanNodeUtil.getRootPlanNodeForStatement(catalog_stmt, true);
assertNotNull(root);
// Make sure that the DistinctPlanNode's target column is OL_I_ID
Collection<DistinctPlanNode> dist_nodes = PlanNodeUtil.getPlanNodes(root, DistinctPlanNode.class);
assertEquals(1, dist_nodes.size());
DistinctPlanNode dist_node = CollectionUtil.first(dist_nodes);
assertNotNull(dist_node);
int col_guid = dist_node.getDistinctColumnGuid();
PlanColumn pc = PlannerContext.singleton().get(col_guid);
assertNotNull(pc);
assertEquals("OL_I_ID", pc.getDisplayName());
}
/**
* testProjectionPushdown
*/
public void testProjectionPushdown() throws Exception {
Procedure catalog_proc = this.getProcedure(neworder.class);
Statement catalog_stmt = this.getStatement(catalog_proc, "getCustomer");
// Grab the root node of the multi-partition query plan tree for this Statement
AbstractPlanNode root = PlanNodeUtil.getRootPlanNodeForStatement(catalog_stmt, false);
assertNotNull(root);
// First check that our single scan node has an inline Projection
Collection<AbstractScanPlanNode> scan_nodes = PlanNodeUtil.getPlanNodes(root, AbstractScanPlanNode.class);
assertEquals(1, scan_nodes.size());
AbstractScanPlanNode scan_node = CollectionUtil.first(scan_nodes);
assertNotNull(scan_node);
assertEquals(1, scan_node.getInlinePlanNodes().size());
assertNotNull(scan_node.getInlinePlanNodes().get(PlanNodeType.PROJECTION));
// Now check to make sure there are no other Projections in the tree
// Set<ProjectionPlanNode> proj_nodes = PlanNodeUtil.getPlanNodes(root, ProjectionPlanNode.class);
// assertEquals(0, proj_nodes.size());
}
/**
* testInlineProjectionColumns
*/
public void testInlineProjectionColums() throws Exception {
Procedure catalog_proc = this.getProcedure(slev.class);
Statement catalog_stmt = this.getStatement(catalog_proc, "GetStockCount");
AbstractPlanNode root = PlanNodeUtil.getRootPlanNodeForStatement(catalog_stmt, false);
assertNotNull(root);
// Make sure the bottom-most IndexScan has an inline projection with the right columns
Collection<IndexScanPlanNode> scan_nodes = PlanNodeUtil.getPlanNodes(root, IndexScanPlanNode.class);
assertEquals(1, scan_nodes.size());
IndexScanPlanNode scan_node = CollectionUtil.first(scan_nodes);
assertNotNull(scan_node);
assertEquals(1, scan_node.getParentPlanNodeCount());
assertEquals(0, scan_node.getChildPlanNodeCount());
System.err.println(PlanNodeUtil.debug(root));
assertEquals(1, scan_node.getInlinePlanNodeCount());
final Map<String, Integer> col_offset_xref = new HashMap<String, Integer>();
Table catalog_tbl = null;
// STOCK
if (scan_node.getTargetTableName().equals("STOCK")) {
catalog_tbl = this.getTable("STOCK");
for (String colName : new String[]{ "S_I_ID", "S_W_ID", "S_QUANTITY"}) {
Column catalog_col = this.getColumn(catalog_tbl, colName);
col_offset_xref.put(colName, catalog_col.getIndex());
} // FOR
}
// ORDER_LINE
else if (scan_node.getTargetTableName().equals("ORDER_LINE")) {
catalog_tbl = this.getTable("ORDER_LINE");
for (String colName : new String[]{ "OL_I_ID" }) {
Column catalog_col = this.getColumn(catalog_tbl, colName);
col_offset_xref.put(colName, catalog_col.getIndex());
} // FOR
}
else {
assert(false) : "Unexpected table '" + scan_node.getTargetTableName() + "'";
}
assertNotNull(catalog_tbl);
assertFalse(col_offset_xref.isEmpty());
assertEquals(catalog_tbl.getName(), scan_node.getTargetTableName());
// The inline projection in the leaf ScanPlanNode should only output a
// single column (S_I_ID), since this is the only column used in the JOIN
ProjectionPlanNode proj_node = scan_node.getInlinePlanNode(PlanNodeType.PROJECTION);
assertNotNull(proj_node);
assertEquals(1, proj_node.getOutputColumnGUIDCount());
System.err.println(PlanNodeUtil.debug(scan_node));
checkExpressionOffsets(proj_node, col_offset_xref);
}
/**
* testAggregatePushdown
*/
public void testAggregatePushdown() throws Exception {
Procedure catalog_proc = this.getProcedure(slev.class);
Statement catalog_stmt = this.getStatement(catalog_proc, "GetStockCount");
// Grab the root node of the multi-partition query plan tree for this Statement
AbstractPlanNode root = PlanNodeUtil.getRootPlanNodeForStatement(catalog_stmt, false);
assertNotNull(root);
// Check that our single scan node has a COUNT AggregatePlanNode above it.
Collection<AbstractScanPlanNode> scan_nodes = PlanNodeUtil.getPlanNodes(root, AbstractScanPlanNode.class);
assertEquals(1, scan_nodes.size());
AbstractScanPlanNode scan_node = CollectionUtil.first(scan_nodes);
assertNotNull(scan_node);
assertEquals(1, scan_node.getParentPlanNodeCount());
// FIXME assertEquals(PlanNodeType.AGGREGATE, scan_node.getParent(0).getPlanNodeType());
// FIXME AggregatePlanNode count_node = (AggregatePlanNode)scan_node.getParent(0);
// FIXME assertNotNull(count_node);
// FIXME assert(count_node.getAggregateTypes().contains(ExpressionType.AGGREGATE_COUNT));
// Now check that we have a SUM AggregatePlanNode right before the root
// This will sum up the counts from the different partitions and give us the total count
assertEquals(1, root.getChildPlanNodeCount());
// FIXME assertEquals(PlanNodeType.AGGREGATE, root.getChild(0).getPlanNodeType());
// FIXME AggregatePlanNode sum_node= (AggregatePlanNode)root.getChild(0);
// FIXME assert(sum_node.getAggregateTypes().contains(ExpressionType.AGGREGATE_SUM));
}
}