File D:\maven-qcr-plugin-testsunitaires\qcr4java\h2-1.3.170-sources\target\site\qc\lecode\value\DataType.java.html

1 /*
2 * Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
3 * Version 1.0, and under the Eclipse Public License, Version 1.0
4 * (http://h2database.com/html/license.html).
5 * Initial Developer: H2 Group
6 */
7 package org.h2.value;
8
9 import java.io.BufferedReader;
10 import java.io.InputStream;
11 import java.io.Reader;
12 import java.math.BigDecimal;
13 import java.sql.Array;
14 import java.sql.Blob;
15 import java.sql.Clob;
16 import java.sql.Date;
17 import java.sql.ResultSet;
18 import java.sql.SQLException;
19 import java.sql.Time;
20 import java.sql.Timestamp;
21 import java.sql.Types;
22 import java.util.ArrayList;
23 import java.util.HashMap;
24 import java.util.UUID;
25 import org.h2.constant.ErrorCode;
26 import org.h2.constant.SysProperties;
27 import org.h2.engine.SessionInterface;
28 import org.h2.jdbc.JdbcBlob;
29 import org.h2.jdbc.JdbcClob;
30 import org.h2.jdbc.JdbcConnection;
31 import org.h2.message.DbException;
32 import org.h2.store.LobStorage;
33 import org.h2.tools.SimpleResultSet;
34 import org.h2.util.New;
35 import org.h2.util.StringUtils;
36 import org.h2.util.Utils;
37
38 /**
39 * This class contains meta data information about data types,
40 * and can convert between Java objects and Values.
41 */
42 public class DataType {
43
44 /**
45 * This constant is used to represent the type of a ResultSet. There is no
46 * equivalent java.sql.Types value, but Oracle uses it to represent a
47 * ResultSet (OracleTypes.CURSOR = -10).
48 */
49 public static final int TYPE_RESULT_SET = -10;
50
51 /**
52 * This constant is used for JDK 1.5 compatibility
53 * and equal to java.sql.Types.LONGNVARCHAR
54 */
55 public static final int TYPE_LONGNVARCHAR = -16;
56
57 /**
58 * This constant is used for JDK 1.5 compatibility
59 * and equal to java.sql.Types.NCHAR
60 */
61 public static final int TYPE_NCHAR = -15;
62
63 /**
64 * This constant is used for JDK 1.5 compatibility
65 * and equal to java.sql.Types.NVARCHAR
66 */
67 public static final int TYPE_NVARCHAR = -9;
68
69 /**
70 * This constant is used for JDK 1.5 compatibility
71 * and equal to java.sql.Types.NCLOB
72 */
73 public static final int TYPE_NCLOB = 2011;
74
75 /**
76 * The list of types. An ArrayList so that Tomcat doesn't set it to null
77 * when clearing references.
78 */
79 private static final ArrayList<DataType> TYPES = New.arrayList();
80 private static final HashMap<String, DataType> TYPES_BY_NAME = New.hashMap();
81 private static final ArrayList<DataType> TYPES_BY_VALUE_TYPE = New.arrayList();
82
83 /**
84 * The value type of this data type.
85 */
86 public int type;
87
88 /**
89 * The data type name.
90 */
91 public String name;
92
93 /**
94 * The SQL type.
95 */
96 public int sqlType;
97
98 /**
99 * The Java class name.
100 */
101 public String jdbc;
102
103 /**
104 * How closely the data type maps to the corresponding JDBC SQL type (low is
105 * best).
106 */
107 public int sqlTypePos;
108
109 /**
110 * The maximum supported precision.
111 */
112 public long maxPrecision;
113
114 /**
115 * The lowest possible scale.
116 */
117 public int minScale;
118
119 /**
120 * The highest possible scale.
121 */
122 public int maxScale;
123
124 /**
125 * If this is a numeric type.
126 */
127 public boolean decimal;
128
129 /**
130 * The prefix required for the SQL literal representation.
131 */
132 public String prefix;
133
134 /**
135 * The suffix required for the SQL literal representation.
136 */
137 public String suffix;
138
139 /**
140 * The list of parameters used in the column definition.
141 */
142 public String params;
143
144 /**
145 * If this is an autoincrement type.
146 */
147 public boolean autoIncrement;
148
149 /**
150 * If this data type is an autoincrement type.
151 */
152 public boolean caseSensitive;
153
154 /**
155 * If the precision parameter is supported.
156 */
157 public boolean supportsPrecision;
158
159 /**
160 * If the scale parameter is supported.
161 */
162 public boolean supportsScale;
163
164 /**
165 * The default precision.
166 */
167 public long defaultPrecision;
168
169 /**
170 * The default scale.
171 */
172 public int defaultScale;
173
174 /**
175 * The default display size.
176 */
177 public int defaultDisplaySize;
178
179 /**
180 * If this data type should not be listed in the database meta data.
181 */
182 public boolean hidden;
183
184 /**
185 * The number of bytes required for an object.
186 */
187 public int memory;
188
189 static {
190 for (int i = 0; i < Value.TYPE_COUNT; i++) {
191 TYPES_BY_VALUE_TYPE.add(null);
192 }
193 add(Value.NULL, Types.NULL, "Null",
194 new DataType(),
195 new String[]{"NULL"},
196 // the value is always in the cache
197 0
198 );
199 add(Value.STRING, Types.VARCHAR, "String",
200 createString(true),
201 new String[]{"VARCHAR", "VARCHAR2", "NVARCHAR", "NVARCHAR2", "VARCHAR_CASESENSITIVE", "CHARACTER VARYING", "TID"},
202 // 24 for ValueString, 24 for String
203 48
204 );
205 add(Value.STRING, Types.LONGVARCHAR, "String",
206 createString(true),
207 new String[]{"LONGVARCHAR", "LONGNVARCHAR"},
208 48
209 );
210 add(Value.STRING_FIXED, Types.CHAR, "String",
211 createString(true),
212 new String[]{"CHAR", "CHARACTER", "NCHAR"},
213 48
214 );
215 add(Value.STRING_IGNORECASE, Types.VARCHAR, "String",
216 createString(false),
217 new String[]{"VARCHAR_IGNORECASE"},
218 48
219 );
220 add(Value.BOOLEAN, Types.BOOLEAN, "Boolean",
221 createDecimal(ValueBoolean.PRECISION, ValueBoolean.PRECISION, 0, ValueBoolean.DISPLAY_SIZE, false, false),
222 new String[]{"BOOLEAN", "BIT", "BOOL"},
223 // the value is always in the cache
224 0
225 );
226 add(Value.BYTE, Types.TINYINT, "Byte",
227 createDecimal(ValueByte.PRECISION, ValueByte.PRECISION, 0, ValueByte.DISPLAY_SIZE, false, false),
228 new String[]{"TINYINT"},
229 // the value is almost always in the cache
230 1
231 );
232 add(Value.SHORT, Types.SMALLINT, "Short",
233 createDecimal(ValueShort.PRECISION, ValueShort.PRECISION, 0, ValueShort.DISPLAY_SIZE, false, false),
234 new String[]{"SMALLINT", "YEAR", "INT2"},
235 // in many cases the value is in the cache
236 20
237 );
238 add(Value.INT, Types.INTEGER, "Int",
239 createDecimal(ValueInt.PRECISION, ValueInt.PRECISION, 0,
240 ValueInt.DISPLAY_SIZE, false, false),
241 new String[]{"INTEGER", "INT", "MEDIUMINT", "INT4", "SIGNED"},
242 // in many cases the value is in the cache
243 20
244 );
245 add(Value.LONG, Types.BIGINT, "Long",
246 createDecimal(ValueLong.PRECISION, ValueLong.PRECISION, 0,
247 ValueLong.DISPLAY_SIZE, false, false),
248 new String[]{"BIGINT", "INT8", "LONG"},
249 24
250 );
251 add(Value.LONG, Types.BIGINT, "Long",
252 createDecimal(ValueLong.PRECISION, ValueLong.PRECISION, 0,
253 ValueLong.DISPLAY_SIZE, false, true),
254 new String[]{"IDENTITY", "SERIAL"},
255 24
256 );
257 add(Value.DECIMAL, Types.DECIMAL, "BigDecimal",
258 createDecimal(Integer.MAX_VALUE, ValueDecimal.DEFAULT_PRECISION,
259 ValueDecimal.DEFAULT_SCALE, ValueDecimal.DEFAULT_DISPLAY_SIZE, true, false),
260 new String[]{"DECIMAL", "DEC"},
261 // 40 for ValueDecimal,
262 64
263 );
264 add(Value.DECIMAL, Types.NUMERIC, "BigDecimal",
265 createDecimal(Integer.MAX_VALUE, ValueDecimal.DEFAULT_PRECISION,
266 ValueDecimal.DEFAULT_SCALE, ValueDecimal.DEFAULT_DISPLAY_SIZE, true, false),
267 new String[]{"NUMERIC", "NUMBER"},
268 64
269 );
270 add(Value.FLOAT, Types.REAL, "Float",
271 createDecimal(ValueFloat.PRECISION, ValueFloat.PRECISION,
272 0, ValueFloat.DISPLAY_SIZE, false, false),
273 new String[] {"REAL", "FLOAT4"},
274 24
275 );
276 add(Value.DOUBLE, Types.DOUBLE, "Double",
277 createDecimal(ValueDouble.PRECISION, ValueDouble.PRECISION,
278 0, ValueDouble.DISPLAY_SIZE, false, false),
279 new String[] { "DOUBLE", "DOUBLE PRECISION" },
280 24
281 );
282 add(Value.DOUBLE, Types.FLOAT, "Double",
283 createDecimal(ValueDouble.PRECISION, ValueDouble.PRECISION,
284 0, ValueDouble.DISPLAY_SIZE, false, false),
285 new String[] {"FLOAT", "FLOAT8" },
286 24
287 );
288 add(Value.TIME, Types.TIME, "Time",
289 createDate(ValueTime.PRECISION, "TIME", 0, ValueTime.DISPLAY_SIZE),
290 new String[]{"TIME"},
291 // 24 for ValueTime, 32 for java.sql.Time
292 56
293 );
294 add(Value.DATE, Types.DATE, "Date",
295 createDate(ValueDate.PRECISION, "DATE", 0, ValueDate.DISPLAY_SIZE),
296 new String[]{"DATE"},
297 // 24 for ValueDate, 32 for java.sql.Data
298 56
299 );
300 add(Value.TIMESTAMP, Types.TIMESTAMP, "Timestamp",
301 createDate(ValueTimestamp.PRECISION, "TIMESTAMP", ValueTimestamp.DEFAULT_SCALE, ValueTimestamp.DISPLAY_SIZE),
302 new String[]{"TIMESTAMP", "DATETIME", "SMALLDATETIME"},
303 // 24 for ValueTimestamp, 32 for java.sql.Timestamp
304 56
305 );
306 add(Value.BYTES, Types.VARBINARY, "Bytes",
307 createString(false),
308 new String[]{"VARBINARY"},
309 32
310 );
311 add(Value.BYTES, Types.BINARY, "Bytes",
312 createString(false),
313 new String[]{"BINARY", "RAW", "BYTEA", "LONG RAW"},
314 32
315 );
316 add(Value.BYTES, Types.LONGVARBINARY, "Bytes",
317 createString(false),
318 new String[]{"LONGVARBINARY"},
319 32
320 );
321 add(Value.UUID, Types.BINARY, "Bytes",
322 createString(false),
323 new String[]{"UUID"},
324 32
325 );
326 add(Value.JAVA_OBJECT, Types.OTHER, "Object",
327 createString(false),
328 new String[]{"OTHER", "OBJECT", "JAVA_OBJECT"},
329 24
330 );
331 add(Value.BLOB, Types.BLOB, "Blob",
332 createLob(),
333 new String[]{"BLOB", "TINYBLOB", "MEDIUMBLOB", "LONGBLOB", "IMAGE", "OID"},
334 // 80 for ValueLob, 24 for String
335 104
336 );
337 add(Value.CLOB, Types.CLOB, "Clob",
338 createLob(),
339 new String[]{"CLOB", "TINYTEXT", "TEXT", "MEDIUMTEXT", "LONGTEXT", "NTEXT", "NCLOB"},
340 // 80 for ValueLob, 24 for String
341 104
342 );
343 DataType dataType = new DataType();
344 dataType.prefix = "(";
345 dataType.suffix = "')";
346 add(Value.ARRAY, Types.ARRAY, "Array",
347 dataType,
348 new String[]{"ARRAY"},
349 32
350 );
351 dataType = new DataType();
352 add(Value.RESULT_SET, DataType.TYPE_RESULT_SET, "ResultSet",
353 dataType,
354 new String[]{"RESULT_SET"},
355 400
356 );
357 for (int i = 0, size = TYPES_BY_VALUE_TYPE.size(); i < size; i++) {
358 DataType dt = TYPES_BY_VALUE_TYPE.get(i);
359 if (dt == null) {
360 DbException.throwInternalError("unmapped type " + i);
361 }
362 Value.getOrder(i);
363 }
364 }
365
366 private static void add(int type, int sqlType, String jdbc, DataType dataType, String[] names, int memory) {
367 for (int i = 0; i < names.length; i++) {
368 DataType dt = new DataType();
369 dt.type = type;
370 dt.sqlType = sqlType;
371 dt.jdbc = jdbc;
372 dt.name = names[i];
373 dt.autoIncrement = dataType.autoIncrement;
374 dt.decimal = dataType.decimal;
375 dt.maxPrecision = dataType.maxPrecision;
376 dt.maxScale = dataType.maxScale;
377 dt.minScale = dataType.minScale;
378 dt.params = dataType.params;
379 dt.prefix = dataType.prefix;
380 dt.suffix = dataType.suffix;
381 dt.supportsPrecision = dataType.supportsPrecision;
382 dt.supportsScale = dataType.supportsScale;
383 dt.defaultPrecision = dataType.defaultPrecision;
384 dt.defaultScale = dataType.defaultScale;
385 dt.defaultDisplaySize = dataType.defaultDisplaySize;
386 dt.caseSensitive = dataType.caseSensitive;
387 dt.hidden = i > 0;
388 dt.memory = memory;
389 for (DataType t2 : TYPES) {
390 if (t2.sqlType == dt.sqlType) {
391 dt.sqlTypePos++;
392 }
393 }
394 TYPES_BY_NAME.put(dt.name, dt);
395 if (TYPES_BY_VALUE_TYPE.get(type) == null) {
396 TYPES_BY_VALUE_TYPE.set(type, dt);
397 }
398 TYPES.add(dt);
399 }
400 }
401
402 private static DataType createDecimal(int maxPrecision,
403 int defaultPrecision, int defaultScale, int defaultDisplaySize,
404 boolean needsPrecisionAndScale, boolean autoInc) {
405 DataType dataType = new DataType();
406 dataType.maxPrecision = maxPrecision;
407 dataType.defaultPrecision = defaultPrecision;
408 dataType.defaultScale = defaultScale;
409 dataType.defaultDisplaySize = defaultDisplaySize;
410 if (needsPrecisionAndScale) {
411 dataType.params = "PRECISION,SCALE";
412 dataType.supportsPrecision = true;
413 dataType.supportsScale = true;
414 }
415 dataType.decimal = true;
416 dataType.autoIncrement = autoInc;
417 return dataType;
418 }
419
420 private static DataType createDate(int precision, String prefix, int scale, int displaySize) {
421 DataType dataType = new DataType();
422 dataType.prefix = prefix + " '";
423 dataType.suffix = "'";
424 dataType.maxPrecision = precision;
425 dataType.supportsScale = scale != 0;
426 dataType.maxScale = scale;
427 dataType.defaultPrecision = precision;
428 dataType.defaultScale = scale;
429 dataType.defaultDisplaySize = displaySize;
430 return dataType;
431 }
432
433 private static DataType createString(boolean caseSensitive) {
434 DataType dataType = new DataType();
435 dataType.prefix = "'";
436 dataType.suffix = "'";
437 dataType.params = "LENGTH";
438 dataType.caseSensitive = caseSensitive;
439 dataType.supportsPrecision = true;
440 dataType.maxPrecision = Integer.MAX_VALUE;
441 dataType.defaultPrecision = Integer.MAX_VALUE;
442 dataType.defaultDisplaySize = Integer.MAX_VALUE;
443 return dataType;
444 }
445
446 private static DataType createLob() {
447 DataType t = createString(true);
448 t.maxPrecision = Long.MAX_VALUE;
449 t.defaultPrecision = Long.MAX_VALUE;
450 return t;
451 }
452
453 /**
454 * Get the list of data types.
455 *
456 * @return the list
457 */
458 public static ArrayList<DataType> getTypes() {
459 return TYPES;
460 }
461
462 /**
463 * Read a value from the given result set.
464 *
465 * @param session the session
466 * @param rs the result set
467 * @param columnIndex the column index (1 based)
468 * @param type the data type
469 * @return the value
470 */
471 public static Value readValue(SessionInterface session, ResultSet rs, int columnIndex, int type) {
472 try {
473 Value v;
474 switch(type) {
475 case Value.NULL: {
476 return ValueNull.INSTANCE;
477 }
478 case Value.BYTES: {
479 byte[] buff = rs.getBytes(columnIndex);
480 v = buff == null ? (Value) ValueNull.INSTANCE : ValueBytes.getNoCopy(buff);
481 break;
482 }
483 case Value.UUID: {
484 byte[] buff = rs.getBytes(columnIndex);
485 v = buff == null ? (Value) ValueNull.INSTANCE : ValueUuid.get(buff);
486 break;
487 }
488 case Value.BOOLEAN: {
489 boolean value = rs.getBoolean(columnIndex);
490 v = rs.wasNull() ? (Value) ValueNull.INSTANCE : ValueBoolean.get(value);
491 break;
492 }
493 case Value.BYTE: {
494 byte value = rs.getByte(columnIndex);
495 v = rs.wasNull() ? (Value) ValueNull.INSTANCE : ValueByte.get(value);
496 break;
497 }
498 case Value.DATE: {
499 Date value = rs.getDate(columnIndex);
500 v = value == null ? (Value) ValueNull.INSTANCE : ValueDate.get(value);
501 break;
502 }
503 case Value.TIME: {
504 Time value = rs.getTime(columnIndex);
505 v = value == null ? (Value) ValueNull.INSTANCE : ValueTime.get(value);
506 break;
507 }
508 case Value.TIMESTAMP: {
509 Timestamp value = rs.getTimestamp(columnIndex);
510 v = value == null ? (Value) ValueNull.INSTANCE : ValueTimestamp.get(value);
511 break;
512 }
513 case Value.DECIMAL: {
514 BigDecimal value = rs.getBigDecimal(columnIndex);
515 v = value == null ? (Value) ValueNull.INSTANCE : ValueDecimal.get(value);
516 break;
517 }
518 case Value.DOUBLE: {
519 double value = rs.getDouble(columnIndex);
520 v = rs.wasNull() ? (Value) ValueNull.INSTANCE : ValueDouble.get(value);
521 break;
522 }
523 case Value.FLOAT: {
524 float value = rs.getFloat(columnIndex);
525 v = rs.wasNull() ? (Value) ValueNull.INSTANCE : ValueFloat.get(value);
526 break;
527 }
528 case Value.INT: {
529 int value = rs.getInt(columnIndex);
530 v = rs.wasNull() ? (Value) ValueNull.INSTANCE : ValueInt.get(value);
531 break;
532 }
533 case Value.LONG: {
534 long value = rs.getLong(columnIndex);
535 v = rs.wasNull() ? (Value) ValueNull.INSTANCE : ValueLong.get(value);
536 break;
537 }
538 case Value.SHORT: {
539 short value = rs.getShort(columnIndex);
540 v = rs.wasNull() ? (Value) ValueNull.INSTANCE : ValueShort.get(value);
541 break;
542 }
543 case Value.STRING_IGNORECASE: {
544 String s = rs.getString(columnIndex);
545 v = (s == null) ? (Value) ValueNull.INSTANCE : ValueStringIgnoreCase.get(s);
546 break;
547 }
548 case Value.STRING_FIXED: {
549 String s = rs.getString(columnIndex);
550 v = (s == null) ? (Value) ValueNull.INSTANCE : ValueStringFixed.get(s);
551 break;
552 }
553 case Value.STRING: {
554 String s = rs.getString(columnIndex);
555 v = (s == null) ? (Value) ValueNull.INSTANCE : ValueString.get(s);
556 break;
557 }
558 case Value.CLOB: {
559 if (session == null) {
560 v = LobStorage.createSmallLob(Value.CLOB, StringUtils.utf8Encode(rs.getString(columnIndex)));
561 } else {
562 Reader in = rs.getCharacterStream(columnIndex);
563 if (in == null) {
564 v = ValueNull.INSTANCE;
565 } else {
566 v = session.getDataHandler().getLobStorage().createClob(new BufferedReader(in), -1);
567 }
568 }
569 break;
570 }
571 case Value.BLOB: {
572 if (session == null) {
573 v = LobStorage.createSmallLob(Value.BLOB, rs.getBytes(columnIndex));
574 } else {
575 InputStream in = rs.getBinaryStream(columnIndex);
576 v = (in == null) ? (Value) ValueNull.INSTANCE : session.getDataHandler().getLobStorage().createBlob(in, -1);
577 }
578 break;
579 }
580 case Value.JAVA_OBJECT: {
581 if (SysProperties.serializeJavaObject) {
582 byte[] buff = rs.getBytes(columnIndex);
583 v = buff == null ? ValueNull.INSTANCE : ValueJavaObject.getNoCopy(null, buff);
584 } else {
585 Object o = rs.getObject(columnIndex);
586 v = o == null ? ValueNull.INSTANCE : ValueJavaObject.getNoCopy(o, null);
587 }
588 break;
589 }
590 case Value.ARRAY: {
591 Array array = rs.getArray(columnIndex);
592 if (array == null) {
593 return ValueNull.INSTANCE;
594 }
595 Object[] list = (Object[]) array.getArray();
596 if (list == null) {
597 return ValueNull.INSTANCE;
598 }
599 int len = list.length;
600 Value[] values = new Value[len];
601 for (int i = 0; i < len; i++) {
602 values[i] = DataType.convertToValue(session, list[i], Value.NULL);
603 }
604 v = ValueArray.get(values);
605 break;
606 }
607 case Value.RESULT_SET: {
608 ResultSet x = (ResultSet) rs.getObject(columnIndex);
609 if (x == null) {
610 return ValueNull.INSTANCE;
611 }
612 return ValueResultSet.get(rs);
613 }
614 default:
615 throw DbException.throwInternalError("type="+type);
616 }
617 return v;
618 } catch (SQLException e) {
619 throw DbException.convert(e);
620 }
621 }
622
623 /**
624 * Get the name of the Java class for the given value type.
625 *
626 * @param type the value type
627 * @return the class name
628 */
629 public static String getTypeClassName(int type) {
630 switch(type) {
631 case Value.BOOLEAN:
632 // "java.lang.Boolean";
633 return Boolean.class.getName();
634 case Value.BYTE:
635 // "java.lang.Byte";
636 return Byte.class.getName();
637 case Value.SHORT:
638 // "java.lang.Short";
639 return Short.class.getName();
640 case Value.INT:
641 // "java.lang.Integer";
642 return Integer.class.getName();
643 case Value.LONG:
644 // "java.lang.Long";
645 return Long.class.getName();
646 case Value.DECIMAL:
647 // "java.math.BigDecimal";
648 return BigDecimal.class.getName();
649 case Value.TIME:
650 // "java.sql.Time";
651 return Time.class.getName();
652 case Value.DATE:
653 // "java.sql.Date";
654 return Date.class.getName();
655 case Value.TIMESTAMP:
656 // "java.sql.Timestamp";
657 return Timestamp.class.getName();
658 case Value.BYTES:
659 case Value.UUID:
660 // "[B", not "byte[]";
661 return byte[].class.getName();
662 case Value.STRING:
663 case Value.STRING_IGNORECASE:
664 case Value.STRING_FIXED:
665 // "java.lang.String";
666 return String.class.getName();
667 case Value.BLOB:
668 // "java.sql.Blob";
669 return java.sql.Blob.class.getName();
670 case Value.CLOB:
671 // "java.sql.Clob";
672 return java.sql.Clob.class.getName();
673 case Value.DOUBLE:
674 // "java.lang.Double";
675 return Double.class.getName();
676 case Value.FLOAT:
677 // "java.lang.Float";
678 return Float.class.getName();
679 case Value.NULL:
680 return null;
681 case Value.JAVA_OBJECT:
682 // "java.lang.Object";
683 return Object.class.getName();
684 case Value.UNKNOWN:
685 // anything
686 return Object.class.getName();
687 case Value.ARRAY:
688 return Array.class.getName();
689 case Value.RESULT_SET:
690 return ResultSet.class.getName();
691 default:
692 throw DbException.throwInternalError("type="+type);
693 }
694 }
695
696 /**
697 * Get the data type object for the given value type.
698 *
699 * @param type the value type
700 * @return the data type object
701 */
702 public static DataType getDataType(int type) {
703 if (type == Value.UNKNOWN) {
704 throw DbException.get(ErrorCode.UNKNOWN_DATA_TYPE_1, "?");
705 }
706 DataType dt = TYPES_BY_VALUE_TYPE.get(type);
707 if (dt == null) {
708 dt = TYPES_BY_VALUE_TYPE.get(Value.NULL);
709 }
710 return dt;
711 }
712
713 /**
714 * Convert a value type to a SQL type.
715 *
716 * @param type the value type
717 * @return the SQL type
718 */
719 public static int convertTypeToSQLType(int type) {
720 return getDataType(type).sqlType;
721 }
722
723 /**
724 * Convert a SQL type to a value type.
725 *
726 * @param sqlType the SQL type
727 * @return the value type
728 */
729 public static int convertSQLTypeToValueType(int sqlType) {
730 switch(sqlType) {
731 case Types.CHAR:
732 case TYPE_NCHAR:
733 return Value.STRING_FIXED;
734 case Types.VARCHAR:
735 case Types.LONGVARCHAR:
736 case TYPE_NVARCHAR:
737 case TYPE_LONGNVARCHAR:
738 return Value.STRING;
739 case Types.NUMERIC:
740 case Types.DECIMAL:
741 return Value.DECIMAL;
742 case Types.BIT:
743 case Types.BOOLEAN:
744 return Value.BOOLEAN;
745 case Types.INTEGER:
746 return Value.INT;
747 case Types.SMALLINT:
748 return Value.SHORT;
749 case Types.TINYINT:
750 return Value.BYTE;
751 case Types.BIGINT:
752 return Value.LONG;
753 case Types.REAL:
754 return Value.FLOAT;
755 case Types.DOUBLE:
756 case Types.FLOAT:
757 return Value.DOUBLE;
758 case Types.BINARY:
759 case Types.VARBINARY:
760 case Types.LONGVARBINARY:
761 return Value.BYTES;
762 case Types.OTHER:
763 case Types.JAVA_OBJECT:
764 return Value.JAVA_OBJECT;
765 case Types.DATE:
766 return Value.DATE;
767 case Types.TIME:
768 return Value.TIME;
769 case Types.TIMESTAMP:
770 return Value.TIMESTAMP;
771 case Types.BLOB:
772 return Value.BLOB;
773 case Types.CLOB:
774 case TYPE_NCLOB:
775 return Value.CLOB;
776 case Types.NULL:
777 return Value.NULL;
778 case Types.ARRAY:
779 return Value.ARRAY;
780 case DataType.TYPE_RESULT_SET:
781 return Value.RESULT_SET;
782 default:
783 throw DbException.get(ErrorCode.UNKNOWN_DATA_TYPE_1, "" + sqlType);
784 }
785 }
786
787 /**
788 * Get the value type for the given Java class.
789 *
790 * @param x the Java class
791 * @return the value type
792 */
793 public static int getTypeFromClass(Class <?> x) {
794 // TODO refactor: too many if/else in functions, can reduce!
795 if (x == null || Void.TYPE == x) {
796 return Value.NULL;
797 }
798 if (x.isPrimitive()) {
799 x = Utils.getNonPrimitiveClass(x);
800 }
801 if (String.class == x) {
802 return Value.STRING;
803 } else if (Integer.class == x) {
804 return Value.INT;
805 } else if (Long.class == x) {
806 return Value.LONG;
807 } else if (Boolean.class == x) {
808 return Value.BOOLEAN;
809 } else if (Double.class == x) {
810 return Value.DOUBLE;
811 } else if (Byte.class == x) {
812 return Value.BYTE;
813 } else if (Short.class == x) {
814 return Value.SHORT;
815 } else if (Character.class == x) {
816 throw DbException.get(ErrorCode.DATA_CONVERSION_ERROR_1, "char (not supported)");
817 } else if (Float.class == x) {
818 return Value.FLOAT;
819 } else if (byte[].class == x) {
820 return Value.BYTES;
821 } else if (UUID.class == x) {
822 return Value.UUID;
823 } else if (Void.class == x) {
824 return Value.NULL;
825 } else if (BigDecimal.class.isAssignableFrom(x)) {
826 return Value.DECIMAL;
827 } else if (ResultSet.class.isAssignableFrom(x)) {
828 return Value.RESULT_SET;
829 } else if (Value.ValueBlob.class.isAssignableFrom(x)) {
830 return Value.BLOB;
831 } else if (Value.ValueClob.class.isAssignableFrom(x)) {
832 return Value.CLOB;
833 } else if (Date.class.isAssignableFrom(x)) {
834 return Value.DATE;
835 } else if (Time.class.isAssignableFrom(x)) {
836 return Value.TIME;
837 } else if (Timestamp.class.isAssignableFrom(x)) {
838 return Value.TIMESTAMP;
839 } else if (java.util.Date.class.isAssignableFrom(x)) {
840 return Value.TIMESTAMP;
841 } else if (java.io.Reader.class.isAssignableFrom(x)) {
842 return Value.CLOB;
843 } else if (java.sql.Clob.class.isAssignableFrom(x)) {
844 return Value.CLOB;
845 } else if (java.io.InputStream.class.isAssignableFrom(x)) {
846 return Value.BLOB;
847 } else if (java.sql.Blob.class.isAssignableFrom(x)) {
848 return Value.BLOB;
849 } else if (Object[].class.isAssignableFrom(x)) {
850 // this includes String[] and so on
851 return Value.ARRAY;
852 } else {
853 return Value.JAVA_OBJECT;
854 }
855 }
856
857 /**
858 * Convert a Java object to a value.
859 *
860 * @param session the session
861 * @param x the value
862 * @param type the value type
863 * @return the value
864 */
865 public static Value convertToValue(SessionInterface session, Object x, int type) {
866 if (x == null) {
867 return ValueNull.INSTANCE;
868 }
869 if (type == Value.JAVA_OBJECT) {
870 return ValueJavaObject.getNoCopy(x, null);
871 }
872 if (x instanceof String) {
873 return ValueString.get((String) x);
874 } else if (x instanceof Value) {
875 return (Value) x;
876 } else if (x instanceof Long) {
877 return ValueLong.get(((Long) x).longValue());
878 } else if (x instanceof Integer) {
879 return ValueInt.get(((Integer) x).intValue());
880 } else if (x instanceof BigDecimal) {
881 return ValueDecimal.get((BigDecimal) x);
882 } else if (x instanceof Boolean) {
883 return ValueBoolean.get(((Boolean) x).booleanValue());
884 } else if (x instanceof Byte) {
885 return ValueByte.get(((Byte) x).byteValue());
886 } else if (x instanceof Short) {
887 return ValueShort.get(((Short) x).shortValue());
888 } else if (x instanceof Float) {
889 return ValueFloat.get(((Float) x).floatValue());
890 } else if (x instanceof Double) {
891 return ValueDouble.get(((Double) x).doubleValue());
892 } else if (x instanceof byte[]) {
893 return ValueBytes.get((byte[]) x);
894 } else if (x instanceof Date) {
895 return ValueDate.get((Date) x);
896 } else if (x instanceof Time) {
897 return ValueTime.get((Time) x);
898 } else if (x instanceof Timestamp) {
899 return ValueTimestamp.get((Timestamp) x);
900 } else if (x instanceof java.util.Date) {
901 return ValueTimestamp.get(new Timestamp(((java.util.Date) x).getTime()));
902 } else if (x instanceof java.io.Reader) {
903 Reader r = new BufferedReader((java.io.Reader) x);
904 return session.getDataHandler().getLobStorage().createClob(r, -1);
905 } else if (x instanceof java.sql.Clob) {
906 try {
907 Reader r = new BufferedReader(((java.sql.Clob) x).getCharacterStream());
908 return session.getDataHandler().getLobStorage().createClob(r, -1);
909 } catch (SQLException e) {
910 throw DbException.convert(e);
911 }
912 } else if (x instanceof java.io.InputStream) {
913 return session.getDataHandler().getLobStorage().createBlob((java.io.InputStream) x, -1);
914 } else if (x instanceof java.sql.Blob) {
915 try {
916 return session.getDataHandler().getLobStorage().createBlob(((java.sql.Blob) x).getBinaryStream(), -1);
917 } catch (SQLException e) {
918 throw DbException.convert(e);
919 }
920 } else if (x instanceof ResultSet) {
921 if (x instanceof SimpleResultSet) {
922 return ValueResultSet.get((ResultSet) x);
923 }
924 return ValueResultSet.getCopy((ResultSet) x, Integer.MAX_VALUE);
925 } else if (x instanceof UUID) {
926 UUID u = (UUID) x;
927 return ValueUuid.get(u.getMostSignificantBits(), u.getLeastSignificantBits());
928 } else if (x instanceof Object[]) {
929 // (a.getClass().isArray());
930 // (a.getClass().getComponentType().isPrimitive());
931 Object[] o = (Object[]) x;
932 int len = o.length;
933 Value[] v = new Value[len];
934 for (int i = 0; i < len; i++) {
935 v[i] = convertToValue(session, o[i], type);
936 }
937 return ValueArray.get(x.getClass().getComponentType(), v);
938 } else if (x instanceof Character) {
939 return ValueStringFixed.get(((Character) x).toString());
940 } else {
941 return ValueJavaObject.getNoCopy(x, null);
942 }
943 }
944
945 /**
946 * Get a data type object from a type name.
947 *
948 * @param s the type name
949 * @return the data type object
950 */
951 public static DataType getTypeByName(String s) {
952 return TYPES_BY_NAME.get(s);
953 }
954
955 /**
956 * Check if the given value type is a large object (BLOB or CLOB).
957 *
958 * @param type the value type
959 * @return true if the value type is a lob type
960 */
961 public static boolean isLargeObject(int type) {
962 if (type == Value.BLOB || type == Value.CLOB) {
963 return true;
964 }
965 return false;
966 }
967
968 /**
969 * Check if the given value type is a String (VARCHAR,...).
970 *
971 * @param type the value type
972 * @return true if the value type is a String type
973 */
974 public static boolean isStringType(int type) {
975 if (type == Value.STRING || type == Value.STRING_FIXED || type == Value.STRING_IGNORECASE) {
976 return true;
977 }
978 return false;
979 }
980
981 /**
982 * Check if the given value type supports the add operation.
983 *
984 * @param type the value type
985 * @return true if add is supported
986 */
987 public static boolean supportsAdd(int type) {
988 switch (type) {
989 case Value.BYTE:
990 case Value.DECIMAL:
991 case Value.DOUBLE:
992 case Value.FLOAT:
993 case Value.INT:
994 case Value.LONG:
995 case Value.SHORT:
996 return true;
997 default:
998 return false;
999 }
1000 }
1001
1002 /**
1003 * Get the data type that will not overflow when calling 'add' 2 billion times.
1004 *
1005 * @param type the value type
1006 * @return the data type that supports adding
1007 */
1008 public static int getAddProofType(int type) {
1009 switch (type) {
1010 case Value.BYTE:
1011 return Value.LONG;
1012 case Value.FLOAT:
1013 return Value.DOUBLE;
1014 case Value.INT:
1015 return Value.LONG;
1016 case Value.LONG:
1017 return Value.DECIMAL;
1018 case Value.SHORT:
1019 return Value.LONG;
1020 default:
1021 return type;
1022 }
1023 }
1024
1025 /**
1026 * Get the default value in the form of a Java object for the given Java class.
1027 *
1028 * @param clazz the Java class
1029 * @return the default object
1030 */
1031 public static Object getDefaultForPrimitiveType(Class<?> clazz) {
1032 if (clazz == Boolean.TYPE) {
1033 return Boolean.FALSE;
1034 } else if (clazz == Byte.TYPE) {
1035 return Byte.valueOf((byte) 0);
1036 } else if (clazz == Character.TYPE) {
1037 return Character.valueOf((char) 0);
1038 } else if (clazz == Short.TYPE) {
1039 return Short.valueOf((short) 0);
1040 } else if (clazz == Integer.TYPE) {
1041 return Integer.valueOf(0);
1042 } else if (clazz == Long.TYPE) {
1043 return Long.valueOf(0);
1044 } else if (clazz == Float.TYPE) {
1045 return Float.valueOf(0);
1046 } else if (clazz == Double.TYPE) {
1047 return Double.valueOf(0);
1048 }
1049 throw DbException.throwInternalError("primitive=" + clazz.toString());
1050 }
1051
1052 /**
1053 * Convert a value to the specified class.
1054 *
1055 * @param conn the database connection
1056 * @param v the value
1057 * @param paramClass the target class
1058 * @return the converted object
1059 */
1060 public static Object convertTo(JdbcConnection conn, Value v, Class<?> paramClass) {
1061 if (paramClass == Blob.class) {
1062 return new JdbcBlob(conn, v, 0);
1063 } else if (paramClass == Clob.class) {
1064 return new JdbcClob(conn, v, 0);
1065 }
1066 if (v.getType() == Value.JAVA_OBJECT) {
1067 Object o = SysProperties.serializeJavaObject ? Utils.deserialize(v.getBytes()) : v.getObject();
1068 if (paramClass.isAssignableFrom(o.getClass())) {
1069 return o;
1070 }
1071 }
1072 throw DbException.getUnsupportedException(paramClass.getName());
1073 }
1074
1075 }
1076