From 71195869e1579d96aaf144b45bda26862f7aa9de Mon Sep 17 00:00:00 2001 From: Kevin Cunnane Date: Tue, 7 Aug 2018 12:59:57 -0700 Subject: [PATCH] Add v2 of the Hosting Service and build nuget packages for it (#675) * Port v2 of Hosting service to SqlToolsService - Renamed project to .v2 so that existing hosted service isn't impacted - Copied over the CoreServices project which contains ConnectionServiceCore and other reusable services for anything interacting with MSSQL - Ported unit test project across and verified tests run. * Nuget package support for reusable DLLs * Use 1.1 version per Karl's suggestion * Use correct license URL and project URL * Use new SMO packages --- build.cake | 28 +- build.json | 6 + sqltoolsservice.sln | 35 + .../Connection/CancelTokenKey.cs | 36 + .../Connection/ConnectParamsExtensions.cs | 50 + .../Connection/ConnectionInfo.cs | 171 + .../Connection/ConnectionServiceCore.cs | 1310 +++++ .../Connection/ConnectionUtils.cs | 31 + .../Connection/DatabaseFullAccessException.cs | 28 + .../Connection/DatabaseLocksManager.cs | 114 + .../Connection/FeatureWithFullDbAccess.cs | 40 + .../Connection/ISqlConnectionFactory.cs | 20 + .../ReliableConnection/AmbientSettings.cs | 452 ++ .../ReliableConnection/CachedServerInfo.cs | 284 + .../ReliableConnection/Constants.cs | 17 + .../ReliableConnection/DataSchemaError.cs | 214 + .../ReliableConnection/DbCommandWrapper.cs | 71 + .../ReliableConnection/DbConnectionWrapper.cs | 113 + .../ReliableConnection/ErrorSeverity.cs | 15 + .../IStackSettingsContext.cs | 19 + .../ReliableConnectionHelper.cs | 1320 +++++ .../ReliableConnection/ReliableSqlCommand.cs | 247 + .../ReliableSqlConnection.cs | 610 ++ .../ReliableConnection/Resources.cs | 157 + .../RetryCallbackEventArgs.cs | 61 + .../RetryLimitExceededException.cs | 45 + ...licy.DataTransferDetectionErrorStrategy.cs | 43 + .../RetryPolicy.IErrorDetectionStrategy.cs | 97 + ...Policy.NetworkConnectivityErrorStrategy.cs | 43 + ...oraryAndIgnorableErrorDetectionStrategy.cs | 63 + ...SqlAzureTemporaryErrorDetectionStrategy.cs | 43 + .../RetryPolicy.ThrottleReason.cs | 357 ++ .../ReliableConnection/RetryPolicy.cs | 542 ++ .../ReliableConnection/RetryPolicyFactory.cs | 459 ++ .../ReliableConnection/RetryPolicyUtils.cs | 485 ++ .../ReliableConnection/RetryState.cs | 86 + .../SqlConnectionHelperScripts.cs | 51 + .../ReliableConnection/SqlErrorNumbers.cs | 32 + .../SqlSchemaModelErrorCodes.cs | 465 ++ .../ReliableConnection/SqlServerError.cs | 74 + .../ReliableConnection/SqlServerRetryError.cs | 54 + .../Connection/SqlConnectionFactory.cs | 28 + .../LanguageServices/BindingQueue.cs | 428 ++ .../ConnectedBindingContext.cs | 217 + .../LanguageServices/ConnectedBindingQueue.cs | 231 + .../LanguageServices/IBindingContext.cs | 81 + .../LanguageServices/LanguageContants.cs | 22 + .../LanguageServices/QueueItem.cs | 77 + .../LanguageServices/TelemetryNotification.cs | 100 + .../Localization/sr.cs | 5172 +++++++++++++++++ .../Localization/sr.de.resx | 490 ++ .../Localization/sr.es.resx | 489 ++ .../Localization/sr.fr.resx | 489 ++ .../Localization/sr.it.resx | 489 ++ .../Localization/sr.ja.resx | 490 ++ .../Localization/sr.ko.resx | 491 ++ .../Localization/sr.pt-BR.resx | 490 ++ .../Localization/sr.resx | 2005 +++++++ .../Localization/sr.ru.resx | 483 ++ .../Localization/sr.strings | 879 +++ .../Localization/sr.xlf | 2358 ++++++++ .../Localization/sr.zh-hans.resx | 489 ++ .../Localization/sr.zh-hant.resx | 491 ++ .../Localization/transXliff/sr.de.xlf | 2776 +++++++++ .../Localization/transXliff/sr.es.xlf | 2775 +++++++++ .../Localization/transXliff/sr.fr.xlf | 2775 +++++++++ .../Localization/transXliff/sr.it.xlf | 2775 +++++++++ .../Localization/transXliff/sr.ja.xlf | 2776 +++++++++ .../Localization/transXliff/sr.ko.xlf | 2777 +++++++++ .../Localization/transXliff/sr.pt-BR.xlf | 2776 +++++++++ .../Localization/transXliff/sr.ru.xlf | 2769 +++++++++ .../Localization/transXliff/sr.zh-hans.xlf | 2775 +++++++++ .../Localization/transXliff/sr.zh-hant.xlf | 2777 +++++++++ .../Microsoft.SqlTools.CoreServices.csproj | 39 + .../Properties/AssemblyInfo.cs | 15 + .../CompoundSqlToolsSettingsValues.cs | 102 + .../SqlContext/ISqlToolsSettingsValues.cs | 33 + .../SqlContext/IntelliSenseSettings.cs | 68 + .../SqlContext/ObjectExplorerSettings.cs | 32 + .../SqlContext/SqlToolsSettings.cs | 145 + .../SqlContext/SqlToolsSettingsValues.cs | 54 + .../Utility/CommonConstants.cs | 21 + .../Utility/DatabaseUtils.cs | 26 + .../Utility/InteractionMetrics.cs | 98 + .../Workspace/SettingsService.cs | 121 + .../ClientCapabilities/ClientCapabilities.cs | 28 + .../DynamicRegistrationCapability.cs | 15 + .../TextDocument/CodeAction.cs | 14 + .../TextDocument/CodeLens.cs | 14 + .../TextDocument/ColorProvider.cs | 14 + .../TextDocument/Completion.cs | 63 + .../TextDocument/Definition.cs | 14 + .../TextDocument/DocumentHighlight.cs | 14 + .../TextDocument/DocumentLink.cs | 14 + .../TextDocument/DocumentSymbol.cs | 33 + .../TextDocument/Formatting.cs | 14 + .../ClientCapabilities/TextDocument/Hover.cs | 21 + .../TextDocument/Implementation.cs | 14 + .../TextDocument/OnTypeFormatting.cs | 14 + .../TextDocument/PublishDignostics.cs | 18 + .../TextDocument/RangeFormatting.cs | 14 + .../TextDocument/References.cs | 14 + .../ClientCapabilities/TextDocument/Rename.cs | 14 + .../TextDocument/SignatureHelp.cs | 29 + .../TextDocument/Synchronization.cs | 23 + .../TextDocument/TextDocumentCapabilities.cs | 103 + .../TextDocument/TypeDefinition.cs | 14 + .../Workspace/DidChangeConfiguration.cs | 14 + .../Workspace/DidChangeWatchedFiles.cs | 14 + .../Workspace/ExecuteCommand.cs | 14 + .../ClientCapabilities/Workspace/Symbol.cs | 37 + .../Workspace/WorkspaceCapabilities.cs | 58 + .../Workspace/WorkspaceEdit.cs | 18 + .../Common/CompletionItemKind.cs | 91 + .../Common/MarkupKind.cs | 24 + .../Common/SymbolKinds.cs | 94 + .../Common/WorkspaceFolder.cs | 20 + .../Connection/CancelConnectParams.cs | 24 + .../Connection/CancelConnectRequest.cs | 19 + .../Connection/ChangeDatabaseParams.cs | 23 + .../Connection/ChangeDatabaseRequest.cs | 19 + .../Connection/ConnectParams.cs | 37 + .../ConnectionChangedNotification.cs | 19 + .../Connection/ConnectionChangedParams.cs | 23 + .../ConnectionCompleteNotification.cs | 66 + .../Connection/ConnectionDetails.cs | 525 ++ .../Connection/ConnectionDetailsExtensions.cs | 51 + .../Connection/ConnectionRequest.cs | 19 + .../Connection/ConnectionSummary.cs | 48 + .../Connection/ConnectionSummaryComparer.cs | 53 + .../Connection/ConnectionSummaryExtensions.cs | 26 + .../Connection/ConnectionType.cs | 23 + .../Connection/DisconnectParams.cs | 25 + .../Connection/DisconnectRequest.cs | 19 + .../Connection/LanguageFlavorChange.cs | 42 + .../Connection/ListDatabasesParams.cs | 18 + .../Connection/ListDatabasesRequest.cs | 19 + .../Connection/ListDatabasesResponse.cs | 18 + .../Connection/ServerInfo.cs | 68 + .../Explorer/CloseSessionRequest.cs | 53 + .../Explorer/CreateSessionRequest.cs | 65 + .../Explorer/ExpandRequest.cs | 76 + .../Explorer/FindNodesRequest.cs | 55 + .../Explorer/NodeInfo.cs | 63 + .../Explorer/RefreshRequest.cs | 29 + .../GeneralRequestDetails.cs | 114 + .../InitializeRequest.cs | 94 + .../InitializeRequestWithOptions.cs | 49 + .../Metadata/ObjectMetadata.cs | 36 + ...oft.SqlTools.DataProtocol.Contracts.csproj | 16 + .../ServerCapabilities/CodeLensOptions.cs | 19 + .../ServerCapabilities/CompletionOptions.cs | 30 + .../ServerCapabilities/DocumentLinkOptions.cs | 19 + .../DocumentOnTypeFormattingOptions.cs | 23 + .../ExecuteCommandOptions.cs | 18 + .../ServerCapabilities/SaveOptions.cs | 18 + .../ServerCapabilities/ServerCapabilities.cs | 122 + .../SignatureHelpOptions.cs | 18 + .../ServerCapabilities/TextDocument.cs | 76 + .../ServerCapabilities/Workspace.cs | 118 + .../Utilities/FlagsIntConverter.cs | 87 + .../Utilities/FlagsStringConverter.cs | 102 + .../Utilities/Union.cs | 103 + .../Workspace/Configuration.cs | 21 + .../EventType.cs | 33 + .../Internal/Error.cs | 23 + .../Internal/ExitNotification.cs | 16 + .../Internal/HostingErrorNotification.cs | 26 + .../Internal/ShutdownRequest.cs | 17 + ...icrosoft.SqlTools.Hosting.Contracts.csproj | 10 + .../RequestType.cs | 24 + .../Channels/ChannelBase.cs | 58 + .../Channels/StdioClientChannel.cs | 111 + .../Channels/StdioServerChannel.cs | 54 + .../ExportStandardMetadataAttribute.cs | 44 + .../Extensibility/ExtensionServiceProvider.cs | 154 + .../Extensibility/IComposableService.cs | 21 + .../Extensibility/IHostedService.cs | 106 + .../Extensibility/IMultiServiceProvider.cs | 101 + .../Extensibility/IStandardMetadata.cs | 28 + .../RegisteredServiceProvider.cs | 120 + .../ExtensibleServiceHost.cs | 59 + .../IServiceHost.cs | 31 + .../Localization/sr.cs | 230 + .../Localization/sr.resx | 181 + .../Localization/sr.strings | 57 + .../Localization/sr.xlf | 83 + .../Microsoft.SqlTools.Hosting.csproj | 28 + .../Properties/AssemblyInfo.cs | 46 + .../Protocol/EventContext.cs | 32 + .../Protocol/Exceptions.cs | 34 + .../Protocol/IEventSender.cs | 23 + .../Protocol/IJsonRpcHost.cs | 28 + .../Protocol/IMessageDispatcher.cs | 72 + .../Protocol/IRequestSender.cs | 27 + .../Protocol/JsonRpcHost.cs | 446 ++ .../Protocol/Message.cs | 251 + .../Protocol/MessageReader.cs | 257 + .../Protocol/MessageWriter.cs | 59 + .../Protocol/RequestContext.cs | 57 + .../ServiceHost.cs | 210 + .../Utility/AsyncLock.cs | 98 + .../Utility/CommandOptions.cs | 164 + .../Utility/Extensions.cs | 100 + .../Utility/Logger.cs | 299 + .../Utility/ServiceProviderNotSetException.cs | 16 + .../Utility/TaskExtensions.cs | 99 + .../Utility/Validate.cs | 158 + .../Microsoft.SqlTools.Hosting.csproj | 1 - src/sqltools.common.targets | 21 + .../CommonObjects.cs | 67 + .../ServiceProviderTests.cs | 116 + ...icrosoft.SqlTools.Hosting.UnitTests.csproj | 17 + .../ProtocolTests/EventContextTests.cs | 30 + .../ProtocolTests/JsonRpcHostTests.cs | 828 +++ .../ProtocolTests/MessageReaderTests.cs | 220 + .../ProtocolTests/MessageTests.cs | 291 + .../ProtocolTests/MessageWriterTests.cs | 158 + .../ProtocolTests/RequestContextTests.cs | 97 + .../ExtensibleServiceHostTest.cs | 80 + .../ServiceHostTests/ServiceHostTests.cs | 325 ++ .../TaskExtensions.cs | 26 + .../UtilityTests/AsyncLockTests.cs | 49 + .../UtilityTests/LoggerTests.cs | 63 + 224 files changed, 63367 insertions(+), 2 deletions(-) create mode 100644 src/Microsoft.SqlTools.CoreServices/Connection/CancelTokenKey.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/Connection/ConnectParamsExtensions.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/Connection/ConnectionInfo.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/Connection/ConnectionServiceCore.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/Connection/ConnectionUtils.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/Connection/DatabaseFullAccessException.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/Connection/DatabaseLocksManager.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/Connection/FeatureWithFullDbAccess.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/Connection/ISqlConnectionFactory.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/AmbientSettings.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/CachedServerInfo.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/Constants.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/DataSchemaError.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/DbCommandWrapper.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/DbConnectionWrapper.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/ErrorSeverity.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/IStackSettingsContext.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/ReliableConnectionHelper.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/ReliableSqlCommand.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/ReliableSqlConnection.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/Resources.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryCallbackEventArgs.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryLimitExceededException.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.DataTransferDetectionErrorStrategy.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.IErrorDetectionStrategy.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.NetworkConnectivityErrorStrategy.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.SqlAzureTemporaryAndIgnorableErrorDetectionStrategy.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.SqlAzureTemporaryErrorDetectionStrategy.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.ThrottleReason.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicyFactory.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicyUtils.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryState.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/SqlConnectionHelperScripts.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/SqlErrorNumbers.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/SqlSchemaModelErrorCodes.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/SqlServerError.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/SqlServerRetryError.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/Connection/SqlConnectionFactory.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/LanguageServices/BindingQueue.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/LanguageServices/ConnectedBindingContext.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/LanguageServices/ConnectedBindingQueue.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/LanguageServices/IBindingContext.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/LanguageServices/LanguageContants.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/LanguageServices/QueueItem.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/LanguageServices/TelemetryNotification.cs create mode 100755 src/Microsoft.SqlTools.CoreServices/Localization/sr.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/Localization/sr.de.resx create mode 100644 src/Microsoft.SqlTools.CoreServices/Localization/sr.es.resx create mode 100644 src/Microsoft.SqlTools.CoreServices/Localization/sr.fr.resx create mode 100644 src/Microsoft.SqlTools.CoreServices/Localization/sr.it.resx create mode 100644 src/Microsoft.SqlTools.CoreServices/Localization/sr.ja.resx create mode 100644 src/Microsoft.SqlTools.CoreServices/Localization/sr.ko.resx create mode 100644 src/Microsoft.SqlTools.CoreServices/Localization/sr.pt-BR.resx create mode 100755 src/Microsoft.SqlTools.CoreServices/Localization/sr.resx create mode 100644 src/Microsoft.SqlTools.CoreServices/Localization/sr.ru.resx create mode 100644 src/Microsoft.SqlTools.CoreServices/Localization/sr.strings create mode 100644 src/Microsoft.SqlTools.CoreServices/Localization/sr.xlf create mode 100644 src/Microsoft.SqlTools.CoreServices/Localization/sr.zh-hans.resx create mode 100644 src/Microsoft.SqlTools.CoreServices/Localization/sr.zh-hant.resx create mode 100644 src/Microsoft.SqlTools.CoreServices/Localization/transXliff/sr.de.xlf create mode 100644 src/Microsoft.SqlTools.CoreServices/Localization/transXliff/sr.es.xlf create mode 100644 src/Microsoft.SqlTools.CoreServices/Localization/transXliff/sr.fr.xlf create mode 100644 src/Microsoft.SqlTools.CoreServices/Localization/transXliff/sr.it.xlf create mode 100644 src/Microsoft.SqlTools.CoreServices/Localization/transXliff/sr.ja.xlf create mode 100644 src/Microsoft.SqlTools.CoreServices/Localization/transXliff/sr.ko.xlf create mode 100644 src/Microsoft.SqlTools.CoreServices/Localization/transXliff/sr.pt-BR.xlf create mode 100644 src/Microsoft.SqlTools.CoreServices/Localization/transXliff/sr.ru.xlf create mode 100644 src/Microsoft.SqlTools.CoreServices/Localization/transXliff/sr.zh-hans.xlf create mode 100644 src/Microsoft.SqlTools.CoreServices/Localization/transXliff/sr.zh-hant.xlf create mode 100644 src/Microsoft.SqlTools.CoreServices/Microsoft.SqlTools.CoreServices.csproj create mode 100644 src/Microsoft.SqlTools.CoreServices/Properties/AssemblyInfo.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/SqlContext/CompoundSqlToolsSettingsValues.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/SqlContext/ISqlToolsSettingsValues.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/SqlContext/IntelliSenseSettings.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/SqlContext/ObjectExplorerSettings.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/SqlContext/SqlToolsSettings.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/SqlContext/SqlToolsSettingsValues.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/Utility/CommonConstants.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/Utility/DatabaseUtils.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/Utility/InteractionMetrics.cs create mode 100644 src/Microsoft.SqlTools.CoreServices/Workspace/SettingsService.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/ClientCapabilities.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/DynamicRegistrationCapability.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/CodeAction.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/CodeLens.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/ColorProvider.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/Completion.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/Definition.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/DocumentHighlight.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/DocumentLink.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/DocumentSymbol.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/Formatting.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/Hover.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/Implementation.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/OnTypeFormatting.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/PublishDignostics.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/RangeFormatting.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/References.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/Rename.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/SignatureHelp.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/Synchronization.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/TextDocumentCapabilities.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/TypeDefinition.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/Workspace/DidChangeConfiguration.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/Workspace/DidChangeWatchedFiles.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/Workspace/ExecuteCommand.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/Workspace/Symbol.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/Workspace/WorkspaceCapabilities.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/Workspace/WorkspaceEdit.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/Common/CompletionItemKind.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/Common/MarkupKind.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/Common/SymbolKinds.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/Common/WorkspaceFolder.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/CancelConnectParams.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/CancelConnectRequest.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ChangeDatabaseParams.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ChangeDatabaseRequest.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ConnectParams.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ConnectionChangedNotification.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ConnectionChangedParams.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ConnectionCompleteNotification.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ConnectionDetails.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ConnectionDetailsExtensions.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ConnectionRequest.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ConnectionSummary.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ConnectionSummaryComparer.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ConnectionSummaryExtensions.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ConnectionType.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/DisconnectParams.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/DisconnectRequest.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/LanguageFlavorChange.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ListDatabasesParams.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ListDatabasesRequest.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ListDatabasesResponse.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ServerInfo.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/Explorer/CloseSessionRequest.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/Explorer/CreateSessionRequest.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/Explorer/ExpandRequest.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/Explorer/FindNodesRequest.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/Explorer/NodeInfo.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/Explorer/RefreshRequest.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/GeneralRequestDetails.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/InitializeRequest.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/InitializeRequestWithOptions.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/Metadata/ObjectMetadata.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/Microsoft.SqlTools.DataProtocol.Contracts.csproj create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/ServerCapabilities/CodeLensOptions.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/ServerCapabilities/CompletionOptions.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/ServerCapabilities/DocumentLinkOptions.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/ServerCapabilities/DocumentOnTypeFormattingOptions.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/ServerCapabilities/ExecuteCommandOptions.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/ServerCapabilities/SaveOptions.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/ServerCapabilities/ServerCapabilities.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/ServerCapabilities/SignatureHelpOptions.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/ServerCapabilities/TextDocument.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/ServerCapabilities/Workspace.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/Utilities/FlagsIntConverter.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/Utilities/FlagsStringConverter.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/Utilities/Union.cs create mode 100644 src/Microsoft.SqlTools.DataProtocol.Contracts/Workspace/Configuration.cs create mode 100644 src/Microsoft.SqlTools.Hosting.Contracts/EventType.cs create mode 100644 src/Microsoft.SqlTools.Hosting.Contracts/Internal/Error.cs create mode 100644 src/Microsoft.SqlTools.Hosting.Contracts/Internal/ExitNotification.cs create mode 100644 src/Microsoft.SqlTools.Hosting.Contracts/Internal/HostingErrorNotification.cs create mode 100644 src/Microsoft.SqlTools.Hosting.Contracts/Internal/ShutdownRequest.cs create mode 100644 src/Microsoft.SqlTools.Hosting.Contracts/Microsoft.SqlTools.Hosting.Contracts.csproj create mode 100644 src/Microsoft.SqlTools.Hosting.Contracts/RequestType.cs create mode 100644 src/Microsoft.SqlTools.Hosting.v2/Channels/ChannelBase.cs create mode 100644 src/Microsoft.SqlTools.Hosting.v2/Channels/StdioClientChannel.cs create mode 100644 src/Microsoft.SqlTools.Hosting.v2/Channels/StdioServerChannel.cs create mode 100644 src/Microsoft.SqlTools.Hosting.v2/Extensibility/ExportStandardMetadataAttribute.cs create mode 100644 src/Microsoft.SqlTools.Hosting.v2/Extensibility/ExtensionServiceProvider.cs create mode 100644 src/Microsoft.SqlTools.Hosting.v2/Extensibility/IComposableService.cs create mode 100644 src/Microsoft.SqlTools.Hosting.v2/Extensibility/IHostedService.cs create mode 100644 src/Microsoft.SqlTools.Hosting.v2/Extensibility/IMultiServiceProvider.cs create mode 100644 src/Microsoft.SqlTools.Hosting.v2/Extensibility/IStandardMetadata.cs create mode 100644 src/Microsoft.SqlTools.Hosting.v2/Extensibility/RegisteredServiceProvider.cs create mode 100644 src/Microsoft.SqlTools.Hosting.v2/ExtensibleServiceHost.cs create mode 100644 src/Microsoft.SqlTools.Hosting.v2/IServiceHost.cs create mode 100755 src/Microsoft.SqlTools.Hosting.v2/Localization/sr.cs create mode 100755 src/Microsoft.SqlTools.Hosting.v2/Localization/sr.resx create mode 100644 src/Microsoft.SqlTools.Hosting.v2/Localization/sr.strings create mode 100644 src/Microsoft.SqlTools.Hosting.v2/Localization/sr.xlf create mode 100644 src/Microsoft.SqlTools.Hosting.v2/Microsoft.SqlTools.Hosting.csproj create mode 100644 src/Microsoft.SqlTools.Hosting.v2/Properties/AssemblyInfo.cs create mode 100644 src/Microsoft.SqlTools.Hosting.v2/Protocol/EventContext.cs create mode 100644 src/Microsoft.SqlTools.Hosting.v2/Protocol/Exceptions.cs create mode 100644 src/Microsoft.SqlTools.Hosting.v2/Protocol/IEventSender.cs create mode 100644 src/Microsoft.SqlTools.Hosting.v2/Protocol/IJsonRpcHost.cs create mode 100644 src/Microsoft.SqlTools.Hosting.v2/Protocol/IMessageDispatcher.cs create mode 100644 src/Microsoft.SqlTools.Hosting.v2/Protocol/IRequestSender.cs create mode 100644 src/Microsoft.SqlTools.Hosting.v2/Protocol/JsonRpcHost.cs create mode 100644 src/Microsoft.SqlTools.Hosting.v2/Protocol/Message.cs create mode 100644 src/Microsoft.SqlTools.Hosting.v2/Protocol/MessageReader.cs create mode 100644 src/Microsoft.SqlTools.Hosting.v2/Protocol/MessageWriter.cs create mode 100644 src/Microsoft.SqlTools.Hosting.v2/Protocol/RequestContext.cs create mode 100644 src/Microsoft.SqlTools.Hosting.v2/ServiceHost.cs create mode 100644 src/Microsoft.SqlTools.Hosting.v2/Utility/AsyncLock.cs create mode 100644 src/Microsoft.SqlTools.Hosting.v2/Utility/CommandOptions.cs create mode 100644 src/Microsoft.SqlTools.Hosting.v2/Utility/Extensions.cs create mode 100644 src/Microsoft.SqlTools.Hosting.v2/Utility/Logger.cs create mode 100644 src/Microsoft.SqlTools.Hosting.v2/Utility/ServiceProviderNotSetException.cs create mode 100644 src/Microsoft.SqlTools.Hosting.v2/Utility/TaskExtensions.cs create mode 100644 src/Microsoft.SqlTools.Hosting.v2/Utility/Validate.cs create mode 100644 src/sqltools.common.targets create mode 100644 test/Microsoft.SqlTools.Hosting.UnitTests/CommonObjects.cs create mode 100644 test/Microsoft.SqlTools.Hosting.UnitTests/ExtensibilityTests/ServiceProviderTests.cs create mode 100644 test/Microsoft.SqlTools.Hosting.UnitTests/Microsoft.SqlTools.Hosting.UnitTests.csproj create mode 100644 test/Microsoft.SqlTools.Hosting.UnitTests/ProtocolTests/EventContextTests.cs create mode 100644 test/Microsoft.SqlTools.Hosting.UnitTests/ProtocolTests/JsonRpcHostTests.cs create mode 100644 test/Microsoft.SqlTools.Hosting.UnitTests/ProtocolTests/MessageReaderTests.cs create mode 100644 test/Microsoft.SqlTools.Hosting.UnitTests/ProtocolTests/MessageTests.cs create mode 100644 test/Microsoft.SqlTools.Hosting.UnitTests/ProtocolTests/MessageWriterTests.cs create mode 100644 test/Microsoft.SqlTools.Hosting.UnitTests/ProtocolTests/RequestContextTests.cs create mode 100644 test/Microsoft.SqlTools.Hosting.UnitTests/ServiceHostTests/ExtensibleServiceHostTest.cs create mode 100644 test/Microsoft.SqlTools.Hosting.UnitTests/ServiceHostTests/ServiceHostTests.cs create mode 100644 test/Microsoft.SqlTools.Hosting.UnitTests/TaskExtensions.cs create mode 100644 test/Microsoft.SqlTools.Hosting.UnitTests/UtilityTests/AsyncLockTests.cs create mode 100644 test/Microsoft.SqlTools.Hosting.UnitTests/UtilityTests/LoggerTests.cs diff --git a/build.cake b/build.cake index ed4865b1..5e2fa7bd 100644 --- a/build.cake +++ b/build.cake @@ -48,6 +48,7 @@ public class BuildPlan public string[] Frameworks { get; set; } public string[] Rids { get; set; } public string[] MainProjects { get; set; } + public string[] PackageProjects { get; set; } } var buildPlan = JsonConvert.DeserializeObject( @@ -65,6 +66,7 @@ var artifactFolder = System.IO.Path.Combine(workingDirectory, buildPlan.Artifact var publishFolder = System.IO.Path.Combine(artifactFolder, "publish"); var logFolder = System.IO.Path.Combine(artifactFolder, "logs"); var packageFolder = System.IO.Path.Combine(artifactFolder, "package"); +var nugetPackageFolder = System.IO.Path.Combine(artifactFolder, "nugetPackages"); var scriptFolder = System.IO.Path.Combine(artifactFolder, "scripts"); /// @@ -226,7 +228,30 @@ Task("BuildTest") } } }); - +/// +/// Build Test projects. +/// +Task("DotnetPack") + .IsDependentOn("Cleanup") + .IsDependentOn("Setup") + .IsDependentOn("Restore") + .Does(() => +{ + foreach (var project in buildPlan.PackageProjects) + { + // For now, putting all nugets in the 1 directory + var outputFolder = System.IO.Path.Combine(nugetPackageFolder); + var projectFolder = System.IO.Path.Combine(sourceFolder, project); + var runLog = new List(); + Run(dotnetcli, $"pack --configuration {configuration} --output {outputFolder} \"{projectFolder}\"", + new RunOptions + { + StandardOutputListing = runLog + }) + .ExceptionOnError($"Packaging test {project} failed."); + System.IO.File.WriteAllLines(System.IO.Path.Combine(logFolder, $"{project}-pack.log"), runLog.ToArray()); + } +}); /// /// Run all tests for .NET Desktop and .NET Core /// @@ -477,6 +502,7 @@ Task("All") .IsDependentOn("Restore") .IsDependentOn("TestAll") .IsDependentOn("AllPublish") + .IsDependentOn("DotnetPack") //.IsDependentOn("TestPublished") .Does(() => { diff --git a/build.json b/build.json index 255024b4..7627ae5d 100644 --- a/build.json +++ b/build.json @@ -19,5 +19,11 @@ "Microsoft.SqlTools.ServiceLayer", "Microsoft.SqlTools.Credentials", "Microsoft.SqlTools.ResourceProvider" + ], + "PackageProjects": [ + "Microsoft.SqlTools.CoreServices", + "Microsoft.SqlTools.DataProtocol.Contracts", + "Microsoft.SqlTools.Hosting.Contracts", + "Microsoft.SqlTools.Hosting.v2" ] } diff --git a/sqltoolsservice.sln b/sqltoolsservice.sln index d594b82b..bcef0a92 100644 --- a/sqltoolsservice.sln +++ b/sqltoolsservice.sln @@ -54,8 +54,18 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.SqlTools.Credenti EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.SqlTools.Hosting", "src\Microsoft.SqlTools.Hosting\Microsoft.SqlTools.Hosting.csproj", "{AAE1F8D1-F7AB-4ABE-A55B-D423393AB352}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.SqlTools.Hosting.v2", "src\Microsoft.SqlTools.Hosting.v2\Microsoft.SqlTools.Hosting.csproj", "{BBF1F8D1-F7AB-4ABE-A55B-D423393AB352}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.SqlTools.DataProtocol.Contracts", "src\Microsoft.SqlTools.DataProtocol.Contracts\Microsoft.SqlTools.DataProtocol.Contracts.csproj", "{220E1DEC-32EC-4B3B-A1DB-159ECFDD3A8D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.SqlTools.CoreServices", "src\Microsoft.SqlTools.CoreServices\Microsoft.SqlTools.CoreServices.csproj", "{444E79F1-477A-481A-9BE6-6559B32CE177}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.SqlTools.Hosting.Contracts", "src\Microsoft.SqlTools.Hosting.Contracts\Microsoft.SqlTools.Hosting.Contracts.csproj", "{BE04C532-C9AE-4C32-9283-F6629112228B}" +EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.SqlTools.ServiceLayer", "src\Microsoft.SqlTools.ServiceLayer\Microsoft.SqlTools.ServiceLayer.csproj", "{835EDEB4-289B-4D6D-A9A0-609E43A87D6E}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.SqlTools.Hosting.UnitTests", "test\Microsoft.SqlTools.Hosting.UnitTests\Microsoft.SqlTools.Hosting.UnitTests.csproj", "{BA3C9622-ABFF-45A2-91AA-CC5189083256}" +EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.SqlTools.ServiceLayer.UnitTests", "test\Microsoft.SqlTools.ServiceLayer.UnitTests\Microsoft.SqlTools.ServiceLayer.UnitTests.csproj", "{F18471B5-2042-409D-BF2C-E5403C322DC9}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.SqlTools.ServiceLayer.TestDriver", "test\Microsoft.SqlTools.ServiceLayer.TestDriver\Microsoft.SqlTools.ServiceLayer.TestDriver.csproj", "{4F250E56-F8B4-4E69-AECC-4D31EDD891E7}" @@ -161,6 +171,26 @@ Global {EFB39C03-F7D2-4E8D-BE51-09121CD71973}.Integration|Any CPU.Build.0 = Debug|Any CPU {EFB39C03-F7D2-4E8D-BE51-09121CD71973}.Release|Any CPU.ActiveCfg = Release|Any CPU {EFB39C03-F7D2-4E8D-BE51-09121CD71973}.Release|Any CPU.Build.0 = Release|Any CPU + {BBF1F8D1-F7AB-4ABE-A55B-D423393AB352}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BBF1F8D1-F7AB-4ABE-A55B-D423393AB352}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BBF1F8D1-F7AB-4ABE-A55B-D423393AB352}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BBF1F8D1-F7AB-4ABE-A55B-D423393AB352}.Release|Any CPU.Build.0 = Release|Any CPU + {220E1DEC-32EC-4B3B-A1DB-159ECFDD3A8D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {220E1DEC-32EC-4B3B-A1DB-159ECFDD3A8D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {220E1DEC-32EC-4B3B-A1DB-159ECFDD3A8D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {220E1DEC-32EC-4B3B-A1DB-159ECFDD3A8D}.Release|Any CPU.Build.0 = Release|Any CPU + {444E79F1-477A-481A-9BE6-6559B32CE177}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {444E79F1-477A-481A-9BE6-6559B32CE177}.Debug|Any CPU.Build.0 = Debug|Any CPU + {444E79F1-477A-481A-9BE6-6559B32CE177}.Release|Any CPU.ActiveCfg = Release|Any CPU + {444E79F1-477A-481A-9BE6-6559B32CE177}.Release|Any CPU.Build.0 = Release|Any CPU + {BE04C532-C9AE-4C32-9283-F6629112228B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BE04C532-C9AE-4C32-9283-F6629112228B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BE04C532-C9AE-4C32-9283-F6629112228B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BE04C532-C9AE-4C32-9283-F6629112228B}.Release|Any CPU.Build.0 = Release|Any CPU + {BA3C9622-ABFF-45A2-91AA-CC5189083256}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BA3C9622-ABFF-45A2-91AA-CC5189083256}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BA3C9622-ABFF-45A2-91AA-CC5189083256}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BA3C9622-ABFF-45A2-91AA-CC5189083256}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -181,6 +211,11 @@ Global {6FEE7E14-8A1D-454E-8F7C-B63597801787} = {2BBD7364-054F-4693-97CD-1C395E3E84A9} {70E63BC1-2C82-41C0-89D6-272FD3C7B0C9} = {2BBD7364-054F-4693-97CD-1C395E3E84A9} {EFB39C03-F7D2-4E8D-BE51-09121CD71973} = {2BBD7364-054F-4693-97CD-1C395E3E84A9} + {BBF1F8D1-F7AB-4ABE-A55B-D423393AB352} = {2BBD7364-054F-4693-97CD-1C395E3E84A9} + {220E1DEC-32EC-4B3B-A1DB-159ECFDD3A8D} = {2BBD7364-054F-4693-97CD-1C395E3E84A9} + {444E79F1-477A-481A-9BE6-6559B32CE177} = {2BBD7364-054F-4693-97CD-1C395E3E84A9} + {BE04C532-C9AE-4C32-9283-F6629112228B} = {2BBD7364-054F-4693-97CD-1C395E3E84A9} + {BA3C9622-ABFF-45A2-91AA-CC5189083256} = {AB9CA2B8-6F70-431C-8A1D-67479D8A7BE4} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {B31CDF4B-2851-45E5-8C5F-BE97125D9DD8} diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/CancelTokenKey.cs b/src/Microsoft.SqlTools.CoreServices/Connection/CancelTokenKey.cs new file mode 100644 index 00000000..63f2032a --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Connection/CancelTokenKey.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.SqlTools.DataProtocol.Contracts.Connection; + +namespace Microsoft.SqlTools.CoreServices.Connection +{ + /// + /// Used to uniquely identify a CancellationTokenSource associated with both + /// a string URI and a string connection type. + /// + public class CancelTokenKey : CancelConnectParams, IEquatable + { + public override bool Equals(object obj) + { + CancelTokenKey other = obj as CancelTokenKey; + if (other == null) + { + return false; + } + + return other.OwnerUri == OwnerUri && other.Type == Type; + } + + public bool Equals(CancelTokenKey obj) + { + return obj.OwnerUri == OwnerUri && obj.Type == Type; + } + + public override int GetHashCode() + { + return OwnerUri.GetHashCode() ^ Type.GetHashCode(); + } + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/ConnectParamsExtensions.cs b/src/Microsoft.SqlTools.CoreServices/Connection/ConnectParamsExtensions.cs new file mode 100644 index 00000000..e2824e2d --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Connection/ConnectParamsExtensions.cs @@ -0,0 +1,50 @@ +// +// 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.DataProtocol.Contracts.Connection; + +namespace Microsoft.SqlTools.CoreServices.Connection +{ + /// + /// Extension methods to ConnectParams + /// + public static class ConnectParamsExtensions + { + /// + /// Check that the fields in ConnectParams are all valid + /// + public static bool IsValid(this ConnectParams parameters, out string errorMessage) + { + errorMessage = string.Empty; + if (string.IsNullOrEmpty(parameters.OwnerUri)) + { + errorMessage = SR.ConnectionParamsValidateNullOwnerUri; + } + else if (parameters.Connection == null) + { + errorMessage = SR.ConnectionParamsValidateNullConnection; + } + else if (!string.IsNullOrEmpty(parameters.Connection.ConnectionString)) + { + // Do not check other connection parameters if a connection string is present + return string.IsNullOrEmpty(errorMessage); + } + else if (string.IsNullOrEmpty(parameters.Connection.ServerName)) + { + errorMessage = SR.ConnectionParamsValidateNullServerName; + } + else if (string.IsNullOrEmpty(parameters.Connection.AuthenticationType) || parameters.Connection.AuthenticationType == "SqlLogin") + { + // For SqlLogin, username cannot be empty + if (string.IsNullOrEmpty(parameters.Connection.UserName)) + { + errorMessage = SR.ConnectionParamsValidateNullSqlAuth("UserName"); + } + } + + return string.IsNullOrEmpty(errorMessage); + } + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/ConnectionInfo.cs b/src/Microsoft.SqlTools.CoreServices/Connection/ConnectionInfo.cs new file mode 100644 index 00000000..96aeeee3 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Connection/ConnectionInfo.cs @@ -0,0 +1,171 @@ +// +// 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.Concurrent; +using System.Collections.Generic; +using System.Data.Common; +using Microsoft.SqlTools.DataProtocol.Contracts.Connection; +using Microsoft.SqlTools.Hosting.Utility; + +namespace Microsoft.SqlTools.CoreServices.Connection +{ + /// + /// Information pertaining to a unique connection instance. + /// + public class ConnectionInfo + { + /// + /// Constructor + /// + public ConnectionInfo(ISqlConnectionFactory factory, string ownerUri, ConnectionDetails details) + { + Factory = factory; + OwnerUri = ownerUri; + ConnectionDetails = details; + ConnectionId = Guid.NewGuid(); + IntellisenseMetrics = new InteractionMetrics(new int[] {50, 100, 200, 500, 1000, 2000}); + } + + /// + /// Unique Id, helpful to identify a connection info object + /// + public Guid ConnectionId { get; private set; } + + /// + /// URI identifying the owner/user of the connection. Could be a file, service, resource, etc. + /// + public string OwnerUri { get; private set; } + + /// + /// Factory used for creating the SQL connection associated with the connection info. + /// + public ISqlConnectionFactory Factory { get; private set; } + + /// + /// Properties used for creating/opening the SQL connection. + /// + public ConnectionDetails ConnectionDetails { get; private set; } + + /// + /// A map containing all connections to the database that are associated with + /// this ConnectionInfo's OwnerUri. + /// This is internal for testing access only + /// + internal readonly ConcurrentDictionary ConnectionTypeToConnectionMap = + new ConcurrentDictionary(); + + /// + /// Intellisense Metrics + /// + public InteractionMetrics IntellisenseMetrics { get; private set; } + + /// + /// Returns true if the db connection is to any cloud instance + /// + public bool IsCloud { get; set; } + + /// + /// Returns true if the db connection is to a SQL db instance + /// + public bool IsSqlDb { get; set; } + + /// Returns true if the sql connection is to a DW instance + /// + public bool IsSqlDW { get; set; } + + /// + /// Returns the major version number of the db we are connected to + /// + public int MajorVersion { get; set; } + + /// + /// All DbConnection instances held by this ConnectionInfo + /// + public ICollection AllConnections + { + get + { + return ConnectionTypeToConnectionMap.Values; + } + } + + /// + /// All connection type strings held by this ConnectionInfo + /// + /// + public ICollection AllConnectionTypes + { + get + { + return ConnectionTypeToConnectionMap.Keys; + } + } + + public bool HasConnectionType(string connectionType) + { + connectionType = connectionType ?? ConnectionType.Default; + return ConnectionTypeToConnectionMap.ContainsKey(connectionType); + } + + /// + /// The count of DbConnectioninstances held by this ConnectionInfo + /// + public int CountConnections + { + get + { + return ConnectionTypeToConnectionMap.Count; + } + } + + /// + /// Try to get the DbConnection associated with the given connection type string. + /// + /// true if a connection with type connectionType was located and out connection was set, + /// false otherwise + /// Thrown when connectionType is null or empty + public bool TryGetConnection(string connectionType, out DbConnection connection) + { + Validate.IsNotNullOrEmptyString("Connection Type", connectionType); + return ConnectionTypeToConnectionMap.TryGetValue(connectionType, out connection); + } + + /// + /// Adds a DbConnection to this object and associates it with the given + /// connection type string. If a connection already exists with an identical + /// connection type string, it is not overwritten. Ignores calls where connectionType = null + /// + /// Thrown when connectionType is null or empty + public void AddConnection(string connectionType, DbConnection connection) + { + Validate.IsNotNullOrEmptyString("Connection Type", connectionType); + ConnectionTypeToConnectionMap.TryAdd(connectionType, connection); + } + + /// + /// Removes the single DbConnection instance associated with string connectionType + /// + /// Thrown when connectionType is null or empty + public void RemoveConnection(string connectionType) + { + Validate.IsNotNullOrEmptyString("Connection Type", connectionType); + DbConnection connection; + ConnectionTypeToConnectionMap.TryRemove(connectionType, out connection); + } + + /// + /// Removes all DbConnection instances held by this object + /// + public void RemoveAllConnections() + { + foreach (var type in AllConnectionTypes) + { + DbConnection connection; + ConnectionTypeToConnectionMap.TryRemove(type, out connection); + } + } + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/ConnectionServiceCore.cs b/src/Microsoft.SqlTools.CoreServices/Connection/ConnectionServiceCore.cs new file mode 100644 index 00000000..229742ed --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Connection/ConnectionServiceCore.cs @@ -0,0 +1,1310 @@ +// +// 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.Concurrent; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Data.SqlClient; +using System.Globalization; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.SqlTools.DataProtocol.Contracts.Connection; +using Microsoft.SqlTools.CoreServices.Connection.ReliableConnection; +using Microsoft.SqlTools.CoreServices.LanguageServices; +using Microsoft.SqlServer.Management.Common; +using Microsoft.SqlTools.Hosting.Utility; +using Microsoft.SqlTools.Hosting; +using Microsoft.SqlTools.Hosting.Protocol; +using Microsoft.SqlTools.CoreServices.LanguageServices.Contracts; +using ConnectionType = Microsoft.SqlTools.DataProtocol.Contracts.Connection.ConnectionType; +using Microsoft.SqlTools.Hosting.Extensibility; +using System.Composition; + +namespace Microsoft.SqlTools.CoreServices.Connection +{ + /// + /// Core Connection Management services, not including hosted service implementation + /// + [Export(typeof(ConnectionServiceCore))] + public class ConnectionServiceCore : IComposableService + { + public const string AdminConnectionPrefix = "ADMIN:"; + private const string SqlAzureEdition = "SQL Azure"; + + + /// + /// The SQL connection factory object + /// + private ISqlConnectionFactory connectionFactory; + + private DatabaseLocksManager lockedDatabaseManager; + + private readonly Dictionary ownerToConnectionMap = new Dictionary(); + + /// + /// A map containing all CancellationTokenSource objects that are associated with a given URI/ConnectionType pair. + /// Entries in this map correspond to DbConnection instances that are in the process of connecting. + /// + private readonly ConcurrentDictionary cancelTupleToCancellationTokenSourceMap = + new ConcurrentDictionary(); + + private readonly object cancellationTokenSourceLock = new object(); + + private ConcurrentDictionary connectedQueues = new ConcurrentDictionary(); + + private IMultiServiceProvider serviceProvider; + + /// + /// Default constructor should be private since it's a singleton class, but we need a constructor + /// for use in unit test mocking. + /// + public ConnectionServiceCore() + { + var defaultQueue = new ConnectedBindingQueue(needsMetadata: false); + connectedQueues.AddOrUpdate(ConnectionType.Default, defaultQueue, (key, old) => defaultQueue); + this.LockedDatabaseManager.ConnectionService = this; + } + + /// + /// Test constructor that injects dependency interfaces + /// + /// + public ConnectionServiceCore(ISqlConnectionFactory testFactory) + { + this.connectionFactory = testFactory; + } + + public void SetServiceProvider(IMultiServiceProvider provider) + { + this.serviceProvider = provider; + } + + + /// + /// Map from script URIs to ConnectionInfo objects + /// This is internal for testing access only + /// + internal Dictionary OwnerToConnectionMap + { + get + { + return this.ownerToConnectionMap; + } + } + + /// + /// Database Lock manager instance + /// + internal DatabaseLocksManager LockedDatabaseManager + { + get + { + if (lockedDatabaseManager == null) + { + lockedDatabaseManager = DatabaseLocksManager.Instance; + } + return lockedDatabaseManager; + } + set + { + this.lockedDatabaseManager = value; + } + } + + /// + /// Gets the connection queue + /// + internal IConnectedBindingQueue ConnectionQueue + { + get + { + return this.GetConnectedQueue("Default"); + } + } + + /// + /// Returns a connection queue for given type + /// + /// + /// + public IConnectedBindingQueue GetConnectedQueue(string type) + { + IConnectedBindingQueue connectedBindingQueue; + if (connectedQueues.TryGetValue(type, out connectedBindingQueue)) + { + return connectedBindingQueue; + } + return null; + } + + /// + /// Returns all the connection queues + /// + public IEnumerable ConnectedQueues + { + get + { + return this.connectedQueues.Values; + } + } + + /// + /// Register a new connection queue if not already registered + /// + /// + /// + public virtual void RegisterConnectedQueue(string type, IConnectedBindingQueue connectedQueue) + { + if (!connectedQueues.ContainsKey(type)) + { + connectedQueues.AddOrUpdate(type, connectedQueue, (key, old) => connectedQueue); + } + } + + /// + /// Callback for onconnection handler + /// + /// + public delegate Task OnConnectionHandler(ConnectionInfo info); + + /// + /// Callback for ondisconnect handler + /// + public delegate Task OnDisconnectHandler(IConnectionSummary summary, string ownerUri); + + /// + /// List of onconnection handlers + /// + private readonly List onConnectionActivities = new List(); + + /// + /// List of ondisconnect handlers + /// + private readonly List onDisconnectActivities = new List(); + + /// + /// Gets the SQL connection factory instance + /// + public ISqlConnectionFactory ConnectionFactory + { + get + { + if (this.connectionFactory == null) + { + this.connectionFactory = new SqlConnectionFactory(); + } + return this.connectionFactory; + } + + internal set { this.connectionFactory = value; } + } + + // Attempts to link a URI to an actively used connection for this URI + public virtual bool TryFindConnection(string ownerUri, out ConnectionInfo connectionInfo) + { + return this.ownerToConnectionMap.TryGetValue(ownerUri, out connectionInfo); + } + + /// + /// Validates the given ConnectParams object. + /// + /// The params to validate + /// A ConnectionCompleteParams object upon validation error, + /// null upon validation success + public ConnectionCompleteParams ValidateConnectParams(ConnectParams connectionParams) + { + string paramValidationErrorMessage; + if (connectionParams == null) + { + return new ConnectionCompleteParams + { + Messages = SR.ConnectionServiceConnectErrorNullParams + }; + } + if (!connectionParams.IsValid(out paramValidationErrorMessage)) + { + return new ConnectionCompleteParams + { + OwnerUri = connectionParams.OwnerUri, + Messages = paramValidationErrorMessage + }; + } + + // return null upon success + return null; + } + + /// + /// Open a connection with the specified ConnectParams + /// + public virtual async Task Connect(ConnectParams connectionParams) + { + // Validate parameters + ConnectionCompleteParams validationResults = ValidateConnectParams(connectionParams); + if (validationResults != null) + { + return validationResults; + } + + TrySetConnectionType(connectionParams); + + connectionParams.Connection.ApplicationName = GetApplicationNameWithFeature(connectionParams.Connection.ApplicationName, connectionParams.Purpose); + // If there is no ConnectionInfo in the map, create a new ConnectionInfo, + // but wait until later when we are connected to add it to the map. + ConnectionInfo connectionInfo; + bool connectionChanged = false; + if (!ownerToConnectionMap.TryGetValue(connectionParams.OwnerUri, out connectionInfo)) + { + connectionInfo = new ConnectionInfo(ConnectionFactory, connectionParams.OwnerUri, connectionParams.Connection); + } + else if (IsConnectionChanged(connectionParams, connectionInfo)) + { + // We are actively changing the connection information for this connection. We must disconnect + // all active connections, since it represents a full context change + connectionChanged = true; + } + + DisconnectExistingConnectionIfNeeded(connectionParams, connectionInfo, disconnectAll: connectionChanged); + + if (connectionChanged) + { + connectionInfo = new ConnectionInfo(ConnectionFactory, connectionParams.OwnerUri, connectionParams.Connection); + } + + // Try to open a connection with the given ConnectParams + ConnectionCompleteParams response = await TryOpenConnection(connectionInfo, connectionParams); + if (response != null) + { + return response; + } + + // If this is the first connection for this URI, add the ConnectionInfo to the map + bool addToMap = connectionChanged || !ownerToConnectionMap.ContainsKey(connectionParams.OwnerUri); + if (addToMap) + { + ownerToConnectionMap[connectionParams.OwnerUri] = connectionInfo; + } + + // Return information about the connected SQL Server instance + ConnectionCompleteParams completeParams = GetConnectionCompleteParams(connectionParams.Type, connectionInfo); + // Invoke callback notifications + InvokeOnConnectionActivities(connectionInfo, connectionParams); + + TryCloseConnectionTemporaryConnection(connectionParams, connectionInfo); + + return completeParams; + } + + private void TryCloseConnectionTemporaryConnection(ConnectParams connectionParams, ConnectionInfo connectionInfo) + { + try + { + if (connectionParams.Purpose == ConnectionType.ObjectExplorer || connectionParams.Purpose == ConnectionType.Dashboard || connectionParams.Purpose == ConnectionType.GeneralConnection) + { + DbConnection connection; + string type = connectionParams.Type; + if (connectionInfo.TryGetConnection(type, out connection)) + { + // OE doesn't need to keep the connection open + connection.Close(); + } + } + } + catch (Exception ex) + { + Logger.Instance.Write(LogLevel.Normal, "Failed to close temporary connections. error: " + ex.Message); + } + } + + private static string GetApplicationNameWithFeature(string applicationName, string featureName) + { + string appNameWithFeature = applicationName; + + if (!string.IsNullOrWhiteSpace(applicationName) && !string.IsNullOrWhiteSpace(featureName)) + { + int index = applicationName.IndexOf('-'); + string appName = applicationName; + if (index > 0) + { + appName = applicationName.Substring(0, index); + } + appNameWithFeature = $"{appName}-{featureName}"; + } + + return appNameWithFeature; + } + + private void TrySetConnectionType(ConnectParams connectionParams) + { + if (connectionParams != null && connectionParams.Type == ConnectionType.Default && !string.IsNullOrWhiteSpace(connectionParams.OwnerUri)) + { + if (connectionParams.OwnerUri.ToLowerInvariant().StartsWith("dashboard://")) + { + connectionParams.Purpose = ConnectionType.Dashboard; + } + else if (connectionParams.OwnerUri.ToLowerInvariant().StartsWith("connection://")) + { + connectionParams.Purpose = ConnectionType.GeneralConnection; + } + } + else if (connectionParams != null) + { + connectionParams.Purpose = connectionParams.Type; + } + } + + private bool IsConnectionChanged(ConnectParams connectionParams, ConnectionInfo connectionInfo) + { + if (connectionInfo.HasConnectionType(connectionParams.Type) + && !connectionInfo.ConnectionDetails.IsComparableTo(connectionParams.Connection)) + { + return true; + } + return false; + } + + private bool IsDefaultConnectionType(string connectionType) + { + return string.IsNullOrEmpty(connectionType) || ConnectionType.Default.Equals(connectionType, StringComparison.CurrentCultureIgnoreCase); + } + + private void DisconnectExistingConnectionIfNeeded(ConnectParams connectionParams, ConnectionInfo connectionInfo, bool disconnectAll) + { + // Resolve if it is an existing connection + // Disconnect active connection if the URI is already connected for this connection type + DbConnection existingConnection; + if (connectionInfo.TryGetConnection(connectionParams.Type, out existingConnection)) + { + var disconnectParams = new DisconnectParams() + { + OwnerUri = connectionParams.OwnerUri, + Type = disconnectAll ? null : connectionParams.Type + }; + Disconnect(disconnectParams); + } + } + + /// + /// Creates a ConnectionCompleteParams as a response to a successful connection. + /// Also sets the DatabaseName and IsAzure properties of ConnectionInfo. + /// + /// A ConnectionCompleteParams in response to the successful connection + private ConnectionCompleteParams GetConnectionCompleteParams(string connectionType, ConnectionInfo connectionInfo) + { + ConnectionCompleteParams response = new ConnectionCompleteParams { OwnerUri = connectionInfo.OwnerUri, Type = connectionType }; + + try + { + DbConnection connection; + connectionInfo.TryGetConnection(connectionType, out connection); + + // Update with the actual database name in connectionInfo and result + // Doing this here as we know the connection is open - expect to do this only on connecting + connectionInfo.ConnectionDetails.DatabaseName = connection.Database; + if (!string.IsNullOrEmpty(connectionInfo.ConnectionDetails.ConnectionString)) + { + // If the connection was set up with a connection string, use the connection string to get the details + var connectionString = new SqlConnectionStringBuilder(connection.ConnectionString); + response.ConnectionSummary = new ConnectionSummary + { + ServerName = connectionString.DataSource, + DatabaseName = connectionString.InitialCatalog, + UserName = connectionString.UserID + }; + } + else + { + response.ConnectionSummary = new ConnectionSummary + { + ServerName = connectionInfo.ConnectionDetails.ServerName, + DatabaseName = connectionInfo.ConnectionDetails.DatabaseName, + UserName = connectionInfo.ConnectionDetails.UserName + }; + } + + response.ConnectionId = connectionInfo.ConnectionId.ToString(); + + var reliableConnection = connection as ReliableSqlConnection; + DbConnection underlyingConnection = reliableConnection != null + ? reliableConnection.GetUnderlyingConnection() + : connection; + + ReliableConnectionHelper.ServerInfo serverInfo = ReliableConnectionHelper.GetServerVersion(underlyingConnection); + response.ServerInfo = new ServerInfo + { + ServerMajorVersion = serverInfo.ServerMajorVersion, + ServerMinorVersion = serverInfo.ServerMinorVersion, + ServerReleaseVersion = serverInfo.ServerReleaseVersion, + EngineEditionId = serverInfo.EngineEditionId, + ServerVersion = serverInfo.ServerVersion, + ServerLevel = serverInfo.ServerLevel, + ServerEdition = MapServerEdition(serverInfo), + IsCloud = serverInfo.IsCloud, + AzureVersion = serverInfo.AzureVersion, + OsVersion = serverInfo.OsVersion, + MachineName = serverInfo.MachineName + }; + connectionInfo.IsCloud = serverInfo.IsCloud; + connectionInfo.MajorVersion = serverInfo.ServerMajorVersion; + connectionInfo.IsSqlDb = serverInfo.EngineEditionId == (int)DatabaseEngineEdition.SqlDatabase; + connectionInfo.IsSqlDW = (serverInfo.EngineEditionId == (int)DatabaseEngineEdition.SqlDataWarehouse); + } + catch (Exception ex) + { + response.Messages = ex.ToString(); + } + + return response; + } + + private string MapServerEdition(ReliableConnectionHelper.ServerInfo serverInfo) + { + string serverEdition = serverInfo.ServerEdition; + if (string.IsNullOrWhiteSpace(serverEdition)) + { + return string.Empty; + } + if (SqlAzureEdition.Equals(serverEdition, StringComparison.OrdinalIgnoreCase)) + { + switch(serverInfo.EngineEditionId) + { + case (int) DatabaseEngineEdition.SqlDataWarehouse: + serverEdition = SR.AzureSqlDwEdition; + break; + case (int) DatabaseEngineEdition.SqlStretchDatabase: + serverEdition = SR.AzureSqlStretchEdition; + break; + default: + serverEdition = SR.AzureSqlDbEdition; + break; + } + } + return serverEdition; + } + + /// + /// Tries to create and open a connection with the given ConnectParams. + /// + /// null upon success, a ConnectionCompleteParams detailing the error upon failure + private async Task TryOpenConnection(ConnectionInfo connectionInfo, ConnectParams connectionParams) + { + CancellationTokenSource source = null; + DbConnection connection = null; + CancelTokenKey cancelKey = new CancelTokenKey { OwnerUri = connectionParams.OwnerUri, Type = connectionParams.Type }; + ConnectionCompleteParams response = new ConnectionCompleteParams { OwnerUri = connectionInfo.OwnerUri, Type = connectionParams.Type }; + bool? currentPooling = connectionInfo.ConnectionDetails.Pooling; + + try + { + connectionInfo.ConnectionDetails.Pooling = false; + // build the connection string from the input parameters + string connectionString = BuildConnectionString(connectionInfo.ConnectionDetails); + + // create a sql connection instance + connection = connectionInfo.Factory.CreateSqlConnection(connectionString); + connectionInfo.AddConnection(connectionParams.Type, connection); + + // Add a cancellation token source so that the connection OpenAsync() can be cancelled + source = new CancellationTokenSource(); + // Locking here to perform two operations as one atomic operation + lock (cancellationTokenSourceLock) + { + // If the URI is currently connecting from a different request, cancel it before we try to connect + CancellationTokenSource currentSource; + if (cancelTupleToCancellationTokenSourceMap.TryGetValue(cancelKey, out currentSource)) + { + currentSource.Cancel(); + } + cancelTupleToCancellationTokenSourceMap[cancelKey] = source; + } + + // Open the connection + await connection.OpenAsync(source.Token); + } + catch (SqlException ex) + { + response.ErrorNumber = ex.Number; + response.ErrorMessage = ex.Message; + response.Messages = ex.ToString(); + return response; + } + catch (OperationCanceledException) + { + // OpenAsync was cancelled + response.Messages = SR.ConnectionServiceConnectionCanceled; + return response; + } + catch (Exception ex) + { + response.ErrorMessage = ex.Message; + response.Messages = ex.ToString(); + return response; + } + finally + { + // Remove our cancellation token from the map since we're no longer connecting + // Using a lock here to perform two operations as one atomic operation + lock (cancellationTokenSourceLock) + { + // Only remove the token from the map if it is the same one created by this request + CancellationTokenSource sourceValue; + if (cancelTupleToCancellationTokenSourceMap.TryGetValue(cancelKey, out sourceValue) && sourceValue == source) + { + cancelTupleToCancellationTokenSourceMap.TryRemove(cancelKey, out sourceValue); + } + source?.Dispose(); + } + if (connectionInfo != null && connectionInfo.ConnectionDetails != null) + { + connectionInfo.ConnectionDetails.Pooling = currentPooling; + } + } + + // Return null upon success + return null; + } + + /// + /// Gets the existing connection with the given URI and connection type string. If none exists, + /// creates a new connection. This cannot be used to create a default connection or to create a + /// connection if a default connection does not exist. + /// + /// URI identifying the resource mapped to this connection + /// + /// What the purpose for this connection is. A single resource + /// such as a SQL file may have multiple connections - one for Intellisense, another for query execution + /// + /// + /// Workaround for .Net Core clone connection issues: should persist security be used so that + /// when SMO clones connections it can do so without breaking on SQL Password connections. + /// This should be removed once the core issue is resolved and clone works as expected + /// + /// A DB connection for the connection type requested + public virtual async Task GetOrOpenConnection(string ownerUri, string connectionType, bool alwaysPersistSecurity = false) + { + Validate.IsNotNullOrEmptyString(nameof(ownerUri), ownerUri); + Validate.IsNotNullOrEmptyString(nameof(connectionType), connectionType); + + // Try to get the ConnectionInfo, if it exists + ConnectionInfo connectionInfo; + if (!ownerToConnectionMap.TryGetValue(ownerUri, out connectionInfo)) + { + throw new ArgumentOutOfRangeException(SR.ConnectionServiceListDbErrorNotConnected(ownerUri)); + } + + // Make sure a default connection exists + DbConnection connection; + DbConnection defaultConnection; + if (!connectionInfo.TryGetConnection(ConnectionType.Default, out defaultConnection)) + { + throw new InvalidOperationException(SR.ConnectionServiceDbErrorDefaultNotConnected(ownerUri)); + } + + if(IsDedicatedAdminConnection(connectionInfo.ConnectionDetails)) + { + // Since this is a dedicated connection only 1 is allowed at any time. Return the default connection for use in the requested action + connection = defaultConnection; + } + else + { + // Try to get the DbConnection and create if it doesn't already exist + if (!connectionInfo.TryGetConnection(connectionType, out connection) && ConnectionType.Default != connectionType) + { + connection = await TryOpenConnectionForConnectionType(ownerUri, connectionType, alwaysPersistSecurity, connectionInfo); + } + } + + VerifyConnectionOpen(connection); + + return connection; + } + + private async Task TryOpenConnectionForConnectionType(string ownerUri, string connectionType, + bool alwaysPersistSecurity, ConnectionInfo connectionInfo) + { + // If the DbConnection does not exist and is not the default connection, create one. + // We can't create the default (initial) connection here because we won't have a ConnectionDetails + // if Connect() has not yet been called. + bool? originalPersistSecurityInfo = connectionInfo.ConnectionDetails.PersistSecurityInfo; + if (alwaysPersistSecurity) + { + connectionInfo.ConnectionDetails.PersistSecurityInfo = true; + } + ConnectParams connectParams = new ConnectParams + { + OwnerUri = ownerUri, + Connection = connectionInfo.ConnectionDetails, + Type = connectionType + }; + try + { + await Connect(connectParams); + } + finally + { + connectionInfo.ConnectionDetails.PersistSecurityInfo = originalPersistSecurityInfo; + } + + DbConnection connection; + connectionInfo.TryGetConnection(connectionType, out connection); + return connection; + } + + private void VerifyConnectionOpen(DbConnection connection) + { + if (connection == null) + { + // Ignore this connection + return; + } + + if (connection.State != ConnectionState.Open) + { + // Note: this will fail and throw to the caller if something goes wrong. + // This seems the right thing to do but if this causes serviceability issues where stack trace + // is unexpected, might consider catching and allowing later code to fail. But given we want to get + // an opened connection for any action using this, it seems OK to handle in this manner + ClearPool(connection); + connection.Open(); + } + } + + /// + /// Clears the connection pool if this is a SqlConnection of some kind. + /// + private void ClearPool(DbConnection connection) + { + SqlConnection sqlConn; + if (TryGetAsSqlConnection(connection, out sqlConn)) + { + SqlConnection.ClearPool(sqlConn); + } + } + + private bool TryGetAsSqlConnection(DbConnection dbConn, out SqlConnection sqlConn) + { + ReliableSqlConnection reliableConn = dbConn as ReliableSqlConnection; + if (reliableConn != null) + { + sqlConn = reliableConn.GetUnderlyingConnection(); + } + else + { + sqlConn = dbConn as SqlConnection; + } + + return sqlConn != null; + } + + /// + /// Cancel a connection that is in the process of opening. + /// + public bool CancelConnect(CancelConnectParams cancelParams) + { + // Validate parameters + if (cancelParams == null || string.IsNullOrEmpty(cancelParams.OwnerUri)) + { + return false; + } + + CancelTokenKey cancelKey = new CancelTokenKey + { + OwnerUri = cancelParams.OwnerUri, + Type = cancelParams.Type + }; + + // Cancel any current connection attempts for this URI + CancellationTokenSource source; + if (cancelTupleToCancellationTokenSourceMap.TryGetValue(cancelKey, out source)) + { + try + { + source.Cancel(); + return true; + } + catch + { + return false; + } + } + + return false; + } + + /// + /// Close a connection with the specified connection details. + /// + public virtual bool Disconnect(DisconnectParams disconnectParams) + { + // Validate parameters + if (disconnectParams == null || string.IsNullOrEmpty(disconnectParams.OwnerUri)) + { + return false; + } + + // Cancel if we are in the middle of connecting + if (CancelConnections(disconnectParams.OwnerUri, disconnectParams.Type)) + { + return false; + } + + // Lookup the ConnectionInfo owned by the URI + ConnectionInfo info; + if (!ownerToConnectionMap.TryGetValue(disconnectParams.OwnerUri, out info)) + { + return false; + } + + // Call Close() on the connections we want to disconnect + // If no connections were located, return false + if (!CloseConnections(info, disconnectParams.Type)) + { + return false; + } + + // Remove the disconnected connections from the ConnectionInfo map + if (disconnectParams.Type == null) + { + info.RemoveAllConnections(); + } + else + { + info.RemoveConnection(disconnectParams.Type); + } + + // If the ConnectionInfo has no more connections, remove the ConnectionInfo + if (info.CountConnections == 0) + { + ownerToConnectionMap.Remove(disconnectParams.OwnerUri); + } + + // Handle Telemetry disconnect events if we are disconnecting the default connection + if (disconnectParams.Type == null || disconnectParams.Type == ConnectionType.Default) + { + HandleDisconnectTelemetry(info); + InvokeOnDisconnectionActivities(info); + } + + // Return true upon success + return true; + } + + /// + /// Cancel connections associated with the given ownerUri. + /// If connectionType is not null, cancel the connection with the given connectionType + /// If connectionType is null, cancel all pending connections associated with ownerUri. + /// + /// true if a single pending connection associated with the non-null connectionType was + /// found and cancelled, false otherwise + private bool CancelConnections(string ownerUri, string connectionType) + { + // Cancel the connection of the given type + if (connectionType != null) + { + // If we are trying to disconnect a specific connection and it was just cancelled, + // this will return true + return CancelConnect(new CancelConnectParams() { OwnerUri = ownerUri, Type = connectionType }); + } + + // Cancel all pending connections + foreach (var entry in cancelTupleToCancellationTokenSourceMap) + { + string entryConnectionUri = entry.Key.OwnerUri; + string entryConnectionType = entry.Key.Type; + if (ownerUri.Equals(entryConnectionUri)) + { + CancelConnect(new CancelConnectParams() { OwnerUri = ownerUri, Type = entryConnectionType }); + } + } + + return false; + } + + /// + /// Closes DbConnections associated with the given ConnectionInfo. + /// If connectionType is not null, closes the DbConnection with the type given by connectionType. + /// If connectionType is null, closes all DbConnections. + /// + /// true if connections were found and attempted to be closed, + /// false if no connections were found + private bool CloseConnections(ConnectionInfo connectionInfo, string connectionType) + { + ICollection connectionsToDisconnect = new List(); + if (connectionType == null) + { + connectionsToDisconnect = connectionInfo.AllConnections; + } + else + { + // Make sure there is an existing connection of this type + DbConnection connection; + if (!connectionInfo.TryGetConnection(connectionType, out connection)) + { + return false; + } + connectionsToDisconnect.Add(connection); + } + + if (connectionsToDisconnect.Count == 0) + { + return false; + } + + foreach (DbConnection connection in connectionsToDisconnect) + { + try + { + connection.Close(); + } + catch (Exception) + { + // Ignore + } + } + + return true; + } + + /// + /// List all databases on the server specified + /// + public ListDatabasesResponse ListDatabases(ListDatabasesParams listDatabasesParams) + { + // Verify parameters + var owner = listDatabasesParams.OwnerUri; + if (string.IsNullOrEmpty(owner)) + { + throw new ArgumentException(SR.ConnectionServiceListDbErrorNullOwnerUri); + } + + // Use the existing connection as a base for the search + ConnectionInfo info; + if (!TryFindConnection(owner, out info)) + { + throw new Exception(SR.ConnectionServiceListDbErrorNotConnected(owner)); + } + + ListDatabasesResponse response = new ListDatabasesResponse(); + response.DatabaseNames = ListDatabasesFromConnInfo(info); + + return response; + } + + public string[] ListDatabasesFromConnInfo(ConnectionInfo info, bool includeSystemDBs = true) + { + ConnectionDetails connectionDetails = info.ConnectionDetails.Clone(); + + // Connect to master and query sys.databases + connectionDetails.DatabaseName = "master"; + List dbNames = new List(); + + using (DbConnection connection = this.ConnectionFactory.CreateSqlConnection(BuildConnectionString(connectionDetails))) + using (DbCommand command = connection.CreateCommand()) + { + connection.Open(); + command.CommandText = @"SELECT name FROM sys.databases WHERE state_desc='ONLINE' ORDER BY name ASC"; + command.CommandTimeout = 15; + command.CommandType = CommandType.Text; + + using (DbDataReader reader = command.ExecuteReader()) + { + while (reader.Read()) + { + dbNames.Add(reader[0].ToString()); + } + } + } + + string[] results; + var systemDBSet = new HashSet(new[] {"master", "model", "msdb", "tempdb"}); + if (includeSystemDBs) + { + // Put system databases at the top of the list + results = + dbNames.Where(s => systemDBSet.Contains(s)) + .Concat(dbNames.Where(s => !systemDBSet.Contains(s))) + .ToArray(); + } + else + { + results = dbNames.Where(s => !systemDBSet.Contains(s)).ToArray(); + } + + return results; + } + + /// + /// Add a new method to be called when the onconnection request is submitted + /// + /// + public void RegisterOnConnectionTask(OnConnectionHandler activity) + { + onConnectionActivities.Add(activity); + } + + /// + /// Add a new method to be called when the ondisconnect request is submitted + /// + public void RegisterOnDisconnectTask(OnDisconnectHandler activity) + { + onDisconnectActivities.Add(activity); + } + + /// + /// Checks if a ConnectionDetails object represents a DAC connection + /// + /// + public static bool IsDedicatedAdminConnection(ConnectionDetails connectionDetails) + { + Validate.IsNotNull(nameof(connectionDetails), connectionDetails); + SqlConnectionStringBuilder builder = CreateConnectionStringBuilder(connectionDetails); + string serverName = builder.DataSource; + return serverName != null && serverName.StartsWith(AdminConnectionPrefix, StringComparison.OrdinalIgnoreCase); + } + + /// + /// Build a connection string from a connection details instance + /// + /// + public static string BuildConnectionString(ConnectionDetails connectionDetails) + { + return CreateConnectionStringBuilder(connectionDetails).ToString(); + } + + /// + /// Build a connection string builder a connection details instance + /// + /// + public static SqlConnectionStringBuilder CreateConnectionStringBuilder(ConnectionDetails connectionDetails) + { + SqlConnectionStringBuilder connectionBuilder; + + // If connectionDetails has a connection string already, use it to initialize the connection builder, then override any provided options. + // Otherwise use the server name, username, and password from the connection details. + if (!string.IsNullOrEmpty(connectionDetails.ConnectionString)) + { + connectionBuilder = new SqlConnectionStringBuilder(connectionDetails.ConnectionString); + } + else + { + // add alternate port to data source property if provided + string dataSource = !connectionDetails.Port.HasValue + ? connectionDetails.ServerName + : string.Format("{0},{1}", connectionDetails.ServerName, connectionDetails.Port.Value); + + connectionBuilder = new SqlConnectionStringBuilder + { + ["Data Source"] = dataSource, + ["User Id"] = connectionDetails.UserName, + ["Password"] = connectionDetails.Password + }; + } + + // Check for any optional parameters + if (!string.IsNullOrEmpty(connectionDetails.DatabaseName)) + { + connectionBuilder["Initial Catalog"] = connectionDetails.DatabaseName; + } + if (!string.IsNullOrEmpty(connectionDetails.AuthenticationType)) + { + switch(connectionDetails.AuthenticationType) + { + case "Integrated": + connectionBuilder.IntegratedSecurity = true; + break; + case "SqlLogin": + break; + default: + throw new ArgumentException(SR.ConnectionServiceConnStringInvalidAuthType(connectionDetails.AuthenticationType)); + } + } + if (connectionDetails.Encrypt.HasValue) + { + connectionBuilder.Encrypt = connectionDetails.Encrypt.Value; + } + if (connectionDetails.TrustServerCertificate.HasValue) + { + connectionBuilder.TrustServerCertificate = connectionDetails.TrustServerCertificate.Value; + } + if (connectionDetails.PersistSecurityInfo.HasValue) + { + connectionBuilder.PersistSecurityInfo = connectionDetails.PersistSecurityInfo.Value; + } + if (connectionDetails.ConnectTimeout.HasValue) + { + connectionBuilder.ConnectTimeout = connectionDetails.ConnectTimeout.Value; + } + if (connectionDetails.ConnectRetryCount.HasValue) + { + connectionBuilder.ConnectRetryCount = connectionDetails.ConnectRetryCount.Value; + } + if (connectionDetails.ConnectRetryInterval.HasValue) + { + connectionBuilder.ConnectRetryInterval = connectionDetails.ConnectRetryInterval.Value; + } + if (!string.IsNullOrEmpty(connectionDetails.ApplicationName)) + { + connectionBuilder.ApplicationName = connectionDetails.ApplicationName; + } + if (!string.IsNullOrEmpty(connectionDetails.WorkstationId)) + { + connectionBuilder.WorkstationID = connectionDetails.WorkstationId; + } + if (!string.IsNullOrEmpty(connectionDetails.ApplicationIntent)) + { + ApplicationIntent intent; + switch (connectionDetails.ApplicationIntent) + { + case "ReadOnly": + intent = ApplicationIntent.ReadOnly; + break; + case "ReadWrite": + intent = ApplicationIntent.ReadWrite; + break; + default: + throw new ArgumentException(SR.ConnectionServiceConnStringInvalidIntent(connectionDetails.ApplicationIntent)); + } + connectionBuilder.ApplicationIntent = intent; + } + if (!string.IsNullOrEmpty(connectionDetails.CurrentLanguage)) + { + connectionBuilder.CurrentLanguage = connectionDetails.CurrentLanguage; + } + if (connectionDetails.Pooling.HasValue) + { + connectionBuilder.Pooling = connectionDetails.Pooling.Value; + } + if (connectionDetails.MaxPoolSize.HasValue) + { + connectionBuilder.MaxPoolSize = connectionDetails.MaxPoolSize.Value; + } + if (connectionDetails.MinPoolSize.HasValue) + { + connectionBuilder.MinPoolSize = connectionDetails.MinPoolSize.Value; + } + if (connectionDetails.LoadBalanceTimeout.HasValue) + { + connectionBuilder.LoadBalanceTimeout = connectionDetails.LoadBalanceTimeout.Value; + } + if (connectionDetails.Replication.HasValue) + { + connectionBuilder.Replication = connectionDetails.Replication.Value; + } + if (!string.IsNullOrEmpty(connectionDetails.AttachDbFilename)) + { + connectionBuilder.AttachDBFilename = connectionDetails.AttachDbFilename; + } + if (!string.IsNullOrEmpty(connectionDetails.FailoverPartner)) + { + connectionBuilder.FailoverPartner = connectionDetails.FailoverPartner; + } + if (connectionDetails.MultiSubnetFailover.HasValue) + { + connectionBuilder.MultiSubnetFailover = connectionDetails.MultiSubnetFailover.Value; + } + if (connectionDetails.MultipleActiveResultSets.HasValue) + { + connectionBuilder.MultipleActiveResultSets = connectionDetails.MultipleActiveResultSets.Value; + } + if (connectionDetails.PacketSize.HasValue) + { + connectionBuilder.PacketSize = connectionDetails.PacketSize.Value; + } + if (!string.IsNullOrEmpty(connectionDetails.TypeSystemVersion)) + { + connectionBuilder.TypeSystemVersion = connectionDetails.TypeSystemVersion; + } + connectionBuilder.Pooling = false; + + return connectionBuilder; + } + + /// + /// Change the database context of a connection. + /// + /// URI of the owner of the connection + /// Name of the database to change the connection to + public bool ChangeConnectionDatabaseContext(string ownerUri, string newDatabaseName, bool force = false) + { + ConnectionInfo info; + if (TryFindConnection(ownerUri, out info)) + { + try + { + info.ConnectionDetails.DatabaseName = newDatabaseName; + + foreach (string key in info.AllConnectionTypes) + { + DbConnection conn; + info.TryGetConnection(key, out conn); + if (conn != null && conn.Database != newDatabaseName && conn.State == ConnectionState.Open) + { + if (info.IsCloud && force) + { + conn.Close(); + conn.Dispose(); + info.RemoveConnection(key); + + string connectionString = BuildConnectionString(info.ConnectionDetails); + + // create a sql connection instance + DbConnection connection = info.Factory.CreateSqlConnection(connectionString); + connection.Open(); + info.AddConnection(key, connection); + } + else + { + conn.ChangeDatabase(newDatabaseName); + } + } + + } + + // Fire a connection changed event + ConnectionChangedParams parameters = new ConnectionChangedParams(); + IConnectionSummary summary = info.ConnectionDetails; + parameters.Connection = summary.Clone(); + parameters.OwnerUri = ownerUri; + SendUsingServiceHost((host) => host.SendEvent(ConnectionChangedNotification.Type, parameters)); + return true; + } + catch (Exception e) + { + Logger.Instance.Write( + LogLevel.Error, + string.Format( + "Exception caught while trying to change database context to [{0}] for OwnerUri [{1}]. Exception:{2}", + newDatabaseName, + ownerUri, + e.ToString()) + ); + } + } + return false; + } + + /// + /// Invokes an action on the service host, if the host exists + /// + private void SendUsingServiceHost(Action send) + { + var serviceHost = serviceProvider.GetService(); + if (serviceHost != null) + { + send(serviceHost); + } + } + + /// + /// Invokes the initial on-connect activities if the provided ConnectParams represents the default + /// connection. + /// + private void InvokeOnConnectionActivities(ConnectionInfo connectionInfo, ConnectParams connectParams) + { + if (connectParams.Type != ConnectionType.Default && connectParams.Type != ConnectionType.GeneralConnection) + { + return; + } + + foreach (var activity in this.onConnectionActivities) + { + // not awaiting here to allow handlers to run in the background + activity(connectionInfo); + } + } + + /// + /// Invokes the final on-disconnect activities if the provided DisconnectParams represents the default + /// connection or is null - representing that all connections are being disconnected. + /// + private void InvokeOnDisconnectionActivities(ConnectionInfo connectionInfo) + { + foreach (var activity in this.onDisconnectActivities) + { + activity(connectionInfo.ConnectionDetails, connectionInfo.OwnerUri); + } + } + + /// + /// Handles the Telemetry events that occur upon disconnect. + /// + /// + private void HandleDisconnectTelemetry(ConnectionInfo connectionInfo) + { + SendUsingServiceHost(host => { + try + { + // Send a telemetry notification for intellisense performance metrics + host.SendEvent(TelemetryNotification.Type, new TelemetryParams() + { + Params = new TelemetryProperties + { + Properties = new Dictionary + { + { TelemetryPropertyNames.IsAzure, connectionInfo.IsCloud.ToOneOrZeroString() } + }, + EventName = TelemetryEventNames.IntellisenseQuantile, + Measures = connectionInfo.IntellisenseMetrics.Quantile + } + }); + } + catch (Exception ex) + { + Logger.Instance.Write(LogLevel.Verbose, "Could not send Connection telemetry event " + ex.ToString()); + } + + }); + } + + /// + /// Create and open a new SqlConnection from a ConnectionInfo object + /// Note: we need to audit all uses of this method to determine why we're + /// bypassing normal ConnectionService connection management + /// + internal static SqlConnection OpenSqlConnection(ConnectionInfo connInfo, string featureName = null) + { + try + { + // capture original values + int? originalTimeout = connInfo.ConnectionDetails.ConnectTimeout; + bool? originalPersistSecurityInfo = connInfo.ConnectionDetails.PersistSecurityInfo; + bool? originalPooling = connInfo.ConnectionDetails.Pooling; + + // increase the connection timeout to at least 30 seconds and and build connection string + connInfo.ConnectionDetails.ConnectTimeout = Math.Max(30, originalTimeout ?? 0); + // enable PersistSecurityInfo to handle issues in SMO where the connection context is lost in reconnections + connInfo.ConnectionDetails.PersistSecurityInfo = true; + // turn off connection pool to avoid hold locks on server resources after calling SqlConnection Close method + connInfo.ConnectionDetails.Pooling = false; + connInfo.ConnectionDetails.ApplicationName = GetApplicationNameWithFeature(connInfo.ConnectionDetails.ApplicationName, featureName); + + // generate connection string + string connectionString = ConnectionServiceCore.BuildConnectionString(connInfo.ConnectionDetails); + + // restore original values + connInfo.ConnectionDetails.ConnectTimeout = originalTimeout; + connInfo.ConnectionDetails.PersistSecurityInfo = originalPersistSecurityInfo; + connInfo.ConnectionDetails.Pooling = originalPooling; + + // open a dedicated binding server connection + SqlConnection sqlConn = new SqlConnection(connectionString); + sqlConn.Open(); + return sqlConn; + } + catch (Exception ex) + { + string error = string.Format(CultureInfo.InvariantCulture, + "Failed opening a SqlConnection: error:{0} inner:{1} stacktrace:{2}", + ex.Message, ex.InnerException != null ? ex.InnerException.Message : string.Empty, ex.StackTrace); + Logger.Instance.Write(LogLevel.Error, error); + } + + return null; + } + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/ConnectionUtils.cs b/src/Microsoft.SqlTools.CoreServices/Connection/ConnectionUtils.cs new file mode 100644 index 00000000..835243e3 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Connection/ConnectionUtils.cs @@ -0,0 +1,31 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + + +using System.Data.Common; +using System.Data.SqlClient; +using Microsoft.SqlTools.CoreServices.Connection.ReliableConnection; + +public static class ConnectionUtils +{ + public static SqlConnection GetAsSqlConnection(DbConnection connection) + { + SqlConnection sqlConn = connection as SqlConnection; + if (sqlConn == null) + { + // It's not actually a SqlConnection, so let's try a reliable SQL connection + ReliableSqlConnection reliableConn = connection as ReliableSqlConnection; + if (reliableConn == null) + { + // If we don't have connection we can use with SMO, just give up on using SMO + return null; + } + + // We have a reliable connection, use the underlying connection + sqlConn = reliableConn.GetUnderlyingConnection(); + } + return sqlConn; + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/DatabaseFullAccessException.cs b/src/Microsoft.SqlTools.CoreServices/Connection/DatabaseFullAccessException.cs new file mode 100644 index 00000000..0286e024 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Connection/DatabaseFullAccessException.cs @@ -0,0 +1,28 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System; + +namespace Microsoft.SqlTools.CoreServices.Connection +{ + public class DatabaseFullAccessException: Exception + { + public DatabaseFullAccessException() + : base() + { + } + + public DatabaseFullAccessException(string message, Exception exception) + : base(message, exception) + { + } + + + public DatabaseFullAccessException(string message) + : base(message) + { + } + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/DatabaseLocksManager.cs b/src/Microsoft.SqlTools.CoreServices/Connection/DatabaseLocksManager.cs new file mode 100644 index 00000000..872a2949 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Connection/DatabaseLocksManager.cs @@ -0,0 +1,114 @@ +// +// 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.CoreServices.LanguageServices; +using System; +using System.Collections.Generic; +using System.Threading; + +namespace Microsoft.SqlTools.CoreServices.Connection +{ + public class DatabaseLocksManager: IDisposable + { + internal DatabaseLocksManager(int waitToGetFullAccess) + { + this.waitToGetFullAccess = waitToGetFullAccess; + } + + private static DatabaseLocksManager instance = new DatabaseLocksManager(DefaultWaitToGetFullAccess); + + public static DatabaseLocksManager Instance + { + get + { + return instance; + } + } + + public ConnectionServiceCore ConnectionService { get; set; } + + private Dictionary databaseAccessEvents = new Dictionary(); + private object databaseAccessLock = new object(); + public const int DefaultWaitToGetFullAccess = 10000; + public int waitToGetFullAccess = DefaultWaitToGetFullAccess; + + private ManualResetEvent GetResetEvent(string serverName, string databaseName) + { + string key = GenerateKey(serverName, databaseName); + ManualResetEvent resetEvent = null; + lock (databaseAccessLock) + { + if (!databaseAccessEvents.TryGetValue(key, out resetEvent)) + { + resetEvent = new ManualResetEvent(true); + databaseAccessEvents.Add(key, resetEvent); + } + } + + return resetEvent; + } + + public bool GainFullAccessToDatabase(string serverName, string databaseName) + { + /* + * TODO: add the lock so not two process can get full access at the same time + ManualResetEvent resetEvent = GetResetEvent(serverName, databaseName); + if (resetEvent.WaitOne(this.waitToGetFullAccess)) + { + resetEvent.Reset(); + + foreach (IConnectedBindingQueue item in ConnectionService.ConnectedQueues) + { + item.CloseConnections(serverName, databaseName); + } + return true; + } + else + { + throw new DatabaseFullAccessException($"Waited more than {waitToGetFullAccess} milli seconds for others to release the lock"); + } + */ + foreach (IConnectedBindingQueue item in ConnectionService.ConnectedQueues) + { + item.CloseConnections(serverName, databaseName, DefaultWaitToGetFullAccess); + } + return true; + + } + + public bool ReleaseAccess(string serverName, string databaseName) + { + /* + ManualResetEvent resetEvent = GetResetEvent(serverName, databaseName); + + foreach (IConnectedBindingQueue item in ConnectionService.ConnectedQueues) + { + item.OpenConnections(serverName, databaseName); + } + + resetEvent.Set(); + */ + foreach (IConnectedBindingQueue item in ConnectionService.ConnectedQueues) + { + item.OpenConnections(serverName, databaseName, DefaultWaitToGetFullAccess); + } + return true; + + } + + private string GenerateKey(string serverName, string databaseName) + { + return $"{serverName.ToLowerInvariant()}-{databaseName.ToLowerInvariant()}"; + } + + public void Dispose() + { + foreach (var resetEvent in databaseAccessEvents) + { + resetEvent.Value.Dispose(); + } + } + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/FeatureWithFullDbAccess.cs b/src/Microsoft.SqlTools.CoreServices/Connection/FeatureWithFullDbAccess.cs new file mode 100644 index 00000000..155386e1 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Connection/FeatureWithFullDbAccess.cs @@ -0,0 +1,40 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.CoreServices.Connection +{ + /// + /// Any operation that needs full access to databas should implement this interface. + /// Make sure to call GainAccessToDatabase before the operation and ReleaseAccessToDatabase after + /// + public interface IFeatureWithFullDbAccess + { + /// + /// Database Lock Manager + /// + DatabaseLocksManager LockedDatabaseManager { get; set; } + + /// + /// Makes sure the feature has fill access to the database + /// + bool GainAccessToDatabase(); + + /// + /// Release the access to db + /// + bool ReleaseAccessToDatabase(); + + /// + /// Server name + /// + string ServerName { get; } + + /// + /// Database name + /// + string DatabaseName { get; } + } + +} diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/ISqlConnectionFactory.cs b/src/Microsoft.SqlTools.CoreServices/Connection/ISqlConnectionFactory.cs new file mode 100644 index 00000000..36af7375 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Connection/ISqlConnectionFactory.cs @@ -0,0 +1,20 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System.Data.Common; + +namespace Microsoft.SqlTools.CoreServices.Connection +{ + /// + /// Interface for the SQL Connection factory + /// + public interface ISqlConnectionFactory + { + /// + /// Create a new SQL Connection object + /// + DbConnection CreateSqlConnection(string connectionString); + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/AmbientSettings.cs b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/AmbientSettings.cs new file mode 100644 index 00000000..230d09c1 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/AmbientSettings.cs @@ -0,0 +1,452 @@ +// +// 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.Reflection; +using Microsoft.SqlTools.Hosting.Utility; + +namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection +{ + /// + /// This class represents connection (and other) settings specified by called of the DacFx API. DacFx + /// cannot rely on the registry to supply override values therefore setting overrides must be made + /// by the top-of-the-stack + /// + internal sealed class AmbientSettings + { + private const string LogicalContextName = "__LocalContextConfigurationName"; + + internal enum StreamBackingStore + { + // MemoryStream + Memory = 0, + + // FileStream + File = 1 + } + + // Internal for test purposes + internal const string MasterReferenceFilePathIndex = "MasterReferenceFilePath"; + internal const string DatabaseLockTimeoutIndex = "DatabaseLockTimeout"; + internal const string QueryTimeoutIndex = "QueryTimeout"; + internal const string LongRunningQueryTimeoutIndex = "LongRunningQueryTimeout"; + internal const string AlwaysRetryOnTransientFailureIndex = "AlwaysRetryOnTransientFailure"; + internal const string MaxDataReaderDegreeOfParallelismIndex = "MaxDataReaderDegreeOfParallelism"; + internal const string ConnectionRetryHandlerIndex = "ConnectionRetryHandler"; + internal const string TraceRowCountFailureIndex = "TraceRowCountFailure"; + internal const string TableProgressUpdateIntervalIndex = "TableProgressUpdateInterval"; + internal const string UseOfflineDataReaderIndex = "UseOfflineDataReader"; + internal const string StreamBackingStoreForOfflineDataReadingIndex = "StreamBackingStoreForOfflineDataReading"; + internal const string DisableIndexesForDataPhaseIndex = "DisableIndexesForDataPhase"; + internal const string ReliableDdlEnabledIndex = "ReliableDdlEnabled"; + internal const string ImportModelDatabaseIndex = "ImportModelDatabase"; + internal const string SupportAlwaysEncryptedIndex = "SupportAlwaysEncrypted"; + internal const string SkipObjectTypeBlockingIndex = "SkipObjectTypeBlocking"; + internal const string DoNotSerializeQueryStoreSettingsIndex = "DoNotSerializeQueryStoreSettings"; + internal const string AlwaysEncryptedWizardMigrationIndex = "AlwaysEncryptedWizardMigration"; + + internal static AmbientData _defaultSettings; + + static AmbientSettings() + { + _defaultSettings = new AmbientData(); + } + + /// + /// Access to the default ambient settings. Access to these settings is made available + /// for SSDT scenarios where settings are read from the registry and not set explicitly through + /// the API + /// + public static AmbientData DefaultSettings + { + get { return _defaultSettings; } + } + + public static string MasterReferenceFilePath + { + get { return GetValue(MasterReferenceFilePathIndex); } + } + + public static int LockTimeoutMilliSeconds + { + get { return GetValue(DatabaseLockTimeoutIndex); } + } + + public static int QueryTimeoutSeconds + { + get { return GetValue(QueryTimeoutIndex); } + } + + public static int LongRunningQueryTimeoutSeconds + { + get { return GetValue(LongRunningQueryTimeoutIndex); } + } + + public static Action ConnectionRetryMessageHandler + { + get { return GetValue>(ConnectionRetryHandlerIndex); } + } + + public static bool AlwaysRetryOnTransientFailure + { + get { return GetValue(AlwaysRetryOnTransientFailureIndex); } + } + + public static int MaxDataReaderDegreeOfParallelism + { + get { return GetValue(MaxDataReaderDegreeOfParallelismIndex); } + } + + public static int TableProgressUpdateInterval + { + // value of zero means do not fire 'heartbeat' progress events. Non-zero values will + // fire a heartbeat progress event every n seconds. + get { return GetValue(TableProgressUpdateIntervalIndex); } + } + + public static bool TraceRowCountFailure + { + get { return GetValue(TraceRowCountFailureIndex); } + } + + public static bool UseOfflineDataReader + { + get { return GetValue(UseOfflineDataReaderIndex); } + } + + public static StreamBackingStore StreamBackingStoreForOfflineDataReading + { + get { return GetValue(StreamBackingStoreForOfflineDataReadingIndex); } + } + + public static bool DisableIndexesForDataPhase + { + get { return GetValue(DisableIndexesForDataPhaseIndex); } + } + + public static bool ReliableDdlEnabled + { + get { return GetValue(ReliableDdlEnabledIndex); } + } + + public static bool ImportModelDatabase + { + get { return GetValue(ImportModelDatabaseIndex); } + } + + /// + /// Setting that shows whether Always Encrypted is supported. + /// If false, then reverse engineering and script interpretation of a database with any Always Encrypted object will fail + /// + public static bool SupportAlwaysEncrypted + { + get { return GetValue(SupportAlwaysEncryptedIndex); } + } + + public static bool AlwaysEncryptedWizardMigration + { + get { return GetValue(AlwaysEncryptedWizardMigrationIndex); } + } + + /// + /// Setting that determines whether checks for unsupported object types are performed. + /// If false, unsupported object types will prevent extract from being performed. + /// Default value is false. + /// + public static bool SkipObjectTypeBlocking + { + get { return GetValue(SkipObjectTypeBlockingIndex); } + } + + /// + /// Setting that determines whether the Database Options that store Query Store settings will be left out during package serialization. + /// Default value is false. + /// + public static bool DoNotSerializeQueryStoreSettings + { + get { return GetValue(DoNotSerializeQueryStoreSettingsIndex); } + } + + /// + /// Called by top-of-stack API to setup/configure settings that should be used + /// throughout the API (lower in the stack). The settings are reverted once the returned context + /// has been disposed. + /// + public static IStackSettingsContext CreateSettingsContext() + { + return new StackConfiguration(); + } + + private static T1 GetValue(string configIndex) + { + IAmbientDataDirectAccess config = _defaultSettings; + + return (T1)config.Data[configIndex].Value; + } + + /// + /// Data-transfer object that represents a specific configuration + /// + public class AmbientData : IAmbientDataDirectAccess + { + private readonly Dictionary _configuration; + + public AmbientData() + { + _configuration = new Dictionary(StringComparer.OrdinalIgnoreCase); + _configuration[DatabaseLockTimeoutIndex] = new AmbientValue(5000); + _configuration[QueryTimeoutIndex] = new AmbientValue(60); + _configuration[LongRunningQueryTimeoutIndex] = new AmbientValue(0); + _configuration[AlwaysRetryOnTransientFailureIndex] = new AmbientValue(false); + _configuration[ConnectionRetryHandlerIndex] = new AmbientValue(typeof(Action), null); + _configuration[MaxDataReaderDegreeOfParallelismIndex] = new AmbientValue(8); + _configuration[TraceRowCountFailureIndex] = new AmbientValue(false); // default: throw DacException on rowcount mismatch during import/export data validation + _configuration[TableProgressUpdateIntervalIndex] = new AmbientValue(300); // default: fire heartbeat progress update events every 5 minutes + _configuration[UseOfflineDataReaderIndex] = new AmbientValue(false); + _configuration[StreamBackingStoreForOfflineDataReadingIndex] = new AmbientValue(StreamBackingStore.File); //applicable only when UseOfflineDataReader is set to true + _configuration[MasterReferenceFilePathIndex] = new AmbientValue(typeof(string), null); + // Defect 1210884: Enable an option to allow secondary index, check and fk constraints to stay enabled during data upload with import in DACFX for IES + _configuration[DisableIndexesForDataPhaseIndex] = new AmbientValue(true); + _configuration[ReliableDdlEnabledIndex] = new AmbientValue(false); + _configuration[ImportModelDatabaseIndex] = new AmbientValue(true); + _configuration[SupportAlwaysEncryptedIndex] = new AmbientValue(false); + _configuration[AlwaysEncryptedWizardMigrationIndex] = new AmbientValue(false); + _configuration[SkipObjectTypeBlockingIndex] = new AmbientValue(false); + _configuration[DoNotSerializeQueryStoreSettingsIndex] = new AmbientValue(false); + } + + public string MasterReferenceFilePath + { + get { return (string)_configuration[MasterReferenceFilePathIndex].Value; } + set { _configuration[MasterReferenceFilePathIndex].Value = value; } + } + + public int LockTimeoutMilliSeconds + { + get { return (int)_configuration[DatabaseLockTimeoutIndex].Value; } + set { _configuration[DatabaseLockTimeoutIndex].Value = value; } + } + public int QueryTimeoutSeconds + { + get { return (int)_configuration[QueryTimeoutIndex].Value; } + set { _configuration[QueryTimeoutIndex].Value = value; } + } + public int LongRunningQueryTimeoutSeconds + { + get { return (int)_configuration[LongRunningQueryTimeoutIndex].Value; } + set { _configuration[LongRunningQueryTimeoutIndex].Value = value; } + } + public bool AlwaysRetryOnTransientFailure + { + get { return (bool)_configuration[AlwaysRetryOnTransientFailureIndex].Value; } + set { _configuration[AlwaysRetryOnTransientFailureIndex].Value = value; } + } + public Action ConnectionRetryMessageHandler + { + get { return (Action)_configuration[ConnectionRetryHandlerIndex].Value; } + set { _configuration[ConnectionRetryHandlerIndex].Value = value; } + } + public bool TraceRowCountFailure + { + get { return (bool)_configuration[TraceRowCountFailureIndex].Value; } + set { _configuration[TraceRowCountFailureIndex].Value = value; } + } + public int TableProgressUpdateInterval + { + get { return (int)_configuration[TableProgressUpdateIntervalIndex].Value; } + set { _configuration[TableProgressUpdateIntervalIndex].Value = value; } + } + + public bool UseOfflineDataReader + { + get { return (bool)_configuration[UseOfflineDataReaderIndex].Value; } + set { _configuration[UseOfflineDataReaderIndex].Value = value; } + } + + public StreamBackingStore StreamBackingStoreForOfflineDataReading + { + get { return (StreamBackingStore)_configuration[StreamBackingStoreForOfflineDataReadingIndex].Value; } + set { _configuration[StreamBackingStoreForOfflineDataReadingIndex].Value = value; } + } + + public bool DisableIndexesForDataPhase + { + get { return (bool)_configuration[DisableIndexesForDataPhaseIndex].Value; } + set { _configuration[DisableIndexesForDataPhaseIndex].Value = value; } + } + + public bool ReliableDdlEnabled + { + get { return (bool)_configuration[ReliableDdlEnabledIndex].Value; } + set { _configuration[ReliableDdlEnabledIndex].Value = value; } + } + + public bool ImportModelDatabase + { + get { return (bool)_configuration[ImportModelDatabaseIndex].Value; } + set { _configuration[ImportModelDatabaseIndex].Value = value; } + } + + internal bool SupportAlwaysEncrypted + { + get { return (bool)_configuration[SupportAlwaysEncryptedIndex].Value; } + set { _configuration[SupportAlwaysEncryptedIndex].Value = value; } + } + + internal bool AlwaysEncryptedWizardMigration + { + get { return (bool)_configuration[AlwaysEncryptedWizardMigrationIndex].Value; } + set { _configuration[AlwaysEncryptedWizardMigrationIndex].Value = value; } + } + + internal bool SkipObjectTypeBlocking + { + get { return (bool)_configuration[SkipObjectTypeBlockingIndex].Value; } + set { _configuration[SkipObjectTypeBlockingIndex].Value = value; } + } + + internal bool DoNotSerializeQueryStoreSettings + { + get { return (bool)_configuration[DoNotSerializeQueryStoreSettingsIndex].Value; } + set { _configuration[DoNotSerializeQueryStoreSettingsIndex].Value = value; } + } + + /// + /// Provides a way to bulk populate settings from a dictionary + /// + public void PopulateSettings(IDictionary settingsCollection) + { + if (settingsCollection != null) + { + Dictionary newSettings = new Dictionary(); + + // We know all the values are set on the current configuration + foreach (KeyValuePair potentialPair in settingsCollection) + { + AmbientValue currentValue; + if (_configuration.TryGetValue(potentialPair.Key, out currentValue)) + { + object newValue = potentialPair.Value; + newSettings[potentialPair.Key] = newValue; + } + } + + if (newSettings.Count > 0) + { + foreach (KeyValuePair newSetting in newSettings) + { + _configuration[newSetting.Key].Value = newSetting.Value; + } + } + } + } + + /// + /// Logs the Ambient Settings + /// + public void TraceSettings() + { + // NOTE: logging as warning so we can get this data in the IEService DacFx logs + Logger.Instance.Write(LogLevel.Warning, Resources.LoggingAmbientSettings); + + foreach (KeyValuePair setting in _configuration) + { + // Log Ambient Settings + Logger.Instance.Write( + LogLevel.Warning, + string.Format( + Resources.AmbientSettingFormat, + setting.Key, + setting.Value == null ? setting.Value : setting.Value.Value)); + } + } + + Dictionary IAmbientDataDirectAccess.Data + { + get { return _configuration; } + } + } + + /// + /// This class is used as value in the dictionary to ensure that the type of value is correct. + /// + private class AmbientValue + { + private readonly Type _type; + private readonly bool _isTypeNullable; + private object _value; + + public AmbientValue(object value) + : this(value == null ? null : value.GetType(), value) + { + } + + public AmbientValue(Type type, object value) + { + if (type == null) + { + throw new ArgumentNullException("type"); + } + _type = type; + _isTypeNullable = !type.GetTypeInfo().IsValueType || Nullable.GetUnderlyingType(type) != null; + Value = value; + } + + public object Value + { + get { return _value; } + set + { + if ((_isTypeNullable && value == null) || _type.GetTypeInfo().IsInstanceOfType(value)) + { + _value = value; + } + else + { + Logger.Instance.Write(LogLevel.Error, string.Format(Resources.UnableToAssignValue, value.GetType().FullName, _type.FullName)); + } + } + } + } + + /// + /// This private interface allows pass-through access directly to member data + /// + private interface IAmbientDataDirectAccess + { + Dictionary Data { get; } + } + + /// + /// This class encapsulated the concept of configuration that is set on the stack and + /// flows across multiple threads as part of the logical call context + /// + private sealed class StackConfiguration : IStackSettingsContext + { + private readonly AmbientData _data; + + public StackConfiguration() + { + _data = new AmbientData(); + //CallContext.LogicalSetData(LogicalContextName, _data); + } + + public AmbientData Settings + { + get { return _data; } + } + + public void Dispose() + { + Dispose(true); + } + private void Dispose(bool disposing) + { + //CallContext.LogicalSetData(LogicalContextName, null); + } + } + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/CachedServerInfo.cs b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/CachedServerInfo.cs new file mode 100644 index 00000000..384326fe --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/CachedServerInfo.cs @@ -0,0 +1,284 @@ +// +// 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.Concurrent; +using System.Data; +using System.Data.SqlClient; +using System.Linq; +using Microsoft.SqlTools.Hosting.Utility; + +namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection +{ + + /// + /// This class caches server information for subsequent use + /// + internal class CachedServerInfo + { + /// + /// Singleton service instance + /// + private static readonly Lazy instance + = new Lazy(() => new CachedServerInfo()); + + /// + /// Gets the singleton instance + /// + public static CachedServerInfo Instance + { + get + { + return instance.Value; + } + } + + public enum CacheVariable { + IsSqlDw, + IsAzure, + IsCloud + } + + #region CacheKey implementation + internal class CacheKey : IEquatable + { + private string dataSource; + private string dbName; + + public CacheKey(SqlConnectionStringBuilder builder) + { + Validate.IsNotNull(nameof(builder), builder); + dataSource = builder.DataSource; + dbName = GetDatabaseName(builder); + } + + internal static string GetDatabaseName(SqlConnectionStringBuilder builder) + { + string dbName = string.Empty; + if (!string.IsNullOrEmpty((builder.InitialCatalog))) + { + dbName = builder.InitialCatalog; + } + else if (!string.IsNullOrEmpty((builder.AttachDBFilename))) + { + dbName = builder.AttachDBFilename; + } + return dbName; + } + + public override bool Equals(object obj) + { + if (obj == null) { return false; } + + CacheKey keyObj = obj as CacheKey; + if (keyObj == null) { return false; } + else { return Equals(keyObj); } + } + + public override int GetHashCode() + { + unchecked // Overflow is fine, just wrap + { + int hash = 17; + hash = (hash * 23) + (dataSource != null ? dataSource.GetHashCode() : 0); + hash = (hash * 23) + (dbName != null ? dbName.GetHashCode() : 0); + return hash; + } + } + + public bool Equals(CacheKey other) + { + return string.Equals(dataSource, other.dataSource, StringComparison.OrdinalIgnoreCase) + && string.Equals(dbName, other.dbName, StringComparison.OrdinalIgnoreCase); + } + } + #endregion + + private struct CachedInfo + { + public bool IsAzure; + public DateTime LastUpdate; + public bool IsSqlDw; + } + + private const int _maxCacheSize = 1024; + private const int _deleteBatchSize = 512; + private const int MinimalQueryTimeoutSecondsForAzure = 300; + + private ConcurrentDictionary _cache; + private object _cacheLock; + + /// + /// Internal constructor for testing purposes. For all code use, please use the + /// default instance. + /// + internal CachedServerInfo() + { + _cache = new ConcurrentDictionary(); + _cacheLock = new object(); + } + + public int GetQueryTimeoutSeconds(IDbConnection connection) + { + SqlConnectionStringBuilder connStringBuilder = SafeGetConnectionStringFromConnection(connection); + return GetQueryTimeoutSeconds(connStringBuilder); + } + + public int GetQueryTimeoutSeconds(SqlConnectionStringBuilder builder) + { + //keep existing behavior and return the default ambient settings + //if the provided data source is null or whitespace, or the original + //setting is already 0 which means no limit. + int originalValue = AmbientSettings.QueryTimeoutSeconds; + if (builder == null || string.IsNullOrWhiteSpace(builder.DataSource) + || (originalValue == 0)) + { + return originalValue; + } + + CachedInfo info; + bool hasFound = TryGetCacheValue(builder, out info); + + if (hasFound && info.IsAzure + && originalValue < MinimalQueryTimeoutSecondsForAzure) + { + return MinimalQueryTimeoutSecondsForAzure; + } + else + { + return originalValue; + } + } + + public void AddOrUpdateIsCloud(IDbConnection connection, bool isCloud) + { + AddOrUpdateCache(connection, isCloud, CacheVariable.IsCloud); + } + + public void AddOrUpdateIsAzure(IDbConnection connection, bool isAzure) + { + AddOrUpdateCache(connection, isAzure, CacheVariable.IsAzure); + } + + public void AddOrUpdateIsSqlDw(IDbConnection connection, bool isSqlDw) + { + AddOrUpdateCache(connection, isSqlDw, CacheVariable.IsSqlDw); + } + + private void AddOrUpdateCache(IDbConnection connection, bool newState, CacheVariable cacheVar) + { + Validate.IsNotNull(nameof(connection), connection); + SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(connection.ConnectionString); + AddOrUpdateCache(builder, newState, cacheVar); + } + + internal void AddOrUpdateCache(SqlConnectionStringBuilder builder, bool newState, CacheVariable cacheVar) + { + Validate.IsNotNull(nameof(builder), builder); + Validate.IsNotNullOrWhitespaceString(nameof(builder) + ".DataSource", builder.DataSource); + CachedInfo info; + bool hasFound = TryGetCacheValue(builder, out info); + + if ((cacheVar == CacheVariable.IsSqlDw && hasFound && info.IsSqlDw == newState) || + (cacheVar == CacheVariable.IsAzure && hasFound && info.IsAzure == newState)) + { + // No change needed + return; + } + else + { + lock (_cacheLock) + { + // Clean older keys, update info, and add this back into the cache + CacheKey key = new CacheKey(builder); + CleanupCache(key); + + if (cacheVar == CacheVariable.IsSqlDw) + { + info.IsSqlDw = newState; + } + else if (cacheVar == CacheVariable.IsAzure) + { + info.IsAzure = newState; + } + info.LastUpdate = DateTime.UtcNow; + _cache.AddOrUpdate(key, info, (k, oldValue) => info); + } + } + } + + private void CleanupCache(CacheKey newKey) + { + if (!_cache.ContainsKey(newKey)) + { + //delete a batch of old elements when we try to add a new one and + //the capacity limitation is hit + if (_cache.Keys.Count > _maxCacheSize - 1) + { + var keysToDelete = _cache + .OrderBy(x => x.Value.LastUpdate) + .Take(_deleteBatchSize) + .Select(pair => pair.Key); + + foreach (CacheKey key in keysToDelete) + { + CachedInfo info; + _cache.TryRemove(key, out info); + } + } + } + } + + public bool TryGetIsSqlDw(IDbConnection connection, out bool isSqlDw) + { + Validate.IsNotNull(nameof(connection), connection); + + SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(connection.ConnectionString); + return TryGetIsSqlDw(builder, out isSqlDw); + } + + public bool TryGetIsSqlDw(SqlConnectionStringBuilder builder, out bool isSqlDw) + { + Validate.IsNotNull(nameof(builder), builder); + Validate.IsNotNullOrWhitespaceString(nameof(builder) + ".DataSource", builder.DataSource); + CachedInfo info; + bool hasFound = TryGetCacheValue(builder, out info); + + if(hasFound) + { + isSqlDw = info.IsSqlDw; + return true; + } + + isSqlDw = false; + return false; + } + + private static SqlConnectionStringBuilder SafeGetConnectionStringFromConnection(IDbConnection connection) + { + if (connection == null) + { + return null; + } + + try + { + SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(connection.ConnectionString); + return builder; + } + catch + { + Logger.Instance.Write(LogLevel.Error, String.Format(Resources.FailedToParseConnectionString, connection.ConnectionString)); + return null; + } + } + + private bool TryGetCacheValue(SqlConnectionStringBuilder builder, out CachedInfo value) + { + CacheKey key = new CacheKey(builder); + return _cache.TryGetValue(key, out value); + } + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/Constants.cs b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/Constants.cs new file mode 100644 index 00000000..80e65098 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/Constants.cs @@ -0,0 +1,17 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection +{ + /// + /// Contains common constants used throughout ReliableConnection code. + /// + internal static class Constants + { + internal const int UndefinedErrorCode = 0; + + internal const string Local = "(local)"; + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/DataSchemaError.cs b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/DataSchemaError.cs new file mode 100644 index 00000000..51335141 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/DataSchemaError.cs @@ -0,0 +1,214 @@ +// +// 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.CoreServices.Connection.ReliableConnection +{ + /// + /// This class is used to encapsulate all the information needed by the DataSchemaErrorTaskService to create a corresponding entry in the Visual Studio Error List. + /// A component should add this Error Object to the for such purpose. + /// Errors and their children are expected to be thread-safe. Ideally, this means that + /// the objects are just data-transfer-objects initialized during construction. + /// + [Serializable] + internal class DataSchemaError + { + internal const string DefaultPrefix = "SQL"; + private const int MaxErrorCode = 99999; + protected const int UndefinedErrorCode = 0; + + public DataSchemaError() : this(string.Empty, ErrorSeverity.Unknown) + { + } + + public DataSchemaError(string message, ErrorSeverity severity) + : this(message, string.Empty, severity) + { + } + + public DataSchemaError(string message, Exception innerException, ErrorSeverity severity) + : this(message, innerException, string.Empty, 0, severity) + { + } + + public DataSchemaError(string message, string document, ErrorSeverity severity) + : this(message, document, 0, 0, DefaultPrefix, UndefinedErrorCode, severity) + { + } + + public DataSchemaError(string message, string document, int errorCode, ErrorSeverity severity) + : this(message, document, 0, 0, DefaultPrefix, errorCode, severity) + { + } + + public DataSchemaError(string message, string document, int line, int column, ErrorSeverity severity) + : this(message, document,line, column, DefaultPrefix, UndefinedErrorCode, severity) + { + } + + public DataSchemaError(DataSchemaError source, ErrorSeverity severity) + : this(source.Message, source.Document, source.Line, source.Column, source.Prefix, source.ErrorCode, severity) + { + } + + public DataSchemaError( + Exception exception, + string prefix, + int errorCode, + ErrorSeverity severity) + : this(exception, string.Empty, 0, 0, prefix, errorCode, severity) + { + } + + public DataSchemaError( + string message, + Exception exception, + string prefix, + int errorCode, + ErrorSeverity severity) + : this(message, exception, string.Empty, 0, 0, prefix, errorCode, severity) + { + } + + public DataSchemaError( + Exception exception, + string document, + int line, + int column, + string prefix, + int errorCode, + ErrorSeverity severity) + : this(exception.Message, exception, document, line, column, prefix, errorCode, severity) + { + } + + public DataSchemaError( + string message, + string document, + int line, + int column, + string prefix, + int errorCode, + ErrorSeverity severity) + : this(message, null, document, line, column, prefix, errorCode, severity) + { + } + + public DataSchemaError( + string message, + Exception exception, + string document, + int line, + int column, + string prefix, + int errorCode, + ErrorSeverity severity) + { + if (errorCode > MaxErrorCode || errorCode < 0) + { + throw new ArgumentOutOfRangeException("errorCode"); + } + + Document = document; + Severity = severity; + Line = line; + Column = column; + Message = message; + Exception = exception; + + ErrorCode = errorCode; + Prefix = prefix; + IsPriorityEditable = true; + } + + /// + /// The filename of the error. It corresponds to the File column on the Visual Studio Error List window. + /// + public string Document { get; set; } + + /// + /// The severity of the error + /// + public ErrorSeverity Severity { get; private set; } + + public int ErrorCode { get; private set; } + + /// + /// Line Number of the error + /// + public int Line { get; set; } + + /// + /// Column Number of the error + /// + public int Column { get; set; } + + /// + /// Prefix of the error + /// + public string Prefix { get; private set; } + + /// + /// If the error has any special help topic, this property may hold the ID to the same. + /// + public string HelpKeyword { get; set; } + + /// + /// Exception associated with the error, or null + /// + public Exception Exception { get; set; } + + /// + /// Message + /// + public string Message { get; set; } + + /// + /// Should this message honor the "treat warnings as error" flag? + /// + public Boolean IsPriorityEditable { get; set; } + + /// + /// Represents the error code used in MSBuild output. This is the prefix and the + /// error code + /// + /// + public string BuildErrorCode + { + get { return FormatErrorCode(Prefix, ErrorCode); } + } + + internal Boolean IsBuildErrorCodeDefined + { + get { return (ErrorCode != UndefinedErrorCode); } + } + + /// + /// true if this error is being displayed in ErrorList. More of an Accounting Mechanism to be used internally. + /// + internal bool IsOnDisplay { get; set; } + + internal static string FormatErrorCode(string prefix, int code) + { + return string.Format( + CultureInfo.InvariantCulture, + "{0}{1:d5}", + prefix, + code); + } + + /// + /// String form of this error. + /// NB: This is for debugging only. + /// + /// String form of the error. + public override string ToString() + { + return string.Format(CultureInfo.CurrentCulture, "{0} - {1}({2},{3}): {4}", FormatErrorCode(Prefix, ErrorCode), Document, Line, Column, Message); + } + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/DbCommandWrapper.cs b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/DbCommandWrapper.cs new file mode 100644 index 00000000..ef9a2fc2 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/DbCommandWrapper.cs @@ -0,0 +1,71 @@ +// +// 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.Data; +using System.Data.SqlClient; +using Microsoft.SqlTools.Hosting.Utility; + +namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection +{ + + /// + /// Wraps objects that could be a or + /// a , providing common methods across both. + /// + internal sealed class DbCommandWrapper + { + private readonly IDbCommand _command; + private readonly bool _isReliableCommand; + + public DbCommandWrapper(IDbCommand command) + { + Validate.IsNotNull(nameof(command), command); + if (command is ReliableSqlConnection.ReliableSqlCommand) + { + _isReliableCommand = true; + } + else if (!(command is SqlCommand)) + { + throw new InvalidOperationException(Resources.InvalidCommandType); + } + _command = command; + } + + public static bool IsSupportedCommand(IDbCommand command) + { + return command is ReliableSqlConnection.ReliableSqlCommand + || command is SqlCommand; + } + + + public event StatementCompletedEventHandler StatementCompleted + { + add + { + SqlCommand sqlCommand = GetAsSqlCommand(); + sqlCommand.StatementCompleted += value; + } + remove + { + SqlCommand sqlCommand = GetAsSqlCommand(); + sqlCommand.StatementCompleted -= value; + } + } + + /// + /// Gets this as a SqlCommand by casting (if we know it is actually a SqlCommand) + /// or by getting the underlying command (if it's a ReliableSqlCommand) + /// + private SqlCommand GetAsSqlCommand() + { + if (_isReliableCommand) + { + return ((ReliableSqlConnection.ReliableSqlCommand) _command).GetUnderlyingCommand(); + } + return (SqlCommand) _command; + } + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/DbConnectionWrapper.cs b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/DbConnectionWrapper.cs new file mode 100644 index 00000000..19352504 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/DbConnectionWrapper.cs @@ -0,0 +1,113 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System; +using System.Data; +using System.Data.SqlClient; +using Microsoft.SqlTools.Hosting.Utility; + +namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection +{ + /// + /// Wraps objects that could be a or + /// a , providing common methods across both. + /// + internal sealed class DbConnectionWrapper + { + private readonly IDbConnection _connection; + private readonly bool _isReliableConnection; + + public DbConnectionWrapper(IDbConnection connection) + { + Validate.IsNotNull(nameof(connection), connection); + if (connection is ReliableSqlConnection) + { + _isReliableConnection = true; + } + else if (!(connection is SqlConnection)) + { + throw new InvalidOperationException(Resources.InvalidConnectionType); + } + + _connection = connection; + } + + public static bool IsSupportedConnection(IDbConnection connection) + { + return connection is ReliableSqlConnection + || connection is SqlConnection; + } + + public event SqlInfoMessageEventHandler InfoMessage + { + add + { + SqlConnection conn = GetAsSqlConnection(); + conn.InfoMessage += value; + } + remove + { + SqlConnection conn = GetAsSqlConnection(); + conn.InfoMessage -= value; + } + } + + public string DataSource + { + get + { + if (_isReliableConnection) + { + return ((ReliableSqlConnection) _connection).DataSource; + } + return ((SqlConnection)_connection).DataSource; + } + } + + public string ServerVersion + { + get + { + if (_isReliableConnection) + { + return ((ReliableSqlConnection)_connection).ServerVersion; + } + return ((SqlConnection)_connection).ServerVersion; + } + } + + /// + /// Gets this as a SqlConnection by casting (if we know it is actually a SqlConnection) + /// or by getting the underlying connection (if it's a ReliableSqlConnection) + /// + public SqlConnection GetAsSqlConnection() + { + if (_isReliableConnection) + { + return ((ReliableSqlConnection) _connection).GetUnderlyingConnection(); + } + return (SqlConnection) _connection; + } + + /* + TODO - IClonable does not exist in .NET Core. + /// + /// Clones the connection and ensures it's opened. + /// If it's a SqlConnection it will clone it, + /// and for ReliableSqlConnection it will clone the underling connection. + /// The reason the entire ReliableSqlConnection is not cloned is that it includes + /// several callbacks and we don't want to try and handle deciding how to clone these + /// yet. + /// + public SqlConnection CloneAndOpenConnection() + { + SqlConnection conn = GetAsSqlConnection(); + SqlConnection clonedConn = ((ICloneable) conn).Clone() as SqlConnection; + clonedConn.Open(); + return clonedConn; + } + */ + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/ErrorSeverity.cs b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/ErrorSeverity.cs new file mode 100644 index 00000000..ce2c6163 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/ErrorSeverity.cs @@ -0,0 +1,15 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection +{ + internal enum ErrorSeverity + { + Unknown = 0, + Error, + Warning, + Message + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/IStackSettingsContext.cs b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/IStackSettingsContext.cs new file mode 100644 index 00000000..2d0990db --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/IStackSettingsContext.cs @@ -0,0 +1,19 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System; + +namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection +{ + /// + /// This interface controls the lifetime of settings created as part of the + /// top-of-stack API. Changes made to this context's AmbientData instance will + /// flow to lower in the stack while this object is not disposed. + /// + internal interface IStackSettingsContext : IDisposable + { + AmbientSettings.AmbientData Settings { get; } + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/ReliableConnectionHelper.cs b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/ReliableConnectionHelper.cs new file mode 100644 index 00000000..77a3b4ad --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/ReliableConnectionHelper.cs @@ -0,0 +1,1320 @@ +// +// 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.Data; +using System.Data.SqlClient; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; +using System.Security; +using Microsoft.SqlTools.Hosting.Utility; +using Microsoft.SqlServer.Management.Common; + +namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection +{ + internal static class ReliableConnectionHelper + { + private const int PCU1BuildNumber = 2816; + public readonly static SqlConnectionStringBuilder BuilderWithDefaultApplicationName = new SqlConnectionStringBuilder("server=(local);"); + + private const string ServerNameLocalhost = "localhost"; + private const string SqlProviderName = "System.Data.SqlClient"; + + private const string ApplicationIntent = "ApplicationIntent"; + private const string MultiSubnetFailover = "MultiSubnetFailover"; + private const string DacFxApplicationName = "DacFx"; + + private const int SqlDwEngineEditionId = (int)DatabaseEngineEdition.SqlDataWarehouse; + + // See MSDN documentation for "SERVERPROPERTY (SQL Azure Database)" for "EngineEdition" property: + // http://msdn.microsoft.com/en-us/library/ee336261.aspx + private const int SqlAzureEngineEditionId = 5; + + private static Lazy> cloudEditions = new Lazy>(() => new HashSet() + { + (int)DatabaseEngineEdition.SqlDatabase, + (int)DatabaseEngineEdition.SqlDataWarehouse, + (int)DatabaseEngineEdition.SqlStretchDatabase, + // Note: for now, ignoring managed instance as it should be treated just like on prem. + }); + + /// + /// Opens the connection and sets the lock/command timeout and pooling=false. + /// + /// The opened connection + public static IDbConnection OpenConnection(SqlConnectionStringBuilder csb, bool useRetry) + { + csb.Pooling = false; + return OpenConnection(csb.ToString(), useRetry); + } + + /// + /// Opens the connection and sets the lock/command timeout. This routine + /// will assert if pooling!=false. + /// + /// The opened connection + public static IDbConnection OpenConnection(string connectionString, bool useRetry) + { +#if DEBUG + try + { + SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(connectionString); + Debug.Assert(!builder.Pooling, "Pooling should be false"); + } + catch (Exception ex) + { + Debug.Assert(false, "Invalid connectionstring: " + ex.Message); + } +#endif + + if (AmbientSettings.AlwaysRetryOnTransientFailure) + { + useRetry = true; + } + + RetryPolicy commandRetryPolicy, connectionRetryPolicy; + if (useRetry) + { + commandRetryPolicy = RetryPolicyFactory.CreateDefaultSchemaCommandRetryPolicy(useRetry: true); + connectionRetryPolicy = RetryPolicyFactory.CreateDefaultSchemaConnectionRetryPolicy(); + } + else + { + commandRetryPolicy = RetryPolicyFactory.CreateNoRetryPolicy(); + connectionRetryPolicy = RetryPolicyFactory.CreateNoRetryPolicy(); + } + + ReliableSqlConnection connection = new ReliableSqlConnection(connectionString, connectionRetryPolicy, commandRetryPolicy); + + try + { + connection.Open(); + } + catch (Exception ex) + { + + string debugMessage = String.Format(CultureInfo.CurrentCulture, + "Opening connection using connection string '{0}' failed with exception: {1}", connectionString, ex.Message); +#if DEBUG + Debug.WriteLine(debugMessage); +#endif + connection.Dispose(); + throw; + } + + return connection; + } + + /// + /// Opens the connection (if it is not already) and sets + /// the lock/command timeout. + /// + /// The connection to open + public static void OpenConnection(IDbConnection conn) + { + if (conn.State == ConnectionState.Closed) + { + conn.Open(); + } + } + + /// + /// Opens a connection using 'csb' as the connection string. Provide + /// 'usingConnection' to execute T-SQL against the open connection and + /// 'catchException' to handle errors. + /// + /// The connection string used when opening the IDbConnection + /// delegate called when the IDbConnection has been successfully opened + /// delegate called when an exception has occurred. Pass back 'true' to handle the + /// exception, 'false' to throw. If Null is passed in then all exceptions are thrown. + /// Should retry logic be used when opening the connection + public static void OpenConnection( + SqlConnectionStringBuilder csb, + Action usingConnection, + Predicate catchException, + bool useRetry) + { + Validate.IsNotNull(nameof(csb), csb); + Validate.IsNotNull(nameof(usingConnection), usingConnection); + + try + { + // Always disable pooling + csb.Pooling = false; + using (IDbConnection conn = OpenConnection(csb.ConnectionString, useRetry)) + { + usingConnection(conn); + } + } + catch (Exception ex) + { + if (catchException == null || !catchException(ex)) + { + throw; + } + } + } + + /* + TODO - re-enable if we port ConnectionStringSecurer + /// + /// This method provides the provides a connection string configured with the specified database name. + /// This is also an opportunity to decrypt the connection string based on the encryption/decryption strategy. + /// InvalidConnectionStringException could be thrown since this routine attempts to restore the connection + /// string if 'restoreConnectionString' is true. + /// + /// Will only set DatabaseName/ApplicationName if the value is not null. + /// + /// + public static SqlConnectionStringBuilder ConfigureConnectionString( + string connectionString, + string databaseName, + string applicationName, + bool restoreConnectionString = true) + { + if (restoreConnectionString) + { + // Read the connection string through the persistence layer + connectionString = ConnectionStringSecurer.RestoreConnectionString( + connectionString, + SqlProviderName); + } + + SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(connectionString); + + builder.Pooling = false; + builder.MultipleActiveResultSets = false; + + // Cannot set the applicationName/initialCatalog to null but empty string is valid + if (databaseName != null) + { + builder.InitialCatalog = databaseName; + } + + if (applicationName != null) + { + builder.ApplicationName = applicationName; + } + + return builder; + } + */ + + /// + /// Optional 'initializeConnection' routine. This sets the lock and command timeout for the connection. + /// + public static void SetLockAndCommandTimeout(IDbConnection conn) + { + ReliableSqlConnection.SetLockAndCommandTimeout(conn); + } + + /// + /// Opens a IDbConnection, creates a IDbCommand and calls ExecuteNonQuery against the connection. + /// + /// The connection string. + /// The scalar T-SQL command. + /// Optional delegate to initialize the IDbCommand before execution. + /// Default is SqlConnectionHelper.SetCommandTimeout + /// delegate called when an exception has occurred. Pass back 'true' to handle the + /// exception, 'false' to throw. If Null is passed in then all exceptions are thrown. + /// Should a retry policy be used when calling ExecuteNonQuery + /// The number of rows affected + public static object ExecuteNonQuery( + SqlConnectionStringBuilder csb, + string commandText, + Action initializeCommand, + Predicate catchException, + bool useRetry) + { + object retObject = null; + OpenConnection( + csb, + (connection) => + { + retObject = ExecuteNonQuery(connection, commandText, initializeCommand, catchException); + }, + catchException, + useRetry); + + return retObject; + } + + /// + /// Creates a IDbCommand and calls ExecuteNonQuery against the connection. + /// + /// The connection. This must be opened. + /// The scalar T-SQL command. + /// Optional delegate to initialize the IDbCommand before execution. + /// Default is SqlConnectionHelper.SetCommandTimeout + /// Optional exception handling. Pass back 'true' to handle the + /// exception, 'false' to throw. If Null is passed in then all exceptions are thrown. + /// The number of rows affected + [SuppressMessage("Microsoft.Security", "CA2100:Review SQL queries for security vulnerabilities")] + public static object ExecuteNonQuery( + IDbConnection conn, + string commandText, + Action initializeCommand, + Predicate catchException) + { + Validate.IsNotNull(nameof(conn), conn); + Validate.IsNotNullOrEmptyString(nameof(commandText), commandText); + + IDbCommand cmd = null; + try + { + + Debug.Assert(conn.State == ConnectionState.Open, "connection passed to ExecuteNonQuery should be open."); + + cmd = conn.CreateCommand(); + if (initializeCommand == null) + { + initializeCommand = SetCommandTimeout; + } + initializeCommand(cmd); + + cmd.CommandText = commandText; + cmd.CommandType = CommandType.Text; + + return cmd.ExecuteNonQuery(); + } + catch (Exception ex) + { + if (catchException == null || !catchException(ex)) + { + throw; + } + } + finally + { + if (cmd != null) + { + cmd.Dispose(); + } + } + return null; + } + + /// + /// Creates a IDbCommand and calls ExecuteScalar against the connection. + /// + /// The connection. This must be opened. + /// The scalar T-SQL command. + /// Optional delegate to initialize the IDbCommand before execution. + /// Default is SqlConnectionHelper.SetCommandTimeout + /// Optional exception handling. Pass back 'true' to handle the + /// exception, 'false' to throw. If Null is passed in then all exceptions are thrown. + /// The scalar result + [SuppressMessage("Microsoft.Security", "CA2100:Review SQL queries for security vulnerabilities")] + public static object ExecuteScalar( + IDbConnection conn, + string commandText, + Action initializeCommand = null, + Predicate catchException = null) + { + Validate.IsNotNull(nameof(conn), conn); + Validate.IsNotNullOrEmptyString(nameof(commandText), commandText); + + IDbCommand cmd = null; + + try + { + Debug.Assert(conn.State == ConnectionState.Open, "connection passed to ExecuteScalar should be open."); + + cmd = conn.CreateCommand(); + if (initializeCommand == null) + { + initializeCommand = SetCommandTimeout; + } + initializeCommand(cmd); + + cmd.CommandText = commandText; + cmd.CommandType = CommandType.Text; + return cmd.ExecuteScalar(); + } + catch (Exception ex) + { + if (catchException == null || !catchException(ex)) + { + throw; + } + } + finally + { + if (cmd != null) + { + cmd.Dispose(); + } + } + return null; + } + + /// + /// Creates a IDbCommand and calls ExecuteReader against the connection. + /// + /// The connection to execute the reader on. This must be opened. + /// The command text to execute + /// A delegate used to read from the reader + /// Optional delegate to initialize the IDbCommand object + /// Optional exception handling. Pass back 'true' to handle the + /// exception, 'false' to throw. If Null is passed in then all exceptions are thrown. + [SuppressMessage("Microsoft.Security", "CA2100:Review SQL queries for security vulnerabilities")] + public static void ExecuteReader( + IDbConnection conn, + string commandText, + Action readResult, + Action initializeCommand = null, + Predicate catchException = null) + { + Validate.IsNotNull(nameof(conn), conn); + Validate.IsNotNullOrEmptyString(nameof(commandText), commandText); + Validate.IsNotNull(nameof(readResult), readResult); + + IDbCommand cmd = null; + try + { + cmd = conn.CreateCommand(); + + if (initializeCommand == null) + { + initializeCommand = SetCommandTimeout; + } + + initializeCommand(cmd); + + cmd.CommandText = commandText; + cmd.CommandType = CommandType.Text; + using (IDataReader reader = cmd.ExecuteReader()) + { + readResult(reader); + } + } + catch (Exception ex) + { + if (catchException == null || !catchException(ex)) + { + throw; + } + } + finally + { + if (cmd != null) + { + cmd.Dispose(); + } + } + } + + /// + /// optional 'initializeCommand' routine. This initializes the IDbCommand + /// + /// + public static void SetCommandTimeout(IDbCommand cmd) + { + Validate.IsNotNull(nameof(cmd), cmd); + cmd.CommandTimeout = CachedServerInfo.Instance.GetQueryTimeoutSeconds(cmd.Connection); + } + + + /// + /// Return true if the database is an Azure database + /// + /// + /// + public static bool IsCloud(IDbConnection connection) + { + Validate.IsNotNull(nameof(connection), connection); + if (!(connection.State == ConnectionState.Open)) + { + Logger.Instance.Write(LogLevel.Warning, Resources.ConnectionPassedToIsCloudShouldBeOpen); + } + + Func executeCommand = commandText => + { + bool result = false; + ExecuteReader(connection, + commandText, + readResult: (reader) => + { + reader.Read(); + int engineEditionId = int.Parse(reader[0].ToString(), CultureInfo.InvariantCulture); + + result = IsCloudEngineId(engineEditionId); + } + ); + return result; + }; + + bool isSqlCloud = false; + try + { + isSqlCloud = executeCommand(SqlConnectionHelperScripts.EngineEdition); + } + catch (SqlException) + { + // The default query contains a WITH (NOLOCK). This doesn't work for Azure DW, so when things don't work out, + // we'll fall back to a version without NOLOCK and try again. + isSqlCloud = executeCommand(SqlConnectionHelperScripts.EngineEditionWithLock); + } + + return isSqlCloud; + } + + private static bool IsCloudEngineId(int engineEditionId) + { + return cloudEditions.Value.Contains(engineEditionId); + } + + /// + /// Determines if the type of database that a connection is being made to is SQL data warehouse. + /// + /// + /// True if the database is a SQL data warehouse + public static bool IsSqlDwDatabase(IDbConnection connection) + { + Validate.IsNotNull(nameof(connection), connection); + + Func executeCommand = commandText => + { + bool result = false; + ExecuteReader(connection, + commandText, + readResult: (reader) => + { + reader.Read(); + int engineEditionId = int.Parse(reader[0].ToString(), CultureInfo.InvariantCulture); + + result = IsSqlDwEngineId(engineEditionId); + } + ); + return result; + }; + + bool isSqlDw = false; + try + { + isSqlDw = executeCommand(SqlConnectionHelperScripts.EngineEdition); + } + catch (SqlException) + { + // The default query contains a WITH (NOLOCK). This doesn't work for Azure DW, so when things don't work out, + // we'll fall back to a version without NOLOCK and try again. + isSqlDw = executeCommand(SqlConnectionHelperScripts.EngineEditionWithLock); + } + + return isSqlDw; + } + + /// + /// Compares the engine edition id of a given database with that of SQL data warehouse. + /// + /// + /// True if the engine edition id is that of SQL data warehouse + private static bool IsSqlDwEngineId(int engineEditionId) + { + return engineEditionId == SqlDwEngineEditionId; + } + + /// + /// Handles the exceptions typically thrown when a SQLConnection is being opened + /// + /// True if the exception was handled + public static bool StandardExceptionHandler(Exception ex) + { + Validate.IsNotNull(nameof(ex), ex); + + if (ex is SqlException || + ex is RetryLimitExceededException) + { + return true; + } + if (ex is InvalidCastException || + ex is ArgumentException || // Thrown when a particular connection string property is invalid (i.e. failover parner = "yes") + ex is InvalidOperationException || // thrown when the connection pool is empty and SQL is down + ex is TimeoutException || + ex is SecurityException) + { + return true; + } + + Logger.Instance.Write(LogLevel.Error, ex.ToString()); + return false; + } + + /// + /// Returns the default database path. + /// + /// The connection + /// The delegate used to initialize the command + /// The exception handler delegate. If Null is passed in then all exceptions are thrown + public static string GetDefaultDatabaseFilePath( + IDbConnection conn, + Action initializeCommand = null, + Predicate catchException = null) + { + Validate.IsNotNull(nameof(conn), conn); + + string filePath = null; + ServerInfo info = GetServerVersion(conn); + + if (!info.IsCloud) + { + filePath = GetDefaultDatabasePath(conn, SqlConnectionHelperScripts.GetDatabaseFilePathAndName, initializeCommand, catchException); + } + + return filePath; + } + + /// + /// Returns the log path or null + /// + /// The connection + /// The delegate used to initialize the command + /// The exception handler delegate. If Null is passed in then all exceptions are thrown + public static string GetDefaultDatabaseLogPath( + IDbConnection conn, + Action initializeCommand = null, + Predicate catchException = null) + { + Validate.IsNotNull(nameof(conn), conn); + + string logPath = null; + ServerInfo info = GetServerVersion(conn); + + if (!info.IsCloud) + { + logPath = GetDefaultDatabasePath(conn, SqlConnectionHelperScripts.GetDatabaseLogPathAndName, initializeCommand, catchException); + } + + return logPath; + } + + /// + /// Returns the database path or null + /// + /// The connection + /// The command to issue + /// The delegate used to initialize the command + /// The exception handler delegate. If Null is passed in then all exceptions are thrown + private static string GetDefaultDatabasePath( + IDbConnection conn, + string commandText, + Action initializeCommand = null, + Predicate catchException = null) + { + Validate.IsNotNull(nameof(conn), conn); + Validate.IsNotNullOrEmptyString(nameof(commandText), commandText); + + string filePath = ExecuteScalar(conn, commandText, initializeCommand, catchException) as string; + if (!string.IsNullOrWhiteSpace(filePath)) + { + // Remove filename from the filePath + Uri pathUri; + if (!Uri.IsWellFormedUriString(filePath, UriKind.Absolute)) + { + // In linux "file://" is required otehrwise the Uri cannot parse the path + //this should be fixed in dotenet core 2.0 + filePath = $"file://{filePath}"; + } + if (!Uri.TryCreate(filePath, UriKind.Absolute, out pathUri)) + { + // Invalid Uri + return null; + } + + // Get a current directory path relative to the pathUri + // This will remove filename from the uri. + Uri filePathUri = new Uri(pathUri, "."); + // For file uri we need to get LocalPath instead of file:// url + filePath = filePathUri.IsFile ? filePathUri.LocalPath : filePathUri.OriginalString; + } + return filePath; + } + + /// + /// Returns true if the database is readonly. This routine will swallow the exceptions you might expect from SQL using StandardExceptionHandler. + /// + public static bool IsDatabaseReadonly(SqlConnectionStringBuilder builder) + { + Validate.IsNotNull(nameof(builder), builder); + + if (builder == null) + { + throw new ArgumentNullException("builder"); + } + bool isDatabaseReadOnly = false; + + OpenConnection( + builder, + (connection) => + { + string commandText = String.Format(CultureInfo.InvariantCulture, SqlConnectionHelperScripts.CheckDatabaseReadonly, builder.InitialCatalog); + ExecuteReader(connection, + commandText, + readResult: (reader) => + { + if (reader.Read()) + { + string currentSetting = reader.GetString(1); + if (String.Compare(currentSetting, "ON", StringComparison.OrdinalIgnoreCase) == 0) + { + isDatabaseReadOnly = true; + } + } + }); + }, + (ex) => + { + Logger.Instance.Write(LogLevel.Error, ex.ToString()); + return StandardExceptionHandler(ex); // handled + }, + useRetry: true); + + return isDatabaseReadOnly; + } + + public class ServerInfo + { + public int ServerMajorVersion; + public int ServerMinorVersion; + public int ServerReleaseVersion; + public int EngineEditionId; + public string ServerVersion; + public string ServerLevel; + public string ServerEdition; + public bool IsCloud; + public int AzureVersion; + + // In SQL 2012 SP1 Selective XML indexes were added. There is bug where upgraded databases from previous versions + // of SQL Server do not have their metadata upgraded to include the xml_index_type column in the sys.xml_indexes view. Because + // of this, we must detect the presence of the column to determine if we can query for Selective Xml Indexes + public bool IsSelectiveXmlIndexMetadataPresent; + + public string OsVersion; + + public string MachineName; + } + + public static bool TryGetServerVersion(string connectionString, out ServerInfo serverInfo) + { + serverInfo = null; + SqlConnectionStringBuilder builder; + if (!TryGetConnectionStringBuilder(connectionString, out builder)) + { + return false; + } + + serverInfo = GetServerVersion(builder); + return true; + } + + /// + /// Returns the version of the server. This routine will throw if an exception is encountered. + /// + public static ServerInfo GetServerVersion(SqlConnectionStringBuilder csb) + { + Validate.IsNotNull(nameof(csb), csb); + ServerInfo serverInfo = null; + + OpenConnection( + csb, + (connection) => + { + serverInfo = GetServerVersion(connection); + }, + catchException: null, // Always throw + useRetry: true); + + return serverInfo; + } + + /// + /// Returns the version of the server. This routine will throw if an exception is encountered. + /// + public static ServerInfo GetServerVersion(IDbConnection connection) + { + Validate.IsNotNull(nameof(connection), connection); + if (!(connection.State == ConnectionState.Open)) + { + Logger.Instance.Write(LogLevel.Error, "connection passed to GetServerVersion should be open."); + } + + Func getServerInfo = commandText => + { + ServerInfo serverInfo = new ServerInfo(); + ExecuteReader( + connection, + commandText, + delegate (IDataReader reader) + { + reader.Read(); + int engineEditionId = Int32.Parse(reader[0].ToString(), CultureInfo.InvariantCulture); + + serverInfo.EngineEditionId = engineEditionId; + serverInfo.IsCloud = IsCloudEngineId(engineEditionId); + + serverInfo.ServerVersion = reader[1].ToString(); + serverInfo.ServerLevel = reader[2].ToString(); + serverInfo.ServerEdition = reader[3].ToString(); + serverInfo.MachineName = reader[4].ToString(); + + if (reader.FieldCount > 5) + { + // Detect the presence of SXI + serverInfo.IsSelectiveXmlIndexMetadataPresent = reader.GetInt32(5) == 1; + } + + // The 'ProductVersion' server property is of the form ##.#[#].####.#, + Version serverVersion = new Version(serverInfo.ServerVersion); + + // The server version is of the form ##.##.####, + serverInfo.ServerMajorVersion = serverVersion.Major; + serverInfo.ServerMinorVersion = serverVersion.Minor; + serverInfo.ServerReleaseVersion = serverVersion.Build; + + if (serverInfo.IsCloud) + { + serverInfo.AzureVersion = serverVersion.Major > 11 ? 2 : 1; + } + + try + { + CachedServerInfo.Instance.AddOrUpdateIsCloud(connection, serverInfo.IsCloud); + } + catch (Exception ex) + { + //we don't want to fail the normal flow if any unexpected thing happens + //during caching although it's unlikely. So we just log the exception and ignore it + Logger.Instance.Write(LogLevel.Error, Resources.FailedToCacheIsCloud); + Logger.Instance.Write(LogLevel.Error, ex.ToString()); + } + }); + + // Also get the OS Version + ExecuteReader( + connection, + SqlConnectionHelperScripts.GetOsVersion, + delegate (IDataReader reader) + { + reader.Read(); + serverInfo.OsVersion = reader[0].ToString(); + }); + + return serverInfo; + }; + + ServerInfo result = null; + try + { + result = getServerInfo(SqlConnectionHelperScripts.EngineEdition); + } + catch (SqlException) + { + // The default query contains a WITH (NOLOCK). This doesn't work for Azure DW, so when things don't work out, + // we'll fall back to a version without NOLOCK and try again. + result = getServerInfo(SqlConnectionHelperScripts.EngineEditionWithLock); + } + + return result; + } + + public static string GetServerName(IDbConnection connection) + { + return new DbConnectionWrapper(connection).DataSource; + } + + public static string ReadServerVersion(IDbConnection connection) + { + return new DbConnectionWrapper(connection).ServerVersion; + } + + /// + /// Converts to a SqlConnection by casting (if we know it is actually a SqlConnection) + /// or by getting the underlying connection (if it's a ReliableSqlConnection) + /// + public static SqlConnection GetAsSqlConnection(IDbConnection connection) + { + return new DbConnectionWrapper(connection).GetAsSqlConnection(); + } + + /* TODO - CloneAndOpenConnection() requires IClonable, which doesn't exist in .NET Core + /// + /// Clones a connection and ensures it's opened. + /// If it's a SqlConnection it will clone it, + /// and for ReliableSqlConnection it will clone the underling connection. + /// The reason the entire ReliableSqlConnection is not cloned is that it includes + /// several callbacks and we don't want to try and handle deciding how to clone these + /// yet. + /// + public static SqlConnection CloneAndOpenConnection(IDbConnection connection) + { + return new DbConnectionWrapper(connection).CloneAndOpenConnection(); + } + */ + + public class ServerAndDatabaseInfo : ServerInfo + { + public int DbCompatibilityLevel; + public string DatabaseName; + } + + internal static bool TryGetConnectionStringBuilder(string connectionString, out SqlConnectionStringBuilder builder) + { + builder = null; + + if (String.IsNullOrEmpty(connectionString)) + { + // Connection string is not valid + return false; + } + + // Attempt to initialize the builder + Exception handledEx = null; + try + { + builder = new SqlConnectionStringBuilder(connectionString); + } + catch (KeyNotFoundException ex) + { + handledEx = ex; + } + catch (FormatException ex) + { + handledEx = ex; + } + catch (ArgumentException ex) + { + handledEx = ex; + } + + if (handledEx != null) + { + Logger.Instance.Write(LogLevel.Error, String.Format(Resources.ErrorParsingConnectionString, handledEx)); + return false; + } + + return true; + } + + /* + /// + /// Get the version of the server and database using + /// the connection string provided. This routine will + /// throw if an exception is encountered. + /// + /// The connection string used to connect to the database. + /// Basic information about the server + public static bool GetServerAndDatabaseVersion(string connectionString, out ServerAndDatabaseInfo info) + { + bool foundVersion = false; + info = new ServerAndDatabaseInfo { IsCloud = false, ServerMajorVersion = -1, DbCompatibilityLevel = -1, DatabaseName = String.Empty }; + + SqlConnectionStringBuilder builder; + if (!TryGetConnectionStringBuilder(connectionString, out builder)) + { + return false; + } + + // The database name is either the InitialCatalog or the AttachDBFilename. The + // AttachDBFilename is used if an mdf file is specified in the connections dialog. + if (String.IsNullOrEmpty(builder.InitialCatalog) || + String.IsNullOrEmpty(builder.AttachDBFilename)) + { + builder.Pooling = false; + + string tempDatabaseName = String.Empty; + int tempDbCompatibilityLevel = 0; + ServerInfo serverInfo = null; + + OpenConnection( + builder, + (connection) => + { + // Set the lock timeout to 3 seconds + SetLockAndCommandTimeout(connection); + + serverInfo = GetServerVersion(connection); + + tempDatabaseName = (!string.IsNullOrEmpty(builder.InitialCatalog)) ? + builder.InitialCatalog : builder.AttachDBFilename; + + // If at this point the dbName remained an empty string then + // we should get the database name from the open IDbConnection + if (String.IsNullOrEmpty(tempDatabaseName)) + { + tempDatabaseName = connection.Database; + } + + // SQL Azure does not support custom DBCompat values. + SqlParameter databaseNameParameter = new SqlParameter( + "@dbname", + SqlDbType.NChar, + 128, + ParameterDirection.Input, + false, + 0, + 0, + null, + DataRowVersion.Default, + tempDatabaseName); + + object compatibilityLevel; + + using (IDbCommand versionCommand = connection.CreateCommand()) + { + versionCommand.CommandText = "SELECT compatibility_level FROM sys.databases WITH (NOLOCK) WHERE name = @dbname"; + versionCommand.CommandType = CommandType.Text; + versionCommand.Parameters.Add(databaseNameParameter); + compatibilityLevel = versionCommand.ExecuteScalar(); + } + + // value is null if db is not online + foundVersion = compatibilityLevel != null && !(compatibilityLevel is DBNull); + if(foundVersion) + { + tempDbCompatibilityLevel = (byte)compatibilityLevel; + } + else + { + string conString = connection.ConnectionString == null ? "null" : connection.ConnectionString; + string dbName = tempDatabaseName == null ? "null" : tempDatabaseName; + string message = string.Format(CultureInfo.CurrentCulture, + "Querying database compatibility level failed. Connection string: '{0}'. dbname: '{1}'.", + conString, dbName); + Tracer.TraceEvent(TraceEventType.Error, TraceId.CoreServices, message); + } + }, + catchException: null, // Always throw + useRetry: true); + + info.IsCloud = serverInfo.IsCloud; + info.ServerMajorVersion = serverInfo.ServerMajorVersion; + info.ServerMinorVersion = serverInfo.ServerMinorVersion; + info.ServerReleaseVersion = serverInfo.ServerReleaseVersion; + info.ServerVersion = serverInfo.ServerVersion; + info.ServerLevel = serverInfo.ServerLevel; + info.ServerEdition = serverInfo.ServerEdition; + info.AzureVersion = serverInfo.AzureVersion; + info.DatabaseName = tempDatabaseName; + info.DbCompatibilityLevel = tempDbCompatibilityLevel; + } + + return foundVersion; + } + */ + + /// + /// Returns true if the authenticating database is master, otherwise false. An example of + /// false is when the user is a contained user connecting to a contained database. + /// + public static bool IsAuthenticatingDatabaseMaster(IDbConnection connection) + { + try + { + const string sqlCommand = + @"use [{0}]; + if (db_id() = 1) + begin + -- contained auth is 0 when connected to master + select 0 + end + else + begin + -- need dynamic sql so that we compile this query only when we know resource db is available + exec('select case when authenticating_database_id = 1 then 0 else 1 end from sys.dm_exec_sessions where session_id = @@SPID') + end"; + + string finalCmd = null; + if (!String.IsNullOrWhiteSpace(connection.Database)) + { + finalCmd = String.Format(CultureInfo.InvariantCulture, sqlCommand, connection.Database); + } + else + { + finalCmd = String.Format(CultureInfo.InvariantCulture, sqlCommand, "master"); + } + + object retValue = ExecuteScalar(connection, finalCmd); + if (retValue != null && retValue.ToString() == "1") + { + // contained auth is 0 when connected to non-master + return false; + } + return true; + } + catch (Exception ex) + { + if (StandardExceptionHandler(ex)) + { + return true; + } + throw; + } + } + + /// + /// Returns true if the authenticating database is master, otherwise false. An example of + /// false is when the user is a contained user connecting to a contained database. + /// + public static bool IsAuthenticatingDatabaseMaster(SqlConnectionStringBuilder builder) + { + bool authIsMaster = true; + OpenConnection( + builder, + usingConnection: (connection) => + { + authIsMaster = IsAuthenticatingDatabaseMaster(connection); + }, + catchException: StandardExceptionHandler, // Don't throw unless it's an unexpected exception + useRetry: true); + return authIsMaster; + } + + /// + /// Returns the form of the server as a it's name - replaces . and (localhost) + /// + public static string GetCompleteServerName(string server) + { + if (String.IsNullOrEmpty(server)) + { + return server; + } + + int nlen = 0; + if (server[0] == '.') + { + nlen = 1; + } + else if (String.Compare(server, Constants.Local, StringComparison.OrdinalIgnoreCase) == 0) + { + nlen = Constants.Local.Length; + } + else if (String.Compare(server, 0, ServerNameLocalhost, 0, ServerNameLocalhost.Length, StringComparison.OrdinalIgnoreCase) == 0) + { + nlen = ServerNameLocalhost.Length; + } + + if (nlen > 0) + { + string strMachine = Environment.MachineName; + if (server.Length == nlen) + return strMachine; + if (server.Length > (nlen + 1) && server[nlen] == '\\') // instance + { + string strRet = strMachine + server.Substring(nlen); + return strRet; + } + } + + return server; + } + + /* + /// + /// Processes a user-supplied connection string and provides a trimmed connection string + /// that eliminates everything except for DataSource, InitialCatalog, UserId, Password, + /// ConnectTimeout, Encrypt, TrustServerCertificate and IntegratedSecurity. + /// + /// When connection string is invalid + public static string TrimConnectionString(string connectionString) + { + Exception handledException; + + try + { + SqlConnectionStringBuilder scsb = new SqlConnectionStringBuilder(connectionString); + return TrimConnectionStringBuilder(scsb).ConnectionString; + } + catch (ArgumentException exception) + { + handledException = exception; + } + catch (KeyNotFoundException exception) + { + handledException = exception; + } + catch (FormatException exception) + { + handledException = exception; + } + + throw new InvalidConnectionStringException(handledException); + } + */ + + /// + /// Sql 2012 PCU1 introduces breaking changes to metadata queries and adds new Selective XML Index support. + /// This method allows components to detect if the represents a build of SQL 2012 after RTM. + /// + public static bool IsVersionGreaterThan2012RTM(ServerInfo _serverInfo) + { + return _serverInfo.ServerMajorVersion > 11 || + // Use the presence of SXI metadata rather than build number as upgrade bugs leave out the SXI metadata for some upgraded databases. + _serverInfo.ServerMajorVersion == 11 && _serverInfo.IsSelectiveXmlIndexMetadataPresent; + } + + + // SQL Server: Defect 1122301: ReliableConnectionHelper does not maintain ApplicationIntent + // The ApplicationIntent and MultiSubnetFailover property is not introduced to .NET until .NET 4.0 update 2 + // However, DacFx is officially depends on .NET 4.0 RTM + // So here we want to support both senarios, on machine with 4.0 RTM installed, it will ignore these 2 properties + // On machine with higher .NET version which included those properties, it will pick them up. + public static void TryAddAlwaysOnConnectionProperties(SqlConnectionStringBuilder userBuilder, SqlConnectionStringBuilder trimBuilder) + { + if (userBuilder.ContainsKey(ApplicationIntent)) + { + trimBuilder[ApplicationIntent] = userBuilder[ApplicationIntent]; + } + + if (userBuilder.ContainsKey(MultiSubnetFailover)) + { + trimBuilder[MultiSubnetFailover] = userBuilder[MultiSubnetFailover]; + } + } + + /* TODO - this relies on porting SqlAuthenticationMethodUtils + /// + /// Processes a user-supplied connection string and provides a trimmed connection string + /// that eliminates everything except for DataSource, InitialCatalog, UserId, Password, + /// ConnectTimeout, Encrypt, TrustServerCertificate, IntegratedSecurity and Pooling. + /// + /// + /// Pooling is always set to false to avoid connections remaining open. + /// + /// When connection string is invalid + public static SqlConnectionStringBuilder TrimConnectionStringBuilder(SqlConnectionStringBuilder userBuilder, Action throwException = null) + { + + Exception handledException; + + if (throwException == null) + { + throwException = (propertyName) => + { + throw new InvalidConnectionStringException(String.Format(CultureInfo.CurrentCulture, Resources.UnsupportedConnectionStringArgument, propertyName)); + }; + } + if (!String.IsNullOrEmpty(userBuilder.AttachDBFilename)) + { + throwException("AttachDBFilename"); + } + if (userBuilder.UserInstance) + { + throwException("User Instance"); + } + + try + { + SqlConnectionStringBuilder trimBuilder = new SqlConnectionStringBuilder(); + + if (String.IsNullOrWhiteSpace(userBuilder.DataSource)) + { + throw new InvalidConnectionStringException(); + } + + trimBuilder.ConnectTimeout = userBuilder.ConnectTimeout; + trimBuilder.DataSource = userBuilder.DataSource; + + if (false == String.IsNullOrWhiteSpace(userBuilder.InitialCatalog)) + { + trimBuilder.InitialCatalog = userBuilder.InitialCatalog; + } + + trimBuilder.IntegratedSecurity = userBuilder.IntegratedSecurity; + + if (!String.IsNullOrWhiteSpace(userBuilder.UserID)) + { + trimBuilder.UserID = userBuilder.UserID; + } + + if (!String.IsNullOrWhiteSpace(userBuilder.Password)) + { + trimBuilder.Password = userBuilder.Password; + } + + trimBuilder.TrustServerCertificate = userBuilder.TrustServerCertificate; + trimBuilder.Encrypt = userBuilder.Encrypt; + + if (String.IsNullOrWhiteSpace(userBuilder.ApplicationName) || + String.Equals(BuilderWithDefaultApplicationName.ApplicationName, userBuilder.ApplicationName, StringComparison.Ordinal)) + { + trimBuilder.ApplicationName = DacFxApplicationName; + } + else + { + trimBuilder.ApplicationName = userBuilder.ApplicationName; + } + + TryAddAlwaysOnConnectionProperties(userBuilder, trimBuilder); + + if (SqlAuthenticationMethodUtils.IsAuthenticationSupported()) + { + SqlAuthenticationMethodUtils.SetAuthentication(userBuilder, trimBuilder); + } + + if (SqlAuthenticationMethodUtils.IsCertificateSupported()) + { + SqlAuthenticationMethodUtils.SetCertificate(userBuilder, trimBuilder); + } + + trimBuilder.Pooling = false; + return trimBuilder; + } + catch (ArgumentException exception) + { + handledException = exception; + } + catch (KeyNotFoundException exception) + { + handledException = exception; + } + catch (FormatException exception) + { + handledException = exception; + } + + throw new InvalidConnectionStringException(handledException); + } + + public static bool TryCreateConnectionStringBuilder(string connectionString, out SqlConnectionStringBuilder builder, out Exception handledException) + { + bool success = false; + builder = null; + handledException = null; + try + { + builder = TrimConnectionStringBuilder(new SqlConnectionStringBuilder(connectionString)); + + success = true; + } + catch (InvalidConnectionStringException e) + { + handledException = e; + } + catch (ArgumentException exception) + { + handledException = exception; + } + catch (KeyNotFoundException exception) + { + handledException = exception; + } + catch (FormatException exception) + { + handledException = exception; + } + finally + { + if (handledException != null) + { + success = false; + } + } + return success; + } + */ + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/ReliableSqlCommand.cs b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/ReliableSqlCommand.cs new file mode 100644 index 00000000..f085be8e --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/ReliableSqlCommand.cs @@ -0,0 +1,247 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +// This code is copied from the source described in the comment below. + +// ======================================================================================= +// Microsoft Windows Server AppFabric Customer Advisory Team (CAT) Best Practices Series +// +// This sample is supplemental to the technical guidance published on the community +// blog at http://blogs.msdn.com/appfabriccat/ and copied from +// sqlmain ./sql/manageability/mfx/common/ +// +// ======================================================================================= +// Copyright © 2012 Microsoft Corporation. All rights reserved. +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER +// EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. YOU BEAR THE RISK OF USING IT. +// ======================================================================================= + +// namespace Microsoft.AppFabricCAT.Samples.Azure.TransientFaultHandling.SqlAzure +// namespace Microsoft.SqlServer.Management.Common + +using System; +using System.Data; +using System.Data.Common; +using System.Data.SqlClient; +using System.Diagnostics.Contracts; + +namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection +{ + /// + /// Provides a reliable way of opening connections to and executing commands + /// taking into account potential network unreliability and a requirement for connection retry. + /// + internal sealed partial class ReliableSqlConnection + { + internal class ReliableSqlCommand : DbCommand + { + private const int Dummy = 0; + private readonly SqlCommand _command; + + // connection is settable + private ReliableSqlConnection _connection; + + public ReliableSqlCommand() + : this(null, Dummy) + { + } + + public ReliableSqlCommand(ReliableSqlConnection connection) + : this(connection, Dummy) + { + Contract.Requires(connection != null); + } + + private ReliableSqlCommand(ReliableSqlConnection connection, int dummy) + { + if (connection != null) + { + _connection = connection; + _command = connection.CreateSqlCommand(); + } + else + { + _command = new SqlCommand(); + } + } + + protected override void Dispose(bool disposing) + { + if (disposing) + { + _command.Dispose(); + } + } + + /// + /// Gets or sets the text command to run against the data source. + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2100:Review SQL queries for security vulnerabilities")] + public override string CommandText + { + get { return _command.CommandText; } + set { _command.CommandText = value; } + } + + /// + /// Gets or sets the wait time before terminating the attempt to execute a command and generating an error. + /// + public override int CommandTimeout + { + get { return _command.CommandTimeout; } + set { _command.CommandTimeout = value; } + } + + /// + /// Gets or sets a value that specifies how the property is interpreted. + /// + public override CommandType CommandType + { + get { return _command.CommandType; } + set { _command.CommandType = value; } + } + + /// + /// Gets or sets the used by this . + /// + protected override DbConnection DbConnection + { + get + { + return _connection; + } + + set + { + if (value == null) + { + throw new ArgumentNullException("value"); + } + + ReliableSqlConnection newConnection = value as ReliableSqlConnection; + + if (newConnection == null) + { + throw new InvalidOperationException(Resources.OnlyReliableConnectionSupported); + } + + _connection = newConnection; + _command.Connection = _connection._underlyingConnection; + } + } + + /// + /// Gets the . + /// + protected override DbParameterCollection DbParameterCollection + { + get { return _command.Parameters; } + } + + /// + /// Gets or sets the transaction within which the Command object of a .NET Framework data provider executes. + /// + protected override DbTransaction DbTransaction + { + get { return _command.Transaction; } + set { _command.Transaction = value as SqlTransaction; } + } + + /// + /// Gets or sets a value indicating whether the command object should be visible in a customized interface control. + /// + public override bool DesignTimeVisible + { + get { return _command.DesignTimeVisible; } + set { _command.DesignTimeVisible = value; } + } + + /// + /// Gets or sets how command results are applied to the System.Data.DataRow when + /// used by the System.Data.IDataAdapter.Update(System.Data.DataSet) method of + /// a . + /// + public override UpdateRowSource UpdatedRowSource + { + get { return _command.UpdatedRowSource; } + set { _command.UpdatedRowSource = value; } + } + + /// + /// Attempts to cancels the execution of an . + /// + public override void Cancel() + { + _command.Cancel(); + } + + /// + /// Creates a new instance of an object. + /// + /// An object. + protected override DbParameter CreateDbParameter() + { + return _command.CreateParameter(); + } + + /// + /// Executes an SQL statement against the Connection object of a .NET Framework + /// data provider, and returns the number of rows affected. + /// + /// The number of rows affected. + public override int ExecuteNonQuery() + { + ValidateConnectionIsSet(); + return _connection.ExecuteNonQuery(_command); + } + + /// + /// Executes the against the + /// and builds an using one of the values. + /// + /// One of the values. + /// An object. + protected override DbDataReader ExecuteDbDataReader(CommandBehavior behavior) + { + ValidateConnectionIsSet(); + return (DbDataReader)_connection.ExecuteReader(_command, behavior); + } + + /// + /// Executes the query, and returns the first column of the first row in the + /// resultset returned by the query. Extra columns or rows are ignored. + /// + /// The first column of the first row in the resultset. + public override object ExecuteScalar() + { + ValidateConnectionIsSet(); + return _connection.ExecuteScalar(_command); + } + + /// + /// Creates a prepared (or compiled) version of the command on the data source. + /// + public override void Prepare() + { + _command.Prepare(); + } + + internal SqlCommand GetUnderlyingCommand() + { + return _command; + } + + internal void ValidateConnectionIsSet() + { + if (_connection == null) + { + throw new InvalidOperationException(Resources.ConnectionPropertyNotSet); + } + } + } + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/ReliableSqlConnection.cs b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/ReliableSqlConnection.cs new file mode 100644 index 00000000..66d7102f --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/ReliableSqlConnection.cs @@ -0,0 +1,610 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +// This code is copied from the source described in the comment below. + +// ======================================================================================= +// Microsoft Windows Server AppFabric Customer Advisory Team (CAT) Best Practices Series +// +// This sample is supplemental to the technical guidance published on the community +// blog at http://blogs.msdn.com/appfabriccat/ and copied from +// sqlmain ./sql/manageability/mfx/common/ +// +// ======================================================================================= +// Copyright © 2012 Microsoft Corporation. All rights reserved. +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER +// EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. YOU BEAR THE RISK OF USING IT. +// ======================================================================================= + +// namespace Microsoft.AppFabricCAT.Samples.Azure.TransientFaultHandling.SqlAzure +// namespace Microsoft.SqlServer.Management.Common + +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Data.SqlClient; +using System.Diagnostics; +using System.Globalization; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.SqlTools.Hosting.Utility; + +namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection +{ + /// + /// Provides a reliable way of opening connections to and executing commands + /// taking into account potential network unreliability and a requirement for connection retry. + /// + internal sealed partial class ReliableSqlConnection : DbConnection, IDisposable + { + private const string QueryAzureSessionId = "SELECT CONVERT(NVARCHAR(36), CONTEXT_INFO())"; + + private readonly SqlConnection _underlyingConnection; + private readonly RetryPolicy _connectionRetryPolicy; + private RetryPolicy _commandRetryPolicy; + private Guid _azureSessionId; + private bool _isSqlDwDatabase; + + /// + /// Initializes a new instance of the ReliableSqlConnection class with a given connection string + /// and a policy defining whether to retry a request if the connection fails to be opened or a command + /// fails to be successfully executed. + /// + /// The connection string used to open the SQL Azure database. + /// The retry policy defining whether to retry a request if a connection fails to be established. + /// The retry policy defining whether to retry a request if a command fails to be executed. + public ReliableSqlConnection(string connectionString, RetryPolicy connectionRetryPolicy, RetryPolicy commandRetryPolicy) + { + _underlyingConnection = new SqlConnection(connectionString); + _connectionRetryPolicy = connectionRetryPolicy ?? RetryPolicyFactory.CreateNoRetryPolicy(); + _commandRetryPolicy = commandRetryPolicy ?? RetryPolicyFactory.CreateNoRetryPolicy(); + + _underlyingConnection.StateChange += OnConnectionStateChange; + _connectionRetryPolicy.RetryOccurred += RetryConnectionCallback; + _commandRetryPolicy.RetryOccurred += RetryCommandCallback; + } + + /// + /// Performs application-defined tasks associated with freeing, releasing, or + /// resetting managed and unmanaged resources. + /// + /// A flag indicating that managed resources must be released. + protected override void Dispose(bool disposing) + { + if (disposing) + { + if (_connectionRetryPolicy != null) + { + _connectionRetryPolicy.RetryOccurred -= RetryConnectionCallback; + } + + if (_commandRetryPolicy != null) + { + _commandRetryPolicy.RetryOccurred -= RetryCommandCallback; + } + + _underlyingConnection.StateChange -= OnConnectionStateChange; + if (_underlyingConnection.State == ConnectionState.Open) + { + _underlyingConnection.Close(); + } + + _underlyingConnection.Dispose(); + } + } + + /// + /// Determines if a connection is being made to a SQL DW database. + /// + /// A connection object. + private bool IsSqlDwConnection(IDbConnection conn) + { + //Set the connection only if it has not been set earlier. + //This is assuming that it is highly unlikely for a connection to change between instances. + //Hence any subsequent calls to this method will just return the cached value and not + //verify again if this is a SQL DW database connection or not. + if (!CachedServerInfo.Instance.TryGetIsSqlDw(conn, out _isSqlDwDatabase)) + { + _isSqlDwDatabase = ReliableConnectionHelper.IsSqlDwDatabase(conn); + CachedServerInfo.Instance.AddOrUpdateIsSqlDw(conn, _isSqlDwDatabase);; + } + + return _isSqlDwDatabase; + } + + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2100:Review SQL queries for security vulnerabilities")] + internal static void SetLockAndCommandTimeout(IDbConnection conn) + { + Validate.IsNotNull(nameof(conn), conn); + + // Make sure we use the underlying connection as ReliableConnection.Open also calls + // this method + ReliableSqlConnection reliableConn = conn as ReliableSqlConnection; + if (reliableConn != null) + { + conn = reliableConn._underlyingConnection; + } + + const string setLockTimeout = @"set LOCK_TIMEOUT {0}"; + + using (IDbCommand cmd = conn.CreateCommand()) + { + cmd.CommandText = string.Format(CultureInfo.InvariantCulture, setLockTimeout, AmbientSettings.LockTimeoutMilliSeconds); + cmd.CommandType = CommandType.Text; + cmd.CommandTimeout = CachedServerInfo.Instance.GetQueryTimeoutSeconds(conn); + cmd.ExecuteNonQuery(); + } + } + + internal static void SetDefaultAnsiSettings(IDbConnection conn, bool isSqlDw) + { + Validate.IsNotNull(nameof(conn), conn); + + // Make sure we use the underlying connection as ReliableConnection.Open also calls + // this method + ReliableSqlConnection reliableConn = conn as ReliableSqlConnection; + if (reliableConn != null) + { + conn = reliableConn._underlyingConnection; + } + + // Configure the connection with proper ANSI settings and lock timeout + using (IDbCommand cmd = conn.CreateCommand()) + { + cmd.CommandTimeout = CachedServerInfo.Instance.GetQueryTimeoutSeconds(conn); + if (!isSqlDw) + { + cmd.CommandText = @"SET ANSI_NULLS, ANSI_PADDING, ANSI_WARNINGS, ARITHABORT, CONCAT_NULL_YIELDS_NULL, QUOTED_IDENTIFIER ON; +SET NUMERIC_ROUNDABORT OFF;"; + } + else + { + cmd.CommandText = @"SET ANSI_NULLS ON; SET ANSI_PADDING ON; SET ANSI_WARNINGS ON; SET ARITHABORT ON; SET CONCAT_NULL_YIELDS_NULL ON; SET QUOTED_IDENTIFIER ON;"; //SQL DW does not support NUMERIC_ROUNDABORT + } + cmd.ExecuteNonQuery(); + } + } + + /// + /// Gets or sets the connection string for opening a connection to the SQL Azure database. + /// + public override string ConnectionString + { + get { return _underlyingConnection.ConnectionString; } + set { _underlyingConnection.ConnectionString = value; } + } + + /// + /// Gets the policy which decides whether to retry a connection request, based on how many + /// times the request has been made and the reason for the last failure. + /// + public RetryPolicy ConnectionRetryPolicy + { + get { return _connectionRetryPolicy; } + } + + /// + /// Gets the policy which decides whether to retry a command, based on how many + /// times the request has been made and the reason for the last failure. + /// + public RetryPolicy CommandRetryPolicy + { + get { return _commandRetryPolicy; } + set + { + Validate.IsNotNull(nameof(value), value); + + if (_commandRetryPolicy != null) + { + _commandRetryPolicy.RetryOccurred -= RetryCommandCallback; + } + + _commandRetryPolicy = value; + _commandRetryPolicy.RetryOccurred += RetryCommandCallback; + } + } + + /// + /// Gets the server name from the underlying connection. + /// + public override string DataSource + { + get { return _underlyingConnection.DataSource; } + } + + /// + /// Gets the server version from the underlying connection. + /// + public override string ServerVersion + { + get { return _underlyingConnection.ServerVersion; } + } + + /// + /// If the underlying SqlConnection absolutely has to be accessed, for instance + /// to pass to external APIs that require this type of connection, then this + /// can be used. + /// + /// + public SqlConnection GetUnderlyingConnection() + { + return _underlyingConnection; + } + + /// + /// Begins a database transaction with the specified System.Data.IsolationLevel value. + /// + /// One of the System.Data.IsolationLevel values. + /// An object representing the new transaction. + protected override DbTransaction BeginDbTransaction(IsolationLevel level) + { + return _underlyingConnection.BeginTransaction(level); + } + + /// + /// Changes the current database for an open Connection object. + /// + /// The name of the database to use in place of the current database. + public override void ChangeDatabase(string databaseName) + { + _underlyingConnection.ChangeDatabase(databaseName); + } + + /// + /// Opens a database connection with the settings specified by the ConnectionString + /// property of the provider-specific Connection object. + /// + public override void Open() + { + // Check if retry policy was specified, if not, disable retries by executing the Open method using RetryPolicy.NoRetry. + _connectionRetryPolicy.ExecuteAction(() => + { + if (_underlyingConnection.State != ConnectionState.Open) + { + _underlyingConnection.Open(); + } + SetLockAndCommandTimeout(_underlyingConnection); + SetDefaultAnsiSettings(_underlyingConnection, IsSqlDwConnection(_underlyingConnection)); + }); + } + + /// + /// Opens a database connection with the settings specified by the ConnectionString + /// property of the provider-specific Connection object. + /// + public override Task OpenAsync(CancellationToken token) + { + // Make sure that the token isn't cancelled before we try + if (token.IsCancellationRequested) + { + return Task.FromCanceled(token); + } + + // Check if retry policy was specified, if not, disable retries by executing the Open method using RetryPolicy.NoRetry. + try + { + return _connectionRetryPolicy.ExecuteAction(async () => + { + if (_underlyingConnection.State != ConnectionState.Open) + { + await _underlyingConnection.OpenAsync(token); + } + SetLockAndCommandTimeout(_underlyingConnection); + SetDefaultAnsiSettings(_underlyingConnection, IsSqlDwConnection(_underlyingConnection)); + }); + } + catch (Exception e) + { + return Task.FromException(e); + } + } + + /// + /// Closes the connection to the database. + /// + public override void Close() + { + _underlyingConnection.Close(); + } + + /// + /// Gets the time to wait while trying to establish a connection before terminating + /// the attempt and generating an error. + /// + public override int ConnectionTimeout + { + get { return _underlyingConnection.ConnectionTimeout; } + } + + /// + /// Creates and returns an object implementing the IDbCommand interface which is associated + /// with the underlying SqlConnection. + /// + /// A object. + protected override DbCommand CreateDbCommand() + { + return CreateReliableCommand(); + } + + /// + /// Creates and returns an object implementing the IDbCommand interface which is associated + /// with the underlying SqlConnection. + /// + /// A object. + public SqlCommand CreateSqlCommand() + { + return _underlyingConnection.CreateCommand(); + } + + /// + /// Gets the name of the current database or the database to be used after a + /// connection is opened. + /// + public override string Database + { + get { return _underlyingConnection.Database; } + } + + /// + /// Gets the current state of the connection. + /// + public override ConnectionState State + { + get { return _underlyingConnection.State; } + } + + /// + /// Adds an info message event listener. + /// + /// An info message event listener. + public void AddInfoMessageHandler(SqlInfoMessageEventHandler handler) + { + _underlyingConnection.InfoMessage += handler; + } + + /// + /// Removes an info message event listener. + /// + /// An info message event listener. + public void RemoveInfoMessageHandler(SqlInfoMessageEventHandler handler) + { + _underlyingConnection.InfoMessage -= handler; + } + + /// + /// Clears underlying connection pool. + /// + public void ClearPool() + { + if (_underlyingConnection != null) + { + SqlConnection.ClearPool(_underlyingConnection); + } + } + + private void RetryCommandCallback(RetryState retryState) + { + RetryPolicyUtils.RaiseSchemaAmbientRetryMessage(retryState, SqlSchemaModelErrorCodes.ServiceActions.CommandRetry, _azureSessionId); + } + + private void RetryConnectionCallback(RetryState retryState) + { + RetryPolicyUtils.RaiseSchemaAmbientRetryMessage(retryState, SqlSchemaModelErrorCodes.ServiceActions.ConnectionRetry, _azureSessionId); + } + + public void OnConnectionStateChange(object sender, StateChangeEventArgs e) + { + SqlConnection conn = (SqlConnection)sender; + switch (e.CurrentState) + { + case ConnectionState.Open: + RetrieveSessionId(); + break; + case ConnectionState.Broken: + case ConnectionState.Closed: + _azureSessionId = Guid.Empty; + break; + case ConnectionState.Connecting: + case ConnectionState.Executing: + case ConnectionState.Fetching: + default: + break; + } + } + + private void RetrieveSessionId() + { + try + { + using (IDbCommand command = CreateReliableCommand()) + { + IDbConnection connection = command.Connection; + if (!IsSqlDwConnection(connection)) + { + command.CommandText = QueryAzureSessionId; + object result = command.ExecuteScalar(); + + // Only returns a session id for SQL Azure + if (DBNull.Value != result) + { + string sessionId = (string)command.ExecuteScalar(); + _azureSessionId = new Guid(sessionId); + } + } + } + } + catch (SqlException exception) + { + Logger.Instance.Write(LogLevel.Error, Resources.UnableToRetrieveAzureSessionId + exception.ToString()); + } + } + + /// + /// Creates and returns a ReliableSqlCommand object associated + /// with the underlying SqlConnection. + /// + /// A object. + private ReliableSqlCommand CreateReliableCommand() + { + return new ReliableSqlCommand(this); + } + + private void VerifyConnectionOpen(IDbCommand command) + { + // Verify whether or not the connection is valid and is open. This code may be retried therefore + // it is important to ensure that a connection is re-established should it have previously failed. + if (command.Connection == null) + { + command.Connection = this; + } + + if (command.Connection.State != ConnectionState.Open) + { + SqlConnection.ClearPool(_underlyingConnection); + + command.Connection.Open(); + } + } + + private IDataReader ExecuteReader(IDbCommand command, CommandBehavior behavior) + { + Tuple[] sessionSettings = null; + return _commandRetryPolicy.ExecuteAction(() => + { + VerifyConnectionOpen(command); + sessionSettings = CacheOrReplaySessionSettings(command, sessionSettings); + + return command.ExecuteReader(behavior); + }); + } + + // Because retry loses session settings, cache session settings or reply if the settings are already cached. + internal Tuple[] CacheOrReplaySessionSettings(IDbCommand originalCommand, Tuple[] sessionSettings) + { + if (sessionSettings == null) + { + sessionSettings = QuerySessionSettings(originalCommand); + } + else + { + SetSessionSettings(originalCommand.Connection, sessionSettings); + } + + return sessionSettings; + } + + private object ExecuteScalar(IDbCommand command) + { + Tuple[] sessionSettings = null; + return _commandRetryPolicy.ExecuteAction(() => + { + VerifyConnectionOpen(command); + sessionSettings = CacheOrReplaySessionSettings(command, sessionSettings); + + return command.ExecuteScalar(); + }); + } + + private Tuple[] QuerySessionSettings(IDbCommand originalCommand) + { + Tuple[] sessionSettings = new Tuple[2]; + + IDbConnection connection = originalCommand.Connection; + if (IsSqlDwConnection(connection)) + { + // SESSIONPROPERTY is not supported. Use default values for now + sessionSettings[0] = Tuple.Create("ANSI_NULLS", true); + sessionSettings[1] = Tuple.Create("QUOTED_IDENTIFIER", true); + } + else + { + using (IDbCommand localCommand = connection.CreateCommand()) + { + // Executing a reader requires preservation of any pending transaction created by the calling command + localCommand.Transaction = originalCommand.Transaction; + localCommand.CommandText = "SELECT ISNULL(SESSIONPROPERTY ('ANSI_NULLS'), 0), ISNULL(SESSIONPROPERTY ('QUOTED_IDENTIFIER'), 1)"; + using (IDataReader reader = localCommand.ExecuteReader()) + { + if (reader.Read()) + { + sessionSettings[0] = Tuple.Create("ANSI_NULLS", ((int)reader[0] == 1)); + sessionSettings[1] = Tuple.Create("QUOTED_IDENTIFIER", ((int)reader[1] ==1)); + } + else + { + Debug.Assert(false, "Reader cannot be empty"); + } + } + } + } + return sessionSettings; + } + + private void SetSessionSettings(IDbConnection connection, params Tuple[] settings) + { + List setONOptions = new List(); + List setOFFOptions = new List(); + if(settings != null) + { + foreach (Tuple setting in settings) + { + if (setting.Item2) + { + setONOptions.Add(setting.Item1); + } + else + { + setOFFOptions.Add(setting.Item1); + } + } + } + + SetSessionSettings(connection, setONOptions, "ON"); + SetSessionSettings(connection, setOFFOptions, "OFF"); + + } + + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2100:Review SQL queries for security vulnerabilities")] + private static void SetSessionSettings(IDbConnection connection, List sessionOptions, string onOff) + { + if (sessionOptions.Count > 0) + { + using (IDbCommand localCommand = connection.CreateCommand()) + { + StringBuilder builder = new StringBuilder("SET "); + for (int i = 0; i < sessionOptions.Count; i++) + { + if (i > 0) + { + builder.Append(','); + } + builder.Append(sessionOptions[i]); + } + builder.Append(" "); + builder.Append(onOff); + localCommand.CommandText = builder.ToString(); + localCommand.ExecuteNonQuery(); + } + } + } + + private int ExecuteNonQuery(IDbCommand command) + { + Tuple[] sessionSettings = null; + return _commandRetryPolicy.ExecuteAction(() => + { + VerifyConnectionOpen(command); + sessionSettings = CacheOrReplaySessionSettings(command, sessionSettings); + + return command.ExecuteNonQuery(); + }); + } + } +} + diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/Resources.cs b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/Resources.cs new file mode 100644 index 00000000..1885e53c --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/Resources.cs @@ -0,0 +1,157 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection +{ + /// + /// Contains string resources used throughout ReliableConnection code. + /// + internal static class Resources + { + internal static string AmbientSettingFormat + { + get + { + return "{0}: {1}"; + } + } + + internal static string ConnectionPassedToIsCloudShouldBeOpen + { + get + { + return "connection passed to IsCloud should be open."; + } + } + + internal static string ConnectionPropertyNotSet + { + get + { + return "Connection property has not been initialized."; + } + } + + internal static string ExceptionCannotBeRetried + { + get + { + return "Exception cannot be retried because of err #{0}:{1}"; + } + } + + internal static string ErrorParsingConnectionString + { + get + { + return "Error parsing connection string {0}"; + } + } + + internal static string FailedToCacheIsCloud + { + get + { + return "failed to cache the server property of IsAzure"; + } + } + + internal static string FailedToParseConnectionString + { + get + { + return "failed to parse the provided connection string: {0}"; + } + } + + internal static string IgnoreOnException + { + get + { + return "Retry number {0}. Ignoring Exception: {1}"; + } + } + + internal static string InvalidCommandType + { + get + { + return "Unsupported command object. Use SqlCommand or ReliableSqlCommand."; + } + } + + internal static string InvalidConnectionType + { + get + { + return "Unsupported connection object. Use SqlConnection or ReliableSqlConnection."; + } + } + + internal static string LoggingAmbientSettings + { + get + { + return "Logging Ambient Settings..."; + } + } + + internal static string Mode + { + get + { + return "Mode"; + } + } + + internal static string OnlyReliableConnectionSupported + { + get + { + return "Connection property can only be set to a value of type ReliableSqlConnection."; + } + } + + internal static string RetryOnException + { + get + { + return "Retry number {0}. Delaying {1} ms before next retry. Exception: {2}"; + } + } + + internal static string ThrottlingTypeInfo + { + get + { + return "ThrottlingTypeInfo"; + } + } + + internal static string UnableToAssignValue + { + get + { + return "Unable to assign the value of type {0} to {1}"; + } + } + + internal static string UnableToRetrieveAzureSessionId + { + get + { + return "Unable to retrieve Azure session-id."; + } + } + + internal static string ServerInfoCacheMiss + { + get + { + return "Server Info does not have the requested property in the cache"; + } + } + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryCallbackEventArgs.cs b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryCallbackEventArgs.cs new file mode 100644 index 00000000..f9b6a4a0 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryCallbackEventArgs.cs @@ -0,0 +1,61 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +// This code is copied from the source described in the comment below. + +// ======================================================================================= +// Microsoft Windows Server AppFabric Customer Advisory Team (CAT) Best Practices Series +// +// This sample is supplemental to the technical guidance published on the community +// blog at http://blogs.msdn.com/appfabriccat/ and copied from +// sqlmain ./sql/manageability/mfx/common/ +// +// ======================================================================================= +// Copyright © 2012 Microsoft Corporation. All rights reserved. +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER +// EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. YOU BEAR THE RISK OF USING IT. +// ======================================================================================= + +// namespace Microsoft.SQL.CAT.BestPractices.SqlAzure.Framework +// namespace Microsoft.SqlServer.Management.Common + +using System; + +namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection +{ + /// + /// Defines a arguments for event handler which will be invoked whenever a retry condition is encountered. + /// + internal sealed class RetryCallbackEventArgs : EventArgs + { + private readonly int _retryCount; + private readonly Exception _exception; + private readonly TimeSpan _delay; + + public RetryCallbackEventArgs(int retryCount, Exception exception, TimeSpan delay) + { + _retryCount = retryCount; + _exception = exception; + _delay = delay; + } + + public TimeSpan Delay + { + get { return _delay; } + } + + public Exception Exception + { + get { return _exception; } + } + + public int RetryCount + { + get { return _retryCount; } + } + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryLimitExceededException.cs b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryLimitExceededException.cs new file mode 100644 index 00000000..d08e91d0 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryLimitExceededException.cs @@ -0,0 +1,45 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +// This code is copied from the source described in the comment below. + +// ======================================================================================= +// Microsoft Windows Server AppFabric Customer Advisory Team (CAT) Best Practices Series +// +// This sample is supplemental to the technical guidance published on the community +// blog at http://blogs.msdn.com/appfabriccat/ and copied from +// sqlmain ./sql/manageability/mfx/common/ +// +// ======================================================================================= +// Copyright © 2012 Microsoft Corporation. All rights reserved. +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER +// EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. YOU BEAR THE RISK OF USING IT. +// ======================================================================================= + +// namespace Microsoft.SQL.CAT.BestPractices.SqlAzure.Framework +// namespace Microsoft.SqlServer.Management.Common + +using System; + +namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection +{ + /// + /// The special type of exception that provides managed exit from a retry loop. The user code can use this + /// exception to notify the retry policy that no further retry attempts are required. + /// + [Serializable] + internal sealed class RetryLimitExceededException : Exception + { + internal RetryLimitExceededException() : base() + { + } + + internal RetryLimitExceededException(string m, Exception e) : base(m, e) + { + } + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.DataTransferDetectionErrorStrategy.cs b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.DataTransferDetectionErrorStrategy.cs new file mode 100644 index 00000000..d8919182 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.DataTransferDetectionErrorStrategy.cs @@ -0,0 +1,43 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System.Data.SqlClient; +using Microsoft.SqlTools.Hosting.Utility; + +namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection +{ + internal abstract partial class RetryPolicy + { + /// + /// Provides the error detection logic for temporary faults that are commonly found during data transfer. + /// + internal class DataTransferErrorDetectionStrategy : ErrorDetectionStrategyBase, IErrorDetectionStrategy + { + private static readonly DataTransferErrorDetectionStrategy instance = new DataTransferErrorDetectionStrategy(); + + public static DataTransferErrorDetectionStrategy Instance + { + get { return instance; } + } + + protected override bool CanRetrySqlException(SqlException sqlException) + { + // Enumerate through all errors found in the exception. + foreach (SqlError err in sqlException.Errors) + { + RetryPolicyUtils.AppendThrottlingDataIfIsThrottlingError(sqlException, err); + if (RetryPolicyUtils.IsNonRetryableDataTransferError(err.Number)) + { + Logger.Instance.Write(LogLevel.Error, string.Format(Resources.ExceptionCannotBeRetried, err.Number, err.Message)); + return false; + } + } + + // Default is to treat all SqlException as retriable. + return true; + } + } + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.IErrorDetectionStrategy.cs b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.IErrorDetectionStrategy.cs new file mode 100644 index 00000000..9d9b36a6 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.IErrorDetectionStrategy.cs @@ -0,0 +1,97 @@ +// +// 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.Data.SqlClient; + +namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection +{ + internal abstract partial class RetryPolicy + { + public interface IErrorDetectionStrategy + { + /// + /// Determines whether the specified exception represents a temporary failure that can be compensated by a retry. + /// + /// The exception object to be verified. + /// True if the specified exception is considered as temporary, otherwise false. + bool CanRetry(Exception ex); + + /// + /// Determines whether the specified exception can be ignored. + /// + /// The exception object to be verified. + /// True if the specified exception is considered as non-harmful. + bool ShouldIgnoreError(Exception ex); + } + + /// + /// Base class with common retry logic. The core behavior for retrying non SqlExceptions is the same + /// across retry policies + /// + internal abstract class ErrorDetectionStrategyBase : IErrorDetectionStrategy + { + public bool CanRetry(Exception ex) + { + if (ex != null) + { + SqlException sqlException; + if ((sqlException = ex as SqlException) != null) + { + return CanRetrySqlException(sqlException); + } + if (ex is InvalidOperationException) + { + // Operations can throw this exception if the connection is killed before the write starts to the server + // However if there's an inner SqlException it may be a CLR load failure or other non-transient error + if (ex.InnerException != null + && ex.InnerException is SqlException) + { + return CanRetry(ex.InnerException); + } + return true; + } + if (ex is TimeoutException) + { + return true; + } + } + + return false; + } + + public bool ShouldIgnoreError(Exception ex) + { + if (ex != null) + { + SqlException sqlException; + if ((sqlException = ex as SqlException) != null) + { + return ShouldIgnoreSqlException(sqlException); + } + if (ex is InvalidOperationException) + { + // Operations can throw this exception if the connection is killed before the write starts to the server + // However if there's an inner SqlException it may be a CLR load failure or other non-transient error + if (ex.InnerException != null + && ex.InnerException is SqlException) + { + return ShouldIgnoreError(ex.InnerException); + } + } + } + + return false; + } + + protected virtual bool ShouldIgnoreSqlException(SqlException sqlException) + { + return false; + } + + protected abstract bool CanRetrySqlException(SqlException sqlException); + } + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.NetworkConnectivityErrorStrategy.cs b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.NetworkConnectivityErrorStrategy.cs new file mode 100644 index 00000000..1439405a --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.NetworkConnectivityErrorStrategy.cs @@ -0,0 +1,43 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System.Data.SqlClient; + +namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection +{ + internal abstract partial class RetryPolicy + { + /// + /// Provides the error detection logic for temporary faults that are commonly found in SQL Azure. + /// The same errors CAN occur on premise also, but they are not seen as often. + /// + internal sealed class NetworkConnectivityErrorDetectionStrategy : ErrorDetectionStrategyBase, IErrorDetectionStrategy + { + private static NetworkConnectivityErrorDetectionStrategy instance = new NetworkConnectivityErrorDetectionStrategy(); + + public static NetworkConnectivityErrorDetectionStrategy Instance + { + get { return instance; } + } + + protected override bool CanRetrySqlException(SqlException sqlException) + { + // Enumerate through all errors found in the exception. + bool foundRetryableError = false; + foreach (SqlError err in sqlException.Errors) + { + RetryPolicyUtils.AppendThrottlingDataIfIsThrottlingError(sqlException, err); + if (!RetryPolicyUtils.IsRetryableNetworkConnectivityError(err.Number)) + { + // If any error is not retryable then cannot retry + return false; + } + foundRetryableError = true; + } + return foundRetryableError; + } + } + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.SqlAzureTemporaryAndIgnorableErrorDetectionStrategy.cs b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.SqlAzureTemporaryAndIgnorableErrorDetectionStrategy.cs new file mode 100644 index 00000000..26b09015 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.SqlAzureTemporaryAndIgnorableErrorDetectionStrategy.cs @@ -0,0 +1,63 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System.Collections.Generic; +using System.Data.SqlClient; + +namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection +{ + internal abstract partial class RetryPolicy + { + /// + /// Provides the error detection logic for temporary faults that are commonly found in SQL Azure. + /// This strategy is similar to SqlAzureTemporaryErrorDetectionStrategy, but it exposes ways + /// to accept a certain exception and treat it as passing. + /// For example, if we are retrying, and we get a failure that an object already exists, we might + /// want to consider this as passing since the first execution that has timed out (or failed for some other temporary error) + /// might have managed to create the object. + /// + internal class SqlAzureTemporaryAndIgnorableErrorDetectionStrategy : ErrorDetectionStrategyBase, IErrorDetectionStrategy + { + /// + /// Azure error that can be ignored + /// + private readonly IList ignorableAzureErrors = null; + + public SqlAzureTemporaryAndIgnorableErrorDetectionStrategy(params int[] ignorableErrors) + { + this.ignorableAzureErrors = ignorableErrors; + } + + protected override bool CanRetrySqlException(SqlException sqlException) + { + // Enumerate through all errors found in the exception. + bool foundRetryableError = false; + foreach (SqlError err in sqlException.Errors) + { + RetryPolicyUtils.AppendThrottlingDataIfIsThrottlingError(sqlException, err); + if (!RetryPolicyUtils.IsRetryableAzureError(err.Number)) + { + return false; + } + + foundRetryableError = true; + } + return foundRetryableError; + } + + protected override bool ShouldIgnoreSqlException(SqlException sqlException) + { + int errorNumber = sqlException.Number; + + if (ignorableAzureErrors == null) + { + return false; + } + + return ignorableAzureErrors.Contains(errorNumber); + } + } + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.SqlAzureTemporaryErrorDetectionStrategy.cs b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.SqlAzureTemporaryErrorDetectionStrategy.cs new file mode 100644 index 00000000..fe45e77b --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.SqlAzureTemporaryErrorDetectionStrategy.cs @@ -0,0 +1,43 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System.Data.SqlClient; + +namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection +{ + internal abstract partial class RetryPolicy + { + /// + /// Provides the error detection logic for temporary faults that are commonly found in SQL Azure. + /// The same errors CAN occur on premise also, but they are not seen as often. + /// + internal sealed class SqlAzureTemporaryErrorDetectionStrategy : ErrorDetectionStrategyBase, IErrorDetectionStrategy + { + private static SqlAzureTemporaryErrorDetectionStrategy instance = new SqlAzureTemporaryErrorDetectionStrategy(); + + public static SqlAzureTemporaryErrorDetectionStrategy Instance + { + get { return instance; } + } + + protected override bool CanRetrySqlException(SqlException sqlException) + { + // Enumerate through all errors found in the exception. + bool foundRetryableError = false; + foreach (SqlError err in sqlException.Errors) + { + RetryPolicyUtils.AppendThrottlingDataIfIsThrottlingError(sqlException, err); + if (!RetryPolicyUtils.IsRetryableAzureError(err.Number)) + { + // If any error is not retryable then cannot retry + return false; + } + foundRetryableError = true; + } + return foundRetryableError; + } + } + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.ThrottleReason.cs b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.ThrottleReason.cs new file mode 100644 index 00000000..759236ef --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.ThrottleReason.cs @@ -0,0 +1,357 @@ +// +// 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.Data.SqlClient; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; + +namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection +{ + internal abstract partial class RetryPolicy + { + /// + /// Implements an object holding the decoded reason code returned from SQL Azure when encountering throttling conditions. + /// + [Serializable] + public class ThrottlingReason + { + /// + /// Returns the error number that corresponds to throttling conditions reported by SQL Azure. + /// + public const int ThrottlingErrorNumber = 40501; + + /// + /// Gets an unknown throttling condition in the event the actual throttling condition cannot be determined. + /// + public static ThrottlingReason Unknown + { + get + { + var unknownCondition = new ThrottlingReason() { ThrottlingMode = ThrottlingMode.Unknown }; + unknownCondition.throttledResources.Add(Tuple.Create(ThrottledResourceType.Unknown, ThrottlingType.Unknown)); + + return unknownCondition; + } + } + + /// + /// Maintains a collection of key-value pairs where a key is resource type and a value is the type of throttling applied to the given resource type. + /// + private readonly IList> throttledResources = new List>(9); + + /// + /// Provides a compiled regular expression used for extracting the reason code from the error message. + /// + private static readonly Regex sqlErrorCodeRegEx = new Regex(@"Code:\s*(\d+)", RegexOptions.IgnoreCase | RegexOptions.Compiled); + + /// + /// Gets the value that reflects the throttling mode in SQL Azure. + /// + public ThrottlingMode ThrottlingMode + { + get; + private set; + } + + /// + /// Gets the list of resources in SQL Azure that were subject to throttling conditions. + /// + public IEnumerable> ThrottledResources + { + get + { + return this.throttledResources; + } + } + + /// + /// Determines throttling conditions from the specified SQL exception. + /// + /// The object containing information relevant to an error returned by SQL Server when encountering throttling conditions. + /// An instance of the object holding the decoded reason codes returned from SQL Azure upon encountering throttling conditions. + public static ThrottlingReason FromException(SqlException ex) + { + if (ex != null) + { + foreach (SqlError error in ex.Errors) + { + if (error.Number == ThrottlingErrorNumber) + { + return FromError(error); + } + } + } + + return Unknown; + } + + /// + /// Determines the throttling conditions from the specified SQL error. + /// + /// The object containing information relevant to a warning or error returned by SQL Server. + /// An instance of the object holding the decoded reason codes returned from SQL Azure when encountering throttling conditions. + public static ThrottlingReason FromError(SqlError error) + { + if (error != null) + { + var match = sqlErrorCodeRegEx.Match(error.Message); + int reasonCode = 0; + + if (match.Success && Int32.TryParse(match.Groups[1].Value, out reasonCode)) + { + return FromReasonCode(reasonCode); + } + } + + return Unknown; + } + + /// + /// Determines the throttling conditions from the specified reason code. + /// + /// The reason code returned by SQL Azure which contains the throttling mode and the exceeded resource types. + /// An instance of the object holding the decoded reason codes returned from SQL Azure when encountering throttling conditions. + public static ThrottlingReason FromReasonCode(int reasonCode) + { + if (reasonCode > 0) + { + // Decode throttling mode from the last 2 bits. + ThrottlingMode throttlingMode = (ThrottlingMode)(reasonCode & 3); + + var condition = new ThrottlingReason() { ThrottlingMode = throttlingMode }; + + // Shift 8 bits to truncate throttling mode. + int groupCode = reasonCode >> 8; + + // Determine throttling type for all well-known resources that may be subject to throttling conditions. + condition.throttledResources.Add(Tuple.Create(ThrottledResourceType.PhysicalDatabaseSpace, (ThrottlingType)(groupCode & 3))); + condition.throttledResources.Add(Tuple.Create(ThrottledResourceType.PhysicalLogSpace, (ThrottlingType)((groupCode = groupCode >> 2) & 3))); + condition.throttledResources.Add(Tuple.Create(ThrottledResourceType.LogWriteIODelay, (ThrottlingType)((groupCode = groupCode >> 2) & 3))); + condition.throttledResources.Add(Tuple.Create(ThrottledResourceType.DataReadIODelay, (ThrottlingType)((groupCode = groupCode >> 2) & 3))); + condition.throttledResources.Add(Tuple.Create(ThrottledResourceType.CPU, (ThrottlingType)((groupCode = groupCode >> 2) & 3))); + condition.throttledResources.Add(Tuple.Create(ThrottledResourceType.DatabaseSize, (ThrottlingType)((groupCode = groupCode >> 2) & 3))); + condition.throttledResources.Add(Tuple.Create(ThrottledResourceType.Internal, (ThrottlingType)((groupCode = groupCode >> 2) & 3))); + condition.throttledResources.Add(Tuple.Create(ThrottledResourceType.WorkerThreads, (ThrottlingType)((groupCode = groupCode >> 2) & 3))); + condition.throttledResources.Add(Tuple.Create(ThrottledResourceType.Internal, (ThrottlingType)((groupCode = groupCode >> 2) & 3))); + + return condition; + } + else + { + return Unknown; + } + } + + /// + /// Gets a value indicating whether physical data file space throttling was reported by SQL Azure. + /// + public bool IsThrottledOnDataSpace + { + get + { + return this.throttledResources.Where(x => x.Item1 == ThrottledResourceType.PhysicalDatabaseSpace).Count() > 0; + } + } + + /// + /// Gets a value indicating whether physical log space throttling was reported by SQL Azure. + /// + public bool IsThrottledOnLogSpace + { + get + { + return this.throttledResources.Where(x => x.Item1 == ThrottledResourceType.PhysicalLogSpace).Count() > 0; + } + } + + /// + /// Gets a value indicating whether transaction activity throttling was reported by SQL Azure. + /// + public bool IsThrottledOnLogWrite + { + get { return this.throttledResources.Where(x => x.Item1 == ThrottledResourceType.LogWriteIODelay).Count() > 0; } + } + + /// + /// Gets a value indicating whether data read activity throttling was reported by SQL Azure. + /// + public bool IsThrottledOnDataRead + { + get { return this.throttledResources.Where(x => x.Item1 == ThrottledResourceType.DataReadIODelay).Count() > 0; } + } + + /// + /// Gets a value indicating whether CPU throttling was reported by SQL Azure. + /// + public bool IsThrottledOnCPU + { + get { return this.throttledResources.Where(x => x.Item1 == ThrottledResourceType.CPU).Count() > 0; } + } + + /// + /// Gets a value indicating whether database size throttling was reported by SQL Azure. + /// + public bool IsThrottledOnDatabaseSize + { + get { return this.throttledResources.Where(x => x.Item1 == ThrottledResourceType.DatabaseSize).Count() > 0; } + } + + /// + /// Gets a value indicating whether concurrent requests throttling was reported by SQL Azure. + /// + public bool IsThrottledOnWorkerThreads + { + get { return this.throttledResources.Where(x => x.Item1 == ThrottledResourceType.WorkerThreads).Count() > 0; } + } + + /// + /// Gets a value indicating whether throttling conditions were not determined with certainty. + /// + public bool IsUnknown + { + get { return ThrottlingMode == ThrottlingMode.Unknown; } + } + + /// + /// Returns a textual representation the current ThrottlingReason object including the information held with respect to throttled resources. + /// + /// A string that represents the current ThrottlingReason object. + public override string ToString() + { + StringBuilder result = new StringBuilder(); + + result.AppendFormat(Resources.Mode, ThrottlingMode); + + var resources = this.throttledResources.Where(x => x.Item1 != ThrottledResourceType.Internal). + Select, string>(x => String.Format(CultureInfo.CurrentCulture, Resources.ThrottlingTypeInfo, x.Item1, x.Item2)). + OrderBy(x => x).ToArray(); + + result.Append(String.Join(", ", resources)); + + return result.ToString(); + } + } + + #region ThrottlingMode enumeration + /// + /// Defines the possible throttling modes in SQL Azure. + /// + public enum ThrottlingMode + { + /// + /// Corresponds to "No Throttling" throttling mode whereby all SQL statements can be processed. + /// + NoThrottling = 0, + + /// + /// Corresponds to "Reject Update / Insert" throttling mode whereby SQL statements such as INSERT, UPDATE, CREATE TABLE and CREATE INDEX are rejected. + /// + RejectUpdateInsert = 1, + + /// + /// Corresponds to "Reject All Writes" throttling mode whereby SQL statements such as INSERT, UPDATE, DELETE, CREATE, DROP are rejected. + /// + RejectAllWrites = 2, + + /// + /// Corresponds to "Reject All" throttling mode whereby all SQL statements are rejected. + /// + RejectAll = 3, + + /// + /// Corresponds to an unknown throttling mode whereby throttling mode cannot be determined with certainty. + /// + Unknown = -1 + } + #endregion + + #region ThrottlingType enumeration + /// + /// Defines the possible throttling types in SQL Azure. + /// + public enum ThrottlingType + { + /// + /// Indicates that no throttling was applied to a given resource. + /// + None = 0, + + /// + /// Corresponds to a Soft throttling type. Soft throttling is applied when machine resources such as, CPU, IO, storage, and worker threads exceed + /// predefined safety thresholds despite the load balancer’s best efforts. + /// + Soft = 1, + + /// + /// Corresponds to a Hard throttling type. Hard throttling is applied when the machine is out of resources, for example storage space. + /// With hard throttling, no new connections are allowed to the databases hosted on the machine until resources are freed up. + /// + Hard = 2, + + /// + /// Corresponds to an unknown throttling type in the event when the throttling type cannot be determined with certainty. + /// + Unknown = 3 + } + #endregion + + #region ThrottledResourceType enumeration + /// + /// Defines the types of resources in SQL Azure which may be subject to throttling conditions. + /// + public enum ThrottledResourceType + { + /// + /// Corresponds to "Physical Database Space" resource which may be subject to throttling. + /// + PhysicalDatabaseSpace = 0, + + /// + /// Corresponds to "Physical Log File Space" resource which may be subject to throttling. + /// + PhysicalLogSpace = 1, + + /// + /// Corresponds to "Transaction Log Write IO Delay" resource which may be subject to throttling. + /// + LogWriteIODelay = 2, + + /// + /// Corresponds to "Database Read IO Delay" resource which may be subject to throttling. + /// + DataReadIODelay = 3, + + /// + /// Corresponds to "CPU" resource which may be subject to throttling. + /// + CPU = 4, + + /// + /// Corresponds to "Database Size" resource which may be subject to throttling. + /// + DatabaseSize = 5, + + /// + /// Corresponds to "SQL Worker Thread Pool" resource which may be subject to throttling. + /// + WorkerThreads = 7, + + /// + /// Corresponds to an internal resource which may be subject to throttling. + /// + Internal = 6, + + /// + /// Corresponds to an unknown resource type in the event when the actual resource cannot be determined with certainty. + /// + Unknown = -1 + } + #endregion + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.cs b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.cs new file mode 100644 index 00000000..37c4fc64 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.cs @@ -0,0 +1,542 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +// This code is copied from the source described in the comment below. + +// ======================================================================================= +// Microsoft Windows Server AppFabric Customer Advisory Team (CAT) Best Practices Series +// +// This sample is supplemental to the technical guidance published on the community +// blog at http://blogs.msdn.com/appfabriccat/ and copied from +// sqlmain ./sql/manageability/mfx/common/ +// +// ======================================================================================= +// Copyright © 2012 Microsoft Corporation. All rights reserved. +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER +// EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. YOU BEAR THE RISK OF USING IT. +// ======================================================================================= + +// namespace Microsoft.SQL.CAT.BestPractices.SqlAzure.Framework +// namespace Microsoft.SqlServer.Management.Common + +using System; +using System.Data.SqlClient; +using System.Diagnostics; +using System.Diagnostics.Contracts; +using System.Globalization; +using System.Threading; +using Microsoft.SqlTools.Hosting.Utility; + +namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection +{ + /// + /// Implements a policy defining and implementing the retry mechanism for unreliable actions. + /// + internal abstract partial class RetryPolicy + { + /// + /// Defines a callback delegate which will be invoked whenever a retry condition is encountered. + /// + /// The state of current retry attempt. + internal delegate void RetryCallbackDelegate(RetryState retryState); + + /// + /// Defines a callback delegate which will be invoked whenever an error is ignored on retry. + /// + /// The state of current retry attempt. + internal delegate void IgnoreErrorCallbackDelegate(RetryState retryState); + + private readonly IErrorDetectionStrategy _errorDetectionStrategy; + + protected RetryPolicy(IErrorDetectionStrategy strategy) + { + Contract.Assert(strategy != null); + + _errorDetectionStrategy = strategy; + this.FastFirstRetry = true; + + //TODO Defect 1078447 Validate whether CommandTimeout needs to be used differently in schema/data scenarios + this.CommandTimeoutInSeconds = AmbientSettings.LongRunningQueryTimeoutSeconds; + } + + /// + /// An instance of a callback delegate which will be invoked whenever a retry condition is encountered. + /// + public event RetryCallbackDelegate RetryOccurred; + + /// + /// An instance of a callback delegate which will be invoked whenever an error is ignored on retry. + /// + public event IgnoreErrorCallbackDelegate IgnoreErrorOccurred; + + /// + /// Gets or sets a value indicating whether or not the very first retry attempt will be made immediately + /// whereas the subsequent retries will remain subject to retry interval. + /// + public bool FastFirstRetry { get; set; } + + /// + /// Gets or sets the timeout in seconds of sql commands + /// + public int CommandTimeoutInSeconds + { + get; + set; + } + + /// + /// Gets the error detection strategy of this retry policy + /// + internal IErrorDetectionStrategy ErrorDetectionStrategy + { + get + { + return _errorDetectionStrategy; + } + } + + /// + /// We should only ignore errors if they happen after the first retry. + /// This flag is used to allow the ignore even on first try, for testing purposes. + /// + /// + /// This flag is currently being used for TESTING PURPOSES ONLY. + /// + internal bool ShouldIgnoreOnFirstTry + { + get; + set; + } + + protected static bool IsLessThanMaxRetryCount(int currentRetryCount, int maxRetryCount) + { + return currentRetryCount <= maxRetryCount; + } + + /// + /// Repetitively executes the specified action while it satisfies the current retry policy. + /// + /// A delegate representing the executable action which doesn't return any results. + /// Cancellation token to cancel action between retries. + public void ExecuteAction(Action action, CancellationToken? token = null) + { + ExecuteAction( + _ => action(), token); + } + + /// + /// Repetitively executes the specified action while it satisfies the current retry policy. + /// + /// A delegate representing the executable action which doesn't return any results. + /// Cancellation token to cancel action between retries. + public void ExecuteAction(Action action, CancellationToken? token = null) + { + ExecuteAction( + retryState => + { + action(retryState); + return null; + }, token); + } + + /// + /// Repetitively executes the specified action while it satisfies the current retry policy. + /// + /// The type of result expected from the executable action. + /// A delegate representing the executable action which returns the result of type T. + /// Cancellation token to cancel action between retries. + /// The result from the action. + public T ExecuteAction(Func func, CancellationToken? token = null) + { + return ExecuteAction( + _ => func(), token); + } + + /// + /// Repetitively executes the specified action while it satisfies the current retry policy. + /// + /// The type of result expected from the executable action. + /// A delegate representing the executable action which returns the result of type R. + /// Cancellation token to cancel action between retries. + /// The result from the action. + public R ExecuteAction(Func func, CancellationToken? token = null) + { + RetryState retryState = CreateRetryState(); + + if (token != null) + { + token.Value.ThrowIfCancellationRequested(); + } + + while (true) + { + try + { + return func(retryState); + } + catch (RetryLimitExceededException limitExceededEx) + { + // The user code can throw a RetryLimitExceededException to force the exit from the retry loop. + // The RetryLimitExceeded exception can have an inner exception attached to it. This is the exception + // which we will have to throw up the stack so that callers can handle it. + if (limitExceededEx.InnerException != null) + { + throw limitExceededEx.InnerException; + } + + return default(R); + } + catch (Exception ex) + { + retryState.LastError = ex; + + if (retryState.RetryCount > 0 || this.ShouldIgnoreOnFirstTry) + { + // If we can ignore this error, then break out of the loop and consider this execution as passing + // We return the default value for the type R + if (ShouldIgnoreError(retryState)) + { + OnIgnoreErrorOccurred(retryState); + return default(R); + } + } + + retryState.RetryCount++; + + if (!ShouldRetry(retryState)) + { + throw; + } + } + + OnRetryOccurred(retryState); + + if ((retryState.RetryCount > 1 || !FastFirstRetry) && !retryState.IsDelayDisabled) + { + Thread.Sleep(retryState.Delay); + } + + // check for cancellation after delay. + if (token != null) + { + token.Value.ThrowIfCancellationRequested(); + } + } + } + + protected virtual RetryState CreateRetryState() + { + return new RetryState(); + } + + public bool IsRetryableException(Exception ex) + { + return ErrorDetectionStrategy.CanRetry(ex); + } + + public bool ShouldRetry(RetryState retryState) + { + bool canRetry = ErrorDetectionStrategy.CanRetry(retryState.LastError); + bool shouldRetry = canRetry + && ShouldRetryImpl(retryState); + + Logger.Instance.Write(LogLevel.Error, + string.Format( + CultureInfo.InvariantCulture, + "Retry requested: Retry count = {0}. Delay = {1}, SQL Error Number = {2}, Can retry error = {3}, Will retry = {4}", + retryState.RetryCount, + retryState.Delay, + GetErrorNumber(retryState.LastError), + canRetry, + shouldRetry)); + + // Perform an extra check in the delay interval. Should prevent from accidentally ending up with the value of -1 which will block a thread indefinitely. + // In addition, any other negative numbers will cause an ArgumentOutOfRangeException fault which will be thrown by Thread.Sleep. + if (retryState.Delay.TotalMilliseconds < 0) + { + retryState.Delay = TimeSpan.Zero; + } + return shouldRetry; + } + + public bool ShouldIgnoreError(RetryState retryState) + { + bool shouldIgnoreError = ErrorDetectionStrategy.ShouldIgnoreError(retryState.LastError); + + Logger.Instance.Write(LogLevel.Error, + string.Format( + CultureInfo.InvariantCulture, + "Ignore Error requested: Retry count = {0}. Delay = {1}, SQL Error Number = {2}, Should Ignore Error = {3}", + retryState.RetryCount, + retryState.Delay, + GetErrorNumber(retryState.LastError), + shouldIgnoreError)); + + return shouldIgnoreError; + } + + /* TODO - Error code does not exist in SqlException for .NET Core + private static int? GetErrorCode(Exception ex) + { + SqlException sqlEx= ex as SqlException; + if (sqlEx == null) + { + return null; + } + + return sqlEx.ErrorCode; + } + */ + + internal static int? GetErrorNumber(Exception ex) + { + SqlException sqlEx = ex as SqlException; + if (sqlEx == null) + { + return null; + } + + return sqlEx.Number; + } + + protected abstract bool ShouldRetryImpl(RetryState retryState); + + /// + /// Notifies the subscribers whenever a retry condition is encountered. + /// + /// The state of current retry attempt. + protected virtual void OnRetryOccurred(RetryState retryState) + { + var retryOccurred = RetryOccurred; + if (retryOccurred != null) + { + retryOccurred(retryState); + } + } + + /// + /// Notifies the subscribers whenever an error is ignored on retry. + /// + /// The state of current retry attempt. + protected virtual void OnIgnoreErrorOccurred(RetryState retryState) + { + var ignoreErrorOccurred = IgnoreErrorOccurred; + if (ignoreErrorOccurred != null) + { + ignoreErrorOccurred(retryState); + } + } + + internal class FixedDelayPolicy : RetryPolicy + { + private readonly int _maxRetryCount; + private readonly TimeSpan _intervalBetweenRetries; + + /// + /// Constructs a new instance of the TRetryPolicy class with the specified number of retry attempts and time interval between retries. + /// + /// The to use when checking whether an error is retryable + /// The max number of retry attempts. Should be 1-indexed. + /// The interval between retries. + public FixedDelayPolicy(IErrorDetectionStrategy strategy, int maxRetryCount, TimeSpan intervalBetweenRetries) + : base(strategy) + { + Contract.Assert(maxRetryCount >= 0, "maxRetryCount cannot be a negative number"); + Contract.Assert(intervalBetweenRetries.Ticks >= 0, "intervalBetweenRetries cannot be negative"); + + _maxRetryCount = maxRetryCount; + _intervalBetweenRetries = intervalBetweenRetries; + } + + protected override bool ShouldRetryImpl(RetryState retryState) + { + Contract.Assert(retryState != null); + + if (IsLessThanMaxRetryCount(retryState.RetryCount, _maxRetryCount)) + { + retryState.Delay = _intervalBetweenRetries; + return true; + } + + retryState.Delay = TimeSpan.Zero; + return false; + } + } + + internal class ProgressiveRetryPolicy : RetryPolicy + { + private readonly int _maxRetryCount; + private readonly TimeSpan _initialInterval; + private readonly TimeSpan _increment; + + /// + /// Constructs a new instance of the TRetryPolicy class with the specified number of retry attempts and parameters defining the progressive delay between retries. + /// + /// The to use when checking whether an error is retryable + /// The maximum number of retry attempts. Should be 1-indexed. + /// The initial interval which will apply for the first retry. + /// The incremental time value which will be used for calculating the progressive delay between retries. + public ProgressiveRetryPolicy(IErrorDetectionStrategy strategy, int maxRetryCount, TimeSpan initialInterval, TimeSpan increment) + : base(strategy) + { + Contract.Assert(maxRetryCount >= 0, "maxRetryCount cannot be a negative number"); + Contract.Assert(initialInterval.Ticks >= 0, "retryInterval cannot be negative"); + Contract.Assert(increment.Ticks >= 0, "retryInterval cannot be negative"); + + _maxRetryCount = maxRetryCount; + _initialInterval = initialInterval; + _increment = increment; + } + + protected override bool ShouldRetryImpl(RetryState retryState) + { + Contract.Assert(retryState != null); + + if (IsLessThanMaxRetryCount(retryState.RetryCount, _maxRetryCount)) + { + retryState.Delay = TimeSpan.FromMilliseconds(_initialInterval.TotalMilliseconds + (_increment.TotalMilliseconds * (retryState.RetryCount - 1))); + return true; + } + + retryState.Delay = TimeSpan.Zero; + return false; + } + } + + internal class ExponentialDelayRetryPolicy : RetryPolicy + { + private readonly int _maxRetryCount; + private readonly double _intervalFactor; + private readonly TimeSpan _minInterval; + private readonly TimeSpan _maxInterval; + + /// + /// Constructs a new instance of the TRetryPolicy class with the specified number of retry attempts and parameters defining the progressive delay between retries. + /// + /// The to use when checking whether an error is retryable + /// The maximum number of retry attempts. + /// Controls the speed at which the delay increases - the retryCount is raised to this power as + /// part of the function + /// Minimum interval between retries. The basis for all backoff calculations + /// Maximum interval between retries. Backoff will not take longer than this period. + public ExponentialDelayRetryPolicy(IErrorDetectionStrategy strategy, int maxRetryCount, double intervalFactor, TimeSpan minInterval, TimeSpan maxInterval) + : base(strategy) + { + Contract.Assert(maxRetryCount >= 0, "maxRetryCount cannot be a negative number"); + Contract.Assert(intervalFactor > 1, "intervalFactor Must be > 1 so that the delay increases exponentially"); + Contract.Assert(minInterval.Ticks >= 0, "minInterval cannot be negative"); + Contract.Assert(maxInterval.Ticks >= 0, "maxInterval cannot be negative"); + Contract.Assert(maxInterval.Ticks >= minInterval.Ticks, "maxInterval must be greater than minInterval"); + + _maxRetryCount = maxRetryCount; + _intervalFactor = intervalFactor; + _minInterval = minInterval; + _maxInterval = maxInterval; + } + + protected override bool ShouldRetryImpl(RetryState retryState) + { + Contract.Assert(retryState != null); + + if (IsLessThanMaxRetryCount(retryState.RetryCount, _maxRetryCount)) + { + retryState.Delay = RetryPolicyUtils.CalcExponentialRetryDelay(retryState.RetryCount, _intervalFactor, _minInterval, _maxInterval); + return true; + } + + retryState.Delay = TimeSpan.Zero; + return false; + } + } + + internal class TimeBasedRetryPolicy : RetryPolicy + { + private readonly TimeSpan _minTotalRetryTimeLimit; + private readonly TimeSpan _maxTotalRetryTimeLimit; + private readonly double _totalRetryTimeLimitRate; + + private readonly TimeSpan _minInterval; + private readonly TimeSpan _maxInterval; + private readonly double _intervalFactor; + + private readonly Stopwatch _stopwatch; + + public TimeBasedRetryPolicy( + IErrorDetectionStrategy strategy, + TimeSpan minTotalRetryTimeLimit, + TimeSpan maxTotalRetryTimeLimit, + double totalRetryTimeLimitRate, + TimeSpan minInterval, + TimeSpan maxInterval, + double intervalFactor) + : base(strategy) + { + Contract.Assert(minTotalRetryTimeLimit.Ticks >= 0); + Contract.Assert(maxTotalRetryTimeLimit.Ticks >= minTotalRetryTimeLimit.Ticks); + Contract.Assert(totalRetryTimeLimitRate >= 0); + + Contract.Assert(minInterval.Ticks >= 0); + Contract.Assert(maxInterval.Ticks >= minInterval.Ticks); + Contract.Assert(intervalFactor >= 1); + + _minTotalRetryTimeLimit = minTotalRetryTimeLimit; + _maxTotalRetryTimeLimit = maxTotalRetryTimeLimit; + _totalRetryTimeLimitRate = totalRetryTimeLimitRate; + + _minInterval = minInterval; + _maxInterval = maxInterval; + _intervalFactor = intervalFactor; + + _stopwatch = Stopwatch.StartNew(); + } + + protected override bool ShouldRetryImpl(RetryState retryStateObj) + { + Contract.Assert(retryStateObj is RetryStateEx); + RetryStateEx retryState = (RetryStateEx)retryStateObj; + + // Calculate the delay as exponential value based on the number of retries. + retryState.Delay = + RetryPolicyUtils.CalcExponentialRetryDelay( + retryState.RetryCount, + _intervalFactor, + _minInterval, + _maxInterval); + + // Add the delay to the total retry time + retryState.TotalRetryTime = retryState.TotalRetryTime + retryState.Delay; + + // Calculate the maximum total retry time depending on how long ago was the task (this retry policy) started. + // Longer running tasks are less eager to abort since, more work is has been done. + TimeSpan totalRetryTimeLimit = checked(TimeSpan.FromMilliseconds( + Math.Max( + Math.Min( + _stopwatch.ElapsedMilliseconds * _totalRetryTimeLimitRate, + _maxTotalRetryTimeLimit.TotalMilliseconds), + _minTotalRetryTimeLimit.TotalMilliseconds))); + + if (retryState.TotalRetryTime <= totalRetryTimeLimit) + { + return true; + } + + retryState.Delay = TimeSpan.Zero; + return false; + } + + protected override RetryState CreateRetryState() + { + return new RetryStateEx { TotalRetryTime = TimeSpan.Zero }; + } + + internal sealed class RetryStateEx : RetryState + { + public TimeSpan TotalRetryTime { get; set; } + } + } + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicyFactory.cs b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicyFactory.cs new file mode 100644 index 00000000..ce6fda81 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicyFactory.cs @@ -0,0 +1,459 @@ +// +// 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.Diagnostics; +using System.Globalization; +using Microsoft.SqlTools.Hosting.Utility; + +namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection +{ + internal sealed class RetryPolicyDefaults + { + /// + /// The default number of retry attempts. + /// + public const int DefaulSchemaRetryCount = 6; + + /// + /// The default number of retry attempts for create database. + /// + public const int DefaultCreateDatabaseRetryCount = 5; + + /// + /// The default amount of time defining an interval between retries. + /// + public static readonly TimeSpan DefaultSchemaMinInterval = TimeSpan.FromSeconds(2.75); + + /// + /// The default factor to use when determining exponential backoff between retries. + /// + public const double DefaultBackoffIntervalFactor = 2.0; + + /// + /// The default maximum time between retries. + /// + public static readonly TimeSpan DefaultMaxRetryInterval = TimeSpan.FromSeconds(60); + + /// + /// The default number of retry attempts. + /// + public static readonly int DefaultDataCommandRetryCount = 5; + + /// + /// The default number of retry attempts for a connection related error + /// + public static readonly int DefaultConnectionRetryCount = 6; + + /// + /// The default amount of time defining an interval between retries. + /// + public static readonly TimeSpan DefaultDataMinInterval = TimeSpan.FromSeconds(1.0); + + /// + /// The default amount of time defining a time increment between retry attempts in the progressive delay policy. + /// + public static readonly TimeSpan DefaultProgressiveRetryIncrement = TimeSpan.FromMilliseconds(500); + } + + /// + /// Implements a collection of the RetryPolicyInfo elements holding retry policy settings. + /// + internal sealed class RetryPolicyFactory + { + /// + /// Returns a default policy that does no retries, it just invokes action exactly once. + /// + public static readonly RetryPolicy NoRetryPolicy = RetryPolicyFactory.CreateNoRetryPolicy(); + + /// + /// Returns a default policy that does no retries, it just invokes action exactly once. + /// + public static readonly RetryPolicy PrimaryKeyViolationRetryPolicy = RetryPolicyFactory.CreatePrimaryKeyCommandRetryPolicy(); + + /// + /// Implements a strategy that ignores any transient errors. + /// Internal for testing purposes only + /// + internal sealed class TransientErrorIgnoreStrategy : RetryPolicy.IErrorDetectionStrategy + { + private static readonly TransientErrorIgnoreStrategy _instance = new TransientErrorIgnoreStrategy(); + + public static TransientErrorIgnoreStrategy Instance + { + get { return _instance; } + } + + public bool CanRetry(Exception ex) + { + return false; + } + + public bool ShouldIgnoreError(Exception ex) + { + return false; + } + } + + /// + /// Creates and returns a default Retry Policy for Schema based operations. + /// + /// An instance of class. + internal static RetryPolicy CreateDefaultSchemaCommandRetryPolicy(bool useRetry, int retriesPerPhase = RetryPolicyDefaults.DefaulSchemaRetryCount) + { + RetryPolicy policy; + + if (useRetry) + { + policy = new RetryPolicy.ExponentialDelayRetryPolicy( + RetryPolicy.SqlAzureTemporaryErrorDetectionStrategy.Instance, + retriesPerPhase, + RetryPolicyDefaults.DefaultBackoffIntervalFactor, + RetryPolicyDefaults.DefaultSchemaMinInterval, + RetryPolicyDefaults.DefaultMaxRetryInterval); + policy.FastFirstRetry = false; + } + else + { + policy = CreateNoRetryPolicy(); + } + + return policy; + } + + /// + /// Creates and returns a default Retry Policy for Schema based connection operations. + /// + /// The RetryOccured event is wired to raise an RaiseAmbientRetryMessage message for a connection retry. + /// An instance of class. + internal static RetryPolicy CreateSchemaConnectionRetryPolicy(int retriesPerPhase) + { + RetryPolicy policy = new RetryPolicy.ExponentialDelayRetryPolicy( + RetryPolicy.SqlAzureTemporaryErrorDetectionStrategy.Instance, + retriesPerPhase, + RetryPolicyDefaults.DefaultBackoffIntervalFactor, + RetryPolicyDefaults.DefaultSchemaMinInterval, + RetryPolicyDefaults.DefaultMaxRetryInterval); + policy.RetryOccurred += DataConnectionFailureRetry; + return policy; + } + + /// + /// Creates and returns a default Retry Policy for Schema based command operations. + /// + /// The RetryOccured event is wired to raise an RaiseAmbientRetryMessage message for a command retry. + /// An instance of class. + internal static RetryPolicy CreateSchemaCommandRetryPolicy(int retriesPerPhase) + { + RetryPolicy policy = new RetryPolicy.ExponentialDelayRetryPolicy( + RetryPolicy.SqlAzureTemporaryErrorDetectionStrategy.Instance, + retriesPerPhase, + RetryPolicyDefaults.DefaultBackoffIntervalFactor, + RetryPolicyDefaults.DefaultSchemaMinInterval, + RetryPolicyDefaults.DefaultMaxRetryInterval); + policy.FastFirstRetry = false; + policy.RetryOccurred += CommandFailureRetry; + return policy; + } + + /// + /// Creates and returns a Retry Policy for database creation operations. + /// + /// Errors to ignore if they occur after first retry + /// + /// The RetryOccured event is wired to raise an RaiseAmbientRetryMessage message for a command retry. + /// The IgnoreErrorOccurred event is wired to raise an RaiseAmbientIgnoreMessage message for ignore. + /// + /// An instance of class. + internal static RetryPolicy CreateDatabaseCommandRetryPolicy(params int[] ignorableErrorNumbers) + { + RetryPolicy.SqlAzureTemporaryAndIgnorableErrorDetectionStrategy errorDetectionStrategy = + new RetryPolicy.SqlAzureTemporaryAndIgnorableErrorDetectionStrategy(ignorableErrorNumbers); + + // 30, 60, 60, 60, 60 second retries + RetryPolicy policy = new RetryPolicy.ExponentialDelayRetryPolicy( + errorDetectionStrategy, + RetryPolicyDefaults.DefaultCreateDatabaseRetryCount /* maxRetryCount */, + RetryPolicyDefaults.DefaultBackoffIntervalFactor, + TimeSpan.FromSeconds(30) /* minInterval */, + TimeSpan.FromSeconds(60) /* maxInterval */); + + policy.FastFirstRetry = false; + policy.RetryOccurred += CreateDatabaseCommandFailureRetry; + policy.IgnoreErrorOccurred += CreateDatabaseCommandFailureIgnore; + + return policy; + } + + /// + /// Creates and returns an "ignoreable" command Retry Policy. + /// + /// Errors to ignore if they occur after first retry + /// + /// The RetryOccured event is wired to raise an RaiseAmbientRetryMessage message for a command retry. + /// The IgnoreErrorOccurred event is wired to raise an RaiseAmbientIgnoreMessage message for ignore. + /// + /// An instance of class. + internal static RetryPolicy CreateElementCommandRetryPolicy(params int[] ignorableErrorNumbers) + { + Debug.Assert(ignorableErrorNumbers != null); + + RetryPolicy.SqlAzureTemporaryAndIgnorableErrorDetectionStrategy errorDetectionStrategy = + new RetryPolicy.SqlAzureTemporaryAndIgnorableErrorDetectionStrategy(ignorableErrorNumbers); + + RetryPolicy policy = new RetryPolicy.ExponentialDelayRetryPolicy( + errorDetectionStrategy, + RetryPolicyDefaults.DefaulSchemaRetryCount, + RetryPolicyDefaults.DefaultBackoffIntervalFactor, + RetryPolicyDefaults.DefaultSchemaMinInterval, + RetryPolicyDefaults.DefaultMaxRetryInterval); + + policy.FastFirstRetry = false; + policy.RetryOccurred += ElementCommandFailureRetry; + policy.IgnoreErrorOccurred += ElementCommandFailureIgnore; + + return policy; + } + + /// + /// Creates and returns an "primary key violation" command Retry Policy. + /// + /// Errors to ignore if they occur after first retry + /// + /// The RetryOccured event is wired to raise an RaiseAmbientRetryMessage message for a command retry. + /// The IgnoreErrorOccurred event is wired to raise an RaiseAmbientIgnoreMessage message for ignore. + /// + /// An instance of class. + internal static RetryPolicy CreatePrimaryKeyCommandRetryPolicy() + { + RetryPolicy.SqlAzureTemporaryAndIgnorableErrorDetectionStrategy errorDetectionStrategy = + new RetryPolicy.SqlAzureTemporaryAndIgnorableErrorDetectionStrategy(SqlErrorNumbers.PrimaryKeyViolationErrorNumber); + + RetryPolicy policy = new RetryPolicy.ExponentialDelayRetryPolicy( + errorDetectionStrategy, + RetryPolicyDefaults.DefaulSchemaRetryCount, + RetryPolicyDefaults.DefaultBackoffIntervalFactor, + RetryPolicyDefaults.DefaultSchemaMinInterval, + RetryPolicyDefaults.DefaultMaxRetryInterval); + + policy.FastFirstRetry = true; + policy.RetryOccurred += CommandFailureRetry; + policy.IgnoreErrorOccurred += CommandFailureIgnore; + + return policy; + } + + /// + /// Creates a Policy that will never allow retries to occur. + /// + /// + public static RetryPolicy CreateNoRetryPolicy() + { + return new RetryPolicy.FixedDelayPolicy(TransientErrorIgnoreStrategy.Instance, 0, TimeSpan.Zero); + } + + /// + /// Creates a Policy that is optimized for data-related script update operations. + /// This is extremely error tolerant and uses a Time based delay policy that backs + /// off until some overall length of delay has occurred. It is not as long-running + /// as the ConnectionManager data transfer retry policy since that's intended for bulk upload + /// of large amounts of data, whereas this is for individual batch scripts executed by the + /// batch execution engine. + /// + /// + public static RetryPolicy CreateDataScriptUpdateRetryPolicy() + { + return new RetryPolicy.TimeBasedRetryPolicy( + RetryPolicy.DataTransferErrorDetectionStrategy.Instance, + TimeSpan.FromMinutes(7), + TimeSpan.FromMinutes(7), + 0.1, + TimeSpan.FromMilliseconds(250), + TimeSpan.FromSeconds(30), + 1.5); + } + + /// + /// Returns the default retry policy dedicated to handling exceptions with SQL connections + /// + /// The RetryPolicy policy + public static RetryPolicy CreateFastDataRetryPolicy() + { + RetryPolicy retryPolicy = new RetryPolicy.FixedDelayPolicy( + RetryPolicy.NetworkConnectivityErrorDetectionStrategy.Instance, + RetryPolicyDefaults.DefaultDataCommandRetryCount, + TimeSpan.FromMilliseconds(5)); + + retryPolicy.FastFirstRetry = true; + retryPolicy.RetryOccurred += DataConnectionFailureRetry; + return retryPolicy; + } + + /// + /// Returns the default retry policy dedicated to handling exceptions with SQL connections. + /// No logging or other message handler is attached to the policy + /// + /// The RetryPolicy policy + public static RetryPolicy CreateDefaultSchemaConnectionRetryPolicy() + { + return CreateDefaultConnectionRetryPolicy(); + } + + /// + /// Returns the default retry policy dedicated to handling exceptions with SQL connections. + /// Adds an event handler to log and notify listeners of data connection retries + /// + /// The RetryPolicy policy + public static RetryPolicy CreateDefaultDataConnectionRetryPolicy() + { + RetryPolicy retryPolicy = CreateDefaultConnectionRetryPolicy(); + retryPolicy.RetryOccurred += DataConnectionFailureRetry; + return retryPolicy; + } + + /// + /// Returns the default retry policy dedicated to handling exceptions with SQL connections + /// + /// The RetryPolicy policy + public static RetryPolicy CreateDefaultConnectionRetryPolicy() + { + // Note: No longer use Ado.net Connection Pooling and hence do not need TimeBasedRetryPolicy to + // conform to the backoff requirements in this case + RetryPolicy retryPolicy = new RetryPolicy.ExponentialDelayRetryPolicy( + RetryPolicy.NetworkConnectivityErrorDetectionStrategy.Instance, + RetryPolicyDefaults.DefaultConnectionRetryCount, + RetryPolicyDefaults.DefaultBackoffIntervalFactor, + RetryPolicyDefaults.DefaultSchemaMinInterval, + RetryPolicyDefaults.DefaultMaxRetryInterval); + + retryPolicy.FastFirstRetry = true; + return retryPolicy; + } + + /// + /// Returns the default retry policy dedicated to handling retryable conditions with data transfer SQL commands. + /// + /// The RetryPolicy policy + public static RetryPolicy CreateDefaultDataSqlCommandRetryPolicy() + { + RetryPolicy retryPolicy = new RetryPolicy.ExponentialDelayRetryPolicy( + RetryPolicy.SqlAzureTemporaryErrorDetectionStrategy.Instance, + RetryPolicyDefaults.DefaultDataCommandRetryCount, + RetryPolicyDefaults.DefaultBackoffIntervalFactor, + RetryPolicyDefaults.DefaultDataMinInterval, + RetryPolicyDefaults.DefaultMaxRetryInterval); + + retryPolicy.FastFirstRetry = true; + retryPolicy.RetryOccurred += CommandFailureRetry; + return retryPolicy; + } + + /// + /// Returns the default retry policy dedicated to handling retryable conditions with data transfer SQL commands. + /// + /// The RetryPolicy policy + public static RetryPolicy CreateDefaultDataTransferRetryPolicy() + { + RetryPolicy retryPolicy = new RetryPolicy.TimeBasedRetryPolicy( + RetryPolicy.DataTransferErrorDetectionStrategy.Instance, + TimeSpan.FromMinutes(20), + TimeSpan.FromMinutes(240), + 0.1, + TimeSpan.FromMilliseconds(250), + TimeSpan.FromMinutes(2), + 2); + + retryPolicy.FastFirstRetry = true; + retryPolicy.RetryOccurred += CommandFailureRetry; + return retryPolicy; + } + + /// + /// Returns the retry policy to handle data migration for column encryption. + /// + /// The RetryPolicy policy + public static RetryPolicy CreateColumnEncryptionTransferRetryPolicy() + { + RetryPolicy retryPolicy = new RetryPolicy.TimeBasedRetryPolicy( + RetryPolicy.DataTransferErrorDetectionStrategy.Instance, + TimeSpan.FromMinutes(5), + TimeSpan.FromMinutes(5), + 0.1, + TimeSpan.FromMilliseconds(250), + TimeSpan.FromMinutes(2), + 2); + + retryPolicy.FastFirstRetry = true; + retryPolicy.RetryOccurred += CommandFailureRetry; + return retryPolicy; + } + + internal static void DataConnectionFailureRetry(RetryState retryState) + { + Logger.Instance.Write(LogLevel.Normal, string.Format(CultureInfo.InvariantCulture, + "Connection retry number {0}. Delaying {1} ms before retry. Exception: {2}", + retryState.RetryCount, + retryState.Delay.TotalMilliseconds.ToString(CultureInfo.InvariantCulture), + retryState.LastError.ToString())); + + RetryPolicyUtils.RaiseAmbientRetryMessage(retryState, SqlSchemaModelErrorCodes.ServiceActions.ConnectionRetry); + } + + internal static void CommandFailureRetry(RetryState retryState, string commandKeyword) + { + Logger.Instance.Write(LogLevel.Normal, string.Format( + CultureInfo.InvariantCulture, + "{0} retry number {1}. Delaying {2} ms before retry. Exception: {3}", + commandKeyword, + retryState.RetryCount, + retryState.Delay.TotalMilliseconds.ToString(CultureInfo.InvariantCulture), + retryState.LastError.ToString())); + + RetryPolicyUtils.RaiseAmbientRetryMessage(retryState, SqlSchemaModelErrorCodes.ServiceActions.CommandRetry); + } + + internal static void CommandFailureIgnore(RetryState retryState, string commandKeyword) + { + Logger.Instance.Write(LogLevel.Normal, string.Format( + CultureInfo.InvariantCulture, + "{0} retry number {1}. Ignoring failure. Exception: {2}", + commandKeyword, + retryState.RetryCount, + retryState.LastError.ToString())); + + RetryPolicyUtils.RaiseAmbientIgnoreMessage(retryState, SqlSchemaModelErrorCodes.ServiceActions.CommandRetry); + } + + internal static void CommandFailureRetry(RetryState retryState) + { + CommandFailureRetry(retryState, "Command"); + } + + internal static void CommandFailureIgnore(RetryState retryState) + { + CommandFailureIgnore(retryState, "Command"); + } + + internal static void CreateDatabaseCommandFailureRetry(RetryState retryState) + { + CommandFailureRetry(retryState, "Database Command"); + } + + internal static void CreateDatabaseCommandFailureIgnore(RetryState retryState) + { + CommandFailureIgnore(retryState, "Database Command"); + } + + internal static void ElementCommandFailureRetry(RetryState retryState) + { + CommandFailureRetry(retryState, "Element Command"); + } + + internal static void ElementCommandFailureIgnore(RetryState retryState) + { + CommandFailureIgnore(retryState, "Element Command"); + } + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicyUtils.cs b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicyUtils.cs new file mode 100644 index 00000000..c301b48b --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicyUtils.cs @@ -0,0 +1,485 @@ +// +// 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.Data.SqlClient; +using System.Runtime.InteropServices; +using Microsoft.SqlTools.Hosting.Utility; + +namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection +{ + internal static class RetryPolicyUtils + { + /// + /// Approved list of transient errors that should be retryable during Network connection stages + /// + private static readonly HashSet _retryableNetworkConnectivityErrors; + /// + /// Approved list of transient errors that should be retryable on Azure + /// + private static readonly HashSet _retryableAzureErrors; + /// + /// Blocklist of non-transient errors that should stop retry during data transfer operations + /// + private static readonly HashSet _nonRetryableDataTransferErrors; + + static RetryPolicyUtils() + { + _retryableNetworkConnectivityErrors = new HashSet + { + /// A severe error occurred on the current command. The results, if any, should be discarded. + 0, + + //// DBNETLIB Error Code: 20 + //// The instance of SQL Server you attempted to connect to does not support encryption. + (int) ProcessNetLibErrorCode.EncryptionNotSupported, + + //// DBNETLIB Error Code: -2 + //// Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding. + (int)ProcessNetLibErrorCode.Timeout, + + //// SQL Error Code: 64 + //// A connection was successfully established with the server, but then an error occurred during the login process. + //// (provider: TCP Provider, error: 0 - The specified network name is no longer available.) + 64, + + //// SQL Error Code: 233 + //// The client was unable to establish a connection because of an error during connection initialization process before login. + //// Possible causes include the following: the client tried to connect to an unsupported version of SQL Server; the server was too busy + //// to accept new connections; or there was a resource limitation (insufficient memory or maximum allowed connections) on the server. + //// (provider: TCP Provider, error: 0 - An existing connection was forcibly closed by the remote host.) + 233, + + //// SQL Error Code: 10053 + //// A transport-level error has occurred when receiving results from the server. + //// An established connection was aborted by the software in your host machine. + 10053, + + //// SQL Error Code: 10054 + //// A transport-level error has occurred when sending the request to the server. + //// (provider: TCP Provider, error: 0 - An existing connection was forcibly closed by the remote host.) + 10054, + + //// SQL Error Code: 10060 + //// A network-related or instance-specific error occurred while establishing a connection to SQL Server. + //// The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server + //// is configured to allow remote connections. (provider: TCP Provider, error: 0 - A connection attempt failed + //// because the connected party did not properly respond after a period of time, or established connection failed + //// because connected host has failed to respond.)"} + 10060, + + // SQL Error Code: 11001 + // A network-related or instance-specific error occurred while establishing a connection to SQL Server. + // The server was not found or was not accessible. Verify that the instance name is correct and that SQL + // Server is configured to allow remote connections. (provider: TCP Provider, error: 0 - No such host is known.) + 11001, + + //// SQL Error Code: 40613 + //// Database XXXX on server YYYY is not currently available. Please retry the connection later. If the problem persists, contact customer + //// support, and provide them the session tracing ID of ZZZZZ. + 40613, + }; + + _retryableAzureErrors = new HashSet + { + //// SQL Error Code: 40 + //// Could not open a connection to SQL Server + //// (provider: Named Pipes Provider, error: 40 Could not open a connection to SQL Server) + 40, + + //// SQL Error Code: 121 + //// A transport-level error has occurred when receiving results from the server. + //// (provider: TCP Provider, error: 0 - The semaphore timeout period has expired.) + 121, + + //// SQL Error Code: 913 (noticed intermittently on SNAP runs with connected unit tests) + //// Could not find database ID %d. Database may not be activated yet or may be in transition. Reissue the query once the database is available. + //// If you do not think this error is due to a database that is transitioning its state and this error continues to occur, contact your primary support provider. + //// Please have available for review the Microsoft SQL Server error log and any additional information relevant to the circumstances when the error occurred. + 913, + + //// SQL Error Code: 1205 + //// Transaction (Process ID %d) was deadlocked on %.*ls resources with another process and has been chosen as the deadlock victim. Rerun the transaction. + 1205, + + //// SQL Error Code: 40501 + //// The service is currently busy. Retry the request after 10 seconds. Code: (reason code to be decoded). + RetryPolicy.ThrottlingReason.ThrottlingErrorNumber, + + //// SQL Error Code: 10928 + //// Resource ID: %d. The %s limit for the database is %d and has been reached. + 10928, + + //// SQL Error Code: 10929 + //// Resource ID: %d. The %s minimum guarantee is %d, maximum limit is %d and the current usage for the database is %d. + //// However, the server is currently too busy to support requests greater than %d for this database. + 10929, + + //// SQL Error Code: 40143 + //// The service has encountered an error processing your request. Please try again. + 40143, + + //// SQL Error Code: 40197 + //// The service has encountered an error processing your request. Please try again. + 40197, + + //// Sql Error Code: 40549 (not supposed to be used anymore as of Q2 2011) + //// Session is terminated because you have a long-running transaction. Try shortening your transaction. + 40549, + + //// Sql Error Code: 40550 (not supposed to be used anymore as of Q2 2011) + //// The session has been terminated because it has acquired too many locks. Try reading or modifying fewer rows in a single transaction. + 40550, + + //// Sql Error Code: 40551 (not supposed to be used anymore as of Q2 2011) + //// The session has been terminated because of excessive TEMPDB usage. Try modifying your query to reduce the temporary table space usage. + 40551, + + //// Sql Error Code: 40552 (not supposed to be used anymore as of Q2 2011) + //// The session has been terminated because of excessive transaction log space usage. Try modifying fewer rows in a single transaction. + 40552, + + //// Sql Error Code: 40553 (not supposed to be used anymore as of Q2 2011) + //// The session has been terminated because of excessive memory usage. Try modifying your query to process fewer rows. + 40553, + + //// SQL Error Code: 40627 + //// Operation on server YYY and database XXX is in progress. Please wait a few minutes before trying again. + 40627, + + //// SQL Error Code: 40671 (DB CRUD) + //// Unable to '%.*ls' '%.*ls' on server '%.*ls'. Please retry the connection later. + 40671, + + //// SQL Error Code: 40676 (DB CRUD) + //// '%.*ls' request was received but may not be processed completely at this time, + //// please query the sys.dm_operation_status table in the master database for status. + 40676, + + //// SQL Error Code: 45133 + //// A connection failed while the operation was still in progress, and the outcome of the operation is unknown. + 45133, + }; + + foreach(int errorNum in _retryableNetworkConnectivityErrors) + { + _retryableAzureErrors.Add(errorNum); + } + + _nonRetryableDataTransferErrors = new HashSet + { + //// Syntax error + 156, + + //// Cannot insert duplicate key row in object '%.*ls' with unique index '%.*ls'. The duplicate key value is %ls. + 2601, + + //// Violation of %ls constraint '%.*ls'. Cannot insert duplicate key in object '%.*ls'. The duplicate key value is %ls. + 2627, + + //// Cannot find index '%.*ls'. + 2727, + + //// SqlClr stack error + 6522, + + //// Divide by zero error encountered. + 8134, + + //// Could not repair this error. + 8922, + + //// Bug 1110540: This error means the table is corrupted due to hardware failure, so we do not want to retry. + //// Table error: Object ID %d. The text, ntext, or image node at page %S_PGID, slot %d, text ID %I64d is referenced by page %S_PGID, slot %d, but was not seen in the scan. + 8965, + + //// The query processor is unable to produce a plan because the clustered index is disabled. + 8655, + + //// The query processor is unable to produce a plan because table is unavailable because the heap is corrupted + 8674, + + //// SqlClr permission / load error. + //// Example Message: An error occurred in the Microsoft .NET Framework while trying to load assembly + 10314, + + //// '%ls' is not supported in this version of SQL Server. + 40514, + + //// The database 'XYZ' has reached its size quota. Partition or delete data, drop indexes, or consult the documentation for possible resolutions + 40544, + }; + } + + public static bool IsRetryableNetworkConnectivityError(int errorNumber) + { + // .NET core has a bug on OSX/Linux that makes this error number always zero (issue 12472) + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + return errorNumber != 0 && _retryableNetworkConnectivityErrors.Contains(errorNumber); + } + return _retryableNetworkConnectivityErrors.Contains(errorNumber); + } + + public static bool IsRetryableAzureError(int errorNumber) + { + return _retryableAzureErrors.Contains(errorNumber) || _retryableNetworkConnectivityErrors.Contains(errorNumber); + } + + public static bool IsNonRetryableDataTransferError(int errorNumber) + { + return _nonRetryableDataTransferErrors.Contains(errorNumber); + } + + public static void AppendThrottlingDataIfIsThrottlingError(SqlException sqlException, SqlError error) + { + //// SQL Error Code: 40501 + //// The service is currently busy. Retry the request after 10 seconds. Code: (reason code to be decoded). + if(error.Number == RetryPolicy.ThrottlingReason.ThrottlingErrorNumber) + { + // Decode the reason code from the error message to determine the grounds for throttling. + var condition = RetryPolicy.ThrottlingReason.FromError(error); + + // Attach the decoded values as additional attributes to the original SQL exception. + sqlException.Data[condition.ThrottlingMode.GetType().Name] = condition.ThrottlingMode.ToString(); + sqlException.Data[condition.GetType().Name] = condition; + } + } + /// + /// Calculates the length of time to delay a retry based on the number of retries up to this point. + /// As the number of retries increases, the timeout increases exponentially based on the intervalFactor. + /// Uses default values for the intervalFactor (), minInterval + /// () and maxInterval () + /// + /// Total number of retries including the current retry + /// TimeSpan defining the length of time to delay + internal static TimeSpan CalcExponentialRetryDelayWithSchemaDefaults(int currentRetryCount) + { + return CalcExponentialRetryDelay(currentRetryCount, + RetryPolicyDefaults.DefaultBackoffIntervalFactor, + RetryPolicyDefaults.DefaultSchemaMinInterval, + RetryPolicyDefaults.DefaultMaxRetryInterval); + } + + /// + /// Calculates the length of time to delay a retry based on the number of retries up to this point. + /// As the number of retries increases, the timeout increases exponentially based on the intervalFactor. + /// A very large retry count can cause huge delay, so the maxInterval is used to cap delay time at a sensible + /// upper bound + /// + /// Total number of retries including the current retry + /// Controls the speed at which the delay increases - the retryCount is raised to this power as + /// part of the function + /// Minimum interval between retries. The basis for all backoff calculations + /// Maximum interval between retries. Backoff will not take longer than this period. + /// TimeSpan defining the length of time to delay + internal static TimeSpan CalcExponentialRetryDelay(int currentRetryCount, double intervalFactor, TimeSpan minInterval, TimeSpan maxInterval) + { + try + { + return checked(TimeSpan.FromMilliseconds( + Math.Max( + Math.Min( + Math.Pow(intervalFactor, currentRetryCount - 1) * minInterval.TotalMilliseconds, + maxInterval.TotalMilliseconds + ), + minInterval.TotalMilliseconds) + )); + } + catch (OverflowException) + { + // If numbers are too large, could conceivably overflow the double. + // Since the maxInterval is the largest TimeSpan expected, can safely return this here + return maxInterval; + } + } + + internal static void RaiseAmbientRetryMessage(RetryState retryState, int errorCode) + { + Action retryMsgHandler = AmbientSettings.ConnectionRetryMessageHandler; + if (retryMsgHandler != null) + { + string msg = SqlServerRetryError.FormatRetryMessage( + retryState.RetryCount, + retryState.Delay, + retryState.LastError); + + retryMsgHandler(new SqlServerRetryError( + msg, + retryState.LastError, + retryState.RetryCount, + errorCode, + ErrorSeverity.Warning)); + } + } + + internal static void RaiseAmbientIgnoreMessage(RetryState retryState, int errorCode) + { + Action retryMsgHandler = AmbientSettings.ConnectionRetryMessageHandler; + if (retryMsgHandler != null) + { + string msg = SqlServerRetryError.FormatIgnoreMessage( + retryState.RetryCount, + retryState.LastError); + + retryMsgHandler(new SqlServerRetryError( + msg, + retryState.LastError, + retryState.RetryCount, + errorCode, + ErrorSeverity.Warning)); + } + } + + /// + /// Traces the Schema retry information before raising the retry message + /// + /// + /// + /// + internal static void RaiseSchemaAmbientRetryMessage(RetryState retryState, int errorCode, Guid azureSessionId) + { + if (azureSessionId != Guid.Empty) + { + Logger.Instance.Write(LogLevel.Warning, string.Format( + "Retry occurred: session: {0}; attempt - {1}; delay - {2}; exception - \"{3}\"", + azureSessionId, + retryState.RetryCount, + retryState.Delay, + retryState.LastError + )); + + RaiseAmbientRetryMessage(retryState, errorCode); + } + } + + #region ProcessNetLibErrorCode enumeration + + /// + /// Error codes reported by the DBNETLIB module. + /// + internal enum ProcessNetLibErrorCode + { + /// + /// Zero bytes were returned + /// + ZeroBytes = -3, + + /// + /// Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding. + /// + Timeout = -2, + + /// + /// An unknown net lib error + /// + Unknown = -1, + + /// + /// Out of memory + /// + InsufficientMemory = 1, + + /// + /// User or machine level access denied + /// + AccessDenied = 2, + + /// + /// Connection was already busy processing another request + /// + ConnectionBusy = 3, + + /// + /// The connection was broken without a proper disconnect + /// + ConnectionBroken = 4, + + /// + /// The connection has reached a limit + /// + ConnectionLimit = 5, + + /// + /// Name resolution failed for the given server name + /// + ServerNotFound = 6, + + /// + /// Network transport could not be found + /// + NetworkNotFound = 7, + + /// + /// A resource required could not be allocated + /// + InsufficientResources = 8, + + /// + /// Network stack denied the request as too busy + /// + NetworkBusy = 9, + + /// + /// Unable to access the requested network + /// + NetworkAccessDenied = 10, + + /// + /// Internal error + /// + GeneralError = 11, + + /// + /// The network mode was set incorrectly + /// + IncorrectMode = 12, + + /// + /// The given name was not found + /// + NameNotFound = 13, + + /// + /// Connection was invalid + /// + InvalidConnection = 14, + + /// + /// A read or write error occurred + /// + ReadWriteError = 15, + + /// + /// Unable to allocate an additional handle + /// + TooManyHandles = 16, + + /// + /// The server reported an error + /// + ServerError = 17, + + /// + /// SSL failed + /// + SSLError = 18, + + /// + /// Encryption failed with an error + /// + EncryptionError = 19, + + /// + /// Remote endpoint does not support encryption + /// + EncryptionNotSupported = 20 + } + + #endregion + + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryState.cs b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryState.cs new file mode 100644 index 00000000..bbb8935e --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryState.cs @@ -0,0 +1,86 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System; + +namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection +{ + internal class RetryState + { + private int _retryCount = 0; + private TimeSpan _delay = TimeSpan.Zero; + private Exception _lastError = null; + private bool _isDelayDisabled = false; + + /// + /// Gets or sets the current retry attempt count. + /// + public int RetryCount + { + get + { + return _retryCount; + } + set + { + _retryCount = value; + } + } + + /// + /// Gets or sets the delay indicating how long the current thread will be suspended for before the next iteration will be invoked. + /// + public TimeSpan Delay + { + get + { + return _delay; + } + set + { + _delay = value; + } + } + + /// + /// Gets or sets the exception which caused the retry conditions to occur. + /// + public Exception LastError + { + get + { + return _lastError; + } + set + { + _lastError = value; + } + } + + /// + /// Gets or sets a value indicating whether we should ignore delay in order to be able to execute our tests faster + /// + /// Intended for test use ONLY + internal bool IsDelayDisabled + { + get + { + return _isDelayDisabled; + } + set + { + _isDelayDisabled = value; + } + } + + public virtual void Reset() + { + this.IsDelayDisabled = false; + this.RetryCount = 0; + this.Delay = TimeSpan.Zero; + this.LastError = null; + } + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/SqlConnectionHelperScripts.cs b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/SqlConnectionHelperScripts.cs new file mode 100644 index 00000000..2e5d6424 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/SqlConnectionHelperScripts.cs @@ -0,0 +1,51 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection +{ + static class SqlConnectionHelperScripts + { + public const string EngineEdition = "SELECT SERVERPROPERTY('EngineEdition'), SERVERPROPERTY('productversion'), SERVERPROPERTY ('productlevel'), SERVERPROPERTY ('edition'), SERVERPROPERTY ('MachineName'), (SELECT CASE WHEN EXISTS (SELECT TOP 1 1 from [sys].[all_columns] WITH (NOLOCK) WHERE name = N'xml_index_type' AND OBJECT_ID(N'sys.xml_indexes') = object_id) THEN 1 ELSE 0 END AS SXI_PRESENT)"; + public const string EngineEditionWithLock = "SELECT SERVERPROPERTY('EngineEdition'), SERVERPROPERTY('productversion'), SERVERPROPERTY ('productlevel'), SERVERPROPERTY ('edition'), SERVERPROPERTY ('MachineName'), (SELECT CASE WHEN EXISTS (SELECT TOP 1 1 from [sys].[all_columns] WHERE name = N'xml_index_type' AND OBJECT_ID(N'sys.xml_indexes') = object_id) THEN 1 ELSE 0 END AS SXI_PRESENT)"; + + public const string CheckDatabaseReadonly = @"EXEC sp_dboption '{0}', 'read only'"; + + public const string GetDatabaseFilePathAndName = @" +DECLARE @filepath nvarchar(260), + @rc int + +EXEC master.dbo.xp_instance_regread N'HKEY_LOCAL_MACHINE',N'Software\Microsoft\MSSQLServer\MSSQLServer',N'DefaultData', @filepath output, 'no_output' + +IF ((@filepath IS NOT NULL) AND (CHARINDEX(N'\', @filepath, len(@filepath)) = 0)) + SELECT @filepath = @filepath + N'\' + +IF (@filepath IS NULL) + SELECT @filepath = [sdf].[physical_name] + FROM [master].[sys].[database_files] AS [sdf] + WHERE [file_id] = 1 + +SELECT @filepath AS FilePath +"; + + public const string GetDatabaseLogPathAndName = @" +DECLARE @filepath nvarchar(260), + @rc int + +EXEC master.dbo.xp_instance_regread N'HKEY_LOCAL_MACHINE',N'Software\Microsoft\MSSQLServer\MSSQLServer',N'DefaultLog', @filepath output, 'no_output' + +IF ((@filepath IS NOT NULL) AND (CHARINDEX(N'\', @filepath, len(@filepath)) = 0)) + SELECT @filepath = @filepath + N'\' + +IF (@filepath IS NULL) + SELECT @filepath = [ldf].[physical_name] + FROM [master].[sys].[database_files] AS [ldf] + WHERE [file_id] = 2 + +SELECT @filepath AS FilePath +"; + + public const string GetOsVersion = @"SELECT OSVersion = RIGHT(@@version, LEN(@@version)- 3 -charindex (' ON ', @@version))"; + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/SqlErrorNumbers.cs b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/SqlErrorNumbers.cs new file mode 100644 index 00000000..19d50c3d --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/SqlErrorNumbers.cs @@ -0,0 +1,32 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection +{ + /// + /// Constants for SQL Error numbers + /// + internal static class SqlErrorNumbers + { + // Database XYZ already exists. Choose a different database name. + internal const int DatabaseAlreadyExistsErrorNumber = 1801; + + // Cannot drop the database 'x', because it does not exist or you do not have permission. + internal const int DatabaseAlreadyDroppedErrorNumber = 3701; + + // Database 'x' was created\altered successfully, but some properties could not be displayed. + internal const int DatabaseCrudMetadataUpdateErrorNumber = 45166; + + // Violation of PRIMARY KEY constraint 'x'. + // Cannot insert duplicate key in object 'y'. The duplicate key value is (z). + internal const int PrimaryKeyViolationErrorNumber = 2627; + + // There is already an object named 'x' in the database. + internal const int ObjectAlreadyExistsErrorNumber = 2714; + + // Cannot drop the object 'x', because it does not exist or you do not have permission. + internal const int ObjectAlreadyDroppedErrorNumber = 3701; + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/SqlSchemaModelErrorCodes.cs b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/SqlSchemaModelErrorCodes.cs new file mode 100644 index 00000000..3df45388 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/SqlSchemaModelErrorCodes.cs @@ -0,0 +1,465 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection +{ + internal static class SqlSchemaModelErrorCodes + { + private const int ParserErrorCodeStartIndex = 46000; + private const int ParserErrorCodeEndIndex = 46499; + + public static bool IsParseErrorCode(int errorCode) + { + return + (errorCode >= ParserErrorCodeStartIndex) && + (errorCode <= ParserErrorCodeEndIndex); + } + + public static bool IsInterpretationErrorCode(int errorCode) + { + return + (errorCode >= Interpretation.InterpretationBaseCode) && + (errorCode <= Interpretation.InterpretationEndCode); + } + + public static bool IsStatementFilterError(int errorCode) + { + return + (errorCode > StatementFilter.StatementFilterBaseCode) && + (errorCode <= StatementFilter.StatementFilterMaxErrorCode); + } + + public static class StatementFilter + { + public const int StatementFilterBaseCode = 70000; + + public const int UnrecognizedStatement = StatementFilterBaseCode + 1; + public const int ServerObject = StatementFilterBaseCode + 2; + public const int AtMostTwoPartName = StatementFilterBaseCode + 3; + public const int AlterTableAddColumn = StatementFilterBaseCode + 4; + public const int ConstraintAll = StatementFilterBaseCode + 5; + public const int TriggerAll = StatementFilterBaseCode + 6; + public const int CreateSchemaWithoutName = StatementFilterBaseCode + 7; + public const int CreateSchemaElements = StatementFilterBaseCode + 8; + public const int AlterAssembly = StatementFilterBaseCode + 9; + public const int CreateStoplist = StatementFilterBaseCode + 10; + public const int UnsupportedPermission = StatementFilterBaseCode + 11; + public const int TopLevelExecuteWithResultSets = StatementFilterBaseCode + 12; + public const int AlterTableAddConstraint = StatementFilterBaseCode + 13; + public const int DatabaseOnlyObjectInServerProject = StatementFilterBaseCode + 14; + public const int UnsupportedBySqlAzure = StatementFilterBaseCode + 15; + public const int UnsupportedSecurityObjectKind = StatementFilterBaseCode + 16; + public const int StatementNotSupportedForCurrentRelease = StatementFilterBaseCode + 17; + public const int ServerPermissionsNotAllowed = StatementFilterBaseCode + 18; + public const int DeprecatedSyntax = StatementFilterBaseCode + 19; + public const int SetRemoteData = StatementFilterBaseCode + 20; + public const int StatementFilterMaxErrorCode = StatementFilterBaseCode + 499; + } + + public static class Interpretation + { + public const int InterpretationBaseCode = 70500; + + public const int InvalidTopLevelStatement = InterpretationBaseCode + 1; + public const int InvalidAssemblySource = InterpretationBaseCode + 2; + public const int InvalidDatabaseName = InterpretationBaseCode + 3; + public const int OnlyTwoPartNameAllowed = InterpretationBaseCode + 4; + public const int SecurityObjectCannotBeNull = InterpretationBaseCode + 5; + public const int UnknownPermission = InterpretationBaseCode + 6; + public const int UnsupportedAll = InterpretationBaseCode + 7; + public const int InvalidColumnList = InterpretationBaseCode + 8; + public const int ColumnsAreNotAllowed = InterpretationBaseCode + 9; + public const int InvalidDataType = InterpretationBaseCode + 10; + public const int InvalidObjectName = InterpretationBaseCode + 11; + public const int InvalidObjectChildName = InterpretationBaseCode + 12; + public const int NoGlobalTemporarySymmetricKey = InterpretationBaseCode + 13; + public const int NoGlobalTemporarySymmetricKey_Warning = InterpretationBaseCode + 14; + public const int NameCannotBeNull = InterpretationBaseCode + 15; + public const int NameCannotBeNull_Warning = InterpretationBaseCode + 16; + public const int InvalidLoginName = InterpretationBaseCode + 17; + public const int InvalidLoginName_Warning = InterpretationBaseCode + 18; + public const int MoreAliasesThanColumns = InterpretationBaseCode + 19; + public const int FewerAliasesThanColumns = InterpretationBaseCode + 20; + public const int InvalidTimestampReturnType = InterpretationBaseCode + 21; + public const int VariableParameterAtTopLevelStatement = InterpretationBaseCode + 22; + public const int CannotCreateTempTable = InterpretationBaseCode + 23; + public const int MultipleNullabilityConstraintError = InterpretationBaseCode + 24; + public const int MultipleNullabilityConstraintWarning = InterpretationBaseCode + 25; + public const int ColumnIsntAllowedForAssemblySource = InterpretationBaseCode + 26; + public const int InvalidUserName = InterpretationBaseCode + 27; + public const int InvalidWindowsLogin = InterpretationBaseCode + 28; + public const int InvalidWindowsLogin_Warning = InterpretationBaseCode + 29; + public const int CannotHaveUsingForPrimaryXmlIndex = InterpretationBaseCode + 30; + public const int UsingIsRequiredForSecondaryXmlIndex = InterpretationBaseCode + 31; + public const int XmlIndexTypeIsRequiredForSecondaryXmlIndex = InterpretationBaseCode + 32; + public const int UnsupportedAlterCryptographicProvider = InterpretationBaseCode + 33; + public const int HttpForSoapOnly = InterpretationBaseCode + 34; + public const int UnknownEventTypeOrGroup = InterpretationBaseCode + 35; + public const int CannotAddLogFileToFilegroup = InterpretationBaseCode + 36; + public const int BuiltInTypeExpected = InterpretationBaseCode + 37; + public const int MissingArgument = InterpretationBaseCode + 38; + public const int InvalidArgument = InterpretationBaseCode + 39; + public const int IncompleteBoundingBoxCoordinates = InterpretationBaseCode + 40; + public const int XMaxLessThanXMin = InterpretationBaseCode + 41; + public const int YMaxLessThanYMin = InterpretationBaseCode + 42; + public const int InvalidCoordinate = InterpretationBaseCode + 43; + public const int InvalidValue = InterpretationBaseCode + 44; + public const int InvalidIdentityValue = InterpretationBaseCode + 45; + public const int InvalidPriorityLevel = InterpretationBaseCode + 46; + public const int TriggerIsNotForEvent = InterpretationBaseCode + 47; + public const int SyntaxError = InterpretationBaseCode + 48; + public const int UnsupportedPintable = InterpretationBaseCode + 49; + public const int DuplicateEventType = InterpretationBaseCode + 50; + public const int ClearAndBasicAreNotAllowed = InterpretationBaseCode + 51; + public const int AssemblyCorruptErrorCode = InterpretationBaseCode + 57; + public const int DynamicQuery = InterpretationBaseCode + 58; + public const int OnlyLcidAllowed = InterpretationBaseCode + 59; + public const int WildCardNotAllowed = InterpretationBaseCode + 60; + public const int CannotBindSchema = InterpretationBaseCode + 61; + public const int TableTypeNotAllowFunctionCall = InterpretationBaseCode + 62; + public const int ColumnNotAllowed = InterpretationBaseCode + 63; + public const int OwnerRequiredForEndpoint = InterpretationBaseCode + 64; + public const int PartitionNumberMustBeInteger = InterpretationBaseCode + 65; + public const int DuplicatedPartitionNumber = InterpretationBaseCode + 66; + public const int FromPartitionGreaterThanToPartition = InterpretationBaseCode + 67; + public const int CannotSpecifyPartitionNumber = InterpretationBaseCode + 68; + public const int MissingColumnNameError = InterpretationBaseCode + 69; + public const int MissingColumnNameWarning = InterpretationBaseCode + 70; + public const int UnknownTableSourceError = InterpretationBaseCode + 71; + public const int UnknownTableSourceWarning = InterpretationBaseCode + 72; + public const int TooManyPartsForCteOrAliasError = InterpretationBaseCode + 73; + public const int TooManyPartsForCteOrAliasWarning = InterpretationBaseCode + 74; + public const int ServerAuditInvalidQueueDelayValue = InterpretationBaseCode + 75; + public const int WrongEventType = InterpretationBaseCode + 76; + public const int CantCreateUddtFromXmlError = InterpretationBaseCode + 77; + public const int CantCreateUddtFromXmlWarning = InterpretationBaseCode + 78; + public const int CantCreateUddtFromUddtError = InterpretationBaseCode + 79; + public const int CantCreateUddtFromUddtWarning = InterpretationBaseCode + 80; + public const int ForReplicationIsNotSupported = InterpretationBaseCode + 81; + public const int TooLongIdentifier = InterpretationBaseCode + 82; + public const int InvalidLanguageTerm = InterpretationBaseCode + 83; + public const int InvalidParameterOrOption = InterpretationBaseCode + 85; + public const int TableLevelForeignKeyWithNoColumnsError = InterpretationBaseCode + 86; + public const int TableLevelForeignKeyWithNoColumnsWarning = InterpretationBaseCode + 87; + public const int ConstraintEnforcementIsIgnored = InterpretationBaseCode + 88; + public const int DeprecatedBackupOption = InterpretationBaseCode + 89; + public const int UndeclaredVariableParameter = InterpretationBaseCode + 90; + public const int UnsupportedAlgorithm = InterpretationBaseCode + 91; + public const int InvalidLanguageNameOrAliasWarning = InterpretationBaseCode + 92; + public const int UnsupportedRevoke = InterpretationBaseCode + 93; + public const int InvalidPermissionTypeAgainstObject = InterpretationBaseCode + 94; + public const int InvalidPermissionObjectType = InterpretationBaseCode + 95; + public const int CannotDetermineSecurableFromPermission = InterpretationBaseCode + 96; + public const int InvalidColumnListForSecurableType = InterpretationBaseCode + 97; + public const int InvalidUserDefaultLanguage = InterpretationBaseCode + 98; + public const int CannotSpecifyGridParameterForAutoGridSpatialIndex = InterpretationBaseCode + 99; + public const int UnsupportedSpatialTessellationScheme = InterpretationBaseCode + 100; + public const int CannotSpecifyBoundingBoxForGeography = InterpretationBaseCode + 101; + public const int InvalidSearchPropertyId = InterpretationBaseCode + 102; + public const int OnlineSpatialIndex = InterpretationBaseCode + 103; + public const int SqlCmdVariableInObjectName = InterpretationBaseCode + 104; + public const int SubqueriesNotAllowed = InterpretationBaseCode + 105; + public const int ArgumentReplaceNotSupported = InterpretationBaseCode + 106; + public const int DuplicateArgument = InterpretationBaseCode + 107; + public const int UnsupportedNoPopulationChangeTrackingOption = InterpretationBaseCode + 108; + public const int UnsupportedResourceManagerLocationProperty = InterpretationBaseCode + 109; + public const int RequiredExternalDataSourceLocationPropertyMissing = InterpretationBaseCode + 110; + public const int UnsupportedSerdeMethodProperty = InterpretationBaseCode + 111; + public const int UnsupportedFormatOptionsProperty = InterpretationBaseCode + 112; + public const int RequiredSerdeMethodPropertyMissing = InterpretationBaseCode + 113; + public const int TableLevelIndexWithNoColumnsError = InterpretationBaseCode + 114; + public const int TableLevelIndexWithNoColumnsWarning = InterpretationBaseCode + 115; + public const int InvalidIndexOption = InterpretationBaseCode + 116; + public const int TypeAndSIDMustBeUsedTogether = InterpretationBaseCode + 117; + public const int TypeCannotBeUsedWithLoginOption = InterpretationBaseCode + 118; + public const int InvalidUserType = InterpretationBaseCode + 119; + public const int InvalidUserSid = InterpretationBaseCode + 120; + public const int InvalidPartitionFunctionDataType = InterpretationBaseCode + 121; + public const int RequiredExternalTableLocationPropertyMissing = InterpretationBaseCode + 122; + public const int UnsupportedRejectSampleValueProperty = InterpretationBaseCode + 123; + public const int RequiredExternalDataSourceDatabasePropertyMissing = InterpretationBaseCode + 124; + public const int RequiredExternalDataSourceShardMapNamePropertyMissing = InterpretationBaseCode + 125; + public const int InvalidPropertyForExternalDataSourceType = InterpretationBaseCode + 126; + public const int UnsupportedExternalDataSourceTypeInCurrentPlatform = InterpretationBaseCode + 127; + public const int UnsupportedExternalTableProperty = InterpretationBaseCode + 128; + public const int MaskingFunctionIsEmpty = InterpretationBaseCode + 129; + public const int InvalidMaskingFunctionFormat = InterpretationBaseCode + 130; + public const int CannotCreateAlwaysEncryptedObject = InterpretationBaseCode + 131; + public const int ExternalTableSchemaOrObjectNameMissing = InterpretationBaseCode + 132; + public const int CannotCreateTemporalTableWithoutHistoryTableName = InterpretationBaseCode + 133; + public const int TemporalPeriodColumnMustNotBeNullable = InterpretationBaseCode + 134; + public const int InterpretationEndCode = InterpretationBaseCode + 499; + } + + public static class ModelBuilder + { + private const int ModelBuilderBaseCode = 71000; + + public const int CannotFindMainElement = ModelBuilderBaseCode + 1; + public const int CannotFindColumnSourceGrantForColumnRevoke = ModelBuilderBaseCode + 2; + public const int AssemblyReferencesNotSupported = ModelBuilderBaseCode + 3; + public const int NoSourceForColumn = ModelBuilderBaseCode + 5; + public const int MoreThanOneStatementPerBatch = ModelBuilderBaseCode + 6; + public const int MaximumSizeExceeded = ModelBuilderBaseCode + 7; + } + + public static class Validation + { + private const int ValidationBaseCode = 71500; + + public const int AllReferencesMustBeResolved = ValidationBaseCode + 1; + public const int AllReferencesMustBeResolved_Warning = ValidationBaseCode + 2; + public const int AssemblyVisibilityRule = ValidationBaseCode + 3; + public const int BreakContinueOnlyInWhile = ValidationBaseCode + 4; + public const int ClrObjectAssemblyReference_InvalidAssembly = ValidationBaseCode + 5; + public const int ClrObjectAssemblyReference = ValidationBaseCode + 6; + public const int ColumnUserDefinedTableType = ValidationBaseCode + 7; + public const int DuplicateName = ValidationBaseCode + 8; + public const int DuplicateName_Warning = ValidationBaseCode + 9; + public const int DuplicateVariableParameterName_TemporaryTable = ValidationBaseCode + 10; + public const int DuplicateVariableParameterName_Variable = ValidationBaseCode + 11; + public const int EndPointRule_DATABASE_MIRRORING = ValidationBaseCode + 12; + public const int EndPointRule_SERVICE_BROKER = ValidationBaseCode + 13; + public const int ForeignKeyColumnTypeNumberMustMatch_NumberOfColumns = ValidationBaseCode + 14; + public const int ForeignKeyColumnTypeNumberMustMatch_TypeMismatch = ValidationBaseCode + 15; + public const int ForeignKeyReferencePKUnique = ValidationBaseCode + 16; + public const int FullTextIndexColumn = ValidationBaseCode + 17; + public const int IdentityColumnValidation_InvalidType = ValidationBaseCode + 18; + public const int IdentityColumnValidation_MoreThanOneIdentity = ValidationBaseCode + 19; + public const int InsertIntoIdentityColumn = ValidationBaseCode + 20; + public const int MatchingSignatureNotFoundInAssembly = ValidationBaseCode + 21; + public const int MatchingTypeNotFoundInAssembly = ValidationBaseCode + 22; + public const int MaxColumnInIndexKey = ValidationBaseCode + 25; + public const int MaxColumnInTable_1024Columns = ValidationBaseCode + 26; + public const int MultiFullTextIndexOnTable = ValidationBaseCode + 28; + public const int NonNullPrimaryKey_NonNullSimpleColumn = ValidationBaseCode + 29; + public const int NonNullPrimaryKey_NotPersistedComputedColumn = ValidationBaseCode + 30; + public const int OneClusteredIndex = ValidationBaseCode + 31; + public const int OneMasterKey = ValidationBaseCode + 32; + public const int OnePrimaryKey = ValidationBaseCode + 33; + public const int PrimaryXMLIndexClustered = ValidationBaseCode + 34; + public const int SelectAssignRetrieval = ValidationBaseCode + 35; + public const int SubroutineParameterReadOnly_NonUDTTReadOnly = ValidationBaseCode + 36; + public const int SubroutineParameterReadOnly_UDTTReadOnly = ValidationBaseCode + 37; + public const int UsingXMLIndex = ValidationBaseCode + 38; + public const int VardecimalOptionRule = ValidationBaseCode + 39; + public const int WildCardExpansion = ValidationBaseCode + 40; + public const int WildCardExpansion_Warning = ValidationBaseCode + 41; + public const int XMLIndexOnlyXMLTypeColumn = ValidationBaseCode + 42; + public const int TableVariablePrefix = ValidationBaseCode + 44; + public const int FileStream_FILESTREAMON = ValidationBaseCode + 45; + public const int FileStream_ROWGUIDCOLUMN = ValidationBaseCode + 46; + public const int MaxColumnInTable100_Columns = ValidationBaseCode + 47; + public const int XMLIndexOnlyXMLTypeColumn_SparseColumnSet = ValidationBaseCode + 48; + public const int ClrObjectAssemblyReference_ParameterTypeMismatch = ValidationBaseCode + 50; + public const int OneDefaultConstraintPerColumn = ValidationBaseCode + 51; + public const int PermissionStatementValidation_DuplicatePermissionOnSecurable = ValidationBaseCode + 52; + public const int PermissionStatementValidation_ConflictingPermissionsOnSecurable = ValidationBaseCode + 53; + public const int PermissionStatementValidation_ConflictingColumnStatements = ValidationBaseCode + 54; + public const int PermissionOnObjectSecurableValidation_InvalidPermissionForObject = ValidationBaseCode + 55; + public const int SequenceValueValidation_ValueOutOfRange = ValidationBaseCode + 56; + public const int SequenceValueValidation_InvalidDataType = ValidationBaseCode + 57; + public const int MismatchedName_Warning = ValidationBaseCode + 58; + public const int DifferentNameCasing_Warning = ValidationBaseCode + 59; + public const int OneClusteredIndexAzure = ValidationBaseCode + 60; + public const int AllExternalReferencesMustBeResolved = ValidationBaseCode + 61; + public const int AllExternalReferencesMustBeResolved_Warning = ValidationBaseCode + 62; + public const int ExternalObjectWildCardExpansion_Warning = ValidationBaseCode + 63; + public const int UnsupportedElementForDataPackage = ValidationBaseCode + 64; + public const int InvalidFileStreamOptions = ValidationBaseCode + 65; + public const int StorageShouldNotSetOnDifferentInstance = ValidationBaseCode + 66; + public const int TableShouldNotHaveStorage = ValidationBaseCode + 67; + public const int MemoryOptimizedObjectsValidation_NonMemoryOptimizedTableCannotBeAccessed = ValidationBaseCode + 68; + public const int MemoryOptimizedObjectsValidation_SyntaxNotSupportedOnHekatonElement = ValidationBaseCode + 69; + public const int MemoryOptimizedObjectsValidation_ValidatePrimaryKeyForSchemaAndDataTables = ValidationBaseCode + 70; + public const int MemoryOptimizedObjectsValidation_ValidatePrimaryKeyForSchemaOnlyTables = ValidationBaseCode + 71; + public const int MemoryOptimizedObjectsValidation_OnlyNotNullableColumnsOnIndexes = ValidationBaseCode + 72; + public const int MemoryOptimizedObjectsValidation_HashIndexesOnlyOnMemoryOptimizedObjects = ValidationBaseCode + 73; + public const int MemoryOptimizedObjectsValidation_OptionOnlyForHashIndexes = ValidationBaseCode + 74; + public const int IncrementalStatisticsValidation_FilterNotSupported = ValidationBaseCode + 75; + public const int IncrementalStatisticsValidation_ViewNotSupported = ValidationBaseCode + 76; + public const int IncrementalStatisticsValidation_IndexNotPartitionAligned = ValidationBaseCode + 77; + public const int AzureV12SurfaceAreaValidation = ValidationBaseCode + 78; + public const int DuplicatedTargetObjectReferencesInSecurityPolicy = ValidationBaseCode + 79; + public const int MultipleSecurityPoliciesOnTargetObject = ValidationBaseCode + 80; + public const int ExportedRowsMayBeIncomplete = ValidationBaseCode + 81; + public const int ExportedRowsMayContainSomeMaskedData = ValidationBaseCode + 82; + public const int EncryptedColumnValidation_EncryptedPrimaryKey = ValidationBaseCode + 83; + public const int EncryptedColumnValidation_EncryptedUniqueColumn = ValidationBaseCode + 84; + public const int EncryptedColumnValidation_EncryptedCheckConstraint = ValidationBaseCode + 85; + public const int EncryptedColumnValidation_PrimaryKeyForeignKeyEncryptionMismatch = ValidationBaseCode + 86; + public const int EncryptedColumnValidation_UnsupportedDataType = ValidationBaseCode + 87; + public const int MemoryOptimizedObjectsValidation_UnSupportedOption = ValidationBaseCode + 88; + public const int MasterKeyExistsForCredential = ValidationBaseCode + 89; + public const int MemoryOptimizedObjectsValidation_InvalidForeignKeyRelationship = ValidationBaseCode + 90; + public const int MemoryOptimizedObjectsValidation_UnsupportedForeignKeyReference = ValidationBaseCode + 91; + public const int EncryptedColumnValidation_RowGuidColumn = ValidationBaseCode + 92; + public const int EncryptedColumnValidation_EncryptedClusteredIndex = ValidationBaseCode + 93; + public const int EncryptedColumnValidation_EncryptedNonClusteredIndex = ValidationBaseCode + 94; + public const int EncryptedColumnValidation_DependentComputedColumn = ValidationBaseCode + 95; + public const int EncryptedColumnValidation_EncryptedFullTextColumn = ValidationBaseCode + 96; + public const int EncryptedColumnValidation_EncryptedSparseColumnSet = ValidationBaseCode + 97; + public const int EncryptedColumnValidation_EncryptedStatisticsColumn = ValidationBaseCode + 98; + public const int EncryptedColumnValidation_EncryptedPartitionColumn = ValidationBaseCode + 99; + public const int EncryptedColumnValidation_PrimaryKeyChangeTrackingColumn = ValidationBaseCode + 100; + public const int EncryptedColumnValidation_ChangeDataCaptureOn = ValidationBaseCode + 101; + public const int EncryptedColumnValidation_FilestreamColumn = ValidationBaseCode + 102; + public const int EncryptedColumnValidation_MemoryOptimizedTable = ValidationBaseCode + 103; + public const int EncryptedColumnValidation_MaskedEncryptedColumn = ValidationBaseCode + 104; + public const int EncryptedColumnValidation_EncryptedIdentityColumn = ValidationBaseCode + 105; + public const int EncryptedColumnValidation_EncryptedDefaultConstraint = ValidationBaseCode + 106; + public const int TemporalValidation_InvalidPeriodSpecification = ValidationBaseCode + 107; + public const int TemporalValidation_MultipleCurrentTables = ValidationBaseCode + 108; + public const int TemporalValidation_SchemaMismatch = ValidationBaseCode + 109; + public const int TemporalValidation_ComputedColumns = ValidationBaseCode + 110; + public const int TemporalValidation_NoAlwaysEncryptedCols = ValidationBaseCode + 111; + public const int IndexesOnExternalTable = ValidationBaseCode + 112; + public const int TriggersOnExternalTable = ValidationBaseCode + 113; + public const int StretchValidation_ExportBlocked = ValidationBaseCode + 114; + public const int StretchValidation_ImportBlocked = ValidationBaseCode + 115; + public const int DeploymentBlocked = ValidationBaseCode + 116; + public const int NoBlockPredicatesTargetingViews = ValidationBaseCode + 117; + public const int SchemaBindingOnSecurityPoliciesValidation = ValidationBaseCode + 118; + public const int SecurityPredicateTargetObjectValidation = ValidationBaseCode + 119; + public const int TemporalValidation_SchemaMismatch_ColumnCount = ValidationBaseCode + 120; + public const int AkvValidation_AuthenticationFailed = ValidationBaseCode + 121; + public const int TemporalValidation_PrimaryKey = ValidationBaseCode + 122; + } + + public static class SqlMSBuild + { + private const int MSBuildBaseCode = 72000; + + public const int FileDoesNotExist = MSBuildBaseCode + 1; + public const int UnknownDeployError = MSBuildBaseCode + 2; + public const int InvalidProperty = MSBuildBaseCode + 3; + public const int CollationError = MSBuildBaseCode + 4; + public const int InvalidSqlClrDefinition = MSBuildBaseCode + 5; + public const int SQL_PrePostFatalParserError = MSBuildBaseCode + 6; + public const int SQL_PrePostSyntaxCheckError = MSBuildBaseCode + 7; + public const int SQL_PrePostVariableError = MSBuildBaseCode + 8; + public const int SQL_CycleError = MSBuildBaseCode + 9; + public const int SQL_NoConnectionStringNoServerVerification = MSBuildBaseCode + 10; + public const int SQL_VardecimalMismatch = MSBuildBaseCode + 11; + public const int SQL_NoAlterFileSystemObject = MSBuildBaseCode + 12; + public const int SQL_SqlCmdVariableOverrideError = MSBuildBaseCode + 13; + public const int SQL_BatchError = MSBuildBaseCode + 14; + public const int SQL_DataLossError = MSBuildBaseCode + 15; + public const int SQL_ExecutionError = MSBuildBaseCode + 16; + public const int SQL_UncheckedConstraint = MSBuildBaseCode + 17; + public const int SQL_UnableToImportElements = MSBuildBaseCode + 18; + public const int SQL_TargetReadOnlyError = MSBuildBaseCode + 19; + public const int SQL_UnsupportedCompatibilityMode = MSBuildBaseCode + 20; + public const int SQL_IncompatibleDSPVersions = MSBuildBaseCode + 21; + public const int SQL_CouldNotLoadSymbols = MSBuildBaseCode + 22; + public const int SQL_ContainmentlMismatch = MSBuildBaseCode + 23; + public const int SQL_PrePostExpectedNoTSqlError = MSBuildBaseCode + 24; + public const int ReferenceErrorCode = MSBuildBaseCode + 25; + public const int FileError = MSBuildBaseCode + 26; + public const int MissingReference = MSBuildBaseCode + 27; + public const int SerializationError = MSBuildBaseCode + 28; + public const int DeploymentContributorVerificationError = MSBuildBaseCode + 29; + public const int Deployment_PossibleRuntimeError = MSBuildBaseCode + 30; + public const int Deployment_BlockingDependency = MSBuildBaseCode + 31; + public const int Deployment_TargetObjectLoss = MSBuildBaseCode + 32; + public const int Deployment_MissingDependency = MSBuildBaseCode + 33; + public const int Deployment_PossibleDataLoss = MSBuildBaseCode + 34; + public const int Deployment_NotSupportedOperation = MSBuildBaseCode + 35; + public const int Deployment_Information = MSBuildBaseCode + 36; + public const int Deployment_UnsupportedDSP = MSBuildBaseCode + 37; + public const int Deployment_SkipManagementScopedChange = MSBuildBaseCode + 38; + public const int StaticCodeAnalysis_GeneralException = MSBuildBaseCode + 39; + public const int StaticCodeAnalysis_ResultsFileIOException = MSBuildBaseCode + 40; + public const int StaticCodeAnalysis_FailToCreateTaskHost = MSBuildBaseCode + 41; + public const int StaticCodeAnalysis_InvalidDataSchemaModel = MSBuildBaseCode + 42; + public const int StaticCodeAnalysis_InvalidElement = MSBuildBaseCode + 43; + public const int Deployment_NoClusteredIndex = MSBuildBaseCode + 44; + public const int Deployment_DetailedScriptExecutionError = MSBuildBaseCode + 45; + } + + public static class Refactoring + { + private const int RefactoringBaseCode = 72500; + + public const int FailedToLoadFile = RefactoringBaseCode + 1; + } + + /// + /// These codes are used to message specific actions for extract and deployment operations. + /// The primary consumer of these codes is the Import/Export service. + /// + public static class ServiceActions + { + public const int ServiceActionsBaseCode = 73000; + public const int ServiceActionsMaxCode = 73000 + 0xFF; + + // Note: These codes are defined so that the lower 3 bits indicate one of three + // event stages: Started (0x01), Done/Complete (0x02), Done/Failed (0x04) + public const int DeployInitializeStart = ServiceActionsBaseCode + 0x01; + public const int DeployInitializeSuccess = ServiceActionsBaseCode + 0x02; + public const int DeployInitializeFailure = ServiceActionsBaseCode + 0x04; + + public const int DeployAnalysisStart = ServiceActionsBaseCode + 0x11; + public const int DeployAnalysisSuccess = ServiceActionsBaseCode + 0x12; + public const int DeployAnalysisFailure = ServiceActionsBaseCode + 0x14; + + public const int DeployExecuteScriptStart = ServiceActionsBaseCode + 0x21; + public const int DeployExecuteScriptSuccess = ServiceActionsBaseCode + 0x22; + public const int DeployExecuteScriptFailure = ServiceActionsBaseCode + 0x24; + + public const int DataImportStart = ServiceActionsBaseCode + 0x41; + public const int DataImportSuccess = ServiceActionsBaseCode + 0x42; + public const int DataImportFailure = ServiceActionsBaseCode + 0x44; + + public const int ExtractSchemaStart = ServiceActionsBaseCode + 0x61; + public const int ExtractSchemaSuccess = ServiceActionsBaseCode + 0x62; + public const int ExtractSchemaFailure = ServiceActionsBaseCode + 0x64; + + public const int ExportVerifyStart = ServiceActionsBaseCode + 0x71; + public const int ExportVerifySuccess = ServiceActionsBaseCode + 0x72; + public const int ExportVerifyFailure = ServiceActionsBaseCode + 0x74; + + public const int ExportDataStart = ServiceActionsBaseCode + 0x81; + public const int ExportDataSuccess = ServiceActionsBaseCode + 0x82; + public const int ExportDataFailure = ServiceActionsBaseCode + 0x84; + + public const int EnableIndexesDataStart = ServiceActionsBaseCode + 0xb1; + public const int EnableIndexesDataSuccess = ServiceActionsBaseCode + 0xb2; + public const int EnableIndexesDataFailure = ServiceActionsBaseCode + 0xb4; + + public const int DisableIndexesDataStart = ServiceActionsBaseCode + 0xc1; + public const int DisableIndexesDataSuccess = ServiceActionsBaseCode + 0xc2; + public const int DisableIndexesDataFailure = ServiceActionsBaseCode + 0xc4; + + public const int EnableIndexDataStart = ServiceActionsBaseCode + 0xd1; + public const int EnableIndexDataSuccess = ServiceActionsBaseCode + 0xd2; + public const int EnableIndexDataFailure = ServiceActionsBaseCode + 0xd4; + + public const int DisableIndexDataStart = ServiceActionsBaseCode + 0xe1; + public const int DisableIndexDataSuccess = ServiceActionsBaseCode + 0xe2; + public const int DisableIndexDataFailure = ServiceActionsBaseCode + 0xe4; + + public const int ColumnEncryptionDataMigrationStart = ServiceActionsBaseCode + 0xf1; + public const int ColumnEncryptionDataMigrationSuccess = ServiceActionsBaseCode + 0xf2; + public const int ColumnEncryptionDataMigrationFailure = ServiceActionsBaseCode + 0xf4; + + // These codes do not set the lower 3 bits + public const int ConnectionRetry = ServiceActionsBaseCode + 0x90; + public const int CommandRetry = ServiceActionsBaseCode + 0x91; + public const int GeneralProgress = ServiceActionsBaseCode + 0x92; + public const int TypeFidelityLoss = ServiceActionsBaseCode + 0x93; + public const int TableProgress = ServiceActionsBaseCode + 0x94; + public const int ImportBlocked = ServiceActionsBaseCode + 0x95; + public const int DataPrecisionLoss = ServiceActionsBaseCode + 0x96; + public const int DataRowCount = ServiceActionsBaseCode + 0x98; + + public const int DataException = ServiceActionsBaseCode + 0xA0; + public const int LogEntry = ServiceActionsBaseCode + 0xA1; + public const int GeneralInfo = ServiceActionsBaseCode + 0xA2; + + + } + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/SqlServerError.cs b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/SqlServerError.cs new file mode 100644 index 00000000..059eaceb --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/SqlServerError.cs @@ -0,0 +1,74 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System; + +namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection +{ + /// + /// Represents an error produced by SQL Server database schema provider + /// + [Serializable] + internal class SqlServerError : DataSchemaError + { + private const string SqlServerPrefix = "SQL"; + private const string DefaultHelpKeyword = "vs.teamsystem.datatools.DefaultErrorMessageHelp"; + + public SqlServerError(string message, string document, ErrorSeverity severity) + : this(message, null, document, 0, 0, Constants.UndefinedErrorCode, severity) + { + } + + public SqlServerError(string message, string document, int errorCode, ErrorSeverity severity) + : this(message, null, document, 0, 0, errorCode, severity) + { + } + + public SqlServerError(Exception exception, string document, int errorCode, ErrorSeverity severity) + : this(exception, document, 0, 0, errorCode, severity) + { + } + + public SqlServerError(string message, string document, int line, int column, ErrorSeverity severity) + : this(message, null, document, line, column, Constants.UndefinedErrorCode, severity) + { + } + + public SqlServerError( + Exception exception, + string document, + int line, + int column, + int errorCode, + ErrorSeverity severity) : + this(exception.Message, exception, document, line, column, errorCode, severity) + { + } + + public SqlServerError( + string message, + string document, + int line, + int column, + int errorCode, + ErrorSeverity severity) : + this(message, null, document, line, column, errorCode, severity) + { + } + + public SqlServerError( + string message, + Exception exception, + string document, + int line, + int column, + int errorCode, + ErrorSeverity severity) : + base(message, exception, document, line, column, SqlServerPrefix, errorCode, severity) + { + this.HelpKeyword = DefaultHelpKeyword; + } + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/SqlServerRetryError.cs b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/SqlServerRetryError.cs new file mode 100644 index 00000000..597de2f7 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/SqlServerRetryError.cs @@ -0,0 +1,54 @@ +// +// 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.CoreServices.Connection.ReliableConnection +{ + /// + /// Captures extended information about a specific error and a retry + /// + internal class SqlServerRetryError : SqlServerError + { + private int _retryCount; + private int _errorCode; + + public SqlServerRetryError(string message, Exception ex, int retryCount, int errorCode, ErrorSeverity severity) + : base(ex, message, errorCode, severity) + { + _retryCount = retryCount; + _errorCode = errorCode; + } + + public int RetryCount + { + get { return _retryCount; } + } + + public static string FormatRetryMessage(int retryCount, TimeSpan delay, Exception transientException) + { + string message = string.Format( + CultureInfo.CurrentCulture, + Resources.RetryOnException, + retryCount, + delay.TotalMilliseconds.ToString(CultureInfo.CurrentCulture), + transientException.ToString()); + + return message; + } + + public static string FormatIgnoreMessage(int retryCount, Exception exception) + { + string message = string.Format( + CultureInfo.CurrentCulture, + Resources.IgnoreOnException, + retryCount, + exception.ToString()); + + return message; + } + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/SqlConnectionFactory.cs b/src/Microsoft.SqlTools.CoreServices/Connection/SqlConnectionFactory.cs new file mode 100644 index 00000000..cc57c6bb --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Connection/SqlConnectionFactory.cs @@ -0,0 +1,28 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System.Data.Common; +using Microsoft.SqlTools.CoreServices.Connection.ReliableConnection; + +namespace Microsoft.SqlTools.CoreServices.Connection +{ + /// + /// Factory class to create SqlClientConnections + /// The purpose of the factory is to make it easier to mock out the database + /// in 'offline' unit test scenarios. + /// + public class SqlConnectionFactory : ISqlConnectionFactory + { + /// + /// Creates a new SqlConnection object + /// + public DbConnection CreateSqlConnection(string connectionString) + { + RetryPolicy connectionRetryPolicy = RetryPolicyFactory.CreateDefaultConnectionRetryPolicy(); + RetryPolicy commandRetryPolicy = RetryPolicyFactory.CreateDefaultConnectionRetryPolicy(); + return new ReliableSqlConnection(connectionString, connectionRetryPolicy, commandRetryPolicy); + } + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/LanguageServices/BindingQueue.cs b/src/Microsoft.SqlTools.CoreServices/LanguageServices/BindingQueue.cs new file mode 100644 index 00000000..df3708ec --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/LanguageServices/BindingQueue.cs @@ -0,0 +1,428 @@ +// +// 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.Threading; +using System.Threading.Tasks; +using System.Linq; +using Microsoft.SqlTools.Hosting.Utility; + +namespace Microsoft.SqlTools.CoreServices.LanguageServices +{ + /// + /// Main class for the Binding Queue + /// + public class BindingQueue : IDisposable where T : IBindingContext, new() + { + internal const int QueueThreadStackSize = 5 * 1024 * 1024; + + private CancellationTokenSource processQueueCancelToken = null; + + private ManualResetEvent itemQueuedEvent = new ManualResetEvent(initialState: false); + + private object bindingQueueLock = new object(); + + private LinkedList bindingQueue = new LinkedList(); + + private object bindingContextLock = new object(); + + private Task queueProcessorTask; + + /// + /// Map from context keys to binding context instances + /// Internal for testing purposes only + /// + internal Dictionary BindingContextMap { get; set; } + + /// + /// Constructor for a binding queue instance + /// + public BindingQueue() + { + this.BindingContextMap = new Dictionary(); + this.StartQueueProcessor(); + } + + public void StartQueueProcessor() + { + this.queueProcessorTask = StartQueueProcessorAsync(); + } + + /// + /// Stops the binding queue by sending cancellation request + /// + /// + public bool StopQueueProcessor(int timeout) + { + this.processQueueCancelToken.Cancel(); + return this.queueProcessorTask.Wait(timeout); + } + + /// + /// Returns true if cancellation is requested + /// + /// + public bool IsCancelRequested + { + get + { + return this.processQueueCancelToken.IsCancellationRequested; + } + } + + /// + /// Queue a binding request item + /// + public virtual QueueItem QueueBindingOperation( + string key, + Func bindOperation, + Func timeoutOperation = null, + Func errorHandler = null, + int? bindingTimeout = null, + int? waitForLockTimeout = null) + { + // don't add null operations to the binding queue + if (bindOperation == null) + { + return null; + } + + QueueItem queueItem = new QueueItem() + { + Key = key, + BindOperation = bindOperation, + TimeoutOperation = timeoutOperation, + ErrorHandler = errorHandler, + BindingTimeout = bindingTimeout, + WaitForLockTimeout = waitForLockTimeout + }; + + lock (this.bindingQueueLock) + { + this.bindingQueue.AddLast(queueItem); + } + + this.itemQueuedEvent.Set(); + + return queueItem; + } + + /// + /// Checks if a particular binding context is connected or not + /// + /// + public bool IsBindingContextConnected(string key) + { + lock (this.bindingContextLock) + { + IBindingContext context; + if (this.BindingContextMap.TryGetValue(key, out context)) + { + return context.IsConnected; + } + return false; + } + } + + /// + /// Gets or creates a binding context for the provided context key + /// + /// + protected IBindingContext GetOrCreateBindingContext(string key) + { + // use a default binding context for disconnected requests + if (string.IsNullOrWhiteSpace(key)) + { + key = "disconnected_binding_context"; + } + + lock (this.bindingContextLock) + { + if (!this.BindingContextMap.ContainsKey(key)) + { + this.BindingContextMap.Add(key, new T()); + } + + return this.BindingContextMap[key]; + } + } + + protected IEnumerable GetBindingContexts(string keyPrefix) + { + // use a default binding context for disconnected requests + if (string.IsNullOrWhiteSpace(keyPrefix)) + { + keyPrefix = "disconnected_binding_context"; + } + + lock (this.bindingContextLock) + { + return this.BindingContextMap.Where(x => x.Key.StartsWith(keyPrefix)).Select(v => v.Value); + } + } + + /// + /// Checks if a binding context already exists for the provided context key + /// + protected bool BindingContextExists(string key) + { + lock (this.bindingContextLock) + { + return this.BindingContextMap.ContainsKey(key); + } + } + + /// + /// Remove the binding queue entry + /// + protected void RemoveBindingContext(string key) + { + lock (this.bindingContextLock) + { + if (this.BindingContextMap.ContainsKey(key)) + { + // disconnect existing connection + var bindingContext = this.BindingContextMap[key]; + if (bindingContext.ServerConnection != null && bindingContext.ServerConnection.IsOpen) + { + bindingContext.ServerConnection.Disconnect(); + } + + // remove key from the map + this.BindingContextMap.Remove(key); + } + } + } + + public bool HasPendingQueueItems + { + get + { + lock (this.bindingQueueLock) + { + return this.bindingQueue.Count > 0; + } + } + } + + /// + /// Gets the next pending queue item + /// + private QueueItem GetNextQueueItem() + { + lock (this.bindingQueueLock) + { + if (this.bindingQueue.Count == 0) + { + return null; + } + + QueueItem queueItem = this.bindingQueue.First.Value; + this.bindingQueue.RemoveFirst(); + return queueItem; + } + } + + /// + /// Starts the queue processing thread + /// + private Task StartQueueProcessorAsync() + { + if (this.processQueueCancelToken != null) + { + this.processQueueCancelToken.Dispose(); + } + this.processQueueCancelToken = new CancellationTokenSource(); + + return Task.Factory.StartNew( + ProcessQueue, + this.processQueueCancelToken.Token, + TaskCreationOptions.LongRunning, + TaskScheduler.Default); + } + + /// + /// The core queue processing method + /// + /// + private void ProcessQueue() + { + CancellationToken token = this.processQueueCancelToken.Token; + WaitHandle[] waitHandles = new WaitHandle[2] + { + this.itemQueuedEvent, + token.WaitHandle + }; + + while (true) + { + // wait for with an item to be queued or the a cancellation request + WaitHandle.WaitAny(waitHandles); + if (token.IsCancellationRequested) + { + break; + } + + try + { + // dispatch all pending queue items + while (this.HasPendingQueueItems) + { + QueueItem queueItem = GetNextQueueItem(); + if (queueItem == null) + { + continue; + } + + IBindingContext bindingContext = GetOrCreateBindingContext(queueItem.Key); + if (bindingContext == null) + { + queueItem.ItemProcessed.Set(); + continue; + } + + bool lockTaken = false; + try + { + // prefer the queue item binding item, otherwise use the context default timeout + int bindTimeout = queueItem.BindingTimeout ?? bindingContext.BindingTimeout; + + // handle the case a previous binding operation is still running + if (!bindingContext.BindingLock.WaitOne(queueItem.WaitForLockTimeout ?? 0)) + { + queueItem.Result = queueItem.TimeoutOperation != null + ? queueItem.TimeoutOperation(bindingContext) + : null; + + continue; + } + + bindingContext.BindingLock.Reset(); + + lockTaken = true; + + // execute the binding operation + object result = null; + CancellationTokenSource cancelToken = new CancellationTokenSource(); + + // run the operation in a separate thread + var bindTask = Task.Run(() => + { + try + { + result = queueItem.BindOperation( + bindingContext, + cancelToken.Token); + } + catch (Exception ex) + { + Logger.Instance.Write(LogLevel.Error, "Unexpected exception on the binding queue: " + ex.ToString()); + if (queueItem.ErrorHandler != null) + { + result = queueItem.ErrorHandler(ex); + } + } + }); + + // check if the binding tasks completed within the binding timeout + if (bindTask.Wait(bindTimeout)) + { + queueItem.Result = result; + } + else + { + cancelToken.Cancel(); + + // if the task didn't complete then call the timeout callback + if (queueItem.TimeoutOperation != null) + { + queueItem.Result = queueItem.TimeoutOperation(bindingContext); + } + + lockTaken = false; + + bindTask + .ContinueWith((a) => bindingContext.BindingLock.Set()) + .ContinueWithOnFaulted(t => Logger.Instance.Write(LogLevel.Error, "Binding queue threw exception " + t.Exception.ToString())); + } + } + catch (Exception ex) + { + // catch and log any exceptions raised in the binding calls + // set item processed to avoid deadlocks + Logger.Instance.Write(LogLevel.Error, "Binding queue threw exception " + ex.ToString()); + } + finally + { + if (lockTaken) + { + bindingContext.BindingLock.Set(); + } + + queueItem.ItemProcessed.Set(); + } + + // if a queue processing cancellation was requested then exit the loop + if (token.IsCancellationRequested) + { + break; + } + } + } + finally + { + lock (this.bindingQueueLock) + { + // verify the binding queue is still empty + if (this.bindingQueue.Count == 0) + { + // reset the item queued event since we've processed all the pending items + this.itemQueuedEvent.Reset(); + } + } + } + } + } + + /// + /// Clear queued items + /// + public void ClearQueuedItems() + { + lock (this.bindingQueueLock) + { + if (this.bindingQueue.Count > 0) + { + this.bindingQueue.Clear(); + } + } + } + + public void Dispose() + { + if (this.processQueueCancelToken != null) + { + this.processQueueCancelToken.Dispose(); + } + + if (itemQueuedEvent != null) + { + itemQueuedEvent.Dispose(); + } + + if (this.BindingContextMap != null) + { + foreach (var item in this.BindingContextMap) + { + if (item.Value != null && item.Value.ServerConnection != null && item.Value.ServerConnection.SqlConnectionObject != null) + { + item.Value.ServerConnection.SqlConnectionObject.Close(); + } + } + } + } + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/LanguageServices/ConnectedBindingContext.cs b/src/Microsoft.SqlTools.CoreServices/LanguageServices/ConnectedBindingContext.cs new file mode 100644 index 00000000..3b94405e --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/LanguageServices/ConnectedBindingContext.cs @@ -0,0 +1,217 @@ +// +// 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.Threading; +using Microsoft.SqlServer.Management.Common; +using Microsoft.SqlServer.Management.SmoMetadataProvider; +using Microsoft.SqlServer.Management.SqlParser.Binder; +using Microsoft.SqlServer.Management.SqlParser.Common; +using Microsoft.SqlServer.Management.SqlParser.MetadataProvider; +using Microsoft.SqlServer.Management.SqlParser.Parser; +using Microsoft.SqlTools.CoreServices.Utility; + +namespace Microsoft.SqlTools.CoreServices.LanguageServices +{ + /// + /// Class for the binding context for connected sessions + /// + public class ConnectedBindingContext : IBindingContext + { + private ParseOptions parseOptions; + + private ManualResetEvent bindingLock; + + private ServerConnection serverConnection; + + /// + /// Connected binding context constructor + /// + public ConnectedBindingContext() + { + this.bindingLock = new ManualResetEvent(initialState: true); + this.BindingTimeout = ConnectedBindingQueue.DefaultBindingTimeout; + this.MetadataDisplayInfoProvider = new MetadataDisplayInfoProvider(); + } + + /// + /// Gets or sets a flag indicating if the binder is connected + /// + public bool IsConnected { get; set; } + + /// + /// Gets or sets the binding server connection + /// + public ServerConnection ServerConnection + { + get + { + return this.serverConnection; + } + set + { + this.serverConnection = value; + + // reset the parse options so the get recreated for the current connection + this.parseOptions = null; + } + } + + /// + /// Gets or sets the metadata display info provider + /// + public MetadataDisplayInfoProvider MetadataDisplayInfoProvider { get; set; } + + /// + /// Gets or sets the SMO metadata provider + /// + public SmoMetadataProvider SmoMetadataProvider { get; set; } + + /// + /// Gets or sets the binder + /// + public IBinder Binder { get; set; } + + /// + /// Gets the binding lock object + /// + public ManualResetEvent BindingLock + { + get + { + return this.bindingLock; + } + } + + /// + /// Gets or sets the binding operation timeout in milliseconds + /// + public int BindingTimeout { get; set; } + + /// + /// Gets the Language Service ServerVersion + /// + public ServerVersion ServerVersion + { + get + { + return this.ServerConnection != null + ? this.ServerConnection.ServerVersion + : null; + } + } + + /// + /// Gets the current DataEngineType + /// + public DatabaseEngineType DatabaseEngineType + { + get + { + return this.ServerConnection != null + ? this.ServerConnection.DatabaseEngineType + : DatabaseEngineType.Standalone; + } + } + + /// + /// Gets the current connections TransactSqlVersion + /// + public TransactSqlVersion TransactSqlVersion + { + get + { + return this.IsConnected + ? GetTransactSqlVersion(this.ServerVersion) + : TransactSqlVersion.Current; + } + } + + /// + /// Gets the current DatabaseCompatibilityLevel + /// + public DatabaseCompatibilityLevel DatabaseCompatibilityLevel + { + get + { + return this.IsConnected + ? GetDatabaseCompatibilityLevel(this.ServerVersion) + : DatabaseCompatibilityLevel.Current; + } + } + + /// + /// Gets the current ParseOptions + /// + public ParseOptions ParseOptions + { + get + { + if (this.parseOptions == null) + { + this.parseOptions = new ParseOptions( + batchSeparator: CommonConstants.DefaultBatchSeperator, + isQuotedIdentifierSet: true, + compatibilityLevel: DatabaseCompatibilityLevel, + transactSqlVersion: TransactSqlVersion); + } + return this.parseOptions; + } + } + + + /// + /// Gets the database compatibility level from a server version + /// + /// + private static DatabaseCompatibilityLevel GetDatabaseCompatibilityLevel(ServerVersion serverVersion) + { + int versionMajor = Math.Max(serverVersion.Major, 8); + + switch (versionMajor) + { + case 8: + return DatabaseCompatibilityLevel.Version80; + case 9: + return DatabaseCompatibilityLevel.Version90; + case 10: + return DatabaseCompatibilityLevel.Version100; + case 11: + return DatabaseCompatibilityLevel.Version110; + case 12: + return DatabaseCompatibilityLevel.Version120; + case 13: + return DatabaseCompatibilityLevel.Version130; + default: + return DatabaseCompatibilityLevel.Current; + } + } + + /// + /// Gets the transaction sql version from a server version + /// + /// + private static TransactSqlVersion GetTransactSqlVersion(ServerVersion serverVersion) + { + int versionMajor = Math.Max(serverVersion.Major, 9); + + switch (versionMajor) + { + case 9: + case 10: + // In case of 10.0 we still use Version 10.5 as it is the closest available. + return TransactSqlVersion.Version105; + case 11: + return TransactSqlVersion.Version110; + case 12: + return TransactSqlVersion.Version120; + case 13: + return TransactSqlVersion.Version130; + default: + return TransactSqlVersion.Current; + } + } + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/LanguageServices/ConnectedBindingQueue.cs b/src/Microsoft.SqlTools.CoreServices/LanguageServices/ConnectedBindingQueue.cs new file mode 100644 index 00000000..cbeb9031 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/LanguageServices/ConnectedBindingQueue.cs @@ -0,0 +1,231 @@ +// +// 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.Data.SqlClient; +using Microsoft.SqlServer.Management.Common; +using Microsoft.SqlServer.Management.SmoMetadataProvider; +using Microsoft.SqlServer.Management.SqlParser.Binder; +using Microsoft.SqlServer.Management.SqlParser.MetadataProvider; +using Microsoft.SqlTools.CoreServices.Connection; +using Microsoft.SqlTools.DataProtocol.Contracts.Connection; +using System.Threading; +using Microsoft.SqlTools.CoreServices.Workspace; +using Microsoft.SqlTools.CoreServices.SqlContext; + +namespace Microsoft.SqlTools.CoreServices.LanguageServices +{ + public interface IConnectedBindingQueue + { + void CloseConnections(string serverName, string databaseName, int millisecondsTimeout); + void OpenConnections(string serverName, string databaseName, int millisecondsTimeout); + string AddConnectionContext(ConnectionInfo connInfo, string featureName = null, bool overwrite = false); + void Dispose(); + QueueItem QueueBindingOperation( + string key, + Func bindOperation, + Func timeoutOperation = null, + Func errorHandler = null, + int? bindingTimeout = null, + int? waitForLockTimeout = null); + } + + public class SqlConnectionOpener + { + /// + /// Virtual method used to support mocking and testing + /// + public virtual SqlConnection OpenSqlConnection(ConnectionInfo connInfo, string featureName) + { + return ConnectionServiceCore.OpenSqlConnection(connInfo, featureName); + } + } + + /// + /// ConnectedBindingQueue class for processing online binding requests + /// + public class ConnectedBindingQueue : BindingQueue, IConnectedBindingQueue + { + internal const int DefaultBindingTimeout = 500; + + internal const int DefaultMinimumConnectionTimeout = 30; + + /// + /// flag determing if the connection queue requires online metadata objects + /// it's much cheaper to not construct these objects if not needed + /// + private bool needsMetadata; + private SqlConnectionOpener connectionOpener; + /// + /// Gets the current settings + /// + internal SqlToolsSettings CurrentSettings + { + get { return SettingsService.Instance.CurrentSettings; } + } + + public ConnectedBindingQueue() + : this(true) + { + } + + public ConnectedBindingQueue(bool needsMetadata) + { + this.needsMetadata = needsMetadata; + this.connectionOpener = new SqlConnectionOpener(); + } + + // For testing purposes only + internal void SetConnectionOpener(SqlConnectionOpener opener) + { + this.connectionOpener = opener; + } + + /// + /// Generate a unique key based on the ConnectionInfo object + /// + /// + private string GetConnectionContextKey(ConnectionInfo connInfo) + { + ConnectionDetails details = connInfo.ConnectionDetails; + string key = string.Format("{0}_{1}_{2}_{3}", + details.ServerName ?? "NULL", + details.DatabaseName ?? "NULL", + details.UserName ?? "NULL", + details.AuthenticationType ?? "NULL" + ); + + if (!string.IsNullOrEmpty(details.DatabaseDisplayName)) + { + key += "_" + details.DatabaseDisplayName; + } + + if (!string.IsNullOrEmpty(details.GroupId)) + { + key += "_" + details.GroupId; + } + + return key; + } + + /// + /// Generate a unique key based on the ConnectionInfo object + /// + /// + private string GetConnectionContextKey(string serverName, string databaseName) + { + return string.Format("{0}_{1}", + serverName ?? "NULL", + databaseName ?? "NULL"); + + } + + public void CloseConnections(string serverName, string databaseName, int millisecondsTimeout) + { + string connectionKey = GetConnectionContextKey(serverName, databaseName); + var contexts = GetBindingContexts(connectionKey); + foreach (var bindingContext in contexts) + { + if (bindingContext.BindingLock.WaitOne(millisecondsTimeout)) + { + bindingContext.ServerConnection.Disconnect(); + } + } + } + + public void OpenConnections(string serverName, string databaseName, int millisecondsTimeout) + { + string connectionKey = GetConnectionContextKey(serverName, databaseName); + var contexts = GetBindingContexts(connectionKey); + foreach (var bindingContext in contexts) + { + if (bindingContext.BindingLock.WaitOne(millisecondsTimeout)) + { + try + { + bindingContext.ServerConnection.Connect(); + } + catch + { + //TODO: remove the binding context? + } + } + } + } + + public void RemoveBindingContext(ConnectionInfo connInfo) + { + string connectionKey = GetConnectionContextKey(connInfo); + if (BindingContextExists(connectionKey)) + { + RemoveBindingContext(connectionKey); + } + } + + /// + /// Use a ConnectionInfo item to create a connected binding context + /// + /// Connection info used to create binding context + /// Overwrite existing context + public virtual string AddConnectionContext(ConnectionInfo connInfo, string featureName = null, bool overwrite = false) + { + if (connInfo == null) + { + return string.Empty; + } + + // lookup the current binding context + string connectionKey = GetConnectionContextKey(connInfo); + if (BindingContextExists(connectionKey)) + { + if (overwrite) + { + RemoveBindingContext(connectionKey); + } + else + { + // no need to populate the context again since the context already exists + return connectionKey; + } + } + IBindingContext bindingContext = this.GetOrCreateBindingContext(connectionKey); + + if (bindingContext.BindingLock.WaitOne()) + { + try + { + bindingContext.BindingLock.Reset(); + SqlConnection sqlConn = connectionOpener.OpenSqlConnection(connInfo, featureName); + + // populate the binding context to work with the SMO metadata provider + bindingContext.ServerConnection = new ServerConnection(sqlConn); + + if (this.needsMetadata) + { + bindingContext.SmoMetadataProvider = SmoMetadataProvider.CreateConnectedProvider(bindingContext.ServerConnection); + bindingContext.MetadataDisplayInfoProvider = new MetadataDisplayInfoProvider(); + bindingContext.MetadataDisplayInfoProvider.BuiltInCasing = + this.CurrentSettings.SqlTools.IntelliSense.LowerCaseSuggestions.Value + ? CasingStyle.Lowercase : CasingStyle.Uppercase; + bindingContext.Binder = BinderProvider.CreateBinder(bindingContext.SmoMetadataProvider); + } + + bindingContext.BindingTimeout = ConnectedBindingQueue.DefaultBindingTimeout; + bindingContext.IsConnected = true; + } + catch (Exception) + { + bindingContext.IsConnected = false; + } + finally + { + bindingContext.BindingLock.Set(); + } + } + + return connectionKey; + } + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/LanguageServices/IBindingContext.cs b/src/Microsoft.SqlTools.CoreServices/LanguageServices/IBindingContext.cs new file mode 100644 index 00000000..baa0126e --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/LanguageServices/IBindingContext.cs @@ -0,0 +1,81 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System.Threading; +using Microsoft.SqlServer.Management.Common; +using Microsoft.SqlServer.Management.SmoMetadataProvider; +using Microsoft.SqlServer.Management.SqlParser.Binder; +using Microsoft.SqlServer.Management.SqlParser.Common; +using Microsoft.SqlServer.Management.SqlParser.MetadataProvider; +using Microsoft.SqlServer.Management.SqlParser.Parser; + +namespace Microsoft.SqlTools.CoreServices.LanguageServices +{ + /// + /// The context used for binding requests + /// + public interface IBindingContext + { + /// + /// Gets or sets a flag indicating if the context is connected + /// + bool IsConnected { get; set; } + + /// + /// Gets or sets the binding server connection + /// + ServerConnection ServerConnection { get; set; } + + /// + /// Gets or sets the metadata display info provider + /// + MetadataDisplayInfoProvider MetadataDisplayInfoProvider { get; set; } + + /// + /// Gets or sets the SMO metadata provider + /// + SmoMetadataProvider SmoMetadataProvider { get; set; } + + /// + /// Gets or sets the binder + /// + IBinder Binder { get; set; } + + /// + /// Gets the binding lock object + /// + ManualResetEvent BindingLock { get; } + + /// + /// Gets or sets the binding operation timeout in milliseconds + /// + int BindingTimeout { get; set; } + + /// + /// Gets or sets the current connection parse options + /// + ParseOptions ParseOptions { get; } + + /// + /// Gets or sets the current connection server version + /// + ServerVersion ServerVersion { get; } + + /// + /// Gets or sets the database engine type + /// + DatabaseEngineType DatabaseEngineType { get; } + + /// + /// Gets or sets the T-SQL version + /// + TransactSqlVersion TransactSqlVersion { get; } + + /// + /// Gets or sets the database compatibility level + /// + DatabaseCompatibilityLevel DatabaseCompatibilityLevel { get; } + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/LanguageServices/LanguageContants.cs b/src/Microsoft.SqlTools.CoreServices/LanguageServices/LanguageContants.cs new file mode 100644 index 00000000..fa8ce36f --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/LanguageServices/LanguageContants.cs @@ -0,0 +1,22 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.CoreServices.LanguageServices +{ + public static class LanguageContants { + private const int OneSecond = 1000; + + internal const int DiagnosticParseDelay = 750; + + internal const int HoverTimeout = 500; + + internal const int BindingTimeout = 500; + + internal const int OnConnectionWaitTimeout = 300 * OneSecond; + + internal const int PeekDefinitionTimeout = 10 * OneSecond; + + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/LanguageServices/QueueItem.cs b/src/Microsoft.SqlTools.CoreServices/LanguageServices/QueueItem.cs new file mode 100644 index 00000000..b72fdbe6 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/LanguageServices/QueueItem.cs @@ -0,0 +1,77 @@ +// +// 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.Threading; + +namespace Microsoft.SqlTools.CoreServices.LanguageServices +{ + /// + /// Class that stores the state of a binding queue request item + /// + public class QueueItem + { + /// + /// QueueItem constructor + /// + public QueueItem() + { + this.ItemProcessed = new ManualResetEvent(initialState: false); + } + + /// + /// Gets or sets the queue item key + /// + public string Key { get; set; } + + /// + /// Gets or sets the bind operation callback method + /// + public Func BindOperation { get; set; } + + /// + /// Gets or sets the timeout operation to call if the bind operation doesn't finish within timeout period + /// + public Func TimeoutOperation { get; set; } + + /// + /// Gets or sets the operation to call if the bind operation encounters an unexpected exception. + /// Supports returning an object in case of the exception occurring since in some cases we need to be + /// tolerant of error cases and still return some value + /// + public Func ErrorHandler { get; set; } + + /// + /// Gets or sets an event to signal when this queue item has been processed + /// + public virtual ManualResetEvent ItemProcessed { get; set; } + + /// + /// Gets or sets the result of the queued task + /// + public object Result { get; set; } + + /// + /// Gets or sets the binding operation timeout in milliseconds + /// + public int? BindingTimeout { get; set; } + + /// + /// Gets or sets the timeout for how long to wait for the binding lock + /// + public int? WaitForLockTimeout { get; set; } + + /// + /// Converts the result of the execution to type T + /// + public T GetResultAsT() where T : class + { + //var task = this.ResultsTask; + return (this.Result != null) + ? this.Result as T + : null; + } + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/LanguageServices/TelemetryNotification.cs b/src/Microsoft.SqlTools.CoreServices/LanguageServices/TelemetryNotification.cs new file mode 100644 index 00000000..dfaedd66 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/LanguageServices/TelemetryNotification.cs @@ -0,0 +1,100 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System.Collections.Generic; +using Microsoft.SqlTools.Hosting.Contracts; + +namespace Microsoft.SqlTools.CoreServices.LanguageServices.Contracts +{ + public class TelemetryProperties + { + public string EventName { get; set; } + + /// + /// Telemetry properties + /// + public Dictionary Properties { get; set; } + + /// + /// Telemetry measures + /// + public Dictionary Measures { get; set; } + } + + /// + /// Parameters sent back with an IntelliSense ready event + /// + public class TelemetryParams + { + public TelemetryProperties Params { get; set; } + } + + /// + /// Event sent when the language service needs to add a telemetry event + /// + public class TelemetryNotification + { + public static readonly + EventType Type = + EventType.Create("telemetry/sqlevent"); + } + + /// + /// List of telemetry events + /// + public static class TelemetryEventNames + { + /// + /// telemetry event name for auto complete response time + /// + public const string IntellisenseQuantile = "IntellisenseQuantile"; + + /// + /// telemetry event name for when definition is requested + /// + public const string PeekDefinitionRequested = "PeekDefinitionRequested"; + + /// + /// telemetry event name for when definition is requested + /// + public const string FormatCode = "FormatCode"; + } + + /// + /// List of properties used in telemetry events + /// + public static class TelemetryPropertyNames + { + /// + /// Is a connection to an Azure database or not + /// + public const string IsAzure = "IsAzure"; + + /// + /// Did an event succeed or not + /// + public const string Succeeded = "Succeeded"; + + /// + /// Was the action against a connected file or similar resource, or not + /// + public const string Connected = "Connected"; + + /// + /// Format type property - should be one of or + /// + public const string FormatType = "FormatType"; + + /// + /// A full document format + /// + public const string DocumentFormatType = "Document"; + + /// + /// A document range format + /// + public const string RangeFormatType = "Range"; + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/Localization/sr.cs b/src/Microsoft.SqlTools.CoreServices/Localization/sr.cs new file mode 100755 index 00000000..56764778 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Localization/sr.cs @@ -0,0 +1,5172 @@ +// WARNING: +// This file was generated by the Microsoft DataWarehouse String Resource Tool 1.37.0.0 +// from information in sr.strings +// DO NOT MODIFY THIS FILE'S CONTENTS, THEY WILL BE OVERWRITTEN +// +namespace Microsoft.SqlTools.CoreServices +{ + using System; + using System.Reflection; + using System.Resources; + using System.Globalization; + + [System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class SR + { + protected SR() + { } + + public static CultureInfo Culture + { + get + { + return Keys.Culture; + } + set + { + Keys.Culture = value; + } + } + + + public static string ConnectionServiceConnectErrorNullParams + { + get + { + return Keys.GetString(Keys.ConnectionServiceConnectErrorNullParams); + } + } + + public static string ConnectionServiceListDbErrorNullOwnerUri + { + get + { + return Keys.GetString(Keys.ConnectionServiceListDbErrorNullOwnerUri); + } + } + + public static string ConnectionServiceConnectionCanceled + { + get + { + return Keys.GetString(Keys.ConnectionServiceConnectionCanceled); + } + } + + public static string ConnectionParamsValidateNullOwnerUri + { + get + { + return Keys.GetString(Keys.ConnectionParamsValidateNullOwnerUri); + } + } + + public static string ConnectionParamsValidateNullConnection + { + get + { + return Keys.GetString(Keys.ConnectionParamsValidateNullConnection); + } + } + + public static string ConnectionParamsValidateNullServerName + { + get + { + return Keys.GetString(Keys.ConnectionParamsValidateNullServerName); + } + } + + public static string AzureSqlDbEdition + { + get + { + return Keys.GetString(Keys.AzureSqlDbEdition); + } + } + + public static string AzureSqlDwEdition + { + get + { + return Keys.GetString(Keys.AzureSqlDwEdition); + } + } + + public static string AzureSqlStretchEdition + { + get + { + return Keys.GetString(Keys.AzureSqlStretchEdition); + } + } + + public static string QueryServiceCancelAlreadyCompleted + { + get + { + return Keys.GetString(Keys.QueryServiceCancelAlreadyCompleted); + } + } + + public static string QueryServiceCancelDisposeFailed + { + get + { + return Keys.GetString(Keys.QueryServiceCancelDisposeFailed); + } + } + + public static string QueryServiceQueryCancelled + { + get + { + return Keys.GetString(Keys.QueryServiceQueryCancelled); + } + } + + public static string QueryServiceSubsetBatchNotCompleted + { + get + { + return Keys.GetString(Keys.QueryServiceSubsetBatchNotCompleted); + } + } + + public static string QueryServiceSubsetBatchOutOfRange + { + get + { + return Keys.GetString(Keys.QueryServiceSubsetBatchOutOfRange); + } + } + + public static string QueryServiceSubsetResultSetOutOfRange + { + get + { + return Keys.GetString(Keys.QueryServiceSubsetResultSetOutOfRange); + } + } + + public static string QueryServiceDataReaderByteCountInvalid + { + get + { + return Keys.GetString(Keys.QueryServiceDataReaderByteCountInvalid); + } + } + + public static string QueryServiceDataReaderCharCountInvalid + { + get + { + return Keys.GetString(Keys.QueryServiceDataReaderCharCountInvalid); + } + } + + public static string QueryServiceDataReaderXmlCountInvalid + { + get + { + return Keys.GetString(Keys.QueryServiceDataReaderXmlCountInvalid); + } + } + + public static string QueryServiceFileWrapperWriteOnly + { + get + { + return Keys.GetString(Keys.QueryServiceFileWrapperWriteOnly); + } + } + + public static string QueryServiceFileWrapperNotInitialized + { + get + { + return Keys.GetString(Keys.QueryServiceFileWrapperNotInitialized); + } + } + + public static string QueryServiceFileWrapperReadOnly + { + get + { + return Keys.GetString(Keys.QueryServiceFileWrapperReadOnly); + } + } + + public static string QueryServiceAffectedOneRow + { + get + { + return Keys.GetString(Keys.QueryServiceAffectedOneRow); + } + } + + public static string QueryServiceCompletedSuccessfully + { + get + { + return Keys.GetString(Keys.QueryServiceCompletedSuccessfully); + } + } + + public static string QueryServiceColumnNull + { + get + { + return Keys.GetString(Keys.QueryServiceColumnNull); + } + } + + public static string QueryServiceCellNull + { + get + { + return Keys.GetString(Keys.QueryServiceCellNull); + } + } + + public static string QueryServiceRequestsNoQuery + { + get + { + return Keys.GetString(Keys.QueryServiceRequestsNoQuery); + } + } + + public static string QueryServiceQueryInvalidOwnerUri + { + get + { + return Keys.GetString(Keys.QueryServiceQueryInvalidOwnerUri); + } + } + + public static string QueryServiceQueryInProgress + { + get + { + return Keys.GetString(Keys.QueryServiceQueryInProgress); + } + } + + public static string QueryServiceMessageSenderNotSql + { + get + { + return Keys.GetString(Keys.QueryServiceMessageSenderNotSql); + } + } + + public static string QueryServiceResultSetAddNoRows + { + get + { + return Keys.GetString(Keys.QueryServiceResultSetAddNoRows); + } + } + + public static string QueryServiceResultSetHasNoResults + { + get + { + return Keys.GetString(Keys.QueryServiceResultSetHasNoResults); + } + } + + public static string QueryServiceResultSetTooLarge + { + get + { + return Keys.GetString(Keys.QueryServiceResultSetTooLarge); + } + } + + public static string QueryServiceSaveAsResultSetNotComplete + { + get + { + return Keys.GetString(Keys.QueryServiceSaveAsResultSetNotComplete); + } + } + + public static string QueryServiceSaveAsMiscStartingError + { + get + { + return Keys.GetString(Keys.QueryServiceSaveAsMiscStartingError); + } + } + + public static string QueryServiceSaveAsInProgress + { + get + { + return Keys.GetString(Keys.QueryServiceSaveAsInProgress); + } + } + + public static string QueryServiceResultSetNotRead + { + get + { + return Keys.GetString(Keys.QueryServiceResultSetNotRead); + } + } + + public static string QueryServiceResultSetStartRowOutOfRange + { + get + { + return Keys.GetString(Keys.QueryServiceResultSetStartRowOutOfRange); + } + } + + public static string QueryServiceResultSetRowCountOutOfRange + { + get + { + return Keys.GetString(Keys.QueryServiceResultSetRowCountOutOfRange); + } + } + + public static string QueryServiceResultSetNoColumnSchema + { + get + { + return Keys.GetString(Keys.QueryServiceResultSetNoColumnSchema); + } + } + + public static string QueryServiceExecutionPlanNotFound + { + get + { + return Keys.GetString(Keys.QueryServiceExecutionPlanNotFound); + } + } + + public static string PeekDefinitionNoResultsError + { + get + { + return Keys.GetString(Keys.PeekDefinitionNoResultsError); + } + } + + public static string PeekDefinitionDatabaseError + { + get + { + return Keys.GetString(Keys.PeekDefinitionDatabaseError); + } + } + + public static string PeekDefinitionNotConnectedError + { + get + { + return Keys.GetString(Keys.PeekDefinitionNotConnectedError); + } + } + + public static string PeekDefinitionTimedoutError + { + get + { + return Keys.GetString(Keys.PeekDefinitionTimedoutError); + } + } + + public static string PeekDefinitionTypeNotSupportedError + { + get + { + return Keys.GetString(Keys.PeekDefinitionTypeNotSupportedError); + } + } + + public static string ErrorEmptyStringReplacement + { + get + { + return Keys.GetString(Keys.ErrorEmptyStringReplacement); + } + } + + public static string WorkspaceServicePositionLineOutOfRange + { + get + { + return Keys.GetString(Keys.WorkspaceServicePositionLineOutOfRange); + } + } + + public static string EditDataObjectNotFound + { + get + { + return Keys.GetString(Keys.EditDataObjectNotFound); + } + } + + public static string EditDataSessionNotFound + { + get + { + return Keys.GetString(Keys.EditDataSessionNotFound); + } + } + + public static string EditDataSessionAlreadyExists + { + get + { + return Keys.GetString(Keys.EditDataSessionAlreadyExists); + } + } + + public static string EditDataSessionNotInitialized + { + get + { + return Keys.GetString(Keys.EditDataSessionNotInitialized); + } + } + + public static string EditDataSessionAlreadyInitialized + { + get + { + return Keys.GetString(Keys.EditDataSessionAlreadyInitialized); + } + } + + public static string EditDataSessionAlreadyInitializing + { + get + { + return Keys.GetString(Keys.EditDataSessionAlreadyInitializing); + } + } + + public static string EditDataMetadataNotExtended + { + get + { + return Keys.GetString(Keys.EditDataMetadataNotExtended); + } + } + + public static string EditDataMetadataObjectNameRequired + { + get + { + return Keys.GetString(Keys.EditDataMetadataObjectNameRequired); + } + } + + public static string EditDataMetadataTooManyIdentifiers + { + get + { + return Keys.GetString(Keys.EditDataMetadataTooManyIdentifiers); + } + } + + public static string EditDataFilteringNegativeLimit + { + get + { + return Keys.GetString(Keys.EditDataFilteringNegativeLimit); + } + } + + public static string EditDataQueryFailed + { + get + { + return Keys.GetString(Keys.EditDataQueryFailed); + } + } + + public static string EditDataQueryNotCompleted + { + get + { + return Keys.GetString(Keys.EditDataQueryNotCompleted); + } + } + + public static string EditDataQueryImproperResultSets + { + get + { + return Keys.GetString(Keys.EditDataQueryImproperResultSets); + } + } + + public static string EditDataFailedAddRow + { + get + { + return Keys.GetString(Keys.EditDataFailedAddRow); + } + } + + public static string EditDataRowOutOfRange + { + get + { + return Keys.GetString(Keys.EditDataRowOutOfRange); + } + } + + public static string EditDataUpdatePending + { + get + { + return Keys.GetString(Keys.EditDataUpdatePending); + } + } + + public static string EditDataUpdateNotPending + { + get + { + return Keys.GetString(Keys.EditDataUpdateNotPending); + } + } + + public static string EditDataObjectMetadataNotFound + { + get + { + return Keys.GetString(Keys.EditDataObjectMetadataNotFound); + } + } + + public static string EditDataInvalidFormatBinary + { + get + { + return Keys.GetString(Keys.EditDataInvalidFormatBinary); + } + } + + public static string EditDataInvalidFormatBoolean + { + get + { + return Keys.GetString(Keys.EditDataInvalidFormatBoolean); + } + } + + public static string EditDataDeleteSetCell + { + get + { + return Keys.GetString(Keys.EditDataDeleteSetCell); + } + } + + public static string EditDataColumnIdOutOfRange + { + get + { + return Keys.GetString(Keys.EditDataColumnIdOutOfRange); + } + } + + public static string EditDataColumnCannotBeEdited + { + get + { + return Keys.GetString(Keys.EditDataColumnCannotBeEdited); + } + } + + public static string EditDataColumnNoKeyColumns + { + get + { + return Keys.GetString(Keys.EditDataColumnNoKeyColumns); + } + } + + public static string EditDataScriptFilePathNull + { + get + { + return Keys.GetString(Keys.EditDataScriptFilePathNull); + } + } + + public static string EditDataCommitInProgress + { + get + { + return Keys.GetString(Keys.EditDataCommitInProgress); + } + } + + public static string EditDataComputedColumnPlaceholder + { + get + { + return Keys.GetString(Keys.EditDataComputedColumnPlaceholder); + } + } + + public static string EditDataTimeOver24Hrs + { + get + { + return Keys.GetString(Keys.EditDataTimeOver24Hrs); + } + } + + public static string EditDataNullNotAllowed + { + get + { + return Keys.GetString(Keys.EditDataNullNotAllowed); + } + } + + public static string EE_BatchSqlMessageNoProcedureInfo + { + get + { + return Keys.GetString(Keys.EE_BatchSqlMessageNoProcedureInfo); + } + } + + public static string EE_BatchSqlMessageWithProcedureInfo + { + get + { + return Keys.GetString(Keys.EE_BatchSqlMessageWithProcedureInfo); + } + } + + public static string EE_BatchSqlMessageNoLineInfo + { + get + { + return Keys.GetString(Keys.EE_BatchSqlMessageNoLineInfo); + } + } + + public static string EE_BatchError_Exception + { + get + { + return Keys.GetString(Keys.EE_BatchError_Exception); + } + } + + public static string EE_BatchExecutionInfo_RowsAffected + { + get + { + return Keys.GetString(Keys.EE_BatchExecutionInfo_RowsAffected); + } + } + + public static string EE_ExecutionNotYetCompleteError + { + get + { + return Keys.GetString(Keys.EE_ExecutionNotYetCompleteError); + } + } + + public static string EE_ScriptError_Error + { + get + { + return Keys.GetString(Keys.EE_ScriptError_Error); + } + } + + public static string EE_ScriptError_ParsingSyntax + { + get + { + return Keys.GetString(Keys.EE_ScriptError_ParsingSyntax); + } + } + + public static string EE_ScriptError_FatalError + { + get + { + return Keys.GetString(Keys.EE_ScriptError_FatalError); + } + } + + public static string EE_ExecutionInfo_FinalizingLoop + { + get + { + return Keys.GetString(Keys.EE_ExecutionInfo_FinalizingLoop); + } + } + + public static string EE_ExecutionInfo_QueryCancelledbyUser + { + get + { + return Keys.GetString(Keys.EE_ExecutionInfo_QueryCancelledbyUser); + } + } + + public static string EE_BatchExecutionError_Halting + { + get + { + return Keys.GetString(Keys.EE_BatchExecutionError_Halting); + } + } + + public static string EE_BatchExecutionError_Ignoring + { + get + { + return Keys.GetString(Keys.EE_BatchExecutionError_Ignoring); + } + } + + public static string EE_ExecutionInfo_InitializingLoop + { + get + { + return Keys.GetString(Keys.EE_ExecutionInfo_InitializingLoop); + } + } + + public static string EE_ExecutionError_CommandNotSupported + { + get + { + return Keys.GetString(Keys.EE_ExecutionError_CommandNotSupported); + } + } + + public static string EE_ExecutionError_VariableNotFound + { + get + { + return Keys.GetString(Keys.EE_ExecutionError_VariableNotFound); + } + } + + public static string BatchParserWrapperExecutionEngineError + { + get + { + return Keys.GetString(Keys.BatchParserWrapperExecutionEngineError); + } + } + + public static string BatchParserWrapperExecutionError + { + get + { + return Keys.GetString(Keys.BatchParserWrapperExecutionError); + } + } + + public static string BatchParserWrapperExecutionEngineBatchMessage + { + get + { + return Keys.GetString(Keys.BatchParserWrapperExecutionEngineBatchMessage); + } + } + + public static string BatchParserWrapperExecutionEngineBatchResultSetProcessing + { + get + { + return Keys.GetString(Keys.BatchParserWrapperExecutionEngineBatchResultSetProcessing); + } + } + + public static string BatchParserWrapperExecutionEngineBatchResultSetFinished + { + get + { + return Keys.GetString(Keys.BatchParserWrapperExecutionEngineBatchResultSetFinished); + } + } + + public static string BatchParserWrapperExecutionEngineBatchCancelling + { + get + { + return Keys.GetString(Keys.BatchParserWrapperExecutionEngineBatchCancelling); + } + } + + public static string EE_ScriptError_Warning + { + get + { + return Keys.GetString(Keys.EE_ScriptError_Warning); + } + } + + public static string TroubleshootingAssistanceMessage + { + get + { + return Keys.GetString(Keys.TroubleshootingAssistanceMessage); + } + } + + public static string BatchParser_CircularReference + { + get + { + return Keys.GetString(Keys.BatchParser_CircularReference); + } + } + + public static string BatchParser_CommentNotTerminated + { + get + { + return Keys.GetString(Keys.BatchParser_CommentNotTerminated); + } + } + + public static string BatchParser_StringNotTerminated + { + get + { + return Keys.GetString(Keys.BatchParser_StringNotTerminated); + } + } + + public static string BatchParser_IncorrectSyntax + { + get + { + return Keys.GetString(Keys.BatchParser_IncorrectSyntax); + } + } + + public static string BatchParser_VariableNotDefined + { + get + { + return Keys.GetString(Keys.BatchParser_VariableNotDefined); + } + } + + public static string TestLocalizationConstant + { + get + { + return Keys.GetString(Keys.TestLocalizationConstant); + } + } + + public static string SqlScriptFormatterDecimalMissingPrecision + { + get + { + return Keys.GetString(Keys.SqlScriptFormatterDecimalMissingPrecision); + } + } + + public static string SqlScriptFormatterLengthTypeMissingSize + { + get + { + return Keys.GetString(Keys.SqlScriptFormatterLengthTypeMissingSize); + } + } + + public static string SqlScriptFormatterScalarTypeMissingScale + { + get + { + return Keys.GetString(Keys.SqlScriptFormatterScalarTypeMissingScale); + } + } + + public static string TreeNodeError + { + get + { + return Keys.GetString(Keys.TreeNodeError); + } + } + + public static string ServerNodeConnectionError + { + get + { + return Keys.GetString(Keys.ServerNodeConnectionError); + } + } + + public static string SchemaHierarchy_Aggregates + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Aggregates); + } + } + + public static string SchemaHierarchy_ServerRoles + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ServerRoles); + } + } + + public static string SchemaHierarchy_ApplicationRoles + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ApplicationRoles); + } + } + + public static string SchemaHierarchy_Assemblies + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Assemblies); + } + } + + public static string SchemaHierarchy_AssemblyFiles + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_AssemblyFiles); + } + } + + public static string SchemaHierarchy_AsymmetricKeys + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_AsymmetricKeys); + } + } + + public static string SchemaHierarchy_DatabaseAsymmetricKeys + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_DatabaseAsymmetricKeys); + } + } + + public static string SchemaHierarchy_DataCompressionOptions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_DataCompressionOptions); + } + } + + public static string SchemaHierarchy_Certificates + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Certificates); + } + } + + public static string SchemaHierarchy_FileTables + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_FileTables); + } + } + + public static string SchemaHierarchy_DatabaseCertificates + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_DatabaseCertificates); + } + } + + public static string SchemaHierarchy_CheckConstraints + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_CheckConstraints); + } + } + + public static string SchemaHierarchy_Columns + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Columns); + } + } + + public static string SchemaHierarchy_Constraints + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Constraints); + } + } + + public static string SchemaHierarchy_Contracts + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Contracts); + } + } + + public static string SchemaHierarchy_Credentials + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Credentials); + } + } + + public static string SchemaHierarchy_ErrorMessages + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ErrorMessages); + } + } + + public static string SchemaHierarchy_ServerRoleMembership + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ServerRoleMembership); + } + } + + public static string SchemaHierarchy_DatabaseOptions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_DatabaseOptions); + } + } + + public static string SchemaHierarchy_DatabaseRoles + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_DatabaseRoles); + } + } + + public static string SchemaHierarchy_RoleMemberships + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_RoleMemberships); + } + } + + public static string SchemaHierarchy_DatabaseTriggers + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_DatabaseTriggers); + } + } + + public static string SchemaHierarchy_DefaultConstraints + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_DefaultConstraints); + } + } + + public static string SchemaHierarchy_Defaults + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Defaults); + } + } + + public static string SchemaHierarchy_Sequences + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Sequences); + } + } + + public static string SchemaHierarchy_Endpoints + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Endpoints); + } + } + + public static string SchemaHierarchy_EventNotifications + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_EventNotifications); + } + } + + public static string SchemaHierarchy_ServerEventNotifications + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ServerEventNotifications); + } + } + + public static string SchemaHierarchy_ExtendedProperties + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ExtendedProperties); + } + } + + public static string SchemaHierarchy_FileGroups + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_FileGroups); + } + } + + public static string SchemaHierarchy_ForeignKeys + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ForeignKeys); + } + } + + public static string SchemaHierarchy_FullTextCatalogs + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_FullTextCatalogs); + } + } + + public static string SchemaHierarchy_FullTextIndexes + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_FullTextIndexes); + } + } + + public static string SchemaHierarchy_Functions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Functions); + } + } + + public static string SchemaHierarchy_Indexes + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Indexes); + } + } + + public static string SchemaHierarchy_InlineFunctions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_InlineFunctions); + } + } + + public static string SchemaHierarchy_Keys + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Keys); + } + } + + public static string SchemaHierarchy_LinkedServers + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_LinkedServers); + } + } + + public static string SchemaHierarchy_LinkedServerLogins + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_LinkedServerLogins); + } + } + + public static string SchemaHierarchy_Logins + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Logins); + } + } + + public static string SchemaHierarchy_MasterKey + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_MasterKey); + } + } + + public static string SchemaHierarchy_MasterKeys + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_MasterKeys); + } + } + + public static string SchemaHierarchy_MessageTypes + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_MessageTypes); + } + } + + public static string SchemaHierarchy_MultiSelectFunctions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_MultiSelectFunctions); + } + } + + public static string SchemaHierarchy_Parameters + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Parameters); + } + } + + public static string SchemaHierarchy_PartitionFunctions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_PartitionFunctions); + } + } + + public static string SchemaHierarchy_PartitionSchemes + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_PartitionSchemes); + } + } + + public static string SchemaHierarchy_Permissions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Permissions); + } + } + + public static string SchemaHierarchy_PrimaryKeys + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_PrimaryKeys); + } + } + + public static string SchemaHierarchy_Programmability + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Programmability); + } + } + + public static string SchemaHierarchy_Queues + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Queues); + } + } + + public static string SchemaHierarchy_RemoteServiceBindings + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_RemoteServiceBindings); + } + } + + public static string SchemaHierarchy_ReturnedColumns + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ReturnedColumns); + } + } + + public static string SchemaHierarchy_Roles + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Roles); + } + } + + public static string SchemaHierarchy_Routes + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Routes); + } + } + + public static string SchemaHierarchy_Rules + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Rules); + } + } + + public static string SchemaHierarchy_Schemas + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Schemas); + } + } + + public static string SchemaHierarchy_Security + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Security); + } + } + + public static string SchemaHierarchy_ServerObjects + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ServerObjects); + } + } + + public static string SchemaHierarchy_Management + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Management); + } + } + + public static string SchemaHierarchy_ServerTriggers + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ServerTriggers); + } + } + + public static string SchemaHierarchy_ServiceBroker + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ServiceBroker); + } + } + + public static string SchemaHierarchy_Services + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Services); + } + } + + public static string SchemaHierarchy_Signatures + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Signatures); + } + } + + public static string SchemaHierarchy_LogFiles + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_LogFiles); + } + } + + public static string SchemaHierarchy_Statistics + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Statistics); + } + } + + public static string SchemaHierarchy_Storage + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Storage); + } + } + + public static string SchemaHierarchy_StoredProcedures + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_StoredProcedures); + } + } + + public static string SchemaHierarchy_SymmetricKeys + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SymmetricKeys); + } + } + + public static string SchemaHierarchy_Synonyms + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Synonyms); + } + } + + public static string SchemaHierarchy_Tables + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Tables); + } + } + + public static string SchemaHierarchy_Triggers + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Triggers); + } + } + + public static string SchemaHierarchy_Types + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Types); + } + } + + public static string SchemaHierarchy_UniqueKeys + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_UniqueKeys); + } + } + + public static string SchemaHierarchy_UserDefinedDataTypes + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_UserDefinedDataTypes); + } + } + + public static string SchemaHierarchy_UserDefinedTypes + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_UserDefinedTypes); + } + } + + public static string SchemaHierarchy_Users + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Users); + } + } + + public static string SchemaHierarchy_Views + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Views); + } + } + + public static string SchemaHierarchy_XmlIndexes + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_XmlIndexes); + } + } + + public static string SchemaHierarchy_XMLSchemaCollections + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_XMLSchemaCollections); + } + } + + public static string SchemaHierarchy_UserDefinedTableTypes + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_UserDefinedTableTypes); + } + } + + public static string SchemaHierarchy_FilegroupFiles + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_FilegroupFiles); + } + } + + public static string MissingCaption + { + get + { + return Keys.GetString(Keys.MissingCaption); + } + } + + public static string SchemaHierarchy_BrokerPriorities + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_BrokerPriorities); + } + } + + public static string SchemaHierarchy_CryptographicProviders + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_CryptographicProviders); + } + } + + public static string SchemaHierarchy_DatabaseAuditSpecifications + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_DatabaseAuditSpecifications); + } + } + + public static string SchemaHierarchy_DatabaseEncryptionKeys + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_DatabaseEncryptionKeys); + } + } + + public static string SchemaHierarchy_EventSessions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_EventSessions); + } + } + + public static string SchemaHierarchy_FullTextStopLists + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_FullTextStopLists); + } + } + + public static string SchemaHierarchy_ResourcePools + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ResourcePools); + } + } + + public static string SchemaHierarchy_ServerAudits + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ServerAudits); + } + } + + public static string SchemaHierarchy_ServerAuditSpecifications + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ServerAuditSpecifications); + } + } + + public static string SchemaHierarchy_SpatialIndexes + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SpatialIndexes); + } + } + + public static string SchemaHierarchy_WorkloadGroups + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_WorkloadGroups); + } + } + + public static string SchemaHierarchy_SqlFiles + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SqlFiles); + } + } + + public static string SchemaHierarchy_ServerFunctions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ServerFunctions); + } + } + + public static string SchemaHierarchy_SqlType + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SqlType); + } + } + + public static string SchemaHierarchy_ServerOptions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ServerOptions); + } + } + + public static string SchemaHierarchy_DatabaseDiagrams + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_DatabaseDiagrams); + } + } + + public static string SchemaHierarchy_SystemTables + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemTables); + } + } + + public static string SchemaHierarchy_Databases + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Databases); + } + } + + public static string SchemaHierarchy_SystemContracts + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemContracts); + } + } + + public static string SchemaHierarchy_SystemDatabases + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemDatabases); + } + } + + public static string SchemaHierarchy_SystemMessageTypes + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemMessageTypes); + } + } + + public static string SchemaHierarchy_SystemQueues + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemQueues); + } + } + + public static string SchemaHierarchy_SystemServices + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemServices); + } + } + + public static string SchemaHierarchy_SystemStoredProcedures + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemStoredProcedures); + } + } + + public static string SchemaHierarchy_SystemViews + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemViews); + } + } + + public static string SchemaHierarchy_DataTierApplications + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_DataTierApplications); + } + } + + public static string SchemaHierarchy_ExtendedStoredProcedures + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ExtendedStoredProcedures); + } + } + + public static string SchemaHierarchy_SystemAggregateFunctions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemAggregateFunctions); + } + } + + public static string SchemaHierarchy_SystemApproximateNumerics + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemApproximateNumerics); + } + } + + public static string SchemaHierarchy_SystemBinaryStrings + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemBinaryStrings); + } + } + + public static string SchemaHierarchy_SystemCharacterStrings + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemCharacterStrings); + } + } + + public static string SchemaHierarchy_SystemCLRDataTypes + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemCLRDataTypes); + } + } + + public static string SchemaHierarchy_SystemConfigurationFunctions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemConfigurationFunctions); + } + } + + public static string SchemaHierarchy_SystemCursorFunctions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemCursorFunctions); + } + } + + public static string SchemaHierarchy_SystemDataTypes + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemDataTypes); + } + } + + public static string SchemaHierarchy_SystemDateAndTime + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemDateAndTime); + } + } + + public static string SchemaHierarchy_SystemDateAndTimeFunctions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemDateAndTimeFunctions); + } + } + + public static string SchemaHierarchy_SystemExactNumerics + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemExactNumerics); + } + } + + public static string SchemaHierarchy_SystemFunctions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemFunctions); + } + } + + public static string SchemaHierarchy_SystemHierarchyIdFunctions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemHierarchyIdFunctions); + } + } + + public static string SchemaHierarchy_SystemMathematicalFunctions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemMathematicalFunctions); + } + } + + public static string SchemaHierarchy_SystemMetadataFunctions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemMetadataFunctions); + } + } + + public static string SchemaHierarchy_SystemOtherDataTypes + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemOtherDataTypes); + } + } + + public static string SchemaHierarchy_SystemOtherFunctions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemOtherFunctions); + } + } + + public static string SchemaHierarchy_SystemRowsetFunctions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemRowsetFunctions); + } + } + + public static string SchemaHierarchy_SystemSecurityFunctions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemSecurityFunctions); + } + } + + public static string SchemaHierarchy_SystemSpatialDataTypes + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemSpatialDataTypes); + } + } + + public static string SchemaHierarchy_SystemStringFunctions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemStringFunctions); + } + } + + public static string SchemaHierarchy_SystemSystemStatisticalFunctions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemSystemStatisticalFunctions); + } + } + + public static string SchemaHierarchy_SystemTextAndImageFunctions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemTextAndImageFunctions); + } + } + + public static string SchemaHierarchy_SystemUnicodeCharacterStrings + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemUnicodeCharacterStrings); + } + } + + public static string SchemaHierarchy_AggregateFunctions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_AggregateFunctions); + } + } + + public static string SchemaHierarchy_ScalarValuedFunctions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ScalarValuedFunctions); + } + } + + public static string SchemaHierarchy_TableValuedFunctions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_TableValuedFunctions); + } + } + + public static string SchemaHierarchy_SystemExtendedStoredProcedures + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemExtendedStoredProcedures); + } + } + + public static string SchemaHierarchy_BuiltInType + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_BuiltInType); + } + } + + public static string SchemaHierarchy_BuiltInServerRole + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_BuiltInServerRole); + } + } + + public static string SchemaHierarchy_UserWithPassword + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_UserWithPassword); + } + } + + public static string SchemaHierarchy_SearchPropertyList + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SearchPropertyList); + } + } + + public static string SchemaHierarchy_SecurityPolicies + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SecurityPolicies); + } + } + + public static string SchemaHierarchy_SecurityPredicates + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SecurityPredicates); + } + } + + public static string SchemaHierarchy_ServerRole + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ServerRole); + } + } + + public static string SchemaHierarchy_SearchPropertyLists + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SearchPropertyLists); + } + } + + public static string SchemaHierarchy_ColumnStoreIndexes + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ColumnStoreIndexes); + } + } + + public static string SchemaHierarchy_TableTypeIndexes + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_TableTypeIndexes); + } + } + + public static string SchemaHierarchy_Server + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Server); + } + } + + public static string SchemaHierarchy_SelectiveXmlIndexes + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SelectiveXmlIndexes); + } + } + + public static string SchemaHierarchy_XmlNamespaces + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_XmlNamespaces); + } + } + + public static string SchemaHierarchy_XmlTypedPromotedPaths + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_XmlTypedPromotedPaths); + } + } + + public static string SchemaHierarchy_SqlTypedPromotedPaths + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SqlTypedPromotedPaths); + } + } + + public static string SchemaHierarchy_DatabaseScopedCredentials + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_DatabaseScopedCredentials); + } + } + + public static string SchemaHierarchy_ExternalDataSources + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ExternalDataSources); + } + } + + public static string SchemaHierarchy_ExternalFileFormats + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ExternalFileFormats); + } + } + + public static string SchemaHierarchy_ExternalResources + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ExternalResources); + } + } + + public static string SchemaHierarchy_ExternalTables + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ExternalTables); + } + } + + public static string SchemaHierarchy_AlwaysEncryptedKeys + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_AlwaysEncryptedKeys); + } + } + + public static string SchemaHierarchy_ColumnMasterKeys + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ColumnMasterKeys); + } + } + + public static string SchemaHierarchy_ColumnEncryptionKeys + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ColumnEncryptionKeys); + } + } + + public static string SchemaHierarchy_SubroutineParameterLabelFormatString + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SubroutineParameterLabelFormatString); + } + } + + public static string SchemaHierarchy_SubroutineParameterNoDefaultLabel + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SubroutineParameterNoDefaultLabel); + } + } + + public static string SchemaHierarchy_SubroutineParameterInputLabel + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SubroutineParameterInputLabel); + } + } + + public static string SchemaHierarchy_SubroutineParameterInputOutputLabel + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SubroutineParameterInputOutputLabel); + } + } + + public static string SchemaHierarchy_SubroutineParameterInputReadOnlyLabel + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SubroutineParameterInputReadOnlyLabel); + } + } + + public static string SchemaHierarchy_SubroutineParameterInputOutputReadOnlyLabel + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SubroutineParameterInputOutputReadOnlyLabel); + } + } + + public static string SchemaHierarchy_SubroutineParameterDefaultLabel + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SubroutineParameterDefaultLabel); + } + } + + public static string SchemaHierarchy_NullColumn_Label + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_NullColumn_Label); + } + } + + public static string SchemaHierarchy_NotNullColumn_Label + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_NotNullColumn_Label); + } + } + + public static string SchemaHierarchy_UDDTLabelWithType + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_UDDTLabelWithType); + } + } + + public static string SchemaHierarchy_UDDTLabelWithoutType + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_UDDTLabelWithoutType); + } + } + + public static string SchemaHierarchy_ComputedColumnLabelWithType + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ComputedColumnLabelWithType); + } + } + + public static string SchemaHierarchy_ComputedColumnLabelWithoutType + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ComputedColumnLabelWithoutType); + } + } + + public static string SchemaHierarchy_ColumnSetLabelWithoutType + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ColumnSetLabelWithoutType); + } + } + + public static string SchemaHierarchy_ColumnSetLabelWithType + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ColumnSetLabelWithType); + } + } + + public static string SchemaHierarchy_ColumnSetLabelWithTypeAndKeyString + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ColumnSetLabelWithTypeAndKeyString); + } + } + + public static string UniqueIndex_LabelPart + { + get + { + return Keys.GetString(Keys.UniqueIndex_LabelPart); + } + } + + public static string NonUniqueIndex_LabelPart + { + get + { + return Keys.GetString(Keys.NonUniqueIndex_LabelPart); + } + } + + public static string ClusteredIndex_LabelPart + { + get + { + return Keys.GetString(Keys.ClusteredIndex_LabelPart); + } + } + + public static string NonClusteredIndex_LabelPart + { + get + { + return Keys.GetString(Keys.NonClusteredIndex_LabelPart); + } + } + + public static string History_LabelPart + { + get + { + return Keys.GetString(Keys.History_LabelPart); + } + } + + public static string SystemVersioned_LabelPart + { + get + { + return Keys.GetString(Keys.SystemVersioned_LabelPart); + } + } + + public static string External_LabelPart + { + get + { + return Keys.GetString(Keys.External_LabelPart); + } + } + + public static string FileTable_LabelPart + { + get + { + return Keys.GetString(Keys.FileTable_LabelPart); + } + } + + public static string DatabaseNotAccessible + { + get + { + return Keys.GetString(Keys.DatabaseNotAccessible); + } + } + + public static string ScriptingParams_ConnectionString_Property_Invalid + { + get + { + return Keys.GetString(Keys.ScriptingParams_ConnectionString_Property_Invalid); + } + } + + public static string ScriptingParams_FilePath_Property_Invalid + { + get + { + return Keys.GetString(Keys.ScriptingParams_FilePath_Property_Invalid); + } + } + + public static string ScriptingListObjectsCompleteParams_ConnectionString_Property_Invalid + { + get + { + return Keys.GetString(Keys.ScriptingListObjectsCompleteParams_ConnectionString_Property_Invalid); + } + } + + public static string StoredProcedureScriptParameterComment + { + get + { + return Keys.GetString(Keys.StoredProcedureScriptParameterComment); + } + } + + public static string ScriptingGeneralError + { + get + { + return Keys.GetString(Keys.ScriptingGeneralError); + } + } + + public static string ScriptingExecuteNotSupportedError + { + get + { + return Keys.GetString(Keys.ScriptingExecuteNotSupportedError); + } + } + + public static string unavailable + { + get + { + return Keys.GetString(Keys.unavailable); + } + } + + public static string filegroup_dialog_defaultFilegroup + { + get + { + return Keys.GetString(Keys.filegroup_dialog_defaultFilegroup); + } + } + + public static string filegroup_dialog_title + { + get + { + return Keys.GetString(Keys.filegroup_dialog_title); + } + } + + public static string filegroups_default + { + get + { + return Keys.GetString(Keys.filegroups_default); + } + } + + public static string filegroups_files + { + get + { + return Keys.GetString(Keys.filegroups_files); + } + } + + public static string filegroups_name + { + get + { + return Keys.GetString(Keys.filegroups_name); + } + } + + public static string filegroups_readonly + { + get + { + return Keys.GetString(Keys.filegroups_readonly); + } + } + + public static string general_autogrowth + { + get + { + return Keys.GetString(Keys.general_autogrowth); + } + } + + public static string general_builderText + { + get + { + return Keys.GetString(Keys.general_builderText); + } + } + + public static string general_default + { + get + { + return Keys.GetString(Keys.general_default); + } + } + + public static string general_fileGroup + { + get + { + return Keys.GetString(Keys.general_fileGroup); + } + } + + public static string general_fileName + { + get + { + return Keys.GetString(Keys.general_fileName); + } + } + + public static string general_fileType + { + get + { + return Keys.GetString(Keys.general_fileType); + } + } + + public static string general_initialSize + { + get + { + return Keys.GetString(Keys.general_initialSize); + } + } + + public static string general_newFilegroup + { + get + { + return Keys.GetString(Keys.general_newFilegroup); + } + } + + public static string general_path + { + get + { + return Keys.GetString(Keys.general_path); + } + } + + public static string general_physicalFileName + { + get + { + return Keys.GetString(Keys.general_physicalFileName); + } + } + + public static string general_rawDevice + { + get + { + return Keys.GetString(Keys.general_rawDevice); + } + } + + public static string general_recoveryModel_bulkLogged + { + get + { + return Keys.GetString(Keys.general_recoveryModel_bulkLogged); + } + } + + public static string general_recoveryModel_full + { + get + { + return Keys.GetString(Keys.general_recoveryModel_full); + } + } + + public static string general_recoveryModel_simple + { + get + { + return Keys.GetString(Keys.general_recoveryModel_simple); + } + } + + public static string general_titleSearchOwner + { + get + { + return Keys.GetString(Keys.general_titleSearchOwner); + } + } + + public static string prototype_autogrowth_disabled + { + get + { + return Keys.GetString(Keys.prototype_autogrowth_disabled); + } + } + + public static string prototype_autogrowth_restrictedGrowthByMB + { + get + { + return Keys.GetString(Keys.prototype_autogrowth_restrictedGrowthByMB); + } + } + + public static string prototype_autogrowth_restrictedGrowthByPercent + { + get + { + return Keys.GetString(Keys.prototype_autogrowth_restrictedGrowthByPercent); + } + } + + public static string prototype_autogrowth_unrestrictedGrowthByMB + { + get + { + return Keys.GetString(Keys.prototype_autogrowth_unrestrictedGrowthByMB); + } + } + + public static string prototype_autogrowth_unrestrictedGrowthByPercent + { + get + { + return Keys.GetString(Keys.prototype_autogrowth_unrestrictedGrowthByPercent); + } + } + + public static string prototype_autogrowth_unlimitedfilestream + { + get + { + return Keys.GetString(Keys.prototype_autogrowth_unlimitedfilestream); + } + } + + public static string prototype_autogrowth_limitedfilestream + { + get + { + return Keys.GetString(Keys.prototype_autogrowth_limitedfilestream); + } + } + + public static string prototype_db_category_automatic + { + get + { + return Keys.GetString(Keys.prototype_db_category_automatic); + } + } + + public static string prototype_db_category_servicebroker + { + get + { + return Keys.GetString(Keys.prototype_db_category_servicebroker); + } + } + + public static string prototype_db_category_collation + { + get + { + return Keys.GetString(Keys.prototype_db_category_collation); + } + } + + public static string prototype_db_category_cursor + { + get + { + return Keys.GetString(Keys.prototype_db_category_cursor); + } + } + + public static string prototype_db_category_misc + { + get + { + return Keys.GetString(Keys.prototype_db_category_misc); + } + } + + public static string prototype_db_category_recovery + { + get + { + return Keys.GetString(Keys.prototype_db_category_recovery); + } + } + + public static string prototype_db_category_state + { + get + { + return Keys.GetString(Keys.prototype_db_category_state); + } + } + + public static string prototype_db_prop_ansiNullDefault + { + get + { + return Keys.GetString(Keys.prototype_db_prop_ansiNullDefault); + } + } + + public static string prototype_db_prop_ansiNulls + { + get + { + return Keys.GetString(Keys.prototype_db_prop_ansiNulls); + } + } + + public static string prototype_db_prop_ansiPadding + { + get + { + return Keys.GetString(Keys.prototype_db_prop_ansiPadding); + } + } + + public static string prototype_db_prop_ansiWarnings + { + get + { + return Keys.GetString(Keys.prototype_db_prop_ansiWarnings); + } + } + + public static string prototype_db_prop_arithabort + { + get + { + return Keys.GetString(Keys.prototype_db_prop_arithabort); + } + } + + public static string prototype_db_prop_autoClose + { + get + { + return Keys.GetString(Keys.prototype_db_prop_autoClose); + } + } + + public static string prototype_db_prop_autoCreateStatistics + { + get + { + return Keys.GetString(Keys.prototype_db_prop_autoCreateStatistics); + } + } + + public static string prototype_db_prop_autoShrink + { + get + { + return Keys.GetString(Keys.prototype_db_prop_autoShrink); + } + } + + public static string prototype_db_prop_autoUpdateStatistics + { + get + { + return Keys.GetString(Keys.prototype_db_prop_autoUpdateStatistics); + } + } + + public static string prototype_db_prop_autoUpdateStatisticsAsync + { + get + { + return Keys.GetString(Keys.prototype_db_prop_autoUpdateStatisticsAsync); + } + } + + public static string prototype_db_prop_caseSensitive + { + get + { + return Keys.GetString(Keys.prototype_db_prop_caseSensitive); + } + } + + public static string prototype_db_prop_closeCursorOnCommit + { + get + { + return Keys.GetString(Keys.prototype_db_prop_closeCursorOnCommit); + } + } + + public static string prototype_db_prop_collation + { + get + { + return Keys.GetString(Keys.prototype_db_prop_collation); + } + } + + public static string prototype_db_prop_concatNullYieldsNull + { + get + { + return Keys.GetString(Keys.prototype_db_prop_concatNullYieldsNull); + } + } + + public static string prototype_db_prop_databaseCompatibilityLevel + { + get + { + return Keys.GetString(Keys.prototype_db_prop_databaseCompatibilityLevel); + } + } + + public static string prototype_db_prop_databaseState + { + get + { + return Keys.GetString(Keys.prototype_db_prop_databaseState); + } + } + + public static string prototype_db_prop_defaultCursor + { + get + { + return Keys.GetString(Keys.prototype_db_prop_defaultCursor); + } + } + + public static string prototype_db_prop_fullTextIndexing + { + get + { + return Keys.GetString(Keys.prototype_db_prop_fullTextIndexing); + } + } + + public static string prototype_db_prop_numericRoundAbort + { + get + { + return Keys.GetString(Keys.prototype_db_prop_numericRoundAbort); + } + } + + public static string prototype_db_prop_pageVerify + { + get + { + return Keys.GetString(Keys.prototype_db_prop_pageVerify); + } + } + + public static string prototype_db_prop_quotedIdentifier + { + get + { + return Keys.GetString(Keys.prototype_db_prop_quotedIdentifier); + } + } + + public static string prototype_db_prop_readOnly + { + get + { + return Keys.GetString(Keys.prototype_db_prop_readOnly); + } + } + + public static string prototype_db_prop_recursiveTriggers + { + get + { + return Keys.GetString(Keys.prototype_db_prop_recursiveTriggers); + } + } + + public static string prototype_db_prop_restrictAccess + { + get + { + return Keys.GetString(Keys.prototype_db_prop_restrictAccess); + } + } + + public static string prototype_db_prop_selectIntoBulkCopy + { + get + { + return Keys.GetString(Keys.prototype_db_prop_selectIntoBulkCopy); + } + } + + public static string prototype_db_prop_honorBrokerPriority + { + get + { + return Keys.GetString(Keys.prototype_db_prop_honorBrokerPriority); + } + } + + public static string prototype_db_prop_serviceBrokerGuid + { + get + { + return Keys.GetString(Keys.prototype_db_prop_serviceBrokerGuid); + } + } + + public static string prototype_db_prop_brokerEnabled + { + get + { + return Keys.GetString(Keys.prototype_db_prop_brokerEnabled); + } + } + + public static string prototype_db_prop_truncateLogOnCheckpoint + { + get + { + return Keys.GetString(Keys.prototype_db_prop_truncateLogOnCheckpoint); + } + } + + public static string prototype_db_prop_dbChaining + { + get + { + return Keys.GetString(Keys.prototype_db_prop_dbChaining); + } + } + + public static string prototype_db_prop_trustworthy + { + get + { + return Keys.GetString(Keys.prototype_db_prop_trustworthy); + } + } + + public static string prototype_db_prop_dateCorrelationOptimization + { + get + { + return Keys.GetString(Keys.prototype_db_prop_dateCorrelationOptimization); + } + } + + public static string prototype_db_prop_parameterization + { + get + { + return Keys.GetString(Keys.prototype_db_prop_parameterization); + } + } + + public static string prototype_db_prop_parameterization_value_forced + { + get + { + return Keys.GetString(Keys.prototype_db_prop_parameterization_value_forced); + } + } + + public static string prototype_db_prop_parameterization_value_simple + { + get + { + return Keys.GetString(Keys.prototype_db_prop_parameterization_value_simple); + } + } + + public static string prototype_file_dataFile + { + get + { + return Keys.GetString(Keys.prototype_file_dataFile); + } + } + + public static string prototype_file_logFile + { + get + { + return Keys.GetString(Keys.prototype_file_logFile); + } + } + + public static string prototype_file_filestreamFile + { + get + { + return Keys.GetString(Keys.prototype_file_filestreamFile); + } + } + + public static string prototype_file_noFileGroup + { + get + { + return Keys.GetString(Keys.prototype_file_noFileGroup); + } + } + + public static string prototype_file_defaultpathstring + { + get + { + return Keys.GetString(Keys.prototype_file_defaultpathstring); + } + } + + public static string title_openConnectionsMustBeClosed + { + get + { + return Keys.GetString(Keys.title_openConnectionsMustBeClosed); + } + } + + public static string warning_openConnectionsMustBeClosed + { + get + { + return Keys.GetString(Keys.warning_openConnectionsMustBeClosed); + } + } + + public static string prototype_db_prop_databaseState_value_autoClosed + { + get + { + return Keys.GetString(Keys.prototype_db_prop_databaseState_value_autoClosed); + } + } + + public static string prototype_db_prop_databaseState_value_emergency + { + get + { + return Keys.GetString(Keys.prototype_db_prop_databaseState_value_emergency); + } + } + + public static string prototype_db_prop_databaseState_value_inaccessible + { + get + { + return Keys.GetString(Keys.prototype_db_prop_databaseState_value_inaccessible); + } + } + + public static string prototype_db_prop_databaseState_value_normal + { + get + { + return Keys.GetString(Keys.prototype_db_prop_databaseState_value_normal); + } + } + + public static string prototype_db_prop_databaseState_value_offline + { + get + { + return Keys.GetString(Keys.prototype_db_prop_databaseState_value_offline); + } + } + + public static string prototype_db_prop_databaseState_value_recovering + { + get + { + return Keys.GetString(Keys.prototype_db_prop_databaseState_value_recovering); + } + } + + public static string prototype_db_prop_databaseState_value_recoveryPending + { + get + { + return Keys.GetString(Keys.prototype_db_prop_databaseState_value_recoveryPending); + } + } + + public static string prototype_db_prop_databaseState_value_restoring + { + get + { + return Keys.GetString(Keys.prototype_db_prop_databaseState_value_restoring); + } + } + + public static string prototype_db_prop_databaseState_value_shutdown + { + get + { + return Keys.GetString(Keys.prototype_db_prop_databaseState_value_shutdown); + } + } + + public static string prototype_db_prop_databaseState_value_standby + { + get + { + return Keys.GetString(Keys.prototype_db_prop_databaseState_value_standby); + } + } + + public static string prototype_db_prop_databaseState_value_suspect + { + get + { + return Keys.GetString(Keys.prototype_db_prop_databaseState_value_suspect); + } + } + + public static string prototype_db_prop_defaultCursor_value_global + { + get + { + return Keys.GetString(Keys.prototype_db_prop_defaultCursor_value_global); + } + } + + public static string prototype_db_prop_defaultCursor_value_local + { + get + { + return Keys.GetString(Keys.prototype_db_prop_defaultCursor_value_local); + } + } + + public static string prototype_db_prop_restrictAccess_value_multiple + { + get + { + return Keys.GetString(Keys.prototype_db_prop_restrictAccess_value_multiple); + } + } + + public static string prototype_db_prop_restrictAccess_value_restricted + { + get + { + return Keys.GetString(Keys.prototype_db_prop_restrictAccess_value_restricted); + } + } + + public static string prototype_db_prop_restrictAccess_value_single + { + get + { + return Keys.GetString(Keys.prototype_db_prop_restrictAccess_value_single); + } + } + + public static string prototype_db_prop_pageVerify_value_checksum + { + get + { + return Keys.GetString(Keys.prototype_db_prop_pageVerify_value_checksum); + } + } + + public static string prototype_db_prop_pageVerify_value_none + { + get + { + return Keys.GetString(Keys.prototype_db_prop_pageVerify_value_none); + } + } + + public static string prototype_db_prop_pageVerify_value_tornPageDetection + { + get + { + return Keys.GetString(Keys.prototype_db_prop_pageVerify_value_tornPageDetection); + } + } + + public static string prototype_db_prop_varDecimalEnabled + { + get + { + return Keys.GetString(Keys.prototype_db_prop_varDecimalEnabled); + } + } + + public static string compatibilityLevel_katmai + { + get + { + return Keys.GetString(Keys.compatibilityLevel_katmai); + } + } + + public static string prototype_db_prop_encryptionEnabled + { + get + { + return Keys.GetString(Keys.prototype_db_prop_encryptionEnabled); + } + } + + public static string prototype_db_prop_databasescopedconfig_value_off + { + get + { + return Keys.GetString(Keys.prototype_db_prop_databasescopedconfig_value_off); + } + } + + public static string prototype_db_prop_databasescopedconfig_value_on + { + get + { + return Keys.GetString(Keys.prototype_db_prop_databasescopedconfig_value_on); + } + } + + public static string prototype_db_prop_databasescopedconfig_value_primary + { + get + { + return Keys.GetString(Keys.prototype_db_prop_databasescopedconfig_value_primary); + } + } + + public static string error_db_prop_invalidleadingColumns + { + get + { + return Keys.GetString(Keys.error_db_prop_invalidleadingColumns); + } + } + + public static string compatibilityLevel_denali + { + get + { + return Keys.GetString(Keys.compatibilityLevel_denali); + } + } + + public static string compatibilityLevel_sql14 + { + get + { + return Keys.GetString(Keys.compatibilityLevel_sql14); + } + } + + public static string compatibilityLevel_sql15 + { + get + { + return Keys.GetString(Keys.compatibilityLevel_sql15); + } + } + + public static string compatibilityLevel_sqlvNext + { + get + { + return Keys.GetString(Keys.compatibilityLevel_sqlvNext); + } + } + + public static string general_containmentType_None + { + get + { + return Keys.GetString(Keys.general_containmentType_None); + } + } + + public static string general_containmentType_Partial + { + get + { + return Keys.GetString(Keys.general_containmentType_Partial); + } + } + + public static string filegroups_filestreamFiles + { + get + { + return Keys.GetString(Keys.filegroups_filestreamFiles); + } + } + + public static string prototype_file_noApplicableFileGroup + { + get + { + return Keys.GetString(Keys.prototype_file_noApplicableFileGroup); + } + } + + public static string NeverBackedUp + { + get + { + return Keys.GetString(Keys.NeverBackedUp); + } + } + + public static string Error_InvalidDirectoryName + { + get + { + return Keys.GetString(Keys.Error_InvalidDirectoryName); + } + } + + public static string Error_ExistingDirectoryName + { + get + { + return Keys.GetString(Keys.Error_ExistingDirectoryName); + } + } + + public static string BackupTaskName + { + get + { + return Keys.GetString(Keys.BackupTaskName); + } + } + + public static string BackupPathIsFolderError + { + get + { + return Keys.GetString(Keys.BackupPathIsFolderError); + } + } + + public static string InvalidBackupPathError + { + get + { + return Keys.GetString(Keys.InvalidBackupPathError); + } + } + + public static string TaskInProgress + { + get + { + return Keys.GetString(Keys.TaskInProgress); + } + } + + public static string TaskCompleted + { + get + { + return Keys.GetString(Keys.TaskCompleted); + } + } + + public static string ConflictWithNoRecovery + { + get + { + return Keys.GetString(Keys.ConflictWithNoRecovery); + } + } + + public static string InvalidPathForDatabaseFile + { + get + { + return Keys.GetString(Keys.InvalidPathForDatabaseFile); + } + } + + public static string Log + { + get + { + return Keys.GetString(Keys.Log); + } + } + + public static string RestorePlanFailed + { + get + { + return Keys.GetString(Keys.RestorePlanFailed); + } + } + + public static string RestoreNotSupported + { + get + { + return Keys.GetString(Keys.RestoreNotSupported); + } + } + + public static string RestoreTaskName + { + get + { + return Keys.GetString(Keys.RestoreTaskName); + } + } + + 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 TheLastBackupTaken + { + get + { + return Keys.GetString(Keys.TheLastBackupTaken); + } + } + + public static string NoBackupsetsToRestore + { + get + { + return Keys.GetString(Keys.NoBackupsetsToRestore); + } + } + + public static string ScriptTaskName + { + get + { + return Keys.GetString(Keys.ScriptTaskName); + } + } + + public static string InvalidPathError + { + get + { + return Keys.GetString(Keys.InvalidPathError); + } + } + + public static string ProfilerConnectionNotFound + { + get + { + return Keys.GetString(Keys.ProfilerConnectionNotFound); + } + } + + public static string ConnectionServiceListDbErrorNotConnected(string uri) + { + return Keys.GetString(Keys.ConnectionServiceListDbErrorNotConnected, uri); + } + + public static string ConnectionServiceDbErrorDefaultNotConnected(string uri) + { + return Keys.GetString(Keys.ConnectionServiceDbErrorDefaultNotConnected, uri); + } + + public static string ConnectionServiceConnStringInvalidAuthType(string authType) + { + return Keys.GetString(Keys.ConnectionServiceConnStringInvalidAuthType, authType); + } + + public static string ConnectionServiceConnStringInvalidIntent(string intent) + { + return Keys.GetString(Keys.ConnectionServiceConnStringInvalidIntent, intent); + } + + public static string ConnectionParamsValidateNullSqlAuth(string component) + { + return Keys.GetString(Keys.ConnectionParamsValidateNullSqlAuth, component); + } + + public static string QueryServiceAffectedRows(long rows) + { + return Keys.GetString(Keys.QueryServiceAffectedRows, rows); + } + + public static string QueryServiceErrorFormat(int msg, int lvl, int state, int line, string newLine, string message) + { + return Keys.GetString(Keys.QueryServiceErrorFormat, msg, lvl, state, line, newLine, message); + } + + public static string QueryServiceQueryFailed(string message) + { + return Keys.GetString(Keys.QueryServiceQueryFailed, message); + } + + public static string QueryServiceSaveAsFail(string fileName, string message) + { + return Keys.GetString(Keys.QueryServiceSaveAsFail, fileName, message); + } + + public static string PeekDefinitionAzureError(string errorMessage) + { + return Keys.GetString(Keys.PeekDefinitionAzureError, errorMessage); + } + + public static string PeekDefinitionError(string errorMessage) + { + return Keys.GetString(Keys.PeekDefinitionError, errorMessage); + } + + public static string WorkspaceServicePositionColumnOutOfRange(int line) + { + return Keys.GetString(Keys.WorkspaceServicePositionColumnOutOfRange, line); + } + + public static string WorkspaceServiceBufferPositionOutOfOrder(int sLine, int sCol, int eLine, int eCol) + { + return Keys.GetString(Keys.WorkspaceServiceBufferPositionOutOfOrder, sLine, sCol, eLine, eCol); + } + + public static string EditDataUnsupportedObjectType(string typeName) + { + return Keys.GetString(Keys.EditDataUnsupportedObjectType, typeName); + } + + public static string EditDataInvalidFormat(string colName, string colType) + { + return Keys.GetString(Keys.EditDataInvalidFormat, colName, colType); + } + + public static string EditDataCreateScriptMissingValue(string colName) + { + return Keys.GetString(Keys.EditDataCreateScriptMissingValue, colName); + } + + public static string EditDataValueTooLarge(string value, string columnType) + { + return Keys.GetString(Keys.EditDataValueTooLarge, value, columnType); + } + + [System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class Keys + { + static ResourceManager resourceManager = new ResourceManager("Microsoft.SqlTools.CoreServices.Localization.SR", typeof(SR).GetTypeInfo().Assembly); + + static CultureInfo _culture = null; + + + public const string ConnectionServiceConnectErrorNullParams = "ConnectionServiceConnectErrorNullParams"; + + + public const string ConnectionServiceListDbErrorNullOwnerUri = "ConnectionServiceListDbErrorNullOwnerUri"; + + + public const string ConnectionServiceListDbErrorNotConnected = "ConnectionServiceListDbErrorNotConnected"; + + + public const string ConnectionServiceDbErrorDefaultNotConnected = "ConnectionServiceDbErrorDefaultNotConnected"; + + + public const string ConnectionServiceConnStringInvalidAuthType = "ConnectionServiceConnStringInvalidAuthType"; + + + public const string ConnectionServiceConnStringInvalidIntent = "ConnectionServiceConnStringInvalidIntent"; + + + public const string ConnectionServiceConnectionCanceled = "ConnectionServiceConnectionCanceled"; + + + public const string ConnectionParamsValidateNullOwnerUri = "ConnectionParamsValidateNullOwnerUri"; + + + public const string ConnectionParamsValidateNullConnection = "ConnectionParamsValidateNullConnection"; + + + public const string ConnectionParamsValidateNullServerName = "ConnectionParamsValidateNullServerName"; + + + public const string ConnectionParamsValidateNullSqlAuth = "ConnectionParamsValidateNullSqlAuth"; + + + public const string AzureSqlDbEdition = "AzureSqlDbEdition"; + + + public const string AzureSqlDwEdition = "AzureSqlDwEdition"; + + + public const string AzureSqlStretchEdition = "AzureSqlStretchEdition"; + + + public const string QueryServiceCancelAlreadyCompleted = "QueryServiceCancelAlreadyCompleted"; + + + public const string QueryServiceCancelDisposeFailed = "QueryServiceCancelDisposeFailed"; + + + public const string QueryServiceQueryCancelled = "QueryServiceQueryCancelled"; + + + public const string QueryServiceSubsetBatchNotCompleted = "QueryServiceSubsetBatchNotCompleted"; + + + public const string QueryServiceSubsetBatchOutOfRange = "QueryServiceSubsetBatchOutOfRange"; + + + public const string QueryServiceSubsetResultSetOutOfRange = "QueryServiceSubsetResultSetOutOfRange"; + + + public const string QueryServiceDataReaderByteCountInvalid = "QueryServiceDataReaderByteCountInvalid"; + + + public const string QueryServiceDataReaderCharCountInvalid = "QueryServiceDataReaderCharCountInvalid"; + + + public const string QueryServiceDataReaderXmlCountInvalid = "QueryServiceDataReaderXmlCountInvalid"; + + + public const string QueryServiceFileWrapperWriteOnly = "QueryServiceFileWrapperWriteOnly"; + + + public const string QueryServiceFileWrapperNotInitialized = "QueryServiceFileWrapperNotInitialized"; + + + public const string QueryServiceFileWrapperReadOnly = "QueryServiceFileWrapperReadOnly"; + + + public const string QueryServiceAffectedOneRow = "QueryServiceAffectedOneRow"; + + + public const string QueryServiceAffectedRows = "QueryServiceAffectedRows"; + + + public const string QueryServiceCompletedSuccessfully = "QueryServiceCompletedSuccessfully"; + + + public const string QueryServiceErrorFormat = "QueryServiceErrorFormat"; + + + public const string QueryServiceQueryFailed = "QueryServiceQueryFailed"; + + + public const string QueryServiceColumnNull = "QueryServiceColumnNull"; + + + public const string QueryServiceCellNull = "QueryServiceCellNull"; + + + public const string QueryServiceRequestsNoQuery = "QueryServiceRequestsNoQuery"; + + + public const string QueryServiceQueryInvalidOwnerUri = "QueryServiceQueryInvalidOwnerUri"; + + + public const string QueryServiceQueryInProgress = "QueryServiceQueryInProgress"; + + + public const string QueryServiceMessageSenderNotSql = "QueryServiceMessageSenderNotSql"; + + + public const string QueryServiceResultSetAddNoRows = "QueryServiceResultSetAddNoRows"; + + + public const string QueryServiceResultSetHasNoResults = "QueryServiceResultSetHasNoResults"; + + + public const string QueryServiceResultSetTooLarge = "QueryServiceResultSetTooLarge"; + + + public const string QueryServiceSaveAsResultSetNotComplete = "QueryServiceSaveAsResultSetNotComplete"; + + + public const string QueryServiceSaveAsMiscStartingError = "QueryServiceSaveAsMiscStartingError"; + + + public const string QueryServiceSaveAsInProgress = "QueryServiceSaveAsInProgress"; + + + public const string QueryServiceSaveAsFail = "QueryServiceSaveAsFail"; + + + public const string QueryServiceResultSetNotRead = "QueryServiceResultSetNotRead"; + + + public const string QueryServiceResultSetStartRowOutOfRange = "QueryServiceResultSetStartRowOutOfRange"; + + + public const string QueryServiceResultSetRowCountOutOfRange = "QueryServiceResultSetRowCountOutOfRange"; + + + public const string QueryServiceResultSetNoColumnSchema = "QueryServiceResultSetNoColumnSchema"; + + + public const string QueryServiceExecutionPlanNotFound = "QueryServiceExecutionPlanNotFound"; + + + public const string PeekDefinitionAzureError = "PeekDefinitionAzureError"; + + + public const string PeekDefinitionError = "PeekDefinitionError"; + + + public const string PeekDefinitionNoResultsError = "PeekDefinitionNoResultsError"; + + + public const string PeekDefinitionDatabaseError = "PeekDefinitionDatabaseError"; + + + public const string PeekDefinitionNotConnectedError = "PeekDefinitionNotConnectedError"; + + + public const string PeekDefinitionTimedoutError = "PeekDefinitionTimedoutError"; + + + public const string PeekDefinitionTypeNotSupportedError = "PeekDefinitionTypeNotSupportedError"; + + + public const string ErrorEmptyStringReplacement = "ErrorEmptyStringReplacement"; + + + public const string WorkspaceServicePositionLineOutOfRange = "WorkspaceServicePositionLineOutOfRange"; + + + public const string WorkspaceServicePositionColumnOutOfRange = "WorkspaceServicePositionColumnOutOfRange"; + + + public const string WorkspaceServiceBufferPositionOutOfOrder = "WorkspaceServiceBufferPositionOutOfOrder"; + + + public const string EditDataObjectNotFound = "EditDataObjectNotFound"; + + + public const string EditDataSessionNotFound = "EditDataSessionNotFound"; + + + public const string EditDataSessionAlreadyExists = "EditDataSessionAlreadyExists"; + + + public const string EditDataSessionNotInitialized = "EditDataSessionNotInitialized"; + + + public const string EditDataSessionAlreadyInitialized = "EditDataSessionAlreadyInitialized"; + + + public const string EditDataSessionAlreadyInitializing = "EditDataSessionAlreadyInitializing"; + + + public const string EditDataMetadataNotExtended = "EditDataMetadataNotExtended"; + + + public const string EditDataMetadataObjectNameRequired = "EditDataMetadataObjectNameRequired"; + + + public const string EditDataMetadataTooManyIdentifiers = "EditDataMetadataTooManyIdentifiers"; + + + public const string EditDataFilteringNegativeLimit = "EditDataFilteringNegativeLimit"; + + + public const string EditDataUnsupportedObjectType = "EditDataUnsupportedObjectType"; + + + public const string EditDataQueryFailed = "EditDataQueryFailed"; + + + public const string EditDataQueryNotCompleted = "EditDataQueryNotCompleted"; + + + public const string EditDataQueryImproperResultSets = "EditDataQueryImproperResultSets"; + + + public const string EditDataFailedAddRow = "EditDataFailedAddRow"; + + + public const string EditDataRowOutOfRange = "EditDataRowOutOfRange"; + + + public const string EditDataUpdatePending = "EditDataUpdatePending"; + + + public const string EditDataUpdateNotPending = "EditDataUpdateNotPending"; + + + public const string EditDataObjectMetadataNotFound = "EditDataObjectMetadataNotFound"; + + + public const string EditDataInvalidFormat = "EditDataInvalidFormat"; + + + public const string EditDataInvalidFormatBinary = "EditDataInvalidFormatBinary"; + + + public const string EditDataInvalidFormatBoolean = "EditDataInvalidFormatBoolean"; + + + public const string EditDataCreateScriptMissingValue = "EditDataCreateScriptMissingValue"; + + + public const string EditDataDeleteSetCell = "EditDataDeleteSetCell"; + + + public const string EditDataColumnIdOutOfRange = "EditDataColumnIdOutOfRange"; + + + public const string EditDataColumnCannotBeEdited = "EditDataColumnCannotBeEdited"; + + + public const string EditDataColumnNoKeyColumns = "EditDataColumnNoKeyColumns"; + + + public const string EditDataScriptFilePathNull = "EditDataScriptFilePathNull"; + + + public const string EditDataCommitInProgress = "EditDataCommitInProgress"; + + + public const string EditDataComputedColumnPlaceholder = "EditDataComputedColumnPlaceholder"; + + + public const string EditDataTimeOver24Hrs = "EditDataTimeOver24Hrs"; + + + public const string EditDataNullNotAllowed = "EditDataNullNotAllowed"; + + + public const string EditDataValueTooLarge = "EditDataValueTooLarge"; + + + public const string EE_BatchSqlMessageNoProcedureInfo = "EE_BatchSqlMessageNoProcedureInfo"; + + + public const string EE_BatchSqlMessageWithProcedureInfo = "EE_BatchSqlMessageWithProcedureInfo"; + + + public const string EE_BatchSqlMessageNoLineInfo = "EE_BatchSqlMessageNoLineInfo"; + + + public const string EE_BatchError_Exception = "EE_BatchError_Exception"; + + + public const string EE_BatchExecutionInfo_RowsAffected = "EE_BatchExecutionInfo_RowsAffected"; + + + public const string EE_ExecutionNotYetCompleteError = "EE_ExecutionNotYetCompleteError"; + + + public const string EE_ScriptError_Error = "EE_ScriptError_Error"; + + + public const string EE_ScriptError_ParsingSyntax = "EE_ScriptError_ParsingSyntax"; + + + public const string EE_ScriptError_FatalError = "EE_ScriptError_FatalError"; + + + public const string EE_ExecutionInfo_FinalizingLoop = "EE_ExecutionInfo_FinalizingLoop"; + + + public const string EE_ExecutionInfo_QueryCancelledbyUser = "EE_ExecutionInfo_QueryCancelledbyUser"; + + + public const string EE_BatchExecutionError_Halting = "EE_BatchExecutionError_Halting"; + + + public const string EE_BatchExecutionError_Ignoring = "EE_BatchExecutionError_Ignoring"; + + + public const string EE_ExecutionInfo_InitializingLoop = "EE_ExecutionInfo_InitializingLoop"; + + + public const string EE_ExecutionError_CommandNotSupported = "EE_ExecutionError_CommandNotSupported"; + + + public const string EE_ExecutionError_VariableNotFound = "EE_ExecutionError_VariableNotFound"; + + + public const string BatchParserWrapperExecutionEngineError = "BatchParserWrapperExecutionEngineError"; + + + public const string BatchParserWrapperExecutionError = "BatchParserWrapperExecutionError"; + + + public const string BatchParserWrapperExecutionEngineBatchMessage = "BatchParserWrapperExecutionEngineBatchMessage"; + + + public const string BatchParserWrapperExecutionEngineBatchResultSetProcessing = "BatchParserWrapperExecutionEngineBatchResultSetProcessing"; + + + public const string BatchParserWrapperExecutionEngineBatchResultSetFinished = "BatchParserWrapperExecutionEngineBatchResultSetFinished"; + + + public const string BatchParserWrapperExecutionEngineBatchCancelling = "BatchParserWrapperExecutionEngineBatchCancelling"; + + + public const string EE_ScriptError_Warning = "EE_ScriptError_Warning"; + + + public const string TroubleshootingAssistanceMessage = "TroubleshootingAssistanceMessage"; + + + public const string BatchParser_CircularReference = "BatchParser_CircularReference"; + + + public const string BatchParser_CommentNotTerminated = "BatchParser_CommentNotTerminated"; + + + public const string BatchParser_StringNotTerminated = "BatchParser_StringNotTerminated"; + + + public const string BatchParser_IncorrectSyntax = "BatchParser_IncorrectSyntax"; + + + public const string BatchParser_VariableNotDefined = "BatchParser_VariableNotDefined"; + + + public const string TestLocalizationConstant = "TestLocalizationConstant"; + + + public const string SqlScriptFormatterDecimalMissingPrecision = "SqlScriptFormatterDecimalMissingPrecision"; + + + public const string SqlScriptFormatterLengthTypeMissingSize = "SqlScriptFormatterLengthTypeMissingSize"; + + + public const string SqlScriptFormatterScalarTypeMissingScale = "SqlScriptFormatterScalarTypeMissingScale"; + + + public const string TreeNodeError = "TreeNodeError"; + + + public const string ServerNodeConnectionError = "ServerNodeConnectionError"; + + + public const string SchemaHierarchy_Aggregates = "SchemaHierarchy_Aggregates"; + + + public const string SchemaHierarchy_ServerRoles = "SchemaHierarchy_ServerRoles"; + + + public const string SchemaHierarchy_ApplicationRoles = "SchemaHierarchy_ApplicationRoles"; + + + public const string SchemaHierarchy_Assemblies = "SchemaHierarchy_Assemblies"; + + + public const string SchemaHierarchy_AssemblyFiles = "SchemaHierarchy_AssemblyFiles"; + + + public const string SchemaHierarchy_AsymmetricKeys = "SchemaHierarchy_AsymmetricKeys"; + + + public const string SchemaHierarchy_DatabaseAsymmetricKeys = "SchemaHierarchy_DatabaseAsymmetricKeys"; + + + public const string SchemaHierarchy_DataCompressionOptions = "SchemaHierarchy_DataCompressionOptions"; + + + public const string SchemaHierarchy_Certificates = "SchemaHierarchy_Certificates"; + + + public const string SchemaHierarchy_FileTables = "SchemaHierarchy_FileTables"; + + + public const string SchemaHierarchy_DatabaseCertificates = "SchemaHierarchy_DatabaseCertificates"; + + + public const string SchemaHierarchy_CheckConstraints = "SchemaHierarchy_CheckConstraints"; + + + public const string SchemaHierarchy_Columns = "SchemaHierarchy_Columns"; + + + public const string SchemaHierarchy_Constraints = "SchemaHierarchy_Constraints"; + + + public const string SchemaHierarchy_Contracts = "SchemaHierarchy_Contracts"; + + + public const string SchemaHierarchy_Credentials = "SchemaHierarchy_Credentials"; + + + public const string SchemaHierarchy_ErrorMessages = "SchemaHierarchy_ErrorMessages"; + + + public const string SchemaHierarchy_ServerRoleMembership = "SchemaHierarchy_ServerRoleMembership"; + + + public const string SchemaHierarchy_DatabaseOptions = "SchemaHierarchy_DatabaseOptions"; + + + public const string SchemaHierarchy_DatabaseRoles = "SchemaHierarchy_DatabaseRoles"; + + + public const string SchemaHierarchy_RoleMemberships = "SchemaHierarchy_RoleMemberships"; + + + public const string SchemaHierarchy_DatabaseTriggers = "SchemaHierarchy_DatabaseTriggers"; + + + public const string SchemaHierarchy_DefaultConstraints = "SchemaHierarchy_DefaultConstraints"; + + + public const string SchemaHierarchy_Defaults = "SchemaHierarchy_Defaults"; + + + public const string SchemaHierarchy_Sequences = "SchemaHierarchy_Sequences"; + + + public const string SchemaHierarchy_Endpoints = "SchemaHierarchy_Endpoints"; + + + public const string SchemaHierarchy_EventNotifications = "SchemaHierarchy_EventNotifications"; + + + public const string SchemaHierarchy_ServerEventNotifications = "SchemaHierarchy_ServerEventNotifications"; + + + public const string SchemaHierarchy_ExtendedProperties = "SchemaHierarchy_ExtendedProperties"; + + + public const string SchemaHierarchy_FileGroups = "SchemaHierarchy_FileGroups"; + + + public const string SchemaHierarchy_ForeignKeys = "SchemaHierarchy_ForeignKeys"; + + + public const string SchemaHierarchy_FullTextCatalogs = "SchemaHierarchy_FullTextCatalogs"; + + + public const string SchemaHierarchy_FullTextIndexes = "SchemaHierarchy_FullTextIndexes"; + + + public const string SchemaHierarchy_Functions = "SchemaHierarchy_Functions"; + + + public const string SchemaHierarchy_Indexes = "SchemaHierarchy_Indexes"; + + + public const string SchemaHierarchy_InlineFunctions = "SchemaHierarchy_InlineFunctions"; + + + public const string SchemaHierarchy_Keys = "SchemaHierarchy_Keys"; + + + public const string SchemaHierarchy_LinkedServers = "SchemaHierarchy_LinkedServers"; + + + public const string SchemaHierarchy_LinkedServerLogins = "SchemaHierarchy_LinkedServerLogins"; + + + public const string SchemaHierarchy_Logins = "SchemaHierarchy_Logins"; + + + public const string SchemaHierarchy_MasterKey = "SchemaHierarchy_MasterKey"; + + + public const string SchemaHierarchy_MasterKeys = "SchemaHierarchy_MasterKeys"; + + + public const string SchemaHierarchy_MessageTypes = "SchemaHierarchy_MessageTypes"; + + + public const string SchemaHierarchy_MultiSelectFunctions = "SchemaHierarchy_MultiSelectFunctions"; + + + public const string SchemaHierarchy_Parameters = "SchemaHierarchy_Parameters"; + + + public const string SchemaHierarchy_PartitionFunctions = "SchemaHierarchy_PartitionFunctions"; + + + public const string SchemaHierarchy_PartitionSchemes = "SchemaHierarchy_PartitionSchemes"; + + + public const string SchemaHierarchy_Permissions = "SchemaHierarchy_Permissions"; + + + public const string SchemaHierarchy_PrimaryKeys = "SchemaHierarchy_PrimaryKeys"; + + + public const string SchemaHierarchy_Programmability = "SchemaHierarchy_Programmability"; + + + public const string SchemaHierarchy_Queues = "SchemaHierarchy_Queues"; + + + public const string SchemaHierarchy_RemoteServiceBindings = "SchemaHierarchy_RemoteServiceBindings"; + + + public const string SchemaHierarchy_ReturnedColumns = "SchemaHierarchy_ReturnedColumns"; + + + public const string SchemaHierarchy_Roles = "SchemaHierarchy_Roles"; + + + public const string SchemaHierarchy_Routes = "SchemaHierarchy_Routes"; + + + public const string SchemaHierarchy_Rules = "SchemaHierarchy_Rules"; + + + public const string SchemaHierarchy_Schemas = "SchemaHierarchy_Schemas"; + + + public const string SchemaHierarchy_Security = "SchemaHierarchy_Security"; + + + public const string SchemaHierarchy_ServerObjects = "SchemaHierarchy_ServerObjects"; + + + public const string SchemaHierarchy_Management = "SchemaHierarchy_Management"; + + + public const string SchemaHierarchy_ServerTriggers = "SchemaHierarchy_ServerTriggers"; + + + public const string SchemaHierarchy_ServiceBroker = "SchemaHierarchy_ServiceBroker"; + + + public const string SchemaHierarchy_Services = "SchemaHierarchy_Services"; + + + public const string SchemaHierarchy_Signatures = "SchemaHierarchy_Signatures"; + + + public const string SchemaHierarchy_LogFiles = "SchemaHierarchy_LogFiles"; + + + public const string SchemaHierarchy_Statistics = "SchemaHierarchy_Statistics"; + + + public const string SchemaHierarchy_Storage = "SchemaHierarchy_Storage"; + + + public const string SchemaHierarchy_StoredProcedures = "SchemaHierarchy_StoredProcedures"; + + + public const string SchemaHierarchy_SymmetricKeys = "SchemaHierarchy_SymmetricKeys"; + + + public const string SchemaHierarchy_Synonyms = "SchemaHierarchy_Synonyms"; + + + public const string SchemaHierarchy_Tables = "SchemaHierarchy_Tables"; + + + public const string SchemaHierarchy_Triggers = "SchemaHierarchy_Triggers"; + + + public const string SchemaHierarchy_Types = "SchemaHierarchy_Types"; + + + public const string SchemaHierarchy_UniqueKeys = "SchemaHierarchy_UniqueKeys"; + + + public const string SchemaHierarchy_UserDefinedDataTypes = "SchemaHierarchy_UserDefinedDataTypes"; + + + public const string SchemaHierarchy_UserDefinedTypes = "SchemaHierarchy_UserDefinedTypes"; + + + public const string SchemaHierarchy_Users = "SchemaHierarchy_Users"; + + + public const string SchemaHierarchy_Views = "SchemaHierarchy_Views"; + + + public const string SchemaHierarchy_XmlIndexes = "SchemaHierarchy_XmlIndexes"; + + + public const string SchemaHierarchy_XMLSchemaCollections = "SchemaHierarchy_XMLSchemaCollections"; + + + public const string SchemaHierarchy_UserDefinedTableTypes = "SchemaHierarchy_UserDefinedTableTypes"; + + + public const string SchemaHierarchy_FilegroupFiles = "SchemaHierarchy_FilegroupFiles"; + + + public const string MissingCaption = "MissingCaption"; + + + public const string SchemaHierarchy_BrokerPriorities = "SchemaHierarchy_BrokerPriorities"; + + + public const string SchemaHierarchy_CryptographicProviders = "SchemaHierarchy_CryptographicProviders"; + + + public const string SchemaHierarchy_DatabaseAuditSpecifications = "SchemaHierarchy_DatabaseAuditSpecifications"; + + + public const string SchemaHierarchy_DatabaseEncryptionKeys = "SchemaHierarchy_DatabaseEncryptionKeys"; + + + public const string SchemaHierarchy_EventSessions = "SchemaHierarchy_EventSessions"; + + + public const string SchemaHierarchy_FullTextStopLists = "SchemaHierarchy_FullTextStopLists"; + + + public const string SchemaHierarchy_ResourcePools = "SchemaHierarchy_ResourcePools"; + + + public const string SchemaHierarchy_ServerAudits = "SchemaHierarchy_ServerAudits"; + + + public const string SchemaHierarchy_ServerAuditSpecifications = "SchemaHierarchy_ServerAuditSpecifications"; + + + public const string SchemaHierarchy_SpatialIndexes = "SchemaHierarchy_SpatialIndexes"; + + + public const string SchemaHierarchy_WorkloadGroups = "SchemaHierarchy_WorkloadGroups"; + + + public const string SchemaHierarchy_SqlFiles = "SchemaHierarchy_SqlFiles"; + + + public const string SchemaHierarchy_ServerFunctions = "SchemaHierarchy_ServerFunctions"; + + + public const string SchemaHierarchy_SqlType = "SchemaHierarchy_SqlType"; + + + public const string SchemaHierarchy_ServerOptions = "SchemaHierarchy_ServerOptions"; + + + public const string SchemaHierarchy_DatabaseDiagrams = "SchemaHierarchy_DatabaseDiagrams"; + + + public const string SchemaHierarchy_SystemTables = "SchemaHierarchy_SystemTables"; + + + public const string SchemaHierarchy_Databases = "SchemaHierarchy_Databases"; + + + public const string SchemaHierarchy_SystemContracts = "SchemaHierarchy_SystemContracts"; + + + public const string SchemaHierarchy_SystemDatabases = "SchemaHierarchy_SystemDatabases"; + + + public const string SchemaHierarchy_SystemMessageTypes = "SchemaHierarchy_SystemMessageTypes"; + + + public const string SchemaHierarchy_SystemQueues = "SchemaHierarchy_SystemQueues"; + + + public const string SchemaHierarchy_SystemServices = "SchemaHierarchy_SystemServices"; + + + public const string SchemaHierarchy_SystemStoredProcedures = "SchemaHierarchy_SystemStoredProcedures"; + + + public const string SchemaHierarchy_SystemViews = "SchemaHierarchy_SystemViews"; + + + public const string SchemaHierarchy_DataTierApplications = "SchemaHierarchy_DataTierApplications"; + + + public const string SchemaHierarchy_ExtendedStoredProcedures = "SchemaHierarchy_ExtendedStoredProcedures"; + + + public const string SchemaHierarchy_SystemAggregateFunctions = "SchemaHierarchy_SystemAggregateFunctions"; + + + public const string SchemaHierarchy_SystemApproximateNumerics = "SchemaHierarchy_SystemApproximateNumerics"; + + + public const string SchemaHierarchy_SystemBinaryStrings = "SchemaHierarchy_SystemBinaryStrings"; + + + public const string SchemaHierarchy_SystemCharacterStrings = "SchemaHierarchy_SystemCharacterStrings"; + + + public const string SchemaHierarchy_SystemCLRDataTypes = "SchemaHierarchy_SystemCLRDataTypes"; + + + public const string SchemaHierarchy_SystemConfigurationFunctions = "SchemaHierarchy_SystemConfigurationFunctions"; + + + public const string SchemaHierarchy_SystemCursorFunctions = "SchemaHierarchy_SystemCursorFunctions"; + + + public const string SchemaHierarchy_SystemDataTypes = "SchemaHierarchy_SystemDataTypes"; + + + public const string SchemaHierarchy_SystemDateAndTime = "SchemaHierarchy_SystemDateAndTime"; + + + public const string SchemaHierarchy_SystemDateAndTimeFunctions = "SchemaHierarchy_SystemDateAndTimeFunctions"; + + + public const string SchemaHierarchy_SystemExactNumerics = "SchemaHierarchy_SystemExactNumerics"; + + + public const string SchemaHierarchy_SystemFunctions = "SchemaHierarchy_SystemFunctions"; + + + public const string SchemaHierarchy_SystemHierarchyIdFunctions = "SchemaHierarchy_SystemHierarchyIdFunctions"; + + + public const string SchemaHierarchy_SystemMathematicalFunctions = "SchemaHierarchy_SystemMathematicalFunctions"; + + + public const string SchemaHierarchy_SystemMetadataFunctions = "SchemaHierarchy_SystemMetadataFunctions"; + + + public const string SchemaHierarchy_SystemOtherDataTypes = "SchemaHierarchy_SystemOtherDataTypes"; + + + public const string SchemaHierarchy_SystemOtherFunctions = "SchemaHierarchy_SystemOtherFunctions"; + + + public const string SchemaHierarchy_SystemRowsetFunctions = "SchemaHierarchy_SystemRowsetFunctions"; + + + public const string SchemaHierarchy_SystemSecurityFunctions = "SchemaHierarchy_SystemSecurityFunctions"; + + + public const string SchemaHierarchy_SystemSpatialDataTypes = "SchemaHierarchy_SystemSpatialDataTypes"; + + + public const string SchemaHierarchy_SystemStringFunctions = "SchemaHierarchy_SystemStringFunctions"; + + + public const string SchemaHierarchy_SystemSystemStatisticalFunctions = "SchemaHierarchy_SystemSystemStatisticalFunctions"; + + + public const string SchemaHierarchy_SystemTextAndImageFunctions = "SchemaHierarchy_SystemTextAndImageFunctions"; + + + public const string SchemaHierarchy_SystemUnicodeCharacterStrings = "SchemaHierarchy_SystemUnicodeCharacterStrings"; + + + public const string SchemaHierarchy_AggregateFunctions = "SchemaHierarchy_AggregateFunctions"; + + + public const string SchemaHierarchy_ScalarValuedFunctions = "SchemaHierarchy_ScalarValuedFunctions"; + + + public const string SchemaHierarchy_TableValuedFunctions = "SchemaHierarchy_TableValuedFunctions"; + + + public const string SchemaHierarchy_SystemExtendedStoredProcedures = "SchemaHierarchy_SystemExtendedStoredProcedures"; + + + public const string SchemaHierarchy_BuiltInType = "SchemaHierarchy_BuiltInType"; + + + public const string SchemaHierarchy_BuiltInServerRole = "SchemaHierarchy_BuiltInServerRole"; + + + public const string SchemaHierarchy_UserWithPassword = "SchemaHierarchy_UserWithPassword"; + + + public const string SchemaHierarchy_SearchPropertyList = "SchemaHierarchy_SearchPropertyList"; + + + public const string SchemaHierarchy_SecurityPolicies = "SchemaHierarchy_SecurityPolicies"; + + + public const string SchemaHierarchy_SecurityPredicates = "SchemaHierarchy_SecurityPredicates"; + + + public const string SchemaHierarchy_ServerRole = "SchemaHierarchy_ServerRole"; + + + public const string SchemaHierarchy_SearchPropertyLists = "SchemaHierarchy_SearchPropertyLists"; + + + public const string SchemaHierarchy_ColumnStoreIndexes = "SchemaHierarchy_ColumnStoreIndexes"; + + + public const string SchemaHierarchy_TableTypeIndexes = "SchemaHierarchy_TableTypeIndexes"; + + + public const string SchemaHierarchy_Server = "SchemaHierarchy_Server"; + + + public const string SchemaHierarchy_SelectiveXmlIndexes = "SchemaHierarchy_SelectiveXmlIndexes"; + + + public const string SchemaHierarchy_XmlNamespaces = "SchemaHierarchy_XmlNamespaces"; + + + public const string SchemaHierarchy_XmlTypedPromotedPaths = "SchemaHierarchy_XmlTypedPromotedPaths"; + + + public const string SchemaHierarchy_SqlTypedPromotedPaths = "SchemaHierarchy_SqlTypedPromotedPaths"; + + + public const string SchemaHierarchy_DatabaseScopedCredentials = "SchemaHierarchy_DatabaseScopedCredentials"; + + + public const string SchemaHierarchy_ExternalDataSources = "SchemaHierarchy_ExternalDataSources"; + + + public const string SchemaHierarchy_ExternalFileFormats = "SchemaHierarchy_ExternalFileFormats"; + + + public const string SchemaHierarchy_ExternalResources = "SchemaHierarchy_ExternalResources"; + + + public const string SchemaHierarchy_ExternalTables = "SchemaHierarchy_ExternalTables"; + + + public const string SchemaHierarchy_AlwaysEncryptedKeys = "SchemaHierarchy_AlwaysEncryptedKeys"; + + + public const string SchemaHierarchy_ColumnMasterKeys = "SchemaHierarchy_ColumnMasterKeys"; + + + public const string SchemaHierarchy_ColumnEncryptionKeys = "SchemaHierarchy_ColumnEncryptionKeys"; + + + public const string SchemaHierarchy_SubroutineParameterLabelFormatString = "SchemaHierarchy_SubroutineParameterLabelFormatString"; + + + public const string SchemaHierarchy_SubroutineParameterNoDefaultLabel = "SchemaHierarchy_SubroutineParameterNoDefaultLabel"; + + + public const string SchemaHierarchy_SubroutineParameterInputLabel = "SchemaHierarchy_SubroutineParameterInputLabel"; + + + public const string SchemaHierarchy_SubroutineParameterInputOutputLabel = "SchemaHierarchy_SubroutineParameterInputOutputLabel"; + + + public const string SchemaHierarchy_SubroutineParameterInputReadOnlyLabel = "SchemaHierarchy_SubroutineParameterInputReadOnlyLabel"; + + + public const string SchemaHierarchy_SubroutineParameterInputOutputReadOnlyLabel = "SchemaHierarchy_SubroutineParameterInputOutputReadOnlyLabel"; + + + public const string SchemaHierarchy_SubroutineParameterDefaultLabel = "SchemaHierarchy_SubroutineParameterDefaultLabel"; + + + public const string SchemaHierarchy_NullColumn_Label = "SchemaHierarchy_NullColumn_Label"; + + + public const string SchemaHierarchy_NotNullColumn_Label = "SchemaHierarchy_NotNullColumn_Label"; + + + public const string SchemaHierarchy_UDDTLabelWithType = "SchemaHierarchy_UDDTLabelWithType"; + + + public const string SchemaHierarchy_UDDTLabelWithoutType = "SchemaHierarchy_UDDTLabelWithoutType"; + + + public const string SchemaHierarchy_ComputedColumnLabelWithType = "SchemaHierarchy_ComputedColumnLabelWithType"; + + + public const string SchemaHierarchy_ComputedColumnLabelWithoutType = "SchemaHierarchy_ComputedColumnLabelWithoutType"; + + + public const string SchemaHierarchy_ColumnSetLabelWithoutType = "SchemaHierarchy_ColumnSetLabelWithoutType"; + + + public const string SchemaHierarchy_ColumnSetLabelWithType = "SchemaHierarchy_ColumnSetLabelWithType"; + + + public const string SchemaHierarchy_ColumnSetLabelWithTypeAndKeyString = "SchemaHierarchy_ColumnSetLabelWithTypeAndKeyString"; + + + public const string UniqueIndex_LabelPart = "UniqueIndex_LabelPart"; + + + public const string NonUniqueIndex_LabelPart = "NonUniqueIndex_LabelPart"; + + + public const string ClusteredIndex_LabelPart = "ClusteredIndex_LabelPart"; + + + public const string NonClusteredIndex_LabelPart = "NonClusteredIndex_LabelPart"; + + + public const string History_LabelPart = "History_LabelPart"; + + + public const string SystemVersioned_LabelPart = "SystemVersioned_LabelPart"; + + + public const string External_LabelPart = "External_LabelPart"; + + + public const string FileTable_LabelPart = "FileTable_LabelPart"; + + + public const string DatabaseNotAccessible = "DatabaseNotAccessible"; + + + public const string ScriptingParams_ConnectionString_Property_Invalid = "ScriptingParams_ConnectionString_Property_Invalid"; + + + public const string ScriptingParams_FilePath_Property_Invalid = "ScriptingParams_FilePath_Property_Invalid"; + + + public const string ScriptingListObjectsCompleteParams_ConnectionString_Property_Invalid = "ScriptingListObjectsCompleteParams_ConnectionString_Property_Invalid"; + + + public const string StoredProcedureScriptParameterComment = "StoredProcedureScriptParameterComment"; + + + public const string ScriptingGeneralError = "ScriptingGeneralError"; + + + public const string ScriptingExecuteNotSupportedError = "ScriptingExecuteNotSupportedError"; + + + public const string unavailable = "unavailable"; + + + public const string filegroup_dialog_defaultFilegroup = "filegroup_dialog_defaultFilegroup"; + + + public const string filegroup_dialog_title = "filegroup_dialog_title"; + + + public const string filegroups_default = "filegroups_default"; + + + public const string filegroups_files = "filegroups_files"; + + + public const string filegroups_name = "filegroups_name"; + + + public const string filegroups_readonly = "filegroups_readonly"; + + + public const string general_autogrowth = "general_autogrowth"; + + + public const string general_builderText = "general_builderText"; + + + public const string general_default = "general_default"; + + + public const string general_fileGroup = "general_fileGroup"; + + + public const string general_fileName = "general_fileName"; + + + public const string general_fileType = "general_fileType"; + + + public const string general_initialSize = "general_initialSize"; + + + public const string general_newFilegroup = "general_newFilegroup"; + + + public const string general_path = "general_path"; + + + public const string general_physicalFileName = "general_physicalFileName"; + + + public const string general_rawDevice = "general_rawDevice"; + + + public const string general_recoveryModel_bulkLogged = "general_recoveryModel_bulkLogged"; + + + public const string general_recoveryModel_full = "general_recoveryModel_full"; + + + public const string general_recoveryModel_simple = "general_recoveryModel_simple"; + + + public const string general_titleSearchOwner = "general_titleSearchOwner"; + + + public const string prototype_autogrowth_disabled = "prototype_autogrowth_disabled"; + + + public const string prototype_autogrowth_restrictedGrowthByMB = "prototype_autogrowth_restrictedGrowthByMB"; + + + public const string prototype_autogrowth_restrictedGrowthByPercent = "prototype_autogrowth_restrictedGrowthByPercent"; + + + public const string prototype_autogrowth_unrestrictedGrowthByMB = "prototype_autogrowth_unrestrictedGrowthByMB"; + + + public const string prototype_autogrowth_unrestrictedGrowthByPercent = "prototype_autogrowth_unrestrictedGrowthByPercent"; + + + public const string prototype_autogrowth_unlimitedfilestream = "prototype_autogrowth_unlimitedfilestream"; + + + public const string prototype_autogrowth_limitedfilestream = "prototype_autogrowth_limitedfilestream"; + + + public const string prototype_db_category_automatic = "prototype_db_category_automatic"; + + + public const string prototype_db_category_servicebroker = "prototype_db_category_servicebroker"; + + + public const string prototype_db_category_collation = "prototype_db_category_collation"; + + + public const string prototype_db_category_cursor = "prototype_db_category_cursor"; + + + public const string prototype_db_category_misc = "prototype_db_category_misc"; + + + public const string prototype_db_category_recovery = "prototype_db_category_recovery"; + + + public const string prototype_db_category_state = "prototype_db_category_state"; + + + public const string prototype_db_prop_ansiNullDefault = "prototype_db_prop_ansiNullDefault"; + + + public const string prototype_db_prop_ansiNulls = "prototype_db_prop_ansiNulls"; + + + public const string prototype_db_prop_ansiPadding = "prototype_db_prop_ansiPadding"; + + + public const string prototype_db_prop_ansiWarnings = "prototype_db_prop_ansiWarnings"; + + + public const string prototype_db_prop_arithabort = "prototype_db_prop_arithabort"; + + + public const string prototype_db_prop_autoClose = "prototype_db_prop_autoClose"; + + + public const string prototype_db_prop_autoCreateStatistics = "prototype_db_prop_autoCreateStatistics"; + + + public const string prototype_db_prop_autoShrink = "prototype_db_prop_autoShrink"; + + + public const string prototype_db_prop_autoUpdateStatistics = "prototype_db_prop_autoUpdateStatistics"; + + + public const string prototype_db_prop_autoUpdateStatisticsAsync = "prototype_db_prop_autoUpdateStatisticsAsync"; + + + public const string prototype_db_prop_caseSensitive = "prototype_db_prop_caseSensitive"; + + + public const string prototype_db_prop_closeCursorOnCommit = "prototype_db_prop_closeCursorOnCommit"; + + + public const string prototype_db_prop_collation = "prototype_db_prop_collation"; + + + public const string prototype_db_prop_concatNullYieldsNull = "prototype_db_prop_concatNullYieldsNull"; + + + public const string prototype_db_prop_databaseCompatibilityLevel = "prototype_db_prop_databaseCompatibilityLevel"; + + + public const string prototype_db_prop_databaseState = "prototype_db_prop_databaseState"; + + + public const string prototype_db_prop_defaultCursor = "prototype_db_prop_defaultCursor"; + + + public const string prototype_db_prop_fullTextIndexing = "prototype_db_prop_fullTextIndexing"; + + + public const string prototype_db_prop_numericRoundAbort = "prototype_db_prop_numericRoundAbort"; + + + public const string prototype_db_prop_pageVerify = "prototype_db_prop_pageVerify"; + + + public const string prototype_db_prop_quotedIdentifier = "prototype_db_prop_quotedIdentifier"; + + + public const string prototype_db_prop_readOnly = "prototype_db_prop_readOnly"; + + + public const string prototype_db_prop_recursiveTriggers = "prototype_db_prop_recursiveTriggers"; + + + public const string prototype_db_prop_restrictAccess = "prototype_db_prop_restrictAccess"; + + + public const string prototype_db_prop_selectIntoBulkCopy = "prototype_db_prop_selectIntoBulkCopy"; + + + public const string prototype_db_prop_honorBrokerPriority = "prototype_db_prop_honorBrokerPriority"; + + + public const string prototype_db_prop_serviceBrokerGuid = "prototype_db_prop_serviceBrokerGuid"; + + + public const string prototype_db_prop_brokerEnabled = "prototype_db_prop_brokerEnabled"; + + + public const string prototype_db_prop_truncateLogOnCheckpoint = "prototype_db_prop_truncateLogOnCheckpoint"; + + + public const string prototype_db_prop_dbChaining = "prototype_db_prop_dbChaining"; + + + public const string prototype_db_prop_trustworthy = "prototype_db_prop_trustworthy"; + + + public const string prototype_db_prop_dateCorrelationOptimization = "prototype_db_prop_dateCorrelationOptimization"; + + + public const string prototype_db_prop_parameterization = "prototype_db_prop_parameterization"; + + + public const string prototype_db_prop_parameterization_value_forced = "prototype_db_prop_parameterization_value_forced"; + + + public const string prototype_db_prop_parameterization_value_simple = "prototype_db_prop_parameterization_value_simple"; + + + public const string prototype_file_dataFile = "prototype_file_dataFile"; + + + public const string prototype_file_logFile = "prototype_file_logFile"; + + + public const string prototype_file_filestreamFile = "prototype_file_filestreamFile"; + + + public const string prototype_file_noFileGroup = "prototype_file_noFileGroup"; + + + public const string prototype_file_defaultpathstring = "prototype_file_defaultpathstring"; + + + public const string title_openConnectionsMustBeClosed = "title_openConnectionsMustBeClosed"; + + + public const string warning_openConnectionsMustBeClosed = "warning_openConnectionsMustBeClosed"; + + + public const string prototype_db_prop_databaseState_value_autoClosed = "prototype_db_prop_databaseState_value_autoClosed"; + + + public const string prototype_db_prop_databaseState_value_emergency = "prototype_db_prop_databaseState_value_emergency"; + + + public const string prototype_db_prop_databaseState_value_inaccessible = "prototype_db_prop_databaseState_value_inaccessible"; + + + public const string prototype_db_prop_databaseState_value_normal = "prototype_db_prop_databaseState_value_normal"; + + + public const string prototype_db_prop_databaseState_value_offline = "prototype_db_prop_databaseState_value_offline"; + + + public const string prototype_db_prop_databaseState_value_recovering = "prototype_db_prop_databaseState_value_recovering"; + + + public const string prototype_db_prop_databaseState_value_recoveryPending = "prototype_db_prop_databaseState_value_recoveryPending"; + + + public const string prototype_db_prop_databaseState_value_restoring = "prototype_db_prop_databaseState_value_restoring"; + + + public const string prototype_db_prop_databaseState_value_shutdown = "prototype_db_prop_databaseState_value_shutdown"; + + + public const string prototype_db_prop_databaseState_value_standby = "prototype_db_prop_databaseState_value_standby"; + + + public const string prototype_db_prop_databaseState_value_suspect = "prototype_db_prop_databaseState_value_suspect"; + + + public const string prototype_db_prop_defaultCursor_value_global = "prototype_db_prop_defaultCursor_value_global"; + + + public const string prototype_db_prop_defaultCursor_value_local = "prototype_db_prop_defaultCursor_value_local"; + + + public const string prototype_db_prop_restrictAccess_value_multiple = "prototype_db_prop_restrictAccess_value_multiple"; + + + public const string prototype_db_prop_restrictAccess_value_restricted = "prototype_db_prop_restrictAccess_value_restricted"; + + + public const string prototype_db_prop_restrictAccess_value_single = "prototype_db_prop_restrictAccess_value_single"; + + + public const string prototype_db_prop_pageVerify_value_checksum = "prototype_db_prop_pageVerify_value_checksum"; + + + public const string prototype_db_prop_pageVerify_value_none = "prototype_db_prop_pageVerify_value_none"; + + + public const string prototype_db_prop_pageVerify_value_tornPageDetection = "prototype_db_prop_pageVerify_value_tornPageDetection"; + + + public const string prototype_db_prop_varDecimalEnabled = "prototype_db_prop_varDecimalEnabled"; + + + public const string compatibilityLevel_katmai = "compatibilityLevel_katmai"; + + + public const string prototype_db_prop_encryptionEnabled = "prototype_db_prop_encryptionEnabled"; + + + public const string prototype_db_prop_databasescopedconfig_value_off = "prototype_db_prop_databasescopedconfig_value_off"; + + + public const string prototype_db_prop_databasescopedconfig_value_on = "prototype_db_prop_databasescopedconfig_value_on"; + + + public const string prototype_db_prop_databasescopedconfig_value_primary = "prototype_db_prop_databasescopedconfig_value_primary"; + + + public const string error_db_prop_invalidleadingColumns = "error_db_prop_invalidleadingColumns"; + + + public const string compatibilityLevel_denali = "compatibilityLevel_denali"; + + + public const string compatibilityLevel_sql14 = "compatibilityLevel_sql14"; + + + public const string compatibilityLevel_sql15 = "compatibilityLevel_sql15"; + + + public const string compatibilityLevel_sqlvNext = "compatibilityLevel_sqlvNext"; + + + public const string general_containmentType_None = "general_containmentType_None"; + + + public const string general_containmentType_Partial = "general_containmentType_Partial"; + + + public const string filegroups_filestreamFiles = "filegroups_filestreamFiles"; + + + public const string prototype_file_noApplicableFileGroup = "prototype_file_noApplicableFileGroup"; + + + public const string NeverBackedUp = "NeverBackedUp"; + + + public const string Error_InvalidDirectoryName = "Error_InvalidDirectoryName"; + + + public const string Error_ExistingDirectoryName = "Error_ExistingDirectoryName"; + + + public const string BackupTaskName = "BackupTaskName"; + + + public const string BackupPathIsFolderError = "BackupPathIsFolderError"; + + + public const string InvalidBackupPathError = "InvalidBackupPathError"; + + + public const string TaskInProgress = "TaskInProgress"; + + + public const string TaskCompleted = "TaskCompleted"; + + + public const string ConflictWithNoRecovery = "ConflictWithNoRecovery"; + + + public const string InvalidPathForDatabaseFile = "InvalidPathForDatabaseFile"; + + + public const string Log = "Log"; + + + public const string RestorePlanFailed = "RestorePlanFailed"; + + + public const string RestoreNotSupported = "RestoreNotSupported"; + + + 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"; + + + public const string TheLastBackupTaken = "TheLastBackupTaken"; + + + public const string NoBackupsetsToRestore = "NoBackupsetsToRestore"; + + + public const string ScriptTaskName = "ScriptTaskName"; + + + public const string InvalidPathError = "InvalidPathError"; + + + public const string ProfilerConnectionNotFound = "ProfilerConnectionNotFound"; + + + private Keys() + { } + + public static CultureInfo Culture + { + get + { + return _culture; + } + set + { + _culture = value; + } + } + + public static string GetString(string key) + { + return resourceManager.GetString(key, _culture); + } + + + public static string GetString(string key, object arg0) + { + return string.Format(global::System.Globalization.CultureInfo.CurrentCulture, resourceManager.GetString(key, _culture), arg0); + } + + + public static string GetString(string key, object arg0, object arg1) + { + return string.Format(global::System.Globalization.CultureInfo.CurrentCulture, resourceManager.GetString(key, _culture), arg0, arg1); + } + + + public static string GetString(string key, object arg0, object arg1, object arg2, object arg3) + { + return string.Format(global::System.Globalization.CultureInfo.CurrentCulture, resourceManager.GetString(key, _culture), arg0, arg1, arg2, arg3); + } + + + public static string GetString(string key, object arg0, object arg1, object arg2, object arg3, object arg4, object arg5) + { + return string.Format(global::System.Globalization.CultureInfo.CurrentCulture, resourceManager.GetString(key, _culture), arg0, arg1, arg2, arg3, arg4, arg5); + } + + } + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/Localization/sr.de.resx b/src/Microsoft.SqlTools.CoreServices/Localization/sr.de.resx new file mode 100644 index 00000000..2ef7a4fe --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Localization/sr.de.resx @@ -0,0 +1,490 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +text/microsoft-resx1.3System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089Verbindungsparameter dürfen nicht null sein. + OwnerUri darf nicht null oder leer sein. + SpecifiedUri '{0}' hat keine gültige Verbindung + Ungültiger Wert '{0}' für AuthenticationType. Gültige Werte sind 'Integrated' und 'SqlLogin'. + Ungültiger Wert '{0}' für ApplicationIntent. Gültige Werte sind 'ReadWrite' und 'ReadOnly'. + Verbindung wurde abgebrochen. + OwnerUri darf nicht null oder leer sein. + Verbindungsdetails-Objekt darf nicht null sein. + ServerName darf nicht null oder leer sein. + {0} darf bei Verwendung der SqlLogin-Authentifizierung nicht null oder leer sein + Die Abfrage wurde bereits abgeschlossen und kann nicht abgebrochen werden + Abfrage wurde erfolgreich abgebrochen, Fehler beim Abfrage verfügen. Benutzer-URI nicht gefunden. + Die Abfrage wurde vom Benutzer abgebrochen. + Die Stapelverarbeitung ist noch nicht abgeschlossen + Batch-Index darf nicht kleiner als 0 oder größer als die Anzahl der Batches sein. + Der Index der Ergebnismenge darf nicht kleiner als 0 oder größer als die Anzahl der Ergebnismengen sein + Die maximale Anzahl an Bytes die zurückgeben wird, muss größer als 0 sein. + Die maximale Anzahl an Zeichen die zurückgeben werden, muss größer als 0 sein. + Die maximale Anzahl an XML Bytes die zurückgeben wird, muss größer als 0 sein. + Die Zugriffsmethode kann nicht write-only sein. + FileStreamWrapper muss initialisiert werden, bevor Operationen ausführt werden können + Diese FileStreamWrapper kann nicht zum Schreiben verwendet werden + (1 Zeile betroffen) + ({0} Zeilen betroffen) + Die Befehle wurden erfolgreich ausgeführt. + Zeile MSG {0} auf {1} Status {2}, {3} {4} {5} + Fehler bei Abfrage: {0} + (Kein Spaltenname) + Die angeforderte Abfrage ist nicht vorhanden. + Dieser Editor ist nicht mit einer Datenbank verbunden. + Eine Abfrage wird für diese Sitzung bereits ausgeführt. Brechen Sie diese Abfrage ab, oder warten Sie auf Beendigung. + Das sender Objekt für OnInfoMessage muss vom Typ SqlConnection sein + Das Ergebnis kann nicht gespeichert werden, solange die Abfrageausführung nicht abgeschlossen ist. + Beim Speichern ist ein interner Fehler aufgetreten + Eine Speicheranforderung mit demselben Pfad wird bereits ausgeführt. + Fehler beim Speichern von {0}: {1} + Der Teil kann nicht gelesen werden solange die Ergebnisse nicht vom Server gelesen wurden + Index der Startzeile kann nicht kleiner als 0 oder größer als die Anzahl der Zeilen der Ergebnismenge sein + Zeilenanzahl muss eine positive ganze Zahl sein. + Es konnten keine Schemainformationen der Spalte abgerufen werden + Es konnten kein Ausführungsplan für die Ergebnismenge abgerufen werden + Diese Funktionalität wird derzeit nicht in Azure SQL DB ud Data Warehouse unterstützt: {0} + Ein unerwarteter Fehler trat beim Einsehen der Definitionen auf: {0} + Es wurden keine Ergebnisse gefunden. + Es wurde kein Datenbankobjekt abgerufen + Verbinden Sie Sich mit einem Server. + Zeitüberschreitung bei der Ausführung + Dieser Objekttyp wird aktuell von dieser Funktionalität nicht unterstützt + Die Position befindet sich außerhalb der Zeile + Die Position befindet sich außerhalb der Spalte in Zeile {0} + Startposition ({0}, {1}) muss vor oder gleich der Endposition ({2}, {3}) sein + Meldung {0}, Ebene {1}, Status {2}, Zeile {3} + Meldung {0}, Ebene {1}, Status {2}, Prozedur {3}, Zeile {4} + Meldung {0}, Ebene {1}, Status {2} + Fehler beim Ausführen des Batches. Fehlermeldung: {0} + ({0} Zeile(n) betroffen) + Die vorherige Ausführung ist noch nicht abgeschlossen. + Ein Skriptfehler ist aufgetreten. + Ein Syntaxfehler ist aufgetreten der bei Analyse von {0} + Ein schwerwiegender Fehler ist aufgetreten. + {0}-mal ausgeführt... + Sie haben die Abfrage abgebrochen. + Fehler während der Batchausführung. + Fehler während der Batchausführung, aber des Fehlers wurde ignoriert. + Beginning execution loop + Befehl {0} wird nicht unterstützt. + Die Variable {0} konnte nicht gefunden werden. + Fehler bei der SQL-Ausführung: {0} + Batch-Ausführung des Batchanalysewrappers: {0} in Zeile {1} gefunden...: {2} Beschreibung: {3} + Batch Parser Wrapper Execution Engine Meldung empfangen: Meldung: {0} Ausführliche Meldung: {1} + Stapelverarbeitung Parser Wrapper Execution Engine Stapel ResultSet: DataReader.FieldCount: {0} DataReader.RecordsAffected: {1} + Batch-Parser Wrapper Execution Engine wurde beendet ResultSet. + Ausführung des Batchanalysewrappers Batch abgebrochen. + Scripting-Warnung. + Weitere Informationen zu diesem Fehler finden Sie in den entsprechenden Abschnitten der Produktdokumentation. + Die Datei '{0}' ist rekursiv eingeschlossen. + Fehlender End Kommentarzeichen "* /". + Fehlendes schließendes Anführungszeichen nach der Zeichenfolge + Syntaxfehler aufgetreten beim Analysieren von '{0}'. + Variable {0} ist nicht definiert. + Test + Ersatz einer leeren Zeichenfolge durch eine leere Zeichenfolge. + Die Sitzung "{0}" ist nicht vorhanden. + Die Abfrage wurde nicht abgeschlossen + Die Abfrage erzeugte mehr als eine Ergebnismenge + Fehler beim Hinzufügen einer neuen Zeile zum Aktualisierungscache + Die angegebene Zeilen-ID ist außerhalb des Bereiches des Bearbeitungscaches + Für diese Zeile steht eine Aktualisierung an, die erst zurückgenommen werden muß + Die angegebene Zeilen-ID hat keine ausstehenden Aktualisierungen + Tabellen oder Sicht Metadaten konnten nicht gefunden werden + Ungültiges Format für eine binäre Spalte + Spalten vom Typ Boolean müssen entweder der Zahl 0 oder 1 oder der Zeichenkette true oder false entsprechen + Ein Pflichtfeld hat keinen Wert. + Für diese Zeile steht ein Löschbefehl aus, die Aktualisierung von Feldern kann nicht durchgeführt werden. + Die ID der Spalte muss innerhalb des Bereichs der Spalten der Abfrage sein + Die Spalte kann nicht editiert werden + Keine Schlüsselspalten gefunden + Der Name der Ausgabedatei muss angegeben werden + Das Datenbankobjekt {0} kan nicht editiert werden + 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 + Eine Session wurde nocht nicht initialisiert + Eine Session wurde bereits initialisiert + Eine Session wurde bereits initialisiert oder befindet sich im Prozess der Initialisierung. + Fehler beim Ausführen der Abfrage. Weitere Informationen finden SIe in der Ausgabe + Die Ergebnismengengrenze darf nicht negativ sein + NULL + Der Name des Objekts muss angegeben werden + Einen bestimmten Server oder Datenbank auszuwählen wird nicht unterstützt. + 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 + Serverrollen + Anwendungsrollen + Assemblys + Assemblydateien + Asymmetrische Schlüssel + Asymmetrische Schlüssel + Datenkomprimierungsoptionen + Zertifikate + FileTables + Zertifikate + Einschränkungen überprüfen + Spalten + Einschränkungen + Verträge + Anmeldeinformationen + Fehlermeldungen + Serverrollenmitgliedschaft + Datenbankoptionen + Datenbankrollen + Rollenmitgliedschaften + Datenbanktrigger + DEFAULT-Einschränkungen + Standardwerte + Sequenzen + Endpunkte + Ereignisbenachrichtigungen + Serverbenachrichtigungsereignisse + Erweiterte Eigenschaften + Dateigruppen + Fremdschlüssel + Volltextkataloge + Volltextindizes + Funktionen + Indizes + Inlinefunktionen + Schlüssel + Verbindungsserver + Anmeldungen für Verbindungsserver + Anmeldungen + Hauptschlüssel + Hauptschlüssel + Meldungstypen + Tabellenwertfunktionen + Parameter + Partitionsfunktionen + Partitionsschemas + Berechtigungen + Primärschlüssel + Programmierbarkeit + Warteschlangen + Remotedienstbindungen + Zurückgegebene Spalten + Rollen + Routen + Regeln + Schemas + Sicherheit + Serverobjekte + Verwaltung + Trigger + Service Broker + Dienste + Signaturen + Protokolldateien + Statistik + Speicher + Gespeicherte Prozeduren + Symmetrische Schlüssel + Synonyme + Tabellen + Trigger + Typen + Eindeutige Schlüssel + Benutzerdefinierte Datentypen + Benutzerdefinierte Typen (CLR) + Benutzer + Sichten + XML-Indizes + XML-Schemaauflistungen + Benutzerdefinierte Tabellentypen + Dateien + Fehlende Beschriftung + Brokerprioritäten + Kryptografieanbieter + Datenbank-Überwachungsspezifikationen + Verschlüsselungsschlüssel für Datenbank + Ereignissitzungen + Volltext-Stopplisten + Ressourcenpools + Überwachungen + Serverüberwachungsspezifikationen + Räumliche Indizes + Arbeitsauslastungsgruppen + SQL-Dateien + Serverfunktionen + SQL-Typ + Serveroptionen + Datenbankdiagramme + Systemtabellen + Datenbanken + Systemverträge + Systemdatenbanken + Systemmeldungstypen + Systemwarteschlangen + Systemdienste + Gespeicherte Systemprozeduren + Systemsichten + Datenebenenanwendungen + Erweiterte gespeicherte Prozeduren + Aggregatfunktionen + Ungefähre numerische Ausdrücke + Binärzeichenfolgen + Zeichenfolgen + CLR-Datentypen + Konfigurationsfunktionen + Cursorfunktionen + Systemdatentypen + Datum und Uhrzeit + Datums- und Uhrzeitfunktionen + Genaue numerische Ausdrücke + Systemfunktionen + Hierarchie-ID-Funktionen + Mathematische Funktionen + Metadatenfunktionen + Andere Datentypen + Andere Funktionen + Rowsetfunktionen + Sicherheitsfunktionen + Räumliche Datentypen + Zeichenfolgenfunktionen + Statistische Systemfunktionen + Text- und Bildfunktionen + Unicode-Zeichenfolgen + Aggregatfunktionen + Skalarwertfunktionen + Tabellenwertfunktionen + Erweiterte gespeicherte Systemprozeduren + Integrierte Typen + Integrierte Serverrollen + Benutzer mit Kennwort + Sucheigenschaftenliste + Sicherheitsrichtlinien + Sicherheitsprädikate + Serverrolle + Sucheigenschaftenlisten + Spaltenspeicherindizes + Tabellentypindex + Selektive XML-Indexe + XML-Namespaces + XML-typisierte höher gestufte Pfade + T-SQL-typisierte höher gestufte Pfade + Datenbankweit gültige Anmeldeinformationen + Externe Datenquellen + Externe Dateiformate + Externe Ressourcen + Externe Tabellen + Immer verschlüsselte Schlüssel + Spaltenhauptschlüssel + 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 + Parametrisierung + Diese Option darf nicht angegeben werden, wenn eine Sicherung mit der NORECOVERY-Option wiederhergestellt wird. + Ungültiger Pfad für Datenbankdatei: {0} + Protokoll + Fehler beim Erstellen des Wiederherstellungsplan + Wiederherstellen der Datenbank wird nicht unterstützt. + Datenbank wiederherstellen + (nur kopieren) + Komponente + Typ + Server + Datenbank + Position + Erste LSN + Letzte LSN + Prüfpunkt-LSN + Vollständige LSN + Startdatum + Beendigungsdatum + Größe + Benutzername + Ablaufdatum + Name + Letzte Sicherung ({0}) + Datenbank sichern + In Bearbeitung + Abgeschlossen + Skripterstellung + Verbindung nicht gefunden + Der angegebene Dateiname ist zugleich ein Verzeichnisname: {0} + Es kann nicht überprüft werden, ob der Speicherort der Sicherungsdatei vorhanden ist: {0} + Auf den angegebenen Pfad auf dem Server kann nicht zugegriffen werden: {0} + Kein Sicherungssatz zur Wiederherstellung ausgewählt + Nie + Azure SQL DB + Azure SQL Data Warehouse + Azure SQL Stretch Database + Der Pfad {0} ist kein gültiges Verzeichnis + Die Datei {1} im Verzeichnis {0} existiert bereits. + Der Wert {0} ist zu groß für eine Spalte mit dem Datentyp {1} + \ No newline at end of file diff --git a/src/Microsoft.SqlTools.CoreServices/Localization/sr.es.resx b/src/Microsoft.SqlTools.CoreServices/Localization/sr.es.resx new file mode 100644 index 00000000..eb2b138b --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Localization/sr.es.resx @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +text/microsoft-resx1.3System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089Los parámetros de conexión no pueden ser nulos + OwnerUri no puede ser nulo ni estar vacío + SpecifiedUri '{0}' no tiene una conexión existente + El valor '{0}' no es válido para AuthenticationType. Los valores válidos son 'Integrated' y 'SqlLogin'. + El valor '{0}' no es válido para ApplicationIntent. Los valores válidos son 'ReadWrite' y 'ReadOnly'. + Conexión cancelada + OwnerUri no puede ser nulo ni estar vacío + El objeto de detalles de conexión no puede ser nulo + ServerName no puede ser nulo ni estar vacío + {0} no puede ser nulo ni estar vacío cuando se utiliza autenticación SqlLogin + Ya se ha completado la consulta, no se puede cancelar + La consulta fue cancelada con éxito, pero no se ha podido desechar. No se encontró el URI del propietario. + Consulta cancelada por el usuario + El lote aún no ha finalizado, + Índice de lote no puede ser menor que 0 o mayor que el número de lotes + Índice del conjunto de resultados no puede ser menor que 0 o mayor que el número de conjuntos de resultados + El número máximo de bytes a devolver debe ser mayor que cero + El número máximo de caracteres a devolver debe ser mayor que cero + El número máximo de bytes XML a devolver debe ser mayor que cero + El método de acceso no puede ser de sólo escritura + FileStreamWrapper debe inicializarse antes de realizar operaciones + Este FileStreamWrapper no se puede utilizar para escritura. + (1 fila afectada) + ({0} filas afectadas) + Comandos finalizados correctamente. + Msg {0}, nivel {1} estado {2}, línea {3} {4} {5} + Error en la consulta: {0} + (Ningún nombre de columna) + La consulta solicitada no existe + Este editor no está conectado a una base de datos + Una consulta ya está en curso para esta sesión de editor. Por favor, cancelar esta consulta o esperar su finalización. + Remitente de eventos de OnInfoMessage debe ser un objeto SqlConnection + No se puede guardar el resultado hasta que haya finalizado la ejecución de la consulta + Error interno al iniciar el guardado de la tarea + Una operacion de guardado en la misma ruta se encuentra en curso + Error al guardar {0}: {1} + No se puede leer el subconjunto, a menos que los resultados se han leído desde el servidor + Fila de inicio no puede ser menor que 0 o mayor que el número de filas en el conjunto de resultados + La cantidad de filas debe ser un entero positivo + No se pudo recuperar el esquema de columna para el conjunto de resultados + No se pudo recuperar un plan de ejecución del conjunto de resultados + Esta característica actualmente no se admite en la base de datos de SQL Azure y almacén de datos: {0} + Se ha producido un error inesperado durante la ejecución de la definición de Peek: {0} + No se encontraron resultados. + No se pudo obtener ningún objeto asociado a la base de datos. + Por favor, conéctese a un servidor + Tiempo de espera agotado para esta operación. + Esta característica no admite actualmente este tipo de objeto. + Posición está fuera del intervalo de la línea de archivo + Posición está fuera del intervalo de la columna de la línea {0} + Posición de inicio ({0}, {1}) debe preceder o ser igual a la posición final ({2}, {3}) + Msg {0}, {1}, nivel de estado {2}, línea {3} + Msj {0}, {1}, nivel de estado {2}, procedimiento {3}, línea {4} + Msg {0}, nivel {1}, {2} de estado + Se produjo un error al procesar el lote. Mensaje de error: {0} + ({0} filas afectadas) + La ejecución anterior aún no está completa. + Se ha producido un error de secuencias de comandos. + Se encontró sintaxis incorrecta mientras se estaba analizando {0}. + Se ha producido un error grave. + La ejecución se completó {0} veces... + Se canceló la consulta. + Se produjo un error mientras se ejecutaba el lote. + Se produjo un error mientras se ejecutaba el lote, pero se ha omitido el error. + Beginning execution loop + No se admite el comando {0}. + La variable {0} no se encontró. + Error de ejecución de SQL: {0} + Ejecución de contenedor del analizador por lotes: {0} se encuentra... en la línea {1}: {2} Descripción: {3} + Lote analizador contenedor ejecución motor lote mensaje recibido: mensaje: {0} mensaje detallado: {1} + Motor de ejecución de analizador contenedor lote ResultSet procesamiento por lotes: DataReader.FieldCount: {0} DataReader.RecordsAffected: {1} + Finalizó el elemento ResultSet analizador contenedor ejecución motor los lotes. + Cancelando la ejecución por lotes del contenedor del analizador por lotes. + Advertencia de scripting. + Para obtener más información acerca de este error, vea los temas de solución de problemas en la documentación del producto. + El archivo '{0}' se incluyó recursivamente. + Falta la marca de final de comentario ' * /'. + Sin comilla de cierre después de la cadena de caracteres. + Se encontró sintaxis incorrecta al analizar '{0}'. + La variable {0} no está definida. + prueba + Sustitución de una cadena vacía por una cadena vacía. + Sesión de edición no existe, + La consulta no ha finalizado. + La consulta no generó un único set de resultados + Falló al agregar una nueva fila a la caché de actualización + El ID de la fila ingresado, se encuentra fuera del rango de filas de la caché de edición + Una actualización está pendiente para esta fila y debe de revertirse primero + El ID de la fila ingresado no tiene actualizaciones pendientes + La metadata de la tabla o vista no pudo ser encontrada + Formato inválido para columna binaria + Columnas del tipo boolean deben de ser numéricos 1 o 0, o tipo string true o false + Falta un valor requerido de la celda + Existe una eliminación pendiente para esta fila, una actualización de celda no puede ser realizada. + El ID de la columna debe de estar en el rango de columnas de la consulta. + La columna no puede ser editada + No se encontró ninguna columna clave + Proporcione un nombre de archivo de salida + Objeto de base de datos {0} no puede ser usado para modificación. + SpecifiedUri '{0}' no tiene alguna conexión por defecto + Una tarea de confirmación se encuentra en progreso. Por favor espere que la operación termine. + Columna del tipo decimal no tiene precisión o escala numérica + <TBD> + No se pueden agregar filas al buffer de resultados, el lector de datos no contiene filas + Los valores en la columna TIME deben estar incluidos en el rango desde 00:00:00:000000 hasta 23:59:59.999999 + No se permite un valor NULL en esta columna + La sesión de edición ya existe. + La sesión de edición no se inicializó + La sesión de edición ya se inicializó + La sesión de edición ya se inicializo o se encuentra en proceso de inicialización + La ejecución de la consulta falló, ver los mensajes para obtener mas detalle + El límite del resultado no puede ser negativo + NULL + Se debe proveer un nombre de objeto + No se permite especificar explícitamente el servidor o la base de datos + Los metadatos de la tabla no tienen propiedades extendidas + La tabla o vista solicitada para edición no se encuentra + Error en expansión: {0} + Error conectando a {0} + Agregados + Roles de servidor + Roles de aplicación + Ensamblados + Archivos de ensamblado + Claves asimétricas + Claves asimétricas + Opciones de compresión de datos + Certificados + Tablas de archivos + Certificados + Restricciones CHECK + Columnas + Restricciones + Contratos + Credenciales + Mensajes de error + Pertenencia a roles de servidor + Opciones de base de datos + Roles de base de datos + Pertenencias a roles + Desencadenadores de base de datos + Restricciones DEFAULT + Valores predeterminados + Secuencias + Extremos + Notificaciones de eventos + Notificaciones de eventos de servidor + Propiedades extendidas + Grupos de archivos + Claves externas + Catálogos de texto completo + Índices de texto completo + Funciones + Índices + Funciones Inline + Claves + Servidores vinculados + Inicios de sesión de servidor vinculado + Inicios de sesión + Clave maestra + Claves maestras + Tipos de mensaje + Funciones con valores de tabla + Parámetros + Funciones de partición + Esquemas de partición + Permisos + Claves principales + Programación + Colas + Enlaces de servicio remoto + Columnas devueltos + Roles + Rutas + Reglas + Esquemas + Seguridad + Objetos de servidor + Administración + Desencadenadores + Service Broker + Servicios + Firmas + Archivos de registro + Estadísticas + Almacenamiento + Procedimientos almacenados + Claves simétricas + Sinónimos + Tablas + Desencadenadores + Tipos + Claves únicas + Tipos de datos definidos por el usuario + Tipos definidos por el usuario (CLR) + Usuarios + Vistas + Índices XML + Colecciones de esquemas XML + Tipos de tablas definidos por el usuario + Archivos + Falta el título + Prioridades de Broker + Proveedores de servicios criptográficos + Especificaciones de auditoría de base de datos + Claves de cifrado de base de datos + Sesiones de eventos + Listas de palabras irrelevantes de texto completo + Grupos de recursos de servidor + Auditorías + Especificaciones de auditoría de servidor + Índices espaciales + Grupos de cargas de trabajo + Archivos SQL + Funciones de servidor + Tipo SQL + Opciones de servidor + Diagramas de base de datos + Tablas del sistema + Bases de datos + Contratos del sistema + Bases de datos del sistema + Tipos de mensaje del sistema + Colas del sistema + Servicios del sistema + Procedimientos almacenados del sistema + Vistas del sistema + Aplicaciones de capa de datos + Procedimientos almacenados extendidos + Funciones de agregado + Valores numéricos aproximados + Cadenas binarias + Cadenas de caracteres + Tipos de datos CLR + Funciones de configuración + Funciones del cursor + Tipos de datos del sistema + Fecha y hora + Funciones de fecha y hora + Valores numéricos exactos + Funciones del sistema + Funciones de id. de jerarquía + Funciones matemáticas + Funciones de metadatos + Otros tipos de datos + Otras funciones + Funciones de conjunto de filas + Funciones de seguridad + Tipos de datos espaciales + Funciones de cadena + Funciones estadísticas del sistema + Funciones de texto y de imagen + Cadenas de caracteres Unicode + Funciones de agregado + Funciones escalares + Funciones con valores de tabla + Procedimientos almacenados extendidos del sistema + Tipos integrados + Roles de servidor integrados + Usuario con contraseña + Lista de propiedades de búsqueda + Directivas de seguridad + Predicados de seguridad + Rol de servidor + Listas de propiedades de búsqueda + Índices de almacenamiento de columnas + Índices de tipo de tabla + Índices XML selectivos + Espacios de nombres XML + Rutas de acceso promovidas de tipo XML + Rutas de acceso promovidas de tipo T-SQL + Credenciales de ámbito de base de datos + Orígenes de datos externos + Formatos de archivo externo + Recursos externos + Tablas externas + Siempre claves cifradas + Claves maestras de columna + 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 + Parametrización + No se permite restaurar una copia de seguridad con la opción NORECOVERY + Ruta de archivo no válida: '{0}' + Registro + No se pudo crear un plan de restauraciones + No se admite restaurar la base de datos + Restaurar base de datos + (Copiar solamente) + Componente + Tipo + Servidor + Base de datos + Posición + Primer LSN + Último LSN + Checkpoint LSN + LSN completo + Fecha de inicio + Fecha de finalización + Tamaño + Nombre del usuario + Expiración + Nombre + La última copia de seguridad tomada ({0}) + Copia de seguridad de la base de datos + En curso + Completado + scripting + Conexión no encontrada + El nombre del archivo especificado es un nombre de directorio: {0} + No se puede verificar la existencia de la ubicación del archivo de copia de seguridad: {0} + No se puede acceder a la ruta de acceso especificada en el servidor: {0} + Ningún backupset seleccionado para ser restaurado + Nunca + Azure SQL Database + Azure SQL Data Warehouse + Azure SQL Stretch Database + La ruta de acceso [{0}] no es un directorio válido + Ya existe un archivo {1} en el directorio '{0}' + El valor {0} es muy grande para el tipo de columna {1} + \ No newline at end of file diff --git a/src/Microsoft.SqlTools.CoreServices/Localization/sr.fr.resx b/src/Microsoft.SqlTools.CoreServices/Localization/sr.fr.resx new file mode 100644 index 00000000..adc2950a --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Localization/sr.fr.resx @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +text/microsoft-resx1.3System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089Les paramètres de connexion ne peuvent pas être null + OwnerUri ne peut pas être null ou vide. + SpecifiedUri '{0}' n’a pas de connexion existante + 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'. + Connexion annulée + OwnerUri ne peut pas être null ou vide. + L'objet "détails de connexion" ne peut pas être null + ServerName ne peut pas être null ou vide + {0} ne peut pas être nul ou vide quand l'authentification SqlLogin est utilisée + La requête est déjà terminée, elle ne peut pas être annulée. + 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 + Le lot n’a pas terminé encore + Index de lot ne peut pas être inférieur à 0 ou supérieur au nombre de lots + L'index de résultats ne peut pas être inférieur à 0 ou supérieur au nombre de résultats + Le nombre maximal d'octets à renvoyer doit être supérieur à zéro + Le nombre maximal de caractères à 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 + FileStreamWrapper doit être initialisée avant d’effectuer des opérations + Ce FileStreamWrapper ne peut pas être utilisé pour l’écriture + (1 ligne affectée) + ({0} lignes affectées) + Commandes terminées avec succès. + Msg {0}, au niveau état {2}, {1}, ligne {3} {4} {5} + La requête a échoué : {0} + (Aucun nom de colonne) + La requête demandée n’existe pas + Cet éditeur n’est pas connecté à une base de données + Une requête est déjà en cours pour cette session d’éditeur. Veuillez annuler cette requête, ou attendre son achèvement. + L’expéditeur de l’événement de OnInfoMessage doit être un objet SqlConnection + 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 de la tâche de sauvegarde. + Une requête de sauvegarde vers le même chemin est en cours + Impossible d’enregistrer {0} : {1} + Impossible de lire le sous-élément à moins que les résultats aient été lus depuis le serveur + La ligne de début ne peut pas être inférieure à 0 ou supérieure au nombre de lignes de résultats + Le nombre de lignes doit être un entier positif + 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 pour le jeu de résultats + 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 du coup d'oeil à la définition: {0}. + Aucun résultat trouvé. + Aucun objet de base de données n'a été récupéré. + Veuillez vous connecter à un serveur. + Opération a expiré. + Ce type d'objet n'est actuellement pas supporté par cette fonctionnalité + La position est en dehors de la plage de lignes du fichier + 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}, Niveau {1}, État {2}, Ligne {3} + Msg {0}, Niveau {1}, État {2}, Procédure {3}, Ligne {4} + Msg {0}, Niveau {1}, État {2} + 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. + Une erreur de script s'est produite. + Une syntaxe incorrecte a été trouvée lors de l'analyse de {0}. + Une erreur irrécupérable s'est produite. + L'exécution a été effectuée {0} fois... + Vous avez annulé la requête. + Une erreur s'est produite lors de l'exécution du lot. + Une erreur s'est produite lors de l'exécution du lot, mais elle a été ignorée. + Beginning execution loop + La commande {0} n'est pas prise en charge. + Impossible de trouver la variable {0}. + Erreur d’exécution de SQL : {0} + Exécution du wrapper de l'analyseur du lot : {0} trouvé... à la ligne {1} : {2} Description : {3} + 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 ResultSet du lot du moteur d'exécution du wrapper de l'analyseur du lot : DataReader.FieldCount : {0} DataReader.RecordsAffected : {1} + ResultSet du lot du moteur d'exécution du wrapper de l'analyseur du lot terminé. + Annulation de l'exécution du lot du wrapper de l'analyseur du lot. + Avertissement de script. + Pour plus d'informations sur cette erreur, consultez les rubriques de dépannage dans la documentation du produit. + Le fichier '{0}' a été inclus de manière récursive. + La marque de commentaire de fin '*/' est manquante. + Guillemets non fermés après la chaîne de caractères. + Détection d'une syntaxe incorrecte pendant l'analyse de '{0}'. + La variable {0} n'est pas définie. + 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 + Rôles serveur + Rôles d'application + Assemblys + Fichiers d'assembly + Clés asymétriques + Clés asymétriques + Options de compression de données + Certificats + FileTables + Certificats + Contraintes de validation + Colonnes + Contraintes + Contrats + Informations d'identification + Messages d'erreur + Appartenance au rôle de serveur + Options de la base de données + Rôles de base de données + Appartenances aux rôles + Déclencheurs de base de données + Contraintes par défaut + Par défaut + Séquences + Points de terminaison + Notifications d'événements + Notifications d'événements du serveur + Propriétés étendues + Groupes de fichiers + Clés étrangères + Catalogues de recherche en texte intégral + Index de recherche en texte intégral + Fonctions + Index + Fonctions incluses + Clés + Serveurs liés + Connexions de serveur lié + Connexions + Clé principale + Clés principales + Types de messages + Fonctions table + Paramètres + Fonctions de partition + Schémas de partition + Autorisations + Clés primaires + Programmabilité + Files d'attente + Liaisons de service distant + Colonnes retournées + Rôles + Itinéraires  + Règles + Schémas + Sécurité + Objets serveur + Gestion + Déclencheurs + Service Broker + Services + Signatures + Fichiers journaux + Statistiques + Stockage + Procédures stockées + Clés symétriques + Synonymes + Tables + Déclencheurs + Types + Clés uniques + Types de données définis par l'utilisateur + Types définis par l'utilisateur (CLR) + Utilisateurs + Vues + Index XML + Collections de schémas XML + Types de tables définis par l'utilisateur + Fichiers + Légende manquante + Priorités de Service Broker + Fournisseurs de chiffrement + Spécifications de l'audit de la base de données + Clés de chiffrement de la base de données + Sessions d'événements + Listes de mots vides de texte intégral + Pools de ressources + Audits + Spécifications de l'audit du serveur + Index spatiaux + Groupes de charges de travail + Fichiers SQL + Fonctions du serveur + Type SQL + Options de serveur + Schémas de base de données + Tables système + Bases de données + Contrats système + Bases de données système + Types de messages système + Files d'attente système + Services système + Procédures stockées système + Vues système + Applications de la couche Données + Procédures stockées étendues + Fonctions d'agrégation + Valeurs numériques approximatives + Chaînes binaires + Chaînes de caractères + Types de données CLR + Fonctions de configuration + Fonctions du curseur + Types de données système + Date et heure + Fonctions de date et d'heure + Valeurs numériques exactes + Fonctions système + Fonctions de l'ID de hiérarchie + Fonctions mathématiques + Fonctions de métadonnées + Autres types de données + Autres fonctions + Fonctions d'ensemble de lignes + Fonctions de sécurité + Types de données spatiales + Fonctions de chaîne + Fonctions statistiques système + Fonctions de texte et d'image + Chaînes de caractères Unicode + Fonctions d'agrégation + Fonctions scalaires + Fonctions table + Procédures stockées étendues système + Types intégrés + Rôles serveur intégrés + Utilisateur avec mot de passe + Liste des propriétés de recherche + Stratégies de sécurité + Prédicats de sécurité + Rôle de serveur + Listes des propriétés de recherche + Index de stockage de colonnes + Index de types de tables + Index XML sélectifs + Espaces de noms XML + Chemins d'accès promus typés XML + Chemins d'accès promus typés T-SQL + Informations d'identification incluses dans l'étendue de la base de données + Sources de données externes + Formats de fichier externes + Ressources externes + Tables externes + Clés Always Encrypted + Clés principales de la colonne + 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é + Paramétrage + La spécification de cette option lors de la restauration d'une sauvegarde avec l'option NORECOVERY n'est pas permise. + Chemin d'accès non valide pour le fichier de base de données : « {0} » + Journal + Échec de la création du plan de restauration + La restauration de la base de données n'est pas supportée + Restaurer la base de données + (Copie seule) + Composant + Type + Serveur  + Base de données  + Position + Premier NSE + Dernier NSE + NSE du point de contrôle + Tous les NSE + Date de début + Date de fin + Taille + Nom d'utilisateur  + Expiration  + Nom  + La dernière sauvegarde effectuée ({0}) + Sauvegarder la base de données + Opération en cours + Terminé + script + Connexion introuvable + Le nom de fichier spécifié est également un nom de répertoire: {0} + Impossible de vérifier l'existence de l'emplacement du fichier de sauvegarde: {0} + Impossible d'accéder au chemin d'accès spécifié sur le serveur: {0} + Aucun jeu de sauvegarde n'a été sélectionné pour être restauré. + Jamais + Azure SQL DB + Azure SQL Data Warehouse + Azure SQL Stretch Database + Le chemin {0} n'est pas un répertoire valide. + Pour le répertoire {0} un fichier avec le nom {1} existe déjà + La valeur {0} est trop grande pour tenir dans la colonne de type {1} + \ No newline at end of file diff --git a/src/Microsoft.SqlTools.CoreServices/Localization/sr.it.resx b/src/Microsoft.SqlTools.CoreServices/Localization/sr.it.resx new file mode 100644 index 00000000..bbe62882 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Localization/sr.it.resx @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +text/microsoft-resx1.3System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089Parametri di connessione non possono essere null + OwnerUri non può essere null o vuoto + SpecifiedUri: '{0}' non dispone di connessione esistente + Valore non valido: '{0}' per AuthenticationType. I valori validi sono 'Integrated' e 'SqlLogin'. + Valore '{0}' non valido per ApplicationIntent. I valori validi sono 'ReadWrite' e 'ReadOnly'. + Connessione annullata + OwnerUri non può essere null o vuoto + L'oggetto Dettagli di connessione non può essere null + ServerName non può essere null o vuoto + {0} non può essere null o vuoto quando si utilizza l'autenticazione SqlLogin + La query è già stata completata e non può essere annullata + Query annullata correttamente, impossibile eliminare query. URI proprietario non trovato. + Query annullata dall'utente + Il batch non è ancora stato completato + Indice di batch non può essere minore di 0 o maggiore del numero di batch + Indice di set di risultati non può essere minore di 0 o maggiore del numero di set di risultati + Numero massimo di byte da restituire deve essere maggiore di zero + Numero massimo di caratteri da restituire deve essere maggiore di zero + Numero massimo di byte XML da restituire deve essere maggiore di zero + Il metodo di accesso non può essere in sola scrittura + FileStreamWrapper deve essere inizializzato prima di eseguire operazioni + Questo FileStreamWrapper non può essere utilizzato per la scrittura + (1 riga interessata) + ({0} righe interessate) + Comandi completati correttamente. + Msg {0}, Livello {1}, Stato {2}, Riga {3} {4} {5} + Query non riuscita: {0} + (Nessun nome di colonna) + La query richiesta non esiste + Questo editor non è connesso a un database + Una query è già in corso per questa sessione dell'editor. Annullare la query o attendere il completamento. + Mittente per l'evento OnInfoMessage deve essere un oggetto SqlConnection + Non è possibile salvare il risultato finché non viene completata l'esecuzione della query + Errore interno durante l'avvio del task di salvataggio + È in corso una richiesta di salvataggio sullo stesso percorso + Impossibile salvare {0}: {1} + Impossibile leggere sottoinsieme a meno che i risultati sono stati letti dal server + Riga di inizio non può essere minore di 0 o maggiore del numero di righe nel set di risultati + Il numero di righe deve essere un numero intero positivo + Impossibile recuperare schema di colonne per set di risultati + Impossibile recuperare un piano di esecuzione dal set di risultati + Questa funzionalità non è supportata su DB SQL Azure e Data Warehouse: {0} + Si è verificato un errore imprevisto durante l'esecuzione di definizione Peek: {0} + Nessun risultato trovato. + Non è stato recuperato alcun oggetto di database. + Connettersi a un server. + Timeout dell'operazione. + Questo tipo di oggetto non è supportato da questa funzionalità. + La posizione non rientra nell'intervallo di righe del file + Posizione non rientra nell'intervallo di colonne per riga {0} + Posizione iniziale ({0}, {1}) deve essere precedente o uguale alla posizione finale ({2}, {3}) + Msg. {0}, Livello {1}, Stato {2}, Riga {3} + Msg. {0}, Livello {1}, Stato {2}, Procedura {3}, Riga {4} + Msg. {0}, Livello {1}, Stato {2} + Si è verificato un errore durante l'elaborazione batch. Messaggio di errore: {0} + ({0} righe interessate dall'operazione) + L'esecuzione precedente non è ancora completa. + Si è verificato un errore di scripting. + Sintassi errata rilevata durante l'analisi di '{0}'. + Si è verificato un errore irreversibile. + Esecuzione completata {0} volte... + È stata annullata la query. + Si è verificato un errore durante l'esecuzione del batch. + Si è verificato un errore durante l'esecuzione del batch, ma l'errore è stato ignorato. + Beginning execution loop + Il comando {0} non è supportato. + Impossibile trovare la variabile {0}. + Errore di esecuzione di SQL: {0} + Esecuzione del wrapper parser batch: trovati {0}... alla riga {1}: {2} Descrizione: {3} + Motore di esecuzione wrapper parser di batch, ricevuto messaggio batch: messaggio: {0} messaggio dettagliato: {1} + Motore di esecuzione wrapper parser di batch, elaborazione batch di ResultSet: DataReader.FieldCount: {0} DataReader.RecordsAffected: {1} + Motore di esecuzione wrapper parser di batch, batch di ResultSet completato. + Annullamento dell'esecuzione batch del wrapper parser batch. + Avviso di script. + Per ulteriori informazioni su questo errore, vedere gli argomenti sulla risoluzione dei problemi nella documentazione del prodotto. + File '{0}' incluso ricorsivamente. + Marker ' * /' di fine commento mancante. + Virgolette mancanti alla fine della stringa di caratteri. + Sintassi errata rilevata durante l'analisi di '{0}'. + Variabile {0} non è definita. + test + Sostituzione di una stringa vuota con una stringa vuota. + La sessione di editing non esiste. + Esecuzione query non completata + La query non ha generato esattamente un insieme di risultati + Errore nell'aggiunta di una riga durante l'aggiornamento della cache + L'ID riga specificato è fuori dal range di righe della cache della modifica + Un aggiornamento di questa riga è già in corso e dev'essere annullato prima di procedere + Questo ID di riga non ha aggiornamenti in corso + Metadati della tabella o della vista non trovati + Formato non valido per una colonna binaria + Colonne booleane devono contenere valori numerici 0 o 1, o stringhe true o false + Il valore di cella richiesto è mancante + La cancellazione di questa riga è in corso, impossibile aggiornare la cella. + L'ID della colonna dev'essere incluso nel range delle colonne della query + Impossibile modificare la colonna + Impossibile trovare colonne chiave + Occorre fornire un nome di file di output + L'oggetto {0} del database non può essere usato per la modifica. + L'URI specificato '{0}' non ha una connessione di default + Azione commit in corso - attenderne il completamento. + Precisione o scala mancante nella colonna Decimal + <TBD> + Impossibile aggiungere una riga al buffer risultati - il datareader non contiene righe + I valori della colonna Time devono essere compresi tra 00:00:00.0000000 e 23:59:59.9999999 + NULL non è consentito per questa colonna + La sessione di editing esiste già. + La sessione di editing non è stata inizializzata. + La sessione di editing è già stata inizializzata. + La sessione di editing è già stata inizializzata o è in fase di inizializzazione + Esecuzione della query fallita - vedere i messaggi per ulteriori dettagli + Il limite del risultato non può essere negativo + NULL + Il nome dell'oggetto è obbligatorio + Non è possibile specificare in modo esplicito il nome di un server o di un database + Nessuna proprietà estesa per la tabella + Impossibile trovare la Tabella o la Vista necessarie alla modifica + Errore durante l'espansione dell'oggetto: {0} + Errore durante la connessione a {0}' + Aggregazioni + Ruoli del server + Ruoli applicazione + Assembly + File di assembly + Chiavi asimmetriche + Chiavi asimmetriche + Opzioni di compressione dati + Certificati + Tabelle file + Certificati + Vincoli CHECK + Colonne + Vincoli + Contratti + Credenziali + Messaggi di errore + Appartenenze al ruolo del server + Opzioni database + Ruoli database + Appartenenze a ruoli + Trigger database + Vincoli predefiniti + Impostazioni predefinite + Sequenze + Endpoint + Notifiche degli eventi + Notifiche degli eventi server + Proprietà estese + Filegroup + Chiavi esterne + Cataloghi full-text + Indici full-text + Funzioni + Indici + Funzioni inline + Chiavi + Server collegati + Accessi server collegato + Accessi + Chiave master + Chiavi master + Tipi di messaggio + Funzioni con valori di tabella + Parametri + Funzioni di partizione + Schemi di partizione + Autorizzazioni + Chiavi primarie + Programmazione + Code + Associazioni a servizi remoti + Colonne restituite + Ruoli + Route + Regole + Schemi + Sicurezza + Oggetti server + Gestione + Trigger + Service Broker + Servizi + Firme + File di log + Statistiche + Archiviazione + Stored procedure + Chiavi simmetriche + Sinonimi + Tabelle + Trigger + Tipi + Chiavi univoche + Tipi di dati definiti dall'utente + Tipi definiti dall'utente (UDT) (CLR) + Utenti + Viste + Indici XML + Raccolte XML Schema + Tipi di tabella definiti dall'utente + File + Didascalia mancante + Priorità di Service Broker + Provider del servizio di crittografia + Specifiche di controllo database + Chiavi di crittografia database + Sessioni eventi + Elenchi di parole non significative full-text + Pool di risorse + Controlli + Specifiche controllo server + Indici spaziali + Gruppi del carico di lavoro + File SQL + Funzioni server + Tipo SQL + Opzioni server + Diagrammi di database + Tabelle di sistema + Database + Contratti di sistema + Database di sistema + Tipi di messaggi di sistema + Code di sistema + Servizi di sistema + Stored procedure di sistema + Viste di sistema + Applicazioni livello dati + Stored procedure estese + Funzioni di aggregazione + Valori numerici approssimati + Stringhe binarie + Stringhe di caratteri + Tipi di dati CLR + Funzioni di configurazione + Funzioni per i cursori + Tipi di dati di sistema + Data e ora + Funzioni di data e ora + Valori numerici esatti + Funzioni di sistema + Funzioni di ID di gerarchia + Funzioni matematiche + Funzioni per i metadati + Altri tipi di dati + Altre funzioni + Funzioni per i set di righe + Funzioni di sicurezza + Tipi di dati spaziali + Funzioni per i valori stringa + Funzioni statistiche di sistema + Funzioni per i valori text e image + Stringhe di caratteri Unicode + Funzioni di aggregazione + Funzioni a valori scalari + Funzioni con valori di tabella + Stored procedure estese di sistema + Tipi predefiniti + Ruoli del server predefiniti + Utente con password + Elenco delle proprietà di ricerca + Criteri di sicurezza + Predicati di sicurezza + Ruolo del server + Elenchi delle proprietà di ricerca + Indici dell'archivio colonne + Indici del tipo di tabella + Indici XML selettivi + Spazi dei nomi XML + Percorsi promossi con tipizzazione XML + Percorsi promossi con tipizzazione T-SQL + Credenziali con ambito database + Origini dati esterne + Formati di file esterni + Risorse esterne + Tabelle esterne + Chiavi Always Encrypted + Chiavi master della colonna + 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 + Parametrizzazione + Non è consentito specificare questa opzione quando si ripristina un backup con NORECOVERY. + Percorso non valido per il file di database: '{0}' + Log + Impossibile creare un piano di ripristino. + Ripristino del database non supportato. + Ripristina Database + (Sola Copia) + Componente + Tipo + Server + Database + Posizione + Primo LSN + Ultimo LSN + LSN di checkpoint + LSN completo + Data di inizio + Data di fine + Dimensione + Nome utente + Scadenza + Nome + L'ultimo backup effettuato ({0}) + Backup database + In corso + Completato + scripting + Connessione non trovata + Il nome file specificato è anche un nome di cartella: {0} + Impossibile verificare l'esistenza della posizione del file di backup: {0} + Impossibile accedere al percorso specificato sul server: {0} + Nessun insieme di backup selezionato per il ripristino + Mai + Azure SQL DB + Azure SQL Data Warehouse + Azure SQL Stretch Database + Il percorso [{0}] non è una directory valida. + Nella directory '{0}' esiste già il file {1} + Il valore {0} è troppo grande per essere contenuto in una colonna di tipo {1} + \ No newline at end of file diff --git a/src/Microsoft.SqlTools.CoreServices/Localization/sr.ja.resx b/src/Microsoft.SqlTools.CoreServices/Localization/sr.ja.resx new file mode 100644 index 00000000..8464e2a4 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Localization/sr.ja.resx @@ -0,0 +1,490 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +text/microsoft-resx1.3System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089接続パラメーターを null にすることはできません。 + OwnerUri を null または空にすることはできません。 + SpecifiedUri '{0}' には、既存の接続はありません。 + AuthenticationType の値 '{0}' が無効です。有効な値は 'Integrated' または 'SqlLogin' です。 + ApplicationIntent の値 '{0}' が無効です。有効な値は 'ReadWrite' または 'ReadOnly' です。 + 接続がキャンセルされました。 + OwnerUri を null または空にすることはできません。 + 接続の詳細オブジェクトを null にすることはできません。 + ServerName を null または空にすることはできません。 + SqlLogin 認証を使用する場合に、{0} を null または空にすることはできません。 + クエリは既に完了して、取り消すことができません。 + クエリのキャンセルに成功しましたが、クエリの処理に失敗しました。OwnerURIが見つかりません。 + クエリは、ユーザーによってキャンセルされました + バッチがまだ完了していません、 + バッチのインデックスは、0 未満あるいは、バッチの数より大きい値にすることはできません。 + 結果セットのインデックスは、0 未満あるいは、結果セットの数より大きい値にすることはできません + 戻り値の最大バイト数は 0 より大きくする必要があります。 + 戻り値の最大文字数は 0 より大きくする必要があります。 + 戻り値の最大のXMLバイト数は 0 より大きくする必要があります。 + アクセス メソッドを書き込み専用にすることはできません。 + FileStreamWrapper は、操作を実行する前に初期化されなければなりません。 + この FileStreamWrapper は、書き込みには利用できません。 + (1 件処理されました) + ({0} 行処理されました) + コマンドが正常に完了しました。 + Msg {0}, Level {1}, State {2}, Line {3}{4}{5} + クエリに失敗しました: {0} + (列名なし) + 要求されたクエリは存在しません + このエディターは、データベースに接続されていません。 + このエディターのクエリは既に実行中です。クエリをキャンセルするか完了まで待って下さい。 + OnInfoMessage イベントのSenderは、SqlConnectionである必要があります。 + クエリの実行が完了するまで、結果を保存することはできません。 + 保存タスクの開始中に内部エラーが発生しました。 + 同一のパスへの保存リクエストを実行中です。 + {0} を保存できませんでした: {1} + サーバーから結果が受信されていないため、サブセットを読み取ることができません。 + 開始行は 0 未満か、結果セット内の行数より大きい値にすることはできません。 + 行数は正の整数でなければなりません。 + 結果セットの列のスキーマを取得できませんでした。 + 結果セットから実行プランを取得できませんでした。 + この機能はAzure SQL DBとData Warehouseでは、現在サポートされていません: {0} + Peek Definitionの実行中に予期しないエラーが発生しました: {0} + 結果は見つかりませんでした。 + データベース オブジェクトを取得できませんでした。 + サーバーに接続してください。 + 操作がタイムアウトになりました。 + このオブジェクトの種類は現在この機能ではサポートされていません。 + 位置がファイルの行の範囲外です。 + 位置が行 {0} の列の範囲外です。 + 開始位置 ({0}, {1}) は、終了位置 ({2}, {3}) より前、または同じでなければなりません。 + Msg {0}, Level {1}, State {2}, Line {3} + Msg {0}, Level {1}, State {2}, Procedure {3}, Line {4} + Msg {0}, Level {1}, State {2} + バッチを処理中にエラーが発生しました。エラー メッセージ: {0} + ({0} 件処理されました) + 前回の実行がまだ完了していません。 + スクリプト エラーが発生しました。 + {0} の解析中に不正な構文が見つかりました。 + 致命的なエラーが発生しました。 + 実行を {0} 回完了しました... + クエリをキャンセルしました。 + バッチの実行中にエラーが発生しました。 + バッチの実行中にエラーが発生しましたが、エラーを無視しました。 + Beginning execution loop + コマンド {0} はサポートされていません。 + 変数 {0} が見つかりませんでした。 + SQL の実行エラー: {0} + バッチ パーサー ラッパーの実行: 行 {1}: {2} で {0} を検出... 説明: {3} + バッチ パーサー ラッパー実行エンジンのバッチ メッセージを受信しました: メッセージ: {0} 詳細メッセージ: {1} + バッチ パーサー ラッパー実行エンジンのバッチ ResultSet 処理: DataReader.FieldCount: {0} DataReader.RecordsAffected: {1} + バッチ パーサー ラッパー実行エンジンのバッチ ResultSet が終了しました。 + バッチ パーサー ラッパーのバッチ実行をキャンセルしています。 + スクリプトの警告。 + このエラーの詳細については、製品ドキュメントのトラブルシューティングに関するトピックを参照してください。 + ファイル '{0}' が再帰的に含まれています。 + '*/' でマークされたコメントの終端がありません。 + 文字列の引用符が閉じていません。 + '{0}' の解析中に無効な構文が見つかりました。 + 変数 {0} が定義されていません。 + テスト + 空の文字列で空の文字列を置換しています。 + 編集セッションは存在しません。 + クエリの実行が完了していません。 + クエリは 1 つの結果セットを生成できませんでした。 + キャッシュを更新する新しい行を追加できませんでした。 + 与えられた行IDは、編集キャッシュに存在する行の範囲外です。 + この行に対する更新がすでに保留されています。まず更新を戻す必要があります。 + 与えられた行IDには保留中の更新はありません。 + テーブルまたはビューのメタデータが見つかりませんでした。 + バイナリ列の形式が無効です。 + ブール列の型は1もしくは0の数値、または true もしくは false の文字列でなければいけません。 + 必須なセルの値が入力されていません。 + この行の削除が保留中であるため、セルの更新は適用できません。 + 列 ID がクエリの列の範囲である必要があります。 + 列を編集できません。 + キー列が見つかりませんでした。 + 出力ファイル名を指定する必要があります。 + データベース オブジェクト {0} は、編集のため使用できません。 + 指定された URI '{0}' には既定の接続はありません。 + コミット処理は実行中です。完了するまで待機してください。 + Decimal 型の列に有効桁数もしくは小数点以下桁数のどちらかが存在していません。 + <TBD> + 結果バッファーへ行を追加できません。データリーダーは行を含んでいません。 + time 型の値は 00:00:00.0000000 と 23:59:59.9999999 の範囲内になければなりません。 + この列では NULL は許可されていません。 + 編集セッションがすでに存在します。 + 編集セッションが初期化されていません。 + 編集セッションはすでに初期化されました。 + 編集セッションはすでに初期化されたか、初期化中です。 + クエリーの実行が失敗しました。詳細メッセージを確認してください。 + 結果の上限は負の値にできません。 + NULL + オブジェクトの名前を指定する必要があります。 + 明示的なサーバーもしくはデータベースの指定はサポートされていません。 + テーブルメタデータは拡張プロパティを持っていません。 + 編集を要求したテーブルもしくはビューが見つかりませんでした。 + '{0}' の拡張中にエラーが発生しました。 + {0} への接続中にエラーが発生しました + 集約 + サーバー ロール + アプリケーション ロール + アセンブリ + アセンブリ ファイル + 非対称キー + 非対称キー + データ圧縮オプション + 証明書 + ファイルテーブル + 証明書 + CHECK 制約 + + 制約 + コントラクト + 資格情報 + エラー メッセージ + サーバー ロール メンバーシップ + データベース オプション + データベース ロール + ロール メンバーシップ + データベース トリガー + 既定の制約 + 既定値 + シーケンス + エンドポイント + イベント通知 + サーバー イベント通知 + 拡張プロパティ + ファイル グループ + 外部キー + フルテキスト カタログ + フルテキスト インデックス + 関数 + インデックス + インライン関数 + キー + リンク サーバー + リンク サーバー ログイン + ログイン + マスター キー + マスター キー + メッセージ型 + テーブル値関数 + パラメーター + パーティション関数 + パーティション構成 + アクセス許可 + 主キー + プログラミング + キュー + リモート サービスのバインド + 返された列 + ロール + ルート + ルール + スキーマ + セキュリティ + サーバー オブジェクト + 管理 + トリガー + Service Broker + サービス + 署名 + ログ ファイル + 統計 + ストレージ + ストアド プロシージャ + 対称キー + シノニム + テーブル + トリガー + + 一意キー + ユーザー定義データ型 + ユーザー定義型 (CLR) + ユーザー + ビュー + XML インデックス + XML スキーマ コレクション + ユーザー定義テーブル型 + ファイル + キャプションが見つかりません + Broker の優先度 + 暗号化プロバイダー + データベース監査の仕様 + データベース暗号化キー + イベント セッション + フルテキスト ストップリスト + リソース プール + 監査 + サーバー監査の仕様 + 空間インデックス + ワークロード グループ + SQL ファイル + サーバー関数 + SQL 型 + サーバー オプション + データベース ダイアグラム + システム テーブル + データベース + システム コントラクト + システム データベース + システム メッセージの種類 + システム キュー + システム サービス + システム ストアド プロシージャ + システム ビュー + データ層アプリケーション + 拡張ストアド プロシージャ + 集計関数 + 概数 + バイナリ文字列 + 文字列 + CLR データ型 + 構成関数 + カーソル関数 + システム データ型 + 日付と時刻 + 日付と時刻関数 + 真数 + システム関数 + 階層 ID 関数 + 数学関数 + メタデータ関数 + その他のデータ型 + その他の関数 + 行セット関数 + セキュリティ関数 + 空間データ型 + 文字列関数 + システム統計関数 + テキストとイメージ関数 + Unicode 文字列 + 集計関数 + スカラー値関数 + テーブル値関数 + システム拡張ストアド プロシージャ + ビルトイン型 + 組み込みのサーバー ロール + ユーザーとパスワード + 検索プロパティ リスト + セキュリティ ポリシー + セキュリティ述語 + サーバー ロール + 検索プロパティ リスト + 列のストア インデックス + テーブル型インデックス + 選択的 XML インデックス + XML 名前空間 + XML の型指定された昇格パス + T-SQL の型指定された昇格パス + データベース スコープ資格情報 + 外部データ ソース + 外部ファイル形式 + 外部リソース + 外部テーブル + Always Encrypted キー + 列マスター キー + 列暗号化キー + サーバー + 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} にアクセスできません。 + クエリーは結果を返しませんでした + 結果セットの行数が多すぎるため安全にロードすることはできません + パラメーター化 + NORECOVERY オプションを使用してバックアップを復元するときにこのオプションを指定することはできません。 + データベース ファイルのパスが無効です: '{0}' + ログ + リストア プランの作成に失敗しました。 + データベースのリストアはサポートされていません。 + データベースのリストア + (コピーのみ) + コンポーネント + 種類 + サーバー + データベース + 位置 + 最初の LSN + 最後の LSN + チェックポイントの LSN + 全 LSN + 開始日 + 完了日 + サイズ + ユーザー名 + 有効期限 + 名前 + 最後に作成されたバックアップ ({0}) + データベースをバックアップする + 実行中 + 完了 + スクリプト + 接続が見つかりません。 + 指定されたファイル名がディレクトリ名と同じです: {0} + バックアップ ファイルの場所が存在するかどうか確認できません: {0} + サーバーで指定されたパスにアクセスできません: {0} + リストアするバックアップセットが選択されていません + 行わない + Azure SQL DB + Azure SQL Data Warehouse + Azure SQL Stretch Database + パス {0} は有効なディレクトリではありません + ディレクトリ {0} 内に {1} という名前のファイルは既に存在します + 値 {0} は大きすぎるため、型 {1} の列に収まりません + \ No newline at end of file diff --git a/src/Microsoft.SqlTools.CoreServices/Localization/sr.ko.resx b/src/Microsoft.SqlTools.CoreServices/Localization/sr.ko.resx new file mode 100644 index 00000000..7d4e551f --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Localization/sr.ko.resx @@ -0,0 +1,491 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +text/microsoft-resx1.3System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089연결 매개 변수는 null 일 수 없습니다. + OwnerUri은 null 이거나 비어 있을 수 없습니다. + SpecifiedUrl '{0}'는 기존 연결이 없습니다. + AuthenticationType 값으로 ' {0} '이 (가) 잘못 되었습니다. 유효한 값은 'Integrated'나 'SqlLogin' 입니다. + ApplicationIntent 값으로 ' {0} '이 (가) 잘못 되었습니다. 유효한 값은 'ReadWrite'나 'ReadOnly' 입니다. + 연결이 취소되었습니다. + OwnerUri는 null 이나 빈값일 수 없습니다 + 연결 세부 정보 개체는 null이 될 수 없습니다. + 서버 이름은 null이거나 비어 있을 수 없습니다. + SqlLogin 인증 사용 시 {0}은(는) null이나 빈값일 수 없습니다. + 쿼리가 이미 완료되어 취소할 수 없습니다. + 쿼리 취소가 완료되었으나 쿼리를 삭제하는데 실패했습니다. Owner URI를 찾을 수 없습니다. + 사용자가 쿼리를 취소 했습니다. + 일괄 처리가 아직 완료되지 않았습니다. + 일괄 처리 인덱스는 0 미만 이거나 일괄 처리 갯수 보다 클 수 없습니다. + 결과 집합 인덱스는 0 미만 이거나 결과 집합의 갯수보다 클 수 없습니다. + 반환되는 최대 바이트 수는 0보다 커야 합니다. + 반환되는 최대 문자 수는 0보다 커야 합니다. + 반환되는 최대 XML 바이트 수는 0보다 커야 합니다. + 액세스 방법은 쓰기 전용이 될 수 없습니다. + FileStreamWrapper 는 작업을 수행 하기 전에 초기화 해야 합니다. + FileStreamWrapper 는 쓰기용으로 사용할 수 없습니다. + (1 개 행이 영향을 받음) + ({0} 개 행이 영향을 받음) + 명령이 성공적으로 완료 되었습니다. + 메시지 {0}, 수준 {1}, 상태 {2}, 줄 {3} {4} {5}. + 쿼리 실패: {0} + (열 이름 없음) + 요청한 쿼리가 존재하지 않습니다. + 편집기가 데이터베이스에 연결되지 않았습니다. + 쿼리가 현재 편집기 세션에서 이미 실행 중입니다. 쿼리를 취소하거나 완료 될 때까지 대기 하십시오. + OnInfoMessage 이벤트 발신자는 SqlConnection 이어야 합니다. + 결과는 쿼리 실행이 완료 될 때까지 저장할 수 없습니다. + 저장 작업을 시작 하는 동안 내부 오류가 발생 했습니다. + 동일한 경로로 저장 요청이 진행 중입니다. + 저장 실패 {0}:{1} + 서버로부터 결과를 모두 읽기 전에는 일부 결과를 읽을 수 없습니다. + 시작 행은 0 미만이거나 결과 집합의 행의 갯수보다 클 수 없습니다. + 행 수는 양수여야 합니다. + 결과 집합의 열 스키마를 검색할 수 없습니다. + 결과 집합에서 실행 계획을 검색할 수 없습니다. + 현재 이 기능은 Azure SQL DB와 데이터 웨어하우스에서 지원 되지 않습니다: {0} + 정의 피킹을 실행하는 동안 예상치 못한 오류가 발생했습니다: {0} + 결과가 없습니다. + 검색된 데이터베이스 개체가 없습니다. + 서버에 연결 하십시오. + 작업 제한 시간이 초과 되었습니다. + 현재 이 개체 형식은 지원되지 않습니다. + 위치가 파일 줄 범위를 벗어났습니다. + 위치가 줄 {0} 의 열 범위를 벗어났습니다. + 시작 위치 ({0}, {1})은(는) 반드시 끝 위치 ({2}, {3}) 과 같거나 이전이어야 합니다. + 메시지 {0}, 수준{1}, 상태 {2}, 줄 {3} + 메시지 {0}, 수준 {1}, 상태 {2}, 프로시저 {3}, 줄 {4} + 메시지 {0}, 수준 {1}, 상태 {2} + 일괄 처리를 처리 하는 동안 하는 동안 오류가 발생 합니다. 오류 메시지: {0} + ({0} 개 행이 영향을 받음) + 이전 실행이 아직 완료 되지 않았습니다. + 스크립팅 오류가 발생 했습니다. + {0}에 잘못된 구문이 발견되었습니다. + 치명적인 오류가 발생 했습니다. + {0}회 실행 완료... + 쿼리를 취소 했습니다. + 일괄 처리를 실행 하는 동안 오류가 발생 합니다. + 일괄 처리를 실행 하는 동안 오류가 발생했으나 그 오류는 무시되었습니다. + Beginning execution loop + {0} 명령은 지원되지 않습니다. + {0} 변수를 찾을 수 없습니다. + SQL 실행 오류: {0} + 일괄처리 구문분석 래퍼 실행: {0} 발견... 줄 {1}: {2} 설명: {3} + 일괄 처리 파서 래퍼 실행 엔진 일괄 처리 메시지를 받았습니다. 메시지: {0} 자세한 메시지: {1} + 일괄 처리 파서 래퍼 실행 엔진 일괄 처리 ResultSet을 처리하고 있습니다. DataReader.FieldCount: {0} DataReader.RecordsAffected: {1} + 일괄 처리 파서 래퍼 실행 엔진 일괄 처리 ResultSet을 완료했습니다. + 일괄 처리 파서 래퍼 일괄 처리 실행을 취소하고 있습니다. + 스크립팅 경고. + 이 오류에 대한 추가 정보는 제품 설명서의 문제 해결 항목을 참조하십시오. + ' {0} '이 (가) 재귀적으로 포함 된 파일입니다. + 주석 끝 표시 ' * /' 누락 . + 문자열에 닫히지 않은 인용 부호. + '{0}'을(를) 구문 분석하는 동안 잘못된 구문을 발견했습니다. + {0} 변수가 정의되지 않았습니다. + 테스트 + +votes +빈 문자열을 빈 문자열로 대체. + 편집 세션이 존재하지 않습니다. + 쿼리 실행이 완료되지 않았습니다. + 쿼리가 정확히 하나의 결과 집합을 생성하지 않았습니다. + 업데이트 캐시에 새로운 행 추가를 실패했습니다. + 지정된 row ID가 수정 중인 캐시의 행 범위 밖에 있습니다. + 이 행에 대한 업데이트가 이미 보류 중이므로 먼저 되돌려야 합니다. + 주어진 row ID에 보류 중인 업데이트가 없습니다. + 테이블이나 뷰 메타 데이터를 찾을 수 없습니다. + 이진 열에 형식이 잘못되었습니다. + Boolean 열은 반드시 숫자 1이나 0 혹은 문자 true나 false여야 합니다. + 필수 셀 값이 누락되었습니다. + 행 삭제가 보류 중이므로, 셀을 업데이트할 수 없습니다. + 열 ID는 쿼리의 열 범위 내에 있어야 합니다. + 열을 편집할 수 없습니다. + 키 열이 없습니다. + 출력 파일명이 필요합니다. + 데이터베이스 개체 {0} 는 편집할 수 없습니다. + 지정된 Uri ' {0} '에 기본 연결이 지정되지 않았습니다. + 커밋 작업이 진행 중입니다. 완료될 때까지 기다리세요. + Decimal 형식 열에 전체 자릿수 또는 소수 자릿수가 없습니다. + <TBD> + 결과 버퍼에 새로운 행을 추가할 수 없거나 데이터 리더에 행이 없습니다. + TIME 열의 값은 00:00:00.0000000과 23:59:59.9999999 사이의 값만 허용됩니다. + 이 열은 NULL을 허용하지 않습니다. + 편집 세션이 이미 존재합니다. + 편집 세션이 초기화 되지 않았습니다. + 편집 세션이 이미 초기화 되었습니다. + 편집 세션이 이미 초기화 되었거나 초기화 중입니다. + 쿼리 실행에 실패했습니다. 자세한 정보는 메시지를 참조하세요. + 결과 제한은 음수가 될 수 없습니다. + NULL + 개체 이름이 필요합니다. + 서버와 데이터베이스를 명시적으로 지정할 수 없습니다. + 테이블 메타데이터에 확장 속성이 없습니다. + 편집하려는 테이블이나 뷰를 찾을 수 없습니다 + 오류 확장: {0} + {0}에 연결하는 동안 오류가 발생했습니다. + 집계 + 서버 역할 + 응용 프로그램 역할 + 어셈블리 + 어셈블리 파일 + 비대칭 키 + 비대칭 키 + 데이터 압축 옵션 + 인증서 + FileTables + 인증서 + Check 제약 조건 + + 제약 조건 + 계약 + 자격 증명 + 오류 메시지 + 서버 역할 멤버 자격 + 데이터베이스 옵션 + 데이터베이스 역할 + 역할 멤버 자격 + 데이터베이스 트리거 + 기본 제약 조건 + 기본값 + 시퀀스 + 끝점 + 이벤트 알림 + 서버 이벤트 알림 + 확장 속성 + 파일 그룹 + 외래 키 + 전체 텍스트 카탈로그 + 전체 텍스트 인덱스 + 함수 + 인덱스 + 인라인 함수 + + 연결된 서버 + 연결된 서버 로그인 + 로그인 + 마스터 키 + 마스터 키 + 메시지 유형 + 테이블 반환 함수 + 매개 변수 + 파티션 함수 + 파티션 구성표 + 사용 권한 + 기본 키 + 프로그래밍 기능 + + 원격 서비스 바인딩 + 반환 열 + 역할 + 경로 + 규칙 + 스키마 + 보안 + 서버 개체 + 관리 + 트리거 + Service Broker + 서비스 + 서명 + 로그 파일 + 통계 + 저장소 + 저장 프로시저 + 대칭 키 + 동의어 + 테이블 + 트리거 + 유형 + 고유 키 + 사용자 정의 데이터 형식 + 사용자 정의 형식 (CLR) + 사용자 + + XML 인덱스 + XML 스키마 컬렉션 + 사용자 정의 테이블 형식 + 파일 + 캡션 누락 + 브로커 우선 순위 + 암호화 공급자 + 데이터베이스 감사 사양 + 데이터베이스 암호화 키 + 이벤트 세션 + 전체 텍스트 중지 목록 + 리소스 풀 + 감사 + 서버 감사 사양 + 공간 인덱스 + 작업 그룹 + SQL 파일 + 서버 함수 + SQL 유형 + 서버 옵션 + 데이터베이스 다이어그램 + 시스템 테이블 + 데이터베이스 + 시스템 계약 + 시스템 데이터베이스 + 시스템 메시지 유형 + 시스템 큐 + 시스템 서비스 + 시스템 저장 프로시저 + 시스템 뷰 + 데이터 계층 응용 프로그램 + 확장 저장 프로시저 + 집계 함수 + 근사치 + 이진 문자열 + 문자열 + CLR 데이터 형식 + 구성 함수 + 커서 함수 + 시스템 데이터 형식 + 날짜 및 시간 + 날짜 및 시간 함수 + 정확한 수치 + 시스템 함수 + 계층 구조 ID 함수 + 수학 함수 + 메타데이터 함수 + 기타 데이터 형식 + 기타 함수 + 행 집합 함수 + 보안 함수 + 공간 데이터 형식 + 문자열 함수 + 시스템 통계 함수 + 텍스트 및 이미지 함수 + 유니코드 문자열 + 집계 함수 + 스칼라 반환 함수 + 테이블 반환 함수 + 시스템 확장 저장 프로시저 + 기본 제공 유형 + 기본 제공 서버 역할 + 암호가 있는 사용자 + 검색 속성 목록 + 보안 정책 + 보안 조건자 + 서버 역할 + 검색 속성 목록 + 열 저장 인덱스 + 테이블 형식 인덱스 + 선택적 XML 인덱스 + XML 네임스페이스 + XML 유형의 공유된 경로 + T-SQL 유형의 공유된 경로 + 데이터베이스 범위 자격 증명 + 외부 데이터 원본 + 외부 파일 형식 + 외부 리소스 + 외부 테이블 + Always Encrypted 키 + 열 마스터 키 + 열 암호화 키 + 서버 + 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} 데이터베이스에 액세스할 수 없습니다. + 쿼리 반환 결과 없음 + 결과 집합의 행 수가 너무 많아서 안전하게 불러들일 수 없습니다. + 매개 변수화 + NORECOVERY 옵션을 사용하여 백업을 복원하는 동안 이 옵션을 지정할 수 없습니다. + 데이터베이스 파일의 경로가 잘못되었습니다. '{0}' + 로그 + 복원 계획을 만들지 못했습니다 + 데이터베이스 복원은 지원되지 않습니다. + 데이터베이스 복원 + 복사 전용 + 구성 요소 + 형식 + 서버 + 데이터베이스 + 위치 + 첫 번째 LSN + 마지막 LSN + 검사점 LSN + 전체 LSN + 시작 날짜 + 완료 날짜 + 크기 + 사용자 이름 + 만료 + Name + 수행된 마지막 백업({0}) + 데이터베이스 백업 + 진행 중 + 완료됨 + 스크립팅 + 연결 없음 + 지정한 파일 이름은 디렉터리 이름이기도 합니다: {0} + 백업 파일 위치를 확인할 수 없습니다: {0} + 서버에서 지정된 경로에 액세스할 수 없습니다: {0} + 복원하려는 백업 세트를 선택하지 않았습니다 + 안 함 + Azure SQL DB + Azure SQL Data Warehouse + Azure SQL 신축성 데이터베이스 + 경로 [{0}]은(는) 올바른 디렉터리가 아닙니다. + 디렉터리 {0}에 대한 파일{1} 이 이미 존재합니다. + 값 {0}이 너무 커서 {1} 유형의 열에 들어갈 수 없습니다. + \ No newline at end of file diff --git a/src/Microsoft.SqlTools.CoreServices/Localization/sr.pt-BR.resx b/src/Microsoft.SqlTools.CoreServices/Localization/sr.pt-BR.resx new file mode 100644 index 00000000..92765727 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Localization/sr.pt-BR.resx @@ -0,0 +1,490 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +text/microsoft-resx1.3System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089Parâmetros de Conexão não podem ser nulos + OwnerUri não pode ser nulo ou vazio + SpecifiedUri '{0}' não há uma conexão existente + Valor inválido '{0}' para AuthenticationType. Os valores válidos são 'Integrada' e 'SqlLogin'. + Valor inválido '{0}' para ApplicationIntent. Os valores válidos são 'ReadWrite' e 'Somente leitura'. + Conexão cancelada + OwnerUri não pode ser nulo ou vazio + Objeto de detalhes de Conexão não pode ser nulo + ServerName não pode ser nulo ou vazio + {0} não pode ser nulo ou vazio quando estiver usando autenticação SqlLogin + A consulta já foi concluída, ela não pode ser cancelada + Consulta cancelada com êxito, Falha ao descartar a consulta. Proprietário do URI não encontrado. + Consulta foi cancelada pelo usuário + O lote ainda não foi concluído. + Índice de lote não pode ser menor que 0 ou maior que o número de lotes + Índice do conjunto de resultados não pode ser menor que 0 ou maior que o número do conjuntos de resultados + Número máximo de bytes a serem retornados deve ser maior que zero + Número máximo de caracteres a serem retornados deve ser maior que zero + Número máximo de bytes XML a serem retornados deve ser maior que zero + Método de acesso não pode ser somente gravação + FileStreamWrapper deve ser inicializado antes de executar operações + Este FileStreamWrapper não pode ser usado para gravação + (1 linha afetada) + ({0} linhas afetadas) + Comandos concluídos com sucesso. + Msg {0}, Nível {1}, Estado {2}, Linha {3} {4} {5} + Falha na consulta: {0} + (Nenhum nome de coluna) + A consulta solicitada não existe. + Este editor não está conectado a um banco de dados + Uma consulta já está em andamento para esta sessão do editor. Favor cancelar esta consulta ou aguardar a sua conclusão + Remetente do evento OnInfoMessage deve ser um SqlConnection + Resultado não pode ser salvo até que seja concluída a execução da consulta + Ocorreu um erro interno ao iniciar tarefa de salvamento + Uma solicitação de salvamento para o mesmo caminho está em andamento + Falha ao salvar {0}: {1} + Não é possível ler o subconjunto, a menos que os resultados tenham sido lidos do servidor + Linha de início não pode ser menor que 0 ou maior que o número de linhas no conjunto de resultados + Contagem de linhas deve ser um inteiro positivo + Não foi possível recuperar o esquema de colunas para o conjunto de resultados + Não foi possível recuperar um plano de execução do conjunto de resultados + Esse recurso não é atualmente suportado no banco de dados de SQL Azure e Data Warehouse: {0} + Ocorreu um erro inesperado durante a execução da inspeção da definição: + Nenhum resultado foi encontrado. + Nenhum objeto de banco de dados foi recuperado. + Favor conectar-se a um servidor. + Tempo limite da operação esgotado. + Este tipo de objeto não é suportado atualmente por esse recurso. + Posição está fora do intervalo de linhas do arquivo + A posição está fora do intervalo de colunas para linha {0} + Posição inicial ({0}, {1}) deve vir antes ou ser igual a posição final ({2}, {3}) + Msg {0}, Nível {1}, Estado {2}, Linha {3} + Msg {0}, Nível {1}, Estado {2}, Procedimento {3}, Linha {4} + Msg {0}, Nível {1}, Estado {2} + Ocorreu um erro durante o processamento do lote. A mensagem de erro é: {0} + ({0} linhas afetadas) + Execução anterior ainda não foi concluída. + Ocorreu um erro de script. + Sintaxe incorreta foi encontrada enquanto {0} estava sendo analisado. + Ocorreu um erro fatal. + Execução concluída {0} vezes... + Você cancelou a consulta. + Ocorreu um erro enquanto o lote estava sendo executado. + Ocorreu um erro enquanto o lote estava sendo executado, mas o erro foi ignorado. + Beginning execution loop + Comando {0} não é suportado. + A variável {0} não pôde ser encontrada. + Erro de execução de SQL: {0} + Execução do pacote do analisador de lotes: {0} encontrado... na linha {1}: {2} Descrição: {3} + Mensagem recebida do motor de execução do pacote do analisador de lotes: Mensagem: {0} Mensagem detalhada: {1} + Processando o conjunto de resultados no motor de execução do pacote do analisador de lotes: DataReader.FieldCount: {0} DataReader.RecordsAffected: {1} + Execução do conjunto de resultados do motor de execução de pacotes do analisador de lotes terminada. + Cancelando execução do conjunto de resultados do motor de execução de pacotes do analisador de lotes. + Aviso de script. + Para obter mais informações sobre esse erro, consulte os tópicos de solução de problemas na documentação do produto. + Arquivo '{0}' incluído recursivamente. + Sem marca de comentário final ' * /'. + Aspas não fechadas depois da sequência de caracteres. + Sintaxe incorreta foi encontrada enquanto {0} estava sendo analisado. + A variável {0} não está definida. + teste + Substituição de uma sequência vazia por uma cadeia de caracteres vazia. + Sessão de edição não existe. + A consulta não completou a execução + A consulta não gerou exatamente um conjunto de resultados + Falha ao adicionar uma nova linha ao cache de atualização + ID de linha de entrada fora da faixa de linhas no cache de edição + Uma atualização está ainda pendente para esta linha e deve ser revertida antes + Não existem atualizações pendentes para o ID informado. + Tabela ou view de metadados não pode ser encontrada + Formato inválido para coluna binária + Colunas Booleanas devem possuir o número 1 ou 0 ou a string true ou false + Um valor requerido para a célula está faltando + Uma exclusão está pendente para esta linha. Uma atualização desta célula não pode ser aplicada. + Um ID de coluna deve estar no intervalo de colunas para a consulta + Coluna não pode ser editada + Não foram encontradas colunas chave + Um nome de arquivo de saída deve ser fornecido + O objecto de banco de dados {0} não pode ser usado para edição. + A URI especificada '{0}' não tem uma conexão padrão + Uma tarefa de gravação está em progresso. Favor aguardar o térnino. + Coluna decimal não tem precisão numérica ou escala numérica + <TBD> + Não é possível adicionar linha ao buffer de resultados, o datareader não contém linhas + Os valores da coluna do tipo de dados TIME devem estar entre 00:00:00.0000000 e 23:59:59.9999999 + Nulo não é permitido para esta coluna. + Sessão de edição já existe. + Sessão de edição não foi inicializada + Sessão de edição já foi inicializada + Sessão de edição já foi inicializada ou está em processo de inicialização + A execução da consulta falhou, veja as mensagens para detalhes + Limite de resultados não pode ser negativo + NULL + O nome do objeto deve ser fornecido. + O servidor ou banco de dados especificado não é suportado. + Metadados da tabela não possuem propriedades extendidas + Tabela ou view requisitada para edição não foi encontrada + Erro expandindo: {0} + Erro conectando a {0} + Agregados + Funcões de Servidor + Funções de Aplicação + Assemblies + Arquivos de Assemblies + Chaves Assimétricas + Chaves Assimétricas + Opções de Compressão de Dados + Certificados + Tabelas de Arquivos + Certificados + Verificação de Restrições + Colunas + Restrições + Contratos + Credenciais + Mensagens de Erro + Adesão às Funções de Servidor + Opções de Banco de Dados + Funções de Bancos de Dados + Adesão às Funções + Gatilhos de Bancos de Dados + + Restrições Padrão + Padrões + Sequências + Pontos finais + Notificações de Eventos + Notificações de Eventos de Servidor + Propriedades Extendidas + Grupos de Arquivos + Chaves Estrangeiras + Catálogos Full-Text + Índices Full-Text + Funções + Índices + Funções em Linha + Chaves + Servidores vinculados + Logins de servidores vinculados + Logins + Master key + Master Keys + Tipos de Mensagens + Funções de Valor de Tabelas + Parâmetros + Funções de Partição + Esquemas de Partição + Permissões + Chaves Primárias + Programabilidade + Filas + Ligações de Serviço Remoto + Colunas Retornadas + Funções + Rotas + Regras + Esquemas + Segurança + Objetos de Servidor + Gerenciamento + Gatilhos + Service Broker + Serviços + Assinaturas + Arquivos de Log + Estatísticas + Armazenamento + Stored Procedures + Chaves Simétricas + Sinônimos + Tabelas + Gatilhos + Tipos + Chaves Únicas + Tipos de Dados Definidos pelo Usuário + Tipos Definidos pelo Usuário (CLR) + Usuários + Visualizações + Índices XML + Coleções de Esquemas XML + Tipos de Tabelas Definidas pelo Usuário + Arquivos + Título Faltando + Prioridades do Agente + Provedores de Criptografia + Especificações de Auditoria de Banco de Dados + Chaves de Criptografia de Banco de Dados + Sessões de Evento + Listas de Parada Full Text + Pool de Recursos + Auditorias + Especificações de Auditoria de Servidor + Índices Espaciais + Grupos de Trabalho + Arquivos SQL + Funções de Servidor + Tipo SQL + Opções de Servidor + Diagramas de Banco de Dados + Tabelas do Sistema + Bancos de Dados + Contratos do Sistema + Bancos de Dados do Sistema + Tipos de Mensagens do Sistema + Filas do Sistema + Serviços do Sistema + Stored Procedures do Sistema + Visualizações do Sistema + Aplicações da Camada de Dados + Stored Procedures Estendidas + Funções Agregadas + Numéricos Aproximados + Cadeias de Caracteres Binárias + Cadeias de Caracteres + Tipos de Dados CLR + Funções de Configuração + Funções de Cursor + Tipos de Dados do Sistema + Data e Hora + Funções de Data e Hora + Numéricos Exatos + Funções do Sistema + Funções de ID de Hierarquia + Funções Matemáticas + Funções de Metadados + Outros tipos de Dados + Outras Funções + Funções de Conjuntos de Linhas + Funções de Segurança + Tipos de Dados Espaciais + Funções de Cadeias de Caracteres + Funções Estatísticas do Sistema + Funções de Texto e Imagem + Cadeias de Caracteres Unicode + Funções Agregadas + Funções de Valores Escalares + Funções de Valores Baseadas em Tabelas + Stored Procedures do Sistema Estendidas + Tipos Intrínsecos + Funções de Servidor Intrínsecas + Usuário com Senha + Pesquisar Lista de Propriedades + Políticas de Segurança + Predicados de Segurança + Função de Servidor + Pesquisar Listas de Propriedades + Índices de Colunas + Índices de Tipos de Tabelas + Índices XML Seletivos + Namespaces XML + Caminhos Promovidos de Tipos XML + Caminhos Promovidos de Tipos T-SQL + Credenciais de Escopo de Banco de Dados + Fontes de Dados Externas + Formatos de Arquivos Externos + Recursos Externos + Tabelas Externas + Chaves Sempre Criptografadas + Chaves Mestras de Colunas + 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 + Parametrização + Não é permitido especificar essa opção ao restaurar um backup com a opção NORECOVERY. + Caminho inválido para o arquivo de banco de dados: '{0}' + Log + Falha ao criar o plano de restauração + Restauração de banco de dados não é suportado + Restaurar o banco de dados + (Apenas cópia) + Componente + Tipo + Servidor + Banco de dados + Posição + Primeiro LSN + Último LSN + Checkpoint LSN + LSN completo + Data de Início + Data de Término + Tamanho + Nome do usuário + Expiração + Nome + O último backup feito ({0}) + Backup do Banco de Dados + Em andamento + Concluído + Gerando script + Conexão não encontrada + O nome do arquivo especificado também é um nome de diretório: {0} + Não foi possível verificar a existência do local do arquivo de backup: {0} + Não foi possível acessar o diretório especificado no servidor: {0} + Nenhum conjunto de backup selecionado para ser restaurado + Nunca + Azure SQL DB + Azure SQL Data Warehouse + Azure SQL Stretch Database + Caminho {0} não é um diretório válido + Já existe um arquivo com nome {1} para o diretório {0} + Valor {0} é muito grande para caber em uma coluna do tipo {1} + \ No newline at end of file diff --git a/src/Microsoft.SqlTools.CoreServices/Localization/sr.resx b/src/Microsoft.SqlTools.CoreServices/Localization/sr.resx new file mode 100755 index 00000000..3e186b0c --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Localization/sr.resx @@ -0,0 +1,2005 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Connection parameters cannot be null + + + + OwnerUri cannot be null or empty + + + + SpecifiedUri '{0}' does not have existing connection + . + Parameters: 0 - uri (string) + + + Specified URI '{0}' does not have a default connection + . + Parameters: 0 - uri (string) + + + Invalid value '{0}' for AuthenticationType. Valid values are 'Integrated' and 'SqlLogin'. + . + Parameters: 0 - authType (string) + + + Invalid value '{0}' for ApplicationIntent. Valid values are 'ReadWrite' and 'ReadOnly'. + . + Parameters: 0 - intent (string) + + + Connection canceled + + + + OwnerUri cannot be null or empty + + + + Connection details object cannot be null + + + + ServerName cannot be null or empty + + + + {0} cannot be null or empty when using SqlLogin authentication + . + Parameters: 0 - component (string) + + + Azure SQL DB + + + + Azure SQL Data Warehouse + + + + Azure SQL Stretch Database + + + + The query has already completed, it cannot be cancelled + + + + Query successfully cancelled, failed to dispose query. Owner URI not found. + + + + Query was canceled by user + + + + The batch has not completed, yet + + + + Batch index cannot be less than 0 or greater than the number of batches + + + + Result set index cannot be less than 0 or greater than the number of result sets + + + + Maximum number of bytes to return must be greater than zero + + + + Maximum number of chars to return must be greater than zero + + + + Maximum number of XML bytes to return must be greater than zero + + + + Access method cannot be write-only + + + + FileStreamWrapper must be initialized before performing operations + + + + This FileStreamWrapper cannot be used for writing + + + + (1 row affected) + + + + ({0} rows affected) + . + Parameters: 0 - rows (long) + + + Commands completed successfully. + + + + Msg {0}, Level {1}, State {2}, Line {3}{4}{5} + . + Parameters: 0 - msg (int), 1 - lvl (int), 2 - state (int), 3 - line (int), 4 - newLine (string), 5 - message (string) + + + Query failed: {0} + . + Parameters: 0 - message (string) + + + (No column name) + + + + NULL + + + + The requested query does not exist + + + + This editor is not connected to a database + + + + A query is already in progress for this editor session. Please cancel this query or wait for its completion. + + + + Sender for OnInfoMessage event must be a SqlConnection + + + + Cannot add row to result buffer, data reader does not contain rows + + + + Query has no results to return + + + + Result set has too many rows to be safely loaded + + + + Result cannot be saved until query execution has completed + + + + Internal error occurred while starting save task + + + + A save request to the same path is in progress + + + + Failed to save {0}: {1} + . + Parameters: 0 - fileName (string), 1 - message (string) + + + Cannot read subset unless the results have been read from the server + + + + Start row cannot be less than 0 or greater than the number of rows in the result set + + + + Row count must be a positive integer + + + + Could not retrieve column schema for result set + + + + Could not retrieve an execution plan from the result set + + + + This feature is currently not supported on Azure SQL DB and Data Warehouse: {0} + . + Parameters: 0 - errorMessage (string) + + + An unexpected error occurred during Peek Definition execution: {0} + . + Parameters: 0 - errorMessage (string) + + + No results were found. + + + + No database object was retrieved. + + + + Please connect to a server. + + + + Operation timed out. + + + + This object type is currently not supported by this feature. + + + + Replacement of an empty string by an empty string. + + + + Position is outside of file line range + + + + Position is outside of column range for line {0} + . + Parameters: 0 - line (int) + + + Start position ({0}, {1}) must come before or be equal to the end position ({2}, {3}) + . + Parameters: 0 - sLine (int), 1 - sCol (int), 2 - eLine (int), 3 - eCol (int) + + + Table or view requested for edit could not be found + + + + Edit session does not exist. + + + + Edit session already exists. + + + + Edit session has not been initialized + + + + Edit session has already been initialized + + + + Edit session has already been initialized or is in the process of initializing + + + + Table metadata does not have extended properties + + + + A object name must be provided + + + + Explicitly specifying server or database is not supported + + + + Result limit cannot be negative + + + + Database object {0} cannot be used for editing. + . + Parameters: 0 - typeName (string) + + + Query execution failed, see messages for details + + + + Query has not completed execution + + + + Query did not generate exactly one result set + + + + Failed to add new row to update cache + + + + Given row ID is outside the range of rows in the edit cache + + + + An update is already pending for this row and must be reverted first + + + + Given row ID does not have pending update + + + + Table or view metadata could not be found + + + + Invalid format for column '{0}', column is defined as {1} + . + Parameters: 0 - colName (string), 1 - colType (string) + + + Invalid format for binary column + + + + Allowed values for boolean columns are 0, 1, "true", or "false" + + + + The column '{0}' is defined as NOT NULL but was not given a value + . + Parameters: 0 - colName (string) + + + A delete is pending for this row, a cell update cannot be applied. + + + + Column ID must be in the range of columns for the query + + + + Column cannot be edited + + + + No key columns were found + + + + An output filename must be provided + + + + A commit task is in progress. Please wait for completion. + + + + <TBD> + + + + TIME column values must be between 00:00:00.0000000 and 23:59:59.9999999 + + + + NULL is not allowed for this column + + + + Value {0} is too large to fit in column of type {1} + . + Parameters: 0 - value (string), 1 - columnType (string) + + + Msg {0}, Level {1}, State {2}, Line {3} + + + + Msg {0}, Level {1}, State {2}, Procedure {3}, Line {4} + + + + Msg {0}, Level {1}, State {2} + + + + An error occurred while the batch was being processed. The error message is: {0} + + + + ({0} row(s) affected) + + + + The previous execution is not yet complete. + + + + A scripting error occurred. + + + + Incorrect syntax was encountered while {0} was being parsed. + + + + A fatal error occurred. + + + + Batch execution completed {0} times... + + + + You cancelled the query. + + + + An error occurred while the batch was being executed. + + + + An error occurred while the batch was being executed, but the error has been ignored. + + + + Beginning execution loop + + + + Command {0} is not supported. + + + + The variable {0} could not be found. + + + + SQL Execution error: {0} + + + + Batch parser wrapper execution: {0} found... at line {1}: {2} Description: {3} + + + + Batch parser wrapper execution engine batch message received: Message: {0} Detailed message: {1} + + + + Batch parser wrapper execution engine batch ResultSet processing: DataReader.FieldCount: {0} DataReader.RecordsAffected: {1} + + + + Batch parser wrapper execution engine batch ResultSet finished. + + + + Canceling batch parser wrapper batch execution. + + + + Scripting warning. + + + + For more information about this error, see the troubleshooting topics in the product documentation. + + + + File '{0}' recursively included. + + + + Missing end comment mark '*/'. + + + + Unclosed quotation mark after the character string. + + + + Incorrect syntax was encountered while parsing '{0}'. + + + + Variable {0} is not defined. + + + + test + + + + Exact numeric column is missing numeric precision or numeric scale + + + + Column with length is missing size + + + + Scalar column missing scale + + + + Error expanding: {0} + + + + Error connecting to {0} + + + + Aggregates + + + + Server Roles + + + + Application Roles + + + + Assemblies + + + + Assembly Files + + + + Asymmetric Keys + + + + Asymmetric Keys + + + + Data Compression Options + + + + Certificates + + + + FileTables + + + + Certificates + + + + Check Constraints + + + + Columns + + + + Constraints + + + + Contracts + + + + Credentials + + + + Error Messages + + + + Server Role Membership + + + + Database Options + + + + Database Roles + + + + Role Memberships + + + + Database Triggers + + + + Default Constraints + + + + Defaults + + + + Sequences + + + + Endpoints + + + + Event Notifications + + + + Server Event Notifications + + + + Extended Properties + + + + Filegroups + + + + Foreign Keys + + + + Full-Text Catalogs + + + + Full-Text Indexes + + + + Functions + + + + Indexes + + + + Inline Functions + + + + Keys + + + + Linked Servers + + + + Linked Server Logins + + + + Logins + + + + Master Key + + + + Master Keys + + + + Message Types + + + + Table-Valued Functions + + + + Parameters + + + + Partition Functions + + + + Partition Schemes + + + + Permissions + + + + Primary Keys + + + + Programmability + + + + Queues + + + + Remote Service Bindings + + + + Returned Columns + + + + Roles + + + + Routes + + + + Rules + + + + Schemas + + + + Security + + + + Server Objects + + + + Management + + + + Triggers + + + + Service Broker + + + + Services + + + + Signatures + + + + Log Files + + + + Statistics + + + + Storage + + + + Stored Procedures + + + + Symmetric Keys + + + + Synonyms + + + + Tables + + + + Triggers + + + + Types + + + + Unique Keys + + + + User-Defined Data Types + + + + User-Defined Types (CLR) + + + + Users + + + + Views + + + + XML Indexes + + + + XML Schema Collections + + + + User-Defined Table Types + + + + Files + + + + Missing Caption + + + + Broker Priorities + + + + Cryptographic Providers + + + + Database Audit Specifications + + + + Database Encryption Keys + + + + Event Sessions + + + + Full Text Stoplists + + + + Resource Pools + + + + Audits + + + + Server Audit Specifications + + + + Spatial Indexes + + + + Workload Groups + + + + SQL Files + + + + Server Functions + + + + SQL Type + + + + Server Options + + + + Database Diagrams + + + + System Tables + + + + Databases + + + + System Contracts + + + + System Databases + + + + System Message Types + + + + System Queues + + + + System Services + + + + System Stored Procedures + + + + System Views + + + + Data-tier Applications + + + + Extended Stored Procedures + + + + Aggregate Functions + + + + Approximate Numerics + + + + Binary Strings + + + + Character Strings + + + + CLR Data Types + + + + Configuration Functions + + + + Cursor Functions + + + + System Data Types + + + + Date and Time + + + + Date and Time Functions + + + + Exact Numerics + + + + System Functions + + + + Hierarchy Id Functions + + + + Mathematical Functions + + + + Metadata Functions + + + + Other Data Types + + + + Other Functions + + + + Rowset Functions + + + + Security Functions + + + + Spatial Data Types + + + + String Functions + + + + System Statistical Functions + + + + Text and Image Functions + + + + Unicode Character Strings + + + + Aggregate Functions + + + + Scalar-valued Functions + + + + Table-valued Functions + + + + System Extended Stored Procedures + + + + Built-in Types + + + + Built-in Server Roles + + + + User with Password + + + + Search Property List + + + + Security Policies + + + + Security Predicates + + + + Server Role + + + + Search Property Lists + + + + Column Store Indexes + + + + Table Type Indexes + + + + Server + + + + Selective XML Indexes + + + + XML Namespaces + + + + XML Typed Promoted Paths + + + + T-SQL Typed Promoted Paths + + + + Database Scoped Credentials + + + + External Data Sources + + + + External File Formats + + + + External Resources + + + + External Tables + + + + Always Encrypted Keys + + + + Column Master Keys + + + + Column Encryption Keys + + + + {0} ({1}, {2}, {3}) + + + + No default + + + + Input + + + + Input/Output + + + + Input/ReadOnly + + + + Input/Output/ReadOnly + + + + Default + + + + null + + + + not null + + + + {0} ({1}, {2}) + + + + {0} ({1}) + + + + {0} ({1}Computed, {2}, {3}) + + + + {0} ({1}Computed) + + + + {0} (Column Set, {1}) + + + + {0} (Column Set, {1}{2}, {3}) + + + + {0} (Column Set, {1}, {2}, {3}) + + + + Unique + + + + Non-Unique + + + + Clustered + + + + Non-Clustered + + + + History + + + + System-Versioned + + + + External + + + + File Table + + + + The database {0} is not accessible. + + + + Error parsing ScriptingParams.ConnectionString property. + + + + Invalid directory specified by the ScriptingParams.FilePath property. + + + + Error parsing ScriptingListObjectsCompleteParams.ConnectionString property. + + + + -- TODO: Set parameter values here. + + + + An error occurred while scripting the objects. + + + + Scripting as Execute is only supported for Stored Procedures + + + + Unavailable + + + + Current default filegroup: {0} + + + + New Filegroup for {0} + + + + Default + + + + Files + + + + Name + + + + Read-Only + + + + Autogrowth / Maxsize + + + + ... + + + + <default> + + + + Filegroup + + + + Logical Name + + + + File Type + + + + Initial Size (MB) + + + + <new filegroup> + + + + Path + + + + File Name + + + + <raw device> + + + + Bulk-logged + + + + Full + + + + Simple + + + + Select Database Owner + + + + None + + + + By {0} MB, Limited to {1} MB + + + + By {0} percent, Limited to {1} MB + + + + By {0} MB, Unlimited + + + + By {0} percent, Unlimited + + + + Unlimited + + + + Limited to {0} MB + + + + Automatic + + + + Service Broker + + + + Collation + + + + Cursor + + + + Miscellaneous + + + + Recovery + + + + State + + + + ANSI NULL Default + + + + ANSI NULLS Enabled + + + + ANSI Padding Enabled + + + + ANSI Warnings Enabled + + + + Arithmetic Abort Enabled + + + + Auto Close + + + + Auto Create Statistics + + + + Auto Shrink + + + + Auto Update Statistics + + + + Auto Update Statistics Asynchronously + + + + Case Sensitive + + + + Close Cursor on Commit Enabled + + + + Collation + + + + Concatenate Null Yields Null + + + + Database Compatibility Level + + + + Database State + + + + Default Cursor + + + + Full-Text Indexing Enabled + + + + Numeric Round-Abort + + + + Page Verify + + + + Quoted Identifiers Enabled + + + + Database Read-Only + + + + Recursive Triggers Enabled + + + + Restrict Access + + + + Select Into/Bulk Copy + + + + Honor Broker Priority + + + + Service Broker Identifier + + + + Broker Enabled + + + + Truncate Log on Checkpoint + + + + Cross-database Ownership Chaining Enabled + + + + Trustworthy + + + + Date Correlation Optimization Enabled + + + + Parameterization + + + + Forced + + + + Simple + + + + ROWS Data + + + + LOG + + + + FILESTREAM Data + + + + Not Applicable + + + + <default path> + + + + Open Connections + + + + To change the database properties, SQL Server must close all other connections to the database_ Are you sure you want to change the properties and close all other connections? + + + + 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 Storage Format Enabled + + + + SQL Server 2008 (100) + + + + Encryption Enabled + + + + OFF + + + + ON + + + + PRIMARY + + + + For the distribution policy HASH, the number of leading hash columns is optional but should be from 1 to 16 columns + + + + SQL Server 2012 (110) + + + + SQL Server 2014 (120) + + + + SQL Server 2016 (130) + + + + SQL Server vNext (140) + + + + None + + + + Partial + + + + FILESTREAM Files + + + + No Applicable Filegroup + + + + Never + + + + Path {0} is not a valid directory + + + + For directory {0} a file with name {1} already exists + + + + Backup Database + + + + Please provide a file path instead of directory path + + + + The provided path is invalid + + + + In progress + + + + Completed + + + + Specifying this option when restoring a backup with the NORECOVERY option is not permitted. + + + + Invalid path for database file: '{0}' + + + + Log + + + + Failed to create restore plan + + + + Restore database is not supported + + + + 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 + + + + The last backup taken ({0}) + + + + No backupset selected to be restored + + + + scripting + + + + Cannot access the specified path on the server: {0} + + + + Connection not found + + + diff --git a/src/Microsoft.SqlTools.CoreServices/Localization/sr.ru.resx b/src/Microsoft.SqlTools.CoreServices/Localization/sr.ru.resx new file mode 100644 index 00000000..9fe98a9d --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Localization/sr.ru.resx @@ -0,0 +1,483 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +text/microsoft-resx1.3System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089Параметры подключения должны быть указаны, значение не может быть неопределенным (null) + OwnerUri не может быть неопределенным или пустым + SpecifiedUri «{0}» не имеет существующего подключения + Значение «{0}» недопустимо для AuthenticationType. Ожидается значение «Integrated» или «SqlLogin». + Значение «{0}» недопустимо для ApplicationIntent. Ожидается значение «ReadWrite» или «ReadOnly». + Подключение к серверу отменено. + OwnerUri не может быть неопределенным или пустым + Параметры подключения не могут быть неопределенными + Имя сервера не может быть неопределенным или пустым + {0} не может быть неопределенным или пустым при использовании проверки подлинности SqlLogin + Запрос уже был выполнен, отмена невозможна + Запрос успешно отменен, но удалить запрос не удалось. Владелец URI не найден. + Выполнение запроса отменено пользователем + Пакет еще не завершен + Индекс пакета не может быть меньше нуля или больше числа пакетов + Индекс не может быть меньше нуля или больше количества записей в наборе + Максимальное количество возвращаемых байтов должно быть больше нуля + Максимальное количество возвращаемых символов должно быть больше нуля + Максимальное количество возвращаемых из XML байтов должно быть больше нуля + Метод доступа не может быть только для записи. + FileStreamWrapper должен быть инициализирован перед выполнением операций + Этот экземпляр FileStreamWrapper не может быть использован для записи + (одна строка затронута) + ({0} строк затронуто) + Выполнение команд успешно завершено. + Сообщение {0}, Уровень {1}, Состояние {2}, Строка {3}{4}{5} + Не удалось выполнить запрос: {0} + (Нет имени столбца) + Указанный запрос не найден + Этот редактор не подключен к базе данных + Запрос уже выполняется для данного сеанса редактора. Отмените запрос или дождитесь завершения его выполнения. + В качестве отправителя (sender) для события OnInfoMessage ожидается экземпляр SqlConnection + Результат не может быть сохранен до завершения выполнения запроса + При запуске задачи сохранения произошла внутренняя ошибка + По указанному пути уже выполняется сохранение результатов + Не удалось сохранить {0}: {1} + Невозможно прочитать подмножество, поскольку результаты еще не были получены с сервера + Индекс начальной строки не может быть меньше нуля или больше количества строк, находящихся в результирующем наборе + Число строк должно быть положительным целым числом + Не удалось получить столбец схемы для результирующего набора + Не удалось получить план выполнения из результирующего набора + В настоящее время эта функция не поддерживается Azure SQL DB и Data Warehouse: {0} + Произошла непредвиденная ошибка во время выполнения Peek Definition: {0} + Результаты не найдены. + Объект базы данных не был получен. + Подключитесь к серверу. + Истекло время ожидания операции. + В настоящее время этот тип объекта не поддерживается этим средством. + Позиция выходит за пределы диапазона строк файла + Позиция выходит за пределы диапазона столбцов строки {0} + Начальная позиция ({0}, {1}) должна быть меньше либо равна конечной ({2}, {3}) + Сообщение {0}, уровень {1}, состояние {2}, строка {3} + Сообщение {0}, уровень {1}, состояние {2}, процедура {3}, строка {4} + Сообщение {0}, уровень {1}, состояние {2} + При обработке пакета произошла ошибка: {0} + ({0} строк затронуто) + Предыдущее выполнение еще не завершено. + Произошла ошибка сценария. + Обнаружен неправильный синтаксис при обработке {0}. + Произошла неустранимая ошибка. + Выполнение завершено такое количество раз: {0}... + Пользователь отменил запрос. + При выполнении пакета произошла ошибка. + В процессе выполнения пакета произошла ошибка, но она была проигнорирована. + Beginning execution loop + Команда {0} не поддерживается. + Переменная {0} не найдена. + Ошибка выполнения SQL: {0} + BatchParserWrapper: {0} найдено; строка {1}: {2}; описание: {3} + BatchParserWrapper получено сообщение: {0}. Детали: {1} + BatchParserWrapper выполнение пакетной обработки ResultSet. DataReader.FieldCount: {0} DataReader.RecordsAffected: {1} + BatchParserWrapper: обработка завершена. + BatchParserWrapper: выполнение пакета отменено. + Сценарий содержит предупреждения. + Для получения дополнительной информации об этой ошибке, обратитесь к разделам по устранению неполадок в документации по продукту. + Обнаружена рекурсивная ссылка на файл «{0}». + Отсутствует обозначение конца комментария - «*/». + Незакрытые кавычки в конце символьной строки. + При разборе «{0}» обнаружен неправильный синтаксис. + Переменная {0} не определена. + тест + Замена пустой строки на пустую строку. + Сеанс не найден. + Выполнение запроса не завершено + Запрос должен содержать только один набор результатов + Не удалось добавить новую строку в кэш обновлений + Указанный идентификатор строки находится за пределами диапазона строк в кэше редактирования + Обновление уже отправлено для этой строки и должно быть отменено первым + Для указанной строки нет обновлений в очереди + Не удалось найти метаданные таблицы или представления + Недопустимый формат данных для двоичного столбца + Логические столбцы должны содержать число 1 или 0, либо строку true или false + Недопустимое значение ячейки + Обновление ячейки не может быть применено, поскольку для данной строки ожидается удаление. + Идентификатор столбца должен находиться в диапазоне столбцов запроса + Столбец не может быть изменен + Ключевые поля не найдены + Должно быть указано имя выходного файла + Объект базы данных {0} не может использоваться для редактирования. + Указанный URI '{0}' не имеет соединения по умолчанию + Выполняется фиксация. Пожалуйста, дождитесь завершения. + В десятичном столбце отсутствует числовая точность или масштаб + <TBD> + Невозможно добавить строку в файл буфера, поток не содержит строк + Значение столбца TIME должно находиться в диапазоне между 00:00:00.0000000 и 23:59:59.9999999 + Значение NULL недопустимо в этом столбце. + Сеанс редактирования уже существует. + Сеанс редактирования не был инициализирован. + Сеанс редактирования уже был инициализирован. + Сеанс редактирования уже был инициализирован или находится в процессе инициализации + Не удалось выполнить запрос, см. сообщения для получения подробностей + Значение, определяющее ограничение числа записей, не может быть отрицательным + NULL + Должно быть указано имя объекта + Явное указание сервера или базы данных не поддерживается + Метаданные таблицы не имеют расширенных свойств + Запрошенная таблица или представление не найдены. + Ошибка при расширении: {0} + Ошибка при подключении к {0} + Статистические выражения + Роли сервера + Роли приложения + Сборки + Файлы сборки + Асимметричные ключи + Асимметричные ключи + Параметры сжатия данных + Сертификаты + Объекты FileTable + Сертификаты + Проверочные ограничения + Столбцы + Ограничения + Контракты + Учетные данные + Сообщения об ошибках + Участие в роли сервера + Параметры базы данных + Роли базы данных + Членства в роли + Триггеры базы данных + Ограничения по умолчанию + Значения по умолчанию + Последовательности + Конечные точки + Уведомления о событиях + Уведомления о событиях сервера + Расширенные свойства + Файловые группы + Внешние ключи + Полнотекстовые каталоги + Полнотекстовые индексы + Функции + Индексы + Встроенная функции + Ключи + Связанные серверы + Имена входа на связанный сервер + Имена входа + Главный ключ + Главные ключи + Типы сообщений + Функция с табличным значением + Параметры + Функции секционирования + Схемы секционирования + Разрешения + Первичные ключи + Программируемость + Списки ожидания + Привязки удаленных служб + Возвращенные столбцы + Роли + Маршруты + Правила + Схемы + Безопасность + Объекты сервера + Управление + Триггеры + Компонент Service Broker + Службы + Сигнатуры + Файлы журнала + Статистика + Хранилище + Хранимые процедуры + Симметричные ключи + Синонимы + Таблицы + Триггеры + Типы + Уникальные ключи + Определяемые пользователем типы данных + Определяемые пользователем типы (CLR) + Пользователи + Представления + XML-индексы + Коллекция схем XML + Определяемые пользователем типы таблиц + Файлы + Отсутствует заголовок + Приоритеты брокера + Поставщики служб шифрования + Спецификации аудита базы данных + Ключи шифрования базы данных + Сеансы событий + Полнотекстовые списки стоп-слов + Пулы ресурсов + Аудит + Спецификации аудита сервера + Пространственные индексы + Группы рабочей нагрузки + Файлы SQL + Функции сервера + Тип SQL + Параметры сервера + Диаграммы базы данных + Системные таблицы + Базы данных + Системные контракты + Системные базы данных + Системные типы сообщений + Системные очереди + Системные службы + Системные хранимые процедуры + Системные представления + Приложения уровня данных + Расширенные хранимые процедуры + Агрегатные функции + Приблизительные числовые значения + Двоичные строки + Символьные строки + Типы данных CLR + Функции конфигурации + Функции работы с курсорами + Системные типы данных + Дата и время + Функции даты и времени + Точные числовые значения + Системные функции + Функции идентификаторов иерархии + Математические функции + Функции метаданных + Другие типы данных + Другие функции + Функции набора строк + Функции безопасности + Пространственные типы данных + Строковые функции + Системные статистические функции + Функции для работы с изображениями и текстом + Строки символов в Юникоде + Агрегатные функции + Скалярные функции + Функции с табличным значением + Системные расширенные хранимые процедуры + Встроенные типы + Встроенные роли сервера + Пользователь с паролем + Список свойств поиска + Политики безопасности + Предикаты безопасности + Роль сервера + Списки свойств поиска + Индексы хранилища столбцов + Индексы типов таблиц + Селективные XML-индексы + Пространства имен XML + Типизированные повышенные пути XML + Типизированные повышенные пути T-SQL + Учетные данные для базы данных + Внешние источники данных + Внешние форматы файлов + Внешние ресурсы + Внешние таблицы + Ключи Always Encrypted + Главные ключи столбца + Ключи шифрования столбца + Сервер + Ошибка при анализе свойства 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езультатов слишком много строк для безопасной загрузки + Параметризация + Не разрешается указывать этот параметр при восстановлении резервной копии с параметром NORECOVERY. + Недопустимый путь к файлу базы данных: {0}"""" + Журнал + Не удалось создать план восстановления + Восстановление базы данных не поддерживается + Восстановление базы данных + (Копировать только) + Тип копии + Тип + Сервер + База данных + Положение + Первый номер LSN + Последний номер LSN + Номер LSN для контрольной точки + Полный номер LSN + Дата начала + Дата завершения + Размер + Имя пользователя + Истечение срока + Имя + Последняя созданная резервная копия ({0}) + Создание резервной копии базы данных + Выполняется + Завершен + Скрипты + Соединение не найдено + Указанное имя файла является также именем каталога: {0} + Невозможно проверить существование расположения файла резервной копии: {0} + Указанный путь на сервере недоступен: {0} + Для восстановления не выбран резервный набор данных + Никогда + \ No newline at end of file diff --git a/src/Microsoft.SqlTools.CoreServices/Localization/sr.strings b/src/Microsoft.SqlTools.CoreServices/Localization/sr.strings new file mode 100644 index 00000000..71ca4655 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Localization/sr.strings @@ -0,0 +1,879 @@ +# String resource file +# +# When processed by the String Resource Tool, this file generates +# both a .CS and a .RESX file with the same name as the file. +# The .CS file contains a class which can be used to access these +# string resources, including the ability to format in +# parameters, which are identified with the .NET {x} format +# (see String.Format help). +# +# Comments below assume the file name is SR.strings. +# +# Lines starting with a semicolon ";" are also treated as comments, but +# in a future version they will be extracted and made available in LocStudio +# Put your comments to localizers _before_ the string they apply to. +# +# SMO build specific comment +# after generating the .resx file, run srgen on it and get the .resx file +# please remember to also check that .resx in, along with the +# .strings and .cs files + +[strings] + +############################################################################ +# Connection Service + +ConnectionServiceConnectErrorNullParams = Connection parameters cannot be null + +ConnectionServiceListDbErrorNullOwnerUri = OwnerUri cannot be null or empty + +ConnectionServiceListDbErrorNotConnected(string uri) = SpecifiedUri '{0}' does not have existing connection + +ConnectionServiceDbErrorDefaultNotConnected(string uri) = Specified URI '{0}' does not have a default connection + +ConnectionServiceConnStringInvalidAuthType(string authType) = Invalid value '{0}' for AuthenticationType. Valid values are 'Integrated' and 'SqlLogin'. + +ConnectionServiceConnStringInvalidIntent(string intent) = Invalid value '{0}' for ApplicationIntent. Valid values are 'ReadWrite' and 'ReadOnly'. + +ConnectionServiceConnectionCanceled = Connection canceled + +### Connection Params Validation Errors + +ConnectionParamsValidateNullOwnerUri = OwnerUri cannot be null or empty + +ConnectionParamsValidateNullConnection = Connection details object cannot be null + +ConnectionParamsValidateNullServerName = ServerName cannot be null or empty + +ConnectionParamsValidateNullSqlAuth(string component) = {0} cannot be null or empty when using SqlLogin authentication + +### General connection service strings +AzureSqlDbEdition = Azure SQL DB +AzureSqlDwEdition = Azure SQL Data Warehouse +AzureSqlStretchEdition = Azure SQL Stretch Database + +############################################################################ +# Query Execution Service + +### Cancel Request + +QueryServiceCancelAlreadyCompleted = The query has already completed, it cannot be cancelled + +QueryServiceCancelDisposeFailed = Query successfully cancelled, failed to dispose query. Owner URI not found. + +QueryServiceQueryCancelled = Query was canceled by user + +### Subset Request + +QueryServiceSubsetBatchNotCompleted = The batch has not completed, yet + +QueryServiceSubsetBatchOutOfRange = Batch index cannot be less than 0 or greater than the number of batches + +QueryServiceSubsetResultSetOutOfRange = Result set index cannot be less than 0 or greater than the number of result sets + +### Data Reader Exceptions + +QueryServiceDataReaderByteCountInvalid = Maximum number of bytes to return must be greater than zero + +QueryServiceDataReaderCharCountInvalid = Maximum number of chars to return must be greater than zero + +QueryServiceDataReaderXmlCountInvalid = Maximum number of XML bytes to return must be greater than zero + +### File Stream Wrapper Exceptions + +QueryServiceFileWrapperWriteOnly = Access method cannot be write-only + +QueryServiceFileWrapperNotInitialized = FileStreamWrapper must be initialized before performing operations + +QueryServiceFileWrapperReadOnly = This FileStreamWrapper cannot be used for writing + +### Query Request + +QueryServiceAffectedOneRow = (1 row affected) + +QueryServiceAffectedRows(long rows) = ({0} rows affected) + +QueryServiceCompletedSuccessfully = Commands completed successfully. + +QueryServiceErrorFormat(int msg, int lvl, int state, int line, string newLine, string message) = Msg {0}, Level {1}, State {2}, Line {3}{4}{5} + +QueryServiceQueryFailed(string message) = Query failed: {0} + +QueryServiceColumnNull = (No column name) + +QueryServiceCellNull = NULL + +QueryServiceRequestsNoQuery = The requested query does not exist + +QueryServiceQueryInvalidOwnerUri = This editor is not connected to a database + +QueryServiceQueryInProgress = A query is already in progress for this editor session. Please cancel this query or wait for its completion. + +QueryServiceMessageSenderNotSql = Sender for OnInfoMessage event must be a SqlConnection + +QueryServiceResultSetAddNoRows = Cannot add row to result buffer, data reader does not contain rows + +QueryServiceResultSetHasNoResults = Query has no results to return + +QueryServiceResultSetTooLarge = Result set has too many rows to be safely loaded + +### Save As Requests + +QueryServiceSaveAsResultSetNotComplete = Result cannot be saved until query execution has completed + +QueryServiceSaveAsMiscStartingError = Internal error occurred while starting save task + +QueryServiceSaveAsInProgress = A save request to the same path is in progress + +QueryServiceSaveAsFail(string fileName, string message) = Failed to save {0}: {1} + +### MISC + +QueryServiceResultSetNotRead = Cannot read subset unless the results have been read from the server + +QueryServiceResultSetStartRowOutOfRange = Start row cannot be less than 0 or greater than the number of rows in the result set + +QueryServiceResultSetRowCountOutOfRange = Row count must be a positive integer + +QueryServiceResultSetNoColumnSchema = Could not retrieve column schema for result set + +QueryServiceExecutionPlanNotFound = Could not retrieve an execution plan from the result set + +############################################################################ +# Language Service + +PeekDefinitionAzureError(string errorMessage) = This feature is currently not supported on Azure SQL DB and Data Warehouse: {0} + +PeekDefinitionError(string errorMessage) = An unexpected error occurred during Peek Definition execution: {0} + +PeekDefinitionNoResultsError = No results were found. + +PeekDefinitionDatabaseError = No database object was retrieved. + +PeekDefinitionNotConnectedError = Please connect to a server. + +PeekDefinitionTimedoutError = Operation timed out. + +PeekDefinitionTypeNotSupportedError = This object type is currently not supported by this feature. + +ErrorEmptyStringReplacement = Replacement of an empty string by an empty string. + +############################################################################ +# Workspace Service + +WorkspaceServicePositionLineOutOfRange = Position is outside of file line range + +WorkspaceServicePositionColumnOutOfRange(int line) = Position is outside of column range for line {0} + +WorkspaceServiceBufferPositionOutOfOrder(int sLine, int sCol, int eLine, int eCol) = Start position ({0}, {1}) must come before or be equal to the end position ({2}, {3}) + +############################################################################ +# Edit Data Service + +EditDataObjectNotFound = Table or view requested for edit could not be found + +EditDataSessionNotFound = Edit session does not exist. + +EditDataSessionAlreadyExists = Edit session already exists. + +EditDataSessionNotInitialized = Edit session has not been initialized + +EditDataSessionAlreadyInitialized = Edit session has already been initialized + +EditDataSessionAlreadyInitializing = Edit session has already been initialized or is in the process of initializing + +EditDataMetadataNotExtended = Table metadata does not have extended properties + +EditDataMetadataObjectNameRequired = A object name must be provided + +EditDataMetadataTooManyIdentifiers = Explicitly specifying server or database is not supported + +EditDataFilteringNegativeLimit = Result limit cannot be negative + +EditDataUnsupportedObjectType(string typeName) = Database object {0} cannot be used for editing. + +EditDataQueryFailed = Query execution failed, see messages for details + +EditDataQueryNotCompleted = Query has not completed execution + +EditDataQueryImproperResultSets = Query did not generate exactly one result set + +EditDataFailedAddRow = Failed to add new row to update cache + +EditDataRowOutOfRange = Given row ID is outside the range of rows in the edit cache + +EditDataUpdatePending = An update is already pending for this row and must be reverted first + +EditDataUpdateNotPending = Given row ID does not have pending update + +EditDataObjectMetadataNotFound = Table or view metadata could not be found + +EditDataInvalidFormat(string colName, string colType) = Invalid format for column '{0}', column is defined as {1} + +EditDataInvalidFormatBinary = Invalid format for binary column + +EditDataInvalidFormatBoolean = Allowed values for boolean columns are 0, 1, "true", or "false" + +EditDataCreateScriptMissingValue(string colName) = The column '{0}' is defined as NOT NULL but was not given a value + +EditDataDeleteSetCell = A delete is pending for this row, a cell update cannot be applied. + +EditDataColumnIdOutOfRange = Column ID must be in the range of columns for the query + +EditDataColumnCannotBeEdited = Column cannot be edited + +EditDataColumnNoKeyColumns = No key columns were found + +EditDataScriptFilePathNull = An output filename must be provided + +EditDataCommitInProgress = A commit task is in progress. Please wait for completion. + +EditDataComputedColumnPlaceholder = + +EditDataTimeOver24Hrs = TIME column values must be between 00:00:00.0000000 and 23:59:59.9999999 + +EditDataNullNotAllowed = NULL is not allowed for this column + +EditDataValueTooLarge(string value, string columnType) = Value {0} is too large to fit in column of type {1} + +############################################################################ +# DacFx Resources + +EE_BatchSqlMessageNoProcedureInfo = Msg {0}, Level {1}, State {2}, Line {3} + +EE_BatchSqlMessageWithProcedureInfo = Msg {0}, Level {1}, State {2}, Procedure {3}, Line {4} + +EE_BatchSqlMessageNoLineInfo = Msg {0}, Level {1}, State {2} + +EE_BatchError_Exception = An error occurred while the batch was being processed. The error message is: {0} + +EE_BatchExecutionInfo_RowsAffected = ({0} row(s) affected) + +EE_ExecutionNotYetCompleteError = The previous execution is not yet complete. + +EE_ScriptError_Error = A scripting error occurred. + +EE_ScriptError_ParsingSyntax = Incorrect syntax was encountered while {0} was being parsed. + +EE_ScriptError_FatalError = A fatal error occurred. + +EE_ExecutionInfo_FinalizingLoop = Batch execution completed {0} times... + +EE_ExecutionInfo_QueryCancelledbyUser = You cancelled the query. + +EE_BatchExecutionError_Halting = An error occurred while the batch was being executed. + +EE_BatchExecutionError_Ignoring = An error occurred while the batch was being executed, but the error has been ignored. + +EE_ExecutionInfo_InitializingLoop = Beginning execution loop + +EE_ExecutionError_CommandNotSupported = Command {0} is not supported. + +EE_ExecutionError_VariableNotFound = The variable {0} could not be found. + +BatchParserWrapperExecutionEngineError = SQL Execution error: {0} + +BatchParserWrapperExecutionError = Batch parser wrapper execution: {0} found... at line {1}: {2} Description: {3} + +BatchParserWrapperExecutionEngineBatchMessage = Batch parser wrapper execution engine batch message received: Message: {0} Detailed message: {1} + +BatchParserWrapperExecutionEngineBatchResultSetProcessing = Batch parser wrapper execution engine batch ResultSet processing: DataReader.FieldCount: {0} DataReader.RecordsAffected: {1} + +BatchParserWrapperExecutionEngineBatchResultSetFinished = Batch parser wrapper execution engine batch ResultSet finished. + +BatchParserWrapperExecutionEngineBatchCancelling = Canceling batch parser wrapper batch execution. + +EE_ScriptError_Warning = Scripting warning. + +TroubleshootingAssistanceMessage = For more information about this error, see the troubleshooting topics in the product documentation. + +BatchParser_CircularReference = File '{0}' recursively included. + +BatchParser_CommentNotTerminated = Missing end comment mark '*/'. + +BatchParser_StringNotTerminated = Unclosed quotation mark after the character string. + +BatchParser_IncorrectSyntax = Incorrect syntax was encountered while parsing '{0}'. + +BatchParser_VariableNotDefined = Variable {0} is not defined. + +############################################################################ +# Workspace Service + +TestLocalizationConstant = test + +############################################################################ +# Utilities + +SqlScriptFormatterDecimalMissingPrecision = Exact numeric column is missing numeric precision or numeric scale + +SqlScriptFormatterLengthTypeMissingSize = Column with length is missing size + +SqlScriptFormatterScalarTypeMissingScale = Scalar column missing scale + +############################################################################ +# Object Explorer Service + +TreeNodeError = Error expanding: {0} + +ServerNodeConnectionError = Error connecting to {0} + +SchemaHierarchy_Aggregates = Aggregates + +SchemaHierarchy_ServerRoles = Server Roles + +SchemaHierarchy_ApplicationRoles = Application Roles + +SchemaHierarchy_Assemblies = Assemblies + +SchemaHierarchy_AssemblyFiles = Assembly Files + +SchemaHierarchy_AsymmetricKeys = Asymmetric Keys + +SchemaHierarchy_DatabaseAsymmetricKeys = Asymmetric Keys + +SchemaHierarchy_DataCompressionOptions = Data Compression Options + +SchemaHierarchy_Certificates = Certificates + +SchemaHierarchy_FileTables = FileTables + +SchemaHierarchy_DatabaseCertificates = Certificates + +SchemaHierarchy_CheckConstraints = Check Constraints + +SchemaHierarchy_Columns = Columns + +SchemaHierarchy_Constraints = Constraints + +SchemaHierarchy_Contracts = Contracts + +SchemaHierarchy_Credentials = Credentials + +SchemaHierarchy_ErrorMessages = Error Messages + +SchemaHierarchy_ServerRoleMembership = Server Role Membership + +SchemaHierarchy_DatabaseOptions = Database Options + +SchemaHierarchy_DatabaseRoles = Database Roles + +SchemaHierarchy_RoleMemberships = Role Memberships + +SchemaHierarchy_DatabaseTriggers = Database Triggers + +SchemaHierarchy_DefaultConstraints = Default Constraints + +SchemaHierarchy_Defaults = Defaults + +SchemaHierarchy_Sequences = Sequences + +SchemaHierarchy_Endpoints = Endpoints + +SchemaHierarchy_EventNotifications = Event Notifications + +SchemaHierarchy_ServerEventNotifications = Server Event Notifications + +SchemaHierarchy_ExtendedProperties = Extended Properties + +SchemaHierarchy_FileGroups = Filegroups + +SchemaHierarchy_ForeignKeys = Foreign Keys + +SchemaHierarchy_FullTextCatalogs = Full-Text Catalogs + +SchemaHierarchy_FullTextIndexes = Full-Text Indexes + +SchemaHierarchy_Functions = Functions + +SchemaHierarchy_Indexes = Indexes + +SchemaHierarchy_InlineFunctions = Inline Functions + +SchemaHierarchy_Keys = Keys + +SchemaHierarchy_LinkedServers = Linked Servers + +SchemaHierarchy_LinkedServerLogins = Linked Server Logins + +SchemaHierarchy_Logins = Logins + +SchemaHierarchy_MasterKey = Master Key + +SchemaHierarchy_MasterKeys = Master Keys + +SchemaHierarchy_MessageTypes = Message Types + +SchemaHierarchy_MultiSelectFunctions = Table-Valued Functions + +SchemaHierarchy_Parameters = Parameters + +SchemaHierarchy_PartitionFunctions = Partition Functions + +SchemaHierarchy_PartitionSchemes = Partition Schemes + +SchemaHierarchy_Permissions = Permissions + +SchemaHierarchy_PrimaryKeys = Primary Keys + +SchemaHierarchy_Programmability = Programmability + +SchemaHierarchy_Queues = Queues + +SchemaHierarchy_RemoteServiceBindings = Remote Service Bindings + +SchemaHierarchy_ReturnedColumns = Returned Columns + +SchemaHierarchy_Roles = Roles + +SchemaHierarchy_Routes = Routes + +SchemaHierarchy_Rules = Rules + +SchemaHierarchy_Schemas = Schemas + +SchemaHierarchy_Security = Security + +SchemaHierarchy_ServerObjects = Server Objects + +SchemaHierarchy_Management = Management + +SchemaHierarchy_ServerTriggers = Triggers + +SchemaHierarchy_ServiceBroker = Service Broker + +SchemaHierarchy_Services = Services + +SchemaHierarchy_Signatures = Signatures + +SchemaHierarchy_LogFiles = Log Files + +SchemaHierarchy_Statistics = Statistics + +SchemaHierarchy_Storage = Storage + +SchemaHierarchy_StoredProcedures = Stored Procedures + +SchemaHierarchy_SymmetricKeys = Symmetric Keys + +SchemaHierarchy_Synonyms = Synonyms + +SchemaHierarchy_Tables = Tables + +SchemaHierarchy_Triggers = Triggers + +SchemaHierarchy_Types = Types + +SchemaHierarchy_UniqueKeys = Unique Keys + +SchemaHierarchy_UserDefinedDataTypes = User-Defined Data Types + +SchemaHierarchy_UserDefinedTypes = User-Defined Types (CLR) + +SchemaHierarchy_Users = Users + +SchemaHierarchy_Views = Views + +SchemaHierarchy_XmlIndexes = XML Indexes + +SchemaHierarchy_XMLSchemaCollections = XML Schema Collections + +SchemaHierarchy_UserDefinedTableTypes = User-Defined Table Types + +SchemaHierarchy_FilegroupFiles = Files + +MissingCaption = Missing Caption + +SchemaHierarchy_BrokerPriorities = Broker Priorities + +SchemaHierarchy_CryptographicProviders = Cryptographic Providers + +SchemaHierarchy_DatabaseAuditSpecifications = Database Audit Specifications + +SchemaHierarchy_DatabaseEncryptionKeys = Database Encryption Keys + +SchemaHierarchy_EventSessions = Event Sessions + +SchemaHierarchy_FullTextStopLists = Full Text Stoplists + +SchemaHierarchy_ResourcePools = Resource Pools + +SchemaHierarchy_ServerAudits = Audits + +SchemaHierarchy_ServerAuditSpecifications = Server Audit Specifications + +SchemaHierarchy_SpatialIndexes = Spatial Indexes + +SchemaHierarchy_WorkloadGroups = Workload Groups + +SchemaHierarchy_SqlFiles = SQL Files + +SchemaHierarchy_ServerFunctions = Server Functions + +SchemaHierarchy_SqlType = SQL Type + +SchemaHierarchy_ServerOptions = Server Options + +SchemaHierarchy_DatabaseDiagrams = Database Diagrams + +SchemaHierarchy_SystemTables = System Tables + +SchemaHierarchy_Databases = Databases + +SchemaHierarchy_SystemContracts = System Contracts + +SchemaHierarchy_SystemDatabases = System Databases + +SchemaHierarchy_SystemMessageTypes = System Message Types + +SchemaHierarchy_SystemQueues = System Queues + +SchemaHierarchy_SystemServices = System Services + +SchemaHierarchy_SystemStoredProcedures = System Stored Procedures + +SchemaHierarchy_SystemViews = System Views + +SchemaHierarchy_DataTierApplications = Data-tier Applications + +SchemaHierarchy_ExtendedStoredProcedures = Extended Stored Procedures + +SchemaHierarchy_SystemAggregateFunctions = Aggregate Functions + +SchemaHierarchy_SystemApproximateNumerics = Approximate Numerics + +SchemaHierarchy_SystemBinaryStrings = Binary Strings + +SchemaHierarchy_SystemCharacterStrings = Character Strings + +SchemaHierarchy_SystemCLRDataTypes = CLR Data Types + +SchemaHierarchy_SystemConfigurationFunctions = Configuration Functions + +SchemaHierarchy_SystemCursorFunctions = Cursor Functions + +SchemaHierarchy_SystemDataTypes = System Data Types + +SchemaHierarchy_SystemDateAndTime = Date and Time + +SchemaHierarchy_SystemDateAndTimeFunctions = Date and Time Functions + +SchemaHierarchy_SystemExactNumerics = Exact Numerics + +SchemaHierarchy_SystemFunctions = System Functions + +SchemaHierarchy_SystemHierarchyIdFunctions = Hierarchy Id Functions + +SchemaHierarchy_SystemMathematicalFunctions = Mathematical Functions + +SchemaHierarchy_SystemMetadataFunctions = Metadata Functions + +SchemaHierarchy_SystemOtherDataTypes = Other Data Types + +SchemaHierarchy_SystemOtherFunctions = Other Functions + +SchemaHierarchy_SystemRowsetFunctions = Rowset Functions + +SchemaHierarchy_SystemSecurityFunctions = Security Functions + +SchemaHierarchy_SystemSpatialDataTypes = Spatial Data Types + +SchemaHierarchy_SystemStringFunctions = String Functions + +SchemaHierarchy_SystemSystemStatisticalFunctions = System Statistical Functions + +SchemaHierarchy_SystemTextAndImageFunctions = Text and Image Functions + +SchemaHierarchy_SystemUnicodeCharacterStrings = Unicode Character Strings + +SchemaHierarchy_AggregateFunctions = Aggregate Functions + +SchemaHierarchy_ScalarValuedFunctions = Scalar-valued Functions + +SchemaHierarchy_TableValuedFunctions = Table-valued Functions + +SchemaHierarchy_SystemExtendedStoredProcedures = System Extended Stored Procedures + +SchemaHierarchy_BuiltInType = Built-in Types + +SchemaHierarchy_BuiltInServerRole = Built-in Server Roles + +SchemaHierarchy_UserWithPassword = User with Password + +SchemaHierarchy_SearchPropertyList = Search Property List + +SchemaHierarchy_SecurityPolicies = Security Policies + +SchemaHierarchy_SecurityPredicates = Security Predicates + +SchemaHierarchy_ServerRole = Server Role + +SchemaHierarchy_SearchPropertyLists = Search Property Lists + +SchemaHierarchy_ColumnStoreIndexes = Column Store Indexes + +SchemaHierarchy_TableTypeIndexes = Table Type Indexes + +SchemaHierarchy_Server = Server + +SchemaHierarchy_SelectiveXmlIndexes = Selective XML Indexes + +SchemaHierarchy_XmlNamespaces = XML Namespaces + +SchemaHierarchy_XmlTypedPromotedPaths = XML Typed Promoted Paths + +SchemaHierarchy_SqlTypedPromotedPaths = T-SQL Typed Promoted Paths + +SchemaHierarchy_DatabaseScopedCredentials = Database Scoped Credentials + +SchemaHierarchy_ExternalDataSources = External Data Sources + +SchemaHierarchy_ExternalFileFormats = External File Formats + +SchemaHierarchy_ExternalResources = External Resources + +SchemaHierarchy_ExternalTables = External Tables + +SchemaHierarchy_AlwaysEncryptedKeys = Always Encrypted Keys + +SchemaHierarchy_ColumnMasterKeys = Column Master Keys + +SchemaHierarchy_ColumnEncryptionKeys = Column Encryption Keys + +SchemaHierarchy_SubroutineParameterLabelFormatString = {0} ({1}, {2}, {3}) + +SchemaHierarchy_SubroutineParameterNoDefaultLabel = No default + +SchemaHierarchy_SubroutineParameterInputLabel = Input + +SchemaHierarchy_SubroutineParameterInputOutputLabel = Input/Output + +SchemaHierarchy_SubroutineParameterInputReadOnlyLabel = Input/ReadOnly + +SchemaHierarchy_SubroutineParameterInputOutputReadOnlyLabel = Input/Output/ReadOnly + +SchemaHierarchy_SubroutineParameterDefaultLabel = Default + +SchemaHierarchy_NullColumn_Label = null + +SchemaHierarchy_NotNullColumn_Label = not null + +SchemaHierarchy_UDDTLabelWithType = {0} ({1}, {2}) + +SchemaHierarchy_UDDTLabelWithoutType = {0} ({1}) + +SchemaHierarchy_ComputedColumnLabelWithType = {0} ({1}Computed, {2}, {3}) + +SchemaHierarchy_ComputedColumnLabelWithoutType = {0} ({1}Computed) + +SchemaHierarchy_ColumnSetLabelWithoutType = {0} (Column Set, {1}) + +SchemaHierarchy_ColumnSetLabelWithType = {0} (Column Set, {1}{2}, {3}) + +SchemaHierarchy_ColumnSetLabelWithTypeAndKeyString = {0} (Column Set, {1}, {2}, {3}) + +UniqueIndex_LabelPart = Unique + +NonUniqueIndex_LabelPart = Non-Unique + +ClusteredIndex_LabelPart = Clustered + +NonClusteredIndex_LabelPart = Non-Clustered + +History_LabelPart = History + +SystemVersioned_LabelPart = System-Versioned + +External_LabelPart = External + +FileTable_LabelPart = File Table + +DatabaseNotAccessible = The database {0} is not accessible. + + +############################################################################ +# Scripting Service + +ScriptingParams_ConnectionString_Property_Invalid = Error parsing ScriptingParams.ConnectionString property. + +ScriptingParams_FilePath_Property_Invalid = Invalid directory specified by the ScriptingParams.FilePath property. + +ScriptingListObjectsCompleteParams_ConnectionString_Property_Invalid = Error parsing ScriptingListObjectsCompleteParams.ConnectionString property. + + +StoredProcedureScriptParameterComment = -- TODO: Set parameter values here. + +ScriptingGeneralError = An error occurred while scripting the objects. +ScriptingExecuteNotSupportedError = Scripting as Execute is only supported for Stored Procedures + +############################################################################ +# Admin Service + +unavailable = Unavailable +filegroup_dialog_defaultFilegroup = Current default filegroup: {0} +filegroup_dialog_title = New Filegroup for {0} +filegroups_default = Default +filegroups_files = Files +filegroups_name = Name +filegroups_readonly = Read-Only +general_autogrowth = Autogrowth / Maxsize +general_builderText = ... +general_default = <default> +general_fileGroup = Filegroup +general_fileName = Logical Name +general_fileType = File Type +general_initialSize = Initial Size (MB) +general_newFilegroup = <new filegroup> +general_path = Path +general_physicalFileName = File Name +general_rawDevice = <raw device> +general_recoveryModel_bulkLogged = Bulk-logged +general_recoveryModel_full = Full +general_recoveryModel_simple = Simple +general_titleSearchOwner = Select Database Owner + +prototype_autogrowth_disabled = None +prototype_autogrowth_restrictedGrowthByMB = By {0} MB, Limited to {1} MB +prototype_autogrowth_restrictedGrowthByPercent = By {0} percent, Limited to {1} MB +prototype_autogrowth_unrestrictedGrowthByMB = By {0} MB, Unlimited +prototype_autogrowth_unrestrictedGrowthByPercent = By {0} percent, Unlimited +prototype_autogrowth_unlimitedfilestream = Unlimited +prototype_autogrowth_limitedfilestream = Limited to {0} MB +prototype_db_category_automatic = Automatic +prototype_db_category_servicebroker = Service Broker +prototype_db_category_collation = Collation +prototype_db_category_cursor = Cursor +prototype_db_category_misc = Miscellaneous +prototype_db_category_recovery = Recovery +prototype_db_category_state = State +prototype_db_prop_ansiNullDefault = ANSI NULL Default +prototype_db_prop_ansiNulls = ANSI NULLS Enabled +prototype_db_prop_ansiPadding = ANSI Padding Enabled +prototype_db_prop_ansiWarnings = ANSI Warnings Enabled +prototype_db_prop_arithabort = Arithmetic Abort Enabled +prototype_db_prop_autoClose = Auto Close +prototype_db_prop_autoCreateStatistics = Auto Create Statistics +prototype_db_prop_autoShrink = Auto Shrink +prototype_db_prop_autoUpdateStatistics = Auto Update Statistics +prototype_db_prop_autoUpdateStatisticsAsync = Auto Update Statistics Asynchronously +prototype_db_prop_caseSensitive = Case Sensitive +prototype_db_prop_closeCursorOnCommit = Close Cursor on Commit Enabled +prototype_db_prop_collation = Collation +prototype_db_prop_concatNullYieldsNull = Concatenate Null Yields Null +prototype_db_prop_databaseCompatibilityLevel = Database Compatibility Level +prototype_db_prop_databaseState = Database State +prototype_db_prop_defaultCursor = Default Cursor +prototype_db_prop_fullTextIndexing = Full-Text Indexing Enabled +prototype_db_prop_numericRoundAbort = Numeric Round-Abort +prototype_db_prop_pageVerify = Page Verify +prototype_db_prop_quotedIdentifier = Quoted Identifiers Enabled +prototype_db_prop_readOnly = Database Read-Only +prototype_db_prop_recursiveTriggers = Recursive Triggers Enabled +prototype_db_prop_restrictAccess = Restrict Access +prototype_db_prop_selectIntoBulkCopy = Select Into/Bulk Copy +prototype_db_prop_honorBrokerPriority = Honor Broker Priority +prototype_db_prop_serviceBrokerGuid = Service Broker Identifier +prototype_db_prop_brokerEnabled = Broker Enabled +prototype_db_prop_truncateLogOnCheckpoint = Truncate Log on Checkpoint +prototype_db_prop_dbChaining = Cross-database Ownership Chaining Enabled +prototype_db_prop_trustworthy = Trustworthy +prototype_db_prop_dateCorrelationOptimization = Date Correlation Optimization Enabled +prototype_db_prop_parameterization = Parameterization +prototype_db_prop_parameterization_value_forced = Forced +prototype_db_prop_parameterization_value_simple = Simple +prototype_file_dataFile = ROWS Data +prototype_file_logFile = LOG +prototype_file_filestreamFile = FILESTREAM Data +prototype_file_noFileGroup = Not Applicable +prototype_file_defaultpathstring = <default path> +title_openConnectionsMustBeClosed = Open Connections +warning_openConnectionsMustBeClosed=To change the database properties, SQL Server must close all other connections to the database_ Are you sure you want to change the properties and close all other connections? +prototype_db_prop_databaseState_value_autoClosed = AUTO_CLOSED +prototype_db_prop_databaseState_value_emergency = EMERGENCY +prototype_db_prop_databaseState_value_inaccessible = INACCESSIBLE +prototype_db_prop_databaseState_value_normal = NORMAL +prototype_db_prop_databaseState_value_offline = OFFLINE +prototype_db_prop_databaseState_value_recovering = RECOVERING +prototype_db_prop_databaseState_value_recoveryPending = RECOVERY PENDING +prototype_db_prop_databaseState_value_restoring = RESTORING +prototype_db_prop_databaseState_value_shutdown=SHUTDOWN +prototype_db_prop_databaseState_value_standby = STANDBY +prototype_db_prop_databaseState_value_suspect = SUSPECT +prototype_db_prop_defaultCursor_value_global = GLOBAL +prototype_db_prop_defaultCursor_value_local = LOCAL +prototype_db_prop_restrictAccess_value_multiple = MULTI_USER +prototype_db_prop_restrictAccess_value_restricted = RESTRICTED_USER +prototype_db_prop_restrictAccess_value_single = SINGLE_USER +prototype_db_prop_pageVerify_value_checksum = CHECKSUM +prototype_db_prop_pageVerify_value_none = NONE +prototype_db_prop_pageVerify_value_tornPageDetection = TORN_PAGE_DETECTION +prototype_db_prop_varDecimalEnabled = VarDecimal Storage Format Enabled +compatibilityLevel_katmai = SQL Server 2008 (100) +prototype_db_prop_encryptionEnabled = Encryption Enabled +prototype_db_prop_databasescopedconfig_value_off = OFF +prototype_db_prop_databasescopedconfig_value_on = ON +prototype_db_prop_databasescopedconfig_value_primary = PRIMARY +error_db_prop_invalidleadingColumns = For the distribution policy HASH, the number of leading hash columns is optional but should be from 1 to 16 columns +compatibilityLevel_denali = SQL Server 2012 (110) +compatibilityLevel_sql14 = SQL Server 2014 (120) +compatibilityLevel_sql15 = SQL Server 2016 (130) +compatibilityLevel_sqlvNext = SQL Server vNext (140) +general_containmentType_None = None +general_containmentType_Partial = Partial +filegroups_filestreamFiles = FILESTREAM Files +prototype_file_noApplicableFileGroup = No Applicable Filegroup +NeverBackedUp = Never +Error_InvalidDirectoryName = Path {0} is not a valid directory +Error_ExistingDirectoryName = For directory {0} a file with name {1} already exists + +############################################################################ +# Backup Service +BackupTaskName = Backup Database + +# Backup File Validation Errors +BackupPathIsFolderError = Please provide a file path instead of directory path +InvalidBackupPathError = The provided path is invalid + +############################################################################ +# Task Service +TaskInProgress = In progress +TaskCompleted = Completed + +########################################################################### +# Restore +ConflictWithNoRecovery = Specifying this option when restoring a backup with the NORECOVERY option is not permitted. +InvalidPathForDatabaseFile = Invalid path for database file: '{0}' +Log = Log +RestorePlanFailed = Failed to create restore plan +RestoreNotSupported = Restore database is not supported +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 +TheLastBackupTaken = The last backup taken ({0}) +NoBackupsetsToRestore = No backupset selected to be restored + +############################################################################ +# Generate Script +ScriptTaskName = scripting + +############################################################################ +# File Browser Validation Errors +InvalidPathError = Cannot access the specified path on the server: {0} + +############################################################################ +# Profiler +ProfilerConnectionNotFound = Connection not found diff --git a/src/Microsoft.SqlTools.CoreServices/Localization/sr.xlf b/src/Microsoft.SqlTools.CoreServices/Localization/sr.xlf new file mode 100644 index 00000000..4aff52ab --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Localization/sr.xlf @@ -0,0 +1,2358 @@ + + + + + + Connection parameters cannot be null + Connection parameters cannot be null + + + + OwnerUri cannot be null or empty + OwnerUri cannot be null or empty + + + + SpecifiedUri '{0}' does not have existing connection + SpecifiedUri '{0}' does not have existing connection + . + Parameters: 0 - uri (string) + + + Invalid value '{0}' for AuthenticationType. Valid values are 'Integrated' and 'SqlLogin'. + Invalid value '{0}' for AuthenticationType. Valid values are 'Integrated' and 'SqlLogin'. + . + Parameters: 0 - authType (string) + + + Invalid value '{0}' for ApplicationIntent. Valid values are 'ReadWrite' and 'ReadOnly'. + Invalid value '{0}' for ApplicationIntent. Valid values are 'ReadWrite' and 'ReadOnly'. + . + Parameters: 0 - intent (string) + + + Connection canceled + Connection canceled + + + + OwnerUri cannot be null or empty + OwnerUri cannot be null or empty + + + + Connection details object cannot be null + Connection details object cannot be null + + + + ServerName cannot be null or empty + ServerName cannot be null or empty + + + + {0} cannot be null or empty when using SqlLogin authentication + {0} cannot be null or empty when using SqlLogin authentication + . + Parameters: 0 - component (string) + + + The query has already completed, it cannot be cancelled + The query has already completed, it cannot be cancelled + + + + Query successfully cancelled, failed to dispose query. Owner URI not found. + Query successfully cancelled, failed to dispose query. Owner URI not found. + + + + Query was canceled by user + Query was canceled by user + + + + The batch has not completed, yet + The batch has not completed, yet + + + + Batch index cannot be less than 0 or greater than the number of batches + Batch index cannot be less than 0 or greater than the number of batches + + + + Result set index cannot be less than 0 or greater than the number of result sets + Result set index cannot be less than 0 or greater than the number of result sets + + + + Maximum number of bytes to return must be greater than zero + Maximum number of bytes to return must be greater than zero + + + + Maximum number of chars to return must be greater than zero + Maximum number of chars to return must be greater than zero + + + + Maximum number of XML bytes to return must be greater than zero + Maximum number of XML bytes to return must be greater than zero + + + + Access method cannot be write-only + Access method cannot be write-only + + + + FileStreamWrapper must be initialized before performing operations + FileStreamWrapper must be initialized before performing operations + + + + This FileStreamWrapper cannot be used for writing + This FileStreamWrapper cannot be used for writing + + + + (1 row affected) + (1 row affected) + + + + ({0} rows affected) + ({0} rows affected) + . + Parameters: 0 - rows (long) + + + Commands completed successfully. + Commands completed successfully. + + + + Msg {0}, Level {1}, State {2}, Line {3}{4}{5} + Msg {0}, Level {1}, State {2}, Line {3}{4}{5} + . + Parameters: 0 - msg (int), 1 - lvl (int), 2 - state (int), 3 - line (int), 4 - newLine (string), 5 - message (string) + + + Query failed: {0} + Query failed: {0} + . + Parameters: 0 - message (string) + + + (No column name) + (No column name) + + + + The requested query does not exist + The requested query does not exist + + + + This editor is not connected to a database + This editor is not connected to a database + + + + A query is already in progress for this editor session. Please cancel this query or wait for its completion. + A query is already in progress for this editor session. Please cancel this query or wait for its completion. + + + + Sender for OnInfoMessage event must be a SqlConnection + Sender for OnInfoMessage event must be a SqlConnection + + + + Result cannot be saved until query execution has completed + Result cannot be saved until query execution has completed + + + + Internal error occurred while starting save task + Internal error occurred while starting save task + + + + A save request to the same path is in progress + A save request to the same path is in progress + + + + Failed to save {0}: {1} + Failed to save {0}: {1} + . + Parameters: 0 - fileName (string), 1 - message (string) + + + Cannot read subset unless the results have been read from the server + Cannot read subset unless the results have been read from the server + + + + Start row cannot be less than 0 or greater than the number of rows in the result set + Start row cannot be less than 0 or greater than the number of rows in the result set + + + + Row count must be a positive integer + Row count must be a positive integer + + + + Could not retrieve column schema for result set + Could not retrieve column schema for result set + + + + Could not retrieve an execution plan from the result set + Could not retrieve an execution plan from the result set + + + + This feature is currently not supported on Azure SQL DB and Data Warehouse: {0} + This feature is currently not supported on Azure SQL DB and Data Warehouse: {0} + . + Parameters: 0 - errorMessage (string) + + + An unexpected error occurred during Peek Definition execution: {0} + An unexpected error occurred during Peek Definition execution: {0} + . + Parameters: 0 - errorMessage (string) + + + No results were found. + No results were found. + + + + No database object was retrieved. + No database object was retrieved. + + + + Please connect to a server. + Please connect to a server. + + + + Operation timed out. + Operation timed out. + + + + This object type is currently not supported by this feature. + This object type is currently not supported by this feature. + + + + Position is outside of file line range + Position is outside of file line range + + + + Position is outside of column range for line {0} + Position is outside of column range for line {0} + . + Parameters: 0 - line (int) + + + Start position ({0}, {1}) must come before or be equal to the end position ({2}, {3}) + Start position ({0}, {1}) must come before or be equal to the end position ({2}, {3}) + . + Parameters: 0 - sLine (int), 1 - sCol (int), 2 - eLine (int), 3 - eCol (int) + + + Msg {0}, Level {1}, State {2}, Line {3} + Msg {0}, Level {1}, State {2}, Line {3} + + + + Msg {0}, Level {1}, State {2}, Procedure {3}, Line {4} + Msg {0}, Level {1}, State {2}, Procedure {3}, Line {4} + + + + Msg {0}, Level {1}, State {2} + Msg {0}, Level {1}, State {2} + + + + An error occurred while the batch was being processed. The error message is: {0} + An error occurred while the batch was being processed. The error message is: {0} + + + + ({0} row(s) affected) + ({0} row(s) affected) + + + + The previous execution is not yet complete. + The previous execution is not yet complete. + + + + A scripting error occurred. + A scripting error occurred. + + + + Incorrect syntax was encountered while {0} was being parsed. + Incorrect syntax was encountered while {0} was being parsed. + + + + A fatal error occurred. + A fatal error occurred. + + + + Batch execution completed {0} times... + Batch execution completed {0} times... + + + + You cancelled the query. + You cancelled the query. + + + + An error occurred while the batch was being executed. + An error occurred while the batch was being executed. + + + + An error occurred while the batch was being executed, but the error has been ignored. + An error occurred while the batch was being executed, but the error has been ignored. + + + + Beginning execution loop + Beginning execution loop + + + + Command {0} is not supported. + Command {0} is not supported. + + + + The variable {0} could not be found. + The variable {0} could not be found. + + + + SQL Execution error: {0} + SQL Execution error: {0} + + + + Batch parser wrapper execution: {0} found... at line {1}: {2} Description: {3} + Batch parser wrapper execution: {0} found... at line {1}: {2} Description: {3} + + + + Batch parser wrapper execution engine batch message received: Message: {0} Detailed message: {1} + Batch parser wrapper execution engine batch message received: Message: {0} Detailed message: {1} + + + + Batch parser wrapper execution engine batch ResultSet processing: DataReader.FieldCount: {0} DataReader.RecordsAffected: {1} + Batch parser wrapper execution engine batch ResultSet processing: DataReader.FieldCount: {0} DataReader.RecordsAffected: {1} + + + + Batch parser wrapper execution engine batch ResultSet finished. + Batch parser wrapper execution engine batch ResultSet finished. + + + + Canceling batch parser wrapper batch execution. + Canceling batch parser wrapper batch execution. + + + + Scripting warning. + Scripting warning. + + + + For more information about this error, see the troubleshooting topics in the product documentation. + For more information about this error, see the troubleshooting topics in the product documentation. + + + + File '{0}' recursively included. + File '{0}' recursively included. + + + + Missing end comment mark '*/'. + Missing end comment mark '*/'. + + + + Unclosed quotation mark after the character string. + Unclosed quotation mark after the character string. + + + + Incorrect syntax was encountered while parsing '{0}'. + Incorrect syntax was encountered while parsing '{0}'. + + + + Variable {0} is not defined. + Variable {0} is not defined. + + + + test + test + + + + Replacement of an empty string by an empty string. + Replacement of an empty string by an empty string. + + + + Edit session does not exist. + Edit session does not exist. + + + + Query has not completed execution + Query has not completed execution + + + + Query did not generate exactly one result set + Query did not generate exactly one result set + + + + Failed to add new row to update cache + Failed to add new row to update cache + + + + Given row ID is outside the range of rows in the edit cache + Given row ID is outside the range of rows in the edit cache + + + + An update is already pending for this row and must be reverted first + An update is already pending for this row and must be reverted first + + + + Given row ID does not have pending update + Given row ID does not have pending update + + + + Table or view metadata could not be found + Table or view metadata could not be found + + + + Invalid format for binary column + Invalid format for binary column + + + + Allowed values for boolean columns are 0, 1, "true", or "false" + Allowed values for boolean columns are 0, 1, "true", or "false" + + + + The column '{0}' is defined as NOT NULL but was not given a value + The column '{0}' is defined as NOT NULL but was not given a value + . + Parameters: 0 - colName (string) + + + A delete is pending for this row, a cell update cannot be applied. + A delete is pending for this row, a cell update cannot be applied. + + + + Column ID must be in the range of columns for the query + Column ID must be in the range of columns for the query + + + + Column cannot be edited + Column cannot be edited + + + + No key columns were found + No key columns were found + + + + An output filename must be provided + An output filename must be provided + + + + Database object {0} cannot be used for editing. + Database object {0} cannot be used for editing. + . + Parameters: 0 - typeName (string) + + + Specified URI '{0}' does not have a default connection + Specified URI '{0}' does not have a default connection + . + Parameters: 0 - uri (string) + + + A commit task is in progress. Please wait for completion. + A commit task is in progress. Please wait for completion. + + + + Exact numeric column is missing numeric precision or numeric scale + Exact numeric column is missing numeric precision or numeric scale + + + + <TBD> + <TBD> + + + + Cannot add row to result buffer, data reader does not contain rows + Cannot add row to result buffer, data reader does not contain rows + + + + TIME column values must be between 00:00:00.0000000 and 23:59:59.9999999 + TIME column values must be between 00:00:00.0000000 and 23:59:59.9999999 + + + + NULL is not allowed for this column + NULL is not allowed for this column + + + + Edit session already exists. + Edit session already exists. + + + + Edit session has not been initialized + Edit session has not been initialized + + + + Edit session has already been initialized + Edit session has already been initialized + + + + Edit session has already been initialized or is in the process of initializing + Edit session has already been initialized or is in the process of initializing + + + + Query execution failed, see messages for details + Query execution failed, see messages for details + + + + Result limit cannot be negative + Result limit cannot be negative + + + + NULL + NULL + + + + A object name must be provided + A object name must be provided + + + + Explicitly specifying server or database is not supported + Explicitly specifying server or database is not supported + + + + Table metadata does not have extended properties + Table metadata does not have extended properties + + + + Table or view requested for edit could not be found + Table or view requested for edit could not be found + + + + Error expanding: {0} + Error expanding: {0} + + + + Error connecting to {0} + Error connecting to {0} + + + + Aggregates + Aggregates + + + + Server Roles + Server Roles + + + + Application Roles + Application Roles + + + + Assemblies + Assemblies + + + + Assembly Files + Assembly Files + + + + Asymmetric Keys + Asymmetric Keys + + + + Asymmetric Keys + Asymmetric Keys + + + + Data Compression Options + Data Compression Options + + + + Certificates + Certificates + + + + FileTables + FileTables + + + + Certificates + Certificates + + + + Check Constraints + Check Constraints + + + + Columns + Columns + + + + Constraints + Constraints + + + + Contracts + Contracts + + + + Credentials + Credentials + + + + Error Messages + Error Messages + + + + Server Role Membership + Server Role Membership + + + + Database Options + Database Options + + + + Database Roles + Database Roles + + + + Role Memberships + Role Memberships + + + + Database Triggers + Database Triggers + + + + Default Constraints + Default Constraints + + + + Defaults + Defaults + + + + Sequences + Sequences + + + + Endpoints + Endpoints + + + + Event Notifications + Event Notifications + + + + Server Event Notifications + Server Event Notifications + + + + Extended Properties + Extended Properties + + + + Filegroups + Filegroups + + + + Foreign Keys + Foreign Keys + + + + Full-Text Catalogs + Full-Text Catalogs + + + + Full-Text Indexes + Full-Text Indexes + + + + Functions + Functions + + + + Indexes + Indexes + + + + Inline Functions + Inline Functions + + + + Keys + Keys + + + + Linked Servers + Linked Servers + + + + Linked Server Logins + Linked Server Logins + + + + Logins + Logins + + + + Master Key + Master Key + + + + Master Keys + Master Keys + + + + Message Types + Message Types + + + + Table-Valued Functions + Table-Valued Functions + + + + Parameters + Parameters + + + + Partition Functions + Partition Functions + + + + Partition Schemes + Partition Schemes + + + + Permissions + Permissions + + + + Primary Keys + Primary Keys + + + + Programmability + Programmability + + + + Queues + Queues + + + + Remote Service Bindings + Remote Service Bindings + + + + Returned Columns + Returned Columns + + + + Roles + Roles + + + + Routes + Routes + + + + Rules + Rules + + + + Schemas + Schemas + + + + Security + Security + + + + Server Objects + Server Objects + + + + Management + Management + + + + Triggers + Triggers + + + + Service Broker + Service Broker + + + + Services + Services + + + + Signatures + Signatures + + + + Log Files + Log Files + + + + Statistics + Statistics + + + + Storage + Storage + + + + Stored Procedures + Stored Procedures + + + + Symmetric Keys + Symmetric Keys + + + + Synonyms + Synonyms + + + + Tables + Tables + + + + Triggers + Triggers + + + + Types + Types + + + + Unique Keys + Unique Keys + + + + User-Defined Data Types + User-Defined Data Types + + + + User-Defined Types (CLR) + User-Defined Types (CLR) + + + + Users + Users + + + + Views + Views + + + + XML Indexes + XML Indexes + + + + XML Schema Collections + XML Schema Collections + + + + User-Defined Table Types + User-Defined Table Types + + + + Files + Files + + + + Missing Caption + Missing Caption + + + + Broker Priorities + Broker Priorities + + + + Cryptographic Providers + Cryptographic Providers + + + + Database Audit Specifications + Database Audit Specifications + + + + Database Encryption Keys + Database Encryption Keys + + + + Event Sessions + Event Sessions + + + + Full Text Stoplists + Full Text Stoplists + + + + Resource Pools + Resource Pools + + + + Audits + Audits + + + + Server Audit Specifications + Server Audit Specifications + + + + Spatial Indexes + Spatial Indexes + + + + Workload Groups + Workload Groups + + + + SQL Files + SQL Files + + + + Server Functions + Server Functions + + + + SQL Type + SQL Type + + + + Server Options + Server Options + + + + Database Diagrams + Database Diagrams + + + + System Tables + System Tables + + + + Databases + Databases + + + + System Contracts + System Contracts + + + + System Databases + System Databases + + + + System Message Types + System Message Types + + + + System Queues + System Queues + + + + System Services + System Services + + + + System Stored Procedures + System Stored Procedures + + + + System Views + System Views + + + + Data-tier Applications + Data-tier Applications + + + + Extended Stored Procedures + Extended Stored Procedures + + + + Aggregate Functions + Aggregate Functions + + + + Approximate Numerics + Approximate Numerics + + + + Binary Strings + Binary Strings + + + + Character Strings + Character Strings + + + + CLR Data Types + CLR Data Types + + + + Configuration Functions + Configuration Functions + + + + Cursor Functions + Cursor Functions + + + + System Data Types + System Data Types + + + + Date and Time + Date and Time + + + + Date and Time Functions + Date and Time Functions + + + + Exact Numerics + Exact Numerics + + + + System Functions + System Functions + + + + Hierarchy Id Functions + Hierarchy Id Functions + + + + Mathematical Functions + Mathematical Functions + + + + Metadata Functions + Metadata Functions + + + + Other Data Types + Other Data Types + + + + Other Functions + Other Functions + + + + Rowset Functions + Rowset Functions + + + + Security Functions + Security Functions + + + + Spatial Data Types + Spatial Data Types + + + + String Functions + String Functions + + + + System Statistical Functions + System Statistical Functions + + + + Text and Image Functions + Text and Image Functions + + + + Unicode Character Strings + Unicode Character Strings + + + + Aggregate Functions + Aggregate Functions + + + + Scalar-valued Functions + Scalar-valued Functions + + + + Table-valued Functions + Table-valued Functions + + + + System Extended Stored Procedures + System Extended Stored Procedures + + + + Built-in Types + Built-in Types + + + + Built-in Server Roles + Built-in Server Roles + + + + User with Password + User with Password + + + + Search Property List + Search Property List + + + + Security Policies + Security Policies + + + + Security Predicates + Security Predicates + + + + Server Role + Server Role + + + + Search Property Lists + Search Property Lists + + + + Column Store Indexes + Column Store Indexes + + + + Table Type Indexes + Table Type Indexes + + + + Selective XML Indexes + Selective XML Indexes + + + + XML Namespaces + XML Namespaces + + + + XML Typed Promoted Paths + XML Typed Promoted Paths + + + + T-SQL Typed Promoted Paths + T-SQL Typed Promoted Paths + + + + Database Scoped Credentials + Database Scoped Credentials + + + + External Data Sources + External Data Sources + + + + External File Formats + External File Formats + + + + External Resources + External Resources + + + + External Tables + External Tables + + + + Always Encrypted Keys + Always Encrypted Keys + + + + Column Master Keys + Column Master Keys + + + + Column Encryption Keys + Column Encryption Keys + + + + Server + Server + + + + Error parsing ScriptingParams.ConnectionString property. + Error parsing ScriptingParams.ConnectionString property. + + + + Invalid directory specified by the ScriptingParams.FilePath property. + Invalid directory specified by the ScriptingParams.FilePath property. + + + + Error parsing ScriptingListObjectsCompleteParams.ConnectionString property. + Error parsing ScriptingListObjectsCompleteParams.ConnectionString property. + + + + {0} ({1}, {2}, {3}) + {0} ({1}, {2}, {3}) + + + + No default + No default + + + + Input + Input + + + + Input/Output + Input/Output + + + + Input/ReadOnly + Input/ReadOnly + + + + Input/Output/ReadOnly + Input/Output/ReadOnly + + + + Default + Default + + + + null + null + + + + not null + not null + + + + {0} ({1}, {2}) + {0} ({1}, {2}) + + + + {0} ({1}) + {0} ({1}) + + + + {0} ({1}Computed, {2}, {3}) + {0} ({1}Computed, {2}, {3}) + + + + {0} ({1}Computed) + {0} ({1}Computed) + + + + {0} (Column Set, {1}) + {0} (Column Set, {1}) + + + + {0} (Column Set, {1}{2}, {3}) + {0} (Column Set, {1}{2}, {3}) + + + + {0} (Column Set, {1}, {2}, {3}) + {0} (Column Set, {1}, {2}, {3}) + + + + Unique + Unique + + + + Non-Unique + Non-Unique + + + + Clustered + Clustered + + + + Non-Clustered + Non-Clustered + + + + History + History + + + + System-Versioned + System-Versioned + + + + Unavailable + Unavailable + + + + Current default filegroup: {0} + Current default filegroup: {0} + + + + New Filegroup for {0} + New Filegroup for {0} + + + + Default + Default + + + + Files + Files + + + + Name + Name + + + + Read-Only + Read-Only + + + + Autogrowth / Maxsize + Autogrowth / Maxsize + + + + ... + ... + + + + <default> + <default> + + + + Filegroup + Filegroup + + + + Logical Name + Logical Name + + + + File Type + File Type + + + + Initial Size (MB) + Initial Size (MB) + + + + <new filegroup> + <new filegroup> + + + + Path + Path + + + + File Name + File Name + + + + <raw device> + <raw device> + + + + Bulk-logged + Bulk-logged + + + + Full + Full + + + + Simple + Simple + + + + Select Database Owner + Select Database Owner + + + + None + None + + + + By {0} MB, Limited to {1} MB + By {0} MB, Limited to {1} MB + + + + By {0} percent, Limited to {1} MB + By {0} percent, Limited to {1} MB + + + + By {0} MB, Unlimited + By {0} MB, Unlimited + + + + By {0} percent, Unlimited + By {0} percent, Unlimited + + + + Unlimited + Unlimited + + + + Limited to {0} MB + Limited to {0} MB + + + + Automatic + Automatic + + + + Service Broker + Service Broker + + + + Collation + Collation + + + + Cursor + Cursor + + + + Miscellaneous + Miscellaneous + + + + Recovery + Recovery + + + + State + State + + + + ANSI NULL Default + ANSI NULL Default + + + + ANSI NULLS Enabled + ANSI NULLS Enabled + + + + ANSI Padding Enabled + ANSI Padding Enabled + + + + ANSI Warnings Enabled + ANSI Warnings Enabled + + + + Arithmetic Abort Enabled + Arithmetic Abort Enabled + + + + Auto Close + Auto Close + + + + Auto Create Statistics + Auto Create Statistics + + + + Auto Shrink + Auto Shrink + + + + Auto Update Statistics + Auto Update Statistics + + + + Auto Update Statistics Asynchronously + Auto Update Statistics Asynchronously + + + + Case Sensitive + Case Sensitive + + + + Close Cursor on Commit Enabled + Close Cursor on Commit Enabled + + + + Collation + Collation + + + + Concatenate Null Yields Null + Concatenate Null Yields Null + + + + Database Compatibility Level + Database Compatibility Level + + + + Database State + Database State + + + + Default Cursor + Default Cursor + + + + Full-Text Indexing Enabled + Full-Text Indexing Enabled + + + + Numeric Round-Abort + Numeric Round-Abort + + + + Page Verify + Page Verify + + + + Quoted Identifiers Enabled + Quoted Identifiers Enabled + + + + Database Read-Only + Database Read-Only + + + + Recursive Triggers Enabled + Recursive Triggers Enabled + + + + Restrict Access + Restrict Access + + + + Select Into/Bulk Copy + Select Into/Bulk Copy + + + + Honor Broker Priority + Honor Broker Priority + + + + Service Broker Identifier + Service Broker Identifier + + + + Broker Enabled + Broker Enabled + + + + Truncate Log on Checkpoint + Truncate Log on Checkpoint + + + + Cross-database Ownership Chaining Enabled + Cross-database Ownership Chaining Enabled + + + + Trustworthy + Trustworthy + + + + Date Correlation Optimization Enabled + Date Correlation Optimization Enabled + + + + Forced + Forced + + + + Simple + Simple + + + + ROWS Data + ROWS Data + + + + LOG + LOG + + + + FILESTREAM Data + FILESTREAM Data + + + + Not Applicable + Not Applicable + + + + <default path> + <default path> + + + + Open Connections + Open Connections + + + + To change the database properties, SQL Server must close all other connections to the database_ Are you sure you want to change the properties and close all other connections? + To change the database properties, SQL Server must close all other connections to the database_ Are you sure you want to change the properties and close all other connections? + + + + AUTO_CLOSED + AUTO_CLOSED + + + + EMERGENCY + EMERGENCY + + + + INACCESSIBLE + INACCESSIBLE + + + + NORMAL + NORMAL + + + + OFFLINE + OFFLINE + + + + RECOVERING + RECOVERING + + + + RECOVERY PENDING + RECOVERY PENDING + + + + RESTORING + RESTORING + + + + SHUTDOWN + SHUTDOWN + + + + STANDBY + STANDBY + + + + SUSPECT + SUSPECT + + + + GLOBAL + GLOBAL + + + + LOCAL + LOCAL + + + + MULTI_USER + MULTI_USER + + + + RESTRICTED_USER + RESTRICTED_USER + + + + SINGLE_USER + SINGLE_USER + + + + CHECKSUM + CHECKSUM + + + + NONE + NONE + + + + TORN_PAGE_DETECTION + TORN_PAGE_DETECTION + + + + VarDecimal Storage Format Enabled + VarDecimal Storage Format Enabled + + + + SQL Server 2008 (100) + SQL Server 2008 (100) + + + + Encryption Enabled + Encryption Enabled + + + + OFF + OFF + + + + ON + ON + + + + PRIMARY + PRIMARY + + + + For the distribution policy HASH, the number of leading hash columns is optional but should be from 1 to 16 columns + For the distribution policy HASH, the number of leading hash columns is optional but should be from 1 to 16 columns + + + + SQL Server 2012 (110) + SQL Server 2012 (110) + + + + SQL Server 2014 (120) + SQL Server 2014 (120) + + + + SQL Server 2016 (130) + SQL Server 2016 (130) + + + + SQL Server vNext (140) + SQL Server vNext (140) + + + + None + None + + + + Partial + Partial + + + + FILESTREAM Files + FILESTREAM Files + + + + No Applicable Filegroup + No Applicable Filegroup + + + + The database {0} is not accessible. + The database {0} is not accessible. + + + + Query has no results to return + Query has no results to return + + + + Result set has too many rows to be safely loaded + Result set has too many rows to be safely loaded + + + Parameterization + Parameterization + + + + Specifying this option when restoring a backup with the NORECOVERY option is not permitted. + Specifying this option when restoring a backup with the NORECOVERY option is not permitted. + + + + Invalid path for database file: '{0}' + Invalid path for database file: '{0}' + + + + Log + Log + + + + Failed to create restore plan + Failed to create restore plan + + + + Restore database is not supported + Restore database is not supported + + + + Restore Database + 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 + + + + The last backup taken ({0}) + The last backup taken ({0}) + + + + Backup Database + Backup Database + + + + In progress + In progress + + + + Completed + Completed + + + + scripting + scripting + + + + Connection not found + Connection not found + + + + Please provide a file path instead of directory path + Please provide a file path instead of directory path + + + + The provided path is invalid + The provided path is invalid + + + + Cannot access the specified path on the server: {0} + Cannot access the specified path on the server: {0} + + + + No backupset selected to be restored + No backupset selected to be restored + + + + Never + Never + + + + Azure SQL DB + Azure SQL DB + + + + Azure SQL Data Warehouse + Azure SQL Data Warehouse + + + + Azure SQL Stretch Database + Azure SQL Stretch Database + + + + Path {0} is not a valid directory + Path {0} is not a valid directory + + + + For directory {0} a file with name {1} already exists + For directory {0} a file with name {1} already exists + + + + Value {0} is too large to fit in column of type {1} + Value {0} is too large to fit in column of type {1} + . + Parameters: 0 - value (string), 1 - columnType (string) + + + Invalid format for column '{0}', column is defined as {1} + Invalid format for column '{0}', column is defined as {1} + . + Parameters: 0 - colName (string), 1 - colType (string) + + + Column with length is missing size + Column with length is missing size + + + + Scalar column missing scale + Scalar column missing scale + + + + -- TODO: Set parameter values here. + -- TODO: Set parameter values here. + + + + An error occurred while scripting the objects. + An error occurred while scripting the objects. + + + + Scripting as Execute is only supported for Stored Procedures + Scripting as Execute is only supported for Stored Procedures + + + + External + External + + + + File Table + File Table + + + + + \ No newline at end of file diff --git a/src/Microsoft.SqlTools.CoreServices/Localization/sr.zh-hans.resx b/src/Microsoft.SqlTools.CoreServices/Localization/sr.zh-hans.resx new file mode 100644 index 00000000..e1dd659e --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Localization/sr.zh-hans.resx @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +text/microsoft-resx1.3System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089连接参数不能为 null + OwnerUri 不能为 null 或为空 + SpecifiedUri '{0}' 没有已有的连接 + AuthenticationType 值"{0}" 无效。 有效值为 'Integrated' 和 'SqlLogin'。 + '{0}' 为无效的ApplicationIntent值。 有效值为 'ReadWrite' 和 'ReadOnly'。 + 连接已取消 + OwnerUri 不能为 null 或为空 + 连接详细信息的对象不能为 null + ServerName 不能是 null 或是空白 + 使用 SqlLogin 身份验证时,{0} 不可是 null 或是空 + 查询已完成,无法取消 + 查询成功取消,无法处理查询。找不到 URI 的所有者。 + 查询已被用户取消 + 该批处理尚未完成 + 批量索引不能小于 0 或大于批量的总数 + 结果集索引不能小于 0 或大于结果集的总数 + 返回的最大字节数必须大于零 + 返回的最大字符数必须大于零 + 返回的 XML 最大字节数必须大于零 + 访问方法不能设置为”只写“ + 在执行操作之前,必须初始化 FileStreamWrapper + 该 FileStreamWrapper 不能用于写入 + (1 行受到影响) + (影响 {0} 行) + 命令已成功完成。 + Msg {0},级别 {1},状态 {2},第 {3} {4} {5} 行 + 查询失败︰ {0} + (没有列名称) + 请求的查询不存在。 + 此编辑器未连接到数据库 + 此编辑器会话已有正在进行中的查询。请取消这项查询,或等待它完成 + OnInfoMessage 事件的发送者必须是 SqlConnection + 查询完成前,不能保存结果 + 保存任务时发生内部错误 + 相同路径的保存请求正在进行中 + 未能保存 {0}: {1} + 没有从服务器读取结果之前,无法读取子数据集 + 起始行不能小于 0 或大于结果集中的行数 + 行数必须是一个正整数 + 未能从结果集获取列架构 + 未能从结果集获取执行计划 + 这功能目前不支持 Azure SQL DB 和数据仓库︰ {0} + 查看定义的执行过程中出现意外的错误︰ {0} + 未找到结果。 + 检索不到任何数据库对象。 + 请连接到服务器。 + 操作超时。 + 此功能当前不支持此对象类型。 + 位置超出文件行范围 + 第 {0} 行位置超出数据列范围 + 起始位置 ({0},{1}) 必须先于或等于结束位置 ({2},{3}) + Msg {0},级别 {1} ,状态 {2},第 {3} 行 + Msg {0},级别 {1},状态 {2},过程 {3},第 {4} 行 + Msg {0},级别 {1},状态 {2} + 执行批处理时发生错误。错误消息︰ {0} + ({0} 行受到影响) + 前一次执行尚未完成。 + 出现脚本错误。 + 正在分析 {0} 时发现语法错误。 + 出现严重错误。 + 已执行完 {0} 次... + 您已取消查询。 + 执行批次处理时发生错误。 + 执行批次处理时发生错误,但该错误已被忽略。 + Beginning execution loop + 不支持命令 {0}。 + 找不到变量 {0}。 + SQL 执行错误︰ {0} + 批处理解析封装器执行︰{0} 找到位于第 {1} 行: {2} 描述︰{3} + 批处理解析封装器执行引擎所收到的消息︰ 消息︰ {0},详细的消息︰ {1} + 批处理解析封装器执行引擎批次结果集处理︰ DataReader.FieldCount: {0} DataReader.RecordsAffected: {1} + 批处理解析封装器执行引擎批次处理结果集已完成。 + 正在取消批处理解析封装器的批处理执行。 + 脚本警告。 + 有关此错误的详细信息,请参阅产品文档中的疑难解答主题。 + 文件 '{0}' 被递归方式包含。 + 缺少结束注释标记 '*/'。 + 未闭合的引号后的字符字串。 + '{0}' 在分析时发现语法错误。 + 未定义变量 {0}。 + 测试 + 用空字符串取代空字符串。 + 编辑会话不存在 + 查询尚未完成 + 查询并非产生单一结果集 + 无法添加新数据行以更新缓存,操作失败 + 给定数据行 ID 已超出 edit cache 中数据行的范围 + 这个数据行已经有一个更新正在等待使用,因此它必须先恢复原状。 + 给定行 ID 没有正在等待的更新操作 + 找不到表格或视图的元数据 + 二进制列格示错误 + Boolean 列必须填入数字 1 或 0, 或字符串 true 或 false + 必填单元格的值缺失 + 这行即将被删除,其中的单元格无法被更新 + 列 ID 必须在数据列总数內才可被查询 + 列无法被编辑 + 找不到键列 + 必须提供输出文件名 + 数据库对象 {0} 无法被编辑 + 指定的 URI '{0}' 没有默认的连接 + 提交的任务正在进行,请等待它完成 + 十进制列缺少数值精度或小数位数 + <TBD> + 无法在结果缓冲区添加行,数据读取器不包含任何行 + TIME 列的取值范围必须在 00:00:00.0000000 至 23:59:59.9999999 之间 + 该列不允许Null 值 + 编辑会话已存在 + 编辑会话尚未初始化 + 编辑会话已被初始化 + 编辑会话已被初始化或正在初始化中 + 执行查询失败,查看消息了解更多详情 + 结果集的限制值不能为负数 + + 必须提供对象名称 + 不支持显式指定服务器或者数据库 + 数据表的元数据没有扩展属性 + 找不到请求编辑的数据表或视图 + 扩展数据库时出错: {0} + 连接到 {0} 时出错 + 聚合 + 服务器角色 + 应用程序角色 + 程序集 + 程序集文件 + 非对称密钥 + 非对称密钥 + 数据压缩选项 + 证书 + 文件表 + 证书 + CHECK 约束 + + 约束 + 协定 + 凭据 + 错误消息 + 服务器角色成员资格 + 数据库选项 + 数据库角色 + 角色成员资格 + 数据库触发器 + 默认约束 + 默认值 + 序列 + 终结点 + 事件通知 + 服务器事件通知 + 扩展属性 + 文件组 + 外键 + 全文目录 + 全文检索 + 函数 + 索引 + 内联函数 + + 链接的服务器 + 链接的服务器登录名 + 登录名 + 主密钥 + 主密钥 + 消息类型 + 表值函数 + 参数 + 分区函数 + 分区方案 + 权限 + 主键 + 可编程性 + 队列 + 远程服务绑定 + 返回列 + 角色 + 路由 + 规则 + 架构 + 安全性 + 服务器对象 + 管理 + 触发器 + Service Broker + 服务 + 签名 + 日志文件 + 统计信息 + 存储 + 存储过程 + 对称密钥 + 同义词 + + 触发器 + 类型 + 唯一键 + 用户定义的数据类型 + 用户定义的类型(CLR) + 用户 + 视图 + XML 索引 + XML 架构集合 + 用户定义的表类型 + 文件 + 缺少标题 + Broker 优先级 + 加密提供程序 + 数据库审核规范 + 数据库加密密钥 + 事件会话 + 全文非索引字表 + 资源池 + 审核 + 服务器审核规范 + 空间索引 + 工作负荷组 + SQL 文件 + 服务器函数 + SQL 类型 + 服务器选项 + 数据库关系图 + 系统表 + 数据库 + 系统约定 + 系统数据库 + 系统消息类型 + 系统队列 + 系统服务 + 系统存储过程 + 系统视图 + 数据层应用程序 + 扩展存储过程 + 聚合函数 + 近似数字 + 二进制字符串 + 字符串 + CLR 数据类型 + 配置函数 + 游标函数 + 系统数据类型 + 日期和时间 + 日期和时间函数 + 精确数字 + 系统函数 + 层次结构 ID 函数 + 数学函数 + 元数据函数 + 其他数据类型 + 其他函数 + 行集函数 + 安全函数 + 空间数据类型 + 字符串函数 + 系统统计函数 + 文本和图像函数 + Unicode 字符串 + 聚合函数 + 标量值函数 + 表值函数 + 系统扩展存储过程 + 内置类型 + 内置服务器角色 + 具有密码的用户 + 搜索属性列表 + 安全策略 + 安全谓词 + 服务器角色 + 搜索属性列表 + 列存储索引 + 表类型索引 + 选择性 XML 索引 + XML 命名空间 + XML 特型提升路径 + T-SQL 特型提升路径 + 数据库范围的凭据 + 外部数据源 + 外部文件格式 + 外部资源 + 外部表 + Always Encrypted 密钥 + 列主密钥 + 列加密密钥 + 服务器 + 解析属性 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} 无法访问。 + 无查询结果 + 资料行因结果集太长而可能无法加载 + 参数化 + 当使用 NORECOVERY 选项还原备份时,不允许指定此选项。 + 数据库文件的路径无效:“{0}” + 日志 + 制订还原计划失败 + 不支持还原数据库 + 还原数据库 + (仅复制) + 组件 + 类型 + 服务器 + 数据库 + 位置 + 第一个 LSN + 最后一个 LSN + 检查点 LSN + 完整 LSN + 开始日期 + 完成日期 + 大小 + 用户名 + 过期 + 名称 + 上次执行的备份({0}) + 备份数据库 + 正在进行 + 已完成 + 开始执行脚本操作 + 找不到连接 + 所指定的文件名同时也是一个文件目录名: {0} + 无法验证备份文件的位置是否存在: {0} + 无法访问服务器上的指定路径: {0} + 未选择用于还原的备份集 + 从不 + Azure SQL 数据库 + Azure SQL 数据仓库 + Azure SQL Stretch Database + 路径 {0} 不是有效的目录 + {0} 文件夹中已存在名为 {1} 的文件 + 值 {0} 太大,无法放入类型为 {1} 的列 + \ No newline at end of file diff --git a/src/Microsoft.SqlTools.CoreServices/Localization/sr.zh-hant.resx b/src/Microsoft.SqlTools.CoreServices/Localization/sr.zh-hant.resx new file mode 100644 index 00000000..13755923 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Localization/sr.zh-hant.resx @@ -0,0 +1,491 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +text/microsoft-resx1.3System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089連接參數不可為 null + OwnerUri 不能為 null 或空白 + SpecifiedUri '{0}' 沒有現有的連線 + AuthenticationType 值 "{0}" 無效。 有效值為 'Integrated' 和 'SqlLogin'。 + '{0}' 為無效的ApplicationIntent值。 有效值為 'ReadWrite' 和 'ReadOnly'。 + 已取消連線 + OwnerUri 不能是 null 或空白 + 連線詳細資料物件不能是 null + ServerName 不能是 null 或空白 + 使用 SqlLogin 驗證時,{0} 不可為 null 或是空白 + 查詢已完成,無法取消 + 成功地取消查詢,無法處置查詢。找不到擁有者 URI 。 + 使用者已取消查詢 + 批次尚未完成 + 批次索引不能小於 0 或大於批次的總數 + 結果集的索引不能小於 0 或大於結果集的總數 + 傳回的最大位元組數目必須大於零 + 傳回的最大字元數目必須大於零 + 傳回的最大 XML 位元組數目必須大於零 + 存取方法不可以設為唯寫 + 執行前,必須先初始化 FileStreamWrapper + 這個 FileStreamWrapper 不能用於寫入 + (1 列受影響) + ({0} 個資料列受到影響) + 命令已順利完成。 + 訊息 {0},層級 {1} ,狀態 {2},第 {3} {4} {5} 行 + 查詢失敗︰ {0} + (沒有資料行名稱) + 所要求的查詢不存在 + 這個編輯器尚未連接到資料庫 + 一個查詢已在這個編輯器工作階段。請取消這項查詢,或等待其完成。 + OnInfoMessage 事件的寄件者必須是一個 SqlConnection。 + 完成查詢執行前無法儲存結果 + 在儲存工作啟動時,發生內部錯誤 + 相同路徑的儲存要求正在進行中 + 無法儲存 {0}: {1} + 從伺服器讀取結果前,無法讀取子集 + 開始資料列不能小於 0 或大於結果集中的資料列總數 + 資料列計數必須是正整數 + 無法從結果集擷取資料行結構描述 + 無法從結果集擷取執行計劃 + 這項功能目前不支援 Azure SQL 資料庫和資料倉儲︰ {0} + 查看定義執行過程中發生未預期的錯誤︰ {0} + 找不到任何結果。 + 沒有資料庫物件被擷取。 + 請連線到伺服器。 + 作業逾時。 + 此功能目前不支援這種物件類型。 + 位置超出檔案行範圍 + 第 {0} 行位置超出資料行範圍 + 開始位置 ({0},{1}) 必須先於或等於結束位置 ({2},{3}) + 訊息 {0},層級 {1} ,狀態 {2},第 {3} 行 + 訊息 {0} ,層級 {1}, 狀態 {2}, 程序 {3},第 {4} 行 + 訊息 {0},層級 {1} ,狀態 {2} + 處理批次時,發生錯誤。錯誤訊息是︰ {0} + ({0} 個資料列受到影響) + 前一個執行尚未完成。 + 發生指令碼的錯誤。 + 正在剖析 {0} 時遇到不正確的語法。 + 發生嚴重的錯誤。 + 已執行完成 {0} 次... + 您已取消查詢。 + 執行此批次時發生錯誤。 + 執行此批次時發生錯誤,但錯誤以忽略。 + Beginning execution loop + 不支援命令 {0}。 + 找不到變數 {0}。 + SQL 執行錯誤︰ {0} + 批次剖析器包裝函式執行︰位於第 {1} 行: {2} 描述︰{3} 找到 {0} + 批次剖析器包裝函式執行引擎批次所收到的訊息︰ 訊息︰ {0},詳細的訊息︰ {1} + 批次剖析器包裝函式執行引擎批次結果集處理︰ DataReader.FieldCount: {0} DataReader.RecordsAffected: {1} + 批次剖析器包裝函式執行引擎批次結果集已完成。 + 正在取消批次剖析器包裝函式的批次執行。 + 指令碼警告。 + 有關此錯誤的詳細資訊,請參閱產品文件中的疑難排解主題。 + 檔案 '{0}' 具有遞迴。 + 遺漏結束的註解記號 ' * /'。 + 字元字串後有未封閉的雙引號 + 正在剖析 {0} 時遇到不正確的語法。 + 未定義變數 {0}。 + 測試 + 用空白字串取代空白字串。 + 編輯工作階段不存在 + 查詢尚未完成 + 查詢並非產生單一結果集 + 在 cashe 裡更新資料列失敗 + 提供的資料列識別碼已超出 edit cashe 中資料列的範圍 + 這個資料列已經有一個更新正在等待使用,因此它必須先恢復原狀。 + 這個資料列識別碼並沒有正在等待更新 + 找不到資料表或檢視表中繼資料 + 二進位資料欄格示錯誤 + Boolean 欄位必須填入數字 1 或 0, 或字串 true 或 false + 必填儲存格未填 + 這個資料列即將被刪除,其中的儲存格無法被更新 + 資料行識別碼必須在資料行總數內才可被查詢 + 資料行無法被編輯 + 找不到索引鍵資料行 + 必須提供輸出檔名 + 資料庫物件 {0} 無法被編輯 + 指定的 URI '{0}' 沒有預設的連線 + 認可的工作正在進行,請等待它完成 + 十進位資料行缺少數值有效位數或小數位數 + <TBD> + 無法在結果緩衝區加資料列,資料讀取器不包含資料列 + TIME 欄的值範圍必須在 00:00:00.0000000 至 23:59:59.9999999 之間 + 這欄不允許填入 NULL 值 + 編輯工作階段已存在 + 編輯工作階段尚未初始化 + 編輯工作階段已初始化 + 編輯工作階段已完成初始化或正在初始化 + 查詢執行失敗, 請查看詳細資訊 + 結果限制不能為負 + NULL + 必須提供物件名稱 + 不支援明確指定的伺服器或資料庫 + 資料表中繼資料無擴充屬性 + 找不到要編輯的資料表或檢視表 + 擴充資料庫時發生錯誤:{0} + 連接到 {0} 時發生錯誤 + 彙總 + 伺服器角色 + 應用程式角色 + 組件 + 組件檔 + 非對稱金鑰 + 非對稱金鑰 + 資料壓縮選項 + 憑證 + FileTable + 憑證 + 檢查條件約束 + 資料行 + 條件約束 + 合約 + 認證 + 錯誤訊息 + 伺服器角色成員資格 + 資料庫選項 + 資料庫角色 + 角色成員資格 + 資料庫觸發程序 + 預設條件約束 + 預設 + 序列 + 端點 + 事件告知 + 伺服器事件通知 + 擴充屬性 + 檔案群組 + 外部索引鍵 + 全文檢索目錄 + 全文檢索索引 + 函式 + 索引 + 內嵌函式 + 索引鍵 + 連結的伺服器 + 連結的伺服器登入 + 登入 + 主要金鑰 + 主要金鑰 + 訊息類型 + 資料表值函式 + 參數 + 資料分割函式 + 資料分割配置 + 權限 + 主索引鍵 + 可程式性 + 佇列 + 遠端服務繫結 + 傳回的資料行 + 角色 + 路由 + 規則 + 結構描述 + 安全性 + 伺服器物件 + 管理 + 觸發程序 + Service Broker + 服務 + 簽章 + 記錄檔 + 統計資料 + 儲存體 + 預存程序 + 對稱金鑰 + 同義資料表 + 資料表 + 觸發程序 + 型別 + 唯一索引鍵 + 使用者定義資料類型 + 使用者定義型別 (CLR) + 使用者 + 檢視 + XML 索引 + XML 結構描述集合 + 使用者定義資料表類型 + 檔案 + 遺漏標題 + Broker 優先權 + 密碼編譯提供者 + 資料庫稽核規格 + 資料庫加密金鑰 + 事件工作階段 + 全文檢索停用字詞表 + 資源集區 + 稽核 + 伺服器稽核規格 + 空間索引 + 工作負載群組 + SQL 檔案 + 伺服器函式 + SQL 類型 + 伺服器選項 + 資料庫圖表 + 系統資料表 + 資料庫 + 系統合約 + 系統資料庫 + 系統訊息類型 + 系統佇列 + 系統服務 + 系統預存程序 + 系統檢視表 + 資料層應用程式 + 擴充預存程序 + 彙總函式 + 近似數值 + 二進位字串 + 字元字串 + CLR 資料型別 + 組態函式 + 資料指標函式 + 系統資料型別 + 日期和時間 + 日期和時間函式 + 精確數值 + 系統函式 + 階層識別碼函式 + 數學函式 + 中繼資料函式 + 其他資料型別 + 其他函式 + 資料列集函式 + 安全性函式 + 空間資料型別 + 字串函式 + 系統統計函式 + 文字和影像函式 + Unicode 字元字串 + 彙總函式 + 純量值函式 + 資料表值函式 + 系統擴充預存程序 + 內建型別 + 內建伺服器角色 + 有密碼的使用者 + 搜尋屬性清單 + 安全性原則 + 安全性述詞 + 伺服器角色 + 搜尋屬性清單 + 資料行儲存索引 + 資料表類型索引 + 選擇性 XML 索引 + XML 命名空間 + XML 具類型的升級路徑 + T-SQL 具類型的升級路徑 + 資料庫範圍認證 + 外部資料來源 + 外部檔案格式 + 外部資源 + 外部資料表 + Always Encrypted 金鑰 + 資料行主要金鑰 + 資料行加密金鑰 + 伺服器 + 剖析屬性 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}。 + 沒有查詢結果可以回傳 + 資料列因結果集太長而無法載入 + 參數化 + 不允許使用 NORECOVERY 選項還原備份時,請指定這個選項。 + 資料庫檔案的路徑無效: '{0}' + 記錄檔 + 無法建立還原計畫 + 不支援還原資料庫 + 還原資料庫 + (僅複製) + 元件 + 型別 + 伺服器 + 資料庫 + 位置 + 第一個 LSN + 最後一個 LSN + 檢查點 LSN + 完整 LSN + 開始日期 + 完成日期 + 大小 + 使用者名稱 + 逾期 + 名稱 + 上次建立的備份 ({0}) + 備份資料庫 + 進行中 + 已完成 + 指令碼 + 找不到連接 + 指定的檔案名稱也是目錄名稱: {0} + 無法確認備份檔案位置的存在: {0} + 無法存取伺服器上指定的路徑: {0} + 無選擇的備份集可還原 + 永不 + Azure SQL DB + Azure SQL 資料倉儲 + Azure SQL 延展資料庫 + 路徑 {0} 不是有效的目錄 + 因目錄 {0} 中已有存在的檔案名稱 {1} + 數值 {0} 太大以致於無法符合欄位型態 {1} + \ No newline at end of file diff --git a/src/Microsoft.SqlTools.CoreServices/Localization/transXliff/sr.de.xlf b/src/Microsoft.SqlTools.CoreServices/Localization/transXliff/sr.de.xlf new file mode 100644 index 00000000..9f563c61 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Localization/transXliff/sr.de.xlf @@ -0,0 +1,2776 @@ + + + + + Connection parameters cannot be null + Verbindungsparameter dürfen nicht null sein. + + + + + OwnerUri cannot be null or empty + OwnerUri darf nicht null oder leer sein. + + + + + SpecifiedUri '{0}' does not have existing connection + SpecifiedUri '{0}' hat keine gültige Verbindung + + . + Parameters: 0 - uri (string) + + + Invalid value '{0}' for AuthenticationType. Valid values are 'Integrated' and 'SqlLogin'. + Ungültiger Wert '{0}' für AuthenticationType. Gültige Werte sind 'Integrated' und 'SqlLogin'. + + . + Parameters: 0 - authType (string) + + + Invalid value '{0}' for ApplicationIntent. Valid values are 'ReadWrite' and 'ReadOnly'. + Ungültiger Wert '{0}' für ApplicationIntent. Gültige Werte sind 'ReadWrite' und 'ReadOnly'. + + . + Parameters: 0 - intent (string) + + + Connection canceled + Verbindung wurde abgebrochen. + + + + + OwnerUri cannot be null or empty + OwnerUri darf nicht null oder leer sein. + + + + + Connection details object cannot be null + Verbindungsdetails-Objekt darf nicht null sein. + + + + + ServerName cannot be null or empty + ServerName darf nicht null oder leer sein. + + + + + {0} cannot be null or empty when using SqlLogin authentication + {0} darf bei Verwendung der SqlLogin-Authentifizierung nicht null oder leer sein + + . + Parameters: 0 - component (string) + + + The query has already completed, it cannot be cancelled + Die Abfrage wurde bereits abgeschlossen und kann nicht abgebrochen werden + + + + + Query successfully cancelled, failed to dispose query. Owner URI not found. + Abfrage wurde erfolgreich abgebrochen, Fehler beim Abfrage verfügen. Benutzer-URI nicht gefunden. + + + + + Query was canceled by user + Die Abfrage wurde vom Benutzer abgebrochen. + + + + + The batch has not completed, yet + Die Stapelverarbeitung ist noch nicht abgeschlossen + + + + + Batch index cannot be less than 0 or greater than the number of batches + Batch-Index darf nicht kleiner als 0 oder größer als die Anzahl der Batches sein. + + + + + Result set index cannot be less than 0 or greater than the number of result sets + Der Index der Ergebnismenge darf nicht kleiner als 0 oder größer als die Anzahl der Ergebnismengen sein + + + + + Maximum number of bytes to return must be greater than zero + Die maximale Anzahl an Bytes die zurückgeben wird, muss größer als 0 sein. + + + + + Maximum number of chars to return must be greater than zero + Die maximale Anzahl an Zeichen die zurückgeben werden, muss größer als 0 sein. + + + + + Maximum number of XML bytes to return must be greater than zero + Die maximale Anzahl an XML Bytes die zurückgeben wird, muss größer als 0 sein. + + + + + Access method cannot be write-only + Die Zugriffsmethode kann nicht write-only sein. + + + + + FileStreamWrapper must be initialized before performing operations + FileStreamWrapper muss initialisiert werden, bevor Operationen ausführt werden können + + + + + This FileStreamWrapper cannot be used for writing + Diese FileStreamWrapper kann nicht zum Schreiben verwendet werden + + + + + (1 row affected) + (1 Zeile betroffen) + + + + + ({0} rows affected) + ({0} Zeilen betroffen) + + . + Parameters: 0 - rows (long) + + + Commands completed successfully. + Die Befehle wurden erfolgreich ausgeführt. + + + + + Msg {0}, Level {1}, State {2}, Line {3}{4}{5} + Zeile MSG {0} auf {1} Status {2}, {3} {4} {5} + + . + Parameters: 0 - msg (int), 1 - lvl (int), 2 - state (int), 3 - line (int), 4 - newLine (string), 5 - message (string) + + + Query failed: {0} + Fehler bei Abfrage: {0} + + . + Parameters: 0 - message (string) + + + (No column name) + (Kein Spaltenname) + + + + + The requested query does not exist + Die angeforderte Abfrage ist nicht vorhanden. + + + + + This editor is not connected to a database + Dieser Editor ist nicht mit einer Datenbank verbunden. + + + + + A query is already in progress for this editor session. Please cancel this query or wait for its completion. + Eine Abfrage wird für diese Sitzung bereits ausgeführt. Brechen Sie diese Abfrage ab, oder warten Sie auf Beendigung. + + + + + Sender for OnInfoMessage event must be a SqlConnection + Das sender Objekt für OnInfoMessage muss vom Typ SqlConnection sein + + + + + Result cannot be saved until query execution has completed + Das Ergebnis kann nicht gespeichert werden, solange die Abfrageausführung nicht abgeschlossen ist. + + + + + Internal error occurred while starting save task + Beim Speichern ist ein interner Fehler aufgetreten + + + + + A save request to the same path is in progress + Eine Speicheranforderung mit demselben Pfad wird bereits ausgeführt. + + + + + Failed to save {0}: {1} + Fehler beim Speichern von {0}: {1} + + . + Parameters: 0 - fileName (string), 1 - message (string) + + + Cannot read subset unless the results have been read from the server + Der Teil kann nicht gelesen werden solange die Ergebnisse nicht vom Server gelesen wurden + + + + + Start row cannot be less than 0 or greater than the number of rows in the result set + Index der Startzeile kann nicht kleiner als 0 oder größer als die Anzahl der Zeilen der Ergebnismenge sein + + + + + Row count must be a positive integer + Zeilenanzahl muss eine positive ganze Zahl sein. + + + + + Could not retrieve column schema for result set + Es konnten keine Schemainformationen der Spalte abgerufen werden + + + + + Could not retrieve an execution plan from the result set + Es konnten kein Ausführungsplan für die Ergebnismenge abgerufen werden + + + + + This feature is currently not supported on Azure SQL DB and Data Warehouse: {0} + Diese Funktionalität wird derzeit nicht in Azure SQL DB ud Data Warehouse unterstützt: {0} + + . + Parameters: 0 - errorMessage (string) + + + An unexpected error occurred during Peek Definition execution: {0} + Ein unerwarteter Fehler trat beim Einsehen der Definitionen auf: {0} + + . + Parameters: 0 - errorMessage (string) + + + No results were found. + Es wurden keine Ergebnisse gefunden. + + + + + No database object was retrieved. + Es wurde kein Datenbankobjekt abgerufen + + + + + Please connect to a server. + Verbinden Sie Sich mit einem Server. + + + + + Operation timed out. + Zeitüberschreitung bei der Ausführung + + + + + This object type is currently not supported by this feature. + Dieser Objekttyp wird aktuell von dieser Funktionalität nicht unterstützt + + + + + Position is outside of file line range + Die Position befindet sich außerhalb der Zeile + + + + + Position is outside of column range for line {0} + Die Position befindet sich außerhalb der Spalte in Zeile {0} + + . + Parameters: 0 - line (int) + + + Start position ({0}, {1}) must come before or be equal to the end position ({2}, {3}) + Startposition ({0}, {1}) muss vor oder gleich der Endposition ({2}, {3}) sein + + . + Parameters: 0 - sLine (int), 1 - sCol (int), 2 - eLine (int), 3 - eCol (int) + + + Msg {0}, Level {1}, State {2}, Line {3} + Meldung {0}, Ebene {1}, Status {2}, Zeile {3} + + + + + Msg {0}, Level {1}, State {2}, Procedure {3}, Line {4} + Meldung {0}, Ebene {1}, Status {2}, Prozedur {3}, Zeile {4} + + + + + Msg {0}, Level {1}, State {2} + Meldung {0}, Ebene {1}, Status {2} + + + + + An error occurred while the batch was being processed. The error message is: {0} + Fehler beim Ausführen des Batches. Fehlermeldung: {0} + + + + + ({0} row(s) affected) + ({0} Zeile(n) betroffen) + + + + + The previous execution is not yet complete. + Die vorherige Ausführung ist noch nicht abgeschlossen. + + + + + A scripting error occurred. + Ein Skriptfehler ist aufgetreten. + + + + + Incorrect syntax was encountered while {0} was being parsed. + Ein Syntaxfehler ist aufgetreten der bei Analyse von {0} + + + + + A fatal error occurred. + Ein schwerwiegender Fehler ist aufgetreten. + + + + + Batch execution completed {0} times... + {0}-mal ausgeführt... + + + + + You cancelled the query. + Sie haben die Abfrage abgebrochen. + + + + + An error occurred while the batch was being executed. + Fehler während der Batchausführung. + + + + + An error occurred while the batch was being executed, but the error has been ignored. + Fehler während der Batchausführung, aber des Fehlers wurde ignoriert. + + + + + Beginning execution loop + Beginning execution loop + + + + + Command {0} is not supported. + Befehl {0} wird nicht unterstützt. + + + + + The variable {0} could not be found. + Die Variable {0} konnte nicht gefunden werden. + + + + + SQL Execution error: {0} + Fehler bei der SQL-Ausführung: {0} + + + + + Batch parser wrapper execution: {0} found... at line {1}: {2} Description: {3} + Batch-Ausführung des Batchanalysewrappers: {0} in Zeile {1} gefunden...: {2} Beschreibung: {3} + + + + + Batch parser wrapper execution engine batch message received: Message: {0} Detailed message: {1} + Batch Parser Wrapper Execution Engine Meldung empfangen: Meldung: {0} Ausführliche Meldung: {1} + + + + + Batch parser wrapper execution engine batch ResultSet processing: DataReader.FieldCount: {0} DataReader.RecordsAffected: {1} + Stapelverarbeitung Parser Wrapper Execution Engine Stapel ResultSet: DataReader.FieldCount: {0} DataReader.RecordsAffected: {1} + + + + + Batch parser wrapper execution engine batch ResultSet finished. + Batch-Parser Wrapper Execution Engine wurde beendet ResultSet. + + + + + Canceling batch parser wrapper batch execution. + Ausführung des Batchanalysewrappers Batch abgebrochen. + + + + + Scripting warning. + Scripting-Warnung. + + + + + For more information about this error, see the troubleshooting topics in the product documentation. + Weitere Informationen zu diesem Fehler finden Sie in den entsprechenden Abschnitten der Produktdokumentation. + + + + + File '{0}' recursively included. + Die Datei '{0}' ist rekursiv eingeschlossen. + + + + + Missing end comment mark '*/'. + Fehlender End Kommentarzeichen "* /". + + + + + Unclosed quotation mark after the character string. + Fehlendes schließendes Anführungszeichen nach der Zeichenfolge + + + + + Incorrect syntax was encountered while parsing '{0}'. + Syntaxfehler aufgetreten beim Analysieren von '{0}'. + + + + + Variable {0} is not defined. + Variable {0} ist nicht definiert. + + + + + test + Test + + + + + Replacement of an empty string by an empty string. + Ersatz einer leeren Zeichenfolge durch eine leere Zeichenfolge. + + + + + Edit session does not exist. + Die Sitzung "{0}" ist nicht vorhanden. + + + + + Query has not completed execution + Die Abfrage wurde nicht abgeschlossen + + + + + Query did not generate exactly one result set + Die Abfrage erzeugte mehr als eine Ergebnismenge + + + + + Failed to add new row to update cache + Fehler beim Hinzufügen einer neuen Zeile zum Aktualisierungscache + + + + + Given row ID is outside the range of rows in the edit cache + Die angegebene Zeilen-ID ist außerhalb des Bereiches des Bearbeitungscaches + + + + + An update is already pending for this row and must be reverted first + Für diese Zeile steht eine Aktualisierung an, die erst zurückgenommen werden muß + + + + + Given row ID does not have pending update + Die angegebene Zeilen-ID hat keine ausstehenden Aktualisierungen + + + + + Table or view metadata could not be found + Tabellen oder Sicht Metadaten konnten nicht gefunden werden + + + + + Invalid format for binary column + Ungültiges Format für eine binäre Spalte + + + + + Allowed values for boolean columns are 0, 1, "true", or "false" + Spalten vom Typ Boolean müssen entweder der Zahl 0 oder 1 oder der Zeichenkette true oder false entsprechen + + + + + The column '{0}' is defined as NOT NULL but was not given a value + Ein Pflichtfeld hat keinen Wert. + + . + Parameters: 0 - colName (string) + + + A delete is pending for this row, a cell update cannot be applied. + Für diese Zeile steht ein Löschbefehl aus, die Aktualisierung von Feldern kann nicht durchgeführt werden. + + + + + Column ID must be in the range of columns for the query + Die ID der Spalte muss innerhalb des Bereichs der Spalten der Abfrage sein + + + + + Column cannot be edited + Die Spalte kann nicht editiert werden + + + + + No key columns were found + Keine Schlüsselspalten gefunden + + + + + An output filename must be provided + Der Name der Ausgabedatei muss angegeben werden + + + + + Database object {0} cannot be used for editing. + Das Datenbankobjekt {0} kan nicht editiert werden + + . + Parameters: 0 - typeName (string) + + + Specified URI '{0}' does not have a default connection + Spezifizierte URI '{0}' hat keine Standardverbindung + + . + Parameters: 0 - uri (string) + + + A commit task is in progress. Please wait for completion. + Eine Commit-Anweisung wird ausgeführt. Bitte warten Sie bis zur Fertigstellung + + + + + Decimal column is missing numeric precision or numeric scale + Für die Decimal-Spalte fehlt die Angabe der Genauigkeit und Dezimalstellenanzahl + + + + + <TBD> + <TBD> + + + + + Cannot add row to result buffer, data reader does not contain rows + Kann Zeile nicht an Ergebnisbuffer anhängen, da keine Zeilen im Datareader enthalten sind. + + + + + TIME column values must be between 00:00:00.0000000 and 23:59:59.9999999 + Der Wert für eine Spalte vom Typ TIME muss zwischen 00:00:00.0000000 und 23:59:59.9999999 liegen + + + + + NULL is not allowed for this column + NULL ist für diese Spalte nicht erlaubt + + + + + Edit session already exists. + Es gibt bereits eine Session + + + + + Edit session has not been initialized + Eine Session wurde nocht nicht initialisiert + + + + + Edit session has already been initialized + Eine Session wurde bereits initialisiert + + + + + Edit session has already been initialized or is in the process of initializing + Eine Session wurde bereits initialisiert oder befindet sich im Prozess der Initialisierung. + + + + + Query execution failed, see messages for details + Fehler beim Ausführen der Abfrage. Weitere Informationen finden SIe in der Ausgabe + + + + + Result limit cannot be negative + Die Ergebnismengengrenze darf nicht negativ sein + + + + + NULL + NULL + + + + + A object name must be provided + Der Name des Objekts muss angegeben werden + + + + + Explicitly specifying server or database is not supported + Einen bestimmten Server oder Datenbank auszuwählen wird nicht unterstützt. + + + + + Table metadata does not have extended properties + Die Metadaten der Tabelle enthält keine erweiterten EIgenschaften. + + + + + Table or view requested for edit could not be found + Tabelle oder Sicht zur Bearbeitung konnte nicht gefunden werden + + + + + Error expanding: {0} + Fehler beim Erweitern von: {0} + + + + + Error connecting to {0} + Fehler bei der Verbindung zu {0} + + + + + Aggregates + Aggregate + + + + + Server Roles + Serverrollen + + + + + Application Roles + Anwendungsrollen + + + + + Assemblies + Assemblys + + + + + Assembly Files + Assemblydateien + + + + + Asymmetric Keys + Asymmetrische Schlüssel + + + + + Asymmetric Keys + Asymmetrische Schlüssel + + + + + Data Compression Options + Datenkomprimierungsoptionen + + + + + Certificates + Zertifikate + + + + + FileTables + FileTables + + + + + Certificates + Zertifikate + + + + + Check Constraints + Einschränkungen überprüfen + + + + + Columns + Spalten + + + + + Constraints + Einschränkungen + + + + + Contracts + Verträge + + + + + Credentials + Anmeldeinformationen + + + + + Error Messages + Fehlermeldungen + + + + + Server Role Membership + Serverrollenmitgliedschaft + + + + + Database Options + Datenbankoptionen + + + + + Database Roles + Datenbankrollen + + + + + Role Memberships + Rollenmitgliedschaften + + + + + Database Triggers + Datenbanktrigger + + + + + Default Constraints + DEFAULT-Einschränkungen + + + + + Defaults + Standardwerte + + + + + Sequences + Sequenzen + + + + + Endpoints + Endpunkte + + + + + Event Notifications + Ereignisbenachrichtigungen + + + + + Server Event Notifications + Serverbenachrichtigungsereignisse + + + + + Extended Properties + Erweiterte Eigenschaften + + + + + Filegroups + Dateigruppen + + + + + Foreign Keys + Fremdschlüssel + + + + + Full-Text Catalogs + Volltextkataloge + + + + + Full-Text Indexes + Volltextindizes + + + + + Functions + Funktionen + + + + + Indexes + Indizes + + + + + Inline Functions + Inlinefunktionen + + + + + Keys + Schlüssel + + + + + Linked Servers + Verbindungsserver + + + + + Linked Server Logins + Anmeldungen für Verbindungsserver + + + + + Logins + Anmeldungen + + + + + Master Key + Hauptschlüssel + + + + + Master Keys + Hauptschlüssel + + + + + Message Types + Meldungstypen + + + + + Table-Valued Functions + Tabellenwertfunktionen + + + + + Parameters + Parameter + + + + + Partition Functions + Partitionsfunktionen + + + + + Partition Schemes + Partitionsschemas + + + + + Permissions + Berechtigungen + + + + + Primary Keys + Primärschlüssel + + + + + Programmability + Programmierbarkeit + + + + + Queues + Warteschlangen + + + + + Remote Service Bindings + Remotedienstbindungen + + + + + Returned Columns + Zurückgegebene Spalten + + + + + Roles + Rollen + + + + + Routes + Routen + + + + + Rules + Regeln + + + + + Schemas + Schemas + + + + + Security + Sicherheit + + + + + Server Objects + Serverobjekte + + + + + Management + Verwaltung + + + + + Triggers + Trigger + + + + + Service Broker + Service Broker + + + + + Services + Dienste + + + + + Signatures + Signaturen + + + + + Log Files + Protokolldateien + + + + + Statistics + Statistik + + + + + Storage + Speicher + + + + + Stored Procedures + Gespeicherte Prozeduren + + + + + Symmetric Keys + Symmetrische Schlüssel + + + + + Synonyms + Synonyme + + + + + Tables + Tabellen + + + + + Triggers + Trigger + + + + + Types + Typen + + + + + Unique Keys + Eindeutige Schlüssel + + + + + User-Defined Data Types + Benutzerdefinierte Datentypen + + + + + User-Defined Types (CLR) + Benutzerdefinierte Typen (CLR) + + + + + Users + Benutzer + + + + + Views + Sichten + + + + + XML Indexes + XML-Indizes + + + + + XML Schema Collections + XML-Schemaauflistungen + + + + + User-Defined Table Types + Benutzerdefinierte Tabellentypen + + + + + Files + Dateien + + + + + Missing Caption + Fehlende Beschriftung + + + + + Broker Priorities + Brokerprioritäten + + + + + Cryptographic Providers + Kryptografieanbieter + + + + + Database Audit Specifications + Datenbank-Überwachungsspezifikationen + + + + + Database Encryption Keys + Verschlüsselungsschlüssel für Datenbank + + + + + Event Sessions + Ereignissitzungen + + + + + Full Text Stoplists + Volltext-Stopplisten + + + + + Resource Pools + Ressourcenpools + + + + + Audits + Überwachungen + + + + + Server Audit Specifications + Serverüberwachungsspezifikationen + + + + + Spatial Indexes + Räumliche Indizes + + + + + Workload Groups + Arbeitsauslastungsgruppen + + + + + SQL Files + SQL-Dateien + + + + + Server Functions + Serverfunktionen + + + + + SQL Type + SQL-Typ + + + + + Server Options + Serveroptionen + + + + + Database Diagrams + Datenbankdiagramme + + + + + System Tables + Systemtabellen + + + + + Databases + Datenbanken + + + + + System Contracts + Systemverträge + + + + + System Databases + Systemdatenbanken + + + + + System Message Types + Systemmeldungstypen + + + + + System Queues + Systemwarteschlangen + + + + + System Services + Systemdienste + + + + + System Stored Procedures + Gespeicherte Systemprozeduren + + + + + System Views + Systemsichten + + + + + Data-tier Applications + Datenebenenanwendungen + + + + + Extended Stored Procedures + Erweiterte gespeicherte Prozeduren + + + + + Aggregate Functions + Aggregatfunktionen + + + + + Approximate Numerics + Ungefähre numerische Ausdrücke + + + + + Binary Strings + Binärzeichenfolgen + + + + + Character Strings + Zeichenfolgen + + + + + CLR Data Types + CLR-Datentypen + + + + + Configuration Functions + Konfigurationsfunktionen + + + + + Cursor Functions + Cursorfunktionen + + + + + System Data Types + Systemdatentypen + + + + + Date and Time + Datum und Uhrzeit + + + + + Date and Time Functions + Datums- und Uhrzeitfunktionen + + + + + Exact Numerics + Genaue numerische Ausdrücke + + + + + System Functions + Systemfunktionen + + + + + Hierarchy Id Functions + Hierarchie-ID-Funktionen + + + + + Mathematical Functions + Mathematische Funktionen + + + + + Metadata Functions + Metadatenfunktionen + + + + + Other Data Types + Andere Datentypen + + + + + Other Functions + Andere Funktionen + + + + + Rowset Functions + Rowsetfunktionen + + + + + Security Functions + Sicherheitsfunktionen + + + + + Spatial Data Types + Räumliche Datentypen + + + + + String Functions + Zeichenfolgenfunktionen + + + + + System Statistical Functions + Statistische Systemfunktionen + + + + + Text and Image Functions + Text- und Bildfunktionen + + + + + Unicode Character Strings + Unicode-Zeichenfolgen + + + + + Aggregate Functions + Aggregatfunktionen + + + + + Scalar-valued Functions + Skalarwertfunktionen + + + + + Table-valued Functions + Tabellenwertfunktionen + + + + + System Extended Stored Procedures + Erweiterte gespeicherte Systemprozeduren + + + + + Built-in Types + Integrierte Typen + + + + + Built-in Server Roles + Integrierte Serverrollen + + + + + User with Password + Benutzer mit Kennwort + + + + + Search Property List + Sucheigenschaftenliste + + + + + Security Policies + Sicherheitsrichtlinien + + + + + Security Predicates + Sicherheitsprädikate + + + + + Server Role + Serverrolle + + + + + Search Property Lists + Sucheigenschaftenlisten + + + + + Column Store Indexes + Spaltenspeicherindizes + + + + + Table Type Indexes + Tabellentypindex + + + + + Selective XML Indexes + Selektive XML-Indexe + + + + + XML Namespaces + XML-Namespaces + + + + + XML Typed Promoted Paths + XML-typisierte höher gestufte Pfade + + + + + T-SQL Typed Promoted Paths + T-SQL-typisierte höher gestufte Pfade + + + + + Database Scoped Credentials + Datenbankweit gültige Anmeldeinformationen + + + + + External Data Sources + Externe Datenquellen + + + + + External File Formats + Externe Dateiformate + + + + + External Resources + Externe Ressourcen + + + + + External Tables + Externe Tabellen + + + + + Always Encrypted Keys + Immer verschlüsselte Schlüssel + + + + + Column Master Keys + Spaltenhauptschlüssel + + + + + Column Encryption Keys + Spaltenverschlüsselungsschlüssel + + + + + Server + Server + + + + + Error parsing ScriptingParams.ConnectionString property. + Fehler beim Analysieren der Eigenschaft ScriptingParams.ConnectionString. + + + + + Invalid directory specified by the ScriptingParams.FilePath property. + Ungültiges Verzeichnis angeben in der Eigenschaft ScriptingParams.FilePath. + + + + + Error parsing ScriptingListObjectsCompleteParams.ConnectionString property. + Fehler beim Analysieren der Eigenschaft ScriptingListObjectsCompleteParams.ConnectionString + + + + + {0} ({1}, {2}, {3}) + {0} ({1}, {2}, {3}) + + + + + No default + Kein Standard + + + + + Input + Eingabe + + + + + Input/Output + Eingabe/Ausgabe + + + + + Input/ReadOnly + Eingabe/schreibgeschützt + + + + + Input/Output/ReadOnly + Eingabe/Ausgabe/schreibgeschützt + + + + + Default + Standard + + + + + null + NULL + + + + + not null + nicht NULL + + + + + {0} ({1}, {2}) + {0} ({1}, {2}) + + + + + {0} ({1}) + {0} ({1}) + + + + + {0} ({1}Computed, {2}, {3}) + {0} ({1}berechnet, {2}, {3}) + + + + + {0} ({1}Computed) + {0} ({1}berechnet) + + + + + {0} (Column Set, {1}) + {0} (Spaltensatz, {1}) + + + + + {0} (Column Set, {1}{2}, {3}) + {0} (Spaltensatz, {1} {2}, {3}) + + + + + {0} (Column Set, {1}, {2}, {3}) + {0} (Spaltensatz, {1}, {2}, {3}) + + + + + Unique + Eindeutig + + + + + Non-Unique + Nicht eindeutig + + + + + Clustered + Gruppiert + + + + + Non-Clustered + Nicht gruppiert + + + + + History + Verlauf + + + + + System-Versioned + System-Mit Versionsangabe + + + + + Unavailable + Nicht verfügbar + + + + + Current default filegroup: {0} + Aktuelle Standarddateigruppe: {0} + + + + + New Filegroup for {0} + Neue Dateigruppe für "{0}" + + + + + Default + Standard + + + + + Files + Dateien + + + + + Name + Name + + + + + Read-Only + Schreibgeschützt + + + + + Autogrowth / Maxsize + Automatische Vergrößerung/Maximale Größe + + + + + ... + ... + + + + + <default> + <Standard> + + + + + Filegroup + Dateigruppe + + + + + Logical Name + Logischer Name + + + + + File Type + Dateityp + + + + + Initial Size (MB) + Anfangsgröße (MB) + + + + + <new filegroup> + <neue Dateigruppe> + + + + + Path + Pfad + + + + + File Name + Dateiname + + + + + <raw device> + <unformatiertes Medium> + + + + + Bulk-logged + Massenprotokolliert + + + + + Full + Vollständig + + + + + Simple + Einfach + + + + + Select Database Owner + Datenbankbesitzer auswählen + + + + + None + Kein(e) + + + + + By {0} MB, Limited to {1} MB + Um {0} MB, auf {1} MB beschränkt + + + + + By {0} percent, Limited to {1} MB + Um {0} Prozent, auf {1} MB beschränkt + + + + + By {0} MB, Unlimited + Um {0} MB, unbegrenzt + + + + + By {0} percent, Unlimited + Um {0} Prozent, unbegrenzt + + + + + Unlimited + Unbegrenzt + + + + + Limited to {0} MB + Auf {0} MB beschränkt + + + + + Automatic + Automatisch + + + + + Service Broker + Service Broker + + + + + Collation + Sortierung + + + + + Cursor + Cursor + + + + + Miscellaneous + Verschiedenes + + + + + Recovery + Wiederherstellung + + + + + State + Status + + + + + ANSI NULL Default + ANSI NULL Default + + + + + ANSI NULLS Enabled + ANSI NULLS aktiviert + + + + + ANSI Padding Enabled + ANSI-Auffüllung aktiviert + + + + + ANSI Warnings Enabled + ANSI Warnings aktiviert + + + + + Arithmetic Abort Enabled + Abbruch bei arithmetischem Fehler aktiviert + + + + + Auto Close + Automatisch schließen + + + + + Auto Create Statistics + Statistik automatisch erstellen + + + + + Auto Shrink + Automatisch verkleinern + + + + + Auto Update Statistics + Statistiken automatisch aktualisieren + + + + + Auto Update Statistics Asynchronously + Statistik automatisch asynchron aktualisieren + + + + + Case Sensitive + Unterscheidung nach Groß-/Kleinschreibung + + + + + Close Cursor on Commit Enabled + Schließen des Cursors nach Commit aktiviert + + + + + Collation + Sortierung + + + + + Concatenate Null Yields Null + Verketten von NULL-Werten ergibt NULL + + + + + Database Compatibility Level + Datenbank-Kompatibilitätsgrad + + + + + Database State + Datenbankstatus + + + + + Default Cursor + Standardcursor + + + + + Full-Text Indexing Enabled + Volltextindizierung aktiviert + + + + + Numeric Round-Abort + Abbruch bei numerischem Runden + + + + + Page Verify + Seitenüberprüfung + + + + + Quoted Identifiers Enabled + Bezeichner in Anführungszeichen aktiviert + + + + + Database Read-Only + Datenbank schreibgeschützt + + + + + Recursive Triggers Enabled + Rekursive Trigger aktiviert + + + + + Restrict Access + Zugriff beschränken + + + + + Select Into/Bulk Copy + Select Into/Bulk Copy + + + + + Honor Broker Priority + Brokerpriorität berücksichtigen + + + + + Service Broker Identifier + Service Broker-Bezeichner + + + + + Broker Enabled + Broker aktiviert + + + + + Truncate Log on Checkpoint + Protokoll bei Prüfpunkt abschneiden + + + + + Cross-database Ownership Chaining Enabled + Datenbankübergreifende Besitzverkettung aktiviert + + + + + Trustworthy + Vertrauenswürdig + + + + + Date Correlation Optimization Enabled + Optimierung der Datumskorrelation aktiviert: +prototype_db_prop_parameterization = Parameterization + + + + + Forced + Erzwungen + + + + + Simple + Einfach + + + + + ROWS Data + ROWS (Daten) + + + + + LOG + LOG + + + + + FILESTREAM Data + FILESTREAM-Daten + + + + + Not Applicable + Nicht zutreffend + + + + + <default path> + <Standardpfad> + + + + + Open Connections + Geöffnete Verbindungen + + + + + To change the database properties, SQL Server must close all other connections to the database_ Are you sure you want to change the properties and close all other connections? + 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 + AUTO_CLOSED + + + + + EMERGENCY + EMERGENCY + + + + + INACCESSIBLE + INACCESSIBLE + + + + + NORMAL + NORMAL + + + + + OFFLINE + OFFLINE + + + + + RECOVERING + RECOVERING + + + + + RECOVERY PENDING + RECOVERY PENDING + + + + + RESTORING + RESTORING + + + + + SHUTDOWN + SHUTDOWN + + + + + STANDBY + STANDBY + + + + + SUSPECT + SUSPECT + + + + + GLOBAL + GLOBAL + + + + + LOCAL + LOCAL + + + + + MULTI_USER + MULTI_USER + + + + + RESTRICTED_USER + RESTRICTED_USER + + + + + SINGLE_USER + SINGLE_USER + + + + + CHECKSUM + CHECKSUM + + + + + NONE + NONE + + + + + TORN_PAGE_DETECTION + TORN_PAGE_DETECTION + + + + + VarDecimal Storage Format Enabled + VarDecimal-Speicherformat aktiviert + + + + + SQL Server 2008 (100) + SQL Server 2008 (100) + + + + + Encryption Enabled + Verschlüsselung aktiviert + + + + + OFF + AUS + + + + + ON + EIN + + + + + PRIMARY + PRIMÄR + + + + + For the distribution policy HASH, the number of leading hash columns is optional but should be from 1 to 16 columns + 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 2012 (110) + + + + + SQL Server 2014 (120) + SQL Server 2014 (120) + + + + + SQL Server 2016 (130) + SQL Server 2016 (130) + + + + + SQL Server vNext (140) + SQL Server vNext (140) + + + + + None + Kein(e) + + + + + Partial + Teilweise + + + + + FILESTREAM Files + FILESTREAM-Dateien + + + + + No Applicable Filegroup + Keine anwendbare Dateigruppe + + + + + The database {0} is not accessible. + Auf die Datenbank "{0}" kann nicht zugegriffen werden. + + + + + Query has no results to return + Abfrage hat keine Ergebnis zum Zurückgeben + + + + + Result set has too many rows to be safely loaded + Ergebnismenge ist zu groß, um sicher geladen zu werden + + + + Parameterization + Parametrisierung + + + + + Specifying this option when restoring a backup with the NORECOVERY option is not permitted. + Diese Option darf nicht angegeben werden, wenn eine Sicherung mit der NORECOVERY-Option wiederhergestellt wird. + + + + + Invalid path for database file: '{0}' + Ungültiger Pfad für Datenbankdatei: {0} + + + + + Log + Protokoll + + + + + Failed to create restore plan + Fehler beim Erstellen des Wiederherstellungsplan + + + + + Restore database is not supported + Wiederherstellen der Datenbank wird nicht unterstützt. + + + + + Restore Database + Datenbank wiederherstellen + + + + + (Copy Only) + (nur kopieren) + + + + + Component + Komponente + + + + + Type + Typ + + + + + Server + Server + + + + + Database + Datenbank + + + + + Position + Position + + + + + First LSN + Erste LSN + + + + + Last LSN + Letzte LSN + + + + + Checkpoint LSN + Prüfpunkt-LSN + + + + + Full LSN + Vollständige LSN + + + + + Start Date + Startdatum + + + + + Finish Date + Beendigungsdatum + + + + + Size + Größe + + + + + User Name + Benutzername + + + + + Expiration + Ablaufdatum + + + + + Name + Name + + + + + The last backup taken ({0}) + Letzte Sicherung ({0}) + + + + + Backup Database + Datenbank sichern + + + + + In progress + In Bearbeitung + + + + + Completed + Abgeschlossen + + + + + scripting + Skripterstellung + + + + + Connection not found + Verbindung nicht gefunden + + + + + Please provide a file path instead of directory path + Der angegebene Dateiname ist zugleich ein Verzeichnisname: {0} + + + + + The provided path is invalid + Es kann nicht überprüft werden, ob der Speicherort der Sicherungsdatei vorhanden ist: {0} + + + + + Cannot access the specified path on the server: {0} + Auf den angegebenen Pfad auf dem Server kann nicht zugegriffen werden: {0} + + + + + No backupset selected to be restored + Kein Sicherungssatz zur Wiederherstellung ausgewählt + + + + + Never + Nie + + + + + Azure SQL DB + Azure SQL DB + + + + + Azure SQL Data Warehouse + Azure SQL Data Warehouse + + + + + Azure SQL Stretch Database + Azure SQL Stretch Database + + + + + Path {0} is not a valid directory + Der Pfad {0} ist kein gültiges Verzeichnis + + + + + For directory {0} a file with name {1} already exists + Die Datei {1} im Verzeichnis {0} existiert bereits. + + + + + Value {0} is too large to fit in column of type {1} + Der Wert {0} ist zu groß für eine Spalte mit dem Datentyp {1} + + . + Parameters: 0 - value (string), 1 - columnType (string) + + + + \ No newline at end of file diff --git a/src/Microsoft.SqlTools.CoreServices/Localization/transXliff/sr.es.xlf b/src/Microsoft.SqlTools.CoreServices/Localization/transXliff/sr.es.xlf new file mode 100644 index 00000000..d91d12a6 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Localization/transXliff/sr.es.xlf @@ -0,0 +1,2775 @@ + + + + + Connection parameters cannot be null + Los parámetros de conexión no pueden ser nulos + + + + + OwnerUri cannot be null or empty + OwnerUri no puede ser nulo ni estar vacío + + + + + SpecifiedUri '{0}' does not have existing connection + SpecifiedUri '{0}' no tiene una conexión existente + + . + Parameters: 0 - uri (string) + + + Invalid value '{0}' for AuthenticationType. Valid values are 'Integrated' and 'SqlLogin'. + El valor '{0}' no es válido para AuthenticationType. Los valores válidos son 'Integrated' y 'SqlLogin'. + + . + Parameters: 0 - authType (string) + + + Invalid value '{0}' for ApplicationIntent. Valid values are 'ReadWrite' and 'ReadOnly'. + El valor '{0}' no es válido para ApplicationIntent. Los valores válidos son 'ReadWrite' y 'ReadOnly'. + + . + Parameters: 0 - intent (string) + + + Connection canceled + Conexión cancelada + + + + + OwnerUri cannot be null or empty + OwnerUri no puede ser nulo ni estar vacío + + + + + Connection details object cannot be null + El objeto de detalles de conexión no puede ser nulo + + + + + ServerName cannot be null or empty + ServerName no puede ser nulo ni estar vacío + + + + + {0} cannot be null or empty when using SqlLogin authentication + {0} no puede ser nulo ni estar vacío cuando se utiliza autenticación SqlLogin + + . + Parameters: 0 - component (string) + + + The query has already completed, it cannot be cancelled + Ya se ha completado la consulta, no se puede cancelar + + + + + Query successfully cancelled, failed to dispose query. Owner URI not found. + La consulta fue cancelada con éxito, pero no se ha podido desechar. No se encontró el URI del propietario. + + + + + Query was canceled by user + Consulta cancelada por el usuario + + + + + The batch has not completed, yet + El lote aún no ha finalizado, + + + + + Batch index cannot be less than 0 or greater than the number of batches + Índice de lote no puede ser menor que 0 o mayor que el número de lotes + + + + + Result set index cannot be less than 0 or greater than the number of result sets + Índice del conjunto de resultados no puede ser menor que 0 o mayor que el número de conjuntos de resultados + + + + + Maximum number of bytes to return must be greater than zero + El número máximo de bytes a devolver debe ser mayor que cero + + + + + Maximum number of chars to return must be greater than zero + El número máximo de caracteres a devolver debe ser mayor que cero + + + + + Maximum number of XML bytes to return must be greater than zero + El número máximo de bytes XML a devolver debe ser mayor que cero + + + + + Access method cannot be write-only + El método de acceso no puede ser de sólo escritura + + + + + FileStreamWrapper must be initialized before performing operations + FileStreamWrapper debe inicializarse antes de realizar operaciones + + + + + This FileStreamWrapper cannot be used for writing + Este FileStreamWrapper no se puede utilizar para escritura. + + + + + (1 row affected) + (1 fila afectada) + + + + + ({0} rows affected) + ({0} filas afectadas) + + . + Parameters: 0 - rows (long) + + + Commands completed successfully. + Comandos finalizados correctamente. + + + + + Msg {0}, Level {1}, State {2}, Line {3}{4}{5} + Msg {0}, nivel {1} estado {2}, línea {3} {4} {5} + + . + Parameters: 0 - msg (int), 1 - lvl (int), 2 - state (int), 3 - line (int), 4 - newLine (string), 5 - message (string) + + + Query failed: {0} + Error en la consulta: {0} + + . + Parameters: 0 - message (string) + + + (No column name) + (Ningún nombre de columna) + + + + + The requested query does not exist + La consulta solicitada no existe + + + + + This editor is not connected to a database + Este editor no está conectado a una base de datos + + + + + A query is already in progress for this editor session. Please cancel this query or wait for its completion. + Una consulta ya está en curso para esta sesión de editor. Por favor, cancelar esta consulta o esperar su finalización. + + + + + Sender for OnInfoMessage event must be a SqlConnection + Remitente de eventos de OnInfoMessage debe ser un objeto SqlConnection + + + + + Result cannot be saved until query execution has completed + No se puede guardar el resultado hasta que haya finalizado la ejecución de la consulta + + + + + Internal error occurred while starting save task + Error interno al iniciar el guardado de la tarea + + + + + A save request to the same path is in progress + Una operacion de guardado en la misma ruta se encuentra en curso + + + + + Failed to save {0}: {1} + Error al guardar {0}: {1} + + . + Parameters: 0 - fileName (string), 1 - message (string) + + + Cannot read subset unless the results have been read from the server + No se puede leer el subconjunto, a menos que los resultados se han leído desde el servidor + + + + + Start row cannot be less than 0 or greater than the number of rows in the result set + Fila de inicio no puede ser menor que 0 o mayor que el número de filas en el conjunto de resultados + + + + + Row count must be a positive integer + La cantidad de filas debe ser un entero positivo + + + + + Could not retrieve column schema for result set + No se pudo recuperar el esquema de columna para el conjunto de resultados + + + + + Could not retrieve an execution plan from the result set + No se pudo recuperar un plan de ejecución del conjunto de resultados + + + + + This feature is currently not supported on Azure SQL DB and Data Warehouse: {0} + Esta característica actualmente no se admite en la base de datos de SQL Azure y almacén de datos: {0} + + . + Parameters: 0 - errorMessage (string) + + + An unexpected error occurred during Peek Definition execution: {0} + Se ha producido un error inesperado durante la ejecución de la definición de Peek: {0} + + . + Parameters: 0 - errorMessage (string) + + + No results were found. + No se encontraron resultados. + + + + + No database object was retrieved. + No se pudo obtener ningún objeto asociado a la base de datos. + + + + + Please connect to a server. + Por favor, conéctese a un servidor + + + + + Operation timed out. + Tiempo de espera agotado para esta operación. + + + + + This object type is currently not supported by this feature. + Esta característica no admite actualmente este tipo de objeto. + + + + + Position is outside of file line range + Posición está fuera del intervalo de la línea de archivo + + + + + Position is outside of column range for line {0} + Posición está fuera del intervalo de la columna de la línea {0} + + . + Parameters: 0 - line (int) + + + Start position ({0}, {1}) must come before or be equal to the end position ({2}, {3}) + Posición de inicio ({0}, {1}) debe preceder o ser igual a la posición final ({2}, {3}) + + . + Parameters: 0 - sLine (int), 1 - sCol (int), 2 - eLine (int), 3 - eCol (int) + + + Msg {0}, Level {1}, State {2}, Line {3} + Msg {0}, {1}, nivel de estado {2}, línea {3} + + + + + Msg {0}, Level {1}, State {2}, Procedure {3}, Line {4} + Msj {0}, {1}, nivel de estado {2}, procedimiento {3}, línea {4} + + + + + Msg {0}, Level {1}, State {2} + Msg {0}, nivel {1}, {2} de estado + + + + + An error occurred while the batch was being processed. The error message is: {0} + Se produjo un error al procesar el lote. Mensaje de error: {0} + + + + + ({0} row(s) affected) + ({0} filas afectadas) + + + + + The previous execution is not yet complete. + La ejecución anterior aún no está completa. + + + + + A scripting error occurred. + Se ha producido un error de secuencias de comandos. + + + + + Incorrect syntax was encountered while {0} was being parsed. + Se encontró sintaxis incorrecta mientras se estaba analizando {0}. + + + + + A fatal error occurred. + Se ha producido un error grave. + + + + + Batch execution completed {0} times... + La ejecución se completó {0} veces... + + + + + You cancelled the query. + Se canceló la consulta. + + + + + An error occurred while the batch was being executed. + Se produjo un error mientras se ejecutaba el lote. + + + + + An error occurred while the batch was being executed, but the error has been ignored. + Se produjo un error mientras se ejecutaba el lote, pero se ha omitido el error. + + + + + Beginning execution loop + Beginning execution loop + + + + + Command {0} is not supported. + No se admite el comando {0}. + + + + + The variable {0} could not be found. + La variable {0} no se encontró. + + + + + SQL Execution error: {0} + Error de ejecución de SQL: {0} + + + + + Batch parser wrapper execution: {0} found... at line {1}: {2} Description: {3} + Ejecución de contenedor del analizador por lotes: {0} se encuentra... en la línea {1}: {2} Descripción: {3} + + + + + Batch parser wrapper execution engine batch message received: Message: {0} Detailed message: {1} + Lote analizador contenedor ejecución motor lote mensaje recibido: mensaje: {0} mensaje detallado: {1} + + + + + Batch parser wrapper execution engine batch ResultSet processing: DataReader.FieldCount: {0} DataReader.RecordsAffected: {1} + Motor de ejecución de analizador contenedor lote ResultSet procesamiento por lotes: DataReader.FieldCount: {0} DataReader.RecordsAffected: {1} + + + + + Batch parser wrapper execution engine batch ResultSet finished. + Finalizó el elemento ResultSet analizador contenedor ejecución motor los lotes. + + + + + Canceling batch parser wrapper batch execution. + Cancelando la ejecución por lotes del contenedor del analizador por lotes. + + + + + Scripting warning. + Advertencia de scripting. + + + + + For more information about this error, see the troubleshooting topics in the product documentation. + Para obtener más información acerca de este error, vea los temas de solución de problemas en la documentación del producto. + + + + + File '{0}' recursively included. + El archivo '{0}' se incluyó recursivamente. + + + + + Missing end comment mark '*/'. + Falta la marca de final de comentario ' * /'. + + + + + Unclosed quotation mark after the character string. + Sin comilla de cierre después de la cadena de caracteres. + + + + + Incorrect syntax was encountered while parsing '{0}'. + Se encontró sintaxis incorrecta al analizar '{0}'. + + + + + Variable {0} is not defined. + La variable {0} no está definida. + + + + + test + prueba + + + + + Replacement of an empty string by an empty string. + Sustitución de una cadena vacía por una cadena vacía. + + + + + Edit session does not exist. + Sesión de edición no existe, + + + + + Query has not completed execution + La consulta no ha finalizado. + + + + + Query did not generate exactly one result set + La consulta no generó un único set de resultados + + + + + Failed to add new row to update cache + Falló al agregar una nueva fila a la caché de actualización + + + + + Given row ID is outside the range of rows in the edit cache + El ID de la fila ingresado, se encuentra fuera del rango de filas de la caché de edición + + + + + An update is already pending for this row and must be reverted first + Una actualización está pendiente para esta fila y debe de revertirse primero + + + + + Given row ID does not have pending update + El ID de la fila ingresado no tiene actualizaciones pendientes + + + + + Table or view metadata could not be found + La metadata de la tabla o vista no pudo ser encontrada + + + + + Invalid format for binary column + Formato inválido para columna binaria + + + + + Allowed values for boolean columns are 0, 1, "true", or "false" + Columnas del tipo boolean deben de ser numéricos 1 o 0, o tipo string true o false + + + + + The column '{0}' is defined as NOT NULL but was not given a value + Falta un valor requerido de la celda + + . + Parameters: 0 - colName (string) + + + A delete is pending for this row, a cell update cannot be applied. + Existe una eliminación pendiente para esta fila, una actualización de celda no puede ser realizada. + + + + + Column ID must be in the range of columns for the query + El ID de la columna debe de estar en el rango de columnas de la consulta. + + + + + Column cannot be edited + La columna no puede ser editada + + + + + No key columns were found + No se encontró ninguna columna clave + + + + + An output filename must be provided + Proporcione un nombre de archivo de salida + + + + + Database object {0} cannot be used for editing. + Objeto de base de datos {0} no puede ser usado para modificación. + + . + Parameters: 0 - typeName (string) + + + Specified URI '{0}' does not have a default connection + SpecifiedUri '{0}' no tiene alguna conexión por defecto + + . + Parameters: 0 - uri (string) + + + A commit task is in progress. Please wait for completion. + Una tarea de confirmación se encuentra en progreso. Por favor espere que la operación termine. + + + + + Decimal column is missing numeric precision or numeric scale + Columna del tipo decimal no tiene precisión o escala numérica + + + + + <TBD> + <TBD> + + + + + Cannot add row to result buffer, data reader does not contain rows + No se pueden agregar filas al buffer de resultados, el lector de datos no contiene filas + + + + + TIME column values must be between 00:00:00.0000000 and 23:59:59.9999999 + Los valores en la columna TIME deben estar incluidos en el rango desde 00:00:00:000000 hasta 23:59:59.999999 + + + + + NULL is not allowed for this column + No se permite un valor NULL en esta columna + + + + + Edit session already exists. + La sesión de edición ya existe. + + + + + Edit session has not been initialized + La sesión de edición no se inicializó + + + + + Edit session has already been initialized + La sesión de edición ya se inicializó + + + + + Edit session has already been initialized or is in the process of initializing + La sesión de edición ya se inicializo o se encuentra en proceso de inicialización + + + + + Query execution failed, see messages for details + La ejecución de la consulta falló, ver los mensajes para obtener mas detalle + + + + + Result limit cannot be negative + El límite del resultado no puede ser negativo + + + + + NULL + NULL + + + + + A object name must be provided + Se debe proveer un nombre de objeto + + + + + Explicitly specifying server or database is not supported + No se permite especificar explícitamente el servidor o la base de datos + + + + + Table metadata does not have extended properties + Los metadatos de la tabla no tienen propiedades extendidas + + + + + Table or view requested for edit could not be found + La tabla o vista solicitada para edición no se encuentra + + + + + Error expanding: {0} + Error en expansión: {0} + + + + + Error connecting to {0} + Error conectando a {0} + + + + + Aggregates + Agregados + + + + + Server Roles + Roles de servidor + + + + + Application Roles + Roles de aplicación + + + + + Assemblies + Ensamblados + + + + + Assembly Files + Archivos de ensamblado + + + + + Asymmetric Keys + Claves asimétricas + + + + + Asymmetric Keys + Claves asimétricas + + + + + Data Compression Options + Opciones de compresión de datos + + + + + Certificates + Certificados + + + + + FileTables + Tablas de archivos + + + + + Certificates + Certificados + + + + + Check Constraints + Restricciones CHECK + + + + + Columns + Columnas + + + + + Constraints + Restricciones + + + + + Contracts + Contratos + + + + + Credentials + Credenciales + + + + + Error Messages + Mensajes de error + + + + + Server Role Membership + Pertenencia a roles de servidor + + + + + Database Options + Opciones de base de datos + + + + + Database Roles + Roles de base de datos + + + + + Role Memberships + Pertenencias a roles + + + + + Database Triggers + Desencadenadores de base de datos + + + + + Default Constraints + Restricciones DEFAULT + + + + + Defaults + Valores predeterminados + + + + + Sequences + Secuencias + + + + + Endpoints + Extremos + + + + + Event Notifications + Notificaciones de eventos + + + + + Server Event Notifications + Notificaciones de eventos de servidor + + + + + Extended Properties + Propiedades extendidas + + + + + Filegroups + Grupos de archivos + + + + + Foreign Keys + Claves externas + + + + + Full-Text Catalogs + Catálogos de texto completo + + + + + Full-Text Indexes + Índices de texto completo + + + + + Functions + Funciones + + + + + Indexes + Índices + + + + + Inline Functions + Funciones Inline + + + + + Keys + Claves + + + + + Linked Servers + Servidores vinculados + + + + + Linked Server Logins + Inicios de sesión de servidor vinculado + + + + + Logins + Inicios de sesión + + + + + Master Key + Clave maestra + + + + + Master Keys + Claves maestras + + + + + Message Types + Tipos de mensaje + + + + + Table-Valued Functions + Funciones con valores de tabla + + + + + Parameters + Parámetros + + + + + Partition Functions + Funciones de partición + + + + + Partition Schemes + Esquemas de partición + + + + + Permissions + Permisos + + + + + Primary Keys + Claves principales + + + + + Programmability + Programación + + + + + Queues + Colas + + + + + Remote Service Bindings + Enlaces de servicio remoto + + + + + Returned Columns + Columnas devueltos + + + + + Roles + Roles + + + + + Routes + Rutas + + + + + Rules + Reglas + + + + + Schemas + Esquemas + + + + + Security + Seguridad + + + + + Server Objects + Objetos de servidor + + + + + Management + Administración + + + + + Triggers + Desencadenadores + + + + + Service Broker + Service Broker + + + + + Services + Servicios + + + + + Signatures + Firmas + + + + + Log Files + Archivos de registro + + + + + Statistics + Estadísticas + + + + + Storage + Almacenamiento + + + + + Stored Procedures + Procedimientos almacenados + + + + + Symmetric Keys + Claves simétricas + + + + + Synonyms + Sinónimos + + + + + Tables + Tablas + + + + + Triggers + Desencadenadores + + + + + Types + Tipos + + + + + Unique Keys + Claves únicas + + + + + User-Defined Data Types + Tipos de datos definidos por el usuario + + + + + User-Defined Types (CLR) + Tipos definidos por el usuario (CLR) + + + + + Users + Usuarios + + + + + Views + Vistas + + + + + XML Indexes + Índices XML + + + + + XML Schema Collections + Colecciones de esquemas XML + + + + + User-Defined Table Types + Tipos de tablas definidos por el usuario + + + + + Files + Archivos + + + + + Missing Caption + Falta el título + + + + + Broker Priorities + Prioridades de Broker + + + + + Cryptographic Providers + Proveedores de servicios criptográficos + + + + + Database Audit Specifications + Especificaciones de auditoría de base de datos + + + + + Database Encryption Keys + Claves de cifrado de base de datos + + + + + Event Sessions + Sesiones de eventos + + + + + Full Text Stoplists + Listas de palabras irrelevantes de texto completo + + + + + Resource Pools + Grupos de recursos de servidor + + + + + Audits + Auditorías + + + + + Server Audit Specifications + Especificaciones de auditoría de servidor + + + + + Spatial Indexes + Índices espaciales + + + + + Workload Groups + Grupos de cargas de trabajo + + + + + SQL Files + Archivos SQL + + + + + Server Functions + Funciones de servidor + + + + + SQL Type + Tipo SQL + + + + + Server Options + Opciones de servidor + + + + + Database Diagrams + Diagramas de base de datos + + + + + System Tables + Tablas del sistema + + + + + Databases + Bases de datos + + + + + System Contracts + Contratos del sistema + + + + + System Databases + Bases de datos del sistema + + + + + System Message Types + Tipos de mensaje del sistema + + + + + System Queues + Colas del sistema + + + + + System Services + Servicios del sistema + + + + + System Stored Procedures + Procedimientos almacenados del sistema + + + + + System Views + Vistas del sistema + + + + + Data-tier Applications + Aplicaciones de capa de datos + + + + + Extended Stored Procedures + Procedimientos almacenados extendidos + + + + + Aggregate Functions + Funciones de agregado + + + + + Approximate Numerics + Valores numéricos aproximados + + + + + Binary Strings + Cadenas binarias + + + + + Character Strings + Cadenas de caracteres + + + + + CLR Data Types + Tipos de datos CLR + + + + + Configuration Functions + Funciones de configuración + + + + + Cursor Functions + Funciones del cursor + + + + + System Data Types + Tipos de datos del sistema + + + + + Date and Time + Fecha y hora + + + + + Date and Time Functions + Funciones de fecha y hora + + + + + Exact Numerics + Valores numéricos exactos + + + + + System Functions + Funciones del sistema + + + + + Hierarchy Id Functions + Funciones de id. de jerarquía + + + + + Mathematical Functions + Funciones matemáticas + + + + + Metadata Functions + Funciones de metadatos + + + + + Other Data Types + Otros tipos de datos + + + + + Other Functions + Otras funciones + + + + + Rowset Functions + Funciones de conjunto de filas + + + + + Security Functions + Funciones de seguridad + + + + + Spatial Data Types + Tipos de datos espaciales + + + + + String Functions + Funciones de cadena + + + + + System Statistical Functions + Funciones estadísticas del sistema + + + + + Text and Image Functions + Funciones de texto y de imagen + + + + + Unicode Character Strings + Cadenas de caracteres Unicode + + + + + Aggregate Functions + Funciones de agregado + + + + + Scalar-valued Functions + Funciones escalares + + + + + Table-valued Functions + Funciones con valores de tabla + + + + + System Extended Stored Procedures + Procedimientos almacenados extendidos del sistema + + + + + Built-in Types + Tipos integrados + + + + + Built-in Server Roles + Roles de servidor integrados + + + + + User with Password + Usuario con contraseña + + + + + Search Property List + Lista de propiedades de búsqueda + + + + + Security Policies + Directivas de seguridad + + + + + Security Predicates + Predicados de seguridad + + + + + Server Role + Rol de servidor + + + + + Search Property Lists + Listas de propiedades de búsqueda + + + + + Column Store Indexes + Índices de almacenamiento de columnas + + + + + Table Type Indexes + Índices de tipo de tabla + + + + + Selective XML Indexes + Índices XML selectivos + + + + + XML Namespaces + Espacios de nombres XML + + + + + XML Typed Promoted Paths + Rutas de acceso promovidas de tipo XML + + + + + T-SQL Typed Promoted Paths + Rutas de acceso promovidas de tipo T-SQL + + + + + Database Scoped Credentials + Credenciales de ámbito de base de datos + + + + + External Data Sources + Orígenes de datos externos + + + + + External File Formats + Formatos de archivo externo + + + + + External Resources + Recursos externos + + + + + External Tables + Tablas externas + + + + + Always Encrypted Keys + Siempre claves cifradas + + + + + Column Master Keys + Claves maestras de columna + + + + + Column Encryption Keys + Claves de cifrado de columna + + + + + Server + Servidor + + + + + Error parsing ScriptingParams.ConnectionString property. + Error interpretando la propiedad ScriptingParams.ConnectionString + + + + + Invalid directory specified by the ScriptingParams.FilePath property. + El directorio especificado en la propiedad ScriptingParams.FilePath no es válido + + + + + Error parsing ScriptingListObjectsCompleteParams.ConnectionString property. + Error interpretando la propiedad ScriptingListObjectsCompleteParams.ConnectionString + + + + + {0} ({1}, {2}, {3}) + {0} ({1}, {2}, {3}) + + + + + No default + Sin valores predeterminados + + + + + Input + Entrada + + + + + Input/Output + Entrada/salida + + + + + Input/ReadOnly + Entrada/solo lectura + + + + + Input/Output/ReadOnly + Entrada/salida/solo lectura + + + + + Default + Predeterminado + + + + + null + NULL + + + + + not null + no es NULL + + + + + {0} ({1}, {2}) + {0} ({1}, {2}) + + + + + {0} ({1}) + {0} ({1}) + + + + + {0} ({1}Computed, {2}, {3}) + {0} ({1}calculado, {2}, {3}) + + + + + {0} ({1}Computed) + {0} ({1}calculado) + + + + + {0} (Column Set, {1}) + {0} (Conjunto de columnas, {1}) + + + + + {0} (Column Set, {1}{2}, {3}) + {0} (Conjunto de columnas, {1}{2}, {3}) + + + + + {0} (Column Set, {1}, {2}, {3}) + {0} (Conjunto de columnas, {1}, {2}, {3}) + + + + + Unique + Único + + + + + Non-Unique + No único + + + + + Clustered + Clúster + + + + + Non-Clustered + No en clúster + + + + + History + Historial + + + + + System-Versioned + Con versión del sistema + + + + + Unavailable + No disponible + + + + + Current default filegroup: {0} + Grupo de archivos predeterminado: {0} + + + + + New Filegroup for {0} + Grupo de archivos nuevo para: {0} + + + + + Default + Predeterminado + + + + + Files + Archivos + + + + + Name + Nombre + + + + + Read-Only + Solo lectura + + + + + Autogrowth / Maxsize + Crecimiento automático / tamaño máximo + + + + + ... + ... + + + + + <default> + <predeterminado> + + + + + Filegroup + Grupo de archivos + + + + + Logical Name + Nombre lógico + + + + + File Type + Tipo de archivo + + + + + Initial Size (MB) + Tamaño inicial (MB) + + + + + <new filegroup> + <nuevo grupo de archivos> + + + + + Path + Ruta de acceso + + + + + File Name + Nombre de archivo + + + + + <raw device> + <dispositivo sin formato> + + + + + Bulk-logged + Registro masivo + + + + + Full + Completo + + + + + Simple + Simple + + + + + Select Database Owner + Seleccionar propietario de base de datos + + + + + None + Ninguno + + + + + By {0} MB, Limited to {1} MB + Por {0} MB, limitado a {1} MB + + + + + By {0} percent, Limited to {1} MB + Por {0} porciento, limitado a {1} MB + + + + + By {0} MB, Unlimited + Por {0} MB, sin límite + + + + + By {0} percent, Unlimited + Por {0} porciento, sin límite + + + + + Unlimited + Sin límite + + + + + Limited to {0} MB + Limitado a {0} MB + + + + + Automatic + Automático + + + + + Service Broker + Service Broker + + + + + Collation + Intercalación + + + + + Cursor + Cursor + + + + + Miscellaneous + Varios + + + + + Recovery + Recuperación + + + + + State + Estado + + + + + ANSI NULL Default + ANSI NULL predeterminado + + + + + ANSI NULLS Enabled + ANSI NULLS habilitados + + + + + ANSI Padding Enabled + Relleno ANSI habilitado + + + + + ANSI Warnings Enabled + Advertencias ANSI habilitadas + + + + + Arithmetic Abort Enabled + Anulación aritmética habilitada + + + + + Auto Close + Cierre automático + + + + + Auto Create Statistics + Crear estadísticas automáticamente + + + + + Auto Shrink + Reducir automáticamente + + + + + Auto Update Statistics + Actualizar estadísticas automáticamente + + + + + Auto Update Statistics Asynchronously + Actualizar estadísticas automáticamente de forma asincrónica + + + + + Case Sensitive + Sensible a mayúsculas y minúsculas + + + + + Close Cursor on Commit Enabled + Cierre del cursor al confirmar habilitado + + + + + Collation + Intercalación + + + + + Concatenate Null Yields Null + Concatenar valores NULL produce NULL + + + + + Database Compatibility Level + Nivel de compatibilidad de base de datos + + + + + Database State + Estado de la base de datos + + + + + Default Cursor + Cursor predeterminado + + + + + Full-Text Indexing Enabled + Índice de texto completo habilitado + + + + + Numeric Round-Abort + Anular redondeo numérico + + + + + Page Verify + Comprobación de página + + + + + Quoted Identifiers Enabled + Identificadores entre comillas habilitados + + + + + Database Read-Only + Base de datos de solo lectura + + + + + Recursive Triggers Enabled + Desencadenadores recursivos habilitados + + + + + Restrict Access + Restringir acceso + + + + + Select Into/Bulk Copy + Select Into/Bulk Copy + + + + + Honor Broker Priority + Asignar prioridad de agente + + + + + Service Broker Identifier + Identificador de Service Broker + + + + + Broker Enabled + Broker habilitado + + + + + Truncate Log on Checkpoint + Truncar registro en el punto de control + + + + + Cross-database Ownership Chaining Enabled + Encadenamiento de propiedad entre bases de datos habilitado + + + + + Trustworthy + De confianza + + + + + Date Correlation Optimization Enabled + Optimización de correlación de fechas Enabledprototype_db_prop_parameterization = Parameterization + + + + + Forced + Forzado + + + + + Simple + Simple + + + + + ROWS Data + Datos de ROWS + + + + + LOG + LOG + + + + + FILESTREAM Data + Datos de FILESTREAM + + + + + Not Applicable + No aplicable + + + + + <default path> + <ruta predeterminada> + + + + + Open Connections + Conexiones abiertas + + + + + To change the database properties, SQL Server must close all other connections to the database_ Are you sure you want to change the properties and close all other connections? + 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 + AUTO_CLOSED + + + + + EMERGENCY + EMERGENCY + + + + + INACCESSIBLE + INACCESSIBLE + + + + + NORMAL + NORMAL + + + + + OFFLINE + OFFLINE + + + + + RECOVERING + RECOVERING + + + + + RECOVERY PENDING + RECOVERY PENDING + + + + + RESTORING + RESTORING + + + + + SHUTDOWN + SHUTDOWN + + + + + STANDBY + STANDBY + + + + + SUSPECT + SUSPECT + + + + + GLOBAL + GLOBAL + + + + + LOCAL + LOCAL + + + + + MULTI_USER + MULTI_USER + + + + + RESTRICTED_USER + RESTRICTED_USER + + + + + SINGLE_USER + SINGLE_USER + + + + + CHECKSUM + CHECKSUM + + + + + NONE + NONE + + + + + TORN_PAGE_DETECTION + TORN_PAGE_DETECTION + + + + + VarDecimal Storage Format Enabled + Formato de almacenamiento VarDecimal habilitado + + + + + SQL Server 2008 (100) + SQL Server 2008 (100) + + + + + Encryption Enabled + Cifrado habilitado + + + + + OFF + OFF + + + + + ON + ON + + + + + PRIMARY + PRIMARY + + + + + For the distribution policy HASH, the number of leading hash columns is optional but should be from 1 to 16 columns + 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 2012 (110) + + + + + SQL Server 2014 (120) + SQL Server 2014 (120) + + + + + SQL Server 2016 (130) + SQL Server 2016 (130) + + + + + SQL Server vNext (140) + SQL Server vNext (140) + + + + + None + Ninguno + + + + + Partial + Parcial + + + + + FILESTREAM Files + Archivos FILESTREAM + + + + + No Applicable Filegroup + Grupo de archivos no aplicable + + + + + The database {0} is not accessible. + La base de datos {0} no es accesible. + + + + + Query has no results to return + La consulta no devolvió resultados + + + + + Result set has too many rows to be safely loaded + El conjunto de resultados contiene demasiada filas para cargarlo de forma segura + + + + Parameterization + Parametrización + + + + + Specifying this option when restoring a backup with the NORECOVERY option is not permitted. + No se permite restaurar una copia de seguridad con la opción NORECOVERY + + + + + Invalid path for database file: '{0}' + Ruta de archivo no válida: '{0}' + + + + + Log + Registro + + + + + Failed to create restore plan + No se pudo crear un plan de restauraciones + + + + + Restore database is not supported + No se admite restaurar la base de datos + + + + + Restore Database + Restaurar base de datos + + + + + (Copy Only) + (Copiar solamente) + + + + + Component + Componente + + + + + Type + Tipo + + + + + Server + Servidor + + + + + Database + Base de datos + + + + + Position + Posición + + + + + First LSN + Primer LSN + + + + + Last LSN + Último LSN + + + + + Checkpoint LSN + Checkpoint LSN + + + + + Full LSN + LSN completo + + + + + Start Date + Fecha de inicio + + + + + Finish Date + Fecha de finalización + + + + + Size + Tamaño + + + + + User Name + Nombre del usuario + + + + + Expiration + Expiración + + + + + Name + Nombre + + + + + The last backup taken ({0}) + La última copia de seguridad tomada ({0}) + + + + + Backup Database + Copia de seguridad de la base de datos + + + + + In progress + En curso + + + + + Completed + Completado + + + + + scripting + scripting + + + + + Connection not found + Conexión no encontrada + + + + + Please provide a file path instead of directory path + El nombre del archivo especificado es un nombre de directorio: {0} + + + + + The provided path is invalid + No se puede verificar la existencia de la ubicación del archivo de copia de seguridad: {0} + + + + + Cannot access the specified path on the server: {0} + No se puede acceder a la ruta de acceso especificada en el servidor: {0} + + + + + No backupset selected to be restored + Ningún backupset seleccionado para ser restaurado + + + + + Never + Nunca + + + + + Azure SQL DB + Azure SQL Database + + + + + Azure SQL Data Warehouse + Azure SQL Data Warehouse + + + + + Azure SQL Stretch Database + Azure SQL Stretch Database + + + + + Path {0} is not a valid directory + La ruta de acceso [{0}] no es un directorio válido + + + + + For directory {0} a file with name {1} already exists + Ya existe un archivo {1} en el directorio '{0}' + + + + + Value {0} is too large to fit in column of type {1} + El valor {0} es muy grande para el tipo de columna {1} + + . + Parameters: 0 - value (string), 1 - columnType (string) + + + + \ No newline at end of file diff --git a/src/Microsoft.SqlTools.CoreServices/Localization/transXliff/sr.fr.xlf b/src/Microsoft.SqlTools.CoreServices/Localization/transXliff/sr.fr.xlf new file mode 100644 index 00000000..0dac86b8 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Localization/transXliff/sr.fr.xlf @@ -0,0 +1,2775 @@ + + + + + Connection parameters cannot be null + Les paramètres de connexion ne peuvent pas être null + + + + + OwnerUri cannot be null or empty + OwnerUri ne peut pas être null ou vide. + + + + + SpecifiedUri '{0}' does not have existing connection + SpecifiedUri '{0}' n’a pas de connexion existante + + . + Parameters: 0 - uri (string) + + + Invalid value '{0}' for AuthenticationType. Valid values are 'Integrated' and 'SqlLogin'. + Valeur '{0}' non valide pour AuthenticationType. Les valeurs valides sont 'Integrated' et 'SqlLogin'. + + . + Parameters: 0 - authType (string) + + + Invalid value '{0}' for ApplicationIntent. Valid values are 'ReadWrite' and 'ReadOnly'. + Valeur '{0}' non valide pour ApplicationIntent. Les valeurs valides sont 'ReadWrite' et 'ReadOnly'. + + . + Parameters: 0 - intent (string) + + + Connection canceled + Connexion annulée + + + + + OwnerUri cannot be null or empty + OwnerUri ne peut pas être null ou vide. + + + + + Connection details object cannot be null + L'objet "détails de connexion" ne peut pas être null + + + + + ServerName cannot be null or empty + ServerName ne peut pas être null ou vide + + + + + {0} cannot be null or empty when using SqlLogin authentication + {0} ne peut pas être nul ou vide quand l'authentification SqlLogin est utilisée + + . + Parameters: 0 - component (string) + + + The query has already completed, it cannot be cancelled + La requête est déjà terminée, elle ne peut pas être annulée. + + + + + Query successfully cancelled, failed to dispose query. Owner URI not found. + 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. + + + + + Query was canceled by user + La requête a été annulée par l’utilisateur + + + + + The batch has not completed, yet + Le lot n’a pas terminé encore + + + + + Batch index cannot be less than 0 or greater than the number of batches + Index de lot ne peut pas être inférieur à 0 ou supérieur au nombre de lots + + + + + Result set index cannot be less than 0 or greater than the number of result sets + L'index de résultats ne peut pas être inférieur à 0 ou supérieur au nombre de résultats + + + + + Maximum number of bytes to return must be greater than zero + Le nombre maximal d'octets à renvoyer doit être supérieur à zéro + + + + + Maximum number of chars to return must be greater than zero + Le nombre maximal de caractères à renvoyer doit être supérieur à zéro + + + + + Maximum number of XML bytes to return must be greater than zero + Le nombre maximal d’octets XML à renvoyer doit être supérieur à zéro + + + + + Access method cannot be write-only + Méthode d’accès ne peut pas être en écriture seule + + + + + FileStreamWrapper must be initialized before performing operations + FileStreamWrapper doit être initialisée avant d’effectuer des opérations + + + + + This FileStreamWrapper cannot be used for writing + Ce FileStreamWrapper ne peut pas être utilisé pour l’écriture + + + + + (1 row affected) + (1 ligne affectée) + + + + + ({0} rows affected) + ({0} lignes affectées) + + . + Parameters: 0 - rows (long) + + + Commands completed successfully. + Commandes terminées avec succès. + + + + + Msg {0}, Level {1}, State {2}, Line {3}{4}{5} + Msg {0}, au niveau état {2}, {1}, ligne {3} {4} {5} + + . + Parameters: 0 - msg (int), 1 - lvl (int), 2 - state (int), 3 - line (int), 4 - newLine (string), 5 - message (string) + + + Query failed: {0} + La requête a échoué : {0} + + . + Parameters: 0 - message (string) + + + (No column name) + (Aucun nom de colonne) + + + + + The requested query does not exist + La requête demandée n’existe pas + + + + + This editor is not connected to a database + Cet éditeur n’est pas connecté à une base de données + + + + + A query is already in progress for this editor session. Please cancel this query or wait for its completion. + Une requête est déjà en cours pour cette session d’éditeur. Veuillez annuler cette requête, ou attendre son achèvement. + + + + + Sender for OnInfoMessage event must be a SqlConnection + L’expéditeur de l’événement de OnInfoMessage doit être un objet SqlConnection + + + + + Result cannot be saved until query execution has completed + Impossible d’enregistrer les résultats jusqu'à ce que l’exécution de la requête est terminée. + + + + + Internal error occurred while starting save task + Une erreur interne s'est produite lors du démarrage de la tâche de sauvegarde. + + + + + A save request to the same path is in progress + Une requête de sauvegarde vers le même chemin est en cours + + + + + Failed to save {0}: {1} + Impossible d’enregistrer {0} : {1} + + . + Parameters: 0 - fileName (string), 1 - message (string) + + + Cannot read subset unless the results have been read from the server + Impossible de lire le sous-élément à moins que les résultats aient été lus depuis le serveur + + + + + Start row cannot be less than 0 or greater than the number of rows in the result set + La ligne de début ne peut pas être inférieure à 0 ou supérieure au nombre de lignes de résultats + + + + + Row count must be a positive integer + Le nombre de lignes doit être un entier positif + + + + + Could not retrieve column schema for result set + Impossible de récupérer le schéma des colonnes pour le jeu de résultats + + + + + Could not retrieve an execution plan from the result set + Impossible de récupérer un plan d’exécution pour le jeu de résultats + + + + + This feature is currently not supported on Azure SQL DB and Data Warehouse: {0} + Cette fonctionnalité n'est actuellement pas supportée sur Azure SQL DB et Data Warehouse : {0} + + . + Parameters: 0 - errorMessage (string) + + + An unexpected error occurred during Peek Definition execution: {0} + Une erreur inattendue s'est produite lors de l'exécution du coup d'oeil à la définition: {0}. + + . + Parameters: 0 - errorMessage (string) + + + No results were found. + Aucun résultat trouvé. + + + + + No database object was retrieved. + Aucun objet de base de données n'a été récupéré. + + + + + Please connect to a server. + Veuillez vous connecter à un serveur. + + + + + Operation timed out. + Opération a expiré. + + + + + This object type is currently not supported by this feature. + Ce type d'objet n'est actuellement pas supporté par cette fonctionnalité + + + + + Position is outside of file line range + La position est en dehors de la plage de lignes du fichier + + + + + Position is outside of column range for line {0} + La position est en dehors de la plage de colonnes pour la ligne {0} + + . + Parameters: 0 - line (int) + + + Start position ({0}, {1}) must come before or be equal to the end position ({2}, {3}) + Position de début ({0}, {1}) doit précéder ou être égale à la position de fin ({2}, {3}) + + . + Parameters: 0 - sLine (int), 1 - sCol (int), 2 - eLine (int), 3 - eCol (int) + + + Msg {0}, Level {1}, State {2}, Line {3} + Msg {0}, Niveau {1}, État {2}, Ligne {3} + + + + + Msg {0}, Level {1}, State {2}, Procedure {3}, Line {4} + Msg {0}, Niveau {1}, État {2}, Procédure {3}, Ligne {4} + + + + + Msg {0}, Level {1}, State {2} + Msg {0}, Niveau {1}, État {2} + + + + + An error occurred while the batch was being processed. The error message is: {0} + Une erreur s'est produite lors du traitement du lot. Le message d'erreur est : {0} + + + + + ({0} row(s) affected) + ({0} lignes affectées) + + + + + The previous execution is not yet complete. + L'exécution précédente n'est pas encore terminée. + + + + + A scripting error occurred. + Une erreur de script s'est produite. + + + + + Incorrect syntax was encountered while {0} was being parsed. + Une syntaxe incorrecte a été trouvée lors de l'analyse de {0}. + + + + + A fatal error occurred. + Une erreur irrécupérable s'est produite. + + + + + Batch execution completed {0} times... + L'exécution a été effectuée {0} fois... + + + + + You cancelled the query. + Vous avez annulé la requête. + + + + + An error occurred while the batch was being executed. + Une erreur s'est produite lors de l'exécution du lot. + + + + + An error occurred while the batch was being executed, but the error has been ignored. + Une erreur s'est produite lors de l'exécution du lot, mais elle a été ignorée. + + + + + Beginning execution loop + Beginning execution loop + + + + + Command {0} is not supported. + La commande {0} n'est pas prise en charge. + + + + + The variable {0} could not be found. + Impossible de trouver la variable {0}. + + + + + SQL Execution error: {0} + Erreur d’exécution de SQL : {0} + + + + + Batch parser wrapper execution: {0} found... at line {1}: {2} Description: {3} + Exécution du wrapper de l'analyseur du lot : {0} trouvé... à la ligne {1} : {2} Description : {3} + + + + + Batch parser wrapper execution engine batch message received: Message: {0} Detailed message: {1} + Message reçu du lot du moteur d'exécution du wrapper de l'analyseur du lot : Message : {0} Message détaillé : {1} + + + + + Batch parser wrapper execution engine batch ResultSet processing: 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} + + + + + Batch parser wrapper execution engine batch ResultSet finished. + ResultSet du lot du moteur d'exécution du wrapper de l'analyseur du lot terminé. + + + + + Canceling batch parser wrapper batch execution. + Annulation de l'exécution du lot du wrapper de l'analyseur du lot. + + + + + Scripting warning. + Avertissement de script. + + + + + For more information about this error, see the troubleshooting topics in the product documentation. + Pour plus d'informations sur cette erreur, consultez les rubriques de dépannage dans la documentation du produit. + + + + + File '{0}' recursively included. + Le fichier '{0}' a été inclus de manière récursive. + + + + + Missing end comment mark '*/'. + La marque de commentaire de fin '*/' est manquante. + + + + + Unclosed quotation mark after the character string. + Guillemets non fermés après la chaîne de caractères. + + + + + Incorrect syntax was encountered while parsing '{0}'. + Détection d'une syntaxe incorrecte pendant l'analyse de '{0}'. + + + + + Variable {0} is not defined. + La variable {0} n'est pas définie. + + + + + test + test + + + + + Replacement of an empty string by an empty string. + Remplacement d’une chaîne vide à une chaîne vide. + + + + + Edit session does not exist. + La session d'édition n’existe pas. + + + + + Query has not completed execution + La requête n’a pas terminé l’exécution + + + + + Query did not generate exactly one result set + La requête n’a pas généré exactement un jeu de résultats + + + + + Failed to add new row to update cache + Impossible d’ajouter la nouvelle ligne pour mettre à jour le cache + + + + + Given row ID is outside the range of rows in the edit cache + L'identifiant de ligne spécifié est en dehors de la plage de lignes dans le cache d’édition + + + + + An update is already pending for this row and must be reverted first + Une mise à jour est déjà en attente pour cette ligne et doit être d’abord annulée + + + + + Given row ID does not have pending update + L'identifiant de la ligne n'a pas de mise à jour en attente + + + + + Table or view metadata could not be found + Les métadonnées de la table ou de la vue n’ont pas pu être trouvées + + + + + Invalid format for binary column + Format invalide pour une colonne binary + + + + + Allowed values for boolean columns are 0, 1, "true", or "false" + Les colonnes booléennes doivent être un numérique 1 ou 0, ou une chaîne true ou false + + + + + The column '{0}' is defined as NOT NULL but was not given a value + Une valeur de cellule requise est manquante. + + . + Parameters: 0 - colName (string) + + + A delete is pending for this row, a cell update cannot be applied. + Une suppression est en attente pour cette ligne, une mise à jour de cellule ne peut pas être appliquée. + + + + + Column ID must be in the range of columns for the query + La colonne Id doit être dans la plage des colonnes de la requête + + + + + Column cannot be edited + La colonne ne peut pas être éditée + + + + + No key columns were found + Aucune colonne clé n'a été trouvée + + + + + An output filename must be provided + Un nom de fichier de sortie doit être fourni + + + + + Database object {0} cannot be used for editing. + L'objet de base de données {0} ne peut pas être utilisé pour éditer + + . + Parameters: 0 - typeName (string) + + + Specified URI '{0}' does not have a default connection + L'Uri spécifiée '{0}' n’a pas de connexion par défaut + + . + Parameters: 0 - uri (string) + + + A commit task is in progress. Please wait for completion. + Une tâche commit est en cours. Veuillez, s'il vous plaît, attendre la fin. + + + + + Decimal column is missing numeric precision or numeric scale + La colonne decimal manque d'une précision numérique + + + + + <TBD> + <TBD> + + + + + Cannot add row to result buffer, data reader does not contain rows + Impossible d'ajouter une ligne au tampon de résultats, le data reader ne contient aucune ligne + + + + + TIME column values must be between 00:00:00.0000000 and 23:59:59.9999999 + Les valeurs de colonne TIME doivent être contenues entre 00:00:00.0000000 et 23:59:59.9999999 + + + + + NULL is not allowed for this column + NULL n'est pas autorisé pour cette colonne + + + + + Edit session already exists. + La session d'édition existe déjà. + + + + + Edit session has not been initialized + La session d'édition n'a pas été initialisée + + + + + Edit session has already been initialized + La session d'édition a déjà été initialisée + + + + + Edit session has already been initialized or is in the process of initializing + La session d'édition a déjà été initialisée ou est en cours d'initialisation + + + + + Query execution failed, see messages for details + L'exécution de la requête a échoué, voir les messages pour plus de détails + + + + + Result limit cannot be negative + La limite de résultat ne peut pas être négative + + + + + NULL + NULL + + + + + A object name must be provided + Un nom d'objet doit être fourni + + + + + Explicitly specifying server or database is not supported + La spécification explicite du serveur ou de la base de données n'est pas pris en charge + + + + + Table metadata does not have extended properties + Les métadonnées de tables n'ont pas de propriétés étendues + + + + + Table or view requested for edit could not be found + La table ou la vue demandée pour édition n'a pas pu être trouvée + + + + + Error expanding: {0} + Erreur en développant : {0} + + + + + Error connecting to {0} + Erreur en se connectant à {0} + + + + + Aggregates + Agrégats + + + + + Server Roles + Rôles serveur + + + + + Application Roles + Rôles d'application + + + + + Assemblies + Assemblys + + + + + Assembly Files + Fichiers d'assembly + + + + + Asymmetric Keys + Clés asymétriques + + + + + Asymmetric Keys + Clés asymétriques + + + + + Data Compression Options + Options de compression de données + + + + + Certificates + Certificats + + + + + FileTables + FileTables + + + + + Certificates + Certificats + + + + + Check Constraints + Contraintes de validation + + + + + Columns + Colonnes + + + + + Constraints + Contraintes + + + + + Contracts + Contrats + + + + + Credentials + Informations d'identification + + + + + Error Messages + Messages d'erreur + + + + + Server Role Membership + Appartenance au rôle de serveur + + + + + Database Options + Options de la base de données + + + + + Database Roles + Rôles de base de données + + + + + Role Memberships + Appartenances aux rôles + + + + + Database Triggers + Déclencheurs de base de données + + + + + Default Constraints + Contraintes par défaut + + + + + Defaults + Par défaut + + + + + Sequences + Séquences + + + + + Endpoints + Points de terminaison + + + + + Event Notifications + Notifications d'événements + + + + + Server Event Notifications + Notifications d'événements du serveur + + + + + Extended Properties + Propriétés étendues + + + + + Filegroups + Groupes de fichiers + + + + + Foreign Keys + Clés étrangères + + + + + Full-Text Catalogs + Catalogues de recherche en texte intégral + + + + + Full-Text Indexes + Index de recherche en texte intégral + + + + + Functions + Fonctions + + + + + Indexes + Index + + + + + Inline Functions + Fonctions incluses + + + + + Keys + Clés + + + + + Linked Servers + Serveurs liés + + + + + Linked Server Logins + Connexions de serveur lié + + + + + Logins + Connexions + + + + + Master Key + Clé principale + + + + + Master Keys + Clés principales + + + + + Message Types + Types de messages + + + + + Table-Valued Functions + Fonctions table + + + + + Parameters + Paramètres + + + + + Partition Functions + Fonctions de partition + + + + + Partition Schemes + Schémas de partition + + + + + Permissions + Autorisations + + + + + Primary Keys + Clés primaires + + + + + Programmability + Programmabilité + + + + + Queues + Files d'attente + + + + + Remote Service Bindings + Liaisons de service distant + + + + + Returned Columns + Colonnes retournées + + + + + Roles + Rôles + + + + + Routes + Itinéraires  + + + + + Rules + Règles + + + + + Schemas + Schémas + + + + + Security + Sécurité + + + + + Server Objects + Objets serveur + + + + + Management + Gestion + + + + + Triggers + Déclencheurs + + + + + Service Broker + Service Broker + + + + + Services + Services + + + + + Signatures + Signatures + + + + + Log Files + Fichiers journaux + + + + + Statistics + Statistiques + + + + + Storage + Stockage + + + + + Stored Procedures + Procédures stockées + + + + + Symmetric Keys + Clés symétriques + + + + + Synonyms + Synonymes + + + + + Tables + Tables + + + + + Triggers + Déclencheurs + + + + + Types + Types + + + + + Unique Keys + Clés uniques + + + + + User-Defined Data Types + Types de données définis par l'utilisateur + + + + + User-Defined Types (CLR) + Types définis par l'utilisateur (CLR) + + + + + Users + Utilisateurs + + + + + Views + Vues + + + + + XML Indexes + Index XML + + + + + XML Schema Collections + Collections de schémas XML + + + + + User-Defined Table Types + Types de tables définis par l'utilisateur + + + + + Files + Fichiers + + + + + Missing Caption + Légende manquante + + + + + Broker Priorities + Priorités de Service Broker + + + + + Cryptographic Providers + Fournisseurs de chiffrement + + + + + Database Audit Specifications + Spécifications de l'audit de la base de données + + + + + Database Encryption Keys + Clés de chiffrement de la base de données + + + + + Event Sessions + Sessions d'événements + + + + + Full Text Stoplists + Listes de mots vides de texte intégral + + + + + Resource Pools + Pools de ressources + + + + + Audits + Audits + + + + + Server Audit Specifications + Spécifications de l'audit du serveur + + + + + Spatial Indexes + Index spatiaux + + + + + Workload Groups + Groupes de charges de travail + + + + + SQL Files + Fichiers SQL + + + + + Server Functions + Fonctions du serveur + + + + + SQL Type + Type SQL + + + + + Server Options + Options de serveur + + + + + Database Diagrams + Schémas de base de données + + + + + System Tables + Tables système + + + + + Databases + Bases de données + + + + + System Contracts + Contrats système + + + + + System Databases + Bases de données système + + + + + System Message Types + Types de messages système + + + + + System Queues + Files d'attente système + + + + + System Services + Services système + + + + + System Stored Procedures + Procédures stockées système + + + + + System Views + Vues système + + + + + Data-tier Applications + Applications de la couche Données + + + + + Extended Stored Procedures + Procédures stockées étendues + + + + + Aggregate Functions + Fonctions d'agrégation + + + + + Approximate Numerics + Valeurs numériques approximatives + + + + + Binary Strings + Chaînes binaires + + + + + Character Strings + Chaînes de caractères + + + + + CLR Data Types + Types de données CLR + + + + + Configuration Functions + Fonctions de configuration + + + + + Cursor Functions + Fonctions du curseur + + + + + System Data Types + Types de données système + + + + + Date and Time + Date et heure + + + + + Date and Time Functions + Fonctions de date et d'heure + + + + + Exact Numerics + Valeurs numériques exactes + + + + + System Functions + Fonctions système + + + + + Hierarchy Id Functions + Fonctions de l'ID de hiérarchie + + + + + Mathematical Functions + Fonctions mathématiques + + + + + Metadata Functions + Fonctions de métadonnées + + + + + Other Data Types + Autres types de données + + + + + Other Functions + Autres fonctions + + + + + Rowset Functions + Fonctions d'ensemble de lignes + + + + + Security Functions + Fonctions de sécurité + + + + + Spatial Data Types + Types de données spatiales + + + + + String Functions + Fonctions de chaîne + + + + + System Statistical Functions + Fonctions statistiques système + + + + + Text and Image Functions + Fonctions de texte et d'image + + + + + Unicode Character Strings + Chaînes de caractères Unicode + + + + + Aggregate Functions + Fonctions d'agrégation + + + + + Scalar-valued Functions + Fonctions scalaires + + + + + Table-valued Functions + Fonctions table + + + + + System Extended Stored Procedures + Procédures stockées étendues système + + + + + Built-in Types + Types intégrés + + + + + Built-in Server Roles + Rôles serveur intégrés + + + + + User with Password + Utilisateur avec mot de passe + + + + + Search Property List + Liste des propriétés de recherche + + + + + Security Policies + Stratégies de sécurité + + + + + Security Predicates + Prédicats de sécurité + + + + + Server Role + Rôle de serveur + + + + + Search Property Lists + Listes des propriétés de recherche + + + + + Column Store Indexes + Index de stockage de colonnes + + + + + Table Type Indexes + Index de types de tables + + + + + Selective XML Indexes + Index XML sélectifs + + + + + XML Namespaces + Espaces de noms XML + + + + + XML Typed Promoted Paths + Chemins d'accès promus typés XML + + + + + T-SQL Typed Promoted Paths + Chemins d'accès promus typés T-SQL + + + + + Database Scoped Credentials + Informations d'identification incluses dans l'étendue de la base de données + + + + + External Data Sources + Sources de données externes + + + + + External File Formats + Formats de fichier externes + + + + + External Resources + Ressources externes + + + + + External Tables + Tables externes + + + + + Always Encrypted Keys + Clés Always Encrypted + + + + + Column Master Keys + Clés principales de la colonne + + + + + Column Encryption Keys + Clés de chiffrement de la colonne + + + + + Server + Serveur + + + + + Error parsing ScriptingParams.ConnectionString property. + Erreur en analysant la propriété ScriptingParams.ConnectionString. + + + + + Invalid directory specified by the ScriptingParams.FilePath property. + Répertoire invalide spécifié pour la propriété ScriptingParams.FilePath. + + + + + Error parsing ScriptingListObjectsCompleteParams.ConnectionString property. + Erreur en analysant la propriété ScriptingListObjectsCompleteParams.ConnectionString. + + + + + {0} ({1}, {2}, {3}) + {0} ({1}, {2}, {3}) + + + + + No default + Pas de valeur par défaut + + + + + Input + Entrée + + + + + Input/Output + Entrée/sortie + + + + + Input/ReadOnly + Entrée/ReadOnly + + + + + Input/Output/ReadOnly + Entrée/sortie/ReadOnly + + + + + Default + Par défaut + + + + + null + Null + + + + + not null + Non Null + + + + + {0} ({1}, {2}) + {0} ({1}, {2}) + + + + + {0} ({1}) + {0} ({1}) + + + + + {0} ({1}Computed, {2}, {3}) + {0} ({1}Calculé, {2}, {3}) + + + + + {0} ({1}Computed) + {0} ({1}Calculé) + + + + + {0} (Column Set, {1}) + {0} (Jeu de colonnes, {1}) + + + + + {0} (Column Set, {1}{2}, {3}) + {0} (Jeu de colonnes, {1}{2}, {3}) + + + + + {0} (Column Set, {1}, {2}, {3}) + {0} (Jeu de colonnes, {1}, {2}, {3}) + + + + + Unique + Unique + + + + + Non-Unique + Non unique + + + + + Clustered + Ordonné en clusters + + + + + Non-Clustered + Non-Clustere + + + + + History + Historique + + + + + System-Versioned + System-Versioned + + + + + Unavailable + Indisponible + + + + + Current default filegroup: {0} + Groupe de fichiers par défaut actuel : {0} + + + + + New Filegroup for {0} + Nouveau groupe de fichiers pour {0} + + + + + Default + Par défaut + + + + + Files + Fichiers + + + + + Name + Nom + + + + + Read-Only + Lecture seule + + + + + Autogrowth / Maxsize + Redimensionnement automatique / Taille max + + + + + ... + ... + + + + + <default> + <par défaut> + + + + + Filegroup + Groupe de fichiers + + + + + Logical Name + Nom logique + + + + + File Type + Type de fichier + + + + + Initial Size (MB) + Taille initiale (Mo) + + + + + <new filegroup> + <new filegroup> + + + + + Path + Chemin d'accès + + + + + File Name + Nom de fichier  + + + + + <raw device> + <raw device> + + + + + Bulk-logged + Bulk-logged + + + + + Full + Full + + + + + Simple + Simple + + + + + Select Database Owner + Sélectionner le propriétaire de base de données + + + + + None + Aucune + + + + + By {0} MB, Limited to {1} MB + Par {0} Mo, Limité à {1} Mo + + + + + By {0} percent, Limited to {1} MB + Par {0} %, Limité à {1} Mo + + + + + By {0} MB, Unlimited + Par {0} Mo, Illimité + + + + + By {0} percent, Unlimited + Par {0} %, Illimité + + + + + Unlimited + Illimité + + + + + Limited to {0} MB + Limité à {0} Mo + + + + + Automatic + Automatique + + + + + Service Broker + Service Broker + + + + + Collation + Classement + + + + + Cursor + Curseur + + + + + Miscellaneous + Divers + + + + + Recovery + Restauration + + + + + State + État + + + + + ANSI NULL Default + Paramètre par défaut ANSI NULL + + + + + ANSI NULLS Enabled + Valeurs ANSI NULLS activées + + + + + ANSI Padding Enabled + Padding ANSI activé + + + + + ANSI Warnings Enabled + ANSI Warnings activés + + + + + Arithmetic Abort Enabled + Annulation arithmétique (Arithmetic Abort) activée + + + + + Auto Close + Fermeture automatique + + + + + Auto Create Statistics + Création automatique des statistiques + + + + + Auto Shrink + Réduction automatique + + + + + Auto Update Statistics + Mise à jour automatique des statistiques + + + + + Auto Update Statistics Asynchronously + Mise à jour automatique des statistiques en mode asynchrone + + + + + Case Sensitive + Sensible à la casse + + + + + Close Cursor on Commit Enabled + Fermeture du curseur lors de la validation activée + + + + + Collation + Classement + + + + + Concatenate Null Yields Null + La concaténation de la valeur Null donne Null + + + + + Database Compatibility Level + Niveau de compatibilité de la base de données + + + + + Database State + État de la base de données + + + + + Default Cursor + Curseur par défaut + + + + + Full-Text Indexing Enabled + Indexation de texte intégral activée + + + + + Numeric Round-Abort + Abandon en cas d'arrondi numérique + + + + + Page Verify + Vérification de la page : + + + + + Quoted Identifiers Enabled + Identificateurs entre guillemets activés + + + + + Database Read-Only + Base de données en lecture seule + + + + + Recursive Triggers Enabled + Déclencheurs récursifs activés + + + + + Restrict Access + Restreindre l'accès + + + + + Select Into/Bulk Copy + Select Into / Bulk Copy + + + + + Honor Broker Priority + Priorité du service Broker respectée + + + + + Service Broker Identifier + Identifant de Service Broker + + + + + Broker Enabled + Broker activé + + + + + Truncate Log on Checkpoint + Truncate Log on Checkpoint + + + + + Cross-database Ownership Chaining Enabled + Chaînage des propriétés des bases de données croisées activé + + + + + Trustworthy + Digne de confiance + + + + + Date Correlation Optimization Enabled + Date Correlation Optimization Enabledprototype_db_prop_parameterization = Parameterization + + + + + Forced + Forcé + + + + + Simple + Simple + + + + + ROWS Data + Données ROWS + + + + + LOG + LOG + + + + + FILESTREAM Data + Données FILESTREAM + + + + + Not Applicable + Non applicable + + + + + <default path> + <default path> + + + + + Open Connections + Ouvrir les connexions + + + + + To change the database properties, SQL Server must close all other connections to the database_ Are you sure you want to change the properties and close all other connections? + 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 + AUTO_CLOSED + + + + + EMERGENCY + EMERGENCY + + + + + INACCESSIBLE + INACCESSIBLE + + + + + NORMAL + NORMAL + + + + + OFFLINE + OFFLINE + + + + + RECOVERING + RECOVERING + + + + + RECOVERY PENDING + RECOVERY PENDING + + + + + RESTORING + RESTORING + + + + + SHUTDOWN + SHUTDOWN + + + + + STANDBY + STANDBY + + + + + SUSPECT + SUSPECT + + + + + GLOBAL + GLOBAL + + + + + LOCAL + LOCAL + + + + + MULTI_USER + MULTI_USER + + + + + RESTRICTED_USER + RESTRICTED_USER + + + + + SINGLE_USER + SINGLE_USER + + + + + CHECKSUM + CHECKSUM + + + + + NONE + NONE + + + + + TORN_PAGE_DETECTION + TORN_PAGE_DETECTION + + + + + VarDecimal Storage Format Enabled + Format de stockage VarDecimal activé + + + + + SQL Server 2008 (100) + SQL Server 2008 (100) + + + + + Encryption Enabled + Chiffrement activé + + + + + OFF + OFF + + + + + ON + ON + + + + + PRIMARY + PRIMARY + + + + + For the distribution policy HASH, the number of leading hash columns is optional but should be from 1 to 16 columns + 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 2012 (110) + + + + + SQL Server 2014 (120) + SQL Server 2014 (120) + + + + + SQL Server 2016 (130) + SQL Server 2016 (130) + + + + + SQL Server vNext (140) + SQL Server vNext (140) + + + + + None + Aucun + + + + + Partial + Partiel + + + + + FILESTREAM Files + Fichiers FILESTREAM + + + + + No Applicable Filegroup + Aucun groupe de fichiers applicable + + + + + The database {0} is not accessible. + La base de données {0} est inaccessible. + + + + + Query has no results to return + La requête n'a aucun résultat à retourner + + + + + Result set has too many rows to be safely loaded + Le jeu de résultats a trop de lignes pour être chargé en toute sécurité + + + + Parameterization + Paramétrage + + + + + Specifying this option when restoring a backup with the NORECOVERY option is not permitted. + La spécification de cette option lors de la restauration d'une sauvegarde avec l'option NORECOVERY n'est pas permise. + + + + + Invalid path for database file: '{0}' + Chemin d'accès non valide pour le fichier de base de données : « {0} » + + + + + Log + Journal + + + + + Failed to create restore plan + Échec de la création du plan de restauration + + + + + Restore database is not supported + La restauration de la base de données n'est pas supportée + + + + + Restore Database + Restaurer la base de données + + + + + (Copy Only) + (Copie seule) + + + + + Component + Composant + + + + + Type + Type + + + + + Server + Serveur  + + + + + Database + Base de données  + + + + + Position + Position + + + + + First LSN + Premier NSE + + + + + Last LSN + Dernier NSE + + + + + Checkpoint LSN + NSE du point de contrôle + + + + + Full LSN + Tous les NSE + + + + + Start Date + Date de début + + + + + Finish Date + Date de fin + + + + + Size + Taille + + + + + User Name + Nom d'utilisateur  + + + + + Expiration + Expiration  + + + + + Name + Nom  + + + + + The last backup taken ({0}) + La dernière sauvegarde effectuée ({0}) + + + + + Backup Database + Sauvegarder la base de données + + + + + In progress + Opération en cours + + + + + Completed + Terminé + + + + + scripting + script + + + + + Connection not found + Connexion introuvable + + + + + Please provide a file path instead of directory path + Le nom de fichier spécifié est également un nom de répertoire: {0} + + + + + The provided path is invalid + Impossible de vérifier l'existence de l'emplacement du fichier de sauvegarde: {0} + + + + + Cannot access the specified path on the server: {0} + Impossible d'accéder au chemin d'accès spécifié sur le serveur: {0} + + + + + No backupset selected to be restored + Aucun jeu de sauvegarde n'a été sélectionné pour être restauré. + + + + + Never + Jamais + + + + + Azure SQL DB + Azure SQL DB + + + + + Azure SQL Data Warehouse + Azure SQL Data Warehouse + + + + + Azure SQL Stretch Database + Azure SQL Stretch Database + + + + + Path {0} is not a valid directory + Le chemin {0} n'est pas un répertoire valide. + + + + + For directory {0} a file with name {1} already exists + Pour le répertoire {0} un fichier avec le nom {1} existe déjà + + + + + Value {0} is too large to fit in column of type {1} + La valeur {0} est trop grande pour tenir dans la colonne de type {1} + + . + Parameters: 0 - value (string), 1 - columnType (string) + + + + \ No newline at end of file diff --git a/src/Microsoft.SqlTools.CoreServices/Localization/transXliff/sr.it.xlf b/src/Microsoft.SqlTools.CoreServices/Localization/transXliff/sr.it.xlf new file mode 100644 index 00000000..a0e5730d --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Localization/transXliff/sr.it.xlf @@ -0,0 +1,2775 @@ + + + + + Connection parameters cannot be null + Parametri di connessione non possono essere null + + + + + OwnerUri cannot be null or empty + OwnerUri non può essere null o vuoto + + + + + SpecifiedUri '{0}' does not have existing connection + SpecifiedUri: '{0}' non dispone di connessione esistente + + . + Parameters: 0 - uri (string) + + + Invalid value '{0}' for AuthenticationType. Valid values are 'Integrated' and 'SqlLogin'. + Valore non valido: '{0}' per AuthenticationType. I valori validi sono 'Integrated' e 'SqlLogin'. + + . + Parameters: 0 - authType (string) + + + Invalid value '{0}' for ApplicationIntent. Valid values are 'ReadWrite' and 'ReadOnly'. + Valore '{0}' non valido per ApplicationIntent. I valori validi sono 'ReadWrite' e 'ReadOnly'. + + . + Parameters: 0 - intent (string) + + + Connection canceled + Connessione annullata + + + + + OwnerUri cannot be null or empty + OwnerUri non può essere null o vuoto + + + + + Connection details object cannot be null + L'oggetto Dettagli di connessione non può essere null + + + + + ServerName cannot be null or empty + ServerName non può essere null o vuoto + + + + + {0} cannot be null or empty when using SqlLogin authentication + {0} non può essere null o vuoto quando si utilizza l'autenticazione SqlLogin + + . + Parameters: 0 - component (string) + + + The query has already completed, it cannot be cancelled + La query è già stata completata e non può essere annullata + + + + + Query successfully cancelled, failed to dispose query. Owner URI not found. + Query annullata correttamente, impossibile eliminare query. URI proprietario non trovato. + + + + + Query was canceled by user + Query annullata dall'utente + + + + + The batch has not completed, yet + Il batch non è ancora stato completato + + + + + Batch index cannot be less than 0 or greater than the number of batches + Indice di batch non può essere minore di 0 o maggiore del numero di batch + + + + + Result set index cannot be less than 0 or greater than the number of result sets + Indice di set di risultati non può essere minore di 0 o maggiore del numero di set di risultati + + + + + Maximum number of bytes to return must be greater than zero + Numero massimo di byte da restituire deve essere maggiore di zero + + + + + Maximum number of chars to return must be greater than zero + Numero massimo di caratteri da restituire deve essere maggiore di zero + + + + + Maximum number of XML bytes to return must be greater than zero + Numero massimo di byte XML da restituire deve essere maggiore di zero + + + + + Access method cannot be write-only + Il metodo di accesso non può essere in sola scrittura + + + + + FileStreamWrapper must be initialized before performing operations + FileStreamWrapper deve essere inizializzato prima di eseguire operazioni + + + + + This FileStreamWrapper cannot be used for writing + Questo FileStreamWrapper non può essere utilizzato per la scrittura + + + + + (1 row affected) + (1 riga interessata) + + + + + ({0} rows affected) + ({0} righe interessate) + + . + Parameters: 0 - rows (long) + + + Commands completed successfully. + Comandi completati correttamente. + + + + + Msg {0}, Level {1}, State {2}, Line {3}{4}{5} + Msg {0}, Livello {1}, Stato {2}, Riga {3} {4} {5} + + . + Parameters: 0 - msg (int), 1 - lvl (int), 2 - state (int), 3 - line (int), 4 - newLine (string), 5 - message (string) + + + Query failed: {0} + Query non riuscita: {0} + + . + Parameters: 0 - message (string) + + + (No column name) + (Nessun nome di colonna) + + + + + The requested query does not exist + La query richiesta non esiste + + + + + This editor is not connected to a database + Questo editor non è connesso a un database + + + + + A query is already in progress for this editor session. Please cancel this query or wait for its completion. + Una query è già in corso per questa sessione dell'editor. Annullare la query o attendere il completamento. + + + + + Sender for OnInfoMessage event must be a SqlConnection + Mittente per l'evento OnInfoMessage deve essere un oggetto SqlConnection + + + + + Result cannot be saved until query execution has completed + Non è possibile salvare il risultato finché non viene completata l'esecuzione della query + + + + + Internal error occurred while starting save task + Errore interno durante l'avvio del task di salvataggio + + + + + A save request to the same path is in progress + È in corso una richiesta di salvataggio sullo stesso percorso + + + + + Failed to save {0}: {1} + Impossibile salvare {0}: {1} + + . + Parameters: 0 - fileName (string), 1 - message (string) + + + Cannot read subset unless the results have been read from the server + Impossibile leggere sottoinsieme a meno che i risultati sono stati letti dal server + + + + + Start row cannot be less than 0 or greater than the number of rows in the result set + Riga di inizio non può essere minore di 0 o maggiore del numero di righe nel set di risultati + + + + + Row count must be a positive integer + Il numero di righe deve essere un numero intero positivo + + + + + Could not retrieve column schema for result set + Impossibile recuperare schema di colonne per set di risultati + + + + + Could not retrieve an execution plan from the result set + Impossibile recuperare un piano di esecuzione dal set di risultati + + + + + This feature is currently not supported on Azure SQL DB and Data Warehouse: {0} + Questa funzionalità non è supportata su DB SQL Azure e Data Warehouse: {0} + + . + Parameters: 0 - errorMessage (string) + + + An unexpected error occurred during Peek Definition execution: {0} + Si è verificato un errore imprevisto durante l'esecuzione di definizione Peek: {0} + + . + Parameters: 0 - errorMessage (string) + + + No results were found. + Nessun risultato trovato. + + + + + No database object was retrieved. + Non è stato recuperato alcun oggetto di database. + + + + + Please connect to a server. + Connettersi a un server. + + + + + Operation timed out. + Timeout dell'operazione. + + + + + This object type is currently not supported by this feature. + Questo tipo di oggetto non è supportato da questa funzionalità. + + + + + Position is outside of file line range + La posizione non rientra nell'intervallo di righe del file + + + + + Position is outside of column range for line {0} + Posizione non rientra nell'intervallo di colonne per riga {0} + + . + Parameters: 0 - line (int) + + + Start position ({0}, {1}) must come before or be equal to the end position ({2}, {3}) + Posizione iniziale ({0}, {1}) deve essere precedente o uguale alla posizione finale ({2}, {3}) + + . + Parameters: 0 - sLine (int), 1 - sCol (int), 2 - eLine (int), 3 - eCol (int) + + + Msg {0}, Level {1}, State {2}, Line {3} + Msg. {0}, Livello {1}, Stato {2}, Riga {3} + + + + + Msg {0}, Level {1}, State {2}, Procedure {3}, Line {4} + Msg. {0}, Livello {1}, Stato {2}, Procedura {3}, Riga {4} + + + + + Msg {0}, Level {1}, State {2} + Msg. {0}, Livello {1}, Stato {2} + + + + + An error occurred while the batch was being processed. The error message is: {0} + Si è verificato un errore durante l'elaborazione batch. Messaggio di errore: {0} + + + + + ({0} row(s) affected) + ({0} righe interessate dall'operazione) + + + + + The previous execution is not yet complete. + L'esecuzione precedente non è ancora completa. + + + + + A scripting error occurred. + Si è verificato un errore di scripting. + + + + + Incorrect syntax was encountered while {0} was being parsed. + Sintassi errata rilevata durante l'analisi di '{0}'. + + + + + A fatal error occurred. + Si è verificato un errore irreversibile. + + + + + Batch execution completed {0} times... + Esecuzione completata {0} volte... + + + + + You cancelled the query. + È stata annullata la query. + + + + + An error occurred while the batch was being executed. + Si è verificato un errore durante l'esecuzione del batch. + + + + + An error occurred while the batch was being executed, but the error has been ignored. + Si è verificato un errore durante l'esecuzione del batch, ma l'errore è stato ignorato. + + + + + Beginning execution loop + Beginning execution loop + + + + + Command {0} is not supported. + Il comando {0} non è supportato. + + + + + The variable {0} could not be found. + Impossibile trovare la variabile {0}. + + + + + SQL Execution error: {0} + Errore di esecuzione di SQL: {0} + + + + + Batch parser wrapper execution: {0} found... at line {1}: {2} Description: {3} + Esecuzione del wrapper parser batch: trovati {0}... alla riga {1}: {2} Descrizione: {3} + + + + + Batch parser wrapper execution engine batch message received: Message: {0} Detailed message: {1} + Motore di esecuzione wrapper parser di batch, ricevuto messaggio batch: messaggio: {0} messaggio dettagliato: {1} + + + + + Batch parser wrapper execution engine batch ResultSet processing: DataReader.FieldCount: {0} DataReader.RecordsAffected: {1} + Motore di esecuzione wrapper parser di batch, elaborazione batch di ResultSet: DataReader.FieldCount: {0} DataReader.RecordsAffected: {1} + + + + + Batch parser wrapper execution engine batch ResultSet finished. + Motore di esecuzione wrapper parser di batch, batch di ResultSet completato. + + + + + Canceling batch parser wrapper batch execution. + Annullamento dell'esecuzione batch del wrapper parser batch. + + + + + Scripting warning. + Avviso di script. + + + + + For more information about this error, see the troubleshooting topics in the product documentation. + Per ulteriori informazioni su questo errore, vedere gli argomenti sulla risoluzione dei problemi nella documentazione del prodotto. + + + + + File '{0}' recursively included. + File '{0}' incluso ricorsivamente. + + + + + Missing end comment mark '*/'. + Marker ' * /' di fine commento mancante. + + + + + Unclosed quotation mark after the character string. + Virgolette mancanti alla fine della stringa di caratteri. + + + + + Incorrect syntax was encountered while parsing '{0}'. + Sintassi errata rilevata durante l'analisi di '{0}'. + + + + + Variable {0} is not defined. + Variabile {0} non è definita. + + + + + test + test + + + + + Replacement of an empty string by an empty string. + Sostituzione di una stringa vuota con una stringa vuota. + + + + + Edit session does not exist. + La sessione di editing non esiste. + + + + + Query has not completed execution + Esecuzione query non completata + + + + + Query did not generate exactly one result set + La query non ha generato esattamente un insieme di risultati + + + + + Failed to add new row to update cache + Errore nell'aggiunta di una riga durante l'aggiornamento della cache + + + + + Given row ID is outside the range of rows in the edit cache + L'ID riga specificato è fuori dal range di righe della cache della modifica + + + + + An update is already pending for this row and must be reverted first + Un aggiornamento di questa riga è già in corso e dev'essere annullato prima di procedere + + + + + Given row ID does not have pending update + Questo ID di riga non ha aggiornamenti in corso + + + + + Table or view metadata could not be found + Metadati della tabella o della vista non trovati + + + + + Invalid format for binary column + Formato non valido per una colonna binaria + + + + + Allowed values for boolean columns are 0, 1, "true", or "false" + Colonne booleane devono contenere valori numerici 0 o 1, o stringhe true o false + + + + + The column '{0}' is defined as NOT NULL but was not given a value + Il valore di cella richiesto è mancante + + . + Parameters: 0 - colName (string) + + + A delete is pending for this row, a cell update cannot be applied. + La cancellazione di questa riga è in corso, impossibile aggiornare la cella. + + + + + Column ID must be in the range of columns for the query + L'ID della colonna dev'essere incluso nel range delle colonne della query + + + + + Column cannot be edited + Impossibile modificare la colonna + + + + + No key columns were found + Impossibile trovare colonne chiave + + + + + An output filename must be provided + Occorre fornire un nome di file di output + + + + + Database object {0} cannot be used for editing. + L'oggetto {0} del database non può essere usato per la modifica. + + . + Parameters: 0 - typeName (string) + + + Specified URI '{0}' does not have a default connection + L'URI specificato '{0}' non ha una connessione di default + + . + Parameters: 0 - uri (string) + + + A commit task is in progress. Please wait for completion. + Azione commit in corso - attenderne il completamento. + + + + + Decimal column is missing numeric precision or numeric scale + Precisione o scala mancante nella colonna Decimal + + + + + <TBD> + <TBD> + + + + + Cannot add row to result buffer, data reader does not contain rows + Impossibile aggiungere una riga al buffer risultati - il datareader non contiene righe + + + + + TIME column values must be between 00:00:00.0000000 and 23:59:59.9999999 + I valori della colonna Time devono essere compresi tra 00:00:00.0000000 e 23:59:59.9999999 + + + + + NULL is not allowed for this column + NULL non è consentito per questa colonna + + + + + Edit session already exists. + La sessione di editing esiste già. + + + + + Edit session has not been initialized + La sessione di editing non è stata inizializzata. + + + + + Edit session has already been initialized + La sessione di editing è già stata inizializzata. + + + + + Edit session has already been initialized or is in the process of initializing + La sessione di editing è già stata inizializzata o è in fase di inizializzazione + + + + + Query execution failed, see messages for details + Esecuzione della query fallita - vedere i messaggi per ulteriori dettagli + + + + + Result limit cannot be negative + Il limite del risultato non può essere negativo + + + + + NULL + NULL + + + + + A object name must be provided + Il nome dell'oggetto è obbligatorio + + + + + Explicitly specifying server or database is not supported + Non è possibile specificare in modo esplicito il nome di un server o di un database + + + + + Table metadata does not have extended properties + Nessuna proprietà estesa per la tabella + + + + + Table or view requested for edit could not be found + Impossibile trovare la Tabella o la Vista necessarie alla modifica + + + + + Error expanding: {0} + Errore durante l'espansione dell'oggetto: {0} + + + + + Error connecting to {0} + Errore durante la connessione a {0}' + + + + + Aggregates + Aggregazioni + + + + + Server Roles + Ruoli del server + + + + + Application Roles + Ruoli applicazione + + + + + Assemblies + Assembly + + + + + Assembly Files + File di assembly + + + + + Asymmetric Keys + Chiavi asimmetriche + + + + + Asymmetric Keys + Chiavi asimmetriche + + + + + Data Compression Options + Opzioni di compressione dati + + + + + Certificates + Certificati + + + + + FileTables + Tabelle file + + + + + Certificates + Certificati + + + + + Check Constraints + Vincoli CHECK + + + + + Columns + Colonne + + + + + Constraints + Vincoli + + + + + Contracts + Contratti + + + + + Credentials + Credenziali + + + + + Error Messages + Messaggi di errore + + + + + Server Role Membership + Appartenenze al ruolo del server + + + + + Database Options + Opzioni database + + + + + Database Roles + Ruoli database + + + + + Role Memberships + Appartenenze a ruoli + + + + + Database Triggers + Trigger database + + + + + Default Constraints + Vincoli predefiniti + + + + + Defaults + Impostazioni predefinite + + + + + Sequences + Sequenze + + + + + Endpoints + Endpoint + + + + + Event Notifications + Notifiche degli eventi + + + + + Server Event Notifications + Notifiche degli eventi server + + + + + Extended Properties + Proprietà estese + + + + + Filegroups + Filegroup + + + + + Foreign Keys + Chiavi esterne + + + + + Full-Text Catalogs + Cataloghi full-text + + + + + Full-Text Indexes + Indici full-text + + + + + Functions + Funzioni + + + + + Indexes + Indici + + + + + Inline Functions + Funzioni inline + + + + + Keys + Chiavi + + + + + Linked Servers + Server collegati + + + + + Linked Server Logins + Accessi server collegato + + + + + Logins + Accessi + + + + + Master Key + Chiave master + + + + + Master Keys + Chiavi master + + + + + Message Types + Tipi di messaggio + + + + + Table-Valued Functions + Funzioni con valori di tabella + + + + + Parameters + Parametri + + + + + Partition Functions + Funzioni di partizione + + + + + Partition Schemes + Schemi di partizione + + + + + Permissions + Autorizzazioni + + + + + Primary Keys + Chiavi primarie + + + + + Programmability + Programmazione + + + + + Queues + Code + + + + + Remote Service Bindings + Associazioni a servizi remoti + + + + + Returned Columns + Colonne restituite + + + + + Roles + Ruoli + + + + + Routes + Route + + + + + Rules + Regole + + + + + Schemas + Schemi + + + + + Security + Sicurezza + + + + + Server Objects + Oggetti server + + + + + Management + Gestione + + + + + Triggers + Trigger + + + + + Service Broker + Service Broker + + + + + Services + Servizi + + + + + Signatures + Firme + + + + + Log Files + File di log + + + + + Statistics + Statistiche + + + + + Storage + Archiviazione + + + + + Stored Procedures + Stored procedure + + + + + Symmetric Keys + Chiavi simmetriche + + + + + Synonyms + Sinonimi + + + + + Tables + Tabelle + + + + + Triggers + Trigger + + + + + Types + Tipi + + + + + Unique Keys + Chiavi univoche + + + + + User-Defined Data Types + Tipi di dati definiti dall'utente + + + + + User-Defined Types (CLR) + Tipi definiti dall'utente (UDT) (CLR) + + + + + Users + Utenti + + + + + Views + Viste + + + + + XML Indexes + Indici XML + + + + + XML Schema Collections + Raccolte XML Schema + + + + + User-Defined Table Types + Tipi di tabella definiti dall'utente + + + + + Files + File + + + + + Missing Caption + Didascalia mancante + + + + + Broker Priorities + Priorità di Service Broker + + + + + Cryptographic Providers + Provider del servizio di crittografia + + + + + Database Audit Specifications + Specifiche di controllo database + + + + + Database Encryption Keys + Chiavi di crittografia database + + + + + Event Sessions + Sessioni eventi + + + + + Full Text Stoplists + Elenchi di parole non significative full-text + + + + + Resource Pools + Pool di risorse + + + + + Audits + Controlli + + + + + Server Audit Specifications + Specifiche controllo server + + + + + Spatial Indexes + Indici spaziali + + + + + Workload Groups + Gruppi del carico di lavoro + + + + + SQL Files + File SQL + + + + + Server Functions + Funzioni server + + + + + SQL Type + Tipo SQL + + + + + Server Options + Opzioni server + + + + + Database Diagrams + Diagrammi di database + + + + + System Tables + Tabelle di sistema + + + + + Databases + Database + + + + + System Contracts + Contratti di sistema + + + + + System Databases + Database di sistema + + + + + System Message Types + Tipi di messaggi di sistema + + + + + System Queues + Code di sistema + + + + + System Services + Servizi di sistema + + + + + System Stored Procedures + Stored procedure di sistema + + + + + System Views + Viste di sistema + + + + + Data-tier Applications + Applicazioni livello dati + + + + + Extended Stored Procedures + Stored procedure estese + + + + + Aggregate Functions + Funzioni di aggregazione + + + + + Approximate Numerics + Valori numerici approssimati + + + + + Binary Strings + Stringhe binarie + + + + + Character Strings + Stringhe di caratteri + + + + + CLR Data Types + Tipi di dati CLR + + + + + Configuration Functions + Funzioni di configurazione + + + + + Cursor Functions + Funzioni per i cursori + + + + + System Data Types + Tipi di dati di sistema + + + + + Date and Time + Data e ora + + + + + Date and Time Functions + Funzioni di data e ora + + + + + Exact Numerics + Valori numerici esatti + + + + + System Functions + Funzioni di sistema + + + + + Hierarchy Id Functions + Funzioni di ID di gerarchia + + + + + Mathematical Functions + Funzioni matematiche + + + + + Metadata Functions + Funzioni per i metadati + + + + + Other Data Types + Altri tipi di dati + + + + + Other Functions + Altre funzioni + + + + + Rowset Functions + Funzioni per i set di righe + + + + + Security Functions + Funzioni di sicurezza + + + + + Spatial Data Types + Tipi di dati spaziali + + + + + String Functions + Funzioni per i valori stringa + + + + + System Statistical Functions + Funzioni statistiche di sistema + + + + + Text and Image Functions + Funzioni per i valori text e image + + + + + Unicode Character Strings + Stringhe di caratteri Unicode + + + + + Aggregate Functions + Funzioni di aggregazione + + + + + Scalar-valued Functions + Funzioni a valori scalari + + + + + Table-valued Functions + Funzioni con valori di tabella + + + + + System Extended Stored Procedures + Stored procedure estese di sistema + + + + + Built-in Types + Tipi predefiniti + + + + + Built-in Server Roles + Ruoli del server predefiniti + + + + + User with Password + Utente con password + + + + + Search Property List + Elenco delle proprietà di ricerca + + + + + Security Policies + Criteri di sicurezza + + + + + Security Predicates + Predicati di sicurezza + + + + + Server Role + Ruolo del server + + + + + Search Property Lists + Elenchi delle proprietà di ricerca + + + + + Column Store Indexes + Indici dell'archivio colonne + + + + + Table Type Indexes + Indici del tipo di tabella + + + + + Selective XML Indexes + Indici XML selettivi + + + + + XML Namespaces + Spazi dei nomi XML + + + + + XML Typed Promoted Paths + Percorsi promossi con tipizzazione XML + + + + + T-SQL Typed Promoted Paths + Percorsi promossi con tipizzazione T-SQL + + + + + Database Scoped Credentials + Credenziali con ambito database + + + + + External Data Sources + Origini dati esterne + + + + + External File Formats + Formati di file esterni + + + + + External Resources + Risorse esterne + + + + + External Tables + Tabelle esterne + + + + + Always Encrypted Keys + Chiavi Always Encrypted + + + + + Column Master Keys + Chiavi master della colonna + + + + + Column Encryption Keys + Chiavi di crittografia della colonna + + + + + Server + Server + + + + + Error parsing ScriptingParams.ConnectionString property. + Errore durante l'analisi della proprietà ScriptingParams.ConnectionString. + + + + + Invalid directory specified by the ScriptingParams.FilePath property. + La Directory specificata dalla proprietà ScriptingParams.FilePath non è valida. + + + + + Error parsing ScriptingListObjectsCompleteParams.ConnectionString property. + Errore durante l'analisi della proprietà ScriptingListObjectsCompleteParams.ConnectionString. + + + + + {0} ({1}, {2}, {3}) + {0} ({1}, {2}, {3}) + + + + + No default + Nessun valore predefinito + + + + + Input + Input + + + + + Input/Output + Input/Output + + + + + Input/ReadOnly + Input/ReadOnly + + + + + Input/Output/ReadOnly + Input/Output/ReadOnly + + + + + Default + Predefinito + + + + + null + Null + + + + + not null + non Null + + + + + {0} ({1}, {2}) + {0} ({1}, {2}) + + + + + {0} ({1}) + {0} ({1}) + + + + + {0} ({1}Computed, {2}, {3}) + {0} ({1} calcolato, {2}, {3}) + + + + + {0} ({1}Computed) + {0} ({1} calcolato) + + + + + {0} (Column Set, {1}) + {0} (Set di colonne: {1}) + + + + + {0} (Column Set, {1}{2}, {3}) + {0} (Set di colonne: {1} {2}, {3}) + + + + + {0} (Column Set, {1}, {2}, {3}) + {0} (Set di colonne: {1}, {2}, {3}) + + + + + Unique + Univoco + + + + + Non-Unique + Non univoco + + + + + Clustered + Cluster + + + + + Non-Clustered + Non cluster + + + + + History + Cronologia + + + + + System-Versioned + Con controllo delle versioni di sistema + + + + + Unavailable + Non disponibile + + + + + Current default filegroup: {0} + Filegroup predefinito corrente: {0} + + + + + New Filegroup for {0} + Nuovo Filegroup per {0} + + + + + Default + Predefinito + + + + + Files + File + + + + + Name + Nome + + + + + Read-Only + Sola lettura + + + + + Autogrowth / Maxsize + Aumento automatico / Maxsize + + + + + ... + ... + + + + + <default> + <predefinito> + + + + + Filegroup + Filegroup + + + + + Logical Name + Nome logico + + + + + File Type + Tipo di file + + + + + Initial Size (MB) + Dimensioni iniziali (MB) + + + + + <new filegroup> + <nuovo Filegroup> + + + + + Path + Percorso + + + + + File Name + Nome file + + + + + <raw device> + <dispositivo RAW> + + + + + Bulk-logged + Registrazione delle operazioni bulk + + + + + Full + Completo + + + + + Simple + Semplice + + + + + Select Database Owner + Seleziona il proprietario del Database + + + + + None + Nessuno + + + + + By {0} MB, Limited to {1} MB + Di {0} MB, limitato a {1} MB + + + + + By {0} percent, Limited to {1} MB + Di {0} percento, limitato a {1} MB + + + + + By {0} MB, Unlimited + Di {0} MB, illimitato + + + + + By {0} percent, Unlimited + Di {0} percento, illimitato + + + + + Unlimited + Senza limiti + + + + + Limited to {0} MB + Limitato a {0} MB + + + + + Automatic + Automatico + + + + + Service Broker + Service Broker + + + + + Collation + Regole di confronto + + + + + Cursor + Cursore + + + + + Miscellaneous + Varie + + + + + Recovery + Recupero + + + + + State + Stato + + + + + ANSI NULL Default + Impostazione predefinita ANSI NULL + + + + + ANSI NULLS Enabled + ANSI NULLS abilitati + + + + + ANSI Padding Enabled + ANSI Padding abilitato + + + + + ANSI Warnings Enabled + Avvisi ANSI abilitati + + + + + Arithmetic Abort Enabled + Arithmetic Abort abilitata + + + + + Auto Close + Chiusura automatica + + + + + Auto Create Statistics + Creazione statistiche automatica + + + + + Auto Shrink + Compattazione automatica + + + + + Auto Update Statistics + Aggiornamento statistiche automatico + + + + + Auto Update Statistics Asynchronously + Aggiornamento statistiche asincrono automatico + + + + + Case Sensitive + Distinzione maiuscole/minuscole + + + + + Close Cursor on Commit Enabled + Chiusura cursore in caso di commit abilitata + + + + + Collation + Regole di confronto + + + + + Concatenate Null Yields Null + La concatenazione di valori Null restituisce valori Null + + + + + Database Compatibility Level + Livello di compatibilità del database + + + + + Database State + Stato database + + + + + Default Cursor + Cursore predefinito + + + + + Full-Text Indexing Enabled + Indicizzazione full-text + + + + + Numeric Round-Abort + Interruzione per perdita di precisione numerica + + + + + Page Verify + Verifica pagina + + + + + Quoted Identifiers Enabled + Identificatori delimitati abilitati + + + + + Database Read-Only + Database di sola lettura + + + + + Recursive Triggers Enabled + Trigger ricorsivi abilitati + + + + + Restrict Access + Limitazione accesso + + + + + Select Into/Bulk Copy + Select Into/Bulk Copy + + + + + Honor Broker Priority + Rispetta priorità di Service Broker + + + + + Service Broker Identifier + Identificatore Service Broker + + + + + Broker Enabled + Broker abilitato + + + + + Truncate Log on Checkpoint + Tronca Log al Checkpoint + + + + + Cross-database Ownership Chaining Enabled + Concatenamento della proprietà tra database abilitato + + + + + Trustworthy + Trustworthy + + + + + Date Correlation Optimization Enabled + Ottimizzazione correlazione date Enabledprototype_db_prop_parameterization = parametrizzazione + + + + + Forced + Forzato + + + + + Simple + Semplice + + + + + ROWS Data + Dati RIGHE + + + + + LOG + LOG + + + + + FILESTREAM Data + Dati FILESTREAM + + + + + Not Applicable + Non applicabile + + + + + <default path> + <percorso predefinito> + + + + + Open Connections + Connessioni aperte + + + + + To change the database properties, SQL Server must close all other connections to the database_ Are you sure you want to change the properties and close all other connections? + 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 + AUTO_CLOSED + + + + + EMERGENCY + EMERGENCY + + + + + INACCESSIBLE + INACCESSIBLE + + + + + NORMAL + NORMAL + + + + + OFFLINE + OFFLINE + + + + + RECOVERING + RECOVERING + + + + + RECOVERY PENDING + RECOVERY PENDING + + + + + RESTORING + RESTORING + + + + + SHUTDOWN + SHUTDOWN + + + + + STANDBY + STANDBY + + + + + SUSPECT + SUSPECT + + + + + GLOBAL + GLOBAL + + + + + LOCAL + LOCAL + + + + + MULTI_USER + MULTI_USER + + + + + RESTRICTED_USER + RESTRICTED_USER + + + + + SINGLE_USER + SINGLE_USER + + + + + CHECKSUM + CHECKSUM + + + + + NONE + NONE + + + + + TORN_PAGE_DETECTION + TORN_PAGE_DETECTION + + + + + VarDecimal Storage Format Enabled + Formato di archiviazione VarDecimal abilitato + + + + + SQL Server 2008 (100) + SQL Server 2008 (100) + + + + + Encryption Enabled + Crittografia abilitata + + + + + OFF + OFF + + + + + ON + ON + + + + + PRIMARY + PRIMARY + + + + + For the distribution policy HASH, the number of leading hash columns is optional but should be from 1 to 16 columns + 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 2012 (110) + + + + + SQL Server 2014 (120) + SQL Server 2014 (120) + + + + + SQL Server 2016 (130) + SQL Server 2016 (130) + + + + + SQL Server vNext (140) + SQL Server vNext (140) + + + + + None + Nessuno + + + + + Partial + Parziale + + + + + FILESTREAM Files + File FILESTREAM + + + + + No Applicable Filegroup + Nessun Filegroup applicabile + + + + + The database {0} is not accessible. + Il database {0} non è accessibile. + + + + + Query has no results to return + La query non ha risultati da restituire + + + + + Result set has too many rows to be safely loaded + L'insieme di risultati ha troppe righe per essere caricato in modo sicuro + + + + Parameterization + Parametrizzazione + + + + + Specifying this option when restoring a backup with the NORECOVERY option is not permitted. + Non è consentito specificare questa opzione quando si ripristina un backup con NORECOVERY. + + + + + Invalid path for database file: '{0}' + Percorso non valido per il file di database: '{0}' + + + + + Log + Log + + + + + Failed to create restore plan + Impossibile creare un piano di ripristino. + + + + + Restore database is not supported + Ripristino del database non supportato. + + + + + Restore Database + Ripristina Database + + + + + (Copy Only) + (Sola Copia) + + + + + Component + Componente + + + + + Type + Tipo + + + + + Server + Server + + + + + Database + Database + + + + + Position + Posizione + + + + + First LSN + Primo LSN + + + + + Last LSN + Ultimo LSN + + + + + Checkpoint LSN + LSN di checkpoint + + + + + Full LSN + LSN completo + + + + + Start Date + Data di inizio + + + + + Finish Date + Data di fine + + + + + Size + Dimensione + + + + + User Name + Nome utente + + + + + Expiration + Scadenza + + + + + Name + Nome + + + + + The last backup taken ({0}) + L'ultimo backup effettuato ({0}) + + + + + Backup Database + Backup database + + + + + In progress + In corso + + + + + Completed + Completato + + + + + scripting + scripting + + + + + Connection not found + Connessione non trovata + + + + + Please provide a file path instead of directory path + Il nome file specificato è anche un nome di cartella: {0} + + + + + The provided path is invalid + Impossibile verificare l'esistenza della posizione del file di backup: {0} + + + + + Cannot access the specified path on the server: {0} + Impossibile accedere al percorso specificato sul server: {0} + + + + + No backupset selected to be restored + Nessun insieme di backup selezionato per il ripristino + + + + + Never + Mai + + + + + Azure SQL DB + Azure SQL DB + + + + + Azure SQL Data Warehouse + Azure SQL Data Warehouse + + + + + Azure SQL Stretch Database + Azure SQL Stretch Database + + + + + Path {0} is not a valid directory + Il percorso [{0}] non è una directory valida. + + + + + For directory {0} a file with name {1} already exists + Nella directory '{0}' esiste già il file {1} + + + + + Value {0} is too large to fit in column of type {1} + Il valore {0} è troppo grande per essere contenuto in una colonna di tipo {1} + + . + Parameters: 0 - value (string), 1 - columnType (string) + + + + \ No newline at end of file diff --git a/src/Microsoft.SqlTools.CoreServices/Localization/transXliff/sr.ja.xlf b/src/Microsoft.SqlTools.CoreServices/Localization/transXliff/sr.ja.xlf new file mode 100644 index 00000000..065c937e --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Localization/transXliff/sr.ja.xlf @@ -0,0 +1,2776 @@ + + + + + Connection parameters cannot be null + 接続パラメーターを null にすることはできません。 + + + + + OwnerUri cannot be null or empty + OwnerUri を null または空にすることはできません。 + + + + + SpecifiedUri '{0}' does not have existing connection + SpecifiedUri '{0}' には、既存の接続はありません。 + + . + Parameters: 0 - uri (string) + + + Invalid value '{0}' for AuthenticationType. Valid values are 'Integrated' and 'SqlLogin'. + AuthenticationType の値 '{0}' が無効です。有効な値は 'Integrated' または 'SqlLogin' です。 + + . + Parameters: 0 - authType (string) + + + Invalid value '{0}' for ApplicationIntent. Valid values are 'ReadWrite' and 'ReadOnly'. + ApplicationIntent の値 '{0}' が無効です。有効な値は 'ReadWrite' または 'ReadOnly' です。 + + . + Parameters: 0 - intent (string) + + + Connection canceled + 接続がキャンセルされました。 + + + + + OwnerUri cannot be null or empty + OwnerUri を null または空にすることはできません。 + + + + + Connection details object cannot be null + 接続の詳細オブジェクトを null にすることはできません。 + + + + + ServerName cannot be null or empty + ServerName を null または空にすることはできません。 + + + + + {0} cannot be null or empty when using SqlLogin authentication + SqlLogin 認証を使用する場合に、{0} を null または空にすることはできません。 + + . + Parameters: 0 - component (string) + + + The query has already completed, it cannot be cancelled + クエリは既に完了して、取り消すことができません。 + + + + + Query successfully cancelled, failed to dispose query. Owner URI not found. + クエリのキャンセルに成功しましたが、クエリの処理に失敗しました。OwnerURIが見つかりません。 + + + + + Query was canceled by user + クエリは、ユーザーによってキャンセルされました + + + + + The batch has not completed, yet + バッチがまだ完了していません、 + + + + + Batch index cannot be less than 0 or greater than the number of batches + バッチのインデックスは、0 未満あるいは、バッチの数より大きい値にすることはできません。 + + + + + Result set index cannot be less than 0 or greater than the number of result sets + 結果セットのインデックスは、0 未満あるいは、結果セットの数より大きい値にすることはできません + + + + + Maximum number of bytes to return must be greater than zero + 戻り値の最大バイト数は 0 より大きくする必要があります。 + + + + + Maximum number of chars to return must be greater than zero + 戻り値の最大文字数は 0 より大きくする必要があります。 + + + + + Maximum number of XML bytes to return must be greater than zero + 戻り値の最大のXMLバイト数は 0 より大きくする必要があります。 + + + + + Access method cannot be write-only + アクセス メソッドを書き込み専用にすることはできません。 + + + + + FileStreamWrapper must be initialized before performing operations + FileStreamWrapper は、操作を実行する前に初期化されなければなりません。 + + + + + This FileStreamWrapper cannot be used for writing + この FileStreamWrapper は、書き込みには利用できません。 + + + + + (1 row affected) + (1 件処理されました) + + + + + ({0} rows affected) + ({0} 行処理されました) + + . + Parameters: 0 - rows (long) + + + Commands completed successfully. + コマンドが正常に完了しました。 + + + + + Msg {0}, Level {1}, State {2}, Line {3}{4}{5} + Msg {0}, Level {1}, State {2}, Line {3}{4}{5} + + . + Parameters: 0 - msg (int), 1 - lvl (int), 2 - state (int), 3 - line (int), 4 - newLine (string), 5 - message (string) + + + Query failed: {0} + クエリに失敗しました: {0} + + . + Parameters: 0 - message (string) + + + (No column name) + (列名なし) + + + + + The requested query does not exist + 要求されたクエリは存在しません + + + + + This editor is not connected to a database + このエディターは、データベースに接続されていません。 + + + + + A query is already in progress for this editor session. Please cancel this query or wait for its completion. + このエディターのクエリは既に実行中です。クエリをキャンセルするか完了まで待って下さい。 + + + + + Sender for OnInfoMessage event must be a SqlConnection + OnInfoMessage イベントのSenderは、SqlConnectionである必要があります。 + + + + + Result cannot be saved until query execution has completed + クエリの実行が完了するまで、結果を保存することはできません。 + + + + + Internal error occurred while starting save task + 保存タスクの開始中に内部エラーが発生しました。 + + + + + A save request to the same path is in progress + 同一のパスへの保存リクエストを実行中です。 + + + + + Failed to save {0}: {1} + {0} を保存できませんでした: {1} + + . + Parameters: 0 - fileName (string), 1 - message (string) + + + Cannot read subset unless the results have been read from the server + サーバーから結果が受信されていないため、サブセットを読み取ることができません。 + + + + + Start row cannot be less than 0 or greater than the number of rows in the result set + 開始行は 0 未満か、結果セット内の行数より大きい値にすることはできません。 + + + + + Row count must be a positive integer + 行数は正の整数でなければなりません。 + + + + + Could not retrieve column schema for result set + 結果セットの列のスキーマを取得できませんでした。 + + + + + Could not retrieve an execution plan from the result set + 結果セットから実行プランを取得できませんでした。 + + + + + This feature is currently not supported on Azure SQL DB and Data Warehouse: {0} + この機能はAzure SQL DBとData Warehouseでは、現在サポートされていません: {0} + + . + Parameters: 0 - errorMessage (string) + + + An unexpected error occurred during Peek Definition execution: {0} + Peek Definitionの実行中に予期しないエラーが発生しました: {0} + + . + Parameters: 0 - errorMessage (string) + + + No results were found. + 結果は見つかりませんでした。 + + + + + No database object was retrieved. + データベース オブジェクトを取得できませんでした。 + + + + + Please connect to a server. + サーバーに接続してください。 + + + + + Operation timed out. + 操作がタイムアウトになりました。 + + + + + This object type is currently not supported by this feature. + このオブジェクトの種類は現在この機能ではサポートされていません。 + + + + + Position is outside of file line range + 位置がファイルの行の範囲外です。 + + + + + Position is outside of column range for line {0} + 位置が行 {0} の列の範囲外です。 + + . + Parameters: 0 - line (int) + + + Start position ({0}, {1}) must come before or be equal to the end position ({2}, {3}) + 開始位置 ({0}, {1}) は、終了位置 ({2}, {3}) より前、または同じでなければなりません。 + + . + Parameters: 0 - sLine (int), 1 - sCol (int), 2 - eLine (int), 3 - eCol (int) + + + Msg {0}, Level {1}, State {2}, Line {3} + Msg {0}, Level {1}, State {2}, Line {3} + + + + + Msg {0}, Level {1}, State {2}, Procedure {3}, Line {4} + Msg {0}, Level {1}, State {2}, Procedure {3}, Line {4} + + + + + Msg {0}, Level {1}, State {2} + Msg {0}, Level {1}, State {2} + + + + + An error occurred while the batch was being processed. The error message is: {0} + バッチを処理中にエラーが発生しました。エラー メッセージ: {0} + + + + + ({0} row(s) affected) + ({0} 件処理されました) + + + + + The previous execution is not yet complete. + 前回の実行がまだ完了していません。 + + + + + A scripting error occurred. + スクリプト エラーが発生しました。 + + + + + Incorrect syntax was encountered while {0} was being parsed. + {0} の解析中に不正な構文が見つかりました。 + + + + + A fatal error occurred. + 致命的なエラーが発生しました。 + + + + + Batch execution completed {0} times... + 実行を {0} 回完了しました... + + + + + You cancelled the query. + クエリをキャンセルしました。 + + + + + An error occurred while the batch was being executed. + バッチの実行中にエラーが発生しました。 + + + + + An error occurred while the batch was being executed, but the error has been ignored. + バッチの実行中にエラーが発生しましたが、エラーを無視しました。 + + + + + Beginning execution loop + Beginning execution loop + + + + + Command {0} is not supported. + コマンド {0} はサポートされていません。 + + + + + The variable {0} could not be found. + 変数 {0} が見つかりませんでした。 + + + + + SQL Execution error: {0} + SQL の実行エラー: {0} + + + + + Batch parser wrapper execution: {0} found... at line {1}: {2} Description: {3} + バッチ パーサー ラッパーの実行: 行 {1}: {2} で {0} を検出... 説明: {3} + + + + + Batch parser wrapper execution engine batch message received: Message: {0} Detailed message: {1} + バッチ パーサー ラッパー実行エンジンのバッチ メッセージを受信しました: メッセージ: {0} 詳細メッセージ: {1} + + + + + Batch parser wrapper execution engine batch ResultSet processing: DataReader.FieldCount: {0} DataReader.RecordsAffected: {1} + バッチ パーサー ラッパー実行エンジンのバッチ ResultSet 処理: DataReader.FieldCount: {0} DataReader.RecordsAffected: {1} + + + + + Batch parser wrapper execution engine batch ResultSet finished. + バッチ パーサー ラッパー実行エンジンのバッチ ResultSet が終了しました。 + + + + + Canceling batch parser wrapper batch execution. + バッチ パーサー ラッパーのバッチ実行をキャンセルしています。 + + + + + Scripting warning. + スクリプトの警告。 + + + + + For more information about this error, see the troubleshooting topics in the product documentation. + このエラーの詳細については、製品ドキュメントのトラブルシューティングに関するトピックを参照してください。 + + + + + File '{0}' recursively included. + ファイル '{0}' が再帰的に含まれています。 + + + + + Missing end comment mark '*/'. + '*/' でマークされたコメントの終端がありません。 + + + + + Unclosed quotation mark after the character string. + 文字列の引用符が閉じていません。 + + + + + Incorrect syntax was encountered while parsing '{0}'. + '{0}' の解析中に無効な構文が見つかりました。 + + + + + Variable {0} is not defined. + 変数 {0} が定義されていません。 + + + + + test + テスト + + + + + Replacement of an empty string by an empty string. + 空の文字列で空の文字列を置換しています。 + + + + + Edit session does not exist. + 編集セッションは存在しません。 + + + + + Query has not completed execution + クエリの実行が完了していません。 + + + + + Query did not generate exactly one result set + クエリは 1 つの結果セットを生成できませんでした。 + + + + + Failed to add new row to update cache + キャッシュを更新する新しい行を追加できませんでした。 + + + + + Given row ID is outside the range of rows in the edit cache + 与えられた行IDは、編集キャッシュに存在する行の範囲外です。 + + + + + An update is already pending for this row and must be reverted first + この行に対する更新がすでに保留されています。まず更新を戻す必要があります。 + + + + + Given row ID does not have pending update + 与えられた行IDには保留中の更新はありません。 + + + + + Table or view metadata could not be found + テーブルまたはビューのメタデータが見つかりませんでした。 + + + + + Invalid format for binary column + バイナリ列の形式が無効です。 + + + + + Allowed values for boolean columns are 0, 1, "true", or "false" + ブール列の型は1もしくは0の数値、または true もしくは false の文字列でなければいけません。 + + + + + The column '{0}' is defined as NOT NULL but was not given a value + 必須なセルの値が入力されていません。 + + . + Parameters: 0 - colName (string) + + + A delete is pending for this row, a cell update cannot be applied. + この行の削除が保留中であるため、セルの更新は適用できません。 + + + + + Column ID must be in the range of columns for the query + 列 ID がクエリの列の範囲である必要があります。 + + + + + Column cannot be edited + 列を編集できません。 + + + + + No key columns were found + キー列が見つかりませんでした。 + + + + + An output filename must be provided + 出力ファイル名を指定する必要があります。 + + + + + Database object {0} cannot be used for editing. + データベース オブジェクト {0} は、編集のため使用できません。 + + . + Parameters: 0 - typeName (string) + + + Specified URI '{0}' does not have a default connection + 指定された URI '{0}' には既定の接続はありません。 + + . + Parameters: 0 - uri (string) + + + A commit task is in progress. Please wait for completion. + コミット処理は実行中です。完了するまで待機してください。 + + + + + Decimal column is missing numeric precision or numeric scale + Decimal 型の列に有効桁数もしくは小数点以下桁数のどちらかが存在していません。 + + + + + <TBD> + <TBD> + + + + + Cannot add row to result buffer, data reader does not contain rows + 結果バッファーへ行を追加できません。データリーダーは行を含んでいません。 + + + + + TIME column values must be between 00:00:00.0000000 and 23:59:59.9999999 + time 型の値は 00:00:00.0000000 と 23:59:59.9999999 の範囲内になければなりません。 + + + + + NULL is not allowed for this column + この列では NULL は許可されていません。 + + + + + Edit session already exists. + 編集セッションがすでに存在します。 + + + + + Edit session has not been initialized + 編集セッションが初期化されていません。 + + + + + Edit session has already been initialized + 編集セッションはすでに初期化されました。 + + + + + Edit session has already been initialized or is in the process of initializing + 編集セッションはすでに初期化されたか、初期化中です。 + + + + + Query execution failed, see messages for details + クエリーの実行が失敗しました。詳細メッセージを確認してください。 + + + + + Result limit cannot be negative + 結果の上限は負の値にできません。 + + + + + NULL + NULL + + + + + A object name must be provided + オブジェクトの名前を指定する必要があります。 + + + + + Explicitly specifying server or database is not supported + 明示的なサーバーもしくはデータベースの指定はサポートされていません。 + + + + + Table metadata does not have extended properties + テーブルメタデータは拡張プロパティを持っていません。 + + + + + Table or view requested for edit could not be found + 編集を要求したテーブルもしくはビューが見つかりませんでした。 + + + + + Error expanding: {0} + '{0}' の拡張中にエラーが発生しました。 + + + + + Error connecting to {0} + {0} への接続中にエラーが発生しました + + + + + Aggregates + 集約 + + + + + Server Roles + サーバー ロール + + + + + Application Roles + アプリケーション ロール + + + + + Assemblies + アセンブリ + + + + + Assembly Files + アセンブリ ファイル + + + + + Asymmetric Keys + 非対称キー + + + + + Asymmetric Keys + 非対称キー + + + + + Data Compression Options + データ圧縮オプション + + + + + Certificates + 証明書 + + + + + FileTables + ファイルテーブル + + + + + Certificates + 証明書 + + + + + Check Constraints + CHECK 制約 + + + + + Columns + + + + + + Constraints + 制約 + + + + + Contracts + コントラクト + + + + + Credentials + 資格情報 + + + + + Error Messages + エラー メッセージ + + + + + Server Role Membership + サーバー ロール メンバーシップ + + + + + Database Options + データベース オプション + + + + + Database Roles + データベース ロール + + + + + Role Memberships + ロール メンバーシップ + + + + + Database Triggers + データベース トリガー + + + + + Default Constraints + 既定の制約 + + + + + Defaults + 既定値 + + + + + Sequences + シーケンス + + + + + Endpoints + エンドポイント + + + + + Event Notifications + イベント通知 + + + + + Server Event Notifications + サーバー イベント通知 + + + + + Extended Properties + 拡張プロパティ + + + + + Filegroups + ファイル グループ + + + + + Foreign Keys + 外部キー + + + + + Full-Text Catalogs + フルテキスト カタログ + + + + + Full-Text Indexes + フルテキスト インデックス + + + + + Functions + 関数 + + + + + Indexes + インデックス + + + + + Inline Functions + インライン関数 + + + + + Keys + キー + + + + + Linked Servers + リンク サーバー + + + + + Linked Server Logins + リンク サーバー ログイン + + + + + Logins + ログイン + + + + + Master Key + マスター キー + + + + + Master Keys + マスター キー + + + + + Message Types + メッセージ型 + + + + + Table-Valued Functions + テーブル値関数 + + + + + Parameters + パラメーター + + + + + Partition Functions + パーティション関数 + + + + + Partition Schemes + パーティション構成 + + + + + Permissions + アクセス許可 + + + + + Primary Keys + 主キー + + + + + Programmability + プログラミング + + + + + Queues + キュー + + + + + Remote Service Bindings + リモート サービスのバインド + + + + + Returned Columns + 返された列 + + + + + Roles + ロール + + + + + Routes + ルート + + + + + Rules + ルール + + + + + Schemas + スキーマ + + + + + Security + セキュリティ + + + + + Server Objects + サーバー オブジェクト + + + + + Management + 管理 + + + + + Triggers + トリガー + + + + + Service Broker + Service Broker + + + + + Services + サービス + + + + + Signatures + 署名 + + + + + Log Files + ログ ファイル + + + + + Statistics + 統計 + + + + + Storage + ストレージ + + + + + Stored Procedures + ストアド プロシージャ + + + + + Symmetric Keys + 対称キー + + + + + Synonyms + シノニム + + + + + Tables + テーブル + + + + + Triggers + トリガー + + + + + Types + + + + + + Unique Keys + 一意キー + + + + + User-Defined Data Types + ユーザー定義データ型 + + + + + User-Defined Types (CLR) + ユーザー定義型 (CLR) + + + + + Users + ユーザー + + + + + Views + ビュー + + + + + XML Indexes + XML インデックス + + + + + XML Schema Collections + XML スキーマ コレクション + + + + + User-Defined Table Types + ユーザー定義テーブル型 + + + + + Files + ファイル + + + + + Missing Caption + キャプションが見つかりません + + + + + Broker Priorities + Broker の優先度 + + + + + Cryptographic Providers + 暗号化プロバイダー + + + + + Database Audit Specifications + データベース監査の仕様 + + + + + Database Encryption Keys + データベース暗号化キー + + + + + Event Sessions + イベント セッション + + + + + Full Text Stoplists + フルテキスト ストップリスト + + + + + Resource Pools + リソース プール + + + + + Audits + 監査 + + + + + Server Audit Specifications + サーバー監査の仕様 + + + + + Spatial Indexes + 空間インデックス + + + + + Workload Groups + ワークロード グループ + + + + + SQL Files + SQL ファイル + + + + + Server Functions + サーバー関数 + + + + + SQL Type + SQL 型 + + + + + Server Options + サーバー オプション + + + + + Database Diagrams + データベース ダイアグラム + + + + + System Tables + システム テーブル + + + + + Databases + データベース + + + + + System Contracts + システム コントラクト + + + + + System Databases + システム データベース + + + + + System Message Types + システム メッセージの種類 + + + + + System Queues + システム キュー + + + + + System Services + システム サービス + + + + + System Stored Procedures + システム ストアド プロシージャ + + + + + System Views + システム ビュー + + + + + Data-tier Applications + データ層アプリケーション + + + + + Extended Stored Procedures + 拡張ストアド プロシージャ + + + + + Aggregate Functions + 集計関数 + + + + + Approximate Numerics + 概数 + + + + + Binary Strings + バイナリ文字列 + + + + + Character Strings + 文字列 + + + + + CLR Data Types + CLR データ型 + + + + + Configuration Functions + 構成関数 + + + + + Cursor Functions + カーソル関数 + + + + + System Data Types + システム データ型 + + + + + Date and Time + 日付と時刻 + + + + + Date and Time Functions + 日付と時刻関数 + + + + + Exact Numerics + 真数 + + + + + System Functions + システム関数 + + + + + Hierarchy Id Functions + 階層 ID 関数 + + + + + Mathematical Functions + 数学関数 + + + + + Metadata Functions + メタデータ関数 + + + + + Other Data Types + その他のデータ型 + + + + + Other Functions + その他の関数 + + + + + Rowset Functions + 行セット関数 + + + + + Security Functions + セキュリティ関数 + + + + + Spatial Data Types + 空間データ型 + + + + + String Functions + 文字列関数 + + + + + System Statistical Functions + システム統計関数 + + + + + Text and Image Functions + テキストとイメージ関数 + + + + + Unicode Character Strings + Unicode 文字列 + + + + + Aggregate Functions + 集計関数 + + + + + Scalar-valued Functions + スカラー値関数 + + + + + Table-valued Functions + テーブル値関数 + + + + + System Extended Stored Procedures + システム拡張ストアド プロシージャ + + + + + Built-in Types + ビルトイン型 + + + + + Built-in Server Roles + 組み込みのサーバー ロール + + + + + User with Password + ユーザーとパスワード + + + + + Search Property List + 検索プロパティ リスト + + + + + Security Policies + セキュリティ ポリシー + + + + + Security Predicates + セキュリティ述語 + + + + + Server Role + サーバー ロール + + + + + Search Property Lists + 検索プロパティ リスト + + + + + Column Store Indexes + 列のストア インデックス + + + + + Table Type Indexes + テーブル型インデックス + + + + + Selective XML Indexes + 選択的 XML インデックス + + + + + XML Namespaces + XML 名前空間 + + + + + XML Typed Promoted Paths + XML の型指定された昇格パス + + + + + T-SQL Typed Promoted Paths + T-SQL の型指定された昇格パス + + + + + Database Scoped Credentials + データベース スコープ資格情報 + + + + + External Data Sources + 外部データ ソース + + + + + External File Formats + 外部ファイル形式 + + + + + External Resources + 外部リソース + + + + + External Tables + 外部テーブル + + + + + Always Encrypted Keys + Always Encrypted キー + + + + + Column Master Keys + 列マスター キー + + + + + Column Encryption Keys + 列暗号化キー + + + + + Server + サーバー + + + + + Error parsing ScriptingParams.ConnectionString property. + ScriptingParams.ConnectionString プロパティの解析エラーです。 + + + + + Invalid directory specified by the ScriptingParams.FilePath property. + ScriptingParams.FilePath プロパティで指定されたディレクトリが無効です。 + + + + + Error parsing ScriptingListObjectsCompleteParams.ConnectionString property. + ScriptingListObjectsCompleteParams.ConnectionString プロパティの解析エラーです。 + + + + + {0} ({1}, {2}, {3}) + {0} ({1}、{2}、{3}) + + + + + No default + 既定値以外 + + + + + Input + 入力 + + + + + Input/Output + 入力/出力 + + + + + Input/ReadOnly + 入力/読み取り専用 + + + + + Input/Output/ReadOnly + 入力/出力/読み取り専用 + + + + + Default + 既定値 + + + + + null + NULL + + + + + not null + NULL 以外 + + + + + {0} ({1}, {2}) + {0} ({1}、{2}) + + + + + {0} ({1}) + {0} ({1}) + + + + + {0} ({1}Computed, {2}, {3}) + {0} ({1} 計算値、{2}、{3}) + + + + + {0} ({1}Computed) + {0} ({1} 計算値) + + + + + {0} (Column Set, {1}) + {0} (列セット、{1}) + + + + + {0} (Column Set, {1}{2}, {3}) + {0} (列セット、{1}{2}、{3}) + + + + + {0} (Column Set, {1}, {2}, {3}) + {0} (列セット、{1}、{2}、{3}) + + + + + Unique + 一意 + + + + + Non-Unique + 一意でない + + + + + Clustered + クラスター化 + + + + + Non-Clustered + 非クラスター + + + + + History + 履歴 + + + + + System-Versioned + システムバージョン管理 + + + + + Unavailable + 使用不可 + + + + + Current default filegroup: {0} + 現在の既定のファイル グループ: {0} + + + + + New Filegroup for {0} + 新しいファイルグループ {0} + + + + + Default + 既定値 + + + + + Files + ファイル + + + + + Name + 名前 + + + + + Read-Only + 読み取り専用 + + + + + Autogrowth / Maxsize + 自動拡張 / 最大容量 + + + + + ... + ... + + + + + <default> + <既定> + + + + + Filegroup + ファイル グループ + + + + + Logical Name + 論理名 + + + + + File Type + ファイルタイプ + + + + + Initial Size (MB) + 初期サイズ (MB) + + + + + <new filegroup> + <新しいファイルグループ> + + + + + Path + パス + + + + + File Name + ファイル名 + + + + + <raw device> + <RAWデバイス> + + + + + Bulk-logged + 一括ログ + + + + + Full + 完全 + + + + + Simple + 単純 + + + + + Select Database Owner + データベース 所有者の選択 + + + + + None + なし + + + + + By {0} MB, Limited to {1} MB + {0} MBごと、{1} MBを上限 + + + + + By {0} percent, Limited to {1} MB + {0} パーセントごと、{1} MBまで + + + + + By {0} MB, Unlimited + {0} MBごと、無制限 + + + + + By {0} percent, Unlimited + {0} パーセントごと、無制限 + + + + + Unlimited + 無制限 + + + + + Limited to {0} MB + {0} MBまで + + + + + Automatic + 自動 + + + + + Service Broker + Service Broker + + + + + Collation + 照合順序 + + + + + Cursor + カーソル + + + + + Miscellaneous + その他 + + + + + Recovery + 復旧 + + + + + State + 状態 + + + + + ANSI NULL Default + ANSI NULL 既定値 + + + + + ANSI NULLS Enabled + ANSI NULLS 有効 + + + + + ANSI Padding Enabled + ANSI Padding 有効 + + + + + ANSI Warnings Enabled + ANSI 警告有効 + + + + + Arithmetic Abort Enabled + 算術アボート有効 + + + + + Auto Close + 自動クローズ + + + + + Auto Create Statistics + 統計の自動作成 + + + + + Auto Shrink + 自動圧縮 + + + + + Auto Update Statistics + 統計の自動更新 + + + + + Auto Update Statistics Asynchronously + 統計の非同期的自動更新 + + + + + Case Sensitive + 大文字と小文字を区別する + + + + + Close Cursor on Commit Enabled + コミットでカーソルを閉じる + + + + + Collation + 照合順序 + + + + + Concatenate Null Yields Null + Nullとの連結をNullとして取り扱う + + + + + Database Compatibility Level + データベース互換性レベル + + + + + Database State + データベース状態 + + + + + Default Cursor + 既定のカーソル + + + + + Full-Text Indexing Enabled + フルテキスト インデックス 有効化 + + + + + Numeric Round-Abort + 数値丸め処理アボート + + + + + Page Verify + ページ確認 + + + + + Quoted Identifiers Enabled + 引用符で囲まれた識別子が有効 + + + + + Database Read-Only + 読み取り専用データベース + + + + + Recursive Triggers Enabled + 再帰トリガー有効 + + + + + Restrict Access + アクセスの制限 + + + + + Select Into/Bulk Copy + Select Into/ バルクコピー + + + + + Honor Broker Priority + Broker の優先度の許可 + + + + + Service Broker Identifier + Service Broker 識別子 + + + + + Broker Enabled + ブローカー有効化 + + + + + Truncate Log on Checkpoint + チェックポイントでのログの切り捨て + + + + + Cross-database Ownership Chaining Enabled + 複数データベースの組み合わせ所有権有効 + + + + + Trustworthy + 信頼可能 + + + + + Date Correlation Optimization Enabled + データ相関性の最適化 +Enabledprototype_db_prop_parameterization = Parameterization + + + + + Forced + 強制 + + + + + Simple + 単純 + + + + + ROWS Data + 列データ + + + + + LOG + ログ + + + + + FILESTREAM Data + FILESTREAM データ + + + + + Not Applicable + 適用不可 + + + + + <default path> + <既定のパス> + + + + + Open Connections + コネクションを開く + + + + + To change the database properties, SQL Server must close all other connections to the database_ Are you sure you want to change the properties and close all other connections? + データベースのプロパティを変更するには、SQL Server はデータベースへの他のすべての接続を閉じる必要があります。プロパティを変更して、他のすべての接続を閉じてよろしいですか? + + + + + AUTO_CLOSED + AUTO_CLOSED + + + + + EMERGENCY + EMERGENCY + + + + + INACCESSIBLE + INACCESSIBLE + + + + + NORMAL + NORMAL + + + + + OFFLINE + OFFLINE + + + + + RECOVERING + RECOVERING + + + + + RECOVERY PENDING + RECOVERY PENDING + + + + + RESTORING + RESTORING + + + + + SHUTDOWN + SHUTDOWN + + + + + STANDBY + STANDBY + + + + + SUSPECT + SUSPECT + + + + + GLOBAL + GLOBAL + + + + + LOCAL + LOCAL + + + + + MULTI_USER + MULTI_USER + + + + + RESTRICTED_USER + RESTRICTED_USER + + + + + SINGLE_USER + SINGLE_USER + + + + + CHECKSUM + CHECKSUM + + + + + NONE + NONE + + + + + TORN_PAGE_DETECTION + TORN_PAGE_DETECTION + + + + + VarDecimal Storage Format Enabled + VarDecimal ストレージ形式有効 + + + + + SQL Server 2008 (100) + SQL Server 2008 (100) + + + + + Encryption Enabled + 暗号化有効 + + + + + OFF + OFF + + + + + ON + ON + + + + + PRIMARY + PRIMARY + + + + + For the distribution policy HASH, the number of leading hash columns is optional but should be from 1 to 16 columns + 配布ポリシーのハッシュでは、ハッシュの先頭列の番号は任意ですが、1 から 16 個の列にする必要があります + + + + + SQL Server 2012 (110) + SQL Server 2012 (110) + + + + + SQL Server 2014 (120) + SQL Server 2014 (120) + + + + + SQL Server 2016 (130) + SQL Server 2016 (130) + + + + + SQL Server vNext (140) + SQL Server vNext (140) + + + + + None + なし + + + + + Partial + 部分的 + + + + + FILESTREAM Files + FILESTREAM ファイル + + + + + No Applicable Filegroup + 適用不可なファイルグループ + + + + + The database {0} is not accessible. + データベース {0} にアクセスできません。 + + + + + Query has no results to return + クエリーは結果を返しませんでした + + + + + Result set has too many rows to be safely loaded + 結果セットの行数が多すぎるため安全にロードすることはできません + + + + Parameterization + パラメーター化 + + + + + Specifying this option when restoring a backup with the NORECOVERY option is not permitted. + NORECOVERY オプションを使用してバックアップを復元するときにこのオプションを指定することはできません。 + + + + + Invalid path for database file: '{0}' + データベース ファイルのパスが無効です: '{0}' + + + + + Log + ログ + + + + + Failed to create restore plan + リストア プランの作成に失敗しました。 + + + + + Restore database is not supported + データベースのリストアはサポートされていません。 + + + + + Restore Database + データベースのリストア + + + + + (Copy Only) + (コピーのみ) + + + + + Component + コンポーネント + + + + + Type + 種類 + + + + + Server + サーバー + + + + + Database + データベース + + + + + Position + 位置 + + + + + First LSN + 最初の LSN + + + + + Last LSN + 最後の LSN + + + + + Checkpoint LSN + チェックポイントの LSN + + + + + Full LSN + 全 LSN + + + + + Start Date + 開始日 + + + + + Finish Date + 完了日 + + + + + Size + サイズ + + + + + User Name + ユーザー名 + + + + + Expiration + 有効期限 + + + + + Name + 名前 + + + + + The last backup taken ({0}) + 最後に作成されたバックアップ ({0}) + + + + + Backup Database + データベースをバックアップする + + + + + In progress + 実行中 + + + + + Completed + 完了 + + + + + scripting + スクリプト + + + + + Connection not found + 接続が見つかりません。 + + + + + Please provide a file path instead of directory path + 指定されたファイル名がディレクトリ名と同じです: {0} + + + + + The provided path is invalid + バックアップ ファイルの場所が存在するかどうか確認できません: {0} + + + + + Cannot access the specified path on the server: {0} + サーバーで指定されたパスにアクセスできません: {0} + + + + + No backupset selected to be restored + リストアするバックアップセットが選択されていません + + + + + Never + 行わない + + + + + Azure SQL DB + Azure SQL DB + + + + + Azure SQL Data Warehouse + Azure SQL Data Warehouse + + + + + Azure SQL Stretch Database + Azure SQL Stretch Database + + + + + Path {0} is not a valid directory + パス {0} は有効なディレクトリではありません + + + + + For directory {0} a file with name {1} already exists + ディレクトリ {0} 内に {1} という名前のファイルは既に存在します + + + + + Value {0} is too large to fit in column of type {1} + 値 {0} は大きすぎるため、型 {1} の列に収まりません + + . + Parameters: 0 - value (string), 1 - columnType (string) + + + + \ No newline at end of file diff --git a/src/Microsoft.SqlTools.CoreServices/Localization/transXliff/sr.ko.xlf b/src/Microsoft.SqlTools.CoreServices/Localization/transXliff/sr.ko.xlf new file mode 100644 index 00000000..34a658e8 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Localization/transXliff/sr.ko.xlf @@ -0,0 +1,2777 @@ + + + + + Connection parameters cannot be null + 연결 매개 변수는 null 일 수 없습니다. + + + + + OwnerUri cannot be null or empty + OwnerUri은 null 이거나 비어 있을 수 없습니다. + + + + + SpecifiedUri '{0}' does not have existing connection + SpecifiedUrl '{0}'는 기존 연결이 없습니다. + + . + Parameters: 0 - uri (string) + + + Invalid value '{0}' for AuthenticationType. Valid values are 'Integrated' and 'SqlLogin'. + AuthenticationType 값으로 ' {0} '이 (가) 잘못 되었습니다. 유효한 값은 'Integrated'나 'SqlLogin' 입니다. + + . + Parameters: 0 - authType (string) + + + Invalid value '{0}' for ApplicationIntent. Valid values are 'ReadWrite' and 'ReadOnly'. + ApplicationIntent 값으로 ' {0} '이 (가) 잘못 되었습니다. 유효한 값은 'ReadWrite'나 'ReadOnly' 입니다. + + . + Parameters: 0 - intent (string) + + + Connection canceled + 연결이 취소되었습니다. + + + + + OwnerUri cannot be null or empty + OwnerUri는 null 이나 빈값일 수 없습니다 + + + + + Connection details object cannot be null + 연결 세부 정보 개체는 null이 될 수 없습니다. + + + + + ServerName cannot be null or empty + 서버 이름은 null이거나 비어 있을 수 없습니다. + + + + + {0} cannot be null or empty when using SqlLogin authentication + SqlLogin 인증 사용 시 {0}은(는) null이나 빈값일 수 없습니다. + + . + Parameters: 0 - component (string) + + + The query has already completed, it cannot be cancelled + 쿼리가 이미 완료되어 취소할 수 없습니다. + + + + + Query successfully cancelled, failed to dispose query. Owner URI not found. + 쿼리 취소가 완료되었으나 쿼리를 삭제하는데 실패했습니다. Owner URI를 찾을 수 없습니다. + + + + + Query was canceled by user + 사용자가 쿼리를 취소 했습니다. + + + + + The batch has not completed, yet + 일괄 처리가 아직 완료되지 않았습니다. + + + + + Batch index cannot be less than 0 or greater than the number of batches + 일괄 처리 인덱스는 0 미만 이거나 일괄 처리 갯수 보다 클 수 없습니다. + + + + + Result set index cannot be less than 0 or greater than the number of result sets + 결과 집합 인덱스는 0 미만 이거나 결과 집합의 갯수보다 클 수 없습니다. + + + + + Maximum number of bytes to return must be greater than zero + 반환되는 최대 바이트 수는 0보다 커야 합니다. + + + + + Maximum number of chars to return must be greater than zero + 반환되는 최대 문자 수는 0보다 커야 합니다. + + + + + Maximum number of XML bytes to return must be greater than zero + 반환되는 최대 XML 바이트 수는 0보다 커야 합니다. + + + + + Access method cannot be write-only + 액세스 방법은 쓰기 전용이 될 수 없습니다. + + + + + FileStreamWrapper must be initialized before performing operations + FileStreamWrapper 는 작업을 수행 하기 전에 초기화 해야 합니다. + + + + + This FileStreamWrapper cannot be used for writing + FileStreamWrapper 는 쓰기용으로 사용할 수 없습니다. + + + + + (1 row affected) + (1 개 행이 영향을 받음) + + + + + ({0} rows affected) + ({0} 개 행이 영향을 받음) + + . + Parameters: 0 - rows (long) + + + Commands completed successfully. + 명령이 성공적으로 완료 되었습니다. + + + + + Msg {0}, Level {1}, State {2}, Line {3}{4}{5} + 메시지 {0}, 수준 {1}, 상태 {2}, 줄 {3} {4} {5}. + + . + Parameters: 0 - msg (int), 1 - lvl (int), 2 - state (int), 3 - line (int), 4 - newLine (string), 5 - message (string) + + + Query failed: {0} + 쿼리 실패: {0} + + . + Parameters: 0 - message (string) + + + (No column name) + (열 이름 없음) + + + + + The requested query does not exist + 요청한 쿼리가 존재하지 않습니다. + + + + + This editor is not connected to a database + 편집기가 데이터베이스에 연결되지 않았습니다. + + + + + A query is already in progress for this editor session. Please cancel this query or wait for its completion. + 쿼리가 현재 편집기 세션에서 이미 실행 중입니다. 쿼리를 취소하거나 완료 될 때까지 대기 하십시오. + + + + + Sender for OnInfoMessage event must be a SqlConnection + OnInfoMessage 이벤트 발신자는 SqlConnection 이어야 합니다. + + + + + Result cannot be saved until query execution has completed + 결과는 쿼리 실행이 완료 될 때까지 저장할 수 없습니다. + + + + + Internal error occurred while starting save task + 저장 작업을 시작 하는 동안 내부 오류가 발생 했습니다. + + + + + A save request to the same path is in progress + 동일한 경로로 저장 요청이 진행 중입니다. + + + + + Failed to save {0}: {1} + 저장 실패 {0}:{1} + + . + Parameters: 0 - fileName (string), 1 - message (string) + + + Cannot read subset unless the results have been read from the server + 서버로부터 결과를 모두 읽기 전에는 일부 결과를 읽을 수 없습니다. + + + + + Start row cannot be less than 0 or greater than the number of rows in the result set + 시작 행은 0 미만이거나 결과 집합의 행의 갯수보다 클 수 없습니다. + + + + + Row count must be a positive integer + 행 수는 양수여야 합니다. + + + + + Could not retrieve column schema for result set + 결과 집합의 열 스키마를 검색할 수 없습니다. + + + + + Could not retrieve an execution plan from the result set + 결과 집합에서 실행 계획을 검색할 수 없습니다. + + + + + This feature is currently not supported on Azure SQL DB and Data Warehouse: {0} + 현재 이 기능은 Azure SQL DB와 데이터 웨어하우스에서 지원 되지 않습니다: {0} + + . + Parameters: 0 - errorMessage (string) + + + An unexpected error occurred during Peek Definition execution: {0} + 정의 피킹을 실행하는 동안 예상치 못한 오류가 발생했습니다: {0} + + . + Parameters: 0 - errorMessage (string) + + + No results were found. + 결과가 없습니다. + + + + + No database object was retrieved. + 검색된 데이터베이스 개체가 없습니다. + + + + + Please connect to a server. + 서버에 연결 하십시오. + + + + + Operation timed out. + 작업 제한 시간이 초과 되었습니다. + + + + + This object type is currently not supported by this feature. + 현재 이 개체 형식은 지원되지 않습니다. + + + + + Position is outside of file line range + 위치가 파일 줄 범위를 벗어났습니다. + + + + + Position is outside of column range for line {0} + 위치가 줄 {0} 의 열 범위를 벗어났습니다. + + . + Parameters: 0 - line (int) + + + Start position ({0}, {1}) must come before or be equal to the end position ({2}, {3}) + 시작 위치 ({0}, {1})은(는) 반드시 끝 위치 ({2}, {3}) 과 같거나 이전이어야 합니다. + + . + Parameters: 0 - sLine (int), 1 - sCol (int), 2 - eLine (int), 3 - eCol (int) + + + Msg {0}, Level {1}, State {2}, Line {3} + 메시지 {0}, 수준{1}, 상태 {2}, 줄 {3} + + + + + Msg {0}, Level {1}, State {2}, Procedure {3}, Line {4} + 메시지 {0}, 수준 {1}, 상태 {2}, 프로시저 {3}, 줄 {4} + + + + + Msg {0}, Level {1}, State {2} + 메시지 {0}, 수준 {1}, 상태 {2} + + + + + An error occurred while the batch was being processed. The error message is: {0} + 일괄 처리를 처리 하는 동안 하는 동안 오류가 발생 합니다. 오류 메시지: {0} + + + + + ({0} row(s) affected) + ({0} 개 행이 영향을 받음) + + + + + The previous execution is not yet complete. + 이전 실행이 아직 완료 되지 않았습니다. + + + + + A scripting error occurred. + 스크립팅 오류가 발생 했습니다. + + + + + Incorrect syntax was encountered while {0} was being parsed. + {0}에 잘못된 구문이 발견되었습니다. + + + + + A fatal error occurred. + 치명적인 오류가 발생 했습니다. + + + + + Batch execution completed {0} times... + {0}회 실행 완료... + + + + + You cancelled the query. + 쿼리를 취소 했습니다. + + + + + An error occurred while the batch was being executed. + 일괄 처리를 실행 하는 동안 오류가 발생 합니다. + + + + + An error occurred while the batch was being executed, but the error has been ignored. + 일괄 처리를 실행 하는 동안 오류가 발생했으나 그 오류는 무시되었습니다. + + + + + Beginning execution loop + Beginning execution loop + + + + + Command {0} is not supported. + {0} 명령은 지원되지 않습니다. + + + + + The variable {0} could not be found. + {0} 변수를 찾을 수 없습니다. + + + + + SQL Execution error: {0} + SQL 실행 오류: {0} + + + + + Batch parser wrapper execution: {0} found... at line {1}: {2} Description: {3} + 일괄처리 구문분석 래퍼 실행: {0} 발견... 줄 {1}: {2} 설명: {3} + + + + + Batch parser wrapper execution engine batch message received: Message: {0} Detailed message: {1} + 일괄 처리 파서 래퍼 실행 엔진 일괄 처리 메시지를 받았습니다. 메시지: {0} 자세한 메시지: {1} + + + + + Batch parser wrapper execution engine batch ResultSet processing: DataReader.FieldCount: {0} DataReader.RecordsAffected: {1} + 일괄 처리 파서 래퍼 실행 엔진 일괄 처리 ResultSet을 처리하고 있습니다. DataReader.FieldCount: {0} DataReader.RecordsAffected: {1} + + + + + Batch parser wrapper execution engine batch ResultSet finished. + 일괄 처리 파서 래퍼 실행 엔진 일괄 처리 ResultSet을 완료했습니다. + + + + + Canceling batch parser wrapper batch execution. + 일괄 처리 파서 래퍼 일괄 처리 실행을 취소하고 있습니다. + + + + + Scripting warning. + 스크립팅 경고. + + + + + For more information about this error, see the troubleshooting topics in the product documentation. + 이 오류에 대한 추가 정보는 제품 설명서의 문제 해결 항목을 참조하십시오. + + + + + File '{0}' recursively included. + ' {0} '이 (가) 재귀적으로 포함 된 파일입니다. + + + + + Missing end comment mark '*/'. + 주석 끝 표시 ' * /' 누락 . + + + + + Unclosed quotation mark after the character string. + 문자열에 닫히지 않은 인용 부호. + + + + + Incorrect syntax was encountered while parsing '{0}'. + '{0}'을(를) 구문 분석하는 동안 잘못된 구문을 발견했습니다. + + + + + Variable {0} is not defined. + {0} 변수가 정의되지 않았습니다. + + + + + test + 테스트 + + + + + Replacement of an empty string by an empty string. + +votes +빈 문자열을 빈 문자열로 대체. + + + + + Edit session does not exist. + 편집 세션이 존재하지 않습니다. + + + + + Query has not completed execution + 쿼리 실행이 완료되지 않았습니다. + + + + + Query did not generate exactly one result set + 쿼리가 정확히 하나의 결과 집합을 생성하지 않았습니다. + + + + + Failed to add new row to update cache + 업데이트 캐시에 새로운 행 추가를 실패했습니다. + + + + + Given row ID is outside the range of rows in the edit cache + 지정된 row ID가 수정 중인 캐시의 행 범위 밖에 있습니다. + + + + + An update is already pending for this row and must be reverted first + 이 행에 대한 업데이트가 이미 보류 중이므로 먼저 되돌려야 합니다. + + + + + Given row ID does not have pending update + 주어진 row ID에 보류 중인 업데이트가 없습니다. + + + + + Table or view metadata could not be found + 테이블이나 뷰 메타 데이터를 찾을 수 없습니다. + + + + + Invalid format for binary column + 이진 열에 형식이 잘못되었습니다. + + + + + Allowed values for boolean columns are 0, 1, "true", or "false" + Boolean 열은 반드시 숫자 1이나 0 혹은 문자 true나 false여야 합니다. + + + + + The column '{0}' is defined as NOT NULL but was not given a value + 필수 셀 값이 누락되었습니다. + + . + Parameters: 0 - colName (string) + + + A delete is pending for this row, a cell update cannot be applied. + 행 삭제가 보류 중이므로, 셀을 업데이트할 수 없습니다. + + + + + Column ID must be in the range of columns for the query + 열 ID는 쿼리의 열 범위 내에 있어야 합니다. + + + + + Column cannot be edited + 열을 편집할 수 없습니다. + + + + + No key columns were found + 키 열이 없습니다. + + + + + An output filename must be provided + 출력 파일명이 필요합니다. + + + + + Database object {0} cannot be used for editing. + 데이터베이스 개체 {0} 는 편집할 수 없습니다. + + . + Parameters: 0 - typeName (string) + + + Specified URI '{0}' does not have a default connection + 지정된 Uri ' {0} '에 기본 연결이 지정되지 않았습니다. + + . + Parameters: 0 - uri (string) + + + A commit task is in progress. Please wait for completion. + 커밋 작업이 진행 중입니다. 완료될 때까지 기다리세요. + + + + + Decimal column is missing numeric precision or numeric scale + Decimal 형식 열에 전체 자릿수 또는 소수 자릿수가 없습니다. + + + + + <TBD> + <TBD> + + + + + Cannot add row to result buffer, data reader does not contain rows + 결과 버퍼에 새로운 행을 추가할 수 없거나 데이터 리더에 행이 없습니다. + + + + + TIME column values must be between 00:00:00.0000000 and 23:59:59.9999999 + TIME 열의 값은 00:00:00.0000000과 23:59:59.9999999 사이의 값만 허용됩니다. + + + + + NULL is not allowed for this column + 이 열은 NULL을 허용하지 않습니다. + + + + + Edit session already exists. + 편집 세션이 이미 존재합니다. + + + + + Edit session has not been initialized + 편집 세션이 초기화 되지 않았습니다. + + + + + Edit session has already been initialized + 편집 세션이 이미 초기화 되었습니다. + + + + + Edit session has already been initialized or is in the process of initializing + 편집 세션이 이미 초기화 되었거나 초기화 중입니다. + + + + + Query execution failed, see messages for details + 쿼리 실행에 실패했습니다. 자세한 정보는 메시지를 참조하세요. + + + + + Result limit cannot be negative + 결과 제한은 음수가 될 수 없습니다. + + + + + NULL + NULL + + + + + A object name must be provided + 개체 이름이 필요합니다. + + + + + Explicitly specifying server or database is not supported + 서버와 데이터베이스를 명시적으로 지정할 수 없습니다. + + + + + Table metadata does not have extended properties + 테이블 메타데이터에 확장 속성이 없습니다. + + + + + Table or view requested for edit could not be found + 편집하려는 테이블이나 뷰를 찾을 수 없습니다 + + + + + Error expanding: {0} + 오류 확장: {0} + + + + + Error connecting to {0} + {0}에 연결하는 동안 오류가 발생했습니다. + + + + + Aggregates + 집계 + + + + + Server Roles + 서버 역할 + + + + + Application Roles + 응용 프로그램 역할 + + + + + Assemblies + 어셈블리 + + + + + Assembly Files + 어셈블리 파일 + + + + + Asymmetric Keys + 비대칭 키 + + + + + Asymmetric Keys + 비대칭 키 + + + + + Data Compression Options + 데이터 압축 옵션 + + + + + Certificates + 인증서 + + + + + FileTables + FileTables + + + + + Certificates + 인증서 + + + + + Check Constraints + Check 제약 조건 + + + + + Columns + + + + + + Constraints + 제약 조건 + + + + + Contracts + 계약 + + + + + Credentials + 자격 증명 + + + + + Error Messages + 오류 메시지 + + + + + Server Role Membership + 서버 역할 멤버 자격 + + + + + Database Options + 데이터베이스 옵션 + + + + + Database Roles + 데이터베이스 역할 + + + + + Role Memberships + 역할 멤버 자격 + + + + + Database Triggers + 데이터베이스 트리거 + + + + + Default Constraints + 기본 제약 조건 + + + + + Defaults + 기본값 + + + + + Sequences + 시퀀스 + + + + + Endpoints + 끝점 + + + + + Event Notifications + 이벤트 알림 + + + + + Server Event Notifications + 서버 이벤트 알림 + + + + + Extended Properties + 확장 속성 + + + + + Filegroups + 파일 그룹 + + + + + Foreign Keys + 외래 키 + + + + + Full-Text Catalogs + 전체 텍스트 카탈로그 + + + + + Full-Text Indexes + 전체 텍스트 인덱스 + + + + + Functions + 함수 + + + + + Indexes + 인덱스 + + + + + Inline Functions + 인라인 함수 + + + + + Keys + + + + + + Linked Servers + 연결된 서버 + + + + + Linked Server Logins + 연결된 서버 로그인 + + + + + Logins + 로그인 + + + + + Master Key + 마스터 키 + + + + + Master Keys + 마스터 키 + + + + + Message Types + 메시지 유형 + + + + + Table-Valued Functions + 테이블 반환 함수 + + + + + Parameters + 매개 변수 + + + + + Partition Functions + 파티션 함수 + + + + + Partition Schemes + 파티션 구성표 + + + + + Permissions + 사용 권한 + + + + + Primary Keys + 기본 키 + + + + + Programmability + 프로그래밍 기능 + + + + + Queues + + + + + + Remote Service Bindings + 원격 서비스 바인딩 + + + + + Returned Columns + 반환 열 + + + + + Roles + 역할 + + + + + Routes + 경로 + + + + + Rules + 규칙 + + + + + Schemas + 스키마 + + + + + Security + 보안 + + + + + Server Objects + 서버 개체 + + + + + Management + 관리 + + + + + Triggers + 트리거 + + + + + Service Broker + Service Broker + + + + + Services + 서비스 + + + + + Signatures + 서명 + + + + + Log Files + 로그 파일 + + + + + Statistics + 통계 + + + + + Storage + 저장소 + + + + + Stored Procedures + 저장 프로시저 + + + + + Symmetric Keys + 대칭 키 + + + + + Synonyms + 동의어 + + + + + Tables + 테이블 + + + + + Triggers + 트리거 + + + + + Types + 유형 + + + + + Unique Keys + 고유 키 + + + + + User-Defined Data Types + 사용자 정의 데이터 형식 + + + + + User-Defined Types (CLR) + 사용자 정의 형식 (CLR) + + + + + Users + 사용자 + + + + + Views + + + + + + XML Indexes + XML 인덱스 + + + + + XML Schema Collections + XML 스키마 컬렉션 + + + + + User-Defined Table Types + 사용자 정의 테이블 형식 + + + + + Files + 파일 + + + + + Missing Caption + 캡션 누락 + + + + + Broker Priorities + 브로커 우선 순위 + + + + + Cryptographic Providers + 암호화 공급자 + + + + + Database Audit Specifications + 데이터베이스 감사 사양 + + + + + Database Encryption Keys + 데이터베이스 암호화 키 + + + + + Event Sessions + 이벤트 세션 + + + + + Full Text Stoplists + 전체 텍스트 중지 목록 + + + + + Resource Pools + 리소스 풀 + + + + + Audits + 감사 + + + + + Server Audit Specifications + 서버 감사 사양 + + + + + Spatial Indexes + 공간 인덱스 + + + + + Workload Groups + 작업 그룹 + + + + + SQL Files + SQL 파일 + + + + + Server Functions + 서버 함수 + + + + + SQL Type + SQL 유형 + + + + + Server Options + 서버 옵션 + + + + + Database Diagrams + 데이터베이스 다이어그램 + + + + + System Tables + 시스템 테이블 + + + + + Databases + 데이터베이스 + + + + + System Contracts + 시스템 계약 + + + + + System Databases + 시스템 데이터베이스 + + + + + System Message Types + 시스템 메시지 유형 + + + + + System Queues + 시스템 큐 + + + + + System Services + 시스템 서비스 + + + + + System Stored Procedures + 시스템 저장 프로시저 + + + + + System Views + 시스템 뷰 + + + + + Data-tier Applications + 데이터 계층 응용 프로그램 + + + + + Extended Stored Procedures + 확장 저장 프로시저 + + + + + Aggregate Functions + 집계 함수 + + + + + Approximate Numerics + 근사치 + + + + + Binary Strings + 이진 문자열 + + + + + Character Strings + 문자열 + + + + + CLR Data Types + CLR 데이터 형식 + + + + + Configuration Functions + 구성 함수 + + + + + Cursor Functions + 커서 함수 + + + + + System Data Types + 시스템 데이터 형식 + + + + + Date and Time + 날짜 및 시간 + + + + + Date and Time Functions + 날짜 및 시간 함수 + + + + + Exact Numerics + 정확한 수치 + + + + + System Functions + 시스템 함수 + + + + + Hierarchy Id Functions + 계층 구조 ID 함수 + + + + + Mathematical Functions + 수학 함수 + + + + + Metadata Functions + 메타데이터 함수 + + + + + Other Data Types + 기타 데이터 형식 + + + + + Other Functions + 기타 함수 + + + + + Rowset Functions + 행 집합 함수 + + + + + Security Functions + 보안 함수 + + + + + Spatial Data Types + 공간 데이터 형식 + + + + + String Functions + 문자열 함수 + + + + + System Statistical Functions + 시스템 통계 함수 + + + + + Text and Image Functions + 텍스트 및 이미지 함수 + + + + + Unicode Character Strings + 유니코드 문자열 + + + + + Aggregate Functions + 집계 함수 + + + + + Scalar-valued Functions + 스칼라 반환 함수 + + + + + Table-valued Functions + 테이블 반환 함수 + + + + + System Extended Stored Procedures + 시스템 확장 저장 프로시저 + + + + + Built-in Types + 기본 제공 유형 + + + + + Built-in Server Roles + 기본 제공 서버 역할 + + + + + User with Password + 암호가 있는 사용자 + + + + + Search Property List + 검색 속성 목록 + + + + + Security Policies + 보안 정책 + + + + + Security Predicates + 보안 조건자 + + + + + Server Role + 서버 역할 + + + + + Search Property Lists + 검색 속성 목록 + + + + + Column Store Indexes + 열 저장 인덱스 + + + + + Table Type Indexes + 테이블 형식 인덱스 + + + + + Selective XML Indexes + 선택적 XML 인덱스 + + + + + XML Namespaces + XML 네임스페이스 + + + + + XML Typed Promoted Paths + XML 유형의 공유된 경로 + + + + + T-SQL Typed Promoted Paths + T-SQL 유형의 공유된 경로 + + + + + Database Scoped Credentials + 데이터베이스 범위 자격 증명 + + + + + External Data Sources + 외부 데이터 원본 + + + + + External File Formats + 외부 파일 형식 + + + + + External Resources + 외부 리소스 + + + + + External Tables + 외부 테이블 + + + + + Always Encrypted Keys + Always Encrypted 키 + + + + + Column Master Keys + 열 마스터 키 + + + + + Column Encryption Keys + 열 암호화 키 + + + + + Server + 서버 + + + + + Error parsing ScriptingParams.ConnectionString property. + ScriptingParams.ConnectionString 속성 분석을 하는 동안 오류가 발생했습니다. + + + + + Invalid directory specified by the ScriptingParams.FilePath property. + ScriptingParams.FilePath 속성에 잘못된 디렉터리 지정 + + + + + Error parsing ScriptingListObjectsCompleteParams.ConnectionString property. + ScriptingListObjectsCompleteParams.ConnectionSring 속성을 분석할때 오류가 생겼습니다. + + + + + {0} ({1}, {2}, {3}) + {0}({1}, {2}, {3}) + + + + + No default + 기본값 없음 + + + + + Input + 입력 + + + + + Input/Output + 입/출력 + + + + + Input/ReadOnly + 입력/읽기 전용 + + + + + Input/Output/ReadOnly + 입/출력/읽기 전용 + + + + + Default + 기본값 + + + + + null + Null + + + + + not null + Not Null + + + + + {0} ({1}, {2}) + {0}({1}, {2}) + + + + + {0} ({1}) + {0}({1}) + + + + + {0} ({1}Computed, {2}, {3}) + {0}({1}계산됨, {2}, {3}) + + + + + {0} ({1}Computed) + {0}({1}계산됨) + + + + + {0} (Column Set, {1}) + {0}(열 집합, {1}) + + + + + {0} (Column Set, {1}{2}, {3}) + {0}(열 집합, {1}{2}, {3}) + + + + + {0} (Column Set, {1}, {2}, {3}) + {0}(열 집합, {1}, {2}, {3}) + + + + + Unique + 고유 + + + + + Non-Unique + 고유하지 않음 + + + + + Clustered + 클러스터형 + + + + + Non-Clustered + 비클러스터형 + + + + + History + 기록 + + + + + System-Versioned + 시스템 버전 관리 + + + + + Unavailable + 사용할 수 없음 + + + + + Current default filegroup: {0} + 현재 기본 파일 그룹: {0} + + + + + New Filegroup for {0} + {0}에 대한 새 파일 그룹 + + + + + Default + 기본값 + + + + + Files + 파일 + + + + + Name + 이름 + + + + + Read-Only + 읽기 전용 + + + + + Autogrowth / Maxsize + 자동 증가 / 최대 크기 + + + + + ... + ... + + + + + <default> + <기본값> + + + + + Filegroup + 파일 그룹 + + + + + Logical Name + 논리적 이름 + + + + + File Type + 파일 형식 + + + + + Initial Size (MB) + 처음 크기 (MB) + + + + + <new filegroup> + <새 파일 그룹> + + + + + Path + 경로 + + + + + File Name + 파일 이름 + + + + + <raw device> + <원시 장치> + + + + + Bulk-logged + 대량 로그 + + + + + Full + 전체 + + + + + Simple + 단순 + + + + + Select Database Owner + 데이터베이스 소유자 선택 + + + + + None + 없음 + + + + + By {0} MB, Limited to {1} MB + {0} MB 단위로 {1} MB까지 제한됨 + + + + + By {0} percent, Limited to {1} MB + {0} % 단위로 {1} MB까지 제한됨 + + + + + By {0} MB, Unlimited + {0} MB 단위로, 제한 없음 + + + + + By {0} percent, Unlimited + {0} % 단위로, 제한 없음 + + + + + Unlimited + 제한 없음 + + + + + Limited to {0} MB + {0} MB로 제한됨 + + + + + Automatic + 자동 + + + + + Service Broker + Service Broker + + + + + Collation + 데이터 정렬 + + + + + Cursor + 커서 + + + + + Miscellaneous + 기타 + + + + + Recovery + 복구 + + + + + State + 상태 + + + + + ANSI NULL Default + ANSI NULL 기본값 + + + + + ANSI NULLS Enabled + ANSI NULLS 사용 + + + + + ANSI Padding Enabled + ANSI 패딩 설정 + + + + + ANSI Warnings Enabled + ANSI Warnings 사용 + + + + + Arithmetic Abort Enabled + 산술 연산 중단 설정 + + + + + Auto Close + 자동 닫기 + + + + + Auto Create Statistics + 통계 자동 작성 + + + + + Auto Shrink + 자동 축소 + + + + + Auto Update Statistics + 통계 자동 업데이트 + + + + + Auto Update Statistics Asynchronously + 통계를 비동기적으로 자동 업데이트 + + + + + Case Sensitive + 대/소문자 구분 + + + + + Close Cursor on Commit Enabled + 커밋 시 커서 닫기 설정 + + + + + Collation + 데이터 정렬 + + + + + Concatenate Null Yields Null + Null 연결 시 Null 생성 + + + + + Database Compatibility Level + 데이터베이스 호환성 수준 + + + + + Database State + 데이터베이스 상태 + + + + + Default Cursor + 기본 커서 + + + + + Full-Text Indexing Enabled + 전체 텍스트 인덱싱 설정 + + + + + Numeric Round-Abort + 숫자 반올림 시 중단 + + + + + Page Verify + 페이지 확인 + + + + + Quoted Identifiers Enabled + 따옴표 붙은 식별자 설정 + + + + + Database Read-Only + 데이터베이스 읽기 전용 + + + + + Recursive Triggers Enabled + 재귀적 트리거 설정 + + + + + Restrict Access + 액세스 제한 + + + + + Select Into/Bulk Copy + SELECT INTO/대량 복사 + + + + + Honor Broker Priority + Broker 우선 순위 인식 + + + + + Service Broker Identifier + Service Broker 식별자 + + + + + Broker Enabled + Broker 활성화 + + + + + Truncate Log on Checkpoint + 검사점에서 로그 자름 + + + + + Cross-database Ownership Chaining Enabled + 데이터베이스 간 소유권 체인 사용 + + + + + Trustworthy + 신뢰 + + + + + Date Correlation Optimization Enabled + 날짜 상관관계 최적화 설정 + + + + + Forced + 강제 + + + + + Simple + 단순 + + + + + ROWS Data + ROWS 데이터 + + + + + LOG + 로그 + + + + + FILESTREAM Data + FILESTREAM 데이터 + + + + + Not Applicable + 해당 사항 없음 + + + + + <default path> + <기본 경로> + + + + + Open Connections + 연결 열기 + + + + + To change the database properties, SQL Server must close all other connections to the database_ Are you sure you want to change the properties and close all other connections? + 데이터베이스 속성을 변경하기 위해, SQL Server가 database_ 에  다른 연결을 모두 닫아야 합니다. 속성을 변경하고 다른 연결을 모두 닫으시겠습니까? + + + + + AUTO_CLOSED + AUTO_CLOSED + + + + + EMERGENCY + 긴급 + + + + + INACCESSIBLE + INACCESSIBLE + + + + + NORMAL + NORMAL + + + + + OFFLINE + 오프라인 + + + + + RECOVERING + 복구 중 + + + + + RECOVERY PENDING + 복구 보류 중 + + + + + RESTORING + RESTORING + + + + + SHUTDOWN + SHUTDOWN + + + + + STANDBY + STANDBY + + + + + SUSPECT + SUSPECT + + + + + GLOBAL + GLOBAL + + + + + LOCAL + LOCAL + + + + + MULTI_USER + MULTI_USER + + + + + RESTRICTED_USER + RESTRICTED_USER + + + + + SINGLE_USER + SINGLE_USER + + + + + CHECKSUM + CHECKSUM + + + + + NONE + NONE + + + + + TORN_PAGE_DETECTION + TORN_PAGE_DETECTION + + + + + VarDecimal Storage Format Enabled + VarDecimal 저장소 형식 사용 + + + + + SQL Server 2008 (100) + SQL Server 2008 (100) + + + + + Encryption Enabled + 암호화 사용 + + + + + OFF + OFF + + + + + ON + ON + + + + + PRIMARY + PRIMARY + + + + + For the distribution policy HASH, the number of leading hash columns is optional but should be from 1 to 16 columns + 배포 정책이 HASH인 경우 선행 해시 열 수는 선택 사항이지만, 선택할 경우 1개에서 16개 사이의 열로 지정해야 합니다. + + + + + SQL Server 2012 (110) + SQL Server 2012 (110) + + + + + SQL Server 2014 (120) + SQL Server 2014 (120) + + + + + SQL Server 2016 (130) + SQL Server 2016 (130) + + + + + SQL Server vNext (140) + SQL Server vNext (140) + + + + + None + 없음 + + + + + Partial + 부분 + + + + + FILESTREAM Files + FILESTREAM 파일 + + + + + No Applicable Filegroup + 해당 파일 그룹 없음 + + + + + The database {0} is not accessible. + {0} 데이터베이스에 액세스할 수 없습니다. + + + + + Query has no results to return + 쿼리 반환 결과 없음 + + + + + Result set has too many rows to be safely loaded + 결과 집합의 행 수가 너무 많아서 안전하게 불러들일 수 없습니다. + + + + Parameterization + 매개 변수화 + + + + + Specifying this option when restoring a backup with the NORECOVERY option is not permitted. + NORECOVERY 옵션을 사용하여 백업을 복원하는 동안 이 옵션을 지정할 수 없습니다. + + + + + Invalid path for database file: '{0}' + 데이터베이스 파일의 경로가 잘못되었습니다. '{0}' + + + + + Log + 로그 + + + + + Failed to create restore plan + 복원 계획을 만들지 못했습니다 + + + + + Restore database is not supported + 데이터베이스 복원은 지원되지 않습니다. + + + + + Restore Database + 데이터베이스 복원 + + + + + (Copy Only) + 복사 전용 + + + + + Component + 구성 요소 + + + + + Type + 형식 + + + + + Server + 서버 + + + + + Database + 데이터베이스 + + + + + Position + 위치 + + + + + First LSN + 첫 번째 LSN + + + + + Last LSN + 마지막 LSN + + + + + Checkpoint LSN + 검사점 LSN + + + + + Full LSN + 전체 LSN + + + + + Start Date + 시작 날짜 + + + + + Finish Date + 완료 날짜 + + + + + Size + 크기 + + + + + User Name + 사용자 이름 + + + + + Expiration + 만료 + + + + + Name + Name + + + + + The last backup taken ({0}) + 수행된 마지막 백업({0}) + + + + + Backup Database + 데이터베이스 백업 + + + + + In progress + 진행 중 + + + + + Completed + 완료됨 + + + + + scripting + 스크립팅 + + + + + Connection not found + 연결 없음 + + + + + Please provide a file path instead of directory path + 지정한 파일 이름은 디렉터리 이름이기도 합니다: {0} + + + + + The provided path is invalid + 백업 파일 위치를 확인할 수 없습니다: {0} + + + + + Cannot access the specified path on the server: {0} + 서버에서 지정된 경로에 액세스할 수 없습니다: {0} + + + + + No backupset selected to be restored + 복원하려는 백업 세트를 선택하지 않았습니다 + + + + + Never + 안 함 + + + + + Azure SQL DB + Azure SQL DB + + + + + Azure SQL Data Warehouse + Azure SQL Data Warehouse + + + + + Azure SQL Stretch Database + Azure SQL 신축성 데이터베이스 + + + + + Path {0} is not a valid directory + 경로 [{0}]은(는) 올바른 디렉터리가 아닙니다. + + + + + For directory {0} a file with name {1} already exists + 디렉터리 {0}에 대한 파일{1} 이 이미 존재합니다. + + + + + Value {0} is too large to fit in column of type {1} + 값 {0}이 너무 커서 {1} 유형의 열에 들어갈 수 없습니다. + + . + Parameters: 0 - value (string), 1 - columnType (string) + + + + \ No newline at end of file diff --git a/src/Microsoft.SqlTools.CoreServices/Localization/transXliff/sr.pt-BR.xlf b/src/Microsoft.SqlTools.CoreServices/Localization/transXliff/sr.pt-BR.xlf new file mode 100644 index 00000000..5a0f5367 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Localization/transXliff/sr.pt-BR.xlf @@ -0,0 +1,2776 @@ + + + + + Connection parameters cannot be null + Parâmetros de Conexão não podem ser nulos + + + + + OwnerUri cannot be null or empty + OwnerUri não pode ser nulo ou vazio + + + + + SpecifiedUri '{0}' does not have existing connection + SpecifiedUri '{0}' não há uma conexão existente + + . + Parameters: 0 - uri (string) + + + Invalid value '{0}' for AuthenticationType. Valid values are 'Integrated' and 'SqlLogin'. + Valor inválido '{0}' para AuthenticationType. Os valores válidos são 'Integrada' e 'SqlLogin'. + + . + Parameters: 0 - authType (string) + + + Invalid value '{0}' for ApplicationIntent. Valid values are 'ReadWrite' and 'ReadOnly'. + Valor inválido '{0}' para ApplicationIntent. Os valores válidos são 'ReadWrite' e 'Somente leitura'. + + . + Parameters: 0 - intent (string) + + + Connection canceled + Conexão cancelada + + + + + OwnerUri cannot be null or empty + OwnerUri não pode ser nulo ou vazio + + + + + Connection details object cannot be null + Objeto de detalhes de Conexão não pode ser nulo + + + + + ServerName cannot be null or empty + ServerName não pode ser nulo ou vazio + + + + + {0} cannot be null or empty when using SqlLogin authentication + {0} não pode ser nulo ou vazio quando estiver usando autenticação SqlLogin + + . + Parameters: 0 - component (string) + + + The query has already completed, it cannot be cancelled + A consulta já foi concluída, ela não pode ser cancelada + + + + + Query successfully cancelled, failed to dispose query. Owner URI not found. + Consulta cancelada com êxito, Falha ao descartar a consulta. Proprietário do URI não encontrado. + + + + + Query was canceled by user + Consulta foi cancelada pelo usuário + + + + + The batch has not completed, yet + O lote ainda não foi concluído. + + + + + Batch index cannot be less than 0 or greater than the number of batches + Índice de lote não pode ser menor que 0 ou maior que o número de lotes + + + + + Result set index cannot be less than 0 or greater than the number of result sets + Índice do conjunto de resultados não pode ser menor que 0 ou maior que o número do conjuntos de resultados + + + + + Maximum number of bytes to return must be greater than zero + Número máximo de bytes a serem retornados deve ser maior que zero + + + + + Maximum number of chars to return must be greater than zero + Número máximo de caracteres a serem retornados deve ser maior que zero + + + + + Maximum number of XML bytes to return must be greater than zero + Número máximo de bytes XML a serem retornados deve ser maior que zero + + + + + Access method cannot be write-only + Método de acesso não pode ser somente gravação + + + + + FileStreamWrapper must be initialized before performing operations + FileStreamWrapper deve ser inicializado antes de executar operações + + + + + This FileStreamWrapper cannot be used for writing + Este FileStreamWrapper não pode ser usado para gravação + + + + + (1 row affected) + (1 linha afetada) + + + + + ({0} rows affected) + ({0} linhas afetadas) + + . + Parameters: 0 - rows (long) + + + Commands completed successfully. + Comandos concluídos com sucesso. + + + + + Msg {0}, Level {1}, State {2}, Line {3}{4}{5} + Msg {0}, Nível {1}, Estado {2}, Linha {3} {4} {5} + + . + Parameters: 0 - msg (int), 1 - lvl (int), 2 - state (int), 3 - line (int), 4 - newLine (string), 5 - message (string) + + + Query failed: {0} + Falha na consulta: {0} + + . + Parameters: 0 - message (string) + + + (No column name) + (Nenhum nome de coluna) + + + + + The requested query does not exist + A consulta solicitada não existe. + + + + + This editor is not connected to a database + Este editor não está conectado a um banco de dados + + + + + A query is already in progress for this editor session. Please cancel this query or wait for its completion. + Uma consulta já está em andamento para esta sessão do editor. Favor cancelar esta consulta ou aguardar a sua conclusão + + + + + Sender for OnInfoMessage event must be a SqlConnection + Remetente do evento OnInfoMessage deve ser um SqlConnection + + + + + Result cannot be saved until query execution has completed + Resultado não pode ser salvo até que seja concluída a execução da consulta + + + + + Internal error occurred while starting save task + Ocorreu um erro interno ao iniciar tarefa de salvamento + + + + + A save request to the same path is in progress + Uma solicitação de salvamento para o mesmo caminho está em andamento + + + + + Failed to save {0}: {1} + Falha ao salvar {0}: {1} + + . + Parameters: 0 - fileName (string), 1 - message (string) + + + Cannot read subset unless the results have been read from the server + Não é possível ler o subconjunto, a menos que os resultados tenham sido lidos do servidor + + + + + Start row cannot be less than 0 or greater than the number of rows in the result set + Linha de início não pode ser menor que 0 ou maior que o número de linhas no conjunto de resultados + + + + + Row count must be a positive integer + Contagem de linhas deve ser um inteiro positivo + + + + + Could not retrieve column schema for result set + Não foi possível recuperar o esquema de colunas para o conjunto de resultados + + + + + Could not retrieve an execution plan from the result set + Não foi possível recuperar um plano de execução do conjunto de resultados + + + + + This feature is currently not supported on Azure SQL DB and Data Warehouse: {0} + Esse recurso não é atualmente suportado no banco de dados de SQL Azure e Data Warehouse: {0} + + . + Parameters: 0 - errorMessage (string) + + + An unexpected error occurred during Peek Definition execution: {0} + Ocorreu um erro inesperado durante a execução da inspeção da definição: + + . + Parameters: 0 - errorMessage (string) + + + No results were found. + Nenhum resultado foi encontrado. + + + + + No database object was retrieved. + Nenhum objeto de banco de dados foi recuperado. + + + + + Please connect to a server. + Favor conectar-se a um servidor. + + + + + Operation timed out. + Tempo limite da operação esgotado. + + + + + This object type is currently not supported by this feature. + Este tipo de objeto não é suportado atualmente por esse recurso. + + + + + Position is outside of file line range + Posição está fora do intervalo de linhas do arquivo + + + + + Position is outside of column range for line {0} + A posição está fora do intervalo de colunas para linha {0} + + . + Parameters: 0 - line (int) + + + Start position ({0}, {1}) must come before or be equal to the end position ({2}, {3}) + Posição inicial ({0}, {1}) deve vir antes ou ser igual a posição final ({2}, {3}) + + . + Parameters: 0 - sLine (int), 1 - sCol (int), 2 - eLine (int), 3 - eCol (int) + + + Msg {0}, Level {1}, State {2}, Line {3} + Msg {0}, Nível {1}, Estado {2}, Linha {3} + + + + + Msg {0}, Level {1}, State {2}, Procedure {3}, Line {4} + Msg {0}, Nível {1}, Estado {2}, Procedimento {3}, Linha {4} + + + + + Msg {0}, Level {1}, State {2} + Msg {0}, Nível {1}, Estado {2} + + + + + An error occurred while the batch was being processed. The error message is: {0} + Ocorreu um erro durante o processamento do lote. A mensagem de erro é: {0} + + + + + ({0} row(s) affected) + ({0} linhas afetadas) + + + + + The previous execution is not yet complete. + Execução anterior ainda não foi concluída. + + + + + A scripting error occurred. + Ocorreu um erro de script. + + + + + Incorrect syntax was encountered while {0} was being parsed. + Sintaxe incorreta foi encontrada enquanto {0} estava sendo analisado. + + + + + A fatal error occurred. + Ocorreu um erro fatal. + + + + + Batch execution completed {0} times... + Execução concluída {0} vezes... + + + + + You cancelled the query. + Você cancelou a consulta. + + + + + An error occurred while the batch was being executed. + Ocorreu um erro enquanto o lote estava sendo executado. + + + + + An error occurred while the batch was being executed, but the error has been ignored. + Ocorreu um erro enquanto o lote estava sendo executado, mas o erro foi ignorado. + + + + + Beginning execution loop + Beginning execution loop + + + + + Command {0} is not supported. + Comando {0} não é suportado. + + + + + The variable {0} could not be found. + A variável {0} não pôde ser encontrada. + + + + + SQL Execution error: {0} + Erro de execução de SQL: {0} + + + + + Batch parser wrapper execution: {0} found... at line {1}: {2} Description: {3} + Execução do pacote do analisador de lotes: {0} encontrado... na linha {1}: {2} Descrição: {3} + + + + + Batch parser wrapper execution engine batch message received: Message: {0} Detailed message: {1} + Mensagem recebida do motor de execução do pacote do analisador de lotes: Mensagem: {0} Mensagem detalhada: {1} + + + + + Batch parser wrapper execution engine batch ResultSet processing: DataReader.FieldCount: {0} DataReader.RecordsAffected: {1} + Processando o conjunto de resultados no motor de execução do pacote do analisador de lotes: DataReader.FieldCount: {0} DataReader.RecordsAffected: {1} + + + + + Batch parser wrapper execution engine batch ResultSet finished. + Execução do conjunto de resultados do motor de execução de pacotes do analisador de lotes terminada. + + + + + Canceling batch parser wrapper batch execution. + Cancelando execução do conjunto de resultados do motor de execução de pacotes do analisador de lotes. + + + + + Scripting warning. + Aviso de script. + + + + + For more information about this error, see the troubleshooting topics in the product documentation. + Para obter mais informações sobre esse erro, consulte os tópicos de solução de problemas na documentação do produto. + + + + + File '{0}' recursively included. + Arquivo '{0}' incluído recursivamente. + + + + + Missing end comment mark '*/'. + Sem marca de comentário final ' * /'. + + + + + Unclosed quotation mark after the character string. + Aspas não fechadas depois da sequência de caracteres. + + + + + Incorrect syntax was encountered while parsing '{0}'. + Sintaxe incorreta foi encontrada enquanto {0} estava sendo analisado. + + + + + Variable {0} is not defined. + A variável {0} não está definida. + + + + + test + teste + + + + + Replacement of an empty string by an empty string. + Substituição de uma sequência vazia por uma cadeia de caracteres vazia. + + + + + Edit session does not exist. + Sessão de edição não existe. + + + + + Query has not completed execution + A consulta não completou a execução + + + + + Query did not generate exactly one result set + A consulta não gerou exatamente um conjunto de resultados + + + + + Failed to add new row to update cache + Falha ao adicionar uma nova linha ao cache de atualização + + + + + Given row ID is outside the range of rows in the edit cache + ID de linha de entrada fora da faixa de linhas no cache de edição + + + + + An update is already pending for this row and must be reverted first + Uma atualização está ainda pendente para esta linha e deve ser revertida antes + + + + + Given row ID does not have pending update + Não existem atualizações pendentes para o ID informado. + + + + + Table or view metadata could not be found + Tabela ou view de metadados não pode ser encontrada + + + + + Invalid format for binary column + Formato inválido para coluna binária + + + + + Allowed values for boolean columns are 0, 1, "true", or "false" + Colunas Booleanas devem possuir o número 1 ou 0 ou a string true ou false + + + + + The column '{0}' is defined as NOT NULL but was not given a value + Um valor requerido para a célula está faltando + + . + Parameters: 0 - colName (string) + + + A delete is pending for this row, a cell update cannot be applied. + Uma exclusão está pendente para esta linha. Uma atualização desta célula não pode ser aplicada. + + + + + Column ID must be in the range of columns for the query + Um ID de coluna deve estar no intervalo de colunas para a consulta + + + + + Column cannot be edited + Coluna não pode ser editada + + + + + No key columns were found + Não foram encontradas colunas chave + + + + + An output filename must be provided + Um nome de arquivo de saída deve ser fornecido + + + + + Database object {0} cannot be used for editing. + O objecto de banco de dados {0} não pode ser usado para edição. + + . + Parameters: 0 - typeName (string) + + + Specified URI '{0}' does not have a default connection + A URI especificada '{0}' não tem uma conexão padrão + + . + Parameters: 0 - uri (string) + + + A commit task is in progress. Please wait for completion. + Uma tarefa de gravação está em progresso. Favor aguardar o térnino. + + + + + Decimal column is missing numeric precision or numeric scale + Coluna decimal não tem precisão numérica ou escala numérica + + + + + <TBD> + <TBD> + + + + + Cannot add row to result buffer, data reader does not contain rows + Não é possível adicionar linha ao buffer de resultados, o datareader não contém linhas + + + + + TIME column values must be between 00:00:00.0000000 and 23:59:59.9999999 + Os valores da coluna do tipo de dados TIME devem estar entre 00:00:00.0000000 e 23:59:59.9999999 + + + + + NULL is not allowed for this column + Nulo não é permitido para esta coluna. + + + + + Edit session already exists. + Sessão de edição já existe. + + + + + Edit session has not been initialized + Sessão de edição não foi inicializada + + + + + Edit session has already been initialized + Sessão de edição já foi inicializada + + + + + Edit session has already been initialized or is in the process of initializing + Sessão de edição já foi inicializada ou está em processo de inicialização + + + + + Query execution failed, see messages for details + A execução da consulta falhou, veja as mensagens para detalhes + + + + + Result limit cannot be negative + Limite de resultados não pode ser negativo + + + + + NULL + NULL + + + + + A object name must be provided + O nome do objeto deve ser fornecido. + + + + + Explicitly specifying server or database is not supported + O servidor ou banco de dados especificado não é suportado. + + + + + Table metadata does not have extended properties + Metadados da tabela não possuem propriedades extendidas + + + + + Table or view requested for edit could not be found + Tabela ou view requisitada para edição não foi encontrada + + + + + Error expanding: {0} + Erro expandindo: {0} + + + + + Error connecting to {0} + Erro conectando a {0} + + + + + Aggregates + Agregados + + + + + Server Roles + Funcões de Servidor + + + + + Application Roles + Funções de Aplicação + + + + + Assemblies + Assemblies + + + + + Assembly Files + Arquivos de Assemblies + + + + + Asymmetric Keys + Chaves Assimétricas + + + + + Asymmetric Keys + Chaves Assimétricas + + + + + Data Compression Options + Opções de Compressão de Dados + + + + + Certificates + Certificados + + + + + FileTables + Tabelas de Arquivos + + + + + Certificates + Certificados + + + + + Check Constraints + Verificação de Restrições + + + + + Columns + Colunas + + + + + Constraints + Restrições + + + + + Contracts + Contratos + + + + + Credentials + Credenciais + + + + + Error Messages + Mensagens de Erro + + + + + Server Role Membership + Adesão às Funções de Servidor + + + + + Database Options + Opções de Banco de Dados + + + + + Database Roles + Funções de Bancos de Dados + + + + + Role Memberships + Adesão às Funções + + + + + Database Triggers + Gatilhos de Bancos de Dados + + + + + + Default Constraints + Restrições Padrão + + + + + Defaults + Padrões + + + + + Sequences + Sequências + + + + + Endpoints + Pontos finais + + + + + Event Notifications + Notificações de Eventos + + + + + Server Event Notifications + Notificações de Eventos de Servidor + + + + + Extended Properties + Propriedades Extendidas + + + + + Filegroups + Grupos de Arquivos + + + + + Foreign Keys + Chaves Estrangeiras + + + + + Full-Text Catalogs + Catálogos Full-Text + + + + + Full-Text Indexes + Índices Full-Text + + + + + Functions + Funções + + + + + Indexes + Índices + + + + + Inline Functions + Funções em Linha + + + + + Keys + Chaves + + + + + Linked Servers + Servidores vinculados + + + + + Linked Server Logins + Logins de servidores vinculados + + + + + Logins + Logins + + + + + Master Key + Master key + + + + + Master Keys + Master Keys + + + + + Message Types + Tipos de Mensagens + + + + + Table-Valued Functions + Funções de Valor de Tabelas + + + + + Parameters + Parâmetros + + + + + Partition Functions + Funções de Partição + + + + + Partition Schemes + Esquemas de Partição + + + + + Permissions + Permissões + + + + + Primary Keys + Chaves Primárias + + + + + Programmability + Programabilidade + + + + + Queues + Filas + + + + + Remote Service Bindings + Ligações de Serviço Remoto + + + + + Returned Columns + Colunas Retornadas + + + + + Roles + Funções + + + + + Routes + Rotas + + + + + Rules + Regras + + + + + Schemas + Esquemas + + + + + Security + Segurança + + + + + Server Objects + Objetos de Servidor + + + + + Management + Gerenciamento + + + + + Triggers + Gatilhos + + + + + Service Broker + Service Broker + + + + + Services + Serviços + + + + + Signatures + Assinaturas + + + + + Log Files + Arquivos de Log + + + + + Statistics + Estatísticas + + + + + Storage + Armazenamento + + + + + Stored Procedures + Stored Procedures + + + + + Symmetric Keys + Chaves Simétricas + + + + + Synonyms + Sinônimos + + + + + Tables + Tabelas + + + + + Triggers + Gatilhos + + + + + Types + Tipos + + + + + Unique Keys + Chaves Únicas + + + + + User-Defined Data Types + Tipos de Dados Definidos pelo Usuário + + + + + User-Defined Types (CLR) + Tipos Definidos pelo Usuário (CLR) + + + + + Users + Usuários + + + + + Views + Visualizações + + + + + XML Indexes + Índices XML + + + + + XML Schema Collections + Coleções de Esquemas XML + + + + + User-Defined Table Types + Tipos de Tabelas Definidas pelo Usuário + + + + + Files + Arquivos + + + + + Missing Caption + Título Faltando + + + + + Broker Priorities + Prioridades do Agente + + + + + Cryptographic Providers + Provedores de Criptografia + + + + + Database Audit Specifications + Especificações de Auditoria de Banco de Dados + + + + + Database Encryption Keys + Chaves de Criptografia de Banco de Dados + + + + + Event Sessions + Sessões de Evento + + + + + Full Text Stoplists + Listas de Parada Full Text + + + + + Resource Pools + Pool de Recursos + + + + + Audits + Auditorias + + + + + Server Audit Specifications + Especificações de Auditoria de Servidor + + + + + Spatial Indexes + Índices Espaciais + + + + + Workload Groups + Grupos de Trabalho + + + + + SQL Files + Arquivos SQL + + + + + Server Functions + Funções de Servidor + + + + + SQL Type + Tipo SQL + + + + + Server Options + Opções de Servidor + + + + + Database Diagrams + Diagramas de Banco de Dados + + + + + System Tables + Tabelas do Sistema + + + + + Databases + Bancos de Dados + + + + + System Contracts + Contratos do Sistema + + + + + System Databases + Bancos de Dados do Sistema + + + + + System Message Types + Tipos de Mensagens do Sistema + + + + + System Queues + Filas do Sistema + + + + + System Services + Serviços do Sistema + + + + + System Stored Procedures + Stored Procedures do Sistema + + + + + System Views + Visualizações do Sistema + + + + + Data-tier Applications + Aplicações da Camada de Dados + + + + + Extended Stored Procedures + Stored Procedures Estendidas + + + + + Aggregate Functions + Funções Agregadas + + + + + Approximate Numerics + Numéricos Aproximados + + + + + Binary Strings + Cadeias de Caracteres Binárias + + + + + Character Strings + Cadeias de Caracteres + + + + + CLR Data Types + Tipos de Dados CLR + + + + + Configuration Functions + Funções de Configuração + + + + + Cursor Functions + Funções de Cursor + + + + + System Data Types + Tipos de Dados do Sistema + + + + + Date and Time + Data e Hora + + + + + Date and Time Functions + Funções de Data e Hora + + + + + Exact Numerics + Numéricos Exatos + + + + + System Functions + Funções do Sistema + + + + + Hierarchy Id Functions + Funções de ID de Hierarquia + + + + + Mathematical Functions + Funções Matemáticas + + + + + Metadata Functions + Funções de Metadados + + + + + Other Data Types + Outros tipos de Dados + + + + + Other Functions + Outras Funções + + + + + Rowset Functions + Funções de Conjuntos de Linhas + + + + + Security Functions + Funções de Segurança + + + + + Spatial Data Types + Tipos de Dados Espaciais + + + + + String Functions + Funções de Cadeias de Caracteres + + + + + System Statistical Functions + Funções Estatísticas do Sistema + + + + + Text and Image Functions + Funções de Texto e Imagem + + + + + Unicode Character Strings + Cadeias de Caracteres Unicode + + + + + Aggregate Functions + Funções Agregadas + + + + + Scalar-valued Functions + Funções de Valores Escalares + + + + + Table-valued Functions + Funções de Valores Baseadas em Tabelas + + + + + System Extended Stored Procedures + Stored Procedures do Sistema Estendidas + + + + + Built-in Types + Tipos Intrínsecos + + + + + Built-in Server Roles + Funções de Servidor Intrínsecas + + + + + User with Password + Usuário com Senha + + + + + Search Property List + Pesquisar Lista de Propriedades + + + + + Security Policies + Políticas de Segurança + + + + + Security Predicates + Predicados de Segurança + + + + + Server Role + Função de Servidor + + + + + Search Property Lists + Pesquisar Listas de Propriedades + + + + + Column Store Indexes + Índices de Colunas + + + + + Table Type Indexes + Índices de Tipos de Tabelas + + + + + Selective XML Indexes + Índices XML Seletivos + + + + + XML Namespaces + Namespaces XML + + + + + XML Typed Promoted Paths + Caminhos Promovidos de Tipos XML + + + + + T-SQL Typed Promoted Paths + Caminhos Promovidos de Tipos T-SQL + + + + + Database Scoped Credentials + Credenciais de Escopo de Banco de Dados + + + + + External Data Sources + Fontes de Dados Externas + + + + + External File Formats + Formatos de Arquivos Externos + + + + + External Resources + Recursos Externos + + + + + External Tables + Tabelas Externas + + + + + Always Encrypted Keys + Chaves Sempre Criptografadas + + + + + Column Master Keys + Chaves Mestras de Colunas + + + + + Column Encryption Keys + Chaves de Criptografia de Colunas + + + + + Server + Servidor + + + + + Error parsing ScriptingParams.ConnectionString property. + Erro ao analisar a propriedade ScriptingParams.ConnectionString. + + + + + Invalid directory specified by the ScriptingParams.FilePath property. + Diretório inválido especificado pela propriedade ScriptingParams.FilePath. + + + + + Error parsing ScriptingListObjectsCompleteParams.ConnectionString property. + Erro ao analisar a propriedade ScriptingListObjectsCompleteParams.ConnectionString. + + + + + {0} ({1}, {2}, {3}) + {0} ({1}, {2}, {3}) + + + + + No default + Nenhum padrão + + + + + Input + Entrada + + + + + Input/Output + Entrada/Saída + + + + + Input/ReadOnly + Entrada/SomenteLeitura + + + + + Input/Output/ReadOnly + Entrada/Saída/SomenteLeitura + + + + + Default + Padrão + + + + + null + nulo + + + + + not null + não nulo + + + + + {0} ({1}, {2}) + {0} ({1}, {2}) + + + + + {0} ({1}) + {0} ({1}) + + + + + {0} ({1}Computed, {2}, {3}) + {0} ({1} Computado, {2}, {3}) + + + + + {0} ({1}Computed) + {0} ({1}Computado) + + + + + {0} (Column Set, {1}) + {0} (Conjunto de Colunas, {1}) + + + + + {0} (Column Set, {1}{2}, {3}) + {0} (Conjunto de Colunas, {1}{2}, {3}) + + + + + {0} (Column Set, {1}, {2}, {3}) + {0} (Conjunto de Colunas, {1}, {2}, {3}) + + + + + Unique + Exclusivo + + + + + Non-Unique + Não Exclusivo + + + + + Clustered + Clusterizado + + + + + Non-Clustered + Não Clusterizado + + + + + History + Histórico + + + + + System-Versioned + Versionado pelo sistema + + + + + Unavailable + Indisponível + + + + + Current default filegroup: {0} + Grupo de arquivos padrão atual: {0} + + + + + New Filegroup for {0} + Novo Grupo de Arquivos para {0} + + + + + Default + Padrão + + + + + Files + Arquivos + + + + + Name + Nome + + + + + Read-Only + Somente Leitura + + + + + Autogrowth / Maxsize + Auto crescimento / Tamanho máximo + + + + + ... + ... + + + + + <default> + <padrão> + + + + + Filegroup + Grupo de Arquivos + + + + + Logical Name + Nome Lógico + + + + + File Type + Tipo de Arquivo + + + + + Initial Size (MB) + Tamanho Inicial (MB) + + + + + <new filegroup> + <novo grupo de arquivos> + + + + + Path + Caminho + + + + + File Name + Nome do Arquivo + + + + + <raw device> + <dispositivo bruto> + + + + + Bulk-logged + Logado em massa + + + + + Full + Completo + + + + + Simple + Simples + + + + + Select Database Owner + Selecionar o proprietário do banco de dados + + + + + None + Nenhum + + + + + By {0} MB, Limited to {1} MB + Por {0} MB, limitado a {1} MB + + + + + By {0} percent, Limited to {1} MB + Por {0}%, Limitado a {1} mb + + + + + By {0} MB, Unlimited + Por {0} MB, Ilimitado + + + + + By {0} percent, Unlimited + Por {0}%, Ilimitado + + + + + Unlimited + Ilimitado + + + + + Limited to {0} MB + Limitado a {0} MB + + + + + Automatic + Automático + + + + + Service Broker + Service Broker + + + + + Collation + Agrupamento + + + + + Cursor + Cursor + + + + + Miscellaneous + Diversos + + + + + Recovery + Recuperação + + + + + State + Estado + + + + + ANSI NULL Default + Padrão ANSI NULL + + + + + ANSI NULLS Enabled + ANSI NULLS Habilitado + + + + + ANSI Padding Enabled + Preenchimento ANSI habilitado + + + + + ANSI Warnings Enabled + ANSI Warnings Habilitados + + + + + Arithmetic Abort Enabled + Arithmetic Abortar habilitado + + + + + Auto Close + Fechamento automático + + + + + Auto Create Statistics + Criar Estatísticas Automaticamente + + + + + Auto Shrink + Reduzir Automaticamente + + + + + Auto Update Statistics + Estatísticas Atualizadas Automaticamente + + + + + Auto Update Statistics Asynchronously + Atualizar estatísticas automaticamente de forma assíncrona + + + + + Case Sensitive + Sensível à Caixa + + + + + Close Cursor on Commit Enabled + Fechar Cursor na Confirmação Habilitado + + + + + Collation + Agrupamento + + + + + Concatenate Null Yields Null + Concatenar Nulo Produz Nulo + + + + + Database Compatibility Level + Nível de Compatibilidade do Banco de Dados + + + + + Database State + Estado do Banco de Dados + + + + + Default Cursor + Cursor Padrão + + + + + Full-Text Indexing Enabled + Indexação Full-Text Habilitada + + + + + Numeric Round-Abort + Anular arredondamento numérico. + + + + + Page Verify + Verificação de Página + + + + + Quoted Identifiers Enabled + Identificadores Entre Aspas Habilitados + + + + + Database Read-Only + Banco de Dados Somente Leitura + + + + + Recursive Triggers Enabled + Gatilhos Recursivos Habilitados + + + + + Restrict Access + Acesso Restrito + + + + + Select Into/Bulk Copy + Selecionar Cópia Into/Em Massa + + + + + Honor Broker Priority + Respeitar a Prioridade do Broker + + + + + Service Broker Identifier + Identificador de agente de serviço + + + + + Broker Enabled + Agente habilitado + + + + + Truncate Log on Checkpoint + Truncar o Log no Ponto de Verificação + + + + + Cross-database Ownership Chaining Enabled + Encadeamento de Propriedades de Bancos de Dados Habilitado + + + + + Trustworthy + Confiável + + + + + Date Correlation Optimization Enabled + Otimizaçao da Correlação de Data Enabledprototype_db_prop_parameterization = Parametrização + + + + + Forced + Forçado + + + + + Simple + Simples + + + + + ROWS Data + Dados ROWS + + + + + LOG + LOG + + + + + FILESTREAM Data + Dados FILESTREAM + + + + + Not Applicable + Não aplicável + + + + + <default path> + <caminho padrão> + + + + + Open Connections + Conexões Abertas + + + + + To change the database properties, SQL Server must close all other connections to the database_ Are you sure you want to change the properties and close all other connections? + 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 + AUTO_CLOSED + + + + + EMERGENCY + EMERGÊNCIA + + + + + INACCESSIBLE + INACESSÍVEL + + + + + NORMAL + NORMAL + + + + + OFFLINE + OFF-LINE + + + + + RECOVERING + RECUPERANDO + + + + + RECOVERY PENDING + RECUPERAÇÃO PENDENTE + + + + + RESTORING + RESTAURANDO + + + + + SHUTDOWN + DESLIGAMENTO + + + + + STANDBY + MODO DE ESPERA + + + + + SUSPECT + SUSPEITO + + + + + GLOBAL + GLOBAL + + + + + LOCAL + LOCAL + + + + + MULTI_USER + MULTI_USUÁRIO + + + + + RESTRICTED_USER + USUÁRIO_RESTRITO + + + + + SINGLE_USER + MONO_USUÁRIO + + + + + CHECKSUM + SOMA DE VERIFICAÇÃO + + + + + NONE + NENHUM + + + + + TORN_PAGE_DETECTION + TORN_PAGE_DETECTION + + + + + VarDecimal Storage Format Enabled + Formato de Armazenamento VarDecimal Habilitado + + + + + SQL Server 2008 (100) + SQL Server 2008 (100) + + + + + Encryption Enabled + Criptografia Habilitada + + + + + OFF + DESLIGADO + + + + + ON + LIGADO + + + + + PRIMARY + PRIMÁRIO + + + + + For the distribution policy HASH, the number of leading hash columns is optional but should be from 1 to 16 columns + 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 2012 (110) + + + + + SQL Server 2014 (120) + SQL Server 2014 (120) + + + + + SQL Server 2016 (130) + SQL Server 2016 (130) + + + + + SQL Server vNext (140) + SQL Server vNext (140) + + + + + None + Nenhum + + + + + Partial + Parcial + + + + + FILESTREAM Files + Arquivos FILESTREAM + + + + + No Applicable Filegroup + Nenhum grupo de arquivos aplicável + + + + + The database {0} is not accessible. + O banco de dados {0} não está acessível. + + + + + Query has no results to return + A consulta não tem resultado para retornar + + + + + Result set has too many rows to be safely loaded + Conjunto de resultados tem muitas linhas para ser carregado com segurança + + + + Parameterization + Parametrização + + + + + Specifying this option when restoring a backup with the NORECOVERY option is not permitted. + Não é permitido especificar essa opção ao restaurar um backup com a opção NORECOVERY. + + + + + Invalid path for database file: '{0}' + Caminho inválido para o arquivo de banco de dados: '{0}' + + + + + Log + Log + + + + + Failed to create restore plan + Falha ao criar o plano de restauração + + + + + Restore database is not supported + Restauração de banco de dados não é suportado + + + + + Restore Database + Restaurar o banco de dados + + + + + (Copy Only) + (Apenas cópia) + + + + + Component + Componente + + + + + Type + Tipo + + + + + Server + Servidor + + + + + Database + Banco de dados + + + + + Position + Posição + + + + + First LSN + Primeiro LSN + + + + + Last LSN + Último LSN + + + + + Checkpoint LSN + Checkpoint LSN + + + + + Full LSN + LSN completo + + + + + Start Date + Data de Início + + + + + Finish Date + Data de Término + + + + + Size + Tamanho + + + + + User Name + Nome do usuário + + + + + Expiration + Expiração + + + + + Name + Nome + + + + + The last backup taken ({0}) + O último backup feito ({0}) + + + + + Backup Database + Backup do Banco de Dados + + + + + In progress + Em andamento + + + + + Completed + Concluído + + + + + scripting + Gerando script + + + + + Connection not found + Conexão não encontrada + + + + + Please provide a file path instead of directory path + O nome do arquivo especificado também é um nome de diretório: {0} + + + + + The provided path is invalid + Não foi possível verificar a existência do local do arquivo de backup: {0} + + + + + Cannot access the specified path on the server: {0} + Não foi possível acessar o diretório especificado no servidor: {0} + + + + + No backupset selected to be restored + Nenhum conjunto de backup selecionado para ser restaurado + + + + + Never + Nunca + + + + + Azure SQL DB + Azure SQL DB + + + + + Azure SQL Data Warehouse + Azure SQL Data Warehouse + + + + + Azure SQL Stretch Database + Azure SQL Stretch Database + + + + + Path {0} is not a valid directory + Caminho {0} não é um diretório válido + + + + + For directory {0} a file with name {1} already exists + Já existe um arquivo com nome {1} para o diretório {0} + + + + + Value {0} is too large to fit in column of type {1} + Valor {0} é muito grande para caber em uma coluna do tipo {1} + + . + Parameters: 0 - value (string), 1 - columnType (string) + + + + \ No newline at end of file diff --git a/src/Microsoft.SqlTools.CoreServices/Localization/transXliff/sr.ru.xlf b/src/Microsoft.SqlTools.CoreServices/Localization/transXliff/sr.ru.xlf new file mode 100644 index 00000000..b9c31434 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Localization/transXliff/sr.ru.xlf @@ -0,0 +1,2769 @@ + + + + + Connection parameters cannot be null + Параметры подключения должны быть указаны, значение не может быть неопределенным (null) + + + + + OwnerUri cannot be null or empty + OwnerUri не может быть неопределенным или пустым + + + + + SpecifiedUri '{0}' does not have existing connection + SpecifiedUri «{0}» не имеет существующего подключения + + . + Parameters: 0 - uri (string) + + + Invalid value '{0}' for AuthenticationType. Valid values are 'Integrated' and 'SqlLogin'. + Значение «{0}» недопустимо для AuthenticationType. Ожидается значение «Integrated» или «SqlLogin». + + . + Parameters: 0 - authType (string) + + + Invalid value '{0}' for ApplicationIntent. Valid values are 'ReadWrite' and 'ReadOnly'. + Значение «{0}» недопустимо для ApplicationIntent. Ожидается значение «ReadWrite» или «ReadOnly». + + . + Parameters: 0 - intent (string) + + + Connection canceled + Подключение к серверу отменено. + + + + + OwnerUri cannot be null or empty + OwnerUri не может быть неопределенным или пустым + + + + + Connection details object cannot be null + Параметры подключения не могут быть неопределенными + + + + + ServerName cannot be null or empty + Имя сервера не может быть неопределенным или пустым + + + + + {0} cannot be null or empty when using SqlLogin authentication + {0} не может быть неопределенным или пустым при использовании проверки подлинности SqlLogin + + . + Parameters: 0 - component (string) + + + The query has already completed, it cannot be cancelled + Запрос уже был выполнен, отмена невозможна + + + + + Query successfully cancelled, failed to dispose query. Owner URI not found. + Запрос успешно отменен, но удалить запрос не удалось. Владелец URI не найден. + + + + + Query was canceled by user + Выполнение запроса отменено пользователем + + + + + The batch has not completed, yet + Пакет еще не завершен + + + + + Batch index cannot be less than 0 or greater than the number of batches + Индекс пакета не может быть меньше нуля или больше числа пакетов + + + + + Result set index cannot be less than 0 or greater than the number of result sets + Индекс не может быть меньше нуля или больше количества записей в наборе + + + + + Maximum number of bytes to return must be greater than zero + Максимальное количество возвращаемых байтов должно быть больше нуля + + + + + Maximum number of chars to return must be greater than zero + Максимальное количество возвращаемых символов должно быть больше нуля + + + + + Maximum number of XML bytes to return must be greater than zero + Максимальное количество возвращаемых из XML байтов должно быть больше нуля + + + + + Access method cannot be write-only + Метод доступа не может быть только для записи. + + + + + FileStreamWrapper must be initialized before performing operations + FileStreamWrapper должен быть инициализирован перед выполнением операций + + + + + This FileStreamWrapper cannot be used for writing + Этот экземпляр FileStreamWrapper не может быть использован для записи + + + + + (1 row affected) + (одна строка затронута) + + + + + ({0} rows affected) + ({0} строк затронуто) + + . + Parameters: 0 - rows (long) + + + Commands completed successfully. + Выполнение команд успешно завершено. + + + + + Msg {0}, Level {1}, State {2}, Line {3}{4}{5} + Сообщение {0}, Уровень {1}, Состояние {2}, Строка {3}{4}{5} + + . + Parameters: 0 - msg (int), 1 - lvl (int), 2 - state (int), 3 - line (int), 4 - newLine (string), 5 - message (string) + + + Query failed: {0} + Не удалось выполнить запрос: {0} + + . + Parameters: 0 - message (string) + + + (No column name) + (Нет имени столбца) + + + + + The requested query does not exist + Указанный запрос не найден + + + + + This editor is not connected to a database + Этот редактор не подключен к базе данных + + + + + A query is already in progress for this editor session. Please cancel this query or wait for its completion. + Запрос уже выполняется для данного сеанса редактора. Отмените запрос или дождитесь завершения его выполнения. + + + + + Sender for OnInfoMessage event must be a SqlConnection + В качестве отправителя (sender) для события OnInfoMessage ожидается экземпляр SqlConnection + + + + + Result cannot be saved until query execution has completed + Результат не может быть сохранен до завершения выполнения запроса + + + + + Internal error occurred while starting save task + При запуске задачи сохранения произошла внутренняя ошибка + + + + + A save request to the same path is in progress + По указанному пути уже выполняется сохранение результатов + + + + + Failed to save {0}: {1} + Не удалось сохранить {0}: {1} + + . + Parameters: 0 - fileName (string), 1 - message (string) + + + Cannot read subset unless the results have been read from the server + Невозможно прочитать подмножество, поскольку результаты еще не были получены с сервера + + + + + Start row cannot be less than 0 or greater than the number of rows in the result set + Индекс начальной строки не может быть меньше нуля или больше количества строк, находящихся в результирующем наборе + + + + + Row count must be a positive integer + Число строк должно быть положительным целым числом + + + + + Could not retrieve column schema for result set + Не удалось получить столбец схемы для результирующего набора + + + + + Could not retrieve an execution plan from the result set + Не удалось получить план выполнения из результирующего набора + + + + + This feature is currently not supported on Azure SQL DB and Data Warehouse: {0} + В настоящее время эта функция не поддерживается Azure SQL DB и Data Warehouse: {0} + + . + Parameters: 0 - errorMessage (string) + + + An unexpected error occurred during Peek Definition execution: {0} + Произошла непредвиденная ошибка во время выполнения Peek Definition: {0} + + . + Parameters: 0 - errorMessage (string) + + + No results were found. + Результаты не найдены. + + + + + No database object was retrieved. + Объект базы данных не был получен. + + + + + Please connect to a server. + Подключитесь к серверу. + + + + + Operation timed out. + Истекло время ожидания операции. + + + + + This object type is currently not supported by this feature. + В настоящее время этот тип объекта не поддерживается этим средством. + + + + + Position is outside of file line range + Позиция выходит за пределы диапазона строк файла + + + + + Position is outside of column range for line {0} + Позиция выходит за пределы диапазона столбцов строки {0} + + . + Parameters: 0 - line (int) + + + Start position ({0}, {1}) must come before or be equal to the end position ({2}, {3}) + Начальная позиция ({0}, {1}) должна быть меньше либо равна конечной ({2}, {3}) + + . + Parameters: 0 - sLine (int), 1 - sCol (int), 2 - eLine (int), 3 - eCol (int) + + + Msg {0}, Level {1}, State {2}, Line {3} + Сообщение {0}, уровень {1}, состояние {2}, строка {3} + + + + + Msg {0}, Level {1}, State {2}, Procedure {3}, Line {4} + Сообщение {0}, уровень {1}, состояние {2}, процедура {3}, строка {4} + + + + + Msg {0}, Level {1}, State {2} + Сообщение {0}, уровень {1}, состояние {2} + + + + + An error occurred while the batch was being processed. The error message is: {0} + При обработке пакета произошла ошибка: {0} + + + + + ({0} row(s) affected) + ({0} строк затронуто) + + + + + The previous execution is not yet complete. + Предыдущее выполнение еще не завершено. + + + + + A scripting error occurred. + Произошла ошибка сценария. + + + + + Incorrect syntax was encountered while {0} was being parsed. + Обнаружен неправильный синтаксис при обработке {0}. + + + + + A fatal error occurred. + Произошла неустранимая ошибка. + + + + + Batch execution completed {0} times... + Выполнение завершено такое количество раз: {0}... + + + + + You cancelled the query. + Пользователь отменил запрос. + + + + + An error occurred while the batch was being executed. + При выполнении пакета произошла ошибка. + + + + + An error occurred while the batch was being executed, but the error has been ignored. + В процессе выполнения пакета произошла ошибка, но она была проигнорирована. + + + + + Beginning execution loop + Beginning execution loop + + + + + Command {0} is not supported. + Команда {0} не поддерживается. + + + + + The variable {0} could not be found. + Переменная {0} не найдена. + + + + + SQL Execution error: {0} + Ошибка выполнения SQL: {0} + + + + + Batch parser wrapper execution: {0} found... at line {1}: {2} Description: {3} + BatchParserWrapper: {0} найдено; строка {1}: {2}; описание: {3} + + + + + Batch parser wrapper execution engine batch message received: Message: {0} Detailed message: {1} + BatchParserWrapper получено сообщение: {0}. Детали: {1} + + + + + Batch parser wrapper execution engine batch ResultSet processing: DataReader.FieldCount: {0} DataReader.RecordsAffected: {1} + BatchParserWrapper выполнение пакетной обработки ResultSet. DataReader.FieldCount: {0} DataReader.RecordsAffected: {1} + + + + + Batch parser wrapper execution engine batch ResultSet finished. + BatchParserWrapper: обработка завершена. + + + + + Canceling batch parser wrapper batch execution. + BatchParserWrapper: выполнение пакета отменено. + + + + + Scripting warning. + Сценарий содержит предупреждения. + + + + + For more information about this error, see the troubleshooting topics in the product documentation. + Для получения дополнительной информации об этой ошибке, обратитесь к разделам по устранению неполадок в документации по продукту. + + + + + File '{0}' recursively included. + Обнаружена рекурсивная ссылка на файл «{0}». + + + + + Missing end comment mark '*/'. + Отсутствует обозначение конца комментария - «*/». + + + + + Unclosed quotation mark after the character string. + Незакрытые кавычки в конце символьной строки. + + + + + Incorrect syntax was encountered while parsing '{0}'. + При разборе «{0}» обнаружен неправильный синтаксис. + + + + + Variable {0} is not defined. + Переменная {0} не определена. + + + + + test + тест + + + + + Replacement of an empty string by an empty string. + Замена пустой строки на пустую строку. + + + + + Edit session does not exist. + Сеанс не найден. + + + + + Query has not completed execution + Выполнение запроса не завершено + + + + + Query did not generate exactly one result set + Запрос должен содержать только один набор результатов + + + + + Failed to add new row to update cache + Не удалось добавить новую строку в кэш обновлений + + + + + Given row ID is outside the range of rows in the edit cache + Указанный идентификатор строки находится за пределами диапазона строк в кэше редактирования + + + + + An update is already pending for this row and must be reverted first + Обновление уже отправлено для этой строки и должно быть отменено первым + + + + + Given row ID does not have pending update + Для указанной строки нет обновлений в очереди + + + + + Table or view metadata could not be found + Не удалось найти метаданные таблицы или представления + + + + + Invalid format for binary column + Недопустимый формат данных для двоичного столбца + + + + + Allowed values for boolean columns are 0, 1, "true", or "false" + Логические столбцы должны содержать число 1 или 0, либо строку true или false + + + + + The column '{0}' is defined as NOT NULL but was not given a value + Недопустимое значение ячейки + + . + Parameters: 0 - colName (string) + + + A delete is pending for this row, a cell update cannot be applied. + Обновление ячейки не может быть применено, поскольку для данной строки ожидается удаление. + + + + + Column ID must be in the range of columns for the query + Идентификатор столбца должен находиться в диапазоне столбцов запроса + + + + + Column cannot be edited + Столбец не может быть изменен + + + + + No key columns were found + Ключевые поля не найдены + + + + + An output filename must be provided + Должно быть указано имя выходного файла + + + + + Database object {0} cannot be used for editing. + Объект базы данных {0} не может использоваться для редактирования. + + . + Parameters: 0 - typeName (string) + + + Specified URI '{0}' does not have a default connection + Указанный URI '{0}' не имеет соединения по умолчанию + + . + Parameters: 0 - uri (string) + + + A commit task is in progress. Please wait for completion. + Выполняется фиксация. Пожалуйста, дождитесь завершения. + + + + + Decimal column is missing numeric precision or numeric scale + В десятичном столбце отсутствует числовая точность или масштаб + + + + + <TBD> + <TBD> + + + + + Cannot add row to result buffer, data reader does not contain rows + Невозможно добавить строку в файл буфера, поток не содержит строк + + + + + TIME column values must be between 00:00:00.0000000 and 23:59:59.9999999 + Значение столбца TIME должно находиться в диапазоне между 00:00:00.0000000 и 23:59:59.9999999 + + + + + NULL is not allowed for this column + Значение NULL недопустимо в этом столбце. + + + + + Edit session already exists. + Сеанс редактирования уже существует. + + + + + Edit session has not been initialized + Сеанс редактирования не был инициализирован. + + + + + Edit session has already been initialized + Сеанс редактирования уже был инициализирован. + + + + + Edit session has already been initialized or is in the process of initializing + Сеанс редактирования уже был инициализирован или находится в процессе инициализации + + + + + Query execution failed, see messages for details + Не удалось выполнить запрос, см. сообщения для получения подробностей + + + + + Result limit cannot be negative + Значение, определяющее ограничение числа записей, не может быть отрицательным + + + + + NULL + NULL + + + + + A object name must be provided + Должно быть указано имя объекта + + + + + Explicitly specifying server or database is not supported + Явное указание сервера или базы данных не поддерживается + + + + + Table metadata does not have extended properties + Метаданные таблицы не имеют расширенных свойств + + + + + Table or view requested for edit could not be found + Запрошенная таблица или представление не найдены. + + + + + Error expanding: {0} + Ошибка при расширении: {0} + + + + + Error connecting to {0} + Ошибка при подключении к {0} + + + + + Aggregates + Статистические выражения + + + + + Server Roles + Роли сервера + + + + + Application Roles + Роли приложения + + + + + Assemblies + Сборки + + + + + Assembly Files + Файлы сборки + + + + + Asymmetric Keys + Асимметричные ключи + + + + + Asymmetric Keys + Асимметричные ключи + + + + + Data Compression Options + Параметры сжатия данных + + + + + Certificates + Сертификаты + + + + + FileTables + Объекты FileTable + + + + + Certificates + Сертификаты + + + + + Check Constraints + Проверочные ограничения + + + + + Columns + Столбцы + + + + + Constraints + Ограничения + + + + + Contracts + Контракты + + + + + Credentials + Учетные данные + + + + + Error Messages + Сообщения об ошибках + + + + + Server Role Membership + Участие в роли сервера + + + + + Database Options + Параметры базы данных + + + + + Database Roles + Роли базы данных + + + + + Role Memberships + Членства в роли + + + + + Database Triggers + Триггеры базы данных + + + + + Default Constraints + Ограничения по умолчанию + + + + + Defaults + Значения по умолчанию + + + + + Sequences + Последовательности + + + + + Endpoints + Конечные точки + + + + + Event Notifications + Уведомления о событиях + + + + + Server Event Notifications + Уведомления о событиях сервера + + + + + Extended Properties + Расширенные свойства + + + + + Filegroups + Файловые группы + + + + + Foreign Keys + Внешние ключи + + + + + Full-Text Catalogs + Полнотекстовые каталоги + + + + + Full-Text Indexes + Полнотекстовые индексы + + + + + Functions + Функции + + + + + Indexes + Индексы + + + + + Inline Functions + Встроенная функции + + + + + Keys + Ключи + + + + + Linked Servers + Связанные серверы + + + + + Linked Server Logins + Имена входа на связанный сервер + + + + + Logins + Имена входа + + + + + Master Key + Главный ключ + + + + + Master Keys + Главные ключи + + + + + Message Types + Типы сообщений + + + + + Table-Valued Functions + Функция с табличным значением + + + + + Parameters + Параметры + + + + + Partition Functions + Функции секционирования + + + + + Partition Schemes + Схемы секционирования + + + + + Permissions + Разрешения + + + + + Primary Keys + Первичные ключи + + + + + Programmability + Программируемость + + + + + Queues + Списки ожидания + + + + + Remote Service Bindings + Привязки удаленных служб + + + + + Returned Columns + Возвращенные столбцы + + + + + Roles + Роли + + + + + Routes + Маршруты + + + + + Rules + Правила + + + + + Schemas + Схемы + + + + + Security + Безопасность + + + + + Server Objects + Объекты сервера + + + + + Management + Управление + + + + + Triggers + Триггеры + + + + + Service Broker + Компонент Service Broker + + + + + Services + Службы + + + + + Signatures + Сигнатуры + + + + + Log Files + Файлы журнала + + + + + Statistics + Статистика + + + + + Storage + Хранилище + + + + + Stored Procedures + Хранимые процедуры + + + + + Symmetric Keys + Симметричные ключи + + + + + Synonyms + Синонимы + + + + + Tables + Таблицы + + + + + Triggers + Триггеры + + + + + Types + Типы + + + + + Unique Keys + Уникальные ключи + + + + + User-Defined Data Types + Определяемые пользователем типы данных + + + + + User-Defined Types (CLR) + Определяемые пользователем типы (CLR) + + + + + Users + Пользователи + + + + + Views + Представления + + + + + XML Indexes + XML-индексы + + + + + XML Schema Collections + Коллекция схем XML + + + + + User-Defined Table Types + Определяемые пользователем типы таблиц + + + + + Files + Файлы + + + + + Missing Caption + Отсутствует заголовок + + + + + Broker Priorities + Приоритеты брокера + + + + + Cryptographic Providers + Поставщики служб шифрования + + + + + Database Audit Specifications + Спецификации аудита базы данных + + + + + Database Encryption Keys + Ключи шифрования базы данных + + + + + Event Sessions + Сеансы событий + + + + + Full Text Stoplists + Полнотекстовые списки стоп-слов + + + + + Resource Pools + Пулы ресурсов + + + + + Audits + Аудит + + + + + Server Audit Specifications + Спецификации аудита сервера + + + + + Spatial Indexes + Пространственные индексы + + + + + Workload Groups + Группы рабочей нагрузки + + + + + SQL Files + Файлы SQL + + + + + Server Functions + Функции сервера + + + + + SQL Type + Тип SQL + + + + + Server Options + Параметры сервера + + + + + Database Diagrams + Диаграммы базы данных + + + + + System Tables + Системные таблицы + + + + + Databases + Базы данных + + + + + System Contracts + Системные контракты + + + + + System Databases + Системные базы данных + + + + + System Message Types + Системные типы сообщений + + + + + System Queues + Системные очереди + + + + + System Services + Системные службы + + + + + System Stored Procedures + Системные хранимые процедуры + + + + + System Views + Системные представления + + + + + Data-tier Applications + Приложения уровня данных + + + + + Extended Stored Procedures + Расширенные хранимые процедуры + + + + + Aggregate Functions + Агрегатные функции + + + + + Approximate Numerics + Приблизительные числовые значения + + + + + Binary Strings + Двоичные строки + + + + + Character Strings + Символьные строки + + + + + CLR Data Types + Типы данных CLR + + + + + Configuration Functions + Функции конфигурации + + + + + Cursor Functions + Функции работы с курсорами + + + + + System Data Types + Системные типы данных + + + + + Date and Time + Дата и время + + + + + Date and Time Functions + Функции даты и времени + + + + + Exact Numerics + Точные числовые значения + + + + + System Functions + Системные функции + + + + + Hierarchy Id Functions + Функции идентификаторов иерархии + + + + + Mathematical Functions + Математические функции + + + + + Metadata Functions + Функции метаданных + + + + + Other Data Types + Другие типы данных + + + + + Other Functions + Другие функции + + + + + Rowset Functions + Функции набора строк + + + + + Security Functions + Функции безопасности + + + + + Spatial Data Types + Пространственные типы данных + + + + + String Functions + Строковые функции + + + + + System Statistical Functions + Системные статистические функции + + + + + Text and Image Functions + Функции для работы с изображениями и текстом + + + + + Unicode Character Strings + Строки символов в Юникоде + + + + + Aggregate Functions + Агрегатные функции + + + + + Scalar-valued Functions + Скалярные функции + + + + + Table-valued Functions + Функции с табличным значением + + + + + System Extended Stored Procedures + Системные расширенные хранимые процедуры + + + + + Built-in Types + Встроенные типы + + + + + Built-in Server Roles + Встроенные роли сервера + + + + + User with Password + Пользователь с паролем + + + + + Search Property List + Список свойств поиска + + + + + Security Policies + Политики безопасности + + + + + Security Predicates + Предикаты безопасности + + + + + Server Role + Роль сервера + + + + + Search Property Lists + Списки свойств поиска + + + + + Column Store Indexes + Индексы хранилища столбцов + + + + + Table Type Indexes + Индексы типов таблиц + + + + + Selective XML Indexes + Селективные XML-индексы + + + + + XML Namespaces + Пространства имен XML + + + + + XML Typed Promoted Paths + Типизированные повышенные пути XML + + + + + T-SQL Typed Promoted Paths + Типизированные повышенные пути T-SQL + + + + + Database Scoped Credentials + Учетные данные для базы данных + + + + + External Data Sources + Внешние источники данных + + + + + External File Formats + Внешние форматы файлов + + + + + External Resources + Внешние ресурсы + + + + + External Tables + Внешние таблицы + + + + + Always Encrypted Keys + Ключи Always Encrypted + + + + + Column Master Keys + Главные ключи столбца + + + + + Column Encryption Keys + Ключи шифрования столбца + + + + + Server + Сервер + + + + + Error parsing ScriptingParams.ConnectionString property. + Ошибка при анализе свойства ScriptingParams.ConnectionString. + + + + + Invalid directory specified by the ScriptingParams.FilePath property. + Недопустимый каталог указан в свойстве ScriptingParams.FilePath. + + + + + Error parsing ScriptingListObjectsCompleteParams.ConnectionString property. + Ошибка при анализе свойства ScriptingListObjectsCompleteParams.ConnectionString. + + + + + {0} ({1}, {2}, {3}) + {0} ({1}, {2}, {3}) + + + + + No default + Нет значения по умолчанию + + + + + Input + Входной + + + + + Input/Output + Входной/выходной + + + + + Input/ReadOnly + Входной/только для чтения + + + + + Input/Output/ReadOnly + Входной/выходной/только для чтения + + + + + Default + Значение по умолчанию + + + + + null + null + + + + + not null + not null + + + + + {0} ({1}, {2}) + {0} ({1}, {2}) + + + + + {0} ({1}) + {0} ({1}) + + + + + {0} ({1}Computed, {2}, {3}) + {0} (вычислено {1}, {2}, {3}) + + + + + {0} ({1}Computed) + {0} (вычислено {1}) + + + + + {0} (Column Set, {1}) + {0} (набор столбцов, {1}) + + + + + {0} (Column Set, {1}{2}, {3}) + {0} (набор столбцов, {1}{2}, {3}) + + + + + {0} (Column Set, {1}, {2}, {3}) + {0} (набор столбцов, {1}, {2}, {3}) + + + + + Unique + UNIQUE + + + + + Non-Unique + Неуникальный + + + + + Clustered + Кластеризованный + + + + + Non-Clustered + Некластеризованный + + + + + History + Журнал + + + + + System-Versioned + Системно-версионный + + + + + Unavailable + Недоступно + + + + + Current default filegroup: {0} + Текущая файловая группа по умолчанию: {0} + + + + + New Filegroup for {0} + Создание файловой группы для {0} + + + + + Default + Значение по умолчанию + + + + + Files + Файлы + + + + + Name + Имя + + + + + Read-Only + Только для чтения + + + + + Autogrowth / Maxsize + Автоувеличение/максимальный размер + + + + + ... + ... + + + + + <default> + <по умолчанию> + + + + + Filegroup + Группа файлов + + + + + Logical Name + Логическое имя + + + + + File Type + Тип файла + + + + + Initial Size (MB) + Начальный размер (МБ) + + + + + <new filegroup> + <создать файловую группу> + + + + + Path + Путь + + + + + File Name + Имя файла + + + + + <raw device> + <неформатированный носитель> + + + + + Bulk-logged + С неполным протоколированием + + + + + Full + Полная + + + + + Simple + Простая + + + + + Select Database Owner + Выбор владельца базы данных + + + + + None + Нет + + + + + By {0} MB, Limited to {1} MB + С шагом по {0} МБ до {1} МБ + + + + + By {0} percent, Limited to {1} MB + С шагом по {0}% до {1} МБ + + + + + By {0} MB, Unlimited + С шагом по {0} МБ, без ограничений + + + + + By {0} percent, Unlimited + С шагом по {0} %, без ограничений + + + + + Unlimited + Без ограничений + + + + + Limited to {0} MB + Ограничено {0} МБ + + + + + Automatic + Автоматически + + + + + Service Broker + Service Broker + + + + + Collation + Параметры сортировки + + + + + Cursor + Курсор + + + + + Miscellaneous + Прочее + + + + + Recovery + Восстановление + + + + + State + Состояние + + + + + ANSI NULL Default + По умолчанию ANSI NULL + + + + + ANSI NULLS Enabled + Значения ANSI NULLS включены + + + + + ANSI Padding Enabled + Включено заполнение ANSI + + + + + ANSI Warnings Enabled + Включены предупреждения ANSI + + + + + Arithmetic Abort Enabled + Включено прерывание при делении на ноль + + + + + Auto Close + Auto Close + + + + + Auto Create Statistics + Автоматическое создание статистики + + + + + Auto Shrink + Автоматическое сжатие + + + + + Auto Update Statistics + Автоматическое обновление статистики + + + + + Auto Update Statistics Asynchronously + Асинхронное автообновление статистики + + + + + Case Sensitive + Case Sensitive + + + + + Close Cursor on Commit Enabled + Закрывать курсор при разрешении фиксации + + + + + Collation + Параметры сортировки + + + + + Concatenate Null Yields Null + Объединение со значением NULL дает NULL + + + + + Database Compatibility Level + Уровень совместимости базы данных + + + + + Database State + Состояние базы данных + + + + + Default Cursor + Курсор по умолчанию + + + + + Full-Text Indexing Enabled + Полнотекстовое индексирование включено + + + + + Numeric Round-Abort + Автоокругление чисел + + + + + Page Verify + Проверка страниц + + + + + Quoted Identifiers Enabled + Включены заключенные в кавычки идентификаторы + + + + + Database Read-Only + База данных только для чтения + + + + + Recursive Triggers Enabled + Включены рекурсивные триггеры + + + + + Restrict Access + Ограничение доступа + + + + + Select Into/Bulk Copy + Выбор/Массовое копирование + + + + + Honor Broker Priority + Учитывать приоритет компонента Honor Broker + + + + + Service Broker Identifier + Идентификатор компонента Service Broker + + + + + Broker Enabled + Включен компонент Broker + + + + + Truncate Log on Checkpoint + Усечение журнала на контрольной точке + + + + + Cross-database Ownership Chaining Enabled + Межбазовые цепочки владения включены + + + + + Trustworthy + Заслуживает доверия + + + + + Date Correlation Optimization Enabled + Date Correlation Optimization Enabledprototype_db_prop_parameterization = Parameterization + + + + + Forced + Принудительное + + + + + Simple + Простая + + + + + ROWS Data + Данные СТРОК + + + + + LOG + ЖУРНАЛ + + + + + FILESTREAM Data + Данные FILESTREAM + + + + + Not Applicable + Неприменимо + + + + + <default path> + <default path> + + + + + Open Connections + Открытые соединения + + + + + To change the database properties, SQL Server must close all other connections to the database_ Are you sure you want to change the properties and close all other connections? + Чтобы изменить свойства базы данных, SQL Server должен закрыть все остальные соединения с этой базой данных. Изменить свойства и закрыть остальные соединения? + + + + + AUTO_CLOSED + AUTO_CLOSED + + + + + EMERGENCY + EMERGENCY + + + + + INACCESSIBLE + INACCESSIBLE + + + + + NORMAL + NORMAL + + + + + OFFLINE + OFFLINE + + + + + RECOVERING + RECOVERING + + + + + RECOVERY PENDING + RECOVERY PENDING + + + + + RESTORING + RESTORING + + + + + SHUTDOWN + SHUTDOWN + + + + + STANDBY + STANDBY + + + + + SUSPECT + SUSPECT + + + + + GLOBAL + GLOBAL + + + + + LOCAL + LOCAL + + + + + MULTI_USER + MULTI_USER + + + + + RESTRICTED_USER + RESTRICTED_USER + + + + + SINGLE_USER + SINGLE_USER + + + + + CHECKSUM + CHECKSUM + + + + + NONE + Нет + + + + + TORN_PAGE_DETECTION + TORN_PAGE_DETECTION + + + + + VarDecimal Storage Format Enabled + Включен формат хранения VarDecimal + + + + + SQL Server 2008 (100) + SQL Server 2008 (100) + + + + + Encryption Enabled + Шифрование включено + + + + + OFF + ОТКЛ. + + + + + ON + ВКЛ. + + + + + PRIMARY + ПЕРВИЧНЫЙ + + + + + For the distribution policy HASH, the number of leading hash columns is optional but should be from 1 to 16 columns + Для политики распространения HASH количество начальных хэш-столбцов указывать не обязательно. Оно может составлять от 1 до 16 столбцов + + + + + SQL Server 2012 (110) + SQL Server 2012 (110) + + + + + SQL Server 2014 (120) + SQL Server 2014 (120) + + + + + SQL Server 2016 (130) + SQL Server 2016 (130) + + + + + SQL Server vNext (140) + SQL Server vNext (140) + + + + + None + Нет + + + + + Partial + Частично + + + + + FILESTREAM Files + Файлы FILESTREAM + + + + + No Applicable Filegroup + Применимая файловая группа отсутствует + + + + + The database {0} is not accessible. + База данных {0} недоступна. + + + + + Query has no results to return + запрос не имеет результатов + + + + + Result set has too many rows to be safely loaded + Pезультатов слишком много строк для безопасной загрузки + + + + Parameterization + Параметризация + + + + + Specifying this option when restoring a backup with the NORECOVERY option is not permitted. + Не разрешается указывать этот параметр при восстановлении резервной копии с параметром NORECOVERY. + + + + + Invalid path for database file: '{0}' + Недопустимый путь к файлу базы данных: {0}"""" + + + + + Log + Журнал + + + + + Failed to create restore plan + Не удалось создать план восстановления + + + + + Restore database is not supported + Восстановление базы данных не поддерживается + + + + + Restore Database + Восстановление базы данных + + + + + (Copy Only) + (Копировать только) + + + + + Component + Тип копии + + + + + Type + Тип + + + + + Server + Сервер + + + + + Database + База данных + + + + + Position + Положение + + + + + First LSN + Первый номер LSN + + + + + Last LSN + Последний номер LSN + + + + + Checkpoint LSN + Номер LSN для контрольной точки + + + + + Full LSN + Полный номер LSN + + + + + Start Date + Дата начала + + + + + Finish Date + Дата завершения + + + + + Size + Размер + + + + + User Name + Имя пользователя + + + + + Expiration + Истечение срока + + + + + Name + Имя + + + + + The last backup taken ({0}) + Последняя созданная резервная копия ({0}) + + + + + Backup Database + Создание резервной копии базы данных + + + + + In progress + Выполняется + + + + + Completed + Завершен + + + + + scripting + Скрипты + + + + + Connection not found + Соединение не найдено + + + + + Please provide a file path instead of directory path + Указанное имя файла является также именем каталога: {0} + + + + + The provided path is invalid + Невозможно проверить существование расположения файла резервной копии: {0} + + + + + Cannot access the specified path on the server: {0} + Указанный путь на сервере недоступен: {0} + + + + + No backupset selected to be restored + Для восстановления не выбран резервный набор данных + + + + + Never + Никогда + + + + + Azure SQL DB + + + + + Azure SQL Data Warehouse + + + + + Azure SQL Stretch Database + + + + + Path {0} is not a valid directory + + + + + For directory {0} a file with name {1} already exists + + + + + Value {0} is too large to fit in column of type {1} + + . + Parameters: 0 - value (string), 1 - columnType (string) + + + + \ No newline at end of file diff --git a/src/Microsoft.SqlTools.CoreServices/Localization/transXliff/sr.zh-hans.xlf b/src/Microsoft.SqlTools.CoreServices/Localization/transXliff/sr.zh-hans.xlf new file mode 100644 index 00000000..81a698a4 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Localization/transXliff/sr.zh-hans.xlf @@ -0,0 +1,2775 @@ + + + + + Connection parameters cannot be null + 连接参数不能为 null + + + + + OwnerUri cannot be null or empty + OwnerUri 不能为 null 或为空 + + + + + SpecifiedUri '{0}' does not have existing connection + SpecifiedUri '{0}' 没有已有的连接 + + . + Parameters: 0 - uri (string) + + + Invalid value '{0}' for AuthenticationType. Valid values are 'Integrated' and 'SqlLogin'. + AuthenticationType 值"{0}" 无效。 有效值为 'Integrated' 和 'SqlLogin'。 + + . + Parameters: 0 - authType (string) + + + Invalid value '{0}' for ApplicationIntent. Valid values are 'ReadWrite' and 'ReadOnly'. + '{0}' 为无效的ApplicationIntent值。 有效值为 'ReadWrite' 和 'ReadOnly'。 + + . + Parameters: 0 - intent (string) + + + Connection canceled + 连接已取消 + + + + + OwnerUri cannot be null or empty + OwnerUri 不能为 null 或为空 + + + + + Connection details object cannot be null + 连接详细信息的对象不能为 null + + + + + ServerName cannot be null or empty + ServerName 不能是 null 或是空白 + + + + + {0} cannot be null or empty when using SqlLogin authentication + 使用 SqlLogin 身份验证时,{0} 不可是 null 或是空 + + . + Parameters: 0 - component (string) + + + The query has already completed, it cannot be cancelled + 查询已完成,无法取消 + + + + + Query successfully cancelled, failed to dispose query. Owner URI not found. + 查询成功取消,无法处理查询。找不到 URI 的所有者。 + + + + + Query was canceled by user + 查询已被用户取消 + + + + + The batch has not completed, yet + 该批处理尚未完成 + + + + + Batch index cannot be less than 0 or greater than the number of batches + 批量索引不能小于 0 或大于批量的总数 + + + + + Result set index cannot be less than 0 or greater than the number of result sets + 结果集索引不能小于 0 或大于结果集的总数 + + + + + Maximum number of bytes to return must be greater than zero + 返回的最大字节数必须大于零 + + + + + Maximum number of chars to return must be greater than zero + 返回的最大字符数必须大于零 + + + + + Maximum number of XML bytes to return must be greater than zero + 返回的 XML 最大字节数必须大于零 + + + + + Access method cannot be write-only + 访问方法不能设置为”只写“ + + + + + FileStreamWrapper must be initialized before performing operations + 在执行操作之前,必须初始化 FileStreamWrapper + + + + + This FileStreamWrapper cannot be used for writing + 该 FileStreamWrapper 不能用于写入 + + + + + (1 row affected) + (1 行受到影响) + + + + + ({0} rows affected) + (影响 {0} 行) + + . + Parameters: 0 - rows (long) + + + Commands completed successfully. + 命令已成功完成。 + + + + + Msg {0}, Level {1}, State {2}, Line {3}{4}{5} + Msg {0},级别 {1},状态 {2},第 {3} {4} {5} 行 + + . + Parameters: 0 - msg (int), 1 - lvl (int), 2 - state (int), 3 - line (int), 4 - newLine (string), 5 - message (string) + + + Query failed: {0} + 查询失败︰ {0} + + . + Parameters: 0 - message (string) + + + (No column name) + (没有列名称) + + + + + The requested query does not exist + 请求的查询不存在。 + + + + + This editor is not connected to a database + 此编辑器未连接到数据库 + + + + + A query is already in progress for this editor session. Please cancel this query or wait for its completion. + 此编辑器会话已有正在进行中的查询。请取消这项查询,或等待它完成 + + + + + Sender for OnInfoMessage event must be a SqlConnection + OnInfoMessage 事件的发送者必须是 SqlConnection + + + + + Result cannot be saved until query execution has completed + 查询完成前,不能保存结果 + + + + + Internal error occurred while starting save task + 保存任务时发生内部错误 + + + + + A save request to the same path is in progress + 相同路径的保存请求正在进行中 + + + + + Failed to save {0}: {1} + 未能保存 {0}: {1} + + . + Parameters: 0 - fileName (string), 1 - message (string) + + + Cannot read subset unless the results have been read from the server + 没有从服务器读取结果之前,无法读取子数据集 + + + + + Start row cannot be less than 0 or greater than the number of rows in the result set + 起始行不能小于 0 或大于结果集中的行数 + + + + + Row count must be a positive integer + 行数必须是一个正整数 + + + + + Could not retrieve column schema for result set + 未能从结果集获取列架构 + + + + + Could not retrieve an execution plan from the result set + 未能从结果集获取执行计划 + + + + + This feature is currently not supported on Azure SQL DB and Data Warehouse: {0} + 这功能目前不支持 Azure SQL DB 和数据仓库︰ {0} + + . + Parameters: 0 - errorMessage (string) + + + An unexpected error occurred during Peek Definition execution: {0} + 查看定义的执行过程中出现意外的错误︰ {0} + + . + Parameters: 0 - errorMessage (string) + + + No results were found. + 未找到结果。 + + + + + No database object was retrieved. + 检索不到任何数据库对象。 + + + + + Please connect to a server. + 请连接到服务器。 + + + + + Operation timed out. + 操作超时。 + + + + + This object type is currently not supported by this feature. + 此功能当前不支持此对象类型。 + + + + + Position is outside of file line range + 位置超出文件行范围 + + + + + Position is outside of column range for line {0} + 第 {0} 行位置超出数据列范围 + + . + Parameters: 0 - line (int) + + + Start position ({0}, {1}) must come before or be equal to the end position ({2}, {3}) + 起始位置 ({0},{1}) 必须先于或等于结束位置 ({2},{3}) + + . + Parameters: 0 - sLine (int), 1 - sCol (int), 2 - eLine (int), 3 - eCol (int) + + + Msg {0}, Level {1}, State {2}, Line {3} + Msg {0},级别 {1} ,状态 {2},第 {3} 行 + + + + + Msg {0}, Level {1}, State {2}, Procedure {3}, Line {4} + Msg {0},级别 {1},状态 {2},过程 {3},第 {4} 行 + + + + + Msg {0}, Level {1}, State {2} + Msg {0},级别 {1},状态 {2} + + + + + An error occurred while the batch was being processed. The error message is: {0} + 执行批处理时发生错误。错误消息︰ {0} + + + + + ({0} row(s) affected) + ({0} 行受到影响) + + + + + The previous execution is not yet complete. + 前一次执行尚未完成。 + + + + + A scripting error occurred. + 出现脚本错误。 + + + + + Incorrect syntax was encountered while {0} was being parsed. + 正在分析 {0} 时发现语法错误。 + + + + + A fatal error occurred. + 出现严重错误。 + + + + + Batch execution completed {0} times... + 已执行完 {0} 次... + + + + + You cancelled the query. + 您已取消查询。 + + + + + An error occurred while the batch was being executed. + 执行批次处理时发生错误。 + + + + + An error occurred while the batch was being executed, but the error has been ignored. + 执行批次处理时发生错误,但该错误已被忽略。 + + + + + Beginning execution loop + Beginning execution loop + + + + + Command {0} is not supported. + 不支持命令 {0}。 + + + + + The variable {0} could not be found. + 找不到变量 {0}。 + + + + + SQL Execution error: {0} + SQL 执行错误︰ {0} + + + + + Batch parser wrapper execution: {0} found... at line {1}: {2} Description: {3} + 批处理解析封装器执行︰{0} 找到位于第 {1} 行: {2} 描述︰{3} + + + + + Batch parser wrapper execution engine batch message received: Message: {0} Detailed message: {1} + 批处理解析封装器执行引擎所收到的消息︰ 消息︰ {0},详细的消息︰ {1} + + + + + Batch parser wrapper execution engine batch ResultSet processing: DataReader.FieldCount: {0} DataReader.RecordsAffected: {1} + 批处理解析封装器执行引擎批次结果集处理︰ DataReader.FieldCount: {0} DataReader.RecordsAffected: {1} + + + + + Batch parser wrapper execution engine batch ResultSet finished. + 批处理解析封装器执行引擎批次处理结果集已完成。 + + + + + Canceling batch parser wrapper batch execution. + 正在取消批处理解析封装器的批处理执行。 + + + + + Scripting warning. + 脚本警告。 + + + + + For more information about this error, see the troubleshooting topics in the product documentation. + 有关此错误的详细信息,请参阅产品文档中的疑难解答主题。 + + + + + File '{0}' recursively included. + 文件 '{0}' 被递归方式包含。 + + + + + Missing end comment mark '*/'. + 缺少结束注释标记 '*/'。 + + + + + Unclosed quotation mark after the character string. + 未闭合的引号后的字符字串。 + + + + + Incorrect syntax was encountered while parsing '{0}'. + '{0}' 在分析时发现语法错误。 + + + + + Variable {0} is not defined. + 未定义变量 {0}。 + + + + + test + 测试 + + + + + Replacement of an empty string by an empty string. + 用空字符串取代空字符串。 + + + + + Edit session does not exist. + 编辑会话不存在 + + + + + Query has not completed execution + 查询尚未完成 + + + + + Query did not generate exactly one result set + 查询并非产生单一结果集 + + + + + Failed to add new row to update cache + 无法添加新数据行以更新缓存,操作失败 + + + + + Given row ID is outside the range of rows in the edit cache + 给定数据行 ID 已超出 edit cache 中数据行的范围 + + + + + An update is already pending for this row and must be reverted first + 这个数据行已经有一个更新正在等待使用,因此它必须先恢复原状。 + + + + + Given row ID does not have pending update + 给定行 ID 没有正在等待的更新操作 + + + + + Table or view metadata could not be found + 找不到表格或视图的元数据 + + + + + Invalid format for binary column + 二进制列格示错误 + + + + + Allowed values for boolean columns are 0, 1, "true", or "false" + Boolean 列必须填入数字 1 或 0, 或字符串 true 或 false + + + + + The column '{0}' is defined as NOT NULL but was not given a value + 必填单元格的值缺失 + + . + Parameters: 0 - colName (string) + + + A delete is pending for this row, a cell update cannot be applied. + 这行即将被删除,其中的单元格无法被更新 + + + + + Column ID must be in the range of columns for the query + 列 ID 必须在数据列总数內才可被查询 + + + + + Column cannot be edited + 列无法被编辑 + + + + + No key columns were found + 找不到键列 + + + + + An output filename must be provided + 必须提供输出文件名 + + + + + Database object {0} cannot be used for editing. + 数据库对象 {0} 无法被编辑 + + . + Parameters: 0 - typeName (string) + + + Specified URI '{0}' does not have a default connection + 指定的 URI '{0}' 没有默认的连接 + + . + Parameters: 0 - uri (string) + + + A commit task is in progress. Please wait for completion. + 提交的任务正在进行,请等待它完成 + + + + + Decimal column is missing numeric precision or numeric scale + 十进制列缺少数值精度或小数位数 + + + + + <TBD> + <TBD> + + + + + Cannot add row to result buffer, data reader does not contain rows + 无法在结果缓冲区添加行,数据读取器不包含任何行 + + + + + TIME column values must be between 00:00:00.0000000 and 23:59:59.9999999 + TIME 列的取值范围必须在 00:00:00.0000000 至 23:59:59.9999999 之间 + + + + + NULL is not allowed for this column + 该列不允许Null 值 + + + + + Edit session already exists. + 编辑会话已存在 + + + + + Edit session has not been initialized + 编辑会话尚未初始化 + + + + + Edit session has already been initialized + 编辑会话已被初始化 + + + + + Edit session has already been initialized or is in the process of initializing + 编辑会话已被初始化或正在初始化中 + + + + + Query execution failed, see messages for details + 执行查询失败,查看消息了解更多详情 + + + + + Result limit cannot be negative + 结果集的限制值不能为负数 + + + + + NULL + + + + + + A object name must be provided + 必须提供对象名称 + + + + + Explicitly specifying server or database is not supported + 不支持显式指定服务器或者数据库 + + + + + Table metadata does not have extended properties + 数据表的元数据没有扩展属性 + + + + + Table or view requested for edit could not be found + 找不到请求编辑的数据表或视图 + + + + + Error expanding: {0} + 扩展数据库时出错: {0} + + + + + Error connecting to {0} + 连接到 {0} 时出错 + + + + + Aggregates + 聚合 + + + + + Server Roles + 服务器角色 + + + + + Application Roles + 应用程序角色 + + + + + Assemblies + 程序集 + + + + + Assembly Files + 程序集文件 + + + + + Asymmetric Keys + 非对称密钥 + + + + + Asymmetric Keys + 非对称密钥 + + + + + Data Compression Options + 数据压缩选项 + + + + + Certificates + 证书 + + + + + FileTables + 文件表 + + + + + Certificates + 证书 + + + + + Check Constraints + CHECK 约束 + + + + + Columns + + + + + + Constraints + 约束 + + + + + Contracts + 协定 + + + + + Credentials + 凭据 + + + + + Error Messages + 错误消息 + + + + + Server Role Membership + 服务器角色成员资格 + + + + + Database Options + 数据库选项 + + + + + Database Roles + 数据库角色 + + + + + Role Memberships + 角色成员资格 + + + + + Database Triggers + 数据库触发器 + + + + + Default Constraints + 默认约束 + + + + + Defaults + 默认值 + + + + + Sequences + 序列 + + + + + Endpoints + 终结点 + + + + + Event Notifications + 事件通知 + + + + + Server Event Notifications + 服务器事件通知 + + + + + Extended Properties + 扩展属性 + + + + + Filegroups + 文件组 + + + + + Foreign Keys + 外键 + + + + + Full-Text Catalogs + 全文目录 + + + + + Full-Text Indexes + 全文检索 + + + + + Functions + 函数 + + + + + Indexes + 索引 + + + + + Inline Functions + 内联函数 + + + + + Keys + + + + + + Linked Servers + 链接的服务器 + + + + + Linked Server Logins + 链接的服务器登录名 + + + + + Logins + 登录名 + + + + + Master Key + 主密钥 + + + + + Master Keys + 主密钥 + + + + + Message Types + 消息类型 + + + + + Table-Valued Functions + 表值函数 + + + + + Parameters + 参数 + + + + + Partition Functions + 分区函数 + + + + + Partition Schemes + 分区方案 + + + + + Permissions + 权限 + + + + + Primary Keys + 主键 + + + + + Programmability + 可编程性 + + + + + Queues + 队列 + + + + + Remote Service Bindings + 远程服务绑定 + + + + + Returned Columns + 返回列 + + + + + Roles + 角色 + + + + + Routes + 路由 + + + + + Rules + 规则 + + + + + Schemas + 架构 + + + + + Security + 安全性 + + + + + Server Objects + 服务器对象 + + + + + Management + 管理 + + + + + Triggers + 触发器 + + + + + Service Broker + Service Broker + + + + + Services + 服务 + + + + + Signatures + 签名 + + + + + Log Files + 日志文件 + + + + + Statistics + 统计信息 + + + + + Storage + 存储 + + + + + Stored Procedures + 存储过程 + + + + + Symmetric Keys + 对称密钥 + + + + + Synonyms + 同义词 + + + + + Tables + + + + + + Triggers + 触发器 + + + + + Types + 类型 + + + + + Unique Keys + 唯一键 + + + + + User-Defined Data Types + 用户定义的数据类型 + + + + + User-Defined Types (CLR) + 用户定义的类型(CLR) + + + + + Users + 用户 + + + + + Views + 视图 + + + + + XML Indexes + XML 索引 + + + + + XML Schema Collections + XML 架构集合 + + + + + User-Defined Table Types + 用户定义的表类型 + + + + + Files + 文件 + + + + + Missing Caption + 缺少标题 + + + + + Broker Priorities + Broker 优先级 + + + + + Cryptographic Providers + 加密提供程序 + + + + + Database Audit Specifications + 数据库审核规范 + + + + + Database Encryption Keys + 数据库加密密钥 + + + + + Event Sessions + 事件会话 + + + + + Full Text Stoplists + 全文非索引字表 + + + + + Resource Pools + 资源池 + + + + + Audits + 审核 + + + + + Server Audit Specifications + 服务器审核规范 + + + + + Spatial Indexes + 空间索引 + + + + + Workload Groups + 工作负荷组 + + + + + SQL Files + SQL 文件 + + + + + Server Functions + 服务器函数 + + + + + SQL Type + SQL 类型 + + + + + Server Options + 服务器选项 + + + + + Database Diagrams + 数据库关系图 + + + + + System Tables + 系统表 + + + + + Databases + 数据库 + + + + + System Contracts + 系统约定 + + + + + System Databases + 系统数据库 + + + + + System Message Types + 系统消息类型 + + + + + System Queues + 系统队列 + + + + + System Services + 系统服务 + + + + + System Stored Procedures + 系统存储过程 + + + + + System Views + 系统视图 + + + + + Data-tier Applications + 数据层应用程序 + + + + + Extended Stored Procedures + 扩展存储过程 + + + + + Aggregate Functions + 聚合函数 + + + + + Approximate Numerics + 近似数字 + + + + + Binary Strings + 二进制字符串 + + + + + Character Strings + 字符串 + + + + + CLR Data Types + CLR 数据类型 + + + + + Configuration Functions + 配置函数 + + + + + Cursor Functions + 游标函数 + + + + + System Data Types + 系统数据类型 + + + + + Date and Time + 日期和时间 + + + + + Date and Time Functions + 日期和时间函数 + + + + + Exact Numerics + 精确数字 + + + + + System Functions + 系统函数 + + + + + Hierarchy Id Functions + 层次结构 ID 函数 + + + + + Mathematical Functions + 数学函数 + + + + + Metadata Functions + 元数据函数 + + + + + Other Data Types + 其他数据类型 + + + + + Other Functions + 其他函数 + + + + + Rowset Functions + 行集函数 + + + + + Security Functions + 安全函数 + + + + + Spatial Data Types + 空间数据类型 + + + + + String Functions + 字符串函数 + + + + + System Statistical Functions + 系统统计函数 + + + + + Text and Image Functions + 文本和图像函数 + + + + + Unicode Character Strings + Unicode 字符串 + + + + + Aggregate Functions + 聚合函数 + + + + + Scalar-valued Functions + 标量值函数 + + + + + Table-valued Functions + 表值函数 + + + + + System Extended Stored Procedures + 系统扩展存储过程 + + + + + Built-in Types + 内置类型 + + + + + Built-in Server Roles + 内置服务器角色 + + + + + User with Password + 具有密码的用户 + + + + + Search Property List + 搜索属性列表 + + + + + Security Policies + 安全策略 + + + + + Security Predicates + 安全谓词 + + + + + Server Role + 服务器角色 + + + + + Search Property Lists + 搜索属性列表 + + + + + Column Store Indexes + 列存储索引 + + + + + Table Type Indexes + 表类型索引 + + + + + Selective XML Indexes + 选择性 XML 索引 + + + + + XML Namespaces + XML 命名空间 + + + + + XML Typed Promoted Paths + XML 特型提升路径 + + + + + T-SQL Typed Promoted Paths + T-SQL 特型提升路径 + + + + + Database Scoped Credentials + 数据库范围的凭据 + + + + + External Data Sources + 外部数据源 + + + + + External File Formats + 外部文件格式 + + + + + External Resources + 外部资源 + + + + + External Tables + 外部表 + + + + + Always Encrypted Keys + Always Encrypted 密钥 + + + + + Column Master Keys + 列主密钥 + + + + + Column Encryption Keys + 列加密密钥 + + + + + Server + 服务器 + + + + + Error parsing ScriptingParams.ConnectionString property. + 解析属性 ScriptingParams.ConnectionString 时出错 + + + + + Invalid directory specified by the ScriptingParams.FilePath property. + ScriptingParams.FilePath 属性指定的路径是无效目录 + + + + + Error parsing ScriptingListObjectsCompleteParams.ConnectionString property. + 解析属性 ScriptingListObjectsCompleteParams.ConnectionString 时出错 + + + + + {0} ({1}, {2}, {3}) + {0} ({1}, {2}, {3}) + + + + + No default + 无默认值 + + + + + Input + 输入 + + + + + Input/Output + 输入/输出 + + + + + Input/ReadOnly + 输入/只读 + + + + + Input/Output/ReadOnly + 输入/输出/只读 + + + + + Default + 默认值 + + + + + null + Null + + + + + not null + 非 Null + + + + + {0} ({1}, {2}) + {0} ({1}, {2}) + + + + + {0} ({1}) + {0} ({1}) + + + + + {0} ({1}Computed, {2}, {3}) + {0} ({1}Computed, {2}, {3}) + + + + + {0} ({1}Computed) + {0} ({1}Computed) + + + + + {0} (Column Set, {1}) + {0} (列集,{1}) + + + + + {0} (Column Set, {1}{2}, {3}) + {0} (列集,{1}{2},{3}) + + + + + {0} (Column Set, {1}, {2}, {3}) + {0} (列集,{1},{2},{3}) + + + + + Unique + 唯一 + + + + + Non-Unique + 非唯一 + + + + + Clustered + 聚集 + + + + + Non-Clustered + 非聚集 + + + + + History + 历史记录 + + + + + System-Versioned + 带有系统版本 + + + + + Unavailable + 不可用 + + + + + Current default filegroup: {0} + 当前默认文件组: {0} + + + + + New Filegroup for {0} + {0} 的新文件组 + + + + + Default + 默认值 + + + + + Files + 文件 + + + + + Name + 名称 + + + + + Read-Only + 只读 + + + + + Autogrowth / Maxsize + 自动增长/最大大小 + + + + + ... + ... + + + + + <default> + <默认值> + + + + + Filegroup + 文件组 + + + + + Logical Name + 逻辑名 + + + + + File Type + 文件类型 + + + + + Initial Size (MB) + 初始大小 (MB) + + + + + <new filegroup> + <新文件组> + + + + + Path + 路径 + + + + + File Name + 文件名 + + + + + <raw device> + <原始设备> + + + + + Bulk-logged + 批量记录的 + + + + + Full + + + + + + Simple + 简单 + + + + + Select Database Owner + 选择数据库所有者 + + + + + None + + + + + + By {0} MB, Limited to {1} MB + 增量为 {0} MB,限制为 {1} MB + + + + + By {0} percent, Limited to {1} MB + 增量为 {0}%,限制为 {1} MB + + + + + By {0} MB, Unlimited + 增量为 {0} MB,增长无限制 + + + + + By {0} percent, Unlimited + 增量为 {0}%,增长无限制 + + + + + Unlimited + 无限制 + + + + + Limited to {0} MB + 不超过{0} MB + + + + + Automatic + 自动 + + + + + Service Broker + Service Broker + + + + + Collation + 排序规则 + + + + + Cursor + 游标 + + + + + Miscellaneous + 杂项 + + + + + Recovery + 恢复 + + + + + State + 状态 + + + + + ANSI NULL Default + ANSI NULL 默认值 + + + + + ANSI NULLS Enabled + 启用 ANSI NULLS + + + + + ANSI Padding Enabled + ANSI 填充已启用 + + + + + ANSI Warnings Enabled + 启用 ANSI 警告 + + + + + Arithmetic Abort Enabled + 算术中止已启用 + + + + + Auto Close + 自动关闭 + + + + + Auto Create Statistics + 自动创建统计信息 + + + + + Auto Shrink + 自动收缩 + + + + + Auto Update Statistics + 自动更新统计信息 + + + + + Auto Update Statistics Asynchronously + 自动异步更新统计信息 + + + + + Case Sensitive + 区分大小写的 + + + + + Close Cursor on Commit Enabled + 已启用“提交时关闭游标” + + + + + Collation + 排序规则 + + + + + Concatenate Null Yields Null + 串联 Null 时得到 Null + + + + + Database Compatibility Level + 数据库兼容级别 + + + + + Database State + 数据库状态 + + + + + Default Cursor + 默认游标 + + + + + Full-Text Indexing Enabled + 已启用全文索引 + + + + + Numeric Round-Abort + 数值舍入 —— 中止 + + + + + Page Verify + 页验证 + + + + + Quoted Identifiers Enabled + 已启用 Quoted Identifiers + + + + + Database Read-Only + 数据库为只读的 + + + + + Recursive Triggers Enabled + 已启用 Recursive Triggers + + + + + Restrict Access + 限制访问 + + + + + Select Into/Bulk Copy + Select Into/Bulk Copy + + + + + Honor Broker Priority + 优先处理 Broker 优先级 + + + + + Service Broker Identifier + Service Broker Identifier + + + + + Broker Enabled + 已启用 Broker + + + + + Truncate Log on Checkpoint + 在检查点删除日志 + + + + + Cross-database Ownership Chaining Enabled + 启用跨数据库所有权链接 + + + + + Trustworthy + 可信 + + + + + Date Correlation Optimization Enabled + Date Correlation Optimization 已启用 prototype_db_prop_parameterization = Parameterization + + + + + Forced + 强迫的 + + + + + Simple + 简单 + + + + + ROWS Data + 行数据 + + + + + LOG + 日志 + + + + + FILESTREAM Data + FILESTREAM 数据 + + + + + Not Applicable + 不适用 + + + + + <default path> + <默认路径> + + + + + Open Connections + 开着的连接 + + + + + To change the database properties, SQL Server must close all other connections to the database_ Are you sure you want to change the properties and close all other connections? + SQL Server 需要关闭所有其它连接来改变数据库属性——你确认要改变属性并关闭所有其它连接吗? + + + + + AUTO_CLOSED + AUTO_CLOSED + + + + + EMERGENCY + 紧急 + + + + + INACCESSIBLE + 不可访问 + + + + + NORMAL + 一般 + + + + + OFFLINE + 离线 + + + + + RECOVERING + 恢复中 + + + + + RECOVERY PENDING + 等待恢复 + + + + + RESTORING + 恢复中 + + + + + SHUTDOWN + 关机 + + + + + STANDBY + 待机 + + + + + SUSPECT + 怀疑 + + + + + GLOBAL + 全局 + + + + + LOCAL + ju + + + + + MULTI_USER + MULTI_USER + + + + + RESTRICTED_USER + RESTRICTED_USER + + + + + SINGLE_USER + SINGLE_USER + + + + + CHECKSUM + 校验码 + + + + + NONE + 没有 + + + + + TORN_PAGE_DETECTION + TORN_PAGE_DETECTION + + + + + VarDecimal Storage Format Enabled + 启用 VarDecimal 存储格式 + + + + + SQL Server 2008 (100) + SQL Server 2008 (100) + + + + + Encryption Enabled + 启用加密 + + + + + OFF + + + + + + ON + + + + + + PRIMARY + 首要的 + + + + + For the distribution policy HASH, the number of leading hash columns is optional but should be from 1 to 16 columns + 对于分配政策HASH,开始的哈希列的数量是可选的,但是应在1到16之间 + + + + + SQL Server 2012 (110) + SQL Server 2012 (110) + + + + + SQL Server 2014 (120) + SQL Server 2014 (120) + + + + + SQL Server 2016 (130) + SQL Server 2016 (130) + + + + + SQL Server vNext (140) + SQL Server vNext (140) + + + + + None + + + + + + Partial + 部分 + + + + + FILESTREAM Files + FILESTREAM 文件 + + + + + No Applicable Filegroup + 没有可用的文件组 + + + + + The database {0} is not accessible. + 数据库 {0} 无法访问。 + + + + + Query has no results to return + 无查询结果 + + + + + Result set has too many rows to be safely loaded + 资料行因结果集太长而可能无法加载 + + + + Parameterization + 参数化 + + + + + Specifying this option when restoring a backup with the NORECOVERY option is not permitted. + 当使用 NORECOVERY 选项还原备份时,不允许指定此选项。 + + + + + Invalid path for database file: '{0}' + 数据库文件的路径无效:“{0}” + + + + + Log + 日志 + + + + + Failed to create restore plan + 制订还原计划失败 + + + + + Restore database is not supported + 不支持还原数据库 + + + + + Restore Database + 还原数据库 + + + + + (Copy Only) + (仅复制) + + + + + Component + 组件 + + + + + Type + 类型 + + + + + Server + 服务器 + + + + + Database + 数据库 + + + + + Position + 位置 + + + + + First LSN + 第一个 LSN + + + + + Last LSN + 最后一个 LSN + + + + + Checkpoint LSN + 检查点 LSN + + + + + Full LSN + 完整 LSN + + + + + Start Date + 开始日期 + + + + + Finish Date + 完成日期 + + + + + Size + 大小 + + + + + User Name + 用户名 + + + + + Expiration + 过期 + + + + + Name + 名称 + + + + + The last backup taken ({0}) + 上次执行的备份({0}) + + + + + Backup Database + 备份数据库 + + + + + In progress + 正在进行 + + + + + Completed + 已完成 + + + + + scripting + 开始执行脚本操作 + + + + + Connection not found + 找不到连接 + + + + + Please provide a file path instead of directory path + 所指定的文件名同时也是一个文件目录名: {0} + + + + + The provided path is invalid + 无法验证备份文件的位置是否存在: {0} + + + + + Cannot access the specified path on the server: {0} + 无法访问服务器上的指定路径: {0} + + + + + No backupset selected to be restored + 未选择用于还原的备份集 + + + + + Never + 从不 + + + + + Azure SQL DB + Azure SQL 数据库 + + + + + Azure SQL Data Warehouse + Azure SQL 数据仓库 + + + + + Azure SQL Stretch Database + Azure SQL Stretch Database + + + + + Path {0} is not a valid directory + 路径 {0} 不是有效的目录 + + + + + For directory {0} a file with name {1} already exists + {0} 文件夹中已存在名为 {1} 的文件 + + + + + Value {0} is too large to fit in column of type {1} + 值 {0} 太大,无法放入类型为 {1} 的列 + + . + Parameters: 0 - value (string), 1 - columnType (string) + + + + \ No newline at end of file diff --git a/src/Microsoft.SqlTools.CoreServices/Localization/transXliff/sr.zh-hant.xlf b/src/Microsoft.SqlTools.CoreServices/Localization/transXliff/sr.zh-hant.xlf new file mode 100644 index 00000000..f5956cc6 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Localization/transXliff/sr.zh-hant.xlf @@ -0,0 +1,2777 @@ + + + + + Connection parameters cannot be null + 連接參數不可為 null + + + + + OwnerUri cannot be null or empty + OwnerUri 不能為 null 或空白 + + + + + SpecifiedUri '{0}' does not have existing connection + SpecifiedUri '{0}' 沒有現有的連線 + + . + Parameters: 0 - uri (string) + + + Invalid value '{0}' for AuthenticationType. Valid values are 'Integrated' and 'SqlLogin'. + AuthenticationType 值 "{0}" 無效。 有效值為 'Integrated' 和 'SqlLogin'。 + + . + Parameters: 0 - authType (string) + + + Invalid value '{0}' for ApplicationIntent. Valid values are 'ReadWrite' and 'ReadOnly'. + '{0}' 為無效的ApplicationIntent值。 有效值為 'ReadWrite' 和 'ReadOnly'。 + + . + Parameters: 0 - intent (string) + + + Connection canceled + 已取消連線 + + + + + OwnerUri cannot be null or empty + OwnerUri 不能是 null 或空白 + + + + + Connection details object cannot be null + 連線詳細資料物件不能是 null + + + + + ServerName cannot be null or empty + ServerName 不能是 null 或空白 + + + + + {0} cannot be null or empty when using SqlLogin authentication + 使用 SqlLogin 驗證時,{0} 不可為 null 或是空白 + + . + Parameters: 0 - component (string) + + + The query has already completed, it cannot be cancelled + 查詢已完成,無法取消 + + + + + Query successfully cancelled, failed to dispose query. Owner URI not found. + 成功地取消查詢,無法處置查詢。找不到擁有者 URI 。 + + + + + Query was canceled by user + 使用者已取消查詢 + + + + + The batch has not completed, yet + 批次尚未完成 + + + + + Batch index cannot be less than 0 or greater than the number of batches + 批次索引不能小於 0 或大於批次的總數 + + + + + Result set index cannot be less than 0 or greater than the number of result sets + 結果集的索引不能小於 0 或大於結果集的總數 + + + + + Maximum number of bytes to return must be greater than zero + 傳回的最大位元組數目必須大於零 + + + + + Maximum number of chars to return must be greater than zero + 傳回的最大字元數目必須大於零 + + + + + Maximum number of XML bytes to return must be greater than zero + 傳回的最大 XML 位元組數目必須大於零 + + + + + Access method cannot be write-only + 存取方法不可以設為唯寫 + + + + + FileStreamWrapper must be initialized before performing operations + 執行前,必須先初始化 FileStreamWrapper + + + + + This FileStreamWrapper cannot be used for writing + 這個 FileStreamWrapper 不能用於寫入 + + + + + (1 row affected) + (1 列受影響) + + + + + ({0} rows affected) + ({0} 個資料列受到影響) + + . + Parameters: 0 - rows (long) + + + Commands completed successfully. + 命令已順利完成。 + + + + + Msg {0}, Level {1}, State {2}, Line {3}{4}{5} + 訊息 {0},層級 {1} ,狀態 {2},第 {3} {4} {5} 行 + + . + Parameters: 0 - msg (int), 1 - lvl (int), 2 - state (int), 3 - line (int), 4 - newLine (string), 5 - message (string) + + + Query failed: {0} + 查詢失敗︰ {0} + + . + Parameters: 0 - message (string) + + + (No column name) + (沒有資料行名稱) + + + + + The requested query does not exist + 所要求的查詢不存在 + + + + + This editor is not connected to a database + 這個編輯器尚未連接到資料庫 + + + + + A query is already in progress for this editor session. Please cancel this query or wait for its completion. + 一個查詢已在這個編輯器工作階段。請取消這項查詢,或等待其完成。 + + + + + Sender for OnInfoMessage event must be a SqlConnection + OnInfoMessage 事件的寄件者必須是一個 SqlConnection。 + + + + + Result cannot be saved until query execution has completed + 完成查詢執行前無法儲存結果 + + + + + Internal error occurred while starting save task + 在儲存工作啟動時,發生內部錯誤 + + + + + A save request to the same path is in progress + 相同路徑的儲存要求正在進行中 + + + + + Failed to save {0}: {1} + 無法儲存 {0}: {1} + + . + Parameters: 0 - fileName (string), 1 - message (string) + + + Cannot read subset unless the results have been read from the server + 從伺服器讀取結果前,無法讀取子集 + + + + + Start row cannot be less than 0 or greater than the number of rows in the result set + 開始資料列不能小於 0 或大於結果集中的資料列總數 + + + + + Row count must be a positive integer + 資料列計數必須是正整數 + + + + + Could not retrieve column schema for result set + 無法從結果集擷取資料行結構描述 + + + + + Could not retrieve an execution plan from the result set + 無法從結果集擷取執行計劃 + + + + + This feature is currently not supported on Azure SQL DB and Data Warehouse: {0} + 這項功能目前不支援 Azure SQL 資料庫和資料倉儲︰ {0} + + . + Parameters: 0 - errorMessage (string) + + + An unexpected error occurred during Peek Definition execution: {0} + 查看定義執行過程中發生未預期的錯誤︰ {0} + + . + Parameters: 0 - errorMessage (string) + + + No results were found. + 找不到任何結果。 + + + + + No database object was retrieved. + 沒有資料庫物件被擷取。 + + + + + Please connect to a server. + 請連線到伺服器。 + + + + + Operation timed out. + 作業逾時。 + + + + + This object type is currently not supported by this feature. + 此功能目前不支援這種物件類型。 + + + + + Position is outside of file line range + 位置超出檔案行範圍 + + + + + Position is outside of column range for line {0} + 第 {0} 行位置超出資料行範圍 + + . + Parameters: 0 - line (int) + + + Start position ({0}, {1}) must come before or be equal to the end position ({2}, {3}) + 開始位置 ({0},{1}) 必須先於或等於結束位置 ({2},{3}) + + . + Parameters: 0 - sLine (int), 1 - sCol (int), 2 - eLine (int), 3 - eCol (int) + + + Msg {0}, Level {1}, State {2}, Line {3} + 訊息 {0},層級 {1} ,狀態 {2},第 {3} 行 + + + + + Msg {0}, Level {1}, State {2}, Procedure {3}, Line {4} + 訊息 {0} ,層級 {1}, 狀態 {2}, 程序 {3},第 {4} 行 + + + + + Msg {0}, Level {1}, State {2} + 訊息 {0},層級 {1} ,狀態 {2} + + + + + An error occurred while the batch was being processed. The error message is: {0} + 處理批次時,發生錯誤。錯誤訊息是︰ {0} + + + + + ({0} row(s) affected) + ({0} 個資料列受到影響) + + + + + The previous execution is not yet complete. + 前一個執行尚未完成。 + + + + + A scripting error occurred. + 發生指令碼的錯誤。 + + + + + Incorrect syntax was encountered while {0} was being parsed. + 正在剖析 {0} 時遇到不正確的語法。 + + + + + A fatal error occurred. + 發生嚴重的錯誤。 + + + + + Batch execution completed {0} times... + 已執行完成 {0} 次... + + + + + You cancelled the query. + 您已取消查詢。 + + + + + An error occurred while the batch was being executed. + 執行此批次時發生錯誤。 + + + + + An error occurred while the batch was being executed, but the error has been ignored. + 執行此批次時發生錯誤,但錯誤以忽略。 + + + + + Beginning execution loop + Beginning execution loop + + + + + Command {0} is not supported. + 不支援命令 {0}。 + + + + + The variable {0} could not be found. + 找不到變數 {0}。 + + + + + SQL Execution error: {0} + SQL 執行錯誤︰ {0} + + + + + Batch parser wrapper execution: {0} found... at line {1}: {2} Description: {3} + 批次剖析器包裝函式執行︰位於第 {1} 行: {2} 描述︰{3} 找到 {0} + + + + + Batch parser wrapper execution engine batch message received: Message: {0} Detailed message: {1} + 批次剖析器包裝函式執行引擎批次所收到的訊息︰ 訊息︰ {0},詳細的訊息︰ {1} + + + + + Batch parser wrapper execution engine batch ResultSet processing: DataReader.FieldCount: {0} DataReader.RecordsAffected: {1} + 批次剖析器包裝函式執行引擎批次結果集處理︰ DataReader.FieldCount: {0} DataReader.RecordsAffected: {1} + + + + + Batch parser wrapper execution engine batch ResultSet finished. + 批次剖析器包裝函式執行引擎批次結果集已完成。 + + + + + Canceling batch parser wrapper batch execution. + 正在取消批次剖析器包裝函式的批次執行。 + + + + + Scripting warning. + 指令碼警告。 + + + + + For more information about this error, see the troubleshooting topics in the product documentation. + 有關此錯誤的詳細資訊,請參閱產品文件中的疑難排解主題。 + + + + + File '{0}' recursively included. + 檔案 '{0}' 具有遞迴。 + + + + + Missing end comment mark '*/'. + 遺漏結束的註解記號 ' * /'。 + + + + + Unclosed quotation mark after the character string. + 字元字串後有未封閉的雙引號 + + + + + Incorrect syntax was encountered while parsing '{0}'. + 正在剖析 {0} 時遇到不正確的語法。 + + + + + Variable {0} is not defined. + 未定義變數 {0}。 + + + + + test + 測試 + + + + + Replacement of an empty string by an empty string. + 用空白字串取代空白字串。 + + + + + Edit session does not exist. + 編輯工作階段不存在 + + + + + Query has not completed execution + 查詢尚未完成 + + + + + Query did not generate exactly one result set + 查詢並非產生單一結果集 + + + + + Failed to add new row to update cache + 在 cashe 裡更新資料列失敗 + + + + + Given row ID is outside the range of rows in the edit cache + 提供的資料列識別碼已超出 edit cashe 中資料列的範圍 + + + + + An update is already pending for this row and must be reverted first + 這個資料列已經有一個更新正在等待使用,因此它必須先恢復原狀。 + + + + + Given row ID does not have pending update + 這個資料列識別碼並沒有正在等待更新 + + + + + Table or view metadata could not be found + 找不到資料表或檢視表中繼資料 + + + + + Invalid format for binary column + 二進位資料欄格示錯誤 + + + + + Allowed values for boolean columns are 0, 1, "true", or "false" + Boolean 欄位必須填入數字 1 或 0, 或字串 true 或 false + + + + + The column '{0}' is defined as NOT NULL but was not given a value + 必填儲存格未填 + + . + Parameters: 0 - colName (string) + + + A delete is pending for this row, a cell update cannot be applied. + 這個資料列即將被刪除,其中的儲存格無法被更新 + + + + + Column ID must be in the range of columns for the query + 資料行識別碼必須在資料行總數內才可被查詢 + + + + + Column cannot be edited + 資料行無法被編輯 + + + + + No key columns were found + 找不到索引鍵資料行 + + + + + An output filename must be provided + 必須提供輸出檔名 + + + + + Database object {0} cannot be used for editing. + 資料庫物件 {0} 無法被編輯 + + . + Parameters: 0 - typeName (string) + + + Specified URI '{0}' does not have a default connection + 指定的 URI '{0}' 沒有預設的連線 + + . + Parameters: 0 - uri (string) + + + A commit task is in progress. Please wait for completion. + 認可的工作正在進行,請等待它完成 + + + + + Decimal column is missing numeric precision or numeric scale + 十進位資料行缺少數值有效位數或小數位數 + + + + + <TBD> + <TBD> + + + + + Cannot add row to result buffer, data reader does not contain rows + 無法在結果緩衝區加資料列,資料讀取器不包含資料列 + + + + + TIME column values must be between 00:00:00.0000000 and 23:59:59.9999999 + TIME 欄的值範圍必須在 00:00:00.0000000 至 23:59:59.9999999 之間 + + + + + NULL is not allowed for this column + 這欄不允許填入 NULL 值 + + + + + Edit session already exists. + 編輯工作階段已存在 + + + + + Edit session has not been initialized + 編輯工作階段尚未初始化 + + + + + Edit session has already been initialized + 編輯工作階段已初始化 + + + + + Edit session has already been initialized or is in the process of initializing + 編輯工作階段已完成初始化或正在初始化 + + + + + Query execution failed, see messages for details + 查詢執行失敗, 請查看詳細資訊 + + + + + Result limit cannot be negative + 結果限制不能為負 + + + + + NULL + NULL + + + + + A object name must be provided + 必須提供物件名稱 + + + + + Explicitly specifying server or database is not supported + 不支援明確指定的伺服器或資料庫 + + + + + Table metadata does not have extended properties + 資料表中繼資料無擴充屬性 + + + + + Table or view requested for edit could not be found + 找不到要編輯的資料表或檢視表 + + + + + Error expanding: {0} + 擴充資料庫時發生錯誤:{0} + + + + + Error connecting to {0} + 連接到 {0} 時發生錯誤 + + + + + Aggregates + 彙總 + + + + + Server Roles + 伺服器角色 + + + + + Application Roles + 應用程式角色 + + + + + Assemblies + 組件 + + + + + Assembly Files + 組件檔 + + + + + Asymmetric Keys + 非對稱金鑰 + + + + + Asymmetric Keys + 非對稱金鑰 + + + + + Data Compression Options + 資料壓縮選項 + + + + + Certificates + 憑證 + + + + + FileTables + FileTable + + + + + Certificates + 憑證 + + + + + Check Constraints + 檢查條件約束 + + + + + Columns + 資料行 + + + + + Constraints + 條件約束 + + + + + Contracts + 合約 + + + + + Credentials + 認證 + + + + + Error Messages + 錯誤訊息 + + + + + Server Role Membership + 伺服器角色成員資格 + + + + + Database Options + 資料庫選項 + + + + + Database Roles + 資料庫角色 + + + + + Role Memberships + 角色成員資格 + + + + + Database Triggers + 資料庫觸發程序 + + + + + Default Constraints + 預設條件約束 + + + + + Defaults + 預設 + + + + + Sequences + 序列 + + + + + Endpoints + 端點 + + + + + Event Notifications + 事件告知 + + + + + Server Event Notifications + 伺服器事件通知 + + + + + Extended Properties + 擴充屬性 + + + + + Filegroups + 檔案群組 + + + + + Foreign Keys + 外部索引鍵 + + + + + Full-Text Catalogs + 全文檢索目錄 + + + + + Full-Text Indexes + 全文檢索索引 + + + + + Functions + 函式 + + + + + Indexes + 索引 + + + + + Inline Functions + 內嵌函式 + + + + + Keys + 索引鍵 + + + + + Linked Servers + 連結的伺服器 + + + + + Linked Server Logins + 連結的伺服器登入 + + + + + Logins + 登入 + + + + + Master Key + 主要金鑰 + + + + + Master Keys + 主要金鑰 + + + + + Message Types + 訊息類型 + + + + + Table-Valued Functions + 資料表值函式 + + + + + Parameters + 參數 + + + + + Partition Functions + 資料分割函式 + + + + + Partition Schemes + 資料分割配置 + + + + + Permissions + 權限 + + + + + Primary Keys + 主索引鍵 + + + + + Programmability + 可程式性 + + + + + Queues + 佇列 + + + + + Remote Service Bindings + 遠端服務繫結 + + + + + Returned Columns + 傳回的資料行 + + + + + Roles + 角色 + + + + + Routes + 路由 + + + + + Rules + 規則 + + + + + Schemas + 結構描述 + + + + + Security + 安全性 + + + + + Server Objects + 伺服器物件 + + + + + Management + 管理 + + + + + Triggers + 觸發程序 + + + + + Service Broker + Service Broker + + + + + Services + 服務 + + + + + Signatures + 簽章 + + + + + Log Files + 記錄檔 + + + + + Statistics + 統計資料 + + + + + Storage + 儲存體 + + + + + Stored Procedures + 預存程序 + + + + + Symmetric Keys + 對稱金鑰 + + + + + Synonyms + 同義資料表 + + + + + Tables + 資料表 + + + + + Triggers + 觸發程序 + + + + + Types + 型別 + + + + + Unique Keys + 唯一索引鍵 + + + + + User-Defined Data Types + 使用者定義資料類型 + + + + + User-Defined Types (CLR) + 使用者定義型別 (CLR) + + + + + Users + 使用者 + + + + + Views + 檢視 + + + + + XML Indexes + XML 索引 + + + + + XML Schema Collections + XML 結構描述集合 + + + + + User-Defined Table Types + 使用者定義資料表類型 + + + + + Files + 檔案 + + + + + Missing Caption + 遺漏標題 + + + + + Broker Priorities + Broker 優先權 + + + + + Cryptographic Providers + 密碼編譯提供者 + + + + + Database Audit Specifications + 資料庫稽核規格 + + + + + Database Encryption Keys + 資料庫加密金鑰 + + + + + Event Sessions + 事件工作階段 + + + + + Full Text Stoplists + 全文檢索停用字詞表 + + + + + Resource Pools + 資源集區 + + + + + Audits + 稽核 + + + + + Server Audit Specifications + 伺服器稽核規格 + + + + + Spatial Indexes + 空間索引 + + + + + Workload Groups + 工作負載群組 + + + + + SQL Files + SQL 檔案 + + + + + Server Functions + 伺服器函式 + + + + + SQL Type + SQL 類型 + + + + + Server Options + 伺服器選項 + + + + + Database Diagrams + 資料庫圖表 + + + + + System Tables + 系統資料表 + + + + + Databases + 資料庫 + + + + + System Contracts + 系統合約 + + + + + System Databases + 系統資料庫 + + + + + System Message Types + 系統訊息類型 + + + + + System Queues + 系統佇列 + + + + + System Services + 系統服務 + + + + + System Stored Procedures + 系統預存程序 + + + + + System Views + 系統檢視表 + + + + + Data-tier Applications + 資料層應用程式 + + + + + Extended Stored Procedures + 擴充預存程序 + + + + + Aggregate Functions + 彙總函式 + + + + + Approximate Numerics + 近似數值 + + + + + Binary Strings + 二進位字串 + + + + + Character Strings + 字元字串 + + + + + CLR Data Types + CLR 資料型別 + + + + + Configuration Functions + 組態函式 + + + + + Cursor Functions + 資料指標函式 + + + + + System Data Types + 系統資料型別 + + + + + Date and Time + 日期和時間 + + + + + Date and Time Functions + 日期和時間函式 + + + + + Exact Numerics + 精確數值 + + + + + System Functions + 系統函式 + + + + + Hierarchy Id Functions + 階層識別碼函式 + + + + + Mathematical Functions + 數學函式 + + + + + Metadata Functions + 中繼資料函式 + + + + + Other Data Types + 其他資料型別 + + + + + Other Functions + 其他函式 + + + + + Rowset Functions + 資料列集函式 + + + + + Security Functions + 安全性函式 + + + + + Spatial Data Types + 空間資料型別 + + + + + String Functions + 字串函式 + + + + + System Statistical Functions + 系統統計函式 + + + + + Text and Image Functions + 文字和影像函式 + + + + + Unicode Character Strings + Unicode 字元字串 + + + + + Aggregate Functions + 彙總函式 + + + + + Scalar-valued Functions + 純量值函式 + + + + + Table-valued Functions + 資料表值函式 + + + + + System Extended Stored Procedures + 系統擴充預存程序 + + + + + Built-in Types + 內建型別 + + + + + Built-in Server Roles + 內建伺服器角色 + + + + + User with Password + 有密碼的使用者 + + + + + Search Property List + 搜尋屬性清單 + + + + + Security Policies + 安全性原則 + + + + + Security Predicates + 安全性述詞 + + + + + Server Role + 伺服器角色 + + + + + Search Property Lists + 搜尋屬性清單 + + + + + Column Store Indexes + 資料行儲存索引 + + + + + Table Type Indexes + 資料表類型索引 + + + + + Selective XML Indexes + 選擇性 XML 索引 + + + + + XML Namespaces + XML 命名空間 + + + + + XML Typed Promoted Paths + XML 具類型的升級路徑 + + + + + T-SQL Typed Promoted Paths + T-SQL 具類型的升級路徑 + + + + + Database Scoped Credentials + 資料庫範圍認證 + + + + + External Data Sources + 外部資料來源 + + + + + External File Formats + 外部檔案格式 + + + + + External Resources + 外部資源 + + + + + External Tables + 外部資料表 + + + + + Always Encrypted Keys + Always Encrypted 金鑰 + + + + + Column Master Keys + 資料行主要金鑰 + + + + + Column Encryption Keys + 資料行加密金鑰 + + + + + Server + 伺服器 + + + + + Error parsing ScriptingParams.ConnectionString property. + 剖析屬性 ScriptingParams.ConnectionString 時發生錯誤 + + + + + Invalid directory specified by the ScriptingParams.FilePath property. + ScriptingParams.FilePath 屬性指定的路径是無效目錄 + + + + + Error parsing ScriptingListObjectsCompleteParams.ConnectionString property. + 剖析屬性 ScriptingListObjectsCompleteParams.ConnectionString 時發生錯誤 + + + + + {0} ({1}, {2}, {3}) + {0} ({1},{2},{3}) + + + + + No default + 無預設值 + + + + + Input + 輸入 + + + + + Input/Output + 輸入/輸出 + + + + + Input/ReadOnly + 輸入/唯讀 + + + + + Input/Output/ReadOnly + 輸入/輸出/唯讀 + + + + + Default + 預設值 + + + + + null + Null + + + + + not null + 非 Null + + + + + {0} ({1}, {2}) + {0} ({1},{2}) + + + + + {0} ({1}) + {0} ({1}) + + + + + {0} ({1}Computed, {2}, {3}) + {0} ({1} 已計算,{2},{3}) + + + + + {0} ({1}Computed) + {0} ({1} 已計算) + + + + + {0} (Column Set, {1}) + {0} (資料行集,{1}) + + + + + {0} (Column Set, {1}{2}, {3}) + {0} (資料行集,{1}{2},{3}) + + + + + {0} (Column Set, {1}, {2}, {3}) + {0} (資料行集,{1},{2},{3}) + + + + + Unique + 唯一 + + + + + Non-Unique + 非唯一 + + + + + Clustered + 叢集 + + + + + Non-Clustered + 非叢集 + + + + + History + 歷程記錄 + + + + + System-Versioned + 系統建立版本 + + + + + Unavailable + 無法使用 + + + + + Current default filegroup: {0} + 當前預設檔案群組: {0} + + + + + New Filegroup for {0} + {0} 的新檔案群組 + + + + + Default + 預設值 + + + + + Files + 檔案 + + + + + Name + 名稱 + + + + + Read-Only + 唯讀 + + + + + Autogrowth / Maxsize + 自動成長 / 大小上限 + + + + + ... + ... + + + + + <default> + <預設> + + + + + Filegroup + 檔案群組 + + + + + Logical Name + 邏輯名稱 + + + + + File Type + 檔案類型 + + + + + Initial Size (MB) + 初始大小 (MB) + + + + + <new filegroup> + <新增檔案群組> + + + + + Path + 路徑 + + + + + File Name + 檔案名稱 + + + + + <raw device> + <未經處理的裝置> + + + + + Bulk-logged + 大量記錄 + + + + + Full + Full + + + + + Simple + Simple + + + + + Select Database Owner + 選取資料庫擁有者 + + + + + None + + + + + + By {0} MB, Limited to {1} MB + 以 {0} MB 為單位,限制為 {1} MB + + + + + By {0} percent, Limited to {1} MB + 以百分之 {0} 為單位,限制為 {1} MB + + + + + By {0} MB, Unlimited + 以 {0} MB 為單位,無限制 + + + + + By {0} percent, Unlimited + 以百分之 {0} 為單位,無限制 + + + + + Unlimited + 無限制 + + + + + Limited to {0} MB + 限制為 {0} MB + + + + + Automatic + 自動 + + + + + Service Broker + Service Broker + + + + + Collation + 定序 + + + + + Cursor + 資料指標 + + + + + Miscellaneous + 其他 + + + + + Recovery + 復原 + + + + + State + 狀態 + + + + + ANSI NULL Default + ANSI NULL 預設值 + + + + + ANSI NULLS Enabled + ANSI NULLS 已啟用 + + + + + ANSI Padding Enabled + +ANSI Padding 已啟用 + + + + + ANSI Warnings Enabled + ANSI Warnings 已啟用 + + + + + Arithmetic Abort Enabled + Arithmetic Abort 已啟用 + + + + + Auto Close + 自動關閉 + + + + + Auto Create Statistics + 自動建立統計資料 + + + + + Auto Shrink + 自動壓縮 + + + + + Auto Update Statistics + 自動更新統計資料 + + + + + Auto Update Statistics Asynchronously + 自動非同步更新統計資料 + + + + + Case Sensitive + 區分大小寫 + + + + + Close Cursor on Commit Enabled + 認可時關閉資料指標已啟用 + + + + + Collation + 定序 + + + + + Concatenate Null Yields Null + 串連 Null 產生 Null + + + + + Database Compatibility Level + 資料庫相容性層級 + + + + + Database State + 資料庫狀態 + + + + + Default Cursor + 預設資料指標 + + + + + Full-Text Indexing Enabled + 全文檢索索引已啟用 + + + + + Numeric Round-Abort + 數值捨入中止 + + + + + Page Verify + 頁面確認 + + + + + Quoted Identifiers Enabled + 引號識別碼已啟用 + + + + + Database Read-Only + 資料庫唯讀 + + + + + Recursive Triggers Enabled + 遞迴觸發程序已啟用 + + + + + Restrict Access + 限制存取 + + + + + Select Into/Bulk Copy + 選取/大量複製 + + + + + Honor Broker Priority + 接受 Broker 優先權 + + + + + Service Broker Identifier + Service Broker 識別碼 + + + + + Broker Enabled + Broker 已啟用 + + + + + Truncate Log on Checkpoint + 在檢查點截斷記錄 + + + + + Cross-database Ownership Chaining Enabled + 已啟用跨資料庫擁有權鏈結 + + + + + Trustworthy + 可信任 + + + + + Date Correlation Optimization Enabled + 已啟用日期相互關聯最佳化 prototype_db_prop_parameterization = 參數化 + + + + + Forced + 強制 + + + + + Simple + 簡易 + + + + + ROWS Data + 資料列資料 + + + + + LOG + LOG + + + + + FILESTREAM Data + FILESTREAM 資料 + + + + + Not Applicable + 不適用 + + + + + <default path> + <預設路徑> + + + + + Open Connections + 開啟連接 + + + + + To change the database properties, SQL Server must close all other connections to the database_ Are you sure you want to change the properties and close all other connections? + 為了變更資料庫屬性,SQL Server必須關閉所有其他與資料庫的連線。 +確定要變更屬性並關閉所有其他連線嗎? + + + + + AUTO_CLOSED + AUTO_CLOSED + + + + + EMERGENCY + EMERGENCY + + + + + INACCESSIBLE + INACCESSIBLE + + + + + NORMAL + NORMAL + + + + + OFFLINE + OFFLINE + + + + + RECOVERING + RECOVERING + + + + + RECOVERY PENDING + RECOVERY PENDING + + + + + RESTORING + RESTORING + + + + + SHUTDOWN + SHUTDOWN + + + + + STANDBY + STANDBY + + + + + SUSPECT + SUSPECT + + + + + GLOBAL + GLOBAL + + + + + LOCAL + LOCAL + + + + + MULTI_USER + MULTI_USER + + + + + RESTRICTED_USER + RESTRICTED_USER + + + + + SINGLE_USER + SINGLE_USER + + + + + CHECKSUM + CHECKSUM + + + + + NONE + NONE + + + + + TORN_PAGE_DETECTION + TORN_PAGE_DETECTION + + + + + VarDecimal Storage Format Enabled + VarDecimal 儲存格式已啟用 + + + + + SQL Server 2008 (100) + SQL Server 2008 (100) + + + + + Encryption Enabled + 加密已啟用 + + + + + OFF + OFF + + + + + ON + ON + + + + + PRIMARY + PRIMARY + + + + + For the distribution policy HASH, the number of leading hash columns is optional but should be from 1 to 16 columns + 散發原則 HASH 的前置雜湊資料行是選擇性的,但應該介於 1 到 16 個資料行之間。 + + + + + SQL Server 2012 (110) + SQL Server 2012 (110) + + + + + SQL Server 2014 (120) + SQL Server 2014 (120) + + + + + SQL Server 2016 (130) + SQL Server 2016 (130) + + + + + SQL Server vNext (140) + SQL Server vNext (140) + + + + + None + + + + + + Partial + Partial + + + + + FILESTREAM Files + FILESTREAM 檔案 + + + + + No Applicable Filegroup + 沒有適用的檔案群組 + + + + + The database {0} is not accessible. + 無法存取資料庫 {0}。 + + + + + Query has no results to return + 沒有查詢結果可以回傳 + + + + + Result set has too many rows to be safely loaded + 資料列因結果集太長而無法載入 + + + + Parameterization + 參數化 + + + + + Specifying this option when restoring a backup with the NORECOVERY option is not permitted. + 不允許使用 NORECOVERY 選項還原備份時,請指定這個選項。 + + + + + Invalid path for database file: '{0}' + 資料庫檔案的路徑無效: '{0}' + + + + + Log + 記錄檔 + + + + + Failed to create restore plan + 無法建立還原計畫 + + + + + Restore database is not supported + 不支援還原資料庫 + + + + + Restore Database + 還原資料庫 + + + + + (Copy Only) + (僅複製) + + + + + Component + 元件 + + + + + Type + 型別 + + + + + Server + 伺服器 + + + + + Database + 資料庫 + + + + + Position + 位置 + + + + + First LSN + 第一個 LSN + + + + + Last LSN + 最後一個 LSN + + + + + Checkpoint LSN + 檢查點 LSN + + + + + Full LSN + 完整 LSN + + + + + Start Date + 開始日期 + + + + + Finish Date + 完成日期 + + + + + Size + 大小 + + + + + User Name + 使用者名稱 + + + + + Expiration + 逾期 + + + + + Name + 名稱 + + + + + The last backup taken ({0}) + 上次建立的備份 ({0}) + + + + + Backup Database + 備份資料庫 + + + + + In progress + 進行中 + + + + + Completed + 已完成 + + + + + scripting + 指令碼 + + + + + Connection not found + 找不到連接 + + + + + Please provide a file path instead of directory path + 指定的檔案名稱也是目錄名稱: {0} + + + + + The provided path is invalid + 無法確認備份檔案位置的存在: {0} + + + + + Cannot access the specified path on the server: {0} + 無法存取伺服器上指定的路徑: {0} + + + + + No backupset selected to be restored + 無選擇的備份集可還原 + + + + + Never + 永不 + + + + + Azure SQL DB + Azure SQL DB + + + + + Azure SQL Data Warehouse + Azure SQL 資料倉儲 + + + + + Azure SQL Stretch Database + Azure SQL 延展資料庫 + + + + + Path {0} is not a valid directory + 路徑 {0} 不是有效的目錄 + + + + + For directory {0} a file with name {1} already exists + 因目錄 {0} 中已有存在的檔案名稱 {1} + + + + + Value {0} is too large to fit in column of type {1} + 數值 {0} 太大以致於無法符合欄位型態 {1} + + . + Parameters: 0 - value (string), 1 - columnType (string) + + + + \ No newline at end of file diff --git a/src/Microsoft.SqlTools.CoreServices/Microsoft.SqlTools.CoreServices.csproj b/src/Microsoft.SqlTools.CoreServices/Microsoft.SqlTools.CoreServices.csproj new file mode 100644 index 00000000..4f981eba --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Microsoft.SqlTools.CoreServices.csproj @@ -0,0 +1,39 @@ + + + Library + netcoreapp2.1 + Microsoft.SqlTools.CoreServices + Microsoft.SqlTools.CoreServices + false + + + � Microsoft Corporation. All rights reserved. + + A collection of core services that can be reused by a Database Management Protocol-based service using the Microsoft.SqlTools.Hosting framework. + + $(PackageDescription) + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Microsoft.SqlTools.CoreServices/Properties/AssemblyInfo.cs b/src/Microsoft.SqlTools.CoreServices/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..840d5cc5 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Properties/AssemblyInfo.cs @@ -0,0 +1,15 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: InternalsVisibleTo("Microsoft.SqlTools.Hosting.UnitTests")] +[assembly: InternalsVisibleTo("Microsoft.SqlTools.Services.UnitTests")] + +// Allowing internals visible access to Moq library to help testing +[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] + diff --git a/src/Microsoft.SqlTools.CoreServices/SqlContext/CompoundSqlToolsSettingsValues.cs b/src/Microsoft.SqlTools.CoreServices/SqlContext/CompoundSqlToolsSettingsValues.cs new file mode 100644 index 00000000..9515f155 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/SqlContext/CompoundSqlToolsSettingsValues.cs @@ -0,0 +1,102 @@ +// +// 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.Linq; +using Microsoft.SqlTools.Hosting.Utility; +using Newtonsoft.Json; + +namespace Microsoft.SqlTools.CoreServices.SqlContext +{ + + /// + /// Handles backwards compatibility of settings by checking for settings in a priority list. If a settings + /// group such as Intellisense is defined on a serialized setting it's used in the order of mssql, then sql, then + /// falls back to a default value. + /// + public class CompoundToolsSettingsValues: ISqlToolsSettingsValues + { + private List priorityList = new List(); + private SqlToolsSettingsValues defaultValues; + public CompoundToolsSettingsValues(ISqlToolsSettingsValues mssql, ISqlToolsSettingsValues all) + { + Validate.IsNotNull(nameof(mssql), mssql); + Validate.IsNotNull(nameof(all), all); + priorityList.Add(mssql); + priorityList.Add(all); + // Always add in a fallback which has default values to be used. + defaultValues = new SqlToolsSettingsValues(createDefaults: true); + priorityList.Add(defaultValues); + } + + private T GetSettingOrDefault(Func lookup) + where T : new() + { + T value = priorityList.Select( (settings) => lookup(settings)).Where(val => val != null).FirstOrDefault(); + return value != null ? value : new T(); + } + + /// + /// Gets or sets the detailed IntelliSense settings + /// + public IntelliSenseSettings IntelliSense + { + get + { + return GetSettingOrDefault((settings) => settings.IntelliSense); + } + set + { + priorityList[0].IntelliSense = value; + } + } + + // /// + // /// Gets or sets the query execution settings + // /// + // public QueryExecutionSettings QueryExecutionSettings + // { + // get + // { + // return GetSettingOrDefault((settings) => settings.QueryExecutionSettings); + // } + // set + // { + // priorityList[0].QueryExecutionSettings = value; + // } + // } + + // /// + // /// Gets or sets the formatter settings + // /// + // public FormatterSettings Format + // { + // get + // { + // return GetSettingOrDefault((settings) => settings.Format); + // } + // set + // { + // priorityList[0].Format = value; + // } + // } + + /// + /// Gets or sets the object explorer settings + /// + public ObjectExplorerSettings ObjectExplorer + { + get + { + return GetSettingOrDefault((settings) => settings.ObjectExplorer); + } + set + { + priorityList[0].ObjectExplorer = value; + } + } + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/SqlContext/ISqlToolsSettingsValues.cs b/src/Microsoft.SqlTools.CoreServices/SqlContext/ISqlToolsSettingsValues.cs new file mode 100644 index 00000000..eafa4f5e --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/SqlContext/ISqlToolsSettingsValues.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. +// + +namespace Microsoft.SqlTools.CoreServices.SqlContext +{ + /// + /// Defines the common settings used by the tools service + /// + public interface ISqlToolsSettingsValues + { + /// + /// Intellisense specific settings + /// + IntelliSenseSettings IntelliSense { get; set; } + + /// + /// Query execution specific settings + /// + // QueryExecutionSettings QueryExecutionSettings { get; set; } + + // /// + // /// Formatter settings + // /// + // FormatterSettings Format { get; set; } + + /// + /// Object Explorer specific settings + /// + ObjectExplorerSettings ObjectExplorer { get; set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.CoreServices/SqlContext/IntelliSenseSettings.cs b/src/Microsoft.SqlTools.CoreServices/SqlContext/IntelliSenseSettings.cs new file mode 100644 index 00000000..52e2364e --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/SqlContext/IntelliSenseSettings.cs @@ -0,0 +1,68 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.CoreServices.SqlContext +{ + /// + /// Class for serialization and deserialization of IntelliSense settings + /// + public class IntelliSenseSettings + { + /// + /// Initialize the IntelliSense settings defaults + /// + public IntelliSenseSettings() + { + this.EnableIntellisense = true; + this.EnableSuggestions = true; + this.LowerCaseSuggestions = false; + this.EnableErrorChecking = true; + this.EnableQuickInfo = true; + } + + /// + /// Gets or sets a flag determining if IntelliSense is enabled + /// + /// + public bool EnableIntellisense { get; set; } + + /// + /// Gets or sets a flag determining if suggestions are enabled + /// + /// + public bool? EnableSuggestions { get; set; } + + /// + /// Gets or sets a flag determining if built-in suggestions should be lowercase + /// + public bool? LowerCaseSuggestions { get; set; } + + /// + /// Gets or sets a flag determining if diagnostics are enabled + /// + public bool? EnableErrorChecking { get; set; } + + /// + /// Gets or sets a flag determining if quick info is enabled + /// + public bool? EnableQuickInfo { get; set; } + + /// + /// Update the Intellisense settings + /// + /// + public void Update(IntelliSenseSettings settings) + { + if (settings != null) + { + this.EnableIntellisense = settings.EnableIntellisense; + this.EnableSuggestions = settings.EnableSuggestions; + this.LowerCaseSuggestions = settings.LowerCaseSuggestions; + this.EnableErrorChecking = settings.EnableErrorChecking; + this.EnableQuickInfo = settings.EnableQuickInfo; + } + } + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/SqlContext/ObjectExplorerSettings.cs b/src/Microsoft.SqlTools.CoreServices/SqlContext/ObjectExplorerSettings.cs new file mode 100644 index 00000000..2ea305c1 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/SqlContext/ObjectExplorerSettings.cs @@ -0,0 +1,32 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.CoreServices.SqlContext +{ + /// + /// Contract for receiving object explorer settings as part of workspace settings + /// + public class ObjectExplorerSettings + { + public static int DefaultCreateSessionTimeout = 45; + public static int DefaultExpandTimeout = 45; + + public ObjectExplorerSettings() + { + CreateSessionTimeout = DefaultCreateSessionTimeout; + ExpandTimeout = DefaultExpandTimeout; + } + + /// + /// Number of seconds to wait before fail create session request with timeout error + /// + public int CreateSessionTimeout { get; set; } + + /// + /// Number of seconds to wait before fail expand request with timeout error + /// + public int ExpandTimeout { get; set; } + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/SqlContext/SqlToolsSettings.cs b/src/Microsoft.SqlTools.CoreServices/SqlContext/SqlToolsSettings.cs new file mode 100644 index 00000000..98adecc5 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/SqlContext/SqlToolsSettings.cs @@ -0,0 +1,145 @@ +// +// 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.Linq; +using Newtonsoft.Json; + +namespace Microsoft.SqlTools.CoreServices.SqlContext +{ + /// + /// Class for serialization and deserialization of the settings the SQL Tools Service needs. + /// + public class SqlToolsSettings + { + private ISqlToolsSettingsValues sqlTools = null; + private SqlToolsSettingsValues mssqlTools = null; + private SqlToolsSettingsValues allSqlTools = null; + + public ISqlToolsSettingsValues SqlTools + { + get + { + if (this.sqlTools == null) + { + this.sqlTools = new CompoundToolsSettingsValues(MssqlTools, AllSqlTools); + } + return this.sqlTools; + } + set + { + this.sqlTools = value; + } + } + + /// + /// Gets or sets the underlying settings value object + /// + [JsonProperty("mssql")] + public SqlToolsSettingsValues MssqlTools + { + get + { + if (this.mssqlTools == null) + { + this.mssqlTools = new SqlToolsSettingsValues(false); + } + return this.mssqlTools; + } + set + { + this.mssqlTools = value; + } + } + + /// + /// Gets or sets the underlying settings value object + /// + [JsonProperty("sql")] + public SqlToolsSettingsValues AllSqlTools + { + get + { + if (this.allSqlTools == null) + { + this.allSqlTools = new SqlToolsSettingsValues(false); + } + return this.allSqlTools; + } + set + { + this.sqlTools = value; + } + } + + /// + /// Query excution settings forwarding property + /// + // public QueryExecutionSettings QueryExecutionSettings + // { + // get { return this.SqlTools.QueryExecutionSettings; } + // } + + /// + /// Updates the extension settings + /// + /// + public void Update(SqlToolsSettings settings) + { + if (settings != null) + { + this.SqlTools.IntelliSense.Update(settings.SqlTools.IntelliSense); + } + } + + /// + /// Gets a flag determining if diagnostics are enabled + /// + public bool IsDiagnosticsEnabled + { + get + { + return this.SqlTools.IntelliSense.EnableIntellisense + && this.SqlTools.IntelliSense.EnableErrorChecking.Value; + } + } + + /// + /// Gets a flag determining if suggestions are enabled + /// + public bool IsSuggestionsEnabled + { + get + { + return this.SqlTools.IntelliSense.EnableIntellisense + && this.SqlTools.IntelliSense.EnableSuggestions.Value; + } + } + + /// + /// Gets a flag determining if quick info is enabled + /// + public bool IsQuickInfoEnabled + { + get + { + return this.SqlTools.IntelliSense.EnableIntellisense + && this.SqlTools.IntelliSense.EnableQuickInfo.Value; + } + } + + /// + /// Gets a flag determining if IntelliSense is enabled + /// + public bool IsIntelliSenseEnabled + { + get + { + return this.SqlTools.IntelliSense.EnableIntellisense; + } + } + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/SqlContext/SqlToolsSettingsValues.cs b/src/Microsoft.SqlTools.CoreServices/SqlContext/SqlToolsSettingsValues.cs new file mode 100644 index 00000000..63342290 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/SqlContext/SqlToolsSettingsValues.cs @@ -0,0 +1,54 @@ +// +// 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.Linq; +using Newtonsoft.Json; + +namespace Microsoft.SqlTools.CoreServices.SqlContext +{ + /// + /// Class that is used to serialize and deserialize SQL Tools settings + /// + public class SqlToolsSettingsValues : ISqlToolsSettingsValues + { + /// + /// Initializes the Sql Tools settings values + /// + public SqlToolsSettingsValues(bool createDefaults = true) + { + if (createDefaults) + { + IntelliSense = new IntelliSenseSettings(); + // QueryExecutionSettings = new QueryExecutionSettings(); + // Format = new FormatterSettings(); + } + } + + /// + /// Gets or sets the detailed IntelliSense settings + /// + public IntelliSenseSettings IntelliSense { get; set; } + + // /// + // /// Gets or sets the query execution settings + // /// + // [JsonProperty("query")] + // public QueryExecutionSettings QueryExecutionSettings { get; set; } + + // /// + // /// Gets or sets the formatter settings + // /// + // [JsonProperty("format")] + // public FormatterSettings Format { get; set; } + + /// + /// Gets or sets the formatter settings + /// + [JsonProperty("objectExplorer")] + public ObjectExplorerSettings ObjectExplorer { get; set; } + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/Utility/CommonConstants.cs b/src/Microsoft.SqlTools.CoreServices/Utility/CommonConstants.cs new file mode 100644 index 00000000..fbf4d0c4 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Utility/CommonConstants.cs @@ -0,0 +1,21 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + + +namespace Microsoft.SqlTools.CoreServices.Utility +{ + /// + /// Common Constant values used across multiple services + /// + public static class CommonConstants + { + public const string MasterDatabaseName = "master"; + public const string MsdbDatabaseName = "msdb"; + public const string ModelDatabaseName = "model"; + public const string TempDbDatabaseName = "tempdb"; + + public const string DefaultBatchSeperator = "GO"; + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/Utility/DatabaseUtils.cs b/src/Microsoft.SqlTools.CoreServices/Utility/DatabaseUtils.cs new file mode 100644 index 00000000..eb528c4f --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Utility/DatabaseUtils.cs @@ -0,0 +1,26 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System; + +namespace Microsoft.SqlTools.CoreServices.Utility +{ + public class DatabaseUtils + { + /// + /// Check if the database is a system database + /// + /// the name of database + /// return true if the database is a system database + public static bool IsSystemDatabaseConnection(string databaseName) + { + return (string.IsNullOrWhiteSpace(databaseName) || + string.Compare(databaseName, CommonConstants.MasterDatabaseName, StringComparison.OrdinalIgnoreCase) == 0 || + string.Compare(databaseName, CommonConstants.MsdbDatabaseName, StringComparison.OrdinalIgnoreCase) == 0 || + string.Compare(databaseName, CommonConstants.ModelDatabaseName, StringComparison.OrdinalIgnoreCase) == 0 || + string.Compare(databaseName, CommonConstants.TempDbDatabaseName, StringComparison.OrdinalIgnoreCase) == 0); + } + } +} diff --git a/src/Microsoft.SqlTools.CoreServices/Utility/InteractionMetrics.cs b/src/Microsoft.SqlTools.CoreServices/Utility/InteractionMetrics.cs new file mode 100644 index 00000000..5e7e4a05 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Utility/InteractionMetrics.cs @@ -0,0 +1,98 @@ +// +// 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.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.SqlTools.Hosting.Utility; + +namespace Microsoft.SqlTools.CoreServices +{ + /// + /// A class to calculate the value for the metrics using the given bucket + /// + public class InteractionMetrics + { + /// + /// Creates new instance given a bucket of metrics + /// + public InteractionMetrics(int[] metrics) + { + Validate.IsNotNull("metrics", metrics); + if(metrics.Length == 0) + { + throw new ArgumentOutOfRangeException("metrics"); + } + + Counters = new ConcurrentDictionary(); + if (!IsSorted(metrics)) + { + Array.Sort(metrics); + } + Metrics = metrics; + } + + private ConcurrentDictionary Counters { get; } + + private object perfCountersLock = new object(); + + /// + /// The metrics bucket + /// + public int[] Metrics { get; private set; } + + /// + /// Returns true if the given list is sorted + /// + private bool IsSorted(int[] metrics) + { + if (metrics.Length > 1) + { + int previous = metrics[0]; + for (int i = 1; i < metrics.Length; i++) + { + if(metrics[i] < previous) + { + return false; + } + previous = metrics[i]; + } + } + return true; + } + + /// + /// Update metric value given new number + /// + public void UpdateMetrics(double duration, T newValue, Func updateValueFactory) + { + int metric = Metrics[Metrics.Length - 1]; + for (int i = 0; i < Metrics.Length; i++) + { + if (duration <= Metrics[i]) + { + metric = Metrics[i]; + break; + } + } + string key = metric.ToString(); + Counters.AddOrUpdate(key, newValue, updateValueFactory); + } + + /// + /// Returns the quantile + /// + public Dictionary Quantile + { + get + { + return Counters.ToDictionary(kvp => kvp.Key, kvp => kvp.Value); + } + } + } +} + diff --git a/src/Microsoft.SqlTools.CoreServices/Workspace/SettingsService.cs b/src/Microsoft.SqlTools.CoreServices/Workspace/SettingsService.cs new file mode 100644 index 00000000..94d73f52 --- /dev/null +++ b/src/Microsoft.SqlTools.CoreServices/Workspace/SettingsService.cs @@ -0,0 +1,121 @@ +// +// 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.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.SqlTools.DataProtocol.Contracts.Workspace; +using Microsoft.SqlTools.Hosting; +using Microsoft.SqlTools.Hosting.Protocol; +using Microsoft.SqlTools.Hosting.Utility; + +namespace Microsoft.SqlTools.CoreServices.Workspace +{ + /// + /// Class for handling requests/events that deal with the state of the workspace, including the + /// opening and closing of files, the changing of configuration, etc. + /// + /// + /// The type of the class used for serializing and deserializing the configuration. Must be the + /// actual type of the instance otherwise deserialization will be incomplete. + /// + public class SettingsService where TConfig : class, new() + { + + #region Singleton Instance Implementation + + private static Lazy> instance = new Lazy>(() => new SettingsService()); + + public static SettingsService Instance + { + get { return instance.Value; } + } + + /// + /// Default, parameterless constructor. + /// TODO: Figure out how to make this truely singleton even with dependency injection for tests + /// + public SettingsService() + { + ConfigChangeCallbacks = new List(); + CurrentSettings = new TConfig(); + } + + #endregion + + #region Properties + /// + /// Current settings for the workspace + /// + public TConfig CurrentSettings { get; internal set; } + + /// + /// Delegate for callbacks that occur when the configuration for the workspace changes + /// + /// The settings that were just set + /// The settings before they were changed + /// Context of the event that triggered the callback + /// + public delegate Task ConfigChangeCallback(TConfig newSettings, TConfig oldSettings, EventContext eventContext); + + /// + /// List of callbacks to call when the configuration of the workspace changes + /// + private List ConfigChangeCallbacks { get; set; } + + #endregion + + #region Public Methods + + public void InitializeService(IServiceHost serviceHost) + { + // Register the handlers for when changes to the workspae occur + serviceHost.SetAsyncEventHandler(DidChangeConfigurationNotification.Type, HandleDidChangeConfigurationNotification); + } + + /// + /// Adds a new task to be called when the configuration has been changed. Use this to + /// handle changing configuration and changing the current configuration. + /// + /// Task to handle the request + public void RegisterConfigChangeCallback(ConfigChangeCallback task) + { + ConfigChangeCallbacks.Add(task); + } + + #endregion + + #region Event Handlers + + /// + /// Handles the configuration change event + /// + internal async Task HandleDidChangeConfigurationNotification( + DidChangeConfigurationParams configChangeParams, + EventContext eventContext) + { + try + { + Logger.Instance.Write(LogLevel.Verbose, "HandleDidChangeConfigurationNotification"); + + // Propagate the changes to the event handlers + var configUpdateTasks = ConfigChangeCallbacks.Select( + t => t(configChangeParams.Settings, CurrentSettings, eventContext)); + await Task.WhenAll(configUpdateTasks); + } + catch (Exception ex) + { + Logger.Instance.Write(LogLevel.Error, "Unknown error " + ex.ToString()); + // Swallow exceptions here to prevent us from crashing + // TODO: this probably means the ScriptFile model is in a bad state or out of sync with the actual file; we should recover here + return; + } + } + + #endregion + } +} diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/ClientCapabilities.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/ClientCapabilities.cs new file mode 100644 index 00000000..660ccd4b --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/ClientCapabilities.cs @@ -0,0 +1,28 @@ +// +// 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.DataProtocol.Contracts.ClientCapabilities.TextDocument; +using Microsoft.SqlTools.DataProtocol.Contracts.ClientCapabilities.Workspace; + +namespace Microsoft.SqlTools.DataProtocol.Contracts.ClientCapabilities +{ + public class ClientCapabilities + { + /// + /// Any experimental client capabilities + /// + public object Experimental { get; set; } + + /// + /// Text document specific client capabilities, can be null + /// + public TextDocumentCapabilities TextDocument { get; set; } + + /// + /// Workspace specific client capabilities, can be null + /// + public WorkspaceCapabilities Workspace { get; set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/DynamicRegistrationCapability.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/DynamicRegistrationCapability.cs new file mode 100644 index 00000000..18eb6806 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/DynamicRegistrationCapability.cs @@ -0,0 +1,15 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.DataProtocol.Contracts.ClientCapabilities +{ + public class DynamicRegistrationCapability + { + /// + /// Whether the capabilitiy supports dynamic registration + /// + public bool? DynamicRegistration { get; set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/CodeAction.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/CodeAction.cs new file mode 100644 index 00000000..e43c8c7c --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/CodeAction.cs @@ -0,0 +1,14 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.DataProtocol.Contracts.ClientCapabilities.TextDocument +{ + /// + /// Capabilities specific to textDocument/codeAction requests + /// + public class CodeActionCapabilities : DynamicRegistrationCapability + { + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/CodeLens.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/CodeLens.cs new file mode 100644 index 00000000..beefa677 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/CodeLens.cs @@ -0,0 +1,14 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.DataProtocol.Contracts.ClientCapabilities.TextDocument +{ + /// + /// Capabilities specific to textDocument/codeLens requests + /// + public class CodeLensCapabilities : DynamicRegistrationCapability + { + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/ColorProvider.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/ColorProvider.cs new file mode 100644 index 00000000..fa7a9a6e --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/ColorProvider.cs @@ -0,0 +1,14 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.DataProtocol.Contracts.ClientCapabilities.TextDocument +{ + /// + /// Capabilities specific to the colorProviderw + /// + public class ColorProviderCapabilities : DynamicRegistrationCapability + { + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/Completion.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/Completion.cs new file mode 100644 index 00000000..6714ef32 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/Completion.cs @@ -0,0 +1,63 @@ +// +// 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.DataProtocol.Contracts.Common; + +namespace Microsoft.SqlTools.DataProtocol.Contracts.ClientCapabilities.TextDocument +{ + /// + /// Capabilities specific to the 'textDocument/completion' request + /// + public class CompletionCapabilities : DynamicRegistrationCapability + { + /// + /// Client supports these CompletionItem specific capabilities. Can be null + /// + public CompletionItemCapabilities CompletionItem { get; set; } + + /// + /// Client supports these CompletionItemKinds as responses to completion requests + /// + public CompletionItemKindCapabiltities CompletionItemKind { get; set; } + } + + public class CompletionItemCapabilities + { + /// + /// Whether client supports snippet formats as completion results + /// + /// + /// A snippet can define tab stops and placeholders with $1, $2 and + /// ${3:foo}. $0 defines the final tab stop, it defaults to the end of + /// the snippet. Placeholders with equal identifiers are linked, that is typing in one + /// will update others, too. + /// + public bool? SnippetSupport { get; set; } + + /// + /// Whether client supports commit characters on a completion item + /// + public bool? CommitCharactersSpport { get; set; } + + /// + /// Client supports these content formats for the documentation property. The order + /// describes the preferred format of the client. May be null + /// + public MarkupKind[] DocumentationFormat { get; set; } + } + + public class CompletionItemKindCapabiltities + { + /// + /// Completion item kind values the client supports. When this property exists, the + /// client also guarantees that it will handle values outside its set gracefully and + /// falls back to a default value when unknown. + /// + /// If this property is not present, the client only supports the completion item kinds + /// from Text to Reference as defined in the initial version of the protocol. + /// + public CompletionItemKinds? ValueSet { get; set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/Definition.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/Definition.cs new file mode 100644 index 00000000..9b19a3b4 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/Definition.cs @@ -0,0 +1,14 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.DataProtocol.Contracts.ClientCapabilities.TextDocument +{ + /// + /// Capabilities specific to textDocument/definition requests + /// + public class DefinitionCapabilities : DynamicRegistrationCapability + { + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/DocumentHighlight.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/DocumentHighlight.cs new file mode 100644 index 00000000..b1ca1e53 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/DocumentHighlight.cs @@ -0,0 +1,14 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.DataProtocol.Contracts.ClientCapabilities.TextDocument +{ + /// + /// Capabilities specific to textDocument/documentHighlight requests + /// + public class DocumentHighlightCapabilities : DynamicRegistrationCapability + { + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/DocumentLink.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/DocumentLink.cs new file mode 100644 index 00000000..113ac8e6 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/DocumentLink.cs @@ -0,0 +1,14 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.DataProtocol.Contracts.ClientCapabilities.TextDocument +{ + /// + /// Capabilities specific to textDocument/documentLink requests + /// + public class DocumentLinkCapabilities : DynamicRegistrationCapability + { + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/DocumentSymbol.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/DocumentSymbol.cs new file mode 100644 index 00000000..96da8353 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/DocumentSymbol.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.DataProtocol.Contracts.Common; + +namespace Microsoft.SqlTools.DataProtocol.Contracts.ClientCapabilities.TextDocument +{ + /// + /// Capabilities specific to textDocument/documentSymbol requests + /// + public class DocumentSymbolCapabilities : DynamicRegistrationCapability + { + /// + /// Specific capabilities for the SymbolKind + /// + public DocumentSymbolKindCapabilities SymbolKind { get; set; } + } + + public class DocumentSymbolKindCapabilities + { + /// + /// Symbol kind values the client supports. When this property exists, the client also + /// guarantees that it will handle values outside its set gracefully and falls back to a + /// default value when unknown. + /// + /// If this property is not present, the client only supports the symbol kinds from File to + /// Array as defined in the initial version of the protocol + /// + public SymbolKinds? ValueSet { get; set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/Formatting.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/Formatting.cs new file mode 100644 index 00000000..3fcde43e --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/Formatting.cs @@ -0,0 +1,14 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +//w + +namespace Microsoft.SqlTools.DataProtocol.Contracts.ClientCapabilities.TextDocument +{ + /// + /// Capabilities specific to textDocument/formatting requests + /// + public class FormattingCapabilities : DynamicRegistrationCapability + { + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/Hover.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/Hover.cs new file mode 100644 index 00000000..d01d1172 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/Hover.cs @@ -0,0 +1,21 @@ +// +// 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.DataProtocol.Contracts.Common; + +namespace Microsoft.SqlTools.DataProtocol.Contracts.ClientCapabilities.TextDocument +{ + /// + /// Capabilities specific to textDocument/hover requests + /// + public class HoverCapabilities : DynamicRegistrationCapability + { + /// + /// Client supports these content formats for the content property. The order describes + /// the preferred format of the client. + /// + public MarkupKind[] ContentFormat { get; set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/Implementation.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/Implementation.cs new file mode 100644 index 00000000..78a4f766 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/Implementation.cs @@ -0,0 +1,14 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.DataProtocol.Contracts.ClientCapabilities.TextDocument +{ + /// + /// Capabilities specific to textDocument/implementation requests + /// + public class ImplementationCapabilities : DynamicRegistrationCapability + { + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/OnTypeFormatting.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/OnTypeFormatting.cs new file mode 100644 index 00000000..1ed2a509 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/OnTypeFormatting.cs @@ -0,0 +1,14 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.DataProtocol.Contracts.ClientCapabilities.TextDocument +{ + /// + /// Capabilities specific to textDocument/onTypeFormatting requests + /// + public class OnTypeFormattingCapabilities : DynamicRegistrationCapability + { + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/PublishDignostics.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/PublishDignostics.cs new file mode 100644 index 00000000..04411576 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/PublishDignostics.cs @@ -0,0 +1,18 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.DataProtocol.Contracts.ClientCapabilities.TextDocument +{ + /// + /// Capabilities specific to textDocument/publishDiagnostics requests + /// + public class PublishDignosticsCapabilities + { + /// + /// Whether the client accepts diagnostics with related information + /// + public bool? RelatedInformation { get; set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/RangeFormatting.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/RangeFormatting.cs new file mode 100644 index 00000000..859a8ef6 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/RangeFormatting.cs @@ -0,0 +1,14 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.DataProtocol.Contracts.ClientCapabilities.TextDocument +{ + /// + /// Capabilities specific to textDocument/rangeFormatting requests + /// + public class RangeFormattingCapabilities : DynamicRegistrationCapability + { + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/References.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/References.cs new file mode 100644 index 00000000..81829d55 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/References.cs @@ -0,0 +1,14 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.DataProtocol.Contracts.ClientCapabilities.TextDocument +{ + /// + /// Capabilities specific to textDocument/reference requests + /// + public class ReferencesCapabilities : DynamicRegistrationCapability + { + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/Rename.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/Rename.cs new file mode 100644 index 00000000..b03559c4 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/Rename.cs @@ -0,0 +1,14 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.DataProtocol.Contracts.ClientCapabilities.TextDocument +{ + /// + /// Capabilities specific to textDocument/rename requests + /// + public class RenameCapabilities : DynamicRegistrationCapability + { + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/SignatureHelp.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/SignatureHelp.cs new file mode 100644 index 00000000..962b7e5f --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/SignatureHelp.cs @@ -0,0 +1,29 @@ +// +// 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.DataProtocol.Contracts.Common; + +namespace Microsoft.SqlTools.DataProtocol.Contracts.ClientCapabilities.TextDocument +{ + /// + /// Capabilities specific to textDocument/signatureHelp requests + /// + public class SignatureHelpCapabilities : DynamicRegistrationCapability + { + /// + /// Client supports these SignatureInformation specific properties + /// + public SignatureInformationCapabilities SignatureInformation { get; set; } + } + + public class SignatureInformationCapabilities + { + /// + /// Client supports these content formats for the documentation property. The order + /// describes the preferred format of the client. + /// + public MarkupKind[] DocumentFormat { get; set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/Synchronization.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/Synchronization.cs new file mode 100644 index 00000000..fcd34821 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/Synchronization.cs @@ -0,0 +1,23 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.DataProtocol.Contracts.ClientCapabilities.TextDocument +{ + /// + /// Defines which synchonization capabilities the client supports + /// + public class SynchronizationCapabilities : DynamicRegistrationCapability + { + /// + /// Whether the client supports sending "will save" notifications + /// + public bool? WillSave { get; set; } + + /// + /// Whether the client supports sending "did save" notifications + /// + public bool? DidSave { get; set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/TextDocumentCapabilities.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/TextDocumentCapabilities.cs new file mode 100644 index 00000000..4f626958 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/TextDocumentCapabilities.cs @@ -0,0 +1,103 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.DataProtocol.Contracts.ClientCapabilities.TextDocument +{ + /// + /// Text document specific client capabilities + /// + public class TextDocumentCapabilities + { + /// + /// Capabilities specific to the textDocument/codeAction request. Can be null + /// + public CodeActionCapabilities CodeAction { get; set; } + + /// + /// Capabilities specific to the colorProvider. Can be null + /// + public ColorProviderCapabilities ColorProvider { get; set; } + + /// + /// Capabilities specific to the textDocument/completion request. Can be null + /// + public CompletionCapabilities Completion { get; set; } + + /// + /// Capabilities specific to the textDocument/definition request. Can be null + /// + public DefinitionCapabilities Definition { get; set; } + + /// + /// Capabilities specific to the textDocument/highlight request. Can be null + /// + public DocumentHighlightCapabilities DocumentHighlight { get; set; } + + /// + /// Capabilities specific to the textDocument/documentLink request. Can be null + /// + public DocumentLinkCapabilities DocumentLink { get; set; } + + /// + /// Capabilities specific to the textDocument/documentSymbol request. Can be null + /// + public DocumentSymbolCapabilities DocumentSymbol { get; set; } + + /// + /// Capabilities specific to the textDocument/formatting request. Can be null + /// + public FormattingCapabilities Formatting { get; set; } + + /// + /// Capabilities specific to the textDocument/hover request. Can be null + /// + public HoverCapabilities Hover { get; set; } + + /// + /// Capabilities specific to the textDocument/implementation request. Can be null + /// + public ImplementationCapabilities Implementation { get; set; } + + /// + /// Capabilities specific to the textDocument/onTypeFormatting request. Can be null + /// + public OnTypeFormattingCapabilities OnTypeFormatting { get; set; } + + /// + /// Capabilities specific to the textDocument/publishDiagnostics request. Can be null + /// + public PublishDignosticsCapabilities PublishDiagnostics { get; set; } + + /// + /// Capabilities specific to the textDocument/rangeFormatting request. Can be null + /// + public RangeFormattingCapabilities RangeFormatting { get; set; } + + /// + /// Capabilities specific to the textDocument/references request. Can be null + /// + public ReferencesCapabilities References { get; set; } + + /// + /// Capabilities specific to the textDocument/rename request. Can be null + /// + public RenameCapabilities Rename { get; set; } + + /// + /// Capabilities specific to the textDocument/signatureHelp request. Can be null + /// + public SignatureHelpCapabilities SignatureHelp { get; set; } + + /// + /// Defines which synchronization capabilities the client supports. Can be null + /// + public SynchronizationCapabilities Synchronization { get; set; } + + /// + /// Capabilities specific to the textDocument/typeDefinition requests. Can be null + /// + public TypeDefinitionCapabilities TypeDefinition { get; set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/TypeDefinition.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/TypeDefinition.cs new file mode 100644 index 00000000..6f0256e6 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/TextDocument/TypeDefinition.cs @@ -0,0 +1,14 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.DataProtocol.Contracts.ClientCapabilities.TextDocument +{ + /// + /// Capabilities specific to textDocument/typeDefinition requests + /// + public class TypeDefinitionCapabilities : DynamicRegistrationCapability + { + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/Workspace/DidChangeConfiguration.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/Workspace/DidChangeConfiguration.cs new file mode 100644 index 00000000..21ade5b3 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/Workspace/DidChangeConfiguration.cs @@ -0,0 +1,14 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.DataProtocol.Contracts.ClientCapabilities.Workspace +{ + /// + /// Capabilities specific to the workspace/didChangeConfiguration notification + /// + public class DidChangeConfigurationCapabilities : DynamicRegistrationCapability + { + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/Workspace/DidChangeWatchedFiles.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/Workspace/DidChangeWatchedFiles.cs new file mode 100644 index 00000000..e6404a6b --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/Workspace/DidChangeWatchedFiles.cs @@ -0,0 +1,14 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.DataProtocol.Contracts.ClientCapabilities.Workspace +{ + /// + /// Capabilities specific to the workspace/didChangeWatchedFiles notificiation + /// + public class DidChangeWatchedFilesCapabilities : DynamicRegistrationCapability + { + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/Workspace/ExecuteCommand.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/Workspace/ExecuteCommand.cs new file mode 100644 index 00000000..bb0c75b3 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/Workspace/ExecuteCommand.cs @@ -0,0 +1,14 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.DataProtocol.Contracts.ClientCapabilities.Workspace +{ + /// + /// Capabilities specific to the workspace/executeCommand request + /// + public class ExecuteCommandCapabilities : DynamicRegistrationCapability + { + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/Workspace/Symbol.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/Workspace/Symbol.cs new file mode 100644 index 00000000..f05d00e1 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/Workspace/Symbol.cs @@ -0,0 +1,37 @@ +// +// 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.DataProtocol.Contracts.Common; + +namespace Microsoft.SqlTools.DataProtocol.Contracts.ClientCapabilities.Workspace +{ + /// + /// Capabilities specific to the workspace/symbol request + /// + public class SymbolCapabilities : DynamicRegistrationCapability + { + /// + /// Specific capabilities for the SymbolKind in a workspace/symbol request. Can be + /// null + /// + public SymbolKindCapabilities SymbolKind { get; set; } + } + + /// + /// Specific capabilities for the SymbolKind in a workspace/symbol request + /// + public class SymbolKindCapabilities + { + /// + /// The symbol kind values the client supports. When this property exists, the client also + /// guarantees that it will handle values outside its set gracefully and falls back to a + /// default value when unknown. + /// + /// If this property is not present the client only supports the symbol kinds from File to + /// Array as defined in the initial version of the protocol. + /// + public SymbolKinds? ValueSet { get; set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/Workspace/WorkspaceCapabilities.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/Workspace/WorkspaceCapabilities.cs new file mode 100644 index 00000000..9d462df5 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/Workspace/WorkspaceCapabilities.cs @@ -0,0 +1,58 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.DataProtocol.Contracts.ClientCapabilities.Workspace +{ + /// + /// Workspace specific client capabilities + /// + public class WorkspaceCapabilities + { + /// + /// Client support applying batche edits to the workspace by supporting the + /// workspace/applyEdit request + /// + public bool? ApplyEdit { get; set; } + + /// + /// Whether the client supports workspace/configuration requests + /// + public bool? Configuration { get; set; } + + /// + /// Capabilities specific to the workspace/didChangeConfiguration notification. Can be + /// null + /// + public DidChangeConfigurationCapabilities DidChangeConfiguration { get; set; } + + /// + /// Capabilities specific to the workspace/executeCommand request. Can be null + /// + public ExecuteCommandCapabilities ExecuteCommand { get; set; } + + /// + /// Capabilities specific to the workspace/didChangeWatchedFiles notificiation. Can be + /// null + /// + public DidChangeWatchedFilesCapabilities DidChangeWatchedFiles { get; set; } + + /// + /// Capabilities specific to the workspace/symbol request. Can be null + /// + public SymbolCapabilities Symbol { get; set; } + + /// + /// Capabilities specific to WorkspaceEdit requests + /// + public WorkspaceEditCapabilities WorkspaceEdit { get; set; } + + /// + /// Whether the client supports multiple workspace folders open at a time. If true, the + /// open workspace folders will be provided during initialization via + /// + /// + public bool? WorkspaceFolders { get; set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/Workspace/WorkspaceEdit.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/Workspace/WorkspaceEdit.cs new file mode 100644 index 00000000..2d61f6d8 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/ClientCapabilities/Workspace/WorkspaceEdit.cs @@ -0,0 +1,18 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.DataProtocol.Contracts.ClientCapabilities.Workspace +{ + /// + /// Capabilities specific to WorkspaceEdit requests + /// + public class WorkspaceEditCapabilities + { + /// + /// Whether the client supports versioned document changes in WorkspaceEdit requests + /// + public bool? DocumentChanges { get; set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/Common/CompletionItemKind.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/Common/CompletionItemKind.cs new file mode 100644 index 00000000..a71de947 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/Common/CompletionItemKind.cs @@ -0,0 +1,91 @@ +// +// 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 Microsoft.SqlTools.DataProtocol.Contracts.Utilities; +using Newtonsoft.Json; + +namespace Microsoft.SqlTools.DataProtocol.Contracts.Common +{ + [Flags] + [JsonConverter(typeof(FlagsIntConverter))] + public enum CompletionItemKinds + { + [FlagsIntConverter.SerializeValue(1)] + Text = 1 << 0, + + [FlagsIntConverter.SerializeValue(2)] + Method = 1 << 1, + + [FlagsIntConverter.SerializeValue(3)] + Function = 1 << 2, + + [FlagsIntConverter.SerializeValue(4)] + Constructor = 1 << 3, + + [FlagsIntConverter.SerializeValue(5)] + Field = 1 << 4, + + [FlagsIntConverter.SerializeValue(6)] + Variable = 1 << 5, + + [FlagsIntConverter.SerializeValue(7)] + Class = 1 << 6, + + [FlagsIntConverter.SerializeValue(8)] + Interface = 1 << 7, + + [FlagsIntConverter.SerializeValue(9)] + Module = 1 << 8, + + [FlagsIntConverter.SerializeValue(10)] + Property = 1 << 9, + + [FlagsIntConverter.SerializeValue(11)] + Unit = 1 << 10, + + [FlagsIntConverter.SerializeValue(12)] + Value = 1 << 11, + + [FlagsIntConverter.SerializeValue(13)] + Enum = 1 << 12, + + [FlagsIntConverter.SerializeValue(14)] + Keyword = 1 << 13, + + [FlagsIntConverter.SerializeValue(15)] + Snippet = 1 << 14, + + [FlagsIntConverter.SerializeValue(16)] + Color = 1 << 15, + + [FlagsIntConverter.SerializeValue(17)] + File = 1 << 16, + + [FlagsIntConverter.SerializeValue(18)] + Reference = 1 << 17, + + [FlagsIntConverter.SerializeValue(19)] + Folder = 1 << 18, + + [FlagsIntConverter.SerializeValue(20)] + EnumMember = 1 << 19, + + [FlagsIntConverter.SerializeValue(21)] + Constant = 1 << 20, + + [FlagsIntConverter.SerializeValue(22)] + Struct = 1 << 21, + + [FlagsIntConverter.SerializeValue(23)] + Event = 1 << 22, + + [FlagsIntConverter.SerializeValue(24)] + Operator = 1 << 23, + + [FlagsIntConverter.SerializeValue(25)] + TypeParameter = 1 << 24 + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/Common/MarkupKind.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/Common/MarkupKind.cs new file mode 100644 index 00000000..8b419ecf --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/Common/MarkupKind.cs @@ -0,0 +1,24 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; + +namespace Microsoft.SqlTools.DataProtocol.Contracts.Common +{ + /// + /// Describes the content type that a client supports in various result literals like Hover, + /// ParameterInfo, or CompletionItem. + /// + /// Please note that MarkupKinds must not start with a '$'. These kinds are reserved for + /// internal usage. + /// + [JsonConverter(typeof(StringEnumConverter))] + public enum MarkupKind + { + PlainText = 1, + Markdown = 2 + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/Common/SymbolKinds.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/Common/SymbolKinds.cs new file mode 100644 index 00000000..80279677 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/Common/SymbolKinds.cs @@ -0,0 +1,94 @@ +// +// 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 Microsoft.SqlTools.DataProtocol.Contracts.Utilities; +using Newtonsoft.Json; + +namespace Microsoft.SqlTools.DataProtocol.Contracts.Common +{ + [Flags] + [JsonConverter(typeof(FlagsIntConverter))] + public enum SymbolKinds + { + [FlagsIntConverter.SerializeValue(1)] + File = 1 << 0, + + [FlagsIntConverter.SerializeValue(2)] + Module = 1 << 1, + + [FlagsIntConverter.SerializeValue(3)] + Namespace = 1 << 2, + + [FlagsIntConverter.SerializeValue(4)] + Package = 1 << 3, + + [FlagsIntConverter.SerializeValue(5)] + Class = 1 << 4, + + [FlagsIntConverter.SerializeValue(6)] + Method = 1 << 5, + + [FlagsIntConverter.SerializeValue(7)] + Property = 1 << 6, + + [FlagsIntConverter.SerializeValue(8)] + Field = 1 << 7, + + [FlagsIntConverter.SerializeValue(9)] + Constructor = 1 << 8, + + [FlagsIntConverter.SerializeValue(10)] + Enum = 1 << 9, + + [FlagsIntConverter.SerializeValue(11)] + Interface = 1 << 10, + + [FlagsIntConverter.SerializeValue(12)] + Function = 1 << 11, + + [FlagsIntConverter.SerializeValue(13)] + Variable = 1 << 12, + + [FlagsIntConverter.SerializeValue(14)] + Constant = 1 << 13, + + [FlagsIntConverter.SerializeValue(15)] + String = 1 << 14, + + [FlagsIntConverter.SerializeValue(16)] + Number = 1 << 15, + + [FlagsIntConverter.SerializeValue(17)] + Boolean = 1 << 16, + + [FlagsIntConverter.SerializeValue(18)] + Array = 1 << 17, + + [FlagsIntConverter.SerializeValue(19)] + Object = 1 << 18, + + [FlagsIntConverter.SerializeValue(20)] + Key = 1 << 19, + + [FlagsIntConverter.SerializeValue(21)] + Null = 1 << 20, + + [FlagsIntConverter.SerializeValue(22)] + EnumMember = 1 << 21, + + [FlagsIntConverter.SerializeValue(23)] + Struct = 1 << 22, + + [FlagsIntConverter.SerializeValue(24)] + Event = 1 << 23, + + [FlagsIntConverter.SerializeValue(25)] + Operator = 1 << 24, + + [FlagsIntConverter.SerializeValue(26)] + TypeParameter = 1 << 25 + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/Common/WorkspaceFolder.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/Common/WorkspaceFolder.cs new file mode 100644 index 00000000..29a54540 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/Common/WorkspaceFolder.cs @@ -0,0 +1,20 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.DataProtocol.Contracts.Common +{ + public class WorkspaceFolder + { + /// + /// Name of the workspace folder. Defaults to 's basename + /// + public string Name { get; set; } + + /// + /// Associated URI for this workspace folder + /// + public string Uri { get; set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/CancelConnectParams.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/CancelConnectParams.cs new file mode 100644 index 00000000..41349022 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/CancelConnectParams.cs @@ -0,0 +1,24 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.DataProtocol.Contracts.Connection +{ + /// + /// Parameters for the Cancel Connect Request. + /// + public class CancelConnectParams + { + /// + /// A URI identifying the owner of the connection. This will most commonly be a file in the workspace + /// or a virtual file representing an object in a database. + /// + public string OwnerUri { get; set; } + + /// + /// The type of connection we are trying to cancel + /// + public string Type { get; set; } = ConnectionType.Default; + } +} diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/CancelConnectRequest.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/CancelConnectRequest.cs new file mode 100644 index 00000000..bbd3cf75 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/CancelConnectRequest.cs @@ -0,0 +1,19 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using Microsoft.SqlTools.Hosting.Contracts; + +namespace Microsoft.SqlTools.DataProtocol.Contracts.Connection +{ + /// + /// Cancel connect request mapping entry + /// + public class CancelConnectRequest + { + public static readonly + RequestType Type = + RequestType.Create("connection/cancelconnect"); + } +} diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ChangeDatabaseParams.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ChangeDatabaseParams.cs new file mode 100644 index 00000000..0ec49df7 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ChangeDatabaseParams.cs @@ -0,0 +1,23 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.DataProtocol.Contracts.Connection +{ + /// + /// Parameters for the List Databases Request. + /// + public class ChangeDatabaseParams + { + /// + /// URI of the owner of the connection requesting the list of databases. + /// + public string OwnerUri { get; set; } + + /// + /// The database to change to + /// + public string NewDatabase { get; set; } + } +} diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ChangeDatabaseRequest.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ChangeDatabaseRequest.cs new file mode 100644 index 00000000..25ec1855 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ChangeDatabaseRequest.cs @@ -0,0 +1,19 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using Microsoft.SqlTools.Hosting.Contracts; + +namespace Microsoft.SqlTools.DataProtocol.Contracts.Connection +{ + /// + /// List databases request mapping entry + /// + public class ChangeDatabaseRequest + { + public static readonly + RequestType Type = + RequestType.Create("connection/changedatabase"); + } +} diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ConnectParams.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ConnectParams.cs new file mode 100644 index 00000000..b7c53530 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ConnectParams.cs @@ -0,0 +1,37 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.DataProtocol.Contracts.Connection +{ + /// + /// Parameters for the Connect Request. + /// + public class ConnectParams + { + /// + /// A URI identifying the owner of the connection. This will most commonly be a file in the workspace + /// or a virtual file representing an object in a database. + /// + public string OwnerUri { get; set; } + + /// + /// Contains the required parameters to initialize a connection to a database. + /// A connection will identified by its server name, database name and user name. + /// This may be changed in the future to support multiple connections with different + /// connection properties to the same database. + /// + public ConnectionDetails Connection { get; set; } + + /// + /// The type of this connection. By default, this is set to ConnectionType.Default. + /// + public string Type { get; set; } = ConnectionType.Default; + + /// + /// The porpose of the connection to keep track of open connections + /// + public string Purpose { get; set; } = ConnectionType.GeneralConnection; + } +} diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ConnectionChangedNotification.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ConnectionChangedNotification.cs new file mode 100644 index 00000000..ee1c2298 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ConnectionChangedNotification.cs @@ -0,0 +1,19 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using Microsoft.SqlTools.Hosting.Contracts; + +namespace Microsoft.SqlTools.DataProtocol.Contracts.Connection +{ + /// + /// ConnectionChanged notification mapping entry + /// + public class ConnectionChangedNotification + { + public static readonly + EventType Type = + EventType.Create("connection/connectionchanged"); + } +} diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ConnectionChangedParams.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ConnectionChangedParams.cs new file mode 100644 index 00000000..45b9e5e0 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ConnectionChangedParams.cs @@ -0,0 +1,23 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.DataProtocol.Contracts.Connection +{ + /// + /// Parameters for the ConnectionChanged Notification. + /// + public class ConnectionChangedParams + { + /// + /// A URI identifying the owner of the connection. This will most commonly be a file in the workspace + /// or a virtual file representing an object in a database. + /// + public string OwnerUri { get; set; } + /// + /// Contains the high-level properties about the connection, for display to the user. + /// + public ConnectionSummary Connection { get; set; } + } +} diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ConnectionCompleteNotification.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ConnectionCompleteNotification.cs new file mode 100644 index 00000000..712f7d71 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ConnectionCompleteNotification.cs @@ -0,0 +1,66 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using Microsoft.SqlTools.Hosting.Contracts; + +namespace Microsoft.SqlTools.DataProtocol.Contracts.Connection +{ + /// + /// Parameters to be sent back with a connection complete event + /// + public class ConnectionCompleteParams + { + /// + /// A URI identifying the owner of the connection. This will most commonly be a file in the workspace + /// or a virtual file representing an object in a database. + /// + public string OwnerUri { get; set; } + + /// + /// A GUID representing a unique connection ID + /// + public string ConnectionId { get; set; } + + /// + /// Gets or sets any detailed connection error messages. + /// + public string Messages { get; set; } + + /// + /// Error message returned from the engine for a connection failure reason, if any. + /// + public string ErrorMessage { get; set; } + + /// + /// Error number returned from the engine for connection failure reason, if any. + /// + public int ErrorNumber { get; set; } + + /// + /// Information about the connected server. + /// + public ServerInfo ServerInfo { get; set; } + + /// + /// Gets or sets the actual Connection established, including Database Name + /// + public ConnectionSummary ConnectionSummary { get; set; } + + /// + /// The type of connection that this notification is for + /// + public string Type { get; set; } = ConnectionType.Default; + } + + /// + /// ConnectionComplete notification mapping entry + /// + public class ConnectionCompleteNotification + { + public static readonly + EventType Type = + EventType.Create("connection/complete"); + } +} diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ConnectionDetails.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ConnectionDetails.cs new file mode 100644 index 00000000..e6d503b4 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ConnectionDetails.cs @@ -0,0 +1,525 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + + +namespace Microsoft.SqlTools.DataProtocol.Contracts.Connection +{ + /// + /// Message format for the initial connection request + /// + /// + /// If this contract is ever changed, be sure to update ConnectionDetailsExtensions methods. + /// + public class ConnectionDetails : GeneralRequestDetails, IConnectionSummary + { + public ConnectionDetails() : base() + { + } + + /// + /// Gets or sets the connection password + /// + public string Password + { + get + { + return GetOptionValue("password"); + } + set + { + SetOptionValue("password", value); + } + } + + /// + /// Gets or sets the connection server name + /// + public string ServerName + { + get + { + return GetOptionValue("server"); + } + + set + { + SetOptionValue("server", value); + } + } + + /// + /// Gets or sets the connection database name + /// + public string DatabaseName + { + get + { + return GetOptionValue("database"); + } + + set + { + SetOptionValue("database", value); + } + } + + /// + /// Gets or sets the connection user name + /// + public string UserName + { + get + { + return GetOptionValue("user"); + } + + set + { + SetOptionValue("user", value); + } + } + + /// + /// Gets or sets the authentication to use. + /// + public string AuthenticationType + { + get + { + return GetOptionValue("authenticationType"); + } + + set + { + SetOptionValue("authenticationType", value); + } + } + + /// + /// Gets or sets a Boolean value that indicates whether SQL Server uses SSL encryption for all data sent between the client and server if the server has a certificate installed. + /// + public bool? Encrypt + { + get + { + return GetOptionValue("encrypt"); + } + + set + { + SetOptionValue("encrypt", value); + } + } + + /// + /// Gets or sets a value that indicates whether the channel will be encrypted while bypassing walking the certificate chain to validate trust. + /// + public bool? TrustServerCertificate + { + get + { + return GetOptionValue("trustServerCertificate"); + } + + set + { + SetOptionValue("trustServerCertificate", value); + } + } + + /// + /// Gets or sets a Boolean value that indicates if security-sensitive information, such as the password, is not returned as part of the connection if the connection is open or has ever been in an open state. + /// + public bool? PersistSecurityInfo + { + get + { + return GetOptionValue("persistSecurityInfo"); + } + + set + { + SetOptionValue("persistSecurityInfo", value); + } + } + + /// + /// Gets or sets the length of time (in seconds) to wait for a connection to the server before terminating the attempt and generating an error. + /// + public int? ConnectTimeout + { + get + { + return GetOptionValue("connectTimeout"); + } + + set + { + SetOptionValue("connectTimeout", value); + } + } + + /// + /// The number of reconnections attempted after identifying that there was an idle connection failure. + /// + public int? ConnectRetryCount + { + get + { + return GetOptionValue("connectRetryCount"); + } + + set + { + SetOptionValue("connectRetryCount", value); + } + } + + /// + /// Amount of time (in seconds) between each reconnection attempt after identifying that there was an idle connection failure. + /// + public int? ConnectRetryInterval + { + get + { + return GetOptionValue("connectRetryInterval"); + } + + set + { + SetOptionValue("connectRetryInterval", value); + } + } + + /// + /// Gets or sets the name of the application associated with the connection string. + /// + public string ApplicationName + { + get + { + return GetOptionValue("applicationName"); + } + + set + { + SetOptionValue("applicationName", value); + } + } + + /// + /// Gets or sets the name of the workstation connecting to SQL Server. + /// + public string WorkstationId + { + get + { + return GetOptionValue("workstationId"); + } + + set + { + SetOptionValue("workstationId", value); + } + } + + /// + /// Declares the application workload type when connecting to a database in an SQL Server Availability Group. + /// + public string ApplicationIntent + { + get + { + return GetOptionValue("applicationIntent"); + } + + set + { + SetOptionValue("applicationIntent", value); + } + } + + /// + /// Gets or sets the SQL Server Language record name. + /// + public string CurrentLanguage + { + get + { + return GetOptionValue("currentLanguage"); + } + + set + { + SetOptionValue("currentLanguage", value); + } + } + + /// + /// Gets or sets a Boolean value that indicates whether the connection will be pooled or explicitly opened every time that the connection is requested. + /// + public bool? Pooling + { + get + { + return GetOptionValue("pooling"); + } + + set + { + SetOptionValue("pooling", value); + } + } + + /// + /// Gets or sets the maximum number of connections allowed in the connection pool for this specific connection string. + /// + public int? MaxPoolSize + { + get + { + return GetOptionValue("maxPoolSize"); + } + + set + { + SetOptionValue("maxPoolSize", value); + } + } + + /// + /// Gets or sets the minimum number of connections allowed in the connection pool for this specific connection string. + /// + public int? MinPoolSize + { + get + { + return GetOptionValue("minPoolSize"); + } + + set + { + SetOptionValue("minPoolSize", value); + } + } + + /// + /// Gets or sets the minimum time, in seconds, for the connection to live in the connection pool before being destroyed. + /// + public int? LoadBalanceTimeout + { + get + { + return GetOptionValue("loadBalanceTimeout"); + } + + set + { + SetOptionValue("loadBalanceTimeout", value); + } + } + + /// + /// Gets or sets a Boolean value that indicates whether replication is supported using the connection. + /// + public bool? Replication + { + get + { + return GetOptionValue("replication"); + } + + set + { + SetOptionValue("replication", value); + } + } + + /// + /// Gets or sets a string that contains the name of the primary data file. This includes the full path name of an attachable database. + /// + public string AttachDbFilename + { + get + { + return GetOptionValue("attachDbFilename"); + } + + set + { + SetOptionValue("attachDbFilename", value); + } + } + + /// + /// Gets or sets the name or address of the partner server to connect to if the primary server is down. + /// + public string FailoverPartner + { + get + { + return GetOptionValue("failoverPartner"); + } + + set + { + SetOptionValue("failoverPartner", value); + } + } + + /// + /// If your application is connecting to an AlwaysOn availability group (AG) on different subnets, setting MultiSubnetFailover=true provides faster detection of and connection to the (currently) active server. + /// + public bool? MultiSubnetFailover + { + get + { + return GetOptionValue("multiSubnetFailover"); + } + + set + { + SetOptionValue("multiSubnetFailover", value); + } + } + + /// + /// When true, an application can maintain multiple active result sets (MARS). + /// + public bool? MultipleActiveResultSets + { + get + { + return GetOptionValue("multipleActiveResultSets"); + } + + set + { + SetOptionValue("multipleActiveResultSets", value); + } + } + + /// + /// Gets or sets the size in bytes of the network packets used to communicate with an instance of SQL Server. + /// + public int? PacketSize + { + get + { + return GetOptionValue("packetSize"); + } + + set + { + SetOptionValue("packetSize", value); + } + } + + /// + /// Gets or sets the port to use for the TCP/IP connection + /// + public int? Port + { + get + { + return GetOptionValue("port"); + } + + set + { + SetOptionValue("port", value); + } + } + + /// + /// Gets or sets a string value that indicates the type system the application expects. + /// + public string TypeSystemVersion + { + get + { + return GetOptionValue("typeSystemVersion"); + } + + set + { + SetOptionValue("typeSystemVersion", value); + } + } + + /// + /// Gets or sets a string value to be used as the connection string. If given, all other options will be ignored. + /// + public string ConnectionString + { + get + { + return GetOptionValue("connectionString"); + } + + set + { + SetOptionValue("connectionString", value); + } + } + + /// + /// Gets or sets the group ID + /// + public string GroupId + { + get + { + return GetOptionValue("groupId"); + } + set + { + SetOptionValue("groupId", value); + } + } + + /// + /// Gets or sets the database display name + /// + public string DatabaseDisplayName + { + get + { + return GetOptionValue("databaseDisplayName"); + } + set + { + SetOptionValue("databaseDisplayName", value); + } + } + + public bool IsComparableTo(ConnectionDetails other) + { + if (other == null) + { + return false; + } + + if (ServerName != other.ServerName + || AuthenticationType != other.AuthenticationType + || UserName != other.UserName) + { + return false; + } + + // For database name, only compare if neither is empty. This is important + // Since it allows for handling of connections to the default database, but is + // not a 100% accurate heuristic. + if (!string.IsNullOrEmpty(DatabaseName) + && !string.IsNullOrEmpty(other.DatabaseName) + && DatabaseName != other.DatabaseName) + { + return false; + } + + return true; + } + } +} diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ConnectionDetailsExtensions.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ConnectionDetailsExtensions.cs new file mode 100644 index 00000000..0a4ffbf1 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ConnectionDetailsExtensions.cs @@ -0,0 +1,51 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.DataProtocol.Contracts.Connection +{ + /// + /// Extension methods for the ConnectionDetails contract class + /// + public static class ConnectionDetailsExtensions + { + /// + /// Create a copy of a connection details object. + /// + public static ConnectionDetails Clone(this ConnectionDetails details) + { + return new ConnectionDetails() + { + ServerName = details.ServerName, + DatabaseName = details.DatabaseName, + UserName = details.UserName, + Password = details.Password, + AuthenticationType = details.AuthenticationType, + Encrypt = details.Encrypt, + TrustServerCertificate = details.TrustServerCertificate, + PersistSecurityInfo = details.PersistSecurityInfo, + ConnectTimeout = details.ConnectTimeout, + ConnectRetryCount = details.ConnectRetryCount, + ConnectRetryInterval = details.ConnectRetryInterval, + ApplicationName = details.ApplicationName, + WorkstationId = details.WorkstationId, + ApplicationIntent = details.ApplicationIntent, + CurrentLanguage = details.CurrentLanguage, + Pooling = details.Pooling, + MaxPoolSize = details.MaxPoolSize, + MinPoolSize = details.MinPoolSize, + LoadBalanceTimeout = details.LoadBalanceTimeout, + Replication = details.Replication, + AttachDbFilename = details.AttachDbFilename, + FailoverPartner = details.FailoverPartner, + MultiSubnetFailover = details.MultiSubnetFailover, + MultipleActiveResultSets = details.MultipleActiveResultSets, + PacketSize = details.PacketSize, + TypeSystemVersion = details.TypeSystemVersion, + ConnectionString = details.ConnectionString, + Port = details.Port + }; + } + } +} diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ConnectionRequest.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ConnectionRequest.cs new file mode 100644 index 00000000..1a32a72d --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ConnectionRequest.cs @@ -0,0 +1,19 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using Microsoft.SqlTools.Hosting.Contracts; + +namespace Microsoft.SqlTools.DataProtocol.Contracts.Connection +{ + /// + /// Connect request mapping entry + /// + public class ConnectionRequest + { + public static readonly + RequestType Type = + RequestType.Create("connection/connect"); + } +} diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ConnectionSummary.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ConnectionSummary.cs new file mode 100644 index 00000000..1fb7992b --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ConnectionSummary.cs @@ -0,0 +1,48 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + + +namespace Microsoft.SqlTools.DataProtocol.Contracts.Connection +{ + + 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 : IConnectionSummary + { + /// + /// Gets or sets the connection server name + /// + public virtual string ServerName { get; set; } + + /// + /// Gets or sets the connection database name + /// + public virtual string DatabaseName { get; set; } + + /// + /// Gets or sets the connection user name + /// + public virtual string UserName { get; set; } + } +} diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ConnectionSummaryComparer.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ConnectionSummaryComparer.cs new file mode 100644 index 00000000..99f2c07b --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ConnectionSummaryComparer.cs @@ -0,0 +1,53 @@ +// +// 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; + +namespace Microsoft.SqlTools.DataProtocol.Contracts.Connection +{ + + /// + /// Treats connections as the same if their server, db and usernames all match + /// + public class ConnectionSummaryComparer : IEqualityComparer + { + public bool Equals(ConnectionSummary x, ConnectionSummary y) + { + if(x == y) { return true; } + else if(x != null) + { + if(y == null) { return false; } + + // Compare server, db, username. Note: server is case-insensitive in the driver + return string.Compare(x.ServerName, y.ServerName, StringComparison.OrdinalIgnoreCase) == 0 + && string.Compare(x.DatabaseName, y.DatabaseName, StringComparison.Ordinal) == 0 + && string.Compare(x.UserName, y.UserName, StringComparison.Ordinal) == 0; + } + return false; + } + + public int GetHashCode(ConnectionSummary obj) + { + int hashcode = 31; + if(obj != null) + { + if(obj.ServerName != null) + { + hashcode ^= obj.ServerName.GetHashCode(); + } + if (obj.DatabaseName != null) + { + hashcode ^= obj.DatabaseName.GetHashCode(); + } + if (obj.UserName != null) + { + hashcode ^= obj.UserName.GetHashCode(); + } + } + return hashcode; + } + } +} diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ConnectionSummaryExtensions.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ConnectionSummaryExtensions.cs new file mode 100644 index 00000000..90c8ad94 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ConnectionSummaryExtensions.cs @@ -0,0 +1,26 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.DataProtocol.Contracts.Connection +{ + /// + /// Extension methods to ConnectionSummary + /// + public static class ConnectionSummaryExtensions + { + /// + /// Create a copy of a ConnectionSummary object + /// + public static ConnectionSummary Clone(this IConnectionSummary summary) + { + return new ConnectionSummary() + { + ServerName = summary.ServerName, + DatabaseName = summary.DatabaseName, + UserName = summary.UserName + }; + } + } +} diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ConnectionType.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ConnectionType.cs new file mode 100644 index 00000000..b60eef91 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ConnectionType.cs @@ -0,0 +1,23 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.DataProtocol.Contracts.Connection +{ + /// + /// String constants that represent connection types. + /// + /// Default: Connection used by the editor. Opened by the editor upon the initial connection. + /// Query: Connection used for executing queries. Opened when the first query is executed. + /// + public static class ConnectionType + { + public const string Default = "Default"; + public const string Query = "Query"; + public const string Edit = "Edit"; + public const string ObjectExplorer = "ObjectExplorer"; + public const string Dashboard = "Dashboard"; + public const string GeneralConnection = "GeneralConnection"; + } +} diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/DisconnectParams.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/DisconnectParams.cs new file mode 100644 index 00000000..472f1f6c --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/DisconnectParams.cs @@ -0,0 +1,25 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.DataProtocol.Contracts.Connection +{ + /// + /// Parameters for the Disconnect Request. + /// + public class DisconnectParams + { + /// + /// A URI identifying the owner of the connection. This will most commonly be a file in the workspace + /// or a virtual file representing an object in a database. + /// + public string OwnerUri { get; set; } + + /// + /// The type of connection we are disconnecting. If null, we will disconnect all connections. + /// connections. + /// + public string Type { get; set; } + } +} diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/DisconnectRequest.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/DisconnectRequest.cs new file mode 100644 index 00000000..2cd0d563 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/DisconnectRequest.cs @@ -0,0 +1,19 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using Microsoft.SqlTools.Hosting.Contracts; + +namespace Microsoft.SqlTools.DataProtocol.Contracts.Connection +{ + /// + /// Disconnect request mapping entry + /// + public class DisconnectRequest + { + public static readonly + RequestType Type = + RequestType.Create("connection/disconnect"); + } +} diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/LanguageFlavorChange.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/LanguageFlavorChange.cs new file mode 100644 index 00000000..aea0b609 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/LanguageFlavorChange.cs @@ -0,0 +1,42 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using Microsoft.SqlTools.Hosting.Contracts; + +namespace Microsoft.SqlTools.DataProtocol.Contracts.Connection +{ + + /// + /// Parameters for the Language Flavor Change notification. + /// + public class LanguageFlavorChangeParams + { + /// + /// A URI identifying the affected resource + /// + public string Uri { get; set; } + + /// + /// The primary language + /// + public string Language { get; set; } + + /// + /// The specific language flavor that is being set + /// + public string Flavor { get; set; } + } + + /// + /// Defines an event that is sent from the client to notify that + /// the client is exiting and the server should as well. + /// + public class LanguageFlavorChangeNotification + { + public static readonly + EventType Type = + EventType.Create("connection/languageflavorchanged"); + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ListDatabasesParams.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ListDatabasesParams.cs new file mode 100644 index 00000000..bcfd1ba8 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ListDatabasesParams.cs @@ -0,0 +1,18 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.DataProtocol.Contracts.Connection +{ + /// + /// Parameters for the List Databases Request. + /// + public class ListDatabasesParams + { + /// + /// URI of the owner of the connection requesting the list of databases. + /// + public string OwnerUri { get; set; } + } +} diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ListDatabasesRequest.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ListDatabasesRequest.cs new file mode 100644 index 00000000..13b96dbb --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ListDatabasesRequest.cs @@ -0,0 +1,19 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using Microsoft.SqlTools.Hosting.Contracts; + +namespace Microsoft.SqlTools.DataProtocol.Contracts.Connection +{ + /// + /// List databases request mapping entry + /// + public class ListDatabasesRequest + { + public static readonly + RequestType Type = + RequestType.Create("connection/listdatabases"); + } +} diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ListDatabasesResponse.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ListDatabasesResponse.cs new file mode 100644 index 00000000..31ef23f7 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ListDatabasesResponse.cs @@ -0,0 +1,18 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.DataProtocol.Contracts.Connection +{ + /// + /// Message format for the list databases response + /// + public class ListDatabasesResponse + { + /// + /// Gets or sets the list of database names. + /// + public string[] DatabaseNames { get; set; } + } +} diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ServerInfo.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ServerInfo.cs new file mode 100644 index 00000000..23f8caf1 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/Connection/ServerInfo.cs @@ -0,0 +1,68 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.DataProtocol.Contracts.Connection +{ + /// + /// Contract for information on the connected SQL Server instance. + /// + public class ServerInfo + { + /// + /// The major version of the SQL Server instance. + /// + public int ServerMajorVersion { get; set; } + + /// + /// The minor version of the SQL Server instance. + /// + public int ServerMinorVersion { get; set; } + + /// + /// The build of the SQL Server instance. + /// + public int ServerReleaseVersion { get; set; } + + /// + /// The ID of the engine edition of the SQL Server instance. + /// + public int EngineEditionId { get; set; } + + /// + /// String containing the full server version text. + /// + public string ServerVersion { get; set; } + + /// + /// String describing the product level of the server. + /// + public string ServerLevel { get; set; } + + /// + /// The edition of the SQL Server instance. + /// + public string ServerEdition { get; set; } + + /// + /// Whether the SQL Server instance is running in the cloud (Azure) or not. + /// + public bool IsCloud { get; set; } + + /// + /// The version of Azure that the SQL Server instance is running on, if applicable. + /// + public int AzureVersion { get; set; } + + /// + /// The Operating System version string of the machine running the SQL Server instance. + /// + public string OsVersion { get; set; } + + /// + /// The Operating System version string of the machine running the SQL Server instance. + /// + public string MachineName { get; set; } + } +} diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/Explorer/CloseSessionRequest.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/Explorer/CloseSessionRequest.cs new file mode 100644 index 00000000..d4e0d00e --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/Explorer/CloseSessionRequest.cs @@ -0,0 +1,53 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using Microsoft.SqlTools.Hosting.Contracts; +using Microsoft.SqlTools.DataProtocol.Contracts.Connection; + +namespace Microsoft.SqlTools.DataProtocol.Contracts.Explorer +{ + /// + /// Information returned from a . + /// Contains success information, a to be used when + /// requesting closing an existing session. + /// + public class CloseSessionResponse + { + /// + /// Boolean indicating if the session was closed successfully + /// + public bool Success { get; set; } + + /// + /// Unique ID to use when sending any requests for objects in the + /// tree under the node + /// + public string SessionId { get; set; } + } + + /// + /// Parameters to the . + /// + public class CloseSessionParams + { + /// + /// The Id returned from a . This + /// is used to disambiguate between different trees. + /// + public string SessionId { get; set; } + } + + /// + /// Establishes an Object Explorer tree session for a specific connection. + /// This will create a connection to a specific server or database, register + /// it for use in the + /// + public class CloseSessionRequest + { + public static readonly + RequestType Type = + RequestType.Create("explorer/closesession"); + } +} diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/Explorer/CreateSessionRequest.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/Explorer/CreateSessionRequest.cs new file mode 100644 index 00000000..0d8648ca --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/Explorer/CreateSessionRequest.cs @@ -0,0 +1,65 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using Microsoft.SqlTools.Hosting.Contracts; +using Microsoft.SqlTools.DataProtocol.Contracts.Connection; + +namespace Microsoft.SqlTools.DataProtocol.Contracts.Explorer +{ + /// + /// Information returned from a . + /// Contains success information, a to be used when + /// requesting expansion of nodes, and a root node to display for this area. + /// + public class CreateSessionResponse + { + /// + /// Unique ID to use when sending any requests for objects in the + /// tree under the node + /// + public string SessionId { get; set; } + + } + + /// + /// Information returned from a . + /// Contains success information, a to be used when + /// requesting expansion of nodes, and a root node to display for this area. + /// + public class SessionCreatedParameters + { + /// + /// Boolean indicating if the connection was successful + /// + public bool Success { get; set; } + + /// + /// Unique ID to use when sending any requests for objects in the + /// tree under the node + /// + public string SessionId { get; set; } + + /// + /// Information describing the base node in the tree + /// + public NodeInfo RootNode { get; set; } + + + /// + /// Error message returned from the engine for a object explorer session failure reason, if any. + /// + public string ErrorMessage { get; set; } + } + + /// + /// Session notification mapping entry + /// + public class CreateSessionCompleteNotification + { + public static readonly + EventType Type = + EventType.Create("explorer/sessioncreated"); + } +} diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/Explorer/ExpandRequest.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/Explorer/ExpandRequest.cs new file mode 100644 index 00000000..670778cf --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/Explorer/ExpandRequest.cs @@ -0,0 +1,76 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using Microsoft.SqlTools.Hosting.Contracts; + +namespace Microsoft.SqlTools.DataProtocol.Contracts.Explorer +{ + /// + /// Information returned from a . + /// + public class ExpandResponse + { + /// + /// Unique ID to use when sending any requests for objects in the + /// tree under the node + /// + public string SessionId { get; set; } + + /// + /// Information describing the expanded nodes in the tree + /// + public NodeInfo[] Nodes { get; set; } + + /// + /// Path identifying the node to expand. See for details + /// + public string NodePath { get; set; } + + /// + /// Error message returned from the engine for a object explorer expand failure reason, if any. + /// + public string ErrorMessage { get; set; } + } + + /// + /// Parameters to the . + /// + public class ExpandParams + { + /// + /// The Id returned from a . This + /// is used to disambiguate between different trees. + /// + public string SessionId { get; set; } + + /// + /// Path identifying the node to expand. See for details + /// + public string NodePath { get; set; } + } + + /// + /// A request to expand a node in the tree + /// + public class ExpandRequest + { + /// + /// Returns children of a given node as a array. + /// + public static readonly + RequestType Type = + RequestType.Create("explorer/expand"); + } + + /// + /// Expand notification mapping entry + /// + public class ExpandCompleteNotification + { + public static readonly + EventType Type = + EventType.Create("explorer/expandCompleted"); + } +} diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/Explorer/FindNodesRequest.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/Explorer/FindNodesRequest.cs new file mode 100644 index 00000000..238dade2 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/Explorer/FindNodesRequest.cs @@ -0,0 +1,55 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System.Collections.Generic; +using Microsoft.SqlTools.Hosting.Contracts; +using Microsoft.SqlTools.DataProtocol.Contracts.Connection; + +namespace Microsoft.SqlTools.DataProtocol.Contracts.Explorer +{ + /// + /// Information returned from a . + /// + public class FindNodesResponse + { + /// + /// Information describing the matching nodes in the tree + /// + public List Nodes { get; set; } + } + + /// + /// Parameters to the . + /// + public class FindNodesParams + { + /// + /// The Id returned from a . This + /// is used to disambiguate between different trees. + /// + public string SessionId { get; set; } + + public string Type { get; set; } + + public string Schema { get; set; } + + public string Name { get; set; } + + public string Database { get; set; } + + public List ParentObjectNames { get; set; } + + } + + /// + /// TODO + /// + public class FindNodesRequest + { + public static readonly + RequestType Type = + RequestType.Create("explorer/findnodes"); + } +} diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/Explorer/NodeInfo.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/Explorer/NodeInfo.cs new file mode 100644 index 00000000..3f82a247 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/Explorer/NodeInfo.cs @@ -0,0 +1,63 @@ +// +// 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.DataProtocol.Contracts.Metadata; + +namespace Microsoft.SqlTools.DataProtocol.Contracts.Explorer +{ + /// + /// Information describing a Node in the Object Explorer tree. + /// Contains information required to display the Node to the user and + /// to know whether actions such as expanding children is possible + /// the node + /// + public class NodeInfo + { + /// + /// Path identifying this node: for example a table will be at ["server", "database", "tables", "tableName"]. + /// This enables rapid navigation of the tree without the need for a global registry of elements. + /// The path functions as a unique ID and is used to disambiguate the node when sending requests for expansion. + /// A common ID is needed since processes do not share address space and need a unique identifier + /// + public string NodePath { get; set; } + + /// + /// The type of the node - for example Server, Database, Folder, Table + /// + public string NodeType { get; set; } + + /// + /// Label to display to the user, describing this node. + /// + public string Label { get; set; } + + /// + /// Node Sub type - for example a key can have type as "Key" and sub type as "PrimaryKey" + /// + public string NodeSubType { get; set; } + + /// + /// Node status - for example login can be disabled/enabled + /// + public string NodeStatus { get; set; } + + /// + /// Is this a leaf node (in which case no children can be generated) or + /// is it expandable? + /// + public bool IsLeaf { get; set; } + + /// + /// Object Metadata for smo objects to be used for scripting + /// + public ObjectMetadata Metadata { get; set; } + + /// + /// Error message returned from the engine for a object explorer node failure reason, if any. + /// + public string ErrorMessage { get; set; } + } +} diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/Explorer/RefreshRequest.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/Explorer/RefreshRequest.cs new file mode 100644 index 00000000..e9099aee --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/Explorer/RefreshRequest.cs @@ -0,0 +1,29 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using Microsoft.SqlTools.Hosting.Contracts; + +namespace Microsoft.SqlTools.DataProtocol.Contracts.Explorer +{ + /// + /// Parameters to the . + /// + public class RefreshParams: ExpandParams + { + } + + /// + /// A request to expand a + /// + public class RefreshRequest + { + /// + /// Returns children of a given node as a array. + /// + public static readonly + RequestType Type = + RequestType.Create("explorer/refresh"); + } +} diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/GeneralRequestDetails.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/GeneralRequestDetails.cs new file mode 100644 index 00000000..17dd01db --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/GeneralRequestDetails.cs @@ -0,0 +1,114 @@ +// +// 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; + +namespace Microsoft.SqlTools.DataProtocol.Contracts +{ + public class GeneralRequestDetails + { + public GeneralRequestDetails() + { + Options = new Dictionary(); + } + + public T GetOptionValue(string name) + { + T result = default(T); + if (Options != null && Options.ContainsKey(name)) + { + object value = Options[name]; + try + { + result = GetValueAs(value); + } + catch + { + result = default(T); + // TODO move logger to a utilities project + // Logger.Instance.Write(LogLevel.Warning, string.Format(CultureInfo.InvariantCulture, + // "Cannot convert option value {0}:{1} to {2}", name, value ?? "", typeof(T))); + } + } + return result; + } + + public static T GetValueAs(object value) + { + T result = default(T); + + 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); + } + else if (typeof(T).IsEnum) + { + object enumValue; + if (TryParseEnum(typeof(T), value.ToString(), out enumValue)) + { + value = (T)enumValue; + } + } + } + else if (value != null && (typeof(T).IsEnum)) + { + object enumValue; + if (TryParseEnum(typeof(T), value.ToString(), out enumValue)) + { + value = enumValue; + } + } + result = value != null ? (T)value : default(T); + + return result; + } + + /// + /// This method exists because in NetStandard the Enum.TryParse methods that accept in a type + /// are not present, and the generic TryParse method requires the type T to be non-nullable which + /// is hard to check. This is different to the NetCore definition for some reason. + /// It seems easier to implement our own than work around this. + /// + private static bool TryParseEnum(Type t, string value, out object enumValue) + { + try + { + enumValue = Enum.Parse(t, value); + return true; + } + catch(Exception) + { + enumValue = default(T); + return false; + } + } + + 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/src/Microsoft.SqlTools.DataProtocol.Contracts/InitializeRequest.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/InitializeRequest.cs new file mode 100644 index 00000000..a9944980 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/InitializeRequest.cs @@ -0,0 +1,94 @@ +// +// 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 Microsoft.SqlTools.DataProtocol.Contracts.Common; +using Microsoft.SqlTools.Hosting.Contracts; + +namespace Microsoft.SqlTools.DataProtocol.Contracts +{ + public enum TraceOptions + { + Off, + Messages, + Verbose + } + + /// + /// Parameters provided with an initialize request + /// + /// + /// This is the initialize request parameters used by VSCode language server. These are + /// provided here for convenience of implementing initialization request handlers when the + /// server is expected to be used by the VSCode language client. You are not obligated to use + /// these initialization params when writing your server, nor are you even obligated to + /// implement an initialize handler. However, the VSCode language client will always send an + /// initialize request when starting the server and will not consider the server "ready" until + /// a response to the init request has been received. + /// + public class InitializeParameters + { + /// + /// Capabilities of the initializing client + /// + public ClientCapabilities.ClientCapabilities Capabilities { get; set; } + + /// + /// Root path of the workspace, is null if no folder is open. + /// + /// + /// This function has been deprecated in favor of workspace folders + /// + [Obsolete("Deprecated in favor of rootUri")] + public string RootPath { get; set; } + + /// + /// Root URI of the workspace, is null if no folder is open. If both + /// and are set, should be used. + /// + /// + /// This function has been deprecated in favor of workspace folders + /// + [Obsolete("Deprecated in favor of workspace folders")] + public string RootUri { get; set; } + + /// + /// Initial trace setting. If omitted, trace is disabled + /// + public TraceOptions? Trace { get; set; } + + /// + /// Workspace folders that are open at the time of initialization. If this is provided, it + /// takes precedence over and + /// + public WorkspaceFolder[] WorkspaceFolders { get; set; } + } + + /// + /// Parameters provided as a result to an initialize request + /// + /// + /// This is the initialize result parameters used by VSCode language server. These are provided + /// for convenience of implementing initialization request handlers when the server is expected + /// to be used by the VSCode language client. You are not obligated to use these initialization + /// params when writing your server, nor are you even obligated to implement an initialize + /// handler. However, the VSCode language client will always send an initialize request when + /// starting the server and will not consider the server "ready" until a response to the init + /// request has been received. + /// + public class InitializeResponse + { + /// + /// Capabilities that this server provides + /// + public ServerCapabilities.ServerCapabilities Capabilities { get; set; } + } + + public class InitializeRequest + { + public static readonly RequestType Type = + RequestType.Create("initialize"); + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/InitializeRequestWithOptions.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/InitializeRequestWithOptions.cs new file mode 100644 index 00000000..a7e55dea --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/InitializeRequestWithOptions.cs @@ -0,0 +1,49 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using Microsoft.SqlTools.Hosting.Contracts; + +namespace Microsoft.SqlTools.DataProtocol.Contracts +{ + /// + /// Parameters provided with an initialize request with extra options provided by the client + /// + /// + /// Type of the initialization options expected from the client, can be any reference type + /// + public class InitializeParametersWithOptions : InitializeParameters where TInitializationOptions : class + { + /// + /// Initialization options provided by the client, can be null + /// + public TInitializationOptions InitializationOptions { get; set; } + } + + /// + /// Request definition for initialization of the server. This version provides optional extra + /// parameters that can be used to pass extra information between client and server during + /// initialization. If these extra options aren't needed, use . + /// + /// + /// Type to use for extra parameters in the initialize request. These appear as + /// . + /// If these extra options are not expected, but extra response options are, simply use + /// object as the type. + /// + /// + /// Type to use for the initialize response. Due to VSCode's protocol definition, any extra + /// params that should be sent back to the client are defined as dictionary of key/value pairs. + /// This can be emulated by defining a class that extends with + /// whatever extra params are expected. If no extra options are needed, but extra request + /// options are, simply use as the type. + /// + public class InitializeRequestWithOptions + where TInitializeOptions : class + where TInitializeResponse : InitializeResponse + { + public static readonly RequestType, TInitializeResponse> Type = + RequestType, TInitializeResponse>.Create("initialize"); + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/Metadata/ObjectMetadata.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/Metadata/ObjectMetadata.cs new file mode 100644 index 00000000..fe6f7b6d --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/Metadata/ObjectMetadata.cs @@ -0,0 +1,36 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.DataProtocol.Contracts.Metadata +{ + /// + /// Metadata type enumeration + /// + public enum MetadataType + { + Table = 0, + View = 1, + SProc = 2, + Function = 3, + Schema = 4, + Database = 5 + } + + /// + /// Object metadata information + /// + public class ObjectMetadata + { + public MetadataType MetadataType { get; set; } + + public string MetadataTypeName { get; set; } + + public string Schema { get; set; } + + public string Name { get; set; } + + public string Urn { get; set; } + } +} diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/Microsoft.SqlTools.DataProtocol.Contracts.csproj b/src/Microsoft.SqlTools.DataProtocol.Contracts/Microsoft.SqlTools.DataProtocol.Contracts.csproj new file mode 100644 index 00000000..af269551 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/Microsoft.SqlTools.DataProtocol.Contracts.csproj @@ -0,0 +1,16 @@ + + + netstandard2.0 + + The contract types used for communication over the VSCode Language Server Protocol and the Database Management Protocol. + + $(PackageDescription) + + + + + + + + + \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/ServerCapabilities/CodeLensOptions.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/ServerCapabilities/CodeLensOptions.cs new file mode 100644 index 00000000..c7fe52b6 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/ServerCapabilities/CodeLensOptions.cs @@ -0,0 +1,19 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.DataProtocol.Contracts.ServerCapabilities +{ + /// + /// Options about Code Lens that the server supports + /// + public class CodeLensOptions + { + /// + /// Code lens has a resolve provider, as well + /// TODO: WTF does this mean?? + /// + public bool? ResolveProvider { get; set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/ServerCapabilities/CompletionOptions.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/ServerCapabilities/CompletionOptions.cs new file mode 100644 index 00000000..477c7b45 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/ServerCapabilities/CompletionOptions.cs @@ -0,0 +1,30 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.DataProtocol.Contracts.ServerCapabilities +{ + /// + /// Defines completion options that the server can support + /// + public class CompletionOptions + { + /// + /// Most tools trigger completion request automatically without explicitly requesting it + /// using a keyboard shortcut (eg, ctrl+space). Typically they do so when the user starts + /// to type an identifier. For example if the user types 'c' in a JavaScript file, code + /// completion will automatically pop up and present 'console' besides others as a + /// completion item. Characters that make up identifiers don't need to be listed here. + /// + /// If code completion should automatically be triggered on characters not being valid + /// inside an identifier (for example '.' in JavaScript) list them in this. + /// + public string[] TriggerCharacters { get; set; } + + /// + /// Server provides support to resolve additional information about a completion item + /// + public bool? ResolveProvider { get; set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/ServerCapabilities/DocumentLinkOptions.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/ServerCapabilities/DocumentLinkOptions.cs new file mode 100644 index 00000000..2d97e44d --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/ServerCapabilities/DocumentLinkOptions.cs @@ -0,0 +1,19 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.DataProtocol.Contracts.ServerCapabilities +{ + /// + /// Options the server support for document links + /// + public class DocumentLinkOptions + { + /// + /// Document links have a resolve provider, as well + /// TODO: WTF does this mean? + /// + public bool? ResolveProvider { get; set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/ServerCapabilities/DocumentOnTypeFormattingOptions.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/ServerCapabilities/DocumentOnTypeFormattingOptions.cs new file mode 100644 index 00000000..9c068692 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/ServerCapabilities/DocumentOnTypeFormattingOptions.cs @@ -0,0 +1,23 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.DataProtocol.Contracts.ServerCapabilities +{ + /// + /// Options the server supports regarding formatting a document on type + /// + public class DocumentOnTypeFormattingOptions + { + /// + /// Character on which formatting should be triggered, eg '}' + /// + public string FirstTriggerCharacter { get; set; } + + /// + /// More charactres that trigger formatting + /// + public string[] MoreTriggerCharacters { get; set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/ServerCapabilities/ExecuteCommandOptions.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/ServerCapabilities/ExecuteCommandOptions.cs new file mode 100644 index 00000000..b62cf521 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/ServerCapabilities/ExecuteCommandOptions.cs @@ -0,0 +1,18 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.DataProtocol.Contracts.ServerCapabilities +{ + /// + /// Options the server supports regarding command execution + /// + public class ExecuteCommandOptions + { + /// + /// Commands the server can execute + /// + public string[] Commands { get; set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/ServerCapabilities/SaveOptions.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/ServerCapabilities/SaveOptions.cs new file mode 100644 index 00000000..de797a76 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/ServerCapabilities/SaveOptions.cs @@ -0,0 +1,18 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.DataProtocol.Contracts.ServerCapabilities +{ + /// + /// Options the server supports for saving + /// + public class SaveOptions + { + /// + /// Whether the client is supposed to include the content on save + /// + public bool? IncludeText { get; set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/ServerCapabilities/ServerCapabilities.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/ServerCapabilities/ServerCapabilities.cs new file mode 100644 index 00000000..810eee09 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/ServerCapabilities/ServerCapabilities.cs @@ -0,0 +1,122 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.DataProtocol.Contracts.ServerCapabilities +{ + public class ServerCapabilities + { + /// + /// Defines how text documents are synced. Is either a detailed structure defining each + /// notification or for backwards compatibility the TextDocumentSyncKind number. + /// + /// TODO: Use the Union type + public TextDocumentSyncKind TextDocumentSync { get; set; } + + /// + /// Whether the server provides code actions. Can be null + /// + public bool? CodeActionProvider { get; set; } + + /// + /// Options that the server provides for code lens. Can be null to indicate code + /// lens is not supported. + /// + public CodeLensOptions CodeLensProvider { get; set; } + + /// + /// Options that the server supports for completion. Can be null to indicate + /// completion is not supported. + /// + public CompletionOptions CompletionProvider { get; set; } + + /// + /// Whether the server provides goto definition support. Can be null + /// + public bool? DefinitionProvider { get; set; } + + /// + /// Whether the server provides document formatting. Can be null + /// + public bool? DocumentFormattingProvider { get; set; } + + /// + /// Whether the server provides document highlight support. Can be null + /// + public bool? DocumentHighlightProvider { get; set; } + + /// + /// Options the server supports for document linking. Can be null to indicate the + /// feature is not supported + /// + public DocumentLinkOptions DocumentLinkProvider { get; set; } + + /// + /// Options that the server supports for document formatting on type. Can be null to + /// indicate the feature is not supported + /// + public DocumentOnTypeFormattingOptions DocumentOnTypeFormattingProvider { get; set; } + + /// + /// Whether the server provides document symbol support. Can be null + /// + public bool? DocumentSymbolProvider { get; set; } + + /// + /// Options the server supports for executing commands. Can be null to indicate the + /// feature is not supported. + /// + public ExecuteCommandOptions ExecuteCommandProvider { get; set; } + + /// + /// Any experimental features the server supports + /// + /// TODO: Should this be a parameterized type? + public object Experimental { get; set; } + + /// + /// Whether or not the server supports goto implementation requests. Can be null + /// + /// TODO: Union type + public bool? ImplementationProvider { get; set; } + + /// + /// Whether the server provides hover support. Can be null + /// + public bool? HoverProvider { get; set; } + + /// + /// Whether the server provides find references support. Can be null + /// + public bool? ReferencesProvider { get; set; } + + /// + /// Whether the server provides support for renaming. Can be null + /// + public bool? RenameProvider { get; set; } + + /// + /// Options that the server supports for signature help. Can be null to indicate + /// completion is not supported + /// + public SignatureHelpOptions SignatureHelpProvider { get; set; } + + /// + /// Whether the server provides goto type definition support. Can be null + /// + /// TODO: Union type + public bool? TypeDefinitionProvider { get; set; } + + /// + /// Options specific to workspaces the server supoorts. Can be null to indicate the + /// server does not support workspace requests. + /// + public WorkspaceCapabilities Workspace { get; set; } + + /// + /// Whether the server provides workpace symbol support. Can be null + /// + public bool? WorkspaceSymbolProvider { get; set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/ServerCapabilities/SignatureHelpOptions.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/ServerCapabilities/SignatureHelpOptions.cs new file mode 100644 index 00000000..b4dab960 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/ServerCapabilities/SignatureHelpOptions.cs @@ -0,0 +1,18 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.DataProtocol.Contracts.ServerCapabilities +{ + /// + /// Defines options for signature help that the server supports + /// + public class SignatureHelpOptions + { + /// + /// Characters that trigger signature help automatically + /// + public string[] TriggerCharacters { get; set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/ServerCapabilities/TextDocument.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/ServerCapabilities/TextDocument.cs new file mode 100644 index 00000000..91a34ce4 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/ServerCapabilities/TextDocument.cs @@ -0,0 +1,76 @@ +// +// 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.DataProtocol.Contracts.Utilities; + +namespace Microsoft.SqlTools.DataProtocol.Contracts.ServerCapabilities +{ + public enum TextDocumentSyncKind + { + None = 0, + Full = 1, + Incremental = 2 + } + + /// + /// Defines options for sae notifications + /// + public class TextDocumentSaveOptions + { + /// + /// Whether the client should send the content of the file being saved with the save notification + /// + public bool? IncludeText { get; set; } + } + + public class TextDocumentSync : Union + { + public static TextDocumentSync FromTextDocumentSyncKind(TextDocumentSyncKind value) + { + return new TextDocumentSync + { + value1 = null, + value2 = value + }; + } + + public static TextDocumentSync FromTextDocumentSyncOptions(TextDocumentSyncOptions value) + { + return new TextDocumentSync + { + value1 = value, + value2 = null + }; + } + } + + public class TextDocumentSyncOptions + { + /// + /// What kind of change notifications are sent to the server + /// + public TextDocumentSyncKind? Change { get; set; } + + /// + /// Whether open and close notifications are sent to the server + /// + public bool? OpenClose { get; set; } + + /// + /// Options for save notifications + /// + public TextDocumentSaveOptions SaveOptions { get; set; } + + /// + /// Whether notifications indicating the client will save are sent to the server + /// + public bool? WillSave { get; set; } + + /// + /// Whether requests should be sent to the server when the client is about to save + /// + public bool? WillSaveWaitUntil { get; set; } + } +} diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/ServerCapabilities/Workspace.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/ServerCapabilities/Workspace.cs new file mode 100644 index 00000000..db03e433 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/ServerCapabilities/Workspace.cs @@ -0,0 +1,118 @@ +// +// 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 Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace Microsoft.SqlTools.DataProtocol.Contracts.ServerCapabilities +{ + public class WorkspaceCapabilities + { + /// + /// Options specific to workspace folders the server supports + /// + public WorkspaceFolderCapabilities WorkspaceFolders { get; set; } + } + + public class WorkspaceFolderCapabilities + { + /// + /// Whether or not the server supports multiple workspace folders + /// + public bool? Supported { get; set; } + + /// + /// Whether the server wants to receive workspace folder change notifications + /// + /// + /// If a string is provided, the string is treated as an ID under which the notification is + /// registered on the client side. The ID can be used to unregister for these events using + /// the client/unregisterCapability request + /// + public WorkspaceChangeNotification ChangeNotifications { get; set; } + } + + [JsonConverter(typeof(WorkspaceChangeNotificationJsonConverter))] + public class WorkspaceChangeNotification + { + public bool BooleanValue { get; } + + public string UnregisterId { get; } + + private WorkspaceChangeNotification(bool booleanValue, string unregisterId) + { + BooleanValue = booleanValue; + UnregisterId = unregisterId; + } + + /// + /// Indicates that this server can accept notifications that the workspace has changed + /// + public static WorkspaceChangeNotification True => new WorkspaceChangeNotification(true, null); + + /// + /// Indicates that this server cannot accept notifications that the workspace has changed + /// + public static WorkspaceChangeNotification False => new WorkspaceChangeNotification(false, null); + + /// + /// Indicates that this server can accept notifications that the workspace has changed but + /// reserves the right to unsubscribe from receiving workspace change notifications + /// + /// ID to use when unregistering for workspace change notifications + public static WorkspaceChangeNotification WithId(string unregisterId) + { + return unregisterId == null ? null : new WorkspaceChangeNotification(true, unregisterId); + } + } + + internal class WorkspaceChangeNotificationJsonConverter : JsonConverter + { + public override bool CanRead => true; + public override bool CanWrite => true; + + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + if (value == null) + { + writer.WriteNull(); + return; + } + + WorkspaceChangeNotification castValue = (WorkspaceChangeNotification) value; + if (castValue.UnregisterId != null) + { + writer.WriteValue(castValue.UnregisterId); + } + else + { + writer.WriteValue(castValue.BooleanValue); + } + } + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + JToken jToken = JToken.Load(reader); + if (jToken.Type == JTokenType.Null) + { + return null; + } + if (jToken.Type == JTokenType.Boolean) + { + return jToken.Value() + ? WorkspaceChangeNotification.True + : WorkspaceChangeNotification.False; + } + + return WorkspaceChangeNotification.WithId(jToken.Value()); + } + + public override bool CanConvert(Type objectType) + { + return objectType == typeof(WorkspaceChangeNotificationJsonConverter); + } + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/Utilities/FlagsIntConverter.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/Utilities/FlagsIntConverter.cs new file mode 100644 index 00000000..32bede37 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/Utilities/FlagsIntConverter.cs @@ -0,0 +1,87 @@ +// +// 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.Linq; +using System.Reflection; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace Microsoft.SqlTools.DataProtocol.Contracts.Utilities +{ + internal class FlagsIntConverter : JsonConverter + { + public override bool CanWrite => true; + public override bool CanRead => true; + + #region Public Methods + + public override bool CanConvert(Type objectType) + { + return objectType.IsEnum && objectType.GetCustomAttribute(typeof(FlagsAttribute)) != null; + } + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + // TODO: Fix to handle nullables properly + + int[] values = JArray.Load(reader).Values().ToArray(); + + FieldInfo[] enumFields = objectType.GetFields(BindingFlags.Public | BindingFlags.Static); + int setFlags = 0; + foreach (FieldInfo enumField in enumFields) + { + int enumValue = (int) enumField.GetValue(null); + + // If there is a serialize value set for the enum value, look for that instead of the int value + SerializeValueAttribute serializeValue = enumField.GetCustomAttribute(); + int searchValue = serializeValue?.Value ?? enumValue; + if (Array.IndexOf(values, searchValue) >= 0) + { + setFlags |= enumValue; + } + } + + return Enum.ToObject(objectType, setFlags); + } + + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + FieldInfo[] enumFields = value.GetType().GetFields(BindingFlags.Public | BindingFlags.Static); + List setFlags = new List(); + foreach (FieldInfo enumField in enumFields) + { + // Make sure the flag is set before doing expensive reflection + int enumValue = (int)enumField.GetValue(null); + if (((int) value & enumValue) == 0) + { + continue; + } + + // If there is a serialize value set for the member, use that instead of the int value + SerializeValueAttribute serializeValue = enumField.GetCustomAttribute(); + int flagValue = serializeValue?.Value ?? enumValue; + setFlags.Add(flagValue); + } + + string joinedFlags = string.Join(", ", setFlags); + writer.WriteRawValue($"[{joinedFlags}]"); + } + + #endregion + + [AttributeUsage(AttributeTargets.Field)] + internal class SerializeValueAttribute : Attribute + { + public int Value { get; } + + public SerializeValueAttribute(int value) + { + Value = value; + } + } + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/Utilities/FlagsStringConverter.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/Utilities/FlagsStringConverter.cs new file mode 100644 index 00000000..d91501c8 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/Utilities/FlagsStringConverter.cs @@ -0,0 +1,102 @@ +// +// 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.Linq; +using System.Reflection; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using Newtonsoft.Json.Serialization; + +namespace Microsoft.SqlTools.DataProtocol.Contracts.Utilities +{ + internal class FlagsStringConverter : JsonConverter + { + public override bool CanWrite => true; + public override bool CanRead => true; + + #region Public Methods + + public override bool CanConvert(Type objectType) + { + return objectType.IsEnum && objectType.GetCustomAttribute(typeof(FlagsAttribute)) != null; + } + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + // TODO: Fix to handle nullables properly + + JToken jToken = JToken.Load(reader); + if (jToken.Type == JTokenType.Null) + { + return null; + } + + string[] values = ((JArray) jToken).Values().ToArray(); + + FieldInfo[] enumFields = objectType.GetFields(BindingFlags.Public | BindingFlags.Static); + int setFlags = 0; + foreach (FieldInfo enumField in enumFields) + { + // If there is a serialize value set for the enum value, look for the instead of the int value + SerializeValueAttribute serializeValue = enumField.GetCustomAttribute(); + string searchValue = serializeValue?.Value ?? enumField.Name; + if (serializer.ContractResolver is CamelCasePropertyNamesContractResolver) + { + searchValue = char.ToLowerInvariant(searchValue[0]) + searchValue.Substring(1); + } + + // If the value is in the json array, or the int value into the flags + if (Array.IndexOf(values, searchValue) >= 0) + { + setFlags |= (int) enumField.GetValue(null); + } + } + + return Enum.ToObject(objectType, setFlags); + } + + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + FieldInfo[] enumFields = value.GetType().GetFields(BindingFlags.Public | BindingFlags.Static); + List setFlags = new List(); + foreach (FieldInfo enumField in enumFields) + { + // Make sure the flag is set before doing any other work + int enumValue = (int) enumField.GetValue(null); + if (((int) value & enumValue) == 0) + { + continue; + } + + // If there is a serialize value set for the member, use that instead of the int value + SerializeValueAttribute serializeValue = enumField.GetCustomAttribute(); + string flagValue = serializeValue?.Value ?? enumField.Name; + if (serializer.ContractResolver is CamelCasePropertyNamesContractResolver) + { + flagValue = char.ToLowerInvariant(flagValue[0]) + flagValue.Substring(1); + } + setFlags.Add($"\"{flagValue}\""); + } + + string joinedFlags = string.Join(", ", setFlags); + writer.WriteRawValue($"[{joinedFlags}]"); + } + + #endregion + + [AttributeUsage(AttributeTargets.Field)] + internal class SerializeValueAttribute : Attribute + { + public string Value { get; } + + public SerializeValueAttribute(string value) + { + Value = value; + } + } + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/Utilities/Union.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/Utilities/Union.cs new file mode 100644 index 00000000..c5092afc --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/Utilities/Union.cs @@ -0,0 +1,103 @@ +// +// 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 Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace Microsoft.SqlTools.DataProtocol.Contracts.Utilities +{ + internal interface IUnion + { + object Value { get; set; } + } + + [JsonConverter(typeof(UnionJsonSerializer))] + public class Union : IUnion + { + protected T1 value1; + protected T2 value2; + + internal Union() {} + + public object Value + { + get => (object) value1 ?? value2; + set + { + if (value == null) + { + throw new ArgumentException(); + } + + if (value is T1) + { + value1 = (T1) value; + } + else if (value is T2) + { + value2 = (T2) value; + } + else + { + throw new InvalidOperationException(); + } + } + } + } + + public class UnionJsonSerializer : JsonConverter + { + public override bool CanRead => true; + public override bool CanWrite => true; + + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + writer.WriteValue(((IUnion)value).Value); + } + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + // Check for null first + JToken jToken = JToken.Load(reader); + if (jToken.Type == JTokenType.Null) + { + return null; + } + + // Cast to an object + JObject jObject = (JObject)jToken; + + // Try to convert to + object value = null; + foreach (Type t in objectType.GenericTypeArguments) + { + try + { + value = jObject.ToObject(t); + break; + } + catch (Exception) + { + // Ignore any failure to cast, we'll throw if we exhaust all the conversion options + } + } + + if (value == null) + { + throw new InvalidCastException(); + } + + IUnion result = (IUnion)Activator.CreateInstance(objectType); + result.Value = value; + return result; + } + + public override bool CanConvert(Type objectType) + { + return objectType.IsAssignableFrom(typeof(IUnion)); + } + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/Workspace/Configuration.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/Workspace/Configuration.cs new file mode 100644 index 00000000..432eb651 --- /dev/null +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/Workspace/Configuration.cs @@ -0,0 +1,21 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using Microsoft.SqlTools.Hosting.Contracts; + +namespace Microsoft.SqlTools.DataProtocol.Contracts.Workspace +{ + public class DidChangeConfigurationNotification + { + public static readonly + EventType> Type = + EventType>.Create("workspace/didChangeConfiguration"); + } + + public class DidChangeConfigurationParams + { + public TConfig Settings { get; set; } + } +} diff --git a/src/Microsoft.SqlTools.Hosting.Contracts/EventType.cs b/src/Microsoft.SqlTools.Hosting.Contracts/EventType.cs new file mode 100644 index 00000000..e65b79bd --- /dev/null +++ b/src/Microsoft.SqlTools.Hosting.Contracts/EventType.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. +// + +namespace Microsoft.SqlTools.Hosting.Contracts +{ + /// + /// Defines an event type with a particular method name. + /// + /// The parameter type for this event. + public class EventType + { + /// + /// Gets the method name for the event type. + /// + public string MethodName { get; private set; } + + /// + /// Creates an EventType instance with the given parameter type and method name. + /// + /// The method name of the event. + /// A new EventType instance for the defined type. + public static EventType Create(string methodName) + { + return new EventType() + { + MethodName = methodName + }; + } + } +} + diff --git a/src/Microsoft.SqlTools.Hosting.Contracts/Internal/Error.cs b/src/Microsoft.SqlTools.Hosting.Contracts/Internal/Error.cs new file mode 100644 index 00000000..dec62449 --- /dev/null +++ b/src/Microsoft.SqlTools.Hosting.Contracts/Internal/Error.cs @@ -0,0 +1,23 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.Hosting.Contracts.Internal +{ + /// + /// Defines the message contract for errors returned via + /// + public class Error + { + /// + /// Error code. If omitted will default to 0 + /// + public int Code { get; set; } + + /// + /// Error message + /// + public string Message { get; set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.Hosting.Contracts/Internal/ExitNotification.cs b/src/Microsoft.SqlTools.Hosting.Contracts/Internal/ExitNotification.cs new file mode 100644 index 00000000..2638e2dc --- /dev/null +++ b/src/Microsoft.SqlTools.Hosting.Contracts/Internal/ExitNotification.cs @@ -0,0 +1,16 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.Hosting.Contracts.Internal +{ + /// + /// Defines an event that is sent from the client to notify that + /// the client is exiting and the server should as well. + /// + public class ExitNotification + { + public static readonly EventType Type = EventType.Create("exit"); + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.Hosting.Contracts/Internal/HostingErrorNotification.cs b/src/Microsoft.SqlTools.Hosting.Contracts/Internal/HostingErrorNotification.cs new file mode 100644 index 00000000..bb929b69 --- /dev/null +++ b/src/Microsoft.SqlTools.Hosting.Contracts/Internal/HostingErrorNotification.cs @@ -0,0 +1,26 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.Hosting.Contracts.Internal +{ + /// + /// Parameters to be used for reporting hosting-level errors, such as protocol violations + /// + public class HostingErrorParams + { + /// + /// The message of the error + /// + public string Message { get; set; } + } + + public class HostingErrorNotification + { + public static readonly + EventType Type = + EventType.Create("hosting/error"); + + } +} diff --git a/src/Microsoft.SqlTools.Hosting.Contracts/Internal/ShutdownRequest.cs b/src/Microsoft.SqlTools.Hosting.Contracts/Internal/ShutdownRequest.cs new file mode 100644 index 00000000..62ffef55 --- /dev/null +++ b/src/Microsoft.SqlTools.Hosting.Contracts/Internal/ShutdownRequest.cs @@ -0,0 +1,17 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.Hosting.Contracts.Internal +{ + /// + /// Defines a message that is sent from the client to request + /// that the server shut down. + /// + public class ShutdownRequest + { + public static readonly RequestType Type = RequestType.Create("shutdown"); + } +} + diff --git a/src/Microsoft.SqlTools.Hosting.Contracts/Microsoft.SqlTools.Hosting.Contracts.csproj b/src/Microsoft.SqlTools.Hosting.Contracts/Microsoft.SqlTools.Hosting.Contracts.csproj new file mode 100644 index 00000000..f2a43107 --- /dev/null +++ b/src/Microsoft.SqlTools.Hosting.Contracts/Microsoft.SqlTools.Hosting.Contracts.csproj @@ -0,0 +1,10 @@ + + + netstandard2.0 + + Defines the core messages needed for the Microsoft.SqlTools.Hosting service to communicate over the VSCode Language Server Protocol. + + $(PackageDescription) + + + \ No newline at end of file diff --git a/src/Microsoft.SqlTools.Hosting.Contracts/RequestType.cs b/src/Microsoft.SqlTools.Hosting.Contracts/RequestType.cs new file mode 100644 index 00000000..6821e906 --- /dev/null +++ b/src/Microsoft.SqlTools.Hosting.Contracts/RequestType.cs @@ -0,0 +1,24 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System.Diagnostics; + +namespace Microsoft.SqlTools.Hosting.Contracts +{ + [DebuggerDisplay("RequestType MethodName = {MethodName}")] + public class RequestType + { + public string MethodName { get; private set; } + + public static RequestType Create(string typeName) + { + return new RequestType() + { + MethodName = typeName + }; + } + } +} + diff --git a/src/Microsoft.SqlTools.Hosting.v2/Channels/ChannelBase.cs b/src/Microsoft.SqlTools.Hosting.v2/Channels/ChannelBase.cs new file mode 100644 index 00000000..9e80b4df --- /dev/null +++ b/src/Microsoft.SqlTools.Hosting.v2/Channels/ChannelBase.cs @@ -0,0 +1,58 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System.Threading.Tasks; +using Microsoft.SqlTools.Hosting.Protocol; + +namespace Microsoft.SqlTools.Hosting.Channels +{ + /// + /// Defines a base implementation for servers and their clients over a + /// single kind of communication channel. + /// + public abstract class ChannelBase + { + #region Properties + + /// + /// Gets a boolean that is true if the channel is connected or false if not. + /// + public bool IsConnected { get; protected internal set; } + + /// + /// Gets the MessageReader for reading messages from the channel. + /// + public MessageReader MessageReader { get; protected internal set; } + + /// + /// Gets the MessageWriter for writing messages to the channel. + /// + public MessageWriter MessageWriter { get; protected internal set; } + + #endregion + + #region Abstract Methods + + /// + /// Starts the channel and initializes the MessageDispatcher. + /// + public abstract void Start(); + + /// + /// Stops the channel. + /// + public abstract void Stop(); + + /// + /// Returns a Task that allows the consumer of the ChannelBase + /// implementation to wait until a connection has been made to + /// the opposite endpoint whether it's a client or server. + /// + /// A Task to be awaited until a connection is made. + public abstract Task WaitForConnection(); + + #endregion + } +} diff --git a/src/Microsoft.SqlTools.Hosting.v2/Channels/StdioClientChannel.cs b/src/Microsoft.SqlTools.Hosting.v2/Channels/StdioClientChannel.cs new file mode 100644 index 00000000..f1752cc0 --- /dev/null +++ b/src/Microsoft.SqlTools.Hosting.v2/Channels/StdioClientChannel.cs @@ -0,0 +1,111 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System.Diagnostics; +using System.IO; +using System.Text; +using System.Threading.Tasks; +using Microsoft.SqlTools.Hosting.Protocol; + +namespace Microsoft.SqlTools.Hosting.Channels +{ + /// + /// Provides a client implementation for the standard I/O channel. + /// Launches the server process and then attaches to its console + /// streams. + /// + public class StdioClientChannel : ChannelBase + { + private readonly string serviceProcessPath; + private readonly string serviceProcessArguments; + + private Stream inputStream; + private Stream outputStream; + private Process serviceProcess; + + /// + /// Initializes an instance of the StdioClient. + /// + /// The full path to the server process executable. + /// Optional arguments to pass to the service process executable. + public StdioClientChannel(string serverProcessPath, params string[] serverProcessArguments) + { + serviceProcessPath = serverProcessPath; + + if (serverProcessArguments != null) + { + serviceProcessArguments = string.Join(" ", serverProcessArguments); + } + } + + public int ProcessId { get; private set; } + + public override void Start() + { + serviceProcess = new Process + { + StartInfo = new ProcessStartInfo + { + FileName = serviceProcessPath, + Arguments = serviceProcessArguments, + CreateNoWindow = true, + UseShellExecute = false, + RedirectStandardInput = true, + RedirectStandardOutput = true, + RedirectStandardError = true, + StandardOutputEncoding = Encoding.UTF8 + }, + EnableRaisingEvents = true + }; + + // Start the process + serviceProcess.Start(); + ProcessId = serviceProcess.Id; + + // Open the standard input/output streams + inputStream = serviceProcess.StandardOutput.BaseStream; + outputStream = serviceProcess.StandardInput.BaseStream; + + // Set up the message reader and writer + MessageReader = new MessageReader(inputStream); + MessageWriter = new MessageWriter(outputStream); + + IsConnected = true; + } + + public override Task WaitForConnection() + { + // We're always connected immediately in the stdio channel + return Task.FromResult(true); + } + + public override void Stop() + { + if (inputStream != null) + { + inputStream.Dispose(); + inputStream = null; + } + + if (outputStream != null) + { + outputStream.Dispose(); + outputStream = null; + } + + if (MessageReader != null) + { + MessageReader = null; + } + + if (MessageWriter != null) + { + MessageWriter = null; + } + + serviceProcess.Kill(); + } + } +} diff --git a/src/Microsoft.SqlTools.Hosting.v2/Channels/StdioServerChannel.cs b/src/Microsoft.SqlTools.Hosting.v2/Channels/StdioServerChannel.cs new file mode 100644 index 00000000..c2ecb695 --- /dev/null +++ b/src/Microsoft.SqlTools.Hosting.v2/Channels/StdioServerChannel.cs @@ -0,0 +1,54 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System.IO; +using System.Text; +using System.Threading.Tasks; +using Microsoft.SqlTools.Hosting.Protocol; + +namespace Microsoft.SqlTools.Hosting.Channels +{ + /// + /// Provides a server implementation for the standard I/O channel. + /// When started in a process, attaches to the console I/O streams + /// to communicate with the client that launched the process. + /// + public class StdioServerChannel : ChannelBase + { + private Stream inputStream; + private Stream outputStream; + + public override void Start() + { +#if !NanoServer + // Ensure that the console is using UTF-8 encoding + System.Console.InputEncoding = Encoding.UTF8; + System.Console.OutputEncoding = Encoding.UTF8; +#endif + + // Open the standard input/output streams + inputStream = System.Console.OpenStandardInput(); + outputStream = System.Console.OpenStandardOutput(); + + // Set up the reader and writer + MessageReader = new MessageReader(inputStream); + MessageWriter = new MessageWriter(outputStream); + + IsConnected = true; + } + + public override void Stop() + { + // No default implementation needed, streams will be + // disposed on process shutdown. + } + + public override Task WaitForConnection() + { + // We're always connected immediately in the stdio channel + return Task.FromResult(true); + } + } +} diff --git a/src/Microsoft.SqlTools.Hosting.v2/Extensibility/ExportStandardMetadataAttribute.cs b/src/Microsoft.SqlTools.Hosting.v2/Extensibility/ExportStandardMetadataAttribute.cs new file mode 100644 index 00000000..35f3f796 --- /dev/null +++ b/src/Microsoft.SqlTools.Hosting.v2/Extensibility/ExportStandardMetadataAttribute.cs @@ -0,0 +1,44 @@ +// +// 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.Composition; + +namespace Microsoft.SqlTools.Hosting.Extensibility +{ + /// + /// Base attribute class for all export definitions. + /// + [MetadataAttribute] + [AttributeUsage(AttributeTargets.Class)] + public abstract class ExportStandardMetadataAttribute : ExportAttribute, IStandardMetadata + { + /// + /// Base class for DAC extensibility exports + /// + protected ExportStandardMetadataAttribute(Type contractType, string id, string displayName = null) + : base(contractType) + { + Id = id; + DisplayName = displayName; + } + + + /// + /// The version of this extension + /// + public string Version { get; set; } + + /// + /// The id of the extension + /// + public string Id { get; } + + /// + /// The display name for the extension + /// + public virtual string DisplayName { get; } + } +} diff --git a/src/Microsoft.SqlTools.Hosting.v2/Extensibility/ExtensionServiceProvider.cs b/src/Microsoft.SqlTools.Hosting.v2/Extensibility/ExtensionServiceProvider.cs new file mode 100644 index 00000000..2fd89909 --- /dev/null +++ b/src/Microsoft.SqlTools.Hosting.v2/Extensibility/ExtensionServiceProvider.cs @@ -0,0 +1,154 @@ +// +// 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; +using System.Collections.Generic; +using System.Composition.Convention; +using System.Composition.Hosting; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Runtime.Loader; +using Microsoft.SqlTools.Hosting.Utility; + +namespace Microsoft.SqlTools.Hosting.Extensibility +{ + /// + /// A MEF-based service provider. Supports any MEF-based configuration but is optimized for + /// service discovery over a set of DLLs in an application scope. Any service registering using + /// the [Export(IServiceContract)] attribute will be discovered and used by this service + /// provider if it's in the set of Assemblies / Types specified during its construction. Manual + /// override of this is supported by calling + /// and similar methods, since + /// this will initialize that service contract and avoid the MEF-based search and discovery + /// process. This allows the service provider to link into existing singleton / known services + /// while using MEF-based dependency injection and inversion of control for most of the code. + /// + public class ExtensionServiceProvider : RegisteredServiceProvider + { + private readonly Func config; + + public ExtensionServiceProvider(Func config) + { + Validate.IsNotNull(nameof(config), config); + this.config = config; + } + + /// + /// Creates a service provider by loading a set of named assemblies, expected to be + /// + /// Directory to search for included assemblies + /// full DLL names, case insensitive, of assemblies to include + /// instance + public static ExtensionServiceProvider CreateFromAssembliesInDirectory(string directory, IList inclusionList) + { + //AssemblyLoadContext context = new AssemblyLoader(directory); + var assemblyPaths = Directory.GetFiles(directory, "*.dll", SearchOption.TopDirectoryOnly); + + List assemblies = new List(); + foreach (var path in assemblyPaths) + { + // skip DLL files not in inclusion list + bool isInList = false; + foreach (var item in inclusionList) + { + if (path.EndsWith(item, StringComparison.OrdinalIgnoreCase)) + { + isInList = true; + break; + } + } + + if (!isInList) + { + continue; + } + + try + { + assemblies.Add(AssemblyLoadContext.Default.LoadFromAssemblyPath(path)); + } + catch (Exception) + { + // we expect exceptions trying to scan all DLLs since directory contains native libraries + } + } + + return Create(assemblies); + } + + public static ExtensionServiceProvider Create(IEnumerable assemblies) + { + Validate.IsNotNull(nameof(assemblies), assemblies); + return new ExtensionServiceProvider(conventions => new ContainerConfiguration().WithAssemblies(assemblies, conventions)); + } + + public static ExtensionServiceProvider Create(IEnumerable types) + { + Validate.IsNotNull(nameof(types), types); + return new ExtensionServiceProvider(conventions => new ContainerConfiguration().WithParts(types, conventions)); + } + + protected override IEnumerable GetServicesImpl() + { + EnsureExtensionStoreRegistered(); + return base.GetServicesImpl(); + } + + private void EnsureExtensionStoreRegistered() + { + if (!services.ContainsKey(typeof(T))) + { + ExtensionStore store = new ExtensionStore(typeof(T), config); + Register(() => store.GetExports()); + } + } + } + + /// + /// A store for MEF exports of a specific type. Provides basic wrapper functionality around MEF to standarize how + /// we lookup types and return to callers. + /// + public class ExtensionStore + { + private readonly CompositionHost host; + private IList exports; + private readonly Type contractType; + + /// + /// Initializes the store with a type to lookup exports of, and a function that configures the + /// lookup parameters. + /// + /// Type to use as a base for all extensions being looked up + /// Function that returns the configuration to be used + public ExtensionStore(Type contractType, Func configure) + { + Validate.IsNotNull(nameof(contractType), contractType); + Validate.IsNotNull(nameof(configure), configure); + this.contractType = contractType; + ConventionBuilder builder = GetExportBuilder(); + ContainerConfiguration config = configure(builder); + host = config.CreateContainer(); + } + + public IEnumerable GetExports() + { + if (exports == null) + { + exports = host.GetExports(contractType).ToList(); + } + return exports.Cast(); + } + + private ConventionBuilder GetExportBuilder() + { + // Define exports as matching a parent type, export as that parent type + var builder = new ConventionBuilder(); + builder.ForTypesDerivedFrom(contractType).Export(exportConventionBuilder => exportConventionBuilder.AsContractType(contractType)); + return builder; + } + } +} diff --git a/src/Microsoft.SqlTools.Hosting.v2/Extensibility/IComposableService.cs b/src/Microsoft.SqlTools.Hosting.v2/Extensibility/IComposableService.cs new file mode 100644 index 00000000..64cbe76d --- /dev/null +++ b/src/Microsoft.SqlTools.Hosting.v2/Extensibility/IComposableService.cs @@ -0,0 +1,21 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.Hosting.Extensibility +{ + /// + /// A Service that expects to lookup other services. Using this interface on an exported service + /// will ensure the method is called during + /// service initialization + /// + public interface IComposableService + { + /// + /// Supports settings the service provider being used to initialize the service. + /// This is useful to look up other services and use them in your own service. + /// + void SetServiceProvider(IMultiServiceProvider provider); + } +} diff --git a/src/Microsoft.SqlTools.Hosting.v2/Extensibility/IHostedService.cs b/src/Microsoft.SqlTools.Hosting.v2/Extensibility/IHostedService.cs new file mode 100644 index 00000000..0d02b754 --- /dev/null +++ b/src/Microsoft.SqlTools.Hosting.v2/Extensibility/IHostedService.cs @@ -0,0 +1,106 @@ +// +// 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.Threading.Tasks; +using Microsoft.SqlTools.Hosting.Protocol; +using Microsoft.SqlTools.Hosting.Utility; + +namespace Microsoft.SqlTools.Hosting.Extensibility +{ + /// + /// Defines a hosted service that communicates with external processes via + /// messages passed over the . The service defines + /// a standard initialization method where it can hook up to the host. + /// + public interface IHostedService + { + /// + /// Callback to initialize this service + /// + /// which supports registering + /// event handlers and other callbacks for messages passed to external callers + void InitializeService(IServiceHost serviceHost); + + /// + /// What is the service type that you wish to register? + /// + Type ServiceType { get; } + } + + /// + /// Base class for implementations that handles defining the + /// being registered. This simplifies service registration. This also implements which + /// allows injection of the service provider for lookup of other services. + /// + /// Extending classes should implement per below code example + /// + /// [Export(typeof(IHostedService)] + /// MyService : HostedService<MyService> + /// { + /// public override void InitializeService(IServiceHost serviceHost) + /// { + /// serviceHost.SetRequestHandler(MyRequest.Type, HandleMyRequest); + /// } + /// } + /// + /// + /// Type to be registered for lookup in the service provider + public abstract class HostedService : IHostedService, IComposableService + { + protected IMultiServiceProvider ServiceProvider { get; private set; } + + public virtual void SetServiceProvider(IMultiServiceProvider provider) + { + ServiceProvider = provider; + } + + public Type ServiceType => typeof(T); + + protected async Task HandleRequestAsync( + Func> handler, + RequestContext requestContext, + string requestType) + { + Logger.Instance.Write(LogLevel.Verbose, requestType); + + try + { + THandler result = await handler(); + requestContext.SendResult(result); + return result; + } + catch (Exception ex) + { + requestContext.SendError(ex.ToString()); + } + return default(THandler); + } + protected async Task HandleSyncRequestAsAsync( + Func handler, + RequestContext requestContext, + string requestType) + { + Logger.Instance.Write(LogLevel.Verbose, requestType); + return await Task.Factory.StartNew(() => { + try + { + THandler result = handler(); + requestContext.SendResult(result); + return result; + } + catch (Exception ex) + { + requestContext.SendError(ex.ToString()); + } + return default(THandler); + }); + } + + + public abstract void InitializeService(IServiceHost serviceHost); + + } +} diff --git a/src/Microsoft.SqlTools.Hosting.v2/Extensibility/IMultiServiceProvider.cs b/src/Microsoft.SqlTools.Hosting.v2/Extensibility/IMultiServiceProvider.cs new file mode 100644 index 00000000..edac7cac --- /dev/null +++ b/src/Microsoft.SqlTools.Hosting.v2/Extensibility/IMultiServiceProvider.cs @@ -0,0 +1,101 @@ +// +// 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.Linq; +using Microsoft.SqlTools.Hosting.Utility; + +namespace Microsoft.SqlTools.Hosting.Extensibility +{ + public interface IMultiServiceProvider + { + /// + /// Gets a service of a specific type. It is expected that only 1 instance of this type will be + /// available + /// + /// Type of service to be found + /// Instance of T or null if not found + /// The input sequence contains more than one element.-or-The input sequence is empty. + T GetService(); + + /// + /// Gets a service of a specific type. The first service matching the specified filter will be returned + /// available + /// + /// Type of service to be found + /// Filter to use in + /// Instance of T or null if not found + /// The input sequence contains more than one element.-or-The input sequence is empty. + T GetService(Predicate filter); + + /// + /// Gets multiple services of a given type + /// + /// + /// An enumerable of matching services + IEnumerable GetServices(); + + /// + /// Gets multiple services of a given type, where they match a filter + /// + /// + /// + /// + IEnumerable GetServices(Predicate filter); + } + + + public abstract class ServiceProviderBase : IMultiServiceProvider + { + + public T GetService() + { + return GetServices().SingleOrDefault(); + } + + public T GetService(Predicate filter) + { + Validate.IsNotNull(nameof(filter), filter); + return GetServices().SingleOrDefault(t => filter(t)); + } + + public IEnumerable GetServices(Predicate filter) + { + Validate.IsNotNull(nameof(filter), filter); + return GetServices().Where(t => filter(t)); + } + + public virtual IEnumerable GetServices() + { + var services = GetServicesImpl(); + if (services == null) + { + return Enumerable.Empty(); + } + + return services.Select(t => + { + InitComposableService(t); + return t; + }); + } + + private void InitComposableService(T t) + { + IComposableService c = t as IComposableService; + c?.SetServiceProvider(this); + } + + /// + /// Gets all services using the build in implementation + /// + /// + /// + protected abstract IEnumerable GetServicesImpl(); + + } + +} diff --git a/src/Microsoft.SqlTools.Hosting.v2/Extensibility/IStandardMetadata.cs b/src/Microsoft.SqlTools.Hosting.v2/Extensibility/IStandardMetadata.cs new file mode 100644 index 00000000..2357651d --- /dev/null +++ b/src/Microsoft.SqlTools.Hosting.v2/Extensibility/IStandardMetadata.cs @@ -0,0 +1,28 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.Hosting.Extensibility +{ + /// + /// Standard Metadata needed for extensions. + /// + public interface IStandardMetadata + { + /// + /// Extension version. Should be in the format "1.0.0.0" or similar + /// + string Version { get; } + + /// + /// Unique Id used to identify the export. + /// + string Id { get; } + + /// + /// Optional Display name describing the export type + /// + string DisplayName { get; } + } +} diff --git a/src/Microsoft.SqlTools.Hosting.v2/Extensibility/RegisteredServiceProvider.cs b/src/Microsoft.SqlTools.Hosting.v2/Extensibility/RegisteredServiceProvider.cs new file mode 100644 index 00000000..322f0a9f --- /dev/null +++ b/src/Microsoft.SqlTools.Hosting.v2/Extensibility/RegisteredServiceProvider.cs @@ -0,0 +1,120 @@ +// +// 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; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using Microsoft.SqlTools.Hosting.Utility; + +namespace Microsoft.SqlTools.Hosting.Extensibility +{ + + /// + /// A service provider implementation that allows registering of specific services + /// + public class RegisteredServiceProvider : ServiceProviderBase + { + public delegate IEnumerable ServiceLookup(); + + protected readonly Dictionary services = new Dictionary(); + + /// + /// Registers a singular service to be returned during lookup + /// + /// + /// this provider, to simplify fluent declarations + /// If service is null + /// If an existing service is already registered + public virtual RegisteredServiceProvider RegisterSingleService(T service) + { + Validate.IsNotNull(nameof(service), service); + ThrowIfAlreadyRegistered(); + services.Add(typeof(T), () => service.AsSingleItemEnumerable()); + return this; + } + + /// + /// Registers a singular service to be returned during lookup + /// + /// + /// Type or interface this service should be registed as. Any request + /// for that type will return this service + /// + /// service object to be added + /// this provider, to simplify fluent declarations + /// If service is null + /// If an existing service is already registered + public virtual RegisteredServiceProvider RegisterSingleService(Type type, object service) + { + Validate.IsNotNull(nameof(type), type); + Validate.IsNotNull(nameof(service), service); + ThrowIfAlreadyRegistered(type); + ThrowIfIncompatible(type, service); + services.Add(type, service.AsSingleItemEnumerable); + return this; + } + + /// + /// Registers a function that can look up multiple services + /// + /// + /// this provider, to simplify fluent declarations + /// If is null + /// If an existing service is already registered + public virtual RegisteredServiceProvider Register(Func> serviceLookup) + { + Validate.IsNotNull(nameof(serviceLookup), serviceLookup); + ThrowIfAlreadyRegistered(); + services.Add(typeof(T), () => serviceLookup()); + return this; + } + + public virtual void RegisterHostedServices() + { + // Register all hosted services the service provider for their requested service type. + // This ensures that when searching for the ConnectionService (eg) you can get it + // without searching for an IHosted service of type ConnectionService + foreach (IHostedService service in GetServices()) + { + RegisterSingleService(service.ServiceType, service); + } + } + + private void ThrowIfAlreadyRegistered() + { + ThrowIfAlreadyRegistered(typeof(T)); + } + + private void ThrowIfAlreadyRegistered(Type type) + { + if (services.ContainsKey(type)) + { + throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, SR.ServiceAlreadyRegistered, type.Name)); + } + + } + + private void ThrowIfIncompatible(Type type, object service) + { + if (!type.IsInstanceOfType(service)) + { + throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, SR.ServiceNotOfExpectedType, service.GetType().Name, type.Name)); + } + + } + + protected override IEnumerable GetServicesImpl() + { + ServiceLookup serviceLookup; + if (services.TryGetValue(typeof(T), out serviceLookup)) + { + return serviceLookup().Cast(); + } + return Enumerable.Empty(); + } + } +} diff --git a/src/Microsoft.SqlTools.Hosting.v2/ExtensibleServiceHost.cs b/src/Microsoft.SqlTools.Hosting.v2/ExtensibleServiceHost.cs new file mode 100644 index 00000000..1affca48 --- /dev/null +++ b/src/Microsoft.SqlTools.Hosting.v2/ExtensibleServiceHost.cs @@ -0,0 +1,59 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System.Collections.Generic; +using Microsoft.SqlTools.Hosting.Channels; +using Microsoft.SqlTools.Hosting.Extensibility; +using Microsoft.SqlTools.Hosting.Utility; + +namespace Microsoft.SqlTools.Hosting +{ + public class ExtensibleServiceHost : ServiceHost + { + private readonly RegisteredServiceProvider serviceProvider; + + #region Construction + + public ExtensibleServiceHost(RegisteredServiceProvider provider, ChannelBase protocolChannel) + : base(protocolChannel) + { + Validate.IsNotNull(nameof(provider), provider); + + provider.RegisterSingleService(this); + provider.RegisterHostedServices(); + + // Initialize all hosted services + foreach (IHostedService service in provider.GetServices()) + { + service.InitializeService(this); + } + + serviceProvider = provider; + } + + /// + /// Constructs a new service host intended to be used as a JSON RPC server. StdIn is used + /// for receiving messages, StdOut is used for sending messages. Services will be + /// discovered from the assemblies in the current directory listed in + /// + /// + /// Directory to include assemblies from + /// + /// List of assembly names in the current directory to search for service exports + /// + /// Service host as a JSON RPC server over StdI/O + public static ExtensibleServiceHost CreateDefaultExtensibleServer(string directory, IList assembliesToInclude) + { + Validate.IsNotNull(nameof(assembliesToInclude), assembliesToInclude); + + ExtensionServiceProvider serviceProvider = ExtensionServiceProvider.CreateFromAssembliesInDirectory(directory, assembliesToInclude); + return new ExtensibleServiceHost(serviceProvider, new StdioServerChannel()); + } + + #endregion + + public IMultiServiceProvider ServiceProvider => serviceProvider; + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.Hosting.v2/IServiceHost.cs b/src/Microsoft.SqlTools.Hosting.v2/IServiceHost.cs new file mode 100644 index 00000000..e153f9d2 --- /dev/null +++ b/src/Microsoft.SqlTools.Hosting.v2/IServiceHost.cs @@ -0,0 +1,31 @@ +// +// 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.Threading.Tasks; +using Microsoft.SqlTools.DataProtocol.Contracts; +using Microsoft.SqlTools.Hosting.Protocol; + +namespace Microsoft.SqlTools.Hosting +{ + /// + /// Interface for service hosts. Inherits interface requirements for JSON RPC hosts + /// + public interface IServiceHost : IJsonRpcHost + { + /// + /// Registers a task to be executed when the initialize event is received + /// + /// Function to execute when the initialize event received + void RegisterInitializeTask(Func initializeCallback); + + /// + /// Registers a task to be executed when the shutdown event is received, before the channel + /// is closed + /// + /// Function to execute when the shutdown request is received + void RegisterShutdownTask(Func shutdownCallback); + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.Hosting.v2/Localization/sr.cs b/src/Microsoft.SqlTools.Hosting.v2/Localization/sr.cs new file mode 100755 index 00000000..7b7c4016 --- /dev/null +++ b/src/Microsoft.SqlTools.Hosting.v2/Localization/sr.cs @@ -0,0 +1,230 @@ +// WARNING: +// This file was generated by the Microsoft DataWarehouse String Resource Tool 1.37.0.0 +// from information in sr.strings +// DO NOT MODIFY THIS FILE'S CONTENTS, THEY WILL BE OVERWRITTEN +// +namespace Microsoft.SqlTools.Hosting +{ + using System; + using System.Reflection; + using System.Resources; + using System.Globalization; + + [System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class SR + { + protected SR() + { } + + public static CultureInfo Culture + { + get + { + return Keys.Culture; + } + set + { + Keys.Culture = value; + } + } + + + public static string ServiceAlreadyRegistered + { + get + { + return Keys.GetString(Keys.ServiceAlreadyRegistered); + } + } + + public static string MultipleServicesFound + { + get + { + return Keys.GetString(Keys.MultipleServicesFound); + } + } + + public static string IncompatibleServiceForExtensionLoader + { + get + { + return Keys.GetString(Keys.IncompatibleServiceForExtensionLoader); + } + } + + public static string ServiceProviderNotSet + { + get + { + return Keys.GetString(Keys.ServiceProviderNotSet); + } + } + + public static string ServiceNotFound + { + get + { + return Keys.GetString(Keys.ServiceNotFound); + } + } + + public static string ServiceNotOfExpectedType + { + get + { + return Keys.GetString(Keys.ServiceNotOfExpectedType); + } + } + + public static string HostingUnexpectedEndOfStream + { + get + { + return Keys.GetString(Keys.HostingUnexpectedEndOfStream); + } + } + + public static string HostingHeaderMissingColon + { + get + { + return Keys.GetString(Keys.HostingHeaderMissingColon); + } + } + + public static string HostingHeaderMissingContentLengthHeader + { + get + { + return Keys.GetString(Keys.HostingHeaderMissingContentLengthHeader); + } + } + + public static string HostingHeaderMissingContentLengthValue + { + get + { + return Keys.GetString(Keys.HostingHeaderMissingContentLengthValue); + } + } + + public static string HostingJsonRpcHostAlreadyStarted + { + get + { + return Keys.GetString(Keys.HostingJsonRpcHostAlreadyStarted); + } + } + + public static string HostingJsonRpcHostNotStarted + { + get + { + return Keys.GetString(Keys.HostingJsonRpcHostNotStarted); + } + } + + public static string HostingJsonRpcVersionMissing + { + get + { + return Keys.GetString(Keys.HostingJsonRpcVersionMissing); + } + } + + public static string HostingMessageMissingMethod + { + get + { + return Keys.GetString(Keys.HostingMessageMissingMethod); + } + } + + public static string HostingMethodHandlerDoesNotExist(string messageType, string method) + { + return Keys.GetString(Keys.HostingMethodHandlerDoesNotExist, messageType, method); + } + + [System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class Keys + { + static ResourceManager resourceManager = new ResourceManager("Microsoft.SqlTools.Hosting.Localization.SR", typeof(SR).GetTypeInfo().Assembly); + + static CultureInfo _culture = null; + + + public const string ServiceAlreadyRegistered = "ServiceAlreadyRegistered"; + + + public const string MultipleServicesFound = "MultipleServicesFound"; + + + public const string IncompatibleServiceForExtensionLoader = "IncompatibleServiceForExtensionLoader"; + + + public const string ServiceProviderNotSet = "ServiceProviderNotSet"; + + + public const string ServiceNotFound = "ServiceNotFound"; + + + public const string ServiceNotOfExpectedType = "ServiceNotOfExpectedType"; + + + public const string HostingUnexpectedEndOfStream = "HostingUnexpectedEndOfStream"; + + + public const string HostingHeaderMissingColon = "HostingHeaderMissingColon"; + + + public const string HostingHeaderMissingContentLengthHeader = "HostingHeaderMissingContentLengthHeader"; + + + public const string HostingHeaderMissingContentLengthValue = "HostingHeaderMissingContentLengthValue"; + + + public const string HostingJsonRpcHostAlreadyStarted = "HostingJsonRpcHostAlreadyStarted"; + + + public const string HostingJsonRpcHostNotStarted = "HostingJsonRpcHostNotStarted"; + + + public const string HostingJsonRpcVersionMissing = "HostingJsonRpcVersionMissing"; + + + public const string HostingMessageMissingMethod = "HostingMessageMissingMethod"; + + + public const string HostingMethodHandlerDoesNotExist = "HostingMethodHandlerDoesNotExist"; + + + private Keys() + { } + + public static CultureInfo Culture + { + get + { + return _culture; + } + set + { + _culture = value; + } + } + + public static string GetString(string key) + { + return resourceManager.GetString(key, _culture); + } + + + public static string GetString(string key, object arg0, object arg1) + { + return string.Format(global::System.Globalization.CultureInfo.CurrentCulture, resourceManager.GetString(key, _culture), arg0, arg1); + } + + } + } +} diff --git a/src/Microsoft.SqlTools.Hosting.v2/Localization/sr.resx b/src/Microsoft.SqlTools.Hosting.v2/Localization/sr.resx new file mode 100755 index 00000000..0fd90fdf --- /dev/null +++ b/src/Microsoft.SqlTools.Hosting.v2/Localization/sr.resx @@ -0,0 +1,181 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Cannot register service for type {0}, one or more services already registered + + + + Multiple services found for type {0}, expected only 1 + + + + Service of type {0} cannot be created by ExtensionLoader<{1}> + + + + SetServiceProvider() was not called to establish the required service provider + + + + Service {0} was not found in the service provider + + + + Service of Type {0} is not compatible with registered Type {1} + + + + MessageReader's input stream ended unexpectedly, terminating + + + + Message header must separate key and value using ':' + + + + Fatal error: Content-Length header must be provided + + + + Fatal error: Content-Length value is not an integer + + + + JSON RPC host has already started + + + + JSON RPC host has not started + + + + JSON RPC version parameter is missing or invalid + + + + JSON RPC message is missing required method parameter + + + + {0} handler for method '{1}' does not exist. + . + Parameters: 0 - messageType (string), 1 - method (string) + + diff --git a/src/Microsoft.SqlTools.Hosting.v2/Localization/sr.strings b/src/Microsoft.SqlTools.Hosting.v2/Localization/sr.strings new file mode 100644 index 00000000..7759e236 --- /dev/null +++ b/src/Microsoft.SqlTools.Hosting.v2/Localization/sr.strings @@ -0,0 +1,57 @@ +# String resource file +# +# When processed by the String Resource Tool, this file generates +# both a .CS and a .RESX file with the same name as the file. +# The .CS file contains a class which can be used to access these +# string resources, including the ability to format in +# parameters, which are identified with the .NET {x} format +# (see String.Format help). +# +# Comments below assume the file name is SR.strings. +# +# Lines starting with a semicolon ";" are also treated as comments, but +# in a future version they will be extracted and made available in LocStudio +# Put your comments to localizers _before_ the string they apply to. +# +# SMO build specific comment +# after generating the .resx file, run srgen on it and get the .resx file +# please remember to also check that .resx in, along with the +# .strings and .cs files + +[strings] + +############################################################################ +# Extensibility + +ServiceAlreadyRegistered = Cannot register service for type {0}, one or more services already registered + +MultipleServicesFound = Multiple services found for type {0}, expected only 1 + +IncompatibleServiceForExtensionLoader = Service of type {0} cannot be created by ExtensionLoader<{1}> + +ServiceProviderNotSet = SetServiceProvider() was not called to establish the required service provider + +ServiceNotFound = Service {0} was not found in the service provider + +ServiceNotOfExpectedType = Service of Type {0} is not compatible with registered Type {1} + +############################################################################ +# Hosting + +HostingUnexpectedEndOfStream = MessageReader's input stream ended unexpectedly, terminating + +HostingHeaderMissingColon = Message header must separate key and value using ':' + +HostingHeaderMissingContentLengthHeader = Fatal error: Content-Length header must be provided + +HostingHeaderMissingContentLengthValue = Fatal error: Content-Length value is not an integer + +HostingJsonRpcHostAlreadyStarted = JSON RPC host has already started + +HostingJsonRpcHostNotStarted = JSON RPC host has not started + +HostingJsonRpcVersionMissing = JSON RPC version parameter is missing or invalid + +HostingMessageMissingMethod = JSON RPC message is missing required method parameter + +HostingMethodHandlerDoesNotExist(string messageType, string method) = {0} handler for method '{1}' does not exist. diff --git a/src/Microsoft.SqlTools.Hosting.v2/Localization/sr.xlf b/src/Microsoft.SqlTools.Hosting.v2/Localization/sr.xlf new file mode 100644 index 00000000..8c656dde --- /dev/null +++ b/src/Microsoft.SqlTools.Hosting.v2/Localization/sr.xlf @@ -0,0 +1,83 @@ + + + + + + MessageReader's input stream ended unexpectedly, terminating + MessageReader's input stream ended unexpectedly, terminating + + + + Message header must separate key and value using ':' + Message header must separate key and value using ':' + + + + Fatal error: Content-Length header must be provided + Fatal error: Content-Length header must be provided + + + + Fatal error: Content-Length value is not an integer + Fatal error: Content-Length value is not an integer + + + + Cannot register service for type {0}, one or more services already registered + Cannot register service for type {0}, one or more services already registered + + + + Multiple services found for type {0}, expected only 1 + Multiple services found for type {0}, expected only 1 + + + + Service of type {0} cannot be created by ExtensionLoader<{1}> + Service of type {0} cannot be created by ExtensionLoader<{1}> + + + + SetServiceProvider() was not called to establish the required service provider + SetServiceProvider() was not called to establish the required service provider + + + + Service {0} was not found in the service provider + Service {0} was not found in the service provider + + + + Service of Type {0} is not compatible with registered Type {1} + Service of Type {0} is not compatible with registered Type {1} + + + + JSON RPC version parameter is missing or invalid + JSON RPC version parameter is missing or invalid + + + + JSON RPC message is missing required method parameter + JSON RPC message is missing required method parameter + + + + {0} handler for method '{1}' does not exist. + {0} handler for method '{1}' does not exist. + . + Parameters: 0 - messageType (string), 1 - method (string) + + + JSON RPC host has already started + JSON RPC host has already started + + + + JSON RPC host has not started + JSON RPC host has not started + + + + + \ No newline at end of file diff --git a/src/Microsoft.SqlTools.Hosting.v2/Microsoft.SqlTools.Hosting.csproj b/src/Microsoft.SqlTools.Hosting.v2/Microsoft.SqlTools.Hosting.csproj new file mode 100644 index 00000000..62a2fc2b --- /dev/null +++ b/src/Microsoft.SqlTools.Hosting.v2/Microsoft.SqlTools.Hosting.csproj @@ -0,0 +1,28 @@ + + + netstandard2.0 + false + Microsoft.SqlTools.Hosting.v2 + Library + + The Microsoft.SqlTools.Hosting framework can host applications implementing the VSCode Language Server Protocol and/or + applications implementing the Database Management Protocol. It handles service discovery, initialization, and communication over + the JSON-RPC protocol. + + $(PackageDescription) + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Microsoft.SqlTools.Hosting.v2/Properties/AssemblyInfo.cs b/src/Microsoft.SqlTools.Hosting.v2/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..a793eda3 --- /dev/null +++ b/src/Microsoft.SqlTools.Hosting.v2/Properties/AssemblyInfo.cs @@ -0,0 +1,46 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SqlTools Hosting Library")] +[assembly: AssemblyDescription("Provides hosting services for SqlTools applications.")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("SqlTools Hosting Library")] +[assembly: AssemblyCopyright("� Microsoft Corporation. All rights reserved.")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("6ECAFE73-131A-4221-AA13-C9BDE07FD92B")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyInformationalVersion("1.0.0.0")] + +[assembly: InternalsVisibleTo("Microsoft.SqlTools.Hosting.UnitTests")] +[assembly: InternalsVisibleTo("Microsoft.SqlTools.CoreServices")] + diff --git a/src/Microsoft.SqlTools.Hosting.v2/Protocol/EventContext.cs b/src/Microsoft.SqlTools.Hosting.v2/Protocol/EventContext.cs new file mode 100644 index 00000000..2c38ec37 --- /dev/null +++ b/src/Microsoft.SqlTools.Hosting.v2/Protocol/EventContext.cs @@ -0,0 +1,32 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System.Collections.Concurrent; +using Microsoft.SqlTools.Hosting.Contracts; + +namespace Microsoft.SqlTools.Hosting.Protocol +{ + /// + /// Provides context for a received event so that handlers + /// can write events back to the channel. + /// + public class EventContext : IEventSender + { + internal readonly BlockingCollection messageQueue; + + public EventContext(BlockingCollection outgoingMessageQueue) + { + // TODO: Either 1) make this constructor internal and provide a test framework for validating + // or 2) extract an interface for eventcontext to allow users to mock + messageQueue = outgoingMessageQueue; + } + + public void SendEvent(EventType eventType, TParams eventParams) + { + messageQueue.Add(Message.CreateEvent(eventType, eventParams)); + } + } +} + diff --git a/src/Microsoft.SqlTools.Hosting.v2/Protocol/Exceptions.cs b/src/Microsoft.SqlTools.Hosting.v2/Protocol/Exceptions.cs new file mode 100644 index 00000000..5aec7c16 --- /dev/null +++ b/src/Microsoft.SqlTools.Hosting.v2/Protocol/Exceptions.cs @@ -0,0 +1,34 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System; + +namespace Microsoft.SqlTools.Hosting.Protocol +{ + /// + /// Exception thrown when parsing a message from input stream fails. + /// + public class MessageParseException : Exception + { + public string OriginalMessageText { get; } + + public MessageParseException(string originalMessageText, string errorMessage, params object[] errorMessageArgs) + : base(string.Format(errorMessage, errorMessageArgs)) + { + OriginalMessageText = originalMessageText; + } + } + + /// + /// Exception thrown when a handler for a given request/event method does not exist + /// + public class MethodHandlerDoesNotExistException : Exception + { + public MethodHandlerDoesNotExistException(MessageType type, string method) + : base(SR.HostingMethodHandlerDoesNotExist(type.ToString(), method)) + { + } + } +} diff --git a/src/Microsoft.SqlTools.Hosting.v2/Protocol/IEventSender.cs b/src/Microsoft.SqlTools.Hosting.v2/Protocol/IEventSender.cs new file mode 100644 index 00000000..c3863dd6 --- /dev/null +++ b/src/Microsoft.SqlTools.Hosting.v2/Protocol/IEventSender.cs @@ -0,0 +1,23 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using Microsoft.SqlTools.Hosting.Contracts; + +namespace Microsoft.SqlTools.Hosting.Protocol +{ + /// + /// Interface for objects that can send events via the JSON RPC channel + /// + public interface IEventSender + { + /// + /// Sends an event over the JSON RPC channel + /// + /// Configuration of the event to send + /// Parameters for the event to send + /// Type of the parameters for the event, defined in + void SendEvent(EventType eventType, TParams eventParams); + } +} diff --git a/src/Microsoft.SqlTools.Hosting.v2/Protocol/IJsonRpcHost.cs b/src/Microsoft.SqlTools.Hosting.v2/Protocol/IJsonRpcHost.cs new file mode 100644 index 00000000..b429bf5d --- /dev/null +++ b/src/Microsoft.SqlTools.Hosting.v2/Protocol/IJsonRpcHost.cs @@ -0,0 +1,28 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +namespace Microsoft.SqlTools.Hosting.Protocol +{ + /// + /// Interface for a JSON RPC host + /// + public interface IJsonRpcHost : IEventSender, IRequestSender, IMessageDispatcher + { + /// + /// Starts the JSON RPC host + /// + void Start(); + + /// + /// Stops the JSON RPC host + /// + void Stop(); + + /// + /// Waits for the JSON RPC host to exit + /// + void WaitForExit(); + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.Hosting.v2/Protocol/IMessageDispatcher.cs b/src/Microsoft.SqlTools.Hosting.v2/Protocol/IMessageDispatcher.cs new file mode 100644 index 00000000..2ca34d28 --- /dev/null +++ b/src/Microsoft.SqlTools.Hosting.v2/Protocol/IMessageDispatcher.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.Threading.Tasks; +using Microsoft.SqlTools.Hosting.Contracts; + +namespace Microsoft.SqlTools.Hosting.Protocol +{ + /// + /// Interface for objects that can will handle messages. The methods exposed via this interface + /// allow users to what to do when a specific message is received. + /// + public interface IMessageDispatcher + { + /// + /// Sets the function to run when a request message of a specific + /// is received + /// + /// Configuration of the request message will handle + /// What to do when a request message of is received + /// If true, any existing handler will be replaced with this one + /// Type of the parameters for the request, defined by + /// Type of the response to the request, defined by + void SetAsyncRequestHandler( + RequestType requestType, + Func, Task> requestHandler, + bool overrideExisting = false); + + /// + /// Sets the function to run when a request message of a specific + /// is received + /// + /// Configuration of the request message will handle + /// What to do when a request message of is received + /// If true, any existing handler will be replaced with this one + /// Type of the parameters for the request, defined by + /// Type of the response to the request, defined by + void SetRequestHandler( + RequestType requestType, + Action> requestHandler, + bool overrideExisting = false); + + /// + /// Sets the function to run when an event message of a specific configurat + /// is received + /// + /// Configuration of the event message will handle + /// What to do when an event message of is received + /// If true, any existing handler will be replaced with this one + /// Type of the parameters for the event + void SetAsyncEventHandler( + EventType eventType, + Func eventHandler, + bool overrideExisting = false); + + /// + /// Sets the function to run when an event message of a specific + /// is received + /// + /// Configuration of the event message will handle + /// What to do when an event message of is received + /// If true, any existing handler will be replaced with this one + /// Type of the parameters for the event + void SetEventHandler( + EventType eventType, + Action eventHandler, + bool overrideExisting = false); + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.Hosting.v2/Protocol/IRequestSender.cs b/src/Microsoft.SqlTools.Hosting.v2/Protocol/IRequestSender.cs new file mode 100644 index 00000000..c7adeb2d --- /dev/null +++ b/src/Microsoft.SqlTools.Hosting.v2/Protocol/IRequestSender.cs @@ -0,0 +1,27 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System.Threading.Tasks; +using Microsoft.SqlTools.Hosting.Contracts; + +namespace Microsoft.SqlTools.Hosting.Protocol +{ + /// + /// Interface for objects that can requests via the JSON RPC channel + /// + public interface IRequestSender + { + /// + /// Sends a request over the JSON RPC channel. It will wait for a response to the message + /// before completing. + /// + /// Configuration of the request to send + /// Parameters for the request to send + /// Type of the parameters for the request, defined by + /// + /// + Task SendRequest(RequestType requestType, TParams requestParams); + } +} diff --git a/src/Microsoft.SqlTools.Hosting.v2/Protocol/JsonRpcHost.cs b/src/Microsoft.SqlTools.Hosting.v2/Protocol/JsonRpcHost.cs new file mode 100644 index 00000000..83696957 --- /dev/null +++ b/src/Microsoft.SqlTools.Hosting.v2/Protocol/JsonRpcHost.cs @@ -0,0 +1,446 @@ +// +// 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.Concurrent; +using System.Collections.Generic; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.SqlTools.Hosting.Channels; +using Microsoft.SqlTools.Hosting.Contracts; +using Microsoft.SqlTools.Hosting.Contracts.Internal; +using Microsoft.SqlTools.Hosting.Utility; + +namespace Microsoft.SqlTools.Hosting.Protocol +{ + public class JsonRpcHost : IJsonRpcHost + { + #region Private Fields + + internal readonly CancellationTokenSource cancellationTokenSource; + + private readonly CancellationToken consumeInputCancellationToken; + private readonly CancellationToken consumeOutputCancellationToken; + + internal readonly BlockingCollection outputQueue; + internal readonly Dictionary> eventHandlers; + internal readonly Dictionary> requestHandlers; + internal readonly ConcurrentDictionary> pendingRequests; + internal readonly ChannelBase protocolChannel; + + internal Task consumeInputTask; + internal Task consumeOutputTask; + private bool isStarted; + + #endregion + + public JsonRpcHost(ChannelBase channel) + { + Validate.IsNotNull(nameof(channel), channel); + + cancellationTokenSource = new CancellationTokenSource(); + consumeInputCancellationToken = cancellationTokenSource.Token; + consumeOutputCancellationToken = cancellationTokenSource.Token; + outputQueue = new BlockingCollection(new ConcurrentQueue()); + protocolChannel = channel; + + eventHandlers = new Dictionary>(); + requestHandlers = new Dictionary>(); + pendingRequests = new ConcurrentDictionary>(); + } + + #region Start/Stop Methods + + /// + /// Starts the JSON RPC host using the protocol channel that was provided + /// + public void Start() + { + // If we've already started, we can't start up again + if (isStarted) + { + throw new InvalidOperationException(SR.HostingJsonRpcHostAlreadyStarted); + } + + // Make sure no other calls try to start the endpoint during startup + isStarted = true; + + // Initialize the protocol channel + protocolChannel.Start(); + protocolChannel.WaitForConnection().Wait(); + + // Start the input and output consumption threads + consumeInputTask = ConsumeInput(); + consumeOutputTask = ConsumeOutput(); + } + + /// + /// Stops the JSON RPC host and the underlying protocol channel + /// + public void Stop() + { + // If we haven't started, we can't stop + if (!isStarted) + { + throw new InvalidOperationException(SR.HostingJsonRpcHostNotStarted); + } + + // Make sure no future calls try to stop the endpoint during shutdown + isStarted = false; + + // Shutdown the host + cancellationTokenSource.Cancel(); + protocolChannel.Stop(); + } + + /// + /// Waits for input and output threads to naturally exit + /// + /// Thrown if the host has not started + public void WaitForExit() + { + // If we haven't started everything, we can't wait for exit + if (!isStarted) + { + throw new InvalidOperationException(SR.HostingJsonRpcHostNotStarted); + } + + // Join the input and output threads to this thread + Task.WaitAll(consumeInputTask, consumeOutputTask); + } + + #endregion + + #region Public Methods + + /// + /// Sends an event, independent of any request + /// + /// Event parameter type + /// Type of event being sent + /// Event parameters being sent + /// Task that tracks completion of the send operation. + public void SendEvent( + EventType eventType, + TParams eventParams) + { + if (!protocolChannel.IsConnected) + { + throw new InvalidOperationException("SendEvent called when ProtocolChannel was not yet connected"); + } + + // Create a message from the event provided + Message message = Message.CreateEvent(eventType, eventParams); + outputQueue.Add(message); + } + + /// + /// Sends a request, independent of any request + /// + /// Configuration of the request that is being sent + /// Contents of the request + /// Type of the message contents + /// Type of the contents of the expected result of the request + /// Task that is completed when the + /// TODO: This doesn't properly handle error responses scenarios. + public async Task SendRequest( + RequestType requestType, + TParams requestParams) + { + if (!protocolChannel.IsConnected) + { + throw new InvalidOperationException("SendRequest called when ProtocolChannel was not yet connected"); + } + + // Add a task completion source for the request's response + string messageId = Guid.NewGuid().ToString(); + TaskCompletionSource responseTask = new TaskCompletionSource(); + pendingRequests.TryAdd(messageId, responseTask); + + // Send the request + outputQueue.Add(Message.CreateRequest(requestType, messageId, requestParams)); + + // Wait for the response + Message responseMessage = await responseTask.Task; + + return responseMessage.GetTypedContents(); + } + + /// + /// Sets the handler for an event with a given configuration + /// + /// Configuration of the event + /// Function for handling the event + /// Whether or not to override any existing event handler for this method + /// Type of the parameters for the event + public void SetAsyncEventHandler( + EventType eventType, + Func eventHandler, + bool overrideExisting = false) + { + Validate.IsNotNull(nameof(eventType), eventType); + Validate.IsNotNull(nameof(eventHandler), eventHandler); + + if (overrideExisting) + { + // Remove the existing handler so a new one can be set + eventHandlers.Remove(eventType.MethodName); + } + + Func handler = eventMessage => + eventHandler(eventMessage.GetTypedContents(), new EventContext(outputQueue)); + + eventHandlers.Add(eventType.MethodName, handler); + } + + /// + /// Creates a Func based that wraps the action in a task and calls the Func-based overload + /// + /// Configuration of the event + /// Function for handling the event + /// Whether or not to override any existing event handler for this method + /// Type of the parameters for the event + public void SetEventHandler( + EventType eventType, + Action eventHandler, + bool overrideExisting = false) + { + Validate.IsNotNull(nameof(eventHandler), eventHandler); + Func eventFunc = (p, e) => Task.Run(() => eventHandler(p, e)); + SetAsyncEventHandler(eventType, eventFunc, overrideExisting); + } + + /// + /// Sets the handler for a request with a given configuration + /// + /// Configuration of the request + /// Function for handling the request + /// Whether or not to override any existing request handler for this method + /// Type of the parameters for the request + /// Type of the parameters for the response + public void SetAsyncRequestHandler( + RequestType requestType, + Func, Task> requestHandler, + bool overrideExisting = false) + { + Validate.IsNotNull(nameof(requestType), requestType); + Validate.IsNotNull(nameof(requestHandler), requestHandler); + + if (overrideExisting) + { + // Remove the existing handler so a new one can be set + requestHandlers.Remove(requestType.MethodName); + } + + // Setup the wrapper around the handler + Func handler = requestMessage => + requestHandler(requestMessage.GetTypedContents(), new RequestContext(requestMessage, outputQueue)); + + requestHandlers.Add(requestType.MethodName, handler); + } + + /// + /// Creates a Func based that wraps the action in a task and calls the Func-based overload + /// + /// /// Configuration of the request + /// Function for handling the request + /// Whether or not to override any existing request handler for this method + /// Type of the parameters for the request + /// Type of the parameters for the response + public void SetRequestHandler( + RequestType requestType, + Action> requestHandler, + bool overrideExisting = false) + { + Validate.IsNotNull(nameof(requestHandler), requestHandler); + Func, Task> requestFunc = (p, e) => Task.Run(() => requestHandler(p, e)); + SetAsyncRequestHandler(requestType, requestFunc, overrideExisting); + } + + #endregion + + #region Message Processing Tasks + + internal Task ConsumeInput() + { + return Task.Factory.StartNew(async () => + { + while (!consumeInputCancellationToken.IsCancellationRequested) + { + Message incomingMessage; + try + { + // Read message from the input channel + incomingMessage = await protocolChannel.MessageReader.ReadMessage(); + } + catch (EndOfStreamException) + { + // The stream has ended, end the input message loop + break; + } + catch (Exception e) + { + // Log the error and send an error event to the client + string message = string.Format("Exception occurred while receiving input message: {0}", e.Message); + Logger.Instance.Write(LogLevel.Error, message); + + // TODO: Add event to output queue, and unit test it + + // Continue the loop + continue; + } + + // Verbose logging + string logMessage = string.Format("Received message of type[{0}] and method[{1}]", + incomingMessage.MessageType, incomingMessage.Method); + Logger.Instance.Write(LogLevel.Verbose, logMessage); + + // Process the message + try + { + await DispatchMessage(incomingMessage); + } + catch (MethodHandlerDoesNotExistException) + { + // Method could not be handled, if the message was a request, send an error back to the client + // TODO: Localize + string mnfLogMessage = string.Format("Failed to find method handler for type[{0}] and method[{1}]", + incomingMessage.MessageType, incomingMessage.Method); + Logger.Instance.Write(LogLevel.Warning, mnfLogMessage); + + if (incomingMessage.MessageType == MessageType.Request) + { + // TODO: Localize + Error mnfError = new Error {Code = -32601, Message = "Method not found"}; + Message errorMessage = Message.CreateResponseError(incomingMessage.Id, mnfError); + outputQueue.Add(errorMessage, consumeInputCancellationToken); + } + } + catch (Exception e) + { + // General errors should be logged but not halt the processing loop + string geLogMessage = string.Format("Exception thrown when handling message of type[{0}] and method[{1}]: {2}", + incomingMessage.MessageType, incomingMessage.Method, e); + Logger.Instance.Write(LogLevel.Error, geLogMessage); + // TODO: Should we be returning a response for failing requests? + } + } + + Logger.Instance.Write(LogLevel.Warning, "Exiting consume input loop!"); + }, consumeOutputCancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Default).Unwrap(); + } + + internal Task ConsumeOutput() + { + return Task.Factory.StartNew(async () => + { + while (!consumeOutputCancellationToken.IsCancellationRequested) + { + Message outgoingMessage; + try + { + // Read message from the output queue + outgoingMessage = outputQueue.Take(consumeOutputCancellationToken); + } + catch (OperationCanceledException) + { + // Cancelled during taking, end the loop + break; + } + catch (Exception e) + { + // If we hit an exception here, it is unrecoverable + string message = string.Format("Unexpected occurred while receiving output message: {0}", e.Message); + Logger.Instance.Write(LogLevel.Error, message); + + break; + } + + // Send the message + string logMessage = string.Format("Sending message of type[{0}] and method[{1}]", + outgoingMessage.MessageType, outgoingMessage.Method); + Logger.Instance.Write(LogLevel.Verbose, logMessage); + + await protocolChannel.MessageWriter.WriteMessage(outgoingMessage); + } + Logger.Instance.Write(LogLevel.Warning, "Exiting consume output loop!"); + }, consumeOutputCancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Default).Unwrap(); + } + + internal async Task DispatchMessage(Message messageToDispatch) + { + Task handlerToAwait = null; + + switch (messageToDispatch.MessageType) + { + case MessageType.Request: + Func requestHandler; + if (requestHandlers.TryGetValue(messageToDispatch.Method, out requestHandler)) + { + handlerToAwait = requestHandler(messageToDispatch); + } + else + { + throw new MethodHandlerDoesNotExistException(MessageType.Request, messageToDispatch.Method); + } + break; + case MessageType.Response: + TaskCompletionSource requestTask; + if (pendingRequests.TryRemove(messageToDispatch.Id, out requestTask)) + { + requestTask.SetResult(messageToDispatch); + return; + } + else + { + throw new MethodHandlerDoesNotExistException(MessageType.Response, "response"); + } + case MessageType.Event: + Func eventHandler; + if (eventHandlers.TryGetValue(messageToDispatch.Method, out eventHandler)) + { + handlerToAwait = eventHandler(messageToDispatch); + } + else + { + throw new MethodHandlerDoesNotExistException(MessageType.Event, messageToDispatch.Method); + } + break; + default: + // TODO: This case isn't handled properly + break; + } + + // Skip processing if there isn't anything to do + if (handlerToAwait == null) + { + return; + } + + // Run the handler + try + { + await handlerToAwait; + } + catch (TaskCanceledException) + { + // Some tasks may be cancelled due to legitimate + // timeouts so don't let those exceptions go higher. + } + catch (AggregateException e) + { + if (!(e.InnerExceptions[0] is TaskCanceledException)) + { + // Cancelled tasks aren't a problem, so rethrow + // anything that isn't a TaskCanceledException + throw; + } + } + } + + #endregion + } +} diff --git a/src/Microsoft.SqlTools.Hosting.v2/Protocol/Message.cs b/src/Microsoft.SqlTools.Hosting.v2/Protocol/Message.cs new file mode 100644 index 00000000..e41e81ba --- /dev/null +++ b/src/Microsoft.SqlTools.Hosting.v2/Protocol/Message.cs @@ -0,0 +1,251 @@ +// +// 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.Diagnostics; +using Microsoft.SqlTools.Hosting.Contracts; +using Microsoft.SqlTools.Hosting.Contracts.Internal; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using Newtonsoft.Json.Serialization; + +namespace Microsoft.SqlTools.Hosting.Protocol +{ + /// + /// Defines all possible message types. + /// + public enum MessageType + { + Request, + Response, + ResponseError, + Event + } + + /// + /// Representation for a JSON RPC message. Provides logic for converting back and forth from + /// string + /// + [DebuggerDisplay("MessageType = {MessageType.ToString()}, Method = {Method}, Id = {Id}")] + public class Message + { + #region Constants + + private const string JsonRpcVersion = "2.0"; + + private static readonly JsonSerializerSettings JsonSerializerSettings = new JsonSerializerSettings + { + ContractResolver = new CamelCasePropertyNamesContractResolver() + }; + private static readonly JsonSerializer ContentSerializer = JsonSerializer.Create(JsonSerializerSettings); + + #endregion + + #region Construction + + private Message(MessageType messageType, JToken contents) + { + MessageType = messageType; + Contents = contents; + } + + /// + /// Creates a message with a Request type + /// + /// Configuration for the request + /// ID of the message + /// Contents of the message + /// Type of the contents of the message + /// Type of the contents of the results to this request + /// Message with a Request type + public static Message CreateRequest( + RequestType requestType, + string id, + TParams contents) + { + JToken contentsToken = contents == null ? null : JToken.FromObject(contents, ContentSerializer); + return new Message(MessageType.Request, contentsToken) + { + Id = id, + Method = requestType.MethodName + }; + } + + /// + /// Creates a message with a Response type. + /// + /// The sequence ID of the original request. + /// The contents of the response. + /// A message with a Response type. + public static Message CreateResponse( + string id, + TParams contents) + { + JToken contentsToken = contents == null ? null : JToken.FromObject(contents, ContentSerializer); + return new Message(MessageType.Response, contentsToken) + { + Id = id + }; + } + + /// + /// Creates a message with a Response type and error details. + /// + /// The sequence ID of the original request. + /// The error details of the response. + /// A message with a Response type and error details. + public static Message CreateResponseError( + string id, + Error error) + { + JToken errorToken = error == null ? null : JToken.FromObject(error, ContentSerializer); + return new Message(MessageType.ResponseError, errorToken) + { + Id = id + }; + } + + /// + /// Creates a message with an Event type. + /// + /// Configuration for the event message + /// The contents of the event. + /// + /// A message with an Event type + public static Message CreateEvent( + EventType eventType, + TParams contents) + { + JToken contentsToken = contents == null ? null : JToken.FromObject(contents, ContentSerializer); + return new Message(MessageType.Event, contentsToken) + { + Method = eventType.MethodName + }; + } + + #endregion + + #region Properties + + /// + /// Gets or sets the message type. + /// + public MessageType MessageType { get; } + + /// + /// Gets or sets the message's sequence ID. + /// + public string Id { get; private set; } + + /// + /// Gets or sets the message's method/command name. + /// + public string Method { get; private set; } + + /// + /// Gets or sets a JToken containing the contents of the message. + /// + public JToken Contents { get; } + + #endregion + + #region Serialization/Deserialization + + public static Message Deserialize(string jsonString) + { + // Deserialize the object from the JSON into an intermediate object + JObject messageObject = JObject.Parse(jsonString); + JToken token; + + // Ensure there's a JSON RPC version or else it's invalid + if (!messageObject.TryGetValue("jsonrpc", out token) || token.Value() != JsonRpcVersion) + { + throw new MessageParseException(null, SR.HostingJsonRpcVersionMissing); + } + + if (messageObject.TryGetValue("id", out token)) + { + // Message with ID is a Request or Response + string messageId = token.ToString(); + + if (messageObject.TryGetValue("result", out token)) + { + return new Message(MessageType.Response, token) {Id = messageId}; + } + if (messageObject.TryGetValue("error", out token)) + { + return new Message(MessageType.ResponseError, token) {Id = messageId}; + } + + // Message without result/error is a Request + JToken messageParams; + messageObject.TryGetValue("params", out messageParams); + if (!messageObject.TryGetValue("method", out token)) + { + throw new MessageParseException(null, SR.HostingMessageMissingMethod); + } + + return new Message(MessageType.Request, messageParams) {Id = messageId, Method = token.ToString()}; + } + else + { + // Messages without an id are events + JToken messageParams; + messageObject.TryGetValue("params", out messageParams); + + if (!messageObject.TryGetValue("method", out token)) + { + throw new MessageParseException(null, SR.HostingMessageMissingMethod); + } + + return new Message(MessageType.Event, messageParams) {Method = token.ToString()}; + } + } + + public string Serialize() + { + JObject messageObject = new JObject + { + {"jsonrpc", JToken.FromObject(JsonRpcVersion)} + }; + + switch (MessageType) + { + case MessageType.Request: + messageObject.Add("id", JToken.FromObject(Id)); + messageObject.Add("method", Method); + messageObject.Add("params", Contents); + break; + case MessageType.Event: + messageObject.Add("method", Method); + messageObject.Add("params", Contents); + break; + case MessageType.Response: + messageObject.Add("id", JToken.FromObject(Id)); + messageObject.Add("result", Contents); + break; + case MessageType.ResponseError: + messageObject.Add("id", JToken.FromObject(Id)); + messageObject.Add("error", Contents); + break; + } + + return JsonConvert.SerializeObject(messageObject); + } + + public TContents GetTypedContents() + { + TContents typedContents = default(TContents); + if (Contents != null) + { + typedContents = Contents.ToObject(); + } + + return typedContents; + } + + #endregion + } +} diff --git a/src/Microsoft.SqlTools.Hosting.v2/Protocol/MessageReader.cs b/src/Microsoft.SqlTools.Hosting.v2/Protocol/MessageReader.cs new file mode 100644 index 00000000..082036cc --- /dev/null +++ b/src/Microsoft.SqlTools.Hosting.v2/Protocol/MessageReader.cs @@ -0,0 +1,257 @@ +// +// 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.IO; +using System.Text; +using System.Threading.Tasks; +using Microsoft.SqlTools.Hosting.Utility; + +namespace Microsoft.SqlTools.Hosting.Protocol +{ + public class MessageReader + { + #region Private Fields + + public const int DefaultBufferSize = 8192; + private const double BufferResizeTrigger = 0.25; + + private const int CR = 0x0D; + private const int LF = 0x0A; + private static readonly string[] NewLineDelimiters = { Environment.NewLine }; + + private readonly Stream inputStream; + + private bool needsMoreData = true; + private int readOffset; + private int bufferEndOffset; + + private byte[] messageBuffer; + + private int expectedContentLength; + private Dictionary messageHeaders; + + internal enum ReadState + { + Headers, + Content + } + + #endregion + + #region Constructors + + public MessageReader(Stream inputStream, Encoding messageEncoding = null) + { + Validate.IsNotNull("streamReader", inputStream); + + this.inputStream = inputStream; + MessageEncoding = messageEncoding ?? Encoding.UTF8; + + messageBuffer = new byte[DefaultBufferSize]; + } + + #endregion + + #region Testable Properties + + internal byte[] MessageBuffer + { + get => messageBuffer; + set => messageBuffer = value; + } + + internal ReadState CurrentState { get; private set; } + + internal Encoding MessageEncoding { get; private set; } + + #endregion + + #region Public Methods + + public virtual async Task ReadMessage() + { + string messageContent = null; + + // Do we need to read more data or can we process the existing buffer? + while (!needsMoreData || await ReadNextChunk()) + { + // Clear the flag since we should have what we need now + needsMoreData = false; + + // Do we need to look for message headers? + if (CurrentState == ReadState.Headers && !TryReadMessageHeaders()) + { + // If we don't have enough data to read headers yet, keep reading + needsMoreData = true; + continue; + } + + // Do we need to look for message content? + if (CurrentState == ReadState.Content && !TryReadMessageContent(out messageContent)) + { + // If we don't have enough data yet to construct the content, keep reading + needsMoreData = true; + continue; + } + + // We've read a message now, break out of the loop + break; + } + + // Now that we have a message, reset the buffer's state + ShiftBufferBytesAndShrink(readOffset); + + // Return the parsed message + return Message.Deserialize(messageContent); + } + + #endregion + + #region Private Methods + + private async Task ReadNextChunk() + { + // Do we need to resize the buffer? See if less than 1/4 of the space is left. + if ((double)(messageBuffer.Length - bufferEndOffset) / messageBuffer.Length < BufferResizeTrigger) + { + // Double the size of the buffer + Array.Resize(ref messageBuffer, messageBuffer.Length * 2); + } + + // Read the next chunk into the message buffer + int readLength = + await inputStream.ReadAsync(messageBuffer, bufferEndOffset, messageBuffer.Length - bufferEndOffset); + + bufferEndOffset += readLength; + + if (readLength == 0) + { + // If ReadAsync returns 0 then it means that the stream was + // closed unexpectedly (usually due to the client application + // ending suddenly). For now, just terminate the language + // server immediately. + throw new EndOfStreamException(SR.HostingUnexpectedEndOfStream); + } + + return true; + } + + private bool TryReadMessageHeaders() + { + int scanOffset = readOffset; + + // Scan for the final double-newline that marks the end of the header lines + while (scanOffset + 3 < bufferEndOffset && + (messageBuffer[scanOffset] != CR || + messageBuffer[scanOffset + 1] != LF || + messageBuffer[scanOffset + 2] != CR || + messageBuffer[scanOffset + 3] != LF)) + { + scanOffset++; + } + + // Make sure we haven't reached the end of the buffer without finding a separator (e.g CRLFCRLF) + if (scanOffset + 3 >= bufferEndOffset) + { + return false; + } + + // Convert the header block into a array of lines + var headers = Encoding.ASCII.GetString(messageBuffer, readOffset, scanOffset) + .Split(NewLineDelimiters, StringSplitOptions.RemoveEmptyEntries); + + try + { + // Read each header and store it in the dictionary + messageHeaders = new Dictionary(); + foreach (var header in headers) + { + int currentLength = header.IndexOf(':'); + if (currentLength == -1) + { + throw new ArgumentException(SR.HostingHeaderMissingColon); + } + + var key = header.Substring(0, currentLength); + var value = header.Substring(currentLength + 1).Trim(); + messageHeaders[key] = value; + } + + // Parse out the content length as an int + string contentLengthString; + if (!messageHeaders.TryGetValue("Content-Length", out contentLengthString)) + { + throw new MessageParseException("", SR.HostingHeaderMissingContentLengthHeader); + } + + // Parse the content length to an integer + if (!int.TryParse(contentLengthString, out expectedContentLength)) + { + throw new MessageParseException("", SR.HostingHeaderMissingContentLengthValue); + } + } + catch (Exception) + { + // The content length was invalid or missing. Trash the buffer we've read + ShiftBufferBytesAndShrink(scanOffset + 4); + throw; + } + + // Skip past the headers plus the newline characters + readOffset += scanOffset + 4; + + // Done reading headers, now read content + CurrentState = ReadState.Content; + + return true; + } + + private bool TryReadMessageContent(out string messageContent) + { + messageContent = null; + + // Do we have enough bytes to reach the expected length? + if (bufferEndOffset - readOffset < expectedContentLength) + { + return false; + } + + // Convert the message contents to a string using the specified encoding + messageContent = MessageEncoding.GetString(messageBuffer, readOffset, expectedContentLength); + + readOffset += expectedContentLength; + + // Done reading content, now look for headers for the next message + CurrentState = ReadState.Headers; + + return true; + } + + private void ShiftBufferBytesAndShrink(int bytesToRemove) + { + // Create a new buffer that is shrunken by the number of bytes to remove + // Note: by using Max, we can guarantee a buffer of at least default buffer size + byte[] newBuffer = new byte[Math.Max(messageBuffer.Length - bytesToRemove, DefaultBufferSize)]; + + // If we need to do shifting, do the shifting + if (bytesToRemove <= messageBuffer.Length) + { + // Copy the existing buffer starting at the offset to remove + Buffer.BlockCopy(messageBuffer, bytesToRemove, newBuffer, 0, bufferEndOffset - bytesToRemove); + } + + // Make the new buffer the message buffer + messageBuffer = newBuffer; + + // Reset the read offset and the end offset + readOffset = 0; + bufferEndOffset -= bytesToRemove; + } + + #endregion + } +} diff --git a/src/Microsoft.SqlTools.Hosting.v2/Protocol/MessageWriter.cs b/src/Microsoft.SqlTools.Hosting.v2/Protocol/MessageWriter.cs new file mode 100644 index 00000000..27535561 --- /dev/null +++ b/src/Microsoft.SqlTools.Hosting.v2/Protocol/MessageWriter.cs @@ -0,0 +1,59 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System.IO; +using System.Text; +using System.Threading.Tasks; +using Microsoft.SqlTools.Hosting.Utility; + +namespace Microsoft.SqlTools.Hosting.Protocol +{ + public class MessageWriter + { + private const string ContentLength = "Content-Length: "; + private const string ContentType = "Content-Type: application/json"; + private const string HeaderSeparator = "\r\n"; + private const string HeaderEnd = "\r\n\r\n"; + + private readonly Stream outputStream; + private readonly AsyncLock writeLock = new AsyncLock(); + + public MessageWriter(Stream outputStream) + { + Validate.IsNotNull("streamWriter", outputStream); + + this.outputStream = outputStream; + } + + public virtual async Task WriteMessage(Message messageToWrite) + { + Validate.IsNotNull("messageToWrite", messageToWrite); + + // Log the JSON representation of the message + string logMessage = string.Format("Sending message of type[{0}] and method[{1}]", + messageToWrite.MessageType, messageToWrite.Method); + Logger.Instance.Write(LogLevel.Verbose, logMessage); + + string serializedMessage = messageToWrite.Serialize(); + // TODO: Allow encoding to be passed in + byte[] messageBytes = Encoding.UTF8.GetBytes(serializedMessage); + + string headers = ContentLength + messageBytes.Length + HeaderSeparator + + ContentType + HeaderEnd; + byte[] headerBytes = Encoding.ASCII.GetBytes(headers); + + // Make sure only one call is writing at a time. You might be thinking + // "Why not use a normal lock?" We use an AsyncLock here so that the + // message loop doesn't get blocked while waiting for I/O to complete. + using (await writeLock.LockAsync()) + { + // Send the message + await outputStream.WriteAsync(headerBytes, 0, headerBytes.Length); + await outputStream.WriteAsync(messageBytes, 0, messageBytes.Length); + await outputStream.FlushAsync(); + } + } + } +} diff --git a/src/Microsoft.SqlTools.Hosting.v2/Protocol/RequestContext.cs b/src/Microsoft.SqlTools.Hosting.v2/Protocol/RequestContext.cs new file mode 100644 index 00000000..c6ceee1a --- /dev/null +++ b/src/Microsoft.SqlTools.Hosting.v2/Protocol/RequestContext.cs @@ -0,0 +1,57 @@ +// +// 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.Concurrent; +using Microsoft.SqlTools.Hosting.Contracts; +using Microsoft.SqlTools.Hosting.Contracts.Internal; + +namespace Microsoft.SqlTools.Hosting.Protocol +{ + public class RequestContext : IEventSender + { + internal readonly BlockingCollection messageQueue; + internal readonly Message requestMessage; + + public RequestContext(Message message, BlockingCollection outgoingMessageQueue) + { + // TODO: Either 1) make this constructor internal and provide a tes framework for validating + // or 2) extract an interface for requestcontext to allow users to mock + requestMessage = message; + messageQueue = outgoingMessageQueue; + } + + public virtual void SendResult(TResult resultDetails) + { + Message message = Message.CreateResponse(requestMessage.Id, resultDetails); + messageQueue.Add(message); + } + + public virtual void SendEvent(EventType eventType, TParams eventParams) + { + Message message = Message.CreateEvent(eventType, eventParams); + messageQueue.Add(message); + } + + public virtual void SendError(string errorMessage, int errorCode = 0) + { + // Build the error message + Error error = new Error + { + Message = errorMessage, + Code = errorCode + }; + Message message = Message.CreateResponseError(requestMessage.Id, error); + messageQueue.Add(message); + } + + public virtual void SendError(Exception e) + { + // Overload to use the parameterized error handler + SendError(e.Message, e.HResult); + } + } +} + diff --git a/src/Microsoft.SqlTools.Hosting.v2/ServiceHost.cs b/src/Microsoft.SqlTools.Hosting.v2/ServiceHost.cs new file mode 100644 index 00000000..a7d11357 --- /dev/null +++ b/src/Microsoft.SqlTools.Hosting.v2/ServiceHost.cs @@ -0,0 +1,210 @@ +// +// 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.Linq; +using System.Threading.Tasks; +using Microsoft.SqlTools.DataProtocol.Contracts; +using Microsoft.SqlTools.DataProtocol.Contracts.ServerCapabilities; +using Microsoft.SqlTools.Hosting.Channels; +using Microsoft.SqlTools.Hosting.Contracts; +using Microsoft.SqlTools.Hosting.Contracts.Internal; +using Microsoft.SqlTools.Hosting.Protocol; +using Microsoft.SqlTools.Hosting.Utility; + +namespace Microsoft.SqlTools.Hosting +{ + public class ServiceHost : IServiceHost + { + private const int DefaultShutdownTimeoutSeconds = 120; + + #region Fields + + private int? shutdownTimeoutSeconds; + + internal readonly List> initCallbacks; + internal readonly List> shutdownCallbacks; + internal IJsonRpcHost jsonRpcHost; + + #endregion + + #region Construction + + /// + /// Base constructor + /// + internal ServiceHost() + { + shutdownCallbacks = new List>(); + initCallbacks = new List>(); + } + + /// + /// Constructs a new service host that with ability to provide custom protocol channels + /// + /// Channel to use for JSON RPC input/output + public ServiceHost(ChannelBase protocolChannel) + : this() + { + Validate.IsNotNull(nameof(protocolChannel), protocolChannel); + jsonRpcHost = new JsonRpcHost(protocolChannel); + + // Register any request that the service host will handle + SetEventHandler(ExitNotification.Type, HandleExitNotification, true); + SetAsyncRequestHandler(ShutdownRequest.Type, HandleShutdownRequest, true); + SetAsyncRequestHandler(InitializeRequest.Type, HandleInitializeRequest, true); + } + + /// + /// Constructs a new service host intended to be used as a JSON RPC server. StdIn is used + /// for receiving messages, StdOut is used for sending messages. + /// + /// Service host as a JSON RPC server over StdI/O + public static ServiceHost CreateDefaultServer() + { + return new ServiceHost(new StdioServerChannel()); + } + + #endregion + + #region Properties + + public int ShutdownTimeoutSeconds + { + get => shutdownTimeoutSeconds ?? DefaultShutdownTimeoutSeconds; + set => shutdownTimeoutSeconds = value; + } + + public InitializeResponse InitializeResponse { get; set; } + + #endregion + + #region IServiceHost Implementations + + public void RegisterShutdownTask(Func shutdownCallback) + { + Validate.IsNotNull(nameof(shutdownCallback), shutdownCallback); + shutdownCallbacks.Add(shutdownCallback); + } + + public void RegisterInitializeTask(Func initializeCallback) + { + Validate.IsNotNull(nameof(initializeCallback), initializeCallback); + initCallbacks.Add(initializeCallback); + } + + #endregion + + #region IJsonRpcHost Implementation + + public void SendEvent( + EventType eventType, + TParams eventParams) + { + jsonRpcHost.SendEvent(eventType, eventParams); + } + + public Task SendRequest( + RequestType requestType, + TParams requestParams) + { + return jsonRpcHost.SendRequest(requestType, requestParams); + } + + public void SetAsyncEventHandler( + EventType eventType, + Func eventHandler, + bool overrideExisting) + { + jsonRpcHost.SetAsyncEventHandler(eventType, eventHandler, overrideExisting); + } + + public void SetEventHandler( + EventType eventType, + Action eventHandler, + bool overrideExisting) + { + jsonRpcHost.SetEventHandler(eventType, eventHandler, overrideExisting); + } + + public void SetAsyncRequestHandler( + RequestType requestType, + Func, Task> requestHandler, + bool overrideExisting) + { + jsonRpcHost.SetAsyncRequestHandler(requestType, requestHandler, overrideExisting); + } + + public void SetRequestHandler( + RequestType requestType, + Action> requestHandler, + bool overrideExisting) + { + jsonRpcHost.SetRequestHandler(requestType, requestHandler, overrideExisting); + } + + public void Start() + { + // Start the host + jsonRpcHost.Start(); + } + + public void Stop() + { + jsonRpcHost.Stop(); + } + + public void WaitForExit() + { + jsonRpcHost.WaitForExit(); + } + + #endregion + + #region Request Handlers + + internal async Task HandleInitializeRequest(InitializeParameters initParams, RequestContext requestContext) + { + Logger.Instance.Write(LogLevel.Normal, "Service host received intialize request"); + + // Call all initialize methods provided by the service components + IEnumerable initializeTasks = initCallbacks.Select(t => t(initParams, requestContext)); + + // Respond to initialize once all tasks are completed + await Task.WhenAll(initializeTasks); + + if (InitializeResponse == null) + { + InitializeResponse = new InitializeResponse + { + Capabilities = new ServerCapabilities() + }; + } + requestContext.SendResult(InitializeResponse); + } + + internal void HandleExitNotification(object exitParams, EventContext eventContext) + { + // Stop the server channel + Stop(); + } + + internal async Task HandleShutdownRequest(object shutdownParams, RequestContext requestContext) + { + Logger.Instance.Write(LogLevel.Normal, "Service host received shutdown request"); + + // Call all the shutdown methods provided by the service components + IEnumerable shutdownTasks = shutdownCallbacks.Select(t => t(shutdownParams, requestContext)); + + // Shutdown once all tasks are completed, or after the timeout expires, whichever comes first + TimeSpan shutdownTimeout = TimeSpan.FromSeconds(ShutdownTimeoutSeconds); + await Task.WhenAny(Task.WhenAll(shutdownTasks), Task.Delay(shutdownTimeout)); + requestContext.SendResult(null); + } + + #endregion + } +} diff --git a/src/Microsoft.SqlTools.Hosting.v2/Utility/AsyncLock.cs b/src/Microsoft.SqlTools.Hosting.v2/Utility/AsyncLock.cs new file mode 100644 index 00000000..1d8b0077 --- /dev/null +++ b/src/Microsoft.SqlTools.Hosting.v2/Utility/AsyncLock.cs @@ -0,0 +1,98 @@ +// +// 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.Threading; +using System.Threading.Tasks; + +namespace Microsoft.SqlTools.Hosting.Utility +{ + /// + /// Provides a simple wrapper over a SemaphoreSlim to allow + /// synchronization locking inside of async calls. Cannot be + /// used recursively. + /// + public class AsyncLock + { + #region Fields + + private readonly Task lockReleaseTask; + private readonly SemaphoreSlim lockSemaphore = new SemaphoreSlim(1, 1); + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the AsyncLock class. + /// + public AsyncLock() + { + lockReleaseTask = Task.FromResult((IDisposable)new LockReleaser(this)); + } + + #endregion + + #region Public Methods + + /// + /// Locks + /// + /// A task which has an IDisposable + public Task LockAsync() + { + return LockAsync(CancellationToken.None); + } + + /// + /// Obtains or waits for a lock which can be used to synchronize + /// access to a resource. The wait may be cancelled with the + /// given CancellationToken. + /// + /// + /// A CancellationToken which can be used to cancel the lock. + /// + /// + public Task LockAsync(CancellationToken cancellationToken) + { + Task waitTask = lockSemaphore.WaitAsync(cancellationToken); + + return waitTask.IsCompleted + ? lockReleaseTask + : waitTask.ContinueWith( + (t, releaser) => (IDisposable)releaser, + lockReleaseTask.Result, + cancellationToken, + TaskContinuationOptions.ExecuteSynchronously, + TaskScheduler.Default); + } + + #endregion + + #region Private Classes + + /// + /// Provides an IDisposable wrapper around an AsyncLock so + /// that it can easily be used inside of a 'using' block. + /// + private class LockReleaser : IDisposable + { + private readonly AsyncLock lockToRelease; + + internal LockReleaser(AsyncLock lockToRelease) + { + this.lockToRelease = lockToRelease; + } + + public void Dispose() + { + lockToRelease.lockSemaphore.Release(); + } + } + + #endregion + } +} + diff --git a/src/Microsoft.SqlTools.Hosting.v2/Utility/CommandOptions.cs b/src/Microsoft.SqlTools.Hosting.v2/Utility/CommandOptions.cs new file mode 100644 index 00000000..bc56d254 --- /dev/null +++ b/src/Microsoft.SqlTools.Hosting.v2/Utility/CommandOptions.cs @@ -0,0 +1,164 @@ +// +// 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; +using System.IO; + +namespace Microsoft.SqlTools.Hosting.Utility +{ + /// + /// The command-line options helper class. + /// + public class CommandOptions + { + /// + /// Construct and parse command line options from the arguments array + /// + public CommandOptions(string[] args, string serviceName) + { + ServiceName = serviceName; + ErrorMessage = string.Empty; + Locale = string.Empty; + + try + { + for (int i = 0; i < args.Length; ++i) + { + string arg = args[i]; + if (arg.StartsWith("--") || arg.StartsWith("-")) + { + // Extracting arguments and properties + arg = arg.Substring(1).ToLowerInvariant(); + string argName = arg; + + switch (argName) + { + case "-enable-logging": + EnableLogging = true; + break; + case "-log-dir": + SetLoggingDirectory(args[++i]); + break; + case "-locale": + SetLocale(args[++i]); + break; + case "h": + case "-help": + ShouldExit = true; + return; + default: + ErrorMessage += string.Format("Unknown argument \"{0}\"" + Environment.NewLine, argName); + break; + } + } + } + } + catch (Exception ex) + { + ErrorMessage += ex.ToString(); + return; + } + finally + { + if (!string.IsNullOrEmpty(ErrorMessage) || ShouldExit) + { + Console.WriteLine(Usage); + ShouldExit = true; + } + } + } + + /// + /// Contains any error messages during execution + /// + public string ErrorMessage { get; private set; } + + + /// + /// Whether diagnostic logging is enabled + /// + public bool EnableLogging { get; private set; } + + /// + /// Gets the directory where log files are output. + /// + public string LoggingDirectory { get; private set; } + + /// + /// Whether the program should exit immediately. Set to true when the usage is printed. + /// + public bool ShouldExit { get; private set; } + + /// + /// The locale our we should instantiate this service in + /// + public string Locale { get; private set; } + + /// + /// Name of service that is receiving command options + /// + public string ServiceName { get; private set; } + + /// + /// Get the usage string describing command-line arguments for the program + /// + public string Usage + { + get + { + var str = string.Format("{0}" + Environment.NewLine + + ServiceName + " " + Environment.NewLine + + " Options:" + Environment.NewLine + + " [--enable-logging]" + Environment.NewLine + + " [--log-dir **] (default: current directory)" + Environment.NewLine + + " [--help]" + Environment.NewLine + + " [--locale **] (default: 'en')" + Environment.NewLine, + ErrorMessage); + return str; + } + } + + private void SetLoggingDirectory(string loggingDirectory) + { + if (string.IsNullOrWhiteSpace(loggingDirectory)) + { + return; + } + + this.LoggingDirectory = Path.GetFullPath(loggingDirectory); + } + + public virtual void SetLocale(string locale) + { + try + { + LocaleSetter(locale); + } + catch (CultureNotFoundException) + { + // Ignore CultureNotFoundException since it only is thrown before Windows 10. Windows 10, + // along with macOS and Linux, pick up the default culture if an invalid locale is passed + // into the CultureInfo constructor. + } + } + + /// + /// Sets the Locale field used for testing and also sets the global CultureInfo used for + /// culture-specific messages + /// + /// + internal void LocaleSetter(string locale) + { + // Creating cultureInfo from our given locale + CultureInfo language = new CultureInfo(locale); + Locale = locale; + + // Setting our language globally + CultureInfo.CurrentCulture = language; + CultureInfo.CurrentUICulture = language; + } + } +} diff --git a/src/Microsoft.SqlTools.Hosting.v2/Utility/Extensions.cs b/src/Microsoft.SqlTools.Hosting.v2/Utility/Extensions.cs new file mode 100644 index 00000000..f725498a --- /dev/null +++ b/src/Microsoft.SqlTools.Hosting.v2/Utility/Extensions.cs @@ -0,0 +1,100 @@ +// +// 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; + +namespace Microsoft.SqlTools.Hosting.Utility +{ + public static class ObjectExtensions + { + + public static IEnumerable AsSingleItemEnumerable(this T obj) + { + yield return obj; + } + + /// + /// Extension to evaluate an object's ToString() method in an exception safe way. This will + /// extension method will not throw. + /// + /// The object on which to call ToString() + /// The ToString() return value or a suitable error message is that throws. + public static string SafeToString(this object obj) + { + string str; + + try + { + str = obj.ToString(); + } + catch (Exception ex) + { + str = $""; + } + + return str; + } + + /// + /// Converts a boolean to a "1" or "0" string. Particularly helpful when sending telemetry + /// + public static string ToOneOrZeroString(this bool isTrue) + { + return isTrue ? "1" : "0"; + } + } + + public static class NullableExtensions + { + /// + /// Extension method to evaluate a bool? and determine if it has the value and is true. + /// This way we avoid throwing if the bool? doesn't have a value. + /// + /// The bool? to process + /// + /// true if has a value and it is true + /// false otherwise. + /// + public static bool HasTrue(this bool? obj) + { + return obj.HasValue && obj.Value; + } + } + + public static class ExceptionExtensions + { + /// + /// Returns true if the passed exception or any inner exception is an OperationCanceledException instance. + /// + public static bool IsOperationCanceledException(this Exception e) + { + Exception current = e; + while (current != null) + { + if (current is OperationCanceledException) + { + return true; + } + + current = current.InnerException; + } + + return false; + } + } + + public static class CollectionExtensions { + + public static TValue GetValueOrSpecifiedDefault(this IReadOnlyDictionary map, TKey key) + { + if (map != null && map.ContainsKey(key)) + { + return map[key]; + } + return default(TValue); + } + } +} diff --git a/src/Microsoft.SqlTools.Hosting.v2/Utility/Logger.cs b/src/Microsoft.SqlTools.Hosting.v2/Utility/Logger.cs new file mode 100644 index 00000000..d8c62c43 --- /dev/null +++ b/src/Microsoft.SqlTools.Hosting.v2/Utility/Logger.cs @@ -0,0 +1,299 @@ +// +// 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.Diagnostics; +using System.IO; +using System.Runtime.CompilerServices; +using System.Text; + +namespace Microsoft.SqlTools.Hosting.Utility +{ + /// + /// Defines the level indicators for log messages. + /// + public enum LogLevel + { + /// + /// Indicates a verbose log message. + /// + Verbose, + + /// + /// Indicates a normal, non-verbose log message. + /// + Normal, + + /// + /// Indicates a warning message. + /// + Warning, + + /// + /// Indicates an error message. + /// + Error + } + + /// + /// Provides a simple logging interface. May be replaced with a + /// more robust solution at a later date. + /// + public class Logger + { + private static LogWriter logWriter; + + private static bool isEnabled; + + private static bool isInitialized = false; + + private static Lazy lazyInstance = new Lazy(() => new Logger()); + + public static Logger Instance + { + get + { + return lazyInstance.Value; + } + } + + /// + /// Initializes the Logger for the current session. + /// + /// + /// Optional. Specifies the path at which log messages will be written. + /// + /// + /// Optional. Specifies the minimum log message level to write to the log file. + /// + public void Initialize( + string logFilePath = "sqltools", + LogLevel minimumLogLevel = LogLevel.Normal, + bool isEnabled = true) + { + Logger.isEnabled = isEnabled; + + // return if the logger is not enabled or already initialized + if (!Logger.isEnabled || Logger.isInitialized) + { + return; + } + + Logger.isInitialized = true; + + // Create the log directory + string logDir = Path.GetDirectoryName(logFilePath); + if (!string.IsNullOrWhiteSpace(logDir)) + { + if (!Directory.Exists(logDir)) + { + try + { + Directory.CreateDirectory(logDir); + } + catch (Exception) + { + // Creating the log directory is a best effort operation, so ignore any failures. + } + } + } + + + // get a unique number to prevent conflicts of two process launching at the same time + int uniqueId; + try + { + uniqueId = Process.GetCurrentProcess().Id; + } + catch (Exception) + { + // if the pid look up fails for any reason, just use a random number + uniqueId = new Random().Next(1000, 9999); + } + + // make the log path unique + string fullFileName = string.Format( + "{0}_{1,4:D4}{2,2:D2}{3,2:D2}{4,2:D2}{5,2:D2}{6,2:D2}{7}.log", + logFilePath, + DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, + DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second, + uniqueId); + + if (logWriter != null) + { + logWriter.Dispose(); + } + + // TODO: Parameterize this + logWriter = + new LogWriter( + minimumLogLevel, + fullFileName, + true); + + Write(LogLevel.Normal, "Initializing SQL Tools Service Host logger"); + } + + /// + /// Closes the Logger. + /// + public void Close() + { + if (logWriter != null) + { + logWriter.Dispose(); + } + } + + /// + /// Writes a message to the log file. + /// + /// The level at which the message will be written. + /// The message text to be written. + /// The name of the calling method. + /// The source file path where the calling method exists. + /// The line number of the calling method. + public void Write( + LogLevel logLevel, + string logMessage, + [CallerMemberName] string callerName = null, + [CallerFilePath] string callerSourceFile = null, + [CallerLineNumber] int callerLineNumber = 0) + { + // return if the logger is not enabled or not initialized + if (!Logger.isEnabled || !Logger.isInitialized) + { + return; + } + + if (logWriter != null) + { + logWriter.Write( + logLevel, + logMessage, + callerName, + callerSourceFile, + callerLineNumber); + } + } + } + + internal class LogWriter : IDisposable + { + private object logLock = new object(); + private TextWriter textWriter; + private LogLevel minimumLogLevel = LogLevel.Verbose; + + public LogWriter(LogLevel minimumLogLevel, string logFilePath, bool deleteExisting) + { + this.minimumLogLevel = minimumLogLevel; + + // Ensure that we have a usable log file path + if (!Path.IsPathRooted(logFilePath)) + { + logFilePath = + Path.Combine( + AppContext.BaseDirectory, + logFilePath); + } + + + if (!this.TryOpenLogFile(logFilePath, deleteExisting)) + { + // If the log file couldn't be opened at this location, + // try opening it in a more reliable path + this.TryOpenLogFile( + Path.Combine( + Environment.GetEnvironmentVariable("TEMP"), + Path.GetFileName(logFilePath)), + deleteExisting); + } + } + + public void Write( + LogLevel logLevel, + string logMessage, + string callerName = null, + string callerSourceFile = null, + int callerLineNumber = 0) + { + if (this.textWriter != null && + logLevel >= this.minimumLogLevel) + { + // System.IO is not thread safe + lock (this.logLock) + { + // Print the timestamp and log level + this.textWriter.WriteLine( + "{0} [{1}] - Method \"{2}\" at line {3} of {4}\r\n", + DateTime.Now, + logLevel.ToString().ToUpper(), + callerName, + callerLineNumber, + callerSourceFile); + + // Print out indented message lines + foreach (var messageLine in logMessage.Split('\n')) + { + this.textWriter.WriteLine(" " + messageLine.TrimEnd()); + } + + // Finish with a newline and flush the writer + this.textWriter.WriteLine(); + this.textWriter.Flush(); + } + } + } + + public void Dispose() + { + if (this.textWriter != null) + { + this.textWriter.Flush(); + this.textWriter.Dispose(); + this.textWriter = null; + } + } + + private bool TryOpenLogFile( + string logFilePath, + bool deleteExisting) + { + try + { + // Make sure the log directory exists + Directory.CreateDirectory( + Path.GetDirectoryName( + logFilePath)); + + // Open the log file for writing with UTF8 encoding + this.textWriter = + new StreamWriter( + new FileStream( + logFilePath, + deleteExisting ? + FileMode.Create : + FileMode.Append), + Encoding.UTF8); + + return true; + } + catch (Exception e) + { + if (e is UnauthorizedAccessException || + e is IOException) + { + // This exception is thrown when we can't open the file + // at the path in logFilePath. Return false to indicate + // that the log file couldn't be created. + return false; + } + + // Unexpected exception, rethrow it + throw; + } + } + } +} diff --git a/src/Microsoft.SqlTools.Hosting.v2/Utility/ServiceProviderNotSetException.cs b/src/Microsoft.SqlTools.Hosting.v2/Utility/ServiceProviderNotSetException.cs new file mode 100644 index 00000000..10318cf0 --- /dev/null +++ b/src/Microsoft.SqlTools.Hosting.v2/Utility/ServiceProviderNotSetException.cs @@ -0,0 +1,16 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System; + +namespace Microsoft.SqlTools.Hosting.Utility +{ + public class ServiceProviderNotSetException : InvalidOperationException { + + public ServiceProviderNotSetException() + : base(SR.ServiceProviderNotSet) { + } + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.Hosting.v2/Utility/TaskExtensions.cs b/src/Microsoft.SqlTools.Hosting.v2/Utility/TaskExtensions.cs new file mode 100644 index 00000000..110d06d7 --- /dev/null +++ b/src/Microsoft.SqlTools.Hosting.v2/Utility/TaskExtensions.cs @@ -0,0 +1,99 @@ +// +// 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.Text; +using System.Threading.Tasks; + +namespace Microsoft.SqlTools.Hosting.Utility +{ + public static class TaskExtensions + { + /// + /// Adds handling to check the Exception field of a task and log it if the task faulted + /// + /// + /// This will effectively swallow exceptions in the task chain. + /// + /// The task to continue + /// + /// An optional operation to perform after exception handling has occurred + /// + /// Task with exception handling on continuation + public static Task ContinueWithOnFaulted(this Task antecedent, Action continuationAction) + { + return antecedent.ContinueWith(task => + { + // If the task hasn't faulted or has an exception, skip processing + if (!task.IsFaulted || task.Exception == null) + { + return; + } + + LogTaskExceptions(task.Exception); + + // Run the continuation task that was provided + try + { + continuationAction?.Invoke(task); + } + catch (Exception e) + { + Logger.Instance.Write(LogLevel.Error, $"Exception in exception handling continuation: {e}"); + Logger.Instance.Write(LogLevel.Error, e.StackTrace); + } + }); + } + + /// + /// Adds handling to check the Exception field of a task and log it if the task faulted. + /// This version allows for async code to be ran in the continuation function. + /// + /// + /// This will effectively swallow exceptions in the task chain. + /// + /// The task to continue + /// + /// An optional operation to perform after exception handling has occurred + /// + /// Task with exception handling on continuation + public static Task ContinueWithOnFaulted(this Task antecedent, Func continuationFunc) + { + return antecedent.ContinueWith(task => + { + // If the task hasn't faulted or doesn't have an exception, skip processing + if (!task.IsFaulted || task.Exception == null) + { + return; + } + + LogTaskExceptions(task.Exception); + + // Run the continuation task that was provided + try + { + continuationFunc?.Invoke(antecedent).Wait(); + } + catch (Exception e) + { + Logger.Instance.Write(LogLevel.Error, $"Exception in exception handling continuation: {e}"); + Logger.Instance.Write(LogLevel.Error, e.StackTrace); + } + }); + } + + private static void LogTaskExceptions(AggregateException exception) + { + // Construct an error message for an aggregate exception and log it + StringBuilder sb = new StringBuilder("Unhandled exception(s) in async task:"); + foreach (Exception e in exception.InnerExceptions) + { + sb.AppendLine($"{e.GetType().Name}: {e.Message}"); + sb.AppendLine(e.StackTrace); + } + Logger.Instance.Write(LogLevel.Error, sb.ToString()); + } + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.Hosting.v2/Utility/Validate.cs b/src/Microsoft.SqlTools.Hosting.v2/Utility/Validate.cs new file mode 100644 index 00000000..f90929fd --- /dev/null +++ b/src/Microsoft.SqlTools.Hosting.v2/Utility/Validate.cs @@ -0,0 +1,158 @@ +// +// 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; + +namespace Microsoft.SqlTools.Hosting.Utility +{ + /// + /// Provides common validation methods to simplify method + /// parameter checks. + /// + public static class Validate + { + /// + /// Throws ArgumentNullException if value is null. + /// + /// The name of the parameter being validated. + /// The value of the parameter being validated. + public static void IsNotNull(string parameterName, object valueToCheck) + { + if (valueToCheck == null) + { + throw new ArgumentNullException(parameterName); + } + } + + /// + /// Throws ArgumentOutOfRangeException if the value is outside + /// of the given lower and upper limits. + /// + /// The name of the parameter being validated. + /// The value of the parameter being validated. + /// The lower limit which the value should not be less than. + /// The upper limit which the value should not be greater than. + public static void IsWithinRange( + string parameterName, + long valueToCheck, + long lowerLimit, + long upperLimit) + { + // TODO: Debug assert here if lowerLimit >= upperLimit + + if (valueToCheck < lowerLimit || valueToCheck > upperLimit) + { + throw new ArgumentOutOfRangeException( + parameterName, + valueToCheck, + string.Format( + "Value is not between {0} and {1}", + lowerLimit, + upperLimit)); + } + } + + /// + /// Throws ArgumentOutOfRangeException if the value is greater than or equal + /// to the given upper limit. + /// + /// The name of the parameter being validated. + /// The value of the parameter being validated. + /// The upper limit which the value should be less than. + public static void IsLessThan( + string parameterName, + long valueToCheck, + long upperLimit) + { + if (valueToCheck >= upperLimit) + { + throw new ArgumentOutOfRangeException( + parameterName, + valueToCheck, + string.Format( + "Value is greater than or equal to {0}", + upperLimit)); + } + } + + /// + /// Throws ArgumentOutOfRangeException if the value is less than or equal + /// to the given lower limit. + /// + /// The name of the parameter being validated. + /// The value of the parameter being validated. + /// The lower limit which the value should be greater than. + public static void IsGreaterThan( + string parameterName, + long valueToCheck, + long lowerLimit) + { + if (valueToCheck < lowerLimit) + { + throw new ArgumentOutOfRangeException( + parameterName, + valueToCheck, + string.Format( + "Value is less than or equal to {0}", + lowerLimit)); + } + } + + /// + /// Throws ArgumentException if the value is equal to the undesired value. + /// + /// The type of value to be validated. + /// The name of the parameter being validated. + /// The value that valueToCheck should not equal. + /// The value of the parameter being validated. + public static void IsNotEqual( + string parameterName, + TValue valueToCheck, + TValue undesiredValue) + { + if (EqualityComparer.Default.Equals(valueToCheck, undesiredValue)) + { + throw new ArgumentException( + string.Format( + "The given value '{0}' should not equal '{1}'", + valueToCheck, + undesiredValue), + parameterName); + } + } + + /// + /// Throws ArgumentException if the value is null or an empty string. + /// + /// The name of the parameter being validated. + /// The value of the parameter being validated. + public static void IsNotNullOrEmptyString(string parameterName, string valueToCheck) + { + if (string.IsNullOrEmpty(valueToCheck)) + { + throw new ArgumentException( + "Parameter contains a null, empty, or whitespace string.", + parameterName); + } + } + + /// + /// Throws ArgumentException if the value is null, an empty string, + /// or a string containing only whitespace. + /// + /// The name of the parameter being validated. + /// The value of the parameter being validated. + public static void IsNotNullOrWhitespaceString(string parameterName, string valueToCheck) + { + if (string.IsNullOrWhiteSpace(valueToCheck)) + { + throw new ArgumentException( + "Parameter contains a null, empty, or whitespace string.", + parameterName); + } + } + } +} diff --git a/src/Microsoft.SqlTools.Hosting/Microsoft.SqlTools.Hosting.csproj b/src/Microsoft.SqlTools.Hosting/Microsoft.SqlTools.Hosting.csproj index 77888fcf..8a4f3589 100644 --- a/src/Microsoft.SqlTools.Hosting/Microsoft.SqlTools.Hosting.csproj +++ b/src/Microsoft.SqlTools.Hosting/Microsoft.SqlTools.Hosting.csproj @@ -12,7 +12,6 @@ portable - diff --git a/src/sqltools.common.targets b/src/sqltools.common.targets new file mode 100644 index 00000000..b9bd184e --- /dev/null +++ b/src/sqltools.common.targets @@ -0,0 +1,21 @@ + + + + + Microsoft Corporation + Microsoft SQL Server + + + 1.1.0 + + + + Microsoft + false + © Microsoft Corporation. All rights reserved. + https://github.com/Microsoft/sqltoolsservice/blob/master/license.txt + http://s.gravatar.com/avatar/6f39d8562df0a3509a8240fb281bc5bd?s=80 + https://github.com/Microsoft/sqltoolsservice/ + SQL XPLAT + + diff --git a/test/Microsoft.SqlTools.Hosting.UnitTests/CommonObjects.cs b/test/Microsoft.SqlTools.Hosting.UnitTests/CommonObjects.cs new file mode 100644 index 00000000..0e030e74 --- /dev/null +++ b/test/Microsoft.SqlTools.Hosting.UnitTests/CommonObjects.cs @@ -0,0 +1,67 @@ +// +// 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 Microsoft.SqlTools.Hosting.Contracts; +using Microsoft.SqlTools.Hosting.Contracts.Internal; +using Microsoft.SqlTools.Hosting.Protocol; +using Newtonsoft.Json.Linq; + +namespace Microsoft.SqlTools.Hosting.UnitTests +{ + public static class CommonObjects + { + public const string MessageId = "123"; + + public static readonly RequestType RequestType = + RequestType.Create("test/request"); + + public static readonly EventType EventType = + EventType.Create("test/event"); + + public static readonly Message RequestMessage = + Message.CreateRequest(RequestType, MessageId, TestMessageContents.DefaultInstance); + + public static readonly Message ResponseMessage = + Message.CreateResponse(MessageId, TestMessageContents.DefaultInstance); + + public static readonly Message EventMessage = + Message.CreateEvent(EventType, TestMessageContents.DefaultInstance); + + public static class TestErrorContents + { + public static readonly JToken SerializedContents = JToken.Parse("{\"code\": 123, \"message\": \"error\"}"); + public static readonly Error DefaultInstance = new Error {Code = 123, Message = "error"}; + } + + public class TestMessageContents : IEquatable + { + public const string JsonContents = "{\"someField\": \"Some value\", \"number\": 42}"; + public static readonly JToken SerializedContents = JToken.Parse(JsonContents); + public static readonly TestMessageContents DefaultInstance = new TestMessageContents {Number = 42, SomeField = "Some value"}; + + public string SomeField { get; set; } + public int Number { get; set; } + + public bool Equals(TestMessageContents other) + { + return string.Equals(SomeField, other.SomeField) + && Number == other.Number; + } + + public static bool operator ==(TestMessageContents obj1, TestMessageContents obj2) + { + bool bothNull = ReferenceEquals(obj1, null) && ReferenceEquals(obj2, null); + bool someNull = ReferenceEquals(obj1, null) || ReferenceEquals(obj2, null); + return bothNull || !someNull && obj1.Equals(obj2); + } + + public static bool operator !=(TestMessageContents obj1, TestMessageContents obj2) + { + return !(obj1 == obj2); + } + } + } +} \ No newline at end of file diff --git a/test/Microsoft.SqlTools.Hosting.UnitTests/ExtensibilityTests/ServiceProviderTests.cs b/test/Microsoft.SqlTools.Hosting.UnitTests/ExtensibilityTests/ServiceProviderTests.cs new file mode 100644 index 00000000..81877be8 --- /dev/null +++ b/test/Microsoft.SqlTools.Hosting.UnitTests/ExtensibilityTests/ServiceProviderTests.cs @@ -0,0 +1,116 @@ +// +// 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.Linq; +using Microsoft.SqlTools.Hosting.Extensibility; +using Microsoft.SqlTools.Hosting.Utility; +using Xunit; + +namespace Microsoft.SqlTools.Hosting.UnitTests.ExtensibilityTests +{ + public class ServiceProviderTests + { + private readonly RegisteredServiceProvider provider; + public ServiceProviderTests() + { + provider = new RegisteredServiceProvider(); + } + + [Fact] + public void GetServiceShouldReturnNullIfNoServicesRegistered() + { + // Given no service registered + // When I call GetService + var service = provider.GetService(); + // Then I expect null to be returned + Assert.Null(service); + } + + + [Fact] + public void GetSingleServiceThrowsMultipleServicesRegistered() + { + // Given 2 services registered + provider.Register(() => new[] { new MyProviderService(), new MyProviderService() }); + // When I call GetService + // Then I expect to throw + Assert.Throws(() => provider.GetService()); + } + + [Fact] + public void GetServicesShouldReturnEmptyIfNoServicesRegistered() + { + // Given no service regisstered + // When I call GetService + var services = provider.GetServices(); + // Then I expect empty enumerable to be returned + Assert.NotNull(services); + Assert.Equal(0, services.Count()); + } + + [Fact] + public void GetServiceShouldReturnRegisteredService() + { + MyProviderService service = new MyProviderService(); + provider.RegisterSingleService(service); + + var returnedService = provider.GetService(); + Assert.Equal(service, returnedService); + } + + [Fact] + public void GetServicesShouldReturnRegisteredServiceWhenMultipleServicesRegistered() + { + MyProviderService service = new MyProviderService(); + provider.RegisterSingleService(service); + + var returnedServices = provider.GetServices(); + Assert.Equal(service, returnedServices.Single()); + } + + [Fact] + public void RegisterServiceProviderShouldThrowIfServiceIsIncompatible() + { + MyProviderService service = new MyProviderService(); + Assert.Throws(() => provider.RegisterSingleService(typeof(OtherService), service)); + } + [Fact] + public void RegisterServiceProviderShouldThrowIfServiceAlreadyRegistered() + { + MyProviderService service = new MyProviderService(); + provider.RegisterSingleService(service); + + Assert.Throws(() => provider.RegisterSingleService(service)); + } + + [Fact] + public void RegisterShouldThrowIfServiceAlreadyRegistered() + { + MyProviderService service = new MyProviderService(); + provider.RegisterSingleService(service); + + Assert.Throws(() => provider.Register(() => service.AsSingleItemEnumerable())); + } + + [Fact] + public void RegisterShouldThrowIfServicesAlreadyRegistered() + { + provider.Register(() => new [] { new MyProviderService(), new MyProviderService() }); + Assert.Throws(() => provider.Register(() => new MyProviderService().AsSingleItemEnumerable())); + } + } + + + public class MyProviderService + { + + } + + public class OtherService + { + + } +} diff --git a/test/Microsoft.SqlTools.Hosting.UnitTests/Microsoft.SqlTools.Hosting.UnitTests.csproj b/test/Microsoft.SqlTools.Hosting.UnitTests/Microsoft.SqlTools.Hosting.UnitTests.csproj new file mode 100644 index 00000000..63dcfea2 --- /dev/null +++ b/test/Microsoft.SqlTools.Hosting.UnitTests/Microsoft.SqlTools.Hosting.UnitTests.csproj @@ -0,0 +1,17 @@ + + + netcoreapp2.1 + false + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/Microsoft.SqlTools.Hosting.UnitTests/ProtocolTests/EventContextTests.cs b/test/Microsoft.SqlTools.Hosting.UnitTests/ProtocolTests/EventContextTests.cs new file mode 100644 index 00000000..230f7792 --- /dev/null +++ b/test/Microsoft.SqlTools.Hosting.UnitTests/ProtocolTests/EventContextTests.cs @@ -0,0 +1,30 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System.Collections.Concurrent; +using Microsoft.SqlTools.Hosting.Protocol; +using Xunit; + +namespace Microsoft.SqlTools.Hosting.UnitTests.ProtocolTests +{ + public class EventContextTests + { + [Fact] + public void SendEvent() + { + // Setup: Create collection + var bc = new BlockingCollection(new ConcurrentQueue()); + + // If: I construct an event context with a message writer + // And send an event with it + var eventContext = new EventContext(bc); + eventContext.SendEvent(CommonObjects.EventType, CommonObjects.TestMessageContents.DefaultInstance); + + // Then: The message should be added to the queue + Assert.Equal(1, bc.ToArray().Length); + Assert.Equal(MessageType.Event, bc.ToArray()[0].MessageType); + } + } +} \ No newline at end of file diff --git a/test/Microsoft.SqlTools.Hosting.UnitTests/ProtocolTests/JsonRpcHostTests.cs b/test/Microsoft.SqlTools.Hosting.UnitTests/ProtocolTests/JsonRpcHostTests.cs new file mode 100644 index 00000000..a5321221 --- /dev/null +++ b/test/Microsoft.SqlTools.Hosting.UnitTests/ProtocolTests/JsonRpcHostTests.cs @@ -0,0 +1,828 @@ +// +// 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.IO; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.SqlTools.Hosting.Channels; +using Microsoft.SqlTools.Hosting.Protocol; +using Microsoft.SqlTools.ServiceLayer.Test.Common; +using Moq; +using Xunit; + +namespace Microsoft.SqlTools.Hosting.UnitTests.ProtocolTests +{ + public class JsonRpcHostTests + { + [Fact] + public void ConstructWithNullProtocolChannel() + { + // If: I construct a JSON RPC host with a null protocol channel + // Then: I should get an exception + Assert.Throws(() => new JsonRpcHost(null)); + } + + #region SetRequestHandler Tests + + [Fact] + public void SetAsyncRequestHandlerNullRequestType() + { + // If: I assign a request handler on the JSON RPC host with a null request type + // Then: I should get an exception + var jh = new JsonRpcHost(GetChannelBase(null, null).Object); + Assert.Throws(() => + jh.SetAsyncRequestHandler(null, (a, b) => Task.FromResult(false))); + } + + [Fact] + public void SetAsyncRequestHandlerNullRequestHandler() + { + // If: I assign a request handler on the JSON RPC host with a null request handler + // Then: I should get an exception + var jh = new JsonRpcHost(GetChannelBase(null, null).Object); + Assert.Throws(() => jh.SetAsyncRequestHandler(CommonObjects.RequestType, null)); + } + + [Fact] + public void SetSyncRequestHandlerNullRequestHandler() + { + // If: I assign a request handler on the JSON RPC host with a null request handler + // Then: I should get an exception + var jh = new JsonRpcHost(GetChannelBase(null, null).Object); + Assert.Throws(() => jh.SetRequestHandler(CommonObjects.RequestType, null)); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public async Task SetAsyncRequestHandler(bool nullContents) + { + // Setup: Create a mock request handler + var requestHandler = new Mock, Task>>(); + var message = nullContents + ? Message.CreateRequest(CommonObjects.RequestType, CommonObjects.MessageId, null) + : CommonObjects.RequestMessage; + + // If: I assign a request handler on the JSON RPC host + var jh = new JsonRpcHost(GetChannelBase(null, null).Object); + jh.SetAsyncRequestHandler(CommonObjects.RequestType, requestHandler.Object); + + // Then: It should be the only request handler set + Assert.Equal(1, jh.requestHandlers.Count); + Assert.Contains(CommonObjects.RequestType.MethodName, jh.requestHandlers.Keys); + + // If: I call the stored request handler + await jh.requestHandlers[CommonObjects.RequestType.MethodName](message); + await jh.requestHandlers[CommonObjects.RequestType.MethodName](message); + + // Then: The request handler should have been called with the params and a proper request context + var expectedContents = nullContents + ? null + : CommonObjects.TestMessageContents.DefaultInstance; + requestHandler.Verify(a => a( + It.Is(p => p == expectedContents), + It.Is>(rc => rc.messageQueue == jh.outputQueue && rc.requestMessage == message) + ), Times.Exactly(2)); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public async Task SetSyncRequestHandler(bool nullContents) + { + // Setup: Create a mock request handler + var requestHandler = new Mock>>(); + var message = nullContents + ? Message.CreateRequest(CommonObjects.RequestType, CommonObjects.MessageId, null) + : CommonObjects.RequestMessage; + + // If: I assign a request handler on the JSON RPC host + var jh = new JsonRpcHost(GetChannelBase(null, null).Object); + jh.SetRequestHandler(CommonObjects.RequestType, requestHandler.Object); + + // Then: It should be the only request handler set + Assert.Equal(1, jh.requestHandlers.Count); + Assert.Contains(CommonObjects.RequestType.MethodName, jh.requestHandlers.Keys); + + // If: I call the stored request handler + await jh.requestHandlers[CommonObjects.RequestType.MethodName](message); + await jh.requestHandlers[CommonObjects.RequestType.MethodName](message); + + // Then: The request handler should have been called with the params and a proper request context + var expectedContents = nullContents + ? null + : CommonObjects.TestMessageContents.DefaultInstance; + requestHandler.Verify(a => a( + It.Is(p => p == expectedContents), + It.Is>(rc => rc.messageQueue == jh.outputQueue && rc.requestMessage == message) + ), Times.Exactly(2)); + } + + [Fact] + public async Task SetAsyncRequestHandlerOverrideTrue() + { + // Setup: Create two mock request handlers + var requestHandler1 = new Mock, Task>>(); + var requestHandler2 = new Mock, Task>>(); + + // If: + // ... I assign a request handler on the JSON RPC host + // ... And I reassign the request handler with an override + var jh = new JsonRpcHost(GetChannelBase(null, null).Object); + jh.SetAsyncRequestHandler(CommonObjects.RequestType, requestHandler1.Object); + jh.SetAsyncRequestHandler(CommonObjects.RequestType, requestHandler2.Object, true); + + // Then: There should only be one request handler + Assert.Equal(1, jh.requestHandlers.Count); + Assert.Contains(CommonObjects.RequestType.MethodName, jh.requestHandlers.Keys); + + // If: I call the stored request handler + await jh.requestHandlers[CommonObjects.RequestType.MethodName](CommonObjects.RequestMessage); + + // Then: The correct request handler should have been called + requestHandler2.Verify(a => a( + It.Is(p => p.Equals(CommonObjects.TestMessageContents.DefaultInstance)), + It.Is>(p => p.messageQueue == jh.outputQueue && p.requestMessage == CommonObjects.RequestMessage) + ), Times.Once); + requestHandler1.Verify(a => a( + It.IsAny(), + It.IsAny>() + ), Times.Never); + } + + [Fact] + public void SetAsyncRequestHandlerOverrideFalse() + { + // Setup: Create a mock request handler + var requestHandler = new Mock, Task>>(); + + // If: + // ... I assign a request handler on the JSON RPC host + // ... And I reassign the request handler without overriding + // Then: I should get an exception + var jh = new JsonRpcHost(GetChannelBase(null, null).Object); + jh.SetAsyncRequestHandler(CommonObjects.RequestType, requestHandler.Object); + Assert.ThrowsAny(() => jh.SetAsyncRequestHandler(CommonObjects.RequestType, requestHandler.Object)); + } + + #endregion + + #region SetEventHandler Tests + + [Fact] + public void SetAsyncEventHandlerNullEventType() + { + // If: I assign an event handler on the JSON RPC host with a null event type + // Then: I should get an exception + var jh = new JsonRpcHost(GetChannelBase(null, null).Object); + Assert.Throws(() => + jh.SetAsyncEventHandler(null, (a, b) => Task.FromResult(false))); + } + + [Fact] + public void SetAsyncEventHandlerNull() + { + // If: I assign an event handler on the message gispatcher with a null event handler + var jh = new JsonRpcHost(GetChannelBase(null, null).Object); + Assert.Throws(() => jh.SetAsyncEventHandler(CommonObjects.EventType, null)); + } + + [Fact] + public void SetSyncEventHandlerNull() + { + // If: I assign an event handler on the message gispatcher with a null event handler + var jh = new JsonRpcHost(GetChannelBase(null, null).Object); + Assert.Throws(() => jh.SetEventHandler(CommonObjects.EventType, null)); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task SetAsyncEventHandler(bool nullContents) + { + // Setup: Create a mock request handler + var eventHandler = new Mock>(); + var message = nullContents + ? Message.CreateEvent(CommonObjects.EventType, null) + : CommonObjects.EventMessage; + + // If: I assign an event handler on the JSON RPC host + var jh = new JsonRpcHost(GetChannelBase(null, null).Object); + jh.SetAsyncEventHandler(CommonObjects.EventType, eventHandler.Object); + + // Then: It should be the only event handler set + Assert.Equal(1, jh.eventHandlers.Count); + Assert.Contains(CommonObjects.EventType.MethodName, jh.eventHandlers.Keys); + + // If: I call the stored event handler + await jh.eventHandlers[CommonObjects.EventType.MethodName](message); + await jh.eventHandlers[CommonObjects.EventType.MethodName](message); + + // Then: The event handler should have been called with the params and a proper event context + var expectedContents = nullContents + ? null + : CommonObjects.TestMessageContents.DefaultInstance; + eventHandler.Verify(a => a( + It.Is(p => p == expectedContents), + It.Is(p => p.messageQueue == jh.outputQueue) + ), Times.Exactly(2)); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task SetSyncEventHandler(bool nullContents) + { + // Setup: Create a mock request handler + var eventHandler = new Mock>(); + var message = nullContents + ? Message.CreateEvent(CommonObjects.EventType, null) + : CommonObjects.EventMessage; + + // If: I assign an event handler on the JSON RPC host + var jh = new JsonRpcHost(GetChannelBase(null, null).Object); + jh.SetEventHandler(CommonObjects.EventType, eventHandler.Object); + + // Then: It should be the only event handler set + Assert.Equal(1, jh.eventHandlers.Count); + Assert.Contains(CommonObjects.EventType.MethodName, jh.eventHandlers.Keys); + + // If: I call the stored event handler + await jh.eventHandlers[CommonObjects.EventType.MethodName](message); + await jh.eventHandlers[CommonObjects.EventType.MethodName](message); + + // Then: The event handler should have been called with the params and a proper event context + var expectedContents = nullContents + ? null + : CommonObjects.TestMessageContents.DefaultInstance; + eventHandler.Verify(a => a( + It.Is(p => p == expectedContents), + It.Is(p => p.messageQueue == jh.outputQueue) + ), Times.Exactly(2)); + } + + [Fact] + public async Task SetAsyncEventHandlerOverrideTrue() + { + // Setup: Create two mock event handlers + var eventHandler1 = new Mock>(); + var eventHandler2 = new Mock>(); + + // If: + // ... I assign an event handler on the JSON RPC host + // ... And I reassign the event handler with an override + var jh = new JsonRpcHost(GetChannelBase(null, null).Object); + + jh.SetAsyncEventHandler(CommonObjects.EventType, eventHandler1.Object); + jh.SetAsyncEventHandler(CommonObjects.EventType, eventHandler2.Object, true); + + // Then: There should only be one event handler + Assert.Equal(1, jh.eventHandlers.Count); + Assert.Contains(CommonObjects.EventType.MethodName, jh.eventHandlers.Keys); + + // If: I call the stored event handler + await jh.eventHandlers[CommonObjects.EventType.MethodName](CommonObjects.EventMessage); + + // Then: The correct event handler should have been called + eventHandler2.Verify(a => a( + It.Is(p => p.Equals(CommonObjects.TestMessageContents.DefaultInstance)), + It.Is(p => p.messageQueue == jh.outputQueue) + ), Times.Once); + eventHandler1.Verify(a => a( + It.IsAny(), + It.IsAny() + ), Times.Never); + } + + [Fact] + public void SetAsyncEventHandlerOverrideFalse() + { + // Setup: Create a mock event handler + var eventHandler = new Mock>(); + + // If: + // ... I assign an event handler on the JSON RPC host + // ... And I reassign the event handler without overriding + // Then: I should get an exception + var jh = new JsonRpcHost(GetChannelBase(null, null).Object); + jh.SetAsyncEventHandler(CommonObjects.EventType, eventHandler.Object); + Assert.ThrowsAny(() => jh.SetAsyncEventHandler(CommonObjects.EventType, eventHandler.Object)); + } + + #endregion + + #region SendEvent Tests + + [Fact] + public void SendEventNotConnected() + { + // If: I send an event when the protocol channel isn't connected + // Then: I should get an exception + var jh = new JsonRpcHost(GetChannelBase(null, null).Object); + Assert.Throws(() => jh.SendEvent(CommonObjects.EventType, CommonObjects.TestMessageContents.DefaultInstance)); + } + + [Fact] + public void SendEvent() + { + // Setup: Create a Json RPC Host with a connected channel + var jh = new JsonRpcHost(GetChannelBase(null, null, true).Object); + + // If: I send an event + jh.SendEvent(CommonObjects.EventType, CommonObjects.TestMessageContents.DefaultInstance); + + // Then: The message should be added to the output queue + Assert.Equal(1, jh.outputQueue.ToArray().Length); + var m = jh.outputQueue.ToArray()[0]; + Assert.Equal(CommonObjects.TestMessageContents.SerializedContents, m.Contents); + Assert.Equal(CommonObjects.EventType.MethodName, m.Method); + } + + #endregion + + #region SendRequest Tests + + [Fact] + public async Task SendRequestNotConnected() + { + // If: I send an event when the protocol channel isn't connected + // Then: I should get an exception + var jh = new JsonRpcHost(GetChannelBase(null, null).Object); + await Assert.ThrowsAsync(() => jh.SendRequest(CommonObjects.RequestType, CommonObjects.TestMessageContents.DefaultInstance)); + } + + [Fact] + public async Task SendRequest() + { + // If: I send a request with the JSON RPC host + var jh = new JsonRpcHost(GetChannelBase(null, null, true).Object); + Task requestTask = jh.SendRequest(CommonObjects.RequestType, CommonObjects.TestMessageContents.DefaultInstance); + + // Then: There should be a pending request + Assert.Equal(1, jh.pendingRequests.Count); + + // If: I then trick it into completing the request + jh.pendingRequests.First().Value.SetResult(CommonObjects.ResponseMessage); + var responseContents = await requestTask; + + // Then: The returned results should be the contents of the message + Assert.Equal(CommonObjects.TestMessageContents.DefaultInstance, responseContents); + } + + #endregion + + #region DispatchMessage Tests + + [Fact] + public async Task DispatchMessageRequestWithoutHandler() + { + // Setup: Create a JSON RPC host without a request handler + var jh = new JsonRpcHost(GetChannelBase(null, null).Object); + + // If: I dispatch a request that doesn't have a handler + // Then: I should get an exception + await Assert.ThrowsAsync(() => jh.DispatchMessage(CommonObjects.RequestMessage)); + } + + [Fact] + public async Task DispatchMessageRequestException() + { + // Setup: Create a JSON RPC host with a request handler that throws an unhandled exception every time + var jh = new JsonRpcHost(GetChannelBase(null, null).Object); + var mockHandler = new Mock, Task>>(); + mockHandler.Setup(f => f( + It.IsAny(), + It.IsAny>() + )) + .Returns(Task.FromException(new Exception())); + jh.SetAsyncRequestHandler(CommonObjects.RequestType, mockHandler.Object); + + // If: I dispatch a message whose handler throws + // Then: I should get an exception + await Assert.ThrowsAsync(() => jh.DispatchMessage(CommonObjects.RequestMessage)); + } + + [Theory] + [MemberData(nameof(DispatchMessageWithHandlerData))] + public async Task DispatchMessageRequestWithHandler(Task result) + { + // Setup: Create a JSON RPC host with a request handler setup + var jh = new JsonRpcHost(GetChannelBase(null, null).Object); + var mockHandler = new Mock, Task>>(); + mockHandler.Setup(f => f( + It.Is(m => m == CommonObjects.TestMessageContents.DefaultInstance), + It.Is>(rc => rc.messageQueue == jh.outputQueue) + )).Returns(result); + jh.SetAsyncRequestHandler(CommonObjects.RequestType, mockHandler.Object); + + // If: I dispatch a request + await jh.DispatchMessage(CommonObjects.RequestMessage); + + // Then: The request handler should have been called + mockHandler.Verify(f => f( + It.Is(m => m == CommonObjects.TestMessageContents.DefaultInstance), + It.IsAny>() + ), Times.Once); + } + + [Fact] + public async Task DispatchmessageResponseWithoutHandler() + { + // Setup: Create a new JSON RPC host without any pending requests + var jh = new JsonRpcHost(GetChannelBase(null, null).Object); + + // If: I dispatch a response that doesn't have a pending request + // Then: I should get an exception + await Assert.ThrowsAsync(() => jh.DispatchMessage(CommonObjects.ResponseMessage)); + } + + [Fact] + public async Task DispatchMessageResponseWithHandler() + { + // Setup: Create a new JSON RPC host that has a pending request handler + var jh = new JsonRpcHost(GetChannelBase(null, null).Object); + var mockPendingRequest = new TaskCompletionSource(); + jh.pendingRequests.TryAdd(CommonObjects.MessageId, mockPendingRequest); + + // If: I dispatch a response + await jh.DispatchMessage(CommonObjects.ResponseMessage); + + // Then: The task completion source should have completed with the message that was given + await mockPendingRequest.Task.WithTimeout(TimeSpan.FromSeconds(1)); + Assert.Equal(CommonObjects.ResponseMessage, mockPendingRequest.Task.Result); + } + + [Fact] + public async Task DispatchMessageEventWithoutHandler() + { + // Setup: Create a JSON RPC host without a request handler + var jh = new JsonRpcHost(GetChannelBase(null, null).Object); + + // If: I dispatch a request that doesn't have a handler + // Then: I should get an exception + await Assert.ThrowsAsync(() => jh.DispatchMessage(CommonObjects.EventMessage)); + } + + [Fact] + public async Task DispatchMessageEventException() + { + // Setup: Create a JSON RPC host with a request handler that throws an unhandled exception every time + var jh = new JsonRpcHost(GetChannelBase(null, null).Object); + var mockHandler = new Mock>(); + mockHandler.Setup(f => f(It.IsAny(), It.IsAny())) + .Returns(Task.FromException(new Exception())); + jh.SetAsyncEventHandler(CommonObjects.EventType, mockHandler.Object); + + // If: I dispatch a message whose handler throws + // Then: I should get an exception + await Assert.ThrowsAsync(() => jh.DispatchMessage(CommonObjects.EventMessage)); + } + + [Theory] + [MemberData(nameof(DispatchMessageWithHandlerData))] + public async Task DispatchMessageEventWithHandler(Task result) + { + // Setup: Create a JSON RPC host with an event handler setup + var jh = new JsonRpcHost(GetChannelBase(null, null).Object); + var mockHandler = new Mock>(); + mockHandler.Setup(f => f( + It.Is(m => m == CommonObjects.TestMessageContents.DefaultInstance), + It.Is(ec => ec.messageQueue == jh.outputQueue) + )).Returns(result); + jh.SetAsyncEventHandler(CommonObjects.EventType, mockHandler.Object); + + // If: I dispatch an event + await jh.DispatchMessage(CommonObjects.EventMessage); + + // Then: The event handler should have been called + mockHandler.Verify(f => f( + It.Is(m => m == CommonObjects.TestMessageContents.DefaultInstance), + It.IsAny() + )); + } + + public static IEnumerable DispatchMessageWithHandlerData + { + get + { + yield return new object[] {Task.FromResult(true)}; // Successful completion + yield return new object[] {Task.FromException(new TaskCanceledException())}; // Cancelled result + yield return new object[] {Task.FromException(new AggregateException(new TaskCanceledException()))}; // Cancelled somewhere inside + } + } + + #endregion + + #region ConsumeInput Loop Tests + + [Fact] + public async Task ConsumeInput() + { + // Setup: + // ... Create a message reader that will return a message every time + var mr = new Mock(Stream.Null, null); + var waitForRead = new TaskCompletionSource(); + mr.Setup(o => o.ReadMessage()) + .Callback(() => waitForRead.TrySetResult(true)) + .ReturnsAsync(CommonObjects.EventMessage); + + // ... Create a no-op event handler to handle the message from the message reader + var noOpHandler = new Mock>(); + noOpHandler.Setup(f => f(It.IsAny())).Returns(Task.FromResult(true)); + + // ... Wire up the event handler to a new JSON RPC host + var jh = new JsonRpcHost(GetChannelBase(mr.Object, null).Object); + jh.eventHandlers[CommonObjects.EventType.MethodName] = noOpHandler.Object; + + // If: + // ... I start the input consumption thread + Task consumeInputTask = jh.ConsumeInput(); + + // ... Wait for the handler to be called once, indicating the message was processed + await waitForRead.Task.WithTimeout(TimeSpan.FromSeconds(1)); + + // ... Stop the input consumption thread (the hard way) and wait for completion + jh.cancellationTokenSource.Cancel(); + await consumeInputTask.WithTimeout(TimeSpan.FromSeconds(1)); + + // Then: The event handler and read message should have been called at least once + noOpHandler.Verify(f => f(It.IsAny()), Times.AtLeastOnce); + mr.Verify(o => o.ReadMessage(), Times.AtLeastOnce); + } + + [Fact] + public async Task ConsumeInputEndOfStream() + { + // Setup: Create a message reader that will throw an end of stream exception on read + var mr = new Mock(Stream.Null, null); + mr.Setup(o => o.ReadMessage()).Returns(Task.FromException(new EndOfStreamException())); + + // If: I start the input consumption thread + // Then: + // ... It should stop gracefully + var jh = new JsonRpcHost(GetChannelBase(mr.Object, null).Object); + await jh.ConsumeInput().WithTimeout(TimeSpan.FromSeconds(1)); + + // ... The read message should have only been called once + mr.Verify(o => o.ReadMessage(), Times.Once); + } + + [Fact] + public async Task ConsumeInputException() + { + // Setup: + // ... Create a message reader that will throw an exception on first read + // ... throw an end of stream on second read + var mr = new Mock(Stream.Null, null); + mr.SetupSequence(o => o.ReadMessage()) + .Returns(Task.FromException(new Exception())) + .Returns(Task.FromException(new EndOfStreamException())); + + // If: I start the input consumption loop + var jh = new JsonRpcHost(GetChannelBase(mr.Object, null).Object); + await jh.ConsumeInput().WithTimeout(TimeSpan.FromSeconds(1)); + + // Then: + // ... Read message should have been called twice + mr.Verify(o => o.ReadMessage(), Times.Exactly(2)); + } + + [Fact] + public async Task ConsumeInputRequestMethodNotFound() + { + // Setup: Create a message reader that will return a request with method that doesn't exist + var mr = new Mock(Stream.Null, null); + mr.SetupSequence(o => o.ReadMessage()) + .ReturnsAsync(CommonObjects.RequestMessage) + .Returns(Task.FromException(new EndOfStreamException())); + + // If: I start the input consumption loop + var jh = new JsonRpcHost(GetChannelBase(mr.Object, null).Object); + await jh.ConsumeInput().WithTimeout(TimeSpan.FromSeconds(1)); + + // Then: + // ... Read message should have been called twice + mr.Verify(o => o.ReadMessage(), Times.Exactly(2)); + + // ... There should be an outgoing message with the error + var outgoing = jh.outputQueue.ToArray(); + Assert.Equal(1, outgoing.Length); + Assert.Equal(MessageType.ResponseError, outgoing[0].MessageType); + Assert.Equal(CommonObjects.MessageId, outgoing[0].Id); + Assert.Equal(-32601, outgoing[0].Contents.Value("code")); + } + + [Fact] + public async Task ConsumeInputRequestException() + { + // Setup: + // ... Create a message reader that will return a request + var mr = new Mock(Stream.Null, null); + mr.SetupSequence(o => o.ReadMessage()) + .ReturnsAsync(CommonObjects.RequestMessage) + .Returns(Task.FromException(new EndOfStreamException())); + + // ... Create a JSON RPC host and register the request handler to throw exception + var jh = new JsonRpcHost(GetChannelBase(mr.Object, null).Object); + var mockHandler = new Mock>>(); + mockHandler.Setup(m => m(It.IsAny(), + It.IsAny>())) + .Throws(new Exception()); + jh.SetRequestHandler(CommonObjects.RequestType, mockHandler.Object); + + // If: I start the input consumption loop + await jh.ConsumeInput().WithTimeout(TimeSpan.FromSeconds(1)); + + // Then: + // ... Read message should have been called twice + mr.Verify(o => o.ReadMessage(), Times.Exactly(2)); + + // ... There should not be any outgoing messages + var outgoing = jh.outputQueue.ToArray(); + Assert.Equal(0, outgoing.Length); + } + + #endregion + + #region ConsumeOutput Loop Tests + + [Fact] + public async Task ConsumeOutput() + { + // Setup: + // ... Create a mock message writer + var mw = new Mock(Stream.Null); + mw.Setup(o => o.WriteMessage(CommonObjects.ResponseMessage)).Returns(Task.FromResult(true)); + + // ... Create the JSON RPC host and add an item to the output queue + var jh = new JsonRpcHost(GetChannelBase(null, mw.Object).Object); + jh.outputQueue.Add(CommonObjects.ResponseMessage); + jh.outputQueue.CompleteAdding(); // This will cause the thread to stop after processing the items + + // If: I start the output consumption thread + Task consumeOutputTask = jh.ConsumeOutput(); + await consumeOutputTask.WithTimeout(TimeSpan.FromSeconds(1)); + + // Then: The message writer should have been called once + mw.Verify(o => o.WriteMessage(CommonObjects.ResponseMessage), Times.Once); + } + + [Fact] + public async Task ConsumeOutputCancelled() + { + // NOTE: This test validates that the blocking collection breaks out when cancellation is requested + + // Setup: Create a mock message writer + var mw = new Mock(Stream.Null); + mw.Setup(o => o.WriteMessage(It.IsAny())).Returns(Task.FromResult(true)); + + // If: + // ... I start the output consumption thread + var jh = new JsonRpcHost(GetChannelBase(null, mw.Object).Object); + Task consumeOuputTask = jh.ConsumeOutput(); + + // ... and I stop the thread via cancellation and wait for completion + jh.cancellationTokenSource.Cancel(); + await consumeOuputTask.WithTimeout(TimeSpan.FromSeconds(1)); + + // Then: The message writer should not have been called + mw.Verify(o => o.WriteMessage(It.IsAny()), Times.Never); + } + + [Fact] + public async Task ConsumeOutputException() + { + // Setup: Create a mock message writer + var mw = new Mock(Stream.Null); + mw.Setup(o => o.WriteMessage(It.IsAny())).Returns(Task.FromResult(true)); + + // If: I start the output consumption thread with a completed blocking collection + var jh = new JsonRpcHost(GetChannelBase(null, mw.Object).Object); + jh.outputQueue.CompleteAdding(); + await jh.ConsumeOutput().WithTimeout(TimeSpan.FromSeconds(1)); + + // Then: The message writer should not have been called + mw.Verify(o => o.WriteMessage(It.IsAny()), Times.Never); + } + + #endregion + + #region Start/Stop Tests + + [Fact] + public async Task StartStop() + { + // Setup: Create mocked message reader and writer + var mr = new Mock(Stream.Null, null); + var mw = new Mock(Stream.Null); + + // If: I start a JSON RPC host + var cb = GetChannelBase(mr.Object, mw.Object); + var jh = new JsonRpcHost(cb.Object); + jh.Start(); + + // Then: The channel protocol should have been + cb.Verify(o => o.Start(), Times.Once); + cb.Verify(o => o.WaitForConnection(), Times.Once); + + // If: I stop the JSON RPC host + jh.Stop(); + + // Then: The long running tasks should stop gracefully + await Task.WhenAll(jh.consumeInputTask, jh.consumeOutputTask).WithTimeout(TimeSpan.FromSeconds(1)); + cb.Verify(o => o.Stop(), Times.Once); + } + + [Fact] + public async Task StartMultiple() + { + // Setup: Create mocked message reader and writer + var mr = new Mock(Stream.Null, null); + var mw = new Mock(Stream.Null); + + // If: + // ... I start a JSON RPC host + var cb = GetChannelBase(mr.Object, mw.Object); + var jh = new JsonRpcHost(cb.Object); + jh.Start(); + + // ... And I start it again + // Then: I should get an exception + Assert.Throws(() => jh.Start()); + + // Cleanup: Stop the JSON RPC host + jh.Stop(); + await Task.WhenAll(jh.consumeInputTask, jh.consumeOutputTask).WithTimeout(TimeSpan.FromSeconds(1)); + } + + [Fact] + public void StopMultiple() + { + // Setup: Create json rpc host and start it + var mr = new Mock(Stream.Null, null); + var mw = new Mock(Stream.Null); + var jh = new JsonRpcHost(GetChannelBase(mr.Object, mw.Object).Object); + jh.Start(); + + // If: I stop the JSON RPC host after stopping it + // Then: I should get an exception + jh.Stop(); + Assert.Throws(() => jh.Stop()); + } + + [Fact] + public void StopBeforeStarting() + { + // If: I stop the JSON RPC host without starting it first + // Then: I should get an exception + var jh = new JsonRpcHost(GetChannelBase(null, null).Object); + Assert.Throws(() => jh.Stop()); + } + + [Fact] + public async Task WaitForExit() + { + // Setup: Create json rpc host and start it + var mr = new Mock(Stream.Null, null); + var mw = new Mock(Stream.Null); + var jh = new JsonRpcHost(GetChannelBase(mr.Object, mw.Object).Object); + jh.Start(); + + // If: I wait for JSON RPC host to exit and stop it + // NOTE: We are wrapping this execution in a task to make sure we can properly stop the host + Task waitForExit = Task.Run(() => { jh.WaitForExit(); }); + jh.Stop(); + + // Then: The host should be stopped + await waitForExit.WithTimeout(TimeSpan.FromSeconds(1)); + } + + [Fact] + public void WaitForExitNotStarted() + { + // If: I wait for exit on the JSON RPC host without starting it + // Then: I should get an exception + var jh = new JsonRpcHost(GetChannelBase(null, null).Object); + Assert.Throws(() => jh.WaitForExit()); + } + + #endregion + + private static Mock GetChannelBase(MessageReader reader, MessageWriter writer, bool isConnected = false) + { + var cb = new Mock(); + cb.Object.MessageReader = reader; + cb.Object.MessageWriter = writer; + cb.Object.IsConnected = isConnected; + cb.Setup(o => o.Start()); + cb.Setup(o => o.Stop()); + cb.Setup(o => o.WaitForConnection()).Returns(Task.FromResult(true)); + + return cb; + } + } +} diff --git a/test/Microsoft.SqlTools.Hosting.UnitTests/ProtocolTests/MessageReaderTests.cs b/test/Microsoft.SqlTools.Hosting.UnitTests/ProtocolTests/MessageReaderTests.cs new file mode 100644 index 00000000..1c748dff --- /dev/null +++ b/test/Microsoft.SqlTools.Hosting.UnitTests/ProtocolTests/MessageReaderTests.cs @@ -0,0 +1,220 @@ +// +// 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.IO; +using System.Text; +using System.Threading.Tasks; +using Microsoft.SqlTools.Hosting.Protocol; +using Microsoft.SqlTools.ServiceLayer.Test.Common; +using Newtonsoft.Json; +using Xunit; + +namespace Microsoft.SqlTools.Hosting.UnitTests.ProtocolTests +{ + public class MessageReaderTests + { + #region Construction Tests + + [Fact] + public void CreateReaderNullStream() + { + // If: I create a message reader with a null stream reader + // Then: It should throw + Assert.Throws(() => new MessageReader(null)); + } + + [Fact] + public void CreateReaderStandardEncoding() + { + // If: I create a message reader without including a message encoding + var mr = new MessageReader(Stream.Null); + + // Then: The reader's encoding should be UTF8 + Assert.Equal(Encoding.UTF8, mr.MessageEncoding); + } + + [Fact] + public void CreateReaderNonStandardEncoding() + { + // If: I create a message reader with a specific message encoding + var mr = new MessageReader(Stream.Null, Encoding.ASCII); + + // Then: The reader's encoding should be ASCII + Assert.Equal(Encoding.ASCII, mr.MessageEncoding); + } + + #endregion + + #region ReadMessage Tests + + [Theory] + [InlineData(512)] // Buffer size can fit everything in one read + [InlineData(10)] // Buffer size must use multiple reads to read the headers + [InlineData(25)] // Buffer size must use multiple reads to read the contents + public async Task ReadMessageSingleRead(int bufferSize) + { + // Setup: Reader with a stream that has an entire message in it + byte[] testBytes = Encoding.UTF8.GetBytes("Content-Length: 50\r\n\r\n{\"jsonrpc\": \"2.0\", \"method\":\"test\", \"params\":null}"); + using (Stream testStream = new MemoryStream(testBytes)) + { + var mr = new MessageReader(testStream) {MessageBuffer = new byte[bufferSize]}; + + // If: I reade a message with the reader + var output = await mr.ReadMessage(); + + // Then: + // ... I should have a successful message read + Assert.NotNull(output); + + // ... The reader should be back in header mode + Assert.Equal(MessageReader.ReadState.Headers, mr.CurrentState); + + // ... The buffer should have been trimmed + Assert.Equal(MessageReader.DefaultBufferSize, mr.MessageBuffer.Length); + } + } + + [Theory] + [InlineData("Content-Type: application/json\r\n\r\n")] // Missing content-length header + [InlineData("Content-Length: abc\r\n\r\n")] // Content-length is not a number + public async Task ReadMessageInvalidHeaders(string testString) + { + // Setup: Reader with a stream that has an invalid header in it + byte[] testBytes = Encoding.UTF8.GetBytes(testString); + using (Stream testStream = new MemoryStream(testBytes)) + { + var mr = new MessageReader(testStream) {MessageBuffer = new byte[20]}; + + // If: I read a message with invalid headers + // Then: ... I should get an exception + await Assert.ThrowsAnyAsync(() => mr.ReadMessage()); + + // ... The buffer should have been trashed (reset to it's original tiny size) + Assert.Equal(MessageReader.DefaultBufferSize, mr.MessageBuffer.Length); + } + } + + [Fact] + public async Task ReadMessageInvalidJson() + { + // Setup: Reader with a stream that has an invalid json message in it + byte[] testBytes = Encoding.UTF8.GetBytes("Content-Length: 10\r\n\r\nabcdefghij"); + using (Stream testStream = new MemoryStream(testBytes)) + { + // ... Buffer size is small to validate if the buffer has been trashed at the end + var mr = new MessageReader(testStream) {MessageBuffer = new byte[20]}; + + // If: I read a message with an invalid JSON in it + // Then: + // ... I should get an exception + await Assert.ThrowsAnyAsync(() => mr.ReadMessage()); + + // ... The buffer should have been trashed (reset to it's original tiny size) + Assert.Equal(MessageReader.DefaultBufferSize, mr.MessageBuffer.Length); + } + } + + [Fact] + public async Task ReadMultipleMessages() + { + // Setup: Reader with a stream that has multiple messages in it + const string testString = "Content-Length: 50\r\n\r\n{\"jsonrpc\": \"2.0\", \"method\":\"test\", \"params\":null}"; + byte[] testBytes = Encoding.UTF8.GetBytes(testString + testString); + using (Stream testStream = new MemoryStream(testBytes)) + { + var mr = new MessageReader(testStream); + + // If: + // ... I read a message + var msg1 = await mr.ReadMessage(); + + // ... And I read another message + var msg2 = await mr.ReadMessage(); + + // Then: + // ... The messages should be real messages + Assert.NotNull(msg1); + Assert.NotNull(msg2); + } + } + + [Fact] + public async Task ReadMultipleMessagesBeforeWriting() + { + // Setup: Reader with a stream that will have multiple messages in it + const string testString = "Content-Length: 50\r\n\r\n{\"jsonrpc\": \"2.0\", \"method\":\"test\", \"params\":null}"; + byte[] testBytes = Encoding.UTF8.GetBytes(testString); + using (Stream testStream = new MemoryStream()) + { + var mr = new MessageReader(testStream); + + // If: I start reading a message then write the message to the stream + var readTask1 = mr.ReadMessage(); + await testStream.WriteAsync(testBytes, 0, testBytes.Length); + var msg1 = await readTask1.WithTimeout(TimeSpan.FromSeconds(1)); + + // Then: The message should be real + Assert.NotNull(msg1); + + // If: I do it again + var readTask2 = mr.ReadMessage(); + await testStream.WriteAsync(testBytes, 0, testBytes.Length); + var msg2 = await readTask2.WithTimeout(TimeSpan.FromSeconds(1)); + + // Then: The message should be real + Assert.NotNull(msg2); + } + } + + [Fact] + public async Task ReadRecoverFromInvalidHeaderMessage() + { + // Setup: Reader with a stream that has incorrect message formatting + const string testString = "Content-Type: application/json\r\n\r\n" + + "Content-Length: 50\r\n\r\n{\"jsonrpc\": \"2.0\", \"method\":\"test\", \"params\":null}"; + byte[] testBytes = Encoding.UTF8.GetBytes(testString); + using (Stream testStream = new MemoryStream(testBytes)) + { + var mr = new MessageReader(testStream); + + // If: I read a message with invalid headers + // Then: I should get an exception + await Assert.ThrowsAnyAsync(() => mr.ReadMessage()); + + // If: I read another, valid, message + var msg = await mr.ReadMessage(); + + // Then: I should have a valid message + Assert.NotNull(msg); + } + } + + [Fact] + public async Task ReadRecoverFromInvalidContentMessage() + { + // Setup: Reader with a stream that has incorrect message formatting + const string testString = "Content-Length: 10\r\n\r\nabcdefghij" + + "Content-Length: 50\r\n\r\n{\"jsonrpc\": \"2.0\", \"method\":\"test\", \"params\":null}"; + byte[] testBytes = Encoding.UTF8.GetBytes(testString); + using (Stream testStream = new MemoryStream(testBytes)) + { + var mr = new MessageReader(testStream); + + // If: I read a message with invalid content + // Then: I should get an exception + await Assert.ThrowsAnyAsync(() => mr.ReadMessage()); + + // If: I read another, valid, message + var msg = await mr.ReadMessage(); + + // Then: I should have a valid message + Assert.NotNull(msg); + } + } + + #endregion + } +} \ No newline at end of file diff --git a/test/Microsoft.SqlTools.Hosting.UnitTests/ProtocolTests/MessageTests.cs b/test/Microsoft.SqlTools.Hosting.UnitTests/ProtocolTests/MessageTests.cs new file mode 100644 index 00000000..3f0366b6 --- /dev/null +++ b/test/Microsoft.SqlTools.Hosting.UnitTests/ProtocolTests/MessageTests.cs @@ -0,0 +1,291 @@ +// +// 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.Linq; +using Microsoft.SqlTools.Hosting.Protocol; +using Newtonsoft.Json.Linq; +using Xunit; + +namespace Microsoft.SqlTools.Hosting.UnitTests.ProtocolTests +{ + public class MessageTests + { + #region Construction/Serialization Tests + + [Fact] + public void CreateRequest() + { + // If: I create a request + var message = Message.CreateRequest(CommonObjects.RequestType, CommonObjects.MessageId, CommonObjects.TestMessageContents.DefaultInstance); + + // Then: + // ... The message should have all the properties I defined + // ... The JObject should have the same properties + var expectedResults = new MessagePropertyResults + { + MessageType = MessageType.Request, + IdSet = true, + MethodSetAs = CommonObjects.RequestType.MethodName, + ContentsSetAs = "params", + ErrorSet = false + }; + AssertPropertiesSet(expectedResults, message); + } + + [Fact] + public void CreateError() + { + // If: I create an error + var message = Message.CreateResponseError(CommonObjects.MessageId, CommonObjects.TestErrorContents.DefaultInstance); + + // Then: Message and JObject should have appropriate properties set + var expectedResults = new MessagePropertyResults + { + MessageType = MessageType.ResponseError, + IdSet = true, + MethodSetAs = null, + ContentsSetAs = null, + ErrorSet = true + }; + AssertPropertiesSet(expectedResults, message); + } + + [Fact] + public void CreateResponse() + { + // If: I create a response + var message = Message.CreateResponse(CommonObjects.MessageId, CommonObjects.TestMessageContents.DefaultInstance); + + // Then: Message and JObject should have appropriate properties set + var expectedResults = new MessagePropertyResults + { + MessageType = MessageType.Response, + IdSet = true, + MethodSetAs = null, + ContentsSetAs = "result", + ErrorSet = false + }; + AssertPropertiesSet(expectedResults, message); + } + + [Fact] + public void CreateEvent() + { + // If: I create an event + var message = Message.CreateEvent(CommonObjects.EventType, CommonObjects.TestMessageContents.DefaultInstance); + + // Then: Message and JObject should have appropriate properties set + var expectedResults = new MessagePropertyResults + { + MessageType = MessageType.Event, + IdSet = false, + MethodSetAs = CommonObjects.EventType.MethodName, + ContentsSetAs = "params", + ErrorSet = false + }; + AssertPropertiesSet(expectedResults, message); + } + + private static void AssertPropertiesSet(MessagePropertyResults results, Message message) + { + Assert.NotNull(message); + + // Serialize the message and deserialize back into a JObject + string messageJson = message.Serialize(); + Assert.NotNull(messageJson); + JObject jObject = JObject.Parse(messageJson); + + // JSON RPC Version + List expectedProperties = new List {"jsonrpc"}; + Assert.Equal("2.0", jObject["jsonrpc"]); + + // Message Type + Assert.Equal(results.MessageType, message.MessageType); + + // ID + if (results.IdSet) + { + Assert.Equal(CommonObjects.MessageId, message.Id); + Assert.Equal(CommonObjects.MessageId, jObject["id"]); + expectedProperties.Add("id"); + } + else + { + Assert.Null(message.Id); + } + + // Method + if (results.MethodSetAs != null) + { + Assert.Equal(results.MethodSetAs, message.Method); + Assert.Equal(results.MethodSetAs, jObject["method"]); + expectedProperties.Add("method"); + } + else + { + Assert.Null(message.Method); + } + + // Contents + if (results.ContentsSetAs != null) + { + Assert.Equal(CommonObjects.TestMessageContents.SerializedContents, message.Contents); + Assert.Equal(CommonObjects.TestMessageContents.SerializedContents, jObject[results.ContentsSetAs]); + expectedProperties.Add(results.ContentsSetAs); + } + + // Error + if (results.ErrorSet) + { + Assert.Equal(CommonObjects.TestErrorContents.SerializedContents, message.Contents); + Assert.Equal(CommonObjects.TestErrorContents.SerializedContents, jObject["error"]); + expectedProperties.Add("error"); + } + + // Look for any extra properties set in the JObject + IEnumerable setProperties = jObject.Properties().Select(p => p.Name); + Assert.Empty(setProperties.Except(expectedProperties)); + } + + private class MessagePropertyResults + { + public MessageType MessageType { get; set; } + public bool IdSet { get; set; } + public string MethodSetAs { get; set; } + public string ContentsSetAs { get; set; } + public bool ErrorSet { get; set; } + } + + #endregion + + #region Deserialization Tests + + [Fact] + public void DeserializeMissingJsonRpc() + { + // If: I deserialize a json string that doesn't have a JSON RPC version + // Then: I should get an exception + Assert.Throws(() => Message.Deserialize("{\"id\": 123}")); + } + + [Fact] + public void DeserializeEvent() + { + // If: I deserialize an event json string + Message m = Message.Deserialize("{\"jsonrpc\": \"2.0\", \"params\": {}, \"method\": \"event\"}"); + + // Then: I should get an event message back + Assert.NotNull(m); + Assert.Equal(MessageType.Event, m.MessageType); + Assert.Equal("event", m.Method); + Assert.NotNull(m.Contents); + Assert.Null(m.Id); + } + + [Fact] + public void DeserializeEventMissingMethod() + { + // If: I deserialize an event json string that is missing a method + // Then: I should get an exception + Assert.Throws(() => Message.Deserialize("{\"jsonrpc\": \"2.0\", \"params\": {}}")); + } + + [Fact] + public void DeserializeResponse() + { + // If: I deserialize a response json string + Message m = Message.Deserialize("{\"jsonrpc\": \"2.0\", \"result\": {}, \"id\": \"123\"}"); + + // Then: I should get a response message back + Assert.NotNull(m); + Assert.Equal(MessageType.Response, m.MessageType); + Assert.Equal("123", m.Id); + Assert.NotNull(m.Contents); + Assert.Null(m.Method); + } + + [Fact] + public void DeserializeErrorResponse() + { + // If: I deserialize an error response + Message m = Message.Deserialize("{\"jsonrpc\": \"2.0\", \"error\": {}, \"id\": \"123\"}"); + + // Then: I should get an error response message back + Assert.NotNull(m); + Assert.Equal(MessageType.ResponseError, m.MessageType); + Assert.Equal("123", m.Id); + Assert.NotNull(m.Contents); + Assert.Null(m.Method); + } + + [Fact] + public void DeserializeRequest() + { + // If: I deserialize a request + Message m = Message.Deserialize("{\"jsonrpc\": \"2.0\", \"params\": {}, \"method\": \"request\", \"id\": \"123\"}"); + + // Then: I should get a request message back + Assert.NotNull(m); + Assert.Equal(MessageType.Request, m.MessageType); + Assert.Equal("123", m.Id); + Assert.Equal("request", m.Method); + Assert.NotNull(m.Contents); + } + + [Fact] + public void DeserializeRequestMissingMethod() + { + // If: I deserialize a request that doesn't have a method parameter + // Then: I should get an exception + Assert.Throws(() => Message.Deserialize("{\"jsonrpc\": \"2.0\", \"params\": {}, \"id\": \"123\"}")); + } + + [Fact] + public void GetTypedContentsNull() + { + // If: I have a message that has a null contents, and I get the typed contents of it + var m = Message.CreateResponse(CommonObjects.MessageId, null); + var c = m.GetTypedContents(); + + // Then: I should get null back as the test message contents + Assert.Null(c); + } + + [Fact] + public void GetTypedContentsSimpleValue() + { + // If: I have a message that has simple contents, and I get the typed contents of it + var m = Message.CreateResponse(CommonObjects.MessageId, 123); + var c = m.GetTypedContents(); + + // Then: I should get an int back + Assert.Equal(123, c); + } + + [Fact] + public void GetTypedContentsClassValue() + { + // If: I have a message that has complex contents, and I get the typed contents of it + var m = Message.CreateResponse(CommonObjects.MessageId, CommonObjects.TestMessageContents.DefaultInstance); + var c = m.GetTypedContents(); + + // Then: I should get the default instance back + Assert.Equal(CommonObjects.TestMessageContents.DefaultInstance, c); + } + + [Fact] + public void GetTypedContentsInvalid() + { + // If: I have a message that has contents and I get incorrectly typed contents from it + // Then: I should get an exception back + var m = Message.CreateResponse(CommonObjects.MessageId, CommonObjects.TestMessageContents.DefaultInstance); + Assert.ThrowsAny(() => m.GetTypedContents()); + } + + #endregion + } +} \ No newline at end of file diff --git a/test/Microsoft.SqlTools.Hosting.UnitTests/ProtocolTests/MessageWriterTests.cs b/test/Microsoft.SqlTools.Hosting.UnitTests/ProtocolTests/MessageWriterTests.cs new file mode 100644 index 00000000..f62d673d --- /dev/null +++ b/test/Microsoft.SqlTools.Hosting.UnitTests/ProtocolTests/MessageWriterTests.cs @@ -0,0 +1,158 @@ +// +// 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.IO; +using System.Text; +using System.Threading.Tasks; +using Microsoft.SqlTools.Hosting.Protocol; +using Newtonsoft.Json; +using Xunit; + +namespace Microsoft.SqlTools.Hosting.UnitTests.ProtocolTests +{ + public class MessageWriterTests + { + #region Construction Tests + + [Fact] + public void ConstructMissingOutputStream() + { + // If: I attempt to create a message writer without an output stream + // Then: I should get an exception + Assert.Throws(() => new MessageWriter(null)); + } + + #endregion + + #region WriteMessageTests + + [Fact] + public async Task WriteMessageNullMessage() + { + // If: I write a null message + // Then: I should get an exception + var mw = new MessageWriter(Stream.Null); + await Assert.ThrowsAsync(() => mw.WriteMessage(null)); + } + + [Theory] + [MemberData(nameof(WriteMessageData))] + public async Task WriteMessage(object contents, Dictionary expectedDict) + { + // NOTE: This technically tests the ability of the Message class to properly serialize + // various types of message contents. This *should* be part of the message tests + // but it is simpler to test it here. + + // Setup: Create a stream to capture the output + var output = new byte[8192]; + using (var outputStream = new MemoryStream(output)) + { + // If: I write a message + var mw = new MessageWriter(outputStream); + await mw.WriteMessage(Message.CreateResponse(CommonObjects.MessageId, contents)); + + // Then: + // ... The returned bytes on the stream should compose a valid message + Assert.NotEqual(0, outputStream.Position); + var messageDict = ValidateMessageHeaders(output, (int) outputStream.Position); + + // ... ID, Params, Method should be present + AssertMessage(messageDict, expectedDict); + } + } + + public static IEnumerable WriteMessageData + { + get + { + yield return new object[] + { + null, + new Dictionary {{"id", "123"}, {"result", null}} + }; + yield return new object[] + { + "simple param", + new Dictionary {{"id", "123"}, {"result", "simple param"}} + }; + yield return new object[] + { + CommonObjects.TestMessageContents.DefaultInstance, + new Dictionary {{"id", "123"}, {"result", CommonObjects.TestMessageContents.SerializedContents}} + }; + } + } + + #endregion + + #region Private Helpers + + private static void AssertMessage(Dictionary messageDict, Dictionary expectedDict) + { + // Add the jsonrpc property to the expected dict + expectedDict.Add("jsonrpc", "2.0"); + + // Make sure the number of elements in both dictionaries are the same + Assert.Equal(expectedDict.Count, messageDict.Count); + + // Make sure the elements match + foreach (var kvp in expectedDict) + { + Assert.Equal(expectedDict[kvp.Key], messageDict[kvp.Key]); + } + } + + private static Dictionary ValidateMessageHeaders(byte[] outputBytes, int bytesWritten) + { + // Convert the written bytes to a string + string outputString = Encoding.UTF8.GetString(outputBytes, 0, bytesWritten); + + // There should be two sections to the message + string[] outputParts = outputString.Split("\r\n\r\n"); + Assert.Equal(2, outputParts.Length); + + // The first section is the headers + string[] headers = outputParts[0].Split("\r\n"); + Assert.Equal(2, outputParts.Length); + + // There should be a content-type and a content-length + int? contentLength = null; + bool contentTypeCorrect = false; + foreach (string header in headers) + { + // Headers should look like "Header-Key: HeaderValue" + string[] headerParts = header.Split(':'); + Assert.Equal(2, headerParts.Length); + + string headerKey = headerParts[0]; + string headerValue = headerParts[1].Trim(); + + if (headerKey == "Content-Type" && headerValue.StartsWith("application/json")) + { + contentTypeCorrect = true; + } + else if (headerKey == "Content-Length") + { + contentLength = int.Parse(headerValue); + } + else + { + throw new Exception($"Invalid header provided: {headerKey}"); + } + } + + // Make sure the headers are correct + Assert.True(contentTypeCorrect); + Assert.Equal(outputParts[1].Length, contentLength); + + // Deserialize the body into a dictionary + return JsonConvert.DeserializeObject>(outputParts[1]); + } + + #endregion + } +} \ No newline at end of file diff --git a/test/Microsoft.SqlTools.Hosting.UnitTests/ProtocolTests/RequestContextTests.cs b/test/Microsoft.SqlTools.Hosting.UnitTests/ProtocolTests/RequestContextTests.cs new file mode 100644 index 00000000..aa3a7ce3 --- /dev/null +++ b/test/Microsoft.SqlTools.Hosting.UnitTests/ProtocolTests/RequestContextTests.cs @@ -0,0 +1,97 @@ +// +// 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.Concurrent; +using Microsoft.SqlTools.Hosting.Contracts.Internal; +using Microsoft.SqlTools.Hosting.Protocol; +using Xunit; + +namespace Microsoft.SqlTools.Hosting.UnitTests.ProtocolTests +{ + public class RequestContextTests + { + #region Send Tests + + [Fact] + public void SendResult() + { + // Setup: Create a blocking collection to collect the output + var bc = new BlockingCollection(new ConcurrentQueue()); + + // If: I write a response with the request context + var rc = new RequestContext(CommonObjects.RequestMessage, bc); + rc.SendResult(CommonObjects.TestMessageContents.DefaultInstance); + + // Then: The message writer should have sent a response + Assert.Equal(1, bc.ToArray().Length); + Assert.Equal(MessageType.Response, bc.ToArray()[0].MessageType); + } + + [Fact] + public void SendEvent() + { + // Setup: Create a blocking collection to collect the output + var bc = new BlockingCollection(new ConcurrentQueue()); + + // If: I write an event with the request context + var rc = new RequestContext(CommonObjects.RequestMessage, bc); + rc.SendEvent(CommonObjects.EventType, CommonObjects.TestMessageContents.DefaultInstance); + + // Then: The message writer should have sent an event + Assert.Equal(1, bc.ToArray().Length); + Assert.Equal(MessageType.Event, bc.ToArray()[0].MessageType); + } + + [Fact] + public void SendError() + { + // Setup: Create a blocking collection to collect the output + const string errorMessage = "error"; + const int errorCode = 123; + var bc = new BlockingCollection(new ConcurrentQueue()); + + // If: I write an error with the request context + var rc = new RequestContext(CommonObjects.RequestMessage, bc); + rc.SendError(errorMessage, errorCode); + + // Then: + // ... The message writer should have sent an error + Assert.Equal(1, bc.ToArray().Length); + Assert.Equal(MessageType.ResponseError, bc.ToArray()[0].MessageType); + + // ... The error object it built should have the reuired fields set + var contents = bc.ToArray()[0].GetTypedContents(); + Assert.Equal(errorCode, contents.Code); + Assert.Equal(errorMessage, contents.Message); + } + + [Fact] + public void SendException() + { + // Setup: Create a blocking collection to collect the output + var bc = new BlockingCollection(new ConcurrentQueue()); + + // If: I write an error as an exception with the request context + const string errorMessage = "error"; + var e = new Exception(errorMessage); + var rc = new RequestContext(CommonObjects.RequestMessage, bc); + rc.SendError(e); + + // Then: + // ... The message writer should have sent an error + Assert.Equal(1, bc.ToArray().Length); + Assert.Equal(MessageType.ResponseError, bc.ToArray()[0].MessageType); + + // ... The error object it built should have the reuired fields set + var contents = bc.ToArray()[0].GetTypedContents(); + Assert.Equal(e.HResult, contents.Code); + Assert.Equal(errorMessage, contents.Message); + + } + + #endregion + } +} \ No newline at end of file diff --git a/test/Microsoft.SqlTools.Hosting.UnitTests/ServiceHostTests/ExtensibleServiceHostTest.cs b/test/Microsoft.SqlTools.Hosting.UnitTests/ServiceHostTests/ExtensibleServiceHostTest.cs new file mode 100644 index 00000000..32c8e46f --- /dev/null +++ b/test/Microsoft.SqlTools.Hosting.UnitTests/ServiceHostTests/ExtensibleServiceHostTest.cs @@ -0,0 +1,80 @@ +// +// 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 Microsoft.SqlTools.Hosting.Channels; +using Microsoft.SqlTools.Hosting.Extensibility; +using Microsoft.SqlTools.Hosting.Protocol; +using Moq; +using Xunit; + +namespace Microsoft.SqlTools.Hosting.UnitTests.ServiceHostTests +{ + public class ExtensibleServiceHostTest + { + [Fact] + public void CreateExtensibleHostNullProvider() + { + // If: I create an extensible host with a null provider + // Then: I should get an exception + var cb = new Mock(); + Assert.Throws(() => new ExtensibleServiceHost(null, cb.Object)); + } + + [Fact] + public void CreateExtensibleHost() + { + // Setup: + // ... Create a mock hosted service that can initialize + var hs = new Mock(); + var mockType = typeof(Mock); + hs.Setup(o => o.InitializeService(It.IsAny())); + hs.SetupGet(o => o.ServiceType).Returns(mockType); + + // ... Create a service provider mock that will return some stuff + var sp = new Mock(); + sp.Setup(o => o.GetServices()) + .Returns(new[] {hs.Object}); + sp.Setup(o => o.RegisterSingleService(mockType, hs.Object)); + + // If: I create an extensible host with a custom provider + var cb = new Mock(); + var esh = new ExtensibleServiceHost(sp.Object, cb.Object); + + // Then: + + // ... The service should have been initialized + hs.Verify(o => o.InitializeService(esh), Times.Once()); + // ... The service host should have it's provider exposed + Assert.Equal(sp.Object, esh.ServiceProvider); + } + + [Fact] + public void CreateDefaultExtensibleHostNullAssemblyList() + { + // If: I create a default server extensible host with a null provider + // Then: I should get an exception + var cb = new Mock(); + Assert.Throws(() => ExtensibleServiceHost.CreateDefaultExtensibleServer(".", null)); + } + + [Fact] + public void CreateDefaultExtensibleHost() + { + // If: I create a default server extensible host + var esh = ExtensibleServiceHost.CreateDefaultExtensibleServer(".", new string[] { }); + + // Then: + // ... The service provider should be setup + Assert.NotNull(esh.ServiceProvider); + + // ... The underlying rpc host should be using the stdio server channel + var jh = esh.jsonRpcHost as JsonRpcHost; + Assert.NotNull(jh); + Assert.IsType(jh.protocolChannel); + Assert.False(jh.protocolChannel.IsConnected); + } + } +} \ No newline at end of file diff --git a/test/Microsoft.SqlTools.Hosting.UnitTests/ServiceHostTests/ServiceHostTests.cs b/test/Microsoft.SqlTools.Hosting.UnitTests/ServiceHostTests/ServiceHostTests.cs new file mode 100644 index 00000000..3f0b3f27 --- /dev/null +++ b/test/Microsoft.SqlTools.Hosting.UnitTests/ServiceHostTests/ServiceHostTests.cs @@ -0,0 +1,325 @@ +// +// 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.Concurrent; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.SqlTools.DataProtocol.Contracts; +using Microsoft.SqlTools.Hosting.Channels; +using Microsoft.SqlTools.Hosting.Contracts; +using Microsoft.SqlTools.Hosting.Contracts.Internal; +using Microsoft.SqlTools.Hosting.Protocol; +using Moq; +using Newtonsoft.Json.Linq; +using Xunit; + +namespace Microsoft.SqlTools.Hosting.UnitTests.ServiceHostTests +{ + public class ServiceHostTests + { + #region Construction Tests + + [Fact] + public void ServiceHostConstructDefaultServer() + { + // If: I construct a default server service host + var sh = ServiceHost.CreateDefaultServer(); + + // Then: The underlying json rpc host should be using the stdio server channel + var jh = sh.jsonRpcHost as JsonRpcHost; + Assert.NotNull(jh); + Assert.IsType(jh.protocolChannel); + Assert.False(jh.protocolChannel.IsConnected); + } + + [Fact] + public void ServiceHostNullParameter() + { + // If: I create a service host with missing parameters + // Then: I should get an exception + Assert.Throws(() => new ServiceHost(null)); + } + + #endregion + + #region IServiceHost Tests + + [Fact] + public void RegisterInitializeTask() + { + // Setup: Create mock initialize handler + var mockHandler = new Mock>().Object; + + // If: I register a couple initialize tasks with the service host + var sh = GetServiceHost(); + sh.RegisterInitializeTask(mockHandler); + sh.RegisterInitializeTask(mockHandler); + + // Then: There should be two initialize tasks registered + Assert.Equal(2, sh.initCallbacks.Count); + Assert.True(sh.initCallbacks.SequenceEqual(new[] {mockHandler, mockHandler})); + } + + [Fact] + public void RegisterInitializeTaskNullHandler() + { + // If: I register a null initialize task + // Then: I should get an exception + var sh = GetServiceHost(); + Assert.Throws(() => sh.RegisterInitializeTask(null)); + } + + [Fact] + public void RegisterShutdownTask() + { + // Setup: Create mock initialize handler + var mockHandler = new Mock>().Object; + + // If: I register a couple shutdown tasks with the service host + var sh = GetServiceHost(); + sh.RegisterShutdownTask(mockHandler); + sh.RegisterShutdownTask(mockHandler); + + // Then: There should be two initialize tasks registered + Assert.Equal(2, sh.shutdownCallbacks.Count); + Assert.True(sh.shutdownCallbacks.SequenceEqual(new[] {mockHandler, mockHandler})); + } + + [Fact] + public void RegisterShutdownTaskNullHandler() + { + // If: I register a null initialize task + // Then: I should get an exception + var sh = GetServiceHost(); + Assert.Throws(() => sh.RegisterShutdownTask(null)); + } + + #endregion + + #region IJsonRpcHost Tests + + [Fact] + public void SendEvent() + { + // If: I send an event + var jh = GetJsonRpcHostMock(); + var sh = GetServiceHost(jh.Object); + sh.SendEvent(CommonObjects.EventType, CommonObjects.TestMessageContents.DefaultInstance); + + // Then: The underlying json rpc host should have handled it + jh.Verify(o => o.SendEvent(CommonObjects.EventType, CommonObjects.TestMessageContents.DefaultInstance), Times.Once); + } + + [Fact] + public async Task SendRequest() + { + // If: I send a request + var jh = GetJsonRpcHostMock(); + var sh = GetServiceHost(jh.Object); + await sh.SendRequest(CommonObjects.RequestType, CommonObjects.TestMessageContents.DefaultInstance); + + // Then: The underlying json rpc host should have handled it + jh.Verify(o => o.SendRequest(CommonObjects.RequestType, CommonObjects.TestMessageContents.DefaultInstance), Times.Once); + } + + [Fact] + public void SetAsyncEventHandler() + { + // If: I set an event handler + var jh = GetJsonRpcHostMock(); + var sh = GetServiceHost(jh.Object); + sh.SetAsyncEventHandler(CommonObjects.EventType, null, true); + + // Then: The underlying json rpc host should have handled it + jh.Verify(o => o.SetAsyncEventHandler(CommonObjects.EventType, null, true), Times.Once); + } + + [Fact] + public void SetSyncEventHandler() + { + // If: I set an event handler + var jh = GetJsonRpcHostMock(); + var sh = GetServiceHost(jh.Object); + sh.SetEventHandler(CommonObjects.EventType, null, true); + + // Then: The underlying json rpc host should have handled it + jh.Verify(o => o.SetEventHandler(CommonObjects.EventType, null, true), Times.Once); + } + + [Fact] + public void SetAsyncRequestHandler() + { + // If: I set a request handler + var jh = GetJsonRpcHostMock(); + var sh = GetServiceHost(jh.Object); + sh.SetAsyncRequestHandler(CommonObjects.RequestType, null, true); + + // Then: The underlying json rpc host should have handled it + jh.Verify(o => o.SetAsyncRequestHandler(CommonObjects.RequestType, null, true), Times.Once); + } + + [Fact] + public void SetSyncRequestHandler() + { + // If: I set a request handler + var jh = GetJsonRpcHostMock(); + var sh = GetServiceHost(jh.Object); + sh.SetRequestHandler(CommonObjects.RequestType, null, true); + + // Then: The underlying json rpc host should have handled it + jh.Verify(o => o.SetRequestHandler(CommonObjects.RequestType, null, true), Times.Once); + } + + [Fact] + public void Start() + { + // If: I start a service host + var jh = GetJsonRpcHostMock(); + var sh = GetServiceHost(jh.Object); + sh.Start(); + + // Then: + // ... The underlying json rpc host should have handled it + jh.Verify(o => o.Start(), Times.Once); + } + + [Fact] + public void Stop() + { + // If: I stop a service host + var jh = GetJsonRpcHostMock(); + var sh = GetServiceHost(jh.Object); + sh.Stop(); + + // Then: The underlying json rpc host should have handled it + jh.Verify(o => o.Stop(), Times.Once); + } + + [Fact] + public void WaitForExit() + { + // If: I wait for service host to exit + var jh = GetJsonRpcHostMock(); + var sh = GetServiceHost(jh.Object); + sh.WaitForExit(); + + // Then: The underlying json rpc host should have handled it + jh.Verify(o => o.WaitForExit()); + } + + #endregion + + #region Request Handling Tests + + [Fact] + public void HandleExitNotification() + { + // If: I handle an exit notification + var jh = GetJsonRpcHostMock(); + var sh = GetServiceHost(jh.Object); + sh.HandleExitNotification(null, null); + + // Then: The json rpc host should have been stopped + jh.Verify(o => o.Stop(), Times.Once); + } + + [Fact] + public async Task HandleInitializeRequest() + { + // Setup: + // ... Create an initialize handler and register it in the service host + var mockHandler = new Mock>(); + mockHandler.Setup(f => f(It.IsAny(), It.IsAny())) + .Returns(Task.FromResult(true)); + + var sh = GetServiceHost(); + sh.RegisterInitializeTask(mockHandler.Object); + sh.RegisterInitializeTask(mockHandler.Object); + + // ... Set a dummy value to return as the initialize response + var ir = new InitializeResponse(); + + // ... Create a mock request that will handle sending a result + // TODO: Replace with event flow validation + var initParams = new InitializeParameters(); + var bc = new BlockingCollection(); + var mockContext = new RequestContext(Message.CreateRequest(InitializeRequest.Type, CommonObjects.MessageId, initParams), bc); + + // If: I handle an initialize request + await sh.HandleInitializeRequest(initParams, mockContext); + + // Then: + // ... The mock handler should have been called twice + mockHandler.Verify(h => h(initParams, mockContext), Times.Exactly(2)); + + // ... There should have been a response sent + var outgoing = bc.ToArray(); + Assert.Equal(1, outgoing.Length); + Assert.Equal(CommonObjects.MessageId, outgoing[0].Id); + Assert.Equal(JToken.FromObject(ir), JToken.FromObject(ir)); + } + + [Fact] + public async Task HandleShutdownRequest() + { + // Setup: + // ... Create a shutdown handler and register it in the service host + var mockHandler = new Mock>(); + mockHandler.Setup(f => f(It.IsAny(), It.IsAny())) + .Returns(Task.FromResult(true)); + + var sh = GetServiceHost(); + sh.RegisterShutdownTask(mockHandler.Object); + sh.RegisterShutdownTask(mockHandler.Object); + + // ... Create a mock request that will handle sending a result + // TODO: Replace with the event flow validation + var shutdownParams = new object(); + var bc = new BlockingCollection(); + var mockContext = new RequestContext(Message.CreateRequest(ShutdownRequest.Type, CommonObjects.MessageId, shutdownParams), bc); + + // If: I handle a shutdown request + await sh.HandleShutdownRequest(shutdownParams, mockContext); + + // Then: + // ... The mock handler should have been called twice + mockHandler.Verify(h => h(shutdownParams, mockContext), Times.Exactly(2)); + + // ... There should have been a response sent + Assert.Equal(1, bc.ToArray().Length); + } + + #endregion + + private static ServiceHost GetServiceHost(IJsonRpcHost jsonRpcHost = null) + { + return new ServiceHost + { + jsonRpcHost = jsonRpcHost + }; + } + + private static Mock GetJsonRpcHostMock() + { + var anyEventType = It.IsAny>(); + var anyRequestType = It.IsAny>(); + var anyParams = It.IsAny(); + + var mock = new Mock(); + mock.Setup(jh => jh.SendEvent(anyEventType, anyParams)); + mock.Setup(jh => jh.SendRequest(anyRequestType, anyParams)).ReturnsAsync(null); + mock.Setup(jh => jh.SetAsyncEventHandler(anyEventType, It.IsAny>(), It.IsAny())); + mock.Setup(jh => jh.SetEventHandler(anyEventType, It.IsAny>(), It.IsAny())); + mock.Setup(jh => jh.SetAsyncRequestHandler(anyRequestType, It.IsAny, Task>>(), It.IsAny())); + mock.Setup(jh => jh.SetRequestHandler(anyRequestType, It.IsAny>>(), It.IsAny())); + mock.Setup(jh => jh.Start()); + mock.Setup(jh => jh.Stop()); + mock.Setup(jh => jh.WaitForExit()); + + return mock; + } + } +} diff --git a/test/Microsoft.SqlTools.Hosting.UnitTests/TaskExtensions.cs b/test/Microsoft.SqlTools.Hosting.UnitTests/TaskExtensions.cs new file mode 100644 index 00000000..201331cc --- /dev/null +++ b/test/Microsoft.SqlTools.Hosting.UnitTests/TaskExtensions.cs @@ -0,0 +1,26 @@ + +// +// 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.Threading.Tasks; + +namespace Microsoft.SqlTools.ServiceLayer.Test.Common +{ + public static class TaskExtensions + { + public static async Task WithTimeout(this Task task, TimeSpan timeout) + { + Task delayTask = Task.Delay(timeout); + Task firstCompleted = await Task.WhenAny(task, delayTask); + if (firstCompleted == delayTask) + { + throw new Exception("Task timed out"); + } + + return task; + } + } +} diff --git a/test/Microsoft.SqlTools.Hosting.UnitTests/UtilityTests/AsyncLockTests.cs b/test/Microsoft.SqlTools.Hosting.UnitTests/UtilityTests/AsyncLockTests.cs new file mode 100644 index 00000000..c34c3404 --- /dev/null +++ b/test/Microsoft.SqlTools.Hosting.UnitTests/UtilityTests/AsyncLockTests.cs @@ -0,0 +1,49 @@ +// +// 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.Threading; +using System.Threading.Tasks; +using Microsoft.SqlTools.Hosting.Utility; +using Xunit; + +namespace Microsoft.SqlTools.Hosting.UnitTests.UtilityTests +{ + public class AsyncLockTests + { + [Fact] + public async Task AsyncLockSynchronizesAccess() + { + AsyncLock asyncLock = new AsyncLock(); + + Task lockOne = asyncLock.LockAsync(); + Task lockTwo = asyncLock.LockAsync(); + + Assert.Equal(TaskStatus.RanToCompletion, lockOne.Status); + Assert.Equal(TaskStatus.WaitingForActivation, lockTwo.Status); + lockOne.Result.Dispose(); + + await lockTwo; + Assert.Equal(TaskStatus.RanToCompletion, lockTwo.Status); + } + + [Fact] + public void AsyncLockCancelsWhenRequested() + { + CancellationTokenSource cts = new CancellationTokenSource(); + AsyncLock asyncLock = new AsyncLock(); + + Task lockOne = asyncLock.LockAsync(); + Task lockTwo = asyncLock.LockAsync(cts.Token); + + // Cancel the second lock before the first is released + cts.Cancel(); + lockOne.Result.Dispose(); + + Assert.Equal(TaskStatus.RanToCompletion, lockOne.Status); + Assert.Equal(TaskStatus.Canceled, lockTwo.Status); + } + } +} diff --git a/test/Microsoft.SqlTools.Hosting.UnitTests/UtilityTests/LoggerTests.cs b/test/Microsoft.SqlTools.Hosting.UnitTests/UtilityTests/LoggerTests.cs new file mode 100644 index 00000000..ca85117c --- /dev/null +++ b/test/Microsoft.SqlTools.Hosting.UnitTests/UtilityTests/LoggerTests.cs @@ -0,0 +1,63 @@ +// +// 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.IO; +using System.Linq; +using Microsoft.SqlTools.Hosting.Utility; +using Xunit; + +namespace Microsoft.SqlTools.Hosting.UnitTests.UtilityTests +{ + /// + /// Logger test cases + /// + public class LoggerTests + { + + /// + /// Test to verify that the logger initialization is generating a valid file + /// + [Fact] + public void LoggerDefaultFile() + { + // delete any existing log files from the current directory + Directory.GetFiles(Directory.GetCurrentDirectory()) + .Where(fileName + => fileName.Contains("sqltools_") + && fileName.EndsWith(".log", StringComparison.OrdinalIgnoreCase)) + .ToList() + .ForEach(File.Delete); + + Logger logger = new Logger(); + // initialize the logger + logger.Initialize( + logFilePath: Path.Combine(Directory.GetCurrentDirectory(), "sqltools"), + minimumLogLevel: LogLevel.Verbose); + + // close the logger + logger.Close(); + + // find the name of the new log file + string logFileName = Directory.GetFiles(Directory.GetCurrentDirectory()) + .SingleOrDefault(fileName => + fileName.Contains("sqltools_") + && fileName.EndsWith(".log", StringComparison.OrdinalIgnoreCase)); + + // validate the log file was created with desired name + Assert.True(!string.IsNullOrWhiteSpace(logFileName)); + if (!string.IsNullOrWhiteSpace(logFileName)) + { + Assert.True(logFileName.Length > "sqltools_.log".Length); + Assert.True(File.Exists(logFileName)); + + // delete the test log file + if (File.Exists(logFileName)) + { + File.Delete(logFileName); + } + } + } + } +}