2.2.6.6 RPC Request

Stream Name:

 RPCRequest

Stream Function:

Request to execute an RPC.

Stream Comments:

  • Packet header type 0x03.

  • To execute an RPC on the server, the client sends an RPCRequest data stream to the server. This is a binary stream that contains the RPC Name (or ProcID), Options, and Parameters. Each RPC MUST be contained within a separate message and not mixed with other SQL statements.

  • A sample RPCRequest message is in section 4.8.

Stream-Specific Rules:

 ProcID           =   USHORT
 ProcIDSwitch     =   %xFF %xFF
 ProcName         =   US_VARCHAR
 NameLenProcID    =   ProcName
                      /
                      (ProcIDSwitch ProcID)
  
 fWithRecomp      =   BIT
 fNoMetaData      =   BIT
 fReuseMetaData   =   BIT
 OptionFlags      =   fWithRecomp
                      fNoMetaData
                      fReuseMetaData
                      13FRESERVEDBIT
  
 fByRefValue      =   BIT
 fDefaultValue    =   BIT
 fEncrypted       =   BIT
 StatusFlags      =   fByRefValue
                      fDefaultValue
                      1FRESERVEDBIT
                      fEncrypted
                      4FRESERVEDBIT
  
 ParamMetaData    =   B_VARCHAR
                      StatusFlags
                      (TYPE_INFO / TVP_TYPE_INFO)    ; (TVP_TYPE_INFO introduced in TDS 7.3)
 ParamLenData     =   TYPE_VARBYTE
  
 EncryptionAlgo   =   BYTE               ; (introduced in TDS 7.4)
  
 AlgoName         =   B_VARCHAR          ; (introduced in TDS 7.4)
  
 EncryptionType   =   BYTE               ; (introduced in TDS 7.4)
  
 NormVersion      =   BYTE               ; (introduced in TDS 7.4)
  
 DatabaseId       =   ULONG              ; (introduced in TDS 7.4)
  
 CekId            =   ULONG              ; (introduced in TDS 7.4)
  
 CekVersion       =   ULONG              ; (introduced in TDS 7.4)
  
 CekMDVersion     =   ULONGLONG          ; (introduced in TDS 7.4)
  
 ParamCipherInfo  =   TYPE_INFO
                      EncryptionAlgo
                      [AlgoName]
                      EncryptionType
                      DatabaseId 
                      CekId
                      CekVersion
                      CekMDVersion
                      NormVersion
 ParameterData    =   ParamMetaData
                      ParamLenData
                      [ParamCipherInfo]
  
 EnclavePackage   =   L_VARBYTE          ; (introduced in TDS 7.4)
  
 BatchFlag        =   %x80 / %xFF        ; (changed to %xFF in TDS 7.2)
 NoExecFlag       =   %xFE               ; (introduced in TDS 7.2)
  
 RPCReqBatch      =   NameLenProcID
                      OptionFlags
                      *EnclavePackage
                      *ParameterData

The length for the instance value of UDTs is specified as a ULONGLONG. Also, ParameterData is repeated once for each parameter in the request.

A StatusFlags of fDefaultValue bit MUST be zero for TVP_TYPE_INFO.

The fByRefValue MUST be zero for TVP_TYPE_INFO.

Stream Definition:

 RPCRequest       =   ALL_HEADERS
                      RPCReqBatch
                      *((BatchFlag / NoExecFlag) RPCReqBatch)
                      [BatchFlag / NoExecFlag]

Note that RPCReqBatch is repeated once for each RPC in the batch.

Stream Parameter Details:

Parameter

Description

ProcID

The number identifying the special stored procedure to be executed. The valid numbers with associated special stored procedure are as follows:

  • Sp_Cursor = 1

  • Sp_CursorOpen = 2

  • Sp_CursorPrepare = 3

  • Sp_CursorExecute = 4

  • Sp_CursorPrepExec = 5

  • Sp_CursorUnprepare = 6

  • Sp_CursorFetch = 7

  • Sp_CursorOption = 8

  • Sp_CursorClose = 9

  • Sp_ExecuteSql = 10

  • Sp_Prepare = 11

  • Sp_Execute = 12

  • Sp_PrepExec = 13

  • Sp_PrepExecRpc = 14

  • Sp_Unprepare = 15

ProcIDSwitch

ProcIDSwitch can occur as part of NameLenProcID (see below).

ProcName

The procedure name length (within US_VARCHAR), which MUST be no more than 1046 bytes.

NameLenProcID

If the first USHORT contains 0xFFFF the following USHORT contains the PROCID. Otherwise, NameLenProcID contains the parameter name length and parameter name.

OptionFlags

Bit flags in least significant bit order:

  • fWithRecomp: 1 if RPC is sent with the "with recompile" option.

  • fNoMetaData: The server sends NoMetaData only if fNoMetaData is set to 1 in the request (see COLMETADATA, section 2.2.7.4).<37>

  • fReuseMetaData: 1 if the metadata has not changed from the previous call and the server SHOULD reuse its cached metadata (the metadata MUST still be sent).

StatusFlags

Bit flags in least significant bit order:

  • fByRefValue: 1 if the parameter is passed by reference (OUTPUT parameter) or 0 if parameter is passed by value.

  • fDefaultValue: 1 if the parameter being passed is to be the default value.

  • fEncrypted: 1 if the parameter that is being passed is encrypted. This flag is valid only when the column encryption feature is negotiated by client and server and is turned on.

ParameterData

The parameter name length and parameter name (within B_VARCHAR), the TYPE_INFO of the RPC data, and the type-dependent data for the RPC (within TYPE_VARBYTE).

EncryptionAlgo

This byte describes the encryption algorithm that is used. For a custom encryption algorithm, the EncryptionAlgo value MUST be set to 0 and the actual encryption algorithm MUST be inferred from the AlgoName. For all other values, AlgoName MUST NOT be sent.

If the value is set to 1, the encryption algorithm that is used is AEAD_AES_256_CBC_HMAC_SHA512, as described in [IETF-AuthEncr] section 5.4.

AlgoName

Algorithm name literal that is used for encrypting the plaintext value. This is an optional field and MUST be sent when EncryptionAlgo = 0. For all other values of EncryptionAlgo, this field MUST NOT be sent.

EncryptionType

This byte describes the flavor of encryption algorithm that is used. The values of this field are as follows:

1 = deterministic encryption.

2 = randomized encryption.

NormVersion

Reserved for future use. The value MUST be set to 1.

DatabaseId

A 4-byte integer value that represents the database ID where the column encryption key is stored.

CekId

An identifier for the column encryption key.

CekVersion

The key version of the column encryption key.

CekMDVersion

The metadata version for the column encryption key.

ParamCipherInfo

The description of the parameter encryption information when the parameter is transparently encrypted. It defines the original TYPE_INFO of the data that is encrypted, the encryption algorithm that is used, the normalization version, the id of the database containing the column encryption key used for encryption, the id of the column encryption key, the version of the column encryption key, and the version of the column encryption key metadata. These fields MUST be sent only when fEncrypted is set to 1.

EnclavePackage

An encrypted byte package that SHOULD<38> be generated by the client. This package contains information that is required by the server-side enclave to perform computations on encrypted columns. The package has an internal structure that is irrelevant to the TDS protocol between client and server. The server forwards the byte array to the enclave without interpreting it, and the enclave decodes the byte array.

Introduced in TDS 7.4.

BatchFlag

Distinguishes the start of the next RPC from another parameter within the current RPC. If the version of TDS in use supports these flags, either the BatchFlag element or the NoExecFlag element MUST be present when another RPC request is in the current batch. BatchFlag SHOULD NOT be sent after the last RPCReqBatch. If BatchFlag is received after the last RPCReqBatch is received, the server MUST ignore it.

NoExecFlag

Indicates that the preceding RPC is not executed. If this separator is found, the previous RPC is not executed. Instead, an error message is returned, followed by the DONEPROC marking that the RPC in the batch has finished, and then execution proceeds to the next RPC in the batch. The tabular data set returned is very similar to what happens if the RPC does not exist—never execute the RPC, just return an error message, followed by DONEPROC, and then execute the next RPC.