Skip to content

NamedParameterJdbcTemplate.query() breaks handling of SqlParameterValue with a collection of UUID's #26481

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
fprochazka opened this issue Jan 31, 2021 · 6 comments
Labels
in: data Issues in data modules (jdbc, orm, oxm, tx) status: duplicate A duplicate of another issue status: feedback-provided Feedback has been provided type: regression A bug that is also a regression

Comments

@fprochazka
Copy link

fprochazka commented Jan 31, 2021

Affects: v5.2.12.RELEASE (Spring Boot v2.3.7.RELEASE)

I have a PostgreSQL query

SELECT * FROM items WHERE id IN (:ids)

executed as

var jdbcTemplate = new NamedParameterJdbcTemplate(new JdbcTemplate(dataSource));
RowMapper<ItemData> rowMapper = null; // not relevant

List<UUID> ids = List.of(
    UUID.fromString("57feb862-b8e4-4754-8b75-4e2621388fa0"),
    UUID.fromString("2225559e-97d3-4839-b7b4-a97f4f4f49a9")
);

var parameters = new LinkedHashMap<String, SqlParameterValue>();
parameters.put("ids", new SqlParameterValue(Types.OTHER, ids));

var query = "SELECT * FROM items WHERE id IN (:ids)";

var result = jdbcTemplate.query(query, parameters, rowMapper);

Previously, this happily worked, it expanded the collection to a list of parameters and executed it.

org.springframework.dao.DataIntegrityViolationException: PreparedStatementCallback; SQL [SELECT * FROM items WHERE id IN (?, ?)]; No value specified for parameter 2.; nested exception is org.postgresql.util.PSQLException: No value specified for parameter 2.
    at org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.doTranslate(SQLStateSQLExceptionTranslator.java:104)
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)
    at org.springframework.jdbc.core.JdbcTemplate.translateException(JdbcTemplate.java:1443)
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:633)
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:669)
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:694)
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:748)
    at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.query(NamedParameterJdbcTemplate.java:216)
    at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.query(NamedParameterJdbcTemplate.java:223)
    ...

org.postgresql.util.PSQLException: No value specified for parameter 2.
    at org.postgresql.core.v3.SimpleParameterList.checkAllParametersSet(SimpleParameterList.java:275)
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:307)
    at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:473)
    at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:393)
    at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:164)
    at org.postgresql.jdbc.PgPreparedStatement.executeQuery(PgPreparedStatement.java:114)
    at com.zaxxer.hikari.pool.ProxyPreparedStatement.executeQuery(ProxyPreparedStatement.java:52)
    at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeQuery(HikariProxyPreparedStatement.java)
    at org.springframework.jdbc.core.JdbcTemplate$1.doInPreparedStatement(JdbcTemplate.java:678)
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:617)
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:669)
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:694)
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:748)
    at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.query(NamedParameterJdbcTemplate.java:216)
    at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.query(NamedParameterJdbcTemplate.java:223)
    ...

I've tried to debug it and at some point, the parameters that it's trying to bind to the prepared statement contain string like this

String valueBeforeApplyingToPrepareStatement = "['57feb862-b8e4-4754-8b75-4e2621388fa0', '2225559e-97d3-4839-b7b4-a97f4f4f49a9']";

which suggest to me that the query is correctly expanded based on the number of values in the collection, but the parameter is then converted somehow to a single value, which breaks the parameter binding

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Jan 31, 2021
@fprochazka fprochazka changed the title NamedParameterJdbcTemplate.query() BC Break with collections handling NamedParameterJdbcTemplate.query() BC Break handling SqlParameterValue with a collections Jan 31, 2021
@fprochazka fprochazka changed the title NamedParameterJdbcTemplate.query() BC Break handling SqlParameterValue with a collections NamedParameterJdbcTemplate.query() BC Break handling SqlParameterValue with a collections of UUID's Jan 31, 2021
@sbrannen
Copy link
Member

Previously, this happily worked, it expanded the collection to a list of parameters and executed it.

Do you mean this worked in 5.2.11 and then stopped working in 5.2.12?

If not, can you tell us which version this previously worked with?

@sbrannen sbrannen added in: data Issues in data modules (jdbc, orm, oxm, tx) status: waiting-for-feedback We need additional information before we can continue labels Jan 31, 2021
@fprochazka
Copy link
Author

I did some more debugging and the problem is introduced in org.springframework.jdbc.core.namedparam.NamedParameterUtils.buildValueArray(), where the SqlParameterValue is wrapped into another SqlParameterValue

image

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Jan 31, 2021
@sbrannen
Copy link
Member

Potentially related to #26071 and #21935.

@fprochazka
Copy link
Author

The problem was introduced here 66292cd

Previously, the value was un-wrapped and then re-wrapped into a new instance of SqlParameterValue, but now it's always wrapped into another instance.

@sbrannen
Copy link
Member

Thanks for the feedback.

This may be a duplicate of #26467.

@sbrannen sbrannen changed the title NamedParameterJdbcTemplate.query() BC Break handling SqlParameterValue with a collections of UUID's NamedParameterJdbcTemplate.query() breaks handling of SqlParameterValue with a collection of UUID's Jan 31, 2021
@fprochazka
Copy link
Author

I wasn't sure at first, that's why I've created a new issue, but now I think you're correct and this is a duplicate.

@sbrannen sbrannen added type: regression A bug that is also a regression and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Jan 31, 2021
@sbrannen sbrannen added this to the 5.3.4 milestone Jan 31, 2021
@jhoeller jhoeller added the status: duplicate A duplicate of another issue label Feb 15, 2021
@jhoeller jhoeller removed this from the 5.3.4 milestone Feb 15, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: data Issues in data modules (jdbc, orm, oxm, tx) status: duplicate A duplicate of another issue status: feedback-provided Feedback has been provided type: regression A bug that is also a regression
Projects
None yet
Development

No branches or pull requests

4 participants