예제 #1
1
 @Override
 public Value createBlob(InputStream in, long maxLength) {
   init();
   int type = Value.BLOB;
   if (maxLength < 0) {
     maxLength = Long.MAX_VALUE;
   }
   int max = (int) Math.min(maxLength, database.getMaxLengthInplaceLob());
   try {
     if (max != 0 && max < Integer.MAX_VALUE) {
       BufferedInputStream b = new BufferedInputStream(in, max);
       b.mark(max);
       byte[] small = new byte[max];
       int len = IOUtils.readFully(b, small, max);
       if (len < max) {
         if (len < small.length) {
           small = Arrays.copyOf(small, len);
         }
         return ValueLobDb.createSmallLob(type, small);
       }
       b.reset();
       in = b;
     }
     if (maxLength != Long.MAX_VALUE) {
       in = new LimitInputStream(in, maxLength);
     }
     return createLob(in, type);
   } catch (IllegalStateException e) {
     throw DbException.get(ErrorCode.OBJECT_CLOSED, e);
   } catch (IOException e) {
     throw DbException.convertIOException(e, null);
   }
 }
예제 #2
0
 @Override
 public void removeLob(ValueLobDb lob) {
   init();
   int tableId = lob.getTableId();
   long lobId = lob.getLobId();
   removeLob(tableId, lobId);
 }
예제 #3
0
 @Override
 public Value convertPrecision(long precision, boolean force) {
   if (this.precision <= precision) {
     return this;
   }
   ValueLobDb lob;
   if (type == CLOB) {
     if (handler == null) {
       try {
         int p = MathUtils.convertLongToInt(precision);
         String s = IOUtils.readStringAndClose(getReader(), p);
         byte[] data = s.getBytes(Constants.UTF8);
         lob = ValueLobDb.createSmallLob(type, data, s.length());
       } catch (IOException e) {
         throw DbException.convertIOException(e, null);
       }
     } else {
       lob = ValueLobDb.createTempClob(getReader(), precision, handler);
     }
   } else {
     if (handler == null) {
       try {
         int p = MathUtils.convertLongToInt(precision);
         byte[] data = IOUtils.readBytesAndClose(getInputStream(), p);
         lob = ValueLobDb.createSmallLob(type, data, data.length);
       } catch (IOException e) {
         throw DbException.convertIOException(e, null);
       }
     } else {
       lob = ValueLobDb.createTempBlob(getInputStream(), precision, handler);
     }
   }
   return lob;
 }
예제 #4
0
  private void testCastTrim() {
    Value v;
    String spaces = new String(new char[100]).replace((char) 0, ' ');

    v = ValueArray.get(new Value[] {ValueString.get("hello"), ValueString.get("world")});
    assertEquals(10, v.getPrecision());
    assertEquals(5, v.convertPrecision(5, true).getPrecision());
    v = ValueArray.get(new Value[] {ValueString.get(""), ValueString.get("")});
    assertEquals(0, v.getPrecision());
    assertEquals("('')", v.convertPrecision(1, true).toString());

    v = ValueBytes.get(spaces.getBytes());
    assertEquals(100, v.getPrecision());
    assertEquals(10, v.convertPrecision(10, false).getPrecision());
    assertEquals(10, v.convertPrecision(10, false).getBytes().length);
    assertEquals(32, v.convertPrecision(10, false).getBytes()[9]);
    assertEquals(10, v.convertPrecision(10, true).getPrecision());

    final Value vd = ValueDecimal.get(new BigDecimal("1234567890.123456789"));
    assertEquals(19, vd.getPrecision());
    assertEquals("1234567890.1234567", vd.convertPrecision(10, true).getString());
    new AssertThrows(ErrorCode.NUMERIC_VALUE_OUT_OF_RANGE_1) {
      @Override
      public void test() {
        vd.convertPrecision(10, false);
      }
    };

    v = ValueLobDb.createSmallLob(Value.CLOB, spaces.getBytes(), 100);
    assertEquals(100, v.getPrecision());
    assertEquals(10, v.convertPrecision(10, false).getPrecision());
    assertEquals(10, v.convertPrecision(10, false).getString().length());
    assertEquals("          ", v.convertPrecision(10, false).getString());
    assertEquals(10, v.convertPrecision(10, true).getPrecision());

    v = ValueLobDb.createSmallLob(Value.BLOB, spaces.getBytes(), 100);
    assertEquals(100, v.getPrecision());
    assertEquals(10, v.convertPrecision(10, false).getPrecision());
    assertEquals(10, v.convertPrecision(10, false).getBytes().length);
    assertEquals(32, v.convertPrecision(10, false).getBytes()[9]);
    assertEquals(10, v.convertPrecision(10, true).getPrecision());

    ResultSet rs = new SimpleResultSet();
    v = ValueResultSet.get(rs);
    assertEquals(Integer.MAX_VALUE, v.getPrecision());
    assertEquals(Integer.MAX_VALUE, v.convertPrecision(10, false).getPrecision());
    assertTrue(rs == v.convertPrecision(10, false).getObject());
    assertFalse(rs == v.convertPrecision(10, true).getObject());
    assertEquals(Integer.MAX_VALUE, v.convertPrecision(10, true).getPrecision());

    v = ValueString.get(spaces);
    assertEquals(100, v.getPrecision());
    assertEquals(10, v.convertPrecision(10, false).getPrecision());
    assertEquals("          ", v.convertPrecision(10, false).getString());
    assertEquals("          ", v.convertPrecision(10, true).getString());
  }
예제 #5
0
 @Override
 public void setTable(ValueLobDb lob, int tableId) {
   init();
   long lobId = lob.getLobId();
   Object[] value = lobMap.remove(lobId);
   if (TRACE) {
     trace("move " + lob.getTableId() + "/" + lob.getLobId() + " > " + tableId + "/" + lobId);
   }
   value[1] = tableId;
   lobMap.put(lobId, value);
 }
예제 #6
0
 private void writeValue(Value v) throws IOException {
   if (v.getType() == Value.CLOB || v.getType() == Value.BLOB) {
     if (v instanceof ValueLobDb) {
       ValueLobDb lob = (ValueLobDb) v;
       if (lob.isStored()) {
         long id = lob.getLobId();
         lobs.put(id, new CachedInputStream(null));
       }
     }
   }
   transfer.writeValue(v);
 }
예제 #7
0
 /**
  * Create a temporary BLOB value from a stream.
  *
  * @param in the input stream
  * @param length the number of characters to read, or -1 for no limit
  * @param handler the data handler
  * @return the lob value
  */
 public static ValueLobDb createTempBlob(InputStream in, long length, DataHandler handler) {
   try {
     long remaining = Long.MAX_VALUE;
     boolean compress = handler.getLobCompressionAlgorithm(Value.BLOB) != null;
     if (length >= 0 && length < remaining) {
       remaining = length;
     }
     int len = getBufferSize(handler, compress, remaining);
     byte[] buff;
     if (len >= Integer.MAX_VALUE) {
       buff = IOUtils.readBytesAndClose(in, -1);
       len = buff.length;
     } else {
       buff = DataUtils.newBytes(len);
       len = IOUtils.readFully(in, buff, len);
     }
     if (len <= handler.getMaxLengthInplaceLob()) {
       byte[] small = DataUtils.newBytes(len);
       System.arraycopy(buff, 0, small, 0, len);
       return ValueLobDb.createSmallLob(Value.BLOB, small, small.length);
     }
     ValueLobDb lob = new ValueLobDb(handler, buff, len, in, remaining);
     return lob;
   } catch (IOException e) {
     throw DbException.convertIOException(e, null);
   }
 }
예제 #8
0
 /**
  * Create a temporary CLOB value from a stream.
  *
  * @param in the reader
  * @param length the number of characters to read, or -1 for no limit
  * @param handler the data handler
  * @return the lob value
  */
 public static ValueLobDb createTempClob(Reader in, long length, DataHandler handler) {
   BufferedReader reader;
   if (in instanceof BufferedReader) {
     reader = (BufferedReader) in;
   } else {
     reader = new BufferedReader(in, Constants.IO_BUFFER_SIZE);
   }
   try {
     boolean compress = handler.getLobCompressionAlgorithm(Value.CLOB) != null;
     long remaining = Long.MAX_VALUE;
     if (length >= 0 && length < remaining) {
       remaining = length;
     }
     int len = getBufferSize(handler, compress, remaining);
     char[] buff;
     if (len >= Integer.MAX_VALUE) {
       String data = IOUtils.readStringAndClose(reader, -1);
       buff = data.toCharArray();
       len = buff.length;
     } else {
       buff = new char[len];
       reader.mark(len);
       len = IOUtils.readFully(reader, buff, len);
     }
     if (len <= handler.getMaxLengthInplaceLob()) {
       byte[] small = new String(buff, 0, len).getBytes(Constants.UTF8);
       return ValueLobDb.createSmallLob(Value.CLOB, small, len);
     }
     reader.reset();
     ValueLobDb lob = new ValueLobDb(handler, reader, remaining);
     return lob;
   } catch (IOException e) {
     throw DbException.convertIOException(e, null);
   }
 }
예제 #9
0
 /**
  * Convert a lob to another data type. The data is fully read in memory except when converting to
  * BLOB or CLOB.
  *
  * @param t the new type
  * @return the converted value
  */
 @Override
 public Value convertTo(int t) {
   if (t == type) {
     return this;
   } else if (t == Value.CLOB) {
     if (handler != null) {
       Value copy = handler.getLobStorage().createClob(getReader(), -1);
       return copy;
     } else if (small != null) {
       return ValueLobDb.createSmallLob(t, small);
     }
   } else if (t == Value.BLOB) {
     if (handler != null) {
       Value copy = handler.getLobStorage().createBlob(getInputStream(), -1);
       return copy;
     } else if (small != null) {
       return ValueLobDb.createSmallLob(t, small);
     }
   }
   return super.convertTo(t);
 }
예제 #10
0
 @Override
 public Value createClob(Reader reader, long maxLength) {
   init();
   int type = Value.CLOB;
   if (maxLength < 0) {
     maxLength = Long.MAX_VALUE;
   }
   int max = (int) Math.min(maxLength, database.getMaxLengthInplaceLob());
   try {
     if (max != 0 && max < Integer.MAX_VALUE) {
       BufferedReader b = new BufferedReader(reader, max);
       b.mark(max);
       char[] small = new char[max];
       int len = IOUtils.readFully(b, small, max);
       if (len < max) {
         if (len < small.length) {
           small = Arrays.copyOf(small, len);
         }
         byte[] utf8 = new String(small, 0, len).getBytes(Constants.UTF8);
         return ValueLobDb.createSmallLob(type, utf8);
       }
       b.reset();
       reader = b;
     }
     CountingReaderInputStream in = new CountingReaderInputStream(reader, maxLength);
     ValueLobDb lob = createLob(in, type);
     // the length is not correct
     lob =
         ValueLobDb.create(type, database, lob.getTableId(), lob.getLobId(), null, in.getLength());
     return lob;
   } catch (IllegalStateException e) {
     throw DbException.get(ErrorCode.OBJECT_CLOSED, e);
   } catch (IOException e) {
     throw DbException.convertIOException(e, null);
   }
 }
예제 #11
0
 @Override
 public InputStream getInputStream(ValueLobDb lob, byte[] hmac, long byteCount)
     throws IOException {
   init();
   Object[] value = lobMap.get(lob.getLobId());
   if (value == null) {
     if (lob.getTableId() == LobStorageFrontend.TABLE_RESULT
         || lob.getTableId() == LobStorageFrontend.TABLE_ID_SESSION_VARIABLE) {
       throw DbException.get(
           ErrorCode.LOB_CLOSED_ON_TIMEOUT_1, "" + lob.getLobId() + "/" + lob.getTableId());
     }
     throw DbException.throwInternalError(
         "Lob not found: " + lob.getLobId() + "/" + lob.getTableId());
   }
   byte[] streamStoreId = (byte[]) value[0];
   return streamStore.get(streamStoreId);
 }
예제 #12
0
 private ValueLobDb createLob(InputStream in, int type) throws IOException {
   byte[] streamStoreId;
   try {
     streamStoreId = streamStore.put(in);
   } catch (Exception e) {
     throw DbException.convertToIOException(e);
   }
   long lobId = generateLobId();
   long length = streamStore.length(streamStoreId);
   int tableId = LobStorageFrontend.TABLE_TEMP;
   Object[] value = new Object[] {streamStoreId, tableId, length, 0};
   lobMap.put(lobId, value);
   Object[] key = new Object[] {streamStoreId, lobId};
   refMap.put(key, Boolean.TRUE);
   ValueLobDb lob = ValueLobDb.create(type, database, tableId, lobId, null, length);
   if (TRACE) {
     trace("create " + tableId + "/" + lobId);
   }
   return lob;
 }
예제 #13
0
 @Override
 public ValueLobDb copyLob(ValueLobDb old, int tableId, long length) {
   init();
   int type = old.getType();
   long oldLobId = old.getLobId();
   long oldLength = old.getPrecision();
   if (oldLength != length) {
     throw DbException.throwInternalError("Length is different");
   }
   Object[] value = lobMap.get(oldLobId);
   value = value.clone();
   byte[] streamStoreId = (byte[]) value[0];
   long lobId = generateLobId();
   value[1] = tableId;
   lobMap.put(lobId, value);
   Object[] key = new Object[] {streamStoreId, lobId};
   refMap.put(key, Boolean.TRUE);
   ValueLobDb lob = ValueLobDb.create(type, database, tableId, lobId, null, length);
   if (TRACE) {
     trace("copy " + old.getTableId() + "/" + old.getLobId() + " > " + tableId + "/" + lobId);
   }
   return lob;
 }
예제 #14
0
 /**
  * Calculate the number of bytes required to encode the given value.
  *
  * @param v the value
  * @param handler the data handler for lobs
  * @return the number of bytes required to store this value
  */
 public static int getValueLen(Value v, DataHandler handler) {
   if (v == ValueNull.INSTANCE) {
     return 1;
   }
   switch (v.getType()) {
     case Value.BOOLEAN:
       return 1;
     case Value.BYTE:
       return 2;
     case Value.SHORT:
       return 3;
     case Value.INT:
       {
         int x = v.getInt();
         if (x < 0) {
           return 1 + getVarIntLen(-x);
         } else if (x < 16) {
           return 1;
         } else {
           return 1 + getVarIntLen(x);
         }
       }
     case Value.LONG:
       {
         long x = v.getLong();
         if (x < 0) {
           return 1 + getVarLongLen(-x);
         } else if (x < 8) {
           return 1;
         } else {
           return 1 + getVarLongLen(x);
         }
       }
     case Value.DOUBLE:
       {
         double x = v.getDouble();
         if (x == 1.0d) {
           return 1;
         }
         long d = Double.doubleToLongBits(x);
         if (d == ValueDouble.ZERO_BITS) {
           return 1;
         }
         return 1 + getVarLongLen(Long.reverse(d));
       }
     case Value.FLOAT:
       {
         float x = v.getFloat();
         if (x == 1.0f) {
           return 1;
         }
         int f = Float.floatToIntBits(x);
         if (f == ValueFloat.ZERO_BITS) {
           return 1;
         }
         return 1 + getVarIntLen(Integer.reverse(f));
       }
     case Value.STRING:
       {
         String s = v.getString();
         int len = s.length();
         if (len < 32) {
           return 1 + getStringWithoutLengthLen(s, len);
         }
         return 1 + getStringLen(s);
       }
     case Value.STRING_IGNORECASE:
     case Value.STRING_FIXED:
       return 1 + getStringLen(v.getString());
     case Value.DECIMAL:
       {
         BigDecimal x = v.getBigDecimal();
         if (BigDecimal.ZERO.equals(x)) {
           return 1;
         } else if (BigDecimal.ONE.equals(x)) {
           return 1;
         }
         int scale = x.scale();
         BigInteger b = x.unscaledValue();
         int bits = b.bitLength();
         if (bits <= 63) {
           if (scale == 0) {
             return 1 + getVarLongLen(b.longValue());
           }
           return 1 + getVarIntLen(scale) + getVarLongLen(b.longValue());
         }
         byte[] bytes = b.toByteArray();
         return 1 + getVarIntLen(scale) + getVarIntLen(bytes.length) + bytes.length;
       }
     case Value.TIME:
       if (SysProperties.STORE_LOCAL_TIME) {
         long nanos = ((ValueTime) v).getNanos();
         long millis = nanos / 1000000;
         nanos -= millis * 1000000;
         return 1 + getVarLongLen(millis) + getVarLongLen(nanos);
       }
       return 1 + getVarLongLen(DateTimeUtils.getTimeLocalWithoutDst(v.getTime()));
     case Value.DATE:
       {
         if (SysProperties.STORE_LOCAL_TIME) {
           long dateValue = ((ValueDate) v).getDateValue();
           return 1 + getVarLongLen(dateValue);
         }
         long x = DateTimeUtils.getTimeLocalWithoutDst(v.getDate());
         return 1 + getVarLongLen(x / MILLIS_PER_MINUTE);
       }
     case Value.TIMESTAMP:
       {
         if (SysProperties.STORE_LOCAL_TIME) {
           ValueTimestamp ts = (ValueTimestamp) v;
           long dateValue = ts.getDateValue();
           long nanos = ts.getNanos();
           long millis = nanos / 1000000;
           nanos -= millis * 1000000;
           return 1 + getVarLongLen(dateValue) + getVarLongLen(millis) + getVarLongLen(nanos);
         }
         Timestamp ts = v.getTimestamp();
         return 1
             + getVarLongLen(DateTimeUtils.getTimeLocalWithoutDst(ts))
             + getVarIntLen(ts.getNanos());
       }
     case Value.GEOMETRY:
     case Value.JAVA_OBJECT:
       {
         byte[] b = v.getBytesNoCopy();
         return 1 + getVarIntLen(b.length) + b.length;
       }
     case Value.BYTES:
       {
         byte[] b = v.getBytesNoCopy();
         int len = b.length;
         if (len < 32) {
           return 1 + b.length;
         }
         return 1 + getVarIntLen(b.length) + b.length;
       }
     case Value.UUID:
       return 1 + LENGTH_LONG + LENGTH_LONG;
     case Value.BLOB:
     case Value.CLOB:
       {
         int len = 1;
         if (v instanceof ValueLob) {
           ValueLob lob = (ValueLob) v;
           lob.convertToFileIfRequired(handler);
           byte[] small = lob.getSmall();
           if (small == null) {
             int t = -1;
             if (!lob.isLinked()) {
               t = -2;
             }
             len += getVarIntLen(t);
             len += getVarIntLen(lob.getTableId());
             len += getVarIntLen(lob.getObjectId());
             len += getVarLongLen(lob.getPrecision());
             len += 1;
             if (t == -2) {
               len += getStringLen(lob.getFileName());
             }
           } else {
             len += getVarIntLen(small.length);
             len += small.length;
           }
         } else {
           ValueLobDb lob = (ValueLobDb) v;
           byte[] small = lob.getSmall();
           if (small == null) {
             len += getVarIntLen(-3);
             len += getVarIntLen(lob.getTableId());
             len += getVarLongLen(lob.getLobId());
             len += getVarLongLen(lob.getPrecision());
           } else {
             len += getVarIntLen(small.length);
             len += small.length;
           }
         }
         return len;
       }
     case Value.ARRAY:
       {
         Value[] list = ((ValueArray) v).getList();
         int len = 1 + getVarIntLen(list.length);
         for (Value x : list) {
           len += getValueLen(x, handler);
         }
         return len;
       }
     case Value.RESULT_SET:
       {
         int len = 1;
         try {
           ResultSet rs = ((ValueResultSet) v).getResultSet();
           rs.beforeFirst();
           ResultSetMetaData meta = rs.getMetaData();
           int columnCount = meta.getColumnCount();
           len += getVarIntLen(columnCount);
           for (int i = 0; i < columnCount; i++) {
             len += getStringLen(meta.getColumnName(i + 1));
             len += getVarIntLen(meta.getColumnType(i + 1));
             len += getVarIntLen(meta.getPrecision(i + 1));
             len += getVarIntLen(meta.getScale(i + 1));
           }
           while (rs.next()) {
             len++;
             for (int i = 0; i < columnCount; i++) {
               int t = DataType.getValueTypeFromResultSet(meta, i + 1);
               Value val = DataType.readValue(null, rs, i + 1, t);
               len += getValueLen(val, handler);
             }
           }
           len++;
           rs.beforeFirst();
         } catch (SQLException e) {
           throw DbException.convert(e);
         }
         return len;
       }
     default:
       throw DbException.throwInternalError("type=" + v.getType());
   }
 }
예제 #15
0
 /**
  * Read a value.
  *
  * @return the value
  */
 public Value readValue() {
   int type = data[pos++] & 255;
   switch (type) {
     case Value.NULL:
       return ValueNull.INSTANCE;
     case BOOLEAN_TRUE:
       return ValueBoolean.get(true);
     case BOOLEAN_FALSE:
       return ValueBoolean.get(false);
     case INT_NEG:
       return ValueInt.get(-readVarInt());
     case Value.INT:
       return ValueInt.get(readVarInt());
     case LONG_NEG:
       return ValueLong.get(-readVarLong());
     case Value.LONG:
       return ValueLong.get(readVarLong());
     case Value.BYTE:
       return ValueByte.get(readByte());
     case Value.SHORT:
       return ValueShort.get(readShortInt());
     case DECIMAL_0_1:
       return (ValueDecimal) ValueDecimal.ZERO;
     case DECIMAL_0_1 + 1:
       return (ValueDecimal) ValueDecimal.ONE;
     case DECIMAL_SMALL_0:
       return ValueDecimal.get(BigDecimal.valueOf(readVarLong()));
     case DECIMAL_SMALL:
       {
         int scale = readVarInt();
         return ValueDecimal.get(BigDecimal.valueOf(readVarLong(), scale));
       }
     case Value.DECIMAL:
       {
         int scale = readVarInt();
         int len = readVarInt();
         byte[] buff = DataUtils.newBytes(len);
         read(buff, 0, len);
         BigInteger b = new BigInteger(buff);
         return ValueDecimal.get(new BigDecimal(b, scale));
       }
     case LOCAL_DATE:
       {
         return ValueDate.fromDateValue(readVarLong());
       }
     case Value.DATE:
       {
         long x = readVarLong() * MILLIS_PER_MINUTE;
         return ValueDate.get(new Date(DateTimeUtils.getTimeUTCWithoutDst(x)));
       }
     case LOCAL_TIME:
       {
         long nanos = readVarLong() * 1000000 + readVarLong();
         return ValueTime.fromNanos(nanos);
       }
     case Value.TIME:
       // need to normalize the year, month and day
       return ValueTime.get(new Time(DateTimeUtils.getTimeUTCWithoutDst(readVarLong())));
     case LOCAL_TIMESTAMP:
       {
         long dateValue = readVarLong();
         long nanos = readVarLong() * 1000000 + readVarLong();
         return ValueTimestamp.fromDateValueAndNanos(dateValue, nanos);
       }
     case Value.TIMESTAMP:
       {
         Timestamp ts = new Timestamp(DateTimeUtils.getTimeUTCWithoutDst(readVarLong()));
         ts.setNanos(readVarInt());
         return ValueTimestamp.get(ts);
       }
     case Value.BYTES:
       {
         int len = readVarInt();
         byte[] b = DataUtils.newBytes(len);
         read(b, 0, len);
         return ValueBytes.getNoCopy(b);
       }
     case Value.GEOMETRY:
       {
         int len = readVarInt();
         byte[] b = DataUtils.newBytes(len);
         read(b, 0, len);
         return ValueGeometry.get(b);
       }
     case Value.JAVA_OBJECT:
       {
         int len = readVarInt();
         byte[] b = DataUtils.newBytes(len);
         read(b, 0, len);
         return ValueJavaObject.getNoCopy(null, b, handler);
       }
     case Value.UUID:
       return ValueUuid.get(readLong(), readLong());
     case Value.STRING:
       return ValueString.get(readString());
     case Value.STRING_IGNORECASE:
       return ValueStringIgnoreCase.get(readString());
     case Value.STRING_FIXED:
       return ValueStringFixed.get(readString());
     case FLOAT_0_1:
       return ValueFloat.get(0);
     case FLOAT_0_1 + 1:
       return ValueFloat.get(1);
     case DOUBLE_0_1:
       return ValueDouble.get(0);
     case DOUBLE_0_1 + 1:
       return ValueDouble.get(1);
     case Value.DOUBLE:
       return ValueDouble.get(Double.longBitsToDouble(Long.reverse(readVarLong())));
     case Value.FLOAT:
       return ValueFloat.get(Float.intBitsToFloat(Integer.reverse(readVarInt())));
     case Value.BLOB:
     case Value.CLOB:
       {
         int smallLen = readVarInt();
         if (smallLen >= 0) {
           byte[] small = DataUtils.newBytes(smallLen);
           read(small, 0, smallLen);
           return ValueLobDb.createSmallLob(type, small);
         } else if (smallLen == -3) {
           int tableId = readVarInt();
           long lobId = readVarLong();
           long precision = readVarLong();
           ValueLobDb lob = ValueLobDb.create(type, handler, tableId, lobId, null, precision);
           return lob;
         } else {
           int tableId = readVarInt();
           int objectId = readVarInt();
           long precision = 0;
           boolean compression = false;
           // -1: regular; -2: regular, but not linked (in this case:
           // including file name)
           if (smallLen == -1 || smallLen == -2) {
             precision = readVarLong();
             compression = readByte() == 1;
           }
           if (smallLen == -2) {
             String filename = readString();
             return ValueLob.openUnlinked(
                 type, handler, tableId, objectId, precision, compression, filename);
           }
           return ValueLob.openLinked(type, handler, tableId, objectId, precision, compression);
         }
       }
     case Value.ARRAY:
       {
         int len = readVarInt();
         Value[] list = new Value[len];
         for (int i = 0; i < len; i++) {
           list[i] = readValue();
         }
         return ValueArray.get(list);
       }
     case Value.RESULT_SET:
       {
         SimpleResultSet rs = new SimpleResultSet();
         rs.setAutoClose(false);
         int columns = readVarInt();
         for (int i = 0; i < columns; i++) {
           rs.addColumn(readString(), readVarInt(), readVarInt(), readVarInt());
         }
         while (true) {
           if (readByte() == 0) {
             break;
           }
           Object[] o = new Object[columns];
           for (int i = 0; i < columns; i++) {
             o[i] = readValue().getObject();
           }
           rs.addRow(o);
         }
         return ValueResultSet.get(rs);
       }
     default:
       if (type >= INT_0_15 && type < INT_0_15 + 16) {
         return ValueInt.get(type - INT_0_15);
       } else if (type >= LONG_0_7 && type < LONG_0_7 + 8) {
         return ValueLong.get(type - LONG_0_7);
       } else if (type >= BYTES_0_31 && type < BYTES_0_31 + 32) {
         int len = type - BYTES_0_31;
         byte[] b = DataUtils.newBytes(len);
         read(b, 0, len);
         return ValueBytes.getNoCopy(b);
       } else if (type >= STRING_0_31 && type < STRING_0_31 + 32) {
         return ValueString.get(readString(type - STRING_0_31));
       }
       throw DbException.get(ErrorCode.FILE_CORRUPTED_1, "type: " + type);
   }
 }
예제 #16
0
 /**
  * Append a value.
  *
  * @param v the value
  */
 public void writeValue(Value v) {
   int start = pos;
   if (v == ValueNull.INSTANCE) {
     data[pos++] = 0;
     return;
   }
   int type = v.getType();
   switch (type) {
     case Value.BOOLEAN:
       writeByte((byte) (v.getBoolean().booleanValue() ? BOOLEAN_TRUE : BOOLEAN_FALSE));
       break;
     case Value.BYTE:
       writeByte((byte) type);
       writeByte(v.getByte());
       break;
     case Value.SHORT:
       writeByte((byte) type);
       writeShortInt(v.getShort());
       break;
     case Value.INT:
       {
         int x = v.getInt();
         if (x < 0) {
           writeByte((byte) INT_NEG);
           writeVarInt(-x);
         } else if (x < 16) {
           writeByte((byte) (INT_0_15 + x));
         } else {
           writeByte((byte) type);
           writeVarInt(x);
         }
         break;
       }
     case Value.LONG:
       {
         long x = v.getLong();
         if (x < 0) {
           writeByte((byte) LONG_NEG);
           writeVarLong(-x);
         } else if (x < 8) {
           writeByte((byte) (LONG_0_7 + x));
         } else {
           writeByte((byte) type);
           writeVarLong(x);
         }
         break;
       }
     case Value.DECIMAL:
       {
         BigDecimal x = v.getBigDecimal();
         if (BigDecimal.ZERO.equals(x)) {
           writeByte((byte) DECIMAL_0_1);
         } else if (BigDecimal.ONE.equals(x)) {
           writeByte((byte) (DECIMAL_0_1 + 1));
         } else {
           int scale = x.scale();
           BigInteger b = x.unscaledValue();
           int bits = b.bitLength();
           if (bits <= 63) {
             if (scale == 0) {
               writeByte((byte) DECIMAL_SMALL_0);
               writeVarLong(b.longValue());
             } else {
               writeByte((byte) DECIMAL_SMALL);
               writeVarInt(scale);
               writeVarLong(b.longValue());
             }
           } else {
             writeByte((byte) type);
             writeVarInt(scale);
             byte[] bytes = b.toByteArray();
             writeVarInt(bytes.length);
             write(bytes, 0, bytes.length);
           }
         }
         break;
       }
     case Value.TIME:
       if (SysProperties.STORE_LOCAL_TIME) {
         writeByte((byte) LOCAL_TIME);
         ValueTime t = (ValueTime) v;
         long nanos = t.getNanos();
         long millis = nanos / 1000000;
         nanos -= millis * 1000000;
         writeVarLong(millis);
         writeVarLong(nanos);
       } else {
         writeByte((byte) type);
         writeVarLong(DateTimeUtils.getTimeLocalWithoutDst(v.getTime()));
       }
       break;
     case Value.DATE:
       {
         if (SysProperties.STORE_LOCAL_TIME) {
           writeByte((byte) LOCAL_DATE);
           long x = ((ValueDate) v).getDateValue();
           writeVarLong(x);
         } else {
           writeByte((byte) type);
           long x = DateTimeUtils.getTimeLocalWithoutDst(v.getDate());
           writeVarLong(x / MILLIS_PER_MINUTE);
         }
         break;
       }
     case Value.TIMESTAMP:
       {
         if (SysProperties.STORE_LOCAL_TIME) {
           writeByte((byte) LOCAL_TIMESTAMP);
           ValueTimestamp ts = (ValueTimestamp) v;
           long dateValue = ts.getDateValue();
           writeVarLong(dateValue);
           long nanos = ts.getNanos();
           long millis = nanos / 1000000;
           nanos -= millis * 1000000;
           writeVarLong(millis);
           writeVarLong(nanos);
         } else {
           Timestamp ts = v.getTimestamp();
           writeByte((byte) type);
           writeVarLong(DateTimeUtils.getTimeLocalWithoutDst(ts));
           writeVarInt(ts.getNanos());
         }
         break;
       }
     case Value.GEOMETRY:
     case Value.JAVA_OBJECT:
       {
         writeByte((byte) type);
         byte[] b = v.getBytesNoCopy();
         int len = b.length;
         writeVarInt(len);
         write(b, 0, len);
         break;
       }
     case Value.BYTES:
       {
         byte[] b = v.getBytesNoCopy();
         int len = b.length;
         if (len < 32) {
           writeByte((byte) (BYTES_0_31 + len));
           write(b, 0, len);
         } else {
           writeByte((byte) type);
           writeVarInt(len);
           write(b, 0, len);
         }
         break;
       }
     case Value.UUID:
       {
         writeByte((byte) type);
         ValueUuid uuid = (ValueUuid) v;
         writeLong(uuid.getHigh());
         writeLong(uuid.getLow());
         break;
       }
     case Value.STRING:
       {
         String s = v.getString();
         int len = s.length();
         if (len < 32) {
           writeByte((byte) (STRING_0_31 + len));
           writeStringWithoutLength(s, len);
         } else {
           writeByte((byte) type);
           writeString(s);
         }
         break;
       }
     case Value.STRING_IGNORECASE:
     case Value.STRING_FIXED:
       writeByte((byte) type);
       writeString(v.getString());
       break;
     case Value.DOUBLE:
       {
         double x = v.getDouble();
         if (x == 1.0d) {
           writeByte((byte) (DOUBLE_0_1 + 1));
         } else {
           long d = Double.doubleToLongBits(x);
           if (d == ValueDouble.ZERO_BITS) {
             writeByte((byte) DOUBLE_0_1);
           } else {
             writeByte((byte) type);
             writeVarLong(Long.reverse(d));
           }
         }
         break;
       }
     case Value.FLOAT:
       {
         float x = v.getFloat();
         if (x == 1.0f) {
           writeByte((byte) (FLOAT_0_1 + 1));
         } else {
           int f = Float.floatToIntBits(x);
           if (f == ValueFloat.ZERO_BITS) {
             writeByte((byte) FLOAT_0_1);
           } else {
             writeByte((byte) type);
             writeVarInt(Integer.reverse(f));
           }
         }
         break;
       }
     case Value.BLOB:
     case Value.CLOB:
       {
         writeByte((byte) type);
         if (v instanceof ValueLob) {
           ValueLob lob = (ValueLob) v;
           lob.convertToFileIfRequired(handler);
           byte[] small = lob.getSmall();
           if (small == null) {
             int t = -1;
             if (!lob.isLinked()) {
               t = -2;
             }
             writeVarInt(t);
             writeVarInt(lob.getTableId());
             writeVarInt(lob.getObjectId());
             writeVarLong(lob.getPrecision());
             writeByte((byte) (lob.isCompressed() ? 1 : 0));
             if (t == -2) {
               writeString(lob.getFileName());
             }
           } else {
             writeVarInt(small.length);
             write(small, 0, small.length);
           }
         } else {
           ValueLobDb lob = (ValueLobDb) v;
           byte[] small = lob.getSmall();
           if (small == null) {
             writeVarInt(-3);
             writeVarInt(lob.getTableId());
             writeVarLong(lob.getLobId());
             writeVarLong(lob.getPrecision());
           } else {
             writeVarInt(small.length);
             write(small, 0, small.length);
           }
         }
         break;
       }
     case Value.ARRAY:
       {
         writeByte((byte) type);
         Value[] list = ((ValueArray) v).getList();
         writeVarInt(list.length);
         for (Value x : list) {
           writeValue(x);
         }
         break;
       }
     case Value.RESULT_SET:
       {
         writeByte((byte) type);
         try {
           ResultSet rs = ((ValueResultSet) v).getResultSet();
           rs.beforeFirst();
           ResultSetMetaData meta = rs.getMetaData();
           int columnCount = meta.getColumnCount();
           writeVarInt(columnCount);
           for (int i = 0; i < columnCount; i++) {
             writeString(meta.getColumnName(i + 1));
             writeVarInt(meta.getColumnType(i + 1));
             writeVarInt(meta.getPrecision(i + 1));
             writeVarInt(meta.getScale(i + 1));
           }
           while (rs.next()) {
             writeByte((byte) 1);
             for (int i = 0; i < columnCount; i++) {
               int t = DataType.getValueTypeFromResultSet(meta, i + 1);
               Value val = DataType.readValue(null, rs, i + 1, t);
               writeValue(val);
             }
           }
           writeByte((byte) 0);
           rs.beforeFirst();
         } catch (SQLException e) {
           throw DbException.convert(e);
         }
         break;
       }
     default:
       DbException.throwInternalError("type=" + v.getType());
   }
   if (SysProperties.CHECK2) {
     if (pos - start != getValueLen(v, handler)) {
       throw DbException.throwInternalError(
           "value size error: got " + (pos - start) + " expected " + getValueLen(v, handler));
     }
   }
 }