提交 a88c87c7 authored 作者: Thomas Mueller's avatar Thomas Mueller

Changes in updatable result sets are now visible even when resetting the result set.

Key values can now be changed in updatable result sets.
上级 449dbd81
......@@ -63,10 +63,21 @@ import org.h2.value.ValueTime;
import org.h2.value.ValueTimestamp;
/**
* Represents a result set. Column names are case-insensitive, quotes are not
* supported. The first column has the column index 1. Result sets are updatable
* when the result only contains columns from one table, and if it contains all
* columns of a unique index (primary key or other) of this table.
* <p>
* Represents a result set.
* </p>
* <p>
* Column names are case-insensitive, quotes are not supported. The first column
* has the column index 1.
* </p>
* <p>
* Updatable result sets:
* Result sets are updatable when the result only contains columns from one
* table, and if it contains all columns of a unique index (primary key or
* other) of this table. Key columns may not contain NULL (because multiple rows
* with NULL could exist). In updatable result sets, own changes are visible,
* but not own inserts and deletes.
* </p>
*/
public class JdbcResultSet extends TraceObject implements ResultSet {
private final SessionInterface session;
......@@ -80,6 +91,7 @@ public class JdbcResultSet extends TraceObject implements ResultSet {
private Value[] insertRow;
private Value[] updateRow;
private HashMap columnNameMap;
private HashMap patchedRows;
JdbcResultSet(JdbcConnection conn, JdbcStatement stat, ResultInterface result, int id,
boolean closeStatement, boolean scrollable) {
......@@ -2821,8 +2833,15 @@ public class JdbcResultSet extends TraceObject implements ResultSet {
checkOnValidRow();
if (updateRow != null) {
UpdatableRow row = getUpdatableRow();
row.updateRow(result.currentRow(), updateRow);
row.refreshRow(result.currentRow());
Value[] current = result.currentRow();
row.updateRow(current, updateRow);
for (int i = 0; i < updateRow.length; i++) {
if (updateRow[i] == null) {
updateRow[i] = current[i];
}
}
Value[] patch = row.readRow(updateRow);
patchCurrentRow(patch);
updateRow = null;
}
} catch (Exception e) {
......@@ -2866,7 +2885,7 @@ public class JdbcResultSet extends TraceObject implements ResultSet {
throw Message.getSQLException(ErrorCode.NO_DATA_AVAILABLE);
}
checkOnValidRow();
getUpdatableRow().refreshRow(result.currentRow());
patchCurrentRow(getUpdatableRow().readRow(result.currentRow()));
updateRow = null;
} catch (Exception e) {
throw logAndConvert(e);
......@@ -2983,7 +3002,15 @@ public class JdbcResultSet extends TraceObject implements ResultSet {
private Value get(int columnIndex) throws SQLException {
checkColumnIndex(columnIndex);
checkOnValidRow();
Value[] list = result.currentRow();
Value[] list;
if (patchedRows == null) {
list = result.currentRow();
} else {
list = (Value[]) patchedRows.get(ObjectUtils.getInteger(result.getRowId()));
if (list == null) {
list = result.currentRow();
}
}
Value value = list[columnIndex - 1];
wasNull = value == ValueNull.INSTANCE;
return value;
......@@ -3474,5 +3501,25 @@ public class JdbcResultSet extends TraceObject implements ResultSet {
public String toString() {
return getTraceObjectName() + ": " + result;
}
private void patchCurrentRow(Value[] row) throws SQLException {
boolean changed = false;
Value[] current = result.currentRow();
for (int i = 0; i < row.length; i++) {
if (!row[i].compareEqual(current[i])) {
changed = true;
break;
}
}
if (patchedRows == null) {
patchedRows = new HashMap();
}
Integer rowId = ObjectUtils.getInteger(result.getRowId());
if (!changed) {
patchedRows.remove(rowId);
} else {
patchedRows.put(rowId, row);
}
}
}
......@@ -156,18 +156,6 @@ public class UpdatableRow {
// return rs.getInt(1) == 0;
// }
/**
* Re-reads a row from the database and updates the values in the array.
*
* @param row the values
*/
public void refreshRow(Value[] row) throws SQLException {
Value[] newRow = readRow(row);
for (int i = 0; i < columnCount; i++) {
row[i] = newRow[i];
}
}
private void appendTableName(StringBuffer buff) {
if (schemaName != null && schemaName.length() > 0) {
buff.append(StringUtils.quoteIdentifier(schemaName));
......@@ -176,7 +164,13 @@ public class UpdatableRow {
buff.append(StringUtils.quoteIdentifier(tableName));
}
private Value[] readRow(Value[] row) throws SQLException {
/**
* Re-reads a row from the database and updates the values in the array.
*
* @param row the values that contain the key
* @return the row
*/
public Value[] readRow(Value[] row) throws SQLException {
StringBuffer buff = new StringBuffer();
buff.append("SELECT ");
appendColumnList(buff, false);
......
......@@ -30,6 +30,31 @@ public class TestUpdatableResultSet extends TestBase {
testScroll();
testUpdateDeleteInsert();
testUpdateDataType();
testUpdateResetRead();
}
private void testUpdateResetRead() throws Exception {
deleteDb("updatableResultSet");
Connection conn = getConnection("updatableResultSet");
Statement stat = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
stat.execute("CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR(255))");
stat.execute("INSERT INTO TEST VALUES(1, 'Hello')");
stat.execute("INSERT INTO TEST VALUES(2, 'World')");
ResultSet rs = stat.executeQuery("SELECT * FROM TEST ORDER BY ID");
rs.next();
rs.updateInt(1, 10);
rs.updateRow();
rs.next();
rs.updateString(2, "Welt");
rs.updateRow();
rs.beforeFirst();
rs.next();
assertEquals(10, rs.getInt(1));
assertEquals("Hello", rs.getString(2));
rs.next();
assertEquals(2, rs.getInt(1));
assertEquals("Welt", rs.getString(2));
conn.close();
}
private void testScroll() throws Exception {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论