Exemple #1
0
  static String genrateStatementRow(Procedure procedure, Statement statement) {
    StringBuilder sb = new StringBuilder();
    sb.append("        <tr class='primaryrow2'>");

    // name column
    String anchor = (procedure.getTypeName() + "-" + statement.getTypeName()).toLowerCase();
    sb.append(
        "<td style='white-space: nowrap'><i id='p-"
            + anchor
            + "--icon' class='icon-chevron-right'></i> <a href='#' id='p-");
    sb.append(anchor).append("' class='togglex'>");
    sb.append(statement.getTypeName());
    sb.append("</a></td>");

    // sql column
    sb.append("<td><tt>");
    sb.append(statement.getSqltext());
    sb.append("</td></tt>");

    // params column
    sb.append("<td>");
    List<StmtParameter> params =
        CatalogUtil.getSortedCatalogItems(statement.getParameters(), "index");
    List<String> paramTypes = new ArrayList<String>();
    for (StmtParameter param : params) {
      paramTypes.add(VoltType.get((byte) param.getJavatype()).name());
    }
    if (paramTypes.size() == 0) {
      sb.append("<i>None</i>");
    }
    sb.append(StringUtils.join(paramTypes, ", "));
    sb.append("</td>");

    // r/w column
    sb.append("<td>");
    if (statement.getReadonly()) {
      tag(sb, "success", "Read");
    } else {
      tag(sb, "warning", "Write");
    }
    sb.append("</td>");

    // attributes
    sb.append("<td>");

    if (!statement.getIscontentdeterministic() || !statement.getIsorderdeterministic()) {
      tag(sb, "inverse", "Determinism");
    }

    if (statement.getSeqscancount() > 0) {
      tag(sb, "important", "Scans");
    }

    sb.append("</td>");

    sb.append("</tr>\n");

    // BUILD THE DROPDOWN FOR THE PLAN/DETAIL TABLE
    sb.append(
        "<tr class='dropdown2'><td colspan='5' id='p-"
            + procedure.getTypeName().toLowerCase()
            + "-"
            + statement.getTypeName().toLowerCase()
            + "--dropdown'>\n");

    sb.append("<div class='well well-small'><h4>Explain Plan:</h4>\n");
    StatementAnnotation annotation = (StatementAnnotation) statement.getAnnotation();
    if (annotation != null) {
      String plan = annotation.explainPlan;
      plan = plan.replace("\n", "<br/>");
      plan = plan.replace(" ", "&nbsp;");

      for (Table t : annotation.tablesRead) {
        String name = t.getTypeName().toUpperCase();
        String link = "\"<a href='#s-" + t.getTypeName() + "'>" + name + "</a>\"";
        plan = plan.replace("\"" + name + "\"", link);
      }
      for (Table t : annotation.tablesUpdated) {
        String name = t.getTypeName().toUpperCase();
        String link = "\"<a href='#s-" + t.getTypeName() + "'>" + name + "</a>\"";
        plan = plan.replace("\"" + name + "\"", link);
      }
      for (Index i : annotation.indexesUsed) {
        Table t = (Table) i.getParent();
        String name = i.getTypeName().toUpperCase();
        String link =
            "\"<a href='#s-" + t.getTypeName() + "-" + i.getTypeName() + "'>" + name + "</a>\"";
        plan = plan.replace("\"" + name + "\"", link);
      }

      sb.append("<tt>").append(plan).append("</tt>");
    } else {
      sb.append("<i>No SQL explain plan found.</i>\n");
    }
    sb.append("</div>\n");

    sb.append("</td></tr>\n");

    return sb.toString();
  }
  /**
   * 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;
  }