/** * Parse the scan_columns element out of the HSQL-generated XML. Fills scanColumns with a list of * the columns used in the plan, hashed by table name. * * @param columnsNode */ void parseScanColumns(VoltXMLElement columnsNode) { scanColumns = new HashMap<String, ArrayList<SchemaColumn>>(); for (VoltXMLElement child : columnsNode.children) { assert (child.name.equals("columnref")); AbstractExpression col_exp = parseExpressionTree(child); // TupleValueExpressions are always specifically typed, // so there is no need for expression type specialization, here. assert (col_exp != null); assert (col_exp instanceof TupleValueExpression); TupleValueExpression tve = (TupleValueExpression) col_exp; SchemaColumn col = new SchemaColumn(tve.getTableName(), tve.getColumnName(), tve.getColumnAlias(), col_exp); ArrayList<SchemaColumn> table_cols = null; if (!scanColumns.containsKey(col.getTableName())) { table_cols = new ArrayList<SchemaColumn>(); scanColumns.put(col.getTableName(), table_cols); } table_cols = scanColumns.get(col.getTableName()); table_cols.add(col); } }
public void setTypeSizeAndInBytes(SchemaColumn typeSource) { setValueType(typeSource.getType()); setValueSize(typeSource.getSize()); m_inBytes = typeSource.getExpression().getInBytes(); }
@Override public String toString() { String retval = "SQL:\n\t" + sql + "\n"; retval += "PARAMETERS:\n\t"; for (VoltType param : paramList) { retval += param.toString() + " "; } retval += "\nTABLE SOURCES:\n\t"; for (Table table : tableList) { retval += table.getTypeName() + " "; } retval += "\nSCAN COLUMNS:\n"; if (scanColumns != null) { for (String table : scanColumns.keySet()) { retval += "\tTable: " + table + ":\n"; for (SchemaColumn col : scanColumns.get(table)) { retval += "\t\tColumn: " + col.getColumnName() + ": "; retval += col.getExpression().toString() + "\n"; } } } else { retval += "\tALL\n"; } if (where != null) { retval += "\nWHERE:\n"; retval += "\t" + where.toString() + "\n"; retval += "WHERE SELECTION LIST:\n"; int i = 0; for (AbstractExpression expr : whereSelectionList) retval += "\t(" + String.valueOf(i++) + ") " + expr.toString() + "\n"; retval += "NO TABLE SELECTION LIST:\n"; i = 0; for (AbstractExpression expr : noTableSelectionList) retval += "\t(" + String.valueOf(i++) + ") " + expr.toString() + "\n"; retval += "TABLE FILTER LIST:\n"; for (Entry<Table, ArrayList<AbstractExpression>> pair : tableFilterList.entrySet()) { i = 0; retval += "\tTABLE: " + pair.getKey().getTypeName() + "\n"; for (AbstractExpression expr : pair.getValue()) retval += "\t\t(" + String.valueOf(i++) + ") " + expr.toString() + "\n"; } retval += "JOIN CLAUSE LIST:\n"; for (Entry<TablePair, ArrayList<AbstractExpression>> pair : joinSelectionList.entrySet()) { i = 0; retval += "\tTABLES: " + pair.getKey().t1.getTypeName() + " and " + pair.getKey().t2.getTypeName() + "\n"; for (AbstractExpression expr : pair.getValue()) retval += "\t\t(" + String.valueOf(i++) + ") " + expr.toString() + "\n"; } } return retval; }
/** * Compile and cache the statement and plan and return the final plan graph. * * @param sql * @param paramCount */ public List<AbstractPlanNode> compile( String sql, int paramCount, String joinOrder, Object partitionParameter, boolean inferSP, boolean lockInSP) { Statement catalogStmt = proc.getStatements().add("stmt-" + String.valueOf(compileCounter++)); catalogStmt.setSqltext(sql); catalogStmt.setSinglepartition(partitionParameter != null); catalogStmt.setBatched(false); catalogStmt.setParamnum(paramCount); // determine the type of the query QueryType qtype = QueryType.SELECT; catalogStmt.setReadonly(true); if (sql.toLowerCase().startsWith("insert")) { qtype = QueryType.INSERT; catalogStmt.setReadonly(false); } if (sql.toLowerCase().startsWith("update")) { qtype = QueryType.UPDATE; catalogStmt.setReadonly(false); } if (sql.toLowerCase().startsWith("delete")) { qtype = QueryType.DELETE; catalogStmt.setReadonly(false); } catalogStmt.setQuerytype(qtype.getValue()); // name will look like "basename-stmt-#" String name = catalogStmt.getParent().getTypeName() + "-" + catalogStmt.getTypeName(); DatabaseEstimates estimates = new DatabaseEstimates(); TrivialCostModel costModel = new TrivialCostModel(); PartitioningForStatement partitioning = new PartitioningForStatement(partitionParameter, inferSP, lockInSP); QueryPlanner planner = new QueryPlanner( catalogStmt.getSqltext(), catalogStmt.getTypeName(), catalogStmt.getParent().getTypeName(), catalog.getClusters().get("cluster"), db, partitioning, hsql, estimates, false, StatementCompiler.DEFAULT_MAX_JOIN_TABLES, costModel, null, joinOrder); CompiledPlan plan = null; planner.parse(); plan = planner.plan(); assert (plan != null); // Input Parameters // We will need to update the system catalogs with this new information // If this is an adhoc query then there won't be any parameters for (int i = 0; i < plan.parameters.length; ++i) { StmtParameter catalogParam = catalogStmt.getParameters().add(String.valueOf(i)); catalogParam.setJavatype(plan.parameters[i].getValue()); catalogParam.setIndex(i); } // Output Columns int index = 0; for (SchemaColumn col : plan.columns.getColumns()) { Column catColumn = catalogStmt.getOutput_columns().add(String.valueOf(index)); catColumn.setNullable(false); catColumn.setIndex(index); catColumn.setName(col.getColumnName()); catColumn.setType(col.getType().getValue()); catColumn.setSize(col.getSize()); index++; } List<PlanNodeList> nodeLists = new ArrayList<PlanNodeList>(); nodeLists.add(new PlanNodeList(plan.rootPlanGraph)); if (plan.subPlanGraph != null) { nodeLists.add(new PlanNodeList(plan.subPlanGraph)); } // Store the list of parameters types and indexes in the plan node list. List<Pair<Integer, VoltType>> parameters = nodeLists.get(0).getParameters(); for (int i = 0; i < plan.parameters.length; ++i) { Pair<Integer, VoltType> parameter = new Pair<Integer, VoltType>(i, plan.parameters[i]); parameters.add(parameter); } // Now update our catalog information // HACK: We're using the node_tree's hashCode() as it's name. It would be really // nice if the Catalog code give us an guid without needing a name first... String json = null; try { JSONObject jobj = new JSONObject(nodeLists.get(0).toJSONString()); json = jobj.toString(4); } catch (JSONException e2) { // TODO Auto-generated catch block e2.printStackTrace(); System.exit(-1); } // // We then stick a serialized version of PlanNodeTree into a PlanFragment // try { BuildDirectoryUtils.writeFile("statement-plans", name + "_json.txt", json); BuildDirectoryUtils.writeFile( "statement-plans", name + ".dot", nodeLists.get(0).toDOTString("name")); } catch (Exception e) { e.printStackTrace(); } List<AbstractPlanNode> plannodes = new ArrayList<AbstractPlanNode>(); for (PlanNodeList nodeList : nodeLists) { plannodes.add(nodeList.getRootPlanNode()); } m_currentPlan = plan; return plannodes; }