// Create the canonical plan ...
long start = System.nanoTime();
PlanNode plan = planner.createPlan(context, query);
long duration = Math.abs(System.nanoTime() - start);
Statistics stats = new Statistics(duration);
final String workspaceName = context.getWorkspaceNames().iterator().next();
if (trace) {
LOGGER.trace("Computed canonical query plan for query {0}: {1}", context.id(), plan);
}
checkCancelled(context);
Columns resultColumns = null;
if (!context.getProblems().hasErrors()) {
// Optimize the plan ...
start = System.nanoTime();
PlanNode optimizedPlan = optimizer.optimize(context, plan);
duration = Math.abs(System.nanoTime() - start);
stats = stats.withOptimizationTime(duration);
if (trace) {
LOGGER.trace("Computed optimized query plan for query {0}:\n{1}", context.id(), optimizedPlan);
}
// Find the query result columns ...
start = System.nanoTime();
// Determine the Columns object for specific nodes in the plan, and store them in the context ...
optimizedPlan.apply(Traversal.POST_ORDER, new PlanNode.Operation() {
@Override
public void apply( PlanNode node ) {
Columns columns = null;
switch (node.getType()) {
case PROJECT:
case SOURCE:
columns = determineProjectedColumns(node, context);
assert columns != null;
break;
case JOIN:
Columns leftColumns = context.columnsFor(node.getFirstChild());
Columns rightColumns = context.columnsFor(node.getLastChild());
columns = leftColumns.with(rightColumns);
assert columns != null;
break;
case DEPENDENT_QUERY:
columns = context.columnsFor(node.getLastChild());
assert columns != null;
break;
case SET_OPERATION:
leftColumns = context.columnsFor(node.getFirstChild());
rightColumns = context.columnsFor(node.getLastChild());
if (checkUnionCompatible(leftColumns, rightColumns, context, query)) {
columns = leftColumns;
assert columns != null;
}
break;
case INDEX:
// do nothing with indexes ...
break;
default:
assert node.getChildCount() == 1;
columns = context.columnsFor(node.getFirstChild());
assert columns != null;
break;
}
if (columns != null) {
context.addColumnsFor(node, columns);
}
}
});
Problems problems = context.getProblems();
if (problems.hasErrors()) {
throw new RepositoryException(JcrI18n.problemsWithQuery.text(query, problems.toString()));
} else if (LOGGER.isDebugEnabled() && problems.hasWarnings()) {
LOGGER.debug("There are several warnings with this query: {0}\n{1}", query, problems.toString());
}
resultColumns = context.columnsFor(optimizedPlan);
assert resultColumns != null;
duration = Math.abs(System.nanoTime() - start);
stats = stats.withResultsFormulationTime(duration);
if (trace) {
LOGGER.trace("Computed output columns for query {0}: {1}", context.id(), resultColumns);
}
if (!context.getProblems().hasErrors()) {
checkCancelled(context);
// Execute the plan ...
try {
start = System.nanoTime();
if (trace) {
LOGGER.trace("Start executing query {0}", context.id());
}
QueryResults results = executeOptimizedQuery(context, query, stats, optimizedPlan);
if (trace) {
LOGGER.trace("Stopped executing query {0}: {1}", context.id(), stats);
}
return results;
} finally {
duration = Math.abs(System.nanoTime() - start);
stats = stats.withExecutionTime(duration);
}
}
}
// Check whether the query was cancelled during execution ...
checkCancelled(context);