001 /* 002 * Cumulus4j - Securing your data in the cloud - http://cumulus4j.org 003 * Copyright (C) 2011 NightLabs Consulting GmbH 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU Affero General Public License as 007 * published by the Free Software Foundation, either version 3 of the 008 * License, or (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU Affero General Public License for more details. 014 * 015 * You should have received a copy of the GNU Affero General Public License 016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 017 */ 018 package org.cumulus4j.store.query; 019 020 import java.util.ArrayList; 021 import java.util.Collection; 022 import java.util.Collections; 023 import java.util.List; 024 import java.util.Map; 025 import java.util.Set; 026 027 import javax.jdo.PersistenceManager; 028 029 import org.cumulus4j.store.Cumulus4jStoreManager; 030 import org.cumulus4j.store.PersistenceManagerConnection; 031 import org.cumulus4j.store.model.ClassMeta; 032 import org.datanucleus.query.evaluator.JPQLEvaluator; 033 import org.datanucleus.query.evaluator.JavaQueryEvaluator; 034 import org.datanucleus.store.ExecutionContext; 035 import org.datanucleus.store.StoreManager; 036 import org.datanucleus.store.connection.ManagedConnection; 037 import org.datanucleus.store.query.AbstractJPQLQuery; 038 import org.datanucleus.util.NucleusLogger; 039 040 /** 041 * JPQL query implementation. Delegates to the query-language-agnostic {@link QueryEvaluator} via 042 * its thin wrapper sub-class {@link JDOQueryEvaluator}. 043 */ 044 public class JPQLQuery extends AbstractJPQLQuery { 045 046 private static final long serialVersionUID = 1L; 047 048 // BEGIN DataNucleus 3.0.0-m6 and 3.0.0-release 049 // public JPQLQuery(ExecutionContext ec, AbstractJPQLQuery q) { 050 // super(ec, q); 051 // } 052 // 053 // public JPQLQuery(ExecutionContext ec, String query) { 054 // super(ec, query); 055 // } 056 // 057 // public JPQLQuery(ExecutionContext ec) { 058 // super(ec); 059 // } 060 // END DataNucleus 3.0.0-m6 and 3.0.0-release 061 062 // BEGIN DataNucleus 3.0.1 and newer 063 public JPQLQuery(StoreManager storeMgr, ExecutionContext ec, AbstractJPQLQuery q) { 064 super(storeMgr, ec, q); 065 } 066 067 public JPQLQuery(StoreManager storeMgr, ExecutionContext ec, String query) { 068 super(storeMgr, ec, query); 069 } 070 071 public JPQLQuery(StoreManager storeMgr, ExecutionContext ec) { 072 super(storeMgr, ec); 073 } 074 // END DataNucleus 3.0.1 and newer 075 076 @Override 077 protected Object performExecute(@SuppressWarnings("rawtypes") Map parameters) { 078 ManagedConnection mconn = ec.getStoreManager().getConnection(ec); 079 try { 080 PersistenceManagerConnection pmConn = (PersistenceManagerConnection)mconn.getConnection(); 081 PersistenceManager pmData = pmConn.getDataPM(); 082 083 boolean inMemory = evaluateInMemory(); 084 boolean inMemory_applyFilter = true; 085 List<Object> candidates = null; 086 if (this.candidateCollection != null) { 087 if (candidateCollection.isEmpty()) { 088 return Collections.EMPTY_LIST; 089 } 090 091 @SuppressWarnings("unchecked") 092 Collection<? extends Object> c = this.candidateCollection; 093 candidates = new ArrayList<Object>(c); 094 } 095 else { 096 if (candidateExtent != null) { 097 this.setCandidateClass(candidateExtent.getCandidateClass()); 098 this.setSubclasses(candidateExtent.hasSubclasses()); 099 } 100 101 if (inMemory) { 102 // Retrieve all candidates and perform all evaluation in-memory 103 Set<ClassMeta> classMetas = QueryHelper.getCandidateClassMetas((Cumulus4jStoreManager) ec.getStoreManager(), 104 ec, candidateClass, subclasses); 105 candidates = QueryHelper.getAllPersistentObjectsForCandidateClasses(pmData, ec, classMetas); 106 } 107 else { 108 try 109 { 110 // Apply filter in datastore 111 @SuppressWarnings("unchecked") 112 Map<String, Object> parameterValues = parameters; 113 JDOQueryEvaluator queryEvaluator = new JDOQueryEvaluator(this, compilation, parameterValues, clr, pmConn); 114 candidates = queryEvaluator.execute(); 115 if (queryEvaluator.isComplete()) { 116 inMemory_applyFilter = false; 117 } 118 else { 119 NucleusLogger.QUERY.debug("Query evaluation of filter in datastore was incomplete so doing further work in-memory"); 120 } 121 } 122 catch (UnsupportedOperationException uoe) { 123 // Some part of the filter is not yet supported, so fallback to in-memory evaluation 124 // Retrieve all candidates and perform all evaluation in-memory 125 NucleusLogger.QUERY.info("Query filter is not totally evaluatable in-datastore using Cumulus4j currently, so evaluating in-memory : "+uoe.getMessage()); 126 Set<ClassMeta> classMetas = QueryHelper.getCandidateClassMetas((Cumulus4jStoreManager) ec.getStoreManager(), 127 ec, candidateClass, subclasses); 128 candidates = QueryHelper.getAllPersistentObjectsForCandidateClasses(pmData, ec, classMetas); 129 } 130 } 131 } 132 133 // Evaluate any remaining query components in-memory 134 JavaQueryEvaluator evaluator = new JPQLEvaluator(this, candidates, compilation, parameters, ec.getClassLoaderResolver()); 135 return evaluator.execute(inMemory_applyFilter, true, true, true, true); 136 } finally { 137 mconn.release(); 138 } 139 } 140 }