From b8fab567cccb7df93aaa5f84c648496ca9c60add Mon Sep 17 00:00:00 2001 From: Andrea Boriero Date: Tue, 18 Jan 2022 09:14:41 +0100 Subject: [PATCH] Fix CriteriaBuidler#locate() arguments order rendering --- .../community/dialect/CacheDialect.java | 6 ++-- .../community/dialect/FirebirdDialect.java | 8 ++--- .../community/dialect/InformixDialect.java | 9 +---- .../community/dialect/IngresDialect.java | 8 ++++- .../community/dialect/MaxDBDialect.java | 4 +-- .../community/dialect/SQLiteDialect.java | 6 ++-- .../community/dialect/TimesTenDialect.java | 6 ++-- .../dialect/AbstractHANADialect.java | 6 ++-- .../org/hibernate/dialect/OracleDialect.java | 6 ++-- .../hibernate/dialect/PostgreSQLDialect.java | 8 +---- .../function/CommonFunctionFactory.java | 33 +++++++------------ .../function/LocatePositionEmulation.java | 15 --------- .../sqm/internal/SqmCriteriaNodeBuilder.java | 8 ++--- .../orm/test/jpa/compliance/LocateTest.java | 19 +++++++++-- .../orm/test/query/hql/FunctionTests.java | 6 ++-- 15 files changed, 65 insertions(+), 83 deletions(-) diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CacheDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CacheDialect.java index e9a634361d..9c0b3246bd 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CacheDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CacheDialect.java @@ -170,10 +170,10 @@ public class CacheDialect extends Dialect { queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern( "locate", queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ), - "$find(?1,?2)", - "$find(?1,?2,?3)", + "$find(?2,?1)", + "$find(?2,?1,?3)", STRING, STRING, INTEGER - ).setArgumentListSignature("(string, pattern[, start])"); + ).setArgumentListSignature("(pattern, string[, start])"); CommonFunctionFactory.bitLength_pattern( queryEngine, "($length(?1)*8)" ); useJdbcEscape(queryEngine, "sin"); diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/FirebirdDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/FirebirdDialect.java index f063055a4f..e3f73fa8e5 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/FirebirdDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/FirebirdDialect.java @@ -276,15 +276,15 @@ public class FirebirdDialect extends Dialect { CommonFunctionFactory.reverse( queryEngine ); CommonFunctionFactory.bitandorxornot_binAndOrXorNot( queryEngine ); CommonFunctionFactory.leastGreatest_minMaxValue( queryEngine ); - SqmFunctionRegistry functionRegistry = queryEngine.getSqmFunctionRegistry(); + SqmFunctionRegistry functionRegistry = queryEngine.getSqmFunctionRegistry(); functionRegistry.registerBinaryTernaryPattern( "locate", integerType, - "position(?2 in ?1)", - "position(?2,?1,?3)", + "position(?1 in ?2)", + "position(?1,?2,?3)", STRING, STRING, INTEGER - ).setArgumentListSignature( "(string, pattern[, start])" ); + ).setArgumentListSignature( "(pattern, string[, start])" ); functionRegistry.namedDescriptorBuilder( "ascii_val" ) .setExactArgumentCount( 1 ) .setInvariantType( shortType ) diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/InformixDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/InformixDialect.java index 86b1799f35..d03935fd47 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/InformixDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/InformixDialect.java @@ -181,14 +181,7 @@ public class InformixDialect extends Dialect { CommonFunctionFactory.monthsBetween( queryEngine ); CommonFunctionFactory.stddev( queryEngine ); CommonFunctionFactory.variance( 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])"); + CommonFunctionFactory.locate_positionSubstring( queryEngine ); //coalesce() and nullif() both supported since Informix 12 diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/IngresDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/IngresDialect.java index 8bc1a49488..3606d7ab52 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/IngresDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/IngresDialect.java @@ -279,10 +279,16 @@ 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 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 ); diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MaxDBDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MaxDBDialect.java index b662fd02bf..39abe5b666 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MaxDBDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MaxDBDialect.java @@ -166,9 +166,9 @@ public class MaxDBDialect extends Dialect { queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern( "locate", - integerType, "index(?1,?2)", "index(?1,?2,?3)", + integerType, "index(?2,?1)", "index(?2,?1,?3)", STRING, STRING, INTEGER - ).setArgumentListSignature("(string, pattern[, start])"); + ).setArgumentListSignature("(pattern, string[, start])"); } @Override diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SQLiteDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SQLiteDialect.java index c02be1eef4..cea98c8205 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SQLiteDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SQLiteDialect.java @@ -274,10 +274,10 @@ public class SQLiteDialect extends Dialect { queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern( "locate", integerType, - "instr(?1,?2)", - "instr(?1,?2,?3)", + "instr(?2,?1)", + "instr(?2,?1,?3)", STRING, STRING, INTEGER - ).setArgumentListSignature("(string, pattern[, start])"); + ).setArgumentListSignature("(pattern, string[, start])"); queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern( "lpad", stringType, diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/TimesTenDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/TimesTenDialect.java index 62be9590a6..5c23e4580f 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/TimesTenDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/TimesTenDialect.java @@ -170,10 +170,10 @@ public class TimesTenDialect extends Dialect { queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern( "locate", queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ), - "instr(?1,?2)", - "instr(?1,?2,?3)", + "instr(?2,?1)", + "instr(?2,?1,?3)", STRING, STRING, INTEGER - ).setArgumentListSignature("(string, pattern[, start])"); + ).setArgumentListSignature("(pattern, string[, start])"); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/AbstractHANADialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/AbstractHANADialect.java index 8736fd624a..5ef435002a 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/AbstractHANADialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/AbstractHANADialect.java @@ -277,10 +277,10 @@ public abstract class AbstractHANADialect extends Dialect { queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern( "locate", queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ), - "locate(?1,?2)", - "locate(?1,?2,?3)", + "locate(?2,?1)", + "locate(?2,?1,?3)", FunctionParameterType.STRING, FunctionParameterType.STRING, FunctionParameterType.INTEGER - ).setArgumentListSignature("(string, pattern[, start])"); + ).setArgumentListSignature("(pattern, string[, start])"); CommonFunctionFactory.ceiling_ceil( queryEngine ); CommonFunctionFactory.concat_pipeOperator( queryEngine ); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java index 00aea691d6..a8518fe573 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java @@ -184,10 +184,10 @@ public class OracleDialect extends Dialect { queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern( "locate", queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ), - "instr(?1,?2)", - "instr(?1,?2,?3)", + "instr(?2,?1)", + "instr(?2,?1,?3)", FunctionParameterType.STRING, FunctionParameterType.STRING, FunctionParameterType.INTEGER - ).setArgumentListSignature("(string, pattern[, start])"); + ).setArgumentListSignature("(pattern, string[, start])"); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java index b27d315175..351163f2b1 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java @@ -449,13 +449,7 @@ public class PostgreSQLDialect extends Dialect { CommonFunctionFactory.overlay( queryEngine ); CommonFunctionFactory.soundex( queryEngine ); //was introduced in Postgres 9 apparently - queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern( - "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])"); + CommonFunctionFactory.locate_positionSubstring( queryEngine ); if ( getVersion().isSameOrAfter( 9, 4 ) ) { CommonFunctionFactory.makeDateTimeTimestamp( queryEngine ); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/CommonFunctionFactory.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/CommonFunctionFactory.java index 6e5ae9ccae..05a4ab4631 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/CommonFunctionFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/CommonFunctionFactory.java @@ -1548,40 +1548,29 @@ public class CommonFunctionFactory { } public static void locate(QueryEngine queryEngine) { - queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern( - "locate", - queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ), - "locate(?2,?1)", - "locate(?2,?1,?3)", - STRING, - STRING, - INTEGER + queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "locate" ) + .setInvariantType( + queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.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 */ 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" ); } /** @@ -1591,10 +1580,10 @@ public class CommonFunctionFactory { queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern( "locate", 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 ) - .setArgumentListSignature( "(STRING string, STRING pattern[, INTEGER start])" ); + .setArgumentListSignature( "(STRING pattern, STRING string[, INTEGER start])" ); } /** * ANSI-style substring diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/LocatePositionEmulation.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/LocatePositionEmulation.java index 6a90cd6d0f..a2128ef736 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/LocatePositionEmulation.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/LocatePositionEmulation.java @@ -6,7 +6,6 @@ */ 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; @@ -18,8 +17,6 @@ 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; @@ -45,18 +42,6 @@ public class LocatePositionEmulation extends AbstractSqmFunctionDescriptor { ReturnableType impliedResultType, QueryEngine queryEngine, TypeConfiguration typeConfiguration) { - if ( arguments instanceof ArrayList ) { - Collections.swap( arguments, 0, 1 ); - } - else { - List> 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 ); } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmCriteriaNodeBuilder.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmCriteriaNodeBuilder.java index 1996a2a3cd..749e167928 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmCriteriaNodeBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmCriteriaNodeBuilder.java @@ -1255,14 +1255,14 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext, final List> arguments; if ( startPosition == null ) { arguments = asList( - source, - pattern - ); + pattern, + source + ); } else { arguments = asList( - source, pattern, + source, startPosition ); } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/compliance/LocateTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/compliance/LocateTest.java index 0d1f179127..8b69db79bb 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/compliance/LocateTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/compliance/LocateTest.java @@ -26,9 +26,9 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @Jpa( - annotatedClasses = CriteriaLocateTest.Person.class + annotatedClasses = LocateTest.Person.class ) -public class CriteriaLocateTest { +public class LocateTest { @BeforeEach public void setUp(EntityManagerFactoryScope scope) { @@ -112,6 +112,21 @@ public class CriteriaLocateTest { ); } + @Test + public void locateQueryTest(EntityManagerFactoryScope scope) { + scope.inTransaction( + entityManager -> { + final List 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") @Table(name = "PERSON_TABLE") public static class Person { diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/FunctionTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/FunctionTests.java index 3ce4147d73..a8fe1b15e3 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/FunctionTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/FunctionTests.java @@ -407,11 +407,11 @@ public class FunctionTests { public void testLocateFunction(SessionFactoryScope scope) { scope.inTransaction( session -> { - session.createQuery("select locate( e.theString, 'hello') from EntityOfBasics e") + session.createQuery("select locate('hello', e.theString) from EntityOfBasics e") .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(); - assertThat( session.createQuery("select locate( 'hello world', 'world')").getSingleResult(), is(7) ); + assertThat( session.createQuery("select locate('world', 'hello world')").getSingleResult(), is(7) ); } ); }