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