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 TVP callable statement exception when sp not exist #265

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 @@ -41,6 +41,8 @@ public final class SQLServerParameterMetaData implements ParameterMetaData {
/* Used for callable statement meta data */
private Statement stmtCall;
private SQLServerResultSet rsProcedureMeta;

protected boolean procedureIsFound = false;

static final private java.util.logging.Logger logger = java.util.logging.Logger
.getLogger("com.microsoft.sqlserver.jdbc.internals.SQLServerParameterMetaData");
Expand Down Expand Up @@ -581,6 +583,16 @@ private void checkClosed() throws SQLServerException {
rsProcedureMeta = s.executeQueryInternal("exec sp_sproc_columns_100 " + sProc + " @ODBCVer=3");
else
rsProcedureMeta = s.executeQueryInternal("exec sp_sproc_columns " + sProc + " @ODBCVer=3");

// if rsProcedureMeta has next row, it means the stored procedure is found
if (rsProcedureMeta.next()) {
procedureIsFound = true;
}
else {
procedureIsFound = false;
}
rsProcedureMeta.beforeFirst();

// Sixth is DATA_TYPE
rsProcedureMeta.getColumn(6).setFilter(new DataTypeFilter());
if (con.isKatmaiOrLater()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2199,6 +2199,13 @@ String getTVPNameIfNull(int n,
if(null != this.procedureName) {
SQLServerParameterMetaData pmd = (SQLServerParameterMetaData) this.getParameterMetaData();
pmd.isTVP = true;

if (!pmd.procedureIsFound) {
MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_StoredProcedureNotFound"));
Object[] msgArgs = {this.procedureName};
SQLServerException.makeFromDriverError(connection, pmd, form.format(msgArgs), null, false);
}

try {
String tvpNameWithoutSchema = pmd.getParameterTypeName(n);
String tvpSchema = pmd.getTVPSchemaFromStoredProcedure(n);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,7 @@ protected Object[][] getContents() {
{"R_serverPreparedStatementDiscardThreshold", "The serverPreparedStatementDiscardThreshold {0} is not valid."},
{"R_kerberosLoginFailedForUsername", "Cannot login with Kerberos principal {0}, check your credentials. {1}"},
{"R_kerberosLoginFailed", "Kerberos Login failed: {0} due to {1} ({2})"},
{"R_StoredProcedureNotFound", "Could not find stored procedure ''{0}''."},
{"R_jaasConfigurationNamePropertyDescription", "Login configuration file for Kerberos authentication."},
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,27 +29,27 @@
@RunWith(JUnitPlatform.class)
public class ParameterMetaDataTest extends AbstractTest {
private static final String tableName = "[" + RandomUtil.getIdentifier("StatementParam") + "]";

/**
* Test ParameterMetaData#isWrapperFor and ParameterMetaData#unwrap.
*
* @throws SQLException
*/
@Test
public void testParameterMetaDataWrapper() throws SQLException {
try (Connection con = DriverManager.getConnection(connectionString);
Statement stmt = con.createStatement()) {
try (Connection con = DriverManager.getConnection(connectionString); Statement stmt = con.createStatement()) {

stmt.executeUpdate("create table " + tableName + " (col1 int identity(1,1) primary key)");
try {
String query = "SELECT * from " + tableName + " where col1 = ?";

try (PreparedStatement pstmt = con.prepareStatement(query)) {
ParameterMetaData parameterMetaData = pstmt.getParameterMetaData();
assertTrue(parameterMetaData.isWrapperFor(ParameterMetaData.class));
assertSame(parameterMetaData, parameterMetaData.unwrap(ParameterMetaData.class));
}
} finally {
}
finally {
Utils.dropTableIfExists(tableName, stmt);
}

Expand Down
54 changes: 51 additions & 3 deletions src/test/java/com/microsoft/sqlserver/jdbc/tvp/TVPIssuesTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
package com.microsoft.sqlserver.jdbc.tvp;

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

import java.io.IOException;
import java.sql.Connection;
Expand All @@ -22,6 +23,8 @@
import org.junit.platform.runner.JUnitPlatform;
import org.junit.runner.RunWith;

import com.microsoft.sqlserver.jdbc.SQLServerCallableStatement;
import com.microsoft.sqlserver.jdbc.SQLServerException;
import com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement;
import com.microsoft.sqlserver.jdbc.SQLServerStatement;
import com.microsoft.sqlserver.testframework.AbstractTest;
Expand All @@ -32,9 +35,10 @@ public class TVPIssuesTest extends AbstractTest {

static Connection connection = null;
static Statement stmt = null;
private static String tvpName = "tryTVP_RS_varcharMax_4001_Issue";
private static String srcTable = "tryTVP_RS_varcharMax_4001_Issue_src";
private static String desTable = "tryTVP_RS_varcharMax_4001_Issue_dest";
private static String tvpName = "TVPIssuesTest_TVP";
private static String procedureName = "TVPIssuesTest_SP";
private static String srcTable = "TVPIssuesTest_src";
private static String desTable = "TVPIssuesTest_dest";

@Test
public void tryTVP_RS_varcharMax_4001_Issue() throws Exception {
Expand All @@ -52,6 +56,34 @@ public void tryTVP_RS_varcharMax_4001_Issue() throws Exception {
testDestinationTable();
}

/**
* Test exception when invalid stored procedure name is used.
*
* @throws Exception
*/
@Test
public void testExceptionWithInvalidStoredProcedureName() throws Exception {
SQLServerStatement st = (SQLServerStatement) connection.createStatement();
ResultSet rs = st.executeQuery("select * from " + srcTable);

dropProcedure();

final String sql = "{call " + procedureName + "(?)}";
SQLServerCallableStatement Cstmt = (SQLServerCallableStatement) connection.prepareCall(sql);
try {
Cstmt.setObject(1, rs);
throw new Exception("Expected Exception for invalied stored procedure name is not thrown.");
}
catch (Exception e) {
if (e instanceof SQLServerException) {
assertTrue(e.getMessage().contains("Could not find stored procedure"), "Invalid Error Message.");
}
else {
throw e;
}
}
}

private void testDestinationTable() throws SQLException, IOException {
ResultSet rs = connection.createStatement().executeQuery("select * from " + desTable);
while (rs.next()) {
Expand Down Expand Up @@ -83,6 +115,8 @@ public static void beforeAll() throws SQLException {
connection = DriverManager.getConnection(connectionString);
stmt = connection.createStatement();

dropProcedure();

stmt.executeUpdate("IF EXISTS (SELECT * FROM sys.types WHERE is_table_type = 1 AND name = '" + tvpName + "') " + " drop type " + tvpName);
Utils.dropTableIfExists(srcTable, stmt);
Utils.dropTableIfExists(desTable, stmt);
Expand All @@ -96,11 +130,25 @@ public static void beforeAll() throws SQLException {
String TVPCreateCmd = "CREATE TYPE " + tvpName + " as table (c1 varchar(max) null)";
stmt.executeUpdate(TVPCreateCmd);

createPreocedure();

populateSourceTable();
}

private static void dropProcedure() throws SQLException {
Utils.dropProcedureIfExists(procedureName, stmt);
}

private static void createPreocedure() throws SQLException {
String sql = "CREATE PROCEDURE " + procedureName + " @InputData " + tvpName + " READONLY " + " AS " + " BEGIN " + " INSERT INTO " + desTable
+ " SELECT * FROM @InputData" + " END";

stmt.execute(sql);
}

@AfterAll
public static void terminateVariation() throws SQLException {
dropProcedure();
stmt.executeUpdate("IF EXISTS (SELECT * FROM sys.types WHERE is_table_type = 1 AND name = '" + tvpName + "') " + " drop type " + tvpName);
Utils.dropTableIfExists(srcTable, stmt);
Utils.dropTableIfExists(desTable, stmt);
Expand Down