Quantcast
Viewing all articles
Browse latest Browse all 10

Assembly and Assembly Module Metadata

So, let's look at assembly, or CLR, objects. There are four principal types of CLR object - Aggregate Functions, Stored Procedures, Table Functions and Scalar Functions. Of course, there are also Assembly Types - but these were covered previously in the post on types, and are not objects, as such.

Assembly modules, as they are called, are all covered by one metadata view - [sys].[assembly_modules]. Let's look at what we get:

object_idThis is the object_id of the object to which the assembly module relates.
assembly_idThis is the ID of the assembly in [sys].[assemblies] that contains the class and, if applicable, method that defines the assembly module.
assembly_classThis is the name of the class that contains the method that defines the module, or the name of the class that implements the module in the case of aggregate functions.
assembly_methodThis is the name of the method within the class that implements the module (NULL for aggregate functions). Note that the method must be marked with an attribute which specifies that the method is a SQL method - these attributes are called SqlFunctionAttribute, SqlProcedureAttribute and SqlTriggerAttribute for functions, procedures and triggers respectively.
null_on_null_inputThis is 1 if the module was declared to produce NULL on any NULL input, by specifying WITH RETURNS NULL ON NULL INPUT. Note that this only applies to functions.
execute_as_principal_idThis is the ID of the database principal specified in the WITH EXECUTE AS clause. If there is no WITH EXECUTE AS clause, then this will be NULL. Explicitly specifying WITH EXECUTE AS CALLER will also result in this column being NULL. Specifying EXECUTE AS OWNER will result in the value being -2. For EXECUTE AS [database_principal_name] or EXECUTE AS SELF, this will be the ID of the relevant database principal in [sys].[database_principals].

So, we get a bit of information there. Certainly enough to re-create the modules, given the source assemblies. However, as virtually all of the 'juicy stuff' is defined within the assembly itself, there's not much to look at.

Let's look at what we're told about the assemblies themselves then, by the metadata view [sys].[assemblies]:

nameThis is the name of the assembly within the database, which is not necessarily the same as the assembly's natural CLR name.
principal_idThis is the ID of the database principal in [sys].[database_principals] that owns the assembly.
assembly_idThis is the ID of the assembly within the database.
clr_nameThis is the fully qualified, version-number-and-all version of the assembly name. This name uniquely identifies not only the assembly, but also the version of the assembly.
permission_setThis is the permission set that the assembly has - 1 for SAFE, 2 for EXTERNAL_ACCESS and 3 for UNSAFE. Permission sets are reasonably complex - and would warrant a post on their own. Basically speaking, however, the SAFE permission set restricts what the assembly can do, as well as limiting it's access to resources within the SQL Server instance. The EXTERNAL_ACCESS permission set still restricts what the assembly can do, but allows it access to resources outside of SQL Server (for example, the event log). Access to external resources is usually performed via the SQL Server service account. The UNSAFE permission set does not restrict what the assembly can do at all, and you have to be very careful when writing UNSAFE. Under this permission set you can do things like start threads, etc.
permission_set_descThis is the description that relates to the value in the permission_set column.
is_visibleThis is 1 if the assembly is 'visible' - i.e. it can be used to create assembly modules. An assembly that is not visible is only used by other assemblies in the database (containing common core functionality, for example).
create_dateThis is the date on which the assembly was created in the database.
modify_dateThis is the date on which the assembly was last modified using ALTER ASSEMBLY.
is_user_definedThis is 1 if the assembly is a user assembly. System assemblies are those that ship with the system (for example Microsoft.SqlServer.Types which defines the geometry, geography and hierarchyid data types).

That tells us quite a lot about the assemblies present in the database, but doesn't actually give us any idea of what the actual assembly DLL would contain, binary-wise. Enter [sys].[assembly_files]:

assembly_idThis is the ID of the assembly in [sys].[assemblies] to which the file belongs.
nameThis is the name of the assembly file. For the main assembly DLL file, this will be the name of the assembly.
file_idThis is the ID of the file within the assembly. ID 1 is always the assembly DLL, i.e. the content of the file as it would be on-disk. Other files can often be present when deploying from Visual Studio, which will include the source files as well as the assembly config files.
contentThis is the varbinary(MAX) content of the file - again, exactly as it would appear on disk.

That's better, that gives us the ability to actually re-create the DLL on-disk. SQL Everywhere, our SQL Server IDE, routinely uses the information contained in [sys].[assembly_files] to re-create the assembly on disk, and inspect it using reflection in order to provide intellisense for assembly classes, methods and type methods.

Next time, we'll be looking at some of the metadata available that gives us information about database principals, server principals and roles.


Viewing all articles
Browse latest Browse all 10

Trending Articles