提交 44af5ac8 authored 作者: Noel Grandin's avatar Noel Grandin

ValueLob is only constructed from PageStore

and even then, only in specific situations, so simplify accordingly
上级 6c182e4c
...@@ -621,7 +621,6 @@ public class Data { ...@@ -621,7 +621,6 @@ public class Data {
writeByte((byte) type); writeByte((byte) type);
if (v instanceof ValueLob) { if (v instanceof ValueLob) {
ValueLob lob = (ValueLob) v; ValueLob lob = (ValueLob) v;
lob.convertToFileIfRequired(handler);
byte[] small = lob.getSmall(); byte[] small = lob.getSmall();
if (small == null) { if (small == null) {
int t = -1; int t = -1;
...@@ -1069,7 +1068,6 @@ public class Data { ...@@ -1069,7 +1068,6 @@ public class Data {
int len = 1; int len = 1;
if (v instanceof ValueLob) { if (v instanceof ValueLob) {
ValueLob lob = (ValueLob) v; ValueLob lob = (ValueLob) v;
lob.convertToFileIfRequired(handler);
byte[] small = lob.getSmall(); byte[] small = lob.getSmall();
if (small == null) { if (small == null) {
int t = -1; int t = -1;
......
...@@ -6,15 +6,12 @@ ...@@ -6,15 +6,12 @@
package org.h2.value; package org.h2.value;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.Reader; import java.io.Reader;
import java.nio.charset.StandardCharsets;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.SQLException; import java.sql.SQLException;
import org.h2.engine.Constants; import org.h2.engine.Constants;
import org.h2.engine.Mode; import org.h2.engine.Mode;
import org.h2.engine.SysProperties; import org.h2.engine.SysProperties;
...@@ -22,7 +19,6 @@ import org.h2.message.DbException; ...@@ -22,7 +19,6 @@ import org.h2.message.DbException;
import org.h2.store.DataHandler; import org.h2.store.DataHandler;
import org.h2.store.FileStore; import org.h2.store.FileStore;
import org.h2.store.FileStoreInputStream; import org.h2.store.FileStoreInputStream;
import org.h2.store.FileStoreOutputStream;
import org.h2.store.RangeInputStream; import org.h2.store.RangeInputStream;
import org.h2.store.RangeReader; import org.h2.store.RangeReader;
import org.h2.store.fs.FileUtils; import org.h2.store.fs.FileUtils;
...@@ -113,15 +109,14 @@ public class ValueLob extends Value { ...@@ -113,15 +109,14 @@ public class ValueLob extends Value {
* either Value.BLOB or Value.CLOB * either Value.BLOB or Value.CLOB
*/ */
private final int valueType; private final int valueType;
private long precision; private final long precision;
private DataHandler handler; private final DataHandler handler;
private int tableId; private int tableId;
private int objectId; private final int objectId;
private String fileName; private String fileName;
private boolean linked; private boolean linked;
private byte[] small;
private int hash; private int hash;
private boolean compressed; private final boolean compressed;
private FileStore tempFile; private FileStore tempFile;
private ValueLob(int type, DataHandler handler, String fileName, private ValueLob(int type, DataHandler handler, String fileName,
...@@ -137,37 +132,6 @@ public class ValueLob extends Value { ...@@ -137,37 +132,6 @@ public class ValueLob extends Value {
this.compressed = compressed; this.compressed = compressed;
} }
private ValueLob(int type, byte[] small) {
this.valueType = type;
this.small = small;
if (small != null) {
if (type == Value.BLOB) {
this.precision = small.length;
} else {
this.precision = getString().length();
}
}
}
private static ValueLob copy(ValueLob lob) {
ValueLob copy = new ValueLob(lob.valueType, lob.handler, lob.fileName,
lob.tableId, lob.objectId, lob.linked, lob.precision, lob.compressed);
copy.small = lob.small;
copy.hash = lob.hash;
return copy;
}
/**
* Create a small lob using the given byte array.
*
* @param type the type (Value.BLOB or CLOB)
* @param small the byte array
* @return the lob value
*/
private static ValueLob createSmallLob(int type, byte[] small) {
return new ValueLob(type, small);
}
private static String getFileName(DataHandler handler, int tableId, private static String getFileName(DataHandler handler, int tableId,
int objectId) { int objectId) {
if (SysProperties.CHECK && tableId == 0 && objectId == 0) { if (SysProperties.CHECK && tableId == 0 && objectId == 0) {
...@@ -215,92 +179,6 @@ public class ValueLob extends Value { ...@@ -215,92 +179,6 @@ public class ValueLob extends Value {
false/* linked */, precision, compression); false/* linked */, precision, compression);
} }
/**
* Create a 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
*/
private static ValueLob createClob(Reader in, long length,
DataHandler handler) {
try {
if (handler == null) {
String s = IOUtils.readStringAndClose(in, (int) length);
return createSmallLob(Value.CLOB, s.getBytes(StandardCharsets.UTF_8));
}
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(in, -1);
buff = data.toCharArray();
len = buff.length;
} else {
buff = new char[len];
len = IOUtils.readFully(in, buff, len);
}
if (len <= handler.getMaxLengthInplaceLob()) {
byte[] small = new String(buff, 0, len).getBytes(StandardCharsets.UTF_8);
return ValueLob.createSmallLob(Value.CLOB, small);
}
ValueLob lob = new ValueLob(Value.CLOB, null);
lob.createFromReader(buff, len, in, remaining, handler);
return lob;
} catch (IOException e) {
throw DbException.convertIOException(e, null);
}
}
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
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;
}
private void createFromReader(char[] buff, int len, Reader in,
long remaining, DataHandler h) throws IOException {
try (FileStoreOutputStream out = initLarge(h)) {
boolean compress = h.getLobCompressionAlgorithm(Value.CLOB) != null;
while (true) {
precision += len;
byte[] b = new String(buff, 0, len).getBytes(StandardCharsets.UTF_8);
out.write(b, 0, b.length);
remaining -= len;
if (remaining <= 0) {
break;
}
len = getBufferSize(h, compress, remaining);
len = IOUtils.readFully(in, buff, len);
if (len == 0) {
break;
}
}
}
}
private static String getFileNamePrefix(String path, int objectId) { private static String getFileNamePrefix(String path, int objectId) {
String name; String name;
int f = objectId % SysProperties.LOB_FILES_PER_DIRECTORY; int f = objectId % SysProperties.LOB_FILES_PER_DIRECTORY;
...@@ -409,91 +287,6 @@ public class ValueLob extends Value { ...@@ -409,91 +287,6 @@ public class ValueLob extends Value {
return list; return list;
} }
/**
* Create a 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
*/
private static ValueLob createBlob(InputStream in, long length,
DataHandler handler) {
try {
if (handler == null) {
byte[] data = IOUtils.readBytesAndClose(in, (int) length);
return createSmallLob(Value.BLOB, data);
}
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 = Utils.newBytes(len);
len = IOUtils.readFully(in, buff, len);
}
if (len <= handler.getMaxLengthInplaceLob()) {
byte[] small = Utils.copyBytes(buff, len);
return ValueLob.createSmallLob(Value.BLOB, small);
}
ValueLob lob = new ValueLob(Value.BLOB, null);
lob.createFromStream(buff, len, in, remaining, handler);
return lob;
} catch (IOException e) {
throw DbException.convertIOException(e, null);
}
}
private FileStoreOutputStream initLarge(DataHandler h) {
this.handler = h;
this.tableId = 0;
this.linked = false;
this.precision = 0;
this.small = null;
this.hash = 0;
String compressionAlgorithm = h.getLobCompressionAlgorithm(valueType);
this.compressed = compressionAlgorithm != null;
synchronized (h) {
String path = h.getDatabasePath();
if ((path != null) && (path.length() == 0)) {
path = new File(Utils.getProperty("java.io.tmpdir", "."),
SysProperties.PREFIX_TEMP_FILE).getAbsolutePath();
}
objectId = getNewObjectId(h);
fileName = getFileNamePrefix(path, objectId) + Constants.SUFFIX_TEMP_FILE;
tempFile = h.openFile(fileName, "rw", false);
tempFile.autoDelete();
}
return new FileStoreOutputStream(tempFile, h,
compressionAlgorithm);
}
private void createFromStream(byte[] buff, int len, InputStream in,
long remaining, DataHandler h) throws IOException {
try (FileStoreOutputStream out = initLarge(h)) {
boolean compress = h.getLobCompressionAlgorithm(Value.BLOB) != null;
while (true) {
precision += len;
out.write(buff, 0, len);
remaining -= len;
if (remaining <= 0) {
break;
}
len = getBufferSize(h, compress, remaining);
len = IOUtils.readFully(in, buff, len);
if (len <= 0) {
break;
}
}
}
}
/** /**
* Convert a lob to another data type. The data is fully read in memory * Convert a lob to another data type. The data is fully read in memory
* except when converting to BLOB or CLOB. * except when converting to BLOB or CLOB.
...@@ -513,9 +306,9 @@ public class ValueLob extends Value { ...@@ -513,9 +306,9 @@ public class ValueLob extends Value {
if (t == valueType) { if (t == valueType) {
return this; return this;
} else if (t == Value.CLOB) { } else if (t == Value.CLOB) {
return ValueLob.createClob(getReader(), -1, handler); return ValueLobDb.createTempClob(getReader(), -1, handler);
} else if (t == Value.BLOB) { } else if (t == Value.BLOB) {
return ValueLob.createBlob(getInputStream(), -1, handler); return ValueLobDb.createTempBlob(getInputStream(), -1, handler);
} }
return super.convertTo(t, precision, mode, column, null); return super.convertTo(t, precision, mode, column, null);
} }
...@@ -552,8 +345,9 @@ public class ValueLob extends Value { ...@@ -552,8 +345,9 @@ public class ValueLob extends Value {
return this; return this;
} }
if (linked) { if (linked) {
ValueLob copy = ValueLob.copy(this); ValueLob copy = new ValueLob(this.valueType, this.handler, this.fileName,
copy.objectId = getNewObjectId(h); this.tableId, getNewObjectId(h), this.linked, this.precision, this.compressed);
copy.hash = this.hash;
copy.tableId = tabId; copy.tableId = tabId;
String live = getFileName(h, copy.tableId, copy.objectId); String live = getFileName(h, copy.tableId, copy.objectId);
copyFileTo(h, fileName, live); copyFileTo(h, fileName, live);
...@@ -610,17 +404,9 @@ public class ValueLob extends Value { ...@@ -610,17 +404,9 @@ public class ValueLob extends Value {
Integer.MAX_VALUE : (int) precision; Integer.MAX_VALUE : (int) precision;
try { try {
if (valueType == Value.CLOB) { if (valueType == Value.CLOB) {
if (small != null) {
return new String(small, StandardCharsets.UTF_8);
}
return IOUtils.readStringAndClose(getReader(), len); return IOUtils.readStringAndClose(getReader(), len);
} }
byte[] buff; byte[] buff = IOUtils.readBytesAndClose(getInputStream(), len);
if (small != null) {
buff = small;
} else {
buff = IOUtils.readBytesAndClose(getInputStream(), len);
}
return StringUtils.convertBytesToHex(buff); return StringUtils.convertBytesToHex(buff);
} catch (IOException e) { } catch (IOException e) {
throw DbException.convertIOException(e, fileName); throw DbException.convertIOException(e, fileName);
...@@ -643,9 +429,6 @@ public class ValueLob extends Value { ...@@ -643,9 +429,6 @@ public class ValueLob extends Value {
// convert hex to string // convert hex to string
return super.getBytesNoCopy(); return super.getBytesNoCopy();
} }
if (small != null) {
return small;
}
try { try {
return IOUtils.readBytesAndClose( return IOUtils.readBytesAndClose(
getInputStream(), Integer.MAX_VALUE); getInputStream(), Integer.MAX_VALUE);
...@@ -700,9 +483,6 @@ public class ValueLob extends Value { ...@@ -700,9 +483,6 @@ public class ValueLob extends Value {
@Override @Override
public InputStream getInputStream() { public InputStream getInputStream() {
if (fileName == null) {
return new ByteArrayInputStream(small);
}
FileStore store = handler.openFile(fileName, "r", true); FileStore store = handler.openFile(fileName, "r", true);
boolean alwaysClose = SysProperties.lobCloseBetweenReads; boolean alwaysClose = SysProperties.lobCloseBetweenReads;
return new BufferedInputStream( return new BufferedInputStream(
...@@ -751,9 +531,6 @@ public class ValueLob extends Value { ...@@ -751,9 +531,6 @@ public class ValueLob extends Value {
@Override @Override
public String getTraceSQL() { public String getTraceSQL() {
if (small != null && getPrecision() <= SysProperties.MAX_TRACE_DATA_LENGTH) {
return getSQL();
}
StringBuilder buff = new StringBuilder(); StringBuilder buff = new StringBuilder();
if (valueType == Value.CLOB) { if (valueType == Value.CLOB) {
buff.append("SPACE(").append(getPrecision()); buff.append("SPACE(").append(getPrecision());
...@@ -771,7 +548,7 @@ public class ValueLob extends Value { ...@@ -771,7 +548,7 @@ public class ValueLob extends Value {
*/ */
@Override @Override
public byte[] getSmall() { public byte[] getSmall() {
return small; return null;
} }
@Override @Override
...@@ -784,35 +561,6 @@ public class ValueLob extends Value { ...@@ -784,35 +561,6 @@ public class ValueLob extends Value {
return other instanceof ValueLob && compareSecure((Value) other, null) == 0; return other instanceof ValueLob && compareSecure((Value) other, null) == 0;
} }
/**
* Store the lob data to a file if the size of the buffer is larger than the
* maximum size for an in-place lob.
*
* @param h the data handler
*/
public void convertToFileIfRequired(DataHandler h) {
try {
if (small != null && small.length > h.getMaxLengthInplaceLob()) {
boolean compress = h.getLobCompressionAlgorithm(valueType) != null;
int len = getBufferSize(h, compress, Long.MAX_VALUE);
int tabId = tableId;
if (valueType == Value.BLOB) {
createFromStream(
Utils.newBytes(len), 0, getInputStream(), Long.MAX_VALUE, h);
} else {
createFromReader(
new char[len], 0, getReader(), Long.MAX_VALUE, h);
}
Value v2 = copy(h, tabId);
if (SysProperties.CHECK && v2 != this) {
DbException.throwInternalError(v2.toString());
}
}
} catch (IOException e) {
throw DbException.convertIOException(e, null);
}
}
/** /**
* Check if this lob value is compressed. * Check if this lob value is compressed.
* *
...@@ -851,9 +599,6 @@ public class ValueLob extends Value { ...@@ -851,9 +599,6 @@ public class ValueLob extends Value {
@Override @Override
public int getMemory() { public int getMemory() {
if (small != null) {
return small.length + 104;
}
return 140; return 140;
} }
...@@ -864,12 +609,12 @@ public class ValueLob extends Value { ...@@ -864,12 +609,12 @@ public class ValueLob extends Value {
* @return the value * @return the value
*/ */
@Override @Override
public ValueLob copyToTemp() { public ValueLobDb copyToTemp() {
ValueLob lob; ValueLobDb lob;
if (valueType == CLOB) { if (valueType == CLOB) {
lob = ValueLob.createClob(getReader(), precision, handler); lob = ValueLobDb.createTempClob(getReader(), precision, handler);
} else { } else {
lob = ValueLob.createBlob(getInputStream(), precision, handler); lob = ValueLobDb.createTempBlob(getInputStream(), precision, handler);
} }
return lob; return lob;
} }
...@@ -879,11 +624,11 @@ public class ValueLob extends Value { ...@@ -879,11 +624,11 @@ public class ValueLob extends Value {
if (this.precision <= precision) { if (this.precision <= precision) {
return this; return this;
} }
ValueLob lob; ValueLobDb lob;
if (valueType == CLOB) { if (valueType == CLOB) {
lob = ValueLob.createClob(getReader(), precision, handler); lob = ValueLobDb.createTempClob(getReader(), precision, handler);
} else { } else {
lob = ValueLob.createBlob(getInputStream(), precision, handler); lob = ValueLobDb.createTempBlob(getInputStream(), precision, handler);
} }
return lob; return lob;
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论