-
Notifications
You must be signed in to change notification settings - Fork 3.8k
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
sql: allow imprecise pgwire type hints #16672
sql: allow imprecise pgwire type hints #16672
Conversation
df933a3
to
6f9f4d8
Compare
6f9f4d8
to
af24d2a
Compare
Completely reworked. PTAL. |
af24d2a
to
2118506
Compare
🎉🎉🎉 Review status: 0 of 7 files reviewed at latest revision, 8 unresolved discussions, some commit checks failed. pkg/acceptance/java_test.go, line 206 at r3 (raw file):
Could you also try selecting pkg/sql/prepare.go, line 45 at r3 (raw file):
pkg/sql/parser/placeholders.go, line 35 at r3 (raw file):
pkg/sql/parser/placeholders.go, line 139 at r3 (raw file):
pkg/sql/parser/placeholders.go, line 142 at r3 (raw file):
Can you use a pgerror here? pkg/sql/parser/placeholders.go, line 147 at r3 (raw file):
also here pkg/sql/parser/placeholders.go, line 224 at r3 (raw file):
just to confirm my understanding - this change is purely an optimization, correct? pkg/sql/parser/type_check.go, line 812 at r3 (raw file):
do we have a test of this case? Comments from Reviewable |
2118506
to
729bed4
Compare
Review status: 0 of 9 files reviewed at latest revision, 8 unresolved discussions. pkg/sql/prepare.go, line 45 at r3 (raw file): Previously, justinj (Justin Jaffray) wrote…
Done. pkg/sql/parser/placeholders.go, line 35 at r3 (raw file): Previously, justinj (Justin Jaffray) wrote…
Done. pkg/sql/parser/placeholders.go, line 139 at r3 (raw file): Previously, justinj (Justin Jaffray) wrote…
Done. pkg/sql/parser/placeholders.go, line 142 at r3 (raw file): Previously, justinj (Justin Jaffray) wrote…
Done. pkg/sql/parser/placeholders.go, line 147 at r3 (raw file): Previously, justinj (Justin Jaffray) wrote…
Done. pkg/sql/parser/placeholders.go, line 224 at r3 (raw file): Previously, justinj (Justin Jaffray) wrote…
Yes. pkg/sql/parser/type_check.go, line 812 at r3 (raw file): Previously, justinj (Justin Jaffray) wrote…
Yes, in TestPGPrepareFail. It actually failed in CI because I didn't account for the case where no pgwire type hint is set. While fixing this, I realized that there's a better way to express the "overriding" that's happening in this PR. Instead of having types and overridden types, we now have type hints and types in both the placeholder info struct and the prepared statement struct. Now it's simple to understand what's going on. Type hints inform the first typing of a placeholder. If there's no type hint for a placeholder, it's set by the first typing of the placeholder. As soon as a placeholder is actually typed, its placeholder type is set. That can only happen once. The end. Comments from Reviewable |
729bed4
to
c899978
Compare
And in general when there's no placeholder information in the semantic context, we don't need to walk the expression tree replacing placeholders.
c899978
to
4a6caf6
Compare
LGTM modulo question! Review status: 0 of 9 files reviewed at latest revision, 9 unresolved discussions, some commit checks pending. pkg/sql/parser/placeholders.go, line 98 at r6 (raw file):
so I don't 100% know what contexts this function will be used in, but is it conceivable that once we've reported a type in this way, we have to "lock in" to it so that if someone attempts to type it differently later on we won't return a different value? pkg/sql/parser/type_check.go, line 812 at r3 (raw file): Previously, jordanlewis (Jordan Lewis) wrote…
Yes this is much more understandable! 👍 Comments from Reviewable |
Review status: 0 of 9 files reviewed at latest revision, 9 unresolved discussions, all commit checks successful. pkg/acceptance/java_test.go, line 206 at r3 (raw file): Previously, justinj (Justin Jaffray) wrote…
I'm not sure what you mean here can you give a concrete example? pkg/sql/parser/placeholders.go, line 98 at r6 (raw file): Previously, justinj (Justin Jaffray) wrote…
We do have to do that, but unfortunately it needs to be up to the caller, since at the time that we get a type hint we might choose to lock in to a different type. This is done in Placeholder.TypeCheck. Comments from Reviewable |
Review status: 0 of 9 files reviewed at latest revision, 9 unresolved discussions, all commit checks successful. pkg/acceptance/java_test.go, line 206 at r3 (raw file): Previously, jordanlewis (Jordan Lewis) wrote…
I just mean try running a query like pkg/sql/parser/placeholders.go, line 98 at r6 (raw file): Previously, jordanlewis (Jordan Lewis) wrote…
I see, ok! Comments from Reviewable |
I think this is OK, I have a few minor comments below.
For the two first points use an example query and show separately for prepare/execute what happens with their placeholders. Reviewed 7 of 7 files at r4, 2 of 2 files at r5, 9 of 9 files at r6. pkg/sql/logictest/testdata/logic_test/prepare, line 251 at r6 (raw file):
nit: say "statement ok" here and below pkg/sql/parser/placeholders.go, line 224 at r3 (raw file): Previously, jordanlewis (Jordan Lewis) wrote…
This deserves an additional comment: your optimization and, "in the case placeholders are present in the SQL but none are provided during execute, the further type analysis will detect this and report an unassigned placeholder error". (This case is checked in a test, right?) pkg/sql/parser/placeholders.go, line 34 at r6 (raw file):
Please document the difference between the two fields here. pkg/sql/parser/placeholders.go, line 98 at r6 (raw file): Previously, justinj (Justin Jaffray) wrote…
It seems to me that (*PlaceholderInfo).Type() can never be called until Placeholder.TypeCheck has been closed. So it's not so clear to me why this case needs to be handled here. For the use of the hint made in Placeholder.TypeCheck, we could have a separate method (PlaceholderInfo.TypeHint?) pkg/sql/parser/placeholders.go, line 185 at r6 (raw file):
Ugh, why not an error? pkg/sql/parser/placeholders.go, line 189 at r6 (raw file):
override pkg/sql/parser/placeholders.go, line 195 at r6 (raw file):
I don't think the error should be silently dropped. pkg/sql/parser/type_check.go, line 814 at r6 (raw file):
There word "here" in this sentence is unclear. Where is the cast happening? Comments from Reviewable |
4a6caf6
to
b5f0454
Compare
Review status: all files reviewed at latest revision, 15 unresolved discussions, all commit checks successful. pkg/acceptance/java_test.go, line 206 at r3 (raw file): Previously, justinj (Justin Jaffray) wrote…
Hmmm but that has nothing to do with this patch because there's no placeholders there. I don't expect it to change. I did a test with a placeholder and it has a different problem that is not related to this patch:
This produces: Exception in thread "main" org.postgresql.util.PSQLException: Unable to find server array type for provided name INT8. We should open an issue for this but it's not related to this patch. pkg/sql/logictest/testdata/logic_test/prepare, line 251 at r6 (raw file): Previously, knz (kena) wrote…
This whole file is missing pkg/sql/parser/placeholders.go, line 224 at r3 (raw file): Previously, knz (kena) wrote…
Done. Detecting missing placeholders is done before this point for both pgwire execute and sql execute. pkg/sql/parser/placeholders.go, line 34 at r6 (raw file): Previously, knz (kena) wrote…
Done. pkg/sql/parser/placeholders.go, line 98 at r6 (raw file): Previously, knz (kena) wrote…
It's called in two places, during type checking and then later. I think it's more confusing than helpful to segregate the methods, since during type checking we do have to examine both. pkg/sql/parser/placeholders.go, line 185 at r6 (raw file): Previously, knz (kena) wrote…
Done. pkg/sql/parser/placeholders.go, line 189 at r6 (raw file): Previously, knz (kena) wrote…
No, I'm using the past tense here on purpose. pkg/sql/parser/placeholders.go, line 195 at r6 (raw file): Previously, knz (kena) wrote…
You're right, Done. Comments from Reviewable |
b5f0454
to
04f80b1
Compare
TFTRs! |
Great commit message 💯 There's still an error message to fix so you're up for another round of CI anyway, so let's finish the discussion on placeholderinfo.Type(). Reviewed 2 of 2 files at r7. pkg/sql/parser/placeholders.go, line 98 at r6 (raw file): Previously, jordanlewis (Jordan Lewis) wrote…
But that's the thing right? After type checking, we should never be looking at the hints map. Right now if there's a bug and we end up not populating p.Types properly, this method will silently mask that and make PlaceholderInfo.Type respond something because there's still a hint laying around. That's why I would like to find a way to assert the hints are only reachable during type checking and not afterwards. pkg/sql/parser/placeholders.go, line 193 at r7 (raw file):
lowercase Comments from Reviewable |
This commit permits the use of imprecise pgwire or sql type hints by recording any mismatch between the client-provided type hint and the type-system inferred type, and inserting a runtime cast from the placeholder's original type to its inferred type. Before this patch, type hints that were sent via pgwire or SQL (e.g. in `PREPARE x(int) as ...` the `int` is the type hint) were taken perfectly literally. Placeholder type hints were required to match the type system's inferred type for that placeholder. This simple behavior unfortunately leaves us with compatibility issues with some drivers, such as JDBC, which send "imprecise type hints" - type hints that don't exactly match the correct type for the placeholder. The main motivating example is the following query: ``` PREPARE x(INT) AS SELECT * FROM pg_type WHERE oid=$1 ``` In this query, the type hint is `INT` but the inferred type is `OID`, since we don't support heterogeneous comparisons between integer and oid. Previously, this would not type check - but JDBC expects it to. After this patch, if the type hint does not match the inferred type, we insert a runtime cast from the original type to the inferred type. This produces the query `SELECT * FROM pg_type WHERE oid=$1::oid` for our example. We accomplish this by separately storing the type hints from the inferred types. Now, type hints inform the typing of the placeholder during prepare, if present. As soon as a placeholder is typed, the final placeholder type is set and cannot be changed. If the type hint was missing for that placeholder, it is set to the final placeholder type - this is required by pgwire so that the values passed to execute can be parsed properly.
04f80b1
to
35279d8
Compare
Review status: all files reviewed at latest revision, 11 unresolved discussions, all commit checks successful. pkg/sql/parser/placeholders.go, line 98 at r6 (raw file): Previously, knz (kena) wrote…
Okay, I added a boolean flag to the function pkg/sql/parser/placeholders.go, line 193 at r7 (raw file): Previously, knz (kena) wrote…
Done. Comments from Reviewable |
LGTM
--
Sent from my Android device with K-9 Mail. Please excuse my brevity.
|
Woohoo! TFTRs! This one started in March - psyched to get it in. |
Previously #14387.
Resolves #14311.
Resolves #14245.
Resolves #14554.
Resolves #17140.