Skip to content

Commit

Permalink
Merge branch 'release/3.0.9'
Browse files Browse the repository at this point in the history
  • Loading branch information
rusher committed Nov 7, 2022
2 parents 11e224e + de514c8 commit a42cde1
Show file tree
Hide file tree
Showing 24 changed files with 454 additions and 152 deletions.
15 changes: 15 additions & 0 deletions 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)

Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Expand Up @@ -7,7 +7,7 @@
<artifactId>mariadb-java-client</artifactId>
<packaging>jar</packaging>
<name>mariadb-java-client</name>
<version>3.0.8</version>
<version>3.0.9</version>
<description>JDBC driver for MariaDB and MySQL</description>
<url>https://mariadb.com/kb/en/mariadb/about-mariadb-connector-j/</url>

Expand Down
3 changes: 2 additions & 1 deletion src/main/java/org/mariadb/jdbc/BaseCallableStatement.java
Expand Up @@ -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 {
Expand Down
7 changes: 6 additions & 1 deletion src/main/java/org/mariadb/jdbc/ClientPreparedStatement.java
Expand Up @@ -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();
Expand Down
79 changes: 72 additions & 7 deletions src/main/java/org/mariadb/jdbc/DatabaseMetaData.java
Expand Up @@ -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;
Expand Down Expand Up @@ -202,7 +199,10 @@ private int parseIdentifierList(char[] part, int startPos, List<Identifier> 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",
Expand Down Expand Up @@ -255,7 +255,7 @@ private ResultSet getImportedKeys(
onDeleteReferenceAction = getImportedKeyAction(referenceAction);
}
}

Map<String, Map<String[], String>> externalInfos = new HashMap<>();
for (int i = 0; i < primaryKeyCols.size(); i++) {

String[] row = new String[columnNames.length];
Expand All @@ -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<String[], String> externalInfo = externalInfos.get(ext);
if (externalInfo != null) {
for (Map.Entry<String[], String> 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);
}
Expand All @@ -301,6 +331,41 @@ private ResultSet getImportedKeys(
columnNames, dataTypes, arr, connection.getContext(), ColumnFlags.PRIMARY_KEY);
}

private Map<String[], String> 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<String[], String> 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<String> 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,
Expand Down
Expand Up @@ -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++) {
Expand Down
Expand Up @@ -81,20 +81,21 @@ 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
if (outToken != null) {
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) {
Expand Down
Expand Up @@ -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();
}
Expand Down
13 changes: 8 additions & 5 deletions src/main/java/org/mariadb/jdbc/plugin/codec/DateCodec.java
Expand Up @@ -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() {
Expand Down
37 changes: 20 additions & 17 deletions src/main/java/org/mariadb/jdbc/plugin/codec/TimeCodec.java
Expand Up @@ -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));
}
}
}

Expand Down
41 changes: 22 additions & 19 deletions src/main/java/org/mariadb/jdbc/plugin/codec/TimestampCodec.java
Expand Up @@ -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);
}
}
}

Expand Down

0 comments on commit a42cde1

Please sign in to comment.