提交 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
......@@ -1793,7 +1793,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
* Returns whether the catalog name in CREATE TABLE is supported.
*
* @return true
*/
*/
public boolean supportsCatalogsInTableDefinitions() {
debugCodeCall("supportsCatalogsInTableDefinitions");
return true;
......@@ -2076,6 +2076,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Returns whether own inserts are visible.
*
* @return false
*/
public boolean ownInsertsAreVisible(int type) {
......@@ -2085,6 +2086,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Returns whether other updates are visible.
*
* @return false
*/
public boolean othersUpdatesAreVisible(int type) {
......@@ -2094,6 +2096,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Returns whether other deletes are visible.
*
* @return false
*/
public boolean othersDeletesAreVisible(int type) {
......@@ -2103,6 +2106,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Returns whether other inserts are visible.
*
* @return false
*/
public boolean othersInsertsAreVisible(int type) {
......@@ -2112,6 +2116,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Returns whether updates are detected.
*
* @return false
*/
public boolean updatesAreDetected(int type) {
......@@ -2121,6 +2126,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Returns whether deletes are detected.
*
* @return false
*/
public boolean deletesAreDetected(int type) {
......@@ -2130,6 +2136,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Returns whether inserts are detected.
*
* @return false
*/
public boolean insertsAreDetected(int type) {
......@@ -2139,6 +2146,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Returns whether batch updates are supported.
*
* @return true
*/
public boolean supportsBatchUpdates() {
......@@ -2148,6 +2156,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Returns whether the maximum row size includes blobs.
*
* @return false
*/
public boolean doesMaxRowSizeIncludeBlobs() {
......@@ -2157,6 +2166,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Returns the default transaction isolation level.
*
* @return Connection.TRANSACTION_READ_COMMITTED
*/
public int getDefaultTransactionIsolation() {
......@@ -2167,6 +2177,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Checks if for CREATE TABLE Test(ID INT), getTables returns Test as the
* table name.
*
* @return false
*/
public boolean supportsMixedCaseIdentifiers() {
......@@ -2177,6 +2188,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Checks if a table created with CREATE TABLE "Test"(ID INT) is a different
* table than a table created with CREATE TABLE TEST(ID INT).
*
* @return true
*/
public boolean supportsMixedCaseQuotedIdentifiers() {
......@@ -2187,6 +2199,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Checks if for CREATE TABLE Test(ID INT), getTables returns TEST as the
* table name.
*
* @return true
*/
public boolean storesUpperCaseIdentifiers() {
......@@ -2197,6 +2210,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Checks if for CREATE TABLE Test(ID INT), getTables returns test as the
* table name.
*
* @return false
*/
public boolean storesLowerCaseIdentifiers() {
......@@ -2207,6 +2221,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Checks if for CREATE TABLE Test(ID INT), getTables returns Test as the
* table name.
*
* @return false
*/
public boolean storesMixedCaseIdentifiers() {
......@@ -2217,6 +2232,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Checks if for CREATE TABLE "Test"(ID INT), getTables returns TEST as the
* table name.
*
* @return false
*/
public boolean storesUpperCaseQuotedIdentifiers() {
......@@ -2227,6 +2243,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Checks if for CREATE TABLE "Test"(ID INT), getTables returns test as the
* table name.
*
* @return false
*/
public boolean storesLowerCaseQuotedIdentifiers() {
......@@ -2237,6 +2254,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Checks if for CREATE TABLE "Test"(ID INT), getTables returns Test as the
* table name.
*
* @return true
*/
public boolean storesMixedCaseQuotedIdentifiers() {
......@@ -2246,6 +2264,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Returns the maximum length for hex values (characters).
*
* @return 0 for limit is unknown
*/
public int getMaxBinaryLiteralLength() {
......@@ -2255,6 +2274,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Returns the maximum length for literals.
*
* @return 0 for limit is unknown
*/
public int getMaxCharLiteralLength() {
......@@ -2264,6 +2284,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Returns the maximum length for column names.
*
* @return 0 for limit is unknown
*/
public int getMaxColumnNameLength() {
......@@ -2273,6 +2294,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Returns the maximum number of columns in GROUP BY.
*
* @return 0 for limit is unknown
*/
public int getMaxColumnsInGroupBy() {
......@@ -2282,6 +2304,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Returns the maximum number of columns in CREATE INDEX.
*
* @return 0 for limit is unknown
*/
public int getMaxColumnsInIndex() {
......@@ -2291,6 +2314,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Returns the maximum number of columns in ORDER BY.
*
* @return 0 for limit is unknown
*/
public int getMaxColumnsInOrderBy() {
......@@ -2300,6 +2324,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Returns the maximum number of columns in SELECT.
*
* @return 0 for limit is unknown
*/
public int getMaxColumnsInSelect() {
......@@ -2309,6 +2334,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Returns the maximum number of columns in CREATE TABLE.
*
* @return 0 for limit is unknown
*/
public int getMaxColumnsInTable() {
......@@ -2318,6 +2344,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Returns the maximum number of open connection.
*
* @return 0 for limit is unknown
*/
public int getMaxConnections() {
......@@ -2327,6 +2354,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Returns the maximum length for a cursor name.
*
* @return 0 for limit is unknown
*/
public int getMaxCursorNameLength() {
......@@ -2336,6 +2364,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Returns the maximum length for an index (in bytes).
*
* @return 0 for limit is unknown
*/
public int getMaxIndexLength() {
......@@ -2345,6 +2374,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Returns the maximum length for a schema name.
*
* @return 0 for limit is unknown
*/
public int getMaxSchemaNameLength() {
......@@ -2354,6 +2384,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Returns the maximum length for a procedure name.
*
* @return 0 for limit is unknown
*/
public int getMaxProcedureNameLength() {
......@@ -2363,6 +2394,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Returns the maximum length for a catalog name.
*
* @return 0 for limit is unknown
*/
public int getMaxCatalogNameLength() {
......@@ -2372,6 +2404,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Returns the maximum size of a row (in bytes).
*
* @return 0 for limit is unknown
*/
public int getMaxRowSize() {
......@@ -2381,6 +2414,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Returns the maximum length of a statement.
*
* @return 0 for limit is unknown
*/
public int getMaxStatementLength() {
......@@ -2390,6 +2424,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Returns the maximum number of open statements.
*
* @return 0 for limit is unknown
*/
public int getMaxStatements() {
......@@ -2399,6 +2434,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Returns the maximum length for a table name.
*
* @return 0 for limit is unknown
*/
public int getMaxTableNameLength() {
......@@ -2408,6 +2444,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Returns the maximum number of tables in a SELECT.
*
* @return 0 for limit is unknown
*/
public int getMaxTablesInSelect() {
......@@ -2417,6 +2454,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Returns the maximum length for a user name.
*
* @return 0 for limit is unknown
*/
public int getMaxUserNameLength() {
......@@ -2426,6 +2464,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Does the database support savepoints.
*
* @return true
*/
public boolean supportsSavepoints() {
......@@ -2435,6 +2474,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Does the database support named parameters.
*
* @return false
*/
public boolean supportsNamedParameters() {
......@@ -2444,6 +2484,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Does the database support multiple open result sets.
*
* @return true
*/
public boolean supportsMultipleOpenResults() {
......@@ -2453,6 +2494,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Does the database support getGeneratedKeys.
*
* @return true
*/
public boolean supportsGetGeneratedKeys() {
......@@ -2550,6 +2592,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Gets the result set holdability.
*
* @return ResultSet.CLOSE_CURSORS_AT_COMMIT
*/
//## Java 1.4 begin ##
......@@ -2561,6 +2604,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Gets the major version of the database.
*
* @return the major version
*/
public int getDatabaseMajorVersion() {
......@@ -2570,6 +2614,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Gets the minor version of the database.
*
* @return the minor version
*/
public int getDatabaseMinorVersion() {
......@@ -2579,6 +2624,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Gets the major version of the supported JDBC API.
*
* @return the major version
*/
public int getJDBCMajorVersion() {
......@@ -2588,6 +2634,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Gets the minor version of the supported JDBC API.
*
* @return the minor version
*/
public int getJDBCMinorVersion() {
......@@ -2597,6 +2644,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Gets the SQL State type.
*
* @return DatabaseMetaData.sqlStateSQL99
*/
//## Java 1.4 begin ##
......@@ -2608,6 +2656,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Does the database make a copy before updating.
*
* @return false
*/
public boolean locatorsUpdateCopy() {
......@@ -2617,6 +2666,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Does the database support statement pooling.
*
* @return false
*/
public boolean supportsStatementPooling() {
......@@ -2645,6 +2695,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Get the lifetime of a rowid.
*
* @return ROWID_UNSUPPORTED
*/
//## Java 1.6 begin ##
......@@ -2667,6 +2718,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Returns whether the database supports calling functions using the call syntax.
*
* @return true
*/
public boolean supportsStoredFunctionsUsingCallSyntax() {
......@@ -2676,6 +2728,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Returns whether an exception while auto commit is on closes all result sets.
*
* @return false
*/
public boolean autoCommitFailureClosesAllResultSets() {
......
......@@ -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 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论