diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj
index 9c7cf50ee5..dc5fc9dd51 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj
@@ -958,7 +958,7 @@
-
+
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs
index 015fb6c1fe..d811c3f021 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs
@@ -6471,7 +6471,7 @@ internal string BuildParamList(TdsParser parser, SqlParameterCollection paramete
paramList.Append(size);
paramList.Append(')');
}
- else if (mt.IsPlp && (mt.SqlDbType != SqlDbType.Xml) && (mt.SqlDbType != SqlDbType.Udt))
+ else if (mt.IsPlp && (mt.SqlDbType != SqlDbType.Xml) && (mt.SqlDbType != SqlDbType.Udt) && (mt.SqlDbType != SqlDbTypeExtensions.Json))
{
paramList.Append("(max) ");
}
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs
index c3291e4e5d..f8865b5540 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs
@@ -5178,7 +5178,7 @@ private TdsOperationStatus TryProcessTypeInfo(TdsParserStateObject stateObj, Sql
}
// read the collation for 7.x servers
- if (col.metaType.IsCharType && (tdsType != TdsEnums.SQLXMLTYPE))
+ if (col.metaType.IsCharType && (tdsType != TdsEnums.SQLXMLTYPE) && ((tdsType != TdsEnums.SQLJSON)))
{
result = TryProcessCollation(stateObj, out col.collation);
if (result != TdsOperationStatus.Done)
@@ -5958,6 +5958,7 @@ private TdsOperationStatus TryReadSqlStringValue(SqlBuffer value, byte type, int
case TdsEnums.SQLVARCHAR:
case TdsEnums.SQLBIGVARCHAR:
case TdsEnums.SQLTEXT:
+ case TdsEnums.SQLJSON:
// If bigvarchar(max), we only read the first chunk here,
// expecting the caller to read the rest
if (encoding == null)
@@ -6427,6 +6428,7 @@ internal TdsOperationStatus TryReadSqlValue(SqlBuffer value, SqlMetaDataPriv md,
case TdsEnums.SQLNCHAR:
case TdsEnums.SQLNVARCHAR:
case TdsEnums.SQLNTEXT:
+ case TdsEnums.SQLJSON:
result = TryReadSqlStringValue(value, tdsType, length, md.encoding, isPlp, stateObj);
if (result != TdsOperationStatus.Done)
{
@@ -7964,6 +7966,7 @@ internal TdsOperationStatus TryGetDataLength(SqlMetaDataPriv colmeta, TdsParserS
colmeta.tdsType == TdsEnums.SQLBIGVARCHAR ||
colmeta.tdsType == TdsEnums.SQLBIGVARBINARY ||
colmeta.tdsType == TdsEnums.SQLNVARCHAR ||
+ colmeta.tdsType == TdsEnums.SQLJSON ||
// Large UDTs is WinFS-only
colmeta.tdsType == TdsEnums.SQLUDT,
"GetDataLength:Invalid streaming datatype");
@@ -9819,7 +9822,7 @@ private Task TDSExecuteRPCAddParameter(TdsParserStateObject stateObj, SqlParamet
}
else if (mt.IsPlp)
{
- if (mt.SqlDbType != SqlDbType.Xml)
+ if (mt.SqlDbType != SqlDbType.Xml && mt.SqlDbType != SqlDbTypeExtensions.Json)
WriteShort(TdsEnums.SQL_USHORTVARMAXLEN, stateObj);
}
else if ((!mt.IsVarTime) && (mt.SqlDbType != SqlDbType.Date))
@@ -9859,53 +9862,56 @@ private Task TDSExecuteRPCAddParameter(TdsParserStateObject stateObj, SqlParamet
// write out collation or xml metadata
- if (_is2005 && (mt.SqlDbType == SqlDbType.Xml))
+ if ((mt.SqlDbType == SqlDbType.Xml || mt.SqlDbType == SqlDbTypeExtensions.Json))
{
- if (!string.IsNullOrEmpty(param.XmlSchemaCollectionDatabase) ||
- !string.IsNullOrEmpty(param.XmlSchemaCollectionOwningSchema) ||
- !string.IsNullOrEmpty(param.XmlSchemaCollectionName))
+ if (mt.SqlDbType == SqlDbType.Xml)
{
- stateObj.WriteByte(1); //Schema present flag
-
- if (!string.IsNullOrEmpty(param.XmlSchemaCollectionDatabase))
+ if (!string.IsNullOrEmpty(param.XmlSchemaCollectionDatabase) ||
+ !string.IsNullOrEmpty(param.XmlSchemaCollectionOwningSchema) ||
+ !string.IsNullOrEmpty(param.XmlSchemaCollectionName))
{
- tempLen = (param.XmlSchemaCollectionDatabase).Length;
- stateObj.WriteByte((byte)(tempLen));
- WriteString(param.XmlSchemaCollectionDatabase, tempLen, 0, stateObj);
- }
- else
- {
- stateObj.WriteByte(0); // No dbname
- }
+ stateObj.WriteByte(1); //Schema present flag
- if (!string.IsNullOrEmpty(param.XmlSchemaCollectionOwningSchema))
- {
- tempLen = (param.XmlSchemaCollectionOwningSchema).Length;
- stateObj.WriteByte((byte)(tempLen));
- WriteString(param.XmlSchemaCollectionOwningSchema, tempLen, 0, stateObj);
- }
- else
- {
- stateObj.WriteByte(0); // no xml schema name
- }
+ if (!string.IsNullOrEmpty(param.XmlSchemaCollectionDatabase))
+ {
+ tempLen = (param.XmlSchemaCollectionDatabase).Length;
+ stateObj.WriteByte((byte)(tempLen));
+ WriteString(param.XmlSchemaCollectionDatabase, tempLen, 0, stateObj);
+ }
+ else
+ {
+ stateObj.WriteByte(0); // No dbname
+ }
+
+ if (!string.IsNullOrEmpty(param.XmlSchemaCollectionOwningSchema))
+ {
+ tempLen = (param.XmlSchemaCollectionOwningSchema).Length;
+ stateObj.WriteByte((byte)(tempLen));
+ WriteString(param.XmlSchemaCollectionOwningSchema, tempLen, 0, stateObj);
+ }
+ else
+ {
+ stateObj.WriteByte(0); // no xml schema name
+ }
+ if (!string.IsNullOrEmpty(param.XmlSchemaCollectionName))
+ {
+ tempLen = (param.XmlSchemaCollectionName).Length;
+ WriteShort((short)(tempLen), stateObj);
+ WriteString(param.XmlSchemaCollectionName, tempLen, 0, stateObj);
+ }
+ else
+ {
+ WriteShort(0, stateObj); // No xml schema collection name
+ }
- if (!string.IsNullOrEmpty(param.XmlSchemaCollectionName))
- {
- tempLen = (param.XmlSchemaCollectionName).Length;
- WriteShort((short)(tempLen), stateObj);
- WriteString(param.XmlSchemaCollectionName, tempLen, 0, stateObj);
}
else
{
- WriteShort(0, stateObj); // No xml schema collection name
+ stateObj.WriteByte(0); // No schema
}
}
- else
- {
- stateObj.WriteByte(0); // No schema
- }
}
- else if (mt.IsCharType)
+ else if (mt.IsCharType && mt.SqlDbType != SqlDbTypeExtensions.Json)
{
// if it is not supplied, simply write out our default collation, otherwise, write out the one attached to the parameter
SqlCollation outCollation = (param.Collation != null) ? param.Collation : _defaultCollation;
@@ -11485,10 +11491,18 @@ private Task WriteUnterminatedSqlValue(object value, MetaType type, int actualLe
case TdsEnums.SQLNVARCHAR:
case TdsEnums.SQLNTEXT:
case TdsEnums.SQLXMLTYPE:
+ case TdsEnums.SQLJSON:
if (type.IsPlp)
{
- if (IsBOMNeeded(type, value))
+ if (type.NullableType == TdsEnums.SQLJSON)
+ {
+ // TODO : Performance and BOM check. Saurabh
+ byte[] jsonAsBytes = Encoding.UTF8.GetBytes(value.ToString());
+ WriteInt(jsonAsBytes.Length, stateObj);
+ return stateObj.WriteByteArray(jsonAsBytes, jsonAsBytes.Length, 0, canAccumulate: false);
+ }
+ else if (IsBOMNeeded(type, value))
{
WriteInt(actualLength + 2, stateObj); // chunk length
WriteShort(TdsEnums.XMLUNICODEBOM, stateObj);
@@ -12135,6 +12149,7 @@ private Task WriteUnterminatedValue(object value, MetaType type, byte scale, int
case TdsEnums.SQLNVARCHAR:
case TdsEnums.SQLNTEXT:
case TdsEnums.SQLXMLTYPE:
+ case TdsEnums.SQLJSON:
{
Debug.Assert(!isDataFeed || (value is TextDataFeed || value is XmlDataFeed), "Value must be a TextReader or XmlReader");
Debug.Assert(isDataFeed || (value is string || value is byte[]), "Value is a byte array or string");
@@ -12156,7 +12171,14 @@ private Task WriteUnterminatedValue(object value, MetaType type, byte scale, int
{
if (type.IsPlp)
{
- if (IsBOMNeeded(type, value))
+ if (type.NullableType == TdsEnums.SQLJSON)
+ {
+ // TODO : Performance and BOM check. Saurabh
+ byte[] jsonAsBytes = Encoding.UTF8.GetBytes((string)value);
+ WriteInt(jsonAsBytes.Length, stateObj);
+ return stateObj.WriteByteArray(jsonAsBytes, jsonAsBytes.Length, 0, canAccumulate: false);
+ }
+ else if (IsBOMNeeded(type, value))
{
WriteInt(actualLength + 2, stateObj); // chunk length
WriteShort(TdsEnums.XMLUNICODEBOM, stateObj);
@@ -12662,7 +12684,7 @@ internal void WriteParameterVarLen(MetaType type, int size, bool isNull, TdsPars
WriteInt(unchecked((int)TdsEnums.VARLONGNULL), stateObj);
}
}
- else if (type.NullableType == TdsEnums.SQLXMLTYPE || unknownLength)
+ else if (type.NullableType is TdsEnums.SQLXMLTYPE or TdsEnums.SQLJSON || unknownLength)
{
WriteUnsignedLong(TdsEnums.SQL_PLP_UNKNOWNLEN, stateObj);
}
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj
index 840f5b6520..9e4fffdfa1 100644
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj
+++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj
@@ -756,7 +756,7 @@
-
+
$(SystemTextEncodingsWebVersion)
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommand.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommand.cs
index 00b17a0213..fcb8aaf58c 100644
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommand.cs
+++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommand.cs
@@ -7180,7 +7180,7 @@ internal string BuildParamList(TdsParser parser, SqlParameterCollection paramete
paramList.Append(size);
paramList.Append(')');
}
- else if (mt.IsPlp && (mt.SqlDbType != SqlDbType.Xml) && (mt.SqlDbType != SqlDbType.Udt))
+ else if (mt.IsPlp && (mt.SqlDbType != SqlDbType.Xml) && (mt.SqlDbType != SqlDbType.Udt) && (mt.SqlDbType != SqlDbTypeExtensions.Json))
{
paramList.Append("(max) ");
}
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParser.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParser.cs
index 459b230be6..cc91798a0c 100644
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParser.cs
+++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParser.cs
@@ -5876,7 +5876,7 @@ private TdsOperationStatus TryProcessTypeInfo(TdsParserStateObject stateObj, Sql
}
// read the collation for 7.x servers
- if (_is2000 && col.metaType.IsCharType && (tdsType != TdsEnums.SQLXMLTYPE))
+ if (_is2000 && col.metaType.IsCharType && (tdsType != TdsEnums.SQLXMLTYPE) && (tdsType != TdsEnums.SQLJSON))
{
result = TryProcessCollation(stateObj, out col.collation);
if (result != TdsOperationStatus.Done)
@@ -6805,6 +6805,7 @@ private TdsOperationStatus TryReadSqlStringValue(SqlBuffer value, byte type, int
case TdsEnums.SQLVARCHAR:
case TdsEnums.SQLBIGVARCHAR:
case TdsEnums.SQLTEXT:
+ case TdsEnums.SQLJSON:
// If bigvarchar(max), we only read the first chunk here,
// expecting the caller to read the rest
if (encoding == null)
@@ -7255,6 +7256,7 @@ internal TdsOperationStatus TryReadSqlValue(SqlBuffer value,
case TdsEnums.SQLNCHAR:
case TdsEnums.SQLNVARCHAR:
case TdsEnums.SQLNTEXT:
+ case TdsEnums.SQLJSON:
result = TryReadSqlStringValue(value, tdsType, length, md.encoding, isPlp, stateObj);
if (result != TdsOperationStatus.Done)
{
@@ -8777,6 +8779,7 @@ internal TdsOperationStatus TryGetDataLength(SqlMetaDataPriv colmeta, TdsParserS
colmeta.tdsType == TdsEnums.SQLBIGVARCHAR ||
colmeta.tdsType == TdsEnums.SQLBIGVARBINARY ||
colmeta.tdsType == TdsEnums.SQLNVARCHAR ||
+ colmeta.tdsType == TdsEnums.SQLJSON ||
// Large UDTs is WinFS-only
colmeta.tdsType == TdsEnums.SQLUDT,
"GetDataLength:Invalid streaming datatype");
@@ -10570,7 +10573,7 @@ internal Task TdsExecuteRPC(SqlCommand cmd, IList<_SqlRPC> rpcArray, int timeout
}
else if (mt.IsPlp)
{
- if (mt.SqlDbType != SqlDbType.Xml)
+ if (mt.SqlDbType != SqlDbType.Xml && mt.SqlDbType != SqlDbTypeExtensions.Json)
WriteShort(TdsEnums.SQL_USHORTVARMAXLEN, stateObj);
}
else if ((!mt.IsVarTime) && (mt.SqlDbType != SqlDbType.Date))
@@ -10611,53 +10614,56 @@ internal Task TdsExecuteRPC(SqlCommand cmd, IList<_SqlRPC> rpcArray, int timeout
// write out collation or xml metadata
- if (_is2005 && (mt.SqlDbType == SqlDbType.Xml))
+ if ((mt.SqlDbType == SqlDbType.Xml || mt.SqlDbType == SqlDbTypeExtensions.Json))
{
- if (!string.IsNullOrEmpty(param.XmlSchemaCollectionDatabase) ||
- !string.IsNullOrEmpty(param.XmlSchemaCollectionOwningSchema) ||
- !string.IsNullOrEmpty(param.XmlSchemaCollectionName))
+ if (mt.SqlDbType == SqlDbType.Xml)
{
- stateObj.WriteByte(1); //Schema present flag
-
- if (!string.IsNullOrEmpty(param.XmlSchemaCollectionDatabase))
+ if (!string.IsNullOrEmpty(param.XmlSchemaCollectionDatabase) ||
+ !string.IsNullOrEmpty(param.XmlSchemaCollectionOwningSchema) ||
+ !string.IsNullOrEmpty(param.XmlSchemaCollectionName))
{
- tempLen = (param.XmlSchemaCollectionDatabase).Length;
- stateObj.WriteByte((byte)(tempLen));
- WriteString(param.XmlSchemaCollectionDatabase, tempLen, 0, stateObj);
- }
- else
- {
- stateObj.WriteByte(0); // No dbname
- }
+ stateObj.WriteByte(1); //Schema present flag
+
+ if (!string.IsNullOrEmpty(param.XmlSchemaCollectionDatabase))
+ {
+ tempLen = (param.XmlSchemaCollectionDatabase).Length;
+ stateObj.WriteByte((byte)(tempLen));
+ WriteString(param.XmlSchemaCollectionDatabase, tempLen, 0, stateObj);
+ }
+ else
+ {
+ stateObj.WriteByte(0); // No dbname
+ }
+
+ if (!string.IsNullOrEmpty(param.XmlSchemaCollectionOwningSchema))
+ {
+ tempLen = (param.XmlSchemaCollectionOwningSchema).Length;
+ stateObj.WriteByte((byte)(tempLen));
+ WriteString(param.XmlSchemaCollectionOwningSchema, tempLen, 0, stateObj);
+ }
+ else
+ {
+ stateObj.WriteByte(0); // no xml schema name
+ }
+ if (!string.IsNullOrEmpty(param.XmlSchemaCollectionName))
+ {
+ tempLen = (param.XmlSchemaCollectionName).Length;
+ WriteShort((short)(tempLen), stateObj);
+ WriteString(param.XmlSchemaCollectionName, tempLen, 0, stateObj);
+ }
+ else
+ {
+ WriteShort(0, stateObj); // No xml schema collection name
+ }
- if (!string.IsNullOrEmpty(param.XmlSchemaCollectionOwningSchema))
- {
- tempLen = (param.XmlSchemaCollectionOwningSchema).Length;
- stateObj.WriteByte((byte)(tempLen));
- WriteString(param.XmlSchemaCollectionOwningSchema, tempLen, 0, stateObj);
- }
- else
- {
- stateObj.WriteByte(0); // no xml schema name
- }
- if (!string.IsNullOrEmpty(param.XmlSchemaCollectionName))
- {
- tempLen = (param.XmlSchemaCollectionName).Length;
- WriteShort((short)(tempLen), stateObj);
- WriteString(param.XmlSchemaCollectionName, tempLen, 0, stateObj);
}
else
{
- WriteShort(0, stateObj); // No xml schema collection name
+ stateObj.WriteByte(0); // No schema
}
-
- }
- else
- {
- stateObj.WriteByte(0); // No schema
}
}
- else if (_is2000 && mt.IsCharType)
+ else if (mt.IsCharType && mt.SqlDbType != SqlDbTypeExtensions.Json)
{
// if it is not supplied, simply write out our default collation, otherwise, write out the one attached to the parameter
SqlCollation outCollation = (param.Collation != null) ? param.Collation : _defaultCollation;
@@ -12432,10 +12438,18 @@ private Task WriteUnterminatedSqlValue(object value, MetaType type, int actualLe
case TdsEnums.SQLNVARCHAR:
case TdsEnums.SQLNTEXT:
case TdsEnums.SQLXMLTYPE:
+ case TdsEnums.SQLJSON:
if (type.IsPlp)
{
- if (IsBOMNeeded(type, value))
+ if (type.NullableType == TdsEnums.SQLJSON)
+ {
+ // TODO : Performance and BOM check. Saurabh
+ byte[] jsonAsBytes = Encoding.UTF8.GetBytes(value.ToString());
+ WriteInt(jsonAsBytes.Length, stateObj);
+ return stateObj.WriteByteArray(jsonAsBytes, jsonAsBytes.Length, 0, canAccumulate: false);
+ }
+ else if (IsBOMNeeded(type, value))
{
WriteInt(actualLength + 2, stateObj); // chunk length
WriteShort(TdsEnums.XMLUNICODEBOM, stateObj);
@@ -13124,6 +13138,7 @@ private Task WriteUnterminatedValue(object value, MetaType type, byte scale, int
case TdsEnums.SQLNVARCHAR:
case TdsEnums.SQLNTEXT:
case TdsEnums.SQLXMLTYPE:
+ case TdsEnums.SQLJSON:
{
Debug.Assert(!isDataFeed || (value is TextDataFeed || value is XmlDataFeed), "Value must be a TextReader or XmlReader");
Debug.Assert(isDataFeed || (value is string || value is byte[]), "Value is a byte array or string");
@@ -13145,7 +13160,14 @@ private Task WriteUnterminatedValue(object value, MetaType type, byte scale, int
{
if (type.IsPlp)
{
- if (IsBOMNeeded(type, value))
+ if (type.NullableType == TdsEnums.SQLJSON)
+ {
+ // TODO : Performance and BOM check. Saurabh
+ byte[] jsonAsBytes = Encoding.UTF8.GetBytes((string)value);
+ WriteInt(jsonAsBytes.Length, stateObj);
+ return stateObj.WriteByteArray(jsonAsBytes, jsonAsBytes.Length, 0, canAccumulate: false);
+ }
+ else if (IsBOMNeeded(type, value))
{
WriteInt(actualLength + 2, stateObj); // chunk length
WriteShort(TdsEnums.XMLUNICODEBOM, stateObj);
@@ -13652,7 +13674,7 @@ internal void WriteParameterVarLen(MetaType type, int size, bool isNull, TdsPars
WriteInt(unchecked((int)TdsEnums.VARLONGNULL), stateObj);
}
}
- else if (type.NullableType == TdsEnums.SQLXMLTYPE || unknownLength)
+ else if (type.NullableType is TdsEnums.SQLXMLTYPE or TdsEnums.SQLJSON || unknownLength)
{
WriteUnsignedLong(TdsEnums.SQL_PLP_UNKNOWNLEN, stateObj);
}
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlEnums.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlEnums.cs
index 3fbd9b112a..fe7bfc7f9a 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlEnums.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlEnums.cs
@@ -226,6 +226,8 @@ internal static MetaType GetMetaTypeFromSqlDbType(SqlDbType target, bool isMulti
return MetaXml;
case SqlDbType.Udt:
return MetaUdt;
+ case SqlDbTypeExtensions.Json:
+ return s_MetaJson;
case SqlDbType.Structured:
if (isMultiValued)
{
@@ -862,6 +864,8 @@ internal static MetaType GetSqlDataType(int tdsType, uint userType, int length)
return s_metaDateTime2;
case TdsEnums.SQLDATETIMEOFFSET:
return MetaDateTimeOffset;
+ case TdsEnums.SQLJSON:
+ return s_MetaJson;
case TdsEnums.SQLVOID:
default:
@@ -968,6 +972,8 @@ internal static string GetStringFromXml(XmlReader xmlreader)
internal static readonly MetaType MetaDateTimeOffset = new(255, 7, -1, false, false, false, TdsEnums.SQLDATETIMEOFFSET, TdsEnums.SQLDATETIMEOFFSET, MetaTypeName.DATETIMEOFFSET, typeof(System.DateTimeOffset), typeof(System.DateTimeOffset), SqlDbType.DateTimeOffset, DbType.DateTimeOffset, 1);
+ internal static readonly MetaType s_MetaJson = new(255, 255, -1, false, true, true, TdsEnums.SQLJSON, TdsEnums.SQLJSON, MetaTypeName.JSON, typeof(string), typeof(string), SqlDbTypeExtensions.Json, DbType.String, 0);
+
public static TdsDateTime FromDateTime(DateTime dateTime, byte cb)
{
SqlDateTime sqlDateTime;
@@ -1054,6 +1060,7 @@ private static class MetaTypeName
public const string TIME = "time";
public const string DATETIME2 = "datetime2";
public const string DATETIMEOFFSET = "datetimeoffset";
+ public const string JSON = "json";
}
}
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlParameter.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlParameter.cs
index a7c7fa58e1..65cd5d1e9b 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlParameter.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlParameter.cs
@@ -1563,6 +1563,7 @@ internal int GetActualSize()
case SqlDbType.NVarChar:
case SqlDbType.NText:
case SqlDbType.Xml:
+ case SqlDbTypeExtensions.Json:
{
coercedSize = ((!HasFlag(SqlParameterFlags.IsNull)) && (!HasFlag(SqlParameterFlags.CoercedValueIsDataFeed))) ? StringSize(val, HasFlag(SqlParameterFlags.CoercedValueIsSqlType)) : 0;
_actualSize = (ShouldSerializeSize() ? Size : 0);
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsEnums.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsEnums.cs
index f8b320be1a..058bf51dc5 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsEnums.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsEnums.cs
@@ -490,6 +490,8 @@ public enum ActiveDirectoryWorkflow : byte
public const int SQLDATETIME2 = 0x2a;
public const int SQLDATETIMEOFFSET = 0x2b;
+ public const int SQLJSON = 0xF4;
+
public const int DEFAULT_VARTIME_SCALE = 7;
//Partially length prefixed datatypes constants. These apply to XMLTYPE, BIGVARCHRTYPE,