Skip to content

Commit

Permalink
Merge pull request #265 from v-xiangs/fix-callable-statement-exceptio…
Browse files Browse the repository at this point in the history
…n-when-SP-not-exist

Fix TVP callable statement exception when sp not exist
  • Loading branch information
Suraiya Hameed authored Apr 27, 2017
2 parents 616472b + bed1305 commit ab62a67
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 8 deletions.
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

0 comments on commit ab62a67

Please sign in to comment.