diff --git a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/Contracts/QueryExecuteRequest.cs b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/Contracts/QueryExecuteRequest.cs
index 4d9bf3ba..7630b712 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/Contracts/QueryExecuteRequest.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/Contracts/QueryExecuteRequest.cs
@@ -29,7 +29,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts
public class QueryExecuteResult
{
///
- /// Connection error messages. Optional, can be set to null to indicate no errors
+ /// Informational messages from the query runner. Optional, can be set to null.
///
public string Messages { get; set; }
}
diff --git a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/QueryExecutionService.cs b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/QueryExecutionService.cs
index c97a566b..04705004 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/QueryExecutionService.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/QueryExecutionService.cs
@@ -424,6 +424,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
OwnerUri = executeParams.OwnerUri,
BatchSummaries = q.BatchSummaries
};
+
await requestContext.SendEvent(QueryExecuteCompleteEvent.Type, eventParams);
};
@@ -470,9 +471,15 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
query.Execute();
// Send back a result showing we were successful
+ string messages = null;
+ if (query.Batches.Length == 0)
+ {
+ // If there were no batches to execute, send back an informational message that the commands were completed successfully
+ messages = SR.QueryServiceCompletedSuccessfully;
+ }
await requestContext.SendResult(new QueryExecuteResult
{
- Messages = null
+ Messages = messages
});
}
diff --git a/test/Microsoft.SqlTools.ServiceLayer.TestDriver/Tests/QueryExecutionTests.cs b/test/Microsoft.SqlTools.ServiceLayer.TestDriver/Tests/QueryExecutionTests.cs
index d57f91d9..462dd354 100644
--- a/test/Microsoft.SqlTools.ServiceLayer.TestDriver/Tests/QueryExecutionTests.cs
+++ b/test/Microsoft.SqlTools.ServiceLayer.TestDriver/Tests/QueryExecutionTests.cs
@@ -7,6 +7,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using Microsoft.SqlTools.ServiceLayer;
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts;
using Microsoft.SqlTools.ServiceLayer.TestDriver.Utility;
using Microsoft.SqlTools.ServiceLayer.Workspace.Contracts;
@@ -323,5 +324,36 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
await testHelper.Disconnect(queryTempFile.FilePath);
}
}
+
+ [Fact]
+ public async Task NoOpQueryReturnsMessage()
+ {
+ // Given queries that do nothing (no-ops)...
+ var queries = new string[]
+ {
+ "-- no-op",
+ "GO",
+ "GO -- no-op"
+ };
+
+ using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
+ using (TestHelper testHelper = new TestHelper())
+ {
+ foreach (var query in queries)
+ {
+ Assert.True(await testHelper.Connect(queryTempFile.FilePath, ConnectionTestUtils.LocalhostConnection));
+
+ // If the queries are executed...
+ var queryResult = await testHelper.RunQueryAsync(queryTempFile.FilePath, query);
+
+ // Then I expect messages that the commands were completed successfully to be in the result
+ Assert.NotNull(queryResult);
+ Assert.NotNull(queryResult.Messages);
+ Assert.Equal("Commands completed successfully.", queryResult.Messages);
+
+ await testHelper.Disconnect(queryTempFile.FilePath);
+ }
+ }
+ }
}
}
diff --git a/test/Microsoft.SqlTools.ServiceLayer.TestDriver/Tests/TestHelper.cs b/test/Microsoft.SqlTools.ServiceLayer.TestDriver/Tests/TestHelper.cs
index 7f675941..3f3906a2 100644
--- a/test/Microsoft.SqlTools.ServiceLayer.TestDriver/Tests/TestHelper.cs
+++ b/test/Microsoft.SqlTools.ServiceLayer.TestDriver/Tests/TestHelper.cs
@@ -272,6 +272,23 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
return null;
}
}
+
+ ///
+ /// Run a query using a given connection bound to a URI. This method only waits for the initial response from query
+ /// execution (QueryExecuteResult). It is up to the caller to wait for the QueryExecuteCompleteEvent if they are interested.
+ ///
+ public async Task RunQueryAsync(string ownerUri, string query, int timeoutMilliseconds = 5000)
+ {
+ WriteToFile(ownerUri, query);
+
+ var queryParams = new QueryExecuteParams
+ {
+ OwnerUri = ownerUri,
+ QuerySelection = null
+ };
+
+ return await Driver.SendRequest(QueryExecuteRequest.Type, queryParams);
+ }
///
/// Request to cancel an executing query