Mercurial > hg > monetdb-java
comparison src/main/java/org/monetdb/jdbc/MonetConnection.java @ 408:5540793628d6
Improve code when setting query timeout. It used to call the sys.settimeout(bigint) which is deprecated as of release Jun2020 (11.37.7) and replaced by new sys.setquerytimeout(int).
As the server call was done from two places MonetConnection.isValid() and MonetStatement.internalExecute(), I created a single utlity method which is now called instead.
author | Martin van Dinther <martin.van.dinther@monetdbsolutions.com> |
---|---|
date | Thu, 07 Jan 2021 21:31:03 +0100 (2021-01-07) |
parents | 40a1db14dca5 |
children | 1e278695fe54 |
comparison
equal
deleted
inserted
replaced
407:40a1db14dca5 | 408:5540793628d6 |
---|---|
140 private boolean treatBlobAsVarBinary = true; | 140 private boolean treatBlobAsVarBinary = true; |
141 /** Whether or not CLOB is mapped to Types.VARCHAR instead of Types.CLOB within this connection */ | 141 /** Whether or not CLOB is mapped to Types.VARCHAR instead of Types.CLOB within this connection */ |
142 private boolean treatClobAsVarChar = true; | 142 private boolean treatClobAsVarChar = true; |
143 | 143 |
144 /** The last set query timeout on the server as used by Statement, PreparedStatement and CallableStatement */ | 144 /** The last set query timeout on the server as used by Statement, PreparedStatement and CallableStatement */ |
145 protected int lastSetQueryTimeout = 0; // 0 means no timeout, which is the default on the server | 145 protected int lastSetQueryTimeout; // 0 means no timeout, which is the default on the server |
146 | 146 |
147 | 147 |
148 /** | 148 /** |
149 * Constructor of a Connection for MonetDB. At this moment the | 149 * Constructor of a Connection for MonetDB. At this moment the |
150 * current implementation limits itself to storing the given host, | 150 * current implementation limits itself to storing the given host, |
1309 if (rs != null && rs.next()) { | 1309 if (rs != null && rs.next()) { |
1310 isValid = true; | 1310 isValid = true; |
1311 } | 1311 } |
1312 } | 1312 } |
1313 } catch (SQLException se) { | 1313 } catch (SQLException se) { |
1314 String msg = se.getMessage(); | 1314 final String msg = se.getMessage(); |
1315 // System.out.println(se.getSQLState() + " Con.isValid(): " + msg); | 1315 // System.out.println(se.getSQLState() + " Con.isValid(): " + msg); |
1316 if (msg != null && msg.equalsIgnoreCase("Current transaction is aborted (please ROLLBACK)")) { | 1316 if (msg != null && msg.equalsIgnoreCase("Current transaction is aborted (please ROLLBACK)")) { |
1317 // Must use equalsIgnoreCase() here because up to Jul2017 release 'Current' was 'current' so with lowercase c. | 1317 // Must use equalsIgnoreCase() here because up to Jul2017 release 'Current' was 'current' so with lowercase c. |
1318 // It changed to 'Current' after Jul2017 release. We need to support all server versions. | 1318 // It changed to 'Current' after Jul2017 release. We need to support all server versions. |
1319 // SQLState = 25005 | 1319 // SQLState = 25005 |
1320 isValid = true; | 1320 isValid = true; |
1321 } | 1321 } |
1322 /* ignore stmt errors/exceptions, we are only testing if the connection is still alive and usable */ | 1322 /* ignore stmt errors/exceptions, we are only testing if the connection is still alive and usable */ |
1323 } finally { | 1323 } finally { |
1324 closeResultsetStatement(rs, stmt); | |
1324 /* when changed, reset the original server timeout value on the server */ | 1325 /* when changed, reset the original server timeout value on the server */ |
1325 if (timeout > 0 && original_timeout != this.lastSetQueryTimeout) { | 1326 if (timeout > 0 && original_timeout != this.lastSetQueryTimeout) { |
1326 this.lastSetQueryTimeout = original_timeout; | 1327 this.lastSetQueryTimeout = original_timeout; |
1327 Statement stmt2 = null; | |
1328 try { | 1328 try { |
1329 /* we have to set in the server explicitly, because the test 'queryTimeout != connection.lastSetQueryTimeout' | 1329 /* we have to set in the server explicitly, because the test 'queryTimeout != connection.lastSetQueryTimeout' |
1330 on MonetStatement.internalExecute(sql) won't pass and the server won't be set back */ | 1330 on MonetStatement.internalExecute(sql) won't pass and the server won't be set back */ |
1331 stmt2 = this.createStatement(); | 1331 setQueryTimeout(original_timeout); |
1332 stmt2.execute("CALL \"sys\".\"settimeout\"(" + this.lastSetQueryTimeout + ")"); | |
1333 } catch (SQLException se) { | 1332 } catch (SQLException se) { |
1334 /* ignore stmt errors/exceptions, we are only testing if the connection is still alive and usable */ | 1333 /* ignore stmt errors/exceptions, we are only testing if the connection is still alive and usable */ |
1335 } finally { | |
1336 closeResultsetStatement(null, stmt2); | |
1337 } | 1334 } |
1338 } | 1335 } |
1339 closeResultsetStatement(rs, stmt); | |
1340 } | 1336 } |
1341 return isValid; | 1337 return isValid; |
1342 } | 1338 } |
1343 | 1339 |
1344 /** | 1340 /** |
1634 | 1630 |
1635 | 1631 |
1636 //== internal helper methods which do not belong to the JDBC interface | 1632 //== internal helper methods which do not belong to the JDBC interface |
1637 | 1633 |
1638 /** | 1634 /** |
1635 * Local helper method to test whether the Connection object is closed | |
1636 * When closed it throws an SQLException | |
1637 */ | |
1638 private void checkNotClosed() throws SQLException { | |
1639 if (closed) | |
1640 throw new SQLException("Connection is closed", "M1M20"); | |
1641 } | |
1642 | |
1643 /** | |
1644 * Utility method to call sys.setquerytimeout(int); procedure on the connected server. | |
1645 * It is called from: MonetConnection.isValid() and MonetStatement.internalExecute() | |
1646 */ | |
1647 void setQueryTimeout(final int millis) throws SQLException { | |
1648 if (millis < 0) | |
1649 throw new SQLException("query timeout milliseconds is less than zero", "M1M05"); | |
1650 | |
1651 checkNotClosed(); | |
1652 Statement st = null; | |
1653 try { | |
1654 // as of release Jun2020 (11.37.7) the function sys.settimeout(bigint) is deprecated and replaced by new sys.setquerytimeout(int) | |
1655 final boolean postJun2020 = (getDatabaseMajorVersion() >=11) && (getDatabaseMinorVersion() >= 37); | |
1656 final String callstmt = postJun2020 ? "CALL sys.\"setquerytimeout\"(" + millis + ")" | |
1657 : "CALL sys.\"settimeout\"(" + millis + ")"; | |
1658 // for debug: System.out.println("Before: " + callstmt); | |
1659 st = createStatement(); | |
1660 st.execute(callstmt); | |
1661 // for debug: System.out.println("After : " + callstmt); | |
1662 | |
1663 this.lastSetQueryTimeout = millis; | |
1664 } | |
1665 /* do not catch SQLException here, as we want to know it when it fails */ | |
1666 finally { | |
1667 closeResultsetStatement(null, st); | |
1668 } | |
1669 } | |
1670 | |
1671 /** | |
1639 * @return whether the JDBC BLOB type should be mapped to VARBINARY type. | 1672 * @return whether the JDBC BLOB type should be mapped to VARBINARY type. |
1640 * This allows generic JDBC programs to fetch Blob data via getBytes() | 1673 * This allows generic JDBC programs to fetch Blob data via getBytes() |
1641 * instead of getBlob() and Blob.getBinaryStream() to reduce overhead. | 1674 * instead of getBlob() and Blob.getBinaryStream() to reduce overhead. |
1642 * It is called from: MonetResultSet and MonetPreparedStatement | 1675 * It is called from: MonetResultSet and MonetPreparedStatement |
1643 */ | 1676 */ |
1651 * instead of getClob() and Clob.getCharacterStream() to reduce overhead. | 1684 * instead of getClob() and Clob.getCharacterStream() to reduce overhead. |
1652 * It is called from: MonetResultSet and MonetPreparedStatement | 1685 * It is called from: MonetResultSet and MonetPreparedStatement |
1653 */ | 1686 */ |
1654 boolean mapClobAsVarChar() { | 1687 boolean mapClobAsVarChar() { |
1655 return treatClobAsVarChar; | 1688 return treatClobAsVarChar; |
1656 } | |
1657 | |
1658 /** | |
1659 * Local helper method to test whether the Connection object is closed | |
1660 * When closed it throws an SQLException | |
1661 */ | |
1662 private void checkNotClosed() throws SQLException { | |
1663 if (closed) | |
1664 throw new SQLException("Connection is closed", "M1M20"); | |
1665 } | 1689 } |
1666 | 1690 |
1667 /** | 1691 /** |
1668 * @return the MonetDB JDBC Connection URL (without user name and password). | 1692 * @return the MonetDB JDBC Connection URL (without user name and password). |
1669 * It is called from: getURL()in MonetDatabaseMetaData | 1693 * It is called from: getURL()in MonetDatabaseMetaData |
1697 | 1721 |
1698 // Internal caches for 3 static mserver environment values, so they aren't queried from mserver again and again | 1722 // Internal caches for 3 static mserver environment values, so they aren't queried from mserver again and again |
1699 private String env_current_user; | 1723 private String env_current_user; |
1700 private String env_monet_version; | 1724 private String env_monet_version; |
1701 private int maxConnections; | 1725 private int maxConnections; |
1702 private int databaseMajorVersion; | |
1703 private int databaseMinorVersion; | |
1704 | 1726 |
1705 /** | 1727 /** |
1706 * Utility method to fetch 3 mserver environment values combined in one query for efficiency. | 1728 * Utility method to fetch 3 mserver environment values combined in one query for efficiency. |
1707 * We currently fetch the env values of: current_user, monet_version and max_clients. | 1729 * We currently fetch the env values of: current_user, monet_version and max_clients. |
1708 * We cache them such that we do not need to query the server again and again. | 1730 * We cache them such that we do not need to query the server again and again. |
1755 getEnvValues(); | 1777 getEnvValues(); |
1756 return env_current_user; | 1778 return env_current_user; |
1757 } | 1779 } |
1758 | 1780 |
1759 /** | 1781 /** |
1782 * @return the maximum number of active connections possible at one time; | |
1783 * a result of zero means that there is no limit or the limit is not known | |
1784 * It is called from: MonetDatabaseMetaData | |
1785 */ | |
1786 int getMaxConnections() throws SQLException { | |
1787 if (maxConnections == 0) | |
1788 getEnvValues(); | |
1789 return maxConnections; | |
1790 } | |
1791 | |
1792 /** | |
1760 * @return the MonetDB Database Server version string. | 1793 * @return the MonetDB Database Server version string. |
1761 * It is called from: MonetDatabaseMetaData | 1794 * It is called from: MonetDatabaseMetaData |
1762 */ | 1795 */ |
1763 String getDatabaseProductVersion() throws SQLException { | 1796 String getDatabaseProductVersion() throws SQLException { |
1764 if (env_monet_version == null) | 1797 if (env_monet_version == null) |
1767 if (env_monet_version != null) | 1800 if (env_monet_version != null) |
1768 return env_monet_version; | 1801 return env_monet_version; |
1769 return ""; | 1802 return ""; |
1770 } | 1803 } |
1771 | 1804 |
1805 private int databaseMajorVersion; | |
1772 /** | 1806 /** |
1773 * @return the MonetDB Database Server major version number. | 1807 * @return the MonetDB Database Server major version number. |
1774 * It is called from: MonetDatabaseMetaData | 1808 * The number is extracted from the env_monet_version the first time and cached for next calls. |
1809 * It is called from: MonetDatabaseMetaData and MonetConnection | |
1775 */ | 1810 */ |
1776 int getDatabaseMajorVersion() throws SQLException { | 1811 int getDatabaseMajorVersion() throws SQLException { |
1777 if (databaseMajorVersion == 0) { | 1812 if (databaseMajorVersion == 0) { |
1778 if (env_monet_version == null) | 1813 if (env_monet_version == null) |
1779 getEnvValues(); | 1814 getEnvValues(); |
1788 } | 1823 } |
1789 } | 1824 } |
1790 return databaseMajorVersion; | 1825 return databaseMajorVersion; |
1791 } | 1826 } |
1792 | 1827 |
1828 private int databaseMinorVersion; | |
1793 /** | 1829 /** |
1794 * @return the MonetDB Database Server minor version number. | 1830 * @return the MonetDB Database Server minor version number. |
1795 * It is called from: MonetDatabaseMetaData | 1831 * The number is extracted from the env_monet_version the first time and cached for next calls. |
1832 * It is called from: MonetDatabaseMetaData and MonetConnection | |
1796 */ | 1833 */ |
1797 int getDatabaseMinorVersion() throws SQLException { | 1834 int getDatabaseMinorVersion() throws SQLException { |
1798 if (databaseMinorVersion == 0) { | 1835 if (databaseMinorVersion == 0) { |
1799 if (env_monet_version == null) | 1836 if (env_monet_version == null) |
1800 getEnvValues(); | 1837 getEnvValues(); |
1811 // ignore | 1848 // ignore |
1812 } | 1849 } |
1813 } | 1850 } |
1814 } | 1851 } |
1815 return databaseMinorVersion; | 1852 return databaseMinorVersion; |
1816 } | |
1817 | |
1818 /** | |
1819 * @return the maximum number of active connections possible at one time; | |
1820 * a result of zero means that there is no limit or the limit is not known | |
1821 * It is called from: MonetDatabaseMetaData | |
1822 */ | |
1823 int getMaxConnections() throws SQLException { | |
1824 if (maxConnections == 0) | |
1825 getEnvValues(); | |
1826 return maxConnections; | |
1827 } | 1853 } |
1828 | 1854 |
1829 | 1855 |
1830 // Internal cache for determining if system table sys.privilege_codes (new as of Jul2017 release) exists on connected server | 1856 // Internal cache for determining if system table sys.privilege_codes (new as of Jul2017 release) exists on connected server |
1831 private boolean queriedPrivilege_codesTable = false; | 1857 private boolean queriedPrivilege_codesTable = false; |
2088 private final boolean cacheSizeSetExplicitly; | 2114 private final boolean cacheSizeSetExplicitly; |
2089 /** Whether we should send an Xclose command to the server | 2115 /** Whether we should send an Xclose command to the server |
2090 * if we close this Response */ | 2116 * if we close this Response */ |
2091 private boolean destroyOnClose; | 2117 private boolean destroyOnClose; |
2092 /** the offset to be used on Xexport queries */ | 2118 /** the offset to be used on Xexport queries */ |
2093 private int blockOffset = 0; | 2119 private int blockOffset; |
2094 | 2120 |
2095 /** A parser for header lines */ | 2121 /** A parser for header lines */ |
2096 private final HeaderLineParser hlp; | 2122 private final HeaderLineParser hlp; |
2097 | 2123 |
2098 /** A boolean array telling whether the headers are set or not */ | 2124 /** A boolean array telling whether the headers are set or not */ |
2099 private final boolean[] isSet; | 2125 private final boolean[] isSet; |
2100 private static final int NAMES = 0; | 2126 private static final int NAMES = 0; |
2101 private static final int TYPES = 1; | 2127 private static final int TYPES = 1; |
2102 private static final int TABLES = 2; | 2128 private static final int TABLES = 2; |
2103 private static final int LENS = 3; | 2129 private static final int LENS = 3; |
2104 | 2130 |
2105 | 2131 |
2106 /** | 2132 /** |
2107 * Sole constructor, which requires a MonetConnection parent to | 2133 * Sole constructor, which requires a MonetConnection parent to |
2108 * be given. | 2134 * be given. |