Introduce special str function implementation for T-SQL

This commit is contained in:
Christian Beikov 2021-08-31 13:45:53 +02:00
parent b4a82f0854
commit 118b160b02
4 changed files with 85 additions and 1 deletions

View File

@ -1459,6 +1459,7 @@ public class HQLTest extends BaseEntityManagerFunctionalTestCase {
public void test_hql_str_function_example_sql_server() {
doInJPA( this::entityManagerFactory, entityManager -> {
//tag::hql-str-function-example[]
// Special SQL Server function "str" that converts floats
List<String> timestamps = entityManager.createQuery(
"select str( cast(duration as float) / 60, 4, 2 ) " +
"from Call c ", String.class )

View File

@ -8,6 +8,8 @@ package org.hibernate.dialect;
import org.hibernate.LockMode;
import org.hibernate.LockOptions;
import org.hibernate.dialect.function.CastStrEmulation;
import org.hibernate.dialect.function.TransactSQLStrFunction;
import org.hibernate.query.NullOrdering;
import org.hibernate.boot.TempTableDdlTransactionHandling;
import org.hibernate.cfg.Environment;
@ -116,6 +118,7 @@ public abstract class AbstractTransactSQLDialect extends Dialect {
queryEngine.getSqmFunctionRegistry().register( "least", new CaseLeastGreatestEmulation( true ) );
queryEngine.getSqmFunctionRegistry().register( "greatest", new CaseLeastGreatestEmulation( false ) );
queryEngine.getSqmFunctionRegistry().register( "str", new TransactSQLStrFunction() );
}
@Override

View File

@ -10,6 +10,8 @@ import org.hibernate.metamodel.model.domain.AllowableFunctionReturnType;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.sqm.function.AbstractSqmFunctionDescriptor;
import org.hibernate.query.sqm.function.SelfRenderingSqmFunction;
import org.hibernate.query.sqm.produce.function.ArgumentsValidator;
import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.query.sqm.tree.SqmTypedNode;
@ -35,13 +37,20 @@ public class CastStrEmulation
);
}
protected CastStrEmulation(
String name,
ArgumentsValidator argumentsValidator,
FunctionReturnTypeResolver returnTypeResolver) {
super( name, argumentsValidator, returnTypeResolver );
}
@Override
protected <T> SelfRenderingSqmFunction<T> generateSqmFunctionExpression(
List<? extends SqmTypedNode<?>> arguments,
AllowableFunctionReturnType<T> impliedResultType,
QueryEngine queryEngine,
TypeConfiguration typeConfiguration) {
SqmTypedNode<?> argument = arguments.get(0);
final SqmTypedNode<?> argument = arguments.get( 0 );
return queryEngine.getSqmFunctionRegistry().findFunctionDescriptor( "cast" )
.generateSqmExpression(
asList(

View File

@ -0,0 +1,71 @@
/*
* 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.dialect.function;
import java.util.List;
import org.hibernate.metamodel.model.domain.AllowableFunctionReturnType;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.sqm.function.FunctionRenderingSupport;
import org.hibernate.query.sqm.function.SelfRenderingSqmFunction;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.query.sqm.tree.SqmTypedNode;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.spi.TypeConfiguration;
/**
* A special function that renders to the T-SQL "str" function if more than a single argument is given,
* otherwise renders a cast expression like {@link CastStrEmulation}.
*
* @author Christian Beikov
*/
public class TransactSQLStrFunction extends CastStrEmulation implements FunctionRenderingSupport {
public TransactSQLStrFunction() {
super(
"str",
StandardArgumentsValidators.between( 1, 3 ),
StandardFunctionReturnTypeResolvers.invariant( StandardBasicTypes.STRING )
);
}
@Override
protected <T> SelfRenderingSqmFunction<T> generateSqmFunctionExpression(
List<? extends SqmTypedNode<?>> arguments,
AllowableFunctionReturnType<T> impliedResultType,
QueryEngine queryEngine,
TypeConfiguration typeConfiguration) {
if ( arguments.size() == 1 ) {
return super.generateSqmFunctionExpression( arguments, impliedResultType, queryEngine, typeConfiguration );
}
return new SelfRenderingSqmFunction<>(
this,
this,
arguments,
impliedResultType,
getReturnTypeResolver(),
queryEngine.getCriteriaBuilder(),
getName()
);
}
@Override
public void render(SqlAppender sqlAppender, List<SqlAstNode> arguments, SqlAstTranslator<?> walker) {
sqlAppender.appendSql( "str(" );
arguments.get( 0 ).accept( walker );
for ( int i = 1; i < arguments.size(); i++ ) {
sqlAppender.appendSql( ", " );
arguments.get( i ).accept( walker );
}
sqlAppender.appendSql( ')' );
}
}