HHH-16989 fix 'cast(string as String(10))', 'cast(string as Binary(10))' on MySQL

This commit is contained in:
Gavin King 2023-08-18 20:39:02 +02:00
parent 8461ba2078
commit 72e092f67f
5 changed files with 164 additions and 109 deletions

View File

@ -299,51 +299,45 @@ public class MySQLLegacyDialect extends Dialect {
final int maxLobLen = 65_535; final int maxLobLen = 65_535;
final int maxMediumLobLen = 16_777_215; final int maxMediumLobLen = 16_777_215;
final CapacityDependentDdlType.Builder varcharBuilder = CapacityDependentDdlType.builder( final CapacityDependentDdlType.Builder varcharBuilder =
VARCHAR, CapacityDependentDdlType.builder( VARCHAR,
columnType( CLOB ), columnType( CLOB ), columnType( CHAR ), castType( CHAR ), this )
"char", .withTypeCapacity( getMaxVarcharLength(), "varchar($l)" )
this .withTypeCapacity( maxMediumLobLen, "mediumtext" );
)
.withTypeCapacity( getMaxVarcharLength(), "varchar($l)" )
.withTypeCapacity( maxMediumLobLen, "mediumtext" );
if ( getMaxVarcharLength() < maxLobLen ) { if ( getMaxVarcharLength() < maxLobLen ) {
varcharBuilder.withTypeCapacity( maxLobLen, "text" ); varcharBuilder.withTypeCapacity( maxLobLen, "text" );
} }
ddlTypeRegistry.addDescriptor( varcharBuilder.build() ); ddlTypeRegistry.addDescriptor( varcharBuilder.build() );
final CapacityDependentDdlType.Builder nvarcharBuilder = CapacityDependentDdlType.builder( final CapacityDependentDdlType.Builder nvarcharBuilder =
NVARCHAR, CapacityDependentDdlType.builder( NVARCHAR,
columnType( NCLOB ), columnType( NCLOB ), columnType( NCHAR ), castType( NCHAR ), this )
"char", .withTypeCapacity( getMaxVarcharLength(), "varchar($l)" )
this .withTypeCapacity( maxMediumLobLen, "mediumtext" );
)
.withTypeCapacity( getMaxVarcharLength(), "varchar($l)" )
.withTypeCapacity( maxMediumLobLen, "mediumtext" );
if ( getMaxVarcharLength() < maxLobLen ) { if ( getMaxVarcharLength() < maxLobLen ) {
nvarcharBuilder.withTypeCapacity( maxLobLen, "text" ); nvarcharBuilder.withTypeCapacity( maxLobLen, "text" );
} }
ddlTypeRegistry.addDescriptor( nvarcharBuilder.build() ); ddlTypeRegistry.addDescriptor( nvarcharBuilder.build() );
final CapacityDependentDdlType.Builder varbinaryBuilder = CapacityDependentDdlType.builder( final CapacityDependentDdlType.Builder varbinaryBuilder =
VARBINARY, CapacityDependentDdlType.builder( VARBINARY,
columnType( BLOB ), columnType( BLOB ), columnType( BINARY ), castType( BINARY ), this )
"binary", .withTypeCapacity( getMaxVarbinaryLength(), "varbinary($l)" )
this .withTypeCapacity( maxMediumLobLen, "mediumblob" );
)
.withTypeCapacity( getMaxVarbinaryLength(), "varbinary($l)" )
.withTypeCapacity( maxMediumLobLen, "mediumblob" );
if ( getMaxVarbinaryLength() < maxLobLen ) { if ( getMaxVarbinaryLength() < maxLobLen ) {
varbinaryBuilder.withTypeCapacity( maxLobLen, "blob" ); varbinaryBuilder.withTypeCapacity( maxLobLen, "blob" );
} }
ddlTypeRegistry.addDescriptor( varbinaryBuilder.build() ); ddlTypeRegistry.addDescriptor( varbinaryBuilder.build() );
ddlTypeRegistry.addDescriptor( new DdlTypeImpl( LONG32VARBINARY, columnType( BLOB ), "binary", this ) ); ddlTypeRegistry.addDescriptor( new DdlTypeImpl( LONG32VARBINARY,
ddlTypeRegistry.addDescriptor( new DdlTypeImpl( LONG32VARCHAR, columnType( CLOB ), "char", this ) ); columnType( BLOB ), castType( BINARY ), this ) );
ddlTypeRegistry.addDescriptor( new DdlTypeImpl( LONG32NVARCHAR, columnType( CLOB ), "char", this ) ); ddlTypeRegistry.addDescriptor( new DdlTypeImpl( LONG32VARCHAR,
columnType( CLOB ), castType( CHAR ), this ) );
ddlTypeRegistry.addDescriptor( new DdlTypeImpl( LONG32NVARCHAR,
columnType( CLOB ), castType( NCHAR ), this ) );
ddlTypeRegistry.addDescriptor( ddlTypeRegistry.addDescriptor(
CapacityDependentDdlType.builder( BLOB, columnType( BLOB ), "binary", this ) CapacityDependentDdlType.builder( BLOB, columnType( BLOB ), castType( BINARY ), this )
.withTypeCapacity( maxTinyLobLen, "tinyblob" ) .withTypeCapacity( maxTinyLobLen, "tinyblob" )
.withTypeCapacity( maxMediumLobLen, "mediumblob" ) .withTypeCapacity( maxMediumLobLen, "mediumblob" )
.withTypeCapacity( maxLobLen, "blob" ) .withTypeCapacity( maxLobLen, "blob" )
@ -351,7 +345,7 @@ public class MySQLLegacyDialect extends Dialect {
); );
ddlTypeRegistry.addDescriptor( ddlTypeRegistry.addDescriptor(
CapacityDependentDdlType.builder( CLOB, columnType( CLOB ), "char", this ) CapacityDependentDdlType.builder( CLOB, columnType( CLOB ), castType( CHAR ), this )
.withTypeCapacity( maxTinyLobLen, "tinytext" ) .withTypeCapacity( maxTinyLobLen, "tinytext" )
.withTypeCapacity( maxMediumLobLen, "mediumtext" ) .withTypeCapacity( maxMediumLobLen, "mediumtext" )
.withTypeCapacity( maxLobLen, "text" ) .withTypeCapacity( maxLobLen, "text" )
@ -359,7 +353,7 @@ public class MySQLLegacyDialect extends Dialect {
); );
ddlTypeRegistry.addDescriptor( ddlTypeRegistry.addDescriptor(
CapacityDependentDdlType.builder( NCLOB, columnType( NCLOB ), "char", this ) CapacityDependentDdlType.builder( NCLOB, columnType( NCLOB ), castType( NCHAR ), this )
.withTypeCapacity( maxTinyLobLen, "tinytext" ) .withTypeCapacity( maxTinyLobLen, "tinytext" )
.withTypeCapacity( maxMediumLobLen, "mediumtext" ) .withTypeCapacity( maxMediumLobLen, "mediumtext" )
.withTypeCapacity( maxLobLen, "text" ) .withTypeCapacity( maxLobLen, "text" )

View File

@ -297,13 +297,14 @@ public class MySQLDialect extends Dialect {
//the default scale is 0 (no decimal places) //the default scale is 0 (no decimal places)
return "decimal($p,$s)"; return "decimal($p,$s)";
case CHAR: case CHAR:
case NCHAR:
case VARCHAR: case VARCHAR:
case NVARCHAR:
case LONG32VARCHAR: case LONG32VARCHAR:
case LONG32NVARCHAR:
//MySQL doesn't let you cast to TEXT/LONGTEXT //MySQL doesn't let you cast to TEXT/LONGTEXT
return "char"; return "char";
case NCHAR:
case NVARCHAR:
case LONG32NVARCHAR:
return "char character set utf8";
case BINARY: case BINARY:
case VARBINARY: case VARBINARY:
case LONG32VARBINARY: case LONG32VARBINARY:
@ -332,14 +333,11 @@ public class MySQLDialect extends Dialect {
final int maxLobLen = 65_535; final int maxLobLen = 65_535;
final int maxMediumLobLen = 16_777_215; final int maxMediumLobLen = 16_777_215;
final CapacityDependentDdlType.Builder varcharBuilder = CapacityDependentDdlType.builder( final CapacityDependentDdlType.Builder varcharBuilder =
VARCHAR, CapacityDependentDdlType.builder( VARCHAR,
columnType( CLOB ), columnType( CLOB ), columnType( CHAR ), castType( CHAR ), this )
"char", .withTypeCapacity( getMaxVarcharLength(), "varchar($l)" )
this .withTypeCapacity( maxMediumLobLen, "mediumtext" );
)
.withTypeCapacity( getMaxVarcharLength(), "varchar($l)" )
.withTypeCapacity( maxMediumLobLen, "mediumtext" );
if ( getMaxVarcharLength() < maxLobLen ) { if ( getMaxVarcharLength() < maxLobLen ) {
varcharBuilder.withTypeCapacity( maxLobLen, "text" ); varcharBuilder.withTypeCapacity( maxLobLen, "text" );
} }
@ -347,38 +345,36 @@ public class MySQLDialect extends Dialect {
// do not use nchar/nvarchar/ntext because these // do not use nchar/nvarchar/ntext because these
// types use a deprecated character set on MySQL 8 // types use a deprecated character set on MySQL 8
final CapacityDependentDdlType.Builder nvarcharBuilder = CapacityDependentDdlType.builder( final CapacityDependentDdlType.Builder nvarcharBuilder =
NVARCHAR, CapacityDependentDdlType.builder( NVARCHAR,
columnType( NCLOB ), columnType( NCLOB ), columnType( NCHAR ), castType( NCHAR ), this )
"char character set utf8", .withTypeCapacity( getMaxVarcharLength(), "varchar($l) character set utf8" )
this .withTypeCapacity( maxMediumLobLen, "mediumtext character set utf8" );
)
.withTypeCapacity( getMaxVarcharLength(), "varchar($l) character set utf8" )
.withTypeCapacity( maxMediumLobLen, "mediumtext character set utf8" );
if ( getMaxVarcharLength() < maxLobLen ) { if ( getMaxVarcharLength() < maxLobLen ) {
nvarcharBuilder.withTypeCapacity( maxLobLen, "text character set utf8" ); nvarcharBuilder.withTypeCapacity( maxLobLen, "text character set utf8" );
} }
ddlTypeRegistry.addDescriptor( nvarcharBuilder.build() ); ddlTypeRegistry.addDescriptor( nvarcharBuilder.build() );
final CapacityDependentDdlType.Builder varbinaryBuilder = CapacityDependentDdlType.builder( final CapacityDependentDdlType.Builder varbinaryBuilder =
VARBINARY, CapacityDependentDdlType.builder( VARBINARY,
columnType( BLOB ), columnType( BLOB ), columnType( BINARY ), castType( BINARY ), this )
"binary", .withTypeCapacity( getMaxVarbinaryLength(), "varbinary($l)" )
this .withTypeCapacity( maxMediumLobLen, "mediumblob" );
)
.withTypeCapacity( getMaxVarbinaryLength(), "varbinary($l)" )
.withTypeCapacity( maxMediumLobLen, "mediumblob" );
if ( getMaxVarbinaryLength() < maxLobLen ) { if ( getMaxVarbinaryLength() < maxLobLen ) {
varbinaryBuilder.withTypeCapacity( maxLobLen, "blob" ); varbinaryBuilder.withTypeCapacity( maxLobLen, "blob" );
} }
ddlTypeRegistry.addDescriptor( varbinaryBuilder.build() ); ddlTypeRegistry.addDescriptor( varbinaryBuilder.build() );
ddlTypeRegistry.addDescriptor( new DdlTypeImpl( LONG32VARBINARY, columnType( BLOB ), "binary", this ) ); ddlTypeRegistry.addDescriptor( new DdlTypeImpl( LONG32VARBINARY,
ddlTypeRegistry.addDescriptor( new DdlTypeImpl( LONG32VARCHAR, columnType( CLOB ), "char", this ) ); columnType( BLOB ), castType( BINARY ), this ) );
ddlTypeRegistry.addDescriptor( new DdlTypeImpl( LONG32NVARCHAR, columnType( CLOB ), "char", this ) ); ddlTypeRegistry.addDescriptor( new DdlTypeImpl( LONG32VARCHAR,
columnType( CLOB ), castType( CHAR ), this ) );
ddlTypeRegistry.addDescriptor( new DdlTypeImpl( LONG32NVARCHAR,
columnType( CLOB ), castType( CHAR ), this ) );
ddlTypeRegistry.addDescriptor( ddlTypeRegistry.addDescriptor(
CapacityDependentDdlType.builder( BLOB, columnType( BLOB ), "binary", this ) CapacityDependentDdlType.builder( BLOB,
columnType( BLOB ), castType( BINARY ), this )
.withTypeCapacity( maxTinyLobLen, "tinyblob" ) .withTypeCapacity( maxTinyLobLen, "tinyblob" )
.withTypeCapacity( maxMediumLobLen, "mediumblob" ) .withTypeCapacity( maxMediumLobLen, "mediumblob" )
.withTypeCapacity( maxLobLen, "blob" ) .withTypeCapacity( maxLobLen, "blob" )
@ -386,7 +382,8 @@ public class MySQLDialect extends Dialect {
); );
ddlTypeRegistry.addDescriptor( ddlTypeRegistry.addDescriptor(
CapacityDependentDdlType.builder( CLOB, columnType( CLOB ), "char", this ) CapacityDependentDdlType.builder( CLOB,
columnType( CLOB ), castType( CHAR ), this )
.withTypeCapacity( maxTinyLobLen, "tinytext" ) .withTypeCapacity( maxTinyLobLen, "tinytext" )
.withTypeCapacity( maxMediumLobLen, "mediumtext" ) .withTypeCapacity( maxMediumLobLen, "mediumtext" )
.withTypeCapacity( maxLobLen, "text" ) .withTypeCapacity( maxLobLen, "text" )
@ -394,7 +391,8 @@ public class MySQLDialect extends Dialect {
); );
ddlTypeRegistry.addDescriptor( ddlTypeRegistry.addDescriptor(
CapacityDependentDdlType.builder( NCLOB, columnType( NCLOB ), "char character set utf8", this ) CapacityDependentDdlType.builder( NCLOB,
columnType( NCLOB ), castType( NCHAR ), this )
.withTypeCapacity( maxTinyLobLen, "tinytext character set utf8" ) .withTypeCapacity( maxTinyLobLen, "tinytext character set utf8" )
.withTypeCapacity( maxMediumLobLen, "mediumtext character set utf8" ) .withTypeCapacity( maxMediumLobLen, "mediumtext character set utf8" )
.withTypeCapacity( maxLobLen, "text character set utf8" ) .withTypeCapacity( maxLobLen, "text character set utf8" )

View File

@ -26,12 +26,14 @@ public class CapacityDependentDdlType extends DdlTypeImpl {
builder.sqlTypeCode, builder.sqlTypeCode,
builder.typeNamePattern, builder.typeNamePattern,
builder.castTypeNamePattern, builder.castTypeNamePattern,
builder.castTypeName,
builder.dialect builder.dialect
); );
builder.typeEntries.sort( Comparator.naturalOrder() ); builder.typeEntries.sort( Comparator.naturalOrder() );
this.typeEntries = builder.typeEntries.toArray(new TypeEntry[0]); this.typeEntries = builder.typeEntries.toArray(new TypeEntry[0]);
} }
@Override @Deprecated
public String[] getRawTypeNames() { public String[] getRawTypeNames() {
final String[] rawTypeNames = new String[typeEntries.length + 1]; final String[] rawTypeNames = new String[typeEntries.length + 1];
for ( int i = 0; i < typeEntries.length; i++ ) { for ( int i = 0; i < typeEntries.length; i++ ) {
@ -78,15 +80,25 @@ public class CapacityDependentDdlType extends DdlTypeImpl {
public static Builder builder( public static Builder builder(
int sqlTypeCode, int sqlTypeCode,
String typeNamePattern, String typeNamePattern,
String castTypeNamePattern, String castTypeName,
Dialect dialect) { Dialect dialect) {
return new Builder( sqlTypeCode, typeNamePattern, castTypeNamePattern, dialect ); return new Builder( sqlTypeCode, typeNamePattern, null, castTypeName, dialect );
}
public static Builder builder(
int sqlTypeCode,
String typeNamePattern,
String castTypeNamePattern,
String castTypeName,
Dialect dialect) {
return new Builder( sqlTypeCode, typeNamePattern, castTypeNamePattern, castTypeName, dialect );
} }
public static class Builder { public static class Builder {
private final int sqlTypeCode; private final int sqlTypeCode;
private final String typeNamePattern; private final String typeNamePattern;
private final String castTypeNamePattern; private final String castTypeNamePattern;
private final String castTypeName;
private final Dialect dialect; private final Dialect dialect;
private final List<TypeEntry> typeEntries; private final List<TypeEntry> typeEntries;
@ -94,10 +106,12 @@ public class CapacityDependentDdlType extends DdlTypeImpl {
int sqlTypeCode, int sqlTypeCode,
String typeNamePattern, String typeNamePattern,
String castTypeNamePattern, String castTypeNamePattern,
String castTypeName,
Dialect dialect) { Dialect dialect) {
this.sqlTypeCode = sqlTypeCode; this.sqlTypeCode = sqlTypeCode;
this.typeNamePattern = typeNamePattern; this.typeNamePattern = typeNamePattern;
this.castTypeNamePattern = castTypeNamePattern; this.castTypeNamePattern = castTypeNamePattern;
this.castTypeName = castTypeName;
this.dialect = dialect; this.dialect = dialect;
this.typeEntries = new ArrayList<>(); this.typeEntries = new ArrayList<>();
} }

View File

@ -10,6 +10,7 @@ import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.Size; import org.hibernate.engine.jdbc.Size;
import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.StringHelper;
import org.hibernate.type.SqlTypes; import org.hibernate.type.SqlTypes;
import org.hibernate.type.descriptor.java.CharacterJavaType;
import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.descriptor.jdbc.JdbcType;
import org.hibernate.type.descriptor.sql.DdlType; import org.hibernate.type.descriptor.sql.DdlType;
@ -24,24 +25,36 @@ public class DdlTypeImpl implements DdlType {
private final int sqlTypeCode; private final int sqlTypeCode;
private final String typeNamePattern; private final String typeNamePattern;
private final String castTypeNamePattern; private final String castTypeNamePattern;
private final String castTypeName;
private final boolean castTypeNameIsStatic; private final boolean castTypeNameIsStatic;
final Dialect dialect; final Dialect dialect;
public DdlTypeImpl(int sqlTypeCode, String typeNamePattern, Dialect dialect) { public DdlTypeImpl(int sqlTypeCode, String typeNamePattern, Dialect dialect) {
this( sqlTypeCode, typeNamePattern, typeNamePattern, dialect ); this( sqlTypeCode, typeNamePattern, typeNamePattern, typeNamePattern, dialect );
} }
public DdlTypeImpl( public DdlTypeImpl(
int sqlTypeCode, int sqlTypeCode,
String typeNamePattern, String typeNamePattern,
String castTypeNamePattern, String castTypeName,
Dialect dialect) {
this( sqlTypeCode, typeNamePattern, null, castTypeName, dialect );
}
public DdlTypeImpl(
int sqlTypeCode,
String typeNamePattern,
String castTypeNamePattern, //optional, usually null
String castTypeName,
Dialect dialect) { Dialect dialect) {
this.sqlTypeCode = sqlTypeCode; this.sqlTypeCode = sqlTypeCode;
this.typeNamePattern = typeNamePattern; this.typeNamePattern = typeNamePattern;
this.castTypeNamePattern = castTypeNamePattern; this.castTypeNamePattern = castTypeNamePattern;
this.castTypeNameIsStatic = !castTypeNamePattern.contains( "$s" ) this.castTypeName = castTypeName;
&& !castTypeNamePattern.contains( "$l" ) this.castTypeNameIsStatic =
&& !castTypeNamePattern.contains( "$p" ); !castTypeName.contains( "$s" )
&& !castTypeName.contains( "$p" )
&& !castTypeName.contains( "$l" );
this.dialect = dialect; this.dialect = dialect;
} }
@ -58,7 +71,7 @@ public class DdlTypeImpl implements DdlType {
final int parenEnd = typeNamePattern.lastIndexOf( ')' ); final int parenEnd = typeNamePattern.lastIndexOf( ')' );
return parenEnd + 1 == typeNamePattern.length() return parenEnd + 1 == typeNamePattern.length()
? typeNamePattern.substring( 0, paren ) ? typeNamePattern.substring( 0, paren )
: ( typeNamePattern.substring( 0, paren ) + typeNamePattern.substring( parenEnd + 1 ) ); : typeNamePattern.substring( 0, paren ) + typeNamePattern.substring( parenEnd + 1 );
} }
return typeNamePattern; return typeNamePattern;
} }
@ -79,38 +92,40 @@ public class DdlTypeImpl implements DdlType {
//needed for cast(x as BigInteger(p)) //needed for cast(x as BigInteger(p))
scale = javaType.getDefaultSqlScale( dialect, jdbcType ); scale = javaType.getDefaultSqlScale( dialect, jdbcType );
} }
return castTypeNamePattern == null
? getTypeName( length, precision, scale )
: replace( castTypeNamePattern, length, precision, scale );
} }
return getTypeName( length, precision, scale );
} }
@Override @Override
public String getCastTypeName(JdbcType jdbcType, JavaType<?> javaType) { public String getCastTypeName(JdbcType jdbcType, JavaType<?> javaType) {
if ( castTypeNameIsStatic ) { if ( javaType instanceof CharacterJavaType && jdbcType.isString() ) {
return castTypeNamePattern; // nasty special case for casting to Character
return getCastTypeName( jdbcType, javaType, 1L, null, null );
} }
Long length = null; else if ( castTypeNameIsStatic ) {
Integer precision = null; return castTypeName;
Integer scale = null; }
else {
final Size size = dialect.getSizeStrategy()
.resolveSize( jdbcType, javaType, null, null, defaultLength( jdbcType ) );
return replace( castTypeName, size.getLength(), size.getPrecision(), size.getScale() );
}
}
//TODO: move this to JdbcType??
private Long defaultLength(JdbcType jdbcType) {
switch ( jdbcType.getDdlTypeCode() ) { switch ( jdbcType.getDdlTypeCode() ) {
case SqlTypes.VARCHAR: case SqlTypes.VARCHAR:
length = (long) dialect.getMaxVarcharLength(); return (long) dialect.getMaxVarcharLength();
break;
case SqlTypes.NVARCHAR: case SqlTypes.NVARCHAR:
length = (long) dialect.getMaxNVarcharLength(); return (long) dialect.getMaxNVarcharLength();
break;
case SqlTypes.VARBINARY: case SqlTypes.VARBINARY:
length = (long) dialect.getMaxVarbinaryLength(); return (long) dialect.getMaxVarbinaryLength();
break; default:
return null;
} }
final Size size = dialect.getSizeStrategy().resolveSize(
jdbcType,
javaType,
precision,
scale,
length
);
return replace( castTypeNamePattern, size.getLength(), size.getPrecision(), size.getScale() );
} }
/** /**

View File

@ -14,6 +14,7 @@ import org.hibernate.dialect.H2Dialect;
import org.hibernate.dialect.MariaDBDialect; import org.hibernate.dialect.MariaDBDialect;
import org.hibernate.dialect.MySQLDialect; import org.hibernate.dialect.MySQLDialect;
import org.hibernate.dialect.OracleDialect; import org.hibernate.dialect.OracleDialect;
import org.hibernate.dialect.PostgreSQLDialect;
import org.hibernate.dialect.SybaseDialect; import org.hibernate.dialect.SybaseDialect;
import org.hibernate.dialect.TiDBDialect; import org.hibernate.dialect.TiDBDialect;
import org.hibernate.testing.TestForIssue; import org.hibernate.testing.TestForIssue;
@ -57,6 +58,7 @@ import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.isOneOf; import static org.hamcrest.Matchers.isOneOf;
import static org.hibernate.testing.orm.domain.gambit.EntityOfBasics.Gender.FEMALE; import static org.hibernate.testing.orm.domain.gambit.EntityOfBasics.Gender.FEMALE;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.Assertions.fail;
import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertThrows;
@ -997,21 +999,6 @@ public class FunctionTests {
); );
} }
@Test
@RequiresDialectFeature( feature = DialectFeatureChecks.SupportsTruncateThroughCast.class)
@SkipForDialect(dialectClass = MySQLDialect.class, matchSubTypes = true, reason = "We need to fix this, see HHH-16989")
public void testCastFunction_withTruncation(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
session.createQuery("select cast(e.theString as String(15)), cast(e.theDouble as String(8)) from EntityOfBasics e", Object[].class)
.list();
session.createQuery("select cast('ABCDEF' as Character) from EntityOfBasics", Character.class)
.list();
}
);
}
@Test @Test
@SkipForDialect(dialectClass = DerbyDialect.class, reason = "Derby doesn't support casting to the binary types") @SkipForDialect(dialectClass = DerbyDialect.class, reason = "Derby doesn't support casting to the binary types")
public void testCastFunctionBinary(SessionFactoryScope scope) { public void testCastFunctionBinary(SessionFactoryScope scope) {
@ -1024,15 +1011,62 @@ public class FunctionTests {
} }
@Test @Test
@SkipForDialect(dialectClass = MySQLDialect.class, matchSubTypes = true, reason = "We need to fix this, see HHH-16989")
@SkipForDialect(dialectClass = DerbyDialect.class, reason = "Derby doesn't support casting to the binary types")
public void testCastFunctionWithLength(SessionFactoryScope scope) { public void testCastFunctionWithLength(SessionFactoryScope scope) {
scope.inTransaction( scope.inTransaction(
session -> { session -> {
session.createQuery("select cast(e.theString as String(15)), cast(e.theDouble as String(17)) from EntityOfBasics e", Object[].class) session.createQuery("select cast(e.theString as String(15)), cast(e.theDouble as String(17)) from EntityOfBasics e", Object[].class)
.list(); .list();
assertEquals( 'A',
session.createQuery("select cast('ABCDEF' as Character)", Character.class)
.getSingleResult() );
assertEquals( "ABC",
session.createQuery("select cast('ABCDEF' as String(3))", String.class)
.getSingleResult() );
}
);
}
@Test
@SkipForDialect(dialectClass = DerbyDialect.class, reason = "Derby doesn't support casting to binary types")
@SkipForDialect(dialectClass = PostgreSQLDialect.class, matchSubTypes = true, reason = "PostgreSQL bytea doesn't have a length")
@SkipForDialect(dialectClass = OracleDialect.class, reason = "Oracle cast to raw does not do truncatation")
public void testCastBinaryWithLength(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
session.createQuery("select cast(e.theString as Binary(10)) from EntityOfBasics e", byte[].class) session.createQuery("select cast(e.theString as Binary(10)) from EntityOfBasics e", byte[].class)
.list(); .list();
assertArrayEquals( new byte[]{(byte)0xFF,(byte)0},
session.createQuery("select cast(X'FF00EE11' as Binary(2))", byte[].class)
.getSingleResult() );
}
);
}
@Test
@SkipForDialect(dialectClass = DerbyDialect.class, reason = "Derby doesn't support casting varchar to binary")
@SkipForDialect(dialectClass = PostgreSQLDialect.class, matchSubTypes = true, reason = "PostgreSQL bytea doesn't have a length")
public void testCastBinaryWithLengthForOracle(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
session.createQuery("select cast(e.theString as Binary(10)) from EntityOfBasics e", byte[].class)
.list();
assertArrayEquals( new byte[]{(byte)0xFF,(byte)0},
session.createQuery("select cast(X'FF00' as Binary(2))", byte[].class)
.getSingleResult() );
}
);
}
@Test
@SkipForDialect(dialectClass = PostgreSQLDialect.class, matchSubTypes = true, reason = "PostgreSQL bytea doesn't have a length")
public void testCastBinaryWithLengthForDerby(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
session.createQuery("select cast(X'22FF00EE11' as Binary(10))", byte[].class)
.list();
assertArrayEquals( new byte[]{(byte)0xFF,(byte)0},
session.createQuery("select cast(X'FF00' as Binary(2))", byte[].class)
.getSingleResult() );
} }
); );
} }