HHH-18213 Fix LimitHandler for Firebird 2.5 and older

This commit is contained in:
Mark Rotteveel 2024-06-01 12:22:57 +02:00 committed by Christian Beikov
parent cfc6df2e27
commit 1e70c51b56
3 changed files with 101 additions and 3 deletions

View File

@ -28,7 +28,7 @@ import org.hibernate.boot.model.FunctionContributions;
import org.hibernate.boot.model.TypeContributions;
import org.hibernate.boot.model.relational.SqlStringGenerationContext;
import org.hibernate.community.dialect.identity.FirebirdIdentityColumnSupport;
import org.hibernate.community.dialect.pagination.SkipFirstLimitHandler;
import org.hibernate.community.dialect.pagination.FirstSkipLimitHandler;
import org.hibernate.community.dialect.sequence.FirebirdSequenceSupport;
import org.hibernate.community.dialect.sequence.InterbaseSequenceSupport;
import org.hibernate.community.dialect.sequence.SequenceInformationExtractorFirebirdDatabaseImpl;
@ -36,7 +36,6 @@ import org.hibernate.dialect.BooleanDecoder;
import org.hibernate.dialect.DatabaseVersion;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.NationalizationSupport;
import org.hibernate.dialect.SimpleDatabaseVersion;
import org.hibernate.dialect.TimeZoneSupport;
import org.hibernate.dialect.function.CommonFunctionFactory;
import org.hibernate.dialect.identity.IdentityColumnSupport;
@ -674,7 +673,7 @@ public class FirebirdDialect extends Dialect {
@Override
public LimitHandler getLimitHandler() {
return getVersion().isBefore( 3, 0 )
? SkipFirstLimitHandler.INSTANCE
? FirstSkipLimitHandler.INSTANCE
: OffsetFetchLimitHandler.INSTANCE;
}

View File

@ -0,0 +1,62 @@
/*
* 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.community.dialect.pagination;
import org.hibernate.dialect.pagination.AbstractLimitHandler;
import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.query.spi.Limit;
/**
* A {@link LimitHandler} for Firebird 2.5 and older which supports the syntax
* {@code FIRST n SKIP m}.
*/
public class FirstSkipLimitHandler extends AbstractLimitHandler {
public static final FirstSkipLimitHandler INSTANCE = new FirstSkipLimitHandler();
@Override
public String processSql(String sql, Limit limit) {
boolean hasFirstRow = hasFirstRow( limit );
boolean hasMaxRows = hasMaxRows( limit );
if ( !hasFirstRow && !hasMaxRows ) {
return sql;
}
StringBuilder skipFirst = new StringBuilder();
if ( hasMaxRows ) {
skipFirst.append( " first ?" );
}
if ( hasFirstRow ) {
skipFirst.append( " skip ?" );
}
return insertAfterSelect( skipFirst.toString(), sql );
}
@Override
public final boolean supportsLimit() {
return true;
}
@Override
public boolean supportsOffset() {
return true;
}
@Override
public boolean bindLimitParametersInReverseOrder() {
return true;
}
@Override
public final boolean bindLimitParametersFirst() {
return true;
}
}

View File

@ -0,0 +1,37 @@
/*
* 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.community.dialect;
import org.hibernate.dialect.DatabaseVersion;
import org.hibernate.query.spi.Limit;
import org.hibernate.testing.orm.junit.JiraKey;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import static org.junit.jupiter.api.Assertions.assertEquals;
class FirebirdDialectTest {
@ParameterizedTest
@CsvSource(useHeadersInDisplayName = true, value = {
"major, minor, offset, limit, expectedSQL",
"2, 5, 0, 10, select first ? * from tablename t where t.cat = 5",
"2, 5, 10, 0, select skip ? * from tablename t where t.cat = 5",
"2, 5, 5, 10, select first ? skip ? * from tablename t where t.cat = 5",
"3, 0, 0, 10, select * from tablename t where t.cat = 5 fetch first ? rows only",
"3, 0, 10, 0, select * from tablename t where t.cat = 5 offset ? rows",
"3, 0, 5, 10, select * from tablename t where t.cat = 5 offset ? rows fetch next ? rows only"
})
@JiraKey( "HHH-18213" )
void insertOffsetLimitClause(int major, int minor, int offset, int limit, String expectedSql) {
String input = "select * from tablename t where t.cat = 5";
FirebirdDialect dialect = new FirebirdDialect( DatabaseVersion.make( major, minor ) );
String actual = dialect.getLimitHandler().processSql( input, new Limit( offset, limit ) );
assertEquals( expectedSql, actual );
}
}