mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-13 17:23:02 -05:00
Remove SELECT * from edit/initialize Query (#288)
* Major refactor of EditDataMetadata providers * EditMetadataFactory generates "basic" EditTableMetadata objects based entirely on SMO metadata * SmoEditTableMetadata no longer depends on SMO, making it unecessary to mock it * Renamed SmoEditTableMetadata to EditTableMetadata * EditTableMetadata can be extended with DbColumnWrappers * Moving logic for extending a EditColumnMetadata into that class * I *think* this will work for async execution of initialize tasks * Fixing unit tests for new Edit(Table|Column)Metadata classes * Async stuff that works! And passes unit tests * Adding unit tests Adding .idea to gitignore * Adding message to the EditSessionReadyEvent * Fixes from dev merge * Fixing unit tests that Rider didn't catch as failing May have been a bit heavy-handed with the async/await stuff * Couple changes as per PR comments
This commit is contained in:
8
.gitignore
vendored
8
.gitignore
vendored
@@ -58,6 +58,9 @@ cross/rootfs/
|
||||
[Bb]uild[Ll]og.*
|
||||
test*json
|
||||
|
||||
## Project Rider ##
|
||||
.idea/
|
||||
|
||||
#NUNIT
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
@@ -169,9 +172,6 @@ publish/
|
||||
*.nupkg
|
||||
**/packages/*
|
||||
|
||||
# NuGet package restore lockfiles
|
||||
project.lock.json
|
||||
|
||||
# Windows Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
@@ -243,8 +243,6 @@ $RECYCLE.BIN/
|
||||
|
||||
### Linux ###
|
||||
|
||||
*~
|
||||
|
||||
# KDE directory preferences
|
||||
.directory
|
||||
|
||||
|
||||
@@ -14,6 +14,12 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.Contracts
|
||||
/// </summary>
|
||||
public string OwnerUri { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Message to explain why a session failed. Should only be set when <see cref="Success"/>
|
||||
/// is <c>false</c>.
|
||||
/// </summary>
|
||||
public string Message { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not the session is ready
|
||||
/// </summary>
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System.Data;
|
||||
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts;
|
||||
using Microsoft.SqlTools.Utility;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.EditData
|
||||
{
|
||||
/// <summary>
|
||||
/// Small class that stores information needed by the edit data service to properly process
|
||||
/// edits into scripts.
|
||||
/// </summary>
|
||||
public class EditColumnMetadata
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructs a simple edit column metadata provider
|
||||
/// </summary>
|
||||
public EditColumnMetadata()
|
||||
{
|
||||
HasExtendedProperties = false;
|
||||
}
|
||||
|
||||
#region Basic Properties (properties provided by SMO)
|
||||
|
||||
/// <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 computed
|
||||
/// </summary>
|
||||
public bool IsComputed { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not the column is deterministically computed
|
||||
/// </summary>
|
||||
public bool IsDeterministic { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not the column is an identity column
|
||||
/// </summary>
|
||||
public bool IsIdentity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The ordinal ID of the column
|
||||
/// </summary>
|
||||
public int Ordinal { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Extended Properties (properties provided by SqlClient)
|
||||
|
||||
public DbColumnWrapper DbColumn { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not the column has extended properties
|
||||
/// </summary>
|
||||
public bool HasExtendedProperties { get; private 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; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not the column is used in a key to uniquely identify a row
|
||||
/// </summary>
|
||||
public bool? IsKey { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not the column can be trusted for uniqueness
|
||||
/// </summary>
|
||||
public bool? IsTrustworthyForUniqueness { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Extracts extended column properties from the database columns from SQL Client
|
||||
/// </summary>
|
||||
/// <param name="dbColumn">The column information provided by SQL Client</param>
|
||||
public void Extend(DbColumnWrapper dbColumn)
|
||||
{
|
||||
Validate.IsNotNull(nameof(dbColumn), dbColumn);
|
||||
|
||||
DbColumn = dbColumn;
|
||||
|
||||
// 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
|
||||
IsTrustworthyForUniqueness = dbColumn.IsUpdatable || dbColumn.IsIdentity.HasTrue();
|
||||
|
||||
// A key column is determined by whether it is a key
|
||||
IsKey = dbColumn.IsKey;
|
||||
|
||||
// A column is calculated if it is identity, computed, or otherwise not updatable
|
||||
IsCalculated = IsIdentity || IsComputed || !dbColumn.IsUpdatable;
|
||||
|
||||
// Mark the column as extended
|
||||
HasExtendedProperties = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.EditData
|
||||
{
|
||||
/// <summary>
|
||||
/// Small class that stores information needed by the edit data service to properly process
|
||||
/// edits into scripts.
|
||||
/// </summary>
|
||||
public class EditColumnWrapper
|
||||
{
|
||||
/// <summary>
|
||||
/// The DB column
|
||||
/// </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>
|
||||
public bool IsKey { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not the column can be trusted for uniqueness
|
||||
/// </summary>
|
||||
public bool IsTrustworthyForUniqueness { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The ordinal ID of the column
|
||||
/// </summary>
|
||||
public int Ordinal { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,6 @@ using Microsoft.SqlTools.ServiceLayer.EditData.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.Hosting;
|
||||
using Microsoft.SqlTools.ServiceLayer.QueryExecution;
|
||||
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts.ExecuteRequests;
|
||||
using Microsoft.SqlTools.ServiceLayer.Utility;
|
||||
using Microsoft.SqlTools.Utility;
|
||||
using ConnectionType = Microsoft.SqlTools.ServiceLayer.Connection.ConnectionType;
|
||||
|
||||
@@ -57,10 +56,6 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
||||
private readonly Lazy<ConcurrentDictionary<string, EditSession>> editSessions = new Lazy<ConcurrentDictionary<string, EditSession>>(
|
||||
() => new ConcurrentDictionary<string, EditSession>());
|
||||
|
||||
private readonly Lazy<ConcurrentDictionary<string, TaskCompletionSource<bool>>> initializeWaitHandles =
|
||||
new Lazy<ConcurrentDictionary<string, TaskCompletionSource<bool>>>(
|
||||
() => new ConcurrentDictionary<string, TaskCompletionSource<bool>>());
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
@@ -70,12 +65,6 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
||||
/// </summary>
|
||||
internal ConcurrentDictionary<string, EditSession> ActiveSessions => editSessions.Value;
|
||||
|
||||
/// <summary>
|
||||
/// Dictionary mapping OwnerURIs to wait handlers for initialize tasks. Pretty much only
|
||||
/// provided for unit test scenarios.
|
||||
/// </summary>
|
||||
internal ConcurrentDictionary<string, TaskCompletionSource<bool>> InitializeWaitHandles => initializeWaitHandles.Value;
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
@@ -159,63 +148,32 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
||||
internal async Task HandleInitializeRequest(EditInitializeParams initParams,
|
||||
RequestContext<EditInitializeResult> requestContext)
|
||||
{
|
||||
Func<Exception, Task> executionFailureHandler = (e) => SendSessionReadyEvent(requestContext, initParams.OwnerUri, false, e.Message);
|
||||
Func<Task> executionSuccessHandler = () => SendSessionReadyEvent(requestContext, initParams.OwnerUri, true, null);
|
||||
|
||||
EditSession.Connector connector = () => connectionService.GetOrOpenConnection(initParams.OwnerUri, ConnectionType.Edit);
|
||||
EditSession.QueryRunner queryRunner = q => SessionInitializeQueryRunner(initParams.OwnerUri, requestContext, q);
|
||||
|
||||
try
|
||||
{
|
||||
{
|
||||
// Make sure we have info to process this request
|
||||
Validate.IsNotNullOrWhitespaceString(nameof(initParams.OwnerUri), initParams.OwnerUri);
|
||||
Validate.IsNotNullOrWhitespaceString(nameof(initParams.ObjectName), initParams.ObjectName);
|
||||
Validate.IsNotNullOrWhitespaceString(nameof(initParams.ObjectType), initParams.ObjectType);
|
||||
|
||||
// Try to add a new wait handler to the
|
||||
if (!InitializeWaitHandles.TryAdd(initParams.OwnerUri, new TaskCompletionSource<bool>()))
|
||||
// Create a session and add it to the session list
|
||||
EditSession session = new EditSession(metadataFactory, initParams.ObjectName, initParams.ObjectType);
|
||||
if (!ActiveSessions.TryAdd(initParams.OwnerUri, session))
|
||||
{
|
||||
throw new InvalidOperationException(SR.EditDataInitializeInProgress);
|
||||
throw new InvalidOperationException(SR.EditDataSessionAlreadyExists);
|
||||
}
|
||||
|
||||
// Setup a callback for when the query has successfully created
|
||||
Func<Query, Task<bool>> queryCreateSuccessCallback = async query =>
|
||||
{
|
||||
await requestContext.SendResult(new EditInitializeResult());
|
||||
return true;
|
||||
};
|
||||
|
||||
// Setup a callback for when the query failed to be created
|
||||
Func<string, Task> queryCreateFailureCallback = async message =>
|
||||
{
|
||||
await requestContext.SendError(message);
|
||||
CompleteInitializeWaitHandler(initParams.OwnerUri, false);
|
||||
};
|
||||
|
||||
// Setup a callback for when the query completes execution successfully
|
||||
Query.QueryAsyncEventHandler queryCompleteSuccessCallback =
|
||||
q => QueryCompleteCallback(q, initParams, requestContext);
|
||||
|
||||
// Setup a callback for when the query completes execution with failure
|
||||
Query.QueryAsyncEventHandler queryCompleteFailureCallback = async query =>
|
||||
{
|
||||
EditSessionReadyParams readyParams = new EditSessionReadyParams
|
||||
{
|
||||
OwnerUri = initParams.OwnerUri,
|
||||
Success = false
|
||||
};
|
||||
await requestContext.SendEvent(EditSessionReadyEvent.Type, readyParams);
|
||||
CompleteInitializeWaitHandler(initParams.OwnerUri, false);
|
||||
};
|
||||
|
||||
// Put together a query for the results and execute it
|
||||
ExecuteStringParams executeParams = new ExecuteStringParams
|
||||
{
|
||||
Query = $"SELECT * FROM {SqlScriptFormatter.FormatMultipartIdentifier(initParams.ObjectName)}",
|
||||
OwnerUri = initParams.OwnerUri
|
||||
};
|
||||
await queryExecutionService.InterServiceExecuteQuery(executeParams, requestContext,
|
||||
queryCreateSuccessCallback, queryCreateFailureCallback,
|
||||
queryCompleteSuccessCallback, queryCompleteFailureCallback);
|
||||
// Initialize the session
|
||||
session.Initialize(connector, queryRunner, executionSuccessHandler, executionFailureHandler);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
await requestContext.SendError(e.Message);
|
||||
CompleteInitializeWaitHandler(initParams.OwnerUri, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -313,52 +271,64 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
||||
return editSession;
|
||||
}
|
||||
|
||||
private async Task QueryCompleteCallback(Query query, EditInitializeParams initParams,
|
||||
IEventSender requestContext)
|
||||
private async Task<EditSession.EditSessionQueryExecutionState> SessionInitializeQueryRunner(string ownerUri,
|
||||
IEventSender eventSender, string query)
|
||||
{
|
||||
EditSessionReadyParams readyParams = new EditSessionReadyParams
|
||||
// Open a task completion source, effectively creating a synchronous block
|
||||
TaskCompletionSource<EditSession.EditSessionQueryExecutionState> taskCompletion =
|
||||
new TaskCompletionSource<EditSession.EditSessionQueryExecutionState>();
|
||||
|
||||
// Setup callback for successful query creation
|
||||
// NOTE: We do not want to set the task completion source, since we will continue executing the query after
|
||||
Func<Query, Task<bool>> queryCreateSuccessCallback = q => Task.FromResult(true);
|
||||
|
||||
// Setup callback for failed query creation
|
||||
Func<string, Task> queryCreateFailureCallback = m =>
|
||||
{
|
||||
OwnerUri = initParams.OwnerUri
|
||||
taskCompletion.SetResult(new EditSession.EditSessionQueryExecutionState(null, m));
|
||||
return Task.FromResult(0);
|
||||
};
|
||||
|
||||
try
|
||||
// Setup callback for successful query execution
|
||||
Query.QueryAsyncEventHandler queryCompleteSuccessCallback = q =>
|
||||
{
|
||||
// Validate the query for a editSession
|
||||
ResultSet resultSet = EditSession.ValidateQueryForSession(query);
|
||||
taskCompletion.SetResult(new EditSession.EditSessionQueryExecutionState(q));
|
||||
return Task.FromResult(0);
|
||||
};
|
||||
|
||||
// Get a connection we'll use for SMO metadata lookup (and committing, later on)
|
||||
DbConnection conn = await connectionService.GetOrOpenConnection(initParams.OwnerUri, ConnectionType.Edit);
|
||||
var metadata = metadataFactory.GetObjectMetadata(conn, resultSet.Columns,
|
||||
initParams.ObjectName, initParams.ObjectType);
|
||||
|
||||
// Create the editSession and add it to the sessions list
|
||||
EditSession editSession = new EditSession(resultSet, metadata);
|
||||
if (!ActiveSessions.TryAdd(initParams.OwnerUri, editSession))
|
||||
{
|
||||
throw new InvalidOperationException("Failed to create edit editSession, editSession already exists.");
|
||||
}
|
||||
readyParams.Success = true;
|
||||
}
|
||||
catch (Exception)
|
||||
// Setup callback for failed query execution
|
||||
Query.QueryAsyncEventHandler queryCompleteFailureCallback = q =>
|
||||
{
|
||||
// Request that the query be disposed
|
||||
await queryExecutionService.InterServiceDisposeQuery(initParams.OwnerUri, null, null);
|
||||
readyParams.Success = false;
|
||||
}
|
||||
taskCompletion.SetResult(new EditSession.EditSessionQueryExecutionState(null));
|
||||
return Task.FromResult(0);
|
||||
};
|
||||
|
||||
// Send the edit session ready notification
|
||||
await requestContext.SendEvent(EditSessionReadyEvent.Type, readyParams);
|
||||
CompleteInitializeWaitHandler(initParams.OwnerUri, true);
|
||||
// Execute the query
|
||||
ExecuteStringParams executeParams = new ExecuteStringParams
|
||||
{
|
||||
Query = query,
|
||||
OwnerUri = ownerUri
|
||||
};
|
||||
await queryExecutionService.InterServiceExecuteQuery(executeParams, eventSender,
|
||||
queryCreateSuccessCallback, queryCreateFailureCallback,
|
||||
queryCompleteSuccessCallback, queryCompleteFailureCallback);
|
||||
|
||||
// Wait for the completion source to complete, this will wait until the query has
|
||||
// completed and sent all its events.
|
||||
return await taskCompletion.Task;
|
||||
}
|
||||
|
||||
private void CompleteInitializeWaitHandler(string ownerUri, bool result)
|
||||
private static Task SendSessionReadyEvent(IEventSender eventSender, string ownerUri, bool success,
|
||||
string message)
|
||||
{
|
||||
// If there isn't a wait handler, just ignore it
|
||||
TaskCompletionSource<bool> initializeWaiter;
|
||||
if (ownerUri != null && InitializeWaitHandles.TryRemove(ownerUri, out initializeWaiter))
|
||||
var sessionReadyParams = new EditSessionReadyParams
|
||||
{
|
||||
initializeWaiter.SetResult(result);
|
||||
}
|
||||
OwnerUri = ownerUri,
|
||||
Message = message,
|
||||
Success = success
|
||||
};
|
||||
|
||||
return eventSender.SendEvent(EditSessionReadyEvent.Type, sessionReadyParams);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -25,28 +25,37 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
||||
public class EditSession
|
||||
{
|
||||
|
||||
private readonly ResultSet associatedResultSet;
|
||||
private readonly IEditTableMetadata objectMetadata;
|
||||
private ResultSet associatedResultSet;
|
||||
|
||||
private readonly IEditMetadataFactory metadataFactory;
|
||||
private EditTableMetadata objectMetadata;
|
||||
private readonly string objectName;
|
||||
private readonly string objectType;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new edit session bound to the result set and metadat object provided
|
||||
/// </summary>
|
||||
/// <param name="resultSet">The result set of the table to be edited</param>
|
||||
/// <param name="objMetadata">Metadata provider for the table to be edited</param>
|
||||
public EditSession(ResultSet resultSet, IEditTableMetadata objMetadata)
|
||||
/// <param name="metaFactory">Factory for creating metadata</param>
|
||||
/// <param name="objName">The name of the object to edit</param>
|
||||
/// <param name="objType">The type of the object to edit</param>
|
||||
public EditSession(IEditMetadataFactory metaFactory, string objName, string objType)
|
||||
{
|
||||
Validate.IsNotNull(nameof(resultSet), resultSet);
|
||||
Validate.IsNotNull(nameof(objMetadata), objMetadata);
|
||||
Validate.IsNotNull(nameof(metaFactory), metaFactory);
|
||||
Validate.IsNotNullOrWhitespaceString(nameof(objName), objName);
|
||||
Validate.IsNotNullOrWhitespaceString(nameof(objType), objType);
|
||||
|
||||
// Setup the internal state
|
||||
associatedResultSet = resultSet;
|
||||
objectMetadata = objMetadata;
|
||||
NextRowId = associatedResultSet.RowCount;
|
||||
EditCache = new ConcurrentDictionary<long, RowEditBase>();
|
||||
metadataFactory = metaFactory;
|
||||
objectName = objName;
|
||||
objectType = objType;
|
||||
}
|
||||
|
||||
#region Properties
|
||||
|
||||
public delegate Task<DbConnection> Connector();
|
||||
|
||||
public delegate Task<EditSessionQueryExecutionState> QueryRunner(string query);
|
||||
|
||||
/// <summary>
|
||||
/// The task that is running to commit the changes to the db
|
||||
/// Internal for unit test purposes.
|
||||
@@ -61,12 +70,43 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
||||
/// <summary>
|
||||
/// The cache of pending updates. Internal for unit test purposes only
|
||||
/// </summary>
|
||||
internal ConcurrentDictionary<long, RowEditBase> EditCache { get; }
|
||||
internal ConcurrentDictionary<long, RowEditBase> EditCache { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The task that is running to initialize the edit session
|
||||
/// </summary>
|
||||
internal Task InitializeTask { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not the session has been initialized
|
||||
/// </summary>
|
||||
public bool IsInitialized { get; internal set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
public void Initialize(Connector connector, QueryRunner queryRunner, Func<Task> successHandler, Func<Exception, Task> errorHandler)
|
||||
{
|
||||
if (IsInitialized)
|
||||
{
|
||||
throw new InvalidOperationException(SR.EditDataSessionAlreadyInitialized);
|
||||
}
|
||||
|
||||
if (InitializeTask != null)
|
||||
{
|
||||
throw new InvalidOperationException(SR.EditDataSessionAlreadyInitializing);
|
||||
}
|
||||
|
||||
Validate.IsNotNull(nameof(connector), connector);
|
||||
Validate.IsNotNull(nameof(queryRunner), queryRunner);
|
||||
Validate.IsNotNull(nameof(successHandler), successHandler);
|
||||
Validate.IsNotNull(nameof(errorHandler), errorHandler);
|
||||
|
||||
// Start up the initialize process
|
||||
InitializeTask = InitializeInternal(connector, queryRunner, successHandler, errorHandler);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates that a query can be used for an edit session. The target result set is returned
|
||||
/// </summary>
|
||||
@@ -100,6 +140,8 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
||||
/// <returns>The internal ID of the newly created row</returns>
|
||||
public EditCreateRowResult CreateRow()
|
||||
{
|
||||
ThrowIfNotInitialized();
|
||||
|
||||
// Create a new row ID (atomically, since this could be accesses concurrently)
|
||||
long newRowId = NextRowId++;
|
||||
|
||||
@@ -113,13 +155,13 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
||||
}
|
||||
|
||||
// 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++)
|
||||
string[] defaultValues = new string[objectMetadata.Columns.Length];
|
||||
for(int i = 0; i < objectMetadata.Columns.Length; i++)
|
||||
{
|
||||
EditColumnWrapper col = objectMetadata.Columns[i];
|
||||
EditColumnMetadata col = objectMetadata.Columns[i];
|
||||
|
||||
// If the column is calculated, return the calculated placeholder as the display value
|
||||
if (col.IsCalculated)
|
||||
if (col.IsCalculated.HasTrue())
|
||||
{
|
||||
defaultValues[i] = SR.EditDataComputedColumnPlaceholder;
|
||||
}
|
||||
@@ -150,6 +192,8 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
||||
/// <param name="errorHandler">Callback to perform if the commit process has failed at some point</param>
|
||||
public void CommitEdits(DbConnection connection, Func<Task> successHandler, Func<Exception, Task> errorHandler)
|
||||
{
|
||||
ThrowIfNotInitialized();
|
||||
|
||||
Validate.IsNotNull(nameof(connection), connection);
|
||||
Validate.IsNotNull(nameof(successHandler), successHandler);
|
||||
Validate.IsNotNull(nameof(errorHandler), errorHandler);
|
||||
@@ -173,6 +217,8 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
||||
/// <param name="rowId">The internal ID of the row to delete</param>
|
||||
public void DeleteRow(long rowId)
|
||||
{
|
||||
ThrowIfNotInitialized();
|
||||
|
||||
// Sanity check the row ID
|
||||
if (rowId >= NextRowId || rowId < 0)
|
||||
{
|
||||
@@ -196,6 +242,8 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
||||
/// <returns>An array of rows with pending edits applied</returns>
|
||||
public async Task<EditRow[]> GetRows(long startIndex, int rowCount)
|
||||
{
|
||||
ThrowIfNotInitialized();
|
||||
|
||||
// Get the cached rows from the result set
|
||||
ResultSetSubset cachedRows = startIndex < associatedResultSet.RowCount
|
||||
? await associatedResultSet.GetSubset(startIndex, rowCount)
|
||||
@@ -249,6 +297,8 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
||||
/// <returns>String version of the old value for the cell</returns>
|
||||
public string RevertCell(long rowId, int columnId)
|
||||
{
|
||||
ThrowIfNotInitialized();
|
||||
|
||||
// Attempt to get the row edit with the given ID
|
||||
RowEditBase pendingEdit;
|
||||
if (!EditCache.TryGetValue(rowId, out pendingEdit))
|
||||
@@ -269,6 +319,8 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
||||
/// <param name="rowId">The internal ID of the row to reset</param>
|
||||
public void RevertRow(long rowId)
|
||||
{
|
||||
ThrowIfNotInitialized();
|
||||
|
||||
// Attempt to remove the row with the given ID
|
||||
RowEditBase removedEdit;
|
||||
if (!EditCache.TryRemove(rowId, out removedEdit))
|
||||
@@ -284,6 +336,8 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
||||
/// <returns></returns>
|
||||
public string ScriptEdits(string outputPath)
|
||||
{
|
||||
ThrowIfNotInitialized();
|
||||
|
||||
// Validate the output path
|
||||
// @TODO: Reinstate this code once we have an interface around file generation
|
||||
//if (outputPath == null)
|
||||
@@ -328,6 +382,8 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
||||
/// <param name="newValue">The new string value of the cell to update</param>
|
||||
public EditUpdateCellResult UpdateCell(long rowId, int columnId, string newValue)
|
||||
{
|
||||
ThrowIfNotInitialized();
|
||||
|
||||
// Sanity check to make sure that the row ID is in the range of possible values
|
||||
if (rowId >= NextRowId || rowId < 0)
|
||||
{
|
||||
@@ -347,6 +403,38 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
||||
|
||||
#endregion
|
||||
|
||||
private async Task InitializeInternal(Connector connector, QueryRunner queryRunner,
|
||||
Func<Task> successHandler, Func<Exception, Task> failureHandler)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Step 1) Look up the SMO metadata
|
||||
objectMetadata = metadataFactory.GetObjectMetadata(await connector(), objectName, objectType);
|
||||
|
||||
// Step 2) Get and execute a query for the rows in the object we're looking up
|
||||
EditSessionQueryExecutionState state = await queryRunner(ConstructInitializeQuery());
|
||||
if (state.Query == null)
|
||||
{
|
||||
// TODO: Move to SR file
|
||||
string message = state.Message ?? SR.EditDataQueryFailed;
|
||||
throw new Exception(message);
|
||||
}
|
||||
|
||||
// Step 3) Setup the internal state
|
||||
associatedResultSet = ValidateQueryForSession(state.Query);
|
||||
NextRowId = associatedResultSet.RowCount;
|
||||
EditCache = new ConcurrentDictionary<long, RowEditBase>();
|
||||
IsInitialized = true;
|
||||
|
||||
// Step 4) Return our success
|
||||
await successHandler();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
await failureHandler(e);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task CommitEditsInternal(DbConnection connection, Func<Task> successHandler, Func<Exception, Task> errorHandler)
|
||||
{
|
||||
try
|
||||
@@ -378,5 +466,50 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
||||
await errorHandler(e);
|
||||
}
|
||||
}
|
||||
|
||||
private string ConstructInitializeQuery()
|
||||
{
|
||||
// Using the columns we know, put together a query for the rows in the table
|
||||
var columns = objectMetadata.Columns.Select(col => col.EscapedName);
|
||||
var columnClause = string.Join(", ", columns);
|
||||
|
||||
return $"SELECT ${columnClause} FROM ${objectMetadata.EscapedMultipartName}";
|
||||
}
|
||||
|
||||
private void ThrowIfNotInitialized()
|
||||
{
|
||||
if (!IsInitialized)
|
||||
{
|
||||
throw new InvalidOperationException(SR.EditDataSessionNotInitialized);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// State object to return upon completion of an edit session intialization query
|
||||
/// </summary>
|
||||
public class EditSessionQueryExecutionState
|
||||
{
|
||||
/// <summary>
|
||||
/// The query object that was used to execute the edit initialization query. If
|
||||
/// <c>null</c> the query was not successfully executed.
|
||||
/// </summary>
|
||||
public Query Query { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Any message that may have occurred during execution of the query (ie, exceptions).
|
||||
/// If this is and <see cref="Query"/> are <c>null</c> then the error messages were
|
||||
/// returned via message events.
|
||||
/// </summary>
|
||||
public string Message { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new instance. Sets the values of the properties.
|
||||
/// </summary>
|
||||
public EditSessionQueryExecutionState(Query query, string message = null)
|
||||
{
|
||||
Query = query;
|
||||
Message = message;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System.Linq;
|
||||
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts;
|
||||
using Microsoft.SqlTools.Utility;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.EditData
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides metadata about the table or view being edited
|
||||
/// </summary>
|
||||
public class EditTableMetadata
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructs a simple edit table metadata provider
|
||||
/// </summary>
|
||||
public EditTableMetadata()
|
||||
{
|
||||
HasExtendedProperties = false;
|
||||
}
|
||||
|
||||
#region Basic Properties (properties provided by SMO)
|
||||
|
||||
/// <summary>
|
||||
/// List of columns in the object being edited
|
||||
/// </summary>
|
||||
public EditColumnMetadata[] Columns { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Full escaped multipart identifier for the object being edited
|
||||
/// </summary>
|
||||
public string EscapedMultipartName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not the object being edited is memory optimized
|
||||
/// </summary>
|
||||
public bool IsMemoryOptimized { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Extended Properties (properties provided by SqlClient)
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not the table has had extended properties added to it
|
||||
/// </summary>
|
||||
public bool HasExtendedProperties { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// List of columns that are used to uniquely identify a row
|
||||
/// </summary>
|
||||
public EditColumnMetadata[] KeyColumns { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Extracts extended column properties from the database columns from SQL Client
|
||||
/// </summary>
|
||||
/// <param name="dbColumnWrappers">The column information provided by SQL Client</param>
|
||||
public void Extend(DbColumnWrapper[] dbColumnWrappers)
|
||||
{
|
||||
Validate.IsNotNull(nameof(dbColumnWrappers), dbColumnWrappers);
|
||||
|
||||
// Iterate over the column wrappers and improve the columns we have
|
||||
for (int i = 0; i < Columns.Length; i++)
|
||||
{
|
||||
Columns[i].Extend(dbColumnWrappers[i]);
|
||||
}
|
||||
|
||||
// Determine what the key columns are
|
||||
KeyColumns = Columns.Where(c => c.IsKey.HasTrue()).ToArray();
|
||||
if (KeyColumns.Length == 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.HasTrue()).ToArray();
|
||||
}
|
||||
|
||||
// Mark that the table is now extended
|
||||
HasExtendedProperties = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,6 @@
|
||||
//
|
||||
|
||||
using System.Data.Common;
|
||||
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.EditData
|
||||
{
|
||||
@@ -17,10 +16,9 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
||||
/// Generates a edit-ready metadata object
|
||||
/// </summary>
|
||||
/// <param name="connection">Connection to use for getting metadata</param>
|
||||
/// <param name="columns">List of columns from a query against the object</param>
|
||||
/// <param name="objectName">Name of the object to return metadata for</param>
|
||||
/// <param name="objectType">Type of the object to return metadata for</param>
|
||||
/// <returns>Metadata about the object requested</returns>
|
||||
IEditTableMetadata GetObjectMetadata(DbConnection connection, DbColumnWrapper[] columns, string objectName, string objectType);
|
||||
EditTableMetadata GetObjectMetadata(DbConnection connection, string objectName, string objectType);
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
//
|
||||
// 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;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.EditData
|
||||
{
|
||||
/// <summary>
|
||||
/// An interface used in edit scenarios that defines properties for what columns are primary
|
||||
/// keys, and other metadata of the table.
|
||||
/// </summary>
|
||||
public interface IEditTableMetadata
|
||||
{
|
||||
/// <summary>
|
||||
/// All columns in the table that's being edited
|
||||
/// </summary>
|
||||
IReadOnlyList<EditColumnWrapper> Columns { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The escaped name of the table that's being edited
|
||||
/// </summary>
|
||||
string EscapedMultipartName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not this table is a memory optimized table
|
||||
/// </summary>
|
||||
bool IsMemoryOptimized { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Columns that can be used to uniquely identify the a row
|
||||
/// </summary>
|
||||
IReadOnlyList<EditColumnWrapper> KeyColumns { get; }
|
||||
}
|
||||
}
|
||||
@@ -4,12 +4,13 @@
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.Common;
|
||||
using System.Data.SqlClient;
|
||||
using Microsoft.SqlServer.Management.Common;
|
||||
using Microsoft.SqlServer.Management.Smo;
|
||||
using Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection;
|
||||
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.Utility;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.EditData
|
||||
{
|
||||
@@ -22,11 +23,10 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
||||
/// Generates a edit-ready metadata object using SMO
|
||||
/// </summary>
|
||||
/// <param name="connection">Connection to use for getting metadata</param>
|
||||
/// <param name="columns">List of columns from a query against the object</param>
|
||||
/// <param name="objectName">Name of the object to return metadata for</param>
|
||||
/// <param name="objectType">Type of the object to return metadata for</param>
|
||||
/// <returns>Metadata about the object requested</returns>
|
||||
public IEditTableMetadata GetObjectMetadata(DbConnection connection, DbColumnWrapper[] columns, string objectName, string objectType)
|
||||
public EditTableMetadata GetObjectMetadata(DbConnection connection, string objectName, string objectType)
|
||||
{
|
||||
// Get a connection to the database for SMO purposes
|
||||
SqlConnection sqlConn = connection as SqlConnection;
|
||||
@@ -44,25 +44,59 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
||||
sqlConn = reliableConn.GetUnderlyingConnection();
|
||||
}
|
||||
|
||||
// Connect with SMO and get the metadata for the table
|
||||
Server server = new Server(new ServerConnection(sqlConn));
|
||||
TableViewTableTypeBase result;
|
||||
TableViewTableTypeBase smoResult;
|
||||
switch (objectType.ToLowerInvariant())
|
||||
{
|
||||
case "table":
|
||||
result = server.Databases[sqlConn.Database].Tables[objectName];
|
||||
smoResult = server.Databases[sqlConn.Database].Tables[objectName];
|
||||
break;
|
||||
case "view":
|
||||
result = server.Databases[sqlConn.Database].Views[objectName];
|
||||
smoResult = server.Databases[sqlConn.Database].Views[objectName];
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(objectType), SR.EditDataUnsupportedObjectType(objectType));
|
||||
}
|
||||
if (result == null)
|
||||
if (smoResult == null)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(objectName), SR.EditDataObjectMetadataNotFound);
|
||||
}
|
||||
|
||||
return new SmoEditTableMetadata(columns, result);
|
||||
// Generate the edit column metadata
|
||||
List<EditColumnMetadata> editColumns = new List<EditColumnMetadata>();
|
||||
for (int i = 0; i < smoResult.Columns.Count; i++)
|
||||
{
|
||||
Column smoColumn = smoResult.Columns[i];
|
||||
|
||||
// The default value may be escaped
|
||||
string defaultValue = smoColumn.DefaultConstraint == null
|
||||
? null
|
||||
: SqlScriptFormatter.UnwrapLiteral(smoColumn.DefaultConstraint.Text);
|
||||
|
||||
EditColumnMetadata column = new EditColumnMetadata
|
||||
{
|
||||
DefaultValue = defaultValue,
|
||||
EscapedName = SqlScriptFormatter.FormatIdentifier(smoColumn.Name),
|
||||
Ordinal = i,
|
||||
};
|
||||
editColumns.Add(column);
|
||||
}
|
||||
|
||||
// Only tables can be memory-optimized
|
||||
Table smoTable = smoResult as Table;
|
||||
bool isMemoryOptimized = smoTable != null && smoTable.IsMemoryOptimized;
|
||||
|
||||
// Escape the parts of the name
|
||||
string[] objectNameParts = {smoResult.Schema, smoResult.Name};
|
||||
string escapedMultipartName = SqlScriptFormatter.FormatMultipartIdentifier(objectNameParts);
|
||||
|
||||
return new EditTableMetadata
|
||||
{
|
||||
Columns = editColumns.ToArray(),
|
||||
EscapedMultipartName = escapedMultipartName,
|
||||
IsMemoryOptimized = isMemoryOptimized,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
//
|
||||
// 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides metadata about the table or view being edited
|
||||
/// </summary>
|
||||
public class SmoEditTableMetadata : IEditTableMetadata
|
||||
{
|
||||
private readonly List<EditColumnWrapper> columns;
|
||||
private readonly List<EditColumnWrapper> keyColumns;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor that extracts useful metadata from the provided metadata objects
|
||||
/// </summary>
|
||||
/// <param name="dbColumns">DB columns from the ResultSet</param>
|
||||
/// <param name="smoObject">SMO metadata object for the table/view being edited</param>
|
||||
public SmoEditTableMetadata(IList<DbColumnWrapper> 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<EditColumnWrapper>();
|
||||
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;
|
||||
|
||||
// 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,
|
||||
|
||||
// A column is calculated if it is identity, computed, or otherwise not updatable
|
||||
IsCalculated = smoColumn.Identity || smoColumn.Computed || !dbColumn.IsUpdatable
|
||||
};
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read-only list of columns in the object being edited
|
||||
/// </summary>
|
||||
public IReadOnlyList<EditColumnWrapper> Columns => columns.AsReadOnly();
|
||||
|
||||
/// <summary>
|
||||
/// Full escaped multipart identifier for the object being edited
|
||||
/// </summary>
|
||||
public string EscapedMultipartName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not the object being edited is memory optimized
|
||||
/// </summary>
|
||||
public bool IsMemoryOptimized { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Read-only list of columns that are used to uniquely identify a row
|
||||
/// </summary>
|
||||
public IReadOnlyList<EditColumnWrapper> KeyColumns => keyColumns.AsReadOnly();
|
||||
}
|
||||
}
|
||||
@@ -35,7 +35,7 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
|
||||
/// <param name="rowId">Internal ID of the row that is being created</param>
|
||||
/// <param name="associatedResultSet">The result set for the rows in the table we're editing</param>
|
||||
/// <param name="associatedMetadata">The metadata for table we're editing</param>
|
||||
public RowCreate(long rowId, ResultSet associatedResultSet, IEditTableMetadata associatedMetadata)
|
||||
public RowCreate(long rowId, ResultSet associatedResultSet, EditTableMetadata associatedMetadata)
|
||||
: base(rowId, associatedResultSet, associatedMetadata)
|
||||
{
|
||||
newCells = new CellUpdate[associatedResultSet.Columns.Length];
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
|
||||
/// <param name="rowId">Internal ID of the row to be deleted</param>
|
||||
/// <param name="associatedResultSet">Result set that is being edited</param>
|
||||
/// <param name="associatedMetadata">Improved metadata of the object being edited</param>
|
||||
public RowDelete(long rowId, ResultSet associatedResultSet, IEditTableMetadata associatedMetadata)
|
||||
public RowDelete(long rowId, ResultSet associatedResultSet, EditTableMetadata associatedMetadata)
|
||||
: base(rowId, associatedResultSet, associatedMetadata)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
|
||||
/// <param name="rowId">The internal ID of the row that is being edited</param>
|
||||
/// <param name="associatedResultSet">The result set that will be updated</param>
|
||||
/// <param name="associatedMetadata">Metadata provider for the object to edit</param>
|
||||
protected RowEditBase(long rowId, ResultSet associatedResultSet, IEditTableMetadata associatedMetadata)
|
||||
protected RowEditBase(long rowId, ResultSet associatedResultSet, EditTableMetadata associatedMetadata)
|
||||
{
|
||||
RowId = rowId;
|
||||
AssociatedResultSet = associatedResultSet;
|
||||
@@ -58,7 +58,7 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
|
||||
/// <summary>
|
||||
/// The metadata for the table this edit is associated to
|
||||
/// </summary>
|
||||
public IEditTableMetadata AssociatedObjectMetadata { get; }
|
||||
public EditTableMetadata AssociatedObjectMetadata { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Sort ID for a row edit. Ensures that when a collection of RowEditBase objects are
|
||||
@@ -162,7 +162,7 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
|
||||
}
|
||||
|
||||
IList<DbCellValue> row = AssociatedResultSet.GetRow(RowId);
|
||||
foreach (EditColumnWrapper col in AssociatedObjectMetadata.KeyColumns)
|
||||
foreach (EditColumnMetadata col in AssociatedObjectMetadata.KeyColumns)
|
||||
{
|
||||
// Put together a clause for the value of the cell
|
||||
DbCellValue cellData = row[col.Ordinal];
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
|
||||
/// <param name="rowId">Internal ID of the row that will be updated with this object</param>
|
||||
/// <param name="associatedResultSet">Result set for the rows of the object to update</param>
|
||||
/// <param name="associatedMetadata">Metadata provider for the object to update</param>
|
||||
public RowUpdate(long rowId, ResultSet associatedResultSet, IEditTableMetadata associatedMetadata)
|
||||
public RowUpdate(long rowId, ResultSet associatedResultSet, EditTableMetadata associatedMetadata)
|
||||
: base(rowId, associatedResultSet, associatedMetadata)
|
||||
{
|
||||
cellUpdates = new ConcurrentDictionary<int, CellUpdate>();
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,18 +1,96 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
@@ -27,106 +105,322 @@
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype"><value>text/microsoft-resx</value></resheader><resheader name="version"><value>1.3</value></resheader><resheader name="reader"><value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value></resheader><resheader name="writer"><value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value></resheader><data name="ConnectionServiceConnectErrorNullParams"><value>Los parámetros de conexión no pueden ser nulos</value></data>
|
||||
<data name="ConnectionServiceListDbErrorNullOwnerUri"><value>OwnerUri no puede ser nulo ni estar vacío</value></data>
|
||||
<data name="ConnectionServiceListDbErrorNotConnected"><value>SpecifiedUri '{0}' no tiene una conexión existente</value></data>
|
||||
<data name="ConnectionServiceConnStringInvalidAuthType"><value>El valor '{0}' no es válido para AuthenticationType. Los valores válidos son 'Integrated' y 'SqlLogin'.</value></data>
|
||||
<data name="ConnectionServiceConnStringInvalidIntent"><value>El valor '{0}' no es válido para ApplicationIntent. Los valores válidos son 'ReadWrite' y 'ReadOnly'.</value></data>
|
||||
<data name="ConnectionServiceConnectionCanceled"><value>Conexión cancelada</value></data>
|
||||
<data name="ConnectionParamsValidateNullOwnerUri"><value>OwnerUri no puede ser nulo ni estar vacío</value></data>
|
||||
<data name="ConnectionParamsValidateNullConnection"><value>El objeto de detalles de conexión no puede ser nulo</value></data>
|
||||
<data name="ConnectionParamsValidateNullServerName"><value>ServerName no puede ser nulo ni estar vacío</value></data>
|
||||
<data name="ConnectionParamsValidateNullSqlAuth"><value>{0} no puede ser nulo ni estar vacío cuando se utiliza autenticación SqlLogin</value></data>
|
||||
<data name="QueryServiceCancelAlreadyCompleted"><value>Ya se ha completado la consulta, no se puede cancelar</value></data>
|
||||
<data name="QueryServiceCancelDisposeFailed"><value>La consulta fue cancelada con éxito, pero no se ha podido desechar. No se encontró el URI del propietario.</value></data>
|
||||
<data name="QueryServiceQueryCancelled"><value>Consulta cancelada por el usuario</value></data>
|
||||
<data name="QueryServiceSubsetBatchNotCompleted"><value>El lote aún no ha finalizado,</value></data>
|
||||
<data name="QueryServiceSubsetBatchOutOfRange"><value>Índice de lote no puede ser menor que 0 o mayor que el número de lotes</value></data>
|
||||
<data name="QueryServiceSubsetResultSetOutOfRange"><value>Índice del conjunto de resultados no puede ser menor que 0 o mayor que el número de conjuntos de resultados</value></data>
|
||||
<data name="QueryServiceDataReaderByteCountInvalid"><value>El número máximo de bytes a devolver debe ser mayor que cero</value></data>
|
||||
<data name="QueryServiceDataReaderCharCountInvalid"><value>El número máximo de caracteres a devolver debe ser mayor que cero</value></data>
|
||||
<data name="QueryServiceDataReaderXmlCountInvalid"><value>El número máximo de bytes XML a devolver debe ser mayor que cero</value></data>
|
||||
<data name="QueryServiceFileWrapperWriteOnly"><value>El método de acceso no puede ser de sólo escritura</value></data>
|
||||
<data name="QueryServiceFileWrapperNotInitialized"><value>FileStreamWrapper debe inicializarse antes de realizar operaciones</value></data>
|
||||
<data name="QueryServiceFileWrapperReadOnly"><value>Este FileStreamWrapper no se puede utilizar para escritura.</value></data>
|
||||
<data name="QueryServiceAffectedOneRow"><value>(1 fila afectada)</value></data>
|
||||
<data name="QueryServiceAffectedRows"><value>({0} filas afectadas)</value></data>
|
||||
<data name="QueryServiceCompletedSuccessfully"><value>Comandos finalizados correctamente.</value></data>
|
||||
<data name="QueryServiceErrorFormat"><value>Msg {0}, nivel {1} estado {2}, línea {3} {4} {5}</value></data>
|
||||
<data name="QueryServiceQueryFailed"><value>Error en la consulta: {0}</value></data>
|
||||
<data name="QueryServiceColumnNull"><value>(Ningún nombre de columna)</value></data>
|
||||
<data name="QueryServiceRequestsNoQuery"><value>La consulta solicitada no existe</value></data>
|
||||
<data name="QueryServiceQueryInvalidOwnerUri"><value>Este editor no está conectado a una base de datos</value></data>
|
||||
<data name="QueryServiceQueryInProgress"><value>Una consulta ya está en curso para esta sesión de editor. Por favor, cancelar esta consulta o esperar su finalización.</value></data>
|
||||
<data name="QueryServiceMessageSenderNotSql"><value>Remitente de eventos de OnInfoMessage debe ser un objeto SqlConnection</value></data>
|
||||
<data name="QueryServiceResultSetReaderNull"><value>Lector no puede ser nulo</value></data>
|
||||
<data name="QueryServiceSaveAsResultSetNotComplete"><value>No se puede guardar el resultado hasta que haya finalizado la ejecución de la consulta</value></data>
|
||||
<data name="QueryServiceSaveAsMiscStartingError"><value>Error interno al iniciar el guardado de la tarea</value></data>
|
||||
<data name="QueryServiceSaveAsInProgress"><value>Una operacion de guardado en la misma ruta se encuentra en curso</value></data>
|
||||
<data name="QueryServiceSaveAsFail"><value>Error al guardar {0}: {1}</value></data>
|
||||
<data name="QueryServiceResultSetNotRead"><value>No se puede leer el subconjunto, a menos que los resultados se han leído desde el servidor</value></data>
|
||||
<data name="QueryServiceResultSetStartRowOutOfRange"><value>Fila de inicio no puede ser menor que 0 o mayor que el número de filas en el conjunto de resultados</value></data>
|
||||
<data name="QueryServiceResultSetRowCountOutOfRange"><value>La cantidad de filas debe ser un entero positivo</value></data>
|
||||
<data name="QueryServiceResultSetNoColumnSchema"><value>No se pudo recuperar el esquema de columna para el conjunto de resultados</value></data>
|
||||
<data name="QueryServiceExecutionPlanNotFound"><value>No se pudo recuperar un plan de ejecución del conjunto de resultados</value></data>
|
||||
<data name="PeekDefinitionAzureError"><value>Esta característica actualmente no se admite en la base de datos de SQL Azure y almacén de datos: {0}</value></data>
|
||||
<data name="PeekDefinitionError"><value>Se ha producido un error inesperado durante la ejecución de la definición de Peek: {0}</value></data>
|
||||
<data name="PeekDefinitionNoResultsError"><value>No se encontraron resultados.</value></data>
|
||||
<data name="PeekDefinitionDatabaseError"><value>No se pudo obtener ningún objeto asociado a la base de datos.</value></data>
|
||||
<data name="PeekDefinitionNotConnectedError"><value>Conéctese a un servidor.</value></data>
|
||||
<data name="PeekDefinitionTimedoutError"><value>Tiempo de espera agotado para esta operación.</value></data>
|
||||
<data name="PeekDefinitionTypeNotSupportedError"><value>Esta característica no admite actualmente este tipo de objeto.</value></data>
|
||||
<data name="WorkspaceServicePositionLineOutOfRange"><value>Posición está fuera del intervalo de la línea de archivo</value></data>
|
||||
<data name="WorkspaceServicePositionColumnOutOfRange"><value>Posición está fuera del intervalo de la columna de la línea {0}</value></data>
|
||||
<data name="WorkspaceServiceBufferPositionOutOfOrder"><value>Posición de inicio ({0}, {1}) debe preceder o ser igual a la posición final ({2}, {3})</value></data>
|
||||
<data name="EE_BatchSqlMessageNoProcedureInfo"><value>Msg {0}, {1}, nivel de estado {2}, línea {3}</value></data>
|
||||
<data name="EE_BatchSqlMessageWithProcedureInfo"><value>Msj {0}, {1}, nivel de estado {2}, procedimiento {3}, línea {4}</value></data>
|
||||
<data name="EE_BatchSqlMessageNoLineInfo"><value>Msg {0}, nivel {1}, {2} de estado</value></data>
|
||||
<data name="EE_BatchError_Exception"><value>Se produjo un error al procesar el lote. Mensaje de error: {0}</value></data>
|
||||
<data name="EE_BatchExecutionInfo_RowsAffected"><value>({0} filas afectadas)</value></data>
|
||||
<data name="EE_ExecutionNotYetCompleteError"><value>La ejecución anterior aún no está completa.</value></data>
|
||||
<data name="EE_ScriptError_Error"><value>Se ha producido un error de secuencias de comandos.</value></data>
|
||||
<data name="EE_ScriptError_ParsingSyntax"><value>Se encontró sintaxis incorrecta mientras se estaba analizando {0}.</value></data>
|
||||
<data name="EE_ScriptError_FatalError"><value>Se ha producido un error grave.</value></data>
|
||||
<data name="EE_ExecutionInfo_FinalizingLoop"><value>La ejecución completó {0} veces...</value></data>
|
||||
<data name="EE_ExecutionInfo_QueryCancelledbyUser"><value>Se canceló la consulta.</value></data>
|
||||
<data name="EE_BatchExecutionError_Halting"><value>Se produjo un error mientras se ejecutaba el lote.</value></data>
|
||||
<data name="EE_BatchExecutionError_Ignoring"><value>Se produjo un error mientras se ejecutaba el lote, pero se ha omitido el error.</value></data>
|
||||
<data name="EE_ExecutionInfo_InitilizingLoop"><value>Iniciando bucle de ejecución de {0} veces...</value></data>
|
||||
<data name="EE_ExecutionError_CommandNotSupported"><value>No se admite el comando {0}.</value></data>
|
||||
<data name="EE_ExecutionError_VariableNotFound"><value>La variable {0} no se encontró.</value></data>
|
||||
<data name="BatchParserWrapperExecutionEngineError"><value>Error de ejecución de SQL: {0}</value></data>
|
||||
<data name="BatchParserWrapperExecutionError"><value>Ejecución de contenedor del analizador por lotes: {0} se encuentra... en la línea {1}: {2} Descripción: {3}</value></data>
|
||||
<data name="BatchParserWrapperExecutionEngineBatchMessage"><value>Lote analizador contenedor ejecución motor lote mensaje recibido: mensaje: {0} mensaje detallado: {1}</value></data>
|
||||
<data name="BatchParserWrapperExecutionEngineBatchResultSetProcessing"><value>Motor de ejecución de analizador contenedor lote ResultSet procesamiento por lotes: DataReader.FieldCount: {0} DataReader.RecordsAffected: {1}</value></data>
|
||||
<data name="BatchParserWrapperExecutionEngineBatchResultSetFinished"><value>Finalizó el elemento ResultSet analizador contenedor ejecución motor los lotes.</value></data>
|
||||
<data name="BatchParserWrapperExecutionEngineBatchCancelling"><value>Cancelando la ejecución por lotes del contenedor del analizador por lotes.</value></data>
|
||||
<data name="EE_ScriptError_Warning"><value>Advertencia de scripting.</value></data>
|
||||
<data name="TroubleshootingAssistanceMessage"><value>Para obtener más información acerca de este error, vea los temas de solución de problemas en la documentación del producto.</value></data>
|
||||
<data name="BatchParser_CircularReference"><value>El archivo '{0}' se incluyó recursivamente.</value></data>
|
||||
<data name="BatchParser_CommentNotTerminated"><value>Falta la marca de final de comentario ' * /'.</value></data>
|
||||
<data name="BatchParser_StringNotTerminated"><value>Sin comilla de cierre después de la cadena de caracteres.</value></data>
|
||||
<data name="BatchParser_IncorrectSyntax"><value>Se encontró sintaxis incorrecta al analizar '{0}'.</value></data>
|
||||
<data name="BatchParser_VariableNotDefined"><value>La variable {0} no está definida.</value></data>
|
||||
<data name="TestLocalizationConstant"><value>prueba</value></data>
|
||||
<data name="ErrorUnexpectedCodeObjectType"><value>No se puede convertir el SqlCodeObject del Tipo {0} al Tipo {1}</value></data>
|
||||
<data name="ErrorEmptyStringReplacement"><value>Sustitución de una cadena vacía por una cadena vacía.</value></data>
|
||||
<data name="EditDataSessionNotFound"><value>Sesión de edición no existe,</value></data>
|
||||
<data name="EditDataQueryNotCompleted"><value>La consulta no ha finalizado.</value></data>
|
||||
<data name="EditDataQueryImproperResultSets"><value>La consulta no generó un único set de resultados</value></data>
|
||||
<data name="EditDataFailedAddRow"><value>Falló al agregar una nueva fila a la caché de actualización</value></data>
|
||||
<data name="EditDataRowOutOfRange"><value>El ID de la fila ingresado, se encuentra fuera del rango de filas de la caché de edición</value></data>
|
||||
<data name="EditDataUpdatePending"><value>Una actualización está pendiente para esta fila y debe de revertirse primero</value></data>
|
||||
<data name="EditDataUpdateNotPending"><value>El ID de la fila ingresado no tiene actualizaciones pendientes</value></data>
|
||||
<data name="EditDataObjectMetadataNotFound"><value>La metadata de la tabla o vista no pudo ser encontrada</value></data>
|
||||
<data name="EditDataInvalidFormatBinary"><value>Formato inválido para columna binaria</value></data>
|
||||
<data name="EditDataInvalidFormatBoolean"><value>Columnas del tipo boolean deben de ser numéricos 1 o 0, o tipo string true o false</value></data>
|
||||
<data name="EditDataCreateScriptMissingValue"><value>Falta un valor requerido de la celda</value></data>
|
||||
<data name="EditDataDeleteSetCell"><value>Existe una eliminación pendiente para esta fila, una actualización de celda no puede ser realizada.</value></data>
|
||||
<data name="EditDataColumnIdOutOfRange"><value>El ID de la columna debe de estar en el rango de columnas de la consulta.</value></data>
|
||||
<data name="EditDataColumnCannotBeEdited"><value>La columna no puede ser editada</value></data>
|
||||
<data name="EditDataColumnNoKeyColumns"><value>No se encontró ninguna columna clave</value></data>
|
||||
<data name="EditDataScriptFilePathNull"><value>Proporcione un nombre de archivo de salida</value></data>
|
||||
<data name="EditDataUnsupportedObjectType"><value>Objeto de base de datos {0} no puede ser usado para modificación.</value></data>
|
||||
<data name="ConnectionServiceDbErrorDefaultNotConnected"><value>SpecifiedUri '{0}' no tiene alguna conexión por defecto</value></data>
|
||||
</root>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="ConnectionServiceConnectErrorNullParams" xml:space="preserve">
|
||||
<value>Los parámetros de conexión no pueden ser nulos</value>
|
||||
</data>
|
||||
<data name="ConnectionServiceListDbErrorNullOwnerUri" xml:space="preserve">
|
||||
<value>OwnerUri no puede ser nulo ni estar vacío</value>
|
||||
</data>
|
||||
<data name="ConnectionServiceListDbErrorNotConnected" xml:space="preserve">
|
||||
<value>SpecifiedUri '{0}' no tiene una conexión existente</value>
|
||||
</data>
|
||||
<data name="ConnectionServiceConnStringInvalidAuthType" xml:space="preserve">
|
||||
<value>El valor '{0}' no es válido para AuthenticationType. Los valores válidos son 'Integrated' y 'SqlLogin'.</value>
|
||||
</data>
|
||||
<data name="ConnectionServiceConnStringInvalidIntent" xml:space="preserve">
|
||||
<value>El valor '{0}' no es válido para ApplicationIntent. Los valores válidos son 'ReadWrite' y 'ReadOnly'.</value>
|
||||
</data>
|
||||
<data name="ConnectionServiceConnectionCanceled" xml:space="preserve">
|
||||
<value>Conexión cancelada</value>
|
||||
</data>
|
||||
<data name="ConnectionParamsValidateNullOwnerUri" xml:space="preserve">
|
||||
<value>OwnerUri no puede ser nulo ni estar vacío</value>
|
||||
</data>
|
||||
<data name="ConnectionParamsValidateNullConnection" xml:space="preserve">
|
||||
<value>El objeto de detalles de conexión no puede ser nulo</value>
|
||||
</data>
|
||||
<data name="ConnectionParamsValidateNullServerName" xml:space="preserve">
|
||||
<value>ServerName no puede ser nulo ni estar vacío</value>
|
||||
</data>
|
||||
<data name="ConnectionParamsValidateNullSqlAuth" xml:space="preserve">
|
||||
<value>{0} no puede ser nulo ni estar vacío cuando se utiliza autenticación SqlLogin</value>
|
||||
</data>
|
||||
<data name="QueryServiceCancelAlreadyCompleted" xml:space="preserve">
|
||||
<value>Ya se ha completado la consulta, no se puede cancelar</value>
|
||||
</data>
|
||||
<data name="QueryServiceCancelDisposeFailed" xml:space="preserve">
|
||||
<value>La consulta fue cancelada con éxito, pero no se ha podido desechar. No se encontró el URI del propietario.</value>
|
||||
</data>
|
||||
<data name="QueryServiceQueryCancelled" xml:space="preserve">
|
||||
<value>Consulta cancelada por el usuario</value>
|
||||
</data>
|
||||
<data name="QueryServiceSubsetBatchNotCompleted" xml:space="preserve">
|
||||
<value>El lote aún no ha finalizado,</value>
|
||||
</data>
|
||||
<data name="QueryServiceSubsetBatchOutOfRange" xml:space="preserve">
|
||||
<value>Índice de lote no puede ser menor que 0 o mayor que el número de lotes</value>
|
||||
</data>
|
||||
<data name="QueryServiceSubsetResultSetOutOfRange" xml:space="preserve">
|
||||
<value>Índice del conjunto de resultados no puede ser menor que 0 o mayor que el número de conjuntos de resultados</value>
|
||||
</data>
|
||||
<data name="QueryServiceDataReaderByteCountInvalid" xml:space="preserve">
|
||||
<value>El número máximo de bytes a devolver debe ser mayor que cero</value>
|
||||
</data>
|
||||
<data name="QueryServiceDataReaderCharCountInvalid" xml:space="preserve">
|
||||
<value>El número máximo de caracteres a devolver debe ser mayor que cero</value>
|
||||
</data>
|
||||
<data name="QueryServiceDataReaderXmlCountInvalid" xml:space="preserve">
|
||||
<value>El número máximo de bytes XML a devolver debe ser mayor que cero</value>
|
||||
</data>
|
||||
<data name="QueryServiceFileWrapperWriteOnly" xml:space="preserve">
|
||||
<value>El método de acceso no puede ser de sólo escritura</value>
|
||||
</data>
|
||||
<data name="QueryServiceFileWrapperNotInitialized" xml:space="preserve">
|
||||
<value>FileStreamWrapper debe inicializarse antes de realizar operaciones</value>
|
||||
</data>
|
||||
<data name="QueryServiceFileWrapperReadOnly" xml:space="preserve">
|
||||
<value>Este FileStreamWrapper no se puede utilizar para escritura.</value>
|
||||
</data>
|
||||
<data name="QueryServiceAffectedOneRow" xml:space="preserve">
|
||||
<value>(1 fila afectada)</value>
|
||||
</data>
|
||||
<data name="QueryServiceAffectedRows" xml:space="preserve">
|
||||
<value>({0} filas afectadas)</value>
|
||||
</data>
|
||||
<data name="QueryServiceCompletedSuccessfully" xml:space="preserve">
|
||||
<value>Comandos finalizados correctamente.</value>
|
||||
</data>
|
||||
<data name="QueryServiceErrorFormat" xml:space="preserve">
|
||||
<value>Msg {0}, nivel {1} estado {2}, línea {3} {4} {5}</value>
|
||||
</data>
|
||||
<data name="QueryServiceQueryFailed" xml:space="preserve">
|
||||
<value>Error en la consulta: {0}</value>
|
||||
</data>
|
||||
<data name="QueryServiceColumnNull" xml:space="preserve">
|
||||
<value>(Ningún nombre de columna)</value>
|
||||
</data>
|
||||
<data name="QueryServiceRequestsNoQuery" xml:space="preserve">
|
||||
<value>La consulta solicitada no existe</value>
|
||||
</data>
|
||||
<data name="QueryServiceQueryInvalidOwnerUri" xml:space="preserve">
|
||||
<value>Este editor no está conectado a una base de datos</value>
|
||||
</data>
|
||||
<data name="QueryServiceQueryInProgress" xml:space="preserve">
|
||||
<value>Una consulta ya está en curso para esta sesión de editor. Por favor, cancelar esta consulta o esperar su finalización.</value>
|
||||
</data>
|
||||
<data name="QueryServiceMessageSenderNotSql" xml:space="preserve">
|
||||
<value>Remitente de eventos de OnInfoMessage debe ser un objeto SqlConnection</value>
|
||||
</data>
|
||||
<data name="QueryServiceResultSetReaderNull" xml:space="preserve">
|
||||
<value>Lector no puede ser nulo</value>
|
||||
</data>
|
||||
<data name="QueryServiceSaveAsResultSetNotComplete" xml:space="preserve">
|
||||
<value>No se puede guardar el resultado hasta que haya finalizado la ejecución de la consulta</value>
|
||||
</data>
|
||||
<data name="QueryServiceSaveAsMiscStartingError" xml:space="preserve">
|
||||
<value>Error interno al iniciar el guardado de la tarea</value>
|
||||
</data>
|
||||
<data name="QueryServiceSaveAsInProgress" xml:space="preserve">
|
||||
<value>Una operacion de guardado en la misma ruta se encuentra en curso</value>
|
||||
</data>
|
||||
<data name="QueryServiceSaveAsFail" xml:space="preserve">
|
||||
<value>Error al guardar {0}: {1}</value>
|
||||
</data>
|
||||
<data name="QueryServiceResultSetNotRead" xml:space="preserve">
|
||||
<value>No se puede leer el subconjunto, a menos que los resultados se han leído desde el servidor</value>
|
||||
</data>
|
||||
<data name="QueryServiceResultSetStartRowOutOfRange" xml:space="preserve">
|
||||
<value>Fila de inicio no puede ser menor que 0 o mayor que el número de filas en el conjunto de resultados</value>
|
||||
</data>
|
||||
<data name="QueryServiceResultSetRowCountOutOfRange" xml:space="preserve">
|
||||
<value>La cantidad de filas debe ser un entero positivo</value>
|
||||
</data>
|
||||
<data name="QueryServiceResultSetNoColumnSchema" xml:space="preserve">
|
||||
<value>No se pudo recuperar el esquema de columna para el conjunto de resultados</value>
|
||||
</data>
|
||||
<data name="QueryServiceExecutionPlanNotFound" xml:space="preserve">
|
||||
<value>No se pudo recuperar un plan de ejecución del conjunto de resultados</value>
|
||||
</data>
|
||||
<data name="PeekDefinitionAzureError" xml:space="preserve">
|
||||
<value>Esta característica actualmente no se admite en la base de datos de SQL Azure y almacén de datos: {0}</value>
|
||||
</data>
|
||||
<data name="PeekDefinitionError" xml:space="preserve">
|
||||
<value>Se ha producido un error inesperado durante la ejecución de la definición de Peek: {0}</value>
|
||||
</data>
|
||||
<data name="PeekDefinitionNoResultsError" xml:space="preserve">
|
||||
<value>No se encontraron resultados.</value>
|
||||
</data>
|
||||
<data name="PeekDefinitionDatabaseError" xml:space="preserve">
|
||||
<value>No se pudo obtener ningún objeto asociado a la base de datos.</value>
|
||||
</data>
|
||||
<data name="PeekDefinitionNotConnectedError" xml:space="preserve">
|
||||
<value>Conéctese a un servidor.</value>
|
||||
</data>
|
||||
<data name="PeekDefinitionTimedoutError" xml:space="preserve">
|
||||
<value>Tiempo de espera agotado para esta operación.</value>
|
||||
</data>
|
||||
<data name="PeekDefinitionTypeNotSupportedError" xml:space="preserve">
|
||||
<value>Esta característica no admite actualmente este tipo de objeto.</value>
|
||||
</data>
|
||||
<data name="WorkspaceServicePositionLineOutOfRange" xml:space="preserve">
|
||||
<value>Posición está fuera del intervalo de la línea de archivo</value>
|
||||
</data>
|
||||
<data name="WorkspaceServicePositionColumnOutOfRange" xml:space="preserve">
|
||||
<value>Posición está fuera del intervalo de la columna de la línea {0}</value>
|
||||
</data>
|
||||
<data name="WorkspaceServiceBufferPositionOutOfOrder" xml:space="preserve">
|
||||
<value>Posición de inicio ({0}, {1}) debe preceder o ser igual a la posición final ({2}, {3})</value>
|
||||
</data>
|
||||
<data name="EE_BatchSqlMessageNoProcedureInfo" xml:space="preserve">
|
||||
<value>Msg {0}, {1}, nivel de estado {2}, línea {3}</value>
|
||||
</data>
|
||||
<data name="EE_BatchSqlMessageWithProcedureInfo" xml:space="preserve">
|
||||
<value>Msj {0}, {1}, nivel de estado {2}, procedimiento {3}, línea {4}</value>
|
||||
</data>
|
||||
<data name="EE_BatchSqlMessageNoLineInfo" xml:space="preserve">
|
||||
<value>Msg {0}, nivel {1}, {2} de estado</value>
|
||||
</data>
|
||||
<data name="EE_BatchError_Exception" xml:space="preserve">
|
||||
<value>Se produjo un error al procesar el lote. Mensaje de error: {0}</value>
|
||||
</data>
|
||||
<data name="EE_BatchExecutionInfo_RowsAffected" xml:space="preserve">
|
||||
<value>({0} filas afectadas)</value>
|
||||
</data>
|
||||
<data name="EE_ExecutionNotYetCompleteError" xml:space="preserve">
|
||||
<value>La ejecución anterior aún no está completa.</value>
|
||||
</data>
|
||||
<data name="EE_ScriptError_Error" xml:space="preserve">
|
||||
<value>Se ha producido un error de secuencias de comandos.</value>
|
||||
</data>
|
||||
<data name="EE_ScriptError_ParsingSyntax" xml:space="preserve">
|
||||
<value>Se encontró sintaxis incorrecta mientras se estaba analizando {0}.</value>
|
||||
</data>
|
||||
<data name="EE_ScriptError_FatalError" xml:space="preserve">
|
||||
<value>Se ha producido un error grave.</value>
|
||||
</data>
|
||||
<data name="EE_ExecutionInfo_FinalizingLoop" xml:space="preserve">
|
||||
<value>La ejecución completó {0} veces...</value>
|
||||
</data>
|
||||
<data name="EE_ExecutionInfo_QueryCancelledbyUser" xml:space="preserve">
|
||||
<value>Se canceló la consulta.</value>
|
||||
</data>
|
||||
<data name="EE_BatchExecutionError_Halting" xml:space="preserve">
|
||||
<value>Se produjo un error mientras se ejecutaba el lote.</value>
|
||||
</data>
|
||||
<data name="EE_BatchExecutionError_Ignoring" xml:space="preserve">
|
||||
<value>Se produjo un error mientras se ejecutaba el lote, pero se ha omitido el error.</value>
|
||||
</data>
|
||||
<data name="EE_ExecutionInfo_InitilizingLoop" xml:space="preserve">
|
||||
<value>Iniciando bucle de ejecución de {0} veces...</value>
|
||||
</data>
|
||||
<data name="EE_ExecutionError_CommandNotSupported" xml:space="preserve">
|
||||
<value>No se admite el comando {0}.</value>
|
||||
</data>
|
||||
<data name="EE_ExecutionError_VariableNotFound" xml:space="preserve">
|
||||
<value>La variable {0} no se encontró.</value>
|
||||
</data>
|
||||
<data name="BatchParserWrapperExecutionEngineError" xml:space="preserve">
|
||||
<value>Error de ejecución de SQL: {0}</value>
|
||||
</data>
|
||||
<data name="BatchParserWrapperExecutionError" xml:space="preserve">
|
||||
<value>Ejecución de contenedor del analizador por lotes: {0} se encuentra... en la línea {1}: {2} Descripción: {3}</value>
|
||||
</data>
|
||||
<data name="BatchParserWrapperExecutionEngineBatchMessage" xml:space="preserve">
|
||||
<value>Lote analizador contenedor ejecución motor lote mensaje recibido: mensaje: {0} mensaje detallado: {1}</value>
|
||||
</data>
|
||||
<data name="BatchParserWrapperExecutionEngineBatchResultSetProcessing" xml:space="preserve">
|
||||
<value>Motor de ejecución de analizador contenedor lote ResultSet procesamiento por lotes: DataReader.FieldCount: {0} DataReader.RecordsAffected: {1}</value>
|
||||
</data>
|
||||
<data name="BatchParserWrapperExecutionEngineBatchResultSetFinished" xml:space="preserve">
|
||||
<value>Finalizó el elemento ResultSet analizador contenedor ejecución motor los lotes.</value>
|
||||
</data>
|
||||
<data name="BatchParserWrapperExecutionEngineBatchCancelling" xml:space="preserve">
|
||||
<value>Cancelando la ejecución por lotes del contenedor del analizador por lotes.</value>
|
||||
</data>
|
||||
<data name="EE_ScriptError_Warning" xml:space="preserve">
|
||||
<value>Advertencia de scripting.</value>
|
||||
</data>
|
||||
<data name="TroubleshootingAssistanceMessage" xml:space="preserve">
|
||||
<value>Para obtener más información acerca de este error, vea los temas de solución de problemas en la documentación del producto.</value>
|
||||
</data>
|
||||
<data name="BatchParser_CircularReference" xml:space="preserve">
|
||||
<value>El archivo '{0}' se incluyó recursivamente.</value>
|
||||
</data>
|
||||
<data name="BatchParser_CommentNotTerminated" xml:space="preserve">
|
||||
<value>Falta la marca de final de comentario ' * /'.</value>
|
||||
</data>
|
||||
<data name="BatchParser_StringNotTerminated" xml:space="preserve">
|
||||
<value>Sin comilla de cierre después de la cadena de caracteres.</value>
|
||||
</data>
|
||||
<data name="BatchParser_IncorrectSyntax" xml:space="preserve">
|
||||
<value>Se encontró sintaxis incorrecta al analizar '{0}'.</value>
|
||||
</data>
|
||||
<data name="BatchParser_VariableNotDefined" xml:space="preserve">
|
||||
<value>La variable {0} no está definida.</value>
|
||||
</data>
|
||||
<data name="TestLocalizationConstant" xml:space="preserve">
|
||||
<value>prueba</value>
|
||||
</data>
|
||||
<data name="ErrorUnexpectedCodeObjectType" xml:space="preserve">
|
||||
<value>No se puede convertir el SqlCodeObject del Tipo {0} al Tipo {1}</value>
|
||||
</data>
|
||||
<data name="ErrorEmptyStringReplacement" xml:space="preserve">
|
||||
<value>Sustitución de una cadena vacía por una cadena vacía.</value>
|
||||
</data>
|
||||
<data name="EditDataSessionNotFound" xml:space="preserve">
|
||||
<value>Sesión de edición no existe,</value>
|
||||
</data>
|
||||
<data name="EditDataQueryNotCompleted" xml:space="preserve">
|
||||
<value>La consulta no ha finalizado.</value>
|
||||
</data>
|
||||
<data name="EditDataQueryImproperResultSets" xml:space="preserve">
|
||||
<value>La consulta no generó un único set de resultados</value>
|
||||
</data>
|
||||
<data name="EditDataFailedAddRow" xml:space="preserve">
|
||||
<value>Falló al agregar una nueva fila a la caché de actualización</value>
|
||||
</data>
|
||||
<data name="EditDataRowOutOfRange" xml:space="preserve">
|
||||
<value>El ID de la fila ingresado, se encuentra fuera del rango de filas de la caché de edición</value>
|
||||
</data>
|
||||
<data name="EditDataUpdatePending" xml:space="preserve">
|
||||
<value>Una actualización está pendiente para esta fila y debe de revertirse primero</value>
|
||||
</data>
|
||||
<data name="EditDataUpdateNotPending" xml:space="preserve">
|
||||
<value>El ID de la fila ingresado no tiene actualizaciones pendientes</value>
|
||||
</data>
|
||||
<data name="EditDataObjectMetadataNotFound" xml:space="preserve">
|
||||
<value>La metadata de la tabla o vista no pudo ser encontrada</value>
|
||||
</data>
|
||||
<data name="EditDataInvalidFormatBinary" xml:space="preserve">
|
||||
<value>Formato inválido para columna binaria</value>
|
||||
</data>
|
||||
<data name="EditDataInvalidFormatBoolean" xml:space="preserve">
|
||||
<value>Columnas del tipo boolean deben de ser numéricos 1 o 0, o tipo string true o false</value>
|
||||
</data>
|
||||
<data name="EditDataCreateScriptMissingValue" xml:space="preserve">
|
||||
<value>Falta un valor requerido de la celda</value>
|
||||
</data>
|
||||
<data name="EditDataDeleteSetCell" xml:space="preserve">
|
||||
<value>Existe una eliminación pendiente para esta fila, una actualización de celda no puede ser realizada.</value>
|
||||
</data>
|
||||
<data name="EditDataColumnIdOutOfRange" xml:space="preserve">
|
||||
<value>El ID de la columna debe de estar en el rango de columnas de la consulta.</value>
|
||||
</data>
|
||||
<data name="EditDataColumnCannotBeEdited" xml:space="preserve">
|
||||
<value>La columna no puede ser editada</value>
|
||||
</data>
|
||||
<data name="EditDataColumnNoKeyColumns" xml:space="preserve">
|
||||
<value>No se encontró ninguna columna clave</value>
|
||||
</data>
|
||||
<data name="EditDataScriptFilePathNull" xml:space="preserve">
|
||||
<value>Proporcione un nombre de archivo de salida</value>
|
||||
</data>
|
||||
<data name="EditDataUnsupportedObjectType" xml:space="preserve">
|
||||
<value>Objeto de base de datos {0} no puede ser usado para modificación.</value>
|
||||
</data>
|
||||
<data name="ConnectionServiceDbErrorDefaultNotConnected" xml:space="preserve">
|
||||
<value>SpecifiedUri '{0}' no tiene alguna conexión por defecto</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -120,451 +120,475 @@
|
||||
<data name="ConnectionServiceConnectErrorNullParams" xml:space="preserve">
|
||||
<value>Connection parameters cannot be null</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="ConnectionServiceListDbErrorNullOwnerUri" xml:space="preserve">
|
||||
<value>OwnerUri cannot be null or empty</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="ConnectionServiceListDbErrorNotConnected" xml:space="preserve">
|
||||
<value>SpecifiedUri '{0}' does not have existing connection</value>
|
||||
<comment>.
|
||||
Parameters: 0 - uri (string) </comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="ConnectionServiceDbErrorDefaultNotConnected" xml:space="preserve">
|
||||
<value>Specified URI '{0}' does not have a default connection</value>
|
||||
<comment>.
|
||||
Parameters: 0 - uri (string) </comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="ConnectionServiceConnStringInvalidAuthType" xml:space="preserve">
|
||||
<value>Invalid value '{0}' for AuthenticationType. Valid values are 'Integrated' and 'SqlLogin'.</value>
|
||||
<comment>.
|
||||
Parameters: 0 - authType (string) </comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="ConnectionServiceConnStringInvalidIntent" xml:space="preserve">
|
||||
<value>Invalid value '{0}' for ApplicationIntent. Valid values are 'ReadWrite' and 'ReadOnly'.</value>
|
||||
<comment>.
|
||||
Parameters: 0 - intent (string) </comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="ConnectionServiceConnectionCanceled" xml:space="preserve">
|
||||
<value>Connection canceled</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="ConnectionParamsValidateNullOwnerUri" xml:space="preserve">
|
||||
<value>OwnerUri cannot be null or empty</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="ConnectionParamsValidateNullConnection" xml:space="preserve">
|
||||
<value>Connection details object cannot be null</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="ConnectionParamsValidateNullServerName" xml:space="preserve">
|
||||
<value>ServerName cannot be null or empty</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="ConnectionParamsValidateNullSqlAuth" xml:space="preserve">
|
||||
<value>{0} cannot be null or empty when using SqlLogin authentication</value>
|
||||
<comment>.
|
||||
Parameters: 0 - component (string) </comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="ErrorUnexpectedCodeObjectType" xml:space="preserve">
|
||||
<value>Cannot convert SqlCodeObject Type {0} to Type {1}</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceCancelAlreadyCompleted" xml:space="preserve">
|
||||
<value>The query has already completed, it cannot be cancelled</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceCancelDisposeFailed" xml:space="preserve">
|
||||
<value>Query successfully cancelled, failed to dispose query. Owner URI not found.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceQueryCancelled" xml:space="preserve">
|
||||
<value>Query was canceled by user</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceSubsetBatchNotCompleted" xml:space="preserve">
|
||||
<value>The batch has not completed, yet</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceSubsetBatchOutOfRange" xml:space="preserve">
|
||||
<value>Batch index cannot be less than 0 or greater than the number of batches</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceSubsetResultSetOutOfRange" xml:space="preserve">
|
||||
<value>Result set index cannot be less than 0 or greater than the number of result sets</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceDataReaderByteCountInvalid" xml:space="preserve">
|
||||
<value>Maximum number of bytes to return must be greater than zero</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceDataReaderCharCountInvalid" xml:space="preserve">
|
||||
<value>Maximum number of chars to return must be greater than zero</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceDataReaderXmlCountInvalid" xml:space="preserve">
|
||||
<value>Maximum number of XML bytes to return must be greater than zero</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceFileWrapperWriteOnly" xml:space="preserve">
|
||||
<value>Access method cannot be write-only</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceFileWrapperNotInitialized" xml:space="preserve">
|
||||
<value>FileStreamWrapper must be initialized before performing operations</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceFileWrapperReadOnly" xml:space="preserve">
|
||||
<value>This FileStreamWrapper cannot be used for writing</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceAffectedOneRow" xml:space="preserve">
|
||||
<value>(1 row affected)</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceAffectedRows" xml:space="preserve">
|
||||
<value>({0} rows affected)</value>
|
||||
<comment>.
|
||||
Parameters: 0 - rows (long) </comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceCompletedSuccessfully" xml:space="preserve">
|
||||
<value>Commands completed successfully.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceErrorFormat" xml:space="preserve">
|
||||
<value>Msg {0}, Level {1}, State {2}, Line {3}{4}{5}</value>
|
||||
<comment>.
|
||||
Parameters: 0 - msg (int), 1 - lvl (int), 2 - state (int), 3 - line (int), 4 - newLine (string), 5 - message (string) </comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceQueryFailed" xml:space="preserve">
|
||||
<value>Query failed: {0}</value>
|
||||
<comment>.
|
||||
Parameters: 0 - message (string) </comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceColumnNull" xml:space="preserve">
|
||||
<value>(No column name)</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceRequestsNoQuery" xml:space="preserve">
|
||||
<value>The requested query does not exist</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceQueryInvalidOwnerUri" xml:space="preserve">
|
||||
<value>This editor is not connected to a database</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceQueryInProgress" xml:space="preserve">
|
||||
<value>A query is already in progress for this editor session. Please cancel this query or wait for its completion.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceMessageSenderNotSql" xml:space="preserve">
|
||||
<value>Sender for OnInfoMessage event must be a SqlConnection</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceResultSetAddNoRows" xml:space="preserve">
|
||||
<value>Cannot add row to result buffer, data reader does not contain rows</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceSaveAsResultSetNotComplete" xml:space="preserve">
|
||||
<value>Result cannot be saved until query execution has completed</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceSaveAsMiscStartingError" xml:space="preserve">
|
||||
<value>Internal error occurred while starting save task</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceSaveAsInProgress" xml:space="preserve">
|
||||
<value>A save request to the same path is in progress</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceSaveAsFail" xml:space="preserve">
|
||||
<value>Failed to save {0}: {1}</value>
|
||||
<comment>.
|
||||
Parameters: 0 - fileName (string), 1 - message (string) </comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceResultSetNotRead" xml:space="preserve">
|
||||
<value>Cannot read subset unless the results have been read from the server</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceResultSetStartRowOutOfRange" xml:space="preserve">
|
||||
<value>Start row cannot be less than 0 or greater than the number of rows in the result set</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceResultSetRowCountOutOfRange" xml:space="preserve">
|
||||
<value>Row count must be a positive integer</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceResultSetNoColumnSchema" xml:space="preserve">
|
||||
<value>Could not retrieve column schema for result set</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceExecutionPlanNotFound" xml:space="preserve">
|
||||
<value>Could not retrieve an execution plan from the result set </value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="PeekDefinitionAzureError" xml:space="preserve">
|
||||
<value>This feature is currently not supported on Azure SQL DB and Data Warehouse: {0}</value>
|
||||
<comment>.
|
||||
Parameters: 0 - errorMessage (string) </comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="PeekDefinitionError" xml:space="preserve">
|
||||
<value>An unexpected error occurred during Peek Definition execution: {0}</value>
|
||||
<comment>.
|
||||
Parameters: 0 - errorMessage (string) </comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="PeekDefinitionNoResultsError" xml:space="preserve">
|
||||
<value>No results were found.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="PeekDefinitionDatabaseError" xml:space="preserve">
|
||||
<value>No database object was retrieved.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="PeekDefinitionNotConnectedError" xml:space="preserve">
|
||||
<value>Please connect to a server.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="PeekDefinitionTimedoutError" xml:space="preserve">
|
||||
<value>Operation timed out.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="PeekDefinitionTypeNotSupportedError" xml:space="preserve">
|
||||
<value>This object type is currently not supported by this feature.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="ErrorEmptyStringReplacement" xml:space="preserve">
|
||||
<value>Replacement of an empty string by an empty string.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="WorkspaceServicePositionLineOutOfRange" xml:space="preserve">
|
||||
<value>Position is outside of file line range</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="WorkspaceServicePositionColumnOutOfRange" xml:space="preserve">
|
||||
<value>Position is outside of column range for line {0}</value>
|
||||
<comment>.
|
||||
Parameters: 0 - line (int) </comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="WorkspaceServiceBufferPositionOutOfOrder" xml:space="preserve">
|
||||
<value>Start position ({0}, {1}) must come before or be equal to the end position ({2}, {3})</value>
|
||||
<comment>.
|
||||
Parameters: 0 - sLine (int), 1 - sCol (int), 2 - eLine (int), 3 - eCol (int) </comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EditDataObjectNotFound" xml:space="preserve">
|
||||
<value>Table or view requested for edit could not be found</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
<data name="EditDataSessionNotFound" xml:space="preserve">
|
||||
<value>Edit session does not exist.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EditDataSessionAlreadyExists" xml:space="preserve">
|
||||
<value>Edit session already exists.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
<data name="EditDataSessionNotInitialized" xml:space="preserve">
|
||||
<value>Edit session has not been initialized</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
<data name="EditDataSessionAlreadyInitialized" xml:space="preserve">
|
||||
<value>Edit session has already been initialized</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
<data name="EditDataSessionAlreadyInitializing" xml:space="preserve">
|
||||
<value>Edit session has already been initialized or is in the process of initializing</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
<data name="EditDataUnsupportedObjectType" xml:space="preserve">
|
||||
<value>Database object {0} cannot be used for editing.</value>
|
||||
<comment>.
|
||||
Parameters: 0 - typeName (string) </comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EditDataQueryFailed" xml:space="preserve">
|
||||
<value>Query execution failed, see messages for details</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
<data name="EditDataQueryNotCompleted" xml:space="preserve">
|
||||
<value>Query has not completed execution</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EditDataQueryImproperResultSets" xml:space="preserve">
|
||||
<value>Query did not generate exactly one result set</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EditDataFailedAddRow" xml:space="preserve">
|
||||
<value>Failed to add new row to update cache</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EditDataRowOutOfRange" xml:space="preserve">
|
||||
<value>Given row ID is outside the range of rows in the edit cache</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EditDataUpdatePending" xml:space="preserve">
|
||||
<value>An update is already pending for this row and must be reverted first</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EditDataUpdateNotPending" xml:space="preserve">
|
||||
<value>Given row ID does not have pending update</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EditDataColumnUpdateNotPending" xml:space="preserve">
|
||||
<value>Give column ID does not have pending update</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EditDataObjectMetadataNotFound" xml:space="preserve">
|
||||
<value>Table or view metadata could not be found</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EditDataInvalidFormatBinary" xml:space="preserve">
|
||||
<value>Invalid format for binary column</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EditDataInvalidFormatBoolean" xml:space="preserve">
|
||||
<value>Allowed values for boolean columns are 0, 1, "true", or "false"</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EditDataCreateScriptMissingValue" xml:space="preserve">
|
||||
<value>A required cell value is missing</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EditDataDeleteSetCell" xml:space="preserve">
|
||||
<value>A delete is pending for this row, a cell update cannot be applied.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EditDataColumnIdOutOfRange" xml:space="preserve">
|
||||
<value>Column ID must be in the range of columns for the query</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EditDataColumnCannotBeEdited" xml:space="preserve">
|
||||
<value>Column cannot be edited</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EditDataColumnNoKeyColumns" xml:space="preserve">
|
||||
<value>No key columns were found</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EditDataScriptFilePathNull" xml:space="preserve">
|
||||
<value>An output filename must be provided</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EditDataCommitInProgress" xml:space="preserve">
|
||||
<value>A commit task is in progress. Please wait for completion.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EditDataComputedColumnPlaceholder" xml:space="preserve">
|
||||
<value><TBD></value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EditDataInitializeInProgress" xml:space="preserve">
|
||||
<value>Another edit data initialize is in progress for this owner URI. Please wait for completion.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EditDataTimeOver24Hrs" xml:space="preserve">
|
||||
<value>TIME column values must be between 00:00:00.0000000 and 23:59:59.9999999</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EditDataNullNotAllowed" xml:space="preserve">
|
||||
<value>NULL is not allowed for this column</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EE_BatchSqlMessageNoProcedureInfo" xml:space="preserve">
|
||||
<value>Msg {0}, Level {1}, State {2}, Line {3}</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EE_BatchSqlMessageWithProcedureInfo" xml:space="preserve">
|
||||
<value>Msg {0}, Level {1}, State {2}, Procedure {3}, Line {4}</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EE_BatchSqlMessageNoLineInfo" xml:space="preserve">
|
||||
<value>Msg {0}, Level {1}, State {2}</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EE_BatchError_Exception" xml:space="preserve">
|
||||
<value>An error occurred while the batch was being processed. The error message is: {0}</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EE_BatchExecutionInfo_RowsAffected" xml:space="preserve">
|
||||
<value>({0} row(s) affected)</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EE_ExecutionNotYetCompleteError" xml:space="preserve">
|
||||
<value>The previous execution is not yet complete.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EE_ScriptError_Error" xml:space="preserve">
|
||||
<value>A scripting error occurred.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EE_ScriptError_ParsingSyntax" xml:space="preserve">
|
||||
<value>Incorrect syntax was encountered while {0} was being parsed.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EE_ScriptError_FatalError" xml:space="preserve">
|
||||
<value>A fatal error occurred.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EE_ExecutionInfo_FinalizingLoop" xml:space="preserve">
|
||||
<value>Execution completed {0} times...</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EE_ExecutionInfo_QueryCancelledbyUser" xml:space="preserve">
|
||||
<value>You cancelled the query.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EE_BatchExecutionError_Halting" xml:space="preserve">
|
||||
<value>An error occurred while the batch was being executed.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EE_BatchExecutionError_Ignoring" xml:space="preserve">
|
||||
<value>An error occurred while the batch was being executed, but the error has been ignored.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EE_ExecutionInfo_InitilizingLoop" xml:space="preserve">
|
||||
<value>Starting execution loop of {0} times...</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EE_ExecutionError_CommandNotSupported" xml:space="preserve">
|
||||
<value>Command {0} is not supported.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EE_ExecutionError_VariableNotFound" xml:space="preserve">
|
||||
<value>The variable {0} could not be found.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="BatchParserWrapperExecutionEngineError" xml:space="preserve">
|
||||
<value>SQL Execution error: {0}</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="BatchParserWrapperExecutionError" xml:space="preserve">
|
||||
<value>Batch parser wrapper execution: {0} found... at line {1}: {2} Description: {3}</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="BatchParserWrapperExecutionEngineBatchMessage" xml:space="preserve">
|
||||
<value>Batch parser wrapper execution engine batch message received: Message: {0} Detailed message: {1}</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="BatchParserWrapperExecutionEngineBatchResultSetProcessing" xml:space="preserve">
|
||||
<value>Batch parser wrapper execution engine batch ResultSet processing: DataReader.FieldCount: {0} DataReader.RecordsAffected: {1}</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="BatchParserWrapperExecutionEngineBatchResultSetFinished" xml:space="preserve">
|
||||
<value>Batch parser wrapper execution engine batch ResultSet finished.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="BatchParserWrapperExecutionEngineBatchCancelling" xml:space="preserve">
|
||||
<value>Canceling batch parser wrapper batch execution.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EE_ScriptError_Warning" xml:space="preserve">
|
||||
<value>Scripting warning.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="TroubleshootingAssistanceMessage" xml:space="preserve">
|
||||
<value>For more information about this error, see the troubleshooting topics in the product documentation.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="BatchParser_CircularReference" xml:space="preserve">
|
||||
<value>File '{0}' recursively included.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="BatchParser_CommentNotTerminated" xml:space="preserve">
|
||||
<value>Missing end comment mark '*/'.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="BatchParser_StringNotTerminated" xml:space="preserve">
|
||||
<value>Unclosed quotation mark after the character string.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="BatchParser_IncorrectSyntax" xml:space="preserve">
|
||||
<value>Incorrect syntax was encountered while parsing '{0}'.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="BatchParser_VariableNotDefined" xml:space="preserve">
|
||||
<value>Variable {0} is not defined.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="TestLocalizationConstant" xml:space="preserve">
|
||||
<value>EN_LOCALIZATION</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="SqlScriptFormatterDecimalMissingPrecision" xml:space="preserve">
|
||||
<value>Decimal column is missing numeric precision or numeric scale</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</root>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -164,10 +164,22 @@ WorkspaceServiceBufferPositionOutOfOrder(int sLine, int sCol, int eLine, int eCo
|
||||
############################################################################
|
||||
# Edit Data Service
|
||||
|
||||
EditDataObjectNotFound = Table or view requested for edit could not be found
|
||||
|
||||
EditDataSessionNotFound = Edit session does not exist.
|
||||
|
||||
EditDataSessionAlreadyExists = Edit session already exists.
|
||||
|
||||
EditDataSessionNotInitialized = Edit session has not been initialized
|
||||
|
||||
EditDataSessionAlreadyInitialized = Edit session has already been initialized
|
||||
|
||||
EditDataSessionAlreadyInitializing = Edit session has already been initialized or is in the process of initializing
|
||||
|
||||
EditDataUnsupportedObjectType(string typeName) = Database object {0} cannot be used for editing.
|
||||
|
||||
EditDataQueryFailed = Query execution failed, see messages for details
|
||||
|
||||
EditDataQueryNotCompleted = Query has not completed execution
|
||||
|
||||
EditDataQueryImproperResultSets = Query did not generate exactly one result set
|
||||
|
||||
@@ -561,6 +561,36 @@
|
||||
<target state="new">NULL is not allowed for this column</target>
|
||||
<note></note>
|
||||
</trans-unit>
|
||||
<trans-unit id="EditDataObjectNotFound">
|
||||
<source>Table or view requested for edit could not be found</source>
|
||||
<target state="new">Table or view requested to edit could not be found</target>
|
||||
<note></note>
|
||||
</trans-unit>
|
||||
<trans-unit id="EditDataSessionAlreadyExists">
|
||||
<source>Edit session already exists.</source>
|
||||
<target state="new">Edit session already exists.</target>
|
||||
<note></note>
|
||||
</trans-unit>
|
||||
<trans-unit id="EditDataSessionNotInitialized">
|
||||
<source>Edit session has not been initialized</source>
|
||||
<target state="new">Edit session has not been initialized</target>
|
||||
<note></note>
|
||||
</trans-unit>
|
||||
<trans-unit id="EditDataSessionAlreadyInitialized">
|
||||
<source>Edit session has already been initialized</source>
|
||||
<target state="new">Edit session has already been initialized</target>
|
||||
<note></note>
|
||||
</trans-unit>
|
||||
<trans-unit id="EditDataSessionAlreadyInitializing">
|
||||
<source>Edit session has already been initialized or is in the process of initializing</source>
|
||||
<target state="new">Edit session has already been initialized or is in the process of initializing</target>
|
||||
<note></note>
|
||||
</trans-unit>
|
||||
<trans-unit id="EditDataQueryFailed">
|
||||
<source>Query execution failed, see messages for details</source>
|
||||
<target state="new">Query execution failed, see messages for details</target>
|
||||
<note></note>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
||||
@@ -29,7 +29,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
|
||||
AddSupportedType(DeclarationType.Synonym, GetSynonymScripts, "Synonym", "");
|
||||
AddSupportedType(DeclarationType.ScalarValuedFunction, GetScalarValuedFunctionScripts, "Function", "scalar-valued function");
|
||||
AddSupportedType(DeclarationType.TableValuedFunction, GetTableValuedFunctionScripts, "Function", "table-valued function");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Script a Table using SMO
|
||||
@@ -50,7 +50,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
|
||||
Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetTableScripts : " + ex.Message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Script a View using SMO
|
||||
@@ -71,7 +71,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
|
||||
Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetViewScripts : " + ex.Message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Script a StoredProcedure using SMO
|
||||
@@ -92,7 +92,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
|
||||
Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetStoredProcedureScripts : " + ex.Message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Script a UserDefinedDataType using SMO
|
||||
@@ -113,7 +113,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
|
||||
Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetUserDefinedDataTypeScripts : " + ex.Message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Script a UserDefinedTableType using SMO
|
||||
@@ -134,7 +134,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
|
||||
Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetUserDefinedTableTypeScripts : " + ex.Message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Script a Synonym using SMO
|
||||
@@ -155,7 +155,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
|
||||
Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetSynonymScripts : " + ex.Message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Script a ScalarValuedFunction using SMO
|
||||
@@ -176,7 +176,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
|
||||
Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetScalarValuedFunctionScripts : " + ex.Message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Script a TableValuedFunction using SMO
|
||||
@@ -197,7 +197,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
|
||||
Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetTableValuedFunctionScripts : " + ex.Message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,13 +7,13 @@ using System.Collections.Generic;
|
||||
using System.Data.Common;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SqlTools.ServiceLayer.EditData;
|
||||
using Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement;
|
||||
using Microsoft.SqlTools.ServiceLayer.QueryExecution;
|
||||
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.Test.Common;
|
||||
using Microsoft.SqlTools.ServiceLayer.UnitTests.Utility;
|
||||
using Microsoft.SqlTools.Utility;
|
||||
using Moq;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
@@ -22,18 +22,49 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
{
|
||||
public const string OwnerUri = "testFile";
|
||||
|
||||
public static IEditTableMetadata GetStandardMetadata(DbColumn[] columns, bool allKeys = true, bool isMemoryOptimized = false)
|
||||
public static async Task<EditSession> GetCustomSession(Query q, EditTableMetadata etm)
|
||||
{
|
||||
// Create a Column Metadata Provider
|
||||
// Mock metadata factory
|
||||
Mock<IEditMetadataFactory> metaFactory = new Mock<IEditMetadataFactory>();
|
||||
metaFactory
|
||||
.Setup(f => f.GetObjectMetadata(It.IsAny<DbConnection>(), It.IsAny<string>(), It.IsAny<string>()))
|
||||
.Returns(etm);
|
||||
|
||||
EditSession session = new EditSession(metaFactory.Object, "tbl", "tbl");
|
||||
|
||||
EditSession.Connector connector = () => Task.FromResult<DbConnection>(null);
|
||||
EditSession.QueryRunner queryRunner = (s) => Task.FromResult(new EditSession.EditSessionQueryExecutionState(q));
|
||||
|
||||
session.Initialize(connector, queryRunner, () => Task.FromResult(0), (e) => Task.FromResult(0));
|
||||
await session.InitializeTask;
|
||||
return session;
|
||||
}
|
||||
|
||||
public static EditTableMetadata GetStandardMetadata(DbColumn[] columns, bool isMemoryOptimized = false)
|
||||
{
|
||||
// Create column metadata providers
|
||||
var columnMetas = columns.Select((c, i) =>
|
||||
new EditColumnWrapper
|
||||
{
|
||||
var ecm = new EditColumnMetadata
|
||||
{
|
||||
DbColumn = new DbColumnWrapper(c),
|
||||
EscapedName = c.ColumnName,
|
||||
Ordinal = i,
|
||||
IsKey = c.IsIdentity.HasTrue()
|
||||
}).ToArray();
|
||||
return GetMetadataProvider(columnMetas, allKeys, isMemoryOptimized);
|
||||
Ordinal = i
|
||||
};
|
||||
return ecm;
|
||||
}).ToArray();
|
||||
|
||||
// Create column wrappers
|
||||
var columnWrappers = columns.Select(c => new DbColumnWrapper(c)).ToArray();
|
||||
|
||||
// Create the table metadata
|
||||
EditTableMetadata editTableMetadata = new EditTableMetadata
|
||||
{
|
||||
Columns = columnMetas,
|
||||
EscapedMultipartName = "tbl",
|
||||
IsMemoryOptimized = isMemoryOptimized
|
||||
};
|
||||
editTableMetadata.Extend(columnWrappers);
|
||||
return editTableMetadata;
|
||||
}
|
||||
|
||||
public static DbColumn[] GetColumns(bool includeIdentity)
|
||||
@@ -42,7 +73,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
|
||||
if (includeIdentity)
|
||||
{
|
||||
columns.Add(new TestDbColumn("id", true));
|
||||
columns.Add(new TestDbColumn("id") {IsKey = true, IsIdentity = true, IsAutoIncrement = true});
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
@@ -52,7 +83,14 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
return columns.ToArray();
|
||||
}
|
||||
|
||||
public static ResultSet GetResultSet(DbColumn[] columns, bool includeIdentity, int rowCount = 1)
|
||||
public static async Task<Query> GetQuery(DbColumn[] columns, bool includIdentity, int rowCount = 1)
|
||||
{
|
||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
||||
q.Batches[0].ResultSets[0] = await GetResultSet(columns, includIdentity, rowCount);
|
||||
return q;
|
||||
}
|
||||
|
||||
public static async Task<ResultSet> GetResultSet(DbColumn[] columns, bool includeIdentity, int rowCount = 1)
|
||||
{
|
||||
IEnumerable<object[]> rows = includeIdentity
|
||||
? Enumerable.Repeat(new object[] { "id", "1", "2", "3" }, rowCount)
|
||||
@@ -60,7 +98,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
var testResultSet = new TestResultSet(columns, rows);
|
||||
var reader = new TestDbDataReader(new[] { testResultSet });
|
||||
var resultSet = new ResultSet(0, 0, MemoryFileSystem.GetFileStreamFactory());
|
||||
resultSet.ReadResultToEnd(reader, CancellationToken.None).Wait();
|
||||
await resultSet.ReadResultToEnd(reader, CancellationToken.None);
|
||||
return resultSet;
|
||||
}
|
||||
|
||||
@@ -82,26 +120,5 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
rc.SetCell(i, "123");
|
||||
}
|
||||
}
|
||||
|
||||
public static IEditTableMetadata GetMetadataProvider(EditColumnWrapper[] columnMetas, bool allKeys = false, bool isMemoryOptimized = false)
|
||||
{
|
||||
// Create a table metadata provider
|
||||
var tableMetaMock = new Mock<IEditTableMetadata>();
|
||||
if (allKeys)
|
||||
{
|
||||
// All columns should be returned as "keys"
|
||||
tableMetaMock.Setup(m => m.KeyColumns).Returns(columnMetas);
|
||||
}
|
||||
else
|
||||
{
|
||||
// All identity columns should be returned as keys
|
||||
tableMetaMock.Setup(m => m.KeyColumns).Returns(columnMetas.Where(c => c.DbColumn.IsIdentity.HasTrue()).ToList());
|
||||
}
|
||||
tableMetaMock.Setup(m => m.Columns).Returns(columnMetas);
|
||||
tableMetaMock.Setup(m => m.IsMemoryOptimized).Returns(isMemoryOptimized);
|
||||
tableMetaMock.Setup(m => m.EscapedMultipartName).Returns("tbl");
|
||||
|
||||
return tableMetaMock.Object;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,13 +22,13 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
public class RowCreateTests
|
||||
{
|
||||
[Fact]
|
||||
public void RowCreateConstruction()
|
||||
public async Task RowCreateConstruction()
|
||||
{
|
||||
// Setup: Create the values to store
|
||||
const long rowId = 100;
|
||||
DbColumn[] columns = Common.GetColumns(false);
|
||||
ResultSet rs = Common.GetResultSet(columns, false);
|
||||
IEditTableMetadata etm = Common.GetStandardMetadata(columns);
|
||||
ResultSet rs = await Common.GetResultSet(columns, false);
|
||||
EditTableMetadata etm = Common.GetStandardMetadata(columns);
|
||||
|
||||
// If: I create a RowCreate instance
|
||||
RowCreate rc = new RowCreate(rowId, rs, etm);
|
||||
@@ -42,13 +42,13 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public void GetScript(bool includeIdentity)
|
||||
public async Task GetScript(bool includeIdentity)
|
||||
{
|
||||
// Setup: Generate the parameters for the row create
|
||||
const long rowId = 100;
|
||||
DbColumn[] columns = Common.GetColumns(includeIdentity);
|
||||
ResultSet rs = Common.GetResultSet(columns, includeIdentity);
|
||||
IEditTableMetadata etm = Common.GetStandardMetadata(columns);
|
||||
ResultSet rs = await Common.GetResultSet(columns, includeIdentity);
|
||||
EditTableMetadata etm = Common.GetStandardMetadata(columns);
|
||||
|
||||
// If: I ask for a script to be generated without an identity column
|
||||
RowCreate rc = new RowCreate(rowId, rs, etm);
|
||||
@@ -74,10 +74,10 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetScriptMissingCell()
|
||||
public async Task GetScriptMissingCell()
|
||||
{
|
||||
// Setup: Generate the parameters for the row create
|
||||
RowCreate rc = GetStandardRowCreate();
|
||||
RowCreate rc = await GetStandardRowCreate();
|
||||
|
||||
// If: I ask for a script to be generated without setting any values
|
||||
// Then: An exception should be thrown for missing cells
|
||||
@@ -93,8 +93,8 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
// ... Generate the parameters for the row create
|
||||
const long rowId = 100;
|
||||
DbColumn[] columns = Common.GetColumns(includeIdentity);
|
||||
ResultSet rs = Common.GetResultSet(columns, includeIdentity);
|
||||
IEditTableMetadata etm = Common.GetStandardMetadata(columns);
|
||||
ResultSet rs = await Common.GetResultSet(columns, includeIdentity);
|
||||
EditTableMetadata etm = Common.GetStandardMetadata(columns);
|
||||
|
||||
// ... Setup a db reader for the result of an insert
|
||||
var newRowReader = Common.GetNewRowDataReader(columns, includeIdentity);
|
||||
@@ -110,13 +110,13 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public void GetCommand(bool includeIdentity)
|
||||
public async Task GetCommand(bool includeIdentity)
|
||||
{
|
||||
// Setup:
|
||||
// ... Create a row create with cell updates
|
||||
const long rowId = 100;
|
||||
var columns = Common.GetColumns(includeIdentity);
|
||||
var rs = Common.GetResultSet(columns, includeIdentity);
|
||||
var rs = await Common.GetResultSet(columns, includeIdentity);
|
||||
var etm = Common.GetStandardMetadata(columns);
|
||||
RowCreate rc = new RowCreate(rowId, rs, etm);
|
||||
Common.AddCells(rc, includeIdentity);
|
||||
@@ -159,10 +159,10 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetCommandNullConnection()
|
||||
public async Task GetCommandNullConnection()
|
||||
{
|
||||
// Setup: Create a row create
|
||||
RowCreate rc = GetStandardRowCreate();
|
||||
RowCreate rc = await GetStandardRowCreate();
|
||||
|
||||
|
||||
// If: I attempt to create a command with a null connection
|
||||
@@ -171,10 +171,10 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetCommandMissingCell()
|
||||
public async Task GetCommandMissingCell()
|
||||
{
|
||||
// Setup: Generate the parameters for the row create
|
||||
RowCreate rc = GetStandardRowCreate();
|
||||
RowCreate rc = await GetStandardRowCreate();
|
||||
var mockConn = new TestSqlConnection(null);
|
||||
|
||||
// If: I ask for a script to be generated without setting any values
|
||||
@@ -183,10 +183,10 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetEditRowNoAdditions()
|
||||
public async Task GetEditRowNoAdditions()
|
||||
{
|
||||
// Setup: Generate a standard row create
|
||||
RowCreate rc = GetStandardRowCreate();
|
||||
RowCreate rc = await GetStandardRowCreate();
|
||||
|
||||
// If: I request an edit row from the row create
|
||||
EditRow er = rc.GetEditRow(null);
|
||||
@@ -209,10 +209,10 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetEditRowWithAdditions()
|
||||
public async Task GetEditRowWithAdditions()
|
||||
{
|
||||
// Setp: Generate a row create with a cell added to it
|
||||
RowCreate rc = GetStandardRowCreate();
|
||||
RowCreate rc = await GetStandardRowCreate();
|
||||
rc.SetCell(0, "foo");
|
||||
|
||||
// If: I request an edit row from the row create
|
||||
@@ -244,20 +244,20 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
[InlineData(-1)] // Negative
|
||||
[InlineData(3)] // At edge of acceptable values
|
||||
[InlineData(100)] // Way too large value
|
||||
public void SetCellOutOfRange(int columnId)
|
||||
public async Task SetCellOutOfRange(int columnId)
|
||||
{
|
||||
// Setup: Generate a row create
|
||||
RowCreate rc = GetStandardRowCreate();
|
||||
RowCreate rc = await GetStandardRowCreate();
|
||||
|
||||
// If: I attempt to set a cell on a column that is out of range, I should get an exception
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => rc.SetCell(columnId, string.Empty));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SetCellNoChange()
|
||||
public async Task SetCellNoChange()
|
||||
{
|
||||
// Setup: Generate a row create
|
||||
RowCreate rc = GetStandardRowCreate();
|
||||
RowCreate rc = await GetStandardRowCreate();
|
||||
|
||||
// If: I set a cell in the newly created row to something that doesn't need changing
|
||||
EditUpdateCellResult eucr = rc.SetCell(0, "1");
|
||||
@@ -278,16 +278,20 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SetCellHasCorrections()
|
||||
public async Task SetCellHasCorrections()
|
||||
{
|
||||
// Setup:
|
||||
// ... Generate a result set with a single binary column
|
||||
DbColumn[] cols = {new TestDbColumn("bin", "binary", typeof(byte[]))};
|
||||
DbColumn[] cols = {new TestDbColumn
|
||||
{
|
||||
DataType = typeof(byte[]),
|
||||
DataTypeName = "binary"
|
||||
}};
|
||||
object[][] rows = {};
|
||||
var testResultSet = new TestResultSet(cols, rows);
|
||||
var testReader = new TestDbDataReader(new[] {testResultSet});
|
||||
var rs = new ResultSet(0, 0, MemoryFileSystem.GetFileStreamFactory());
|
||||
rs.ReadResultToEnd(testReader, CancellationToken.None).Wait();
|
||||
await rs.ReadResultToEnd(testReader, CancellationToken.None);
|
||||
|
||||
// ... Generate the metadata
|
||||
var etm = Common.GetStandardMetadata(cols);
|
||||
@@ -314,10 +318,10 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SetCellNull()
|
||||
public async Task SetCellNull()
|
||||
{
|
||||
// Setup: Generate a row create
|
||||
RowCreate rc = GetStandardRowCreate();
|
||||
RowCreate rc = await GetStandardRowCreate();
|
||||
|
||||
// If: I set a cell in the newly created row to null
|
||||
EditUpdateCellResult eucr = rc.SetCell(0, "NULL");
|
||||
@@ -341,10 +345,10 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
[InlineData(-1)] // Negative
|
||||
[InlineData(3)] // At edge of acceptable values
|
||||
[InlineData(100)] // Way too large value
|
||||
public void RevertCellOutOfRange(int columnId)
|
||||
public async Task RevertCellOutOfRange(int columnId)
|
||||
{
|
||||
// Setup: Generate the row create
|
||||
RowCreate rc = GetStandardRowCreate();
|
||||
RowCreate rc = await GetStandardRowCreate();
|
||||
|
||||
// If: I attempt to revert a cell that is out of range
|
||||
// Then: I should get an exception
|
||||
@@ -352,10 +356,10 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RevertCellNotSet()
|
||||
public async Task RevertCellNotSet()
|
||||
{
|
||||
// Setup: Generate the row create
|
||||
RowCreate rc = GetStandardRowCreate();
|
||||
RowCreate rc = await GetStandardRowCreate();
|
||||
|
||||
// If: I attempt to revert a cell that has not been set
|
||||
string result = rc.RevertCell(0);
|
||||
@@ -369,10 +373,10 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RevertCellThatWasSet()
|
||||
public async Task RevertCellThatWasSet()
|
||||
{
|
||||
// Setup: Generate the row create
|
||||
RowCreate rc = GetStandardRowCreate();
|
||||
RowCreate rc = await GetStandardRowCreate();
|
||||
rc.SetCell(0, "1");
|
||||
|
||||
// If: I attempt to revert a cell that was set
|
||||
@@ -386,10 +390,10 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
Assert.Null(rc.newCells[0]);
|
||||
}
|
||||
|
||||
private static RowCreate GetStandardRowCreate()
|
||||
private static async Task<RowCreate> GetStandardRowCreate()
|
||||
{
|
||||
var cols = Common.GetColumns(false);
|
||||
var rs = Common.GetResultSet(cols, false);
|
||||
var rs = await Common.GetResultSet(cols, false);
|
||||
var etm = Common.GetStandardMetadata(cols);
|
||||
return new RowCreate(100, rs, etm);
|
||||
}
|
||||
|
||||
@@ -21,12 +21,12 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
public class RowDeleteTests
|
||||
{
|
||||
[Fact]
|
||||
public void RowDeleteConstruction()
|
||||
public async Task RowDeleteConstruction()
|
||||
{
|
||||
// Setup: Create the values to store
|
||||
DbColumn[] columns = Common.GetColumns(true);
|
||||
ResultSet rs = Common.GetResultSet(columns, true);
|
||||
IEditTableMetadata etm = Common.GetStandardMetadata(columns, false);
|
||||
ResultSet rs = await Common.GetResultSet(columns, true);
|
||||
EditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
||||
|
||||
// If: I create a RowCreate instance
|
||||
RowDelete rc = new RowDelete(100, rs, etm);
|
||||
@@ -40,11 +40,11 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public void GetScriptTest(bool isMemoryOptimized)
|
||||
public async Task GetScriptTest(bool isMemoryOptimized)
|
||||
{
|
||||
DbColumn[] columns = Common.GetColumns(true);
|
||||
ResultSet rs = Common.GetResultSet(columns, true);
|
||||
IEditTableMetadata etm = Common.GetStandardMetadata(columns, false, isMemoryOptimized);
|
||||
ResultSet rs = await Common.GetResultSet(columns, true);
|
||||
EditTableMetadata etm = Common.GetStandardMetadata(columns, isMemoryOptimized);
|
||||
|
||||
// If: I ask for a script to be generated for delete
|
||||
RowDelete rd = new RowDelete(0, rs, etm);
|
||||
@@ -68,7 +68,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
{
|
||||
// Setup: Generate the parameters for the row delete object
|
||||
var columns = Common.GetColumns(false);
|
||||
var rs = Common.GetResultSet(columns, false);
|
||||
var rs = await Common.GetResultSet(columns, false);
|
||||
var etm = Common.GetStandardMetadata(columns);
|
||||
|
||||
// If: I ask for the change to be applied
|
||||
@@ -84,13 +84,13 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
[InlineData(false, true)]
|
||||
[InlineData(true, false)]
|
||||
[InlineData(false, false)]
|
||||
public void GetCommand(bool includeIdentity, bool isMemoryOptimized)
|
||||
public async Task GetCommand(bool includeIdentity, bool isMemoryOptimized)
|
||||
{
|
||||
// Setup:
|
||||
// ... Create a row delete
|
||||
var columns = Common.GetColumns(includeIdentity);
|
||||
var rs = Common.GetResultSet(columns, includeIdentity);
|
||||
var etm = Common.GetStandardMetadata(columns, !includeIdentity, isMemoryOptimized);
|
||||
var rs = await Common.GetResultSet(columns, includeIdentity);
|
||||
var etm = Common.GetStandardMetadata(columns, isMemoryOptimized);
|
||||
RowDelete rd = new RowDelete(0, rs, etm);
|
||||
|
||||
// ... Mock db connection for building the command
|
||||
@@ -128,10 +128,10 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetCommandNullConnection()
|
||||
public async Task GetCommandNullConnection()
|
||||
{
|
||||
// Setup: Create a row delete
|
||||
RowDelete rd = GetStandardRowDelete();
|
||||
RowDelete rd = await GetStandardRowDelete();
|
||||
|
||||
// If: I attempt to create a command with a null connection
|
||||
// Then: It should throw an exception
|
||||
@@ -139,11 +139,11 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetEditRow()
|
||||
public async Task GetEditRow()
|
||||
{
|
||||
// Setup: Create a row delete
|
||||
var columns = Common.GetColumns(false);
|
||||
var rs = Common.GetResultSet(columns, false);
|
||||
var rs = await Common.GetResultSet(columns, false);
|
||||
var etm = Common.GetStandardMetadata(columns);
|
||||
RowDelete rd = new RowDelete(0, rs, etm);
|
||||
|
||||
@@ -173,10 +173,10 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetEditNullRow()
|
||||
public async Task GetEditNullRow()
|
||||
{
|
||||
// Setup: Create a row delete
|
||||
RowDelete rd = GetStandardRowDelete();
|
||||
RowDelete rd = await GetStandardRowDelete();
|
||||
|
||||
// If: I attempt to get an edit row with a null cached row
|
||||
// Then: I should get an exception
|
||||
@@ -184,10 +184,10 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SetCell()
|
||||
public async Task SetCell()
|
||||
{
|
||||
// Setup: Create a row delete
|
||||
RowDelete rd = GetStandardRowDelete();
|
||||
RowDelete rd = await GetStandardRowDelete();
|
||||
|
||||
// If: I set a cell on a delete row edit
|
||||
// Then: It should throw as invalid operation
|
||||
@@ -195,20 +195,20 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RevertCell()
|
||||
public async Task RevertCell()
|
||||
{
|
||||
// Setup: Create a row delete
|
||||
RowDelete rd = GetStandardRowDelete();
|
||||
RowDelete rd = await GetStandardRowDelete();
|
||||
|
||||
// If: I revert a cell on a delete row edit
|
||||
// Then: It should throw
|
||||
Assert.Throws<InvalidOperationException>(() => rd.RevertCell(0));
|
||||
}
|
||||
|
||||
private RowDelete GetStandardRowDelete()
|
||||
private async Task<RowDelete> GetStandardRowDelete()
|
||||
{
|
||||
var cols = Common.GetColumns(false);
|
||||
var rs = Common.GetResultSet(cols, false);
|
||||
var rs = await Common.GetResultSet(cols, false);
|
||||
var etm = Common.GetStandardMetadata(cols);
|
||||
return new RowDelete(0, rs, etm);
|
||||
}
|
||||
|
||||
@@ -25,12 +25,16 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(-1)] // Negative index
|
||||
[InlineData(2)] // Equal to count of columns
|
||||
[InlineData(100)] // Index larger than number of columns
|
||||
public void ValidateUpdatableColumnOutOfRange(int columnId)
|
||||
public async Task ValidateUpdatableColumnOutOfRange(int columnId)
|
||||
{
|
||||
// Setup: Create a result set
|
||||
ResultSet rs = GetResultSet(
|
||||
new DbColumn[] { new TestDbColumn("id", true), new TestDbColumn("col1")},
|
||||
ResultSet rs = await GetResultSet(
|
||||
new DbColumn[] {
|
||||
new TestDbColumn("id") {IsKey = true, IsAutoIncrement = true, IsIdentity = true},
|
||||
new TestDbColumn("col1")
|
||||
},
|
||||
new object[] { "id", "1" });
|
||||
|
||||
// If: I validate a column ID that is out of range
|
||||
@@ -40,11 +44,14 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ValidateUpdatableColumnNotUpdatable()
|
||||
public async Task ValidateUpdatableColumnNotUpdatable()
|
||||
{
|
||||
// Setup: Create a result set with an identity column
|
||||
ResultSet rs = GetResultSet(
|
||||
new DbColumn[] { new TestDbColumn("id", true), new TestDbColumn("col1") },
|
||||
ResultSet rs = await GetResultSet(
|
||||
new DbColumn[] {
|
||||
new TestDbColumn("id") {IsKey = true, IsAutoIncrement = true, IsIdentity = true},
|
||||
new TestDbColumn("col1")
|
||||
},
|
||||
new object[] { "id", "1" });
|
||||
|
||||
// If: I validate a column ID that is not updatable
|
||||
@@ -55,12 +62,12 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(GetWhereClauseIsNotNullData))]
|
||||
public void GetWhereClauseSimple(DbColumn col, object val, string nullClause)
|
||||
public async Task GetWhereClauseSimple(DbColumn col, object val, string nullClause)
|
||||
{
|
||||
// Setup: Create a result set and metadata provider with a single column
|
||||
var cols = new[] {col};
|
||||
ResultSet rs = GetResultSet(cols, new[] {val});
|
||||
IEditTableMetadata etm = Common.GetStandardMetadata(cols);
|
||||
ResultSet rs = await GetResultSet(cols, new[] {val});
|
||||
EditTableMetadata etm = Common.GetStandardMetadata(cols);
|
||||
|
||||
RowEditTester rt = new RowEditTester(rs, etm);
|
||||
rt.ValidateWhereClauseSingleKey(nullClause);
|
||||
@@ -71,42 +78,69 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
get
|
||||
{
|
||||
yield return new object[] {new TestDbColumn("col"), DBNull.Value, "IS NULL"};
|
||||
yield return new object[] {new TestDbColumn("col", "VARBINARY", typeof(byte[])), new byte[5], "IS NOT NULL"};
|
||||
yield return new object[] {new TestDbColumn("col", "TEXT", typeof(string)), "abc", "IS NOT NULL"};
|
||||
yield return new object[] {new TestDbColumn("col", "NTEXT", typeof(string)), "abc", "IS NOT NULL"};
|
||||
yield return new object[] {
|
||||
new TestDbColumn
|
||||
{
|
||||
DataTypeName = "BINARY",
|
||||
DataType = typeof(byte[])
|
||||
},
|
||||
new byte[5],
|
||||
"IS NOT NULL"
|
||||
};
|
||||
yield return new object[]
|
||||
{
|
||||
new TestDbColumn
|
||||
{
|
||||
DataType = typeof(string),
|
||||
DataTypeName = "TEXT"
|
||||
},
|
||||
"abc",
|
||||
"IS NOT NULL"
|
||||
};
|
||||
yield return new object[]
|
||||
{
|
||||
new TestDbColumn
|
||||
{
|
||||
DataType = typeof(string),
|
||||
DataTypeName = "NTEXT",
|
||||
|
||||
},
|
||||
"abc",
|
||||
"IS NOT NULL"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetWhereClauseMultipleKeyColumns()
|
||||
public async Task GetWhereClauseMultipleKeyColumns()
|
||||
{
|
||||
// Setup: Create a result set and metadata provider with multiple key columns
|
||||
DbColumn[] cols = {new TestDbColumn("col1"), new TestDbColumn("col2")};
|
||||
ResultSet rs = GetResultSet(cols, new object[] {"abc", "def"});
|
||||
IEditTableMetadata etm = Common.GetStandardMetadata(cols);
|
||||
ResultSet rs = await GetResultSet(cols, new object[] {"abc", "def"});
|
||||
EditTableMetadata etm = Common.GetStandardMetadata(cols);
|
||||
|
||||
RowEditTester rt = new RowEditTester(rs, etm);
|
||||
rt.ValidateWhereClauseMultipleKeys();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetWhereClauseNoKeyColumns()
|
||||
public async Task GetWhereClauseNoKeyColumns()
|
||||
{
|
||||
// Setup: Create a result set and metadata provider with no key columns
|
||||
DbColumn[] cols = {new TestDbColumn("col1"), new TestDbColumn("col2")};
|
||||
ResultSet rs = GetResultSet(cols, new object[] {"abc", "def"});
|
||||
IEditTableMetadata etm = Common.GetStandardMetadata(new DbColumn[] {});
|
||||
ResultSet rs = await GetResultSet(cols, new object[] {"abc", "def"});
|
||||
EditTableMetadata etm = Common.GetStandardMetadata(new DbColumn[] {});
|
||||
|
||||
RowEditTester rt = new RowEditTester(rs, etm);
|
||||
rt.ValidateWhereClauseNoKeys();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SortingByTypeTest()
|
||||
public async Task SortingByTypeTest()
|
||||
{
|
||||
// Setup: Create a result set and metadata we can reuse
|
||||
var cols = Common.GetColumns(false);
|
||||
var rs = Common.GetResultSet(cols, false);
|
||||
var rs = await Common.GetResultSet(cols, false);
|
||||
var etm = Common.GetStandardMetadata(cols);
|
||||
|
||||
// If: I request to sort a list of the three different edit operations
|
||||
@@ -124,11 +158,11 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SortingUpdatesByRowIdTest()
|
||||
public async Task SortingUpdatesByRowIdTest()
|
||||
{
|
||||
// Setup: Create a result set and metadata we can reuse
|
||||
var cols = Common.GetColumns(false);
|
||||
var rs = Common.GetResultSet(cols, false, 4);
|
||||
var rs = await Common.GetResultSet(cols, false, 4);
|
||||
var etm = Common.GetStandardMetadata(cols);
|
||||
|
||||
// If: I sort 3 edit operations of the same type
|
||||
@@ -147,11 +181,11 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SortingCreatesByRowIdTest()
|
||||
public async Task SortingCreatesByRowIdTest()
|
||||
{
|
||||
// Setup: Create a result set and metadata we can reuse
|
||||
var cols = Common.GetColumns(false);
|
||||
var rs = Common.GetResultSet(cols, false);
|
||||
var rs = await Common.GetResultSet(cols, false);
|
||||
var etm = Common.GetStandardMetadata(cols);
|
||||
|
||||
// If: I sort 3 edit operations of the same type
|
||||
@@ -170,11 +204,11 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SortingDeletesByRowIdTest()
|
||||
public async Task SortingDeletesByRowIdTest()
|
||||
{
|
||||
// Setup: Create a result set and metadata we can reuse
|
||||
var cols = Common.GetColumns(false);
|
||||
var rs = Common.GetResultSet(cols, false);
|
||||
var rs = await Common.GetResultSet(cols, false);
|
||||
var etm = Common.GetStandardMetadata(cols);
|
||||
|
||||
// If: I sort 3 delete operations of the same type
|
||||
@@ -192,19 +226,19 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
Assert.Equal(1, rowEdits[2].RowId);
|
||||
}
|
||||
|
||||
private static ResultSet GetResultSet(DbColumn[] columns, object[] row)
|
||||
private static async Task<ResultSet> GetResultSet(DbColumn[] columns, object[] row)
|
||||
{
|
||||
object[][] rows = {row};
|
||||
var testResultSet = new TestResultSet(columns, rows);
|
||||
var testReader = new TestDbDataReader(new [] {testResultSet});
|
||||
var resultSet = new ResultSet(0,0, MemoryFileSystem.GetFileStreamFactory());
|
||||
resultSet.ReadResultToEnd(testReader, CancellationToken.None).Wait();
|
||||
await resultSet.ReadResultToEnd(testReader, CancellationToken.None);
|
||||
return resultSet;
|
||||
}
|
||||
|
||||
private class RowEditTester : RowEditBase
|
||||
{
|
||||
public RowEditTester(ResultSet rs, IEditTableMetadata meta) : base(0, rs, meta) { }
|
||||
public RowEditTester(ResultSet rs, EditTableMetadata meta) : base(0, rs, meta) { }
|
||||
|
||||
public void ValidateColumn(int columnId)
|
||||
{
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
// Setup: Create the values to store
|
||||
const long rowId = 0;
|
||||
ResultSet rs = QueryExecution.Common.GetBasicExecutedBatch().ResultSets[0];
|
||||
IEditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
||||
EditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
||||
|
||||
// If: I create a RowUpdate instance
|
||||
RowUpdate rc = new RowUpdate(rowId, rs, etm);
|
||||
@@ -40,10 +40,10 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SetCell()
|
||||
public async Task SetCell()
|
||||
{
|
||||
// Setup: Create a row update
|
||||
RowUpdate ru = GetStandardRowUpdate();
|
||||
RowUpdate ru = await GetStandardRowUpdate();
|
||||
|
||||
// If: I set a cell that can be updated
|
||||
EditUpdateCellResult eucr = ru.SetCell(0, "col1");
|
||||
@@ -69,7 +69,14 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
{
|
||||
// Setup:
|
||||
// ... Generate a result set with a single binary column
|
||||
DbColumn[] cols = { new TestDbColumn("bin", "binary", typeof(byte[])) };
|
||||
DbColumn[] cols =
|
||||
{
|
||||
new TestDbColumn
|
||||
{
|
||||
DataType = typeof(byte[]),
|
||||
DataTypeName = "binary"
|
||||
}
|
||||
};
|
||||
object[][] rows = { new object[]{new byte[] {0x00}}};
|
||||
var testResultSet = new TestResultSet(cols, rows);
|
||||
var testReader = new TestDbDataReader(new[] { testResultSet });
|
||||
@@ -102,12 +109,12 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SetCellImplicitRevertTest()
|
||||
public async Task SetCellImplicitRevertTest()
|
||||
{
|
||||
// Setup: Create a fake table to update
|
||||
DbColumn[] columns = Common.GetColumns(true);
|
||||
ResultSet rs = Common.GetResultSet(columns, true);
|
||||
IEditTableMetadata etm = Common.GetStandardMetadata(columns);
|
||||
ResultSet rs = await Common.GetResultSet(columns, true);
|
||||
EditTableMetadata etm = Common.GetStandardMetadata(columns);
|
||||
|
||||
// If:
|
||||
// ... I add updates to all the cells in the row
|
||||
@@ -139,12 +146,12 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public void GetScriptTest(bool isMemoryOptimized)
|
||||
public async Task GetScriptTest(bool isMemoryOptimized)
|
||||
{
|
||||
// Setup: Create a fake table to update
|
||||
DbColumn[] columns = Common.GetColumns(true);
|
||||
ResultSet rs = Common.GetResultSet(columns, true);
|
||||
IEditTableMetadata etm = Common.GetStandardMetadata(columns, false, isMemoryOptimized);
|
||||
ResultSet rs = await Common.GetResultSet(columns, true);
|
||||
EditTableMetadata etm = Common.GetStandardMetadata(columns, isMemoryOptimized);
|
||||
|
||||
// If: I ask for a script to be generated for update
|
||||
RowUpdate ru = new RowUpdate(0, rs, etm);
|
||||
@@ -177,13 +184,13 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
[InlineData(true, false)]
|
||||
[InlineData(false, true)]
|
||||
[InlineData(false, false)]
|
||||
public void GetCommand(bool includeIdentity, bool isMemoryOptimized)
|
||||
public async Task GetCommand(bool includeIdentity, bool isMemoryOptimized)
|
||||
{
|
||||
// Setup:
|
||||
// ... Create a row update with cell updates
|
||||
var columns = Common.GetColumns(includeIdentity);
|
||||
var rs = Common.GetResultSet(columns, includeIdentity);
|
||||
var etm = Common.GetStandardMetadata(columns, !includeIdentity, isMemoryOptimized);
|
||||
var rs = await Common.GetResultSet(columns, includeIdentity);
|
||||
var etm = Common.GetStandardMetadata(columns, isMemoryOptimized);
|
||||
RowUpdate ru = new RowUpdate(0, rs, etm);
|
||||
Common.AddCells(ru, includeIdentity);
|
||||
|
||||
@@ -231,10 +238,10 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetCommandNullConnection()
|
||||
public async Task GetCommandNullConnection()
|
||||
{
|
||||
// Setup: Create a row update
|
||||
RowUpdate ru = GetStandardRowUpdate();
|
||||
RowUpdate ru = await GetStandardRowUpdate();
|
||||
|
||||
// If: I attempt to create a command with a null connection
|
||||
// Then: It should throw an exception
|
||||
@@ -242,11 +249,11 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetEditRow()
|
||||
public async Task GetEditRow()
|
||||
{
|
||||
// Setup: Create a row update with a cell set
|
||||
var columns = Common.GetColumns(false);
|
||||
var rs = Common.GetResultSet(columns, false);
|
||||
var rs = await Common.GetResultSet(columns, false);
|
||||
var etm = Common.GetStandardMetadata(columns);
|
||||
RowUpdate ru = new RowUpdate(0, rs, etm);
|
||||
ru.SetCell(0, "foo");
|
||||
@@ -282,10 +289,10 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetEditNullRow()
|
||||
public async Task GetEditNullRow()
|
||||
{
|
||||
// Setup: Create a row update
|
||||
RowUpdate ru = GetStandardRowUpdate();
|
||||
RowUpdate ru = await GetStandardRowUpdate();
|
||||
|
||||
// If: I attempt to get an edit row with a null cached row
|
||||
// Then: I should get an exception
|
||||
@@ -300,8 +307,8 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
// Setup:
|
||||
// ... Create a row update (no cell updates needed)
|
||||
var columns = Common.GetColumns(includeIdentity);
|
||||
var rs = Common.GetResultSet(columns, includeIdentity);
|
||||
var etm = Common.GetStandardMetadata(columns, !includeIdentity);
|
||||
var rs = await Common.GetResultSet(columns, includeIdentity);
|
||||
var etm = Common.GetStandardMetadata(columns);
|
||||
RowUpdate ru = new RowUpdate(0, rs, etm);
|
||||
long oldBytesWritten = rs.totalBytesWritten;
|
||||
|
||||
@@ -323,8 +330,8 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
// Setup:
|
||||
// ... Create a row update (no cell updates needed)
|
||||
var columns = Common.GetColumns(true);
|
||||
var rs = Common.GetResultSet(columns, true);
|
||||
var etm = Common.GetStandardMetadata(columns, false);
|
||||
var rs = await Common.GetResultSet(columns, true);
|
||||
var etm = Common.GetStandardMetadata(columns);
|
||||
RowUpdate ru = new RowUpdate(0, rs, etm);
|
||||
|
||||
// If: I ask for the changes to be applied with a null db reader
|
||||
@@ -336,12 +343,12 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
[InlineData(-1)] // Negative
|
||||
[InlineData(3)] // At edge of acceptable values
|
||||
[InlineData(100)] // Way too large value
|
||||
public void RevertCellOutOfRange(int columnId)
|
||||
public async Task RevertCellOutOfRange(int columnId)
|
||||
{
|
||||
// Setup:
|
||||
// ... Create a row update (no cell updates needed)
|
||||
var columns = Common.GetColumns(false);
|
||||
var rs = Common.GetResultSet(columns, false);
|
||||
var rs = await Common.GetResultSet(columns, false);
|
||||
var etm = Common.GetStandardMetadata(columns);
|
||||
RowUpdate ru = new RowUpdate(0, rs, etm);
|
||||
|
||||
@@ -351,12 +358,12 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RevertCellNotSet()
|
||||
public async Task RevertCellNotSet()
|
||||
{
|
||||
// Setup:
|
||||
// ... Create a row update (no cell updates needed)
|
||||
var columns = Common.GetColumns(true);
|
||||
var rs = Common.GetResultSet(columns, true);
|
||||
var rs = await Common.GetResultSet(columns, true);
|
||||
var etm = Common.GetStandardMetadata(columns);
|
||||
RowUpdate ru = new RowUpdate(0, rs, etm);
|
||||
|
||||
@@ -371,12 +378,12 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RevertCellThatWasSet()
|
||||
public async Task RevertCellThatWasSet()
|
||||
{
|
||||
// Setup:
|
||||
// ... Create a row update
|
||||
var columns = Common.GetColumns(false);
|
||||
var rs = Common.GetResultSet(columns, false);
|
||||
var rs = await Common.GetResultSet(columns, false);
|
||||
var etm = Common.GetStandardMetadata(columns);
|
||||
RowUpdate ru = new RowUpdate(0, rs, etm);
|
||||
ru.SetCell(0, "1");
|
||||
@@ -392,10 +399,10 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
Assert.DoesNotContain(0, ru.cellUpdates.Keys);
|
||||
}
|
||||
|
||||
private RowUpdate GetStandardRowUpdate()
|
||||
private async Task<RowUpdate> GetStandardRowUpdate()
|
||||
{
|
||||
var columns = Common.GetColumns(false);
|
||||
var rs = Common.GetResultSet(columns, false);
|
||||
var rs = await Common.GetResultSet(columns, false);
|
||||
var etm = Common.GetStandardMetadata(columns);
|
||||
return new RowUpdate(0, rs, etm);
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
// Setup:
|
||||
// ... Create an edit data service with a session
|
||||
var eds = new EditDataService(null, null, null);
|
||||
eds.ActiveSessions[Common.OwnerUri] = GetDefaultSession();
|
||||
eds.ActiveSessions[Common.OwnerUri] = await GetDefaultSession();
|
||||
|
||||
// ... Create a session param that returns the common owner uri
|
||||
var mockParams = new EditCreateRowParams { OwnerUri = Common.OwnerUri };
|
||||
@@ -94,7 +94,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
{
|
||||
// Setup: Create an edit data service with a session
|
||||
var eds = new EditDataService(null, null, null);
|
||||
eds.ActiveSessions[Common.OwnerUri] = GetDefaultSession();
|
||||
eds.ActiveSessions[Common.OwnerUri] = await GetDefaultSession();
|
||||
|
||||
// If: I ask to dispose of an existing session
|
||||
var efv = new EventFlowValidator<EditDisposeResult>()
|
||||
@@ -117,7 +117,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
{
|
||||
// Setup: Create an edit data service with a session
|
||||
var eds = new EditDataService(null, null, null);
|
||||
eds.ActiveSessions[Constants.OwnerUri] = GetDefaultSession();
|
||||
eds.ActiveSessions[Constants.OwnerUri] = await GetDefaultSession();
|
||||
|
||||
// If: I validly ask to delete a row
|
||||
var efv = new EventFlowValidator<EditDeleteRowResult>()
|
||||
@@ -139,7 +139,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
{
|
||||
// Setup: Create an edit data service with a session
|
||||
var eds = new EditDataService(null, null, null);
|
||||
eds.ActiveSessions[Constants.OwnerUri] = GetDefaultSession();
|
||||
eds.ActiveSessions[Constants.OwnerUri] = await GetDefaultSession();
|
||||
|
||||
// If: I ask to create a row from a non existant session
|
||||
var efv = new EventFlowValidator<EditCreateRowResult>()
|
||||
@@ -161,7 +161,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
{
|
||||
// Setup: Create an edit data service with a session that has an pending edit
|
||||
var eds = new EditDataService(null, null, null);
|
||||
var session = GetDefaultSession();
|
||||
var session = await GetDefaultSession();
|
||||
session.EditCache[0] = new Mock<RowEditBase>().Object;
|
||||
eds.ActiveSessions[Constants.OwnerUri] = session;
|
||||
|
||||
@@ -185,7 +185,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
{
|
||||
// Setup: Create an edit data service with a session
|
||||
var eds = new EditDataService(null, null, null);
|
||||
var session = GetDefaultSession();
|
||||
var session = await GetDefaultSession();
|
||||
eds.ActiveSessions[Constants.OwnerUri] = session;
|
||||
var edit = new Mock<RowEditBase>();
|
||||
edit.Setup(e => e.SetCell(It.IsAny<int>(), It.IsAny<string>())).Returns(new EditUpdateCellResult
|
||||
@@ -223,7 +223,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
// Setup: Create an edit data service with a session
|
||||
// Setup: Create an edit data service with a session
|
||||
var eds = new EditDataService(null, null, null);
|
||||
var session = GetDefaultSession();
|
||||
var session = await GetDefaultSession();
|
||||
eds.ActiveSessions[Constants.OwnerUri] = session;
|
||||
|
||||
// If: I validly ask for rows
|
||||
@@ -277,119 +277,15 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
|
||||
// ... There should not be a session
|
||||
Assert.Empty(eds.ActiveSessions);
|
||||
|
||||
// ... There should not be a wait handler
|
||||
Assert.Empty(eds.InitializeWaitHandles);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task InitializeInProgress()
|
||||
{
|
||||
// Setup: Create an edit data service with an "in-progress initialize"
|
||||
var eds = new EditDataService(null, null, null);
|
||||
eds.InitializeWaitHandles[Common.OwnerUri] = new TaskCompletionSource<bool>();
|
||||
|
||||
// If:
|
||||
// ... I ask to initialize a session when an initialize task is already in progress
|
||||
var initParams = new EditInitializeParams
|
||||
{
|
||||
ObjectName = "table",
|
||||
OwnerUri = Common.OwnerUri,
|
||||
ObjectType = "table"
|
||||
};
|
||||
var efv = new EventFlowValidator<EditInitializeResult>()
|
||||
.AddErrorValidation<string>(Assert.NotNull)
|
||||
.Complete();
|
||||
await eds.HandleInitializeRequest(initParams, efv.Object);
|
||||
|
||||
// Then:
|
||||
// ... An error event should have been raised
|
||||
efv.Validate();
|
||||
|
||||
// ... There should not be a session
|
||||
Assert.Empty(eds.ActiveSessions);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task InitializeQueryCreateFailed()
|
||||
{
|
||||
// Setup:
|
||||
// ... Create a query execution service that will throw on creation of the query
|
||||
var qes = QueryExecution.Common.GetPrimedExecutionService(null, false, false, null);
|
||||
|
||||
// ... Create an edit data service that uses the mocked up query service
|
||||
var eds = new EditDataService(qes, null, null);
|
||||
|
||||
// If:
|
||||
// ... I initialize a session
|
||||
var initParams = new EditInitializeParams
|
||||
{
|
||||
ObjectName = "table",
|
||||
OwnerUri = Common.OwnerUri,
|
||||
ObjectType = "table"
|
||||
};
|
||||
var efv = new EventFlowValidator<EditInitializeResult>()
|
||||
.AddErrorValidation<string>(Assert.NotEmpty)
|
||||
.Complete();
|
||||
await eds.HandleInitializeRequest(initParams, efv.Object);
|
||||
|
||||
// Then:
|
||||
// ... We should have gotten an error back
|
||||
efv.Validate();
|
||||
|
||||
// ... There should not be any sessions created
|
||||
Assert.Empty(eds.ActiveSessions);
|
||||
|
||||
// ... There should not be a wait handle
|
||||
Assert.Empty(eds.InitializeWaitHandles);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task InitializeQueryExecutionFails()
|
||||
{
|
||||
// Setup:
|
||||
// ... Create a query execution service that will throw on execution of the query
|
||||
var qes = QueryExecution.Common.GetPrimedExecutionService(null, true, true, null);
|
||||
|
||||
// ... Create an edit data service that uses the mocked up query service
|
||||
var eds = new EditDataService(qes, null, null);
|
||||
|
||||
// If:
|
||||
// ... I initialize a session
|
||||
var initParams = new EditInitializeParams
|
||||
{
|
||||
ObjectName = "table",
|
||||
OwnerUri = Common.OwnerUri,
|
||||
ObjectType = "table"
|
||||
};
|
||||
var efv = new EventFlowValidator<EditInitializeResult>()
|
||||
.AddResultValidation(Assert.NotNull)
|
||||
.AddEventValidation(EditSessionReadyEvent.Type, esrp =>
|
||||
{
|
||||
Assert.NotNull(esrp);
|
||||
Assert.False(esrp.Success);
|
||||
}).Complete();
|
||||
await eds.HandleInitializeRequest(initParams, efv.Object);
|
||||
await eds.InitializeWaitHandles[Common.OwnerUri].Task;
|
||||
|
||||
// Then:
|
||||
// ... We should have started execution, but failed
|
||||
efv.Validate();
|
||||
|
||||
// ... There should not be any sessions created
|
||||
Assert.Empty(eds.ActiveSessions);
|
||||
|
||||
// ... There should not be a wait handle. It should have been cleaned up by now
|
||||
Assert.Empty(eds.InitializeWaitHandles);
|
||||
}
|
||||
|
||||
private static EditSession GetDefaultSession()
|
||||
private static async Task<EditSession> GetDefaultSession()
|
||||
{
|
||||
// ... Create a session with a proper query and metadata
|
||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
||||
IEditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
||||
EditSession s = new EditSession(rs, etm);
|
||||
EditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
||||
EditSession s = await Common.GetCustomSession(q, etm);
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,40 +28,55 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
#region Construction Tests
|
||||
|
||||
[Fact]
|
||||
public void SessionConstructionNullQuery()
|
||||
public void SessionConstructionNullMetadataFactory()
|
||||
{
|
||||
// If: I create a session object without a null query
|
||||
// If: I create a session object with a null metadata factory
|
||||
// Then: It should throw an exception
|
||||
Assert.Throws<ArgumentNullException>(() => new EditSession(null, Common.GetStandardMetadata(new DbColumn[] {})));
|
||||
Assert.Throws<ArgumentNullException>(() => new EditSession(null, Constants.OwnerUri, Constants.OwnerUri));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SessionConstructionNullMetadataProvider()
|
||||
[Theory]
|
||||
[InlineData(null)]
|
||||
[InlineData("")]
|
||||
[InlineData(" \t\r\n")]
|
||||
public void SessionConstructionNullObjectName(string objName)
|
||||
{
|
||||
// If: I create a session object without a null metadata provider
|
||||
// If: I create a session object with a null or whitespace object name
|
||||
// Then: It should throw an exception
|
||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
||||
Assert.Throws<ArgumentNullException>(() => new EditSession(rs, null));
|
||||
Mock<IEditMetadataFactory> mockFactory = new Mock<IEditMetadataFactory>();
|
||||
Assert.Throws<ArgumentException>(() => new EditSession(mockFactory.Object, objName, Constants.OwnerUri));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null)]
|
||||
[InlineData("")]
|
||||
[InlineData(" \t\r\n")]
|
||||
public void SessionConstructionNullObjectType(string objType)
|
||||
{
|
||||
// If: I create a session object with a null or whitespace object type
|
||||
// Then: It should throw an exception
|
||||
Mock<IEditMetadataFactory> mockFactory = new Mock<IEditMetadataFactory>();
|
||||
Assert.Throws<ArgumentException>(() => new EditSession(mockFactory.Object, Constants.OwnerUri, objType));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SessionConstructionValid()
|
||||
{
|
||||
// If: I create a session object with a proper query and metadata
|
||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
||||
IEditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
||||
EditSession s = new EditSession(rs, etm);
|
||||
// If: I create a session object with a proper arguments
|
||||
Mock<IEditMetadataFactory> mockFactory = new Mock<IEditMetadataFactory>();
|
||||
EditSession s = new EditSession(mockFactory.Object, Constants.OwnerUri, Constants.OwnerUri);
|
||||
|
||||
// Then:
|
||||
// ... The edit cache should exist and be empty
|
||||
Assert.NotNull(s.EditCache);
|
||||
Assert.Empty(s.EditCache);
|
||||
// ... The edit cache should not exist
|
||||
Assert.Null(s.EditCache);
|
||||
|
||||
// ... The session shouldn't be initialized
|
||||
Assert.False(s.IsInitialized);
|
||||
Assert.Null(s.EditCache);
|
||||
Assert.Null(s.CommitTask);
|
||||
|
||||
// ... The next row ID should be equivalent to the number of rows in the result set
|
||||
Assert.Equal(q.Batches[0].ResultSets[0].RowCount, s.NextRowId);
|
||||
// ... The next row ID should be the default long
|
||||
Assert.Equal(default(long), s.NextRowId);
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -118,15 +133,28 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
#region Create Row Tests
|
||||
|
||||
[Fact]
|
||||
public void CreateRowAddFailure()
|
||||
public void CreateRowNotInitialized()
|
||||
{
|
||||
// Setup:
|
||||
// ... Create a session without initializing
|
||||
Mock<IEditMetadataFactory> emf = new Mock<IEditMetadataFactory>();
|
||||
EditSession s = new EditSession(emf.Object, Constants.OwnerUri, Constants.OwnerUri);
|
||||
|
||||
// If: I ask to create a row without initializing
|
||||
// Then: I should get an exception
|
||||
Assert.Throws<InvalidOperationException>(() => s.CreateRow());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CreateRowAddFailure()
|
||||
{
|
||||
// NOTE: This scenario should theoretically never occur, but is tested for completeness
|
||||
// Setup:
|
||||
// ... Create a session with a proper query and metadata
|
||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
||||
IEditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
||||
EditSession s = new EditSession(rs, etm);
|
||||
EditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
||||
EditSession s = await Common.GetCustomSession(q, etm);
|
||||
|
||||
// ... Add a mock edit to the edit cache to cause the .TryAdd to fail
|
||||
var mockEdit = new Mock<RowEditBase>().Object;
|
||||
@@ -145,13 +173,13 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateRowSuccess()
|
||||
public async Task CreateRowSuccess()
|
||||
{
|
||||
// Setup: Create a session with a proper query and metadata
|
||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
||||
IEditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
||||
EditSession s = new EditSession(rs, etm);
|
||||
EditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
||||
EditSession s = await Common.GetCustomSession(q, etm);
|
||||
|
||||
// If: I add a row to the session
|
||||
EditCreateRowResult result = s.CreateRow();
|
||||
@@ -172,48 +200,48 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateRowDefaultTest()
|
||||
public async Task CreateRowDefaultTest()
|
||||
{
|
||||
// Setup:
|
||||
// ... We will have 3 columns
|
||||
DbColumn[] cols =
|
||||
DbColumnWrapper[] cols =
|
||||
{
|
||||
new TestDbColumn("col1", false), // No default
|
||||
new TestDbColumn("col2", false), // Has default (defined below)
|
||||
new TestDbColumn("filler", false) // Filler column so we can use the common code
|
||||
new DbColumnWrapper(new TestDbColumn("col1")), // No default
|
||||
new DbColumnWrapper(new TestDbColumn("col2")), // Has default (defined below)
|
||||
new DbColumnWrapper(new TestDbColumn("filler")) // Filler column so we can use the common code
|
||||
};
|
||||
|
||||
// ... Metadata provider will return 3 columns
|
||||
EditColumnWrapper[] metas =
|
||||
EditColumnMetadata[] metas =
|
||||
{
|
||||
new EditColumnWrapper // No default
|
||||
new EditColumnMetadata // No default
|
||||
{
|
||||
DbColumn = new DbColumnWrapper(cols[0]),
|
||||
DefaultValue = null,
|
||||
EscapedName = cols[0].ColumnName,
|
||||
Ordinal = 0,
|
||||
IsKey = false
|
||||
},
|
||||
new EditColumnWrapper // Has default
|
||||
new EditColumnMetadata // Has default
|
||||
{
|
||||
DbColumn = new DbColumnWrapper(cols[1]),
|
||||
DefaultValue = "default",
|
||||
EscapedName = cols[0].ColumnName,
|
||||
Ordinal = 0,
|
||||
IsKey = false
|
||||
},
|
||||
new EditColumnWrapper()
|
||||
new EditColumnMetadata()
|
||||
};
|
||||
var etm = Common.GetMetadataProvider(metas, true);
|
||||
var etm = new EditTableMetadata
|
||||
{
|
||||
Columns = metas,
|
||||
EscapedMultipartName = "tbl",
|
||||
IsMemoryOptimized = false
|
||||
};
|
||||
etm.Extend(cols);
|
||||
|
||||
// ... Create a result set
|
||||
var rs = Common.GetResultSet(cols, false, 1);
|
||||
var q = await Common.GetQuery(cols, false);
|
||||
|
||||
// ... Create a session from all this
|
||||
var session = new EditSession(rs, etm);
|
||||
EditSession s = await Common.GetCustomSession(q, etm);
|
||||
|
||||
// If: I add a row to the session, on a table that has defaults
|
||||
var result = session.CreateRow();
|
||||
var result = s.CreateRow();
|
||||
|
||||
// Then:
|
||||
// ... Result should not be null, new row ID should be > 0
|
||||
@@ -233,13 +261,10 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RowIdOutOfRangeData))]
|
||||
public void RowIdOutOfRange(long rowId, Action<EditSession, long> testAction)
|
||||
public async Task RowIdOutOfRange(long rowId, Action<EditSession, long> testAction)
|
||||
{
|
||||
// Setup: Create a session with a proper query and metadata
|
||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
||||
IEditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
||||
EditSession s = new EditSession(rs, etm);
|
||||
EditSession s = await GetBasicSession();
|
||||
|
||||
// If: I delete a row that is out of range for the result set
|
||||
// Then: I should get an exception
|
||||
@@ -253,26 +278,260 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
// Delete Row
|
||||
Action<EditSession, long> delAction = (s, l) => s.DeleteRow(l);
|
||||
yield return new object[] { -1L, delAction };
|
||||
yield return new object[] {(long) QueryExecution.Common.StandardRows, delAction};
|
||||
yield return new object[] { 100L, delAction };
|
||||
|
||||
// Update Cell
|
||||
Action<EditSession, long> upAction = (s, l) => s.UpdateCell(l, 0, null);
|
||||
yield return new object[] { -1L, upAction };
|
||||
yield return new object[] {(long) QueryExecution.Common.StandardRows, upAction};
|
||||
yield return new object[] { 100L, upAction };
|
||||
|
||||
// Revert Row
|
||||
Action<EditSession, long> revertRowAction = (s, l) => s.RevertRow(l);
|
||||
yield return new object[] {-1L, revertRowAction};
|
||||
yield return new object[] {0L, revertRowAction}; // This is invalid b/c there isn't an edit pending for this row
|
||||
yield return new object[] {(long) QueryExecution.Common.StandardRows, revertRowAction};
|
||||
yield return new object[] {100L, revertRowAction};
|
||||
|
||||
// Revert Cell
|
||||
Action<EditSession, long> revertCellAction = (s, l) => s.RevertCell(l, 0);
|
||||
yield return new object[] {-1L, revertRowAction};
|
||||
yield return new object[] {0L, revertRowAction}; // This is invalid b/c there isn't an edit pending for this row
|
||||
yield return new object[] {(long) QueryExecution.Common.StandardRows, revertRowAction};
|
||||
yield return new object[] {100L, revertRowAction};
|
||||
}
|
||||
}
|
||||
|
||||
#region Initialize Tests
|
||||
|
||||
[Fact]
|
||||
public void InitializeAlreadyInitialized()
|
||||
{
|
||||
// Setup:
|
||||
// ... Create a session and fake that it has been initialized
|
||||
Mock<IEditMetadataFactory> emf = new Mock<IEditMetadataFactory>();
|
||||
EditSession s = new EditSession(emf.Object, Constants.OwnerUri, Constants.OwnerUri);
|
||||
s.IsInitialized = true;
|
||||
|
||||
// If: I initialize it
|
||||
// Then: I should get an exception
|
||||
Assert.Throws<InvalidOperationException>(() => s.Initialize(null, null, null, null));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InitializeAlreadyInitializing()
|
||||
{
|
||||
// Setup:
|
||||
// ... Create a session and fake that it is in progress of initializing
|
||||
Mock<IEditMetadataFactory> emf = new Mock<IEditMetadataFactory>();
|
||||
EditSession s = new EditSession(emf.Object, Constants.OwnerUri, Constants.OwnerUri);
|
||||
s.InitializeTask = new Task(() => { });
|
||||
|
||||
// If: I initialize it
|
||||
// Then: I should get an exception
|
||||
Assert.Throws<InvalidOperationException>(() => s.Initialize(null, null, null, null));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(InitializeNullParamsData))]
|
||||
public void InitializeNullParams(EditSession.Connector c, EditSession.QueryRunner qr,
|
||||
Func<Task> sh, Func<Exception, Task> fh)
|
||||
{
|
||||
// Setup:
|
||||
// ... Create a session that hasn't been initialized
|
||||
Mock<IEditMetadataFactory> emf = new Mock<IEditMetadataFactory>();
|
||||
EditSession s = new EditSession(emf.Object, Constants.OwnerUri, Constants.OwnerUri);
|
||||
|
||||
// If: I initialize it with a missing parameter
|
||||
// Then: It should throw an exception
|
||||
Assert.ThrowsAny<ArgumentException>(() => s.Initialize(c, qr, sh, fh));
|
||||
}
|
||||
|
||||
public static IEnumerable<object> InitializeNullParamsData
|
||||
{
|
||||
get
|
||||
{
|
||||
yield return new object[] {null, DoNothingQueryRunner, DoNothingSuccessHandler, DoNothingFailureHandler};
|
||||
yield return new object[] {DoNothingConnector, null, DoNothingSuccessHandler, DoNothingFailureHandler};
|
||||
yield return new object[] {DoNothingConnector, DoNothingQueryRunner, null, DoNothingFailureHandler};
|
||||
yield return new object[] {DoNothingConnector, DoNothingQueryRunner, DoNothingSuccessHandler, null};
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task InitializeMetadataFails()
|
||||
{
|
||||
// Setup:
|
||||
// ... Create a metadata factory that throws
|
||||
Mock<IEditMetadataFactory> emf = new Mock<IEditMetadataFactory>();
|
||||
emf.Setup(f => f.GetObjectMetadata(It.IsAny<DbConnection>(), It.IsAny<string>(), It.IsAny<string>()))
|
||||
.Throws<Exception>();
|
||||
|
||||
// ... Create a session that hasn't been initialized
|
||||
EditSession s = new EditSession(emf.Object, Constants.OwnerUri, Constants.OwnerUri);
|
||||
|
||||
// ... Create a mock for verifying the failure handler will be called
|
||||
var successHandler = DoNothingSuccessMock;
|
||||
var failureHandler = DoNothingFailureMock;
|
||||
|
||||
// If: I initalize the session with a metadata factory that will fail
|
||||
s.Initialize(DoNothingConnector, DoNothingQueryRunner, successHandler.Object, failureHandler.Object);
|
||||
await s.InitializeTask;
|
||||
|
||||
// Then:
|
||||
// ... The session should not be initialized
|
||||
Assert.False(s.IsInitialized);
|
||||
|
||||
// ... The failure handler should have been called once
|
||||
failureHandler.Verify(f => f(It.IsAny<Exception>()), Times.Once);
|
||||
|
||||
// ... The success handler should not have been called at all
|
||||
successHandler.Verify(f => f(), Times.Never);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task InitializeQueryFailException()
|
||||
{
|
||||
// Setup:
|
||||
// ... Create a metadata factory that will return some generic column information
|
||||
var b = QueryExecution.Common.GetBasicExecutedBatch();
|
||||
var etm = Common.GetStandardMetadata(b.ResultSets[0].Columns);
|
||||
Mock<IEditMetadataFactory> emf = new Mock<IEditMetadataFactory>();
|
||||
emf.Setup(f => f.GetObjectMetadata(It.IsAny<DbConnection>(), It.IsAny<string>(), It.IsAny<string>()))
|
||||
.Returns(etm);
|
||||
|
||||
// ... Create a session that hasn't been initialized
|
||||
EditSession s = new EditSession(emf.Object, Constants.OwnerUri, Constants.OwnerUri);
|
||||
|
||||
// ... Create a query runner that will fail via exception
|
||||
Mock<EditSession.QueryRunner> qr = new Mock<EditSession.QueryRunner>();
|
||||
qr.Setup(r => r(It.IsAny<string>())).Throws(new Exception("qqq"));
|
||||
|
||||
// ... Create a mock for verifying the failure handler will be called
|
||||
var successHandler = DoNothingSuccessMock;
|
||||
var failureHandler = DoNothingFailureMock;
|
||||
|
||||
// If: I initialize the session with a query runner that will fail
|
||||
s.Initialize(DoNothingConnector, qr.Object, successHandler.Object, failureHandler.Object);
|
||||
await s.InitializeTask;
|
||||
|
||||
// Then:
|
||||
// ... The session should not be initialized
|
||||
Assert.False(s.IsInitialized);
|
||||
|
||||
// ... The failure handler should have been called once
|
||||
failureHandler.Verify(f => f(It.IsAny<Exception>()), Times.Once);
|
||||
|
||||
// ... The success handler should not have been called at all
|
||||
successHandler.Verify(f => f(), Times.Never);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null)]
|
||||
[InlineData("It fail.")]
|
||||
public async Task InitializeQueryFailReturnNull(string message)
|
||||
{
|
||||
// Setup:
|
||||
// ... Create a metadata factory that will return some generic column information
|
||||
var b = QueryExecution.Common.GetBasicExecutedBatch();
|
||||
var etm = Common.GetStandardMetadata(b.ResultSets[0].Columns);
|
||||
Mock<IEditMetadataFactory> emf = new Mock<IEditMetadataFactory>();
|
||||
emf.Setup(f => f.GetObjectMetadata(It.IsAny<DbConnection>(), It.IsAny<string>(), It.IsAny<string>()))
|
||||
.Returns(etm);
|
||||
|
||||
// ... Create a session that hasn't been initialized
|
||||
EditSession s = new EditSession(emf.Object, Constants.OwnerUri, Constants.OwnerUri);
|
||||
|
||||
// ... Create a query runner that will fail via returning a null query
|
||||
Mock<EditSession.QueryRunner> qr = new Mock<EditSession.QueryRunner>();
|
||||
qr.Setup(r => r(It.IsAny<string>()))
|
||||
.Returns(Task.FromResult(new EditSession.EditSessionQueryExecutionState(null, message)));
|
||||
|
||||
// ... Create a mock for verifying the failure handler will be called
|
||||
var successHandler = DoNothingSuccessMock;
|
||||
var failureHandler = DoNothingFailureMock;
|
||||
|
||||
// If: I initialize the session with a query runner that will fail
|
||||
s.Initialize(DoNothingConnector, qr.Object, successHandler.Object, failureHandler.Object);
|
||||
await s.InitializeTask;
|
||||
|
||||
// Then:
|
||||
// ... The session should not be initialized
|
||||
Assert.False(s.IsInitialized);
|
||||
|
||||
// ... The failure handler should have been called once
|
||||
failureHandler.Verify(f => f(It.IsAny<Exception>()), Times.Once);
|
||||
|
||||
// ... The success handler should not have been called at all
|
||||
successHandler.Verify(f => f(), Times.Never);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task InitializeSuccess()
|
||||
{
|
||||
// Setup:
|
||||
// ... Create a metadata factory that will return some generic column information
|
||||
var q = QueryExecution.Common.GetBasicExecutedQuery();
|
||||
var rs = q.Batches[0].ResultSets[0];
|
||||
var etm = Common.GetStandardMetadata(rs.Columns);
|
||||
Mock<IEditMetadataFactory> emf = new Mock<IEditMetadataFactory>();
|
||||
emf.Setup(f => f.GetObjectMetadata(It.IsAny<DbConnection>(), It.IsAny<string>(), It.IsAny<string>()))
|
||||
.Returns(etm);
|
||||
|
||||
// ... Create a session that hasn't been initialized
|
||||
EditSession s = new EditSession(emf.Object, Constants.OwnerUri, Constants.OwnerUri);
|
||||
|
||||
// ... Create a query runner that will return a successful query
|
||||
Mock<EditSession.QueryRunner> qr = new Mock<EditSession.QueryRunner>();
|
||||
qr.Setup(r => r(It.IsAny<string>()))
|
||||
.Returns(Task.FromResult(new EditSession.EditSessionQueryExecutionState(q, null)));
|
||||
|
||||
// ... Create a mock for verifying the failure handler will be called
|
||||
var successHandler = DoNothingSuccessMock;
|
||||
var failureHandler = DoNothingFailureMock;
|
||||
|
||||
// If: I initialize the session with a query runner that will fail
|
||||
s.Initialize(DoNothingConnector, qr.Object, successHandler.Object, failureHandler.Object);
|
||||
await s.InitializeTask;
|
||||
|
||||
// Then:
|
||||
// ... The failure handler should not have been called
|
||||
failureHandler.Verify(f => f(It.IsAny<Exception>()), Times.Never);
|
||||
|
||||
// ... The success handler should have been called
|
||||
successHandler.Verify(f => f(), Times.Once);
|
||||
|
||||
// ... The session should have been initialized
|
||||
Assert.True(s.IsInitialized);
|
||||
Assert.Equal(rs.RowCount, s.NextRowId);
|
||||
Assert.NotNull(s.EditCache);
|
||||
Assert.Empty(s.EditCache);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Delete Row Tests
|
||||
|
||||
[Fact]
|
||||
public void DeleteRowAddFailure()
|
||||
public void DeleteRowNotInitialized()
|
||||
{
|
||||
// Setup:
|
||||
// ... Create a session without initializing
|
||||
Mock<IEditMetadataFactory> emf = new Mock<IEditMetadataFactory>();
|
||||
EditSession s = new EditSession(emf.Object, Constants.OwnerUri, Constants.OwnerUri);
|
||||
|
||||
// If: I ask to delete a row without initializing
|
||||
// Then: I should get an exception
|
||||
Assert.Throws<InvalidOperationException>(() => s.DeleteRow(0));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DeleteRowAddFailure()
|
||||
{
|
||||
// Setup:
|
||||
// ... Create a session with a proper query and metadata
|
||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
||||
IEditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
||||
EditSession s = new EditSession(rs, etm);
|
||||
EditSession s = await GetBasicSession();
|
||||
|
||||
// ... Add a mock edit to the edit cache to cause the .TryAdd to fail
|
||||
var mockEdit = new Mock<RowEditBase>().Object;
|
||||
@@ -288,13 +547,10 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DeleteRowSuccess()
|
||||
public async Task DeleteRowSuccess()
|
||||
{
|
||||
// Setup: Create a session with a proper query and metadata
|
||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
||||
IEditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
||||
EditSession s = new EditSession(rs, etm);
|
||||
var s = await GetBasicSession();
|
||||
|
||||
// If: I add a row to the session
|
||||
s.DeleteRow(0);
|
||||
@@ -309,28 +565,24 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
#region Revert Row Tests
|
||||
|
||||
[Fact]
|
||||
public void RevertRowOutOfRange()
|
||||
public void RevertRowNotInitialized()
|
||||
{
|
||||
// Setup: Create a session with a proper query and metadata
|
||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
||||
IEditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
||||
EditSession s = new EditSession(rs, etm);
|
||||
// Setup:
|
||||
// ... Create a session without initializing
|
||||
Mock<IEditMetadataFactory> emf = new Mock<IEditMetadataFactory>();
|
||||
EditSession s = new EditSession(emf.Object, Constants.OwnerUri, Constants.OwnerUri);
|
||||
|
||||
// If: I revert a row that doesn't have any pending changes
|
||||
// If: I ask to revert a row without initializing
|
||||
// Then: I should get an exception
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => s.RevertRow(0));
|
||||
Assert.Throws<InvalidOperationException>(() => s.RevertRow(0));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RevertRowSuccess()
|
||||
public async Task RevertRowSuccess()
|
||||
{
|
||||
// Setup:
|
||||
// ... Create a session with a proper query and metadata
|
||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
||||
IEditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
||||
EditSession s = new EditSession(rs, etm);
|
||||
EditSession s = await GetBasicSession();
|
||||
|
||||
// ... Add a mock edit to the edit cache to cause the .TryAdd to fail
|
||||
var mockEdit = new Mock<RowEditBase>().Object;
|
||||
@@ -346,17 +598,44 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
|
||||
#endregion
|
||||
|
||||
#region Revert Cell Tests
|
||||
|
||||
[Fact]
|
||||
public void RevertCellNotInitialized()
|
||||
{
|
||||
// Setup:
|
||||
// ... Create a session without initializing
|
||||
Mock<IEditMetadataFactory> emf = new Mock<IEditMetadataFactory>();
|
||||
EditSession s = new EditSession(emf.Object, Constants.OwnerUri, Constants.OwnerUri);
|
||||
|
||||
// If: I ask to revert a cell without initializing
|
||||
// Then: I should get an exception
|
||||
Assert.Throws<InvalidOperationException>(() => s.RevertCell(0, 0));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Update Cell Tests
|
||||
|
||||
[Fact]
|
||||
public void UpdateCellExisting()
|
||||
public void UpdateCellNotInitialized()
|
||||
{
|
||||
// Setup:
|
||||
// ... Create a session without initializing
|
||||
Mock<IEditMetadataFactory> emf = new Mock<IEditMetadataFactory>();
|
||||
EditSession s = new EditSession(emf.Object, Constants.OwnerUri, Constants.OwnerUri);
|
||||
|
||||
// If: I ask to update a cell without initializing
|
||||
// Then: I should get an exception
|
||||
Assert.Throws<InvalidOperationException>(() => s.UpdateCell(0, 0, ""));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task UpdateCellExisting()
|
||||
{
|
||||
// Setup:
|
||||
// ... Create a session with a proper query and metadata
|
||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
||||
IEditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
||||
EditSession s = new EditSession(rs, etm);
|
||||
EditSession s = await GetBasicSession();
|
||||
|
||||
// ... Add a mock edit to the edit cache to cause the .TryAdd to fail
|
||||
var mockEdit = new Mock<RowEditBase>();
|
||||
@@ -373,14 +652,11 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UpdateCellNew()
|
||||
public async Task UpdateCellNew()
|
||||
{
|
||||
// Setup:
|
||||
// ... Create a session with a proper query and metadata
|
||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
||||
IEditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
||||
EditSession s = new EditSession(rs, etm);
|
||||
EditSession s = await GetBasicSession();
|
||||
|
||||
// If: I update a cell on a row that does not have a pending edit
|
||||
s.UpdateCell(0, 0, "");
|
||||
@@ -395,14 +671,27 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
|
||||
#region SubSet Tests
|
||||
|
||||
[Fact]
|
||||
public async Task SubsetNotInitialized()
|
||||
{
|
||||
// Setup:
|
||||
// ... Create a session without initializing
|
||||
Mock<IEditMetadataFactory> emf = new Mock<IEditMetadataFactory>();
|
||||
EditSession s = new EditSession(emf.Object, Constants.OwnerUri, Constants.OwnerUri);
|
||||
|
||||
// If: I ask to update a cell without initializing
|
||||
// Then: I should get an exception
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => s.GetRows(0, 100));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetRowsNoEdits()
|
||||
{
|
||||
// Setup: Create a session with a proper query and metadata
|
||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
||||
IEditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
||||
EditSession s = new EditSession(rs, etm);
|
||||
EditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
||||
EditSession s = await Common.GetCustomSession(q, etm);
|
||||
|
||||
// If: I ask for 3 rows from session skipping the first
|
||||
EditRow[] rows = await s.GetRows(1, 3);
|
||||
@@ -439,10 +728,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
{
|
||||
// Setup:
|
||||
// ... Create a session with a proper query and metadata
|
||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
||||
IEditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
||||
EditSession s = new EditSession(rs, etm);
|
||||
EditSession s = await GetBasicSession();
|
||||
|
||||
// ... Add a cell update to it
|
||||
s.UpdateCell(1, 0, "foo");
|
||||
@@ -472,10 +758,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
{
|
||||
// Setup:
|
||||
// ... Create a session with a proper query and metadata
|
||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
||||
IEditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
||||
EditSession s = new EditSession(rs, etm);
|
||||
EditSession s = await GetBasicSession();
|
||||
|
||||
// ... Add a row deletion
|
||||
s.DeleteRow(1);
|
||||
@@ -505,10 +788,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
{
|
||||
// Setup:
|
||||
// ... Create a session with a proper query and metadata
|
||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
||||
IEditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
||||
EditSession s = new EditSession(rs, etm);
|
||||
EditSession s = await GetBasicSession();
|
||||
|
||||
// ... Add a row creation
|
||||
s.CreateRow();
|
||||
@@ -536,10 +816,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
{
|
||||
// Setup:
|
||||
// ... Create a session with a query and metadata
|
||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
||||
IEditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
||||
EditSession s = new EditSession(rs, etm);
|
||||
EditSession s = await GetBasicSession();
|
||||
|
||||
// ... Add a few row creations
|
||||
s.CreateRow();
|
||||
@@ -561,17 +838,27 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
|
||||
#region Script Edits Tests
|
||||
|
||||
[Fact]
|
||||
public void ScriptEditsNotInitialized()
|
||||
{
|
||||
// Setup:
|
||||
// ... Create a session without initializing
|
||||
Mock<IEditMetadataFactory> emf = new Mock<IEditMetadataFactory>();
|
||||
EditSession s = new EditSession(emf.Object, Constants.OwnerUri, Constants.OwnerUri);
|
||||
|
||||
// If: I ask to script edits without initializing
|
||||
// Then: I should get an exception
|
||||
Assert.Throws<InvalidOperationException>(() => s.ScriptEdits(string.Empty));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null)]
|
||||
[InlineData("")]
|
||||
[InlineData(" \t\r\n")]
|
||||
public void ScriptNullOrEmptyOutput(string outputPath)
|
||||
public async Task ScriptNullOrEmptyOutput(string outputPath)
|
||||
{
|
||||
// Setup: Create a session with a proper query and metadata
|
||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
||||
IEditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
||||
EditSession s = new EditSession(rs, etm);
|
||||
EditSession s = await GetBasicSession();
|
||||
|
||||
// If: I try to script the edit cache with a null or whitespace output path
|
||||
// Then: It should throw an exception
|
||||
@@ -579,14 +866,11 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ScriptProvidedOutputPath()
|
||||
public async Task ScriptProvidedOutputPath()
|
||||
{
|
||||
// Setup:
|
||||
// ... Create a session with a proper query and metadata
|
||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
||||
IEditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
||||
EditSession s = new EditSession(rs, etm);
|
||||
EditSession s = await GetBasicSession();
|
||||
|
||||
// ... Add two mock edits that will generate a script
|
||||
Mock<RowEditBase> edit = new Mock<RowEditBase>();
|
||||
@@ -613,10 +897,23 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
#region Commit Tests
|
||||
|
||||
[Fact]
|
||||
public void CommitNullConnection()
|
||||
public void CommitEditsNotInitialized()
|
||||
{
|
||||
// Setup:
|
||||
// ... Create a session without initializing
|
||||
Mock<IEditMetadataFactory> emf = new Mock<IEditMetadataFactory>();
|
||||
EditSession s = new EditSession(emf.Object, Constants.OwnerUri, Constants.OwnerUri);
|
||||
|
||||
// If: I ask to script edits without initializing
|
||||
// Then: I should get an exception
|
||||
Assert.Throws<InvalidOperationException>(() => s.CommitEdits(null, null, null));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CommitNullConnection()
|
||||
{
|
||||
// Setup: Create a basic session
|
||||
EditSession s = GetBasicSession();
|
||||
EditSession s = await GetBasicSession();
|
||||
|
||||
// If: I attempt to commit with a null connection
|
||||
// Then: I should get an exception
|
||||
@@ -625,11 +922,11 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CommitNullSuccessHandler()
|
||||
public async Task CommitNullSuccessHandler()
|
||||
{
|
||||
// Setup:
|
||||
// ... Create a basic session
|
||||
EditSession s = GetBasicSession();
|
||||
EditSession s = await GetBasicSession();
|
||||
|
||||
// ... Mock db connection
|
||||
DbConnection conn = new TestSqlConnection(null);
|
||||
@@ -640,11 +937,11 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CommitNullFailureHandler()
|
||||
public async Task CommitNullFailureHandler()
|
||||
{
|
||||
// Setup:
|
||||
// ... Create a basic session
|
||||
EditSession s = GetBasicSession();
|
||||
EditSession s = await GetBasicSession();
|
||||
|
||||
// ... Mock db connection
|
||||
DbConnection conn = new TestSqlConnection(null);
|
||||
@@ -655,11 +952,11 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CommitInProgress()
|
||||
public async Task CommitInProgress()
|
||||
{
|
||||
// Setup:
|
||||
// ... Basic session and db connection
|
||||
EditSession s = GetBasicSession();
|
||||
EditSession s = await GetBasicSession();
|
||||
DbConnection conn = new TestSqlConnection(null);
|
||||
|
||||
// ... Mock a task that has not completed
|
||||
@@ -677,7 +974,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
{
|
||||
// Setup:
|
||||
// ... Basic session and db connection
|
||||
EditSession s = GetBasicSession();
|
||||
EditSession s = await GetBasicSession();
|
||||
DbConnection conn = new TestSqlConnection(null);
|
||||
|
||||
// ... Add a mock commands for fun
|
||||
@@ -721,7 +1018,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
{
|
||||
// Setup:
|
||||
// ... Basic session and db connection
|
||||
EditSession s = GetBasicSession();
|
||||
EditSession s = await GetBasicSession();
|
||||
DbConnection conn = new TestSqlConnection(null);
|
||||
|
||||
// ... Add a mock edit that will explode on generating a command
|
||||
@@ -760,12 +1057,51 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
|
||||
#endregion
|
||||
|
||||
private static EditSession GetBasicSession()
|
||||
private static EditSession.Connector DoNothingConnector
|
||||
{
|
||||
get { return () => Task.FromResult<DbConnection>(null); }
|
||||
}
|
||||
|
||||
private static EditSession.QueryRunner DoNothingQueryRunner
|
||||
{
|
||||
get { return q => Task.FromResult<EditSession.EditSessionQueryExecutionState>(null); }
|
||||
}
|
||||
|
||||
private static Func<Task> DoNothingSuccessHandler
|
||||
{
|
||||
get { return () => Task.FromResult(0); }
|
||||
}
|
||||
|
||||
private static Func<Exception, Task> DoNothingFailureHandler
|
||||
{
|
||||
get { return e => Task.FromResult(0); }
|
||||
}
|
||||
|
||||
private static Mock<Func<Task>> DoNothingSuccessMock
|
||||
{
|
||||
get {
|
||||
Mock<Func<Task>> successHandler = new Mock<Func<Task>>();
|
||||
successHandler.Setup(f => f()).Returns(Task.FromResult(0));
|
||||
return successHandler;
|
||||
}
|
||||
}
|
||||
|
||||
private static Mock<Func<Exception, Task>> DoNothingFailureMock
|
||||
{
|
||||
get
|
||||
{
|
||||
Mock<Func<Exception, Task>> failureHandler = new Mock<Func<Exception, Task>>();
|
||||
failureHandler.Setup(f => f(It.IsAny<Exception>())).Returns(Task.FromResult(0));
|
||||
return failureHandler;
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task<EditSession> GetBasicSession()
|
||||
{
|
||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
||||
IEditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
||||
return new EditSession(rs, etm);
|
||||
EditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
||||
return await Common.GetCustomSession(q, etm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -302,7 +302,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
|
||||
};
|
||||
|
||||
// Setup: Create a DATE column
|
||||
DbColumnWrapper col = new DbColumnWrapper(new TestDbColumn("col", "DaTe"));
|
||||
DbColumnWrapper col = new DbColumnWrapper(new TestDbColumn {DataTypeName = "DaTe"});
|
||||
|
||||
foreach (DateTime value in testValues)
|
||||
{
|
||||
@@ -324,7 +324,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
|
||||
};
|
||||
|
||||
// Setup: Create a DATETIME column
|
||||
DbColumnWrapper col = new DbColumnWrapper(new TestDbColumn("col", "DaTeTiMe"));
|
||||
DbColumnWrapper col = new DbColumnWrapper(new TestDbColumn {DataTypeName = "DaTeTiMe"});
|
||||
|
||||
foreach (DateTime value in testValues)
|
||||
{
|
||||
@@ -353,7 +353,11 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
|
||||
};
|
||||
|
||||
// Setup: Create a DATETIME column
|
||||
DbColumnWrapper col = new DbColumnWrapper(new TestDbColumn("col", "DaTeTiMe2", precision));
|
||||
DbColumnWrapper col = new DbColumnWrapper(new TestDbColumn
|
||||
{
|
||||
DataTypeName = "DaTeTiMe2",
|
||||
NumericScale = precision
|
||||
});
|
||||
|
||||
foreach (DateTime value in testValues)
|
||||
{
|
||||
@@ -379,7 +383,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
|
||||
};
|
||||
|
||||
// Setup: Create a DATETIME2 column
|
||||
DbColumnWrapper col = new DbColumnWrapper(new TestDbColumn("col", "DaTeTiMe2", 0));
|
||||
DbColumnWrapper col = new DbColumnWrapper(new TestDbColumn {DataTypeName = "DaTeTiMe2", NumericScale = 0});
|
||||
|
||||
foreach (DateTime value in testValues)
|
||||
{
|
||||
@@ -401,7 +405,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
|
||||
};
|
||||
|
||||
// Setup: Create a DATETIME2 column
|
||||
DbColumnWrapper col = new DbColumnWrapper(new TestDbColumn("col", "DaTeTiMe2", 255));
|
||||
DbColumnWrapper col = new DbColumnWrapper(new TestDbColumn {DataTypeName = "DaTeTiMe2", NumericScale = 255});
|
||||
|
||||
foreach (DateTime value in testValues)
|
||||
{
|
||||
|
||||
@@ -4,11 +4,85 @@
|
||||
|
||||
using System;
|
||||
using System.Data.Common;
|
||||
using Microsoft.SqlTools.Utility;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Utility
|
||||
{
|
||||
public class TestDbColumn : DbColumn
|
||||
{
|
||||
#region Overridden Properties
|
||||
|
||||
public new bool AllowDBNull
|
||||
{
|
||||
get { return base.AllowDBNull.HasTrue(); }
|
||||
set { base.AllowDBNull = value; }
|
||||
}
|
||||
|
||||
public new string ColumnName
|
||||
{
|
||||
get { return base.ColumnName; }
|
||||
set { base.ColumnName = value; }
|
||||
}
|
||||
|
||||
public new int ColumnSize
|
||||
{
|
||||
get { return base.ColumnSize ?? -1; }
|
||||
set { base.ColumnSize = value; }
|
||||
}
|
||||
|
||||
public new Type DataType
|
||||
{
|
||||
get { return base.DataType; }
|
||||
set { base.DataType = value; }
|
||||
}
|
||||
|
||||
public new string DataTypeName
|
||||
{
|
||||
get { return base.DataTypeName; }
|
||||
set { base.DataTypeName = value; }
|
||||
}
|
||||
|
||||
public new bool IsAutoIncrement
|
||||
{
|
||||
get { return base.IsAutoIncrement.HasTrue(); }
|
||||
set { base.IsAutoIncrement = value; }
|
||||
}
|
||||
|
||||
public new bool IsLong
|
||||
{
|
||||
get { return base.IsLong.HasTrue(); }
|
||||
set { base.IsLong = value; }
|
||||
}
|
||||
|
||||
public new bool IsIdentity
|
||||
{
|
||||
get { return base.IsIdentity.HasTrue(); }
|
||||
set { base.IsIdentity = value; }
|
||||
}
|
||||
|
||||
public new bool IsKey
|
||||
{
|
||||
get { return base.IsKey.HasTrue(); }
|
||||
set { base.IsKey = value; }
|
||||
}
|
||||
|
||||
public new int NumericScale
|
||||
{
|
||||
get { return base.NumericScale ?? -1; }
|
||||
set { base.NumericScale = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public TestDbColumn()
|
||||
{
|
||||
base.ColumnName = "col";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a basic DbColumn that is an NVARCHAR(128) NULL
|
||||
/// </summary>
|
||||
/// <param name="columnName">Name of the column</param>
|
||||
public TestDbColumn(string columnName)
|
||||
{
|
||||
base.IsLong = false;
|
||||
@@ -18,34 +92,5 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Utility
|
||||
base.DataType = typeof(string);
|
||||
base.DataTypeName = "nvarchar";
|
||||
}
|
||||
|
||||
public TestDbColumn(string columnName, string columnType)
|
||||
: this(columnName)
|
||||
{
|
||||
base.DataTypeName = columnType;
|
||||
}
|
||||
|
||||
public TestDbColumn(string columnName, string columnType, Type columnDataType)
|
||||
{
|
||||
base.IsLong = false;
|
||||
base.ColumnName = columnName;
|
||||
base.ColumnSize = 128;
|
||||
base.AllowDBNull = true;
|
||||
base.DataType = columnDataType;
|
||||
base.DataTypeName = columnType;
|
||||
}
|
||||
|
||||
public TestDbColumn(string columnName, string columnType, int scale)
|
||||
: this(columnName, columnType)
|
||||
{
|
||||
base.NumericScale = scale;
|
||||
}
|
||||
|
||||
public TestDbColumn(string columnName, bool isAutoIncrement)
|
||||
: this(columnName)
|
||||
{
|
||||
base.IsAutoIncrement = isAutoIncrement;
|
||||
base.IsIdentity = isAutoIncrement;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user