-
Notifications
You must be signed in to change notification settings - Fork 1.5k
QueryEnhancerFactory with JSqlParser on classpath prevent using an {h-schema} placeholder in native queries #2564
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
Comments
Ok as far as I can see the main problem is that I dug a bit deeper to find a solution to that problem and it turns out your query If I replace As far as I can see using I identified two things that need to be changed/fixed:
I think Point 2 needs a decision from the members. |
Thanks for advanced research! Regarding p.1 - yes it's definitely supported at least by |
Yeah as far as I can see it does not fail because the count query is not used anywhere (yet). When I checkout spring-projects/spring-data-jpa/2.5.x and add the following test case: @Test
void hibernatePlaceHolderStringCountQuery() {
assertCountQuery("SELECT c.* FROM {h-schema}countries c", "SELECT count(c.*) FROM {h-schema}countries c");
} the count query is wrong. (Test case fails). So I think this should be fixed. |
I have the same issue and want to use DefaultQueryEnhancer without dig publicity into unnecessary details.... this is resolution for Kotlin, expect you'll fix the issue to avoid such workarounds ASAP:
|
@DiegoKrupitza Hi. The issue is still reproducing in SB 2.7.3. Any ETA to fix it? It would be nice to have some configuration property to tell application either to use JSQL parser for query enhancer, or no. @vyemialyanchyk Thanks for the snippet. Currently I solved it by placing my own implementation of QueryEnhancerFactory in the same package which return false in isJSqlParserInClassPath method. |
Hey @valkuc,
I understood this as "a flag in the In my opinion there are two ways on how to deal with this problem without introducing a flag:
(1.) is of course not a maintainable solutions and is obviously a bad decision. Right now I can't say when I have time to work on this because I am really busy with uni and other stuff... But maybe you could try to come up with a solution based on my thoughts and create a PR ( one more contributor 🤩). I would be happy to look over it :) |
@DiegoKrupitza Let me disagree with you :) I don't see anything bad in allowing developer to choose which query parser he want to use independently of what is located in the classpath. Let's take Just for info: we added JSQL parser in our project just to perform syntax analysis of sql queries entered by user in UI and we definitely do not want for it to be used in spring internals, but... there is no way to turn that off. |
@DiegoKrupitza So, what is you opinion? Just want to be sure that if I will start working on my approach there will be a chance that I will not waste time :) |
@valkuc I see your point and It makes sense but unfortunately I am not the one who decides this. I am just a normal contributer as you. Members of spring data jpa have to decide this. Regarding disabling certain parsers with properties.. I have a counter example. Let's say we have multiple QueryEnhancer implementations (JSQLParser for SQL, Hibernate Parser for JPQL, EclipseLink for JPQL and the DefaultImpl using QueryUtils). Your approach must have configuration for all of them and ideally should not be hardcoded. Because maybe I want to use for JPQL the recommended Impl which is decided based on whats in classpath and only the DefaultImpl for native SQL queries. There has to be 2 configuration properties: One for SQL and one for JPQL. But now, what if I want to use EclipseLink over Hibernate for JPQL (and have both in classpath) how do you configure this? I think with the comment from @gregturn it was meant to avoid such complicated configuration. |
@DiegoKrupitza Interesting... I got your point. Well, maybe this is a bit of "off-topic" but could you please guide me where I can find information about why JSQLParser support was introduced. Just want to understand, because for me current situation looks like: "hey, that functionality worked for years and now it's broken" (I'm about |
@valkuc The reason to introduce the JSQLParser was that Spring Data JPA struggles with tons of problems resulting from failing to parse SQL properly. That Hibernate supports stuff that looks almost like SQL, but isn't was surprise to everyone involved I guess. |
Looks looks like the problem is even more wider. Having JSQLParser on the classpath makes it not possible to use SpEL in native queries. For example:
will fail with I guess that if JSQLParser was introduced to validate query syntax, maybe it should be invoked as a last processor, just before query will be sent to DB? But... I'm not sure this is possible in scope of Spring Data JPA as this means that query should be processed after it passed to underlying persistence provider (Hibernate for example). |
I tried to reproduce the error mentioned in spring-projects#2564 but I can't.
@valkuc I hooked into the debugger to check whether it is really detected as a native query and saw that the query is rewritten before feeding it to the JSQLParserQueryEnhancer. Apparently JSQLParser accepts this placeholder, because it is in the format that is also used for prepared statements. |
@DiegoKrupitza Looks like my fault. I did not removed original query which uses {h-schema} placeholder. |
…ons fail. In spring-projects#2564 we discovered that sometimes queries contain content that cannot be parsed by special implementation such as `JSqlParserQueryEnhancer`. Therefore, we implement a fallback mechanism that tries to use the first possible suitable implementation for a given query, that does not fail with an exception on creation. If the first one fails we fallback to the next one until we have reached the `DefaultQueryEnhancer`. Closes spring-projects#2564
In spring-projects#2564 we discovered that sometimes queries contain content that cannot be parsed by special implementation such as `JSqlParserQueryEnhancer`. Therefore, we implement a fallback mechanism that tries to use the first possible suitable implementation for a given query, that does not fail with an exception on creation. If the first one fails we fallback to the next one until we have reached the `DefaultQueryEnhancer`. Closes spring-projects#2564
I created a proposal for this in #2639 . It is now up to the members to decide whether this should be considers or not. |
Keywords also have this problem, such as sql contains 'binary' |
@kender1314 could you please provide an example query that has this problem? |
What about my idea over at #2639 (comment) in response to @DiegoKrupitza 's proposal. |
With this commit it is possible to manually select which `@QueryEnhancer` should be used for a given query. Selection can be performed on method or type level. Closes spring-projects#2564
I can confirm that this bug is indeed present in spring-data-jpa 2.7.3 |
@koszta5 Could you provide a code snippet (method + all annotations + how you call it) and the stack trace you get, because I can not really reproduce the error. |
…ically selected `QueryEnhancer`. Sometimes queryies contain content that cannot be pasrsed by special implementations such as `JSqlParserQueryEnhancer` (or other potential solutions). We implemented a means for developers to deliberately override the automatic choice with their own via annotation. Resolves #2564.
…ically selected `QueryEnhancer`. Sometimes queryies contain content that cannot be pasrsed by special implementations such as `JSqlParserQueryEnhancer` (or other potential solutions). We implemented a means for developers to deliberately override the automatic choice with their own via annotation. Resolves #2564.
Sometimes the automatically chosen `QueryEnhancer` (e.g. `JSqlParserQueryEnhancer`) isn't the right one. Go through a series of choices, finding the first one that doesn't fail on query creation. Also provide an override through `@QueryEnhancerOverride` that bypasses the selection process, supporting per-method as well as on the entire repository. Resolves #2564.
Sometimes the automatically chosen `QueryEnhancer` (e.g. `JSqlParserQueryEnhancer`) isn't the right one. Go through a series of choices, finding the first one that doesn't fail on query creation. Also provide an override through `@QueryEnhancerOverride` that bypasses the selection process, supporting per-method as well as on the entire repository. Resolves #2564.
Sometimes the automatically chosen `QueryEnhancer` (e.g. `JSqlParserQueryEnhancer`) isn't the right one. Go through a series of choices, finding the first one that doesn't fail on query creation. Also provide an override through `@QueryEnhancerOverride` that bypasses the selection process, supporting per-method as well as on the entire repository. Resolves #2564.
Sometimes the automatically chosen `QueryEnhancer` (e.g. `JSqlParserQueryEnhancer`) isn't the right one. Go through a series of choices, finding the first one that doesn't fail on query creation. Also provide an override through `@QueryEnhancerOverride` that bypasses the selection process, supporting per-method as well as on the entire repository. Resolves #2564.
Sometimes the automatically chosen `QueryEnhancer` (e.g. `JSqlParserQueryEnhancer`) isn't the right one. Go through a series of choices, finding the first one that doesn't fail on query creation. Also provide an override through `@QueryEnhancerOverride` that bypasses the selection process, supporting per-method as well as on the entire repository. Resolves #2564.
@DiegoKrupitza Sorry for pulling this change out. We appreciate your efforts. But further review has raised various questions, some of which are captured here. For now, I've pulled these efforts aside to https://github.com/spring-projects/spring-data-jpa/tree/issue/gh-2564 so we can further review the scope of the problem (handling failing custom queries) and ensure the solution gives end-users a practical means to reach that solution. In the mean time, the |
Sometimes the automatically chosen `QueryEnhancer` (e.g. `JSqlParserQueryEnhancer`) isn't the right one. Go through a series of choices, finding the first one that doesn't fail on query creation. Also provide an override through `@QueryEnhancerOverride` that bypasses the selection process, available at the repository level and on a per-method basis. Resolves #2564.
After further review, this If you are interested in something analogous, you can always implement it out-of-band to what Spring Data JPA offers by using currently supported bindings and variable names. You simply have to track the variable yourself and pass it along to the operations you have it implemented. |
Hello.
Using Spring Data 2.7.0 (from spring-data-bom version 2021.2.0) and having
com.github.jsqlparser
in the classpath prevent application to start if repositories use native queries with hibernate placeholders likeh-schema
. It failing early withnet.sf.jsqlparser.JSQLParserException: Encountered unexpected token: "{" "{"
.I did not find ability to turn off that feature. The decision to use
JSqlParserQueryEnhancer
instead ofDefaultQueryEnhancer
is made in static way in QueryEnhancerFactory.My project is based on Spring Boot 2.6.8 and in order to mitigate this issue I had switched from shipped spring-data-bom version 2021.1.4 to 2021.2.0. This solved mentioned critical issue but introduced new one :(
Here is test project to help reproduce that issue. Just run
CountryRepositoryTest
.Thanks in advance.
The text was updated successfully, but these errors were encountered: