mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-02-16 10:58:30 -05:00
Initial metadata and scripting services (#280)
* Initial metadata service and scripting service files * Simple metadata lookup with SMO objects * Add metadata type class * Remove SMO from metadata service. * Cleanup metadata service SQL * Initial MetadataService test * Add scripting commands * Add metadata test case * Remove sleep used for testing * Use random table name in metadata test * Add scripting tests
This commit is contained in:
6
.gitignore
vendored
6
.gitignore
vendored
@@ -284,7 +284,7 @@ Session.vim
|
|||||||
|
|
||||||
# docfx generated files
|
# docfx generated files
|
||||||
_site
|
_site
|
||||||
metadata
|
docs/metadata
|
||||||
|
|
||||||
# Stuff from cake
|
# Stuff from cake
|
||||||
/artifacts/
|
/artifacts/
|
||||||
@@ -292,3 +292,7 @@ metadata
|
|||||||
/.dotnet/
|
/.dotnet/
|
||||||
/test/Microsoft.SqlTools.ServiceLayer.TestEnvConfig/Properties/launchSettings.json
|
/test/Microsoft.SqlTools.ServiceLayer.TestEnvConfig/Properties/launchSettings.json
|
||||||
/test/Microsoft.SqlTools.ServiceLayer.PerfTests/Properties/launchSettings.json
|
/test/Microsoft.SqlTools.ServiceLayer.PerfTests/Properties/launchSettings.json
|
||||||
|
|
||||||
|
# Test output files
|
||||||
|
*cycle*txt*
|
||||||
|
*input*txt*
|
||||||
|
|||||||
@@ -10,7 +10,9 @@ using Microsoft.SqlTools.ServiceLayer.Connection;
|
|||||||
using Microsoft.SqlTools.ServiceLayer.EditData;
|
using Microsoft.SqlTools.ServiceLayer.EditData;
|
||||||
using Microsoft.SqlTools.ServiceLayer.Hosting;
|
using Microsoft.SqlTools.ServiceLayer.Hosting;
|
||||||
using Microsoft.SqlTools.ServiceLayer.LanguageServices;
|
using Microsoft.SqlTools.ServiceLayer.LanguageServices;
|
||||||
|
using Microsoft.SqlTools.ServiceLayer.Metadata;
|
||||||
using Microsoft.SqlTools.ServiceLayer.QueryExecution;
|
using Microsoft.SqlTools.ServiceLayer.QueryExecution;
|
||||||
|
using Microsoft.SqlTools.ServiceLayer.Scripting;
|
||||||
using Microsoft.SqlTools.ServiceLayer.SqlContext;
|
using Microsoft.SqlTools.ServiceLayer.SqlContext;
|
||||||
using Microsoft.SqlTools.ServiceLayer.Workspace;
|
using Microsoft.SqlTools.ServiceLayer.Workspace;
|
||||||
|
|
||||||
@@ -76,6 +78,12 @@ namespace Microsoft.SqlTools.ServiceLayer
|
|||||||
EditDataService.Instance.InitializeService(serviceHost);
|
EditDataService.Instance.InitializeService(serviceHost);
|
||||||
serviceProvider.RegisterSingleService(EditDataService.Instance);
|
serviceProvider.RegisterSingleService(EditDataService.Instance);
|
||||||
|
|
||||||
|
MetadataService.Instance.InitializeService(serviceHost);
|
||||||
|
serviceProvider.RegisterSingleService(MetadataService.Instance);
|
||||||
|
|
||||||
|
ScriptingService.Instance.InitializeService(serviceHost);
|
||||||
|
serviceProvider.RegisterSingleService(ScriptingService.Instance);
|
||||||
|
|
||||||
InitializeHostedServices(serviceProvider, serviceHost);
|
InitializeHostedServices(serviceProvider, serviceHost);
|
||||||
|
|
||||||
serviceHost.InitializeRequestHandlers();
|
serviceHost.InitializeRequestHandlers();
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
//
|
||||||
|
// 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.Metadata.Contracts
|
||||||
|
{
|
||||||
|
public class MetadataQueryParams
|
||||||
|
{
|
||||||
|
public string OwnerUri { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MetadataQueryResult
|
||||||
|
{
|
||||||
|
public ObjectMetadata[] Metadata { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MetadataListRequest
|
||||||
|
{
|
||||||
|
public static readonly
|
||||||
|
RequestType<MetadataQueryParams, MetadataQueryResult> Type =
|
||||||
|
RequestType<MetadataQueryParams, MetadataQueryResult>.Create("metadata/list");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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.
|
||||||
|
//
|
||||||
|
|
||||||
|
namespace Microsoft.SqlTools.ServiceLayer.Metadata.Contracts
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Metadata type enumeration
|
||||||
|
/// </summary>
|
||||||
|
public enum MetadataType
|
||||||
|
{
|
||||||
|
Table = 0,
|
||||||
|
View = 1,
|
||||||
|
SProc = 2,
|
||||||
|
Function = 3
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Object metadata information
|
||||||
|
/// </summary>
|
||||||
|
public class ObjectMetadata
|
||||||
|
{
|
||||||
|
public MetadataType MetadataType { get; set; }
|
||||||
|
|
||||||
|
public string MetadataTypeName { get; set; }
|
||||||
|
|
||||||
|
public string Schema { get; set; }
|
||||||
|
|
||||||
|
public string Name { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
167
src/Microsoft.SqlTools.ServiceLayer/Metadata/MetadataService.cs
Normal file
167
src/Microsoft.SqlTools.ServiceLayer/Metadata/MetadataService.cs
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) Microsoft. All rights reserved.
|
||||||
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Data.SqlClient;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.SqlTools.Hosting.Protocol;
|
||||||
|
using Microsoft.SqlTools.ServiceLayer.Connection;
|
||||||
|
using Microsoft.SqlTools.ServiceLayer.Hosting;
|
||||||
|
using Microsoft.SqlTools.ServiceLayer.Metadata.Contracts;
|
||||||
|
|
||||||
|
namespace Microsoft.SqlTools.ServiceLayer.Metadata
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Main class for Metadata Service functionality
|
||||||
|
/// </summary>
|
||||||
|
public sealed class MetadataService
|
||||||
|
{
|
||||||
|
private static readonly Lazy<MetadataService> LazyInstance = new Lazy<MetadataService>(() => new MetadataService());
|
||||||
|
|
||||||
|
public static MetadataService Instance => LazyInstance.Value;
|
||||||
|
|
||||||
|
private static ConnectionService connectionService = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Internal for testing purposes only
|
||||||
|
/// </summary>
|
||||||
|
internal static ConnectionService ConnectionServiceInstance
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (connectionService == null)
|
||||||
|
{
|
||||||
|
connectionService = ConnectionService.Instance;
|
||||||
|
}
|
||||||
|
return connectionService;
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
connectionService = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes the Metadata Service instance
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="serviceHost"></param>
|
||||||
|
/// <param name="context"></param>
|
||||||
|
public void InitializeService(ServiceHost serviceHost)
|
||||||
|
{
|
||||||
|
serviceHost.SetRequestHandler(MetadataListRequest.Type, HandleMetadataListRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handle a metadata query request
|
||||||
|
/// </summary>
|
||||||
|
internal static async Task HandleMetadataListRequest(
|
||||||
|
MetadataQueryParams metadataParams,
|
||||||
|
RequestContext<MetadataQueryResult> requestContext)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ConnectionInfo connInfo;
|
||||||
|
MetadataService.ConnectionServiceInstance.TryFindConnection(
|
||||||
|
metadataParams.OwnerUri,
|
||||||
|
out connInfo);
|
||||||
|
|
||||||
|
var metadata = new List<ObjectMetadata>();
|
||||||
|
if (connInfo != null)
|
||||||
|
{
|
||||||
|
SqlConnection sqlConn = OpenMetadataConnection(connInfo);
|
||||||
|
ReadMetadata(sqlConn, metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
await requestContext.SendResult(new MetadataQueryResult()
|
||||||
|
{
|
||||||
|
Metadata = metadata.ToArray()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await requestContext.SendError(ex.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a SqlConnection to use for querying metadata
|
||||||
|
/// </summary>
|
||||||
|
internal static SqlConnection OpenMetadataConnection(ConnectionInfo connInfo)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// increase the connection timeout to at least 30 seconds and and build connection string
|
||||||
|
// enable PersistSecurityInfo to handle issues in SMO where the connection context is lost in reconnections
|
||||||
|
int? originalTimeout = connInfo.ConnectionDetails.ConnectTimeout;
|
||||||
|
bool? originalPersistSecurityInfo = connInfo.ConnectionDetails.PersistSecurityInfo;
|
||||||
|
connInfo.ConnectionDetails.ConnectTimeout = Math.Max(30, originalTimeout ?? 0);
|
||||||
|
connInfo.ConnectionDetails.PersistSecurityInfo = true;
|
||||||
|
string connectionString = ConnectionService.BuildConnectionString(connInfo.ConnectionDetails);
|
||||||
|
connInfo.ConnectionDetails.ConnectTimeout = originalTimeout;
|
||||||
|
connInfo.ConnectionDetails.PersistSecurityInfo = originalPersistSecurityInfo;
|
||||||
|
|
||||||
|
// open a dedicated binding server connection
|
||||||
|
SqlConnection sqlConn = new SqlConnection(connectionString);
|
||||||
|
sqlConn.Open();
|
||||||
|
return sqlConn;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Read metadata for the current connection
|
||||||
|
/// </summary>
|
||||||
|
internal static void ReadMetadata(SqlConnection sqlConn, List<ObjectMetadata> metadata)
|
||||||
|
{
|
||||||
|
string sql =
|
||||||
|
@"SELECT s.name AS schema_name, o.[name] AS object_name, o.[type] AS object_type
|
||||||
|
FROM sys.all_objects o
|
||||||
|
INNER JOIN sys.schemas s ON o.schema_id = s.schema_id
|
||||||
|
WHERE o.is_ms_shipped != 1
|
||||||
|
AND (o.[type] = 'P' OR o.[type] = 'V' OR o.[type] = 'U')
|
||||||
|
ORDER BY object_type, schema_name, object_name";
|
||||||
|
|
||||||
|
using (SqlCommand sqlCommand = new SqlCommand(sql, sqlConn))
|
||||||
|
{
|
||||||
|
using (var reader = sqlCommand.ExecuteReader())
|
||||||
|
{
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
var schemaName = reader[0] as string;
|
||||||
|
var objectName = reader[1] as string;
|
||||||
|
var objectType = reader[2] as string;
|
||||||
|
|
||||||
|
MetadataType metadataType;
|
||||||
|
if (objectType.StartsWith("V"))
|
||||||
|
{
|
||||||
|
metadataType = MetadataType.View;
|
||||||
|
}
|
||||||
|
else if (objectType.StartsWith("P"))
|
||||||
|
{
|
||||||
|
metadataType = MetadataType.SProc;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
metadataType = MetadataType.Table;
|
||||||
|
}
|
||||||
|
|
||||||
|
metadata.Add(new ObjectMetadata
|
||||||
|
{
|
||||||
|
MetadataType = metadataType,
|
||||||
|
Schema = schemaName,
|
||||||
|
Name = objectName
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
//
|
||||||
|
// 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;
|
||||||
|
using Microsoft.SqlTools.ServiceLayer.Metadata.Contracts;
|
||||||
|
|
||||||
|
namespace Microsoft.SqlTools.ServiceLayer.Scripting.Contracts
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The type of scripting operation requested
|
||||||
|
/// </summary>
|
||||||
|
public enum ScriptOperation
|
||||||
|
{
|
||||||
|
Select = 0,
|
||||||
|
Create = 1,
|
||||||
|
Insert = 2,
|
||||||
|
Update = 3,
|
||||||
|
Delete = 4
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Script as request parameter type
|
||||||
|
/// </summary>
|
||||||
|
public class ScriptingScriptAsParams
|
||||||
|
{
|
||||||
|
public string OwnerUri { get; set; }
|
||||||
|
|
||||||
|
public ScriptOperation Operation { get; set; }
|
||||||
|
|
||||||
|
public ObjectMetadata Metadata { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Script as request result type
|
||||||
|
/// </summary>
|
||||||
|
public class ScriptingScriptAsResult
|
||||||
|
{
|
||||||
|
public string OwnerUri { get; set; }
|
||||||
|
|
||||||
|
public string Script { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Script as request message type
|
||||||
|
/// </summary>
|
||||||
|
public class ScriptingScriptAsRequest
|
||||||
|
{
|
||||||
|
public static readonly
|
||||||
|
RequestType<ScriptingScriptAsParams, ScriptingScriptAsResult> Type =
|
||||||
|
RequestType<ScriptingScriptAsParams, ScriptingScriptAsResult>.Create("scripting/scriptas");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) Microsoft. All rights reserved.
|
||||||
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.SqlTools.Hosting.Protocol;
|
||||||
|
using Microsoft.SqlTools.ServiceLayer.Hosting;
|
||||||
|
using Microsoft.SqlTools.ServiceLayer.Scripting.Contracts;
|
||||||
|
|
||||||
|
namespace Microsoft.SqlTools.ServiceLayer.Scripting
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Main class for Scripting Service functionality
|
||||||
|
/// </summary>
|
||||||
|
public sealed class ScriptingService
|
||||||
|
{
|
||||||
|
private static readonly Lazy<ScriptingService> LazyInstance = new Lazy<ScriptingService>(() => new ScriptingService());
|
||||||
|
|
||||||
|
public static ScriptingService Instance => LazyInstance.Value;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes the Scripting Service instance
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="serviceHost"></param>
|
||||||
|
/// <param name="context"></param>
|
||||||
|
public void InitializeService(ServiceHost serviceHost)
|
||||||
|
{
|
||||||
|
serviceHost.SetRequestHandler(ScriptingScriptAsRequest.Type, HandleScriptingScriptAsRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handles script as request messages
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="scriptingParams"></param>
|
||||||
|
/// <param name="requestContext"></param>
|
||||||
|
internal static async Task HandleScriptingScriptAsRequest(
|
||||||
|
ScriptingScriptAsParams scriptingParams,
|
||||||
|
RequestContext<ScriptingScriptAsResult> requestContext)
|
||||||
|
{
|
||||||
|
string script = string.Empty;
|
||||||
|
if (scriptingParams.Operation == ScriptOperation.Select)
|
||||||
|
{
|
||||||
|
script = string.Format(
|
||||||
|
@"SELECT *
|
||||||
|
FROM {0}.{1}",
|
||||||
|
scriptingParams.Metadata.Schema, scriptingParams.Metadata.Name);
|
||||||
|
}
|
||||||
|
else if (scriptingParams.Operation == ScriptOperation.Create)
|
||||||
|
{
|
||||||
|
script = string.Format(
|
||||||
|
@"CREATE {0}.{1}",
|
||||||
|
scriptingParams.Metadata.Schema, scriptingParams.Metadata.Name);
|
||||||
|
}
|
||||||
|
else if (scriptingParams.Operation == ScriptOperation.Update)
|
||||||
|
{
|
||||||
|
script = string.Format(
|
||||||
|
@"UPDATE {0}.{1}",
|
||||||
|
scriptingParams.Metadata.Schema, scriptingParams.Metadata.Name);
|
||||||
|
}
|
||||||
|
else if (scriptingParams.Operation == ScriptOperation.Insert)
|
||||||
|
{
|
||||||
|
script = string.Format(
|
||||||
|
@"INSERT {0}.{1}",
|
||||||
|
scriptingParams.Metadata.Schema, scriptingParams.Metadata.Name);
|
||||||
|
}
|
||||||
|
else if (scriptingParams.Operation == ScriptOperation.Delete)
|
||||||
|
{
|
||||||
|
script = string.Format(
|
||||||
|
@"DELETE {0}.{1}",
|
||||||
|
scriptingParams.Metadata.Schema, scriptingParams.Metadata.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
await requestContext.SendResult(new ScriptingScriptAsResult()
|
||||||
|
{
|
||||||
|
OwnerUri = scriptingParams.OwnerUri,
|
||||||
|
Script = script
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
//
|
||||||
|
// 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.Workspace.Contracts;
|
||||||
|
using Xunit;
|
||||||
|
using Microsoft.SqlTools.ServiceLayer.Test.Common;
|
||||||
|
using Microsoft.SqlTools.ServiceLayer.IntegrationTests.Utility;
|
||||||
|
using Microsoft.SqlTools.ServiceLayer.Metadata;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.SqlTools.ServiceLayer.Metadata.Contracts;
|
||||||
|
using System.Data.SqlClient;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Metadata
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Tests for the Metadata service component
|
||||||
|
/// </summary>
|
||||||
|
public class MetadataServiceTests
|
||||||
|
{
|
||||||
|
private string testTableSchema = "dbo";
|
||||||
|
private string testTableName = "MetadataTestTable";
|
||||||
|
|
||||||
|
private LiveConnectionHelper.TestConnectionResult GetLiveAutoCompleteTestObjects()
|
||||||
|
{
|
||||||
|
var textDocument = new TextDocumentPosition
|
||||||
|
{
|
||||||
|
TextDocument = new TextDocumentIdentifier { Uri = Constants.OwnerUri },
|
||||||
|
Position = new Position
|
||||||
|
{
|
||||||
|
Line = 0,
|
||||||
|
Character = 0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = LiveConnectionHelper.InitLiveConnectionInfo();
|
||||||
|
result.TextDocumentPosition = textDocument;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateTestTable(SqlConnection sqlConn)
|
||||||
|
{
|
||||||
|
string sql = string.Format("IF OBJECT_ID('{0}.{1}', 'U') IS NULL CREATE TABLE {0}.{1}(id int)",
|
||||||
|
this.testTableSchema, this.testTableName);
|
||||||
|
using (var sqlCommand = new SqlCommand(sql, sqlConn))
|
||||||
|
{
|
||||||
|
sqlCommand.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DeleteTestTable(SqlConnection sqlConn)
|
||||||
|
{
|
||||||
|
string sql = string.Format("IF OBJECT_ID('{0}.{1}', 'U') IS NOT NULL DROP TABLE {0}.{1}",
|
||||||
|
this.testTableSchema, this.testTableName);
|
||||||
|
using (var sqlCommand = new SqlCommand(sql, sqlConn))
|
||||||
|
{
|
||||||
|
sqlCommand.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Verify that the metadata service correctly returns details for user tables
|
||||||
|
/// </summary>
|
||||||
|
[Fact]
|
||||||
|
public void MetadataReturnsUserTable()
|
||||||
|
{
|
||||||
|
this.testTableName += new Random().Next(1000000, 9999999).ToString();
|
||||||
|
|
||||||
|
var result = GetLiveAutoCompleteTestObjects();
|
||||||
|
var sqlConn = MetadataService.OpenMetadataConnection(result.ConnectionInfo);
|
||||||
|
Assert.NotNull(sqlConn);
|
||||||
|
|
||||||
|
CreateTestTable(sqlConn);
|
||||||
|
|
||||||
|
var metadata = new List<ObjectMetadata>();
|
||||||
|
MetadataService.ReadMetadata(sqlConn, metadata);
|
||||||
|
Assert.NotNull(metadata.Count > 0);
|
||||||
|
|
||||||
|
bool foundTestTable = false;
|
||||||
|
foreach (var item in metadata)
|
||||||
|
{
|
||||||
|
if (string.Equals(item.Schema, this.testTableSchema, StringComparison.OrdinalIgnoreCase)
|
||||||
|
&& string.Equals(item.Name, this.testTableName, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
foundTestTable = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Assert.True(foundTestTable);
|
||||||
|
|
||||||
|
DeleteTestTable(sqlConn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
//
|
||||||
|
// 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.Workspace.Contracts;
|
||||||
|
using Xunit;
|
||||||
|
using Microsoft.SqlTools.ServiceLayer.IntegrationTests.Utility;
|
||||||
|
using Microsoft.SqlTools.ServiceLayer.Metadata.Contracts;
|
||||||
|
using Microsoft.SqlTools.ServiceLayer.Scripting;
|
||||||
|
using Moq;
|
||||||
|
using Microsoft.SqlTools.Hosting.Protocol;
|
||||||
|
using Microsoft.SqlTools.ServiceLayer.Scripting.Contracts;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Scripting
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Tests for the scripting service component
|
||||||
|
/// </summary>
|
||||||
|
public class ScriptingServiceTests
|
||||||
|
{
|
||||||
|
private const string SchemaName = "sys";
|
||||||
|
private const string TableName = "all_objects";
|
||||||
|
|
||||||
|
private LiveConnectionHelper.TestConnectionResult GetLiveAutoCompleteTestObjects()
|
||||||
|
{
|
||||||
|
var textDocument = new TextDocumentPosition
|
||||||
|
{
|
||||||
|
TextDocument = new TextDocumentIdentifier { Uri = Test.Common.Constants.OwnerUri },
|
||||||
|
Position = new Position
|
||||||
|
{
|
||||||
|
Line = 0,
|
||||||
|
Character = 0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = LiveConnectionHelper.InitLiveConnectionInfo();
|
||||||
|
result.TextDocumentPosition = textDocument;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private async Task<Mock<RequestContext<ScriptingScriptAsResult>>> SendAndValidateScriptRequest(ScriptOperation operation)
|
||||||
|
{
|
||||||
|
var result = GetLiveAutoCompleteTestObjects();
|
||||||
|
var requestContext = new Mock<RequestContext<ScriptingScriptAsResult>>();
|
||||||
|
requestContext.Setup(x => x.SendResult(It.IsAny<ScriptingScriptAsResult>())).Returns(Task.FromResult(new object()));
|
||||||
|
|
||||||
|
var scriptingParams = new ScriptingScriptAsParams
|
||||||
|
{
|
||||||
|
OwnerUri = Test.Common.Constants.OwnerUri,
|
||||||
|
Operation = operation,
|
||||||
|
Metadata = new ObjectMetadata()
|
||||||
|
{
|
||||||
|
MetadataType = MetadataType.Table,
|
||||||
|
MetadataTypeName = "View",
|
||||||
|
Schema = SchemaName,
|
||||||
|
Name = TableName
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
await ScriptingService.HandleScriptingScriptAsRequest(scriptingParams, requestContext.Object);
|
||||||
|
|
||||||
|
requestContext.Verify(x => x.SendResult(It.Is<ScriptingScriptAsResult>(
|
||||||
|
i => i.Script.Contains(operation.ToString().ToUpper())
|
||||||
|
&& i.Script.Contains(TableName)
|
||||||
|
&& i.Script.Contains(SchemaName))));
|
||||||
|
|
||||||
|
return requestContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Verify the script as select request
|
||||||
|
/// </summary>
|
||||||
|
[Fact]
|
||||||
|
public async void ScriptingScriptAsSelect()
|
||||||
|
{
|
||||||
|
await SendAndValidateScriptRequest(ScriptOperation.Select);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Verify the script as create request
|
||||||
|
/// </summary>
|
||||||
|
[Fact]
|
||||||
|
public async void ScriptingScriptAsCreate()
|
||||||
|
{
|
||||||
|
await SendAndValidateScriptRequest(ScriptOperation.Create);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Verify the script as insert request
|
||||||
|
/// </summary>
|
||||||
|
[Fact]
|
||||||
|
public async void ScriptingScriptAsInsert()
|
||||||
|
{
|
||||||
|
await SendAndValidateScriptRequest(ScriptOperation.Insert);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Verify the script as update request
|
||||||
|
/// </summary>
|
||||||
|
[Fact]
|
||||||
|
public async void ScriptingScriptAsUpdate()
|
||||||
|
{
|
||||||
|
await SendAndValidateScriptRequest(ScriptOperation.Update);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Verify the script as delete request
|
||||||
|
/// </summary>
|
||||||
|
[Fact]
|
||||||
|
public async void ScriptingScriptAsDelete()
|
||||||
|
{
|
||||||
|
await SendAndValidateScriptRequest(ScriptOperation.Delete);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user