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

COVERAGE SUMMARY FOR SOURCE FILE [ValueDataType.java]

nameclass, %method, %block, %line, %
ValueDataType.java100% (1/1)95%  (19/20)96%  (1255/1312)96%  (292/304)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class ValueDataType100% (1/1)95%  (19/20)96%  (1255/1312)96%  (292/304)
hashCode (): int 0%   (0/1)0%   (0/8)0%   (0/1)
compareTypeSave (Value, Value): int 100% (1/1)82%  (9/11)67%  (2/3)
equals (Object): boolean 100% (1/1)85%  (23/27)75%  (6/8)
readValue (ByteBuffer): Object 100% (1/1)95%  (389/411)98%  (91/93)
compare (Object, Object): int 100% (1/1)95%  (71/75)89%  (17/19)
compareValues (Value, Value, int): int 100% (1/1)96%  (47/49)93%  (13/14)
writeValue (WriteBuffer, Value): void 100% (1/1)98%  (592/607)98%  (129/132)
ValueDataType (CompareMode, DataHandler, int []): void 100% (1/1)100% (12/12)100% (5/5)
getMemory (Object): int 100% (1/1)100% (12/12)100% (3/3)
getMemory (Value): int 100% (1/1)100% (7/7)100% (1/1)
getSpatialDataType (): SpatialDataType 100% (1/1)100% (12/12)100% (3/3)
read (ByteBuffer): Object 100% (1/1)100% (4/4)100% (1/1)
read (ByteBuffer, Object [], int, boolean): void 100% (1/1)100% (14/14)100% (3/3)
readString (ByteBuffer): String 100% (1/1)100% (7/7)100% (2/2)
readString (ByteBuffer, int): String 100% (1/1)100% (4/4)100% (1/1)
readVarInt (ByteBuffer): int 100% (1/1)100% (3/3)100% (1/1)
readVarLong (ByteBuffer): long 100% (1/1)100% (3/3)100% (1/1)
write (WriteBuffer, Object [], int, boolean): void 100% (1/1)100% (14/14)100% (3/3)
write (WriteBuffer, Object): void 100% (1/1)100% (21/21)100% (7/7)
writeString (WriteBuffer, String): void 100% (1/1)100% (11/11)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.mvstore.db;
7 
8import java.math.BigDecimal;
9import java.math.BigInteger;
10import java.nio.ByteBuffer;
11import java.sql.ResultSet;
12import java.sql.ResultSetMetaData;
13import java.sql.SQLException;
14import java.util.Arrays;
15 
16import org.h2.api.ErrorCode;
17import org.h2.message.DbException;
18import org.h2.mvstore.DataUtils;
19import org.h2.mvstore.WriteBuffer;
20import org.h2.mvstore.rtree.SpatialDataType;
21import org.h2.mvstore.rtree.SpatialKey;
22import org.h2.mvstore.type.DataType;
23import org.h2.result.SortOrder;
24import org.h2.store.DataHandler;
25import org.h2.tools.SimpleResultSet;
26import org.h2.value.CompareMode;
27import org.h2.value.Value;
28import org.h2.value.ValueArray;
29import org.h2.value.ValueBoolean;
30import org.h2.value.ValueByte;
31import org.h2.value.ValueBytes;
32import org.h2.value.ValueDate;
33import org.h2.value.ValueDecimal;
34import org.h2.value.ValueDouble;
35import org.h2.value.ValueFloat;
36import org.h2.value.ValueGeometry;
37import org.h2.value.ValueInt;
38import org.h2.value.ValueJavaObject;
39import org.h2.value.ValueLobDb;
40import org.h2.value.ValueLong;
41import org.h2.value.ValueNull;
42import org.h2.value.ValueResultSet;
43import org.h2.value.ValueShort;
44import org.h2.value.ValueString;
45import org.h2.value.ValueStringFixed;
46import org.h2.value.ValueStringIgnoreCase;
47import org.h2.value.ValueTime;
48import org.h2.value.ValueTimestamp;
49import org.h2.value.ValueUuid;
50 
51/**
52 * A row type.
53 */
54public class ValueDataType implements DataType {
55 
56    private static final int INT_0_15 = 32;
57    private static final int LONG_0_7 = 48;
58    private static final int DECIMAL_0_1 = 56;
59    private static final int DECIMAL_SMALL_0 = 58;
60    private static final int DECIMAL_SMALL = 59;
61    private static final int DOUBLE_0_1 = 60;
62    private static final int FLOAT_0_1 = 62;
63    private static final int BOOLEAN_FALSE = 64;
64    private static final int BOOLEAN_TRUE = 65;
65    private static final int INT_NEG = 66;
66    private static final int LONG_NEG = 67;
67    private static final int STRING_0_31 = 68;
68    private static final int BYTES_0_31 = 100;
69    private static final int SPATIAL_KEY_2D = 132;
70 
71    final DataHandler handler;
72    final CompareMode compareMode;
73    final int[] sortTypes;
74    SpatialDataType spatialType;
75 
76    public ValueDataType(CompareMode compareMode, DataHandler handler,
77            int[] sortTypes) {
78        this.compareMode = compareMode;
79        this.handler = handler;
80        this.sortTypes = sortTypes;
81    }
82 
83    private SpatialDataType getSpatialDataType() {
84        if (spatialType == null) {
85            spatialType = new SpatialDataType(2);
86        }
87        return spatialType;
88    }
89 
90    @Override
91    public int compare(Object a, Object b) {
92        if (a == b) {
93            return 0;
94        }
95        if (a instanceof ValueArray && b instanceof ValueArray) {
96            Value[] ax = ((ValueArray) a).getList();
97            Value[] bx = ((ValueArray) b).getList();
98            int al = ax.length;
99            int bl = bx.length;
100            int len = Math.min(al, bl);
101            for (int i = 0; i < len; i++) {
102                int sortType = sortTypes[i];
103                int comp = compareValues(ax[i], bx[i], sortType);
104                if (comp != 0) {
105                    return comp;
106                }
107            }
108            if (len < al) {
109                return -1;
110            } else if (len < bl) {
111                return 1;
112            }
113            return 0;
114        }
115        return compareValues((Value) a, (Value) b, SortOrder.ASCENDING);
116    }
117 
118    private int compareValues(Value a, Value b, int sortType) {
119        if (a == b) {
120            return 0;
121        }
122        // null is never stored;
123        // comparison with null is used to retrieve all entries
124        // in which case null is always lower than all entries
125        // (even for descending ordered indexes)
126        if (a == null) {
127            return -1;
128        } else if (b == null) {
129            return 1;
130        }
131        boolean aNull = a == ValueNull.INSTANCE;
132        boolean bNull = b == ValueNull.INSTANCE;
133        if (aNull || bNull) {
134            return SortOrder.compareNull(aNull, sortType);
135        }
136        int comp = compareTypeSave(a, b);
137        if ((sortType & SortOrder.DESCENDING) != 0) {
138            comp = -comp;
139        }
140        return comp;
141    }
142 
143    private int compareTypeSave(Value a, Value b) {
144        if (a == b) {
145            return 0;
146        }
147        return a.compareTypeSave(b, compareMode);
148    }
149 
150    @Override
151    public int getMemory(Object obj) {
152        if (obj instanceof SpatialKey) {
153            return getSpatialDataType().getMemory(obj);
154        }
155        return getMemory((Value) obj);
156    }
157 
158    private static int getMemory(Value v) {
159        return v == null ? 0 : v.getMemory();
160    }
161 
162    @Override
163    public void read(ByteBuffer buff, Object[] obj, int len, boolean key) {
164        for (int i = 0; i < len; i++) {
165            obj[i] = read(buff);
166        }
167    }
168 
169    @Override
170    public void write(WriteBuffer buff, Object[] obj, int len, boolean key) {
171        for (int i = 0; i < len; i++) {
172            write(buff, obj[i]);
173        }
174    }
175 
176    @Override
177    public Object read(ByteBuffer buff) {
178        return readValue(buff);
179    }
180 
181    @Override
182    public void write(WriteBuffer buff, Object obj) {
183        if (obj instanceof SpatialKey) {
184            buff.put((byte) SPATIAL_KEY_2D);
185            getSpatialDataType().write(buff, obj);
186            return;
187        }
188        Value x = (Value) obj;
189        writeValue(buff, x);
190    }
191 
192    private void writeValue(WriteBuffer buff, Value v) {
193        if (v == ValueNull.INSTANCE) {
194            buff.put((byte) 0);
195            return;
196        }
197        int type = v.getType();
198        switch (type) {
199        case Value.BOOLEAN:
200            buff.put((byte) (v.getBoolean().booleanValue() ?
201                    BOOLEAN_TRUE : BOOLEAN_FALSE));
202            break;
203        case Value.BYTE:
204            buff.put((byte) type).put(v.getByte());
205            break;
206        case Value.SHORT:
207            buff.put((byte) type).putShort(v.getShort());
208            break;
209        case Value.INT: {
210            int x = v.getInt();
211            if (x < 0) {
212                buff.put((byte) INT_NEG).putVarInt(-x);
213            } else if (x < 16) {
214                buff.put((byte) (INT_0_15 + x));
215            } else {
216                buff.put((byte) type).putVarInt(x);
217            }
218            break;
219        }
220        case Value.LONG: {
221            long x = v.getLong();
222            if (x < 0) {
223                buff.put((byte) LONG_NEG).putVarLong(-x);
224            } else if (x < 8) {
225                buff.put((byte) (LONG_0_7 + x));
226            } else {
227                buff.put((byte) type).putVarLong(x);
228            }
229            break;
230        }
231        case Value.DECIMAL: {
232            BigDecimal x = v.getBigDecimal();
233            if (BigDecimal.ZERO.equals(x)) {
234                buff.put((byte) DECIMAL_0_1);
235            } else if (BigDecimal.ONE.equals(x)) {
236                buff.put((byte) (DECIMAL_0_1 + 1));
237            } else {
238                int scale = x.scale();
239                BigInteger b = x.unscaledValue();
240                int bits = b.bitLength();
241                if (bits <= 63) {
242                    if (scale == 0) {
243                        buff.put((byte) DECIMAL_SMALL_0).
244                            putVarLong(b.longValue());
245                    } else {
246                        buff.put((byte) DECIMAL_SMALL).
247                            putVarInt(scale).
248                            putVarLong(b.longValue());
249                    }
250                } else {
251                    byte[] bytes = b.toByteArray();
252                    buff.put((byte) type).
253                        putVarInt(scale).
254                        putVarInt(bytes.length).
255                        put(bytes);
256                }
257            }
258            break;
259        }
260        case Value.TIME: {
261            ValueTime t = (ValueTime) v;
262            long nanos = t.getNanos();
263            long millis = nanos / 1000000;
264            nanos -= millis * 1000000;
265            buff.put((byte) type).
266                putVarLong(millis).
267                putVarLong(nanos);
268            break;
269        }
270        case Value.DATE: {
271            long x = ((ValueDate) v).getDateValue();
272            buff.put((byte) type).putVarLong(x);
273            break;
274        }
275        case Value.TIMESTAMP: {
276            ValueTimestamp ts = (ValueTimestamp) v;
277            long dateValue = ts.getDateValue();
278            long nanos = ts.getTimeNanos();
279            long millis = nanos / 1000000;
280            nanos -= millis * 1000000;
281            buff.put((byte) type).
282                putVarLong(dateValue).
283                putVarLong(millis).
284                putVarLong(nanos);
285            break;
286        }
287        case Value.JAVA_OBJECT: {
288            byte[] b = v.getBytesNoCopy();
289            buff.put((byte) type).
290                putVarInt(b.length).
291                put(b);
292            break;
293        }
294        case Value.BYTES: {
295            byte[] b = v.getBytesNoCopy();
296            int len = b.length;
297            if (len < 32) {
298                buff.put((byte) (BYTES_0_31 + len)).
299                    put(b);
300            } else {
301                buff.put((byte) type).
302                    putVarInt(b.length).
303                    put(b);
304            }
305            break;
306        }
307        case Value.UUID: {
308            ValueUuid uuid = (ValueUuid) v;
309            buff.put((byte) type).
310                putLong(uuid.getHigh()).
311                putLong(uuid.getLow());
312            break;
313        }
314        case Value.STRING: {
315            String s = v.getString();
316            int len = s.length();
317            if (len < 32) {
318                buff.put((byte) (STRING_0_31 + len)).
319                    putStringData(s, len);
320            } else {
321                buff.put((byte) type);
322                writeString(buff, s);
323            }
324            break;
325        }
326        case Value.STRING_IGNORECASE:
327        case Value.STRING_FIXED:
328            buff.put((byte) type);
329            writeString(buff, v.getString());
330            break;
331        case Value.DOUBLE: {
332            double x = v.getDouble();
333            if (x == 1.0d) {
334                buff.put((byte) (DOUBLE_0_1 + 1));
335            } else {
336                long d = Double.doubleToLongBits(x);
337                if (d == ValueDouble.ZERO_BITS) {
338                    buff.put((byte) DOUBLE_0_1);
339                } else {
340                    buff.put((byte) type).
341                        putVarLong(Long.reverse(d));
342                }
343            }
344            break;
345        }
346        case Value.FLOAT: {
347            float x = v.getFloat();
348            if (x == 1.0f) {
349                buff.put((byte) (FLOAT_0_1 + 1));
350            } else {
351                int f = Float.floatToIntBits(x);
352                if (f == ValueFloat.ZERO_BITS) {
353                    buff.put((byte) FLOAT_0_1);
354                } else {
355                    buff.put((byte) type).
356                        putVarInt(Integer.reverse(f));
357                }
358            }
359            break;
360        }
361        case Value.BLOB:
362        case Value.CLOB: {
363            buff.put((byte) type);
364            ValueLobDb lob = (ValueLobDb) v;
365            byte[] small = lob.getSmall();
366            if (small == null) {
367                buff.putVarInt(-3).
368                    putVarInt(lob.getTableId()).
369                    putVarLong(lob.getLobId()).
370                    putVarLong(lob.getPrecision());
371            } else {
372                buff.putVarInt(small.length).
373                    put(small);
374            }
375            break;
376        }
377        case Value.ARRAY: {
378            Value[] list = ((ValueArray) v).getList();
379            buff.put((byte) type).putVarInt(list.length);
380            for (Value x : list) {
381                writeValue(buff, x);
382            }
383            break;
384        }
385        case Value.RESULT_SET: {
386            buff.put((byte) type);
387            try {
388                ResultSet rs = ((ValueResultSet) v).getResultSet();
389                rs.beforeFirst();
390                ResultSetMetaData meta = rs.getMetaData();
391                int columnCount = meta.getColumnCount();
392                buff.putVarInt(columnCount);
393                for (int i = 0; i < columnCount; i++) {
394                    writeString(buff, meta.getColumnName(i + 1));
395                    buff.putVarInt(meta.getColumnType(i + 1)).
396                        putVarInt(meta.getPrecision(i + 1)).
397                        putVarInt(meta.getScale(i + 1));
398                }
399                while (rs.next()) {
400                    buff.put((byte) 1);
401                    for (int i = 0; i < columnCount; i++) {
402                        int t = org.h2.value.DataType.
403                                getValueTypeFromResultSet(meta, i + 1);
404                        Value val = org.h2.value.DataType.readValue(
405                                null, rs, i + 1, t);
406                        writeValue(buff, val);
407                    }
408                }
409                buff.put((byte) 0);
410                rs.beforeFirst();
411            } catch (SQLException e) {
412                throw DbException.convert(e);
413            }
414            break;
415        }
416        case Value.GEOMETRY: {
417            byte[] b = v.getBytes();
418            int len = b.length;
419            buff.put((byte) type).
420                putVarInt(len).
421                put(b);
422            break;
423        }
424        default:
425            DbException.throwInternalError("type=" + v.getType());
426        }
427    }
428 
429    private static void writeString(WriteBuffer buff, String s) {
430        int len = s.length();
431        buff.putVarInt(len).putStringData(s, len);
432    }
433 
434    /**
435     * Read a value.
436     *
437     * @return the value
438     */
439    private Object readValue(ByteBuffer buff) {
440        int type = buff.get() & 255;
441        switch (type) {
442        case Value.NULL:
443            return ValueNull.INSTANCE;
444        case BOOLEAN_TRUE:
445            return ValueBoolean.get(true);
446        case BOOLEAN_FALSE:
447            return ValueBoolean.get(false);
448        case INT_NEG:
449            return ValueInt.get(-readVarInt(buff));
450        case Value.INT:
451            return ValueInt.get(readVarInt(buff));
452        case LONG_NEG:
453            return ValueLong.get(-readVarLong(buff));
454        case Value.LONG:
455            return ValueLong.get(readVarLong(buff));
456        case Value.BYTE:
457            return ValueByte.get(buff.get());
458        case Value.SHORT:
459            return ValueShort.get(buff.getShort());
460        case DECIMAL_0_1:
461            return ValueDecimal.ZERO;
462        case DECIMAL_0_1 + 1:
463            return ValueDecimal.ONE;
464        case DECIMAL_SMALL_0:
465            return ValueDecimal.get(BigDecimal.valueOf(
466                    readVarLong(buff)));
467        case DECIMAL_SMALL: {
468            int scale = readVarInt(buff);
469            return ValueDecimal.get(BigDecimal.valueOf(
470                    readVarLong(buff), scale));
471        }
472        case Value.DECIMAL: {
473            int scale = readVarInt(buff);
474            int len = readVarInt(buff);
475            byte[] buff2 = DataUtils.newBytes(len);
476            buff.get(buff2, 0, len);
477            BigInteger b = new BigInteger(buff2);
478            return ValueDecimal.get(new BigDecimal(b, scale));
479        }
480        case Value.DATE: {
481            return ValueDate.fromDateValue(readVarLong(buff));
482        }
483        case Value.TIME: {
484            long nanos = readVarLong(buff) * 1000000 + readVarLong(buff);
485            return ValueTime.fromNanos(nanos);
486        }
487        case Value.TIMESTAMP: {
488            long dateValue = readVarLong(buff);
489            long nanos = readVarLong(buff) * 1000000 + readVarLong(buff);
490            return ValueTimestamp.fromDateValueAndNanos(dateValue, nanos);
491        }
492        case Value.BYTES: {
493            int len = readVarInt(buff);
494            byte[] b = DataUtils.newBytes(len);
495            buff.get(b, 0, len);
496            return ValueBytes.getNoCopy(b);
497        }
498        case Value.JAVA_OBJECT: {
499            int len = readVarInt(buff);
500            byte[] b = DataUtils.newBytes(len);
501            buff.get(b, 0, len);
502            return ValueJavaObject.getNoCopy(null, b, handler);
503        }
504        case Value.UUID:
505            return ValueUuid.get(buff.getLong(), buff.getLong());
506        case Value.STRING:
507            return ValueString.get(readString(buff));
508        case Value.STRING_IGNORECASE:
509            return ValueStringIgnoreCase.get(readString(buff));
510        case Value.STRING_FIXED:
511            return ValueStringFixed.get(readString(buff));
512        case FLOAT_0_1:
513            return ValueFloat.get(0);
514        case FLOAT_0_1 + 1:
515            return ValueFloat.get(1);
516        case DOUBLE_0_1:
517            return ValueDouble.get(0);
518        case DOUBLE_0_1 + 1:
519            return ValueDouble.get(1);
520        case Value.DOUBLE:
521            return ValueDouble.get(Double.longBitsToDouble(
522                    Long.reverse(readVarLong(buff))));
523        case Value.FLOAT:
524            return ValueFloat.get(Float.intBitsToFloat(
525                    Integer.reverse(readVarInt(buff))));
526        case Value.BLOB:
527        case Value.CLOB: {
528            int smallLen = readVarInt(buff);
529            if (smallLen >= 0) {
530                byte[] small = DataUtils.newBytes(smallLen);
531                buff.get(small, 0, smallLen);
532                return ValueLobDb.createSmallLob(type, small);
533            } else if (smallLen == -3) {
534                int tableId = readVarInt(buff);
535                long lobId = readVarLong(buff);
536                long precision = readVarLong(buff);
537                ValueLobDb lob = ValueLobDb.create(type,
538                        handler, tableId, lobId, null, precision);
539                return lob;
540            } else {
541                throw DbException.get(ErrorCode.FILE_CORRUPTED_1,
542                        "lob type: " + smallLen);
543            }
544        }
545        case Value.ARRAY: {
546            int len = readVarInt(buff);
547            Value[] list = new Value[len];
548            for (int i = 0; i < len; i++) {
549                list[i] = (Value) readValue(buff);
550            }
551            return ValueArray.get(list);
552        }
553        case Value.RESULT_SET: {
554            SimpleResultSet rs = new SimpleResultSet();
555            rs.setAutoClose(false);
556            int columns = readVarInt(buff);
557            for (int i = 0; i < columns; i++) {
558                rs.addColumn(readString(buff),
559                        readVarInt(buff),
560                        readVarInt(buff),
561                        readVarInt(buff));
562            }
563            while (true) {
564                if (buff.get() == 0) {
565                    break;
566                }
567                Object[] o = new Object[columns];
568                for (int i = 0; i < columns; i++) {
569                    o[i] = ((Value) readValue(buff)).getObject();
570                }
571                rs.addRow(o);
572            }
573            return ValueResultSet.get(rs);
574        }
575        case Value.GEOMETRY: {
576            int len = readVarInt(buff);
577            byte[] b = DataUtils.newBytes(len);
578            buff.get(b, 0, len);
579            return ValueGeometry.get(b);
580        }
581        case SPATIAL_KEY_2D:
582            return getSpatialDataType().read(buff);
583        default:
584            if (type >= INT_0_15 && type < INT_0_15 + 16) {
585                return ValueInt.get(type - INT_0_15);
586            } else if (type >= LONG_0_7 && type < LONG_0_7 + 8) {
587                return ValueLong.get(type - LONG_0_7);
588            } else if (type >= BYTES_0_31 && type < BYTES_0_31 + 32) {
589                int len = type - BYTES_0_31;
590                byte[] b = DataUtils.newBytes(len);
591                buff.get(b, 0, len);
592                return ValueBytes.getNoCopy(b);
593            } else if (type >= STRING_0_31 && type < STRING_0_31 + 32) {
594                return ValueString.get(readString(buff, type - STRING_0_31));
595            }
596            throw DbException.get(ErrorCode.FILE_CORRUPTED_1, "type: " + type);
597        }
598    }
599 
600    private static int readVarInt(ByteBuffer buff) {
601        return DataUtils.readVarInt(buff);
602    }
603 
604    private static long readVarLong(ByteBuffer buff) {
605        return DataUtils.readVarLong(buff);
606    }
607 
608    private static String readString(ByteBuffer buff, int len) {
609        return DataUtils.readString(buff, len);
610    }
611 
612    private static String readString(ByteBuffer buff) {
613        int len = readVarInt(buff);
614        return DataUtils.readString(buff, len);
615    }
616 
617    @Override
618    public int hashCode() {
619        return compareMode.hashCode() ^ Arrays.hashCode(sortTypes);
620    }
621 
622    @Override
623    public boolean equals(Object obj) {
624        if (obj == this) {
625            return true;
626        } else if (!(obj instanceof ValueDataType)) {
627            return false;
628        }
629        ValueDataType v = (ValueDataType) obj;
630        if (!compareMode.equals(v.compareMode)) {
631            return false;
632        }
633        return Arrays.equals(sortTypes, v.sortTypes);
634    }
635 
636}

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