- 
                Notifications
    You must be signed in to change notification settings 
- Fork 316
Closed
Labels
Triage Done ✔️Issues that are triaged by dev team and are in investigation.Issues that are triaged by dev team and are in investigation.
Milestone
Description
Describe the bug
I tried the new 6.1 PReview1 bits, a few of my tests failed with wrong data output, I tracked it down to sqlDataReader.GetChars apparently ignoring the buffer index. In the GetPooledChars loop below the buffer is always written at bufferIndex 0 ignoring the offset parameter. If you run the same code with 6.0.2 it works.
To reproduce
using System.Buffers;
using System.Data;
using Microsoft.Data.SqlClient;
namespace SqlRepro
{
    internal class Program
    {
        static async Task Main(string[] args)
        {
            const CommandBehavior commandBehavior = CommandBehavior.SequentialAccess | CommandBehavior.SingleResult;
            await using var sqlConnection = new SqlConnection("Server=localhost;Database=DatabaseTests;TrustServerCertificate=True;Trusted_Connection=True;");
            await sqlConnection.OpenAsync();
            const int length = 32000;
            const string sqlCharWithArg = "SELECT CONVERT(BIGINT, 1) AS [Id], CONVERT(NVARCHAR(MAX), @input) AS [Value];";
            var input = string.Create(length, length, (span, state) =>
            {
                for (int i = 0; i < state; i++)
                {
                    span[i] = (char) Random.Shared.Next(0x30, 0x5A);
                }
            });
            await using var sqlCommand = new SqlCommand();
            sqlCommand.Connection = sqlConnection;
            sqlCommand.CommandTimeout = 0;
            sqlCommand.CommandText = sqlCharWithArg;
            sqlCommand.Parameters.Add(new SqlParameter("@input", SqlDbType.NVarChar, -1) {Value = input});
            await using var sqlReader = await sqlCommand.ExecuteReaderAsync(commandBehavior);
            var succ = await sqlReader.ReadAsync();
            long id = sqlReader.GetInt64(0);
            if (id != 1)
            {
                Console.WriteLine("Id not 1");
            }
            var sliced = GetPooledChars(sqlReader, 1);
            if (!sliced.SequenceEqual(input.ToCharArray()))
            {
                Console.WriteLine("sliced != input");
            }
        }
        private static char[] GetPooledChars(SqlDataReader sqlDataReader, int ordinal)
        {
            var buffer = ArrayPool<char>.Shared.Rent(8192);
            int offset = 0;
            while (true)
            {
                var read = (int) sqlDataReader.GetChars(ordinal, offset, buffer, offset, buffer.Length - offset);
                // in the second iteration, the buffer is already overwritten from offset 0, bufferIndex ignored?
                if (read == 0)
                {
                    break;
                }
                offset += read;
                if (buffer.Length - offset < 128)
                {
                    buffer = Resize(buffer);
                }
            }
            var sliced = buffer.AsSpan(0, offset).ToArray();
            ArrayPool<char>.Shared.Return(buffer);
            return sliced;
            static char[] Resize(char[] buffer)
            {
                var newBuffer = ArrayPool<char>.Shared.Rent(buffer.Length * 2);
                Array.Copy(buffer, newBuffer, buffer.Length);
                ArrayPool<char>.Shared.Return(buffer);
                return newBuffer;
            }
        }
    }
}<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net9.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.Data.SqlClient" Version="6.1.0-preview1.25120.4" />
  </ItemGroup>
</Project>Expected behavior
Slice should be the same as input in the repro
Further technical details
Microsoft.Data.SqlClient version: 6.1.0-preview1.25120.4
.NET target: 9.0
SQL Server version: SQL Server 2022
Operating system: Windows 11
viktor-svub
Metadata
Metadata
Assignees
Labels
Triage Done ✔️Issues that are triaged by dev team and are in investigation.Issues that are triaged by dev team and are in investigation.