mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-13 17:23:02 -05:00
Merge pull request #31 from Microsoft/feature/listDatabases
Added request to list databases on the server for the current connection
This commit is contained in:
@@ -5,6 +5,8 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Data.Common;
|
||||
using System.Data.SqlClient;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SqlTools.EditorServices.Utility;
|
||||
@@ -194,11 +196,57 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// List all databases on the server specified
|
||||
/// </summary>
|
||||
public ListDatabasesResponse ListDatabases(ListDatabasesParams listDatabasesParams)
|
||||
{
|
||||
// Verify parameters
|
||||
var owner = listDatabasesParams.OwnerUri;
|
||||
if (String.IsNullOrEmpty(owner))
|
||||
{
|
||||
throw new ArgumentException("OwnerUri cannot be null or empty");
|
||||
}
|
||||
|
||||
// Use the existing connection as a base for the search
|
||||
ConnectionInfo info;
|
||||
if (!TryFindConnection(owner, out info))
|
||||
{
|
||||
throw new Exception("Specified OwnerUri \"" + owner + "\" does not have an existing connection");
|
||||
}
|
||||
ConnectionDetails connectionDetails = info.ConnectionDetails.Clone();
|
||||
|
||||
// Connect to master and query sys.databases
|
||||
connectionDetails.DatabaseName = "master";
|
||||
var connection = this.ConnectionFactory.CreateSqlConnection(BuildConnectionString(connectionDetails));
|
||||
connection.Open();
|
||||
|
||||
DbCommand command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT name FROM sys.databases";
|
||||
command.CommandTimeout = 15;
|
||||
command.CommandType = CommandType.Text;
|
||||
var reader = command.ExecuteReader();
|
||||
|
||||
List<string> results = new List<string>();
|
||||
while (reader.Read())
|
||||
{
|
||||
results.Add(reader[0].ToString());
|
||||
}
|
||||
|
||||
connection.Close();
|
||||
|
||||
ListDatabasesResponse response = new ListDatabasesResponse();
|
||||
response.DatabaseNames = results.ToArray();
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
public void InitializeService(IProtocolEndpoint serviceHost)
|
||||
{
|
||||
// Register request and event handlers with the Service Host
|
||||
serviceHost.SetRequestHandler(ConnectionRequest.Type, HandleConnectRequest);
|
||||
serviceHost.SetRequestHandler(DisconnectRequest.Type, HandleDisconnectRequest);
|
||||
serviceHost.SetRequestHandler(ListDatabasesRequest.Type, HandleListDatabasesRequest);
|
||||
|
||||
// Register the configuration update handler
|
||||
WorkspaceService<SqlToolsSettings>.Instance.RegisterConfigChangeCallback(HandleDidChangeConfigurationNotification);
|
||||
@@ -265,6 +313,26 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle requests to list databases on the current server
|
||||
/// </summary>
|
||||
protected async Task HandleListDatabasesRequest(
|
||||
ListDatabasesParams listDatabasesParams,
|
||||
RequestContext<ListDatabasesResponse> requestContext)
|
||||
{
|
||||
Logger.Write(LogLevel.Verbose, "ListDatabasesRequest");
|
||||
|
||||
try
|
||||
{
|
||||
ListDatabasesResponse result = ConnectionService.Instance.ListDatabases(listDatabasesParams);
|
||||
await requestContext.SendResult(result);
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
await requestContext.SendError(ex.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public Task HandleDidChangeConfigurationNotification(
|
||||
SqlToolsSettings newSettings,
|
||||
|
||||
@@ -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.
|
||||
//
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.Connection.Contracts
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension methods for the ConnectionDetails contract class
|
||||
/// </summary>
|
||||
public static class ConnectionDetailsExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Create a copy of a connection details object.
|
||||
/// </summary>
|
||||
public static ConnectionDetails Clone(this ConnectionDetails details)
|
||||
{
|
||||
return new ConnectionDetails()
|
||||
{
|
||||
ServerName = details.ServerName,
|
||||
DatabaseName = details.DatabaseName,
|
||||
UserName = details.UserName,
|
||||
Password = details.Password
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.ServiceLayer.Connection.Contracts
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameters for the List Databases Request.
|
||||
/// </summary>
|
||||
public class ListDatabasesParams
|
||||
{
|
||||
/// <summary>
|
||||
/// URI of the owner of the connection requesting the list of databases.
|
||||
/// </summary>
|
||||
public string OwnerUri { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -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.ServiceLayer.Hosting.Protocol.Contracts;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.Connection.Contracts
|
||||
{
|
||||
/// <summary>
|
||||
/// List databases request mapping entry
|
||||
/// </summary>
|
||||
public class ListDatabasesRequest
|
||||
{
|
||||
public static readonly
|
||||
RequestType<ListDatabasesParams, ListDatabasesResponse> Type =
|
||||
RequestType<ListDatabasesParams, ListDatabasesResponse>.Create("connection/listdatabases");
|
||||
}
|
||||
}
|
||||
@@ -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.ServiceLayer.Connection.Contracts
|
||||
{
|
||||
/// <summary>
|
||||
/// Message format for the list databases response
|
||||
/// </summary>
|
||||
public class ListDatabasesResponse
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the list of database names.
|
||||
/// </summary>
|
||||
public string[] DatabaseNames { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -4,12 +4,17 @@
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Data.Common;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SqlTools.ServiceLayer.Connection;
|
||||
using Microsoft.SqlTools.ServiceLayer.Connection.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol;
|
||||
using Microsoft.SqlTools.ServiceLayer.Test.Utility;
|
||||
using Microsoft.SqlTools.Test.Utility;
|
||||
using Moq;
|
||||
using Moq.Protected;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.Test.Connection
|
||||
@@ -20,6 +25,32 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Connection
|
||||
public class ConnectionServiceTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a mock db command that returns a predefined result set
|
||||
/// </summary>
|
||||
public static DbCommand CreateTestCommand(Dictionary<string, string>[][] data)
|
||||
{
|
||||
var commandMock = new Mock<DbCommand> { CallBase = true };
|
||||
var commandMockSetup = commandMock.Protected()
|
||||
.Setup<DbDataReader>("ExecuteDbDataReader", It.IsAny<CommandBehavior>());
|
||||
|
||||
commandMockSetup.Returns(new TestDbDataReader(data));
|
||||
|
||||
return commandMock.Object;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a mock db connection that returns predefined data when queried for a result set
|
||||
/// </summary>
|
||||
public DbConnection CreateMockDbConnection(Dictionary<string, string>[][] data)
|
||||
{
|
||||
var connectionMock = new Mock<DbConnection> { CallBase = true };
|
||||
connectionMock.Protected()
|
||||
.Setup<DbCommand>("CreateDbCommand")
|
||||
.Returns(CreateTestCommand(data));
|
||||
|
||||
return connectionMock.Object;
|
||||
}
|
||||
|
||||
/// Verify that we can connect to the default database when no database name is
|
||||
/// provided as a parameter.
|
||||
/// </summary>
|
||||
@@ -331,6 +362,55 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Connection
|
||||
Assert.False(disconnectResult);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies the the list databases operation lists database names for the server used by a connection.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void ListDatabasesOnServerForCurrentConnectionReturnsDatabaseNames()
|
||||
{
|
||||
// Result set for the query of database names
|
||||
Dictionary<string, string>[] data =
|
||||
{
|
||||
new Dictionary<string, string> { {"name", "master" } },
|
||||
new Dictionary<string, string> { {"name", "model" } },
|
||||
new Dictionary<string, string> { {"name", "msdb" } },
|
||||
new Dictionary<string, string> { {"name", "tempdb" } },
|
||||
new Dictionary<string, string> { {"name", "mydatabase" } },
|
||||
};
|
||||
|
||||
// Setup mock connection factory to inject query results
|
||||
var mockFactory = new Mock<ISqlConnectionFactory>();
|
||||
mockFactory.Setup(factory => factory.CreateSqlConnection(It.IsAny<string>()))
|
||||
.Returns(CreateMockDbConnection(new[] {data}));
|
||||
var connectionService = new ConnectionService(mockFactory.Object);
|
||||
|
||||
// connect to a database instance
|
||||
string ownerUri = "file://my/sample/file.sql";
|
||||
var connectionResult =
|
||||
connectionService
|
||||
.Connect(new ConnectParams()
|
||||
{
|
||||
OwnerUri = ownerUri,
|
||||
Connection = TestObjects.GetTestConnectionDetails()
|
||||
});
|
||||
|
||||
// verify that a valid connection id was returned
|
||||
Assert.NotEmpty(connectionResult.ConnectionId);
|
||||
|
||||
// list databases for the connection
|
||||
ListDatabasesParams parameters = new ListDatabasesParams();
|
||||
parameters.OwnerUri = ownerUri;
|
||||
var listDatabasesResult = connectionService.ListDatabases(parameters);
|
||||
string[] databaseNames = listDatabasesResult.DatabaseNames;
|
||||
|
||||
Assert.Equal(databaseNames.Length, 5);
|
||||
Assert.Equal(databaseNames[0], "master");
|
||||
Assert.Equal(databaseNames[1], "model");
|
||||
Assert.Equal(databaseNames[2], "msdb");
|
||||
Assert.Equal(databaseNames[3], "tempdb");
|
||||
Assert.Equal(databaseNames[4], "mydatabase");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verify that the SQL parser correctly detects errors in text
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user