Example #1
0
  /**
   * Add a table to the schema.
   *
   * @param data the create table information
   * @return the created {@link Table} object
   */
  public Table createTable(CreateTableData data) {
    synchronized (database) {
      if (!data.temporary || data.globalTemporary) {
        database.lockMeta(data.session);
      }
      data.schema = this;

      if (data.isMemoryTable()) data.storageEngineName = MemoryStorageEngine.NAME;

      // 用默认的数据库参数
      if (data.storageEngineName == null) {
        data.storageEngineName = database.getDefaultStorageEngineName();
      }
      if (data.storageEngineName != null) {
        StorageEngine engine = StorageEngineManager.getInstance().getEngine(data.storageEngineName);
        if (engine == null) {
          try {
            engine = (StorageEngine) Utils.loadUserClass(data.storageEngineName).newInstance();
            StorageEngineManager.getInstance().registerEngine(engine);
          } catch (Exception e) {
            throw DbException.convert(e);
          }
        }

        if (engine instanceof TableFactory) {
          return ((TableFactory) engine).createTable(data);
        }
        return new StandardTable(data, engine);
      }
      throw DbException.convert(new NullPointerException("table engine is null"));
    }
  }
Example #2
0
 /**
  * Add an object to this schema. This method must not be called within CreateSchemaObject; use
  * Database.addSchemaObject() instead
  *
  * @param obj the object to add
  */
 public void add(SchemaObject obj) {
   if (SysProperties.CHECK && obj.getSchema() != this) {
     DbException.throwInternalError("wrong schema");
   }
   String name = obj.getName();
   HashMap<String, SchemaObject> map = getMap(obj.getType());
   if (SysProperties.CHECK && map.get(name) != null) {
     DbException.throwInternalError("object already exists: " + name);
   }
   map.put(name, obj);
   freeUniqueName(name);
 }
Example #3
0
 /**
  * Get the index with the given name.
  *
  * @param name the index name
  * @return the index
  * @throws DbException if no such object exists
  */
 public Index getIndex(String name) {
   Index index = indexes.get(name);
   if (index == null) {
     throw DbException.get(ErrorCode.INDEX_NOT_FOUND_1, name);
   }
   return index;
 }
Example #4
0
 @SuppressWarnings("unchecked")
 private HashMap<String, SchemaObject> getMap(DbObjectType type) {
   HashMap<String, ? extends SchemaObject> result;
   switch (type) {
     case TABLE_OR_VIEW:
       result = tablesAndViews;
       break;
     case SEQUENCE:
       result = sequences;
       break;
     case INDEX:
       result = indexes;
       break;
     case TRIGGER:
       result = triggers;
       break;
     case CONSTRAINT:
       result = constraints;
       break;
     case CONSTANT:
       result = constants;
       break;
     case FUNCTION_ALIAS:
       result = functions;
       break;
     default:
       throw DbException.throwInternalError("type=" + type);
   }
   return (HashMap<String, SchemaObject>) result;
 }
Example #5
0
 /**
  * Get the sequence with the given name.
  *
  * @param sequenceName the sequence name
  * @return the sequence
  * @throws DbException if no such object exists
  */
 public Sequence getSequence(String sequenceName) {
   Sequence sequence = sequences.get(sequenceName);
   if (sequence == null) {
     throw DbException.get(ErrorCode.SEQUENCE_NOT_FOUND_1, sequenceName);
   }
   return sequence;
 }
Example #6
0
 @Override
 public Value getValue(ServerSession session) {
   query.setSession(session);
   Result result = query.query(2); // session.createSubqueryResult(query, 2); // query.query(2);
   try {
     int rowcount = result.getRowCount();
     if (rowcount > 1) {
       throw DbException.get(ErrorCode.SCALAR_SUBQUERY_CONTAINS_MORE_THAN_ONE_ROW);
     }
     Value v;
     if (rowcount <= 0) {
       v = ValueNull.INSTANCE;
     } else {
       result.next();
       Value[] values = result.currentRow();
       if (result.getVisibleColumnCount() == 1) {
         v = values[0];
       } else {
         v = ValueArray.get(values);
       }
     }
     return v;
   } finally {
     result.close();
   }
 }
Example #7
0
 /**
  * Creates a new sequence.
  *
  * @param schema the schema
  * @param id the object id
  * @param name the sequence name
  * @param startValue the first value to return
  * @param increment the increment count
  * @param cacheSize the number of entries to pre-fetch
  * @param minValue the minimum value
  * @param maxValue the maximum value
  * @param cycle whether to jump back to the min value if needed
  * @param belongsToTable whether this sequence belongs to a table (for auto-increment columns)
  */
 public Sequence(
     Schema schema,
     int id,
     String name,
     Long startValue,
     Long increment,
     Long cacheSize,
     Long minValue,
     Long maxValue,
     boolean cycle,
     boolean belongsToTable) {
   super(schema, id, name, Trace.SEQUENCE);
   this.increment = increment != null ? increment : 1;
   this.minValue = minValue != null ? minValue : getDefaultMinValue(startValue, this.increment);
   this.maxValue = maxValue != null ? maxValue : getDefaultMaxValue(startValue, this.increment);
   this.value = startValue != null ? startValue : getDefaultStartValue(this.increment);
   this.valueWithMargin = value;
   this.cacheSize = cacheSize != null ? Math.max(1, cacheSize) : DEFAULT_CACHE_SIZE;
   this.cycle = cycle;
   this.belongsToTable = belongsToTable;
   if (!isValid(this.value, this.minValue, this.maxValue, this.increment)) {
     throw DbException.get(
         ErrorCode.SEQUENCE_ATTRIBUTES_INVALID,
         name,
         String.valueOf(this.value),
         String.valueOf(this.minValue),
         String.valueOf(this.maxValue),
         String.valueOf(this.increment));
   }
 }
Example #8
0
 /**
  * Get the next value for this sequence.
  *
  * @param session the session
  * @return the next value
  */
 public long getNext(ServerSession session) {
   boolean needsFlush = false;
   long retVal;
   long flushValueWithMargin = -1;
   synchronized (this) {
     if ((increment > 0 && value >= valueWithMargin)
         || (increment < 0 && value <= valueWithMargin)) {
       valueWithMargin += increment * cacheSize;
       flushValueWithMargin = valueWithMargin;
       needsFlush = true;
     }
     if ((increment > 0 && value > maxValue) || (increment < 0 && value < minValue)) {
       if (cycle) {
         value = increment > 0 ? minValue : maxValue;
         valueWithMargin = value + (increment * cacheSize);
         flushValueWithMargin = valueWithMargin;
         needsFlush = true;
       } else {
         throw DbException.get(ErrorCode.SEQUENCE_EXHAUSTED, getName());
       }
     }
     retVal = value;
     value += increment;
   }
   if (needsFlush) {
     flush(session, flushValueWithMargin);
   }
   return retVal;
 }
Example #9
0
 /**
  * Allows the start value, increment, min value and max value to be updated atomically, including
  * atomic validation. Useful because setting these attributes one after the other could otherwise
  * result in an invalid sequence state (e.g. min value > max value, start value < min value, etc).
  *
  * @param startValue the new start value (<code>null</code> if no change)
  * @param minValue the new min value (<code>null</code> if no change)
  * @param maxValue the new max value (<code>null</code> if no change)
  * @param increment the new increment (<code>null</code> if no change)
  */
 public synchronized void modify(Long startValue, Long minValue, Long maxValue, Long increment) {
   if (startValue == null) {
     startValue = this.value;
   }
   if (minValue == null) {
     minValue = this.minValue;
   }
   if (maxValue == null) {
     maxValue = this.maxValue;
   }
   if (increment == null) {
     increment = this.increment;
   }
   if (!isValid(startValue, minValue, maxValue, increment)) {
     throw DbException.get(
         ErrorCode.SEQUENCE_ATTRIBUTES_INVALID,
         getName(),
         String.valueOf(startValue),
         String.valueOf(minValue),
         String.valueOf(maxValue),
         String.valueOf(increment));
   }
   this.value = startValue;
   this.valueWithMargin = startValue;
   this.minValue = minValue;
   this.maxValue = maxValue;
   this.increment = increment;
 }
Example #10
0
 /**
  * Get the user defined constant with the given name.
  *
  * @param constantName the constant name
  * @return the constant
  * @throws DbException if no such object exists
  */
 public Constant getConstant(String constantName) {
   Constant constant = constants.get(constantName);
   if (constant == null) {
     throw DbException.get(ErrorCode.CONSTANT_NOT_FOUND_1, constantName);
   }
   return constant;
 }
Example #11
0
 /**
  * Get the constraint with the given name.
  *
  * @param name the constraint name
  * @return the constraint
  * @throws DbException if no such object exists
  */
 public Constraint getConstraint(String name) {
   Constraint constraint = constraints.get(name);
   if (constraint == null) {
     throw DbException.get(ErrorCode.CONSTRAINT_NOT_FOUND_1, name);
   }
   return constraint;
 }
Example #12
0
 /**
  * Rename an object.
  *
  * @param obj the object to rename
  * @param newName the new name
  */
 public void rename(SchemaObject obj, String newName) {
   DbObjectType type = obj.getType();
   HashMap<String, SchemaObject> map = getMap(type);
   if (SysProperties.CHECK) {
     if (!map.containsKey(obj.getName())) {
       DbException.throwInternalError("not found: " + obj.getName());
     }
     if (obj.getName().equals(newName) || map.containsKey(newName)) {
       DbException.throwInternalError("object already exists: " + newName);
     }
   }
   obj.checkRename();
   map.remove(obj.getName());
   freeUniqueName(obj.getName());
   obj.rename(newName);
   map.put(newName, obj);
   freeUniqueName(newName);
 }
Example #13
0
 /**
  * Remove an object from this schema.
  *
  * @param obj the object to remove
  */
 public void remove(SchemaObject obj) {
   String objName = obj.getName();
   HashMap<String, SchemaObject> map = getMap(obj.getType());
   if (SysProperties.CHECK && !map.containsKey(objName)) {
     DbException.throwInternalError("not found: " + objName);
   }
   map.remove(objName);
   freeUniqueName(objName);
 }
Example #14
0
 /**
  * Get the table or view with the given name. Local temporary tables are also returned.
  *
  * @param session the session
  * @param name the table or view name
  * @return the table or view
  * @throws DbException if no such object exists
  */
 public Table getTableOrView(ServerSession session, String name) {
   Table table = tablesAndViews.get(name);
   if (table == null) {
     if (session != null) {
       table = session.findLocalTempTable(name);
     }
     if (table == null) {
       throw DbException.get(ErrorCode.TABLE_OR_VIEW_NOT_FOUND_1, name);
     }
   }
   return table;
 }
 @Override
 public int update() {
   session.commit(true);
   session.getUser().checkAdmin();
   Database db = session.getDatabase();
   if (db.findAggregate(name) != null || schema.findFunction(name) != null) {
     if (!ifNotExists) {
       throw DbException.get(ErrorCode.FUNCTION_ALIAS_ALREADY_EXISTS_1, name);
     }
   } else {
     int id = getObjectId();
     UserAggregate aggregate = new UserAggregate(db, id, name, javaClassName, force);
     db.addDatabaseObject(session, aggregate);
   }
   return 0;
 }
Example #16
0
 /**
  * Get or create a UUID for the given text representation.
  *
  * @param s the text representation of the UUID
  * @return the UUID
  */
 public static ValueUuid get(String s) {
   long low = 0, high = 0;
   for (int i = 0, j = 0, length = s.length(); i < length; i++) {
     char c = s.charAt(i);
     if (c >= '0' && c <= '9') {
       low = (low << 4) | (c - '0');
     } else if (c >= 'a' && c <= 'f') {
       low = (low << 4) | (c - 'a' + 0xa);
     } else if (c == '-') {
       continue;
     } else if (c >= 'A' && c <= 'F') {
       low = (low << 4) | (c - 'A' + 0xa);
     } else if (c <= ' ') {
       continue;
     } else {
       throw DbException.get(ErrorCode.DATA_CONVERSION_ERROR_1, s);
     }
     if (j++ == 15) {
       high = low;
       low = 0;
     }
   }
   return (ValueUuid) Value.cache(new ValueUuid(high, low));
 }
 @Override
 public boolean isEverything(ExpressionVisitor visitor) {
   throw DbException.throwInternalError();
 }
 @Override
 public int getDisplaySize() {
   throw DbException.throwInternalError();
 }
 @Override
 public void updateAggregate(ServerSession session) {
   DbException.throwInternalError();
 }
 @Override
 public int getScale() {
   throw DbException.throwInternalError();
 }
 @Override
 public long getPrecision() {
   throw DbException.throwInternalError();
 }
 @Override
 public Expression optimize(ServerSession session) {
   throw DbException.get(ErrorCode.SYNTAX_ERROR_1, table);
 }
 @Override
 public void setEvaluatable(TableFilter tableFilter, boolean b) {
   DbException.throwInternalError();
 }
 @Override
 public void mapColumns(ColumnResolver resolver, int level) {
   throw DbException.get(ErrorCode.SYNTAX_ERROR_1, table);
 }
 @Override
 public Value getValue(ServerSession session) {
   throw DbException.throwInternalError();
 }
Example #26
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.JAVA_OBJECT:
       {
         writeByte((byte) type);
         byte[] b = v.getBytesNoCopy();
         writeVarInt(b.length);
         write(b, 0, b.length);
         break;
       }
     case Value.BYTES:
       {
         byte[] b = v.getBytesNoCopy();
         int len = b.length;
         if (len < 32) {
           writeByte((byte) (BYTES_0_31 + len));
           write(b, 0, b.length);
         } else {
           writeByte((byte) type);
           writeVarInt(b.length);
           write(b, 0, b.length);
         }
         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);
         ValueLob lob = (ValueLob) v;
         byte[] small = lob.getSmall();
         if (small == null) {
           writeVarInt(-1);
           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.convertSQLTypeToValueType(meta.getColumnType(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));
     }
   }
 }
Example #27
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.JAVA_OBJECT:
       {
         int len = readVarInt();
         byte[] b = DataUtils.newBytes(len);
         read(b, 0, len);
         return ValueJavaObject.getNoCopy(null, b);
       }
     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 ValueLob.createSmallLob(type, small);
         } else {
           int tableId = readVarInt();
           long lobId = readVarLong();
           long precision = readVarLong();
           ValueLob lob = ValueLob.create(type, handler, tableId, lobId, null, precision);
           return lob;
         }
       }
     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();
         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);
   }
 }
Example #28
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.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;
         ValueLob lob = (ValueLob) v;
         byte[] small = lob.getSmall();
         if (small == null) {
           len += getVarIntLen(-1);
           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.convertSQLTypeToValueType(meta.getColumnType(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());
   }
 }