mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-19 09:35:36 -05:00
Feature/batch line info (#56)
* inital pipe of line numbers and getting text from workspace services * tests compile * Fixed bug regarding tests using connections on mac * updated tests * fixed workspace service and fixed tests * integrated feedback
This commit is contained in:
@@ -197,20 +197,24 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection
|
||||
// try to get information about the connected SQL Server instance
|
||||
try
|
||||
{
|
||||
ReliableConnectionHelper.ServerInfo serverInfo = ReliableConnectionHelper.GetServerVersion(connectionInfo.SqlConnection);
|
||||
response.ServerInfo = new Contracts.ServerInfo()
|
||||
var connection = connectionInfo.SqlConnection as ReliableSqlConnection;
|
||||
if (connection != null)
|
||||
{
|
||||
ServerMajorVersion = serverInfo.ServerMajorVersion,
|
||||
ServerMinorVersion = serverInfo.ServerMinorVersion,
|
||||
ServerReleaseVersion = serverInfo.ServerReleaseVersion,
|
||||
EngineEditionId = serverInfo.EngineEditionId,
|
||||
ServerVersion = serverInfo.ServerVersion,
|
||||
ServerLevel = serverInfo.ServerLevel,
|
||||
ServerEdition = serverInfo.ServerEdition,
|
||||
IsCloud = serverInfo.IsCloud,
|
||||
AzureVersion = serverInfo.AzureVersion,
|
||||
OsVersion = serverInfo.OsVersion
|
||||
};
|
||||
ReliableConnectionHelper.ServerInfo serverInfo = ReliableConnectionHelper.GetServerVersion(connection.GetUnderlyingConnection());
|
||||
response.ServerInfo = new Contracts.ServerInfo()
|
||||
{
|
||||
ServerMajorVersion = serverInfo.ServerMajorVersion,
|
||||
ServerMinorVersion = serverInfo.ServerMinorVersion,
|
||||
ServerReleaseVersion = serverInfo.ServerReleaseVersion,
|
||||
EngineEditionId = serverInfo.EngineEditionId,
|
||||
ServerVersion = serverInfo.ServerVersion,
|
||||
ServerLevel = serverInfo.ServerLevel,
|
||||
ServerEdition = serverInfo.ServerEdition,
|
||||
IsCloud = serverInfo.IsCloud,
|
||||
AzureVersion = serverInfo.AzureVersion,
|
||||
OsVersion = serverInfo.OsVersion
|
||||
};
|
||||
}
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
|
||||
#endregion
|
||||
|
||||
internal Batch(string batchText, int startLine, IFileStreamFactory outputFileFactory)
|
||||
internal Batch(string batchText, int startLine, int startColumn, int endLine, int endColumn, IFileStreamFactory outputFileFactory)
|
||||
{
|
||||
// Sanity check for input
|
||||
Validate.IsNotNullOrEmptyString(nameof(batchText), batchText);
|
||||
@@ -54,7 +54,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
|
||||
// Initialize the internal state
|
||||
BatchText = batchText;
|
||||
StartLine = startLine - 1; // -1 to make sure that the line number of the batch is 0-indexed, since SqlParser gives 1-indexed line numbers
|
||||
Selection = new SelectionData(startLine, startColumn, endLine, endColumn);
|
||||
HasExecuted = false;
|
||||
resultSets = new List<ResultSet>();
|
||||
resultMessages = new List<string>();
|
||||
@@ -111,9 +111,9 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The 0-indexed line number that this batch started on
|
||||
/// The range from the file that is this batch
|
||||
/// </summary>
|
||||
internal int StartLine { get; set; }
|
||||
internal SelectionData Selection { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -253,9 +253,10 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
SqlError sqlError = error as SqlError;
|
||||
if (sqlError != null)
|
||||
{
|
||||
int lineNumber = sqlError.LineNumber + StartLine;
|
||||
string message = SR.QueryServiceErrorFormat(sqlError.Number, sqlError.Class, sqlError.State,
|
||||
lineNumber, Environment.NewLine, sqlError.Message);
|
||||
int lineNumber = sqlError.LineNumber + Selection.StartLine;
|
||||
string message = string.Format("Msg {0}, Level {1}, State {2}, Line {3}{4}{5}",
|
||||
sqlError.Number, sqlError.Class, sqlError.State, lineNumber,
|
||||
Environment.NewLine, sqlError.Message);
|
||||
resultMessages.Add(message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,11 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts
|
||||
/// </summary>
|
||||
public int Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The selection from the file for this batch
|
||||
/// </summary>
|
||||
public SelectionData Selection { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Any messages that came back from the server during execution of the batch
|
||||
/// </summary>
|
||||
|
||||
@@ -7,15 +7,30 @@ using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Contracts;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts
|
||||
{
|
||||
/// <summary>
|
||||
/// Container class for a selection range from file
|
||||
/// </summary>
|
||||
public class SelectionData {
|
||||
public int StartLine { get; set; }
|
||||
public int StartColumn { get; set; }
|
||||
public int EndLine { get; set; }
|
||||
public int EndColumn { get; set; }
|
||||
public SelectionData(int startLine, int startColumn, int endLine, int endColumn) {
|
||||
StartLine = startLine;
|
||||
StartColumn = startColumn;
|
||||
EndLine = endLine;
|
||||
EndColumn = endColumn;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Parameters for the query execute request
|
||||
/// </summary>
|
||||
public class QueryExecuteParams
|
||||
{
|
||||
/// <summary>
|
||||
/// The text of the query to execute
|
||||
/// The selection from the document
|
||||
/// </summary>
|
||||
public string QueryText { get; set; }
|
||||
public SelectionData QuerySelection { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// URI for the editor that is asking for the query execute
|
||||
|
||||
@@ -86,7 +86,12 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
});
|
||||
// NOTE: We only want to process batches that have statements (ie, ignore comments and empty lines)
|
||||
Batches = parseResult.Script.Batches.Where(b => b.Statements.Count > 0)
|
||||
.Select(b => new Batch(b.Sql, b.StartLocation.LineNumber, outputFileFactory)).ToArray();
|
||||
.Select(b => new Batch(b.Sql,
|
||||
b.StartLocation.LineNumber - 1,
|
||||
b.StartLocation.ColumnNumber - 1,
|
||||
b.EndLocation.LineNumber - 1,
|
||||
b.EndLocation.ColumnNumber - 1,
|
||||
outputFileFactory)).ToArray();
|
||||
}
|
||||
|
||||
#region Properties
|
||||
@@ -113,7 +118,8 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
Id = index,
|
||||
HasError = batch.HasError,
|
||||
Messages = batch.ResultMessages.ToArray(),
|
||||
ResultSetSummaries = batch.ResultSummaries
|
||||
ResultSetSummaries = batch.ResultSummaries,
|
||||
Selection = batch.Selection
|
||||
}).ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage;
|
||||
using Microsoft.SqlTools.ServiceLayer.SqlContext;
|
||||
using Microsoft.SqlTools.ServiceLayer.Workspace;
|
||||
using Microsoft.SqlTools.ServiceLayer.Workspace.Contracts;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
@@ -38,11 +39,13 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
private QueryExecutionService()
|
||||
{
|
||||
ConnectionService = ConnectionService.Instance;
|
||||
WorkspaceService = WorkspaceService<SqlToolsSettings>.Instance;
|
||||
}
|
||||
|
||||
internal QueryExecutionService(ConnectionService connService)
|
||||
internal QueryExecutionService(ConnectionService connService, WorkspaceService<SqlToolsSettings> workspaceService)
|
||||
{
|
||||
ConnectionService = connService;
|
||||
WorkspaceService = workspaceService;
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -78,6 +81,8 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
/// </summary>
|
||||
private ConnectionService ConnectionService { get; set; }
|
||||
|
||||
private WorkspaceService<SqlToolsSettings> WorkspaceService { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Internal storage of active queries, lazily constructed as a threadsafe dictionary
|
||||
/// </summary>
|
||||
@@ -111,7 +116,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
});
|
||||
|
||||
// Register a handler for when the configuration changes
|
||||
WorkspaceService<SqlToolsSettings>.Instance.RegisterConfigChangeCallback((oldSettings, newSettings, eventContext) =>
|
||||
WorkspaceService.RegisterConfigChangeCallback((oldSettings, newSettings, eventContext) =>
|
||||
{
|
||||
Settings.QueryExecutionSettings.Update(newSettings.QueryExecutionSettings);
|
||||
return Task.FromResult(0);
|
||||
@@ -403,10 +408,36 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
}
|
||||
|
||||
// Retrieve the current settings for executing the query with
|
||||
QueryExecutionSettings settings = WorkspaceService<SqlToolsSettings>.Instance.CurrentSettings.QueryExecutionSettings;
|
||||
QueryExecutionSettings settings = WorkspaceService.CurrentSettings.QueryExecutionSettings;
|
||||
|
||||
// Get query text from the workspace.
|
||||
ScriptFile queryFile = WorkspaceService.Workspace.GetFile(executeParams.OwnerUri);
|
||||
|
||||
string queryText;
|
||||
|
||||
if (executeParams.QuerySelection != null)
|
||||
{
|
||||
string[] queryTextArray = queryFile.GetLinesInRange(
|
||||
new BufferRange(
|
||||
new BufferPosition(
|
||||
executeParams.QuerySelection.StartLine + 1,
|
||||
executeParams.QuerySelection.StartColumn + 1
|
||||
),
|
||||
new BufferPosition(
|
||||
executeParams.QuerySelection.EndLine + 1,
|
||||
executeParams.QuerySelection.EndColumn + 1
|
||||
)
|
||||
)
|
||||
);
|
||||
queryText = queryTextArray.Aggregate((a, b) => a + '\r' + '\n' + b);
|
||||
}
|
||||
else
|
||||
{
|
||||
queryText = queryFile.Contents;
|
||||
}
|
||||
|
||||
// If we can't add the query now, it's assumed the query is in progress
|
||||
Query newQuery = new Query(executeParams.QueryText, connectionInfo, settings, BufferFileFactory);
|
||||
Query newQuery = new Query(queryText, connectionInfo, settings, BufferFileFactory);
|
||||
if (!ActiveQueries.TryAdd(executeParams.OwnerUri, newQuery))
|
||||
{
|
||||
await requestContext.SendResult(new QueryExecuteResult
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace.Contracts
|
||||
/// Gets or sets a string containing the full contents of the file.
|
||||
/// Setter for testing purposes only
|
||||
/// </summary>
|
||||
public string Contents
|
||||
public virtual string Contents
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -109,7 +109,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace.Contracts
|
||||
/// <summary>
|
||||
/// Add a default constructor for testing
|
||||
/// </summary>
|
||||
internal ScriptFile()
|
||||
public ScriptFile()
|
||||
{
|
||||
ClientFilePath = "test.sql";
|
||||
}
|
||||
@@ -171,11 +171,12 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace.Contracts
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a range of lines from the file's contents.
|
||||
/// Gets a range of lines from the file's contents. Virtual method to allow for
|
||||
/// mocking.
|
||||
/// </summary>
|
||||
/// <param name="bufferRange">The buffer range from which lines will be extracted.</param>
|
||||
/// <returns>An array of strings from the specified range of the file.</returns>
|
||||
public string[] GetLinesInRange(BufferRange bufferRange)
|
||||
public virtual string[] GetLinesInRange(BufferRange bufferRange)
|
||||
{
|
||||
this.ValidatePosition(bufferRange.Start);
|
||||
this.ValidatePosition(bufferRange.End);
|
||||
|
||||
@@ -50,7 +50,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace
|
||||
|
||||
/// <summary>
|
||||
/// Gets an open file in the workspace. If the file isn't open but
|
||||
/// exists on the filesystem, load and return it.
|
||||
/// exists on the filesystem, load and return it. Virtual method to
|
||||
/// allow for mocking
|
||||
/// </summary>
|
||||
/// <param name="filePath">The file path at which the script resides.</param>
|
||||
/// <exception cref="FileNotFoundException">
|
||||
@@ -59,7 +60,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace
|
||||
/// <exception cref="ArgumentException">
|
||||
/// <paramref name="filePath"/> contains a null or empty string.
|
||||
/// </exception>
|
||||
public ScriptFile GetFile(string filePath)
|
||||
public virtual ScriptFile GetFile(string filePath)
|
||||
{
|
||||
Validate.IsNotNullOrWhitespaceString("filePath", filePath);
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace
|
||||
|
||||
#region Singleton Instance Implementation
|
||||
|
||||
private static readonly Lazy<WorkspaceService<TConfig>> instance = new Lazy<WorkspaceService<TConfig>>(() => new WorkspaceService<TConfig>());
|
||||
private static Lazy<WorkspaceService<TConfig>> instance = new Lazy<WorkspaceService<TConfig>>(() => new WorkspaceService<TConfig>());
|
||||
|
||||
public static WorkspaceService<TConfig> Instance
|
||||
{
|
||||
@@ -52,8 +52,14 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace
|
||||
|
||||
#region Properties
|
||||
|
||||
public Workspace Workspace { get; private set; }
|
||||
/// <summary>
|
||||
/// Workspace object for the service. Virtual to allow for mocking
|
||||
/// </summary>
|
||||
public virtual Workspace Workspace { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Current settings for the workspace
|
||||
/// </summary>
|
||||
public TConfig CurrentSettings { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user