Example #1
0
  static String generateSchemaRow(Table table, boolean isExportTable) {
    StringBuilder sb = new StringBuilder();
    sb.append("<tr class='primaryrow'>");

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

    // column 2: type
    sb.append("<td>");
    if (table.getMaterializer() != null) {
      tag(sb, "info", "Materialized View");
    } else {
      if (isExportTable) {
        tag(sb, "inverse", "Export Table");
      } else {
        tag(sb, null, "Table");
      }
    }
    sb.append("</td>");

    // column 3: partitioning
    sb.append("<td style='whitespace: nowrap;'>");
    if (table.getIsreplicated()) {
      tag(sb, "warning", "Replicated");
    } else {
      tag(sb, "success", "Partitioned");
      Column partitionCol = table.getPartitioncolumn();
      if (partitionCol != null) {
        sb.append("<small> on " + partitionCol.getName() + "</small>");
      } else {
        Table matSrc = table.getMaterializer();
        if (matSrc != null) {
          sb.append("<small> with " + matSrc.getTypeName() + "</small>");
        }
      }
    }
    sb.append("</td>");

    // column 4: column count
    sb.append("<td>");
    sb.append(table.getColumns().size());
    sb.append("</td>");

    // column 5: index count
    sb.append("<td>");
    sb.append(table.getIndexes().size());
    sb.append("</td>");

    // column 6: has pkey
    sb.append("<td>");
    boolean found = false;
    for (Constraint constraint : table.getConstraints()) {
      if (ConstraintType.get(constraint.getType()) == ConstraintType.PRIMARY_KEY) {
        found = true;
        break;
      }
    }
    if (found) {
      tag(sb, "info", "Has-PKey");
    } else {
      tag(sb, null, "No-PKey");
    }
    sb.append("</td>");

    // column 6: has tuple limit
    sb.append("<td>");
    if (table.getTuplelimit() != Integer.MAX_VALUE) {
      tag(sb, "info", String.valueOf(table.getTuplelimit()));
    } else {
      tag(sb, null, "No-limit");
    }
    sb.append("</td>");

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

    // BUILD THE DROPDOWN FOR THE DDL / INDEXES DETAIL

    sb.append(
        "<tr class='tablesorter-childRow'><td class='invert' colspan='7' id='s-"
            + table.getTypeName().toLowerCase()
            + "--dropdown'>\n");

    TableAnnotation annotation = (TableAnnotation) table.getAnnotation();
    if (annotation != null) {
      // output the DDL
      if (annotation.ddl == null) {
        sb.append("<p>MISSING DDL</p>\n");
      } else {
        String ddl = annotation.ddl;
        sb.append("<p><pre>" + ddl + "</pre></p>\n");
      }

      // make sure procs appear in only one category
      annotation.proceduresThatReadThis.removeAll(annotation.proceduresThatUpdateThis);

      if (annotation.proceduresThatReadThis.size() > 0) {
        sb.append("<p>Read-only by procedures: ");
        List<String> procs = new ArrayList<String>();
        for (Procedure proc : annotation.proceduresThatReadThis) {
          procs.add("<a href='#p-" + proc.getTypeName() + "'>" + proc.getTypeName() + "</a>");
        }
        sb.append(StringUtils.join(procs, ", "));
        sb.append("</p>");
      }
      if (annotation.proceduresThatUpdateThis.size() > 0) {
        sb.append("<p>Read/Write by procedures: ");
        List<String> procs = new ArrayList<String>();
        for (Procedure proc : annotation.proceduresThatUpdateThis) {
          procs.add("<a href='#p-" + proc.getTypeName() + "'>" + proc.getTypeName() + "</a>");
        }
        sb.append(StringUtils.join(procs, ", "));
        sb.append("</p>");
      }
    }

    if (table.getIndexes().size() > 0) {
      sb.append(generateIndexesTable(table));
    } else {
      sb.append("<p>No indexes defined on table.</p>\n");
    }

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

    return sb.toString();
  }
Example #2
0
  private CompiledPlan compileFromXML(VoltXMLElement xmlSQL, String[] paramValues) {
    // Get a parsed statement from the xml
    // The callers of compilePlan are ready to catch any exceptions thrown here.
    AbstractParsedStmt parsedStmt =
        AbstractParsedStmt.parse(m_sql, xmlSQL, paramValues, m_db, m_joinOrder);
    if (parsedStmt == null) {
      m_recentErrorMsg = "Failed to parse SQL statement: " + getOriginalSql();
      return null;
    }

    if (m_isUpsert) {
      // no insert/upsert with joins
      if (parsedStmt.m_tableList.size() != 1) {
        m_recentErrorMsg = "UPSERT is support only with one single table: " + getOriginalSql();
        return null;
      }

      Table tb = parsedStmt.m_tableList.get(0);
      Constraint pkey = null;
      for (Constraint ct : tb.getConstraints()) {
        if (ct.getType() == ConstraintType.PRIMARY_KEY.getValue()) {
          pkey = ct;
          break;
        }
      }

      if (pkey == null) {
        m_recentErrorMsg = "Unsupported UPSERT table without primary key: " + getOriginalSql();
        return null;
      }
    }

    m_planSelector.outputParsedStatement(parsedStmt);

    // Init Assembler. Each plan assembler requires a new instance of the PlanSelector
    // to keep track of the best plan
    PlanAssembler assembler =
        new PlanAssembler(m_cluster, m_db, m_partitioning, (PlanSelector) m_planSelector.clone());
    // find the plan with minimal cost
    CompiledPlan bestPlan = assembler.getBestCostPlan(parsedStmt);

    // This processing of bestPlan outside/after getBestCostPlan
    // allows getBestCostPlan to be called both here and
    // in PlanAssembler.getNextUnion on each branch of a union.

    // make sure we got a winner
    if (bestPlan == null) {
      if (m_debuggingStaticModeToRetryOnError) {
        assembler.getBestCostPlan(parsedStmt);
      }
      m_recentErrorMsg = assembler.getErrorMessage();
      if (m_recentErrorMsg == null) {
        m_recentErrorMsg = "Unable to plan for statement. Error unknown.";
      }
      return null;
    }

    if (bestPlan.isReadOnly()) {
      SendPlanNode sendNode = new SendPlanNode();
      // connect the nodes to build the graph
      sendNode.addAndLinkChild(bestPlan.rootPlanGraph);
      // this plan is final, generate schema and resolve all the column index references
      bestPlan.rootPlanGraph = sendNode;
    }

    // Execute the generateOutputSchema and resolveColumnIndexes once for the best plan
    bestPlan.rootPlanGraph.generateOutputSchema(m_db);
    bestPlan.rootPlanGraph.resolveColumnIndexes();

    if (parsedStmt instanceof ParsedSelectStmt) {
      List<SchemaColumn> columns = bestPlan.rootPlanGraph.getOutputSchema().getColumns();
      ((ParsedSelectStmt) parsedStmt).checkPlanColumnMatch(columns);
    }

    // Output the best plan debug info
    assembler.finalizeBestCostPlan();

    // reset all the plan node ids for a given plan
    // this makes the ids deterministic
    bestPlan.resetPlanNodeIds(1);

    // split up the plan everywhere we see send/recieve into multiple plan fragments
    List<AbstractPlanNode> receives =
        bestPlan.rootPlanGraph.findAllNodesOfClass(AbstractReceivePlanNode.class);
    if (receives.size() > 1) {
      // Have too many receive node for two fragment plan limit
      m_recentErrorMsg =
          "This join of multiple partitioned tables is too complex. "
              + "Consider simplifying its subqueries: "
              + getOriginalSql();
      return null;
    }

    /*/ enable for debug ...
    if (receives.size() > 1) {
        System.out.println(plan.rootPlanGraph.toExplainPlanString());
    }
    // ... enable for debug */
    if (receives.size() == 1) {
      AbstractReceivePlanNode recvNode = (AbstractReceivePlanNode) receives.get(0);
      fragmentize(bestPlan, recvNode);
    }

    return bestPlan;
  }