From b0ecfc24b7c5963441fbb30dd5ff3e30cb3caf06 Mon Sep 17 00:00:00 2001 From: rusher Date: Sun, 23 Jul 2017 13:28:20 +0200 Subject: [PATCH] [CONJ-322] ResultSet.update* implementation - using virtual insert row in respect of java API philosophy --- .../mariadb/jdbc/MariaDbDatabaseMetaData.java | 31 ++++ .../com/read/resultset/SelectResultSet.java | 1 + .../read/resultset/UpdatableResultSet.java | 132 +++++++++++++----- .../jdbc/ServerPrepareStatementTest.java | 6 +- 4 files changed, 133 insertions(+), 37 deletions(-) diff --git a/src/main/java/org/mariadb/jdbc/MariaDbDatabaseMetaData.java b/src/main/java/org/mariadb/jdbc/MariaDbDatabaseMetaData.java index b5b398afe..1e6767d1f 100644 --- a/src/main/java/org/mariadb/jdbc/MariaDbDatabaseMetaData.java +++ b/src/main/java/org/mariadb/jdbc/MariaDbDatabaseMetaData.java @@ -2274,10 +2274,41 @@ public ResultSet getIndexInfo(String catalog, String schema, String table, return executeQuery(sql); } + /** + * Retrieves whether this database supports the given result set type. + * ResultSet.TYPE_FORWARD_ONLY and ResultSet.TYPE_SCROLL_INSENSITIVE are supported. + * + * @param type one of the following ResultSet constants: + * + * @return true if supported + * @throws SQLException cannot occur here + */ public boolean supportsResultSetType(int type) throws SQLException { return (type == ResultSet.TYPE_SCROLL_INSENSITIVE || type == ResultSet.TYPE_FORWARD_ONLY); } + /** + * Retrieves whether this database supports the given concurrency type in combination with the given result set type. + * All are supported, but combination that use ResultSet.TYPE_SCROLL_INSENSITIVE. + * + * @param type one of the following ResultSet constants: + * + * @param concurrency one of the following ResultSet constants: + * + * @return true if supported + * @throws SQLException cannot occur here + */ public boolean supportsResultSetConcurrency(int type, int concurrency) throws SQLException { //Support all concurrency (ResultSet.CONCUR_READ_ONLY and ResultSet.CONCUR_UPDATABLE) //so just return scroll type diff --git a/src/main/java/org/mariadb/jdbc/internal/com/read/resultset/SelectResultSet.java b/src/main/java/org/mariadb/jdbc/internal/com/read/resultset/SelectResultSet.java index 544e170c1..f603230a0 100644 --- a/src/main/java/org/mariadb/jdbc/internal/com/read/resultset/SelectResultSet.java +++ b/src/main/java/org/mariadb/jdbc/internal/com/read/resultset/SelectResultSet.java @@ -549,6 +549,7 @@ protected void updateRowData(byte[] rawData) { /** * Delete current data. * Position cursor to the previous row. + * @throws SQLException if previous() fail. */ protected void deleteCurrentRowData() throws SQLException { //move data diff --git a/src/main/java/org/mariadb/jdbc/internal/com/read/resultset/UpdatableResultSet.java b/src/main/java/org/mariadb/jdbc/internal/com/read/resultset/UpdatableResultSet.java index 930ecda71..1355c2c8f 100644 --- a/src/main/java/org/mariadb/jdbc/internal/com/read/resultset/UpdatableResultSet.java +++ b/src/main/java/org/mariadb/jdbc/internal/com/read/resultset/UpdatableResultSet.java @@ -79,15 +79,13 @@ public class UpdatableResultSet extends SelectResultSet { private static final int STATE_UPDATE = 1; private static final int STATE_UPDATED = 2; private static final int STATE_INSERT = 3; - public boolean rowUpdated = false; - public boolean rowInserted = false; - public boolean rowDeleted = false; private String database; private String table; private boolean canBeUpdate; private boolean canBeInserted; private boolean canBeRefresh; + private int notInsertRowPointer; private String exceptionUpdateMsg; private String exceptionInsertMsg; @@ -117,6 +115,12 @@ public UpdatableResultSet(ColumnInformation[] columnsInformation, Results result parameterHolders = new ParameterHolder[columnInformationLength]; } + + @Override + public int getConcurrency() throws SQLException { + return CONCUR_UPDATABLE; + } + private void checkIfUpdatable(Results results) throws IOException, SQLException { database = null; @@ -1199,7 +1203,6 @@ public void insertRow() throws SQLException { } insertPreparedStatement.execute(); - rowInserted = true; if (hasGeneratedPrimaryFields) { //primary is auto_increment (only one field) @@ -1219,7 +1222,6 @@ public void insertRow() throws SQLException { } Arrays.fill(parameterHolders, null); - state = STATE_STANDARD; } } @@ -1229,7 +1231,7 @@ public void insertRow() throws SQLException { public void updateRow() throws SQLException { if (state == STATE_INSERT) { - throw new SQLException("Cannot call updateRow() when inserting a new row", "24000"); + throw new SQLException("Cannot call updateRow() when inserting a new row"); } if (state == STATE_UPDATE) { @@ -1288,7 +1290,6 @@ public void updateRow() throws SQLException { refreshRow(); - rowUpdated = true; Arrays.fill(parameterHolders, null); state = STATE_STANDARD; } @@ -1301,11 +1302,11 @@ public void updateRow() throws SQLException { public void deleteRow() throws SQLException { if (state == STATE_INSERT) { - throw new SQLException("Cannot call deleteRow() when inserting a new row", "24000"); + throw new SQLException("Cannot call deleteRow() when inserting a new row"); } if (!canBeUpdate) { - throw new SQLDataException(exceptionUpdateMsg, "24000"); + throw new SQLDataException(exceptionUpdateMsg); } if (getRowPointer() < 0) { @@ -1346,7 +1347,6 @@ public void deleteRow() throws SQLException { deletePreparedStatement.executeUpdate(); deleteCurrentRowData(); - rowDeleted = true; } @@ -1418,39 +1418,27 @@ private byte[] refreshRawData() throws SQLException { * {inheritDoc}. */ public void refreshRow() throws SQLException { - if (canBeRefresh) { - updateRowData(refreshRawData()); + if (state == STATE_INSERT) { + throw new SQLException("Cannot call deleteRow() when inserting a new row"); } - } - /** - * {inheritDoc}. - */ - public boolean rowUpdated() throws SQLException { - return rowUpdated; - } + if (getRowPointer() < 0) { + throw new SQLDataException("Current position is before the first row", "22023"); + } - /** - * {inheritDoc}. - */ - public boolean rowInserted() throws SQLException { - return rowInserted; - } + if (getRowPointer() >= getDataSize()) { + throw new SQLDataException("Current position is after the last row", "22023"); + } - /** - * {inheritDoc}. - */ - public boolean rowDeleted() throws SQLException { - return rowDeleted; + if (canBeRefresh) { + updateRowData(refreshRawData()); + } } /** * {inheritDoc}. */ public void cancelRowUpdates() throws SQLException { - if (state == STATE_INSERT) { - throw new SQLException("Cannot call cancelRowUpdates() when inserting a new row", "24000"); - } Arrays.fill(parameterHolders, null); state = STATE_STANDARD; } @@ -1459,9 +1447,10 @@ public void cancelRowUpdates() throws SQLException { * {inheritDoc}. */ public void moveToInsertRow() throws SQLException { - if (!canBeInserted) throw new SQLException(exceptionInsertMsg, "24000"); + if (!canBeInserted) throw new SQLException(exceptionInsertMsg); Arrays.fill(parameterHolders, null); state = STATE_INSERT; + notInsertRowPointer = getRowPointer(); } /** @@ -1470,5 +1459,80 @@ public void moveToInsertRow() throws SQLException { public void moveToCurrentRow() throws SQLException { Arrays.fill(parameterHolders, null); state = STATE_STANDARD; + setRowPointer(notInsertRowPointer); + } + + + @Override + public void beforeFirst() throws SQLException { + if (state == STATE_INSERT) { + state = STATE_UPDATE; + setRowPointer(notInsertRowPointer); + } + super.beforeFirst(); } + + @Override + public boolean first() throws SQLException { + if (state == STATE_INSERT) { + state = STATE_UPDATE; + setRowPointer(notInsertRowPointer); + } + return super.first(); + } + + @Override + public boolean last() throws SQLException { + if (state == STATE_INSERT) { + state = STATE_UPDATE; + setRowPointer(notInsertRowPointer); + } + return super.last(); + } + + @Override + public void afterLast() throws SQLException { + if (state == STATE_INSERT) { + state = STATE_UPDATE; + setRowPointer(notInsertRowPointer); + } + super.afterLast(); + } + + @Override + public boolean absolute(int row) throws SQLException { + if (state == STATE_INSERT) { + state = STATE_UPDATE; + setRowPointer(notInsertRowPointer); + } + return super.absolute(row); + } + + @Override + public boolean relative(int rows) throws SQLException { + if (state == STATE_INSERT) { + state = STATE_UPDATE; + setRowPointer(notInsertRowPointer); + } + return super.relative(rows); + } + + @Override + public boolean next() throws SQLException { + if (state == STATE_INSERT) { + state = STATE_UPDATE; + setRowPointer(notInsertRowPointer); + } + return super.next(); + } + + @Override + public boolean previous() throws SQLException { + if (state == STATE_INSERT) { + state = STATE_UPDATE; + setRowPointer(notInsertRowPointer); + } + return super.previous(); + } + } diff --git a/src/test/java/org/mariadb/jdbc/ServerPrepareStatementTest.java b/src/test/java/org/mariadb/jdbc/ServerPrepareStatementTest.java index 70b4a9156..69f11a6d6 100644 --- a/src/test/java/org/mariadb/jdbc/ServerPrepareStatementTest.java +++ b/src/test/java/org/mariadb/jdbc/ServerPrepareStatementTest.java @@ -479,9 +479,9 @@ public void dataConformity() throws SQLException { new String(varbinary0, StandardCharsets.UTF_8)); - /*************************************************************************** - * Update Row - **************************************************************************/ + //*************************************************************************** + // Update Row + //*************************************************************************** rs.updateBoolean(1, Boolean.TRUE); rs.updateByte(2, (byte) 2);