001: /**
002: * Copyright (C) 2001-2006 France Telecom R&D
003: */package org.objectweb.speedo.query.jdo;
004:
005: import org.objectweb.jorm.metainfo.api.Manager;
006: import org.objectweb.medor.api.EvaluationException;
007: import org.objectweb.medor.api.MedorException;
008: import org.objectweb.medor.eval.api.ConnectionResources;
009: import org.objectweb.medor.eval.api.QueryEvaluator;
010: import org.objectweb.medor.eval.lib.DeleteEvaluator;
011: import org.objectweb.medor.expression.api.ExpressionException;
012: import org.objectweb.medor.expression.api.ParameterOperand;
013: import org.objectweb.medor.query.api.QueryLeaf;
014: import org.objectweb.medor.query.api.QueryTree;
015: import org.objectweb.medor.query.jorm.lib.QueryBuilder;
016: import org.objectweb.medor.query.lib.QueryTreePrinter;
017: import org.objectweb.medor.query.lib.SelectProject;
018: import org.objectweb.medor.tuple.api.TupleCollection;
019: import org.objectweb.speedo.api.ExceptionHelper;
020: import org.objectweb.speedo.api.SpeedoException;
021: import org.objectweb.speedo.pm.jdo.api.JDOPOManagerItf;
022: import org.objectweb.speedo.query.api.QueryDefinition;
023: import org.objectweb.speedo.query.jdo.parser.ASTSpeedoQL;
024: import org.objectweb.speedo.query.jdo.parser.ParseException;
025: import org.objectweb.speedo.query.jdo.parser.SelectGroupByVisitor;
026: import org.objectweb.speedo.query.jdo.parser.SimpleNode;
027: import org.objectweb.speedo.query.jdo.parser.SpeedoQL;
028: import org.objectweb.speedo.query.jdo.parser.SpeedoQLQueryFilterVisitor;
029: import org.objectweb.speedo.query.jdo.parser.SpeedoQLVariableVisitor;
030: import org.objectweb.speedo.workingset.api.TransactionItf;
031: import org.objectweb.util.monolog.api.BasicLevel;
032:
033: import java.io.CharArrayReader;
034: import java.util.Map;
035:
036: import javax.jdo.JDOFatalException;
037:
038: public class JDOCompiledDeleteQuery extends JDOAbstractCompiledQuery {
039:
040: QueryTree optimizedQT;
041: QueryEvaluator evaluator;
042:
043: public synchronized void compile() throws SpeedoException,
044: MedorException, ExpressionException {
045: if (status == UNDEFINED)
046: throw new SpeedoException(
047: "Impossible to compile an undefined query");
048: if (status == COMPILED)
049: return;
050: long timeToCompile = System.currentTimeMillis();
051: boolean debug = logger.isLoggable(BasicLevel.DEBUG);
052: // create a speedoQL object with a filter string
053: String filter = qd.filter;
054: filter = '(' + filter + ')';
055: // create representations of the parameters list and the variable
056: // list
057: toHashtableParams(qd.parameters, ";,");
058: toHashtableVars(qd.variables, ";,");
059: Manager miManager = mapper.getMetaInfoManager();
060: if (miManager == null)
061: throw new SpeedoException(
062: "A non null Meta information manager is needed");
063: try {
064: jf.getPClassMapping(qd.candidateClass.getName(),
065: classLoader);
066: } catch (Exception e) {
067: throw new SpeedoException(e);
068: }
069: SimpleNode node = null;
070: try {
071: node = new SpeedoQL(new CharArrayReader(filter
072: .toCharArray())).SpeedoQL();
073: } catch (ParseException e) {
074: throw new SpeedoException(
075: "Impossible to parse the filter and to create AST",
076: e);
077: }
078: SpeedoQLVariableVisitor sqvv = new SpeedoQLVariableVisitor(
079: node, miManager, varParserlogger, hparams, hvars,
080: qd.order, qd.candidateClass.getName(),
081: qd.includeSubClasses);
082: // start the variable visitor to catch all variables and build a
083: // first tree of them without collection navigation
084: Map fields = sqvv.getFields();
085: QueryBuilder qb = sqvv.getQueryBuilder();
086: QueryTree qt = sqvv.getQueryTree();
087:
088: SelectProject sp = new SelectProject("");
089: if (!filter.equals("(true)") && !filter.equals("true")) {
090: //Ther is a filter and potentialy collection navigation
091: if (debug) {
092: logger.log(BasicLevel.DEBUG, "filter = " + qd.filter);
093: }
094: // start the query filter visitor, to build and expression tree of
095: // the filter expression
096: SpeedoQLQueryFilterVisitor sqfv = new SpeedoQLQueryFilterVisitor(
097: fields, sp, (ASTSpeedoQL) node, filterParserLogger,
098: hparams, hvars, qd.candidateClass, qb, jf);
099: sp.setQueryFilter(sqfv.getQueryFilter());
100: }
101: assignMapper(sp);
102: assignMapper(qt);
103:
104: SelectGroupByVisitor sgv = new SelectGroupByVisitor(sp, qt,
105: sqvv, classLoader);
106:
107: sgv.visit(qd);
108: assignMapper(sp);
109:
110: logger.log(BasicLevel.INFO, "QueryTree built");
111: if (debug) {
112: QueryTreePrinter.printQueryTree(sp, logger);
113: }
114:
115: // Optimize the queryTree
116: optimizedQT = optimize(sp, debug);
117:
118: // Creates an evaluator associated to the QueryTree
119: evaluator = new DeleteEvaluator(optimizedQT);
120: timeToCompile = System.currentTimeMillis() - timeToCompile;
121: status = COMPILED;
122: logger.log(BasicLevel.INFO, "Query compiled in "
123: + timeToCompile + "ms");
124: }
125:
126: /**
127: * executes a the current delete query, and returns a Long object
128: * corresponding to the number of delete instances
129: */
130: protected Object executeQT(JDOPOManagerItf pm,
131: ParameterOperand[] pos, QueryDefinition userqd)
132: throws EvaluationException, MedorException, SpeedoException {
133: flushCache(pm);
134: Object connection = ((TransactionItf) pm.currentTransaction())
135: .getConnectionHolder();
136: ConnectionResources connRess = evaluator
137: .getRequiredConnectionResources();
138:
139: // Gets the QueryLeafs that require connections
140: QueryLeaf[] leafs = connRess.getRequiredQueryLeafConnection();
141: // Setting QueryLeaf's appropriated connection Object
142: for (int cpt = 0; (cpt < leafs.length); cpt++) {
143: connRess.setConnection(leafs[cpt], connection);
144: }
145:
146: TupleCollection queryResult = null;
147: try {
148: queryResult = evaluator.evaluate(pos, connRess, null);
149: } catch (EvaluationException e) {
150: throw new JDOFatalException(
151: "Impossible to evaluate the query: ",
152: ExceptionHelper.getNested(e));
153: }
154: return new JDOQueryResultUnique(queryResult, pm,
155: new Object[] { connection }, null,
156: new Class[] { Long.class }, true, false, logger)
157: .getResult();
158: }
159:
160: }
|