-
Notifications
You must be signed in to change notification settings - Fork 212
When we use isIn(emptyList) in where condition, it should not query full table. #509
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
@jesusslim I understand the concern and I agree that the current solutions are a bit lacking. The problem is more that just One thing I will not compromise is about invalid SQL - I will not allow the library to generate invalid SQL. I've actually been adding checks for this in various places.
Configuration isn't so easy as there is no owning context for the statements. What is needed is a method of configuring each statement - probably by adding something to the DSL. So we could make the default behavior to throw an exception if no where clause will render, but provide a DSL mechanism to disable the exception if it was needed for some reason. |
@jesusslim see the new docs page for details on how I've addressed this issue and let me know what you think. |
@jeffgbutler @jesusslim /* [1] this is a general query case:
I need to query all the data because the user has no input criteria
*/
select(c -> c.where(age, isInWhenPresent(request.getAgeList()))); // I think it works well!
/* [2] this is a preQuery case:
I filter some username by a condition (In most cases, it is filtered first in another table),
after filtering, the matching usernameList is empty, so no data should be queried in the end
*/
List<String> usernameList = filterUsernameBySomeConditions(request.getUsernameList());
select(c -> c.where(username, isInWhenPresent(usernameList))); // not as expected!
/* [3] In fact, a mixture of the two */
List<Integer> ageList = request.getAgeList();
List<String> usernameList = filterUsernameBySomeConditions(request.getUsernameList());
select(c -> c.where(age, isInWhenPresent(ageList)).and(username, isInWhenPresent(usernameList)));
// ... so what do you think it is
/* So I usually handle it myself */
List<Integer> ageList = request.getAgeList();
List<String> usernameList = filterUsernameBySomeConditions(request.getUsernameList());
if (CollectionUtils.isEmpty(usernameList)) {
return ;
}
select(c -> c.where(age, isInWhenPresent(ageList)).and(username, isInWhenPresent(usernameList))); |
@Roderland Thanks for the excellent writeup! Starting in version 1.4.1, your case [1] will throw an exception if select(c -> c.where(age, isInWhenPresent(request.getAgeList()))
.configureStatement(cfg -> cfg.setNonRenderingWhereClauseAllowed(true))) Also in version 1.4.1, your case [2] will throw an exception if Your case [3] is a good example of doing parameter validation before calling the query - that is always the best thing to do. With that case you do not need to configure the statement to allow a non-rendering where clause because you check for values in |
This change is now released in version 1.4.1. Thanks for all the feedback. |
It's been posted here two years ago. But I don't think
isInRequired
orwithListEmptyCallback
is a good solution.Because if we can remember to useisInRequired
,of course we can also remember to check empty list beforeisIn
.I can understand that you never want to build invalid sql, but in my opinion, once we use
isIn
, whatever param we pass, you should never change our sql, we don't want fixing, if you think our sql is invalid just throw exception, not change it to another wrong sql.If we pass empty list, the sql should be
in ()
,you can't change it to query full table, because it will be a disaster in production if we have a table with big data, there will be lots of slow queries. And if we use it indelete
, it will delete all rows, it's a real disaster because you changed our sql wrong for "valid sql".And for most programmers, they don't know this issue, so every time in code review, we have to take time to check if they have checked empty list or not before
isIn
.And it's like a time bomb if someone forget to check empty list before use isIn.I think it will be a good solution if there is a config setting to decision throw exception or query full table when isIn empty list.
The text was updated successfully, but these errors were encountered: