Skip to content

Use RDBMS specific queries updating session attributes #1481

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

Conversation

candrews
Copy link
Contributor

@candrews candrews commented Aug 1, 2019

Inserting new attributes for the same session can result in a duplicate key exceptions. Using RDMS specific upsert queries solves this problem.

Resolves: #1213

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Aug 1, 2019
@candrews candrews force-pushed the attributes-duplicate-key branch 5 times, most recently from 97d9b7a to 96577e6 Compare August 1, 2019 19:47
@vpavic vpavic self-assigned this Aug 1, 2019
@candrews candrews force-pushed the attributes-duplicate-key branch from 96577e6 to 84c3c79 Compare August 1, 2019 20:26
@vpavic
Copy link
Contributor

vpavic commented Aug 1, 2019

Thanks for the PR @candrews but I'm not keen to add this kind of complexity to JDBC repo. I've got strong preference for sticking with standard SQL here. For advanced use cases there's an option of customizing SQL, which you already do. Besides complexity, having custom SQL OOTB is just too risky testing-wise as we cannot test all the databases - for instance, while we do have an integration test for Oracle, we cannot run it as a part of our build due to restrictions around Oracle JDBC driver.

Also note that this is only a workaround for #1213 because as explained in that issue the core problem lies in how sessions are consumed. As such, it doesn't really justify the complexity presented here.

@vpavic vpavic closed this Aug 1, 2019
@vpavic vpavic added status: declined A suggestion or change that we don't feel we should currently apply and removed status: waiting-for-triage An issue we've not yet triaged labels Aug 1, 2019
@candrews
Copy link
Contributor Author

candrews commented Aug 1, 2019

I've got strong preference for sticking with standard SQL here.

MERGE is part of the sql standard - we're just using it. If by "standard" you mean "widely supported," then yes - you have a point. But database specific code is nothing new - there are already per-database script distributed as part of Spring Session.

Besides complexity, having custom SQL OOTB is just too risky testing-wise as we cannot test all the databases

Which is why I've written this PR so that it falls back to the current behavior for all other databases. For example, H2 falls back to the basic INSERT query. Therefore, only the databases that have specific SQL need to be tested, which are MySQL, PostgreSQL, DB2, Oracle, and Microsoft SQL Server. Of those, all have automated integration tests already except for DB2 and Oracle. I'm quite willing to drop DB2; I just included it for completeness. Oracle I can assert that I've tested, and that's the best I can do - unfortunately, as you said, licensing for Oracle is problematic. Perhaps you could manually run the tests?

Also note that this is only a workaround for #1213 because as explained in that issue the core problem lies in how sessions are consumed. As such, it doesn't really justify the complexity presented here.

I don't agree that this is a workaround - this is the solution. Applications create attributes and they expect that to work (just see #1213 for users that agree with my perspective); currently, Spring Session doesn't always work. Asking all applications to change their implementation (in a complex way) isn't great - it's much better to have Spring Session JDBC support the approach that applications already take and meet the exceptions they already in alignment with other session implementations (including every application server and other Spring Session implementations).

Could you please reconsider?

@vpavic
Copy link
Contributor

vpavic commented Aug 2, 2019

MERGE is part of the sql standard - we're just using it. If by "standard" you mean "widely supported," then yes - you have a point. But database specific code is nothing new - there are already per-database script distributed as part of Spring Session.

Indeed I used term SQL standard to refer to widely adopted level of SQL standard, sorry for the confusion there. Schema scripts are not really in the same ballpark, as they're not truly normative but rather simply provided for convenience/guidance.

Which is why I've written this PR so that it falls back to the current behavior for all other databases.

I understand that, but it adds complexity that we really don't want to deal with in Spring Session. I'm sure there are other users with their own cases for database specific SQL in other places so if we add such behavior in one place, there will surely be requests for other places as well.

There's simply isn't any pressing need to add this complexity, as customization of SQL is already possible. I agree that it isn't ideal since it requires you to manually declare JdbcOperationsSessionRepository bean, but we'll try to improve things for 2.2 in #1199.

For the most optimal solution to leverage capabilities of your RDBMS, I'd recommend going custom SessionRepository route - this could be quite beneficial in case of database like Oracle. You could publish it as a 3rd party extension and we'll link it in our docs. I've had a similar idea for PostgreSQL for a while now but never had time to realize it. Alternatively, perhaps a jOOQ based SessionRepository implementation could also be an option.

Of those, all have automated integration tests already except for DB2 and Oracle. I'm quite willing to drop DB2; I just included it for completeness. Oracle I can assert that I've tested, and that's the best I can do - unfortunately, as you said, licensing for Oracle is problematic. Perhaps you could manually run the tests?

I'm afraid anything manual is just to risky. Regarding DB2, I've just added integration tests yesterday.

I don't agree that this is a workaround - this is the solution.

We'll have to disagree there, because as explained in #1213, the original problem is that concurrent requests operate on the same attribute overwriting each other - his just makes the request that lost race condition (and threw an exception) to win the race condition.

To summarize:

  • we'd like to avoid SQL dialect handling in Spring Session
  • we'll improve configuration capabilities for custom SQL
  • integration testing isn't possible for Oracle in the same manner as it is for most other databases, which is a huge risk for any Oracle specific SQL
  • the original race condition problem still exists

@candrews
Copy link
Contributor Author

candrews commented Aug 2, 2019

  • integration testing isn't possible for Oracle in the same manner as it is for most other databases, which is a huge risk for any Oracle specific SQL

That is bad.... but maybe it can be made a bit better.
Oracle offers the OJDBC drivers in their maven repository, but you need to authenticate. We could store Oracle credentials in an encrypted Travis CI variable, and have Spring Session's tests depend on OJDBC and get it from Oracle's maven repository only if that variable is set.
Users would only be able to run the Oracle tests if they also set the variable on their systems, but at least Spring Session's Travis CI would run them automatically.
I could prepare a PR to this.

@vpavic
Copy link
Contributor

vpavic commented Aug 27, 2019

Thanks for the offer @candrews, but again that kind of complexity is what we'd like to avoid.

* other databases.
*/
// @formatter:off
private static final String CREATE_SESSION_ATTRIBUTE_QUERY_MERGE = "MERGE INTO %TABLE_NAME%_ATTRIBUTES x "
Copy link

@shark300 shark300 Aug 29, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've got a "bad SQL grammar" exception on Oracle 18c if the SQL query has an ending semicolon.

(Yes, I know it's a declined PR, but we're using this as a workaround until the final solution.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this PR was declined, GitHub doesn't seem to be updating it when I push to the branch for it.

I had fixed this a while ago in my branch, so I suggest you grab it from there: https://github.com/candrews/spring-session/tree/attributes-duplicate-key

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: declined A suggestion or change that we don't feel we should currently apply
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Concurrent requests adding the same session attribute result in duplicate key constraint violation
4 participants