From 41d0ef1814f6a5f4a7d0ca7b8e6bdeaf082e91ea Mon Sep 17 00:00:00 2001 From: AlexFsmn Date: Tue, 25 Sep 2018 23:24:39 +0200 Subject: [PATCH] Fixed correct value types when saving columns to a json file (#691) --- .../DataStorage/SaveAsJsonFileStreamWriter.cs | 12 +++- .../SaveAsJsonFileStreamWriterTests.cs | 55 +++++++++++++++++++ .../Utility/TestDbColumn.cs | 38 +++++++++++++ 3 files changed, 104 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/DataStorage/SaveAsJsonFileStreamWriter.cs b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/DataStorage/SaveAsJsonFileStreamWriter.cs index e13f42db..e232b1b6 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/DataStorage/SaveAsJsonFileStreamWriter.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/DataStorage/SaveAsJsonFileStreamWriter.cs @@ -70,7 +70,17 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage } else { - jsonWriter.WriteValue(row[i].DisplayValue); + // Try converting to column type + try + { + var value = Convert.ChangeType(row[i].DisplayValue, columns[i].DataType); + jsonWriter.WriteValue(value); + } + // Default column type as string + catch + { + jsonWriter.WriteValue(row[i].DisplayValue); + } } } diff --git a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/QueryExecution/DataStorage/SaveAsJsonFileStreamWriterTests.cs b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/QueryExecution/DataStorage/SaveAsJsonFileStreamWriterTests.cs index 84ee1c41..a0b4cb16 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/QueryExecution/DataStorage/SaveAsJsonFileStreamWriterTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/QueryExecution/DataStorage/SaveAsJsonFileStreamWriterTests.cs @@ -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.Generic; using System.IO; using System.Text; @@ -142,5 +143,59 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage } } } + + [Fact] + public void WriteRowWithSpecialTypesSuccess() + { + + // Setup: + // ... Create a request params that has three different types of value + // ... Create a set of data to write + // ... Create storage for the output + SaveResultsAsJsonRequestParams saveParams = new SaveResultsAsJsonRequestParams(); + List data = new List + { + new DbCellValue {DisplayValue = "1", RawObject = 1}, + new DbCellValue {DisplayValue = "1.234", RawObject = 1.234}, + new DbCellValue {DisplayValue = "2017-07-08T00:00:00", RawObject = new DateTime(2017, 07, 08)}, + + }; + List columns = new List + { + new DbColumnWrapper(new TestDbColumn("numberCol", typeof(int))), + new DbColumnWrapper(new TestDbColumn("decimalCol", typeof(decimal))), + new DbColumnWrapper(new TestDbColumn("datetimeCol", typeof(DateTime))) + }; + byte[] output = new byte[8192]; + + // If: + // ... I write two rows + var jsonWriter = new SaveAsJsonFileStreamWriter(new MemoryStream(output), saveParams); + using (jsonWriter) + { + jsonWriter.WriteRow(data, columns); + jsonWriter.WriteRow(data, columns); + } + + // Then: + // ... Upon deserialization to an array of dictionaries + string outputString = Encoding.UTF8.GetString(output).TrimEnd('\0'); + Dictionary[] outputObject = + JsonConvert.DeserializeObject[]>(outputString); + + // ... There should be 2 items in the array, + // ... The item should have three fields, and three values, assigned appropriately + // ... The deserialized values should match the display value + Assert.Equal(2, outputObject.Length); + foreach (var item in outputObject) + { + Assert.Equal(3, item.Count); + for (int i = 0; i < columns.Count; i++) + { + Assert.True(item.ContainsKey(columns[i].ColumnName)); + Assert.Equal(data[i].RawObject == null ? null : data[i].DisplayValue, item[columns[i].ColumnName]); + } + } + } } } diff --git a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Utility/TestDbColumn.cs b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Utility/TestDbColumn.cs index 812a0ec9..17fde31c 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Utility/TestDbColumn.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Utility/TestDbColumn.cs @@ -79,6 +79,27 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Utility base.ColumnName = "col"; } + private string GetDbColString(Type colType) + { + if(colType == typeof(string)) + { + return "nvarchar"; + } + else if(colType == typeof(int)) + { + return "int"; + } + else if (colType == typeof(double) || colType == typeof(float) || colType == typeof(decimal)) + { + return "decimal"; + } + else if(colType == typeof(DateTime)) + { + return "datetime"; + } + return "nvarchar"; + } + /// /// Constructs a basic DbColumn that is an NVARCHAR(128) NULL /// @@ -93,5 +114,22 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Utility base.DataTypeName = "nvarchar"; base.ColumnOrdinal = columnOrdinal; } + + + /// + /// Constructs a DbColumn that is of input type + /// + /// Name of the column + /// Type of the column + public TestDbColumn(string columnName, Type colType, int? columnOrdinal = null) + { + base.IsLong = false; + base.ColumnName = columnName; + base.ColumnSize = 128; + base.AllowDBNull = true; + base.DataType = colType; + base.DataTypeName = GetDbColString(colType); + base.ColumnOrdinal = columnOrdinal; + } } }