Skip to content

Commit 830b551

Browse files
committed
Fix for Bug#82084 (23743938), YEAR DATA TYPE RETURNS INCORRECT VALUE FOR
JDBC GETCOLUMNTYPE().
1 parent 7ad95bc commit 830b551

File tree

6 files changed

+85
-11
lines changed

6 files changed

+85
-11
lines changed

CHANGES

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
Version 8.0.29
55

6+
- Fix for Bug#82084 (23743938), YEAR DATA TYPE RETURNS INCORRECT VALUE FOR JDBC GETCOLUMNTYPE().
7+
68
- Fix for Bug#106441 (33850155), Add charset mapping for utf8mb3.
79

810
- WL#15048, Upgrade Protocol Buffers dependency to protobuf-java-3.19.4.

src/main/user-impl/java/com/mysql/cj/jdbc/DatabaseMetaData.java

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import java.sql.RowIdLifetime;
3838
import java.sql.SQLException;
3939
import java.sql.Statement;
40+
import java.sql.Types;
4041
import java.util.ArrayList;
4142
import java.util.Arrays;
4243
import java.util.Collections;
@@ -752,6 +753,7 @@ protected enum ProcedureType {
752753
protected boolean tinyInt1isBit;
753754
protected boolean transformedBitIsBoolean;
754755
protected boolean useHostsInPrivileges;
756+
protected boolean yearIsDateType;
755757

756758
protected RuntimeProperty<DatabaseTerm> databaseTerm;
757759
protected RuntimeProperty<Boolean> nullDatabaseMeansCurrent;
@@ -792,6 +794,7 @@ protected DatabaseMetaData(JdbcConnection connToSet, String databaseToSet, Resul
792794
this.tinyInt1isBit = this.conn.getPropertySet().getBooleanProperty(PropertyKey.tinyInt1isBit).getValue();
793795
this.transformedBitIsBoolean = this.conn.getPropertySet().getBooleanProperty(PropertyKey.transformedBitIsBoolean).getValue();
794796
this.useHostsInPrivileges = this.conn.getPropertySet().getBooleanProperty(PropertyKey.useHostsInPrivileges).getValue();
797+
this.yearIsDateType = this.conn.getPropertySet().getBooleanProperty(PropertyKey.yearIsDateType).getValue();
795798
this.quotedId = this.session.getIdentifierQuoteString();
796799
}
797800

@@ -873,7 +876,8 @@ private Row convertTypeDescriptorToProcedureRow(byte[] procNameAsBytes, byte[] p
873876
row[2] = procNameAsBytes; // PROCEDURE/NAME
874877
row[3] = s2b(paramName); // COLUMN_NAME
875878
row[4] = s2b(String.valueOf(getColumnType(isOutParam, isInParam, isReturnParam, forGetFunctionColumns))); // COLUMN_TYPE
876-
row[5] = s2b(Short.toString((short) typeDesc.mysqlType.getJdbcType())); // DATA_TYPE
879+
row[5] = Short.toString(typeDesc.mysqlType == MysqlType.YEAR && !DatabaseMetaData.this.yearIsDateType ? //
880+
Types.SMALLINT : (short) typeDesc.mysqlType.getJdbcType()).getBytes(); // DATA_TYPE (jdbc)
877881
row[6] = s2b(typeDesc.mysqlType.getName()); // TYPE_NAME
878882
row[7] = typeDesc.datetimePrecision == null ? s2b(typeDesc.columnSize.toString()) : s2b(typeDesc.datetimePrecision.toString()); // PRECISION
879883
row[8] = typeDesc.columnSize == null ? null : s2b(typeDesc.columnSize.toString()); // LENGTH
@@ -1346,7 +1350,8 @@ void forEach(String dbStr) throws SQLException {
13461350
}
13471351

13481352
MysqlType ft = MysqlType.getByName(type.toUpperCase());
1349-
rowVal[2] = s2b(String.valueOf(ft.getJdbcType()));
1353+
rowVal[2] = s2b(
1354+
String.valueOf(ft == MysqlType.YEAR && !DatabaseMetaData.this.yearIsDateType ? Types.SMALLINT : ft.getJdbcType()));
13501355
rowVal[3] = s2b(type);
13511356
rowVal[4] = hasLength ? Integer.toString(size + decimals).getBytes() : Long.toString(ft.getPrecision()).getBytes();
13521357
rowVal[5] = Integer.toString(maxBufferSize).getBytes();
@@ -2171,7 +2176,8 @@ void forEach(String dbStr) throws SQLException {
21712176
rowVal[1] = DatabaseMetaData.this.databaseTerm.getValue() == DatabaseTerm.SCHEMA ? s2b(dbStr) : null; // TABLE_SCHEM
21722177
rowVal[2] = s2b(tableName); // TABLE_NAME
21732178
rowVal[3] = results.getBytes("Field");
2174-
rowVal[4] = Short.toString((short) typeDesc.mysqlType.getJdbcType()).getBytes();// DATA_TYPE (jdbc)
2179+
rowVal[4] = Short.toString(typeDesc.mysqlType == MysqlType.YEAR && !DatabaseMetaData.this.yearIsDateType ? Types.SMALLINT
2180+
: (short) typeDesc.mysqlType.getJdbcType()).getBytes(); // DATA_TYPE (jdbc)
21752181
rowVal[5] = s2b(typeDesc.mysqlType.getName()); // TYPE_NAME (native)
21762182
if (typeDesc.columnSize == null) { // COLUMN_SIZE
21772183
rowVal[6] = null;
@@ -3943,7 +3949,7 @@ private byte[][] getTypeInfo(String mysqlTypeName) throws SQLException {
39433949
byte[][] rowVal = new byte[18][];
39443950

39453951
rowVal[0] = s2b(mysqlTypeName); // Type name
3946-
rowVal[1] = Integer.toString(mt.getJdbcType()).getBytes(); // JDBC Data type
3952+
rowVal[1] = Integer.toString(mt == MysqlType.YEAR && !DatabaseMetaData.this.yearIsDateType ? Types.SMALLINT : mt.getJdbcType()).getBytes(); // JDBC Data type
39473953
// JDBC spec reserved only 'int' type for precision, thus we need to cut longer values
39483954
rowVal[2] = Integer.toString(mt.getPrecision() > Integer.MAX_VALUE ? Integer.MAX_VALUE : mt.getPrecision().intValue()).getBytes(); // Precision
39493955
switch (mt) {
@@ -4208,7 +4214,8 @@ void forEach(String dbStr) throws SQLException {
42084214
byte[][] rowVal = new byte[8][];
42094215
rowVal[0] = null; // SCOPE is not used
42104216
rowVal[1] = results.getBytes("Field"); // COLUMN_NAME
4211-
rowVal[2] = Short.toString((short) typeDesc.mysqlType.getJdbcType()).getBytes(); // DATA_TYPE
4217+
rowVal[2] = Short.toString(typeDesc.mysqlType == MysqlType.YEAR && !DatabaseMetaData.this.yearIsDateType ? Types.SMALLINT
4218+
: (short) typeDesc.mysqlType.getJdbcType()).getBytes(); // DATA_TYPE (jdbc)
42124219
rowVal[3] = s2b(typeDesc.mysqlType.getName()); // TYPE_NAME
42134220
rowVal[4] = typeDesc.columnSize == null ? null : s2b(typeDesc.columnSize.toString()); // COLUMN_SIZE
42144221
rowVal[5] = s2b(Integer.toString(typeDesc.bufferLength)); // BUFFER_LENGTH

src/main/user-impl/java/com/mysql/cj/jdbc/DatabaseMetaDataUsingInfoSchema.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2005, 2021, Oracle and/or its affiliates.
2+
* Copyright (c) 2005, 2022, Oracle and/or its affiliates.
33
*
44
* This program is free software; you can redistribute it and/or modify it under
55
* the terms of the GNU General Public License, version 2.0, as published by the
@@ -32,6 +32,7 @@
3232
import java.sql.ResultSet;
3333
import java.sql.SQLException;
3434
import java.sql.Statement;
35+
import java.sql.Types;
3536
import java.util.ArrayList;
3637
import java.util.Collections;
3738
import java.util.List;
@@ -1233,7 +1234,9 @@ private final void appendJdbcTypeMappingQuery(StringBuilder buf, String mysqlTyp
12331234
buf.append(mysqlType.getJdbcType());
12341235
}
12351236
break;
1236-
1237+
case YEAR:
1238+
buf.append(this.yearIsDateType ? mysqlType.getJdbcType() : Types.SMALLINT);
1239+
break;
12371240
default:
12381241
buf.append(mysqlType.getJdbcType());
12391242
}

src/main/user-impl/java/com/mysql/cj/jdbc/result/ResultSetMetaData.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2002, 2021, Oracle and/or its affiliates.
2+
* Copyright (c) 2002, 2022, Oracle and/or its affiliates.
33
*
44
* This program is free software; you can redistribute it and/or modify it under
55
* the terms of the GNU General Public License, version 2.0, as published by the
@@ -30,6 +30,7 @@
3030
package com.mysql.cj.jdbc.result;
3131

3232
import java.sql.SQLException;
33+
import java.sql.Types;
3334

3435
import com.mysql.cj.Messages;
3536
import com.mysql.cj.MysqlType;
@@ -185,7 +186,11 @@ public String getColumnName(int column) throws SQLException {
185186

186187
@Override
187188
public int getColumnType(int column) throws SQLException {
188-
return getField(column).getJavaType();
189+
Field f = getField(column);
190+
if (f.getMysqlType() == MysqlType.YEAR && !this.treatYearAsDate) {
191+
return Types.SMALLINT;
192+
}
193+
return f.getJavaType();
189194
}
190195

191196
@Override

src/test/java/testsuite/regression/ConnectionRegressionTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6560,7 +6560,7 @@ public void testBug75592() throws Exception {
65606560
this.rs = con.createStatement().executeQuery("SHOW VARIABLES");
65616561
while (this.rs.next()) {
65626562
String val = this.rs.getString(2);
6563-
serverVariables.put(this.rs.getString(1), "utf8mb3".equals(val) ? "utf8" : val);
6563+
serverVariables.put(this.rs.getString(1), val);
65646564
}
65656565

65666566
// fix the renaming of "tx_isolation" to "transaction_isolation" that is made in NativeSession.loadServerVariables().

src/test/java/testsuite/regression/MetaDataRegressionTest.java

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
import com.mysql.cj.CharsetMappingWrapper;
6868
import com.mysql.cj.Constants;
6969
import com.mysql.cj.MysqlConnection;
70+
import com.mysql.cj.MysqlType;
7071
import com.mysql.cj.NativeCharsetSettings;
7172
import com.mysql.cj.Query;
7273
import com.mysql.cj.conf.PropertyDefinitions.DatabaseTerm;
@@ -3987,7 +3988,7 @@ public void testBug35115() throws Exception {
39873988
rsMetaData = this.rs.getMetaData();
39883989

39893990
assertTrue(this.rs.next());
3990-
assertEquals(Types.DATE, rsMetaData.getColumnType(1), "YEAR columns should be treated as java.sql.Types.DATE");
3991+
assertEquals(Types.SMALLINT, rsMetaData.getColumnType(1), "YEAR columns should be treated as java.sql.Types.SMALLINT");
39913992
assertEquals("YEAR", rsMetaData.getColumnTypeName(1), "YEAR columns should be identified as 'YEAR'");
39923993
assertEquals(java.lang.Short.class.getName(), rsMetaData.getColumnClassName(1), "YEAR columns should be mapped to java.lang.Short");
39933994
assertEquals(java.lang.Short.class.getName(), this.rs.getObject(1).getClass().getName(), "YEAR columns should be returned as java.lang.Short");
@@ -5408,4 +5409,60 @@ public void testBug33723611() throws Exception {
54085409
DatabaseMetaData dbmd = this.conn.getMetaData();
54095410
assertEquals(Connection.TRANSACTION_REPEATABLE_READ, dbmd.getDefaultTransactionIsolation());
54105411
}
5412+
5413+
/**
5414+
* Tests fix for Bug#82084 (23743938), YEAR DATA TYPE RETURNS INCORRECT VALUE FOR JDBC GETCOLUMNTYPE().
5415+
*
5416+
* @throws Exception
5417+
*/
5418+
@Test
5419+
public void testBug82084() throws Exception {
5420+
createProcedure("testBug82084p", "(in param1 int, out result year) BEGIN select 1, ''; END");
5421+
createTable("testBug82084", "(col_tiny SMALLINT, col_year year, col_date date)");
5422+
this.stmt.executeUpdate("INSERT INTO testBug82084 VALUES(1,2006, '2006-01-01')");
5423+
Properties props = new Properties();
5424+
props.setProperty(PropertyKey.sslMode.getKeyName(), SslMode.DISABLED.name());
5425+
props.setProperty(PropertyKey.allowPublicKeyRetrieval.getKeyName(), "true");
5426+
5427+
for (boolean useIS : new Boolean[] { true, false }) {
5428+
for (boolean yearIsDate : new Boolean[] { true, false }) {
5429+
props.setProperty(PropertyKey.yearIsDateType.getKeyName(), "" + yearIsDate);
5430+
props.setProperty(PropertyKey.useInformationSchema.getKeyName(), "" + useIS);
5431+
Connection con = getConnectionWithProps(props);
5432+
5433+
DatabaseMetaData dbmd = con.getMetaData();
5434+
this.rs = dbmd.getColumns(null, null, "testBug82084", "%year");
5435+
assertTrue(this.rs.next());
5436+
assertEquals(MysqlType.YEAR.getName(), this.rs.getString("TYPE_NAME"));
5437+
assertEquals(yearIsDate ? Types.DATE : Types.SMALLINT, this.rs.getInt("DATA_TYPE"));
5438+
5439+
this.rs = dbmd.getTypeInfo();
5440+
while (this.rs.next()) {
5441+
if (this.rs.getString("TYPE_NAME").equals("YEAR")) {
5442+
assertEquals(yearIsDate ? Types.DATE : Types.SMALLINT, this.rs.getInt("DATA_TYPE"));
5443+
break;
5444+
}
5445+
}
5446+
5447+
ResultSet procMD = con.getMetaData().getProcedureColumns(null, null, "testBug82084p", "%result");
5448+
assertTrue(procMD.next());
5449+
assertEquals(MysqlType.YEAR.getName(), procMD.getString("TYPE_NAME"));
5450+
assertEquals(yearIsDate ? Types.DATE : Types.SMALLINT, procMD.getInt("DATA_TYPE"));
5451+
5452+
this.rs = con.createStatement().executeQuery("select * from testBug82084");
5453+
ResultSetMetaData rsmd = this.rs.getMetaData();
5454+
5455+
assertEquals(MysqlType.YEAR.getName(), rsmd.getColumnTypeName(2));
5456+
if (yearIsDate) {
5457+
assertEquals(Types.DATE, rsmd.getColumnType(2));
5458+
assertEquals(java.sql.Date.class.getName(), rsmd.getColumnClassName(2));
5459+
} else {
5460+
assertEquals(Types.SMALLINT, rsmd.getColumnType(2));
5461+
assertEquals(Short.class.getName(), rsmd.getColumnClassName(2));
5462+
}
5463+
5464+
con.close();
5465+
}
5466+
}
5467+
}
54115468
}

0 commit comments

Comments
 (0)