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