/* // $Id: //guest/julian_hyde/saffron/src/main/saffron/rel/AggInternalTranslator.java#1 $ // 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 saffron.rel; import openjava.mop.Environment; import openjava.mop.OJClass; import openjava.mop.QueryEnvironment; import openjava.ptree.*; import saffron.BuiltinAggregator; import saffron.util.Util; import java.util.Vector; /** * Converts expressions to consist only of constants, references to group * by expressions (variables called "$group0", etc.), and calls to * aggregate functions (variables called "$agg0", etc.). * * <p> These names exist only fleetingly, before {@link AggUnpickler} * converts them to field references in the output record. But if we did * not use them, we could not be sure whether a field reference such as * $input0.$f1 had been converted. * * <p> Throws {@link NotAGroupException}. * * @see AggUnpickler **/ class AggInternalTranslator extends InternalTranslator { Expression[] groups; ExpressionList aggInputList; Vector aggCallVector; InternalTranslator nonAggTranslator; AggInternalTranslator( QueryInfo queryInfo, Rel[] inputs, Expression[] groups, ExpressionList aggInputList, Vector aggCallVector) { super(queryInfo, inputs); this.groups = groups; this.aggInputList = aggInputList; this.aggCallVector = aggCallVector; this.nonAggTranslator = new InternalTranslator(queryInfo, inputs); } private Expression toGroupReference(Expression expression) { for (int i = 0; i < groups.length; i++) { if (groups[i].equals(expression)) { return new Variable("$group" + i); } } return expression; } // overrides EvaluationShuttle public Expression evaluateDown(MethodCall call) throws ParseTreeException { String methodName = call.getName(); ExpressionList args = call.getArguments(); Environment env = getEnvironment(); int argCount = args.size(); OJClass[] argTypes = new OJClass[argCount]; try { for (int i = 0; i < argTypes.length; i++) { argTypes[i] = args.get(i).getType(env); } } catch (Exception e) { throw Util.newInternal(e); } // todo: Unify aggregator lookup with method lookup -- perhaps // create a special OJClass with a refined getAcceptableMethod() // method. Then make Aggregation and BuiltinAggregator // package-protected again. See MethodCall.pickupMethod(). Aggregation aggregator = BuiltinAggregator.lookup( methodName, argTypes); if (aggregator != null) { // translate the arguments into internal form, then canonize // them args = (ExpressionList) args.makeRecursiveCopy(); nonAggTranslator.visit(args); int[] argIndexes = new int[argCount]; outer: for (int i = 0; i < argCount; i++) { Expression arg = args.get(i); for (int j = 0, m = aggInputList.size(); j < m; j++) { if (aggInputList.get(j).equals(arg)) { // expression already exists; use that argIndexes[i] = j; continue outer; } } argIndexes[i] = aggInputList.size(); aggInputList.add(arg); } Aggregate.Call aggCall = new Aggregate.Call( aggregator, argIndexes); // create a new aggregate call, if there isn't already an // identical one int k = aggCallVector.indexOf(aggCall); if (k < 0) { k = aggCallVector.size(); aggCallVector.addElement(aggCall); } return new Variable("$agg" + k); } return toGroupReference(call); } public Expression evaluateUp(FieldAccess p) { return toGroupReference(p); } public Expression evaluateUp(UnaryExpression p) { return toGroupReference(p); } public Expression evaluateUp(BinaryExpression p) { return toGroupReference(p); } public Expression evaluateDown(Variable p) { Expression e = toGroupReference(p); if (e != p) { return e; } throw new NotAGroupException( "variable " + p + " is not a group expression"); } boolean isGoodAgg_obsolete(Expression expression) { if (expression instanceof Literal) { return true; } for (int i = 0; i < groups.length; i++) { if (groups[i].equals(expression)) { return true; } } if (expression instanceof MethodCall) { MethodCall methodCall = (MethodCall) expression; // if (isAggregate(methodCall)) { return true; // } } if (expression instanceof Variable) { Variable variable = (Variable) expression; String name = variable.toString(); QueryEnvironment qenv = (QueryEnvironment) this.getEnvironment(); int count = qenv.lookupFrom(name); if (count >= 0) { // found in current query's from list -- bad return false; } else { // either an alias from an enclosing query, or a java // variable -- good return true; } } if (expression instanceof NonLeaf) { throw Util.newInternal("todo:"); } return false; } }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#3 | 1801 | Julian Hyde |
saffron: add ObjectSchema; rules can now be matched more than once; started to implement correlations in queries in from list. |
||
#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. |