diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/ConnectionService.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/ConnectionService.cs
index ef2e59d2..2d7acbde 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/Connection/ConnectionService.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/ConnectionService.cs
@@ -29,6 +29,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection
public class ConnectionService
{
public const string AdminConnectionPrefix = "ADMIN:";
+ private const string SqlAzureEdition = "SQL Azure";
///
/// Singleton service instance
@@ -456,7 +457,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection
EngineEditionId = serverInfo.EngineEditionId,
ServerVersion = serverInfo.ServerVersion,
ServerLevel = serverInfo.ServerLevel,
- ServerEdition = serverInfo.ServerEdition,
+ ServerEdition = MapServerEdition(serverInfo),
IsCloud = serverInfo.IsCloud,
AzureVersion = serverInfo.AzureVersion,
OsVersion = serverInfo.OsVersion,
@@ -474,6 +475,31 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection
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.
///
diff --git a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/BindingQueue.cs b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/BindingQueue.cs
index b8584e77..b57f960f 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/BindingQueue.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/BindingQueue.cs
@@ -9,6 +9,7 @@ using System.Threading;
using System.Threading.Tasks;
using Microsoft.SqlTools.Utility;
using System.Linq;
+using Microsoft.SqlTools.ServiceLayer.Utility;
namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
{
@@ -64,6 +65,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
string key,
Func bindOperation,
Func timeoutOperation = null,
+ Func errorHandler = null,
int? bindingTimeout = null,
int? waitForLockTimeout = null)
{
@@ -78,6 +80,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
Key = key,
BindOperation = bindOperation,
TimeoutOperation = timeoutOperation,
+ ErrorHandler = errorHandler,
BindingTimeout = bindingTimeout,
WaitForLockTimeout = waitForLockTimeout
};
@@ -92,6 +95,23 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
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
///
@@ -270,9 +290,20 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
// run the operation in a separate thread
var bindThread = new Thread(() =>
{
- result = queueItem.BindOperation(
- bindingContext,
- cancelToken.Token);
+ try
+ {
+ result = queueItem.BindOperation(
+ bindingContext,
+ cancelToken.Token);
+ }
+ catch (Exception ex)
+ {
+ Logger.Write(LogLevel.Error, "Unexpected exception on the binding queue: " + ex.ToString());
+ if (queueItem.ErrorHandler != null)
+ {
+ result = queueItem.ErrorHandler(ex);
+ }
+ }
}, BindingQueue.QueueThreadStackSize);
bindThread.Start();
@@ -282,7 +313,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
queueItem.Result = result;
}
else
- {
+ {
cancelToken.Cancel();
// if the task didn't complete then call the timeout callback
@@ -298,7 +329,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
// wait for the operation to complete before releasing the lock
bindThread.Join();
bindingContext.BindingLock.Set();
- });
+ }).ContinueWithOnFaulted(t => Logger.Write(LogLevel.Error, "Binding queue threw exception " + t.Exception.ToString()));
}
}
catch (Exception ex)
diff --git a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/Completion/CompletionService.cs b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/Completion/CompletionService.cs
index cf7eb6c3..9de595d3 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/Completion/CompletionService.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/Completion/CompletionService.cs
@@ -104,6 +104,11 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices.Completion
{
// return the default list if the connected bind fails
return CreateDefaultCompletionItems(scriptParseInfo, scriptDocumentInfo, useLowerCaseSuggestions);
+ },
+ errorHandler: ex =>
+ {
+ // return the default list if an unexpected exception occurs
+ return CreateDefaultCompletionItems(scriptParseInfo, scriptDocumentInfo, useLowerCaseSuggestions);
});
return queueItem;
}
diff --git a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/ConnectedBindingQueue.cs b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/ConnectedBindingQueue.cs
index 1a427251..ce48c512 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/ConnectedBindingQueue.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/ConnectedBindingQueue.cs
@@ -27,6 +27,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
string key,
Func bindOperation,
Func timeoutOperation = null,
+ Func errorHandler = null,
int? bindingTimeout = null,
int? waitForLockTimeout = null);
}
diff --git a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/LanguageService.cs b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/LanguageService.cs
index 96fe16cd..d19f24c9 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/LanguageService.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/LanguageService.cs
@@ -794,10 +794,13 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
List parseResults = new List();
parseResults.Add(parseResult);
- bindingContext.Binder.Bind(
- parseResults,
- connInfo.ConnectionDetails.DatabaseName,
- BindMode.Batch);
+ if (bindingContext.IsConnected && bindingContext.Binder != null)
+ {
+ bindingContext.Binder.Bind(
+ parseResults,
+ connInfo.ConnectionDetails.DatabaseName,
+ BindMode.Batch);
+ }
}
catch (ConnectionException)
{
@@ -856,8 +859,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
try
{
scriptInfo.ConnectionKey = this.BindingQueue.AddConnectionContext(info, "languageService");
- scriptInfo.IsConnected = true;
-
+ scriptInfo.IsConnected = this.BindingQueue.IsBindingContextConnected(scriptInfo.ConnectionKey);
}
catch (Exception ex)
{
@@ -917,40 +919,42 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
ParseResult parseResult = Parser.Parse(
"select ",
bindingContext.ParseOptions);
+ if (bindingContext.IsConnected && bindingContext.Binder != null)
+ {
+ List parseResults = new List();
+ parseResults.Add(parseResult);
+ bindingContext.Binder.Bind(
+ parseResults,
+ info.ConnectionDetails.DatabaseName,
+ BindMode.Batch);
- List parseResults = new List();
- parseResults.Add(parseResult);
- bindingContext.Binder.Bind(
- parseResults,
- info.ConnectionDetails.DatabaseName,
- BindMode.Batch);
+ // get the completion list from SQL Parser
+ var suggestions = Resolver.FindCompletions(
+ parseResult, 1, 8,
+ bindingContext.MetadataDisplayInfoProvider);
- // get the completion list from SQL Parser
- var suggestions = Resolver.FindCompletions(
- parseResult, 1, 8,
- bindingContext.MetadataDisplayInfoProvider);
+ // this forces lazy evaluation of the suggestion metadata
+ AutoCompleteHelper.ConvertDeclarationsToCompletionItems(suggestions, 1, 8, 8);
- // this forces lazy evaluation of the suggestion metadata
- AutoCompleteHelper.ConvertDeclarationsToCompletionItems(suggestions, 1, 8, 8);
+ parseResult = Parser.Parse(
+ "exec ",
+ bindingContext.ParseOptions);
- parseResult = Parser.Parse(
- "exec ",
- bindingContext.ParseOptions);
+ parseResults = new List();
+ parseResults.Add(parseResult);
+ bindingContext.Binder.Bind(
+ parseResults,
+ info.ConnectionDetails.DatabaseName,
+ BindMode.Batch);
- parseResults = new List();
- parseResults.Add(parseResult);
- bindingContext.Binder.Bind(
- parseResults,
- info.ConnectionDetails.DatabaseName,
- BindMode.Batch);
+ // get the completion list from SQL Parser
+ suggestions = Resolver.FindCompletions(
+ parseResult, 1, 6,
+ bindingContext.MetadataDisplayInfoProvider);
- // get the completion list from SQL Parser
- suggestions = Resolver.FindCompletions(
- parseResult, 1, 6,
- bindingContext.MetadataDisplayInfoProvider);
-
- // this forces lazy evaluation of the suggestion metadata
- AutoCompleteHelper.ConvertDeclarationsToCompletionItems(suggestions, 1, 6, 6);
+ // this forces lazy evaluation of the suggestion metadata
+ AutoCompleteHelper.ConvertDeclarationsToCompletionItems(suggestions, 1, 6, 6);
+ }
return null;
});
@@ -1103,6 +1107,16 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
Message = SR.PeekDefinitionTimedoutError,
Locations = null
};
+ },
+ errorHandler: ex =>
+ {
+ // return error result
+ return new DefinitionResult
+ {
+ IsErrorResult = true,
+ Message = ex.Message,
+ Locations = null
+ };
});
// wait for the queue item
diff --git a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/QueueItem.cs b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/QueueItem.cs
index 2b45de8b..30cc3548 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/QueueItem.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/QueueItem.cs
@@ -36,6 +36,13 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
///
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
///
diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.cs b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.cs
index 6cfb1c95..a3fdb6bf 100755
--- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.cs
@@ -77,6 +77,30 @@ namespace Microsoft.SqlTools.ServiceLayer
}
}
+ 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
@@ -3652,6 +3676,15 @@ namespace Microsoft.SqlTools.ServiceLayer
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";
diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.resx b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.resx
index d83ce345..88515160 100755
--- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.resx
+++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.resx
@@ -166,6 +166,18 @@
.
Parameters: 0 - component (string)
+
+ Azure SQL DB
+
+
+
+ Azure SQL Data Warehouse
+
+
+
+ Azure SQL Stretch Database
+
+
The query has already completed, it cannot be cancelled
diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.strings b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.strings
index c1e00cda..fe050287 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.strings
+++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.strings
@@ -47,6 +47,11 @@ 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
diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.xlf b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.xlf
index 8c452ae5..5d8d3424 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.xlf
+++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.xlf
@@ -2280,6 +2280,21 @@
Never
+
+ Azure SQL DB
+ Azure SQL DB
+
+
+
+ Azure SQL Data Warehouse
+ Azure SQL Data Warehouse
+
+
+
+ Azure SQL Stretch Database
+ Azure SQL Stretch Database
+
+