Mercurial > hg > monetdb-java
diff src/main/java/nl/cwi/monetdb/jdbc/MonetStatement.java @ 376:ffdc7b0e102d
Updated JDBC driver to comply with JDBC 4.2 interface now we compile for Java 8. This includes:
- adding 8 methods to MonetCallableStatement
- adding 2 methods to MonetDatabaseMetaData
- adding 3 methods to MonetPreparedStatement
- adding 4 methods to MonetResultSet
- adding 8 methods to MonetStatement
Some methods needs some more work, for instance getLargeUpdateCount(). This will be done in a separate checkin.
author | Martin van Dinther <martin.van.dinther@monetdbsolutions.com> |
---|---|
date | Wed, 23 Sep 2020 18:55:33 +0200 (2020-09-23) |
parents | 253363a2ae28 |
children | 8a813f5cef1b |
line wrap: on
line diff
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetStatement.java +++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetStatement.java @@ -41,15 +41,12 @@ import java.util.concurrent.locks.Reentr * * @author Fabian Groffen * @author Martin van Dinther - * @version 0.8 + * @version 0.9 */ public class MonetStatement extends MonetWrapper implements Statement, AutoCloseable { - /** the default value of maxRows, 0 indicates unlimited */ - static final int DEF_MAXROWS = 0; - /** The parental Connection object */ protected final MonetConnection connection; /** The last ResponseList object this Statement produced */ @@ -68,8 +65,8 @@ public class MonetStatement private int queryTimeout = 0; /** The size of the blocks of results to ask for at the server */ private int fetchSize = 0; - /** The maximum number of rows to return in a ResultSet */ - private int maxRows = DEF_MAXROWS; + /** The maximum number of rows to return in a ResultSet, 0 indicates unlimited */ + private long maxRows = 0; /** The type of ResultSet to produce; i.e. forward only, random access */ private int resultSetType = MonetResultSet.DEF_RESULTSETTYPE; /** The suggested direction of fetching data (implemented but not used) */ @@ -797,7 +794,9 @@ public class MonetStatement */ @Override public int getMaxRows() { - return maxRows; + if (maxRows >= Integer.MAX_VALUE) + return Integer.MAX_VALUE; + return (int)maxRows; } /** @@ -1203,8 +1202,270 @@ public class MonetStatement return closeOnCompletion; } + //== Java 1.8 methods (JDBC 4.2) + + /** + * Retrieves the current result as an update count; + * if the result is a ResultSet object or there are no more results, -1 is returned. + * This method should be called only once per result. + * + * This method should be used when the returned row count may exceed Integer.MAX_VALUE. + * The default implementation will throw UnsupportedOperationException + * + * @return the current result as an update count; -1 if the current + * result is a ResultSet object or there are no more results + * @throws SQLException if a database access error occurs or this + * method is called on a closed Statement + */ + public long getLargeUpdateCount() throws SQLException { + return getUpdateCount(); + } + + /** + * Sets the limit for the maximum number of rows that any ResultSet object + * generated by this Statement object can contain to the given number. + * If the limit is exceeded, the excess rows are silently dropped. + * + * This method should be used when the row limit may exceed Integer.MAX_VALUE. + * The default implementation will throw UnsupportedOperationException + * + * @param max the new max rows limit; zero means there is no limit + * @throws SQLException if a database access error occurs, + * this method is called on a closed Statement or + * the condition max >= 0 is not satisfied + * @see #getLargeMaxRows() + */ + @Override + public void setLargeMaxRows(final long max) throws SQLException { + if (max < 0) + throw new SQLException("Illegal max value: " + max, "M1M05"); + maxRows = max; + } + + /** + * Retrieves the maximum number of rows that a ResultSet object produced by + * this Statement object can contain. If this limit is exceeded, the excess + * rows are silently dropped. + * + * This method should be used when the returned row limit may exceed Integer.MAX_VALUE. + * The default implementation will return 0 + * + * @return the current maximum number of rows for a ResultSet object + * produced by this Statement object; zero means there is no limit + * @see #setLargeMaxRows(long max) + */ + @Override + public long getLargeMaxRows() { + return maxRows; + } + + /** + * Submits a batch of commands to the database for execution and if + * all commands execute successfully, returns an array of update counts. + * The long elements of the array that is returned are ordered to + * correspond to the commands in the batch, which are ordered according + * to the order in which they were added to the batch. + * The elements in the array returned by the method executeLargeBatch + * may be one of the following: + * <ol> + * <li>A number greater than or equal to zero -- indicates that the command + * was processed successfully and is an update count giving the number of + * rows in the database that were affected by the command's execution</li> + * <li>A value of SUCCESS_NO_INFO -- indicates that the command was + * processed successfully but that the number of rows affected is unknown</li> + * If one of the commands in a batch update fails to execute properly, + * this method throws a BatchUpdateException, and a JDBC driver may or + * may not continue to process the remaining commands in the batch. + * However, the driver's behavior must be consistent with a particular DBMS, + * either always continuing to process commands or never continuing to process + * commands. If the driver continues processing after a failure, the array + * returned by the method BatchUpdateException.getLargeUpdateCounts will + * contain as many elements as there are commands in the batch, and at + * least one of the elements will be the following: + * <li>A value of EXECUTE_FAILED -- indicates that the command failed to + * execute successfully and occurs only if a driver continues to process + * commands after a command fails</li> + * </ol> + * + * This method should be used when the returned row count may exceed Integer.MAX_VALUE. + * The default implementation will throw UnsupportedOperationException + * + * MonetDB does continues after an error has occurred in the batch. + * If one of the commands attempts to return a result set, an + * SQLException is added to the SQLException list and thrown + * afterwards execution. Failing queries result in SQLExceptions + * too and may cause subparts of the batch to fail as well. + * + * @return an array of update counts containing one element for each + * command in the batch. The elements of the array are ordered + * according to the order in which commands were added to the batch. + * @throws SQLException if a database access error occurs, this method is called + * on a closed Statement or the driver does not support batch statements. + * Throws BatchUpdateException (a subclass of SQLException) if one of the + * commands sent to the database fails to execute properly or attempts to return a result set. + */ + @Override + public long[] executeLargeBatch() throws SQLException { + if (batch == null || batch.isEmpty()) { + return new long[0]; + } + + final int[] ret = executeBatch(); + // copy contents of int[] into new long[] + final long[] counts = new long[ret.length]; + for (int i = 0; i < ret.length; i++) { + counts[i] = ret[i]; + } + return counts; + } + + /** + * Executes the given SQL statement, which may be an INSERT, UPDATE, or + * DELETE statement or an SQL statement that returns nothing, such as an + * SQL DDL statement. + * + * This method should be used when the returned row count may exceed Integer.MAX_VALUE. + * Note: This method cannot be called on a PreparedStatement or CallableStatement. + * The default implementation will throw SQLFeatureNotSupportedException + * + * @param sql an SQL Data Manipulation Language (DML) statement, such as + * INSERT, UPDATE or DELETE; or an SQL statement that returns nothing, + * such as a DDL statement. + * @return either (1) the row count for SQL Data Manipulation Language (DML) statements + * or (2) 0 for SQL statements that return nothing + * @throws SQLException if a database access error occurs, this method is + * called on a closed Statement, the given SQL statement produces a + * ResultSet object, the method is called on a PreparedStatement or CallableStatement + */ + @Override + public long executeLargeUpdate(final String sql) throws SQLException { + if (execute(sql) != false) + throw new SQLException("Query produced a result set", "M1M17"); + + return getLargeUpdateCount(); + } + + /** + * Executes the given SQL statement and signals the driver with the + * given flag about whether the auto-generated keys produced by this + * Statement object should be made available for retrieval. + * The driver will ignore the flag if the SQL statement is not an INSERT + * statement, or an SQL statement able to return auto-generated keys + * (the list of such statements is vendor-specific). + * + * This method should be used when the returned row count may exceed Integer.MAX_VALUE. + * Note: This method cannot be called on a PreparedStatement or CallableStatement. + * The default implementation will throw SQLFeatureNotSupportedException + * + * @param sql an SQL Data Manipulation Language (DML) statement, such as + * INSERT, UPDATE or DELETE; or an SQL statement that returns nothing, + * such as a DDL statement. + * @param autoGeneratedKeys - a flag indicating whether + * auto-generated keys should be made available for + * retrieval; one of the following constants: + * Statement.RETURN_GENERATED_KEYS + * Statement.NO_GENERATED_KEYS + * @return either (1) the row count for SQL Data Manipulation Language (DML) statements + * or (2) 0 for SQL statements that return nothing + * @throws SQLException if a database access error occurs, this method is + * called on a closed Statement, the given SQL statement produces a + * ResultSet object, the given constant is not one of those allowed, + * the method is called on a PreparedStatement or CallableStatement + */ + @Override + public long executeLargeUpdate(final String sql, final int autoGeneratedKeys) + throws SQLException + { + if (autoGeneratedKeys != Statement.RETURN_GENERATED_KEYS && + autoGeneratedKeys != Statement.NO_GENERATED_KEYS) + throw new SQLException("Invalid argument, expected RETURN_GENERATED_KEYS or NO_GENERATED_KEYS", "M1M05"); + + /* MonetDB has no way to disable this, so just do the normal thing ;) */ + if (execute(sql) != false) + throw new SQLException("Query produced a result set", "M1M17"); + + return getLargeUpdateCount(); + } + + /** + * Executes the given SQL statement and signals the driver that the + * auto-generated keys indicated in the given array should be made + * available for retrieval. The driver will ignore the array if the + * SQL statement is not an INSERT statement. + * + * This method should be used when the returned row count may exceed Integer.MAX_VALUE. + * Note: This method cannot be called on a PreparedStatement or CallableStatement. + * The default implementation will throw SQLFeatureNotSupportedException + * + * MonetDB only supports returing the generated key for one column, + * which will be the first column that has a serial. Hence, this + * method cannot work as required and the driver will fall back to + * executing with request to the database to return the generated + * key, if any. + * + * @param sql an SQL Data Manipulation Language (DML) statement, such as + * INSERT, UPDATE or DELETE; or an SQL statement that returns nothing, + * such as a DDL statement. + * @param columnIndexes an array of column indexes indicating the + * columns that should be returned from the inserted row + * @return either (1) the row count for SQL Data Manipulation Language (DML) statements + * or (2) 0 for SQL statements that return nothing + * @throws SQLException if a database access error occurs, this method is + * called on a closed Statement, the given SQL statement produces a + * ResultSet object, the second argument supplied to this method is + * not an int array whose elements are valid column indexes, + * the method is called on a PreparedStatement or CallableStatement + */ + @Override + public long executeLargeUpdate(final String sql, final int[] columnIndexes) + throws SQLException + { + addWarning("executeLargeUpdate: generated keys for fixed set of columns not supported", "01M18"); + return executeLargeUpdate(sql, Statement.RETURN_GENERATED_KEYS); + } + + /** + * Executes the given SQL statement and signals the driver that the + * auto-generated keys indicated in the given array should be made + * available for retrieval. The driver will ignore the array if the + * SQL statement is not an INSERT statement. + * + * This method should be used when the returned row count may exceed Integer.MAX_VALUE. + * Note: This method cannot be called on a PreparedStatement or CallableStatement. + * The default implementation will throw SQLFeatureNotSupportedException + * + * MonetDB only supports returing the generated key for one column, + * which will be the first column that has a serial. Hence, this + * method cannot work as required and the driver will fall back to + * executing with request to the database to return the generated + * key, if any. + * + * @param sql an SQL Data Manipulation Language (DML) statement, such as + * INSERT, UPDATE or DELETE; or an SQL statement that returns nothing, + * such as a DDL statement. + * @param columnNames an array of the names of the columns that + * should be returned from the inserted row + * @return either (1) the row count for SQL Data Manipulation Language (DML) statements + * or (2) 0 for SQL statements that return nothing + * @throws SQLException if a database access error occurs, this method is + * called on a closed Statement, the given SQL statement produces a + * ResultSet object, the second argument supplied to this method is + * not a String array whose elements are valid column names, + * the method is called on a PreparedStatement or CallableStatement + */ + @Override + public long executeLargeUpdate(final String sql, final String[] columnNames) + throws SQLException + { + addWarning("executeLargeUpdate: generated keys for fixed set of columns not supported", "01M18"); + return executeLargeUpdate(sql, Statement.RETURN_GENERATED_KEYS); + } + //== end methods of interface Statement + + //== internal helper methods which do not belong to the JDBC interface + /** * Adds a warning to the pile of warnings this Statement object has. If * there were no warnings (or clearWarnings was called) this warning will