//LOG.fine("Compiling Statement: ");
//LOG.fine(stmt);
compiler.addInfo("Compiling Statement: " + stmt);
// determine the type of the query
QueryType qtype;
if (stmt.toLowerCase().startsWith("insert")) {
qtype = QueryType.INSERT;
catalogStmt.setReadonly(false);
}
else if (stmt.toLowerCase().startsWith("update")) {
qtype = QueryType.UPDATE;
catalogStmt.setReadonly(false);
}
else if (stmt.toLowerCase().startsWith("delete")) {
qtype = QueryType.DELETE;
catalogStmt.setReadonly(false);
}
else if (stmt.toLowerCase().startsWith("select")) {
qtype = QueryType.SELECT;
catalogStmt.setReadonly(true);
}
else {
throw compiler.new VoltCompilerException("Unparsable SQL statement.");
}
catalogStmt.setQuerytype(qtype.getValue());
// put the data in the catalog that we have
catalogStmt.setSqltext(stmt);
catalogStmt.setSinglepartition(singlePartition);
catalogStmt.setBatched(false);
catalogStmt.setParamnum(0);
catalogStmt.setHas_singlesited(false);
catalogStmt.setHas_multisited(false);
// PAVLO: Super Hack!
// Always compile the multi-partition and single-partition query plans!
// We don't need the multi-partition query plans for MapReduce transactions
Procedure catalog_proc = catalogStmt.getParent();
boolean isMapReduce = catalog_proc.getMapreduce();
CompiledPlan plan = null;
CompiledPlan last_plan = null;
PlanNodeList node_list = null;
QueryPlanner planner = new QueryPlanner(catalog.getClusters().get("cluster"), db, hsql, estimates, true, false);
Throwable first_exception = null;
for (boolean _singleSited : new boolean[]{ true, false }) {
if (_singleSited == false && isMapReduce) continue;
QueryType stmt_type = QueryType.get(catalogStmt.getQuerytype());
String msg = "Creating " + stmt_type.name() + " query plan for " + catalogStmt.fullName() + ": singleSited=" + _singleSited;
if (trace.val) LOG.trace(msg);
compiler.addInfo(msg);
catalogStmt.setSinglepartition(_singleSited);
String name = catalogStmt.getParent().getName() + "-" + catalogStmt.getName();
TrivialCostModel costModel = new TrivialCostModel();
try {
plan = planner.compilePlan(costModel, catalogStmt.getSqltext(),
catalogStmt.getName(), catalogStmt.getParent().getName(),
catalogStmt.getSinglepartition(), null);
} catch (Throwable e) {
LOG.error("Failed to plan for stmt: " + catalogStmt.fullName(), e);
if (first_exception == null) {
if (debug.val) LOG.warn("Ignoring first error for " + catalogStmt.getName() + " :: " + e.getMessage());
first_exception = e;
continue;
}
e.printStackTrace();
throw compiler.new VoltCompilerException("Failed to plan for stmt: " + catalogStmt.fullName());
}
if (plan == null) {
msg = "Failed to plan for stmt: " + catalogStmt.fullName();
String plannerMsg = planner.getErrorMessage();
if (plannerMsg == null) plannerMsg = "PlannerMessage was empty!";
// HACK: Ignore if they were trying to do a single-sited INSERT/UPDATE/DELETE
// on a replicated table
if (plannerMsg.contains("replicated table") && _singleSited) {
if (debug.val)
LOG.warn(String.format("Ignoring error for %s: %s", catalogStmt.fullName(), plannerMsg));
continue;
// HACK: If we get an unknown error message on an multi-sited INSERT/UPDATE/DELETE, assume
// that it's because we are trying to insert on a non-replicated table
} else if (!_singleSited && stmt_type == QueryType.INSERT && plannerMsg.contains("Error unknown")) {
if (debug.val)
LOG.warn(String.format("Ignoring multi-sited %s %s on non-replicated table: %s",
stmt_type.name(), catalogStmt.fullName(), plannerMsg));
continue;
} else if (planner.getError() != null) {
if (debug.val) LOG.error(msg);
throw compiler.new VoltCompilerException(msg, planner.getError());
// Otherwise, report the error