@Override
 Value getMergedValue(Database database, int dataType, boolean distinct) {
   if (distinct) {
     count = 0;
     groupDistinct(database, dataType);
   }
   Value v = null;
   switch (aggregateType) {
     case Aggregate.SUM:
     case Aggregate.MIN:
     case Aggregate.MAX:
     case Aggregate.BOOL_AND:
     case Aggregate.BOOL_OR:
     case Aggregate.BIT_AND:
     case Aggregate.BIT_OR:
       v = value;
       break;
     case Aggregate.AVG:
     case Aggregate.STDDEV_POP:
     case Aggregate.STDDEV_SAMP:
     case Aggregate.VAR_POP:
     case Aggregate.VAR_SAMP:
     default:
       DbException.throwInternalError("type=" + aggregateType);
   }
   return v == null ? ValueNull.INSTANCE : v.convertTo(dataType);
 }
 @Override
 Value getValue(Database database, int dataType, boolean distinct) {
   if (distinct) {
     count = 0;
     groupDistinct(database, dataType);
   }
   Value v = null;
   switch (aggregateType) {
     case Aggregate.SUM:
     case Aggregate.MIN:
     case Aggregate.MAX:
     case Aggregate.BIT_OR:
     case Aggregate.BIT_AND:
     case Aggregate.BOOL_OR:
     case Aggregate.BOOL_AND:
       v = value;
       break;
     case Aggregate.AVG:
       if (value != null) {
         v = Aggregate.divide(value, count);
       }
       break;
     case Aggregate.STDDEV_POP:
       {
         if (count < 1) {
           return ValueNull.INSTANCE;
         }
         v = ValueDouble.get(Math.sqrt(m2 / count));
         break;
       }
     case Aggregate.STDDEV_SAMP:
       {
         if (count < 2) {
           return ValueNull.INSTANCE;
         }
         v = ValueDouble.get(Math.sqrt(m2 / (count - 1)));
         break;
       }
     case Aggregate.VAR_POP:
       {
         if (count < 1) {
           return ValueNull.INSTANCE;
         }
         v = ValueDouble.get(m2 / count);
         break;
       }
     case Aggregate.VAR_SAMP:
       {
         if (count < 2) {
           return ValueNull.INSTANCE;
         }
         v = ValueDouble.get(m2 / (count - 1));
         break;
       }
     default:
       DbException.throwInternalError("type=" + aggregateType);
   }
   return v == null ? ValueNull.INSTANCE : v.convertTo(dataType);
 }
 @Override
 void add(Database database, int dataType, boolean distinct, Value v) {
   if (v == ValueNull.INSTANCE) {
     return;
   }
   count++;
   if (distinct) {
     if (distinctValues == null) {
       distinctValues = ValueHashMap.newInstance();
     }
     distinctValues.put(v, this);
     return;
   }
   switch (aggregateType) {
     case Aggregate.SUM:
       if (value == null) {
         value = v.convertTo(dataType);
       } else {
         v = v.convertTo(value.getType());
         value = value.add(v);
       }
       break;
     case Aggregate.AVG:
       if (value == null) {
         value = v.convertTo(DataType.getAddProofType(dataType));
       } else {
         v = v.convertTo(value.getType());
         value = value.add(v);
       }
       break;
     case Aggregate.MIN:
       if (value == null || database.compare(v, value) < 0) {
         value = v;
       }
       break;
     case Aggregate.MAX:
       if (value == null || database.compare(v, value) > 0) {
         value = v;
       }
       break;
     case Aggregate.STDDEV_POP:
     case Aggregate.STDDEV_SAMP:
     case Aggregate.VAR_POP:
     case Aggregate.VAR_SAMP:
       {
         // Using Welford's method, see also
         // http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
         // http://www.johndcook.com/standard_deviation.html
         double x = v.getDouble();
         if (count == 1) {
           mean = x;
           m2 = 0;
         } else {
           double delta = x - mean;
           mean += delta / count;
           m2 += delta * (x - mean);
         }
         break;
       }
     case Aggregate.BOOL_AND:
       v = v.convertTo(Value.BOOLEAN);
       if (value == null) {
         value = v;
       } else {
         value =
             ValueBoolean.get(value.getBoolean().booleanValue() && v.getBoolean().booleanValue());
       }
       break;
     case Aggregate.BOOL_OR:
       v = v.convertTo(Value.BOOLEAN);
       if (value == null) {
         value = v;
       } else {
         value =
             ValueBoolean.get(value.getBoolean().booleanValue() || v.getBoolean().booleanValue());
       }
       break;
     case Aggregate.BIT_AND:
       if (value == null) {
         value = v.convertTo(dataType);
       } else {
         value = ValueLong.get(value.getLong() & v.getLong()).convertTo(dataType);
       }
       break;
     case Aggregate.BIT_OR:
       if (value == null) {
         value = v.convertTo(dataType);
       } else {
         value = ValueLong.get(value.getLong() | v.getLong()).convertTo(dataType);
       }
       break;
     default:
       DbException.throwInternalError("type=" + aggregateType);
   }
 }
 @Override
 void merge(Database database, int dataType, boolean distinct, Value v) {
   if (v == ValueNull.INSTANCE) {
     return;
   }
   count++;
   if (distinct) {
     if (distinctValues == null) {
       distinctValues = ValueHashMap.newInstance();
     }
     distinctValues.put(v, this);
     return;
   }
   switch (aggregateType) {
     case Aggregate.SUM:
       if (value == null) {
         value = v.convertTo(dataType);
       } else {
         v = v.convertTo(value.getType());
         value = value.add(v);
       }
       break;
     case Aggregate.MIN:
       if (value == null || database.compare(v, value) < 0) {
         value = v;
       }
       break;
     case Aggregate.MAX:
       if (value == null || database.compare(v, value) > 0) {
         value = v;
       }
       break;
     case Aggregate.BOOL_AND:
       v = v.convertTo(Value.BOOLEAN);
       if (value == null) {
         value = v;
       } else {
         value =
             ValueBoolean.get(value.getBoolean().booleanValue() && v.getBoolean().booleanValue());
       }
       break;
     case Aggregate.BOOL_OR:
       v = v.convertTo(Value.BOOLEAN);
       if (value == null) {
         value = v;
       } else {
         value =
             ValueBoolean.get(value.getBoolean().booleanValue() || v.getBoolean().booleanValue());
       }
       break;
     case Aggregate.BIT_AND:
       if (value == null) {
         value = v.convertTo(dataType);
       } else {
         value = ValueLong.get(value.getLong() & v.getLong()).convertTo(dataType);
       }
       break;
     case Aggregate.BIT_OR:
       if (value == null) {
         value = v.convertTo(dataType);
       } else {
         value = ValueLong.get(value.getLong() | v.getLong()).convertTo(dataType);
       }
       break;
       // 这5个在分布式环境下会进行重写,所以合并时是不会出现的
     case Aggregate.AVG:
     case Aggregate.STDDEV_POP:
     case Aggregate.STDDEV_SAMP:
     case Aggregate.VAR_POP:
     case Aggregate.VAR_SAMP:
     default:
       DbException.throwInternalError("type=" + aggregateType);
   }
 }
Example #5
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());
   }
 }
Example #6
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));
     }
   }
 }