Object Explorer Service (#311)

* moving OE service from an old branch
This commit is contained in:
Leila Lali
2017-04-11 15:50:20 -07:00
committed by GitHub
parent 90861b7d9e
commit d903ba56a9
58 changed files with 15013 additions and 1057 deletions

View File

@@ -52,7 +52,7 @@ namespace Microsoft.SqlTools.Hosting
protected IMultiServiceProvider ServiceProvider { get; private set; }
public void SetServiceProvider(IMultiServiceProvider provider)
public virtual void SetServiceProvider(IMultiServiceProvider provider)
{
ServiceProvider = provider;
}

View File

@@ -176,7 +176,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection
/// <summary>
/// Open a connection with the specified ConnectParams
/// </summary>
public async Task<ConnectionCompleteParams> Connect(ConnectParams connectionParams)
public virtual async Task<ConnectionCompleteParams> Connect(ConnectParams connectionParams)
{
// Validate parameters
ConnectionCompleteParams validationResults = ValidateConnectParams(connectionParams);

View File

@@ -11,6 +11,7 @@ using Microsoft.SqlTools.ServiceLayer.EditData;
using Microsoft.SqlTools.ServiceLayer.Hosting;
using Microsoft.SqlTools.ServiceLayer.LanguageServices;
using Microsoft.SqlTools.ServiceLayer.Metadata;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer;
using Microsoft.SqlTools.ServiceLayer.QueryExecution;
using Microsoft.SqlTools.ServiceLayer.Scripting;
using Microsoft.SqlTools.ServiceLayer.SqlContext;
@@ -85,6 +86,7 @@ namespace Microsoft.SqlTools.ServiceLayer
serviceProvider.RegisterSingleService(ScriptingService.Instance);
InitializeHostedServices(serviceProvider, serviceHost);
serviceHost.ServiceProvider = serviceProvider;
serviceHost.InitializeRequestHandlers();
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,426 +1,426 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ConnectionServiceConnectErrorNullParams" xml:space="preserve">
<value>Los parámetros de conexión no pueden ser nulos</value>
</data>
<data name="ConnectionServiceListDbErrorNullOwnerUri" xml:space="preserve">
<value>OwnerUri no puede ser nulo ni estar vacío</value>
</data>
<data name="ConnectionServiceListDbErrorNotConnected" xml:space="preserve">
<value>SpecifiedUri '{0}' no tiene una conexión existente</value>
</data>
<data name="ConnectionServiceConnStringInvalidAuthType" xml:space="preserve">
<value>El valor '{0}' no es válido para AuthenticationType. Los valores válidos son 'Integrated' y 'SqlLogin'.</value>
</data>
<data name="ConnectionServiceConnStringInvalidIntent" xml:space="preserve">
<value>El valor '{0}' no es válido para ApplicationIntent. Los valores válidos son 'ReadWrite' y 'ReadOnly'.</value>
</data>
<data name="ConnectionServiceConnectionCanceled" xml:space="preserve">
<value>Conexión cancelada</value>
</data>
<data name="ConnectionParamsValidateNullOwnerUri" xml:space="preserve">
<value>OwnerUri no puede ser nulo ni estar vacío</value>
</data>
<data name="ConnectionParamsValidateNullConnection" xml:space="preserve">
<value>El objeto de detalles de conexión no puede ser nulo</value>
</data>
<data name="ConnectionParamsValidateNullServerName" xml:space="preserve">
<value>ServerName no puede ser nulo ni estar vacío</value>
</data>
<data name="ConnectionParamsValidateNullSqlAuth" xml:space="preserve">
<value>{0} no puede ser nulo ni estar vacío cuando se utiliza autenticación SqlLogin</value>
</data>
<data name="QueryServiceCancelAlreadyCompleted" xml:space="preserve">
<value>Ya se ha completado la consulta, no se puede cancelar</value>
</data>
<data name="QueryServiceCancelDisposeFailed" xml:space="preserve">
<value>La consulta fue cancelada con éxito, pero no se ha podido desechar. No se encontró el URI del propietario.</value>
</data>
<data name="QueryServiceQueryCancelled" xml:space="preserve">
<value>Consulta cancelada por el usuario</value>
</data>
<data name="QueryServiceSubsetBatchNotCompleted" xml:space="preserve">
<value>El lote aún no ha finalizado,</value>
</data>
<data name="QueryServiceSubsetBatchOutOfRange" xml:space="preserve">
<value>Índice de lote no puede ser menor que 0 o mayor que el número de lotes</value>
</data>
<data name="QueryServiceSubsetResultSetOutOfRange" xml:space="preserve">
<value>Índice del conjunto de resultados no puede ser menor que 0 o mayor que el número de conjuntos de resultados</value>
</data>
<data name="QueryServiceDataReaderByteCountInvalid" xml:space="preserve">
<value>El número máximo de bytes a devolver debe ser mayor que cero</value>
</data>
<data name="QueryServiceDataReaderCharCountInvalid" xml:space="preserve">
<value>El número máximo de caracteres a devolver debe ser mayor que cero</value>
</data>
<data name="QueryServiceDataReaderXmlCountInvalid" xml:space="preserve">
<value>El número máximo de bytes XML a devolver debe ser mayor que cero</value>
</data>
<data name="QueryServiceFileWrapperWriteOnly" xml:space="preserve">
<value>El método de acceso no puede ser de sólo escritura</value>
</data>
<data name="QueryServiceFileWrapperNotInitialized" xml:space="preserve">
<value>FileStreamWrapper debe inicializarse antes de realizar operaciones</value>
</data>
<data name="QueryServiceFileWrapperReadOnly" xml:space="preserve">
<value>Este FileStreamWrapper no se puede utilizar para escritura.</value>
</data>
<data name="QueryServiceAffectedOneRow" xml:space="preserve">
<value>(1 fila afectada)</value>
</data>
<data name="QueryServiceAffectedRows" xml:space="preserve">
<value>({0} filas afectadas)</value>
</data>
<data name="QueryServiceCompletedSuccessfully" xml:space="preserve">
<value>Comandos finalizados correctamente.</value>
</data>
<data name="QueryServiceErrorFormat" xml:space="preserve">
<value>Msg {0}, nivel {1} estado {2}, línea {3} {4} {5}</value>
</data>
<data name="QueryServiceQueryFailed" xml:space="preserve">
<value>Error en la consulta: {0}</value>
</data>
<data name="QueryServiceColumnNull" xml:space="preserve">
<value>(Ningún nombre de columna)</value>
</data>
<data name="QueryServiceRequestsNoQuery" xml:space="preserve">
<value>La consulta solicitada no existe</value>
</data>
<data name="QueryServiceQueryInvalidOwnerUri" xml:space="preserve">
<value>Este editor no está conectado a una base de datos</value>
</data>
<data name="QueryServiceQueryInProgress" xml:space="preserve">
<value>Una consulta ya está en curso para esta sesión de editor. Por favor, cancelar esta consulta o esperar su finalización.</value>
</data>
<data name="QueryServiceMessageSenderNotSql" xml:space="preserve">
<value>Remitente de eventos de OnInfoMessage debe ser un objeto SqlConnection</value>
</data>
<data name="QueryServiceResultSetReaderNull" xml:space="preserve">
<value>Lector no puede ser nulo</value>
</data>
<data name="QueryServiceSaveAsResultSetNotComplete" xml:space="preserve">
<value>No se puede guardar el resultado hasta que haya finalizado la ejecución de la consulta</value>
</data>
<data name="QueryServiceSaveAsMiscStartingError" xml:space="preserve">
<value>Error interno al iniciar el guardado de la tarea</value>
</data>
<data name="QueryServiceSaveAsInProgress" xml:space="preserve">
<value>Una operacion de guardado en la misma ruta se encuentra en curso</value>
</data>
<data name="QueryServiceSaveAsFail" xml:space="preserve">
<value>Error al guardar {0}: {1}</value>
</data>
<data name="QueryServiceResultSetNotRead" xml:space="preserve">
<value>No se puede leer el subconjunto, a menos que los resultados se han leído desde el servidor</value>
</data>
<data name="QueryServiceResultSetStartRowOutOfRange" xml:space="preserve">
<value>Fila de inicio no puede ser menor que 0 o mayor que el número de filas en el conjunto de resultados</value>
</data>
<data name="QueryServiceResultSetRowCountOutOfRange" xml:space="preserve">
<value>La cantidad de filas debe ser un entero positivo</value>
</data>
<data name="QueryServiceResultSetNoColumnSchema" xml:space="preserve">
<value>No se pudo recuperar el esquema de columna para el conjunto de resultados</value>
</data>
<data name="QueryServiceExecutionPlanNotFound" xml:space="preserve">
<value>No se pudo recuperar un plan de ejecución del conjunto de resultados</value>
</data>
<data name="PeekDefinitionAzureError" xml:space="preserve">
<value>Esta característica actualmente no se admite en la base de datos de SQL Azure y almacén de datos: {0}</value>
</data>
<data name="PeekDefinitionError" xml:space="preserve">
<value>Se ha producido un error inesperado durante la ejecución de la definición de Peek: {0}</value>
</data>
<data name="PeekDefinitionNoResultsError" xml:space="preserve">
<value>No se encontraron resultados.</value>
</data>
<data name="PeekDefinitionDatabaseError" xml:space="preserve">
<value>No se pudo obtener ningún objeto asociado a la base de datos.</value>
</data>
<data name="PeekDefinitionNotConnectedError" xml:space="preserve">
<value>Conéctese a un servidor.</value>
</data>
<data name="PeekDefinitionTimedoutError" xml:space="preserve">
<value>Tiempo de espera agotado para esta operación.</value>
</data>
<data name="PeekDefinitionTypeNotSupportedError" xml:space="preserve">
<value>Esta característica no admite actualmente este tipo de objeto.</value>
</data>
<data name="WorkspaceServicePositionLineOutOfRange" xml:space="preserve">
<value>Posición está fuera del intervalo de la línea de archivo</value>
</data>
<data name="WorkspaceServicePositionColumnOutOfRange" xml:space="preserve">
<value>Posición está fuera del intervalo de la columna de la línea {0}</value>
</data>
<data name="WorkspaceServiceBufferPositionOutOfOrder" xml:space="preserve">
<value>Posición de inicio ({0}, {1}) debe preceder o ser igual a la posición final ({2}, {3})</value>
</data>
<data name="EE_BatchSqlMessageNoProcedureInfo" xml:space="preserve">
<value>Msg {0}, {1}, nivel de estado {2}, línea {3}</value>
</data>
<data name="EE_BatchSqlMessageWithProcedureInfo" xml:space="preserve">
<value>Msj {0}, {1}, nivel de estado {2}, procedimiento {3}, línea {4}</value>
</data>
<data name="EE_BatchSqlMessageNoLineInfo" xml:space="preserve">
<value>Msg {0}, nivel {1}, {2} de estado</value>
</data>
<data name="EE_BatchError_Exception" xml:space="preserve">
<value>Se produjo un error al procesar el lote. Mensaje de error: {0}</value>
</data>
<data name="EE_BatchExecutionInfo_RowsAffected" xml:space="preserve">
<value>({0} filas afectadas)</value>
</data>
<data name="EE_ExecutionNotYetCompleteError" xml:space="preserve">
<value>La ejecución anterior aún no está completa.</value>
</data>
<data name="EE_ScriptError_Error" xml:space="preserve">
<value>Se ha producido un error de secuencias de comandos.</value>
</data>
<data name="EE_ScriptError_ParsingSyntax" xml:space="preserve">
<value>Se encontró sintaxis incorrecta mientras se estaba analizando {0}.</value>
</data>
<data name="EE_ScriptError_FatalError" xml:space="preserve">
<value>Se ha producido un error grave.</value>
</data>
<data name="EE_ExecutionInfo_FinalizingLoop" xml:space="preserve">
<value>La ejecución completó {0} veces...</value>
</data>
<data name="EE_ExecutionInfo_QueryCancelledbyUser" xml:space="preserve">
<value>Se canceló la consulta.</value>
</data>
<data name="EE_BatchExecutionError_Halting" xml:space="preserve">
<value>Se produjo un error mientras se ejecutaba el lote.</value>
</data>
<data name="EE_BatchExecutionError_Ignoring" xml:space="preserve">
<value>Se produjo un error mientras se ejecutaba el lote, pero se ha omitido el error.</value>
</data>
<data name="EE_ExecutionInfo_InitilizingLoop" xml:space="preserve">
<value>Iniciando bucle de ejecución de {0} veces...</value>
</data>
<data name="EE_ExecutionError_CommandNotSupported" xml:space="preserve">
<value>No se admite el comando {0}.</value>
</data>
<data name="EE_ExecutionError_VariableNotFound" xml:space="preserve">
<value>La variable {0} no se encontró.</value>
</data>
<data name="BatchParserWrapperExecutionEngineError" xml:space="preserve">
<value>Error de ejecución de SQL: {0}</value>
</data>
<data name="BatchParserWrapperExecutionError" xml:space="preserve">
<value>Ejecución de contenedor del analizador por lotes: {0} se encuentra... en la línea {1}: {2} Descripción: {3}</value>
</data>
<data name="BatchParserWrapperExecutionEngineBatchMessage" xml:space="preserve">
<value>Lote analizador contenedor ejecución motor lote mensaje recibido: mensaje: {0} mensaje detallado: {1}</value>
</data>
<data name="BatchParserWrapperExecutionEngineBatchResultSetProcessing" xml:space="preserve">
<value>Motor de ejecución de analizador contenedor lote ResultSet procesamiento por lotes: DataReader.FieldCount: {0} DataReader.RecordsAffected: {1}</value>
</data>
<data name="BatchParserWrapperExecutionEngineBatchResultSetFinished" xml:space="preserve">
<value>Finalizó el elemento ResultSet analizador contenedor ejecución motor los lotes.</value>
</data>
<data name="BatchParserWrapperExecutionEngineBatchCancelling" xml:space="preserve">
<value>Cancelando la ejecución por lotes del contenedor del analizador por lotes.</value>
</data>
<data name="EE_ScriptError_Warning" xml:space="preserve">
<value>Advertencia de scripting.</value>
</data>
<data name="TroubleshootingAssistanceMessage" xml:space="preserve">
<value>Para obtener más información acerca de este error, vea los temas de solución de problemas en la documentación del producto.</value>
</data>
<data name="BatchParser_CircularReference" xml:space="preserve">
<value>El archivo '{0}' se incluyó recursivamente.</value>
</data>
<data name="BatchParser_CommentNotTerminated" xml:space="preserve">
<value>Falta la marca de final de comentario ' * /'.</value>
</data>
<data name="BatchParser_StringNotTerminated" xml:space="preserve">
<value>Sin comilla de cierre después de la cadena de caracteres.</value>
</data>
<data name="BatchParser_IncorrectSyntax" xml:space="preserve">
<value>Se encontró sintaxis incorrecta al analizar '{0}'.</value>
</data>
<data name="BatchParser_VariableNotDefined" xml:space="preserve">
<value>La variable {0} no está definida.</value>
</data>
<data name="TestLocalizationConstant" xml:space="preserve">
<value>prueba</value>
</data>
<data name="ErrorUnexpectedCodeObjectType" xml:space="preserve">
<value>No se puede convertir el SqlCodeObject del Tipo {0} al Tipo {1}</value>
</data>
<data name="ErrorEmptyStringReplacement" xml:space="preserve">
<value>Sustitución de una cadena vacía por una cadena vacía.</value>
</data>
<data name="EditDataSessionNotFound" xml:space="preserve">
<value>Sesión de edición no existe,</value>
</data>
<data name="EditDataQueryNotCompleted" xml:space="preserve">
<value>La consulta no ha finalizado.</value>
</data>
<data name="EditDataQueryImproperResultSets" xml:space="preserve">
<value>La consulta no generó un único set de resultados</value>
</data>
<data name="EditDataFailedAddRow" xml:space="preserve">
<value>Falló al agregar una nueva fila a la caché de actualización</value>
</data>
<data name="EditDataRowOutOfRange" xml:space="preserve">
<value>El ID de la fila ingresado, se encuentra fuera del rango de filas de la caché de edición</value>
</data>
<data name="EditDataUpdatePending" xml:space="preserve">
<value>Una actualización está pendiente para esta fila y debe de revertirse primero</value>
</data>
<data name="EditDataUpdateNotPending" xml:space="preserve">
<value>El ID de la fila ingresado no tiene actualizaciones pendientes</value>
</data>
<data name="EditDataObjectMetadataNotFound" xml:space="preserve">
<value>La metadata de la tabla o vista no pudo ser encontrada</value>
</data>
<data name="EditDataInvalidFormatBinary" xml:space="preserve">
<value>Formato inválido para columna binaria</value>
</data>
<data name="EditDataInvalidFormatBoolean" xml:space="preserve">
<value>Columnas del tipo boolean deben de ser numéricos 1 o 0, o tipo string true o false</value>
</data>
<data name="EditDataCreateScriptMissingValue" xml:space="preserve">
<value>Falta un valor requerido de la celda</value>
</data>
<data name="EditDataDeleteSetCell" xml:space="preserve">
<value>Existe una eliminación pendiente para esta fila, una actualización de celda no puede ser realizada.</value>
</data>
<data name="EditDataColumnIdOutOfRange" xml:space="preserve">
<value>El ID de la columna debe de estar en el rango de columnas de la consulta.</value>
</data>
<data name="EditDataColumnCannotBeEdited" xml:space="preserve">
<value>La columna no puede ser editada</value>
</data>
<data name="EditDataColumnNoKeyColumns" xml:space="preserve">
<value>No se encontró ninguna columna clave</value>
</data>
<data name="EditDataScriptFilePathNull" xml:space="preserve">
<value>Proporcione un nombre de archivo de salida</value>
</data>
<data name="EditDataUnsupportedObjectType" xml:space="preserve">
<value>Objeto de base de datos {0} no puede ser usado para modificación.</value>
</data>
<data name="ConnectionServiceDbErrorDefaultNotConnected" xml:space="preserve">
<value>SpecifiedUri '{0}' no tiene alguna conexión por defecto</value>
</data>
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ConnectionServiceConnectErrorNullParams" xml:space="preserve">
<value>Los parámetros de conexión no pueden ser nulos</value>
</data>
<data name="ConnectionServiceListDbErrorNullOwnerUri" xml:space="preserve">
<value>OwnerUri no puede ser nulo ni estar vacío</value>
</data>
<data name="ConnectionServiceListDbErrorNotConnected" xml:space="preserve">
<value>SpecifiedUri '{0}' no tiene una conexión existente</value>
</data>
<data name="ConnectionServiceConnStringInvalidAuthType" xml:space="preserve">
<value>El valor '{0}' no es válido para AuthenticationType. Los valores válidos son 'Integrated' y 'SqlLogin'.</value>
</data>
<data name="ConnectionServiceConnStringInvalidIntent" xml:space="preserve">
<value>El valor '{0}' no es válido para ApplicationIntent. Los valores válidos son 'ReadWrite' y 'ReadOnly'.</value>
</data>
<data name="ConnectionServiceConnectionCanceled" xml:space="preserve">
<value>Conexión cancelada</value>
</data>
<data name="ConnectionParamsValidateNullOwnerUri" xml:space="preserve">
<value>OwnerUri no puede ser nulo ni estar vacío</value>
</data>
<data name="ConnectionParamsValidateNullConnection" xml:space="preserve">
<value>El objeto de detalles de conexión no puede ser nulo</value>
</data>
<data name="ConnectionParamsValidateNullServerName" xml:space="preserve">
<value>ServerName no puede ser nulo ni estar vacío</value>
</data>
<data name="ConnectionParamsValidateNullSqlAuth" xml:space="preserve">
<value>{0} no puede ser nulo ni estar vacío cuando se utiliza autenticación SqlLogin</value>
</data>
<data name="QueryServiceCancelAlreadyCompleted" xml:space="preserve">
<value>Ya se ha completado la consulta, no se puede cancelar</value>
</data>
<data name="QueryServiceCancelDisposeFailed" xml:space="preserve">
<value>La consulta fue cancelada con éxito, pero no se ha podido desechar. No se encontró el URI del propietario.</value>
</data>
<data name="QueryServiceQueryCancelled" xml:space="preserve">
<value>Consulta cancelada por el usuario</value>
</data>
<data name="QueryServiceSubsetBatchNotCompleted" xml:space="preserve">
<value>El lote aún no ha finalizado,</value>
</data>
<data name="QueryServiceSubsetBatchOutOfRange" xml:space="preserve">
<value>Índice de lote no puede ser menor que 0 o mayor que el número de lotes</value>
</data>
<data name="QueryServiceSubsetResultSetOutOfRange" xml:space="preserve">
<value>Índice del conjunto de resultados no puede ser menor que 0 o mayor que el número de conjuntos de resultados</value>
</data>
<data name="QueryServiceDataReaderByteCountInvalid" xml:space="preserve">
<value>El número máximo de bytes a devolver debe ser mayor que cero</value>
</data>
<data name="QueryServiceDataReaderCharCountInvalid" xml:space="preserve">
<value>El número máximo de caracteres a devolver debe ser mayor que cero</value>
</data>
<data name="QueryServiceDataReaderXmlCountInvalid" xml:space="preserve">
<value>El número máximo de bytes XML a devolver debe ser mayor que cero</value>
</data>
<data name="QueryServiceFileWrapperWriteOnly" xml:space="preserve">
<value>El método de acceso no puede ser de sólo escritura</value>
</data>
<data name="QueryServiceFileWrapperNotInitialized" xml:space="preserve">
<value>FileStreamWrapper debe inicializarse antes de realizar operaciones</value>
</data>
<data name="QueryServiceFileWrapperReadOnly" xml:space="preserve">
<value>Este FileStreamWrapper no se puede utilizar para escritura.</value>
</data>
<data name="QueryServiceAffectedOneRow" xml:space="preserve">
<value>(1 fila afectada)</value>
</data>
<data name="QueryServiceAffectedRows" xml:space="preserve">
<value>({0} filas afectadas)</value>
</data>
<data name="QueryServiceCompletedSuccessfully" xml:space="preserve">
<value>Comandos finalizados correctamente.</value>
</data>
<data name="QueryServiceErrorFormat" xml:space="preserve">
<value>Msg {0}, nivel {1} estado {2}, línea {3} {4} {5}</value>
</data>
<data name="QueryServiceQueryFailed" xml:space="preserve">
<value>Error en la consulta: {0}</value>
</data>
<data name="QueryServiceColumnNull" xml:space="preserve">
<value>(Ningún nombre de columna)</value>
</data>
<data name="QueryServiceRequestsNoQuery" xml:space="preserve">
<value>La consulta solicitada no existe</value>
</data>
<data name="QueryServiceQueryInvalidOwnerUri" xml:space="preserve">
<value>Este editor no está conectado a una base de datos</value>
</data>
<data name="QueryServiceQueryInProgress" xml:space="preserve">
<value>Una consulta ya está en curso para esta sesión de editor. Por favor, cancelar esta consulta o esperar su finalización.</value>
</data>
<data name="QueryServiceMessageSenderNotSql" xml:space="preserve">
<value>Remitente de eventos de OnInfoMessage debe ser un objeto SqlConnection</value>
</data>
<data name="QueryServiceResultSetReaderNull" xml:space="preserve">
<value>Lector no puede ser nulo</value>
</data>
<data name="QueryServiceSaveAsResultSetNotComplete" xml:space="preserve">
<value>No se puede guardar el resultado hasta que haya finalizado la ejecución de la consulta</value>
</data>
<data name="QueryServiceSaveAsMiscStartingError" xml:space="preserve">
<value>Error interno al iniciar el guardado de la tarea</value>
</data>
<data name="QueryServiceSaveAsInProgress" xml:space="preserve">
<value>Una operacion de guardado en la misma ruta se encuentra en curso</value>
</data>
<data name="QueryServiceSaveAsFail" xml:space="preserve">
<value>Error al guardar {0}: {1}</value>
</data>
<data name="QueryServiceResultSetNotRead" xml:space="preserve">
<value>No se puede leer el subconjunto, a menos que los resultados se han leído desde el servidor</value>
</data>
<data name="QueryServiceResultSetStartRowOutOfRange" xml:space="preserve">
<value>Fila de inicio no puede ser menor que 0 o mayor que el número de filas en el conjunto de resultados</value>
</data>
<data name="QueryServiceResultSetRowCountOutOfRange" xml:space="preserve">
<value>La cantidad de filas debe ser un entero positivo</value>
</data>
<data name="QueryServiceResultSetNoColumnSchema" xml:space="preserve">
<value>No se pudo recuperar el esquema de columna para el conjunto de resultados</value>
</data>
<data name="QueryServiceExecutionPlanNotFound" xml:space="preserve">
<value>No se pudo recuperar un plan de ejecución del conjunto de resultados</value>
</data>
<data name="PeekDefinitionAzureError" xml:space="preserve">
<value>Esta característica actualmente no se admite en la base de datos de SQL Azure y almacén de datos: {0}</value>
</data>
<data name="PeekDefinitionError" xml:space="preserve">
<value>Se ha producido un error inesperado durante la ejecución de la definición de Peek: {0}</value>
</data>
<data name="PeekDefinitionNoResultsError" xml:space="preserve">
<value>No se encontraron resultados.</value>
</data>
<data name="PeekDefinitionDatabaseError" xml:space="preserve">
<value>No se pudo obtener ningún objeto asociado a la base de datos.</value>
</data>
<data name="PeekDefinitionNotConnectedError" xml:space="preserve">
<value>Conéctese a un servidor.</value>
</data>
<data name="PeekDefinitionTimedoutError" xml:space="preserve">
<value>Tiempo de espera agotado para esta operación.</value>
</data>
<data name="PeekDefinitionTypeNotSupportedError" xml:space="preserve">
<value>Esta característica no admite actualmente este tipo de objeto.</value>
</data>
<data name="WorkspaceServicePositionLineOutOfRange" xml:space="preserve">
<value>Posición está fuera del intervalo de la línea de archivo</value>
</data>
<data name="WorkspaceServicePositionColumnOutOfRange" xml:space="preserve">
<value>Posición está fuera del intervalo de la columna de la línea {0}</value>
</data>
<data name="WorkspaceServiceBufferPositionOutOfOrder" xml:space="preserve">
<value>Posición de inicio ({0}, {1}) debe preceder o ser igual a la posición final ({2}, {3})</value>
</data>
<data name="EE_BatchSqlMessageNoProcedureInfo" xml:space="preserve">
<value>Msg {0}, {1}, nivel de estado {2}, línea {3}</value>
</data>
<data name="EE_BatchSqlMessageWithProcedureInfo" xml:space="preserve">
<value>Msj {0}, {1}, nivel de estado {2}, procedimiento {3}, línea {4}</value>
</data>
<data name="EE_BatchSqlMessageNoLineInfo" xml:space="preserve">
<value>Msg {0}, nivel {1}, {2} de estado</value>
</data>
<data name="EE_BatchError_Exception" xml:space="preserve">
<value>Se produjo un error al procesar el lote. Mensaje de error: {0}</value>
</data>
<data name="EE_BatchExecutionInfo_RowsAffected" xml:space="preserve">
<value>({0} filas afectadas)</value>
</data>
<data name="EE_ExecutionNotYetCompleteError" xml:space="preserve">
<value>La ejecución anterior aún no está completa.</value>
</data>
<data name="EE_ScriptError_Error" xml:space="preserve">
<value>Se ha producido un error de secuencias de comandos.</value>
</data>
<data name="EE_ScriptError_ParsingSyntax" xml:space="preserve">
<value>Se encontró sintaxis incorrecta mientras se estaba analizando {0}.</value>
</data>
<data name="EE_ScriptError_FatalError" xml:space="preserve">
<value>Se ha producido un error grave.</value>
</data>
<data name="EE_ExecutionInfo_FinalizingLoop" xml:space="preserve">
<value>La ejecución completó {0} veces...</value>
</data>
<data name="EE_ExecutionInfo_QueryCancelledbyUser" xml:space="preserve">
<value>Se canceló la consulta.</value>
</data>
<data name="EE_BatchExecutionError_Halting" xml:space="preserve">
<value>Se produjo un error mientras se ejecutaba el lote.</value>
</data>
<data name="EE_BatchExecutionError_Ignoring" xml:space="preserve">
<value>Se produjo un error mientras se ejecutaba el lote, pero se ha omitido el error.</value>
</data>
<data name="EE_ExecutionInfo_InitilizingLoop" xml:space="preserve">
<value>Iniciando bucle de ejecución de {0} veces...</value>
</data>
<data name="EE_ExecutionError_CommandNotSupported" xml:space="preserve">
<value>No se admite el comando {0}.</value>
</data>
<data name="EE_ExecutionError_VariableNotFound" xml:space="preserve">
<value>La variable {0} no se encontró.</value>
</data>
<data name="BatchParserWrapperExecutionEngineError" xml:space="preserve">
<value>Error de ejecución de SQL: {0}</value>
</data>
<data name="BatchParserWrapperExecutionError" xml:space="preserve">
<value>Ejecución de contenedor del analizador por lotes: {0} se encuentra... en la línea {1}: {2} Descripción: {3}</value>
</data>
<data name="BatchParserWrapperExecutionEngineBatchMessage" xml:space="preserve">
<value>Lote analizador contenedor ejecución motor lote mensaje recibido: mensaje: {0} mensaje detallado: {1}</value>
</data>
<data name="BatchParserWrapperExecutionEngineBatchResultSetProcessing" xml:space="preserve">
<value>Motor de ejecución de analizador contenedor lote ResultSet procesamiento por lotes: DataReader.FieldCount: {0} DataReader.RecordsAffected: {1}</value>
</data>
<data name="BatchParserWrapperExecutionEngineBatchResultSetFinished" xml:space="preserve">
<value>Finalizó el elemento ResultSet analizador contenedor ejecución motor los lotes.</value>
</data>
<data name="BatchParserWrapperExecutionEngineBatchCancelling" xml:space="preserve">
<value>Cancelando la ejecución por lotes del contenedor del analizador por lotes.</value>
</data>
<data name="EE_ScriptError_Warning" xml:space="preserve">
<value>Advertencia de scripting.</value>
</data>
<data name="TroubleshootingAssistanceMessage" xml:space="preserve">
<value>Para obtener más información acerca de este error, vea los temas de solución de problemas en la documentación del producto.</value>
</data>
<data name="BatchParser_CircularReference" xml:space="preserve">
<value>El archivo '{0}' se incluyó recursivamente.</value>
</data>
<data name="BatchParser_CommentNotTerminated" xml:space="preserve">
<value>Falta la marca de final de comentario ' * /'.</value>
</data>
<data name="BatchParser_StringNotTerminated" xml:space="preserve">
<value>Sin comilla de cierre después de la cadena de caracteres.</value>
</data>
<data name="BatchParser_IncorrectSyntax" xml:space="preserve">
<value>Se encontró sintaxis incorrecta al analizar '{0}'.</value>
</data>
<data name="BatchParser_VariableNotDefined" xml:space="preserve">
<value>La variable {0} no está definida.</value>
</data>
<data name="TestLocalizationConstant" xml:space="preserve">
<value>prueba</value>
</data>
<data name="ErrorUnexpectedCodeObjectType" xml:space="preserve">
<value>No se puede convertir el SqlCodeObject del Tipo {0} al Tipo {1}</value>
</data>
<data name="ErrorEmptyStringReplacement" xml:space="preserve">
<value>Sustitución de una cadena vacía por una cadena vacía.</value>
</data>
<data name="EditDataSessionNotFound" xml:space="preserve">
<value>Sesión de edición no existe,</value>
</data>
<data name="EditDataQueryNotCompleted" xml:space="preserve">
<value>La consulta no ha finalizado.</value>
</data>
<data name="EditDataQueryImproperResultSets" xml:space="preserve">
<value>La consulta no generó un único set de resultados</value>
</data>
<data name="EditDataFailedAddRow" xml:space="preserve">
<value>Falló al agregar una nueva fila a la caché de actualización</value>
</data>
<data name="EditDataRowOutOfRange" xml:space="preserve">
<value>El ID de la fila ingresado, se encuentra fuera del rango de filas de la caché de edición</value>
</data>
<data name="EditDataUpdatePending" xml:space="preserve">
<value>Una actualización está pendiente para esta fila y debe de revertirse primero</value>
</data>
<data name="EditDataUpdateNotPending" xml:space="preserve">
<value>El ID de la fila ingresado no tiene actualizaciones pendientes</value>
</data>
<data name="EditDataObjectMetadataNotFound" xml:space="preserve">
<value>La metadata de la tabla o vista no pudo ser encontrada</value>
</data>
<data name="EditDataInvalidFormatBinary" xml:space="preserve">
<value>Formato inválido para columna binaria</value>
</data>
<data name="EditDataInvalidFormatBoolean" xml:space="preserve">
<value>Columnas del tipo boolean deben de ser numéricos 1 o 0, o tipo string true o false</value>
</data>
<data name="EditDataCreateScriptMissingValue" xml:space="preserve">
<value>Falta un valor requerido de la celda</value>
</data>
<data name="EditDataDeleteSetCell" xml:space="preserve">
<value>Existe una eliminación pendiente para esta fila, una actualización de celda no puede ser realizada.</value>
</data>
<data name="EditDataColumnIdOutOfRange" xml:space="preserve">
<value>El ID de la columna debe de estar en el rango de columnas de la consulta.</value>
</data>
<data name="EditDataColumnCannotBeEdited" xml:space="preserve">
<value>La columna no puede ser editada</value>
</data>
<data name="EditDataColumnNoKeyColumns" xml:space="preserve">
<value>No se encontró ninguna columna clave</value>
</data>
<data name="EditDataScriptFilePathNull" xml:space="preserve">
<value>Proporcione un nombre de archivo de salida</value>
</data>
<data name="EditDataUnsupportedObjectType" xml:space="preserve">
<value>Objeto de base de datos {0} no puede ser usado para modificación.</value>
</data>
<data name="ConnectionServiceDbErrorDefaultNotConnected" xml:space="preserve">
<value>SpecifiedUri '{0}' no tiene alguna conexión por defecto</value>
</data>
</root>

View File

@@ -599,4 +599,656 @@
<value>Decimal column is missing numeric precision or numeric scale</value>
<comment></comment>
</data>
<data name="TreeNodeError" xml:space="preserve">
<value>Error expanding: {0}</value>
<comment></comment>
</data>
<data name="ServerNodeConnectionError" xml:space="preserve">
<value>Error connecting to {0}</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Aggregates" xml:space="preserve">
<value>Aggregates</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ServerRoles" xml:space="preserve">
<value>Server Roles</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ApplicationRoles" xml:space="preserve">
<value>Application Roles</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Assemblies" xml:space="preserve">
<value>Assemblies</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_AssemblyFiles" xml:space="preserve">
<value>Assembly Files</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_AsymmetricKeys" xml:space="preserve">
<value>Asymmetric Keys</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_DatabaseAsymmetricKeys" xml:space="preserve">
<value>Asymmetric Keys</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_DataCompressionOptions" xml:space="preserve">
<value>Data Compression Options</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Certificates" xml:space="preserve">
<value>Certificates</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_FileTables" xml:space="preserve">
<value>FileTables</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_DatabaseCertificates" xml:space="preserve">
<value>Certificates</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_CheckConstraints" xml:space="preserve">
<value>Check Constraints</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Columns" xml:space="preserve">
<value>Columns</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Constraints" xml:space="preserve">
<value>Constraints</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Contracts" xml:space="preserve">
<value>Contracts</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Credentials" xml:space="preserve">
<value>Credentials</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ErrorMessages" xml:space="preserve">
<value>Error Messages</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ServerRoleMembership" xml:space="preserve">
<value>Server Role Membership</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_DatabaseOptions" xml:space="preserve">
<value>Database Options</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_DatabaseRoles" xml:space="preserve">
<value>Database Roles</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_RoleMemberships" xml:space="preserve">
<value>Role Memberships</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_DatabaseTriggers" xml:space="preserve">
<value>Database Triggers</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_DefaultConstraints" xml:space="preserve">
<value>Default Constraints</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Defaults" xml:space="preserve">
<value>Defaults</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Sequences" xml:space="preserve">
<value>Sequences</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Endpoints" xml:space="preserve">
<value>Endpoints</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_EventNotifications" xml:space="preserve">
<value>Event Notifications</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ServerEventNotifications" xml:space="preserve">
<value>Server Event Notifications</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ExtendedProperties" xml:space="preserve">
<value>Extended Properties</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_FileGroups" xml:space="preserve">
<value>Filegroups</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ForeignKeys" xml:space="preserve">
<value>Foreign Keys</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_FullTextCatalogs" xml:space="preserve">
<value>Full-Text Catalogs</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_FullTextIndexes" xml:space="preserve">
<value>Full-Text Indexes</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Functions" xml:space="preserve">
<value>Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Indexes" xml:space="preserve">
<value>Indexes</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_InlineFunctions" xml:space="preserve">
<value>Inline Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Keys" xml:space="preserve">
<value>Keys</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_LinkedServers" xml:space="preserve">
<value>Linked Servers</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_LinkedServerLogins" xml:space="preserve">
<value>Linked Server Logins</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Logins" xml:space="preserve">
<value>Logins</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_MasterKey" xml:space="preserve">
<value>Master Key</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_MasterKeys" xml:space="preserve">
<value>Master Keys</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_MessageTypes" xml:space="preserve">
<value>Message Types</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_MultiSelectFunctions" xml:space="preserve">
<value>Table-Valued Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Parameters" xml:space="preserve">
<value>Parameters</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_PartitionFunctions" xml:space="preserve">
<value>Partition Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_PartitionSchemes" xml:space="preserve">
<value>Partition Schemes</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Permissions" xml:space="preserve">
<value>Permissions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_PrimaryKeys" xml:space="preserve">
<value>Primary Keys</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Programmability" xml:space="preserve">
<value>Programmability</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Queues" xml:space="preserve">
<value>Queues</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_RemoteServiceBindings" xml:space="preserve">
<value>Remote Service Bindings</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ReturnedColumns" xml:space="preserve">
<value>Returned Columns</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Roles" xml:space="preserve">
<value>Roles</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Routes" xml:space="preserve">
<value>Routes</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Rules" xml:space="preserve">
<value>Rules</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Schemas" xml:space="preserve">
<value>Schemas</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Security" xml:space="preserve">
<value>Security</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ServerObjects" xml:space="preserve">
<value>Server Objects</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Management" xml:space="preserve">
<value>Management</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ServerTriggers" xml:space="preserve">
<value>Triggers</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ServiceBroker" xml:space="preserve">
<value>Service Broker</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Services" xml:space="preserve">
<value>Services</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Signatures" xml:space="preserve">
<value>Signatures</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_LogFiles" xml:space="preserve">
<value>Log Files</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Statistics" xml:space="preserve">
<value>Statistics</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Storage" xml:space="preserve">
<value>Storage</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_StoredProcedures" xml:space="preserve">
<value>Stored Procedures</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SymmetricKeys" xml:space="preserve">
<value>Symmetric Keys</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Synonyms" xml:space="preserve">
<value>Synonyms</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Tables" xml:space="preserve">
<value>Tables</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Triggers" xml:space="preserve">
<value>Triggers</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Types" xml:space="preserve">
<value>Types</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_UniqueKeys" xml:space="preserve">
<value>Unique Keys</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_UserDefinedDataTypes" xml:space="preserve">
<value>User-Defined Data Types</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_UserDefinedTypes" xml:space="preserve">
<value>User-Defined Types (CLR)</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Users" xml:space="preserve">
<value>Users</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Views" xml:space="preserve">
<value>Views</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_XmlIndexes" xml:space="preserve">
<value>XML Indexes</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_XMLSchemaCollections" xml:space="preserve">
<value>XML Schema Collections</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_UserDefinedTableTypes" xml:space="preserve">
<value>User-Defined Table Types</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_FilegroupFiles" xml:space="preserve">
<value>Files</value>
<comment></comment>
</data>
<data name="MissingCaption" xml:space="preserve">
<value>Missing Caption</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_BrokerPriorities" xml:space="preserve">
<value>Broker Priorities</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_CryptographicProviders" xml:space="preserve">
<value>Cryptographic Providers</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_DatabaseAuditSpecifications" xml:space="preserve">
<value>Database Audit Specifications</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_DatabaseEncryptionKeys" xml:space="preserve">
<value>Database Encryption Keys</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_EventSessions" xml:space="preserve">
<value>Event Sessions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_FullTextStopLists" xml:space="preserve">
<value>Full Text Stoplists</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ResourcePools" xml:space="preserve">
<value>Resource Pools</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ServerAudits" xml:space="preserve">
<value>Audits</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ServerAuditSpecifications" xml:space="preserve">
<value>Server Audit Specifications</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SpatialIndexes" xml:space="preserve">
<value>Spatial Indexes</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_WorkloadGroups" xml:space="preserve">
<value>Workload Groups</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SqlFiles" xml:space="preserve">
<value>SQL Files</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ServerFunctions" xml:space="preserve">
<value>Server Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SqlType" xml:space="preserve">
<value>SQL Type</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ServerOptions" xml:space="preserve">
<value>Server Options</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_DatabaseDiagrams" xml:space="preserve">
<value>Database Diagrams</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemTables" xml:space="preserve">
<value>System Tables</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Databases" xml:space="preserve">
<value>Databases</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemContracts" xml:space="preserve">
<value>System Contracts</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemDatabases" xml:space="preserve">
<value>System Databases</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemMessageTypes" xml:space="preserve">
<value>System Message Types</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemQueues" xml:space="preserve">
<value>System Queues</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemServices" xml:space="preserve">
<value>System Services</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemStoredProcedures" xml:space="preserve">
<value>System Stored Procedures</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemViews" xml:space="preserve">
<value>System Views</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_DataTierApplications" xml:space="preserve">
<value>Data-tier Applications</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ExtendedStoredProcedures" xml:space="preserve">
<value>Extended Stored Procedures</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemAggregateFunctions" xml:space="preserve">
<value>Aggregate Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemApproximateNumerics" xml:space="preserve">
<value>Approximate Numerics</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemBinaryStrings" xml:space="preserve">
<value>Binary Strings</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemCharacterStrings" xml:space="preserve">
<value>Character Strings</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemCLRDataTypes" xml:space="preserve">
<value>CLR Data Types</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemConfigurationFunctions" xml:space="preserve">
<value>Configuration Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemCursorFunctions" xml:space="preserve">
<value>Cursor Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemDataTypes" xml:space="preserve">
<value>System Data Types</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemDateAndTime" xml:space="preserve">
<value>Date and Time</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemDateAndTimeFunctions" xml:space="preserve">
<value>Date and Time Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemExactNumerics" xml:space="preserve">
<value>Exact Numerics</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemFunctions" xml:space="preserve">
<value>System Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemHierarchyIdFunctions" xml:space="preserve">
<value>Hierarchy Id Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemMathematicalFunctions" xml:space="preserve">
<value>Mathematical Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemMetadataFunctions" xml:space="preserve">
<value>Metadata Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemOtherDataTypes" xml:space="preserve">
<value>Other Data Types</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemOtherFunctions" xml:space="preserve">
<value>Other Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemRowsetFunctions" xml:space="preserve">
<value>Rowset Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemSecurityFunctions" xml:space="preserve">
<value>Security Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemSpatialDataTypes" xml:space="preserve">
<value>Spatial Data Types</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemStringFunctions" xml:space="preserve">
<value>String Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemSystemStatisticalFunctions" xml:space="preserve">
<value>System Statistical Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemTextAndImageFunctions" xml:space="preserve">
<value>Text and Image Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemUnicodeCharacterStrings" xml:space="preserve">
<value>Unicode Character Strings</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_AggregateFunctions" xml:space="preserve">
<value>Aggregate Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ScalarValuedFunctions" xml:space="preserve">
<value>Scalar-valued Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_TableValuedFunctions" xml:space="preserve">
<value>Table-valued Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemExtendedStoredProcedures" xml:space="preserve">
<value>System Extended Stored Procedures</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_BuiltInType" xml:space="preserve">
<value>Built-in Types</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_BuiltInServerRole" xml:space="preserve">
<value>Built-in Server Roles</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_UserWithPassword" xml:space="preserve">
<value>User with Password</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SearchPropertyList" xml:space="preserve">
<value>Search Property List</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SecurityPolicies" xml:space="preserve">
<value>Security Policies</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SecurityPredicates" xml:space="preserve">
<value>Security Predicates</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ServerRole" xml:space="preserve">
<value>Server Role</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SearchPropertyLists" xml:space="preserve">
<value>Search Property Lists</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ColumnStoreIndexes" xml:space="preserve">
<value>Column Store Indexes</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_TableTypeIndexes" xml:space="preserve">
<value>Table Type Indexes</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ServerInstance" xml:space="preserve">
<value>ServerInstance</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SelectiveXmlIndexes" xml:space="preserve">
<value>Selective XML Indexes</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_XmlNamespaces" xml:space="preserve">
<value>XML Namespaces</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_XmlTypedPromotedPaths" xml:space="preserve">
<value>XML Typed Promoted Paths</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SqlTypedPromotedPaths" xml:space="preserve">
<value>T-SQL Typed Promoted Paths</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_DatabaseScopedCredentials" xml:space="preserve">
<value>Database Scoped Credentials</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ExternalDataSources" xml:space="preserve">
<value>External Data Sources</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ExternalFileFormats" xml:space="preserve">
<value>External File Formats</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ExternalResources" xml:space="preserve">
<value>External Resources</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ExternalTables" xml:space="preserve">
<value>External Tables</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_AlwaysEncryptedKeys" xml:space="preserve">
<value>Always Encrypted Keys</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ColumnMasterKeys" xml:space="preserve">
<value>Column Master Keys</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ColumnEncryptionKeys" xml:space="preserve">
<value>Column Encryption Keys</value>
<comment></comment>
</data>
</root>

View File

@@ -293,3 +293,333 @@ TestLocalizationConstant = test
# Utilities
SqlScriptFormatterDecimalMissingPrecision = Decimal column is missing numeric precision or numeric scale
############################################################################
# Object Explorer Service
TreeNodeError = Error expanding: {0}
ServerNodeConnectionError = Error connecting to {0}
SchemaHierarchy_Aggregates = Aggregates
SchemaHierarchy_ServerRoles = Server Roles
SchemaHierarchy_ApplicationRoles = Application Roles
SchemaHierarchy_Assemblies = Assemblies
SchemaHierarchy_AssemblyFiles = Assembly Files
SchemaHierarchy_AsymmetricKeys = Asymmetric Keys
SchemaHierarchy_DatabaseAsymmetricKeys = Asymmetric Keys
SchemaHierarchy_DataCompressionOptions = Data Compression Options
SchemaHierarchy_Certificates = Certificates
SchemaHierarchy_FileTables = FileTables
SchemaHierarchy_DatabaseCertificates = Certificates
SchemaHierarchy_CheckConstraints = Check Constraints
SchemaHierarchy_Columns = Columns
SchemaHierarchy_Constraints = Constraints
SchemaHierarchy_Contracts = Contracts
SchemaHierarchy_Credentials = Credentials
SchemaHierarchy_ErrorMessages = Error Messages
SchemaHierarchy_ServerRoleMembership = Server Role Membership
SchemaHierarchy_DatabaseOptions = Database Options
SchemaHierarchy_DatabaseRoles = Database Roles
SchemaHierarchy_RoleMemberships = Role Memberships
SchemaHierarchy_DatabaseTriggers = Database Triggers
SchemaHierarchy_DefaultConstraints = Default Constraints
SchemaHierarchy_Defaults = Defaults
SchemaHierarchy_Sequences = Sequences
SchemaHierarchy_Endpoints = Endpoints
SchemaHierarchy_EventNotifications = Event Notifications
SchemaHierarchy_ServerEventNotifications = Server Event Notifications
SchemaHierarchy_ExtendedProperties = Extended Properties
SchemaHierarchy_FileGroups = Filegroups
SchemaHierarchy_ForeignKeys = Foreign Keys
SchemaHierarchy_FullTextCatalogs = Full-Text Catalogs
SchemaHierarchy_FullTextIndexes = Full-Text Indexes
SchemaHierarchy_Functions = Functions
SchemaHierarchy_Indexes = Indexes
SchemaHierarchy_InlineFunctions = Inline Functions
SchemaHierarchy_Keys = Keys
SchemaHierarchy_LinkedServers = Linked Servers
SchemaHierarchy_LinkedServerLogins = Linked Server Logins
SchemaHierarchy_Logins = Logins
SchemaHierarchy_MasterKey = Master Key
SchemaHierarchy_MasterKeys = Master Keys
SchemaHierarchy_MessageTypes = Message Types
SchemaHierarchy_MultiSelectFunctions = Table-Valued Functions
SchemaHierarchy_Parameters = Parameters
SchemaHierarchy_PartitionFunctions = Partition Functions
SchemaHierarchy_PartitionSchemes = Partition Schemes
SchemaHierarchy_Permissions = Permissions
SchemaHierarchy_PrimaryKeys = Primary Keys
SchemaHierarchy_Programmability = Programmability
SchemaHierarchy_Queues = Queues
SchemaHierarchy_RemoteServiceBindings = Remote Service Bindings
SchemaHierarchy_ReturnedColumns = Returned Columns
SchemaHierarchy_Roles = Roles
SchemaHierarchy_Routes = Routes
SchemaHierarchy_Rules = Rules
SchemaHierarchy_Schemas = Schemas
SchemaHierarchy_Security = Security
SchemaHierarchy_ServerObjects = Server Objects
SchemaHierarchy_Management = Management
SchemaHierarchy_ServerTriggers = Triggers
SchemaHierarchy_ServiceBroker = Service Broker
SchemaHierarchy_Services = Services
SchemaHierarchy_Signatures = Signatures
SchemaHierarchy_LogFiles = Log Files
SchemaHierarchy_Statistics = Statistics
SchemaHierarchy_Storage = Storage
SchemaHierarchy_StoredProcedures = Stored Procedures
SchemaHierarchy_SymmetricKeys = Symmetric Keys
SchemaHierarchy_Synonyms = Synonyms
SchemaHierarchy_Tables = Tables
SchemaHierarchy_Triggers = Triggers
SchemaHierarchy_Types = Types
SchemaHierarchy_UniqueKeys = Unique Keys
SchemaHierarchy_UserDefinedDataTypes = User-Defined Data Types
SchemaHierarchy_UserDefinedTypes = User-Defined Types (CLR)
SchemaHierarchy_Users = Users
SchemaHierarchy_Views = Views
SchemaHierarchy_XmlIndexes = XML Indexes
SchemaHierarchy_XMLSchemaCollections = XML Schema Collections
SchemaHierarchy_UserDefinedTableTypes = User-Defined Table Types
SchemaHierarchy_FilegroupFiles = Files
MissingCaption = Missing Caption
SchemaHierarchy_BrokerPriorities = Broker Priorities
SchemaHierarchy_CryptographicProviders = Cryptographic Providers
SchemaHierarchy_DatabaseAuditSpecifications = Database Audit Specifications
SchemaHierarchy_DatabaseEncryptionKeys = Database Encryption Keys
SchemaHierarchy_EventSessions = Event Sessions
SchemaHierarchy_FullTextStopLists = Full Text Stoplists
SchemaHierarchy_ResourcePools = Resource Pools
SchemaHierarchy_ServerAudits = Audits
SchemaHierarchy_ServerAuditSpecifications = Server Audit Specifications
SchemaHierarchy_SpatialIndexes = Spatial Indexes
SchemaHierarchy_WorkloadGroups = Workload Groups
SchemaHierarchy_SqlFiles = SQL Files
SchemaHierarchy_ServerFunctions = Server Functions
SchemaHierarchy_SqlType = SQL Type
SchemaHierarchy_ServerOptions = Server Options
SchemaHierarchy_DatabaseDiagrams = Database Diagrams
SchemaHierarchy_SystemTables = System Tables
SchemaHierarchy_Databases = Databases
SchemaHierarchy_SystemContracts = System Contracts
SchemaHierarchy_SystemDatabases = System Databases
SchemaHierarchy_SystemMessageTypes = System Message Types
SchemaHierarchy_SystemQueues = System Queues
SchemaHierarchy_SystemServices = System Services
SchemaHierarchy_SystemStoredProcedures = System Stored Procedures
SchemaHierarchy_SystemViews = System Views
SchemaHierarchy_DataTierApplications = Data-tier Applications
SchemaHierarchy_ExtendedStoredProcedures = Extended Stored Procedures
SchemaHierarchy_SystemAggregateFunctions = Aggregate Functions
SchemaHierarchy_SystemApproximateNumerics = Approximate Numerics
SchemaHierarchy_SystemBinaryStrings = Binary Strings
SchemaHierarchy_SystemCharacterStrings = Character Strings
SchemaHierarchy_SystemCLRDataTypes = CLR Data Types
SchemaHierarchy_SystemConfigurationFunctions = Configuration Functions
SchemaHierarchy_SystemCursorFunctions = Cursor Functions
SchemaHierarchy_SystemDataTypes = System Data Types
SchemaHierarchy_SystemDateAndTime = Date and Time
SchemaHierarchy_SystemDateAndTimeFunctions = Date and Time Functions
SchemaHierarchy_SystemExactNumerics = Exact Numerics
SchemaHierarchy_SystemFunctions = System Functions
SchemaHierarchy_SystemHierarchyIdFunctions = Hierarchy Id Functions
SchemaHierarchy_SystemMathematicalFunctions = Mathematical Functions
SchemaHierarchy_SystemMetadataFunctions = Metadata Functions
SchemaHierarchy_SystemOtherDataTypes = Other Data Types
SchemaHierarchy_SystemOtherFunctions = Other Functions
SchemaHierarchy_SystemRowsetFunctions = Rowset Functions
SchemaHierarchy_SystemSecurityFunctions = Security Functions
SchemaHierarchy_SystemSpatialDataTypes = Spatial Data Types
SchemaHierarchy_SystemStringFunctions = String Functions
SchemaHierarchy_SystemSystemStatisticalFunctions = System Statistical Functions
SchemaHierarchy_SystemTextAndImageFunctions = Text and Image Functions
SchemaHierarchy_SystemUnicodeCharacterStrings = Unicode Character Strings
SchemaHierarchy_AggregateFunctions = Aggregate Functions
SchemaHierarchy_ScalarValuedFunctions = Scalar-valued Functions
SchemaHierarchy_TableValuedFunctions = Table-valued Functions
SchemaHierarchy_SystemExtendedStoredProcedures = System Extended Stored Procedures
SchemaHierarchy_BuiltInType = Built-in Types
SchemaHierarchy_BuiltInServerRole = Built-in Server Roles
SchemaHierarchy_UserWithPassword = User with Password
SchemaHierarchy_SearchPropertyList = Search Property List
SchemaHierarchy_SecurityPolicies = Security Policies
SchemaHierarchy_SecurityPredicates = Security Predicates
SchemaHierarchy_ServerRole = Server Role
SchemaHierarchy_SearchPropertyLists = Search Property Lists
SchemaHierarchy_ColumnStoreIndexes = Column Store Indexes
SchemaHierarchy_TableTypeIndexes = Table Type Indexes
SchemaHierarchy_ServerInstance = ServerInstance
SchemaHierarchy_SelectiveXmlIndexes = Selective XML Indexes
SchemaHierarchy_XmlNamespaces = XML Namespaces
SchemaHierarchy_XmlTypedPromotedPaths = XML Typed Promoted Paths
SchemaHierarchy_SqlTypedPromotedPaths = T-SQL Typed Promoted Paths
SchemaHierarchy_DatabaseScopedCredentials = Database Scoped Credentials
SchemaHierarchy_ExternalDataSources = External Data Sources
SchemaHierarchy_ExternalFileFormats = External File Formats
SchemaHierarchy_ExternalResources = External Resources
SchemaHierarchy_ExternalTables = External Tables
SchemaHierarchy_AlwaysEncryptedKeys = Always Encrypted Keys
SchemaHierarchy_ColumnMasterKeys = Column Master Keys
SchemaHierarchy_ColumnEncryptionKeys = Column Encryption Keys

File diff suppressed because it is too large Load Diff

View File

@@ -1,19 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>{0D61DC2B-DA66-441D-B9D0-F76C98F780F9}</ProjectGuid>
<RootNamespace>Microsoft.SqlTools.ServiceLayer</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'==''">.\obj</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>{0D61DC2B-DA66-441D-B9D0-F76C98F780F9}</ProjectGuid>
<RootNamespace>Microsoft.SqlTools.ServiceLayer</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'==''">.\obj</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<ItemGroup>
<Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
</ItemGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

View File

@@ -0,0 +1,45 @@
//
// 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.Connection.Contracts;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts
{
/// <summary>
/// Information returned from a <see cref="CreateSessionRequest"/>.
/// Contains success information, a <see cref="SessionId"/> to be used when
/// requesting expansion of nodes, and a root node to display for this area.
/// </summary>
public class CreateSessionResponse
{
/// <summary>
/// Boolean indicating if the connection was successful
/// </summary>
public bool Success { get; set; }
/// <summary>
/// Unique ID to use when sending any requests for objects in the
/// tree under the node
/// </summary>
public string SessionId { get; set; }
/// <summary>
/// Information describing the base node in the tree
/// </summary>
public NodeInfo RootNode { get; set; }
}
/// <summary>
/// Establishes an Object Explorer tree session for a specific connection.
/// This will create a connection to a specific server or database, register
/// it for use in the
/// </summary>
public class CreateSessionRequest
{
public static readonly
RequestType<ConnectionDetails, CreateSessionResponse> Type =
RequestType<ConnectionDetails, CreateSessionResponse>.Create("objectexplorer/createsession");
}
}

View File

@@ -0,0 +1,56 @@
//
// 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.ObjectExplorer.Contracts
{
/// <summary>
/// Information returned from a <see cref="ExpandRequest"/>.
/// </summary>
public class ExpandResponse
{
/// <summary>
/// Unique ID to use when sending any requests for objects in the
/// tree under the node
/// </summary>
public string SessionId { get; set; }
/// <summary>
/// Information describing the expanded nodes in the tree
/// </summary>
public NodeInfo[] Nodes { get; set; }
}
/// <summary>
/// Parameters to the <see cref="ExpandRequest"/>.
/// </summary>
public class ExpandParams
{
/// <summary>
/// The Id returned from a <see cref="CreateSessionRequest"/>. This
/// is used to disambiguate between different trees.
/// </summary>
public string SessionId { get; set; }
/// <summary>
/// Path identifying the node to expand. See <see cref="NodeInfo.NodePath"/> for details
/// </summary>
public string NodePath { get; set; }
}
/// <summary>
/// A request to expand a
/// </summary>
public class ExpandRequest
{
/// <summary>
/// Returns children of a given node as a <see cref="NodeInfo"/> array.
/// </summary>
public static readonly
RequestType<ExpandParams, ExpandResponse> Type =
RequestType<ExpandParams, ExpandResponse>.Create("objectexplorer/expand");
}
}

View File

@@ -0,0 +1,40 @@
//
// 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.ObjectExplorer.Contracts
{
/// <summary>
/// Information describing a Node in the Object Explorer tree.
/// Contains information required to display the Node to the user and
/// to know whether actions such as expanding children is possible
/// the node
/// </summary>
public class NodeInfo
{
/// <summary>
/// Path identifying this node: for example a table will be at ["server", "database", "tables", "tableName"].
/// This enables rapid navigation of the tree without the need for a global registry of elements.
/// The path functions as a unique ID and is used to disambiguate the node when sending requests for expansion.
/// A common ID is needed since processes do not share address space and need a unique identifier
/// </summary>
public string NodePath { get; set; }
/// <summary>
/// The type of the node - for example Server, Database, Folder, Table
/// </summary>
public string NodeType { get; set; }
/// <summary>
/// Label to display to the user, describing this node.
/// </summary>
public string Label { get; set; }
/// <summary>
/// Is this a leaf node (in which case no children can be generated) or
/// is it expandable?
/// </summary>
public bool IsLeaf { get; set; }
}
}

View File

@@ -0,0 +1,39 @@
//
// 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.ObjectExplorer.Contracts
{
/// <summary>
/// Parameters to the <see cref="ExpandRequest"/>.
/// </summary>
public class RefreshParams
{
/// <summary>
/// The Id returned from a <see cref="CreateSessionRequest"/>. This
/// is used to disambiguate between different trees.
/// </summary>
public string SessionId { get; set; }
/// <summary>
/// Path identifying the node to expand. See <see cref="NodeInfo.NodePath"/> for details
/// </summary>
public string[] NodePath { get; set; }
}
/// <summary>
/// A request to expand a
/// </summary>
public class RefreshRequest
{
/// <summary>
/// Returns children of a given node as a <see cref="NodeInfo"/> array.
/// </summary>
public static readonly
RequestType<ExpandParams, NodeInfo[]> Type =
RequestType<ExpandParams, NodeInfo[]>.Create("objectexplorer/refresh");
}
}

View File

@@ -0,0 +1,39 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using System.Collections.Generic;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
{
/// <summary>
/// A <see cref="ChildFactory"/> supports creation of <see cref="TreeNode"/> children
/// for a class of objects in the tree. The
/// </summary>
public abstract class ChildFactory
{
/// <summary>
/// The set of applicable parents for which the factory can create children.
/// </summary>
/// <returns>
/// the string names for each <see cref="TreeNode.NodeType"/> that
/// this factory can create children for
/// </returns>
public abstract IEnumerable<string> ApplicableParents();
/// <summary>
/// Expands an element in the
/// </summary>
/// <param name="parent"></param>
/// <returns></returns>
public abstract IEnumerable<TreeNode> Expand(TreeNode parent);
public abstract bool CanCreateChild(TreeNode parent, object context);
public abstract TreeNode CreateChild(TreeNode parent, object context);
// TODO Consider whether Remove operations need to be supported
//public abstract bool CanRemoveChild(TreeNode parent, object context);
//public abstract int GetChildIndexToRemove(TreeNode parent, object context);
}
}

View File

@@ -0,0 +1,177 @@
//
// 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.Collections.ObjectModel;
using System.Linq;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
{
/// <summary>
/// A collection class for <see cref="TreeNode"/>
/// </summary>
public sealed class NodeObservableCollection : ObservableCollection<TreeNode>
{
public event EventHandler Initialized;
private int? numInits;
private static int cleanupBlocker;
public bool IsInitialized
{
get { return numInits.HasValue && numInits == 0; }
}
public bool IsPopulating
{
get { return numInits.HasValue && numInits != 0; }
}
public void BeginInit()
{
if (!numInits.HasValue)
{
numInits = 1;
}
else
{
numInits = numInits + 1;
}
}
public void EndInit()
{
IList<TreeNode> empty = null;
EndInit(null, ref empty);
}
public void EndInit(TreeNode parent, ref IList<TreeNode> deferredChildren)
{
if (numInits.HasValue &&
numInits.Value == 1)
{
try
{
DoSort();
if (deferredChildren != null)
{
// Set the parents so the children know how to sort themselves
foreach (var item in deferredChildren)
{
item.Parent = parent;
}
deferredChildren = deferredChildren.OrderBy(x => x).ToList();
// Add the deferredChildren
foreach (var item in deferredChildren)
{
this.Add(item);
}
}
}
finally
{
if (deferredChildren != null)
{
deferredChildren.Clear();
}
numInits = numInits - 1;
}
Initialized?.Invoke(this, EventArgs.Empty);
}
else
{
numInits = numInits - 1;
}
}
/// <summary>
/// Repositions this child in the list
/// </summary>
public void ReSortChild(TreeNode child)
{
if (child == null)
return;
List<TreeNode> sorted = this.OrderBy(x => x).ToList();
// Remove without cleanup
try
{
cleanupBlocker++;
Remove(child);
}
finally
{
cleanupBlocker--;
}
// Then insert
for (int i = 0; i < sorted.Count; i++)
{
if (sorted[i] == child)
{
Insert(i, child);
return;
}
}
}
protected override void RemoveItem(int index)
{
// Cleanup all the children
Cleanup(this[index]);
base.RemoveItem(index);
}
protected override void ClearItems()
{
// Cleanup all the children
foreach (var child in this)
{
Cleanup(child);
}
base.ClearItems();
}
private static void Cleanup(TreeNode parent)
{
if (cleanupBlocker > 0 ||
parent.Parent == null)
return;
// TODO implement cleanup policy / pattern
//ICleanupPattern parentAsCleanup = parent as ICleanupPattern;
//if (parentAsCleanup != null)
// parentAsCleanup.DoCleanup();
//foreach (var child in parent.Children)
//{
// Cleanup(child);
//}
parent.Parent = null;
}
private void DoSort()
{
List<TreeNode> sorted = this.OrderBy(x => x).ToList();
for (int i = 0; i < sorted.Count(); i++)
{
int index = IndexOf(sorted[i]);
if (index != i)
{
Move(IndexOf(sorted[i]), i);
}
}
}
}
}

View File

@@ -0,0 +1,141 @@
//
// 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.ObjectExplorer.Nodes
{
/// <summary>
/// Enum listing possible node types in the object explorer tree
/// </summary>
// TODO Consider replacing this with an auto-gen'd version
public enum NodeTypes
{
None,
SqlServersRoot,
DatabaseInstance,
DacInstance,
ServerInstance,
ScalarValuedFunctionInstance,
TableValuedFunctionInstance,
AggregateFunctionInstance,
FileGroupInstance,
StoredProcedureInstance,
UserDefinedTableTypeInstance,
ViewInstance,
TableInstance,
HistoryTableInstance,
Databases,
ExternalResources,
ServerLevelSecurity,
ServerLevelServerObjects,
ServerLevelManagement,
SystemDatabases,
ServerLevelLinkedServerLogins,
ServerLevelServerAudits,
ServerLevelCryptographicProviders,
ServerLevelCredentials,
ServerLevelServerRoles,
ServerLevelLogins,
ServerLevelEventSessions,
ServerLevelServerAuditSpecifications,
ServerLevelEventNotifications,
ServerLevelErrorMessages,
ServerLevelServerTriggers,
ServerLevelLinkedServers,
ServerLevelEndpoints,
DacInstancesFolder,
Tables,
Views,
Synonyms,
Programmability,
ServiceBroker,
Storage,
Security,
SystemTables,
FileTables,
SystemViews,
StoredProcedures,
Functions,
ExtendedStoredProcedures,
DatabaseTriggers,
Defaults,
Rules,
Types,
Assemblies,
MessageTypes,
Contracts,
Queues,
Services,
Routes,
DatabaseAndQueueEventNotifications,
RemoteServiceBindings,
BrokerPriorities,
FileGroups,
FullTextCatalogs,
FullTextStopLists,
SqlLogFiles,
PartitionFunctions,
PartitionSchemes,
SearchPropertyLists,
Users,
Roles,
Schemas,
AsymmetricKeys,
Certificates,
SymmetricKeys,
DatabaseEncryptionKeys,
MasterKeys,
Signatures,
DatabaseAuditSpecifications,
Columns,
Keys,
Constraints,
Triggers,
Indexes,
Statistics,
TableValuedFunctions,
ScalarValuedFunctions,
AggregateFunctions,
SystemDataTypes,
UserDefinedDataTypes,
UserDefinedTableTypes,
UserDefinedTypes,
XmlSchemaCollections,
SystemExactNumerics,
SystemApproximateNumerics,
SystemDateAndTimes,
SystemCharacterStrings,
SystemUnicodeCharacterStrings,
SystemBinaryStrings,
SystemOtherDataTypes,
SystemClrDataTypes,
SystemSpatialDataTypes,
UserDefinedTableTypeColumns,
UserDefinedTableTypeKeys,
UserDefinedTableTypeConstraints,
SystemStoredProcedures,
StoredProcedureParameters,
TableValuedFunctionParameters,
ScalarValuedFunctionParameters,
AggregateFunctionParameters,
DatabaseRoles,
ApplicationRoles,
FileGroupFiles,
SystemMessageTypes,
SystemContracts,
SystemServices,
SystemQueues,
Sequences,
SecurityPolicies,
DatabaseScopedCredentials,
ExternalTables,
ExternalResourceInstance,
ExternalDataSources,
ExternalFileFormats,
ExternalTableInstance,
AlwaysEncryptedKeys,
ColumnMasterKeys,
ColumnEncryptionKeys
}
}

View File

@@ -0,0 +1,329 @@
//
// 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.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel;
using Microsoft.SqlTools.Utility;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
{
/// <summary>
/// Base class for elements in the object explorer tree. Provides common methods for tree navigation
/// and other core functionality
/// </summary>
public class TreeNode : IComparable<TreeNode>
{
private NodeObservableCollection children = new NodeObservableCollection();
private TreeNode parent;
private string nodePath;
private string label;
private ObjectExplorerService objectExplorerService;
public const char PathPartSeperator = '/';
/// <summary>
/// Constructor with no required inputs
/// </summary>
public TreeNode()
{
}
/// <summary>
/// Constructor that accepts a label to identify the node
/// </summary>
/// <param name="value">Label identifying the node</param>
public TreeNode(string value)
{
// We intentionally do not valid this being null or empty since
// some nodes may need to set it
NodeValue = value;
}
/// <summary>
/// Value describing this node
/// </summary>
public string NodeValue { get; set; }
/// <summary>
/// The type of the node - for example Server, Database, Folder, Table
/// </summary>
public string NodeType { get; set; }
/// <summary>
/// Enum defining the type of the node - for example Server, Database, Folder, Table
/// </summary>
public NodeTypes NodeTypeId { get; set; }
/// <summary>
/// Label to display to the user, describing this node.
/// If not explicitly set this will fall back to the <see cref="NodeValue"/> but
/// for many nodes such as the server, the display label will be different
/// to the value.
/// </summary>
public string Label {
get
{
if(label == null)
{
return NodeValue;
}
return label;
}
set
{
label = value;
}
}
/// <summary>
/// Is this a leaf node (in which case no children can be generated) or
/// is it expandable?
/// </summary>
public bool IsAlwaysLeaf { get; set; }
/// <summary>
/// Message to show if this Node is in an error state. This indicates
/// that children could be retrieved
/// </summary>
public string ErrorStateMessage { get; set; }
/// <summary>
/// Parent of this node
/// </summary>
public TreeNode Parent
{
get
{
return parent;
}
set
{
parent = value;
// Reset the node path since it's no longer valid
nodePath = null;
}
}
/// <summary>
/// Path identifying this node: for example a table will be at ["server", "database", "tables", "tableName"].
/// This enables rapid navigation of the tree without the need for a global registry of elements.
/// The path functions as a unique ID and is used to disambiguate the node when sending requests for expansion.
/// A common ID is needed since processes do not share address space and need a unique identifier
/// </summary>
public string GetNodePath()
{
if (nodePath == null)
{
GenerateNodePath();
}
return nodePath;
}
private void GenerateNodePath()
{
string path = "";
ObjectExplorerUtils.VisitChildAndParents(this, node =>
{
if (string.IsNullOrEmpty(node.NodeValue))
{
// Hit a node with no NodeValue. This indicates we need to stop traversing
return false;
}
// Otherwise add this value to the beginning of the path and keep iterating up
path = string.Format(CultureInfo.InvariantCulture,
"{0}{1}{2}", node.NodeValue, string.IsNullOrEmpty(path) ? "" : PathPartSeperator.ToString(), path);
return true;
});
nodePath = path;
}
public TreeNode FindNodeByPath(string path)
{
TreeNode nodeForPath = ObjectExplorerUtils.FindNode(this, node =>
{
return node.GetNodePath() == path;
}, nodeToFilter =>
{
return path.StartsWith(nodeToFilter.GetNodePath());
});
return nodeForPath;
}
/// <summary>
/// Converts to a <see cref="NodeInfo"/> object for serialization with just the relevant properties
/// needed to identify the node
/// </summary>
/// <returns></returns>
public NodeInfo ToNodeInfo()
{
return new NodeInfo()
{
IsLeaf = this.IsAlwaysLeaf,
Label = this.Label,
NodePath = this.GetNodePath(),
NodeType = this.NodeType
};
}
/// <summary>
/// Expands this node and returns its children
/// </summary>
/// <returns>Children as an IList. This is the raw children collection, not a copy</returns>
public IList<TreeNode> Expand()
{
// TODO consider why solution explorer has separate Children and Items options
if (children.IsInitialized)
{
return children;
}
PopulateChildren();
return children;
}
/// <summary>
/// Gets a readonly view of the currently defined children for this node.
/// This does not expand the node at all
/// Since the tree needs to keep track of parent relationships, directly
/// adding to the list is not supported.
/// </summary>
/// <returns><see cref="IList{TreeNode}"/> containing all children for this node</returns>
public IList<TreeNode> GetChildren()
{
return new ReadOnlyCollection<TreeNode>(children);
}
/// <summary>
/// Adds a child to the list of children under this node
/// </summary>
/// <param name="newChild"><see cref="TreeNode"/></param>
public void AddChild(TreeNode newChild)
{
Validate.IsNotNull(nameof(newChild), newChild);
children.Add(newChild);
newChild.Parent = this;
}
/// <summary>
/// Optional context to help with lookup of children
/// </summary>
public virtual object GetContext()
{
return null;
}
/// <summary>
/// Helper method to convert context to expected format
/// </summary>
/// <typeparam name="T">Type to convert to</typeparam>
/// <returns>context as expected type of null if it doesn't match</returns>
public T GetContextAs<T>()
where T : class
{
return GetContext() as T;
}
public T ParentAs<T>()
where T : TreeNode
{
return Parent as T;
}
protected void PopulateChildren()
{
Debug.Assert(IsAlwaysLeaf == false);
SmoQueryContext context = this.GetContextAs<SmoQueryContext>();
if (children.IsPopulating || context == null)
return;
children.Clear();
BeginChildrenInit();
try
{
IEnumerable<ChildFactory> childFactories = context.GetObjectExplorerService().GetApplicableChildFactories(this);
if (childFactories != null)
{
foreach (var factory in childFactories)
{
IEnumerable<TreeNode> items = factory.Expand(this);
if (items != null)
{
foreach (TreeNode item in items)
{
children.Add(item);
item.Parent = this;
}
}
}
}
}
finally
{
EndChildrenInit();
}
}
public void BeginChildrenInit()
{
children.BeginInit();
}
public void EndChildrenInit()
{
children.EndInit();
// TODO consider use of deferred children and if it's necessary
// children.EndInit(this, ref deferredChildren);
}
/// <summary>
/// Sort Priority to help when ordering elements in the tree
/// </summary>
public int? SortPriority { get; set; }
protected virtual int CompareSamePriorities(TreeNode thisItem, TreeNode otherItem)
{
return string.Compare(thisItem.NodeValue, otherItem.NodeValue, StringComparison.OrdinalIgnoreCase);
}
public int CompareTo(TreeNode other)
{
if (!this.SortPriority.HasValue &&
!other.SortPriority.HasValue)
{
return CompareSamePriorities(this, other);
}
if (this.SortPriority.HasValue &&
!other.SortPriority.HasValue)
{
return -1; // this is above other
}
if (!this.SortPriority.HasValue)
{
return 1; // this is below other
}
// Both have sort priority
int priDiff = this.SortPriority.Value - other.SortPriority.Value;
if (priDiff < 0)
return -1; // this is below other
if (priDiff == 0)
return 0;
return 1;
}
}
}

View File

@@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
{
public class TreeNodeWithContext
{
}
}

View File

@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
{
/// <summary>
/// Indicates which type of server a given node type is valid for
/// </summary>
[Flags]
public enum ValidForFlag
{
Sql2005 = 0x01,
Sql2008 = 0x02,
Sql2012 = 0x04,
Sql2014 = 0x08,
Azure = 0x10,
NotDebugInstance = 0x20,
NotContainedUser = 0x40,
AzureV12 = 0x80,
Sql2016 = 0x100,
CanConnectToMaster = 0x200,
CanViewSecurity = 0x400,
SqlvNext = 0x800,
All = Sql2005 | Sql2008 | Sql2012 | Sql2014 | Sql2016 | SqlvNext | Azure | AzureV12
}
}

View File

@@ -0,0 +1,344 @@
//
// 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.Globalization;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.SqlTools.Extensibility;
using Microsoft.SqlTools.Hosting;
using Microsoft.SqlTools.Hosting.Protocol;
using Microsoft.SqlTools.ServiceLayer.Connection;
using Microsoft.SqlTools.ServiceLayer.Connection.Contracts;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel;
using Microsoft.SqlTools.Utility;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer
{
/// <summary>
/// A Service to support querying server and database information as an Object Explorer tree.
/// The APIs used for this are modeled closely on the VSCode TreeExplorerNodeProvider API.
/// </summary>
public class ObjectExplorerService : HostedService<ObjectExplorerService>, IComposableService
{
internal const string uriPrefix = "objectexplorer://";
// Instance of the connection service, used to get the connection info for a given owner URI
private ConnectionService connectionService;
private IProtocolEndpoint serviceHost;
private Dictionary<string, ObjectExplorerSession> sessionMap;
private readonly Lazy<Dictionary<string, HashSet<ChildFactory>>> applicableNodeChildFactories;
private IMultiServiceProvider serviceProvider;
/// <summary>
/// Singleton constructor
/// </summary>
public ObjectExplorerService()
{
sessionMap = new Dictionary<string, ObjectExplorerSession>();
applicableNodeChildFactories = new Lazy<Dictionary<string, HashSet<ChildFactory>>>(() => PopulateFactories());
}
/// <summary>
/// Internal for testing only
/// </summary>
internal ObjectExplorerService(ExtensionServiceProvider serviceProvider)
: this()
{
SetServiceProvider(serviceProvider);
}
private Dictionary<string, HashSet<ChildFactory>> ApplicableNodeChildFactories
{
get
{
return applicableNodeChildFactories.Value;
}
}
/// <summary>
/// As an <see cref="IComposableService"/>, this will be set whenever the service is initialized
/// via an <see cref="IMultiServiceProvider"/>
/// </summary>
/// <param name="provider"></param>
public override void SetServiceProvider(IMultiServiceProvider provider)
{
Validate.IsNotNull(nameof(provider), provider);
serviceProvider = provider;
connectionService = provider.GetService<ConnectionService>();
}
/// <summary>
/// Initializes the service with the service host and registers request handlers.
/// </summary>
/// <param name="serviceHost">The service host instance to register with</param>
public override void InitializeService(IProtocolEndpoint serviceHost)
{
this.serviceHost = serviceHost;
// Register handlers for requests
serviceHost.SetRequestHandler(CreateSessionRequest.Type, HandleCreateSessionRequest);
serviceHost.SetRequestHandler(ExpandRequest.Type, HandleExpandRequest);
}
internal async Task HandleCreateSessionRequest(ConnectionDetails connectionDetails, RequestContext<CreateSessionResponse> context)
{
Logger.Write(LogLevel.Verbose, "HandleCreateSessionRequest");
Func<Task<CreateSessionResponse>> doCreateSession = async () =>
{
Validate.IsNotNull(nameof(connectionDetails), connectionDetails);
Validate.IsNotNull(nameof(context), context);
string uri = GenerateUri(connectionDetails);
ObjectExplorerSession session;
if (!sessionMap.TryGetValue(uri, out session))
{
// Establish a connection to the specified server/database
session = await DoCreateSession(connectionDetails, uri);
}
CreateSessionResponse response;
if (session == null)
{
response = new CreateSessionResponse() { Success = false };
}
else
{
// Else we have a session available, response with existing session information
response = new CreateSessionResponse()
{
Success = true,
RootNode = session.Root.ToNodeInfo(),
SessionId = session.Uri
};
}
return response;
};
await HandleRequestAsync(doCreateSession, context, "HandleCreateSessionRequest");
}
internal async Task<NodeInfo[]> ExpandNode(ObjectExplorerSession session, string nodePath)
{
return await Task.Factory.StartNew(() =>
{
NodeInfo[] nodes = null;
TreeNode node = session.Root.FindNodeByPath(nodePath);
if(node != null)
{
nodes = node.Expand().Select(x => x.ToNodeInfo()).ToArray();
}
return nodes;
});
}
/// <summary>
/// Establishes a new session and stores its information
/// </summary>
/// <returns><see cref="ObjectExplorerSession"/> object if successful, null if unsuccessful</returns>
internal async Task<ObjectExplorerSession> DoCreateSession(ConnectionDetails connectionDetails, string uri)
{
ObjectExplorerSession session;
ConnectParams connectParams = new ConnectParams() { OwnerUri = uri, Connection = connectionDetails };
ConnectionCompleteParams connectionResult = await Connect(connectParams);
if (connectionResult == null)
{
return null;
}
session = ObjectExplorerSession.CreateSession(connectionResult, serviceProvider);
sessionMap[uri] = session;
return session;
}
private async Task<ConnectionCompleteParams> Connect(ConnectParams connectParams)
{
try
{
// open connection based on request details
ConnectionCompleteParams result = await connectionService.Connect(connectParams);
return result;
}
catch (Exception ex)
{
// Send a connection failed error message in this case.
ConnectionCompleteParams result = new ConnectionCompleteParams()
{
Messages = ex.ToString()
};
await serviceHost.SendEvent(ConnectionCompleteNotification.Type, result);
return null;
}
}
internal async Task HandleExpandRequest(ExpandParams expandParams, RequestContext<ExpandResponse> context)
{
Logger.Write(LogLevel.Verbose, "HandleExpandRequest");
Func<Task<ExpandResponse>> expandNode = async () =>
{
Validate.IsNotNull(nameof(expandParams), expandParams);
Validate.IsNotNull(nameof(context), context);
string uri = expandParams.SessionId;
ObjectExplorerSession session = null;
NodeInfo[] nodes = null;
if (sessionMap.ContainsKey(uri))
{
session = sessionMap[uri];
}
else
{
//TODO: error
}
if (session != null)
{
// Establish a connection to the specified server/database
nodes = await ExpandNode(session, expandParams.NodePath);
}
ExpandResponse response;
response = new ExpandResponse() { Nodes = nodes, SessionId = uri };
return response;
};
await HandleRequestAsync(expandNode, context, "HandleExpandRequest");
}
private async Task HandleRequestAsync<T>(Func<Task<T>> handler, RequestContext<T> requestContext, string requestType)
{
Logger.Write(LogLevel.Verbose, requestType);
try
{
T result = await handler();
await requestContext.SendResult(result);
}
catch (Exception ex)
{
await requestContext.SendError(ex.ToString());
}
}
/// <summary>
/// Generates a URI for object explorer using a similar pattern to Mongo DB (which has URI-based database definition)
/// as this should ensure uniqueness
/// </summary>
/// <param name="details"></param>
/// <returns>string representing a URI</returns>
/// <remarks>Internal for testing purposes only</remarks>
internal static string GenerateUri(ConnectionDetails details)
{
Validate.IsNotNull("details", details);
string uri = string.Format(CultureInfo.InvariantCulture, "{0}{1}", uriPrefix, Uri.EscapeUriString(details.ServerName));
uri = AppendIfExists(uri, "databaseName", details.DatabaseName);
uri = AppendIfExists(uri, "user", details.UserName);
return uri;
}
private static string AppendIfExists(string uri, string propertyName, string propertyValue)
{
if (!string.IsNullOrEmpty(propertyValue))
{
uri += string.Format(CultureInfo.InvariantCulture, ";{0}={1}", propertyName, Uri.EscapeUriString(propertyValue));
}
return uri;
}
public IEnumerable<ChildFactory> GetApplicableChildFactories(TreeNode item)
{
if (ApplicableNodeChildFactories != null)
{
HashSet<ChildFactory> applicableFactories;
if (ApplicableNodeChildFactories.TryGetValue(item.NodeTypeId.ToString(), out applicableFactories))
{
return applicableFactories;
}
}
return null;
}
internal Dictionary<string, HashSet<ChildFactory>> PopulateFactories()
{
VerifyServicesInitialized();
var childFactories = new Dictionary<string, HashSet<ChildFactory>>();
// Create our list of all NodeType to ChildFactory objects so we can expand appropriately
foreach (var factory in serviceProvider.GetServices<ChildFactory>())
{
var parents = factory.ApplicableParents();
if (parents != null)
{
foreach (var parent in parents)
{
AddToApplicableChildFactories(childFactories, factory, parent);
}
}
}
return childFactories;
}
private void VerifyServicesInitialized()
{
if (serviceProvider == null)
{
throw new InvalidOperationException(SqlTools.Hosting.Localization.sr.ServiceProviderNotSet);
}
if (connectionService == null)
{
throw new InvalidOperationException(SqlTools.Hosting.Localization.sr.ServiceProviderNotSet);
}
}
private static void AddToApplicableChildFactories(Dictionary<string, HashSet<ChildFactory>> childFactories, ChildFactory factory, string parent)
{
HashSet<ChildFactory> applicableFactories;
if (!childFactories.TryGetValue(parent, out applicableFactories))
{
applicableFactories = new HashSet<ChildFactory>();
childFactories[parent] = applicableFactories;
}
applicableFactories.Add(factory);
}
internal class ObjectExplorerSession
{
private ConnectionService connectionService;
private IMultiServiceProvider serviceProvider;
// TODO decide whether a cache is needed to handle lookups in elements with a large # children
//private const int Cachesize = 10000;
//private Cache<string, NodeMapping> cache;
public ObjectExplorerSession(string uri, TreeNode root, IMultiServiceProvider serviceProvider, ConnectionService connectionService)
{
Validate.IsNotNullOrEmptyString("uri", uri);
Validate.IsNotNull("root", root);
Uri = uri;
Root = root;
this.serviceProvider = serviceProvider;
this.connectionService = connectionService;
}
public string Uri { get; private set; }
public TreeNode Root { get; private set; }
public static ObjectExplorerSession CreateSession(ConnectionCompleteParams response, IMultiServiceProvider serviceProvider)
{
TreeNode serverNode = new ServerNode(response, serviceProvider);
return new ObjectExplorerSession(response.OwnerUri, serverNode, serviceProvider, serviceProvider.GetService<ConnectionService>());
}
}
}
}

View File

@@ -0,0 +1,76 @@
//
// 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 Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer
{
/// <summary>
/// Utility class for Object Explorer related operations
/// </summary>
public static class ObjectExplorerUtils
{
/// <summary>
/// Visitor that walks all nodes from the child to the root node, unless the
/// <paramref name="visitor"/> function indicates that this should stop traversing
/// </summary>
/// <param name="child">node to start traversing at</param>
/// <param name="visitor">Predicate function that accesses the tree and
/// determines whether to stop going further up the tree</param>
/// <returns>
/// boolean - true to continue navigating up the tree, false to end the loop
/// and return early
/// </returns>
public static bool VisitChildAndParents(TreeNode child, Predicate<TreeNode> visitor)
{
if (child == null)
{
// End case: all nodes have been visited
return true;
}
// Visit the child first, then go up the parents
if (!visitor(child))
{
return false;
}
return VisitChildAndParents(child.Parent, visitor);
}
/// <summary>
/// Finds a node by traversing the tree starting from the given node through all the children
/// </summary>
/// <param name="node">node to start traversing at</param>
/// <param name="condition">Predicate function that accesses the tree and
/// determines whether to stop going further up the tree</param>
/// <param name="filter">Predicate function to filter the children when traversing</param>
/// <returns>A Tree Node that matches the condition</returns>
public static TreeNode FindNode(TreeNode node, Predicate<TreeNode> condition, Predicate<TreeNode> filter)
{
if(node == null)
{
return null;
}
if (condition(node))
{
return node;
}
foreach (var child in node.GetChildren())
{
if (filter != null && filter(child))
{
TreeNode childNode = FindNode(child, condition, filter);
if (childNode != null)
{
return childNode;
}
}
}
return null;
}
}
}

View File

@@ -0,0 +1,30 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using Microsoft.SqlServer.Management.Smo;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{
internal partial class DatabaseInstanceTreeNode
{
/// <summary>
/// Initializes the context and ensures that
/// </summary>
protected override void EnsureContextInitialized()
{
if (context == null)
{
base.EnsureContextInitialized();
Database db = SmoObject as Database;
if (context != null && db != null)
{
context.Database = db;
}
}
}
}
}

View File

@@ -0,0 +1,33 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using Microsoft.SqlServer.Management.Smo;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{
/// <summary>
/// Represents a folder node in the tree
/// </summary>
public class FolderNode : SmoTreeNode
{
/// <summary>
/// For folders, this copies the context of its parent if available
/// </summary>
/// <returns></returns>
public override object GetContext()
{
return Parent?.GetContext();
}
/// <summary>
/// For folders, searches for its parent's SMO object rather than copying for itself
/// </summary>
/// <returns><see cref="NamedSmoObject"/> from this parent's parent, or null if not found</returns>
public override NamedSmoObject GetParentSmoObject()
{
return ParentAs<SmoTreeNode>()?.GetParentSmoObject();
}
}
}

View File

@@ -0,0 +1,192 @@
//
// 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.Data.Common;
using System.Data.SqlClient;
using System.Globalization;
using System.Linq;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.Extensibility;
using Microsoft.SqlTools.ServiceLayer.Connection;
using Microsoft.SqlTools.ServiceLayer.Connection.Contracts;
using Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
using Microsoft.SqlTools.ServiceLayer.Utility;
using Microsoft.SqlTools.Utility;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{
/// <summary>
/// Server node implementation
/// </summary>
public class ServerNode : TreeNode
{
private ConnectionSummary connectionSummary;
private ServerInfo serverInfo;
private string connectionUri;
private Lazy<SmoQueryContext> context;
private ConnectionService connectionService;
private SmoServerCreator serverCreator;
public ServerNode(ConnectionCompleteParams connInfo, IMultiServiceProvider serviceProvider)
: base()
{
Validate.IsNotNull(nameof(connInfo), connInfo);
Validate.IsNotNull("connInfo.ConnectionSummary", connInfo.ConnectionSummary);
Validate.IsNotNull(nameof(serviceProvider), serviceProvider);
this.connectionSummary = connInfo.ConnectionSummary;
this.serverInfo = connInfo.ServerInfo;
this.connectionUri = connInfo.OwnerUri;
this.connectionService = serviceProvider.GetService<ConnectionService>();
this.context = new Lazy<SmoQueryContext>(() => CreateContext(serviceProvider));
NodeValue = connectionSummary.ServerName;
IsAlwaysLeaf = false;
NodeType = NodeTypes.ServerInstance.ToString();
NodeTypeId = NodeTypes.ServerInstance;
Label = GetConnectionLabel();
}
internal SmoServerCreator ServerCreator
{
get
{
if (serverCreator == null)
{
ServerCreator = new SmoServerCreator();
}
return serverCreator;
}
set
{
this.serverCreator = value;
}
}
/// <summary>
/// Returns the label to display to the user.
/// </summary>
internal string GetConnectionLabel()
{
string userName = connectionSummary.UserName;
// TODO Domain and username is not yet supported on .Net Core.
// Consider passing as an input from the extension where this can be queried
//if (string.IsNullOrWhiteSpace(userName))
//{
// userName = Environment.UserDomainName + @"\" + Environment.UserName;
//}
// TODO Consider adding IsAuthenticatingDatabaseMaster check in the code and
// referencing result here
if (!string.IsNullOrWhiteSpace(connectionSummary.DatabaseName) &&
string.Compare(connectionSummary.DatabaseName, CommonConstants.MasterDatabaseName, StringComparison.OrdinalIgnoreCase) != 0 &&
(serverInfo.IsCloud /* || !ci.IsAuthenticatingDatabaseMaster */))
{
// We either have an azure with a database specified or a Denali database using a contained user
userName += ", " + connectionSummary.DatabaseName;
}
string label;
if (string.IsNullOrWhiteSpace(userName))
{
label = string.Format(
CultureInfo.InvariantCulture,
"{0} ({1} {2})",
connectionSummary.ServerName,
"SQL Server",
serverInfo.ServerVersion);
}
else
{
label = string.Format(
CultureInfo.InvariantCulture,
"{0} ({1} {2} - {3})",
connectionSummary.ServerName,
"SQL Server",
serverInfo.ServerVersion,
userName);
}
return label;
}
private SmoQueryContext CreateContext(IMultiServiceProvider serviceProvider)
{
string exceptionMessage;
ConnectionInfo connectionInfo;
SqlConnection connection = null;
// Get server object from connection
if (!connectionService.TryFindConnection(this.connectionUri, out connectionInfo) ||
connectionInfo.AllConnections == null || connectionInfo.AllConnections.Count == 0)
{
ErrorStateMessage = string.Format(CultureInfo.CurrentCulture,
SR.ServerNodeConnectionError, connectionSummary.ServerName);
return null;
}
//TODO: figure out how to use existing connections
DbConnection dbConnection = connectionInfo.AllConnections.First();
ReliableSqlConnection reliableSqlConnection = dbConnection as ReliableSqlConnection;
SqlConnection sqlConnection = dbConnection as SqlConnection;
if (reliableSqlConnection != null)
{
connection = reliableSqlConnection.GetUnderlyingConnection();
}
else if (sqlConnection != null)
{
connection = sqlConnection;
}
else
{
ErrorStateMessage = string.Format(CultureInfo.CurrentCulture,
SR.ServerNodeConnectionError, connectionSummary.ServerName);
return null;
}
try
{
Server server = ServerCreator.Create(connection);
return new SmoQueryContext(server, serviceProvider)
{
Parent = server
};
}
catch (ConnectionFailureException cfe)
{
exceptionMessage = cfe.Message;
}
catch (Exception ex)
{
exceptionMessage = ex.Message;
}
Logger.Write(LogLevel.Error, "Exception at ServerNode.CreateContext() : " + exceptionMessage);
this.ErrorStateMessage = string.Format(SR.TreeNodeError, exceptionMessage);
return null;
}
public override object GetContext()
{
return context.Value;
}
}
/// <summary>
/// Internal for testing purposes only
/// </summary>
internal class SmoServerCreator
{
public virtual Server Create(SqlConnection connection)
{
ServerConnection serverConn = new ServerConnection(connection);
return new Server(serverConn);
}
}
}

View File

@@ -0,0 +1,161 @@
//
// 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.Diagnostics;
using System.Linq;
using System.Reflection;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
using Microsoft.SqlTools.ServiceLayer.Utility;
using Microsoft.SqlTools.Utility;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{
public class SmoChildFactoryBase : ChildFactory
{
public override IEnumerable<string> ApplicableParents()
{
return null;
}
public override IEnumerable<TreeNode> Expand(TreeNode parent)
{
//parent.BeginChildrenInit();
try
{
List<TreeNode> allChildren = new List<TreeNode>();
OnExpandPopulateFolders(allChildren, parent);
RemoveFoldersFromInvalidSqlServerVersions(allChildren, parent);
OnExpandPopulateNonFolders(allChildren, parent);
OnBeginAsyncOperations(parent);
return allChildren;
}
finally
{
//parent.EndChildrenInit();
}
}
/// <summary>
/// Populates any folders for a given parent node
/// </summary>
/// <param name="allChildren">List to which nodes should be added</param>
/// <param name="parent">Parent the nodes are being added to</param>
protected virtual void OnExpandPopulateFolders(IList<TreeNode> allChildren, TreeNode parent)
{
}
/// <summary>
/// Populates any non-folder nodes such as specific items in the tree.
/// </summary>
/// <param name="allChildren">List to which nodes should be added</param>
/// <param name="parent">Parent the nodes are being added to</param>
protected virtual void OnExpandPopulateNonFolders(IList<TreeNode> allChildren, TreeNode parent)
{
if (ChildQuerierTypes == null)
{
// This node does not support non-folder children
return;
}
SmoQueryContext context = parent.GetContextAs<SmoQueryContext>();
Validate.IsNotNull(nameof(context), context);
IEnumerable<SmoQuerier> queriers = context.ServiceProvider.GetServices<SmoQuerier>(q => IsCompatibleQuerier(q));
foreach (var querier in queriers)
{
foreach(var smoObject in querier.Query(context))
{
if (smoObject == null)
{
Console.WriteLine("smoObject should not be null");
}
TreeNode childNode = CreateChild(parent, smoObject);
if (childNode != null)
{
allChildren.Add(childNode);
}
}
}
}
private bool IsCompatibleQuerier(SmoQuerier querier)
{
if (ChildQuerierTypes == null)
{
return false;
}
Type actualType = querier.GetType();
foreach (Type childType in ChildQuerierTypes)
{
// We will accept any querier that is compatible with the listed querier type
if (childType.IsAssignableFrom(actualType))
{
return true;
}
}
return false;
}
/// <summary>
/// Filters out invalid folders if they cannot be displayed for the current server version
/// </summary>
/// <param name="allChildren">List to which nodes should be added</param>
/// <param name="parent">Parent the nodes are being added to</param>
protected virtual void RemoveFoldersFromInvalidSqlServerVersions(IList<TreeNode> allChildren, TreeNode parent)
{
}
// TODO Assess whether async operations node is required
protected virtual void OnBeginAsyncOperations(TreeNode parent)
{
}
public override bool CanCreateChild(TreeNode parent, object context)
{
return false;
}
public override TreeNode CreateChild(TreeNode parent, object context)
{
throw new NotImplementedException();
}
protected virtual void InitializeChild(TreeNode child, object context)
{
NamedSmoObject smoObj = context as NamedSmoObject;
if (smoObj == null)
{
Debug.WriteLine("context is not a NamedSmoObject. type: " + context.GetType());
}
else
{
SmoTreeNode childAsMeItem = (SmoTreeNode)child;
childAsMeItem.CacheInfoFromModel(smoObj);
}
}
internal virtual Type[] ChildQuerierTypes {
get
{
return null;
}
}
/// <summary>
/// Returns true if any final validation of the object to be added passes, and false
/// if validation fails. This provides a chance to filter specific items out of a list
/// </summary>
/// <param name="parent"></param>
/// <param name="contextObject"></param>
/// <returns>boolean</returns>
public virtual bool PassesFinalFilters(TreeNode parent, object context)
{
return true;
}
}
}

View File

@@ -0,0 +1,57 @@
//
// 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;
using System.Collections.Generic;
using Microsoft.SqlServer.Management.Smo;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{
/// <summary>
/// Wrapper to convert non-generic Smo enumerables to generic enumerable types for easier use in
/// </summary>
/// <typeparam name="T"></typeparam>
public class SmoCollectionWrapper<T> : IEnumerable<T>
where T : SqlSmoObject
{
private SmoCollectionBase collection;
/// <summary>
/// Constructor which accepts a <see cref="SmoCollectionBase"/> containing the objects
/// to wrap
/// </summary>
/// <param name="collection"><see cref="SmoCollectionBase"/> or null if none were set</param>
public SmoCollectionWrapper(SmoCollectionBase collection)
{
this.collection = collection;
}
/// <summary>
/// <see cref="IEnumerable{T}.GetEnumerator"/>
/// </summary>
/// <returns></returns>
public IEnumerator<T> GetEnumerator()
{
if (collection == null)
{
yield break;
}
foreach(Object obj in collection)
{
yield return (T)obj;
}
}
/// <summary>
/// <see cref="IEnumerable.GetEnumerator"/>
/// </summary>
/// <returns></returns>
IEnumerator IEnumerable.GetEnumerator()
{
return collection?.GetEnumerator();
}
}
}

View File

@@ -0,0 +1,42 @@
//
// 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 Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.Extensibility;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{
/// <summary>
/// A <see cref="SmoQuerier"/> handles SMO queries for one or more SMO object types.
/// The <see cref="SupportedObjectTypes"/> property defines which types can be queried.
///
/// To query multiple
/// </summary>
public abstract class SmoQuerier : IComposableService
{
public abstract Type[] SupportedObjectTypes { get; }
/// <summary>
/// Queries SMO for a collection of objects using the <see cref="SmoQueryContext"/>
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public abstract IEnumerable<SqlSmoObject> Query(SmoQueryContext context);
internal IMultiServiceProvider ServiceProvider
{
get;
private set;
}
public void SetServiceProvider(IMultiServiceProvider provider)
{
ServiceProvider = provider;
}
}
}

View File

@@ -0,0 +1,102 @@
//
// 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;
using System.Collections.Generic;
using System.Globalization;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.Extensibility;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{
/// <summary>
/// Context object containing key properties needed to query for SMO objects
/// </summary>
public class SmoQueryContext
{
/// <summary>
/// Creates a context object with a server to use as the basis for any queries
/// </summary>
/// <param name="server"></param>
public SmoQueryContext(Server server, IMultiServiceProvider serviceProvider)
{
Server = server;
ServiceProvider = serviceProvider;
}
/// <summary>
/// The server SMO will query against
/// </summary>
public Server Server { get; private set; }
/// <summary>
/// Optional Database context object to query against
/// </summary>
public Database Database { get; set; }
/// <summary>
/// Parent of a give node to use for queries
/// </summary>
public SmoObjectBase Parent { get; set; }
/// <summary>
/// A query loader that can be used to find <see cref="SmoQuerier"/> objects
/// for specific SMO types
/// </summary>
public IMultiServiceProvider ServiceProvider { get; private set; }
/// <summary>
/// Helper method to cast a parent to a specific type
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public T ParentAs<T>()
where T : TreeNode
{
return Parent as T;
}
/// <summary>
/// Gets the <see cref="ObjectExplorerService"/> if available, by looking it up
/// from the <see cref="ServiceProvider"/>
/// </summary>
/// <returns></returns>
/// <exception cref="InvalidOperationException">
/// Thrown if the <see cref="ServiceProvider"/> is not set or the <see cref="ObjectExplorerService"/>
/// isn't available from that provider
/// </exception>
public ObjectExplorerService GetObjectExplorerService()
{
if (ServiceProvider == null)
{
throw new InvalidOperationException(SqlTools.Hosting.Localization.sr.ServiceProviderNotSet);
}
ObjectExplorerService service = ServiceProvider.GetService<ObjectExplorerService>();
if (service == null)
{
throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture,
SqlTools.Hosting.Localization.sr.ServiceNotFound, nameof(ObjectExplorerService)));
}
return service;
}
/// <summary>
/// Copies the context for use by another node
/// </summary>
/// <param name="parent">New Parent to set</param>
/// <returns>new <see cref="SmoQueryContext"/> with all fields except <see cref="Parent"/> the same</returns>
public SmoQueryContext CopyWithParent(SmoObjectBase parent)
{
SmoQueryContext context = new SmoQueryContext(this.Server, this.ServiceProvider)
{
Database = this.Database,
Parent = parent
};
return context;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,215 @@
<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ output extension=".cs" #>
<#@ assembly name="System.Xml.dll" #>
<#@ import namespace="System" #>
<#@ import namespace="System.Globalization" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Xml" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.IO" #>
// This file was generated by a T4 Template. Do not modify directly, instead update the SmoQueryModelDefinition.xml file
// and re-run the T4 template. This can be done in Visual Studio by right-click in and choosing "Run Custom Tool",
// or from the command-line on any platform by running "build.cmd -Target=CodeGen" or "build.sh -Target=CodeGen".
using System;
using System.Collections.Generic;
using System.Composition;
using System.Linq;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Smo.Broker;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{
<#
var directory = Path.GetDirectoryName(Host.TemplateFile);
string xmlFile = Path.Combine(directory, "SmoQueryModelDefinition.xml");
/////////
// Now generate all the Query methods
/////////
var allNodes = GetNodes(xmlFile);
var indent = " ";
foreach (var nodeName in allNodes)
{
XmlElement nodeElement = GetNodeElement(xmlFile, nodeName);
IList<string> parents = GetParents(nodeElement, xmlFile, nodeName);
string nodeType = GetNodeType(nodeElement, nodeName);
string queryBaseClass = "SmoQuerier";
PushIndent(indent);
WriteLine("");
WriteLine(string.Format("[Export(typeof({0}))]", queryBaseClass));
WriteLine(string.Format("internal partial class {0}Querier: {1}", nodeName, queryBaseClass));
WriteLine("{");
PushIndent(indent);
// Supported Types
WriteLine("Type[] supportedTypes = new Type[] { typeof("+ nodeType + ") };");
WriteLine("");
WriteLine("public override Type[] SupportedObjectTypes { get { return supportedTypes; } }");
WriteLine("");
// Query impl
WriteLine("public override IEnumerable<SqlSmoObject> Query(SmoQueryContext context)");
WriteLine("{");
PushIndent(indent);
// TODO Allow override of the navigation path
foreach(var parentType in parents)
{
string parentVar = string.Format("parent{0}", parentType);
WriteLine(string.Format("{0} {1} = context.Parent as {0};", parentType, parentVar));
WriteLine(string.Format("if ({0} != null)", parentVar));
WriteLine("{");
PushIndent(indent);
string navigationPath = GetNavigationPath(nodeElement, xmlFile, nodeName, parentType);
WriteLine(string.Format("var retValue = {0}.{1};", parentVar, navigationPath));
WriteLine("if(retValue != null)");
WriteLine("{");
PushIndent(indent);
if (IsCollection(nodeElement))
{
WriteLine(string.Format("return new SmoCollectionWrapper<{0}>(retValue);", nodeType));
}
else
{
WriteLine("return new SqlSmoObject[] { retValue };");
}
PopIndent();
WriteLine("}");
PopIndent();
WriteLine("}"); // close If
}
WriteLine("return Enumerable.Empty<SqlSmoObject>();");
PopIndent();
WriteLine("}"); // close Query method
PopIndent();
WriteLine("}"); // close Class
PopIndent();
}
#>
}
<#+
public static string[] GetNodes(string xmlFile)
{
List<string> typesList = new List<string>();
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
XmlNodeList treeTypes = doc.SelectNodes("/SmoQueryModel/Node");
if (treeTypes != null)
{
foreach (var type in treeTypes)
{
XmlElement element = type as XmlElement;
if (element != null)
{
typesList.Add(element.GetAttribute("Name"));
}
}
}
return typesList.ToArray();
}
public static XmlElement GetNodeElement(string xmlFile, string nodeName)
{
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
return (XmlElement)doc.SelectSingleNode(string.Format("/SmoQueryModel/Node[@Name='{0}']", nodeName));
}
public static string GetNavPathField(string xmlFile, string nodeName, string parent)
{
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
XmlElement navPathElement = (XmlElement)doc.SelectSingleNode(string.Format("/SmoQueryModel/Node[@Name='{0}']/NavigationPath[@Parent='{1}']", nodeName, parent));
return navPathElement?.GetAttribute("Field");
}
public static string GetNavigationPath(XmlElement nodeElement, string xmlFile, string nodeName, string parentName)
{
string navPathField = GetNavPathField(xmlFile, nodeName, parentName);
if (!string.IsNullOrEmpty(navPathField))
{
return navPathField;
}
// else use pluralized type as this is the most common scenario
string nodeType = GetNodeType(nodeElement, nodeName);
string nodeTypeAccessor = IsCollection(nodeElement) ? string.Format("{0}s", nodeType) : nodeType;
return nodeTypeAccessor;
}
public static string GetNodeType(XmlElement nodeElement, string nodeName)
{
var type = nodeElement.GetAttribute("Type");
if (!string.IsNullOrEmpty(type))
{
return type;
}
// Otherwise assume the type is the node name without "Sql" at the start
var prefix = "Sql";
return nodeName.IndexOf(prefix) == 0 ? nodeName.Substring(prefix.Length) : nodeName;
}
public static bool IsCollection(XmlElement nodeElement)
{
var collection = nodeElement.GetAttribute("Collection");
bool result;
if (bool.TryParse(collection, out result))
{
return result;
}
// Default is true
return true;
}
public static IList<string> GetParents(XmlElement nodeElement, string xmlFile, string parentName)
{
var parentAttr = nodeElement.GetAttribute("Parent");
if (!string.IsNullOrEmpty(parentAttr))
{
return new string[] { parentAttr };
}
var parentNodes = GetChildren(xmlFile, parentName, "Parent");
if (parentNodes != null && parentNodes.Count > 0)
{
List<string> parents = new List<string>();
int i = 0;
foreach(var node in parentNodes)
{
parents.Add(node.InnerText);
}
return parents;
}
// default to assuming a type is under Database
return new string[] { "Database" };
}
public static List<XmlElement> GetChildren(string xmlFile, string parentName, string childNode)
{
XmlElement nodeElement = GetNodeElement(xmlFile, parentName);
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
List<XmlElement> retElements = new List<XmlElement>();
XmlNodeList nodeList = doc.SelectNodes(string.Format("/SmoQueryModel/Node[@Name='{0}']/{1}", parentName, childNode));
foreach (var item in nodeList)
{
XmlElement itemAsElement = item as XmlElement;
if (itemAsElement != null)
{
retElements.Add(itemAsElement);
}
}
return retElements;
}
#>

View File

@@ -0,0 +1,146 @@
<?xml version="1.0" encoding="utf-8" ?>
<!--
This XML file defines how to query for a given SMO type based on a parent/child or
XPath relationship. From this file, the paths to query each type should be buildable
into code using a T4 template.
Key properties:
Name: This maps
Type: Optional SMO type. If not specified, the Name without the Sql prefix is used
Parent: Expected parent type. Needed to codegen the response. if there are multiple parents
then each one
NavigationPath: For types whose access path differs based on parent or needs custom navigation
this can be used.
-->
<SmoQueryModel>
<!--<Node Name="SqlServer"/> -->
<Node Name="SqlDatabase" Type="Database" Parent="Server" />
<Node Name="SqlLinkedServerLogin" Type="LinkedServer" Parent="Server"/>
<Node Name="SqlLogin" Type="Login" Parent="Server" />
<Node Name="SqlServerRole" Type="" Parent="Server" >
<NavigationPath Parent="Server" Field="Roles" />
</Node>
<Node Name="SqlCredential" Parent="Server" />
<Node Name="SqlCryptographicProvider" Parent="Server" />
<Node Name="SqlServerAudit" Type="Audit" Parent="Server" />
<Node Name="SqlServerAuditSpecification" Type="ServerAuditSpecification" Parent="Server"/>
<Node Name="SqlEndpoint" Parent="Server"/>
<Node Name="SqlLinkedServer" Parent="Server" />
<Node Name="SqlServerDdlTrigger" Parent="Server" >
<NavigationPath Parent="Server" Field="Triggers" />
</Node>
<Node Name="SqlErrorMessage" Type="UserDefinedMessage" Parent="Server" />
<Node Name="SqlTable" Parent="Database" />
<Node Name="SqlView" Parent="Database" />
<Node Name="SqlSynonym" Parent="Database" />
<Node Name="SqlColumn" Parent="TableViewTableTypeBase"/>
<Node Name="SqlIndex" Parent="TableViewTableTypeBase">
<NavigationPath Parent="TableViewTableTypeBase" Field="Indexes" />
</Node>
<Node Name="SqlCheck" Parent="Table"/>
<Node Name="SqlForeignKeyConstraint" Type="ForeignKey" Parent="Table" />
<Node Name="SqlDefaultConstraint" Parent="Column" Collection="False" />
<Node Name="SqlDmlTrigger" Type="Trigger" Parent="Table" />
<Node Name="SqlFullTextIndex" Parent="Table" Collection="False" />
<Node Name="SqlStatistic" Parent="TableViewBase"/>
<Node Name="SqlDatabaseDdlTrigger" Type="Trigger" Parent="Database"/>
<Node Name="SqlAssembly" Type="SqlAssembly" Parent="Database" >
<NavigationPath Parent="Database" Field="Assemblies" />
</Node>
<Node Name="SqlRule" Parent="Database" />
<Node Name="SqlDefault" Parent="Database" />
<Node Name="SqlSequence" Parent="Database" />
<Node Name="SqlSystemDataType" Parent="Server" />
<Node Name="SqlUserDefinedDataType" Parent="Database" />
<Node Name="SqlUserDefinedTableType" Parent="Database" />
<Node Name="SqlXmlSchemaCollection" />
<Node Name="SqlUserDefinedType" />
<Node Name="SqlUserDefinedFunction" />
<Node Name="SqlUserDefinedAggregate" />
<Node Name="SqlFileGroup" />
<Node Name="SqlFile" Type="DataFile" Parent="FileGroup" >
<NavigationPath Parent="FileGroup" Field="Files" />
</Node>
<Node Name="SqlFullTextCatalog"/>
<Node Name="SqlFullTextStopList" />
<Node Name="SqlPartitionFunction"/>
<Node Name="SqlPartitionScheme"/>
<Node Name="SqlSearchPropertyList" />
<Node Name="SqlUser"/>
<Node Name="SqlSchema"/>
<Node Name="SqlAsymmetricKey" />
<Node Name="SqlCertificate" />
<Node Name="SqlSymmetricKey" />
<Node Name="SqlDatabaseEncryptionKey" Collection="False" />
<Node Name="SqlMasterKey" Collection="False" />
<Node Name="SqlDatabaseAuditSpecification" />
<Node Name="SqlSecurityPolicy" >
<NavigationPath Parent="Database" Field="SecurityPolicies" />
</Node>
<Node Name="SqlDatabaseCredential" Type="DatabaseScopedCredential"/>
<Node Name="SqlRole" Type="DatabaseRole" >
<NavigationPath Parent="Database" Field="Roles" />
</Node>
<Node Name="SqlApplicationRole" />
<Node Name="SqlColumnMasterKey" />
<Node Name="SqlColumnEncryptionKey" />
<Node Name="SqlServiceBroker" Type="ServiceBroker" Collection="False" />
<Node Name="SqlService" Type="BrokerService" Parent="ServiceBroker" >
<NavigationPath Parent="ServiceBroker" Field="Services" />
</Node>
<Node Name="SqlContract" Type="ServiceContract" Parent="ServiceBroker" />
<Node Name="SqlQueue" Type="ServiceQueue" Parent="ServiceBroker" >
<NavigationPath Parent="ServiceBroker" Field="Queues" />
</Node>
<Node Name="SqlRemoteServiceBinding" Parent="ServiceBroker" />
<Node Name="SqlBrokerPriority" Parent="ServiceBroker" >
<NavigationPath Parent="ServiceBroker" Field="Priorities" />
</Node>
<Node Name="SqlMessageType" Parent="ServiceBroker"/>
<Node Name="SqlExternalDataSource" />
<Node Name="SqlExternalFileFormat" />
<Node Name="SqlProcedure" Type="StoredProcedure"/>
<Node Name="SqlExtendedStoredProcedure" />
<Node Name="SqlSubroutineParameter" Type="Parameter" >
<Parent>StoredProcedure</Parent>
<Parent>UserDefinedAggregate</Parent>
<Parent>UserDefinedFunction</Parent>
</Node>
<Node Name="SqlPartitionFunctionParameter" Parent="PartitionFunction" />
<Node Name="SqlBuiltInType" Type="SystemDataType" Parent="Server"/>
<!-- TODO Enable all types
<Node Name="SqlRoute"/>
-->
<!-- Signatures appear to be missing entirely from SMO and SSMS object explorer...
<Node Name="SqlSignature" />
-->
<!-- TODO find mapping - exists in SSDT but not SSMS / SMO?
<Node Name="SqlEventNotification" Parent="ServiceBroker" />
-->
<!-- TODO Requires XEvents SMO DLL in .Net Core
<Node Name="SqlEventSession" Type="Session" />
<Node Name="SqlServerEventNotification" Type="Event" Parent="Server" />
-->
</SmoQueryModel>

View File

@@ -0,0 +1,90 @@
//
// 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 Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{
/// <summary>
/// A Node in the tree representing a SMO-based object
/// </summary>
public class SmoTreeNode : TreeNode
{
public static int FolderSortPriority = 0;
private static int _nextSortPriority = FolderSortPriority + 1; // 0 is reserved for folders
protected SmoQueryContext context;
public SmoTreeNode() : base()
{
}
protected virtual void OnInitialize()
{
// TODO setup initialization
}
/// <summary>
/// Is this a system (MSShipped) object?
/// </summary>
public bool IsMsShippedOwned { get; set; }
/// <summary>
/// Indicates which platforms a node is valid for
/// </summary>
public ValidForFlag ValidFor { get; set; }
/// <summary>
/// Gets an incrementing sort priority value to assist in automatically sorting
/// elements in a tree
/// </summary>
public static int NextSortPriority
{
get
{
return System.Threading.Interlocked.Increment(ref _nextSortPriority);
}
}
public NamedSmoObject SmoObject { get; private set; }
public virtual void CacheInfoFromModel(NamedSmoObject smoObject)
{
SmoObject = smoObject;
NodeValue = smoObject.Name;
}
public virtual NamedSmoObject GetParentSmoObject()
{
if (SmoObject != null)
{
return SmoObject;
}
// Return the parent's object, or null if it's not set / not a SmoTreeNode
return ParentAs<SmoTreeNode>()?.GetParentSmoObject();
}
public override object GetContext()
{
EnsureContextInitialized();
return context;
}
protected virtual void EnsureContextInitialized()
{
if (context == null)
{
SmoObjectBase smoParent = GetParentSmoObject();
SmoQueryContext parentContext = Parent?.GetContextAs<SmoQueryContext>();
if (smoParent != null && parentContext != null)
{
context = parentContext.CopyWithParent(smoParent);
}
}
}
}
}

View File

@@ -0,0 +1,208 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using System.Collections.Generic;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{
internal partial class SystemExactNumericsChildFactory
{
private static readonly HashSet<string> _exactNumerics = new HashSet<string>{
"bit",
"tinyint",
"smallint",
"int",
"bigint",
"numeric",
"decimal",
"smallmoney",
"money"
};
public override bool PassesFinalFilters(TreeNode parent, object contextObject)
{
NamedSmoObject smoObject = contextObject as NamedSmoObject;
if (smoObject != null)
{
string name = smoObject.Name;
if (!string.IsNullOrWhiteSpace(name))
{
return _exactNumerics.Contains(name);
}
}
return false;
}
}
internal partial class SystemApproximateNumericsChildFactory
{
private static readonly HashSet<string> _approxNumerics = new HashSet<string>{
"float",
"real"
};
public override bool PassesFinalFilters(TreeNode parent, object contextObject)
{
NamedSmoObject smoObject = contextObject as NamedSmoObject;
if (smoObject != null)
{
string name = smoObject.Name;
if (!string.IsNullOrWhiteSpace(name))
{
return _approxNumerics.Contains(name);
}
}
return false;
}
}
internal partial class SystemDateAndTimesChildFactory
{
private static readonly HashSet<string> _dateAndTime = new HashSet<string>{
"datetime",
"smalldatetime",
"date",
"time",
"datetimeoffset",
"datetime2",
};
public override bool PassesFinalFilters(TreeNode parent, object contextObject)
{
NamedSmoObject smoObject = contextObject as NamedSmoObject;
if (smoObject != null)
{
string name = smoObject.Name;
if (!string.IsNullOrWhiteSpace(name))
{
return _dateAndTime.Contains(name);
}
}
return false;
}
}
internal partial class SystemCharacterStringsChildFactory
{
private static readonly HashSet<string> _characterStrings = new HashSet<string>{
"char",
"varchar",
"text",
};
public override bool PassesFinalFilters(TreeNode parent, object contextObject)
{
NamedSmoObject smoObject = contextObject as NamedSmoObject;
if (smoObject != null)
{
string name = smoObject.Name;
if (!string.IsNullOrWhiteSpace(name))
{
return _characterStrings.Contains(name);
}
}
return false;
}
}
internal partial class SystemUnicodeCharacterStringsChildFactory
{
private static readonly HashSet<string> _unicodeCharacterStrings = new HashSet<string>
{
"nchar",
"nvarchar",
"ntext",
};
public override bool PassesFinalFilters(TreeNode parent, object contextObject)
{
NamedSmoObject smoObject = contextObject as NamedSmoObject;
if (smoObject != null)
{
string name = smoObject.Name;
if (!string.IsNullOrWhiteSpace(name))
{
return _unicodeCharacterStrings.Contains(name);
}
}
return false;
}
}
internal partial class SystemBinaryStringsChildFactory
{
private static readonly HashSet<string> _binaryStrings = new HashSet<string>{
"binary",
"varbinary",
"image",
};
public override bool PassesFinalFilters(TreeNode parent, object contextObject)
{
NamedSmoObject smoObject = contextObject as NamedSmoObject;
if (smoObject != null)
{
string name = smoObject.Name;
if (!string.IsNullOrWhiteSpace(name))
{
return _binaryStrings.Contains(name);
}
}
return false;
}
}
internal partial class SystemOtherDataTypesChildFactory
{
private static readonly HashSet<string> _otherDataTypes = new HashSet<string>{
"sql_variant",
"timestamp",
"uniqueidentifier",
"xml",
};
public override bool PassesFinalFilters(TreeNode parent, object contextObject)
{
NamedSmoObject smoObject = contextObject as NamedSmoObject;
if (smoObject != null)
{
string name = smoObject.Name;
if (!string.IsNullOrWhiteSpace(name))
{
return _otherDataTypes.Contains(name);
}
}
return false;
}
}
internal partial class SystemClrDataTypesChildFactory
{
private static readonly HashSet<string> _clrDataTypes = new HashSet<string>{
"hierarchyid",
};
public override bool PassesFinalFilters(TreeNode parent, object contextObject)
{
NamedSmoObject smoObject = contextObject as NamedSmoObject;
if (smoObject != null)
{
string name = smoObject.Name;
if (!string.IsNullOrWhiteSpace(name))
{
return _clrDataTypes.Contains(name);
}
}
return false;
}
}
internal partial class SystemSpatialDataTypesChildFactory
{
private static readonly HashSet<string> _spatialDataTypes = new HashSet<string>{
"geometry",
"geography",
};
public override bool PassesFinalFilters(TreeNode parent, object contextObject)
{
NamedSmoObject smoObject = contextObject as NamedSmoObject;
if (smoObject != null)
{
string name = smoObject.Name;
if (!string.IsNullOrWhiteSpace(name))
{
return _spatialDataTypes.Contains(name);
}
}
return false;
}
}
}

View File

@@ -0,0 +1,396 @@
<?xml version="1.0" encoding="utf-8" ?>
<ServerExplorerTree>
<Node Name="ServerInstance" LocLabel="SR.SchemaHierarchy_ServerInstance" Image="Server">
<Child Name="Databases"/>
<Child Name="ServerLevelSecurity"/>
<Child Name="ServerLevelServerObjects"/>
</Node>
<Node Name="Databases" LocLabel="SR.SchemaHierarchy_Databases" IsAsyncLoad="" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlDatabase" TreeNode="DatabaseInstanceTreeNode">
<Child Name="SystemDatabases"/>
</Node>
<Node Name="ServerLevelSecurity" LocLabel="SR.SchemaHierarchy_Security" BaseClass="ModelBased" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext|AzureV11|AzureV12|NotContainedUser|CanViewSecurity">
<Child Name="ServerLevelLinkedServerLogins"/>
<Child Name="ServerLevelLogins"/>
<Child Name="ServerLevelServerRoles"/>
<Child Name="ServerLevelCredentials"/>
<Child Name="ServerLevelCryptographicProviders"/>
<Child Name="ServerLevelServerAudits"/>
<Child Name="ServerLevelServerAuditSpecifications"/>
<!-- TODO Support XEvents in .Net Core SMO
<Child Name="ServerLevelEventSessions"/>
-->
</Node>
<Node Name="ServerLevelServerObjects" LocLabel="SR.SchemaHierarchy_ServerObjects" BaseClass="ModelBased" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext|NotContainedUser">
<Child Name="ServerLevelEndpoints"/>
<Child Name="ServerLevelLinkedServers"/>
<Child Name="ServerLevelServerTriggers"/>
<Child Name="ServerLevelErrorMessages"/>
<!-- TODO Support XEvents in .Net Core SMO
<Child Name="ServerLevelEventNotifications"/>
-->
</Node>
<Node Name="SystemDatabases" LocLabel="SR.SchemaHierarchy_SystemDatabases" BaseClass="Databases" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext|AzureV11|AzureV12|NotContainedUser|CanConnectToMaster"/>
<!-- TODO Support XEvents in .Net Core SMO
<Node Name="ServerLevelEventSessions" LocLabel="SR.SchemaHierarchy_EventSessions" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlEventSession" ValidFor="Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext"/>
<Node Name="ServerLevelEventNotifications" LocLabel="SR.SchemaHierarchy_ServerEventNotifications" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlServerEventNotification"/>
-->
<Node Name="ServerLevelLinkedServerLogins" LocLabel="SR.SchemaHierarchy_LinkedServerLogins" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlLinkedServerLogin" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext"/>
<Node Name="ServerLevelLogins" LocLabel="SR.SchemaHierarchy_Logins" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlLogin"/>
<Node Name="ServerLevelServerRoles" LocLabel="SR.SchemaHierarchy_ServerRoles" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlServerRole" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext"/>
<Node Name="ServerLevelCredentials" LocLabel="SR.SchemaHierarchy_Credentials" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlCredential" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext"/>
<Node Name="ServerLevelCryptographicProviders" LocLabel="SR.SchemaHierarchy_CryptographicProviders" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlCryptographicProvider" ValidFor="Sql2008|Sql2012|Sql2014|NotDebugInstance|Sql2016|SqlvNext"/>
<Node Name="ServerLevelServerAudits" LocLabel="SR.SchemaHierarchy_ServerAudits" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlServerAudit" ValidFor="Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext"/>
<Node Name="ServerLevelServerAuditSpecifications" LocLabel="SR.SchemaHierarchy_ServerAuditSpecifications" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlServerAuditSpecification" ValidFor="Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext"/>
<Node Name="ServerLevelEndpoints" LocLabel="SR.SchemaHierarchy_Endpoints" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlEndpoint" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext"/>
<Node Name="ServerLevelLinkedServers" LocLabel="SR.SchemaHierarchy_LinkedServers" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlLinkedServer"/>
<Node Name="ServerLevelServerTriggers" LocLabel="SR.SchemaHierarchy_ServerTriggers" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlServerDdlTrigger"/>
<Node Name="ServerLevelErrorMessages" LocLabel="SR.SchemaHierarchy_ErrorMessages" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlErrorMessage"/>
<Node Name="DatabaseInstance" LocLabel="string.Empty" Image="Database" BaseClass="ModelBased" IsAsyncLoad="" Strategy="CreateModel">
<Child Name="Tables"/>
<Child Name="Views"/>
<Child Name="Synonyms"/>
<Child Name="Programmability"/>
<Child Name="ExternalResources"/>
<Child Name="ServiceBroker"/>
<Child Name="Storage"/>
<Child Name="Security"/>
</Node>
<Node Name="Tables" LocLabel="SR.SchemaHierarchy_Tables" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlTable" TreeNode="TableInstanceTreeNode">
<Filters>
<Filter Property="IsFileTable" Value="0" Type="bool" />
<Filter Property="IsExternal" Value="0" Type="bool" ValidFor="Sql2016|SqlvNext|AzureV12"/>
<Filter Property="TemporalType" Type="Enum" ValidFor="Sql2016|SqlvNext|AzureV12">
<Value>TemporalTableType.None</Value>
<Value>TemporalTableType.SystemVersioned</Value>
</Filter>
</Filters>
<Child Name="SystemTables"/>
<Child Name="FileTables"/>
<Child Name="ExternalTables"/>
</Node>
<Node Name="Views" LocLabel="SR.SchemaHierarchy_Views" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlView" TreeNode="ViewInstanceTreeNode">
<Child Name="SystemViews"/>
</Node>
<Node Name="Synonyms" LocLabel="SR.SchemaHierarchy_Synonyms" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlSynonym"/>
<Node Name="Programmability" LocLabel="SR.SchemaHierarchy_Programmability" BaseClass="ModelBased">
<Child Name="StoredProcedures"/>
<Child Name="Functions"/>
<Child Name="DatabaseTriggers"/>
<Child Name="Assemblies"/>
<Child Name="Types"/>
<Child Name="Rules"/>
<Child Name="Defaults"/>
<Child Name="Sequences"/>
</Node>
<Node Name="ExternalResources" LocLabel="SR.SchemaHierarchy_ExternalResources" BaseClass="ModelBased" TreeNode="ExternalResourceInstanceTreeNode" ValidFor="Sql2016|SqlvNext|AzureV12">
<Child Name="ExternalDataSources"/>
<Child Name="ExternalFileFormats"/>
</Node>
<Node Name="ServiceBroker" LocLabel="SR.SchemaHierarchy_ServiceBroker" BaseClass="ModelBased" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext">
<Child Name="MessageTypes"/>
<Child Name="Contracts"/>
<Child Name="Queues"/>
<Child Name="Services"/>
<!-- <Child Name="Routes"/> -->
<Child Name="DatabaseAndQueueEventNotifications"/>
<Child Name="RemoteServiceBindings"/>
<Child Name="BrokerPriorities"/>
</Node>
<Node Name="Storage" LocLabel="SR.SchemaHierarchy_Storage" BaseClass="ModelBased" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext|AzureV12">
<Child Name="FileGroups"/>
<Child Name="FullTextCatalogs"/>
<Child Name="FullTextStopLists"/>
<Child Name="SqlLogFiles"/>
<Child Name="PartitionFunctions"/>
<Child Name="PartitionSchemes"/>
<Child Name="SearchPropertyLists"/>
</Node>
<Node Name="Security" LocLabel="SR.SchemaHierarchy_Security" BaseClass="ModelBased" >
<Child Name="Users"/>
<Child Name="Roles"/>
<Child Name="Schemas"/>
<Child Name="AsymmetricKeys"/>
<Child Name="Certificates"/>
<Child Name="SymmetricKeys"/>
<Child Name="DatabaseScopedCredentials"/>
<Child Name="DatabaseEncryptionKeys"/>
<Child Name="MasterKeys"/>
<Child Name="Signatures"/>
<Child Name="DatabaseAuditSpecifications"/>
<Child Name="SecurityPolicies"/>
<Child Name="AlwaysEncryptedKeys"/>
</Node>
<!-- Childs of Tables -->
<Node Name="SystemTables" LocLabel="SR.SchemaHierarchy_SystemTables" BaseClass="ModelBased" IsMsShippedOwned="true" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlTable" TreeNode="TableInstanceTreeNode"/>
<Node Name="FileTables" LocLabel="SR.SchemaHierarchy_FileTables" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlTable" TreeNode="TableInstanceTreeNode" ValidFor="Sql2012|Sql2014|Sql2016|SqlvNext|NotDebugInstance">
<Filters>
<Filter Property="IsFileTable" Value="1" Type="boolean" />
</Filters>
</Node>
<Node Name="ExternalTables" LocLabel="SR.SchemaHierarchy_ExternalTables" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlTable" TreeNode="ExternalTableInstanceTreeNode" ValidFor="Sql2016|SqlvNext|AzureV12">
<Filters>
<Filter Property="IsExternalTable" Value="1" Type="boolean" />
</Filters>
</Node>
<Node Name="TableInstance" LocLabel="string.Empty" BaseClass="ModelBased" IsAsyncLoad="" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlTable" TreeNode="HistoryTableInstanceTreeNode">
<!-- TODO Add special history table handling to only return related history table instead of all! Under Table, we directly show any related history tables.-->
<Filters>
<Filter Property="TemporalType" Type="Enum" ValidFor="Sql2016|SqlvNext|AzureV12">
<Value>TemporalTableType.History</Value>
</Filter>
</Filters>
<Child Name="Columns"/>
<Child Name="Keys"/>
<Child Name="Constraints"/>
<Child Name="Triggers"/>
<Child Name="Indexes"/>
<Child Name="Statistics"/>
</Node>
<!-- TODO This should use display item not ChildQuerierTypes -->
<Node Name="HistoryTableInstance" LocLabel="string.Empty" BaseClass="ModelBased" IsAsyncLoad="" Strategy="PopulateDetails" ChildQuerierTypes="SqlTable" ValidFor="Sql2016|SqlvNext|AzureV12">
<Child Name="Columns"/>
<Child Name="Indexes"/>
<Child Name="Statistics"/>
</Node>
<!-- TODO This should use display item not ChildQuerierTypes -->
<Node Name="ExternalTableInstance" LocLabel="string.Empty" BaseClass="ModelBased" IsAsyncLoad="" Strategy="PopulateDetails" ChildQuerierTypes="SqlTable" ValidFor="Sql2016|SqlvNext|AzureV12">
<Child Name="Columns"/>
<Child Name="Statistics"/>
</Node>
<Node Name="Columns" LocLabel="SR.SchemaHierarchy_Columns" BaseClass="ModelBased" Strategy="PopulateParentDetails" ChildQuerierTypes="SqlColumn" DisableSort=""/>
<Node Name="Keys" LocLabel="SR.SchemaHierarchy_Keys" BaseClass="ModelBased" Strategy="ElementsInRelationship" ChildQuerierTypes="SqlIndex;SqlForeignKeyConstraint" >
<Filters>
<Filter TypeToReverse="SqlIndex" Property="IndexKeyType" Type="Enum" ValidFor="Sql2016|SqlvNext|AzureV12">
<Value>IndexKeyType.DriPrimaryKey</Value>
<Value>IndexKeyType.DriUniqueKey</Value>
</Filter>
</Filters>
</Node>
<Node Name="Constraints" LocLabel="SR.SchemaHierarchy_Constraints" BaseClass="ModelBased" Strategy="ElementsInRelationship" ChildQuerierTypes="SqlDefaultConstraint;SqlCheck"/>
<Node Name="Triggers" LocLabel="SR.SchemaHierarchy_Triggers" BaseClass="ModelBased" Strategy="ElementsInRelationship" ChildQuerierTypes="SqlDmlTrigger"/>
<Node Name="Indexes" LocLabel="SR.SchemaHierarchy_Indexes" BaseClass="ModelBased" Strategy="ElementsInRelationship" ChildQuerierTypes="SqlIndex;SqlFullTextIndex">
<Filters>
<Filter TypeToReverse="SqlIndex" Property="IndexKeyType" Type="Enum" ValidFor="Sql2016|SqlvNext|AzureV12">
<Value>IndexKeyType.None</Value>
</Filter>
</Filters>
</Node>
<Node Name="Statistics" LocLabel="SR.SchemaHierarchy_Statistics" BaseClass="ModelBased" Strategy="ElementsInRelationship" ChildQuerierTypes="SqlStatistic"/>
<Node Name="SystemViews" LocLabel="SR.SchemaHierarchy_SystemViews" BaseClass="ModelBased" IsMsShippedOwned="true" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlView" TreeNode="ViewInstanceTreeNode"/>
<Node Name="ViewInstance" LocLabel="string.Empty" BaseClass="ModelBased" IsAsyncLoad="" Strategy="PopulateDetails">
<Child Name="Columns"/>
<Child Name="Triggers"/>
<Child Name="Indexes"/>
<Child Name="Statistics"/>
</Node>
<Node Name="Functions" LocLabel="SR.SchemaHierarchy_Functions" BaseClass="ModelBased" >
<Child Name="TableValuedFunctions"/>
<Child Name="ScalarValuedFunctions"/>
<Child Name="AggregateFunctions"/>
</Node>
<Node Name="DatabaseTriggers" LocLabel="SR.SchemaHierarchy_DatabaseTriggers" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlDatabaseDdlTrigger"/>
<Node Name="Assemblies" LocLabel="SR.SchemaHierarchy_Assemblies" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlAssembly" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext|AzureV12"/>
<Node Name="Types" LocLabel="SR.SchemaHierarchy_Types" BaseClass="ModelBased" >
<Child Name="SystemDataTypes"/>
<Child Name="UserDefinedDataTypes"/>
<Child Name="UserDefinedTableTypes"/>
<Child Name="UserDefinedTypes"/>
<Child Name="XmlSchemaCollections"/>
</Node>
<Node Name="Rules" LocLabel="SR.SchemaHierarchy_Rules" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlRule" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext|AzureV12"/>
<Node Name="Defaults" LocLabel="SR.SchemaHierarchy_Defaults" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlDefault" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext|AzureV12"/>
<Node Name="Sequences" LocLabel="SR.SchemaHierarchy_Sequences" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlSequence" ValidFor="Sql2012|Sql2014|Sql2016|SqlvNext|AzureV12"/>
<Node Name="SystemDataTypes" LocLabel="SR.SchemaHierarchy_SystemDataTypes" BaseClass="ModelBased" >
<Child Name="SystemExactNumerics"/>
<Child Name="SystemApproximateNumerics"/>
<Child Name="SystemDateAndTimes"/>
<Child Name="SystemCharacterStrings"/>
<Child Name="SystemUnicodeCharacterStrings"/>
<Child Name="SystemBinaryStrings"/>
<Child Name="SystemOtherDataTypes"/>
<Child Name="SystemClrDataTypes"/>
<Child Name="SystemSpatialDataTypes"/>
</Node>
<Node Name="UserDefinedDataTypes" LocLabel="SR.SchemaHierarchy_UserDefinedDataTypes" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlUserDefinedDataType"/>
<Node Name="UserDefinedTableTypes" LocLabel="SR.SchemaHierarchy_UserDefinedTableTypes" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlUserDefinedTableType" TreeNode="UserDefinedTableTypeInstanceTreeNode" ValidFor="Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext|AzureV11|AzureV12"/>
<Node Name="UserDefinedTypes" LocLabel="SR.SchemaHierarchy_UserDefinedTypes" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlUserDefinedType" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext|AzureV12"/>
<Node Name="XmlSchemaCollections" LocLabel="SR.SchemaHierarchy_XMLSchemaCollections" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlXmlSchemaCollection" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext|AzureV12"/>
<Node Name="UserDefinedTableTypeInstance" LocLabel="string.Empty" BaseClass="ModelBased" ChildQuerierTypes="" IsAsyncLoad="" Strategy="PopulateDetails">
<Child Name="UserDefinedTableTypeColumns"/>
<Child Name="UserDefinedTableTypeKeys"/>
<Child Name="UserDefinedTableTypeConstraints"/>
</Node>
<Node Name="UserDefinedTableTypeColumns" LocLabel="SR.SchemaHierarchy_Columns" BaseClass="ModelBased" Strategy="PopulateParentDetails" ChildQuerierTypes="SqlColumn" DisableSort=""/>
<Node Name="UserDefinedTableTypeKeys" LocLabel="SR.SchemaHierarchy_Keys" BaseClass="ModelBased" Strategy="PopulateParentDetails" ChildQuerierTypes="SqlIndex">
<Filters>
<Filter TypeToReverse="SqlIndex" Property="IndexKeyType" Type="Enum" ValidFor="Sql2016|SqlvNext|AzureV12">
<Value>IndexKeyType.DriPrimaryKey</Value>
<Value>IndexKeyType.DriUniqueKey</Value>
</Filter>
</Filters>
</Node>
<Node Name="UserDefinedTableTypeConstraints" LocLabel="SR.SchemaHierarchy_Constraints" BaseClass="ModelBased" Strategy="PopulateParentDetails" ChildQuerierTypes="SqlDefaultConstraint;SqlCheck"/>/>
<Node Name="SystemExactNumerics" LocLabel="SR.SchemaHierarchy_SystemExactNumerics" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlBuiltInType"/>
<Node Name="SystemApproximateNumerics" LocLabel="SR.SchemaHierarchy_SystemApproximateNumerics" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlBuiltInType"/>
<Node Name="SystemDateAndTimes" LocLabel="SR.SchemaHierarchy_SystemDateAndTime" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlBuiltInType"/>
<Node Name="SystemCharacterStrings" LocLabel="SR.SchemaHierarchy_SystemCharacterStrings" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlBuiltInType"/>
<Node Name="SystemUnicodeCharacterStrings" LocLabel="SR.SchemaHierarchy_SystemUnicodeCharacterStrings" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlBuiltInType"/>
<Node Name="SystemBinaryStrings" LocLabel="SR.SchemaHierarchy_SystemBinaryStrings" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlBuiltInType"/>
<Node Name="SystemOtherDataTypes" LocLabel="SR.SchemaHierarchy_SystemOtherDataTypes" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlBuiltInType"/>
<Node Name="SystemClrDataTypes" LocLabel="SR.SchemaHierarchy_SystemCLRDataTypes" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlUserDefinedType" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext|AzureV11|AzureV12"/>
<Node Name="SystemSpatialDataTypes" LocLabel="SR.SchemaHierarchy_SystemSpatialDataTypes" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlUserDefinedType" ValidFor="Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext|AzureV11|AzureV12"/>
<!-- Childs of ExternalResources -->
<Node Name="ExternalDataSources" LocLabel="SR.SchemaHierarchy_ExternalDataSources" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlExternalDataSource" ValidFor="Sql2016|SqlvNext|AzureV12"/>
<Node Name="ExternalFileFormats" LocLabel="SR.SchemaHierarchy_ExternalFileFormats" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlExternalFileFormat" ValidFor="Sql2016|SqlvNext"/>
<Node Name="StoredProcedures" LocLabel="SR.SchemaHierarchy_StoredProcedures" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlProcedure" TreeNode="StoredProcedureInstanceTreeNode">
<Child Name="SystemStoredProcedures"/>
</Node>
<Node Name="SystemStoredProcedures" LocLabel="SR.SchemaHierarchy_SystemStoredProcedures" BaseClass="ModelBased" IsMsShippedOwned="true" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlProcedure" TreeNode="StoredProcedureInstanceTreeNode"/>
<Node Name="StoredProcedureInstance" LocLabel="string.Empty" BaseClass="ModelBased" ChildQuerierTypes="" IsAsyncLoad="" Strategy="PopulateDetails">
<Child Name="StoredProcedureParameters"/>
</Node>
<Node Name="StoredProcedureParameters" LocLabel="SR.SchemaHierarchy_Parameters" BaseClass="ModelBased" Strategy="StoredProcedureParameters" ChildQuerierTypes="SqlSubroutineParameter" DisableSort=""/>
<Node Name="TableValuedFunctions" LocLabel="SR.SchemaHierarchy_TableValuedFunctions" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlUserDefinedFunction" TreeNode="TableValuedFunctionInstanceTreeNode">
<Filters>
<Filter Property="UserDefinedFunctionType" Type="Enum" ValidFor="Sql2016|SqlvNext|AzureV12">
<Value>UserDefinedFunctionType.Table</Value>
</Filter>
</Filters>
</Node>
<Node Name="TableValuedFunctionInstance" LocLabel="string.Empty" BaseClass="ModelBased" ChildQuerierTypes="" IsAsyncLoad="" Strategy="PopulateDetails">
<Child Name="TableValuedFunctionParameters"/>
</Node>
<Node Name="TableValuedFunctionParameters" LocLabel="SR.SchemaHierarchy_Parameters" BaseClass="ModelBased" Strategy="FunctionParameters" ChildQuerierTypes="SqlSubroutineParameter" DisableSort=""/>
<Node Name="ScalarValuedFunctions" LocLabel="SR.SchemaHierarchy_ScalarValuedFunctions" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlUserDefinedFunction" TreeNode="ScalarValuedFunctionInstanceTreeNode" >
<Filters>
<Filter Property="UserDefinedFunctionType" Type="Enum" ValidFor="Sql2016|SqlvNext|AzureV12">
<Value>UserDefinedFunctionType.Table</Value>
</Filter>
</Filters>
</Node>
<Node Name="ScalarValuedFunctionInstance" LocLabel="string.Empty" BaseClass="ModelBased" ChildQuerierTypes="" IsAsyncLoad="" Strategy="PopulateDetails">
<Child Name="ScalarValuedFunctionParameters"/>
</Node>
<Node Name="ScalarValuedFunctionParameters" LocLabel="SR.SchemaHierarchy_Parameters" BaseClass="ModelBased" Strategy="FunctionParameters" ChildQuerierTypes="SqlSubroutineParameter" DisableSort=""/>
<Node Name="AggregateFunctions" LocLabel="SR.SchemaHierarchy_AggregateFunctions" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlUserDefinedAggregate" TreeNode="AggregateFunctionInstanceTreeNode" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext|AzureV12"/>
<Node Name="AggregateFunctionInstance" LocLabel="string.Empty" BaseClass="ModelBased" ChildQuerierTypes="" IsAsyncLoad="" Strategy="PopulateDetails">
<Child Name="AggregateFunctionParameters"/>
</Node>
<Node Name="AggregateFunctionParameters" LocLabel="SR.SchemaHierarchy_Parameters" BaseClass="ModelBased" Strategy="PopulateParentDetails" ChildQuerierTypes="SqlSubroutineParameter" DisableSort=""/>
<!-- TODO Support Route in SMO
<Node Name="Routes" LocLabel="SR.SchemaHierarchy_Routes" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlRoute"/>
-->
<!-- TODO support events
<Node Name="DatabaseAndQueueEventNotifications" LocLabel="SR.SchemaHierarchy_EventNotifications" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlEventNotification"/>
-->
<Node Name="RemoteServiceBindings" LocLabel="SR.SchemaHierarchy_RemoteServiceBindings" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlRemoteServiceBinding"/>
<Node Name="BrokerPriorities" LocLabel="SR.SchemaHierarchy_BrokerPriorities" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlBrokerPriority" ValidFor="Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext"/>
<Node Name="FileGroups" LocLabel="SR.SchemaHierarchy_FileGroups" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlFileGroup" TreeNode="FileGroupInstanceTreeNode"/>
<Node Name="FullTextCatalogs" LocLabel="SR.SchemaHierarchy_FullTextCatalogs" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlFullTextCatalog"/>
<Node Name="FullTextStopLists" LocLabel="SR.SchemaHierarchy_FullTextStopLists" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlFullTextStopList" ValidFor="Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext|AzureV12"/>
<Node Name="SqlLogFiles" LocLabel="SR.SchemaHierarchy_LogFiles" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlFile"/>
<Node Name="PartitionFunctions" LocLabel="SR.SchemaHierarchy_PartitionFunctions" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlPartitionFunction"/>
<Node Name="PartitionSchemes" LocLabel="SR.SchemaHierarchy_PartitionSchemes" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlPartitionScheme"/>
<Node Name="SearchPropertyLists" LocLabel="SR.SchemaHierarchy_SearchPropertyLists" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlSearchPropertyList" ValidFor="Sql2012|Sql2014|Sql2016|SqlvNext|AzureV12"/>
<Node Name="FileGroupInstance" LocLabel="string.Empty" BaseClass="ModelBased" ChildQuerierTypes="">
<Child Name="FileGroupFiles"/>
</Node>
<Node Name="FileGroupFiles" LocLabel="SR.SchemaHierarchy_FilegroupFiles" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlFile" >
</Node>
<Node Name="Users" LocLabel="SR.SchemaHierarchy_Users" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlUser"/>
<Node Name="Roles" LocLabel="SR.SchemaHierarchy_Roles" BaseClass="ModelBased" >
<Child Name="DatabaseRoles"/>
<Child Name="ApplicationRoles"/>
</Node>
<Node Name="Schemas" LocLabel="SR.SchemaHierarchy_Schemas" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlSchema"/>
<Node Name="AsymmetricKeys" LocLabel="SR.SchemaHierarchy_AsymmetricKeys" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlAsymmetricKey" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext"/>
<Node Name="Certificates" LocLabel="SR.SchemaHierarchy_Certificates" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlCertificate" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext"/>
<Node Name="SymmetricKeys" LocLabel="SR.SchemaHierarchy_SymmetricKeys" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlSymmetricKey" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext"/>
<Node Name="DatabaseEncryptionKeys" LocLabel="SR.SchemaHierarchy_DatabaseEncryptionKeys" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlDatabaseEncryptionKey" ValidFor="Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext"/>
<Node Name="MasterKeys" LocLabel="SR.SchemaHierarchy_MasterKeys" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlMasterKey" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext"/>
<!-- TODO Support signatures
<Node Name="Signatures" LocLabel="SR.SchemaHierarchy_Signatures" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlSignature" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext"/>
-->
<Node Name="DatabaseAuditSpecifications" LocLabel="SR.SchemaHierarchy_DatabaseAuditSpecifications" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlDatabaseAuditSpecification" ValidFor="Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext"/>
<Node Name="SecurityPolicies" LocLabel="SR.SchemaHierarchy_SecurityPolicies" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlSecurityPolicy" ValidFor="Sql2016|SqlvNext|AzureV12"/>
<Node Name="DatabaseScopedCredentials" LocLabel="SR.SchemaHierarchy_DatabaseScopedCredentials" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlDatabaseCredential" ValidFor="Sql2016|SqlvNext|AzureV12"/>
<Node Name="AlwaysEncryptedKeys" LocLabel="SR.SchemaHierarchy_AlwaysEncryptedKeys" BaseClass="ModelBased" ValidFor="Sql2016|SqlvNext|AzureV12">
<Child Name="ColumnMasterKeys"/>
<Child Name="ColumnEncryptionKeys"/>
</Node>
<Node Name="DatabaseRoles" LocLabel="SR.SchemaHierarchy_DatabaseRoles" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlRole"/>
<Node Name="ApplicationRoles" LocLabel="SR.SchemaHierarchy_ApplicationRoles" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlApplicationRole" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext|AzureV12"/>
<Node Name="ColumnMasterKeys" LocLabel="SR.SchemaHierarchy_ColumnMasterKeys" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlColumnMasterKey" ValidFor="Sql2016|SqlvNext|AzureV12"/>
<Node Name="ColumnEncryptionKeys" LocLabel="SR.SchemaHierarchy_ColumnEncryptionKeys" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlColumnEncryptionKey" ValidFor="Sql2016|SqlvNext|AzureV12"/>
<Node Name="MessageTypes" LocLabel="SR.SchemaHierarchy_MessageTypes" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlMessageType">
<Child Name="SystemMessageTypes"/>
</Node>
<Node Name="SystemMessageTypes" LocLabel="SR.SchemaHierarchy_SystemMessageTypes" BaseClass="ModelBased" IsMsShippedOwned="true" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlMessageType"/>
<Node Name="Contracts" LocLabel="SR.SchemaHierarchy_Contracts" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlContract">
<Child Name="SystemContracts"/>
</Node>
<Node Name="SystemContracts" LocLabel="SR.SchemaHierarchy_SystemContracts" BaseClass="ModelBased" IsMsShippedOwned="true" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlContract"/>
<Node Name="Queues" LocLabel="SR.SchemaHierarchy_Queues" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlQueue">
<Child Name="SystemQueues"/>
</Node>
<Node Name="SystemQueues" LocLabel="SR.SchemaHierarchy_SystemQueues" BaseClass="ModelBased" IsMsShippedOwned="true" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlQueue"/>
<Node Name="Services" LocLabel="SR.SchemaHierarchy_Services" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlService">
<Child Name="SystemServices"/>
</Node>
<Node Name="SystemServices" LocLabel="SR.SchemaHierarchy_SystemServices" BaseClass="ModelBased" IsMsShippedOwned="true" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlService"/>
<CodeGenOptions>
<UniqueTreeNode Name="DatabaseInstanceTreeNode"/>
<UniqueTreeNode Name="TableInstanceTreeNode"/>
<UniqueTreeNode Name="ViewInstanceTreeNode"/>
<UniqueTreeNode Name="UserDefinedTableTypeInstanceTreeNode"/>
<UniqueTreeNode Name="StoredProcedureInstanceTreeNode"/>
<UniqueTreeNode Name="TableValuedFunctionInstanceTreeNode"/>
<UniqueTreeNode Name="ScalarValuedFunctionInstanceTreeNode"/>
<UniqueTreeNode Name="AggregateFunctionInstanceTreeNode"/>
<UniqueTreeNode Name="FileGroupInstanceTreeNode"/>
<UniqueTreeNode Name="ExternalTableInstanceTreeNode"/>
<UniqueTreeNode Name="ExternalResourceInstanceTreeNode"/>
<UniqueTreeNode Name="HistoryTableInstanceTreeNode" />
</CodeGenOptions>
<!-- WARNING: Specifying reverse dependencies that could load large numbers of objects will be detrimental to performance. -->
<ReverseDependencyList>
<ReverseDependency Type="SqlUser" DependsOn="SqlRole;SqlRoleMembership"/>
</ReverseDependencyList>
</ServerExplorerTree>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,387 @@
<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ output extension=".cs" #>
<#@ assembly name="System.Xml.dll" #>
<#@ import namespace="System" #>
<#@ import namespace="System.Globalization" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Xml" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.IO" #>
using System;
using System.Collections.Generic;
using System.Composition;
using Microsoft.SqlTools.ServiceLayer;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{
<#
var directory = Path.GetDirectoryName(Host.TemplateFile);
string xmlFile = Path.Combine(directory, "TreeNodeDefinition.xml");
/////////
// TODO - is Generate all the ReverseDependencies needed?
/////////
// var allReverseDependencies = GetReverseDependencies(xmlFile);
// WriteLine(" internal static class TreeNodeRules");
// WriteLine(" {");
// WriteLine(" internal static Dictionary<Type, IList<Type>> TypeReverseDependencyMap = new Dictionary<Type, IList<Type>>()");
// WriteLine(" {");
// foreach (var reverseDependencyKey in allReverseDependencies.Keys)
// {
// bool isFirstDependentType = true;
// StringBuilder dependentListBuilder = new StringBuilder("{");
// foreach (var dependentType in allReverseDependencies[reverseDependencyKey])
// {
// if (isFirstDependentType)
// {
// isFirstDependentType = false;
// }
// else
// {
// dependentListBuilder.Append(",");
// }
//
// dependentListBuilder.Append(string.Format(CultureInfo.InvariantCulture, " typeof({0})", dependentType));
// }
// dependentListBuilder.Append(" }");
//
// WriteLine(string.Format(CultureInfo.InvariantCulture, " {{ typeof({0}), new List<Type> {1} }}", reverseDependencyKey, dependentListBuilder.ToString()));
// }
// WriteLine(" };");
// WriteLine(" }");
// WriteLine("");
/////////
// First generate all the TreeNodes
/////////
var allTreeNodes = GetUniqueTreeNodes(xmlFile);
foreach (var TreeNode in allTreeNodes)
{
var name = TreeNode.GetAttribute("Name");
WriteLine(string.Format(" internal sealed partial class {0} : SmoTreeNode", name));
WriteLine(" {");
WriteLine(string.Format(" public {0}() : base()", name));
WriteLine(" {");
WriteLine(" NodeValue = string.Empty;");
WriteLine(string.Format(" this.NodeType = \"{0}\";", name.Replace("TreeNode", string.Empty)));
WriteLine(string.Format(" this.NodeTypeId = NodeTypes.{0};", name.Replace("TreeNode", string.Empty)));
WriteLine(" OnInitialize();");
WriteLine(" }");
WriteLine(" }");
WriteLine("");
}
/////////
// Now generate all the ChildFactories
/////////
var allNodes = GetNodes(xmlFile);
foreach (var type in allNodes)
{
XmlElement nodeElement = GetNodeElement(xmlFile, type);
var imageAttr = nodeElement.GetAttribute("Image");
var isAlwaysLeaf = nodeElement.GetAttributeNode("IsAlwaysLeaf");
var baseClass = nodeElement.GetAttribute("BaseClass");
var strategy = nodeElement.GetAttribute("Strategy");
var ChildQuerierTypes = nodeElement.GetAttribute("ChildQuerierTypes");
var TreeNode = nodeElement.GetAttribute("TreeNode");
var isAsync = nodeElement.GetAttributeNode("IsAsyncLoad");
var disableSort = nodeElement.GetAttributeNode("DisableSort");
string childFactoryBaseClass = "SmoChildFactoryBase";
// TODO Will we need alternative child factories? If so, add code here to support this
if (isAlwaysLeaf == null)
{
WriteLine(" [Export(typeof(ChildFactory))]");
WriteLine(" [Shared]");
WriteLine(string.Format(" internal partial class {0}ChildFactory : {1}", type, childFactoryBaseClass));
WriteLine(" {");
WriteLine(string.Format(" public override IEnumerable<string> ApplicableParents() {{ return new[] {{ \"{0}\" }}; }}", type));
List<XmlElement> children = GetChildren(xmlFile, type);
if (children.Count > 0)
{
WriteLine("");
WriteLine(" protected override void OnExpandPopulateFolders(IList<TreeNode> currentChildren, TreeNode parent)");
WriteLine(" {");
foreach (var child in children)
{
XmlElement childAsXmlElement = GetNodeElement(xmlFile, child.GetAttribute("Name"));
if (childAsXmlElement == null)
{
// TODO SHould we error with clear message that this needs to be fixed?
continue;
}
string childImage = childAsXmlElement.GetAttribute("Image");
var msShippedOwned = childAsXmlElement.GetAttributeNode("IsMsShippedOwned");
var validFor = childAsXmlElement.GetAttribute("ValidFor");
if (TreeNodeExists(xmlFile, child.GetAttribute("Name") + "TreeNode"))
{
WriteLine(string.Format(" currentChildren.Add(new {0}TreeNode {{ SortPriority = SmoTreeNode.NextSortPriority }} );", child.GetAttribute("Name")));
}
else
{
WriteLine(" currentChildren.Add(new FolderNode {");
WriteLine(string.Format(" NodeValue = {0},", childAsXmlElement.GetAttribute("LocLabel")));
WriteLine(string.Format(" NodeType = \"{0}\",", "Folder"));
WriteLine(string.Format(" NodeTypeId = NodeTypes.{0},", child.GetAttribute("Name")));
if (msShippedOwned != null)
{
WriteLine(" IsMsShippedOwned = true,");
}
if (!string.IsNullOrWhiteSpace(validFor))
{
WriteLine(string.Format(" ValidFor = {0},", GetValidForFlags(validFor)));
}
WriteLine(" SortPriority = SmoTreeNode.NextSortPriority,");
WriteLine(" });");
}
}
WriteLine(" }");
}
if (!string.IsNullOrWhiteSpace(strategy))
{
string[] allTypes = ChildQuerierTypes.Split(new [] { ';' }, StringSplitOptions.RemoveEmptyEntries);
WriteLine("");
WriteLine(" internal override Type[] ChildQuerierTypes");
WriteLine(" {");
WriteLine(" get");
WriteLine(" {");
if (!string.IsNullOrWhiteSpace(ChildQuerierTypes))
{
Write(" return new [] {");
foreach (var typeToRe in allTypes)
{
Write(string.Format(" typeof({0}Querier),", typeToRe));
}
WriteLine(" };");
}
else
{
Write(" return new Type[0];");
}
WriteLine(" }");
WriteLine(" }");
WriteLine("");
WriteLine(" public override TreeNode CreateChild(TreeNode parent, object context)");
WriteLine(" {");
if (string.IsNullOrWhiteSpace(TreeNode))
{
WriteLine(" var child = new SmoTreeNode();");
WriteLine(" child.IsAlwaysLeaf = true;");
}
else
{
var modelNodeChildren = GetNodeElement(xmlFile, TreeNode.Replace("TreeNode",string.Empty));
WriteLine(string.Format(" var child = new {0}();", TreeNode));
if (modelNodeChildren.ChildNodes.Count == 0)
{
WriteLine(" child.IsAlwaysLeaf = true;");
}
}
if (disableSort != null)
{
WriteLine(" child.SortPriority = SmoTreeNode.NextSortPriority;");
}
WriteLine(" InitializeChild(child, context);");
WriteLine(" return child;");
WriteLine(" }");
}
else if (baseClass == "ModelBased")
{
WriteLine("");
WriteLine(" internal override Type[] ChildQuerierTypes { get {return null;} }");
WriteLine("");
// TODO Is reverse engineering strategy every needed?
// WriteLine(" protected override ReverseEngineeringStrategy Strategy { get {return ReverseEngineeringStrategy.None;} }");
WriteLine("");
WriteLine(" public override TreeNode CreateChild(TreeNode parent, object context)");
WriteLine(" {");
WriteLine(" return null;");
WriteLine(" }");
}
WriteLine(" }");
WriteLine("");
}
}
#>
}
<#+
public static string GetValidForFlags(string validForStr)
{
List<string> flags = new List<string>();
if (validForStr.Contains("Sql2005"))
{
flags.Add("ValidForFlag.Sql2005");
}
if (validForStr.Contains("Sql2008"))
{
flags.Add("ValidForFlag.Sql2008");
}
if (validForStr.Contains("Sql2012"))
{
flags.Add("ValidForFlag.Sql2012");
}
if (validForStr.Contains("Sql2014"))
{
flags.Add("ValidForFlag.Sql2014");
}
if (validForStr.Contains("Sql2016"))
{
flags.Add("ValidForFlag.Sql2016");
}
if (validForStr.Contains("AzureV11"))
{
flags.Add("ValidForFlag.Azure");
}
if (validForStr.Contains("AzureV12"))
{
flags.Add("ValidForFlag.AzureV12");
}
if (validForStr.Contains("NotDebugInstance"))
{
flags.Add("ValidForFlag.NotDebugInstance");
}
if (validForStr.Contains("NotContainedUser"))
{
flags.Add("ValidForFlag.NotContainedUser");
}
if (validForStr.Contains("CanConnectToMaster"))
{
flags.Add("ValidForFlag.CanConnectToMaster");
}
if (validForStr.Contains("CanViewSecurity"))
{
flags.Add("ValidForFlag.CanViewSecurity");
}
return string.Join("|", flags);
}
public static string[] GetNodes(string xmlFile)
{
List<string> typesList = new List<string>();
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
XmlNodeList treeTypes = doc.SelectNodes("/ServerExplorerTree/Node");
if (treeTypes != null)
{
foreach (var type in treeTypes)
{
XmlElement element = type as XmlElement;
if (element != null)
{
typesList.Add(element.GetAttribute("Name"));
}
}
}
return typesList.ToArray();
}
public static Dictionary<string, List<string>> GetReverseDependencies(string xmlFile)
{
Dictionary<string, List<string>> dependencyMap = new Dictionary<string, List<string>>();
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
XmlNodeList treeTypes = doc.SelectNodes("/ServerExplorerTree/ReverseDependencyList/ReverseDependency");
if (treeTypes != null)
{
foreach (var type in treeTypes)
{
XmlElement element = type as XmlElement;
if (element != null)
{
string typeName = element.GetAttribute("Type");
string dependency = element.GetAttribute("DependsOn");
List<string> dependenciesForType;
if (dependencyMap.TryGetValue(typeName, out dependenciesForType))
{
dependenciesForType.Add(dependency);
}
else
{
string[] allDepedencies = dependency.Split(new [] { ';' }, StringSplitOptions.RemoveEmptyEntries);
dependenciesForType = new List<string>();
dependenciesForType.AddRange(allDepedencies);
dependencyMap.Add(typeName, dependenciesForType);
}
}
}
}
return dependencyMap;
}
public static XmlElement GetNodeElement(string xmlFile, string nodeName)
{
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
return (XmlElement)doc.SelectSingleNode(string.Format("/ServerExplorerTree/Node[@Name='{0}']", nodeName));
}
public static bool TreeNodeExists(string xmlFile, string TreeNode)
{
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
var found = (XmlElement)doc.SelectSingleNode(string.Format("/ServerExplorerTree/CodeGenOptions/UniqueTreeNode[@Name='{0}']", TreeNode));
return (found != null);
}
public static List<XmlElement> GetUniqueTreeNodes(string xmlFile)
{
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
List<XmlElement> retElements = new List<XmlElement>();
XmlNodeList nodeList = doc.SelectNodes("/ServerExplorerTree/CodeGenOptions/UniqueTreeNode");
foreach (var item in nodeList)
{
XmlElement itemAsElement = item as XmlElement;
if (itemAsElement != null)
{
retElements.Add(itemAsElement);
}
}
return retElements;
}
public static List<XmlElement> GetChildren(string xmlFile, string parentName)
{
XmlElement nodeElement = GetNodeElement(xmlFile, parentName);
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
List<XmlElement> retElements = new List<XmlElement>();
XmlNodeList nodeList = doc.SelectNodes(string.Format("/ServerExplorerTree/Node[@Name='{0}']/Child", parentName));
foreach (var item in nodeList)
{
XmlElement itemAsElement = item as XmlElement;
if (itemAsElement != null)
{
retElements.Add(itemAsElement);
}
}
return retElements;
}
#>

View File

@@ -44,3 +44,6 @@ using System.Runtime.InteropServices;
[assembly: InternalsVisibleTo("Microsoft.SqlTools.ServiceLayer.UnitTests")]
[assembly: InternalsVisibleTo("Microsoft.SqlTools.ServiceLayer.IntegrationTests")]
[assembly: InternalsVisibleTo("Microsoft.SqlTools.ServiceLayer.Test.Common")]
// Allowing internals visible access to Moq library to help testing
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]

View File

@@ -8,6 +8,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.SqlTools.Extensibility;
using Microsoft.SqlTools.Hosting;
using Microsoft.SqlTools.Hosting.Contracts;
using Microsoft.SqlTools.Hosting.Protocol;
@@ -29,6 +30,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Hosting
/// </summary>
private const int ShutdownTimeoutInSeconds = 120;
public static readonly string[] CompletionTriggerCharacters = new string[] { ".", "-", ":", "\\", "[", "\"" };
private IMultiServiceProvider serviceProvider;
#region Singleton Instance Code
@@ -54,6 +56,18 @@ namespace Microsoft.SqlTools.ServiceLayer.Hosting
// Initialize the shutdown activities
shutdownCallbacks = new List<ShutdownCallback>();
initializeCallbacks = new List<InitializeCallback>();
}
public IMultiServiceProvider ServiceProvider
{
get
{
return serviceProvider;
}
internal set
{
serviceProvider = value;
}
}
/// <summary>

View File

@@ -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.
//
namespace Microsoft.SqlTools.ServiceLayer.Utility
{
/// <summary>
/// Common Constant values used across multiple services
/// </summary>
public static class CommonConstants
{
public const string MasterDatabaseName = "master";
public const string MsdbDatabaseName = "msdb";
public const string ModelDatabaseName = "model";
public const string TempDbDatabaseName = "tempdb";
}
}

View File

@@ -0,0 +1,215 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.SqlTools.ServiceLayer.Connection;
using Microsoft.SqlTools.ServiceLayer.Connection.Contracts;
using Microsoft.SqlTools.ServiceLayer.IntegrationTests.Utility;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
using Microsoft.SqlTools.ServiceLayer.Test.Common;
using Xunit;
using static Microsoft.SqlTools.ServiceLayer.ObjectExplorer.ObjectExplorerService;
namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectExplorer
{
public class ObjectExplorerServiceTests
{
private ObjectExplorerService _service = TestServiceProvider.Instance.ObjectExplorerService;
[Fact]
public async void CreateSessionAndExpandOnTheServerShouldReturnTheDatabases()
{
var query = "";
string uri = "CreateSessionAndExpand";
string databaseName = null;
using (SqlTestDb testDb = SqlTestDb.CreateNew(TestServerType.OnPrem, false, databaseName, query, uri))
{
var session = await CreateSession(testDb.DatabaseName, uri);
await CreateSessionAndDatabaseNode(testDb.DatabaseName, session);
CancelConnection(uri);
}
}
private async Task<ObjectExplorerSession> CreateSession(string databaseName, string uri)
{
ConnectParams connectParams = TestServiceProvider.Instance.ConnectionProfileService.GetConnectionParameters(TestServerType.OnPrem, databaseName);
ConnectionDetails details = connectParams.Connection;
return await _service.DoCreateSession(details, uri);
}
private async Task<NodeInfo> CreateSessionAndDatabaseNode(string databaseName, ObjectExplorerSession session)
{
Assert.NotNull(session);
Assert.NotNull(session.Root);
NodeInfo nodeInfo = session.Root.ToNodeInfo();
Assert.Equal(nodeInfo.IsLeaf, false);
Assert.Equal(nodeInfo.NodeType, NodeTypes.ServerInstance.ToString());
var children = session.Root.Expand();
//All server children should be folder nodes
foreach (var item in children)
{
Assert.Equal(item.NodeType, "Folder");
}
var databasesRoot = children.FirstOrDefault(x => x.NodeTypeId == NodeTypes.Databases);
var databasesChildren = await _service.ExpandNode(session, databasesRoot.GetNodePath());
var databases = databasesChildren.Where(x => x.NodeType == NodeTypes.DatabaseInstance.ToString());
//Verify the test databases is in the list
Assert.NotNull(databases);
var databaseNode = databases.FirstOrDefault(d => d.Label == databaseName);
Assert.NotNull(databaseNode);
return databaseNode;
}
private void CancelConnection(string uri)
{
//ConnectionService.Instance.CancelConnect(new CancelConnectParams
//{
// OwnerUri = uri,
// Type = ConnectionType.Default
//});
}
private async Task ExpandTree(NodeInfo node, ObjectExplorerSession session)
{
if(node != null && !node.IsLeaf)
{
var children = await _service.ExpandNode(session, node.NodePath);
Assert.NotNull(children);
if(children.Count() == 0 && !node.NodePath.Contains("System") &&
!node.NodePath.Contains("FileTables") && !node.NodePath.Contains("External Tables"))
{
var labaleToUpper = node.Label.ToUpper();
if (labaleToUpper.Contains("TABLE") || labaleToUpper.Contains("StoredProcedure")
|| labaleToUpper.Contains("VIEW"))
{
//TOOD: Add a better validation. For now at least check tables not to be empty
//Assert.True(false, "The list of tables, procedure and views cannot be empty");
}
}
foreach (var child in children)
{
//Console.WriteLine(child.Label);
await ExpandTree(child, session);
}
}
}
[Fact]
public async void VerifyAdventureWorksDatabaseObjects()
{
var query = Scripts.AdventureWorksScript;
string uri = "VerifyAdventureWorksDatabaseObjects";
string databaseName = null;
using (SqlTestDb testDb = SqlTestDb.CreateNew(TestServerType.OnPrem, false, databaseName, query, uri))
{
var session = await CreateSession(testDb.DatabaseName, uri);
var databaseNodeInfo = await CreateSessionAndDatabaseNode(testDb.DatabaseName, session);
await ExpandTree(databaseNodeInfo, session);
CancelConnection(uri);
}
}
// [Fact]
public async void VerifySql2016Objects()
{
var query = LoadScript("Sql_2016_Additions.sql");
string uri = "VerifySql2016Objects";
string databaseName = null;
using (SqlTestDb testDb = SqlTestDb.CreateNew(TestServerType.OnPrem, false, databaseName, query, uri))
{
var session = await CreateSession(testDb.DatabaseName, uri);
var databaseNodeInfo = await CreateSessionAndDatabaseNode(testDb.DatabaseName, session);
await ExpandTree(databaseNodeInfo, session);
CancelConnection(uri);
}
}
// [Fact]
public async void VerifySqlObjects()
{
var query = LoadScript("Sql_Additions.sql");
string uri = "VerifySqlObjects";
string databaseName = null;
using (SqlTestDb testDb = SqlTestDb.CreateNew(TestServerType.OnPrem, false, databaseName, query, uri))
{
var session = await CreateSession(testDb.DatabaseName, uri);
var databaseNodeInfo = await CreateSessionAndDatabaseNode(testDb.DatabaseName, session);
await ExpandTree(databaseNodeInfo, session);
CancelConnection(uri);
}
}
// [Fact]
public async void VerifyFileTableTest()
{
var query = LoadScript("FileTableTest.sql");
string uri = "VerifyFileTableTest";
string databaseName = null;
using (SqlTestDb testDb = SqlTestDb.CreateNew(TestServerType.OnPrem, false, databaseName, query, uri))
{
var session = await CreateSession(testDb.DatabaseName, uri);
var databaseNodeInfo = await CreateSessionAndDatabaseNode(testDb.DatabaseName, session);
await ExpandTree(databaseNodeInfo, session);
CancelConnection(uri);
}
}
//[Fact]
public async void VerifyColumnstoreindexSql16()
{
var query = LoadScript("ColumnstoreindexSql16.sql");
string uri = "VerifyColumnstoreindexSql16";
string databaseName = null;
using (SqlTestDb testDb = SqlTestDb.CreateNew(TestServerType.OnPrem, false, databaseName, query, uri))
{
var session = await CreateSession(testDb.DatabaseName, uri);
var databaseNodeInfo = await CreateSessionAndDatabaseNode(testDb.DatabaseName, session);
await ExpandTree(databaseNodeInfo, session);
CancelConnection(uri);
}
}
private static string TestLocationDirectory
{
get
{
return Path.Combine(RunEnvironmentInfo.GetTestDataLocation(), "ObjectExplorer");
}
}
public DirectoryInfo InputFileDirectory
{
get
{
string d = Path.Combine(TestLocationDirectory, "TestScripts");
return new DirectoryInfo(d);
}
}
public FileInfo GetInputFile(string fileName)
{
return new FileInfo(Path.Combine(InputFileDirectory.FullName, fileName));
}
private string LoadScript(string fileName)
{
FileInfo inputFile = GetInputFile(fileName);
return TestUtilities.ReadTextAndNormalizeLineEndings(inputFile.FullName);
}
}
}

View File

@@ -1,7 +1,10 @@
using System.Data.SqlClient;
using System;
using System.Data.SqlClient;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlTools.ServiceLayer.Connection;
using Microsoft.SqlTools.ServiceLayer.Connection.Contracts;
@@ -27,11 +30,11 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Utility
}
public static TestConnectionResult InitLiveConnectionInfo()
public static TestConnectionResult InitLiveConnectionInfo(string databaseName = null)
{
string sqlFilePath = GetTestSqlFile();
ScriptFile scriptFile = TestServiceProvider.Instance.WorkspaceService.Workspace.GetFile(sqlFilePath);
ConnectParams connectParams = TestServiceProvider.Instance.ConnectionProfileService.GetConnectionParameters(TestServerType.OnPrem);
ConnectParams connectParams = TestServiceProvider.Instance.ConnectionProfileService.GetConnectionParameters(TestServerType.OnPrem, databaseName);
string ownerUri = scriptFile.ClientFilePath;
var connectionService = GetLiveTestConnectionService();
@@ -50,6 +53,35 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Utility
return new TestConnectionResult() { ConnectionInfo = connInfo, ScriptFile = scriptFile };
}
public static async Task<TestConnectionResult> InitLiveConnectionInfoAsync(string databaseName = null, string ownerUri = null)
{
ScriptFile scriptFile = null;
if (string.IsNullOrEmpty(ownerUri))
{
string sqlFilePath = GetTestSqlFile();
scriptFile = TestServiceProvider.Instance.WorkspaceService.Workspace.GetFile(sqlFilePath);
ownerUri = scriptFile.ClientFilePath;
}
ConnectParams connectParams = TestServiceProvider.Instance.ConnectionProfileService.GetConnectionParameters(TestServerType.OnPrem, databaseName);
var connectionService = GetLiveTestConnectionService();
var connectionResult =
await connectionService
.Connect(new ConnectParams
{
OwnerUri = ownerUri,
Connection = connectParams.Connection
});
if (!string.IsNullOrEmpty(connectionResult.ErrorMessage))
{
Console.WriteLine(connectionResult.ErrorMessage);
}
ConnectionInfo connInfo = null;
connectionService.TryFindConnection(ownerUri, out connInfo);
return new TestConnectionResult() { ConnectionInfo = connInfo, ScriptFile = scriptFile };
}
public static ConnectionInfo InitLiveConnectionInfoForDefinition(string databaseName = null)
{
ConnectParams connectParams = TestServiceProvider.Instance.ConnectionProfileService.GetConnectionParameters(TestServerType.OnPrem, databaseName);

View File

@@ -43,7 +43,9 @@ END
public static string CreateDatabaseQuery { get { return CreateDatabaseQueryInstance.Value; } }
public static string TestDbComplexSelectQueries { get { return TestDbSelectQueriesInstance.Value; } }
public static string TestDbComplexSelectQueries { get { return TestDbSelectQueriesInstance.Value; } }
public static string AdventureWorksScript { get { return AdventureWorksScriptInstance.Value; } }
private static readonly Lazy<string> CreateDatabaseObjectsQueryInstance = new Lazy<string>(() =>
{
@@ -58,6 +60,11 @@ END
private static readonly Lazy<string> TestDbSelectQueriesInstance = new Lazy<string>(() =>
{
return GetScriptFileContent(ResourceNameRefix + "TestDbTableQueries.sql");
});
private static readonly Lazy<string> AdventureWorksScriptInstance = new Lazy<string>(() =>
{
return GetScriptFileContent(ResourceNameRefix + "AdventureWorks.sql");
});
private static string GetScriptFileContent(string fileName)

View File

@@ -27,13 +27,18 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Common
/// <summary>
/// Create the test db if not already exists
/// </summary>
public static SqlTestDb CreateNew(TestServerType serverType, bool doNotCleanupDb = false, string databaseName = null, string query = null)
public static SqlTestDb CreateNew(
TestServerType serverType,
bool doNotCleanupDb = false,
string databaseName = null,
string query = null,
string dbNamePrefix = null)
{
SqlTestDb testDb = new SqlTestDb();
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
{
databaseName = databaseName ?? GetUniqueDBName("");
databaseName = databaseName ?? GetUniqueDBName(dbNamePrefix);
string createDatabaseQuery = Scripts.CreateDatabaseQuery.Replace("#DatabaseName#", databaseName);
TestServiceProvider.Instance.RunQuery(serverType, MasterDatabaseName, createDatabaseQuery);
Console.WriteLine(string.Format(CultureInfo.InvariantCulture, "Test database '{0}' is created", databaseName));

View File

@@ -0,0 +1,34 @@
CREATE TABLE CS_Delay_Table1
(ProductKey [int] NOT NULL,
OrderDateKey [int] NOT NULL,
DueDateKey [int] NOT NULL,
ShipDateKey [int] NOT NULL);
GO
CREATE CLUSTERED COLUMNSTORE INDEX CSI_1 ON CS_Delay_Table1
WITH (COMPRESSION_DELAY = 100 minutes);
GO
CREATE TABLE CS_Delay_Table2
(ProductKey [int] NOT NULL,
OrderDateKey [int] NOT NULL,
DueDateKey [int] NOT NULL,
ShipDateKey [int] NOT NULL);
GO
CREATE CLUSTERED INDEX CI_Table2 ON CS_Delay_Table2 (ProductKey);
GO
CREATE NONCLUSTERED COLUMNSTORE INDEX CSI_2
ON CS_Delay_Table2
(OrderDateKey, DueDateKey, ShipDateKey)
WITH (COMPRESSION_DELAY = 200);
GO
CREATE TABLE CS_Delay_Table3
(ProductKey [int] NOT NULL,
OrderDateKey [int] NOT NULL,
DueDateKey [int] NOT NULL,
ShipDateKey [int] NOT NULL,
INDEX CSI_3 CLUSTERED COLUMNSTORE WITH(COMPRESSION_DELAY = 50 minute));
GO

View File

@@ -0,0 +1,103 @@
CREATE DATABASE [$(DatabaseName)]
GO
ALTER DATABASE [$(DatabaseName)] SET TARGET_RECOVERY_TIME = 1 MINUTES
GO
USE [$(DatabaseName)]
GO
ALTER DATABASE [$(DatabaseName)]
SET FILESTREAM(
NON_TRANSACTED_ACCESS = FULL,
DIRECTORY_NAME = N'$(DatabaseName)'
) WITH NO_WAIT
GO
ALTER DATABASE $(DatabaseName)
ADD FILEGROUP [FileGroup1]
CONTAINS FILESTREAM
GO
ALTER DATABASE $(DatabaseName)
ADD FILE
(NAME = 'FileTableFile'
, FILENAME = '$(DefaultDataPath)$(DatabaseName)_FT'
)
TO FILEGROUP [FileGroup1]
GO
CREATE TABLE [dbo].[FileTablePass] AS FILETABLE WITH(
FileTable_Directory = 'docs',
FILETABLE_PRIMARY_KEY_CONSTRAINT_NAME=MyPk,
FILETABLE_STREAMID_UNIQUE_CONSTRAINT_NAME=MyStreamUQ,
FILETABLE_FULLPATH_UNIQUE_CONSTRAINT_NAME=MyPathUQ)
GO
ALTER TABLE [dbo].[FileTablePass] WITH CHECK ADD CONSTRAINT [MyCheck] CHECK ((stream_id IS NOT NULL))
GO
ALTER TABLE [dbo].[FileTablePass] ADD CONSTRAINT [MyDefault] DEFAULT ((NULL)) FOR [name]
GO
ALTER TABLE [dbo].[FileTablePass] ADD CONSTRAINT [MyQU] UNIQUE NONCLUSTERED ([name] ASC)
GO
ALTER TABLE [dbo].[FileTablePass] WITH CHECK ADD CONSTRAINT [MyFk] FOREIGN KEY([parent_path_locator])
REFERENCES [dbo].[FileTablePass] ([path_locator])
GO
CREATE TABLE [dbo].[t2] (
[c1] INT NOT NULL,
[c2] INT DEFAULT ((1)) NULL,
[c3] INT DEFAULT ((1)) NOT NULL,
[path_locator] hierarchyid,
PRIMARY KEY CLUSTERED ([c1] ASC),
UNIQUE NONCLUSTERED ([c2] ASC),
CHECK ([c2] > (0))
);
GO
CREATE STATISTICS stat1
ON dbo.[FileTablePass](stream_id)
WITH SAMPLE 50 PERCENT;
GO
CREATE INDEX IX_FileTablePass_Stream_id
ON dbo.FileTablePass(stream_id);
GO
CREATE TRIGGER FileTableTrigger
ON dbo.FileTablePass
AFTER INSERT
AS RAISERROR ('Block insert', 16, 10);
GO
CREATE INDEX IX_T2_C3
ON [dbo].[t2](c3);
GO
CREATE TRIGGER reminder2
ON dbo.t2
AFTER INSERT, UPDATE, DELETE
AS
PRINT 'reminder trigger';
GO
ALTER TABLE dbo.t2
ADD CONSTRAINT FK_TO_FILETABLE FOREIGN KEY (path_locator)
REFERENCES FileTablePass (path_locator) ;
GO
exec sp_addextendedproperty 'prop_ex', 'FileTable', 'SCHEMA', 'dbo', 'TABLE', 'FileTablePass'
exec sp_addextendedproperty 'prop_ex', 'MyPk', 'SCHEMA', 'dbo', 'TABLE', 'FileTablePass', 'CONSTRAINT', 'MyPk'
exec sp_addextendedproperty 'prop_ex', 'MyStreamUQ', 'SCHEMA', 'dbo', 'TABLE', 'FileTablePass', 'CONSTRAINT', 'MyStreamUQ'
exec sp_addextendedproperty 'prop_ex', 'MyPathUQ', 'SCHEMA', 'dbo', 'TABLE', 'FileTablePass', 'CONSTRAINT', 'MyPathUQ'
GO
CREATE USER test_user WITHOUT LOGIN
GO
GRANT SELECT ON dbo.FileTablePass TO test_user
GO

View File

@@ -0,0 +1,62 @@
CREATE PROCEDURE [dbo].[Encrypted_Additional_Numbered_Procedure]
( @param1 int)
WITH ENCRYPTION
AS
SELECT 1 AS Col1
GO
CREATE PROCEDURE [dbo].[Encrypted_Additional_Numbered_Procedure];2
( @param1 int)
WITH ENCRYPTION
AS
SELECT 2 AS Col1
GO
CREATE PROCEDURE [dbo].[Encrypted_Additional_Numbered_Procedure];3
( @param1 int)
WITH ENCRYPTION
AS
SELECT 3 AS Col1
GO
CREATE PROCEDURE [dbo].[Encrypted_Additional_Numbered_Procedure];4
( @param1 int)
WITH ENCRYPTION
AS
SELECT 4 AS Col1
GO
CREATE PROCEDURE [dbo].[Additional_Numbered_Procedure]
(@param1 int)
AS
SELECT 1 AS Col1
GO
CREATE PROCEDURE [dbo].[Additional_Numbered_Procedure];2
(@param1 int)
AS
SELECT 2 AS Col1
GO
CREATE PROCEDURE [dbo].[Additional_Numbered_Procedure];3
(@param1 int)
AS
SELECT 3 AS Col1
GO
CREATE PROCEDURE [dbo].[Additional_Numbered_Procedure];4
(@param1 int)
AS
SELECT 4 AS Col1

View File

@@ -0,0 +1,275 @@
ALTER DATABASE current SET COMPATIBILITY_LEVEL=130
GO
/* Dropping previous master key in master db that could have been created from other runs */
IF ( EXISTS(SELECT name FROM sys.symmetric_keys WHERE name = '##MS_DatabaseMasterKey##')) DROP MASTER KEY
CREATE MASTER KEY ENCRYPTION BY PASSWORD= 'Password01!';
OPEN MASTER KEY DECRYPTION BY PASSWORD = 'Password01!';
CREATE DATABASE SCOPED CREDENTIAL AlterEgo WITH IDENTITY = 'RettigB',
SECRET = 'sdrlk8$40-dksli87nNN8';
GO
-- Row-Level Security
CREATE TABLE [dbo].[Sales1]
(
OrderID INT,
SalesRep SYSNAME NOT NULL,
Product VARCHAR(10),
Qty INT
);
GO
CREATE TABLE [dbo].[Sales2]
(
OrderID INT,
SalesRep SYSNAME NOT NULL,
Product VARCHAR(10),
Qty INT
);
GO
CREATE FUNCTION [dbo].[fn_securitypredicate](@SalesRep AS SYSNAME)
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN SELECT 1 AS fn_securitypredicate_result
WHERE @SalesRep = USER_NAME() OR USER_NAME() = 'Manager';
GO
CREATE SECURITY POLICY [dbo].[SalesFilter]
ADD FILTER PREDICATE [dbo].[fn_securitypredicate]([SalesRep]) ON [dbo].[Sales1],
ADD FILTER PREDICATE [dbo].[fn_securitypredicate]([SalesRep]) ON [dbo].[Sales2],
ADD BLOCK PREDICATE [dbo].[fn_securitypredicate]([SalesRep]) ON [dbo].[Sales1],
ADD BLOCK PREDICATE [dbo].[fn_securitypredicate]([SalesRep]) ON [dbo].[Sales2] AFTER UPDATE
WITH (STATE = OFF)
NOT FOR REPLICATION
GO
CREATE COLUMN MASTER KEY CMK1
WITH (
KEY_STORE_PROVIDER_NAME = 'MSSQL_CERTIFICATE_STORE',
KEY_PATH = 'Current User/Personal/f2260f28d909d21c642a3d8e0b45a830e79a1420'
);
GO
CREATE COLUMN MASTER KEY CMK2
WITH (
KEY_STORE_PROVIDER_NAME = 'MSSQL_CERTIFICATE_STORE',
KEY_PATH = 'Current User/Personal/f2260f28d909d21c642a3d8e0b45a830e79a1420'
);
GO
CREATE COLUMN ENCRYPTION KEY TwoValueCEK
WITH VALUES
(
COLUMN_MASTER_KEY = CMK1,
ALGORITHM = 'RSA_OAEP',
ENCRYPTED_VALUE = 0x016E000001630075007200720065006E00740075007300650072002F006D0079002F0037006300380061003100310033003400320037003800620037003000630038003100390062003900630039003400360061006600340039006500610030003200650038006200650038003400340065006C33A82ECF04A7185824B4545457AC5244CD9C219E64067B9520C0081B8399B58C2863F7494ABE3694BD87D55FFD7576FFDC47C28F94ECC99577DF4FB8FA19AA95764FEF889CDE0F176DA5897B74382FBB22756CE2921050A09201A0EB6AF3D6091014C30146EA62635EE8CBF0A8074DEDFF125CEA80D1C0F5E8C58750A07D270E2A8BF824EE4C0C156366BF26D38CCE49EBDD5639A2DF029A7DBAE5A5D111F2F2FA3246DF8C2FA83C1E542C10570FADA98F6B29478DC58CE5CBDD407CCEFCDB97814525F6F32BECA266014AC346AC39C4F185C6C0F0A24FEC4DFA015649624692DE7865B9827BA22C3B574C9FD169F822B609F902288C5880EB25F14BD990D871B1BC4BA3A5B237AF76D26354773FA2A25CF4511AF58C911E601CFCB1905128C997844EED056C2AE7F0B48700AB41307E470FF9520997D0EB0D887DE11AFE574FFE845B7DC6C03FEEE8D467236368FC0CB2FDBD54DADC65B10B3DE6C80DF8B7B3F8F3CE5BE914713EE7B1FA5B7A578359592B8A5FDFDDE5FF9F392BC87C3CD02FBA94582AC063BBB9FFAC803FD489E16BEB28C4E3374A8478C737236A0B232F5A9DDE4D119573F1AEAE94B2192B81575AD6F57E670C1B2AB91045124DFDAEC2898F3F0112026DFC93BF9391D667D1AD7ED7D4E6BB119BBCEF1D1ADA589DD3E1082C3DAD13223BE438EB9574DA04E9D8A06320CAC6D3EC21D5D1C2A0AA484C7C
),
(
COLUMN_MASTER_KEY = CMK2,
ALGORITHM = 'RSA_OAEP',
ENCRYPTED_VALUE = 0x016E000001630075007200720065006E00740075007300650072002F006D0079002F0064006500650063006200660034006100340031003000380034006200350033003200360066003200630062006200350030003600380065003900620061003000320030003600610037003800310066001DDA6134C3B73A90D349C8905782DD819B428162CF5B051639BA46EC69A7C8C8F81591A92C395711493B25DCBCCC57836E5B9F17A0713E840721D098F3F8E023ABCDFE2F6D8CC4339FC8F88630ED9EBADA5CA8EEAFA84164C1095B12AE161EABC1DF778C07F07D413AF1ED900F578FC00894BEE705EAC60F4A5090BBE09885D2EFE1C915F7B4C581D9CE3FDAB78ACF4829F85752E9FC985DEB8773889EE4A1945BD554724803A6F5DC0A2CD5EFE001ABED8D61E8449E4FAA9E4DD392DA8D292ECC6EB149E843E395CDE0F98D04940A28C4B05F747149B34A0BAEC04FFF3E304C84AF1FF81225E615B5F94E334378A0A888EF88F4E79F66CB377E3C21964AACB5049C08435FE84EEEF39D20A665C17E04898914A85B3DE23D56575EBC682D154F4F15C37723E04974DB370180A9A579BC84F6BC9B5E7C223E5CBEE721E57EE07EFDCC0A3257BBEBF9ADFFB00DBF7EF682EC1C4C47451438F90B4CF8DA709940F72CFDC91C6EB4E37B4ED7E2385B1FF71B28A1D2669FBEB18EA89F9D391D2FDDEA0ED362E6A591AC64EF4AE31CA8766C259ECB77D01A7F5C36B8418F91C1BEADDD4491C80F0016B66421B4B788C55127135DA2FA625FB7FD195FB40D90A6C67328602ECAF3EC4F5894BFD84A99EB4753BE0D22E0D4DE6A0ADFEDC80EB1B556749B4A8AD00E73B329C95827AB91C0256347E85E3C5FD6726D0E1FE82C925D3DF4A9
);
GO
CREATE TABLE Customers (
CustName nvarchar(60),
SSN varchar(11)
COLLATE Latin1_General_BIN2 ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = TwoValueCEK,
ENCRYPTION_TYPE = DETERMINISTIC ,
ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256'),
Age int NULL,
ACTNO varchar(11)
ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = TwoValueCEK,
ENCRYPTION_TYPE = RANDOMIZED,
ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256')
);
GO
USE [$(DatabaseName)]
GO
DBCC TRACEON(4631,-1)
GO
OPEN MASTER KEY DECRYPTION BY PASSWORD = 'Password01!';
CREATE DATABASE SCOPED CREDENTIAL cred1 WITH IDENTITY = 'test_user', SECRET = '$(Secret)';
CREATE EXTERNAL DATA SOURCE eds1
WITH (
TYPE = HADOOP,
LOCATION = '$(DataSourceLocation)',
CREDENTIAL = cred1
);
CREATE EXTERNAL DATA SOURCE eds2
WITH (
TYPE = HADOOP,
LOCATION = '$(DataSourceLocation)'
);
CREATE EXTERNAL FILE FORMAT eff1
WITH (
FORMAT_TYPE = DELIMITEDTEXT
);
CREATE EXTERNAL FILE FORMAT eff2
WITH (
FORMAT_TYPE = ORC
);
CREATE EXTERNAL FILE FORMAT eff3
WITH (
FORMAT_TYPE = PARQUET
);
CREATE EXTERNAL FILE FORMAT eff4
WITH (
FORMAT_TYPE = RCFILE,
SERDE_METHOD = 'org.apache.hadoop.hive.serde2.columnar.ColumnarSerDe'
);
CREATE EXTERNAL FILE FORMAT eff5
WITH (
FORMAT_TYPE = DELIMITEDTEXT,
FORMAT_OPTIONS (FIELD_TERMINATOR = '|', STRING_DELIMITER = ';', DATE_FORMAT = 'MM-dd-yyyy', USE_TYPE_DEFAULT = FALSE)
);
CREATE EXTERNAL FILE FORMAT eff6
WITH (
FORMAT_TYPE = DELIMITEDTEXT,
FORMAT_OPTIONS (FIELD_TERMINATOR = '|')
);
CREATE EXTERNAL FILE FORMAT eff7
WITH (
FORMAT_TYPE = DELIMITEDTEXT,
FORMAT_OPTIONS (DATE_FORMAT = 'MM-dd-yyyy', FIELD_TERMINATOR = '|')
);
CREATE EXTERNAL FILE FORMAT eff8
WITH (
FORMAT_TYPE = DELIMITEDTEXT,
FORMAT_OPTIONS (DATE_FORMAT = 'MM-dd-yyyy', FIELD_TERMINATOR = '|', STRING_DELIMITER = ';')
);
CREATE EXTERNAL FILE FORMAT eff9
WITH (
FORMAT_TYPE = DELIMITEDTEXT,
FORMAT_OPTIONS (DATE_FORMAT = 'MM-dd-yyyy', FIELD_TERMINATOR = '|', STRING_DELIMITER = ';'),
DATA_COMPRESSION = 'org.apache.hadoop.io.compress.GzipCodec'
);
CREATE EXTERNAL FILE FORMAT eff10
WITH (
FORMAT_TYPE = RCFILE,
SERDE_METHOD = 'org.apache.hadoop.hive.serde2.columnar.ColumnarSerDe',
DATA_COMPRESSION = 'org.apache.hadoop.io.compress.DefaultCodec'
);
CREATE EXTERNAL FILE FORMAT eff11
WITH (
FORMAT_TYPE = ORC,
DATA_COMPRESSION = 'org.apache.hadoop.io.compress.SnappyCodec'
);
CREATE EXTERNAL FILE FORMAT eff12
WITH (
FORMAT_TYPE = PARQUET,
DATA_COMPRESSION = 'org.apache.hadoop.io.compress.SnappyCodec'
);
CREATE EXTERNAL TABLE bands1
(
id INTEGER NOT NULL,
name VARCHAR(50) NOT NULL,
origin CHAR(3),
rate FLOAT,
experience SMALLINT
)
WITH (
LOCATION = '/bands.dat',
DATA_SOURCE = eds1,
FILE_FORMAT = eff1
);
CREATE EXTERNAL TABLE bands2
(
id INTEGER NOT NULL,
name VARCHAR(50) NOT NULL,
origin CHAR(3),
rate FLOAT,
experience SMALLINT
)
WITH (
LOCATION = '/bands.dat',
DATA_SOURCE = eds2,
FILE_FORMAT = eff1
);
CREATE EXTERNAL TABLE bands3
(
id INTEGER NOT NULL,
name VARCHAR(50) NOT NULL,
origin CHAR(3),
rate FLOAT,
experience SMALLINT
)
WITH (
LOCATION = '/bands.dat',
DATA_SOURCE = eds2,
FILE_FORMAT = eff1,
REJECT_TYPE = VALUE,
REJECT_VALUE = 0
);
CREATE EXTERNAL TABLE bands4
(
id INTEGER NOT NULL,
name VARCHAR(50) NOT NULL,
origin CHAR(3),
rate FLOAT,
experience SMALLINT
)
WITH (
LOCATION = '/bands.dat',
DATA_SOURCE = eds1,
FILE_FORMAT = eff1,
REJECT_TYPE = PERCENTAGE,
REJECT_VALUE = 30.5,
REJECT_SAMPLE_VALUE = 10
);
CREATE EXTERNAL TABLE bands5
(
id INTEGER NOT NULL,
name VARCHAR(50) NOT NULL,
origin CHAR(3),
rate FLOAT,
experience SMALLINT
)
WITH (
LOCATION = '/bands.dat',
DATA_SOURCE = eds1,
FILE_FORMAT = eff1,
REJECT_TYPE = VALUE,
REJECT_VALUE = 30
);

View File

@@ -0,0 +1,298 @@
-- create signature
ADD SIGNATURE TO [Procedure1]
BY CERTIFICATE [Certificate1]
WITH PASSWORD = 'pGFD4bb925DGvbd2439587y' ;
GO
--Create a queue to receive messages.
CREATE QUEUE NotifyQueue ;
GO
--Create a service on the queue that references
--the event notifications contract.
CREATE SERVICE NotifyService
ON QUEUE NotifyQueue
([http://schemas.microsoft.com/SQL/Notifications/PostEventNotification]);
GO
--Create the event notification on queue.
CREATE EVENT NOTIFICATION Notify_ALTER_T1
ON QUEUE notifyqueue
FOR QUEUE_ACTIVATION
TO SERVICE 'NotifyService',
'8140a771-3c4b-4479-8ac0-81008ab17984';
GO
--Create the event notification on database
CREATE EVENT NOTIFICATION Notify_ALTER_T1
ON DATABASE
FOR ALTER_TABLE
TO SERVICE 'NotifyService',
'8140a771-3c4b-4479-8ac0-81008ab17984';
GO
CREATE FUNCTION [dbo].[TableFunctionWithComputedColumns]
(
-- Add the parameters for the function here
@p1 int = 2,
@p2 nchar(10) = NUll
)
RETURNS
@Table_Var TABLE
(
-- Add the column definitions for the TABLE variable here
c1 int,
c2 nchar(10),
c3 AS 1 * 3
)
AS
BEGIN
-- Fill the table variable with the rows for your result set
INSERT INTO @Table_Var
SELECT a.column_1, a.column_2
FROM Table_1 a
WHERE a.column_1 > 5
INSERT INTO @Table_Var
SELECT column_1, 'From 2'
FROM Table_2
WHERE @p1 > column_1
RETURN
END
GO
CREATE FUNCTION [dbo].[TableFunctionWithComputedColumnsEncrypted]
(
-- Add the parameters for the function here
@p1 int = 2,
@p2 nchar(10)
)
RETURNS
@Table_Var TABLE
(
-- Add the column definitions for the TABLE variable here
c1 int,
c2 nchar(10),
c3 AS 1 * 3
)
WITH ENCRYPTION
AS
BEGIN
-- Fill the table variable with the rows for your result set
INSERT INTO @Table_Var
SELECT a.column_1, a.column_2
FROM Table_1 a
WHERE a.column_1 > 5
INSERT INTO @Table_Var
SELECT column_1, 'From 2'
FROM Table_2
WHERE @p1 > column_1
RETURN
END
GO
Create table [dbo].[referenced_table] (C1 int, C2 int);
GO
CREATE PROCEDURE GetReferenedTable
AS
BEGIN
SELECT * from [dbo].[referenced_table];
END
GO
exec sp_addextendedproperty N'microsoft_database_tools_support', 'GetReferenedTable', N'SCHEMA', 'dbo', N'PROCEDURE' ,'GetReferenedTable'
GO
DISABLE TRIGGER [Trigger_1]
ON DATABASE;
GO
CREATE VIEW [dbo].[View_2] (c1)
AS
SELECT column_1 as c1
FROM dbo.Table_1
GO
exec sp_addextendedproperty 'prop_ex', 'Table_1', 'SCHEMA', 'dbo', 'TABLE', 'Table_1'
GO
exec sp_addextendedproperty 'prop_ex', 'column_1', 'SCHEMA', 'dbo', 'TABLE', 'Table_1', 'COLUMN', 'column_1'
GO
CREATE TABLE dbo.MultipleIndexTable
( [c1] INT NOT NULL CHECK (c1 > 0),
[c2] int default 10 null,
PRIMARY KEY NONCLUSTERED (c1 ASC),
UNIQUE CLUSTERED (c1 ASC, c2 DESC)
)
GO
CREATE TRIGGER [Trigger_2]
ON DATABASE
FOR DROP_TABLE
AS
SELECT COUNT(column_1) from dbo.Table_1
RAISERROR ('You must disable Trigger "Trigger_1" to drop synonyms!',10, 1)
ROLLBACK
GO
SET ANSI_NULLS OFF
GO
SET QUOTED_IDENTIFIER OFF
GO
DISABLE TRIGGER [Trigger_1] ON DATABASE
GO
GO
CREATE TABLE dbo.Table_3
(
c1 int,
c2 int,
) ON PartitionScheme(c1)
GO
CREATE TABLE [dbo].[Different_WithAppend_Table](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Col] [char](1) NULL
) ON [PRIMARY]
GO
CREATE FUNCTION [dbo].[EncryptedFunctionWithConstraints]
(@p1 INT)
RETURNS
@GeneratedTableName TABLE (
[c0] INT NOT NULL PRIMARY KEY,
[c1] INT DEFAULT ((1)) NULL,
[c2] NCHAR (10) NULL,
[c3] INT UNIQUE ,
CHECK ([c1]>(0)))
WITH ENCRYPTION
AS
BEGIN
insert into @GeneratedTableName values (1,1, 'abc',1);
RETURN
END
GO
CREATE TABLE [[] (c1 int)
GO
CREATE TABLE []]] (c1 int)
GO
CREATE TABLE [asdf'[] (c1 int)
GO
CREATE TABLE [噂構申表5] (c1 int)
GO
-- Casing of NULL is explicit 'NUll'
CREATE PROC CasingOnDefaultValue @param1 int = NUll, @param2 nvarchar(123) = N'abc'
AS
BEGIN
select 1 as a
END
-- permissions
GO
CREATE USER nologon4 without login
GO
GRANT VIEW DEFINITION ON CasingOnDefaultValue to nologon4
GO
CREATE USER granter without login
GO
GRANT CONNECT TO granter WITH GRANT OPTION;
GO
DENY CONNECT TO nologon4 CASCADE AS granter;
GO
GRANT VIEW DEFINITION ON [噂構申表5] to nologon4
GO
GRANT VIEW DEFINITION ON [[] TO nologon4
GO
GRANT VIEW DEFINITION ON []]] TO nologon4
GO
GRANT VIEW DEFINITION ON [asdf'[] TO nologon4
GO
GRANT SELECT ON dbo.Table_1 to nologon4
GO
GRANT SELECT ON dbo.Table_2 to nologon4
GO
REVOKE SELECT ON dbo.Table_2(column_2) TO nologon4
GO
GRANT SELECT ON dbo.View_1 to nologon4
GO
GRANT SELECT ON dbo.EncryptedView(A) to nologon4
GO
GRANT EXECUTE ON dbo.Procedure1 TO nologon4
GO
GRANT EXECUTE ON dbo.CLR_SimpleResultsetProcedure TO nologon4
GO
GRANT EXECUTE ON dbo.EncryptedProcedure TO nologon4
GO
GRANT VIEW DEFINITION ON CERTIFICATE :: Certificate1 TO nologon4
GO
GRANT EXECUTE ON dbo.ScalarFunction1 TO nologon4
GO
GRANT EXECUTE ON dbo.EncryptedFunction TO nologon4
GO
GRANT SELECT ON dbo.InlineFunction_1 TO nologon4
GO
GRANT SELECT ON dbo.TableFunction1 TO nologon4
GO
GRANT SELECT ON dbo.CLRTableValueFunction TO nologon4
GO
GRANT VIEW DEFINITION ON TYPE::dbo.dataType To nologon4
GO
GRANT VIEW DEFINITION ON FULLTEXT CATALOG ::FullTextCatalog1 To nologon4
GO
GRANT VIEW DEFINITION ON XML SCHEMA COLLECTION :: dbo.XmlSchemaCollection To nologon4
GO
GRANT VIEW DEFINITION ON ASSEMBLY :: [Geometry] To nologon4
GO
GRANT VIEW DEFINITION ON TYPE:: dbo.Angle To nologon4
GO
GRANT VIEW DEFINITION ON dbo.[Concat] To nologon4
GO
GRANT VIEW DEFINITION ON dbo.Synonym_1 To nologon4
GO
GRANT VIEW DEFINITION ON SCHEMA :: Schema1 To nologon4
GO
GRANT VIEW DEFINITION ON SYMMETRIC KEY :: SymKey1 To nologon4
GO
GRANT VIEW DEFINITION ON ASYMMETRIC KEY :: AsmKey1 To nologon4
GO
GRANT VIEW DEFINITION ON dbo.Queue1 To nologon4
GO
GRANT VIEW DEFINITION ON dbo.NotifyQueue To nologon4
GO
GRANT VIEW DEFINITION ON SERVICE :: Service1 To nologon4
GO
GRANT VIEW DEFINITION ON SERVICE :: NotifyService To nologon4
GO
GRANT VIEW DEFINITION ON CONTRACT :: Contract1 To nologon4
GO
GRANT VIEW DEFINITION ON MESSAGE TYPE :: MessageType1 To nologon4
GO
GRANT VIEW DEFINITION ON ROUTE :: AutoCreatedLocal To nologon4
GO
GRANT VIEW DEFINITION ON ROUTE :: Route1 To nologon4
GO
GRANT VIEW DEFINITION ON REMOTE SERVICE BINDING :: ServiceBinding1 To nologon4
GO
GRANT SELECT ON dbo.referenced_table To nologon4
GO
GRANT SELECT ON dbo.TableFunctionWithComputedColumns To nologon4
GO
GRANT SELECT ON dbo.TableFunctionWithComputedColumnsEncrypted To nologon4
GO
GRANT SELECT ON dbo.View_2 TO nologon4
GO
GRANT SELECT ON dbo.MultipleIndexTable TO nologon4
GO
GRANT SELECT ON dbo.Table_3 TO nologon4
GO
GRANT SELECT ON dbo.Different_WithAppend_Table TO nologon4
GO
GRANT SELECT ON dbo.[EncryptedFunctionWithConstraints] TO nologon4
GO

View File

@@ -8,6 +8,7 @@ using Microsoft.SqlTools.Credentials;
using Microsoft.SqlTools.ServiceLayer.Connection;
using Microsoft.SqlTools.ServiceLayer.Connection.Contracts;
using Microsoft.SqlTools.ServiceLayer.Hosting;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer;
using Microsoft.SqlTools.ServiceLayer.QueryExecution;
using Microsoft.SqlTools.ServiceLayer.SqlContext;
using Microsoft.SqlTools.ServiceLayer.Workspace;
@@ -43,6 +44,15 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Common
{
return CredentialService.Instance;
}
}
public ObjectExplorerService ObjectExplorerService
{
get
{
var serviceProvider = ServiceHost.Instance.ServiceProvider;
return serviceProvider.GetService<ObjectExplorerService>();
}
}
public TestConnectionProfileService ConnectionProfileService

View File

@@ -6,7 +6,8 @@
"includeFiles": [
"Scripts/CreateTestDatabaseObjects.sql",
"Scripts/CreateTestDatabase.sql",
"Scripts/TestDbTableQueries.sql"
"Scripts/TestDbTableQueries.sql",
"Scripts/AdventureWorks.sql"
]
}
},

View File

@@ -0,0 +1,369 @@
//
// 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.Globalization;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.Extensibility;
using Microsoft.SqlTools.ServiceLayer.Connection;
using Microsoft.SqlTools.ServiceLayer.Connection.Contracts;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel;
using Microsoft.SqlTools.ServiceLayer.UnitTests.Utility;
using Moq;
using Xunit;
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer
{
/// <summary>
/// Tests covering basic operation of Node based classes
/// </summary>
public class NodeTests : ObjectExplorerTestBase
{
private string defaultOwnerUri = "objectexplorer://myserver";
private ServerInfo defaultServerInfo;
private ConnectionDetails defaultConnectionDetails;
private ConnectionCompleteParams defaultConnParams;
private string fakeConnectionString = "Data Source=server;Initial Catalog=database;Integrated Security=False;User Id=user";
public NodeTests()
{
defaultServerInfo = TestObjects.GetTestServerInfo();
defaultConnectionDetails = new ConnectionDetails()
{
DatabaseName = "master",
ServerName = "localhost",
UserName = "serverAdmin",
Password = "..."
};
defaultConnParams = new ConnectionCompleteParams()
{
ServerInfo = defaultServerInfo,
ConnectionSummary = defaultConnectionDetails,
OwnerUri = defaultOwnerUri
};
// TODO can all tests use the standard service provider?
ServiceProvider = ExtensionServiceProvider.CreateDefaultServiceProvider();
}
[Fact]
public void ServerNodeConstructorValidatesFields()
{
Assert.Throws<ArgumentNullException>(() => new ServerNode(null, ServiceProvider));
Assert.Throws<ArgumentNullException>(() => new ServerNode(defaultConnParams, null));
}
[Fact]
public void ServerNodeConstructorShouldSetValuesCorrectly()
{
// Given a server node with valid inputs
ServerNode node = new ServerNode(defaultConnParams, ServiceProvider);
// Then expect all fields set correctly
Assert.False(node.IsAlwaysLeaf, "Server node should never be a leaf");
Assert.Equal(defaultConnectionDetails.ServerName, node.NodeValue);
string expectedLabel = defaultConnectionDetails.ServerName + " (SQL Server " + defaultServerInfo.ServerVersion + " - "
+ defaultConnectionDetails.UserName + ")";
Assert.Equal(expectedLabel, node.Label);
Assert.Equal(NodeTypes.ServerInstance.ToString(), node.NodeType);
string[] nodePath = node.GetNodePath().Split(TreeNode.PathPartSeperator);
Assert.Equal(1, nodePath.Length);
Assert.Equal(defaultConnectionDetails.ServerName, nodePath[0]);
}
[Fact]
public void ServerNodeLabelShouldIgnoreUserNameIfEmptyOrNull()
{
// Given no username set
ConnectionSummary integratedAuthSummary = new ConnectionSummary()
{
DatabaseName = defaultConnectionDetails.DatabaseName,
ServerName = defaultConnectionDetails.ServerName,
UserName = null
};
ConnectionCompleteParams connParams = new ConnectionCompleteParams()
{
ConnectionSummary = integratedAuthSummary,
ServerInfo = defaultServerInfo,
OwnerUri = defaultOwnerUri
};
// When querying label
string label = new ServerNode(connParams, ServiceProvider).Label;
// Then only server name and version shown
string expectedLabel = defaultConnectionDetails.ServerName + " (SQL Server " + defaultServerInfo.ServerVersion + ")";
Assert.Equal(expectedLabel, label);
}
[Fact]
public void ServerNodeConstructorShouldShowDbNameForCloud()
{
defaultServerInfo.IsCloud = true;
// Given a server node for a cloud DB, with master name
ServerNode node = new ServerNode(defaultConnParams, ServiceProvider);
// Then expect label to not include db name
string expectedLabel = defaultConnectionDetails.ServerName + " (SQL Server " + defaultServerInfo.ServerVersion + " - "
+ defaultConnectionDetails.UserName + ")";
Assert.Equal(expectedLabel, node.Label);
// But given a server node for a cloud DB that's not master
defaultConnectionDetails.DatabaseName = "NotMaster";
node = new ServerNode(defaultConnParams, ServiceProvider);
// Then expect label to include db name
expectedLabel = defaultConnectionDetails.ServerName + " (SQL Server " + defaultServerInfo.ServerVersion + " - "
+ defaultConnectionDetails.UserName + ", " + defaultConnectionDetails.DatabaseName + ")";
Assert.Equal(expectedLabel, node.Label);
}
[Fact]
public void ToNodeInfoIncludeAllFields()
{
// Given a server connection
ServerNode node = new ServerNode(defaultConnParams, ServiceProvider);
// When converting to NodeInfo
NodeInfo info = node.ToNodeInfo();
// Then all fields should match
Assert.Equal(node.IsAlwaysLeaf, info.IsLeaf);
Assert.Equal(node.Label, info.Label);
Assert.Equal(node.NodeType, info.NodeType);
string[] nodePath = node.GetNodePath().Split(TreeNode.PathPartSeperator);
string[] nodeInfoPathParts = info.NodePath.Split(TreeNode.PathPartSeperator);
Assert.Equal(nodePath.Length, nodeInfoPathParts.Length);
for (int i = 0; i < nodePath.Length; i++)
{
Assert.Equal(nodePath[i], nodeInfoPathParts[i]);
}
}
[Fact]
public void AddChildShouldSetParent()
{
TreeNode parent = new TreeNode("parent");
TreeNode child = new TreeNode("child");
Assert.Null(child.Parent);
parent.AddChild(child);
Assert.Equal(parent, child.Parent);
}
[Fact]
public void GetChildrenShouldReturnReadonlyList()
{
TreeNode node = new TreeNode("parent");
IList<TreeNode> children = node.GetChildren();
Assert.Throws<NotSupportedException>(() => children.Add(new TreeNode("child")));
}
[Fact]
public void GetChildrenShouldReturnAddedNodesInOrder()
{
TreeNode parent = new TreeNode("parent");
TreeNode[] expectedKids = new TreeNode[] { new TreeNode("1"), new TreeNode("2") };
foreach (TreeNode child in expectedKids)
{
parent.AddChild(child);
}
IList<TreeNode> children = parent.GetChildren();
Assert.Equal(expectedKids.Length, children.Count);
for (int i = 0; i < expectedKids.Length; i++)
{
Assert.Equal(expectedKids[i], children[i]);
}
}
public void MultiLevelTreeShouldFormatPath()
{
TreeNode root = new TreeNode("root");
Assert.Equal("/root" , root.GetNodePath());
TreeNode level1Child1 = new TreeNode("L1C1");
TreeNode level1Child2 = new TreeNode("L1C2");
root.AddChild(level1Child1);
root.AddChild(level1Child2);
Assert.Equal("/root/L1C1" , level1Child1.GetNodePath());
Assert.Equal("/root/L1C2", level1Child2.GetNodePath());
TreeNode level2Child1 = new TreeNode("L2C2");
level1Child1.AddChild(level2Child1);
Assert.Equal("/root/L1C1/L2C2", level2Child1.GetNodePath());
}
[Fact]
public void ServerNodeContextShouldIncludeServer()
{
// given a successful Server creation
SetupAndRegisterTestConnectionService();
Server smoServer = new Server(new ServerConnection(new SqlConnection(fakeConnectionString)));
ServerNode node = SetupServerNodeWithServer(smoServer);
// When I get the context for a ServerNode
var context = node.GetContextAs<SmoQueryContext>();
// Then I expect it to contain the server I created
Assert.NotNull(context);
Assert.Equal(smoServer, context.Server);
// And the server should be the parent
Assert.Equal(smoServer, context.Parent);
Assert.Null(context.Database);
}
[Fact]
public void ServerNodeContextShouldSetErrorMessageIfSqlConnectionIsNull()
{
// given a connectionInfo with no SqlConnection to use for queries
ConnectionService connService = SetupAndRegisterTestConnectionService();
connService.OwnerToConnectionMap.Remove(defaultOwnerUri);
Server smoServer = new Server(new ServerConnection(new SqlConnection(fakeConnectionString)));
ServerNode node = SetupServerNodeWithServer(smoServer);
// When I get the context for a ServerNode
var context = node.GetContextAs<SmoQueryContext>();
// Then I expect it to be in an error state
Assert.Null(context);
Assert.Equal(
string.Format(CultureInfo.CurrentCulture, SR.ServerNodeConnectionError, defaultConnectionDetails.ServerName),
node.ErrorStateMessage);
}
[Fact]
public void ServerNodeContextShouldSetErrorMessageIfConnFailureExceptionThrown()
{
// given a connectionInfo with no SqlConnection to use for queries
SetupAndRegisterTestConnectionService();
Server smoServer = new Server(new ServerConnection(new SqlConnection(fakeConnectionString)));
string expectedMsg = "ConnFailed!";
ServerNode node = SetupServerNodeWithExceptionCreator(new ConnectionFailureException(expectedMsg));
// When I get the context for a ServerNode
var context = node.GetContextAs<SmoQueryContext>();
// Then I expect it to be in an error state
Assert.Null(context);
Assert.Equal(
string.Format(CultureInfo.CurrentCulture, SR.TreeNodeError, expectedMsg),
node.ErrorStateMessage);
}
[Fact]
public void ServerNodeContextShouldSetErrorMessageIfExceptionThrown()
{
// given a connectionInfo with no SqlConnection to use for queries
SetupAndRegisterTestConnectionService();
Server smoServer = new Server(new ServerConnection(new SqlConnection(fakeConnectionString)));
string expectedMsg = "Failed!";
ServerNode node = SetupServerNodeWithExceptionCreator(new Exception(expectedMsg));
// When I get the context for a ServerNode
var context = node.GetContextAs<SmoQueryContext>();
// Then I expect it to be in an error state
Assert.Null(context);
Assert.Equal(
string.Format(CultureInfo.CurrentCulture, SR.TreeNodeError, expectedMsg),
node.ErrorStateMessage);
}
private ConnectionService SetupAndRegisterTestConnectionService()
{
ConnectionService connService = TestObjects.GetTestConnectionService();
ConnectionInfo connectionInfo = new ConnectionInfo(TestObjects.GetTestSqlConnectionFactory(),
defaultOwnerUri, defaultConnectionDetails);
connectionInfo.AddConnection("Default", new SqlConnection());
connService.OwnerToConnectionMap.Add(defaultOwnerUri, connectionInfo);
ServiceProvider.RegisterSingleService(connService);
return connService;
}
private ServerNode SetupServerNodeWithServer(Server smoServer)
{
Mock<SmoServerCreator> creator = new Mock<SmoServerCreator>();
creator.Setup(c => c.Create(It.IsAny<SqlConnection>()))
.Returns(() => smoServer);
ServerNode node = SetupServerNodeWithCreator(creator.Object);
return node;
}
private ServerNode SetupServerNodeWithExceptionCreator(Exception ex)
{
Mock<SmoServerCreator> creator = new Mock<SmoServerCreator>();
creator.Setup(c => c.Create(It.IsAny<SqlConnection>()))
.Throws(ex);
ServerNode node = SetupServerNodeWithCreator(creator.Object);
return node;
}
private ServerNode SetupServerNodeWithCreator(SmoServerCreator creator)
{
ServerNode node = new ServerNode(defaultConnParams, ServiceProvider);
node.ServerCreator = creator;
return node;
}
[Fact]
public void ServerNodeChildrenShouldIncludeFoldersAndDatabases()
{
// Given a server with 1 database
SetupAndRegisterTestConnectionService();
ServiceProvider.RegisterSingleService(new ObjectExplorerService());
string dbName = "DB1";
Mock<NamedSmoObject> smoObjectMock = new Mock<NamedSmoObject>();
smoObjectMock.SetupGet(s => s.Name).Returns(dbName);
Mock<SqlDatabaseQuerier> querierMock = new Mock<SqlDatabaseQuerier>();
querierMock.Setup(q => q.Query(It.IsAny<SmoQueryContext>()))
.Returns(smoObjectMock.Object.SingleItemAsEnumerable());
ServiceProvider.Register<SmoQuerier>(() => new[] { querierMock.Object });
Server smoServer = new Server(new ServerConnection(new SqlConnection(fakeConnectionString)));
ServerNode node = SetupServerNodeWithServer(smoServer);
// When I populate its children
IList<TreeNode> children = node.Expand();
// Then I expect it to contain server-level folders
Assert.Equal(3, children.Count);
VerifyTreeNode<FolderNode>(children[0], "Folder", SR.SchemaHierarchy_Databases);
VerifyTreeNode<FolderNode>(children[1], "Folder", SR.SchemaHierarchy_Security);
VerifyTreeNode<FolderNode>(children[2], "Folder", SR.SchemaHierarchy_ServerObjects);
// And the database is contained under it
TreeNode databases = children[0];
IList<TreeNode> dbChildren = databases.Expand();
Assert.Equal(2, dbChildren.Count);
Assert.Equal("System Databases", dbChildren[0].NodeValue);
TreeNode dbNode = dbChildren[1];
Assert.Equal(dbName, dbNode.NodeValue);
Assert.Equal(dbName, dbNode.Label);
Assert.False(dbNode.IsAlwaysLeaf);
// Note: would like to verify Database in the context, but cannot since it's a Sealed class and isn't easily mockable
}
private void VerifyTreeNode<T>(TreeNode node, string nodeType, string folderValue)
where T : TreeNode
{
T nodeAsT = node as T;
Assert.NotNull(nodeAsT);
Assert.Equal(nodeType, nodeAsT.NodeType);
Assert.Equal(folderValue, nodeAsT.NodeValue);
}
}
}

View File

@@ -0,0 +1,151 @@
//
// 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.Connection;
using Microsoft.SqlTools.ServiceLayer.Connection.Contracts;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
using Microsoft.SqlTools.ServiceLayer.Test.Common;
using Microsoft.SqlTools.ServiceLayer.UnitTests.Utility;
using Moq;
using Xunit;
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer
{
public class ObjectExplorerServiceTests : ObjectExplorerTestBase
{
private ObjectExplorerService service;
private Mock<ConnectionService> connectionServiceMock;
private Mock<IProtocolEndpoint> serviceHostMock;
public ObjectExplorerServiceTests()
{
connectionServiceMock = new Mock<ConnectionService>();
serviceHostMock = new Mock<IProtocolEndpoint>();
service = CreateOEService(connectionServiceMock.Object);
service.InitializeService(serviceHostMock.Object);
}
[Fact]
public async Task CreateSessionRequestErrorsIfConnectionDetailsIsNull()
{
object errorResponse = null;
var contextMock = RequestContextMocks.Create<CreateSessionResponse>(null)
.AddErrorHandling((errorMessage, errorCode, obj) => errorResponse = errorMessage);
await service.HandleCreateSessionRequest(null, contextMock.Object);
VerifyErrorSent(contextMock);
Assert.True(((string)errorResponse).Contains("ArgumentNullException"));
}
[Fact]
public async Task CreateSessionRequestReturnsFalseOnConnectionFailure()
{
// Given the connection service fails to connect
ConnectionDetails details = TestObjects.GetTestConnectionDetails();
ConnectionCompleteParams completeParams = null;
serviceHostMock.AddEventHandling(ConnectionCompleteNotification.Type, (et, p) => completeParams = p);
string expectedExceptionText = "Error!!!";
connectionServiceMock.Setup(c => c.Connect(It.IsAny<ConnectParams>()))
.Throws(new Exception(expectedExceptionText));
// when creating a new session
// then expect the create session request to return false
await RunAndVerify<CreateSessionResponse>(
test: (requestContext) => service.HandleCreateSessionRequest(details, requestContext),
verify: (actual =>
{
Assert.False(actual.Success);
Assert.Null(actual.SessionId);
Assert.Null(actual.RootNode);
}));
// And expect error notification to be sent
serviceHostMock.Verify(x => x.SendEvent(ConnectionCompleteNotification.Type, It.IsAny<ConnectionCompleteParams>()), Times.Once());
Assert.NotNull(completeParams);
Assert.True(completeParams.Messages.Contains(expectedExceptionText));
}
[Fact]
public async Task CreateSessionRequestReturnsSuccessAndNodeInfo()
{
// Given the connection service fails to connect
ConnectionDetails details = TestObjects.GetTestConnectionDetails();
serviceHostMock.AddEventHandling(ConnectionCompleteNotification.Type, null);
connectionServiceMock.Setup(c => c.Connect(It.IsAny<ConnectParams>()))
.Returns((ConnectParams connectParams) => Task.FromResult(GetCompleteParamsForConnection(connectParams.OwnerUri, details)));
// when creating a new session
// then expect the create session request to return false
await RunAndVerify<CreateSessionResponse>(
test: (requestContext) => service.HandleCreateSessionRequest(details, requestContext),
verify: (actual =>
{
Assert.True(actual.Success);
Assert.NotNull(actual.SessionId);
VerifyServerNode(actual.RootNode, details);
}));
// And expect no error notification to be sent
serviceHostMock.Verify(x => x.SendEvent(ConnectionCompleteNotification.Type,
It.IsAny<ConnectionCompleteParams>()), Times.Never());
}
private void VerifyServerNode(NodeInfo serverNode, ConnectionDetails details)
{
Assert.NotNull(serverNode);
Assert.Equal(NodeTypes.ServerInstance.ToString(), serverNode.NodeType);
string[] pathParts = serverNode.NodePath.Split(TreeNode.PathPartSeperator);
Assert.Equal(1, pathParts.Length);
Assert.Equal(details.ServerName, pathParts[0]);
Assert.True(serverNode.Label.Contains(details.ServerName));
Assert.False(serverNode.IsLeaf);
}
private static ConnectionCompleteParams GetCompleteParamsForConnection(string uri, ConnectionDetails details)
{
return new ConnectionCompleteParams()
{
OwnerUri = uri,
ConnectionSummary = new ConnectionSummary()
{
ServerName = details.ServerName,
DatabaseName = details.DatabaseName,
UserName = details.UserName
},
ServerInfo = TestObjects.GetTestServerInfo()
};
}
private async Task RunAndVerify<T>(Func<RequestContext<T>, Task> test, Action<T> verify)
{
T result = default(T);
var contextMock = RequestContextMocks.Create<T>(r => result = r).AddErrorHandling(null);
await test(contextMock.Object);
VerifyResult(contextMock, verify, result);
}
private void VerifyResult<T>(Mock<RequestContext<T>> contextMock, Action<T> verify, T actual)
{
contextMock.Verify(c => c.SendResult(It.IsAny<T>()), Times.Once);
contextMock.Verify(c => c.SendError(It.IsAny<string>(), It.IsAny<int>(), It.IsAny<object>()), Times.Never);
verify(actual);
}
private void VerifyErrorSent<T>(Mock<RequestContext<T>> contextMock)
{
contextMock.Verify(c => c.SendResult(It.IsAny<T>()), Times.Never);
contextMock.Verify(c => c.SendError(It.IsAny<string>(), It.IsAny<int>(), It.IsAny<object>()), Times.Once);
}
}
}

View File

@@ -0,0 +1,45 @@
//
// 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.Extensibility;
using Microsoft.SqlTools.ServiceLayer.Connection;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer;
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer
{
// Base class providing common test functionality for OE tests
public abstract class ObjectExplorerTestBase
{
protected RegisteredServiceProvider ServiceProvider
{
get;
set;
}
protected RegisteredServiceProvider CreateServiceProviderWithMinServices()
{
return CreateProvider()
.RegisterSingleService(new ConnectionService())
.RegisterSingleService(new ObjectExplorerService());
}
protected RegisteredServiceProvider CreateProvider()
{
ServiceProvider = new RegisteredServiceProvider();
return ServiceProvider;
}
protected ObjectExplorerService CreateOEService(ConnectionService connService)
{
CreateProvider()
.RegisterSingleService(connService)
.RegisterSingleService(new ObjectExplorerService());
// Create the service using the service provider, which will initialize dependencies
return ServiceProvider.GetService<ObjectExplorerService>();
}
}
}

View File

@@ -0,0 +1,65 @@
//
// 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.Linq;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.Extensibility;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel;
using Xunit;
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer
{
public class SmoQueryModelTests
{
[Fact]
public void ShouldFindDatabaseQuerierFromRealPath()
{
// Given the extension type loader is set to find SmoCollectionQuerier objects
IMultiServiceProvider serviceProvider = ExtensionServiceProvider.CreateDefaultServiceProvider();
// When I request a database compatible querier
SmoQuerier querier = serviceProvider.GetService<SmoQuerier>(q => q.SupportedObjectTypes.Contains(typeof(Database)));
// Then I expect to get back the SqlDatabaseQuerier
Assert.NotNull(querier);
Assert.Equal(typeof(SqlDatabaseQuerier), querier.GetType());
// And I expect the service provider to have been set by the extension code
Assert.NotNull(querier.ServiceProvider);
}
[Fact]
public void ShouldFindQuerierIfInExtensionList()
{
VerifyQuerierLookup(typeof(Table), typeof(SqlTableQuerier), expectExists: true);
}
[Fact]
public void ShouldNotFindQuerierIfNotInExtensionList()
{
VerifyQuerierLookup(typeof(Database), null, expectExists: false);
}
private static void VerifyQuerierLookup(Type smoType, Type querierType, bool expectExists)
{
ExtensionServiceProvider serviceProvider = ExtensionServiceProvider.Create(new Type[] {
typeof(SqlTableQuerier),
typeof(SqlLinkedServerQuerier)
});
SmoQuerier querier = serviceProvider.GetService<SmoQuerier>(q => q.SupportedObjectTypes.Contains(smoType));
if (expectExists)
{
Assert.NotNull(querier);
Assert.Equal(querierType, querier.GetType());
Assert.NotNull(querier.ServiceProvider);
}
else
{
Assert.Null(querier);
}
}
}
}

View File

@@ -43,6 +43,169 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ServiceHost
var queryServiceErrorFormat = SR.QueryServiceErrorFormat(1, 1, 1, 1, "\n", "..");
var queryServiceQueryFailed = SR.QueryServiceQueryFailed("..");
var workspaceServiceBufferPositionOutOfOrder = SR.WorkspaceServiceBufferPositionOutOfOrder(1, 2, 3, 4);
var treeNodeError = SR.TreeNodeError;
var serverNodeConnectionError = SR.ServerNodeConnectionError;
var schemaHierarchyAggregates = SR.SchemaHierarchy_Aggregates;
var SchemaHierarchy_ServerRoles = SR.SchemaHierarchy_ServerRoles;
var SchemaHierarchy_ApplicationRoles = SR.SchemaHierarchy_ApplicationRoles;
var SchemaHierarchy_Assemblies = SR.SchemaHierarchy_Assemblies;
var SchemaHierarchy_AssemblyFiles = SR.SchemaHierarchy_AssemblyFiles;
var SchemaHierarchy_AsymmetricKeys = SR.SchemaHierarchy_AsymmetricKeys;
var SchemaHierarchy_DatabaseAsymmetricKeys = SR.SchemaHierarchy_DatabaseAsymmetricKeys;
var SchemaHierarchy_DataCompressionOptions = SR.SchemaHierarchy_DataCompressionOptions;
var SchemaHierarchy_Certificates = SR.SchemaHierarchy_Certificates;
var SchemaHierarchy_FileTables = SR.SchemaHierarchy_FileTables;
var SchemaHierarchy_DatabaseCertificates = SR.SchemaHierarchy_DatabaseCertificates;
var SchemaHierarchy_CheckConstraints = SR.SchemaHierarchy_CheckConstraints;
var SchemaHierarchy_Columns = SR.SchemaHierarchy_Columns;
var SchemaHierarchy_Constraints = SR.SchemaHierarchy_Constraints;
var SchemaHierarchy_Contracts = SR.SchemaHierarchy_Contracts;
var SchemaHierarchy_Credentials = SR.SchemaHierarchy_Credentials;
var SchemaHierarchy_ErrorMessages = SR.SchemaHierarchy_ErrorMessages;
var SchemaHierarchy_ServerRoleMembership = SR.SchemaHierarchy_ServerRoleMembership;
var SchemaHierarchy_DatabaseOptions = SR.SchemaHierarchy_DatabaseOptions;
var SchemaHierarchy_DatabaseRoles = SR.SchemaHierarchy_DatabaseRoles;
var SchemaHierarchy_RoleMemberships = SR.SchemaHierarchy_RoleMemberships;
var SchemaHierarchy_DatabaseTriggers = SR.SchemaHierarchy_DatabaseTriggers;
var SchemaHierarchy_DefaultConstraints = SR.SchemaHierarchy_DefaultConstraints;
var SchemaHierarchy_Defaults = SR.SchemaHierarchy_Defaults;
var SchemaHierarchy_Sequences = SR.SchemaHierarchy_Sequences;
var SchemaHierarchy_Endpoints = SR.SchemaHierarchy_Endpoints;
var SchemaHierarchy_EventNotifications = SR.SchemaHierarchy_EventNotifications;
var SchemaHierarchy_ServerEventNotifications = SR.SchemaHierarchy_ServerEventNotifications;
var SchemaHierarchy_ExtendedProperties = SR.SchemaHierarchy_ExtendedProperties;
var SchemaHierarchy_FileGroups = SR.SchemaHierarchy_FileGroups;
var SchemaHierarchy_ForeignKeys = SR.SchemaHierarchy_ForeignKeys;
var SchemaHierarchy_FullTextCatalogs = SR.SchemaHierarchy_FullTextCatalogs;
var SchemaHierarchy_FullTextIndexes = SR.SchemaHierarchy_FullTextIndexes;
var SchemaHierarchy_Functions = SR.SchemaHierarchy_Functions;
var SchemaHierarchy_Indexes = SR.SchemaHierarchy_Indexes;
var SchemaHierarchy_InlineFunctions = SR.SchemaHierarchy_InlineFunctions;
var SchemaHierarchy_Keys = SR.SchemaHierarchy_Keys;
var SchemaHierarchy_LinkedServers = SR.SchemaHierarchy_LinkedServers;
var SchemaHierarchy_LinkedServerLogins = SR.SchemaHierarchy_LinkedServerLogins;
var SchemaHierarchy_Logins = SR.SchemaHierarchy_Logins;
var SchemaHierarchy_MasterKey = SR.SchemaHierarchy_MasterKey;
var SchemaHierarchy_MasterKeys = SR.SchemaHierarchy_MasterKeys;
var SchemaHierarchy_MessageTypes = SR.SchemaHierarchy_MessageTypes;
var SchemaHierarchy_MultiSelectFunctions = SR.SchemaHierarchy_MultiSelectFunctions;
var SchemaHierarchy_Parameters = SR.SchemaHierarchy_Parameters;
var SchemaHierarchy_PartitionFunctions = SR.SchemaHierarchy_PartitionFunctions;
var SchemaHierarchy_PartitionSchemes = SR.SchemaHierarchy_PartitionSchemes;
var SchemaHierarchy_Permissions = SR.SchemaHierarchy_Permissions;
var SchemaHierarchy_PrimaryKeys = SR.SchemaHierarchy_PrimaryKeys;
var schemaHierarchyPrimaryKeys = SR.SchemaHierarchy_PrimaryKeys;
var schemaHierarchyProgrammability = SR.SchemaHierarchy_Programmability;
var schemaHierarchyQueues = SR.SchemaHierarchy_Queues;
var schemaHierarchyRemoteServiceBindings = SR.SchemaHierarchy_RemoteServiceBindings;
var schemaHierarchyReturnedColumns = SR.SchemaHierarchy_ReturnedColumns;
var schemaHierarchyRoles = SR.SchemaHierarchy_Roles;
var schemaHierarchyRoutes = SR.SchemaHierarchy_Routes;
var schemaHierarchyRules = SR.SchemaHierarchy_Rules;
var schemaHierarchySchemas = SR.SchemaHierarchy_Schemas;
var schemaHierarchySecurity = SR.SchemaHierarchy_Security;
var schemaHierarchyServerObjects = SR.SchemaHierarchy_ServerObjects;
var schemaHierarchyManagement = SR.SchemaHierarchy_Management;
var schemaHierarchyServerTriggers = SR.SchemaHierarchy_ServerTriggers;
var schemaHierarchyServiceBroker = SR.SchemaHierarchy_ServiceBroker;
var schemaHierarchyServices = SR.SchemaHierarchy_Services;
var schemaHierarchySignatures = SR.SchemaHierarchy_LogFiles;
var schemaHierarchyStatistics = SR.SchemaHierarchy_Statistics;
var schemaHierarchyStorage = SR.SchemaHierarchy_Storage;
var schemaHierarchyStoredProcedures = SR.SchemaHierarchy_StoredProcedures;
var schemaHierarchySymmetricKeys = SR.SchemaHierarchy_SymmetricKeys;
var schemaHierarchySynonyms = SR.SchemaHierarchy_Synonyms;
var schemaHierarchyTables = SR.SchemaHierarchy_Tables;
var schemaHierarchyTriggers = SR.SchemaHierarchy_Triggers;
var schemaHierarchyTypes = SR.SchemaHierarchy_Types;
var schemaHierarchyUniqueKeys = SR.SchemaHierarchy_UniqueKeys;
var schemaHierarchyUserDefinedDataTypes = SR.SchemaHierarchy_UserDefinedDataTypes;
var schemaHierarchyUserDefinedTypes = SR.SchemaHierarchy_UserDefinedTypes;
var schemaHierarchyUsers = SR.SchemaHierarchy_Users;
var schemaHierarchyViews = SR.SchemaHierarchy_Views;
var schemaHierarchyXmlIndexes = SR.SchemaHierarchy_XmlIndexes;
var schemaHierarchyXMLSchemaCollections = SR.SchemaHierarchy_XMLSchemaCollections;
var schemaHierarchyUserDefinedTableTypes = SR.SchemaHierarchy_UserDefinedTableTypes;
var schemaHierarchyFilegroupFiles = SR.SchemaHierarchy_FilegroupFiles;
var missingCaption = SR.MissingCaption;
var schemaHierarchyBrokerPriorities = SR.SchemaHierarchy_BrokerPriorities;
var schemaHierarchyCryptographicProviders = SR.SchemaHierarchy_CryptographicProviders;
var schemaHierarchyDatabaseAuditSpecifications = SR.SchemaHierarchy_DatabaseAuditSpecifications;
var schemaHierarchyDatabaseEncryptionKeys = SR.SchemaHierarchy_DatabaseEncryptionKeys;
var schemaHierarchyEventSessions = SR.SchemaHierarchy_EventSessions;
var schemaHierarchyFullTextStopLists = SR.SchemaHierarchy_FullTextStopLists;
var schemaHierarchyResourcePools = SR.SchemaHierarchy_ResourcePools;
var schemaHierarchyServerAudits = SR.SchemaHierarchy_ServerAudits;
var schemaHierarchyServerAuditSpecifications = SR.SchemaHierarchy_ServerAuditSpecifications;
var schemaHierarchySpatialIndexes = SR.SchemaHierarchy_SpatialIndexes;
var schemaHierarchyWorkloadGroups = SR.SchemaHierarchy_WorkloadGroups;
var schemaHierarchySqlFiles = SR.SchemaHierarchy_SqlFiles;
var schemaHierarchyServerFunctions = SR.SchemaHierarchy_ServerFunctions;
var schemaHierarchySqlType = SR.SchemaHierarchy_SqlType;
var schemaHierarchyServerOptions = SR.SchemaHierarchy_ServerOptions;
var schemaHierarchyDatabaseDiagrams = SR.SchemaHierarchy_DatabaseDiagrams;
var schemaHierarchySystemTables = SR.SchemaHierarchy_SystemTables;
var schemaHierarchyDatabases = SR.SchemaHierarchy_Databases;
var schemaHierarchySystemContracts = SR.SchemaHierarchy_SystemContracts;
var schemaHierarchySystemDatabases = SR.SchemaHierarchy_SystemDatabases;
var schemaHierarchySystemMessageTypes = SR.SchemaHierarchy_SystemMessageTypes;
var schemaHierarchySystemQueues = SR.SchemaHierarchy_SystemQueues;
var schemaHierarchySystemServices = SR.SchemaHierarchy_SystemServices;
var schemaHierarchySystemStoredProcedures = SR.SchemaHierarchy_SystemStoredProcedures;
var schemaHierarchySystemViews = SR.SchemaHierarchy_SystemViews;
var schemaHierarchyDataTierApplications = SR.SchemaHierarchy_DataTierApplications;
var schemaHierarchyExtendedStoredProcedures = SR.SchemaHierarchy_ExtendedStoredProcedures;
var schemaHierarchySystemAggregateFunctions = SR.SchemaHierarchy_SystemAggregateFunctions;
var schemaHierarchySystemApproximateNumerics = SR.SchemaHierarchy_SystemApproximateNumerics;
var schemaHierarchySystemBinaryStrings = SR.SchemaHierarchy_SystemBinaryStrings;
var schemaHierarchySystemCharacterStrings = SR.SchemaHierarchy_SystemCharacterStrings;
var schemaHierarchySystemCLRDataTypes = SR.SchemaHierarchy_SystemCLRDataTypes;
var schemaHierarchySystemConfigurationFunctions = SR.SchemaHierarchy_SystemConfigurationFunctions;
var schemaHierarchySystemCursorFunctions = SR.SchemaHierarchy_SystemCursorFunctions;
var schemaHierarchySystemDataTypes = SR.SchemaHierarchy_SystemDataTypes;
var schemaHierarchySystemDateAndTime = SR.SchemaHierarchy_SystemDateAndTime;
var schemaHierarchySystemDateAndTimeFunctions = SR.SchemaHierarchy_SystemDateAndTimeFunctions;
var schemaHierarchySystemExactNumerics = SR.SchemaHierarchy_SystemExactNumerics;
var schemaHierarchySystemFunctions = SR.SchemaHierarchy_SystemFunctions;
var schemaHierarchySystemHierarchyIdFunctions = SR.SchemaHierarchy_SystemHierarchyIdFunctions;
var schemaHierarchySystemMathematicalFunctions = SR.SchemaHierarchy_SystemMathematicalFunctions;
var schemaHierarchySystemMetadataFunctionions = SR.SchemaHierarchy_SystemMetadataFunctions;
var schemaHierarchySystemOtherDataTypes = SR.SchemaHierarchy_SystemOtherDataTypes;
var schemaHierarchySystemOtherFunctions = SR.SchemaHierarchy_SystemOtherFunctions;
var schemaHierarchySystemRowsetFunctions = SR.SchemaHierarchy_SystemRowsetFunctions;
var schemaHierarchySystemSecurityFunctions = SR.SchemaHierarchy_SystemSecurityFunctions;
var schemaHierarchySystemSpatialDataTypes = SR.SchemaHierarchy_SystemSpatialDataTypes;
var schemaHierarchySystemStringFunctions = SR.SchemaHierarchy_SystemStringFunctions;
var schemaHierarchySystemSystemStatisticalFunctions = SR.SchemaHierarchy_SystemSystemStatisticalFunctions;
var schemaHierarchySystemTextAndImageFunctions = SR.SchemaHierarchy_SystemTextAndImageFunctions;
var schemaHierarchySystemUnicodeCharacterStrings = SR.SchemaHierarchy_SystemUnicodeCharacterStrings;
var schemaHierarchyAggregateFunctions = SR.SchemaHierarchy_AggregateFunctions;
var schemaHierarchyScalarValuedFunctions = SR.SchemaHierarchy_ScalarValuedFunctions;
var schemaHierarchyTableValuedFunctions = SR.SchemaHierarchy_TableValuedFunctions;
var schemaHierarchySystemExtendedStoredProcedures = SR.SchemaHierarchy_SystemExtendedStoredProcedures;
var schemaHierarchyBuiltInType = SR.SchemaHierarchy_BuiltInType;
var schemaHierarchyBuiltInServerRole = SR.SchemaHierarchy_BuiltInServerRole;
var schemaHierarchyUserWithPassword = SR.SchemaHierarchy_UserWithPassword;
var schemaHierarchySearchPropertyList = SR.SchemaHierarchy_SearchPropertyList;
var schemaHierarchySecurityPolicies = SR.SchemaHierarchy_SecurityPolicies;
var schemaHierarchySecurityPredicates = SR.SchemaHierarchy_SecurityPredicates;
var schemaHierarchyServerRole = SR.SchemaHierarchy_ServerRole;
var schemaHierarchySearchPropertyLists = SR.SchemaHierarchy_SearchPropertyLists;
var schemaHierarchyColumnStoreIndexes = SR.SchemaHierarchy_ColumnStoreIndexes;
var schemaHierarchyTableTypeIndexes = SR.SchemaHierarchy_TableTypeIndexes;
var schemaHierarchyServerInstance = SR.SchemaHierarchy_ServerInstance;
var schemaHierarchySelectiveXmlIndexes = SR.SchemaHierarchy_SelectiveXmlIndexes;
var schemaHierarchyXmlNamespaces = SR.SchemaHierarchy_XmlNamespaces;
var schemaHierarchyXmlTypedPromotedPaths = SR.SchemaHierarchy_XmlTypedPromotedPaths;
var schemaHierarchySqlTypedPromotedPaths = SR.SchemaHierarchy_SqlTypedPromotedPaths;
var schemaHierarchyDatabaseScopedCredentials = SR.SchemaHierarchy_DatabaseScopedCredentials;
var schemaHierarchyExternalDataSources = SR.SchemaHierarchy_ExternalDataSources;
var schemaHierarchyExternalFileFormats = SR.SchemaHierarchy_ExternalFileFormats;
var schemaHierarchyExternalResources = SR.SchemaHierarchy_ExternalResources;
var schemaHierarchyExternalTables = SR.SchemaHierarchy_ExternalTables;
var schemaHierarchyAlwaysEncryptedKeys = SR.SchemaHierarchy_AlwaysEncryptedKeys;
var schemaHierarchyColumnMasterKeys = SR.SchemaHierarchy_ColumnMasterKeys;
var schemaHierarchyColumnEncryptionKeys = SR.SchemaHierarchy_ColumnEncryptionKeys;
}
[Fact]

View File

@@ -0,0 +1,33 @@
//
// 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.Hosting.Protocol.Contracts;
using Moq;
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Utility
{
public static class ProtocolEndpointMocks
{
public static Mock<IProtocolEndpoint> AddEventHandling<TParams>(
this Mock<IProtocolEndpoint> mock,
EventType<TParams> expectedEvent,
Action<EventType<TParams>, TParams> eventCallback)
{
var flow = mock.Setup(h => h.SendEvent(
It.Is<EventType<TParams>>(m => m == expectedEvent),
It.IsAny<TParams>()))
.Returns(Task.FromResult(0));
if (eventCallback != null)
{
flow.Callback(eventCallback);
}
return mock;
}
}
}

View File

@@ -53,6 +53,30 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Utility
};
}
public static ServerInfo GetTestServerInfo()
{
return new ServerInfo()
{
ServerVersion = "14.0.1.0",
ServerMajorVersion = 14,
ServerMinorVersion = 0,
EngineEditionId = 3,
OsVersion = "Linux (Ubuntu 15.10)",
IsCloud = false,
ServerEdition = "Developer Edition",
ServerLevel = ""
};
}
/// <summary>
/// Creates a test sql connection factory instance
/// </summary>
public static ISqlConnectionFactory GetTestSqlConnectionFactory()
{
// use mock database connection
return new TestSqlConnectionFactory();
}
/// <summary>
/// Creates a test connection details object
/// </summary>