/** * Get the number of bytes required for the data. * * @param dummy the template buffer * @return the number of bytes */ public int getByteCount(Data dummy) { int size = 0; for (Value v : data) { size += dummy.getValueLen(v); } return size; }
@Override public int addRows(ArrayList<Value[]> rows) { if (sort != null) { sort.sort(rows); } Data buff = rowBuff; long start = file.getFilePointer(); ByteArrayOutputStream buffer = new ByteArrayOutputStream(); int bufferLen = 0; for (Value[] row : rows) { buff.reset(); buff.writeInt(0); for (int j = 0; j < columnCount; j++) { Value v = row[j]; buff.checkCapacity(buff.getValueLen(v)); buff.writeValue(v); } buff.fillAligned(); int len = buff.length(); buff.setInt(0, len); if (maxBufferSize > 0) { buffer.write(buff.getBytes(), 0, len); bufferLen += len; if (bufferLen > maxBufferSize) { byte[] data = buffer.toByteArray(); buffer.reset(); file.write(data, 0, data.length); bufferLen = 0; } } else { file.write(buff.getBytes(), 0, len); } } if (bufferLen > 0) { byte[] data = buffer.toByteArray(); file.write(data, 0, data.length); } if (sort != null) { ResultDiskTape tape = new ResultDiskTape(); tape.start = start; tape.end = file.getFilePointer(); tapes.add(tape); } else { mainTape.end = file.getFilePointer(); } rowCount += rows.size(); return rowCount; }
private void writeRow(Data buff, Row r) { buff.checkCapacity(1 + Data.LENGTH_INT * 8); buff.writeByte((byte) 1); buff.writeInt(r.getMemory()); int columnCount = r.getColumnCount(); buff.writeInt(columnCount); buff.writeLong(r.getKey()); buff.writeInt(r.getVersion()); buff.writeInt(r.isDeleted() ? 1 : 0); buff.writeInt(r.getSessionId()); for (int i = 0; i < columnCount; i++) { Value v = r.getValue(i); buff.checkCapacity(1); if (v == null) { buff.writeByte((byte) 0); } else { buff.writeByte((byte) 1); if (v.getType() == Value.CLOB || v.getType() == Value.BLOB) { // need to keep a reference to temporary lobs, // otherwise the temp file is deleted if (v.getSmall() == null && v.getTableId() == 0) { if (lobs == null) { lobs = New.arrayList(); } // need to create a copy, otherwise, // if stored multiple times, it may be renamed // and then not found v = v.copyToTemp(); lobs.add(v); } } buff.checkCapacity(buff.getValueLen(v)); buff.writeValue(v); } } }
private ByteBuffer writeValue(ByteBuffer buff, Value v) { int start = buff.position(); if (v == ValueNull.INSTANCE) { buff.put((byte) 0); return buff; } int type = v.getType(); switch (type) { case Value.BOOLEAN: buff.put((byte) (v.getBoolean().booleanValue() ? BOOLEAN_TRUE : BOOLEAN_FALSE)); break; case Value.BYTE: buff.put((byte) type); buff.put(v.getByte()); break; case Value.SHORT: buff.put((byte) type); buff.putShort(v.getShort()); break; case Value.INT: { int x = v.getInt(); if (x < 0) { buff.put((byte) INT_NEG); writeVarInt(buff, -x); } else if (x < 16) { buff.put((byte) (INT_0_15 + x)); } else { buff.put((byte) type); writeVarInt(buff, x); } break; } case Value.LONG: { long x = v.getLong(); if (x < 0) { buff.put((byte) LONG_NEG); writeVarLong(buff, -x); } else if (x < 8) { buff.put((byte) (LONG_0_7 + x)); } else { buff.put((byte) type); writeVarLong(buff, x); } break; } case Value.DECIMAL: { BigDecimal x = v.getBigDecimal(); if (BigDecimal.ZERO.equals(x)) { buff.put((byte) DECIMAL_0_1); } else if (BigDecimal.ONE.equals(x)) { buff.put((byte) (DECIMAL_0_1 + 1)); } else { int scale = x.scale(); BigInteger b = x.unscaledValue(); int bits = b.bitLength(); if (bits <= 63) { if (scale == 0) { buff.put((byte) DECIMAL_SMALL_0); writeVarLong(buff, b.longValue()); } else { buff.put((byte) DECIMAL_SMALL); writeVarInt(buff, scale); writeVarLong(buff, b.longValue()); } } else { buff.put((byte) type); writeVarInt(buff, scale); byte[] bytes = b.toByteArray(); writeVarInt(buff, bytes.length); buff = DataUtils.ensureCapacity(buff, bytes.length); buff.put(bytes, 0, bytes.length); } } break; } case Value.TIME: if (SysProperties.STORE_LOCAL_TIME) { buff.put((byte) LOCAL_TIME); ValueTime t = (ValueTime) v; long nanos = t.getNanos(); long millis = nanos / 1000000; nanos -= millis * 1000000; writeVarLong(buff, millis); writeVarLong(buff, nanos); } else { buff.put((byte) type); writeVarLong(buff, DateTimeUtils.getTimeLocalWithoutDst(v.getTime())); } break; case Value.DATE: { if (SysProperties.STORE_LOCAL_TIME) { buff.put((byte) LOCAL_DATE); long x = ((ValueDate) v).getDateValue(); writeVarLong(buff, x); } else { buff.put((byte) type); long x = DateTimeUtils.getTimeLocalWithoutDst(v.getDate()); writeVarLong(buff, x / MILLIS_PER_MINUTE); } break; } case Value.TIMESTAMP: { if (SysProperties.STORE_LOCAL_TIME) { buff.put((byte) LOCAL_TIMESTAMP); ValueTimestamp ts = (ValueTimestamp) v; long dateValue = ts.getDateValue(); writeVarLong(buff, dateValue); long nanos = ts.getNanos(); long millis = nanos / 1000000; nanos -= millis * 1000000; writeVarLong(buff, millis); writeVarLong(buff, nanos); } else { Timestamp ts = v.getTimestamp(); buff.put((byte) type); writeVarLong(buff, DateTimeUtils.getTimeLocalWithoutDst(ts)); writeVarInt(buff, ts.getNanos()); } break; } case Value.JAVA_OBJECT: { buff.put((byte) type); byte[] b = v.getBytesNoCopy(); writeVarInt(buff, b.length); buff = DataUtils.ensureCapacity(buff, b.length); buff.put(b, 0, b.length); break; } case Value.BYTES: { byte[] b = v.getBytesNoCopy(); int len = b.length; if (len < 32) { buff.put((byte) (BYTES_0_31 + len)); buff.put(b, 0, b.length); } else { buff.put((byte) type); writeVarInt(buff, b.length); buff = DataUtils.ensureCapacity(buff, b.length); buff.put(b, 0, b.length); } break; } case Value.UUID: { buff.put((byte) type); ValueUuid uuid = (ValueUuid) v; buff.putLong(uuid.getHigh()); buff.putLong(uuid.getLow()); break; } case Value.STRING: { String s = v.getString(); int len = s.length(); if (len < 32) { buff.put((byte) (STRING_0_31 + len)); buff = writeStringWithoutLength(buff, s, len); } else { buff.put((byte) type); buff = writeString(buff, s); } break; } case Value.STRING_IGNORECASE: case Value.STRING_FIXED: buff.put((byte) type); buff = writeString(buff, v.getString()); break; case Value.DOUBLE: { double x = v.getDouble(); if (x == 1.0d) { buff.put((byte) (DOUBLE_0_1 + 1)); } else { long d = Double.doubleToLongBits(x); if (d == ValueDouble.ZERO_BITS) { buff.put((byte) DOUBLE_0_1); } else { buff.put((byte) type); writeVarLong(buff, Long.reverse(d)); } } break; } case Value.FLOAT: { float x = v.getFloat(); if (x == 1.0f) { buff.put((byte) (FLOAT_0_1 + 1)); } else { int f = Float.floatToIntBits(x); if (f == ValueFloat.ZERO_BITS) { buff.put((byte) FLOAT_0_1); } else { buff.put((byte) type); writeVarInt(buff, Integer.reverse(f)); } } break; } case Value.BLOB: case Value.CLOB: { buff.put((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(buff, t); writeVarInt(buff, lob.getTableId()); writeVarInt(buff, lob.getObjectId()); writeVarLong(buff, lob.getPrecision()); buff.put((byte) (lob.useCompression() ? 1 : 0)); if (t == -2) { buff = writeString(buff, lob.getFileName()); } } else { writeVarInt(buff, small.length); buff = DataUtils.ensureCapacity(buff, small.length); buff.put(small, 0, small.length); } } else { ValueLobDb lob = (ValueLobDb) v; byte[] small = lob.getSmall(); if (small == null) { writeVarInt(buff, -3); writeVarInt(buff, lob.getTableId()); writeVarLong(buff, lob.getLobId()); writeVarLong(buff, lob.getPrecision()); } else { writeVarInt(buff, small.length); buff = DataUtils.ensureCapacity(buff, small.length); buff.put(small, 0, small.length); } } break; } case Value.ARRAY: { buff.put((byte) type); Value[] list = ((ValueArray) v).getList(); writeVarInt(buff, list.length); for (Value x : list) { buff = DataUtils.ensureCapacity(buff, 0); buff = writeValue(buff, x); } break; } case Value.RESULT_SET: { buff.put((byte) type); try { ResultSet rs = ((ValueResultSet) v).getResultSet(); rs.beforeFirst(); ResultSetMetaData meta = rs.getMetaData(); int columnCount = meta.getColumnCount(); writeVarInt(buff, columnCount); for (int i = 0; i < columnCount; i++) { buff = DataUtils.ensureCapacity(buff, 0); buff = writeString(buff, meta.getColumnName(i + 1)); writeVarInt(buff, meta.getColumnType(i + 1)); writeVarInt(buff, meta.getPrecision(i + 1)); writeVarInt(buff, meta.getScale(i + 1)); } while (rs.next()) { buff.put((byte) 1); for (int i = 0; i < columnCount; i++) { int t = org.h2.value.DataType.convertSQLTypeToValueType(meta.getColumnType(i + 1)); Value val = org.h2.value.DataType.readValue(null, rs, i + 1, t); buff = writeValue(buff, val); } } buff.put((byte) 0); rs.beforeFirst(); } catch (SQLException e) { throw DbException.convert(e); } break; } default: DbException.throwInternalError("type=" + v.getType()); } if (SysProperties.CHECK2) { if (buff.position() - start != Data.getValueLen(v, handler)) { throw DbException.throwInternalError( "value size error: got " + (buff.position() - start) + " expected " + Data.getValueLen(v, handler)); } } return buff; }