Skip to content

Commit fc950e8

Browse files
Introduce SqlVectorFloat32 SqlType class for vector datatype support (#3433)
This commit adds support for vector datatype by introducing new feature extension and SqlType class SqlVectorFloat32.
1 parent dbc6c83 commit fc950e8

38 files changed

+2578
-25
lines changed

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

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,7 @@ No conversions are performed; therefore. the data retrieved must already be a ch
415415
<item><description>SqlMoney</description></item>
416416
<item><description>SqlSingle</description></item>
417417
<item><description>SqlString</description></item>
418+
<item><description>SqlVectorFloat32</description></item>
418419
<item><description>Stream</description></item>
419420
<item><description>String</description></item>
420421
<item><description>TextReader</description></item>
@@ -489,6 +490,7 @@ No conversions are performed; therefore. the data retrieved must already be a ch
489490
<item><description>SqlMoney</description></item>
490491
<item><description>SqlSingle</description></item>
491492
<item><description>SqlString</description></item>
493+
<item><description>SqlVectorFloat32</description></item>
492494
<item><description>Stream</description></item>
493495
<item><description>String</description></item>
494496
<item><description>TextReader</description></item>
@@ -958,7 +960,31 @@ The <xref:Microsoft.Data.SqlClient.SqlDataReader.GetSchemaTable%2A> method retur
958960
<param name="i"></param>
959961
<summary>Gets the value of the specified column as a <see cref="T:Microsoft.Data.SqlTypes.SqlJson"/>.</summary>
960962
<returns>A <see cref="T:Microsoft.Data.SqlTypes.SqlJson"/> object representing the column at the given ordinal.</returns>
963+
<remarks>
964+
No conversions are performed; therefore, the data retrieved must already be a JSON string, or an exception is generated.
965+
</remarks>
961966
</GetSqlJson>
967+
<GetSqlVectorFloat32>
968+
<param name="i"></param>
969+
<summary>
970+
Gets the value of the specified column as a <see cref="T:Microsoft.Data.SqlTypes.SqlVectorFloat32"/>.
971+
</summary>
972+
<returns>
973+
A <see cref="T:Microsoft.Data.SqlTypes.SqlVectorFloat32"/> object representing the column at the given ordinal.
974+
</returns>
975+
<exception cref="T:System.ArgumentOutOfRangeException">
976+
The index passed was outside the range of 0 to <see cref="P:System.Data.DataTableReader.FieldCount" /> - 1
977+
</exception>
978+
<exception cref="T:System.InvalidOperationException">
979+
An attempt was made to read or access columns in a closed <see cref="T:Microsoft.Data.SqlClient.SqlDataReader" />.
980+
</exception>
981+
<exception cref="T:System.InvalidCastException">
982+
The retrieved data is not compatible with the <see cref="T:Microsoft.Data.SqlTypes.SqlVectorFloat32" /> type.
983+
</exception>
984+
<remarks>
985+
No conversions are performed; therefore, the data retrieved must already be a vector value, or an exception is generated.
986+
</remarks>
987+
</GetSqlVectorFloat32>
962988
<GetSqlMoney>
963989
<param name="i">
964990
The zero-based column ordinal.
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?xml version="1.0"?>
2+
<docs>
3+
<members name="SqlVectorFloat32">
4+
<SqlVectorFloat32>
5+
<summary>Represents the 32-bit float vector datatype in SQL Server.</summary>
6+
</SqlVectorFloat32>
7+
<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 column length must be non-negative.
14+
</exception>
15+
</ctor1>
16+
<ctor2>
17+
<param name="values"></param>
18+
<summary>
19+
Constructs a vector with the given values.
20+
</summary>
21+
</ctor2>
22+
<IsNull>
23+
<inheritdoc/>
24+
</IsNull>
25+
<Null>
26+
<summary>
27+
Represents a null instance of the <see cref="SqlVectorFloat32"/> type without any attributes.
28+
</summary>
29+
<remarks>
30+
This is equivalent to the C# <c>null</c> value.
31+
</remarks>
32+
</Null>
33+
<Length>
34+
<summary>
35+
Returns the number of elements in the vector.
36+
</summary>
37+
</Length>
38+
<Size>
39+
<summary>
40+
Returns the number of bytes required to represent this vector when communicating with SQL Server.
41+
</summary>
42+
</Size>
43+
<Values>
44+
<summary>Returns the vector values as a memory region. No copies are made.</summary>
45+
<returns>An array of float32 values as <see cref="T:System.ReadOnlyMemory{System.Single}"/> value.</returns>
46+
</Values>
47+
<ToString>
48+
<summary>Returns a JSON string representation of the vector. A new string is generated each time you call this method.</summary>
49+
<returns>A JSON <see cref="T:System.String"/> value.</returns>
50+
</ToString>
51+
<ToArray>
52+
<summary>Returns the vector values as an array of floats.</summary>
53+
<returns>An array of <see cref="T:System.String"/> values.</returns>
54+
</ToArray>
55+
</members>
56+
</docs>

doc/snippets/Microsoft.Data/SqlDbTypeExtensions.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,13 @@ The <xref:Microsoft.Data.SqlDbTypeExtensions> class provides <xref:System.Data.S
1818
<see cref="T:System.Data.SqlDbType" /> enum value for JSON datatype.
1919
</returns>
2020
</SqlJson>
21+
<SqlVector name="default">
22+
<summary>
23+
Gets the <see cref="T:System.Data.SqlDbType" /> enum value for the vector datatype.
24+
</summary>
25+
<returns>
26+
<see cref="T:System.Data.SqlDbType" /> enum value for vector datatype.
27+
</returns>
28+
</SqlVector>
2129
</members>
2230
</docs>

src/Microsoft.Data.SqlClient.sln

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Microsoft.Data.SqlTypes", "
172172
ProjectSection(SolutionItems) = preProject
173173
..\doc\snippets\Microsoft.Data.SqlTypes\SqlFileStream.xml = ..\doc\snippets\Microsoft.Data.SqlTypes\SqlFileStream.xml
174174
..\doc\snippets\Microsoft.Data.SqlTypes\SqlJson.xml = ..\doc\snippets\Microsoft.Data.SqlTypes\SqlJson.xml
175+
..\doc\snippets\Microsoft.Data.SqlTypes\SqlVectorFloat32.xml = ..\doc\snippets\Microsoft.Data.SqlTypes\SqlVectorFloat32.xml
175176
EndProjectSection
176177
EndProject
177178
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Data.SqlClient.TestUtilities", "Microsoft.Data.SqlClient\tests\tools\Microsoft.Data.SqlClient.TestUtilities\Microsoft.Data.SqlClient.TestUtilities.csproj", "{89D6D382-9B36-43C9-A912-03802FDA8E36}"

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

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ public static class SqlDbTypeExtensions
1919
{
2020
/// <include file='../../../../doc/snippets/Microsoft.Data/SqlDbTypeExtensions.xml' path='docs/members[@name="SqlDbTypeExtensions"]/SqlJson[@name="default"]' />
2121
public const System.Data.SqlDbType Json = (System.Data.SqlDbType)35;
22+
/// <include file='../../../../doc/snippets/Microsoft.Data/SqlDbTypeExtensions.xml' path='docs/members[@name="SqlDbTypeExtensions"]/SqlVector[@name="default"]' />
23+
public const System.Data.SqlDbType Vector = (System.Data.SqlDbType)36;
2224
}
2325
}
2426

@@ -119,6 +121,29 @@ public SqlJson(System.Text.Json.JsonDocument jsonDoc) { }
119121
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlJson.xml' path='docs/members[@name="SqlJson"]/ToString/*' />
120122
public override string ToString() { throw null; }
121123
}
124+
125+
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlVectorFloat32.xml' path='docs/members[@name="SqlVectorFloat32"]/SqlVectorFloat32/*' />
126+
public sealed class SqlVectorFloat32 : System.Data.SqlTypes.INullable
127+
{
128+
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlVectorFloat32.xml' path='docs/members[@name="SqlVectorFloat32"]/ctor1/*' />
129+
public SqlVectorFloat32(int length) { }
130+
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlVectorFloat32.xml' path='docs/members[@name="SqlVectorFloat32"]/ctor2/*' />
131+
public SqlVectorFloat32(System.ReadOnlyMemory<float> values) { }
132+
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlVectorFloat32.xml' path='docs/members[@name="SqlVectorFloat32"]/IsNull/*' />
133+
public bool IsNull => throw null;
134+
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlVectorFloat32.xml' path='docs/members[@name="SqlVectorFloat32"]/Null/*' />
135+
public static SqlVectorFloat32 Null => throw null;
136+
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlVectorFloat32.xml' path='docs/members[@name="SqlVectorFloat32"]/Length/*' />
137+
public int Length { get { throw null; } }
138+
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlVectorFloat32.xml' path='docs/members[@name="SqlVectorFloat32"]/Size/*' />
139+
public int Size { get { throw null; } }
140+
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlVectorFloat32.xml' path='docs/members[@name="SqlVectorFloat32"]/Values/*' />
141+
public System.ReadOnlyMemory<float> Values { get { throw null; } }
142+
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlVectorFloat32.xml' path='docs/members[@name="SqlVectorFloat32"]/ToString/*' />
143+
public override string ToString() { throw null; }
144+
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlVectorFloat32.xml' path='docs/members[@name="SqlVectorFloat32"]/ToArray/*' />
145+
public float[] ToArray() { throw null; }
146+
}
122147
}
123148
namespace Microsoft.Data.SqlClient
124149
{
@@ -1370,6 +1395,8 @@ public override void Close() { }
13701395
public virtual object GetSqlValue(int i) { throw null; }
13711396
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/SqlDataReader.xml' path='docs/members[@name="SqlDataReader"]/GetSqlValues/*'/>
13721397
public virtual int GetSqlValues(object[] values) { throw null; }
1398+
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/SqlDataReader.xml' path='docs/members[@name="SqlDataReader"]/GetSqlVectorFloat32/*'/>
1399+
public virtual Microsoft.Data.SqlTypes.SqlVectorFloat32 GetSqlVectorFloat32(int i) { throw null; }
13731400
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/SqlDataReader.xml' path='docs/members[@name="SqlDataReader"]/GetSqlXml/*'/>
13741401
public virtual System.Data.SqlTypes.SqlXml GetSqlXml(int i) { throw null; }
13751402
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/SqlDataReader.xml' path='docs/members[@name="SqlDataReader"]/GetSchemaTable/*'/>

src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,9 @@
471471
<Compile Include="$(CommonSourceRoot)Microsoft\Data\SqlClient\Server\ValueUtilsSmi.cs">
472472
<Link>Microsoft\Data\SqlClient\Server\ValueUtilsSmi.cs</Link>
473473
</Compile>
474+
<Compile Include="$(CommonSourceRoot)Microsoft\Data\SqlClient\ISqlVector.cs">
475+
<Link>Microsoft\Data\SqlClient\ISqlVector.cs</Link>
476+
</Compile>
474477
<Compile Include="$(CommonSourceRoot)Microsoft\Data\SqlClient\SignatureVerificationCache.cs">
475478
<Link>Microsoft\Data\SqlClient\SignatureVerificationCache.cs</Link>
476479
</Compile>
@@ -792,6 +795,9 @@
792795
<Compile Include="$(CommonSourceRoot)Microsoft\Data\SqlTypes\SqlJson.cs">
793796
<Link>Microsoft\Data\SqlTypes\SqlJson.cs</Link>
794797
</Compile>
798+
<Compile Include="$(CommonSourceRoot)Microsoft\Data\SqlTypes\SqlVectorFloat32.cs">
799+
<Link>Microsoft\Data\SqlTypes\SqlVectorFloat32.cs</Link>
800+
</Compile>
795801
<Compile Include="$(CommonSourceRoot)Resources\ResCategoryAttribute.cs">
796802
<Link>Resources\ResCategoryAttribute.cs</Link>
797803
</Compile>

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6435,6 +6435,16 @@ internal string BuildParamList(TdsParser parser, SqlParameterCollection paramete
64356435
paramList.Append(scale);
64366436
paramList.Append(')');
64376437
}
6438+
else if (mt.SqlDbType == SqlDbTypeExtensions.Vector)
6439+
{
6440+
// The validate function for SqlParameters would
6441+
// have already thrown InvalidCastException if an incompatible
6442+
// value is specified for SqlDbType Vector.
6443+
var sqlVectorProps = (ISqlVector)sqlParam.Value;
6444+
paramList.Append('(');
6445+
paramList.Append(sqlVectorProps.Length);
6446+
paramList.Append(')');
6447+
}
64386448
else if (!mt.IsFixed && !mt.IsLong && mt.SqlDbType != SqlDbType.Timestamp && mt.SqlDbType != SqlDbType.Udt && SqlDbType.Structured != mt.SqlDbType)
64396449
{
64406450
int size = sqlParam.Size;

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

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,9 @@ internal bool IsDNSCachingBeforeRedirectSupported
207207
// Json Support Flag
208208
internal bool IsJsonSupportEnabled = false;
209209

210+
// Vector Support Flag
211+
internal bool IsVectorSupportEnabled = false;
212+
210213
// TCE flags
211214
internal byte _tceVersionSupported;
212215

@@ -1422,9 +1425,10 @@ private void Login(ServerInfo server, TimeoutTimer timeout, string newPassword,
14221425
requestedFeatures |= TdsEnums.FeatureExtension.AzureSQLSupport;
14231426
}
14241427

1425-
// The SQLDNSCaching and JSON features are implicitly set
1428+
// The following features are implicitly set
14261429
requestedFeatures |= TdsEnums.FeatureExtension.SQLDNSCaching;
14271430
requestedFeatures |= TdsEnums.FeatureExtension.JsonSupport;
1431+
requestedFeatures |= TdsEnums.FeatureExtension.VectorSupport;
14281432

14291433
_parser.TdsLogin(login, requestedFeatures, _recoverySessionData, _fedAuthFeatureExtensionData, encrypt);
14301434
}
@@ -3011,6 +3015,24 @@ internal void OnFeatureExtAck(int featureId, byte[] data)
30113015
break;
30123016
}
30133017

3018+
case TdsEnums.FEATUREEXT_VECTORSUPPORT:
3019+
{
3020+
SqlClientEventSource.Log.TryAdvancedTraceEvent("<sc.SqlInternalConnectionTds.OnFeatureExtAck|ADV> {0}, Received feature extension acknowledgement for VECTORSUPPORT", ObjectID);
3021+
if (data.Length != 1)
3022+
{
3023+
SqlClientEventSource.Log.TryTraceEvent("<sc.SqlInternalConnectionTds.OnFeatureExtAck|ERR> {0}, Unknown token for VECTORSUPPORT", ObjectID);
3024+
throw SQL.ParsingError(ParsingErrorState.CorruptedTdsStream);
3025+
}
3026+
byte vectorSupportVersion = data[0];
3027+
if (vectorSupportVersion == 0 || vectorSupportVersion > TdsEnums.MAX_SUPPORTED_VECTOR_VERSION)
3028+
{
3029+
SqlClientEventSource.Log.TryTraceEvent("<sc.SqlInternalConnectionTds.OnFeatureExtAck|ERR> {0}, Invalid version number {1} for VECTORSUPPORT, Max supported version is {2}", ObjectID, vectorSupportVersion, TdsEnums.MAX_SUPPORTED_VECTOR_VERSION);
3030+
throw SQL.ParsingError();
3031+
}
3032+
IsVectorSupportEnabled = true;
3033+
break;
3034+
}
3035+
30143036
default:
30153037
{
30163038
// Unknown feature ack

0 commit comments

Comments
 (0)