edit/createRow Default Values (#266)

Returns strings for the default value of a column when a new row is created. The values that could come back:
* `null` when there isn't a default for the column
* a string when there is a default for the column
* a placeholder (currently <TBD>) when the column cannot be updated

* Renaming EditTableMetadata to reflect its SMO source

* Implementation of returning default values

* Unit test for default values

* Reworking column defaults using default constraints

* Adding unit test for new sql script unwrapper

* Disabling flaky test

* Fixing oddities in tests, removing personal tests

* Fixing broken unit test
This commit is contained in:
Benjamin Russell
2017-03-08 13:51:38 -08:00
committed by GitHub
parent 29d27c2341
commit 056a08cd1b
21 changed files with 286 additions and 90 deletions

View File

@@ -19,6 +19,12 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.Contracts
/// </summary>
public class EditCreateRowResult
{
/// <summary>
/// Each element corresponds to the default value for the column. If null, no default is
/// defined. Calculated columns will have placeholders provided here.
/// </summary>
public string[] DefaultValues { get; set; }
/// <summary>
/// The internal ID of the newly created row
/// </summary>

View File

@@ -18,11 +18,23 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
/// </summary>
public DbColumnWrapper DbColumn { get; set; }
/// <summary>
/// If set, this is a string representation of the default value. If set to null, then the
/// column does not have a default value.
/// </summary>
public string DefaultValue { get; set; }
/// <summary>
/// Escaped identifier for the name of the column
/// </summary>
public string EscapedName { get; set; }
/// <summary>
/// Whether or not the column is calculated on the server side. This could be a computed
/// column or a identity column.
/// </summary>
public bool IsCalculated { get; set; }
/// <summary>
/// Whether or not the column is used in a key to uniquely identify a row
/// </summary>

View File

@@ -115,15 +115,7 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
internal Task HandleCreateRowRequest(EditCreateRowParams createParams,
RequestContext<EditCreateRowResult> requestContext)
{
return HandleSessionRequest(createParams, requestContext, session =>
{
// Create the row and get the ID of the new row
long newRowId = session.CreateRow();
return new EditCreateRowResult
{
NewRowId = newRowId
};
});
return HandleSessionRequest(createParams, requestContext, s => s.CreateRow());
}
internal Task HandleDeleteRowRequest(EditDeleteRowParams deleteParams,

View File

@@ -5,6 +5,7 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data.Common;
using System.IO;
using System.Linq;
@@ -96,7 +97,7 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
/// </summary>
/// <exception cref="InvalidOperationException">If inserting into cache fails</exception>
/// <returns>The internal ID of the newly created row</returns>
public long CreateRow()
public EditCreateRowResult CreateRow()
{
// Create a new row ID (atomically, since this could be accesses concurrently)
long newRowId = NextRowId++;
@@ -110,7 +111,33 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
throw new InvalidOperationException(SR.EditDataFailedAddRow);
}
return newRowId;
// Set the default values of the row if we know them
string[] defaultValues = new string[objectMetadata.Columns.Count];
for(int i = 0; i < objectMetadata.Columns.Count; i++)
{
EditColumnWrapper col = objectMetadata.Columns[i];
// If the column is calculated, return the calculated placeholder as the display value
if (col.IsCalculated)
{
defaultValues[i] = SR.EditDataComputedColumnPlaceholder;
}
else
{
if (col.DefaultValue != null)
{
newRow.SetCell(i, col.DefaultValue);
}
defaultValues[i] = col.DefaultValue;
}
}
EditCreateRowResult output = new EditCreateRowResult
{
NewRowId = newRowId,
DefaultValues = defaultValues
};
return output;
}
/// <summary>

View File

@@ -16,7 +16,7 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
/// <summary>
/// All columns in the table that's being edited
/// </summary>
IEnumerable<EditColumnWrapper> Columns { get; }
IReadOnlyList<EditColumnWrapper> Columns { get; }
/// <summary>
/// The escaped name of the table that's being edited
@@ -31,6 +31,6 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
/// <summary>
/// Columns that can be used to uniquely identify the a row
/// </summary>
IEnumerable<EditColumnWrapper> KeyColumns { get; }
IReadOnlyList<EditColumnWrapper> KeyColumns { get; }
}
}

View File

@@ -62,7 +62,7 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
throw new ArgumentOutOfRangeException(nameof(objectName), SR.EditDataObjectMetadataNotFound);
}
return new EditTableMetadata(columns, result);
return new SmoEditTableMetadata(columns, result);
}
}
}

View File

@@ -16,7 +16,7 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
/// <summary>
/// Provides metadata about the table or view being edited
/// </summary>
public class EditTableMetadata : IEditTableMetadata
public class SmoEditTableMetadata : IEditTableMetadata
{
private readonly List<EditColumnWrapper> columns;
private readonly List<EditColumnWrapper> keyColumns;
@@ -26,7 +26,7 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
/// </summary>
/// <param name="dbColumns">DB columns from the ResultSet</param>
/// <param name="smoObject">SMO metadata object for the table/view being edited</param>
public EditTableMetadata(IList<DbColumnWrapper> dbColumns, TableViewTableTypeBase smoObject)
public SmoEditTableMetadata(IList<DbColumnWrapper> dbColumns, TableViewTableTypeBase smoObject)
{
Validate.IsNotNull(nameof(dbColumns), dbColumns);
Validate.IsNotNull(nameof(smoObject), smoObject);
@@ -46,15 +46,24 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
// identify a row in the table
bool isTrustworthyForUniqueness = dbColumn.IsUpdatable || smoColumn.Identity;
// The default value may be escaped
string defaultValue = smoColumn.DefaultConstraint == null
? null
: SqlScriptFormatter.UnwrapLiteral(smoColumn.DefaultConstraint.Text);
EditColumnWrapper column = new EditColumnWrapper
{
DbColumn = dbColumn,
Ordinal = i,
DefaultValue = defaultValue,
EscapedName = SqlScriptFormatter.FormatIdentifier(dbColumn.ColumnName),
IsTrustworthyForUniqueness = isTrustworthyForUniqueness,
// A key column is determined by whether it is in the primary key and trustworthy
IsKey = smoColumn.InPrimaryKey && isTrustworthyForUniqueness
IsKey = smoColumn.InPrimaryKey && isTrustworthyForUniqueness,
// A column is calculated if it is identity, computed, or otherwise not updatable
IsCalculated = smoColumn.Identity || smoColumn.Computed || !dbColumn.IsUpdatable
};
columns.Add(column);
}
@@ -80,7 +89,7 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
/// <summary>
/// Read-only list of columns in the object being edited
/// </summary>
public IEnumerable<EditColumnWrapper> Columns => columns.AsReadOnly();
public IReadOnlyList<EditColumnWrapper> Columns => columns.AsReadOnly();
/// <summary>
/// Full escaped multipart identifier for the object being edited
@@ -95,6 +104,6 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
/// <summary>
/// Read-only list of columns that are used to uniquely identify a row
/// </summary>
public IEnumerable<EditColumnWrapper> KeyColumns => keyColumns.AsReadOnly();
public IReadOnlyList<EditColumnWrapper> KeyColumns => keyColumns.AsReadOnly();
}
}