Skip to content

Commit 1ef22c0

Browse files
committed
HHH-18806 fix nationalized strings on Sybase jTDS
Signed-off-by: Gavin King <[email protected]>
1 parent 1c87d73 commit 1ef22c0

File tree

6 files changed

+48
-37
lines changed

6 files changed

+48
-37
lines changed

hibernate-core/src/main/java/org/hibernate/dialect/NationalizationSupport.java

Lines changed: 25 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -15,58 +15,57 @@
1515
* @see Dialect#getNationalizationSupport()
1616
*/
1717
public enum NationalizationSupport {
18+
1819
/**
1920
* The {@code CHAR}, {@code VARCHAR}, and {@code CLOB}
2021
* types inherently handle nationalized character data.
2122
* Usually the database will not even define dedicated
2223
* nationalized data types like {@code NVARCHAR}.
2324
*/
24-
IMPLICIT( Types.CHAR, Types.VARCHAR, Types.LONGVARCHAR, Types.CLOB ),
25+
IMPLICIT,
26+
2527
/**
2628
* The database does define and support distinct SQL types
2729
* for representing nationalized character data, typically
2830
* named {@code NCHAR}, {@code NVARCHAR}, and {@code NCLOB}.
2931
*/
30-
EXPLICIT( Types.NCHAR, Types.NVARCHAR, Types.LONGNVARCHAR, Types.NCLOB ),
32+
EXPLICIT,
33+
3134
/**
3235
* The database does not even have support for nationalized
3336
* character data.
3437
*/
3538
UNSUPPORTED;
3639

37-
private final int charVariantCode;
38-
private final int varcharVariantCode;
39-
private final int longVarcharVariantCode;
40-
private final int clobVariantCode;
41-
42-
NationalizationSupport() {
43-
this( -1, -1, -1, -1 );
44-
}
45-
46-
NationalizationSupport(
47-
int charVariantCode,
48-
int varcharVariantCode,
49-
int longVarcharVariantCode,
50-
int clobVariantCode) {
51-
this.charVariantCode = charVariantCode;
52-
this.varcharVariantCode = varcharVariantCode;
53-
this.longVarcharVariantCode = longVarcharVariantCode;
54-
this.clobVariantCode = clobVariantCode;
55-
}
56-
5740
public int getCharVariantCode() {
58-
return charVariantCode;
41+
return switch ( this ) {
42+
case IMPLICIT -> Types.CHAR;
43+
case EXPLICIT -> Types.NCHAR;
44+
case UNSUPPORTED -> throw new UnsupportedOperationException("Nationalized character data not supported on this database");
45+
};
5946
}
6047

6148
public int getVarcharVariantCode() {
62-
return varcharVariantCode;
49+
return switch ( this ) {
50+
case IMPLICIT -> Types.VARCHAR;
51+
case EXPLICIT -> Types.NVARCHAR;
52+
case UNSUPPORTED -> throw new UnsupportedOperationException("Nationalized character data not supported on this database");
53+
};
6354
}
6455

6556
public int getLongVarcharVariantCode() {
66-
return longVarcharVariantCode;
57+
return switch ( this ) {
58+
case IMPLICIT -> Types.LONGVARCHAR;
59+
case EXPLICIT -> Types.LONGNVARCHAR;
60+
case UNSUPPORTED -> throw new UnsupportedOperationException("Nationalized character data not supported on this database");
61+
};
6762
}
6863

6964
public int getClobVariantCode() {
70-
return clobVariantCode;
65+
return switch ( this ) {
66+
case IMPLICIT -> Types.CLOB;
67+
case EXPLICIT -> Types.NCLOB;
68+
case UNSUPPORTED -> throw new UnsupportedOperationException("Nationalized character data not supported on this database");
69+
};
7170
}
7271
}

hibernate-core/src/main/java/org/hibernate/dialect/SybaseDialect.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -213,10 +213,7 @@ public void contributeTypes(TypeContributions typeContributions, ServiceRegistry
213213

214214
// The jTDS driver doesn't support the JDBC4 signatures using 'long length' for stream bindings
215215
jdbcTypeRegistry.addDescriptor( Types.CLOB, ClobJdbcType.CLOB_BINDING );
216-
217-
// The jTDS driver doesn't support nationalized types
218216
jdbcTypeRegistry.addDescriptor( Types.NCLOB, ClobJdbcType.CLOB_BINDING );
219-
jdbcTypeRegistry.addDescriptor( Types.NVARCHAR, ClobJdbcType.CLOB_BINDING );
220217
}
221218
else {
222219
// jConnect driver only conditionally supports getClob/getNClob depending on a server setting. See
@@ -254,7 +251,7 @@ public void contributeTypes(TypeContributions typeContributions, ServiceRegistry
254251
@Override
255252
public NationalizationSupport getNationalizationSupport() {
256253
// At least the jTDS driver doesn't support this
257-
return driverKind == SybaseDriverKind.JTDS ? NationalizationSupport.IMPLICIT : super.getNationalizationSupport();
254+
return super.getNationalizationSupport();
258255
}
259256

260257
@Override

hibernate-core/src/main/java/org/hibernate/dialect/function/xml/HANAXmlTableFunction.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
import org.hibernate.query.sqm.tree.expression.SqmXmlTableFunction;
3030
import org.hibernate.spi.NavigablePath;
3131
import org.hibernate.sql.Template;
32-
import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
3332
import org.hibernate.sql.ast.SqlAstTranslator;
3433
import org.hibernate.sql.ast.internal.ColumnQualifierCollectorSqlAstWalker;
3534
import org.hibernate.sql.ast.spi.FromClauseAccess;

hibernate-core/src/main/java/org/hibernate/type/descriptor/java/StringJavaType.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
1919
import org.hibernate.type.spi.TypeConfiguration;
2020

21+
import static java.nio.charset.StandardCharsets.UTF_8;
22+
2123
/**
2224
* Descriptor for {@link String} handling.
2325
*
@@ -68,6 +70,9 @@ public <X> X unwrap(String value, Class<X> type, WrapperOptions options) {
6870
if ( String.class.isAssignableFrom( type ) ) {
6971
return (X) value;
7072
}
73+
if ( byte[].class.isAssignableFrom( type ) ) {
74+
return (X) value.getBytes( UTF_8 );
75+
}
7176
if ( Reader.class.isAssignableFrom( type ) ) {
7277
return (X) new StringReader( value );
7378
}
@@ -103,6 +108,9 @@ public <X> String wrap(X value, WrapperOptions options) {
103108
if (value instanceof char[] chars) {
104109
return new String( chars );
105110
}
111+
if (value instanceof byte[] bytes) {
112+
return new String( bytes, UTF_8 );
113+
}
106114
if (value instanceof Reader reader) {
107115
return DataHelper.extractString( reader );
108116
}

hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/NVarcharJdbcType.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,13 @@ public <X> ValueBinder<X> getBinder(final JavaType<X> javaType) {
105105
@Override
106106
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options) throws SQLException {
107107
if ( options.getDialect().supportsNationalizedMethods() ) {
108-
st.setNString( index, javaType.unwrap( value, String.class, options ) );
108+
try {
109+
st.setNString( index, javaType.unwrap( value, String.class, options ) );
110+
}
111+
// workaround for jTDS driver for Sybase
112+
catch ( AbstractMethodError e ) {
113+
st.setBytes( index, javaType.unwrap( value, byte[].class, options ) );
114+
}
109115
}
110116
else {
111117
st.setString( index, javaType.unwrap( value, String.class, options ) );
@@ -131,7 +137,13 @@ public <X> ValueExtractor<X> getExtractor(final JavaType<X> javaType) {
131137
@Override
132138
protected X doExtract(ResultSet rs, int paramIndex, WrapperOptions options) throws SQLException {
133139
if ( options.getDialect().supportsNationalizedMethods() ) {
134-
return javaType.wrap( rs.getNString( paramIndex ), options );
140+
try {
141+
return javaType.wrap( rs.getNString( paramIndex ), options );
142+
}
143+
// workaround for jTDS driver for Sybase
144+
catch ( AbstractMethodError e ) {
145+
return javaType.wrap( rs.getBytes( paramIndex ), options );
146+
}
135147
}
136148
else {
137149
return javaType.wrap( rs.getString( paramIndex ), options );

hibernate-core/src/test/java/org/hibernate/orm/test/mapping/basic/NationalizedTest.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,8 @@
88
import jakarta.persistence.Id;
99

1010
import org.hibernate.annotations.Nationalized;
11-
import org.hibernate.dialect.SybaseASEDialect;
1211
import org.hibernate.orm.test.jpa.BaseEntityManagerFunctionalTestCase;
1312

14-
import org.hibernate.testing.orm.junit.SkipForDialect;
1513
import org.junit.Test;
1614

1715
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
@@ -20,8 +18,6 @@
2018
/**
2119
* @author Vlad Mihalcea
2220
*/
23-
@SkipForDialect(dialectClass = SybaseASEDialect.class,
24-
reason = "Error converting characters into server's character set")
2521
public class NationalizedTest extends BaseEntityManagerFunctionalTestCase {
2622

2723
@Override

0 commit comments

Comments
 (0)