mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-13 17:23:02 -05:00
edit/commit Command (#262)
The main goal of this feature is to enable a command that will 1) Generate a parameterized command for each edit that is in the session 2) Execute that command against the server 3) Update the cached results of the table/view that's being edited with the committed changes (including computed/identity columns) There's some secret sauce in here where I cheated around worrying about gaps in the updated results. This was accomplished by implementing an IComparable for row edit objects that ensures deletes are the *last* actions to occur and that they occur from the bottom of the list up (highest row ID to lowest). Thus, all other actions that are dependent on the row ID are performed first, then the largest row ID is deleted, then next largest, etc. Nevertheless, by the end of a commit the associated ResultSet is still the source of truth. It is expected that the results grid will need updating once changes are committed. Also worth noting, although this pull request supports a "many edits, one commit" approach, it will work just fine for a "one edit, one commit" approach. * WIP * Adding basic commit support. Deletions work! * Nailing down the commit logic, insert commits work! * Updates work! * Fixing bug in DbColumnWrapper IsReadOnly setting * Comments * ResultSet unit tests, fixing issue with seeking in mock writers * Unit tests for RowCreate commands * Unit tests for RowDelete * RowUpdate unit tests * Session and edit base tests * Fixing broken unit tests * Moving constants to constants file * Addressing code review feedback * Fixes from merge issues, string consts * Removing ad-hoc code * fixing as per @abist requests * Fixing a couple more issues
This commit is contained in:
@@ -38,7 +38,7 @@ namespace Microsoft.SqlTools.Credentials.Localization {
|
||||
public static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.SqlTools.ServiceLayer.Localization.sr", typeof(sr).GetTypeInfo().Assembly);
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.SqlTools.Credentials.Localization.sr", typeof(sr).GetTypeInfo().Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
@@ -59,195 +59,6 @@ namespace Microsoft.SqlTools.Credentials.Localization {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to File '{0}' recursively included..
|
||||
/// </summary>
|
||||
public static string BatchParser_CircularReference {
|
||||
get {
|
||||
return ResourceManager.GetString("BatchParser_CircularReference", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Missing end comment mark '*/'..
|
||||
/// </summary>
|
||||
public static string BatchParser_CommentNotTerminated {
|
||||
get {
|
||||
return ResourceManager.GetString("BatchParser_CommentNotTerminated", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Incorrect syntax was encountered while parsing '{0}'..
|
||||
/// </summary>
|
||||
public static string BatchParser_IncorrectSyntax {
|
||||
get {
|
||||
return ResourceManager.GetString("BatchParser_IncorrectSyntax", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Unclosed quotation mark after the character string..
|
||||
/// </summary>
|
||||
public static string BatchParser_StringNotTerminated {
|
||||
get {
|
||||
return ResourceManager.GetString("BatchParser_StringNotTerminated", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Variable {0} is not defined..
|
||||
/// </summary>
|
||||
public static string BatchParser_VariableNotDefined {
|
||||
get {
|
||||
return ResourceManager.GetString("BatchParser_VariableNotDefined", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Canceling batch parser wrapper batch execution..
|
||||
/// </summary>
|
||||
public static string BatchParserWrapperExecutionEngineBatchCancelling {
|
||||
get {
|
||||
return ResourceManager.GetString("BatchParserWrapperExecutionEngineBatchCancelling", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Batch parser wrapper execution engine batch message received: Message: {0} Detailed message: {1}.
|
||||
/// </summary>
|
||||
public static string BatchParserWrapperExecutionEngineBatchMessage {
|
||||
get {
|
||||
return ResourceManager.GetString("BatchParserWrapperExecutionEngineBatchMessage", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Batch parser wrapper execution engine batch ResultSet finished..
|
||||
/// </summary>
|
||||
public static string BatchParserWrapperExecutionEngineBatchResultSetFinished {
|
||||
get {
|
||||
return ResourceManager.GetString("BatchParserWrapperExecutionEngineBatchResultSetFinished", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Batch parser wrapper execution engine batch ResultSet processing: DataReader.FieldCount: {0} DataReader.RecordsAffected: {1}.
|
||||
/// </summary>
|
||||
public static string BatchParserWrapperExecutionEngineBatchResultSetProcessing {
|
||||
get {
|
||||
return ResourceManager.GetString("BatchParserWrapperExecutionEngineBatchResultSetProcessing", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to SQL Execution error: {0}.
|
||||
/// </summary>
|
||||
public static string BatchParserWrapperExecutionEngineError {
|
||||
get {
|
||||
return ResourceManager.GetString("BatchParserWrapperExecutionEngineError", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Batch parser wrapper execution: {0} found... at line {1}: {2} Description: {3}.
|
||||
/// </summary>
|
||||
public static string BatchParserWrapperExecutionError {
|
||||
get {
|
||||
return ResourceManager.GetString("BatchParserWrapperExecutionError", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Connection details object cannot be null.
|
||||
/// </summary>
|
||||
public static string ConnectionParamsValidateNullConnection {
|
||||
get {
|
||||
return ResourceManager.GetString("ConnectionParamsValidateNullConnection", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to OwnerUri cannot be null or empty.
|
||||
/// </summary>
|
||||
public static string ConnectionParamsValidateNullOwnerUri {
|
||||
get {
|
||||
return ResourceManager.GetString("ConnectionParamsValidateNullOwnerUri", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to ServerName cannot be null or empty.
|
||||
/// </summary>
|
||||
public static string ConnectionParamsValidateNullServerName {
|
||||
get {
|
||||
return ResourceManager.GetString("ConnectionParamsValidateNullServerName", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to {0} cannot be null or empty when using SqlLogin authentication.
|
||||
/// </summary>
|
||||
public static string ConnectionParamsValidateNullSqlAuth {
|
||||
get {
|
||||
return ResourceManager.GetString("ConnectionParamsValidateNullSqlAuth", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Connection parameters cannot be null.
|
||||
/// </summary>
|
||||
public static string ConnectionServiceConnectErrorNullParams {
|
||||
get {
|
||||
return ResourceManager.GetString("ConnectionServiceConnectErrorNullParams", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Connection canceled.
|
||||
/// </summary>
|
||||
public static string ConnectionServiceConnectionCanceled {
|
||||
get {
|
||||
return ResourceManager.GetString("ConnectionServiceConnectionCanceled", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Invalid value '{0}' for AuthenticationType. Valid values are 'Integrated' and 'SqlLogin'..
|
||||
/// </summary>
|
||||
public static string ConnectionServiceConnStringInvalidAuthType {
|
||||
get {
|
||||
return ResourceManager.GetString("ConnectionServiceConnStringInvalidAuthType", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Invalid value '{0}' for ApplicationIntent. Valid values are 'ReadWrite' and 'ReadOnly'..
|
||||
/// </summary>
|
||||
public static string ConnectionServiceConnStringInvalidIntent {
|
||||
get {
|
||||
return ResourceManager.GetString("ConnectionServiceConnStringInvalidIntent", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to SpecifiedUri '{0}' does not have existing connection.
|
||||
/// </summary>
|
||||
public static string ConnectionServiceListDbErrorNotConnected {
|
||||
get {
|
||||
return ResourceManager.GetString("ConnectionServiceListDbErrorNotConnected", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to OwnerUri cannot be null or empty.
|
||||
/// </summary>
|
||||
public static string ConnectionServiceListDbErrorNullOwnerUri {
|
||||
get {
|
||||
return ResourceManager.GetString("ConnectionServiceListDbErrorNullOwnerUri", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Win32Credential object is already disposed.
|
||||
/// </summary>
|
||||
@@ -292,662 +103,5 @@ namespace Microsoft.SqlTools.Credentials.Localization {
|
||||
return ResourceManager.GetString("CredentialsServiceTargetForLookup", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to An error occurred while the batch was being processed. The error message is: {0}.
|
||||
/// </summary>
|
||||
public static string EE_BatchError_Exception {
|
||||
get {
|
||||
return ResourceManager.GetString("EE_BatchError_Exception", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to An error occurred while the batch was being executed..
|
||||
/// </summary>
|
||||
public static string EE_BatchExecutionError_Halting {
|
||||
get {
|
||||
return ResourceManager.GetString("EE_BatchExecutionError_Halting", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to An error occurred while the batch was being executed, but the error has been ignored..
|
||||
/// </summary>
|
||||
public static string EE_BatchExecutionError_Ignoring {
|
||||
get {
|
||||
return ResourceManager.GetString("EE_BatchExecutionError_Ignoring", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to ({0} row(s) affected).
|
||||
/// </summary>
|
||||
public static string EE_BatchExecutionInfo_RowsAffected {
|
||||
get {
|
||||
return ResourceManager.GetString("EE_BatchExecutionInfo_RowsAffected", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Msg {0}, Level {1}, State {2}.
|
||||
/// </summary>
|
||||
public static string EE_BatchSqlMessageNoLineInfo {
|
||||
get {
|
||||
return ResourceManager.GetString("EE_BatchSqlMessageNoLineInfo", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Msg {0}, Level {1}, State {2}, Line {3}.
|
||||
/// </summary>
|
||||
public static string EE_BatchSqlMessageNoProcedureInfo {
|
||||
get {
|
||||
return ResourceManager.GetString("EE_BatchSqlMessageNoProcedureInfo", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Msg {0}, Level {1}, State {2}, Procedure {3}, Line {4}.
|
||||
/// </summary>
|
||||
public static string EE_BatchSqlMessageWithProcedureInfo {
|
||||
get {
|
||||
return ResourceManager.GetString("EE_BatchSqlMessageWithProcedureInfo", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Command {0} is not supported..
|
||||
/// </summary>
|
||||
public static string EE_ExecutionError_CommandNotSupported {
|
||||
get {
|
||||
return ResourceManager.GetString("EE_ExecutionError_CommandNotSupported", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The variable {0} could not be found..
|
||||
/// </summary>
|
||||
public static string EE_ExecutionError_VariableNotFound {
|
||||
get {
|
||||
return ResourceManager.GetString("EE_ExecutionError_VariableNotFound", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Execution completed {0} times....
|
||||
/// </summary>
|
||||
public static string EE_ExecutionInfo_FinalizingLoop {
|
||||
get {
|
||||
return ResourceManager.GetString("EE_ExecutionInfo_FinalizingLoop", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Starting execution loop of {0} times....
|
||||
/// </summary>
|
||||
public static string EE_ExecutionInfo_InitilizingLoop {
|
||||
get {
|
||||
return ResourceManager.GetString("EE_ExecutionInfo_InitilizingLoop", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to You cancelled the query..
|
||||
/// </summary>
|
||||
public static string EE_ExecutionInfo_QueryCancelledbyUser {
|
||||
get {
|
||||
return ResourceManager.GetString("EE_ExecutionInfo_QueryCancelledbyUser", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The previous execution is not yet complete..
|
||||
/// </summary>
|
||||
public static string EE_ExecutionNotYetCompleteError {
|
||||
get {
|
||||
return ResourceManager.GetString("EE_ExecutionNotYetCompleteError", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to A scripting error occurred..
|
||||
/// </summary>
|
||||
public static string EE_ScriptError_Error {
|
||||
get {
|
||||
return ResourceManager.GetString("EE_ScriptError_Error", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to A fatal error occurred..
|
||||
/// </summary>
|
||||
public static string EE_ScriptError_FatalError {
|
||||
get {
|
||||
return ResourceManager.GetString("EE_ScriptError_FatalError", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Incorrect syntax was encountered while {0} was being parsed..
|
||||
/// </summary>
|
||||
public static string EE_ScriptError_ParsingSyntax {
|
||||
get {
|
||||
return ResourceManager.GetString("EE_ScriptError_ParsingSyntax", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Scripting warning..
|
||||
/// </summary>
|
||||
public static string EE_ScriptError_Warning {
|
||||
get {
|
||||
return ResourceManager.GetString("EE_ScriptError_Warning", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Replacement of an empty string by an empty string..
|
||||
/// </summary>
|
||||
public static string ErrorEmptyStringReplacement {
|
||||
get {
|
||||
return ResourceManager.GetString("ErrorEmptyStringReplacement", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Cannot convert SqlCodeObject Type {0} to Type {1}.
|
||||
/// </summary>
|
||||
public static string ErrorUnexpectedCodeObjectType {
|
||||
get {
|
||||
return ResourceManager.GetString("ErrorUnexpectedCodeObjectType", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Message header must separate key and value using ':'.
|
||||
/// </summary>
|
||||
public static string HostingHeaderMissingColon {
|
||||
get {
|
||||
return ResourceManager.GetString("HostingHeaderMissingColon", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Fatal error: Content-Length header must be provided.
|
||||
/// </summary>
|
||||
public static string HostingHeaderMissingContentLengthHeader {
|
||||
get {
|
||||
return ResourceManager.GetString("HostingHeaderMissingContentLengthHeader", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Fatal error: Content-Length value is not an integer.
|
||||
/// </summary>
|
||||
public static string HostingHeaderMissingContentLengthValue {
|
||||
get {
|
||||
return ResourceManager.GetString("HostingHeaderMissingContentLengthValue", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to MessageReader's input stream ended unexpectedly, terminating.
|
||||
/// </summary>
|
||||
public static string HostingUnexpectedEndOfStream {
|
||||
get {
|
||||
return ResourceManager.GetString("HostingUnexpectedEndOfStream", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Service of type {0} cannot be created by ExtensionLoader<{1}>.
|
||||
/// </summary>
|
||||
public static string IncompatibleServiceForExtensionLoader {
|
||||
get {
|
||||
return ResourceManager.GetString("IncompatibleServiceForExtensionLoader", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Multiple services found for type {0}, expected only 1.
|
||||
/// </summary>
|
||||
public static string MultipleServicesFound {
|
||||
get {
|
||||
return ResourceManager.GetString("MultipleServicesFound", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to This feature is currently not supported on Azure SQL DB and Data Warehouse: {0}.
|
||||
/// </summary>
|
||||
public static string PeekDefinitionAzureError {
|
||||
get {
|
||||
return ResourceManager.GetString("PeekDefinitionAzureError", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to No database object was retrieved..
|
||||
/// </summary>
|
||||
public static string PeekDefinitionDatabaseError {
|
||||
get {
|
||||
return ResourceManager.GetString("PeekDefinitionDatabaseError", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to An unexpected error occurred during Peek Definition execution: {0}.
|
||||
/// </summary>
|
||||
public static string PeekDefinitionError {
|
||||
get {
|
||||
return ResourceManager.GetString("PeekDefinitionError", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to No results were found..
|
||||
/// </summary>
|
||||
public static string PeekDefinitionNoResultsError {
|
||||
get {
|
||||
return ResourceManager.GetString("PeekDefinitionNoResultsError", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Please connect to a server..
|
||||
/// </summary>
|
||||
public static string PeekDefinitionNotConnectedError {
|
||||
get {
|
||||
return ResourceManager.GetString("PeekDefinitionNotConnectedError", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Operation timed out..
|
||||
/// </summary>
|
||||
public static string PeekDefinitionTimedoutError {
|
||||
get {
|
||||
return ResourceManager.GetString("PeekDefinitionTimedoutError", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to This object type is currently not supported by this feature..
|
||||
/// </summary>
|
||||
public static string PeekDefinitionTypeNotSupportedError {
|
||||
get {
|
||||
return ResourceManager.GetString("PeekDefinitionTypeNotSupportedError", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to (1 row affected).
|
||||
/// </summary>
|
||||
public static string QueryServiceAffectedOneRow {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceAffectedOneRow", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to ({0} rows affected).
|
||||
/// </summary>
|
||||
public static string QueryServiceAffectedRows {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceAffectedRows", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The query has already completed, it cannot be cancelled.
|
||||
/// </summary>
|
||||
public static string QueryServiceCancelAlreadyCompleted {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceCancelAlreadyCompleted", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Query successfully cancelled, failed to dispose query. Owner URI not found..
|
||||
/// </summary>
|
||||
public static string QueryServiceCancelDisposeFailed {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceCancelDisposeFailed", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to (No column name).
|
||||
/// </summary>
|
||||
public static string QueryServiceColumnNull {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceColumnNull", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Commands completed successfully..
|
||||
/// </summary>
|
||||
public static string QueryServiceCompletedSuccessfully {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceCompletedSuccessfully", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Maximum number of bytes to return must be greater than zero.
|
||||
/// </summary>
|
||||
public static string QueryServiceDataReaderByteCountInvalid {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceDataReaderByteCountInvalid", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Maximum number of chars to return must be greater than zero.
|
||||
/// </summary>
|
||||
public static string QueryServiceDataReaderCharCountInvalid {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceDataReaderCharCountInvalid", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Maximum number of XML bytes to return must be greater than zero.
|
||||
/// </summary>
|
||||
public static string QueryServiceDataReaderXmlCountInvalid {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceDataReaderXmlCountInvalid", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Msg {0}, Level {1}, State {2}, Line {3}{4}{5}.
|
||||
/// </summary>
|
||||
public static string QueryServiceErrorFormat {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceErrorFormat", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Could not retrieve an execution plan from the result set .
|
||||
/// </summary>
|
||||
public static string QueryServiceExecutionPlanNotFound {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceExecutionPlanNotFound", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to FileStreamWrapper must be initialized before performing operations.
|
||||
/// </summary>
|
||||
public static string QueryServiceFileWrapperNotInitialized {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceFileWrapperNotInitialized", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to This FileStreamWrapper cannot be used for writing.
|
||||
/// </summary>
|
||||
public static string QueryServiceFileWrapperReadOnly {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceFileWrapperReadOnly", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Access method cannot be write-only.
|
||||
/// </summary>
|
||||
public static string QueryServiceFileWrapperWriteOnly {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceFileWrapperWriteOnly", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Sender for OnInfoMessage event must be a SqlConnection.
|
||||
/// </summary>
|
||||
public static string QueryServiceMessageSenderNotSql {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceMessageSenderNotSql", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Query was canceled by user.
|
||||
/// </summary>
|
||||
public static string QueryServiceQueryCancelled {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceQueryCancelled", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Query failed: {0}.
|
||||
/// </summary>
|
||||
public static string QueryServiceQueryFailed {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceQueryFailed", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to A query is already in progress for this editor session. Please cancel this query or wait for its completion..
|
||||
/// </summary>
|
||||
public static string QueryServiceQueryInProgress {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceQueryInProgress", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to This editor is not connected to a database.
|
||||
/// </summary>
|
||||
public static string QueryServiceQueryInvalidOwnerUri {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceQueryInvalidOwnerUri", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The requested query does not exist.
|
||||
/// </summary>
|
||||
public static string QueryServiceRequestsNoQuery {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceRequestsNoQuery", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Could not retrieve column schema for result set.
|
||||
/// </summary>
|
||||
public static string QueryServiceResultSetNoColumnSchema {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceResultSetNoColumnSchema", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Cannot read subset unless the results have been read from the server.
|
||||
/// </summary>
|
||||
public static string QueryServiceResultSetNotRead {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceResultSetNotRead", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Reader cannot be null.
|
||||
/// </summary>
|
||||
public static string QueryServiceResultSetReaderNull {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceResultSetReaderNull", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Row count must be a positive integer.
|
||||
/// </summary>
|
||||
public static string QueryServiceResultSetRowCountOutOfRange {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceResultSetRowCountOutOfRange", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Start row cannot be less than 0 or greater than the number of rows in the result set.
|
||||
/// </summary>
|
||||
public static string QueryServiceResultSetStartRowOutOfRange {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceResultSetStartRowOutOfRange", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Failed to save {0}: {1}.
|
||||
/// </summary>
|
||||
public static string QueryServiceSaveAsFail {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceSaveAsFail", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to A save request to the same path is in progress.
|
||||
/// </summary>
|
||||
public static string QueryServiceSaveAsInProgress {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceSaveAsInProgress", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Internal error occurred while starting save task.
|
||||
/// </summary>
|
||||
public static string QueryServiceSaveAsMiscStartingError {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceSaveAsMiscStartingError", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Result cannot be saved until query execution has completed.
|
||||
/// </summary>
|
||||
public static string QueryServiceSaveAsResultSetNotComplete {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceSaveAsResultSetNotComplete", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The batch has not completed, yet.
|
||||
/// </summary>
|
||||
public static string QueryServiceSubsetBatchNotCompleted {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceSubsetBatchNotCompleted", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Batch index cannot be less than 0 or greater than the number of batches.
|
||||
/// </summary>
|
||||
public static string QueryServiceSubsetBatchOutOfRange {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceSubsetBatchOutOfRange", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Result set index cannot be less than 0 or greater than the number of result sets.
|
||||
/// </summary>
|
||||
public static string QueryServiceSubsetResultSetOutOfRange {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceSubsetResultSetOutOfRange", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Cannot register service for type {0}, one or more services already registered.
|
||||
/// </summary>
|
||||
public static string ServiceAlreadyRegistered {
|
||||
get {
|
||||
return ResourceManager.GetString("ServiceAlreadyRegistered", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Service {0} was not found in the service provider.
|
||||
/// </summary>
|
||||
public static string ServiceNotFound {
|
||||
get {
|
||||
return ResourceManager.GetString("ServiceNotFound", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Service of Type {0} is not compatible with registered Type {1}.
|
||||
/// </summary>
|
||||
public static string ServiceNotOfExpectedType {
|
||||
get {
|
||||
return ResourceManager.GetString("ServiceNotOfExpectedType", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to SetServiceProvider() was not called to establish the required service provider.
|
||||
/// </summary>
|
||||
public static string ServiceProviderNotSet {
|
||||
get {
|
||||
return ResourceManager.GetString("ServiceProviderNotSet", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to EN_LOCALIZATION.
|
||||
/// </summary>
|
||||
public static string TestLocalizationConstant {
|
||||
get {
|
||||
return ResourceManager.GetString("TestLocalizationConstant", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to For more information about this error, see the troubleshooting topics in the product documentation..
|
||||
/// </summary>
|
||||
public static string TroubleshootingAssistanceMessage {
|
||||
get {
|
||||
return ResourceManager.GetString("TroubleshootingAssistanceMessage", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Start position ({0}, {1}) must come before or be equal to the end position ({2}, {3}).
|
||||
/// </summary>
|
||||
public static string WorkspaceServiceBufferPositionOutOfOrder {
|
||||
get {
|
||||
return ResourceManager.GetString("WorkspaceServiceBufferPositionOutOfOrder", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Position is outside of column range for line {0}.
|
||||
/// </summary>
|
||||
public static string WorkspaceServicePositionColumnOutOfRange {
|
||||
get {
|
||||
return ResourceManager.GetString("WorkspaceServicePositionColumnOutOfRange", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Position is outside of file line range.
|
||||
/// </summary>
|
||||
public static string WorkspaceServicePositionLineOutOfRange {
|
||||
get {
|
||||
return ResourceManager.GetString("WorkspaceServicePositionLineOutOfRange", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace Microsoft.SqlTools.Credentials
|
||||
Keys.Culture = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static string CredentialsServiceInvalidCriticalHandle
|
||||
{
|
||||
@@ -35,7 +35,7 @@ namespace Microsoft.SqlTools.Credentials
|
||||
{
|
||||
return Keys.GetString(Keys.CredentialsServiceInvalidCriticalHandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static string CredentialsServicePasswordLengthExceeded
|
||||
{
|
||||
@@ -43,7 +43,7 @@ namespace Microsoft.SqlTools.Credentials
|
||||
{
|
||||
return Keys.GetString(Keys.CredentialsServicePasswordLengthExceeded);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static string CredentialsServiceTargetForDelete
|
||||
{
|
||||
@@ -51,7 +51,7 @@ namespace Microsoft.SqlTools.Credentials
|
||||
{
|
||||
return Keys.GetString(Keys.CredentialsServiceTargetForDelete);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static string CredentialsServiceTargetForLookup
|
||||
{
|
||||
@@ -59,7 +59,7 @@ namespace Microsoft.SqlTools.Credentials
|
||||
{
|
||||
return Keys.GetString(Keys.CredentialsServiceTargetForLookup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static string CredentialServiceWin32CredentialDisposed
|
||||
{
|
||||
@@ -67,7 +67,7 @@ namespace Microsoft.SqlTools.Credentials
|
||||
{
|
||||
return Keys.GetString(Keys.CredentialServiceWin32CredentialDisposed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
public class Keys
|
||||
@@ -75,22 +75,22 @@ namespace Microsoft.SqlTools.Credentials
|
||||
static ResourceManager resourceManager = new ResourceManager("Microsoft.SqlTools.Credentials.Localization.SR", typeof(SR).GetTypeInfo().Assembly);
|
||||
|
||||
static CultureInfo _culture = null;
|
||||
|
||||
|
||||
public const string CredentialsServiceInvalidCriticalHandle = "CredentialsServiceInvalidCriticalHandle";
|
||||
|
||||
|
||||
public const string CredentialsServicePasswordLengthExceeded = "CredentialsServicePasswordLengthExceeded";
|
||||
|
||||
|
||||
public const string CredentialsServiceTargetForDelete = "CredentialsServiceTargetForDelete";
|
||||
|
||||
|
||||
public const string CredentialsServiceTargetForLookup = "CredentialsServiceTargetForLookup";
|
||||
|
||||
|
||||
public const string CredentialServiceWin32CredentialDisposed = "CredentialServiceWin32CredentialDisposed";
|
||||
|
||||
|
||||
|
||||
public const string CredentialsServiceInvalidCriticalHandle = "CredentialsServiceInvalidCriticalHandle";
|
||||
|
||||
|
||||
public const string CredentialsServicePasswordLengthExceeded = "CredentialsServicePasswordLengthExceeded";
|
||||
|
||||
|
||||
public const string CredentialsServiceTargetForDelete = "CredentialsServiceTargetForDelete";
|
||||
|
||||
|
||||
public const string CredentialsServiceTargetForLookup = "CredentialsServiceTargetForLookup";
|
||||
|
||||
|
||||
public const string CredentialServiceWin32CredentialDisposed = "CredentialServiceWin32CredentialDisposed";
|
||||
|
||||
|
||||
private Keys()
|
||||
{ }
|
||||
@@ -111,7 +111,7 @@ namespace Microsoft.SqlTools.Credentials
|
||||
{
|
||||
return resourceManager.GetString(key, _culture);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,96 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
@@ -27,5 +105,19 @@
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype"><value>text/microsoft-resx</value></resheader><resheader name="version"><value>1.3</value></resheader><resheader name="reader"><value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value></resheader><resheader name="writer"><value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value></resheader><data name="TestLocalizationConstant"><value>ES_LOCALIZATION</value></data>
|
||||
</root>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="TestLocalizationConstant" xml:space="preserve">
|
||||
<value>ES_LOCALIZATION</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -120,21 +120,21 @@
|
||||
<data name="CredentialsServiceInvalidCriticalHandle" xml:space="preserve">
|
||||
<value>Invalid CriticalHandle!</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="CredentialsServicePasswordLengthExceeded" xml:space="preserve">
|
||||
<value>The password has exceeded 512 bytes</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="CredentialsServiceTargetForDelete" xml:space="preserve">
|
||||
<value>Target must be specified to delete a credential</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="CredentialsServiceTargetForLookup" xml:space="preserve">
|
||||
<value>Target must be specified to check existance of a credential</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="CredentialServiceWin32CredentialDisposed" xml:space="preserve">
|
||||
<value>Win32Credential object is already disposed</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</root>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace Microsoft.SqlTools.Hosting.Localization {
|
||||
public static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.SqlTools.ServiceLayer.Localization.sr", typeof(sr).GetTypeInfo().Assembly);
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.SqlTools.Hosting.Localization.sr", typeof(sr).GetTypeInfo().Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
@@ -59,195 +59,6 @@ namespace Microsoft.SqlTools.Hosting.Localization {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to File '{0}' recursively included..
|
||||
/// </summary>
|
||||
public static string BatchParser_CircularReference {
|
||||
get {
|
||||
return ResourceManager.GetString("BatchParser_CircularReference", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Missing end comment mark '*/'..
|
||||
/// </summary>
|
||||
public static string BatchParser_CommentNotTerminated {
|
||||
get {
|
||||
return ResourceManager.GetString("BatchParser_CommentNotTerminated", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Incorrect syntax was encountered while parsing '{0}'..
|
||||
/// </summary>
|
||||
public static string BatchParser_IncorrectSyntax {
|
||||
get {
|
||||
return ResourceManager.GetString("BatchParser_IncorrectSyntax", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Unclosed quotation mark after the character string..
|
||||
/// </summary>
|
||||
public static string BatchParser_StringNotTerminated {
|
||||
get {
|
||||
return ResourceManager.GetString("BatchParser_StringNotTerminated", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Variable {0} is not defined..
|
||||
/// </summary>
|
||||
public static string BatchParser_VariableNotDefined {
|
||||
get {
|
||||
return ResourceManager.GetString("BatchParser_VariableNotDefined", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Canceling batch parser wrapper batch execution..
|
||||
/// </summary>
|
||||
public static string BatchParserWrapperExecutionEngineBatchCancelling {
|
||||
get {
|
||||
return ResourceManager.GetString("BatchParserWrapperExecutionEngineBatchCancelling", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Batch parser wrapper execution engine batch message received: Message: {0} Detailed message: {1}.
|
||||
/// </summary>
|
||||
public static string BatchParserWrapperExecutionEngineBatchMessage {
|
||||
get {
|
||||
return ResourceManager.GetString("BatchParserWrapperExecutionEngineBatchMessage", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Batch parser wrapper execution engine batch ResultSet finished..
|
||||
/// </summary>
|
||||
public static string BatchParserWrapperExecutionEngineBatchResultSetFinished {
|
||||
get {
|
||||
return ResourceManager.GetString("BatchParserWrapperExecutionEngineBatchResultSetFinished", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Batch parser wrapper execution engine batch ResultSet processing: DataReader.FieldCount: {0} DataReader.RecordsAffected: {1}.
|
||||
/// </summary>
|
||||
public static string BatchParserWrapperExecutionEngineBatchResultSetProcessing {
|
||||
get {
|
||||
return ResourceManager.GetString("BatchParserWrapperExecutionEngineBatchResultSetProcessing", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to SQL Execution error: {0}.
|
||||
/// </summary>
|
||||
public static string BatchParserWrapperExecutionEngineError {
|
||||
get {
|
||||
return ResourceManager.GetString("BatchParserWrapperExecutionEngineError", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Batch parser wrapper execution: {0} found... at line {1}: {2} Description: {3}.
|
||||
/// </summary>
|
||||
public static string BatchParserWrapperExecutionError {
|
||||
get {
|
||||
return ResourceManager.GetString("BatchParserWrapperExecutionError", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Connection details object cannot be null.
|
||||
/// </summary>
|
||||
public static string ConnectionParamsValidateNullConnection {
|
||||
get {
|
||||
return ResourceManager.GetString("ConnectionParamsValidateNullConnection", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to OwnerUri cannot be null or empty.
|
||||
/// </summary>
|
||||
public static string ConnectionParamsValidateNullOwnerUri {
|
||||
get {
|
||||
return ResourceManager.GetString("ConnectionParamsValidateNullOwnerUri", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to ServerName cannot be null or empty.
|
||||
/// </summary>
|
||||
public static string ConnectionParamsValidateNullServerName {
|
||||
get {
|
||||
return ResourceManager.GetString("ConnectionParamsValidateNullServerName", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to {0} cannot be null or empty when using SqlLogin authentication.
|
||||
/// </summary>
|
||||
public static string ConnectionParamsValidateNullSqlAuth {
|
||||
get {
|
||||
return ResourceManager.GetString("ConnectionParamsValidateNullSqlAuth", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Connection parameters cannot be null.
|
||||
/// </summary>
|
||||
public static string ConnectionServiceConnectErrorNullParams {
|
||||
get {
|
||||
return ResourceManager.GetString("ConnectionServiceConnectErrorNullParams", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Connection canceled.
|
||||
/// </summary>
|
||||
public static string ConnectionServiceConnectionCanceled {
|
||||
get {
|
||||
return ResourceManager.GetString("ConnectionServiceConnectionCanceled", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Invalid value '{0}' for AuthenticationType. Valid values are 'Integrated' and 'SqlLogin'..
|
||||
/// </summary>
|
||||
public static string ConnectionServiceConnStringInvalidAuthType {
|
||||
get {
|
||||
return ResourceManager.GetString("ConnectionServiceConnStringInvalidAuthType", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Invalid value '{0}' for ApplicationIntent. Valid values are 'ReadWrite' and 'ReadOnly'..
|
||||
/// </summary>
|
||||
public static string ConnectionServiceConnStringInvalidIntent {
|
||||
get {
|
||||
return ResourceManager.GetString("ConnectionServiceConnStringInvalidIntent", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to SpecifiedUri '{0}' does not have existing connection.
|
||||
/// </summary>
|
||||
public static string ConnectionServiceListDbErrorNotConnected {
|
||||
get {
|
||||
return ResourceManager.GetString("ConnectionServiceListDbErrorNotConnected", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to OwnerUri cannot be null or empty.
|
||||
/// </summary>
|
||||
public static string ConnectionServiceListDbErrorNullOwnerUri {
|
||||
get {
|
||||
return ResourceManager.GetString("ConnectionServiceListDbErrorNullOwnerUri", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Win32Credential object is already disposed.
|
||||
/// </summary>
|
||||
@@ -293,177 +104,6 @@ namespace Microsoft.SqlTools.Hosting.Localization {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to An error occurred while the batch was being processed. The error message is: {0}.
|
||||
/// </summary>
|
||||
public static string EE_BatchError_Exception {
|
||||
get {
|
||||
return ResourceManager.GetString("EE_BatchError_Exception", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to An error occurred while the batch was being executed..
|
||||
/// </summary>
|
||||
public static string EE_BatchExecutionError_Halting {
|
||||
get {
|
||||
return ResourceManager.GetString("EE_BatchExecutionError_Halting", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to An error occurred while the batch was being executed, but the error has been ignored..
|
||||
/// </summary>
|
||||
public static string EE_BatchExecutionError_Ignoring {
|
||||
get {
|
||||
return ResourceManager.GetString("EE_BatchExecutionError_Ignoring", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to ({0} row(s) affected).
|
||||
/// </summary>
|
||||
public static string EE_BatchExecutionInfo_RowsAffected {
|
||||
get {
|
||||
return ResourceManager.GetString("EE_BatchExecutionInfo_RowsAffected", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Msg {0}, Level {1}, State {2}.
|
||||
/// </summary>
|
||||
public static string EE_BatchSqlMessageNoLineInfo {
|
||||
get {
|
||||
return ResourceManager.GetString("EE_BatchSqlMessageNoLineInfo", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Msg {0}, Level {1}, State {2}, Line {3}.
|
||||
/// </summary>
|
||||
public static string EE_BatchSqlMessageNoProcedureInfo {
|
||||
get {
|
||||
return ResourceManager.GetString("EE_BatchSqlMessageNoProcedureInfo", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Msg {0}, Level {1}, State {2}, Procedure {3}, Line {4}.
|
||||
/// </summary>
|
||||
public static string EE_BatchSqlMessageWithProcedureInfo {
|
||||
get {
|
||||
return ResourceManager.GetString("EE_BatchSqlMessageWithProcedureInfo", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Command {0} is not supported..
|
||||
/// </summary>
|
||||
public static string EE_ExecutionError_CommandNotSupported {
|
||||
get {
|
||||
return ResourceManager.GetString("EE_ExecutionError_CommandNotSupported", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The variable {0} could not be found..
|
||||
/// </summary>
|
||||
public static string EE_ExecutionError_VariableNotFound {
|
||||
get {
|
||||
return ResourceManager.GetString("EE_ExecutionError_VariableNotFound", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Execution completed {0} times....
|
||||
/// </summary>
|
||||
public static string EE_ExecutionInfo_FinalizingLoop {
|
||||
get {
|
||||
return ResourceManager.GetString("EE_ExecutionInfo_FinalizingLoop", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Starting execution loop of {0} times....
|
||||
/// </summary>
|
||||
public static string EE_ExecutionInfo_InitilizingLoop {
|
||||
get {
|
||||
return ResourceManager.GetString("EE_ExecutionInfo_InitilizingLoop", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to You cancelled the query..
|
||||
/// </summary>
|
||||
public static string EE_ExecutionInfo_QueryCancelledbyUser {
|
||||
get {
|
||||
return ResourceManager.GetString("EE_ExecutionInfo_QueryCancelledbyUser", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The previous execution is not yet complete..
|
||||
/// </summary>
|
||||
public static string EE_ExecutionNotYetCompleteError {
|
||||
get {
|
||||
return ResourceManager.GetString("EE_ExecutionNotYetCompleteError", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to A scripting error occurred..
|
||||
/// </summary>
|
||||
public static string EE_ScriptError_Error {
|
||||
get {
|
||||
return ResourceManager.GetString("EE_ScriptError_Error", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to A fatal error occurred..
|
||||
/// </summary>
|
||||
public static string EE_ScriptError_FatalError {
|
||||
get {
|
||||
return ResourceManager.GetString("EE_ScriptError_FatalError", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Incorrect syntax was encountered while {0} was being parsed..
|
||||
/// </summary>
|
||||
public static string EE_ScriptError_ParsingSyntax {
|
||||
get {
|
||||
return ResourceManager.GetString("EE_ScriptError_ParsingSyntax", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Scripting warning..
|
||||
/// </summary>
|
||||
public static string EE_ScriptError_Warning {
|
||||
get {
|
||||
return ResourceManager.GetString("EE_ScriptError_Warning", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Replacement of an empty string by an empty string..
|
||||
/// </summary>
|
||||
public static string ErrorEmptyStringReplacement {
|
||||
get {
|
||||
return ResourceManager.GetString("ErrorEmptyStringReplacement", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Cannot convert SqlCodeObject Type {0} to Type {1}.
|
||||
/// </summary>
|
||||
public static string ErrorUnexpectedCodeObjectType {
|
||||
get {
|
||||
return ResourceManager.GetString("ErrorUnexpectedCodeObjectType", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Message header must separate key and value using ':'.
|
||||
/// </summary>
|
||||
@@ -518,357 +158,6 @@ namespace Microsoft.SqlTools.Hosting.Localization {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to This feature is currently not supported on Azure SQL DB and Data Warehouse: {0}.
|
||||
/// </summary>
|
||||
public static string PeekDefinitionAzureError {
|
||||
get {
|
||||
return ResourceManager.GetString("PeekDefinitionAzureError", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to No database object was retrieved..
|
||||
/// </summary>
|
||||
public static string PeekDefinitionDatabaseError {
|
||||
get {
|
||||
return ResourceManager.GetString("PeekDefinitionDatabaseError", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to An unexpected error occurred during Peek Definition execution: {0}.
|
||||
/// </summary>
|
||||
public static string PeekDefinitionError {
|
||||
get {
|
||||
return ResourceManager.GetString("PeekDefinitionError", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to No results were found..
|
||||
/// </summary>
|
||||
public static string PeekDefinitionNoResultsError {
|
||||
get {
|
||||
return ResourceManager.GetString("PeekDefinitionNoResultsError", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Please connect to a server..
|
||||
/// </summary>
|
||||
public static string PeekDefinitionNotConnectedError {
|
||||
get {
|
||||
return ResourceManager.GetString("PeekDefinitionNotConnectedError", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Operation timed out..
|
||||
/// </summary>
|
||||
public static string PeekDefinitionTimedoutError {
|
||||
get {
|
||||
return ResourceManager.GetString("PeekDefinitionTimedoutError", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to This object type is currently not supported by this feature..
|
||||
/// </summary>
|
||||
public static string PeekDefinitionTypeNotSupportedError {
|
||||
get {
|
||||
return ResourceManager.GetString("PeekDefinitionTypeNotSupportedError", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to (1 row affected).
|
||||
/// </summary>
|
||||
public static string QueryServiceAffectedOneRow {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceAffectedOneRow", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to ({0} rows affected).
|
||||
/// </summary>
|
||||
public static string QueryServiceAffectedRows {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceAffectedRows", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The query has already completed, it cannot be cancelled.
|
||||
/// </summary>
|
||||
public static string QueryServiceCancelAlreadyCompleted {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceCancelAlreadyCompleted", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Query successfully cancelled, failed to dispose query. Owner URI not found..
|
||||
/// </summary>
|
||||
public static string QueryServiceCancelDisposeFailed {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceCancelDisposeFailed", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to (No column name).
|
||||
/// </summary>
|
||||
public static string QueryServiceColumnNull {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceColumnNull", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Commands completed successfully..
|
||||
/// </summary>
|
||||
public static string QueryServiceCompletedSuccessfully {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceCompletedSuccessfully", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Maximum number of bytes to return must be greater than zero.
|
||||
/// </summary>
|
||||
public static string QueryServiceDataReaderByteCountInvalid {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceDataReaderByteCountInvalid", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Maximum number of chars to return must be greater than zero.
|
||||
/// </summary>
|
||||
public static string QueryServiceDataReaderCharCountInvalid {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceDataReaderCharCountInvalid", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Maximum number of XML bytes to return must be greater than zero.
|
||||
/// </summary>
|
||||
public static string QueryServiceDataReaderXmlCountInvalid {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceDataReaderXmlCountInvalid", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Msg {0}, Level {1}, State {2}, Line {3}{4}{5}.
|
||||
/// </summary>
|
||||
public static string QueryServiceErrorFormat {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceErrorFormat", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Could not retrieve an execution plan from the result set .
|
||||
/// </summary>
|
||||
public static string QueryServiceExecutionPlanNotFound {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceExecutionPlanNotFound", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to FileStreamWrapper must be initialized before performing operations.
|
||||
/// </summary>
|
||||
public static string QueryServiceFileWrapperNotInitialized {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceFileWrapperNotInitialized", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to This FileStreamWrapper cannot be used for writing.
|
||||
/// </summary>
|
||||
public static string QueryServiceFileWrapperReadOnly {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceFileWrapperReadOnly", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Access method cannot be write-only.
|
||||
/// </summary>
|
||||
public static string QueryServiceFileWrapperWriteOnly {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceFileWrapperWriteOnly", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Sender for OnInfoMessage event must be a SqlConnection.
|
||||
/// </summary>
|
||||
public static string QueryServiceMessageSenderNotSql {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceMessageSenderNotSql", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Query was canceled by user.
|
||||
/// </summary>
|
||||
public static string QueryServiceQueryCancelled {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceQueryCancelled", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Query failed: {0}.
|
||||
/// </summary>
|
||||
public static string QueryServiceQueryFailed {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceQueryFailed", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to A query is already in progress for this editor session. Please cancel this query or wait for its completion..
|
||||
/// </summary>
|
||||
public static string QueryServiceQueryInProgress {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceQueryInProgress", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to This editor is not connected to a database.
|
||||
/// </summary>
|
||||
public static string QueryServiceQueryInvalidOwnerUri {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceQueryInvalidOwnerUri", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The requested query does not exist.
|
||||
/// </summary>
|
||||
public static string QueryServiceRequestsNoQuery {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceRequestsNoQuery", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Could not retrieve column schema for result set.
|
||||
/// </summary>
|
||||
public static string QueryServiceResultSetNoColumnSchema {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceResultSetNoColumnSchema", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Cannot read subset unless the results have been read from the server.
|
||||
/// </summary>
|
||||
public static string QueryServiceResultSetNotRead {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceResultSetNotRead", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Reader cannot be null.
|
||||
/// </summary>
|
||||
public static string QueryServiceResultSetReaderNull {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceResultSetReaderNull", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Row count must be a positive integer.
|
||||
/// </summary>
|
||||
public static string QueryServiceResultSetRowCountOutOfRange {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceResultSetRowCountOutOfRange", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Start row cannot be less than 0 or greater than the number of rows in the result set.
|
||||
/// </summary>
|
||||
public static string QueryServiceResultSetStartRowOutOfRange {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceResultSetStartRowOutOfRange", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Failed to save {0}: {1}.
|
||||
/// </summary>
|
||||
public static string QueryServiceSaveAsFail {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceSaveAsFail", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to A save request to the same path is in progress.
|
||||
/// </summary>
|
||||
public static string QueryServiceSaveAsInProgress {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceSaveAsInProgress", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Internal error occurred while starting save task.
|
||||
/// </summary>
|
||||
public static string QueryServiceSaveAsMiscStartingError {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceSaveAsMiscStartingError", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Result cannot be saved until query execution has completed.
|
||||
/// </summary>
|
||||
public static string QueryServiceSaveAsResultSetNotComplete {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceSaveAsResultSetNotComplete", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The batch has not completed, yet.
|
||||
/// </summary>
|
||||
public static string QueryServiceSubsetBatchNotCompleted {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceSubsetBatchNotCompleted", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Batch index cannot be less than 0 or greater than the number of batches.
|
||||
/// </summary>
|
||||
public static string QueryServiceSubsetBatchOutOfRange {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceSubsetBatchOutOfRange", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Result set index cannot be less than 0 or greater than the number of result sets.
|
||||
/// </summary>
|
||||
public static string QueryServiceSubsetResultSetOutOfRange {
|
||||
get {
|
||||
return ResourceManager.GetString("QueryServiceSubsetResultSetOutOfRange", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Cannot register service for type {0}, one or more services already registered.
|
||||
/// </summary>
|
||||
@@ -904,50 +193,5 @@ namespace Microsoft.SqlTools.Hosting.Localization {
|
||||
return ResourceManager.GetString("ServiceProviderNotSet", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to EN_LOCALIZATION.
|
||||
/// </summary>
|
||||
public static string TestLocalizationConstant {
|
||||
get {
|
||||
return ResourceManager.GetString("TestLocalizationConstant", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to For more information about this error, see the troubleshooting topics in the product documentation..
|
||||
/// </summary>
|
||||
public static string TroubleshootingAssistanceMessage {
|
||||
get {
|
||||
return ResourceManager.GetString("TroubleshootingAssistanceMessage", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Start position ({0}, {1}) must come before or be equal to the end position ({2}, {3}).
|
||||
/// </summary>
|
||||
public static string WorkspaceServiceBufferPositionOutOfOrder {
|
||||
get {
|
||||
return ResourceManager.GetString("WorkspaceServiceBufferPositionOutOfOrder", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Position is outside of column range for line {0}.
|
||||
/// </summary>
|
||||
public static string WorkspaceServicePositionColumnOutOfRange {
|
||||
get {
|
||||
return ResourceManager.GetString("WorkspaceServicePositionColumnOutOfRange", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Position is outside of file line range.
|
||||
/// </summary>
|
||||
public static string WorkspaceServicePositionLineOutOfRange {
|
||||
get {
|
||||
return ResourceManager.GetString("WorkspaceServicePositionLineOutOfRange", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace Microsoft.SqlTools.Hosting
|
||||
Keys.Culture = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static string CredentialsServiceInvalidCriticalHandle
|
||||
{
|
||||
@@ -35,7 +35,7 @@ namespace Microsoft.SqlTools.Hosting
|
||||
{
|
||||
return Keys.GetString(Keys.CredentialsServiceInvalidCriticalHandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static string CredentialsServicePasswordLengthExceeded
|
||||
{
|
||||
@@ -43,7 +43,7 @@ namespace Microsoft.SqlTools.Hosting
|
||||
{
|
||||
return Keys.GetString(Keys.CredentialsServicePasswordLengthExceeded);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static string CredentialsServiceTargetForDelete
|
||||
{
|
||||
@@ -51,7 +51,7 @@ namespace Microsoft.SqlTools.Hosting
|
||||
{
|
||||
return Keys.GetString(Keys.CredentialsServiceTargetForDelete);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static string CredentialsServiceTargetForLookup
|
||||
{
|
||||
@@ -59,7 +59,7 @@ namespace Microsoft.SqlTools.Hosting
|
||||
{
|
||||
return Keys.GetString(Keys.CredentialsServiceTargetForLookup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static string CredentialServiceWin32CredentialDisposed
|
||||
{
|
||||
@@ -67,7 +67,7 @@ namespace Microsoft.SqlTools.Hosting
|
||||
{
|
||||
return Keys.GetString(Keys.CredentialServiceWin32CredentialDisposed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static string ServiceAlreadyRegistered
|
||||
{
|
||||
@@ -75,7 +75,7 @@ namespace Microsoft.SqlTools.Hosting
|
||||
{
|
||||
return Keys.GetString(Keys.ServiceAlreadyRegistered);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static string MultipleServicesFound
|
||||
{
|
||||
@@ -83,7 +83,7 @@ namespace Microsoft.SqlTools.Hosting
|
||||
{
|
||||
return Keys.GetString(Keys.MultipleServicesFound);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static string IncompatibleServiceForExtensionLoader
|
||||
{
|
||||
@@ -91,7 +91,7 @@ namespace Microsoft.SqlTools.Hosting
|
||||
{
|
||||
return Keys.GetString(Keys.IncompatibleServiceForExtensionLoader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static string ServiceProviderNotSet
|
||||
{
|
||||
@@ -99,7 +99,7 @@ namespace Microsoft.SqlTools.Hosting
|
||||
{
|
||||
return Keys.GetString(Keys.ServiceProviderNotSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static string ServiceNotFound
|
||||
{
|
||||
@@ -107,7 +107,7 @@ namespace Microsoft.SqlTools.Hosting
|
||||
{
|
||||
return Keys.GetString(Keys.ServiceNotFound);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static string ServiceNotOfExpectedType
|
||||
{
|
||||
@@ -115,7 +115,7 @@ namespace Microsoft.SqlTools.Hosting
|
||||
{
|
||||
return Keys.GetString(Keys.ServiceNotOfExpectedType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static string HostingUnexpectedEndOfStream
|
||||
{
|
||||
@@ -123,7 +123,7 @@ namespace Microsoft.SqlTools.Hosting
|
||||
{
|
||||
return Keys.GetString(Keys.HostingUnexpectedEndOfStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static string HostingHeaderMissingColon
|
||||
{
|
||||
@@ -131,7 +131,7 @@ namespace Microsoft.SqlTools.Hosting
|
||||
{
|
||||
return Keys.GetString(Keys.HostingHeaderMissingColon);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static string HostingHeaderMissingContentLengthHeader
|
||||
{
|
||||
@@ -139,7 +139,7 @@ namespace Microsoft.SqlTools.Hosting
|
||||
{
|
||||
return Keys.GetString(Keys.HostingHeaderMissingContentLengthHeader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static string HostingHeaderMissingContentLengthValue
|
||||
{
|
||||
@@ -147,7 +147,7 @@ namespace Microsoft.SqlTools.Hosting
|
||||
{
|
||||
return Keys.GetString(Keys.HostingHeaderMissingContentLengthValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
public class Keys
|
||||
@@ -155,52 +155,52 @@ namespace Microsoft.SqlTools.Hosting
|
||||
static ResourceManager resourceManager = new ResourceManager("Microsoft.SqlTools.Hosting.Localization.SR", typeof(SR).GetTypeInfo().Assembly);
|
||||
|
||||
static CultureInfo _culture = null;
|
||||
|
||||
|
||||
public const string CredentialsServiceInvalidCriticalHandle = "CredentialsServiceInvalidCriticalHandle";
|
||||
|
||||
|
||||
public const string CredentialsServicePasswordLengthExceeded = "CredentialsServicePasswordLengthExceeded";
|
||||
|
||||
|
||||
public const string CredentialsServiceTargetForDelete = "CredentialsServiceTargetForDelete";
|
||||
|
||||
|
||||
public const string CredentialsServiceTargetForLookup = "CredentialsServiceTargetForLookup";
|
||||
|
||||
|
||||
public const string CredentialServiceWin32CredentialDisposed = "CredentialServiceWin32CredentialDisposed";
|
||||
|
||||
|
||||
public const string ServiceAlreadyRegistered = "ServiceAlreadyRegistered";
|
||||
|
||||
|
||||
public const string MultipleServicesFound = "MultipleServicesFound";
|
||||
|
||||
|
||||
public const string IncompatibleServiceForExtensionLoader = "IncompatibleServiceForExtensionLoader";
|
||||
|
||||
|
||||
public const string ServiceProviderNotSet = "ServiceProviderNotSet";
|
||||
|
||||
|
||||
public const string ServiceNotFound = "ServiceNotFound";
|
||||
|
||||
|
||||
public const string ServiceNotOfExpectedType = "ServiceNotOfExpectedType";
|
||||
|
||||
|
||||
public const string HostingUnexpectedEndOfStream = "HostingUnexpectedEndOfStream";
|
||||
|
||||
|
||||
public const string HostingHeaderMissingColon = "HostingHeaderMissingColon";
|
||||
|
||||
|
||||
public const string HostingHeaderMissingContentLengthHeader = "HostingHeaderMissingContentLengthHeader";
|
||||
|
||||
|
||||
public const string HostingHeaderMissingContentLengthValue = "HostingHeaderMissingContentLengthValue";
|
||||
|
||||
|
||||
|
||||
public const string CredentialsServiceInvalidCriticalHandle = "CredentialsServiceInvalidCriticalHandle";
|
||||
|
||||
|
||||
public const string CredentialsServicePasswordLengthExceeded = "CredentialsServicePasswordLengthExceeded";
|
||||
|
||||
|
||||
public const string CredentialsServiceTargetForDelete = "CredentialsServiceTargetForDelete";
|
||||
|
||||
|
||||
public const string CredentialsServiceTargetForLookup = "CredentialsServiceTargetForLookup";
|
||||
|
||||
|
||||
public const string CredentialServiceWin32CredentialDisposed = "CredentialServiceWin32CredentialDisposed";
|
||||
|
||||
|
||||
public const string ServiceAlreadyRegistered = "ServiceAlreadyRegistered";
|
||||
|
||||
|
||||
public const string MultipleServicesFound = "MultipleServicesFound";
|
||||
|
||||
|
||||
public const string IncompatibleServiceForExtensionLoader = "IncompatibleServiceForExtensionLoader";
|
||||
|
||||
|
||||
public const string ServiceProviderNotSet = "ServiceProviderNotSet";
|
||||
|
||||
|
||||
public const string ServiceNotFound = "ServiceNotFound";
|
||||
|
||||
|
||||
public const string ServiceNotOfExpectedType = "ServiceNotOfExpectedType";
|
||||
|
||||
|
||||
public const string HostingUnexpectedEndOfStream = "HostingUnexpectedEndOfStream";
|
||||
|
||||
|
||||
public const string HostingHeaderMissingColon = "HostingHeaderMissingColon";
|
||||
|
||||
|
||||
public const string HostingHeaderMissingContentLengthHeader = "HostingHeaderMissingContentLengthHeader";
|
||||
|
||||
|
||||
public const string HostingHeaderMissingContentLengthValue = "HostingHeaderMissingContentLengthValue";
|
||||
|
||||
|
||||
private Keys()
|
||||
{ }
|
||||
@@ -221,7 +221,7 @@ namespace Microsoft.SqlTools.Hosting
|
||||
{
|
||||
return resourceManager.GetString(key, _culture);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,96 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
@@ -27,5 +105,19 @@
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype"><value>text/microsoft-resx</value></resheader><resheader name="version"><value>1.3</value></resheader><resheader name="reader"><value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value></resheader><resheader name="writer"><value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value></resheader><data name="TestLocalizationConstant"><value>ES_LOCALIZATION</value></data>
|
||||
</root>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="TestLocalizationConstant" xml:space="preserve">
|
||||
<value>ES_LOCALIZATION</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -120,61 +120,61 @@
|
||||
<data name="CredentialsServiceInvalidCriticalHandle" xml:space="preserve">
|
||||
<value>Invalid CriticalHandle!</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="CredentialsServicePasswordLengthExceeded" xml:space="preserve">
|
||||
<value>The password has exceeded 512 bytes</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="CredentialsServiceTargetForDelete" xml:space="preserve">
|
||||
<value>Target must be specified to delete a credential</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="CredentialsServiceTargetForLookup" xml:space="preserve">
|
||||
<value>Target must be specified to check existance of a credential</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="CredentialServiceWin32CredentialDisposed" xml:space="preserve">
|
||||
<value>Win32Credential object is already disposed</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="ServiceAlreadyRegistered" xml:space="preserve">
|
||||
<value>Cannot register service for type {0}, one or more services already registered</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="MultipleServicesFound" xml:space="preserve">
|
||||
<value>Multiple services found for type {0}, expected only 1</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="IncompatibleServiceForExtensionLoader" xml:space="preserve">
|
||||
<value>Service of type {0} cannot be created by ExtensionLoader<{1}></value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="ServiceProviderNotSet" xml:space="preserve">
|
||||
<value>SetServiceProvider() was not called to establish the required service provider</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="ServiceNotFound" xml:space="preserve">
|
||||
<value>Service {0} was not found in the service provider</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="ServiceNotOfExpectedType" xml:space="preserve">
|
||||
<value>Service of Type {0} is not compatible with registered Type {1}</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="HostingUnexpectedEndOfStream" xml:space="preserve">
|
||||
<value>MessageReader's input stream ended unexpectedly, terminating</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="HostingHeaderMissingColon" xml:space="preserve">
|
||||
<value>Message header must separate key and value using ':'</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="HostingHeaderMissingContentLengthHeader" xml:space="preserve">
|
||||
<value>Fatal error: Content-Length header must be provided</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="HostingHeaderMissingContentLengthValue" xml:space="preserve">
|
||||
<value>Fatal error: Content-Length value is not an integer</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</root>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -51,6 +51,11 @@ namespace Microsoft.SqlTools.Utility
|
||||
{
|
||||
return GetItem(index);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
SetItem(index, value);
|
||||
}
|
||||
}
|
||||
|
||||
public int ExpandListSize
|
||||
@@ -137,6 +142,30 @@ namespace Microsoft.SqlTools.Utility
|
||||
return val;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the item at the specified index
|
||||
/// </summary>
|
||||
/// <param name="index">Index of the item to set</param>
|
||||
/// <param name="value">The item to store at the index specified</param>
|
||||
public void SetItem(long index, T value)
|
||||
{
|
||||
Validate.IsLessThan(nameof(index), index, Count);
|
||||
|
||||
if (Count <= this.ExpandListSize)
|
||||
{
|
||||
int i32Index = Convert.ToInt32(index);
|
||||
shortList[i32Index] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
int iArray32Index = (int) (Count / this.ExpandListSize);
|
||||
List<T> arr = expandedList[iArray32Index];
|
||||
|
||||
int i32Index = (int)(Count % this.ExpandListSize);
|
||||
arr[i32Index] = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes an item at the specified location and shifts all the items after the provided
|
||||
/// index up by one.
|
||||
|
||||
@@ -64,8 +64,8 @@ namespace Microsoft.SqlTools.Utility
|
||||
/// <param name="upperLimit">The upper limit which the value should be less than.</param>
|
||||
public static void IsLessThan(
|
||||
string parameterName,
|
||||
int valueToCheck,
|
||||
int upperLimit)
|
||||
long valueToCheck,
|
||||
long upperLimit)
|
||||
{
|
||||
if (valueToCheck >= upperLimit)
|
||||
{
|
||||
@@ -87,8 +87,8 @@ namespace Microsoft.SqlTools.Utility
|
||||
/// <param name="lowerLimit">The lower limit which the value should be greater than.</param>
|
||||
public static void IsGreaterThan(
|
||||
string parameterName,
|
||||
int valueToCheck,
|
||||
int lowerLimit)
|
||||
long valueToCheck,
|
||||
long lowerLimit)
|
||||
{
|
||||
if (valueToCheck < lowerLimit)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
//
|
||||
// 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.Hosting.Protocol.Contracts;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.EditData.Contracts
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameters for a request to commit pending edit operations
|
||||
/// </summary>
|
||||
public class EditCommitParams : SessionOperationParams
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parameters to return upon successful completion of commiting pending edit operations
|
||||
/// </summary>
|
||||
public class EditCommitResult
|
||||
{
|
||||
}
|
||||
|
||||
public class EditCommitRequest
|
||||
{
|
||||
public static readonly
|
||||
RequestType<EditCommitParams, EditCommitResult> Type =
|
||||
RequestType<EditCommitParams, EditCommitResult>.Create("edit/commit");
|
||||
}
|
||||
}
|
||||
@@ -54,8 +54,8 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
||||
|
||||
private readonly QueryExecutionService queryExecutionService;
|
||||
|
||||
private readonly Lazy<ConcurrentDictionary<string, Session>> editSessions = new Lazy<ConcurrentDictionary<string, Session>>(
|
||||
() => new ConcurrentDictionary<string, Session>());
|
||||
private readonly Lazy<ConcurrentDictionary<string, EditSession>> editSessions = new Lazy<ConcurrentDictionary<string, EditSession>>(
|
||||
() => new ConcurrentDictionary<string, EditSession>());
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -64,7 +64,7 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
||||
/// <summary>
|
||||
/// Dictionary mapping OwnerURIs to active sessions
|
||||
/// </summary>
|
||||
internal ConcurrentDictionary<string, Session> ActiveSessions => editSessions.Value;
|
||||
internal ConcurrentDictionary<string, EditSession> ActiveSessions => editSessions.Value;
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -86,14 +86,14 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
||||
#region Request Handlers
|
||||
|
||||
internal async Task HandleSessionRequest<TResult>(SessionOperationParams sessionParams,
|
||||
RequestContext<TResult> requestContext, Func<Session, TResult> sessionOperation)
|
||||
RequestContext<TResult> requestContext, Func<EditSession, TResult> sessionOperation)
|
||||
{
|
||||
try
|
||||
{
|
||||
Session session = GetActiveSessionOrThrow(sessionParams.OwnerUri);
|
||||
EditSession editSession = GetActiveSessionOrThrow(sessionParams.OwnerUri);
|
||||
|
||||
// Get the result from execution of the session operation
|
||||
TResult result = sessionOperation(session);
|
||||
// Get the result from execution of the editSession operation
|
||||
TResult result = sessionOperation(editSession);
|
||||
await requestContext.SendResult(result);
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -135,9 +135,9 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
||||
// Sanity check the owner URI
|
||||
Validate.IsNotNullOrWhitespaceString(nameof(disposeParams.OwnerUri), disposeParams.OwnerUri);
|
||||
|
||||
// Attempt to remove the session
|
||||
Session session;
|
||||
if (!ActiveSessions.TryRemove(disposeParams.OwnerUri, out session))
|
||||
// Attempt to remove the editSession
|
||||
EditSession editSession;
|
||||
if (!ActiveSessions.TryRemove(disposeParams.OwnerUri, out editSession))
|
||||
{
|
||||
await requestContext.SendError(SR.EditDataSessionNotFound);
|
||||
return;
|
||||
@@ -219,6 +219,31 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
||||
session => session.UpdateCell(updateParams.RowId, updateParams.ColumnId, updateParams.NewValue));
|
||||
}
|
||||
|
||||
internal async Task HandleCommitRequest(EditCommitParams commitParams,
|
||||
RequestContext<EditCommitResult> requestContext)
|
||||
{
|
||||
// Setup a callback for if the edits have been successfully written to the db
|
||||
Func<Task> successHandler = () => requestContext.SendResult(new EditCommitResult());
|
||||
|
||||
// Setup a callback for if the edits failed to be written to db
|
||||
Func<Exception, Task> failureHandler = e => requestContext.SendError(e.Message);
|
||||
|
||||
try
|
||||
{
|
||||
// Get the editSession
|
||||
EditSession editSession = GetActiveSessionOrThrow(commitParams.OwnerUri);
|
||||
|
||||
// Get a connection for doing the committing
|
||||
DbConnection conn = await connectionService.GetOrOpenConnection(commitParams.OwnerUri,
|
||||
ConnectionType.Edit);
|
||||
editSession.CommitEdits(conn, successHandler, failureHandler);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
await failureHandler(e);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Helpers
|
||||
@@ -229,19 +254,19 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
||||
/// <exception cref="Exception">If the edit session doesn't exist</exception>
|
||||
/// <param name="ownerUri">Owner URI for the edit session</param>
|
||||
/// <returns>The edit session that corresponds to the owner URI</returns>
|
||||
private Session GetActiveSessionOrThrow(string ownerUri)
|
||||
private EditSession GetActiveSessionOrThrow(string ownerUri)
|
||||
{
|
||||
// Sanity check the owner URI is provided
|
||||
Validate.IsNotNullOrWhitespaceString(nameof(ownerUri), ownerUri);
|
||||
|
||||
// Attempt to get the session, throw if unable
|
||||
Session session;
|
||||
if (!ActiveSessions.TryGetValue(ownerUri, out session))
|
||||
// Attempt to get the editSession, throw if unable
|
||||
EditSession editSession;
|
||||
if (!ActiveSessions.TryGetValue(ownerUri, out editSession))
|
||||
{
|
||||
throw new Exception(SR.EditDataSessionNotFound);
|
||||
}
|
||||
|
||||
return session;
|
||||
return editSession;
|
||||
}
|
||||
|
||||
private async Task QueryCompleteCallback(Query query, EditInitializeParams initParams,
|
||||
@@ -254,19 +279,19 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
||||
|
||||
try
|
||||
{
|
||||
// Validate the query for a session
|
||||
ResultSet resultSet = Session.ValidateQueryForSession(query);
|
||||
// Validate the query for a editSession
|
||||
ResultSet resultSet = EditSession.ValidateQueryForSession(query);
|
||||
|
||||
// Get a connection we'll use for SMO metadata lookup (and committing, later on)
|
||||
DbConnection conn = await connectionService.GetOrOpenConnection(initParams.OwnerUri, ConnectionType.Edit);
|
||||
var metadata = metadataFactory.GetObjectMetadata(conn, resultSet.Columns,
|
||||
initParams.ObjectName, initParams.ObjectType);
|
||||
|
||||
// Create the session and add it to the sessions list
|
||||
Session session = new Session(resultSet, metadata);
|
||||
if (!ActiveSessions.TryAdd(initParams.OwnerUri, session))
|
||||
// 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 session, session already exists.");
|
||||
throw new InvalidOperationException("Failed to create edit editSession, editSession already exists.");
|
||||
}
|
||||
readyParams.Success = true;
|
||||
}
|
||||
|
||||
@@ -5,8 +5,10 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Data.Common;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SqlTools.ServiceLayer.EditData.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement;
|
||||
using Microsoft.SqlTools.ServiceLayer.QueryExecution;
|
||||
@@ -18,22 +20,18 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
||||
/// Represents an edit "session" bound to the results of a query, containing a cache of edits
|
||||
/// that are pending. Provides logic for performing edit operations.
|
||||
/// </summary>
|
||||
public class Session
|
||||
public class EditSession
|
||||
{
|
||||
|
||||
#region Member Variables
|
||||
|
||||
private readonly ResultSet associatedResultSet;
|
||||
private readonly IEditTableMetadata objectMetadata;
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new edit session bound to the result set and metadat object provided
|
||||
/// </summary>
|
||||
/// <param name="resultSet">The result set of the table to be edited</param>
|
||||
/// <param name="objMetadata">Metadata provider for the table to be edited</param>
|
||||
public Session(ResultSet resultSet, IEditTableMetadata objMetadata)
|
||||
public EditSession(ResultSet resultSet, IEditTableMetadata objMetadata)
|
||||
{
|
||||
Validate.IsNotNull(nameof(resultSet), resultSet);
|
||||
Validate.IsNotNull(nameof(objMetadata), objMetadata);
|
||||
@@ -47,6 +45,12 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// The task that is running to commit the changes to the db
|
||||
/// Internal for unit test purposes.
|
||||
/// </summary>
|
||||
internal Task CommitTask { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The internal ID for the next row in the table. Internal for unit testing purposes only.
|
||||
/// </summary>
|
||||
@@ -55,7 +59,7 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
||||
/// <summary>
|
||||
/// The cache of pending updates. Internal for unit test purposes only
|
||||
/// </summary>
|
||||
internal ConcurrentDictionary<long, RowEditBase> EditCache { get;}
|
||||
internal ConcurrentDictionary<long, RowEditBase> EditCache { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -109,6 +113,29 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
||||
return newRowId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Commits the edits in the cache to the database and then to the associated result set of
|
||||
/// this edit session. This is launched asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="connection">The connection to use for executing the query</param>
|
||||
/// <param name="successHandler">Callback to perform when the commit process has finished</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)
|
||||
{
|
||||
Validate.IsNotNull(nameof(connection), connection);
|
||||
Validate.IsNotNull(nameof(successHandler), successHandler);
|
||||
Validate.IsNotNull(nameof(errorHandler), errorHandler);
|
||||
|
||||
// Make sure that there isn't a commit task in progress
|
||||
if (CommitTask != null && !CommitTask.IsCompleted)
|
||||
{
|
||||
throw new InvalidOperationException(SR.EditDataCommitInProgress);
|
||||
}
|
||||
|
||||
// Start up the commit process
|
||||
CommitTask = CommitEditsInternal(connection, successHandler, errorHandler);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a delete row update and adds it to the update cache
|
||||
/// </summary>
|
||||
@@ -149,6 +176,11 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates a single script file with all the pending edits scripted.
|
||||
/// </summary>
|
||||
/// <param name="outputPath">The path to output the script to</param>
|
||||
/// <returns></returns>
|
||||
public string ScriptEdits(string outputPath)
|
||||
{
|
||||
// Validate the output path
|
||||
@@ -203,7 +235,10 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
||||
|
||||
// Attempt to get the row that is being edited, create a new update object if one
|
||||
// doesn't exist
|
||||
RowEditBase editRow = EditCache.GetOrAdd(rowId, new RowUpdate(rowId, associatedResultSet, objectMetadata));
|
||||
// NOTE: This *must* be done as a lambda. RowUpdate creation requires that the row
|
||||
// exist in the result set. We only want a new RowUpdate to be created if the edit
|
||||
// doesn't already exist in the cache
|
||||
RowEditBase editRow = EditCache.GetOrAdd(rowId, key => new RowUpdate(rowId, associatedResultSet, objectMetadata));
|
||||
|
||||
// Pass the call to the row update
|
||||
return editRow.SetCell(columnId, newValue);
|
||||
@@ -211,5 +246,36 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
|
||||
|
||||
#endregion
|
||||
|
||||
private async Task CommitEditsInternal(DbConnection connection, Func<Task> successHandler, Func<Exception, Task> errorHandler)
|
||||
{
|
||||
try
|
||||
{
|
||||
// @TODO: Add support for transactional commits
|
||||
|
||||
// Trust the RowEdit to sort itself appropriately
|
||||
var editOperations = EditCache.Values.ToList();
|
||||
editOperations.Sort();
|
||||
foreach (var editOperation in editOperations)
|
||||
{
|
||||
// Get the command from the edit operation and execute it
|
||||
using (DbCommand editCommand = editOperation.GetCommand(connection))
|
||||
using (DbDataReader reader = await editCommand.ExecuteReaderAsync())
|
||||
{
|
||||
// Apply the changes of the command to the result set
|
||||
await editOperation.ApplyChanges(reader);
|
||||
}
|
||||
|
||||
// If we succeeded in applying the changes, then remove this from the cache
|
||||
// @TODO: Prevent edit sessions from being modified while a commit is in progress
|
||||
RowEditBase re;
|
||||
EditCache.TryRemove(editOperation.RowId, out re);
|
||||
}
|
||||
await successHandler();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
await errorHandler(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,9 +4,9 @@
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Data.Common;
|
||||
using System.Globalization;
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts;
|
||||
using Microsoft.SqlTools.Utility;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
|
||||
@@ -26,7 +26,7 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
|
||||
/// </summary>
|
||||
/// <param name="column">Column the cell will be under</param>
|
||||
/// <param name="valueAsString">The string from the client to convert to an object</param>
|
||||
public CellUpdate(DbColumn column, string valueAsString)
|
||||
public CellUpdate(DbColumnWrapper column, string valueAsString)
|
||||
{
|
||||
Validate.IsNotNull(nameof(column), column);
|
||||
Validate.IsNotNull(nameof(valueAsString), valueAsString);
|
||||
@@ -89,7 +89,7 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
|
||||
/// <summary>
|
||||
/// The column that the cell will be placed in
|
||||
/// </summary>
|
||||
public DbColumn Column { get; }
|
||||
public DbColumnWrapper Column { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The object representation of the cell provided by the client
|
||||
|
||||
@@ -5,10 +5,16 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Data.Common;
|
||||
using System.Data.SqlClient;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SqlTools.ServiceLayer.EditData.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.QueryExecution;
|
||||
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.Utility;
|
||||
using Microsoft.SqlTools.Utility;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
|
||||
{
|
||||
@@ -17,7 +23,9 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
|
||||
/// </summary>
|
||||
public sealed class RowCreate : RowEditBase
|
||||
{
|
||||
private const string InsertStatement = "INSERT INTO {0}({1}) VALUES ({2})";
|
||||
private const string InsertStart = "INSERT INTO {0}({1})";
|
||||
private const string InsertCompleteScript = "{0} VALUES ({1})";
|
||||
private const string InsertCompleteOutput = "{0} OUTPUT {1} VALUES ({2})";
|
||||
|
||||
private readonly CellUpdate[] newCells;
|
||||
|
||||
@@ -34,42 +42,121 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates the INSERT INTO statement that will apply the row creation
|
||||
/// Sort ID for a RowCreate object. Setting to 1 ensures that these are the first changes
|
||||
/// to be committed
|
||||
/// </summary>
|
||||
/// <returns>INSERT INTO statement</returns>
|
||||
public override string GetScript()
|
||||
{
|
||||
List<string> columnNames = new List<string>();
|
||||
List<string> columnValues = new List<string>();
|
||||
protected override int SortId => 1;
|
||||
|
||||
// Build the column list and value list
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Applies the changes to the associated result set after successfully executing the
|
||||
/// change on the database
|
||||
/// </summary>
|
||||
/// <param name="dataReader">
|
||||
/// Reader returned from the execution of the command to insert a new row. Should contain
|
||||
/// a single row that represents the newly added row.
|
||||
/// </param>
|
||||
public override Task ApplyChanges(DbDataReader dataReader)
|
||||
{
|
||||
Validate.IsNotNull(nameof(dataReader), dataReader);
|
||||
|
||||
return AssociatedResultSet.AddRow(dataReader);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates a command that can be executed to insert a new row -- and return the newly
|
||||
/// inserted row.
|
||||
/// </summary>
|
||||
/// <param name="connection">The connection the command should be associated with</param>
|
||||
/// <returns>Command to insert the new row</returns>
|
||||
public override DbCommand GetCommand(DbConnection connection)
|
||||
{
|
||||
Validate.IsNotNull(nameof(connection), connection);
|
||||
|
||||
// Process all the columns. Add the column to the output columns, add updateable
|
||||
// columns to the input parameters
|
||||
List<string> outColumns = new List<string>();
|
||||
List<string> inColumns = new List<string>();
|
||||
DbCommand command = connection.CreateCommand();
|
||||
for (int i = 0; i < AssociatedResultSet.Columns.Length; i++)
|
||||
{
|
||||
DbColumnWrapper column = AssociatedResultSet.Columns[i];
|
||||
CellUpdate cell = newCells[i];
|
||||
|
||||
// If the column is not updatable, then skip it
|
||||
// Add the column to the output
|
||||
outColumns.Add($"inserted.{SqlScriptFormatter.FormatIdentifier(column.ColumnName)}");
|
||||
|
||||
// Skip columns that cannot be updated
|
||||
if (!column.IsUpdatable)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the cell doesn't have a value, but is updatable, don't try to create the script
|
||||
// If we're missing a cell, then we cannot continue
|
||||
if (cell == null)
|
||||
{
|
||||
throw new InvalidOperationException(SR.EditDataCreateScriptMissingValue);
|
||||
}
|
||||
|
||||
// Add the column and the data to their respective lists
|
||||
columnNames.Add(SqlScriptFormatter.FormatIdentifier(column.ColumnName));
|
||||
columnValues.Add(SqlScriptFormatter.FormatValue(cell.Value, column));
|
||||
// Create a parameter for the value and add it to the command
|
||||
// Add the parameterization to the list and add it to the command
|
||||
string paramName = $"@Value{RowId}{i}";
|
||||
inColumns.Add(paramName);
|
||||
SqlParameter param = new SqlParameter(paramName, cell.Column.SqlDbType)
|
||||
{
|
||||
Value = cell.Value
|
||||
};
|
||||
command.Parameters.Add(param);
|
||||
}
|
||||
string joinedInColumns = string.Join(", ", inColumns);
|
||||
string joinedOutColumns = string.Join(", ", outColumns);
|
||||
|
||||
// Get the start clause
|
||||
string start = GetTableClause();
|
||||
|
||||
// Put together the components of the statement
|
||||
string joinedColumnNames = string.Join(", ", columnNames);
|
||||
string joinedColumnValues = string.Join(", ", columnValues);
|
||||
return string.Format(InsertStatement, AssociatedObjectMetadata.EscapedMultipartName, joinedColumnNames,
|
||||
joinedColumnValues);
|
||||
// Put the whole #! together
|
||||
command.CommandText = string.Format(InsertCompleteOutput, start, joinedOutColumns, joinedInColumns);
|
||||
command.CommandType = CommandType.Text;
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates the INSERT INTO statement that will apply the row creation
|
||||
/// </summary>
|
||||
/// <returns>INSERT INTO statement</returns>
|
||||
public override string GetScript()
|
||||
{
|
||||
// Process all the cells, and generate the values
|
||||
List<string> values = new List<string>();
|
||||
for (int i = 0; i < AssociatedResultSet.Columns.Length; i++)
|
||||
{
|
||||
DbColumnWrapper column = AssociatedResultSet.Columns[i];
|
||||
CellUpdate cell = newCells[i];
|
||||
|
||||
// Skip columns that cannot be updated
|
||||
if (!column.IsUpdatable)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// If we're missing a cell, then we cannot continue
|
||||
if (cell == null)
|
||||
{
|
||||
throw new InvalidOperationException(SR.EditDataCreateScriptMissingValue);
|
||||
}
|
||||
|
||||
// Format the value and add it to the list
|
||||
values.Add(SqlScriptFormatter.FormatValue(cell.Value, column));
|
||||
}
|
||||
string joinedValues = string.Join(", ", values);
|
||||
|
||||
// Get the start clause
|
||||
string start = GetTableClause();
|
||||
|
||||
// Put the whole #! together
|
||||
return string.Format(InsertCompleteScript, start, joinedValues);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -99,5 +186,19 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
|
||||
};
|
||||
return eucr;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private string GetTableClause()
|
||||
{
|
||||
// Get all the columns that will be provided
|
||||
var inColumns = from c in AssociatedResultSet.Columns
|
||||
where c.IsUpdatable
|
||||
select SqlScriptFormatter.FormatIdentifier(c.ColumnName);
|
||||
|
||||
// Package it into a single INSERT statement starter
|
||||
string inColumnsJoined = string.Join(", ", inColumns);
|
||||
return string.Format(InsertStart, AssociatedObjectMetadata.EscapedMultipartName, inColumnsJoined);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,9 +4,12 @@
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Data.Common;
|
||||
using System.Globalization;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SqlTools.ServiceLayer.EditData.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.QueryExecution;
|
||||
using Microsoft.SqlTools.Utility;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
|
||||
{
|
||||
@@ -29,15 +32,53 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sort ID for a RowDelete object. Setting to 2 ensures that these are the LAST changes
|
||||
/// to be committed
|
||||
/// </summary>
|
||||
protected override int SortId => 2;
|
||||
|
||||
/// <summary>
|
||||
/// Applies the changes to the associated result set after successfully executing the
|
||||
/// change on the database
|
||||
/// </summary>
|
||||
/// <param name="dataReader">
|
||||
/// Reader returned from the execution of the command to insert a new row. Should NOT
|
||||
/// contain any rows.
|
||||
/// </param>
|
||||
public override Task ApplyChanges(DbDataReader dataReader)
|
||||
{
|
||||
// Take the result set and remove the row from it
|
||||
AssociatedResultSet.RemoveRow(RowId);
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates a command for deleting the selected row
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override DbCommand GetCommand(DbConnection connection)
|
||||
{
|
||||
Validate.IsNotNull(nameof(connection), connection);
|
||||
|
||||
// Return a SqlCommand with formatted with the parameters from the where clause
|
||||
WhereClause where = GetWhereClause(true);
|
||||
string commandText = GetCommandText(where.CommandText);
|
||||
|
||||
DbCommand command = connection.CreateCommand();
|
||||
command.CommandText = commandText;
|
||||
command.Parameters.AddRange(where.Parameters.ToArray());
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates a DELETE statement to delete this row
|
||||
/// </summary>
|
||||
/// <returns>String of the DELETE statement</returns>
|
||||
public override string GetScript()
|
||||
{
|
||||
string formatString = AssociatedObjectMetadata.IsMemoryOptimized ? DeleteMemoryOptimizedStatement : DeleteStatement;
|
||||
return string.Format(CultureInfo.InvariantCulture, formatString,
|
||||
AssociatedObjectMetadata.EscapedMultipartName, GetWhereClause(false).CommandText);
|
||||
return GetCommandText(GetWhereClause(false).CommandText);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -51,5 +92,23 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
|
||||
{
|
||||
throw new InvalidOperationException(SR.EditDataDeleteSetCell);
|
||||
}
|
||||
|
||||
protected override int CompareToSameType(RowEditBase rowEdit)
|
||||
{
|
||||
// We want to sort by row ID *IN REVERSE* to make sure we delete from the bottom first.
|
||||
// If we delete from the top first, it will change IDs, making all subsequent deletes
|
||||
// off by one or more!
|
||||
return RowId.CompareTo(rowEdit.RowId) * -1;
|
||||
}
|
||||
|
||||
private string GetCommandText(string whereText)
|
||||
{
|
||||
string formatString = AssociatedObjectMetadata.IsMemoryOptimized
|
||||
? DeleteMemoryOptimizedStatement
|
||||
: DeleteStatement;
|
||||
|
||||
return string.Format(CultureInfo.InvariantCulture, formatString,
|
||||
AssociatedObjectMetadata.EscapedMultipartName, whereText);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ using System.Collections.Generic;
|
||||
using System.Data.Common;
|
||||
using System.Data.SqlClient;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SqlTools.ServiceLayer.EditData.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.QueryExecution;
|
||||
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts;
|
||||
@@ -18,9 +19,10 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
|
||||
/// <summary>
|
||||
/// Base class for row edit operations. Provides basic information and helper functionality
|
||||
/// that all RowEdit implementations can use. Defines functionality that must be implemented
|
||||
/// in all child classes.
|
||||
/// in all child classes. Implements a custom IComparable to enable sorting by type of the edit
|
||||
/// and then by an overrideable
|
||||
/// </summary>
|
||||
public abstract class RowEditBase
|
||||
public abstract class RowEditBase : IComparable<RowEditBase>
|
||||
{
|
||||
/// <summary>
|
||||
/// Internal parameterless constructor, required for mocking
|
||||
@@ -58,8 +60,31 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
|
||||
/// </summary>
|
||||
public IEditTableMetadata AssociatedObjectMetadata { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Sort ID for a row edit. Ensures that when a collection of RowEditBase objects are
|
||||
/// sorted, the appropriate types are sorted to the top.
|
||||
/// </summary>
|
||||
protected abstract int SortId { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Abstract Methods
|
||||
|
||||
/// <summary>
|
||||
/// Applies the changes to the associated result set
|
||||
/// </summary>
|
||||
/// <param name="dataReader">
|
||||
/// Data reader from execution of the command to commit the change to the db
|
||||
/// </param>
|
||||
public abstract Task ApplyChanges(DbDataReader dataReader);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a command that will commit the change to the db
|
||||
/// </summary>
|
||||
/// <param name="connection">The connection to associate the command to</param>
|
||||
/// <returns>Command to commit the change to the db</returns>
|
||||
public abstract DbCommand GetCommand(DbConnection connection);
|
||||
|
||||
/// <summary>
|
||||
/// Converts the row edit into a SQL statement
|
||||
/// </summary>
|
||||
@@ -74,6 +99,10 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
|
||||
/// <returns>The value of the cell after applying validation logic</returns>
|
||||
public abstract EditUpdateCellResult SetCell(int columnId, string newValue);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Protected Helper Methods
|
||||
|
||||
/// <summary>
|
||||
/// Performs validation of column ID and if column can be updated.
|
||||
/// </summary>
|
||||
@@ -146,7 +175,11 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
|
||||
// we execute multiple row edits at once.
|
||||
string paramName = $"@Param{RowId}{col.Ordinal}";
|
||||
cellDataClause = $"= {paramName}";
|
||||
output.Parameters.Add(new SqlParameter(paramName, col.DbColumn.SqlDbType));
|
||||
SqlParameter parameter = new SqlParameter(paramName, col.DbColumn.SqlDbType)
|
||||
{
|
||||
Value = cellData.RawObject
|
||||
};
|
||||
output.Parameters.Add(parameter);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -163,6 +196,66 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
|
||||
return output;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IComparable Implementation
|
||||
|
||||
/// <summary>
|
||||
/// Compares a row edit against another row edit. If they are the same type, then we
|
||||
/// compare using an overrideable "same type" comparer. If they are different types, they
|
||||
/// are sorted by their sort indexes.
|
||||
///
|
||||
/// In general, RowCreate and RowUpdates are sorted to the top. RowDeletes are sorted last.
|
||||
/// If there are ties, default behavior is to sort by row ID ascending.
|
||||
/// </summary>
|
||||
/// <param name="other">The other row edit to compare against</param>
|
||||
/// <returns>
|
||||
/// A positive value if this edit should go first, a negative value if the other edit
|
||||
/// should go first. 0 is returned if there is a tie.
|
||||
/// </returns>
|
||||
public int CompareTo(RowEditBase other)
|
||||
{
|
||||
// If the other is null, this one will come out on top
|
||||
if (other == null)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
// If types are the same, use the type's tiebreaking sorter
|
||||
if (GetType() == other.GetType())
|
||||
{
|
||||
return CompareToSameType(other);
|
||||
}
|
||||
|
||||
// If the type's sort index is the same, use our tiebreaking sorter
|
||||
// If they are different, use that as the comparison
|
||||
int sortIdComparison = SortId.CompareTo(other.SortId);
|
||||
return sortIdComparison == 0
|
||||
? CompareByRowId(other)
|
||||
: sortIdComparison;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Default behavior for sorting if the two compared row edits are the same type. Sorts
|
||||
/// by row ID ascending.
|
||||
/// </summary>
|
||||
/// <param name="rowEdit">The other row edit to compare against</param>
|
||||
protected virtual int CompareToSameType(RowEditBase rowEdit)
|
||||
{
|
||||
return CompareByRowId(rowEdit);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compares two row edits by their row ID ascending.
|
||||
/// </summary>
|
||||
/// <param name="rowEdit">The other row edit to compare against</param>
|
||||
private int CompareByRowId(RowEditBase rowEdit)
|
||||
{
|
||||
return RowId.CompareTo(rowEdit.RowId);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Represents a WHERE clause that can be used for identifying a row in a table.
|
||||
/// </summary>
|
||||
|
||||
@@ -5,12 +5,16 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Data;
|
||||
using System.Data.Common;
|
||||
using System.Data.SqlClient;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SqlTools.ServiceLayer.EditData.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.QueryExecution;
|
||||
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.Utility;
|
||||
using Microsoft.SqlTools.Utility;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
|
||||
{
|
||||
@@ -19,8 +23,11 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
|
||||
/// </summary>
|
||||
public sealed class RowUpdate : RowEditBase
|
||||
{
|
||||
private const string UpdateStatement = "UPDATE {0} SET {1} {2}";
|
||||
private const string UpdateStatementMemoryOptimized = "UPDATE {0} WITH (SNAPSHOT) SET {1} {2}";
|
||||
private const string UpdateScriptStart = @"UPDATE {0}";
|
||||
private const string UpdateScriptStartMemOptimized = @"UPDATE {0} WITH (SNAPSHOT)";
|
||||
|
||||
private const string UpdateScript = @"{0} SET {1} {2}";
|
||||
private const string UpdateScriptOutput = @"{0} SET {1} OUTPUT {2} {3}";
|
||||
|
||||
private readonly Dictionary<int, CellUpdate> cellUpdates;
|
||||
private readonly IList<DbCellValue> associatedRow;
|
||||
@@ -38,6 +45,73 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
|
||||
associatedRow = associatedResultSet.GetRow(rowId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sort order property. Sorts to same position as RowCreate
|
||||
/// </summary>
|
||||
protected override int SortId => 1;
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Applies the changes to the associated result set after successfully executing the
|
||||
/// change on the database
|
||||
/// </summary>
|
||||
/// <param name="dataReader">
|
||||
/// Reader returned from the execution of the command to update a row. Should contain
|
||||
/// a single row that represents all the values of the row.
|
||||
/// </param>
|
||||
public override Task ApplyChanges(DbDataReader dataReader)
|
||||
{
|
||||
Validate.IsNotNull(nameof(dataReader), dataReader);
|
||||
return AssociatedResultSet.UpdateRow(RowId, dataReader);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates a command that can be executed to update a row -- and return the contents of
|
||||
/// the updated row.
|
||||
/// </summary>
|
||||
/// <param name="connection">The connection the command should be associated with</param>
|
||||
/// <returns>Command to update the row</returns>
|
||||
public override DbCommand GetCommand(DbConnection connection)
|
||||
{
|
||||
Validate.IsNotNull(nameof(connection), connection);
|
||||
DbCommand command = connection.CreateCommand();
|
||||
|
||||
// Build the "SET" portion of the statement
|
||||
List<string> setComponents = new List<string>();
|
||||
foreach (var updateElement in cellUpdates)
|
||||
{
|
||||
string formattedColumnName = SqlScriptFormatter.FormatIdentifier(updateElement.Value.Column.ColumnName);
|
||||
string paramName = $"@Value{RowId}{updateElement.Key}";
|
||||
setComponents.Add($"{formattedColumnName} = {paramName}");
|
||||
SqlParameter parameter = new SqlParameter(paramName, updateElement.Value.Column.SqlDbType)
|
||||
{
|
||||
Value = updateElement.Value.Value
|
||||
};
|
||||
command.Parameters.Add(parameter);
|
||||
}
|
||||
string setComponentsJoined = string.Join(", ", setComponents);
|
||||
|
||||
// Build the "OUTPUT" portion of the statement
|
||||
var outColumns = from c in AssociatedResultSet.Columns
|
||||
let formatted = SqlScriptFormatter.FormatIdentifier(c.ColumnName)
|
||||
select $"inserted.{formatted}";
|
||||
string outColumnsJoined = string.Join(", ", outColumns);
|
||||
|
||||
// Get the where clause
|
||||
WhereClause where = GetWhereClause(true);
|
||||
command.Parameters.AddRange(where.Parameters.ToArray());
|
||||
|
||||
// Get the start of the statement
|
||||
string statementStart = GetStatementStart();
|
||||
|
||||
// Put the whole #! together
|
||||
command.CommandText = string.Format(UpdateScriptOutput, statementStart, setComponentsJoined,
|
||||
outColumnsJoined, where.CommandText);
|
||||
command.CommandType = CommandType.Text;
|
||||
return command;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs an update statement to change the associated row.
|
||||
/// </summary>
|
||||
@@ -45,7 +119,7 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
|
||||
public override string GetScript()
|
||||
{
|
||||
// Build the "SET" portion of the statement
|
||||
IEnumerable<string> setComponents = cellUpdates.Values.Select(cellUpdate =>
|
||||
var setComponents = cellUpdates.Values.Select(cellUpdate =>
|
||||
{
|
||||
string formattedColumnName = SqlScriptFormatter.FormatIdentifier(cellUpdate.Column.ColumnName);
|
||||
string formattedValue = SqlScriptFormatter.FormatValue(cellUpdate.Value, cellUpdate.Column);
|
||||
@@ -56,10 +130,11 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
|
||||
// Get the where clause
|
||||
string whereClause = GetWhereClause(false).CommandText;
|
||||
|
||||
// Put it all together
|
||||
string formatString = AssociatedObjectMetadata.IsMemoryOptimized ? UpdateStatementMemoryOptimized : UpdateStatement;
|
||||
return string.Format(CultureInfo.InvariantCulture, formatString,
|
||||
AssociatedObjectMetadata.EscapedMultipartName, setClause, whereClause);
|
||||
// Get the start of the statement
|
||||
string statementStart = GetStatementStart();
|
||||
|
||||
// Put the whole #! together
|
||||
return string.Format(UpdateScript, statementStart, setClause, whereClause);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -106,5 +181,16 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
|
||||
IsRevert = false // If we're in this branch, it is not a revert
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private string GetStatementStart()
|
||||
{
|
||||
string formatString = AssociatedObjectMetadata.IsMemoryOptimized
|
||||
? UpdateScriptStartMemOptimized
|
||||
: UpdateScriptStart;
|
||||
|
||||
return string.Format(formatString, AssociatedObjectMetadata.EscapedMultipartName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,18 +1,96 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
@@ -27,5 +105,19 @@
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype"><value>text/microsoft-resx</value></resheader><resheader name="version"><value>1.3</value></resheader><resheader name="reader"><value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value></resheader><resheader name="writer"><value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value></resheader><data name="TestLocalizationConstant"><value>ES_LOCALIZATION</value></data>
|
||||
</root>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="TestLocalizationConstant" xml:space="preserve">
|
||||
<value>ES_LOCALIZATION</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -120,423 +120,431 @@
|
||||
<data name="ConnectionServiceConnectErrorNullParams" xml:space="preserve">
|
||||
<value>Connection parameters cannot be null</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="ConnectionServiceListDbErrorNullOwnerUri" xml:space="preserve">
|
||||
<value>OwnerUri cannot be null or empty</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="ConnectionServiceListDbErrorNotConnected" xml:space="preserve">
|
||||
<value>SpecifiedUri '{0}' does not have existing connection</value>
|
||||
<comment>.
|
||||
Parameters: 0 - uri (string) </comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="ConnectionServiceDbErrorDefaultNotConnected" xml:space="preserve">
|
||||
<value>Specified URI '{0}' does not have a default connection</value>
|
||||
<comment>.
|
||||
Parameters: 0 - uri (string) </comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="ConnectionServiceConnStringInvalidAuthType" xml:space="preserve">
|
||||
<value>Invalid value '{0}' for AuthenticationType. Valid values are 'Integrated' and 'SqlLogin'.</value>
|
||||
<comment>.
|
||||
Parameters: 0 - authType (string) </comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="ConnectionServiceConnStringInvalidIntent" xml:space="preserve">
|
||||
<value>Invalid value '{0}' for ApplicationIntent. Valid values are 'ReadWrite' and 'ReadOnly'.</value>
|
||||
<comment>.
|
||||
Parameters: 0 - intent (string) </comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="ConnectionServiceConnectionCanceled" xml:space="preserve">
|
||||
<value>Connection canceled</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="ConnectionParamsValidateNullOwnerUri" xml:space="preserve">
|
||||
<value>OwnerUri cannot be null or empty</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="ConnectionParamsValidateNullConnection" xml:space="preserve">
|
||||
<value>Connection details object cannot be null</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="ConnectionParamsValidateNullServerName" xml:space="preserve">
|
||||
<value>ServerName cannot be null or empty</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="ConnectionParamsValidateNullSqlAuth" xml:space="preserve">
|
||||
<value>{0} cannot be null or empty when using SqlLogin authentication</value>
|
||||
<comment>.
|
||||
Parameters: 0 - component (string) </comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="ErrorUnexpectedCodeObjectType" xml:space="preserve">
|
||||
<value>Cannot convert SqlCodeObject Type {0} to Type {1}</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceCancelAlreadyCompleted" xml:space="preserve">
|
||||
<value>The query has already completed, it cannot be cancelled</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceCancelDisposeFailed" xml:space="preserve">
|
||||
<value>Query successfully cancelled, failed to dispose query. Owner URI not found.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceQueryCancelled" xml:space="preserve">
|
||||
<value>Query was canceled by user</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceSubsetBatchNotCompleted" xml:space="preserve">
|
||||
<value>The batch has not completed, yet</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceSubsetBatchOutOfRange" xml:space="preserve">
|
||||
<value>Batch index cannot be less than 0 or greater than the number of batches</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceSubsetResultSetOutOfRange" xml:space="preserve">
|
||||
<value>Result set index cannot be less than 0 or greater than the number of result sets</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceDataReaderByteCountInvalid" xml:space="preserve">
|
||||
<value>Maximum number of bytes to return must be greater than zero</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceDataReaderCharCountInvalid" xml:space="preserve">
|
||||
<value>Maximum number of chars to return must be greater than zero</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceDataReaderXmlCountInvalid" xml:space="preserve">
|
||||
<value>Maximum number of XML bytes to return must be greater than zero</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceFileWrapperWriteOnly" xml:space="preserve">
|
||||
<value>Access method cannot be write-only</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceFileWrapperNotInitialized" xml:space="preserve">
|
||||
<value>FileStreamWrapper must be initialized before performing operations</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceFileWrapperReadOnly" xml:space="preserve">
|
||||
<value>This FileStreamWrapper cannot be used for writing</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceAffectedOneRow" xml:space="preserve">
|
||||
<value>(1 row affected)</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceAffectedRows" xml:space="preserve">
|
||||
<value>({0} rows affected)</value>
|
||||
<comment>.
|
||||
Parameters: 0 - rows (long) </comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceCompletedSuccessfully" xml:space="preserve">
|
||||
<value>Commands completed successfully.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceErrorFormat" xml:space="preserve">
|
||||
<value>Msg {0}, Level {1}, State {2}, Line {3}{4}{5}</value>
|
||||
<comment>.
|
||||
Parameters: 0 - msg (int), 1 - lvl (int), 2 - state (int), 3 - line (int), 4 - newLine (string), 5 - message (string) </comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceQueryFailed" xml:space="preserve">
|
||||
<value>Query failed: {0}</value>
|
||||
<comment>.
|
||||
Parameters: 0 - message (string) </comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceColumnNull" xml:space="preserve">
|
||||
<value>(No column name)</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceRequestsNoQuery" xml:space="preserve">
|
||||
<value>The requested query does not exist</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceQueryInvalidOwnerUri" xml:space="preserve">
|
||||
<value>This editor is not connected to a database</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceQueryInProgress" xml:space="preserve">
|
||||
<value>A query is already in progress for this editor session. Please cancel this query or wait for its completion.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceMessageSenderNotSql" xml:space="preserve">
|
||||
<value>Sender for OnInfoMessage event must be a SqlConnection</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
<data name="QueryServiceResultSetReaderNull" xml:space="preserve">
|
||||
<value>Reader cannot be null</value>
|
||||
</data>
|
||||
<data name="QueryServiceResultSetAddNoRows" xml:space="preserve">
|
||||
<value>Cannot add row to result buffer, data reader does not contain rows</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceSaveAsResultSetNotComplete" xml:space="preserve">
|
||||
<value>Result cannot be saved until query execution has completed</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceSaveAsMiscStartingError" xml:space="preserve">
|
||||
<value>Internal error occurred while starting save task</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceSaveAsInProgress" xml:space="preserve">
|
||||
<value>A save request to the same path is in progress</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceSaveAsFail" xml:space="preserve">
|
||||
<value>Failed to save {0}: {1}</value>
|
||||
<comment>.
|
||||
Parameters: 0 - fileName (string), 1 - message (string) </comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceResultSetNotRead" xml:space="preserve">
|
||||
<value>Cannot read subset unless the results have been read from the server</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceResultSetStartRowOutOfRange" xml:space="preserve">
|
||||
<value>Start row cannot be less than 0 or greater than the number of rows in the result set</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceResultSetRowCountOutOfRange" xml:space="preserve">
|
||||
<value>Row count must be a positive integer</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceResultSetNoColumnSchema" xml:space="preserve">
|
||||
<value>Could not retrieve column schema for result set</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="QueryServiceExecutionPlanNotFound" xml:space="preserve">
|
||||
<value>Could not retrieve an execution plan from the result set </value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="PeekDefinitionAzureError" xml:space="preserve">
|
||||
<value>This feature is currently not supported on Azure SQL DB and Data Warehouse: {0}</value>
|
||||
<comment>.
|
||||
Parameters: 0 - errorMessage (string) </comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="PeekDefinitionError" xml:space="preserve">
|
||||
<value>An unexpected error occurred during Peek Definition execution: {0}</value>
|
||||
<comment>.
|
||||
Parameters: 0 - errorMessage (string) </comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="PeekDefinitionNoResultsError" xml:space="preserve">
|
||||
<value>No results were found.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="PeekDefinitionDatabaseError" xml:space="preserve">
|
||||
<value>No database object was retrieved.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="PeekDefinitionNotConnectedError" xml:space="preserve">
|
||||
<value>Please connect to a server.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="PeekDefinitionTimedoutError" xml:space="preserve">
|
||||
<value>Operation timed out.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="PeekDefinitionTypeNotSupportedError" xml:space="preserve">
|
||||
<value>This object type is currently not supported by this feature.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="ErrorEmptyStringReplacement" xml:space="preserve">
|
||||
<value>Replacement of an empty string by an empty string.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="WorkspaceServicePositionLineOutOfRange" xml:space="preserve">
|
||||
<value>Position is outside of file line range</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="WorkspaceServicePositionColumnOutOfRange" xml:space="preserve">
|
||||
<value>Position is outside of column range for line {0}</value>
|
||||
<comment>.
|
||||
Parameters: 0 - line (int) </comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="WorkspaceServiceBufferPositionOutOfOrder" xml:space="preserve">
|
||||
<value>Start position ({0}, {1}) must come before or be equal to the end position ({2}, {3})</value>
|
||||
<comment>.
|
||||
Parameters: 0 - sLine (int), 1 - sCol (int), 2 - eLine (int), 3 - eCol (int) </comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EditDataSessionNotFound" xml:space="preserve">
|
||||
<value>Edit session does not exist.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EditDataUnsupportedObjectType" xml:space="preserve">
|
||||
<value>Database object {0} cannot be used for editing.</value>
|
||||
<comment>.
|
||||
Parameters: 0 - typeName (string) </comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EditDataQueryNotCompleted" xml:space="preserve">
|
||||
<value>Query has not completed execution</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EditDataQueryImproperResultSets" xml:space="preserve">
|
||||
<value>Query did not generate exactly one result set</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EditDataFailedAddRow" xml:space="preserve">
|
||||
<value>Failed to add new row to update cache</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EditDataRowOutOfRange" xml:space="preserve">
|
||||
<value>Given row ID is outside the range of rows in the edit cache</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EditDataUpdatePending" xml:space="preserve">
|
||||
<value>An update is already pending for this row and must be reverted first</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EditDataUpdateNotPending" xml:space="preserve">
|
||||
<value>Given row ID does not have pending updated</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EditDataObjectMetadataNotFound" xml:space="preserve">
|
||||
<value>Table or view metadata could not be found</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EditDataInvalidFormatBinary" xml:space="preserve">
|
||||
<value>Invalid format for binary column</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EditDataInvalidFormatBoolean" xml:space="preserve">
|
||||
<value>Allowed values for boolean columns are 0, 1, "true", or "false"</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EditDataCreateScriptMissingValue" xml:space="preserve">
|
||||
<value>A required cell value is missing</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EditDataDeleteSetCell" xml:space="preserve">
|
||||
<value>A delete is pending for this row, a cell update cannot be applied.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EditDataColumnIdOutOfRange" xml:space="preserve">
|
||||
<value>Column ID must be in the range of columns for the query</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EditDataColumnCannotBeEdited" xml:space="preserve">
|
||||
<value>Column cannot be edited</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EditDataColumnNoKeyColumns" xml:space="preserve">
|
||||
<value>No key columns were found</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EditDataScriptFilePathNull" xml:space="preserve">
|
||||
<value>An output filename must be provided</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EditDataCommitInProgress" xml:space="preserve">
|
||||
<value>A commit task is in progress. Please wait for completion.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
<data name="EE_BatchSqlMessageNoProcedureInfo" xml:space="preserve">
|
||||
<value>Msg {0}, Level {1}, State {2}, Line {3}</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EE_BatchSqlMessageWithProcedureInfo" xml:space="preserve">
|
||||
<value>Msg {0}, Level {1}, State {2}, Procedure {3}, Line {4}</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EE_BatchSqlMessageNoLineInfo" xml:space="preserve">
|
||||
<value>Msg {0}, Level {1}, State {2}</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EE_BatchError_Exception" xml:space="preserve">
|
||||
<value>An error occurred while the batch was being processed. The error message is: {0}</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EE_BatchExecutionInfo_RowsAffected" xml:space="preserve">
|
||||
<value>({0} row(s) affected)</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EE_ExecutionNotYetCompleteError" xml:space="preserve">
|
||||
<value>The previous execution is not yet complete.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EE_ScriptError_Error" xml:space="preserve">
|
||||
<value>A scripting error occurred.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EE_ScriptError_ParsingSyntax" xml:space="preserve">
|
||||
<value>Incorrect syntax was encountered while {0} was being parsed.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EE_ScriptError_FatalError" xml:space="preserve">
|
||||
<value>A fatal error occurred.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EE_ExecutionInfo_FinalizingLoop" xml:space="preserve">
|
||||
<value>Execution completed {0} times...</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EE_ExecutionInfo_QueryCancelledbyUser" xml:space="preserve">
|
||||
<value>You cancelled the query.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EE_BatchExecutionError_Halting" xml:space="preserve">
|
||||
<value>An error occurred while the batch was being executed.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EE_BatchExecutionError_Ignoring" xml:space="preserve">
|
||||
<value>An error occurred while the batch was being executed, but the error has been ignored.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EE_ExecutionInfo_InitilizingLoop" xml:space="preserve">
|
||||
<value>Starting execution loop of {0} times...</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EE_ExecutionError_CommandNotSupported" xml:space="preserve">
|
||||
<value>Command {0} is not supported.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EE_ExecutionError_VariableNotFound" xml:space="preserve">
|
||||
<value>The variable {0} could not be found.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="BatchParserWrapperExecutionEngineError" xml:space="preserve">
|
||||
<value>SQL Execution error: {0}</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="BatchParserWrapperExecutionError" xml:space="preserve">
|
||||
<value>Batch parser wrapper execution: {0} found... at line {1}: {2} Description: {3}</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="BatchParserWrapperExecutionEngineBatchMessage" xml:space="preserve">
|
||||
<value>Batch parser wrapper execution engine batch message received: Message: {0} Detailed message: {1}</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="BatchParserWrapperExecutionEngineBatchResultSetProcessing" xml:space="preserve">
|
||||
<value>Batch parser wrapper execution engine batch ResultSet processing: DataReader.FieldCount: {0} DataReader.RecordsAffected: {1}</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="BatchParserWrapperExecutionEngineBatchResultSetFinished" xml:space="preserve">
|
||||
<value>Batch parser wrapper execution engine batch ResultSet finished.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="BatchParserWrapperExecutionEngineBatchCancelling" xml:space="preserve">
|
||||
<value>Canceling batch parser wrapper batch execution.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="EE_ScriptError_Warning" xml:space="preserve">
|
||||
<value>Scripting warning.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="TroubleshootingAssistanceMessage" xml:space="preserve">
|
||||
<value>For more information about this error, see the troubleshooting topics in the product documentation.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="BatchParser_CircularReference" xml:space="preserve">
|
||||
<value>File '{0}' recursively included.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="BatchParser_CommentNotTerminated" xml:space="preserve">
|
||||
<value>Missing end comment mark '*/'.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="BatchParser_StringNotTerminated" xml:space="preserve">
|
||||
<value>Unclosed quotation mark after the character string.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="BatchParser_IncorrectSyntax" xml:space="preserve">
|
||||
<value>Incorrect syntax was encountered while parsing '{0}'.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="BatchParser_VariableNotDefined" xml:space="preserve">
|
||||
<value>Variable {0} is not defined.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</data>
|
||||
<data name="TestLocalizationConstant" xml:space="preserve">
|
||||
<value>EN_LOCALIZATION</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</root>
|
||||
</data>
|
||||
<data name="SqlScriptFormatterDecimalMissingPrecision" xml:space="preserve">
|
||||
<value>Decimal column is missing numeric precision or numeric scale</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -37,7 +37,6 @@ ConnectionServiceConnStringInvalidIntent(string intent) = Invalid value '{0}' fo
|
||||
|
||||
ConnectionServiceConnectionCanceled = Connection canceled
|
||||
|
||||
######
|
||||
### Connection Params Validation Errors
|
||||
|
||||
ConnectionParamsValidateNullOwnerUri = OwnerUri cannot be null or empty
|
||||
@@ -110,7 +109,7 @@ QueryServiceQueryInProgress = A query is already in progress for this editor ses
|
||||
|
||||
QueryServiceMessageSenderNotSql = Sender for OnInfoMessage event must be a SqlConnection
|
||||
|
||||
QueryServiceResultSetReaderNull = Reader cannot be null
|
||||
QueryServiceResultSetAddNoRows = Cannot add row to result buffer, data reader does not contain rows
|
||||
|
||||
### Save As Requests
|
||||
|
||||
@@ -199,6 +198,8 @@ EditDataColumnNoKeyColumns = No key columns were found
|
||||
|
||||
EditDataScriptFilePathNull = An output filename must be provided
|
||||
|
||||
EditDataCommitInProgress = A commit task is in progress. Please wait for completion.
|
||||
|
||||
############################################################################
|
||||
# DacFx Resources
|
||||
|
||||
@@ -264,3 +265,8 @@ BatchParser_VariableNotDefined = Variable {0} is not defined.
|
||||
# Workspace Service
|
||||
|
||||
TestLocalizationConstant = EN_LOCALIZATION
|
||||
|
||||
############################################################################
|
||||
# Utilities
|
||||
|
||||
SqlScriptFormatterDecimalMissingPrecision = Decimal column is missing numeric precision or numeric scale
|
||||
|
||||
@@ -169,11 +169,6 @@
|
||||
<target state="new">Sender for OnInfoMessage event must be a SqlConnection</target>
|
||||
<note></note>
|
||||
</trans-unit>
|
||||
<trans-unit id="QueryServiceResultSetReaderNull">
|
||||
<source>Reader cannot be null</source>
|
||||
<target state="new">Reader cannot be null</target>
|
||||
<note></note>
|
||||
</trans-unit>
|
||||
<trans-unit id="QueryServiceSaveAsResultSetNotComplete">
|
||||
<source>Result cannot be saved until query execution has completed</source>
|
||||
<target state="new">Result cannot be saved until query execution has completed</target>
|
||||
@@ -526,6 +521,21 @@
|
||||
<note>.
|
||||
Parameters: 0 - uri (string) </note>
|
||||
</trans-unit>
|
||||
<trans-unit id="EditDataCommitInProgress">
|
||||
<source>A commit task is in progress. Please wait for completion.</source>
|
||||
<target state="new">A commit task is in progress. Please wait for completion.</target>
|
||||
<note></note>
|
||||
</trans-unit>
|
||||
<trans-unit id="SqlScriptFormatterDecimalMissingPrecision">
|
||||
<source>Decimal column is missing numeric precision or numeric scale</source>
|
||||
<target state="new">Decimal column is missing numeric precision or numeric scale</target>
|
||||
<note></note>
|
||||
</trans-unit>
|
||||
<trans-unit id="QueryServiceResultSetAddNoRows">
|
||||
<source>Cannot add row to result buffer, data reader does not contain rows</source>
|
||||
<target state="new">Cannot add row to result buffer, data reader does not contain rows</target>
|
||||
<note></note>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
||||
@@ -286,7 +286,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
}
|
||||
|
||||
// This resultset has results (ie, SELECT/etc queries)
|
||||
ResultSet resultSet = new ResultSet(reader, resultSetOrdinal, Id, outputFileFactory);
|
||||
ResultSet resultSet = new ResultSet(resultSetOrdinal, Id, outputFileFactory);
|
||||
resultSet.ResultCompletion += ResultSetCompletion;
|
||||
|
||||
// Add the result set to the results of the query
|
||||
@@ -297,7 +297,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
}
|
||||
|
||||
// Read until we hit the end of the result set
|
||||
await resultSet.ReadResultToEnd(cancellationToken).ConfigureAwait(false);
|
||||
await resultSet.ReadResultToEnd(reader, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
} while (await reader.NextResultAsync(cancellationToken));
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts
|
||||
IsIdentity = column.IsIdentity;
|
||||
IsKey = column.IsKey;
|
||||
IsLong = column.IsLong;
|
||||
IsReadOnly = column.IsLong;
|
||||
IsReadOnly = column.IsReadOnly;
|
||||
IsUnique = column.IsUnique;
|
||||
NumericPrecision = column.NumericPrecision;
|
||||
NumericScale = column.NumericScale;
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage
|
||||
{
|
||||
int WriteRow(StorageDataReader dataReader);
|
||||
void WriteRow(IList<DbCellValue> row, IList<DbColumnWrapper> columns);
|
||||
|
||||
void Seek(long offset);
|
||||
void FlushBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,6 +75,15 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage
|
||||
/// <param name="columns">The list of columns to output</param>
|
||||
public abstract void WriteRow(IList<DbCellValue> row, IList<DbColumnWrapper> columns);
|
||||
|
||||
/// <summary>
|
||||
/// Not implemented, do not use.
|
||||
/// </summary>
|
||||
[Obsolete]
|
||||
public void Seek(long offset)
|
||||
{
|
||||
throw new InvalidOperationException("SaveAs writers are meant to be written once contiguously.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Flushes the file stream buffer
|
||||
/// </summary>
|
||||
|
||||
@@ -212,6 +212,14 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage
|
||||
throw new InvalidOperationException("This type of writer is meant to write values from a DbDataReader only.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Seeks to a given offset in the file, relative to the beginning of the file
|
||||
/// </summary>
|
||||
public void Seek(long offset)
|
||||
{
|
||||
fileStream.Seek(offset, SeekOrigin.Begin);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Flushes the internal buffer to the file stream
|
||||
/// </summary>
|
||||
|
||||
@@ -33,11 +33,6 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
|
||||
#region Member Variables
|
||||
|
||||
/// <summary>
|
||||
/// The reader to use for this resultset
|
||||
/// </summary>
|
||||
private readonly StorageDataReader dataReader;
|
||||
|
||||
/// <summary>
|
||||
/// For IDisposable pattern, whether or not object has been disposed
|
||||
/// </summary>
|
||||
@@ -69,30 +64,37 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
/// </summary>
|
||||
private readonly string outputFileName;
|
||||
|
||||
/// <summary>
|
||||
/// Row count to use in special scenarios where we want to override the number of rows.
|
||||
/// </summary>
|
||||
private long? rowCountOverride;
|
||||
|
||||
/// <summary>
|
||||
/// The special action which applied to this result set
|
||||
/// </summary>
|
||||
private readonly SpecialAction specialAction;
|
||||
|
||||
/// <summary>
|
||||
/// Total number of bytes written to the file. Used to jump to end of the file for append
|
||||
/// scenarios. Internal for unit test validation.
|
||||
/// </summary>
|
||||
internal long totalBytesWritten;
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new result set and initializes its state
|
||||
/// </summary>
|
||||
/// <param name="reader">The reader from executing a query</param>
|
||||
/// <param name="ordinal">The ID of the resultset, the ordinal of the result within the batch</param>
|
||||
/// <param name="batchOrdinal">The ID of the batch, the ordinal of the batch within the query</param>
|
||||
/// <param name="factory">Factory for creating a reader/writer</param>
|
||||
public ResultSet(DbDataReader reader, int ordinal, int batchOrdinal, IFileStreamFactory factory)
|
||||
public ResultSet(int ordinal, int batchOrdinal, IFileStreamFactory factory)
|
||||
{
|
||||
// Sanity check to make sure we got a reader
|
||||
Validate.IsNotNull(nameof(reader), SR.QueryServiceResultSetReaderNull);
|
||||
|
||||
dataReader = new StorageDataReader(reader);
|
||||
Id = ordinal;
|
||||
BatchId = batchOrdinal;
|
||||
|
||||
// Initialize the storage
|
||||
totalBytesWritten = 0;
|
||||
outputFileName = factory.CreateFile();
|
||||
fileOffsets = new LongList<long>();
|
||||
specialAction = new SpecialAction();
|
||||
@@ -103,7 +105,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
SaveTasks = new ConcurrentDictionary<string, Task>();
|
||||
}
|
||||
|
||||
#region Properties
|
||||
#region Eventing
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronous handler for when saving query results succeeds
|
||||
@@ -129,6 +131,10 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
/// </summary>
|
||||
public event ResultSetAsyncEventHandler ResultCompletion;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Whether the resultSet is in the process of being disposed
|
||||
/// </summary>
|
||||
@@ -153,7 +159,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
/// <summary>
|
||||
/// The number of rows for this result set
|
||||
/// </summary>
|
||||
public long RowCount { get; private set; }
|
||||
public long RowCount => rowCountOverride ?? fileOffsets.Count;
|
||||
|
||||
/// <summary>
|
||||
/// All save tasks currently saving this ResultSet
|
||||
@@ -173,8 +179,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
Id = Id,
|
||||
BatchId = BatchId,
|
||||
RowCount = RowCount,
|
||||
SpecialAction = ProcessSpecialAction()
|
||||
|
||||
SpecialAction = hasBeenRead ? ProcessSpecialAction() : null
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -183,6 +188,15 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Returns a specific row from the result set.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Creates a new file reader for a single reader. This method should only be used for one
|
||||
/// off requests, not for requesting a large subset of the results.
|
||||
/// </remarks>
|
||||
/// <param name="rowId">The internal ID of the row to read</param>
|
||||
/// <returns>The requested row</returns>
|
||||
public IList<DbCellValue> GetRow(long rowId)
|
||||
{
|
||||
// Sanity check to make sure that results have been read beforehand
|
||||
@@ -313,14 +327,20 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
/// <summary>
|
||||
/// Reads from the reader until there are no more results to read
|
||||
/// </summary>
|
||||
/// <param name="dbDataReader">The data reader for getting results from the db</param>
|
||||
/// <param name="cancellationToken">Cancellation token for cancelling the query</param>
|
||||
public async Task ReadResultToEnd(CancellationToken cancellationToken)
|
||||
public async Task ReadResultToEnd(DbDataReader dbDataReader, CancellationToken cancellationToken)
|
||||
{
|
||||
// Sanity check to make sure we got a reader
|
||||
Validate.IsNotNull(nameof(dbDataReader), dbDataReader);
|
||||
|
||||
try
|
||||
{
|
||||
// Mark that result has been read
|
||||
hasBeenRead = true;
|
||||
|
||||
StorageDataReader dataReader = new StorageDataReader(dbDataReader);
|
||||
|
||||
// Open a writer for the file
|
||||
var fileWriter = fileStreamFactory.GetWriter(outputFileName);
|
||||
using (fileWriter)
|
||||
@@ -331,13 +351,10 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
throw new InvalidOperationException(SR.QueryServiceResultSetNoColumnSchema);
|
||||
}
|
||||
Columns = dataReader.Columns;
|
||||
long currentFileOffset = 0;
|
||||
|
||||
while (await dataReader.ReadAsync(cancellationToken))
|
||||
{
|
||||
RowCount++;
|
||||
fileOffsets.Add(currentFileOffset);
|
||||
currentFileOffset += fileWriter.WriteRow(dataReader);
|
||||
fileOffsets.Add(totalBytesWritten);
|
||||
totalBytesWritten += fileWriter.WriteRow(dataReader);
|
||||
}
|
||||
}
|
||||
// Check if resultset is 'for xml/json'. If it is, set isJson/isXml value in column metadata
|
||||
@@ -353,6 +370,50 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a row from the result set cache
|
||||
/// </summary>
|
||||
/// <param name="internalId">Internal ID of the row</param>
|
||||
public void RemoveRow(long internalId)
|
||||
{
|
||||
// Make sure that the results have been read
|
||||
if (!hasBeenRead)
|
||||
{
|
||||
throw new InvalidOperationException(SR.QueryServiceResultSetNotRead);
|
||||
}
|
||||
|
||||
// Simply remove the row from the list of row offsets
|
||||
fileOffsets.RemoveAt(internalId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new row to the result set by reading the row from the provided db data reader
|
||||
/// </summary>
|
||||
/// <param name="dbDataReader">The result of a command to insert a new row should be UNREAD</param>
|
||||
public async Task AddRow(DbDataReader dbDataReader)
|
||||
{
|
||||
// Write the new row to the end of the file
|
||||
long newOffset = await AppendRowToBuffer(dbDataReader);
|
||||
|
||||
// Add the row to file offset list
|
||||
fileOffsets.Add(newOffset);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the values in a row with the
|
||||
/// </summary>
|
||||
/// <param name="rowId"></param>
|
||||
/// <param name="dbDataReader"></param>
|
||||
/// <returns></returns>
|
||||
public async Task UpdateRow(long rowId, DbDataReader dbDataReader)
|
||||
{
|
||||
// Write the updated row to the end of the file
|
||||
long newOffset = await AppendRowToBuffer(dbDataReader);
|
||||
|
||||
// Update the file offset of the row in question
|
||||
fileOffsets[rowId] = newOffset;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves the contents of this result set to a file using the IFileStreamFactory provided
|
||||
/// </summary>
|
||||
@@ -508,13 +569,13 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
{
|
||||
Columns[0].IsXml = true;
|
||||
isSingleColumnXmlJsonResultSet = true;
|
||||
RowCount = 1;
|
||||
rowCountOverride = 1;
|
||||
}
|
||||
else if (Columns[0].ColumnName.Equals(NameOfForJsonColumn, StringComparison.Ordinal))
|
||||
{
|
||||
Columns[0].IsJson = true;
|
||||
isSingleColumnXmlJsonResultSet = true;
|
||||
RowCount = 1;
|
||||
rowCountOverride = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -526,7 +587,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
{
|
||||
|
||||
// Check if this result set is a showplan
|
||||
if (dataReader.Columns.Length == 1 && string.Compare(dataReader.Columns[0].ColumnName, YukonXmlShowPlanColumn, StringComparison.OrdinalIgnoreCase) == 0)
|
||||
if (Columns.Length == 1 && string.Compare(Columns[0].ColumnName, YukonXmlShowPlanColumn, StringComparison.OrdinalIgnoreCase) == 0)
|
||||
{
|
||||
specialAction.ExpectYukonXMLShowPlan = true;
|
||||
}
|
||||
@@ -534,6 +595,36 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
return specialAction;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a single row to the end of the buffer file. INTENDED FOR SINGLE ROW INSERTION ONLY.
|
||||
/// </summary>
|
||||
/// <param name="dbDataReader">An UNREAD db data reader</param>
|
||||
/// <returns>The offset into the file where the row was inserted</returns>
|
||||
private async Task<long> AppendRowToBuffer(DbDataReader dbDataReader)
|
||||
{
|
||||
Validate.IsNotNull(nameof(dbDataReader), dbDataReader);
|
||||
if (!hasBeenRead)
|
||||
{
|
||||
throw new InvalidOperationException(SR.QueryServiceResultSetNotRead);
|
||||
}
|
||||
if (!dbDataReader.HasRows)
|
||||
{
|
||||
throw new InvalidOperationException(SR.QueryServiceResultSetAddNoRows);
|
||||
}
|
||||
|
||||
StorageDataReader dataReader = new StorageDataReader(dbDataReader);
|
||||
|
||||
using (IFileStreamWriter writer = fileStreamFactory.GetWriter(outputFileName))
|
||||
{
|
||||
// Write the row to the end of the file
|
||||
long currentFileOffset = totalBytesWritten;
|
||||
writer.Seek(currentFileOffset);
|
||||
await dataReader.ReadAsync(CancellationToken.None);
|
||||
totalBytesWritten += writer.WriteRow(dataReader);
|
||||
return currentFileOffset;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,8 +185,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Utility
|
||||
// Make sure we have numeric precision and numeric scale
|
||||
if (!column.NumericPrecision.HasValue || !column.NumericScale.HasValue)
|
||||
{
|
||||
// @TODO Move to constants
|
||||
throw new InvalidOperationException("Decimal column is missing numeric precision or numeric scale");
|
||||
throw new InvalidOperationException(SR.SqlScriptFormatterDecimalMissingPrecision);
|
||||
}
|
||||
|
||||
// Convert the value to a decimal, then convert that to a string
|
||||
|
||||
@@ -7,6 +7,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.Common;
|
||||
using Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement;
|
||||
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
@@ -26,7 +27,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
{
|
||||
// If: I attempt to create a CellUpdate with a null string value
|
||||
// Then: I should get an exception thrown
|
||||
Assert.Throws<ArgumentNullException>(() => new CellUpdate(new CellUpdateTestDbColumn(null), null));
|
||||
Assert.Throws<ArgumentNullException>(() => new CellUpdate(GetWrapper<string>("ntext"), null));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -34,7 +35,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
{
|
||||
// If: I attempt to create a CellUpdate to set it to NULL (with mixed cases)
|
||||
const string nullString = "NULL";
|
||||
DbColumn col = new CellUpdateTestDbColumn(typeof(string));
|
||||
DbColumnWrapper col = GetWrapper<string>("ntext");
|
||||
CellUpdate cu = new CellUpdate(col, nullString);
|
||||
|
||||
// Then: The value should be a DBNull and the string value should be the same as what
|
||||
@@ -49,7 +50,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
public void NullTextStringTest()
|
||||
{
|
||||
// If: I attempt to create a CellUpdate with the text 'NULL' (with mixed case)
|
||||
DbColumn col = new CellUpdateTestDbColumn(typeof(string));
|
||||
DbColumnWrapper col = GetWrapper<string>("ntext");
|
||||
CellUpdate cu = new CellUpdate(col, "'NULL'");
|
||||
|
||||
// Then: The value should be NULL
|
||||
@@ -64,7 +65,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
public void ByteArrayTest(string strValue, byte[] expectedValue, string expectedString)
|
||||
{
|
||||
// If: I attempt to create a CellUpdate for a binary column
|
||||
DbColumn col = new CellUpdateTestDbColumn(typeof(byte[]));
|
||||
DbColumnWrapper col = GetWrapper<byte[]>("binary");
|
||||
CellUpdate cu = new CellUpdate(col, strValue);
|
||||
|
||||
// Then: The value should be a binary and should match the expected data
|
||||
@@ -118,7 +119,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
{
|
||||
// If: I attempt to create a CellUpdate for a binary column
|
||||
// Then: It should throw an exception
|
||||
DbColumn col = new CellUpdateTestDbColumn(typeof(byte[]));
|
||||
DbColumnWrapper col = GetWrapper<byte[]>("binary");
|
||||
Assert.Throws<FormatException>(() => new CellUpdate(col, "this is totally invalid"));
|
||||
}
|
||||
|
||||
@@ -127,7 +128,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
public void BoolTest(string input, bool output, string outputString)
|
||||
{
|
||||
// If: I attempt to create a CellUpdate for a boolean column
|
||||
DbColumn col = new CellUpdateTestDbColumn(typeof(bool));
|
||||
DbColumnWrapper col = GetWrapper<bool>("bit");
|
||||
CellUpdate cu = new CellUpdate(col, input);
|
||||
|
||||
// Then: The value should match what was expected
|
||||
@@ -153,23 +154,22 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
{
|
||||
// If: I create a CellUpdate for a bool column and provide an invalid numeric value
|
||||
// Then: It should throw an exception
|
||||
DbColumn col = new CellUpdateTestDbColumn(typeof(bool));
|
||||
DbColumnWrapper col = GetWrapper<bool>("bit");
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => new CellUpdate(col, "12345"));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RoundTripTestParams))]
|
||||
public void RoundTripTest(Type dbColType, object obj)
|
||||
public void RoundTripTest(DbColumnWrapper col, object obj)
|
||||
{
|
||||
// Setup: Figure out the test string
|
||||
string testString = obj.ToString();
|
||||
|
||||
// If: I attempt to create a CellUpdate for a GUID column
|
||||
DbColumn col = new CellUpdateTestDbColumn(dbColType);
|
||||
// If: I attempt to create a CellUpdate
|
||||
CellUpdate cu = new CellUpdate(col, testString);
|
||||
|
||||
// Then: The value and type should match what we put in
|
||||
Assert.IsType(dbColType, cu.Value);
|
||||
Assert.IsType(col.DataType, cu.Value);
|
||||
Assert.Equal(obj, cu.Value);
|
||||
Assert.Equal(testString, cu.ValueAsString);
|
||||
Assert.Equal(col, cu.Column);
|
||||
@@ -179,29 +179,35 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
{
|
||||
get
|
||||
{
|
||||
yield return new object[] {typeof(Guid), Guid.NewGuid()};
|
||||
yield return new object[] {typeof(TimeSpan), new TimeSpan(0, 1, 20, 0, 123)};
|
||||
yield return new object[] {typeof(DateTime), new DateTime(2016, 04, 25, 9, 45, 0)};
|
||||
yield return new object[] {GetWrapper<Guid>("uniqueidentifier"), Guid.NewGuid()};
|
||||
yield return new object[] {GetWrapper<TimeSpan>("time"), new TimeSpan(0, 1, 20, 0, 123)};
|
||||
yield return new object[] {GetWrapper<DateTime>("datetime"), new DateTime(2016, 04, 25, 9, 45, 0)};
|
||||
yield return new object[]
|
||||
{
|
||||
typeof(DateTimeOffset),
|
||||
GetWrapper<DateTimeOffset>("datetimeoffset"),
|
||||
new DateTimeOffset(2016, 04, 25, 9, 45, 0, TimeSpan.FromHours(8))
|
||||
};
|
||||
yield return new object[] {typeof(long), 1000L};
|
||||
yield return new object[] {typeof(decimal), new decimal(3.14)};
|
||||
yield return new object[] {typeof(int), 1000};
|
||||
yield return new object[] {typeof(short), (short) 1000};
|
||||
yield return new object[] {typeof(byte), (byte) 5};
|
||||
yield return new object[] {typeof(double), 3.14d};
|
||||
yield return new object[] {typeof(float), 3.14f};
|
||||
yield return new object[] {GetWrapper<long>("bigint"), 1000L};
|
||||
yield return new object[] {GetWrapper<decimal>("decimal"), new decimal(3.14)};
|
||||
yield return new object[] {GetWrapper<int>("int"), 1000};
|
||||
yield return new object[] {GetWrapper<short>("smallint"), (short) 1000};
|
||||
yield return new object[] {GetWrapper<byte>("tinyint"), (byte) 5};
|
||||
yield return new object[] {GetWrapper<double>("float"), 3.14d};
|
||||
yield return new object[] {GetWrapper<float>("real"), 3.14f};
|
||||
}
|
||||
}
|
||||
|
||||
private static DbColumnWrapper GetWrapper<T>(string dataTypeName)
|
||||
{
|
||||
return new DbColumnWrapper(new CellUpdateTestDbColumn(typeof(T), dataTypeName));
|
||||
}
|
||||
|
||||
private class CellUpdateTestDbColumn : DbColumn
|
||||
{
|
||||
public CellUpdateTestDbColumn(Type dataType)
|
||||
public CellUpdateTestDbColumn(Type dataType, string dataTypeName)
|
||||
{
|
||||
DataType = dataType;
|
||||
DataTypeName = dataTypeName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,18 +69,27 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
return columns.ToArray();
|
||||
}
|
||||
|
||||
public static ResultSet GetResultSet(DbColumn[] columns, bool includeIdentity)
|
||||
public static ResultSet GetResultSet(DbColumn[] columns, bool includeIdentity, int rowCount = 1)
|
||||
{
|
||||
object[][] rows = includeIdentity
|
||||
? new[] { new object[] { "id", "1", "2", "3" } }
|
||||
: new[] { new object[] { "1", "2", "3" } };
|
||||
IEnumerable<object[]> rows = includeIdentity
|
||||
? Enumerable.Repeat(new object[] { "id", "1", "2", "3" }, rowCount)
|
||||
: Enumerable.Repeat(new object[] { "1", "2", "3" }, rowCount);
|
||||
var testResultSet = new TestResultSet(columns, rows);
|
||||
var reader = new TestDbDataReader(new[] { testResultSet });
|
||||
var resultSet = new ResultSet(reader, 0, 0, MemoryFileSystem.GetFileStreamFactory());
|
||||
resultSet.ReadResultToEnd(CancellationToken.None).Wait();
|
||||
var resultSet = new ResultSet(0, 0, MemoryFileSystem.GetFileStreamFactory());
|
||||
resultSet.ReadResultToEnd(reader, CancellationToken.None).Wait();
|
||||
return resultSet;
|
||||
}
|
||||
|
||||
public static DbDataReader GetNewRowDataReader(DbColumn[] columns, bool includeIdentity)
|
||||
{
|
||||
object[][] rows = includeIdentity
|
||||
? new[] {new object[] {"id", "q", "q", "q"}}
|
||||
: new[] {new object[] {"q", "q", "q"}};
|
||||
var testResultSet = new TestResultSet(columns, rows);
|
||||
return new TestDbDataReader(new [] {testResultSet});
|
||||
}
|
||||
|
||||
public static void AddCells(RowEditBase rc, bool includeIdentity)
|
||||
{
|
||||
// Skip the first column since if identity, since identity columns can't be updated
|
||||
|
||||
@@ -6,9 +6,11 @@
|
||||
using System;
|
||||
using System.Data.Common;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SqlTools.ServiceLayer.EditData;
|
||||
using Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement;
|
||||
using Microsoft.SqlTools.ServiceLayer.QueryExecution;
|
||||
using Microsoft.SqlTools.ServiceLayer.UnitTests.Utility;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
@@ -80,5 +82,110 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
RowCreate rc = new RowCreate(rowId, rs, etm);
|
||||
Assert.Throws<InvalidOperationException>(() => rc.GetScript());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public async Task ApplyChanges(bool includeIdentity)
|
||||
{
|
||||
// Setup:
|
||||
// ... Generate the parameters for the row create
|
||||
const long rowId = 100;
|
||||
DbColumn[] columns = Common.GetColumns(includeIdentity);
|
||||
ResultSet rs = Common.GetResultSet(columns, includeIdentity);
|
||||
IEditTableMetadata etm = Common.GetMetadata(columns);
|
||||
|
||||
// ... Setup a db reader for the result of an insert
|
||||
var newRowReader = Common.GetNewRowDataReader(columns, includeIdentity);
|
||||
|
||||
// If: I ask for the change to be applied
|
||||
RowCreate rc = new RowCreate(rowId, rs, etm);
|
||||
await rc.ApplyChanges(newRowReader);
|
||||
|
||||
// Then: The result set should have an additional row in it
|
||||
Assert.Equal(2, rs.RowCount);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public void GetCommand(bool includeIdentity)
|
||||
{
|
||||
// Setup:
|
||||
// ... Create a row create with cell updates
|
||||
const long rowId = 100;
|
||||
var columns = Common.GetColumns(includeIdentity);
|
||||
var rs = Common.GetResultSet(columns, includeIdentity);
|
||||
var etm = Common.GetMetadata(columns);
|
||||
RowCreate rc = new RowCreate(rowId, rs, etm);
|
||||
Common.AddCells(rc, includeIdentity);
|
||||
|
||||
// ... Mock db connection for building the command
|
||||
var mockConn = new TestSqlConnection(null);
|
||||
|
||||
// If: I attempt to get a command for the edit
|
||||
DbCommand cmd = rc.GetCommand(mockConn);
|
||||
|
||||
// Then:
|
||||
// ... The command should not be null
|
||||
Assert.NotNull(cmd);
|
||||
|
||||
// ... There should be parameters in it
|
||||
Assert.Equal(3, cmd.Parameters.Count);
|
||||
|
||||
// ... It should be formatted into an insert script with output
|
||||
Regex r = new Regex(@"INSERT INTO (.+)\((.+)\) OUTPUT (.+) VALUES \((.+)\)");
|
||||
var m = r.Match(cmd.CommandText);
|
||||
Assert.True(m.Success);
|
||||
|
||||
// ... There should be a table
|
||||
string tbl = m.Groups[1].Value;
|
||||
Assert.Equal(etm.EscapedMultipartName, tbl);
|
||||
|
||||
// ... There should be 3 columns for input
|
||||
string inCols = m.Groups[2].Value;
|
||||
Assert.Equal(3, inCols.Split(',').Length);
|
||||
|
||||
// ... There should be 3 OR 4 columns for output that are inserted.
|
||||
string[] outCols = m.Groups[3].Value.Split(',');
|
||||
Assert.Equal(includeIdentity ? 4 : 3, outCols.Length);
|
||||
Assert.All(outCols, s => Assert.StartsWith("inserted.", s.Trim()));
|
||||
|
||||
// ... There should be 3 parameters
|
||||
string[] param = m.Groups[4].Value.Split(',');
|
||||
Assert.Equal(3, param.Length);
|
||||
Assert.All(param, s => Assert.StartsWith("@Value", s.Trim()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetCommandNullConnection()
|
||||
{
|
||||
// Setup: Create a row create
|
||||
const long rowId = 100;
|
||||
var columns = Common.GetColumns(false);
|
||||
var rs = Common.GetResultSet(columns, false);
|
||||
var etm = Common.GetMetadata(columns);
|
||||
RowCreate rc = new RowCreate(rowId, rs, etm);
|
||||
|
||||
// If: I attempt to create a command with a null connection
|
||||
// Then: It should throw an exception
|
||||
Assert.Throws<ArgumentNullException>(() => rc.GetCommand(null));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetCommandMissingCell()
|
||||
{
|
||||
// Setup: Generate the parameters for the row create
|
||||
const long rowId = 100;
|
||||
var columns = Common.GetColumns(false);
|
||||
var rs = Common.GetResultSet(columns, false);
|
||||
var etm = Common.GetMetadata(columns);
|
||||
var mockConn = new TestSqlConnection(null);
|
||||
|
||||
// If: I ask for a script to be generated without setting any values
|
||||
// Then: An exception should be thrown for missing cells
|
||||
RowCreate rc = new RowCreate(rowId, rs, etm);
|
||||
Assert.Throws<InvalidOperationException>(() => rc.GetCommand(mockConn));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,9 +5,12 @@
|
||||
|
||||
using System;
|
||||
using System.Data.Common;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SqlTools.ServiceLayer.EditData;
|
||||
using Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement;
|
||||
using Microsoft.SqlTools.ServiceLayer.QueryExecution;
|
||||
using Microsoft.SqlTools.ServiceLayer.UnitTests.Utility;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
@@ -34,11 +37,11 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public void GetScriptTest(bool isHekaton)
|
||||
public void GetScriptTest(bool isMemoryOptimized)
|
||||
{
|
||||
DbColumn[] columns = Common.GetColumns(true);
|
||||
ResultSet rs = Common.GetResultSet(columns, true);
|
||||
IEditTableMetadata etm = Common.GetMetadata(columns, false, isHekaton);
|
||||
IEditTableMetadata etm = Common.GetMetadata(columns, false, isMemoryOptimized);
|
||||
|
||||
// If: I ask for a script to be generated for delete
|
||||
RowDelete rd = new RowDelete(0, rs, etm);
|
||||
@@ -50,13 +53,94 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
|
||||
// ... It should be formatted as a delete script
|
||||
string scriptStart = $"DELETE FROM {etm.EscapedMultipartName}";
|
||||
if (isHekaton)
|
||||
if (isMemoryOptimized)
|
||||
{
|
||||
scriptStart += " WITH(SNAPSHOT)";
|
||||
}
|
||||
Assert.StartsWith(scriptStart, script);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ApplyChanges()
|
||||
{
|
||||
// Setup: Generate the parameters for the row delete object
|
||||
// We don't care about the values besides the row ID
|
||||
const long rowId = 0;
|
||||
var columns = Common.GetColumns(false);
|
||||
var rs = Common.GetResultSet(columns, false);
|
||||
var etm = Common.GetMetadata(columns);
|
||||
|
||||
// If: I ask for the change to be applied
|
||||
RowDelete rd = new RowDelete(rowId, rs, etm);
|
||||
await rd.ApplyChanges(null); // Reader not used, can be null
|
||||
|
||||
// Then : The result set should have one less row in it
|
||||
Assert.Equal(0, rs.RowCount);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true, true)]
|
||||
[InlineData(false, true)]
|
||||
[InlineData(true, false)]
|
||||
[InlineData(false, false)]
|
||||
public void GetCommand(bool includeIdentity, bool isMemoryOptimized)
|
||||
{
|
||||
// Setup:
|
||||
// ... Create a row delete
|
||||
const long rowId = 0;
|
||||
var columns = Common.GetColumns(includeIdentity);
|
||||
var rs = Common.GetResultSet(columns, includeIdentity);
|
||||
var etm = Common.GetMetadata(columns, !includeIdentity, isMemoryOptimized);
|
||||
RowDelete rd = new RowDelete(rowId, rs, etm);
|
||||
|
||||
// ... Mock db connection for building the command
|
||||
var mockConn = new TestSqlConnection(null);
|
||||
|
||||
// If: I attempt to get a command for the edit
|
||||
DbCommand cmd = rd.GetCommand(mockConn);
|
||||
|
||||
// Then:
|
||||
// ... The command should not be null
|
||||
Assert.NotNull(cmd);
|
||||
|
||||
// ... Only the keys should be used for parameters
|
||||
int expectedKeys = includeIdentity ? 1 : 3;
|
||||
Assert.Equal(expectedKeys, cmd.Parameters.Count);
|
||||
|
||||
// ... It should be formatted into an delete script
|
||||
string regexTest = isMemoryOptimized
|
||||
? @"DELETE FROM (.+) WITH\(SNAPSHOT\) WHERE (.+)"
|
||||
: @"DELETE FROM (.+) WHERE (.+)";
|
||||
Regex r = new Regex(regexTest);
|
||||
var m = r.Match(cmd.CommandText);
|
||||
Assert.True(m.Success);
|
||||
|
||||
// ... There should be a table
|
||||
string tbl = m.Groups[1].Value;
|
||||
Assert.Equal(etm.EscapedMultipartName, tbl);
|
||||
|
||||
// ... There should be as many where components as there are keys
|
||||
string[] whereComponents = m.Groups[2].Value.Split(new[] {"AND"}, StringSplitOptions.None);
|
||||
Assert.Equal(expectedKeys, whereComponents.Length);
|
||||
|
||||
// ... Each component should have be equal to a parameter
|
||||
Assert.All(whereComponents, c => Assert.True(Regex.IsMatch(c.Trim(), @"\(.+ = @.+\)")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetCommandNullConnection()
|
||||
{
|
||||
// Setup: Create a row delete
|
||||
var columns = Common.GetColumns(false);
|
||||
var rs = Common.GetResultSet(columns, false);
|
||||
var etm = Common.GetMetadata(columns);
|
||||
RowDelete rd = new RowDelete(0, rs, etm);
|
||||
|
||||
// If: I attempt to create a command with a null connection
|
||||
// Then: It should throw an exception
|
||||
Assert.Throws<ArgumentNullException>(() => rd.GetCommand(null));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SetCell()
|
||||
{
|
||||
|
||||
@@ -9,6 +9,7 @@ using System.Data.Common;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SqlTools.ServiceLayer.EditData;
|
||||
using Microsoft.SqlTools.ServiceLayer.EditData.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement;
|
||||
@@ -99,13 +100,104 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
rt.ValidateWhereClauseNoKeys();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SortingByTypeTest()
|
||||
{
|
||||
// Setup: Create a result set and metadata we can reuse
|
||||
var cols = Common.GetColumns(false);
|
||||
var rs = Common.GetResultSet(cols, false);
|
||||
var etm = Common.GetMetadata(cols);
|
||||
|
||||
// If: I request to sort a list of the three different edit operations
|
||||
List<RowEditBase> rowEdits = new List<RowEditBase>
|
||||
{
|
||||
new RowDelete(0, rs, etm),
|
||||
new RowUpdate(0, rs, etm),
|
||||
new RowCreate(0, rs, etm)
|
||||
};
|
||||
rowEdits.Sort();
|
||||
|
||||
// Then: Delete should be the last operation to execute
|
||||
// (we don't care about the order of the other two)
|
||||
Assert.IsType<RowDelete>(rowEdits.Last());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SortingUpdatesByRowIdTest()
|
||||
{
|
||||
// Setup: Create a result set and metadata we can reuse
|
||||
var cols = Common.GetColumns(false);
|
||||
var rs = Common.GetResultSet(cols, false, 4);
|
||||
var etm = Common.GetMetadata(cols);
|
||||
|
||||
// If: I sort 3 edit operations of the same type
|
||||
List<RowEditBase> rowEdits = new List<RowEditBase>
|
||||
{
|
||||
new RowUpdate(3, rs, etm),
|
||||
new RowUpdate(1, rs, etm),
|
||||
new RowUpdate(2, rs, etm)
|
||||
};
|
||||
rowEdits.Sort();
|
||||
|
||||
// Then: They should be in order by row ID ASCENDING
|
||||
Assert.Equal(1, rowEdits[0].RowId);
|
||||
Assert.Equal(2, rowEdits[1].RowId);
|
||||
Assert.Equal(3, rowEdits[2].RowId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SortingCreatesByRowIdTest()
|
||||
{
|
||||
// Setup: Create a result set and metadata we can reuse
|
||||
var cols = Common.GetColumns(false);
|
||||
var rs = Common.GetResultSet(cols, false);
|
||||
var etm = Common.GetMetadata(cols);
|
||||
|
||||
// If: I sort 3 edit operations of the same type
|
||||
List<RowEditBase> rowEdits = new List<RowEditBase>
|
||||
{
|
||||
new RowCreate(3, rs, etm),
|
||||
new RowCreate(1, rs, etm),
|
||||
new RowCreate(2, rs, etm)
|
||||
};
|
||||
rowEdits.Sort();
|
||||
|
||||
// Then: They should be in order by row ID ASCENDING
|
||||
Assert.Equal(1, rowEdits[0].RowId);
|
||||
Assert.Equal(2, rowEdits[1].RowId);
|
||||
Assert.Equal(3, rowEdits[2].RowId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SortingDeletesByRowIdTest()
|
||||
{
|
||||
// Setup: Create a result set and metadata we can reuse
|
||||
var cols = Common.GetColumns(false);
|
||||
var rs = Common.GetResultSet(cols, false);
|
||||
var etm = Common.GetMetadata(cols);
|
||||
|
||||
// If: I sort 3 delete operations of the same type
|
||||
List<RowEditBase> rowEdits = new List<RowEditBase>
|
||||
{
|
||||
new RowDelete(1, rs, etm),
|
||||
new RowDelete(3, rs, etm),
|
||||
new RowDelete(2, rs, etm)
|
||||
};
|
||||
rowEdits.Sort();
|
||||
|
||||
// Then: They should be in order by row ID DESCENDING
|
||||
Assert.Equal(3, rowEdits[0].RowId);
|
||||
Assert.Equal(2, rowEdits[1].RowId);
|
||||
Assert.Equal(1, rowEdits[2].RowId);
|
||||
}
|
||||
|
||||
private static ResultSet GetResultSet(DbColumn[] columns, object[] row)
|
||||
{
|
||||
object[][] rows = {row};
|
||||
var testResultSet = new TestResultSet(columns, rows);
|
||||
var testReader = new TestDbDataReader(new [] {testResultSet});
|
||||
var resultSet = new ResultSet(testReader, 0,0, MemoryFileSystem.GetFileStreamFactory());
|
||||
resultSet.ReadResultToEnd(CancellationToken.None).Wait();
|
||||
var resultSet = new ResultSet(0,0, MemoryFileSystem.GetFileStreamFactory());
|
||||
resultSet.ReadResultToEnd(testReader, CancellationToken.None).Wait();
|
||||
return resultSet;
|
||||
}
|
||||
|
||||
@@ -179,6 +271,18 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override Task ApplyChanges(DbDataReader reader)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override DbCommand GetCommand(DbConnection conn)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected override int SortId => 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,11 +3,14 @@
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Data.Common;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SqlTools.ServiceLayer.EditData;
|
||||
using Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement;
|
||||
using Microsoft.SqlTools.ServiceLayer.QueryExecution;
|
||||
using Microsoft.SqlTools.ServiceLayer.UnitTests.Utility;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
@@ -69,12 +72,12 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public void GetScriptTest(bool isHekaton)
|
||||
public void GetScriptTest(bool isMemoryOptimized)
|
||||
{
|
||||
// Setup: Create a fake table to update
|
||||
DbColumn[] columns = Common.GetColumns(true);
|
||||
ResultSet rs = Common.GetResultSet(columns, true);
|
||||
IEditTableMetadata etm = Common.GetMetadata(columns, false, isHekaton);
|
||||
IEditTableMetadata etm = Common.GetMetadata(columns, false, isMemoryOptimized);
|
||||
|
||||
// If: I ask for a script to be generated for update
|
||||
RowUpdate ru = new RowUpdate(0, rs, etm);
|
||||
@@ -86,7 +89,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
Assert.NotNull(script);
|
||||
|
||||
// ... It should be formatted as an update script
|
||||
string regexString = isHekaton
|
||||
string regexString = isMemoryOptimized
|
||||
? @"UPDATE (.+) WITH \(SNAPSHOT\) SET (.*) WHERE .+"
|
||||
: @"UPDATE (.+) SET (.*) WHERE .+";
|
||||
Regex r = new Regex(regexString);
|
||||
@@ -101,5 +104,117 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
Assert.Equal(3, updateSplit.Length);
|
||||
Assert.All(updateSplit, s => Assert.Equal(2, s.Split('=').Length));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true, true)]
|
||||
[InlineData(true, false)]
|
||||
[InlineData(false, true)]
|
||||
[InlineData(false, false)]
|
||||
public void GetCommand(bool includeIdentity, bool isMemoryOptimized)
|
||||
{
|
||||
// Setup:
|
||||
// ... Create a row update with cell updates
|
||||
var columns = Common.GetColumns(includeIdentity);
|
||||
var rs = Common.GetResultSet(columns, includeIdentity);
|
||||
var etm = Common.GetMetadata(columns, !includeIdentity, isMemoryOptimized);
|
||||
RowUpdate ru = new RowUpdate(0, rs, etm);
|
||||
Common.AddCells(ru, includeIdentity);
|
||||
|
||||
// ... Mock db connection for building the command
|
||||
var mockConn = new TestSqlConnection(null);
|
||||
|
||||
// If: I ask for a command to be generated for update
|
||||
DbCommand cmd = ru.GetCommand(mockConn);
|
||||
|
||||
// Then:
|
||||
// ... The command should not be null
|
||||
Assert.NotNull(cmd);
|
||||
|
||||
// ... There should be an appropriate number of parameters in it
|
||||
// (1 or 3 keys, 3 value parameters)
|
||||
int expectedKeys = includeIdentity ? 1 : 3;
|
||||
Assert.Equal(expectedKeys + 3, cmd.Parameters.Count);
|
||||
|
||||
// ... It should be formatted into an update script with output
|
||||
string regexFormat = isMemoryOptimized
|
||||
? @"UPDATE (.+) WITH \(SNAPSHOT\) SET (.+) OUTPUT (.+) WHERE (.+)"
|
||||
: @"UPDATE (.+) SET (.+) OUTPUT(.+) WHERE (.+)";
|
||||
Regex r = new Regex(regexFormat);
|
||||
var m = r.Match(cmd.CommandText);
|
||||
Assert.True(m.Success);
|
||||
|
||||
// ... There should be a table
|
||||
string tbl = m.Groups[1].Value;
|
||||
Assert.Equal(etm.EscapedMultipartName, tbl);
|
||||
|
||||
// ... There should be 3 parameters for input
|
||||
string[] inCols = m.Groups[2].Value.Split(',');
|
||||
Assert.Equal(3, inCols.Length);
|
||||
Assert.All(inCols, s => Assert.Matches(@"\[.+\] = @Value\d+", s));
|
||||
|
||||
// ... There should be 3 OR 4 columns for output
|
||||
string[] outCols = m.Groups[3].Value.Split(',');
|
||||
Assert.Equal(includeIdentity ? 4 : 3, outCols.Length);
|
||||
Assert.All(outCols, s => Assert.StartsWith("inserted.", s.Trim()));
|
||||
|
||||
// ... There should be 1 OR 3 columns for where components
|
||||
string[] whereComponents = m.Groups[4].Value.Split(new[] {"AND"}, StringSplitOptions.None);
|
||||
Assert.Equal(expectedKeys, whereComponents.Length);
|
||||
Assert.All(whereComponents, s => Assert.Matches(@"\(.+ = @Param\d+\)", s));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetCommandNullConnection()
|
||||
{
|
||||
// Setup: Create a row create
|
||||
var columns = Common.GetColumns(false);
|
||||
var rs = Common.GetResultSet(columns, false);
|
||||
var etm = Common.GetMetadata(columns);
|
||||
RowUpdate rc = new RowUpdate(0, rs, etm);
|
||||
|
||||
// If: I attempt to create a command with a null connection
|
||||
// Then: It should throw an exception
|
||||
Assert.Throws<ArgumentNullException>(() => rc.GetCommand(null));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public async Task ApplyChanges(bool includeIdentity)
|
||||
{
|
||||
// Setup:
|
||||
// ... Create a row update (no cell updates needed)
|
||||
var columns = Common.GetColumns(includeIdentity);
|
||||
var rs = Common.GetResultSet(columns, includeIdentity);
|
||||
var etm = Common.GetMetadata(columns, !includeIdentity);
|
||||
RowUpdate ru = new RowUpdate(0, rs, etm);
|
||||
long oldBytesWritten = rs.totalBytesWritten;
|
||||
|
||||
// ... Setup a db reader for the result of an update
|
||||
var newRowReader = Common.GetNewRowDataReader(columns, includeIdentity);
|
||||
|
||||
// If: I ask for the change to be applied
|
||||
await ru.ApplyChanges(newRowReader);
|
||||
|
||||
// Then:
|
||||
// ... The result set should have the same number of rows as before
|
||||
Assert.Equal(1, rs.RowCount);
|
||||
Assert.True(oldBytesWritten < rs.totalBytesWritten);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ApplyChangesNullReader()
|
||||
{
|
||||
// Setup:
|
||||
// ... Create a row update (no cell updates needed)
|
||||
var columns = Common.GetColumns(true);
|
||||
var rs = Common.GetResultSet(columns, true);
|
||||
var etm = Common.GetMetadata(columns, false);
|
||||
RowUpdate ru = new RowUpdate(0, rs, etm);
|
||||
|
||||
// If: I ask for the changes to be applied with a null db reader
|
||||
// Then: I should get an exception
|
||||
await Assert.ThrowsAsync<ArgumentNullException>(() => ru.ApplyChanges(null));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
{
|
||||
public class ServiceIntegrationTests
|
||||
{
|
||||
#region Session Operation Helper Tests
|
||||
#region EditSession Operation Helper Tests
|
||||
|
||||
[Theory]
|
||||
[InlineData(null)]
|
||||
@@ -128,7 +128,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
efv.Validate();
|
||||
|
||||
// ... There should be a delete in the session
|
||||
Session s = eds.ActiveSessions[Constants.OwnerUri];
|
||||
EditSession s = eds.ActiveSessions[Constants.OwnerUri];
|
||||
Assert.True(s.EditCache.Any(e => e.Value is RowDelete));
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
efv.Validate();
|
||||
|
||||
// ... There should be a create in the session
|
||||
Session s = eds.ActiveSessions[Constants.OwnerUri];
|
||||
EditSession s = eds.ActiveSessions[Constants.OwnerUri];
|
||||
Assert.True(s.EditCache.Any(e => e.Value is RowCreate));
|
||||
}
|
||||
|
||||
@@ -174,7 +174,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
efv.Validate();
|
||||
|
||||
// ... The edit cache should be empty again
|
||||
Session s = eds.ActiveSessions[Constants.OwnerUri];
|
||||
EditSession s = eds.ActiveSessions[Constants.OwnerUri];
|
||||
Assert.Empty(s.EditCache);
|
||||
}
|
||||
|
||||
@@ -215,13 +215,13 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
edit.Verify(e => e.SetCell(It.IsAny<int>(), It.IsAny<string>()), Times.Once);
|
||||
}
|
||||
|
||||
private static Session GetDefaultSession()
|
||||
private static EditSession GetDefaultSession()
|
||||
{
|
||||
// ... Create a session with a proper query and metadata
|
||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
||||
IEditTableMetadata etm = Common.GetMetadata(rs.Columns);
|
||||
Session s = new Session(rs, etm);
|
||||
EditSession s = new EditSession(rs, etm);
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.Common;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SqlTools.ServiceLayer.Connection;
|
||||
using Microsoft.SqlTools.ServiceLayer.EditData;
|
||||
using Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement;
|
||||
@@ -28,7 +29,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
{
|
||||
// If: I create a session object without a null query
|
||||
// Then: It should throw an exception
|
||||
Assert.Throws<ArgumentNullException>(() => new Session(null, Common.GetMetadata(new DbColumn[] {})));
|
||||
Assert.Throws<ArgumentNullException>(() => new EditSession(null, Common.GetMetadata(new DbColumn[] {})));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -38,7 +39,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
// Then: It should throw an exception
|
||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
||||
Assert.Throws<ArgumentNullException>(() => new Session(rs, null));
|
||||
Assert.Throws<ArgumentNullException>(() => new EditSession(rs, null));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -48,12 +49,13 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
||||
IEditTableMetadata etm = Common.GetMetadata(rs.Columns);
|
||||
Session s = new Session(rs, etm);
|
||||
EditSession s = new EditSession(rs, etm);
|
||||
|
||||
// Then:
|
||||
// ... The edit cache should exist and be empty
|
||||
Assert.NotNull(s.EditCache);
|
||||
Assert.Empty(s.EditCache);
|
||||
Assert.Null(s.CommitTask);
|
||||
|
||||
// ... The next row ID should be equivalent to the number of rows in the result set
|
||||
Assert.Equal(q.Batches[0].ResultSets[0].RowCount, s.NextRowId);
|
||||
@@ -70,7 +72,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
// Then: It should throw an exception
|
||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
||||
q.HasExecuted = false;
|
||||
Assert.Throws<InvalidOperationException>(() => Session.ValidateQueryForSession(q));
|
||||
Assert.Throws<InvalidOperationException>(() => EditSession.ValidateQueryForSession(q));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -94,7 +96,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
|
||||
// If: I create a session object with a query that has !=1 result sets
|
||||
// Then: It should throw an exception
|
||||
Assert.Throws<InvalidOperationException>(() => Session.ValidateQueryForSession(query));
|
||||
Assert.Throws<InvalidOperationException>(() => EditSession.ValidateQueryForSession(query));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -102,7 +104,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
{
|
||||
// If: I validate a query for a session with a valid query
|
||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
||||
ResultSet rs = Session.ValidateQueryForSession(q);
|
||||
ResultSet rs = EditSession.ValidateQueryForSession(q);
|
||||
|
||||
// Then: I should get the only result set back
|
||||
Assert.NotNull(rs);
|
||||
@@ -121,7 +123,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
||||
IEditTableMetadata etm = Common.GetMetadata(rs.Columns);
|
||||
Session s = new Session(rs, etm);
|
||||
EditSession s = new EditSession(rs, etm);
|
||||
|
||||
// ... Add a mock edit to the edit cache to cause the .TryAdd to fail
|
||||
var mockEdit = new Mock<RowEditBase>().Object;
|
||||
@@ -146,7 +148,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
||||
IEditTableMetadata etm = Common.GetMetadata(rs.Columns);
|
||||
Session s = new Session(rs, etm);
|
||||
EditSession s = new EditSession(rs, etm);
|
||||
|
||||
// If: I add a row to the session
|
||||
long newId = s.CreateRow();
|
||||
@@ -167,13 +169,13 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RowIdOutOfRangeData))]
|
||||
public void RowIdOutOfRange(long rowId, Action<Session, long> testAction)
|
||||
public void RowIdOutOfRange(long rowId, Action<EditSession, long> testAction)
|
||||
{
|
||||
// Setup: Create a session with a proper query and metadata
|
||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
||||
IEditTableMetadata etm = Common.GetMetadata(rs.Columns);
|
||||
Session s = new Session(rs, etm);
|
||||
EditSession s = new EditSession(rs, etm);
|
||||
|
||||
// If: I delete a row that is out of range for the result set
|
||||
// Then: I should get an exception
|
||||
@@ -185,12 +187,12 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
get
|
||||
{
|
||||
// Delete Row
|
||||
Action<Session, 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[] { 100L, delAction };
|
||||
|
||||
// Update Cell
|
||||
Action<Session, 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[] { 100L, upAction };
|
||||
}
|
||||
@@ -206,7 +208,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
||||
IEditTableMetadata etm = Common.GetMetadata(rs.Columns);
|
||||
Session s = new Session(rs, etm);
|
||||
EditSession s = new EditSession(rs, etm);
|
||||
|
||||
// ... Add a mock edit to the edit cache to cause the .TryAdd to fail
|
||||
var mockEdit = new Mock<RowEditBase>().Object;
|
||||
@@ -228,7 +230,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
||||
IEditTableMetadata etm = Common.GetMetadata(rs.Columns);
|
||||
Session s = new Session(rs, etm);
|
||||
EditSession s = new EditSession(rs, etm);
|
||||
|
||||
// If: I add a row to the session
|
||||
s.DeleteRow(0);
|
||||
@@ -249,7 +251,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
||||
IEditTableMetadata etm = Common.GetMetadata(rs.Columns);
|
||||
Session s = new Session(rs, etm);
|
||||
EditSession s = new EditSession(rs, etm);
|
||||
|
||||
// If: I revert a row that doesn't have any pending changes
|
||||
// Then: I should get an exception
|
||||
@@ -264,7 +266,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
||||
IEditTableMetadata etm = Common.GetMetadata(rs.Columns);
|
||||
Session s = new Session(rs, etm);
|
||||
EditSession s = new EditSession(rs, etm);
|
||||
|
||||
// ... Add a mock edit to the edit cache to cause the .TryAdd to fail
|
||||
var mockEdit = new Mock<RowEditBase>().Object;
|
||||
@@ -290,7 +292,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
||||
IEditTableMetadata etm = Common.GetMetadata(rs.Columns);
|
||||
Session s = new Session(rs, etm);
|
||||
EditSession s = new EditSession(rs, etm);
|
||||
|
||||
// ... Add a mock edit to the edit cache to cause the .TryAdd to fail
|
||||
var mockEdit = new Mock<RowEditBase>();
|
||||
@@ -314,7 +316,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
||||
IEditTableMetadata etm = Common.GetMetadata(rs.Columns);
|
||||
Session s = new Session(rs, etm);
|
||||
EditSession s = new EditSession(rs, etm);
|
||||
|
||||
// If: I update a cell on a row that does not have a pending edit
|
||||
s.UpdateCell(0, 0, "");
|
||||
@@ -339,7 +341,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
||||
IEditTableMetadata etm = Common.GetMetadata(rs.Columns);
|
||||
Session s = new Session(rs, etm);
|
||||
EditSession s = new EditSession(rs, etm);
|
||||
|
||||
// If: I try to script the edit cache with a null or whitespace output path
|
||||
// Then: It should throw an exception
|
||||
@@ -354,7 +356,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
||||
IEditTableMetadata etm = Common.GetMetadata(rs.Columns);
|
||||
Session s = new Session(rs, etm);
|
||||
EditSession s = new EditSession(rs, etm);
|
||||
|
||||
// ... Add two mock edits that will generate a script
|
||||
Mock<RowEditBase> edit = new Mock<RowEditBase>();
|
||||
@@ -377,5 +379,163 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Commit Tests
|
||||
|
||||
[Fact]
|
||||
public void CommitNullConnection()
|
||||
{
|
||||
// Setup: Create a basic session
|
||||
EditSession s = GetBasicSession();
|
||||
|
||||
// If: I attempt to commit with a null connection
|
||||
// Then: I should get an exception
|
||||
Assert.Throws<ArgumentNullException>(
|
||||
() => s.CommitEdits(null, () => Task.CompletedTask, e => Task.CompletedTask));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CommitNullSuccessHandler()
|
||||
{
|
||||
// Setup:
|
||||
// ... Create a basic session
|
||||
EditSession s = GetBasicSession();
|
||||
|
||||
// ... Mock db connection
|
||||
DbConnection conn = new TestSqlConnection(null);
|
||||
|
||||
// If: I attempt to commit with a null success handler
|
||||
// Then: I should get an exception
|
||||
Assert.Throws<ArgumentNullException>(() => s.CommitEdits(conn, null, e => Task.CompletedTask));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CommitNullFailureHandler()
|
||||
{
|
||||
// Setup:
|
||||
// ... Create a basic session
|
||||
EditSession s = GetBasicSession();
|
||||
|
||||
// ... Mock db connection
|
||||
DbConnection conn = new TestSqlConnection(null);
|
||||
|
||||
// If: I attempt to commit with a null success handler
|
||||
// Then: I should get an exception
|
||||
Assert.Throws<ArgumentNullException>(() => s.CommitEdits(conn, () => Task.CompletedTask, null));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CommitInProgress()
|
||||
{
|
||||
// Setup:
|
||||
// ... Basic session and db connection
|
||||
EditSession s = GetBasicSession();
|
||||
DbConnection conn = new TestSqlConnection(null);
|
||||
|
||||
// ... Mock a task that has not completed
|
||||
Task notCompleted = new Task(() => {});
|
||||
s.CommitTask = notCompleted;
|
||||
|
||||
// If: I attempt to commit while a task is in progress
|
||||
// Then: I should get an exception
|
||||
Assert.Throws<InvalidOperationException>(
|
||||
() => s.CommitEdits(conn, () => Task.CompletedTask, e => Task.CompletedTask));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CommitSuccess()
|
||||
{
|
||||
// Setup:
|
||||
// ... Basic session and db connection
|
||||
EditSession s = GetBasicSession();
|
||||
DbConnection conn = new TestSqlConnection(null);
|
||||
|
||||
// ... Add a mock commands for fun
|
||||
Mock<RowEditBase> edit = new Mock<RowEditBase>();
|
||||
edit.Setup(e => e.GetCommand(It.IsAny<DbConnection>())).Returns<DbConnection>(dbc => dbc.CreateCommand());
|
||||
edit.Setup(e => e.ApplyChanges(It.IsAny<DbDataReader>())).Returns(Task.FromResult(0));
|
||||
s.EditCache[0] = edit.Object;
|
||||
|
||||
// If: I commit these changes (and await completion)
|
||||
bool successCalled = false;
|
||||
bool failureCalled = false;
|
||||
s.CommitEdits(conn,
|
||||
() => {
|
||||
successCalled = true;
|
||||
return Task.FromResult(0);
|
||||
},
|
||||
e => {
|
||||
failureCalled = true;
|
||||
return Task.FromResult(0);
|
||||
});
|
||||
await s.CommitTask;
|
||||
|
||||
// Then:
|
||||
// ... The task should still exist
|
||||
Assert.NotNull(s.CommitTask);
|
||||
|
||||
// ... The success handler should have been called (not failure)
|
||||
Assert.True(successCalled);
|
||||
Assert.False(failureCalled);
|
||||
|
||||
// ... The mock edit should have generated a command and applied changes
|
||||
edit.Verify(e => e.GetCommand(conn), Times.Once);
|
||||
edit.Verify(e => e.ApplyChanges(It.IsAny<DbDataReader>()), Times.Once);
|
||||
|
||||
// ... The edit cache should be empty
|
||||
Assert.Empty(s.EditCache);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CommitFailure()
|
||||
{
|
||||
// Setup:
|
||||
// ... Basic session and db connection
|
||||
EditSession s = GetBasicSession();
|
||||
DbConnection conn = new TestSqlConnection(null);
|
||||
|
||||
// ... Add a mock edit that will explode on generating a command
|
||||
Mock<RowEditBase> edit = new Mock<RowEditBase>();
|
||||
edit.Setup(e => e.GetCommand(It.IsAny<DbConnection>())).Throws<Exception>();
|
||||
s.EditCache[0] = edit.Object;
|
||||
|
||||
// If: I commit these changes (and await completion)
|
||||
bool successCalled = false;
|
||||
bool failureCalled = false;
|
||||
s.CommitEdits(conn,
|
||||
() => {
|
||||
successCalled = true;
|
||||
return Task.FromResult(0);
|
||||
},
|
||||
e => {
|
||||
failureCalled = true;
|
||||
return Task.FromResult(0);
|
||||
});
|
||||
await s.CommitTask;
|
||||
|
||||
// Then:
|
||||
// ... The task should still exist
|
||||
Assert.NotNull(s.CommitTask);
|
||||
|
||||
// ... The error handler should have been called (not success)
|
||||
Assert.False(successCalled);
|
||||
Assert.True(failureCalled);
|
||||
|
||||
// ... The mock edit should have been asked to generate a command
|
||||
edit.Verify(e => e.GetCommand(conn), Times.Once);
|
||||
|
||||
// ... The edit cache should not be empty
|
||||
Assert.NotEmpty(s.EditCache);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private static EditSession GetBasicSession()
|
||||
{
|
||||
Query q = QueryExecution.Common.GetBasicExecutedQuery();
|
||||
ResultSet rs = q.Batches[0].ResultSets[0];
|
||||
IEditTableMetadata etm = Common.GetMetadata(rs.Columns);
|
||||
return new EditSession(rs, etm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,10 +24,9 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution
|
||||
{
|
||||
// Setup: Mock file stream factory, mock db reader
|
||||
var mockFileStreamFactory = new Mock<IFileStreamFactory>();
|
||||
var mockDataReader = Common.CreateTestConnection(null, false).CreateCommand().ExecuteReaderAsync().Result;
|
||||
|
||||
// If: I setup a single resultset and then dispose it
|
||||
ResultSet rs = new ResultSet(mockDataReader, Common.Ordinal, Common.Ordinal, mockFileStreamFactory.Object);
|
||||
ResultSet rs = new ResultSet(Common.Ordinal, Common.Ordinal, mockFileStreamFactory.Object);
|
||||
rs.Dispose();
|
||||
|
||||
// Then: The file that was created should have been deleted
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.Common;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
@@ -24,8 +25,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
|
||||
{
|
||||
// If:
|
||||
// ... I create a new result set with a valid db data reader
|
||||
DbDataReader mockReader = GetReader(null, false, string.Empty);
|
||||
ResultSet resultSet = new ResultSet(mockReader, Common.Ordinal, Common.Ordinal, MemoryFileSystem.GetFileStreamFactory());
|
||||
ResultSet resultSet = new ResultSet(Common.Ordinal, Common.Ordinal, MemoryFileSystem.GetFileStreamFactory());
|
||||
|
||||
// Then:
|
||||
// ... There should not be any data read yet
|
||||
@@ -41,14 +41,13 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ResultCreationInvalidReader()
|
||||
public async Task ReadToEndNullReader()
|
||||
{
|
||||
// If:
|
||||
// ... I create a new result set without a reader
|
||||
// Then:
|
||||
// ... It should throw an exception
|
||||
Assert.Throws<ArgumentNullException>(() => new ResultSet(null, Common.Ordinal, Common.Ordinal, null));
|
||||
|
||||
// If: I create a new result set with a null db data reader
|
||||
// Then: I should get an exception
|
||||
var fsf = MemoryFileSystem.GetFileStreamFactory();
|
||||
ResultSet resultSet = new ResultSet(Common.Ordinal, Common.Ordinal, fsf);
|
||||
await Assert.ThrowsAsync<ArgumentNullException>(() => resultSet.ReadResultToEnd(null, CancellationToken.None));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -67,9 +66,9 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
|
||||
// ... and I read it to the end
|
||||
DbDataReader mockReader = GetReader(Common.StandardTestDataSet, false, Constants.StandardQuery);
|
||||
var fileStreamFactory = MemoryFileSystem.GetFileStreamFactory();
|
||||
ResultSet resultSet = new ResultSet(mockReader, Common.Ordinal, Common.Ordinal, fileStreamFactory);
|
||||
ResultSet resultSet = new ResultSet(Common.Ordinal, Common.Ordinal, fileStreamFactory);
|
||||
resultSet.ResultCompletion += callback;
|
||||
await resultSet.ReadResultToEnd(CancellationToken.None);
|
||||
await resultSet.ReadResultToEnd(mockReader, CancellationToken.None);
|
||||
|
||||
// Then:
|
||||
// ... The columns should be set
|
||||
@@ -86,7 +85,35 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
|
||||
// ... The callback for result set completion should have been fired
|
||||
Assert.NotNull(resultSummaryFromCallback);
|
||||
}
|
||||
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(CallMethodWithoutReadingData))]
|
||||
public void CallMethodWithoutReading(Action<ResultSet> testMethod)
|
||||
{
|
||||
// Setup: Create a new result set with valid db data reader
|
||||
var fileStreamFactory = MemoryFileSystem.GetFileStreamFactory();
|
||||
ResultSet resultSet = new ResultSet(Common.Ordinal, Common.Ordinal, fileStreamFactory);
|
||||
|
||||
// If:
|
||||
// ... I have a result set that has not been read
|
||||
// ... and I attempt to call a method on it
|
||||
// Then: It should throw an exception
|
||||
Assert.ThrowsAny<Exception>(() => testMethod(resultSet));
|
||||
}
|
||||
|
||||
public static IEnumerable<object> CallMethodWithoutReadingData
|
||||
{
|
||||
get
|
||||
{
|
||||
yield return new object[] {new Action<ResultSet>(rs => rs.GetSubset(0, 0).Wait())};
|
||||
yield return new object[] {new Action<ResultSet>(rs => rs.UpdateRow(0, null).Wait())};
|
||||
yield return new object[] {new Action<ResultSet>(rs => rs.AddRow(null).Wait())};
|
||||
yield return new object[] {new Action<ResultSet>(rs => rs.RemoveRow(0))};
|
||||
yield return new object[] {new Action<ResultSet>(rs => rs.GetRow(0))};
|
||||
yield return new object[] {new Action<ResultSet>(rs => rs.GetExecutionPlan().Wait())};
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("JSON")]
|
||||
[InlineData("XML")]
|
||||
@@ -111,9 +138,9 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
|
||||
// ... and I read it to the end
|
||||
DbDataReader mockReader = GetReader(dataSets, false, Constants.StandardQuery);
|
||||
var fileStreamFactory = MemoryFileSystem.GetFileStreamFactory();
|
||||
ResultSet resultSet = new ResultSet(mockReader, Common.Ordinal, Common.Ordinal, fileStreamFactory);
|
||||
ResultSet resultSet = new ResultSet(Common.Ordinal, Common.Ordinal, fileStreamFactory);
|
||||
resultSet.ResultCompletion += callback;
|
||||
await resultSet.ReadResultToEnd(CancellationToken.None);
|
||||
await resultSet.ReadResultToEnd(mockReader, CancellationToken.None);
|
||||
|
||||
// Then:
|
||||
// ... There should only be one column
|
||||
@@ -133,20 +160,6 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
|
||||
Assert.Equal(1, subset.RowCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetSubsetWithoutExecution()
|
||||
{
|
||||
// If:
|
||||
// ... I create a new result set with a valid db data reader without executing it
|
||||
DbDataReader mockReader = GetReader(null, false, string.Empty);
|
||||
var fileStreamFactory = MemoryFileSystem.GetFileStreamFactory();
|
||||
ResultSet resultSet = new ResultSet(mockReader, Common.Ordinal, Common.Ordinal, fileStreamFactory);
|
||||
|
||||
// Then:
|
||||
// ... Attempting to read a subset should fail miserably
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => resultSet.GetSubset(0, 0));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(-1, 0)] // Too small start row
|
||||
[InlineData(20, 0)] // Too large start row
|
||||
@@ -158,8 +171,8 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
|
||||
// ... And execute the result
|
||||
DbDataReader mockReader = GetReader(Common.StandardTestDataSet, false, Constants.StandardQuery);
|
||||
var fileStreamFactory = MemoryFileSystem.GetFileStreamFactory();
|
||||
ResultSet resultSet = new ResultSet(mockReader, Common.Ordinal, Common.Ordinal, fileStreamFactory);
|
||||
await resultSet.ReadResultToEnd(CancellationToken.None);
|
||||
ResultSet resultSet = new ResultSet(Common.Ordinal, Common.Ordinal, fileStreamFactory);
|
||||
await resultSet.ReadResultToEnd(mockReader, CancellationToken.None);
|
||||
|
||||
// ... And attempt to get a subset with invalid parameters
|
||||
// Then:
|
||||
@@ -179,8 +192,8 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
|
||||
// ... And execute the result set
|
||||
DbDataReader mockReader = GetReader(Common.StandardTestDataSet, false, Constants.StandardQuery);
|
||||
var fileStreamFactory = MemoryFileSystem.GetFileStreamFactory();
|
||||
ResultSet resultSet = new ResultSet(mockReader, Common.Ordinal, Common.Ordinal, fileStreamFactory);
|
||||
await resultSet.ReadResultToEnd(CancellationToken.None);
|
||||
ResultSet resultSet = new ResultSet(Common.Ordinal, Common.Ordinal, fileStreamFactory);
|
||||
await resultSet.ReadResultToEnd(mockReader, CancellationToken.None);
|
||||
|
||||
// ... And attempt to get a subset with valid number of rows
|
||||
ResultSetSubset subset = await resultSet.GetSubset(startRow, rowCount);
|
||||
@@ -195,6 +208,159 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
|
||||
Assert.Equal(resultSet.Columns.Length, subset.Rows[0].Length);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RowInvalidParameterData))]
|
||||
public async Task RowInvalidParameter(Action<ResultSet> actionToPerform)
|
||||
{
|
||||
// If: I create a new result set and execute it
|
||||
var mockReader = GetReader(Common.StandardTestDataSet, false, Constants.StandardQuery);
|
||||
var fileStreamFactory = MemoryFileSystem.GetFileStreamFactory();
|
||||
ResultSet resultSet = new ResultSet(Common.Ordinal, Common.Ordinal, fileStreamFactory);
|
||||
await resultSet.ReadResultToEnd(mockReader, CancellationToken.None);
|
||||
|
||||
// Then: Attempting to read an invalid row should fail
|
||||
Assert.ThrowsAny<Exception>(() => actionToPerform(resultSet));
|
||||
}
|
||||
|
||||
public static IEnumerable<object> RowInvalidParameterData
|
||||
{
|
||||
get
|
||||
{
|
||||
foreach (var method in RowInvalidParameterMethods)
|
||||
{
|
||||
yield return new object[] {new Action<ResultSet>(rs => method(rs, -1))};
|
||||
yield return new object[] {new Action<ResultSet>(rs => method(rs, 100))};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<Action<ResultSet, long>> RowInvalidParameterMethods
|
||||
{
|
||||
get
|
||||
{
|
||||
yield return (rs, id) => rs.RemoveRow(id);
|
||||
yield return (rs, id) => rs.GetRow(id);
|
||||
yield return (rs, id) => rs.UpdateRow(id, null).Wait();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task RemoveRowSuccess()
|
||||
{
|
||||
// Setup: Create a result set that has the standard data set on it
|
||||
var fileFactory = MemoryFileSystem.GetFileStreamFactory();
|
||||
var mockReader = GetReader(Common.StandardTestDataSet, false, Constants.StandardQuery);
|
||||
ResultSet resultSet = new ResultSet(Common.Ordinal, Common.Ordinal, fileFactory);
|
||||
await resultSet.ReadResultToEnd(mockReader, CancellationToken.None);
|
||||
|
||||
// If: I delete a row from the result set
|
||||
resultSet.RemoveRow(0);
|
||||
|
||||
// Then:
|
||||
// ... The row count should decrease
|
||||
// ... The last row should have moved up by 1
|
||||
Assert.Equal(Common.StandardRows - 1, resultSet.RowCount);
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => resultSet.GetRow(Common.StandardRows - 1));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AddRowNoRows()
|
||||
{
|
||||
// Setup:
|
||||
// ... Create a standard result set with standard data
|
||||
var fileFactory = MemoryFileSystem.GetFileStreamFactory();
|
||||
var mockReader = GetReader(Common.StandardTestDataSet, false, Constants.StandardQuery);
|
||||
ResultSet resultSet = new ResultSet(Common.Ordinal, Common.Ordinal, fileFactory);
|
||||
await resultSet.ReadResultToEnd(mockReader, CancellationToken.None);
|
||||
|
||||
// ... Create a mock reader that has no rows
|
||||
var emptyReader = GetReader(new[] {new TestResultSet(5, 0)}, false, Constants.StandardQuery);
|
||||
|
||||
// If: I add a row with a reader that has no rows
|
||||
// Then:
|
||||
// ... I should get an exception
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => resultSet.AddRow(emptyReader));
|
||||
|
||||
// ... The row count should not have changed
|
||||
Assert.Equal(Common.StandardRows, resultSet.RowCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AddRowSuccess()
|
||||
{
|
||||
// Setup:
|
||||
// ... Create a standard result set with standard data
|
||||
var fileFactory = MemoryFileSystem.GetFileStreamFactory();
|
||||
var mockReader = GetReader(Common.StandardTestDataSet, false, Constants.StandardQuery);
|
||||
ResultSet resultSet = new ResultSet(Common.Ordinal, Common.Ordinal, fileFactory);
|
||||
await resultSet.ReadResultToEnd(mockReader, CancellationToken.None);
|
||||
|
||||
// ... Create a mock reader that has one row
|
||||
object[] row = Enumerable.Range(0, Common.StandardColumns).Select(i => "QQQ").ToArray();
|
||||
IEnumerable<object[]> rows = new List<object[]>{ row };
|
||||
TestResultSet[] results = {new TestResultSet(TestResultSet.GetStandardColumns(Common.StandardColumns), rows)};
|
||||
var newRowReader = GetReader(results, false, Constants.StandardQuery);
|
||||
|
||||
// If: I add a new row to the result set
|
||||
await resultSet.AddRow(newRowReader);
|
||||
|
||||
// Then:
|
||||
// ... There should be a new row in the list of rows
|
||||
Assert.Equal(Common.StandardRows + 1, resultSet.RowCount);
|
||||
|
||||
// ... The new row should be readable and all cells contain the test value
|
||||
Assert.All(resultSet.GetRow(Common.StandardRows), cell => Assert.Equal("QQQ", cell.RawObject));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task UpdateRowNoRows()
|
||||
{
|
||||
// Setup:
|
||||
// ... Create a standard result set with standard data
|
||||
var fileFactory = MemoryFileSystem.GetFileStreamFactory();
|
||||
var mockReader = GetReader(Common.StandardTestDataSet, false, Constants.StandardQuery);
|
||||
ResultSet resultSet = new ResultSet(Common.Ordinal, Common.Ordinal, fileFactory);
|
||||
await resultSet.ReadResultToEnd(mockReader, CancellationToken.None);
|
||||
|
||||
// ... Create a mock reader that has no rows
|
||||
var emptyReader = GetReader(new[] { new TestResultSet(5, 0) }, false, Constants.StandardQuery);
|
||||
|
||||
// If: I add a row with a reader that has no rows
|
||||
// Then:
|
||||
// ... I should get an exception
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => resultSet.UpdateRow(0, emptyReader));
|
||||
|
||||
// ... The row count should not have changed
|
||||
Assert.Equal(Common.StandardRows, resultSet.RowCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task UpdateRowSuccess()
|
||||
{
|
||||
// Setup:
|
||||
// ... Create a standard result set with standard data
|
||||
var fileFactory = MemoryFileSystem.GetFileStreamFactory();
|
||||
var mockReader = GetReader(Common.StandardTestDataSet, false, Constants.StandardQuery);
|
||||
ResultSet resultSet = new ResultSet(Common.Ordinal, Common.Ordinal, fileFactory);
|
||||
await resultSet.ReadResultToEnd(mockReader, CancellationToken.None);
|
||||
|
||||
// ... Create a mock reader that has one row
|
||||
object[] row = Enumerable.Range(0, Common.StandardColumns).Select(i => "QQQ").ToArray();
|
||||
IEnumerable<object[]> rows = new List<object[]> { row };
|
||||
TestResultSet[] results = { new TestResultSet(TestResultSet.GetStandardColumns(Common.StandardColumns), rows) };
|
||||
var newRowReader = GetReader(results, false, Constants.StandardQuery);
|
||||
|
||||
// If: I add a new row to the result set
|
||||
await resultSet.UpdateRow(0, newRowReader);
|
||||
|
||||
// Then:
|
||||
// ... There should be the same number of rows
|
||||
Assert.Equal(Common.StandardRows, resultSet.RowCount);
|
||||
|
||||
// ... The new row should be readable and all cells contain the test value
|
||||
Assert.All(resultSet.GetRow(0), cell => Assert.Equal("QQQ", cell.RawObject));
|
||||
}
|
||||
|
||||
private static DbDataReader GetReader(TestResultSet[] dataSet, bool throwOnRead, string query)
|
||||
{
|
||||
var info = Common.CreateTestConnectionInfo(dataSet, throwOnRead);
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.SaveResults
|
||||
// If: I attempt to save with a null set of params
|
||||
// Then: I should get a null argument exception
|
||||
ResultSet rs = new ResultSet(
|
||||
GetReader(null, false, Common.NoOpQuery), Common.Ordinal, Common.Ordinal,
|
||||
Common.Ordinal, Common.Ordinal,
|
||||
MemoryFileSystem.GetFileStreamFactory());
|
||||
Assert.Throws<ArgumentNullException>(() => rs.SaveAs(
|
||||
null,
|
||||
@@ -41,7 +41,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.SaveResults
|
||||
// If: I attempt to save with a null set of params
|
||||
// Then: I should get a null argument exception
|
||||
ResultSet rs = new ResultSet(
|
||||
GetReader(null, false, Common.NoOpQuery), Common.Ordinal, Common.Ordinal,
|
||||
Common.Ordinal, Common.Ordinal,
|
||||
MemoryFileSystem.GetFileStreamFactory());
|
||||
Assert.Throws<ArgumentNullException>(() => rs.SaveAs(
|
||||
new SaveResultsRequestParams(),
|
||||
@@ -54,7 +54,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.SaveResults
|
||||
// If: I attempt to save a result set that hasn't completed execution
|
||||
// Then: I should get an invalid operation exception
|
||||
ResultSet rs = new ResultSet(
|
||||
GetReader(null, false, Common.NoOpQuery), Common.Ordinal, Common.Ordinal,
|
||||
Common.Ordinal, Common.Ordinal,
|
||||
MemoryFileSystem.GetFileStreamFactory());
|
||||
Assert.Throws<InvalidOperationException>(() => rs.SaveAs(
|
||||
new SaveResultsRequestParams(),
|
||||
@@ -68,7 +68,6 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.SaveResults
|
||||
// Setup:
|
||||
// ... Create a result set that has been executed
|
||||
ResultSet rs = new ResultSet(
|
||||
GetReader(Common.StandardTestDataSet, false, Constants.StandardQuery),
|
||||
Common.Ordinal, Common.Ordinal,
|
||||
MemoryFileSystem.GetFileStreamFactory());
|
||||
|
||||
@@ -92,10 +91,9 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.SaveResults
|
||||
|
||||
// ... Create a result set with dummy data and read to the end
|
||||
ResultSet rs = new ResultSet(
|
||||
GetReader(Common.StandardTestDataSet, false, Constants.StandardQuery),
|
||||
Common.Ordinal, Common.Ordinal,
|
||||
resultFactory);
|
||||
await rs.ReadResultToEnd(CancellationToken.None);
|
||||
await rs.ReadResultToEnd(GetReader(Common.StandardTestDataSet, false, Constants.StandardQuery), CancellationToken.None);
|
||||
|
||||
// ... Create a mock writer for writing the save as file
|
||||
Mock<IFileStreamWriter> saveWriter = GetMockWriter();
|
||||
@@ -125,10 +123,9 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.SaveResults
|
||||
|
||||
// ... Create a result set with dummy data and read to the end
|
||||
ResultSet rs = new ResultSet(
|
||||
GetReader(Common.StandardTestDataSet, false, Constants.StandardQuery),
|
||||
Common.Ordinal, Common.Ordinal,
|
||||
resultFactory);
|
||||
await rs.ReadResultToEnd(CancellationToken.None);
|
||||
await rs.ReadResultToEnd(GetReader(Common.StandardTestDataSet, false, Constants.StandardQuery), CancellationToken.None);
|
||||
|
||||
// ... Create a mock writer for writing the save as file
|
||||
Mock<IFileStreamWriter> saveWriter = GetMockWriter();
|
||||
|
||||
@@ -64,7 +64,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution
|
||||
// ... I have a resultset that hasn't been executed and I request a valid result set from it
|
||||
// Then:
|
||||
// ... It should throw an exception for having not been read
|
||||
ResultSet rs = new ResultSet(new TestDbDataReader(null), Common.Ordinal, Common.Ordinal, MemoryFileSystem.GetFileStreamFactory());
|
||||
ResultSet rs = new ResultSet(Common.Ordinal, Common.Ordinal, MemoryFileSystem.GetFileStreamFactory());
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => rs.GetSubset(0, 1));
|
||||
}
|
||||
|
||||
|
||||
@@ -15,9 +15,14 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Utility
|
||||
public List<DbColumn> Columns;
|
||||
public List<object[]> Rows;
|
||||
|
||||
public static List<DbColumn> GetStandardColumns(int columnCount)
|
||||
{
|
||||
return Enumerable.Range(0, columnCount).Select(i => new TestDbColumn($"Col{i}")).Cast<DbColumn>().ToList();
|
||||
}
|
||||
|
||||
public TestResultSet(int columns, int rows)
|
||||
{
|
||||
Columns = Enumerable.Range(0, columns).Select(i => new TestDbColumn($"Col{i}")).Cast<DbColumn>().ToList();
|
||||
Columns = GetStandardColumns(columns);
|
||||
Rows = new List<object[]>(rows);
|
||||
for (int i = 0; i < rows; i++)
|
||||
{
|
||||
|
||||
@@ -4,12 +4,15 @@
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Data.Common;
|
||||
using System.Linq;
|
||||
using Microsoft.SqlTools.ServiceLayer.Connection;
|
||||
using Microsoft.SqlTools.ServiceLayer.Connection.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.LanguageServices;
|
||||
using Microsoft.SqlTools.ServiceLayer.Workspace.Contracts;
|
||||
using Moq;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Utility
|
||||
{
|
||||
@@ -98,6 +101,15 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Utility
|
||||
internal TestSqlCommand(TestResultSet[] data)
|
||||
{
|
||||
Data = data;
|
||||
|
||||
var mockParameterCollection = new Mock<DbParameterCollection>();
|
||||
mockParameterCollection.Setup(c => c.Add(It.IsAny<object>()))
|
||||
.Callback<object>(d => listParams.Add((DbParameter)d));
|
||||
mockParameterCollection.Setup(c => c.AddRange(It.IsAny<Array>()))
|
||||
.Callback<Array>(d => listParams.AddRange(d.Cast<DbParameter>()));
|
||||
mockParameterCollection.Setup(c => c.Count)
|
||||
.Returns(() => listParams.Count);
|
||||
DbParameterCollection = mockParameterCollection.Object;
|
||||
}
|
||||
|
||||
internal TestResultSet[] Data { get; set; }
|
||||
@@ -140,6 +152,8 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Utility
|
||||
{
|
||||
return new TestDbDataReader(Data);
|
||||
}
|
||||
|
||||
private List<DbParameter> listParams = new List<DbParameter>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user