From b12536f0c301fb72070982f883957f2e21e4c327 Mon Sep 17 00:00:00 2001 From: kolzeq Date: Mon, 13 Jun 2016 09:54:33 +0200 Subject: [PATCH 1/5] [CONJ-312] NPE correction on resultset.getDate() on null timestamp when using binary protocol --- .../resultset/MariaSelectResultSet.java | 19 +++++++----- src/test/java/org/mariadb/jdbc/DateTest.java | 31 +++++++++++++++++++ 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/mariadb/jdbc/internal/queryresults/resultset/MariaSelectResultSet.java b/src/main/java/org/mariadb/jdbc/internal/queryresults/resultset/MariaSelectResultSet.java index 66d4f19e5..9f187da84 100644 --- a/src/main/java/org/mariadb/jdbc/internal/queryresults/resultset/MariaSelectResultSet.java +++ b/src/main/java/org/mariadb/jdbc/internal/queryresults/resultset/MariaSelectResultSet.java @@ -878,7 +878,7 @@ private String getString(byte[] rawBytes, ColumnInformation columnInfo, Calendar if (isBinaryEncoded) { try { Date date = getDate(rawBytes, columnInfo, cal); - return date == null ? null : date.toString(); + return (date == null) ? null : date.toString(); } catch (ParseException e) { } } @@ -886,7 +886,8 @@ private String getString(byte[] rawBytes, ColumnInformation columnInfo, Calendar case YEAR: if (options.yearIsDateType) { try { - return getDate(rawBytes, columnInfo, cal).toString(); + Date date = getDate(rawBytes, columnInfo, cal); + return (date == null) ? null : date.toString(); } catch (ParseException e) { //eat exception } @@ -898,18 +899,19 @@ private String getString(byte[] rawBytes, ColumnInformation columnInfo, Calendar case TIMESTAMP: case DATETIME: try { - return getTimestamp(rawBytes, columnInfo, cal).toString(); + Timestamp timestamp = getTimestamp(rawBytes, columnInfo, cal); + return (timestamp == null) ? null : timestamp.toString(); } catch (ParseException e) { } break; case DECIMAL: - return getBigDecimal(rawBytes, columnInfo).toString(); + case OLDDECIMAL: + BigDecimal bigDecimal = getBigDecimal(rawBytes, columnInfo); + return (bigDecimal == null ) ? null : bigDecimal.toString(); case GEOMETRY: return new String(rawBytes); case NULL: return null; - case OLDDECIMAL: - return getBigDecimal(rawBytes, columnInfo).toString(); default: return new String(rawBytes, StandardCharsets.UTF_8); } @@ -3257,7 +3259,8 @@ private Date binaryDate(byte[] rawBytes, ColumnInformation columnInfo, Calendar switch (columnInfo.getType()) { case TIMESTAMP: case DATETIME: - return new Date(getTimestamp(rawBytes, columnInfo, cal).getTime()); + Timestamp timestamp = getTimestamp(rawBytes, columnInfo, cal); + return (timestamp == null) ? null : new Date(timestamp.getTime()); default: if (rawBytes.length == 0) { return null; @@ -3305,7 +3308,7 @@ private Time binaryTime(byte[] rawBytes, ColumnInformation columnInfo, Calendar case TIMESTAMP: case DATETIME: Timestamp ts = binaryTimestamp(rawBytes, columnInfo, cal); - return new Time(ts.getTime()); + return (ts == null) ? null : new Time(ts.getTime()); case DATE: Calendar tmpCalendar = Calendar.getInstance(); tmpCalendar.clear(); diff --git a/src/test/java/org/mariadb/jdbc/DateTest.java b/src/test/java/org/mariadb/jdbc/DateTest.java index 513661d26..04de67e72 100644 --- a/src/test/java/org/mariadb/jdbc/DateTest.java +++ b/src/test/java/org/mariadb/jdbc/DateTest.java @@ -535,4 +535,35 @@ public void nullDateString() throws Throwable { } } + /** + * Conj-317 : null pointer exception on getDate on null timestamp. + */ + @Test + public void nullDateFromTimestamp() throws Throwable { + + createTable("nulltimestamp", "ts timestamp(6) NULL "); + Statement stmt = sharedConnection.createStatement(); + try { + stmt.execute("INSERT INTO nulltimestamp (ts) VALUES ('0000-00-00'), (null)"); + + PreparedStatement pst = sharedConnection.prepareStatement("SELECT * FROM nulltimestamp WHERE 1 = ?"); + pst.setInt(1, 1); + ResultSet rs = pst.executeQuery(); + Assert.assertTrue(rs.next()); + Assert.assertNull(rs.getString(1)); + Assert.assertNull(rs.getDate(1)); + Assert.assertNull(rs.getTimestamp(1)); + Assert.assertNull(rs.getTime(1)); + + Assert.assertTrue(rs.next()); + Assert.assertNull(rs.getString(1)); + Assert.assertNull(rs.getDate(1)); + Assert.assertNull(rs.getTimestamp(1)); + Assert.assertNull(rs.getTime(1)); + + } catch (SQLDataException sqldataException) { + //'0000-00-00' doesn't work anymore on mysql 5.7. + } + } + } From 2216614434a1f56cb77632b0e7740dc86991852e Mon Sep 17 00:00:00 2001 From: kolzeq Date: Mon, 13 Jun 2016 10:16:06 +0200 Subject: [PATCH 2/5] [CONJ-309] possible NPE on aurora when failover occur during connection initialisation --- .../org/mariadb/jdbc/internal/failover/impl/AuroraListener.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/mariadb/jdbc/internal/failover/impl/AuroraListener.java b/src/main/java/org/mariadb/jdbc/internal/failover/impl/AuroraListener.java index c65b0ad8d..ef806b176 100644 --- a/src/main/java/org/mariadb/jdbc/internal/failover/impl/AuroraListener.java +++ b/src/main/java/org/mariadb/jdbc/internal/failover/impl/AuroraListener.java @@ -191,7 +191,7 @@ public HostAddress searchByStartName(Protocol secondaryProtocol, List Date: Mon, 13 Jun 2016 12:30:53 +0200 Subject: [PATCH 3/5] [CONJ-293] Permit named pipe connection without host --- .../protocol/AbstractConnectProtocol.java | 40 ++++++++----- .../java/org/mariadb/jdbc/DriverTest.java | 56 +++++++++++-------- 2 files changed, 58 insertions(+), 38 deletions(-) diff --git a/src/main/java/org/mariadb/jdbc/internal/protocol/AbstractConnectProtocol.java b/src/main/java/org/mariadb/jdbc/internal/protocol/AbstractConnectProtocol.java index 046a92b30..a270a6f75 100644 --- a/src/main/java/org/mariadb/jdbc/internal/protocol/AbstractConnectProtocol.java +++ b/src/main/java/org/mariadb/jdbc/internal/protocol/AbstractConnectProtocol.java @@ -57,31 +57,30 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWIS import org.mariadb.jdbc.internal.MariaDbServerCapabilities; import org.mariadb.jdbc.internal.MyX509TrustManager; import org.mariadb.jdbc.internal.failover.FailoverProxy; +import org.mariadb.jdbc.internal.packet.read.Packet; +import org.mariadb.jdbc.internal.packet.read.ReadInitialConnectPacket; +import org.mariadb.jdbc.internal.packet.read.ReadPacketFetcher; +import org.mariadb.jdbc.internal.packet.result.EndOfFilePacket; +import org.mariadb.jdbc.internal.packet.result.ErrorPacket; +import org.mariadb.jdbc.internal.packet.result.OkPacket; import org.mariadb.jdbc.internal.packet.send.*; import org.mariadb.jdbc.internal.protocol.authentication.AuthenticationProviderHolder; import org.mariadb.jdbc.internal.queryresults.ExecutionResult; import org.mariadb.jdbc.internal.queryresults.SingleExecutionResult; import org.mariadb.jdbc.internal.queryresults.resultset.MariaSelectResultSet; -import org.mariadb.jdbc.internal.util.*; +import org.mariadb.jdbc.internal.stream.DecompressInputStream; +import org.mariadb.jdbc.internal.stream.PacketOutputStream; +import org.mariadb.jdbc.internal.util.ExceptionMapper; +import org.mariadb.jdbc.internal.util.Options; +import org.mariadb.jdbc.internal.util.PrepareStatementCache; +import org.mariadb.jdbc.internal.util.Utils; import org.mariadb.jdbc.internal.util.buffer.Buffer; -import org.mariadb.jdbc.internal.packet.read.ReadInitialConnectPacket; -import org.mariadb.jdbc.internal.packet.read.ReadPacketFetcher; -import org.mariadb.jdbc.internal.packet.read.Packet; import org.mariadb.jdbc.internal.util.constant.HaMode; import org.mariadb.jdbc.internal.util.constant.ParameterConstant; import org.mariadb.jdbc.internal.util.constant.ServerStatus; import org.mariadb.jdbc.internal.util.dao.QueryException; -import org.mariadb.jdbc.internal.packet.result.*; -import org.mariadb.jdbc.internal.stream.DecompressInputStream; -import org.mariadb.jdbc.internal.stream.PacketOutputStream; - -import javax.net.ssl.KeyManager; -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLSocket; -import javax.net.ssl.SSLSocketFactory; -import javax.net.ssl.X509TrustManager; +import javax.net.ssl.*; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; @@ -688,6 +687,19 @@ public void connectWithoutProxy() throws QueryException { List addrs = urlParser.getHostAddresses(); List hosts = new LinkedList<>(addrs); + //CONJ-293 : handle name-pipe without host + if (hosts.isEmpty() && options.pipe != null) { + try { + connect(null, 0); + return; + } catch (IOException e) { + if (hosts.isEmpty()) { + throw new QueryException("Could not connect to named pipe '" + options.pipe + "' : " + + e.getMessage(), -1, ExceptionMapper.SqlStates.CONNECTION_EXCEPTION.getSqlState(), e); + } + } + } + // There could be several addresses given in the URL spec, try all of them, and throw exception if all hosts // fail. while (!hosts.isEmpty()) { diff --git a/src/test/java/org/mariadb/jdbc/DriverTest.java b/src/test/java/org/mariadb/jdbc/DriverTest.java index 51e850ccb..ff970e872 100644 --- a/src/test/java/org/mariadb/jdbc/DriverTest.java +++ b/src/test/java/org/mariadb/jdbc/DriverTest.java @@ -1088,33 +1088,41 @@ public void conj25() throws Exception { } @Test - public void namedpipe() throws Exception { - String namedPipeName = null; - try { - ResultSet rs = sharedConnection.createStatement().executeQuery("select @@named_pipe,@@socket"); - rs.next(); - if (rs.getBoolean(1)) { - namedPipeName = rs.getString(2); - } else { - System.out.println("test 'namedpipe' skipped"); + public void namedPipe() throws Exception { + ResultSet rs = sharedConnection.createStatement().executeQuery("select @@named_pipe,@@socket"); + rs.next(); + if (rs.getBoolean(1)) { + String namedPipeName = rs.getString(2); + //skip test if no namedPipeName was obtained because then we do not use a socket connection + Assume.assumeTrue(namedPipeName != null); + try (Connection connection = setConnection("&pipe=" + namedPipeName)) { + Statement stmt = connection.createStatement(); + rs = stmt.executeQuery("SELECT 1"); + assertTrue(rs.next()); + rs.close(); } - } catch (SQLException e) { - //named pipe not found, - System.out.println("test 'namedpipe' skipped"); } + } - //skip test if no namedPipeName was obtained because then we do not use a socket connection - Assume.assumeTrue(namedPipeName != null); - - Connection connection = null; - try { - connection = setConnection("&pipe=" + namedPipeName); - Statement stmt = connection.createStatement(); - ResultSet rs = stmt.executeQuery("SELECT 1"); - assertTrue(rs.next()); - rs.close(); - } finally { - connection.close(); + /** + * CONJ-293 : permit connection to named pipe when no host is defined. + * + * @throws Exception mustn't occur. + */ + @Test + public void namedPipeWithoutHost() throws Exception { + ResultSet rs = sharedConnection.createStatement().executeQuery("select @@named_pipe,@@socket"); + rs.next(); + if (rs.getBoolean(1)) { + String namedPipeName = rs.getString(2); + //skip test if no namedPipeName was obtained because then we do not use a socket connection + Assume.assumeTrue(namedPipeName != null); + try (Connection connection = DriverManager.getConnection("jdbc:mariadb://localhost/testj?user=" + username + "&pipe=" + namedPipeName)) { + Statement stmt = connection.createStatement(); + rs = stmt.executeQuery("SELECT 1"); + assertTrue(rs.next()); + rs.close(); + } } } From 67aaeb1cd42bca8c61656f886114119ab3938d12 Mon Sep 17 00:00:00 2001 From: kolzeq Date: Mon, 13 Jun 2016 15:50:35 +0200 Subject: [PATCH 4/5] version 1.4.6 --- documentation/Changelog.md | 8 +++ pom.xml | 2 +- .../jdbc/internal/util/constant/Version.java | 4 +- .../java/org/mariadb/jdbc/DriverTest.java | 53 +++++++++++-------- 4 files changed, 42 insertions(+), 25 deletions(-) diff --git a/documentation/Changelog.md b/documentation/Changelog.md index 74fb5f541..a21bd2ad9 100644 --- a/documentation/Changelog.md +++ b/documentation/Changelog.md @@ -1,4 +1,5 @@ # Changelog +* [1.4.6](#1.4.6) Released on 13 june 2016 * [1.4.5](#1.4.5) Released on 18 mai 2016 * [1.4.4](#1.4.4) Released on 04 mai 2016 * [1.4.3](#1.4.3) Released on 22 april 2016 @@ -7,6 +8,13 @@ * [1.4.0](#1.4.0) Released on 31 march 2016 --- + +## 1.4.6 +* [CONJ-293] Permit named pipe connection without host +* [CONJ-309] Possible NPE on aurora when failover occur during connection initialisation +* [CONJ-312] NPE while loading a null from TIMESTAMP field using binary protocol +* [misc] batch with one parameter correction (using rewriteBatchedStatements option) + ## 1.4.5 * [CONJ-297] Useless memory consumption when using Statement.setQueryTimeout * [CONJ-294] PrepareStatement on master reconnection after a failover diff --git a/pom.xml b/pom.xml index d4a9f52dc..4768203cb 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ mariadb-java-client jar mariadb-java-client - 1.4.6-SNAPSHOT + 1.4.6 JDBC driver for MariaDB and MySQL https://mariadb.com/kb/en/mariadb/about-mariadb-connector-j/ diff --git a/src/main/java/org/mariadb/jdbc/internal/util/constant/Version.java b/src/main/java/org/mariadb/jdbc/internal/util/constant/Version.java index fcbf2842d..ad7200efd 100644 --- a/src/main/java/org/mariadb/jdbc/internal/util/constant/Version.java +++ b/src/main/java/org/mariadb/jdbc/internal/util/constant/Version.java @@ -51,10 +51,10 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWIS package org.mariadb.jdbc.internal.util.constant; public final class Version { - public static final String version = "1.4.6-SNAPSHOT"; + public static final String version = "1.4.6"; public static final int majorVersion = 1; public static final int minorVersion = 4; public static final int patchVersion = 6; - public static final String qualifier = "SNAPSHOT"; + public static final String qualifier = ""; } \ No newline at end of file diff --git a/src/test/java/org/mariadb/jdbc/DriverTest.java b/src/test/java/org/mariadb/jdbc/DriverTest.java index ff970e872..b411d0e08 100644 --- a/src/test/java/org/mariadb/jdbc/DriverTest.java +++ b/src/test/java/org/mariadb/jdbc/DriverTest.java @@ -1089,18 +1089,22 @@ public void conj25() throws Exception { @Test public void namedPipe() throws Exception { - ResultSet rs = sharedConnection.createStatement().executeQuery("select @@named_pipe,@@socket"); - rs.next(); - if (rs.getBoolean(1)) { - String namedPipeName = rs.getString(2); - //skip test if no namedPipeName was obtained because then we do not use a socket connection - Assume.assumeTrue(namedPipeName != null); - try (Connection connection = setConnection("&pipe=" + namedPipeName)) { - Statement stmt = connection.createStatement(); - rs = stmt.executeQuery("SELECT 1"); - assertTrue(rs.next()); - rs.close(); + try { + ResultSet rs = sharedConnection.createStatement().executeQuery("select @@named_pipe,@@socket"); + rs.next(); + if (rs.getBoolean(1)) { + String namedPipeName = rs.getString(2); + //skip test if no namedPipeName was obtained because then we do not use a socket connection + Assume.assumeTrue(namedPipeName != null); + try (Connection connection = setConnection("&pipe=" + namedPipeName)) { + Statement stmt = connection.createStatement(); + rs = stmt.executeQuery("SELECT 1"); + assertTrue(rs.next()); + rs.close(); + } } + } catch (SQLException e) { + //not on windows } } @@ -1111,18 +1115,23 @@ public void namedPipe() throws Exception { */ @Test public void namedPipeWithoutHost() throws Exception { - ResultSet rs = sharedConnection.createStatement().executeQuery("select @@named_pipe,@@socket"); - rs.next(); - if (rs.getBoolean(1)) { - String namedPipeName = rs.getString(2); - //skip test if no namedPipeName was obtained because then we do not use a socket connection - Assume.assumeTrue(namedPipeName != null); - try (Connection connection = DriverManager.getConnection("jdbc:mariadb://localhost/testj?user=" + username + "&pipe=" + namedPipeName)) { - Statement stmt = connection.createStatement(); - rs = stmt.executeQuery("SELECT 1"); - assertTrue(rs.next()); - rs.close(); + try { + ResultSet rs = sharedConnection.createStatement().executeQuery("select @@named_pipe,@@socket"); + rs.next(); + if (rs.getBoolean(1)) { + String namedPipeName = rs.getString(2); + //skip test if no namedPipeName was obtained because then we do not use a socket connection + Assume.assumeTrue(namedPipeName != null); + try (Connection connection = DriverManager.getConnection("jdbc:mariadb://localhost/testj?user=" + + username + "&pipe=" + namedPipeName)) { + Statement stmt = connection.createStatement(); + rs = stmt.executeQuery("SELECT 1"); + assertTrue(rs.next()); + rs.close(); + } } + } catch (SQLException e) { + //not on windows } } From 89657fcb71e399da4510bd3f21f4a133795f5aea Mon Sep 17 00:00:00 2001 From: diego dupin Date: Mon, 13 Jun 2016 18:01:24 +0200 Subject: [PATCH 5/5] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 94873f96d..45b09ec62 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ or maven : org.mariadb.jdbc mariadb-java-client - 1.4.5 + 1.4.6 ```