/** * 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); } }
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(); }