Skip to content

Commit 6773a65

Browse files
Port #3468 from main to 6.1 (#3472)
This commit ports #3468 from main to release/6.1
1 parent 3396340 commit 6773a65

File tree

10 files changed

+111
-118
lines changed

10 files changed

+111
-118
lines changed

doc/snippets/Microsoft.Data.SqlClient/SqlCommand.xml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3604,7 +3604,9 @@ Before you call <xref:Microsoft.Data.SqlClient.SqlCommand.Prepare%2A>, specify t
36043604
36053605
If you call an `Execute` method after calling <xref:Microsoft.Data.SqlClient.SqlCommand.Prepare%2A>, any parameter value that is larger than the value specified by the <xref:Microsoft.Data.SqlClient.SqlParameter.Size%2A> property is automatically truncated to the original specified size of the parameter, and no truncation errors are returned.
36063606
3607-
Output parameters (whether prepared or not) must have a user-specified data type. If you specify a variable length data type, you must also specify the maximum <xref:Microsoft.Data.SqlClient.SqlParameter.Size%2A>.
3607+
Output parameters (whether prepared or not) must have a user-specified data type. If you specify a variable length data type except vector, you must also specify the maximum <xref:Microsoft.Data.SqlClient.SqlParameter.Size%2A>.
3608+
3609+
For vector data types, the <xref:Microsoft.Data.SqlClient.SqlParameter.Size%2A> property is ignored. The size of the vector is inferred from the <xref:Microsoft.Data.SqlClient.SqlParameter.Value%2A> of type <xref:Microsoft.Data.SqlTypes.SqlVector%2A>.
36083610
36093611
Prior to Visual Studio 2010, <xref:Microsoft.Data.SqlClient.SqlCommand.Prepare%2A> threw an exception. Beginning in Visual Studio 2010, this method does not throw an exception.
36103612

doc/snippets/Microsoft.Data.SqlTypes/SqlVector.xml

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,11 @@
55
<summary>Represents a vector value in SQL Server.</summary>
66
</SqlVector>
77
<ctor1>
8-
<param name="length"></param>
9-
<summary>
10-
Constructs a null vector of the given length. SQL Server requires vector arguments to specify their length even when null.
11-
</summary>
12-
<exception cref="T:System.ArgumentOutOfRangeException">
13-
Vector length must be non-negative.
14-
</exception>
15-
</ctor1>
16-
<ctor2>
178
<param name="memory"></param>
189
<summary>
1910
Constructs a vector with the given values.
2011
</summary>
21-
</ctor2>
12+
</ctor1>
2213
<IsNull>
2314
<inheritdoc/>
2415
</IsNull>
@@ -37,13 +28,17 @@
3728
Returns the number of elements in the vector.
3829
</summary>
3930
</Length>
40-
<Size>
41-
<summary>
42-
Returns the number of bytes required to represent this vector when communicating with SQL Server.
43-
</summary>
44-
</Size>
4531
<Memory>
4632
<summary>Returns the vector values as a memory region. No copies are made.</summary>
4733
</Memory>
34+
<CreateNull>
35+
<param name="length"></param>
36+
<summary>
37+
Constructs a null vector of the given length. SQL Server requires vector arguments to specify their length even when null.
38+
</summary>
39+
<exception cref="T:System.ArgumentOutOfRangeException">
40+
Vector length must be non-negative.
41+
</exception>
42+
</CreateNull>
4843
</members>
4944
</docs>

src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.cs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -123,23 +123,21 @@ public SqlJson(System.Text.Json.JsonDocument jsonDoc) { }
123123
}
124124

125125
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlVector.xml' path='docs/members[@name="SqlVector"]/SqlVector/*' />
126-
public sealed class SqlVector<T> : System.Data.SqlTypes.INullable
126+
public readonly struct SqlVector<T> : System.Data.SqlTypes.INullable
127127
where T : unmanaged
128128
{
129129
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlVector.xml' path='docs/members[@name="SqlVector"]/ctor1/*' />
130-
public SqlVector(int length) { }
131-
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlVector.xml' path='docs/members[@name="SqlVector"]/ctor2/*' />
132130
public SqlVector(System.ReadOnlyMemory<T> memory) { }
133131
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlVector.xml' path='docs/members[@name="SqlVector"]/IsNull/*' />
134132
public bool IsNull => throw null;
135133
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlVector.xml' path='docs/members[@name="SqlVector"]/Null/*' />
136134
public static SqlVector<T> Null => throw null;
137135
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlVector.xml' path='docs/members[@name="SqlVector"]/Length/*' />
138136
public int Length { get { throw null; } }
139-
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlVector.xml' path='docs/members[@name="SqlVector"]/Size/*' />
140-
public int Size { get { throw null; } }
141137
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlVector.xml' path='docs/members[@name="SqlVector"]/Memory/*' />
142138
public System.ReadOnlyMemory<T> Memory { get { throw null; } }
139+
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlVector.xml' path='docs/members[@name="SqlVector"]/CreateNull/*' />
140+
public static SqlVector<T> CreateNull(int length) { throw null; }
143141
}
144142
}
145143
namespace Microsoft.Data.SqlClient

src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.cs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2417,22 +2417,20 @@ public SqlJson(System.Text.Json.JsonDocument jsonDoc) { }
24172417
}
24182418

24192419
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlVector.xml' path='docs/members[@name="SqlVector"]/SqlVector/*' />
2420-
public sealed class SqlVector<T> : System.Data.SqlTypes.INullable
2420+
public readonly struct SqlVector<T> : System.Data.SqlTypes.INullable
24212421
where T : unmanaged
24222422
{
24232423
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlVector.xml' path='docs/members[@name="SqlVector"]/ctor1/*' />
2424-
public SqlVector(int length) { }
2425-
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlVector.xml' path='docs/members[@name="SqlVector"]/ctor2/*' />
24262424
public SqlVector(System.ReadOnlyMemory<T> memory) { }
24272425
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlVector.xml' path='docs/members[@name="SqlVector"]/IsNull/*' />
24282426
public bool IsNull => throw null;
24292427
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlVector.xml' path='docs/members[@name="SqlVector"]/Null/*' />
24302428
public static SqlVector<T> Null => throw null;
24312429
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlVector.xml' path='docs/members[@name="SqlVector"]/Length/*' />
24322430
public int Length { get { throw null; } }
2433-
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlVector.xml' path='docs/members[@name="SqlVector"]/Size/*' />
2434-
public int Size { get { throw null; } }
24352431
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlVector.xml' path='docs/members[@name="SqlVector"]/Memory/*' />
24362432
public System.ReadOnlyMemory<T> Memory { get { throw null; } }
2433+
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlVector.xml' path='docs/members[@name="SqlVector"]/CreateNull/*' />
2434+
public static SqlVector<T> CreateNull(int length) { throw null; }
24372435
}
24382436
}

src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlBuffer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -993,7 +993,7 @@ internal SqlVector<T> GetSqlVector<T>() where T : unmanaged
993993
{
994994
if (IsNull)
995995
{
996-
return new SqlVector<T>(_value._vectorInfo._elementCount);
996+
return SqlVector<T>.CreateNull(_value._vectorInfo._elementCount);
997997
}
998998
return new SqlVector<T>(SqlBinary.Value);
999999
}

src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlDataReader.cs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3365,10 +3365,7 @@ private T GetFieldValueFromSqlBufferInternal<T>(SqlBuffer data, _SqlMetaData met
33653365
{
33663366
if (typeof(T) == typeof(string) && metaData.metaType.SqlDbType == SqlDbTypeExtensions.Vector)
33673367
{
3368-
if (data.IsNull)
3369-
return (T)(object)data.String;
3370-
else
3371-
return (T)(object)data.GetSqlVector<float>().GetString();
3368+
return (T)(object)data.String;
33723369
}
33733370
// the requested type is likely to be one that isn't supported so try the cast and
33743371
// unless there is a null value conversion then feedback the cast exception with

src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlParameter.cs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -773,7 +773,7 @@ private object GetVectorReturnValue()
773773
switch (elementType)
774774
{
775775
case MetaType.SqlVectorElementType.Float32:
776-
return new SqlVector<float>(elementCount);
776+
return SqlVector<float>.CreateNull(elementCount);
777777
default:
778778
throw SQL.VectorTypeNotSupported(elementType.ToString());
779779
}
@@ -857,8 +857,13 @@ public override int Size
857857
{
858858
throw ADP.InvalidSizeValue(value);
859859
}
860-
PropertyChanging();
861-
_size = value;
860+
861+
// We ignore the Size property for Vector types, as it is not applicable.
862+
if (_metaType == null || _metaType.SqlDbType != SqlDbTypeExtensions.Vector)
863+
{
864+
PropertyChanging();
865+
_size = value;
866+
}
862867
}
863868
}
864869
}
@@ -1970,7 +1975,8 @@ internal void Prepare(SqlCommand cmd)
19701975
{
19711976
throw ADP.PrepareParameterType(cmd);
19721977
}
1973-
else if (!ShouldSerializeSize() && !_metaType.IsFixed)
1978+
// For vector datatype we do not require size to be specified. It is inferred from the SqlParameter.Value.
1979+
else if (!ShouldSerializeSize() && !_metaType.IsFixed && _metaType.SqlDbType != SqlDbTypeExtensions.Vector)
19741980
{
19751981
throw ADP.PrepareParameterSize(cmd);
19761982
}

src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlTypes/SqlVector.cs

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
namespace Microsoft.Data.SqlTypes;
1717

1818
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlVector.xml' path='docs/members[@name="SqlVector"]/SqlVector/*' />
19-
public sealed class SqlVector<T> : INullable, ISqlVector
19+
public readonly struct SqlVector<T> : INullable, ISqlVector
2020
where T : unmanaged
2121
{
2222
#region Constants
@@ -31,13 +31,13 @@ public sealed class SqlVector<T> : INullable, ISqlVector
3131
private readonly byte _elementType;
3232
private readonly byte _elementSize;
3333
private readonly byte[] _tdsBytes;
34-
34+
private readonly int _size;
35+
3536
#endregion
3637

3738
#region Constructors
3839

39-
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlVector.xml' path='docs/members[@name="SqlVector"]/ctor1/*' />
40-
public SqlVector(int length)
40+
private SqlVector(int length)
4141
{
4242
if (length < 0)
4343
{
@@ -49,21 +49,24 @@ public SqlVector(int length)
4949
IsNull = true;
5050

5151
Length = length;
52-
Size = TdsEnums.VECTOR_HEADER_SIZE + (_elementSize * Length);
52+
_size = TdsEnums.VECTOR_HEADER_SIZE + (_elementSize * Length);
5353

5454
_tdsBytes = Array.Empty<byte>();
5555
Memory = new();
5656
}
5757

58-
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlVector.xml' path='docs/members[@name="SqlVector"]/ctor2/*' />
58+
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlVector.xml' path='docs/members[@name="SqlVector"]/CreateNull/*' />
59+
public static SqlVector<T> CreateNull(int length) => new(length);
60+
61+
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlVector.xml' path='docs/members[@name="SqlVector"]/ctor1/*' />
5962
public SqlVector(ReadOnlyMemory<T> memory)
6063
{
6164
(_elementType, _elementSize) = GetTypeFieldsOrThrow();
6265

6366
IsNull = false;
6467

6568
Length = memory.Length;
66-
Size = TdsEnums.VECTOR_HEADER_SIZE + (_elementSize * Length);
69+
_size = TdsEnums.VECTOR_HEADER_SIZE + (_elementSize * Length);
6770

6871
_tdsBytes = MakeTdsBytes(memory);
6972
Memory = memory;
@@ -73,7 +76,7 @@ internal SqlVector(byte[] tdsBytes)
7376
{
7477
(_elementType, _elementSize) = GetTypeFieldsOrThrow();
7578

76-
(Length, Size) = GetCountsOrThrow(tdsBytes);
79+
(Length, _size) = GetCountsOrThrow(tdsBytes);
7780

7881
IsNull = false;
7982

@@ -99,25 +102,25 @@ internal string GetString()
99102
#region Properties
100103

101104
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlVector.xml' path='docs/members[@name="SqlVector"]/IsNull/*' />
102-
public bool IsNull { get; init; }
105+
public bool IsNull { get; }
103106

104107
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlVector.xml' path='docs/members[@name="SqlVector"]/Null/*' />
105108
public static SqlVector<T>? Null => null;
106109

107110
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlVector.xml' path='docs/members[@name="SqlVector"]/Length/*' />
108-
public int Length { get; init; }
109-
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlVector.xml' path='docs/members[@name="SqlVector"]/Size/*' />
110-
public int Size { get; init; }
111-
111+
public int Length { get; }
112+
112113
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlVector.xml' path='docs/members[@name="SqlVector"]/Memory/*' />
113-
public ReadOnlyMemory<T> Memory { get; init; }
114+
public ReadOnlyMemory<T> Memory { get; }
114115

115116
#endregion
116117

117118
#region ISqlVector Internal Properties
118119
byte ISqlVector.ElementType => _elementType;
119120
byte ISqlVector.ElementSize => _elementSize;
120121
byte[] ISqlVector.VectorPayload => _tdsBytes;
122+
int ISqlVector.Size => _size;
123+
121124
#endregion
122125

123126
#region Helpers
@@ -154,7 +157,7 @@ private byte[] MakeTdsBytes(ReadOnlyMemory<T> values)
154157
// | Stream of Values | NN * sizeof(T) | [element bytes...] | Raw bytes for vector elements |
155158
// +------------------------+-----------------+----------------------+--------------------------------------------------------------+
156159

157-
byte[] result = new byte[Size];
160+
byte[] result = new byte[_size];
158161

159162
// Header Bytes
160163
result[0] = VecHeaderMagicNo;

0 commit comments

Comments
 (0)