HHH-17276 Be more forgiving when determining lobness

This commit is contained in:
Christian Beikov 2023-10-09 12:49:22 +02:00
parent df5fc98abd
commit e424eea9e9
14 changed files with 124 additions and 47 deletions

View File

@ -242,7 +242,7 @@ public class MariaDBLegacySqlAstTranslator<T extends JdbcOperation> extends Abst
@Override @Override
public void visitCastTarget(CastTarget castTarget) { public void visitCastTarget(CastTarget castTarget) {
String sqlType = MySQLSqlAstTranslator.getSqlType( castTarget, dialect ); String sqlType = MySQLSqlAstTranslator.getSqlType( castTarget, getSessionFactory() );
if ( sqlType != null ) { if ( sqlType != null ) {
appendSql( sqlType ); appendSql( sqlType );
} }

View File

@ -250,7 +250,7 @@ public class MySQLLegacySqlAstTranslator<T extends JdbcOperation> extends Abstra
@Override @Override
public void visitCastTarget(CastTarget castTarget) { public void visitCastTarget(CastTarget castTarget) {
String sqlType = MySQLSqlAstTranslator.getSqlType( castTarget, getDialect() ); String sqlType = MySQLSqlAstTranslator.getSqlType( castTarget, getSessionFactory() );
if ( sqlType != null ) { if ( sqlType != null ) {
appendSql( sqlType ); appendSql( sqlType );
} }

View File

@ -236,7 +236,7 @@ public class MariaDBSqlAstTranslator<T extends JdbcOperation> extends AbstractSq
@Override @Override
public void visitCastTarget(CastTarget castTarget) { public void visitCastTarget(CastTarget castTarget) {
String sqlType = MySQLSqlAstTranslator.getSqlType( castTarget, dialect ); String sqlType = MySQLSqlAstTranslator.getSqlType( castTarget, getSessionFactory() );
if ( sqlType != null ) { if ( sqlType != null ) {
appendSql( sqlType ); appendSql( sqlType );
} }

View File

@ -37,9 +37,20 @@ public class MySQLSqlAstTranslator<T extends JdbcOperation> extends AbstractSqlA
super( sessionFactory, statement ); super( sessionFactory, statement );
} }
/**
* @deprecated Use {@link #getSqlType(CastTarget, SessionFactoryImplementor)} instead
*/
@Deprecated(forRemoval = true)
public static String getSqlType(CastTarget castTarget, Dialect dialect) { public static String getSqlType(CastTarget castTarget, Dialect dialect) {
final String sqlType = castTarget.getSqlType(); return getSqlType( castTarget, castTarget.getSqlType(), dialect );
}
public static String getSqlType(CastTarget castTarget, SessionFactoryImplementor factory) {
final String sqlType = getSqlTypeName( castTarget, factory );
return getSqlType( castTarget, sqlType, factory.getJdbcServices().getDialect() );
}
private static String getSqlType(CastTarget castTarget, String sqlType, Dialect dialect) {
if ( sqlType != null ) { if ( sqlType != null ) {
int parenthesesIndex = sqlType.indexOf( '(' ); int parenthesesIndex = sqlType.indexOf( '(' );
final String baseName = parenthesesIndex == -1 ? sqlType : sqlType.substring( 0, parenthesesIndex ); final String baseName = parenthesesIndex == -1 ? sqlType : sqlType.substring( 0, parenthesesIndex );
@ -63,10 +74,14 @@ public class MySQLSqlAstTranslator<T extends JdbcOperation> extends AbstractSqlA
case "varchar": case "varchar":
case "nchar": case "nchar":
case "nvarchar": case "nvarchar":
return "char"; return castTarget.getLength() == null
? "char"
: ( "char(" + castTarget.getLength() + ")" );
case "binary": case "binary":
case "varbinary": case "varbinary":
return "binary"; return castTarget.getLength() == null
? "binary"
: ( "binary(" + castTarget.getLength() + ")" );
} }
} }
return sqlType; return sqlType;
@ -286,7 +301,7 @@ public class MySQLSqlAstTranslator<T extends JdbcOperation> extends AbstractSqlA
@Override @Override
public void visitCastTarget(CastTarget castTarget) { public void visitCastTarget(CastTarget castTarget) {
String sqlType = getSqlType( castTarget, getDialect() ); String sqlType = getSqlType( castTarget, getSessionFactory() );
if ( sqlType != null ) { if ( sqlType != null ) {
appendSql( sqlType ); appendSql( sqlType );
} }

View File

@ -193,7 +193,7 @@ public class TiDBSqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAs
@Override @Override
public void visitCastTarget(CastTarget castTarget) { public void visitCastTarget(CastTarget castTarget) {
String sqlType = MySQLSqlAstTranslator.getSqlType( castTarget, dialect ); String sqlType = MySQLSqlAstTranslator.getSqlType( castTarget, getSessionFactory() );
if ( sqlType != null ) { if ( sqlType != null ) {
appendSql( sqlType ); appendSql( sqlType );
} }

View File

@ -20,6 +20,7 @@ import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.tool.schema.extract.spi.ColumnTypeInformation; import org.hibernate.tool.schema.extract.spi.ColumnTypeInformation;
import org.hibernate.type.descriptor.jdbc.AggregateJdbcType; import org.hibernate.type.descriptor.jdbc.AggregateJdbcType;
import org.hibernate.type.descriptor.sql.DdlType;
import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.type.spi.TypeConfiguration;
import static org.hibernate.type.SqlTypes.BIGINT; import static org.hibernate.type.SqlTypes.BIGINT;
@ -231,7 +232,7 @@ public class OracleAggregateSupport extends AggregateSupportImpl {
final int aggregateSqlTypeCode = aggregateColumn.getJdbcMapping().getJdbcType().getDefaultSqlTypeCode(); final int aggregateSqlTypeCode = aggregateColumn.getJdbcMapping().getJdbcType().getDefaultSqlTypeCode();
switch ( aggregateSqlTypeCode ) { switch ( aggregateSqlTypeCode ) {
case JSON: case JSON:
return jsonAggregateColumnWriter( aggregateColumn, columnsToUpdate ); return jsonAggregateColumnWriter( aggregateColumn, columnsToUpdate, typeConfiguration );
} }
throw new IllegalArgumentException( "Unsupported aggregate SQL type: " + aggregateSqlTypeCode ); throw new IllegalArgumentException( "Unsupported aggregate SQL type: " + aggregateSqlTypeCode );
} }
@ -269,8 +270,9 @@ public class OracleAggregateSupport extends AggregateSupportImpl {
private WriteExpressionRenderer jsonAggregateColumnWriter( private WriteExpressionRenderer jsonAggregateColumnWriter(
SelectableMapping aggregateColumn, SelectableMapping aggregateColumn,
SelectableMapping[] columns) { SelectableMapping[] columns,
return new RootJsonWriteExpression( aggregateColumn, columns, this ); TypeConfiguration typeConfiguration) {
return new RootJsonWriteExpression( aggregateColumn, columns, this, typeConfiguration );
} }
interface JsonWriteExpression { interface JsonWriteExpression {
@ -293,7 +295,10 @@ public class OracleAggregateSupport extends AggregateSupportImpl {
this.ddlTypeName = aggregateSupport.determineJsonTypeName( selectableMapping ); this.ddlTypeName = aggregateSupport.determineJsonTypeName( selectableMapping );
} }
protected void initializeSubExpressions(SelectableMapping[] columns, OracleAggregateSupport aggregateSupport) { protected void initializeSubExpressions(
SelectableMapping[] columns,
OracleAggregateSupport aggregateSupport,
TypeConfiguration typeConfiguration) {
for ( SelectableMapping column : columns ) { for ( SelectableMapping column : columns ) {
final SelectablePath selectablePath = column.getSelectablePath(); final SelectablePath selectablePath = column.getSelectablePath();
final SelectablePath[] parts = selectablePath.getParts(); final SelectablePath[] parts = selectablePath.getParts();
@ -318,13 +323,33 @@ public class OracleAggregateSupport extends AggregateSupportImpl {
aggregateSupport.jsonCustomWriteExpression( aggregateSupport.jsonCustomWriteExpression(
customWriteExpression, customWriteExpression,
sqlTypeCode, sqlTypeCode,
column.getColumnDefinition() determineTypeName( column, typeConfiguration )
) )
) )
); );
} }
} }
private static String determineTypeName(SelectableMapping column, TypeConfiguration typeConfiguration) {
final String typeName;
if ( column.getColumnDefinition() == null ) {
final DdlType ddlType = typeConfiguration.getDdlTypeRegistry().getDescriptor(
column.getJdbcMapping().getJdbcType().getDefaultSqlTypeCode()
);
return ddlType.getCastTypeName(
column.getJdbcMapping().getJdbcType(),
column.getJdbcMapping().getJavaTypeDescriptor(),
column.getLength(),
column.getPrecision(),
column.getScale()
);
}
else{
typeName = column.getColumnDefinition();
}
return typeName;
}
@Override @Override
public void append( public void append(
SqlAppender sb, SqlAppender sb,
@ -363,11 +388,12 @@ public class OracleAggregateSupport extends AggregateSupportImpl {
RootJsonWriteExpression( RootJsonWriteExpression(
SelectableMapping aggregateColumn, SelectableMapping aggregateColumn,
SelectableMapping[] columns, SelectableMapping[] columns,
OracleAggregateSupport aggregateSupport) { OracleAggregateSupport aggregateSupport,
TypeConfiguration typeConfiguration) {
super( aggregateColumn, aggregateSupport ); super( aggregateColumn, aggregateSupport );
this.nullable = aggregateColumn.isNullable(); this.nullable = aggregateColumn.isNullable();
this.path = aggregateColumn.getSelectionExpression(); this.path = aggregateColumn.getSelectionExpression();
initializeSubExpressions( columns, aggregateSupport ); initializeSubExpressions( columns, aggregateSupport, typeConfiguration );
} }
@Override @Override

View File

@ -29,6 +29,7 @@ import org.hibernate.type.ComponentType;
import org.hibernate.type.EntityType; import org.hibernate.type.EntityType;
import org.hibernate.type.Type; import org.hibernate.type.Type;
import org.hibernate.type.descriptor.JdbcTypeNameMapper; import org.hibernate.type.descriptor.JdbcTypeNameMapper;
import org.hibernate.type.descriptor.jdbc.JdbcType;
import org.hibernate.type.descriptor.sql.DdlType; import org.hibernate.type.descriptor.sql.DdlType;
import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry; import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry;
import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.type.spi.TypeConfiguration;
@ -58,7 +59,7 @@ public class Column implements Selectable, Serializable, Cloneable, ColumnTypeIn
private boolean unique; private boolean unique;
private String sqlTypeName; private String sqlTypeName;
private Integer sqlTypeCode; private Integer sqlTypeCode;
private boolean sqlTypeLob; private Boolean sqlTypeLob;
private boolean quoted; private boolean quoted;
private boolean explicit; private boolean explicit;
int uniqueInteger; int uniqueInteger;
@ -509,6 +510,40 @@ public class Column implements Selectable, Serializable, Cloneable, ColumnTypeIn
} }
public boolean isSqlTypeLob() { public boolean isSqlTypeLob() {
return sqlTypeLob != null && sqlTypeLob;
}
public boolean isSqlTypeLob(Metadata mapping) {
final Database database = mapping.getDatabase();
final DdlTypeRegistry ddlTypeRegistry = database.getTypeConfiguration().getDdlTypeRegistry();
final Dialect dialect = database.getDialect();
if ( sqlTypeLob == null ) {
try {
final int typeCode = getSqlTypeCode( mapping );
final DdlType descriptor = ddlTypeRegistry.getDescriptor( typeCode );
if ( descriptor == null ) {
sqlTypeLob = JdbcType.isLob( typeCode );
}
else {
final Size size = getColumnSize( dialect, mapping );
sqlTypeLob = descriptor.isLob( size );
}
}
catch ( MappingException cause ) {
throw cause;
}
catch ( Exception cause ) {
throw new MappingException(
String.format(
Locale.ROOT,
"Unable to determine SQL type name for column '%s' of table '%s'",
getName(),
getValue().getTable().getName()
),
cause
);
}
}
return sqlTypeLob; return sqlTypeLob;
} }

View File

@ -287,12 +287,12 @@ public abstract class AbstractEmbeddableMapping implements EmbeddableMappingType
final boolean nullable; final boolean nullable;
if ( selectable instanceof Column ) { if ( selectable instanceof Column ) {
final Column column = (Column) selectable; final Column column = (Column) selectable;
columnDefinition = column.getSqlType( creationProcess.getCreationContext().getMetadata() ); columnDefinition = column.getSqlType();
length = column.getLength(); length = column.getLength();
precision = column.getPrecision(); precision = column.getPrecision();
scale = column.getScale(); scale = column.getScale();
nullable = column.isNullable(); nullable = column.isNullable();
isLob = column.isSqlTypeLob(); isLob = column.isSqlTypeLob( creationProcess.getCreationContext().getMetadata() );
selectablePath = basicValue.createSelectablePath( column.getQuotedName( dialect ) ); selectablePath = basicValue.createSelectablePath( column.getQuotedName( dialect ) );
} }
else { else {

View File

@ -86,7 +86,7 @@ public class DiscriminatedAssociationMapping implements MappingType, FetchOption
declaringModelPart, declaringModelPart,
tableName, tableName,
metaColumn.getText( dialect ), metaColumn.getText( dialect ),
metaColumn.getSqlType( creationProcess.getCreationContext().getMetadata() ), metaColumn.getSqlType(),
metaColumn.getLength(), metaColumn.getLength(),
metaColumn.getPrecision(), metaColumn.getPrecision(),
metaColumn.getScale(), metaColumn.getScale(),
@ -105,7 +105,7 @@ public class DiscriminatedAssociationMapping implements MappingType, FetchOption
declaringModelPart, declaringModelPart,
tableName, tableName,
keyColumn.getText( dialect ), keyColumn.getText( dialect ),
keyColumn.getSqlType( creationProcess.getCreationContext().getMetadata() ), keyColumn.getSqlType(),
keyColumn.getLength(), keyColumn.getLength(),
keyColumn.getPrecision(), keyColumn.getPrecision(),
keyColumn.getScale(), keyColumn.getScale(),

View File

@ -383,11 +383,11 @@ public class EmbeddableMappingTypeImpl extends AbstractEmbeddableMapping impleme
final boolean nullable; final boolean nullable;
if ( selectable instanceof Column ) { if ( selectable instanceof Column ) {
final Column column = (Column) selectable; final Column column = (Column) selectable;
columnDefinition = column.getSqlType( creationProcess.getCreationContext().getMetadata() ); columnDefinition = column.getSqlType();
length = column.getLength(); length = column.getLength();
precision = column.getPrecision(); precision = column.getPrecision();
scale = column.getScale(); scale = column.getScale();
isLob = column.isSqlTypeLob(); isLob = column.isSqlTypeLob( creationProcess.getCreationContext().getMetadata() );
nullable = bootPropertyDescriptor.isOptional() && column.isNullable() ; nullable = bootPropertyDescriptor.isOptional() && column.isNullable() ;
selectablePath = basicValue.createSelectablePath( column.getQuotedName( dialect ) ); selectablePath = basicValue.createSelectablePath( column.getQuotedName( dialect ) );
} }

View File

@ -184,13 +184,13 @@ public class SelectableMappingImpl extends SqlTypedMappingImpl implements Select
else { else {
Column column = (Column) selectable; Column column = (Column) selectable;
columnExpression = selectable.getText( dialect ); columnExpression = selectable.getText( dialect );
columnDefinition = column.getSqlType( creationContext.getMetadata() ); columnDefinition = column.getSqlType();
length = column.getLength(); length = column.getLength();
precision = column.getPrecision(); precision = column.getPrecision();
scale = column.getScale(); scale = column.getScale();
isNullable = forceNotNullable ? false : column.isNullable(); isNullable = forceNotNullable ? false : column.isNullable();
isLob = column.isSqlTypeLob(); isLob = column.isSqlTypeLob( creationContext.getMetadata() );
selectableName = column.getQuotedName( dialect ); selectableName = column.getQuotedName( dialect );
} }
return new SelectableMappingImpl( return new SelectableMappingImpl(

View File

@ -5202,7 +5202,7 @@ public abstract class AbstractEntityPersister
scale = null; scale = null;
} }
else { else {
columnDefinition = column.getSqlType( modelCreationProcess.getCreationContext().getMetadata() ); columnDefinition = column.getSqlType();
length = column.getLength(); length = column.getLength();
precision = column.getPrecision(); precision = column.getPrecision();
scale = column.getScale(); scale = column.getScale();
@ -5379,7 +5379,7 @@ public abstract class AbstractEntityPersister
} }
else { else {
Column column = bootEntityDescriptor.getIdentifier().getColumns().get( 0 ); Column column = bootEntityDescriptor.getIdentifier().getColumns().get( 0 );
columnDefinition = column.getSqlType( creationProcess.getCreationContext().getMetadata() ); columnDefinition = column.getSqlType();
length = column.getLength(); length = column.getLength();
precision = column.getPrecision(); precision = column.getPrecision();
scale = column.getScale(); scale = column.getScale();
@ -5438,7 +5438,7 @@ public abstract class AbstractEntityPersister
bootModelRootEntityDescriptor.getVersion().getName(), bootModelRootEntityDescriptor.getVersion().getName(),
entityPersister.getTableName(), entityPersister.getTableName(),
column.getText( dialect ), column.getText( dialect ),
column.getSqlType( creationProcess.getCreationContext().getMetadata() ), column.getSqlType(),
column.getLength(), column.getLength(),
column.getPrecision(), column.getPrecision(),
column.getScale(), column.getScale(),
@ -5483,11 +5483,11 @@ public abstract class AbstractEntityPersister
false, false,
null, null,
"?", "?",
column.getSqlType( creationProcess.getCreationContext().getMetadata() ), column.getSqlType(),
column.getLength(), column.getLength(),
column.getPrecision(), column.getPrecision(),
column.getScale(), column.getScale(),
column.isSqlTypeLob(), column.isSqlTypeLob( creationProcess.getCreationContext().getMetadata() ),
column.isNullable(), column.isNullable(),
value.isColumnInsertable( 0 ), value.isColumnInsertable( 0 ),
value.isColumnUpdateable( 0 ), value.isColumnUpdateable( 0 ),
@ -5515,11 +5515,11 @@ public abstract class AbstractEntityPersister
customReadExpr = null; customReadExpr = null;
customWriteExpr = "?"; customWriteExpr = "?";
Column column = value.getColumns().get( 0 ); Column column = value.getColumns().get( 0 );
columnDefinition = column.getSqlType( creationProcess.getCreationContext().getMetadata() ); columnDefinition = column.getSqlType();
length = column.getLength(); length = column.getLength();
precision = column.getPrecision(); precision = column.getPrecision();
scale = column.getScale(); scale = column.getScale();
isLob = column.isSqlTypeLob(); isLob = column.isSqlTypeLob( creationProcess.getCreationContext().getMetadata() );
nullable = column.isNullable(); nullable = column.isNullable();
} }
else { else {
@ -5542,12 +5542,12 @@ public abstract class AbstractEntityPersister
); );
customWriteExpr = selectable.getWriteExpr( (JdbcMapping) attrType, creationContext.getDialect() ); customWriteExpr = selectable.getWriteExpr( (JdbcMapping) attrType, creationContext.getDialect() );
Column column = value.getColumns().get( 0 ); Column column = value.getColumns().get( 0 );
columnDefinition = column.getSqlType( creationContext.getMetadata() ); columnDefinition = column.getSqlType();
length = column.getLength(); length = column.getLength();
precision = column.getPrecision(); precision = column.getPrecision();
scale = column.getScale(); scale = column.getScale();
nullable = column.isNullable(); nullable = column.isNullable();
isLob = column.isSqlTypeLob(); isLob = column.isSqlTypeLob( creationContext.getMetadata() );
} }
else { else {
final String[] attrColumnFormulaTemplate = propertyColumnFormulaTemplates[ propertyIndex ]; final String[] attrColumnFormulaTemplate = propertyColumnFormulaTemplates[ propertyIndex ];

View File

@ -1187,7 +1187,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
} }
else { else {
final Column column = bootEntityDescriptor.getIdentifier().getColumns().get( 0 ); final Column column = bootEntityDescriptor.getIdentifier().getColumns().get( 0 );
columnDefinition = column.getSqlType( creationProcess.getCreationContext().getMetadata() ); columnDefinition = column.getSqlType();
length = column.getLength(); length = column.getLength();
precision = column.getPrecision(); precision = column.getPrecision();
scale = column.getScale(); scale = column.getScale();

View File

@ -6229,8 +6229,12 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
@Override @Override
public void visitCastTarget(CastTarget castTarget) { public void visitCastTarget(CastTarget castTarget) {
appendSql( getSqlTypeName( castTarget, sessionFactory ) );
}
public static String getSqlTypeName(CastTarget castTarget, SessionFactoryImplementor factory) {
if ( castTarget.getSqlType() != null ) { if ( castTarget.getSqlType() != null ) {
appendSql( castTarget.getSqlType() ); return castTarget.getSqlType();
} }
else { else {
final SqlExpressible expressionType = (SqlExpressible) castTarget.getExpressionType(); final SqlExpressible expressionType = (SqlExpressible) castTarget.getExpressionType();
@ -6238,7 +6242,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
final BasicPluralType<?, ?> containerType = (BasicPluralType<?, ?>) expressionType; final BasicPluralType<?, ?> containerType = (BasicPluralType<?, ?>) expressionType;
final BasicPluralJavaType<?> javaTypeDescriptor = (BasicPluralJavaType<?>) containerType.getJavaTypeDescriptor(); final BasicPluralJavaType<?> javaTypeDescriptor = (BasicPluralJavaType<?>) containerType.getJavaTypeDescriptor();
final BasicType<?> elementType = containerType.getElementType(); final BasicType<?> elementType = containerType.getElementType();
final String elementTypeName = sessionFactory.getTypeConfiguration().getDdlTypeRegistry() final String elementTypeName = factory.getTypeConfiguration().getDdlTypeRegistry()
.getDescriptor( elementType.getJdbcType().getDdlTypeCode() ) .getDescriptor( elementType.getJdbcType().getDdlTypeCode() )
.getCastTypeName( .getCastTypeName(
elementType, elementType,
@ -6246,17 +6250,16 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
castTarget.getPrecision(), castTarget.getPrecision(),
castTarget.getScale() castTarget.getScale()
); );
final String arrayTypeName = dialect.getArrayTypeName( final String arrayTypeName = factory.getJdbcServices().getDialect().getArrayTypeName(
javaTypeDescriptor.getElementJavaType().getJavaTypeClass().getSimpleName(), javaTypeDescriptor.getElementJavaType().getJavaTypeClass().getSimpleName(),
elementTypeName, elementTypeName,
null null
); );
if ( arrayTypeName != null ) { if ( arrayTypeName != null ) {
appendSql( arrayTypeName ); return arrayTypeName;
return;
} }
} }
final DdlTypeRegistry ddlTypeRegistry = getSessionFactory().getTypeConfiguration().getDdlTypeRegistry(); final DdlTypeRegistry ddlTypeRegistry = factory.getTypeConfiguration().getDdlTypeRegistry();
DdlType ddlType = ddlTypeRegistry DdlType ddlType = ddlTypeRegistry
.getDescriptor( expressionType.getJdbcMapping().getJdbcType().getDdlTypeCode() ); .getDescriptor( expressionType.getJdbcMapping().getJdbcType().getDdlTypeCode() );
if ( ddlType == null ) { if ( ddlType == null ) {
@ -6265,13 +6268,11 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
ddlType = ddlTypeRegistry.getDescriptor( SqlTypes.INTEGER ); ddlType = ddlTypeRegistry.getDescriptor( SqlTypes.INTEGER );
} }
appendSql( return ddlType.getCastTypeName(
ddlType.getCastTypeName(
expressionType, expressionType,
castTarget.getLength(), castTarget.getLength(),
castTarget.getPrecision(), castTarget.getPrecision(),
castTarget.getScale() castTarget.getScale()
)
); );
} }
} }