Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.
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
132 changes: 70 additions & 62 deletions src/System.Data.SqlClient/src/System/Data/SqlClient/SqlCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3258,10 +3258,9 @@ private SqlParameter GetParameterForOutputValueExtraction(SqlParameterCollection
return null;
}

private void GetRPCObject(int paramCount, ref _SqlRPC rpc)
private void GetRPCObject(int systemParamCount, int userParamCount, ref _SqlRPC rpc)
{
// Designed to minimize necessary allocations
int ii;
if (rpc == null)
{
if (_rpcArrayOf1 == null)
Expand All @@ -3272,42 +3271,39 @@ private void GetRPCObject(int paramCount, ref _SqlRPC rpc)
rpc = _rpcArrayOf1[0];
}

rpc.ProcID = 0;
rpc.rpcName = null;
rpc.options = 0;
rpc.systemParamCount = systemParamCount;


int currentCount = rpc.systemParams?.Length ?? 0;
// Make sure there is enough space in the parameters and paramoptions arrays
if (rpc.parameters == null || rpc.parameters.Length < paramCount)
{
rpc.parameters = new SqlParameter[paramCount];
}
else if (rpc.parameters.Length > paramCount)
if (currentCount < systemParamCount)
{
rpc.parameters[paramCount] = null; // Terminator
Array.Resize(ref rpc.systemParams, systemParamCount);
Array.Resize(ref rpc.systemParamOptions, systemParamCount);
for (int index = currentCount; index < systemParamCount; index++)
{
rpc.systemParams[index] = new SqlParameter();
}
}
if (rpc.paramoptions == null || (rpc.paramoptions.Length < paramCount))
for (int ii = 0; ii < systemParamCount; ii++)
{
rpc.paramoptions = new byte[paramCount];
rpc.systemParamOptions[ii] = 0;
}
else
if ((rpc.userParamMap?.Length ?? 0) < userParamCount)
{
for (ii = 0; ii < paramCount; ii++)
rpc.paramoptions[ii] = 0;
Array.Resize(ref rpc.userParamMap, userParamCount);
}
}

private void SetUpRPCParameters(_SqlRPC rpc, int startCount, bool inSchema, SqlParameterCollection parameters)
private void SetUpRPCParameters(_SqlRPC rpc, bool inSchema, SqlParameterCollection parameters)
{
int ii;
int paramCount = GetParameterCount(parameters);
int j = startCount;
TdsParser parser = _activeConnection.Parser;
int userParamCount = 0;

for (ii = 0; ii < paramCount; ii++)
for (int index = 0; index < paramCount; index++)
{
SqlParameter parameter = parameters[ii];
parameter.Validate(ii, CommandType.StoredProcedure == CommandType);
SqlParameter parameter = parameters[index];
parameter.Validate(index, CommandType.StoredProcedure == CommandType);

// func will change type to that with a 4 byte length if the type has a two
// byte length and a parameter length > than that expressible in 2 bytes
Expand All @@ -3318,12 +3314,12 @@ private void SetUpRPCParameters(_SqlRPC rpc, int startCount, bool inSchema, SqlP

if (ShouldSendParameter(parameter))
{
rpc.parameters[j] = parameter;
byte options = 0;

// set output bit
if (parameter.Direction == ParameterDirection.InputOutput ||
parameter.Direction == ParameterDirection.Output)
rpc.paramoptions[j] = TdsEnums.RPC_PARAM_BYREF;
options = TdsEnums.RPC_PARAM_BYREF;

// set default value bit
if (parameter.Direction != ParameterDirection.Output)
Expand Down Expand Up @@ -3352,50 +3348,58 @@ private void SetUpRPCParameters(_SqlRPC rpc, int startCount, bool inSchema, SqlP
// TVPs use DEFAULT and do not allow NULL, even for schema only.
if (null == parameter.Value && (!inSchema || SqlDbType.Structured == parameter.SqlDbType))
{
rpc.paramoptions[j] |= TdsEnums.RPC_PARAM_DEFAULT;
options |= TdsEnums.RPC_PARAM_DEFAULT;
}
}

rpc.userParamMap[userParamCount] = ((((long)options) << 32) | (long)index);
userParamCount += 1;
// Must set parameter option bit for LOB_COOKIE if unfilled LazyMat blob
j++;

}
}
rpc.userParamCount = userParamCount;
rpc.userParams = parameters;
}

private _SqlRPC BuildPrepExec(CommandBehavior behavior)
{
Debug.Assert(System.Data.CommandType.Text == this.CommandType, "invalid use of sp_prepexec for stored proc invocation!");
SqlParameter sqlParam;
int j = 3;
const int systemParameterCount = 3;

int count = CountSendableParameters(_parameters);
int userParameterCount = CountSendableParameters(_parameters);

_SqlRPC rpc = null;
GetRPCObject(count + j, ref rpc);
GetRPCObject(systemParameterCount, userParameterCount, ref rpc);

rpc.ProcID = TdsEnums.RPC_PROCID_PREPEXEC;
rpc.rpcName = TdsEnums.SP_PREPEXEC;

//@handle
sqlParam = new SqlParameter(null, SqlDbType.Int);
sqlParam.Direction = ParameterDirection.InputOutput;
sqlParam = rpc.systemParams[0];
sqlParam.SqlDbType = SqlDbType.Int;
sqlParam.Value = _prepareHandle;
rpc.parameters[0] = sqlParam;
rpc.paramoptions[0] = TdsEnums.RPC_PARAM_BYREF;
sqlParam.Size = 4;
sqlParam.Direction = ParameterDirection.InputOutput;
rpc.systemParamOptions[0] = TdsEnums.RPC_PARAM_BYREF;

//@batch_params
string paramList = BuildParamList(_stateObj.Parser, _parameters);
sqlParam = new SqlParameter(null, ((paramList.Length << 1) <= TdsEnums.TYPE_SIZE_LIMIT) ? SqlDbType.NVarChar : SqlDbType.NText, paramList.Length);
sqlParam = rpc.systemParams[1];
sqlParam.SqlDbType = ((paramList.Length << 1) <= TdsEnums.TYPE_SIZE_LIMIT) ? SqlDbType.NVarChar : SqlDbType.NText;
sqlParam.Size = paramList.Length;
sqlParam.Value = paramList;
rpc.parameters[1] = sqlParam;

//@batch_text
string text = GetCommandText(behavior);
sqlParam = new SqlParameter(null, ((text.Length << 1) <= TdsEnums.TYPE_SIZE_LIMIT) ? SqlDbType.NVarChar : SqlDbType.NText, text.Length);
sqlParam = rpc.systemParams[2];
sqlParam.SqlDbType = ((text.Length << 1) <= TdsEnums.TYPE_SIZE_LIMIT) ? SqlDbType.NVarChar : SqlDbType.NText;
sqlParam.Size = text.Length;
sqlParam.Value = text;
rpc.parameters[2] = sqlParam;

SetUpRPCParameters(rpc, j, false, _parameters);
SetUpRPCParameters(rpc, false, _parameters);

return rpc;
}

Expand Down Expand Up @@ -3450,12 +3454,13 @@ private int GetParameterCount(SqlParameterCollection parameters)
private void BuildRPC(bool inSchema, SqlParameterCollection parameters, ref _SqlRPC rpc)
{
Debug.Assert(this.CommandType == System.Data.CommandType.StoredProcedure, "Command must be a stored proc to execute an RPC");
int count = CountSendableParameters(parameters);
GetRPCObject(count, ref rpc);
int userParameterCount = CountSendableParameters(parameters);
GetRPCObject(0, userParameterCount, ref rpc);

rpc.ProcID = 0;
rpc.rpcName = this.CommandText; // just get the raw command text

SetUpRPCParameters(rpc, 0, inSchema, parameters);
SetUpRPCParameters(rpc, inSchema, parameters);
}

//
Expand All @@ -3472,24 +3477,23 @@ private void BuildRPC(bool inSchema, SqlParameterCollection parameters, ref _Sql
private _SqlRPC BuildExecute(bool inSchema)
{
Debug.Assert((int)_prepareHandle != -1, "Invalid call to sp_execute without a valid handle!");
int j = 1;
const int systemParameterCount = 1;

int count = CountSendableParameters(_parameters);
int userParameterCount = CountSendableParameters(_parameters);

_SqlRPC rpc = null;
GetRPCObject(count + j, ref rpc);

SqlParameter sqlParam;
GetRPCObject(systemParameterCount, userParameterCount, ref rpc);

rpc.ProcID = TdsEnums.RPC_PROCID_EXECUTE;
rpc.rpcName = TdsEnums.SP_EXECUTE;

//@handle
sqlParam = new SqlParameter(null, SqlDbType.Int);
SqlParameter sqlParam = rpc.systemParams[0];
sqlParam.SqlDbType = SqlDbType.Int;
sqlParam.Value = _prepareHandle;
rpc.parameters[0] = sqlParam;
sqlParam.Direction = ParameterDirection.Input;

SetUpRPCParameters(rpc, j, inSchema, _parameters);
SetUpRPCParameters(rpc, inSchema, _parameters);
return rpc;
}

Expand All @@ -3503,20 +3507,21 @@ private void BuildExecuteSql(CommandBehavior behavior, string commandText, SqlPa

Debug.Assert((int)_prepareHandle == -1, "This command has an existing handle, use sp_execute!");
Debug.Assert(CommandType.Text == this.CommandType, "invalid use of sp_executesql for stored proc invocation!");
int j;
int systemParamCount;
SqlParameter sqlParam;

int cParams = CountSendableParameters(parameters);
if (cParams > 0)
int userParamCount = CountSendableParameters(parameters);
if (userParamCount > 0)
{
j = 2;
systemParamCount = 2;
}
else
{
j = 1;
systemParamCount = 1;
}

GetRPCObject(cParams + j, ref rpc);
GetRPCObject(systemParamCount, userParamCount, ref rpc);

rpc.ProcID = TdsEnums.RPC_PROCID_EXECUTESQL;
rpc.rpcName = TdsEnums.SP_EXECUTESQL;

Expand All @@ -3525,19 +3530,22 @@ private void BuildExecuteSql(CommandBehavior behavior, string commandText, SqlPa
{
commandText = GetCommandText(behavior);
}
sqlParam = new SqlParameter(null, ((commandText.Length << 1) <= TdsEnums.TYPE_SIZE_LIMIT) ? SqlDbType.NVarChar : SqlDbType.NText, commandText.Length);
sqlParam = rpc.systemParams[0];
sqlParam.SqlDbType = ((commandText.Length << 1) <= TdsEnums.TYPE_SIZE_LIMIT) ? SqlDbType.NVarChar : SqlDbType.NText;
sqlParam.Size = commandText.Length;
sqlParam.Value = commandText;
rpc.parameters[0] = sqlParam;
sqlParam.Direction = ParameterDirection.Input;

if (cParams > 0)
if (userParamCount > 0)
{
string paramList = BuildParamList(_stateObj.Parser, BatchRPCMode ? parameters : _parameters);
sqlParam = new SqlParameter(null, ((paramList.Length << 1) <= TdsEnums.TYPE_SIZE_LIMIT) ? SqlDbType.NVarChar : SqlDbType.NText, paramList.Length);
sqlParam = rpc.systemParams[1];
sqlParam.SqlDbType = ((paramList.Length << 1) <= TdsEnums.TYPE_SIZE_LIMIT) ? SqlDbType.NVarChar : SqlDbType.NText;
sqlParam.Size = paramList.Length;
sqlParam.Value = paramList;
rpc.parameters[1] = sqlParam;

bool inSchema = (0 != (behavior & CommandBehavior.SchemaOnly));
SetUpRPCParameters(rpc, j, inSchema, parameters);
SetUpRPCParameters(rpc, inSchema, parameters);
}
}

Expand Down
Loading