Skip to content

Commit 0e97689

Browse files
authored
Fixed regression with specifying arg names in call syntax (#2480)
* Fixed regression with specifying arg names in call syntax * Corrected inefficient regex * Corrected inefficient regex * Corrected inefficient regex p2 * Corrected inefficient regex p3 * Corrected inefficient regex p4 * Updated changelog * Added comment
1 parent fdf5430 commit 0e97689

File tree

3 files changed

+34
-2
lines changed

3 files changed

+34
-2
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](http://keepachangelog.com/)
55

66
## [12.8.0] Stable Release
7-
- No changes since previous release
7+
### Fixed issues
8+
- Fixed regression with specifying argument names in callable statement syntax [#2480](https://github.com/microsoft/mssql-jdbc/pull/2480)
89

910
## [12.7.1] Preview Release
1011
### Added

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,9 +137,12 @@ private void setPreparedStatementHandle(int handle) {
137137

138138
/**
139139
* Regex for JDBC 'call' escape syntax
140+
*
141+
* Matches {[? =] call sproc ([@arg =] ?, [@arg =] ?, [@arg =] ? ...)}
140142
*/
141143
private static final Pattern callEscapePattern = Pattern
142-
.compile("^\\s*(?i)\\{(\\s*\\??\\s*=?\\s*)call [^\\(\\)]+\\s*((\\(\\s*\\?\\s*(,\\s*\\?\\s*)*\\))?|\\(\\))\\s*}");
144+
.compile("^\\s*(?i)\\{(\\s*\\??\\s*=?\\s*)call [^\\(\\)]+\\s*" +
145+
"((\\(\\s*(.+\\s*=\\s*)?\\?\\s*(,\\s*\\?\\s*)*\\))?|\\(\\))\\s*}");
143146

144147
/**
145148
* Regex for 'exec' escape syntax

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

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import java.util.TimeZone;
2323
import java.util.UUID;
2424

25+
import org.junit.Assert;
2526
import org.junit.jupiter.api.AfterAll;
2627
import org.junit.jupiter.api.BeforeAll;
2728
import org.junit.jupiter.api.Tag;
@@ -57,6 +58,8 @@ public class CallableStatementTest extends AbstractTest {
5758
.escapeIdentifier(RandomUtil.getIdentifier("CallableStatementTest_inputParams_SP"));
5859
private static String conditionalSproc = AbstractSQLGenerator
5960
.escapeIdentifier(RandomUtil.getIdentifier("CallableStatementTest_conditionalSproc"));
61+
private static String simpleRetValSproc = AbstractSQLGenerator
62+
.escapeIdentifier(RandomUtil.getIdentifier("CallableStatementTest_simpleSproc"));
6063
private static String getObjectLocalDateTimeProcedureName = AbstractSQLGenerator
6164
.escapeIdentifier(RandomUtil.getIdentifier("CallableStatementTest_getObjectLocalDateTime_SP"));
6265
private static String getObjectOffsetDateTimeProcedureName = AbstractSQLGenerator
@@ -100,6 +103,7 @@ public static void setupTest() throws Exception {
100103
TestUtils.dropProcedureIfExists(outOfOrderSproc, stmt);
101104
TestUtils.dropProcedureIfExists(byParamNameSproc, stmt);
102105
TestUtils.dropProcedureIfExists(conditionalSproc, stmt);
106+
TestUtils.dropProcedureIfExists(simpleRetValSproc, stmt);
103107
TestUtils.dropFunctionIfExists(userDefinedFunction, stmt);
104108
TestUtils.dropUserDefinedTypeIfExists(manyParamUserDefinedType, stmt);
105109
TestUtils.dropProcedureIfExists(manyParamProc, stmt);
@@ -119,6 +123,7 @@ public static void setupTest() throws Exception {
119123
createOutOfOrderSproc();
120124
createByParamNameSproc();
121125
createConditionalProcedure();
126+
createSimpleRetValSproc();
122127
createUserDefinedFunction();
123128
}
124129
}
@@ -1197,6 +1202,21 @@ public void testCallableStatementDefaultValues() throws SQLException {
11971202
}
11981203
}
11991204

1205+
@Test
1206+
public void testCallableStatementSetByAnnotatedArgs() throws SQLException {
1207+
String call = "{? = call " + simpleRetValSproc + " (@Arg1 = ?)}";
1208+
int expectedValue = 1; // The sproc should return this value
1209+
1210+
try (CallableStatement cstmt = connection.prepareCall(call)) {
1211+
cstmt.registerOutParameter(1, Types.INTEGER);
1212+
cstmt.setInt(1, 2);
1213+
cstmt.setString(2, "foo");
1214+
cstmt.execute();
1215+
1216+
Assert.assertEquals(expectedValue, cstmt.getInt(1));
1217+
}
1218+
}
1219+
12001220
@Test
12011221
@Tag(Constants.reqExternalSetup)
12021222
@Tag(Constants.xAzureSQLDB)
@@ -1305,6 +1325,7 @@ public static void cleanup() throws SQLException {
13051325
TestUtils.dropProcedureIfExists(byParamNameSproc, stmt);
13061326
TestUtils.dropProcedureIfExists(currentTimeProc, stmt);
13071327
TestUtils.dropProcedureIfExists(conditionalSproc, stmt);
1328+
TestUtils.dropProcedureIfExists(simpleRetValSproc, stmt);
13081329
TestUtils.dropFunctionIfExists(userDefinedFunction, stmt);
13091330
}
13101331
}
@@ -1373,6 +1394,13 @@ private static void createConditionalProcedure() throws SQLException {
13731394
}
13741395
}
13751396

1397+
private static void createSimpleRetValSproc() throws SQLException {
1398+
String sql = "CREATE PROCEDURE " + simpleRetValSproc + " (@Arg1 VARCHAR(128)) AS DECLARE @ReturnCode INT RETURN 1";
1399+
try (Statement stmt = connection.createStatement()) {
1400+
stmt.execute(sql);
1401+
}
1402+
}
1403+
13761404
private static void createTableManyParams() throws SQLException {
13771405
String type = manyParamUserDefinedType;
13781406
String sql = "CREATE TABLE" + manyParamsTable + " (c1 " + type + " null, " + "c2 " + type + " null, " + "c3 "

0 commit comments

Comments
 (0)