@ -22,6 +22,7 @@ import java.util.Optional;
@@ -22,6 +22,7 @@ import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap ;
import java.util.regex.Pattern ;
import org.springframework.data.r2dbc.core.ReactiveDataAccessStrategy ;
import org.springframework.data.relational.repository.query.RelationalParameterAccessor ;
import org.springframework.data.repository.query.Parameter ;
import org.springframework.data.repository.query.Parameters ;
@ -38,15 +39,19 @@ class ExpressionEvaluatingParameterBinder {
@@ -38,15 +39,19 @@ class ExpressionEvaluatingParameterBinder {
private final ExpressionQuery expressionQuery ;
private final ReactiveDataAccessStrategy dataAccessStrategy ;
private final Map < String , Boolean > namedParameters = new ConcurrentHashMap < > ( ) ;
/ * *
* Creates new { @link ExpressionEvaluatingParameterBinder }
*
* @param expressionQuery must not be { @literal null } .
* @param dataAccessStrategy must not be { @literal null } .
* /
ExpressionEvaluatingParameterBinder ( ExpressionQuery expressionQuery ) {
ExpressionEvaluatingParameterBinder ( ExpressionQuery expressionQuery , ReactiveDataAccessStrategy dataAccessStrategy ) {
this . expressionQuery = expressionQuery ;
this . dataAccessStrategy = dataAccessStrategy ;
}
/ * *
@ -76,50 +81,44 @@ class ExpressionEvaluatingParameterBinder {
@@ -76,50 +81,44 @@ class ExpressionEvaluatingParameterBinder {
for ( ParameterBinding binding : expressionQuery . getBindings ( ) ) {
org . springframework . r2dbc . core . Parameter valueForBinding = evaluator . evaluate ( binding . getExpression ( ) ) ;
org . springframework . r2dbc . core . Parameter valueForBinding = getBindValue (
evaluator . evaluate ( binding . getExpression ( ) ) ) ;
if ( valueForBinding . isEmpty ( ) ) {
bindSpecToUse = bindSpecToUse . bindNull ( binding . getParameterName ( ) , valueForBinding . getType ( ) ) ;
} else {
bindSpecToUse = bindSpecToUse . bind ( binding . getParameterName ( ) , valueForBinding . getValue ( ) ) ;
}
bindSpecToUse = bind ( bindSpecToUse , binding . getParameterName ( ) , valueForBinding ) ;
}
return bindSpecToUse ;
}
private DatabaseClient . GenericExecuteSpec bindParameters ( DatabaseClient . GenericExecuteSpec bindSpec ,
boolean bindableNull , Object [ ] values , Parameters < ? , ? > bindableParameters ) {
boolean hasBindableNullValue , Object [ ] values , Parameters < ? , ? > bindableParameters ) {
DatabaseClient . GenericExecuteSpec bindSpecToUse = bindSpec ;
int bindingIndex = 0 ;
for ( Parameter bindableParameter : bindableParameters ) {
Object value = values [ bindableParameter . getIndex ( ) ] ;
Optional < String > name = bindableParameter . getName ( ) ;
if ( ( name . isPresent ( ) & & isNamedParameterUsed ( name ) ) | | ! expressionQuery . getBindings ( ) . isEmpty ( ) ) {
if ( name . isPresent ( ) & & ( isNamedParameterReferencedFromQuery ( name ) ) | | ! expressionQuery . getBindings ( ) . isEmpty ( ) ) {
if ( isNamedParameterUsed ( name ) ) {
if ( ! isNamedParameterReferencedFromQuery ( name ) ) {
continue ;
}
org . springframework . r2dbc . core . Parameter parameter = getBindValue ( values , bindableParameter ) ;
if ( value = = null ) {
if ( bindableNull ) {
bindSpecToUse = bindSpecToUse . bindNull ( name . get ( ) , bindableParameter . getType ( ) ) ;
}
} else {
bindSpecToUse = bindSpecToUse . bind ( name . get ( ) , value ) ;
}
if ( ! parameter . isEmpty ( ) | | hasBindableNullValue ) {
bindSpecToUse = bind ( bindSpecToUse , name . get ( ) , parameter ) ;
}
// skip unused named parameters if there is SpEL
} else {
if ( value = = null ) {
if ( bindableNull ) {
bindSpecToUse = bindSpecToUse . bindNull ( bindingIndex + + , bindableParameter . getType ( ) ) ;
}
} else {
bindSpecToUse = bindSpecToUse . bind ( bindingIndex + + , value ) ;
org . springframework . r2dbc . core . Parameter parameter = getBindValue ( values , bindableParameter ) ;
if ( ! parameter . isEmpty ( ) | | hasBindableNullValue ) {
bindSpecToUse = bind ( bindSpecToUse , bindingIndex + + , parameter ) ;
}
}
}
@ -127,7 +126,42 @@ class ExpressionEvaluatingParameterBinder {
@@ -127,7 +126,42 @@ class ExpressionEvaluatingParameterBinder {
return bindSpecToUse ;
}
private boolean isNamedParameterUsed ( Optional < String > name ) {
private org . springframework . r2dbc . core . Parameter getBindValue ( Object [ ] values , Parameter bindableParameter ) {
org . springframework . r2dbc . core . Parameter parameter = org . springframework . r2dbc . core . Parameter
. fromOrEmpty ( values [ bindableParameter . getIndex ( ) ] , bindableParameter . getType ( ) ) ;
return dataAccessStrategy . getBindValue ( parameter ) ;
}
private static DatabaseClient . GenericExecuteSpec bind ( DatabaseClient . GenericExecuteSpec spec , String name ,
org . springframework . r2dbc . core . Parameter parameter ) {
Object value = parameter . getValue ( ) ;
if ( value = = null ) {
return spec . bindNull ( name , parameter . getType ( ) ) ;
} else {
return spec . bind ( name , value ) ;
}
}
private static DatabaseClient . GenericExecuteSpec bind ( DatabaseClient . GenericExecuteSpec spec , int index ,
org . springframework . r2dbc . core . Parameter parameter ) {
Object value = parameter . getValue ( ) ;
if ( value = = null ) {
return spec . bindNull ( index , parameter . getType ( ) ) ;
} else {
return spec . bind ( index , value ) ;
}
}
private org . springframework . r2dbc . core . Parameter getBindValue ( org . springframework . r2dbc . core . Parameter bindValue ) {
return dataAccessStrategy . getBindValue ( bindValue ) ;
}
private boolean isNamedParameterReferencedFromQuery ( Optional < String > name ) {
if ( ! name . isPresent ( ) ) {
return false ;