001: /**
002: * Copyright (C) 2001-2004 France Telecom R&D
003: *
004: * This library is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 2 of the License, or (at your option) any later version.
008: *
009: * This library is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: */package org.objectweb.speedo.query.jdo;
018:
019: import org.objectweb.jorm.api.PClassMapping;
020: import org.objectweb.jorm.mapper.rdb.lib.RdbPPolymorphicClass;
021: import org.objectweb.medor.api.EvaluationException;
022: import org.objectweb.medor.api.MedorException;
023: import org.objectweb.medor.eval.api.ConnectionResources;
024: import org.objectweb.medor.eval.api.QueryEvaluator;
025: import org.objectweb.medor.eval.lib.BasicEvaluationMetaData;
026: import org.objectweb.medor.eval.prefetch.api.IntermediaryPrefetchBuffer;
027: import org.objectweb.medor.eval.prefetch.api.PrefetchBuffer;
028: import org.objectweb.medor.eval.prefetch.lib.IntermediaryPrefetchBufferImpl;
029: import org.objectweb.medor.expression.api.ParameterOperand;
030: import org.objectweb.medor.query.api.QueryLeaf;
031: import org.objectweb.medor.query.api.QueryTree;
032: import org.objectweb.medor.tuple.api.TupleCollection;
033: import org.objectweb.speedo.api.ExceptionHelper;
034: import org.objectweb.speedo.pm.jdo.api.JDOPOManagerItf;
035: import org.objectweb.speedo.query.api.QueryDefinition;
036: import org.objectweb.util.monolog.api.BasicLevel;
037:
038: import java.util.HashMap;
039: import java.util.Map;
040:
041: import javax.jdo.JDOFatalException;
042:
043: /**
044: * Represent a Medor query executed for a JDO query. It contains the query, the
045: * evaluator, a link to the SpeedoCompiledQuery and some information about
046: * the data prefetching. A JDO can correspond to several Medor query in case of
047: * inheritance for example.
048: *
049: * @author S.Chassande-Barrioz
050: */
051: public class JDOQueryEvalContext {
052: /**
053: * The medor querytree representing the query
054: */
055: public QueryTree query;
056:
057: /**
058: * the evaluator of the query
059: */
060: public QueryEvaluator evaluator;
061:
062: /**
063: * is the index of the identifier (prefetch index too)
064: */
065: public int pnIndex;
066:
067: /**
068: * the PClassMapping of the prefetched class
069: */
070: public PClassMapping pcm;
071:
072: /**
073: * The original speedo compiled query
074: */
075: public JDOCompiledSelectQuery sqc;
076:
077: /**
078: * @param qt is the medor querytree representing the query
079: * @param sqc is the original speedo compiled query
080: */
081: public JDOQueryEvalContext(QueryTree qt, JDOCompiledSelectQuery sqc) {
082: query = qt;
083: this .sqc = sqc;
084: }
085:
086: /**
087: * Executes the sub query
088: * @param pm is the current persistence manager
089: * @param pos is the parameter of the query
090: * @param connection is the way to reach the persistence support
091: * @return a TupleCollection containing the result
092: * @throws MedorException
093: *
094: */
095: public TupleCollection eval(JDOPOManagerItf pm,
096: ParameterOperand[] pos, Object connection,
097: QueryDefinition userqd) throws MedorException {
098: // Calculates and gets the required connection ressources for this query
099: ConnectionResources connRess = evaluator
100: .getRequiredConnectionResources();
101:
102: Map evalMDMap = null;
103: if (userqd != null
104: && (userqd.getIndexFirst() > 0 || userqd.getIndexLast() < Integer.MAX_VALUE)) {
105: //range values specified
106: evalMDMap = new HashMap();
107: }
108:
109: // Gets the QueryLeafs that require connections
110: QueryLeaf[] leafs = connRess.getRequiredQueryLeafConnection();
111: // Setting QueryLeaf's appropriated connection Object
112: for (int cpt = 0; (cpt < leafs.length); cpt++) {
113: connRess.setConnection(leafs[cpt], connection);
114: if (evalMDMap != null) {
115: //range values specified
116: BasicEvaluationMetaData evalMD = new BasicEvaluationMetaData();
117: evalMD.setLimitedRangeStartAt((int) userqd
118: .getIndexFirst());
119: evalMD
120: .setLimitedRangeSize((int) (userqd
121: .getIndexLast() - userqd
122: .getIndexFirst()));
123: evalMDMap.put(leafs[cpt], evalMD);
124: }
125: }
126:
127: PrefetchBuffer prefetchBuffer = null;
128: if (pcm != null) {
129: boolean isPolymorphic = (pcm instanceof RdbPPolymorphicClass)
130: && ((JDOQueryDefinitionImpl) sqc.getDefinition())
131: .getIncludeSubClasses();
132: prefetchBuffer = sqc.getMapper().getPrefetchCache()
133: .createPrefetchBuffer(
134: sqc.getPrefetchBufferFactory(), pcm,
135: pm.currentTransaction(), pnIndex,
136: pm.getMultithreaded(), !isPolymorphic);
137: //if the class is polymorphic, register an intermediary prefetch buffer
138: if (isPolymorphic) {
139: IntermediaryPrefetchBuffer ipb = new IntermediaryPrefetchBufferImpl(
140: prefetchBuffer, pcm.getIndexesTable(pcm));
141: if (!pcm.getPMapper().getPrefetchCache()
142: .registerPrefetchBuffer(ipb, pcm,
143: pm.currentTransaction())) {
144: throw new MedorException(
145: "No prefetch buffer registered for the pcm "
146: + pcm.getClassName() + ".");
147: }
148: //register the prefetch buffer for all the subclasses
149: try {
150: //get the list of all the sub pclassmappings
151: PClassMapping[] subPCMs = pcm.getSubPCMs();
152: if (subPCMs != null) {
153: for (int i = 0; i < subPCMs.length; i++) {
154: //create an intermediary prefetchBuffer that has the prefetchBuffer
155: //of the superclass as delegate prefetch buffer
156: //and the association table for the pcm of the superclass
157: IntermediaryPrefetchBuffer intermediaryPb = new IntermediaryPrefetchBufferImpl(
158: prefetchBuffer, subPCMs[i]
159: .getIndexesTable(pcm));
160: if (!subPCMs[i].getPMapper()
161: .getPrefetchCache()
162: .registerPrefetchBuffer(
163: intermediaryPb, subPCMs[i],
164: pm.currentTransaction())) {
165: throw new MedorException(
166: "No prefetch buffer registered for the pcm "
167: + subPCMs[i]
168: .getClassName()
169: + ".");
170: }
171: }
172: }
173: } catch (Exception e) {
174: throw new MedorException(
175: "Error while trying to register the prefetchBuffer with the subclasses. ",
176: e);
177: }
178: }
179: }
180: // Launching Medor Evaluator...
181: if (sqc.getLogger().isLoggable(BasicLevel.DEBUG)) {
182: sqc.getLogger().log(BasicLevel.DEBUG,
183: "Parameters: " + posToString(pos));
184: }
185: TupleCollection queryResult = null;
186: try {
187: queryResult = evaluator.evaluate(pos, connRess,
188: prefetchBuffer, evalMDMap);
189: } catch (EvaluationException e) {
190: throw new JDOFatalException(
191: "Impossible to evaluate the query: ",
192: ExceptionHelper.getNested(e));
193: }
194: return queryResult;
195: }
196:
197: /**
198: * Produces a String representation of parameter for logging.
199: */
200: protected String posToString(ParameterOperand[] pos) {
201: if (pos == null) {
202: return "null";
203: }
204: StringBuffer sb = new StringBuffer("[");
205: String sep = "";
206: for (int i = 0; i < pos.length; i++) {
207: sb.append(sep);
208: sb.append("(name='");
209: sb.append("'");
210: sb.append(pos[i].getName());
211: sb.append("', value=");
212: sb.append(pos[i]);
213: sb.append(")");
214: }
215: sb.append("]");
216: return sb.toString();
217: }
218: }
|