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

Simple query mode callable statement test broken in omni CI #2399

Open
sehrope opened this issue Jan 10, 2022 · 2 comments
Open

Simple query mode callable statement test broken in omni CI #2399

sehrope opened this issue Jan 10, 2022 · 2 comments

Comments

@sehrope
Copy link
Member

sehrope commented Jan 10, 2022

The Omni CI matrix build for simple query mode is broken: https://github.com/pgjdbc/pgjdbc/runs/4757699941?check_suite_focus=true#step:11:341

I think it's a change in the test, not the code itself that's broken though. The only recent change touching that part of the driver is #2386.

@marschall Can you check it out? If not I'll circle back to this later today or tomorrow.

You can reproduce it locally via:

$ ./gradlew clean postgresql:test -DpreferQueryMode=simple --tests org.postgresql.test.jdbc3.Jdbc3CallableStatementTest

> Configure project :
Building pgjdbc 42.3.2-SNAPSHOT

> Task :postgresql:test
FAILURE   0.0sec, org.postgresql.test.jdbc3.Jdbc3CallableStatementTest > testGetBit1WithoutArg
    org.postgresql.util.PSQLException: ERROR: function testspg__getbit1withoutarg(unknown) does not exist
      Hint: No function matches the given name and argument types. You might need to add explicit type casts.
      Position: 15
        at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2675)
        at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2365)
        at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:355)
        at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:490)
        at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:408)
        at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:166)
        at org.postgresql.jdbc.PgCallableStatement.executeWithFlags(PgCallableStatement.java:83)
        at org.postgresql.jdbc.PgPreparedStatement.execute(PgPreparedStatement.java:155)
        at org.postgresql.test.jdbc3.Jdbc3CallableStatementTest.testGetBit1WithoutArg(Jdbc3CallableStatementTest.java:400)

FAILURE   0.1sec, org.postgresql.test.jdbc3.Jdbc3CallableStatementTest > testGetBooleanWithoutArg
    org.postgresql.util.PSQLException: ERROR: function testspg__getbooleanwithoutarg(unknown) does not exist
      Hint: No function matches the given name and argument types. You might need to add explicit type casts.
      Position: 15
        at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2675)
        at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2365)
        at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:355)
        at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:490)
        at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:408)
        at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:166)
        at org.postgresql.jdbc.PgCallableStatement.executeWithFlags(PgCallableStatement.java:83)
        at org.postgresql.jdbc.PgPreparedStatement.execute(PgPreparedStatement.java:155)
        at org.postgresql.test.jdbc3.Jdbc3CallableStatementTest.testGetBooleanWithoutArg(Jdbc3CallableStatementTest.java:985)

FAILURE   0.0sec, org.postgresql.test.jdbc3.Jdbc3CallableStatementTest > testGetBit2WithoutArg
    org.junit.ComparisonFailure: expected:<428[46]> but was:<428[83]>
        at org.junit.Assert.assertEquals(Assert.java:117)
        at org.junit.Assert.assertEquals(Assert.java:146)
        at org.postgresql.test.jdbc3.Jdbc3CallableStatementTest.testGetBit2WithoutArg(Jdbc3CallableStatementTest.java:414)

FAILURE   1.9sec,   33 completed,   3 failed,  23 skipped, org.postgresql.test.jdbc3.Jdbc3CallableStatementTest
FAILURE   2.7sec,   33 completed,   3 failed,  23 skipped, Gradle Test Run :postgresql:test
@sehrope
Copy link
Member Author

sehrope commented Jan 21, 2022

Looked into this a bit and it's an odd one. I think the driver is messing up parsing JDBC function calls without parameters and there's a server bug (feature?) that allows it to work correctly but only in extended query protocol. I don't see anything special in the code that would have broken this in simple mode either. I think the new test created by @marschall just exposed the existing error.

The JDBC call syntax for "{ ? = call testspg__getBit1WithoutArg () }" is being transformed into select * from testspg__getBit1WithoutArg ($1) as result in both simple and extended query mode. That $1 does not make sense because the function does not have any parameters.

But what's odd is that it works fine in extended mode. My guess is that the extra parse step is treating the parameter as void for the purposes of finding the function to invoke.

I haven't dug through the server code to confirm how this works but a manual PREPARE / EXECUTE v.s. directly executing the function in psql seems to match:

postgres=# CREATE FUNCTION foo () RETURNS bool LANGUAGE SQL AS $$ SELECT true; $$;
CREATE FUNCTION
​
postgres=# SELECT foo();
    foo 
-----
    t
(1 row)
​
postgres=# SELECT foo(NULL);
ERROR:  function foo(unknown) does not exist
LINE 1: SELECT foo(NULL);
                ^
HINT:  No function matches the given name and argument types. You might need to add explicit type casts.

postgres=# SELECT foo(NULL::void);
ERROR:  function foo(void) does not exist
LINE 1: SELECT foo(NULL::void);
            ^
HINT:  No function matches the given name and argument types. You might need to add explicit type casts.

​
# Same function call but simulating extended protocol via PREPARE with a void param works
​
postgres=# PREPARE foo_with_void_param (void) AS SELECT foo($1);
PREPARE
​
postgres=# EXECUTE foo_with_void_param (NULL);
    foo 
-----
    t
(1 row)

Next places to look are why the driver JDBC call parsing is adding a $1 and why the server is fine with it.

@davecramer
Copy link
Member

Ya, I thought there was something funky with it.

sehrope added a commit to sehrope/pgjdbc that referenced this issue Jan 25, 2022
Disables the JDBC function call syntax callable statement tests with no arguments
when running the test suite in simple query mode. The new tests fail with simple
query mode as internal JDBC-to-native query parser generates SQL that contains
the out parameters in the SQL body which is only ignored by the server when
processed in an extended parse, bind, execute sequence. When executed as a simple
query command the server does not ignore the extra parameters and the query
fails.

This commit does not fix anything yet. It simply skips the new failing test in simple
query mode so that the rest of the quite can execute. The behavior of the driver has
not changed in the recent additions either, the new tests simply brought to light an
existing issue with simple query mode.

See pgjdbc#2399 for more details.
sehrope added a commit that referenced this issue Jan 25, 2022
Disables the JDBC function call syntax callable statement tests with no arguments
when running the test suite in simple query mode. The new tests fail with simple
query mode as internal JDBC-to-native query parser generates SQL that contains
the out parameters in the SQL body which is only ignored by the server when
processed in an extended parse, bind, execute sequence. When executed as a simple
query command the server does not ignore the extra parameters and the query
fails.

This commit does not fix anything yet. It simply skips the new failing test in simple
query mode so that the rest of the quite can execute. The behavior of the driver has
not changed in the recent additions either, the new tests simply brought to light an
existing issue with simple query mode.

See #2399 for more details.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants