Skip to content

Commit 7878bac

Browse files
committed
HHH-19749 honor precision/scale for Oracle merges
1 parent a5dc413 commit 7878bac

File tree

11 files changed

+305
-40
lines changed

11 files changed

+305
-40
lines changed

hibernate-core/src/main/java/org/hibernate/dialect/sql/ast/OracleSqlAstTranslator.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -765,10 +765,9 @@ protected void renderMergeSource(OptionalTableUpdate optionalTableUpdate) {
765765
appendSql( " " );
766766
appendSql( keyBinding.getColumnReference().getColumnExpression() );
767767
}
768-
for ( int i = 0; i < valueBindings.size(); i++ ) {
768+
for ( ColumnValueBinding valueBinding : valueBindings ) {
769769
appendSql( ", " );
770-
final ColumnValueBinding valueBinding = valueBindings.get( i );
771-
renderCasted( valueBinding.getValueExpression() );
770+
renderCasted( valueBinding.getValueExpression(), valueBinding.getColumnReference() );
772771
appendSql( " " );
773772
appendSql( valueBinding.getColumnReference().getColumnExpression() );
774773
}

hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5709,11 +5709,7 @@ else if ( expression instanceof CaseSearchedExpression caseSearchedExpression )
57095709
}
57105710

57115711
protected void renderCasted(Expression expression) {
5712-
if ( expression instanceof SqmParameterInterpretation parameterInterpretation ) {
5713-
expression = parameterInterpretation.getResolvedExpression();
5714-
}
5715-
final List<SqlAstNode> arguments = new ArrayList<>( 2 );
5716-
arguments.add( expression );
5712+
final var arguments = initiateArguments(expression);
57175713
final CastTarget castTarget;
57185714
if ( expression instanceof SqlTypedMappingJdbcParameter parameter ) {
57195715
final SqlTypedMapping sqlTypedMapping = parameter.getSqlTypedMapping();
@@ -5735,6 +5731,26 @@ protected void renderCasted(Expression expression) {
57355731
castFunction().render( this, arguments, (ReturnableType<?>) castTarget.getJdbcMapping(), this );
57365732
}
57375733

5734+
protected void renderCasted(Expression expression, ColumnReference columnReference) {
5735+
final var arguments = initiateArguments(expression);
5736+
final var castTarget = new CastTarget(
5737+
expression.getExpressionType().getSingleJdbcMapping(),
5738+
columnReference.getPrecision(),
5739+
columnReference.getScale()
5740+
);
5741+
arguments.add( castTarget );
5742+
castFunction().render( this, arguments, (ReturnableType<?>) castTarget.getJdbcMapping(), this );
5743+
}
5744+
5745+
private static List<SqlAstNode> initiateArguments(Expression expression) {
5746+
if ( expression instanceof SqmParameterInterpretation parameterInterpretation ) {
5747+
expression = parameterInterpretation.getResolvedExpression();
5748+
}
5749+
final List<SqlAstNode> arguments = new ArrayList<>( 2 );
5750+
arguments.add( expression );
5751+
return arguments;
5752+
}
5753+
57385754
@SuppressWarnings("unchecked")
57395755
protected void renderLiteral(Literal literal, boolean castParameter) {
57405756
assert literal.getExpressionType().getJdbcTypeCount() == 1;

hibernate-core/src/main/java/org/hibernate/sql/ast/tree/expression/CastTarget.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ public CastTarget(JdbcMapping type) {
2626
this( type, null, null, null, null, null );
2727
}
2828

29+
public CastTarget(JdbcMapping type, Integer precision, Integer scale) {
30+
this( type, null, null, null, precision, scale );
31+
}
32+
2933
public CastTarget(JdbcMapping type, @Nullable Long length, @Nullable Integer precision, @Nullable Integer scale) {
3034
this( type, null, length, precision, scale );
3135
}

hibernate-core/src/main/java/org/hibernate/sql/ast/tree/expression/ColumnReference.java

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ public class ColumnReference implements Expression, Assignable {
3939
private final boolean isFormula;
4040
private final @Nullable String readExpression;
4141
private final JdbcMapping jdbcMapping;
42+
private final @Nullable Integer precision;
43+
private final @Nullable Integer scale;
4244

4345
public ColumnReference(TableReference tableReference, SelectableMapping selectableMapping) {
4446
this(
@@ -47,7 +49,9 @@ public ColumnReference(TableReference tableReference, SelectableMapping selectab
4749
selectableMapping.getSelectablePath(),
4850
selectableMapping.isFormula(),
4951
selectableMapping.getCustomReadExpression(),
50-
selectableMapping.getJdbcMapping()
52+
selectableMapping.getJdbcMapping(),
53+
selectableMapping.getPrecision(),
54+
selectableMapping.getScale()
5155
);
5256
}
5357

@@ -58,7 +62,22 @@ public ColumnReference(TableReference tableReference, String mapping, JdbcMappin
5862
null,
5963
false,
6064
null,
61-
jdbcMapping
65+
jdbcMapping,
66+
null,
67+
null
68+
);
69+
}
70+
71+
public ColumnReference(TableReference tableReference, String mapping, JdbcMapping jdbcMapping, Integer precision, Integer scale) {
72+
this(
73+
tableReference.getIdentificationVariable(),
74+
mapping,
75+
null,
76+
false,
77+
null,
78+
jdbcMapping,
79+
precision,
80+
scale
6281
);
6382
}
6483

@@ -69,7 +88,9 @@ public ColumnReference(@Nullable String qualifier, SelectableMapping selectableM
6988
selectableMapping.getSelectablePath(),
7089
selectableMapping.isFormula(),
7190
selectableMapping.getCustomReadExpression(),
72-
selectableMapping.getJdbcMapping()
91+
selectableMapping.getJdbcMapping(),
92+
selectableMapping.getPrecision(),
93+
selectableMapping.getScale()
7394
);
7495
}
7596

@@ -80,7 +101,9 @@ public ColumnReference(@Nullable String qualifier, SelectableMapping selectableM
80101
selectableMapping.getSelectablePath(),
81102
selectableMapping.isFormula(),
82103
selectableMapping.getCustomReadExpression(),
83-
jdbcMapping
104+
jdbcMapping,
105+
selectableMapping.getPrecision(),
106+
selectableMapping.getScale()
84107
);
85108
}
86109

@@ -96,7 +119,9 @@ public ColumnReference(
96119
null,
97120
isFormula,
98121
customReadExpression,
99-
jdbcMapping
122+
jdbcMapping,
123+
null,
124+
null
100125
);
101126
}
102127

@@ -106,7 +131,7 @@ public ColumnReference(
106131
boolean isFormula,
107132
@Nullable String customReadExpression,
108133
JdbcMapping jdbcMapping) {
109-
this( qualifier, columnExpression, null, isFormula, customReadExpression, jdbcMapping );
134+
this( qualifier, columnExpression, null, isFormula, customReadExpression, jdbcMapping, null, null );
110135
}
111136

112137
public ColumnReference(
@@ -115,8 +140,12 @@ public ColumnReference(
115140
@Nullable SelectablePath selectablePath,
116141
boolean isFormula,
117142
@Nullable String customReadExpression,
118-
JdbcMapping jdbcMapping) {
143+
JdbcMapping jdbcMapping,
144+
Integer precision,
145+
Integer scale) {
119146
this.qualifier = nullIfEmpty( qualifier );
147+
this.precision = precision;
148+
this.scale = scale;
120149

121150
if ( isFormula ) {
122151
this.columnExpression = qualifier == null
@@ -145,6 +174,14 @@ public ColumnReference getColumnReference() {
145174
return qualifier;
146175
}
147176

177+
public Integer getPrecision() {
178+
return precision;
179+
}
180+
181+
public Integer getScale() {
182+
return scale;
183+
}
184+
148185
public String getColumnExpression() {
149186
return columnExpression;
150187
}

hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/AbstractTableInsertBuilder.java

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -68,17 +68,14 @@ protected List<ColumnValueBinding> getLobValueBindingList() {
6868

6969
@Override
7070
public void addValueColumn(String columnName, String columnWriteFragment, JdbcMapping jdbcMapping, boolean isLob) {
71-
final ColumnValueBinding valueBinding = createValueBinding( columnName, columnWriteFragment, jdbcMapping );
71+
final var valueBinding = createValueBinding( columnName, columnWriteFragment, jdbcMapping );
72+
addLob(valueBinding, isLob);
73+
}
7274

73-
if ( isLob && getJdbcServices().getDialect().forceLobAsLastValue() ) {
74-
if ( lobValueBindingList == null ) {
75-
lobValueBindingList = new ArrayList<>();
76-
}
77-
lobValueBindingList.add( valueBinding );
78-
}
79-
else {
80-
valueBindingList.add( valueBinding );
81-
}
75+
@Override
76+
public void addValueColumn(String columnName, String columnWriteFragment, JdbcMapping jdbcMapping, boolean isLob, Integer precision, Integer scale) {
77+
final var valueBinding = createValueBinding( columnName, columnWriteFragment, jdbcMapping, precision, scale );
78+
addLob(valueBinding, isLob);
8279
}
8380

8481
@Override
@@ -90,4 +87,16 @@ public void addValueColumn(ColumnValueBinding valueBinding) {
9087
public void addKeyColumn(String columnName, String columnWriteFragment, JdbcMapping jdbcMapping) {
9188
addColumn( columnName, columnWriteFragment, jdbcMapping, keyBindingList );
9289
}
90+
91+
private void addLob(ColumnValueBinding valueBinding, boolean isLob) {
92+
if ( isLob && getJdbcServices().getDialect().forceLobAsLastValue() ) {
93+
if ( lobValueBindingList == null ) {
94+
lobValueBindingList = new ArrayList<>();
95+
}
96+
lobValueBindingList.add( valueBinding );
97+
}
98+
else {
99+
valueBindingList.add( valueBinding );
100+
}
101+
}
93102
}

hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/AbstractTableMutationBuilder.java

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,16 @@ protected ColumnValueBinding createValueBinding(
100100
JdbcMapping jdbcMapping) {
101101
return createValueBinding( columnName, columnWriteFragment, jdbcMapping, ParameterUsage.SET );
102102
}
103+
104+
protected ColumnValueBinding createValueBinding(
105+
String columnName,
106+
String columnWriteFragment,
107+
JdbcMapping jdbcMapping,
108+
Integer precision,
109+
Integer scale) {
110+
return createValueBinding( columnName, columnWriteFragment, jdbcMapping, ParameterUsage.SET, precision, scale );
111+
}
112+
103113
protected ColumnValueBinding createValueBinding(
104114
String columnName,
105115
String customWriteExpression,
@@ -115,18 +125,37 @@ protected ColumnValueBinding createValueBinding(
115125
);
116126
}
117127

128+
protected ColumnValueBinding createValueBinding(
129+
String columnName,
130+
String customWriteExpression,
131+
JdbcMapping jdbcMapping,
132+
ParameterUsage parameterUsage,
133+
Integer precision,
134+
Integer scale) {
135+
return ColumnValueBindingBuilder.createValueBinding(
136+
columnName,
137+
customWriteExpression,
138+
jdbcMapping,
139+
getMutatingTable(),
140+
parameterUsage,
141+
parameters::apply,
142+
precision,
143+
scale
144+
);
145+
}
146+
118147
@SafeVarargs
119148
protected final <T> List<T> combine(List<T> list1, List<T>... additionalLists) {
120149
final ArrayList<T> combined = list1 == null
121150
? new ArrayList<>()
122151
: new ArrayList<>( list1 );
123152

124153
if ( additionalLists != null ) {
125-
for ( int i = 0; i < additionalLists.length; i++ ) {
126-
if ( additionalLists[i] == null ) {
154+
for ( List<T> additionalList : additionalLists ) {
155+
if ( additionalList == null ) {
127156
continue;
128157
}
129-
combined.addAll( additionalLists[i] );
158+
combined.addAll( additionalList );
130159
}
131160
}
132161

hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/AbstractTableUpdateBuilder.java

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -91,16 +91,7 @@ public void addValueColumn(
9191
JdbcMapping jdbcMapping,
9292
boolean isLob) {
9393
final ColumnValueBinding valueBinding = createValueBinding( columnName, columnWriteFragment, jdbcMapping );
94-
95-
if ( isLob && getJdbcServices().getDialect().forceLobAsLastValue() ) {
96-
if ( lobValueBindings == null ) {
97-
lobValueBindings = new ArrayList<>();
98-
}
99-
lobValueBindings.add( valueBinding );
100-
}
101-
else {
102-
valueBindings.add( valueBinding );
103-
}
94+
addLob( valueBinding, isLob );
10495
}
10596

10697
@Override
@@ -115,4 +106,22 @@ public void addKeyColumn(
115106
JdbcMapping jdbcMapping) {
116107
addColumn( columnName, columnWriteFragment, jdbcMapping, keyBindings );
117108
}
109+
110+
@Override
111+
public void addValueColumn(String columnName, String columnWriteFragment, JdbcMapping jdbcMapping, boolean isLob, Integer precision, Integer scale) {
112+
final var valueBinding = createValueBinding( columnName, columnWriteFragment, jdbcMapping, precision, scale );
113+
addLob(valueBinding, isLob);
114+
}
115+
116+
private void addLob(ColumnValueBinding valueBinding, boolean isLob) {
117+
if ( isLob && getJdbcServices().getDialect().forceLobAsLastValue() ) {
118+
if ( lobValueBindings == null ) {
119+
lobValueBindings = new ArrayList<>();
120+
}
121+
lobValueBindings.add( valueBinding );
122+
}
123+
else {
124+
valueBindings.add( valueBinding );
125+
}
126+
}
118127
}

hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/ColumnValueBindingBuilder.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,27 @@ public static ColumnValueBinding createValueBinding(
5353
return new ColumnValueBinding( columnReference, columnWriteFragment ) ;
5454
}
5555

56+
public static ColumnValueBinding createValueBinding(
57+
String columnName,
58+
String writeExpression,
59+
JdbcMapping jdbcMapping,
60+
MutatingTableReference mutatingTableReference,
61+
ParameterUsage parameterUsage,
62+
Consumer<Object> parameterConsumer,
63+
Integer precision,
64+
Integer scale) {
65+
final ColumnReference columnReference = new ColumnReference( mutatingTableReference, columnName, jdbcMapping, precision, scale );
66+
final ColumnWriteFragment columnWriteFragment = buildWriteFragment(
67+
writeExpression,
68+
jdbcMapping,
69+
mutatingTableReference,
70+
columnReference,
71+
parameterUsage,
72+
parameterConsumer
73+
);
74+
return new ColumnValueBinding( columnReference, columnWriteFragment ) ;
75+
}
76+
5677
public static ColumnWriteFragment buildWriteFragment(
5778
String writeExpression,
5879
JdbcMapping jdbcMapping,

hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/ColumnValuesTableMutationBuilder.java

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import org.hibernate.Internal;
99
import org.hibernate.metamodel.mapping.JdbcMapping;
1010
import org.hibernate.metamodel.mapping.SelectableMapping;
11+
import org.hibernate.metamodel.mapping.internal.BasicAttributeMapping;
1112
import org.hibernate.sql.model.ast.ColumnValueBinding;
1213
import org.hibernate.sql.model.ast.TableMutation;
1314

@@ -32,6 +33,12 @@ public interface ColumnValuesTableMutationBuilder<M extends TableMutation<?>> ex
3233
* Add a column as part of the values list
3334
*/
3435
void addValueColumn(String columnName, String columnWriteFragment, JdbcMapping jdbcMapping, boolean isLob);
36+
37+
/**
38+
* Add a column as part of the values list
39+
*/
40+
void addValueColumn(String columnName, String columnWriteFragment, JdbcMapping jdbcMapping, boolean isLob, Integer precision, Integer scale);
41+
3542
/**
3643
* Add a column as part of the values list
3744
*/
@@ -43,12 +50,24 @@ default void addValueColumn(String columnName, String columnWriteFragment, JdbcM
4350
* Add a column as part of the values list
4451
*/
4552
default void addValueColumn(SelectableMapping selectableMapping) {
46-
addValueColumn(
53+
if ( selectableMapping instanceof BasicAttributeMapping ) {
54+
addValueColumn(
55+
selectableMapping.getSelectionExpression(),
56+
selectableMapping.getWriteExpression(),
57+
selectableMapping.getJdbcMapping(),
58+
selectableMapping.isLob(),
59+
selectableMapping.getPrecision(),
60+
selectableMapping.getScale()
61+
);
62+
}
63+
else {
64+
addValueColumn(
4765
selectableMapping.getSelectionExpression(),
4866
selectableMapping.getWriteExpression(),
4967
selectableMapping.getJdbcMapping(),
5068
selectableMapping.isLob()
51-
);
69+
);
70+
}
5271
}
5372

5473
/**

0 commit comments

Comments
 (0)