File D:\maven-qcr-plugin-testsunitaires\qcr4java\h2-1.3.170-sources\target\site\qc\lecode\store\Data.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 * The variable size number format code is a port from SQLite,
8 * but stored in reverse order (least significant bits in the first byte).
9 */
10 package org.h2.store;
11
12 import java.io.IOException;
13 import java.io.OutputStream;
14 import java.io.Reader;
15 import java.math.BigDecimal;
16 import java.math.BigInteger;
17 import java.sql.Date;
18 import java.sql.ResultSet;
19 import java.sql.ResultSetMetaData;
20 import java.sql.SQLException;
21 import java.sql.Time;
22 import java.sql.Timestamp;
23 import org.h2.constant.ErrorCode;
24 import org.h2.constant.SysProperties;
25 import org.h2.engine.Constants;
26 import org.h2.message.DbException;
27 import org.h2.tools.SimpleResultSet;
28 import org.h2.util.DateTimeUtils;
29 import org.h2.util.MathUtils;
30 import org.h2.util.Utils;
31 import org.h2.value.DataType;
32 import org.h2.value.Value;
33 import org.h2.value.ValueArray;
34 import org.h2.value.ValueBoolean;
35 import org.h2.value.ValueByte;
36 import org.h2.value.ValueBytes;
37 import org.h2.value.ValueDate;
38 import org.h2.value.ValueDecimal;
39 import org.h2.value.ValueDouble;
40 import org.h2.value.ValueFloat;
41 import org.h2.value.ValueInt;
42 import org.h2.value.ValueJavaObject;
43 import org.h2.value.ValueLob;
44 import org.h2.value.ValueLobDb;
45 import org.h2.value.ValueLong;
46 import org.h2.value.ValueNull;
47 import org.h2.value.ValueResultSet;
48 import org.h2.value.ValueShort;
49 import org.h2.value.ValueString;
50 import org.h2.value.ValueStringFixed;
51 import org.h2.value.ValueStringIgnoreCase;
52 import org.h2.value.ValueTime;
53 import org.h2.value.ValueTimestamp;
54 import org.h2.value.ValueUuid;
55
56 /**
57 * This class represents a byte buffer that contains persistent data of a page.
58 */
59 public class Data {
60
61 /**
62 * The length of an integer value.
63 */
64 public static final int LENGTH_INT = 4;
65
66 /**
67 * The length of a long value.
68 */
69 private static final int LENGTH_LONG = 8;
70
71 private static final int INT_0_15 = 32;
72 private static final int LONG_0_7 = 48;
73 private static final int DECIMAL_0_1 = 56;
74 private static final int DECIMAL_SMALL_0 = 58;
75 private static final int DECIMAL_SMALL = 59;
76 private static final int DOUBLE_0_1 = 60;
77 private static final int FLOAT_0_1 = 62;
78 private static final int BOOLEAN_FALSE = 64;
79 private static final int BOOLEAN_TRUE = 65;
80 private static final int INT_NEG = 66;
81 private static final int LONG_NEG = 67;
82 private static final int STRING_0_31 = 68;
83 private static final int BYTES_0_31 = 100;
84 private static final int LOCAL_TIME = 132;
85 private static final int LOCAL_DATE = 133;
86 private static final int LOCAL_TIMESTAMP = 134;
87
88 private static final long MILLIS_PER_MINUTE = 1000 * 60;
89
90 /**
91 * The data itself.
92 */
93 private byte[] data;
94
95 /**
96 * The current write or read position.
97 */
98 private int pos;
99
100 /**
101 * The data handler responsible for lob objects.
102 */
103 private final DataHandler handler;
104
105 private Data(DataHandler handler, byte[] data) {
106 this.handler = handler;
107 this.data = data;
108 }
109
110 /**
111 * Update an integer at the given position.
112 * The current position is not change.
113 *
114 * @param pos the position
115 * @param x the value
116 */
117 public void setInt(int pos, int x) {
118 byte[] buff = data;
119 buff[pos] = (byte) (x >> 24);
120 buff[pos + 1] = (byte) (x >> 16);
121 buff[pos + 2] = (byte) (x >> 8);
122 buff[pos + 3] = (byte) x;
123 }
124
125 /**
126 * Write an integer at the current position.
127 * The current position is incremented.
128 *
129 * @param x the value
130 */
131 public void writeInt(int x) {
132 byte[] buff = data;
133 buff[pos] = (byte) (x >> 24);
134 buff[pos + 1] = (byte) (x >> 16);
135 buff[pos + 2] = (byte) (x >> 8);
136 buff[pos + 3] = (byte) x;
137 pos += 4;
138 }
139
140 /**
141 * Read an integer at the current position.
142 * The current position is incremented.
143 *
144 * @return the value
145 */
146 public int readInt() {
147 byte[] buff = data;
148 int x = (buff[pos] << 24) + ((buff[pos+1] & 0xff) << 16) + ((buff[pos+2] & 0xff) << 8) + (buff[pos+3] & 0xff);
149 pos += 4;
150 return x;
151 }
152
153 /**
154 * Get the length of a String. This includes the bytes required to encode
155 * the length.
156 *
157 * @param s the string
158 * @return the number of bytes required
159 */
160 public static int getStringLen(String s) {
161 int len = s.length();
162 return getStringWithoutLengthLen(s, len) + getVarIntLen(len);
163 }
164
165 /**
166 * Calculate the length of String, excluding the bytes required to encode
167 * the length.
168 * <p>
169 * For performance reasons the internal representation of a String is
170 * similar to UTF-8, but not exactly UTF-8.
171 *
172 * @param s the string
173 * @param len the length of the string
174 * @return the number of bytes required
175 */
176 private static int getStringWithoutLengthLen(String s, int len) {
177 int plus = 0;
178 for (int i = 0; i < len; i++) {
179 char c = s.charAt(i);
180 if (c >= 0x800) {
181 plus += 2;
182 } else if (c >= 0x80) {
183 plus++;
184 }
185 }
186 return len + plus;
187 }
188
189 /**
190 * Read a String value.
191 * The current position is incremented.
192 *
193 * @return the value
194 */
195 public String readString() {
196 int len = readVarInt();
197 return readString(len);
198 }
199
200 /**
201 * Read a String from the byte array.
202 * <p>
203 * For performance reasons the internal representation of a String is
204 * similar to UTF-8, but not exactly UTF-8.
205 *
206 * @param len the length of the resulting string
207 * @return the String
208 */
209 private String readString(int len) {
210 byte[] buff = data;
211 int p = pos;
212 char[] chars = new char[len];
213 for (int i = 0; i < len; i++) {
214 int x = buff[p++] & 0xff;
215 if (x < 0x80) {
216 chars[i] = (char) x;
217 } else if (x >= 0xe0) {
218 chars[i] = (char) (((x & 0xf) << 12) + ((buff[p++] & 0x3f) << 6) + (buff[p++] & 0x3f));
219 } else {
220 chars[i] = (char) (((x & 0x1f) << 6) + (buff[p++] & 0x3f));
221 }
222 }
223 pos = p;
224 return new String(chars);
225 }
226
227 /**
228 * Write a String.
229 * The current position is incremented.
230 *
231 * @param s the value
232 */
233 public void writeString(String s) {
234 int len = s.length();
235 writeVarInt(len);
236 writeStringWithoutLength(s, len);
237 }
238
239 /**
240 * Write a String.
241 * <p>
242 * For performance reasons the internal representation of a String is
243 * similar to UTF-8, but not exactly UTF-8.
244 *
245 * @param s the string
246 * @param len the number of characters to write
247 */
248 private void writeStringWithoutLength(String s, int len) {
249 int p = pos;
250 byte[] buff = data;
251 for (int i = 0; i < len; i++) {
252 int c = s.charAt(i);
253 if (c < 0x80) {
254 buff[p++] = (byte) c;
255 } else if (c >= 0x800) {
256 buff[p++] = (byte) (0xe0 | (c >> 12));
257 buff[p++] = (byte) (((c >> 6) & 0x3f));
258 buff[p++] = (byte) (c & 0x3f);
259 } else {
260 buff[p++] = (byte) (0xc0 | (c >> 6));
261 buff[p++] = (byte) (c & 0x3f);
262 }
263 }
264 pos = p;
265 }
266
267 private void writeStringWithoutLength(char[] chars, int len) {
268 int p = pos;
269 byte[] buff = data;
270 for (int i = 0; i < len; i++) {
271 int c = chars[i];
272 if (c < 0x80) {
273 buff[p++] = (byte) c;
274 } else if (c >= 0x800) {
275 buff[p++] = (byte) (0xe0 | (c >> 12));
276 buff[p++] = (byte) (((c >> 6) & 0x3f));
277 buff[p++] = (byte) (c & 0x3f);
278 } else {
279 buff[p++] = (byte) (0xc0 | (c >> 6));
280 buff[p++] = (byte) (c & 0x3f);
281 }
282 }
283 pos = p;
284 }
285
286 /**
287 * Create a new buffer for the given handler. The
288 * handler will decide what type of buffer is created.
289 *
290 * @param handler the data handler
291 * @param capacity the initial capacity of the buffer
292 * @return the buffer
293 */
294 public static Data create(DataHandler handler, int capacity) {
295 return new Data(handler, new byte[capacity]);
296 }
297
298 /**
299 * Create a new buffer using the given data for the given handler. The
300 * handler will decide what type of buffer is created.
301 *
302 * @param handler the data handler
303 * @param buff the data
304 * @return the buffer
305 */
306 public static Data create(DataHandler handler, byte[] buff) {
307 return new Data(handler, buff);
308 }
309
310 /**
311 * Get the current write position of this buffer, which is the current
312 * length.
313 *
314 * @return the length
315 */
316 public int length() {
317 return pos;
318 }
319
320 /**
321 * Get the byte array used for this page.
322 *
323 * @return the byte array
324 */
325 public byte[] getBytes() {
326 return data;
327 }
328
329 /**
330 * Set the position to 0.
331 */
332 public void reset() {
333 pos = 0;
334 }
335
336 /**
337 * Append a number of bytes to this buffer.
338 *
339 * @param buff the data
340 * @param off the offset in the data
341 * @param len the length in bytes
342 */
343 public void write(byte[] buff, int off, int len) {
344 System.arraycopy(buff, off, data, pos, len);
345 pos += len;
346 }
347
348 /**
349 * Copy a number of bytes to the given buffer from the current position. The
350 * current position is incremented accordingly.
351 *
352 * @param buff the output buffer
353 * @param off the offset in the output buffer
354 * @param len the number of bytes to copy
355 */
356 public void read(byte[] buff, int off, int len) {
357 System.arraycopy(data, pos, buff, off, len);
358 pos += len;
359 }
360
361 /**
362 * Append one single byte.
363 *
364 * @param x the value
365 */
366 public void writeByte(byte x) {
367 data[pos++] = x;
368 }
369
370 /**
371 * Read one single byte.
372 *
373 * @return the value
374 */
375 public byte readByte() {
376 return data[pos++];
377 }
378
379 /**
380 * Read a long value. This method reads two int values and combines them.
381 *
382 * @return the long value
383 */
384 public long readLong() {
385 return ((long) (readInt()) << 32) + (readInt() & 0xffffffffL);
386 }
387
388 /**
389 * Append a long value. This method writes two int values.
390 *
391 * @param x the value
392 */
393 public void writeLong(long x) {
394 writeInt((int) (x >>> 32));
395 writeInt((int) x);
396 }
397
398 /**
399 * Append a value.
400 *
401 * @param v the value
402 */
403 public void writeValue(Value v) {
404 int start = pos;
405 if (v == ValueNull.INSTANCE) {
406 data[pos++] = 0;
407 return;
408 }
409 int type = v.getType();
410 switch (type) {
411 case Value.BOOLEAN:
412 writeByte((byte) (v.getBoolean().booleanValue() ? BOOLEAN_TRUE : BOOLEAN_FALSE));
413 break;
414 case Value.BYTE:
415 writeByte((byte) type);
416 writeByte(v.getByte());
417 break;
418 case Value.SHORT:
419 writeByte((byte) type);
420 writeShortInt(v.getShort());
421 break;
422 case Value.INT: {
423 int x = v.getInt();
424 if (x < 0) {
425 writeByte((byte) INT_NEG);
426 writeVarInt(-x);
427 } else if (x < 16) {
428 writeByte((byte) (INT_0_15 + x));
429 } else {
430 writeByte((byte) type);
431 writeVarInt(x);
432 }
433 break;
434 }
435 case Value.LONG: {
436 long x = v.getLong();
437 if (x < 0) {
438 writeByte((byte) LONG_NEG);
439 writeVarLong(-x);
440 } else if (x < 8) {
441 writeByte((byte) (LONG_0_7 + x));
442 } else {
443 writeByte((byte) type);
444 writeVarLong(x);
445 }
446 break;
447 }
448 case Value.DECIMAL: {
449 BigDecimal x = v.getBigDecimal();
450 if (BigDecimal.ZERO.equals(x)) {
451 writeByte((byte) DECIMAL_0_1);
452 } else if (BigDecimal.ONE.equals(x)) {
453 writeByte((byte) (DECIMAL_0_1 + 1));
454 } else {
455 int scale = x.scale();
456 BigInteger b = x.unscaledValue();
457 int bits = b.bitLength();
458 if (bits <= 63) {
459 if (scale == 0) {
460 writeByte((byte) DECIMAL_SMALL_0);
461 writeVarLong(b.longValue());
462 } else {
463 writeByte((byte) DECIMAL_SMALL);
464 writeVarInt(scale);
465 writeVarLong(b.longValue());
466 }
467 } else {
468 writeByte((byte) type);
469 writeVarInt(scale);
470 byte[] bytes = b.toByteArray();
471 writeVarInt(bytes.length);
472 write(bytes, 0, bytes.length);
473 }
474 }
475 break;
476 }
477 case Value.TIME:
478 if (SysProperties.STORE_LOCAL_TIME) {
479 writeByte((byte) LOCAL_TIME);
480 ValueTime t = (ValueTime) v;
481 long nanos = t.getNanos();
482 long millis = nanos / 1000000;
483 nanos -= millis * 1000000;
484 writeVarLong(millis);
485 writeVarLong(nanos);
486 } else {
487 writeByte((byte) type);
488 writeVarLong(DateTimeUtils.getTimeLocalWithoutDst(v.getTime()));
489 }
490 break;
491 case Value.DATE: {
492 if (SysProperties.STORE_LOCAL_TIME) {
493 writeByte((byte) LOCAL_DATE);
494 long x = ((ValueDate) v).getDateValue();
495 writeVarLong(x);
496 } else {
497 writeByte((byte) type);
498 long x = DateTimeUtils.getTimeLocalWithoutDst(v.getDate());
499 writeVarLong(x / MILLIS_PER_MINUTE);
500 }
501 break;
502 }
503 case Value.TIMESTAMP: {
504 if (SysProperties.STORE_LOCAL_TIME) {
505 writeByte((byte) LOCAL_TIMESTAMP);
506 ValueTimestamp ts = (ValueTimestamp) v;
507 long dateValue = ts.getDateValue();
508 writeVarLong(dateValue);
509 long nanos = ts.getNanos();
510 long millis = nanos / 1000000;
511 nanos -= millis * 1000000;
512 writeVarLong(millis);
513 writeVarLong(nanos);
514 } else {
515 Timestamp ts = v.getTimestamp();
516 writeByte((byte) type);
517 writeVarLong(DateTimeUtils.getTimeLocalWithoutDst(ts));
518 writeVarInt(ts.getNanos());
519 }
520 break;
521 }
522 case Value.JAVA_OBJECT: {
523 writeByte((byte) type);
524 byte[] b = v.getBytesNoCopy();
525 writeVarInt(b.length);
526 write(b, 0, b.length);
527 break;
528 }
529 case Value.BYTES: {
530 byte[] b = v.getBytesNoCopy();
531 int len = b.length;
532 if (len < 32) {
533 writeByte((byte) (BYTES_0_31 + len));
534 write(b, 0, b.length);
535 } else {
536 writeByte((byte) type);
537 writeVarInt(b.length);
538 write(b, 0, b.length);
539 }
540 break;
541 }
542 case Value.UUID: {
543 writeByte((byte) type);
544 ValueUuid uuid = (ValueUuid) v;
545 writeLong(uuid.getHigh());
546 writeLong(uuid.getLow());
547 break;
548 }
549 case Value.STRING: {
550 String s = v.getString();
551 int len = s.length();
552 if (len < 32) {
553 writeByte((byte) (STRING_0_31 + len));
554 writeStringWithoutLength(s, len);
555 } else {
556 writeByte((byte) type);
557 writeString(s);
558 }
559 break;
560 }
561 case Value.STRING_IGNORECASE:
562 case Value.STRING_FIXED:
563 writeByte((byte) type);
564 writeString(v.getString());
565 break;
566 case Value.DOUBLE: {
567 double x = v.getDouble();
568 if (x == 1.0d) {
569 writeByte((byte) (DOUBLE_0_1 + 1));
570 } else {
571 long d = Double.doubleToLongBits(x);
572 if (d == ValueDouble.ZERO_BITS) {
573 writeByte((byte) DOUBLE_0_1);
574 } else {
575 writeByte((byte) type);
576 writeVarLong(Long.reverse(d));
577 }
578 }
579 break;
580 }
581 case Value.FLOAT: {
582 float x = v.getFloat();
583 if (x == 1.0f) {
584 writeByte((byte) (FLOAT_0_1 + 1));
585 } else {
586 int f = Float.floatToIntBits(x);
587 if (f == ValueFloat.ZERO_BITS) {
588 writeByte((byte) FLOAT_0_1);
589 } else {
590 writeByte((byte) type);
591 writeVarInt(Integer.reverse(f));
592 }
593 }
594 break;
595 }
596 case Value.BLOB:
597 case Value.CLOB: {
598 writeByte((byte) type);
599 if (v instanceof ValueLob) {
600 ValueLob lob = (ValueLob) v;
601 lob.convertToFileIfRequired(handler);
602 byte[] small = lob.getSmall();
603 if (small == null) {
604 int t = -1;
605 if (!lob.isLinked()) {
606 t = -2;
607 }
608 writeVarInt(t);
609 writeVarInt(lob.getTableId());
610 writeVarInt(lob.getObjectId());
611 writeVarLong(lob.getPrecision());
612 writeByte((byte) (lob.useCompression() ? 1 : 0));
613 if (t == -2) {
614 writeString(lob.getFileName());
615 }
616 } else {
617 writeVarInt(small.length);
618 write(small, 0, small.length);
619 }
620 } else {
621 ValueLobDb lob = (ValueLobDb) v;
622 byte[] small = lob.getSmall();
623 if (small == null) {
624 writeVarInt(-3);
625 writeVarInt(lob.getTableId());
626 writeVarLong(lob.getLobId());
627 writeVarLong(lob.getPrecision());
628 } else {
629 writeVarInt(small.length);
630 write(small, 0, small.length);
631 }
632 }
633 break;
634 }
635 case Value.ARRAY: {
636 writeByte((byte) type);
637 Value[] list = ((ValueArray) v).getList();
638 writeVarInt(list.length);
639 for (Value x : list) {
640 writeValue(x);
641 }
642 break;
643 }
644 case Value.RESULT_SET: {
645 writeByte((byte) type);
646 try {
647 ResultSet rs = ((ValueResultSet) v).getResultSet();
648 rs.beforeFirst();
649 ResultSetMetaData meta = rs.getMetaData();
650 int columnCount = meta.getColumnCount();
651 writeVarInt(columnCount);
652 for (int i = 0; i < columnCount; i++) {
653 writeString(meta.getColumnName(i + 1));
654 writeVarInt(meta.getColumnType(i + 1));
655 writeVarInt(meta.getPrecision(i + 1));
656 writeVarInt(meta.getScale(i + 1));
657 }
658 while (rs.next()) {
659 writeByte((byte) 1);
660 for (int i = 0; i < columnCount; i++) {
661 int t = DataType.convertSQLTypeToValueType(meta.getColumnType(i + 1));
662 Value val = DataType.readValue(null, rs, i + 1, t);
663 writeValue(val);
664 }
665 }
666 writeByte((byte) 0);
667 rs.beforeFirst();
668 } catch (SQLException e) {
669 throw DbException.convert(e);
670 }
671 break;
672 }
673 default:
674 DbException.throwInternalError("type=" + v.getType());
675 }
676 if (SysProperties.CHECK2) {
677 if (pos - start != getValueLen(v, handler)) {
678 throw DbException
679 .throwInternalError("value size error: got " + (pos - start) + " expected " + getValueLen(v, handler));
680 }
681 }
682 }
683
684 /**
685 * Read a value.
686 *
687 * @return the value
688 */
689 public Value readValue() {
690 int type = data[pos++] & 255;
691 switch (type) {
692 case Value.NULL:
693 return ValueNull.INSTANCE;
694 case BOOLEAN_TRUE:
695 return ValueBoolean.get(true);
696 case BOOLEAN_FALSE:
697 return ValueBoolean.get(false);
698 case INT_NEG:
699 return ValueInt.get(-readVarInt());
700 case Value.INT:
701 return ValueInt.get(readVarInt());
702 case LONG_NEG:
703 return ValueLong.get(-readVarLong());
704 case Value.LONG:
705 return ValueLong.get(readVarLong());
706 case Value.BYTE:
707 return ValueByte.get(readByte());
708 case Value.SHORT:
709 return ValueShort.get(readShortInt());
710 case DECIMAL_0_1:
711 return (ValueDecimal) ValueDecimal.ZERO;
712 case DECIMAL_0_1 + 1:
713 return (ValueDecimal) ValueDecimal.ONE;
714 case DECIMAL_SMALL_0:
715 return ValueDecimal.get(BigDecimal.valueOf(readVarLong()));
716 case DECIMAL_SMALL: {
717 int scale = readVarInt();
718 return ValueDecimal.get(BigDecimal.valueOf(readVarLong(), scale));
719 }
720 case Value.DECIMAL: {
721 int scale = readVarInt();
722 int len = readVarInt();
723 byte[] buff = Utils.newBytes(len);
724 read(buff, 0, len);
725 BigInteger b = new BigInteger(buff);
726 return ValueDecimal.get(new BigDecimal(b, scale));
727 }
728 case LOCAL_DATE: {
729 return ValueDate.fromDateValue(readVarLong());
730 }
731 case Value.DATE: {
732 long x = readVarLong() * MILLIS_PER_MINUTE;
733 return ValueDate.get(new Date(DateTimeUtils.getTimeUTCWithoutDst(x)));
734 }
735 case LOCAL_TIME: {
736 long nanos = readVarLong() * 1000000 + readVarLong();
737 return ValueTime.fromNanos(nanos);
738 }
739 case Value.TIME:
740 // need to normalize the year, month and day
741 return ValueTime.get(new Time(DateTimeUtils.getTimeUTCWithoutDst(readVarLong())));
742 case LOCAL_TIMESTAMP: {
743 long dateValue = readVarLong();
744 long nanos = readVarLong() * 1000000 + readVarLong();
745 return ValueTimestamp.fromDateValueAndNanos(dateValue, nanos);
746 }
747 case Value.TIMESTAMP: {
748 Timestamp ts = new Timestamp(DateTimeUtils.getTimeUTCWithoutDst(readVarLong()));
749 ts.setNanos(readVarInt());
750 return ValueTimestamp.get(ts);
751 }
752 case Value.BYTES: {
753 int len = readVarInt();
754 byte[] b = Utils.newBytes(len);
755 read(b, 0, len);
756 return ValueBytes.getNoCopy(b);
757 }
758 case Value.JAVA_OBJECT: {
759 int len = readVarInt();
760 byte[] b = Utils.newBytes(len);
761 read(b, 0, len);
762 return ValueJavaObject.getNoCopy(null, b);
763 }
764 case Value.UUID:
765 return ValueUuid.get(readLong(), readLong());
766 case Value.STRING:
767 return ValueString.get(readString());
768 case Value.STRING_IGNORECASE:
769 return ValueStringIgnoreCase.get(readString());
770 case Value.STRING_FIXED:
771 return ValueStringFixed.get(readString());
772 case FLOAT_0_1:
773 return ValueFloat.get(0);
774 case FLOAT_0_1 + 1:
775 return ValueFloat.get(1);
776 case DOUBLE_0_1:
777 return ValueDouble.get(0);
778 case DOUBLE_0_1 + 1:
779 return ValueDouble.get(1);
780 case Value.DOUBLE:
781 return ValueDouble.get(Double.longBitsToDouble(Long.reverse(readVarLong())));
782 case Value.FLOAT:
783 return ValueFloat.get(Float.intBitsToFloat(Integer.reverse(readVarInt())));
784 case Value.BLOB:
785 case Value.CLOB: {
786 int smallLen = readVarInt();
787 if (smallLen >= 0) {
788 byte[] small = Utils.newBytes(smallLen);
789 read(small, 0, smallLen);
790 return LobStorage.createSmallLob(type, small);
791 } else if (smallLen == -3) {
792 int tableId = readVarInt();
793 long lobId = readVarLong();
794 long precision = readVarLong();
795 LobStorage lobStorage = handler.getLobStorage();
796 ValueLobDb lob = ValueLobDb.create(type, lobStorage, tableId, lobId, null, precision);
797 return lob;
798 } else {
799 int tableId = readVarInt();
800 int objectId = readVarInt();
801 long precision = 0;
802 boolean compression = false;
803 // -1: regular
804 // -2: regular, but not linked (in this case: including file name)
805 if (smallLen == -1 || smallLen == -2) {
806 precision = readVarLong();
807 compression = readByte() == 1;
808 }
809 ValueLob lob = ValueLob.open(type, handler, tableId, objectId, precision, compression);
810 if (smallLen == -2) {
811 lob.setFileName(readString(), false);
812 }
813 return lob;
814 }
815 }
816 case Value.ARRAY: {
817 int len = readVarInt();
818 Value[] list = new Value[len];
819 for (int i = 0; i < len; i++) {
820 list[i] = readValue();
821 }
822 return ValueArray.get(list);
823 }
824 case Value.RESULT_SET: {
825 SimpleResultSet rs = new SimpleResultSet();
826 int columns = readVarInt();
827 for (int i = 0; i < columns; i++) {
828 rs.addColumn(readString(), readVarInt(), readVarInt(), readVarInt());
829 }
830 while (true) {
831 if (readByte() == 0) {
832 break;
833 }
834 Object[] o = new Object[columns];
835 for (int i = 0; i < columns; i++) {
836 o[i] = readValue().getObject();
837 }
838 rs.addRow(o);
839 }
840 return ValueResultSet.get(rs);
841 }
842 default:
843 if (type >= INT_0_15 && type < INT_0_15 + 16) {
844 return ValueInt.get(type - INT_0_15);
845 } else if (type >= LONG_0_7 && type < LONG_0_7 + 8) {
846 return ValueLong.get(type - LONG_0_7);
847 } else if (type >= BYTES_0_31 && type < BYTES_0_31 + 32) {
848 int len = type - BYTES_0_31;
849 byte[] b = Utils.newBytes(len);
850 read(b, 0, len);
851 return ValueBytes.getNoCopy(b);
852 } else if (type >= STRING_0_31 && type < STRING_0_31 + 32) {
853 return ValueString.get(readString(type - STRING_0_31));
854 }
855 throw DbException.get(ErrorCode.FILE_CORRUPTED_1, "type: " + type);
856 }
857 }
858
859 /**
860 * Calculate the number of bytes required to encode the given value.
861 *
862 * @param v the value
863 * @return the number of bytes required to store this value
864 */
865 public int getValueLen(Value v) {
866 return getValueLen(v, handler);
867 }
868
869 /**
870 * Calculate the number of bytes required to encode the given value.
871 *
872 * @param v the value
873 * @param handler the data handler for lobs
874 * @return the number of bytes required to store this value
875 */
876 private static int getValueLen(Value v, DataHandler handler) {
877 if (v == ValueNull.INSTANCE) {
878 return 1;
879 }
880 switch (v.getType()) {
881 case Value.BOOLEAN:
882 return 1;
883 case Value.BYTE:
884 return 2;
885 case Value.SHORT:
886 return 3;
887 case Value.INT: {
888 int x = v.getInt();
889 if (x < 0) {
890 return 1 + getVarIntLen(-x);
891 } else if (x < 16) {
892 return 1;
893 } else {
894 return 1 + getVarIntLen(x);
895 }
896 }
897 case Value.LONG: {
898 long x = v.getLong();
899 if (x < 0) {
900 return 1 + getVarLongLen(-x);
901 } else if (x < 8) {
902 return 1;
903 } else {
904 return 1 + getVarLongLen(x);
905 }
906 }
907 case Value.DOUBLE: {
908 double x = v.getDouble();
909 if (x == 1.0d) {
910 return 1;
911 }
912 long d = Double.doubleToLongBits(x);
913 if (d == ValueDouble.ZERO_BITS) {
914 return 1;
915 }
916 return 1 + getVarLongLen(Long.reverse(d));
917 }
918 case Value.FLOAT: {
919 float x = v.getFloat();
920 if (x == 1.0f) {
921 return 1;
922 }
923 int f = Float.floatToIntBits(x);
924 if (f == ValueFloat.ZERO_BITS) {
925 return 1;
926 }
927 return 1 + getVarIntLen(Integer.reverse(f));
928 }
929 case Value.STRING: {
930 String s = v.getString();
931 int len = s.length();
932 if (len < 32) {
933 return 1 + getStringWithoutLengthLen(s, len);
934 }
935 return 1 + getStringLen(s);
936 }
937 case Value.STRING_IGNORECASE:
938 case Value.STRING_FIXED:
939 return 1 + getStringLen(v.getString());
940 case Value.DECIMAL: {
941 BigDecimal x = v.getBigDecimal();
942 if (BigDecimal.ZERO.equals(x)) {
943 return 1;
944 } else if (BigDecimal.ONE.equals(x)) {
945 return 1;
946 }
947 int scale = x.scale();
948 BigInteger b = x.unscaledValue();
949 int bits = b.bitLength();
950 if (bits <= 63) {
951 if (scale == 0) {
952 return 1 + getVarLongLen(b.longValue());
953 }
954 return 1 + getVarIntLen(scale) + getVarLongLen(b.longValue());
955 }
956 byte[] bytes = b.toByteArray();
957 return 1 + getVarIntLen(scale) + getVarIntLen(bytes.length) + bytes.length;
958 }
959 case Value.TIME:
960 if (SysProperties.STORE_LOCAL_TIME) {
961 long nanos = ((ValueTime) v).getNanos();
962 long millis = nanos / 1000000;
963 nanos -= millis * 1000000;
964 return 1 + getVarLongLen(millis) + getVarLongLen(nanos);
965 }
966 return 1 + getVarLongLen(DateTimeUtils.getTimeLocalWithoutDst(v.getTime()));
967 case Value.DATE: {
968 if (SysProperties.STORE_LOCAL_TIME) {
969 long dateValue = ((ValueDate) v).getDateValue();
970 return 1 + getVarLongLen(dateValue);
971 }
972 long x = DateTimeUtils.getTimeLocalWithoutDst(v.getDate());
973 return 1 + getVarLongLen(x / MILLIS_PER_MINUTE);
974 }
975 case Value.TIMESTAMP: {
976 if (SysProperties.STORE_LOCAL_TIME) {
977 ValueTimestamp ts = (ValueTimestamp) v;
978 long dateValue = ts.getDateValue();
979 long nanos = ts.getNanos();
980 long millis = nanos / 1000000;
981 nanos -= millis * 1000000;
982 return 1 + getVarLongLen(dateValue) + getVarLongLen(millis) + getVarLongLen(nanos);
983 }
984 Timestamp ts = v.getTimestamp();
985 return 1 + getVarLongLen(DateTimeUtils.getTimeLocalWithoutDst(ts)) + getVarIntLen(ts.getNanos());
986 }
987 case Value.JAVA_OBJECT: {
988 byte[] b = v.getBytesNoCopy();
989 return 1 + getVarIntLen(b.length) + b.length;
990 }
991 case Value.BYTES: {
992 byte[] b = v.getBytesNoCopy();
993 int len = b.length;
994 if (len < 32) {
995 return 1 + b.length;
996 }
997 return 1 + getVarIntLen(b.length) + b.length;
998 }
999 case Value.UUID:
1000 return 1 + LENGTH_LONG + LENGTH_LONG;
1001 case Value.BLOB:
1002 case Value.CLOB: {
1003 int len = 1;
1004 if (v instanceof ValueLob) {
1005 ValueLob lob = (ValueLob) v;
1006 lob.convertToFileIfRequired(handler);
1007 byte[] small = lob.getSmall();
1008 if (small == null) {
1009 int t = -1;
1010 if (!lob.isLinked()) {
1011 t = -2;
1012 }
1013 len += getVarIntLen(t);
1014 len += getVarIntLen(lob.getTableId());
1015 len += getVarIntLen(lob.getObjectId());
1016 len += getVarLongLen(lob.getPrecision());
1017 len += 1;
1018 if (t == -2) {
1019 len += getStringLen(lob.getFileName());
1020 }
1021 } else {
1022 len += getVarIntLen(small.length);
1023 len += small.length;
1024 }
1025 } else {
1026 ValueLobDb lob = (ValueLobDb) v;
1027 byte[] small = lob.getSmall();
1028 if (small == null) {
1029 len += getVarIntLen(-3);
1030 len += getVarIntLen(lob.getTableId());
1031 len += getVarLongLen(lob.getLobId());
1032 len += getVarLongLen(lob.getPrecision());
1033 } else {
1034 len += getVarIntLen(small.length);
1035 len += small.length;
1036 }
1037 }
1038 return len;
1039 }
1040 case Value.ARRAY: {
1041 Value[] list = ((ValueArray) v).getList();
1042 int len = 1 + getVarIntLen(list.length);
1043 for (Value x : list) {
1044 len += getValueLen(x, handler);
1045 }
1046 return len;
1047 }
1048 case Value.RESULT_SET: {
1049 int len = 1;
1050 try {
1051 ResultSet rs = ((ValueResultSet) v).getResultSet();
1052 rs.beforeFirst();
1053 ResultSetMetaData meta = rs.getMetaData();
1054 int columnCount = meta.getColumnCount();
1055 len += getVarIntLen(columnCount);
1056 for (int i = 0; i < columnCount; i++) {
1057 len += getStringLen(meta.getColumnName(i + 1));
1058 len += getVarIntLen(meta.getColumnType(i + 1));
1059 len += getVarIntLen(meta.getPrecision(i + 1));
1060 len += getVarIntLen(meta.getScale(i + 1));
1061 }
1062 while (rs.next()) {
1063 len++;
1064 for (int i = 0; i < columnCount; i++) {
1065 int t = DataType.convertSQLTypeToValueType(meta.getColumnType(i + 1));
1066 Value val = DataType.readValue(null, rs, i + 1, t);
1067 len += getValueLen(val, handler);
1068 }
1069 }
1070 len++;
1071 rs.beforeFirst();
1072 } catch (SQLException e) {
1073 throw DbException.convert(e);
1074 }
1075 return len;
1076 }
1077 default:
1078 throw DbException.throwInternalError("type=" + v.getType());
1079 }
1080 }
1081
1082 /**
1083 * Set the current read / write position.
1084 *
1085 * @param pos the new position
1086 */
1087 public void setPos(int pos) {
1088 this.pos = pos;
1089 }
1090
1091 /**
1092 * Write a short integer at the current position.
1093 * The current position is incremented.
1094 *
1095 * @param x the value
1096 */
1097 public void writeShortInt(int x) {
1098 byte[] buff = data;
1099 buff[pos++] = (byte) (x >> 8);
1100 buff[pos++] = (byte) x;
1101 }
1102
1103 /**
1104 * Read an short integer at the current position.
1105 * The current position is incremented.
1106 *
1107 * @return the value
1108 */
1109 public short readShortInt() {
1110 byte[] buff = data;
1111 return (short) (((buff[pos++] & 0xff) << 8) + (buff[pos++] & 0xff));
1112 }
1113
1114 /**
1115 * Shrink the array to this size.
1116 *
1117 * @param size the new size
1118 */
1119 public void truncate(int size) {
1120 if (pos > size) {
1121 byte[] buff = new byte[size];
1122 System.arraycopy(data, 0, buff, 0, size);
1123 this.pos = size;
1124 data = buff;
1125 }
1126 }
1127
1128 /**
1129 * The number of bytes required for a variable size int.
1130 *
1131 * @param x the value
1132 * @return the len
1133 */
1134 private static int getVarIntLen(int x) {
1135 if ((x & (-1 << 7)) == 0) {
1136 return 1;
1137 } else if ((x & (-1 << 14)) == 0) {
1138 return 2;
1139 } else if ((x & (-1 << 21)) == 0) {
1140 return 3;
1141 } else if ((x & (-1 << 28)) == 0) {
1142 return 4;
1143 }
1144 return 5;
1145 }
1146
1147 /**
1148 * Write a variable size int.
1149 *
1150 * @param x the value
1151 */
1152 public void writeVarInt(int x) {
1153 while ((x & ~0x7f) != 0) {
1154 data[pos++] = (byte) (0x80 | (x & 0x7f));
1155 x >>>= 7;
1156 }
1157 data[pos++] = (byte) x;
1158 }
1159
1160 /**
1161 * Read a variable size int.
1162 *
1163 * @return the value
1164 */
1165 public int readVarInt() {
1166 int b = data[pos];
1167 if (b >= 0) {
1168 pos++;
1169 return b;
1170 }
1171 // a separate function so that this one can be inlined
1172 return readVarIntRest(b);
1173 }
1174
1175 private int readVarIntRest(int b) {
1176 int x = b & 0x7f;
1177 b = data[pos + 1];
1178 if (b >= 0) {
1179 pos += 2;
1180 return x | (b << 7);
1181 }
1182 x |= (b & 0x7f) << 7;
1183 b = data[pos + 2];
1184 if (b >= 0) {
1185 pos += 3;
1186 return x | (b << 14);
1187 }
1188 x |= (b & 0x7f) << 14;
1189 b = data[pos + 3];
1190 if (b >= 0) {
1191 pos += 4;
1192 return x | b << 21;
1193 }
1194 x |= ((b & 0x7f) << 21) | (data[pos + 4] << 28);
1195 pos += 5;
1196 return x;
1197 }
1198
1199 /**
1200 * The number of bytes required for a variable size long.
1201 *
1202 * @param x the value
1203 * @return the len
1204 */
1205 public static int getVarLongLen(long x) {
1206 int i = 1;
1207 while (true) {
1208 x >>>= 7;
1209 if (x == 0) {
1210 return i;
1211 }
1212 i++;
1213 }
1214 }
1215
1216 /**
1217 * Write a variable size long.
1218 *
1219 * @param x the value
1220 */
1221 public void writeVarLong(long x) {
1222 while ((x & ~0x7f) != 0) {
1223 data[pos++] = (byte) ((x & 0x7f) | 0x80);
1224 x >>>= 7;
1225 }
1226 data[pos++] = (byte) x;
1227 }
1228
1229 /**
1230 * Read a variable size long.
1231 *
1232 * @return the value
1233 */
1234 public long readVarLong() {
1235 long x = data[pos++];
1236 if (x >= 0) {
1237 return x;
1238 }
1239 x &= 0x7f;
1240 for (int s = 7;; s += 7) {
1241 long b = data[pos++];
1242 x |= (b & 0x7f) << s;
1243 if (b >= 0) {
1244 return x;
1245 }
1246 }
1247 }
1248
1249 /**
1250 * Check if there is still enough capacity in the buffer.
1251 * This method extends the buffer if required.
1252 *
1253 * @param plus the number of additional bytes required
1254 */
1255 public void checkCapacity(int plus) {
1256 if (pos + plus >= data.length) {
1257 // a separate method to simplify inlining
1258 expand(plus);
1259 }
1260 }
1261
1262 private void expand(int plus) {
1263 byte[] d = Utils.newBytes((data.length + plus) * 2);
1264 // must copy everything, because pos could be 0 and data may be
1265 // still required
1266 System.arraycopy(data, 0, d, 0, data.length);
1267 data = d;
1268 }
1269
1270 /**
1271 * Fill up the buffer with empty space and an (initially empty) checksum
1272 * until the size is a multiple of Constants.FILE_BLOCK_SIZE.
1273 */
1274 public void fillAligned() {
1275 // 0..6 > 8, 7..14 > 16, 15..22 > 24, ...
1276 int len = MathUtils.roundUpInt(pos + 2, Constants.FILE_BLOCK_SIZE);
1277 pos = len;
1278 if (data.length < len) {
1279 checkCapacity(len - data.length);
1280 }
1281 }
1282
1283 /**
1284 * Copy a String from a reader to an output stream.
1285 *
1286 * @param source the reader
1287 * @param target the output stream
1288 */
1289 public static void copyString(Reader source, OutputStream target) throws IOException {
1290 char[] buff = new char[Constants.IO_BUFFER_SIZE];
1291 Data d = new Data(null, new byte[3 * Constants.IO_BUFFER_SIZE]);
1292 while (true) {
1293 int l = source.read(buff);
1294 if (l < 0) {
1295 break;
1296 }
1297 d.writeStringWithoutLength(buff, l);
1298 target.write(d.data, 0, d.pos);
1299 d.reset();
1300 }
1301 }
1302
1303 public DataHandler getHandler() {
1304 return handler;
1305 }
1306
1307 }
1308