KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2
3    Derby - Class org.apache.derby.impl.sql.compile.ExtractOperatorNode
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.compile.C_NodeTypes;
25
26 import org.apache.derby.iapi.sql.dictionary.DataDictionary;
27
28 import org.apache.derby.iapi.types.TypeId;
29 import org.apache.derby.iapi.types.DateTimeDataValue;
30 import org.apache.derby.iapi.types.DataTypeDescriptor;
31
32 import org.apache.derby.iapi.sql.compile.TypeCompiler;
33
34 import org.apache.derby.iapi.reference.SQLState;
35 import org.apache.derby.iapi.error.StandardException;
36
37 import org.apache.derby.iapi.services.sanity.SanityManager;
38
39 import java.sql.Types JavaDoc;
40
41 import java.util.Vector JavaDoc;
42
43 /**
44  * This node represents a unary extract operator, used to extract
45  * a field from a date/time. The field value is returned as an integer.
46  *
47  * @author ames
48  */

49 public class ExtractOperatorNode extends UnaryOperatorNode {
50
51     static private final String JavaDoc fieldName[] = {
52         "YEAR", "MONTH", "DAY", "HOUR", "MINUTE", "SECOND"
53     };
54     static private final String JavaDoc fieldMethod[] = {
55         "getYear","getMonth","getDate","getHours","getMinutes","getSeconds"
56     };
57
58     private int extractField;
59
60     /**
61      * Initializer for a ExtractOperatorNode
62      *
63      * @param field The field to extract
64      * @param operand The operand
65      */

66     public void init(Object JavaDoc field, Object JavaDoc operand) {
67         extractField = ((Integer JavaDoc) field).intValue();
68         super.init( operand,
69                     "EXTRACT "+fieldName[extractField],
70                     fieldMethod[extractField] );
71     }
72
73     /**
74      * Bind this operator
75      *
76      * @param fromList The query's FROM list
77      * @param subqueryList The subquery list being built as we find SubqueryNodes
78      * @param aggregateVector The aggregate vector being built as we find AggregateNodes
79      *
80      * @return The new top of the expression tree.
81      *
82      * @exception StandardException Thrown on error
83      */

84
85     public ValueNode bindExpression(
86         FromList fromList,
87         SubqueryList subqueryList,
88         Vector JavaDoc aggregateVector)
89             throws StandardException
90     {
91         int operandType;
92         TypeId opTypeId;
93
94         super.bindExpression(fromList, subqueryList,
95                 aggregateVector);
96
97         opTypeId = operand.getTypeId();
98         operandType = opTypeId.getJDBCTypeId();
99         TypeCompiler tc = operand.getTypeCompiler();
100
101         /*
102         ** Cast the operand, if necessary, - this function is allowed only on
103         ** date/time types. By default, we cast to DATE if extracting
104         ** YEAR, MONTH or DAY and to TIME if extracting HOUR, MINUTE or
105         ** SECOND.
106         */

107         if (opTypeId.isStringTypeId())
108         {
109             int castType = (extractField < 3) ? Types.DATE : Types.TIME;
110             operand = (ValueNode)
111                 getNodeFactory().getNode(
112                     C_NodeTypes.CAST_NODE,
113                     operand,
114                     DataTypeDescriptor.getBuiltInDataTypeDescriptor(castType, true,
115                                         tc.getCastToCharWidth(
116                                                 operand.getTypeServices())),
117                     getContextManager());
118             ((CastNode) operand).bindCastNodeOnly();
119
120             opTypeId = operand.getTypeId();
121             operandType = opTypeId.getJDBCTypeId();
122         }
123
124         if ( ! ( ( operandType == Types.DATE )
125                || ( operandType == Types.TIME )
126                || ( operandType == Types.TIMESTAMP )
127             ) ) {
128             throw StandardException.newException(SQLState.LANG_UNARY_FUNCTION_BAD_TYPE,
129                         "EXTRACT "+fieldName[extractField],
130                         opTypeId.getSQLTypeName());
131         }
132
133         /*
134             If the type is DATE, ensure the field is okay.
135          */

136         if ( (operandType == Types.DATE)
137              && (extractField > DateTimeDataValue.DAY_FIELD) ) {
138             throw StandardException.newException(SQLState.LANG_UNARY_FUNCTION_BAD_TYPE,
139                         "EXTRACT "+fieldName[extractField],
140                         opTypeId.getSQLTypeName());
141         }
142
143         /*
144             If the type is TIME, ensure the field is okay.
145          */

146         if ( (operandType == Types.TIME)
147              && (extractField < DateTimeDataValue.HOUR_FIELD) ) {
148             throw StandardException.newException(SQLState.LANG_UNARY_FUNCTION_BAD_TYPE,
149                         "EXTRACT "+fieldName[extractField],
150                         opTypeId.getSQLTypeName());
151         }
152
153         /*
154         ** The result type of extract is int,
155         ** unless it is TIMESTAMP and SECOND, in which case
156         ** for now it is DOUBLE but eventually it will need to
157         ** be DECIMAL(11,9).
158         */

159         if ( (operandType == Types.TIMESTAMP)
160              && (extractField == DateTimeDataValue.SECOND_FIELD) ) {
161             setType(new DataTypeDescriptor(
162                             TypeId.getBuiltInTypeId(Types.DOUBLE),
163                             operand.getTypeServices().isNullable()
164                         )
165                 );
166         } else {
167             setType(new DataTypeDescriptor(
168                             TypeId.INTEGER_ID,
169                             operand.getTypeServices().isNullable()
170                         )
171                 );
172         }
173
174         return this;
175     }
176
177     public String JavaDoc toString() {
178         if (SanityManager.DEBUG)
179         {
180             return super.toString() + "field is "+fieldName[extractField]+"\n";
181         }
182         else
183         {
184             return "";
185         }
186     }
187 }
188
Popular Tags