changeset 77:83aee4f60649

Added private method sendTransactionCommand(String); to reduce duplicate code in 6 methods. Throw a SQLFeatureNotSupportedException for not implemented methods: prepareStatement(String sql, int[] columnIndexes) and prepareStatement(String sql, String[] columnNames). Rest of the changes are only layout and removal of trailing tabs.
author Martin van Dinther <martin.van.dinther@monetdbsolutions.com>
date Thu, 15 Dec 2016 15:29:36 +0100 (2016-12-15)
parents 3abb3634f467
children 80de05f07508
files src/main/java/nl/cwi/monetdb/jdbc/MonetConnection.java
diffstat 1 files changed, 128 insertions(+), 173 deletions(-) [+]
line wrap: on
line diff
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetConnection.java
+++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetConnection.java
@@ -396,20 +396,7 @@ public class MonetConnection extends Mon
 	public void commit() throws SQLException {
 		// note: can't use sendIndependentCommand here because we need
 		// to process the auto_commit state the server gives
-
-		// create a container for the result
-		ResponseList l = new ResponseList(
-			0,
-			0,
-			ResultSet.FETCH_FORWARD,
-			ResultSet.CONCUR_READ_ONLY
-		);
-		// send commit to the server
-		try {
-			l.processQuery("COMMIT");
-		} finally {
-			l.close();
-		}
+		sendTransactionCommand("COMMIT");
 	}
 
 	/**
@@ -428,10 +415,7 @@ public class MonetConnection extends Mon
 	 */
 	@Override
 	public Statement createStatement() throws SQLException {
-		return createStatement(
-					ResultSet.TYPE_FORWARD_ONLY,
-					ResultSet.CONCUR_READ_ONLY,
-					ResultSet.HOLD_CURSORS_OVER_COMMIT);
+		return createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT);
 	}
 
 	/**
@@ -450,15 +434,8 @@ public class MonetConnection extends Mon
 	 * @throws SQLException if a database access error occurs
 	 */
 	@Override
-	public Statement createStatement(
-			int resultSetType,
-			int resultSetConcurrency)
-		throws SQLException
-	{
-		return createStatement(
-					resultSetType,
-					resultSetConcurrency,
-					ResultSet.HOLD_CURSORS_OVER_COMMIT);
+	public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
+		return createStatement(resultSetType, resultSetConcurrency, ResultSet.HOLD_CURSORS_OVER_COMMIT);
 	}
 
 	/**
@@ -485,20 +462,9 @@ public class MonetConnection extends Mon
 	 * concurrency, and holdability
 	 */
 	@Override
-	public Statement createStatement(
-			int resultSetType,
-			int resultSetConcurrency,
-			int resultSetHoldability)
-		throws SQLException
-	{
+	public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
 		try {
-			Statement ret =
-				new MonetStatement(
-					this,
-					resultSetType,
-					resultSetConcurrency,
-					resultSetHoldability
-				);
+			Statement ret = new MonetStatement(this, resultSetType, resultSetConcurrency, resultSetHoldability);
 			// store it in the map for when we close...
 			statements.put(ret, null);
 			return ret;
@@ -510,11 +476,9 @@ public class MonetConnection extends Mon
 	}
 
 	/**
-	 * Retrieves the current auto-commit mode for this Connection
-	 * object.
+	 * Retrieves the current auto-commit mode for this Connection object.
 	 *
-	 * @return the current state of this Connection object's auto-commit
-	 *         mode
+	 * @return the current state of this Connection object's auto-commit mode
 	 * @see #setAutoCommit(boolean)
 	 */
 	@Override
@@ -534,7 +498,7 @@ public class MonetConnection extends Mon
 		// MonetDB does NOT support catalogs
 		return null;
 	}
-	
+
 	/**
 	 * Retrieves the current holdability of ResultSet objects created
 	 * using this Connection object.
@@ -654,16 +618,29 @@ public class MonetConnection extends Mon
 	}
 
 	@Override
-	public String nativeSQL(String sql) {return sql;}
+	public String nativeSQL(String sql) {
+		/* there is currently no way to get the native MonetDB rewritten SQL string back, so just return the original string */
+		/* in future we may replace/remove the escape sequences { <escape-type> ...} before sending it to the server */
+		return sql;
+	}
 
 	@Override
-	public CallableStatement prepareCall(String sql) {return null;}
+	public CallableStatement prepareCall(String sql) {
+		/* not implemented yet */
+		return null;
+	}
 
 	@Override
-	public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) {return null;}
+	public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) {
+		/* not implemented yet */
+		return null;
+	}
 
 	@Override
-	public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) {return null;}
+	public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) {
+		/* not implemented yet */
+		return null;
+	}
 
 	/**
 	 * Creates a PreparedStatement object for sending parameterized SQL
@@ -694,12 +671,7 @@ public class MonetConnection extends Mon
 	 */
 	@Override
 	public PreparedStatement prepareStatement(String sql) throws SQLException {
-		return prepareStatement(
-					sql,
-					ResultSet.TYPE_FORWARD_ONLY,
-					ResultSet.CONCUR_READ_ONLY,
-					ResultSet.HOLD_CURSORS_OVER_COMMIT
-		);
+		return prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT);
 	}
 
 	/**
@@ -723,18 +695,8 @@ public class MonetConnection extends Mon
 	 *                      type and concurrency
 	 */
 	@Override
-	public PreparedStatement prepareStatement(
-			String sql,
-			int resultSetType,
-			int resultSetConcurrency)
-		throws SQLException
-	{
-		return prepareStatement(
-					sql,
-					resultSetType,
-					resultSetConcurrency,
-					ResultSet.HOLD_CURSORS_OVER_COMMIT
-		);
+	public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
+		return prepareStatement(sql, resultSetType, resultSetConcurrency, ResultSet.HOLD_CURSORS_OVER_COMMIT);
 	}
 
 	/**
@@ -764,11 +726,7 @@ public class MonetConnection extends Mon
 	 * concurrency, and holdability
 	 */
 	@Override
-	public PreparedStatement prepareStatement(
-			String sql,
-			int resultSetType,
-			int resultSetConcurrency,
-			int resultSetHoldability)
+	public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability)
 		throws SQLException
 	{
 		try {
@@ -823,29 +781,79 @@ public class MonetConnection extends Mon
 	 *         whether auto-generated keys should be returned
 	 */
 	@Override
-	public PreparedStatement prepareStatement(
-			String sql,
-			int autoGeneratedKeys)
-		throws SQLException
-	{
+	public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
 		if (autoGeneratedKeys != Statement.RETURN_GENERATED_KEYS &&
-				autoGeneratedKeys != Statement.NO_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 ;) */
-		return prepareStatement(
-					sql,
-					ResultSet.TYPE_FORWARD_ONLY,
-					ResultSet.CONCUR_READ_ONLY
-		);
+		return prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
 	}
 
+	/**
+	 * Creates a default PreparedStatement object capable of returning the auto-generated keys designated by the given array.
+	 * This array contains the indexes of the columns in the target table that contain the auto-generated keys that should be made available.
+	 * The driver will ignore the array 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).
+	 *
+	 * An SQL statement with or without IN parameters can be pre-compiled and stored in a PreparedStatement object.
+	 * This object can then be used to efficiently execute this statement multiple times.
+	 *
+	 * Note: This method is optimized for handling parametric SQL statements that benefit from precompilation.
+	 * If the driver supports precompilation, the method prepareStatement will send the statement to the database for precompilation.
+	 * Some drivers may not support precompilation. In this case, the statement may not be sent to the database until the PreparedStatement
+	 * object is executed. This has no direct effect on users; however, it does affect which methods throw certain SQLExceptions.
+	 *
+	 * Result sets created using the returned PreparedStatement object will by default be type TYPE_FORWARD_ONLY and have
+	 * a concurrency level of CONCUR_READ_ONLY. The holdability of the created result sets can be determined by calling getHoldability().
+	 *
+	 * Parameters:
+	 *     sql - an SQL statement that may contain one or more '?' IN parameter placeholders
+	 *     columnIndexes - an array of column indexes indicating the columns that should be returned from the inserted row or rows
+	 * Returns:
+	 *     a new PreparedStatement object, containing the pre-compiled statement, that is capable of
+	 *     returning the auto-generated keys designated by the given array of column indexes
+	 * Throws:
+	 *     SQLException - if a database access error occurs or this method is called on a closed connection
+	 *     SQLFeatureNotSupportedException - if the JDBC driver does not support this method
+	 */
 	@Override
-	public PreparedStatement prepareStatement(String sql, int[] columnIndexes) {return null;}
+	public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
+		throw new SQLFeatureNotSupportedException("prepareStatement(String sql, int[] columnIndexes) not supported", "0A000");
+	}
 
+	/**
+	 * Creates a default PreparedStatement object capable of returning the auto-generated keys designated by the given array.
+	 * This array contains the names of the columns in the target table that contain the auto-generated keys that should be returned.
+	 * The driver will ignore the array 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).
+	 *
+	 * An SQL statement with or without IN parameters can be pre-compiled and stored in a PreparedStatement object.
+	 * This object can then be used to efficiently execute this statement multiple times.
+	 *
+	 * Note: This method is optimized for handling parametric SQL statements that benefit from precompilation.
+	 * If the driver supports precompilation, the method prepareStatement will send the statement to the database for precompilation.
+	 * Some drivers may not support precompilation. In this case, the statement may not be sent to the database until the PreparedStatement
+	 * object is executed. This has no direct effect on users; however, it does affect which methods throw certain SQLExceptions.
+	 *
+	 * Result sets created using the returned PreparedStatement object will by default be type TYPE_FORWARD_ONLY and have
+	 * a concurrency level of CONCUR_READ_ONLY. The holdability of the created result sets can be determined by calling getHoldability().
+	 *
+	 * Parameters:
+	 *     sql - an SQL statement that may contain one or more '?' IN parameter placeholders
+	 *     columnNames - an array of column names indicating the columns that should be returned from the inserted row or rows
+	 * Returns:
+	 *     a new PreparedStatement object, containing the pre-compiled statement, that is capable of
+	 *     returning the auto-generated keys designated by the given array of column names
+	 * Throws:
+	 *     SQLException - if a database access error occurs or this method is called on a closed connection
+	 *     SQLFeatureNotSupportedException - if the JDBC driver does not support this method
+	 */
 	@Override
-	public PreparedStatement prepareStatement(String sql, String[] columnNames) {return null;}
+	public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
+		throw new SQLFeatureNotSupportedException("prepareStatement(String sql, String[] columnNames) not supported", "0A000");
+	}
 
 	/**
 	 * Removes the given Savepoint object from the current transaction.
@@ -866,20 +874,7 @@ public class MonetConnection extends Mon
 
 		// note: can't use sendIndependentCommand here because we need
 		// to process the auto_commit state the server gives
-
-		// create a container for the result
-		ResponseList l = new ResponseList(
-			0,
-			0,
-			ResultSet.FETCH_FORWARD,
-			ResultSet.CONCUR_READ_ONLY
-		);
-		// send the appropriate query string to the database
-		try {
-			l.processQuery("RELEASE SAVEPOINT " + sp.getName());
-		} finally {
-			l.close();
-		}
+		sendTransactionCommand("RELEASE SAVEPOINT " + sp.getName());
 	}
 
 	/**
@@ -895,20 +890,7 @@ public class MonetConnection extends Mon
 	public void rollback() throws SQLException {
 		// note: can't use sendIndependentCommand here because we need
 		// to process the auto_commit state the server gives
-
-		// create a container for the result
-		ResponseList l = new ResponseList(
-			0,
-			0,
-			ResultSet.FETCH_FORWARD,
-			ResultSet.CONCUR_READ_ONLY
-		);
-		// send rollback to the server
-		try {
-			l.processQuery("ROLLBACK");
-		} finally {
-			l.close();
-		}
+		sendTransactionCommand("ROLLBACK");
 	}
 
 	/**
@@ -930,20 +912,7 @@ public class MonetConnection extends Mon
 
 		// note: can't use sendIndependentCommand here because we need
 		// to process the auto_commit state the server gives
-
-		// create a container for the result
-		ResponseList l = new ResponseList(
-			0,
-			0,
-			ResultSet.FETCH_FORWARD,
-			ResultSet.CONCUR_READ_ONLY
-		);
-		// send the appropriate query string to the database
-		try {
-			l.processQuery("ROLLBACK TO SAVEPOINT " + sp.getName());
-		} finally {
-			l.close();
-		}
+		sendTransactionCommand("ROLLBACK TO SAVEPOINT " + sp.getName());
 	}
 
 	/**
@@ -1036,21 +1005,7 @@ public class MonetConnection extends Mon
 
 		// note: can't use sendIndependentCommand here because we need
 		// to process the auto_commit state the server gives
-
-		// create a container for the result
-		ResponseList l = new ResponseList(
-			0,
-			0,
-			ResultSet.FETCH_FORWARD,
-			ResultSet.CONCUR_READ_ONLY
-		);
-		// send the appropriate query string to the database
-		try {
-			l.processQuery("SAVEPOINT " + sp.getName());
-		} finally {
-			l.close();
-		}
-
+		sendTransactionCommand("SAVEPOINT " + sp.getName());
 		return sp;
 	}
 
@@ -1075,21 +1030,7 @@ public class MonetConnection extends Mon
 
 		// note: can't use sendIndependentCommand here because we need
 		// to process the auto_commit state the server gives
-
-		// create a container for the result
-		ResponseList l = new ResponseList(
-			0,
-			0,
-			ResultSet.FETCH_FORWARD,
-			ResultSet.CONCUR_READ_ONLY
-		);
-		// send the appropriate query string to the database
-		try {
-			l.processQuery("SAVEPOINT " + sp.getName());
-		} finally {
-			l.close();
-		}
-
+		sendTransactionCommand("SAVEPOINT " + sp.getName());
 		return sp;
 	}
 
@@ -1170,9 +1111,7 @@ public class MonetConnection extends Mon
 	 * @since 1.6
 	 */
 	@Override
-	public java.sql.Array createArrayOf(String typeName, Object[] elements)
-		throws SQLException
-	{
+	public java.sql.Array createArrayOf(String typeName, Object[] elements) throws SQLException {
 		throw new SQLFeatureNotSupportedException("createArrayOf() not supported", "0A000");
 	}
 
@@ -1243,9 +1182,7 @@ public class MonetConnection extends Mon
 	 * @since 1.6
 	 */
 	@Override
-	public java.sql.Struct createStruct(String typeName, Object[] attributes)
-		throws SQLException
-	{
+	public java.sql.Struct createStruct(String typeName, Object[] attributes) throws SQLException {
 		throw new SQLFeatureNotSupportedException("createStruct() not supported", "0A000");
 	}
 
@@ -1561,9 +1498,7 @@ public class MonetConnection extends Mon
 	 * @since 1.7
 	 */
 	@Override
-	public void setNetworkTimeout(Executor executor, int millis)
-		throws SQLException
-	{
+	public void setNetworkTimeout(Executor executor, int millis) throws SQLException {
 		if (closed)
 			throw new SQLException("Cannot call on closed Connection", "M1M20");
 		if (executor == null)
@@ -1624,6 +1559,26 @@ public class MonetConnection extends Mon
 		return blobIsBinary;
 	}
 
+
+	/**
+	 * Sends the given string to MonetDB as special transaction command.
+	 * All possible returned information is discarded.
+	 * Encountered errors are reported.
+	 *
+	 * @param command the exact string to send to MonetDB
+	 * @throws SQLException if an IO exception or a database error occurs
+	 */
+	private void sendTransactionCommand(String command) throws SQLException {
+		// create a container for the result
+		ResponseList l = new ResponseList(0, 0, ResultSet.FETCH_FORWARD, ResultSet.CONCUR_READ_ONLY);
+		// send the appropriate query string to the database
+		try {
+			l.processQuery(command);
+		} finally {
+			l.close();
+		}
+	}
+
 	/**
 	 * Sends the given string to MonetDB as regular statement, making
 	 * sure there is a prompt after the command is sent.  All possible
@@ -1945,7 +1900,7 @@ public class MonetConnection extends Mon
 		final private String[] getValues(char[] chrLine, int start, int stop) {
 			int elem = 0;
 			String[] values = new String[columncount];
-			
+
 			for (int i = start; i < stop; i++) {
 				if (chrLine[i] == '\t' && chrLine[i - 1] == ',') {
 					values[elem++] =
@@ -2176,7 +2131,7 @@ public class MonetConnection extends Mon
 		}
 	}
 	// }}}
-	
+
 	/**
 	 * The DataBlockResponse is tabular data belonging to a
 	 * ResultSetResponse.  Tabular data from the server typically looks
@@ -2308,7 +2263,7 @@ public class MonetConnection extends Mon
 	static class UpdateResponse implements Response {
 		public final int count;
 		public final String lastid;
-		
+
 		public UpdateResponse(int cnt, String id) {
 			// fill the blank finals
 			this.count = cnt;
@@ -2349,7 +2304,7 @@ public class MonetConnection extends Mon
 	// {{{ SchemaResponse class implementation
 	class SchemaResponse implements Response {
 		public final int state = Statement.SUCCESS_NO_INFO;
-		
+
 		@Override
 		public String addLine(String line, int linetype) {
 			return "Header lines are not supported for a SchemaResponse";
@@ -2380,7 +2335,7 @@ public class MonetConnection extends Mon
 	// {{{ AutoCommitResponse class implementation
 	class AutoCommitResponse extends SchemaResponse {
 		public final boolean autocommit;
-		
+
 		public AutoCommitResponse(boolean ac) {
 			// fill the blank final
 			this.autocommit = ac;
@@ -2823,7 +2778,7 @@ public class MonetConnection extends Mon
 		private BufferedMCLWriter out;
 		private String error;
 		private int state = WAIT;
-		
+
 		final Lock sendLock = new ReentrantLock();
 		final Condition queryAvailable = sendLock.newCondition();
 		final Condition waiting = sendLock.newCondition();