SET QUOTED_IDENTIFIER ON GO SET ANSI_NULLS ON GO if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[vssCompareDatabaseToVss]') and OBJECTPROPERTY(id, N'IsProcedure') = 1) drop procedure [dbo].[vssCompareDatabaseToVss] GO create procedure dbo.vssCompareDatabaseToVss @pDatabaseName varchar(30), @pEnvironmentName varchar(30), @pTempFolder varchar(255) as /*************************************************************************** A local database can be compared to any environments SourceSafe copy of that database. Compare the contents s SQL Server database to a project hierarchy in Visual SourceSafe. Scripts the database to the specified temporary work area and the compares objects and contents between the temp area and the corresponding SourceSafe store of the specified Environment. Notes: The temp area is always cleared at the beginning of this procedure. Will not work with UNC paths. ****************************************************************************/ declare @Cmd nvarchar(1200), @returnStatus int, @procedureName varchar(255), @vssHierarchy varchar(255), @vssShare varchar(255), @vssUserName varchar(30), @line varchar(255), @diffCount int set nocount on -- make sure there is a trailing whack on the path if (substring(@pTempFolder,datalength(@pTempFolder),1) <> '\') set @pTempFolder = @pTempFolder + '\' set @diffCount = 0 set @procedureName = db_name() + '.' + user_name(objectproperty(@@procid,'OwnerId')) + '.' + object_name(@@procid) -- get info if local and specified are both in matadata select @vssShare = p.vssShare, @vssHierarchy = p.vssHierarchyRoot + e.environmentName + '/' + s.serverName + '/' + s.instanceName + '/' + @pDatabaseName + '/', @vssUserName = n.vssUserName from Admin.dbo.SqlDatabase d inner join Admin.dbo.ProjectNode n on d.id = n.sqlDatabase_id inner join Admin.dbo.SQlServer s on s.id = n.sqlServer_id inner join Admin.dbo.Environment e on e.id = n.environment_id inner join Admin.dbo.Project p on p.id = n.project_id inner join Admin.dbo.ProjectNode l -- local on (n.project_Id = l.project_Id and n.sqlDatabase_Id = l.sqlDatabase_id) inner join Admin.dbo.SQlServer sl on l.sqlServer_id = sl.Id where d.databaseName = @pDatabaseName --and s.id = Admin.dbo.thisSQLServer_id() cannot use function in SQL Server 7 and e.environmentName = @pEnvironmentName and sl.serverName = reverse(substring(reverse(@@servername), charindex('\',reverse(@@servername)) + 1, datalength(reverse(@@servername)))) and sl.instanceName = substring(@@servername, charindex('\',@@servername) + 1, datalength(@@servername)) and n.IsActive = 1 and l.IsActive = 1 -- valid project node must exist if @@rowcount = 0 begin raiserror(59002,16,1,@procedureName,@pDatabaseName) goto ErrorHandler end -- wrong user asking if substring(system_user,charindex('\', system_user) + 1, datalength(system_user)) <> @vssUserName begin set @vssUserName = substring(system_user,charindex('\', system_user) + 1, datalength(system_user)) raiserror (59005,16,1, @procedurename, @vssUserName, @vssShare) goto ErrorHandler end -- file system temporary working folder must exist set @cmd = 'dir ' + @pTempFolder exec @returnstatus = master.dbo.xp_cmdshell @CMD, no_output if @returnstatus <> 0 begin raiserror (59007,16,1,@procedureName, @pTempFolder,@@servername) goto ErrorHandler end -- vss project must exist and be visible to local system -- NOTE! if you put a password on vss, this will hang (tries to prompt for password) set @cmd = @vssShare + 'win32\ss Cp ' + @vssHierarchy + ' -I-N -Y' + @vssUserName exec @returnstatus = master.dbo.xp_cmdshell @cmd, no_output if @returnstatus <> 0 begin raiserror(59008,16,1,@procedureName, @vssHierarchy, @vssShare) goto ErrorHandler end -- everything is in place, so script the database -- keep the worthless stored procedure output off the results pane create table #junk (junk varchar(255)) insert #junk exec @returnstatus = Admin.dbo.dmoScriptDatabase @pDatabaseName, @pTempFolder if @returnstatus <> 0 goto ErrorHandler insert #junk exec @returnstatus = Admin.dbo.dmoScriptTables @pDatabaseName, @pTempFolder if @returnstatus <> 0 goto ErrorHandler drop table #junk set @pTempFolder = @pTempFolder + @pDataBaseName + '\' -- compare objects set @Cmd = substring(@pTempFolder,1,2) + '&cd ' + substring(@pTempFolder,3,datalength(@pTempFolder)) + '&' + @vssShare + 'win32\ss Diff ' --+ @vssHierarchy --is current + ' -R -B -Y' + @vssUserName exec @returnstatus = master.dbo.xp_cmdshell @Cmd, NO_OUTPUT if @returnstatus = 1 begin print '' print 'Unmatched Objects found!' print '' create table #ObjectDifferences(output varchar(255)) insert #ObjectDifferences exec master.dbo.xp_cmdshell @Cmd delete #ObjectDifferences where output like 'Against:%' update #ObjectDifferences set output = '' where output is NULL update #ObjectDifferences set output = 'SourceSafe files not in the database:' where output like 'SourceSafe files not in the current folder:%' update #ObjectDifferences set output = 'Local database objects not in environment ' + @pEnvironmentName + ' in SourceSafe :' where output like 'Local files not in the current project:%' select * from #ObjectDifferences drop table #ObjectDifferences end else begin if @returnstatus <> 0 goto ErrorHandler else begin print '' print 'No unmatched objects found.' end end -- compare contents -- get list of all files in the working folder create table #fileList (line varchar(255)) set @Cmd = 'dir ' + @pTempFolder + ' /A /S /B' insert #fileList exec master.dbo.xp_cmdshell @Cmd -- a little clean up of the list -- only .sql files delete #fileList where line not like '%.sql' or line is null -- position just past the database name update #fileList set line = substring(line, datalength(@pTempFolder) + 1, datalength(line)) -- compare each file to it's VSS mate set @line = (select top 1 line from #fileList order by line) while @line is not null begin set @Cmd = @vssShare + 'win32\ss Diff ' --+ @vssHierarchy + replace(@line,'\','/') + ' ' + @pTempFolder + @line + ' -DS -Y' + @vssUSerName exec @returnstatus = master.dbo.xp_cmdshell @Cmd, NO_OUTPUT if @returnstatus = 1 begin set @diffCount = @diffCount + 1 print '' print 'Internal Object Differences found!' print '' create table #ContentDifferences(output varchar(255)) insert #ContentDifferences exec master.dbo.xp_cmdshell @Cmd update #ContentDifferences set output = '' where output is NULL select * from #ContentDifferences drop table #ContentDifferences end else if @returnstatus <> 0 goto ErrorHandler delete #fileList where line = @line set @line = (select top 1 line from #fileList order by line) end if @diffCOunt = 0 begin print '' print 'No internal object differences found.' end print '' print 'Compare complete' return ErrorHandler: if (@Cmd is not null) begin insert Admin.dbo.ActivityLog (activity) select @procedureName + ' ' + @pDatabaseName + ' ' + @pEnvironmentName + ' ' + @pTempFolder + ' failed with returnstatus ' + cast(@returnstatus as varchar(10)) + ' at: ' + @cmd raiserror(59001,16,1,@procedureName) end else raiserror(59000,16,1,@procedureName) return -1 GO SET QUOTED_IDENTIFIER OFF GO SET ANSI_NULLS ON GO