Mercurial > hg > monetdb-java
changeset 65:e605cdd6373f embedded
More cleaning. Created the responses layer. The JDBC embedded connection will be compatible with the standard embedded API.
line wrap: on
line diff
--- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,23 @@ # ChangeLog file for java # This file is updated with Maddlog +* Thu Nov 17 2016 Martin van Dinther <martin.van.dinther@monetdbsolutions.com> +- The MapiSocket object now supports getting and setting the + socket timeout, even before the TCP socket is created. To set + the socket timeout specify it in the JDBC URL, for example: + jdbc:monetdb://localhost:50000/demo?so_timeout=8000 + This enables the timeout and sets it to 8000 milliseconds (= 8 seconds). + By default the timeout is not set, so wait infinitely. + +* Thu Nov 10 2016 Martin van Dinther <martin.van.dinther@monetdbsolutions.com> +- Implemented Connection methods: getClientInfo(name) and getClientInfo(). + They used to return null and empty Properties object. + Corrected implementation of Connection methods: setClientInfo(name, value) + and setClientInfo(properties). They are now processed as expected. + Corrected implementation of Connection.setHoldability(holdability). It now + throws an SQLFeatureNotSupportedException when holdability is not + ResultSet.HOLD_CURSORS_OVER_COMMIT (which is the only supported holdability). + * Thu Oct 13 2016 Martin van Dinther <martin.van.dinther@monetdbsolutions.com> - Corrected implementation of java.sql.Wrapper methods isWrapperFor() and unwrap(). They now properly return expected results instead of
--- a/release.txt +++ b/release.txt @@ -5,41 +5,39 @@ Release date: 2016-07-13 This JDBC driver is designed for use with MonetDB, a main-memory database. For more information see https://www.monetdb.org/. +The JDBC driver complies to JDBC 4.1 definition, see + http://docs.oracle.com/javase/7/docs/technotes/guides/jdbc/index.html + +Note: as of Jul2015 release we compile all the java sources to target: Java 1.7 +so you need a JRE/JDK of version 1.7 or higher to use it. + Within the current implementation not all functionalities of the JDBC interface are available. It is believed, however, that this implementation is rich enough to be suitable for a majority of application settings. -Note that this driver is JDBC4 compatible, and hence cannot be compiled -with Java 1.5 and earlier. -As of Jul2015 release we compile the java sources to target: Java 1.7. -Below a list of supported features can be found. Please read this list -if you intend to use this driver. +Below a list of (un)supported features can be found. +Please read this list if you intend to use this driver. If you feel some features are missing or have encountered an issue/bug, please let us know at our bugtracker: - https://bugs.monetdb.org/Developers/ReportingABug + https://www.monetdb.org/bugzilla/ + -Currently implemented JDBC interfaces: +Currently implemented JDBC 4.1 interfaces include: * java.sql.Driver - * javax.sql.DataSource (not tested) - * java.sql.Connection The next features/methods are NOT implemented: - - createStatement with result set holdability - - nativeSQL (there is no query parsing for JDBC escapes yet) - - prepareCall (CallableStatement not supported) - - prepareStatement with column indices or names - - setCatalog (there is no catalog) - - setHoldability (close/hold cursors over commit is not - configurable) - - isReadOnly/setReadOnly (updateable result sets are not supported at - all) - createArrayOf - createBlob, createClob, createNClob - createStruct - createSQLXML + - createStatement with result set holdability + - prepareCall (CallableStatement is not supported) + - prepareStatement with column indices or names + - setHoldability (close/hold cursors over commit is not + configurable) NOTE: be sure to check for warnings after setting concurrencies or isolation levels; MonetDB currently does not support anything else but "fully serializable" transactions. @@ -48,19 +46,19 @@ Currently implemented JDBC interfaces: * java.sql.Statement The next features/methods are NOT implemented: - - cancel/getQueryTimeout/setQueryTimeout (query execution cannot be - terminated, once started) + - cancel (query execution cannot be terminated, once started) - execute with column indices or names - executeUpdate with column indices or names - - getMaxFieldSize/setMaxFieldSize + - setMaxFieldSize - setCursorName - - setEscapeProcessing + - setEscapeProcessing on * java.sql.PreparedStatement The next features/methods are NOT implemented: - setArray - setAsciiStream, setBinaryStream, setUnicodeStream - - setBlob, setNClob, setNString + - setBlob + - setNCharacterStream, setNClob, setNString - setRef, setRowId, setSQLXML, setURL * java.sql.ParameterMetaData @@ -68,14 +66,17 @@ Currently implemented JDBC interfaces: * java.sql.ResultSet The next features/methods are NOT implemented: - getArray - - getAsciiStream, getBinaryStream, getUnicodeStream - - getRef, getURL + - getAsciiStream, getUnicodeStream + - getNCharacterStream, getNClob, getNString + - getRef, getRowId, getSQLXML - all methods related to updateable result sets * java.sql.ResultSetMetaData * java.sql.SavePoint + * java.sql.Wrapper + * java.sql.Blob A simple implementation using a byte[] to store the whole BLOB The next features/methods are NOT implemented: @@ -89,7 +90,18 @@ Currently implemented JDBC interfaces: - setAsciiStream - setCharacterStream + * javax.sql.DataSource (not tested) -- Auto-commit behaviour is defined by the server which handles the - auto-commit. This is in general in line with the JDBC standard. +The next java.sql.* interfaces are NOT implemented: + * java.sql.Array + * java.sql.CallableStatement (use Statement or PreparedStatement instead) + * java.sql.NClob + * java.sql.Ref + * java.sql.Rowid + * java.sql.SQLData + * java.sql.SQLInput + * java.sql.SQLOutput + * java.sql.SQLXML + * java.sql.Struct +
deleted file mode 100644 --- a/src/main/java/nl/cwi/monetdb/embedded/env/IEmbeddedConnection.java +++ /dev/null @@ -1,11 +0,0 @@ -package nl.cwi.monetdb.embedded.env; - -/** - * Created by ferreira on 11/24/16. - */ -public interface IEmbeddedConnection { - - long getConnectionPointer(); - - void closeConnectionImplementation(); -}
--- a/src/main/java/nl/cwi/monetdb/embedded/env/MonetDBEmbeddedConnection.java +++ b/src/main/java/nl/cwi/monetdb/embedded/env/MonetDBEmbeddedConnection.java @@ -22,9 +22,9 @@ import java.util.concurrent.ConcurrentHa * * @author <a href="mailto:pedro.ferreira@monetdbsolutions.com">Pedro Ferreira</a> */ -public final class MonetDBEmbeddedConnection implements IEmbeddedConnection { +public class MonetDBEmbeddedConnection { - private final long connectionPointer; + protected final long connectionPointer; private final ConcurrentHashMap<Long, AbstractConnectionResult> results = new ConcurrentHashMap<>();
--- a/src/main/java/nl/cwi/monetdb/embedded/env/MonetDBEmbeddedDatabase.java +++ b/src/main/java/nl/cwi/monetdb/embedded/env/MonetDBEmbeddedDatabase.java @@ -8,8 +8,7 @@ package nl.cwi.monetdb.embedded.env; -import nl.cwi.monetdb.mcl.connection.EmbeddedMonetDB; -import nl.cwi.monetdb.mcl.io.InternalConnection; +import nl.cwi.monetdb.mcl.io.JDBCEmbeddedConnection; import java.util.concurrent.ConcurrentHashMap; @@ -115,7 +114,7 @@ public final class MonetDBEmbeddedDataba if(MonetDBEmbeddedDatabase == null) { throw new MonetDBEmbeddedException("The database is not running!"); } else { - for(IEmbeddedConnection mdbec : MonetDBEmbeddedDatabase.connections.values()) { + for(MonetDBEmbeddedConnection mdbec : MonetDBEmbeddedDatabase.connections.values()) { mdbec.closeConnectionImplementation(); } MonetDBEmbeddedDatabase.connections.clear(); @@ -139,7 +138,7 @@ public final class MonetDBEmbeddedDataba private final boolean sequentialFlag; - private final ConcurrentHashMap<Long, IEmbeddedConnection> connections = new ConcurrentHashMap<>(); + private final ConcurrentHashMap<Long, MonetDBEmbeddedConnection> connections = new ConcurrentHashMap<>(); private MonetDBEmbeddedDatabase(String dbDirectory, boolean silentFlag, boolean sequentialFlag) { this.databaseDirectory = dbDirectory; @@ -163,23 +162,13 @@ public final class MonetDBEmbeddedDataba } } - /* - * Creates a connection on the database, set on the default schema asynchronously. - * - * @return A MonetDBEmbeddedConnection instance - * @throws MonetDBEmbeddedException If the database is not running or an error in the database occurred - */ - /*public CompletableFuture<MonetDBEmbeddedConnection> createConnectionAsync() throws MonetDBEmbeddedException { - return CompletableFuture.supplyAsync(() -> this.createConnectionInternal()); - }*/ - - public static InternalConnection AddJDBCEmbeddedConnection() throws MonetDBEmbeddedException { + public static JDBCEmbeddedConnection CreateJDBCEmbeddedConnection() throws MonetDBEmbeddedException { if(MonetDBEmbeddedDatabase == null) { throw new MonetDBEmbeddedException("The database is not running!"); } else { - InternalConnection res = MonetDBEmbeddedDatabase.createJDBCConnectionInternal(); - MonetDBEmbeddedDatabase.connections.put(res.getConnectionPointer(), res); - return res; + JDBCEmbeddedConnection con = MonetDBEmbeddedDatabase.createJDBCEmbeddedConnectionInternal(); + MonetDBEmbeddedDatabase.connections.put(con.getConnectionPointer(), con); + return con; } } @@ -210,5 +199,5 @@ public final class MonetDBEmbeddedDataba /** * Internal implementation to create a JDBC embeddded connection on this database. */ - private native InternalConnection createJDBCConnectionInternal() throws MonetDBEmbeddedException; + private native JDBCEmbeddedConnection createJDBCEmbeddedConnectionInternal() throws MonetDBEmbeddedException; }
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetConnection.java +++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetConnection.java @@ -7,10 +7,9 @@ import nl.cwi.monetdb.mcl.connection.Deb import nl.cwi.monetdb.mcl.connection.MonetDBLanguage; import nl.cwi.monetdb.mcl.parser.MCLParseException; import nl.cwi.monetdb.responses.ResponseList; -import nl.cwi.monetdb.responses.SendThread; +import nl.cwi.monetdb.mcl.connection.SendThread; import java.io.*; -import java.net.SocketException; import java.net.SocketTimeoutException; import java.sql.*; import java.util.*; @@ -38,16 +37,15 @@ import java.util.concurrent.Executor; * The current state of this connection is that it nearly implements the * whole Connection interface. * - * @author Fabian Groffen - * @version 1.2 + * @author Martin van Dinther + * @version 1.3 */ public abstract class MonetConnection extends MonetWrapper implements Connection { /** the successful processed input properties */ - private final Properties conn_props; - + protected final Properties conn_props; /** The language to connect with */ - protected MonetDBLanguage currentMonetDBLanguage = MonetDBLanguage.LANG_SQL; + protected MonetDBLanguage language; /** The database to connect to */ protected String database; /** Authentication hash method */ @@ -96,17 +94,17 @@ public abstract class MonetConnection ex this.conn_props = props; this.database = database; this.hash = hash; - this.currentMonetDBLanguage = MonetDBLanguage.GetLanguageFromString(language); + this.language = MonetDBLanguage.GetLanguageFromString(language); this.blobIsBinary = blobIsBinary; this.isDebugging = isDebugging; } - public MonetDBLanguage getCurrentMonetDBLanguage() { - return currentMonetDBLanguage; + public MonetDBLanguage getLanguage() { + return language; } - public void setCurrentMonetDBLanguage(MonetDBLanguage currentMonetDBLanguage) { - this.currentMonetDBLanguage = currentMonetDBLanguage; + public void setLanguage(MonetDBLanguage language) { + this.language = language; } public void setDebugging(String filename) throws IOException { @@ -129,9 +127,9 @@ public abstract class MonetConnection ex public abstract int getBlockSize(); - public abstract int getSoTimeout() throws SocketException; + public abstract int getSoTimeout(); - public abstract void setSoTimeout(int s) throws SocketException; + public abstract void setSoTimeout(int s); public abstract void closeUnderlyingConnection() throws IOException; @@ -227,44 +225,6 @@ public abstract class MonetConnection ex } /** - * Factory method for creating Array objects. - * - * Note: When createArrayOf is used to create an array object that - * maps to a primitive data type, then it is implementation-defined - * whether the Array object is an array of that primitive data type - * or an array of Object. - * - * Note: The JDBC driver is responsible for mapping the elements - * Object array to the default JDBC SQL type defined in - * java.sql.Types for the given class of Object. The default mapping - * is specified in Appendix B of the JDBC specification. If the - * resulting JDBC type is not the appropriate type for the given - * typeName then it is implementation defined whether an - * SQLException is thrown or the driver supports the resulting - * conversion. - * - * @param typeName the SQL name of the type the elements of the - * array map to. The typeName is a database-specific name - * which may be the name of a built-in type, a user-defined - * type or a standard SQL type supported by this database. - * This is the value returned by Array.getBaseTypeName - * @return an Array object whose elements map to the specified SQL - * type - * @throws SQLException if a database error occurs, the JDBC type - * is not appropriate for the typeName and the conversion is - * not supported, the typeName is null or this method is - * called on a closed connection - * @throws SQLFeatureNotSupportedException the JDBC driver does - * not support this data type - * - * @since 1.6 - */ - @Override - public Array createArrayOf(String typeName, Object[] elements) throws SQLException { - throw new SQLFeatureNotSupportedException("createArrayOf(String, Object[]) not supported", "0A000"); - } - - /** * Creates a Statement object for sending SQL statements to the * database. SQL statements without parameters are normally * executed using Statement objects. If the same SQL statement is @@ -341,88 +301,6 @@ public abstract class MonetConnection ex } /** - * Constructs an object that implements the Clob interface. The - * object returned initially contains no data. The setAsciiStream, - * setCharacterStream and setString methods of the Clob interface - * may be used to add data to the Clob. - * - * @return a MonetClob instance - * @throws SQLFeatureNotSupportedException the JDBC driver does - * not support MonetClob objects that can be filled in - * @since 1.6 - */ - @Override - public Clob createClob() throws SQLException { - return new MonetClob(""); - } - - /** - * Constructs an object that implements the Blob interface. The - * object returned initially contains no data. The setBinaryStream - * and setBytes methods of the Blob interface may be used to add - * data to the Blob. - * - * @return a MonetBlob instance - * @throws SQLFeatureNotSupportedException the JDBC driver does - * not support MonetBlob objects that can be filled in - */ - @Override - public Blob createBlob() throws SQLException { - throw new SQLFeatureNotSupportedException("createBlob() not supported", "0A000"); - } - - /** - * Constructs an object that implements the NClob interface. The - * object returned initially contains no data. The setAsciiStream, - * setCharacterStream and setString methods of the NClob interface - * may be used to add data to the NClob. - * - * @return an NClob instance - * @throws SQLFeatureNotSupportedException the JDBC driver does - * not support MonetClob objects that can be filled in - */ - @Override - public NClob createNClob() throws SQLException { - throw new SQLFeatureNotSupportedException("createNClob() not supported", "0A000"); - } - - /** - * Factory method for creating Struct objects. - * - * @param typeName the SQL type name of the SQL structured type that - * this Struct object maps to. The typeName is the name of a - * user-defined type that has been defined for this database. - * It is the value returned by Struct.getSQLTypeName. - * @param attributes the attributes that populate the returned - * object - * @return a Struct object that maps to the given SQL type and is - * populated with the given attributes - * @throws SQLException if a database error occurs, the typeName - * is null or this method is called on a closed connection - * @throws SQLFeatureNotSupportedException the JDBC driver does - * not support this data type - */ - @Override - public Struct createStruct(String typeName, Object[] attributes) throws SQLException { - throw new SQLFeatureNotSupportedException("createStruct() not supported", "0A000"); - } - - /** - * Constructs an object that implements the SQLXML interface. The - * object returned initially contains no data. The - * createXmlStreamWriter object and setString method of the SQLXML - * interface may be used to add data to the SQLXML object. - * - * @return An object that implements the SQLXML interface - * @throws SQLFeatureNotSupportedException the JDBC driver does - * not support this data type - */ - @Override - public SQLXML createSQLXML() throws SQLException { - throw new SQLFeatureNotSupportedException("createSQLXML() not supported", "0A000"); - } - - /** * Retrieves the current auto-commit mode for this Connection * object. * @@ -449,31 +327,6 @@ public abstract class MonetConnection ex } /** - * Not implemented by MonetDB's JDBC driver. - * - * @param name The name of the client info property to retrieve - * @return The value of the client info property specified - */ - @Override - public String getClientInfo(String name) { - // This method will also return null if the specified client - // info property name is not supported by the driver. - return null; - } - - /** - * Not implemented by MonetDB's JDBC driver. - * - * @return A Properties object that contains the name and current - * value of each of the client info properties supported by - * the driver. - */ - @Override - public Properties getClientInfo() { - return new Properties(); - } - - /** * Retrieves the current holdability of ResultSet objects created * using this Connection object. * @@ -500,7 +353,7 @@ public abstract class MonetConnection ex */ @Override public DatabaseMetaData getMetaData() throws SQLException { - if (this.currentMonetDBLanguage != MonetDBLanguage.LANG_SQL) { + if (this.language != MonetDBLanguage.LANG_SQL) { throw new SQLException("This method is only supported in SQL mode", "M0M04"); } return new MonetDatabaseMetaData(this); @@ -590,49 +443,6 @@ public abstract class MonetConnection ex return false; } - /** - * Returns true if the connection has not been closed and is still - * valid. The driver shall submit a query on the connection or use - * some other mechanism that positively verifies the connection is - * still valid when this method is called. - * - * The query submitted by the driver to validate the connection - * shall be executed in the context of the current transaction. - * - * @param timeout The time in seconds to wait for the database - * operation used to validate the connection to complete. If - * the timeout period expires before the operation completes, - * this method returns false. A value of 0 indicates a - * timeout is not applied to the database operation. - * @return true if the connection is valid, false otherwise - * @throws SQLException if the value supplied for timeout is less - * than 0 - */ - @Override - public boolean isValid(int timeout) throws SQLException { - if (timeout < 0) - throw new SQLException("timeout is less than 0", "M1M05"); - if (closed) - return false; - // ping db using select 1; - Statement stmt = null; - try { - stmt = createStatement(); - // the timeout parameter is ignored here, since - // MonetStatement.setQueryTimeout(timeout) is not supported. - stmt.executeQuery("SELECT 1"); - stmt.close(); - return true; - } catch (Exception e) { - if (stmt != null) { - try { - stmt.close(); - } catch (Exception e2) {} - } - } - return false; - } - @Override public String nativeSQL(String sql) {return sql;} @@ -916,31 +726,6 @@ public abstract class MonetConnection ex } /** - * Not implemented by MonetDB's JDBC driver. - * - * @param name The name of the client info property to set - * @param value The value to set the client info property to. If the - * value is null, the current value of the specified property - * is cleared. - */ - @Override - public void setClientInfo(String name, String value) { - addWarning("clientInfo: " + name + "is not a recognised property", "01M07"); - } - - /** - * Not implemented by MonetDB's JDBC driver. - * - * @param props The list of client info properties to set - */ - @Override - public void setClientInfo(Properties props) { - for (Map.Entry<Object, Object> entry : props.entrySet()) { - setClientInfo(entry.getKey().toString(), entry.getValue().toString()); - } - } - - /** * Changes the default holdability of ResultSet objects created using this * Connection object to the given holdability. The default holdability of * ResultSet objects can be be determined by invoking DatabaseMetaData.getResultSetHoldability(). @@ -1046,7 +831,8 @@ public abstract class MonetConnection ex @Override public void setTransactionIsolation(int level) { if (level != TRANSACTION_SERIALIZABLE) { - addWarning("MonetDB only supports fully serializable " + "transactions, continuing with transaction level " + + addWarning("MonetDB only supports fully serializable " + + "transactions, continuing with transaction level " + "raised to TRANSACTION_SERIALIZABLE", "01M09"); } } @@ -1065,8 +851,7 @@ public abstract class MonetConnection ex } /** - * Returns a string identifying this Connection to the MonetDB - * server. + * Returns a string identifying this Connection to the MonetDB server. * * @return a String representing this Object */ @@ -1075,7 +860,325 @@ public abstract class MonetConnection ex return "MonetDB Connection (" + this.getJDBCURL() + ") " + (closed ? "connected" : "disconnected"); } - //== 1.7 methods (JDBC 4.1) + //== Java 1.6 methods (JDBC 4.0) + + /** + * Factory method for creating Array objects. + * + * Note: When createArrayOf is used to create an array object that + * maps to a primitive data type, then it is implementation-defined + * whether the Array object is an array of that primitive data type + * or an array of Object. + * + * Note: The JDBC driver is responsible for mapping the elements + * Object array to the default JDBC SQL type defined in + * java.sql.Types for the given class of Object. The default mapping + * is specified in Appendix B of the JDBC specification. If the + * resulting JDBC type is not the appropriate type for the given + * typeName then it is implementation defined whether an + * SQLException is thrown or the driver supports the resulting conversion. + * + * @param typeName the SQL name of the type the elements of the + * array map to. The typeName is a database-specific name + * which may be the name of a built-in type, a user-defined + * type or a standard SQL type supported by this database. + * This is the value returned by Array.getBaseTypeName + * @return an Array object whose elements map to the specified SQL type + * @throws SQLException if a database error occurs, the JDBC type + * is not appropriate for the typeName and the conversion is + * not supported, the typeName is null or this method is + * called on a closed connection + * @throws SQLFeatureNotSupportedException the JDBC driver does + * not support this data type + * @since 1.6 + */ + @Override + public java.sql.Array createArrayOf(String typeName, Object[] elements) + throws SQLException + { + throw new SQLFeatureNotSupportedException("createArrayOf() not supported", "0A000"); + } + + /** + * Constructs an object that implements the Clob interface. The + * object returned initially contains no data. The setAsciiStream, + * setCharacterStream and setString methods of the Clob interface + * may be used to add data to the Clob. + * + * @return a MonetClob instance + * @throws SQLFeatureNotSupportedException the JDBC driver does + * not support MonetClob objects that can be filled in + * @since 1.6 + */ + @Override + public java.sql.Clob createClob() throws SQLException { + return new MonetClob(""); + } + + /** + * Constructs an object that implements the Blob interface. The + * object returned initially contains no data. The setBinaryStream + * and setBytes methods of the Blob interface may be used to add + * data to the Blob. + * + * @return a MonetBlob instance + * @throws SQLFeatureNotSupportedException the JDBC driver does + * not support MonetBlob objects that can be filled in + * @since 1.6 + */ + @Override + public java.sql.Blob createBlob() throws SQLException { + byte[] buf = new byte[1]; + return new MonetBlob(buf); + } + + /** + * Constructs an object that implements the NClob interface. The + * object returned initially contains no data. The setAsciiStream, + * setCharacterStream and setString methods of the NClob interface + * may be used to add data to the NClob. + * + * @return an NClob instance + * @throws SQLFeatureNotSupportedException the JDBC driver does + * not support MonetNClob objects that can be filled in + * @since 1.6 + */ + @Override + public java.sql.NClob createNClob() throws SQLException { + throw new SQLFeatureNotSupportedException("createNClob() not supported", "0A000"); + } + + /** + * Factory method for creating Struct objects. + * + * @param typeName the SQL type name of the SQL structured type that + * this Struct object maps to. The typeName is the name of a + * user-defined type that has been defined for this database. + * It is the value returned by Struct.getSQLTypeName. + * @param attributes the attributes that populate the returned object + * @return a Struct object that maps to the given SQL type and is + * populated with the given attributes + * @throws SQLException if a database error occurs, the typeName + * is null or this method is called on a closed connection + * @throws SQLFeatureNotSupportedException the JDBC driver does + * not support this data type + * @since 1.6 + */ + @Override + public java.sql.Struct createStruct(String typeName, Object[] attributes) + throws SQLException + { + throw new SQLFeatureNotSupportedException("createStruct() not supported", "0A000"); + } + + /** + * Constructs an object that implements the SQLXML interface. The + * object returned initially contains no data. The + * createXmlStreamWriter object and setString method of the SQLXML + * interface may be used to add data to the SQLXML object. + * + * @return An object that implements the SQLXML interface + * @throws SQLFeatureNotSupportedException the JDBC driver does + * not support this data type + * @since 1.6 + */ + @Override + public java.sql.SQLXML createSQLXML() throws SQLException { + throw new SQLFeatureNotSupportedException("createSQLXML() not supported", "0A000"); + } + + /** + * Returns true if the connection has not been closed and is still + * valid. The driver shall submit a query on the connection or use + * some other mechanism that positively verifies the connection is + * still valid when this method is called. + * + * The query submitted by the driver to validate the connection + * shall be executed in the context of the current transaction. + * + * @param timeout The time in seconds to wait for the database + * operation used to validate the connection to complete. If + * the timeout period expires before the operation completes, + * this method returns false. A value of 0 indicates a + * timeout is not applied to the database operation. + * @return true if the connection is valid, false otherwise + * @throws SQLException if the value supplied for timeout is less than 0 + * @since 1.6 + */ + @Override + public boolean isValid(int timeout) throws SQLException { + if (timeout < 0) + throw new SQLException("timeout is less than 0", "M1M05"); + if (closed) + return false; + + // ping db using query: select 1; + Statement stmt = null; + ResultSet rs = null; + try { + stmt = createStatement(); + stmt.setQueryTimeout(timeout); + rs = stmt.executeQuery("SELECT 1"); + rs.close(); + rs = null; + stmt.close(); + return true; + } catch (Exception e) { + if (rs != null) { + try { + rs.close(); + } catch (Exception e2) {} + } + if (stmt != null) { + try { + stmt.close(); + } catch (Exception e2) {} + } + } + return false; + } + + /** + * Returns the value of the client info property specified by name. + * This method may return null if the specified client info property + * has not been set and does not have a default value. + * This method will also return null if the specified client info + * property name is not supported by the driver. + * Applications may use the DatabaseMetaData.getClientInfoProperties method + * to determine the client info properties supported by the driver. + * + * @param name - The name of the client info property to retrieve + * @return The value of the client info property specified or null + * @throws SQLException - if the database server returns an error + * when fetching the client info value from the database + * or this method is called on a closed connection + * @since 1.6 + */ + @Override + public String getClientInfo(String name) throws SQLException { + if (name == null || name.isEmpty()) + return null; + return conn_props.getProperty(name); + } + + /** + * Returns a list containing the name and current value of each client info + * property supported by the driver. The value of a client info property may + * be null if the property has not been set and does not have a default value. + * + * @return A Properties object that contains the name and current value + * of each of the client info properties supported by the driver. + * @throws SQLException - if the database server returns an error + * when fetching the client info value from the database + * or this method is called on a closed connection + * @since 1.6 + */ + @Override + public Properties getClientInfo() throws SQLException { + // return a clone of the connection properties object + return new Properties(conn_props); + } + + + /** + * Sets the value of the client info property specified by name to the value specified by value. + * Applications may use the DatabaseMetaData.getClientInfoProperties method to determine + * the client info properties supported by the driver and the maximum length that may be specified + * for each property. + * + * The driver stores the value specified in a suitable location in the database. For example + * in a special register, session parameter, or system table column. For efficiency the driver + * may defer setting the value in the database until the next time a statement is executed + * or prepared. Other than storing the client information in the appropriate place in the + * database, these methods shall not alter the behavior of the connection in anyway. + * The values supplied to these methods are used for accounting, diagnostics and debugging purposes only. + * + * The driver shall generate a warning if the client info name specified is not recognized by the driver. + * + * If the value specified to this method is greater than the maximum length for the property + * the driver may either truncate the value and generate a warning or generate a SQLClientInfoException. + * If the driver generates a SQLClientInfoException, the value specified was not set on the connection. + * + * The following are standard client info properties. Drivers are not required to support these + * properties however if the driver supports a client info property that can be described by one + * of the standard properties, the standard property name should be used. + * + * ApplicationName - The name of the application currently utilizing the connection + * ClientUser - The name of the user that the application using the connection is performing work for. + * This may not be the same as the user name that was used in establishing the connection. + * ClientHostname - The hostname of the computer the application using the connection is running on. + * + * @param name - The name of the client info property to set + * @param value - The value to set the client info property to. If the + * value is null, the current value of the specified property is cleared. + * @throws SQLClientInfoException - if the database server returns an error + * while setting the clientInfo values on the database server + * or this method is called on a closed connection + * @since 1.6 + */ + @Override + public void setClientInfo(String name, String value) throws java.sql.SQLClientInfoException { + if (name == null || name.isEmpty()) { + addWarning("setClientInfo: missing property name", "01M07"); + return; + } + // If the value is null, the current value of the specified property is cleared. + if (value == null) { + if (conn_props.containsKey(name)) + conn_props.remove(name); + return; + } + // only set value for supported property names + if (name.equals("host") || + name.equals("port") || + name.equals("user") || + name.equals("password") || + name.equals("database") || + name.equals("language") || + name.equals("so_timeout") || + name.equals("debug") || + name.equals("hash") || + name.equals("treat_blob_as_binary")) { + conn_props.setProperty(name, value); + } else { + addWarning("setClientInfo: " + name + "is not a recognised property", "01M07"); + } + } + + /** + * Sets the value of the connection's client info properties. + * The Properties object contains the names and values of the client info + * properties to be set. The set of client info properties contained in the + * properties list replaces the current set of client info properties on the connection. + * If a property that is currently set on the connection is not present in the + * properties list, that property is cleared. Specifying an empty properties list + * will clear all of the properties on the connection. + * See setClientInfo (String, String) for more information. + * + * If an error occurs in setting any of the client info properties, a + * SQLClientInfoException is thrown. The SQLClientInfoException contains information + * indicating which client info properties were not set. The state of the client + * information is unknown because some databases do not allow multiple client info + * properties to be set atomically. For those databases, one or more properties may + * have been set before the error occurred. + * + * @param props - The list of client info properties to set + * @throws SQLClientInfoException - if the database server returns an error + * while setting the clientInfo values on the database server + * or this method is called on a closed connection + * @since 1.6 + */ + @Override + public void setClientInfo(Properties props) throws java.sql.SQLClientInfoException { + if (props != null) { + for (Map.Entry<Object, Object> entry : props.entrySet()) { + setClientInfo(entry.getKey().toString(), + entry.getValue().toString()); + } + } + } + + //== Java 1.7 methods (JDBC 4.1) /** * Sets the given schema name to access. @@ -1083,14 +1186,20 @@ public abstract class MonetConnection ex * @param schema the name of a schema in which to work * @throws SQLException if a database access error occurs or this * method is called on a closed connection + * @since 1.7 */ @Override public void setSchema(String schema) throws SQLException { - if (closed) { + if (closed) throw new SQLException("Cannot call on closed Connection", "M1M20"); - } - if (schema != null) { - createStatement().execute("SET SCHEMA \"" + schema + "\""); + if (schema == null) + throw new SQLException("Missing schema name", "M1M05"); + + Statement st = createStatement(); + try { + st.execute("SET SCHEMA \"" + schema + "\""); + } finally { + st.close(); } } @@ -1178,11 +1287,7 @@ public abstract class MonetConnection ex throw new SQLException("executor is null", "M1M05"); if (millis < 0) throw new SQLException("milliseconds is less than zero", "M1M05"); - try { - this.setSoTimeout(millis); - } catch (SocketException e) { - throw new SQLException(e.getMessage(), "08000"); - } + this.setSoTimeout(millis); } /** @@ -1200,11 +1305,7 @@ public abstract class MonetConnection ex if (closed) { throw new SQLException("Cannot call on closed Connection", "M1M20"); } - try { - return this.getSoTimeout(); - } catch (SocketException e) { - throw new SQLException(e.getMessage(), "08000"); - } + return this.getSoTimeout(); } //== end methods of interface Connection @@ -1228,11 +1329,10 @@ public abstract class MonetConnection ex public void sendIndependentCommand(String command) throws SQLException { synchronized (this) { try { - out.writeLine(server.getQueryTemplateHeader(0) + command + server.getQueryTemplateHeader(1)); + out.writeLine(language.getQueryTemplateIndex(0) + command + language.getQueryTemplateIndex(1)); String error = in.waitForPrompt(); if (error != null) - throw new SQLException(error.substring(6), - error.substring(0, 5)); + throw new SQLException(error.substring(6), error.substring(0, 5)); } catch (SocketTimeoutException e) { close(); // JDBC 4.1 semantics: abort() throw new SQLException("connection timed out", "08M33"); @@ -1255,11 +1355,10 @@ public abstract class MonetConnection ex // send X command synchronized (this) { try { - out.writeLine(server.getCommandTemplateHeader(0) + command + server.getCommandTemplateHeader(1)); + out.writeLine(language.getCommandTemplateIndex(0) + command + language.getCommandTemplateIndex(1)); String error = in.waitForPrompt(); if (error != null) - throw new SQLException(error.substring(6), - error.substring(0, 5)); + throw new SQLException(error.substring(6), error.substring(0, 5)); } catch (SocketTimeoutException e) { close(); // JDBC 4.1 semantics, abort() throw new SQLException("connection timed out", "08M33");
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetDatabaseMetaData.java +++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetDatabaseMetaData.java @@ -3800,10 +3800,11 @@ public class MonetDatabaseMetaData exten "SELECT 'user', 1024, '', 'user name to login to MonetDB server' UNION ALL " + "SELECT 'password', 128, '', 'password for user name to login to MonetDB server' UNION ALL " + "SELECT 'language', 16, 'sql', 'language (sql or mal) used to parse commands in MonetDB server' UNION ALL " + + "SELECT 'database', 1024, 'demo', 'name of database. It matches the dbfarm subdirectory name' UNION ALL " + "SELECT 'debug', 5, 'false', 'boolean flag true or false' UNION ALL " + "SELECT 'hash', 128, '', 'hash string' UNION ALL " + "SELECT 'treat_blob_as_binary', 5, 'false', 'boolean flag true or false' UNION ALL " + - "SELECT 'so_timeout', 10, '0', 'timeout of communication socket. 0 means no timeout is set' " + + "SELECT 'so_timeout', 10, '0', 'timeout (in milliseconds) of communication socket. 0 means no timeout is set' " + "ORDER BY \"NAME\""; return executeMetaDataQuery(query);
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetPreparedStatement.java +++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetPreparedStatement.java @@ -280,7 +280,7 @@ public class MonetPreparedStatement * statement does not return a ResultSet object */ @Override - public ResultSet executeQuery() throws SQLException{ + public ResultSet executeQuery() throws SQLException { if (!execute()) throw new SQLException("Query did not produce a result set", "M1M19"); @@ -949,7 +949,7 @@ public class MonetPreparedStatement */ @Override public void setArray(int i, Array x) throws SQLException { - throw new SQLException("Operation setArray(int i, Array x) currently not supported!", "0A000"); + throw newSQLFeatureNotSupportedException("setArray"); } /** @@ -1035,31 +1035,29 @@ public class MonetPreparedStatement * @throws SQLException if a database access error occurs */ @Override - public void setBigDecimal(int idx, BigDecimal x) - throws SQLException - { - // get array position - int i = getParamIdx(idx); + public void setBigDecimal(int idx, BigDecimal x) throws SQLException { + // get array position + int i = getParamIdx(idx); - // round to the scale of the DB: - x = x.setScale(scale[i], RoundingMode.HALF_UP); + // round to the scale of the DB: + x = x.setScale(scale[i], RoundingMode.HALF_UP); + + // if precision is now greater than that of the db, throw an error: + if (x.precision() > digits[i]) { + throw new SQLDataException("DECIMAL value exceeds allowed digits/scale: " + x.toPlainString() + " (" + digits[i] + "/" + scale[i] + ")", "22003"); + } - // if precision is now greater than that of the db, throw an error: - if (x.precision() > digits[i]) { - throw new SQLDataException("DECIMAL value exceeds allowed digits/scale: " + x.toPlainString() + " (" + digits[i] + "/" + scale[i] + ")", "22003"); - } - - // MonetDB doesn't like leading 0's, since it counts them as part of - // the precision, so let's strip them off. (But be careful not to do - // this to the exact number "0".) Also strip off trailing - // numbers that are inherent to the double representation. - String xStr = x.toPlainString(); - int dot = xStr.indexOf('.'); - if (dot >= 0) - xStr = xStr.substring(0, Math.min(xStr.length(), dot + 1 + scale[i])); - while (xStr.startsWith("0") && xStr.length() > 1) - xStr = xStr.substring(1); - setValue(idx, xStr); + // MonetDB doesn't like leading 0's, since it counts them as part of + // the precision, so let's strip them off. (But be careful not to do + // this to the exact number "0".) Also strip off trailing + // numbers that are inherent to the double representation. + String xStr = x.toPlainString(); + int dot = xStr.indexOf('.'); + if (dot >= 0) + xStr = xStr.substring(0, Math.min(xStr.length(), dot + 1 + scale[i])); + while (xStr.startsWith("0") && xStr.length() > 1) + xStr = xStr.substring(1); + setValue(idx, xStr); } /**
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetResultSet.java +++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetResultSet.java @@ -10,6 +10,7 @@ package nl.cwi.monetdb.jdbc; import nl.cwi.monetdb.mcl.parser.MCLParseException; import nl.cwi.monetdb.mcl.parser.TupleLineParser; +import nl.cwi.monetdb.responses.ResultSetResponse; import java.io.ByteArrayInputStream; import java.io.InputStream; @@ -76,7 +77,7 @@ public class MonetResultSet extends Mone // a blank final is immutable once assigned in the constructor /** A Header to retrieve lines from */ - private final MonetConnection.ResultSetResponse header; + private final ResultSetResponse header; /** The names of the columns in this ResultSet */ private final String[] columns; /** The MonetDB types of the columns in this ResultSet */ @@ -107,11 +108,7 @@ public class MonetResultSet extends Mone * @param header a header containing the query, resultset type, etc. * @throws SQLException is a protocol error occurs */ - MonetResultSet( - Statement statement, - MonetConnection.ResultSetResponse header) - throws SQLException - { + MonetResultSet(Statement statement, ResultSetResponse header) throws SQLException { if (statement == null) { throw new IllegalArgumentException("Statement may not be null!"); } @@ -151,13 +148,7 @@ public class MonetResultSet extends Mone * @param results the number of rows in the ResultSet * @throws IllegalArgumentException if communicating with monet failed */ - MonetResultSet( - Statement statement, - String[] columns, - String[] types, - int results - ) throws IllegalArgumentException - { + MonetResultSet(Statement statement, String[] columns, String[] types, int results) throws IllegalArgumentException { if (statement == null) { throw new IllegalArgumentException("Statement may not be null!"); } @@ -1792,7 +1783,7 @@ public class MonetResultSet extends Mone * types. In the JDBC 2.0 API, the behavior of method getObject is extended * to materialize data of SQL user-defined types. When a column contains a * structured or distinct value, the behavior of this method is as if it - * were a call to: getObject(columnIndex, this.getStatement().getConnection().getTypeMap()). + * were a call to: getObject(columnIndex, this.getStatement().getInternalConnection().getTypeMap()). * * @param columnIndex the first column is 1, the second is 2, ... * @return a java.lang.Object holding the column value or null @@ -1964,7 +1955,7 @@ public class MonetResultSet extends Mone * If Connection.getTypeMap does not throw a SQLFeatureNotSupportedException, then * when a column contains a structured or distinct value, the behavior of this * method is as if it were a call to: getObject(columnIndex, - * this.getStatement().getConnection().getTypeMap()). + * this.getStatement().getInternalConnection().getTypeMap()). * If Connection.getTypeMap does throw a SQLFeatureNotSupportedException, then * structured values are not supported, and distinct values are mapped to the * default Java class as determined by the underlying SQL type of the DISTINCT type.
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetStatement.java +++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetStatement.java @@ -8,6 +8,8 @@ package nl.cwi.monetdb.jdbc; +import nl.cwi.monetdb.responses.*; + import java.sql.BatchUpdateException; import java.sql.Connection; import java.sql.Statement; @@ -39,7 +41,7 @@ import java.util.concurrent.locks.Reentr * which relies on server side auto commit.<br /> * Multi-result queries are supported using the getMoreResults() method. * - * @author Fabian Groffen + * @author Martin van Dinther * @version 0.7 */ public class MonetStatement extends MonetWrapper implements Statement { @@ -49,9 +51,9 @@ public class MonetStatement extends Mone /** The parental Connection object */ private MonetConnection connection; /** The last ResponseList object this Statement produced */ - private MonetConnection.ResponseList lastResponseList; + private ResponseList lastResponseList; /** The last Response that this object uses */ - MonetConnection.Response header; + IResponse header; /** The warnings this Statement object generated */ private SQLWarning warnings; /** Whether this Statement object is closed or not */ @@ -86,13 +88,8 @@ public class MonetStatement extends Mone * @throws SQLException if an error occurs during login * @throws IllegalArgumentException is one of the arguments is null or empty */ - MonetStatement( - MonetConnection connection, - int resultSetType, - int resultSetConcurrency, - int resultSetHoldability) - throws SQLException, IllegalArgumentException - { + MonetStatement(MonetConnection connection, int resultSetType, int resultSetConcurrency, int resultSetHoldability) + throws SQLException, IllegalArgumentException { if (connection == null) throw new IllegalArgumentException("No Connection given!"); @@ -246,14 +243,7 @@ public class MonetStatement extends Mone } } - private boolean internalBatch( - String batch, - int[] counts, - int offset, - int max, - BatchUpdateException e) - throws BatchUpdateException - { + private boolean internalBatch(String batch, int[] counts, int offset, int max, BatchUpdateException e) throws BatchUpdateException { try { boolean type = internalExecute(batch); int count = -1; @@ -322,7 +312,9 @@ public class MonetStatement extends Mone @Override public void close() { // close previous ResultSet, if not closed already - if (lastResponseList != null) lastResponseList.close(); + if (lastResponseList != null) { + lastResponseList.close(); + } closed = true; } @@ -381,15 +373,11 @@ public class MonetStatement extends Mone * Statement.NO_GENERATED_KEYS. */ @Override - public boolean execute(String sql, int autoGeneratedKeys) - throws SQLException - { - if (autoGeneratedKeys != Statement.RETURN_GENERATED_KEYS && - autoGeneratedKeys != Statement.NO_GENERATED_KEYS) + public boolean execute(String sql, 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 ;) */ + } + /* MonetDB has no way to disable this, so just do the normal thing ;) */ return internalExecute(sql); } @@ -430,10 +418,8 @@ public class MonetStatement extends Mone * valid column indexes */ @Override - public boolean execute(String sql, int[] columnIndexes) - throws SQLException - { - addWarning("execute: generated keys for fixed set of columns not supported", "01M18"); + public boolean execute(String sql, int[] columnIndexes) throws SQLException { + this.addWarning("execute: generated keys for fixed set of columns not supported", "01M18"); return execute(sql, Statement.RETURN_GENERATED_KEYS); } @@ -502,12 +488,7 @@ public class MonetStatement extends Mone } // create a container for the result - lastResponseList = connection.new ResponseList( - fetchSize, - maxRows, - resultSetType, - resultSetConcurrency - ); + lastResponseList = new ResponseList(fetchSize, maxRows, resultSetType, resultSetConcurrency); // fill the header list by processing the query lastResponseList.processQuery(sql); @@ -611,9 +592,7 @@ public class MonetStatement extends Mone * whose elements are valid column indexes */ @Override - public int executeUpdate(String sql, int[] columnIndexes) - throws SQLException - { + public int executeUpdate(String sql, int[] columnIndexes) throws SQLException { addWarning("executeUpdate: generated keys for fixed set of columns not supported", "01M18"); return executeUpdate(sql, Statement.RETURN_GENERATED_KEYS); } @@ -642,9 +621,7 @@ public class MonetStatement extends Mone * whose elements are valid column names */ @Override - public int executeUpdate(String sql, String[] columnNames) - throws SQLException - { + public int executeUpdate(String sql, String[] columnNames) throws SQLException { addWarning("executeUpdate: generated keys for fixed set of columns not supported", "01M18"); return executeUpdate(sql, Statement.RETURN_GENERATED_KEYS); } @@ -710,8 +687,8 @@ public class MonetStatement extends Mone * frameworks such as spring expect this. */ types[0] = "BIGINT"; - if (header instanceof MonetConnection.UpdateResponse) { - String lastid = ((MonetConnection.UpdateResponse)header).lastid; + if (header instanceof UpdateResponse) { + String lastid = ((UpdateResponse)header).lastid; if (lastid.equals("-1")) { results = new String[0][1]; } else { @@ -742,12 +719,9 @@ public class MonetStatement extends Mone * * @return the current column size limit for columns storing * character and binary values; zero means there is no limit - * @throws SQLException if a database access error occurs */ @Override - public int getMaxFieldSize() - throws SQLException - { + public int getMaxFieldSize() { return 0; } @@ -814,7 +788,7 @@ public class MonetStatement extends Mone // we default to keep current result, which requires no action header = lastResponseList.getNextResponse(); - return header instanceof MonetConnection.ResultSetResponse; + return header instanceof ResultSetResponse; } /** @@ -861,9 +835,8 @@ public class MonetStatement extends Mone */ @Override public ResultSet getResultSet() throws SQLException{ - return (header instanceof MonetConnection.ResultSetResponse) - ? new MonetResultSet(this, - (MonetConnection.ResultSetResponse)header) + return (header instanceof ResultSetResponse) + ? new MonetResultSet(this, (ResultSetResponse)header) : null; } @@ -916,10 +889,10 @@ public class MonetStatement extends Mone @Override public int getUpdateCount() throws SQLException { int ret = -1; - if (header instanceof MonetConnection.UpdateResponse) { - ret = ((MonetConnection.UpdateResponse)header).count; - } else if (header instanceof MonetConnection.SchemaResponse) { - ret = ((MonetConnection.SchemaResponse)header).state; + if (header instanceof UpdateResponse) { + ret = ((UpdateResponse)header).count; + } else if (header instanceof SchemaResponse) { + ret = ((SchemaResponse)header).state; } return ret; @@ -942,9 +915,9 @@ public class MonetStatement extends Mone */ @Override public SQLWarning getWarnings() throws SQLException { - if (closed) + if (closed) { throw new SQLException("Cannot call on closed Statement", "M1M20"); - + } // if there are no warnings, this will be null, which fits with the // specification. return warnings; @@ -998,8 +971,9 @@ public class MonetStatement extends Mone */ @Override public void setEscapeProcessing(boolean enable) throws SQLException { - if (enable) + if (enable) { addWarning("setEscapeProcessing: JDBC escape syntax is not supported by this driver", "01M22"); + } } /** @@ -1018,10 +992,7 @@ public class MonetStatement extends Mone */ @Override public void setFetchDirection(int direction) throws SQLException { - if (direction == ResultSet.FETCH_FORWARD || - direction == ResultSet.FETCH_REVERSE || - direction == ResultSet.FETCH_UNKNOWN) - { + if (direction == ResultSet.FETCH_FORWARD || direction == ResultSet.FETCH_REVERSE || direction == ResultSet.FETCH_UNKNOWN) { fetchDirection = direction; } else { throw new SQLException("Illegal direction: " + direction, "M1M05"); @@ -1066,10 +1037,12 @@ public class MonetStatement extends Mone */ @Override public void setMaxFieldSize(int max) throws SQLException { - if (max < 0) + if (max < 0) { throw new SQLException("Illegal max value: " + max, "M1M05"); - if (max > 0) + } + if (max > 0) { addWarning("setMaxFieldSize: field size limitation not supported", "01M23"); + } } /** @@ -1082,8 +1055,9 @@ public class MonetStatement extends Mone */ @Override public void setMaxRows(int max) throws SQLException { - if (max < 0) + if (max < 0) { throw new SQLException("Illegal max value: " + max, "M1M05"); + } maxRows = max; } @@ -1099,9 +1073,9 @@ public class MonetStatement extends Mone */ @Override public void setQueryTimeout(int seconds) throws SQLException { - if (seconds < 0) + if (seconds < 0) { throw new SQLException("Illegal timeout value: " + seconds, "M1M05"); - + } Statement st = null; try { st = connection.createStatement(); @@ -1175,8 +1149,9 @@ public class MonetStatement extends Mone */ @Override public void closeOnCompletion() throws SQLException { - if (closed) + if (closed) { throw new SQLException("Cannot call on closed Statement", "M1M20"); + } closeOnCompletion = true; } @@ -1190,8 +1165,9 @@ public class MonetStatement extends Mone */ @Override public boolean isCloseOnCompletion() throws SQLException { - if (closed) + if (closed) { throw new SQLException("Cannot call on closed Statement", "M1M20"); + } return closeOnCompletion; } @@ -1244,14 +1220,8 @@ final class MonetVirtualResultSet extend private String results[][]; private boolean closed; - MonetVirtualResultSet( - Statement statement, - String[] columns, - String[] types, - String[][] results - ) throws IllegalArgumentException { + MonetVirtualResultSet(Statement statement, String[] columns, String[] types, String[][] results) throws IllegalArgumentException { super(statement, columns, types, results.length); - this.results = results; closed = false; } @@ -1269,9 +1239,9 @@ final class MonetVirtualResultSet extend */ @Override public boolean absolute(int row) throws SQLException { - if (closed) + if (closed) { throw new SQLException("ResultSet is closed!", "M1M20"); - + } // first calculate what the JDBC row is if (row < 0) { // calculate the negatives...
rename from src/main/java/nl/cwi/monetdb/mcl/connection/EmbeddedMonetDB.java rename to src/main/java/nl/cwi/monetdb/mcl/connection/EmbeddedConnection.java --- a/src/main/java/nl/cwi/monetdb/mcl/connection/EmbeddedMonetDB.java +++ b/src/main/java/nl/cwi/monetdb/mcl/connection/EmbeddedConnection.java @@ -1,5 +1,6 @@ package nl.cwi.monetdb.mcl.connection; +import nl.cwi.monetdb.embedded.env.MonetDBEmbeddedConnection; import nl.cwi.monetdb.embedded.env.MonetDBEmbeddedDatabase; import nl.cwi.monetdb.embedded.env.MonetDBEmbeddedException; import nl.cwi.monetdb.jdbc.MonetConnection; @@ -7,21 +8,29 @@ import nl.cwi.monetdb.mcl.io.*; import nl.cwi.monetdb.mcl.parser.MCLParseException; import java.io.*; -import java.net.SocketException; import java.util.List; +import java.util.Properties; /** * Created by ferreira on 11/23/16. */ -public final class EmbeddedMonetDB extends MonetConnection { +public final class EmbeddedConnection extends MonetConnection { private final String directory; - private InternalConnection connection; + private JDBCEmbeddedConnection internalConnection; + + public EmbeddedConnection(Properties props, String database, String hash, String language, boolean blobIsBinary, boolean isDebugging, String directory) throws IOException { + super(props, database, hash, language, blobIsBinary, isDebugging); + this.directory = directory; + } - public EmbeddedMonetDB(String database, String hash, String language, boolean blobIsBinary, boolean isDebugging, String directory) throws IOException { - super(database, hash, language, blobIsBinary, isDebugging); - this.directory = directory; + public String getDirectory() { + return directory; + } + + public MonetDBEmbeddedConnection getAsMonetDBEmbeddedConnection() { + return internalConnection; } @Override @@ -32,7 +41,7 @@ public final class EmbeddedMonetDB exten } else { MonetDBEmbeddedDatabase.StartDatabase(this.directory, true, false); } - this.connection = MonetDBEmbeddedDatabase.AddJDBCEmbeddedConnection(); + this.internalConnection = MonetDBEmbeddedDatabase.CreateJDBCEmbeddedConnection(); } catch (MonetDBEmbeddedException ex) { throw new MCLException(ex); } @@ -50,13 +59,14 @@ public final class EmbeddedMonetDB exten } @Override - public int getSoTimeout() throws SocketException { - throw new SocketException("Cannot get a timeout on a embedded connection!"); + public int getSoTimeout() { + this.addWarning("Cannot get a timeout on a embedded connection!", "M1M05"); + return -1; } @Override - public void setSoTimeout(int s) throws SocketException { - throw new SocketException("Cannot set a timeout on a embedded connection!"); + public void setSoTimeout(int s) { + this.addWarning("Cannot set a timeout on a embedded connection!", "M1M05"); } @Override
--- a/src/main/java/nl/cwi/monetdb/mcl/connection/MapiConnection.java +++ b/src/main/java/nl/cwi/monetdb/mcl/connection/MapiConnection.java @@ -80,12 +80,32 @@ public class MapiConnection extends Mone protected OldMapiProtocol protocol; - public MapiConnection(String database, String hash, String language, boolean blobIsBinary, boolean isDebugging, String hostname, int port) throws IOException { - super(database, hash, language, blobIsBinary, isDebugging); + public MapiConnection(Properties props, String database, String hash, String language, boolean blobIsBinary, boolean isDebugging, String hostname, int port) throws IOException { + super(props, database, hash, language, blobIsBinary, isDebugging); this.hostname = hostname; this.port = port; } + public String getHostname() { + return hostname; + } + + public int getPort() { + return port; + } + + public boolean isFollowRedirects() { + return followRedirects; + } + + public int getTtl() { + return ttl; + } + + public int setProtocolVersion() { + return version; + } + /** * Sets whether MCL redirections should be followed or not. If set * to false, an MCLException will be thrown when a redirect is @@ -130,13 +150,22 @@ public class MapiConnection extends Mone } @Override - public int getSoTimeout() throws SocketException { - return protocol.getConnection().getSoTimeout(); + public int getSoTimeout() { + try { + return protocol.getConnection().getSoTimeout(); + } catch (SocketException e) { + this.addWarning("The socket timeout could not be get", "M1M05"); + } + return -1; } @Override - public void setSoTimeout(int s) throws SocketException { - protocol.getConnection().setSoTimeout(s); + public void setSoTimeout(int s) { + try { + protocol.getConnection().setSoTimeout(s); + } catch (SocketException e) { + this.addWarning("The socket timeout could not be set", "M1M05"); + } } @Override @@ -147,7 +176,7 @@ public class MapiConnection extends Mone @Override public String getJDBCURL() { String language = ""; - if (this.getCurrentMonetDBLanguage() == MonetDBLanguage.LANG_MAL) + if (this.getLanguage() == MonetDBLanguage.LANG_MAL) language = "?language=mal"; return "jdbc:monetdb://" + this.hostname + ":" + this.port + "/" + this.database + language; } @@ -178,7 +207,7 @@ public class MapiConnection extends Mone this.protocol.getNextResponseHeader(); String test = this.getChallengeResponse(this.protocol.getEntireResponseLine(), user, pass, - this.currentMonetDBLanguage.getRepresentation(), this.database, this.hash); + this.language.getRepresentation(), this.database, this.hash); this.protocol.writeNextLine(test.getBytes()); List<String> redirects = new ArrayList<>(); @@ -243,7 +272,7 @@ public class MapiConnection extends Mone case "language": tmp = arg.substring(pos + 1); warns.add("redirect specifies use of different language: " + tmp); - this.currentMonetDBLanguage = MonetDBLanguage.GetLanguageFromString(tmp); + this.language = MonetDBLanguage.GetLanguageFromString(tmp); break; case "user": tmp = arg.substring(pos + 1); @@ -432,6 +461,10 @@ public class MapiConnection extends Mone response += username + ":" + pwhash + ":" + language; response += ":" + (database == null ? "" : database) + ":"; + this.conn_props.setProperty("hash", hashes); + this.conn_props.setProperty("language", language); + this.conn_props.setProperty("database", database); + return response; } }
--- a/src/main/java/nl/cwi/monetdb/mcl/connection/MonetDBConnectionFactory.java +++ b/src/main/java/nl/cwi/monetdb/mcl/connection/MonetDBConnectionFactory.java @@ -1,11 +1,11 @@ package nl.cwi.monetdb.mcl.connection; import nl.cwi.monetdb.jdbc.MonetConnection; +import nl.cwi.monetdb.jdbc.MonetDriver; import nl.cwi.monetdb.mcl.parser.MCLParseException; import java.io.File; import java.io.IOException; -import java.net.SocketException; import java.sql.SQLException; import java.util.Calendar; import java.util.List; @@ -38,7 +38,7 @@ public final class MonetDBConnectionFact if (directory == null || directory.trim().isEmpty()) throw new IllegalArgumentException("directory should not be null or empty"); try { - res = new EmbeddedMonetDB(database, hash, language, blobIsBinary, debug, directory); + res = new EmbeddedConnection(props, database, hash, language, blobIsBinary, debug, directory); } catch (IOException e) { throw new SQLException(e); } @@ -46,40 +46,60 @@ public final class MonetDBConnectionFact String hostname = props.getProperty("host"); if (hostname == null || hostname.trim().isEmpty()) throw new IllegalArgumentException("hostname should not be null or empty"); - int port = 0; - try { - port = Integer.parseInt(props.getProperty("port")); - } catch (NumberFormatException e) { - } - if (port <= 0) - throw new IllegalArgumentException("port should not be 0 or less"); if (username == null || username.trim().isEmpty()) throw new IllegalArgumentException("user should not be null or empty"); if (password == null || password.trim().isEmpty()) throw new IllegalArgumentException("password should not be null or empty"); + String portout = props.getProperty("portout"); + boolean negative1 = false; + boolean failedparse1 = false; + int port = 0; try { - res = new MapiConnection(database, hash, language, blobIsBinary, debug, hostname, port); - } catch (IOException e) { - throw new SQLException(e); + port = Integer.parseInt(props.getProperty("port")); + } catch (NumberFormatException e) { + failedparse1 = true; + props.setProperty("port", MonetDriver.getPORT()); } + if (port <= 0) { + negative1 = true; + port = Integer.parseInt(MonetDriver.getPORT()); + props.setProperty("port", MonetDriver.getPORT()); + } + String timout = props.getProperty("so_timeout", "0"); + boolean negative2 = false; + boolean failedparse2 = false; try { sockTimeout = Integer.parseInt(timout); } catch (NumberFormatException e) { - res.addWarning("Unable to parse socket timeout number from: " + timout, "M1M05"); + failedparse2 = true; + props.setProperty("so_timeout", "0"); } if (sockTimeout < 0) { - res.addWarning("Negative socket timeout not allowed. Value ignored", "M1M05"); + negative2 = true; sockTimeout = 0; + props.setProperty("so_timeout", "0"); } try { - res.setSoTimeout(sockTimeout); - } catch (SocketException e) { - res.addWarning("The socket timeout could not be set", "M1M05"); + res = new MapiConnection(props, database, hash, language, blobIsBinary, debug, hostname, port); + } catch (IOException e) { + throw new SQLException(e); + } + if(failedparse1) { + res.addWarning("Unable to parse port number from: " + portout, "M1M05"); } + if(negative1) { + res.addWarning("Negative port not allowed. Value ignored", "M1M05"); + } + if(failedparse2) { + res.addWarning("Unable to parse socket timeout number from: " + timout, "M1M05"); + } + if(negative2) { + res.addWarning("Negative socket timeout not allowed. Value ignored", "M1M05"); + } + res.setSoTimeout(sockTimeout); } - //initialize the debugging stuff if so if (debug) { try { @@ -100,25 +120,24 @@ public final class MonetDBConnectionFact try { List<String> warnings = res.connect(username, password); - for (String warning : warnings) { - res.addWarning(warning, "01M02"); + if(warnings != null) { + for (String warning : warnings) { + res.addWarning(warning, "01M02"); + } } - // apply NetworkTimeout value from legacy (pre 4.1) driver // so_timeout calls if(!isEmbedded) { res.setSoTimeout(sockTimeout); } - - - in = server.getReader(); - out = server.getWriter(); - - String error = in.waitForPrompt(); - if (error != null) - throw new SQLException((error.length() > 6) ? error.substring(6) : error, "08001"); } catch (IOException e) { - throw new SQLException("Unable to connect (" + hostname + ":" + port + "): " + e.getMessage(), "08006"); + if(!isEmbedded) { + MapiConnection con = (MapiConnection) res; + throw new SQLException("Unable to connect (" + con.getHostname() + ":" + con.getPort() + "): " + e.getMessage(), "08006"); + } else { + EmbeddedConnection em = (EmbeddedConnection) res; + throw new SQLException("Unable to connect the directory " + em.getDirectory() + ": " + e.getMessage(), "08006"); + } } catch (MCLParseException e) { throw new SQLException(e.getMessage(), "08001"); } catch (MCLException e) { @@ -130,7 +149,8 @@ public final class MonetDBConnectionFact throw sqle; } - if (res.getCurrentMonetDBLanguage() == MonetDBLanguage.LANG_SQL) { + //set the timezone + if (res.getLanguage() == MonetDBLanguage.LANG_SQL) { // enable auto commit res.setAutoCommit(true);
rename from src/main/java/nl/cwi/monetdb/responses/SendThread.java rename to src/main/java/nl/cwi/monetdb/mcl/connection/SendThread.java --- a/src/main/java/nl/cwi/monetdb/responses/SendThread.java +++ b/src/main/java/nl/cwi/monetdb/mcl/connection/SendThread.java @@ -1,4 +1,4 @@ -package nl.cwi.monetdb.responses; +package nl.cwi.monetdb.mcl.connection; import nl.cwi.monetdb.mcl.io.AbstractMCLWriter; @@ -20,19 +20,21 @@ import java.util.concurrent.locks.Reentr * high. */ public class SendThread extends Thread { - /** The state WAIT represents this thread to be waiting for - * something to do */ - private final static int WAIT = 0; - /** The state QUERY represents this thread to be executing a query */ - private final static int QUERY = 1; - /** The state SHUTDOWN is the final state that ends this thread */ - private final static int SHUTDOWN = -1; + + private enum SendThreadStatus { + /** The state WAIT represents this thread to be waiting for something to do */ + WAIT, + /** The state QUERY represents this thread to be executing a query */ + QUERY, + /** The state SHUTDOWN is the final state that ends this thread */ + SHUTDOWN + } private String[] templ; private String query; private AbstractMCLWriter out; private String error; - private int state = WAIT; + private SendThreadStatus state = SendThreadStatus.WAIT; private final Lock sendLock = new ReentrantLock(); private final Condition queryAvailable = sendLock.newCondition(); @@ -56,14 +58,14 @@ public class SendThread extends Thread { sendLock.lock(); try { while (true) { - while (state == WAIT) { + while (state == SendThreadStatus.WAIT) { try { queryAvailable.await(); } catch (InterruptedException e) { // woken up, eh? } } - if (state == SHUTDOWN) + if (state == SendThreadStatus.SHUTDOWN) break; // state is QUERY here @@ -75,7 +77,7 @@ public class SendThread extends Thread { // update our state, and notify, maybe someone is waiting // for us in throwErrors - state = WAIT; + state = SendThreadStatus.WAIT; waiting.signal(); } } finally { @@ -95,14 +97,14 @@ public class SendThread extends Thread { public void runQuery(String[] templ, String query) throws SQLException { sendLock.lock(); try { - if (state != WAIT) + if (state != SendThreadStatus.WAIT) throw new SQLException("SendThread already in use or shutting down!", "M0M03"); this.templ = templ; this.query = query; // let the thread know there is some work to do - state = QUERY; + state = SendThreadStatus.QUERY; queryAvailable.signal(); } finally { sendLock.unlock(); @@ -118,14 +120,14 @@ public class SendThread extends Thread { sendLock.lock(); try { // make sure the thread is in WAIT state, not QUERY - while (state == QUERY) { + while (state == SendThreadStatus.QUERY) { try { waiting.await(); } catch (InterruptedException e) { // just try again } } - if (state == SHUTDOWN) + if (state == SendThreadStatus.SHUTDOWN) error = "SendThread is shutting down"; } finally { sendLock.unlock(); @@ -138,7 +140,7 @@ public class SendThread extends Thread { */ public void shutdown() { sendLock.lock(); - state = SHUTDOWN; + state = SendThreadStatus.SHUTDOWN; sendLock.unlock(); this.interrupt(); // break any wait conditions }
--- a/src/main/java/nl/cwi/monetdb/mcl/io/BufferedMCLReader.java +++ b/src/main/java/nl/cwi/monetdb/mcl/io/BufferedMCLReader.java @@ -8,8 +8,6 @@ package nl.cwi.monetdb.mcl.io; -import nl.cwi.monetdb.mcl.connection.DeleteMe; - import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -39,7 +37,6 @@ import java.io.UnsupportedEncodingExcept * messages as the server receives them. * * @author Fabian Groffen <Fabian.Groffen> - * @see DeleteMe * @see BufferedMCLWriter */ public class BufferedMCLReader extends AbstractMCLReader {
--- a/src/main/java/nl/cwi/monetdb/mcl/io/BufferedMCLWriter.java +++ b/src/main/java/nl/cwi/monetdb/mcl/io/BufferedMCLWriter.java @@ -8,8 +8,6 @@ package nl.cwi.monetdb.mcl.io; -import nl.cwi.monetdb.mcl.connection.DeleteMe; - import java.io.*; /** @@ -30,7 +28,6 @@ import java.io.*; * class client-oriented when a reader is registered. * * @author Fabian Groffen <Fabian.Groffen> - * @see DeleteMe * @see BufferedMCLWriter */ public class BufferedMCLWriter extends AbstractMCLWriter {
deleted file mode 100644 --- a/src/main/java/nl/cwi/monetdb/mcl/io/EmbeddedMCLReader.java +++ /dev/null @@ -1,46 +0,0 @@ -package nl.cwi.monetdb.mcl.io; - -import nl.cwi.monetdb.mcl.connection.EmbeddedMonetDB; - -import java.io.*; - -/** - * Created by ferreira on 11/24/16. - */ -public final class EmbeddedMCLReader extends AbstractMCLReader { - - private final EmbeddedMonetDB connection; - - private int readerCurrentPos; - - private final int[] responseHeaderValues = new int[4]; - - private String nextLine = ""; - - public EmbeddedMCLReader(EmbeddedMonetDB connection) { - super(null); - this.connection = connection; - } - - @Override - public String readLine() throws IOException { - this.lineType = this.responseHeaderValues[this.readerCurrentPos]; - this.readerCurrentPos++; - - String res = this.nextLine; //this readline will never wait!! - - if (this.lineType == ERROR && !res.matches("^![0-9A-Z]{5}!.+")) - res = "!22000!" + res.substring(1); - return res; - } - - @Override - public synchronized String waitForPrompt() throws IOException { - try { - this.wait(); //must mimic the socket readline with the wait/notify methods - } catch (InterruptedException e) { - throw new IOException(e); - } - return null; - } -}
deleted file mode 100644 --- a/src/main/java/nl/cwi/monetdb/mcl/io/EmbeddedMCLWriter.java +++ /dev/null @@ -1,43 +0,0 @@ -package nl.cwi.monetdb.mcl.io; - -import nl.cwi.monetdb.mcl.connection.EmbeddedMonetDB; -import nl.cwi.monetdb.mcl.parser.embedded.EmbeddedHeaderLineParser; -import nl.cwi.monetdb.mcl.parser.embedded.EmbeddedStartOfHeaderParser; -import nl.cwi.monetdb.mcl.parser.embedded.EmbeddedTupleLineParser; - -import java.io.*; - -/** - * Created by ferreira on 11/24/16. - */ -public final class EmbeddedMCLWriter extends AbstractMCLWriter { - - private final EmbeddedMonetDB connection; - - private final EmbeddedStartOfHeaderParser sohp; - - private EmbeddedHeaderLineParser nexthlp; - - private EmbeddedTupleLineParser nexttlp; - - public void setNexthlp(EmbeddedHeaderLineParser nexthlp) { - this.nexthlp = nexthlp; - } - - public void setNexttlp(EmbeddedTupleLineParser nexttlp) { - this.nexttlp = nexttlp; - } - - public EmbeddedMCLWriter(EmbeddedMonetDB con, EmbeddedMCLReader reader, EmbeddedStartOfHeaderParser sohp) { - super(null); - this.connection = con; - this.reader = reader; - this.sohp = sohp; - } - - @Override - public void writeLine(String line) throws IOException { - this.reader.notify(); //wake up the embedded reader. - } - -}
rename from src/main/java/nl/cwi/monetdb/mcl/io/InternalConnection.java rename to src/main/java/nl/cwi/monetdb/mcl/io/JDBCEmbeddedConnection.java --- a/src/main/java/nl/cwi/monetdb/mcl/io/InternalConnection.java +++ b/src/main/java/nl/cwi/monetdb/mcl/io/JDBCEmbeddedConnection.java @@ -1,27 +1,13 @@ package nl.cwi.monetdb.mcl.io; -import nl.cwi.monetdb.embedded.env.IEmbeddedConnection; +import nl.cwi.monetdb.embedded.env.MonetDBEmbeddedConnection; /** - * Created by ferreira on 11/30/16. + * Created by ferreira on 12/1/16. */ -public class InternalConnection implements IEmbeddedConnection { - - private long connectionPointer; - - public InternalConnection(long connectionPointer) { - this.connectionPointer = connectionPointer; - } +public class JDBCEmbeddedConnection extends MonetDBEmbeddedConnection { - @Override - public long getConnectionPointer() { - return this.connectionPointer; + protected JDBCEmbeddedConnection(long connectionPointer) { + super(connectionPointer); } - - @Override - public void closeConnectionImplementation() { - this.closeConnectionInternal(this.connectionPointer); - } - - private native void closeConnectionInternal(long connectionPointer); }
deleted file mode 100644 --- a/src/main/java/nl/cwi/monetdb/mcl/parser/embedded/EmbeddedHeaderLineParser.java +++ /dev/null @@ -1,44 +0,0 @@ -package nl.cwi.monetdb.mcl.parser.embedded; - -import nl.cwi.monetdb.mcl.parser.HeaderLineParser; -import nl.cwi.monetdb.mcl.parser.MCLParseException; - -/** - * Created by ferreira on 11/25/16. - */ -public class EmbeddedHeaderLineParser extends HeaderLineParser { - - private long resultSetPointer; - - /** - * Creates an MCLParser targeted at a given number of field values. - * The lines parsed by an instance of this MCLParser should have - * exactly capacity field values. - * - * @param capacity the number of field values to expect - */ - public EmbeddedHeaderLineParser(int capacity) { - super(capacity); - } - - @Override - public int parse(String source) throws MCLParseException { - /*switch(this.colnr) { - case HeaderLineParser.NAME: - System.arraycopy(this.columnNames, 0, this.values, 0, this.values.length); - break; - case HeaderLineParser.LENGTH: - System.arraycopy(this.columnLengths, 0, this.intValues, 0, this.intValues.length); - break; - case HeaderLineParser.TABLE: - System.arraycopy(this.columnTables, 0, this.values, 0, this.values.length); - break; - case HeaderLineParser.TYPE: - System.arraycopy(this.columnTypes, 0, this.values, 0, this.values.length); - break; - }*/ - return this.parseNextHeadLineInternal(); - } - - private native int parseNextHeadLineInternal(); -}
deleted file mode 100644 --- a/src/main/java/nl/cwi/monetdb/mcl/parser/embedded/EmbeddedStartOfHeaderParser.java +++ /dev/null @@ -1,55 +0,0 @@ -package nl.cwi.monetdb.mcl.parser.embedded; - -import nl.cwi.monetdb.mcl.parser.MCLParseException; -import nl.cwi.monetdb.mcl.parser.StartOfHeaderParser; - -/** - * Created by ferreira on 11/25/16. - */ -public class EmbeddedStartOfHeaderParser extends StartOfHeaderParser { - - private int nextResponseType; - - private final int[] nextIntValues = new int[4]; - - private String nextStringValue; - - @Override - public int parse(String in) throws MCLParseException { - this.pos = 0; - switch (this.nextResponseType) { - /*case Q_PARSE:*/ - case Q_SCHEMA: - this.len = 0; - break; - case Q_TABLE: - case Q_PREPARE: - this.len = 4; - break; - case Q_UPDATE: - this.len = 2; - break; - case Q_TRANS: - this.len = 1; - break; - /*case Q_BLOCK: - len = 3; - break;*/ - default: - throw new MCLParseException("invalid or unknown header", 1); - } - return this.nextResponseType; - } - - @Override - public int getNextAsInt() throws MCLParseException { - int res = this.nextIntValues[this.pos]; - this.pos++; - return res; - } - - @Override - public String getNextAsString() throws MCLParseException { - return this.nextStringValue; - } -}
deleted file mode 100644 --- a/src/main/java/nl/cwi/monetdb/mcl/parser/embedded/EmbeddedTupleLineParser.java +++ /dev/null @@ -1,26 +0,0 @@ -package nl.cwi.monetdb.mcl.parser.embedded; - -import nl.cwi.monetdb.mcl.parser.MCLParseException; -import nl.cwi.monetdb.mcl.parser.TupleLineParser; - -/** - * Created by ferreira on 11/25/16. - */ -public class EmbeddedTupleLineParser extends TupleLineParser { - - /** - * Creates an MCLParser targeted at a given number of field values. - * The lines parsed by an instance of this MCLParser should have - * exactly capacity field values. - * - * @param capacity the number of field values to expect - */ - public EmbeddedTupleLineParser(int capacity) { - super(capacity); - } - - @Override - public int parse(String source) throws MCLParseException { - return 0; - } -}
--- a/src/main/java/nl/cwi/monetdb/mcl/protocol/embedded/EmbeddedProtocol.java +++ b/src/main/java/nl/cwi/monetdb/mcl/protocol/embedded/EmbeddedProtocol.java @@ -1,6 +1,6 @@ package nl.cwi.monetdb.mcl.protocol.embedded; -import nl.cwi.monetdb.mcl.io.InternalConnection; +import nl.cwi.monetdb.mcl.io.JDBCEmbeddedConnection; import nl.cwi.monetdb.mcl.protocol.AbstractProtocolParser; import nl.cwi.monetdb.mcl.protocol.ServerResponses; import nl.cwi.monetdb.mcl.protocol.StarterHeaders; @@ -11,9 +11,9 @@ import nl.cwi.monetdb.mcl.protocol.Table */ public class EmbeddedProtocol extends AbstractProtocolParser { - private final InternalConnection embeddedConnection; + private final JDBCEmbeddedConnection embeddedConnection; - public EmbeddedProtocol(InternalConnection embeddedConnection) { + public EmbeddedProtocol(JDBCEmbeddedConnection embeddedConnection) { this.embeddedConnection = embeddedConnection; }
--- a/src/main/java/nl/cwi/monetdb/responses/AutoCommitResponse.java +++ b/src/main/java/nl/cwi/monetdb/responses/AutoCommitResponse.java @@ -6,6 +6,7 @@ package nl.cwi.monetdb.responses; * <tt>&4 (t|f)</tt> */ public class AutoCommitResponse extends SchemaResponse { + public final boolean autocommit; public AutoCommitResponse(boolean ac) {
--- a/src/main/java/nl/cwi/monetdb/responses/ResponseList.java +++ b/src/main/java/nl/cwi/monetdb/responses/ResponseList.java @@ -1,6 +1,7 @@ package nl.cwi.monetdb.responses; import nl.cwi.monetdb.jdbc.MonetConnection; +import nl.cwi.monetdb.mcl.connection.SendThread; import nl.cwi.monetdb.mcl.io.AbstractMCLReader; import nl.cwi.monetdb.mcl.parser.MCLParseException; import nl.cwi.monetdb.mcl.parser.StartOfHeaderParser; @@ -38,13 +39,12 @@ public class ResponseList { private final int seqnr; /** A list of the Responses associated with the query, * in the right order */ - private List<IResponse> responses; + private List<IResponse> responses = new ArrayList<>(); /** A map of ResultSetResponses, used for additional * DataBlockResponse mapping */ private Map<Integer, ResultSetResponse> rsresponses; - /** The current header returned by getNextResponse() */ - private int curResponse; + private int curResponse = -1; /** * Main constructor. The query argument can either be a String @@ -61,9 +61,7 @@ public class ResponseList { this.maxrows = maxrows; this.rstype = rstype; this.rsconcur = rsconcur; - responses = new ArrayList<>(); - curResponse = -1; - seqnr = SeqCounter++; + this.seqnr = SeqCounter++; } /** @@ -107,14 +105,14 @@ public class ResponseList { /** * Closes the current response. */ - void closeCurrentResponse() { + public void closeCurrentResponse() { closeResponse(curResponse); } /** * Closes the current and previous responses. */ - void closeCurOldResponses() { + public void closeCurOldResponses() { for (int i = curResponse; i >= 0; i--) { closeResponse(i); } @@ -134,7 +132,7 @@ public class ResponseList { * Returns whether this ResponseList has still unclosed * Responses. */ - boolean hasUnclosedResponses() { + public boolean hasUnclosedResponses() { for (IResponse r : responses) { if (r != null) return true;
--- a/src/main/java/nl/cwi/monetdb/responses/ResultSetResponse.java +++ b/src/main/java/nl/cwi/monetdb/responses/ResultSetResponse.java @@ -206,7 +206,7 @@ public class ResultSetResponse implement * @param offset the offset number of rows for this block * @param rr the DataBlockResponse to add */ - void addDataBlockResponse(int offset, DataBlockResponse rr) { + public void addDataBlockResponse(int offset, DataBlockResponse rr) { int block = (offset - blockOffset) / cacheSize; resultBlocks[block] = rr; } @@ -233,7 +233,7 @@ public class ResultSetResponse implement * * @return the names of the columns */ - String[] getNames() { + public String[] getNames() { return name; } @@ -242,7 +242,7 @@ public class ResultSetResponse implement * * @return the types of the columns */ - String[] getTypes() { + public String[] getTypes() { return type; } @@ -251,7 +251,7 @@ public class ResultSetResponse implement * * @return the tables of the columns */ - String[] getTableNames() { + public String[] getTableNames() { return tableNames; } @@ -260,7 +260,7 @@ public class ResultSetResponse implement * * @return the lengths of the columns */ - int[] getColumnLengths() { + public int[] getColumnLengths() { return columnLengths; } @@ -269,7 +269,7 @@ public class ResultSetResponse implement * * @return the cache size */ - int getCacheSize() { + public int getCacheSize() { return cacheSize; } @@ -278,7 +278,7 @@ public class ResultSetResponse implement * * @return the current block offset */ - int getBlockOffset() { + public int getBlockOffset() { return blockOffset; } @@ -287,7 +287,7 @@ public class ResultSetResponse implement * * @return the ResultSet type */ - int getRSType() { + public int getRSType() { return parent.rstype; } @@ -296,7 +296,7 @@ public class ResultSetResponse implement * * @return the ResultSet concurrency */ - int getRSConcur() { + public int getRSConcur() { return parent.rsconcur; } @@ -311,7 +311,7 @@ public class ResultSetResponse implement * is out of the scope of the result set * @throws SQLException if an database error occurs */ - String getLine(int row) throws SQLException { + public String getLine(int row) throws SQLException { if (row >= tuplecount || row < 0) return null; @@ -403,7 +403,7 @@ public class ResultSetResponse implement * * @return whether this Response is closed */ - boolean isClosed() { + public boolean isClosed() { return closed; } }