Skip to content
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

NamedParameterJdbcTemplate does not support backticks for quoted identifiers #31944

Closed
Ganledes opened this issue Jan 4, 2024 · 6 comments
Closed
Assignees
Labels
in: data Issues in data modules (jdbc, orm, oxm, tx) type: enhancement A general enhancement
Milestone

Comments

@Ganledes
Copy link

Ganledes commented Jan 4, 2024

Affects: 6.1.2

When the table name contains the '&' character, the table name after '&' will be recognized as a parameter.
Example:

    @Test
    void test() {
        NamedParameterJdbcTemplate ops = new NamedParameterJdbcTemplate(new JdbcTemplate());

        SqlParameterSource sqlParameterSource = new MapSqlParameterSource("id", 1);
        ops.query("select * from `tb&user` where id = :id", sqlParameterSource, new ColumnMapRowMapper());
    }

The result of running the code is:

org.springframework.dao.InvalidDataAccessApiUsageException: No value supplied for the SQL parameter 'user`': No value registered for key 'user`'

	at org.springframework.jdbc.core.namedparam.NamedParameterUtils.buildValueArray(NamedParameterUtils.java:379)
	at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.getPreparedStatementCreator(NamedParameterJdbcTemplate.java:472)
	at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.getPreparedStatementCreator(NamedParameterJdbcTemplate.java:446)
	at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.query(NamedParameterJdbcTemplate.java:218)
	at org.example.demo.jdbc.NamedParameterJdbcTemplateTest.test(NamedParameterJdbcTemplateTest.java:20)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Jan 4, 2024
@jhoeller
Copy link
Contributor

jhoeller commented Jan 4, 2024

NamedParameterUtils does not detect backticks for quoting there, just standard single and double quotes. I'm therefore turning this into an enhancement request for processing backticks as quotes as well.

For the time being, can you use a different quoting symbol or possibly escape the ampersand? Are you on MySQL by any chance, given that you are using backticks to begin with (outside of standard SQL)?

@jhoeller jhoeller changed the title NamedParameterJdbcTemplate does not recognize parameters correctly NamedParameterJdbcTemplate does not detect backticks for quoting Jan 4, 2024
@jhoeller jhoeller added in: data Issues in data modules (jdbc, orm, oxm, tx) type: enhancement A general enhancement and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Jan 4, 2024
@jhoeller jhoeller added this to the 6.2.x milestone Jan 4, 2024
@Ganledes
Copy link
Author

Ganledes commented Jan 5, 2024

For the time being, can you use a different quoting symbol or possibly escape the ampersand? Are you on MySQL by any chance, given that you are using backticks to begin with (outside of standard SQL)?

@jhoeller Yes, I use MySQL. The two methods you mentioned above don't work for me. I've employed some less conventional approaches to address this issue, and it's currently functioning well.

@snicoll snicoll self-assigned this Jan 5, 2024
@snicoll snicoll modified the milestones: 6.2.x, 6.2.0-M1 Jan 5, 2024
@sbrannen sbrannen changed the title NamedParameterJdbcTemplate does not detect backticks for quoting NamedParameterJdbcTemplate does not detect backticks for quoting Jan 5, 2024
@snicoll
Copy link
Member

snicoll commented Jan 5, 2024

The two methods you mentioned above don't work for me.

Can you share what the problem is by reworking the example above to show what the problem was? I expect using standard quotes to work. As @jhoeller mentioned, backticks aren't standard so we need a justification before handling them as it could have a side effect elsewhere.

@snicoll snicoll added the status: waiting-for-feedback We need additional information before we can continue label Jan 5, 2024
@Ganledes
Copy link
Author

Ganledes commented Jan 5, 2024

@snicoll What I mean by "not working" is not that it's technically infeasible. MySQL defaults to using backticks to quote identifiers, but it can be configured to support double quotes by setting sql_mode=ANSI_QUOTES. The official documentation describes as follows:

Treat " as an identifier quote character (like the ` quote character) and not as a string quote character. You can still use ` to quote identifiers with this mode enabled. With ANSI_QUOTES enabled, you cannot use double quotation marks to quote literal strings because they are interpreted as identifiers.

Unfortunately, altering the database configuration is a bit impractical for me. Another solution I thought of is to check if the character before '&' or ':' is a whitespace to determine if it's a named parameter. I'm not sure if this approach is viable.

@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 5, 2024
@sbrannen
Copy link
Member

sbrannen commented Jan 6, 2024

MySQL defaults to using backticks to quote identifiers, but it can be configured to support double quotes by setting sql_mode=ANSI_QUOTES.

@Ganledes, the code in question is NamedParameterUtils.parseSqlStatement(String) which does not take the given database into account. It only takes the given query String into account. Thus, the fact that "MySQL defaults to using backticks to quote identifiers" does not influence the algorithm in NamedParameterUtils.parseSqlStatement(String).

@snicoll snicoll removed the status: feedback-provided Feedback has been provided label Jan 15, 2024
snicoll added a commit to snicoll/spring-framework that referenced this issue Jan 31, 2024
This commit makes sure that content within backticks are skipped
when parsing a SQL statement using NamedParameterUtils. This harmonizes
the current behavior of ignoring special characters that are wrapped
in backticks.

Closes spring-projectsgh-31944
@bclozel bclozel changed the title NamedParameterJdbcTemplate does not detect backticks for quoting NamedParameterJdbcTemplate does not detect backticks for quoting Feb 14, 2024
@sbrannen
Copy link
Member

Reopening to provide analogous support in org.springframework.r2dbc.core.NamedParameterUtils.

sbrannen added a commit that referenced this issue Feb 17, 2024
NamedParameterUtils in spring-r2dbc now supports MySQL-style backticks
for quoted identifiers for consistency with spring-jdbc.

See gh-31944
Closes gh-32285
@sbrannen sbrannen changed the title NamedParameterJdbcTemplate does not detect backticks for quoting NamedParameterJdbcTemplate does not support backticks for quoted identifiers Feb 17, 2024
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) type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

5 participants