📄 binaryoperatornode.java
字号:
/* Derby - Class org.apache.derby.impl.sql.compile.BinaryOperatorNode Copyright 1997, 2004 The Apache Software Foundation or its licensors, as applicable. 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 http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */package org.apache.derby.impl.sql.compile;import org.apache.derby.iapi.sql.compile.Visitable;import org.apache.derby.iapi.sql.compile.Visitor;import org.apache.derby.iapi.sql.dictionary.DataDictionary;import org.apache.derby.iapi.error.StandardException;import org.apache.derby.iapi.services.sanity.SanityManager;import org.apache.derby.iapi.services.compiler.MethodBuilder;import org.apache.derby.iapi.services.compiler.LocalField;import java.lang.reflect.Modifier;import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;import org.apache.derby.impl.sql.compile.ActivationClassBuilder;import org.apache.derby.iapi.types.StringDataValue;import org.apache.derby.iapi.types.TypeId;import org.apache.derby.iapi.types.DataTypeDescriptor;import org.apache.derby.iapi.store.access.Qualifier;import org.apache.derby.iapi.reference.ClassName;import org.apache.derby.iapi.reference.SQLState;import org.apache.derby.iapi.util.JBitSet;import org.apache.derby.iapi.services.classfile.VMOpcode;import java.sql.Types;import java.util.Vector;/** * A BinaryOperatorNode represents a built-in binary operator as defined by * the ANSI/ISO SQL standard. This covers operators like +, -, *, /, =, <, etc. * Java operators are not represented here: the JSQL language allows Java * methods to be called from expressions, but not Java operators. * * @author Jeff Lichtman */public class BinaryOperatorNode extends ValueNode{ String operator; String methodName; ValueNode receiver; // used in generation /* ** These identifiers are used in the grammar. */ public final static int PLUS = 1; public final static int MINUS = 2; public final static int TIMES = 3; public final static int DIVIDE = 4; public final static int CONCATENATE = 5; public final static int EQ = 6; public final static int NE = 7; public final static int GT = 8; public final static int GE = 9; public final static int LT = 10; public final static int LE = 11; public final static int AND = 12; public final static int OR = 13; public final static int LIKE = 14; ValueNode leftOperand; ValueNode rightOperand; String leftInterfaceType; String rightInterfaceType; String resultInterfaceType; int operatorType; // At the time of adding XML support, it was decided that // we should avoid creating new OperatorNodes where possible. // So for the XML-related binary operators we just add the // necessary code to _this_ class, similar to what is done in // TernarnyOperatorNode. Subsequent binary operators (whether // XML-related or not) should follow this example when // possible. public final static int XMLEXISTS_OP = 0; // NOTE: in the following 4 arrays, order // IS important. static final String[] BinaryOperators = { "xmlexists", }; static final String[] BinaryMethodNames = { "XMLExists", }; static final String[] BinaryResultTypes = { ClassName.BooleanDataValue // XMLExists }; static final String[][] BinaryArgTypes = { {ClassName.StringDataValue, ClassName.XMLDataValue} // XMLExists }; /** * Initializer for a BinaryOperatorNode * * @param leftOperand The left operand of the node * @param rightOperand The right operand of the node * @param operator The name of the operator * @param methodName The name of the method to call for this operator * @param leftInterfaceType The name of the interface for the left operand * @param rightInterfaceType The name of the interface for the right * operand */ public void init( Object leftOperand, Object rightOperand, Object operator, Object methodName, Object leftInterfaceType, Object rightInterfaceType) { this.leftOperand = (ValueNode) leftOperand; this.rightOperand = (ValueNode) rightOperand; this.operator = (String) operator; this.methodName = (String) methodName; this.leftInterfaceType = (String) leftInterfaceType; this.rightInterfaceType = (String) rightInterfaceType; this.operatorType = -1; } public void init( Object leftOperand, Object rightOperand, Object leftInterfaceType, Object rightInterfaceType) { this.leftOperand = (ValueNode) leftOperand; this.rightOperand = (ValueNode) rightOperand; this.leftInterfaceType = (String) leftInterfaceType; this.rightInterfaceType = (String) rightInterfaceType; this.operatorType = -1; } /** * Initializer for a BinaryOperatorNode * * @param leftOperand The left operand of the node * @param rightOperand The right operand of the node * @param opType An Integer holding the operatorType * for this operator. */ public void init( Object leftOperand, Object rightOperand, Object opType) { this.leftOperand = (ValueNode)leftOperand; this.rightOperand = (ValueNode)rightOperand; this.operatorType = ((Integer)opType).intValue(); this.operator = BinaryOperators[this.operatorType]; this.methodName = BinaryMethodNames[this.operatorType]; this.leftInterfaceType = BinaryArgTypes[this.operatorType][0]; this.rightInterfaceType = BinaryArgTypes[this.operatorType][1]; this.resultInterfaceType = BinaryResultTypes[this.operatorType]; } /** * Convert this object to a String. See comments in QueryTreeNode.java * for how this should be done for tree printing. * * @return This object as a String */ public String toString() { if (SanityManager.DEBUG) { return "operator: " + operator + "\n" + "methodName: " + methodName + "\n" + super.toString(); } else { return ""; } } /** * Set the operator. * * @param operator The operator. * * @return Nothing. */ void setOperator(String operator) { this.operator = operator; this.operatorType = -1; } /** * Set the methodName. * * @param methodName The methodName. * * @return Nothing. */ void setMethodName(String methodName) { this.methodName = methodName; this.operatorType = -1; } /** * Set the interface type for the left and right arguments. * Used when we don't know the interface type until * later in binding. * * @return void */ public void setLeftRightInterfaceType(String iType) { leftInterfaceType = iType; rightInterfaceType = iType; this.operatorType = -1; } /** * Set the clause that this node appears in. * * @param clause The clause that this node appears in. * * @return Nothing. */ public void setClause(int clause) { super.setClause(clause); leftOperand.setClause(clause); rightOperand.setClause(clause); } /** * Prints the sub-nodes of this object. See QueryTreeNode.java for * how tree printing is supposed to work. * * @param depth The depth of this node in the tree * * @return Nothing */ public void printSubNodes(int depth) { if (SanityManager.DEBUG) { super.printSubNodes(depth); if (leftOperand != null) { printLabel(depth, "leftOperand: "); leftOperand.treePrint(depth + 1); } if (rightOperand != null) { printLabel(depth, "rightOperand: "); rightOperand.treePrint(depth + 1); } } } /** * Bind this expression. This means binding the sub-expressions, * as well as figuring out what the return type is for this expression. * * @param fromList The FROM list for the query this * expression is in, for binding columns. * @param subqueryList The subquery list being built as we find SubqueryNodes * @param aggregateVector The aggregate vector being built as we find AggregateNodes * * @return The new top of the expression tree. * * @exception StandardException Thrown on error */ public ValueNode bindExpression( FromList fromList, SubqueryList subqueryList, Vector aggregateVector) throws StandardException { leftOperand = leftOperand.bindExpression(fromList, subqueryList, aggregateVector); rightOperand = rightOperand.bindExpression(fromList, subqueryList, aggregateVector); if (operatorType == XMLEXISTS_OP) return bindXMLExists(); /* Is there a ? parameter on the left? */ if (leftOperand.isParameterNode()) { /* ** It's an error if both operands are ? parameters. */ if (rightOperand.isParameterNode()) { throw StandardException.newException(SQLState.LANG_BINARY_OPERANDS_BOTH_PARMS, operator); } /* Set the left operand to the type of right parameter. */ ((ParameterNode) leftOperand).setDescriptor(rightOperand.getTypeServices()); } /* Is there a ? parameter on the right? */ if (rightOperand.isParameterNode()) { /* Set the right operand to the type of the left parameter. */ ((ParameterNode) rightOperand).setDescriptor(leftOperand.getTypeServices()); } return genSQLJavaSQLTree(); } /** * Bind an XMLEXISTS operator. Makes sure the operand type * and target type are both correct, and sets the result type. * * @exception StandardException Thrown on error */ public ValueNode bindXMLExists() throws StandardException { // Check operand types. TypeId leftOperandType = leftOperand.getTypeId(); TypeId rightOperandType = rightOperand.getTypeId(); // Left operand is query expression, and must be a string. if (leftOperandType != null) { switch (leftOperandType.getJDBCTypeId()) { case Types.CHAR: case Types.VARCHAR: case Types.LONGVARCHAR: case Types.CLOB: break; default: { throw StandardException.newException( SQLState.LANG_BINARY_OPERATOR_NOT_SUPPORTED, methodName, leftOperandType.getSQLTypeName(), rightOperandType.getSQLTypeName()); } } } // Right operand is an XML data value. if ((rightOperandType != null) && !rightOperandType.isXMLTypeId()) { throw StandardException.newException( SQLState.LANG_BINARY_OPERATOR_NOT_SUPPORTED, methodName, leftOperandType.getSQLTypeName(), rightOperandType.getSQLTypeName()); } // Is there a ? parameter on the left? if (leftOperand.isParameterNode()) { // Set the left operand to be a VARCHAR, which should be // long enough to hold the XPath expression. ((ParameterNode) leftOperand).setDescriptor( DataTypeDescriptor.getBuiltInDataTypeDescriptor(Types.VARCHAR)); } // Is there a ? parameter on the right? if (rightOperand.isParameterNode()) { // For now, since JDBC has no type defined for XML, we // don't allow binding to an XML parameter. throw StandardException.newException( SQLState.LANG_ATTEMPT_TO_BIND_XML); } // Set the result type of this XMLExists operator--it's always // SQLBoolean. The "true" in the next line says that the result // can be nullable--which it can be if evaluation of the expression // returns a null (this is per SQL/XML spec section 8.4). setType(new DataTypeDescriptor(TypeId.BOOLEAN_ID, true)); return genSQLJavaSQLTree(); } /** generate a SQL->Java->SQL conversion tree above the left and right * operand of this Binary Operator Node if needed. Subclasses can override * the default behavior.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -