Skip to content

Commit

Permalink
Add serialization service support (#840)
Browse files Browse the repository at this point in the history
Added a method that handles serialization requests
Support splitting save over multiple requests to reduce overall message size
Added unit tests
String changes used a new version of the string tool for generation.
Will publish PR separately for the changes to build & localization
so this can run on Mac without .Net Core 1.0
  • Loading branch information
kevcunnane committed Aug 6, 2019
1 parent 92bb281 commit 7ef82fe
Show file tree
Hide file tree
Showing 18 changed files with 7,676 additions and 16,821 deletions.
3,264 changes: 1,644 additions & 1,620 deletions src/Microsoft.SqlTools.ServiceLayer/Localization/sr.cs

Large diffs are not rendered by default.

1,932 changes: 462 additions & 1,470 deletions src/Microsoft.SqlTools.ServiceLayer/Localization/sr.de.resx

Large diffs are not rendered by default.

1,930 changes: 461 additions & 1,469 deletions src/Microsoft.SqlTools.ServiceLayer/Localization/sr.es.resx

Large diffs are not rendered by default.

1,930 changes: 461 additions & 1,469 deletions src/Microsoft.SqlTools.ServiceLayer/Localization/sr.fr.resx

Large diffs are not rendered by default.

1,930 changes: 461 additions & 1,469 deletions src/Microsoft.SqlTools.ServiceLayer/Localization/sr.it.resx

Large diffs are not rendered by default.

1,932 changes: 462 additions & 1,470 deletions src/Microsoft.SqlTools.ServiceLayer/Localization/sr.ja.resx

Large diffs are not rendered by default.

1,932 changes: 462 additions & 1,470 deletions src/Microsoft.SqlTools.ServiceLayer/Localization/sr.ko.resx

Large diffs are not rendered by default.

1,932 changes: 462 additions & 1,470 deletions src/Microsoft.SqlTools.ServiceLayer/Localization/sr.pt-BR.resx

Large diffs are not rendered by default.

842 changes: 429 additions & 413 deletions src/Microsoft.SqlTools.ServiceLayer/Localization/sr.resx

Large diffs are not rendered by default.

1,906 changes: 455 additions & 1,451 deletions src/Microsoft.SqlTools.ServiceLayer/Localization/sr.ru.resx

Large diffs are not rendered by default.

9 changes: 8 additions & 1 deletion src/Microsoft.SqlTools.ServiceLayer/Localization/sr.strings
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,13 @@ QueryServiceResultSetNoColumnSchema = Could not retrieve column schema for resul

QueryServiceExecutionPlanNotFound = Could not retrieve an execution plan from the result set

############################################################################
# Serialization Service

SerializationServiceUnsupportedFormat (string formatName) = Unsupported Save Format: {0}
SerializationServiceRequestInProgress (string filePath) = A request for file {0} is already in progress
SerializationServiceRequestNotFound (string filePath) = Cannot serialize more data as no request for file {0} could be found

############################################################################
# Language Service

Expand Down Expand Up @@ -798,4 +805,4 @@ ExtractInvalidVersion = Invalid version '{0}' passed. Version must be in the for
PublishChangesTaskName = Apply schema compare changes
SchemaCompareExcludeIncludeNodeNotFound = Failed to find the specified change in the model
OpenScmpConnectionBasedModelParsingError = Error encountered while trying to parse connection information for endpoint '{0}' with error message '{1}'
SchemaCompareSessionNotFound = Could not find the schema compare session to cancel
SchemaCompareSessionNotFound = Could not find the schema compare session to cancel
18 changes: 18 additions & 0 deletions src/Microsoft.SqlTools.ServiceLayer/Localization/sr.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -2006,6 +2006,24 @@
<target state="new">Could not find the schema compare session to cancel</target>
<note></note>
</trans-unit>
<trans-unit id="SerializationServiceUnsupportedFormat">
<source>Unsupported Save Format: {0}</source>
<target state="new">Unsupported Save Format: {0}</target>
<note>.
Parameters: 0 - formatName (string) </note>
</trans-unit>
<trans-unit id="SerializationServiceRequestInProgress">
<source>A request for file {0} is already in progress</source>
<target state="new">A request for file {0} is already in progress</target>
<note>.
Parameters: 0 - filePath (string) </note>
</trans-unit>
<trans-unit id="SerializationServiceRequestNotFound">
<source>Cannot serialize more data as no request for file {0} could be found</source>
<target state="new">Cannot serialize more data as no request for file {0} could be found</target>
<note>.
Parameters: 0 - filePath (string) </note>
</trans-unit>
</body>
</file>
</xliff>
1,930 changes: 461 additions & 1,469 deletions src/Microsoft.SqlTools.ServiceLayer/Localization/sr.zh-hans.resx

Large diffs are not rendered by default.

1,934 changes: 463 additions & 1,471 deletions src/Microsoft.SqlTools.ServiceLayer/Localization/sr.zh-hant.resx

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
Expand Down Expand Up @@ -93,104 +94,8 @@ public DbColumnWrapper(DbColumn column)
DataType = column.DataType;
DataTypeName = column.DataTypeName.ToLowerInvariant();

// Determine the SqlDbType
SqlDbType type;
if (Enum.TryParse(DataTypeName, true, out type))
{
SqlDbType = type;
}
else
{
switch (DataTypeName)
{
case "numeric":
SqlDbType = SqlDbType.Decimal;
break;
case "sql_variant":
SqlDbType = SqlDbType.Variant;
break;
case "timestamp":
SqlDbType = SqlDbType.VarBinary;
break;
case "sysname":
SqlDbType = SqlDbType.NVarChar;
break;
default:
SqlDbType = DataTypeName.EndsWith(".sys.hierarchyid") ? SqlDbType.NVarChar : SqlDbType.Udt;
break;
}
}

// We want the display name for the column to always exist
ColumnName = string.IsNullOrEmpty(column.ColumnName)
? SR.QueryServiceColumnNull
: column.ColumnName;

switch (DataTypeName)
{
case "varchar":
case "nvarchar":
IsChars = true;

Debug.Assert(ColumnSize.HasValue);
if (ColumnSize.Value == int.MaxValue)
{
//For Yukon, special case nvarchar(max) with column name == "Microsoft SQL Server 2005 XML Showplan" -
//assume it is an XML showplan.
//Please note this field must be in sync with a similar field defined in QESQLBatch.cs.
//This is not the best fix that we could do but we are trying to minimize code impact
//at this point. Post Yukon we should review this code again and avoid
//hard-coding special column name in multiple places.
const string yukonXmlShowPlanColumn = "Microsoft SQL Server 2005 XML Showplan";
if (column.ColumnName == yukonXmlShowPlanColumn)
{
// Indicate that this is xml to apply the right size limit
// Note we leave chars type as well to use the right retrieval mechanism.
IsXml = true;
}
IsLong = true;
}
break;
case "text":
case "ntext":
IsChars = true;
IsLong = true;
break;
case "xml":
IsXml = true;
IsLong = true;
break;
case "binary":
case "image":
IsBytes = true;
IsLong = true;
break;
case "varbinary":
case "rowversion":
IsBytes = true;

Debug.Assert(ColumnSize.HasValue);
if (ColumnSize.Value == int.MaxValue)
{
IsLong = true;
}
break;
case "sql_variant":
IsSqlVariant = true;
break;
default:
if (!AllServerDataTypes.Contains(DataTypeName))
{
// treat all UDT's as long/bytes data types to prevent the CLR from attempting
// to load the UDT assembly into our process to call ToString() on the object.

IsUdt = true;
IsBytes = true;
IsLong = true;
}
break;
}

DetermineSqlDbType();
AddNameAndDataFields(column.ColumnName);

if (IsUdt)
{
Expand All @@ -215,6 +120,19 @@ public DbColumnWrapper(DbColumn column)
}
}

public DbColumnWrapper(ColumnInfo columnInfo)
{
DataTypeName = columnInfo.DataTypeName.ToLowerInvariant();
DetermineSqlDbType();
DataType = TypeConvertor.ToNetType(this.SqlDbType);
if (DataType == typeof(String))
{
this.ColumnSize = int.MaxValue;
}
AddNameAndDataFields(columnInfo.Name);
}


/// <summary>
/// Default constructor, used for deserializing JSON RPC only
/// </summary>
Expand Down Expand Up @@ -299,5 +217,176 @@ public DbColumnWrapper()

#endregion


private void DetermineSqlDbType()
{
// Determine the SqlDbType
SqlDbType type;
if (Enum.TryParse(DataTypeName, true, out type))
{
SqlDbType = type;
}
else
{
switch (DataTypeName)
{
case "numeric":
SqlDbType = SqlDbType.Decimal;
break;
case "sql_variant":
SqlDbType = SqlDbType.Variant;
break;
case "timestamp":
SqlDbType = SqlDbType.VarBinary;
break;
case "sysname":
SqlDbType = SqlDbType.NVarChar;
break;
default:
SqlDbType = DataTypeName.EndsWith(".sys.hierarchyid") ? SqlDbType.NVarChar : SqlDbType.Udt;
break;
}
}
}

private void AddNameAndDataFields(string columnName)
{
// We want the display name for the column to always exist
ColumnName = string.IsNullOrEmpty(columnName)
? SR.QueryServiceColumnNull
: columnName;

switch (DataTypeName)
{
case "varchar":
case "nvarchar":
IsChars = true;

Debug.Assert(ColumnSize.HasValue);
if (ColumnSize.Value == int.MaxValue)
{
//For Yukon, special case nvarchar(max) with column name == "Microsoft SQL Server 2005 XML Showplan" -
//assume it is an XML showplan.
//Please note this field must be in sync with a similar field defined in QESQLBatch.cs.
//This is not the best fix that we could do but we are trying to minimize code impact
//at this point. Post Yukon we should review this code again and avoid
//hard-coding special column name in multiple places.
const string yukonXmlShowPlanColumn = "Microsoft SQL Server 2005 XML Showplan";
if (columnName == yukonXmlShowPlanColumn)
{
// Indicate that this is xml to apply the right size limit
// Note we leave chars type as well to use the right retrieval mechanism.
IsXml = true;
}
IsLong = true;
}
break;
case "text":
case "ntext":
IsChars = true;
IsLong = true;
break;
case "xml":
IsXml = true;
IsLong = true;
break;
case "binary":
case "image":
IsBytes = true;
IsLong = true;
break;
case "varbinary":
case "rowversion":
IsBytes = true;

Debug.Assert(ColumnSize.HasValue);
if (ColumnSize.Value == int.MaxValue)
{
IsLong = true;
}
break;
case "sql_variant":
IsSqlVariant = true;
break;
default:
if (!AllServerDataTypes.Contains(DataTypeName))
{
// treat all UDT's as long/bytes data types to prevent the CLR from attempting
// to load the UDT assembly into our process to call ToString() on the object.

IsUdt = true;
IsBytes = true;
IsLong = true;
}
break;
}
}
}



/// <summary>
/// Convert a base data type to another base data type
/// </summary>
public sealed class TypeConvertor
{
private static Dictionary<SqlDbType,Type> _typeMap = new Dictionary<SqlDbType,Type>();

static TypeConvertor()
{
_typeMap[SqlDbType.BigInt] = typeof(Int64);
_typeMap[SqlDbType.Binary] = typeof(Byte);
_typeMap[SqlDbType.Bit] = typeof(Boolean);
_typeMap[SqlDbType.Char] = typeof(String);
_typeMap[SqlDbType.DateTime] = typeof(DateTime);
_typeMap[SqlDbType.Decimal] = typeof(Decimal);
_typeMap[SqlDbType.Float] = typeof(Double);
_typeMap[SqlDbType.Image] = typeof(Byte[]);
_typeMap[SqlDbType.Int] = typeof(Int32);
_typeMap[SqlDbType.Money] = typeof(Decimal);
_typeMap[SqlDbType.NChar] = typeof(String);
_typeMap[SqlDbType.NChar] = typeof(String);
_typeMap[SqlDbType.NChar] = typeof(String);
_typeMap[SqlDbType.NText] = typeof(String);
_typeMap[SqlDbType.NVarChar] = typeof(String);
_typeMap[SqlDbType.Real] = typeof(Single);
_typeMap[SqlDbType.UniqueIdentifier] = typeof(Guid);
_typeMap[SqlDbType.SmallDateTime] = typeof(DateTime);
_typeMap[SqlDbType.SmallInt] = typeof(Int16);
_typeMap[SqlDbType.SmallMoney] = typeof(Decimal);
_typeMap[SqlDbType.Text] = typeof(String);
_typeMap[SqlDbType.Timestamp] = typeof(Byte[]);
_typeMap[SqlDbType.TinyInt] = typeof(Byte);
_typeMap[SqlDbType.VarBinary] = typeof(Byte[]);
_typeMap[SqlDbType.VarChar] = typeof(String);
_typeMap[SqlDbType.Variant] = typeof(Object);
// Note: treating as string
_typeMap[SqlDbType.Xml] = typeof(String);
_typeMap[SqlDbType.TinyInt] = typeof(Byte);
_typeMap[SqlDbType.TinyInt] = typeof(Byte);
_typeMap[SqlDbType.TinyInt] = typeof(Byte);
_typeMap[SqlDbType.TinyInt] = typeof(Byte);
}

private TypeConvertor()
{

}


/// <summary>
/// Convert TSQL type to .Net data type
/// </summary>
/// <param name="sqlDbType"></param>
/// <returns></returns>
public static Type ToNetType(SqlDbType sqlDbType)
{
Type netType;
if (!_typeMap.TryGetValue(sqlDbType, out netType))
{
netType = typeof(String);
}
return netType;
}
}
}
Loading

0 comments on commit 7ef82fe

Please sign in to comment.