HHH-13694 fix numeric overflow exception for large sequence min values

This commit is contained in:
Christian Beikov 2022-03-08 14:50:51 +01:00
parent ac4a792f84
commit 3d55855a87
10 changed files with 151 additions and 33 deletions

View File

@ -202,9 +202,9 @@ public class SequenceStyleGenerator
if ( sequenceMismatchStrategy != SequenceMismatchStrategy.NONE && isPooledOptimizer && isPhysicalSequence( jdbcEnvironment, forceTableUse ) ) {
String databaseSequenceName = sequenceName.getObjectName().getText();
Long databaseIncrementValue = getSequenceIncrementValue( jdbcEnvironment, databaseSequenceName );
Number databaseIncrementValue = getSequenceIncrementValue( jdbcEnvironment, databaseSequenceName );
if ( databaseIncrementValue != null && !databaseIncrementValue.equals( (long) incrementSize ) ) {
if ( databaseIncrementValue != null && databaseIncrementValue.intValue() != incrementSize ) {
int dbIncrementValue = databaseIncrementValue.intValue();
switch ( sequenceMismatchStrategy ) {
@ -553,7 +553,7 @@ public class SequenceStyleGenerator
*
* @return sequence increment value
*/
private Long getSequenceIncrementValue(JdbcEnvironment jdbcEnvironment, String sequenceName) {
private Number getSequenceIncrementValue(JdbcEnvironment jdbcEnvironment, String sequenceName) {
return jdbcEnvironment.getExtractedDatabaseMetaData().getSequenceInformationList()
.stream()
.filter(

View File

@ -105,22 +105,22 @@ public class SequenceInformationExtractorLegacyImpl implements SequenceInformati
return column != null ? resultSet.getString( column ) : null;
}
protected Long resultSetStartValueSize(ResultSet resultSet) throws SQLException {
protected Number resultSetStartValueSize(ResultSet resultSet) throws SQLException {
String column = sequenceStartValueColumn();
return column != null ? resultSet.getLong( column ) : null;
}
protected Long resultSetMinValue(ResultSet resultSet) throws SQLException {
protected Number resultSetMinValue(ResultSet resultSet) throws SQLException {
String column = sequenceMinValueColumn();
return column != null ? resultSet.getLong( column ) : null;
}
protected Long resultSetMaxValue(ResultSet resultSet) throws SQLException {
protected Number resultSetMaxValue(ResultSet resultSet) throws SQLException {
String column = sequenceMaxValueColumn();
return column != null ? resultSet.getLong( column ) : null;
}
protected Long resultSetIncrementValue(ResultSet resultSet) throws SQLException {
protected Number resultSetIncrementValue(ResultSet resultSet) throws SQLException {
String column = sequenceIncrementColumn();
return column != null ? resultSet.getLong( column ) : null;
}

View File

@ -39,8 +39,24 @@ public class SequenceInformationExtractorOracleDatabaseImpl extends SequenceInfo
}
@Override
protected Long resultSetMaxValue(ResultSet resultSet) throws SQLException {
return resultSet.getBigDecimal( "max_value" ).longValue();
protected String sequenceMaxValueColumn() {
return "max_value";
}
@Override
protected Number resultSetIncrementValue(ResultSet resultSet) throws SQLException {
return resultSet.getBigDecimal( sequenceIncrementColumn() );
}
@Override
protected Number resultSetMinValue(ResultSet resultSet) throws SQLException {
return resultSet.getBigDecimal( sequenceMinValueColumn() );
}
@Override
protected Number resultSetMaxValue(ResultSet resultSet) throws SQLException {
return resultSet.getBigDecimal( sequenceMaxValueColumn() );
}
@Override

View File

@ -110,7 +110,7 @@ public class SequenceInformationExtractorTiDBDatabaseImpl extends SequenceInform
return resultSet.getString( sequenceNameColumn() );
}
protected Long resultSetIncrementValue(ResultSet resultSet) throws SQLException {
protected Number resultSetIncrementValue(ResultSet resultSet) throws SQLException {
String column = sequenceIncrementColumn();
return column != null ? resultSet.getLong( column ) : null;
}

View File

@ -17,16 +17,16 @@ import org.hibernate.tool.schema.extract.spi.SequenceInformation;
public class SequenceInformationImpl implements SequenceInformation {
private final QualifiedSequenceName sequenceName;
private final Long startValue;
private final Long minValue;
private final Long maxValue;
private final Long incrementValue;
private final Number startValue;
private final Number minValue;
private final Number maxValue;
private final Number incrementValue;
public SequenceInformationImpl(
QualifiedSequenceName sequenceName,
Long startValue,
Long minValue,
Long maxValue, Long incrementValue) {
Number startValue,
Number minValue,
Number maxValue, Number incrementValue) {
this.sequenceName = sequenceName;
this.startValue = startValue;
this.minValue = minValue;
@ -40,21 +40,21 @@ public class SequenceInformationImpl implements SequenceInformation {
}
@Override
public Long getStartValue() {
public Number getStartValue() {
return startValue;
}
@Override
public Long getMinValue() {
public Number getMinValue() {
return minValue;
}
public Long getMaxValue() {
public Number getMaxValue() {
return maxValue;
}
@Override
public Long getIncrementValue() {
public Number getIncrementValue() {
return incrementValue;
}
}

View File

@ -27,26 +27,26 @@ public interface SequenceInformation {
*
* @return The extracted start value or null id the value could not be extracted.
*/
Long getStartValue();
Number getStartValue();
/**
* Retrieve the extracted minimum value defined for the sequence.
*
* @return The extracted minimum value or null id the value could not be extracted.
*/
Long getMinValue();
Number getMinValue();
/**
* Retrieve the extracted maximum value defined for the sequence.
*
* @return The extracted maximum value or null id the value could not be extracted.
*/
Long getMaxValue();
Number getMaxValue();
/**
* Retrieve the extracted increment value defined for the sequence.
*
* @return The extracted increment value; use a negative number to indicate the increment could not be extracted.
*/
Long getIncrementValue();
Number getIncrementValue();
}

View File

@ -184,8 +184,8 @@ public abstract class AbstractSchemaValidator implements SchemaValidator {
);
}
if ( sequenceInformation.getIncrementValue() != null && sequenceInformation.getIncrementValue() > 0
&& sequence.getIncrementSize() != sequenceInformation.getIncrementValue() ) {
if ( sequenceInformation.getIncrementValue() != null && sequenceInformation.getIncrementValue().intValue() > 0
&& sequence.getIncrementSize() != sequenceInformation.getIncrementValue().intValue() ) {
throw new SchemaManagementException(
String.format(
"Schema-validation: sequence [%s] defined inconsistent increment-size; found [%s] but expecting [%s]",

View File

@ -0,0 +1,102 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.orm.test.dialect.functional;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Optional;
import java.util.stream.StreamSupport;
import org.hibernate.dialect.OracleDialect;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.testing.RequiresDialect;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorOracleDatabaseImpl;
import org.hibernate.tool.schema.extract.spi.ExtractionContext;
import org.hibernate.tool.schema.extract.spi.SequenceInformation;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.hibernate.testing.transaction.TransactionUtil.doInAutoCommit;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@RequiresDialect(value = { OracleDialect.class })
@TestForIssue(jiraKey = "HHH-13694")
public class OracleDialectSequenceInformationTest extends BaseNonConfigCoreFunctionalTestCase {
private static final String MIN_SEQUENCE_NAME = "SEQ_MIN_TEST";
private static final String MAX_SEQUENCE_NAME = "SEQ_MAX_TEST";
private static final String MIN_VALUE = "-99999999999999999999999999";
private static final String MAX_VALUE = "99999999999999999999999999";
@Before
public void prepareTest() throws Exception {
doInAutoCommit(
"DROP SEQUENCE " + MIN_SEQUENCE_NAME,
"CREATE SEQUENCE " + MIN_SEQUENCE_NAME + " MINVALUE " + MIN_VALUE + " MAXVALUE -1 INCREMENT BY -1",
"DROP SEQUENCE " + MAX_SEQUENCE_NAME,
"CREATE SEQUENCE " + MAX_SEQUENCE_NAME + " MINVALUE 0 MAXVALUE " + MAX_VALUE + " INCREMENT BY 1" );
}
@After
public void cleanupTest() throws Exception {
doInAutoCommit(
"DROP SEQUENCE " + MIN_SEQUENCE_NAME,
"DROP SEQUENCE " + MAX_SEQUENCE_NAME );
}
@Test
public void testExtractSequenceWithMinValueLowerThanLongMinValue() throws SQLException {
SequenceInformation sequence = fetchSequenceInformation( MIN_SEQUENCE_NAME );
assertEquals( -1L, sequence.getIncrementValue().longValue() );
assertEquals( new BigDecimal( MIN_VALUE ), sequence.getMinValue() );
}
@Test
public void testExtractSequenceWithMaxValueGreaterThanLongMaxValue() throws SQLException {
SequenceInformation sequence = fetchSequenceInformation( MAX_SEQUENCE_NAME );
assertEquals( 1L, sequence.getIncrementValue().longValue() );
assertEquals( new BigDecimal( MAX_VALUE ), sequence.getMaxValue() );
}
private SequenceInformation fetchSequenceInformation(String sequenceName) throws SQLException {
try ( Connection connection = sessionFactory().getJdbcServices()
.getBootstrapJdbcConnectionAccess()
.obtainConnection() ) {
JdbcEnvironment jdbcEnvironment = sessionFactory().getJdbcServices().getJdbcEnvironment();
SequenceInformationExtractorOracleDatabaseImpl sequenceExtractor = SequenceInformationExtractorOracleDatabaseImpl.INSTANCE;
Iterable<SequenceInformation> sequenceInformations = sequenceExtractor.extractMetadata(
new ExtractionContext.EmptyExtractionContext() {
@Override
public Connection getJdbcConnection() {
return connection;
}
@Override
public JdbcEnvironment getJdbcEnvironment() {
return jdbcEnvironment;
}
} );
// lets skip system sequences
Optional<SequenceInformation> foundSequence = StreamSupport.stream( sequenceInformations.spliterator(), false )
.filter( sequence -> sequenceName.equals( sequence.getSequenceName().getSequenceName().getText().toUpperCase() ) )
.findFirst();
assertTrue( sequenceName + " not found", foundSequence.isPresent() );
return foundSequence.get();
}
}
}

View File

@ -26,14 +26,14 @@ public class OracleSequenceInfoTest extends
@Override
protected void assertProductSequence(SequenceInformation productSequenceInfo) {
assertNull( productSequenceInfo.getStartValue() );
assertEquals( Long.valueOf( 1 ), productSequenceInfo.getMinValue() );
assertEquals( Long.valueOf( 10 ), productSequenceInfo.getIncrementValue() );
assertEquals( Long.valueOf( 1 ), productSequenceInfo.getMinValue().longValue() );
assertEquals( Long.valueOf( 10 ), productSequenceInfo.getIncrementValue().longValue() );
}
@Override
protected void assertVehicleSequenceInfo(SequenceInformation vehicleSequenceInfo) {
assertNull( vehicleSequenceInfo.getStartValue() );
assertEquals( Long.valueOf( 1 ), vehicleSequenceInfo.getMinValue() );
assertEquals( Long.valueOf( 1 ), vehicleSequenceInfo.getIncrementValue() );
assertEquals( Long.valueOf( 1 ), vehicleSequenceInfo.getMinValue().longValue() );
assertEquals( Long.valueOf( 1 ), vehicleSequenceInfo.getIncrementValue().longValue() );
}
}

View File

@ -88,11 +88,11 @@ public class SequenceInformationTest extends
}
protected void assertProductSequence(SequenceInformation productSequenceInfo) {
assertEquals( Long.valueOf( 10 ), productSequenceInfo.getIncrementValue() );
assertEquals( Long.valueOf( 10 ), productSequenceInfo.getIncrementValue().longValue() );
}
protected void assertVehicleSequenceInfo(SequenceInformation vehicleSequenceInfo) {
assertEquals( Long.valueOf( 1 ), vehicleSequenceInfo.getIncrementValue() );
assertEquals( Long.valueOf( 1 ), vehicleSequenceInfo.getIncrementValue().longValue() );
}
private SequenceInformation sequenceInformation(String sequenceName) {