Skip to content

Commit 6e9c756

Browse files
authored
[Backport] Fixed CallableStatement default value regression (2452) (#2456)
* Fixed CallableStatement default value regression (#2452) * Fixed default value regression for cstmts * Adjusted regex * Test update * Updated test p2 * Updated regex * Backport of cstmt default value regression
1 parent 17caf22 commit 6e9c756

File tree

3 files changed

+47
-1
lines changed

3 files changed

+47
-1
lines changed

src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ private void setPreparedStatementHandle(int handle) {
137137
* Regex for JDBC 'call' escape syntax
138138
*/
139139
private static final Pattern callEscapePattern = Pattern
140-
.compile("^\\s*(?i)\\{(\\s*\\??\\s*=?\\s*)call (.+)\\s*\\(?\\?*,?\\)?\\s*}\\s*$");
140+
.compile("^\\s*(?i)\\{(\\s*\\??\\s*=?\\s*)call [^\\(\\)]+\\s*(\\(\\s*\\?\\s*(,\\s*\\?\\s*)*\\))?\\s*}");
141141

142142
/**
143143
* Regex for 'exec' escape syntax

src/test/java/com/microsoft/sqlserver/jdbc/TestResource.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ protected Object[][] getContents() {
4242
{"R_givenValueType", "The given value of type"},
4343
{"R_lengthTruncated", " The inserted length is truncated or not correct!"},
4444
{"R_timeValueTruncated", " The time value is truncated or not correct!"},
45+
{"R_nullPointerExceptionFromResultSet", "Cannot invoke \"java.sql.ResultSet.next()\" because \"rs\" is null"},
4546
{"R_invalidErrorMessage", "Invalid Error Message: "},
4647
{"R_kerberosNativeGSSFailure",
4748
"No valid credentials provided (Mechanism level: Failed to find any Kerberos tgt)"},

src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableStatementTest.java

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ public class CallableStatementTest extends AbstractTest {
5858
.escapeIdentifier(RandomUtil.getIdentifier("CallableStatementTest_setNull_SP"));
5959
private static String inputParamsProcedureName = AbstractSQLGenerator
6060
.escapeIdentifier(RandomUtil.getIdentifier("CallableStatementTest_inputParams_SP"));
61+
private static String conditionalSproc = AbstractSQLGenerator
62+
.escapeIdentifier(RandomUtil.getIdentifier("CallableStatementTest_conditionalSproc"));
6163
private static String getObjectLocalDateTimeProcedureName = AbstractSQLGenerator
6264
.escapeIdentifier(RandomUtil.getIdentifier("CallableStatementTest_getObjectLocalDateTime_SP"));
6365
private static String getObjectOffsetDateTimeProcedureName = AbstractSQLGenerator
@@ -98,6 +100,7 @@ public static void setupTest() throws Exception {
98100
TestUtils.dropProcedureIfExists(zeroParamSproc, stmt);
99101
TestUtils.dropProcedureIfExists(outOfOrderSproc, stmt);
100102
TestUtils.dropProcedureIfExists(byParamNameSproc, stmt);
103+
TestUtils.dropProcedureIfExists(conditionalSproc, stmt);
101104
TestUtils.dropFunctionIfExists(userDefinedFunction, stmt);
102105
TestUtils.dropUserDefinedTypeIfExists(manyParamUserDefinedType, stmt);
103106
TestUtils.dropProcedureIfExists(manyParamProc, stmt);
@@ -115,6 +118,7 @@ public static void setupTest() throws Exception {
115118
createProcedureZeroParams();
116119
createOutOfOrderSproc();
117120
createByParamNameSproc();
121+
createConditionalProcedure();
118122
createUserDefinedFunction();
119123
}
120124
}
@@ -1150,6 +1154,38 @@ public void testExecDocumentedSystemStoredProceduresIndexedParameters() throws S
11501154
}
11511155
}
11521156

1157+
@Test
1158+
public void testCallableStatementDefaultValues() throws SQLException {
1159+
String call0 = "{call " + conditionalSproc + " (?, ?, 1)}";
1160+
String call1 = "{call " + conditionalSproc + " (?, ?, 2)}";
1161+
int expectedValue = 5; // The sproc should return this value
1162+
1163+
try (CallableStatement cstmt = connection.prepareCall(call0)) {
1164+
cstmt.setInt(1, 1);
1165+
cstmt.setInt(2, 2);
1166+
cstmt.execute();
1167+
ResultSet rs = cstmt.getResultSet();
1168+
rs.next();
1169+
fail(TestResource.getResource("R_expectedFailPassed"));
1170+
1171+
} catch (Exception e) {
1172+
String msg = e.getMessage();
1173+
assertTrue(TestResource
1174+
.getResource("R_nullPointerExceptionFromResultSet").equalsIgnoreCase(msg)
1175+
|| msg == null);
1176+
}
1177+
1178+
try (CallableStatement cstmt = connection.prepareCall(call1)) {
1179+
cstmt.setInt(1, 1);
1180+
cstmt.setInt(2, 2);
1181+
cstmt.execute();
1182+
ResultSet rs = cstmt.getResultSet();
1183+
rs.next();
1184+
1185+
assertEquals(Integer.toString(expectedValue), rs.getString(1));
1186+
}
1187+
}
1188+
11531189
@Test
11541190
@Tag(Constants.reqExternalSetup)
11551191
@Tag(Constants.xAzureSQLDB)
@@ -1242,6 +1278,7 @@ public static void cleanup() throws SQLException {
12421278
TestUtils.dropProcedureIfExists(zeroParamSproc, stmt);
12431279
TestUtils.dropProcedureIfExists(outOfOrderSproc, stmt);
12441280
TestUtils.dropProcedureIfExists(byParamNameSproc, stmt);
1281+
TestUtils.dropProcedureIfExists(conditionalSproc, stmt);
12451282
TestUtils.dropFunctionIfExists(userDefinedFunction, stmt);
12461283
}
12471284
}
@@ -1294,6 +1331,14 @@ private static void createProcedureManyParams() throws SQLException {
12941331
}
12951332
}
12961333

1334+
private static void createConditionalProcedure() throws SQLException {
1335+
String sql = "CREATE PROCEDURE " + conditionalSproc + " @param0 INT, @param1 INT, @maybe bigint = 2 " +
1336+
"AS BEGIN IF @maybe >= 2 BEGIN SELECT 5 END END";
1337+
try (Statement stmt = connection.createStatement()) {
1338+
stmt.execute(sql);
1339+
}
1340+
}
1341+
12971342
private static void createTableManyParams() throws SQLException {
12981343
String type = manyParamUserDefinedType;
12991344
String sql = "CREATE TABLE" + manyParamsTable + " (c1 " + type + " null, " + "c2 " + type + " null, " + "c3 "

0 commit comments

Comments
 (0)