Skip to content

Commit 39be7f3

Browse files
Johnny PhamDavoud Eshtehari
authored andcommitted
Do not add parameters for sp_describe_parameter_encryption when not provided (dotnet#1115)
* Update SqlCommand.cs * only execute sp_describe_parameter_encryption if parameters not empty * add test * improve test coverage * only go through parameters if not null * revert previous attempt * Update ApiShould.cs * Update ApiShould.cs
1 parent b45cadd commit 39be7f3

File tree

4 files changed

+76
-7
lines changed

4 files changed

+76
-7
lines changed

doc/samples/AzureKeyVaultProviderExample_2_0.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,5 @@ public CustomerRecord(int id, string fName, string lName)
242242
}
243243
}
244244
}
245-
246-
//</Snippet1>
247-
248245
}
246+
//</Snippet1>

src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5824,11 +5824,22 @@ private SqlParameter BuildStoredProcedureStatementForColumnEncryption(string sto
58245824
{
58255825
Debug.Assert(CommandType == CommandType.StoredProcedure, "BuildStoredProcedureStatementForColumnEncryption() should only be called for stored procedures");
58265826
Debug.Assert(!string.IsNullOrWhiteSpace(storedProcedureName), "storedProcedureName cannot be null or empty in BuildStoredProcedureStatementForColumnEncryption");
5827-
Debug.Assert(parameters != null, "parameters cannot be null in BuildStoredProcedureStatementForColumnEncryption");
58285827

58295828
StringBuilder execStatement = new StringBuilder();
58305829
execStatement.Append(@"EXEC ");
58315830

5831+
if (parameters is null)
5832+
{
5833+
execStatement.Append(ParseAndQuoteIdentifier(storedProcedureName, false));
5834+
return new SqlParameter(
5835+
null,
5836+
((execStatement.Length << 1) <= TdsEnums.TYPE_SIZE_LIMIT) ? SqlDbType.NVarChar : SqlDbType.NText,
5837+
execStatement.Length)
5838+
{
5839+
Value = execStatement.ToString()
5840+
};
5841+
}
5842+
58325843
// Find the return value parameter (if any).
58335844
SqlParameter returnValueParameter = null;
58345845
foreach (SqlParameter parameter in parameters)

src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommand.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6771,11 +6771,22 @@ private SqlParameter BuildStoredProcedureStatementForColumnEncryption(string sto
67716771
{
67726772
Debug.Assert(CommandType == CommandType.StoredProcedure, "BuildStoredProcedureStatementForColumnEncryption() should only be called for stored procedures");
67736773
Debug.Assert(!string.IsNullOrWhiteSpace(storedProcedureName), "storedProcedureName cannot be null or empty in BuildStoredProcedureStatementForColumnEncryption");
6774-
Debug.Assert(parameters != null, "parameters cannot be null in BuildStoredProcedureStatementForColumnEncryption");
67756774

67766775
StringBuilder execStatement = new StringBuilder();
67776776
execStatement.Append(@"EXEC ");
67786777

6778+
if (parameters is null)
6779+
{
6780+
execStatement.Append(ParseAndQuoteIdentifier(storedProcedureName, false));
6781+
return new SqlParameter(
6782+
null,
6783+
((execStatement.Length << 1) <= TdsEnums.TYPE_SIZE_LIMIT) ? SqlDbType.NVarChar : SqlDbType.NText,
6784+
execStatement.Length)
6785+
{
6786+
Value = execStatement.ToString()
6787+
};
6788+
}
6789+
67796790
// Find the return value parameter (if any).
67806791
SqlParameter returnValueParameter = null;
67816792
foreach (SqlParameter parameter in parameters)

src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -878,6 +878,53 @@ public void TestExecuteReaderWithCommandBehavior(string connection, CommandBehav
878878
});
879879
}
880880

881+
[ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringSetupForAE))]
882+
[ClassData(typeof(AEConnectionStringProvider))]
883+
public void TestEnclaveStoredProceduresWithAndWithoutParameters(string connectionString)
884+
{
885+
using SqlConnection sqlConnection = new(connectionString);
886+
sqlConnection.Open();
887+
888+
using SqlCommand sqlCommand = new("", sqlConnection, transaction: null,
889+
columnEncryptionSetting: SqlCommandColumnEncryptionSetting.Enabled);
890+
891+
string procWithoutParams = DataTestUtility.GetUniqueName("EnclaveWithoutParams", withBracket: false);
892+
string procWithParam = DataTestUtility.GetUniqueName("EnclaveWithParams", withBracket: false);
893+
894+
try
895+
{
896+
sqlCommand.CommandText = $"CREATE PROCEDURE {procWithoutParams} AS SELECT FirstName, LastName FROM [{_tableName}];";
897+
sqlCommand.ExecuteNonQuery();
898+
sqlCommand.CommandText = $"CREATE PROCEDURE {procWithParam} @id INT AS SELECT FirstName, LastName FROM [{_tableName}] WHERE CustomerId = @id";
899+
sqlCommand.ExecuteNonQuery();
900+
int expectedFields = 2;
901+
902+
sqlCommand.CommandText = procWithoutParams;
903+
sqlCommand.CommandType = CommandType.StoredProcedure;
904+
using (SqlDataReader reader = sqlCommand.ExecuteReader())
905+
{
906+
Assert.Equal(expectedFields, reader.VisibleFieldCount);
907+
}
908+
909+
sqlCommand.CommandText = procWithParam;
910+
sqlCommand.CommandType = CommandType.StoredProcedure;
911+
Exception ex = Assert.Throws<SqlException>(() => sqlCommand.ExecuteReader());
912+
string expectedMsg = $"Procedure or function '{procWithParam}' expects parameter '@id', which was not supplied.";
913+
914+
Assert.Equal(expectedMsg, ex.Message);
915+
916+
sqlCommand.Parameters.AddWithValue("@id", 0);
917+
using (SqlDataReader reader = sqlCommand.ExecuteReader())
918+
{
919+
Assert.Equal(expectedFields, reader.VisibleFieldCount);
920+
}
921+
}
922+
finally
923+
{
924+
DropHelperProcedures(new[] { procWithoutParams, procWithParam }, connectionString);
925+
}
926+
}
927+
881928
[ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringSetupForAE))]
882929
[ClassData(typeof(AEConnectionStringProvider))]
883930
public void TestPrepareWithExecuteNonQuery(string connection)
@@ -2262,15 +2309,17 @@ public void TestSystemProvidersHavePrecedenceOverInstanceLevelProviders(string c
22622309
connection.Open();
22632310
using SqlCommand command = CreateCommandThatRequiresSystemKeyStoreProvider(connection);
22642311
connection.RegisterColumnEncryptionKeyStoreProvidersOnConnection(customKeyStoreProviders);
2265-
command.ExecuteReader();
2312+
SqlDataReader reader = command.ExecuteReader();
2313+
Assert.Equal(3, reader.VisibleFieldCount);
22662314
}
22672315

22682316
using (SqlConnection connection = new(connectionString))
22692317
{
22702318
connection.Open();
22712319
using SqlCommand command = CreateCommandThatRequiresSystemKeyStoreProvider(connection);
22722320
command.RegisterColumnEncryptionKeyStoreProvidersOnCommand(customKeyStoreProviders);
2273-
command.ExecuteReader();
2321+
SqlDataReader reader = command.ExecuteReader();
2322+
Assert.Equal(3, reader.VisibleFieldCount);
22742323
}
22752324
}
22762325

0 commit comments

Comments
 (0)