Skip to content

Commit b9274f5

Browse files
jrenaatbeikov
authored andcommitted
HHH-18765 - additional fix needed for the generic array_to_string function
Signed-off-by: Jan Schatteman <[email protected]>
1 parent 7e1a740 commit b9274f5

16 files changed

+121
-44
lines changed

hibernate-core/src/main/java/org/hibernate/dialect/function/array/ArrayToStringFunction.java

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
import org.hibernate.sql.ast.SqlAstTranslator;
1717
import org.hibernate.sql.ast.spi.SqlAppender;
1818
import org.hibernate.sql.ast.tree.SqlAstNode;
19+
import org.hibernate.sql.ast.tree.expression.Expression;
20+
import org.hibernate.type.BasicPluralType;
21+
import org.hibernate.type.SqlTypes;
1922
import org.hibernate.type.StandardBasicTypes;
2023
import org.hibernate.type.spi.TypeConfiguration;
2124

@@ -32,8 +35,7 @@ public ArrayToStringFunction(TypeConfiguration typeConfiguration) {
3235
"array_to_string",
3336
FunctionKind.NORMAL,
3437
StandardArgumentsValidators.composite(
35-
new ArgumentTypesValidator( StandardArgumentsValidators.between( 2, 3 ), ANY, STRING, ANY ),
36-
new ArrayAndElementArgumentValidator( 0, 2 )
38+
new ArgumentTypesValidator( StandardArgumentsValidators.between( 2, 3 ), ANY, STRING, ANY )
3739
),
3840
StandardFunctionReturnTypeResolvers.invariant(
3941
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING )
@@ -51,15 +53,42 @@ public void render(
5153
List<? extends SqlAstNode> sqlAstArguments,
5254
ReturnableType<?> returnType,
5355
SqlAstTranslator<?> walker) {
54-
sqlAppender.appendSql( "array_to_string(" );
55-
sqlAstArguments.get( 0 ).accept( walker );
56-
sqlAppender.appendSql( ',' );
57-
sqlAstArguments.get( 1 ).accept( walker );
58-
if ( sqlAstArguments.size() > 2 ) {
56+
final Expression arrayExpression = (Expression) sqlAstArguments.get( 0 );
57+
final Expression separatorExpression = (Expression) sqlAstArguments.get( 1 );
58+
final Expression defaultExpression = sqlAstArguments.size() > 2 ? (Expression) sqlAstArguments.get( 2 ) : null;
59+
final BasicPluralType<?, ?> pluralType = (BasicPluralType<?, ?>) arrayExpression.getExpressionType().getSingleJdbcMapping();
60+
final int ddlTypeCode = pluralType.getElementType().getJdbcType().getDdlTypeCode();
61+
if ( ddlTypeCode == SqlTypes.BOOLEAN ) {
62+
// For some reason, PostgreSQL turns true/false to t/f in this function, so unnest this manually
63+
sqlAppender.append( "case when " );
64+
arrayExpression.accept( walker );
65+
sqlAppender.append( " is not null then coalesce((select string_agg(" );
66+
if ( defaultExpression != null ) {
67+
sqlAppender.append( "coalesce(" );
68+
}
69+
sqlAppender.append( "cast(t.v as varchar)" );
70+
if ( defaultExpression != null ) {
71+
sqlAppender.append( "," );
72+
defaultExpression.accept( walker );
73+
sqlAppender.append( ")" );
74+
}
5975
sqlAppender.appendSql( ',' );
60-
sqlAstArguments.get( 2 ).accept( walker );
76+
separatorExpression.accept( walker );
77+
sqlAppender.append( " order by t.i) from unnest(");
78+
arrayExpression.accept( walker );
79+
sqlAppender.append(") with ordinality t(v,i)),'') end" );
80+
}
81+
else {
82+
sqlAppender.appendSql( "array_to_string(" );
83+
arrayExpression.accept( walker );
84+
sqlAppender.appendSql( ',' );
85+
separatorExpression.accept( walker );
86+
if ( defaultExpression != null ) {
87+
sqlAppender.appendSql( ',' );
88+
defaultExpression.accept( walker );
89+
}
90+
sqlAppender.appendSql( ')' );
6191
}
62-
sqlAppender.appendSql( ')' );
6392
}
6493

6594
}

hibernate-core/src/main/java/org/hibernate/dialect/function/array/H2ArrayToStringFunction.java

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
import org.hibernate.sql.ast.spi.SqlAppender;
1212
import org.hibernate.sql.ast.tree.SqlAstNode;
1313
import org.hibernate.sql.ast.tree.expression.Expression;
14+
import org.hibernate.type.BasicPluralType;
15+
import org.hibernate.type.SqlTypes;
1416
import org.hibernate.type.spi.TypeConfiguration;
1517

1618
/**
@@ -36,19 +38,35 @@ public void render(
3638
final Expression arrayExpression = (Expression) sqlAstArguments.get( 0 );
3739
final Expression separatorExpression = (Expression) sqlAstArguments.get( 1 );
3840
final Expression defaultExpression = sqlAstArguments.size() > 2 ? (Expression) sqlAstArguments.get( 2 ) : null;
41+
final BasicPluralType<?, ?> pluralType = (BasicPluralType<?, ?>) arrayExpression.getExpressionType().getSingleJdbcMapping();
42+
final int ddlTypeCode = pluralType.getElementType().getJdbcType().getDdlTypeCode();
43+
final boolean needsCast = !SqlTypes.isStringType( ddlTypeCode );
3944
sqlAppender.append( "case when " );
4045
arrayExpression.accept( walker );
4146
sqlAppender.append( " is not null then coalesce((select listagg(" );
4247
if ( defaultExpression != null ) {
4348
sqlAppender.append( "coalesce(" );
4449
}
50+
if ( needsCast ) {
51+
if ( ddlTypeCode == SqlTypes.BOOLEAN ) {
52+
// By default, H2 uses upper case, so lower it for a consistent experience
53+
sqlAppender.append( "lower(" );
54+
}
55+
sqlAppender.append( "cast(" );
56+
}
4557
sqlAppender.append( "array_get(" );
4658
arrayExpression.accept( walker );
4759
sqlAppender.append(",i.idx)" );
60+
if ( needsCast ) {
61+
sqlAppender.append( " as varchar)" );
62+
if ( ddlTypeCode == SqlTypes.BOOLEAN ) {
63+
sqlAppender.append( ')' );
64+
}
65+
}
4866
if ( defaultExpression != null ) {
49-
sqlAppender.append( "," );
67+
sqlAppender.append( ',' );
5068
defaultExpression.accept( walker );
51-
sqlAppender.append( ")" );
69+
sqlAppender.append( ')' );
5270
}
5371
sqlAppender.append("," );
5472
separatorExpression.accept( walker );

hibernate-core/src/main/java/org/hibernate/dialect/function/array/HSQLArrayToStringFunction.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
import org.hibernate.sql.ast.spi.SqlAppender;
1313
import org.hibernate.sql.ast.tree.SqlAstNode;
1414
import org.hibernate.sql.ast.tree.expression.Expression;
15+
import org.hibernate.type.BasicPluralType;
16+
import org.hibernate.type.SqlTypes;
1517
import org.hibernate.type.spi.TypeConfiguration;
1618

1719
/**
@@ -32,13 +34,29 @@ public void render(
3234
final Expression arrayExpression = (Expression) sqlAstArguments.get( 0 );
3335
final Expression separatorExpression = (Expression) sqlAstArguments.get( 1 );
3436
final Expression defaultExpression = sqlAstArguments.size() > 2 ? (Expression) sqlAstArguments.get( 2 ) : null;
37+
final BasicPluralType<?, ?> pluralType = (BasicPluralType<?, ?>) arrayExpression.getExpressionType().getSingleJdbcMapping();
38+
final int ddlTypeCode = pluralType.getElementType().getJdbcType().getDdlTypeCode();
39+
final boolean needsCast = !SqlTypes.isStringType( ddlTypeCode );
3540
sqlAppender.append( "case when " );
3641
arrayExpression.accept( walker );
3742
sqlAppender.append( " is not null then coalesce((select group_concat(" );
3843
if ( defaultExpression != null ) {
3944
sqlAppender.append( "coalesce(" );
4045
}
46+
if ( needsCast ) {
47+
if ( ddlTypeCode == SqlTypes.BOOLEAN ) {
48+
// By default, HSQLDB uses upper case, so lower it for a consistent experience
49+
sqlAppender.append( "lower(" );
50+
}
51+
sqlAppender.append( "cast(" );
52+
}
4153
sqlAppender.append( "t.val" );
54+
if ( needsCast ) {
55+
sqlAppender.append( " as longvarchar)" );
56+
if ( ddlTypeCode == SqlTypes.BOOLEAN ) {
57+
sqlAppender.append( ')' );
58+
}
59+
}
4260
if ( defaultExpression != null ) {
4361
sqlAppender.append( "," );
4462
defaultExpression.accept( walker );

hibernate-core/src/main/java/org/hibernate/query/results/internal/ResultsHelper.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,12 @@
44
*/
55
package org.hibernate.query.results.internal;
66

7-
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
87
import org.hibernate.metamodel.mapping.ModelPart;
98
import org.hibernate.metamodel.mapping.SelectableMapping;
109
import org.hibernate.metamodel.mapping.internal.SingleAttributeIdentifierMapping;
11-
import org.hibernate.spi.EntityIdentifierNavigablePath;
1210
import org.hibernate.sql.ast.tree.expression.Expression;
13-
import org.hibernate.sql.ast.tree.from.TableGroup;
1411
import org.hibernate.sql.ast.tree.from.TableReference;
15-
import org.hibernate.sql.results.graph.DomainResult;
1612
import org.hibernate.sql.results.graph.DomainResultCreationState;
17-
import org.hibernate.sql.results.graph.Fetch;
18-
import org.hibernate.sql.results.graph.basic.BasicFetch;
1913
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
2014

2115
import static org.hibernate.sql.ast.spi.SqlExpressionResolver.createColumnReferenceKey;

hibernate-core/src/main/java/org/hibernate/query/results/internal/complete/CompleteFetchBuilderEmbeddableValuedModelPart.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,7 @@
1313
import org.hibernate.query.results.FetchBuilder;
1414
import org.hibernate.query.results.internal.ResultsHelper;
1515
import org.hibernate.spi.NavigablePath;
16-
import org.hibernate.sql.ast.spi.SqlSelection;
1716
import org.hibernate.sql.ast.tree.from.TableGroup;
18-
import org.hibernate.sql.ast.tree.from.TableReference;
1917
import org.hibernate.sql.results.graph.DomainResultCreationState;
2018
import org.hibernate.sql.results.graph.Fetch;
2119
import org.hibernate.sql.results.graph.FetchParent;

hibernate-core/src/main/java/org/hibernate/query/results/internal/complete/CompleteFetchBuilderEntityValuedModelPart.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,7 @@
1313
import org.hibernate.spi.NavigablePath;
1414
import org.hibernate.query.results.internal.DomainResultCreationStateImpl;
1515
import org.hibernate.query.results.FetchBuilder;
16-
import org.hibernate.sql.ast.spi.SqlSelection;
1716
import org.hibernate.sql.ast.tree.from.TableGroup;
18-
import org.hibernate.sql.ast.tree.from.TableReference;
1917
import org.hibernate.sql.results.graph.DomainResultCreationState;
2018
import org.hibernate.sql.results.graph.Fetch;
2119
import org.hibernate.sql.results.graph.FetchParent;

hibernate-core/src/main/java/org/hibernate/query/results/internal/complete/CompleteResultBuilderBasicModelPart.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
import org.hibernate.query.results.internal.ResultsHelper;
1111
import org.hibernate.spi.NavigablePath;
1212
import org.hibernate.sql.ast.spi.SqlSelection;
13-
import org.hibernate.sql.ast.tree.from.TableGroup;
1413
import org.hibernate.sql.ast.tree.from.TableReference;
1514
import org.hibernate.sql.results.graph.DomainResultCreationState;
1615
import org.hibernate.sql.results.graph.basic.BasicResult;

hibernate-core/src/main/java/org/hibernate/query/results/internal/complete/CompleteResultBuilderBasicValuedStandard.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
import org.hibernate.engine.spi.SessionFactoryImplementor;
88
import org.hibernate.metamodel.mapping.BasicValuedMapping;
9-
import org.hibernate.metamodel.mapping.JdbcMapping;
109
import org.hibernate.query.results.ResultBuilder;
1110
import org.hibernate.query.results.internal.DomainResultCreationStateImpl;
1211
import org.hibernate.query.results.internal.ResultSetMappingSqlSelection;

hibernate-core/src/main/java/org/hibernate/query/results/internal/complete/CompleteResultBuilderCollectionStandard.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
*/
55
package org.hibernate.query.results.internal.complete;
66

7-
import org.hibernate.engine.spi.SessionFactoryImplementor;
87
import org.hibernate.metamodel.mapping.EntityMappingType;
98
import org.hibernate.metamodel.mapping.EntityValuedModelPart;
109
import org.hibernate.metamodel.mapping.ModelPart;

hibernate-core/src/main/java/org/hibernate/query/results/internal/complete/EntityResultImpl.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
import org.hibernate.spi.NavigablePath;
1515
import org.hibernate.sql.ast.spi.SqlAstCreationState;
1616
import org.hibernate.sql.results.graph.AssemblerCreationState;
17-
import org.hibernate.sql.results.graph.DomainResultAssembler;
1817
import org.hibernate.sql.results.graph.DomainResultCreationState;
1918
import org.hibernate.sql.results.graph.Fetch;
2019
import org.hibernate.sql.results.graph.Fetchable;

0 commit comments

Comments
 (0)