-
Notifications
You must be signed in to change notification settings - Fork 324
GetFieldType() does not Return SqlVector<float> #4104
Description
Describe the bug
SqlDataReader.GetFieldType() does not properly identify a VECTOR(3) field as vector, while .GetValue() and others
do the proper identification.
To reproduce
Based on original Vector usage sample this code triggers the issue with a set of assertions
class Vectors
{
public int Id { get; set; }
public SqlVector<float> VectorData { get; set; }
}
using var connection = new SqlConnection("...");
connection.Open();
var vectorDimensionCount = 3;
using (var command = connection.CreateCommand())
{
command.CommandText = $@" IF OBJECT_ID('{nameof(Vectors)}', 'U') IS NOT NULL DROP TABLE {nameof(Vectors)};";
command.ExecuteNonQuery();
}
using (var command = connection.CreateCommand())
{
command.CommandText = $@"
CREATE TABLE {nameof(Vectors)} (
Id INT IDENTITY(1,1) PRIMARY KEY,
VectorData VECTOR({vectorDimensionCount})
);";
command.ExecuteNonQuery();
}
// Raw insert, from Microsoft sample code
using (var command = connection.CreateCommand())
{
command.CommandText = $@"INSERT INTO {nameof(Vectors)} (VectorData) VALUES (@VectorData)";
var param = command.Parameters.Add("@VectorData", SqlDbTypeExtensions.Vector);
// Insert non-null vector
param.Value = new SqlVector<float>(new float[] { 3.14159f, 1.61803f, 1.41421f });
command.ExecuteNonQuery();
}
using (var command = connection.CreateCommand())
{
command.CommandText = $@"SELECT Id, VectorData FROM {nameof(Vectors)}";
using var reader = command.ExecuteReader();
Assert.AreEqual(typeof(int), reader.GetFieldType(0));
// Assert.AreEqual(typeof(SqlVector<float>), reader.GetFieldType(1)); // This should be the check
Assert.AreEqual(typeof(byte[]), reader.GetFieldType(1)); // This should return SqlVector<float>, but currently returns byte[] due to a bug in SqlClient
while (reader.Read())
{
var value = reader.GetValue(1);
Assert.IsInstanceOfType<SqlVector<float>>(value); // This succeeds, so the library is correctly identifying the type as SqlVector<float> and returning it as such, but the GetFieldType method is incorrectly reporting it as byte[] due to a bug in SqlClient
var id = reader.GetFieldValue<int>(0);
var dt = reader.GetFieldValue<SqlVector<float>>(1);
Assert.ThrowsExactly<InvalidCastException>(() => reader.GetFieldValue<byte[]>(1));
var dt2 = reader.GetSqlVector<float>(1);
}
}This sample passes with 7.0.0 on SqlServer 2025
Expected behavior
The GetFieldType call returns a type with which the value is not retrievable. It should return the right type, or at least a type with which the value is retrievable. (Returning typeof(object) is better than typeof(byte[]).
Given that the .GetValue(1) does the right thing, I think it should just return typeof(SqlVector<float>)
Further technical details
Tested with SqlServer 2025 (linux docker) on .Net 10 (=RepoDB test environment), but it looks like it is reproducable on many more configurations
Metadata
Metadata
Assignees
Labels
Type
Projects
Status