EMMA Coverage Report (generated Sun Mar 01 22:06:14 CET 2015)
[all classes][org.h2.value]

COVERAGE SUMMARY FOR SOURCE FILE [DataType.java]

nameclass, %method, %block, %line, %
DataType.java100% (1/1)100% (26/26)89%  (1878/2116)87%  (382.6/442)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class DataType100% (1/1)100% (26/26)89%  (1878/2116)87%  (382.6/442)
getDefaultForPrimitiveType (Class): Object 100% (1/1)31%  (18/58)35%  (6/17)
getDataType (int): DataType 100% (1/1)57%  (12/21)67%  (4/6)
supportsAdd (int): boolean 100% (1/1)67%  (4/6)67%  (2/3)
getTypeClassName (int): String 100% (1/1)71%  (52/73)78%  (18/23)
convertSQLTypeToValueType (int): int 100% (1/1)72%  (38/53)86%  (19/22)
readValue (SessionInterface, ResultSet, int, int): Value 100% (1/1)72%  (269/373)74%  (68.7/93)
isGeometry (Object): boolean 100% (1/1)75%  (6/8)67%  (2/3)
convertTo (JdbcConnection, Value, Class): Object 100% (1/1)76%  (41/54)88%  (7.9/9)
isGeometryClass (Class): boolean 100% (1/1)80%  (8/10)67%  (2/3)
getAddProofType (int): int 100% (1/1)86%  (12/14)86%  (6/7)
convertToValue (SessionInterface, Object, int): Value 100% (1/1)96%  (261/272)93%  (62/67)
getTypeFromClass (Class): int 100% (1/1)98%  (156/160)98%  (56/57)
<static initializer> 100% (1/1)98%  (690/703)94%  (47/50)
DataType (): void 100% (1/1)100% (3/3)100% (1/1)
add (int, int, String, DataType, String [], int): void 100% (1/1)100% (134/134)100% (31/31)
convertSQLTypeToValueType (int, String): int 100% (1/1)100% (11/11)100% (4/4)
convertTypeToSQLType (int): int 100% (1/1)100% (4/4)100% (1/1)
createDate (int, String, int, int): DataType 100% (1/1)100% (43/43)100% (10/10)
createDecimal (int, int, int, int, boolean, boolean): DataType 100% (1/1)100% (37/37)100% (12/12)
createLob (): DataType 100% (1/1)100% (11/11)100% (4/4)
createString (boolean): DataType 100% (1/1)100% (30/30)100% (10/10)
getTypeByName (String): DataType 100% (1/1)100% (5/5)100% (1/1)
getTypes (): ArrayList 100% (1/1)100% (2/2)100% (1/1)
getValueTypeFromResultSet (ResultSetMetaData, int): int 100% (1/1)100% (8/8)100% (1/1)
isLargeObject (int): boolean 100% (1/1)100% (10/10)100% (3/3)
isStringType (int): boolean 100% (1/1)100% (13/13)100% (3/3)

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

[all classes][org.h2.value]
EMMA 2.0.5312 (C) Vladimir Roubtsov