Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -201,6 +201,9 @@ internal bool IsDNSCachingBeforeRedirectSupported

internal SQLDNSInfo pendingSQLDNSObject = null;

// Json Support Flag
internal bool IsJsonSupportEnabled = false;

// TCE flags
internal byte _tceVersionSupported;

Expand Down Expand Up @@ -1365,6 +1368,8 @@ private void Login(ServerInfo server, TimeoutTimer timeout, string newPassword,
// The SQLDNSCaching feature is implicitly set
requestedFeatures |= TdsEnums.FeatureExtension.SQLDNSCaching;

requestedFeatures |= TdsEnums.FeatureExtension.JsonSupport;

_parser.TdsLogin(login, requestedFeatures, _recoverySessionData, _fedAuthFeatureExtensionData, encrypt);
}

Expand Down Expand Up @@ -2812,6 +2817,24 @@ internal void OnFeatureExtAck(int featureId, byte[] data)
break;
}

case TdsEnums.FEATUREEXT_JSONSUPPORT:
{
SqlClientEventSource.Log.TryAdvancedTraceEvent("<sc.SqlInternalConnectionTds.OnFeatureExtAck|ADV> {0}, Received feature extension acknowledgement for JSONSUPPORT", ObjectID);
if (data.Length != 1)
{
SqlClientEventSource.Log.TryTraceEvent("<sc.SqlInternalConnectionTds.OnFeatureExtAck|ERR> {0}, Unknown token for JSONSUPPORT", ObjectID);
throw SQL.ParsingError(ParsingErrorState.CorruptedTdsStream);
}
byte jsonSupportVersion = data[0];
if (jsonSupportVersion == 0 || jsonSupportVersion > 1)
{
SqlClientEventSource.Log.TryTraceEvent("<sc.SqlInternalConnectionTds.OnFeatureExtAck|ERR> {0}, Invalid version number for JSONSUPPORT", ObjectID);
throw SQL.ParsingError();
}
IsJsonSupportEnabled = true;
break;
}

default:
{
// Unknown feature ack
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8115,6 +8115,21 @@ internal int WriteFedAuthFeatureRequest(FederatedAuthenticationFeatureExtensionD
return len;
}

internal int WriteJsonSupportFeatureRequest(bool write /* if false just calculates the length */)
{
int len = 6; // 1byte = featureID, 4bytes = featureData length, 1 bytes = Version

if (write)
{
// Write Feature ID
_physicalStateObj.WriteByte(TdsEnums.FEATUREEXT_JSONSUPPORT);
WriteInt(1, _physicalStateObj);
_physicalStateObj.WriteByte(1);
}

return len;
}

private void WriteLoginData(SqlLogin rec,
TdsEnums.FeatureExtension requestedFeatures,
SessionData recoverySessionData,
Expand Down Expand Up @@ -8425,6 +8440,11 @@ private int ApplyFeatureExData(TdsEnums.FeatureExtension requestedFeatures,
length += WriteSQLDNSCachingFeatureRequest(write);
}

if ((requestedFeatures & TdsEnums.FeatureExtension.JsonSupport) != 0)
{
length += WriteJsonSupportFeatureRequest(write);
}

length++; // for terminator
if (write)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,9 @@ internal bool IsDNSCachingBeforeRedirectSupported

internal SQLDNSInfo pendingSQLDNSObject = null;

// Json Support Flag
internal bool IsJsonSupportEnabled = false;

// TCE flags
internal byte _tceVersionSupported;

Expand Down Expand Up @@ -1638,6 +1641,8 @@ private void Login(ServerInfo server, TimeoutTimer timeout, string newPassword,
// The SQLDNSCaching feature is implicitly set
requestedFeatures |= TdsEnums.FeatureExtension.SQLDNSCaching;

requestedFeatures |= TdsEnums.FeatureExtension.JsonSupport;

_parser.TdsLogin(login, requestedFeatures, _recoverySessionData, _fedAuthFeatureExtensionData, _originalNetworkAddressInfo, encrypt);
}

Expand Down Expand Up @@ -3239,6 +3244,24 @@ internal void OnFeatureExtAck(int featureId, byte[] data)
break;
}

case TdsEnums.FEATUREEXT_JSONSUPPORT:
{
SqlClientEventSource.Log.TryAdvancedTraceEvent("<sc.SqlInternalConnectionTds.OnFeatureExtAck|ADV> {0}, Received feature extension acknowledgement for JSONSUPPORT", ObjectID);
if (data.Length != 1)
{
SqlClientEventSource.Log.TryTraceEvent("<sc.SqlInternalConnectionTds.OnFeatureExtAck|ERR> {0}, Unknown token for JSONSUPPORT", ObjectID);
throw SQL.ParsingError(ParsingErrorState.CorruptedTdsStream);
}
byte jsonSupportVersion = data[0];
if (jsonSupportVersion == 0 || jsonSupportVersion > 1)
{
SqlClientEventSource.Log.TryTraceEvent("<sc.SqlInternalConnectionTds.OnFeatureExtAck|ERR> {0}, Invalid version number for JSONSUPPORT", ObjectID);
throw SQL.ParsingError(ParsingErrorState.CorruptedTdsStream);
}
IsJsonSupportEnabled = true;
break;
}

default:
{
// Unknown feature ack
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8914,6 +8914,21 @@ internal int WriteFedAuthFeatureRequest(FederatedAuthenticationFeatureExtensionD
return len;
}

internal int WriteJsonSupportFeatureRequest(bool write /* if false just calculates the length */)
{
int len = 6; // 1byte = featureID, 4bytes = featureData length, 1 bytes = Version

if (write)
{
// Write Feature ID
_physicalStateObj.WriteByte(TdsEnums.FEATUREEXT_JSONSUPPORT);
WriteInt(1, _physicalStateObj);
_physicalStateObj.WriteByte(1);
}

return len;
}

private void WriteLoginData(SqlLogin rec,
TdsEnums.FeatureExtension requestedFeatures,
SessionData recoverySessionData,
Expand Down Expand Up @@ -9241,6 +9256,11 @@ private int ApplyFeatureExData(TdsEnums.FeatureExtension requestedFeatures,
length += WriteSQLDNSCachingFeatureRequest(write);
}

if ((requestedFeatures & TdsEnums.FeatureExtension.JsonSupport) != 0)
{
length += WriteJsonSupportFeatureRequest(write);
}

length++; // for terminator
if (write)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ public enum EnvChangeType : byte
public const byte FEATUREEXT_DATACLASSIFICATION = 0x09;
public const byte FEATUREEXT_UTF8SUPPORT = 0x0A;
public const byte FEATUREEXT_SQLDNSCACHING = 0x0B;
public const byte FEATUREEXT_JSONSUPPORT = 0x0D;

[Flags]
public enum FeatureExtension : uint
Expand All @@ -250,7 +251,8 @@ public enum FeatureExtension : uint
AzureSQLSupport = 1 << (TdsEnums.FEATUREEXT_AZURESQLSUPPORT - 1),
DataClassification = 1 << (TdsEnums.FEATUREEXT_DATACLASSIFICATION - 1),
UTF8Support = 1 << (TdsEnums.FEATUREEXT_UTF8SUPPORT - 1),
SQLDNSCaching = 1 << (TdsEnums.FEATUREEXT_SQLDNSCACHING - 1)
SQLDNSCaching = 1 << (TdsEnums.FEATUREEXT_SQLDNSCACHING - 1),
JsonSupport = 1 << (TdsEnums.FEATUREEXT_JSONSUPPORT - 1)
}

public const uint UTF8_IN_TDSCOLLATION = 0x4000000;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,5 +77,10 @@ public interface ITDSServerSession
/// Indicates whether this session supports transport-level recovery
/// </summary>
bool IsSessionRecoveryEnabled { get; set; }

/// <summary>
/// Indicates whether the client supports Json column type
/// </summary>
bool IsJsonSupportEnabled { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,12 @@ public virtual TDSMessageCollection OnLogin7Request(ITDSServerSession session, T
// Save the fed auth library to be used
(session as GenericTDSServerSession).FederatedAuthenticationLibrary = federatedAuthenticationOption.Library;

break;
}
case TDSFeatureID.JsonSupport:
{
// Enable Json Support
session.IsJsonSupportEnabled = true;
break;
}
default:
Expand Down Expand Up @@ -544,6 +550,32 @@ protected virtual TDSMessageCollection OnAuthenticationCompleted(ITDSServerSessi
responseMessage.Add(featureExtActToken);
}

// Check if Json is supported
if (session.IsJsonSupportEnabled)
{
// Create ack data (1 byte: Version number)
byte[] data = new byte[1];
data[0] = (byte)1;

// Create Json support as a generic feature extension option
TDSFeatureExtAckGenericOption jsonSupportOption = new TDSFeatureExtAckGenericOption(TDSFeatureID.JsonSupport, (uint)data.Length, data);

// Look for feature extension token
TDSFeatureExtAckToken featureExtAckToken = (TDSFeatureExtAckToken)responseMessage.Where(t => t is TDSFeatureExtAckToken).FirstOrDefault();

if (featureExtAckToken == null)
{
// Create feature extension ack token
featureExtAckToken = new TDSFeatureExtAckToken(jsonSupportOption);
responseMessage.Add(featureExtAckToken);
}
else
{
// Update the existing token
featureExtAckToken.Options.Add(jsonSupportOption);
}
}

// Create DONE token
TDSDoneToken doneToken = new TDSDoneToken(TDSDoneTokenStatusType.Final);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,11 @@ public class GenericTDSServerSession : ITDSServerSession
/// </summary>
public bool IsSessionRecoveryEnabled { get; set; }

/// <summary>
/// Indicates whether this session supports Json column type
/// </summary>
public bool IsJsonSupportEnabled { get; set; }

#region Session Options

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ public enum TDSFeatureID : byte
/// </summary>
FederatedAuthentication = 0x02,

/// <summary>
/// JSON Support
/// </summary>
JsonSupport = 0x0D,

/// <summary>
/// End of the list
/// </summary>
Expand Down