comparison src/main/java/nl/cwi/monetdb/jdbc/MonetConnection.java @ 144:d6abd1ffffbb

Use SQLNonTransientConnectionException instead of SQLException where applicable (SQLState starts with 08) Use SQLDataException instead of SQLException where applicable (SQLState starts with 22) Also updated documentation file: SQLSTATEs which documents the MonetDB JDBC driver specific SQLSTATEs
author Martin van Dinther <martin.van.dinther@monetdbsolutions.com>
date Thu, 03 Aug 2017 18:53:04 +0200 (2017-08-03)
parents 4320e6891536
children 7c9e386fe49a
comparison
equal deleted inserted replaced
143:dcf7879d4862 144:d6abd1ffffbb
17 import java.sql.DatabaseMetaData; 17 import java.sql.DatabaseMetaData;
18 import java.sql.PreparedStatement; 18 import java.sql.PreparedStatement;
19 import java.sql.ResultSet; 19 import java.sql.ResultSet;
20 import java.sql.SQLException; 20 import java.sql.SQLException;
21 import java.sql.SQLFeatureNotSupportedException; 21 import java.sql.SQLFeatureNotSupportedException;
22 import java.sql.SQLNonTransientConnectionException;
22 import java.sql.SQLWarning; 23 import java.sql.SQLWarning;
23 import java.sql.Savepoint; 24 import java.sql.Savepoint;
24 import java.sql.Statement; 25 import java.sql.Statement;
25 import java.util.ArrayList; 26 import java.util.ArrayList;
26 import java.util.Calendar; 27 import java.util.Calendar;
258 f = new File(pre + "-" + i + suf); 259 f = new File(pre + "-" + i + suf);
259 } 260 }
260 261
261 server.debug(f.getAbsolutePath()); 262 server.debug(f.getAbsolutePath());
262 } catch (IOException ex) { 263 } catch (IOException ex) {
263 throw new SQLException("Opening logfile failed: " + ex.getMessage(), "08M01"); 264 throw new SQLNonTransientConnectionException("Opening logfile failed: " + ex.getMessage(), "08M01");
264 } 265 }
265 } 266 }
266 267
267 try { 268 try {
268 List<String> warnings = server.connect(hostname, port, username, password); 269 List<String> warnings = server.connect(hostname, port, username, password);
277 in = server.getReader(); 278 in = server.getReader();
278 out = server.getWriter(); 279 out = server.getWriter();
279 280
280 String error = in.waitForPrompt(); 281 String error = in.waitForPrompt();
281 if (error != null) 282 if (error != null)
282 throw new SQLException((error.length() > 6) ? error.substring(6) : error, "08001"); 283 throw new SQLNonTransientConnectionException((error.length() > 6) ? error.substring(6) : error, "08001");
283 } catch (IOException e) { 284 } catch (IOException e) {
284 throw new SQLException("Unable to connect (" + hostname + ":" + port + "): " + e.getMessage(), "08006"); 285 throw new SQLNonTransientConnectionException("Unable to connect (" + hostname + ":" + port + "): " + e.getMessage(), "08006");
285 } catch (MCLParseException e) { 286 } catch (MCLParseException e) {
286 throw new SQLException(e.getMessage(), "08001"); 287 throw new SQLNonTransientConnectionException(e.getMessage(), "08001");
287 } catch (MCLException e) { 288 } catch (MCLException e) {
288 String[] connex = e.getMessage().split("\n"); 289 String[] connex = e.getMessage().split("\n");
289 SQLException sqle = new SQLException(connex[0], "08001", e); 290 SQLException sqle = new SQLNonTransientConnectionException(connex[0], "08001", e);
290 for (int i = 1; i < connex.length; i++) { 291 for (int i = 1; i < connex.length; i++) {
291 sqle.setNextException(new SQLException(connex[1], "08001")); 292 sqle.setNextException(new SQLNonTransientConnectionException(connex[1], "08001"));
292 } 293 }
293 throw sqle; 294 throw sqle;
294 } 295 }
295 296
296 // we seem to have managed to log in, let's store the 297 // we seem to have managed to log in, let's store the
679 * objects with the given type and concurrency. This method is the 680 * objects with the given type and concurrency. This method is the
680 * same as the prepareStatement method above, but it allows the 681 * same as the prepareStatement method above, but it allows the
681 * default result set type and concurrency to be overridden. 682 * default result set type and concurrency to be overridden.
682 * 683 *
683 * @param sql a String object that is the SQL statement to be sent to the 684 * @param sql a String object that is the SQL statement to be sent to the
684 * database; may contain one or more ? IN parameters 685 * database; may contain one or more ? IN parameters
685 * @param resultSetType a result set type; one of 686 * @param resultSetType a result set type; one of
686 * ResultSet.TYPE_FORWARD_ONLY, ResultSet.TYPE_SCROLL_INSENSITIVE, 687 * ResultSet.TYPE_FORWARD_ONLY, ResultSet.TYPE_SCROLL_INSENSITIVE,
687 * or ResultSet.TYPE_SCROLL_SENSITIVE 688 * or ResultSet.TYPE_SCROLL_SENSITIVE
688 * @param resultSetConcurrency a concurrency type; one of 689 * @param resultSetConcurrency a concurrency type; one of
689 * ResultSet.CONCUR_READ_ONLY or ResultSet.CONCUR_UPDATABLE 690 * ResultSet.CONCUR_READ_ONLY or ResultSet.CONCUR_UPDATABLE
690 * @return a new PreparedStatement object containing the pre-compiled SQL 691 * @return a new PreparedStatement object containing the pre-compiled SQL
691 * statement that will produce ResultSet objects with the given 692 * statement that will produce ResultSet objects with the given
692 * type and concurrency 693 * type and concurrency
693 * @throws SQLException if a database access error occurs or the given 694 * @throws SQLException if a database access error occurs or the given
694 * parameters are not ResultSet constants indicating 695 * parameters are not ResultSet constants indicating
695 * type and concurrency 696 * type and concurrency
696 */ 697 */
697 @Override 698 @Override
698 public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { 699 public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
699 return prepareStatement(sql, resultSetType, resultSetConcurrency, ResultSet.HOLD_CURSORS_OVER_COMMIT); 700 return prepareStatement(sql, resultSetType, resultSetConcurrency, ResultSet.HOLD_CURSORS_OVER_COMMIT);
700 } 701 }
1505 throw new SQLException("milliseconds is less than zero", "M1M05"); 1506 throw new SQLException("milliseconds is less than zero", "M1M05");
1506 1507
1507 try { 1508 try {
1508 server.setSoTimeout(millis); 1509 server.setSoTimeout(millis);
1509 } catch (SocketException e) { 1510 } catch (SocketException e) {
1510 throw new SQLException(e.getMessage(), "08000"); 1511 throw new SQLNonTransientConnectionException(e.getMessage(), "08000");
1511 } 1512 }
1512 } 1513 }
1513 1514
1514 /** 1515 /**
1515 * Retrieves the number of milliseconds the driver will wait for a 1516 * Retrieves the number of milliseconds the driver will wait for a
1528 throw new SQLException("Cannot call on closed Connection", "M1M20"); 1529 throw new SQLException("Cannot call on closed Connection", "M1M20");
1529 1530
1530 try { 1531 try {
1531 return server.getSoTimeout(); 1532 return server.getSoTimeout();
1532 } catch (SocketException e) { 1533 } catch (SocketException e) {
1533 throw new SQLException(e.getMessage(), "08000"); 1534 throw new SQLNonTransientConnectionException(e.getMessage(), "08000");
1534 } 1535 }
1535 } 1536 }
1536 1537
1537 1538
1538 //== end methods of interface java.sql.Connection 1539 //== end methods of interface java.sql.Connection
1544 */ 1545 */
1545 public String getJDBCURL() { 1546 public String getJDBCURL() {
1546 String language = ""; 1547 String language = "";
1547 if (lang == LANG_MAL) 1548 if (lang == LANG_MAL)
1548 language = "?language=mal"; 1549 language = "?language=mal";
1549 return "jdbc:monetdb://" + hostname + ":" + port + "/" + 1550 return "jdbc:monetdb://" + hostname + ":" + port + "/" + database + language;
1550 database + language;
1551 } 1551 }
1552 1552
1553 /** 1553 /**
1554 * Returns whether the BLOB type should be mapped to BINARY type. 1554 * Returns whether the BLOB type should be mapped to BINARY type.
1555 */ 1555 */
1593 (queryTempl[0] == null ? "" : queryTempl[0]) + 1593 (queryTempl[0] == null ? "" : queryTempl[0]) +
1594 command + 1594 command +
1595 (queryTempl[1] == null ? "" : queryTempl[1])); 1595 (queryTempl[1] == null ? "" : queryTempl[1]));
1596 String error = in.waitForPrompt(); 1596 String error = in.waitForPrompt();
1597 if (error != null) 1597 if (error != null)
1598 throw new SQLException(error.substring(6), 1598 throw new SQLException(error.substring(6), error.substring(0, 5));
1599 error.substring(0, 5));
1600 } catch (SocketTimeoutException e) { 1599 } catch (SocketTimeoutException e) {
1601 close(); // JDBC 4.1 semantics: abort() 1600 close(); // JDBC 4.1 semantics: abort()
1602 throw new SQLException("connection timed out", "08M33"); 1601 throw new SQLNonTransientConnectionException("connection timed out", "08M33");
1603 } catch (IOException e) { 1602 } catch (IOException e) {
1604 throw new SQLException(e.getMessage(), "08000"); 1603 throw new SQLNonTransientConnectionException(e.getMessage(), "08000");
1605 } 1604 }
1606 } 1605 }
1607 } 1606 }
1608 1607
1609 /** 1608 /**
1623 (commandTempl[0] == null ? "" : commandTempl[0]) + 1622 (commandTempl[0] == null ? "" : commandTempl[0]) +
1624 command + 1623 command +
1625 (commandTempl[1] == null ? "" : commandTempl[1])); 1624 (commandTempl[1] == null ? "" : commandTempl[1]));
1626 String error = in.waitForPrompt(); 1625 String error = in.waitForPrompt();
1627 if (error != null) 1626 if (error != null)
1628 throw new SQLException(error.substring(6), 1627 throw new SQLException(error.substring(6), error.substring(0, 5));
1629 error.substring(0, 5));
1630 } catch (SocketTimeoutException e) { 1628 } catch (SocketTimeoutException e) {
1631 close(); // JDBC 4.1 semantics, abort() 1629 close(); // JDBC 4.1 semantics, abort()
1632 throw new SQLException("connection timed out", "08M33"); 1630 throw new SQLNonTransientConnectionException("connection timed out", "08M33");
1633 } catch (IOException e) { 1631 } catch (IOException e) {
1634 throw new SQLException(e.getMessage(), "08000"); 1632 throw new SQLNonTransientConnectionException(e.getMessage(), "08000");
1635 } 1633 }
1636 } 1634 }
1637 } 1635 }
1638 1636
1639 /** 1637 /**
1769 * @param id the ID of the result set 1767 * @param id the ID of the result set
1770 * @param tuplecount the total number of tuples in the result set 1768 * @param tuplecount the total number of tuples in the result set
1771 * @param columncount the number of columns in the result set 1769 * @param columncount the number of columns in the result set
1772 * @param rowcount the number of rows in the current block 1770 * @param rowcount the number of rows in the current block
1773 * @param parent the parent that created this Response and will 1771 * @param parent the parent that created this Response and will
1774 * supply new result blocks when necessary 1772 * supply new result blocks when necessary
1775 * @param seq the query sequence number 1773 * @param seq the query sequence number
1776 */ 1774 */
1777 ResultSetResponse( 1775 ResultSetResponse(
1778 int id, 1776 int id,
1779 int tuplecount, 1777 int tuplecount,
1927 /** 1925 /**
1928 * Marks this Response as being completed. A complete Response 1926 * Marks this Response as being completed. A complete Response
1929 * needs to be consistent with regard to its internal data. 1927 * needs to be consistent with regard to its internal data.
1930 * 1928 *
1931 * @throws SQLException if the data currently in this Response is not 1929 * @throws SQLException if the data currently in this Response is not
1932 * sufficient to be consistant 1930 * sufficient to be consistant
1933 */ 1931 */
1934 @Override 1932 @Override
1935 public void complete() throws SQLException { 1933 public void complete() throws SQLException {
1936 String error = ""; 1934 String error = "";
1937 if (!isSet[NAMES]) error = "name header missing\n"; 1935 if (!isSet[NAMES]) error = "name header missing\n";
2725 } 2723 }
2726 if (error != null) { 2724 if (error != null) {
2727 SQLException ret = null; 2725 SQLException ret = null;
2728 String[] errors = error.split("\n"); 2726 String[] errors = error.split("\n");
2729 for (int i = 0; i < errors.length; i++) { 2727 for (int i = 0; i < errors.length; i++) {
2728 SQLException newErr;
2729 if (errors[i].length() >= 6) {
2730 newErr = new SQLException(errors[i].substring(6), errors[i].substring(0, 5));
2731 } else {
2732 newErr = new SQLNonTransientConnectionException(errors[i], "08000");
2733 }
2730 if (ret == null) { 2734 if (ret == null) {
2731 ret = new SQLException(errors[i].substring(6), 2735 ret = newErr;
2732 errors[i].substring(0, 5));
2733 } else { 2736 } else {
2734 ret.setNextException(new SQLException( 2737 ret.setNextException(newErr);
2735 errors[i].substring(6),
2736 errors[i].substring(0, 5)));
2737 } 2738 }
2738 } 2739 }
2739 throw ret; 2740 throw ret;
2740 } 2741 }
2741 } catch (SocketTimeoutException e) { 2742 } catch (SocketTimeoutException e) {
2742 close(); // JDBC 4.1 semantics, abort() 2743 close(); // JDBC 4.1 semantics, abort()
2743 throw new SQLException("connection timed out", "08M33"); 2744 throw new SQLNonTransientConnectionException("connection timed out", "08M33");
2744 } catch (IOException e) { 2745 } catch (IOException e) {
2745 closed = true; 2746 closed = true;
2746 throw new SQLException(e.getMessage() + " (mserver still alive?)", "08000"); 2747 throw new SQLNonTransientConnectionException(e.getMessage() + " (mserver5 still alive?)", "08006");
2747 } 2748 }
2748 } 2749 }
2749 } 2750 }
2750 // }}} 2751 // }}}
2751 2752