예제 #1
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);
   }
 }
예제 #2
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);
   }
 }
예제 #3
0
 @Override
 public void remove() {
   if (fileName != null) {
     if (tempFile != null) {
       tempFile.stopAutoDelete();
     }
     // synchronize on the database, to avoid concurrent temp file
     // creation / deletion / backup
     synchronized (handler.getLobSyncObject()) {
       FileUtils.delete(fileName);
     }
   }
   if (handler != null) {
     handler.getLobStorage().removeLob(this);
   }
 }
예제 #4
0
 private static String createTempLobFileName(DataHandler handler) throws IOException {
   String path = handler.getDatabasePath();
   if (path.length() == 0) {
     path = SysProperties.PREFIX_TEMP_FILE;
   }
   return FileUtils.createTempFile(path, Constants.SUFFIX_TEMP_FILE, true, true);
 }
예제 #5
0
 @Override
 public InputStream getInputStream() {
   if (small != null) {
     return new ByteArrayInputStream(small);
   } else if (fileName != null) {
     FileStore store = handler.openFile(fileName, "r", true);
     boolean alwaysClose = SysProperties.lobCloseBetweenReads;
     return new BufferedInputStream(
         new FileStoreInputStream(store, handler, false, alwaysClose), Constants.IO_BUFFER_SIZE);
   }
   long byteCount = (type == Value.BLOB) ? precision : -1;
   try {
     return handler.getLobStorage().getInputStream(this, hmac, byteCount);
   } catch (IOException e) {
     throw DbException.convertIOException(e, toString());
   }
 }
예제 #6
0
 @Override
 public Value copy(DataHandler database, int tableId) {
   if (small == null) {
     Value v2 = handler.getLobStorage().copyLob(this, tableId, getPrecision());
     return v2;
   } else if (small.length > database.getMaxLengthInplaceLob()) {
     LobStorageInterface s = database.getLobStorage();
     Value v;
     if (type == Value.BLOB) {
       v = s.createBlob(getInputStream(), getPrecision());
     } else {
       v = s.createClob(getReader(), getPrecision());
     }
     Value v2 = v.copy(database, tableId);
     v.remove();
     return v2;
   }
   return this;
 }
예제 #7
0
 /**
  * Create an independent copy of this value, that will be bound to a result.
  *
  * @return the value (this for small objects)
  */
 @Override
 public ValueLobDb copyToResult() {
   if (handler == null) {
     return this;
   }
   LobStorageInterface s = handler.getLobStorage();
   if (s.isReadOnly()) {
     return this;
   }
   return s.copyLob(this, LobStorageFrontend.TABLE_RESULT, getPrecision());
 }
예제 #8
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);
 }
예제 #9
0
 private static int getBufferSize(DataHandler handler, boolean compress, long remaining) {
   if (remaining < 0 || remaining > Integer.MAX_VALUE) {
     remaining = Integer.MAX_VALUE;
   }
   int inplace = handler.getMaxLengthInplaceLob();
   long m = compress ? Constants.IO_BUFFER_SIZE_COMPRESS : Constants.IO_BUFFER_SIZE;
   if (m < remaining && m <= inplace) {
     // using "1L" to force long arithmetic because
     // inplace could be Integer.MAX_VALUE
     m = Math.min(remaining, inplace + 1L);
     // the buffer size must be bigger than the inplace lob, otherwise we
     // can't know if it must be stored in-place or not
     m = MathUtils.roundUpLong(m, Constants.IO_BUFFER_SIZE);
   }
   m = Math.min(remaining, m);
   m = MathUtils.convertLongToInt(m);
   if (m < 0) {
     m = Integer.MAX_VALUE;
   }
   return (int) m;
 }
예제 #10
0
 /**
  * Read a value.
  *
  * @return the value
  */
 private Value readValue(ByteBuffer buff) {
   int type = buff.get() & 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(buff));
     case Value.INT:
       return ValueInt.get(readVarInt(buff));
     case LONG_NEG:
       return ValueLong.get(-readVarLong(buff));
     case Value.LONG:
       return ValueLong.get(readVarLong(buff));
     case Value.BYTE:
       return ValueByte.get(buff.get());
     case Value.SHORT:
       return ValueShort.get(buff.getShort());
     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(buff)));
     case DECIMAL_SMALL:
       {
         int scale = readVarInt(buff);
         return ValueDecimal.get(BigDecimal.valueOf(readVarLong(buff), scale));
       }
     case Value.DECIMAL:
       {
         int scale = readVarInt(buff);
         int len = readVarInt(buff);
         byte[] buff2 = DataUtils.newBytes(len);
         buff.get(buff2, 0, len);
         BigInteger b = new BigInteger(buff2);
         return ValueDecimal.get(new BigDecimal(b, scale));
       }
     case LOCAL_DATE:
       {
         return ValueDate.fromDateValue(readVarLong(buff));
       }
     case Value.DATE:
       {
         long x = readVarLong(buff) * MILLIS_PER_MINUTE;
         return ValueDate.get(new Date(DateTimeUtils.getTimeUTCWithoutDst(x)));
       }
     case LOCAL_TIME:
       {
         long nanos = readVarLong(buff) * 1000000 + readVarLong(buff);
         return ValueTime.fromNanos(nanos);
       }
     case Value.TIME:
       // need to normalize the year, month and day
       return ValueTime.get(new Time(DateTimeUtils.getTimeUTCWithoutDst(readVarLong(buff))));
     case LOCAL_TIMESTAMP:
       {
         long dateValue = readVarLong(buff);
         long nanos = readVarLong(buff) * 1000000 + readVarLong(buff);
         return ValueTimestamp.fromDateValueAndNanos(dateValue, nanos);
       }
     case Value.TIMESTAMP:
       {
         Timestamp ts = new Timestamp(DateTimeUtils.getTimeUTCWithoutDst(readVarLong(buff)));
         ts.setNanos(readVarInt(buff));
         return ValueTimestamp.get(ts);
       }
     case Value.BYTES:
       {
         int len = readVarInt(buff);
         byte[] b = DataUtils.newBytes(len);
         buff.get(b, 0, len);
         return ValueBytes.getNoCopy(b);
       }
     case Value.JAVA_OBJECT:
       {
         int len = readVarInt(buff);
         byte[] b = DataUtils.newBytes(len);
         buff.get(b, 0, len);
         return ValueJavaObject.getNoCopy(null, b);
       }
     case Value.UUID:
       return ValueUuid.get(buff.getLong(), buff.getLong());
     case Value.STRING:
       return ValueString.get(readString(buff));
     case Value.STRING_IGNORECASE:
       return ValueStringIgnoreCase.get(readString(buff));
     case Value.STRING_FIXED:
       return ValueStringFixed.get(readString(buff));
     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(buff))));
     case Value.FLOAT:
       return ValueFloat.get(Float.intBitsToFloat(Integer.reverse(readVarInt(buff))));
     case Value.BLOB:
     case Value.CLOB:
       {
         int smallLen = readVarInt(buff);
         if (smallLen >= 0) {
           byte[] small = DataUtils.newBytes(smallLen);
           buff.get(small, 0, smallLen);
           return LobStorageFrontend.createSmallLob(type, small);
         } else if (smallLen == -3) {
           int tableId = readVarInt(buff);
           long lobId = readVarLong(buff);
           long precision = readVarLong(buff);
           LobStorageInterface lobStorage = handler.getLobStorage();
           ValueLobDb lob = ValueLobDb.create(type, lobStorage, tableId, lobId, null, precision);
           return lob;
         } else {
           int tableId = readVarInt(buff);
           int objectId = readVarInt(buff);
           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(buff);
             compression = buff.get() == 1;
           }
           if (smallLen == -2) {
             String filename = readString(buff);
             return ValueLob.openUnlinked(
                 type, handler, tableId, objectId, precision, compression, filename);
           }
           ValueLob lob =
               ValueLob.openLinked(type, handler, tableId, objectId, precision, compression);
           return lob;
         }
       }
     case Value.ARRAY:
       {
         int len = readVarInt(buff);
         Value[] list = new Value[len];
         for (int i = 0; i < len; i++) {
           list[i] = readValue(buff);
         }
         return ValueArray.get(list);
       }
     case Value.RESULT_SET:
       {
         SimpleResultSet rs = new SimpleResultSet();
         int columns = readVarInt(buff);
         for (int i = 0; i < columns; i++) {
           rs.addColumn(readString(buff), readVarInt(buff), readVarInt(buff), readVarInt(buff));
         }
         while (true) {
           if (buff.get() == 0) {
             break;
           }
           Object[] o = new Object[columns];
           for (int i = 0; i < columns; i++) {
             o[i] = readValue(buff).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);
         buff.get(b, 0, len);
         return ValueBytes.getNoCopy(b);
       } else if (type >= STRING_0_31 && type < STRING_0_31 + 32) {
         return ValueString.get(readString(buff, type - STRING_0_31));
       }
       throw DbException.get(ErrorCode.FILE_CORRUPTED_1, "type: " + type);
   }
 }