/* // $Id: //guest/julian_hyde/saffron/src/main/saffron/rel/SubqueryFinder.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.OJClass; import openjava.mop.Toolbox; import openjava.ptree.*; import openjava.ptree.util.GenericVisitor; import openjava.tools.DebugOut; import saffron.util.RelEnvironment; class SubqueryFinder extends GenericVisitor { QueryInfo queryInfo; SubqueryFinder(QueryInfo queryInfo) { this.queryInfo = queryInfo; } public void visit(BinaryExpression p) throws ParseTreeException { if (p.getOperator() == BinaryExpression.IN) { Expression left = p.getLeft(), right = p.getRight(); DebugOut.println( "SubqueryFinder: found IN: left=[" + left + "], right=[" + right + "]"); Rel oldFrom = queryInfo.getRoot(); left = queryInfo.convertExpToInternal(left); Rel rightRel = queryInfo.convertFromExpToRel(right); OJClass rightRowType = Toolbox.getRowType(queryInfo.env, right); boolean wrap = rightRowType.isPrimitive(); if (wrap) { rightRel = new Project( queryInfo.cluster, rightRel, new Expression[] { Toolbox.box( rightRowType, new Variable(RelEnvironment.makeName(0)))}, new String[] {null}, false); } int leafCount = queryInfo.countLeaves(oldFrom); // Variable with which to refer to the new relation Variable v = new Variable(RelEnvironment.makeName(leafCount)); // Join the sub-query from the 'in' to the tree built up from // the 'from' clause Join join = new Join( queryInfo.cluster, oldFrom, new Distinct(queryInfo.cluster, rightRel), new BinaryExpression( left, BinaryExpression.EQUAL, wrap ? Toolbox.unbox( rightRowType.primitiveWrapper(), v) : v), Join.LEFT); queryInfo.setRoot(join); // Replace the 'in' condition with 'q != null' BinaryExpression condition = new BinaryExpression( new Variable(RelEnvironment.makeName(0)), BinaryExpression.NOTEQUAL, Literal.constantNull()); p.replace(condition); // signal that we want to stop iteration (not really an error) throw new Toolbox.StopIterationException(); } else { super.visit(p); } } public void visit(UnaryExpression p) throws ParseTreeException { if (p.getOperator() == UnaryExpression.EXISTS) { Expression right = p.getExpression(); DebugOut.println( "SubqueryFinder: found EXISTS: expr=[" + right + "]"); Rel oldFrom = queryInfo.getRoot(); Rel rightRel = queryInfo.convertFromExpToRel(right); Rel rightProject = new Project( queryInfo.cluster, rightRel, new Expression[] {}, new String[] {}, true); Rel rightDistinct = new Distinct( queryInfo.cluster, rightProject); queryInfo.leaves.add(rightDistinct); int leafCount = queryInfo.countLeaves(oldFrom); Join join = new Join( queryInfo.cluster, oldFrom, rightDistinct, Literal.constantTrue(), Join.INNER); queryInfo.setRoot(join); // Replace the 'exists' with '<right-row> != null' BinaryExpression condition = new BinaryExpression( RelEnvironment.makeFieldAccess(0, leafCount), BinaryExpression.NOTEQUAL, Literal.constantNull()); p.replace(condition); // signal that we want to stop iteration (not really an error) throw new Toolbox.StopIterationException(); } else { super.visit(p); } } }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#5 | 1853 | Julian Hyde |
saffron: Further improve binding of rows to variables. |
||
#4 | 1818 | Julian Hyde |
saffron: Oops (forgot ParseTreeAction.java), Correlation now works, Smarter code generation (now burrow into synthetic classes, rather than invoking constructors). |
||
#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. |