From jdo-commits-return-216-apmail-db-jdo-commits-archive=www.apache.org@db.apache.org Sat Mar 19 05:09:59 2005 Return-Path: Delivered-To: apmail-db-jdo-commits-archive@www.apache.org Received: (qmail 86840 invoked from network); 19 Mar 2005 05:09:59 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 19 Mar 2005 05:09:59 -0000 Received: (qmail 89567 invoked by uid 500); 19 Mar 2005 05:09:59 -0000 Mailing-List: contact jdo-commits-help@db.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: jdo-dev@db.apache.org Delivered-To: mailing list jdo-commits@db.apache.org Delivered-To: moderator for jdo-commits@db.apache.org Received: (qmail 3998 invoked by uid 99); 19 Mar 2005 01:32:47 -0000 X-ASF-Spam-Status: No, hits=-9.8 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Message-ID: <20050319010605.28135.qmail@minotaur.apache.org> Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Mailer: svnmailer-1.0.0-dev Date: Sat, 19 Mar 2005 01:06:04 -0000 Subject: svn commit: r158176 [30/79] - in incubator/jdo/trunk/ri11: ./ src/ src/conf/ src/java/ src/java/org/ src/java/org/apache/ src/java/org/apache/jdo/ src/java/org/apache/jdo/ejb/ src/java/org/apache/jdo/enhancer/ src/java/org/apache/jdo/impl/ src/java/org/apache/jdo/impl/enhancer/ src/java/org/apache/jdo/impl/enhancer/classfile/ src/java/org/apache/jdo/impl/enhancer/core/ src/java/org/apache/jdo/impl/enhancer/generator/ src/java/org/apache/jdo/impl/enhancer/meta/ src/java/org/apache/jdo/impl/enhancer/meta/model/ src/java/org/apache/jdo/impl/enhancer/meta/prop/ src/java/org/apache/jdo/impl/enhancer/meta/util/ src/java/org/apache/jdo/impl/enhancer/util/ src/java/org/apache/jdo/impl/fostore/ src/java/org/apache/jdo/impl/jdoql/ src/java/org/apache/jdo/impl/jdoql/jdoqlc/ src/java/org/apache/jdo/impl/jdoql/scope/ src/java/org/apache/jdo/impl/jdoql/tree/ src/java/org/apache/jdo/impl/model/ src/java/org/apache/jdo/impl/model/java/ src/java/org/apache/jdo/impl/model/java/runtime/ src/java/org/apache/jdo/impl/model/jdo/ src/java/org/apache/jdo/impl/model/jdo/caching/ src/java/org/apache/jdo/impl/model/jdo/util/ src/java/org/apache/jdo/impl/model/jdo/xml/ src/java/org/apache/jdo/impl/pm/ src/java/org/apache/jdo/impl/sco/ src/java/org/apache/jdo/impl/state/ src/java/org/apache/jdo/jdoql/ src/java/org/apache/jdo/jdoql/tree/ src/java/org/apache/jdo/model/ src/java/org/apache/jdo/model/java/ src/java/org/apache/jdo/model/jdo/ src/java/org/apache/jdo/pm/ src/java/org/apache/jdo/sco/ src/java/org/apache/jdo/state/ src/java/org/apache/jdo/store/ src/java/org/apache/jdo/util/ test/ test/conf/ test/enhancer/ test/enhancer/sempdept/ test/enhancer/sempdept/src/ test/enhancer/sempdept/src/empdept/ test/fsuid2/ test/fsuid2/org/ test/fsuid2/org/apache/ test/fsuid2/org/apache/jdo/ test/fsuid2/org/apache/jdo/pc/ test/java/ test/java/org/ test/java/org/apache/ test/java/org/apache/jdo/ test/java/org/apache/jdo/impl/ test/java/org/apache/jdo/impl/fostore/ test/java/org/apache/jdo/pc/ test/java/org/apache/jdo/pc/appid/ test/java/org/apache/jdo/pc/empdept/ test/java/org/apache/jdo/pc/serializable/ test/java/org/apache/jdo/pc/xempdept/ test/java/org/apache/jdo/test/ test/java/org/apache/jdo/test/query/ test/java/org/apache/jdo/test/util/ test/jdo/ test/jdo/org/ test/jdo/org/apache/ test/jdo/org/apache/jdo/ test/jdo/org/apache/jdo/pc/ test/jdo/org/apache/jdo/pc/appid/ test/jdo/org/apache/jdo/pc/empdept/ test/jdo/org/apache/jdo/pc/serializable/ test/jdo/org/apache/jdo/pc/xempdept/ xdocs/ To: jdo-commits@db.apache.org From: mbo@apache.org X-Virus-Checked: Checked X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/jdoql/jdoqlc/O= ptimizer.g URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/ap= ache/jdo/impl/jdoql/jdoqlc/Optimizer.g?view=3Dauto&rev=3D158176 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/jdoql/jdoqlc/Opti= mizer.g (added) +++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/jdoql/jdoqlc/Opti= mizer.g Fri Mar 18 17:02:29 2005 @@ -0,0 +1,1313 @@ +/* + * Copyright 2005 The Apache Software Foundation. + *=20 + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at=20 + *=20 + * http://www.apache.org/licenses/LICENSE-2.0 + *=20 + * Unless required by applicable law or agreed to in writing, software=20 + * distributed under the License is distributed on an "AS IS" BASIS,=20 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied= .=20 + * See the License for the specific language governing permissions and=20 + * limitations under the License. + */ + +/* + * Optimizer.g + * + * Created on August 28, 2001 + */ + +header +{ + package org.apache.jdo.impl.jdoql.jdoqlc; + =20 + import java.util.Collection; + =20 + import java.math.BigDecimal; + import java.math.BigInteger; + + import java.lang.reflect.Field; + import java.security.AccessController; + import java.security.PrivilegedAction; + + import org.apache.jdo.model.java.JavaField; + import org.apache.jdo.model.java.JavaType; + import org.apache.jdo.impl.model.java.PredefinedType; + import org.apache.jdo.impl.model.java.WrapperClassType; + + import org.apache.jdo.pm.PersistenceManagerInternal; + import org.apache.jdo.util.I18NHelper; + import org.apache.jdo.impl.jdoql.tree.*; + import org.apache.jdo.impl.jdoql.scope.ParameterTable; +} + +/** + * This class defines the optimizer pass of the JDOQL compiler. + * It takes the typed AST as produced by the smenatic analysis and + * converts it into a simpler but equivalent typed AST. + *=20 + * @author Michael Bouschen + */ +class Optimizer extends TreeParser; + +options +{ + importVocab =3D JDOQL; + buildAST =3D true; + defaultErrorHandler =3D false; + ASTLabelType =3D "JDOQLAST"; //NOI18N +} + +{ + /** The persistence manager of the query instance. */ + protected PersistenceManagerInternal pm; + + /** The error message support class. */ + protected ErrorMsg errorMsg; + =20 + /** The query parameter table */ + protected ParameterTable paramtab; + =20 + /** Flag indicating whether query parameers should be included. */ + protected boolean optimizeParameters; + + /** I18N support */ + protected final static I18NHelper msg =3D I18NHelper.getInstance( + "org.apache.jdo.impl.jdoql.Bundle", Optimizer.class.getClassLoader= ()); //NOI18N + =20 + /** + * + */ + public void init(PersistenceManagerInternal pm, + ParameterTable paramtab, ErrorMsg errorMsg) + { + this.pm =3D pm; + this.errorMsg =3D errorMsg; + this.paramtab =3D paramtab; + this.optimizeParameters =3D (paramtab !=3D null); + } + + /** + * + */ + public void reportError(RecognitionException ex) { + errorMsg.fatal(msg.msg("ERR_OptimizerError", ex)); //NOI18N + } + + /** + * + */ + public void reportError(String s) { + errorMsg.fatal(msg.msg("ERR_OptimizerError") + s); //NOI18N + } + + /** + * Converts the string argument into a single char. + */ + protected static char parseChar(String text) + { + char first =3D text.charAt(0); + if (first =3D=3D '\\') { + //found escape =3D> check the next char + char second =3D text.charAt(1); + switch (second) + { + case 'n': return '\n'; + case 'r': return '\r'; + case 't': return '\t'; + case 'b': return '\b'; + case 'f': return '\f'; + case 'u':=20 + // unicode spec + return (char)Integer.parseInt(text.substring(2, text.lengt= h()), 16); + case '0': =20 + case '1': + case '2': + case '3': =20 + case '4': + case '5': =20 + case '6': + case '7':=20 + // octal spec=20 + return (char)Integer.parseInt(text.substring(1, text.lengt= h()), 8); + default : return second; + } + } + return first; + } + + /** + * Check an AND operation (BAND, AND) for constant operands=20 + * that could be optimized. + * @param op the AND operator + * @param left the left operand + * @param right the right operand + * @return optimized JDOQLAST=20 + */ + protected JDOQLAST checkAnd(JDOQLAST op, JDOQLAST left, JDOQLAST right) + { + JDOQLAST ast =3D op; + + if (isBooleanValueAST(left)) { + ast =3D handleValueAndExpr(op, ((ConstantExpr)left).getValue()= , right); + } + else if (isBooleanValueAST(right)) { + ast =3D handleValueAndExpr(op, ((ConstantExpr)right).getValue(= ), left); + } + return ast; + } + + /** + * Check an OR operation (BOR, OR) for constant operands=20 + * that could be optimized. + * @param op the OR operator + * @param left the left operand + * @param right the right operand + * @return optimized JDOQLAST=20 + */ + protected JDOQLAST checkOr(JDOQLAST op, JDOQLAST left, JDOQLAST right) + { + JDOQLAST ast =3D op; + + if (isBooleanValueAST(left)) { + ast =3D handleValueOrExpr(op, ((ConstantExpr)left).getValue(),= right); + } + else if (isBooleanValueAST(right)) { + ast =3D handleValueOrExpr(op, ((ConstantExpr)right).getValue()= , left); + } + return ast; + } + + /** + * Check a equality operation (EQUAL, NOT_EQUAL) for constant operands + * that could be optimized. + * @param op the equality operator + * @param left the left operand + * @param right the right operand + * @param negate true for not equal operation, false otherwise + * @return optimized JDOQLAST=20 + */ + protected JDOQLAST checkEqualityOp(JDOQLAST op, JDOQLAST left,=20 + JDOQLAST right, boolean negate) + { + JDOQLAST ast =3D op; + =20 + // case =20 + if ((left.getType() =3D=3D CONSTANT) && (right.getType() =3D=3D CO= NSTANT)) { + ast =3D handleValueEqValue(op, left, right, negate); + } + // case + else if (isBooleanValueAST(left)) { + ast =3D handleBooleanValueEqExpr(op, ((ConstantExpr)left).getV= alue(),=20 + right, negate); + } + // case + else if (isBooleanValueAST(right)) { + ast =3D handleBooleanValueEqExpr(op, ((ConstantExpr)right).get= Value(), + left, negate); + } + return ast; + } + + /** + * Check a object equality operation (OBJECT_EQUAL, OBJECT_NOT_EQUAL)=20 + * for constant operands that could be optimized. + * @param op the object equality operator + * @param left the left operand + * @param right the right operand + * @param negate true for not equal operation, false otherwise + * @return optimized JDOQLAST=20 + */ + protected JDOQLAST checkObjectEqualityOp(JDOQLAST op, JDOQLAST left,=20 + JDOQLAST right, boolean negat= e) + { + JDOQLAST ast =3D op; + + if ((left.getType() =3D=3D CONSTANT) && (right.getType() =3D=3D CO= NSTANT)) { + ast =3D handleValueEqValue(op, left, right, negate); + } + return ast; + } + + /** + * Check a collection equality operation (COLLECTION_EQUAL,=20 + * COLLECTION_NOT_EQUAL) for constant operands that could be optimized. + * @param op the collection equality operator + * @param left the left operand + * @param right the right operand + * @param negate true for not equal operation, false otherwise + * @return optimized JDOQLAST=20 + */ + protected JDOQLAST checkCollectionEqualityOp(JDOQLAST op, JDOQLAST lef= t,=20 + JDOQLAST right, boolean n= egate) + { + JDOQLAST ast =3D op; + boolean isLeftConstant =3D (left.getType() =3D=3D CONSTANT); + boolean isRightConstant =3D (right.getType() =3D=3D CONSTANT); + =20 + if (isLeftConstant && isRightConstant) { + ast =3D handleValueEqValue(op, left, right, negate); + } + return ast; + } + + /** + * Check a logical not operation (LNOT) for a constant operand=20 + * that could be optimized. + * @param op the logical not operator + * @param arg the operand + * @return optimized JDOQLAST=20 + */ + protected JDOQLAST checkLogicalNotOp(JDOQLAST op, JDOQLAST arg) + { + JDOQLAST ast =3D op; + + if (arg.getType() =3D=3D CONSTANT) { + // !value may be calculated at compile time. + Object valueObj =3D ((ConstantExpr)arg).getValue(); + Boolean value =3D (valueObj instanceof Boolean) ?=20 + new Boolean(!((Boolean)valueObj).booleanValue(= )) : + Boolean.TRUE; + ast =3D ConstantExpr.newConstant(value); + ast.setType(CONSTANT); + ast.setText(value.toString()); + ast.setTypeInfo(op.getTypeInfo()); + } + return ast; + } + + /** + * Check a binary plus operation (PLUS) for constant operands + * that could be optimized. + * @param op the plus operator + * @param left the left operand + * @param right the right operand + * @return optimized JDOQLAST=20 + */ + protected JDOQLAST checkBinaryPlusOp(JDOQLAST op, JDOQLAST left,=20 + JDOQLAST right) + { + JDOQLAST ast =3D op; + + if ((left.getType() =3D=3D CONSTANT) && (right.getType() =3D=3D CO= NSTANT)) { + Object leftValue =3D ((ConstantExpr)left).getValue(); + Object rightValue =3D ((ConstantExpr)right).getValue(); + Object value =3D null; + if (leftValue =3D=3D null) + value =3D rightValue; + else if (rightValue =3D=3D null) + value =3D leftValue; + else { + JavaType type =3D op.getTypeInfo(); + =20 + if (type.isWrapperClass()) + type =3D ((WrapperClassType)type).getWrappedPrimitiveT= ype(); + =20 + if (type.equals(PredefinedType.intType)) + value =3D new Integer(((Number)leftValue).intValue() +=20 + ((Number)rightValue).intValue()); + else if (type.equals(PredefinedType.longType)) + value =3D new Long(((Number)leftValue).longValue() +=20 + ((Number)rightValue).longValue()); + else if (type.equals(PredefinedType.floatType)) + value =3D new Float(((Number)leftValue).floatValue() +=20 + ((Number)rightValue).floatValue()); + else if (type.equals(PredefinedType.doubleType)) + value =3D new Double(((Number)leftValue).doubleValue()= +=20 + ((Number)rightValue).doubleValue()); + else if (type.equals(PredefinedType.bigDecimalType)) + value =3D getBigDecimalValue(leftValue).add( + getBigDecimalValue(rightValue)); + else if (type.equals(PredefinedType.bigIntegerType)) + value =3D getBigIntegerValue(leftValue).add( + getBigIntegerValue(rightValue)); + else=20 + errorMsg.fatal(msg.msg("ERR_OptmizerInvalidType", //NO= I18N + "checkBinaryPlusOp", type)); //NOI18N + } + ast =3D ConstantExpr.newConstant(value); + ast.setType(CONSTANT); + ast.setText(value.toString()); + ast.setTypeInfo(op.getTypeInfo()); + } + return ast; + } + =20 + /** + * Check a string concatenation operation (CONCAT) for constant operan= ds + * that could be optimized. + * @param op the concat operator + * @param left the left operand + * @param right the right operand + * @return optimized JDOQLAST=20 + */ + protected JDOQLAST checkConcatOp(JDOQLAST op, JDOQLAST left, JDOQLAST = right) + { + JDOQLAST ast =3D op; + + if ((left.getType() =3D=3D CONSTANT) && (right.getType() =3D=3D CO= NSTANT)) { + Object leftValue =3D ((ConstantExpr)left).getValue(); + Object rightValue =3D ((ConstantExpr)right).getValue(); + Object value =3D null; + if (leftValue =3D=3D null) + value =3D rightValue; + else if (rightValue =3D=3D null) + value =3D leftValue; + else=20 + value =3D leftValue.toString() + rightValue.toString(); + ast =3D ConstantExpr.newConstant(value); + ast.setType(CONSTANT); + ast.setText(value.toString()); + ast.setTypeInfo(op.getTypeInfo()); + } + return ast; + } + + /** + * Check a binary minus operation (MINUS) for constant operands + * that could be optimized. + * @param op the minus operator + * @param left the left operand + * @param right the right operand + * @return optimized JDOQLAST=20 + */ + protected JDOQLAST checkBinaryMinusOp(JDOQLAST op, JDOQLAST left,=20 + JDOQLAST right) + { + JDOQLAST ast =3D op; + + if ((left.getType() =3D=3D CONSTANT) && (right.getType() =3D=3D CO= NSTANT)) { + Object leftValue =3D ((ConstantExpr)left).getValue(); + Object rightValue =3D ((ConstantExpr)right).getValue(); + Object value =3D null; + if (rightValue =3D=3D null) + value =3D leftValue; + else { + if (leftValue =3D=3D null) + leftValue =3D new Integer(0); + =20 + JavaType type =3D op.getTypeInfo(); + =20 + if (type.isWrapperClass()) + type =3D ((WrapperClassType)type).getWrappedPrimitiveT= ype(); + =20 + if (type.equals(PredefinedType.intType)) + value =3D new Integer(((Number)leftValue).intValue() - + ((Number)rightValue).intValue()); + else if (type.equals(PredefinedType.longType)) + value =3D new Long(((Number)leftValue).longValue() - + ((Number)rightValue).longValue()); + else if (type.equals(PredefinedType.floatType)) + value =3D new Float(((Number)leftValue).floatValue() -=20 + ((Number)rightValue).floatValue()); + else if (type.equals(PredefinedType.doubleType)) + value =3D new Double(((Number)leftValue).doubleValue()= -=20 + ((Number)rightValue).doubleValue()); + else if (type.equals(PredefinedType.bigDecimalType)) + value =3D getBigDecimalValue(leftValue).subtract( + getBigDecimalValue(rightValue)); + else if (type.equals(PredefinedType.bigIntegerType)) + value =3D getBigIntegerValue(leftValue).subtract( + getBigIntegerValue(rightValue)); + else=20 + errorMsg.fatal(msg.msg("ERR_OptmizerInvalidType", //NO= I18N + "checkBinaryMinusOp", type)); //NOI18N + } + ast =3D ConstantExpr.newConstant(value); + ast.setType(CONSTANT); + ast.setText(value.toString()); + ast.setTypeInfo(op.getTypeInfo()); + } + return ast; + } + =20 + /** + * Check a binary multiplication operation (STAR) for constant operands + * that could be optimized. + * @param op the multiplication operator + * @param left the left operand + * @param right the right operand + * @return optimized JDOQLAST=20 + */ + protected JDOQLAST checkMultiplicationOp(JDOQLAST op, JDOQLAST left,=20 + JDOQLAST right) + { + JDOQLAST ast =3D op; + + if ((left.getType() =3D=3D CONSTANT) && (right.getType() =3D=3D CO= NSTANT)) { + Object leftValue =3D ((ConstantExpr)left).getValue(); + Object rightValue =3D ((ConstantExpr)right).getValue(); + Object value =3D null; + if (leftValue =3D=3D null) + leftValue =3D new Integer(0); + if (rightValue =3D=3D null) + rightValue =3D new Integer(0); + JavaType type =3D op.getTypeInfo(); + =20 + if (type.isWrapperClass()) + type =3D ((WrapperClassType)type).getWrappedPrimitiveType(= ); + =20 + if (type.equals(PredefinedType.intType)) + value =3D new Integer(((Number)leftValue).intValue() * + ((Number)rightValue).intValue()); + else if (type.equals(PredefinedType.longType)) + value =3D new Long(((Number)leftValue).longValue() * + ((Number)rightValue).longValue()); + else if (type.equals(PredefinedType.floatType)) + value =3D new Float(((Number)leftValue).floatValue() *=20 + ((Number)rightValue).floatValue()); + else if (type.equals(PredefinedType.doubleType)) + value =3D new Double(((Number)leftValue).doubleValue() *=20 + ((Number)rightValue).doubleValue()); + else if (type.equals(PredefinedType.bigDecimalType)) + value =3D getBigDecimalValue(leftValue).multiply( + getBigDecimalValue(rightValue)); + else if (type.equals(PredefinedType.bigIntegerType)) + value =3D getBigIntegerValue(leftValue).multiply( + getBigIntegerValue(rightValue)); + else=20 + errorMsg.fatal(msg.msg("ERR_OptmizerInvalidType", //NOI18N + "checkMultiplicationOp", type)); //NOI18N + + ast =3D ConstantExpr.newConstant(value); + ast.setType(CONSTANT); + ast.setText(value.toString()); + ast.setTypeInfo(op.getTypeInfo()); + } + return ast; + } + =20 + /** + * Check a binary division operation (DIV) for constant operands + * that could be optimized. + * @param op the division operator + * @param left the left operand + * @param right the right operand + * @return optimized JDOQLAST=20 + */ + protected JDOQLAST checkDivisionOp(JDOQLAST op, JDOQLAST left,=20 + JDOQLAST right) + { + JDOQLAST ast =3D op; + + if ((left.getType() =3D=3D CONSTANT) && (right.getType() =3D=3D CO= NSTANT)) { + Object leftValue =3D ((ConstantExpr)left).getValue(); + Object rightValue =3D ((ConstantExpr)right).getValue(); + Object value =3D null; + if (leftValue =3D=3D null) + leftValue =3D new Integer(0); + if (rightValue =3D=3D null) + // division by zero! + rightValue =3D new Integer(0); + + JavaType type =3D op.getTypeInfo(); + =20 + if (type.isWrapperClass()) + type =3D ((WrapperClassType)type).getWrappedPrimitiveType(= ); + =20 + if (type.equals(PredefinedType.intType)) + value =3D new Integer(((Number)leftValue).intValue() / + ((Number)rightValue).intValue()); + else if (type.equals(PredefinedType.longType)) + value =3D new Long(((Number)leftValue).longValue() / + ((Number)rightValue).longValue()); + else if (type.equals(PredefinedType.floatType)) + value =3D new Float(((Number)leftValue).floatValue() /=20 + ((Number)rightValue).floatValue()); + else if (type.equals(PredefinedType.doubleType)) + value =3D new Double(((Number)leftValue).doubleValue() /=20 + ((Number)rightValue).doubleValue()); + else if (type.equals(PredefinedType.bigDecimalType)) + value =3D getBigDecimalValue(leftValue).divide( + getBigDecimalValue(rightValue), BigDecimal.ROUND_HALF_E= VEN); + else if (type.equals(PredefinedType.bigIntegerType)) + value =3D getBigIntegerValue(leftValue).divide( + getBigIntegerValue(rightValue)); + else=20 + errorMsg.fatal(msg.msg("ERR_OptmizerInvalidType", //NOI18N + "checkDivisionOp", type)); //NOI18N + + ast =3D ConstantExpr.newConstant(value); + ast.setType(CONSTANT); + ast.setText(value.toString()); + ast.setTypeInfo(op.getTypeInfo()); + } + return ast; + } + =20 + /** + * Check a unary minus operation (UNARY_MINUS) for a constant operand + * that could be optimized. + * @param op the unary minus operator + * @param arg the operand + * @return optimized JDOQLAST=20 + */ + protected JDOQLAST checkUnaryMinusOp(JDOQLAST op, JDOQLAST arg) + { + JDOQLAST ast =3D op; + =20 + if (arg.getType() =3D=3D CONSTANT) { + Object value =3D ((ConstantExpr)arg).getValue(); + JavaType type =3D op.getTypeInfo(); + Object negate =3D null; + =20 + if (type.equals(PredefinedType.intType)) + negate =3D new Integer(-((Number)value).intValue()); + else if (type.equals(PredefinedType.longType)) + negate =3D new Long(-((Number)value).longValue()); + else if (type.equals(PredefinedType.floatType)) + negate =3D new Float(-((Number)value).floatValue()); + else if (type.equals(PredefinedType.doubleType)) + negate =3D new Double(-((Number)value).doubleValue()); + else if (type.equals(PredefinedType.bigDecimalType)) + negate =3D getBigDecimalValue(value).negate(); + else if (type.equals(PredefinedType.bigIntegerType)) + negate =3D getBigIntegerValue(value).negate(); + else=20 + errorMsg.fatal(msg.msg("ERR_OptmizerInvalidType", //NOI18N + "checkUnaryMinusOp", type)); //NOI18N + =20 + ast =3D ConstantExpr.newConstant(negate); + ast.setType(CONSTANT); + ast.setText(negate.toString()); + ast.setTypeInfo(op.getTypeInfo()); + } + return ast; + } + + /** + * Converts the specified value into a BigDecimal value.=20 + * @param value value to be converted + * @return BigDecimal representation + */ + protected BigDecimal getBigDecimalValue(Object value) + { + BigDecimal ret =3D null; + if (value instanceof BigDecimal) + ret =3D (BigDecimal)value; + else if (value instanceof BigInteger) + ret =3D new BigDecimal((BigInteger)value); + else if (value instanceof Double) + ret =3D new BigDecimal(((Double)value).doubleValue()); + else if (value instanceof Float) + ret =3D new BigDecimal(((Float)value).doubleValue()); + else if (value instanceof Number) + ret =3D BigDecimal.valueOf(((Number)value).longValue()); + else + errorMsg.fatal(msg.msg("ERR_OptmizerNumberExpected", //NOI18N + "getBigDecimalValue", value)); //NOI18N + return ret; + } + + /** + * Converts the specified value into a BigInteger value.=20 + * @param value value to be converted + * @return BigInteger representation + */ + protected BigInteger getBigIntegerValue(Object value) + { + BigInteger ret =3D null; + + if (value instanceof BigInteger) + ret =3D (BigInteger)value; + else if (value instanceof Number) + ret =3D BigInteger.valueOf(((Number)value).longValue()); + else + errorMsg.fatal(msg.msg("ERR_OptmizerNumberExpected", //NOI18N + "getBigIntegerValue", value)); //NOI18N + return ret; + } + =20 + /** + * This method is called in the case of an equality operation having t= wo=20 + * constant operands. It calculates the result of this constant operat= ion=20 + * and returns a JDOQLAST node representing a constant boolean value. + * @param op the equality operator + * @param left the left operand + * @param right the right operand + * @param negate true for not equal operation, false otherwise + * @return optimized JDOQLAST=20 + */ + protected JDOQLAST handleValueEqValue(JDOQLAST op, JDOQLAST left, + JDOQLAST right,=20 + boolean negate) + { + Object leftValue =3D ((ConstantExpr)left).getValue(); + Object rightValue =3D ((ConstantExpr)right).getValue(); + boolean booleanValue =3D false; + =20 + if ((leftValue =3D=3D null) && (rightValue =3D=3D null)) { + // both values are null -> true + booleanValue =3D true; + } + else if ((leftValue !=3D null) && (rightValue !=3D null)) { + // both values are not null -> use equals + booleanValue =3D leftValue.equals(rightValue); + } + else + { + // one value is null, the other is not null -> false + booleanValue =3D false; + } + if (negate) { + booleanValue =3D !booleanValue; + } + =20 + Boolean value =3D booleanValue ? Boolean.TRUE : Boolean.FALSE; + ConstantExpr constant =3D ConstantExpr.newConstant(value); + constant.setType(CONSTANT); + constant.setText(value.toString()); + constant.setTypeInfo(op.getTypeInfo()); + return op; + } + + /** + * This method is called in the case of an equality operation having=20 + * a boolean constant operand and a non constant operand.=20 + * It returns the non constant operand either as it is or inverted,=20 + * depending on the equality operation. + * @param op the equality operator + * @param value the contant boolean value + * @param expr the non constant operand + * @param negate true for not equal operation, false otherwise + * @return optimized JDOQLAST=20 + */ + private JDOQLAST handleBooleanValueEqExpr(JDOQLAST op, Object value,=20 + JDOQLAST expr, boolean negat= e) + { + JDOQLAST ast; + boolean skip =3D (value instanceof Boolean) ?=20 + ((Boolean)value).booleanValue() : false; + if (negate) skip =3D !skip; + + if (skip) { + // expr =3D=3D true -> expr + // expr !=3D false -> expr + ast =3D expr; + } + else { + // if expr is a equality op or a not op the invert operation=20 + // may be "inlined": + // (expr1 =3D=3D expr2) !=3D true -> expr1 !=3D expr2 + // (expr1 !=3D expr2) !=3D true -> expr1 =3D=3D expr2 + // !expr !=3D true -> expr + // !expr =3D=3D false -> expr + // Otherwise wrap the expr with a not op + // expr !=3D true -> !expr + // expr =3D=3D false -> !expr + switch (expr.getType()) { + case EQUAL: + ast =3D new NotEqualsExpr(); + ast.initialize(NOT_EQUAL, "!=3D", PredefinedType.booleanTy= pe); //NOI18N + ast.setFirstChild(expr.getFirstChild()); + ((BinaryExpr)ast).setCommonOperandType( + ((BinaryExpr)expr).getCommonOperandType()); + break; + case NOT_EQUAL: + ast =3D new EqualsExpr(); + ast.initialize(EQUAL, "=3D=3D", PredefinedType.booleanType= ); //NOI18N + ast.setFirstChild(expr.getFirstChild()); + ((BinaryExpr)ast).setCommonOperandType( + ((BinaryExpr)expr).getCommonOperandType()); + break; + case LNOT: + ast =3D (JDOQLAST)expr.getFirstChild(); + break; + default: + ast =3D new NotExpr(); + ast.initialize(LNOT, "!", PredefinedType.booleanType); //N= OI18N + ast.setFirstChild(expr); + } + expr.setNextSibling(null); + } + return ast; + } + + /** + * This method is called in the case of an AND operation having at lea= st=20 + * one constant operand. If the constant operand evaluates to true it=20 + * returns the other operand. If it evaluates to false it returns an A= ST + * representing the constant boolean value false. + * @param op the AND operator + * @param value the value of the contsnat operand + * @param expr the other operand + * @return optimized JDOQLAST=20 + */ + private JDOQLAST handleValueAndExpr(JDOQLAST op, Object value, JDOQLAS= T expr) + { + JDOQLAST ast; + + if ((value instanceof Boolean) && ((Boolean)value).booleanValue())= { + // true AND expr -> expr + // expr AND true -> expr + expr.setNextSibling(null); + ast =3D expr; + } + else + { + // false AND expr -> false + // expr AND false -> false + ast =3D ConstantExpr.newConstant(Boolean.FALSE); + ast.setType(CONSTANT); + ast.setText("false"); //NOI18N + ast.setTypeInfo(op.getTypeInfo()); + } + return ast; + } + + /** + * This method is called in the case of an OR operation having at leas= t=20 + * one constant operand. If the constant operand evaluates to false it=20 + * returns the other operand. If it evaluates to true it returns an AST + * representing the constant boolean value true. + * @param op the AND operator + * @param value the value of the constant operand + * @param expr the other operand + * @return optimized JDOQLAST=20 + */ + private JDOQLAST handleValueOrExpr(JDOQLAST op, Object value, JDOQLAST= expr) + { + JDOQLAST ast; + + if ((value instanceof Boolean) && ((Boolean)value).booleanValue())= { + // true OR expr -> true + // expr OR true -> true + ast =3D ConstantExpr.newConstant(Boolean.TRUE); + ast.setType(CONSTANT); + ast.setText("true"); //NOI18N + ast.setTypeInfo(op.getTypeInfo()); + } + else { + // false OR expr -> expr + // expr OR false -> expr + expr.setNextSibling(null); + ast =3D expr; + } + return ast; + } + + /** + * Returns true if the specified AST represents a constant boolean val= ue. + */ + protected boolean isBooleanValueAST(JDOQLAST ast) + { + return (ast.getType() =3D=3D CONSTANT) &&=20 + (PredefinedType.booleanType.equals(ast.getTypeInfo())); + } + + /** + * Returns the specified string w/o a long type suffix 'l' or 'L' or + * the specified string if there is no such suffix. + */ + private String skipLongTypeSuffix(String txt) + { + int index =3D txt.length() - 1; + char last =3D txt.charAt(index); + return ((last =3D=3D 'l') || (last =3D=3D 'L')) ? txt.substring(0,= index) : txt; + } + + /** + * Returns the value of the specified field of the specified object. + * The method uses StateManager methods to access the field value,=20 + * if it is a managed field of a persistent instance.=20 + * Otherwise it uses reflection. + * @param javaField the field representation + * @param pm the pm used in case of a managed field of a persistent in= stance + * @param object the instance + * @return the field value + */ + private Object getFieldValue(JavaField javaField,=20 + PersistenceManagerInternal pm,=20 + Object object) + { + int fieldNumber =3D=20 + TypeSupport.getFieldNumber(javaField.getJDOField(), pm, object= ); + if (fieldNumber =3D=3D -1)=20 + return TypeSupport.getFieldValue(getAccessibleField(javaField)= ,=20 + object); + else + return TypeSupport.getFieldValue(fieldNumber, pm, object); + } + + /** + * Returns the value of the specified static field. + * @param javaField the field representation + * @return the field value + */ + private Object getStaticFieldValue(JavaField javaField) + { + return TypeSupport.getFieldValue(getAccessibleField(javaField), nu= ll); + }=20 + + /** + * Method executing TypeSupport.getAccessibleField in a doPrivileged b= lock. + */ + private Field getAccessibleField(final JavaField javaField) + { + return (Field) AccessController.doPrivileged( + new PrivilegedAction() { + public Object run () { + return TypeSupport.getAccessibleField(javaField); + }}); + } + +} + +// rules + +query! + : #( q:QUERY_TREE + c:candidateClass + p:parameters + v:variables + o:ordering + f:filter + ) + { + Tree tree =3D new Tree((CandidateClassImpl)#c, (ParameterDecl)= #p,=20 + (VariableDecl)#v, (OrderingExpr)#o, (Expr= )#f); + tree.setType(QUERY_TREE); + tree.setText("QUERY_TREE"); //NOI18N + #query =3D tree; + } + ; + +// ---------------------------------- +// rules: candidate class +// ---------------------------------- + +candidateClass +{ =20 + errorMsg.setContext("setCandidates"); //NOI18N +} + : #(CANDIDATE_CLASS TYPE) + ; + +// ---------------------------------- +// rules: parameter declaration +// ---------------------------------- + +parameters +{ =20 + errorMsg.setContext("declareParameters"); //NOI18N +} + : ( declareParameter )* + ; + +declareParameter + : #( PARAMETER_DECL TYPE ( IDENT )? ) + ; + +// ---------------------------------- +// rules: variable declaration +// ---------------------------------- + +variables=20 +{=20 + errorMsg.setContext("declareVariables"); //NOI18N +} + : ( declareVariable )* + ; + +declareVariable + : #( VARIABLE_DECL TYPE ( IDENT )? ) + ; + +// ---------------------------------- +// rules: ordering specification +// ---------------------------------- + +ordering=20 +{ =20 + errorMsg.setContext("setOrdering"); //NOI18N +} + : ( orderSpec )* + ; + +orderSpec + : #( ASCENDING expression ) + | #( DESCENDING expression ) + ; + +// ---------------------------------- +// rules: filer expression +// ---------------------------------- + +filter +{ =20 + errorMsg.setContext("setFilter"); //NOI18N +} + : expression + ; + +expression=20 + : primary + | bitwiseExpr + | conditionalExpr + | relationalExpr + | binaryArithmeticExpr + | unaryArithmeticExpr + | complementExpr + ; + +bitwiseExpr + : #( op1:BAND left1:expression right1:expression ) + { + #bitwiseExpr =3D checkAnd(#op1, #left1, #right1); + } + | #( op2:BOR left2:expression right2:expression ) + { + #bitwiseExpr =3D checkOr(#op2, #left2, #right2); + } + ; + +conditionalExpr + : #( op1:AND left1:expression right1:expression ) + { + #conditionalExpr =3D checkAnd(#op1, #left1, #right1); + } + | #( op2:OR left2:expression right2:expression ) + { + #conditionalExpr =3D checkOr(#op2, #left2, #right2); + } + ; + +relationalExpr + : #( op1:EQUAL left1:expression right1:expression ) + { + #relationalExpr =3D checkEqualityOp(#op1, #left1, #right1, fal= se); + } + | #( op2:NOT_EQUAL left2:expression right2:expression ) + { + #relationalExpr =3D checkEqualityOp(#op2, #left2, #right2, tru= e); + } + | #( op3:OBJECT_EQUAL left3:expression right3:expression )=20 + { + #relationalExpr =3D checkObjectEqualityOp(#op3, #left3, #right= 3, false); + } + | #( op4:OBJECT_NOT_EQUAL left4:expression right4:expression ) + { + #relationalExpr =3D checkObjectEqualityOp(#op4, #left4, #right= 4, true); + } + | #( op5:COLLECTION_EQUAL left5:expression right5:expression ) + { + #relationalExpr =3D checkCollectionEqualityOp(#op5, #left5, #r= ight5, false); + } + | #( op6:COLLECTION_NOT_EQUAL left6:expression right6:expression ) + { + #relationalExpr =3D checkCollectionEqualityOp(#op6, #left6, #r= ight6, true); + } + | #( LT expression expression ) + | #( GT expression expression ) + | #( LE expression expression ) + | #( GE expression expression ) + ; + +binaryArithmeticExpr + : #( op1:PLUS left1:expression right1:expression ) + { + #binaryArithmeticExpr =3D checkBinaryPlusOp(#op1, #left1, #rig= ht1); + } + | #( op2:CONCAT left2:expression right2:expression ) + { + #binaryArithmeticExpr =3D checkConcatOp(#op2, #left2, #right2); + } + | #( op3:MINUS left3:expression right3:expression ) + { + #binaryArithmeticExpr =3D checkBinaryMinusOp(#op3, #left3, #ri= ght3); + } + | #( op4:STAR left4:expression right4:expression ) + { + #binaryArithmeticExpr =3D checkMultiplicationOp(#op4, #left4, = #right4); + } + | #( op5:DIV left5:expression right5:expression ) + { + #binaryArithmeticExpr =3D checkDivisionOp(#op5, #left5, #right= 5); + } + ; + +unaryArithmeticExpr=20 + : #( UNARY_PLUS expression ) + | ( #( UNARY_MINUS ( INT_LITERAL | LONG_LITERAL ) ) )=3D>=20 + #( UNARY_MINUS l:integralLiteral[true] ) + {=20 + #unaryArithmeticExpr =3D #l;=20 + } + | #( op2:UNARY_MINUS arg2:expression ) + { + #unaryArithmeticExpr =3D checkUnaryMinusOp(#op2, #arg2); + } + ; + +complementExpr=20 + : #( op1:BNOT arg1:expression ) + | #( op2:LNOT arg2:expression ) + { + #complementExpr =3D checkLogicalNotOp(#op2, #arg2); + } + ; + +primary=20 + : #( CAST TYPE expression ) + | literal + | THIS + | parameterAccess + | variableAccess + | staticFieldAccess + | fieldAccess + | navigation + | contains + | startsWith + | endsWith + | isEmpty + ; + +literal + : b1:TRUE + {=20 + ConstantExpr constant =3D ConstantExpr.newConstant(Boolean.TRU= E); + constant.setType(CONSTANT); + constant.setText("true"); //NOI18N + constant.setTypeInfo(b1.getTypeInfo()); + #literal =3D constant; + } + | b2:FALSE + {=20 + ConstantExpr constant =3D ConstantExpr.newConstant(Boolean.FAL= SE); + constant.setType(CONSTANT); + constant.setText("false"); //NOI18N + constant.setTypeInfo(b2.getTypeInfo()); + #literal =3D constant; + } + | b3:BOOLEAN_LITERAL + { + b3.setType(CONSTANT); + } + | integralLiteral[false] + | f:FLOAT_LITERAL + { =20 + String txt =3D f.getText(); + Float value =3D null; + try { + value =3D new Float(txt); + }=20 + catch (NumberFormatException ex) { + errorMsg.error(f.getLine(), f.getColumn(),=20 + msg.msg("EXC_InvalidLiteral", "float", txt)); //NOI18N + } + ConstantExpr constant =3D ConstantExpr.newConstant(value); + constant.setType(CONSTANT); + constant.setText(f.getText()); + constant.setTypeInfo(f.getTypeInfo()); + #literal =3D constant; + } + | d:DOUBLE_LITERAL + { =20 + String txt =3D d.getText(); + Double value =3D null; + try { + value =3D new Double(txt); + }=20 + catch (NumberFormatException ex) { + errorMsg.error(d.getLine(), d.getColumn(),=20 + msg.msg("EXC_InvalidLiteral", "double", txt)); //NOI18N + } + ConstantExpr constant =3D ConstantExpr.newConstant(value); + constant.setType(CONSTANT); + constant.setText(d.getText()); + constant.setTypeInfo(d.getTypeInfo()); + #literal =3D constant; + } + | c:CHAR_LITERAL + {=20 + Character value =3D new Character(parseChar(c.getText()));=20 + ConstantExpr constant =3D ConstantExpr.newConstant(value); + constant.setType(CONSTANT); + constant.setText(c.getText()); + constant.setTypeInfo(c.getTypeInfo()); + #literal =3D constant; + } + | s:STRING_LITERAL + {=20 + ConstantExpr constant =3D ConstantExpr.newConstant(s.getText()= ); + constant.setType(CONSTANT); + constant.setText(s.getText()); + constant.setTypeInfo(s.getTypeInfo()); + #literal =3D constant; + } + | n:NULL + {=20 + ConstantExpr constant =3D ConstantExpr.newConstant(null); + constant.setType(CONSTANT); + constant.setText("null"); //NOI18N + constant.setTypeInfo(n.getTypeInfo()); + #literal =3D constant; + } + | by:BYTE_LITERAL + { + by.setType(CONSTANT); + } + | sh:SHORT_LITERAL + { + sh.setType(CONSTANT); + } + | con:CONSTANT + ; + +integralLiteral! [boolean negate] + : i:INT_LITERAL + {=20 + String txt =3D negate ? "-" + i.getText() : i.getText(); + Integer value =3D null; + try { + value =3D Integer.decode(txt); + }=20 + catch (NumberFormatException ex) { + errorMsg.error(i.getLine(), i.getColumn(),=20 + msg.msg("EXC_InvalidLiteral", "int", txt)); //NOI18N + } + ConstantExpr constant =3D ConstantExpr.newConstant(value); + constant.setType(CONSTANT); + constant.setText(txt); + constant.setTypeInfo(i.getTypeInfo()); + #integralLiteral =3D constant; + } + | l:LONG_LITERAL + { =20 + String txt =3D negate ? "-" + l.getText() : l.getText(); + Long value =3D null; + try { + value =3D Long.decode(skipLongTypeSuffix(txt)); + }=20 + catch (NumberFormatException ex) { + errorMsg.error(l.getLine(), l.getColumn(),=20 + msg.msg("EXC_InvalidLiteral", "long", txt)); //NOI18N + } + ConstantExpr constant =3D ConstantExpr.newConstant(value); + constant.setType(CONSTANT); + constant.setText(txt); + constant.setTypeInfo(l.getTypeInfo()); + #integralLiteral =3D constant; + } + ; + +parameterAccess + : p:PARAMETER_ACCESS + { + if (optimizeParameters) { + Object value =3D paramtab.getValue(#p.getText()); + ConstantExpr constant =3D ConstantExpr.newConstant(value); + constant.setType(CONSTANT); + constant.setText((value=3D=3Dnull) ? "null" : value.toStri= ng()); //NOI18N + constant.setTypeInfo(#p.getTypeInfo()); + #parameterAccess =3D constant; + } + } + ; + +variableAccess + : #( VARIABLE_ACCESS ( expression )? ) + ; + +staticFieldAccess! + : #( s:STATIC_FIELD_ACCESS t:TYPE (i:IDENT)? ) + { + // Calculate the value of the static field at compile time + // and treat it as constant value. + StaticFieldAccessExpr fieldAccess =3D (StaticFieldAccessExpr)#= s; + String fieldName =3D fieldAccess.getName(); + JavaField javaField =3D #t.getTypeInfo().getJavaField(fieldNam= e); + Object value =3D getStaticFieldValue(javaField); + ConstantExpr constant =3D ConstantExpr.newConstant(value); + constant.setType(CONSTANT); + constant.setText((value=3D=3Dnull) ? "null" : value.toString()= ); //NOI18N + constant.setTypeInfo(#s.getTypeInfo()); + #staticFieldAccess =3D constant; + } + ; + +fieldAccess + : #( f:FIELD_ACCESS o:expression ( i:IDENT )? ) + { + if (#o.getType() =3D=3D CONSTANT) { + // If the object of the field access is a constant value,=20 + // evaluate the field access at compile time and=20 + // treat the expression as constant value. + FieldAccessExpr fieldAccess =3D (FieldAccessExpr)#f; + String fieldName =3D fieldAccess.getName(); + JavaField javaField =3D #o.getTypeInfo().getJavaField(fiel= dName); + Object value =3D getFieldValue( + javaField, pm, ((ConstantExpr)#o).getValue()); + ConstantExpr constant =3D ConstantExpr.newConstant(value); + constant.setType(CONSTANT); + constant.setText((value=3D=3Dnull) ? "null" : value.toStri= ng()); //NOI18N + constant.setTypeInfo(#f.getTypeInfo()); + #fieldAccess =3D constant; + } + } + ; + +navigation + : #( n:NAVIGATION o:expression ( i:IDENT )? ) + { + if (#o.getType() =3D=3D CONSTANT) { + // If the object of the navigation is a constant value,=20 + // evaluate the field access at compile time and=20 + // treat the expression as constant value. + FieldAccessExpr fieldAccess =3D (FieldAccessExpr)#n; + String fieldName =3D fieldAccess.getName(); + JavaField javaField =3D #o.getTypeInfo().getJavaField(fiel= dName); + Object value =3D getFieldValue( + javaField, pm, ((ConstantExpr)#o).getValue()); + ConstantExpr constant =3D ConstantExpr.newConstant(value); + constant.setType(CONSTANT); + constant.setText((value=3D=3Dnull) ? "null" : value.toStri= ng()); //NOI18N + constant.setTypeInfo(#n.getTypeInfo()); + #navigation =3D constant; + } + } + ; + +contains + : #( CONTAINS expression expression ) + ; + +startsWith + : #( STARTS_WITH expression expression )=20 + ; + +endsWith + : #( ENDS_WITH expression expression )=20 + ; + +isEmpty + : #( op:IS_EMPTY e:expression) + { + if (#e.getType() =3D=3D CONSTANT) { + // If the expression that specifies the collection is a=20 + // constant value, evaluate the isEmpty call at compile ti= me=20 + // and treat the expression as constant value. + Object object =3D ((ConstantExpr)#e).getValue(); + Object value =3D null; + if (object =3D=3D null) { + value =3D new Boolean(false); + } + else if (object instanceof Collection) { + value =3D new Boolean(((Collection)object).isEmpty()); + } + else { + errorMsg.fatal(msg.msg("ERR_OptmizerCollectionExpected= ", //NOI18N + "isEmpty", object)); //NOI18N + } + ConstantExpr constant =3D ConstantExpr.newConstant(value); + constant.setType(CONSTANT); + constant.setText((value=3D=3Dnull) ? "null" : value.toStri= ng()); //NOI18N + constant.setTypeInfo(#op.getTypeInfo()); + #isEmpty =3D constant; + } + } + ; +