-
Notifications
You must be signed in to change notification settings - Fork 868
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
inappropriate statement sharing #674
inappropriate statement sharing #674
Conversation
when parameter type changed
Check original parameter type when current parameter type is Oid.UNSPECIFIED. fixes pgjdbc#648
Current coverage is 64.12% (diff: 60.00%)@@ master #674 diff @@
==========================================
Files 165 164 -1
Lines 15129 15131 +2
Methods 0 0
Messages 0 0
Branches 2978 2982 +4
==========================================
+ Hits 9694 9703 +9
+ Misses 4201 4193 -8
- Partials 1234 1235 +1
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please update test code. Please add batch insert into t(...) values(?)
kind of test.
insert values
is needed for two reasons:
-
test insert case;
-
test how the fix plays with "insert batch rewritter".
PreparedStatement ps = con.prepareStatement("SELECT ?::timestamp"); | ||
try { | ||
Timestamp ts = new Timestamp(1474997614836L); | ||
for (int i = 0; i < 3; ++i) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is it required to have a loop here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because PreparedStatement is not cached after first executions. But after 5-th executions (which happens on 3-rd iteration) it become cached.
rs = ps.executeQuery(); | ||
try { | ||
assertTrue(rs.next()); | ||
assertNull(rs.getObject(1)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please follow https://github.com/pgjdbc/pgjdbc/blob/master/CONTRIBUTING.md#test guidelines for writing tests and assertions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I read the rules for the tests writing. But not figured, what I'm doing wrong.
Also, there is (into pgjdbc test classes) a lot of code that uses assertTrue for rs.next() and assertEquals without a message.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a lot of code that uses assertTrue for rs.next() and assertEquals without a message.
That is unfortunate. New code should explain what it is trying to test.
I agree assertTrue(rs.next());
might be fine (I would agree even with plain rs.next()
without assert), however assertNull(rs.getObject(1));
should explain why does it expect null
there.
The thing is when test fails, it takes lots of time to figure out what was the intention behind the test and why did it fail.
Having decent messages greatly reduces maintenance costs.
200061c
to
534c05a
Compare
I added comments into the PreparedStatementTest#testInappropriateStatementSharing source code (for readability purposes). |
rs = ps.executeQuery(); | ||
try { | ||
assertTrue(rs.next()); | ||
assertNull(rs.getObject(1)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a lot of code that uses assertTrue for rs.next() and assertEquals without a message.
That is unfortunate. New code should explain what it is trying to test.
I agree assertTrue(rs.next());
might be fine (I would agree even with plain rs.next()
without assert), however assertNull(rs.getObject(1));
should explain why does it expect null
there.
The thing is when test fails, it takes lots of time to figure out what was the intention behind the test and why did it fail.
Having decent messages greatly reduces maintenance costs.
try { | ||
assertTrue(rs.next()); | ||
// If an inappropriate caching occurred, then we'll get the data narrowing (TIMESTAMP -> DATE) | ||
assertEquals(ts, rs.getObject(1)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment above this line should be moved into message argument of assertEquals. That would make error message much cleaner.
@vlsi thanks for you detailed answers. |
Ping on this - I think we might be running into this scenario under some rare conditions. |
I'm sorry to say that, however I need postpone the review to the release after 42.1.0. |
I've been postponing this fix for quite a while now, and now I think the whole notion of "resolving parameter types" is odd (
Current pgjdbc implementation parses the statement with Oid.UNSPECIFIED , receives the updated types from the backend and overwrites UNSPECIFIED with the DB results.
I would try the following approach:
|
…ypes timestamp, date, are sent as UNSPECIFIED, and pgjdbc did not verify the actual parameter types at parse time. This might cause wrong results if the query was parsed with explicit type (e.g. setString(...)), and then re-executed with TIMESTAMP parameter (timestamps are sent as UNSPECIFIED, thus pgjdbc silently accepted the statement even though it should reparse) fixes pgjdbc#648 closes pgjdbc#674
…ypes (#1137) Timestamp, date (and some other types), are sent as UNSPECIFIED, and pgjdbc did not verify the actual parameter types at parse time. This might cause wrong results if the query was parsed with explicit type (e.g. setString(...)), and then re-executed with TIMESTAMP parameter (timestamps are sent as UNSPECIFIED, thus pgjdbc silently accepted the statement even though it should reparse) fixes #648 closes #674
Add more parameter type checks into
SimpleQuery.isPreparedFor
for Oid.UNSPECIFIED parameter type.This commit addresses issue #648