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 | Misleading error message in CallableStatement #1064

Merged
merged 19 commits into from
Jun 10, 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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;


/**
Expand Down Expand Up @@ -67,6 +70,9 @@ String getClassNameInternal() {
return "SQLServerCallableStatement";
}

Map<String, Integer> map = new ConcurrentHashMap<>();
AtomicInteger ai = new AtomicInteger(0);

/**
* Create a new callable statement.
*
Expand Down Expand Up @@ -1294,10 +1300,13 @@ private int findColumn(String columnName) throws SQLServerException {
}

int l = 0;
if (parameterNames != null)
if (null != parameterNames) {
l = parameterNames.size();
if (l == 0)// Server didn't return anything, user might not have access
return 1;// attempting to look up the first column will return no access exception
}
if (l == 0) { // Server didn't return anything, user might not have access
map.putIfAbsent(columnName, ai.incrementAndGet());
return map.get(columnName);// attempting to look up the first column will return no access exception
rene-ye marked this conversation as resolved.
Show resolved Hide resolved
rene-ye marked this conversation as resolved.
Show resolved Hide resolved
}

// handle `@name` as well as `name`, since `@name` is what's returned
// by DatabaseMetaData#getProcedureColumns
Expand Down
7 changes: 6 additions & 1 deletion src/test/java/com/microsoft/sqlserver/jdbc/TestResource.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ public final class TestResource extends ListResourceBundle {
public static String getResource(String key) {
return TestResource.getBundle(Constants.MSSQL_JDBC_PACKAGE + ".TestResource").getString(key);
}

public static String formatErrorMsg(String resource) {
return (".*\\Q" + getResource(resource) + "\\E").replaceAll("\\{+[0-9]+\\}", "\\\\E.*\\\\Q");
}
rene-ye marked this conversation as resolved.
Show resolved Hide resolved

protected Object[][] getContents() {
return contents;
Expand Down Expand Up @@ -173,5 +177,6 @@ protected Object[][] getContents() {
{"R_incorrectSyntaxTable", "Incorrect syntax near the keyword 'table'."},
{"R_incorrectSyntaxTableDW", "Incorrect syntax near 'table'."},
{"R_ConnectionStringNull", "Connection String should not be null"},
{"R_OperandTypeClash", "Operand type clash"}};
{"R_OperandTypeClash", "Operand type clash"},
{"R_NoPrivilege", "The EXECUTE permission was denied on the object {0}"}};
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
package com.microsoft.sqlserver.jdbc.callablestatement;

import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.jupiter.api.Assertions.assertEquals;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.UUID;

import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.junit.platform.runner.JUnitPlatform;
import org.junit.runner.RunWith;

import com.microsoft.sqlserver.jdbc.RandomUtil;
import com.microsoft.sqlserver.jdbc.TestResource;
import com.microsoft.sqlserver.jdbc.TestUtils;
import com.microsoft.sqlserver.testframework.AbstractSQLGenerator;
import com.microsoft.sqlserver.testframework.AbstractTest;
Expand Down Expand Up @@ -78,4 +83,42 @@ public void datatypestest() throws Exception {
}
}
}

@Test
@Tag("xAzureSQLDB")
@Tag("xAzureSQLDW")
@Tag("xAzureSQLMI")
public void noPrivilegeTest() throws SQLException {
try (Connection c = getConnection(); Statement stmt = c.createStatement()) {
String tableName = RandomUtil.getIdentifier("jdbc_priv");
String procName = RandomUtil.getIdentifier("priv_proc");
String user = "priv_user" + UUID.randomUUID();
String pass = "priv_pass" + UUID.randomUUID();

stmt.execute(
"CREATE TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName) + " (id int, name varchar(50))");
stmt.execute("CREATE PROC " + AbstractSQLGenerator.escapeIdentifier(procName)
+ " @id int, @str varchar(50) as INSERT INTO " + AbstractSQLGenerator.escapeIdentifier(tableName)
+ " values(@id,@str)");
stmt.execute(
"CREATE LOGIN " + AbstractSQLGenerator.escapeIdentifier(user) + " WITH password='" + pass + "'");
stmt.execute("CREATE USER " + AbstractSQLGenerator.escapeIdentifier(user) + "");
try {
stmt.execute("EXECUTE AS USER='" + user + "';EXECUTE " + AbstractSQLGenerator.escapeIdentifier(procName)
+ " 1,'hi';");
fail(TestResource.getResource("R_shouldThrowException"));
} catch (SQLException e) {
assertTrue(e.getMessage().matches(TestResource.formatErrorMsg("R_NoPrivilege")));
} finally {
TestUtils.dropProcedureIfExists(procName, stmt);
rene-ye marked this conversation as resolved.
Show resolved Hide resolved
TestUtils.dropTableIfExists(tableName, stmt);
stmt.close();
rene-ye marked this conversation as resolved.
Show resolved Hide resolved
c.close();
try (Connection c2 = getConnection(); Statement stmt2 = c2.createStatement()) {
stmt2.execute("DROP USER " + AbstractSQLGenerator.escapeIdentifier(user));
stmt2.execute("DROP LOGIN " + AbstractSQLGenerator.escapeIdentifier(user));
}
}
cheenamalhotra marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public static void setupTest() throws SQLException {

createGUIDTable(stmt);
createGUIDStoredProcedure(stmt);
createSetNullPreocedure(stmt);
createSetNullProcedure(stmt);
createInputParamsProcedure(stmt);
}
}
Expand Down Expand Up @@ -195,7 +195,7 @@ private static void createGUIDTable(Statement stmt) throws SQLException {
stmt.execute(sql);
}

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