Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix LOBs in data change delta tables #3378

Merged
merged 2 commits into from Jan 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ReferenceEquality: Comparison using reference equality instead of value equality (details)
(at-me in a reply with help or ignore)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sonatype-lift ignore

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've recorded this as ignored for this pull request. If you change your mind, just comment @sonatype-lift unignore.

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