mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-02-16 18:47:57 -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.*
|
[Bb]uild[Ll]og.*
|
||||||
test*json
|
test*json
|
||||||
|
|
||||||
|
## Project Rider ##
|
||||||
|
.idea/
|
||||||
|
|
||||||
#NUNIT
|
#NUNIT
|
||||||
*.VisualState.xml
|
*.VisualState.xml
|
||||||
TestResult.xml
|
TestResult.xml
|
||||||
@@ -169,9 +172,6 @@ publish/
|
|||||||
*.nupkg
|
*.nupkg
|
||||||
**/packages/*
|
**/packages/*
|
||||||
|
|
||||||
# NuGet package restore lockfiles
|
|
||||||
project.lock.json
|
|
||||||
|
|
||||||
# Windows Azure Build Output
|
# Windows Azure Build Output
|
||||||
csx/
|
csx/
|
||||||
*.build.csdef
|
*.build.csdef
|
||||||
@@ -243,8 +243,6 @@ $RECYCLE.BIN/
|
|||||||
|
|
||||||
### Linux ###
|
### Linux ###
|
||||||
|
|
||||||
*~
|
|
||||||
|
|
||||||
# KDE directory preferences
|
# KDE directory preferences
|
||||||
.directory
|
.directory
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,12 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.Contracts
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string OwnerUri { get; set; }
|
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>
|
/// <summary>
|
||||||
/// Whether or not the session is ready
|
/// Whether or not the session is ready
|
||||||
/// </summary>
|
/// </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.Hosting;
|
||||||
using Microsoft.SqlTools.ServiceLayer.QueryExecution;
|
using Microsoft.SqlTools.ServiceLayer.QueryExecution;
|
||||||
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts.ExecuteRequests;
|
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts.ExecuteRequests;
|
||||||
using Microsoft.SqlTools.ServiceLayer.Utility;
|
|
||||||
using Microsoft.SqlTools.Utility;
|
using Microsoft.SqlTools.Utility;
|
||||||
using ConnectionType = Microsoft.SqlTools.ServiceLayer.Connection.ConnectionType;
|
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>>(
|
private readonly Lazy<ConcurrentDictionary<string, EditSession>> editSessions = new Lazy<ConcurrentDictionary<string, EditSession>>(
|
||||||
() => new 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
|
#endregion
|
||||||
|
|
||||||
#region Properties
|
#region Properties
|
||||||
@@ -70,12 +65,6 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
internal ConcurrentDictionary<string, EditSession> ActiveSessions => editSessions.Value;
|
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
|
#endregion
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -159,63 +148,32 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
|||||||
internal async Task HandleInitializeRequest(EditInitializeParams initParams,
|
internal async Task HandleInitializeRequest(EditInitializeParams initParams,
|
||||||
RequestContext<EditInitializeResult> requestContext)
|
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
|
try
|
||||||
{
|
{
|
||||||
// Make sure we have info to process this request
|
// Make sure we have info to process this request
|
||||||
Validate.IsNotNullOrWhitespaceString(nameof(initParams.OwnerUri), initParams.OwnerUri);
|
Validate.IsNotNullOrWhitespaceString(nameof(initParams.OwnerUri), initParams.OwnerUri);
|
||||||
Validate.IsNotNullOrWhitespaceString(nameof(initParams.ObjectName), initParams.ObjectName);
|
Validate.IsNotNullOrWhitespaceString(nameof(initParams.ObjectName), initParams.ObjectName);
|
||||||
Validate.IsNotNullOrWhitespaceString(nameof(initParams.ObjectType), initParams.ObjectType);
|
Validate.IsNotNullOrWhitespaceString(nameof(initParams.ObjectType), initParams.ObjectType);
|
||||||
|
|
||||||
// Try to add a new wait handler to the
|
// Create a session and add it to the session list
|
||||||
if (!InitializeWaitHandles.TryAdd(initParams.OwnerUri, new TaskCompletionSource<bool>()))
|
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
|
// Initialize the session
|
||||||
Func<string, Task> queryCreateFailureCallback = async message =>
|
session.Initialize(connector, queryRunner, executionSuccessHandler, executionFailureHandler);
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
await requestContext.SendError(e.Message);
|
await requestContext.SendError(e.Message);
|
||||||
CompleteInitializeWaitHandler(initParams.OwnerUri, false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -313,52 +271,64 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
|||||||
return editSession;
|
return editSession;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task QueryCompleteCallback(Query query, EditInitializeParams initParams,
|
private async Task<EditSession.EditSessionQueryExecutionState> SessionInitializeQueryRunner(string ownerUri,
|
||||||
IEventSender requestContext)
|
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
|
taskCompletion.SetResult(new EditSession.EditSessionQueryExecutionState(q));
|
||||||
ResultSet resultSet = EditSession.ValidateQueryForSession(query);
|
return Task.FromResult(0);
|
||||||
|
};
|
||||||
|
|
||||||
// Get a connection we'll use for SMO metadata lookup (and committing, later on)
|
// Setup callback for failed query execution
|
||||||
DbConnection conn = await connectionService.GetOrOpenConnection(initParams.OwnerUri, ConnectionType.Edit);
|
Query.QueryAsyncEventHandler queryCompleteFailureCallback = q =>
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
// Request that the query be disposed
|
taskCompletion.SetResult(new EditSession.EditSessionQueryExecutionState(null));
|
||||||
await queryExecutionService.InterServiceDisposeQuery(initParams.OwnerUri, null, null);
|
return Task.FromResult(0);
|
||||||
readyParams.Success = false;
|
};
|
||||||
}
|
|
||||||
|
|
||||||
// Send the edit session ready notification
|
// Execute the query
|
||||||
await requestContext.SendEvent(EditSessionReadyEvent.Type, readyParams);
|
ExecuteStringParams executeParams = new ExecuteStringParams
|
||||||
CompleteInitializeWaitHandler(initParams.OwnerUri, true);
|
{
|
||||||
|
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
|
var sessionReadyParams = new EditSessionReadyParams
|
||||||
TaskCompletionSource<bool> initializeWaiter;
|
|
||||||
if (ownerUri != null && InitializeWaitHandles.TryRemove(ownerUri, out initializeWaiter))
|
|
||||||
{
|
{
|
||||||
initializeWaiter.SetResult(result);
|
OwnerUri = ownerUri,
|
||||||
}
|
Message = message,
|
||||||
|
Success = success
|
||||||
|
};
|
||||||
|
|
||||||
|
return eventSender.SendEvent(EditSessionReadyEvent.Type, sessionReadyParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@@ -25,28 +25,37 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
|||||||
public class EditSession
|
public class EditSession
|
||||||
{
|
{
|
||||||
|
|
||||||
private readonly ResultSet associatedResultSet;
|
private ResultSet associatedResultSet;
|
||||||
private readonly IEditTableMetadata objectMetadata;
|
|
||||||
|
private readonly IEditMetadataFactory metadataFactory;
|
||||||
|
private EditTableMetadata objectMetadata;
|
||||||
|
private readonly string objectName;
|
||||||
|
private readonly string objectType;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructs a new edit session bound to the result set and metadat object provided
|
/// Constructs a new edit session bound to the result set and metadat object provided
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="resultSet">The result set of the table to be edited</param>
|
/// <param name="metaFactory">Factory for creating metadata</param>
|
||||||
/// <param name="objMetadata">Metadata provider for the table to be edited</param>
|
/// <param name="objName">The name of the object to edit</param>
|
||||||
public EditSession(ResultSet resultSet, IEditTableMetadata objMetadata)
|
/// <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(metaFactory), metaFactory);
|
||||||
Validate.IsNotNull(nameof(objMetadata), objMetadata);
|
Validate.IsNotNullOrWhitespaceString(nameof(objName), objName);
|
||||||
|
Validate.IsNotNullOrWhitespaceString(nameof(objType), objType);
|
||||||
|
|
||||||
// Setup the internal state
|
// Setup the internal state
|
||||||
associatedResultSet = resultSet;
|
metadataFactory = metaFactory;
|
||||||
objectMetadata = objMetadata;
|
objectName = objName;
|
||||||
NextRowId = associatedResultSet.RowCount;
|
objectType = objType;
|
||||||
EditCache = new ConcurrentDictionary<long, RowEditBase>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Properties
|
#region Properties
|
||||||
|
|
||||||
|
public delegate Task<DbConnection> Connector();
|
||||||
|
|
||||||
|
public delegate Task<EditSessionQueryExecutionState> QueryRunner(string query);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The task that is running to commit the changes to the db
|
/// The task that is running to commit the changes to the db
|
||||||
/// Internal for unit test purposes.
|
/// Internal for unit test purposes.
|
||||||
@@ -61,12 +70,43 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The cache of pending updates. Internal for unit test purposes only
|
/// The cache of pending updates. Internal for unit test purposes only
|
||||||
/// </summary>
|
/// </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
|
#endregion
|
||||||
|
|
||||||
#region Public Methods
|
#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>
|
/// <summary>
|
||||||
/// Validates that a query can be used for an edit session. The target result set is returned
|
/// Validates that a query can be used for an edit session. The target result set is returned
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -100,6 +140,8 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
|||||||
/// <returns>The internal ID of the newly created row</returns>
|
/// <returns>The internal ID of the newly created row</returns>
|
||||||
public EditCreateRowResult CreateRow()
|
public EditCreateRowResult CreateRow()
|
||||||
{
|
{
|
||||||
|
ThrowIfNotInitialized();
|
||||||
|
|
||||||
// Create a new row ID (atomically, since this could be accesses concurrently)
|
// Create a new row ID (atomically, since this could be accesses concurrently)
|
||||||
long newRowId = NextRowId++;
|
long newRowId = NextRowId++;
|
||||||
|
|
||||||
@@ -113,13 +155,13 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set the default values of the row if we know them
|
// Set the default values of the row if we know them
|
||||||
string[] defaultValues = new string[objectMetadata.Columns.Count];
|
string[] defaultValues = new string[objectMetadata.Columns.Length];
|
||||||
for(int i = 0; i < objectMetadata.Columns.Count; i++)
|
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 the column is calculated, return the calculated placeholder as the display value
|
||||||
if (col.IsCalculated)
|
if (col.IsCalculated.HasTrue())
|
||||||
{
|
{
|
||||||
defaultValues[i] = SR.EditDataComputedColumnPlaceholder;
|
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>
|
/// <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)
|
public void CommitEdits(DbConnection connection, Func<Task> successHandler, Func<Exception, Task> errorHandler)
|
||||||
{
|
{
|
||||||
|
ThrowIfNotInitialized();
|
||||||
|
|
||||||
Validate.IsNotNull(nameof(connection), connection);
|
Validate.IsNotNull(nameof(connection), connection);
|
||||||
Validate.IsNotNull(nameof(successHandler), successHandler);
|
Validate.IsNotNull(nameof(successHandler), successHandler);
|
||||||
Validate.IsNotNull(nameof(errorHandler), errorHandler);
|
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>
|
/// <param name="rowId">The internal ID of the row to delete</param>
|
||||||
public void DeleteRow(long rowId)
|
public void DeleteRow(long rowId)
|
||||||
{
|
{
|
||||||
|
ThrowIfNotInitialized();
|
||||||
|
|
||||||
// Sanity check the row ID
|
// Sanity check the row ID
|
||||||
if (rowId >= NextRowId || rowId < 0)
|
if (rowId >= NextRowId || rowId < 0)
|
||||||
{
|
{
|
||||||
@@ -196,6 +242,8 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
|||||||
/// <returns>An array of rows with pending edits applied</returns>
|
/// <returns>An array of rows with pending edits applied</returns>
|
||||||
public async Task<EditRow[]> GetRows(long startIndex, int rowCount)
|
public async Task<EditRow[]> GetRows(long startIndex, int rowCount)
|
||||||
{
|
{
|
||||||
|
ThrowIfNotInitialized();
|
||||||
|
|
||||||
// Get the cached rows from the result set
|
// Get the cached rows from the result set
|
||||||
ResultSetSubset cachedRows = startIndex < associatedResultSet.RowCount
|
ResultSetSubset cachedRows = startIndex < associatedResultSet.RowCount
|
||||||
? await associatedResultSet.GetSubset(startIndex, 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>
|
/// <returns>String version of the old value for the cell</returns>
|
||||||
public string RevertCell(long rowId, int columnId)
|
public string RevertCell(long rowId, int columnId)
|
||||||
{
|
{
|
||||||
|
ThrowIfNotInitialized();
|
||||||
|
|
||||||
// Attempt to get the row edit with the given ID
|
// Attempt to get the row edit with the given ID
|
||||||
RowEditBase pendingEdit;
|
RowEditBase pendingEdit;
|
||||||
if (!EditCache.TryGetValue(rowId, out 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>
|
/// <param name="rowId">The internal ID of the row to reset</param>
|
||||||
public void RevertRow(long rowId)
|
public void RevertRow(long rowId)
|
||||||
{
|
{
|
||||||
|
ThrowIfNotInitialized();
|
||||||
|
|
||||||
// Attempt to remove the row with the given ID
|
// Attempt to remove the row with the given ID
|
||||||
RowEditBase removedEdit;
|
RowEditBase removedEdit;
|
||||||
if (!EditCache.TryRemove(rowId, out removedEdit))
|
if (!EditCache.TryRemove(rowId, out removedEdit))
|
||||||
@@ -284,6 +336,8 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public string ScriptEdits(string outputPath)
|
public string ScriptEdits(string outputPath)
|
||||||
{
|
{
|
||||||
|
ThrowIfNotInitialized();
|
||||||
|
|
||||||
// Validate the output path
|
// Validate the output path
|
||||||
// @TODO: Reinstate this code once we have an interface around file generation
|
// @TODO: Reinstate this code once we have an interface around file generation
|
||||||
//if (outputPath == null)
|
//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>
|
/// <param name="newValue">The new string value of the cell to update</param>
|
||||||
public EditUpdateCellResult UpdateCell(long rowId, int columnId, string newValue)
|
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
|
// Sanity check to make sure that the row ID is in the range of possible values
|
||||||
if (rowId >= NextRowId || rowId < 0)
|
if (rowId >= NextRowId || rowId < 0)
|
||||||
{
|
{
|
||||||
@@ -347,6 +403,38 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
|||||||
|
|
||||||
#endregion
|
#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)
|
private async Task CommitEditsInternal(DbConnection connection, Func<Task> successHandler, Func<Exception, Task> errorHandler)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -378,5 +466,50 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
|||||||
await errorHandler(e);
|
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 System.Data.Common;
|
||||||
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts;
|
|
||||||
|
|
||||||
namespace Microsoft.SqlTools.ServiceLayer.EditData
|
namespace Microsoft.SqlTools.ServiceLayer.EditData
|
||||||
{
|
{
|
||||||
@@ -17,10 +16,9 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
|||||||
/// Generates a edit-ready metadata object
|
/// Generates a edit-ready metadata object
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="connection">Connection to use for getting metadata</param>
|
/// <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="objectName">Name of the object to return metadata for</param>
|
||||||
/// <param name="objectType">Type 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>
|
/// <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;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Data.Common;
|
using System.Data.Common;
|
||||||
using System.Data.SqlClient;
|
using System.Data.SqlClient;
|
||||||
using Microsoft.SqlServer.Management.Common;
|
using Microsoft.SqlServer.Management.Common;
|
||||||
using Microsoft.SqlServer.Management.Smo;
|
using Microsoft.SqlServer.Management.Smo;
|
||||||
using Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection;
|
using Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection;
|
||||||
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts;
|
using Microsoft.SqlTools.ServiceLayer.Utility;
|
||||||
|
|
||||||
namespace Microsoft.SqlTools.ServiceLayer.EditData
|
namespace Microsoft.SqlTools.ServiceLayer.EditData
|
||||||
{
|
{
|
||||||
@@ -22,11 +23,10 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
|||||||
/// Generates a edit-ready metadata object using SMO
|
/// Generates a edit-ready metadata object using SMO
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="connection">Connection to use for getting metadata</param>
|
/// <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="objectName">Name of the object to return metadata for</param>
|
||||||
/// <param name="objectType">Type 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>
|
/// <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
|
// Get a connection to the database for SMO purposes
|
||||||
SqlConnection sqlConn = connection as SqlConnection;
|
SqlConnection sqlConn = connection as SqlConnection;
|
||||||
@@ -44,25 +44,59 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
|||||||
sqlConn = reliableConn.GetUnderlyingConnection();
|
sqlConn = reliableConn.GetUnderlyingConnection();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Connect with SMO and get the metadata for the table
|
||||||
Server server = new Server(new ServerConnection(sqlConn));
|
Server server = new Server(new ServerConnection(sqlConn));
|
||||||
TableViewTableTypeBase result;
|
TableViewTableTypeBase smoResult;
|
||||||
switch (objectType.ToLowerInvariant())
|
switch (objectType.ToLowerInvariant())
|
||||||
{
|
{
|
||||||
case "table":
|
case "table":
|
||||||
result = server.Databases[sqlConn.Database].Tables[objectName];
|
smoResult = server.Databases[sqlConn.Database].Tables[objectName];
|
||||||
break;
|
break;
|
||||||
case "view":
|
case "view":
|
||||||
result = server.Databases[sqlConn.Database].Views[objectName];
|
smoResult = server.Databases[sqlConn.Database].Views[objectName];
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new ArgumentOutOfRangeException(nameof(objectType), SR.EditDataUnsupportedObjectType(objectType));
|
throw new ArgumentOutOfRangeException(nameof(objectType), SR.EditDataUnsupportedObjectType(objectType));
|
||||||
}
|
}
|
||||||
if (result == null)
|
if (smoResult == null)
|
||||||
{
|
{
|
||||||
throw new ArgumentOutOfRangeException(nameof(objectName), SR.EditDataObjectMetadataNotFound);
|
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="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="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>
|
/// <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)
|
: base(rowId, associatedResultSet, associatedMetadata)
|
||||||
{
|
{
|
||||||
newCells = new CellUpdate[associatedResultSet.Columns.Length];
|
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="rowId">Internal ID of the row to be deleted</param>
|
||||||
/// <param name="associatedResultSet">Result set that is being edited</param>
|
/// <param name="associatedResultSet">Result set that is being edited</param>
|
||||||
/// <param name="associatedMetadata">Improved metadata of the object 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)
|
: 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="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="associatedResultSet">The result set that will be updated</param>
|
||||||
/// <param name="associatedMetadata">Metadata provider for the object to edit</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;
|
RowId = rowId;
|
||||||
AssociatedResultSet = associatedResultSet;
|
AssociatedResultSet = associatedResultSet;
|
||||||
@@ -58,7 +58,7 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The metadata for the table this edit is associated to
|
/// The metadata for the table this edit is associated to
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IEditTableMetadata AssociatedObjectMetadata { get; }
|
public EditTableMetadata AssociatedObjectMetadata { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sort ID for a row edit. Ensures that when a collection of RowEditBase objects are
|
/// 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);
|
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
|
// Put together a clause for the value of the cell
|
||||||
DbCellValue cellData = row[col.Ordinal];
|
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="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="associatedResultSet">Result set for the rows of the object to update</param>
|
||||||
/// <param name="associatedMetadata">Metadata provider for 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)
|
: base(rowId, associatedResultSet, associatedMetadata)
|
||||||
{
|
{
|
||||||
cellUpdates = new ConcurrentDictionary<int, CellUpdate>();
|
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"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<root>
|
<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: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:element name="root" msdata:IsDataSet="true">
|
||||||
<xsd:complexType>
|
<xsd:complexType>
|
||||||
<xsd:choice maxOccurs="unbounded">
|
<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:element name="data">
|
||||||
<xsd:complexType>
|
<xsd:complexType>
|
||||||
<xsd:sequence>
|
<xsd:sequence>
|
||||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
<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:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
</xsd:sequence>
|
</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="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
</xsd:complexType>
|
</xsd:complexType>
|
||||||
</xsd:element>
|
</xsd:element>
|
||||||
<xsd:element name="resheader">
|
<xsd:element name="resheader">
|
||||||
@@ -27,106 +105,322 @@
|
|||||||
</xsd:complexType>
|
</xsd:complexType>
|
||||||
</xsd:element>
|
</xsd:element>
|
||||||
</xsd:schema>
|
</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>
|
<resheader name="resmimetype">
|
||||||
<data name="ConnectionServiceListDbErrorNullOwnerUri"><value>OwnerUri no puede ser nulo ni estar vacío</value></data>
|
<value>text/microsoft-resx</value>
|
||||||
<data name="ConnectionServiceListDbErrorNotConnected"><value>SpecifiedUri '{0}' no tiene una conexión existente</value></data>
|
</resheader>
|
||||||
<data name="ConnectionServiceConnStringInvalidAuthType"><value>El valor '{0}' no es válido para AuthenticationType. Los valores válidos son 'Integrated' y 'SqlLogin'.</value></data>
|
<resheader name="version">
|
||||||
<data name="ConnectionServiceConnStringInvalidIntent"><value>El valor '{0}' no es válido para ApplicationIntent. Los valores válidos son 'ReadWrite' y 'ReadOnly'.</value></data>
|
<value>2.0</value>
|
||||||
<data name="ConnectionServiceConnectionCanceled"><value>Conexión cancelada</value></data>
|
</resheader>
|
||||||
<data name="ConnectionParamsValidateNullOwnerUri"><value>OwnerUri no puede ser nulo ni estar vacío</value></data>
|
<resheader name="reader">
|
||||||
<data name="ConnectionParamsValidateNullConnection"><value>El objeto de detalles de conexión no puede ser nulo</value></data>
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
<data name="ConnectionParamsValidateNullServerName"><value>ServerName no puede ser nulo ni estar vacío</value></data>
|
</resheader>
|
||||||
<data name="ConnectionParamsValidateNullSqlAuth"><value>{0} no puede ser nulo ni estar vacío cuando se utiliza autenticación SqlLogin</value></data>
|
<resheader name="writer">
|
||||||
<data name="QueryServiceCancelAlreadyCompleted"><value>Ya se ha completado la consulta, no se puede cancelar</value></data>
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
<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>
|
</resheader>
|
||||||
<data name="QueryServiceQueryCancelled"><value>Consulta cancelada por el usuario</value></data>
|
<data name="ConnectionServiceConnectErrorNullParams" xml:space="preserve">
|
||||||
<data name="QueryServiceSubsetBatchNotCompleted"><value>El lote aún no ha finalizado,</value></data>
|
<value>Los parámetros de conexión no pueden ser nulos</value>
|
||||||
<data name="QueryServiceSubsetBatchOutOfRange"><value>Índice de lote no puede ser menor que 0 o mayor que el número de lotes</value></data>
|
</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="ConnectionServiceListDbErrorNullOwnerUri" xml:space="preserve">
|
||||||
<data name="QueryServiceDataReaderByteCountInvalid"><value>El número máximo de bytes a devolver debe ser mayor que cero</value></data>
|
<value>OwnerUri no puede ser nulo ni estar vacío</value>
|
||||||
<data name="QueryServiceDataReaderCharCountInvalid"><value>El número máximo de caracteres a devolver debe ser mayor que cero</value></data>
|
</data>
|
||||||
<data name="QueryServiceDataReaderXmlCountInvalid"><value>El número máximo de bytes XML a devolver debe ser mayor que cero</value></data>
|
<data name="ConnectionServiceListDbErrorNotConnected" xml:space="preserve">
|
||||||
<data name="QueryServiceFileWrapperWriteOnly"><value>El método de acceso no puede ser de sólo escritura</value></data>
|
<value>SpecifiedUri '{0}' no tiene una conexión existente</value>
|
||||||
<data name="QueryServiceFileWrapperNotInitialized"><value>FileStreamWrapper debe inicializarse antes de realizar operaciones</value></data>
|
</data>
|
||||||
<data name="QueryServiceFileWrapperReadOnly"><value>Este FileStreamWrapper no se puede utilizar para escritura.</value></data>
|
<data name="ConnectionServiceConnStringInvalidAuthType" xml:space="preserve">
|
||||||
<data name="QueryServiceAffectedOneRow"><value>(1 fila afectada)</value></data>
|
<value>El valor '{0}' no es válido para AuthenticationType. Los valores válidos son 'Integrated' y 'SqlLogin'.</value>
|
||||||
<data name="QueryServiceAffectedRows"><value>({0} filas afectadas)</value></data>
|
</data>
|
||||||
<data name="QueryServiceCompletedSuccessfully"><value>Comandos finalizados correctamente.</value></data>
|
<data name="ConnectionServiceConnStringInvalidIntent" xml:space="preserve">
|
||||||
<data name="QueryServiceErrorFormat"><value>Msg {0}, nivel {1} estado {2}, línea {3} {4} {5}</value></data>
|
<value>El valor '{0}' no es válido para ApplicationIntent. Los valores válidos son 'ReadWrite' y 'ReadOnly'.</value>
|
||||||
<data name="QueryServiceQueryFailed"><value>Error en la consulta: {0}</value></data>
|
</data>
|
||||||
<data name="QueryServiceColumnNull"><value>(Ningún nombre de columna)</value></data>
|
<data name="ConnectionServiceConnectionCanceled" xml:space="preserve">
|
||||||
<data name="QueryServiceRequestsNoQuery"><value>La consulta solicitada no existe</value></data>
|
<value>Conexión cancelada</value>
|
||||||
<data name="QueryServiceQueryInvalidOwnerUri"><value>Este editor no está conectado a una base de datos</value></data>
|
</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="ConnectionParamsValidateNullOwnerUri" xml:space="preserve">
|
||||||
<data name="QueryServiceMessageSenderNotSql"><value>Remitente de eventos de OnInfoMessage debe ser un objeto SqlConnection</value></data>
|
<value>OwnerUri no puede ser nulo ni estar vacío</value>
|
||||||
<data name="QueryServiceResultSetReaderNull"><value>Lector no puede ser nulo</value></data>
|
</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="ConnectionParamsValidateNullConnection" xml:space="preserve">
|
||||||
<data name="QueryServiceSaveAsMiscStartingError"><value>Error interno al iniciar el guardado de la tarea</value></data>
|
<value>El objeto de detalles de conexión no puede ser nulo</value>
|
||||||
<data name="QueryServiceSaveAsInProgress"><value>Una operacion de guardado en la misma ruta se encuentra en curso</value></data>
|
</data>
|
||||||
<data name="QueryServiceSaveAsFail"><value>Error al guardar {0}: {1}</value></data>
|
<data name="ConnectionParamsValidateNullServerName" xml:space="preserve">
|
||||||
<data name="QueryServiceResultSetNotRead"><value>No se puede leer el subconjunto, a menos que los resultados se han leído desde el servidor</value></data>
|
<value>ServerName no puede ser nulo ni estar vacío</value>
|
||||||
<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>
|
||||||
<data name="QueryServiceResultSetRowCountOutOfRange"><value>La cantidad de filas debe ser un entero positivo</value></data>
|
<data name="ConnectionParamsValidateNullSqlAuth" xml:space="preserve">
|
||||||
<data name="QueryServiceResultSetNoColumnSchema"><value>No se pudo recuperar el esquema de columna para el conjunto de resultados</value></data>
|
<value>{0} no puede ser nulo ni estar vacío cuando se utiliza autenticación SqlLogin</value>
|
||||||
<data name="QueryServiceExecutionPlanNotFound"><value>No se pudo recuperar un plan de ejecución del conjunto de resultados</value></data>
|
</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="QueryServiceCancelAlreadyCompleted" xml:space="preserve">
|
||||||
<data name="PeekDefinitionError"><value>Se ha producido un error inesperado durante la ejecución de la definición de Peek: {0}</value></data>
|
<value>Ya se ha completado la consulta, no se puede cancelar</value>
|
||||||
<data name="PeekDefinitionNoResultsError"><value>No se encontraron resultados.</value></data>
|
</data>
|
||||||
<data name="PeekDefinitionDatabaseError"><value>No se pudo obtener ningún objeto asociado a la base de datos.</value></data>
|
<data name="QueryServiceCancelDisposeFailed" xml:space="preserve">
|
||||||
<data name="PeekDefinitionNotConnectedError"><value>Conéctese a un servidor.</value></data>
|
<value>La consulta fue cancelada con éxito, pero no se ha podido desechar. No se encontró el URI del propietario.</value>
|
||||||
<data name="PeekDefinitionTimedoutError"><value>Tiempo de espera agotado para esta operación.</value></data>
|
</data>
|
||||||
<data name="PeekDefinitionTypeNotSupportedError"><value>Esta característica no admite actualmente este tipo de objeto.</value></data>
|
<data name="QueryServiceQueryCancelled" xml:space="preserve">
|
||||||
<data name="WorkspaceServicePositionLineOutOfRange"><value>Posición está fuera del intervalo de la línea de archivo</value></data>
|
<value>Consulta cancelada por el usuario</value>
|
||||||
<data name="WorkspaceServicePositionColumnOutOfRange"><value>Posición está fuera del intervalo de la columna de la línea {0}</value></data>
|
</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="QueryServiceSubsetBatchNotCompleted" xml:space="preserve">
|
||||||
<data name="EE_BatchSqlMessageNoProcedureInfo"><value>Msg {0}, {1}, nivel de estado {2}, línea {3}</value></data>
|
<value>El lote aún no ha finalizado,</value>
|
||||||
<data name="EE_BatchSqlMessageWithProcedureInfo"><value>Msj {0}, {1}, nivel de estado {2}, procedimiento {3}, línea {4}</value></data>
|
</data>
|
||||||
<data name="EE_BatchSqlMessageNoLineInfo"><value>Msg {0}, nivel {1}, {2} de estado</value></data>
|
<data name="QueryServiceSubsetBatchOutOfRange" xml:space="preserve">
|
||||||
<data name="EE_BatchError_Exception"><value>Se produjo un error al procesar el lote. Mensaje de error: {0}</value></data>
|
<value>Índice de lote no puede ser menor que 0 o mayor que el número de lotes</value>
|
||||||
<data name="EE_BatchExecutionInfo_RowsAffected"><value>({0} filas afectadas)</value></data>
|
</data>
|
||||||
<data name="EE_ExecutionNotYetCompleteError"><value>La ejecución anterior aún no está completa.</value></data>
|
<data name="QueryServiceSubsetResultSetOutOfRange" xml:space="preserve">
|
||||||
<data name="EE_ScriptError_Error"><value>Se ha producido un error de secuencias de comandos.</value></data>
|
<value>Índice del conjunto de resultados no puede ser menor que 0 o mayor que el número de conjuntos de resultados</value>
|
||||||
<data name="EE_ScriptError_ParsingSyntax"><value>Se encontró sintaxis incorrecta mientras se estaba analizando {0}.</value></data>
|
</data>
|
||||||
<data name="EE_ScriptError_FatalError"><value>Se ha producido un error grave.</value></data>
|
<data name="QueryServiceDataReaderByteCountInvalid" xml:space="preserve">
|
||||||
<data name="EE_ExecutionInfo_FinalizingLoop"><value>La ejecución completó {0} veces...</value></data>
|
<value>El número máximo de bytes a devolver debe ser mayor que cero</value>
|
||||||
<data name="EE_ExecutionInfo_QueryCancelledbyUser"><value>Se canceló la consulta.</value></data>
|
</data>
|
||||||
<data name="EE_BatchExecutionError_Halting"><value>Se produjo un error mientras se ejecutaba el lote.</value></data>
|
<data name="QueryServiceDataReaderCharCountInvalid" xml:space="preserve">
|
||||||
<data name="EE_BatchExecutionError_Ignoring"><value>Se produjo un error mientras se ejecutaba el lote, pero se ha omitido el error.</value></data>
|
<value>El número máximo de caracteres a devolver debe ser mayor que cero</value>
|
||||||
<data name="EE_ExecutionInfo_InitilizingLoop"><value>Iniciando bucle de ejecución de {0} veces...</value></data>
|
</data>
|
||||||
<data name="EE_ExecutionError_CommandNotSupported"><value>No se admite el comando {0}.</value></data>
|
<data name="QueryServiceDataReaderXmlCountInvalid" xml:space="preserve">
|
||||||
<data name="EE_ExecutionError_VariableNotFound"><value>La variable {0} no se encontró.</value></data>
|
<value>El número máximo de bytes XML a devolver debe ser mayor que cero</value>
|
||||||
<data name="BatchParserWrapperExecutionEngineError"><value>Error de ejecución de SQL: {0}</value></data>
|
</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="QueryServiceFileWrapperWriteOnly" xml:space="preserve">
|
||||||
<data name="BatchParserWrapperExecutionEngineBatchMessage"><value>Lote analizador contenedor ejecución motor lote mensaje recibido: mensaje: {0} mensaje detallado: {1}</value></data>
|
<value>El método de acceso no puede ser de sólo escritura</value>
|
||||||
<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>
|
||||||
<data name="BatchParserWrapperExecutionEngineBatchResultSetFinished"><value>Finalizó el elemento ResultSet analizador contenedor ejecución motor los lotes.</value></data>
|
<data name="QueryServiceFileWrapperNotInitialized" xml:space="preserve">
|
||||||
<data name="BatchParserWrapperExecutionEngineBatchCancelling"><value>Cancelando la ejecución por lotes del contenedor del analizador por lotes.</value></data>
|
<value>FileStreamWrapper debe inicializarse antes de realizar operaciones</value>
|
||||||
<data name="EE_ScriptError_Warning"><value>Advertencia de scripting.</value></data>
|
</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="QueryServiceFileWrapperReadOnly" xml:space="preserve">
|
||||||
<data name="BatchParser_CircularReference"><value>El archivo '{0}' se incluyó recursivamente.</value></data>
|
<value>Este FileStreamWrapper no se puede utilizar para escritura.</value>
|
||||||
<data name="BatchParser_CommentNotTerminated"><value>Falta la marca de final de comentario ' * /'.</value></data>
|
</data>
|
||||||
<data name="BatchParser_StringNotTerminated"><value>Sin comilla de cierre después de la cadena de caracteres.</value></data>
|
<data name="QueryServiceAffectedOneRow" xml:space="preserve">
|
||||||
<data name="BatchParser_IncorrectSyntax"><value>Se encontró sintaxis incorrecta al analizar '{0}'.</value></data>
|
<value>(1 fila afectada)</value>
|
||||||
<data name="BatchParser_VariableNotDefined"><value>La variable {0} no está definida.</value></data>
|
</data>
|
||||||
<data name="TestLocalizationConstant"><value>prueba</value></data>
|
<data name="QueryServiceAffectedRows" xml:space="preserve">
|
||||||
<data name="ErrorUnexpectedCodeObjectType"><value>No se puede convertir el SqlCodeObject del Tipo {0} al Tipo {1}</value></data>
|
<value>({0} filas afectadas)</value>
|
||||||
<data name="ErrorEmptyStringReplacement"><value>Sustitución de una cadena vacía por una cadena vacía.</value></data>
|
</data>
|
||||||
<data name="EditDataSessionNotFound"><value>Sesión de edición no existe,</value></data>
|
<data name="QueryServiceCompletedSuccessfully" xml:space="preserve">
|
||||||
<data name="EditDataQueryNotCompleted"><value>La consulta no ha finalizado.</value></data>
|
<value>Comandos finalizados correctamente.</value>
|
||||||
<data name="EditDataQueryImproperResultSets"><value>La consulta no generó un único set de resultados</value></data>
|
</data>
|
||||||
<data name="EditDataFailedAddRow"><value>Falló al agregar una nueva fila a la caché de actualización</value></data>
|
<data name="QueryServiceErrorFormat" xml:space="preserve">
|
||||||
<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>
|
<value>Msg {0}, nivel {1} estado {2}, línea {3} {4} {5}</value>
|
||||||
<data name="EditDataUpdatePending"><value>Una actualización está pendiente para esta fila y debe de revertirse primero</value></data>
|
</data>
|
||||||
<data name="EditDataUpdateNotPending"><value>El ID de la fila ingresado no tiene actualizaciones pendientes</value></data>
|
<data name="QueryServiceQueryFailed" xml:space="preserve">
|
||||||
<data name="EditDataObjectMetadataNotFound"><value>La metadata de la tabla o vista no pudo ser encontrada</value></data>
|
<value>Error en la consulta: {0}</value>
|
||||||
<data name="EditDataInvalidFormatBinary"><value>Formato inválido para columna binaria</value></data>
|
</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="QueryServiceColumnNull" xml:space="preserve">
|
||||||
<data name="EditDataCreateScriptMissingValue"><value>Falta un valor requerido de la celda</value></data>
|
<value>(Ningún nombre de columna)</value>
|
||||||
<data name="EditDataDeleteSetCell"><value>Existe una eliminación pendiente para esta fila, una actualización de celda no puede ser realizada.</value></data>
|
</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="QueryServiceRequestsNoQuery" xml:space="preserve">
|
||||||
<data name="EditDataColumnCannotBeEdited"><value>La columna no puede ser editada</value></data>
|
<value>La consulta solicitada no existe</value>
|
||||||
<data name="EditDataColumnNoKeyColumns"><value>No se encontró ninguna columna clave</value></data>
|
</data>
|
||||||
<data name="EditDataScriptFilePathNull"><value>Proporcione un nombre de archivo de salida</value></data>
|
<data name="QueryServiceQueryInvalidOwnerUri" xml:space="preserve">
|
||||||
<data name="EditDataUnsupportedObjectType"><value>Objeto de base de datos {0} no puede ser usado para modificación.</value></data>
|
<value>Este editor no está conectado a una base de datos</value>
|
||||||
<data name="ConnectionServiceDbErrorDefaultNotConnected"><value>SpecifiedUri '{0}' no tiene alguna conexión por defecto</value></data>
|
</data>
|
||||||
</root>
|
<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">
|
<data name="ConnectionServiceConnectErrorNullParams" xml:space="preserve">
|
||||||
<value>Connection parameters cannot be null</value>
|
<value>Connection parameters cannot be null</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="ConnectionServiceListDbErrorNullOwnerUri" xml:space="preserve">
|
<data name="ConnectionServiceListDbErrorNullOwnerUri" xml:space="preserve">
|
||||||
<value>OwnerUri cannot be null or empty</value>
|
<value>OwnerUri cannot be null or empty</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="ConnectionServiceListDbErrorNotConnected" xml:space="preserve">
|
<data name="ConnectionServiceListDbErrorNotConnected" xml:space="preserve">
|
||||||
<value>SpecifiedUri '{0}' does not have existing connection</value>
|
<value>SpecifiedUri '{0}' does not have existing connection</value>
|
||||||
<comment>.
|
<comment>.
|
||||||
Parameters: 0 - uri (string) </comment>
|
Parameters: 0 - uri (string) </comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="ConnectionServiceDbErrorDefaultNotConnected" xml:space="preserve">
|
<data name="ConnectionServiceDbErrorDefaultNotConnected" xml:space="preserve">
|
||||||
<value>Specified URI '{0}' does not have a default connection</value>
|
<value>Specified URI '{0}' does not have a default connection</value>
|
||||||
<comment>.
|
<comment>.
|
||||||
Parameters: 0 - uri (string) </comment>
|
Parameters: 0 - uri (string) </comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="ConnectionServiceConnStringInvalidAuthType" xml:space="preserve">
|
<data name="ConnectionServiceConnStringInvalidAuthType" xml:space="preserve">
|
||||||
<value>Invalid value '{0}' for AuthenticationType. Valid values are 'Integrated' and 'SqlLogin'.</value>
|
<value>Invalid value '{0}' for AuthenticationType. Valid values are 'Integrated' and 'SqlLogin'.</value>
|
||||||
<comment>.
|
<comment>.
|
||||||
Parameters: 0 - authType (string) </comment>
|
Parameters: 0 - authType (string) </comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="ConnectionServiceConnStringInvalidIntent" xml:space="preserve">
|
<data name="ConnectionServiceConnStringInvalidIntent" xml:space="preserve">
|
||||||
<value>Invalid value '{0}' for ApplicationIntent. Valid values are 'ReadWrite' and 'ReadOnly'.</value>
|
<value>Invalid value '{0}' for ApplicationIntent. Valid values are 'ReadWrite' and 'ReadOnly'.</value>
|
||||||
<comment>.
|
<comment>.
|
||||||
Parameters: 0 - intent (string) </comment>
|
Parameters: 0 - intent (string) </comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="ConnectionServiceConnectionCanceled" xml:space="preserve">
|
<data name="ConnectionServiceConnectionCanceled" xml:space="preserve">
|
||||||
<value>Connection canceled</value>
|
<value>Connection canceled</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="ConnectionParamsValidateNullOwnerUri" xml:space="preserve">
|
<data name="ConnectionParamsValidateNullOwnerUri" xml:space="preserve">
|
||||||
<value>OwnerUri cannot be null or empty</value>
|
<value>OwnerUri cannot be null or empty</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="ConnectionParamsValidateNullConnection" xml:space="preserve">
|
<data name="ConnectionParamsValidateNullConnection" xml:space="preserve">
|
||||||
<value>Connection details object cannot be null</value>
|
<value>Connection details object cannot be null</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="ConnectionParamsValidateNullServerName" xml:space="preserve">
|
<data name="ConnectionParamsValidateNullServerName" xml:space="preserve">
|
||||||
<value>ServerName cannot be null or empty</value>
|
<value>ServerName cannot be null or empty</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="ConnectionParamsValidateNullSqlAuth" xml:space="preserve">
|
<data name="ConnectionParamsValidateNullSqlAuth" xml:space="preserve">
|
||||||
<value>{0} cannot be null or empty when using SqlLogin authentication</value>
|
<value>{0} cannot be null or empty when using SqlLogin authentication</value>
|
||||||
<comment>.
|
<comment>.
|
||||||
Parameters: 0 - component (string) </comment>
|
Parameters: 0 - component (string) </comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="ErrorUnexpectedCodeObjectType" xml:space="preserve">
|
<data name="ErrorUnexpectedCodeObjectType" xml:space="preserve">
|
||||||
<value>Cannot convert SqlCodeObject Type {0} to Type {1}</value>
|
<value>Cannot convert SqlCodeObject Type {0} to Type {1}</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="QueryServiceCancelAlreadyCompleted" xml:space="preserve">
|
<data name="QueryServiceCancelAlreadyCompleted" xml:space="preserve">
|
||||||
<value>The query has already completed, it cannot be cancelled</value>
|
<value>The query has already completed, it cannot be cancelled</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="QueryServiceCancelDisposeFailed" xml:space="preserve">
|
<data name="QueryServiceCancelDisposeFailed" xml:space="preserve">
|
||||||
<value>Query successfully cancelled, failed to dispose query. Owner URI not found.</value>
|
<value>Query successfully cancelled, failed to dispose query. Owner URI not found.</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="QueryServiceQueryCancelled" xml:space="preserve">
|
<data name="QueryServiceQueryCancelled" xml:space="preserve">
|
||||||
<value>Query was canceled by user</value>
|
<value>Query was canceled by user</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="QueryServiceSubsetBatchNotCompleted" xml:space="preserve">
|
<data name="QueryServiceSubsetBatchNotCompleted" xml:space="preserve">
|
||||||
<value>The batch has not completed, yet</value>
|
<value>The batch has not completed, yet</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="QueryServiceSubsetBatchOutOfRange" xml:space="preserve">
|
<data name="QueryServiceSubsetBatchOutOfRange" xml:space="preserve">
|
||||||
<value>Batch index cannot be less than 0 or greater than the number of batches</value>
|
<value>Batch index cannot be less than 0 or greater than the number of batches</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="QueryServiceSubsetResultSetOutOfRange" xml:space="preserve">
|
<data name="QueryServiceSubsetResultSetOutOfRange" xml:space="preserve">
|
||||||
<value>Result set index cannot be less than 0 or greater than the number of result sets</value>
|
<value>Result set index cannot be less than 0 or greater than the number of result sets</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="QueryServiceDataReaderByteCountInvalid" xml:space="preserve">
|
<data name="QueryServiceDataReaderByteCountInvalid" xml:space="preserve">
|
||||||
<value>Maximum number of bytes to return must be greater than zero</value>
|
<value>Maximum number of bytes to return must be greater than zero</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="QueryServiceDataReaderCharCountInvalid" xml:space="preserve">
|
<data name="QueryServiceDataReaderCharCountInvalid" xml:space="preserve">
|
||||||
<value>Maximum number of chars to return must be greater than zero</value>
|
<value>Maximum number of chars to return must be greater than zero</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="QueryServiceDataReaderXmlCountInvalid" xml:space="preserve">
|
<data name="QueryServiceDataReaderXmlCountInvalid" xml:space="preserve">
|
||||||
<value>Maximum number of XML bytes to return must be greater than zero</value>
|
<value>Maximum number of XML bytes to return must be greater than zero</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="QueryServiceFileWrapperWriteOnly" xml:space="preserve">
|
<data name="QueryServiceFileWrapperWriteOnly" xml:space="preserve">
|
||||||
<value>Access method cannot be write-only</value>
|
<value>Access method cannot be write-only</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="QueryServiceFileWrapperNotInitialized" xml:space="preserve">
|
<data name="QueryServiceFileWrapperNotInitialized" xml:space="preserve">
|
||||||
<value>FileStreamWrapper must be initialized before performing operations</value>
|
<value>FileStreamWrapper must be initialized before performing operations</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="QueryServiceFileWrapperReadOnly" xml:space="preserve">
|
<data name="QueryServiceFileWrapperReadOnly" xml:space="preserve">
|
||||||
<value>This FileStreamWrapper cannot be used for writing</value>
|
<value>This FileStreamWrapper cannot be used for writing</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="QueryServiceAffectedOneRow" xml:space="preserve">
|
<data name="QueryServiceAffectedOneRow" xml:space="preserve">
|
||||||
<value>(1 row affected)</value>
|
<value>(1 row affected)</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="QueryServiceAffectedRows" xml:space="preserve">
|
<data name="QueryServiceAffectedRows" xml:space="preserve">
|
||||||
<value>({0} rows affected)</value>
|
<value>({0} rows affected)</value>
|
||||||
<comment>.
|
<comment>.
|
||||||
Parameters: 0 - rows (long) </comment>
|
Parameters: 0 - rows (long) </comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="QueryServiceCompletedSuccessfully" xml:space="preserve">
|
<data name="QueryServiceCompletedSuccessfully" xml:space="preserve">
|
||||||
<value>Commands completed successfully.</value>
|
<value>Commands completed successfully.</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="QueryServiceErrorFormat" xml:space="preserve">
|
<data name="QueryServiceErrorFormat" xml:space="preserve">
|
||||||
<value>Msg {0}, Level {1}, State {2}, Line {3}{4}{5}</value>
|
<value>Msg {0}, Level {1}, State {2}, Line {3}{4}{5}</value>
|
||||||
<comment>.
|
<comment>.
|
||||||
Parameters: 0 - msg (int), 1 - lvl (int), 2 - state (int), 3 - line (int), 4 - newLine (string), 5 - message (string) </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">
|
<data name="QueryServiceQueryFailed" xml:space="preserve">
|
||||||
<value>Query failed: {0}</value>
|
<value>Query failed: {0}</value>
|
||||||
<comment>.
|
<comment>.
|
||||||
Parameters: 0 - message (string) </comment>
|
Parameters: 0 - message (string) </comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="QueryServiceColumnNull" xml:space="preserve">
|
<data name="QueryServiceColumnNull" xml:space="preserve">
|
||||||
<value>(No column name)</value>
|
<value>(No column name)</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="QueryServiceRequestsNoQuery" xml:space="preserve">
|
<data name="QueryServiceRequestsNoQuery" xml:space="preserve">
|
||||||
<value>The requested query does not exist</value>
|
<value>The requested query does not exist</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="QueryServiceQueryInvalidOwnerUri" xml:space="preserve">
|
<data name="QueryServiceQueryInvalidOwnerUri" xml:space="preserve">
|
||||||
<value>This editor is not connected to a database</value>
|
<value>This editor is not connected to a database</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="QueryServiceQueryInProgress" xml:space="preserve">
|
<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>
|
<value>A query is already in progress for this editor session. Please cancel this query or wait for its completion.</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="QueryServiceMessageSenderNotSql" xml:space="preserve">
|
<data name="QueryServiceMessageSenderNotSql" xml:space="preserve">
|
||||||
<value>Sender for OnInfoMessage event must be a SqlConnection</value>
|
<value>Sender for OnInfoMessage event must be a SqlConnection</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="QueryServiceResultSetAddNoRows" xml:space="preserve">
|
<data name="QueryServiceResultSetAddNoRows" xml:space="preserve">
|
||||||
<value>Cannot add row to result buffer, data reader does not contain rows</value>
|
<value>Cannot add row to result buffer, data reader does not contain rows</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="QueryServiceSaveAsResultSetNotComplete" xml:space="preserve">
|
<data name="QueryServiceSaveAsResultSetNotComplete" xml:space="preserve">
|
||||||
<value>Result cannot be saved until query execution has completed</value>
|
<value>Result cannot be saved until query execution has completed</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="QueryServiceSaveAsMiscStartingError" xml:space="preserve">
|
<data name="QueryServiceSaveAsMiscStartingError" xml:space="preserve">
|
||||||
<value>Internal error occurred while starting save task</value>
|
<value>Internal error occurred while starting save task</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="QueryServiceSaveAsInProgress" xml:space="preserve">
|
<data name="QueryServiceSaveAsInProgress" xml:space="preserve">
|
||||||
<value>A save request to the same path is in progress</value>
|
<value>A save request to the same path is in progress</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="QueryServiceSaveAsFail" xml:space="preserve">
|
<data name="QueryServiceSaveAsFail" xml:space="preserve">
|
||||||
<value>Failed to save {0}: {1}</value>
|
<value>Failed to save {0}: {1}</value>
|
||||||
<comment>.
|
<comment>.
|
||||||
Parameters: 0 - fileName (string), 1 - message (string) </comment>
|
Parameters: 0 - fileName (string), 1 - message (string) </comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="QueryServiceResultSetNotRead" xml:space="preserve">
|
<data name="QueryServiceResultSetNotRead" xml:space="preserve">
|
||||||
<value>Cannot read subset unless the results have been read from the server</value>
|
<value>Cannot read subset unless the results have been read from the server</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="QueryServiceResultSetStartRowOutOfRange" xml:space="preserve">
|
<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>
|
<value>Start row cannot be less than 0 or greater than the number of rows in the result set</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="QueryServiceResultSetRowCountOutOfRange" xml:space="preserve">
|
<data name="QueryServiceResultSetRowCountOutOfRange" xml:space="preserve">
|
||||||
<value>Row count must be a positive integer</value>
|
<value>Row count must be a positive integer</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="QueryServiceResultSetNoColumnSchema" xml:space="preserve">
|
<data name="QueryServiceResultSetNoColumnSchema" xml:space="preserve">
|
||||||
<value>Could not retrieve column schema for result set</value>
|
<value>Could not retrieve column schema for result set</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="QueryServiceExecutionPlanNotFound" xml:space="preserve">
|
<data name="QueryServiceExecutionPlanNotFound" xml:space="preserve">
|
||||||
<value>Could not retrieve an execution plan from the result set </value>
|
<value>Could not retrieve an execution plan from the result set </value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="PeekDefinitionAzureError" xml:space="preserve">
|
<data name="PeekDefinitionAzureError" xml:space="preserve">
|
||||||
<value>This feature is currently not supported on Azure SQL DB and Data Warehouse: {0}</value>
|
<value>This feature is currently not supported on Azure SQL DB and Data Warehouse: {0}</value>
|
||||||
<comment>.
|
<comment>.
|
||||||
Parameters: 0 - errorMessage (string) </comment>
|
Parameters: 0 - errorMessage (string) </comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="PeekDefinitionError" xml:space="preserve">
|
<data name="PeekDefinitionError" xml:space="preserve">
|
||||||
<value>An unexpected error occurred during Peek Definition execution: {0}</value>
|
<value>An unexpected error occurred during Peek Definition execution: {0}</value>
|
||||||
<comment>.
|
<comment>.
|
||||||
Parameters: 0 - errorMessage (string) </comment>
|
Parameters: 0 - errorMessage (string) </comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="PeekDefinitionNoResultsError" xml:space="preserve">
|
<data name="PeekDefinitionNoResultsError" xml:space="preserve">
|
||||||
<value>No results were found.</value>
|
<value>No results were found.</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="PeekDefinitionDatabaseError" xml:space="preserve">
|
<data name="PeekDefinitionDatabaseError" xml:space="preserve">
|
||||||
<value>No database object was retrieved.</value>
|
<value>No database object was retrieved.</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="PeekDefinitionNotConnectedError" xml:space="preserve">
|
<data name="PeekDefinitionNotConnectedError" xml:space="preserve">
|
||||||
<value>Please connect to a server.</value>
|
<value>Please connect to a server.</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="PeekDefinitionTimedoutError" xml:space="preserve">
|
<data name="PeekDefinitionTimedoutError" xml:space="preserve">
|
||||||
<value>Operation timed out.</value>
|
<value>Operation timed out.</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="PeekDefinitionTypeNotSupportedError" xml:space="preserve">
|
<data name="PeekDefinitionTypeNotSupportedError" xml:space="preserve">
|
||||||
<value>This object type is currently not supported by this feature.</value>
|
<value>This object type is currently not supported by this feature.</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="ErrorEmptyStringReplacement" xml:space="preserve">
|
<data name="ErrorEmptyStringReplacement" xml:space="preserve">
|
||||||
<value>Replacement of an empty string by an empty string.</value>
|
<value>Replacement of an empty string by an empty string.</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="WorkspaceServicePositionLineOutOfRange" xml:space="preserve">
|
<data name="WorkspaceServicePositionLineOutOfRange" xml:space="preserve">
|
||||||
<value>Position is outside of file line range</value>
|
<value>Position is outside of file line range</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="WorkspaceServicePositionColumnOutOfRange" xml:space="preserve">
|
<data name="WorkspaceServicePositionColumnOutOfRange" xml:space="preserve">
|
||||||
<value>Position is outside of column range for line {0}</value>
|
<value>Position is outside of column range for line {0}</value>
|
||||||
<comment>.
|
<comment>.
|
||||||
Parameters: 0 - line (int) </comment>
|
Parameters: 0 - line (int) </comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="WorkspaceServiceBufferPositionOutOfOrder" xml:space="preserve">
|
<data name="WorkspaceServiceBufferPositionOutOfOrder" xml:space="preserve">
|
||||||
<value>Start position ({0}, {1}) must come before or be equal to the end position ({2}, {3})</value>
|
<value>Start position ({0}, {1}) must come before or be equal to the end position ({2}, {3})</value>
|
||||||
<comment>.
|
<comment>.
|
||||||
Parameters: 0 - sLine (int), 1 - sCol (int), 2 - eLine (int), 3 - eCol (int) </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">
|
<data name="EditDataSessionNotFound" xml:space="preserve">
|
||||||
<value>Edit session does not exist.</value>
|
<value>Edit session does not exist.</value>
|
||||||
<comment></comment>
|
<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">
|
<data name="EditDataUnsupportedObjectType" xml:space="preserve">
|
||||||
<value>Database object {0} cannot be used for editing.</value>
|
<value>Database object {0} cannot be used for editing.</value>
|
||||||
<comment>.
|
<comment>.
|
||||||
Parameters: 0 - typeName (string) </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">
|
<data name="EditDataQueryNotCompleted" xml:space="preserve">
|
||||||
<value>Query has not completed execution</value>
|
<value>Query has not completed execution</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="EditDataQueryImproperResultSets" xml:space="preserve">
|
<data name="EditDataQueryImproperResultSets" xml:space="preserve">
|
||||||
<value>Query did not generate exactly one result set</value>
|
<value>Query did not generate exactly one result set</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="EditDataFailedAddRow" xml:space="preserve">
|
<data name="EditDataFailedAddRow" xml:space="preserve">
|
||||||
<value>Failed to add new row to update cache</value>
|
<value>Failed to add new row to update cache</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="EditDataRowOutOfRange" xml:space="preserve">
|
<data name="EditDataRowOutOfRange" xml:space="preserve">
|
||||||
<value>Given row ID is outside the range of rows in the edit cache</value>
|
<value>Given row ID is outside the range of rows in the edit cache</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="EditDataUpdatePending" xml:space="preserve">
|
<data name="EditDataUpdatePending" xml:space="preserve">
|
||||||
<value>An update is already pending for this row and must be reverted first</value>
|
<value>An update is already pending for this row and must be reverted first</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="EditDataUpdateNotPending" xml:space="preserve">
|
<data name="EditDataUpdateNotPending" xml:space="preserve">
|
||||||
<value>Given row ID does not have pending update</value>
|
<value>Given row ID does not have pending update</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="EditDataColumnUpdateNotPending" xml:space="preserve">
|
<data name="EditDataColumnUpdateNotPending" xml:space="preserve">
|
||||||
<value>Give column ID does not have pending update</value>
|
<value>Give column ID does not have pending update</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="EditDataObjectMetadataNotFound" xml:space="preserve">
|
<data name="EditDataObjectMetadataNotFound" xml:space="preserve">
|
||||||
<value>Table or view metadata could not be found</value>
|
<value>Table or view metadata could not be found</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="EditDataInvalidFormatBinary" xml:space="preserve">
|
<data name="EditDataInvalidFormatBinary" xml:space="preserve">
|
||||||
<value>Invalid format for binary column</value>
|
<value>Invalid format for binary column</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="EditDataInvalidFormatBoolean" xml:space="preserve">
|
<data name="EditDataInvalidFormatBoolean" xml:space="preserve">
|
||||||
<value>Allowed values for boolean columns are 0, 1, "true", or "false"</value>
|
<value>Allowed values for boolean columns are 0, 1, "true", or "false"</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="EditDataCreateScriptMissingValue" xml:space="preserve">
|
<data name="EditDataCreateScriptMissingValue" xml:space="preserve">
|
||||||
<value>A required cell value is missing</value>
|
<value>A required cell value is missing</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="EditDataDeleteSetCell" xml:space="preserve">
|
<data name="EditDataDeleteSetCell" xml:space="preserve">
|
||||||
<value>A delete is pending for this row, a cell update cannot be applied.</value>
|
<value>A delete is pending for this row, a cell update cannot be applied.</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="EditDataColumnIdOutOfRange" xml:space="preserve">
|
<data name="EditDataColumnIdOutOfRange" xml:space="preserve">
|
||||||
<value>Column ID must be in the range of columns for the query</value>
|
<value>Column ID must be in the range of columns for the query</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="EditDataColumnCannotBeEdited" xml:space="preserve">
|
<data name="EditDataColumnCannotBeEdited" xml:space="preserve">
|
||||||
<value>Column cannot be edited</value>
|
<value>Column cannot be edited</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="EditDataColumnNoKeyColumns" xml:space="preserve">
|
<data name="EditDataColumnNoKeyColumns" xml:space="preserve">
|
||||||
<value>No key columns were found</value>
|
<value>No key columns were found</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="EditDataScriptFilePathNull" xml:space="preserve">
|
<data name="EditDataScriptFilePathNull" xml:space="preserve">
|
||||||
<value>An output filename must be provided</value>
|
<value>An output filename must be provided</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="EditDataCommitInProgress" xml:space="preserve">
|
<data name="EditDataCommitInProgress" xml:space="preserve">
|
||||||
<value>A commit task is in progress. Please wait for completion.</value>
|
<value>A commit task is in progress. Please wait for completion.</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="EditDataComputedColumnPlaceholder" xml:space="preserve">
|
<data name="EditDataComputedColumnPlaceholder" xml:space="preserve">
|
||||||
<value><TBD></value>
|
<value><TBD></value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="EditDataInitializeInProgress" xml:space="preserve">
|
<data name="EditDataInitializeInProgress" xml:space="preserve">
|
||||||
<value>Another edit data initialize is in progress for this owner URI. Please wait for completion.</value>
|
<value>Another edit data initialize is in progress for this owner URI. Please wait for completion.</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="EditDataTimeOver24Hrs" xml:space="preserve">
|
<data name="EditDataTimeOver24Hrs" xml:space="preserve">
|
||||||
<value>TIME column values must be between 00:00:00.0000000 and 23:59:59.9999999</value>
|
<value>TIME column values must be between 00:00:00.0000000 and 23:59:59.9999999</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="EditDataNullNotAllowed" xml:space="preserve">
|
<data name="EditDataNullNotAllowed" xml:space="preserve">
|
||||||
<value>NULL is not allowed for this column</value>
|
<value>NULL is not allowed for this column</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="EE_BatchSqlMessageNoProcedureInfo" xml:space="preserve">
|
<data name="EE_BatchSqlMessageNoProcedureInfo" xml:space="preserve">
|
||||||
<value>Msg {0}, Level {1}, State {2}, Line {3}</value>
|
<value>Msg {0}, Level {1}, State {2}, Line {3}</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="EE_BatchSqlMessageWithProcedureInfo" xml:space="preserve">
|
<data name="EE_BatchSqlMessageWithProcedureInfo" xml:space="preserve">
|
||||||
<value>Msg {0}, Level {1}, State {2}, Procedure {3}, Line {4}</value>
|
<value>Msg {0}, Level {1}, State {2}, Procedure {3}, Line {4}</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="EE_BatchSqlMessageNoLineInfo" xml:space="preserve">
|
<data name="EE_BatchSqlMessageNoLineInfo" xml:space="preserve">
|
||||||
<value>Msg {0}, Level {1}, State {2}</value>
|
<value>Msg {0}, Level {1}, State {2}</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="EE_BatchError_Exception" xml:space="preserve">
|
<data name="EE_BatchError_Exception" xml:space="preserve">
|
||||||
<value>An error occurred while the batch was being processed. The error message is: {0}</value>
|
<value>An error occurred while the batch was being processed. The error message is: {0}</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="EE_BatchExecutionInfo_RowsAffected" xml:space="preserve">
|
<data name="EE_BatchExecutionInfo_RowsAffected" xml:space="preserve">
|
||||||
<value>({0} row(s) affected)</value>
|
<value>({0} row(s) affected)</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="EE_ExecutionNotYetCompleteError" xml:space="preserve">
|
<data name="EE_ExecutionNotYetCompleteError" xml:space="preserve">
|
||||||
<value>The previous execution is not yet complete.</value>
|
<value>The previous execution is not yet complete.</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="EE_ScriptError_Error" xml:space="preserve">
|
<data name="EE_ScriptError_Error" xml:space="preserve">
|
||||||
<value>A scripting error occurred.</value>
|
<value>A scripting error occurred.</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="EE_ScriptError_ParsingSyntax" xml:space="preserve">
|
<data name="EE_ScriptError_ParsingSyntax" xml:space="preserve">
|
||||||
<value>Incorrect syntax was encountered while {0} was being parsed.</value>
|
<value>Incorrect syntax was encountered while {0} was being parsed.</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="EE_ScriptError_FatalError" xml:space="preserve">
|
<data name="EE_ScriptError_FatalError" xml:space="preserve">
|
||||||
<value>A fatal error occurred.</value>
|
<value>A fatal error occurred.</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="EE_ExecutionInfo_FinalizingLoop" xml:space="preserve">
|
<data name="EE_ExecutionInfo_FinalizingLoop" xml:space="preserve">
|
||||||
<value>Execution completed {0} times...</value>
|
<value>Execution completed {0} times...</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="EE_ExecutionInfo_QueryCancelledbyUser" xml:space="preserve">
|
<data name="EE_ExecutionInfo_QueryCancelledbyUser" xml:space="preserve">
|
||||||
<value>You cancelled the query.</value>
|
<value>You cancelled the query.</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="EE_BatchExecutionError_Halting" xml:space="preserve">
|
<data name="EE_BatchExecutionError_Halting" xml:space="preserve">
|
||||||
<value>An error occurred while the batch was being executed.</value>
|
<value>An error occurred while the batch was being executed.</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="EE_BatchExecutionError_Ignoring" xml:space="preserve">
|
<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>
|
<value>An error occurred while the batch was being executed, but the error has been ignored.</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="EE_ExecutionInfo_InitilizingLoop" xml:space="preserve">
|
<data name="EE_ExecutionInfo_InitilizingLoop" xml:space="preserve">
|
||||||
<value>Starting execution loop of {0} times...</value>
|
<value>Starting execution loop of {0} times...</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="EE_ExecutionError_CommandNotSupported" xml:space="preserve">
|
<data name="EE_ExecutionError_CommandNotSupported" xml:space="preserve">
|
||||||
<value>Command {0} is not supported.</value>
|
<value>Command {0} is not supported.</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="EE_ExecutionError_VariableNotFound" xml:space="preserve">
|
<data name="EE_ExecutionError_VariableNotFound" xml:space="preserve">
|
||||||
<value>The variable {0} could not be found.</value>
|
<value>The variable {0} could not be found.</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="BatchParserWrapperExecutionEngineError" xml:space="preserve">
|
<data name="BatchParserWrapperExecutionEngineError" xml:space="preserve">
|
||||||
<value>SQL Execution error: {0}</value>
|
<value>SQL Execution error: {0}</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="BatchParserWrapperExecutionError" xml:space="preserve">
|
<data name="BatchParserWrapperExecutionError" xml:space="preserve">
|
||||||
<value>Batch parser wrapper execution: {0} found... at line {1}: {2} Description: {3}</value>
|
<value>Batch parser wrapper execution: {0} found... at line {1}: {2} Description: {3}</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="BatchParserWrapperExecutionEngineBatchMessage" xml:space="preserve">
|
<data name="BatchParserWrapperExecutionEngineBatchMessage" xml:space="preserve">
|
||||||
<value>Batch parser wrapper execution engine batch message received: Message: {0} Detailed message: {1}</value>
|
<value>Batch parser wrapper execution engine batch message received: Message: {0} Detailed message: {1}</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="BatchParserWrapperExecutionEngineBatchResultSetProcessing" xml:space="preserve">
|
<data name="BatchParserWrapperExecutionEngineBatchResultSetProcessing" xml:space="preserve">
|
||||||
<value>Batch parser wrapper execution engine batch ResultSet processing: DataReader.FieldCount: {0} DataReader.RecordsAffected: {1}</value>
|
<value>Batch parser wrapper execution engine batch ResultSet processing: DataReader.FieldCount: {0} DataReader.RecordsAffected: {1}</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="BatchParserWrapperExecutionEngineBatchResultSetFinished" xml:space="preserve">
|
<data name="BatchParserWrapperExecutionEngineBatchResultSetFinished" xml:space="preserve">
|
||||||
<value>Batch parser wrapper execution engine batch ResultSet finished.</value>
|
<value>Batch parser wrapper execution engine batch ResultSet finished.</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="BatchParserWrapperExecutionEngineBatchCancelling" xml:space="preserve">
|
<data name="BatchParserWrapperExecutionEngineBatchCancelling" xml:space="preserve">
|
||||||
<value>Canceling batch parser wrapper batch execution.</value>
|
<value>Canceling batch parser wrapper batch execution.</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="EE_ScriptError_Warning" xml:space="preserve">
|
<data name="EE_ScriptError_Warning" xml:space="preserve">
|
||||||
<value>Scripting warning.</value>
|
<value>Scripting warning.</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="TroubleshootingAssistanceMessage" xml:space="preserve">
|
<data name="TroubleshootingAssistanceMessage" xml:space="preserve">
|
||||||
<value>For more information about this error, see the troubleshooting topics in the product documentation.</value>
|
<value>For more information about this error, see the troubleshooting topics in the product documentation.</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="BatchParser_CircularReference" xml:space="preserve">
|
<data name="BatchParser_CircularReference" xml:space="preserve">
|
||||||
<value>File '{0}' recursively included.</value>
|
<value>File '{0}' recursively included.</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="BatchParser_CommentNotTerminated" xml:space="preserve">
|
<data name="BatchParser_CommentNotTerminated" xml:space="preserve">
|
||||||
<value>Missing end comment mark '*/'.</value>
|
<value>Missing end comment mark '*/'.</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="BatchParser_StringNotTerminated" xml:space="preserve">
|
<data name="BatchParser_StringNotTerminated" xml:space="preserve">
|
||||||
<value>Unclosed quotation mark after the character string.</value>
|
<value>Unclosed quotation mark after the character string.</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="BatchParser_IncorrectSyntax" xml:space="preserve">
|
<data name="BatchParser_IncorrectSyntax" xml:space="preserve">
|
||||||
<value>Incorrect syntax was encountered while parsing '{0}'.</value>
|
<value>Incorrect syntax was encountered while parsing '{0}'.</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="BatchParser_VariableNotDefined" xml:space="preserve">
|
<data name="BatchParser_VariableNotDefined" xml:space="preserve">
|
||||||
<value>Variable {0} is not defined.</value>
|
<value>Variable {0} is not defined.</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="TestLocalizationConstant" xml:space="preserve">
|
<data name="TestLocalizationConstant" xml:space="preserve">
|
||||||
<value>EN_LOCALIZATION</value>
|
<value>EN_LOCALIZATION</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="SqlScriptFormatterDecimalMissingPrecision" xml:space="preserve">
|
<data name="SqlScriptFormatterDecimalMissingPrecision" xml:space="preserve">
|
||||||
<value>Decimal column is missing numeric precision or numeric scale</value>
|
<value>Decimal column is missing numeric precision or numeric scale</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|||||||
@@ -164,10 +164,22 @@ WorkspaceServiceBufferPositionOutOfOrder(int sLine, int sCol, int eLine, int eCo
|
|||||||
############################################################################
|
############################################################################
|
||||||
# Edit Data Service
|
# Edit Data Service
|
||||||
|
|
||||||
|
EditDataObjectNotFound = Table or view requested for edit could not be found
|
||||||
|
|
||||||
EditDataSessionNotFound = Edit session does not exist.
|
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.
|
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
|
EditDataQueryNotCompleted = Query has not completed execution
|
||||||
|
|
||||||
EditDataQueryImproperResultSets = Query did not generate exactly one result set
|
EditDataQueryImproperResultSets = Query did not generate exactly one result set
|
||||||
|
|||||||
@@ -561,6 +561,36 @@
|
|||||||
<target state="new">NULL is not allowed for this column</target>
|
<target state="new">NULL is not allowed for this column</target>
|
||||||
<note></note>
|
<note></note>
|
||||||
</trans-unit>
|
</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>
|
</body>
|
||||||
</file>
|
</file>
|
||||||
</xliff>
|
</xliff>
|
||||||
@@ -29,7 +29,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
|
|||||||
AddSupportedType(DeclarationType.Synonym, GetSynonymScripts, "Synonym", "");
|
AddSupportedType(DeclarationType.Synonym, GetSynonymScripts, "Synonym", "");
|
||||||
AddSupportedType(DeclarationType.ScalarValuedFunction, GetScalarValuedFunctionScripts, "Function", "scalar-valued function");
|
AddSupportedType(DeclarationType.ScalarValuedFunction, GetScalarValuedFunctionScripts, "Function", "scalar-valued function");
|
||||||
AddSupportedType(DeclarationType.TableValuedFunction, GetTableValuedFunctionScripts, "Function", "table-valued function");
|
AddSupportedType(DeclarationType.TableValuedFunction, GetTableValuedFunctionScripts, "Function", "table-valued function");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Script a Table using SMO
|
/// Script a Table using SMO
|
||||||
@@ -50,7 +50,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
|
|||||||
Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetTableScripts : " + ex.Message);
|
Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetTableScripts : " + ex.Message);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Script a View using SMO
|
/// Script a View using SMO
|
||||||
@@ -71,7 +71,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
|
|||||||
Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetViewScripts : " + ex.Message);
|
Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetViewScripts : " + ex.Message);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Script a StoredProcedure using SMO
|
/// Script a StoredProcedure using SMO
|
||||||
@@ -92,7 +92,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
|
|||||||
Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetStoredProcedureScripts : " + ex.Message);
|
Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetStoredProcedureScripts : " + ex.Message);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Script a UserDefinedDataType using SMO
|
/// Script a UserDefinedDataType using SMO
|
||||||
@@ -113,7 +113,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
|
|||||||
Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetUserDefinedDataTypeScripts : " + ex.Message);
|
Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetUserDefinedDataTypeScripts : " + ex.Message);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Script a UserDefinedTableType using SMO
|
/// Script a UserDefinedTableType using SMO
|
||||||
@@ -134,7 +134,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
|
|||||||
Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetUserDefinedTableTypeScripts : " + ex.Message);
|
Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetUserDefinedTableTypeScripts : " + ex.Message);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Script a Synonym using SMO
|
/// Script a Synonym using SMO
|
||||||
@@ -155,7 +155,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
|
|||||||
Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetSynonymScripts : " + ex.Message);
|
Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetSynonymScripts : " + ex.Message);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Script a ScalarValuedFunction using SMO
|
/// Script a ScalarValuedFunction using SMO
|
||||||
@@ -176,7 +176,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
|
|||||||
Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetScalarValuedFunctionScripts : " + ex.Message);
|
Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetScalarValuedFunctionScripts : " + ex.Message);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Script a TableValuedFunction using SMO
|
/// Script a TableValuedFunction using SMO
|
||||||
@@ -197,7 +197,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
|
|||||||
Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetTableValuedFunctionScripts : " + ex.Message);
|
Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetTableValuedFunctionScripts : " + ex.Message);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,13 +7,13 @@ using System.Collections.Generic;
|
|||||||
using System.Data.Common;
|
using System.Data.Common;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Microsoft.SqlTools.ServiceLayer.EditData;
|
using Microsoft.SqlTools.ServiceLayer.EditData;
|
||||||
using Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement;
|
using Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement;
|
||||||
using Microsoft.SqlTools.ServiceLayer.QueryExecution;
|
using Microsoft.SqlTools.ServiceLayer.QueryExecution;
|
||||||
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts;
|
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts;
|
||||||
using Microsoft.SqlTools.ServiceLayer.Test.Common;
|
using Microsoft.SqlTools.ServiceLayer.Test.Common;
|
||||||
using Microsoft.SqlTools.ServiceLayer.UnitTests.Utility;
|
using Microsoft.SqlTools.ServiceLayer.UnitTests.Utility;
|
||||||
using Microsoft.SqlTools.Utility;
|
|
||||||
using Moq;
|
using Moq;
|
||||||
|
|
||||||
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||||
@@ -22,18 +22,49 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
{
|
{
|
||||||
public const string OwnerUri = "testFile";
|
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) =>
|
var columnMetas = columns.Select((c, i) =>
|
||||||
new EditColumnWrapper
|
{
|
||||||
|
var ecm = new EditColumnMetadata
|
||||||
{
|
{
|
||||||
DbColumn = new DbColumnWrapper(c),
|
|
||||||
EscapedName = c.ColumnName,
|
EscapedName = c.ColumnName,
|
||||||
Ordinal = i,
|
Ordinal = i
|
||||||
IsKey = c.IsIdentity.HasTrue()
|
};
|
||||||
}).ToArray();
|
return ecm;
|
||||||
return GetMetadataProvider(columnMetas, allKeys, isMemoryOptimized);
|
}).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)
|
public static DbColumn[] GetColumns(bool includeIdentity)
|
||||||
@@ -42,7 +73,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
|
|
||||||
if (includeIdentity)
|
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++)
|
for (int i = 0; i < 3; i++)
|
||||||
@@ -52,7 +83,14 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
return columns.ToArray();
|
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
|
IEnumerable<object[]> rows = includeIdentity
|
||||||
? Enumerable.Repeat(new object[] { "id", "1", "2", "3" }, rowCount)
|
? 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 testResultSet = new TestResultSet(columns, rows);
|
||||||
var reader = new TestDbDataReader(new[] { testResultSet });
|
var reader = new TestDbDataReader(new[] { testResultSet });
|
||||||
var resultSet = new ResultSet(0, 0, MemoryFileSystem.GetFileStreamFactory());
|
var resultSet = new ResultSet(0, 0, MemoryFileSystem.GetFileStreamFactory());
|
||||||
resultSet.ReadResultToEnd(reader, CancellationToken.None).Wait();
|
await resultSet.ReadResultToEnd(reader, CancellationToken.None);
|
||||||
return resultSet;
|
return resultSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,26 +120,5 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
rc.SetCell(i, "123");
|
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
|
public class RowCreateTests
|
||||||
{
|
{
|
||||||
[Fact]
|
[Fact]
|
||||||
public void RowCreateConstruction()
|
public async Task RowCreateConstruction()
|
||||||
{
|
{
|
||||||
// Setup: Create the values to store
|
// Setup: Create the values to store
|
||||||
const long rowId = 100;
|
const long rowId = 100;
|
||||||
DbColumn[] columns = Common.GetColumns(false);
|
DbColumn[] columns = Common.GetColumns(false);
|
||||||
ResultSet rs = Common.GetResultSet(columns, false);
|
ResultSet rs = await Common.GetResultSet(columns, false);
|
||||||
IEditTableMetadata etm = Common.GetStandardMetadata(columns);
|
EditTableMetadata etm = Common.GetStandardMetadata(columns);
|
||||||
|
|
||||||
// If: I create a RowCreate instance
|
// If: I create a RowCreate instance
|
||||||
RowCreate rc = new RowCreate(rowId, rs, etm);
|
RowCreate rc = new RowCreate(rowId, rs, etm);
|
||||||
@@ -42,13 +42,13 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
[Theory]
|
[Theory]
|
||||||
[InlineData(true)]
|
[InlineData(true)]
|
||||||
[InlineData(false)]
|
[InlineData(false)]
|
||||||
public void GetScript(bool includeIdentity)
|
public async Task GetScript(bool includeIdentity)
|
||||||
{
|
{
|
||||||
// Setup: Generate the parameters for the row create
|
// Setup: Generate the parameters for the row create
|
||||||
const long rowId = 100;
|
const long rowId = 100;
|
||||||
DbColumn[] columns = Common.GetColumns(includeIdentity);
|
DbColumn[] columns = Common.GetColumns(includeIdentity);
|
||||||
ResultSet rs = Common.GetResultSet(columns, includeIdentity);
|
ResultSet rs = await Common.GetResultSet(columns, includeIdentity);
|
||||||
IEditTableMetadata etm = Common.GetStandardMetadata(columns);
|
EditTableMetadata etm = Common.GetStandardMetadata(columns);
|
||||||
|
|
||||||
// If: I ask for a script to be generated without an identity column
|
// If: I ask for a script to be generated without an identity column
|
||||||
RowCreate rc = new RowCreate(rowId, rs, etm);
|
RowCreate rc = new RowCreate(rowId, rs, etm);
|
||||||
@@ -74,10 +74,10 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GetScriptMissingCell()
|
public async Task GetScriptMissingCell()
|
||||||
{
|
{
|
||||||
// Setup: Generate the parameters for the row create
|
// 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
|
// If: I ask for a script to be generated without setting any values
|
||||||
// Then: An exception should be thrown for missing cells
|
// 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
|
// ... Generate the parameters for the row create
|
||||||
const long rowId = 100;
|
const long rowId = 100;
|
||||||
DbColumn[] columns = Common.GetColumns(includeIdentity);
|
DbColumn[] columns = Common.GetColumns(includeIdentity);
|
||||||
ResultSet rs = Common.GetResultSet(columns, includeIdentity);
|
ResultSet rs = await Common.GetResultSet(columns, includeIdentity);
|
||||||
IEditTableMetadata etm = Common.GetStandardMetadata(columns);
|
EditTableMetadata etm = Common.GetStandardMetadata(columns);
|
||||||
|
|
||||||
// ... Setup a db reader for the result of an insert
|
// ... Setup a db reader for the result of an insert
|
||||||
var newRowReader = Common.GetNewRowDataReader(columns, includeIdentity);
|
var newRowReader = Common.GetNewRowDataReader(columns, includeIdentity);
|
||||||
@@ -110,13 +110,13 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
[Theory]
|
[Theory]
|
||||||
[InlineData(true)]
|
[InlineData(true)]
|
||||||
[InlineData(false)]
|
[InlineData(false)]
|
||||||
public void GetCommand(bool includeIdentity)
|
public async Task GetCommand(bool includeIdentity)
|
||||||
{
|
{
|
||||||
// Setup:
|
// Setup:
|
||||||
// ... Create a row create with cell updates
|
// ... Create a row create with cell updates
|
||||||
const long rowId = 100;
|
const long rowId = 100;
|
||||||
var columns = Common.GetColumns(includeIdentity);
|
var columns = Common.GetColumns(includeIdentity);
|
||||||
var rs = Common.GetResultSet(columns, includeIdentity);
|
var rs = await Common.GetResultSet(columns, includeIdentity);
|
||||||
var etm = Common.GetStandardMetadata(columns);
|
var etm = Common.GetStandardMetadata(columns);
|
||||||
RowCreate rc = new RowCreate(rowId, rs, etm);
|
RowCreate rc = new RowCreate(rowId, rs, etm);
|
||||||
Common.AddCells(rc, includeIdentity);
|
Common.AddCells(rc, includeIdentity);
|
||||||
@@ -159,10 +159,10 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GetCommandNullConnection()
|
public async Task GetCommandNullConnection()
|
||||||
{
|
{
|
||||||
// Setup: Create a row create
|
// Setup: Create a row create
|
||||||
RowCreate rc = GetStandardRowCreate();
|
RowCreate rc = await GetStandardRowCreate();
|
||||||
|
|
||||||
|
|
||||||
// If: I attempt to create a command with a null connection
|
// If: I attempt to create a command with a null connection
|
||||||
@@ -171,10 +171,10 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GetCommandMissingCell()
|
public async Task GetCommandMissingCell()
|
||||||
{
|
{
|
||||||
// Setup: Generate the parameters for the row create
|
// Setup: Generate the parameters for the row create
|
||||||
RowCreate rc = GetStandardRowCreate();
|
RowCreate rc = await GetStandardRowCreate();
|
||||||
var mockConn = new TestSqlConnection(null);
|
var mockConn = new TestSqlConnection(null);
|
||||||
|
|
||||||
// If: I ask for a script to be generated without setting any values
|
// If: I ask for a script to be generated without setting any values
|
||||||
@@ -183,10 +183,10 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GetEditRowNoAdditions()
|
public async Task GetEditRowNoAdditions()
|
||||||
{
|
{
|
||||||
// Setup: Generate a standard row create
|
// Setup: Generate a standard row create
|
||||||
RowCreate rc = GetStandardRowCreate();
|
RowCreate rc = await GetStandardRowCreate();
|
||||||
|
|
||||||
// If: I request an edit row from the row create
|
// If: I request an edit row from the row create
|
||||||
EditRow er = rc.GetEditRow(null);
|
EditRow er = rc.GetEditRow(null);
|
||||||
@@ -209,10 +209,10 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GetEditRowWithAdditions()
|
public async Task GetEditRowWithAdditions()
|
||||||
{
|
{
|
||||||
// Setp: Generate a row create with a cell added to it
|
// Setp: Generate a row create with a cell added to it
|
||||||
RowCreate rc = GetStandardRowCreate();
|
RowCreate rc = await GetStandardRowCreate();
|
||||||
rc.SetCell(0, "foo");
|
rc.SetCell(0, "foo");
|
||||||
|
|
||||||
// If: I request an edit row from the row create
|
// If: I request an edit row from the row create
|
||||||
@@ -244,20 +244,20 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
[InlineData(-1)] // Negative
|
[InlineData(-1)] // Negative
|
||||||
[InlineData(3)] // At edge of acceptable values
|
[InlineData(3)] // At edge of acceptable values
|
||||||
[InlineData(100)] // Way too large value
|
[InlineData(100)] // Way too large value
|
||||||
public void SetCellOutOfRange(int columnId)
|
public async Task SetCellOutOfRange(int columnId)
|
||||||
{
|
{
|
||||||
// Setup: Generate a row create
|
// 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
|
// 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));
|
Assert.Throws<ArgumentOutOfRangeException>(() => rc.SetCell(columnId, string.Empty));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void SetCellNoChange()
|
public async Task SetCellNoChange()
|
||||||
{
|
{
|
||||||
// Setup: Generate a row create
|
// 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
|
// If: I set a cell in the newly created row to something that doesn't need changing
|
||||||
EditUpdateCellResult eucr = rc.SetCell(0, "1");
|
EditUpdateCellResult eucr = rc.SetCell(0, "1");
|
||||||
@@ -278,16 +278,20 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void SetCellHasCorrections()
|
public async Task SetCellHasCorrections()
|
||||||
{
|
{
|
||||||
// Setup:
|
// Setup:
|
||||||
// ... Generate a result set with a single binary column
|
// ... 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 = {};
|
object[][] rows = {};
|
||||||
var testResultSet = new TestResultSet(cols, rows);
|
var testResultSet = new TestResultSet(cols, rows);
|
||||||
var testReader = new TestDbDataReader(new[] {testResultSet});
|
var testReader = new TestDbDataReader(new[] {testResultSet});
|
||||||
var rs = new ResultSet(0, 0, MemoryFileSystem.GetFileStreamFactory());
|
var rs = new ResultSet(0, 0, MemoryFileSystem.GetFileStreamFactory());
|
||||||
rs.ReadResultToEnd(testReader, CancellationToken.None).Wait();
|
await rs.ReadResultToEnd(testReader, CancellationToken.None);
|
||||||
|
|
||||||
// ... Generate the metadata
|
// ... Generate the metadata
|
||||||
var etm = Common.GetStandardMetadata(cols);
|
var etm = Common.GetStandardMetadata(cols);
|
||||||
@@ -314,10 +318,10 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void SetCellNull()
|
public async Task SetCellNull()
|
||||||
{
|
{
|
||||||
// Setup: Generate a row create
|
// Setup: Generate a row create
|
||||||
RowCreate rc = GetStandardRowCreate();
|
RowCreate rc = await GetStandardRowCreate();
|
||||||
|
|
||||||
// If: I set a cell in the newly created row to null
|
// If: I set a cell in the newly created row to null
|
||||||
EditUpdateCellResult eucr = rc.SetCell(0, "NULL");
|
EditUpdateCellResult eucr = rc.SetCell(0, "NULL");
|
||||||
@@ -341,10 +345,10 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
[InlineData(-1)] // Negative
|
[InlineData(-1)] // Negative
|
||||||
[InlineData(3)] // At edge of acceptable values
|
[InlineData(3)] // At edge of acceptable values
|
||||||
[InlineData(100)] // Way too large value
|
[InlineData(100)] // Way too large value
|
||||||
public void RevertCellOutOfRange(int columnId)
|
public async Task RevertCellOutOfRange(int columnId)
|
||||||
{
|
{
|
||||||
// Setup: Generate the row create
|
// Setup: Generate the row create
|
||||||
RowCreate rc = GetStandardRowCreate();
|
RowCreate rc = await GetStandardRowCreate();
|
||||||
|
|
||||||
// If: I attempt to revert a cell that is out of range
|
// If: I attempt to revert a cell that is out of range
|
||||||
// Then: I should get an exception
|
// Then: I should get an exception
|
||||||
@@ -352,10 +356,10 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void RevertCellNotSet()
|
public async Task RevertCellNotSet()
|
||||||
{
|
{
|
||||||
// Setup: Generate the row create
|
// Setup: Generate the row create
|
||||||
RowCreate rc = GetStandardRowCreate();
|
RowCreate rc = await GetStandardRowCreate();
|
||||||
|
|
||||||
// If: I attempt to revert a cell that has not been set
|
// If: I attempt to revert a cell that has not been set
|
||||||
string result = rc.RevertCell(0);
|
string result = rc.RevertCell(0);
|
||||||
@@ -369,10 +373,10 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void RevertCellThatWasSet()
|
public async Task RevertCellThatWasSet()
|
||||||
{
|
{
|
||||||
// Setup: Generate the row create
|
// Setup: Generate the row create
|
||||||
RowCreate rc = GetStandardRowCreate();
|
RowCreate rc = await GetStandardRowCreate();
|
||||||
rc.SetCell(0, "1");
|
rc.SetCell(0, "1");
|
||||||
|
|
||||||
// If: I attempt to revert a cell that was set
|
// 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]);
|
Assert.Null(rc.newCells[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static RowCreate GetStandardRowCreate()
|
private static async Task<RowCreate> GetStandardRowCreate()
|
||||||
{
|
{
|
||||||
var cols = Common.GetColumns(false);
|
var cols = Common.GetColumns(false);
|
||||||
var rs = Common.GetResultSet(cols, false);
|
var rs = await Common.GetResultSet(cols, false);
|
||||||
var etm = Common.GetStandardMetadata(cols);
|
var etm = Common.GetStandardMetadata(cols);
|
||||||
return new RowCreate(100, rs, etm);
|
return new RowCreate(100, rs, etm);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,12 +21,12 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
public class RowDeleteTests
|
public class RowDeleteTests
|
||||||
{
|
{
|
||||||
[Fact]
|
[Fact]
|
||||||
public void RowDeleteConstruction()
|
public async Task RowDeleteConstruction()
|
||||||
{
|
{
|
||||||
// Setup: Create the values to store
|
// Setup: Create the values to store
|
||||||
DbColumn[] columns = Common.GetColumns(true);
|
DbColumn[] columns = Common.GetColumns(true);
|
||||||
ResultSet rs = Common.GetResultSet(columns, true);
|
ResultSet rs = await Common.GetResultSet(columns, true);
|
||||||
IEditTableMetadata etm = Common.GetStandardMetadata(columns, false);
|
EditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
||||||
|
|
||||||
// If: I create a RowCreate instance
|
// If: I create a RowCreate instance
|
||||||
RowDelete rc = new RowDelete(100, rs, etm);
|
RowDelete rc = new RowDelete(100, rs, etm);
|
||||||
@@ -40,11 +40,11 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
[Theory]
|
[Theory]
|
||||||
[InlineData(true)]
|
[InlineData(true)]
|
||||||
[InlineData(false)]
|
[InlineData(false)]
|
||||||
public void GetScriptTest(bool isMemoryOptimized)
|
public async Task GetScriptTest(bool isMemoryOptimized)
|
||||||
{
|
{
|
||||||
DbColumn[] columns = Common.GetColumns(true);
|
DbColumn[] columns = Common.GetColumns(true);
|
||||||
ResultSet rs = Common.GetResultSet(columns, true);
|
ResultSet rs = await Common.GetResultSet(columns, true);
|
||||||
IEditTableMetadata etm = Common.GetStandardMetadata(columns, false, isMemoryOptimized);
|
EditTableMetadata etm = Common.GetStandardMetadata(columns, isMemoryOptimized);
|
||||||
|
|
||||||
// If: I ask for a script to be generated for delete
|
// If: I ask for a script to be generated for delete
|
||||||
RowDelete rd = new RowDelete(0, rs, etm);
|
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
|
// Setup: Generate the parameters for the row delete object
|
||||||
var columns = Common.GetColumns(false);
|
var columns = Common.GetColumns(false);
|
||||||
var rs = Common.GetResultSet(columns, false);
|
var rs = await Common.GetResultSet(columns, false);
|
||||||
var etm = Common.GetStandardMetadata(columns);
|
var etm = Common.GetStandardMetadata(columns);
|
||||||
|
|
||||||
// If: I ask for the change to be applied
|
// If: I ask for the change to be applied
|
||||||
@@ -84,13 +84,13 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
[InlineData(false, true)]
|
[InlineData(false, true)]
|
||||||
[InlineData(true, false)]
|
[InlineData(true, false)]
|
||||||
[InlineData(false, false)]
|
[InlineData(false, false)]
|
||||||
public void GetCommand(bool includeIdentity, bool isMemoryOptimized)
|
public async Task GetCommand(bool includeIdentity, bool isMemoryOptimized)
|
||||||
{
|
{
|
||||||
// Setup:
|
// Setup:
|
||||||
// ... Create a row delete
|
// ... Create a row delete
|
||||||
var columns = Common.GetColumns(includeIdentity);
|
var columns = Common.GetColumns(includeIdentity);
|
||||||
var rs = Common.GetResultSet(columns, includeIdentity);
|
var rs = await Common.GetResultSet(columns, includeIdentity);
|
||||||
var etm = Common.GetStandardMetadata(columns, !includeIdentity, isMemoryOptimized);
|
var etm = Common.GetStandardMetadata(columns, isMemoryOptimized);
|
||||||
RowDelete rd = new RowDelete(0, rs, etm);
|
RowDelete rd = new RowDelete(0, rs, etm);
|
||||||
|
|
||||||
// ... Mock db connection for building the command
|
// ... Mock db connection for building the command
|
||||||
@@ -128,10 +128,10 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GetCommandNullConnection()
|
public async Task GetCommandNullConnection()
|
||||||
{
|
{
|
||||||
// Setup: Create a row delete
|
// Setup: Create a row delete
|
||||||
RowDelete rd = GetStandardRowDelete();
|
RowDelete rd = await GetStandardRowDelete();
|
||||||
|
|
||||||
// If: I attempt to create a command with a null connection
|
// If: I attempt to create a command with a null connection
|
||||||
// Then: It should throw an exception
|
// Then: It should throw an exception
|
||||||
@@ -139,11 +139,11 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GetEditRow()
|
public async Task GetEditRow()
|
||||||
{
|
{
|
||||||
// Setup: Create a row delete
|
// Setup: Create a row delete
|
||||||
var columns = Common.GetColumns(false);
|
var columns = Common.GetColumns(false);
|
||||||
var rs = Common.GetResultSet(columns, false);
|
var rs = await Common.GetResultSet(columns, false);
|
||||||
var etm = Common.GetStandardMetadata(columns);
|
var etm = Common.GetStandardMetadata(columns);
|
||||||
RowDelete rd = new RowDelete(0, rs, etm);
|
RowDelete rd = new RowDelete(0, rs, etm);
|
||||||
|
|
||||||
@@ -173,10 +173,10 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GetEditNullRow()
|
public async Task GetEditNullRow()
|
||||||
{
|
{
|
||||||
// Setup: Create a row delete
|
// 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
|
// If: I attempt to get an edit row with a null cached row
|
||||||
// Then: I should get an exception
|
// Then: I should get an exception
|
||||||
@@ -184,10 +184,10 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void SetCell()
|
public async Task SetCell()
|
||||||
{
|
{
|
||||||
// Setup: Create a row delete
|
// Setup: Create a row delete
|
||||||
RowDelete rd = GetStandardRowDelete();
|
RowDelete rd = await GetStandardRowDelete();
|
||||||
|
|
||||||
// If: I set a cell on a delete row edit
|
// If: I set a cell on a delete row edit
|
||||||
// Then: It should throw as invalid operation
|
// Then: It should throw as invalid operation
|
||||||
@@ -195,20 +195,20 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void RevertCell()
|
public async Task RevertCell()
|
||||||
{
|
{
|
||||||
// Setup: Create a row delete
|
// Setup: Create a row delete
|
||||||
RowDelete rd = GetStandardRowDelete();
|
RowDelete rd = await GetStandardRowDelete();
|
||||||
|
|
||||||
// If: I revert a cell on a delete row edit
|
// If: I revert a cell on a delete row edit
|
||||||
// Then: It should throw
|
// Then: It should throw
|
||||||
Assert.Throws<InvalidOperationException>(() => rd.RevertCell(0));
|
Assert.Throws<InvalidOperationException>(() => rd.RevertCell(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
private RowDelete GetStandardRowDelete()
|
private async Task<RowDelete> GetStandardRowDelete()
|
||||||
{
|
{
|
||||||
var cols = Common.GetColumns(false);
|
var cols = Common.GetColumns(false);
|
||||||
var rs = Common.GetResultSet(cols, false);
|
var rs = await Common.GetResultSet(cols, false);
|
||||||
var etm = Common.GetStandardMetadata(cols);
|
var etm = Common.GetStandardMetadata(cols);
|
||||||
return new RowDelete(0, rs, etm);
|
return new RowDelete(0, rs, etm);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,12 +25,16 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
{
|
{
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData(-1)] // Negative index
|
[InlineData(-1)] // Negative index
|
||||||
|
[InlineData(2)] // Equal to count of columns
|
||||||
[InlineData(100)] // Index larger than number 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
|
// Setup: Create a result set
|
||||||
ResultSet rs = GetResultSet(
|
ResultSet rs = await GetResultSet(
|
||||||
new DbColumn[] { new TestDbColumn("id", true), new TestDbColumn("col1")},
|
new DbColumn[] {
|
||||||
|
new TestDbColumn("id") {IsKey = true, IsAutoIncrement = true, IsIdentity = true},
|
||||||
|
new TestDbColumn("col1")
|
||||||
|
},
|
||||||
new object[] { "id", "1" });
|
new object[] { "id", "1" });
|
||||||
|
|
||||||
// If: I validate a column ID that is out of range
|
// If: I validate a column ID that is out of range
|
||||||
@@ -40,11 +44,14 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void ValidateUpdatableColumnNotUpdatable()
|
public async Task ValidateUpdatableColumnNotUpdatable()
|
||||||
{
|
{
|
||||||
// Setup: Create a result set with an identity column
|
// Setup: Create a result set with an identity column
|
||||||
ResultSet rs = GetResultSet(
|
ResultSet rs = await GetResultSet(
|
||||||
new DbColumn[] { new TestDbColumn("id", true), new TestDbColumn("col1") },
|
new DbColumn[] {
|
||||||
|
new TestDbColumn("id") {IsKey = true, IsAutoIncrement = true, IsIdentity = true},
|
||||||
|
new TestDbColumn("col1")
|
||||||
|
},
|
||||||
new object[] { "id", "1" });
|
new object[] { "id", "1" });
|
||||||
|
|
||||||
// If: I validate a column ID that is not updatable
|
// If: I validate a column ID that is not updatable
|
||||||
@@ -55,12 +62,12 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[MemberData(nameof(GetWhereClauseIsNotNullData))]
|
[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
|
// Setup: Create a result set and metadata provider with a single column
|
||||||
var cols = new[] {col};
|
var cols = new[] {col};
|
||||||
ResultSet rs = GetResultSet(cols, new[] {val});
|
ResultSet rs = await GetResultSet(cols, new[] {val});
|
||||||
IEditTableMetadata etm = Common.GetStandardMetadata(cols);
|
EditTableMetadata etm = Common.GetStandardMetadata(cols);
|
||||||
|
|
||||||
RowEditTester rt = new RowEditTester(rs, etm);
|
RowEditTester rt = new RowEditTester(rs, etm);
|
||||||
rt.ValidateWhereClauseSingleKey(nullClause);
|
rt.ValidateWhereClauseSingleKey(nullClause);
|
||||||
@@ -71,42 +78,69 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
get
|
get
|
||||||
{
|
{
|
||||||
yield return new object[] {new TestDbColumn("col"), DBNull.Value, "IS NULL"};
|
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[] {
|
||||||
yield return new object[] {new TestDbColumn("col", "TEXT", typeof(string)), "abc", "IS NOT NULL"};
|
new TestDbColumn
|
||||||
yield return new object[] {new TestDbColumn("col", "NTEXT", typeof(string)), "abc", "IS NOT NULL"};
|
{
|
||||||
|
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]
|
[Fact]
|
||||||
public void GetWhereClauseMultipleKeyColumns()
|
public async Task GetWhereClauseMultipleKeyColumns()
|
||||||
{
|
{
|
||||||
// Setup: Create a result set and metadata provider with multiple key columns
|
// Setup: Create a result set and metadata provider with multiple key columns
|
||||||
DbColumn[] cols = {new TestDbColumn("col1"), new TestDbColumn("col2")};
|
DbColumn[] cols = {new TestDbColumn("col1"), new TestDbColumn("col2")};
|
||||||
ResultSet rs = GetResultSet(cols, new object[] {"abc", "def"});
|
ResultSet rs = await GetResultSet(cols, new object[] {"abc", "def"});
|
||||||
IEditTableMetadata etm = Common.GetStandardMetadata(cols);
|
EditTableMetadata etm = Common.GetStandardMetadata(cols);
|
||||||
|
|
||||||
RowEditTester rt = new RowEditTester(rs, etm);
|
RowEditTester rt = new RowEditTester(rs, etm);
|
||||||
rt.ValidateWhereClauseMultipleKeys();
|
rt.ValidateWhereClauseMultipleKeys();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GetWhereClauseNoKeyColumns()
|
public async Task GetWhereClauseNoKeyColumns()
|
||||||
{
|
{
|
||||||
// Setup: Create a result set and metadata provider with no key columns
|
// Setup: Create a result set and metadata provider with no key columns
|
||||||
DbColumn[] cols = {new TestDbColumn("col1"), new TestDbColumn("col2")};
|
DbColumn[] cols = {new TestDbColumn("col1"), new TestDbColumn("col2")};
|
||||||
ResultSet rs = GetResultSet(cols, new object[] {"abc", "def"});
|
ResultSet rs = await GetResultSet(cols, new object[] {"abc", "def"});
|
||||||
IEditTableMetadata etm = Common.GetStandardMetadata(new DbColumn[] {});
|
EditTableMetadata etm = Common.GetStandardMetadata(new DbColumn[] {});
|
||||||
|
|
||||||
RowEditTester rt = new RowEditTester(rs, etm);
|
RowEditTester rt = new RowEditTester(rs, etm);
|
||||||
rt.ValidateWhereClauseNoKeys();
|
rt.ValidateWhereClauseNoKeys();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void SortingByTypeTest()
|
public async Task SortingByTypeTest()
|
||||||
{
|
{
|
||||||
// Setup: Create a result set and metadata we can reuse
|
// Setup: Create a result set and metadata we can reuse
|
||||||
var cols = Common.GetColumns(false);
|
var cols = Common.GetColumns(false);
|
||||||
var rs = Common.GetResultSet(cols, false);
|
var rs = await Common.GetResultSet(cols, false);
|
||||||
var etm = Common.GetStandardMetadata(cols);
|
var etm = Common.GetStandardMetadata(cols);
|
||||||
|
|
||||||
// If: I request to sort a list of the three different edit operations
|
// If: I request to sort a list of the three different edit operations
|
||||||
@@ -124,11 +158,11 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void SortingUpdatesByRowIdTest()
|
public async Task SortingUpdatesByRowIdTest()
|
||||||
{
|
{
|
||||||
// Setup: Create a result set and metadata we can reuse
|
// Setup: Create a result set and metadata we can reuse
|
||||||
var cols = Common.GetColumns(false);
|
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);
|
var etm = Common.GetStandardMetadata(cols);
|
||||||
|
|
||||||
// If: I sort 3 edit operations of the same type
|
// If: I sort 3 edit operations of the same type
|
||||||
@@ -147,11 +181,11 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void SortingCreatesByRowIdTest()
|
public async Task SortingCreatesByRowIdTest()
|
||||||
{
|
{
|
||||||
// Setup: Create a result set and metadata we can reuse
|
// Setup: Create a result set and metadata we can reuse
|
||||||
var cols = Common.GetColumns(false);
|
var cols = Common.GetColumns(false);
|
||||||
var rs = Common.GetResultSet(cols, false);
|
var rs = await Common.GetResultSet(cols, false);
|
||||||
var etm = Common.GetStandardMetadata(cols);
|
var etm = Common.GetStandardMetadata(cols);
|
||||||
|
|
||||||
// If: I sort 3 edit operations of the same type
|
// If: I sort 3 edit operations of the same type
|
||||||
@@ -170,11 +204,11 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void SortingDeletesByRowIdTest()
|
public async Task SortingDeletesByRowIdTest()
|
||||||
{
|
{
|
||||||
// Setup: Create a result set and metadata we can reuse
|
// Setup: Create a result set and metadata we can reuse
|
||||||
var cols = Common.GetColumns(false);
|
var cols = Common.GetColumns(false);
|
||||||
var rs = Common.GetResultSet(cols, false);
|
var rs = await Common.GetResultSet(cols, false);
|
||||||
var etm = Common.GetStandardMetadata(cols);
|
var etm = Common.GetStandardMetadata(cols);
|
||||||
|
|
||||||
// If: I sort 3 delete operations of the same type
|
// 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);
|
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};
|
object[][] rows = {row};
|
||||||
var testResultSet = new TestResultSet(columns, rows);
|
var testResultSet = new TestResultSet(columns, rows);
|
||||||
var testReader = new TestDbDataReader(new [] {testResultSet});
|
var testReader = new TestDbDataReader(new [] {testResultSet});
|
||||||
var resultSet = new ResultSet(0,0, MemoryFileSystem.GetFileStreamFactory());
|
var resultSet = new ResultSet(0,0, MemoryFileSystem.GetFileStreamFactory());
|
||||||
resultSet.ReadResultToEnd(testReader, CancellationToken.None).Wait();
|
await resultSet.ReadResultToEnd(testReader, CancellationToken.None);
|
||||||
return resultSet;
|
return resultSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class RowEditTester : RowEditBase
|
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)
|
public void ValidateColumn(int columnId)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
// Setup: Create the values to store
|
// Setup: Create the values to store
|
||||||
const long rowId = 0;
|
const long rowId = 0;
|
||||||
ResultSet rs = QueryExecution.Common.GetBasicExecutedBatch().ResultSets[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
|
// If: I create a RowUpdate instance
|
||||||
RowUpdate rc = new RowUpdate(rowId, rs, etm);
|
RowUpdate rc = new RowUpdate(rowId, rs, etm);
|
||||||
@@ -40,10 +40,10 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void SetCell()
|
public async Task SetCell()
|
||||||
{
|
{
|
||||||
// Setup: Create a row update
|
// Setup: Create a row update
|
||||||
RowUpdate ru = GetStandardRowUpdate();
|
RowUpdate ru = await GetStandardRowUpdate();
|
||||||
|
|
||||||
// If: I set a cell that can be updated
|
// If: I set a cell that can be updated
|
||||||
EditUpdateCellResult eucr = ru.SetCell(0, "col1");
|
EditUpdateCellResult eucr = ru.SetCell(0, "col1");
|
||||||
@@ -69,7 +69,14 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
{
|
{
|
||||||
// Setup:
|
// Setup:
|
||||||
// ... Generate a result set with a single binary column
|
// ... 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}}};
|
object[][] rows = { new object[]{new byte[] {0x00}}};
|
||||||
var testResultSet = new TestResultSet(cols, rows);
|
var testResultSet = new TestResultSet(cols, rows);
|
||||||
var testReader = new TestDbDataReader(new[] { testResultSet });
|
var testReader = new TestDbDataReader(new[] { testResultSet });
|
||||||
@@ -102,12 +109,12 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void SetCellImplicitRevertTest()
|
public async Task SetCellImplicitRevertTest()
|
||||||
{
|
{
|
||||||
// Setup: Create a fake table to update
|
// Setup: Create a fake table to update
|
||||||
DbColumn[] columns = Common.GetColumns(true);
|
DbColumn[] columns = Common.GetColumns(true);
|
||||||
ResultSet rs = Common.GetResultSet(columns, true);
|
ResultSet rs = await Common.GetResultSet(columns, true);
|
||||||
IEditTableMetadata etm = Common.GetStandardMetadata(columns);
|
EditTableMetadata etm = Common.GetStandardMetadata(columns);
|
||||||
|
|
||||||
// If:
|
// If:
|
||||||
// ... I add updates to all the cells in the row
|
// ... I add updates to all the cells in the row
|
||||||
@@ -139,12 +146,12 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
[Theory]
|
[Theory]
|
||||||
[InlineData(true)]
|
[InlineData(true)]
|
||||||
[InlineData(false)]
|
[InlineData(false)]
|
||||||
public void GetScriptTest(bool isMemoryOptimized)
|
public async Task GetScriptTest(bool isMemoryOptimized)
|
||||||
{
|
{
|
||||||
// Setup: Create a fake table to update
|
// Setup: Create a fake table to update
|
||||||
DbColumn[] columns = Common.GetColumns(true);
|
DbColumn[] columns = Common.GetColumns(true);
|
||||||
ResultSet rs = Common.GetResultSet(columns, true);
|
ResultSet rs = await Common.GetResultSet(columns, true);
|
||||||
IEditTableMetadata etm = Common.GetStandardMetadata(columns, false, isMemoryOptimized);
|
EditTableMetadata etm = Common.GetStandardMetadata(columns, isMemoryOptimized);
|
||||||
|
|
||||||
// If: I ask for a script to be generated for update
|
// If: I ask for a script to be generated for update
|
||||||
RowUpdate ru = new RowUpdate(0, rs, etm);
|
RowUpdate ru = new RowUpdate(0, rs, etm);
|
||||||
@@ -177,13 +184,13 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
[InlineData(true, false)]
|
[InlineData(true, false)]
|
||||||
[InlineData(false, true)]
|
[InlineData(false, true)]
|
||||||
[InlineData(false, false)]
|
[InlineData(false, false)]
|
||||||
public void GetCommand(bool includeIdentity, bool isMemoryOptimized)
|
public async Task GetCommand(bool includeIdentity, bool isMemoryOptimized)
|
||||||
{
|
{
|
||||||
// Setup:
|
// Setup:
|
||||||
// ... Create a row update with cell updates
|
// ... Create a row update with cell updates
|
||||||
var columns = Common.GetColumns(includeIdentity);
|
var columns = Common.GetColumns(includeIdentity);
|
||||||
var rs = Common.GetResultSet(columns, includeIdentity);
|
var rs = await Common.GetResultSet(columns, includeIdentity);
|
||||||
var etm = Common.GetStandardMetadata(columns, !includeIdentity, isMemoryOptimized);
|
var etm = Common.GetStandardMetadata(columns, isMemoryOptimized);
|
||||||
RowUpdate ru = new RowUpdate(0, rs, etm);
|
RowUpdate ru = new RowUpdate(0, rs, etm);
|
||||||
Common.AddCells(ru, includeIdentity);
|
Common.AddCells(ru, includeIdentity);
|
||||||
|
|
||||||
@@ -231,10 +238,10 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GetCommandNullConnection()
|
public async Task GetCommandNullConnection()
|
||||||
{
|
{
|
||||||
// Setup: Create a row update
|
// Setup: Create a row update
|
||||||
RowUpdate ru = GetStandardRowUpdate();
|
RowUpdate ru = await GetStandardRowUpdate();
|
||||||
|
|
||||||
// If: I attempt to create a command with a null connection
|
// If: I attempt to create a command with a null connection
|
||||||
// Then: It should throw an exception
|
// Then: It should throw an exception
|
||||||
@@ -242,11 +249,11 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GetEditRow()
|
public async Task GetEditRow()
|
||||||
{
|
{
|
||||||
// Setup: Create a row update with a cell set
|
// Setup: Create a row update with a cell set
|
||||||
var columns = Common.GetColumns(false);
|
var columns = Common.GetColumns(false);
|
||||||
var rs = Common.GetResultSet(columns, false);
|
var rs = await Common.GetResultSet(columns, false);
|
||||||
var etm = Common.GetStandardMetadata(columns);
|
var etm = Common.GetStandardMetadata(columns);
|
||||||
RowUpdate ru = new RowUpdate(0, rs, etm);
|
RowUpdate ru = new RowUpdate(0, rs, etm);
|
||||||
ru.SetCell(0, "foo");
|
ru.SetCell(0, "foo");
|
||||||
@@ -282,10 +289,10 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GetEditNullRow()
|
public async Task GetEditNullRow()
|
||||||
{
|
{
|
||||||
// Setup: Create a row update
|
// 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
|
// If: I attempt to get an edit row with a null cached row
|
||||||
// Then: I should get an exception
|
// Then: I should get an exception
|
||||||
@@ -300,8 +307,8 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
// Setup:
|
// Setup:
|
||||||
// ... Create a row update (no cell updates needed)
|
// ... Create a row update (no cell updates needed)
|
||||||
var columns = Common.GetColumns(includeIdentity);
|
var columns = Common.GetColumns(includeIdentity);
|
||||||
var rs = Common.GetResultSet(columns, includeIdentity);
|
var rs = await Common.GetResultSet(columns, includeIdentity);
|
||||||
var etm = Common.GetStandardMetadata(columns, !includeIdentity);
|
var etm = Common.GetStandardMetadata(columns);
|
||||||
RowUpdate ru = new RowUpdate(0, rs, etm);
|
RowUpdate ru = new RowUpdate(0, rs, etm);
|
||||||
long oldBytesWritten = rs.totalBytesWritten;
|
long oldBytesWritten = rs.totalBytesWritten;
|
||||||
|
|
||||||
@@ -323,8 +330,8 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
// Setup:
|
// Setup:
|
||||||
// ... Create a row update (no cell updates needed)
|
// ... Create a row update (no cell updates needed)
|
||||||
var columns = Common.GetColumns(true);
|
var columns = Common.GetColumns(true);
|
||||||
var rs = Common.GetResultSet(columns, true);
|
var rs = await Common.GetResultSet(columns, true);
|
||||||
var etm = Common.GetStandardMetadata(columns, false);
|
var etm = Common.GetStandardMetadata(columns);
|
||||||
RowUpdate ru = new RowUpdate(0, rs, etm);
|
RowUpdate ru = new RowUpdate(0, rs, etm);
|
||||||
|
|
||||||
// If: I ask for the changes to be applied with a null db reader
|
// 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(-1)] // Negative
|
||||||
[InlineData(3)] // At edge of acceptable values
|
[InlineData(3)] // At edge of acceptable values
|
||||||
[InlineData(100)] // Way too large value
|
[InlineData(100)] // Way too large value
|
||||||
public void RevertCellOutOfRange(int columnId)
|
public async Task RevertCellOutOfRange(int columnId)
|
||||||
{
|
{
|
||||||
// Setup:
|
// Setup:
|
||||||
// ... Create a row update (no cell updates needed)
|
// ... Create a row update (no cell updates needed)
|
||||||
var columns = Common.GetColumns(false);
|
var columns = Common.GetColumns(false);
|
||||||
var rs = Common.GetResultSet(columns, false);
|
var rs = await Common.GetResultSet(columns, false);
|
||||||
var etm = Common.GetStandardMetadata(columns);
|
var etm = Common.GetStandardMetadata(columns);
|
||||||
RowUpdate ru = new RowUpdate(0, rs, etm);
|
RowUpdate ru = new RowUpdate(0, rs, etm);
|
||||||
|
|
||||||
@@ -351,12 +358,12 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void RevertCellNotSet()
|
public async Task RevertCellNotSet()
|
||||||
{
|
{
|
||||||
// Setup:
|
// Setup:
|
||||||
// ... Create a row update (no cell updates needed)
|
// ... Create a row update (no cell updates needed)
|
||||||
var columns = Common.GetColumns(true);
|
var columns = Common.GetColumns(true);
|
||||||
var rs = Common.GetResultSet(columns, true);
|
var rs = await Common.GetResultSet(columns, true);
|
||||||
var etm = Common.GetStandardMetadata(columns);
|
var etm = Common.GetStandardMetadata(columns);
|
||||||
RowUpdate ru = new RowUpdate(0, rs, etm);
|
RowUpdate ru = new RowUpdate(0, rs, etm);
|
||||||
|
|
||||||
@@ -371,12 +378,12 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void RevertCellThatWasSet()
|
public async Task RevertCellThatWasSet()
|
||||||
{
|
{
|
||||||
// Setup:
|
// Setup:
|
||||||
// ... Create a row update
|
// ... Create a row update
|
||||||
var columns = Common.GetColumns(false);
|
var columns = Common.GetColumns(false);
|
||||||
var rs = Common.GetResultSet(columns, false);
|
var rs = await Common.GetResultSet(columns, false);
|
||||||
var etm = Common.GetStandardMetadata(columns);
|
var etm = Common.GetStandardMetadata(columns);
|
||||||
RowUpdate ru = new RowUpdate(0, rs, etm);
|
RowUpdate ru = new RowUpdate(0, rs, etm);
|
||||||
ru.SetCell(0, "1");
|
ru.SetCell(0, "1");
|
||||||
@@ -392,10 +399,10 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
Assert.DoesNotContain(0, ru.cellUpdates.Keys);
|
Assert.DoesNotContain(0, ru.cellUpdates.Keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
private RowUpdate GetStandardRowUpdate()
|
private async Task<RowUpdate> GetStandardRowUpdate()
|
||||||
{
|
{
|
||||||
var columns = Common.GetColumns(false);
|
var columns = Common.GetColumns(false);
|
||||||
var rs = Common.GetResultSet(columns, false);
|
var rs = await Common.GetResultSet(columns, false);
|
||||||
var etm = Common.GetStandardMetadata(columns);
|
var etm = Common.GetStandardMetadata(columns);
|
||||||
return new RowUpdate(0, rs, etm);
|
return new RowUpdate(0, rs, etm);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
// Setup:
|
// Setup:
|
||||||
// ... Create an edit data service with a session
|
// ... Create an edit data service with a session
|
||||||
var eds = new EditDataService(null, null, null);
|
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
|
// ... Create a session param that returns the common owner uri
|
||||||
var mockParams = new EditCreateRowParams { OwnerUri = Common.OwnerUri };
|
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
|
// Setup: Create an edit data service with a session
|
||||||
var eds = new EditDataService(null, null, null);
|
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
|
// If: I ask to dispose of an existing session
|
||||||
var efv = new EventFlowValidator<EditDisposeResult>()
|
var efv = new EventFlowValidator<EditDisposeResult>()
|
||||||
@@ -117,7 +117,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 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
|
// If: I validly ask to delete a row
|
||||||
var efv = new EventFlowValidator<EditDeleteRowResult>()
|
var efv = new EventFlowValidator<EditDeleteRowResult>()
|
||||||
@@ -139,7 +139,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 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
|
// If: I ask to create a row from a non existant session
|
||||||
var efv = new EventFlowValidator<EditCreateRowResult>()
|
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
|
// Setup: Create an edit data service with a session that has an pending edit
|
||||||
var eds = new EditDataService(null, null, null);
|
var eds = new EditDataService(null, null, null);
|
||||||
var session = GetDefaultSession();
|
var session = await GetDefaultSession();
|
||||||
session.EditCache[0] = new Mock<RowEditBase>().Object;
|
session.EditCache[0] = new Mock<RowEditBase>().Object;
|
||||||
eds.ActiveSessions[Constants.OwnerUri] = session;
|
eds.ActiveSessions[Constants.OwnerUri] = session;
|
||||||
|
|
||||||
@@ -185,7 +185,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 eds = new EditDataService(null, null, null);
|
||||||
var session = GetDefaultSession();
|
var session = await GetDefaultSession();
|
||||||
eds.ActiveSessions[Constants.OwnerUri] = session;
|
eds.ActiveSessions[Constants.OwnerUri] = session;
|
||||||
var edit = new Mock<RowEditBase>();
|
var edit = new Mock<RowEditBase>();
|
||||||
edit.Setup(e => e.SetCell(It.IsAny<int>(), It.IsAny<string>())).Returns(new EditUpdateCellResult
|
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
|
||||||
// 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 eds = new EditDataService(null, null, null);
|
||||||
var session = GetDefaultSession();
|
var session = await GetDefaultSession();
|
||||||
eds.ActiveSessions[Constants.OwnerUri] = session;
|
eds.ActiveSessions[Constants.OwnerUri] = session;
|
||||||
|
|
||||||
// If: I validly ask for rows
|
// If: I validly ask for rows
|
||||||
@@ -277,119 +277,15 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
|
|
||||||
// ... There should not be a session
|
// ... There should not be a session
|
||||||
Assert.Empty(eds.ActiveSessions);
|
Assert.Empty(eds.ActiveSessions);
|
||||||
|
|
||||||
// ... There should not be a wait handler
|
|
||||||
Assert.Empty(eds.InitializeWaitHandles);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
private static async Task<EditSession> GetDefaultSession()
|
||||||
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()
|
|
||||||
{
|
{
|
||||||
// ... Create a session with a proper query and metadata
|
// ... Create a session with a proper query and metadata
|
||||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
||||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
ResultSet rs = q.Batches[0].ResultSets[0];
|
||||||
IEditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
EditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
||||||
EditSession s = new EditSession(rs, etm);
|
EditSession s = await Common.GetCustomSession(q, etm);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,40 +28,55 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
#region Construction Tests
|
#region Construction Tests
|
||||||
|
|
||||||
[Fact]
|
[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
|
// 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]
|
[Theory]
|
||||||
public void SessionConstructionNullMetadataProvider()
|
[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
|
// Then: It should throw an exception
|
||||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
Mock<IEditMetadataFactory> mockFactory = new Mock<IEditMetadataFactory>();
|
||||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
Assert.Throws<ArgumentException>(() => new EditSession(mockFactory.Object, objName, Constants.OwnerUri));
|
||||||
Assert.Throws<ArgumentNullException>(() => new EditSession(rs, null));
|
}
|
||||||
|
|
||||||
|
[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]
|
[Fact]
|
||||||
public void SessionConstructionValid()
|
public void SessionConstructionValid()
|
||||||
{
|
{
|
||||||
// If: I create a session object with a proper query and metadata
|
// If: I create a session object with a proper arguments
|
||||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
Mock<IEditMetadataFactory> mockFactory = new Mock<IEditMetadataFactory>();
|
||||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
EditSession s = new EditSession(mockFactory.Object, Constants.OwnerUri, Constants.OwnerUri);
|
||||||
IEditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
|
||||||
EditSession s = new EditSession(rs, etm);
|
|
||||||
|
|
||||||
// Then:
|
// Then:
|
||||||
// ... The edit cache should exist and be empty
|
// ... The edit cache should not exist
|
||||||
Assert.NotNull(s.EditCache);
|
Assert.Null(s.EditCache);
|
||||||
Assert.Empty(s.EditCache);
|
|
||||||
|
// ... The session shouldn't be initialized
|
||||||
|
Assert.False(s.IsInitialized);
|
||||||
|
Assert.Null(s.EditCache);
|
||||||
Assert.Null(s.CommitTask);
|
Assert.Null(s.CommitTask);
|
||||||
|
|
||||||
// ... The next row ID should be equivalent to the number of rows in the result set
|
// ... The next row ID should be the default long
|
||||||
Assert.Equal(q.Batches[0].ResultSets[0].RowCount, s.NextRowId);
|
Assert.Equal(default(long), s.NextRowId);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -118,15 +133,28 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
#region Create Row Tests
|
#region Create Row Tests
|
||||||
|
|
||||||
[Fact]
|
[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
|
// NOTE: This scenario should theoretically never occur, but is tested for completeness
|
||||||
// Setup:
|
// Setup:
|
||||||
// ... Create a session with a proper query and metadata
|
// ... Create a session with a proper query and metadata
|
||||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
||||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
ResultSet rs = q.Batches[0].ResultSets[0];
|
||||||
IEditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
EditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
||||||
EditSession s = new EditSession(rs, etm);
|
EditSession s = await Common.GetCustomSession(q, etm);
|
||||||
|
|
||||||
// ... Add a mock edit to the edit cache to cause the .TryAdd to fail
|
// ... Add a mock edit to the edit cache to cause the .TryAdd to fail
|
||||||
var mockEdit = new Mock<RowEditBase>().Object;
|
var mockEdit = new Mock<RowEditBase>().Object;
|
||||||
@@ -145,13 +173,13 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void CreateRowSuccess()
|
public async Task CreateRowSuccess()
|
||||||
{
|
{
|
||||||
// Setup: Create a session with a proper query and metadata
|
// Setup: Create a session with a proper query and metadata
|
||||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
||||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
ResultSet rs = q.Batches[0].ResultSets[0];
|
||||||
IEditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
EditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
||||||
EditSession s = new EditSession(rs, etm);
|
EditSession s = await Common.GetCustomSession(q, etm);
|
||||||
|
|
||||||
// If: I add a row to the session
|
// If: I add a row to the session
|
||||||
EditCreateRowResult result = s.CreateRow();
|
EditCreateRowResult result = s.CreateRow();
|
||||||
@@ -172,48 +200,48 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void CreateRowDefaultTest()
|
public async Task CreateRowDefaultTest()
|
||||||
{
|
{
|
||||||
// Setup:
|
// Setup:
|
||||||
// ... We will have 3 columns
|
// ... We will have 3 columns
|
||||||
DbColumn[] cols =
|
DbColumnWrapper[] cols =
|
||||||
{
|
{
|
||||||
new TestDbColumn("col1", false), // No default
|
new DbColumnWrapper(new TestDbColumn("col1")), // No default
|
||||||
new TestDbColumn("col2", false), // Has default (defined below)
|
new DbColumnWrapper(new TestDbColumn("col2")), // Has default (defined below)
|
||||||
new TestDbColumn("filler", false) // Filler column so we can use the common code
|
new DbColumnWrapper(new TestDbColumn("filler")) // Filler column so we can use the common code
|
||||||
};
|
};
|
||||||
|
|
||||||
// ... Metadata provider will return 3 columns
|
// ... 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,
|
DefaultValue = null,
|
||||||
EscapedName = cols[0].ColumnName,
|
EscapedName = cols[0].ColumnName,
|
||||||
Ordinal = 0,
|
|
||||||
IsKey = false
|
|
||||||
},
|
},
|
||||||
new EditColumnWrapper // Has default
|
new EditColumnMetadata // Has default
|
||||||
{
|
{
|
||||||
DbColumn = new DbColumnWrapper(cols[1]),
|
|
||||||
DefaultValue = "default",
|
DefaultValue = "default",
|
||||||
EscapedName = cols[0].ColumnName,
|
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
|
// ... Create a result set
|
||||||
var rs = Common.GetResultSet(cols, false, 1);
|
var q = await Common.GetQuery(cols, false);
|
||||||
|
|
||||||
// ... Create a session from all this
|
// ... 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
|
// If: I add a row to the session, on a table that has defaults
|
||||||
var result = session.CreateRow();
|
var result = s.CreateRow();
|
||||||
|
|
||||||
// Then:
|
// Then:
|
||||||
// ... Result should not be null, new row ID should be > 0
|
// ... Result should not be null, new row ID should be > 0
|
||||||
@@ -233,13 +261,10 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[MemberData(nameof(RowIdOutOfRangeData))]
|
[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
|
// Setup: Create a session with a proper query and metadata
|
||||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
EditSession s = await GetBasicSession();
|
||||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
|
||||||
IEditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
|
||||||
EditSession s = new EditSession(rs, etm);
|
|
||||||
|
|
||||||
// If: I delete a row that is out of range for the result set
|
// If: I delete a row that is out of range for the result set
|
||||||
// Then: I should get an exception
|
// Then: I should get an exception
|
||||||
@@ -253,26 +278,260 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
// Delete Row
|
// Delete Row
|
||||||
Action<EditSession, long> delAction = (s, l) => s.DeleteRow(l);
|
Action<EditSession, long> delAction = (s, l) => s.DeleteRow(l);
|
||||||
yield return new object[] { -1L, delAction };
|
yield return new object[] { -1L, delAction };
|
||||||
|
yield return new object[] {(long) QueryExecution.Common.StandardRows, delAction};
|
||||||
yield return new object[] { 100L, delAction };
|
yield return new object[] { 100L, delAction };
|
||||||
|
|
||||||
// Update Cell
|
// Update Cell
|
||||||
Action<EditSession, long> upAction = (s, l) => s.UpdateCell(l, 0, null);
|
Action<EditSession, long> upAction = (s, l) => s.UpdateCell(l, 0, null);
|
||||||
yield return new object[] { -1L, upAction };
|
yield return new object[] { -1L, upAction };
|
||||||
|
yield return new object[] {(long) QueryExecution.Common.StandardRows, upAction};
|
||||||
yield return new object[] { 100L, 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
|
#region Delete Row Tests
|
||||||
|
|
||||||
[Fact]
|
[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:
|
// Setup:
|
||||||
// ... Create a session with a proper query and metadata
|
// ... Create a session with a proper query and metadata
|
||||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
EditSession s = await GetBasicSession();
|
||||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
|
||||||
IEditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
|
||||||
EditSession s = new EditSession(rs, etm);
|
|
||||||
|
|
||||||
// ... Add a mock edit to the edit cache to cause the .TryAdd to fail
|
// ... Add a mock edit to the edit cache to cause the .TryAdd to fail
|
||||||
var mockEdit = new Mock<RowEditBase>().Object;
|
var mockEdit = new Mock<RowEditBase>().Object;
|
||||||
@@ -288,13 +547,10 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void DeleteRowSuccess()
|
public async Task DeleteRowSuccess()
|
||||||
{
|
{
|
||||||
// Setup: Create a session with a proper query and metadata
|
// Setup: Create a session with a proper query and metadata
|
||||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
var s = await GetBasicSession();
|
||||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
|
||||||
IEditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
|
||||||
EditSession s = new EditSession(rs, etm);
|
|
||||||
|
|
||||||
// If: I add a row to the session
|
// If: I add a row to the session
|
||||||
s.DeleteRow(0);
|
s.DeleteRow(0);
|
||||||
@@ -309,28 +565,24 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
#region Revert Row Tests
|
#region Revert Row Tests
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void RevertRowOutOfRange()
|
public void RevertRowNotInitialized()
|
||||||
{
|
{
|
||||||
// Setup: Create a session with a proper query and metadata
|
// Setup:
|
||||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
// ... Create a session without initializing
|
||||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
Mock<IEditMetadataFactory> emf = new Mock<IEditMetadataFactory>();
|
||||||
IEditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
EditSession s = new EditSession(emf.Object, Constants.OwnerUri, Constants.OwnerUri);
|
||||||
EditSession s = new EditSession(rs, etm);
|
|
||||||
|
|
||||||
// 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
|
// Then: I should get an exception
|
||||||
Assert.Throws<ArgumentOutOfRangeException>(() => s.RevertRow(0));
|
Assert.Throws<InvalidOperationException>(() => s.RevertRow(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void RevertRowSuccess()
|
public async Task RevertRowSuccess()
|
||||||
{
|
{
|
||||||
// Setup:
|
// Setup:
|
||||||
// ... Create a session with a proper query and metadata
|
// ... Create a session with a proper query and metadata
|
||||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
EditSession s = await GetBasicSession();
|
||||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
|
||||||
IEditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
|
||||||
EditSession s = new EditSession(rs, etm);
|
|
||||||
|
|
||||||
// ... Add a mock edit to the edit cache to cause the .TryAdd to fail
|
// ... Add a mock edit to the edit cache to cause the .TryAdd to fail
|
||||||
var mockEdit = new Mock<RowEditBase>().Object;
|
var mockEdit = new Mock<RowEditBase>().Object;
|
||||||
@@ -346,17 +598,44 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
|
|
||||||
#endregion
|
#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
|
#region Update Cell Tests
|
||||||
|
|
||||||
[Fact]
|
[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:
|
// Setup:
|
||||||
// ... Create a session with a proper query and metadata
|
// ... Create a session with a proper query and metadata
|
||||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
EditSession s = await GetBasicSession();
|
||||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
|
||||||
IEditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
|
||||||
EditSession s = new EditSession(rs, etm);
|
|
||||||
|
|
||||||
// ... Add a mock edit to the edit cache to cause the .TryAdd to fail
|
// ... Add a mock edit to the edit cache to cause the .TryAdd to fail
|
||||||
var mockEdit = new Mock<RowEditBase>();
|
var mockEdit = new Mock<RowEditBase>();
|
||||||
@@ -373,14 +652,11 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void UpdateCellNew()
|
public async Task UpdateCellNew()
|
||||||
{
|
{
|
||||||
// Setup:
|
// Setup:
|
||||||
// ... Create a session with a proper query and metadata
|
// ... Create a session with a proper query and metadata
|
||||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
EditSession s = await GetBasicSession();
|
||||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
|
||||||
IEditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
|
||||||
EditSession s = new EditSession(rs, etm);
|
|
||||||
|
|
||||||
// If: I update a cell on a row that does not have a pending edit
|
// If: I update a cell on a row that does not have a pending edit
|
||||||
s.UpdateCell(0, 0, "");
|
s.UpdateCell(0, 0, "");
|
||||||
@@ -395,14 +671,27 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
|
|
||||||
#region SubSet Tests
|
#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]
|
[Fact]
|
||||||
public async Task GetRowsNoEdits()
|
public async Task GetRowsNoEdits()
|
||||||
{
|
{
|
||||||
// Setup: Create a session with a proper query and metadata
|
// Setup: Create a session with a proper query and metadata
|
||||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
||||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
ResultSet rs = q.Batches[0].ResultSets[0];
|
||||||
IEditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
EditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
||||||
EditSession s = new EditSession(rs, etm);
|
EditSession s = await Common.GetCustomSession(q, etm);
|
||||||
|
|
||||||
// If: I ask for 3 rows from session skipping the first
|
// If: I ask for 3 rows from session skipping the first
|
||||||
EditRow[] rows = await s.GetRows(1, 3);
|
EditRow[] rows = await s.GetRows(1, 3);
|
||||||
@@ -439,10 +728,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
{
|
{
|
||||||
// Setup:
|
// Setup:
|
||||||
// ... Create a session with a proper query and metadata
|
// ... Create a session with a proper query and metadata
|
||||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
EditSession s = await GetBasicSession();
|
||||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
|
||||||
IEditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
|
||||||
EditSession s = new EditSession(rs, etm);
|
|
||||||
|
|
||||||
// ... Add a cell update to it
|
// ... Add a cell update to it
|
||||||
s.UpdateCell(1, 0, "foo");
|
s.UpdateCell(1, 0, "foo");
|
||||||
@@ -472,10 +758,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
{
|
{
|
||||||
// Setup:
|
// Setup:
|
||||||
// ... Create a session with a proper query and metadata
|
// ... Create a session with a proper query and metadata
|
||||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
EditSession s = await GetBasicSession();
|
||||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
|
||||||
IEditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
|
||||||
EditSession s = new EditSession(rs, etm);
|
|
||||||
|
|
||||||
// ... Add a row deletion
|
// ... Add a row deletion
|
||||||
s.DeleteRow(1);
|
s.DeleteRow(1);
|
||||||
@@ -505,10 +788,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
{
|
{
|
||||||
// Setup:
|
// Setup:
|
||||||
// ... Create a session with a proper query and metadata
|
// ... Create a session with a proper query and metadata
|
||||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
EditSession s = await GetBasicSession();
|
||||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
|
||||||
IEditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
|
||||||
EditSession s = new EditSession(rs, etm);
|
|
||||||
|
|
||||||
// ... Add a row creation
|
// ... Add a row creation
|
||||||
s.CreateRow();
|
s.CreateRow();
|
||||||
@@ -536,10 +816,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
{
|
{
|
||||||
// Setup:
|
// Setup:
|
||||||
// ... Create a session with a query and metadata
|
// ... Create a session with a query and metadata
|
||||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
EditSession s = await GetBasicSession();
|
||||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
|
||||||
IEditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
|
||||||
EditSession s = new EditSession(rs, etm);
|
|
||||||
|
|
||||||
// ... Add a few row creations
|
// ... Add a few row creations
|
||||||
s.CreateRow();
|
s.CreateRow();
|
||||||
@@ -561,17 +838,27 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
|
|
||||||
#region Script Edits Tests
|
#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]
|
[Theory]
|
||||||
[InlineData(null)]
|
[InlineData(null)]
|
||||||
[InlineData("")]
|
[InlineData("")]
|
||||||
[InlineData(" \t\r\n")]
|
[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
|
// Setup: Create a session with a proper query and metadata
|
||||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
EditSession s = await GetBasicSession();
|
||||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
|
||||||
IEditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
|
||||||
EditSession s = new EditSession(rs, etm);
|
|
||||||
|
|
||||||
// If: I try to script the edit cache with a null or whitespace output path
|
// If: I try to script the edit cache with a null or whitespace output path
|
||||||
// Then: It should throw an exception
|
// Then: It should throw an exception
|
||||||
@@ -579,14 +866,11 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void ScriptProvidedOutputPath()
|
public async Task ScriptProvidedOutputPath()
|
||||||
{
|
{
|
||||||
// Setup:
|
// Setup:
|
||||||
// ... Create a session with a proper query and metadata
|
// ... Create a session with a proper query and metadata
|
||||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
EditSession s = await GetBasicSession();
|
||||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
|
||||||
IEditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
|
||||||
EditSession s = new EditSession(rs, etm);
|
|
||||||
|
|
||||||
// ... Add two mock edits that will generate a script
|
// ... Add two mock edits that will generate a script
|
||||||
Mock<RowEditBase> edit = new Mock<RowEditBase>();
|
Mock<RowEditBase> edit = new Mock<RowEditBase>();
|
||||||
@@ -613,10 +897,23 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
#region Commit Tests
|
#region Commit Tests
|
||||||
|
|
||||||
[Fact]
|
[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
|
// Setup: Create a basic session
|
||||||
EditSession s = GetBasicSession();
|
EditSession s = await GetBasicSession();
|
||||||
|
|
||||||
// If: I attempt to commit with a null connection
|
// If: I attempt to commit with a null connection
|
||||||
// Then: I should get an exception
|
// Then: I should get an exception
|
||||||
@@ -625,11 +922,11 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void CommitNullSuccessHandler()
|
public async Task CommitNullSuccessHandler()
|
||||||
{
|
{
|
||||||
// Setup:
|
// Setup:
|
||||||
// ... Create a basic session
|
// ... Create a basic session
|
||||||
EditSession s = GetBasicSession();
|
EditSession s = await GetBasicSession();
|
||||||
|
|
||||||
// ... Mock db connection
|
// ... Mock db connection
|
||||||
DbConnection conn = new TestSqlConnection(null);
|
DbConnection conn = new TestSqlConnection(null);
|
||||||
@@ -640,11 +937,11 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void CommitNullFailureHandler()
|
public async Task CommitNullFailureHandler()
|
||||||
{
|
{
|
||||||
// Setup:
|
// Setup:
|
||||||
// ... Create a basic session
|
// ... Create a basic session
|
||||||
EditSession s = GetBasicSession();
|
EditSession s = await GetBasicSession();
|
||||||
|
|
||||||
// ... Mock db connection
|
// ... Mock db connection
|
||||||
DbConnection conn = new TestSqlConnection(null);
|
DbConnection conn = new TestSqlConnection(null);
|
||||||
@@ -655,11 +952,11 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void CommitInProgress()
|
public async Task CommitInProgress()
|
||||||
{
|
{
|
||||||
// Setup:
|
// Setup:
|
||||||
// ... Basic session and db connection
|
// ... Basic session and db connection
|
||||||
EditSession s = GetBasicSession();
|
EditSession s = await GetBasicSession();
|
||||||
DbConnection conn = new TestSqlConnection(null);
|
DbConnection conn = new TestSqlConnection(null);
|
||||||
|
|
||||||
// ... Mock a task that has not completed
|
// ... Mock a task that has not completed
|
||||||
@@ -677,7 +974,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
{
|
{
|
||||||
// Setup:
|
// Setup:
|
||||||
// ... Basic session and db connection
|
// ... Basic session and db connection
|
||||||
EditSession s = GetBasicSession();
|
EditSession s = await GetBasicSession();
|
||||||
DbConnection conn = new TestSqlConnection(null);
|
DbConnection conn = new TestSqlConnection(null);
|
||||||
|
|
||||||
// ... Add a mock commands for fun
|
// ... Add a mock commands for fun
|
||||||
@@ -721,7 +1018,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
{
|
{
|
||||||
// Setup:
|
// Setup:
|
||||||
// ... Basic session and db connection
|
// ... Basic session and db connection
|
||||||
EditSession s = GetBasicSession();
|
EditSession s = await GetBasicSession();
|
||||||
DbConnection conn = new TestSqlConnection(null);
|
DbConnection conn = new TestSqlConnection(null);
|
||||||
|
|
||||||
// ... Add a mock edit that will explode on generating a command
|
// ... Add a mock edit that will explode on generating a command
|
||||||
@@ -760,12 +1057,51 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
|||||||
|
|
||||||
#endregion
|
#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();
|
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
||||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
ResultSet rs = q.Batches[0].ResultSets[0];
|
||||||
IEditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
EditTableMetadata etm = Common.GetStandardMetadata(rs.Columns);
|
||||||
return new EditSession(rs, etm);
|
return await Common.GetCustomSession(q, etm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -302,7 +302,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Setup: Create a DATE column
|
// 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)
|
foreach (DateTime value in testValues)
|
||||||
{
|
{
|
||||||
@@ -324,7 +324,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Setup: Create a DATETIME column
|
// 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)
|
foreach (DateTime value in testValues)
|
||||||
{
|
{
|
||||||
@@ -353,7 +353,11 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Setup: Create a DATETIME column
|
// 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)
|
foreach (DateTime value in testValues)
|
||||||
{
|
{
|
||||||
@@ -379,7 +383,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Setup: Create a DATETIME2 column
|
// 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)
|
foreach (DateTime value in testValues)
|
||||||
{
|
{
|
||||||
@@ -401,7 +405,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Setup: Create a DATETIME2 column
|
// 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)
|
foreach (DateTime value in testValues)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,11 +4,85 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Data.Common;
|
using System.Data.Common;
|
||||||
|
using Microsoft.SqlTools.Utility;
|
||||||
|
|
||||||
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Utility
|
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Utility
|
||||||
{
|
{
|
||||||
public class TestDbColumn : DbColumn
|
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)
|
public TestDbColumn(string columnName)
|
||||||
{
|
{
|
||||||
base.IsLong = false;
|
base.IsLong = false;
|
||||||
@@ -18,34 +92,5 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Utility
|
|||||||
base.DataType = typeof(string);
|
base.DataType = typeof(string);
|
||||||
base.DataTypeName = "nvarchar";
|
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