1 | /* ============================================================= |
2 | * SmallSQL : a free Java DBMS library for the Java(tm) platform |
3 | * ============================================================= |
4 | * |
5 | * (C) Copyright 2004-2006, by Volker Berlin. |
6 | * |
7 | * Project Info: http://www.smallsql.de/ |
8 | * |
9 | * This library is free software; you can redistribute it and/or modify it |
10 | * under the terms of the GNU Lesser General Public License as published by |
11 | * the Free Software Foundation; either version 2.1 of the License, or |
12 | * (at your option) any later version. |
13 | * |
14 | * This library is distributed in the hope that it will be useful, but |
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
16 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public |
17 | * License for more details. |
18 | * |
19 | * You should have received a copy of the GNU Lesser General Public |
20 | * License along with this library; if not, write to the Free Software |
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, |
22 | * USA. |
23 | * |
24 | * [Java is a trademark or registered trademark of Sun Microsystems, Inc. |
25 | * in the United States and other countries.] |
26 | * |
27 | * --------------- |
28 | * ExpressionFunctionConvert.java |
29 | * --------------- |
30 | * Author: Volker Berlin |
31 | * |
32 | * Created on 29.04.2004 |
33 | */ |
34 | package smallsql.database; |
35 | |
36 | import java.util.Arrays; |
37 | |
38 | |
39 | /** |
40 | * @author Volker Berlin |
41 | */ |
42 | public class ExpressionFunctionConvert extends ExpressionFunction { |
43 | |
44 | final private Column datatype; |
45 | |
46 | public ExpressionFunctionConvert(Column datatype, Expression value, Expression style) { |
47 | super(); |
48 | this.datatype = datatype; |
49 | Expression[] params = (style == null) ? new Expression[]{value} : new Expression[]{value, style}; |
50 | setParams( params ); |
51 | } |
52 | |
53 | |
54 | int getFunction() { |
55 | return SQLTokenizer.CONVERT; |
56 | } |
57 | |
58 | |
59 | boolean isNull() throws Exception { |
60 | return param1.isNull(); |
61 | } |
62 | |
63 | |
64 | boolean getBoolean() throws Exception { |
65 | return ExpressionValue.getBoolean( getObject(), getDataType() ); |
66 | } |
67 | |
68 | |
69 | int getInt() throws Exception { |
70 | return ExpressionValue.getInt( getObject(), getDataType() ); |
71 | } |
72 | |
73 | |
74 | long getLong() throws Exception { |
75 | return ExpressionValue.getLong( getObject(), getDataType() ); |
76 | } |
77 | |
78 | |
79 | float getFloat() throws Exception { |
80 | return ExpressionValue.getFloat( getObject(), getDataType() ); |
81 | } |
82 | |
83 | |
84 | double getDouble() throws Exception { |
85 | return ExpressionValue.getDouble( getObject(), getDataType() ); |
86 | } |
87 | |
88 | |
89 | long getMoney() throws Exception { |
90 | return ExpressionValue.getMoney(getObject(), getDataType()); |
91 | } |
92 | |
93 | |
94 | MutableNumeric getNumeric() throws Exception { |
95 | return ExpressionValue.getNumeric(getObject(), getDataType()); |
96 | } |
97 | |
98 | |
99 | String getString() throws Exception { |
100 | Object obj = getObject(); |
101 | if(obj == null) return null; |
102 | switch(datatype.getDataType()){ |
103 | case SQLTokenizer.BIT: |
104 | return ((Boolean)obj).booleanValue() ? "1" : "0"; |
105 | } |
106 | return obj.toString(); |
107 | } |
108 | |
109 | |
110 | Object getObject() throws Exception { |
111 | if(param1.isNull()) return null; |
112 | final int dataType = getDataType(); |
113 | switch(dataType){ |
114 | case SQLTokenizer.LONGVARCHAR: |
115 | return convertToString(); |
116 | case SQLTokenizer.VARCHAR:{ |
117 | String str = convertToString(); |
118 | int length = datatype.getDisplaySize(); |
119 | if(length > str.length()) |
120 | return str; |
121 | return str.substring(0,length); |
122 | } |
123 | case SQLTokenizer.CHAR:{ |
124 | String str = convertToString(); |
125 | int length = datatype.getDisplaySize(); |
126 | if(length > str.length()){ |
127 | char[] buffer = new char[length-str.length()]; |
128 | Arrays.fill(buffer, ' '); |
129 | return str + new String(buffer); |
130 | } |
131 | return str.substring(0,length); |
132 | } |
133 | case SQLTokenizer.LONGVARBINARY: |
134 | return param1.getBytes(); |
135 | case SQLTokenizer.VARBINARY:{ |
136 | byte[] bytes = param1.getBytes(); |
137 | int length = datatype.getPrecision(); |
138 | if(length < bytes.length){ |
139 | byte[] buffer = new byte[length]; |
140 | System.arraycopy(bytes, 0, buffer, 0, Math.min(bytes.length,length) ); |
141 | return buffer; |
142 | } |
143 | return bytes; |
144 | |
145 | } |
146 | case SQLTokenizer.BINARY:{ |
147 | byte[] bytes = param1.getBytes(); |
148 | int length = datatype.getPrecision(); |
149 | if(length != bytes.length){ |
150 | byte[] buffer = new byte[length]; |
151 | System.arraycopy(bytes, 0, buffer, 0, Math.min(bytes.length,length) ); |
152 | return buffer; |
153 | } |
154 | return bytes; |
155 | |
156 | } |
157 | case SQLTokenizer.BOOLEAN: |
158 | case SQLTokenizer.BIT: |
159 | return param1.getBoolean() ? Boolean.TRUE : Boolean.FALSE; |
160 | case SQLTokenizer.TINYINT: |
161 | return Utils.getInteger(param1.getInt() & 0xFF); |
162 | case SQLTokenizer.SMALLINT: |
163 | return Utils.getInteger((short)param1.getInt()); |
164 | case SQLTokenizer.INT: |
165 | return Utils.getInteger(param1.getInt()); |
166 | case SQLTokenizer.BIGINT: |
167 | return new Long(param1.getLong()); |
168 | case SQLTokenizer.REAL: |
169 | return new Float(param1.getFloat()); |
170 | case SQLTokenizer.FLOAT: |
171 | case SQLTokenizer.DOUBLE: |
172 | return new Double(param1.getDouble()); |
173 | case SQLTokenizer.DATE: |
174 | case SQLTokenizer.TIME: |
175 | case SQLTokenizer.TIMESTAMP: |
176 | case SQLTokenizer.SMALLDATETIME: |
177 | return new DateTime( getDateTimeLong(), dataType ); |
178 | case SQLTokenizer.NUMERIC: |
179 | case SQLTokenizer.DECIMAL: |
180 | MutableNumeric num = param1.getNumeric(); |
181 | if(num != null && (dataType == SQLTokenizer.NUMERIC || dataType == SQLTokenizer.DECIMAL)) |
182 | num.setScale(getScale()); |
183 | return num; |
184 | case SQLTokenizer.MONEY: |
185 | case SQLTokenizer.SMALLMONEY: |
186 | return Money.createFromUnscaledValue(param1.getMoney()); |
187 | case SQLTokenizer.UNIQUEIDENTIFIER: |
188 | switch(param1.getDataType()){ |
189 | case SQLTokenizer.VARCHAR: |
190 | case SQLTokenizer.CHAR: |
191 | case SQLTokenizer.LONGVARCHAR: |
192 | case SQLTokenizer.CLOB: |
193 | return Utils.bytes2unique( Utils.unique2bytes(param1.getString()), 0); |
194 | } |
195 | return Utils.bytes2unique(param1.getBytes(), 0); |
196 | } |
197 | throw Utils.createSQLException("Unsupported type for CONVERT function:"+SQLTokenizer.getKeyWord(dataType)); |
198 | } |
199 | |
200 | |
201 | final private String convertToString() throws Exception{ |
202 | if(param2 != null){ |
203 | int type = param1.getDataType(); |
204 | switch(type){ |
205 | case SQLTokenizer.SMALLDATETIME: |
206 | type = SQLTokenizer.TIMESTAMP; |
207 | case SQLTokenizer.TIMESTAMP: |
208 | case SQLTokenizer.DATE: |
209 | case SQLTokenizer.TIME: |
210 | return new DateTime( param1.getLong(), type ).toString(param2.getInt()); |
211 | default: |
212 | return param1.getString(); |
213 | } |
214 | //TODO Format for MONEY, REAL and DOUBLE |
215 | }else |
216 | return param1.getString(); |
217 | } |
218 | |
219 | |
220 | final private long getDateTimeLong() throws Exception{ |
221 | //try{ |
222 | switch(param1.getDataType()){ |
223 | case SQLTokenizer.LONGVARCHAR: |
224 | case SQLTokenizer.VARCHAR: |
225 | case SQLTokenizer.CHAR: |
226 | return DateTime.parse( param1.getString() ); |
227 | } |
228 | //}catch(Exception e){/* do nothing */} |
229 | return param1.getLong(); |
230 | } |
231 | |
232 | |
233 | final int getDataType() { |
234 | return datatype.getDataType(); |
235 | } |
236 | |
237 | |
238 | final int getPrecision(){ |
239 | final int dataType = getDataType(); |
240 | switch(dataType){ |
241 | case SQLTokenizer.VARCHAR: |
242 | case SQLTokenizer.VARBINARY: |
243 | case SQLTokenizer.BINARY: |
244 | case SQLTokenizer.CHAR: |
245 | case SQLTokenizer.NUMERIC: |
246 | case SQLTokenizer.DECIMAL: |
247 | return datatype.getPrecision(); |
248 | default: |
249 | return super.getPrecision(); |
250 | } |
251 | } |
252 | |
253 | |
254 | final int getScale() { |
255 | return datatype.getScale(); |
256 | } |
257 | |
258 | |
259 | } |