70
70
import org .hibernate .sql .ast .SqlAstNodeRenderingMode ;
71
71
import org .hibernate .sql .ast .SqlAstTranslator ;
72
72
import org .hibernate .sql .ast .SqlTreeCreationException ;
73
- import org .hibernate .sql .ast .internal .ParameterMarkerStrategyStandard ;
74
73
import org .hibernate .sql .ast .internal .TableGroupHelper ;
74
+ import org .hibernate .sql .ast .internal .ParameterMarkerStrategyStandard ;
75
75
import org .hibernate .sql .ast .tree .AbstractUpdateOrDeleteStatement ;
76
76
import org .hibernate .sql .ast .tree .MutationStatement ;
77
77
import org .hibernate .sql .ast .tree .SqlAstNode ;
135
135
import org .hibernate .sql .exec .internal .AbstractJdbcParameter ;
136
136
import org .hibernate .sql .exec .internal .JdbcOperationQueryInsertImpl ;
137
137
import org .hibernate .sql .exec .internal .JdbcParameterBindingImpl ;
138
- import org .hibernate .sql .exec .internal .JdbcParametersImpl ;
139
138
import org .hibernate .sql .exec .internal .SqlTypedMappingJdbcParameter ;
140
139
import org .hibernate .sql .exec .spi .ExecutionContext ;
141
140
import org .hibernate .sql .exec .spi .JdbcLockStrategy ;
177
176
import java .sql .SQLException ;
178
177
import java .time .Period ;
179
178
import java .util .ArrayList ;
179
+ import java .util .Arrays ;
180
180
import java .util .BitSet ;
181
181
import java .util .Collection ;
182
182
import java .util .Collections ;
@@ -260,7 +260,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
260
260
private final StringBuilder sqlBuffer = new StringBuilder ();
261
261
262
262
private final List <JdbcParameterBinder > parameterBinders = new ArrayList <>();
263
- private final JdbcParametersImpl jdbcParameters = new JdbcParametersImpl () ;
263
+ private int [] parameterIdToBinderIndex ;
264
264
private JdbcParameterBindings jdbcParameterBindings ;
265
265
private Map <JdbcParameter , JdbcParameterBinding > appliedParameterBindings = Collections .emptyMap ();
266
266
private SqlAstNodeRenderingMode parameterRenderingMode = SqlAstNodeRenderingMode .DEFAULT ;
@@ -4607,11 +4607,10 @@ protected void renderFetchPlusOffsetExpressionAsSingleParameter(
4607
4607
appendSql ( fetchCount .intValue () + offsetCount .intValue () + offset );
4608
4608
}
4609
4609
else {
4610
- appendSql ( PARAM_MARKER );
4611
4610
final JdbcParameter offsetParameter = (JdbcParameter ) offsetClauseExpression ;
4612
4611
final int offsetValue = offset + fetchCount .intValue ();
4613
- jdbcParameters . addParameter ( offsetParameter );
4614
- parameterBinders . add (
4612
+ final int parameterPosition = addParameterBinder (
4613
+ offsetParameter ,
4615
4614
(statement , startPosition , jdbcParameterBindings , executionContext ) -> {
4616
4615
final JdbcParameterBinding binding = jdbcParameterBindings .getBinding ( offsetParameter );
4617
4616
if ( binding == null ) {
@@ -4627,44 +4626,29 @@ protected void renderFetchPlusOffsetExpressionAsSingleParameter(
4627
4626
);
4628
4627
}
4629
4628
);
4629
+ renderParameterAsParameter ( parameterPosition , offsetParameter );
4630
4630
}
4631
4631
}
4632
4632
else {
4633
- appendSql ( PARAM_MARKER );
4634
4633
final JdbcParameter offsetParameter = (JdbcParameter ) offsetClauseExpression ;
4635
4634
final JdbcParameter fetchParameter = (JdbcParameter ) fetchClauseExpression ;
4636
- final OffsetReceivingParameterBinder fetchBinder = new OffsetReceivingParameterBinder (
4635
+ final FetchPlusOffsetParameterBinder fetchBinder = new FetchPlusOffsetParameterBinder (
4637
4636
offsetParameter ,
4638
4637
fetchParameter ,
4639
4638
offset
4640
4639
);
4641
- // We don't register and bind the special OffsetJdbcParameter as that comes from the query options
4642
- // And in this case, we only want to bind a single JDBC parameter
4643
- if ( !( offsetParameter instanceof OffsetJdbcParameter ) ) {
4644
- jdbcParameters .addParameter ( offsetParameter );
4645
- parameterBinders .add (
4646
- (statement , startPosition , jdbcParameterBindings , executionContext ) -> {
4647
- final JdbcParameterBinding binding = jdbcParameterBindings .getBinding ( offsetParameter );
4648
- if ( binding == null ) {
4649
- throw new ExecutionException ( "JDBC parameter value not bound - " + offsetParameter );
4650
- }
4651
- fetchBinder .dynamicOffset = (Number ) binding .getBindValue ();
4652
- }
4653
- );
4654
- }
4655
- jdbcParameters .addParameter ( fetchParameter );
4656
- parameterBinders .add ( fetchBinder );
4640
+ final int parameterPosition = addParameterBinder ( fetchParameter , fetchBinder );
4641
+ renderParameterAsParameter ( parameterPosition , fetchParameter );
4657
4642
}
4658
4643
}
4659
4644
4660
- private static class OffsetReceivingParameterBinder implements JdbcParameterBinder {
4645
+ private static class FetchPlusOffsetParameterBinder implements JdbcParameterBinder {
4661
4646
4662
4647
private final JdbcParameter offsetParameter ;
4663
4648
private final JdbcParameter fetchParameter ;
4664
4649
private final int staticOffset ;
4665
- private Number dynamicOffset ;
4666
4650
4667
- public OffsetReceivingParameterBinder (
4651
+ public FetchPlusOffsetParameterBinder (
4668
4652
JdbcParameter offsetParameter ,
4669
4653
JdbcParameter fetchParameter ,
4670
4654
int staticOffset ) {
@@ -4695,8 +4679,11 @@ public void bindParameterValue(
4695
4679
offsetValue = executionContext .getQueryOptions ().getEffectiveLimit ().getFirstRow ();
4696
4680
}
4697
4681
else {
4698
- offsetValue = dynamicOffset .intValue () + staticOffset ;
4699
- dynamicOffset = null ;
4682
+ final JdbcParameterBinding binding = jdbcParameterBindings .getBinding ( offsetParameter );
4683
+ if ( binding == null ) {
4684
+ throw new ExecutionException ( "JDBC parameter value not bound - " + offsetParameter );
4685
+ }
4686
+ offsetValue = ((Number ) binding .getBindValue ()).intValue () + staticOffset ;
4700
4687
}
4701
4688
//noinspection unchecked
4702
4689
fetchParameter .getExpressionType ().getSingleJdbcMapping ().getJdbcValueBinder ().bind (
@@ -5670,15 +5657,15 @@ protected void renderLiteral(Literal literal, boolean castParameter) {
5670
5657
final JdbcLiteralFormatter <Object > literalFormatter = literal .getJdbcMapping ().getJdbcLiteralFormatter ();
5671
5658
// If we encounter a plain literal in the select clause which has no literal formatter, we must render it as parameter
5672
5659
if ( literalFormatter == null ) {
5673
- parameterBinders . add ( literal );
5660
+ final int parameterPosition = addParameterBinderOnly ( literal );
5674
5661
final JdbcType jdbcType = literal .getJdbcMapping ().getJdbcType ();
5675
- final String marker = parameterMarkerStrategy .createMarker ( parameterBinders . size () , jdbcType );
5676
- final LiteralAsParameter <?> jdbcParameter = new LiteralAsParameter <>( literal , marker );
5662
+ final String marker = parameterMarkerStrategy .createMarker ( parameterPosition , jdbcType );
5663
+
5677
5664
if ( castParameter ) {
5678
- renderCasted ( jdbcParameter );
5665
+ renderCasted ( new LiteralAsParameter <>( literal , marker ) );
5679
5666
}
5680
5667
else {
5681
- jdbcParameter . renderToSql ( this , this , sessionFactory );
5668
+ jdbcType . appendWriteExpression ( marker , this , dialect );
5682
5669
}
5683
5670
}
5684
5671
else {
@@ -7002,15 +6989,8 @@ public void visitParameter(JdbcParameter jdbcParameter) {
7002
6989
}
7003
6990
7004
6991
protected void visitParameterAsParameter (JdbcParameter jdbcParameter ) {
7005
- renderParameterAsParameter ( jdbcParameter );
7006
- parameterBinders .add ( jdbcParameter .getParameterBinder () );
7007
- jdbcParameters .addParameter ( jdbcParameter );
7008
- }
7009
-
7010
- protected final void renderParameterAsParameter (JdbcParameter jdbcParameter ) {
7011
- final JdbcType jdbcType = jdbcParameter .getExpressionType ().getJdbcMapping ( 0 ).getJdbcType ();
7012
- assert jdbcType != null ;
7013
- renderParameterAsParameter ( parameterBinders .size () + 1 , jdbcParameter );
6992
+ final int parameterPosition = addParameterBinder ( jdbcParameter );
6993
+ renderParameterAsParameter ( parameterPosition , jdbcParameter );
7014
6994
}
7015
6995
7016
6996
protected void renderWrappedParameter (JdbcParameter jdbcParameter ) {
@@ -7037,6 +7017,53 @@ protected void renderParameterAsParameter(int position, JdbcParameter jdbcParame
7037
7017
jdbcType .appendWriteExpression ( parameterMarker , this , dialect );
7038
7018
}
7039
7019
7020
+ protected final int addParameterBinder (JdbcParameter parameter ) {
7021
+ return addParameterBinder ( parameter , parameter .getParameterBinder () );
7022
+ }
7023
+
7024
+ protected final int addParameterBinder (JdbcParameter parameter , JdbcParameterBinder parameterBinder ) {
7025
+ final Integer parameterId = parameter .getParameterId ();
7026
+ if ( ParameterMarkerStrategyStandard .isStandardRenderer ( parameterMarkerStrategy )
7027
+ // Filter parameters are unique and they are not tracked via parameterInfo
7028
+ || parameter instanceof FilterJdbcParameter
7029
+ || parameterId == null ) {
7030
+ return addParameterBinderOnly ( parameterBinder );
7031
+ }
7032
+ else {
7033
+ parameterIdToBinderIndex = ensureCapacity ( parameterIdToBinderIndex , parameterId + 1 );
7034
+ int binderIndex = parameterIdToBinderIndex [parameterId ];
7035
+ if ( binderIndex == -1 ) {
7036
+ parameterIdToBinderIndex [parameterId ] = binderIndex = addParameterBinderOnly ( parameterBinder );
7037
+ }
7038
+ return binderIndex ;
7039
+ }
7040
+ }
7041
+
7042
+ private static int [] ensureCapacity (int [] array , int minCapacity ) {
7043
+ int oldCapacity ;
7044
+ if ( array == null ) {
7045
+ oldCapacity = 0 ;
7046
+ array = new int [minCapacity ];
7047
+ }
7048
+ else {
7049
+ oldCapacity = array .length ;
7050
+ if ( minCapacity > oldCapacity ) {
7051
+ int newCapacity = oldCapacity + (oldCapacity >> 1 );
7052
+ newCapacity = Math .max ( Math .max ( newCapacity , minCapacity ), 10 );
7053
+ array = Arrays .copyOf ( array , newCapacity );
7054
+ }
7055
+ }
7056
+ for ( int i = oldCapacity ; i < array .length ; i ++ ) {
7057
+ array [i ] = -1 ;
7058
+ }
7059
+ return array ;
7060
+ }
7061
+
7062
+ private int addParameterBinderOnly (JdbcParameterBinder parameterBinder ) {
7063
+ parameterBinders .add ( parameterBinder );
7064
+ return parameterBinders .size ();
7065
+ }
7066
+
7040
7067
@ Override
7041
7068
public void render (SqlAstNode sqlAstNode , SqlAstNodeRenderingMode renderingMode ) {
7042
7069
final SqlAstNodeRenderingMode original = this .parameterRenderingMode ;
@@ -8495,7 +8522,7 @@ public void visitCustomTableInsert(TableInsertCustomSql tableInsert) {
8495
8522
assert sqlBuffer .toString ().isEmpty ();
8496
8523
sqlBuffer .append ( tableInsert .getCustomSql () );
8497
8524
8498
- tableInsert .forEachParameter ( this ::applyParameter );
8525
+ tableInsert .forEachParameter ( this ::addParameterBinder );
8499
8526
}
8500
8527
8501
8528
@ Override
@@ -8604,7 +8631,7 @@ public void visitCustomTableUpdate(TableUpdateCustomSql tableUpdate) {
8604
8631
assert sqlBuffer .toString ().isEmpty ();
8605
8632
sqlBuffer .append ( tableUpdate .getCustomSql () );
8606
8633
8607
- tableUpdate .forEachParameter ( this ::applyParameter );
8634
+ tableUpdate .forEachParameter ( this ::addParameterBinder );
8608
8635
}
8609
8636
8610
8637
@ Override
@@ -8668,13 +8695,7 @@ public void visitCustomTableDelete(TableDeleteCustomSql tableDelete) {
8668
8695
assert sqlBuffer .toString ().isEmpty ();
8669
8696
sqlBuffer .append ( tableDelete .getCustomSql () );
8670
8697
8671
- tableDelete .forEachParameter ( this ::applyParameter );
8672
- }
8673
-
8674
- protected void applyParameter (ColumnValueParameter parameter ) {
8675
- assert parameter != null ;
8676
- parameterBinders .add ( parameter .getParameterBinder () );
8677
- jdbcParameters .addParameter ( parameter );
8698
+ tableDelete .forEachParameter ( this ::addParameterBinder );
8678
8699
}
8679
8700
8680
8701
@ Override
@@ -8711,10 +8732,6 @@ public void visitColumnWriteFragment(ColumnWriteFragment columnWriteFragment) {
8711
8732
8712
8733
protected void simpleColumnWriteFragmentRendering (ColumnWriteFragment columnWriteFragment ) {
8713
8734
appendSql ( columnWriteFragment .getFragment () );
8714
-
8715
- for ( ColumnValueParameter parameter : columnWriteFragment .getParameters () ) {
8716
- parameterBinders .add ( parameter .getParameterBinder () );
8717
- jdbcParameters .addParameter ( parameter );
8718
- }
8735
+ columnWriteFragment .getParameters ().forEach ( this ::addParameterBinder );
8719
8736
}
8720
8737
}
0 commit comments