Skip to content

Commit 904e540

Browse files
committed
HHH-18860 Store SelectableMapping in ColumnWriteFragment to allow precise parameter casts
1 parent 4e9f872 commit 904e540

28 files changed

+366
-335
lines changed

hibernate-core/src/main/java/org/hibernate/metamodel/mapping/SelectableConsumer.java

Lines changed: 145 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package org.hibernate.metamodel.mapping;
66

77
import org.checkerframework.checker.nullness.qual.Nullable;
8+
import org.hibernate.engine.jdbc.Size;
89

910
import java.util.function.BiConsumer;
1011
import java.util.function.IntFunction;
@@ -27,7 +28,7 @@ public interface SelectableConsumer {
2728

2829
/**
2930
* Simple form of visitation over a number of columns by name, using
30-
* a separate {@link SelectableMappings} as a base for additional details.
31+
* a separate {@link JdbcMappingContainer} as a base for additional details.
3132
* <p>
3233
* Intended for use in visiting table keys, where we know JdbcMappings, etc.
3334
* from the identifier.
@@ -46,6 +47,149 @@ default void accept(String tableName, JdbcMappingContainer base, String[] column
4647
mutableSelectableMapping.forEach( this::accept );
4748
}
4849

50+
/**
51+
* Simple form of visitation over a number of columns by name, using
52+
* a separate {@link SelectableMappings} as a base for additional details.
53+
* <p>
54+
* Intended for use in visiting table keys, where we know JdbcMappings, etc.
55+
* from the identifier.
56+
* <p>
57+
* The expectation here is for the following details to be available:<ul>
58+
* <li>{@link SelectableMapping#getContainingTableExpression()}</li>
59+
* <li>{@link SelectableMapping#getSelectionExpression()} (the column name)</li>
60+
* <li>{@link SelectableMapping#getWriteExpression()}</li>
61+
* <li>{@link SelectableMapping#getJdbcMapping()}</li>
62+
* </ul>
63+
*/
64+
default void accept(SelectableMappings base, String tableName, String[] columnNames) {
65+
class SelectableMappingIterator implements SelectableMapping {
66+
private final String tableName;
67+
private final SelectableMappings delegate;
68+
private final String[] columnNames;
69+
70+
private int index;
71+
72+
public SelectableMappingIterator(String tableName, SelectableMappings delegate, String[] columnNames) {
73+
this.tableName = tableName;
74+
this.delegate = delegate;
75+
this.columnNames = columnNames;
76+
assert delegate.getJdbcTypeCount() == columnNames.length;
77+
}
78+
79+
private void forEach(BiConsumer<Integer,SelectableMapping> consumer) {
80+
for ( index = 0; index < columnNames.length; index++ ) {
81+
consumer.accept( index, this );
82+
}
83+
}
84+
85+
@Override
86+
public String getContainingTableExpression() {
87+
return tableName;
88+
}
89+
90+
@Override
91+
public String getSelectionExpression() {
92+
return columnNames[index];
93+
}
94+
95+
@Override
96+
public @Nullable String getCustomReadExpression() {
97+
return null;
98+
}
99+
100+
@Override
101+
public @Nullable String getCustomWriteExpression() {
102+
return null;
103+
}
104+
105+
private SelectableMapping getDelegate() {
106+
return delegate.getSelectable( index );
107+
}
108+
109+
@Override
110+
public String getSelectableName() {
111+
return getDelegate().getSelectableName();
112+
}
113+
114+
@Override
115+
public SelectablePath getSelectablePath() {
116+
return getDelegate().getSelectablePath();
117+
}
118+
119+
@Override
120+
public boolean isFormula() {
121+
return getDelegate().isFormula();
122+
}
123+
124+
@Override
125+
public boolean isNullable() {
126+
return getDelegate().isNullable();
127+
}
128+
129+
@Override
130+
public boolean isInsertable() {
131+
return getDelegate().isInsertable();
132+
}
133+
134+
@Override
135+
public boolean isUpdateable() {
136+
return getDelegate().isUpdateable();
137+
}
138+
139+
@Override
140+
public boolean isPartitioned() {
141+
return getDelegate().isPartitioned();
142+
}
143+
144+
@Override
145+
public @Nullable String getColumnDefinition() {
146+
return getDelegate().getColumnDefinition();
147+
}
148+
149+
@Override
150+
public @Nullable Long getLength() {
151+
return getDelegate().getLength();
152+
}
153+
154+
@Override
155+
public @Nullable Integer getArrayLength() {
156+
return getDelegate().getArrayLength();
157+
}
158+
159+
@Override
160+
public @Nullable Integer getPrecision() {
161+
return getDelegate().getPrecision();
162+
}
163+
164+
@Override
165+
public @Nullable Integer getScale() {
166+
return getDelegate().getScale();
167+
}
168+
169+
@Override
170+
public @Nullable Integer getTemporalPrecision() {
171+
return getDelegate().getTemporalPrecision();
172+
}
173+
174+
@Override
175+
public boolean isLob() {
176+
return getDelegate().isLob();
177+
}
178+
179+
@Override
180+
public JdbcMapping getJdbcMapping() {
181+
return getDelegate().getJdbcMapping();
182+
}
183+
184+
@Override
185+
public Size toSize() {
186+
return getDelegate().toSize();
187+
}
188+
}
189+
190+
final SelectableMappingIterator mutableSelectableMapping = new SelectableMappingIterator( tableName, base, columnNames );
191+
mutableSelectableMapping.forEach( this::accept );
192+
}
49193

50194
class MutableSelectableMapping implements SelectableMapping {
51195
private final String tableName;

hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/SelectableMappingImpl.java

Lines changed: 23 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ public class SelectableMappingImpl extends SqlTypedMappingImpl implements Select
2525
private final String containingTableExpression;
2626
private final String selectionExpression;
2727
private final SelectablePath selectablePath;
28-
private final String customReadExpression;
29-
private final String customWriteExpression;
28+
private final @Nullable String customReadExpression;
29+
private final @Nullable String customWriteExpression;
3030
private final boolean isLob;
3131
private final boolean nullable;
3232
private final boolean insertable;
@@ -37,14 +37,14 @@ public class SelectableMappingImpl extends SqlTypedMappingImpl implements Select
3737
public SelectableMappingImpl(
3838
String containingTableExpression,
3939
String selectionExpression,
40-
SelectablePath selectablePath,
41-
String customReadExpression,
42-
String customWriteExpression,
43-
String columnDefinition,
44-
Long length,
45-
Integer precision,
46-
Integer scale,
47-
Integer temporalPrecision,
40+
@Nullable SelectablePath selectablePath,
41+
@Nullable String customReadExpression,
42+
@Nullable String customWriteExpression,
43+
@Nullable String columnDefinition,
44+
@Nullable Long length,
45+
@Nullable Integer precision,
46+
@Nullable Integer scale,
47+
@Nullable Integer temporalPrecision,
4848
boolean isLob,
4949
boolean nullable,
5050
boolean insertable,
@@ -77,15 +77,15 @@ public SelectableMappingImpl(
7777
public SelectableMappingImpl(
7878
String containingTableExpression,
7979
String selectionExpression,
80-
SelectablePath selectablePath,
81-
String customReadExpression,
82-
String customWriteExpression,
83-
String columnDefinition,
84-
Long length,
85-
Integer arrayLength,
86-
Integer precision,
87-
Integer scale,
88-
Integer temporalPrecision,
80+
@Nullable SelectablePath selectablePath,
81+
@Nullable String customReadExpression,
82+
@Nullable String customWriteExpression,
83+
@Nullable String columnDefinition,
84+
@Nullable Long length,
85+
@Nullable Integer arrayLength,
86+
@Nullable Integer precision,
87+
@Nullable Integer scale,
88+
@Nullable Integer temporalPrecision,
8989
boolean isLob,
9090
boolean nullable,
9191
boolean insertable,
@@ -96,7 +96,7 @@ public SelectableMappingImpl(
9696
super( columnDefinition, length, arrayLength, precision, scale, temporalPrecision, jdbcMapping );
9797
assert selectionExpression != null;
9898
// Save memory by using interned strings. Probability is high that we have multiple duplicate strings
99-
this.containingTableExpression = containingTableExpression == null ? null : containingTableExpression.intern();
99+
this.containingTableExpression = containingTableExpression.intern();
100100
this.selectionExpression = selectionExpression.intern();
101101
this.selectablePath = selectablePath == null ? new SelectablePath( selectionExpression ) : selectablePath;
102102
this.customReadExpression = customReadExpression == null ? null : customReadExpression.intern();
@@ -286,7 +286,7 @@ public String getSelectionExpression() {
286286

287287
@Override
288288
public String getSelectableName() {
289-
return selectablePath == null ? null : selectablePath.getSelectableName();
289+
return selectablePath.getSelectableName();
290290
}
291291

292292
@Override
@@ -295,17 +295,12 @@ public SelectablePath getSelectablePath() {
295295
}
296296

297297
@Override
298-
public String getCustomReadExpression() {
298+
public @Nullable String getCustomReadExpression() {
299299
return customReadExpression;
300300
}
301301

302302
@Override
303-
public String getCustomWriteExpression() {
304-
return customWriteExpression;
305-
}
306-
307-
@Override
308-
public String getWriteExpression() {
303+
public @Nullable String getCustomWriteExpression() {
309304
return customWriteExpression;
310305
}
311306

hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/SoftDeleteMappingImpl.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -210,17 +210,17 @@ public Predicate createNonDeletedRestriction(TableReference tableReference, SqlE
210210
public ColumnValueBinding createNonDeletedValueBinding(ColumnReference softDeleteColumnReference) {
211211
final var nonDeletedFragment =
212212
strategy == SoftDeleteType.TIMESTAMP
213-
? new ColumnWriteFragment( null, emptyList(), jdbcMapping )
214-
: new ColumnWriteFragment( nonDeletedLiteralText, emptyList(), jdbcMapping );
213+
? new ColumnWriteFragment( null, emptyList(), this )
214+
: new ColumnWriteFragment( nonDeletedLiteralText, emptyList(), this );
215215
return new ColumnValueBinding( softDeleteColumnReference, nonDeletedFragment );
216216
}
217217

218218
@Override
219219
public ColumnValueBinding createDeletedValueBinding(ColumnReference softDeleteColumnReference) {
220220
final ColumnWriteFragment deletedFragment =
221221
strategy == SoftDeleteType.TIMESTAMP
222-
? new ColumnWriteFragment( currentTimestampFunctionName, emptyList(), getJdbcMapping() )
223-
: new ColumnWriteFragment( deletedLiteralText, emptyList(), jdbcMapping );
222+
? new ColumnWriteFragment( currentTimestampFunctionName, emptyList(), this )
223+
: new ColumnWriteFragment( deletedLiteralText, emptyList(), this );
224224
return new ColumnValueBinding( softDeleteColumnReference, deletedFragment );
225225
}
226226

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1739,20 +1739,20 @@ protected void applyKeyRestrictions(
17391739
List<ColumnValueBinding> restrictionBindings) {
17401740
final var foreignKeyDescriptor = getAttributeMapping().getKeyDescriptor();
17411741
assert foreignKeyDescriptor != null;
1742-
foreignKeyDescriptor.getKeyPart().forEachSelectable( parameterList );
1743-
for ( var columnValueParameter : parameterList ) {
1742+
foreignKeyDescriptor.getKeyPart().forEachSelectable( (selectionIndex, selectableMapping) -> {
1743+
final var columnValueParameter = parameterList.addColumValueParameter( selectableMapping );
17441744
final var columnReference = columnValueParameter.getColumnReference();
17451745
restrictionBindings.add(
17461746
new ColumnValueBinding(
17471747
columnReference,
17481748
new ColumnWriteFragment(
17491749
"?",
17501750
columnValueParameter,
1751-
columnReference.getJdbcMapping()
1751+
selectableMapping
17521752
)
17531753
)
17541754
);
1755-
}
1755+
});
17561756
}
17571757

17581758

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

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -296,34 +296,34 @@ public RestrictedTableMutation<JdbcMutationOperation> generateDeleteAllAst(Mutat
296296
new ColumnValueParameterList( tableReference, ParameterUsage.RESTRICT, keyColumnCount );
297297
final List<ColumnValueBinding> keyRestrictionBindings = arrayList( keyColumnCount );
298298
final List<ColumnValueBinding> valueBindings = arrayList( valuesCount );
299-
foreignKeyDescriptor.getKeyPart().forEachSelectable( parameterBinders );
300-
for ( var columnValueParameter : parameterBinders ) {
299+
foreignKeyDescriptor.getKeyPart().forEachSelectable( (selectionIndex, selectableMapping) -> {
300+
final var columnValueParameter = parameterBinders.addColumValueParameter( selectableMapping );
301301
final var columnReference = columnValueParameter.getColumnReference();
302302
keyRestrictionBindings.add(
303303
new ColumnValueBinding(
304304
columnReference,
305305
new ColumnWriteFragment(
306306
"?",
307307
columnValueParameter,
308-
columnReference.getJdbcMapping()
308+
selectableMapping
309309
)
310310
)
311311
);
312312
valueBindings.add(
313313
new ColumnValueBinding(
314314
columnReference,
315-
new ColumnWriteFragment( "null", columnReference.getJdbcMapping() )
315+
new ColumnWriteFragment( "null", selectableMapping )
316316
)
317317
);
318-
}
318+
} );
319319

320320
if ( hasIndex() && !indexContainsFormula ) {
321321
attributeMapping.getIndexDescriptor().forEachSelectable( (selectionIndex, selectableMapping) -> {
322322
if ( selectableMapping.isUpdateable() ) {
323323
valueBindings.add(
324324
new ColumnValueBinding(
325325
new ColumnReference( tableReference, selectableMapping ),
326-
new ColumnWriteFragment( "null", selectableMapping.getJdbcMapping() )
326+
new ColumnWriteFragment( "null", selectableMapping )
327327
)
328328
);
329329
}
@@ -484,10 +484,8 @@ public RestrictedTableMutation<JdbcMutationOperation> generateDeleteRowAst(Mutat
484484
if ( selectable.isUpdateable() ) {
485485
// set null
486486
updateBuilder.addValueColumn(
487-
selectable.getSelectionExpression(),
488487
NULL,
489-
selectable.getJdbcMapping(),
490-
selectable.isLob()
488+
selectable
491489
);
492490
}
493491
// restrict
@@ -504,10 +502,8 @@ public RestrictedTableMutation<JdbcMutationOperation> generateDeleteRowAst(Mutat
504502
final var selectable = indexDescriptor.getSelectable( i );
505503
if ( selectable.isUpdateable() ) {
506504
updateBuilder.addValueColumn(
507-
selectable.getSelectionExpression(),
508505
NULL,
509-
selectable.getJdbcMapping(),
510-
selectable.isLob()
506+
selectable
511507
);
512508
}
513509
}

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

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3356,10 +3356,7 @@ protected EntityTableMapping[] buildTableMappings() {
33563356
.accept( (selectionIndex, selectableMapping) -> {
33573357
keyColumns.add( new EntityTableMapping.KeyColumn(
33583358
tableExpression,
3359-
selectableMapping.getSelectionExpression(),
3360-
selectableMapping.getWriteExpression(),
3361-
selectableMapping.isFormula(),
3362-
selectableMapping.getJdbcMapping()
3359+
selectableMapping
33633360
) );
33643361
} );
33653362

0 commit comments

Comments
 (0)