Colm Ryan


The problem we are having is that we are including components from 3rd parties that are expecting the default behaviour of the EXEC statement within a SP to default the schema correctly according to the invoking user. From what I can see this is not happening in SQL2005. Is this a bug in SQL 2005 or normal behaviour



Re: Schema use in SQL2005

Michael Hotek


I don't understand. Do you have a script to reproduce the issue







Re: Schema use in SQL2005

Colm Ryan

Certainly...Se my Comments below in bold red....

The problem is how the EXEC statement resolves to the default schema. I'd like to know if this is a bug or expected behaviour or can it be resolved

/****** Object: StoredProcedure [myschema].[dnn_Forum_StatisticsGet] Script Date: 09/29/2007 08:53:05 ******/

SET ANSI_NULLS ON

GO

SET QUOTED_IDENTIFIER ON

GO

ALTER PROCEDURE [myschema.[dnn_Forum_StatisticsGet] /*SCHEMA SPECIFIED is DEFAULT FOR THE USER*/

(

@ModuleID int,

@UpdateWindow int = 12,

@TabId int

)

AS

-- Do we need to update the statistics

DECLARE @LastUpdate datetime

DECLARE @DateWindow datetime

SET @LastUpdate = ISNULL((SELECT MAX(CreatedDate) FROM dnn_Forum_Statistics_Site), '1/1/1797')

SET @DateWindow = DATEADD(hh, -@UpdateWindow, GetDate())

if (@LastUpdate < @DateWindow)

BEGIN

EXEC dnn_Forum_AA_StatisticsSiteUpdate 0, 0, @ModuleID, @TabId /*THIS COMMAND FAILS AS SCHEMA NOT SPECIFIED - SQL2000 this would resolve to the default owner*/

END

-- SELECT current statistics

SELECT TOP 1

S.*,

MostReadSubject = (SELECT Subject FROM dnn_Forum_Posts (nolock) WHERE PostID = S.MostReadThreadID),

MostViewsSubject = (SELECT Subject FROM dnn_Forum_Posts (nolock) WHERE PostID = S.MostViewsThreadID),

MostViewsThreadForumID = (SELECT ForumID FROM dnn_Forum_Threads (nolock) WHERE ThreadID = S.MostViewsThreadID),

MostActiveSubject = (SELECT Subject FROM dnn_Forum_Posts (nolock) WHERE PostID = S.MostActiveThreadID),

MostActiveThreadForumID = (SELECT ForumID FROM dnn_Forum_Threads (nolock) WHERE ThreadID = S.MostActiveThreadID),

MostActiveUserAlias = (SELECT Alias FROM dnn_Forum_Users (nolock) WHERE UserID = S.MostActiveUserID)

FROM

dnn_Forum_Statistics_Site S (nolock) /*THIS WILL RESOLVE CORRECTLY TO THE DEFAULT SCHEMA*/

WHERE

ModuleID = @ModuleID

ORDER BY CreatedDate DESC

-- SELECT TOP 10 Users

SELECT DISTINCT TOP 10

U.*,

FUR.Alias,

FUR.IsTrusted,

FUR.PostCount,

FUR.EnableOnlineStatus

FROM

dnn_Forum_Users FUR (nolock),

dnn_Users U (nolock),

dnn_UserPortals UP (nolock),

dnn_Tabs DT (nolock),

dnn_TabModules TM (nolock),

dnn_Modules DM (nolock)

WHERE

FUR.UserID = U.UserID AND

U.UserID = UP.UserID AND

UP.PortalID = DT.PortalID AND

DT.TabID = TM.TabID AND

TM.ModuleID = DM.ModuleID AND

DM.ModuleID = @ModuleID AND

U.UserName <> 'NNTP_NEWSGROUP_USER' AND

FUR.PostCount > 0

ORDER BY

FUR.PostCount DESC

-- SELECT top 10 Moderators

SELECT TOP 10

U.*,

FUR.Alias,

FUR.IsTrusted,

FUR.PostCount,

M.PostsModerated

FROM

dnn_Users U (nolock),

dnn_UserPortals UP (nolock),

dnn_Forum_Users FUR (nolock),

dnn_Forum_Moderators M (nolock),

dnn_Tabs DT (nolock),

dnn_TabModules TM (nolock),

dnn_Modules DM (nolock)

WHERE

U.UserID = FUR.UserID AND

FUR.UserID = M.UserID AND

U.UserID = UP.UserID AND

UP.PortalID = DT.PortalID AND

DT.TabID = TM.TabID AND

TM.TabID = DM.ModuleID AND

DM.ModuleID = @ModuleID AND

M.PostsModerated > 0

ORDER BY

PostsModerated DESC

-- SELECT Moderator actions

SELECT

Description,

TotalActions

FROM

dnn_Forum_ModerationAction (nolock)

ORDER BY

TotalActions DESC






Re: Schema use in SQL2005

Michael Hotek

Which schema is dnn_Forum_AA_StatisticsSiteUpdate defined in

Which schema is dnn_Forum_Statistics_Site defined in

The behavior of SQL Server 2005 is the same as SQL Server 2000 with respect to resolution. If you do not specific a schema, it will first look for the object in the default schema of the user. If it does not find the object in the default schema of the user, it will fall through and look in the dbo schema. If it is not found in the dbo schema, it will fail.

It should be noted that not fully qualifying the name of an object in SQL Server is just as bad of a practice as not fully qualifying an object in any programming language. It leads to issues and the default resolution order is not guaranteed to be preserved from one version to another.






Re: Schema use in SQL2005

Colm Ryan

Both are specified in the same schema which is the default schema for the user that is invoking the stored procedure. Notwithstanding good practise or otherwise (we didn't develop the SP, rather are porting an existing DB from 2000-> 2005, the behaviour in this case is different between the two versions.

The only explanation I can gather from this is that when executing the EXEC statement within a stored procedure, SQL server is changing the context and losing the reference to the default schema. Confirmation of this would be nice.





Re: Schema use in SQL2005

Allen White

When I upgraded from SQL 2000 to SQL 2005 the upgrade process created a schema for each user, and set the default schema for each user to the schema the upgrade created. After I saw that behavior I created an SMO program to remove the schemas created and set the default schema back to dbo.






Re: Schema use in SQL2005

Colm Ryan

This doesn't explain the behaviour of the EXEC statement within an SP. Each of the SP's within the DB are upgraded with the new schema. It is only when the EXEC statement is met within a stored procedure that SQL server forgets the user context and the schema it should be using. My question therefore to determine if this is expected behaviour or is a bug in the SQL server engine.

Colm





Re: Schema use in SQL2005

Steven Gott - MS

Hi Colm,

The exec statement refers to a single part name which is not a best practice for this precise reason - you do not know with certainty which proc you will get.

The lookup algorithm in SQL2005 is to check first the caller's default schema and then check the dbo schema.

Here is an example:

create database db_repro

go

use db_repro

go

create user U1 without login

go

create schema S1

go

create proc S1.P1 as select 'inside s1 schema'

go

create proc dbo.P1 as select 'inside dbo schema'

go

create proc dbo.outer_proc as exec P1

go

grant execute on S1.P1 to U1

grant execute on dbo.P1 to U1

grant execute on dbo.outer_proc to U1

go

Execute as user = 'U1'

go

exec dbo.outer_proc -- calls dbo.P1

go

exec P1 -- calls dbo.P1

go

revert

go

alter user U1 with default_schema=S1

go

Execute as user = 'U1'

go

exec dbo.outer_proc -- calls S1.P1

go

exec P1 -- calls S1.P1

go

revert

go

HTH,

-Steven Gott

SDE/T

SQL Server






Re: Schema use in SQL2005

Colm Ryan

Thank you for the example. It makes perfect sense to me but I'm afraid my scenario still doesn't!

Here are some details about the db config and object ownership:

  • I've a login called colm3rd_mssql which uses the database by default
  • I've a user called colm3rd_mssql within the database with a default schema of colm3rd_mssql.
  • The .net connection string specifies the db and logs in with the user colm3rd_mssql.
  • All user stored procedures in the DB are owned by the schema colm3rd_mssql

Shouldn't this be enough for the exec statement within a procedure to have identified that it should use colm3rd_mssql as the default schema The only part I can assume is missing is that the "execute as" component is unknown when the exec statement is called.
I guess I will need to modify these procedures I guess to work around this but I am feeling more inclined to believe that there is something awry here with the DB Engine.

Rgds and Thks

Colm





Re: Schema use in SQL2005

Colm Ryan

OK! Thanks to your pointers I think I've figured out a solution to this. Seems that I need to have a dblogin and dbuser that has a different name to the schema. The db restore had create all of the same name by default. I created a seperate login and mapped this to the same user within the db. Once this is mapped to the schema that was created during the import everything worked as expected and the EXEC statements worked out ok.

Rgds

Colm





Re: Schema use in SQL2005

Michael Hotek

Now, it makes sense. Go back and drop the extra login that you created.

You have a login cross mapped in the database, because of a restore operation. Go back into the database and execute sp_changeuserslogin. This will remap the user in the database to the login and then everything will work as you expect it to.

The most critical piece of information to solving this was "I restored a backup". We'd have solved this days ago, if we would have known we were dealing with a restore, because it is almost always an issue of cross mapped users and logins.