comparison src/main/java/nl/cwi/monetdb/jdbc/MonetDriver.java.in @ 295:003ae6d881db

Add "final" keyword to method arguments and local variables where possible. It discovered some bugs in the MonetStatement constructor (changed the argument instead of object variable) which are fixed now. See also https://en.wikipedia.org/wiki/Final_(Java)
author Martin van Dinther <martin.van.dinther@monetdbsolutions.com>
date Thu, 01 Aug 2019 20:18:43 +0200 (2019-08-01)
parents 2d62ca1f758b
children 55330e40cbf1
comparison
equal deleted inserted replaced
294:894abb249de1 295:003ae6d881db
7 */ 7 */
8 8
9 package nl.cwi.monetdb.jdbc; 9 package nl.cwi.monetdb.jdbc;
10 10
11 import java.net.URI; 11 import java.net.URI;
12 import java.net.URISyntaxException;
13 import java.sql.Connection; 12 import java.sql.Connection;
14 import java.sql.Driver; 13 import java.sql.Driver;
15 import java.sql.DriverManager; 14 import java.sql.DriverManager;
16 import java.sql.DriverPropertyInfo; 15 import java.sql.DriverPropertyInfo;
17 import java.sql.SQLException; 16 import java.sql.SQLException;
18 import java.sql.SQLFeatureNotSupportedException; 17 import java.sql.SQLFeatureNotSupportedException;
19 import java.sql.SQLNonTransientConnectionException;
20 import java.sql.Types; 18 import java.sql.Types;
21 import java.util.ArrayList;
22 import java.util.List;
23 import java.util.Map.Entry; 19 import java.util.Map.Entry;
24 import java.util.Properties; 20 import java.util.Properties;
25 import java.util.logging.Logger;
26 21
27 /** 22 /**
28 * A Driver suitable for the MonetDB database. 23 * A Driver suitable for the MonetDB database.
29 * 24 *
30 * This driver will be used by the DriverManager to determine if an URL 25 * This driver will be used by the DriverManager to determine if an URL
54 /** Minor version of this driver */ 49 /** Minor version of this driver */
55 private static final int DRIVERMINOR = @JDBC_MINOR@; 50 private static final int DRIVERMINOR = @JDBC_MINOR@;
56 /** Version suffix string */ 51 /** Version suffix string */
57 private static final String DRIVERVERSIONSUFFIX = 52 private static final String DRIVERVERSIONSUFFIX =
58 "@JDBC_VER_SUFFIX@ based on MCL v@MCL_MAJOR@.@MCL_MINOR@"; 53 "@JDBC_VER_SUFFIX@ based on MCL v@MCL_MAJOR@.@MCL_MINOR@";
59 // We're not fully compliant, but what we support is compliant
60 /** Whether this driver is JDBC compliant or not */
61 private static final boolean MONETJDBCCOMPLIANT = false;
62 54
63 /** MonetDB default port to connect to */ 55 /** MonetDB default port to connect to */
64 private static final String PORT = "@JDBC_DEF_PORT@"; 56 private static final String PORT = "@JDBC_DEF_PORT@";
65 57
66 58
83 * 75 *
84 * @param url the URL of the database 76 * @param url the URL of the database
85 * @return true if this driver understands the given URL; false otherwise 77 * @return true if this driver understands the given URL; false otherwise
86 */ 78 */
87 @Override 79 @Override
88 public boolean acceptsURL(String url) { 80 public boolean acceptsURL(final String url) {
89 return url != null && url.startsWith(MONETURL); 81 return url != null && url.startsWith(MONETURL);
90 } 82 }
91 83
92 /** 84 /**
93 * Attempts to make a database connection to the given URL. The driver 85 * Attempts to make a database connection to the given URL. The driver
109 * should be included 101 * should be included
110 * @return a Connection object that represents a connection to the URL 102 * @return a Connection object that represents a connection to the URL
111 * @throws SQLException if a database access error occurs 103 * @throws SQLException if a database access error occurs
112 */ 104 */
113 @Override 105 @Override
114 public Connection connect(String url, Properties info) 106 public Connection connect(final String url, Properties info)
115 throws SQLException 107 throws SQLException
116 { 108 {
117 // url should be of style jdbc:monetdb://<host>/<database> 109 // url should be of style jdbc:monetdb://<host>/<database>
118 if (!acceptsURL(url)) 110 if (!acceptsURL(url))
119 return null; 111 return null;
120 112
121 Properties props = new Properties(); 113 final Properties props = new Properties();
122 // set the optional properties and their defaults here 114 // set the optional properties and their defaults here
123 props.put("port", PORT); 115 props.put("port", PORT);
124 props.put("debug", "false"); 116 props.put("debug", "false");
125 props.put("language", "sql"); // mal, sql, <future> 117 props.put("language", "sql"); // mal, sql, <future>
126 props.put("so_timeout", "0"); 118 props.put("so_timeout", "0");
128 if (info != null) 120 if (info != null)
129 props.putAll(info); 121 props.putAll(info);
130 info = props; 122 info = props;
131 123
132 // remove leading "jdbc:" so the rest is a valid hierarchical URI 124 // remove leading "jdbc:" so the rest is a valid hierarchical URI
133 URI uri; 125 final URI uri;
134 try { 126 try {
135 uri = new URI(url.substring(5)); 127 uri = new URI(url.substring(5));
136 } catch (URISyntaxException e) { 128 } catch (java.net.URISyntaxException e) {
137 return null; 129 return null;
138 } 130 }
139 131
140 String uri_host = uri.getHost(); 132 final String uri_host = uri.getHost();
141 if (uri_host == null) 133 if (uri_host == null)
142 return null; 134 return null;
143 info.put("host", uri_host); 135 info.put("host", uri_host);
144 136
145 int uri_port = uri.getPort(); 137 int uri_port = uri.getPort();
152 uri_path = uri_path.substring(1).trim(); 144 uri_path = uri_path.substring(1).trim();
153 if (!uri_path.isEmpty()) 145 if (!uri_path.isEmpty())
154 info.put("database", uri_path); 146 info.put("database", uri_path);
155 } 147 }
156 148
157 String uri_query = uri.getQuery(); 149 final String uri_query = uri.getQuery();
158 if (uri_query != null) { 150 if (uri_query != null) {
159 int pos; 151 int pos;
160 // handle additional connection properties separated by the & character 152 // handle additional connection properties separated by the & character
161 String args[] = uri_query.split("&"); 153 final String args[] = uri_query.split("&");
162 for (int i = 0; i < args.length; i++) { 154 for (int i = 0; i < args.length; i++) {
163 pos = args[i].indexOf('='); 155 pos = args[i].indexOf('=');
164 if (pos > 0) 156 if (pos > 0)
165 info.put(args[i].substring(0, pos), args[i].substring(pos + 1)); 157 info.put(args[i].substring(0, pos), args[i].substring(pos + 1));
166 } 158 }
206 * @return an array of DriverPropertyInfo objects describing possible 198 * @return an array of DriverPropertyInfo objects describing possible
207 * properties. This array may be an empty array if no properties 199 * properties. This array may be an empty array if no properties
208 * are required. 200 * are required.
209 */ 201 */
210 @Override 202 @Override
211 public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) { 203 public DriverPropertyInfo[] getPropertyInfo(final String url, final Properties info) {
212 if (!acceptsURL(url)) 204 if (!acceptsURL(url))
213 return null; 205 return null;
214 206
215 String[] boolean_choices = new String[] { "true", "false" }; 207 final String[] boolean_choices = new String[] { "true", "false" };
216 String[] language_choices = new String[] { "sql", "mal" }; 208 final String[] language_choices = new String[] { "sql", "mal" };
217 String[] hash_choices = new String[] { "SHA512", "SHA384", "SHA256", "SHA1", "MD5" }; 209 final String[] hash_choices = new String[] { "SHA512", "SHA384", "SHA256", "SHA1", "MD5" };
218 DriverPropertyInfo[] dpi = new DriverPropertyInfo[9]; // we currently support 9 connection properties 210 final DriverPropertyInfo[] dpi = new DriverPropertyInfo[9]; // we currently support 9 connection properties
219 211
220 DriverPropertyInfo prop = new DriverPropertyInfo("user", info != null ? info.getProperty("user") : null); 212 DriverPropertyInfo prop = new DriverPropertyInfo("user", info != null ? info.getProperty("user") : null);
221 prop.required = true; 213 prop.required = true;
222 prop.description = "The user loginname to use when authenticating on the database server"; 214 prop.description = "The user loginname to use when authenticating on the database server";
223 dpi[0] = prop; 215 dpi[0] = prop;
296 * 288 *
297 * @return true if this driver is JDBC Compliant; false otherwise 289 * @return true if this driver is JDBC Compliant; false otherwise
298 */ 290 */
299 @Override 291 @Override
300 public boolean jdbcCompliant() { 292 public boolean jdbcCompliant() {
301 return MONETJDBCCOMPLIANT; 293 // We're not fully JDBC compliant, but what we support is compliant
294 return false;
302 } 295 }
303 296
304 /** 297 /**
305 * Return the parent Logger of all the Loggers used by this data source. 298 * Return the parent Logger of all the Loggers used by this data source.
306 * This should be the Logger farthest from the root Logger that is 299 * This should be the Logger farthest from the root Logger that is
313 * @throws SQLFeatureNotSupportedException if the data source does 306 * @throws SQLFeatureNotSupportedException if the data source does
314 * not use java.util.logging 307 * not use java.util.logging
315 * @since 1.7 308 * @since 1.7
316 */ 309 */
317 @Override 310 @Override
318 public Logger getParentLogger() throws SQLFeatureNotSupportedException { 311 public java.util.logging.Logger getParentLogger() throws SQLFeatureNotSupportedException {
319 throw MonetWrapper.newSQLFeatureNotSupportedException("getParentLogger"); 312 throw MonetWrapper.newSQLFeatureNotSupportedException("getParentLogger");
320 } 313 }
321 314
322 //== end methods of interface driver 315 //== end methods of interface driver
323 316
324 317
325 /** A static Map containing the mapping between MonetDB types and Java SQL types */ 318 /** A static Map containing the mapping between MonetDB types and Java SQL types */
326 /* use SELECT sqlname, * FROM sys.types order by 1, id; to view all MonetDB types */ 319 /* use SELECT sqlname, * FROM sys.types order by 1, id; to view all MonetDB types */
327 /* see http://docs.oracle.com/javase/7/docs/api/java/sql/Types.html to view all supported java SQL types */ 320 /* see http://docs.oracle.com/javase/7/docs/api/java/sql/Types.html to view all supported java SQL types */
328 private static java.util.Map<String, Integer> typeMap = new java.util.HashMap<String, Integer>(); 321 private static final java.util.Map<String, Integer> typeMap = new java.util.HashMap<String, Integer>();
329 static { 322 static {
330 // fill the typeMap once 323 // fill the typeMap once
331 // typeMap.put("any", Integer.valueOf(Types.???)); 324 // typeMap.put("any", Integer.valueOf(Types.???));
332 typeMap.put("bigint", Integer.valueOf(Types.BIGINT)); 325 typeMap.put("bigint", Integer.valueOf(Types.BIGINT));
333 typeMap.put("blob", Integer.valueOf(Types.BLOB)); 326 typeMap.put("blob", Integer.valueOf(Types.BLOB));
369 * 362 *
370 * @param type the SQL data type name as used by MonetDB 363 * @param type the SQL data type name as used by MonetDB
371 * @return the matching java.sql.Types constant or 364 * @return the matching java.sql.Types constant or
372 * java.sql.Types.OTHER if nothing matched the given type name 365 * java.sql.Types.OTHER if nothing matched the given type name
373 */ 366 */
374 static int getJdbcSQLType(String type) { 367 static final int getJdbcSQLType(final String type) {
375 // find the column type name in the typeMap 368 // find the column type name in the typeMap
376 Integer tp = typeMap.get(type); 369 final Integer tp = typeMap.get(type);
377 if (tp != null) { 370 if (tp != null) {
378 return tp.intValue(); 371 return tp.intValue();
379 } 372 }
380 // When type name is not found in the map, for instance 373 // When type name is not found in the map, for instance
381 // when it is a new type (not yet added in the above typeMap) or 374 // when it is a new type (not yet added in the above typeMap) or
392 * @param column a String representing the value that should be evaluated 385 * @param column a String representing the value that should be evaluated
393 * in the SQL CASE statement 386 * in the SQL CASE statement
394 * @return a SQL CASE statement 387 * @return a SQL CASE statement
395 */ 388 */
396 private static String TypeMapppingSQL = null; // cache to optimise getSQLTypeMap() 389 private static String TypeMapppingSQL = null; // cache to optimise getSQLTypeMap()
397 static String getSQLTypeMap(String column) { 390 static final String getSQLTypeMap(final String column) {
398 if (TypeMapppingSQL == null) { 391 if (TypeMapppingSQL == null) {
399 // first time, compose TypeMappping SQL string 392 // first time, compose TypeMappping SQL string
400 StringBuilder val = new StringBuilder((typeMap.size() * (7 + 7 + 7 + 4)) + 14); 393 final StringBuilder val = new StringBuilder((typeMap.size() * (7 + 7 + 7 + 4)) + 14);
401 for (Entry<String, Integer> entry : typeMap.entrySet()) { 394 for (Entry<String, Integer> entry : typeMap.entrySet()) {
402 val.append(" WHEN '").append(entry.getKey()).append("' THEN ").append(entry.getValue().toString()); 395 val.append(" WHEN '").append(entry.getKey()).append("' THEN ").append(entry.getValue().toString());
403 } 396 }
404 val.append(" ELSE ").append(Types.OTHER).append(" END"); 397 val.append(" ELSE ").append(Types.OTHER).append(" END");
405 // as the typeMap is static, cache this SQL part for all next calls 398 // as the typeMap is static, cache this SQL part for all next calls
408 return "CASE " + column + TypeMapppingSQL; 401 return "CASE " + column + TypeMapppingSQL;
409 } 402 }
410 403
411 /** 404 /**
412 * Returns a touched up identifying version string of this driver. 405 * Returns a touched up identifying version string of this driver.
413 * 406 * It is made public as it is called from nl/cwi/monetdb/client/JdbcClient.java
414 * @return the version string 407 * @return the version string
415 */ 408 */
416 public static String getDriverVersion() { 409 public static final String getDriverVersion() {
417 return DRIVERMAJOR + "." + DRIVERMINOR + " (" + DRIVERVERSIONSUFFIX + ")"; 410 return DRIVERMAJOR + "." + DRIVERMINOR + " (" + DRIVERVERSIONSUFFIX + ")";
418 } 411 }
419 412
420 static int getDriverMajorVersion() { 413 static final int getDriverMajorVersion() {
421 return DRIVERMAJOR; 414 return DRIVERMAJOR;
422 } 415 }
423 416
424 static int getDriverMinorVersion() { 417 static final int getDriverMinorVersion() {
425 return DRIVERMINOR; 418 return DRIVERMINOR;
426 } 419 }
427 } 420 }