//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts;
using Microsoft.SqlTools.Utility;
using Microsoft.SqlTools.ServiceLayer.Utility;
namespace Microsoft.SqlTools.ServiceLayer.EditData
{
///
/// Provides metadata about the table or view being edited
///
public class EditTableMetadata : IEditTableMetadata
{
private readonly List columns;
private readonly List keyColumns;
///
/// Constructor that extracts useful metadata from the provided metadata objects
///
/// DB columns from the ResultSet
/// SMO metadata object for the table/view being edited
public EditTableMetadata(IList dbColumns, TableViewTableTypeBase smoObject)
{
Validate.IsNotNull(nameof(dbColumns), dbColumns);
Validate.IsNotNull(nameof(smoObject), smoObject);
// Make sure that we have equal columns on both metadata providers
Debug.Assert(dbColumns.Count == smoObject.Columns.Count);
// Create the columns for edit usage
columns = new List();
for (int i = 0; i < dbColumns.Count; i++)
{
Column smoColumn = smoObject.Columns[i];
DbColumnWrapper dbColumn = dbColumns[i];
// A column is trustworthy for uniqueness if it can be updated or it has an identity
// property. If both of these are false (eg, timestamp) we can't trust it to uniquely
// identify a row in the table
bool isTrustworthyForUniqueness = dbColumn.IsUpdatable || smoColumn.Identity;
EditColumnWrapper column = new EditColumnWrapper
{
DbColumn = dbColumn,
Ordinal = i,
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
};
columns.Add(column);
}
// Determine what the key columns are
keyColumns = columns.Where(c => c.IsKey).ToList();
if (keyColumns.Count == 0)
{
// We didn't find any explicit key columns. Instead, we'll use all columns that are
// trustworthy for uniqueness (usually all the columns)
keyColumns = columns.Where(c => c.IsTrustworthyForUniqueness).ToList();
}
// If a table is memory optimized it is Hekaton. If it's a view, then it can't be Hekaton
Table smoTable = smoObject as Table;
IsMemoryOptimized = smoTable != null && smoTable.IsMemoryOptimized;
// Escape the parts of the name
string[] objectNameParts = {smoObject.Schema, smoObject.Name};
EscapedMultipartName = SqlScriptFormatter.FormatMultipartIdentifier(objectNameParts);
}
///
/// Read-only list of columns in the object being edited
///
public IEnumerable Columns => columns.AsReadOnly();
///
/// Full escaped multipart identifier for the object being edited
///
public string EscapedMultipartName { get; }
///
/// Whether or not the object being edited is memory optimized
///
public bool IsMemoryOptimized { get; }
///
/// Read-only list of columns that are used to uniquely identify a row
///
public IEnumerable KeyColumns => keyColumns.AsReadOnly();
}
}