Skip to content

Commit 7f0f0be

Browse files
cigalygavinking
authored andcommitted
HHH-18708 Implemented StringFunction as copy of OrdinalFunction with slight changes
1 parent fa2e481 commit 7f0f0be

File tree

2 files changed

+94
-0
lines changed

2 files changed

+94
-0
lines changed

hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import org.hibernate.dialect.function.LpadRpadPadEmulation;
3737
import org.hibernate.dialect.function.OrdinalFunction;
3838
import org.hibernate.dialect.function.SqlFunction;
39+
import org.hibernate.dialect.function.StringFunction;
3940
import org.hibernate.dialect.function.TrimFunction;
4041
import org.hibernate.dialect.identity.IdentityColumnSupport;
4142
import org.hibernate.dialect.identity.IdentityColumnSupportImpl;
@@ -1218,6 +1219,11 @@ public void initializeFunctionRegistry(FunctionContributions functionContributio
12181219
functionContributions.getFunctionRegistry().register( "ordinal",
12191220
new OrdinalFunction( typeConfiguration ) );
12201221

1222+
// Function to convert enum mapped as String to their string value
1223+
1224+
functionContributions.getFunctionRegistry().register( "string",
1225+
new StringFunction( typeConfiguration ) );
1226+
12211227
//format() function for datetimes, emulated on many databases using the
12221228
//Oracle-style to_char() function, and on others using their native
12231229
//formatting functions
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.dialect.function;
6+
7+
import org.hibernate.QueryException;
8+
import org.hibernate.metamodel.mapping.JdbcMapping;
9+
import org.hibernate.metamodel.model.domain.ReturnableType;
10+
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
11+
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
12+
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
13+
import org.hibernate.sql.ast.SqlAstTranslator;
14+
import org.hibernate.sql.ast.spi.SqlAppender;
15+
import org.hibernate.sql.ast.tree.SqlAstNode;
16+
import org.hibernate.sql.ast.tree.expression.Expression;
17+
import org.hibernate.type.SqlTypes;
18+
import org.hibernate.type.StandardBasicTypes;
19+
import org.hibernate.type.descriptor.java.EnumJavaType;
20+
import org.hibernate.type.descriptor.jdbc.JdbcType;
21+
import org.hibernate.type.spi.TypeConfiguration;
22+
23+
import java.util.List;
24+
25+
import static org.hibernate.query.sqm.produce.function.FunctionParameterType.ENUM;
26+
27+
28+
/**
29+
* The HQL {@code string()} function returns the string value of an enum
30+
* <p>
31+
* For enum fields mapped as STRING or ENUM it's a synonym for {@code cast(x as String)}. Same as {@link CastStrEmulation}.
32+
* For enum fields mapped as ORDINAL it's a case statement that returns the bane if enum.
33+
*
34+
* @author Luca Molteni, Cedomir Igaly
35+
*/
36+
public class StringFunction
37+
extends AbstractSqmSelfRenderingFunctionDescriptor {
38+
39+
public StringFunction(TypeConfiguration typeConfiguration) {
40+
super(
41+
"string",
42+
new ArgumentTypesValidator( null, ENUM ),
43+
StandardFunctionReturnTypeResolvers.invariant(
44+
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING )
45+
),
46+
null
47+
);
48+
}
49+
50+
@Override
51+
public void render(
52+
SqlAppender sqlAppender,
53+
List<? extends SqlAstNode> arguments,
54+
ReturnableType<?> returnType,
55+
SqlAstTranslator<?> walker) {
56+
Expression singleExpression = (Expression) arguments.get( 0 );
57+
58+
JdbcMapping singleJdbcMapping = singleExpression.getExpressionType().getSingleJdbcMapping();
59+
JdbcType argumentType = singleJdbcMapping.getJdbcType();
60+
61+
if ( argumentType.isString() || argumentType.getDefaultSqlTypeCode() == SqlTypes.ENUM ) {
62+
singleExpression.accept( walker );
63+
}
64+
else if ( argumentType.isInteger() ) {
65+
EnumJavaType<?> enumJavaType = (EnumJavaType<?>) singleJdbcMapping.getMappedJavaType();
66+
Object[] enumConstants = enumJavaType.getJavaTypeClass().getEnumConstants();
67+
68+
sqlAppender.appendSql( "case " );
69+
singleExpression.accept( walker );
70+
for ( Object e : enumConstants ) {
71+
Enum<?> enumValue = (Enum<?>) e;
72+
sqlAppender.appendSql( " when " );
73+
sqlAppender.appendSql( enumValue.ordinal() );
74+
sqlAppender.appendSql( " then " );
75+
sqlAppender.appendSingleQuoteEscapedString( enumValue.name() );
76+
}
77+
sqlAppender.appendSql( " end" );
78+
}
79+
else {
80+
throw new QueryException( "Unsupported enum type passed to 'string()' function: " + argumentType );
81+
}
82+
}
83+
84+
@Override
85+
public String getArgumentListSignature() {
86+
return "(ENUM arg)";
87+
}
88+
}

0 commit comments

Comments
 (0)