diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4dbc59704..16668ca64 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,20 @@
# Change Log
+## [3.0.9](https://github.com/mariadb-corporation/mariadb-connector-j/tree/3.0.9) (Nov 2022)
+[Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.0.8...3.0.9)
+* 2.7.7 merge
+* CONJ-1012 stored procedure register output parameter as null if set before registerOutParameter command
+* CONJ-1017 Calendar possible race condition, cause wrong timestamp setting
+
+## [2.7.7](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.7.7) (Nov 2022)
+[Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.7.6...2.7.7)
+
+* CONJ-1021 GSSAPI authentication might result in connection reset
+* CONJ-1019 DatabaseMetaData.getImportedKeys should return real value for PK_NAME column
+* CONJ-1016 avoid splitting BULK command into multiple commands in case of prepareStatement.setNull() use
+* CONJ-1011 correcting possible NPE when using statement.cancel() that coincide with statement.close() in another thread
+* CONJ-1007 Socket file descriptors are leaked after connecting with unix socket if DB is not up running
+
## [3.0.8](https://github.com/mariadb-corporation/mariadb-connector-j/tree/3.0.8) (Sept 2022)
[Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.0.7...3.0.8)
diff --git a/pom.xml b/pom.xml
index 83bf6e879..b026aa8dc 100644
--- a/pom.xml
+++ b/pom.xml
@@ -7,7 +7,7 @@
mariadb-java-client
jar
mariadb-java-client
- 3.0.8
+ 3.0.9
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/BaseCallableStatement.java b/src/main/java/org/mariadb/jdbc/BaseCallableStatement.java
index df5faa1b9..92d0e3d09 100644
--- a/src/main/java/org/mariadb/jdbc/BaseCallableStatement.java
+++ b/src/main/java/org/mariadb/jdbc/BaseCallableStatement.java
@@ -128,7 +128,8 @@ protected void outputResultFromRes(int i) throws SQLException {
public void registerOutParameter(int parameterIndex, int sqlType) throws SQLException {
checkIndex(parameterIndex);
outputParameters.add(parameterIndex);
- parameters.set(parameterIndex - 1, Parameter.NULL_PARAMETER);
+ if (!parameters.containsKey(parameterIndex - 1))
+ parameters.set(parameterIndex - 1, Parameter.NULL_PARAMETER);
}
private void checkIndex(int index) throws SQLException {
diff --git a/src/main/java/org/mariadb/jdbc/ClientPreparedStatement.java b/src/main/java/org/mariadb/jdbc/ClientPreparedStatement.java
index 2d4927e48..dc4fb2b21 100644
--- a/src/main/java/org/mariadb/jdbc/ClientPreparedStatement.java
+++ b/src/main/java/org/mariadb/jdbc/ClientPreparedStatement.java
@@ -509,7 +509,12 @@ public long[] executeLargeBatch() throws SQLException {
@Override
public void close() throws SQLException {
if (prepareResult != null) {
- prepareResult.close(this.con.getClient());
+ lock.lock();
+ try {
+ prepareResult.close(this.con.getClient());
+ } finally {
+ lock.unlock();
+ }
}
con.fireStatementClosed(this);
super.close();
diff --git a/src/main/java/org/mariadb/jdbc/DatabaseMetaData.java b/src/main/java/org/mariadb/jdbc/DatabaseMetaData.java
index 1debd8b84..c531bff6f 100644
--- a/src/main/java/org/mariadb/jdbc/DatabaseMetaData.java
+++ b/src/main/java/org/mariadb/jdbc/DatabaseMetaData.java
@@ -7,10 +7,7 @@
import java.sql.*;
import java.sql.Statement;
import java.text.ParseException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Locale;
+import java.util.*;
import org.mariadb.jdbc.client.DataType;
import org.mariadb.jdbc.client.result.CompleteResult;
import org.mariadb.jdbc.client.result.Result;
@@ -202,7 +199,10 @@ private int parseIdentifierList(char[] part, int startPos, List list
*/
private ResultSet getImportedKeys(
String tableDef, String tableName, String catalog, org.mariadb.jdbc.Connection connection)
- throws ParseException {
+ throws Exception, SQLException {
+ boolean importedKeysWithConstraintNames =
+ Boolean.parseBoolean(
+ conf.nonMappedOptions().getProperty("importedKeysWithConstraintNames", "true"));
String[] columnNames = {
"PKTABLE_CAT", "PKTABLE_SCHEM", "PKTABLE_NAME",
"PKCOLUMN_NAME", "FKTABLE_CAT", "FKTABLE_SCHEM",
@@ -255,7 +255,7 @@ private ResultSet getImportedKeys(
onDeleteReferenceAction = getImportedKeyAction(referenceAction);
}
}
-
+ Map> externalInfos = new HashMap<>();
for (int i = 0; i < primaryKeyCols.size(); i++) {
String[] row = new String[columnNames.length];
@@ -274,7 +274,37 @@ private ResultSet getImportedKeys(
row[9] = Integer.toString(onUpdateReferenceAction); // UPDATE_RULE
row[10] = Integer.toString(onDeleteReferenceAction); // DELETE_RULE
row[11] = constraintName.name; // FK_NAME
- row[12] = null; // PK_NAME - unlike using information_schema, cannot know constraint name
+ if (importedKeysWithConstraintNames) {
+ String ext =
+ (pkTable.schema == null ? "" : quoteIdentifier(pkTable.schema) + ".")
+ + quoteIdentifier(pkTable.name);
+ if (!externalInfos.containsKey(ext)) {
+ externalInfos.put(ext, getExtImportedKeys(ext, connection));
+ }
+ row[12] = null; // PK_NAME
+ Map externalInfo = externalInfos.get(ext);
+ if (externalInfo != null) {
+ for (Map.Entry entry : externalInfo.entrySet()) {
+ boolean foundAll = true;
+
+ for (String keyPart : entry.getKey()) {
+ boolean foundKey = false;
+ for (Identifier keyCol : primaryKeyCols) {
+ if (keyCol.name.equals(keyPart)) {
+ foundKey = true;
+ break;
+ }
+ }
+ if (!foundKey) foundAll = false;
+ }
+ if (foundAll) {
+ row[12] = entry.getValue();
+ }
+ }
+ }
+ } else {
+ row[12] = null; // PK_NAME
+ }
row[13] = Integer.toString(DatabaseMetaData.importedKeyNotDeferrable); // DEFERRABILITY
data.add(row);
}
@@ -301,6 +331,41 @@ private ResultSet getImportedKeys(
columnNames, dataTypes, arr, connection.getContext(), ColumnFlags.PRIMARY_KEY);
}
+ private Map getExtImportedKeys(
+ String tableName, org.mariadb.jdbc.Connection connection) throws SQLException {
+ ResultSet rs = connection.createStatement().executeQuery("SHOW CREATE TABLE " + tableName);
+ rs.next();
+ String refTableDef = rs.getString(2);
+ Map res = new HashMap<>();
+ String[] parts = refTableDef.split("\n");
+ for (int i = 1; i < parts.length - 1; i++) {
+ String part = parts[i].trim();
+ if (part.startsWith("`")) {
+ // field
+ continue;
+ }
+ if (part.startsWith("PRIMARY KEY") || part.startsWith("UNIQUE KEY")) {
+ String name = "PRIMARY";
+ if (part.indexOf("`") < part.indexOf("(")) {
+ int offset = part.indexOf("`");
+ name = part.substring(offset + 1, part.indexOf("`", offset + 1));
+ }
+
+ String subPart = part.substring(part.indexOf("(") + 1, part.lastIndexOf(")"));
+ List cols = new ArrayList<>();
+ int pos = 0;
+ while (pos < subPart.length()) {
+ pos = subPart.indexOf("`", pos);
+ int endpos = subPart.indexOf("`", pos + 1);
+ cols.add(subPart.substring(pos + 1, endpos));
+ pos = endpos + 1;
+ }
+ res.put(cols.toArray(new String[0]), name);
+ }
+ }
+ return res;
+ }
+
/**
* Retrieves a description of the primary key columns that are referenced by the given table's
* foreign key columns (the primary keys imported by a table). They are ordered by PKTABLE_CAT,
diff --git a/src/main/java/org/mariadb/jdbc/message/client/BulkExecutePacket.java b/src/main/java/org/mariadb/jdbc/message/client/BulkExecutePacket.java
index 3770f8fcc..d0a1a69d7 100644
--- a/src/main/java/org/mariadb/jdbc/message/client/BulkExecutePacket.java
+++ b/src/main/java/org/mariadb/jdbc/message/client/BulkExecutePacket.java
@@ -162,7 +162,8 @@ public int encode(Writer writer, Context context, Prepare newPrepareResult)
// ensure type has not changed
for (int i = 0; i < parameterCount; i++) {
if (parameterHeaderType[i].getBinaryEncodeType()
- != parameters.get(i).getBinaryEncodeType()) {
+ != parameters.get(i).getBinaryEncodeType()
+ && !parameters.get(i).isNull()) {
writer.flush();
// reset header type
for (int j = 0; j < parameterCount; j++) {
diff --git a/src/main/java/org/mariadb/jdbc/plugin/authentication/addon/gssapi/StandardGssapiAuthentication.java b/src/main/java/org/mariadb/jdbc/plugin/authentication/addon/gssapi/StandardGssapiAuthentication.java
index 331cdaec7..14ffcbd9b 100644
--- a/src/main/java/org/mariadb/jdbc/plugin/authentication/addon/gssapi/StandardGssapiAuthentication.java
+++ b/src/main/java/org/mariadb/jdbc/plugin/authentication/addon/gssapi/StandardGssapiAuthentication.java
@@ -81,8 +81,8 @@ public void authenticate(
byte[] inToken = new byte[0];
byte[] outToken;
- while (!context.isEstablished()) {
+ while (true) {
outToken = context.initSecContext(inToken, 0, inToken.length);
// Send a token to the peer if one was generated by acceptSecContext
@@ -90,11 +90,12 @@ public void authenticate(
out.writeBytes(outToken);
out.flush();
}
- if (!context.isEstablished()) {
- ReadableByteBuf buf = in.readPacket(true);
- inToken = new byte[buf.readableBytes()];
- buf.readBytes(inToken);
+ if (context.isEstablished()) {
+ break;
}
+ ReadableByteBuf buf = in.readPacket(true);
+ inToken = new byte[buf.readableBytes()];
+ buf.readBytes(inToken);
}
} catch (GSSException le) {
diff --git a/src/main/java/org/mariadb/jdbc/plugin/authentication/addon/gssapi/WindowsNativeSspiAuthentication.java b/src/main/java/org/mariadb/jdbc/plugin/authentication/addon/gssapi/WindowsNativeSspiAuthentication.java
index 63a78b079..e29a37a9c 100644
--- a/src/main/java/org/mariadb/jdbc/plugin/authentication/addon/gssapi/WindowsNativeSspiAuthentication.java
+++ b/src/main/java/org/mariadb/jdbc/plugin/authentication/addon/gssapi/WindowsNativeSspiAuthentication.java
@@ -37,20 +37,23 @@ public void authenticate(
// Step 1: send token to server
byte[] tokenForTheServerOnTheClient = clientContext.getToken();
- out.writeBytes(tokenForTheServerOnTheClient);
- out.flush();
-
- // Step 2: read server response token
- if (clientContext.isContinue()) {
- ReadableByteBuf buf = in.readPacket(true);
- byte[] tokenForTheClientOnTheServer = new byte[buf.readableBytes()];
- buf.readBytes(tokenForTheClientOnTheServer);
- Sspi.SecBufferDesc continueToken =
- new SspiUtil.ManagedSecBufferDesc(Sspi.SECBUFFER_TOKEN, tokenForTheClientOnTheServer);
- clientContext.initialize(clientContext.getHandle(), continueToken, servicePrincipalName);
+ if (tokenForTheServerOnTheClient != null && tokenForTheServerOnTheClient.length > 0) {
+ out.writeBytes(tokenForTheServerOnTheClient);
+ out.flush();
+ }
+ if (!clientContext.isContinue()) {
+ break;
}
- } while (clientContext.isContinue());
+ // Step 2: read server response token
+ ReadableByteBuf buf = in.readPacket(true);
+ byte[] tokenForTheClientOnTheServer = new byte[buf.readableBytes()];
+ buf.readBytes(tokenForTheClientOnTheServer);
+ Sspi.SecBufferDesc continueToken =
+ new SspiUtil.ManagedSecBufferDesc(Sspi.SECBUFFER_TOKEN, tokenForTheClientOnTheServer);
+ clientContext.initialize(clientContext.getHandle(), continueToken, servicePrincipalName);
+
+ } while (true);
clientContext.dispose();
}
diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/DateCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/DateCodec.java
index ba9b98bde..9ae3c6430 100644
--- a/src/main/java/org/mariadb/jdbc/plugin/codec/DateCodec.java
+++ b/src/main/java/org/mariadb/jdbc/plugin/codec/DateCodec.java
@@ -215,11 +215,14 @@ public void encodeText(
public void encodeBinary(Writer encoder, Object value, Calendar providedCal, Long maxLength)
throws IOException {
Calendar cal = providedCal == null ? Calendar.getInstance() : providedCal;
- cal.setTimeInMillis(((java.util.Date) value).getTime());
- encoder.writeByte(4); // length
- encoder.writeShort((short) cal.get(Calendar.YEAR));
- encoder.writeByte(((cal.get(Calendar.MONTH) + 1) & 0xff));
- encoder.writeByte((cal.get(Calendar.DAY_OF_MONTH) & 0xff));
+ synchronized (cal) {
+ cal.clear();
+ cal.setTimeInMillis(((java.util.Date) value).getTime());
+ encoder.writeByte(4); // length
+ encoder.writeShort((short) cal.get(Calendar.YEAR));
+ encoder.writeByte(((cal.get(Calendar.MONTH) + 1) & 0xff));
+ encoder.writeByte((cal.get(Calendar.DAY_OF_MONTH) & 0xff));
+ }
}
public int getBinaryEncodeType() {
diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/TimeCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/TimeCodec.java
index 67728a4e0..5db864c48 100644
--- a/src/main/java/org/mariadb/jdbc/plugin/codec/TimeCodec.java
+++ b/src/main/java/org/mariadb/jdbc/plugin/codec/TimeCodec.java
@@ -231,23 +231,26 @@ public void encodeText(
public void encodeBinary(Writer encoder, Object value, Calendar providedCal, Long maxLength)
throws IOException {
Calendar cal = providedCal == null ? Calendar.getInstance() : providedCal;
- cal.setTime((Time) value);
- cal.set(Calendar.DAY_OF_MONTH, 1);
- if (cal.get(Calendar.MILLISECOND) > 0) {
- encoder.writeByte((byte) 12);
- encoder.writeByte((byte) 0);
- encoder.writeInt(0);
- encoder.writeByte((byte) cal.get(Calendar.HOUR_OF_DAY));
- encoder.writeByte((byte) cal.get(Calendar.MINUTE));
- encoder.writeByte((byte) cal.get(Calendar.SECOND));
- encoder.writeInt(cal.get(Calendar.MILLISECOND) * 1000);
- } else {
- encoder.writeByte((byte) 8); // length
- encoder.writeByte((byte) 0);
- encoder.writeInt(0);
- encoder.writeByte((byte) cal.get(Calendar.HOUR_OF_DAY));
- encoder.writeByte((byte) cal.get(Calendar.MINUTE));
- encoder.writeByte((byte) cal.get(Calendar.SECOND));
+ synchronized (cal) {
+ cal.clear();
+ cal.setTime((Time) value);
+ cal.set(Calendar.DAY_OF_MONTH, 1);
+ if (cal.get(Calendar.MILLISECOND) > 0) {
+ encoder.writeByte((byte) 12);
+ encoder.writeByte((byte) 0);
+ encoder.writeInt(0);
+ encoder.writeByte((byte) cal.get(Calendar.HOUR_OF_DAY));
+ encoder.writeByte((byte) cal.get(Calendar.MINUTE));
+ encoder.writeByte((byte) cal.get(Calendar.SECOND));
+ encoder.writeInt(cal.get(Calendar.MILLISECOND) * 1000);
+ } else {
+ encoder.writeByte((byte) 8); // length
+ encoder.writeByte((byte) 0);
+ encoder.writeInt(0);
+ encoder.writeByte((byte) cal.get(Calendar.HOUR_OF_DAY));
+ encoder.writeByte((byte) cal.get(Calendar.MINUTE));
+ encoder.writeByte((byte) cal.get(Calendar.SECOND));
+ }
}
}
diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/TimestampCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/TimestampCodec.java
index 440051a72..70db6cd37 100644
--- a/src/main/java/org/mariadb/jdbc/plugin/codec/TimestampCodec.java
+++ b/src/main/java/org/mariadb/jdbc/plugin/codec/TimestampCodec.java
@@ -352,26 +352,29 @@ public void encodeText(
@Override
public void encodeBinary(Writer encoder, Object value, Calendar providedCal, Long maxLength)
throws IOException {
- Calendar cal = providedCal == null ? Calendar.getInstance() : providedCal;
Timestamp ts = (Timestamp) value;
- cal.setTimeInMillis(ts.getTime());
- if (ts.getNanos() == 0) {
- encoder.writeByte(7); // length
- encoder.writeShort((short) cal.get(Calendar.YEAR));
- encoder.writeByte((cal.get(Calendar.MONTH) + 1));
- encoder.writeByte(cal.get(Calendar.DAY_OF_MONTH));
- encoder.writeByte(cal.get(Calendar.HOUR_OF_DAY));
- encoder.writeByte(cal.get(Calendar.MINUTE));
- encoder.writeByte(cal.get(Calendar.SECOND));
- } else {
- encoder.writeByte(11); // length
- encoder.writeShort((short) cal.get(Calendar.YEAR));
- encoder.writeByte((cal.get(Calendar.MONTH) + 1));
- encoder.writeByte(cal.get(Calendar.DAY_OF_MONTH));
- encoder.writeByte(cal.get(Calendar.HOUR_OF_DAY));
- encoder.writeByte(cal.get(Calendar.MINUTE));
- encoder.writeByte(cal.get(Calendar.SECOND));
- encoder.writeInt(ts.getNanos() / 1000);
+ Calendar cal = providedCal == null ? Calendar.getInstance() : providedCal;
+ synchronized (cal) {
+ cal.clear();
+ cal.setTimeInMillis(ts.getTime());
+ if (ts.getNanos() == 0) {
+ encoder.writeByte(7); // length
+ encoder.writeShort((short) cal.get(Calendar.YEAR));
+ encoder.writeByte((cal.get(Calendar.MONTH) + 1));
+ encoder.writeByte(cal.get(Calendar.DAY_OF_MONTH));
+ encoder.writeByte(cal.get(Calendar.HOUR_OF_DAY));
+ encoder.writeByte(cal.get(Calendar.MINUTE));
+ encoder.writeByte(cal.get(Calendar.SECOND));
+ } else {
+ encoder.writeByte(11); // length
+ encoder.writeShort((short) cal.get(Calendar.YEAR));
+ encoder.writeByte((cal.get(Calendar.MONTH) + 1));
+ encoder.writeByte(cal.get(Calendar.DAY_OF_MONTH));
+ encoder.writeByte(cal.get(Calendar.HOUR_OF_DAY));
+ encoder.writeByte(cal.get(Calendar.MINUTE));
+ encoder.writeByte(cal.get(Calendar.SECOND));
+ encoder.writeInt(ts.getNanos() / 1000);
+ }
}
}
diff --git a/src/test/java/org/mariadb/jdbc/integration/BatchTest.java b/src/test/java/org/mariadb/jdbc/integration/BatchTest.java
index ee2541674..00178b218 100644
--- a/src/test/java/org/mariadb/jdbc/integration/BatchTest.java
+++ b/src/test/java/org/mariadb/jdbc/integration/BatchTest.java
@@ -7,6 +7,8 @@
import static org.junit.jupiter.api.Assertions.*;
import java.sql.*;
+import java.util.Calendar;
+import java.util.stream.Stream;
import org.junit.jupiter.api.*;
import org.mariadb.jdbc.Connection;
import org.mariadb.jdbc.Statement;
@@ -20,11 +22,14 @@ public static void beforeAll2() throws SQLException {
stmt.execute(
"CREATE TABLE BatchTest (t1 int not null primary key auto_increment, t2 LONGTEXT)");
createSequenceTables();
+ stmt.execute("CREATE TABLE timestampCal(id int, val TIMESTAMP)");
}
@AfterAll
public static void after2() throws SQLException {
- sharedConn.createStatement().execute("DROP TABLE IF EXISTS BatchTest");
+ Statement stmt = sharedConn.createStatement();
+ stmt.execute("DROP TABLE IF EXISTS timestampCal");
+ stmt.execute("DROP TABLE IF EXISTS BatchTest");
}
@Test
@@ -122,10 +127,20 @@ public void differentParameterType(Connection con, boolean expectSuccessUnknown)
prep.setInt(1, 2);
prep.setInt(2, 2);
prep.addBatch();
+ prep.setInt(1, 3);
+ prep.setNull(2, Types.INTEGER);
+ prep.addBatch();
int[] res = prep.executeBatch();
- assertEquals(2, res.length);
- assertEquals(1, res[0]);
- assertEquals(1, res[1]);
+ assertEquals(3, res.length);
+ if (expectSuccessUnknown) {
+ assertEquals(Statement.SUCCESS_NO_INFO, res[0]);
+ assertEquals(Statement.SUCCESS_NO_INFO, res[1]);
+ assertEquals(Statement.SUCCESS_NO_INFO, res[2]);
+ } else {
+ assertEquals(1, res[0]);
+ assertEquals(1, res[1]);
+ assertEquals(1, res[2]);
+ }
}
ResultSet rs = stmt.executeQuery("SELECT * FROM BatchTest");
assertTrue(rs.next());
@@ -134,6 +149,9 @@ public void differentParameterType(Connection con, boolean expectSuccessUnknown)
assertTrue(rs.next());
assertEquals(2, rs.getInt(1));
assertEquals("2", rs.getString(2));
+ assertTrue(rs.next());
+ assertEquals(3, rs.getInt(1));
+ assertNull(rs.getString(2));
assertFalse(rs.next());
stmt.execute("TRUNCATE BatchTest");
@@ -401,4 +419,74 @@ private void batchWithError(Connection con) throws SQLException {
assertThrows(BatchUpdateException.class, prep::executeBatch);
}
}
+
+ private class TimestampCal {
+ private Timestamp val;
+ private int id;
+
+ public TimestampCal(Timestamp val, int id) {
+ this.val = val;
+ this.id = id;
+ }
+
+ public Timestamp getVal() {
+ return val;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ @Override
+ public String toString() {
+ return "TimestampCal{" + "val=" + val + ", id=" + id + '}';
+ }
+ }
+
+ @Test
+ public void ensureCalendarSync() throws SQLException {
+ Assumptions.assumeTrue(isMariaDBServer() && !isXpand());
+ // to ensure that calendar is use at the same time, using BULK command
+ TimestampCal[] t1 = new TimestampCal[50];
+ for (int i = 0; i < 50; i++) {
+ t1[i] = new TimestampCal(Timestamp.valueOf((1970 + i) + "-01-31 12:00:00.0"), i);
+ }
+ TimestampCal[] t2 = new TimestampCal[50];
+ for (int i = 0; i < 50; i++) {
+ t2[i] = new TimestampCal(Timestamp.valueOf((1970 + i) + "-12-01 01:12:15.0"), i + 50);
+ }
+
+ Calendar cal = Calendar.getInstance();
+
+ int inserts = Stream.of(t1, t2).parallel().mapToInt(l -> insertTimestamp(l, cal)).sum();
+ assertEquals(100, inserts);
+ Statement stmt = sharedConn.createStatement();
+ ResultSet rs = stmt.executeQuery("SELECT * FROM timestampCal order by ID");
+ for (int i = 0; i < 50; i++) {
+ rs.next();
+ assertEquals(t1[i].getVal().toString(), rs.getTimestamp(2, cal).toString());
+ }
+ for (int i = 0; i < 50; i++) {
+ rs.next();
+ assertEquals(t2[i].getVal().toString(), rs.getTimestamp(2, cal).toString());
+ }
+ }
+
+ private int insertTimestamp(TimestampCal[] vals, Calendar cal) {
+ try (Connection con = createCon()) {
+ try (PreparedStatement prep =
+ con.prepareStatement("INSERT INTO timestampCal(val, id) VALUES (?,?)")) {
+ for (int i = 0; i < vals.length; i++) {
+ System.out.println(vals[i]);
+ prep.setTimestamp(1, vals[i].getVal(), cal);
+ prep.setInt(2, vals[i].getId());
+ prep.addBatch();
+ }
+ return prep.executeBatch().length;
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ return -1;
+ }
+ }
}
diff --git a/src/test/java/org/mariadb/jdbc/integration/Common.java b/src/test/java/org/mariadb/jdbc/integration/Common.java
index d37e56b86..94fce6541 100644
--- a/src/test/java/org/mariadb/jdbc/integration/Common.java
+++ b/src/test/java/org/mariadb/jdbc/integration/Common.java
@@ -119,6 +119,12 @@ public static boolean minVersion(int major, int minor, int patch) {
return sharedConn.getContext().getVersion().versionGreaterOrEqual(major, minor, patch);
}
+ public static boolean exactVersion(int major, int minor, int patch) {
+ return sharedConn.getContext().getVersion().getMajorVersion() == major
+ && sharedConn.getContext().getVersion().getMinorVersion() == minor
+ && sharedConn.getContext().getVersion().getPatchVersion() == patch;
+ }
+
public static Connection createCon() throws SQLException {
return (Connection) DriverManager.getConnection(mDefUrl);
}
diff --git a/src/test/java/org/mariadb/jdbc/integration/ConnectionTest.java b/src/test/java/org/mariadb/jdbc/integration/ConnectionTest.java
index cfcf53ec9..145141864 100644
--- a/src/test/java/org/mariadb/jdbc/integration/ConnectionTest.java
+++ b/src/test/java/org/mariadb/jdbc/integration/ConnectionTest.java
@@ -862,6 +862,9 @@ public void pamAuthPlugin() throws Throwable {
}
stmt.execute("CREATE USER '" + pamUser + "'@'%' IDENTIFIED VIA pam USING 'mariadb'");
stmt.execute("GRANT SELECT ON *.* TO '" + pamUser + "'@'%' IDENTIFIED VIA pam");
+
+ // mysql 8.0.31 broken public key retrieval, so avoid FLUSHING for now
+ Assumptions.assumeTrue(!isMariaDBServer() && !exactVersion(8, 0, 31));
stmt.execute("FLUSH PRIVILEGES");
int testPort = port;
@@ -993,6 +996,8 @@ public void localSocket() throws Exception {
stmt.execute("CREATE USER testSocket IDENTIFIED BY 'heyPassw!µ20§rd'");
stmt.execute("GRANT SELECT on *.* to testSocket IDENTIFIED BY 'heyPassw!µ20§rd'");
+ // mysql 8.0.31 broken public key retrieval, so avoid FLUSHING for now
+ Assumptions.assumeTrue(!isMariaDBServer() && !exactVersion(8, 0, 31));
stmt.execute("FLUSH PRIVILEGES");
String url =
diff --git a/src/test/java/org/mariadb/jdbc/integration/CredentialPluginTest.java b/src/test/java/org/mariadb/jdbc/integration/CredentialPluginTest.java
index bc32aca20..fbf197c59 100644
--- a/src/test/java/org/mariadb/jdbc/integration/CredentialPluginTest.java
+++ b/src/test/java/org/mariadb/jdbc/integration/CredentialPluginTest.java
@@ -50,6 +50,8 @@ public static void beforeTest() throws SQLException {
stmt.execute("CREATE USER 'identityUser'@'%' IDENTIFIED BY '!Passw0rd3Works'");
stmt.execute("GRANT SELECT ON " + sharedConn.getCatalog() + ".* TO 'identityUser'@'%'");
}
+ // mysql 8.0.31 broken public key retrieval, so avoid FLUSHING for now
+ Assumptions.assumeTrue(!isMariaDBServer() && !exactVersion(8, 0, 31));
stmt.execute("FLUSH PRIVILEGES");
}
diff --git a/src/test/java/org/mariadb/jdbc/integration/DataSourceTest.java b/src/test/java/org/mariadb/jdbc/integration/DataSourceTest.java
index 47f74bb02..0144b0e33 100644
--- a/src/test/java/org/mariadb/jdbc/integration/DataSourceTest.java
+++ b/src/test/java/org/mariadb/jdbc/integration/DataSourceTest.java
@@ -150,6 +150,8 @@ public void switchUser() throws SQLException {
+ sharedConn.getCatalog()
+ ".* TO 'dsUser'@'%' IDENTIFIED BY 'MySup8%rPassw@ord'");
}
+ // mysql 8.0.31 broken public key retrieval, so avoid FLUSHING for now
+ Assumptions.assumeTrue(!isMariaDBServer() && !exactVersion(8, 0, 31));
stmt.execute("FLUSH PRIVILEGES");
DataSource ds = new MariaDbDataSource(mDefUrl + "&allowPublicKeyRetrieval");
diff --git a/src/test/java/org/mariadb/jdbc/integration/DatabaseMetadataTest.java b/src/test/java/org/mariadb/jdbc/integration/DatabaseMetadataTest.java
index 9d4f8b3a4..2320d85ab 100644
--- a/src/test/java/org/mariadb/jdbc/integration/DatabaseMetadataTest.java
+++ b/src/test/java/org/mariadb/jdbc/integration/DatabaseMetadataTest.java
@@ -236,15 +236,21 @@ public void functionColumns() throws SQLException {
/** Same as getImportedKeys, with one foreign key in a table in another catalog. */
@Test
public void getImportedKeys() throws Exception {
- getImportedKeys(sharedConn);
+ getImportedKeys(sharedConn, true);
try (org.mariadb.jdbc.Connection con = createCon()) {
java.sql.Statement stmt = con.createStatement();
stmt.execute("SET sql_mode = concat(@@sql_mode,',NO_BACKSLASH_ESCAPES')");
- getImportedKeys(con);
+ getImportedKeys(con, true);
+ }
+ try (org.mariadb.jdbc.Connection con = createCon("importedKeysWithConstraintNames=false")) {
+ java.sql.Statement stmt = con.createStatement();
+ stmt.execute("SET sql_mode = concat(@@sql_mode,',NO_BACKSLASH_ESCAPES')");
+ getImportedKeys(con, false);
}
}
- private void getImportedKeys(org.mariadb.jdbc.Connection con) throws Exception {
+ private void getImportedKeys(
+ org.mariadb.jdbc.Connection con, boolean importedKeysWithConstraintNames) throws Exception {
// cancel for MySQL 8.0, since CASCADE with I_S give importedKeySetDefault, not
// importedKeyCascade
// Assumptions.assumeFalse(!isMariaDBServer() && minVersion(8, 0, 0));
@@ -349,7 +355,9 @@ Get result sets using either method and compare (ignore minor differences INT vs
assertEquals(DatabaseMetaData.importedKeyCascade, rs.getInt("DELETE_RULE"));
assertEquals("product order 1_ibfk_1", rs.getString("FK_NAME"));
// with show, meta don't know contraint name
- assertEquals((i == 0) ? null : "unik_name", rs.getString("PK_NAME"));
+ assertEquals(
+ (i == 0 && !importedKeysWithConstraintNames) ? null : "unik_name",
+ rs.getString("PK_NAME"));
assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getInt("DEFERRABILITY"));
assertTrue(rs.next());
@@ -366,7 +374,9 @@ Get result sets using either method and compare (ignore minor differences INT vs
assertEquals(DatabaseMetaData.importedKeyCascade, rs.getInt("DELETE_RULE"));
assertEquals("product order 1_ibfk_1", rs.getString("FK_NAME"));
// with show, meta don't know contraint name
- assertEquals((i == 0) ? null : "unik_name", rs.getString("PK_NAME"));
+ assertEquals(
+ (i == 0 && !importedKeysWithConstraintNames) ? null : "unik_name",
+ rs.getString("PK_NAME"));
assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getInt("DEFERRABILITY"));
assertTrue(rs.next());
@@ -388,7 +398,8 @@ Get result sets using either method and compare (ignore minor differences INT vs
}
assertEquals("product order 1_ibfk_2", rs.getString("FK_NAME"));
// with show, meta don't know contraint name
- assertEquals((i == 0) ? null : "PRIMARY", rs.getString("PK_NAME"));
+ assertEquals(
+ (i == 0 && !importedKeysWithConstraintNames) ? null : "PRIMARY", rs.getString("PK_NAME"));
assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getInt("DEFERRABILITY"));
}
diff --git a/src/test/java/org/mariadb/jdbc/integration/GssapiAuthenticationTest.java b/src/test/java/org/mariadb/jdbc/integration/GssapiAuthenticationTest.java
new file mode 100644
index 000000000..d5df69d8d
--- /dev/null
+++ b/src/test/java/org/mariadb/jdbc/integration/GssapiAuthenticationTest.java
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+// Copyright (c) 2012-2014 Monty Program Ab
+// Copyright (c) 2015-2021 MariaDB Corporation Ab
+
+package org.mariadb.jdbc.integration;
+
+import java.sql.*;
+import org.junit.jupiter.api.Assumptions;
+import org.junit.jupiter.api.Test;
+
+public class GssapiAuthenticationTest extends Common {
+
+ @Test
+ public void nativePassword() throws Exception {
+ Assumptions.assumeTrue(isWindows());
+ Statement stmt = sharedConn.createStatement();
+ try {
+ stmt.execute("INSTALL SONAME 'auth_gssapi'");
+ } catch (SQLException e) {
+ // eat
+ }
+ System.out.println("user name:" + System.getProperty("user.name"));
+ stmt.execute("CREATE USER " + System.getProperty("user.name") + " IDENTIFIED VIA gssapi");
+ stmt.execute("GRANT ALL PRIVILEGES ON *.* TO " + System.getProperty("user.name"));
+
+ String gssapiUrl = String.format("jdbc:mariadb://%s:%s/%s", hostname, port, database);
+ try (Connection con = DriverManager.getConnection(gssapiUrl)) {
+ con.createStatement().execute("SELECT 1");
+ }
+ }
+}
diff --git a/src/test/java/org/mariadb/jdbc/integration/PoolDataSourceTest.java b/src/test/java/org/mariadb/jdbc/integration/PoolDataSourceTest.java
index e9248d5dc..46c54bfc2 100644
--- a/src/test/java/org/mariadb/jdbc/integration/PoolDataSourceTest.java
+++ b/src/test/java/org/mariadb/jdbc/integration/PoolDataSourceTest.java
@@ -53,6 +53,8 @@ public static void beforeClassDataSourceTest() throws SQLException {
stmt.execute(
"CREATE TABLE testResetRollback(id int not null primary key auto_increment, test varchar(20))");
stmt.execute("FLUSH TABLES");
+ // mysql 8.0.31 broken public key retrieval, so avoid FLUSHING for now
+ Assumptions.assumeTrue(!isMariaDBServer() && !exactVersion(8, 0, 31));
stmt.execute("FLUSH PRIVILEGES");
}
diff --git a/src/test/java/org/mariadb/jdbc/integration/PooledConnectionTest.java b/src/test/java/org/mariadb/jdbc/integration/PooledConnectionTest.java
index 99ffd8777..2b4a3e895 100644
--- a/src/test/java/org/mariadb/jdbc/integration/PooledConnectionTest.java
+++ b/src/test/java/org/mariadb/jdbc/integration/PooledConnectionTest.java
@@ -240,6 +240,8 @@ public void testPooledConnectionStatementError() throws Exception {
+ sharedConn.getCatalog()
+ ".* TO 'dsUser'@'%' IDENTIFIED BY 'MySup8%rPassw@ord'");
}
+ // mysql 8.0.31 broken public key retrieval, so avoid FLUSHING for now
+ Assumptions.assumeTrue(!isMariaDBServer() && !exactVersion(8, 0, 31));
stmt.execute("FLUSH PRIVILEGES");
ConnectionPoolDataSource ds = new MariaDbDataSource(mDefUrl);
diff --git a/src/test/java/org/mariadb/jdbc/integration/ProcedureTest.java b/src/test/java/org/mariadb/jdbc/integration/ProcedureTest.java
index 49aec3a43..5271caa00 100644
--- a/src/test/java/org/mariadb/jdbc/integration/ProcedureTest.java
+++ b/src/test/java/org/mariadb/jdbc/integration/ProcedureTest.java
@@ -29,6 +29,7 @@ public class ProcedureTest extends Common {
public static void drop() throws SQLException {
Statement stmt = sharedConn.createStatement();
stmt.execute("DROP TABLE IF EXISTS procedure_test");
+ stmt.execute("DROP PROCEDURE IF EXISTS multiply_by_2");
}
@BeforeAll
@@ -36,6 +37,17 @@ public static void beforeAll2() throws SQLException {
drop();
Statement stmt = sharedConn.createStatement();
stmt.execute("CREATE TABLE procedure_test (t0 int)");
+ stmt.execute("CREATE PROCEDURE multiply_by_2 (INOUT t1 INT) BEGIN \nset t1 = t1 * 2;\nEND");
+ }
+
+ @Test
+ public void settingParameterBeforeOutRegistration() throws SQLException {
+ try (CallableStatement cstmt = sharedConn.prepareCall("{ CALL multiply_by_2(?) }")) {
+ cstmt.setLong(1, 42L);
+ cstmt.registerOutParameter(1, Types.NUMERIC);
+ cstmt.executeQuery();
+ assertEquals(84, cstmt.getLong(1));
+ }
}
@Test
diff --git a/src/test/java/org/mariadb/jdbc/integration/Sha256AuthenticationTest.java b/src/test/java/org/mariadb/jdbc/integration/Sha256AuthenticationTest.java
index 7ac1981ac..50b9c52ea 100644
--- a/src/test/java/org/mariadb/jdbc/integration/Sha256AuthenticationTest.java
+++ b/src/test/java/org/mariadb/jdbc/integration/Sha256AuthenticationTest.java
@@ -77,6 +77,8 @@ public static void init() throws Exception {
stmt.execute("GRANT ALL PRIVILEGES ON *.* TO 'cachingSha256User2'@'%'");
stmt.execute("GRANT ALL PRIVILEGES ON *.* TO 'cachingSha256User3'@'%'");
stmt.execute("GRANT ALL PRIVILEGES ON *.* TO 'cachingSha256User4'@'%'");
+ // mysql 8.0.31 broken public key retrieval, so avoid FLUSHING for now
+ Assumptions.assumeTrue(!isMariaDBServer() && !exactVersion(8, 0, 31));
stmt.execute("FLUSH PRIVILEGES");
}
@@ -106,7 +108,13 @@ public void nativePassword() throws Exception {
stmt.execute(
"CREATE USER tmpUser@'%' IDENTIFIED WITH mysql_native_password BY '!Passw0rd3Works'");
stmt.execute("grant all on `" + sharedConn.getCatalog() + "`.* TO tmpUser@'%'");
- stmt.execute("FLUSH PRIVILEGES"); // reset cache
+ // mysql 8.0.31 broken public key retrieval, so avoid FLUSHING for now
+ Assumptions.assumeTrue(!isMariaDBServer() && !exactVersion(8, 0, 31));
+
+ // mysql 8.0.31 broken public key retrieval, so avoid FLUSHING for now
+ Assumptions.assumeTrue(!isMariaDBServer() && !exactVersion(8, 0, 31));
+ stmt.execute("FLUSH PRIVILEGES");
+
try (Connection con = createCon("user=tmpUser&password=!Passw0rd3Works")) {
con.isValid(1);
}
@@ -121,7 +129,10 @@ public void nativePassword() throws Exception {
public void cachingSha256Empty() throws Exception {
Assumptions.assumeTrue(
!isWindows() && !isMariaDBServer() && rsaPublicKey != null && minVersion(8, 0, 0));
+ // mysql 8.0.31 broken public key retrieval, so avoid FLUSHING for now
+ Assumptions.assumeTrue(!isMariaDBServer() && !exactVersion(8, 0, 31));
sharedConn.createStatement().execute("FLUSH PRIVILEGES"); // reset cache
+
try (Connection con = createCon("user=cachingSha256User2&allowPublicKeyRetrieval&password=")) {
con.isValid(1);
}
@@ -131,7 +142,10 @@ public void cachingSha256Empty() throws Exception {
public void wrongRsaPath() throws Exception {
Assumptions.assumeTrue(
!isWindows() && !isMariaDBServer() && rsaPublicKey != null && minVersion(8, 0, 0));
+ // mysql 8.0.31 broken public key retrieval, so avoid FLUSHING for now
+ Assumptions.assumeTrue(!isMariaDBServer() && !exactVersion(8, 0, 31));
sharedConn.createStatement().execute("FLUSH PRIVILEGES"); // reset cache
+
File tempFile = File.createTempFile("log", ".tmp");
Common.assertThrowsContains(
SQLException.class,
@@ -146,6 +160,8 @@ public void wrongRsaPath() throws Exception {
@Test
public void cachingSha256Allow() throws Exception {
Assumptions.assumeTrue(!isMariaDBServer() && rsaPublicKey != null && minVersion(8, 0, 0));
+ // mysql 8.0.31 broken public key retrieval, so avoid FLUSHING for now
+ Assumptions.assumeTrue(!isMariaDBServer() && !exactVersion(8, 0, 31));
sharedConn.createStatement().execute("FLUSH PRIVILEGES"); // reset cache
try (Connection con =
createCon("user=cachingSha256User3&allowPublicKeyRetrieval&password=!Passw0rd3Works")) {
@@ -156,6 +172,8 @@ public void cachingSha256Allow() throws Exception {
@Test
public void cachingSha256PluginTest() throws Exception {
Assumptions.assumeTrue(!isMariaDBServer() && rsaPublicKey != null && minVersion(8, 0, 0));
+ // mysql 8.0.31 broken public key retrieval, so avoid FLUSHING for now
+ Assumptions.assumeTrue(!isMariaDBServer() && !exactVersion(8, 0, 31));
sharedConn.createStatement().execute("FLUSH PRIVILEGES"); // reset cache
try (Connection con =
@@ -192,6 +210,8 @@ public void cachingSha256PluginTest() throws Exception {
@Test
public void cachingSha256PluginTestWithoutServerRsaKey() throws Exception {
Assumptions.assumeTrue(!isWindows() && minVersion(8, 0, 0));
+ // mysql 8.0.31 broken public key retrieval, so avoid FLUSHING for now
+ Assumptions.assumeTrue(!isMariaDBServer() && !exactVersion(8, 0, 31));
sharedConn.createStatement().execute("FLUSH PRIVILEGES"); // reset cache
try (Connection con =
createCon("user=cachingSha256User&password=!Passw0rd3Works&allowPublicKeyRetrieval")) {
@@ -202,6 +222,8 @@ public void cachingSha256PluginTestWithoutServerRsaKey() throws Exception {
@Test
public void cachingSha256PluginTestException() throws Exception {
Assumptions.assumeTrue(!isMariaDBServer() && minVersion(8, 0, 0));
+ // mysql 8.0.31 broken public key retrieval, so avoid FLUSHING for now
+ Assumptions.assumeTrue(!isMariaDBServer() && !exactVersion(8, 0, 31));
sharedConn.createStatement().execute("FLUSH PRIVILEGES"); // reset cache
Common.assertThrowsContains(
diff --git a/src/test/java/org/mariadb/jdbc/integration/SslTest.java b/src/test/java/org/mariadb/jdbc/integration/SslTest.java
index b059ca48a..d5205d9a1 100644
--- a/src/test/java/org/mariadb/jdbc/integration/SslTest.java
+++ b/src/test/java/org/mariadb/jdbc/integration/SslTest.java
@@ -44,6 +44,8 @@ public static void beforeAll2() throws SQLException {
createSslUser("mutualAuthUser", "REQUIRE X509");
Statement stmt = sharedConn.createStatement();
+ // mysql 8.0.31 broken public key retrieval, so avoid FLUSHING for now
+ Assumptions.assumeTrue(!isMariaDBServer() && !exactVersion(8, 0, 31));
stmt.execute("FLUSH PRIVILEGES");
sslPort =
System.getenv("TEST_MAXSCALE_TLS_PORT") == null
diff --git a/src/test/java/org/mariadb/jdbc/integration/UpdateResultSetTest.java b/src/test/java/org/mariadb/jdbc/integration/UpdateResultSetTest.java
index 9738dfb02..5abf9b4b9 100644
--- a/src/test/java/org/mariadb/jdbc/integration/UpdateResultSetTest.java
+++ b/src/test/java/org/mariadb/jdbc/integration/UpdateResultSetTest.java
@@ -240,6 +240,7 @@ public void testMeta() throws Exception {
+ "`t1` VARCHAR(50) NOT NULL,"
+ "`t2` VARCHAR(50) NULL default 'default-value',"
+ "PRIMARY KEY (`id`))");
+ stmt.execute("START TRANSACTION"); // if MAXSCALE ensure using WRITER
stmt.executeQuery("INSERT INTO UpdateWithoutPrimary(t1,t2) values ('1-1','1-2')");
try (PreparedStatement preparedStatement =
@@ -282,6 +283,7 @@ public void testMeta() throws Exception {
assertEquals("1-1", rs.getString(2));
assertEquals("1-2", rs.getString(3));
assertFalse(rs.next());
+ sharedConn.rollback();
}
@Test
@@ -607,78 +609,87 @@ public void updateBlobClob() throws SQLException, IOException {
Statement stmt = sharedConn.createStatement();
stmt.execute("DROP TABLE IF EXISTS updateBlob");
stmt.execute("CREATE TABLE updateBlob(id int not null primary key, strm blob)");
- PreparedStatement prep =
- sharedConn.prepareStatement("insert into updateBlob (id, strm) values (?,?)");
- byte[] theBlob = {1, 2, 3, 4, 5, 6};
- InputStream stream = new ByteArrayInputStream(theBlob);
-
- prep.setInt(1, 1);
- prep.setBlob(2, stream);
- prep.execute();
-
- byte[] updatedBlob = "abcdef".getBytes(StandardCharsets.UTF_8);
-
- try (PreparedStatement preparedStatement =
- sharedConn.prepareStatement(
- "select * from updateBlob", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE)) {
- ResultSet rs = preparedStatement.executeQuery();
- assertTrue(rs.next());
-
- rs.updateBlob(2, new ByteArrayInputStream(updatedBlob));
- rs.updateRow();
- checkResult(rs, updatedBlob);
-
- rs.updateBlob("strm", new ByteArrayInputStream(updatedBlob));
- rs.updateRow();
- checkResult(rs, updatedBlob);
-
- rs.updateBlob(2, new ByteArrayInputStream(updatedBlob), 20L);
- rs.updateRow();
- checkResult(rs, updatedBlob);
-
- rs.updateBlob("strm", new ByteArrayInputStream(updatedBlob), 20L);
- rs.updateRow();
- checkResult(rs, updatedBlob);
-
- rs.updateClob(2, new StringReader("abcdef"));
- rs.updateRow();
- checkResult(rs, updatedBlob);
-
- rs.updateClob("strm", new StringReader("abcdef"));
- rs.updateRow();
- checkResult(rs, updatedBlob);
-
- rs.updateClob(2, new StringReader("abcdef"), 20L);
- rs.updateRow();
- checkResult(rs, updatedBlob);
-
- rs.updateClob("strm", new StringReader("abcdef"), 20L);
- rs.updateRow();
- checkResult(rs, updatedBlob);
-
- rs.updateNClob(2, new StringReader("abcdef"));
- rs.updateRow();
- checkResult(rs, updatedBlob);
-
- rs.updateNClob("strm", new StringReader("abcdef"));
- rs.updateRow();
- checkResult(rs, updatedBlob);
-
- rs.updateNClob(2, new StringReader("abcdef"), 20L);
- rs.updateRow();
- checkResult(rs, updatedBlob);
-
- rs.updateNClob("strm", new StringReader("abcdef"), 20L);
- rs.updateRow();
- checkResult(rs, updatedBlob);
- }
+ stmt.execute("START TRANSACTION ");
+ try {
+ PreparedStatement prep =
+ sharedConn.prepareStatement("insert into updateBlob (id, strm) values (?,?)");
+ byte[] theBlob = {1, 2, 3, 4, 5, 6};
+ InputStream stream = new ByteArrayInputStream(theBlob);
+
+ prep.setInt(1, 1);
+ prep.setBlob(2, stream);
+ prep.execute();
+
+ byte[] updatedBlob = "abcdef".getBytes(StandardCharsets.UTF_8);
+
+ try (PreparedStatement preparedStatement =
+ sharedConn.prepareStatement(
+ "select * from updateBlob",
+ ResultSet.TYPE_FORWARD_ONLY,
+ ResultSet.CONCUR_UPDATABLE)) {
+ ResultSet rs = preparedStatement.executeQuery();
+ assertTrue(rs.next());
+
+ rs.updateBlob(2, new ByteArrayInputStream(updatedBlob));
+ rs.updateRow();
+ checkResult(rs, updatedBlob);
+
+ rs.updateBlob("strm", new ByteArrayInputStream(updatedBlob));
+ rs.updateRow();
+ checkResult(rs, updatedBlob);
+
+ rs.updateBlob(2, new ByteArrayInputStream(updatedBlob), 20L);
+ rs.updateRow();
+ checkResult(rs, updatedBlob);
+
+ rs.updateBlob("strm", new ByteArrayInputStream(updatedBlob), 20L);
+ rs.updateRow();
+ checkResult(rs, updatedBlob);
+
+ rs.updateClob(2, new StringReader("abcdef"));
+ rs.updateRow();
+ checkResult(rs, updatedBlob);
+
+ rs.updateClob("strm", new StringReader("abcdef"));
+ rs.updateRow();
+ checkResult(rs, updatedBlob);
+
+ rs.updateClob(2, new StringReader("abcdef"), 20L);
+ rs.updateRow();
+ checkResult(rs, updatedBlob);
+
+ rs.updateClob("strm", new StringReader("abcdef"), 20L);
+ rs.updateRow();
+ checkResult(rs, updatedBlob);
+
+ rs.updateNClob(2, new StringReader("abcdef"));
+ rs.updateRow();
+ checkResult(rs, updatedBlob);
+
+ rs.updateNClob("strm", new StringReader("abcdef"));
+ rs.updateRow();
+ checkResult(rs, updatedBlob);
+
+ rs.updateNClob(2, new StringReader("abcdef"), 20L);
+ rs.updateRow();
+ checkResult(rs, updatedBlob);
+
+ rs.updateNClob("strm", new StringReader("abcdef"), 20L);
+ rs.updateRow();
+ checkResult(rs, updatedBlob);
+ }
- try (PreparedStatement preparedStatement =
- sharedConn.prepareStatement(
- "select * from updateBlob", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE)) {
- ResultSet rs = preparedStatement.executeQuery();
- assertTrue(rs.next());
- checkResult(rs, updatedBlob);
+ try (PreparedStatement preparedStatement =
+ sharedConn.prepareStatement(
+ "select * from updateBlob",
+ ResultSet.TYPE_FORWARD_ONLY,
+ ResultSet.CONCUR_UPDATABLE)) {
+ ResultSet rs = preparedStatement.executeQuery();
+ assertTrue(rs.next());
+ checkResult(rs, updatedBlob);
+ }
+ } finally {
+ sharedConn.rollback();
}
}
@@ -819,7 +830,7 @@ private void testMoveToInsertRow(Connection con) throws SQLException {
Statement stmt = con.createStatement();
stmt.execute("DROP TABLE IF EXISTS testMoveToInsertRow");
stmt.execute("CREATE TABLE testMoveToInsertRow(t2 text, t1 text, id int primary key)");
-
+ stmt.execute("START TRANSACTION"); // if MAXSCALE ensure using WRITER
try (PreparedStatement preparedStatement =
con.prepareStatement(
"select id, t1, t2 from testMoveToInsertRow",
@@ -861,8 +872,12 @@ private void testMoveToInsertRow(Connection con) throws SQLException {
assertEquals(3, rs.getInt("id"));
assertEquals("other-t1-value", rs.getString("t1"));
assertNull(rs.getString("t2"));
+ } finally {
+ con.commit();
}
+ stmt = sharedConn.createStatement();
+ stmt.execute("START TRANSACTION"); // if MAXSCALE ensure using WRITER
try (PreparedStatement preparedStatement =
sharedConn.prepareStatement(
"select id, t1, t2 from testMoveToInsertRow",
@@ -902,6 +917,8 @@ private void testMoveToInsertRow(Connection con) throws SQLException {
assertTrue(rs.next());
assertEquals(5, rs.getInt("id"));
assertEquals("t1-5", rs.getString("t1"));
+ } finally {
+ sharedConn.rollback();
}
}