Mercurial > hg > monetdb-java
changeset 195:89c285fc0a49 embedded
Merged with default
line wrap: on
line diff
--- a/.hgtags +++ b/.hgtags @@ -1,3 +1,4 @@ 80de05f07508fec938845b4a6e05f600bf0b48c0 v2.24 c43c293f3d5841517cbe0d858108c4da5fb1ec0c v2.26 a6a2f4ee2d42d7e192f9d8d37f79ea99178d7f2c v2.25 +fe8170e2b549c22ceb2d96301022b9304f62424d v2.27
--- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,37 @@ # ChangeLog file for monetdb-java # This file is updated with Maddlog +* Mon Oct 23 2017 Sjoerd Mullender <sjoerd@acm.org> +- Compiled and released new jars: monetdb-jdbc-2.27.jar, monetdb-mcl-1.16.jar + and updated jdbcclient.jar + +* Thu Oct 5 2017 Martin van Dinther <martin.van.dinther@monetdbsolutions.com> +- Corrected method Connection.prepareCall(). It used to return null. + Now it throws an SQLFeatureNotSupportedException to comply with the + JDBC specification. + +* Thu Sep 28 2017 Martin van Dinther <martin.van.dinther@monetdbsolutions.com> +- Added possibility to let the JDBC driver return columnType value + Types.VARCHAR instead of Types.CLOB in case the result column of a + ResultSet or parameter in a PreparedStatement is of data type 'clob'. + To enable this behavior provide it as JDBC connection URL property: + treat_clob_as_varchar=true + For example: jdbc:monetdb://localhost:50000/demo?treat_clob_as_varchar=true + See also: + https://www.monetdb.org/Documentation/Manuals/SQLreference/Programming/JDBC + This custom clob mapping informs generic JDBC programs to fetch clob + column values via method ResultSet.getString() instead of getClob() + and Clob.getCharacterStream() and next fetching from the stream. + As MonetDB server MAPI communication protocol does not support + streaming of parts of a CLOB value, the current implementation is to + send over the whole CLOB value as a string. Therefore there is no + performance gain when fetching those Clob values via getClob() and + getCharacterStream(). In fact it creates a lot of overhead (additional + objects and method calls) and triples the amount of needed Java Heap memory + for each Clob value! + With this connection property set, you can reduce this overhead when + working with clob column data from generic JDBC programs. + * Thu Sep 7 2017 Martin van Dinther <martin.van.dinther@monetdbsolutions.com> - Implemented PreparedStatement methods setNCharacterStream(int, Reader) and setNCharacterStream(int, Reader, long). @@ -15,8 +46,8 @@ - Implemented PreparedStatement method setURL(int, URL). - Implemented PreparedStatement method setNString(int, String). - The MonetDB JDBC driver code and jdbcclient program are now compiled - without debug info and with optimise flag enabled. The new jar files are - now smaller in size. + without debug info and with optimise flag enabled. + The new jar files are now some 20% smaller in size. * Thu Aug 17 2017 Martin van Dinther <martin.van.dinther@monetdbsolutions.com> - Implemented ResultSet method getNCharacterStream(). @@ -24,16 +55,7 @@ and getCharacterStream(long pos, long length). Method getCharacterStream() is called by DBeaver to fetch the Clob value. It used to throw a SQLFeatureNotSupportedException with message: - "Method getCharacterStream() currently not supported". This caused + "Operation getCharacterStream() currently not supported". This caused DBeaver to log the exception and show NULL as the value on screen, which is incorrect. This has been fixed. -* Fri Jul 28 2017 Sjoerd Mullender <sjoerd@acm.org> -- Compiled and released new jars: monetdb-jdbc-2.26.jar and updated jdbcclient.jar - -* Thu Jul 13 2017 Martin van Dinther <martin.van.dinther@monetdbsolutions.com> -- Corrected implementation of PreparedStatement method - setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength) - for the case the targetSqlType is Types.CLOB. - See also: https://www.monetdb.org/bugzilla/show_bug.cgi?id=6349 -
--- a/ChangeLog-Archive +++ b/ChangeLog-Archive @@ -1,6 +1,64 @@ # DO NOT EDIT THIS FILE -- MAINTAINED AUTOMATICALLY # This file contains past monetdb-java ChangeLog entries +* Mon Oct 23 2017 Sjoerd Mullender <sjoerd@acm.org> +- Compiled and released new jars: monetdb-jdbc-2.27.jar, monetdb-mcl-1.16.jar + and updated jdbcclient.jar + +* Thu Oct 5 2017 Martin van Dinther <martin.van.dinther@monetdbsolutions.com> +- Corrected method Connection.prepareCall(). It used to return null. + Now it throws an SQLFeatureNotSupportedException to comply with the + JDBC specification. + +* Thu Sep 28 2017 Martin van Dinther <martin.van.dinther@monetdbsolutions.com> +- Added possibility to let the JDBC driver return columnType value + Types.VARCHAR instead of Types.CLOB in case the result column of a + ResultSet or parameter in a PreparedStatement is of data type 'clob'. + To enable this behavior provide it as JDBC connection URL property: + treat_clob_as_varchar=true + For example: jdbc:monetdb://localhost:50000/demo?treat_clob_as_varchar=true + See also: + https://www.monetdb.org/Documentation/Manuals/SQLreference/Programming/JDBC + This custom clob mapping informs generic JDBC programs to fetch clob + column values via method ResultSet.getString() instead of getClob() + and Clob.getCharacterStream() and next fetching from the stream. + As MonetDB server MAPI communication protocol does not support + streaming of parts of a CLOB value, the current implementation is to + send over the whole CLOB value as a string. Therefore there is no + performance gain when fetching those Clob values via getClob() and + getCharacterStream(). In fact it creates a lot of overhead (additional + objects and method calls) and triples the amount of needed Java Heap memory + for each Clob value! + With this connection property set, you can reduce this overhead when + working with clob column data from generic JDBC programs. + +* Thu Sep 7 2017 Martin van Dinther <martin.van.dinther@monetdbsolutions.com> +- Implemented PreparedStatement methods setNCharacterStream(int, Reader) + and setNCharacterStream(int, Reader, long). + +* Thu Aug 31 2017 Martin van Dinther <martin.van.dinther@monetdbsolutions.com> +- Corrected PreparedStatement methods setString(int, String) + and setObject(int, Object, ...) in case the target parameter + data type was json or inet or url or uuid. See also + https://www.monetdb.org/bugzilla/show_bug.cgi?id=6382 + +* Thu Aug 24 2017 Martin van Dinther <martin.van.dinther@monetdbsolutions.com> +- Implemented PreparedStatement method setURL(int, URL). +- Implemented PreparedStatement method setNString(int, String). +- The MonetDB JDBC driver code and jdbcclient program are now compiled + without debug info and with optimise flag enabled. + The new jar files are now some 20% smaller in size. + +* Thu Aug 17 2017 Martin van Dinther <martin.van.dinther@monetdbsolutions.com> +- Implemented ResultSet method getNCharacterStream(). +- In class MonetClob implemented methods getCharacterStream() + and getCharacterStream(long pos, long length). Method + getCharacterStream() is called by DBeaver to fetch the Clob value. + It used to throw a SQLFeatureNotSupportedException with message: + "Operation getCharacterStream() currently not supported". This caused + DBeaver to log the exception and show NULL as the value on screen, + which is incorrect. This has been fixed. + * Fri Jul 28 2017 Sjoerd Mullender <sjoerd@acm.org> - Compiled and released new jars: monetdb-jdbc-2.26.jar and updated jdbcclient.jar
--- a/Makefile +++ b/Makefile @@ -5,6 +5,9 @@ all: src/main/java/nl/cwi/monetdb/jdbc/M src/main/java/nl/cwi/monetdb/jdbc/MonetDriver.java: build.properties src/main/java/nl/cwi/monetdb/jdbc/MonetDriver.java.in . ./build.properties; sed -e "s/@MCL_MAJOR@/$$MCL_MAJOR/g;s/@MCL_MINOR@/$$MCL_MINOR/g;s/@JDBC_MAJOR@/$$JDBC_MAJOR/g;s/@JDBC_MINOR@/$$JDBC_MINOR/g;s/@JDBC_VER_SUFFIX@/$$JDBC_VER_SUFFIX $$buildno/g;s/@JDBC_DEF_PORT@/$$JDBC_DEF_PORT/g" src/main/java/nl/cwi/monetdb/jdbc/MonetDriver.java.in > src/main/java/nl/cwi/monetdb/jdbc/MonetDriver.java +doc: + ant -f build.xml doc + clean: rm -f src/main/java/nl/cwi/monetdb/jdbc/MonetDriver.java - rm -rf build tests/build jars + rm -rf build tests/build jars doc
--- a/build.xml +++ b/build.xml @@ -11,8 +11,7 @@ Copyright 1997 - July 2008 CWI, August 2 <!-- Build file to allow ant (http://jakarta.apache.org/ant/) to be used - to build the MonetDB Java libraries, such as the JDBC and XML:DB - drivers. + to build the MonetDB Java packages, such as the JDBC driver. --> @@ -32,12 +31,16 @@ Copyright 1997 - July 2008 CWI, August 2 <property file="build.properties" /> - <property name="jdbc-jar" value="${jardir}/monetdb-jdbc-new-${JDBC_MAJOR}.${JDBC_MINOR}.jar" /> - <property name="jdbcclient-jar" value="${jardir}/jdbcclient.jar" /> - <property name="jmonetdb-jar" value="${jardir}/jmonetdb.jar" /> - <property name="mcl-jar" value="${jardir}/monetdb-mcl-${MCL_MAJOR}.${MCL_MINOR}.jar" /> - - <property name="mero-control-jar" value="${jardir}/merocontrol.jar" /> + <property name="jdbc-jar" + value="${jardir}/monetdb-jdbc-new-${JDBC_MAJOR}.${JDBC_MINOR}.jar" /> + <property name="jdbcclient-jar" + value="${jardir}/jdbcclient.jar" /> + <property name="jmonetdb-jar" + value="${jardir}/jmonetdb.jar" /> + <property name="mcl-jar" + value="${jardir}/monetdb-mcl-${MCL_MAJOR}.${MCL_MINOR}.jar" /> + <property name="mero-control-jar" + value="${jardir}/merocontrol.jar" /> <!-- @@ -57,9 +60,7 @@ Copyright 1997 - July 2008 CWI, August 2 <!-- full target --> <target name="all"> <antcall target="distjdbc" /> - <antcall target="distmerocontrol" /> - <antcall target="doc" /> </target> @@ -113,11 +114,11 @@ Copyright 1997 - July 2008 CWI, August 2 </jar> </target> - <!-- a convenience jar of JDBC plus the JdbcClient utililty --> + <!-- a convenience jar of jdbcclient command line program plus JDBC driver --> <target name="jar_jdbcclient" depends="compile_mcl,compile_jdbc,compile_util,compile_client" unless="uptodate.jdbcclient-jar"> - <echo message="Building JDBC + JdbcClient convenience jar" /> + <echo message="Building jdbcclient + JDBC driver convenience jar" /> <jar jarfile="${jdbcclient-jar}"> <fileset dir="${builddir}"> <include name="${jdbc-package}/**/*.class" /> @@ -251,8 +252,8 @@ Copyright 1997 - July 2008 CWI, August 2 </target> <!-- - This generates MonetDriver.java.in from its ".java.in" equivalents. It's - required for importing the driver version properties. + This generates MonetDriver.java from its ".java.in" equivalent. + It's required for importing the driver version properties. --> <target name="driver" depends="prepare" unless="uptodate.drivers"> <tstamp> @@ -349,7 +350,7 @@ Copyright 1997 - July 2008 CWI, August 2 <!-- documentation target --> <target name="doc" - depends="compile_mcl,compile_jdbc,compile_util,compile_client,compile_mero_control"> + depends="driver"> <javadoc destdir="${docdir}" author="true" @@ -364,14 +365,6 @@ Copyright 1997 - July 2008 CWI, August 2 <include name="${util-package}/**/*.java" /> <include name="${mero-control-package}/**/*.java" /> </fileset> - - <fileset dir="${builddir}/src" defaultexcludes="yes"> - <include name="${jdbc-package}/**/*.java" /> - <include name="${mcl-package}/**/*.java" /> - <include name="${client-package}/**/*.java" /> - <include name="${util-package}/**/*.java" /> - <include name="${mero-control-package}/**/*.java" /> - </fileset> </javadoc> </target>
--- a/pom.xml +++ b/pom.xml @@ -1,141 +1,141 @@ <?xml version="1.0" encoding="UTF-8"?> <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> - <modelVersion>4.0.0</modelVersion> + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <modelVersion>4.0.0</modelVersion> - <groupId>monetdb</groupId> - <artifactId>monetdb-jdbc-new</artifactId> - <version>2.32</version> - <name>MonetDB JDBC new</name> - <description>MonetDB Adapted JDBC driver for embedded connection</description> - <url>https://www.monetdb.org</url> + <groupId>monetdb</groupId> + <artifactId>monetdb-jdbc-new</artifactId> + <version>2.32</version> + <name>MonetDB JDBC new</name> + <description>MonetDB Adapted JDBC driver for embedded connection</description> + <url>https://www.monetdb.org</url> - <licenses> - <license> - <name>Mozilla Public License, Version 2.0</name> - <url>https://www.mozilla.org/MPL/2.0/</url> - </license> - </licenses> + <licenses> + <license> + <name>Mozilla Public License, Version 2.0</name> + <url>https://www.mozilla.org/MPL/2.0/</url> + </license> + </licenses> - <developers> - <developer> - <name>Pedro Ferreira</name> - <email>pedro.ferreira@monetdbsolutions.com</email> - <organization>MonetDB</organization> - <organizationUrl>https://www.monetdb.org</organizationUrl> - </developer> - </developers> + <developers> + <developer> + <name>Pedro Ferreira</name> + <email>pedro.ferreira@monetdbsolutions.com</email> + <organization>MonetDB</organization> + <organizationUrl>https://www.monetdb.org</organizationUrl> + </developer> + </developers> - <distributionManagement> - <snapshotRepository> - <id>ossrh</id> - <url>https://oss.sonatype.org/content/repositories/snapshots</url> - </snapshotRepository> - <repository> - <id>ossrh</id> - <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url> - </repository> - </distributionManagement> + <distributionManagement> + <snapshotRepository> + <id>ossrh</id> + <url>https://oss.sonatype.org/content/repositories/snapshots</url> + </snapshotRepository> + <repository> + <id>ossrh</id> + <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url> + </repository> + </distributionManagement> - <scm> - <connection>scm:hg:https://dev.monetdb.org/hg/monetdb-java/</connection> - <developerConnection>scm:hg:ssh://hg@dev.monetdb.org/monetdb-java/</developerConnection> - <url>https://dev.monetdb.org/hg/monetdb-java/</url> - </scm> + <scm> + <connection>scm:hg:https://dev.monetdb.org/hg/monetdb-java/</connection> + <developerConnection>scm:hg:ssh://hg@dev.monetdb.org/monetdb-java/</developerConnection> + <url>https://dev.monetdb.org/hg/monetdb-java/</url> + </scm> - <properties> - <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> - <jdbc.sources>nl/cwi/monetdb/jdbc/**/*.java</jdbc.sources> - </properties> + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <jdbc.sources>nl/cwi/monetdb/jdbc/**/*.java</jdbc.sources> + </properties> - <build> - <plugins> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-compiler-plugin</artifactId> - <version>3.6.1</version> - <configuration> - <includes> - <include>${jdbc.sources}</include> - </includes> - <source>1.7</source> - <target>1.7</target> - </configuration> - </plugin> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-source-plugin</artifactId> - <version>3.0.1</version> - <executions> - <execution> - <id>attach-sources</id> - <goals> - <goal>jar-no-fork</goal> - </goals> - </execution> - </executions> - <configuration> - <includes> - <include>${jdbc.sources}</include> - </includes> - </configuration> - </plugin> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-javadoc-plugin</artifactId> - <version>2.10.4</version> - <executions> - <execution> - <id>attach-javadocs</id> - <goals> - <goal>jar</goal> - </goals> - </execution> - </executions> - <configuration> - <sourceFileIncludes> - <include>${jdbc.sources}</include> - </sourceFileIncludes> - <additionalparam>-Xdoclint:none</additionalparam> - </configuration> - </plugin> - <plugin> - <groupId>org.sonatype.plugins</groupId> - <artifactId>nexus-staging-maven-plugin</artifactId> - <version>1.6.8</version> - <extensions>true</extensions> - <configuration> - <serverId>ossrh</serverId> - <nexusUrl>https://oss.sonatype.org/</nexusUrl> - <autoReleaseAfterClose>true</autoReleaseAfterClose> - </configuration> - </plugin> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-release-plugin</artifactId> - <version>2.5.3</version> - <configuration> - <autoVersionSubmodules>true</autoVersionSubmodules> - <useReleaseProfile>false</useReleaseProfile> - <releaseProfiles>release</releaseProfiles> - <goals>deploy</goals> - </configuration> - </plugin> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-gpg-plugin</artifactId> - <version>1.6</version> - <executions> - <execution> - <id>sign-artifacts</id> - <phase>verify</phase> - <goals> - <goal>sign</goal> - </goals> - </execution> - </executions> - </plugin> - </plugins> - </build> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.6.1</version> + <configuration> + <includes> + <include>${jdbc.sources}</include> + </includes> + <source>1.7</source> + <target>1.7</target> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-source-plugin</artifactId> + <version>3.0.1</version> + <executions> + <execution> + <id>attach-sources</id> + <goals> + <goal>jar-no-fork</goal> + </goals> + </execution> + </executions> + <configuration> + <includes> + <include>${jdbc.sources}</include> + </includes> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-javadoc-plugin</artifactId> + <version>2.10.4</version> + <executions> + <execution> + <id>attach-javadocs</id> + <goals> + <goal>jar</goal> + </goals> + </execution> + </executions> + <configuration> + <sourceFileIncludes> + <include>${jdbc.sources}</include> + </sourceFileIncludes> + <additionalparam>-Xdoclint:none</additionalparam> + </configuration> + </plugin> + <plugin> + <groupId>org.sonatype.plugins</groupId> + <artifactId>nexus-staging-maven-plugin</artifactId> + <version>1.6.8</version> + <extensions>true</extensions> + <configuration> + <serverId>ossrh</serverId> + <nexusUrl>https://oss.sonatype.org/</nexusUrl> + <autoReleaseAfterClose>true</autoReleaseAfterClose> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-release-plugin</artifactId> + <version>2.5.3</version> + <configuration> + <autoVersionSubmodules>true</autoVersionSubmodules> + <useReleaseProfile>false</useReleaseProfile> + <releaseProfiles>release</releaseProfiles> + <goals>deploy</goals> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-gpg-plugin</artifactId> + <version>1.6</version> + <executions> + <execution> + <id>sign-artifacts</id> + <phase>verify</phase> + <goals> + <goal>sign</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> </project>
--- a/release.txt +++ b/release.txt @@ -1,11 +1,36 @@ RELEASE NOTES -MonetDB JDBC driver version 2.26 (Liberica/MCL-1.15) -Release date: 2017-07-28 +MonetDB JDBC driver version 2.27 (Liberica/MCL-1.16) +Release date: 2017-10-23 + +This JDBC driver is designed for use with MonetDB, a main-memory column-store RDBMS. +For more information see https://www.monetdb.org/ + +The MonetDB JDBC connection URL format to use is: + jdbc:monetdb://<hostname>[:<portnr>]/<databasename>[?<property>=<value>[&<property>=<value>]] + +Note: For a successful connection the database name part must be provided + and be equal to the name of the database served by the mserver5 process running on + the specified host and listening to the specified port number (default port is 50000). -This JDBC driver is designed for use with MonetDB, a main-memory -database. For more information see https://www.monetdb.org/. +Supported connection properties are: + user=<login name> + password=<secret value> + so_timeout=<time in milliseconds> + hash=<SHA512, SHA384, SHA256, SHA1 and MD5> + language=<sql or mal> default is: sql + treat_blob_as_binary=true default is: false + treat_clob_as_varchar=true default is: false + debug=true default is: false + logfile=<name of logfile> -The JDBC driver complies to JDBC 4.1 definition, see +For example: + jdbc:monetdb://localhost:41000/mydb?user=monetdb&password=monetdb&so_timeout=7000&treat_clob_as_varchar=true + +See also: https://www.monetdb.org/Documentation/Manuals/SQLreference/Programming/JDBC + + +JDBC COMPLIANCE +The MonetDB 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
--- a/src/main/java/nl/cwi/monetdb/client/JdbcClient.java +++ b/src/main/java/nl/cwi/monetdb/client/JdbcClient.java @@ -531,6 +531,7 @@ public final class JdbcClient { * * @param hasFile a boolean indicating whether a file is used as input * @param doEcho a boolean indicating whether to echo the given input + * @param scolonterm whether a ';' makes this query part complete * @param user a String representing the username of the current user * @throws IOException if an IO exception occurs * @throws SQLException if a database related error occurs
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetConnection.java +++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetConnection.java @@ -84,10 +84,10 @@ public abstract class MonetConnection ex private Map<Statement,?> statements = new WeakHashMap<>(); /** The number of results we receive from the server at once */ private int curReplySize = -1; // the server by default uses -1 (all) - /** Whether or not BLOB is mapped to LONGVARBINARY within the driver */ - private final boolean blobIsBinary; - /** Whether or not CLOB is mapped to LONGVARCHAR within the driver */ - private final boolean clobIsLongChar; + /** Whether or not BLOB is mapped to Types.VARBINARY instead of Types.BLOB within this connection */ + private final boolean treatBlobAsVarBinary; + /** Whether or not CLOB is mapped to Types.VARCHAR instead of Types.CLOB within this connection */ + private final boolean treatClobAsVarChar; /** The underlying proticol provided by the connection (MAPI or embedded) */ protected AbstractProtocol protocol; /** Tells if the connection is embedded or not */ @@ -103,8 +103,8 @@ public abstract class MonetConnection ex this.conn_props = props; this.hash = hash; this.language = language; - this.blobIsBinary = blobIsBinary; - this.clobIsLongChar = clobIsLongChar; + this.treatBlobAsVarBinary = blobIsBinary; + this.treatClobAsVarChar = clobIsLongChar; //"instance of" should be cleanner, but this is faster. this.isEmbedded = props.getProperty("embedded", "false").equals("true"); } @@ -373,6 +373,7 @@ public abstract class MonetConnection ex * Retrieves the current holdability of ResultSet objects created using this Connection object. * * @return the holdability, one of ResultSet.HOLD_CURSORS_OVER_COMMIT or ResultSet.CLOSE_CURSORS_AT_COMMIT + * @see #setHoldability(int) */ @Override public int getHoldability() { @@ -475,6 +476,16 @@ public abstract class MonetConnection ex return false; } + /** + * Converts the given SQL statement into the system's native SQL grammar. + * A driver may convert the JDBC SQL grammar into its system's native SQL grammar prior to sending it. + * This method returns the native form of the statement that the driver would have sent. + * + * Parameters: + * sql - an SQL statement that may contain one or more '?' parameter placeholders. + * Returns: the native form of this statement + * Throws: SQLException - if a database access error occurs or this method is called on a closed connection + */ @Override public String nativeSQL(String sql) { /* there is currently no way to get the native MonetDB rewritten SQL string back, so just return the original string */ @@ -482,22 +493,77 @@ public abstract class MonetConnection ex return sql; } + /** + * Creates a CallableStatement object for calling database stored procedures. + * The CallableStatement object provides methods for setting up its IN and OUT parameters, + * and methods for executing the call to a stored procedure. + * + * Note: This method is optimized for handling stored procedure call statements. + * Some drivers may send the call statement to the database when the method prepareCall is done; + * others may wait until the CallableStatement object is executed. This has no direct effect + * on users; however, it does affect which method throws certain SQLExceptions. + * + * Result sets created using the returned CallableStatement object will by default be type TYPE_FORWARD_ONLY + * and have a concurrency level of CONCUR_READ_ONLY. + * The holdability of the created result sets can be determined by calling getHoldability(). + * + * Parameters: + * sql - an SQL statement that may contain one or more '?' parameter placeholders. + * Typically this statement is specified using JDBC call escape syntax. + * Returns: a new default CallableStatement object containing the pre-compiled SQL statement + * Throws: SQLException - if a database access error occurs or this method is called on a closed connection + */ @Override - public CallableStatement prepareCall(String sql) { - /* not implemented yet */ - return null; + public CallableStatement prepareCall(String sql) throws SQLException { + return prepareCall(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT); } + /** + * Creates a CallableStatement object that will generate ResultSet objects with the given type and concurrency. + * This method is the same as the prepareCall method above, but it allows the default result set type and concurrency to be overridden. + * The holdability of the created result sets can be determined by calling getHoldability(). + * + * Parameters: + * sql - a String object that is the SQL statement to be sent to the database; may contain on or more '?' parameters + * Typically this statement is specified using JDBC call escape syntax. + * resultSetType - a result set type; one of ResultSet.TYPE_FORWARD_ONLY, ResultSet.TYPE_SCROLL_INSENSITIVE, or ResultSet.TYPE_SCROLL_SENSITIVE + * resultSetConcurrency - a concurrency type; one of ResultSet.CONCUR_READ_ONLY or ResultSet.CONCUR_UPDATABLE + * Returns: a new CallableStatement object containing the pre-compiled SQL statement that + * will produce ResultSet objects with the given type and concurrency + * Throws: + * SQLException - if a database access error occurs, this method is called on a closed connection or + * the given parameters are not ResultSet constants indicating type and concurrency + * SQLFeatureNotSupportedException - if the JDBC driver does not support this method or + * this method is not supported for the specified result set type and result set concurrency. + */ @Override - public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) { - /* not implemented yet */ - return null; + public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { + return prepareCall(sql, resultSetType, resultSetConcurrency, ResultSet.HOLD_CURSORS_OVER_COMMIT); } + /** + * Creates a CallableStatement object that will generate ResultSet objects with the given type and concurrency. + * This method is the same as the prepareCall method above, but it allows the default result set type, result set concurrency type and holdability to be overridden. + * + * Parameters: + * sql - a String object that is the SQL statement to be sent to the database; may contain on or more '?' parameters + * Typically this statement is specified using JDBC call escape syntax. + * resultSetType - a result set type; one of ResultSet.TYPE_FORWARD_ONLY, ResultSet.TYPE_SCROLL_INSENSITIVE, or ResultSet.TYPE_SCROLL_SENSITIVE + * resultSetConcurrency - a concurrency type; one of ResultSet.CONCUR_READ_ONLY or ResultSet.CONCUR_UPDATABLE + * resultSetHoldability - one of the following ResultSet constants: ResultSet.HOLD_CURSORS_OVER_COMMIT or ResultSet.CLOSE_CURSORS_AT_COMMIT + * Returns: a new CallableStatement object, containing the pre-compiled SQL statement, that will generate ResultSet objects with the given type, concurrency, and holdability + * Throws: + * SQLException - if a database access error occurs, this method is called on a closed connection or + * the given parameters are not ResultSet constants indicating type, concurrency, and holdability + * SQLFeatureNotSupportedException - if the JDBC driver does not support this method or + * this method is not supported for the specified result set type, result set holdability and result set concurrency. + */ @Override - public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) { - /* not implemented yet */ - return null; + public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) + throws SQLException + { + throw new SQLFeatureNotSupportedException("prepareCall() not yet supported", "0A000"); + /* a request to implement prepareCall() has already been logged, see https://www.monetdb.org/bugzilla/show_bug.cgi?id=6402 */ } /** @@ -1104,7 +1170,11 @@ public abstract class MonetConnection ex } } catch (SQLException se) { String msg = se.getMessage(); - if (msg != null && msg.equals("Current transaction is aborted (please ROLLBACK)")) { + // System.out.println(se.getSQLState() + " Con.isValid(): " + msg); + if (msg != null && msg.equalsIgnoreCase("Current transaction is aborted (please ROLLBACK)")) { + // Must use equalsIgnoreCase() here because up to Jul2017 release 'Current' was 'current' so with lowercase c. + // It changed to 'Current' after Jul2017 release. We need to support all server versions. + // SQLState = 25005 isValid = true; } /* ignore stmt errors/exceptions, we are only testing if the connection is still alive and usable */ @@ -1201,7 +1271,7 @@ public abstract class MonetConnection ex * @since 1.6 */ @Override - public void setClientInfo(String name, String value) throws java.sql.SQLClientInfoException { + public void setClientInfo(String name, String value) throws SQLClientInfoException { if (name == null || name.isEmpty()) { addWarning("setClientInfo: missing property name", "01M07"); return; @@ -1213,10 +1283,19 @@ public abstract class MonetConnection ex 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("hash") || name.equals("treat_blob_as_binary") || name.equals("follow_redirects") || - name.equals("treat_clob_as_longvarchar") || name.equals("embedded") || name.equals("directory")) { + 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("hash") || + name.equals("treat_blob_as_binary") || + name.equals("treat_clob_as_varchar") || + name.equals("embedded") || + name.equals("directory")) + { conn_props.setProperty(name, value); } else { addWarning("setClientInfo: " + name + "is not a recognised property", "01M07"); @@ -1247,7 +1326,7 @@ public abstract class MonetConnection ex * @since 1.6 */ @Override - public void setClientInfo(Properties props) throws java.sql.SQLClientInfoException { + public void setClientInfo(Properties props) throws SQLClientInfoException { if (props != null) { for (Map.Entry<Object, Object> entry : props.entrySet()) { setClientInfo(entry.getKey().toString(), entry.getValue().toString()); @@ -1385,20 +1464,24 @@ public abstract class MonetConnection ex } } - //== end methods of interface Connection + //== end methods of interface java.sql.Connection /** - * Returns whether the BLOB type should be mapped to BINARY type. + * @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. */ - public boolean getBlobAsBinary() { - return blobIsBinary; + public boolean mapBlobAsVarBinary() { + return treatBlobAsVarBinary; } /** - * Returns whether the CLOB type should be mapped to LONGVARCHAR type. + * @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. */ - public boolean getClobAsLongChar() { - return clobIsLongChar; + public boolean mapClobAsVarChar() { + return treatClobAsVarChar; } /** @@ -1451,10 +1534,11 @@ public abstract class MonetConnection ex * @param reason the warning message */ void addWarning(String reason, String sqlstate) { + SQLWarning warng = new SQLWarning(reason, sqlstate); if (warnings == null) { - warnings = new SQLWarning(reason, sqlstate); + warnings = warng; } else { - warnings.setNextWarning(new SQLWarning(reason, sqlstate)); + warnings.setNextWarning(warng); } } @@ -1463,7 +1547,6 @@ public abstract class MonetConnection ex * left as responsibility to the caller to prevent concurrent access. */ public class ResponseList { - /** The cache size (number of rows in a DataBlockResponse object) */ private final int cachesize; /** The maximum number of results for this query */
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetDatabaseMetaData.java +++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetDatabaseMetaData.java @@ -17,6 +17,8 @@ import java.sql.ResultSetMetaData; import java.sql.RowIdLifetime; import java.sql.Types; +import java.util.ArrayList; + /** * A DatabaseMetaData object suitable for the MonetDB database. * @@ -87,7 +89,7 @@ public class MonetDatabaseMetaData exten * we set it to close (and free server resources) when the ResultSet object is closed by the caller. */ private ResultSet executeMetaDataQuery(String query) throws SQLException { - Statement stmt; + Statement stmt = null; ResultSet rs = null; stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); if (stmt != null) { @@ -180,6 +182,8 @@ public class MonetDatabaseMetaData exten * By contrast, the method nullsAreSortedAtStart indicates whether NULL values are sorted at the beginning regardless of sort order. * * @return true because MonetDB shows NULL values at the beginning upon ORDER BY .. ASC + * + * @return negative of nullsAreSortedHigh() * @see #nullsAreSortedHigh() */ @Override @@ -473,12 +477,12 @@ public class MonetDatabaseMetaData exten } // SQL query parts shared by four get<Type>Functions() below - private final static String FunctionsSelect = "SELECT DISTINCT \"name\" FROM \"sys\".\"functions\" "; - private final static String FunctionsWhere = "WHERE \"id\" IN (SELECT \"func_id\" FROM \"sys\".\"args\" WHERE \"number\" = 1 AND \"name\" = 'arg_1' AND \"type\" IN "; + private static final String FunctionsSelect = "SELECT DISTINCT \"name\" FROM \"sys\".\"functions\" "; + private static final String FunctionsWhere = "WHERE \"id\" IN (SELECT \"func_id\" FROM \"sys\".\"args\" WHERE \"number\" = 1 AND \"name\" = 'arg_1' AND \"type\" IN "; // Scalar functions sql_max(x, y) and sql_min(x, y) are defined in sys.args only for type 'any'. // Easiest way to include them in the Num, Str and TimeDate lists is to add them explicitly via UNION SQL: - private final static String AddFunctionsMaxMin = " UNION SELECT 'sql_max' UNION SELECT 'sql_min'"; - private final static String FunctionsOrderBy1 = " ORDER BY 1"; + private static final String AddFunctionsMaxMin = " UNION SELECT 'sql_max' UNION SELECT 'sql_min'"; + private static final String FunctionsOrderBy1 = " ORDER BY 1"; @Override public String getNumericFunctions() { @@ -536,12 +540,12 @@ public class MonetDatabaseMetaData exten /** * Get all the "extra" characters that can be used in unquoted * identifier names (those beyond a-zA-Z0-9 and _) - * MonetDB has no extra characters (verified it for chars: !@#$%^&*()~{}[]? * * @return a string containing the extra characters */ @Override public String getExtraNameCharacters() { + // MonetDB has no extra characters. Verified it for chars: !@#$%^&*()~{}[]? return ""; } @@ -1629,7 +1633,7 @@ public class MonetDatabaseMetaData exten * Does a data definition statement within a transaction force * the transaction to commit? I think this means something like: * - * <p><pre> + * <pre> * CREATE TABLE T (A INT); * INSERT INTO T (A) VALUES (2); * BEGIN; @@ -1637,7 +1641,7 @@ public class MonetDatabaseMetaData exten * CREATE TABLE X (A INT); * SELECT A FROM T INTO X; * COMMIT; - * </pre></p> + * </pre> * * does the CREATE TABLE call cause a commit? The answer is no. * @@ -1667,21 +1671,21 @@ public class MonetDatabaseMetaData exten * * <p>Each procedure description has the following columns: * <ol> - * <li><b>PROCEDURE_CAT</b> String => procedure catalog (may be null) - * <li><b>PROCEDURE_SCHEM</b> String => procedure schema (may be null) - * <li><b>PROCEDURE_NAME</b> String => procedure name + * <li><b>PROCEDURE_CAT</b> String => procedure catalog (may be null) + * <li><b>PROCEDURE_SCHEM</b> String => procedure schema (may be null) + * <li><b>PROCEDURE_NAME</b> String => procedure name * <li><b>Field4</b> reserved (make it null) * <li><b>Field5</b> reserved (make it null) * <li><b>Field6</b> reserved (make it null) - * <li><b>REMARKS</b> String => explanatory comment on the procedure - * <li><b>PROCEDURE_TYPE</b> short => kind of procedure + * <li><b>REMARKS</b> String => explanatory comment on the procedure + * <li><b>PROCEDURE_TYPE</b> short => kind of procedure * <ul> * <li> procedureResultUnknown - May return a result * <li> procedureNoResult - Does not return a result * <li> procedureReturnsResult - Returns a result * </ul> + * <li><b>SPECIFIC_NAME</b> String => The name which uniquely identifies this procedure within its schema. * </ol> - * <li><b>SPECIFIC_NAME</b> String => The name which uniquely identifies this procedure within its schema. * * @param catalog - a catalog name; must match the catalog name as it is stored in the database; * "" retrieves those without a catalog; @@ -1694,8 +1698,12 @@ public class MonetDatabaseMetaData exten * @throws SQLException if a database access error occurs */ @Override - public ResultSet getProcedures(String catalog, String schemaPattern, String procedureNamePattern) - throws SQLException { + public ResultSet getProcedures( + String catalog, + String schemaPattern, + String procedureNamePattern + ) throws SQLException + { StringBuilder query = new StringBuilder(980); query.append("SELECT cast(null as varchar(1)) AS \"PROCEDURE_CAT\", " + "\"schemas\".\"name\" AS \"PROCEDURE_SCHEM\", " + @@ -1742,11 +1750,11 @@ public class MonetDatabaseMetaData exten * <p>Each row in the ResultSet is a parameter description or column * description with the following fields: * <ol> - * <li><b>PROCEDURE_CAT</b> String => procedure catalog (may be null) - * <li><b>PROCEDURE_SCHEM</b> String => procedure schema (may be null) - * <li><b>PROCEDURE_NAME</b> String => procedure name - * <li><b>COLUMN_NAME</b> String => column/parameter name - * <li><b>COLUMN_TYPE</b> Short => kind of column/parameter: + * <li><b>PROCEDURE_CAT</b> String => procedure catalog (may be null) + * <li><b>PROCEDURE_SCHEM</b> String => procedure schema (may be null) + * <li><b>PROCEDURE_NAME</b> String => procedure name + * <li><b>COLUMN_NAME</b> String => column/parameter name + * <li><b>COLUMN_TYPE</b> Short => kind of column/parameter: * <ul><li>procedureColumnUnknown - nobody knows * <li>procedureColumnIn - IN parameter * <li>procedureColumnInOut - INOUT parameter @@ -1754,34 +1762,34 @@ public class MonetDatabaseMetaData exten * <li>procedureColumnReturn - procedure return value * <li>procedureColumnResult - result column in ResultSet * </ul> - * <li><b>DATA_TYPE</b> int => SQL type from java.sql.Types - * <li><b>TYPE_NAME</b> String => SQL type name, for a UDT type the type name is fully qualified - * <li><b>PRECISION</b> int => precision - * <li><b>LENGTH</b> int => length in bytes of data - * <li><b>SCALE</b> short => scale - null is returned for data types where SCALE is not applicable. - * <li><b>RADIX</b> short => radix - * <li><b>NULLABLE</b> short => can it contain NULL? + * <li><b>DATA_TYPE</b> int => SQL type from java.sql.Types + * <li><b>TYPE_NAME</b> String => SQL type name, for a UDT type the type name is fully qualified + * <li><b>PRECISION</b> int => precision + * <li><b>LENGTH</b> int => length in bytes of data + * <li><b>SCALE</b> short => scale - null is returned for data types where SCALE is not applicable. + * <li><b>RADIX</b> short => radix + * <li><b>NULLABLE</b> short => can it contain NULL? * <ul><li>procedureNoNulls - does not allow NULL values * <li>procedureNullable - allows NULL values * <li>procedureNullableUnknown - nullability unknown * </ul> - * <li><b>REMARKS</b> String => comment describing parameter/column - * <li><b>COLUMN_DEF</b> String => default value for the column, which should be interpreted as a string when the value is enclosed in single quotes (may be null) + * <li><b>REMARKS</b> String => comment describing parameter/column + * <li><b>COLUMN_DEF</b> String => default value for the column, which should be interpreted as a string when the value is enclosed in single quotes (may be null) * The string NULL (not enclosed in quotes) - if NULL was specified as the default value * TRUNCATE (not enclosed in quotes) - if the specified default value cannot be represented without truncation * NULL - if a default value was not specified - * <li><b>SQL_DATA_TYPE</b> int => reserved for future use - * <li><b>SQL_DATETIME_SUB</b> int => reserved for future use - * <li><b>CHAR_OCTET_LENGTH</b> int => the maximum length of binary and character based columns. For any other datatype the returned value is a NULL - * <li><b>ORDINAL_POSITION</b> int => the ordinal position, starting from 1, for the input and output parameters for a procedure. + * <li><b>SQL_DATA_TYPE</b> int => reserved for future use + * <li><b>SQL_DATETIME_SUB</b> int => reserved for future use + * <li><b>CHAR_OCTET_LENGTH</b> int => the maximum length of binary and character based columns. For any other datatype the returned value is a NULL + * <li><b>ORDINAL_POSITION</b> int => the ordinal position, starting from 1, for the input and output parameters for a procedure. * A value of 0 is returned if this row describes the procedure's return value. For result set columns, it is the ordinal position of the * column in the result set starting from 1. If there are multiple result sets, the column ordinal positions are implementation defined. - * <li><b>IS_NULLABLE</b> String => ISO rules are used to determine the nullability for a column. + * <li><b>IS_NULLABLE</b> String => ISO rules are used to determine the nullability for a column. * <ul><li>YES --- if the parameter can include NULLs * <li>NO --- if the parameter cannot include NULLs * <li>empty string --- if the nullability for the parameter is unknown * </ul> - * <li><b>SPECIFIC_NAME</b> String => the name which uniquely identifies this procedure within its schema. + * <li><b>SPECIFIC_NAME</b> String => the name which uniquely identifies this procedure within its schema. * </ol> * @param catalog - a catalog name; must match the catalog name as it is stored in the database; * "" retrieves those without a catalog; @@ -1796,8 +1804,12 @@ public class MonetDatabaseMetaData exten * @see #getSearchStringEscape */ @Override - public ResultSet getProcedureColumns(String catalog, String schemaPattern, String procedureNamePattern, - String columnNamePattern) throws SQLException { + public ResultSet getProcedureColumns( + String catalog, + String schemaPattern, + String procedureNamePattern, + String columnNamePattern + ) throws SQLException { StringBuilder query = new StringBuilder(2900); query.append("SELECT cast(null as varchar(1)) AS \"PROCEDURE_CAT\", " + "\"schemas\".\"name\" AS \"PROCEDURE_SCHEM\", " + @@ -1897,17 +1909,17 @@ public class MonetDatabaseMetaData exten * <p>Each table description has the following columns: * * <ol> - * <li><b>TABLE_CAT</b> String => table catalog (may be null) - * <li><b>TABLE_SCHEM</b> String => table schema (may be null) - * <li><b>TABLE_NAME</b> String => table name - * <li><b>TABLE_TYPE</b> String => table type. Typical types are "TABLE", + * <li><b>TABLE_CAT</b> String => table catalog (may be null) + * <li><b>TABLE_SCHEM</b> String => table schema (may be null) + * <li><b>TABLE_NAME</b> String => table name + * <li><b>TABLE_TYPE</b> String => table type. Typical types are "TABLE", * "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY", "LOCAL TEMPORARY", "ALIAS", "SYNONYM". - * <li><b>REMARKS</b> String => explanatory comment on the table - * <li><b>TYPE_CAT</b> String => the types catalog (may be null) - * <li><b>TYPE_SCHEM</b> String => the types schema (may be null) - * <li><b>TYPE_NAME</b> String => type name (may be null) - * <li><b>SELF_REFERENCING_COL_NAME</b> String => name of the designated "identifier" column of a typed table (may be null) - * <li><b>REF_GENERATION</b> String => specifies how values in SELF_REFERENCING_COL_NAME are created. Values are "SYSTEM", "USER", "DERIVED". (may be null) + * <li><b>REMARKS</b> String => explanatory comment on the table + * <li><b>TYPE_CAT</b> String => the types catalog (may be null) + * <li><b>TYPE_SCHEM</b> String => the types schema (may be null) + * <li><b>TYPE_NAME</b> String => type name (may be null) + * <li><b>SELF_REFERENCING_COL_NAME</b> String => name of the designated "identifier" column of a typed table (may be null) + * <li><b>REF_GENERATION</b> String => specifies how values in SELF_REFERENCING_COL_NAME are created. Values are "SYSTEM", "USER", "DERIVED". (may be null) * </ol> * * @param catalog - a catalog name; must match the catalog name as it is stored in the database; @@ -1924,8 +1936,13 @@ public class MonetDatabaseMetaData exten * @throws SQLException if a database-access error occurs. */ @Override - public ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String types[]) - throws SQLException { + public ResultSet getTables( + String catalog, + String schemaPattern, + String tableNamePattern, + String types[] + ) throws SQLException + { // as of Jul2015 release the sys.tables.type values (0 through 6) is extended with new values 10, 11, 20, and 30 (for system and temp tables/views). // as of Jul2015 release we also have a new table: sys.table_types with names for the new table types // for correct behavior we need to know if the server is using the old (pre Jul2015) or new sys.tables.type values @@ -2006,8 +2023,8 @@ public class MonetDatabaseMetaData exten * * <P>The schema column is: * <OL> - * <LI><B>TABLE_SCHEM</B> String => schema name - * <LI><B>TABLE_CATALOG</B> String => catalog name (may be null) + * <LI><B>TABLE_SCHEM</B> String => schema name + * <LI><B>TABLE_CATALOG</B> String => catalog name (may be null) * </OL> * * @param catalog a catalog name; must match the catalog name as it @@ -2022,7 +2039,9 @@ public class MonetDatabaseMetaData exten * @throws SQLException if a database error occurs */ @Override - public ResultSet getSchemas(String catalog, String schemaPattern) throws SQLException { + public ResultSet getSchemas(String catalog, String schemaPattern) + throws SQLException + { StringBuilder query = new StringBuilder(170); query.append("SELECT \"name\" AS \"TABLE_SCHEM\", " + "cast(null as char(1)) AS \"TABLE_CATALOG\" " + @@ -2048,7 +2067,7 @@ public class MonetDatabaseMetaData exten * * <P>The catalog column is: * <OL> - * <LI><B>TABLE_CAT</B> String => catalog name + * <LI><B>TABLE_CAT</B> String => catalog name * </OL> * * @@ -2069,7 +2088,7 @@ public class MonetDatabaseMetaData exten * * <P>The table type is: * <OL> - * <LI><B>TABLE_TYPE</B> String => table type. Typical types are "TABLE", + * <LI><B>TABLE_TYPE</B> String => table type. Typical types are "TABLE", * "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY", * "LOCAL TEMPORARY", "ALIAS", "SYNONYM". * </OL> @@ -2107,46 +2126,46 @@ public class MonetDatabaseMetaData exten * * <P>Each column description has the following columns: * <OL> - * <LI><B>TABLE_CAT</B> String => table catalog (may be null) - * <LI><B>TABLE_SCHEM</B> String => table schema (may be null) - * <LI><B>TABLE_NAME</B> String => table name - * <LI><B>COLUMN_NAME</B> String => column name - * <LI><B>DATA_TYPE</B> int => SQL type from java.sql.Types - * <LI><B>TYPE_NAME</B> String => Data source dependent type name - * <LI><B>COLUMN_SIZE</B> int => column size. For char or date + * <LI><B>TABLE_CAT</B> String => table catalog (may be null) + * <LI><B>TABLE_SCHEM</B> String => table schema (may be null) + * <LI><B>TABLE_NAME</B> String => table name + * <LI><B>COLUMN_NAME</B> String => column name + * <LI><B>DATA_TYPE</B> int => SQL type from java.sql.Types + * <LI><B>TYPE_NAME</B> String => Data source dependent type name + * <LI><B>COLUMN_SIZE</B> int => column size. For char or date * types this is the maximum number of characters, for numeric or * decimal types this is precision. * <LI><B>BUFFER_LENGTH</B> is not used. - * <LI><B>DECIMAL_DIGITS</B> int => the number of fractional digits - * <LI><B>NUM_PREC_RADIX</B> int => Radix (typically either 10 or 2) - * <LI><B>NULLABLE</B> int => is NULL allowed? + * <LI><B>DECIMAL_DIGITS</B> int => the number of fractional digits + * <LI><B>NUM_PREC_RADIX</B> int => Radix (typically either 10 or 2) + * <LI><B>NULLABLE</B> int => is NULL allowed? * <UL> * <LI> columnNoNulls - might not allow NULL values * <LI> columnNullable - definitely allows NULL values * <LI> columnNullableUnknown - nullability unknown * </UL> - * <LI><B>REMARKS</B> String => comment describing column (may be null) - * <LI><B>COLUMN_DEF</B> String => default value (may be null) - * <LI><B>SQL_DATA_TYPE</B> int => unused - * <LI><B>SQL_DATETIME_SUB</B> int => unused - * <LI><B>CHAR_OCTET_LENGTH</B> int => for char types the + * <LI><B>REMARKS</B> String => comment describing column (may be null) + * <LI><B>COLUMN_DEF</B> String => default value (may be null) + * <LI><B>SQL_DATA_TYPE</B> int => unused + * <LI><B>SQL_DATETIME_SUB</B> int => unused + * <LI><B>CHAR_OCTET_LENGTH</B> int => for char types the * maximum number of bytes in the column - * <LI><B>ORDINAL_POSITION</B> int => index of column in table + * <LI><B>ORDINAL_POSITION</B> int => index of column in table * (starting at 1) - * <LI><B>IS_NULLABLE</B> String => "NO" means column definitely + * <LI><B>IS_NULLABLE</B> String => "NO" means column definitely * does not allow NULL values; "YES" means the column might * allow NULL values. An empty string means nobody knows. - * <LI><B>SCOPE_CATALOG</B> String => catalog of table that is the scope of a reference attribute (null if DATA_TYPE isn't REF) - * <LI><B>SCOPE_SCHEMA</B> String => schema of table that is the scope of a reference attribute (null if the DATA_TYPE isn't REF) - * <LI><B>SCOPE_TABLE</B> String => table name that this the scope of a reference attribute (null if the DATA_TYPE isn't REF) - * <LI><B>SOURCE_DATA_TYPE</B> short => source type of a distinct type or user-generated Ref type, SQL type from java.sql.Types (null if DATA_TYPE isn't DISTINCT or user-generated REF) - * <LI><B>IS_AUTOINCREMENT</B> String => Indicates whether this column is auto incremented + * <LI><B>SCOPE_CATALOG</B> String => catalog of table that is the scope of a reference attribute (null if DATA_TYPE isn't REF) + * <LI><B>SCOPE_SCHEMA</B> String => schema of table that is the scope of a reference attribute (null if the DATA_TYPE isn't REF) + * <LI><B>SCOPE_TABLE</B> String => table name that this the scope of a reference attribute (null if the DATA_TYPE isn't REF) + * <LI><B>SOURCE_DATA_TYPE</B> short => source type of a distinct type or user-generated Ref type, SQL type from java.sql.Types (null if DATA_TYPE isn't DISTINCT or user-generated REF) + * <LI><B>IS_AUTOINCREMENT</B> String => Indicates whether this column is auto incremented * <UL> * <LI> YES --- if the column is auto incremented * <LI> NO --- if the column is not auto incremented * <LI> empty string --- if it cannot be determined whether the column is auto incremented * </UL> - * <LI><B>IS_GENERATEDCOLUMN</B> String => Indicates whether this is a generated column + * <LI><B>IS_GENERATEDCOLUMN</B> String => Indicates whether this is a generated column * <UL> * <LI> YES --- if this a generated column * <LI> NO --- if this not a generated column @@ -2168,8 +2187,13 @@ public class MonetDatabaseMetaData exten * @see #getSearchStringEscape */ @Override - public ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) - throws SQLException { + public ResultSet getColumns( + String catalog, + String schemaPattern, + String tableNamePattern, + String columnNamePattern + ) throws SQLException + { StringBuilder query = new StringBuilder(2450); query.append("SELECT cast(null as char(1)) AS \"TABLE_CAT\", " + "\"schemas\".\"name\" AS \"TABLE_SCHEM\", " + @@ -2233,15 +2257,15 @@ public class MonetDatabaseMetaData exten * * <P>Each privilige description has the following columns: * <OL> - * <LI><B>TABLE_CAT</B> String => table catalog (may be null) - * <LI><B>TABLE_SCHEM</B> String => table schema (may be null) - * <LI><B>TABLE_NAME</B> String => table name - * <LI><B>COLUMN_NAME</B> String => column name - * <LI><B>GRANTOR</B> => grantor of access (may be null) - * <LI><B>GRANTEE</B> String => grantee of access - * <LI><B>PRIVILEGE</B> String => name of access (SELECT, + * <LI><B>TABLE_CAT</B> String => table catalog (may be null) + * <LI><B>TABLE_SCHEM</B> String => table schema (may be null) + * <LI><B>TABLE_NAME</B> String => table name + * <LI><B>COLUMN_NAME</B> String => column name + * <LI><B>GRANTOR</B> => grantor of access (may be null) + * <LI><B>GRANTEE</B> String => grantee of access + * <LI><B>PRIVILEGE</B> String => name of access (SELECT, * INSERT, UPDATE, REFRENCES, ...) - * <LI><B>IS_GRANTABLE</B> String => "YES" if grantee is permitted + * <LI><B>IS_GRANTABLE</B> String => "YES" if grantee is permitted * to grant to others; "NO" if not; null if unknown * </OL> * @@ -2254,8 +2278,13 @@ public class MonetDatabaseMetaData exten * @throws SQLException if a database error occurs */ @Override - public ResultSet getColumnPrivileges(String catalog, String schemaPattern, String tableNamePattern, - String columnNamePattern) throws SQLException { + public ResultSet getColumnPrivileges( + String catalog, + String schemaPattern, + String tableNamePattern, + String columnNamePattern + ) throws SQLException + { StringBuilder query = new StringBuilder(1100); query.append("SELECT cast(null as char(1)) AS \"TABLE_CAT\", " + "\"schemas\".\"name\" AS \"TABLE_SCHEM\", " + @@ -2319,14 +2348,14 @@ public class MonetDatabaseMetaData exten * * <P>Each privilege description has the following columns: * <OL> - * <LI><B>TABLE_CAT</B> String => table catalog (may be null) - * <LI><B>TABLE_SCHEM</B> String => table schema (may be null) - * <LI><B>TABLE_NAME</B> String => table name - * <LI><B>GRANTOR</B> => grantor of access (may be null) - * <LI><B>GRANTEE</B> String => grantee of access - * <LI><B>PRIVILEGE</B> String => name of access (SELECT, + * <LI><B>TABLE_CAT</B> String => table catalog (may be null) + * <LI><B>TABLE_SCHEM</B> String => table schema (may be null) + * <LI><B>TABLE_NAME</B> String => table name + * <LI><B>GRANTOR</B> => grantor of access (may be null) + * <LI><B>GRANTEE</B> String => grantee of access + * <LI><B>PRIVILEGE</B> String => name of access (SELECT, * INSERT, UPDATE, REFRENCES, ...) - * <LI><B>IS_GRANTABLE</B> String => "YES" if grantee is permitted + * <LI><B>IS_GRANTABLE</B> String => "YES" if grantee is permitted * to grant to others; "NO" if not; null if unknown * </OL> * @@ -2338,8 +2367,12 @@ public class MonetDatabaseMetaData exten * @throws SQLException if a database error occurs */ @Override - public ResultSet getTablePrivileges(String catalog, String schemaPattern, String tableNamePattern) - throws SQLException { + public ResultSet getTablePrivileges( + String catalog, + String schemaPattern, + String tableNamePattern + ) throws SQLException + { StringBuilder query = new StringBuilder(1000); query.append("SELECT cast(null as char(1)) AS \"TABLE_CAT\", " + "\"schemas\".\"name\" AS \"TABLE_SCHEM\", " + @@ -2393,19 +2426,19 @@ public class MonetDatabaseMetaData exten * * <P>Each column description has the following columns: * <OL> - * <LI><B>SCOPE</B> short => actual scope of result + * <LI><B>SCOPE</B> short => actual scope of result * <UL> * <LI> bestRowTemporary - very temporary, while using row * <LI> bestRowTransaction - valid for remainder of current transaction * <LI> bestRowSession - valid for remainder of current session * </UL> - * <LI><B>COLUMN_NAME</B> String => column name - * <LI><B>DATA_TYPE</B> int => SQL data type from java.sql.Types - * <LI><B>TYPE_NAME</B> String => Data source dependent type name - * <LI><B>COLUMN_SIZE</B> int => precision - * <LI><B>BUFFER_LENGTH</B> int => not used - * <LI><B>DECIMAL_DIGITS</B> short => scale - * <LI><B>PSEUDO_COLUMN</B> short => is this a pseudo column + * <LI><B>COLUMN_NAME</B> String => column name + * <LI><B>DATA_TYPE</B> int => SQL data type from java.sql.Types + * <LI><B>TYPE_NAME</B> String => Data source dependent type name + * <LI><B>COLUMN_SIZE</B> int => precision + * <LI><B>BUFFER_LENGTH</B> int => not used + * <LI><B>DECIMAL_DIGITS</B> short => scale + * <LI><B>PSEUDO_COLUMN</B> short => is this a pseudo column * like an Oracle ROWID * <UL> * <LI> bestRowUnknown - may or may not be pseudo column @@ -2423,8 +2456,14 @@ public class MonetDatabaseMetaData exten * @throws SQLException if a database error occurs */ @Override - public ResultSet getBestRowIdentifier(String catalog, String schema, String table, int scope, boolean nullable) - throws SQLException { + public ResultSet getBestRowIdentifier( + String catalog, + String schema, + String table, + int scope, + boolean nullable + ) throws SQLException + { StringBuilder query = new StringBuilder(1500); query.append("SELECT CAST(").append(DatabaseMetaData.bestRowSession).append(" AS smallint) AS \"SCOPE\", " + "\"columns\".\"name\" AS \"COLUMN_NAME\", " + @@ -2475,14 +2514,14 @@ public class MonetDatabaseMetaData exten * * <P>Each column description has the following columns: * <OL> - * <LI><B>SCOPE</B> short => is not used - * <LI><B>COLUMN_NAME</B> String => column name - * <LI><B>DATA_TYPE</B> int => SQL data type from java.sql.Types - * <LI><B>TYPE_NAME</B> String => Data source dependent type name - * <LI><B>COLUMN_SIZE</B> int => precision - * <LI><B>BUFFER_LENGTH</B> int => length of column value in bytes - * <LI><B>DECIMAL_DIGITS</B> short => scale - * <LI><B>PSEUDO_COLUMN</B> short => is this a pseudo column like an Oracle ROWID + * <LI><B>SCOPE</B> short => is not used + * <LI><B>COLUMN_NAME</B> String => column name + * <LI><B>DATA_TYPE</B> int => SQL data type from java.sql.Types + * <LI><B>TYPE_NAME</B> String => Data source dependent type name + * <LI><B>COLUMN_SIZE</B> int => precision + * <LI><B>BUFFER_LENGTH</B> int => length of column value in bytes + * <LI><B>DECIMAL_DIGITS</B> short => scale + * <LI><B>PSEUDO_COLUMN</B> short => is this a pseudo column like an Oracle ROWID * <UL> * <LI> versionColumnUnknown - may or may not be pseudo column * <LI> versionColumnNotPseudo - is NOT a pseudo column @@ -2497,7 +2536,12 @@ public class MonetDatabaseMetaData exten * @throws SQLException if a database error occurs */ @Override - public ResultSet getVersionColumns(String catalog, String schema, String table) throws SQLException { + public ResultSet getVersionColumns( + String catalog, + String schema, + String table + ) throws SQLException + { // MonetDB currently does not have columns which update themselves, so return an empty ResultSet String query = "SELECT CAST(0 as smallint) AS \"SCOPE\", " + @@ -2519,12 +2563,12 @@ public class MonetDatabaseMetaData exten * * <P>Each column description has the following columns: * <OL> - * <LI><B>TABLE_CAT</B> String => table catalog (may be null) - * <LI><B>TABLE_SCHEM</B> String => table schema (may be null) - * <LI><B>TABLE_NAME</B> String => table name - * <LI><B>COLUMN_NAME</B> String => column name - * <LI><B>KEY_SEQ</B> short => sequence number within primary key - * <LI><B>PK_NAME</B> String => primary key name (may be null) + * <LI><B>TABLE_CAT</B> String => table catalog (may be null) + * <LI><B>TABLE_SCHEM</B> String => table schema (may be null) + * <LI><B>TABLE_NAME</B> String => table name + * <LI><B>COLUMN_NAME</B> String => column name + * <LI><B>KEY_SEQ</B> short => sequence number within primary key + * <LI><B>PK_NAME</B> String => primary key name (may be null) * </OL> * * @param catalog a catalog name; "" retrieves those without a catalog @@ -2535,7 +2579,12 @@ public class MonetDatabaseMetaData exten * @throws SQLException if a database error occurs */ @Override - public ResultSet getPrimaryKeys(String catalog, String schema, String table) throws SQLException { + public ResultSet getPrimaryKeys( + String catalog, + String schema, + String table + ) throws SQLException + { StringBuilder query = new StringBuilder(600); query.append("SELECT cast(null AS varchar(1)) AS \"TABLE_CAT\", " + "\"schemas\".\"name\" AS \"TABLE_SCHEM\", " + @@ -2569,7 +2618,8 @@ public class MonetDatabaseMetaData exten return executeMetaDataQuery(query.toString()); } - private final static String keyQuery = + + private static final String keyQuery = "SELECT cast(null AS varchar(1)) AS \"PKTABLE_CAT\", " + "\"pkschema\".\"name\" AS \"PKTABLE_SCHEM\", " + "\"pktable\".\"name\" AS \"PKTABLE_NAME\", " + @@ -2610,21 +2660,21 @@ public class MonetDatabaseMetaData exten * * <P>Each primary key column description has the following columns: * <OL> - * <LI><B>PKTABLE_CAT</B> String => primary key table catalog + * <LI><B>PKTABLE_CAT</B> String => primary key table catalog * being imported (may be null) - * <LI><B>PKTABLE_SCHEM</B> String => primary key table schema + * <LI><B>PKTABLE_SCHEM</B> String => primary key table schema * being imported (may be null) - * <LI><B>PKTABLE_NAME</B> String => primary key table name + * <LI><B>PKTABLE_NAME</B> String => primary key table name * being imported - * <LI><B>PKCOLUMN_NAME</B> String => primary key column name + * <LI><B>PKCOLUMN_NAME</B> String => primary key column name * being imported - * <LI><B>FKTABLE_CAT</B> String => foreign key table catalog (may be null) - * <LI><B>FKTABLE_SCHEM</B> String => foreign key table schema (may be null) - * <LI><B>FKTABLE_NAME</B> String => foreign key table name - * <LI><B>FKCOLUMN_NAME</B> String => foreign key column name - * <LI><B>KEY_SEQ</B> short => sequence number within foreign key + * <LI><B>FKTABLE_CAT</B> String => foreign key table catalog (may be null) + * <LI><B>FKTABLE_SCHEM</B> String => foreign key table schema (may be null) + * <LI><B>FKTABLE_NAME</B> String => foreign key table name + * <LI><B>FKCOLUMN_NAME</B> String => foreign key column name + * <LI><B>KEY_SEQ</B> short => sequence number within foreign key * (a value of 1 represents the first column of the foreign key, a value of 2 would represent the second column within the foreign key). - * <LI><B>UPDATE_RULE</B> short => What happens to + * <LI><B>UPDATE_RULE</B> short => What happens to * foreign key when primary is updated: * <UL> * <LI> importedKeyNoAction - do not allow update of primary key if it has been imported @@ -2635,7 +2685,7 @@ public class MonetDatabaseMetaData exten * <LI> importedKeySetNull - change imported key to NULL if * its primary key has been updated * </UL> - * <LI><B>DELETE_RULE</B> short => What happens to + * <LI><B>DELETE_RULE</B> short => What happens to * the foreign key when primary is deleted. * <UL> * <LI> importedKeyNoAction - do not allow delete of primary key if it has been imported @@ -2645,9 +2695,9 @@ public class MonetDatabaseMetaData exten * <LI> importedKeySetNull - change imported key to NULL if * its primary key has been deleted * </UL> - * <LI><B>FK_NAME</B> String => foreign key name (may be null) - * <LI><B>PK_NAME</B> String => primary key name (may be null) - * <LI><B>DEFERRABILITY</B> short => can the evaluation of foreign key constraints be deferred until commit + * <LI><B>FK_NAME</B> String => foreign key name (may be null) + * <LI><B>PK_NAME</B> String => primary key name (may be null) + * <LI><B>DEFERRABILITY</B> short => can the evaluation of foreign key constraints be deferred until commit * <UL> * <LI> importedKeyInitiallyDeferred - see SQL92 for definition * <LI> importedKeyInitiallyImmediate - see SQL92 for definition @@ -2663,7 +2713,9 @@ public class MonetDatabaseMetaData exten * @throws SQLException if a database error occurs */ @Override - public ResultSet getImportedKeys(String catalog, String schema, String table) throws SQLException { + public ResultSet getImportedKeys(String catalog, String schema, String table) + throws SQLException + { StringBuilder query = new StringBuilder(keyQuery.length() + 250); query.append(keyQuery); @@ -2691,21 +2743,21 @@ public class MonetDatabaseMetaData exten * * <P>Each foreign key column description has the following columns: * <OL> - * <LI><B>PKTABLE_CAT</B> String => primary key table catalog (may be null) - * <LI><B>PKTABLE_SCHEM</B> String => primary key table schema (may be null) - * <LI><B>PKTABLE_NAME</B> String => primary key table name - * <LI><B>PKCOLUMN_NAME</B> String => primary key column name - * <LI><B>FKTABLE_CAT</B> String => foreign key table catalog (may be null) + * <LI><B>PKTABLE_CAT</B> String => primary key table catalog (may be null) + * <LI><B>PKTABLE_SCHEM</B> String => primary key table schema (may be null) + * <LI><B>PKTABLE_NAME</B> String => primary key table name + * <LI><B>PKCOLUMN_NAME</B> String => primary key column name + * <LI><B>FKTABLE_CAT</B> String => foreign key table catalog (may be null) * being exported (may be null) - * <LI><B>FKTABLE_SCHEM</B> String => foreign key table schema (may be null) + * <LI><B>FKTABLE_SCHEM</B> String => foreign key table schema (may be null) * being exported (may be null) - * <LI><B>FKTABLE_NAME</B> String => foreign key table name + * <LI><B>FKTABLE_NAME</B> String => foreign key table name * being exported - * <LI><B>FKCOLUMN_NAME</B> String => foreign key column name + * <LI><B>FKCOLUMN_NAME</B> String => foreign key column name * being exported - * <LI><B>KEY_SEQ</B> short => sequence number within foreign key + * <LI><B>KEY_SEQ</B> short => sequence number within foreign key * (a value of 1 represents the first column of the foreign key, a value of 2 would represent the second column within the foreign key). - * <LI><B>UPDATE_RULE</B> short => What happens to + * <LI><B>UPDATE_RULE</B> short => What happens to * foreign key when primary is updated: * <UL> * <LI> importedKeyNoAction - do not allow update of primary key if it has been imported @@ -2716,7 +2768,7 @@ public class MonetDatabaseMetaData exten * <LI> importedKeySetNull - change imported key to NULL if * its primary key has been updated * </UL> - * <LI><B>DELETE_RULE</B> short => What happens to + * <LI><B>DELETE_RULE</B> short => What happens to * the foreign key when primary is deleted. * <UL> * <LI> importedKeyNoAction - do not allow delete of primary key if it has been imported @@ -2726,9 +2778,9 @@ public class MonetDatabaseMetaData exten * <LI> importedKeySetNull - change imported key to NULL if * its primary key has been deleted * </UL> - * <LI><B>FK_NAME</B> String => foreign key identifier (may be null) - * <LI><B>PK_NAME</B> String => primary key identifier (may be null) - * <LI><B>DEFERRABILITY</B> short => can the evaluation of foreign key constraints be deferred until commit + * <LI><B>FK_NAME</B> String => foreign key identifier (may be null) + * <LI><B>PK_NAME</B> String => primary key identifier (may be null) + * <LI><B>DEFERRABILITY</B> short => can the evaluation of foreign key constraints be deferred until commit * <UL> * <LI> importedKeyInitiallyDeferred - see SQL92 for definition * <LI> importedKeyInitiallyImmediate - see SQL92 for definition @@ -2744,7 +2796,9 @@ public class MonetDatabaseMetaData exten * @throws SQLException if a database error occurs */ @Override - public ResultSet getExportedKeys(String catalog, String schema, String table) throws SQLException { + public ResultSet getExportedKeys(String catalog, String schema, String table) + throws SQLException + { StringBuilder query = new StringBuilder(keyQuery.length() + 250); query.append(keyQuery); @@ -2775,21 +2829,21 @@ public class MonetDatabaseMetaData exten * * <P>Each foreign key column description has the following columns: * <OL> - * <LI><B>PKTABLE_CAT</B> String => primary key table catalog (may be null) - * <LI><B>PKTABLE_SCHEM</B> String => primary key table schema (may be null) - * <LI><B>PKTABLE_NAME</B> String => primary key table name - * <LI><B>PKCOLUMN_NAME</B> String => primary key column name - * <LI><B>FKTABLE_CAT</B> String => foreign key table catalog (may be null) + * <LI><B>PKTABLE_CAT</B> String => primary key table catalog (may be null) + * <LI><B>PKTABLE_SCHEM</B> String => primary key table schema (may be null) + * <LI><B>PKTABLE_NAME</B> String => primary key table name + * <LI><B>PKCOLUMN_NAME</B> String => primary key column name + * <LI><B>FKTABLE_CAT</B> String => foreign key table catalog (may be null) * being exported (may be null) - * <LI><B>FKTABLE_SCHEM</B> String => foreign key table schema (may be null) + * <LI><B>FKTABLE_SCHEM</B> String => foreign key table schema (may be null) * being exported (may be null) - * <LI><B>FKTABLE_NAME</B> String => foreign key table name + * <LI><B>FKTABLE_NAME</B> String => foreign key table name * being exported - * <LI><B>FKCOLUMN_NAME</B> String => foreign key column name + * <LI><B>FKCOLUMN_NAME</B> String => foreign key column name * being exported - * <LI><B>KEY_SEQ</B> short => sequence number within foreign key + * <LI><B>KEY_SEQ</B> short => sequence number within foreign key * (a value of 1 represents the first column of the foreign key, a value of 2 would represent the second column within the foreign key). - * <LI><B>UPDATE_RULE</B> short => What happens to + * <LI><B>UPDATE_RULE</B> short => What happens to * foreign key when primary is updated: * <UL> * <LI> importedKeyNoAction - do not allow update of primary key if it has been imported @@ -2800,7 +2854,7 @@ public class MonetDatabaseMetaData exten * <LI> importedKeySetNull - change imported key to NULL if * its primary key has been updated * </UL> - * <LI><B>DELETE_RULE</B> short => What happens to + * <LI><B>DELETE_RULE</B> short => What happens to * the foreign key when primary is deleted. * <UL> * <LI> importedKeyNoAction - do not allow delete of primary key if it has been imported @@ -2810,9 +2864,9 @@ public class MonetDatabaseMetaData exten * <LI> importedKeySetNull - change imported key to NULL if * its primary key has been deleted * </UL> - * <LI><B>FK_NAME</B> String => foreign key identifier (may be null) - * <LI><B>PK_NAME</B> String => primary key identifier (may be null) - * <LI><B>DEFERRABILITY</B> short => can the evaluation of foreign key constraints be deferred until commit + * <LI><B>FK_NAME</B> String => foreign key identifier (may be null) + * <LI><B>PK_NAME</B> String => primary key identifier (may be null) + * <LI><B>DEFERRABILITY</B> short => can the evaluation of foreign key constraints be deferred until commit * <UL> * <LI> importedKeyInitiallyDeferred - see SQL92 for definition * <LI> importedKeyInitiallyImmediate - see SQL92 for definition @@ -2831,8 +2885,15 @@ public class MonetDatabaseMetaData exten * @see #getImportedKeys */ @Override - public ResultSet getCrossReference(String pcatalog, String pschema, String ptable, String fcatalog, String fschema, - String ftable) throws SQLException { + public ResultSet getCrossReference( + String pcatalog, + String pschema, + String ptable, + String fcatalog, + String fschema, + String ftable + ) throws SQLException + { StringBuilder query = new StringBuilder(keyQuery.length() + 350); query.append(keyQuery); @@ -2879,42 +2940,42 @@ public class MonetDatabaseMetaData exten * * <P>Each type description has the following columns: * <OL> - * <LI><B>TYPE_NAME</B> String => Type name - * <LI><B>DATA_TYPE</B> int => SQL data type from java.sql.Types - * <LI><B>PRECISION</B> int => maximum precision - * <LI><B>LITERAL_PREFIX</B> String => prefix used to quote a literal (may be null) - * <LI><B>LITERAL_SUFFIX</B> String => suffix used to quote a literal (may be null) - * <LI><B>CREATE_PARAMS</B> String => parameters used in creating + * <LI><B>TYPE_NAME</B> String => Type name + * <LI><B>DATA_TYPE</B> int => SQL data type from java.sql.Types + * <LI><B>PRECISION</B> int => maximum precision + * <LI><B>LITERAL_PREFIX</B> String => prefix used to quote a literal (may be null) + * <LI><B>LITERAL_SUFFIX</B> String => suffix used to quote a literal (may be null) + * <LI><B>CREATE_PARAMS</B> String => parameters used in creating * the type (may be null) - * <LI><B>NULLABLE</B> short => can you use NULL for this type? + * <LI><B>NULLABLE</B> short => can you use NULL for this type? * <UL> * <LI> typeNoNulls - does not allow NULL values * <LI> typeNullable - allows NULL values * <LI> typeNullableUnknown - nullability unknown * </UL> - * <LI><B>CASE_SENSITIVE</B> boolean=> is it case sensitive? - * <LI><B>SEARCHABLE</B> short => can you use "WHERE" based on this type: + * <LI><B>CASE_SENSITIVE</B> boolean=> is it case sensitive? + * <LI><B>SEARCHABLE</B> short => can you use "WHERE" based on this type: * <UL> * <LI> typePredNone - No support * <LI> typePredChar - Only supported with WHERE .. LIKE * <LI> typePredBasic - Supported except for WHERE .. LIKE * <LI> typeSearchable - Supported for all WHERE .. * </UL> - * <LI><B>UNSIGNED_ATTRIBUTE</B> boolean => is it unsigned? - * <LI><B>FIXED_PREC_SCALE</B> boolean => can it be a money value? - * <LI><B>AUTO_INCREMENT</B> boolean => can it be used for an + * <LI><B>UNSIGNED_ATTRIBUTE</B> boolean => is it unsigned? + * <LI><B>FIXED_PREC_SCALE</B> boolean => can it be a money value? + * <LI><B>AUTO_INCREMENT</B> boolean => can it be used for an * auto-increment value? - * <LI><B>LOCAL_TYPE_NAME</B> String => localized version of type name + * <LI><B>LOCAL_TYPE_NAME</B> String => localized version of type name * (may be null) - * <LI><B>MINIMUM_SCALE</B> short => minimum scale supported - * <LI><B>MAXIMUM_SCALE</B> short => maximum scale supported - * <LI><B>SQL_DATA_TYPE</B> int => unused - * <LI><B>SQL_DATETIME_SUB</B> int => unused - * <LI><B>NUM_PREC_RADIX</B> int => usually 2 or 10 + * <LI><B>MINIMUM_SCALE</B> short => minimum scale supported + * <LI><B>MAXIMUM_SCALE</B> short => maximum scale supported + * <LI><B>SQL_DATA_TYPE</B> int => unused + * <LI><B>SQL_DATETIME_SUB</B> int => unused + * <LI><B>NUM_PREC_RADIX</B> int => usually 2 or 10 * </OL> * * @return ResultSet each row is a SQL type description - * @throws SQLException if the developer made a Boo-Boo + * @throws SQLException if a database error occurs */ @Override public ResultSet getTypeInfo() throws SQLException { @@ -2959,16 +3020,16 @@ public class MonetDatabaseMetaData exten * * <P>Each index column description has the following columns: * <OL> - * <LI><B>TABLE_CAT</B> String => table catalog (may be null) - * <LI><B>TABLE_SCHEM</B> String => table schema (may be null) - * <LI><B>TABLE_NAME</B> String => table name - * <LI><B>NON_UNIQUE</B> boolean => Can index values be non-unique? + * <LI><B>TABLE_CAT</B> String => table catalog (may be null) + * <LI><B>TABLE_SCHEM</B> String => table schema (may be null) + * <LI><B>TABLE_NAME</B> String => table name + * <LI><B>NON_UNIQUE</B> boolean => Can index values be non-unique? * false when TYPE is tableIndexStatistic - * <LI><B>INDEX_QUALIFIER</B> String => index catalog (may be null); + * <LI><B>INDEX_QUALIFIER</B> String => index catalog (may be null); * null when TYPE is tableIndexStatistic - * <LI><B>INDEX_NAME</B> String => index name; null when TYPE is + * <LI><B>INDEX_NAME</B> String => index name; null when TYPE is * tableIndexStatistic - * <LI><B>TYPE</B> short => index type: + * <LI><B>TYPE</B> short => index type: * <UL> * <LI> tableIndexStatistic - this identifies table statistics that are * returned in conjuction with a table's index descriptions @@ -2976,20 +3037,20 @@ public class MonetDatabaseMetaData exten * <LI> tableIndexHashed - this is a hashed index * <LI> tableIndexOther - this is some other style of index * </UL> - * <LI><B>ORDINAL_POSITION</B> short => column sequence number + * <LI><B>ORDINAL_POSITION</B> short => column sequence number * within index; zero when TYPE is tableIndexStatistic - * <LI><B>COLUMN_NAME</B> String => column name; null when TYPE is + * <LI><B>COLUMN_NAME</B> String => column name; null when TYPE is * tableIndexStatistic - * <LI><B>ASC_OR_DESC</B> String => column sort sequence, "A" => ascending - * "D" => descending, may be null if sort sequence is not supported; + * <LI><B>ASC_OR_DESC</B> String => column sort sequence, "A" => ascending + * "D" => descending, may be null if sort sequence is not supported; * null when TYPE is tableIndexStatistic - * <LI><B>CARDINALITY</B> int => When TYPE is tableIndexStatisic then + * <LI><B>CARDINALITY</B> int => When TYPE is tableIndexStatisic then * this is the number of rows in the table; otherwise it is the * number of unique values in the index. - * <LI><B>PAGES</B> int => When TYPE is tableIndexStatisic then + * <LI><B>PAGES</B> int => When TYPE is tableIndexStatisic then * this is the number of pages used for the table, otherwise it * is the number of pages used for the current index. - * <LI><B>FILTER_CONDITION</B> String => Filter condition, if any. + * <LI><B>FILTER_CONDITION</B> String => Filter condition, if any. * (may be null) * </OL> * @@ -3005,8 +3066,14 @@ public class MonetDatabaseMetaData exten * @throws SQLException if a database occurs */ @Override - public ResultSet getIndexInfo(String catalog, String schema, String table, boolean unique, boolean approximate) - throws SQLException { + public ResultSet getIndexInfo( + String catalog, + String schema, + String table, + boolean unique, + boolean approximate + ) throws SQLException + { String table_row_count = "0"; if (!approximate && schema != null && table != null && schema.length() > 0 && table.length() > 0) { @@ -3093,7 +3160,8 @@ public class MonetDatabaseMetaData exten /** - * Does the database support the concurrency type in combination with the given result set type? + * Does the database support the concurrency type in combination + * with the given result set type? * * @param type - defined in java.sql.ResultSet * @param concurrency - type defined in java.sql.ResultSet @@ -3101,7 +3169,9 @@ public class MonetDatabaseMetaData exten * @throws SQLException - if a database access error occurs */ @Override - public boolean supportsResultSetConcurrency(int type, int concurrency) throws SQLException { + public boolean supportsResultSetConcurrency(int type, int concurrency) + throws SQLException + { // These combinations are not supported! if (type == ResultSet.TYPE_SCROLL_SENSITIVE) return false; @@ -3178,20 +3248,26 @@ public class MonetDatabaseMetaData exten * * Each type description has the following columns: * - * 1 TYPE_CAT String => the type's catalog (may be null) - * 2 TYPE_SCHEM String => type's schema (may be null) - * 3 TYPE_NAME String => type name - * 4 CLASS_NAME String => Java class name - * 5 DATA_TYPE int => type value defined in java.sql.Types. One of JAVA_OBJECT, STRUCT, or DISTINCT - * 6 REMARKS String => explanatory comment on the type - * 7 BASE_TYPE short => type code of the source type of a DISTINCT type or the type that implements the + * 1 TYPE_CAT String => the type's catalog (may be null) + * 2 TYPE_SCHEM String => type's schema (may be null) + * 3 TYPE_NAME String => type name + * 4 CLASS_NAME String => Java class name + * 5 DATA_TYPE int => type value defined in java.sql.Types. One of JAVA_OBJECT, STRUCT, or DISTINCT + * 6 REMARKS String => explanatory comment on the type + * 7 BASE_TYPE short => type code of the source type of a DISTINCT type or the type that implements the * user-generated reference type of the SELF_REFERENCING_COLUMN of a structured type as defined * in java.sql.Types (null if DATA_TYPE is not DISTINCT or not STRUCT with REFERENCE_GENERATION = USER_DEFINED) * + * @throws SQLException - if a database access error occurs */ @Override - public ResultSet getUDTs(String catalog, String schemaPattern, String typeNamePattern, int[] types) - throws SQLException { + public ResultSet getUDTs( + String catalog, + String schemaPattern, + String typeNamePattern, + int[] types + ) throws SQLException + { StringBuilder query = new StringBuilder(990); if (types != null && types.length > 0) { query.append("SELECT * FROM ("); @@ -3265,7 +3341,8 @@ public class MonetDatabaseMetaData exten /** * Retrieves whether this database supports savepoints. * - * @return <code>true</code> if savepoints are supported; <code>false</code> otherwise + * @return <code>true</code> if savepoints are supported; + * <code>false</code> otherwise */ @Override public boolean supportsSavepoints() { @@ -3273,9 +3350,11 @@ public class MonetDatabaseMetaData exten } /** - * Retrieves whether this database supports named parameters to callable statements. + * Retrieves whether this database supports named parameters to callable + * statements. * - * @return <code>true</code> if named parameters are supported; <code>false</code> otherwise + * @return <code>true</code> if named parameters are supported; + * <code>false</code> otherwise */ @Override public boolean supportsNamedParameters() { @@ -3284,10 +3363,12 @@ public class MonetDatabaseMetaData exten /** * Retrieves whether it is possible to have multiple <code>ResultSet</code> objects - * returned from a <code>CallableStatement</code> object simultaneously. + * returned from a <code>CallableStatement</code> object + * simultaneously. * * @return <code>true</code> if a <code>CallableStatement</code> object - * can return multiple <code>ResultSet</code> objects simultaneously; <code>false</code> otherwise + * can return multiple <code>ResultSet</code> objects + * simultaneously; <code>false</code> otherwise */ @Override public boolean supportsMultipleOpenResults() { @@ -3295,10 +3376,11 @@ public class MonetDatabaseMetaData exten } /** - * Retrieves whether auto-generated keys can be retrieved after a statement has been executed. + * Retrieves whether auto-generated keys can be retrieved after + * a statement has been executed. * - * @return <code>true</code> if auto-generated keys can be retrieved after a statement has executed; - * <code>false</code> otherwise + * @return <code>true</code> if auto-generated keys can be retrieved + * after a statement has executed; <code>false</code> otherwise */ @Override public boolean supportsGetGeneratedKeys() { @@ -3321,14 +3403,14 @@ public class MonetDatabaseMetaData exten * describes the designated UDT and a direct supertype. A row has the following * columns: * <OL> - * <LI><B>TYPE_CAT</B> String => the UDT's catalog (may be <code>null</code>) - * <LI><B>TYPE_SCHEM</B> String => UDT's schema (may be <code>null</code>) - * <LI><B>TYPE_NAME</B> String => type name of the UDT - * <LI><B>SUPERTYPE_CAT</B> String => the direct super type's catalog + * <LI><B>TYPE_CAT</B> String => the UDT's catalog (may be <code>null</code>) + * <LI><B>TYPE_SCHEM</B> String => UDT's schema (may be <code>null</code>) + * <LI><B>TYPE_NAME</B> String => type name of the UDT + * <LI><B>SUPERTYPE_CAT</B> String => the direct super type's catalog * (may be <code>null</code>) - * <LI><B>SUPERTYPE_SCHEM</B> String => the direct super type's schema + * <LI><B>SUPERTYPE_SCHEM</B> String => the direct super type's schema * (may be <code>null</code>) - * <LI><B>SUPERTYPE_NAME</B> String => the direct super type's name + * <LI><B>SUPERTYPE_NAME</B> String => the direct super type's name * </OL> * * <P><B>Note:</B> If the driver does not support type hierarchies, an @@ -3345,10 +3427,17 @@ public class MonetDatabaseMetaData exten * @throws SQLException if a database access error occurs */ @Override - public ResultSet getSuperTypes(String catalog, String schemaPattern, String typeNamePattern) throws SQLException { - String query = "SELECT cast(null as char(1)) AS \"TYPE_CAT\", '' AS \"TYPE_SCHEM\", '' AS \"TYPE_NAME\", " + + public ResultSet getSuperTypes( + String catalog, + String schemaPattern, + String typeNamePattern + ) throws SQLException + { + String query = + "SELECT cast(null as char(1)) AS \"TYPE_CAT\", '' AS \"TYPE_SCHEM\", '' AS \"TYPE_NAME\", " + "cast(null as char(1)) AS \"SUPERTYPE_CAT\", '' AS \"SUPERTYPE_SCHEM\", '' AS \"SUPERTYPE_NAME\" " + "WHERE 1 = 0"; + return executeMetaDataQuery(query); } @@ -3366,10 +3455,10 @@ public class MonetDatabaseMetaData exten * * <P>Each type description has the following columns: * <OL> - * <LI><B>TABLE_CAT</B> String => the type's catalog (may be <code>null</code>) - * <LI><B>TABLE_SCHEM</B> String => type's schema (may be <code>null</code>) - * <LI><B>TABLE_NAME</B> String => type name - * <LI><B>SUPERTABLE_NAME</B> String => the direct super type's name + * <LI><B>TABLE_CAT</B> String => the type's catalog (may be <code>null</code>) + * <LI><B>TABLE_SCHEM</B> String => type's schema (may be <code>null</code>) + * <LI><B>TABLE_NAME</B> String => type name + * <LI><B>SUPERTABLE_NAME</B> String => the direct super type's name * </OL> * * <P><B>Note:</B> If the driver does not support type hierarchies, an @@ -3385,9 +3474,17 @@ public class MonetDatabaseMetaData exten * @throws SQLException if a database access error occurs */ @Override - public ResultSet getSuperTables(String catalog, String schemaPattern, String tableNamePattern) throws SQLException { - String query = "SELECT cast(null as char(1)) AS \"TABLE_CAT\", " + - "'' AS \"TABLE_SCHEM\", '' AS \"TABLE_NAME\", '' AS \"SUPERTABLE_NAME\" WHERE 1 = 0"; + public ResultSet getSuperTables( + String catalog, + String schemaPattern, + String tableNamePattern + ) throws SQLException + { + String query = + "SELECT cast(null as char(1)) AS \"TABLE_CAT\", " + + "'' AS \"TABLE_SCHEM\", '' AS \"TABLE_NAME\", '' AS \"SUPERTABLE_NAME\" " + + "WHERE 1 = 0"; + return executeMetaDataQuery(query); } @@ -3404,43 +3501,43 @@ public class MonetDatabaseMetaData exten * The <code>ResultSet</code> object that is returned has the following * columns: * <OL> - * <LI><B>TYPE_CAT</B> String => type catalog (may be <code>null</code>) - * <LI><B>TYPE_SCHEM</B> String => type schema (may be <code>null</code>) - * <LI><B>TYPE_NAME</B> String => type name - * <LI><B>ATTR_NAME</B> String => attribute name - * <LI><B>DATA_TYPE</B> int => attribute type SQL type from java.sql.Types - * <LI><B>ATTR_TYPE_NAME</B> String => Data source dependent type name. + * <LI><B>TYPE_CAT</B> String => type catalog (may be <code>null</code>) + * <LI><B>TYPE_SCHEM</B> String => type schema (may be <code>null</code>) + * <LI><B>TYPE_NAME</B> String => type name + * <LI><B>ATTR_NAME</B> String => attribute name + * <LI><B>DATA_TYPE</B> int => attribute type SQL type from java.sql.Types + * <LI><B>ATTR_TYPE_NAME</B> String => Data source dependent type name. * For a UDT, the type name is fully qualified. For a REF, the type name is * fully qualified and represents the target type of the reference type. - * <LI><B>ATTR_SIZE</B> int => column size. For char or date + * <LI><B>ATTR_SIZE</B> int => column size. For char or date * types this is the maximum number of characters; for numeric or * decimal types this is precision. - * <LI><B>DECIMAL_DIGITS</B> int => the number of fractional digits - * <LI><B>NUM_PREC_RADIX</B> int => Radix (typically either 10 or 2) - * <LI><B>NULLABLE</B> int => whether NULL is allowed + * <LI><B>DECIMAL_DIGITS</B> int => the number of fractional digits + * <LI><B>NUM_PREC_RADIX</B> int => Radix (typically either 10 or 2) + * <LI><B>NULLABLE</B> int => whether NULL is allowed * <UL> * <LI> attributeNoNulls - might not allow NULL values * <LI> attributeNullable - definitely allows NULL values * <LI> attributeNullableUnknown - nullability unknown * </UL> - * <LI><B>REMARKS</B> String => comment describing column (may be <code>null</code>) - * <LI><B>ATTR_DEF</B> String => default value (may be <code>null</code>) - * <LI><B>SQL_DATA_TYPE</B> int => unused - * <LI><B>SQL_DATETIME_SUB</B> int => unused - * <LI><B>CHAR_OCTET_LENGTH</B> int => for char types the + * <LI><B>REMARKS</B> String => comment describing column (may be <code>null</code>) + * <LI><B>ATTR_DEF</B> String => default value (may be <code>null</code>) + * <LI><B>SQL_DATA_TYPE</B> int => unused + * <LI><B>SQL_DATETIME_SUB</B> int => unused + * <LI><B>CHAR_OCTET_LENGTH</B> int => for char types the * maximum number of bytes in the column - * <LI><B>ORDINAL_POSITION</B> int => index of column in table + * <LI><B>ORDINAL_POSITION</B> int => index of column in table * (starting at 1) - * <LI><B>IS_NULLABLE</B> String => "NO" means column definitely + * <LI><B>IS_NULLABLE</B> String => "NO" means column definitely * does not allow NULL values; "YES" means the column might * allow NULL values. An empty string means unknown. - * <LI><B>SCOPE_CATALOG</B> String => catalog of table that is the + * <LI><B>SCOPE_CATALOG</B> String => catalog of table that is the * scope of a reference attribute (<code>null</code> if DATA_TYPE isn't REF) - * <LI><B>SCOPE_SCHEMA</B> String => schema of table that is the + * <LI><B>SCOPE_SCHEMA</B> String => schema of table that is the * scope of a reference attribute (<code>null</code> if DATA_TYPE isn't REF) - * <LI><B>SCOPE_TABLE</B> String => table name that is the scope of a + * <LI><B>SCOPE_TABLE</B> String => table name that is the scope of a * reference attribute (<code>null</code> if the DATA_TYPE isn't REF) - * <LI><B>SOURCE_DATA_TYPE</B> short => source type of a distinct type or user-generated + * <LI><B>SOURCE_DATA_TYPE</B> short => source type of a distinct type or user-generated * Ref type,SQL type from java.sql.Types (<code>null</code> if DATA_TYPE * isn't DISTINCT or user-generated REF) * </OL> @@ -3461,9 +3558,15 @@ public class MonetDatabaseMetaData exten * @throws SQLException if a database access error occurs */ @Override - public ResultSet getAttributes(String catalog, String schemaPattern, String typeNamePattern, - String attributeNamePattern) throws SQLException { - String query = "SELECT cast(null as char(1)) AS \"TYPE_CAT\", '' AS \"TYPE_SCHEM\", '' AS \"TYPE_NAME\", " + + public ResultSet getAttributes( + String catalog, + String schemaPattern, + String typeNamePattern, + String attributeNamePattern + ) throws SQLException + { + String query = + "SELECT cast(null as char(1)) AS \"TYPE_CAT\", '' AS \"TYPE_SCHEM\", '' AS \"TYPE_NAME\", " + "'' AS \"ATTR_NAME\", CAST(0 as int) AS \"DATA_TYPE\", '' AS \"ATTR_TYPE_NAME\", CAST(0 as int) AS \"ATTR_SIZE\", " + "CAST(0 as int) AS \"DECIMAL_DIGITS\", CAST(0 as int) AS \"NUM_PREC_RADIX\", CAST(0 as int) AS \"NULLABLE\", " + "'' AS \"REMARKS\", '' AS \"ATTR_DEF\", CAST(0 as int) AS \"SQL_DATA_TYPE\", " + @@ -3472,13 +3575,15 @@ public class MonetDatabaseMetaData exten "'' AS \"SCOPE_CATALOG\", '' AS \"SCOPE_SCHEMA\", '' AS \"SCOPE_TABLE\", " + "CAST(0 as smallint) AS \"SOURCE_DATA_TYPE\" " + "WHERE 1 = 0"; + return executeMetaDataQuery(query); } /** * Retrieves whether this database supports the given result set holdability. * - * @param holdability one of the following constants: <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or + * @param holdability one of the following constants: + * <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or * <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code> * @return <code>true</code> if so; <code>false</code> otherwise * @see Connection @@ -3491,10 +3596,12 @@ public class MonetDatabaseMetaData exten } /** - * Retrieves the default holdability of this <code>ResultSet</code> object. + * Retrieves the default holdability of this <code>ResultSet</code> + * object. * - * @return the default holdability; either <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or - * <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code> + * @return the default holdability; either + * <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or + * <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code> */ @Override public int getResultSetHoldability() { @@ -3572,7 +3679,9 @@ public class MonetDatabaseMetaData exten /** * Indicates whether the SQLSTATEs returned by <code>SQLException.getSQLState</code> * is X/Open (now known as Open Group) SQL CLI or SQL:2003. - * @return the type of SQLSTATEs, one of: sqlStateXOpen or sqlStateSQL + * @return the type of SQLSTATEs, one of: + * sqlStateXOpen or + * sqlStateSQL */ @Override public int getSQLStateType() { @@ -3581,7 +3690,8 @@ public class MonetDatabaseMetaData exten } /** - * Indicates whether updates made to a LOB are made on a copy or directly to the LOB. + * Indicates whether updates made to a LOB are made on a copy or directly + * to the LOB. * @return <code>true</code> if updates are made to a copy of the LOB; * <code>false</code> if updates are made directly to the LOB */ @@ -3606,8 +3716,9 @@ public class MonetDatabaseMetaData exten //== 1.6 methods (JDBC 4) /** - * Indicates whether or not this data source supports the SQL ROWID type, and if so the lifetime for which a RowId - * object remains valid. + * Indicates whether or not this data source supports the SQL ROWID + * type, and if so the lifetime for which a RowId object remains + * valid. * * @return ROWID_UNSUPPORTED for now */ @@ -3618,15 +3729,17 @@ public class MonetDatabaseMetaData exten } /** - * Get the schema names available in this database. The results are ordered by schema name. + * Get the schema names available in this database. The results + * are ordered by schema name. * * <P>The schema column is: * <OL> - * <LI><B>TABLE_SCHEM</B> String => schema name - * <LI><B>TABLE_CATALOG</B> String => catalog name (may be null) + * <LI><B>TABLE_SCHEM</B> String => schema name + * <LI><B>TABLE_CATALOG</B> String => catalog name (may be null) * </OL> * - * @return ResultSet each row has a single String column that is a schema name + * @return ResultSet each row has a single String column that is a + * schema name * @throws SQLException if a database error occurs */ @Override @@ -3635,8 +3748,8 @@ public class MonetDatabaseMetaData exten } /** - * Retrieves whether this database supports invoking user-defined or vendor functions using the stored procedure - * escape syntax. + * Retrieves whether this database supports invoking user-defined or + * vendor functions using the stored procedure escape syntax. * * @return true if so; false otherwise */ @@ -3668,19 +3781,19 @@ public class MonetDatabaseMetaData exten * Retrieves a list of the client info properties that the driver * supports. The result set contains the following columns * - * 1. NAME String=> The name of the client info property - * 2. MAX_LEN int=> The maximum length of the value for the + * 1. NAME String => The name of the client info property + * 2. MAX_LEN int => The maximum length of the value for the * property - * 3. DEFAULT_VALUE String=> The default value of the + * 3. DEFAULT_VALUE String => The default value of the * property - * 4. DESCRIPTION String=> A description of the + * 4. DESCRIPTION String => A description of the * property. This will typically contain information as * to where this property is stored in the database. * * The ResultSet is sorted by the NAME column * - * @return A ResultSet object; each row is a supported client info property, none in case of MonetDB's current JDBC - * driver + * @return A ResultSet object; each row is a supported client info + * property, none in case of MonetDB's current JDBC driver * @throws SQLException if a database access error occurs */ @Override @@ -3694,8 +3807,10 @@ public class MonetDatabaseMetaData exten "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 'logfile', 1024, 'monet_######.log', 'name of logfile used when debug is enabled' UNION ALL " + + "SELECT 'hash', 128, '', 'hash methods list to use in server connection. Supported are SHA512, SHA384, SHA256, SHA1 and MD5' UNION ALL " + + "SELECT 'treat_blob_as_binary', 5, 'false', 'should blob columns be mapped to Types.VARBINARY instead of default Types.BLOB in ResultSets and PreparedStatements' UNION ALL " + + "SELECT 'treat_clob_as_varchar', 5, 'false', 'should clob columns be mapped to Types.VARCHAR instead of default Types.CLOB in ResultSets and PreparedStatements' UNION ALL " + "SELECT 'so_timeout', 10, '0', 'timeout (in milliseconds) of communication socket. 0 means no timeout is set' " + "ORDER BY \"NAME\""; @@ -3712,17 +3827,17 @@ public class MonetDatabaseMetaData exten * * Each function description has the the following columns: * - * 1. FUNCTION_CAT String => function catalog (may be null) - * 2. FUNCTION_SCHEM String => function schema (may be null) - * 3. FUNCTION_NAME String => function name. This is the + * 1. FUNCTION_CAT String => function catalog (may be null) + * 2. FUNCTION_SCHEM String => function schema (may be null) + * 3. FUNCTION_NAME String => function name. This is the * name used to invoke the function - * 4. REMARKS String => explanatory comment on the function - * 5. FUNCTION_TYPE short => kind of function: + * 4. REMARKS String => explanatory comment on the function + * 5. FUNCTION_TYPE short => kind of function: * * functionResultUnknown - Cannot determine if a return * value or table will be returned * * functionNoTable- Does not return a table * * functionReturnsTable - Returns a table - * 6. SPECIFIC_NAME String => the name which uniquely identifies + * 6. SPECIFIC_NAME String => the name which uniquely identifies * this function within its schema. This is a user specified, * or DBMS generated, name that may be different then the * FUNCTION_NAME for example with overload functions @@ -3744,8 +3859,12 @@ public class MonetDatabaseMetaData exten * @throws SQLException if a database access error occurs */ @Override - public ResultSet getFunctions(String catalog, String schemaPattern, String functionNamePattern) - throws SQLException { + public ResultSet getFunctions( + String catalog, + String schemaPattern, + String functionNamePattern) + throws SQLException + { StringBuilder query = new StringBuilder(800); query.append("SELECT cast(null as varchar(1)) AS \"FUNCTION_CAT\", " + "\"schemas\".\"name\" AS \"FUNCTION_SCHEM\", " + @@ -3791,36 +3910,36 @@ public class MonetDatabaseMetaData exten * Within this, the return value, if any, is first. Next are the parameter descriptions in call order. * The column descriptions follow in column number order. * - * 1. FUNCTION_CAT String => function catalog (may be null) - * 2. FUNCTION_SCHEM String => function schema (may be null) - * 3. FUNCTION_NAME String => function name. This is the name used to invoke the function - * 4. COLUMN_NAME String => column/parameter name - * 5. COLUMN_TYPE Short => kind of column/parameter: + * 1. FUNCTION_CAT String => function catalog (may be null) + * 2. FUNCTION_SCHEM String => function schema (may be null) + * 3. FUNCTION_NAME String => function name. This is the name used to invoke the function + * 4. COLUMN_NAME String => column/parameter name + * 5. COLUMN_TYPE Short => kind of column/parameter: * functionColumnUnknown - nobody knows * functionColumnIn - IN parameter * functionColumnInOut - INOUT parameter * functionColumnOut - OUT parameter * functionColumnReturn - function return value * functionColumnResult - Indicates that the parameter or column is a column in the ResultSet - * 6. DATA_TYPE int => SQL type from java.sql.Types - * 7. TYPE_NAME String => SQL type name, for a UDT type the type name is fully qualified - * 8. PRECISION int => precision - * 9. LENGTH int => length in bytes of data - * 10. SCALE short => scale - null is returned for data types where SCALE is not applicable. - * 11. RADIX short => radix - * 12. NULLABLE short => can it contain NULL. + * 6. DATA_TYPE int => SQL type from java.sql.Types + * 7. TYPE_NAME String => SQL type name, for a UDT type the type name is fully qualified + * 8. PRECISION int => precision + * 9. LENGTH int => length in bytes of data + * 10. SCALE short => scale - null is returned for data types where SCALE is not applicable. + * 11. RADIX short => radix + * 12. NULLABLE short => can it contain NULL. * functionNoNulls - does not allow NULL values * functionNullable - allows NULL values * functionNullableUnknown - nullability unknown - * 13. REMARKS String => comment describing column/parameter - * 14. CHAR_OCTET_LENGTH int => the maximum length of binary and character based parameters or columns. For any other datatype the returned value is a NULL - * 15. ORDINAL_POSITION int => the ordinal position, starting from 1, for the input and output parameters. + * 13. REMARKS String => comment describing column/parameter + * 14. CHAR_OCTET_LENGTH int => the maximum length of binary and character based parameters or columns. For any other datatype the returned value is a NULL + * 15. ORDINAL_POSITION int => the ordinal position, starting from 1, for the input and output parameters. * A value of 0 is returned if this row describes the function's return value. For result set columns, it is the ordinal position of the column in the result set starting from 1. - * 16. IS_NULLABLE String => ISO rules are used to determine the nullability for a parameter or column. + * 16. IS_NULLABLE String => ISO rules are used to determine the nullability for a parameter or column. * YES --- if the parameter or column can include NULLs * NO --- if the parameter or column cannot include NULLs * empty string --- if the nullability for the parameter or column is unknown - * 17. SPECIFIC_NAME String => the name which uniquely identifies this function within its schema. + * 17. SPECIFIC_NAME String => the name which uniquely identifies this function within its schema. * This is a user specified, or DBMS generated, name that may be different then the FUNCTION_NAME for example with overload functions * * @param catalog a catalog name; must match the catalog name as @@ -3840,8 +3959,13 @@ public class MonetDatabaseMetaData exten * @throws SQLException - if a database access error occurs */ @Override - public ResultSet getFunctionColumns(String catalog, String schemaPattern, String functionNamePattern, - String columnNamePattern) throws SQLException { + public ResultSet getFunctionColumns( + String catalog, + String schemaPattern, + String functionNamePattern, + String columnNamePattern) + throws SQLException + { StringBuilder query = new StringBuilder(2600); query.append("SELECT DISTINCT CAST(null as char(1)) AS \"FUNCTION_CAT\", " + "\"schemas\".\"name\" AS \"FUNCTION_SCHEM\", " + @@ -3910,18 +4034,18 @@ public class MonetDatabaseMetaData exten * * Each column description has the following columns: * - * 1. TABLE_CAT String => table catalog (may be null) - * 2. TABLE_SCHEM String => table schema (may be null) - * 3. TABLE_NAME String => table name - * 4. COLUMN_NAME String => column name - * 5. DATA_TYPE int => SQL type from java.sql.Types - * 6. COLUMN_SIZE int => column size. - * 7. DECIMAL_DIGITS int => the number of fractional digits. Null is returned for data types where DECIMAL_DIGITS is not applicable. - * 8. NUM_PREC_RADIX int => Radix (typically either 10 or 2) - * 9. COLUMN_USAGE String => The allowed usage for the column. The value returned will correspond to the enum name returned by PseudoColumnUsage.name() - * 10. REMARKS String => comment describing column (may be null) - * 11. CHAR_OCTET_LENGTH int => for char types the maximum number of bytes in the column - * 12. IS_NULLABLE String => ISO rules are used to determine the nullability for a column. + * 1. TABLE_CAT String => table catalog (may be null) + * 2. TABLE_SCHEM String => table schema (may be null) + * 3. TABLE_NAME String => table name + * 4. COLUMN_NAME String => column name + * 5. DATA_TYPE int => SQL type from java.sql.Types + * 6. COLUMN_SIZE int => column size. + * 7. DECIMAL_DIGITS int => the number of fractional digits. Null is returned for data types where DECIMAL_DIGITS is not applicable. + * 8. NUM_PREC_RADIX int => Radix (typically either 10 or 2) + * 9. COLUMN_USAGE String => The allowed usage for the column. The value returned will correspond to the enum name returned by PseudoColumnUsage.name() + * 10. REMARKS String => comment describing column (may be null) + * 11. CHAR_OCTET_LENGTH int => for char types the maximum number of bytes in the column + * 12. IS_NULLABLE String => ISO rules are used to determine the nullability for a column. * YES --- if the column can include NULLs * NO --- if the column cannot include NULLs * empty string --- if the nullability for the column is unknown @@ -3934,8 +4058,13 @@ public class MonetDatabaseMetaData exten * @throws SQLException if a database access error occurs */ @Override - public ResultSet getPseudoColumns(String catalog, String schemaPattern, String tableNamePattern, - String columnNamePattern) throws SQLException { + public ResultSet getPseudoColumns( + String catalog, + String schemaPattern, + String tableNamePattern, + String columnNamePattern) + throws SQLException + { // MonetDB currently does not support pseudo or hidden columns, so return an empty ResultSet String query = "SELECT CAST(null as char(1)) AS \"TABLE_CAT\", " +
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetDriver.java.in +++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetDriver.java.in @@ -160,14 +160,14 @@ public final class MonetDriver implement prop.description = "Defines the maximum time to wait in milliseconds on a blocking read socket call (MAPI connection only)"; // this corresponds to the Connection.setNetworkTimeout() method introduced in JDBC 4.1 props.add(prop); - prop = new DriverPropertyInfo("follow_redirects", "true"); + prop = new DriverPropertyInfo("treat_blob_as_binary", "false"); prop.required = false; - prop.description = "Whether redirects issued by the server should be followed (MAPI connection only)"; + prop.description = "Whether BLOBs on the server should be treated as BINARY types, thus mapped to byte[] (MAPI connection only)"; props.add(prop); - prop = new DriverPropertyInfo("treat_blob_as_binary", "false"); + prop = new DriverPropertyInfo("treat_clob_as_varchar", "false"); prop.required = false; - prop.description = "Whether BLOBs on the server should be treated as LONGVARBINARY types, thus mapped to byte[] (MAPI connection only)"; + prop.description = "Whether CLOBs on the server should be treated and handled as VARCHAR types in the JDBC driver (MAPI connection only)"; // recommend for increased performance due to less overhead props.add(prop); prop = new DriverPropertyInfo("treat_clob_as_longvarchar", "false"); @@ -185,7 +185,7 @@ public final class MonetDriver implement } /** - * Reports whether this driver is a genuine JDBC Compliant&tm; driver. A + * Reports whether this driver is a genuine JDBC Compliant™ driver. A * driver may only report true here if it passes the JDBC compliance tests; * otherwise it is required to return false. * @@ -297,7 +297,7 @@ public final class MonetDriver implement * @return the version string */ public static String getDriverVersion() { - return "" + DRIVERMAJOR + "." + DRIVERMINOR + " (" + DRIVERVERSIONSUFFIX + ")"; + return DRIVERMAJOR + "." + DRIVERMINOR + " (" + DRIVERVERSIONSUFFIX + ")"; } public static int getDriverMajorVersion() { @@ -339,8 +339,9 @@ public final class MonetDriver implement * "password" properties should be included in the Properties object. * * @param url the URL of the database to which to connect - * @param info a list of arbitrary string tag/value pairs as connection arguments. Normally at least a "user" and - * "password" property should be included + * @param info a list of arbitrary string tag/value pairs as connection + * arguments. Normally at least a "user" and "password" property + * should be included * @return a Connection object that represents a connection to the URL * @throws SQLException if a database access error occurs */ @@ -348,25 +349,32 @@ public final class MonetDriver implement int tmp; boolean isEmbedded; Properties props = new Properties(); - props.putAll(info); - info = props; if (!acceptsURL(url)) throw new SQLException("Invalid URL: it does not start with: " + MONETURL, "08M26"); if(!url.startsWith("jdbc:monetdb:embedded:")) { // url should be of style jdbc:monetdb://<host>/<database> + + // set the optional properties and their defaults here + props.put("port", PORT); + props.put("debug", "false"); + props.put("language", "sql"); // mal, sql, <future> + props.put("so_timeout", "0"); + props.putAll(info); + info = props; + isEmbedded = false; URI uri; try { uri = new URI(url.substring(5)); } catch (URISyntaxException e) { - throw new SQLException(e.toString(), "08M26"); + throw new SQLNonTransientConnectionException(e.toString(), "08M26"); } String uri_host = uri.getHost(); if (uri_host == null) - throw new SQLException("Invalid URL: no hostname given or unparsable in '" + url + "'", "08M26"); + throw new SQLNonTransientConnectionException("Invalid URL: no hostname given or unparsable in '" + url + "'", "08M26"); info.put("host", uri_host); int uri_port = uri.getPort(); @@ -393,6 +401,9 @@ public final class MonetDriver implement } } else { // url should be of style jdbc:monetdb:embedded:<directory> + props.putAll(info); + info = props; + isEmbedded = true; info.put("directory", url.substring(22)); }
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetPreparedStatement.java +++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetPreparedStatement.java @@ -117,6 +117,14 @@ public class MonetPreparedStatement exte for (int i = 0; rs.next(); i++) { monetdbType[i] = rs.getString(type_colnr); javaType[i] = MonetDriver.getJavaType(monetdbType[i]); + if (javaType[i] == Types.CLOB) { + if (connection.mapClobAsVarChar()) + javaType[i] = Types.VARCHAR; + } else + if (javaType[i] == Types.BLOB) { + if (connection.mapBlobAsVarBinary()) + javaType[i] = Types.VARBINARY; + } digits[i] = rs.getInt(digits_colnr); scale[i] = rs.getInt(scale_colnr); if (rscolcnt == 3) @@ -295,7 +303,7 @@ public class MonetPreparedStatement exte * driver cannot return a ResultSetMetaData object */ @Override - public ResultSetMetaData getMetaData() { + public ResultSetMetaData getMetaData() throws SQLException { if (rscolcnt == 3) return null; // not sufficient data with pre-Dec2011 PREPARE @@ -1999,7 +2007,7 @@ public class MonetPreparedStatement exte } /** - * Sets the designated parameter to the given REF(<structured-type>) value. + * Sets the designated parameter to the given REF(<structured-type>) value. * The driver converts this to an SQL REF value when it sends it to the * database. * @@ -2454,7 +2462,7 @@ public class MonetPreparedStatement exte */ private String transform() throws SQLException { StringBuilder buf = new StringBuilder(8 + 12 * size); - buf.append("exec ").append(id).append('('); + buf.append("execute ").append(id).append('('); // check if all columns are set and do a replace int col = 0; for (int i = 0; i < size; i++) { @@ -2481,7 +2489,7 @@ public class MonetPreparedStatement exte * @param paramIdx the parameter index number * @return a new created SQLDataException object with SQLState 22010 */ - private static SQLDataException newSQLInvalidParameterIndexException(int paramIdx) { + private static final SQLDataException newSQLInvalidParameterIndexException(int paramIdx) { return new SQLDataException("Invalid Parameter Index number: " + paramIdx, "22010"); } @@ -2493,7 +2501,7 @@ public class MonetPreparedStatement exte * @param name the method name * @return a new created SQLFeatureNotSupportedException object with SQLState 0A000 */ - private static SQLFeatureNotSupportedException newSQLFeatureNotSupportedException(String name) { + private static final SQLFeatureNotSupportedException newSQLFeatureNotSupportedException(String name) { return new SQLFeatureNotSupportedException("Method " + name + " not implemented", "0A000"); } }
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetResultSet.java +++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetResultSet.java @@ -133,6 +133,31 @@ public class MonetResultSet extends Mone this.JdbcSQLTypes = JdbcSQLTypes; } + /** + * Internal utility method to fill the JdbcSQLTypes array with derivable values. + * By doing it once (in the constructor) we can avoid doing this in many getXyz() + * methods again and again thereby improving getXyz() method performance. + */ + private void populateJdbcSQLtypesArray() { + MonetConnection connection = null; + try { + connection = (MonetConnection)statement.getConnection(); + } catch (SQLException se) { /* ignore it */ } + + for (int i = 0; i < types.length; i++) { + int javaSQLtype = MonetDriver.getJavaType(types[i]); + if (javaSQLtype == Types.CLOB) { + if (connection != null && connection.mapClobAsVarChar()) + javaSQLtype = Types.VARCHAR; + } else + if (javaSQLtype == Types.BLOB) { + if (connection != null && connection.mapBlobAsVarBinary()) + javaSQLtype = Types.VARBINARY; + } + JdbcSQLTypes[i] = javaSQLtype; + } + } + //== methods of interface ResultSet // Chapter 14.2.2 Sun JDBC 3.0 Specification @@ -159,12 +184,10 @@ public class MonetResultSet extends Mone */ @Override public boolean absolute(int row) throws SQLException { + checkNotClosed(); if (row != curRow + 1 && type == TYPE_FORWARD_ONLY) throw new SQLException("(Absolute) positioning not allowed on forward only result sets!", "M1M05"); - if (header.isClosed()) - throw new SQLException("ResultSet is closed!", "M1M20"); - // first calculate what the JDBC row is if (row < 0) { // calculate the negatives... @@ -235,10 +258,12 @@ public class MonetResultSet extends Mone * * @param columnLabel the name of the column * @return the column index of the given column name - * @throws SQLException if the ResultSet object does not contain columnLabel + * @throws SQLException if the ResultSet object does not contain a column labeled columnLabel, + * a database access error occurs or this method is called on a closed result set */ @Override public int findColumn(String columnLabel) throws SQLException { + checkNotClosed(); if (columnLabel != null) { final int array_size = columns.length; for (int i = 0; i < array_size; i++) { @@ -326,22 +351,27 @@ public class MonetResultSet extends Mone } /** - * Retrieves the value of the designated column in the current row of this ResultSet object as a stream of - * uninterpreted bytes. The value can then be read in chunks from the stream. This method is particularly suitable - * for retrieving large LONGVARBINARY values. - * <br/><br/> - * Note: All the data in the returned stream must be read prior to getting the value of any other column. The next - * call to a getter method implicitly closes the stream. Also, a stream may return 0 when the method - * InputStream.available is called whether there is data available or not. + * Retrieves the value of the designated column in the current row + * of this ResultSet object as a stream of uninterpreted bytes. The + * value can then be read in chunks from the stream. This method is + * particularly suitable for retrieving large LONGVARBINARY values. + * + * Note: All the data in the returned stream must be read prior to + * getting the value of any other column. The next call to a getter + * method implicitly closes the stream. Also, a stream may return 0 + * when the method InputStream.available is called whether there is + * data available or not. * * @param columnIndex the first column is 1, the second is 2, ... - * @return a Java input stream that delivers the database column value as a stream of uninterpreted bytes; if the - * value is SQL NULL, the value returned is null - * @throws SQLException if the columnIndex is not valid; if a database access error occurs or this method is called - * on a closed result set + * @return a Java input stream that delivers the database column + * value as a stream of uninterpreted bytes; if the value is SQL + * NULL, the value returned is null + * @throws SQLException if the columnIndex is not valid; if a + * database access error occurs or this method is called on a closed result set */ @Override public InputStream getBinaryStream(int columnIndex) throws SQLException { + checkNotClosed(); try { InputStream res = null; switch (JdbcSQLTypes[columnIndex - 1]) { @@ -370,20 +400,25 @@ public class MonetResultSet extends Mone } /** - * Retrieves the value of the designated column in the current row of this ResultSet object as a stream of - * uninterpreted bytes. The value can then be read in chunks from the stream. This method is particularly suitable - * for retrieving large LONGVARBINARY values. - * <br/><br/> - * Note: All the data in the returned stream must be read prior to getting the value of any other column. The next - * call to a getter method implicitly closes the stream. Also, a stream may return 0 when the method available is - * called whether there is data available or not. + * Retrieves the value of the designated column in the current row + * of this ResultSet object as a stream of uninterpreted bytes. The + * value can then be read in chunks from the stream. This method is + * particularly suitable for retrieving large LONGVARBINARY values. * - * @param columnLabel the label for the column specified with he SQL AS clause. If the SQL AS clause was not - * specified, then the label is the name of the column - * @return a Java input stream that delivers the database column value as a stream of uninterpreted bytes; if the - * value is SQL NULL, the result is null - * @throws SQLException if the columnLabel is not valid; if a database access error occurs or this method is called - * on a closed result set + * Note: All the data in the returned stream must be read prior to + * getting the value of any other column. The next call to a getter + * method implicitly closes the stream. Also, a stream may return 0 + * when the method available is called whether there is data + * available or not. + * + * @param columnLabel the label for the column specified with + * the SQL AS clause. If the SQL AS clause was not specified, then + * the label is the name of the column + * @return a Java input stream that delivers the database column + * value as a stream of uninterpreted bytes; if the value is SQL + * NULL, the result is null + * @throws SQLException if the columnLabel is not valid; if a + * database access error occurs or this method is called on a closed result set */ @Override public InputStream getBinaryStream(String columnLabel) throws SQLException { @@ -395,12 +430,14 @@ public class MonetResultSet extends Mone * object. * * @param columnIndex the first column is 1, the second is 2, ... - * @return a java.io.Reader object that contains the column value; if the value is SQL NULL, the value returned - * is null in the Java programming language. - * @throws SQLException if a database access error occurs + * @return a java.io.Reader object that contains the column value; + * if the value is SQL NULL, the value returned is null in + * the Java programming language. + * @throws SQLException if a database access error occurs or this method is called on a closed result set */ @Override public Reader getCharacterStream(int columnIndex) throws SQLException { + checkNotClosed(); try { String ss = currentBlock.getValueAsString(columnIndex - 1); return (ss == null) ? null : new StringReader(ss); @@ -463,11 +500,13 @@ public class MonetResultSet extends Mone * the Java programming language. * * @param columnIndex the first column is 1, the second is 2, ... - * @return a Blob object representing the SQL BLOB value in the specified column - * @throws SQLException if a database access error occurs + * @return a Blob object representing the SQL BLOB value in the + * specified column + * @throws SQLException if a database access error occurs or this method is called on a closed result set */ @Override public Blob getBlob(int columnIndex) throws SQLException { + checkNotClosed(); try { return (MonetBlob) currentBlock.getObjectValue(columnIndex - 1); } catch (ClassCastException ex) { @@ -497,11 +536,13 @@ public class MonetResultSet extends Mone * Java programming language. * * @param columnIndex the first column is 1, the second is 2, ... - * @return a Clob object representing the SQL CLOB value in the specified column - * @throws SQLException if a database access error occurs + * @return a Clob object representing the SQL CLOB value in the + * specified column + * @throws SQLException if a database access error occurs or this method is called on a closed result set */ @Override public Clob getClob(int columnIndex) throws SQLException { + checkNotClosed(); try { return (MonetClob) currentBlock.getObjectValue(columnIndex - 1); } catch (ClassCastException ex) { @@ -561,10 +602,11 @@ public class MonetResultSet extends Mone * @param columnIndex the first column is 1, the second is 2, ... * @return the column value (full precision); if the value is SQL NULL, * the value returned is null in the Java programming language. - * @throws SQLException if a database access error occurs + * @throws SQLException if a database access error occurs or this method is called on a closed result set */ @Override public BigDecimal getBigDecimal(int columnIndex) throws SQLException { + checkNotClosed(); try { switch (JdbcSQLTypes[columnIndex - 1]) { case Types.NUMERIC: @@ -620,11 +662,12 @@ public class MonetResultSet extends Mone * @param scale the number of digits to the right of the decimal point * @return the column value (full precision); if the value is SQL NULL, * the value returned is null in the Java programming language. - * @throws SQLException if a database access error occurs + * @throws SQLException if a database access error occurs or this method is called on a closed result set */ @Override @Deprecated public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException { + checkNotClosed(); try { BigDecimal val = getBigDecimal(columnIndex); if(val != null) { @@ -674,11 +717,14 @@ public class MonetResultSet extends Mone * programming language. * * @param columnIndex the first column is 1, the second is 2, ... - * @return the column value; if the value is SQL NULL, the value returned is false - * @throws SQLException if there is no such column + * @return the column value; if the value is SQL NULL, the value returned + * is false + * @throws SQLException if the columnIndex is not valid; if a database access error occurs + * or this method is called on a closed result set */ @Override public boolean getBoolean(int columnIndex) throws SQLException { + checkNotClosed(); try { // match type specific values switch (JdbcSQLTypes[columnIndex - 1]) { @@ -746,11 +792,13 @@ public class MonetResultSet extends Mone * programming language. * * @param columnIndex the first column is 1, the second is 2, ... - * @return the column value; if the value is SQL NULL, the value returned is 0 - * @throws SQLException if a database access error occurs + * @return the column value; if the value is SQL NULL, the value returned + * is 0 + * @throws SQLException if a database access error occurs or this method is called on a closed result set */ @Override public byte getByte(int columnIndex) throws SQLException { + checkNotClosed(); try { switch (JdbcSQLTypes[columnIndex - 1]) { case Types.TINYINT: @@ -819,11 +867,13 @@ public class MonetResultSet extends Mone * bytes represent the raw values returned by the driver. * * @param columnIndex the first column is 1, the second is 2, ... - * @return the column value; if the value is SQL NULL, the value returned is null - * @throws SQLException if a database access error occurs + * @return the column value; if the value is SQL NULL, the value returned + * is null + * @throws SQLException if a database access error occurs or this method is called on a closed result set */ @Override public byte[] getBytes(int columnIndex) throws SQLException { + checkNotClosed(); try { // According to Table B-6, getBytes() only operates on BINARY types switch (JdbcSQLTypes[columnIndex - 1]) { @@ -909,10 +959,11 @@ public class MonetResultSet extends Mone * * @param columnIndex the first column is 1, the second is 2, ... * @return the column value; if the value is SQL NULL, the value returned is 0 - * @throws SQLException if there is no such column + * @throws SQLException if there is no such column or this method is called on a closed result set */ @Override public double getDouble(int columnIndex) throws SQLException { + checkNotClosed(); try { switch (JdbcSQLTypes[columnIndex - 1]) { case Types.DOUBLE: @@ -987,7 +1038,6 @@ public class MonetResultSet extends Mone /** * Retrieves the fetch direction for this ResultSet object. - * <b>currently not implemented</b> * * @return the current fetch direction for this ResultSet object */ @@ -1001,7 +1051,6 @@ public class MonetResultSet extends Mone * object will be processed. The initial value is determined by the * Statement object that produced this ResultSet object. * The fetch direction may be changed at any time. - * <b>currently not implemented</b> * * @param direction - an int specifying the suggested fetch direction; * one of ResultSet.FETCH_FORWARD, ResultSet.FETCH_REVERSE, or ResultSet.FETCH_UNKNOWN @@ -1059,10 +1108,11 @@ public class MonetResultSet extends Mone * * @param columnIndex the first column is 1, the second is 2, ... * @return the column value; if the value is SQL NULL, the value returned is 0 - * @throws SQLException if there is no such column + * @throws SQLException if there is no such column or this method is called on a closed result set */ @Override public float getFloat(int columnIndex) throws SQLException { + checkNotClosed(); try { switch (JdbcSQLTypes[columnIndex - 1]) { case Types.REAL: @@ -1130,10 +1180,11 @@ public class MonetResultSet extends Mone * * @param columnIndex the first column is 1, the second is 2, ... * @return the column value; if the value is SQL NULL, the value returned is 0 - * @throws SQLException if there is no such column + * @throws SQLException if there is no such column or this method is called on a closed result set */ @Override public int getInt(int columnIndex) throws SQLException { + checkNotClosed(); try { switch (JdbcSQLTypes[columnIndex - 1]) { case Types.INTEGER: @@ -1201,10 +1252,11 @@ public class MonetResultSet extends Mone * * @param columnIndex the first column is 1, the second is 2, ... * @return the column value; if the value is SQL NULL, the value returned is 0 - * @throws SQLException if there is no such column + * @throws SQLException if there is no such column or this method is called on a closed result set */ @Override public long getLong(int columnIndex) throws SQLException { + checkNotClosed(); try { switch (JdbcSQLTypes[columnIndex - 1]) { case Types.BIGINT: @@ -1280,24 +1332,33 @@ public class MonetResultSet extends Mone return new rsmdw() { // for the more expensive methods (getPrecision(), getScale(), isNullable()), we provide a simple cache // caches to store precision, scale and isNullable values from getColumns() - final int array_size = columns.length + 1; // add 1 as in JDBC columns start from 1 (array from 0). - private boolean[] _is_fetched = new boolean[array_size]; - private int[] _precision = new int[array_size]; - private int[] _scale = new int[array_size]; - private int[] _isNullable = new int[array_size]; - private boolean[] _isAutoincrement = new boolean[array_size]; + private final int array_size = columns.length + 1; // add 1 as in JDBC columns start from 1 (array from 0). + private final boolean[] _is_fetched = new boolean[array_size]; + private final int[] _precision = new int[array_size]; + private final int[] _scale = new int[array_size]; + private final int[] _isNullable = new int[array_size]; + private final boolean[] _isAutoincrement = new boolean[array_size]; private Connection conn = null; private DatabaseMetaData dbmd = null; /** + * A private utility method to check validity of column index number + * @throws SQLDataException when invalid column index number + */ + private void checkColumnIndexValidity(int column) throws SQLDataException { + if (column < 1 || column > columns.length) + throw MonetResultSet.newSQLInvalidColumnIndexException(column); + } + + /** * A private method to fetch the precision, scale, isNullable and isAutoincrement value for a fully qualified column. * As md.getColumns() is an expensive method we call it only once per column * and cache the precision, scale, isNullable and isAutoincrement values in the above array chaches. * Also we only call md.getColumns() when we have a non empty schema name and table name and column name. */ - private void fetchColumnInfo(int column) throws SQLException { - if (column <= 0 || column > columns.length) - throw newSQLInvalidColumnIndexException(column); + private void fetchColumnInfo(int column) throws SQLException + { + checkColumnIndexValidity(column); _is_fetched[column] = true; _precision[column] = 0; @@ -1360,13 +1421,14 @@ public class MonetResultSet extends Mone */ @Override public boolean isAutoIncrement(int column) throws SQLException { + checkColumnIndexValidity(column); try { if (!_is_fetched[column]) { fetchColumnInfo(column); } return _isAutoincrement[column]; } catch (IndexOutOfBoundsException e) { - throw newSQLInvalidColumnIndexException(column); + throw MonetResultSet.newSQLInvalidColumnIndexException(column); } } @@ -1402,7 +1464,8 @@ public class MonetResultSet extends Mone * @return true */ @Override - public boolean isSearchable(int column) { + public boolean isSearchable(int column) throws SQLException { + checkColumnIndexValidity(column); return true; } @@ -1417,7 +1480,8 @@ public class MonetResultSet extends Mone * @return false */ @Override - public boolean isCurrency(int column) { + public boolean isCurrency(int column) throws SQLException { + checkColumnIndexValidity(column); return false; } @@ -1454,12 +1518,13 @@ public class MonetResultSet extends Mone */ @Override public int getColumnDisplaySize(int column) throws SQLException { + checkColumnIndexValidity(column); int ret = 1; if (header != null) { try { ret = header.getColumnLengths()[column - 1]; } catch (IndexOutOfBoundsException e) { - throw newSQLInvalidColumnIndexException(column); + throw MonetResultSet.newSQLInvalidColumnIndexException(column); } } return ret; @@ -1474,6 +1539,7 @@ public class MonetResultSet extends Mone */ @Override public String getSchemaName(int column) throws SQLException { + checkColumnIndexValidity(column); if (header != null) { // figure the name out try { @@ -1483,7 +1549,7 @@ public class MonetResultSet extends Mone return (dot >= 0) ? schema.substring(0, dot) : ""; } } catch (IndexOutOfBoundsException e) { - throw newSQLInvalidColumnIndexException(column); + throw MonetResultSet.newSQLInvalidColumnIndexException(column); } } return ""; @@ -1497,6 +1563,7 @@ public class MonetResultSet extends Mone */ @Override public String getTableName(int column) throws SQLException { + checkColumnIndexValidity(column); if (header != null) { // figure the name out try { @@ -1506,7 +1573,7 @@ public class MonetResultSet extends Mone return (dot >= 0) ? table.substring(dot + 1) : table; } } catch (IndexOutOfBoundsException e) { - throw newSQLInvalidColumnIndexException(column); + throw MonetResultSet.newSQLInvalidColumnIndexException(column); } } return ""; @@ -1522,6 +1589,7 @@ public class MonetResultSet extends Mone */ @Override public int getPrecision(int column) throws SQLException { + checkColumnIndexValidity(column); try { if (!_is_fetched[column]) { fetchColumnInfo(column); @@ -1579,7 +1647,7 @@ public class MonetResultSet extends Mone } return _precision[column]; } catch (IndexOutOfBoundsException e) { - throw newSQLInvalidColumnIndexException(column); + throw MonetResultSet.newSQLInvalidColumnIndexException(column); } } @@ -1595,13 +1663,14 @@ public class MonetResultSet extends Mone */ @Override public int getScale(int column) throws SQLException { + checkColumnIndexValidity(column); try { if (!_is_fetched[column]) { fetchColumnInfo(column); } return _scale[column]; } catch (IndexOutOfBoundsException e) { - throw newSQLInvalidColumnIndexException(column); + throw MonetResultSet.newSQLInvalidColumnIndexException(column); } } @@ -1618,13 +1687,14 @@ public class MonetResultSet extends Mone */ @Override public int isNullable(int column) throws SQLException { + checkColumnIndexValidity(column); try { if (!_is_fetched[column]) { fetchColumnInfo(column); } return _isNullable[column]; } catch (IndexOutOfBoundsException e) { - throw newSQLInvalidColumnIndexException(column); + throw MonetResultSet.newSQLInvalidColumnIndexException(column); } } @@ -1638,7 +1708,8 @@ public class MonetResultSet extends Mone */ @Override public String getCatalogName(int column) throws SQLException { - return null; // MonetDB does NOT support catalogs + checkColumnIndexValidity(column); + return null; // MonetDB does NOT support catalogs } /** @@ -1649,7 +1720,8 @@ public class MonetResultSet extends Mone * @return true if so; false otherwise */ @Override - public boolean isReadOnly(int column) { + public boolean isReadOnly(int column) throws SQLException { + checkColumnIndexValidity(column); return true; } @@ -1660,7 +1732,8 @@ public class MonetResultSet extends Mone * @return true if so; false otherwise */ @Override - public boolean isWritable(int column) { + public boolean isWritable(int column) throws SQLException { + checkColumnIndexValidity(column); return false; } @@ -1671,7 +1744,8 @@ public class MonetResultSet extends Mone * @return true if so; false otherwise */ @Override - public boolean isDefinitelyWritable(int column) { + public boolean isDefinitelyWritable(int column) throws SQLException { + checkColumnIndexValidity(column); return false; } @@ -1692,6 +1766,7 @@ public class MonetResultSet extends Mone */ @Override public String getColumnClassName(int column) throws SQLException { + checkColumnIndexValidity(column); if (conn == null) { // first time, get a Connection object and cache it for all next columns conn = getStatement().getConnection(); @@ -1714,7 +1789,7 @@ public class MonetResultSet extends Mone } throw new SQLException("column type mapping null: " + MonetDBType, "M0M03"); } catch (IndexOutOfBoundsException e) { - throw newSQLInvalidColumnIndexException(column); + throw MonetResultSet.newSQLInvalidColumnIndexException(column); } } @@ -1740,10 +1815,11 @@ public class MonetResultSet extends Mone */ @Override public String getColumnName(int column) throws SQLException { + checkColumnIndexValidity(column); try { return columns[column - 1]; } catch (IndexOutOfBoundsException e) { - throw newSQLInvalidColumnIndexException(column); + throw MonetResultSet.newSQLInvalidColumnIndexException(column); } } @@ -1756,10 +1832,11 @@ public class MonetResultSet extends Mone */ @Override public int getColumnType(int column) throws SQLException { + checkColumnIndexValidity(column); try { return JdbcSQLTypes[column - 1]; } catch (IndexOutOfBoundsException e) { - throw newSQLInvalidColumnIndexException(column); + throw MonetResultSet.newSQLInvalidColumnIndexException(column); } } @@ -1773,10 +1850,11 @@ public class MonetResultSet extends Mone */ @Override public String getColumnTypeName(int column) throws SQLException { + checkColumnIndexValidity(column); try { return types[column - 1]; } catch (IndexOutOfBoundsException e) { - throw newSQLInvalidColumnIndexException(column); + throw MonetResultSet.newSQLInvalidColumnIndexException(column); } } @@ -1801,12 +1879,13 @@ public class MonetResultSet extends Mone * * @param columnIndex the first column is 1, the second is 2, ... * @return a java.lang.Object holding the column value or null - * @throws SQLException if a database access error occurs + * @throws SQLException if a database access error occurs or this method is called on a closed result set */ @Override public Object getObject(int columnIndex) throws SQLException { - // Many generic JDBC programs use getObject(colnr) to retrieve value objects from a resultset. For speed the - // implementation should be as fast as possible, so avoid method calls (by inlining code) where possible + // Many generic JDBC programs use getObject(colnr) to retrieve value objects from a resultset + // For speed the implementation should be as fast as possible, so avoid method calls (by inlining code) where possible + checkNotClosed(); final int JdbcType; try { JdbcType = JdbcSQLTypes[columnIndex - 1]; @@ -2123,10 +2202,11 @@ public class MonetResultSet extends Mone * @param map a java.util.Map object that contains the mapping from SQL * type names to classes in the Java programming language * @return an Object in the Java programming language representing the SQL value - * @throws SQLException if a database access error occurs + * @throws SQLException if a database access error occurs or this method is called on a closed result set */ @Override public Object getObject(int columnIndex, Map<String, Class<?>> map) throws SQLException { + checkNotClosed(); try { String MonetDBtype = types[columnIndex - 1]; Class<?> type = null; @@ -2160,6 +2240,7 @@ public class MonetResultSet extends Mone @Override @SuppressWarnings("unchecked") public <T> T getObject(int columnIndex, Class<T> type) throws SQLException { + checkNotClosed(); if (type == null) throw new SQLException("type is null", "M1M05"); try { @@ -2253,7 +2334,7 @@ public class MonetResultSet extends Mone * * @param columnLabel the SQL name of the column * @return a java.lang.Object holding the column value - * @throws SQLException if a database access error occurs + * @throws SQLException if a database access error occurs or this method is called on a closed result set */ @Override public Object getObject(String columnLabel) throws SQLException { @@ -2270,7 +2351,7 @@ public class MonetResultSet extends Mone * @param map a java.util.Map object that contains the mapping from SQL * type names to classes in the Java programming language * @return an Object representing the SQL value in the specified column - * @throws SQLException if a database access error occurs + * @throws SQLException if a database access error occurs or this method is called on a closed result set */ @Override public Object getObject(String columnLabel, Map<String,Class<?>> map) throws SQLException { @@ -2332,10 +2413,11 @@ public class MonetResultSet extends Mone * * @param columnIndex the first column is 1, the second is 2, ... * @return the column value; if the value is SQL NULL, the value returned is 0 - * @throws SQLException if there is no such column + * @throws SQLException if there is no such column or this method is called on a closed result set */ @Override public short getShort(int columnIndex) throws SQLException { + checkNotClosed(); try { switch (JdbcSQLTypes[columnIndex - 1]) { case Types.SMALLINT: @@ -2398,11 +2480,12 @@ public class MonetResultSet extends Mone } /** - * Retrieves the Statement object that produced this ResultSet object. If the result set was generated some other - * way, such as by a DatabaseMetaData method, this method returns null. + * Retrieves the Statement object that produced this ResultSet object. + * If the result set was generated some other way, such as by a + * DatabaseMetaData method, this method may return null. * - * @return the Statement object that produced this ResultSet object or null if the result set was produced some - * other way + * @return the Statement object that produced this ResultSet object or + * null if the result set was produced some other way */ @Override public Statement getStatement() { @@ -2415,10 +2498,11 @@ public class MonetResultSet extends Mone * * @param columnIndex the first column is 1, the second is 2, ... * @return the column value; if the value is SQL NULL, the value returned is null - * @throws SQLException if there is no such column + * @throws SQLException if there is no such column or this method is called on a closed result set */ @Override public String getString(int columnIndex) throws SQLException { + checkNotClosed(); try { return currentBlock.getValueAsString(columnIndex - 1); } catch (ClassCastException ex) { @@ -2510,7 +2594,7 @@ public class MonetResultSet extends Mone * language. * * @param columnIndex the first column is 1, the second is 2, ... - * @return the column value; if the value is SQL NULL, the value returned is null + * @return the column value as a java.sql.Date object; if the value is SQL NULL, the value returned is null * @throws SQLException if a database access error occurs * @see #getDate(int col, Calendar cal) */ @@ -2528,11 +2612,12 @@ public class MonetResultSet extends Mone * * @param columnIndex the first column is 1, the second is 2, ... * @param cal the java.util.Calendar object to use in constructing the date - * @return the column value; if the value is SQL NULL, the value returned is null + * @return the column value as a java.sql.Date object; if the value is SQL NULL, the value returned is null * @throws SQLException if a database access error occurs */ @Override public Date getDate(int columnIndex, Calendar cal) throws SQLException { + checkNotClosed(); try { Calendar res; long millis; @@ -2587,7 +2672,7 @@ public class MonetResultSet extends Mone * language. * * @param columnLabel the SQL name of the column from which to retrieve the value - * @return the column value; if the value is SQL NULL, the value returned is null + * @return the column value as a java.sql.Date object; if the value is SQL NULL, the value returned is null * @throws SQLException if a database access error occurs */ @Override @@ -2604,7 +2689,7 @@ public class MonetResultSet extends Mone * * @param columnLabel the SQL name of the column from which to retrieve the value * @param cal the java.util.Calendar object to use in constructing the date - * @return the column value; if the value is SQL NULL, the value returned is null + * @return the column value as a java.sql.Date object; if the value is SQL NULL, the value returned is null * @throws SQLException if a database access error occurs */ @Override @@ -2617,7 +2702,7 @@ public class MonetResultSet extends Mone * object in the Java programming language. * * @param columnIndex the first column is 1, the second is 2, ... - * @return the column value; if the value is SQL NULL, the value returned is null + * @return the column value as a java.sql.Time object; if the value is SQL NULL, the value returned is null * @throws SQLException if a database access error occurs */ @Override @@ -2634,12 +2719,12 @@ public class MonetResultSet extends Mone * * @param columnIndex the first column is 1, the second is 2, ... * @param cal the java.util.Calendar object to use in constructing the timestamp - * @return the column value as a java.sql.Time object; if the value is SQL NULL, the value returned is null in the - * Java programming language + * @return the column value as a java.sql.Time object; if the value is SQL NULL, the value returned is null * @throws SQLException if a database access error occurs */ @Override public Time getTime(int columnIndex, Calendar cal) throws SQLException { + checkNotClosed(); try { Calendar res; long millis; @@ -2693,7 +2778,7 @@ public class MonetResultSet extends Mone * object in the Java programming language. * * @param columnLabel the SQL name of the column - * @return the column value; if the value is SQL NULL, the value returned is null + * @return the column value as a java.sql.Time object; if the value is SQL NULL, the value returned is null * @throws SQLException if a database access error occurs */ @Override @@ -2710,8 +2795,7 @@ public class MonetResultSet extends Mone * * @param columnLabel the SQL name of the column * @param cal the java.util.Calendar object to use in constructing the timestamp - * @return the column value as a java.sql.Time object; if the value is SQL NULL, the value returned is null in the - * Java programming language + * @return the column value as a java.sql.Time object; if the value is SQL NULL, the value returned is null * @throws SQLException if a database access error occurs */ @Override @@ -2724,7 +2808,7 @@ public class MonetResultSet extends Mone * object in the Java programming language. * * @param columnIndex the first column is 1, the second is 2, ... - * @return the column value; if the value is SQL NULL, the value returned is null + * @return the column value as a java.sql.Timestamp object; if the value is SQL NULL, the value returned is null * @throws SQLException if a database access error occurs */ @Override @@ -2742,11 +2826,11 @@ public class MonetResultSet extends Mone * @param columnIndex the first column is 1, the second is 2, ... * @param cal the java.util.Calendar object to use in constructing the timestamp * @return the column value as a java.sql.Timestamp object; if the value is SQL NULL, the value returned is null - * in the Java programming language * @throws SQLException if a database access error occurs */ @Override public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException { + checkNotClosed(); try { Calendar res; long millis; @@ -2817,7 +2901,7 @@ public class MonetResultSet extends Mone * object in the Java programming language. * * @param columnLabel the SQL name of the column - * @return the column value; if the value is SQL NULL, the value returned is null + * @return the column value as a java.sql.Timestamp object; if the value is SQL NULL, the value returned is null * @throws SQLException if a database access error occurs */ @Override @@ -2834,8 +2918,7 @@ public class MonetResultSet extends Mone * * @param columnLabel the SQL name of the column * @param cal the java.util.Calendar object to use in constructing the timestamp - * @return the column value as a java.sql.Timestamp object; if the value is - * SQL NULL, the value returned is null in the Java programming language + * @return the column value as a java.sql.Timestamp object; if the value is SQL NULL, the value returned is null * @throws SQLException if a database access error occurs */ @Override @@ -2859,12 +2942,12 @@ public class MonetResultSet extends Mone * object in the Java programming language. * * @param columnIndex the index of the column 1 is the first, 2 is the second,... - * @return the column value as a java.net.URL object; if the value is SQL NULL, the value returned is null in the - * Java programming language + * @return the column value as a java.net.URL object; if the value is SQL NULL, the value returned is null * @throws SQLException if a database access error occurs, or if a URL is malformed */ @Override public URL getURL(int columnIndex) throws SQLException { + checkNotClosed(); try { switch(JdbcSQLTypes[columnIndex - 1]) { //if it's a string type, will attempt the conversion case Types.OTHER: @@ -2897,8 +2980,7 @@ public class MonetResultSet extends Mone * in the Java programming language. * * @param columnLabel the SQL name of the column - * @return the column value as a java.net.URL object; if the value is SQL NULL, the value returned is null in the - * Java programming language + * @return the column value as a java.net.URL object; if the value is SQL NULL, the value returned is null * @throws SQLException if a database access error occurs, or if a URL is malformed */ @Override @@ -2918,37 +3000,39 @@ public class MonetResultSet extends Mone * Note: Subsequent warnings will be chained to this SQLWarning. * * @return the first SQLWarning object or null if there are none - * @throws SQLException if a database access error occurs or this method is - * called on a closed connection + * @throws SQLException if a database access error occurs or this method is called on a closed result set */ @Override public SQLWarning getWarnings() throws SQLException { - if (header != null && header.isClosed()) - throw new SQLException("Cannot call on closed ResultSet", "M1M20"); - - // if there are no warnings, this will be null, which fits with the specification. + checkNotClosed(); + // if there are no warnings, this will be null, which fits with the + // specification. return warnings; } /** * Retrieves whether the cursor is after the last row in this ResultSet object. * - * @return true if the cursor is after the last row; false if the cursor is at any other position or the result set - * contains no rows + * @return true if the cursor is after the last row; false if the cursor is + * at any other position or the result set contains no rows + * @throws SQLException if a database access error occurs or this method is called on a closed result set */ @Override - public boolean isAfterLast() { + public boolean isAfterLast() throws SQLException { + checkNotClosed(); return curRow == tupleCount + 1; } /** * Retrieves whether the cursor is before the first row in this ResultSet object. * - * @return true if the cursor is before the first row; false if the cursor is at any other position or the result - * set contains no rows + * @return true if the cursor is before the first row; false if the cursor + * is at any other position or the result set contains no rows + * @throws SQLException if a database access error occurs or this method is called on a closed result set */ @Override - public boolean isBeforeFirst() { + public boolean isBeforeFirst() throws SQLException { + checkNotClosed(); return curRow == 0; } @@ -2957,9 +3041,10 @@ public class MonetResultSet extends Mone * called on it, or if it is automatically closed. * * @return true if this ResultSet object is closed; false if it is still open + * @throws SQLException if a database access error occurs or this method is called on a closed result set */ @Override - public boolean isClosed() { + public boolean isClosed() throws SQLException { return header != null && header.isClosed(); } @@ -2967,9 +3052,11 @@ public class MonetResultSet extends Mone * Retrieves whether the cursor is on the first row of this ResultSet object. * * @return true if the cursor is on the first row; false otherwise + * @throws SQLException if a database access error occurs or this method is called on a closed result set */ @Override - public boolean isFirst() { + public boolean isFirst() throws SQLException { + checkNotClosed(); return curRow == 1; } @@ -2977,17 +3064,22 @@ public class MonetResultSet extends Mone * Retrieves whether the cursor is on the last row of this ResultSet object. * * @return true if the cursor is on the last row; false otherwise + * @throws SQLException if a database access error occurs or this method is called on a closed result set */ @Override - public boolean isLast() { + public boolean isLast() throws SQLException { + checkNotClosed(); return curRow == tupleCount; } /** * Moves the cursor to the last row in this ResultSet object. * - * @return true if the cursor is on a valid row; false if there are no rows in the result set - * @throws SQLException if a database access error occurs or the result set type is TYPE_FORWARD_ONLY + * @return true if the cursor is on a valid row; false if there are no rows + * in the result set + * @throws SQLException if a database access error occurs or the result set + * type is TYPE_FORWARD_ONLY + * @throws SQLException if a database access error occurs or this method is called on a closed result set */ @Override public boolean last() throws SQLException { @@ -3063,6 +3155,7 @@ public class MonetResultSet extends Mone */ @Override public boolean rowDeleted() throws SQLException { + checkNotClosed(); return false; } @@ -3082,6 +3175,7 @@ public class MonetResultSet extends Mone */ @Override public boolean rowInserted() throws SQLException { + checkNotClosed(); return false; } @@ -3101,25 +3195,10 @@ public class MonetResultSet extends Mone */ @Override public boolean rowUpdated() throws SQLException { + checkNotClosed(); return false; } - /** - * Adds a warning to the pile of warnings this ResultSet object has. If - * there were no warnings (or clearWarnings was called) this warning will - * be the first, otherwise this warning will get appended to the current - * warning. - * - * @param reason the warning message - */ - public void addWarning(String reason, String sqlstate) { - if (warnings == null) { - warnings = new SQLWarning(reason, sqlstate); - } else { - warnings.setNextWarning(new SQLWarning(reason, sqlstate)); - } - } - /* the next methods are all related to updateable result sets, which we currently do not support */ @Override public void cancelRowUpdates() throws SQLException { @@ -3583,13 +3662,39 @@ public class MonetResultSet extends Mone //== end methods of interface ResultSet /** + * Adds a warning to the pile of warnings this ResultSet object has. If + * there were no warnings (or clearWarnings was called) this warning will + * be the first, otherwise this warning will get appended to the current + * warning. + * + * @param reason the warning message + */ + private void addWarning(String reason, String sqlstate) { + SQLWarning warng = new SQLWarning(reason, sqlstate); + if (warnings == null) { + warnings = warng; + } else { + warnings.setNextWarning(warng); + } + } + + /** + * Local helper method to test whether the ResultSet object is closed + * When closed it throws an SQLException + */ + private void checkNotClosed() throws SQLException { + if (isClosed()) + throw new SQLException("ResultSet is closed", "M1M20"); + } + + /** * Small helper method that formats the "Invalid Column Index number ..." message * and creates a new SQLDataException object whose SQLState is set to "22010": invalid indicator parameter value. * * @param colIdx the column index number * @return a new created SQLDataException object with SQLState 22010 */ - static SQLDataException newSQLInvalidColumnIndexException(int colIdx) { + public static final SQLDataException newSQLInvalidColumnIndexException(int colIdx) { return new SQLDataException("Invalid Column Index number: " + colIdx, "22010"); } @@ -3600,7 +3705,7 @@ public class MonetResultSet extends Mone * @param name the method name * @return a new created SQLFeatureNotSupportedException object with SQLState 0A000 */ - private static SQLFeatureNotSupportedException newSQLFeatureNotSupportedException(String name) { + private static final SQLFeatureNotSupportedException newSQLFeatureNotSupportedException(String name) { return new SQLFeatureNotSupportedException("Method " + name + " not implemented", "0A000"); } }
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetStatement.java +++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetStatement.java @@ -17,6 +17,7 @@ import java.sql.Connection; import java.sql.Statement; import java.sql.ResultSet; import java.sql.SQLException; +import java.sql.SQLFeatureNotSupportedException; import java.sql.SQLWarning; import java.util.ArrayList; import java.util.List; @@ -27,8 +28,8 @@ import java.util.concurrent.locks.Reentr * A Statement suitable for the MonetDB database. * * The object used for executing a static SQL statement and returning - * the results it produces.<br /> - * + * the results it produces. + * * By default, only one {@link ResultSet} object per Statement object can be * open at the same time. Therefore, if the reading of one ResultSet * object is interleaved with the reading of another, each must have @@ -40,7 +41,7 @@ import java.util.concurrent.locks.Reentr * executeQuery() which returns a ResultSet where from results can be * read and executeUpdate() which doesn't return the affected rows. * Commit and rollback are implemented, as is the autoCommit mechanism - * which relies on server side auto commit.<br /> + * which relies on server side auto commit. * Multi-result queries are supported using the getMoreResults() method. * * @author Martin van Dinther @@ -146,7 +147,6 @@ public class MonetStatement extends Mone * ordered according to the order in which they were added to the * batch. The elements in the array returned by the method * executeBatch may be one of the following: - * <br /> * <ol> * <li>A number greater than or equal to zero -- indicates that the * command was processed successfully and is an update count giving @@ -167,7 +167,7 @@ public class MonetStatement extends Mone * If one of the commands attempts to return a result set, an * SQLException is added to the SQLException list and thrown * afterwards execution. Failing queries result in SQLExceptions - * too and may cause subparts of the batch to fail as well.<br /> + * too and may cause subparts of the batch to fail as well. * * @return an array of update counts containing one element for each * command in the batch. The elements of the array are ordered @@ -263,16 +263,15 @@ public class MonetStatement extends Mone } /** - * Cancels this Statement object if both the DBMS and driver support - * aborting an SQL statement. This method can be used by one thread to - * cancel a statement that is being executed by another thread. + * Cancels this Statement object if both the DBMS and driver support aborting an SQL statement. + * This method can be used by one thread to cancel a statement that is being executed by another thread. * - * @throws SQLException if a database access error occurs or the cancel - * operation is not supported + * @throws SQLException - if a database access error occurs or this method is called on a closed Statement + * @throws SQLFeatureNotSupportedException - if the JDBC driver does not support this method */ @Override public void cancel() throws SQLException { - throw new SQLException("Query cancelling is currently not supported by the DBMS.", "0A000"); + throw new SQLFeatureNotSupportedException("Query cancelling is currently not supported by the driver.", "0A000"); } /** @@ -303,6 +302,7 @@ public class MonetStatement extends Mone // close previous ResultSet, if not closed already if (lastResponseList != null) { lastResponseList.close(); + lastResponseList = null; } closed = true; } @@ -509,7 +509,7 @@ public class MonetStatement extends Mone * @param sql an SQL INSERT, UPDATE or DELETE statement or an SQL statement * that returns nothing * @return either the row count for INSERT, UPDATE or DELETE statements, or - * 0 for SQL statements that return nothing<br /> + * 0 for SQL statements that return nothing * @throws SQLException if a database access error occurs or the given SQL * statement produces a ResultSet object */ @@ -697,10 +697,12 @@ 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 + * @see #setMaxFieldSize(int max) */ @Override - public int getMaxFieldSize() { - return 0; + public int getMaxFieldSize() throws SQLException { + return 2*1024*1024*1024 - 2; // MonetDB supports null terminated strings of max 2GB, see function: int UTF8_strlen() } /** @@ -710,9 +712,11 @@ public class MonetStatement extends Mone * * @return the current maximum number of rows for a ResultSet object * produced by this Statement object; zero means there is no limit + * @throws SQLException if a database access error occurs + * @see #setMaxRows(int max) */ @Override - public int getMaxRows() { + public int getMaxRows() throws SQLException { return maxRows; } @@ -721,7 +725,7 @@ public class MonetStatement extends Mone * ResultSet object, and implicitly closes any current ResultSet object(s) * obtained with the method getResultSet. * - * There are no more results when the following is true:<br /> + * There are no more results when the following is true: * (!getMoreResults() && (getUpdateCount() == -1) * * @return true if the next result is a ResultSet object; false if it is @@ -739,7 +743,7 @@ public class MonetStatement extends Mone * ResultSet object(s) according to the instructions specified by the given * flag, and returns true if the next result is a ResultSet object. * - * There are no more results when the following is true:<br /> + * There are no more results when the following is true: * (!getMoreResults() && (getUpdateCount() == -1) * * @param current one of the following Statement constants indicating what @@ -1002,6 +1006,7 @@ public class MonetStatement extends Mone * is no limit * @throws SQLException if a database access error occurs or the * condition max >= 0 is not satisfied + * @see #getMaxFieldSize() */ @Override public void setMaxFieldSize(int max) throws SQLException { @@ -1019,7 +1024,8 @@ public class MonetStatement extends Mone * rows are silently dropped. * * @param max the new max rows limit; zero means there is no limit - * @throws SQLException if the condition max >= 0 is not satisfied + * @throws SQLException if the condition max >= 0 is not satisfied + * @see #getMaxRows() */ @Override public void setMaxRows(int max) throws SQLException { @@ -1149,10 +1155,11 @@ public class MonetStatement extends Mone * @param reason the warning message */ private void addWarning(String reason, String sqlstate) { + SQLWarning warng = new SQLWarning(reason, sqlstate); if (warnings == null) { - warnings = new SQLWarning(reason, sqlstate); + warnings = warng; } else { - warnings.setNextWarning(new SQLWarning(reason, sqlstate)); + warnings.setNextWarning(warng); } }
--- a/src/main/java/nl/cwi/monetdb/mcl/responses/ResultSetResponse.java +++ b/src/main/java/nl/cwi/monetdb/mcl/responses/ResultSetResponse.java @@ -134,10 +134,10 @@ public class ResultSetResponse implement private void populateJdbcSQLTypesArray() { for (int i = 0; i < this.type.length; i++) { int javaSQLtype = MonetDriver.getJavaType(this.type[i]); - if (javaSQLtype == Types.BLOB && con.getBlobAsBinary()) { + if (javaSQLtype == Types.BLOB && con.mapBlobAsVarBinary()) { javaSQLtype = Types.LONGVARBINARY; } - if (javaSQLtype == Types.CLOB && con.getClobAsLongChar()) { + if (javaSQLtype == Types.CLOB && con.mapClobAsVarChar()) { javaSQLtype = Types.LONGVARCHAR; } this.JdbcSQLTypes[i] = javaSQLtype;
--- a/src/main/java/nl/cwi/monetdb/merovingian/Control.java +++ b/src/main/java/nl/cwi/monetdb/merovingian/Control.java @@ -33,7 +33,7 @@ import java.util.Properties; * This class implements the protocol specific bits to perform all * possible actions against a merovingian server that has remote control * facilities enabled. - * <br /> + * * In the merovingian world, other merovingians in the vicinity are * known to each merovingian, allowing to perform cluster wide actions. * The implementation taken in this class is to require one known @@ -56,6 +56,9 @@ public class Control { /** * Constructs a new Control object. * + * @param host - IP address or DNS + * @param port - port number + * @param passphrase - phrase used to pass authorisation * @throws IllegalArgumentException if host, port or passphrase are * null or <= 0 */ @@ -294,10 +297,12 @@ public class Control { /** * Test whether a specific database exists. * - * @param database + * @param database name of database * @return true, iff database already exists. - * @throws MerovingianException - * @throws IOException + * @throws MerovingianException if performing the command failed at + * the merovingian side + * @throws IOException if connecting to or communicating with + * merovingian failed */ public boolean exists(String database) throws MerovingianException, IOException { List<SabaothDB> all = getAllStatuses();
--- a/src/main/java/nl/cwi/monetdb/merovingian/MerovingianException.java +++ b/src/main/java/nl/cwi/monetdb/merovingian/MerovingianException.java @@ -19,6 +19,8 @@ package nl.cwi.monetdb.merovingian; * @version 1.0 */ public class MerovingianException extends Exception { + private static final long serialVersionUID = 101L; + public MerovingianException(String reason) { super(reason); }
--- a/src/main/java/nl/cwi/monetdb/merovingian/SabaothDB.java +++ b/src/main/java/nl/cwi/monetdb/merovingian/SabaothDB.java @@ -15,7 +15,7 @@ import java.util.Date; * * This Class implements a parser for the string representation of a * sabaoth information struct as returned by monetdbd. - * <br /> + * * Currently this class implements version 1 and 2 of the sabdb * serialisation. *
--- a/src/main/java/nl/cwi/monetdb/util/Extract.java +++ b/src/main/java/nl/cwi/monetdb/util/Extract.java @@ -19,7 +19,7 @@ import java.io.InputStreamReader; /** * This file contains a function to extract files from its including Jar package. * - * @author Ying Zhang <Y.Zhang@cwi.nl> + * @author Ying Zhang "Y.Zhang@cwi.nl" * @version 0.1 */
--- a/src/main/java/nl/cwi/monetdb/util/SQLExporter.java +++ b/src/main/java/nl/cwi/monetdb/util/SQLExporter.java @@ -436,6 +436,7 @@ public class SQLExporter extends Exporte * to the output writer. * * @param rs the ResultSet to write out + * @throws SQLException if a database related error occurs */ public void resultSetToTable(ResultSet rs) throws SQLException { ResultSetMetaData md = rs.getMetaData();
--- a/src/main/java/nl/cwi/monetdb/util/SQLRestore.java +++ b/src/main/java/nl/cwi/monetdb/util/SQLRestore.java @@ -98,8 +98,8 @@ public class SQLRestore { /** * Restores a given SQL dump to the database. * - * @param source - * @throws IOException + * @param source file object + * @throws IOException when IO exception occurred */ public void restore(File source) throws IOException { MapiConnection server = new MapiConnection(null,null, "sql", false, true, _host, _port, _dbName);
--- a/tests/Test_Cmanycon.java +++ b/tests/Test_Cmanycon.java @@ -31,8 +31,8 @@ public class Test_Cmanycon { // now try to nicely close them i = 0; - for (Iterator it = cons.iterator(); it.hasNext(); i++) { - Connection con = (Connection)(it.next()); + for (Iterator<Connection> it = cons.iterator(); it.hasNext(); i++) { + Connection con = it.next(); // see if the connection still works System.out.print("Closing Connection " + i + "...");
--- a/tests/Test_PSmanycon.java +++ b/tests/Test_PSmanycon.java @@ -12,10 +12,10 @@ import java.util.*; public class Test_PSmanycon { public static void main(String[] args) throws Exception { // Class.forName("nl.cwi.monetdb.jdbc.MonetDriver"); // not needed anymore for self registering JDBC drivers - List<PreparedStatement> pss = new ArrayList<>(100); // Connections go in here + List<PreparedStatement> pss = new ArrayList<>(100); // PreparedStatements go in here try { - // spawn a lot of Connections, just for fun... + // spawn a lot of Connections with 1 PreparedStatement, just for fun... int i; for (i = 0; i < 50; i++) { System.out.print("Establishing Connection " + i + "..."); @@ -31,8 +31,8 @@ public class Test_PSmanycon { // now try to nicely execute them i = 0; - for (Iterator it = pss.iterator(); it.hasNext(); i++) { - PreparedStatement pstmt = (PreparedStatement)(it.next()); + for (Iterator<PreparedStatement> it = pss.iterator(); it.hasNext(); i++) { + PreparedStatement pstmt = it.next(); // see if the connection still works System.out.print("Executing PreparedStatement " + i + "..."); @@ -43,6 +43,8 @@ public class Test_PSmanycon { if (!rs.next()) throw new Exception("ResultSet is empty"); System.out.print(" result: " + rs.getString(1)); + + // close the connection and associated resources pstmt.getConnection().close(); System.out.println(", done");
--- a/tests/build.xml +++ b/tests/build.xml @@ -44,13 +44,14 @@ Copyright 1997 - July 2008 CWI, August 2 <javac srcdir="${srcdir}" destdir="${builddir}" - debug="true" + debug="false" optimize="false" includeantruntime="false" source="${jvm.version}" target="${jvm.version}" > <include name="**/*.java" /> + <compilerarg line="${javac.flags}" /> <classpath> <pathelement path="${srcdir}" /> <pathelement path="${jdbc_jar}" />