Skip to content

Commit cb9fe0c

Browse files
committed
HHH-9952 Formula in join columns lead to several errors
1 parent 5c924a2 commit cb9fe0c

File tree

8 files changed

+97
-105
lines changed

8 files changed

+97
-105
lines changed

hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/AbstractNullnessCheckNode.java

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,8 @@
66
*/
77
package org.hibernate.hql.internal.ast.tree;
88

9-
import org.hibernate.HibernateException;
109
import org.hibernate.engine.spi.SessionFactoryImplementor;
1110
import org.hibernate.hql.internal.antlr.HqlSqlTokenTypes;
12-
import org.hibernate.internal.util.StringHelper;
1311
import org.hibernate.type.Type;
1412

1513
import antlr.collections.AST;
@@ -102,40 +100,4 @@ private static Type extractDataType(Node operand) {
102100
return null;
103101
}
104102

105-
private static String[] extractMutationTexts(Node operand, int count) {
106-
if ( operand instanceof ParameterNode ) {
107-
String[] rtn = new String[count];
108-
for ( int i = 0; i < count; i++ ) {
109-
rtn[i] = "?";
110-
}
111-
return rtn;
112-
}
113-
else if ( operand.getType() == HqlSqlTokenTypes.VECTOR_EXPR ) {
114-
final String[] rtn = new String[ operand.getNumberOfChildren() ];
115-
AST node = operand.getFirstChild();
116-
int x = 0;
117-
while ( node != null ) {
118-
rtn[ x++ ] = node.getText();
119-
node = node.getNextSibling();
120-
}
121-
return rtn;
122-
}
123-
else if ( operand instanceof SqlNode ) {
124-
String nodeText = operand.getText();
125-
if ( nodeText.startsWith( "(" ) ) {
126-
nodeText = nodeText.substring( 1 );
127-
}
128-
if ( nodeText.endsWith( ")" ) ) {
129-
nodeText = nodeText.substring( 0, nodeText.length() - 1 );
130-
}
131-
String[] splits = StringHelper.split( ", ", nodeText );
132-
if ( count != splits.length ) {
133-
throw new HibernateException( "SqlNode's text did not reference expected number of columns" );
134-
}
135-
return splits;
136-
}
137-
else {
138-
throw new HibernateException( "don't know how to extract row value elements from node : " + operand );
139-
}
140-
}
141103
}

hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/AbstractSelectExpression.java

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,15 @@
66
*/
77
package org.hibernate.hql.internal.ast.tree;
88

9+
import java.util.Arrays;
10+
11+
import org.hibernate.HibernateException;
12+
import org.hibernate.hql.internal.antlr.HqlSqlTokenTypes;
13+
import org.hibernate.internal.util.StringHelper;
914
import org.hibernate.type.Type;
1015

1116
import antlr.SemanticException;
17+
import antlr.collections.AST;
1218

1319
/**
1420
* Partial implementation of SelectExpression for all the nodes that aren't constructors.
@@ -55,4 +61,40 @@ public void setScalarColumn(int i) throws SemanticException {
5561
public int getScalarColumnIndex() {
5662
return scalarColumnIndex;
5763
}
64+
65+
protected static String[] extractMutationTexts(Node operand, int count) {
66+
if ( operand instanceof ParameterNode ) {
67+
String[] rtn = new String[count];
68+
Arrays.fill( rtn, "?" );
69+
return rtn;
70+
}
71+
else if ( operand.getType() == HqlSqlTokenTypes.VECTOR_EXPR ) {
72+
String[] rtn = new String[operand.getNumberOfChildren()];
73+
int x = 0;
74+
AST node = operand.getFirstChild();
75+
while ( node != null ) {
76+
rtn[x++] = node.getText();
77+
node = node.getNextSibling();
78+
}
79+
return rtn;
80+
}
81+
else if ( operand instanceof SqlNode ) {
82+
String nodeText = operand.getText();
83+
if ( nodeText.startsWith( "(" ) ) {
84+
nodeText = nodeText.substring( 1 );
85+
}
86+
if ( nodeText.endsWith( ")" ) ) {
87+
nodeText = nodeText.substring( 0, nodeText.length() - 1 );
88+
}
89+
String[] splits = StringHelper.split( ",", nodeText );
90+
if ( count != splits.length ) {
91+
throw new HibernateException( "SqlNode's text did not reference expected number of columns" );
92+
}
93+
return splits;
94+
}
95+
else {
96+
throw new HibernateException( "dont know how to extract row value elements from node : " + operand );
97+
}
98+
}
99+
58100
}

hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/BinaryLogicOperatorNode.java

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,12 @@
66
*/
77
package org.hibernate.hql.internal.ast.tree;
88

9-
import java.util.Arrays;
10-
11-
import org.hibernate.HibernateException;
129
import org.hibernate.TypeMismatchException;
1310
import org.hibernate.dialect.Dialect;
1411
import org.hibernate.engine.spi.SessionFactoryImplementor;
1512
import org.hibernate.hql.internal.antlr.HqlSqlTokenTypes;
1613
import org.hibernate.hql.internal.ast.QuerySyntaxException;
1714
import org.hibernate.hql.internal.ast.util.ColumnHelper;
18-
import org.hibernate.internal.util.StringHelper;
1915
import org.hibernate.param.ParameterSpecification;
2016
import org.hibernate.type.OneToOneType;
2117
import org.hibernate.type.StandardBasicTypes;
@@ -239,41 +235,6 @@ private static void copyReferencedTables(Node from, SqlFragment to) {
239235
}
240236
}
241237

242-
protected static String[] extractMutationTexts(Node operand, int count) {
243-
if ( operand instanceof ParameterNode ) {
244-
String[] rtn = new String[count];
245-
Arrays.fill( rtn, "?" );
246-
return rtn;
247-
}
248-
else if ( operand.getType() == HqlSqlTokenTypes.VECTOR_EXPR ) {
249-
String[] rtn = new String[operand.getNumberOfChildren()];
250-
int x = 0;
251-
AST node = operand.getFirstChild();
252-
while ( node != null ) {
253-
rtn[x++] = node.getText();
254-
node = node.getNextSibling();
255-
}
256-
return rtn;
257-
}
258-
else if ( operand instanceof SqlNode ) {
259-
String nodeText = operand.getText();
260-
if ( nodeText.startsWith( "(" ) ) {
261-
nodeText = nodeText.substring( 1 );
262-
}
263-
if ( nodeText.endsWith( ")" ) ) {
264-
nodeText = nodeText.substring( 0, nodeText.length() - 1 );
265-
}
266-
String[] splits = StringHelper.split( ", ", nodeText );
267-
if ( count != splits.length ) {
268-
throw new HibernateException( "SqlNode's text did not reference expected number of columns" );
269-
}
270-
return splits;
271-
}
272-
else {
273-
throw new HibernateException( "dont know how to extract row value elements from node : " + operand );
274-
}
275-
}
276-
277238
protected Type extractDataType(Node operand) {
278239
Type type = null;
279240
if ( operand instanceof SqlNode ) {

hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -637,7 +637,7 @@ public SqlValueReference[] map(String reference) {
637637
formulaTemplates = elementFormulaTemplates;
638638
}
639639
else {
640-
columnNames = elementPropertyMapping.toColumns( reference );
640+
columnNames = columnNames( reference );
641641
formulaTemplates = formulaTemplates( reference, columnNames.length );
642642
}
643643

@@ -670,6 +670,20 @@ public String getColumnName() {
670670
}
671671
}
672672

673+
private String[] columnNames(String reference) {
674+
if ( elementPersister == null ) {
675+
return elementPropertyMapping.toColumns( reference );
676+
}
677+
678+
final Integer propertyIndex = elementPersister.getEntityMetamodel().getPropertyIndexOrNull( reference );
679+
if ( propertyIndex != null ) {
680+
return ( (Queryable) elementPersister ).getSubclassPropertyColumnNameClosure()[propertyIndex];
681+
}
682+
else {
683+
return elementPropertyMapping.toColumns( reference );
684+
}
685+
}
686+
673687
private String[] formulaTemplates(String reference, int expectedSize) {
674688
try {
675689
final int propertyIndex = elementPersister.getEntityMetamodel().getPropertyIndex( reference );

hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2032,7 +2032,7 @@ public String[] toColumns(String alias, String propertyName) throws QueryExcepti
20322032
*/
20332033
@Override
20342034
public String[] toColumns(String propertyName) throws QueryException {
2035-
return propertyMapping.getColumnNames( propertyName );
2035+
return propertyMapping.toColumns( propertyName );
20362036
}
20372037

20382038
/**
@@ -2224,7 +2224,8 @@ protected Type[] getSubclassPropertyTypeClosure() {
22242224
return subclassPropertyTypeClosure;
22252225
}
22262226

2227-
protected String[][] getSubclassPropertyColumnNameClosure() {
2227+
@Override
2228+
public String[][] getSubclassPropertyColumnNameClosure() {
22282229
return subclassPropertyColumnNameClosure;
22292230
}
22302231

@@ -2820,17 +2821,36 @@ else if ( isAllOrDirtyOptLocking() && oldFields != null ) {
28202821
String[] propertyColumnNames = getPropertyColumnNames( i );
28212822
String[] propertyColumnWriters = getPropertyColumnWriters( i );
28222823
boolean[] propertyNullness = types[i].toColumnNullness( oldFields[i], getFactory() );
2824+
String[] propertyColumnFormulaTemplates = this.propertyColumnFormulaTemplates[i];
28232825
for ( int k = 0; k < propertyNullness.length; k++ ) {
2824-
if ( propertyNullness[k] ) {
2825-
update.addWhereColumn( propertyColumnNames[k], "=" + propertyColumnWriters[k] );
2826+
final String propertyColumnFormulaTemplate = propertyColumnFormulaTemplates[k];
2827+
final String propertyColumnName = propertyColumnNames[k];
2828+
if ( propertyColumnName == null && propertyColumnFormulaTemplate != null ) {
2829+
final String formula = StringHelper.replace(
2830+
propertyColumnFormulaTemplate,
2831+
Template.TEMPLATE + ".",
2832+
""
2833+
);
2834+
if ( propertyNullness[k] ) {
2835+
final String propertyColumnWriter = propertyColumnWriters[k];
2836+
update.addWhereColumn(
2837+
formula,
2838+
"=" + ( propertyColumnWriter == null ? "?" : propertyColumnWriter )
2839+
);
2840+
}
2841+
else {
2842+
update.addWhereColumn( formula, " is null" );
2843+
}
2844+
}
2845+
else if ( propertyNullness[k] ) {
2846+
update.addWhereColumn( propertyColumnName, "=" + propertyColumnWriters[k] );
28262847
}
28272848
else {
2828-
update.addWhereColumn( propertyColumnNames[k], " is null" );
2849+
update.addWhereColumn( propertyColumnName, " is null" );
28292850
}
28302851
}
28312852
}
28322853
}
2833-
28342854
}
28352855

28362856
if ( getFactory().getSessionFactoryOptions().isCommentsEnabled() ) {

hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractPropertyMapping.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ public String[] toColumns(String propertyName) throws QueryException {
115115
String[] result = new String[columns.length];
116116
for ( int i = 0; i < columns.length; i++ ) {
117117
if ( columnReaders[i] == null ) {
118-
result[i] = StringHelper.replace( formulaTemplates[i], Template.TEMPLATE, "" );
118+
result[i] = StringHelper.replace( formulaTemplates[i], Template.TEMPLATE + ".", "" );
119119
}
120120
else {
121121
result[i] = columnReaders[i];

hibernate-core/src/main/java/org/hibernate/persister/entity/Queryable.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,8 @@ public interface Queryable extends Loadable, PropertyMapping, Joinable {
138138

139139
String[][] getSubclassPropertyFormulaTemplateClosure();
140140

141+
String[][] getSubclassPropertyColumnNameClosure();
142+
141143
public static class Declarer {
142144
public static final Declarer CLASS = new Declarer( "class" );
143145
public static final Declarer SUBCLASS = new Declarer( "subclass" );

hibernate-core/src/test/java/org/hibernate/test/formulajoin/AssociationFormulaTest.java

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
import org.hibernate.testing.TestForIssue;
1212
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
13+
import org.junit.After;
1314
import org.junit.Before;
1415
import org.junit.Ignore;
1516
import org.junit.Test;
@@ -27,11 +28,6 @@ public AssociationFormulaTest() {
2728
super();
2829
}
2930

30-
@Override
31-
protected boolean isCleanupTestDataRequired() {
32-
return true;
33-
}
34-
3531
@Override
3632
protected boolean rebuildSessionFactoryOnError() {
3733
return true;
@@ -61,6 +57,16 @@ public void fillDb() {
6157
);
6258
}
6359

60+
@After
61+
public void tearDown() {
62+
inTransaction(
63+
session -> {
64+
session.createQuery( "delete from Entity" ).executeUpdate();
65+
session.createQuery( "delete from OtherEntity" ).executeUpdate();
66+
}
67+
);
68+
}
69+
6470
@Test
6571
public void testJoin() {
6672

@@ -219,21 +225,6 @@ public void testDeleteHql() {
219225
);
220226
}
221227

222-
@Test
223-
public void testDeleteHqlNull() {
224-
inTransaction(
225-
session -> {
226-
assertEquals(
227-
"execute",
228-
1,
229-
session.createQuery( "delete Entity e where e.other is null" ).executeUpdate()
230-
);
231-
Entity loaded = (Entity) session.createQuery( "from Entity e where e.id.id = 3" ).uniqueResult();
232-
assertNull( "loaded", loaded );
233-
}
234-
);
235-
}
236-
237228
@Test
238229
public void testPersist() {
239230
inTransaction(

0 commit comments

Comments
 (0)