/* // $Id: //guest/julian_hyde/saffron/src/main/openjava/ptree/util/QueryExpander.java#3 $ // Saffron preprocessor and data engine // Copyright (C) 2002 Julian Hyde <julian.hyde@mail.com> // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Library General Public License for more details. // // You should have received a copy of the GNU Library General Public // License along with this library; if not, write to the // Free Software Foundation, Inc., 59 Temple Place - Suite 330, // Boston, MA 02111-1307, USA. // // See the COPYING file located in the top-level-directory of // the archive of this library for complete text of license. */ package openjava.ptree.util; import openjava.mop.*; import openjava.ptree.*; import openjava.tools.parser.ParserConstants; import java.util.HashSet; /** * <code>QueryExpander</code> is a {@link ParseTreeVisitor} which, as it passes * over a parse tree, converts {@link QueryExpression}s into regular java * constructs. * * <p>The non-abstract derived class {@link saffron.rel.SaffronQueryExpander} * does this by converting the expression to a tree of {@link saffron.rel.Rel} * nodes, and using an optimizer ({@link saffron.Planner}) to choose the * optimal java implementation.</p> **/ public abstract class QueryExpander extends ScopeHandler { public QueryExpander(Environment env) { super(env); } public Expression evaluateDown( QueryExpression p ) throws ParseTreeException { super.evaluateDown(p); return expandExpression(p); } private boolean isRelational(Expression p) { if (p instanceof QueryExpression) { return true; } else if (p instanceof BinaryExpression) { switch (((BinaryExpression) p).getOperator()) { case BinaryExpression.IN: case BinaryExpression.UNION: case BinaryExpression.INTERSECT: case BinaryExpression.REL_MINUS: return true; default: return false; } } else if (p instanceof UnaryExpression) { switch (((UnaryExpression) p).getOperator()) { case UnaryExpression.EXISTS: return true; default: return false; } } else if (p instanceof MethodCall) { // A call to the method saffron.Connection.contentsAsArray(String) // is relational. MethodCall methodCall = (MethodCall) p; String name = methodCall.getName(); if (!name.equals("contentsAsArray")) { return false; } Expression refexpr = methodCall.getReferenceExpr(); if (refexpr == null) { return false; } Environment env = getEnvironment(); OJClass reftype = Toolbox.getType(env, refexpr); if (!Toolbox.clazzConnection.isAssignableFrom(reftype)) { return false; } return true; } else { return false; } } public Expression evaluateDown(CastExpression p) throws ParseTreeException { Expression exp = p.getExpression(); if (isRelational(exp)) { return expandExpression(p); } else { return super.evaluateDown(p); } } /** * Expand 'for (<<variable>> in <<query>>) ...'. */ public Statement evaluateDown(ForStatement p) throws ParseTreeException { if (p.getQuery() == null) { return super.evaluateDown(p); } else { return expandForIn( new Variable(p.getVariable()), p.getQuery(), p.getStatements()); } } /** * Expands <code>in</code> <code>union</code>, <code>minus</code>, and * <code>intersect</code>. **/ public Expression evaluateDown(BinaryExpression p) throws ParseTreeException { switch (p.getOperator()) { case BinaryExpression.IN: case BinaryExpression.UNION: case BinaryExpression.INTERSECT: case BinaryExpression.REL_MINUS: return expandExpression(p); default: return super.evaluateDown(p); } } /** * Expands <code>exists</code>. **/ public Expression evaluateDown(UnaryExpression p) throws ParseTreeException { switch (p.getOperator()) { case UnaryExpression.EXISTS: return expandExpression(p); default: return super.evaluateDown(p); } } /** * Expands <code>connection.contentsAsArray("name")</code>, which was * probably generated by expanding <code>connection.name</code>. **/ public Expression evaluateDown(MethodCall p) throws ParseTreeException { if (isRelational(p)) { // The call "connection.contentsAsArray("name")" will become // "select from something" return expandExpression(p); } return super.evaluateDown(p); } /* boolean isRelational(Expression exp) { if (exp instanceof QueryExpression) { return true; } else if (exp instanceof BinaryExpression) { BinaryExpression p = (BinaryExpression) exp; switch (p.getOperator()) { case BinaryExpression.IN: case BinaryExpression.UNION: case BinaryExpression.REL_MINUS: case BinaryExpression.INTERSECT: return true; default: return false; } } else if (exp instanceof UnaryExpression) { UnaryExpression p = (UnaryExpression) exp; switch (p.getOperator()) { case UnaryExpression.EXISTS: return true; default: return false; } } else { return false; } } */ /** * Converts an {@link Expression} into a java expression which returns an * array. **/ protected abstract Expression expandExpression(Expression p); /** * Converts an {@link Expression} of the form <code>for (<i>variable</i> in * <i>exp</i>) { <i>body</i> }</code> into a regular java {@link * openjava.ptree.Statement}. **/ protected abstract Statement expandForIn( Variable var, Expression p, StatementList body); } // End QueryExpander.java
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#3 | 1748 | Julian Hyde |
saffron: convert unit tests to JUnit; add CallingConvention.ITERABLE; lots of other stuff; release 0.1. |
||
#2 | 1474 | Julian Hyde |
saffron: Aggregations are working. Renamed 'aggregator' to 'aggregation'. |
||
#1 | 1467 | Julian Hyde |
saffron: First saffron check-in; incorporate my changes to openjava. |