Skip to content

Commit

Permalink
Merge pull request #3378 from katzyn/lob
Browse files Browse the repository at this point in the history
Fix LOBs in data change delta tables
  • Loading branch information
katzyn committed Jan 15, 2022
2 parents ccaadc0 + 1392152 commit c5f11a5
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 10 deletions.
4 changes: 4 additions & 0 deletions h2/src/docsrc/html/changelog.html
Expand Up @@ -21,6 +21,10 @@ <h1>Change Log</h1>

<h2>Next Version (unreleased)</h2>
<ul>
<li>Issue #3376: Data cannot be read after insert of clob data > MAX_LENGTH_INPLACE_LOB with data change delta table
</li>
<li>PR #3377: Add -webExternalNames setting and fix WebServer.getConnection()
</li>
<li>PR #3367: Use faster checks of dimension systems of geometries
</li>
<li>PR #3369: Added v2 changes in migration docs
Expand Down
4 changes: 4 additions & 0 deletions h2/src/main/org/h2/command/Parser.java
Expand Up @@ -1989,6 +1989,10 @@ private Table readDataChangeDeltaTable(String resultOptionName, int backupIndex)
throw getSyntaxError();
}
read(CLOSE_PAREN);
if (currentSelect != null) {
// Lobs aren't copied, so use it for more safety
currentSelect.setNeverLazy(true);
}
return new DataChangeDeltaTable(getSchemaWithDefault(), session, statement, resultOption);
}

Expand Down
18 changes: 15 additions & 3 deletions h2/src/main/org/h2/result/LocalResult.java
Expand Up @@ -62,6 +62,7 @@ public static LocalResult forTable(SessionLocal session, Table table) {
private int visibleColumnCount;
private int resultColumnCount;
private Expression[] expressions;
private boolean forDataChangeDeltaTable;
private long rowId, rowCount;
private ArrayList<Value[]> rows;
private SortOrder sort;
Expand Down Expand Up @@ -140,6 +141,13 @@ public void setMaxMemoryRows(int maxValue) {
this.maxMemoryRows = maxValue;
}

/**
* Sets value collection mode for data change delta tables.
*/
public void setForDataChangeDeltaTable() {
forDataChangeDeltaTable = true;
}

/**
* Create a shallow copy of the result set. The data and a temporary table
* (if there is any) is not copied.
Expand Down Expand Up @@ -343,10 +351,14 @@ private void cloneLobs(Value[] values) {
for (int i = 0; i < values.length; i++) {
Value v = values[i];
if (v instanceof ValueLob) {
ValueLob v2 = ((ValueLob) v).copyToResult();
if (v2 != v) {
if (forDataChangeDeltaTable) {
containsLobs = true;
values[i] = session.addTemporaryLob(v2);
} else {
ValueLob v2 = ((ValueLob) v).copyToResult();
if (v2 != v) {
containsLobs = true;
values[i] = session.addTemporaryLob(v2);
}
}
}
}
Expand Down
16 changes: 10 additions & 6 deletions h2/src/main/org/h2/server/web/WebThread.java
Expand Up @@ -184,21 +184,22 @@ private boolean process() throws IOException {
message += "Transfer-Encoding: chunked\r\n";
message += "\r\n";
trace(message);
output.write(message.getBytes());
output.write(message.getBytes(StandardCharsets.ISO_8859_1));
while (it.hasNext()) {
String s = it.next();
s = PageParser.parse(s, session.map);
bytes = s.getBytes(StandardCharsets.UTF_8);
if (bytes.length == 0) {
continue;
}
output.write(Integer.toHexString(bytes.length).getBytes());
output.write("\r\n".getBytes());
output.write(Integer.toHexString(bytes.length).getBytes(StandardCharsets.ISO_8859_1));
output.write(RN);
output.write(bytes);
output.write("\r\n".getBytes());
output.write(RN);
output.flush();
}
output.write("0\r\n\r\n".getBytes());
output.write('0');
output.write(RNRN);
output.flush();
return keepAlive;
}
Expand All @@ -217,7 +218,7 @@ private boolean process() throws IOException {
message += "Content-Length: " + bytes.length + "\r\n";
message += "\r\n";
trace(message);
output.write(message.getBytes());
output.write(message.getBytes(StandardCharsets.ISO_8859_1));
output.write(bytes);
output.flush();
return keepAlive;
Expand Down Expand Up @@ -252,6 +253,9 @@ private boolean checkHost(String host) throws IOException {
if (index >= 0) {
host = host.substring(0, index);
}
if (host.isEmpty()) {
return false;
}
if (host.equals(server.getHost()) || host.equals("localhost") || host.equals("127.0.0.1")) {
return true;
}
Expand Down
3 changes: 2 additions & 1 deletion h2/src/main/org/h2/store/fs/encrypt/FileEncrypt.java
Expand Up @@ -10,6 +10,7 @@
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import org.h2.security.AES;
import org.h2.security.SHA256;
Expand Down Expand Up @@ -37,7 +38,7 @@ public class FileEncrypt extends FileBaseDefault {
*/
static final int HEADER_LENGTH = BLOCK_SIZE;

private static final byte[] HEADER = "H2encrypt\n".getBytes();
private static final byte[] HEADER = "H2encrypt\n".getBytes(StandardCharsets.ISO_8859_1);
private static final int SALT_POS = HEADER.length;

/**
Expand Down
1 change: 1 addition & 0 deletions h2/src/main/org/h2/table/DataChangeDeltaTable.java
Expand Up @@ -116,6 +116,7 @@ public ResultInterface getResult(SessionLocal session) {
statement.prepare();
int columnCount = expressions.length;
LocalResult result = new LocalResult(session, expressions, columnCount, columnCount);
result.setForDataChangeDeltaTable();
statement.update(result, resultOption);
return result;
}
Expand Down
28 changes: 28 additions & 0 deletions h2/src/test/org/h2/test/scripts/other/data-change-delta-table.sql
Expand Up @@ -387,3 +387,31 @@ SELECT * FROM NEW TABLE (MERGE INTO TEST_VIEW TEST USING

DROP TABLE TEST CASCADE;
> ok

CREATE TABLE TEST(ID BIGINT, DATA CHARACTER LARGE OBJECT);
> ok

INSERT INTO TEST VALUES (1, REPEAT('A', 1000));
> update count: 1

SELECT ID FROM FINAL TABLE (INSERT INTO TEST VALUES (2, REPEAT('B', 1000)));
>> 2

SELECT ID, SUBSTRING(DATA FROM 1 FOR 2) FROM TEST;
> ID SUBSTRING(DATA FROM 1 FOR 2)
> -- ----------------------------
> 1 AA
> 2 BB
> rows: 2

@reconnect

SELECT ID, SUBSTRING(DATA FROM 1 FOR 2) FROM TEST;
> ID SUBSTRING(DATA FROM 1 FOR 2)
> -- ----------------------------
> 1 AA
> 2 BB
> rows: 2

DROP TABLE TEST;
> ok

0 comments on commit c5f11a5

Please sign in to comment.