From e1395cbd7d45d15983be3c28ab20a4098bb5e8b4 Mon Sep 17 00:00:00 2001 From: Leila Lali Date: Mon, 24 Jul 2017 09:41:32 -0700 Subject: [PATCH] Adding more features to restore operation (#420) * Adding more features to restore operations and added tests --- .../Connection/ConnectionService.cs | 4 +- .../Connection/Contracts/ConnectionDetails.cs | 65 +- .../Connection/Contracts/ConnectionSummary.cs | 22 +- .../Contracts/ConnectionSummaryExtensions.cs | 2 +- .../Contracts/DatabaseFileInfo.cs | 60 ++ .../Contracts/LocalizedPropertyInfo.cs | 72 ++ .../Contracts/RestoreRequest.cs | 95 ++- .../DisasterRecoveryService.cs | 2 +- .../RestoreOperation/BackupSetInfo.cs | 186 ++++- .../RestoreOperation/RestoreDatabaseHelper.cs | 100 ++- .../RestoreDatabaseTaskDataObject.cs | 145 ++-- .../LanguageServices/LanguageService.cs | 2 +- .../Localization/sr.cs | 176 +++++ .../Localization/sr.de.resx | 461 ++++++++++++- .../Localization/sr.es.resx | 447 +++++++++++- .../Localization/sr.fr.resx | 645 ++++++++++++++++-- .../Localization/sr.it.resx | 443 +++++++++++- .../Localization/sr.ja.resx | 444 +++++++++++- .../Localization/sr.ko.resx | 449 +++++++++++- .../Localization/sr.pt-BR.resx | 437 +++++++++++- .../Localization/sr.resx | 64 ++ .../Localization/sr.ru.resx | 443 +++++++++++- .../Localization/sr.strings | 18 +- .../Localization/sr.xlf | 80 +++ .../Localization/sr.zh-hans.resx | 478 ++++++++++++- .../Localization/sr.zh-hant.resx | 459 ++++++++++++- .../TaskServices/SqlTask.cs | 7 +- .../Utility/GeneralRequestDetails.cs | 69 ++ .../RestoreDatabaseServiceTests.cs | 166 ++++- .../DisasterRecovery/Backups/DiffBackup.bak | Bin 442368 -> 966656 bytes .../DisasterRecovery/Backups/FullBackup.bak | Bin 2932736 -> 2736128 bytes .../DisasterRecovery/DatabaseFileInfoTests.cs | 53 ++ .../LocalizedPropertyInfoTests.cs | 33 + .../ObjectExplorer/NodeTests.cs | 3 +- 34 files changed, 5861 insertions(+), 269 deletions(-) create mode 100644 src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/Contracts/DatabaseFileInfo.cs create mode 100644 src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/Contracts/LocalizedPropertyInfo.cs create mode 100644 src/Microsoft.SqlTools.ServiceLayer/Utility/GeneralRequestDetails.cs create mode 100644 test/Microsoft.SqlTools.ServiceLayer.UnitTests/DisasterRecovery/DatabaseFileInfoTests.cs create mode 100644 test/Microsoft.SqlTools.ServiceLayer.UnitTests/DisasterRecovery/LocalizedPropertyInfoTests.cs diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/ConnectionService.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/ConnectionService.cs index 194d6415..5583a837 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Connection/ConnectionService.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/ConnectionService.cs @@ -100,7 +100,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection /// /// Callback for ondisconnect handler /// - public delegate Task OnDisconnectHandler(ConnectionSummary summary, string ownerUri); + public delegate Task OnDisconnectHandler(IConnectionSummary summary, string ownerUri); /// /// List of onconnection handlers @@ -1007,7 +1007,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection // Fire a connection changed event ConnectionChangedParams parameters = new ConnectionChangedParams(); - ConnectionSummary summary = info.ConnectionDetails; + IConnectionSummary summary = info.ConnectionDetails; parameters.Connection = summary.Clone(); parameters.OwnerUri = ownerUri; ServiceHost.SendEvent(ConnectionChangedNotification.Type, parameters); diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/Contracts/ConnectionDetails.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/Contracts/ConnectionDetails.cs index 57312cbf..707ad49f 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Connection/Contracts/ConnectionDetails.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/Contracts/ConnectionDetails.cs @@ -3,10 +3,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -using System; -using System.Collections.Generic; -using System.Globalization; -using Microsoft.SqlTools.Utility; +using Microsoft.SqlTools.ServiceLayer.Utility; namespace Microsoft.SqlTools.ServiceLayer.Connection.Contracts { @@ -16,18 +13,12 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.Contracts /// /// If this contract is ever changed, be sure to update ConnectionDetailsExtensions methods. /// - public class ConnectionDetails : ConnectionSummary + public class ConnectionDetails : GeneralRequestDetails, IConnectionSummary { - public ConnectionDetails() + public ConnectionDetails() : base() { - Options = new Dictionary(); } - /// - /// Gets or Sets the connection options - /// - public Dictionary Options { get; set; } - /// /// Gets or sets the connection password /// @@ -46,7 +37,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.Contracts /// /// Gets or sets the connection server name /// - public override string ServerName + public string ServerName { get { @@ -62,7 +53,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.Contracts /// /// Gets or sets the connection database name /// - public override string DatabaseName + public string DatabaseName { get { @@ -78,7 +69,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.Contracts /// /// Gets or sets the connection user name /// - public override string UserName + public string UserName { get { @@ -459,49 +450,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.Contracts } } - private T GetOptionValue(string name) - { - T result = default(T); - if (Options != null && Options.ContainsKey(name)) - { - object value = Options[name]; - try - { - if (value != null && (typeof(T) != value.GetType())) - { - if (typeof(T) == typeof(int) || typeof(T) == typeof(int?)) - { - value = Convert.ToInt32(value); - } - else if (typeof(T) == typeof(bool) || typeof(T) == typeof(bool?)) - { - value = Convert.ToBoolean(value); - } - } - result = value != null ? (T)value : default(T); - } - catch - { - result = default(T); - Logger.Write(LogLevel.Warning, string.Format(CultureInfo.InvariantCulture, - "Cannot convert option value {0}:{1} to {2}", name, value ?? "", typeof(T))); - } - } - return result; - } - - private void SetOptionValue(string name, T value) - { - Options = Options ?? new Dictionary(); - if (Options.ContainsKey(name)) - { - Options[name] = value; - } - else - { - Options.Add(name, value); - } - } + public bool IsComparableTo(ConnectionDetails other) { diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/Contracts/ConnectionSummary.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/Contracts/ConnectionSummary.cs index fa99ab8a..54642c87 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Connection/Contracts/ConnectionSummary.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/Contracts/ConnectionSummary.cs @@ -3,12 +3,32 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // + namespace Microsoft.SqlTools.ServiceLayer.Connection.Contracts { + + public interface IConnectionSummary + { + /// + /// Gets or sets the connection server name + /// + string ServerName { get; set; } + + /// + /// Gets or sets the connection database name + /// + string DatabaseName { get; set; } + + /// + /// Gets or sets the connection user name + /// + string UserName { get; set; } + } + /// /// Provides high level information about a connection. /// - public class ConnectionSummary + public class ConnectionSummary : IConnectionSummary { /// /// Gets or sets the connection server name diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/Contracts/ConnectionSummaryExtensions.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/Contracts/ConnectionSummaryExtensions.cs index 02bc7623..bdce9f04 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Connection/Contracts/ConnectionSummaryExtensions.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/Contracts/ConnectionSummaryExtensions.cs @@ -13,7 +13,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.Contracts /// /// Create a copy of a ConnectionSummary object /// - public static ConnectionSummary Clone(this ConnectionSummary summary) + public static ConnectionSummary Clone(this IConnectionSummary summary) { return new ConnectionSummary() { diff --git a/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/Contracts/DatabaseFileInfo.cs b/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/Contracts/DatabaseFileInfo.cs new file mode 100644 index 00000000..9321655c --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/Contracts/DatabaseFileInfo.cs @@ -0,0 +1,60 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System.Linq; +using Microsoft.SqlTools.Utility; + +namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.Contracts +{ + /// + /// Class includes information about a file related to a database operation. + /// Can be used for backup set files or restored database files + /// + public class DatabaseFileInfo + { + /// + /// The property name used for ids + /// + public const string IdPropertyName = "Id"; + + public DatabaseFileInfo(LocalizedPropertyInfo[] properties) + { + Validate.IsNotNull("properties", properties); + + this.Properties = properties; + if (this.Properties != null ) + { + var idProperty = this.Properties.FirstOrDefault(x => x.PropertyName == IdPropertyName); + Id = idProperty == null || idProperty.PropertyValue == null ? string.Empty : idProperty.PropertyValue.ToString(); + } + } + + /// + /// Properties + /// + public LocalizedPropertyInfo[] Properties { get; private set; } + + public string GetPropertyValueAsString(string name) + { + string value = string.Empty; + if (Properties != null) + { + var property = Properties.FirstOrDefault(x => x.PropertyName == name); + value = property == null || property.PropertyValue == null ? string.Empty : property.PropertyValue.ToString(); + } + return value; + } + + /// + /// Unique id for this item + /// + public string Id { get; private set; } + + /// + /// Indicates whether the item is selected in client + /// + public bool IsSelected { get; set; } + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/Contracts/LocalizedPropertyInfo.cs b/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/Contracts/LocalizedPropertyInfo.cs new file mode 100644 index 00000000..617b3bd4 --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/Contracts/LocalizedPropertyInfo.cs @@ -0,0 +1,72 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System; +using System.Globalization; + +namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.Contracts +{ + public class LocalizedPropertyInfo + { + + private string propertyValueDisplayName; + private string propertyDisplayName; + + /// + /// Property name + /// + public string PropertyName { get; set; } + + + /// + /// Property value + /// + public object PropertyValue { get; set; } + + /// + /// Property display name + /// + public string PropertyDisplayName + { + get + { + return string.IsNullOrEmpty(this.propertyDisplayName) ? PropertyName : this.propertyDisplayName; + } + set + { + this.propertyDisplayName = value; + } + } + + /// + /// Property display name for the value + /// + public string PropertyValueDisplayName + { + get + { + return string.IsNullOrEmpty(propertyValueDisplayName) ? GetLocalizedPropertyValue() : propertyValueDisplayName; + } + set + { + this.propertyValueDisplayName = value; + } + } + + private string GetLocalizedPropertyValue() + { + string displayName = string.Empty; + if(PropertyValue is DateTime) + { + displayName = ((DateTime)PropertyValue) != DateTime.MinValue ? Convert.ToString(PropertyValue, CultureInfo.CurrentCulture) : string.Empty; + } + else + { + displayName = Convert.ToString(PropertyValue, CultureInfo.CurrentCulture); + } + return displayName; + } + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/Contracts/RestoreRequest.cs b/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/Contracts/RestoreRequest.cs index d2e30b55..be5f622b 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/Contracts/RestoreRequest.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/Contracts/RestoreRequest.cs @@ -5,33 +5,106 @@ using System.Collections.Generic; using Microsoft.SqlTools.Hosting.Protocol.Contracts; +using Microsoft.SqlTools.ServiceLayer.Utility; namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.Contracts { /// /// Restore request parameters /// - public class RestoreParams + public class RestoreParams : GeneralRequestDetails { + public string SessionId + { + get + { + return GetOptionValue("sessionId"); + } + set + { + SetOptionValue("sessionId", value); + } + } + /// /// The Uri to find the connection to do the restore operations /// public string OwnerUri { get; set; } /// - /// The backup file path + /// Comma delimited list of backup files /// - public string BackupFilePath { get; set; } + public string BackupFilePaths + { + get + { + return GetOptionValue("backupFilePaths"); + } + set + { + SetOptionValue("backupFilePaths", value); + } + } /// /// Target Database name to restore to /// - public string DatabaseName { get; set; } + public string TargetDatabaseName + { + get + { + return GetOptionValue("targetDatabaseName"); + } + set + { + SetOptionValue("targetDatabaseName", value); + } + } + + /// + /// Source Database name to restore from + /// + public string SourceDatabaseName + { + get + { + return GetOptionValue("sourceDatabaseName"); + } + set + { + SetOptionValue("sourceDatabaseName", value); + } + } /// /// If set to true, the db files will be relocated to default data location in the server /// - public bool RelocateDbFiles { get; set; } + public bool RelocateDbFiles + { + get + { + return GetOptionValue("relocateDbFiles"); + } + set + { + SetOptionValue("relocateDbFiles", value); + } + } + + /// + /// Ids of the backup set to restore + /// + public string[] SelectedBackupSets + { + get + { + return GetOptionValue("selectedBackupSets"); + } + set + { + SetOptionValue("selectedBackupSets", value); + } + } } /// @@ -87,10 +160,9 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.Contracts /// public class RestorePlanResponse { - /// - /// The backup file path - /// - public string BackupFilePath { get; set; } + public string RestoreSessionId { get; set; } + + public DatabaseFileInfo[] BackupSetsToRestore { get; set; } /// /// Indicates whether the restore operation is supported @@ -107,6 +179,11 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.Contracts /// public IEnumerable DbFiles { get; set; } + /// + /// Database names extracted from backup sets + /// + public string[] DatabaseNamesFromBackupSets { get; set; } + /// /// Server name /// diff --git a/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/DisasterRecoveryService.cs b/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/DisasterRecoveryService.cs index d2006a61..e01a7d79 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/DisasterRecoveryService.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/DisasterRecoveryService.cs @@ -26,7 +26,7 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery { private static readonly Lazy instance = new Lazy(() => new DisasterRecoveryService()); private static ConnectionService connectionService = null; - private RestoreDatabaseHelper restoreDatabaseService = new RestoreDatabaseHelper(); + private RestoreDatabaseHelper restoreDatabaseService = RestoreDatabaseHelper.Instance; /// /// Default, parameterless constructor. diff --git a/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/RestoreOperation/BackupSetInfo.cs b/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/RestoreOperation/BackupSetInfo.cs index 89787946..bd2e23f4 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/RestoreOperation/BackupSetInfo.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/RestoreOperation/BackupSetInfo.cs @@ -3,6 +3,14 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Globalization; +using System.Linq; +using Microsoft.SqlServer.Management.Smo; +using Microsoft.SqlTools.ServiceLayer.DisasterRecovery.Contracts; + namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation { /// @@ -10,14 +18,186 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation /// public class BackupSetInfo { + public const string BackupComponentPropertyName = "Component"; + public const string NamePropertyName = "Name"; + public const string BackupTypePropertyName = "Type"; + public const string ServerNamePropertyName = "Server"; + public const string DatabaseNamePropertyName = "Database"; + public const string PositionPropertyName = "Position"; + public const string FirstLsnPropertyName = "FirstLSN"; + public const string LastLsnPropertyName = "LastLSN"; + public const string CheckpointLsnPropertyName = "CheckpointLSN"; + public const string FullLsnPropertyName = "FullLSN"; + public const string StartDatePropertyName = "StartDate"; + public const string FinishDatePropertyName = "FinishDate"; + public const string SizePropertyName = "Size"; + public const string UserNamePropertyName = "UserName"; + public const string ExpirationPropertyName = "Expiration"; + + private Dictionary properties; + + public BackupSetInfo(Dictionary properties) + { + this.properties = properties; + } + /// /// Backup type (Full, Transaction Log, Differential ...) /// - public string BackupType { get; set; } + public string BackupType + { + get + { + return GetPropertyValueAsString(BackupTypePropertyName); + } + } /// - /// Backup component (Database, File, Log ...) + /// Backup set properties /// - public string BackupComponent { get; set; } + public ReadOnlyDictionary Properties + { + get + { + return new ReadOnlyDictionary(this.properties); + } + } + + /// + /// Convert properties to array + /// + /// + public LocalizedPropertyInfo[] ConvertPropertiesToArray() + { + return this.properties == null ? new LocalizedPropertyInfo[] { } : this.properties.Values.ToArray(); + } + + /// + /// Creates new BackupSet info + /// + /// + public static BackupSetInfo Create(Restore restore, Server server) + { + BackupSet backupSet = restore.BackupSet; + Dictionary properties = new Dictionary(); + + string bkSetComponent; + string bkSetType; + CommonUtilities.GetBackupSetTypeAndComponent(backupSet.BackupSetType, out bkSetType, out bkSetComponent); + + if (server.Version.Major > 8 && backupSet.IsCopyOnly) + { + bkSetType += SR.RestoreCopyOnly; + } + + properties.Add(NamePropertyName, new LocalizedPropertyInfo + { + PropertyName = NamePropertyName, + PropertyValue = backupSet.Name, + PropertyDisplayName = SR.RestoreBackupSetName + }); + properties.Add(BackupComponentPropertyName, new LocalizedPropertyInfo + { + PropertyName = BackupComponentPropertyName, + PropertyValue = bkSetComponent, + PropertyDisplayName = SR.RestoreBackupSetType + }); + properties.Add(BackupTypePropertyName, new LocalizedPropertyInfo + { + PropertyName = BackupTypePropertyName, + PropertyValue = bkSetType, + PropertyDisplayName = SR.RestoreBackupSetComponent + }); + properties.Add(ServerNamePropertyName, new LocalizedPropertyInfo + { + PropertyName = ServerNamePropertyName, + PropertyValue = backupSet.ServerName, + PropertyDisplayName = SR.RestoreBackupSetServer + }); + properties.Add(DatabaseNamePropertyName, new LocalizedPropertyInfo + { + PropertyName = DatabaseNamePropertyName, + PropertyValue = backupSet.DatabaseName, + PropertyDisplayName = SR.RestoreBackupSetDatabase + }); + properties.Add(PositionPropertyName, new LocalizedPropertyInfo + { + PropertyName = PositionPropertyName, + PropertyValueDisplayName = Convert.ToString(backupSet.Position, CultureInfo.CurrentCulture), + PropertyValue = backupSet.Position, + PropertyDisplayName = SR.RestoreBackupSetPosition + }); + properties.Add(FirstLsnPropertyName, new LocalizedPropertyInfo + { + PropertyName = FirstLsnPropertyName, + PropertyValue = backupSet.FirstLsn, + PropertyDisplayName = SR.RestoreBackupSetFirstLsn + }); + properties.Add(LastLsnPropertyName, new LocalizedPropertyInfo + { + PropertyName = LastLsnPropertyName, + PropertyValue = backupSet.LastLsn, + PropertyDisplayName = SR.RestoreBackupSetLastLsn + }); + properties.Add(FullLsnPropertyName, new LocalizedPropertyInfo + { + PropertyName = FullLsnPropertyName, + PropertyValue = backupSet.DatabaseBackupLsn, + PropertyDisplayName = SR.RestoreBackupSetFullLsn + }); + properties.Add(CheckpointLsnPropertyName, new LocalizedPropertyInfo + { + PropertyName = CheckpointLsnPropertyName, + PropertyValue = backupSet.CheckpointLsn, + PropertyDisplayName = SR.RestoreBackupSetCheckpointLsn + }); + properties.Add(StartDatePropertyName, new LocalizedPropertyInfo + { + PropertyName = StartDatePropertyName, + PropertyValue = backupSet.BackupStartDate, + PropertyDisplayName = SR.RestoreBackupSetStartDate + }); + properties.Add(FinishDatePropertyName, new LocalizedPropertyInfo + { + PropertyName = FinishDatePropertyName, + PropertyValue = backupSet.BackupFinishDate, + PropertyDisplayName = SR.RestoreBackupSetFinishDate + }); + properties.Add(SizePropertyName, new LocalizedPropertyInfo + { + PropertyName = SizePropertyName, + PropertyValue = backupSet.BackupSize, + PropertyDisplayName = SR.RestoreBackupSetSize, + }); + properties.Add(UserNamePropertyName, new LocalizedPropertyInfo + { + PropertyName = UserNamePropertyName, + PropertyValue = backupSet.UserName, + PropertyDisplayName = SR.RestoreBackupSetUserName, + }); + properties.Add(ExpirationPropertyName, new LocalizedPropertyInfo + { + PropertyName = ExpirationPropertyName, + PropertyValue = backupSet.ExpirationDate, + PropertyDisplayName = SR.RestoreBackupSetExpiration, + }); + properties.Add(DatabaseFileInfo.IdPropertyName, new LocalizedPropertyInfo + { + PropertyName = DatabaseFileInfo.IdPropertyName, + PropertyValue = backupSet.BackupSetGuid + }); + + return new BackupSetInfo(properties); + } + + public string GetPropertyValueAsString(string propertyName) + { + LocalizedPropertyInfo propertyValue = null; + if(!string.IsNullOrEmpty(propertyName) && Properties != null) + { + Properties.TryGetValue(propertyName, out propertyValue); + } + return propertyValue.PropertyValue != null ? propertyValue.PropertyValue.ToString() : string.Empty; + } } } diff --git a/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/RestoreOperation/RestoreDatabaseHelper.cs b/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/RestoreOperation/RestoreDatabaseHelper.cs index e4322c5d..43e0a40a 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/RestoreOperation/RestoreDatabaseHelper.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/RestoreOperation/RestoreDatabaseHelper.cs @@ -15,6 +15,7 @@ using Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection; using Microsoft.SqlTools.ServiceLayer.DisasterRecovery.Contracts; using Microsoft.SqlTools.ServiceLayer.TaskServices; using Microsoft.SqlTools.Utility; +using System.Collections.Concurrent; namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation { @@ -24,6 +25,22 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation public class RestoreDatabaseHelper { + private static RestoreDatabaseHelper instance = new RestoreDatabaseHelper(); + private ConcurrentDictionary restoreSessions = new ConcurrentDictionary(); + + internal RestoreDatabaseHelper() + { + + } + + public static RestoreDatabaseHelper Instance + { + get + { + return instance; + } + } + /// /// Create a backup task for execution and cancellation /// @@ -45,7 +62,7 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation { if (restoreDataObject.IsValid) { - ExecuteRestore(restoreDataObject); + ExecuteRestore(restoreDataObject, sqlTask); result.TaskStatus = SqlTaskStatus.Succeeded; } else @@ -135,7 +152,7 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation { RestorePlanResponse response = new RestorePlanResponse() { - DatabaseName = restoreDataObject.RestoreParams.DatabaseName + DatabaseName = restoreDataObject.RestoreParams.TargetDatabaseName }; try { @@ -145,6 +162,7 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation if (restoreDataObject != null && restoreDataObject.IsValid) { + response.RestoreSessionId = restoreDataObject.SessionId; response.DatabaseName = restoreDataObject.TargetDatabase; response.DbFiles = restoreDataObject.DbFiles.Select(x => new RestoreDatabaseFileInfo { @@ -160,6 +178,9 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation response.ErrorMessage = SR.RestoreNotSupported; } + response.BackupSetsToRestore = restoreDataObject.GetBackupSetInfo().Select(x => new DatabaseFileInfo(x.ConvertPropertiesToArray())).ToArray(); + var dbNames = restoreDataObject.GetSourceDbNames(); + response.DatabaseNamesFromBackupSets = dbNames == null ? new string[] { } : dbNames.ToArray(); response.RelocateFilesNeeded = !restoreDataObject.DbFilesLocationAreValid(); response.DefaultDataFolder = restoreDataObject.DefaultDataFileFolder; response.DefaultLogFolder = restoreDataObject.DefaultLogFileFolder; @@ -204,7 +225,9 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation if (restoreDataObject != null) { var backupTypes = restoreDataObject.GetBackupSetInfo(); - return backupTypes.Any(x => x.BackupType.StartsWith(RestoreConstants.TypeFull)); + var selectedBackupSets = restoreDataObject.RestoreParams.SelectedBackupSets; + return backupTypes.Any(x => (selectedBackupSets == null || selectedBackupSets.Contains(x.GetPropertyValueAsString(DatabaseFileInfo.IdPropertyName))) + && x.BackupType.StartsWith(RestoreConstants.TypeFull)); } return false; } @@ -215,6 +238,24 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation /// Restore request parameters /// Restore task object public RestoreDatabaseTaskDataObject CreateRestoreDatabaseTaskDataObject(RestoreParams restoreParams) + { + RestoreDatabaseTaskDataObject restoreTaskObject = null; + if (!string.IsNullOrWhiteSpace(restoreParams.SessionId)) + { + this.restoreSessions.TryGetValue(restoreParams.SessionId, out restoreTaskObject); + } + + if (restoreTaskObject == null) + { + restoreTaskObject = CreateRestoreForNewSession(restoreParams); + string sessionId = string.IsNullOrWhiteSpace(restoreParams.SessionId) ? Guid.NewGuid().ToString() : restoreParams.SessionId; + this.restoreSessions.AddOrUpdate(sessionId, restoreTaskObject, (key, oldSession) => restoreTaskObject); + restoreTaskObject.SessionId = sessionId; + } + return restoreTaskObject; + } + + private RestoreDatabaseTaskDataObject CreateRestoreForNewSession(RestoreParams restoreParams) { ConnectionInfo connInfo; DisasterRecoveryService.ConnectionServiceInstance.TryFindConnection( @@ -242,7 +283,7 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation } Server server = new Server(new ServerConnection(connection)); - RestoreDatabaseTaskDataObject restoreDataObject = new RestoreDatabaseTaskDataObject(server, restoreParams.DatabaseName); + RestoreDatabaseTaskDataObject restoreDataObject = new RestoreDatabaseTaskDataObject(server, restoreParams.TargetDatabaseName); restoreDataObject.RestoreParams = restoreParams; return restoreDataObject; } @@ -256,35 +297,54 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation /// private void UpdateRestorePlan(RestoreDatabaseTaskDataObject restoreDataObject) { - if (!string.IsNullOrEmpty(restoreDataObject.RestoreParams.BackupFilePath)) + if (restoreDataObject.PlanUpdateRequired) { - restoreDataObject.AddFile(restoreDataObject.RestoreParams.BackupFilePath); - } - restoreDataObject.RestorePlanner.ReadHeaderFromMedia = !string.IsNullOrEmpty(restoreDataObject.RestoreParams.BackupFilePath); - - restoreDataObject.RestorePlanner.DatabaseName = restoreDataObject.DefaultDbName; - restoreDataObject.TargetDatabase = restoreDataObject.RestoreParams.DatabaseName; - //TODO: used for other types of restore - /*bool isTailLogBackupPossible = restoreDataObject.RestorePlanner.IsTailLogBackupPossible(restoreDataObject.RestorePlanner.DatabaseName); - restoreDataObject.RestorePlanner.BackupTailLog = isTailLogBackupPossible; - restoreDataObject.TailLogBackupFile = restoreDataObject.Util.GetDefaultTailLogbackupFile(dbName); - restoreDataObject.RestorePlanner.TailLogBackupFile = restoreDataObject.TailLogBackupFile; - */ + if (!string.IsNullOrEmpty(restoreDataObject.RestoreParams.BackupFilePaths)) + { + restoreDataObject.AddFiles(restoreDataObject.RestoreParams.BackupFilePaths); + } + restoreDataObject.RestorePlanner.ReadHeaderFromMedia = !string.IsNullOrEmpty(restoreDataObject.RestoreParams.BackupFilePaths); - restoreDataObject.UpdateRestorePlan(restoreDataObject.RestoreParams.RelocateDbFiles); + if (string.IsNullOrWhiteSpace(restoreDataObject.RestoreParams.SourceDatabaseName)) + { + restoreDataObject.RestorePlanner.DatabaseName = restoreDataObject.DefaultDbName; + } + else + { + restoreDataObject.RestorePlanner.DatabaseName = restoreDataObject.RestoreParams.SourceDatabaseName; + } + restoreDataObject.TargetDatabase = restoreDataObject.RestoreParams.TargetDatabaseName; + //TODO: used for other types of restore + /*bool isTailLogBackupPossible = restoreDataObject.RestorePlanner.IsTailLogBackupPossible(restoreDataObject.RestorePlanner.DatabaseName); + restoreDataObject.RestorePlanner.BackupTailLog = isTailLogBackupPossible; + restoreDataObject.TailLogBackupFile = restoreDataObject.Util.GetDefaultTailLogbackupFile(dbName); + restoreDataObject.RestorePlanner.TailLogBackupFile = restoreDataObject.TailLogBackupFile; + */ + + restoreDataObject.UpdateRestorePlan(restoreDataObject.RestoreParams.RelocateDbFiles); + } } /// /// Executes the restore operation /// /// - public void ExecuteRestore(RestoreDatabaseTaskDataObject restoreDataObject) + public void ExecuteRestore(RestoreDatabaseTaskDataObject restoreDataObject, SqlTask sqlTask = null) { + // Restore Plan should be already created and updated at this point UpdateRestorePlan(restoreDataObject); if (restoreDataObject != null && CanRestore(restoreDataObject)) { - restoreDataObject.RestorePlan.Execute(); + try + { + restoreDataObject.SqlTask = sqlTask; + restoreDataObject.Execute(); + } + catch(Exception ex) + { + throw ex; + } } else { diff --git a/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/RestoreOperation/RestoreDatabaseTaskDataObject.cs b/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/RestoreOperation/RestoreDatabaseTaskDataObject.cs index 1f6b2351..d746e89a 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/RestoreOperation/RestoreDatabaseTaskDataObject.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/RestoreOperation/RestoreDatabaseTaskDataObject.cs @@ -9,6 +9,7 @@ using System.IO; using System.Linq; using Microsoft.SqlServer.Management.Smo; using Microsoft.SqlTools.ServiceLayer.DisasterRecovery.Contracts; +using Microsoft.SqlTools.ServiceLayer.TaskServices; namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation { @@ -17,8 +18,11 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation /// public class RestoreDatabaseTaskDataObject { + + private const char BackupMediaNameSeparator = ','; public RestoreDatabaseTaskDataObject(Server server, String databaseName) { + PlanUpdateRequired = true; this.Server = server; this.Util = new RestoreUtil(server); restorePlanner = new DatabaseRestorePlanner(server); @@ -39,6 +43,16 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation this.restoreOptions.PercentCompleteNotification = 5; } + /// + /// Restore session id + /// + public string SessionId { get; set; } + + /// + /// Sql task assigned to the restore object + /// + public SqlTask SqlTask { get; set; } + public string TargetDatabase { get @@ -86,14 +100,74 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation /// /// Add a backup file to restore plan media list /// - /// - public void AddFile(string filePath) + /// + public void AddFiles(string filePaths) { - this.RestorePlanner.BackupMediaList.Add(new BackupDeviceItem + PlanUpdateRequired = true; + if (!string.IsNullOrWhiteSpace(filePaths)) { - DeviceType = DeviceType.File, - Name = filePath - }); + string[] files = filePaths.Split(BackupMediaNameSeparator); + files = files.Select(x => x.Trim()).ToArray(); + foreach (var file in files) + { + if (!this.RestorePlanner.BackupMediaList.Any(x => x.Name == file)) + { + this.RestorePlanner.BackupMediaList.Add(new BackupDeviceItem + { + DeviceType = DeviceType.File, + Name = file + }); + } + } + + var itemsToRemove = this.RestorePlanner.BackupMediaList.Where(x => !files.Contains(x.Name)); + foreach (var item in itemsToRemove) + { + this.RestorePlanner.BackupMediaList.Remove(item); + } + } + } + + /// + /// Removes the backup sets that are filtered in the request + /// + public void RemoveFilteredBackupSets() + { + var backupSetIdsToRestore = RestoreParams.SelectedBackupSets; + if (backupSetIdsToRestore != null) + { + var ids = backupSetIdsToRestore.Select(x => + { + Guid guid; + Guid.TryParse(x, out guid); + return guid; + } + ); + restorePlan.RestoreOperations.RemoveAll(x => !ids.Contains(x.BackupSet.BackupSetGuid)); + } + } + + /// + /// Executes the restore operations + /// + public void Execute() + { + RestorePlan restorePlan = RestorePlan; + // ssms creates a new restore plan by calling GetRestorePlanForExecutionAndScript and + // Doens't use the plan already created here. not sure why, using the existing restore plan doesn't make + // any issue so far so keeping in it for now but we might want to double check later + if (restorePlan != null && restorePlan.RestoreOperations.Count > 0) + { + RemoveFilteredBackupSets(); + restorePlan.PercentComplete += (object sender, PercentCompleteEventArgs e) => + { + if (SqlTask != null) + { + SqlTask.AddMessage($"{e.Percent}%", SqlTaskStatus.InProgress); + } + }; + restorePlan.Execute(); + } } public RestoreUtil Util { get; set; } @@ -109,7 +183,7 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation } private string tailLogBackupFile; - private bool planUpdateRequired = false; + public bool PlanUpdateRequired { get; private set; } /// /// File to backup tail log before doing the restore @@ -122,7 +196,7 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation if (tailLogBackupFile == null || !tailLogBackupFile.Equals(value)) { this.RestorePlanner.TailLogBackupFile = value; - this.planUpdateRequired = true; + this.PlanUpdateRequired = true; this.tailLogBackupFile = value; } } @@ -384,43 +458,6 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation /// internal string ContainerSharedAccessPolicy = string.Empty; - /// - /// Gets RestorePlan to perform restore and to script - /// - public RestorePlan GetRestorePlanForExecutionAndScript() - { - this.ActiveException = null; //Clear any existing exceptions as the plan is getting recreated. - //Clear any existing exceptions as new plan is getting recreated. - this.CreateOrUpdateRestorePlanException = null; - bool tailLogBackup = this.RestorePlanner.BackupTailLog; - if (this.planUpdateRequired) - { - this.RestorePlan = this.RestorePlanner.CreateRestorePlan(this.RestoreOptions); - this.UpdateRestoreSelected(); - this.Util.AddCredentialNameForUrlBackupSet(this.RestorePlan, this.CredentialName); - } - RestorePlan rp = new RestorePlan(this.Server); - rp.RestoreAction = RestoreActionType.Database; - if (this.RestorePlan != null) - { - if (this.RestorePlan.TailLogBackupOperation != null && tailLogBackup) - { - rp.TailLogBackupOperation = this.RestorePlan.TailLogBackupOperation; - } - int i = 0; - foreach (Restore res in this.RestorePlan.RestoreOperations) - { - if (this.RestoreSelected[i] == true) - { - rp.RestoreOperations.Add(res); - } - i++; - } - } - this.SetRestorePlanProperties(rp); - return rp; - } - /// /// Updates the RestoreSelected Array to hold information about updated Restore Plan /// @@ -472,17 +509,7 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation List result = new List(); foreach (Restore restore in RestorePlan.RestoreOperations) { - BackupSet backupSet = restore.BackupSet; - - String bkSetComponent; - String bkSetType; - CommonUtilities.GetBackupSetTypeAndComponent(backupSet.BackupSetType, out bkSetType, out bkSetComponent); - - if (this.Server.Version.Major > 8 && backupSet.IsCopyOnly) - { - bkSetType += " (Copy Only)"; - } - result.Add(new BackupSetInfo { BackupComponent = bkSetComponent, BackupType = bkSetType }); + result.Add(BackupSetInfo.Create(restore, Server)); } return result; @@ -564,7 +591,7 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation //Clear any existing exceptions as new plan is getting recreated. this.CreateOrUpdateRestorePlanException = null; this.DbFiles.Clear(); - this.planUpdateRequired = false; + this.PlanUpdateRequired = false; this.restorePlan = null; if (String.IsNullOrEmpty(this.RestorePlanner.DatabaseName)) { @@ -666,7 +693,7 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation if (this.RestorePlanner.BackupTailLog != value) { this.RestorePlanner.BackupTailLog = value; - this.planUpdateRequired = true; + this.PlanUpdateRequired = true; } } } @@ -685,7 +712,7 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation if (this.RestorePlanner.TailLogWithNoRecovery != value) { this.RestorePlanner.TailLogWithNoRecovery = value; - this.planUpdateRequired = true; + this.PlanUpdateRequired = true; } } } diff --git a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/LanguageService.cs b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/LanguageService.cs index c788e734..ed52e61b 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/LanguageService.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/LanguageService.cs @@ -729,7 +729,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices /// it is the last URI connected to a particular connection, /// then remove the cache. /// - public async Task RemoveAutoCompleteCacheUriReference(ConnectionSummary summary, string ownerUri) + public async Task RemoveAutoCompleteCacheUriReference(IConnectionSummary summary, string ownerUri) { RemoveScriptParseInfo(ownerUri); diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.cs b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.cs index 5a2221ea..7491761c 100755 --- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.cs @@ -3349,6 +3349,134 @@ namespace Microsoft.SqlTools.ServiceLayer } } + public static string RestoreCopyOnly + { + get + { + return Keys.GetString(Keys.RestoreCopyOnly); + } + } + + public static string RestoreBackupSetComponent + { + get + { + return Keys.GetString(Keys.RestoreBackupSetComponent); + } + } + + public static string RestoreBackupSetName + { + get + { + return Keys.GetString(Keys.RestoreBackupSetName); + } + } + + public static string RestoreBackupSetType + { + get + { + return Keys.GetString(Keys.RestoreBackupSetType); + } + } + + public static string RestoreBackupSetServer + { + get + { + return Keys.GetString(Keys.RestoreBackupSetServer); + } + } + + public static string RestoreBackupSetDatabase + { + get + { + return Keys.GetString(Keys.RestoreBackupSetDatabase); + } + } + + public static string RestoreBackupSetPosition + { + get + { + return Keys.GetString(Keys.RestoreBackupSetPosition); + } + } + + public static string RestoreBackupSetFirstLsn + { + get + { + return Keys.GetString(Keys.RestoreBackupSetFirstLsn); + } + } + + public static string RestoreBackupSetLastLsn + { + get + { + return Keys.GetString(Keys.RestoreBackupSetLastLsn); + } + } + + public static string RestoreBackupSetCheckpointLsn + { + get + { + return Keys.GetString(Keys.RestoreBackupSetCheckpointLsn); + } + } + + public static string RestoreBackupSetFullLsn + { + get + { + return Keys.GetString(Keys.RestoreBackupSetFullLsn); + } + } + + public static string RestoreBackupSetStartDate + { + get + { + return Keys.GetString(Keys.RestoreBackupSetStartDate); + } + } + + public static string RestoreBackupSetFinishDate + { + get + { + return Keys.GetString(Keys.RestoreBackupSetFinishDate); + } + } + + public static string RestoreBackupSetSize + { + get + { + return Keys.GetString(Keys.RestoreBackupSetSize); + } + } + + public static string RestoreBackupSetUserName + { + get + { + return Keys.GetString(Keys.RestoreBackupSetUserName); + } + } + + public static string RestoreBackupSetExpiration + { + get + { + return Keys.GetString(Keys.RestoreBackupSetExpiration); + } + } + public static string ConnectionServiceListDbErrorNotConnected(string uri) { return Keys.GetString(Keys.ConnectionServiceListDbErrorNotConnected, uri); @@ -4714,6 +4842,54 @@ namespace Microsoft.SqlTools.ServiceLayer public const string RestoreTaskName = "RestoreTaskName"; + public const string RestoreCopyOnly = "RestoreCopyOnly"; + + + public const string RestoreBackupSetComponent = "RestoreBackupSetComponent"; + + + public const string RestoreBackupSetName = "RestoreBackupSetName"; + + + public const string RestoreBackupSetType = "RestoreBackupSetType"; + + + public const string RestoreBackupSetServer = "RestoreBackupSetServer"; + + + public const string RestoreBackupSetDatabase = "RestoreBackupSetDatabase"; + + + public const string RestoreBackupSetPosition = "RestoreBackupSetPosition"; + + + public const string RestoreBackupSetFirstLsn = "RestoreBackupSetFirstLsn"; + + + public const string RestoreBackupSetLastLsn = "RestoreBackupSetLastLsn"; + + + public const string RestoreBackupSetCheckpointLsn = "RestoreBackupSetCheckpointLsn"; + + + public const string RestoreBackupSetFullLsn = "RestoreBackupSetFullLsn"; + + + public const string RestoreBackupSetStartDate = "RestoreBackupSetStartDate"; + + + public const string RestoreBackupSetFinishDate = "RestoreBackupSetFinishDate"; + + + public const string RestoreBackupSetSize = "RestoreBackupSetSize"; + + + public const string RestoreBackupSetUserName = "RestoreBackupSetUserName"; + + + public const string RestoreBackupSetExpiration = "RestoreBackupSetExpiration"; + + private Keys() { } diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.de.resx b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.de.resx index 80860aa3..7f3e1dea 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.de.resx +++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.de.resx @@ -154,7 +154,7 @@ Abfrage wurde erfolgreich abgebrochen, Fehler beim Abfrage verfügen. Benutzer-URI nicht gefunden. - Abfrage wurde vom Benutzer abgebrochen. + Die Abfrage wurde vom Benutzer abgebrochen. Die Stapelverarbeitung ist noch nicht abgeschlossen @@ -358,7 +358,7 @@ Variable {0} ist nicht definiert. - EN_LOCALIZATION + Test Ersatz einer leeren Zeichenfolge durch eine leere Zeichenfolge. @@ -417,12 +417,24 @@ Spezifizierte URI '{0}' hat keine Standardverbindung + + Eine Commit-Anweisung wird ausgeführt. Bitte warten Sie bis zur Fertigstellung + + + Für die Decimal-Spalte fehlt die Angabe der Genauigkeit und Dezimalstellenanzahl + <TBD> Kann Zeile nicht an Ergebnisbuffer anhängen, da keine Zeilen im Datareader enthalten sind. + + Der Wert für eine Spalte vom Typ TIME muss zwischen 00:00:00.0000000 und 23:59:59.9999999 liegen + + + NULL ist für diese Spalte nicht erlaubt + Es gibt bereits eine Session @@ -453,6 +465,15 @@ Die Metadaten der Tabelle enthält keine erweiterten EIgenschaften. + + Tabelle oder Sicht zur Bearbeitung konnte nicht gefunden werden + + + Fehler beim Erweitern von: {0} + + + Fehler bei der Verbindung zu {0} + Aggregate @@ -897,9 +918,6 @@ Tabellentypindex - - ServerInstance - Selektive XML-Indexe @@ -936,4 +954,437 @@ Spaltenverschlüsselungsschlüssel + + Server + + + Fehler beim Analysieren der Eigenschaft ScriptingParams.ConnectionString. + + + Ungültiges Verzeichnis angeben in der Eigenschaft ScriptingParams.FilePath. + + + Fehler beim Analysieren der Eigenschaft ScriptingListObjectsCompleteParams.ConnectionString + + + {0} ({1}, {2}, {3}) + + + Kein Standard + + + Eingabe + + + Eingabe/Ausgabe + + + Eingabe/schreibgeschützt + + + Eingabe/Ausgabe/schreibgeschützt + + + Standard + + + NULL + + + nicht NULL + + + {0} ({1}, {2}) + + + {0} ({1}) + + + {0} ({1}berechnet, {2}, {3}) + + + {0} ({1}berechnet) + + + {0} (Spaltensatz, {1}) + + + {0} (Spaltensatz, {1} {2}, {3}) + + + {0} (Spaltensatz, {1}, {2}, {3}) + + + Eindeutig + + + Nicht eindeutig + + + Gruppiert + + + Nicht gruppiert + + + Verlauf + + + System-Mit Versionsangabe + + + Nicht verfügbar + + + Aktuelle Standarddateigruppe: {0} + + + Neue Dateigruppe für "{0}" + + + Standard + + + Dateien + + + Name + + + Schreibgeschützt + + + Automatische Vergrößerung/Maximale Größe + + + ... + + + <Standard> + + + Dateigruppe + + + Logischer Name + + + Dateityp + + + Anfangsgröße (MB) + + + <neue Dateigruppe> + + + Pfad + + + Dateiname + + + <unformatiertes Medium> + + + Massenprotokolliert + + + Vollständig + + + Einfach + + + Datenbankbesitzer auswählen + + + Kein(e) + + + Um {0} MB, auf {1} MB beschränkt + + + Um {0} Prozent, auf {1} MB beschränkt + + + Um {0} MB, unbegrenzt + + + Um {0} Prozent, unbegrenzt + + + Unbegrenzt + + + Auf {0} MB beschränkt + + + Automatisch + + + Service Broker + + + Sortierung + + + Cursor + + + Verschiedenes + + + Wiederherstellung + + + Status + + + ANSI NULL Default + + + ANSI NULLS aktiviert + + + ANSI-Auffüllung aktiviert + + + ANSI Warnings aktiviert + + + Abbruch bei arithmetischem Fehler aktiviert + + + Automatisch schließen + + + Statistik automatisch erstellen + + + Automatisch verkleinern + + + Statistiken automatisch aktualisieren + + + Statistik automatisch asynchron aktualisieren + + + Unterscheidung nach Groß-/Kleinschreibung + + + Schließen des Cursors nach Commit aktiviert + + + Sortierung + + + Verketten von NULL-Werten ergibt NULL + + + Datenbank-Kompatibilitätsgrad + + + Datenbankstatus + + + Standardcursor + + + Volltextindizierung aktiviert + + + Abbruch bei numerischem Runden + + + Seitenüberprüfung + + + Bezeichner in Anführungszeichen aktiviert + + + Datenbank schreibgeschützt + + + Rekursive Trigger aktiviert + + + Zugriff beschränken + + + Select Into/Bulk Copy + + + Brokerpriorität berücksichtigen + + + Service Broker-Bezeichner + + + Broker aktiviert + + + Protokoll bei Prüfpunkt abschneiden + + + Datenbankübergreifende Besitzverkettung aktiviert + + + Vertrauenswürdig + + + Optimierung der Datumskorrelation aktiviert: +prototype_db_prop_parameterization = Parameterization + + + Erzwungen + + + Einfach + + + ROWS (Daten) + + + LOG + + + FILESTREAM-Daten + + + Nicht zutreffend + + + <Standardpfad> + + + Geöffnete Verbindungen + + + Zum Ändern der Datenbankeigenschaften muss SQL Server alle anderen Verbindungen mit der Datenbank schließen. Möchten Sie wirklich die Eigenschaften ändern und alle anderen Verbindungen schließen? + + + AUTO_CLOSED + + + EMERGENCY + + + INACCESSIBLE + + + NORMAL + + + OFFLINE + + + RECOVERING + + + RECOVERY PENDING + + + RESTORING + + + SHUTDOWN + + + STANDBY + + + SUSPECT + + + GLOBAL + + + LOCAL + + + MULTI_USER + + + RESTRICTED_USER + + + SINGLE_USER + + + CHECKSUM + + + NONE + + + TORN_PAGE_DETECTION + + + VarDecimal-Speicherformat aktiviert + + + SQL Server 2008 (100) + + + Verschlüsselung aktiviert + + + AUS + + + EIN + + + PRIMÄR + + + Die Anzahl führender Hashspalten ist bei der HASH-Verteilungsrichtlinie optional, sollte aber zwischen 1 und 16 Spalten liegen. + + + SQL Server 2012 (110) + + + SQL Server 2014 (120) + + + SQL Server 2016 (130) + + + SQL Server vNext (140) + + + Kein(e) + + + Teilweise + + + FILESTREAM-Dateien + + + Keine anwendbare Dateigruppe + + + Auf die Datenbank "{0}" kann nicht zugegriffen werden. + + + Abfrage hat keine Ergebnis zum Zurückgeben + + + Ergebnismenge ist zu groß, um sicher geladen zu werden + + + Datenbank sichern + + + In Bearbeitung + + + Abgeschlossen + + + Parametrisierung + \ No newline at end of file diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.es.resx b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.es.resx index 747d97d4..7cd731a3 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.es.resx +++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.es.resx @@ -468,6 +468,12 @@ La tabla o vista solicitada para edición no se encuentra + + Error en expansión: {0} + + + Error conectando a {0} + Agregados @@ -520,7 +526,7 @@ Mensajes de error - Pertenencia a rol de servidor + Pertenencia a roles de servidor Opciones de base de datos @@ -583,7 +589,7 @@ Servidores vinculados - Inicios de sesión de servidores vinculados + Inicios de sesión de servidor vinculado Inicios de sesión @@ -625,7 +631,7 @@ Enlaces de servicio remoto - Columnas devueltas + Columnas devueltos Roles @@ -912,9 +918,6 @@ Índices de tipo de tabla - - instanciaDeServidor - Índices XML selectivos @@ -951,4 +954,436 @@ Claves de cifrado de columna + + Servidor + + + Error interpretando la propiedad ScriptingParams.ConnectionString + + + El directorio especificado en la propiedad ScriptingParams.FilePath no es válido + + + Error interpretando la propiedad ScriptingListObjectsCompleteParams.ConnectionString + + + {0} ({1}, {2}, {3}) + + + Sin valores predeterminados + + + Entrada + + + Entrada/salida + + + Entrada/solo lectura + + + Entrada/salida/solo lectura + + + Predeterminado + + + NULL + + + no es NULL + + + {0} ({1}, {2}) + + + {0} ({1}) + + + {0} ({1}calculado, {2}, {3}) + + + {0} ({1}calculado) + + + {0} (Conjunto de columnas, {1}) + + + {0} (Conjunto de columnas, {1}{2}, {3}) + + + {0} (Conjunto de columnas, {1}, {2}, {3}) + + + Único + + + No único + + + Clúster + + + No en clúster + + + Historial + + + Con versión del sistema + + + No disponible + + + Grupo de archivos predeterminado: {0} + + + Grupo de archivos nuevo para: {0} + + + Predeterminado + + + Archivos + + + Nombre + + + Solo lectura + + + Crecimiento automático / tamaño máximo + + + ... + + + <predeterminado> + + + Grupo de archivos + + + Nombre lógico + + + Tipo de archivo + + + Tamaño inicial (MB) + + + <nuevo grupo de archivos> + + + Ruta de acceso + + + Nombre de archivo + + + <dispositivo sin formato> + + + Registro masivo + + + Completo + + + Simple + + + Seleccionar propietario de base de datos + + + Ninguno + + + Por {0} MB, limitado a {1} MB + + + Por {0} porciento, limitado a {1} MB + + + Por {0} MB, sin límite + + + Por {0} porciento, sin límite + + + Sin límite + + + Limitado a {0} MB + + + Automático + + + Service Broker + + + Intercalación + + + Cursor + + + Varios + + + Recuperación + + + Estado + + + ANSI NULL predeterminado + + + ANSI NULLS habilitados + + + Relleno ANSI habilitado + + + Advertencias ANSI habilitadas + + + Anulación aritmética habilitada + + + Cierre automático + + + Crear estadísticas automáticamente + + + Reducir automáticamente + + + Actualizar estadísticas automáticamente + + + Actualizar estadísticas automáticamente de forma asincrónica + + + Sensible a mayúsculas y minúsculas + + + Cierre del cursor al confirmar habilitado + + + Intercalación + + + Concatenar valores NULL produce NULL + + + Nivel de compatibilidad de base de datos + + + Estado de la base de datos + + + Cursor predeterminado + + + Índice de texto completo habilitado + + + Anular redondeo numérico + + + Comprobación de página + + + Identificadores entre comillas habilitados + + + Base de datos de solo lectura + + + Desencadenadores recursivos habilitados + + + Restringir acceso + + + Select Into/Bulk Copy + + + Asignar prioridad de agente + + + Identificador de Service Broker + + + Broker habilitado + + + Truncar registro en el punto de control + + + Encadenamiento de propiedad entre bases de datos habilitado + + + De confianza + + + Optimización de correlación de fechas Enabledprototype_db_prop_parameterization = Parameterization + + + Forzado + + + Simple + + + Datos de ROWS + + + LOG + + + Datos de FILESTREAM + + + No aplicable + + + <ruta predeterminada> + + + Conexiones abiertas + + + Para cambiar las propiedades de la base de datos, SQL Server debe cerrar todas las otras conexiones a la base de datos. ¿Seguro que desea cambiar las propiedades y cerrar todas las otras conexiones? + + + AUTO_CLOSED + + + EMERGENCY + + + INACCESSIBLE + + + NORMAL + + + OFFLINE + + + RECOVERING + + + RECOVERY PENDING + + + RESTORING + + + SHUTDOWN + + + STANDBY + + + SUSPECT + + + GLOBAL + + + LOCAL + + + MULTI_USER + + + RESTRICTED_USER + + + SINGLE_USER + + + CHECKSUM + + + NONE + + + TORN_PAGE_DETECTION + + + Formato de almacenamiento VarDecimal habilitado + + + SQL Server 2008 (100) + + + Cifrado habilitado + + + OFF + + + ON + + + PRIMARY + + + Para la directiva de distribución HASH, el número de columnas iniciales hash es opcional pero debe de ser entre 1 y 16 columnas + + + SQL Server 2012 (110) + + + SQL Server 2014 (120) + + + SQL Server 2016 (130) + + + SQL Server vNext (140) + + + Ninguno + + + Parcial + + + Archivos FILESTREAM + + + Grupo de archivos no aplicable + + + La base de datos {0} no es accesible. + + + La consulta no devolvió resultados + + + El conjunto de resultados contiene demasiada filas para cargarlo de forma segura + + + Copia de seguridad de la base de datos + + + En curso + + + Completado + + + Parametrización + \ No newline at end of file diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.fr.resx b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.fr.resx index 14364185..0568000d 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.fr.resx +++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.fr.resx @@ -127,7 +127,7 @@ SpecifiedUri '{0}' n’a pas de connexion existante - Valeur non valide '{0}' pour AuthenticationType. Les valeurs valides sont « Intégré » et « SqlLogin ». + Valeur '{0}' non valide pour AuthenticationType. Les valeurs valides sont 'Integrated' et 'SqlLogin'. Valeur '{0}' non valide pour ApplicationIntent. Les valeurs valides sont 'ReadWrite' et 'ReadOnly'. @@ -145,13 +145,13 @@ ServerName ne peut pas être null ou vide - {0} ne peut pas être null ou vide lors de l’utilisation de l’authentification SqlLogin + {0} ne peut pas être nul ou vide quand l'authentification SqlLogin est utilisée - La requête a déjà terminé, il ne peut pas être annulée + La requête est déjà terminée, elle ne peut pas être annulée. - Requête annulée avec succès, n’a pas pu supprimer la requête. Propriétaire d’URI non trouvé. + Requête annulée avec succès, échec de la libération de la requête. L'URI propriétaire n'a pas été trouvée. La requête a été annulée par l’utilisateur @@ -163,16 +163,16 @@ Index de lot ne peut pas être inférieur à 0 ou supérieur au nombre de lots - Index du jeu de résultats ne peut pas être inférieur à 0 ou supérieur au nombre de jeux de résultats + L'index de résultats ne peut pas être inférieur à 0 ou supérieur au nombre de résultats - Nombre maximal d’octets à renvoyer doit être supérieur à zéro + Le nombre maximal d'octets à renvoyer doit être supérieur à zéro - Nombre maximal de caractères à renvoyer doit être supérieur à zéro + Le nombre maximal de caractères à renvoyer doit être supérieur à zéro - Nombre maximal d’octets XML pour renvoyer doit être supérieur à zéro + Le nombre maximal d’octets XML à renvoyer doit être supérieur à zéro Méthode d’accès ne peut pas être en écriture seule @@ -190,13 +190,13 @@ ({0} lignes affectées) - Commandes s’est terminées correctement. + Commandes terminées avec succès. Msg {0}, au niveau état {2}, {1}, ligne {3} {4} {5} - La requête a échoué : {0} + La requête a échoué : {0} (Aucun nom de colonne) @@ -217,40 +217,40 @@ Impossible d’enregistrer les résultats jusqu'à ce que l’exécution de la requête est terminée. - Une erreur interne s’est produite lors du démarrage d’enregistrement + Une erreur interne s'est produite lors du démarrage de la tâche de sauvegarde. - Une demande vers le même chemin de sauvegarde est en cours + Une requête de sauvegarde vers le même chemin est en cours Impossible d’enregistrer {0} : {1} - Impossible de lire le sous-ensemble, sauf si les résultats ont été lus à partir du serveur + Impossible de lire le sous-élément à moins que les résultats aient été lus depuis le serveur - Début de la ligne ne peut pas être inférieur à 0 ou supérieur au nombre de lignes dans le jeu de résultats + La ligne de début ne peut pas être inférieure à 0 ou supérieure au nombre de lignes de résultats - Nombre de lignes doit être un entier positif + Le nombre de lignes doit être un entier positif - Schéma de colonne de jeu de résultats n’a pas pu être récupérer + Impossible de récupérer le schéma des colonnes pour le jeu de résultats - Impossible de récupérer un plan d’exécution le jeu de résultats + Impossible de récupérer un plan d’exécution pour le jeu de résultats - Cette fonctionnalité n’est actuellement pas pris en charge sur la base de données SQL Azure et entrepôt de données : {0} + Cette fonctionnalité n'est actuellement pas supportée sur Azure SQL DB et Data Warehouse : {0} - Une erreur inattendue s’est produite lors de l’exécution de lire une définition : {0} + Une erreur inattendue s'est produite lors de l'exécution du coup d'oeil à la définition: {0}. - Aucun résultat n’a été trouvé. + Aucun résultat trouvé. - Aucun objet de base de données a été récupérée. + Aucun objet de base de données n'a été récupéré. Veuillez vous connecter à un serveur. @@ -259,113 +259,221 @@ Opération a expiré. - Ce type d’objet n’est actuellement pas pris en charge par cette fonctionnalité. + Ce type d'objet n'est actuellement pas supporté par cette fonctionnalité - Position est en dehors de la plage de ligne de fichier + La position est en dehors de la plage de lignes du fichier - Position est en dehors de la plage de colonnes de la ligne {0} + La position est en dehors de la plage de colonnes pour la ligne {0} Position de début ({0}, {1}) doit précéder ou être égale à la position de fin ({2}, {3}) - Msg {0}, {1}, niveau d’état {2}, ligne {3} + Msg {0}, Niveau {1}, État {2}, Ligne {3} - Msg {0}, {1}, niveau d’état {2}, procédure {3}, ligne {4} + Msg {0}, Niveau {1}, État {2}, Procédure {3}, Ligne {4} - Msg {0}, {1}, niveau d’état {2} + Msg {0}, Niveau {1}, État {2} - Une erreur s’est produite lors du traitement du lot. Le message d’erreur est : {0} + Une erreur s'est produite lors du traitement du lot. Le message d'erreur est : {0} ({0} lignes affectées) - L’exécution précédente n’est pas encore terminée. + L'exécution précédente n'est pas encore terminée. - Une erreur de script s’est produite. + Une erreur de script s'est produite. - Syntaxe incorrecte a été rencontrée pendant {0} était en cours d’analyse. + Une syntaxe incorrecte a été trouvée lors de l'analyse de {0}. - Une erreur irrécupérable s’est produite. + Une erreur irrécupérable s'est produite. - L’exécution effectuée {0} fois... + L'exécution a été effectuée {0} fois... Vous avez annulé la requête. - Une erreur s’est produite pendant le traitement par lots a été exécuté. + Une erreur s'est produite lors de l'exécution du lot. - Une erreur s’est produite pendant le traitement par lots a été exécuté, mais que l’erreur a été ignorée. + Une erreur s'est produite lors de l'exécution du lot, mais elle a été ignorée. - Démarrage de la boucle d’exécution de {0} fois... + Démarrage de la boucle d'exécution pour {0} fois... - La commande {0} n’est pas pris en charge. + La commande {0} n'est pas prise en charge. - La variable {0} est introuvable. + Impossible de trouver la variable {0}. Erreur d’exécution de SQL : {0} - Exécution du wrapper d’Analyseur de lot : {0} trouvé... à la ligne {1} : {2} Description : {3} + Exécution du wrapper de l'analyseur du lot : {0} trouvé... à la ligne {1} : {2} Description : {3} - Lot analyseur wrapper d’exécution moteur lot message reçu : Message : {0} message détaillé : {1} + Message reçu du lot du moteur d'exécution du wrapper de l'analyseur du lot : Message : {0} Message détaillé : {1} - Traitement du moteur par lots ResultSet pour analyseur wrapper d’exécution de lot : DataReader.FieldCount : {0} DataReader.RecordsAffected : {1} + Traitement du ResultSet du lot du moteur d'exécution du wrapper de l'analyseur du lot : DataReader.FieldCount : {0} DataReader.RecordsAffected : {1} - Lot de moteur analyseur wrapper d’exécution terminée de jeu de résultats. + ResultSet du lot du moteur d'exécution du wrapper de l'analyseur du lot terminé. - Annulation de l’exécution par lots wrapper analyseur du lot. + Annulation de l'exécution du lot du wrapper de l'analyseur du lot. - Avertissement pour le script. + Avertissement de script. - Pour plus d’informations sur cette erreur, consultez les rubriques de dépannage dans la documentation du produit. + Pour plus d'informations sur cette erreur, consultez les rubriques de dépannage dans la documentation du produit. - Le fichier '{0}' inclus de manière récursive. + Le fichier '{0}' a été inclus de manière récursive. - Pas de marque de fin de commentaire ' * /'. + La marque de commentaire de fin '*/' est manquante. - Ouvrez les guillemets après la chaîne de caractères. + Guillemets non fermés après la chaîne de caractères. - Syntaxe incorrecte a été rencontrée lors de l’analyse de '{0}'. + Détection d'une syntaxe incorrecte pendant l'analyse de '{0}'. - La variable {0} n’est pas défini. + La variable {0} n'est pas définie. - EN_LOCALIZATION + test Remplacement d’une chaîne vide à une chaîne vide. + + La session d'édition n’existe pas. + + + La requête n’a pas terminé l’exécution + + + La requête n’a pas généré exactement un jeu de résultats + + + Impossible d’ajouter la nouvelle ligne pour mettre à jour le cache + + + L'identifiant de ligne spécifié est en dehors de la plage de lignes dans le cache d’édition + + + Une mise à jour est déjà en attente pour cette ligne et doit être d’abord annulée + + + L'identifiant de la ligne n'a pas de mise à jour en attente + + + Les métadonnées de la table ou de la vue n’ont pas pu être trouvées + + + Format invalide pour une colonne binary + + + Les colonnes booléennes doivent être un numérique 1 ou 0, ou une chaîne true ou false + + + Une valeur de cellule requise est manquante. + + + Une suppression est en attente pour cette ligne, une mise à jour de cellule ne peut pas être appliquée. + + + La colonne Id doit être dans la plage des colonnes de la requête + + + La colonne ne peut pas être éditée + + + Aucune colonne clé n'a été trouvée + + + Un nom de fichier de sortie doit être fourni + + + L'objet de base de données {0} ne peut pas être utilisé pour éditer + + + L'Uri spécifiée '{0}' n’a pas de connexion par défaut + + + Une tâche commit est en cours. Veuillez, s'il vous plaît, attendre la fin. + + + La colonne decimal manque d'une précision numérique + <TBD> + + Impossible d'ajouter une ligne au tampon de résultats, le data reader ne contient aucune ligne + + + Les valeurs de colonne TIME doivent être contenues entre 00:00:00.0000000 et 23:59:59.9999999 + + + NULL n'est pas autorisé pour cette colonne + + + La session d'édition existe déjà. + + + La session d'édition n'a pas été initialisée + + + La session d'édition a déjà été initialisée + + + La session d'édition a déjà été initialisée ou est en cours d'initialisation + + + L'exécution de la requête a échoué, voir les messages pour plus de détails + + + La limite de résultat ne peut pas être négative + + + NULL + + + Un nom d'objet doit être fourni + + + La spécification explicite du serveur ou de la base de données n'est pas pris en charge + + + Les métadonnées de tables n'ont pas de propriétés étendues + + + La table ou la vue demandée pour édition n'a pas pu être trouvée + + + Erreur en développant : {0} + + + Erreur en se connectant à {0} + Agrégats @@ -810,9 +918,6 @@ Index de types de tables - - ServerInstance - Index XML sélectifs @@ -849,4 +954,436 @@ Clés de chiffrement de la colonne + + Serveur + + + Erreur en analysant la propriété ScriptingParams.ConnectionString. + + + Répertoire invalide spécifié pour la propriété ScriptingParams.FilePath. + + + Erreur en analysant la propriété ScriptingListObjectsCompleteParams.ConnectionString. + + + {0} ({1}, {2}, {3}) + + + Pas de valeur par défaut + + + Entrée + + + Entrée/sortie + + + Entrée/ReadOnly + + + Entrée/sortie/ReadOnly + + + Par défaut + + + Null + + + Non Null + + + {0} ({1}, {2}) + + + {0} ({1}) + + + {0} ({1}Calculé, {2}, {3}) + + + {0} ({1}Calculé) + + + {0} (Jeu de colonnes, {1}) + + + {0} (Jeu de colonnes, {1}{2}, {3}) + + + {0} (Jeu de colonnes, {1}, {2}, {3}) + + + Unique + + + Non unique + + + Ordonné en clusters + + + Non-Clustere + + + Historique + + + System-Versioned + + + Indisponible + + + Groupe de fichiers par défaut actuel : {0} + + + Nouveau groupe de fichiers pour {0} + + + Par défaut + + + Fichiers + + + Nom + + + Lecture seule + + + Redimensionnement automatique / Taille max + + + ... + + + <par défaut> + + + Groupe de fichiers + + + Nom logique + + + Type de fichier + + + Taille initiale (Mo) + + + <new filegroup> + + + Chemin d'accès + + + Nom de fichier  + + + <raw device> + + + Bulk-logged + + + Full + + + Simple + + + Sélectionner le propriétaire de base de données + + + Aucune + + + Par {0} Mo, Limité à {1} Mo + + + Par {0} %, Limité à {1} Mo + + + Par {0} Mo, Illimité + + + Par {0} %, Illimité + + + Illimité + + + Limité à {0} Mo + + + Automatique + + + Service Broker + + + Classement + + + Curseur + + + Divers + + + Restauration + + + État + + + Paramètre par défaut ANSI NULL + + + Valeurs ANSI NULLS activées + + + Padding ANSI activé + + + ANSI Warnings activés + + + Annulation arithmétique (Arithmetic Abort) activée + + + Fermeture automatique + + + Création automatique des statistiques + + + Réduction automatique + + + Mise à jour automatique des statistiques + + + Mise à jour automatique des statistiques en mode asynchrone + + + Sensible à la casse + + + Fermeture du curseur lors de la validation activée + + + Classement + + + La concaténation de la valeur Null donne Null + + + Niveau de compatibilité de la base de données + + + État de la base de données + + + Curseur par défaut + + + Indexation de texte intégral activée + + + Abandon en cas d'arrondi numérique + + + Vérification de la page : + + + Identificateurs entre guillemets activés + + + Base de données en lecture seule + + + Déclencheurs récursifs activés + + + Restreindre l'accès + + + Select Into / Bulk Copy + + + Priorité du service Broker respectée + + + Identifant de Service Broker + + + Broker activé + + + Truncate Log on Checkpoint + + + Chaînage des propriétés des bases de données croisées activé + + + Digne de confiance + + + Date Correlation Optimization Enabledprototype_db_prop_parameterization = Parameterization + + + Forcé + + + Simple + + + Données ROWS + + + LOG + + + Données FILESTREAM + + + Non applicable + + + <default path> + + + Ouvrir les connexions + + + Pour changer les propriétés de la base de données, SQL Server doit fermer toutes les autres connexions à la base de données. Etes-vous sûr de vouloir changer les propriétés et fermer toutes les autres connexions ? + + + AUTO_CLOSED + + + EMERGENCY + + + INACCESSIBLE + + + NORMAL + + + OFFLINE + + + RECOVERING + + + RECOVERY PENDING + + + RESTORING + + + SHUTDOWN + + + STANDBY + + + SUSPECT + + + GLOBAL + + + LOCAL + + + MULTI_USER + + + RESTRICTED_USER + + + SINGLE_USER + + + CHECKSUM + + + NONE + + + TORN_PAGE_DETECTION + + + Format de stockage VarDecimal activé + + + SQL Server 2008 (100) + + + Chiffrement activé + + + OFF + + + ON + + + PRIMARY + + + Pour la politique de distribution HASH, le nombre de colonnes hash qui débutent est optionnel mais devrait être entre 1 et 16 colonnes. + + + SQL Server 2012 (110) + + + SQL Server 2014 (120) + + + SQL Server 2016 (130) + + + SQL Server vNext (140) + + + Aucun + + + Partiel + + + Fichiers FILESTREAM + + + Aucun groupe de fichiers applicable + + + La base de données {0} est inaccessible. + + + La requête n'a aucun résultat à retourner + + + Le jeu de résultats a trop de lignes pour être chargé en toute sécurité + + + Sauvegarder la base de données + + + En cours + + + Terminé + + + Paramétrage + \ No newline at end of file diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.it.resx b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.it.resx index 8a20a2ae..155573af 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.it.resx +++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.it.resx @@ -358,7 +358,7 @@ Variabile {0} non è definita. - EN_LOCALIZATION + test Sostituzione di una stringa vuota con una stringa vuota. @@ -468,6 +468,12 @@ Impossibile trovare la Tabella o la Vista necessarie alla modifica + + Errore durante l'espansione dell'oggetto: {0} + + + Errore durante la connessione a {0}' + Aggregazioni @@ -912,9 +918,6 @@ Indici del tipo di tabella - - ServerInstance - Indici XML selettivi @@ -951,4 +954,436 @@ Chiavi di crittografia della colonna + + Server + + + Errore durante l'analisi della proprietà ScriptingParams.ConnectionString. + + + La Directory specificata dalla proprietà ScriptingParams.FilePath non è valida. + + + Errore durante l'analisi della proprietà ScriptingListObjectsCompleteParams.ConnectionString. + + + {0} ({1}, {2}, {3}) + + + Nessun valore predefinito + + + Input + + + Input/Output + + + Input/ReadOnly + + + Input/Output/ReadOnly + + + Predefinito + + + Null + + + non Null + + + {0} ({1}, {2}) + + + {0} ({1}) + + + {0} ({1} calcolato, {2}, {3}) + + + {0} ({1} calcolato) + + + {0} (Set di colonne: {1}) + + + {0} (Set di colonne: {1} {2}, {3}) + + + {0} (Set di colonne: {1}, {2}, {3}) + + + Univoco + + + Non univoco + + + Cluster + + + Non cluster + + + Cronologia + + + Con controllo delle versioni di sistema + + + Non disponibile + + + Filegroup predefinito corrente: {0} + + + Nuovo Filegroup per {0} + + + Predefinito + + + File + + + Nome + + + Sola lettura + + + Aumento automatico / Maxsize + + + ... + + + <predefinito> + + + Filegroup + + + Nome logico + + + Tipo di file + + + Dimensioni iniziali (MB) + + + <nuovo Filegroup> + + + Percorso + + + Nome file + + + <dispositivo RAW> + + + Registrazione delle operazioni bulk + + + Completo + + + Semplice + + + Seleziona il proprietario del Database + + + Nessuno + + + Di {0} MB, limitato a {1} MB + + + Di {0} percento, limitato a {1} MB + + + Di {0} MB, illimitato + + + Di {0} percento, illimitato + + + Senza limiti + + + Limitato a {0} MB + + + Automatico + + + Service Broker + + + Regole di confronto + + + Cursore + + + Varie + + + Recupero + + + Stato + + + Impostazione predefinita ANSI NULL + + + ANSI NULLS abilitati + + + ANSI Padding abilitato + + + Avvisi ANSI abilitati + + + Arithmetic Abort abilitata + + + Chiusura automatica + + + Creazione statistiche automatica + + + Compattazione automatica + + + Aggiornamento statistiche automatico + + + Aggiornamento statistiche asincrono automatico + + + Distinzione maiuscole/minuscole + + + Chiusura cursore in caso di commit abilitata + + + Regole di confronto + + + La concatenazione di valori Null restituisce valori Null + + + Livello di compatibilità del database + + + Stato database + + + Cursore predefinito + + + Indicizzazione full-text + + + Interruzione per perdita di precisione numerica + + + Verifica pagina + + + Identificatori delimitati abilitati + + + Database di sola lettura + + + Trigger ricorsivi abilitati + + + Limitazione accesso + + + Select Into/Bulk Copy + + + Rispetta priorità di Service Broker + + + Identificatore Service Broker + + + Broker abilitato + + + Tronca Log al Checkpoint + + + Concatenamento della proprietà tra database abilitato + + + Trustworthy + + + Ottimizzazione correlazione date Enabledprototype_db_prop_parameterization = parametrizzazione + + + Forzato + + + Semplice + + + Dati RIGHE + + + LOG + + + Dati FILESTREAM + + + Non applicabile + + + <percorso predefinito> + + + Connessioni aperte + + + Per modificare le proprietà del database, SQL Server deve chiudere tutte le altre connessioni al database_ Sei sicuro di voler modificare le proprietà e chiudere tutte le altre connessioni? + + + AUTO_CLOSED + + + EMERGENCY + + + INACCESSIBLE + + + NORMAL + + + OFFLINE + + + RECOVERING + + + RECOVERY PENDING + + + RESTORING + + + SHUTDOWN + + + STANDBY + + + SUSPECT + + + GLOBAL + + + LOCAL + + + MULTI_USER + + + RESTRICTED_USER + + + SINGLE_USER + + + CHECKSUM + + + NONE + + + TORN_PAGE_DETECTION + + + Formato di archiviazione VarDecimal abilitato + + + SQL Server 2008 (100) + + + Crittografia abilitata + + + OFF + + + ON + + + PRIMARY + + + Per il criterio di distribuzione HASH, il numero di colonne iniziali di hash è facoltativo, ma dovrebbe essere da 1 a 16 colonne + + + SQL Server 2012 (110) + + + SQL Server 2014 (120) + + + SQL Server 2016 (130) + + + SQL Server vNext (140) + + + Nessuno + + + Parziale + + + File FILESTREAM + + + Nessun Filegroup applicabile + + + Il database {0} non è accessibile. + + + La query non ha risultati da restituire + + + L'insieme di risultati ha troppe righe per essere caricato in modo sicuro + + + Backup database + + + In corso + + + Completato + + + Parametrizzazione + \ No newline at end of file diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.ja.resx b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.ja.resx index 76cad177..b0fb3745 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.ja.resx +++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.ja.resx @@ -358,7 +358,7 @@ 変数 {0} が定義されていません。 - EN_LOCALIZATION + テスト 空の文字列で空の文字列を置換しています。 @@ -468,6 +468,12 @@ 編集を要求したテーブルもしくはビューが見つかりませんでした。 + + '{0}' の拡張中にエラーが発生しました。 + + + {0} への接続中にエラーが発生しました + 集約 @@ -912,9 +918,6 @@ テーブル型インデックス - - ServerInstance - 選択的 XML インデックス @@ -951,4 +954,437 @@ 列暗号化キー + + サーバー + + + ScriptingParams.ConnectionString プロパティの解析エラーです。 + + + ScriptingParams.FilePath プロパティで指定されたディレクトリが無効です。 + + + ScriptingListObjectsCompleteParams.ConnectionString プロパティの解析エラーです。 + + + {0} ({1}、{2}、{3}) + + + 既定値以外 + + + 入力 + + + 入力/出力 + + + 入力/読み取り専用 + + + 入力/出力/読み取り専用 + + + 既定値 + + + NULL + + + NULL 以外 + + + {0} ({1}、{2}) + + + {0} ({1}) + + + {0} ({1} 計算値、{2}、{3}) + + + {0} ({1} 計算値) + + + {0} (列セット、{1}) + + + {0} (列セット、{1}{2}、{3}) + + + {0} (列セット、{1}、{2}、{3}) + + + 一意 + + + 一意でない + + + クラスター化 + + + 非クラスター + + + 履歴 + + + システムバージョン管理 + + + 使用不可 + + + 現在の既定のファイル グループ: {0} + + + 新しいファイルグループ {0} + + + 既定値 + + + ファイル + + + 名前 + + + 読み取り専用 + + + 自動拡張 / 最大容量 + + + ... + + + <既定> + + + ファイル グループ + + + 論理名 + + + ファイルタイプ + + + 初期サイズ (MB) + + + <新しいファイルグループ> + + + パス + + + ファイル名 + + + <RAWデバイス> + + + 一括ログ + + + 完全 + + + 単純 + + + データベース 所有者の選択 + + + なし + + + {0} MBごと、{1} MBを上限 + + + {0} パーセントごと、{1} MBまで + + + {0} MBごと、無制限 + + + {0} パーセントごと、無制限 + + + 無制限 + + + {0} MBまで + + + 自動 + + + Service Broker + + + 照合順序 + + + カーソル + + + その他 + + + 復旧 + + + 状態 + + + ANSI NULL 既定値 + + + ANSI NULLS 有効 + + + ANSI Padding 有効 + + + ANSI 警告有効 + + + 算術アボート有効 + + + 自動クローズ + + + 統計の自動作成 + + + 自動圧縮 + + + 統計の自動更新 + + + 統計の非同期的自動更新 + + + 大文字と小文字を区別する + + + コミットでカーソルを閉じる + + + 照合順序 + + + Nullとの連結をNullとして取り扱う + + + データベース互換性レベル + + + データベース状態 + + + 既定のカーソル + + + フルテキスト インデックス 有効化 + + + 数値丸め処理アボート + + + ページ確認 + + + 引用符で囲まれた識別子が有効 + + + 読み取り専用データベース + + + 再帰トリガー有効 + + + アクセスの制限 + + + Select Into/ バルクコピー + + + Broker の優先度の許可 + + + Service Broker 識別子 + + + ブローカー有効化 + + + チェックポイントでのログの切り捨て + + + 複数データベースの組み合わせ所有権有効 + + + 信頼可能 + + + データ相関性の最適化 +Enabledprototype_db_prop_parameterization = Parameterization + + + 強制 + + + 単純 + + + 列データ + + + ログ + + + FILESTREAM データ + + + 適用不可 + + + <既定のパス> + + + コネクションを開く + + + データベースのプロパティを変更するには、SQL Server はデータベースへの他のすべての接続を閉じる必要があります。プロパティを変更して、他のすべての接続を閉じてよろしいですか? + + + AUTO_CLOSED + + + EMERGENCY + + + INACCESSIBLE + + + NORMAL + + + OFFLINE + + + RECOVERING + + + RECOVERY PENDING + + + RESTORING + + + SHUTDOWN + + + STANDBY + + + SUSPECT + + + GLOBAL + + + LOCAL + + + MULTI_USER + + + RESTRICTED_USER + + + SINGLE_USER + + + CHECKSUM + + + NONE + + + TORN_PAGE_DETECTION + + + VarDecimal ストレージ形式有効 + + + SQL Server 2008 (100) + + + 暗号化有効 + + + OFF + + + ON + + + PRIMARY + + + 配布ポリシーのハッシュでは、ハッシュの先頭列の番号は任意ですが、1 から 16 個の列にする必要があります + + + SQL Server 2012 (110) + + + SQL Server 2014 (120) + + + SQL Server 2016 (130) + + + SQL Server vNext (140) + + + なし + + + 部分的 + + + FILESTREAM ファイル + + + 適用不可なファイルグループ + + + データベース {0} にアクセスできません。 + + + クエリーは結果を返しませんでした + + + 結果セットの行数が多すぎるため安全にロードすることはできません + + + データベースをバックアップする + + + 実行中 + + + 完了 + + + パラメーター化 + \ No newline at end of file diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.ko.resx b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.ko.resx index 3f2a0a6c..09a36a29 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.ko.resx +++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.ko.resx @@ -358,7 +358,7 @@ {0} 변수가 정의되지 않았습니다. - EN_LOCALIZATION + 테스트 @@ -422,9 +422,15 @@ votes 커밋 작업이 진행 중입니다. 완료될 때까지 기다리세요. + + Decimal 형식 열에 전체 자릿수 또는 소수 자릿수가 없습니다. + <TBD> + + 결과 버퍼에 새로운 행을 추가할 수 없거나 데이터 리더에 행이 없습니다. + TIME 열의 값은 00:00:00.0000000과 23:59:59.9999999 사이의 값만 허용됩니다. @@ -464,6 +470,12 @@ votes 편집하려는 테이블이나 뷰를 찾을 수 없습니다 + + 오류 확장: {0} + + + {0}에 연결하는 동안 오류가 발생했습니다. + 집계 @@ -908,9 +920,6 @@ votes 테이블 형식 인덱스 - - ServerInstance - 선택적 XML 인덱스 @@ -947,4 +956,436 @@ votes 열 암호화 키 + + 서버 + + + ScriptingParams.ConnectionString 속성 분석을 하는 동안 오류가 발생했습니다. + + + ScriptingParams.FilePath 속성에 잘못된 디렉터리 지정 + + + ScriptingListObjectsCompleteParams.ConnectionSring 속성을 분석할때 오류가 생겼습니다. + + + {0}({1}, {2}, {3}) + + + 기본값 없음 + + + 입력 + + + 입/출력 + + + 입력/읽기 전용 + + + 입/출력/읽기 전용 + + + 기본값 + + + Null + + + Not Null + + + {0}({1}, {2}) + + + {0}({1}) + + + {0}({1}계산됨, {2}, {3}) + + + {0}({1}계산됨) + + + {0}(열 집합, {1}) + + + {0}(열 집합, {1}{2}, {3}) + + + {0}(열 집합, {1}, {2}, {3}) + + + 고유 + + + 고유하지 않음 + + + 클러스터형 + + + 비클러스터형 + + + 기록 + + + 시스템 버전 관리 + + + 사용할 수 없음 + + + 현재 기본 파일 그룹: {0} + + + {0}에 대한 새 파일 그룹 + + + 기본값 + + + 파일 + + + 이름 + + + 읽기 전용 + + + 자동 증가 / 최대 크기 + + + ... + + + <기본값> + + + 파일 그룹 + + + 논리적 이름 + + + 파일 형식 + + + 처음 크기 (MB) + + + <새 파일 그룹> + + + 경로 + + + 파일 이름 + + + <원시 장치> + + + 대량 로그 + + + 전체 + + + 단순 + + + 데이터베이스 소유자 선택 + + + 없음 + + + {0} MB 단위로 {1} MB까지 제한됨 + + + {0} % 단위로 {1} MB까지 제한됨 + + + {0} MB 단위로, 제한 없음 + + + {0} % 단위로, 제한 없음 + + + 제한 없음 + + + {0} MB로 제한됨 + + + 자동 + + + Service Broker + + + 데이터 정렬 + + + 커서 + + + 기타 + + + 복구 + + + 상태 + + + ANSI NULL 기본값 + + + ANSI NULLS 사용 + + + ANSI 패딩 설정 + + + ANSI Warnings 사용 + + + 산술 연산 중단 설정 + + + 자동 닫기 + + + 통계 자동 작성 + + + 자동 축소 + + + 통계 자동 업데이트 + + + 통계를 비동기적으로 자동 업데이트 + + + 대/소문자 구분 + + + 커밋 시 커서 닫기 설정 + + + 데이터 정렬 + + + Null 연결 시 Null 생성 + + + 데이터베이스 호환성 수준 + + + 데이터베이스 상태 + + + 기본 커서 + + + 전체 텍스트 인덱싱 설정 + + + 숫자 반올림 시 중단 + + + 페이지 확인 + + + 따옴표 붙은 식별자 설정 + + + 데이터베이스 읽기 전용 + + + 재귀적 트리거 설정 + + + 액세스 제한 + + + SELECT INTO/대량 복사 + + + Broker 우선 순위 인식 + + + Service Broker 식별자 + + + Broker 활성화 + + + 검사점에서 로그 자름 + + + 데이터베이스 간 소유권 체인 사용 + + + 신뢰 + + + 날짜 상관관계 최적화 설정 + + + 강제 + + + 단순 + + + ROWS 데이터 + + + 로그 + + + FILESTREAM 데이터 + + + 해당 사항 없음 + + + <기본 경로> + + + 연결 열기 + + + 데이터베이스 속성을 변경하기 위해, SQL Server가 database_ 에  다른 연결을 모두 닫아야 합니다. 속성을 변경하고 다른 연결을 모두 닫으시겠습니까? + + + AUTO_CLOSED + + + 긴급 + + + INACCESSIBLE + + + NORMAL + + + 오프라인 + + + 복구 중 + + + 복구 보류 중 + + + RESTORING + + + SHUTDOWN + + + STANDBY + + + SUSPECT + + + GLOBAL + + + LOCAL + + + MULTI_USER + + + RESTRICTED_USER + + + SINGLE_USER + + + CHECKSUM + + + NONE + + + TORN_PAGE_DETECTION + + + VarDecimal 저장소 형식 사용 + + + SQL Server 2008 (100) + + + 암호화 사용 + + + OFF + + + ON + + + PRIMARY + + + 배포 정책이 HASH인 경우 선행 해시 열 수는 선택 사항이지만, 선택할 경우 1개에서 16개 사이의 열로 지정해야 합니다. + + + SQL Server 2012 (110) + + + SQL Server 2014 (120) + + + SQL Server 2016 (130) + + + SQL Server vNext (140) + + + 없음 + + + 부분 + + + FILESTREAM 파일 + + + 해당 파일 그룹 없음 + + + {0} 데이터베이스에 액세스할 수 없습니다. + + + 쿼리 반환 결과 없음 + + + 결과 집합의 행 수가 너무 많아서 안전하게 불러들일 수 없습니다. + + + 데이터베이스 백업 + + + 진행 중 + + + 완료됨 + + + 매개 변수화 + \ No newline at end of file diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.pt-BR.resx b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.pt-BR.resx index 24cd7925..385d2ab1 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.pt-BR.resx +++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.pt-BR.resx @@ -358,7 +358,7 @@ A variável {0} não está definida. - EN_LOCALIZATION + teste Substituição de uma sequência vazia por uma cadeia de caracteres vazia. @@ -919,9 +919,6 @@ Índices de Tipos de Tabelas - - ServerInstance - Índices XML Seletivos @@ -958,4 +955,436 @@ Chaves de Criptografia de Colunas + + Servidor + + + Erro ao analisar a propriedade ScriptingParams.ConnectionString. + + + Diretório inválido especificado pela propriedade ScriptingParams.FilePath. + + + Erro ao analisar a propriedade ScriptingListObjectsCompleteParams.ConnectionString. + + + {0} ({1}, {2}, {3}) + + + Nenhum padrão + + + Entrada + + + Entrada/Saída + + + Entrada/SomenteLeitura + + + Entrada/Saída/SomenteLeitura + + + Padrão + + + nulo + + + não nulo + + + {0} ({1}, {2}) + + + {0} ({1}) + + + {0} ({1} Computado, {2}, {3}) + + + {0} ({1}Computado) + + + {0} (Conjunto de Colunas, {1}) + + + {0} (Conjunto de Colunas, {1}{2}, {3}) + + + {0} (Conjunto de Colunas, {1}, {2}, {3}) + + + Exclusivo + + + Não Exclusivo + + + Clusterizado + + + Não Clusterizado + + + Histórico + + + Versionado pelo sistema + + + Indisponível + + + Grupo de arquivos padrão atual: {0} + + + Novo Grupo de Arquivos para {0} + + + Padrão + + + Arquivos + + + Nome + + + Somente Leitura + + + Auto crescimento / Tamanho máximo + + + ... + + + <padrão> + + + Grupo de Arquivos + + + Nome Lógico + + + Tipo de Arquivo + + + Tamanho Inicial (MB) + + + <novo grupo de arquivos> + + + Caminho + + + Nome do Arquivo + + + <dispositivo bruto> + + + Logado em massa + + + Completo + + + Simples + + + Selecionar o proprietário do banco de dados + + + Nenhum + + + Por {0} MB, limitado a {1} MB + + + Por {0}%, Limitado a {1} mb + + + Por {0} MB, Ilimitado + + + Por {0}%, Ilimitado + + + Ilimitado + + + Limitado a {0} MB + + + Automático + + + Service Broker + + + Agrupamento + + + Cursor + + + Diversos + + + Recuperação + + + Estado + + + Padrão ANSI NULL + + + ANSI NULLS Habilitado + + + Preenchimento ANSI habilitado + + + ANSI Warnings Habilitados + + + Arithmetic Abortar habilitado + + + Fechamento automático + + + Criar Estatísticas Automaticamente + + + Reduzir Automaticamente + + + Estatísticas Atualizadas Automaticamente + + + Atualizar estatísticas automaticamente de forma assíncrona + + + Sensível à Caixa + + + Fechar Cursor na Confirmação Habilitado + + + Agrupamento + + + Concatenar Nulo Produz Nulo + + + Nível de Compatibilidade do Banco de Dados + + + Estado do Banco de Dados + + + Cursor Padrão + + + Indexação Full-Text Habilitada + + + Anular arredondamento numérico. + + + Verificação de Página + + + Identificadores Entre Aspas Habilitados + + + Banco de Dados Somente Leitura + + + Gatilhos Recursivos Habilitados + + + Acesso Restrito + + + Selecionar Cópia Into/Em Massa + + + Respeitar a Prioridade do Broker + + + Identificador de agente de serviço + + + Agente habilitado + + + Truncar o Log no Ponto de Verificação + + + Encadeamento de Propriedades de Bancos de Dados Habilitado + + + Confiável + + + Otimizaçao da Correlação de Data Enabledprototype_db_prop_parameterization = Parametrização + + + Forçado + + + Simples + + + Dados ROWS + + + LOG + + + Dados FILESTREAM + + + Não aplicável + + + <caminho padrão> + + + Conexões Abertas + + + Para modificar as propriedades do banco de dados, o SQL Server deve fechar todas as outras conexões ao banco de dados_ Tem certeza que você quer modificar as propriedades e fechar todas as outras conexões? + + + AUTO_CLOSED + + + EMERGÊNCIA + + + INACESSÍVEL + + + NORMAL + + + OFF-LINE + + + RECUPERANDO + + + RECUPERAÇÃO PENDENTE + + + RESTAURANDO + + + DESLIGAMENTO + + + MODO DE ESPERA + + + SUSPEITO + + + GLOBAL + + + LOCAL + + + MULTI_USUÁRIO + + + USUÁRIO_RESTRITO + + + MONO_USUÁRIO + + + SOMA DE VERIFICAÇÃO + + + NENHUM + + + TORN_PAGE_DETECTION + + + Formato de Armazenamento VarDecimal Habilitado + + + SQL Server 2008 (100) + + + Criptografia Habilitada + + + DESLIGADO + + + LIGADO + + + PRIMÁRIO + + + Para a política de distribuição de HASH, o número de colunas hash principais é opcional, mas deve ser de 1 a 16 colunas + + + SQL Server 2012 (110) + + + SQL Server 2014 (120) + + + SQL Server 2016 (130) + + + SQL Server vNext (140) + + + Nenhum + + + Parcial + + + Arquivos FILESTREAM + + + Nenhum grupo de arquivos aplicável + + + O banco de dados {0} não está acessível. + + + A consulta não tem resultado para retornar + + + Conjunto de resultados tem muitas linhas para ser carregado com segurança + + + Fazer Backup do Banco de Dados + + + Em andamento + + + Concluído + + + Parametrização + \ No newline at end of file diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.resx b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.resx index 15c5345c..5dcda5ca 100755 --- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.resx +++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.resx @@ -1847,4 +1847,68 @@ Restore Database + + (Copy Only) + + + + Component + + + + Name + + + + Type + + + + Server + + + + Database + + + + Position + + + + First LSN + + + + Last LSN + + + + Checkpoint LSN + + + + Full LSN + + + + Start Date + + + + Finish Date + + + + Size + + + + User Name + + + + Expiration + + diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.ru.resx b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.ru.resx index 0600767d..dd814d7c 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.ru.resx +++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.ru.resx @@ -358,7 +358,7 @@ Переменная {0} не определена. - EN_LOCALIZATION + тест Замена пустой строки на пустую строку. @@ -468,6 +468,12 @@ Запрошенная таблица или представление не найдены. + + Ошибка при расширении: {0} + + + Ошибка при подключении к {0} + Статистические выражения @@ -912,9 +918,6 @@ Индексы типов таблиц - - ServerInstance - Селективные XML-индексы @@ -951,4 +954,436 @@ Ключи шифрования столбца + + Сервер + + + Ошибка при анализе свойства ScriptingParams.ConnectionString. + + + Недопустимый каталог указан в свойстве ScriptingParams.FilePath. + + + Ошибка при анализе свойства ScriptingListObjectsCompleteParams.ConnectionString. + + + {0} ({1}, {2}, {3}) + + + Нет значения по умолчанию + + + Входной + + + Входной/выходной + + + Входной/только для чтения + + + Входной/выходной/только для чтения + + + Значение по умолчанию + + + null + + + not null + + + {0} ({1}, {2}) + + + {0} ({1}) + + + {0} (вычислено {1}, {2}, {3}) + + + {0} (вычислено {1}) + + + {0} (набор столбцов, {1}) + + + {0} (набор столбцов, {1}{2}, {3}) + + + {0} (набор столбцов, {1}, {2}, {3}) + + + UNIQUE + + + Неуникальный + + + Кластеризованный + + + Некластеризованный + + + Журнал + + + Системно-версионный + + + Недоступно + + + Текущая файловая группа по умолчанию: {0} + + + Создание файловой группы для {0} + + + Значение по умолчанию + + + Файлы + + + Имя + + + Только для чтения + + + Автоувеличение/максимальный размер + + + ... + + + <по умолчанию> + + + Группа файлов + + + Логическое имя + + + Тип файла + + + Начальный размер (МБ) + + + <создать файловую группу> + + + Путь + + + Имя файла + + + <неформатированный носитель> + + + С неполным протоколированием + + + Полная + + + Простая + + + Выбор владельца базы данных + + + Нет + + + С шагом по {0} МБ до {1} МБ + + + С шагом по {0}% до {1} МБ + + + С шагом по {0} МБ, без ограничений + + + С шагом по {0} %, без ограничений + + + Без ограничений + + + Ограничено {0} МБ + + + Автоматически + + + Service Broker + + + Параметры сортировки + + + Курсор + + + Прочее + + + Восстановление + + + Состояние + + + По умолчанию ANSI NULL + + + Значения ANSI NULLS включены + + + Включено заполнение ANSI + + + Включены предупреждения ANSI + + + Включено прерывание при делении на ноль + + + Auto Close + + + Автоматическое создание статистики + + + Автоматическое сжатие + + + Автоматическое обновление статистики + + + Асинхронное автообновление статистики + + + Case Sensitive + + + Закрывать курсор при разрешении фиксации + + + Параметры сортировки + + + Объединение со значением NULL дает NULL + + + Уровень совместимости базы данных + + + Состояние базы данных + + + Курсор по умолчанию + + + Полнотекстовое индексирование включено + + + Автоокругление чисел + + + Проверка страниц + + + Включены заключенные в кавычки идентификаторы + + + База данных только для чтения + + + Включены рекурсивные триггеры + + + Ограничение доступа + + + Выбор/Массовое копирование + + + Учитывать приоритет компонента Honor Broker + + + Идентификатор компонента Service Broker + + + Включен компонент Broker + + + Усечение журнала на контрольной точке + + + Межбазовые цепочки владения включены + + + Заслуживает доверия + + + Date Correlation Optimization Enabledprototype_db_prop_parameterization = Parameterization + + + Принудительное + + + Простая + + + Данные СТРОК + + + ЖУРНАЛ + + + Данные FILESTREAM + + + Неприменимо + + + <default path> + + + Открытые соединения + + + Чтобы изменить свойства базы данных, SQL Server должен закрыть все остальные соединения с этой базой данных. Изменить свойства и закрыть остальные соединения? + + + AUTO_CLOSED + + + EMERGENCY + + + INACCESSIBLE + + + NORMAL + + + OFFLINE + + + RECOVERING + + + RECOVERY PENDING + + + RESTORING + + + SHUTDOWN + + + STANDBY + + + SUSPECT + + + GLOBAL + + + LOCAL + + + MULTI_USER + + + RESTRICTED_USER + + + SINGLE_USER + + + CHECKSUM + + + Нет + + + TORN_PAGE_DETECTION + + + Включен формат хранения VarDecimal + + + SQL Server 2008 (100) + + + Шифрование включено + + + ОТКЛ. + + + ВКЛ. + + + ПЕРВИЧНЫЙ + + + Для политики распространения HASH количество начальных хэш-столбцов указывать не обязательно. Оно может составлять от 1 до 16 столбцов + + + SQL Server 2012 (110) + + + SQL Server 2014 (120) + + + SQL Server 2016 (130) + + + SQL Server vNext (140) + + + Нет + + + Частично + + + Файлы FILESTREAM + + + Применимая файловая группа отсутствует + + + База данных {0} недоступна. + + + запрос не имеет результатов + + + Pезультатов слишком много строк для безопасной загрузки + + + Резервное копирование базы данных + + + Выполняется + + + Завершен + + + Параметризация + \ No newline at end of file diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.strings b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.strings index 2616a842..f9b8ca62 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.strings +++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.strings @@ -819,4 +819,20 @@ InvalidPathForDatabaseFile = Invalid path for database file: '{0}' Log = Log RestorePlanFailed = Failed to create restore plan RestoreNotSupported = Restore database is not supported -RestoreTaskName = Restore Database \ No newline at end of file +RestoreTaskName = Restore Database +RestoreCopyOnly = (Copy Only) +RestoreBackupSetComponent = Component +RestoreBackupSetName = Name +RestoreBackupSetType = Type +RestoreBackupSetServer = Server +RestoreBackupSetDatabase = Database +RestoreBackupSetPosition = Position +RestoreBackupSetFirstLsn = First LSN +RestoreBackupSetLastLsn = Last LSN +RestoreBackupSetCheckpointLsn = Checkpoint LSN +RestoreBackupSetFullLsn = Full LSN +RestoreBackupSetStartDate = Start Date +RestoreBackupSetFinishDate = Finish Date +RestoreBackupSetSize = Size +RestoreBackupSetUserName = User Name +RestoreBackupSetExpiration = Expiration \ No newline at end of file diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.xlf b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.xlf index 066273ab..d1fa9fab 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.xlf +++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.xlf @@ -2159,6 +2159,86 @@ Restore Database + + (Copy Only) + (Copy Only) + + + + Component + Component + + + + Type + Type + + + + Server + Server + + + + Database + Database + + + + Position + Position + + + + First LSN + First LSN + + + + Last LSN + Last LSN + + + + Checkpoint LSN + Checkpoint LSN + + + + Full LSN + Full LSN + + + + Start Date + Start Date + + + + Finish Date + Finish Date + + + + Size + Size + + + + User Name + User Name + + + + Expiration + Expiration + + + + Name + Name + + \ No newline at end of file diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.zh-hans.resx b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.zh-hans.resx index 10dc5d5f..3c6f327f 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.zh-hans.resx +++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.zh-hans.resx @@ -124,7 +124,7 @@ OwnerUri 不能为 null 或为空 - SpecifiedUri"{0} 没有现有的连接 + SpecifiedUri '{0}' 没有已有的连接 AuthenticationType 值"{0}" 无效。 有效值为 'Integrated' 和 'SqlLogin'。 @@ -358,7 +358,7 @@ 未定义变量 {0}。 - EN_LOCALIZATION + 测试 用空字符串取代空字符串。 @@ -435,6 +435,45 @@ 该列不允许Null 值 + + 编辑会话已存在 + + + 编辑会话尚未初始化 + + + 编辑会话已被初始化 + + + 编辑会话已被初始化或正在初始化中 + + + 执行查询失败,查看消息了解更多详情 + + + 结果集的限制值不能为负数 + + + + + + 必须提供对象名称 + + + 不支持显式指定服务器或者数据库 + + + 数据表的元数据没有扩展属性 + + + 找不到请求编辑的数据表或视图 + + + 扩展数据库时出错: {0} + + + 连接到 {0} 时出错 + 聚合 @@ -879,9 +918,6 @@ 表类型索引 - - ServerInstance - 选择性 XML 索引 @@ -918,4 +954,436 @@ 列加密密钥 + + 服务器 + + + 解析属性 ScriptingParams.ConnectionString 时出错 + + + ScriptingParams.FilePath 属性指定的路径是无效目录 + + + 解析属性 ScriptingListObjectsCompleteParams.ConnectionString 时出错 + + + {0} ({1}, {2}, {3}) + + + 无默认值 + + + 输入 + + + 输入/输出 + + + 输入/只读 + + + 输入/输出/只读 + + + 默认值 + + + Null + + + 非 Null + + + {0} ({1}, {2}) + + + {0} ({1}) + + + {0} ({1}Computed, {2}, {3}) + + + {0} ({1}Computed) + + + {0} (列集,{1}) + + + {0} (列集,{1}{2},{3}) + + + {0} (列集,{1},{2},{3}) + + + 唯一 + + + 非唯一 + + + 聚集 + + + 非聚集 + + + 历史记录 + + + 带有系统版本 + + + 不可用 + + + 当前默认文件组: {0} + + + {0} 的新文件组 + + + 默认值 + + + 文件 + + + 名称 + + + 只读 + + + 自动增长/最大大小 + + + ... + + + <默认值> + + + 文件组 + + + 逻辑名 + + + 文件类型 + + + 初始大小 (MB) + + + <新文件组> + + + 路径 + + + 文件名 + + + <原始设备> + + + 批量记录的 + + + + + + 简单 + + + 选择数据库所有者 + + + + + + 增量为 {0} MB,限制为 {1} MB + + + 增量为 {0}%,限制为 {1} MB + + + 增量为 {0} MB,增长无限制 + + + 增量为 {0}%,增长无限制 + + + 无限制 + + + 不超过{0} MB + + + 自动 + + + Service Broker + + + 排序规则 + + + 游标 + + + 杂项 + + + 恢复 + + + 状态 + + + ANSI NULL 默认值 + + + 启用 ANSI NULLS + + + ANSI 填充已启用 + + + 启用 ANSI 警告 + + + 算术中止已启用 + + + 自动关闭 + + + 自动创建统计信息 + + + 自动收缩 + + + 自动更新统计信息 + + + 自动异步更新统计信息 + + + 区分大小写的 + + + 已启用“提交时关闭游标” + + + 排序规则 + + + 串联 Null 时得到 Null + + + 数据库兼容级别 + + + 数据库状态 + + + 默认游标 + + + 已启用全文索引 + + + 数值舍入 —— 中止 + + + 页验证 + + + 已启用 Quoted Identifiers + + + 数据库为只读的 + + + 已启用 Recursive Triggers + + + 限制访问 + + + Select Into/Bulk Copy + + + 优先处理 Broker 优先级 + + + Service Broker Identifier + + + 已启用 Broker + + + 在检查点删除日志 + + + 启用跨数据库所有权链接 + + + 可信 + + + Date Correlation Optimization 已启用 prototype_db_prop_parameterization = Parameterization + + + 强迫的 + + + 简单 + + + 行数据 + + + 日志 + + + FILESTREAM 数据 + + + 不适用 + + + <默认路径> + + + 开着的连接 + + + SQL Server 需要关闭所有其它连接来改变数据库属性——你确认要改变属性并关闭所有其它连接吗? + + + AUTO_CLOSED + + + 紧急 + + + 不可访问 + + + 一般 + + + 离线 + + + 恢复中 + + + 等待恢复 + + + 恢复中 + + + 关机 + + + 待机 + + + 怀疑 + + + 全局 + + + ju + + + MULTI_USER + + + RESTRICTED_USER + + + SINGLE_USER + + + 校验码 + + + 没有 + + + TORN_PAGE_DETECTION + + + 启用 VarDecimal 存储格式 + + + SQL Server 2008 (100) + + + 启用加密 + + + + + + + + + 首要的 + + + 对于分配政策HASH,开始的哈希列的数量是可选的,但是应在1到16之间 + + + SQL Server 2012 (110) + + + SQL Server 2014 (120) + + + SQL Server 2016 (130) + + + SQL Server vNext (140) + + + + + + 部分 + + + FILESTREAM 文件 + + + 没有可用的文件组 + + + 数据库 {0} 无法访问。 + + + 无查询结果 + + + 资料行因结果集太长而可能无法加载 + + + 备份数据库 + + + 正在进行 + + + 已完成 + + + 参数化 + \ No newline at end of file diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.zh-hant.resx b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.zh-hant.resx index ee8b04a7..4c3bdcf7 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.zh-hant.resx +++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.zh-hant.resx @@ -145,7 +145,7 @@ ServerName 不能是 null 或空白 - {0} 不可為空值或空白,使用 SqlLogin 驗證時 + 使用 SqlLogin 驗證時,{0} 不可為 null 或是空白 查詢已完成,無法取消 @@ -358,7 +358,7 @@ 未定義變數 {0}。 - EN_LOCALIZATION + 測試 用空白字串取代空白字串。 @@ -441,6 +441,9 @@ 編輯工作階段尚未初始化 + + 編輯工作階段已初始化 + 編輯工作階段已完成初始化或正在初始化 @@ -456,6 +459,21 @@ 必須提供物件名稱 + + 不支援明確指定的伺服器或資料庫 + + + 資料表中繼資料無擴充屬性 + + + 找不到要編輯的資料表或檢視表 + + + 擴充資料庫時發生錯誤:{0} + + + 連接到 {0} 時發生錯誤 + 彙總 @@ -900,9 +918,6 @@ 資料表類型索引 - - ServerInstance - 選擇性 XML 索引 @@ -939,4 +954,438 @@ 資料行加密金鑰 + + 伺服器 + + + 剖析屬性 ScriptingParams.ConnectionString 時發生錯誤 + + + ScriptingParams.FilePath 屬性指定的路径是無效目錄 + + + 剖析屬性 ScriptingListObjectsCompleteParams.ConnectionString 時發生錯誤 + + + {0} ({1},{2},{3}) + + + 無預設值 + + + 輸入 + + + 輸入/輸出 + + + 輸入/唯讀 + + + 輸入/輸出/唯讀 + + + 預設值 + + + Null + + + 非 Null + + + {0} ({1},{2}) + + + {0} ({1}) + + + {0} ({1} 已計算,{2},{3}) + + + {0} ({1} 已計算) + + + {0} (資料行集,{1}) + + + {0} (資料行集,{1}{2},{3}) + + + {0} (資料行集,{1},{2},{3}) + + + 唯一 + + + 非唯一 + + + 叢集 + + + 非叢集 + + + 歷程記錄 + + + 系統建立版本 + + + 無法使用 + + + 當前預設檔案群組: {0} + + + {0} 的新檔案群組 + + + 預設值 + + + 檔案 + + + 名稱 + + + 唯讀 + + + 自動成長 / 大小上限 + + + ... + + + <預設> + + + 檔案群組 + + + 邏輯名稱 + + + 檔案類型 + + + 初始大小 (MB) + + + <新增檔案群組> + + + 路徑 + + + 檔案名稱 + + + <未經處理的裝置> + + + 大量記錄 + + + Full + + + Simple + + + 選取資料庫擁有者 + + + + + + 以 {0} MB 為單位,限制為 {1} MB + + + 以百分之 {0} 為單位,限制為 {1} MB + + + 以 {0} MB 為單位,無限制 + + + 以百分之 {0} 為單位,無限制 + + + 無限制 + + + 限制為 {0} MB + + + 自動 + + + Service Broker + + + 定序 + + + 資料指標 + + + 其他 + + + 復原 + + + 狀態 + + + ANSI NULL 預設值 + + + ANSI NULLS 已啟用 + + + +ANSI Padding 已啟用 + + + ANSI Warnings 已啟用 + + + Arithmetic Abort 已啟用 + + + 自動關閉 + + + 自動建立統計資料 + + + 自動壓縮 + + + 自動更新統計資料 + + + 自動非同步更新統計資料 + + + 區分大小寫 + + + 認可時關閉資料指標已啟用 + + + 定序 + + + 串連 Null 產生 Null + + + 資料庫相容性層級 + + + 資料庫狀態 + + + 預設資料指標 + + + 全文檢索索引已啟用 + + + 數值捨入中止 + + + 頁面確認 + + + 引號識別碼已啟用 + + + 資料庫唯讀 + + + 遞迴觸發程序已啟用 + + + 限制存取 + + + 選取/大量複製 + + + 接受 Broker 優先權 + + + Service Broker 識別碼 + + + Broker 已啟用 + + + 在檢查點截斷記錄 + + + 已啟用跨資料庫擁有權鏈結 + + + 可信任 + + + 已啟用日期相互關聯最佳化 prototype_db_prop_parameterization = 參數化 + + + 強制 + + + 簡易 + + + 資料列資料 + + + LOG + + + FILESTREAM 資料 + + + 不適用 + + + <預設路徑> + + + 開啟連接 + + + 為了變更資料庫屬性,SQL Server必須關閉所有其他與資料庫的連線。 +確定要變更屬性並關閉所有其他連線嗎? + + + AUTO_CLOSED + + + EMERGENCY + + + INACCESSIBLE + + + NORMAL + + + OFFLINE + + + RECOVERING + + + RECOVERY PENDING + + + RESTORING + + + SHUTDOWN + + + STANDBY + + + SUSPECT + + + GLOBAL + + + LOCAL + + + MULTI_USER + + + RESTRICTED_USER + + + SINGLE_USER + + + CHECKSUM + + + NONE + + + TORN_PAGE_DETECTION + + + VarDecimal 儲存格式已啟用 + + + SQL Server 2008 (100) + + + 加密已啟用 + + + OFF + + + ON + + + PRIMARY + + + 散發原則 HASH 的前置雜湊資料行是選擇性的,但應該介於 1 到 16 個資料行之間。 + + + SQL Server 2012 (110) + + + SQL Server 2014 (120) + + + SQL Server 2016 (130) + + + SQL Server vNext (140) + + + + + + Partial + + + FILESTREAM 檔案 + + + 沒有適用的檔案群組 + + + 無法存取資料庫 {0}。 + + + 沒有查詢結果可以回傳 + + + 資料列因結果集太長而無法載入 + + + 備份資料庫 + + + 進行中 + + + 已完成 + + + 參數化 + \ No newline at end of file diff --git a/src/Microsoft.SqlTools.ServiceLayer/TaskServices/SqlTask.cs b/src/Microsoft.SqlTools.ServiceLayer/TaskServices/SqlTask.cs index d84ab501..98697689 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/TaskServices/SqlTask.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/TaskServices/SqlTask.cs @@ -190,8 +190,11 @@ namespace Microsoft.SqlTools.ServiceLayer.TaskServices WaitHandle.WaitAny(waitHandles); try { - await this.TaskToCancel(this); - result.TaskStatus = SqlTaskStatus.Canceled; + if (token.IsCancellationRequested) + { + await this.TaskToCancel(this); + result.TaskStatus = SqlTaskStatus.Canceled; + } } catch (Exception ex) { diff --git a/src/Microsoft.SqlTools.ServiceLayer/Utility/GeneralRequestDetails.cs b/src/Microsoft.SqlTools.ServiceLayer/Utility/GeneralRequestDetails.cs new file mode 100644 index 00000000..af8a5bc4 --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/Utility/GeneralRequestDetails.cs @@ -0,0 +1,69 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System; +using System.Collections.Generic; +using System.Globalization; +using Microsoft.SqlTools.Utility; + +namespace Microsoft.SqlTools.ServiceLayer.Utility +{ + public class GeneralRequestDetails + { + public GeneralRequestDetails() + { + Options = new Dictionary(); + } + + protected T GetOptionValue(string name) + { + T result = default(T); + if (Options != null && Options.ContainsKey(name)) + { + object value = Options[name]; + try + { + if (value != null && (typeof(T) != value.GetType())) + { + if (typeof(T) == typeof(int) || typeof(T) == typeof(int?)) + { + value = Convert.ToInt32(value); + } + else if (typeof(T) == typeof(bool) || typeof(T) == typeof(bool?)) + { + value = Convert.ToBoolean(value); + } + } + result = value != null ? (T)value : default(T); + } + catch + { + result = default(T); + Logger.Write(LogLevel.Warning, string.Format(CultureInfo.InvariantCulture, + "Cannot convert option value {0}:{1} to {2}", name, value ?? "", typeof(T))); + } + } + return result; + } + + protected void SetOptionValue(string name, T value) + { + Options = Options ?? new Dictionary(); + if (Options.ContainsKey(name)) + { + Options[name] = value; + } + else + { + Options.Add(name, value); + } + } + + /// + /// Gets or Sets the options + /// + public Dictionary Options { get; set; } + } +} diff --git a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/DisasterRecovery/RestoreDatabaseServiceTests.cs b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/DisasterRecovery/RestoreDatabaseServiceTests.cs index 4c44be41..21d90329 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/DisasterRecovery/RestoreDatabaseServiceTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/DisasterRecovery/RestoreDatabaseServiceTests.cs @@ -3,13 +3,17 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // +using System.Collections.Generic; +using System.Data.SqlClient; using System.Globalization; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.SqlServer.Management.Smo; using Microsoft.SqlTools.Extensibility; using Microsoft.SqlTools.Hosting.Protocol; +using Microsoft.SqlTools.ServiceLayer.Admin; using Microsoft.SqlTools.ServiceLayer.Connection; using Microsoft.SqlTools.ServiceLayer.DisasterRecovery; using Microsoft.SqlTools.ServiceLayer.DisasterRecovery.Contracts; @@ -29,6 +33,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.DisasterRecovery private ConnectionService _connectService = TestServiceProvider.Instance.ConnectionService; private Mock serviceHostMock; private DisasterRecoveryService service; + private string fullBackUpDatabase; public RestoreDatabaseServiceTests() { @@ -37,26 +42,81 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.DisasterRecovery service.InitializeService(serviceHostMock.Object); } + private async Task VerifyBackupFileCreated() + { + if(fullBackUpDatabase == null) + { + fullBackUpDatabase = await CreateBackupFile(); + } + } + [Fact] public async void RestorePlanShouldCreatedSuccessfullyForFullBackup() { - string backupFileName = "FullBackup.bak"; + await VerifyBackupFileCreated(); bool canRestore = true; - await VerifyRestore(backupFileName, canRestore); + await VerifyRestore(fullBackUpDatabase, canRestore); + } + + [Fact] + public async void RestoreShouldCreatedSuccessfullyGivenTwoBackupFiles() + { + + string[] backupFileNames = new string[] { "FullBackup.bak", "DiffBackup.bak" }; + bool canRestore = true; + var response = await VerifyRestore(backupFileNames, canRestore, false, "RestoredFromTwoBackupFile"); + Assert.True(response.BackupSetsToRestore.Count() == 2); + } + + [Fact] + public async void RestoreShouldFailGivenTwoBackupFilesButFilterFullBackup() + { + + string[] backupFileNames = new string[] { "FullBackup.bak", "DiffBackup.bak" }; + bool canRestore = true; + var response = await VerifyRestore(backupFileNames, canRestore, false, "RestoredFromTwoBackupFile"); + Assert.True(response.BackupSetsToRestore.Count() == 2); + var fileInfo = response.BackupSetsToRestore.FirstOrDefault(x => x.GetPropertyValueAsString(BackupSetInfo.BackupTypePropertyName) != RestoreConstants.TypeFull); + if(fileInfo != null) + { + var selectedBackupSets = new string[] { fileInfo.Id }; + await VerifyRestore(backupFileNames, false, false, "RestoredFromTwoBackupFile", selectedBackupSets); + } + } + + [Fact] + public async void RestoreShouldCompletedSuccessfullyGivenTowBackupFilesButFilterDifferentialBackup() + { + + string[] backupFileNames = new string[] { "FullBackup.bak", "DiffBackup.bak" }; + bool canRestore = true; + var response = await VerifyRestore(backupFileNames, canRestore, false, "RestoredFromTwoBackupFile"); + Assert.True(response.BackupSetsToRestore.Count() == 2); + var fileInfo = response.BackupSetsToRestore.FirstOrDefault(x => x.GetPropertyValueAsString(BackupSetInfo.BackupTypePropertyName) == RestoreConstants.TypeFull); + if (fileInfo != null) + { + var selectedBackupSets = new string[] { fileInfo.Id }; + await VerifyRestore(backupFileNames, true, false, "RestoredFromTwoBackupFile2", selectedBackupSets); + } } [Fact] public async void RestoreShouldExecuteSuccessfullyForFullBackup() { - string backupFileName = "FullBackup.bak"; + await VerifyBackupFileCreated(); + + string backupFileName = fullBackUpDatabase; bool canRestore = true; var restorePlan = await VerifyRestore(backupFileName, canRestore, true); + Assert.NotNull(restorePlan.BackupSetsToRestore); } [Fact] public async void RestoreToAnotherDatabaseShouldExecuteSuccessfullyForFullBackup() { - string backupFileName = "FullBackup.bak"; + await VerifyBackupFileCreated(); + + string backupFileName = fullBackUpDatabase; bool canRestore = true; var restorePlan = await VerifyRestore(backupFileName, canRestore, true, "NewRestoredDatabase"); } @@ -80,15 +140,17 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.DisasterRecovery [Fact] public async Task RestorePlanRequestShouldReturnResponseWithDbFiles() { + await VerifyBackupFileCreated(); + using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile()) { TestConnectionResult connectionResult = await LiveConnectionHelper.InitLiveConnectionInfoAsync("master", queryTempFile.FilePath); - string filePath = GetBackupFilePath("FullBackup.bak"); + string filePath = GetBackupFilePath(fullBackUpDatabase); RestoreParams restoreParams = new RestoreParams { - BackupFilePath = filePath, + BackupFilePaths = filePath, OwnerUri = queryTempFile.FilePath }; @@ -97,7 +159,6 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.DisasterRecovery verify: ((result) => { Assert.True(result.DbFiles.Any()); - Assert.Equal(result.DatabaseName, "BackupTestDb"); })); } } @@ -113,7 +174,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.DisasterRecovery RestoreParams restoreParams = new RestoreParams { - BackupFilePath = filePath, + BackupFilePaths = filePath, OwnerUri = queryTempFile.FilePath }; @@ -140,7 +201,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.DisasterRecovery RestoreParams restoreParams = new RestoreParams { - BackupFilePath = filePath, + BackupFilePaths = filePath, OwnerUri = queryTempFile.FilePath }; @@ -164,7 +225,15 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.DisasterRecovery private async Task VerifyRestore(string backupFileName, bool canRestore, bool execute = false, string targetDatabase = null) { - string filePath = GetBackupFilePath(backupFileName); + return await VerifyRestore(new string[] { backupFileName }, canRestore, execute, targetDatabase); + } + + private async Task VerifyRestore(string[] backupFileNames, bool canRestore, bool execute = false, string targetDatabase = null, string[] selectedBackupSets = null) + { + var filePaths = backupFileNames.Select(x => GetBackupFilePath(x)); + string backUpFilePath = filePaths.Aggregate((current, next) => current + " ," + next); + + using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile()) { TestConnectionResult connectionResult = await LiveConnectionHelper.InitLiveConnectionInfoAsync("master", queryTempFile.FilePath); @@ -172,15 +241,17 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.DisasterRecovery RestoreDatabaseHelper service = new RestoreDatabaseHelper(); var request = new RestoreParams { - BackupFilePath = filePath, - DatabaseName = targetDatabase, - OwnerUri = queryTempFile.FilePath + BackupFilePaths = backUpFilePath, + TargetDatabaseName = targetDatabase, + OwnerUri = queryTempFile.FilePath, + SelectedBackupSets = selectedBackupSets }; var restoreDataObject = service.CreateRestoreDatabaseTaskDataObject(request); var response = service.CreateRestorePlanResponse(restoreDataObject); Assert.NotNull(response); + Assert.False(string.IsNullOrWhiteSpace(response.RestoreSessionId)); Assert.Equal(response.CanRestore, canRestore); if (canRestore) { @@ -193,11 +264,18 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.DisasterRecovery if(execute) { + request.SessionId = response.RestoreSessionId; + restoreDataObject = service.CreateRestoreDatabaseTaskDataObject(request); + Assert.Equal(response.RestoreSessionId, restoreDataObject.SessionId); await DropDatabase(targetDatabase); Thread.Sleep(2000); request.RelocateDbFiles = response.RelocateFilesNeeded; service.ExecuteRestore(restoreDataObject); Assert.True(restoreDataObject.Server.Databases.Contains(targetDatabase)); + if(selectedBackupSets != null) + { + Assert.Equal(selectedBackupSets.Count(), restoreDataObject.RestorePlan.RestoreOperations.Count()); + } await DropDatabase(targetDatabase); } } @@ -230,8 +308,15 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.DisasterRecovery private string GetBackupFilePath(string fileName) { - FileInfo inputFile = GetBackupFile(fileName); - return inputFile.FullName; + if (!Path.IsPathRooted(fileName)) + { + FileInfo inputFile = GetBackupFile(fileName); + return inputFile.FullName; + } + else + { + return fileName; + } } protected DisasterRecoveryService CreateService() @@ -247,5 +332,56 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.DisasterRecovery return CreateProvider() .RegisterSingleService(new DisasterRecoveryService()); } + + public async Task CreateBackupFile() + { + using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile()) + { + SqlTestDb testDb = await SqlTestDb.CreateNewAsync(TestServerType.OnPrem, false, null, null, "RestoreTest"); + var liveConnection = LiveConnectionHelper.InitLiveConnectionInfo(testDb.DatabaseName, queryTempFile.FilePath); + + // Initialize backup service + DatabaseTaskHelper helper = AdminService.CreateDatabaseTaskHelper(liveConnection.ConnectionInfo, databaseExists: true); + SqlConnection sqlConn = DisasterRecoveryService.GetSqlConnection(liveConnection.ConnectionInfo); + + // Get default backup path + BackupConfigInfo backupConfigInfo = DisasterRecoveryService.Instance.GetBackupConfigInfo(helper.DataContainer, sqlConn, sqlConn.Database); + string backupPath = Path.Combine(backupConfigInfo.DefaultBackupFolder, testDb.DatabaseName + ".bak"); + + BackupInfo backupInfo = CreateBackupInfo(testDb.DatabaseName, + BackupType.Full, + new List() { backupPath }, + new Dictionary() { { backupPath, (int)DeviceType.File } }); + + var backupParams = new BackupParams + { + OwnerUri = liveConnection.ConnectionInfo.OwnerUri, + BackupInfo = backupInfo + }; + + // Backup the database + BackupOperation backupOperation = DisasterRecoveryService.Instance.SetBackupInput(helper.DataContainer, sqlConn, backupParams.BackupInfo); + DisasterRecoveryService.Instance.PerformBackup(backupOperation); + + // Clean up the database + testDb.Cleanup(); + return backupPath; + } + } + + private BackupInfo CreateBackupInfo(string databaseName, BackupType backupType, List backupPathList, Dictionary backupPathDevices) + { + BackupInfo backupInfo = new BackupInfo(); + backupInfo.BackupComponent = (int)BackupComponent.Database; + backupInfo.BackupDeviceType = (int)BackupDeviceType.Disk; + backupInfo.BackupPathDevices = backupPathDevices; + backupInfo.BackupPathList = backupPathList; + backupInfo.BackupsetName = "default_backup"; + backupInfo.BackupType = (int)backupType; + backupInfo.DatabaseName = databaseName; + backupInfo.SelectedFileGroup = null; + backupInfo.SelectedFiles = ""; + return backupInfo; + } } } diff --git a/test/Microsoft.SqlTools.ServiceLayer.Test.Common/TestData/DisasterRecovery/Backups/DiffBackup.bak b/test/Microsoft.SqlTools.ServiceLayer.Test.Common/TestData/DisasterRecovery/Backups/DiffBackup.bak index d0b957950456cf3df3f829886de5c609b787403e..9a31fe12921ea2e718d1de16b14344909424cee1 100644 GIT binary patch literal 966656 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�OR5vQ=T$!Z|I-31cu%~NO9%G6tN6R$zS|3X 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 delta 8523 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 SZ+_o`Pwyk=N?B+#SpEj!(|d*h diff --git a/test/Microsoft.SqlTools.ServiceLayer.Test.Common/TestData/DisasterRecovery/Backups/FullBackup.bak b/test/Microsoft.SqlTools.ServiceLayer.Test.Common/TestData/DisasterRecovery/Backups/FullBackup.bak index bcc7074f78c6a5e018281b49a3feea0c3d697628..0d769c967df1eda690aa6a3abbbcb8dcda52977f 100644 GIT binary patch delta 14220 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 => new DatabaseFileInfo(null)); + } + + [Fact] + public void DatabaseFileInfoShouldReturnNullGivenEmptyProperties() + { + LocalizedPropertyInfo[] properties = new LocalizedPropertyInfo[] { }; + var fileInfo = new DatabaseFileInfo(properties); + Assert.True(string.IsNullOrEmpty(fileInfo.Id)); + Assert.True(string.IsNullOrEmpty(fileInfo.GetPropertyValueAsString(BackupSetInfo.BackupComponentPropertyName))); + } + + [Fact] + public void DatabaseFileInfoShouldReturnValuesGivenValidProperties() + { + LocalizedPropertyInfo[] properties = new LocalizedPropertyInfo[] { + new LocalizedPropertyInfo + { + PropertyName = "name", + PropertyValue = 1 + }, + new LocalizedPropertyInfo + { + PropertyName = DatabaseFileInfo.IdPropertyName, + PropertyValue = "id" + } + + }; + var fileInfo = new DatabaseFileInfo(properties); + Assert.Equal(fileInfo.Id, "id"); + Assert.Equal(fileInfo.GetPropertyValueAsString("name"), "1"); + } + } +} diff --git a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/DisasterRecovery/LocalizedPropertyInfoTests.cs b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/DisasterRecovery/LocalizedPropertyInfoTests.cs new file mode 100644 index 00000000..3f8f2143 --- /dev/null +++ b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/DisasterRecovery/LocalizedPropertyInfoTests.cs @@ -0,0 +1,33 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + + +using Microsoft.SqlTools.ServiceLayer.DisasterRecovery.Contracts; +using Xunit; + +namespace Microsoft.SqlTools.ServiceLayer.UnitTests.DisasterRecovery +{ + public class LocalizedPropertyInfoTests + { + [Fact] + public void PropertyDisplayNameShouldReturnNameWhenNotSet() + { + LocalizedPropertyInfo propertyInfo = new LocalizedPropertyInfo(); + propertyInfo.PropertyName = "name"; + + Assert.Equal(propertyInfo.PropertyDisplayName, propertyInfo.PropertyName); + } + + [Fact] + public void PropertyValudDisplayNameShouldReturnValudWhenNotSet() + { + LocalizedPropertyInfo propertyInfo = new LocalizedPropertyInfo(); + propertyInfo.PropertyName = "name"; + propertyInfo.PropertyValue = "value"; + + Assert.Equal(propertyInfo.PropertyValueDisplayName, propertyInfo.PropertyValue); + } + } +} diff --git a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ObjectExplorer/NodeTests.cs b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ObjectExplorer/NodeTests.cs index 8cf9cac3..3ae9ea25 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ObjectExplorer/NodeTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ObjectExplorer/NodeTests.cs @@ -48,7 +48,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer defaultConnParams = new ConnectionCompleteParams() { ServerInfo = defaultServerInfo, - ConnectionSummary = defaultConnectionDetails, + ConnectionSummary = defaultConnectionDetails != null ? ((IConnectionSummary)defaultConnectionDetails).Clone(): null, OwnerUri = defaultOwnerUri }; @@ -119,6 +119,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer // But given a server node for a cloud DB that's not master defaultConnectionDetails.DatabaseName = "NotMaster"; + defaultConnParams.ConnectionSummary.DatabaseName = defaultConnectionDetails.DatabaseName; node = new ServerNode(defaultConnParams, ServiceProvider); // Then expect label to include db name