Search in sources :

Example 1 with Statement

use of org.voltdb.catalog.Statement in project voltdb by VoltDB.

the class ReportMaker method generateSchemaRow.

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 Streams");
        } 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());
    // computing unused indexes
    int unusedIndexes = 0;
    for (Index index : table.getIndexes()) {
        IndexAnnotation indexAnnotation = (IndexAnnotation) index.getAnnotation();
        if (indexAnnotation == null) {
            unusedIndexes++;
        }
    }
    if (unusedIndexes != 0) {
        sb.append(" (" + unusedIndexes + " unused)");
    }
    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()));
        if (CatalogUtil.getLimitPartitionRowsDeleteStmt(table) != null) {
            sb.append("<small>enforced by DELETE statement</small>");
        }
    } 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 = escapeHtml4(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>");
        }
    }
    // LIMIT PARTITION ROW statement may also use the index in this table, prepare the information for report
    if (!table.getTuplelimitdeletestmt().isEmpty()) {
        assert (table.getTuplelimitdeletestmt().size() == 1);
        Statement stmt = table.getTuplelimitdeletestmt().iterator().next();
        for (String tableDotIndexPair : stmt.getIndexesused().split(",")) {
            if (tableDotIndexPair.length() == 0) {
                continue;
            }
            String[] parts = tableDotIndexPair.split("\\.", 2);
            assert (parts.length == 2);
            if (parts.length != 2) {
                continue;
            }
            String tableName = parts[0];
            String indexName = parts[1];
            if (!table.getTypeName().equals(tableName)) {
                continue;
            }
            Index i = table.getIndexes().get(indexName);
            assert (i != null);
            IndexAnnotation ia = (IndexAnnotation) i.getAnnotation();
            if (ia == null) {
                ia = new IndexAnnotation();
                i.setAnnotation(ia);
            }
            ia.statementsThatUseThis.add(stmt);
        }
    }
    if (table.getIndexes().size() > 0) {
        sb.append(generateIndexesTable(table));
    } else {
        sb.append("<p>No indexes defined on table.</p>\n");
    }
    // Generate explainview report.
    if (table.getMaterializer() != null) {
        sb.append(generateExplainViewTable(table));
    }
    sb.append("</td></tr>\n");
    return sb.toString();
}
Also used : Table(org.voltdb.catalog.Table) Constraint(org.voltdb.catalog.Constraint) Statement(org.voltdb.catalog.Statement) ArrayList(java.util.ArrayList) Index(org.voltdb.catalog.Index) Constraint(org.voltdb.catalog.Constraint) Column(org.voltdb.catalog.Column) Procedure(org.voltdb.catalog.Procedure)

Example 2 with Statement

use of org.voltdb.catalog.Statement in project voltdb by VoltDB.

the class LoadSinglepartitionTable method run.

/**
     * These parameters, with the exception of ctx, map to user provided values.
     *
     * @param ctx Internal API provided to all system procedures.
     * @param partitionParam Partitioning parameter used to match invocation to partition.
     * @param tableName Name of persistent, parititoned table receiving data.
     * @param table A VoltTable with schema matching the target table containing data to load.
     *              It's assumed that each row in this table partitions to the same partition
     *              as the other rows, and to the same partition as the partition parameter.
     * @param upsertMode True if using upsert instead of insert. If using insert, this proc
     *              will fail if there are any uniqueness constraints violated.
     * @return The number of rows modified. This will be inserts in insert mode, but in upsert
     *              mode, this will be the sum of inserts and updates.
     * @throws VoltAbortException on any failure, but the most common failures are non-matching
     *              partitioning or unique constraint violations.
     */
public long run(SystemProcedureExecutionContext ctx, byte[] partitionParam, String tableName, byte upsertMode, VoltTable table) throws VoltAbortException {
    // if tableName is replicated, fail.
    // otherwise, create a VoltTable for each partition and
    // split up the incoming table .. then send those partial
    // tables to the appropriate sites.
    // Get the metadata object for the table in question from the global metadata/config
    // store, the Catalog.
    Table catTable = ctx.getDatabase().getTables().getIgnoreCase(tableName);
    if (catTable == null) {
        throw new VoltAbortException("Table not present in catalog.");
    }
    // if tableName is replicated, fail.
    if (catTable.getIsreplicated()) {
        throw new VoltAbortException(String.format("LoadSinglepartitionTable incompatible with replicated table %s.", tableName));
    }
    // convert from 8bit signed integer (byte) to boolean
    boolean isUpsert = (upsertMode != 0);
    // upsert requires a primary key on the table to work
    if (isUpsert) {
        boolean hasPkey = false;
        for (Constraint c : catTable.getConstraints()) {
            if (c.getType() == ConstraintType.PRIMARY_KEY.getValue()) {
                hasPkey = true;
                break;
            }
        }
        if (!hasPkey) {
            throw new VoltAbortException(String.format("The --update argument cannot be used for LoadingSinglePartionTable because the table %s does not have a primary key. " + "Either remove the --update argument or add a primary key to the table.", tableName));
        }
    }
    // action should be either "insert" or "upsert"
    final String action = (isUpsert ? "upsert" : "insert");
    // fix any case problems
    tableName = catTable.getTypeName();
    // check that the schema of the input matches
    int columnCount = table.getColumnCount();
    //////////////////////////////////////////////////////////////////////
    // Find the insert/upsert statement for this table
    // This is actually the big trick this procedure does.
    // It borrows the insert plan from the auto-generated insert procedure
    // named "TABLENAME.insert" or "TABLENAME.upsert".
    // We don't like it when users do this stuff, but it is safe in this
    // case.
    //
    // Related code to read is org.voltdb.DefaultProcedureManager, which
    // manages all of the default (CRUD) procedures created lazily for
    // each table in the database, including the plans used here.
    //
    String crudProcName = String.format("%s.%s", tableName, action);
    Procedure p = ctx.ensureDefaultProcLoaded(crudProcName);
    if (p == null) {
        throw new VoltAbortException(String.format("Unable to locate auto-generated CRUD %s statement for table %s", action, tableName));
    }
    // statements of all single-statement procs are named "sql"
    Statement catStmt = p.getStatements().get(VoltDB.ANON_STMT_NAME);
    if (catStmt == null) {
        throw new VoltAbortException(String.format("Unable to find SQL statement for found table %s: BAD", tableName));
    }
    // Create a SQLStmt instance on the fly
    // This unusual to do, as they are typically required to be final instance variables.
    // This only works because the SQL text and plan is identical from the borrowed procedure.
    SQLStmt stmt = new SQLStmt(catStmt.getSqltext());
    m_runner.initSQLStmt(stmt, catStmt);
    long queued = 0;
    long executed = 0;
    // make sure at the start of the table
    table.resetRowPosition();
    // iterate over the rows queueing a sql statement for each row to insert
    for (int i = 0; table.advanceRow(); ++i) {
        Object[] params = new Object[columnCount];
        // get the parameters from the volt table
        for (int col = 0; col < columnCount; ++col) {
            params[col] = table.get(col, table.getColumnType(col));
        }
        // queue an insert and count it
        voltQueueSQL(stmt, params);
        ++queued;
        // 100 is an arbitrary number
        if ((i % 100) == 0) {
            executed += executeSQL();
        }
    }
    // execute any leftover batched statements
    if (queued > executed) {
        executed += executeSQL();
    }
    return executed;
}
Also used : SQLStmt(org.voltdb.SQLStmt) Table(org.voltdb.catalog.Table) VoltTable(org.voltdb.VoltTable) Constraint(org.voltdb.catalog.Constraint) Statement(org.voltdb.catalog.Statement) VoltSystemProcedure(org.voltdb.VoltSystemProcedure) Procedure(org.voltdb.catalog.Procedure) Constraint(org.voltdb.catalog.Constraint)

Example 3 with Statement

use of org.voltdb.catalog.Statement in project voltdb by VoltDB.

the class RealVoltDB method printDiagnosticInformation.

public static void printDiagnosticInformation(CatalogContext context, String procName, LoadedProcedureSet procSet) {
    StringBuilder sb = new StringBuilder();
    final CatalogMap<Procedure> catalogProcedures = context.database.getProcedures();
    PureJavaCrc32C crc = new PureJavaCrc32C();
    sb.append("Statements within " + procName + ": ").append("\n");
    for (final Procedure proc : catalogProcedures) {
        if (proc.getTypeName().equals(procName)) {
            for (Statement stmt : proc.getStatements()) {
                // compute hash for determinism check
                crc.reset();
                String sqlText = stmt.getSqltext();
                crc.update(sqlText.getBytes(Constants.UTF8ENCODING));
                int hash = (int) crc.getValue();
                sb.append("Statement Hash: ").append(hash);
                sb.append(", Statement SQL: ").append(sqlText);
                for (PlanFragment frag : stmt.getFragments()) {
                    byte[] planHash = Encoder.hexDecode(frag.getPlanhash());
                    long planId = ActivePlanRepository.getFragmentIdForPlanHash(planHash);
                    String stmtText = ActivePlanRepository.getStmtTextForPlanHash(planHash);
                    byte[] jsonPlan = ActivePlanRepository.planForFragmentId(planId);
                    sb.append(", Plan Fragment Id:").append(planId);
                    sb.append(", Plan Stmt Text:").append(stmtText);
                    sb.append(", Json Plan:").append(new String(jsonPlan));
                }
                sb.append("\n");
            }
        }
    }
    sb.append("Default CRUD Procedures: ").append("\n");
    for (Entry<String, Procedure> pair : context.m_defaultProcs.m_defaultProcMap.entrySet()) {
        crc.reset();
        String sqlText = DefaultProcedureManager.sqlForDefaultProc(pair.getValue());
        crc.update(sqlText.getBytes(Constants.UTF8ENCODING));
        int hash = (int) crc.getValue();
        sb.append("Statement Hash: ").append(hash);
        sb.append(", Statement SQL: ").append(sqlText);
        ProcedureRunner runner = procSet.getProcByName(pair.getValue().getTypeName());
        for (Statement stmt : runner.getCatalogProcedure().getStatements()) {
            for (PlanFragment frag : stmt.getFragments()) {
                byte[] planHash = Encoder.hexDecode(frag.getPlanhash());
                long planId = ActivePlanRepository.getFragmentIdForPlanHash(planHash);
                String stmtText = ActivePlanRepository.getStmtTextForPlanHash(planHash);
                byte[] jsonPlan = ActivePlanRepository.planForFragmentId(planId);
                sb.append(", Plan Fragment Id:").append(planId);
                sb.append(", Plan Stmt Text:").append(stmtText);
                sb.append(", Json Plan:").append(new String(jsonPlan));
            }
        }
        sb.append("\n");
    }
    hostLog.error(sb.toString());
}
Also used : PureJavaCrc32C(org.apache.hadoop_voltpatches.util.PureJavaCrc32C) Statement(org.voltdb.catalog.Statement) Procedure(org.voltdb.catalog.Procedure) PlanFragment(org.voltdb.catalog.PlanFragment)

Example 4 with Statement

use of org.voltdb.catalog.Statement in project voltdb by VoltDB.

the class VoltCompiler method compileProcedures.

/**
     * @param db the database entry in the catalog
     * @param hsql an interface to the hsql frontend, initialized and potentially reused by the caller.
     * @param classDependencies
     * @param voltDdlTracker non-standard VoltDB schema annotations
     * @param whichProcs indicates which ddl-defined procedures to load: none, single-statement, or all
     * @throws VoltCompilerException
     */
private void compileProcedures(Database db, HSQLInterface hsql, Collection<ProcedureDescriptor> allProcs, Collection<Class<?>> classDependencies, DdlProceduresToLoad whichProcs, CatalogMap<Procedure> prevProcsIfAny, InMemoryJarfile jarOutput) throws VoltCompilerException {
    // build a cache of previous SQL stmts
    m_previousCatalogStmts.clear();
    if (prevProcsIfAny != null) {
        for (Procedure prevProc : prevProcsIfAny) {
            for (Statement prevStmt : prevProc.getStatements()) {
                addStatementToCache(prevStmt);
            }
        }
    }
    // dependencies for its "dry run" on an unchanged application ddl file.
    if (whichProcs == DdlProceduresToLoad.ALL_DDL_PROCEDURES) {
        // Add all the class dependencies to the output jar
        for (final Class<?> classDependency : classDependencies) {
            addClassToJar(jarOutput, classDependency);
        }
    }
    final List<ProcedureDescriptor> procedures = new ArrayList<>();
    procedures.addAll(allProcs);
    // Actually parse and handle all the Procedures
    for (final ProcedureDescriptor procedureDescriptor : procedures) {
        final String procedureName = procedureDescriptor.m_className;
        if (procedureDescriptor.m_singleStmt == null) {
            m_currentFilename = procedureName.substring(procedureName.lastIndexOf('.') + 1);
            m_currentFilename += ".class";
        } else if (whichProcs == DdlProceduresToLoad.ONLY_SINGLE_STATEMENT_PROCEDURES) {
            // for all the single-statement procedures of an unchanged application ddl file.
            continue;
        } else {
            m_currentFilename = procedureName;
        }
        ProcedureCompiler.compile(this, hsql, m_estimates, db, procedureDescriptor, jarOutput);
    }
    // done handling files
    m_currentFilename = NO_FILENAME;
    // allow gc to reclaim any cache memory here
    m_previousCatalogStmts.clear();
}
Also used : Statement(org.voltdb.catalog.Statement) ArrayList(java.util.ArrayList) Procedure(org.voltdb.catalog.Procedure)

Example 5 with Statement

use of org.voltdb.catalog.Statement in project voltdb by VoltDB.

the class VoltCompiler method getCachedStatement.

/** Look for a match from the previous catalog that matches the key + sql */
Statement getCachedStatement(String keyPrefix, String sql) {
    String key = keyPrefix + sql;
    Statement candidate = m_previousCatalogStmts.get(key);
    if (candidate == null) {
        ++m_stmtCacheMisses;
        return null;
    }
    // check that no underlying tables have been modified since the proc had been compiled
    String[] tablesTouched = candidate.getTablesread().split(",");
    for (String tableName : tablesTouched) {
        if (m_dirtyTables.contains(tableName.toLowerCase())) {
            ++m_stmtCacheMisses;
            return null;
        }
    }
    tablesTouched = candidate.getTablesupdated().split(",");
    for (String tableName : tablesTouched) {
        if (m_dirtyTables.contains(tableName.toLowerCase())) {
            ++m_stmtCacheMisses;
            return null;
        }
    }
    ++m_stmtCacheHits;
    //printStmtCacheStats();
    return candidate;
}
Also used : Statement(org.voltdb.catalog.Statement)

Aggregations

Statement (org.voltdb.catalog.Statement)28 Procedure (org.voltdb.catalog.Procedure)12 ArrayList (java.util.ArrayList)8 Constraint (org.voltdb.catalog.Constraint)7 PlanFragment (org.voltdb.catalog.PlanFragment)7 ProcParameter (org.voltdb.catalog.ProcParameter)5 Table (org.voltdb.catalog.Table)5 VoltTable (org.voltdb.VoltTable)4 StmtParameter (org.voltdb.catalog.StmtParameter)4 VoltCompilerException (org.voltdb.compiler.VoltCompiler.VoltCompilerException)4 ParameterValueExpression (org.voltdb.expressions.ParameterValueExpression)4 QueryType (org.voltdb.types.QueryType)4 VoltXMLElement (org.hsqldb_voltpatches.VoltXMLElement)3 ParameterSet (org.voltdb.ParameterSet)3 SQLStmt (org.voltdb.SQLStmt)3 Database (org.voltdb.catalog.Database)3 GroupRef (org.voltdb.catalog.GroupRef)3 Index (org.voltdb.catalog.Index)3 StatementPartitioning (org.voltdb.planner.StatementPartitioning)3 Method (java.lang.reflect.Method)2