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

fix: allow OUT parameter registration when using CallableStatement na… #1561

Merged
merged 2 commits into from Nov 26, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
15 changes: 15 additions & 0 deletions pgjdbc/src/main/java/org/postgresql/core/Parser.java
Expand Up @@ -1040,6 +1040,21 @@ public static JdbcCallParseInfo modifyJdbcCall(String jdbcSql, boolean stdString
if (i == len && !syntaxError) {
if (state == 1) {
// Not an escaped syntax.

// Detect PostgreSQL native CALL.
// (OUT parameter registration, needed for stored procedures with INOUT arguments, will fail without this)
i = 0;
while (i < len && Character.isWhitespace(jdbcSql.charAt(i))) {
i++; // skip any preceding whitespace
}
if (i < len - 5) { // 5 == length of "call" + 1 whitespace
//Check for CALL followed by whitespace
char ch = jdbcSql.charAt(i);
if ((ch == 'c' || ch == 'C') && jdbcSql.substring(i, i + 4).equalsIgnoreCase("call")
&& Character.isWhitespace(jdbcSql.charAt(i + 4))) {
isFunction = true;
}
}
return new JdbcCallParseInfo(sql, isFunction);
}
if (state != 8) {
Expand Down
Expand Up @@ -11,6 +11,7 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import org.postgresql.core.ServerVersion;
import org.postgresql.test.TestUtil;
import org.postgresql.test.jdbc2.BaseTest4;
import org.postgresql.util.PSQLState;
Expand Down Expand Up @@ -84,6 +85,12 @@ public void setUp() throws Exception {
+ "end;'"
+ "LANGUAGE plpgsql VOLATILE;"
);
if (TestUtil.haveMinimumServerVersion(con, ServerVersion.v11)) {
stmt.execute(
"CREATE OR REPLACE PROCEDURE inonlyprocedure(a IN int) AS 'BEGIN NULL; END;' LANGUAGE plpgsql");
stmt.execute(
"CREATE OR REPLACE PROCEDURE inoutprocedure(a INOUT int) AS 'BEGIN a := a + a; END;' LANGUAGE plpgsql");
}
}

@Override
Expand All @@ -97,6 +104,10 @@ public void tearDown() throws SQLException {
stmt.execute("drop function myif(a INOUT int, b IN int)");
stmt.execute("drop function mynoparams()");
stmt.execute("drop function mynoparamsproc()");
if (TestUtil.haveMinimumServerVersion(con, ServerVersion.v11)) {
stmt.execute("drop procedure inonlyprocedure(a IN int)");
stmt.execute("drop procedure inoutprocedure(a INOUT int)");
}
stmt.close();
super.tearDown();
}
Expand Down Expand Up @@ -1034,4 +1045,26 @@ public void testProcedureNoParametersWithoutParentheses() throws SQLException {
TestUtil.closeQuietly(cs);
}

@Test
public void testProcedureInOnlyNativeCall() throws SQLException {
assumeMinimumServerVersion(ServerVersion.v11);
assumeCallableStatementsSupported();
CallableStatement cs = con.prepareCall("call inonlyprocedure(?)");
cs.setInt(1, 5);
cs.execute();
TestUtil.closeQuietly(cs);
}

@Test
public void testProcedureInOutNativeCall() throws SQLException {
assumeMinimumServerVersion(ServerVersion.v11);
assumeCallableStatementsSupported();
// inoutprocedure(a INOUT int) returns a*2 via the INOUT parameter
CallableStatement cs = con.prepareCall("call inoutprocedure(?)");
cs.setInt(1, 5);
cs.registerOutParameter(1, Types.INTEGER);
cs.execute();
assertEquals("call inoutprocedure(?) should return 10 (when input param = 5) via the INOUT parameter, but did not.", 10, cs.getInt(1));
TestUtil.closeQuietly(cs);
}
}