Edit Data: Better Formatting Errors (#562)

* Refactoring sql script formatting helpers into To and From helpers

* Updates to make error messages for formatting errors more useful

* Fixing dumb breaks in unit tests

* Addressing comments from PR

* Updates to the SR files...
This commit is contained in:
Benjamin Russell
2017-12-05 17:00:13 -08:00
committed by GitHub
parent e7b76a6dec
commit 64133d929e
37 changed files with 7869 additions and 17711 deletions

View File

@@ -8,6 +8,7 @@ using System.Globalization;
using System.Text.RegularExpressions;
using Microsoft.SqlTools.ServiceLayer.EditData.Contracts;
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts;
using Microsoft.SqlTools.ServiceLayer.Utility.SqlScriptFormatters;
using Microsoft.SqlTools.Utility;
namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
@@ -34,50 +35,60 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
Validate.IsNotNull(nameof(valueAsString), valueAsString);
// Store the state that won't be changed
Column = column;
Type columnType = column.DataType;
try
{
Column = column;
Type columnType = column.DataType;
// Check for null
if (valueAsString == NullString)
{
ProcessNullValue();
// Check for null
if (valueAsString == NullString)
{
ProcessNullValue();
}
else if (columnType == typeof(byte[]))
{
// Binary columns need special attention
ProcessBinaryCell(valueAsString);
}
else if (columnType == typeof(string))
{
ProcessTextCell(valueAsString);
}
else if (columnType == typeof(Guid))
{
Value = Guid.Parse(valueAsString);
ValueAsString = Value.ToString();
}
else if (columnType == typeof(TimeSpan))
{
ProcessTimespanColumn(valueAsString);
}
else if (columnType == typeof(DateTimeOffset))
{
Value = DateTimeOffset.Parse(valueAsString, CultureInfo.CurrentCulture);
ValueAsString = Value.ToString();
}
else if (columnType == typeof(bool))
{
ProcessBooleanCell(valueAsString);
}
// @TODO: Microsoft.SqlServer.Types.SqlHierarchyId
else
{
// Attempt to go straight to the destination type, if we know what it is, otherwise
// leave it as a string
Value = columnType != null
? Convert.ChangeType(valueAsString, columnType, CultureInfo.CurrentCulture)
: valueAsString;
ValueAsString = Value.ToString();
}
}
else if (columnType == typeof(byte[]))
catch (FormatException fe)
{
// Binary columns need special attention
ProcessBinaryCell(valueAsString);
}
else if (columnType == typeof(string))
{
ProcessTextCell(valueAsString);
}
else if (columnType == typeof(Guid))
{
Value = Guid.Parse(valueAsString);
ValueAsString = Value.ToString();
}
else if (columnType == typeof(TimeSpan))
{
ProcessTimespanColumn(valueAsString);
}
else if (columnType == typeof(DateTimeOffset))
{
Value = DateTimeOffset.Parse(valueAsString, CultureInfo.CurrentCulture);
ValueAsString = Value.ToString();
}
else if (columnType == typeof(bool))
{
ProcessBooleanCell(valueAsString);
}
// @TODO: Microsoft.SqlServer.Types.SqlHierarchyId
else
{
// Attempt to go straight to the destination type, if we know what it is, otherwise
// leave it as a string
Value = columnType != null
? Convert.ChangeType(valueAsString, columnType, CultureInfo.CurrentCulture)
: valueAsString;
ValueAsString = Value.ToString();
// Pretty up the exception so the user can learn a bit from it
// NOTE: Other formatting errors raised by helpers are InvalidOperationException to
// avoid being prettied here
throw new FormatException(SR.EditDataInvalidFormat(column.ColumnName, ToSqlScript.FormatColumnType(column)), fe);
}
}
@@ -181,8 +192,7 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
}
else
{
// Invalid format
throw new FormatException(SR.EditDataInvalidFormatBinary);
throw new InvalidOperationException(SR.EditDataInvalidFormatBinary);
}
// Generate the hex string as the return value
@@ -205,8 +215,7 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
Value = false;
break;
default:
throw new ArgumentOutOfRangeException(nameof(valueAsString),
SR.EditDataInvalidFormatBoolean);
throw new InvalidOperationException(SR.EditDataInvalidFormatBoolean);
}
}
else
@@ -253,7 +262,7 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
{
string columnSizeString = $"({Column.ColumnSize.Value})";
string columnTypeString = Column.DataTypeName.ToUpperInvariant() + columnSizeString;
throw new FormatException(SR.EditDataValueTooLarge(valueAsString, columnTypeString));
throw new InvalidOperationException(SR.EditDataValueTooLarge(valueAsString, columnTypeString));
}
ValueAsString = valueAsString;

View File

@@ -14,7 +14,7 @@ using System.Threading.Tasks;
using Microsoft.SqlTools.ServiceLayer.EditData.Contracts;
using Microsoft.SqlTools.ServiceLayer.QueryExecution;
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts;
using Microsoft.SqlTools.ServiceLayer.Utility;
using Microsoft.SqlTools.ServiceLayer.Utility.SqlScriptFormatters;
using Microsoft.SqlTools.Utility;
namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
@@ -202,7 +202,7 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
// Add an out column if we're doing this for a command
if (forCommand)
{
outColumns.Add($"inserted.{SqlScriptFormatter.FormatIdentifier(column.ColumnName)}");
outColumns.Add($"inserted.{ToSqlScript.FormatIdentifier(column.ColumnName)}");
}
// Skip columns that cannot be updated
@@ -237,11 +237,11 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
else
{
// This script isn't for command use, add the value, formatted for insertion
inValues.Add(SqlScriptFormatter.FormatValue(cell.Value, column));
inValues.Add(ToSqlScript.FormatValue(cell.Value, column));
}
// Add the column to the in columns
inColumns.Add(SqlScriptFormatter.FormatIdentifier(column.ColumnName));
inColumns.Add(ToSqlScript.FormatIdentifier(column.ColumnName));
}
// Begin the script (ie, INSERT INTO blah)

View File

@@ -12,7 +12,7 @@ using System.Threading.Tasks;
using Microsoft.SqlTools.ServiceLayer.EditData.Contracts;
using Microsoft.SqlTools.ServiceLayer.QueryExecution;
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts;
using Microsoft.SqlTools.ServiceLayer.Utility;
using Microsoft.SqlTools.ServiceLayer.Utility.SqlScriptFormatters;
namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
{
@@ -27,6 +27,7 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
/// <summary>
/// Internal parameterless constructor, required for mocking
/// </summary>
// ReSharper disable once UnusedMember.Global
protected internal RowEditBase() { }
/// <summary>
@@ -204,7 +205,7 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
else
{
// Add the clause component with the formatted value
cellDataClause = $"= {SqlScriptFormatter.FormatValue(cellData, col.DbColumn)}";
cellDataClause = $"= {ToSqlScript.FormatValue(cellData, col.DbColumn)}";
}
}
}

View File

@@ -13,7 +13,7 @@ using System.Threading.Tasks;
using Microsoft.SqlTools.ServiceLayer.EditData.Contracts;
using Microsoft.SqlTools.ServiceLayer.QueryExecution;
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts;
using Microsoft.SqlTools.ServiceLayer.Utility;
using Microsoft.SqlTools.ServiceLayer.Utility.SqlScriptFormatters;
using Microsoft.SqlTools.Utility;
namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
@@ -81,7 +81,7 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
List<string> setComponents = new List<string>();
foreach (var updateElement in cellUpdates)
{
string formattedColumnName = SqlScriptFormatter.FormatIdentifier(updateElement.Value.Column.ColumnName);
string formattedColumnName = ToSqlScript.FormatIdentifier(updateElement.Value.Column.ColumnName);
string paramName = $"@Value{RowId}_{updateElement.Key}";
setComponents.Add($"{formattedColumnName} = {paramName}");
SqlParameter parameter = new SqlParameter(paramName, updateElement.Value.Column.SqlDbType)
@@ -94,7 +94,7 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
// Build the "OUTPUT" portion of the statement
var outColumns = from c in AssociatedResultSet.Columns
let formatted = SqlScriptFormatter.FormatIdentifier(c.ColumnName)
let formatted = ToSqlScript.FormatIdentifier(c.ColumnName)
select $"inserted.{formatted}";
string outColumnsJoined = string.Join(", ", outColumns);
@@ -148,8 +148,8 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
// Build the "SET" portion of the statement
var setComponents = cellUpdates.Values.Select(cellUpdate =>
{
string formattedColumnName = SqlScriptFormatter.FormatIdentifier(cellUpdate.Column.ColumnName);
string formattedValue = SqlScriptFormatter.FormatValue(cellUpdate.Value, cellUpdate.Column);
string formattedColumnName = ToSqlScript.FormatIdentifier(cellUpdate.Column.ColumnName);
string formattedValue = ToSqlScript.FormatValue(cellUpdate.Value, cellUpdate.Column);
return $"{formattedColumnName} = {formattedValue}";
});
string setClause = string.Join(", ", setComponents);