Mercurial > hg > monetdb-java
changeset 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 | a229ac4e275c |
children | 8a813f5cef1b |
files | ChangeLog release.txt src/main/java/nl/cwi/monetdb/jdbc/MonetCallableStatement.java src/main/java/nl/cwi/monetdb/jdbc/MonetConnection.java src/main/java/nl/cwi/monetdb/jdbc/MonetDatabaseMetaData.java src/main/java/nl/cwi/monetdb/jdbc/MonetPreparedStatement.java src/main/java/nl/cwi/monetdb/jdbc/MonetResultSet.java src/main/java/nl/cwi/monetdb/jdbc/MonetStatement.java |
diffstat | 8 files changed, 464 insertions(+), 84 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog +++ b/ChangeLog @@ -2,10 +2,20 @@ # This file is updated with Maddlog * Wed Sep 23 2020 Martin van Dinther <martin.van.dinther@monetdbsolutions.com> +- 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 - Corrected MonetDatabaseMetaData.getTypeInfo() - - The LITERAL_PREFIX column now includes the required casting name for types: clob, inet, json, url, uuid and blob. - - The SEARCHABLE column now returns typePredBasic instead of typeSearchable for type: blob. - - The AUTO_INCREMENT column now returns false for types: hugeint, decimal, oid and wrd. + - The LITERAL_PREFIX column now includes the required casting name for + types: clob, inet, json, url, uuid and blob. + - The SEARCHABLE column now returns typePredBasic instead of typeSearchable + for type: blob. + - The AUTO_INCREMENT column now returns false for types: hugeint, decimal, + oid and wrd. * Thu Sep 10 2020 Martin van Dinther <martin.van.dinther@monetdbsolutions.com> - Removed support for deprecated MD5 encryption algorithm in MapiSocket.
--- a/release.txt +++ b/release.txt @@ -43,8 +43,8 @@ See also: https://www.monetdb.org/Docume JDBC COMPLIANCE The MonetDB JDBC driver is a type 4 driver (100% pure Java) and -complies to JDBC 4.1 definition, see - http://docs.oracle.com/javase/7/docs/technotes/guides/jdbc/index.html +complies to JDBC 4.2 definition, see + http://docs.oracle.com/javase/8/docs/technotes/guides/jdbc/index.html and https://en.wikipedia.org/wiki/Java_Database_Connectivity @@ -60,7 +60,7 @@ If you feel some features are missing or please let us know at our bugtracker: https://www.monetdb.org/bugzilla/ -Currently implemented JDBC 4.1 interfaces include: +Currently implemented JDBC 4.2 interfaces include: * java.sql.Driver * java.sql.Connection @@ -138,11 +138,13 @@ Currently implemented JDBC 4.1 interface The following java.sql.* interfaces are NOT implemented: * java.sql.Array + * java.sql.DriverAction * java.sql.NClob * java.sql.Ref * java.sql.Rowid * java.sql.SQLInput * java.sql.SQLOutput + * java.sql.SQLType * java.sql.SQLXML * java.sql.Struct
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetCallableStatement.java +++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetCallableStatement.java @@ -23,6 +23,7 @@ import java.sql.Ref; import java.sql.RowId; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; +import java.sql.SQLType; // new as of Java 1.8 import java.sql.SQLXML; import java.sql.Time; import java.sql.Timestamp; @@ -63,7 +64,7 @@ import java.util.Map; * because output parameters in stored procedures are not supported by MonetDB. * * @author Martin van Dinther - * @version 1.0 + * @version 1.1 */ public class MonetCallableStatement @@ -631,5 +632,44 @@ public class MonetCallableStatement throw newSQLFeatureNotSupportedException("wasNull"); } + //== Java 1.8 methods (JDBC 4.2) + + @Override + public void setObject(String parameterName, Object x, SQLType targetSqlType, int scaleOrLength) throws SQLException { + // setObject(nameToIndex(parameterName), x, convertSQLType(targetSqlType), scaleOrLength); // TODO implement convertSQLType(targetSqlType) + throw newSQLFeatureNotSupportedException("setObject"); + } + + @Override + public void setObject(String parameterName, Object x, SQLType targetSqlType) throws SQLException { + // setObject(nameToIndex(parameterName), x, convertSQLType(targetSqlType)); // TODO implement convertSQLType(targetSqlType) + throw newSQLFeatureNotSupportedException("setObject"); + } + + @Override + public void registerOutParameter(int parameterIndex, SQLType sqlType) throws SQLException { + throw newSQLFeatureNotSupportedException("registerOutParameter"); + } + @Override + public void registerOutParameter(int parameterIndex, SQLType sqlType, int scale) throws SQLException { + throw newSQLFeatureNotSupportedException("registerOutParameter"); + } + @Override + public void registerOutParameter(int parameterIndex, SQLType sqlType, String typeName) throws SQLException { + throw newSQLFeatureNotSupportedException("registerOutParameter"); + } + @Override + public void registerOutParameter(String parameterName, SQLType sqlType) throws SQLException { + throw newSQLFeatureNotSupportedException("registerOutParameter"); + } + @Override + public void registerOutParameter(String parameterName, SQLType sqlType, int scale) throws SQLException { + throw newSQLFeatureNotSupportedException("registerOutParameter"); + } + @Override + public void registerOutParameter(String parameterName, SQLType sqlType, String typeName) throws SQLException { + throw newSQLFeatureNotSupportedException("registerOutParameter"); + } + // end methods interface CallableStatement }
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetConnection.java +++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetConnection.java @@ -2697,7 +2697,7 @@ public class MonetConnection /** The cache size (number of rows in a DataBlockResponse object) */ private final int cachesize; /** The maximum number of results for this query */ - private final int maxrows; + private final long maxrows; /** The ResultSet type to produce */ private final int rstype; /** The ResultSet concurrency to produce */ @@ -2726,7 +2726,7 @@ public class MonetConnection */ ResponseList( final int cachesize, - final int maxrows, + final long maxrows, final int rstype, final int rsconcur ) throws SQLException { @@ -2858,7 +2858,7 @@ public class MonetConnection */ int size = (cachesize == 0 ? DEF_FETCHSIZE : cachesize); if (maxrows > 0 && maxrows < size) - size = maxrows; + size = (int)maxrows; // don't do work if it's not needed if (lang == LANG_SQL && size != curReplySize && templ != commandTempl) { sendControlCommand("reply_size " + size); @@ -2887,12 +2887,12 @@ public class MonetConnection case StartOfHeaderParser.Q_TABLE: case StartOfHeaderParser.Q_PREPARE: { final int id = sohp.getNextAsInt(); - int tuplecount = sohp.getNextAsInt(); + int tuplecount = sohp.getNextAsInt(); // TODO implement StartOfHeaderParser.getNextAsLong() and change tuplecount to long final int columncount = sohp.getNextAsInt(); final int rowcount = sohp.getNextAsInt(); // enforce the maxrows setting if (maxrows != 0 && tuplecount > maxrows) - tuplecount = maxrows; + tuplecount = (int)maxrows; res = new ResultSetResponse(id, tuplecount, columncount, rowcount, this, seqnr); // only add this resultset to the hashmap if it can possibly have an additional datablock if (rowcount < tuplecount) {
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetDatabaseMetaData.java +++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetDatabaseMetaData.java @@ -22,7 +22,7 @@ import java.sql.Types; * * @author Fabian Groffen * @author Martin van Dinther - * @version 0.9 + * @version 1.0 */ public class MonetDatabaseMetaData extends MonetWrapper @@ -4023,12 +4023,12 @@ public class MonetDatabaseMetaData return true; } - //== 1.8 methods (JDBC 4.2) + //== Java 1.8 methods (JDBC 4.2) /** * Retrieves the maximum number of bytes this database allows for the logical size for a LOB. * The default implementation will return 0 - * @return the maximum number of bytes + * @return the maximum number of bytes allowed; a result of zero means that there is no limit or the limit is not known */ @Override public long getMaxLogicalLobSize() { @@ -4038,7 +4038,7 @@ public class MonetDatabaseMetaData /** * Retrieves whether this database supports REF CURSOR. * The default implementation will return false - * @return true if so, false otherwise + * @return true if this database supports REF CURSOR; false otherwise */ @Override public boolean supportsRefCursors() {
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetPreparedStatement.java +++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetPreparedStatement.java @@ -30,6 +30,7 @@ import java.sql.SQLDataException; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; import java.sql.SQLOutput; +import java.sql.SQLType; // new as of Java 1.8 import java.sql.SQLXML; import java.sql.Struct; import java.sql.Time; @@ -61,7 +62,7 @@ import java.util.Map; * * @author Fabian Groffen * @author Martin van Dinther - * @version 0.5 + * @version 0.6 */ public class MonetPreparedStatement extends MonetStatement @@ -2613,8 +2614,46 @@ public class MonetPreparedStatement close(); } + //== Java 1.8 methods (JDBC 4.2) + + @Override + public void setObject(final int parameterIndex, final Object x, final SQLType targetSqlType, final int scaleOrLength) throws SQLException { + // setObject(parameterIndex, x, convertSQLType(targetSqlType), scaleOrLength); // TODO implement convertSQLType(targetSqlType) + throw newSQLFeatureNotSupportedException("setObject"); + } + + @Override + public void setObject(final int parameterIndex, final Object x, final SQLType targetSqlType) throws SQLException { + // setObject(parameterIndex, x, convertSQLType(targetSqlType)); // TODO implement convertSQLType(targetSqlType) + throw newSQLFeatureNotSupportedException("setObject"); + } + + /** + * Executes the SQL statement in this PreparedStatement object, which must be + * an SQL Data Manipulation Language (DML) statement, such as INSERT, UPDATE or DELETE statement; + * or an SQL statement that returns nothing, such as a DDL statement. + * + * This method should be used when the returned row count may exceed Integer.MAX_VALUE. + * The default implementation will throw UnsupportedOperationException + * + * @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 PreparedStatement + * or the SQL statement returns a ResultSet object + */ + @Override + public long executeLargeUpdate() throws SQLException { + if (execute() != false) + throw new SQLException("Query produced a result set", "M1M17"); + + return getLargeUpdateCount(); + } + //== end methods interface PreparedStatement + + //== internal helper methods which do not belong to the JDBC interface + /** * Sets the given index with the supplied value. If the given index is * out of bounds, and SQLException is thrown. The given value should
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetResultSet.java +++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetResultSet.java @@ -29,6 +29,7 @@ import java.sql.SQLDataException; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; import java.sql.SQLInput; +import java.sql.SQLType; // new as of Java 1.8 import java.sql.SQLWarning; import java.sql.SQLXML; import java.sql.Statement; @@ -58,8 +59,9 @@ import java.util.TimeZone; * for FORWARD_ONLY result sets the memory usage will be likely lower for large * result sets. * - * @author Fabian Groffen, Martin van Dinther - * @version 0.8 + * @author Fabian Groffen + * @author Martin van Dinther + * @version 0.9 */ public class MonetResultSet extends MonetWrapper @@ -2213,63 +2215,6 @@ public class MonetResultSet } /** - * Retrieves the value of the designated column in the current row - * of this ResultSet object and will convert from the SQL type of - * the column to the requested Java data type, if the conversion is - * supported. If the conversion is not supported or null is - * specified for the type, a SQLException is thrown. - * - * At a minimum, an implementation must support the conversions defined - * in Appendix B, Table B-3 and conversion of appropriate user defined - * SQL types to a Java type which implements SQLData, or Struct. - * Additional conversions may be supported and are vendor defined. - * - * @param columnIndex the first column is 1, the second is 2, ... - * @param type Class representing the Java data type to convert the - * designated column to - * @return an instance of type holding the column value - * @throws SQLException if conversion is not supported, type is - * null or another error occurs. The getCause() method of - * the exception may provide a more detailed exception, for - * example, if a conversion error occurs - * @throws SQLFeatureNotSupportedException the JDBC driver does - * not support this method - */ - @Override - public <T> T getObject(final int columnIndex, final Class<T> type) throws SQLException { - checkNotClosed(); - if (type == null) - throw new SQLException("type is null", "M1M05"); - - throw newSQLFeatureNotSupportedException("getObject(column, Class<T> type)"); - } - - /** - * Retrieves the value of the designated column in the current row - * of this ResultSet object and will convert from the SQL type of - * the column to the requested Java data type, if the conversion is - * supported. If the conversion is not supported or null is - * specified for the type, a SQLException is thrown. - * - * @param columnLabel the label for the column specified with the - * SQL AS clause. If the SQL AS clause was not specified, - * then the label is the name of the column - * @param type Class representing the Java data type to convert the - * designated column to - * @return an instance of type holding the column value - * @throws SQLException if conversion is not supported, type is - * null or another error occurs. The getCause() method of - * the exception may provide a more detailed exception, for - * example, if a conversion error occurs - * @throws SQLFeatureNotSupportedException the JDBC driver does - * not support this method - */ - @Override - public <T> T getObject(final String columnLabel, final Class<T> type) throws SQLException { - return getObject(findColumn(columnLabel), type); - } - - /** * Helper method to support the getObject and * ResultsetMetaData.getColumnClassName JDBC methods. * @@ -3785,8 +3730,92 @@ public class MonetResultSet return lastReadWasNull; } + //== Java 1.7 methods (JDBC 4.1) + + /** + * Retrieves the value of the designated column in the current row + * of this ResultSet object and will convert from the SQL type of + * the column to the requested Java data type, if the conversion is + * supported. If the conversion is not supported or null is + * specified for the type, a SQLException is thrown. + * + * At a minimum, an implementation must support the conversions defined + * in Appendix B, Table B-3 and conversion of appropriate user defined + * SQL types to a Java type which implements SQLData, or Struct. + * Additional conversions may be supported and are vendor defined. + * + * @param columnIndex the first column is 1, the second is 2, ... + * @param type Class representing the Java data type to convert the + * designated column to + * @return an instance of type holding the column value + * @throws SQLException if conversion is not supported, type is + * null or another error occurs. The getCause() method of + * the exception may provide a more detailed exception, for + * example, if a conversion error occurs + * @throws SQLFeatureNotSupportedException the JDBC driver does + * not support this method + */ + @Override + public <T> T getObject(final int columnIndex, final Class<T> type) throws SQLException { + checkNotClosed(); + if (type == null) + throw new SQLException("type is null", "M1M05"); + + throw newSQLFeatureNotSupportedException("getObject(column, Class<T> type)"); + } + + /** + * Retrieves the value of the designated column in the current row + * of this ResultSet object and will convert from the SQL type of + * the column to the requested Java data type, if the conversion is + * supported. If the conversion is not supported or null is + * specified for the type, a SQLException is thrown. + * + * @param columnLabel the label for the column specified with the + * SQL AS clause. If the SQL AS clause was not specified, + * then the label is the name of the column + * @param type Class representing the Java data type to convert the + * designated column to + * @return an instance of type holding the column value + * @throws SQLException if conversion is not supported, type is + * null or another error occurs. The getCause() method of + * the exception may provide a more detailed exception, for + * example, if a conversion error occurs + * @throws SQLFeatureNotSupportedException the JDBC driver does + * not support this method + */ + @Override + public <T> T getObject(final String columnLabel, final Class<T> type) throws SQLException { + return getObject(findColumn(columnLabel), type); + } + + //== Java 1.8 methods (JDBC 4.2) + + @Override + public void updateObject(int columnIndex, Object x, SQLType targetSqlType, int scaleOrLength) throws SQLException { + throw newSQLFeatureNotSupportedException("updateObject"); + } + + @Override + public void updateObject(String columnLabel, Object x, SQLType targetSqlType, int scaleOrLength) throws SQLException { + throw newSQLFeatureNotSupportedException("updateObject"); + } + + @Override + public void updateObject(int columnIndex, Object x, SQLType targetSqlType) throws SQLException { + throw newSQLFeatureNotSupportedException("updateObject"); + } + + @Override + public void updateObject(String columnLabel, Object x, SQLType targetSqlType) throws SQLException { + throw newSQLFeatureNotSupportedException("updateObject"); + } + //== end methods of interface ResultSet + + //== internal helper methods which do not belong to the JDBC interface + /** * Adds a warning to the pile of warnings this ResultSet object has. If * there were no warnings (or clearWarnings was called) this warning will @@ -3837,4 +3866,3 @@ public class MonetResultSet return new SQLDataException("Could not convert value to a number. " + error.getMessage(), "22003"); } } -
--- 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