use of org.datanucleus.store.query.Query in project datanucleus-core by datanucleus.
the class JavaQueryInMemoryEvaluator method execute.
/**
* Method to perform the evaluation, applying the query restrictions that are required.
* @param applyFilter Whether to apply any filter constraints on the results
* @param applyOrdering Whether to apply any order constraints on the results
* @param applyResult Whether to apply any result/grouping/having on the results
* @param applyResultClass Whether to apply any resultClass constraint on the results
* @param applyRange Whether to apply any range constraint on the results
* @return The results after evaluation.
*/
public Collection execute(boolean applyFilter, boolean applyOrdering, boolean applyResult, boolean applyResultClass, boolean applyRange) {
if (!applyFilter && !applyOrdering && !applyResult && !applyResultClass && !applyRange) {
// Nothing to evaluate in-memory
return candidates;
}
Collection executeCandidates = new ArrayList();
Expression[] result = compilation.getExprResult();
if (candidates != null) {
if (applyResult && result != null && result.length > 1) {
// Have result but not returning rows of candidate type so remove dupd candidates
Iterator candIter = candidates.iterator();
while (candIter.hasNext()) {
Object candidate = candIter.next();
if (!executeCandidates.contains(candidate)) {
executeCandidates.add(candidate);
}
}
} else {
executeCandidates.addAll(candidates);
}
}
// Really we should aim to have the following order of execution of the different components : FROM, WHERE, GROUP BY, HAVING, SELECT, ORDER BY
// TODO Retain variables across the different parts of the query. Currently evaluated in filter then forgotten
// TODO Where the subquery makes use of the parent query candidate, set the candidates for the subquery using that. This currently just passes the same parent candidates in!
String[] subqueryAliases = compilation.getSubqueryAliases();
if (subqueryAliases != null) {
for (int i = 0; i < subqueryAliases.length; i++) {
// Evaluate subquery first
Query subquery = query.getSubqueryForVariable(subqueryAliases[i]).getQuery();
QueryCompilation subqueryCompilation = compilation.getCompilationForSubquery(subqueryAliases[i]);
if (subqueryCompilation.getExprFrom() != null) {
// TODO Evaluate "from"
NucleusLogger.QUERY.warn("In-memory evaluation of subquery with 'from'=" + StringUtils.objectArrayToString(subqueryCompilation.getExprFrom()) + " but from clause evaluation not currently supported!");
}
Collection subqueryResult = evaluateSubquery(subquery, subqueryCompilation, executeCandidates, null);
if (QueryUtils.queryReturnsSingleRow(subquery)) {
// Subquery is expected to return single value
state.put(subqueryAliases[i], subqueryResult.iterator().next());
} else {
state.put(subqueryAliases[i], subqueryResult);
}
}
}
// Evaluate filter
List resultSet = new ArrayList(executeCandidates);
Expression filter = compilation.getExprFilter();
if (applyFilter && filter != null) {
// Process any filter constraints
if (NucleusLogger.QUERY.isDebugEnabled()) {
NucleusLogger.QUERY.debug(Localiser.msg("021012", "filter", language, filter));
}
resultSet = handleFilter(resultSet);
}
Expression[] ordering = compilation.getExprOrdering();
if (applyOrdering && ordering != null) {
// Process any ordering constraints
if (NucleusLogger.QUERY.isDebugEnabled()) {
NucleusLogger.QUERY.debug(Localiser.msg("021012", "ordering", language, StringUtils.objectArrayToString(ordering)));
}
resultSet = ordering(resultSet);
}
if (applyRange && query.getRange() != null) {
// Process any range constraints
long fromIncl = query.getRangeFromIncl();
long toExcl = query.getRangeToExcl();
if (query.getRangeFromInclParam() != null) {
fromIncl = ((Number) parameterValues.get(query.getRangeFromInclParam())).longValue();
}
if (query.getRangeToExclParam() != null) {
toExcl = ((Number) parameterValues.get(query.getRangeToExclParam())).longValue();
}
if (NucleusLogger.QUERY.isDebugEnabled()) {
NucleusLogger.QUERY.debug(Localiser.msg("021012", "range", language, "" + fromIncl + "," + toExcl));
}
resultSet = handleRange(resultSet, fromIncl, toExcl);
}
if (applyResult && result != null) {
// Process any result/grouping/having constraints
if (NucleusLogger.QUERY.isDebugEnabled()) {
NucleusLogger.QUERY.debug(Localiser.msg("021012", "result", language, StringUtils.objectArrayToString(result)));
}
// Apply grouping
List aggregateList = new ArrayList();
List s = resultSet;
Expression[] grouping = compilation.getExprGrouping();
if (grouping != null) {
s = sortByGrouping(resultSet);
}
aggregateList = s;
// TODO Move this to within sortByGrouping
if (grouping != null) {
aggregateList = handleAggregates(s);
}
resultSet = handleResult(aggregateList);
if (query.getResultDistinct()) {
List tmpList = new ArrayList();
Iterator iter = resultSet.iterator();
while (iter.hasNext()) {
Object obj = iter.next();
if (// Omit dups
!tmpList.contains(obj)) {
tmpList.add(obj);
}
}
resultSet = tmpList;
}
}
if (applyResultClass && query.getResultClass() != null) {
// Process any result class constraints
if (NucleusLogger.QUERY.isDebugEnabled()) {
NucleusLogger.QUERY.debug(Localiser.msg("021012", "resultClass", language, query.getResultClass().getName()));
}
if (result != null && !(result[0] instanceof CreatorExpression)) {
return this.mapResultClass(resultSet);
}
}
return resultSet;
}
use of org.datanucleus.store.query.Query in project datanucleus-core by datanucleus.
the class FederatedQueryManagerImpl method newQuery.
/**
* Method to generate a new query using the passed query as basis.
* @param language The query language
* @param ec ExecutionContext
* @param query The query filter (String) or a previous Query
* @return The Query
*/
public Query newQuery(String language, ExecutionContext ec, Object query) {
if (language == null) {
return null;
}
String languageImpl = language;
// Find the query support for this language and this datastore
if (query == null) {
// TODO We don't have candidate so don't know the StoreManager to use
throw new NucleusException("Not yet supported for queries with unknown candidate");
}
if (query instanceof String) {
// Single-string query
String queryString = (String) query;
String candidateName = null;
if (languageImpl.equalsIgnoreCase(Query.LANGUAGE_JDOQL) && queryString.toUpperCase().indexOf(" FROM ") > 0) {
int candidateStart = queryString.toUpperCase().indexOf(" FROM ") + 6;
int candidateEnd = queryString.indexOf(" ", candidateStart + 1);
candidateName = queryString.substring(candidateStart, candidateEnd);
}
if (candidateName != null) {
ClassLoaderResolver clr = nucleusCtx.getClassLoaderResolver(null);
AbstractClassMetaData cmd = nucleusCtx.getMetaDataManager().getMetaDataForClass(candidateName, clr);
StoreManager classStoreMgr = ((FederatedStoreManager) storeMgr).getStoreManagerForClass(cmd);
return classStoreMgr.newQuery(languageImpl, ec, (String) query);
}
// TODO Find StoreManager for the candidate
throw new NucleusException("Not yet supported for single-string queries");
} else if (query instanceof Query) {
// Based on previous query
StoreManager storeMgr = ((Query) query).getStoreManager();
return storeMgr.newQuery(languageImpl, ec, (Query) query);
} else {
throw new NucleusException("Not yet supported for queries taking in object of type " + query.getClass());
}
}
use of org.datanucleus.store.query.Query in project tests by datanucleus.
the class JDOQLEvaluatorTest method testFilterMapContainsKeyNonPC.
/**
* Test of filter with mapField.containsKey(nonPC).
*/
public void testFilterMapContainsKeyNonPC() {
PersistenceManager pm = pmf.getPersistenceManager();
Transaction tx = pm.currentTransaction();
try {
tx.begin();
// Create some instances to query over
List<MapHolder> instances = new ArrayList<>();
MapHolder holder1 = new MapHolder("First");
MapHolder holder2 = new MapHolder("Second");
MapHolder holder3 = new MapHolder("Third");
holder1.getJoinMapNonNon().put("First", "First Element");
holder2.getJoinMapNonNon().put("First", "First Element");
holder2.getJoinMapNonNon().put("Second", "Second Element");
holder3.getJoinMapNonNon().put("Second", "Second Element");
holder3.getJoinMapNonNon().put("Third", "Third Element");
instances.add(holder1);
instances.add(holder2);
instances.add(holder3);
// Compile the query
JDOQuery q = (JDOQuery) pm.newQuery(MapHolder.class, "joinMapNonNon.containsKey('Third')");
Query query = q.getInternalQuery();
ClassLoaderResolver clr = query.getExecutionContext().getClassLoaderResolver();
JavaQueryCompiler compiler = new JDOQLCompiler(query.getExecutionContext().getNucleusContext(), clr, null, query.getCandidateClass(), null, query.getFilter(), query.getParsedImports(), query.getOrdering(), query.getResult(), query.getGrouping(), query.getHaving(), query.getExplicitParametersDeclaration(), query.getExplicitVariablesDeclaration(), null);
QueryCompilation compilation = compiler.compile(new HashMap(), null);
// Execute the query
JavaQueryInMemoryEvaluator eval = new JDOQLInMemoryEvaluator(query, instances, compilation, null, clr);
List results = (List) eval.execute(true, true, true, true, true);
assertEquals("Number of result instances was wrong", 1, results.size());
MapHolder holder = (MapHolder) results.get(0);
assertEquals("Result instance has wrong name", "Third", holder.getName());
tx.commit();
} catch (Exception e) {
e.printStackTrace();
fail("Exception thrown during query execution " + e.getMessage());
} finally {
if (tx.isActive()) {
tx.rollback();
}
pm.close();
}
}
use of org.datanucleus.store.query.Query in project tests by datanucleus.
the class JDOQLEvaluatorTest method testFilterMapContainsValueNonPC.
/**
* Test of filter with mapField.containsValue(nonPC).
*/
public void testFilterMapContainsValueNonPC() {
PersistenceManager pm = pmf.getPersistenceManager();
Transaction tx = pm.currentTransaction();
try {
tx.begin();
// Create some instances to query over
List<MapHolder> instances = new ArrayList<>();
MapHolder holder1 = new MapHolder("First");
MapHolder holder2 = new MapHolder("Second");
MapHolder holder3 = new MapHolder("Third");
holder1.getJoinMapNonNon().put("First", "First Element");
holder2.getJoinMapNonNon().put("First", "First Element");
holder2.getJoinMapNonNon().put("Second", "Second Element");
holder3.getJoinMapNonNon().put("Second", "Second Element");
holder3.getJoinMapNonNon().put("Third", "Third Element");
instances.add(holder1);
instances.add(holder2);
instances.add(holder3);
// Compile the query
JDOQuery q = (JDOQuery) pm.newQuery(MapHolder.class, "joinMapNonNon.containsValue('Third Element')");
Query query = q.getInternalQuery();
ClassLoaderResolver clr = query.getExecutionContext().getClassLoaderResolver();
JavaQueryCompiler compiler = new JDOQLCompiler(query.getExecutionContext().getNucleusContext(), clr, null, query.getCandidateClass(), null, query.getFilter(), query.getParsedImports(), query.getOrdering(), query.getResult(), query.getGrouping(), query.getHaving(), query.getExplicitParametersDeclaration(), query.getExplicitVariablesDeclaration(), null);
QueryCompilation compilation = compiler.compile(new HashMap(), null);
// Execute the query
JavaQueryInMemoryEvaluator eval = new JDOQLInMemoryEvaluator(query, instances, compilation, null, clr);
List results = (List) eval.execute(true, true, true, true, true);
assertEquals("Number of result instances was wrong", 1, results.size());
MapHolder holder = (MapHolder) results.get(0);
assertEquals("Result instance has wrong name", "Third", holder.getName());
tx.commit();
} catch (Exception e) {
e.printStackTrace();
fail("Exception thrown during query execution " + e.getMessage());
} finally {
if (tx.isActive()) {
tx.rollback();
}
pm.close();
}
}
use of org.datanucleus.store.query.Query in project tests by datanucleus.
the class JDOQLEvaluatorTest method testFilterInstanceOf.
/**
* Test of filter with "instanceof".
*/
public void testFilterInstanceOf() {
PersistenceManager pm = pmf.getPersistenceManager();
Transaction tx = pm.currentTransaction();
try {
tx.begin();
// Create some instances to query over
List<Person> instances = new ArrayList<>();
Person p1 = new Person(101, "Mickey", "Mouse", "mickey.mouse@warnerbros.com");
p1.setAge(34);
Employee p2 = new Employee(102, "Donald", "Duck", "donald.duck@warnerbros.com", 13400.0f, "12345");
p2.setAge(38);
Person p3 = new Person(103, "Minnie", "Mouse", "minnie.mouse@warnerbros.com");
p3.setAge(31);
instances.add(p1);
instances.add(p2);
instances.add(p3);
// Compile the query
JDOQuery q = (JDOQuery) pm.newQuery(Person.class, "this instanceof " + Employee.class.getName());
Query query = q.getInternalQuery();
ClassLoaderResolver clr = query.getExecutionContext().getClassLoaderResolver();
JavaQueryCompiler compiler = new JDOQLCompiler(query.getExecutionContext().getNucleusContext(), clr, null, query.getCandidateClass(), null, query.getFilter(), query.getParsedImports(), query.getOrdering(), query.getResult(), query.getGrouping(), query.getHaving(), query.getExplicitParametersDeclaration(), query.getExplicitVariablesDeclaration(), null);
QueryCompilation compilation = compiler.compile(new HashMap(), null);
// Execute the query
JavaQueryInMemoryEvaluator eval = new JDOQLInMemoryEvaluator(query, instances, compilation, null, clr);
List results = (List) eval.execute(true, true, true, true, true);
assertEquals("Number of result instances was wrong", 1, results.size());
Person p = (Person) results.get(0);
assertEquals("Result instance has wrong first name", "Donald", p.getFirstName());
assertEquals("Result instance has wrong last name", "Duck", p.getLastName());
assertEquals("Person number of result instance is wrong", 102, p.getPersonNum());
assertEquals("Age of result instance is wrong", 38, p.getAge());
tx.commit();
} catch (Exception e) {
e.printStackTrace();
fail("Exception thrown during query execution " + e.getMessage());
} finally {
if (tx.isActive()) {
tx.rollback();
}
pm.close();
}
}
Aggregations