/* // $Id: //guest/julian_hyde/saffron/src/main/saffron/rel/ExpressionReader.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 saffron.rel; import openjava.mop.OJClass; import openjava.ptree.Expression; import saffron.PlanWriter; import saffron.Planner; import saffron.opt.CallingConvention; import saffron.opt.Cluster; import saffron.opt.Cost; import saffron.opt.Implementor; import saffron.util.Util; /** * An <code>ExpressionReader</code> is a relational expression node which * evaluates an expression and returns the results as a relation. Cases:<ol> * <li>If the expression is an array <code>T[]</code>, the each result row is * of type <code>T</code>.</li> * <li>If the expression implements {@link java.util.Map} or derives from * {@link java.util.Hashtable}, each result row contains fields <code>{Object * key; Object value;}</code>.</li> * <li>If the expression implements {@link java.util.Iterator} or derives from * {@link java.util.Enumeration}, each result row is an {@link Object}.</li> * </ol> * * <p>NOTE: We support {@link java.util.Hashtable}, {@link * java.util.Enumeration} and {@link java.util.Vector} explicitly because * {@link java.util.Map}, {@link java.util.Iterator} and {@link java.util.Map} * does not exist until JDK 1.2.</p> * * <p>Example accessing an array: * * <blockquote><pre>Emp[] emps; * Emp[] males = (select from emps as emp where emp.gender.equals("M"));</pre> * </blockquote></p> * * <p>The following example shows how you can cast the values returned from a * {@link java.util.Hashtable}: * * <blockquote><pre>Hashtable nameToDeptno = new Hashtable(); * nameToDeptno.put("Fred", new Integer(20)); * nameToDeptno.put("Eric", new Integer(10)); * nameToDeptno.put("Bill", new Integer(10)); * for (i in (select {(String) key, ((Integer) value).intValue() as value} * from nameToDeptno)) { * print(i.key + " is in dept " + i.value); * }</pre></blockquote></p> * * <p>Here we access a value in a {@link java.util.Hashtable} by key: * * <blockquote><pre>Object fredDeptno = * (select value from nameToDeptno where key.equals("Fred");</pre> * </blockquote> * * Because the Hashtable is being accessed via its key, the optimizer will * probably optimize this code to <code>nameToDeptno.get("Fred")</code>.</p> * * @author jhyde * @since 8 December, 2001 * @version $Id: //guest/julian_hyde/saffron/src/main/saffron/rel/ExpressionReader.java#3 $ **/ public class ExpressionReader extends Rel { protected Expression exp; protected int convention; /** * Creates an <code>ExpressionReader</code>. * * @param cluster {@link Cluster} this relational expression belongs to * @param exp expression to evaluate * @param rowType row type of the expression; if null, the row type is * deduced from the expression (for example, the row type * of a {@link java.util.Iterator} is {@link * java.lang.Object}. **/ public ExpressionReader(Cluster cluster, Expression exp, OJClass rowType) { super(cluster); this.rowType = rowType; this.exp = exp; this.convention = chooseConvention(exp); Util.discard(getRowType()); } public Expression getExp() { return exp; } private int chooseConvention(Expression exp) { OJClass clazz = getType(exp); if (clazz.getComponentType() != null) { return CallingConvention.ARRAY; } else if (Util.clazzCollection.isAssignableFrom(clazz)) { return CallingConvention.COLLECTION; } else if (Util.clazzIterable.isAssignableFrom(clazz)) { return CallingConvention.ITERABLE; // preferable to ITERATOR } else if (Util.clazzVector.isAssignableFrom(clazz)) { return CallingConvention.VECTOR; } else if (Util.clazzIterator.isAssignableFrom(clazz)) { return CallingConvention.ITERATOR; } else if (Util.clazzEnumeration.isAssignableFrom(clazz)) { return CallingConvention.ENUMERATION; } else if (Util.clazzMap.isAssignableFrom(clazz)) { return CallingConvention.MAP; } else if (Util.clazzHashtable.isAssignableFrom(clazz)) { return CallingConvention.HASHTABLE; } else { throw Util.newInternal("bad type " + clazz); } } public Object clone() { return new ExpressionReader(cluster, Util.clone(exp), getRowType()); } // implement Rel public int getConvention() { return convention; } // implement Rel public Expression[] getChildExps() { return new Expression[] {exp}; } /** * Returns whether an expression <code>clazz</code> can be read as a * relation. **/ public static boolean isRelational(OJClass clazz) { return clazz.getComponentType() != null || Util.clazzVector.isAssignableFrom(clazz) || Util.clazzCollection.isAssignableFrom(clazz) || Util.clazzIterable.isAssignableFrom(clazz) || Util.clazzIterator.isAssignableFrom(clazz) || Util.clazzEnumeration.isAssignableFrom(clazz) || Util.clazzMap.isAssignableFrom(clazz) || Util.clazzHashtable.isAssignableFrom(clazz); } // implement Rel protected OJClass deriveRowType() { OJClass clazz = getType(exp); OJClass rowType = Util.guessRowType(getEnvironment(), clazz); if (rowType == null) { throw Util.newInternal( "expression " + clazz + " is not relational " + "(array, iterator, enumeration, map or hashtable)"); } return rowType; } // implement Rel public Cost computeSelfCost(Planner planner) { int arrayLength = 50; // a guess double dRows = arrayLength, dCpu = arrayLength, dIo = 0; return planner.makeCost(dRows, dCpu, dIo); } // implement Rel public void explain(PlanWriter pw) { pw.explain(this, new String[] {"expression"}); } // implement Rel public Object implement(Implementor implementor, int ordinal) { switch (ordinal) { case -1: // called from parent // Generate // <<exp>> Expression exp2 = implementor.translate(this, exp); return exp2; default: throw Util.newInternal("implement: ordinal=" + ordinal); } } } // End ExpressionReader.java
# | 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 | 1748 | Julian Hyde |
saffron: convert unit tests to JUnit; add CallingConvention.ITERABLE; lots of other stuff; release 0.1. |
||
#1 | 1467 | Julian Hyde |
saffron: First saffron check-in; incorporate my changes to openjava. |