tags:

views:

31

answers:

2

I am trying to write a classifier function for the SQL 2008 resource governor. I would like to use a user created database role to identify if the user should go into a particular work load group. The logins in question are SQL logins. I can not use IS_MEMBER(), because IS_MEMBER restricts itself to the current database context (in this case, master). I can't use [user database].sys.database_principals because the classifier function must be schema bound (thus restricting lookups to the current database context). Furthermore, any views referenced by the function must also be schema bound, meaning that I can't create a view in master to reference the user database's security views.

The goal here is to be able to basically execute IS_MEMBER() from master to check a role in another database.

A: 

MSDN says:

The following system functions can be used for classification: HOST_NAME(), 
APP_NAME(), SUSER_NAME(), SUSER_SNAME(), IS_SRVROLEMEMBER(), and IS_MEMBER().

That would suggest the governor function is executed in the default database of the end user, and you can use IS_MEMBER there.

If not, I guess you can join together some system views to check if the current user is in a role. System views allow you to specify a three part name, like TestDb.sys.database_principals:

select  *
from    master.sys.login_token l
join    TestDB.sys.database_principals m
on      l.sid = m.sid
join    TestDB.sys.database_role_members rm
on      rm.member_principal_id = m.principal_id
join    TestDB.sys.database_principals r
on      rm.role_principal_id = r.principal_id
where   r.name = 'testrole' -- Role Name
        and l.name = SUSER_NAME() -- User Name

This sounds rather complex and insecure, so I hope there is a better answer :)

Andomar
Sorry, can't use the ____.sys.database_principals and other views, as stated in my question. The function must be schema bound, so you can't use 3 part naming. Testing shows that the IS_MEMBER is not executed in the context of the default database, but in the master. So IS_MEMBER does not work.
Sake God
+2  A: 

You can create a DDL trigger in your database that updates a table in master so that you have all of the user/group information there as well. You can then query against that. You would probably want to attach the trigger to ADD_ROLE_MEMBER and DROP_ROLE_MEMBER at the very least.

I'm just starting to work with the Resource Governor, so if I run across a "cleaner" way of doing it, I'll post here again.

Tom H.
Ooo, I love this solution. To explain it in a little more detail, Tom's saying that you would maintain a user table in master with your list of databases, roles, and users. Ideally, SQL Server would maintain this table for you with DDL triggers, but I don't know if you can set DDL triggers on some of the related system tables that you'd want. May have to update the list manually. Then have your Resource Governor classifier function query that table to get the right resource pool. Brilliant.
Brent Ozar
This might be the best solution, although you end up duplicating info between master and the user db and it sounds like an administrative headache. Not sure that I would approach it by creating triggers, since I would be concern that any triggers I put on system sprocs/tables could easily be overwritten by a patch. My approach would be to build a stored procedure in the master to live with the table and scan the sys.database_principals of the user databases and manage the lookup table. It might even be possible to call this synchronization sproc from within the classifier function itself.
Sake God
A function can't have any effect on an object outside of the function itself, so it wouldn't be possible to fill a permanent table that way. I think that if you tried to fill a temporary table within the function then you would have a problem with the fact that the function must be schema bound. That's going to cause problems with going across databases.
Tom H.
Well, after some testing, a schema bound function can not contain an EXECUTE statement (for a populating stored procedure), so in order to make this work you will need a separate process to populate your table in master. Hopefully this sort of functionality will be supported by Microsoft more gracefully in the future. Thanks Tom.
Sake God