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.JDOQLEvaluator; 033 import org.datanucleus.query.evaluator.JavaQueryEvaluator; 034 import org.datanucleus.store.ExecutionContext; 035 import org.datanucleus.store.connection.ManagedConnection; 036 import org.datanucleus.store.query.AbstractJDOQLQuery; 037 import org.datanucleus.util.NucleusLogger; 038 039 /** 040 * JDOQL query implementation. Delegates to the query-language-agnostic {@link QueryEvaluator} via 041 * its thin wrapper sub-class {@link JDOQueryEvaluator}. 042 * 043 * @author Marco หงุ่ยตระกูล-Schulze - marco at nightlabs dot de 044 */ 045 public class JDOQLQuery extends AbstractJDOQLQuery 046 { 047 private static final long serialVersionUID = 1L; 048 049 // BEGIN DataNucleus 3.0.0-m6 and 3.0.0-release 050 public JDOQLQuery(ExecutionContext ec, AbstractJDOQLQuery q) { 051 super(ec, q); 052 } 053 054 public JDOQLQuery(ExecutionContext ec, String query) { 055 super(ec, query); 056 } 057 058 public JDOQLQuery(ExecutionContext ec) { 059 super(ec); 060 } 061 // END DataNucleus 3.0.0-m6 and 3.0.0-release 062 063 // BEGIN DataNucleus 3.0.1 and newer 064 // public JDOQLQuery(StoreManager storeMgr, ExecutionContext ec, AbstractJDOQLQuery q) { 065 // super(storeMgr, ec, q); 066 // } 067 // 068 // public JDOQLQuery(StoreManager storeMgr, ExecutionContext ec, String query) { 069 // super(storeMgr, ec, query); 070 // } 071 // 072 // public JDOQLQuery(StoreManager storeMgr, ExecutionContext ec) { 073 // super(storeMgr, ec); 074 // } 075 // END DataNucleus 3.0.1 and newer 076 077 @Override 078 protected Object performExecute(@SuppressWarnings("rawtypes") Map parameters) 079 { 080 ManagedConnection mconn = ec.getStoreManager().getConnection(ec); 081 try { 082 PersistenceManagerConnection pmConn = (PersistenceManagerConnection)mconn.getConnection(); 083 PersistenceManager pmData = pmConn.getDataPM(); 084 085 boolean inMemory = evaluateInMemory(); 086 boolean inMemory_applyFilter = true; 087 List<Object> candidates = null; 088 if (this.candidateCollection != null) { 089 if (candidateCollection.isEmpty()) 090 { 091 return Collections.EMPTY_LIST; 092 } 093 094 @SuppressWarnings("unchecked") 095 Collection<? extends Object> c = this.candidateCollection; 096 candidates = new ArrayList<Object>(c); 097 } 098 else { 099 if (candidateExtent != null) { 100 this.setCandidateClass(candidateExtent.getCandidateClass()); 101 this.setSubclasses(candidateExtent.hasSubclasses()); 102 } 103 104 if (inMemory) { 105 // Retrieve all candidates and perform all evaluation in-memory 106 Set<ClassMeta> classMetas = QueryHelper.getCandidateClassMetas((Cumulus4jStoreManager) ec.getStoreManager(), 107 ec, candidateClass, subclasses); 108 candidates = QueryHelper.getAllPersistentObjectsForCandidateClasses(pmData, ec, classMetas); 109 } 110 else { 111 try 112 { 113 // Apply filter in datastore 114 @SuppressWarnings("unchecked") 115 Map<String, Object> parameterValues = parameters; 116 JDOQueryEvaluator queryEvaluator = new JDOQueryEvaluator(this, compilation, parameterValues, clr, pmConn); 117 candidates = queryEvaluator.execute(); 118 if (queryEvaluator.isComplete()) { 119 inMemory_applyFilter = false; 120 } 121 else { 122 NucleusLogger.QUERY.debug("Query evaluation of filter in datastore was incomplete so doing further work in-memory"); 123 } 124 } 125 catch (UnsupportedOperationException uoe) { 126 // Some part of the filter is not yet supported, so fallback to in-memory evaluation 127 // Retrieve all candidates and perform all evaluation in-memory 128 NucleusLogger.QUERY.info("Query filter is not totally evaluatable in-datastore using Cumulus4j currently, so evaluating in-memory : "+uoe.getMessage()); 129 Set<ClassMeta> classMetas = QueryHelper.getCandidateClassMetas((Cumulus4jStoreManager) ec.getStoreManager(), 130 ec, candidateClass, subclasses); 131 candidates = QueryHelper.getAllPersistentObjectsForCandidateClasses(pmData, ec, classMetas); 132 } 133 } 134 } 135 136 // Evaluate any remaining query components in-memory 137 JavaQueryEvaluator evaluator = new JDOQLEvaluator(this, candidates, compilation, parameters, ec.getClassLoaderResolver()); 138 return evaluator.execute(inMemory_applyFilter, true, true, true, true); 139 } finally { 140 mconn.release(); 141 } 142 } 143 144 }