use of org.datanucleus.query.compiler.JDOQLParser in project datanucleus-core by datanucleus.
the class JDOQLCompiler method compile.
/**
* Method to compile the query, and return the compiled results.
* @param parameters the parameter map of values keyed by param name
* @param subqueryMap Map of subquery variables, keyed by the subquery name
* @return The compiled query
*/
public QueryCompilation compile(Map parameters, Map subqueryMap) {
parser = new JDOQLParser();
parser.setExplicitParameters(this.parameters != null);
if (options != null && options.containsKey(Query.EXTENSION_JDOQL_STRICT)) {
parser.setStrict(Boolean.parseBoolean((String) options.get(Query.EXTENSION_JDOQL_STRICT)));
}
symtbl = new SymbolTable();
symtbl.setSymbolResolver(this);
if (parentCompiler != null) {
symtbl.setParentSymbolTable(parentCompiler.symtbl);
}
if (subqueryMap != null && !subqueryMap.isEmpty()) {
// Load subqueries into symbol table so the compilation knows about them
Iterator<String> subqueryIter = subqueryMap.keySet().iterator();
while (subqueryIter.hasNext()) {
String subqueryName = subqueryIter.next();
Symbol sym = new PropertySymbol(subqueryName);
sym.setType(Symbol.VARIABLE);
symtbl.addSymbol(sym);
}
}
Expression[] exprFrom = compileFrom();
compileCandidatesParametersVariables(parameters);
Expression exprFilter = compileFilter();
Expression[] exprOrdering = compileOrdering();
Expression[] exprResult = compileResult();
Expression[] exprGrouping = compileGrouping();
Expression exprHaving = compileHaving();
Expression[] exprUpdate = compileUpdate();
// Impose checks from JDO spec
if (exprGrouping != null) {
// - an aggregate expression evaluated once per group.
if (exprResult != null) {
for (int i = 0; i < exprResult.length; i++) {
if (!isExpressionGroupingOrAggregate(exprResult[i], exprGrouping)) {
throw new NucleusUserException(Localiser.msg("021086", exprResult[i]));
}
}
}
// - an aggregate expression evaluated once per group.
if (exprOrdering != null) {
for (int i = 0; i < exprOrdering.length; i++) {
if (!isExpressionGroupingOrAggregate(exprOrdering[i], exprGrouping)) {
throw new NucleusUserException(Localiser.msg("021087", exprOrdering[i]));
}
}
}
}
if (exprHaving != null) {
// grouping expression.
if (!containsOnlyGroupingOrAggregates(exprHaving, exprGrouping)) {
throw new NucleusUserException(Localiser.msg("021088", exprHaving));
}
}
if (exprResult != null) {
for (int i = 0; i < exprResult.length; i++) {
if (exprResult[i] instanceof InvokeExpression) {
InvokeExpression invokeExpr = (InvokeExpression) exprResult[i];
if (isMethodNameAggregate(invokeExpr.getOperation())) {
// Make sure these have 1 argument
List<Expression> args = invokeExpr.getArguments();
if (args == null || args.size() != 1) {
throw new NucleusUserException(Localiser.msg("021089", invokeExpr.getOperation()));
}
}
}
}
}
QueryCompilation compilation = new QueryCompilation(candidateClass, candidateAlias, symtbl, exprResult, exprFrom, exprFilter, exprGrouping, exprHaving, exprOrdering, exprUpdate);
compilation.setQueryLanguage(getLanguage());
// Apply compilation optimisations
if (options != null) {
if (options.containsKey(PropertyNames.PROPERTY_QUERY_COMPILE_OPTIMISE_VAR_THIS)) {
Boolean val = (Boolean) options.get(PropertyNames.PROPERTY_QUERY_COMPILE_OPTIMISE_VAR_THIS);
if (val == Boolean.TRUE) {
// Perform "var == this" optimisation TODO Enable this using a query extension
CompilationOptimiser optimiser = new VarThisCompilationOptimiser(compilation, metaDataManager, clr);
optimiser.optimise();
}
}
// TODO Add handling of relation navigation implying "relation != null". See NavigationNullCompilationOptimiser for a start point
// i.e if we have "this.field1.field2 = val" this is equivalent to "this.field1 != null && this.field1.field2 = val"
}
return compilation;
}
Aggregations