protected VoltTable[] executeQueriesInABatch(List<QueuedSQL> batch, boolean isFinalSQL) {
    final int batchSize = batch.size();

    VoltTable[] results = null;

    if (batchSize == 0) {
      return new VoltTable[] {};
    }

    // IF THIS IS HSQL, RUN THE QUERIES DIRECTLY IN HSQL
    if (getHsqlBackendIfExists() != null) {
      results = new VoltTable[batchSize];
      int i = 0;
      for (QueuedSQL qs : batch) {
        List<StmtParameter> sparams;
        if (qs.stmt.catStmt != null) {
          CatalogMap<StmtParameter> sparamsMap = qs.stmt.catStmt.getParameters();
          sparams = CatalogUtil.getSortedCatalogItems(sparamsMap, "index");
        } else {
          assert (qs.stmt.plan != null);
          // TODO: For now extracted ad hoc SQL parameters are discarded
          qs.params = new ParameterSet();
          sparams = new ArrayList<StmtParameter>();
        }
        results[i++] =
            getHsqlBackendIfExists().runSQLWithSubstitutions(qs.stmt, qs.params, sparams);
      }
    } else if (m_catProc.getSinglepartition()) {
      results = fastPath(batch);
    } else {
      results = slowPath(batch, isFinalSQL);
    }

    // check expectations
    int i = 0;
    for (QueuedSQL qs : batch) {
      Expectation.check(m_procedureName, qs.stmt.sqlText, i, qs.expectation, results[i]);
      i++;
    }

    // clear the queued sql list for the next call
    batch.clear();

    return results;
  }
  /** Determine which parameter is the partition indicator */
  static void parsePartitionInfo(
      VoltCompiler compiler, Database db, Procedure procedure, String info)
      throws VoltCompilerException {

    assert (procedure.getSinglepartition() == true);

    // check this isn't empty
    if (info.length() == 0) {
      String msg =
          "Missing or Truncated PartitionInfo in attribute for procedure: "
              + procedure.getClassname();
      throw compiler.new VoltCompilerException(msg);
    }

    // split on the colon
    String[] parts = info.split(":");

    // if the colon doesn't split well, we have a problem
    if (parts.length != 2) {
      String msg =
          "Possibly invalid PartitionInfo in attribute for procedure: " + procedure.getClassname();
      throw compiler.new VoltCompilerException(msg);
    }

    // relabel the parts for code readability
    String columnInfo = parts[0].trim();
    int paramIndex = Integer.parseInt(parts[1].trim());

    int paramCount = procedure.getParameters().size();
    if ((paramIndex < 0) || (paramIndex >= paramCount)) {
      String msg =
          "PartitionInfo specifies invalid parameter index for procedure: "
              + procedure.getClassname();
      throw compiler.new VoltCompilerException(msg);
    }

    // locate the parameter
    procedure.setPartitionparameter(paramIndex);

    // split the columninfo
    parts = columnInfo.split("\\.");
    if (parts.length != 2) {
      String msg =
          "Possibly invalid PartitionInfo in attribute for procedure: " + procedure.getClassname();
      throw compiler.new VoltCompilerException(msg);
    }

    // relabel the parts for code readability
    String tableName = parts[0].trim();
    String columnName = parts[1].trim();

    // locate the partition column
    CatalogMap<Table> tables = db.getTables();
    for (Table table : tables) {
      if (table.getTypeName().equalsIgnoreCase(tableName)) {
        CatalogMap<Column> columns = table.getColumns();
        Column partitionColumn = table.getPartitioncolumn();
        if (partitionColumn == null) {
          String msg =
              String.format(
                  "PartitionInfo for procedure %s references table %s which has no partition column (may be replicated).",
                  procedure.getClassname(), table.getTypeName());
          throw compiler.new VoltCompilerException(msg);
        }

        for (Column column : columns) {
          if (column.getTypeName().equalsIgnoreCase(columnName)) {
            if (partitionColumn.getTypeName().equals(column.getTypeName())) {
              procedure.setPartitioncolumn(column);
              procedure.setPartitiontable(table);
              return;
            } else {
              String msg =
                  "PartitionInfo for procedure "
                      + procedure.getClassname()
                      + " refers to a column in schema which is not a partition key.";
              throw compiler.new VoltCompilerException(msg);
            }
          }
        }
      }
    }

    String msg =
        "PartitionInfo for procedure "
            + procedure.getClassname()
            + " refers to a column in schema which can't be found.";
    throw compiler.new VoltCompilerException(msg);
  }
Exemple #3
0
  /**
   * Get some embeddable HTML of some generic catalog/application stats that is drawn on the first
   * page of the report.
   */
  static String getStatsHTML(Database db, ArrayList<Feedback> warnings) {
    StringBuilder sb = new StringBuilder();
    sb.append("<table class='table table-condensed'>\n");

    // count things
    int indexes = 0, views = 0, statements = 0;
    int partitionedTables = 0, replicatedTables = 0;
    int partitionedProcs = 0, replicatedProcs = 0;
    int readProcs = 0, writeProcs = 0;
    for (Table t : db.getTables()) {
      if (t.getMaterializer() != null) {
        views++;
      } else {
        if (t.getIsreplicated()) {
          replicatedTables++;
        } else {
          partitionedTables++;
        }
      }

      indexes += t.getIndexes().size();
    }
    for (Procedure p : db.getProcedures()) {
      // skip auto-generated crud procs
      if (p.getDefaultproc()) {
        continue;
      }

      if (p.getSinglepartition()) {
        partitionedProcs++;
      } else {
        replicatedProcs++;
      }

      if (p.getReadonly()) {
        readProcs++;
      } else {
        writeProcs++;
      }

      statements += p.getStatements().size();
    }

    // version
    sb.append("<tr><td>Compiled by VoltDB Version</td><td>");
    sb.append(VoltDB.instance().getVersionString()).append("</td></tr>\n");

    // timestamp
    sb.append("<tr><td>Compiled on</td><td>");
    SimpleDateFormat sdf = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss z");
    sb.append(sdf.format(m_timestamp)).append("</td></tr>\n");

    // tables
    sb.append("<tr><td>Table Count</td><td>");
    sb.append(
        String.format(
            "%d (%d partitioned / %d replicated)",
            partitionedTables + replicatedTables, partitionedTables, replicatedTables));
    sb.append("</td></tr>\n");

    // views
    sb.append("<tr><td>Materialized View Count</td><td>").append(views).append("</td></tr>\n");

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

    // procedures
    sb.append("<tr><td>Procedure Count</td><td>");
    sb.append(
        String.format(
            "%d (%d partitioned / %d replicated) (%d read-only / %d read-write)",
            partitionedProcs + replicatedProcs,
            partitionedProcs,
            replicatedProcs,
            readProcs,
            writeProcs));
    sb.append("</td></tr>\n");

    // statements
    sb.append("<tr><td>SQL Statement Count</td><td>").append(statements).append("</td></tr>\n");
    sb.append("</table>\n\n");

    // warnings, add warning section if any
    if (warnings.size() > 0) {
      sb.append("<h4>Warnings</h4>");
      sb.append("<table class='table table-condensed'>\n");
      for (Feedback warning : warnings) {
        String procName = warning.getFileName().replace(".class", "");
        String nameLink = "";
        // not a warning during compiling procedures, must from the schema
        if (procName.compareToIgnoreCase("null") == 0) {
          String schemaName = "";
          String warningMsg = warning.getMessage().toLowerCase();
          if (warningMsg.contains("table ")) {
            int begin = warningMsg.indexOf("table ") + 6;
            int end = (warningMsg.substring(begin)).indexOf(" ");
            schemaName = warningMsg.substring(begin, begin + end);
          }
          nameLink = "<a href='#s-" + schemaName + "'>" + schemaName.toUpperCase() + "</a>";
        } else {
          nameLink = "<a href='#p-" + procName.toLowerCase() + "'>" + procName + "</a>";
        }
        sb.append("<tr><td>")
            .append(nameLink)
            .append("</td><td>")
            .append(warning.getMessage())
            .append("</td></tr>\n");
      }
      sb.append("").append("</table>\n").append("</td></tr>\n");
    }

    return sb.toString();
  }
  public void voltQueueSQL(final String sql, Object... args) {
    if (sql == null || sql.isEmpty()) {
      throw new IllegalArgumentException("SQL statement '" + sql + "' is null or the empty string");
    }

    try {
      AdHocPlannedStmtBatch paw =
          m_csp
              .plan(sql, !m_catProc.getSinglepartition(), ProcedureInvocationType.ORIGINAL, 0, 0)
              .get();
      if (paw.errorMsg != null) {
        throw new VoltAbortException("Failed to plan sql '" + sql + "' error: " + paw.errorMsg);
      }

      if (m_catProc.getReadonly() && !paw.isReadOnly()) {
        throw new VoltAbortException(
            "Attempted to queue DML adhoc sql '" + sql + "' from read only procedure");
      }

      assert (1 == paw.plannedStatements.size());

      QueuedSQL queuedSQL = new QueuedSQL();
      AdHocPlannedStatement plannedStatement = paw.plannedStatements.get(0);
      queuedSQL.stmt =
          SQLStmtAdHocHelper.createWithPlan(
              plannedStatement.sql,
              plannedStatement.core.aggregatorFragment,
              plannedStatement.core.collectorFragment,
              plannedStatement.core.isReplicatedTableDML,
              plannedStatement.core.readOnly,
              plannedStatement.core.parameterTypes);
      if (plannedStatement.extractedParamValues.size() == 0) {
        // case handles if there were parameters OR
        // if there were no constants to pull out
        queuedSQL.params = getCleanParams(queuedSQL.stmt, args);
      } else {
        if (args.length > 0) {
          throw new ExpectedProcedureException(
              "Number of arguments provided was "
                  + args.length
                  + " where 0 were expected for statement "
                  + sql);
        }
        Object[] extractedParams = plannedStatement.extractedParamValues.toArray();
        if (extractedParams.length != queuedSQL.stmt.numStatementParamJavaTypes) {
          String msg =
              String.format("Wrong number of extracted param for parameterized statement: %s", sql);
          throw new VoltAbortException(msg);
        }
        queuedSQL.params = getCleanParams(queuedSQL.stmt, extractedParams);
      }

      updateCRC(queuedSQL);
      m_batch.add(queuedSQL);
    } catch (Exception e) {
      if (e instanceof ExecutionException) {
        throw new VoltAbortException(e.getCause());
      }
      if (e instanceof VoltAbortException) {
        throw (VoltAbortException) e;
      }
      throw new VoltAbortException(e);
    }
  }
Exemple #5
0
  static String generateProcedureRow(Procedure procedure) {
    StringBuilder sb = new StringBuilder();
    sb.append("<tr class='primaryrow'>");

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

    // column 2: parameter types
    sb.append("<td>");
    List<ProcParameter> params =
        CatalogUtil.getSortedCatalogItems(procedure.getParameters(), "index");
    List<String> paramTypes = new ArrayList<String>();
    for (ProcParameter param : params) {
      String paramType = VoltType.get((byte) param.getType()).name();
      if (param.getIsarray()) {
        paramType += "[]";
      }
      paramTypes.add(paramType);
    }
    if (paramTypes.size() == 0) {
      sb.append("<i>None</i>");
    }
    sb.append(StringUtils.join(paramTypes, ", "));
    sb.append("</td>");

    // column 3: partitioning
    sb.append("<td>");
    if (procedure.getSinglepartition()) {
      tag(sb, "success", "Single");
    } else {
      tag(sb, "warning", "Multi");
    }
    sb.append("</td>");

    // column 4: read/write
    sb.append("<td>");
    if (procedure.getReadonly()) {
      tag(sb, "success", "Read");
    } else {
      tag(sb, "warning", "Write");
    }
    sb.append("</td>");

    // column 5: access
    sb.append("<td>");
    List<String> groupNames = new ArrayList<String>();
    for (GroupRef groupRef : procedure.getAuthgroups()) {
      groupNames.add(groupRef.getGroup().getTypeName());
    }
    if (groupNames.size() == 0) {
      sb.append("<i>None</i>");
    }
    sb.append(StringUtils.join(groupNames, ", "));
    sb.append("</td>");

    // column 6: attributes
    sb.append("<td>");
    if (procedure.getHasjava()) {
      tag(sb, "info", "Java");
    } else {
      tag(sb, null, "Single-Stmt");
    }
    boolean isND = false;
    int scanCount = 0;
    for (Statement stmt : procedure.getStatements()) {
      scanCount += stmt.getSeqscancount();
      if (!stmt.getIscontentdeterministic() || !stmt.getIsorderdeterministic()) {
        isND = false;
      }
    }
    if (isND) {
      tag(sb, "inverse", "Determinism");
    }
    if (scanCount > 0) {
      tag(sb, "important", "Scans");
    }
    sb.append("</td>");

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

    // BUILD THE DROPDOWN FOR THE STATEMENT/DETAIL TABLE

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

    // output partitioning parameter info
    if (procedure.getSinglepartition()) {
      String pTable = procedure.getPartitioncolumn().getParent().getTypeName();
      String pColumn = procedure.getPartitioncolumn().getTypeName();
      int pIndex = procedure.getPartitionparameter();

      sb.append(
          String.format(
              "<p>Partitioned on parameter %d which maps to column %s"
                  + " of table <a class='invert' href='#s-%s'>%s</a>.</p>",
              pIndex, pColumn, pTable, pTable));
    }

    // output what schema this interacts with
    ProcedureAnnotation annotation = (ProcedureAnnotation) procedure.getAnnotation();
    if (annotation != null) {
      // make sure tables appear in only one category
      annotation.tablesRead.removeAll(annotation.tablesUpdated);

      if (annotation.tablesRead.size() > 0) {
        sb.append("<p>Read-only access to tables: ");
        List<String> tables = new ArrayList<String>();
        for (Table table : annotation.tablesRead) {
          tables.add("<a href='#s-" + table.getTypeName() + "'>" + table.getTypeName() + "</a>");
        }
        sb.append(StringUtils.join(tables, ", "));
        sb.append("</p>");
      }
      if (annotation.tablesUpdated.size() > 0) {
        sb.append("<p>Read/Write access to tables: ");
        List<String> tables = new ArrayList<String>();
        for (Table table : annotation.tablesUpdated) {
          tables.add("<a href='#s-" + table.getTypeName() + "'>" + table.getTypeName() + "</a>");
        }
        sb.append(StringUtils.join(tables, ", "));
        sb.append("</p>");
      }
      if (annotation.indexesUsed.size() > 0) {
        sb.append("<p>Uses indexes: ");
        List<String> indexes = new ArrayList<String>();
        for (Index index : annotation.indexesUsed) {
          Table table = (Table) index.getParent();
          indexes.add(
              "<a href='#s-"
                  + table.getTypeName()
                  + "-"
                  + index.getTypeName()
                  + "'>"
                  + index.getTypeName()
                  + "</a>");
        }
        sb.append(StringUtils.join(indexes, ", "));
        sb.append("</p>");
      }
    }

    sb.append(generateStatementsTable(procedure));

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

    return sb.toString();
  }