changeset 764:052c23fbfab2

Corrected implementation of Connection methods getClientInfo() and setClientInfo(). They used to get/set Connection properties instead of Client Info properties which was a incorrect. MonetDB does not support Client Info properties.
author Martin van Dinther <martin.van.dinther@monetdbsolutions.com>
date Wed, 05 Jul 2023 21:34:11 +0200 (21 months ago)
parents e8afd7de2538
children 552c125e5cdc
files ChangeLog src/main/java/org/monetdb/jdbc/MonetConnection.java tests/JDBC_API_Tester.java
diffstat 3 files changed, 79 insertions(+), 64 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,12 @@
 # ChangeLog file for monetdb-java
 # This file is updated with Maddlog
 
+* Wed Jul  5 2023 Martin van Dinther <martin.van.dinther@monetdbsolutions.com>
+- Corrected implementation of Connection methods getClientInfo() and
+  setClientInfo(). They used to get/set Connection properties instead
+  of Client Info properties which was a incorrect. MonetDB does not
+  support Client Info properties.
+
 * Thu Jun 22 2023 Martin van Dinther <martin.van.dinther@monetdbsolutions.com>
 - Corrected DatabaseMetaData method getClientProperties().
   It used to return connection properties instead of client info properties.
--- a/src/main/java/org/monetdb/jdbc/MonetConnection.java
+++ b/src/main/java/org/monetdb/jdbc/MonetConnection.java
@@ -74,9 +74,6 @@ public class MonetConnection
 	extends MonetWrapper
 	implements Connection, AutoCloseable
 {
-	/** the successful processed input properties */
-	private final Properties conn_props = new Properties();
-
 	/** The hostname to connect to */
 	private final String hostname;
 	/** The port to connect on the host to */
@@ -172,10 +169,7 @@ public class MonetConnection
 
 		// for debug: System.out.println("New connection object. Received properties are: " + props.toString());
 		// get supported property values from the props argument.
-		// When a value is found add it to the internal conn_props list for use by getClientInfo().
 		this.hostname = props.getProperty("host");
-		if (this.hostname != null)
-			conn_props.setProperty("host", this.hostname);
 
 		final String port_prop = props.getProperty("port");
 		if (port_prop != null) {
@@ -184,41 +178,25 @@ public class MonetConnection
 			} catch (NumberFormatException e) {
 				addWarning("Unable to parse port number from: " + port_prop, "M1M05");
 			}
-			conn_props.setProperty("port", Integer.toString(this.port));
 		}
 
 		this.database = props.getProperty("database");
-		if (this.database != null)
-			conn_props.setProperty("database", this.database);
-
 		this.username = props.getProperty("user");
-		if (this.username != null)
-			conn_props.setProperty("user", this.username);
-
 		this.password = props.getProperty("password");
-		if (this.password != null)
-			conn_props.setProperty("password", this.password);
-
 		String language = props.getProperty("language");
-		if (language != null)
-			conn_props.setProperty("language", language);
 
 		boolean debug = false;
 		String debug_prop = props.getProperty("debug");
 		if (debug_prop != null) {
 			debug = Boolean.parseBoolean(debug_prop);
-			conn_props.setProperty("debug", Boolean.toString(debug));
 		}
 
 		final String hash = props.getProperty("hash");
-		if (hash != null)
-			conn_props.setProperty("hash", hash);
 
 		String autocommit_prop = props.getProperty("autocommit");
 		if (autocommit_prop != null) {
 			boolean ac = Boolean.parseBoolean(autocommit_prop);
 			autoCommitSetting.set(ac);
-			conn_props.setProperty("autocommit", Boolean.toString(ac));
 		}
 
 		final String fetchsize_prop = props.getProperty("fetchsize");
@@ -227,7 +205,6 @@ public class MonetConnection
 				int fetchsize = Integer.parseInt(fetchsize_prop);
 				if (fetchsize > 0 || fetchsize == -1) {
 					replySizeSetting.set(fetchsize);
-					conn_props.setProperty("fetchsize", fetchsize_prop);
 				} else {
 					addWarning("Fetch size must either be positive or -1. Value " + fetchsize + " ignored", "M1M05");
 				}
@@ -239,7 +216,6 @@ public class MonetConnection
 		final String treatBlobAsVarBinary_prop = props.getProperty("treat_blob_as_binary");
 		if (treatBlobAsVarBinary_prop != null) {
 			treatBlobAsVarBinary = Boolean.parseBoolean(treatBlobAsVarBinary_prop);
-			conn_props.setProperty("treat_blob_as_binary", Boolean.toString(treatBlobAsVarBinary));
 			if (treatBlobAsVarBinary)
 				typeMap.put("blob", Byte[].class);
 		}
@@ -247,7 +223,6 @@ public class MonetConnection
 		final String treatClobAsVarChar_prop = props.getProperty("treat_clob_as_varchar");
 		if (treatClobAsVarChar_prop != null) {
 			treatClobAsVarChar = Boolean.parseBoolean(treatClobAsVarChar_prop);
-			conn_props.setProperty("treat_clob_as_varchar", Boolean.toString(treatClobAsVarChar));
 			if (treatClobAsVarChar)
 				typeMap.put("clob", String.class);
 		}
@@ -264,7 +239,6 @@ public class MonetConnection
 			} catch (NumberFormatException e) {
 				addWarning("Unable to parse socket timeout number from: " + so_timeout_prop, "M1M05");
 			}
-			conn_props.setProperty("so_timeout", Integer.toString(sockTimeout));
 		}
 
 		// check mandatory input arguments
@@ -283,7 +257,7 @@ public class MonetConnection
 			addWarning("No language specified, defaulting to 'sql'", "M1M05");
 		}
 
-		// warn about unrecognized settings
+		// warn about unrecognized property names
 		for (Entry<Object,Object> e: props.entrySet()) {
 			checkValidProperty(e.getKey().toString(), "MonetConnection");
 		}
@@ -1431,10 +1405,8 @@ public class MonetConnection
 	 */
 	@Override
 	public String getClientInfo(final String name) throws SQLException {
-		if (name == null || name.isEmpty())
-			return null;
-		checkNotClosed();
-		return conn_props.getProperty(name);
+		// MonetDB doesn't support any Client Info Properties yet
+		return null;
 	}
 
 	/**
@@ -1451,9 +1423,8 @@ public class MonetConnection
 	 */
 	@Override
 	public Properties getClientInfo() throws SQLException {
-		checkNotClosed();
-		// return a clone of the connection properties object
-		return new Properties(conn_props);
+		// MonetDB doesn't support any Client Info Properties yet
+		return new Properties();
 	}
 
 	/**
@@ -1494,20 +1465,8 @@ public class MonetConnection
 	 */
 	@Override
 	public void setClientInfo(final String name, final String value) throws 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, warn about the others
-		if (checkValidProperty(name, "setClientInfo")) {
-			conn_props.setProperty(name, value);
-		}
+		// MonetDB doesn't support any Client Info Properties yet
+		addWarning("setClientInfo: client info property name not recognized", "01M07");
 	}
 
 	/**
@@ -1854,7 +1813,7 @@ public class MonetConnection
 	 */
 	private boolean checkValidProperty(String name, String context) {
 		// supported MonetDB connection properties.
-		// See also MonetDatabaseMetaData.getClientInfoProperties()
+		// See also MonetDriver.connect()
 		if (name.equals("host")
 		 || name.equals("port")
 		 || name.equals("user")
@@ -1871,7 +1830,7 @@ public class MonetConnection
 		 || name.equals("fetchsize"))	// only supported by servers from version 11.41.1 onwards
 			return true;
 
-		addWarning(context + ": '" + name + "' is not a recognised property", "01M07");
+		addWarning(context + " property name '" + name + "' is not recognized", "01M07");
 		return false;
 	}
 
--- a/tests/JDBC_API_Tester.java
+++ b/tests/JDBC_API_Tester.java
@@ -110,7 +110,7 @@ final public class JDBC_API_Tester {
 		jt.Bug_PrepStmt_With_Errors_Jira292();
 		jt.BugResultSetMetaData_Bug_6183();
 		jt.BugSetQueryTimeout_Bug_3357();
-		jt.SQLcopyinto();
+		jt.SQLcopyinto(con_URL);
 		jt.DecimalPrecisionAndScale();
 
 		/* run next long running test (11 minutes) only before a new release */
@@ -6622,7 +6622,7 @@ final public class JDBC_API_Tester {
 	 *
 	 * @author Fabian Groffen, Martin van Dinther
 	 */
-	private void SQLcopyinto() {
+	private void SQLcopyinto(final String conn_URL) {
 		sb.setLength(0);	// clear the output log buffer
 
 		final String tablenm = "exampleSQLCopyInto";
@@ -6632,7 +6632,7 @@ final public class JDBC_API_Tester {
 			stmt = con.createStatement();
 			stmt.execute("CREATE TABLE IF NOT EXISTS " + tablenm + " (id int, val varchar(24))");
 
-			fillTableUsingCopyIntoSTDIN(tablenm);
+			fillTableUsingCopyIntoSTDIN(conn_URL, tablenm);
 
 			// check content of the table populated via COPY INTO ... FROM STDIN
 			sb.append("Listing uploaded data:\n");
@@ -6682,24 +6682,24 @@ final public class JDBC_API_Tester {
 				"SQLcopyinto completed\n");
 	}
 
-	private void fillTableUsingCopyIntoSTDIN(String tablenm) throws Exception {
+	private void fillTableUsingCopyIntoSTDIN(final String conn_URL, final String tablenm) throws Exception {
 		sb.append("CopyInto STDIN begin\n");
 
 		org.monetdb.mcl.net.MapiSocket server = new org.monetdb.mcl.net.MapiSocket();
 		try {
 			server.setLanguage("sql");
 
-			// extract from MonetConnection object the used connection properties
-			String host = con.getClientInfo("host");
-			int port = Integer.parseInt(con.getClientInfo("port"));
-			String login = con.getClientInfo("user");
-			String passw = con.getClientInfo("password");
-
-			String database = con.getClientInfo("database");
+			// extract from conn_URL the used connection properties
+			String host = extractFromJDBCURL(conn_URL, "host");
+			int port = Integer.parseInt(extractFromJDBCURL(conn_URL, "port"));
+			String login = extractFromJDBCURL(conn_URL, "user");
+			String passw = extractFromJDBCURL(conn_URL, "password");
+			String database = extractFromJDBCURL(conn_URL, "database");
+			// sb.append("conn_URL: " + conn_URL + "\n");
+			// sb.append("host: " + host + " port: " + port + " dbname: " + database + " login: " + login + " passwd: " + passw + "\n");
+
+			sb.append("Before connecting to MonetDB server via MapiSocket\n");
 			server.setDatabase(database);
-
-			// sb.append("host: " + host + " port: " + port + " login: " + login + " passwd: " + passw + "\n");
-			sb.append("Before connecting to MonetDB server via MapiSocket\n");
 			List<String> warning = server.connect(host, port, login, passw);
 			if (warning != null) {
 				for (Iterator<String> it = warning.iterator(); it.hasNext(); ) {
@@ -6750,6 +6750,56 @@ final public class JDBC_API_Tester {
 		sb.append("CopyInto STDIN end\n");
 	}
 
+	private String extractFromJDBCURL(String conn_URL, String prop) {
+		// URL="jdbc:monetdb://${HOST}:${MAPIPORT}/${DBNAME}?user=$(USER)&password=$(PWD)&${JDBC_EXTRA_ARGS}"
+		// URL example: jdbc:monetdb://localhost:35145/mTests_sql_jdbc_tests?user=monetdb&password=monetdb
+		final String pre = "jdbc:monetdb://";
+		final int pre_len = pre.length();
+		int start = 0, end = 0;
+		if ("host".equals(prop)) {
+			start = conn_URL.indexOf(pre);
+			if (start >= 0) {
+				start += pre_len;
+				end = conn_URL.indexOf(':', start);
+			}
+		} else
+		if ("port".equals(prop)) {
+			start = conn_URL.indexOf(':', pre_len);
+			if (start >= 0) {
+				start += 1;
+				end = conn_URL.indexOf('/', start);
+			}
+		} else
+		if ("database".equals(prop)) {
+			start = conn_URL.indexOf('/', pre_len + 1);
+			if (start >= 0) {
+				start += 1;
+				end = conn_URL.indexOf('?', start);
+			}
+		} else
+		if ("user".equals(prop)) {
+			start = conn_URL.indexOf("user=", pre_len);
+			if (start >= 0) {
+				start += 5;
+				end = conn_URL.indexOf('&', start);
+			}
+		} else
+		if ("password".equals(prop)) {
+			start = conn_URL.indexOf("password=", pre_len);
+			if (start >= 0) {
+				start += 9;
+				end = conn_URL.indexOf('&', start);
+			}
+		}
+		if (start >= pre_len) {
+			if (end < 0)
+				end = conn_URL.length();
+			if (end > start)
+				return conn_URL.substring(start, end);
+		}
+		return "";
+	}
+
 	private void DecimalPrecisionAndScale() {
 		sb.setLength(0);	// clear the output log buffer