KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > impl > sql > compile > UnaryArithmeticOperatorNode


1 /*
2
3    Derby - Class org.apache.derby.impl.sql.compile.UnaryArithmeticOperatorNode
4
5    Licensed to the Apache Software Foundation (ASF) under one or more
6    contributor license agreements. See the NOTICE file distributed with
7    this work for additional information regarding copyright ownership.
8    The ASF licenses this file to you under the Apache License, Version 2.0
9    (the "License"); you may not use this file except in compliance with
10    the License. You may obtain a copy of the License at
11
12       http://www.apache.org/licenses/LICENSE-2.0
13
14    Unless required by applicable law or agreed to in writing, software
15    distributed under the License is distributed on an "AS IS" BASIS,
16    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17    See the License for the specific language governing permissions and
18    limitations under the License.
19
20  */

21
22 package org.apache.derby.impl.sql.compile;
23
24 import org.apache.derby.iapi.sql.dictionary.DataDictionary;
25
26 import org.apache.derby.iapi.types.TypeId;
27 import org.apache.derby.iapi.types.DataTypeDescriptor;
28 import org.apache.derby.iapi.reference.SQLState;
29 import org.apache.derby.iapi.error.StandardException;
30
31 import org.apache.derby.iapi.services.compiler.MethodBuilder;
32 import org.apache.derby.iapi.services.sanity.SanityManager;
33 import org.apache.derby.iapi.sql.compile.C_NodeTypes;
34 import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;
35
36 import java.sql.Types JavaDoc;
37 import java.util.Vector JavaDoc;
38
39 /**
40  * This node represents a unary arithmetic operator
41  *
42  * @author Manish Khettry
43  */

44
45 public class UnaryArithmeticOperatorNode extends UnaryOperatorNode
46 {
47     private final static int UNARY_PLUS = 0;
48     private final static int UNARY_MINUS = 1;
49     private final static int SQRT = 2;
50     private final static int ABSOLUTE = 3;
51     private final static String JavaDoc[] UNARY_OPERATORS = {"+","-","SQRT", "ABS/ABSVAL"};
52     private final static String JavaDoc[] UNARY_METHODS = {"plus","minus","sqrt", "absolute"};
53
54     private int operatorType;
55
56     //when the bindExpression method is called during the normal binding phase,
57
//unary minus and unary plus dynamic parameters are not ready for
58
//binding because the type of these dynamic parameters is not yet set.
59
//For eg, consider sql select * from t1 where c1 = -?
60
//bindExpression on -? gets called from BinaryComparisonOperatorNode's
61
//bindExpression but the parameter type has not been set yet for -?
62
//Later on, in BinaryComparisonOperatorNode's bindExpression, the type
63
//of the -? gets set to the type of c1 by the setType call.
64
//Now, at this point, we are ready to finish binding phase for -?
65
//(This class's setType method calls the bindExpression to finish binding)
66
//In order to accomplish binding later on, we need to save the following
67
//3 objects during first call to bindExpression and then later this
68
//gets used in setType method when it calls the bindExpression method.
69
FromList localCopyFromList;
70     SubqueryList localCopySubqueryList;
71     Vector JavaDoc localAggregateVector;
72   
73     /**
74      * Initializer for a UnaryArithmeticOperatorNode
75      *
76      * @param operand The operand of the node
77      */

78     public void init(Object JavaDoc operand)
79     {
80         switch(getNodeType())
81         {
82             case C_NodeTypes.UNARY_PLUS_OPERATOR_NODE:
83                 operatorType = UNARY_PLUS;
84                 break;
85             case C_NodeTypes.UNARY_MINUS_OPERATOR_NODE:
86                 operatorType = UNARY_MINUS;
87                 break;
88             case C_NodeTypes.SQRT_OPERATOR_NODE:
89                 operatorType = SQRT;
90                 break;
91             case C_NodeTypes.ABSOLUTE_OPERATOR_NODE:
92                 operatorType = ABSOLUTE;
93                 break;
94             default:
95                 if (SanityManager.DEBUG)
96                 {
97                     SanityManager.THROWASSERT("init for UnaryArithmeticOperator called with wrong nodeType = " + getNodeType());
98                 }
99                 break;
100         }
101         init(operand, UNARY_OPERATORS[this.operatorType],
102                 UNARY_METHODS[this.operatorType]);
103     }
104
105     /**
106      * By default unary operators don't accept ? parameters as operands.
107      * This can be over-ridden for particular unary operators.
108      *
109      * We throw an exception if the parameter doesn't have a datatype
110      * assigned to it yet.
111      *
112      * @exception StandardException Thrown if ? parameter doesn't
113      * have a type bound to it yet.
114      * ? parameter where it isn't allowed.
115      */

116
117     void bindParameter() throws StandardException
118     {
119         if (operatorType == SQRT || operatorType == ABSOLUTE)
120         {
121             operand.setType(
122                 new DataTypeDescriptor(TypeId.getBuiltInTypeId(Types.DOUBLE), true));
123         }
124         //Derby-582 add support for dynamic parameter for unary plus and minus
125
else if (operatorType == UNARY_MINUS || operatorType == UNARY_PLUS)
126             return;
127         else if (operand.getTypeServices() == null)
128         {
129             throw StandardException.newException(SQLState.LANG_UNARY_OPERAND_PARM, operator);
130         }
131     }
132     /**
133      * Bind this operator
134      *
135      * @param fromList The query's FROM list
136      * @param subqueryList The subquery list being built as we find SubqueryNodes
137      * @param aggregateVector The aggregate vector being built as we find AggregateNodes
138      *
139      * @return The new top of the expression tree.
140      *
141      * @exception StandardException Thrown on error
142      */

143
144     public ValueNode bindExpression(
145         FromList fromList, SubqueryList subqueryList,
146         Vector JavaDoc aggregateVector)
147             throws StandardException
148     {
149         localCopyFromList = fromList;
150         localCopySubqueryList = subqueryList;
151         localAggregateVector = aggregateVector;
152         //Return with no binding, if the type of unary minus/plus parameter is not set yet.
153
if (operand.requiresTypeFromContext() && ((operatorType == UNARY_PLUS || operatorType == UNARY_MINUS))
154                 && operand.getTypeServices() == null)
155                 return this;
156
157         super.bindExpression(fromList, subqueryList,
158                 aggregateVector);
159
160         if (operatorType == SQRT || operatorType == ABSOLUTE)
161         {
162             bindSQRTABS();
163         }
164         else if (operatorType == UNARY_PLUS || operatorType == UNARY_MINUS)
165         {
166             TypeId operandType = operand.getTypeId();
167
168             if ( ! operandType.isNumericTypeId())
169             {
170             
171                 throw StandardException.newException(SQLState.LANG_UNARY_ARITHMETIC_BAD_TYPE,
172                     (operatorType == UNARY_PLUS) ? "+" : "-",
173                     operandType.getSQLTypeName());
174             }
175         }
176         /*
177         ** The result type of a +, -, SQRT, ABS is the same as its operand.
178         */

179         super.setType(operand.getTypeServices());
180         return this;
181     }
182
183     /**
184      * Do code generation for this unary plus operator
185      *
186      * @param acb The ExpressionClassBuilder for the class we're generating
187      * @param mb The method the expression will go into
188      *
189      * @exception StandardException Thrown on error
190      */

191
192     public void generateExpression(ExpressionClassBuilder acb,
193                                             MethodBuilder mb)
194                                     throws StandardException
195     {
196         /* Unary + doesn't do anything. Just return the operand */
197         if (operatorType == UNARY_PLUS)
198             operand.generateExpression(acb, mb);
199         else
200             super.generateExpression(acb, mb);
201     }
202     /**
203      * Bind SQRT or ABS
204      *
205      * @exception StandardException Thrown on error
206      */

207     private void bindSQRTABS()
208             throws StandardException
209     {
210         TypeId operandType;
211         int jdbcType;
212
213         /*
214         ** Check the type of the operand
215         */

216         operandType = operand.getTypeId();
217
218         /*
219          * If the operand is not a build-in type, generate a bound conversion
220          * tree to build-in types.
221          */

222         if (operandType.userType() )
223         {
224             operand = operand.genSQLJavaSQLTree();
225         }
226         /* DB2 doesn't cast string types to numeric types for numeric functions */
227
228         jdbcType = operandType.getJDBCTypeId();
229
230         /* Both SQRT and ABS are only allowed on numeric types */
231         if (!operandType.isNumericTypeId())
232             throw StandardException.newException(
233                         SQLState.LANG_UNARY_FUNCTION_BAD_TYPE,
234                         getOperatorString(), operandType.getSQLTypeName());
235
236         /* For SQRT, if operand is not a DOUBLE, convert it to DOUBLE */
237         if (operatorType == SQRT && jdbcType != Types.DOUBLE)
238         {
239             operand = (ValueNode) getNodeFactory().getNode(
240                     C_NodeTypes.CAST_NODE,
241                     operand,
242                     new DataTypeDescriptor(TypeId.getBuiltInTypeId(Types.DOUBLE), true),
243                     getContextManager());
244             ((CastNode) operand).bindCastNodeOnly();
245         }
246     }
247
248     /** @see ValueNode#setType */
249     /* We are overwriting this method here because for -?/+?, we now know
250     the type of these dynamic parameters and hence we can do the parameter
251     binding. The setType method will call the binding code after setting
252     the type of the parameter*/

253     public void setType(DataTypeDescriptor descriptor) throws StandardException
254     {
255         operand.setType(descriptor);
256         super.setType(descriptor);
257         //Derby-582 add support for dynamic parameters for unary plus and minus
258
//Now that we know the type of this parameter node, we can do the
259
//binding.
260
bindExpression(localCopyFromList, localCopySubqueryList, localAggregateVector);
261     }
262 }
263
Popular Tags