Execute SQL statement at cursor location (#412)

* Stage changes to other machine

* Parse sql statement from script document

* Fix a few typos and minor changes

* Fix bug
This commit is contained in:
Karl Burtram
2017-07-13 20:33:05 -07:00
committed by GitHub
parent 005fc9e4df
commit cfa78bbc3b
4 changed files with 140 additions and 25 deletions

View File

@@ -1679,5 +1679,42 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
FileUtilities.SafeDirectoryDelete(FileUtilities.PeekDefinitionTempFolder, true);
}
}
internal string ParseStatementAtPosition(string sql, int line, int column)
{
// adjust from 0-based to 1-based index
int parserLine = line + 1;
int parserColumn = column + 1;
// parse current SQL file contents to retrieve a list of errors
ParseResult parseResult = Parser.Parse(sql, this.DefaultParseOptions);
if (parseResult != null && parseResult.Script != null && parseResult.Script.Batches != null)
{
foreach (var batch in parseResult.Script.Batches)
{
if (batch.Statements == null)
{
continue;
}
// check if the batch matches parameters
if (batch.StartLocation.LineNumber <= parserLine
&& batch.EndLocation.LineNumber >= parserLine)
{
foreach (var statement in batch.Statements)
{
// check if the statement matches parameters
if (statement.StartLocation.LineNumber <= parserLine
&& statement.EndLocation.LineNumber >= parserLine)
{
return statement.Sql;
}
}
}
}
}
return string.Empty;
}
}
}

View File

@@ -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 Microsoft.SqlTools.Hosting.Protocol.Contracts;
namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts.ExecuteRequests
{
/// <summary>
/// Parameters for executing a query from a document open in the workspace
/// </summary>
public class ExecuteDocumentStatementParams : ExecuteRequestParamsBase
{
/// <summary>
/// Line in the document for the location of the SQL statement
/// </summary>
public int Line { get; set; }
/// <summary>
/// Column in the document for the location of the SQL statement
/// </summary>
public int Column { get; set; }
}
public class ExecuteDocumentStatementRequest
{
public static readonly
RequestType<ExecuteDocumentStatementParams, ExecuteRequestResult> Type =
RequestType<ExecuteDocumentStatementParams, ExecuteRequestResult>.Create("query/executedocumentstatement");
}
}

View File

@@ -129,6 +129,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
{
// Register handlers for requests
serviceHost.SetRequestHandler(ExecuteDocumentSelectionRequest.Type, HandleExecuteRequest);
serviceHost.SetRequestHandler(ExecuteDocumentStatementRequest.Type, HandleExecuteRequest);
serviceHost.SetRequestHandler(ExecuteStringRequest.Type, HandleExecuteRequest);
serviceHost.SetRequestHandler(SubsetRequest.Type, HandleResultSubsetRequest);
serviceHost.SetRequestHandler(QueryDisposeRequest.Type, HandleDisposeRequest);
@@ -691,32 +692,14 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
ExecuteDocumentSelectionParams docRequest = request as ExecuteDocumentSelectionParams;
if (docRequest != null)
{
// Get the document from the parameters
ScriptFile queryFile = WorkspaceService.Workspace.GetFile(docRequest.OwnerUri);
if (queryFile == null)
{
return string.Empty;
}
// If a selection was not provided, use the entire document
if (docRequest.QuerySelection == null)
{
return queryFile.Contents;
}
return GetSqlTextFromSelectionData(docRequest.OwnerUri, docRequest.QuerySelection);
}
// A selection was provided, so get the lines in the selected range
string[] queryTextArray = queryFile.GetLinesInRange(
new BufferRange(
new BufferPosition(
docRequest.QuerySelection.StartLine + 1,
docRequest.QuerySelection.StartColumn + 1
),
new BufferPosition(
docRequest.QuerySelection.EndLine + 1,
docRequest.QuerySelection.EndColumn + 1
)
)
);
return string.Join(Environment.NewLine, queryTextArray);
// If it is a document statement, we'll retrieve the text from the document
ExecuteDocumentStatementParams stmtRequest = request as ExecuteDocumentStatementParams;
if (stmtRequest != null)
{
return GetSqlStatementAtPosition(stmtRequest.OwnerUri, stmtRequest.Line, stmtRequest.Column);
}
// If it is an ExecuteStringParams, return the text as is
@@ -730,6 +713,55 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
throw new InvalidCastException("Invalid request type");
}
/// <summary>
/// Return portion of document corresponding to the selection range
/// </summary>
internal string GetSqlTextFromSelectionData(string ownerUri, SelectionData selection)
{
// Get the document from the parameters
ScriptFile queryFile = WorkspaceService.Workspace.GetFile(ownerUri);
if (queryFile == null)
{
return string.Empty;
}
// If a selection was not provided, use the entire document
if (selection == null)
{
return queryFile.Contents;
}
// A selection was provided, so get the lines in the selected range
string[] queryTextArray = queryFile.GetLinesInRange(
new BufferRange(
new BufferPosition(
selection.StartLine + 1,
selection.StartColumn + 1
),
new BufferPosition(
selection.EndLine + 1,
selection.EndColumn + 1
)
)
);
return string.Join(Environment.NewLine, queryTextArray);
}
/// <summary>
/// Return portion of document corresponding to the statement at the line and column
/// </summary>
internal string GetSqlStatementAtPosition(string ownerUri, int line, int column)
{
// Get the document from the parameters
ScriptFile queryFile = WorkspaceService.Workspace.GetFile(ownerUri);
if (queryFile == null)
{
return string.Empty;
}
return LanguageServices.LanguageService.Instance.ParseStatementAtPosition(
queryFile.Contents, line, column);
}
/// Internal for testing purposes
internal Task UpdateSettings(SqlToolsSettings newSettings, SqlToolsSettings oldSettings, EventContext eventContext)
{

View File

@@ -21,6 +21,20 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
#region Get SQL Tests
[Fact]
public void ExecuteDocumentStatementTest()
{
string query = string.Format("{0}{1}GO{1}{0}", Constants.StandardQuery, Environment.NewLine);
var workspaceService = GetDefaultWorkspaceService(query);
var queryService = new QueryExecutionService(null, workspaceService);
var queryParams = new ExecuteDocumentStatementParams { OwnerUri = Constants.OwnerUri, Line = 0, Column = 0 };
var queryText = queryService.GetSqlText(queryParams);
// The text should match the standard query
Assert.Equal(queryText, Constants.StandardQuery);
}
[Fact]
public void GetSqlTextFromDocumentRequestFull()
{