mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-02-16 10:58:30 -05:00
Fix/peek def mac (#170)
* Fix Integrated auth error and Uri for *nix/Mac * Format code * Add Logging and unit tests * Modify tests for Windows: * Workaround missing default schema on *nix and Mac * Add unit tests * Correct comments * Change loop length * Fix Log message
This commit is contained in:
@@ -6,8 +6,12 @@ using System;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
|
using System.Data.SqlClient;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using Microsoft.SqlServer.Management.Smo;
|
using Microsoft.SqlServer.Management.Smo;
|
||||||
|
using Microsoft.SqlServer.Management.Common;
|
||||||
using Microsoft.SqlServer.Management.SqlParser.Intellisense;
|
using Microsoft.SqlServer.Management.SqlParser.Intellisense;
|
||||||
|
using Microsoft.SqlTools.ServiceLayer.Utility;
|
||||||
using Microsoft.SqlTools.ServiceLayer.Connection;
|
using Microsoft.SqlTools.ServiceLayer.Connection;
|
||||||
using Microsoft.SqlTools.ServiceLayer.Workspace.Contracts;
|
using Microsoft.SqlTools.ServiceLayer.Workspace.Contracts;
|
||||||
|
|
||||||
@@ -37,9 +41,21 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
|||||||
{
|
{
|
||||||
if (this.connectionInfo.SqlConnection != null)
|
if (this.connectionInfo.SqlConnection != null)
|
||||||
{
|
{
|
||||||
Server server = new Server(this.connectionInfo.SqlConnection.DataSource);
|
try
|
||||||
return server.Databases[this.connectionInfo.SqlConnection.Database];
|
{
|
||||||
|
// Get server object from connection
|
||||||
|
string connectionString = ConnectionService.BuildConnectionString(this.connectionInfo.ConnectionDetails);
|
||||||
|
SqlConnection sqlConn = new SqlConnection(connectionString);
|
||||||
|
sqlConn.Open();
|
||||||
|
ServerConnection serverConn = new ServerConnection(sqlConn);
|
||||||
|
Server server = new Server(serverConn);
|
||||||
|
return server.Databases[this.connectionInfo.SqlConnection.Database];
|
||||||
|
}
|
||||||
|
catch(Exception ex)
|
||||||
|
{
|
||||||
|
Logger.Write(LogLevel.Error, "Exception at PeekDefinition Database.get() : " + ex.Message);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -83,11 +99,19 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Convert a file to a location array containing a location object as expected by the extension
|
/// Convert a file to a location array containing a location object as expected by the extension
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private Location[] GetLocationFromFile(string tempFileName, int lineNumber)
|
internal Location[] GetLocationFromFile(string tempFileName, int lineNumber)
|
||||||
{
|
{
|
||||||
|
if (Path.DirectorySeparatorChar.Equals('/'))
|
||||||
|
{
|
||||||
|
tempFileName = "file:" + tempFileName;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tempFileName = new Uri(tempFileName).AbsoluteUri;
|
||||||
|
}
|
||||||
Location[] locations = new[] {
|
Location[] locations = new[] {
|
||||||
new Location {
|
new Location {
|
||||||
Uri = new Uri(tempFileName).AbsoluteUri,
|
Uri = tempFileName,
|
||||||
Range = new Range {
|
Range = new Range {
|
||||||
Start = new Position { Line = lineNumber, Character = 1},
|
Start = new Position { Line = lineNumber, Character = 1},
|
||||||
End = new Position { Line = lineNumber + 1, Character = 1}
|
End = new Position { Line = lineNumber + 1, Character = 1}
|
||||||
@@ -135,6 +159,15 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
|||||||
DeclarationType type = declarationItem.Type;
|
DeclarationType type = declarationItem.Type;
|
||||||
if (sqlScriptGetters.ContainsKey(type) && sqlObjectTypes.ContainsKey(type))
|
if (sqlScriptGetters.ContainsKey(type) && sqlObjectTypes.ContainsKey(type))
|
||||||
{
|
{
|
||||||
|
// On *nix and mac systems, the defaultSchema property throws an Exception when accessed.
|
||||||
|
// This workaround ensures that a schema name is present by attempting
|
||||||
|
// to get the schema name from the declaration item
|
||||||
|
// If all fails, the default schema name is assumed to be "dbo"
|
||||||
|
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && string.IsNullOrEmpty(schemaName))
|
||||||
|
{
|
||||||
|
string fullObjectName = declarationItem.DatabaseQualifiedName;
|
||||||
|
schemaName = this.GetSchemaFromDatabaseQualifiedName(fullObjectName, tokenText);
|
||||||
|
}
|
||||||
return GetSqlObjectDefinition(
|
return GetSqlObjectDefinition(
|
||||||
sqlScriptGetters[type],
|
sqlScriptGetters[type],
|
||||||
tokenText,
|
tokenText,
|
||||||
@@ -148,6 +181,25 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Return schema name from the full name of the database. If schema is missing return dbo as schema name.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fullObjectName"> The full database qualified name(database.schema.object)</param>
|
||||||
|
/// <param name="objectName"> Object name</param>
|
||||||
|
/// <returns>Schema name</returns>
|
||||||
|
internal string GetSchemaFromDatabaseQualifiedName(string fullObjectName, string objectName)
|
||||||
|
{
|
||||||
|
string[] tokens = fullObjectName.Split('.');
|
||||||
|
for (int i = tokens.Length - 1; i > 0; i--)
|
||||||
|
{
|
||||||
|
if(tokens[i].Equals(objectName))
|
||||||
|
{
|
||||||
|
return tokens[i-1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "dbo";
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Script a table using SMO
|
/// Script a table using SMO
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -2,10 +2,11 @@
|
|||||||
// Copyright (c) Microsoft. All rights reserved.
|
// Copyright (c) Microsoft. All rights reserved.
|
||||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||||
//
|
//
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.IO;
|
using System.Runtime.InteropServices;
|
||||||
using System;
|
|
||||||
using Microsoft.SqlServer.Management.SqlParser.Binder;
|
using Microsoft.SqlServer.Management.SqlParser.Binder;
|
||||||
using Microsoft.SqlServer.Management.SqlParser.MetadataProvider;
|
using Microsoft.SqlServer.Management.SqlParser.MetadataProvider;
|
||||||
using Microsoft.SqlServer.Management.SqlParser.Parser;
|
using Microsoft.SqlServer.Management.SqlParser.Parser;
|
||||||
@@ -46,10 +47,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices
|
|||||||
|
|
||||||
private const string OwnerUri = "testFile1";
|
private const string OwnerUri = "testFile1";
|
||||||
|
|
||||||
private const string ViewOwnerUri = "testFile2";
|
|
||||||
|
|
||||||
private const string TriggerOwnerUri = "testFile3";
|
|
||||||
|
|
||||||
private void InitializeTestObjects()
|
private void InitializeTestObjects()
|
||||||
{
|
{
|
||||||
// initial cursor position in the script file
|
// initial cursor position in the script file
|
||||||
@@ -126,15 +123,74 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices
|
|||||||
|
|
||||||
// verify that send result was not called
|
// verify that send result was not called
|
||||||
requestContext.Verify(m => m.SendResult(It.IsAny<Location[]>()), Times.Never());
|
requestContext.Verify(m => m.SendResult(It.IsAny<Location[]>()), Times.Never());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests creating location objects on windows and non-windows systems
|
||||||
|
/// </summary>
|
||||||
|
[Fact]
|
||||||
|
public void GetLocationFromFileForValidFilePathTest()
|
||||||
|
{
|
||||||
|
String filePath = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "C:\\test\\script.sql" : "/test/script.sql";
|
||||||
|
PeekDefinition peekDefinition = new PeekDefinition(null);
|
||||||
|
Location[] locations = peekDefinition.GetLocationFromFile(filePath, 0);
|
||||||
|
|
||||||
|
String expectedFilePath = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "file:///C:/test/script.sql" : "file:/test/script.sql";
|
||||||
|
Assert.Equal(locations[0].Uri, expectedFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Test PeekDefinition.GetSchemaFromDatabaseQualifiedName with a valid database name
|
||||||
|
/// </summary>
|
||||||
|
[Fact]
|
||||||
|
public void GetSchemaFromDatabaseQualifiedNameWithValidNameTest()
|
||||||
|
{
|
||||||
|
PeekDefinition peekDefinition = new PeekDefinition(null);
|
||||||
|
string validDatabaseQualifiedName = "master.test.test_table";
|
||||||
|
string objectName = "test_table";
|
||||||
|
string expectedSchemaName = "test";
|
||||||
|
|
||||||
|
string actualSchemaName = peekDefinition.GetSchemaFromDatabaseQualifiedName(validDatabaseQualifiedName, objectName);
|
||||||
|
Assert.Equal(actualSchemaName, expectedSchemaName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Test PeekDefinition.GetSchemaFromDatabaseQualifiedName with a valid object name and no schema
|
||||||
|
/// </summary>
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GetSchemaFromDatabaseQualifiedNameWithNoSchemaTest()
|
||||||
|
{
|
||||||
|
PeekDefinition peekDefinition = new PeekDefinition(null);
|
||||||
|
string validDatabaseQualifiedName = "test_table";
|
||||||
|
string objectName = "test_table";
|
||||||
|
string expectedSchemaName = "dbo";
|
||||||
|
|
||||||
|
string actualSchemaName = peekDefinition.GetSchemaFromDatabaseQualifiedName(validDatabaseQualifiedName, objectName);
|
||||||
|
Assert.Equal(actualSchemaName, expectedSchemaName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Test PeekDefinition.GetSchemaFromDatabaseQualifiedName with a invalid database name
|
||||||
|
/// </summary>
|
||||||
|
[Fact]
|
||||||
|
public void GetSchemaFromDatabaseQualifiedNameWithInvalidNameTest()
|
||||||
|
{
|
||||||
|
PeekDefinition peekDefinition = new PeekDefinition(null);
|
||||||
|
string validDatabaseQualifiedName = "x.y.z";
|
||||||
|
string objectName = "test_table";
|
||||||
|
string expectedSchemaName = "dbo";
|
||||||
|
|
||||||
|
string actualSchemaName = peekDefinition.GetSchemaFromDatabaseQualifiedName(validDatabaseQualifiedName, objectName);
|
||||||
|
Assert.Equal(actualSchemaName, expectedSchemaName);
|
||||||
|
}
|
||||||
|
|
||||||
#if LIVE_CONNECTION_TESTS
|
#if LIVE_CONNECTION_TESTS
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Test get definition for a table object with active connection
|
/// Test get definition for a table object with active connection
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GetTableDefinitionTest()
|
public void GetValidTableDefinitionTest()
|
||||||
{
|
{
|
||||||
// Get live connectionInfo
|
// Get live connectionInfo
|
||||||
ConnectionInfo connInfo = TestObjects.InitLiveConnectionInfoForDefinition();
|
ConnectionInfo connInfo = TestObjects.InitLiveConnectionInfoForDefinition();
|
||||||
@@ -143,11 +199,52 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices
|
|||||||
string schemaName = null;
|
string schemaName = null;
|
||||||
string objectType = "TABLE";
|
string objectType = "TABLE";
|
||||||
|
|
||||||
|
// Get locations for valid table object
|
||||||
Location[] locations = peekDefinition.GetSqlObjectDefinition(peekDefinition.GetTableScripts, objectName, schemaName, objectType);
|
Location[] locations = peekDefinition.GetSqlObjectDefinition(peekDefinition.GetTableScripts, objectName, schemaName, objectType);
|
||||||
Assert.NotNull(locations);
|
Assert.NotNull(locations);
|
||||||
Cleanup(locations);
|
Cleanup(locations);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Test get definition for a invalid table object with active connection
|
||||||
|
/// </summary>
|
||||||
|
[Fact]
|
||||||
|
public void GetTableDefinitionInvalidObjectTest()
|
||||||
|
{
|
||||||
|
// Get live connectionInfo
|
||||||
|
ConnectionInfo connInfo = TestObjects.InitLiveConnectionInfoForDefinition();
|
||||||
|
PeekDefinition peekDefinition = new PeekDefinition(connInfo);
|
||||||
|
string objectName = "test_invalid";
|
||||||
|
string schemaName = null;
|
||||||
|
string objectType = "TABLE";
|
||||||
|
|
||||||
|
// Get locations for invalid table object
|
||||||
|
Location[] locations = peekDefinition.GetSqlObjectDefinition(peekDefinition.GetTableScripts, objectName, schemaName, objectType);
|
||||||
|
Assert.Null(locations);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Test get definition for a valid table object with schema and active connection
|
||||||
|
/// </summary>
|
||||||
|
[Fact]
|
||||||
|
public void GetTableDefinitionWithSchemaTest()
|
||||||
|
{
|
||||||
|
// Get live connectionInfo
|
||||||
|
ConnectionInfo connInfo = TestObjects.InitLiveConnectionInfoForDefinition();
|
||||||
|
PeekDefinition peekDefinition = new PeekDefinition(connInfo);
|
||||||
|
string objectName = "test_table";
|
||||||
|
string schemaName = "dbo";
|
||||||
|
string objectType = "TABLE";
|
||||||
|
|
||||||
|
// Get locations for valid table object with schema name
|
||||||
|
Location[] locations = peekDefinition.GetSqlObjectDefinition(peekDefinition.GetTableScripts, objectName, schemaName, objectType);
|
||||||
|
Assert.NotNull(locations);
|
||||||
|
Cleanup(locations);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Test GetDefinition with an unsupported type(function)
|
||||||
|
/// </summary>
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GetUnsupportedDefinitionForFullScript()
|
public void GetUnsupportedDefinitionForFullScript()
|
||||||
{
|
{
|
||||||
@@ -177,7 +274,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices
|
|||||||
/// Test get definition for a view object with active connection
|
/// Test get definition for a view object with active connection
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GetViewDefinitionTest()
|
public void GetValidViewDefinitionTest()
|
||||||
{
|
{
|
||||||
ConnectionInfo connInfo = TestObjects.InitLiveConnectionInfoForDefinition();
|
ConnectionInfo connInfo = TestObjects.InitLiveConnectionInfoForDefinition();
|
||||||
PeekDefinition peekDefinition = new PeekDefinition(connInfo);
|
PeekDefinition peekDefinition = new PeekDefinition(connInfo);
|
||||||
|
|||||||
Reference in New Issue
Block a user