Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions src/main/core-impl/java/com/mysql/cj/result/UuidValueFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* Copyright (c) 2025, Oracle and/or its affiliates.
*
* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, as published by
* the Free Software Foundation.
*
* This program is designed to work with certain software that is licensed under separate terms, as designated in a particular file or component or in
* included license documentation. The authors of MySQL hereby grant you an additional permission to link the program and your derivative works with the
* separately licensed software that they have either included with the program or referenced in the documentation.
*
* Without limiting anything contained in the foregoing, this file, which is part of MySQL Connector/J, is also subject to the Universal FOSS Exception,
* version 1.0, a copy of which can be found at http://oss.oracle.com/licenses/universal-foss-exception.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0, for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

package com.mysql.cj.result;

import java.nio.ByteBuffer;
import java.util.UUID;

import com.mysql.cj.Messages;
import com.mysql.cj.MysqlType;
import com.mysql.cj.conf.PropertySet;
import com.mysql.cj.exceptions.DataConversionException;
import com.mysql.cj.util.StringUtils;

public class UuidValueFactory extends DefaultValueFactory<UUID> {

public UuidValueFactory(PropertySet pset) {
super(pset);
}

@Override
public UUID createFromBytes(byte[] bytes, int offset, int length, Field f) {
if (f.isBinary()) {
return getUuidFromBytes(bytes);
}
MysqlType mysqlType = f.getMysqlType();
switch (mysqlType) {
case CHAR:
case VARCHAR:
case TEXT:
case TINYTEXT:
case MEDIUMTEXT:
case LONGTEXT:
String s = StringUtils.toString(bytes, offset, length, f.getEncoding());
try {
return UUID.fromString(s);
} catch (IllegalArgumentException e) {
throw new DataConversionException(Messages.getString("ResultSet.UnableToConvertString", new Object[] { s, getTargetTypeName() }));
}
default:
break;
}
throw new DataConversionException(Messages.getString("ResultSet.UnsupportedConversion", new Object[] { mysqlType.name(), getTargetTypeName() }));
}

@Override
public String getTargetTypeName() {
return UUID.class.getName();
}

private static UUID getUuidFromBytes(byte[] bytes) {
ByteBuffer bb = ByteBuffer.wrap(bytes);
long high = bb.getLong();
long low = bb.getLong();

return new UUID(high, low);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
import java.util.Calendar;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.locks.Lock;

import com.mysql.cj.Messages;
Expand Down Expand Up @@ -106,6 +107,7 @@
import com.mysql.cj.result.SqlTimestampValueFactory;
import com.mysql.cj.result.StringValueFactory;
import com.mysql.cj.result.UtilCalendarValueFactory;
import com.mysql.cj.result.UuidValueFactory;
import com.mysql.cj.result.ValueFactory;
import com.mysql.cj.result.ZonedDateTimeValueFactory;
import com.mysql.cj.util.LogUtils;
Expand Down Expand Up @@ -192,6 +194,7 @@ public class ResultSetImpl extends NativeResultset implements ResultSetInternalM
private ValueFactory<Double> doubleValueFactory;
private ValueFactory<BigDecimal> bigDecimalValueFactory;
private ValueFactory<InputStream> binaryStreamValueFactory;
private ValueFactory<UUID> uuidValueFactory;
private ValueFactory<Time> defaultTimeValueFactory;
private ValueFactory<Timestamp> defaultTimestampValueFactory;

Expand Down Expand Up @@ -274,6 +277,7 @@ public ResultSetImpl(ResultsetRows tuples, JdbcConnection conn, StatementImpl cr
this.doubleValueFactory = new DoubleValueFactory(pset);
this.bigDecimalValueFactory = new BigDecimalValueFactory(pset);
this.binaryStreamValueFactory = new BinaryStreamValueFactory(pset);
this.uuidValueFactory = new UuidValueFactory(pset);

this.defaultTimeValueFactory = new SqlTimeValueFactory(pset, null, this.session.getServerSession().getDefaultTimeZone(), this);
this.defaultTimestampValueFactory = new SqlTimestampValueFactory(pset, null, this.session.getServerSession().getDefaultTimeZone(),
Expand Down Expand Up @@ -1319,7 +1323,10 @@ public <T> T getObject(int columnIndex, Class<T> type) throws SQLException {
checkRowPos();
checkColumnBounds(columnIndex);
return (T) this.thisRow.getValue(columnIndex - 1, this.doubleValueFactory);

} else if (type.equals(UUID.class)) {
checkRowPos();
checkColumnBounds(columnIndex);
return (T) this.thisRow.getValue(columnIndex - 1, this.uuidValueFactory);
} else if (type.equals(byte[].class)) {
return (T) getBytes(columnIndex);

Expand Down
117 changes: 117 additions & 0 deletions src/test/java/testsuite/simple/UuidTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
* Copyright (c) 2025, Oracle and/or its affiliates.
*
* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, as published by
* the Free Software Foundation.
*
* This program is designed to work with certain software that is licensed under separate terms, as designated in a particular file or component or in
* included license documentation. The authors of MySQL hereby grant you an additional permission to link the program and your derivative works with the
* separately licensed software that they have either included with the program or referenced in the documentation.
*
* Without limiting anything contained in the foregoing, this file, which is part of MySQL Connector/J, is also subject to the Universal FOSS Exception,
* version 1.0, a copy of which can be found at http://oss.oracle.com/licenses/universal-foss-exception.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0, for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

package testsuite.simple;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.sql.SQLException;
import java.util.UUID;

import org.junit.jupiter.api.Test;

import testsuite.BaseTestCase;

public class UuidTest extends BaseTestCase {

@Test
public void testUuidGetObjectFromNull() throws SQLException {
this.rs = this.stmt.executeQuery("select null col");
assertTrue(this.rs.next());
assertNull(this.rs.getObject(1, UUID.class));

this.rs.close();
this.rs = null;
}

@Test
public void testUuidGetObjectFromEmpty() throws SQLException {
this.rs = this.stmt.executeQuery("select '' col");
assertTrue(this.rs.next());
assertThrows(SQLException.class, "Cannot convert string '' to java.util.UUID value", () -> this.rs.getObject(1, UUID.class));

this.rs.close();
this.rs = null;
}

@Test
public void testUuidGetObjectFromInvalidStr() throws SQLException {
this.rs = this.stmt.executeQuery("select 'bogus uuid' col");
assertTrue(this.rs.next());
assertThrows(SQLException.class, "Cannot convert string 'bogus uuid' to java.util.UUID value", () -> this.rs.getObject(1, UUID.class));

this.rs.close();
this.rs = null;
}

@Test
public void testUuidGetObjectFromNumber() throws SQLException {
this.rs = this.stmt.executeQuery("select 1 col");
assertTrue(this.rs.next());
assertThrows(SQLException.class, "Unsupported conversion from LONG to java.util.UUID", () -> this.rs.getObject(1, UUID.class));

this.rs.close();
this.rs = null;
}

@Test
public void testUuidGetObjectFromBinary() throws SQLException {
testBinaryTypeColumns("binary(16)");
testBinaryTypeColumns("varbinary(16)");
}

private void testBinaryTypeColumns(String colDef) throws SQLException {
final UUID uuid = UUID.fromString("ed37122f-e13d-466e-b68e-38d3c06cc612");
createTable("uuid_test", "(col " + colDef + ")");
this.stmt.executeUpdate("insert into uuid_test (col) VALUES (uuid_to_bin('" + uuid.toString() + "'))");

assertGetObjectResult(uuid);
}

@Test
public void testUuidGetObjectFromChar() throws SQLException {
testCharTypeColumns("char(36)");
testCharTypeColumns("varchar(36)");
testCharTypeColumns("text");
testCharTypeColumns("tinytext");
testCharTypeColumns("mediumtext");
testCharTypeColumns("longtext");
}

private void testCharTypeColumns(String colDef) throws SQLException {
final UUID uuid = UUID.fromString("ed37122f-e13d-466e-b68e-38d3c06cc612");
createTable("uuid_test", "(col " + colDef + ")");
this.stmt.executeUpdate("insert into uuid_test (col) VALUES ('" + uuid.toString() + "')");

assertGetObjectResult(uuid);
}

private void assertGetObjectResult(UUID expected) throws SQLException {
this.rs = this.stmt.executeQuery("select col from uuid_test");
assertTrue(this.rs.next());
assertEquals(expected, this.rs.getObject(1, UUID.class));

this.rs.close();
this.rs = null;
}

}