Fix CriteriaBuidler#locate() arguments order rendering

This commit is contained in:
Andrea Boriero 2022-01-18 09:14:41 +01:00 committed by Christian Beikov
parent 370d9354fc
commit b8fab567cc
15 changed files with 65 additions and 83 deletions

View File

@ -170,10 +170,10 @@ public class CacheDialect extends Dialect {
queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern( queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern(
"locate", "locate",
queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ), queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ),
"$find(?1,?2)", "$find(?2,?1)",
"$find(?1,?2,?3)", "$find(?2,?1,?3)",
STRING, STRING, INTEGER STRING, STRING, INTEGER
).setArgumentListSignature("(string, pattern[, start])"); ).setArgumentListSignature("(pattern, string[, start])");
CommonFunctionFactory.bitLength_pattern( queryEngine, "($length(?1)*8)" ); CommonFunctionFactory.bitLength_pattern( queryEngine, "($length(?1)*8)" );
useJdbcEscape(queryEngine, "sin"); useJdbcEscape(queryEngine, "sin");

View File

@ -276,15 +276,15 @@ public class FirebirdDialect extends Dialect {
CommonFunctionFactory.reverse( queryEngine ); CommonFunctionFactory.reverse( queryEngine );
CommonFunctionFactory.bitandorxornot_binAndOrXorNot( queryEngine ); CommonFunctionFactory.bitandorxornot_binAndOrXorNot( queryEngine );
CommonFunctionFactory.leastGreatest_minMaxValue( queryEngine ); CommonFunctionFactory.leastGreatest_minMaxValue( queryEngine );
SqmFunctionRegistry functionRegistry = queryEngine.getSqmFunctionRegistry();
SqmFunctionRegistry functionRegistry = queryEngine.getSqmFunctionRegistry();
functionRegistry.registerBinaryTernaryPattern( functionRegistry.registerBinaryTernaryPattern(
"locate", "locate",
integerType, integerType,
"position(?2 in ?1)", "position(?1 in ?2)",
"position(?2,?1,?3)", "position(?1,?2,?3)",
STRING, STRING, INTEGER STRING, STRING, INTEGER
).setArgumentListSignature( "(string, pattern[, start])" ); ).setArgumentListSignature( "(pattern, string[, start])" );
functionRegistry.namedDescriptorBuilder( "ascii_val" ) functionRegistry.namedDescriptorBuilder( "ascii_val" )
.setExactArgumentCount( 1 ) .setExactArgumentCount( 1 )
.setInvariantType( shortType ) .setInvariantType( shortType )

View File

@ -181,14 +181,7 @@ public class InformixDialect extends Dialect {
CommonFunctionFactory.monthsBetween( queryEngine ); CommonFunctionFactory.monthsBetween( queryEngine );
CommonFunctionFactory.stddev( queryEngine ); CommonFunctionFactory.stddev( queryEngine );
CommonFunctionFactory.variance( queryEngine ); CommonFunctionFactory.variance( queryEngine );
CommonFunctionFactory.locate_positionSubstring( queryEngine );
queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern(
"locate",
queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ),
"instr(?1,?2)",
"instr(?1,?2,?3)",
STRING, STRING, INTEGER
).setArgumentListSignature("(string, pattern[, start])");
//coalesce() and nullif() both supported since Informix 12 //coalesce() and nullif() both supported since Informix 12

View File

@ -279,10 +279,16 @@ public class IngresDialect extends Dialect {
CommonFunctionFactory.format_dateFormat( queryEngine ); CommonFunctionFactory.format_dateFormat( queryEngine );
CommonFunctionFactory.dateTrunc( queryEngine ); CommonFunctionFactory.dateTrunc( queryEngine );
CommonFunctionFactory.bitLength_pattern( queryEngine, "octet_length(hex(?1))*4" ); CommonFunctionFactory.bitLength_pattern( queryEngine, "octet_length(hex(?1))*4" );
CommonFunctionFactory.locate_positionSubstring( queryEngine );
final BasicType<Integer> integerType = queryEngine.getTypeConfiguration().getBasicTypeRegistry() final BasicType<Integer> integerType = queryEngine.getTypeConfiguration().getBasicTypeRegistry()
.resolve( StandardBasicTypes.INTEGER ); .resolve( StandardBasicTypes.INTEGER );
queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern(
"locate",
integerType,
"position(?1 in ?2)",
"(position(?1 in substring(?2 from ?3))+(?3)-1)",
STRING, STRING, INTEGER
).setArgumentListSignature("(pattern, string[, start])");
queryEngine.getSqmFunctionRegistry().registerPattern( "extract", "date_part('?1',?2)", integerType ); queryEngine.getSqmFunctionRegistry().registerPattern( "extract", "date_part('?1',?2)", integerType );

View File

@ -166,9 +166,9 @@ public class MaxDBDialect extends Dialect {
queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern( queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern(
"locate", "locate",
integerType, "index(?1,?2)", "index(?1,?2,?3)", integerType, "index(?2,?1)", "index(?2,?1,?3)",
STRING, STRING, INTEGER STRING, STRING, INTEGER
).setArgumentListSignature("(string, pattern[, start])"); ).setArgumentListSignature("(pattern, string[, start])");
} }
@Override @Override

View File

@ -274,10 +274,10 @@ public class SQLiteDialect extends Dialect {
queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern( queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern(
"locate", "locate",
integerType, integerType,
"instr(?1,?2)", "instr(?2,?1)",
"instr(?1,?2,?3)", "instr(?2,?1,?3)",
STRING, STRING, INTEGER STRING, STRING, INTEGER
).setArgumentListSignature("(string, pattern[, start])"); ).setArgumentListSignature("(pattern, string[, start])");
queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern( queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern(
"lpad", "lpad",
stringType, stringType,

View File

@ -170,10 +170,10 @@ public class TimesTenDialect extends Dialect {
queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern( queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern(
"locate", "locate",
queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ), queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ),
"instr(?1,?2)", "instr(?2,?1)",
"instr(?1,?2,?3)", "instr(?2,?1,?3)",
STRING, STRING, INTEGER STRING, STRING, INTEGER
).setArgumentListSignature("(string, pattern[, start])"); ).setArgumentListSignature("(pattern, string[, start])");
} }
@Override @Override

View File

@ -277,10 +277,10 @@ public abstract class AbstractHANADialect extends Dialect {
queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern( queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern(
"locate", "locate",
queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ), queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ),
"locate(?1,?2)", "locate(?2,?1)",
"locate(?1,?2,?3)", "locate(?2,?1,?3)",
FunctionParameterType.STRING, FunctionParameterType.STRING, FunctionParameterType.INTEGER FunctionParameterType.STRING, FunctionParameterType.STRING, FunctionParameterType.INTEGER
).setArgumentListSignature("(string, pattern[, start])"); ).setArgumentListSignature("(pattern, string[, start])");
CommonFunctionFactory.ceiling_ceil( queryEngine ); CommonFunctionFactory.ceiling_ceil( queryEngine );
CommonFunctionFactory.concat_pipeOperator( queryEngine ); CommonFunctionFactory.concat_pipeOperator( queryEngine );

View File

@ -184,10 +184,10 @@ public class OracleDialect extends Dialect {
queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern( queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern(
"locate", "locate",
queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ), queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ),
"instr(?1,?2)", "instr(?2,?1)",
"instr(?1,?2,?3)", "instr(?2,?1,?3)",
FunctionParameterType.STRING, FunctionParameterType.STRING, FunctionParameterType.INTEGER FunctionParameterType.STRING, FunctionParameterType.STRING, FunctionParameterType.INTEGER
).setArgumentListSignature("(string, pattern[, start])"); ).setArgumentListSignature("(pattern, string[, start])");
} }
@Override @Override

View File

@ -449,13 +449,7 @@ public class PostgreSQLDialect extends Dialect {
CommonFunctionFactory.overlay( queryEngine ); CommonFunctionFactory.overlay( queryEngine );
CommonFunctionFactory.soundex( queryEngine ); //was introduced in Postgres 9 apparently CommonFunctionFactory.soundex( queryEngine ); //was introduced in Postgres 9 apparently
queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern( CommonFunctionFactory.locate_positionSubstring( queryEngine );
"locate",
queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ),
"position(?2 in ?1)",
"(position(?2 in substring(?1 from ?3))+(?3)-1)",
FunctionParameterType.STRING, FunctionParameterType.STRING, FunctionParameterType.INTEGER
).setArgumentListSignature("(string, pattern[, start])");
if ( getVersion().isSameOrAfter( 9, 4 ) ) { if ( getVersion().isSameOrAfter( 9, 4 ) ) {
CommonFunctionFactory.makeDateTimeTimestamp( queryEngine ); CommonFunctionFactory.makeDateTimeTimestamp( queryEngine );

View File

@ -1548,40 +1548,29 @@ public class CommonFunctionFactory {
} }
public static void locate(QueryEngine queryEngine) { public static void locate(QueryEngine queryEngine) {
queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern( queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "locate" )
"locate", .setInvariantType(
queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ), queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER )
"locate(?2,?1)",
"locate(?2,?1,?3)",
STRING,
STRING,
INTEGER
) )
.setArgumentListSignature( "(STRING string, STRING pattern[, INTEGER start])" ); .setArgumentCountBetween( 2, 3 )
.setParameterTypes(STRING, STRING, INTEGER)
.setArgumentListSignature( "(STRING pattern, STRING string[, INTEGER start])" )
.register();
} }
/** /**
* Transact SQL-style * Transact SQL-style
*/ */
public static void locate_charindex(QueryEngine queryEngine) { public static void locate_charindex(QueryEngine queryEngine) {
queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern(
"locate",
queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ),
"charindex(?2,?1)",
"charindex(?2,?1,?3)",
STRING,
STRING,
INTEGER
).setArgumentListSignature( "(STRING string, STRING pattern[, INTEGER start])" );
queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "charindex" ) queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "charindex" )
.setInvariantType( .setInvariantType(
queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ) queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER )
) )
.setArgumentCountBetween( 2, 3 ) .setArgumentCountBetween( 2, 3 )
.setParameterTypes( STRING, STRING, INTEGER ) .setParameterTypes(STRING, STRING, INTEGER)
.setArgumentListSignature( "(STRING pattern, STRING string[, INTEGER start])" ) .setArgumentListSignature( "(STRING pattern, STRING string[, INTEGER start])" )
.register(); .register();
queryEngine.getSqmFunctionRegistry().registerAlternateKey( "locate", "charindex" );
} }
/** /**
@ -1591,10 +1580,10 @@ public class CommonFunctionFactory {
queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern( queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern(
"locate", "locate",
queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ), queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ),
"position(?2 in ?1)", "(position(?2 in substring(?1 from ?3))+?3)", "position(?1 in ?2)", "(position(?1 in substring(?2 from ?3))+(?3)-1)",
STRING, STRING, INTEGER STRING, STRING, INTEGER
) )
.setArgumentListSignature( "(STRING string, STRING pattern[, INTEGER start])" ); .setArgumentListSignature( "(STRING pattern, STRING string[, INTEGER start])" );
} }
/** /**
* ANSI-style substring * ANSI-style substring

View File

@ -6,7 +6,6 @@
*/ */
package org.hibernate.dialect.function; package org.hibernate.dialect.function;
import org.hibernate.mapping.Collection;
import org.hibernate.query.ReturnableType; import org.hibernate.query.ReturnableType;
import org.hibernate.query.spi.QueryEngine; import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.sqm.function.AbstractSqmFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmFunctionDescriptor;
@ -18,8 +17,6 @@ import org.hibernate.query.sqm.tree.SqmTypedNode;
import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.type.spi.TypeConfiguration;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import static org.hibernate.query.sqm.produce.function.FunctionParameterType.STRING; import static org.hibernate.query.sqm.produce.function.FunctionParameterType.STRING;
@ -45,18 +42,6 @@ public class LocatePositionEmulation extends AbstractSqmFunctionDescriptor {
ReturnableType<T> impliedResultType, ReturnableType<T> impliedResultType,
QueryEngine queryEngine, QueryEngine queryEngine,
TypeConfiguration typeConfiguration) { TypeConfiguration typeConfiguration) {
if ( arguments instanceof ArrayList ) {
Collections.swap( arguments, 0, 1 );
}
else {
List<SqmTypedNode<?>> argumentTemp = new ArrayList<>( arguments.size() );
argumentTemp.add( arguments.get( 1 ) );
argumentTemp.add( arguments.get( 0 ) );
for ( int i = 2; i < arguments.size(); i++ ) {
argumentTemp.add( arguments.get( i ) );
}
arguments = argumentTemp;
}
return queryEngine.getSqmFunctionRegistry().findFunctionDescriptor( "locate" ) return queryEngine.getSqmFunctionRegistry().findFunctionDescriptor( "locate" )
.generateSqmExpression( arguments, impliedResultType, queryEngine, typeConfiguration ); .generateSqmExpression( arguments, impliedResultType, queryEngine, typeConfiguration );
} }

View File

@ -1255,14 +1255,14 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
final List<SqmTypedNode<?>> arguments; final List<SqmTypedNode<?>> arguments;
if ( startPosition == null ) { if ( startPosition == null ) {
arguments = asList( arguments = asList(
source, pattern,
pattern source
); );
} }
else { else {
arguments = asList( arguments = asList(
source,
pattern, pattern,
source,
startPosition startPosition
); );
} }

View File

@ -26,9 +26,9 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
@Jpa( @Jpa(
annotatedClasses = CriteriaLocateTest.Person.class annotatedClasses = LocateTest.Person.class
) )
public class CriteriaLocateTest { public class LocateTest {
@BeforeEach @BeforeEach
public void setUp(EntityManagerFactoryScope scope) { public void setUp(EntityManagerFactoryScope scope) {
@ -112,6 +112,21 @@ public class CriteriaLocateTest {
); );
} }
@Test
public void locateQueryTest(EntityManagerFactoryScope scope) {
scope.inTransaction(
entityManager -> {
final List<Integer> ids = entityManager.createQuery(
"select distinct p.id from Person p where locate('nd', p.name) = 2" )
.getResultList();
assertEquals( 2, ids.size() );
assertTrue( ids.contains( 3 ) );
assertTrue( ids.contains( 4 ) );
}
);
}
@Entity(name = "Person") @Entity(name = "Person")
@Table(name = "PERSON_TABLE") @Table(name = "PERSON_TABLE")
public static class Person { public static class Person {

View File

@ -407,11 +407,11 @@ public class FunctionTests {
public void testLocateFunction(SessionFactoryScope scope) { public void testLocateFunction(SessionFactoryScope scope) {
scope.inTransaction( scope.inTransaction(
session -> { session -> {
session.createQuery("select locate( e.theString, 'hello') from EntityOfBasics e") session.createQuery("select locate('hello', e.theString) from EntityOfBasics e")
.list(); .list();
session.createQuery("select locate( e.theString, 'hello', e.theInteger) from EntityOfBasics e") session.createQuery("select locate('hello', e.theString, e.theInteger) from EntityOfBasics e")
.list(); .list();
assertThat( session.createQuery("select locate( 'hello world', 'world')").getSingleResult(), is(7) ); assertThat( session.createQuery("select locate('world', 'hello world')").getSingleResult(), is(7) );
} }
); );
} }