Fix CriteriaBuidler#locate() arguments order rendering
This commit is contained in:
parent
23a011385d
commit
9e7a091d67
|
@ -170,10 +170,10 @@ public class CacheDialect extends Dialect {
|
|||
queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern(
|
||||
"locate",
|
||||
queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ),
|
||||
"$find(?2,?1)",
|
||||
"$find(?2,?1,?3)",
|
||||
"$find(?1,?2)",
|
||||
"$find(?1,?2,?3)",
|
||||
STRING, STRING, INTEGER
|
||||
).setArgumentListSignature("(pattern, string[, start])");
|
||||
).setArgumentListSignature("(string, pattern[, start])");
|
||||
CommonFunctionFactory.bitLength_pattern( queryEngine, "($length(?1)*8)" );
|
||||
|
||||
useJdbcEscape(queryEngine, "sin");
|
||||
|
|
|
@ -276,15 +276,15 @@ public class FirebirdDialect extends Dialect {
|
|||
CommonFunctionFactory.reverse( queryEngine );
|
||||
CommonFunctionFactory.bitandorxornot_binAndOrXorNot( queryEngine );
|
||||
CommonFunctionFactory.leastGreatest_minMaxValue( queryEngine );
|
||||
|
||||
SqmFunctionRegistry functionRegistry = queryEngine.getSqmFunctionRegistry();
|
||||
|
||||
functionRegistry.registerBinaryTernaryPattern(
|
||||
"locate",
|
||||
integerType,
|
||||
"position(?1 in ?2)",
|
||||
"position(?1,?2,?3)",
|
||||
"position(?2 in ?1)",
|
||||
"position(?2,?1,?3)",
|
||||
STRING, STRING, INTEGER
|
||||
).setArgumentListSignature( "(pattern, string[, start])" );
|
||||
).setArgumentListSignature( "(string, pattern[, start])" );
|
||||
functionRegistry.namedDescriptorBuilder( "ascii_val" )
|
||||
.setExactArgumentCount( 1 )
|
||||
.setInvariantType( shortType )
|
||||
|
|
|
@ -185,10 +185,10 @@ public class InformixDialect extends Dialect {
|
|||
queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern(
|
||||
"locate",
|
||||
queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ),
|
||||
"instr(?2,?1)",
|
||||
"instr(?2,?1,?3)",
|
||||
"instr(?1,?2)",
|
||||
"instr(?1,?2,?3)",
|
||||
STRING, STRING, INTEGER
|
||||
).setArgumentListSignature("(pattern, string[, start])");
|
||||
).setArgumentListSignature("(string, pattern[, start])");
|
||||
|
||||
//coalesce() and nullif() both supported since Informix 12
|
||||
|
||||
|
|
|
@ -279,16 +279,10 @@ public class IngresDialect extends Dialect {
|
|||
CommonFunctionFactory.format_dateFormat( queryEngine );
|
||||
CommonFunctionFactory.dateTrunc( queryEngine );
|
||||
CommonFunctionFactory.bitLength_pattern( queryEngine, "octet_length(hex(?1))*4" );
|
||||
CommonFunctionFactory.locate_positionSubstring( queryEngine );
|
||||
|
||||
final BasicType<Integer> integerType = queryEngine.getTypeConfiguration().getBasicTypeRegistry()
|
||||
.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 );
|
||||
|
||||
|
|
|
@ -166,9 +166,9 @@ public class MaxDBDialect extends Dialect {
|
|||
|
||||
queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern(
|
||||
"locate",
|
||||
integerType, "index(?2,?1)", "index(?2,?1,?3)",
|
||||
integerType, "index(?1,?2)", "index(?1,?2,?3)",
|
||||
STRING, STRING, INTEGER
|
||||
).setArgumentListSignature("(pattern, string[, start])");
|
||||
).setArgumentListSignature("(string, pattern[, start])");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -274,10 +274,10 @@ public class SQLiteDialect extends Dialect {
|
|||
queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern(
|
||||
"locate",
|
||||
integerType,
|
||||
"instr(?2,?1)",
|
||||
"instr(?2,?1,?3)",
|
||||
"instr(?1,?2)",
|
||||
"instr(?1,?2,?3)",
|
||||
STRING, STRING, INTEGER
|
||||
).setArgumentListSignature("(pattern, string[, start])");
|
||||
).setArgumentListSignature("(string, pattern[, start])");
|
||||
queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern(
|
||||
"lpad",
|
||||
stringType,
|
||||
|
|
|
@ -170,10 +170,10 @@ public class TimesTenDialect extends Dialect {
|
|||
queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern(
|
||||
"locate",
|
||||
queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ),
|
||||
"instr(?2,?1)",
|
||||
"instr(?2,?1,?3)",
|
||||
"instr(?1,?2)",
|
||||
"instr(?1,?2,?3)",
|
||||
STRING, STRING, INTEGER
|
||||
).setArgumentListSignature("(pattern, string[, start])");
|
||||
).setArgumentListSignature("(string, pattern[, start])");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -277,10 +277,10 @@ public abstract class AbstractHANADialect extends Dialect {
|
|||
queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern(
|
||||
"locate",
|
||||
queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ),
|
||||
"locate(?2,?1)",
|
||||
"locate(?2,?1,?3)",
|
||||
"locate(?1,?2)",
|
||||
"locate(?1,?2,?3)",
|
||||
FunctionParameterType.STRING, FunctionParameterType.STRING, FunctionParameterType.INTEGER
|
||||
).setArgumentListSignature("(pattern, string[, start])");
|
||||
).setArgumentListSignature("(string, pattern[, start])");
|
||||
|
||||
CommonFunctionFactory.ceiling_ceil( queryEngine );
|
||||
CommonFunctionFactory.concat_pipeOperator( queryEngine );
|
||||
|
|
|
@ -184,10 +184,10 @@ public class OracleDialect extends Dialect {
|
|||
queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern(
|
||||
"locate",
|
||||
queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ),
|
||||
"instr(?2,?1)",
|
||||
"instr(?2,?1,?3)",
|
||||
"instr(?1,?2)",
|
||||
"instr(?1,?2,?3)",
|
||||
FunctionParameterType.STRING, FunctionParameterType.STRING, FunctionParameterType.INTEGER
|
||||
).setArgumentListSignature("(pattern, string[, start])");
|
||||
).setArgumentListSignature("(string, pattern[, start])");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -452,10 +452,10 @@ public class PostgreSQLDialect extends Dialect {
|
|||
queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern(
|
||||
"locate",
|
||||
queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ),
|
||||
"position(?1 in ?2)",
|
||||
"(position(?1 in substring(?2 from ?3))+(?3)-1)",
|
||||
"position(?2 in ?1)",
|
||||
"(position(?2 in substring(?1 from ?3))+(?3)-1)",
|
||||
FunctionParameterType.STRING, FunctionParameterType.STRING, FunctionParameterType.INTEGER
|
||||
).setArgumentListSignature("(pattern, string[, start])");
|
||||
).setArgumentListSignature("(string, pattern[, start])");
|
||||
|
||||
if ( getVersion().isSameOrAfter( 9, 4 ) ) {
|
||||
CommonFunctionFactory.makeDateTimeTimestamp( queryEngine );
|
||||
|
|
|
@ -1548,29 +1548,40 @@ public class CommonFunctionFactory {
|
|||
}
|
||||
|
||||
public static void locate(QueryEngine queryEngine) {
|
||||
queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "locate" )
|
||||
.setInvariantType(
|
||||
queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER )
|
||||
queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern(
|
||||
"locate",
|
||||
queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ),
|
||||
"locate(?2,?1)",
|
||||
"locate(?2,?1,?3)",
|
||||
STRING,
|
||||
STRING,
|
||||
INTEGER
|
||||
)
|
||||
.setArgumentCountBetween( 2, 3 )
|
||||
.setParameterTypes(STRING, STRING, INTEGER)
|
||||
.setArgumentListSignature( "(STRING pattern, STRING string[, INTEGER start])" )
|
||||
.register();
|
||||
.setArgumentListSignature( "(STRING string, STRING pattern[, INTEGER start])" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Transact SQL-style
|
||||
*/
|
||||
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" )
|
||||
.setInvariantType(
|
||||
queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER )
|
||||
)
|
||||
.setArgumentCountBetween( 2, 3 )
|
||||
.setParameterTypes(STRING, STRING, INTEGER)
|
||||
.setParameterTypes( STRING, STRING, INTEGER )
|
||||
.setArgumentListSignature( "(STRING pattern, STRING string[, INTEGER start])" )
|
||||
.register();
|
||||
queryEngine.getSqmFunctionRegistry().registerAlternateKey( "locate", "charindex" );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1580,10 +1591,10 @@ public class CommonFunctionFactory {
|
|||
queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern(
|
||||
"locate",
|
||||
queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ),
|
||||
"position(?1 in ?2)", "(position(?1 in substring(?2 from ?3))+?3)",
|
||||
"position(?2 in ?1)", "(position(?2 in substring(?1 from ?3))+?3)",
|
||||
STRING, STRING, INTEGER
|
||||
)
|
||||
.setArgumentListSignature( "(STRING pattern, STRING string[, INTEGER start])" );
|
||||
.setArgumentListSignature( "(STRING string, STRING pattern[, INTEGER start])" );
|
||||
}
|
||||
/**
|
||||
* ANSI-style substring
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
package org.hibernate.dialect.function;
|
||||
|
||||
import org.hibernate.mapping.Collection;
|
||||
import org.hibernate.query.ReturnableType;
|
||||
import org.hibernate.query.spi.QueryEngine;
|
||||
import org.hibernate.query.sqm.function.AbstractSqmFunctionDescriptor;
|
||||
|
@ -17,6 +18,8 @@ import org.hibernate.query.sqm.tree.SqmTypedNode;
|
|||
import org.hibernate.type.StandardBasicTypes;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.hibernate.query.sqm.produce.function.FunctionParameterType.STRING;
|
||||
|
@ -42,6 +45,18 @@ public class LocatePositionEmulation extends AbstractSqmFunctionDescriptor {
|
|||
ReturnableType<T> impliedResultType,
|
||||
QueryEngine queryEngine,
|
||||
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" )
|
||||
.generateSqmExpression( arguments, impliedResultType, queryEngine, typeConfiguration );
|
||||
}
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/*
|
||||
* 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.jpa.compliance;
|
||||
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
|
|
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* 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.jpa.compliance;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
|
||||
import org.hibernate.testing.orm.junit.Jpa;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.persistence.criteria.CriteriaBuilder;
|
||||
import jakarta.persistence.criteria.CriteriaQuery;
|
||||
import jakarta.persistence.criteria.Expression;
|
||||
import jakarta.persistence.criteria.Root;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
@Jpa(
|
||||
annotatedClasses = CriteriaLocateTest.Person.class
|
||||
)
|
||||
public class CriteriaLocateTest {
|
||||
|
||||
@BeforeEach
|
||||
public void setUp(EntityManagerFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
entityManager -> {
|
||||
for ( int i = 0; i < 10; i++ ) {
|
||||
Person person;
|
||||
if ( i == 3 ) {
|
||||
person = new Person( i, "Andrea" );
|
||||
}
|
||||
else if ( i == 4 ) {
|
||||
person = new Person( i, "Andrew" );
|
||||
}
|
||||
else {
|
||||
person = new Person( i, "Luigi " + i );
|
||||
}
|
||||
entityManager.persist( person );
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void tearDown(EntityManagerFactoryScope scope){
|
||||
scope.inTransaction(
|
||||
entityManager ->
|
||||
entityManager.createQuery( "delete from Person" ).executeUpdate()
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLocate(EntityManagerFactoryScope scope) {
|
||||
scope.inEntityManager(
|
||||
entityManager -> {
|
||||
final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
|
||||
final CriteriaQuery<Integer> query = criteriaBuilder.createQuery( Integer.class );
|
||||
final Root<Person> personRoot = query.from( Person.class );
|
||||
|
||||
query.select( personRoot.get( "id" ) );
|
||||
|
||||
final Expression<Integer> locate = criteriaBuilder.locate(
|
||||
personRoot.get( "name" ),
|
||||
criteriaBuilder.literal( "nd" )
|
||||
);
|
||||
|
||||
query.where( criteriaBuilder.equal( locate, 2 ) );
|
||||
|
||||
final List<Integer> results = entityManager.createQuery( query ).getResultList();
|
||||
|
||||
assertEquals( 2, results.size() );
|
||||
assertTrue( results.contains( 3 ) );
|
||||
assertTrue( results.contains( 4 ) );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLocate2(EntityManagerFactoryScope scope) {
|
||||
scope.inEntityManager(
|
||||
entityManager -> {
|
||||
final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
|
||||
final CriteriaQuery<Integer> query = criteriaBuilder.createQuery( Integer.class );
|
||||
final Root<Person> personRoot = query.from( Person.class );
|
||||
|
||||
query.select( personRoot.get( "id" ) );
|
||||
|
||||
final Expression<Integer> locate = criteriaBuilder.locate(
|
||||
personRoot.get( "name" ),
|
||||
"nd" ,
|
||||
1
|
||||
);
|
||||
|
||||
query.where( criteriaBuilder.equal( locate, 2 ) );
|
||||
|
||||
final List<Integer> results = entityManager.createQuery( query ).getResultList();
|
||||
|
||||
assertEquals( 2, results.size() );
|
||||
assertTrue( results.contains( 3 ) );
|
||||
assertTrue( results.contains( 4 ) );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Entity(name = "Person")
|
||||
@Table(name = "PERSON_TABLE")
|
||||
public static class Person {
|
||||
|
||||
@Id
|
||||
private Integer id;
|
||||
|
||||
private String name;
|
||||
|
||||
Person() {
|
||||
}
|
||||
|
||||
public Person(Integer id, String name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -407,11 +407,11 @@ public class FunctionTests {
|
|||
public void testLocateFunction(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
session.createQuery("select locate('hello', e.theString) from EntityOfBasics e")
|
||||
session.createQuery("select locate( e.theString, 'hello') from EntityOfBasics e")
|
||||
.list();
|
||||
session.createQuery("select locate('hello', e.theString, e.theInteger) from EntityOfBasics e")
|
||||
session.createQuery("select locate( e.theString, 'hello', e.theInteger) from EntityOfBasics e")
|
||||
.list();
|
||||
assertThat( session.createQuery("select locate('world', 'hello world')").getSingleResult(), is(7) );
|
||||
assertThat( session.createQuery("select locate( 'hello world', 'world')").getSingleResult(), is(7) );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue