Skip to content

Commit e7bc66e

Browse files
committed
HHH-9952 Formula in join columns lead to several errors
1 parent 777cef6 commit e7bc66e

File tree

7 files changed

+51
-66
lines changed

7 files changed

+51
-66
lines changed

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

Lines changed: 1 addition & 39 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;
@@ -64,7 +62,7 @@ private void mutateRowValueConstructorSyntax(int operandColumnSpan) {
6462
setType( expansionConnectorType );
6563
setText( expansionConnectorText );
6664

67-
String[] mutationTexts = extractMutationTexts( getOperand(), operandColumnSpan );
65+
String[] mutationTexts = BinaryLogicOperatorNode.extractMutationTexts( getOperand(), operandColumnSpan );
6866

6967
AST container = this;
7068
for ( int i = operandColumnSpan - 1; i > 0; i-- ) {
@@ -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/BinaryLogicOperatorNode.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ else if ( operand instanceof SqlNode ) {
263263
if ( nodeText.endsWith( ")" ) ) {
264264
nodeText = nodeText.substring( 0, nodeText.length() - 1 );
265265
}
266-
String[] splits = StringHelper.split( ", ", nodeText );
266+
String[] splits = StringHelper.split( ",", nodeText );
267267
if ( count != splits.length ) {
268268
throw new HibernateException( "SqlNode's text did not reference expected number of columns" );
269269
}

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: 20 additions & 4 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

@@ -2821,7 +2822,23 @@ else if ( isAllOrDirtyOptLocking() && oldFields != null ) {
28212822
String[] propertyColumnWriters = getPropertyColumnWriters( i );
28222823
boolean[] propertyNullness = types[i].toColumnNullness( oldFields[i], getFactory() );
28232824
for ( int k = 0; k < propertyNullness.length; k++ ) {
2824-
if ( propertyNullness[k] ) {
2825+
if ( propertyColumnNames[k] == null && propertyColumnFormulaTemplates[k] != null ) {
2826+
String formula = StringHelper.replace(
2827+
propertyColumnFormulaTemplates[k][i],
2828+
Template.TEMPLATE + ".",
2829+
""
2830+
);
2831+
if ( propertyNullness[k] ) {
2832+
update.addWhereColumn(
2833+
formula,
2834+
"=" + ( propertyColumnWriters[k] == null ? "?" : propertyColumnWriters[k] )
2835+
);
2836+
}
2837+
else {
2838+
update.addWhereColumn( formula, " is null" );
2839+
}
2840+
}
2841+
else if ( propertyNullness[k] ) {
28252842
update.addWhereColumn( propertyColumnNames[k], "=" + propertyColumnWriters[k] );
28262843
}
28272844
else {
@@ -2830,7 +2847,6 @@ else if ( isAllOrDirtyOptLocking() && oldFields != null ) {
28302847
}
28312848
}
28322849
}
2833-
28342850
}
28352851

28362852
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)