Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
a6646c0
Add ConnectionCapabilities class
edwardneal Dec 27, 2025
e37f3a2
Hook LOGINACK handling
edwardneal Dec 27, 2025
de5c285
Update reference to _is20XX to reference Capabilities property
edwardneal Dec 27, 2025
65e701f
Errata: use BinaryPrimitives
edwardneal Dec 27, 2025
943c7db
Move handling of SqlLoginAck to ConnectionCapabilities
edwardneal Dec 27, 2025
c4ab86d
TdsEnums.cs constants cleanup
edwardneal Dec 27, 2025
d68b90c
Hook FEATUREEXT handling
edwardneal Dec 27, 2025
936218e
Move JSON feature detection handling
edwardneal Dec 27, 2025
53f8947
Move float32 vector feature detection handling
edwardneal Dec 27, 2025
8ee0fb4
Move Azure SQL feature detection handling
edwardneal Dec 27, 2025
7713018
Add additional detection logic for Global Transactions
edwardneal Dec 27, 2025
0e1fcc5
Move Global Transactions feature detection handling
edwardneal Dec 27, 2025
ade2336
Move data classification feature detection handling
edwardneal Dec 27, 2025
ab9ebff
Move initial SQL DNS caching feature detection handling
edwardneal Dec 28, 2025
abd69b7
Remove unnecessary _cleanSQLDNSCaching member
edwardneal Dec 28, 2025
50ccf47
Move column encryption feature detection handling
edwardneal Dec 28, 2025
24caa2a
Move logic to throw on unknown FEATUREEXT tokens into TdsParser
edwardneal Dec 28, 2025
984ac2e
Refactor parsing condition into ShouldProcessFeatureExtAck
edwardneal Dec 28, 2025
9380711
Maintain original server version behaviour
edwardneal Dec 28, 2025
95ac4f5
Performance: convert SqlLoginAck to a readonly ref struct
edwardneal Dec 28, 2025
229a04d
Enable Release mode build
edwardneal Dec 28, 2025
25b01d4
Plumb new ConnectionCapabilities to SqlMetaDataFactory
edwardneal Dec 28, 2025
6560f5f
Cross-check FEATUREEXT validation to original OnFeatureExtAck
edwardneal Dec 28, 2025
7c86769
Merge main
edwardneal Feb 12, 2026
2402cd7
Merge branch 'main' into cleanup/unified-connection-capabilities
edwardneal Feb 17, 2026
f532f60
Merge main
edwardneal Mar 26, 2026
a67a8a8
Move enhanced routing feature detection support
edwardneal Mar 26, 2026
731e99d
Merge main
edwardneal May 6, 2026
b1fea76
Revert movement of feature/login handling
edwardneal May 13, 2026
a84b88f
Revert handling of _cleanSQLDNSCaching
edwardneal May 13, 2026
5791efe
Move Capabilities to DbConnectionInternal
edwardneal May 13, 2026
7ef36b5
Move capability reset to connect methods
edwardneal May 13, 2026
0c41cf4
Align Capabilities and ServerVersion exception behaviour across deriv…
edwardneal May 13, 2026
dd9db7e
Add unit test verifying behaviour of TDS version validation
edwardneal May 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,17 @@ internal static void ValidateCommandBehavior(CommandBehavior value)
}
}

internal static void ValidateTdsVersion(uint tdsVersion)
{
if (tdsVersion is not TdsEnums.SQL2005_VERSION
and not TdsEnums.SQL2008_VERSION
and not TdsEnums.TDS7X_VERSION
and not TdsEnums.TDS80_VERSION)
{
throw SQL.InvalidTDSVersion();
}
}

internal static ArgumentOutOfRangeException InvalidUserDefinedTypeSerializationFormat(Format value)
{
#if DEBUG
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ protected DbConnectionClosed(ConnectionState state, bool hidePassword, bool allo

public override string ServerVersion => throw ADP.ClosedConnectionError();

public override ConnectionCapabilities Capabilities => throw ADP.ClosedConnectionError();

protected override void Activate(System.Transactions.Transaction transaction) => throw ADP.ClosedConnectionError();

public override DbTransaction BeginTransaction(IsolationLevel il) => throw ADP.ClosedConnectionError();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ internal bool IsInPool

public abstract string ServerVersion { get; }

public virtual ConnectionCapabilities Capabilities => null;

// this should be abstract but until it is added to all the providers virtual will have to do RickFe
public virtual string ServerVersionNormalized
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using Microsoft.Data.SqlClient.Internal;
using System;
using System.Text;

#nullable enable

namespace Microsoft.Data.SqlClient;

/// <summary>
/// Describes the capabilities and related information (such as the
/// reported server version and TDS version) of the connection.
/// </summary>
internal sealed class ConnectionCapabilities
{
/// <summary>
/// The TDS version reported by the LoginAck response
/// from the server.
/// </summary>
public uint TdsVersion { get; set; }

/// <summary>
/// The SQL Server major version reported by the LoginAck
/// response from the server.
/// </summary>
public byte ServerMajorVersion { get; set; }

/// <summary>
/// The SQL Server minor version reported by the LoginAck
/// response from the server.
/// </summary>
public byte ServerMinorVersion { get; set; }

/// <summary>
/// The SQL Server build number reported by the LoginAck
/// response from the server.
/// </summary>
public ushort ServerBuildNumber { get; set; }

/// <summary>
/// The user-friendly SQL Server version reported by the
/// LoginAck response from the server.
/// </summary>
public string ServerVersion =>
$"{ServerMajorVersion:00}.{ServerMinorVersion:00}.{ServerBuildNumber:0000}";

/// <summary>
/// If true (as determined by the value of <see cref="TdsVersion"/>)
/// then the connection is to SQL Server 2008 R2 or newer.
/// </summary>
public bool Is2008R2OrNewer =>
Is2012OrNewer || TdsVersion == TdsEnums.SQL2008_VERSION;

/// <summary>
/// If true (as determined by the value of <see cref="TdsVersion"/>)
/// then the connection is to SQL Server 2012 or newer.
/// </summary>
public bool Is2012OrNewer =>
Is2022OrNewer || TdsVersion == TdsEnums.TDS7X_VERSION;

/// <summary>
/// If true (as determined by the value of <see cref="TdsVersion"/>)
/// then the connection is to SQL Server 2022 or newer.
/// </summary>
public bool Is2022OrNewer =>
TdsVersion == TdsEnums.TDS80_VERSION;

/// <summary>
/// If true, this connection is to an Azure SQL instance. This is determined
/// by the receipt of a FEATUREEXTACK token of value <c>0x08</c>.
/// </summary>
public bool IsAzureSql { get; set; }

/// <summary>
/// Indicates support for user-defined CLR types (up to a length of 8000
/// bytes.) This was introduced in SQL Server 2005.
/// </summary>
public bool UserDefinedTypes => true;
Comment thread
mdaigle marked this conversation as resolved.

/// <summary>
/// Indicates support for the <c>xml</c> data type. This was introduced
/// in SQL Server 2005.
/// </summary>
public bool XmlDataType => true;

/// <summary>
/// Indicates support for the <c>date</c>, <c>time</c>, <c>datetime2</c>
/// and <c>datetimeoffset</c> data types. These were introduced in SQL
/// Server 2008.
/// </summary>
public bool ExpandedDateTimeDataTypes => Is2008R2OrNewer;

/// <summary>
/// Indicates support for user-defined CLR types of any length. This
/// was introduced in SQL Server 2008.
/// </summary>
public bool LargeUserDefinedTypes => Is2008R2OrNewer;

/// <summary>
/// Indicates support for the client to include a TDS trace header,
/// which is surfaced in XEvents traces to correlate events between
/// the client and the server. This was introduced in SQL Server 2012.
/// </summary>
public bool TraceHeader => Is2012OrNewer;

/// <summary>
/// Indicates support for UTF8 collations. This was introduced in SQL
/// Server 2019, and is only available if a FEATUREEXTACK token of value
/// <c>0x0A</c> is received.
/// </summary>
public bool Utf8 { get; set; }

/// <summary>
/// Indicates support for the client to cache DNS resolution responses for
/// the server. This is only supported by Azure SQL, and is only available
/// if a FEATUREEXTACK token of value <c>0x0B</c> is received.
/// </summary>
public bool DnsCaching { get; set; }

/// <summary>
/// Indicates support for Data Classification and specifies the version of
/// Data Classification which is supported. This was introduced in SQL
/// Server 2019, and is only available if a FEATUREEXTACK token of value
/// <c>0x09</c> is received.
/// </summary>
/// <remarks>
/// This should only be <c>1</c> or <c>2</c>.
/// </remarks>
public byte DataClassificationVersion { get; set; }

/// <summary>
/// Indicates that Global Transactions are available (even if not currently enabled.)
/// Global Transactions are only supported by Azure SQL, and are only available if a
/// FEATUREEXTACK token of value <c>0x05</c> is received.
/// </summary>
public bool GlobalTransactionsAvailable { get; set; }

/// <summary>
/// Indicates support for Global Transactions. This is only supported by
/// Azure SQL, and is only available if a FEATUREEXTACK token of value
/// <c>0x05</c> is received.
/// </summary>
public bool GlobalTransactionsSupported { get; set; }

/// <summary>
/// Indicates support for Enhanced Routing. This is only supported by
/// Azure SQL, and is only available if a FEATUREEXTACK token of value
/// <c>0x0F</c> is received.
/// </summary>
public bool EnhancedRouting { get; set; }

/// <summary>
/// Indicates support for connecting to the current connection's failover
/// partner with an Application Intent of ReadOnly. This is only supported
/// by Azure SQL, and is only available if a FEATUREEXTACK token of value
/// <c>0x08</c> is received, and if bit zero of this token's data is set.
/// </summary>
public bool ReadOnlyFailoverPartnerConnection { get; set; }

/// <summary>
/// Indicates support for the <c>vector</c> data type, with a backing type
/// of <c>float32</c>. This was introduced in SQL Server 2022, and is only
/// available if a FEATUREEXTACK token of value <c>0x0E</c> is received, and
/// if the version in this token's data is greater than or equal to <c>1</c>.
/// </summary>
public bool Float32VectorType { get; set; }

/// <summary>
/// Indicates support for the <c>json</c> data type. This was introduced in
/// SQL Server 2022, and is only available if a FEATUREEXTACK token of value
/// <c>0x0D</c> is received, and if the version in this token's data is
/// greater than or equal to <c>1</c>.
/// </summary>
public bool JsonType { get; set; }

/// <summary>
/// Indicates support for column encryption and specifies the version of column
/// encryption which is supported. This was introduced in SQL Server 2016, and is
/// only available if a FEATUREEXTACK token of value <c>0x04</c> is received.
/// </summary>
/// <remarks>
/// This should only be <c>1</c>, <c>2</c> or <c>3</c>. v1 is supported from SQL
/// Server 2016 upwards, v2 is supported from SQL Server 2019 upwards, v3 is supported
/// from SQL Server 2022 upwards.
/// </remarks>
public byte ColumnEncryptionVersion { get; set; }

/// <summary>
/// If column encryption is enabled, the type of enclave reported by the server. This
/// was introduced in SQL Server 2019, and is only available if a FEATUREEXTACK token
/// of value <c>0x04</c> is received, and the resultant <see cref="ColumnEncryptionVersion"/>
/// is <c>2</c> or <c>3</c>.
/// </summary>
public string? ColumnEncryptionEnclaveType { get; set; }

/// <summary>
/// Returns the capability records to unset values.
/// </summary>
public void Reset()
{
TdsVersion = 0;
ServerMajorVersion = 0;
ServerMinorVersion = 0;
ServerBuildNumber = 0;

IsAzureSql = false;
Utf8 = false;
DnsCaching = false;
DataClassificationVersion = TdsEnums.DATA_CLASSIFICATION_NOT_ENABLED;
GlobalTransactionsAvailable = false;
GlobalTransactionsSupported = false;
EnhancedRouting = false;
ReadOnlyFailoverPartnerConnection = false;
Float32VectorType = false;
JsonType = false;
ColumnEncryptionVersion = TdsEnums.TCE_NOT_ENABLED;
ColumnEncryptionEnclaveType = null;
}
}
Loading
Loading