Fix SybaseASEDialect column lenght resolution

This commit is contained in:
Andrea Boriero 2024-04-12 16:40:04 +02:00 committed by Andrea Boriero
parent 7cc7bac5d4
commit af6c8eefea
8 changed files with 85 additions and 47 deletions

View File

@ -508,6 +508,23 @@ public class MySQLLegacyDialect extends Dialect {
);
}
@Override
public int resolveSqlTypeLength(
String columnTypeName,
int jdbcTypeCode,
int precision,
int scale,
int displaySize) {
// It seems MariaDB/MySQL return the precision in bytes depending on the charset,
// so to detect whether we have a single character here, we check the display size
if ( jdbcTypeCode == Types.CHAR && precision <= 4 ) {
return displaySize;
}
else {
return precision;
}
}
@Override
public int getPreferredSqlTypeCodeForBoolean() {
return Types.BIT;

View File

@ -10,14 +10,12 @@ import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Map;
import org.hibernate.LockMode;
import org.hibernate.LockOptions;
import org.hibernate.boot.model.TypeContributions;
import org.hibernate.dialect.DatabaseVersion;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.RowLockStrategy;
import org.hibernate.dialect.SybaseDriverKind;
import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.dialect.pagination.TopLimitHandler;
@ -33,7 +31,6 @@ import org.hibernate.internal.util.JdbcExceptionHelper;
import org.hibernate.query.sqm.IntervalType;
import org.hibernate.query.sqm.TemporalUnit;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.sql.ForUpdateFragment;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
@ -237,22 +234,6 @@ public class SybaseASELegacyDialect extends SybaseLegacyDialect {
}
}
@Override
public int resolveSqlTypeLength(
String columnTypeName,
int jdbcTypeCode,
int precision,
int scale,
int displaySize) {
// Sybase ASE reports the "actual" precision in the display size
switch ( jdbcTypeCode ) {
case Types.REAL:
case Types.DOUBLE:
return displaySize;
}
return super.resolveSqlTypeLength( columnTypeName, jdbcTypeCode, precision, scale, displaySize );
}
@Override
public String currentDate() {
return "current_date()";

View File

@ -158,6 +158,23 @@ public class SybaseLegacyDialect extends AbstractTransactSQLDialect {
);
}
@Override
public int resolveSqlTypeLength(
String columnTypeName,
int jdbcTypeCode,
int precision,
int scale,
int displaySize) {
// Sybase jconnect driver reports the "actual" precision in the display size
switch ( jdbcTypeCode ) {
case Types.VARCHAR:
case Types.REAL:
case Types.DOUBLE:
return displaySize;
}
return super.resolveSqlTypeLength( columnTypeName, jdbcTypeCode, precision, scale, displaySize );
}
@Override
public SqmTranslatorFactory getSqmTranslatorFactory() {
return new StandardSqmTranslatorFactory() {

View File

@ -764,14 +764,7 @@ public abstract class Dialect implements ConversionContext, TypeContributor, Fun
int precision,
int scale,
int displaySize) {
// It seems MariaDB/MySQL return the precision in bytes depending on the charset,
// so to detect whether we have a single character here, we check the display size
if ( jdbcTypeCode == Types.CHAR && precision <= 4 ) {
return displaySize;
}
else {
return precision;
}
return precision;
}
/**

View File

@ -544,6 +544,23 @@ public class MySQLDialect extends Dialect {
);
}
@Override
public int resolveSqlTypeLength(
String columnTypeName,
int jdbcTypeCode,
int precision,
int scale,
int displaySize) {
// It seems MariaDB/MySQL return the precision in bytes depending on the charset,
// so to detect whether we have a single character here, we check the display size
if ( jdbcTypeCode == Types.CHAR && precision <= 4 ) {
return displaySize;
}
else {
return precision;
}
}
@Override
public int getPreferredSqlTypeCodeForBoolean() {
return Types.BIT;

View File

@ -251,22 +251,6 @@ public class SybaseASEDialect extends SybaseDialect {
}
}
@Override
public int resolveSqlTypeLength(
String columnTypeName,
int jdbcTypeCode,
int precision,
int scale,
int displaySize) {
// Sybase ASE reports the "actual" precision in the display size
switch ( jdbcTypeCode ) {
case Types.REAL:
case Types.DOUBLE:
return displaySize;
}
return super.resolveSqlTypeLength( columnTypeName, jdbcTypeCode, precision, scale, displaySize );
}
@Override
public String currentDate() {
return "current_date()";

View File

@ -140,6 +140,23 @@ public class SybaseDialect extends AbstractTransactSQLDialect {
);
}
@Override
public int resolveSqlTypeLength(
String columnTypeName,
int jdbcTypeCode,
int precision,
int scale,
int displaySize) {
// Sybase jconnect driver reports the "actual" precision in the display size
switch ( jdbcTypeCode ) {
case Types.VARCHAR:
case Types.REAL:
case Types.DOUBLE:
return displaySize;
}
return super.resolveSqlTypeLength( columnTypeName, jdbcTypeCode, precision, scale, displaySize );
}
@Override
public SqmTranslatorFactory getSqmTranslatorFactory() {
return new StandardSqmTranslatorFactory() {

View File

@ -13,6 +13,7 @@ import java.util.StringTokenizer;
import org.hibernate.boot.model.naming.DatabaseIdentifier;
import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.dialect.Dialect;
import org.hibernate.tool.schema.extract.spi.ExtractionContext;
import org.hibernate.tool.schema.extract.spi.TableInformation;
@ -134,6 +135,8 @@ public class InformationExtractorJdbcDatabaseMetaDataImpl extends AbstractInform
}
protected void addColumns(TableInformation tableInformation) {
final Dialect dialect = getExtractionContext().getJdbcEnvironment().getDialect();
final ExtractionContext extractionContext = getExtractionContext();
// We use this dummy query to retrieve the table information through the ResultSetMetaData
// This is significantly better than to use the DatabaseMetaData especially on Oracle with synonyms enabled
@ -153,13 +156,22 @@ public class InformationExtractorJdbcDatabaseMetaDataImpl extends AbstractInform
for ( int i = 1; i <= columnCount; i++ ) {
final String columnName = metaData.getColumnName( i );
final int columnType = metaData.getColumnType( i );
final String typeName = new StringTokenizer( metaData.getColumnTypeName( i ), "()" ).nextToken();
final int scale = metaData.getScale( i );
final ColumnInformationImpl columnInformation = new ColumnInformationImpl(
tableInformation,
DatabaseIdentifier.toIdentifier( columnName ),
metaData.getColumnType( i ),
new StringTokenizer( metaData.getColumnTypeName( i ), "()" ).nextToken(),
metaData.getPrecision( i ),
metaData.getScale( i ),
columnType,
typeName,
dialect.resolveSqlTypeLength(
typeName,
columnType,
metaData.getPrecision( i ),
scale,
metaData.getColumnDisplaySize( i )
),
scale,
interpretNullable( metaData.isNullable( i ) )
);
tableInformation.addColumn( columnInformation );