in src/Microsoft.Health.Fhir.SqlServer/Features/Search/HashingSqlQueryParameterManager.cs [97:182]
public void AppendHash(IndentedStringBuilder stringBuilder)
{
IncrementalHash incrementalHash = null;
Span<byte> buf = stackalloc byte[256];
int currentBufferIndex = 0;
foreach (SqlParameter sqlParameter in _setToHash)
{
switch (sqlParameter.SqlDbType)
{
case SqlDbType.BigInt:
WriteAndAdvance(buf, ref currentBufferIndex, ref incrementalHash, (long)sqlParameter.Value);
break;
case SqlDbType.Bit:
WriteAndAdvance(buf, ref currentBufferIndex, ref incrementalHash, (bool)sqlParameter.Value);
break;
case SqlDbType.Date:
case SqlDbType.DateTime:
case SqlDbType.DateTime2:
case SqlDbType.SmallDateTime:
case SqlDbType.Time:
WriteAndAdvance(buf, ref currentBufferIndex, ref incrementalHash, (DateTime)sqlParameter.Value);
break;
case SqlDbType.DateTimeOffset:
WriteAndAdvance(buf, ref currentBufferIndex, ref incrementalHash, (DateTimeOffset)sqlParameter.Value);
break;
case SqlDbType.Decimal:
WriteAndAdvance(buf, ref currentBufferIndex, ref incrementalHash, (decimal)sqlParameter.Value);
break;
case SqlDbType.Float:
case SqlDbType.Real:
WriteAndAdvance(buf, ref currentBufferIndex, ref incrementalHash, (double)sqlParameter.Value);
break;
case SqlDbType.Int:
WriteAndAdvance(buf, ref currentBufferIndex, ref incrementalHash, (int)sqlParameter.Value);
break;
case SqlDbType.SmallInt:
WriteAndAdvance(buf, ref currentBufferIndex, ref incrementalHash, (short)sqlParameter.Value);
break;
case SqlDbType.TinyInt:
WriteAndAdvance(buf, ref currentBufferIndex, ref incrementalHash, (byte)sqlParameter.Value);
break;
case SqlDbType.UniqueIdentifier:
WriteAndAdvance(buf, ref currentBufferIndex, ref incrementalHash, (Guid)sqlParameter.Value);
break;
case SqlDbType.NChar:
case SqlDbType.NText:
case SqlDbType.VarChar:
case SqlDbType.NVarChar:
case SqlDbType.Text:
WriteAndAdvanceString(buf, ref currentBufferIndex, ref incrementalHash, (string)sqlParameter.Value);
break;
default:
throw new InvalidOperationException($"Unexpected parameter type {sqlParameter.SqlDbType}");
}
}
Span<byte> hashBytes = stackalloc byte[32];
if (incrementalHash != null)
{
if (currentBufferIndex > 0)
{
incrementalHash.AppendData(buf[..currentBufferIndex]);
}
incrementalHash.GetCurrentHash(hashBytes);
incrementalHash.Dispose();
}
else
{
if (!SHA256.TryHashData(buf[..currentBufferIndex], hashBytes, out _))
{
throw new InvalidOperationException("Failed to hash data");
}
}
Span<char> hashChars = stackalloc char[44]; // 44 since inputLength = 32 and inputLength => (inputLength / 3 * 4) + (((inputLength % 3) != 0) ? 4 : 0) = 44
if (!Convert.TryToBase64Chars(hashBytes, hashChars, out int hashCharsLength))
{
throw new InvalidOperationException("Failed to convert to Base64 chars.");
}
stringBuilder.Append(hashChars[..hashCharsLength]);
}