HHH-18451 Fix CheckConstraints for Booleans with null value converters

This commit is contained in:
Sebastien Santschi 2024-07-31 22:12:47 +02:00 committed by Christian Beikov
parent 1f8d6f0339
commit 71a616f2be
3 changed files with 84 additions and 9 deletions

View File

@ -555,7 +555,7 @@ public class BasicValue extends SimpleValue implements JdbcTypeIndicators, Resol
@Override @Override
public R toRelationalValue(Boolean domainValue) { public R toRelationalValue(Boolean domainValue) {
return underlyingJpaConverter.toRelationalValue( !domainValue ); return underlyingJpaConverter.toRelationalValue( domainValue != null ? !domainValue : null );
} }
@Override @Override

View File

@ -198,10 +198,7 @@ public class BooleanJavaType extends AbstractClassJavaType<Boolean> implements
(BasicValueConverter<Boolean, ?>) converter; (BasicValueConverter<Boolean, ?>) converter;
final Object falseValue = stringConverter.toRelationalValue( false ); final Object falseValue = stringConverter.toRelationalValue( false );
final Object trueValue = stringConverter.toRelationalValue( true ); final Object trueValue = stringConverter.toRelationalValue( true );
String[] values = new String[] { final String[] values = getPossibleStringValues( stringConverter, falseValue, trueValue );
falseValue != null ? falseValue.toString() : null,
trueValue != null ? trueValue.toString() : null
};
return dialect.getCheckCondition( columnName, values ); return dialect.getCheckCondition( columnName, values );
} }
else if ( jdbcType.isInteger() ) { else if ( jdbcType.isInteger() ) {
@ -210,13 +207,48 @@ public class BooleanJavaType extends AbstractClassJavaType<Boolean> implements
(BasicValueConverter<Boolean, ? extends Number>) converter; (BasicValueConverter<Boolean, ? extends Number>) converter;
final Number falseValue = numericConverter.toRelationalValue( false ); final Number falseValue = numericConverter.toRelationalValue( false );
final Number trueValue = numericConverter.toRelationalValue( true ); final Number trueValue = numericConverter.toRelationalValue( true );
Long[] values = new Long[] { Long[] values = getPossibleNumericValues( numericConverter, falseValue, trueValue );
falseValue != null ? Long.valueOf(falseValue.longValue()) : null,
trueValue != null ? Long.valueOf(trueValue.longValue()) : null
};
return dialect.getCheckCondition( columnName, values ); return dialect.getCheckCondition( columnName, values );
} }
} }
return null; return null;
} }
private static Long[] getPossibleNumericValues(
BasicValueConverter<Boolean, ? extends Number> numericConverter,
Number falseValue,
Number trueValue) {
Number nullValue = null;
try {
nullValue = numericConverter.toRelationalValue( null );
}
catch ( NullPointerException ignored ) {
}
Long[] values = new Long[nullValue != null ? 3 : 2];
values[0] = falseValue != null ? falseValue.longValue() : null;
values[1] = trueValue != null ? trueValue.longValue() : null;
if ( nullValue != null ) {
values[2] = nullValue.longValue();
}
return values;
}
private static String[] getPossibleStringValues(
BasicValueConverter<Boolean, ?> stringConverter,
Object falseValue,
Object trueValue) {
Object nullValue = null;
try {
nullValue = stringConverter.toRelationalValue( null);
}
catch ( NullPointerException ignored ) {
}
final String[] values = new String[nullValue != null ? 3 : 2];
values[0] = falseValue != null ? falseValue.toString() : null;
values[1] = trueValue != null ? trueValue.toString() : null;
if ( nullValue != null ) {
values[2] = nullValue.toString();
}
return values;
}
} }

View File

@ -63,6 +63,15 @@ public class BooleanJavaTypeDescriptorTest {
assertEquals("is_active in (0,1)", checkCondition); assertEquals("is_active in (0,1)", checkCondition);
} }
@Test
public void testCheckConditionShouldReturnCorrectStatementWhen1And0AndNullIntegerGiven() {
// given
// when
String checkCondition = underTest.getCheckCondition("is_active", IntegerJdbcType.INSTANCE, new TriStateBooleanConverter(), new AnyDialect());
// then
assertEquals("is_active in (0,1,-1)", checkCondition);
}
@Test @Test
public void testWrapShouldReturnTrueWhenYStringGiven() { public void testWrapShouldReturnTrueWhenYStringGiven() {
// given // given
@ -176,4 +185,38 @@ public class BooleanJavaTypeDescriptorTest {
return IntegerJavaType.INSTANCE; return IntegerJavaType.INSTANCE;
} }
} }
private static class TriStateBooleanConverter implements AttributeConverter<Boolean, Integer>, BasicValueConverter<Boolean, Integer> {
@Override
public Integer convertToDatabaseColumn(Boolean attribute) {
if (attribute == null) return -1;
return attribute ? 1 : 0;
}
@Override
public Boolean convertToEntityAttribute(Integer dbData) {
if (dbData == null || dbData == -1) return null;
return dbData == 1;
}
@Override
public @Nullable Boolean toDomainValue(@Nullable Integer relationalForm) {
return convertToEntityAttribute(relationalForm);
}
@Override
public @Nullable Integer toRelationalValue(@Nullable Boolean domainForm) {
return convertToDatabaseColumn(domainForm);
}
@Override
public JavaType<Boolean> getDomainJavaType() {
return BooleanJavaType.INSTANCE;
}
@Override
public JavaType<Integer> getRelationalJavaType() {
return IntegerJavaType.INSTANCE;
}
}
} }