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

Compiler: Add Defaults support in bindings #3375

Merged
merged 23 commits into from Oct 3, 2022
Merged

Compiler: Add Defaults support in bindings #3375

merged 23 commits into from Oct 3, 2022

Conversation

hfhbd
Copy link
Collaborator

@hfhbd hfhbd commented Jul 15, 2022

Fixes #3374
Fixes #3526

@AlecKazakova
Copy link
Collaborator

Is this a SQLDelight feature? Like would writing

INSERT INTO dog
VALUES (?, ?, DEFAULT);

be valid HSQL?

@hfhbd
Copy link
Collaborator Author

hfhbd commented Jul 15, 2022

Yes it is valid and normal HSql

@AlecKazakova
Copy link
Collaborator

im confused then, isn't this replacing it with ? in the actual executed SQL?

@hfhbd
Copy link
Collaborator Author

hfhbd commented Jul 15, 2022

Before the PR, all binding parameter are replaced with ?, regardless the provided string, eg DEFAULT. With my changes, in the executeBlock the binding parameter is "replaced" with the string defined in the dialect function replaceBind.
So yes, the original statement INSERT INTO dog VALUES (?, ?, DEFAULT); is now 1:1 executed in the sqldelight query INSERT INTO dog VALUES (?, ?, DEFAULT);. But the function of the query still has the unused parameter is_good, because I did only changed the executeBlock, not the actual parameter of the insert stmt. So how can I improve the implementation?

@hfhbd hfhbd marked this pull request as ready for review July 17, 2022 11:19
@hfhbd
Copy link
Collaborator Author

hfhbd commented Jul 17, 2022

This PR needs a mixin, specified in sql-psi. I will try to add the mixin to sqldelight.
Update: Added to sqldelight :)

@hfhbd hfhbd marked this pull request as draft July 17, 2022 11:30
@hfhbd hfhbd marked this pull request as ready for review July 17, 2022 11:45
@hfhbd
Copy link
Collaborator Author

hfhbd commented Jul 17, 2022

im confused then, isn't this replacing it with ? in the actual executed SQL?

Yes, this was the problem

@AlecKazakova
Copy link
Collaborator

Oh I see, you're doing the opposite of what I was saying: before it was replacing DEFAULT with ?, this PR keeps it as DEFAULT

@hfhbd
Copy link
Collaborator Author

hfhbd commented Jul 18, 2022

Exactly, this is the reason for the PR.

@AlecKazakova
Copy link
Collaborator

I will review this at some point it just requires more brain power than the easy PRs and I am short on brain power atm

Copy link
Collaborator

@AlecKazakova AlecKazakova left a comment

Choose a reason for hiding this comment

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

I'm also okay exploring the suggested change myself later if you've spun off this

Add test for PostgreSQL

Spotless

Move mixin to sqldelight

Use mixin instead

Don't add DEFAULT bindings to query

Fix DEFAULT in binding
@hfhbd
Copy link
Collaborator Author

hfhbd commented Sep 22, 2022

To test the replacement with the async code generator I also needed to fix R2DBC driver... So this PR contains some commits of #3525 and #3524, which should be merged first.

@hfhbd hfhbd enabled auto-merge (squash) September 23, 2022 05:58
@hfhbd hfhbd disabled auto-merge September 23, 2022 06:03
abstract class BindParameterMixin(node: ASTNode) : BindParameterMixin(node) {
override fun replaceWith(isAsync: Boolean, index: Int): String = when {
text == "DEFAULT" -> text
isAsync -> "$$index"
Copy link
Collaborator

Choose a reason for hiding this comment

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

this feels like a driver implementation detail, that specifically for R2DBC we need indexed parameters.

We're getting closer and I'm very happy to have functioning tests for this stuff now, so this is really the only thing I'm still hung up on

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Copy link
Collaborator

Choose a reason for hiding this comment

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

I kinda like that approach more, doing it at the driver level

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

But at driver level you only have strings. So "SELECT '?'" or "LIKE 'foo?%'" does not work. (Except using sql-psi at driver level during runtime again before executing each stmt)

Copy link
Collaborator

Choose a reason for hiding this comment

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

alright, I buy that

last suggestion then: could we just always replace arguments for the postgres driver with their indexed argument, even if its not the async driver? So that parameter can be removed and we're just saying for this dialect this is the expected parameter format

Copy link
Collaborator Author

@hfhbd hfhbd Oct 1, 2022

Choose a reason for hiding this comment

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

What parameter do you want to drop?
index => How do you want to do this? Hardcode a check in sqldelight-core to replace the parameter wildcard with a specific string for postgresql only?
isAsync => I have to check it

Copy link
Collaborator Author

@hfhbd hfhbd Oct 1, 2022

Choose a reason for hiding this comment

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

As expected, using $1 does not work on JDBC and results in an org.postgresql.util.PSQLException, because you try to bind a parameter to an unknown one:
In JDBC, the question mark (?) is the placeholder for the positional parameters of a PreparedStatement. There are, however, a number of PostgreSQL® operators that contain a question mark. To keep such question marks in an SQL statement from being interpreted as positional parameters, use two question marks ( ?? ) as escape sequence. You can also use this escape sequence in a Statement , but that is not required. Specifically only in a Statement a single ( ? ) can be used as an operator.
https://jdbc.postgresql.org/documentation/query/#using-the-statement-or-preparedstatement-interface

But I removed some useless check/binding implementations because I already check for DEFAULT

Copy link
Collaborator

Choose a reason for hiding this comment

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

sounds good. I'm still wishing that this logic was in the driver somewhere instead of the dialect since it looks like a driver constraint, not a postgres one, but lets just merge to fix the underlying issue and then if it becomes a problem later we can revisit.

@AlecKazakova AlecKazakova merged commit 4c0f582 into cashapp:master Oct 3, 2022
@hfhbd hfhbd deleted the defaults branch October 3, 2022 21:09
AlecKazakova pushed a commit that referenced this pull request Oct 3, 2022
@hfhbd hfhbd restored the defaults branch October 3, 2022 22:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants