Skip to content

Commit 9ff36a5

Browse files
Fix | Misleading error message in CallableStatement (#1064)
* Fix | Callablestatement not setting parameter properly when columns aren't found * Fix | Typo in tests * Fix | Typo fix cont... * Add | Tests * Fix | null check * Update src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixedTest.java Co-Authored-By: Cheena Malhotra <v-chmalh@microsoft.com> * Update src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixedTest.java Co-Authored-By: Cheena Malhotra <v-chmalh@microsoft.com> * Update src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixedTest.java Co-Authored-By: Cheena Malhotra <v-chmalh@microsoft.com> * Update src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixedTest.java Co-Authored-By: Cheena Malhotra <v-chmalh@microsoft.com> * Update src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixedTest.java Co-Authored-By: Cheena Malhotra <v-chmalh@microsoft.com> * Update src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixedTest.java Co-Authored-By: Cheena Malhotra <v-chmalh@microsoft.com>
1 parent 3447732 commit 9ff36a5

File tree

4 files changed

+63
-6
lines changed

4 files changed

+63
-6
lines changed

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

+12-3
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@
2626
import java.text.MessageFormat;
2727
import java.util.ArrayList;
2828
import java.util.Calendar;
29+
import java.util.Map;
2930
import java.util.UUID;
31+
import java.util.concurrent.ConcurrentHashMap;
32+
import java.util.concurrent.atomic.AtomicInteger;
3033

3134

3235
/**
@@ -67,6 +70,9 @@ String getClassNameInternal() {
6770
return "SQLServerCallableStatement";
6871
}
6972

73+
Map<String, Integer> map = new ConcurrentHashMap<>();
74+
AtomicInteger ai = new AtomicInteger(0);
75+
7076
/**
7177
* Create a new callable statement.
7278
*
@@ -1294,10 +1300,13 @@ private int findColumn(String columnName) throws SQLServerException {
12941300
}
12951301

12961302
int l = 0;
1297-
if (parameterNames != null)
1303+
if (null != parameterNames) {
12981304
l = parameterNames.size();
1299-
if (l == 0)// Server didn't return anything, user might not have access
1300-
return 1;// attempting to look up the first column will return no access exception
1305+
}
1306+
if (l == 0) { // Server didn't return anything, user might not have access
1307+
map.putIfAbsent(columnName, ai.incrementAndGet());
1308+
return map.get(columnName);// attempting to look up the first column will return no access exception
1309+
}
13011310

13021311
// handle `@name` as well as `name`, since `@name` is what's returned
13031312
// by DatabaseMetaData#getProcedureColumns

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

+6-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ public final class TestResource extends ListResourceBundle {
1818
public static String getResource(String key) {
1919
return TestResource.getBundle(Constants.MSSQL_JDBC_PACKAGE + ".TestResource").getString(key);
2020
}
21+
22+
public static String formatErrorMsg(String resource) {
23+
return (".*\\Q" + getResource(resource) + "\\E").replaceAll("\\{+[0-9]+\\}", "\\\\E.*\\\\Q");
24+
}
2125

2226
protected Object[][] getContents() {
2327
return contents;
@@ -174,5 +178,6 @@ protected Object[][] getContents() {
174178
{"R_incorrectSyntaxTable", "Incorrect syntax near the keyword 'table'."},
175179
{"R_incorrectSyntaxTableDW", "Incorrect syntax near 'table'."},
176180
{"R_ConnectionStringNull", "Connection String should not be null"},
177-
{"R_OperandTypeClash", "Operand type clash"}};
181+
{"R_OperandTypeClash", "Operand type clash"},
182+
{"R_NoPrivilege", "The EXECUTE permission was denied on the object {0}"}};
178183
}

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

+43
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,23 @@
11
package com.microsoft.sqlserver.jdbc.callablestatement;
22

3+
import static org.junit.Assert.assertTrue;
4+
import static org.junit.Assert.fail;
35
import static org.junit.jupiter.api.Assertions.assertEquals;
46

57
import java.sql.CallableStatement;
68
import java.sql.Connection;
79
import java.sql.ResultSet;
10+
import java.sql.SQLException;
811
import java.sql.Statement;
12+
import java.util.UUID;
913

1014
import org.junit.jupiter.api.Tag;
1115
import org.junit.jupiter.api.Test;
1216
import org.junit.platform.runner.JUnitPlatform;
1317
import org.junit.runner.RunWith;
1418

1519
import com.microsoft.sqlserver.jdbc.RandomUtil;
20+
import com.microsoft.sqlserver.jdbc.TestResource;
1621
import com.microsoft.sqlserver.jdbc.TestUtils;
1722
import com.microsoft.sqlserver.testframework.AbstractSQLGenerator;
1823
import com.microsoft.sqlserver.testframework.AbstractTest;
@@ -79,4 +84,42 @@ public void datatypestest() throws Exception {
7984
}
8085
}
8186
}
87+
88+
@Test
89+
@Tag("xAzureSQLDB")
90+
@Tag("xAzureSQLDW")
91+
@Tag("xAzureSQLMI")
92+
public void noPrivilegeTest() throws SQLException {
93+
try (Connection c = getConnection(); Statement stmt = c.createStatement()) {
94+
String tableName = RandomUtil.getIdentifier("jdbc_priv");
95+
String procName = RandomUtil.getIdentifier("priv_proc");
96+
String user = "priv_user" + UUID.randomUUID();
97+
String pass = "priv_pass" + UUID.randomUUID();
98+
99+
stmt.execute(
100+
"CREATE TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName) + " (id int, name varchar(50))");
101+
stmt.execute("CREATE PROC " + AbstractSQLGenerator.escapeIdentifier(procName)
102+
+ " @id int, @str varchar(50) as INSERT INTO " + AbstractSQLGenerator.escapeIdentifier(tableName)
103+
+ " values(@id,@str)");
104+
stmt.execute(
105+
"CREATE LOGIN " + AbstractSQLGenerator.escapeIdentifier(user) + " WITH password='" + pass + "'");
106+
stmt.execute("CREATE USER " + AbstractSQLGenerator.escapeIdentifier(user) + "");
107+
try {
108+
stmt.execute("EXECUTE AS USER='" + user + "';EXECUTE " + AbstractSQLGenerator.escapeIdentifier(procName)
109+
+ " 1,'hi';");
110+
fail(TestResource.getResource("R_shouldThrowException"));
111+
} catch (SQLException e) {
112+
assertTrue(e.getMessage().matches(TestResource.formatErrorMsg("R_NoPrivilege")));
113+
} finally {
114+
TestUtils.dropProcedureIfExists(procName, stmt);
115+
TestUtils.dropTableIfExists(tableName, stmt);
116+
stmt.close();
117+
c.close();
118+
try (Connection c2 = getConnection(); Statement stmt2 = c2.createStatement()) {
119+
stmt2.execute("DROP USER " + AbstractSQLGenerator.escapeIdentifier(user));
120+
stmt2.execute("DROP LOGIN " + AbstractSQLGenerator.escapeIdentifier(user));
121+
}
122+
}
123+
}
124+
}
82125
}

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public static void setupTest() throws SQLException {
5656

5757
createGUIDTable(stmt);
5858
createGUIDStoredProcedure(stmt);
59-
createSetNullPreocedure(stmt);
59+
createSetNullProcedure(stmt);
6060
createInputParamsProcedure(stmt);
6161
}
6262
}
@@ -195,7 +195,7 @@ private static void createGUIDTable(Statement stmt) throws SQLException {
195195
stmt.execute(sql);
196196
}
197197

198-
private static void createSetNullPreocedure(Statement stmt) throws SQLException {
198+
private static void createSetNullProcedure(Statement stmt) throws SQLException {
199199
stmt.execute("create procedure " + AbstractSQLGenerator.escapeIdentifier(setNullProcedureName)
200200
+ " (@p1 nvarchar(255), @p2 nvarchar(255) output) as select @p2=@p1 return 0");
201201
}

0 commit comments

Comments
 (0)