Changeset: e8962bdaa206 for monetdb-java
URL: https://dev.monetdb.org/hg/monetdb-java?cmd=changeset;node=e8962bdaa206
Modified Files:
        src/main/java/nl/cwi/monetdb/jdbc/MonetConnection.java
        src/main/java/nl/cwi/monetdb/jdbc/MonetDatabaseMetaData.java
Branch: default
Log Message:

Moved utility methods and associated caches from DatabaseMetaData to Connection 
object.
This allows the cached values to be shared across multiple DatabaseMetaData 
objects and
thereby reduce the number of queries sent to the server and the number of 
caches.
For instance SQuirreL instantiates many DatabaseMetaData objects and each time 
the caches
needed to be refilled by getting values from the server. This is now optimized.

Also made sure that in MonetConnection the internal queryTempl[] and 
commandTempl[] array
entries never contain null. This eleviates the need to test on null when 
composing
the marked-up command string which is sent to the server via mapi.


diffs (truncated from 607 to 300 lines):

diff --git a/src/main/java/nl/cwi/monetdb/jdbc/MonetConnection.java 
b/src/main/java/nl/cwi/monetdb/jdbc/MonetConnection.java
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetConnection.java
+++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetConnection.java
@@ -64,7 +64,7 @@ import nl.cwi.monetdb.mcl.parser.StartOf
  *
  * @author Fabian Groffen
  * @author Martin van Dinther
- * @version 1.4
+ * @version 1.5
  */
 public class MonetConnection
        extends MonetWrapper
@@ -121,7 +121,8 @@ public class MonetConnection
        private int curReplySize = -1;  // the server by default uses -1 (all)
 
        /** A template to apply to each query (like pre and post fixes), filled 
in constructor */
-       public final String[] queryTempl = new String[3]; // pre, post, sep
+       // note: it is made public to the package as it is used from 
MonetStatement
+       final String[] queryTempl = new String[3]; // pre, post, sep
 
        /** A template to apply to each command (like pre and post fixes), 
filled in constructor */
        private final String[] commandTempl = new String[3]; // pre, post, sep
@@ -140,14 +141,6 @@ public class MonetConnection
        /** Whether or not CLOB is mapped to Types.VARCHAR instead of 
Types.CLOB within this connection */
        private boolean treatClobAsVarChar = false;
 
-       // Internal cache for determining if system table sys.privilege_codes 
(new as of Jul2017 release) exists on server
-       private boolean queriedPrivilege_codesTable = false;
-       private boolean hasPrivilege_codesTable = false;
-
-       // Internal cache for determining if system table sys.comments (new as 
of Mar2018 release) exists on server
-       private boolean queriedCommentsTable = false;
-       private boolean hasCommentsTable = false;
-
        /** The last set query timeout on the server as used by Statement, 
PreparedStatement and CallableStatement */
        protected int lastSetQueryTimeout = 0;  // 0 means no timeout, which is 
the default on the server
 
@@ -326,18 +319,18 @@ public class MonetConnection
                        queryTempl[2] = "\n;\n";        // separator
 
                        commandTempl[0] = "X";          // pre
-                       commandTempl[1] = null;         // post
+                       commandTempl[1] = "";           // post
                        commandTempl[2] = "\nX";        // separator
                } else if ("mal".equals(language)) {
                        lang = LANG_MAL;
 
-                       queryTempl[0] = null;
-                       queryTempl[1] = ";\n";
-                       queryTempl[2] = ";\n";
+                       queryTempl[0] = "";             // pre
+                       queryTempl[1] = ";\n";          // post
+                       queryTempl[2] = ";\n";          // separator
 
-                       commandTempl[0] = null;         // pre
-                       commandTempl[1] = null;         // post
-                       commandTempl[2] = null;         // separator
+                       commandTempl[0] = "";           // pre
+                       commandTempl[1] = "";           // post
+                       commandTempl[2] = "";           // separator
                } else {
                        lang = LANG_UNKNOWN;
                }
@@ -1628,22 +1621,14 @@ public class MonetConnection
                }
        }
 
-
        //== end methods of interface java.sql.Connection
 
 
        /**
-        * @return the MonetDB JDBC Connection URL (without user name and 
password).
-        * Defined as public because it is called from: 
MonetDatabaseMetaData.java getURL()
-        */
-       String getJDBCURL() {
-               return MonetDriver.MONETURL + hostname + ":" + port + "/" + 
database + (lang == LANG_MAL ? "?language=mal" : "");
-       }
-
-       /**
         * @return whether the JDBC BLOB type should be mapped to VARBINARY 
type.
         * This allows generic JDBC programs to fetch Blob data via getBytes()
         * instead of getBlob() and Blob.getBinaryStream() to reduce overhead.
+        * It is called from: MonetResultSet and MonetPreparedStatement
         */
        boolean mapBlobAsVarBinary() {
                return treatBlobAsVarBinary;
@@ -1653,13 +1638,175 @@ public class MonetConnection
         * @return whether the JDBC CLOB type should be mapped to VARCHAR type.
         * This allows generic JDBC programs to fetch Clob data via getString()
         * instead of getClob() and Clob.getCharacterStream() to reduce 
overhead.
+        * It is called from: MonetResultSet and MonetPreparedStatement
         */
        boolean mapClobAsVarChar() {
                return treatClobAsVarChar;
        }
 
        /**
-        * Internal utility method to query the server to find out if it has
+        * @return the MonetDB JDBC Connection URL (without user name and 
password).
+        * It is called from: getURL()in MonetDatabaseMetaData
+        */
+       String getJDBCURL() {
+               final StringBuilder sb = new StringBuilder(128);
+               sb.append(MonetDriver.MONETURL).append(hostname)
+                       .append(':').append(port)
+                       .append('/').append(database);
+               if (lang == LANG_MAL)
+                       sb.append("?language=mal");
+               return sb.toString();
+       }
+
+       // Internal cache for 3 static mserver environment values, so they 
aren't queried from mserver again and again
+       private String env_current_user = null;
+       private String env_monet_version = null;
+       private String env_max_clients = null;
+
+       /**
+        * Utility method to fetch 3 mserver environment values combined in one 
query for efficiency.
+        * We currently fetch the env values of: current_user, monet_version 
and max_clients.
+        * We cache them such that we do not need to query the server again and 
again.
+        */
+       private synchronized void getEnvValues() throws SQLException {
+               Statement st = null;
+               ResultSet rs = null;
+               try {
+                       st = createStatement();
+                       if (st != null) {
+                               rs = st.executeQuery(
+                                       "SELECT \"name\", \"value\" FROM 
\"sys\".\"env\"()" +
+                                       " WHERE \"name\" IN ('monet_version', 
'max_clients')" +
+                                       " UNION SELECT 'current_user' as 
\"name\", current_user as \"value\"");
+                               if (rs != null) {
+                                       while (rs.next()) {
+                                               final String prop = 
rs.getString(1);
+                                               final String value = 
rs.getString(2);
+                                               if 
("current_user".equals(prop)) {
+                                                       env_current_user = 
value;
+                                               } else
+                                               if 
("monet_version".equals(prop)) {
+                                                       env_monet_version = 
value;
+                                               } else
+                                               if ("max_clients".equals(prop)) 
{
+                                                       env_max_clients = value;
+                                               }
+                                       }
+                               }
+                       }
+               /* do not catch SQLException here, as we need to know it when 
it fails */
+               } finally {
+                       closeResultsetStatement(rs, st);
+               }
+               // for debug: System.out.println("Read: env_current_user: " + 
env_current_user + "  env_monet_version: " + env_monet_version + "  
env_max_clients: " + env_max_clients);
+       }
+
+       /**
+        * @return the current User Name.
+        * It is called from: MonetDatabaseMetaData
+        */
+       String getUserName() throws SQLException {
+               if (env_current_user == null)
+                       getEnvValues();
+               return env_current_user;
+       }
+
+       /**
+        * @return the MonetDB Database Server version string.
+        * It is called from: MonetDatabaseMetaData
+        */
+       String getDatabaseProductVersion() throws SQLException {
+               if (env_monet_version == null)
+                       getEnvValues();
+               // always return a valid String to prevent NPE in getTables() 
and getTableTypes()
+               if (env_monet_version != null)
+                       return env_monet_version;
+               return "";
+       }
+
+       /**
+        * @return the MonetDB Database Server major version number.
+        * It is called from: MonetDatabaseMetaData
+        */
+       int getDatabaseMajorVersion() throws SQLException {
+               if (env_monet_version == null)
+                       getEnvValues();
+               if (env_monet_version != null) {
+                       try {
+                               // from version string such as 11.33.9 extract 
number: 11
+                               final int start = 
env_monet_version.indexOf('.');
+                               return Integer.parseInt((start >= 0) ? 
env_monet_version.substring(0, start) : env_monet_version);
+                       } catch (NumberFormatException nfe) {
+                               // ignore
+                       }
+               }
+               return 0;
+       }
+
+       /**
+        * @return the MonetDB Database Server minor version number.
+        * It is called from: MonetDatabaseMetaData
+        */
+       int getDatabaseMinorVersion() throws SQLException {
+               if (env_monet_version == null)
+                       getEnvValues();
+               if (env_monet_version != null) {
+                       try {
+                               // from version string such as 11.33.9 extract 
number: 33
+                               int start = env_monet_version.indexOf('.');
+                               if (start >= 0) {
+                                       start++;
+                                       final int end = 
env_monet_version.indexOf('.', start);
+                                       return Integer.parseInt((end > 0) ? 
env_monet_version.substring(start, end) : env_monet_version.substring(start));
+                               }
+                       } catch (NumberFormatException nfe) {
+                               // ignore
+                       }
+               }
+               return 0;
+       }
+
+       /**
+        * @return the maximum number of active connections possible at one 
time;
+        * a result of zero means that there is no limit or the limit is not 
known
+        * It is called from: MonetDatabaseMetaData
+        */
+       int getMaxConnections() throws SQLException {
+               if (env_max_clients == null)
+                       getEnvValues();
+               if (env_max_clients != null) {
+                       try {
+                               return Integer.parseInt(env_max_clients);
+                       } catch (NumberFormatException nfe) {
+                               /* ignore */
+                       }
+               }
+               return 0;
+       }
+
+
+       // Internal cache for determining if system table sys.privilege_codes 
(new as of Jul2017 release) exists on connected server
+       private boolean queriedPrivilege_codesTable = false;
+       private boolean hasPrivilege_codesTable = false;
+       /**
+        * Utility method to query the server to find out if it has
+        * the system table sys.privilege_codes (which is new as of Jul2017 
release).
+        * The result is cached and reused, so that we only test the query once 
per connection.
+        * This method is used by methods from MonetDatabaseMetaData.
+        */
+       boolean privilege_codesTableExists() {
+               if (!queriedPrivilege_codesTable) {
+                       hasPrivilege_codesTable = 
existsSysTable("privilege_codes");
+                       queriedPrivilege_codesTable = true;     // set flag, so 
the querying is done only at first invocation.
+               }
+               return hasPrivilege_codesTable;
+       }
+
+       // Internal cache for determining if system table sys.comments (new as 
of Mar2018 release) exists on connected server
+       private boolean queriedCommentsTable = false;
+       private boolean hasCommentsTable = false;
+       /**
+        * Utility method to query the server to find out if it has
         * the system table sys.comments (which is new as of Mar2018 release).
         * The result is cached and reused, so that we only test the query once 
per connection.
         * This method is used by methods from MonetDatabaseMetaData.
@@ -1672,22 +1819,9 @@ public class MonetConnection
                return hasCommentsTable;
        }
 
-       /**
-        * Internal utility method to query the server to find out if it has
-        * the system table sys.privilege_codes (which is new as of Jul2017 
release).
-        * The result is cached and reused, so that we only test the query once 
per connection.
-        * This method is used by methods from MonetDatabaseMetaData.
-        */
-       boolean privilege_codesTableExists() {
-               if (!queriedPrivilege_codesTable) {
-                       hasPrivilege_codesTable = 
existsSysTable("privilege_codes");
-                       queriedPrivilege_codesTable = true;     // set flag, so 
the querying is done only at first invocation.
-               }
-               return hasPrivilege_codesTable;
-       }
 
        /**
-        * Internal utility method to query the server to find out if it has 
the system table sys.<tablename>.
+        * Internal utility method to query the server to find out if it has a 
specific system table sys.<tablename>.
         */
        private boolean existsSysTable(final String tablename) {
                boolean exists = false;
@@ -1708,7 +1842,7 @@ public class MonetConnection
                } finally {
                        closeResultsetStatement(rs, stmt);
                }
-// for debug: System.out.println("testTableExists(" + tablename + ") returns: 
" + exists);
+               // for debug: System.out.println("testTableExists(" + tablename 
+ ") returns: " + exists);
                return exists;
        }
 
@@ -1780,20 +1914,17 @@ public class MonetConnection
        /**
         * Sends the given string to MonetDB as command/query using 
commandTempl or queryTempl
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to