HHH-18312 Fix for Informix nationalized JDBC types support

This commit is contained in:
Vladimír Kuruc 2024-06-28 17:04:27 +02:00 committed by Christian Beikov
parent a6503e100e
commit 711dffa7e3
9 changed files with 238 additions and 41 deletions

View File

@ -952,7 +952,7 @@ informix() {
informix_14_10() {
$PRIVILEGED_CLI $CONTAINER_CLI rm -f informix || true
$PRIVILEGED_CLI $CONTAINER_CLI run --name informix --privileged -p 9088:9088 -e LICENSE=accept -d icr.io/informix/informix-developer-database:14.10.FC9W1DE
$PRIVILEGED_CLI $CONTAINER_CLI run --name informix --privileged -p 9088:9088 -e LICENSE=accept -e GL_USEGLU=1 -d icr.io/informix/informix-developer-database:14.10.FC9W1DE
echo "Starting Informix. This can take a few minutes"
# Give the container some time to start
OUTPUT=
@ -962,7 +962,7 @@ informix_14_10() {
OUTPUT=$($PRIVILEGED_CLI $CONTAINER_CLI logs informix 2>&1)
if [[ $OUTPUT == *"Server Started"* ]]; then
sleep 15
$PRIVILEGED_CLI $CONTAINER_CLI exec informix bash -l -c "echo \"execute function task('create dbspace from storagepool', 'datadbs', '100 MB', '4');execute function task('create sbspace from storagepool', 'sbspace', '20 M', '0');create database dev in datadbs with log nlscase sensitive;\" > post_init.sql;dbaccess sysadmin post_init.sql"
$PRIVILEGED_CLI $CONTAINER_CLI exec informix bash -l -c "export DB_LOCALE=en_US.utf8;export CLIENT_LOCALE=en_US.utf8;echo \"execute function task('create dbspace from storagepool', 'datadbs', '100 MB', '4');execute function task('create sbspace from storagepool', 'sbspace', '20 M', '0');create database dev in datadbs with log;\" > post_init.sql;dbaccess sysadmin post_init.sql"
break;
fi
n=$((n+1))
@ -978,7 +978,7 @@ informix_14_10() {
informix_12_10() {
$PRIVILEGED_CLI $CONTAINER_CLI rm -f informix || true
$PRIVILEGED_CLI $CONTAINER_CLI run --name informix --privileged -p 9088:9088 -e LICENSE=accept -d ibmcom/informix-developer-database:12.10.FC12W1DE
$PRIVILEGED_CLI $CONTAINER_CLI run --name informix --privileged -p 9088:9088 -e LICENSE=accept -e GL_USEGLU=1 -d ibmcom/informix-developer-database:12.10.FC12W1DE
echo "Starting Informix. This can take a few minutes"
# Give the container some time to start
OUTPUT=
@ -988,7 +988,7 @@ informix_12_10() {
OUTPUT=$($PRIVILEGED_CLI $CONTAINER_CLI logs informix 2>&1)
if [[ $OUTPUT == *"login Information"* ]]; then
sleep 15
$PRIVILEGED_CLI $CONTAINER_CLI exec informix bash -l -c "echo \"execute function task('create dbspace from storagepool', 'datadbs', '100 MB', '4');execute function task('create sbspace from storagepool', 'sbspace', '20 M', '0');create database dev in datadbs with log nlscase sensitive;\" > post_init.sql;dbaccess sysadmin post_init.sql"
$PRIVILEGED_CLI $CONTAINER_CLI exec informix bash -l -c "export DB_LOCALE=en_US.utf8;export CLIENT_LOCALE=en_US.utf8;echo \"execute function task('create dbspace from storagepool', 'datadbs', '100 MB', '4');execute function task('create sbspace from storagepool', 'sbspace', '20 M', '0');create database dev in datadbs with log;\" > post_init.sql;dbaccess sysadmin post_init.sql"
break;
fi
n=$((n+1))

View File

@ -295,7 +295,7 @@ ext {
'jdbc.driver': 'com.informix.jdbc.IfxDriver',
'jdbc.user' : 'informix',
'jdbc.pass' : 'in4mix',
'jdbc.url' : 'jdbc:informix-sqli://' + dbHost + ':9088/dev:INFORMIXSERVER=informix;user=informix;password=in4mix;DELIMIDENT=Y',
'jdbc.url' : 'jdbc:informix-sqli://' + dbHost + ':9088/dev:INFORMIXSERVER=informix;user=informix;password=in4mix;DELIMIDENT=Y;DB_LOCALE=en_US.utf8',
'jdbc.datasource' : 'com.informix.jdbc.IfxDriver',
// 'jdbc.datasource' : 'com.informix.jdbcx.IfxDataSource',
'connection.init_sql' : ''

View File

@ -6,6 +6,8 @@
*/
package org.hibernate.community.dialect;
import java.sql.Types;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.model.FunctionContributions;
import org.hibernate.boot.model.TypeContributions;
@ -65,6 +67,8 @@ import org.hibernate.sql.exec.spi.JdbcOperation;
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
import org.hibernate.tool.schema.internal.StandardForeignKeyExporter;
import org.hibernate.tool.schema.spi.Exporter;
import org.hibernate.type.descriptor.jdbc.ClobJdbcType;
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
import org.hibernate.type.descriptor.sql.DdlType;
import org.hibernate.type.descriptor.sql.internal.CapacityDependentDdlType;
import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry;
@ -728,4 +732,16 @@ public class InformixDialect extends Dialect {
public String getNoColumnsInsertString() {
return "values (0)";
}
@Override
public boolean supportsNationalizedMethods(){
return false;
}
@Override
public void contributeTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
super.contributeTypes( typeContributions, serviceRegistry );
final JdbcTypeRegistry jdbcTypeRegistry = typeContributions.getTypeConfiguration().getJdbcTypeRegistry();
jdbcTypeRegistry.addDescriptor( Types.NCLOB, ClobJdbcType.DEFAULT );
}
}

View File

@ -9,6 +9,7 @@ package org.hibernate.dialect;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.sql.Blob;
import java.sql.CallableStatement;
import java.sql.Clob;
@ -4370,6 +4371,18 @@ public abstract class Dialect implements ConversionContext, TypeContributor, Fun
return NationalizationSupport.EXPLICIT;
}
/**
* Checks whether the JDBC driver implements methods for handling nationalized character data types
* {@link ResultSet#getNString(int)} / {@link java.sql.PreparedStatement#setNString(int, String)},
* {@link ResultSet#getNClob(int)} /{@link java.sql.PreparedStatement#setNClob(int, NClob)},
* {@link ResultSet#getNCharacterStream(int)} / {@link java.sql.PreparedStatement#setNCharacterStream(int, Reader, long)}
*
* @return {@code true} if the driver implements these methods
*/
public boolean supportsNationalizedMethods(){
return true;
}
/**
* How does this dialect support aggregate types like {@link SqlTypes#STRUCT}.
*

View File

@ -120,15 +120,25 @@ public class JsonAsStringJdbcType extends JsonJdbcType implements AdjustableJdbc
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
throws SQLException {
final String json = ( (JsonAsStringJdbcType) getJdbcType() ).toString( value, getJavaType(), options );
if (options.getDialect().supportsNationalizedMethods()) {
st.setNString( index, json );
}
else {
st.setString( index, json );
}
}
@Override
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
throws SQLException {
final String json = ( (JsonAsStringJdbcType) getJdbcType() ).toString( value, getJavaType(), options );
if (options.getDialect().supportsNationalizedMethods()) {
st.setNString( name, json );
}
else {
st.setString( name, json );
}
}
};
}
else {
@ -142,20 +152,35 @@ public class JsonAsStringJdbcType extends JsonJdbcType implements AdjustableJdbc
return new BasicExtractor<>( javaType, this ) {
@Override
protected X doExtract(ResultSet rs, int paramIndex, WrapperOptions options) throws SQLException {
if (options.getDialect().supportsNationalizedMethods()) {
return fromString( rs.getNString( paramIndex ), getJavaType(), options );
}
else {
return fromString( rs.getString( paramIndex ), getJavaType(), options );
}
}
@Override
protected X doExtract(CallableStatement statement, int index, WrapperOptions options)
throws SQLException {
if (options.getDialect().supportsNationalizedMethods()) {
return fromString( statement.getNString( index ), getJavaType(), options );
}
else {
return fromString( statement.getString( index ), getJavaType(), options );
}
}
@Override
protected X doExtract(CallableStatement statement, String name, WrapperOptions options)
throws SQLException {
if (options.getDialect().supportsNationalizedMethods()) {
return fromString( statement.getNString( name ), getJavaType(), options );
}
else {
return fromString( statement.getString( name ), getJavaType(), options );
}
}
};
}

View File

@ -46,20 +46,35 @@ public abstract class NClobJdbcType implements JdbcType {
return new BasicExtractor<>( javaType, this ) {
@Override
protected X doExtract(ResultSet rs, int paramIndex, WrapperOptions options) throws SQLException {
if (options.getDialect().supportsNationalizedMethods()) {
return javaType.wrap( rs.getNClob( paramIndex ), options );
}
else {
return javaType.wrap( rs.getClob( paramIndex ), options );
}
}
@Override
protected X doExtract(CallableStatement statement, int index, WrapperOptions options)
throws SQLException {
if (options.getDialect().supportsNationalizedMethods()) {
return javaType.wrap( statement.getNClob( index ), options );
}
else {
return javaType.wrap( statement.getClob( index ), options );
}
}
@Override
protected X doExtract(CallableStatement statement, String name, WrapperOptions options)
throws SQLException {
if (options.getDialect().supportsNationalizedMethods()) {
return javaType.wrap( statement.getNClob( name ), options );
}
else {
return javaType.wrap( statement.getClob( name ), options );
}
}
};
}
@ -130,14 +145,24 @@ public abstract class NClobJdbcType implements JdbcType {
@Override
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
throws SQLException {
if (options.getDialect().supportsNationalizedMethods()) {
st.setNString( index, javaType.unwrap( value, String.class, options ) );
}
else {
st.setString( index, javaType.unwrap( value, String.class, options ) );
}
}
@Override
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
throws SQLException {
if (options.getDialect().supportsNationalizedMethods()) {
st.setNString( name, javaType.unwrap( value, String.class, options ) );
}
else {
st.setString( name, javaType.unwrap( value, String.class, options ) );
}
}
};
}
@Override
@ -145,20 +170,35 @@ public abstract class NClobJdbcType implements JdbcType {
return new BasicExtractor<>( javaType, this ) {
@Override
protected X doExtract(ResultSet rs, int paramIndex, WrapperOptions options) throws SQLException {
if (options.getDialect().supportsNationalizedMethods()) {
return javaType.wrap( rs.getNString( paramIndex ), options );
}
else {
return javaType.wrap( rs.getString( paramIndex ), options );
}
}
@Override
protected X doExtract(CallableStatement statement, int index, WrapperOptions options)
throws SQLException {
if (options.getDialect().supportsNationalizedMethods()) {
return javaType.wrap( statement.getNString( index ), options );
}
else {
return javaType.wrap( statement.getString( index ), options );
}
}
@Override
protected X doExtract(CallableStatement statement, String name, WrapperOptions options)
throws SQLException {
if (options.getDialect().supportsNationalizedMethods()) {
return javaType.wrap( statement.getNString( name ), options );
}
else {
return javaType.wrap( statement.getString( name ), options );
}
}
};
}
};
@ -180,14 +220,24 @@ public abstract class NClobJdbcType implements JdbcType {
@Override
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
throws SQLException {
if (options.getDialect().supportsNationalizedMethods()) {
st.setNClob( index, javaType.unwrap( value, NClob.class, options ) );
}
else {
st.setClob( index, javaType.unwrap( value, NClob.class, options ) );
}
}
@Override
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
throws SQLException {
if (options.getDialect().supportsNationalizedMethods()) {
st.setNClob( name, javaType.unwrap( value, NClob.class, options ) );
}
else {
st.setClob( name, javaType.unwrap( value, NClob.class, options ) );
}
}
};
}
};
@ -210,15 +260,25 @@ public abstract class NClobJdbcType implements JdbcType {
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
throws SQLException {
final CharacterStream characterStream = javaType.unwrap( value, CharacterStream.class, options );
if (options.getDialect().supportsNationalizedMethods()) {
st.setNCharacterStream( index, characterStream.asReader(), characterStream.getLength() );
}
else {
st.setCharacterStream( index, characterStream.asReader(), characterStream.getLength() );
}
}
@Override
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
throws SQLException {
final CharacterStream characterStream = javaType.unwrap( value, CharacterStream.class, options );
if (options.getDialect().supportsNationalizedMethods()) {
st.setNCharacterStream( name, characterStream.asReader(), characterStream.getLength() );
}
else {
st.setCharacterStream( name, characterStream.asReader(), characterStream.getLength() );
}
}
};
}
};
@ -240,14 +300,24 @@ public abstract class NClobJdbcType implements JdbcType {
@Override
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
throws SQLException {
if (options.getDialect().supportsNationalizedMethods()) {
st.setNString( index, javaType.unwrap( value, String.class, options ) );
}
else {
st.setString( index, javaType.unwrap( value, String.class, options ) );
}
}
@Override
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
throws SQLException {
if (options.getDialect().supportsNationalizedMethods()) {
st.setNString( name, javaType.unwrap( value, String.class, options ) );
}
else {
st.setString( name, javaType.unwrap( value, String.class, options ) );
}
}
};
}
@ -256,20 +326,35 @@ public abstract class NClobJdbcType implements JdbcType {
return new BasicExtractor<>( javaType, this ) {
@Override
protected X doExtract(ResultSet rs, int paramIndex, WrapperOptions options) throws SQLException {
if (options.getDialect().supportsNationalizedMethods()) {
return javaType.wrap( rs.getNString( paramIndex ), options );
}
else {
return javaType.wrap( rs.getString( paramIndex ), options );
}
}
@Override
protected X doExtract(CallableStatement statement, int index, WrapperOptions options)
throws SQLException {
if (options.getDialect().supportsNationalizedMethods()) {
return javaType.wrap( statement.getNString( index ), options );
}
else {
return javaType.wrap( statement.getString( index ), options );
}
}
@Override
protected X doExtract(CallableStatement statement, String name, WrapperOptions options)
throws SQLException {
if (options.getDialect().supportsNationalizedMethods()) {
return javaType.wrap( statement.getNString( name ), options );
}
else {
return javaType.wrap( statement.getString( name ), options );
}
}
};
}
};

View File

@ -106,14 +106,24 @@ public class NVarcharJdbcType implements AdjustableJdbcType {
return new BasicBinder<>( javaType, this ) {
@Override
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options) throws SQLException {
if (options.getDialect().supportsNationalizedMethods()) {
st.setNString( index, javaType.unwrap( value, String.class, options ) );
}
else {
st.setString( index, javaType.unwrap( value, String.class, options ) );
}
}
@Override
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
throws SQLException {
if (options.getDialect().supportsNationalizedMethods()) {
st.setNString( name, javaType.unwrap( value, String.class, options ) );
}
else {
st.setString( name, javaType.unwrap( value, String.class, options ) );
}
}
};
}
@ -122,18 +132,33 @@ public class NVarcharJdbcType implements AdjustableJdbcType {
return new BasicExtractor<>( javaType, this ) {
@Override
protected X doExtract(ResultSet rs, int paramIndex, WrapperOptions options) throws SQLException {
if (options.getDialect().supportsNationalizedMethods()) {
return javaType.wrap( rs.getNString( paramIndex ), options );
}
else {
return javaType.wrap( rs.getString( paramIndex ), options );
}
}
@Override
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
if (options.getDialect().supportsNationalizedMethods()) {
return javaType.wrap( statement.getNString( index ), options );
}
else {
return javaType.wrap( statement.getString( index ), options );
}
}
@Override
protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
if (options.getDialect().supportsNationalizedMethods()) {
return javaType.wrap( statement.getNString( name ), options );
}
else {
return javaType.wrap( statement.getString( name ), options );
}
}
};
}
}

View File

@ -130,8 +130,13 @@ public class XmlAsStringJdbcType extends XmlJdbcType implements AdjustableJdbcTy
getJavaType(),
options
);
if (options.getDialect().supportsNationalizedMethods()) {
st.setNString( index, xml );
}
else {
st.setString( index, xml );
}
}
@Override
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
@ -141,8 +146,13 @@ public class XmlAsStringJdbcType extends XmlJdbcType implements AdjustableJdbcTy
getJavaType(),
options
);
if (options.getDialect().supportsNationalizedMethods()) {
st.setNString( name, xml );
}
else {
st.setString( name, xml );
}
}
};
}
else {
@ -179,20 +189,35 @@ public class XmlAsStringJdbcType extends XmlJdbcType implements AdjustableJdbcTy
@Override
protected X doExtract(ResultSet rs, int paramIndex, WrapperOptions options) throws SQLException {
if (options.getDialect().supportsNationalizedMethods()) {
return getObject( rs.getNString( paramIndex ), options );
}
else {
return getObject( rs.getString( paramIndex ), options );
}
}
@Override
protected X doExtract(CallableStatement statement, int index, WrapperOptions options)
throws SQLException {
if (options.getDialect().supportsNationalizedMethods()) {
return getObject( statement.getNString( index ), options );
}
else {
return getObject( statement.getString( index ), options );
}
}
@Override
protected X doExtract(CallableStatement statement, String name, WrapperOptions options)
throws SQLException {
if (options.getDialect().supportsNationalizedMethods()) {
return getObject( statement.getNString( name ), options );
}
else {
return getObject( statement.getString( name ), options );
}
}
private X getObject(String xml, WrapperOptions options) throws SQLException {
if ( xml == null ) {

View File

@ -15,6 +15,8 @@ import java.sql.SQLException;
import java.sql.Types;
import java.util.TimeZone;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.H2Dialect;
import org.hibernate.engine.jdbc.LobCreator;
import org.hibernate.engine.jdbc.NonContextualLobCreator;
import org.hibernate.engine.spi.SessionFactoryImplementor;
@ -85,6 +87,7 @@ public class MaterializedNClobBindTest {
private class MockWrapperOptions implements WrapperOptions {
private final boolean useStreamForLobBinding;
private final Dialect dialect = new H2Dialect();
public MockWrapperOptions(boolean useStreamForLobBinding) {
this.useStreamForLobBinding = useStreamForLobBinding;
@ -119,6 +122,11 @@ public class MaterializedNClobBindTest {
public TimeZone getJdbcTimeZone() {
return null;
}
@Override
public Dialect getDialect() {
return dialect;
}
}
private PreparedStatement createPreparedStatementProxy(WrapperOptions options) {