set nocount on
go

execute dbo.sp_configure 'update',1
go
reconfigure with override
go

set ANSI_NULLS off
go

use master
go

dump tran master with no_log
go

/* 
** Drop the stored procedures in this script using the old dropping SP 
** and then drop itself
*/
if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_MSdrop_rlcore')
begin
	exec dbo.sp_MSdrop_rlcore
	drop procedure sp_MSdrop_rlcore
end

/*
** Create stored procedures to drop the stored procedures
** created by this script
*/

raiserror('Creating procedure sp_MSdrop_rlcore', 0,1)
GO
create procedure sp_MSdrop_rlcore
as

	if exists (select * from sysobjects
			where type = 'P'
				and name = 'sp_MSguidtostr')
		drop procedure sp_MSguidtostr

	if exists (select * from sysobjects
			where type = 'P'
				and name = 'sp_MSgetconflicttablename')
		drop procedure sp_MSgetconflicttablename

	if exists (select * from sysobjects
			where type = 'P'
				and name = 'sp_MSuniquetempname')
		drop procedure sp_MSuniquetempname

	if exists (select * from sysobjects
			where type = 'P'
				and name = 'sp_MSuniqueobjectname')
		drop procedure sp_MSuniqueobjectname


	if exists (select * from sysobjects
			where type = 'P'
				and name = 'sp_MSaddguidcolumn')
		drop procedure sp_MSaddguidcolumn

	if exists (select * from sysobjects
			where type = 'P'
				and name = 'sp_MSuniquecolname')
		drop procedure sp_MSuniquecolname

	if exists (select * from sysobjects
			where type = 'P'
				and name = 'sp_MSaddguidindex')
		drop procedure sp_MSaddguidindex

	if exists (select * from sysobjects
			where type = 'P'
				and name = 'sp_MSrefcnt')
		drop procedure sp_MSrefcnt
	
	if exists (select * from sysobjects
			where type = 'P'
				and name = 'sp_MSgentablenickname')
		drop procedure sp_MSgentablenickname
	
	if exists (select * from sysobjects
			where type = 'P'
				and name = 'sp_MStablenickname')
		drop procedure sp_MStablenickname
	
	if exists (select * from sysobjects
		where type = 'P'
			and name = 'sp_MStablenamefromnick')
		drop procedure sp_MStablenamefromnick
	
	if exists (select * from sysobjects
			where type = 'P'
				and name = 'sp_MSmakegeneration')
		drop procedure sp_MSmakegeneration
	
	if exists (select * from sysobjects
			where type = 'P'
				and name = 'sp_MSaddupdatetrigger')
		drop procedure sp_MSaddupdatetrigger
	
	if exists (select * from sysobjects
			where type = 'P'
				and name = 'sp_MSaddmergetriggers')
		drop procedure sp_MSaddmergetriggers
	
	if exists (select * from sysobjects
				where type = 'P' and
				name = 'sp_MSmaptype')
		drop procedure sp_MSmaptype 

go
exec dbo.sp_MS_marksystemobject sp_MSdrop_rlcore
go
exec dbo.sp_MSdrop_rlcore
go

dump tran master with no_log
go

raiserror('Creating procedure sp_MSguidtostr', 0, 1)
GO


create proc sp_MSguidtostr (@guid uniqueidentifier, @mystr nvarchar(32) output)
	as
declare @guidstr nvarchar(36)
set @guidstr = convert(nchar(36), @guid)
set @mystr = substring(@guidstr, 1, 8) + substring(@guidstr, 10, 4) +
	substring(@guidstr, 15, 4)+ substring(@guidstr, 20, 4)+ substring(@guidstr, 25, 12)
go
exec dbo.sp_MS_marksystemobject sp_MSguidtostr
go

raiserror('Creating procedure sp_MSgetconflicttablename', 0,1)
GO

CREATE PROCEDURE sp_MSgetconflicttablename
@source_object nvarchar(258),
@conflict_table sysname = NULL OUTPUT
AS

declare @objid 				int
declare @retcode			int
declare @current_conflict	sysname
declare @object_name		sysname
declare @name_out			sysname

select @objid = object_id(@source_object)
select @current_conflict = conflict_table from sysmergearticles where objid = @objid and conflict_table is not NULL
if @current_conflict is not NULL
	begin
		if @conflict_table is NULL
			select @current_conflict
		else	
			select @conflict_table = @current_conflict
		return (0)
	end
select @object_name = object_name(@objid)
select @object_name = 'conflict_' + @object_name
exec @retcode = dbo.sp_MSuniqueobjectname @object_name, @conflict_table OUTPUT

GO

exec dbo.sp_MS_marksystemobject sp_MSgetconflicttablename
go
grant exec on dbo.sp_MSgetconflicttablename to public
go

raiserror('Creating procedure sp_MSuniqueobjectname', 0,1)
GO

CREATE PROCEDURE sp_MSuniqueobjectname 
	@name_in sysname,
 	@name_out sysname = NULL output
AS

 	declare @name_out_local sysname
	declare @subschars 		sysname
	declare @curchar 		nchar(1)
	declare @substidx 		int
	declare @pos 			int

	select @subschars = 'abcdefghijklmnopqrstuvwxyz'
	select @name_out_local = @name_in


	select @substidx = 0
	select @pos = 1

	while exists (select * from sysobjects where name = @name_out_local)
		begin
		if @substidx > 25 
			begin
			select @pos = @pos + 1
			select @substidx = 1
			end
		else
			select @substidx = @substidx + 1
		select @curchar = substring(@subschars, @substidx, 1)
		select @name_out_local = stuff(@name_out_local, @pos, 1, @curchar)
		end

	if @name_out IS NULL
		select @name_out_local
	else
		select @name_out = @name_out_local

	return (0)
GO

exec dbo.sp_MS_marksystemobject sp_MSuniqueobjectname 
go


raiserror('Creating procedure sp_MSuniquetempname', 0,1)
GO

CREATE PROCEDURE sp_MSuniquetempname @name_in sysname,
 	@name_out sysname output
AS

	declare @subschars nvarchar(26)
	declare @curchar nchar(1)
	declare @substidx int
	declare @pos int
	declare @saverr int

	select @subschars = 'abcdefghijklmnopqrstuvwxyz'
	select @saverr = @@error
	if (@saverr <> 0)
		goto EXIT_LABEL
	select @name_out = @name_in
	select @saverr = @@error
	if (@saverr <> 0)
		goto EXIT_LABEL

	select @saverr = @@error
	if (@saverr <> 0)
		goto EXIT_LABEL
	select @substidx = 0
	select @pos = 3

	while exists (select * from tempdb..sysobjects where name = @name_out)
		begin
			if @substidx > 25 
				begin
				select @pos = @pos + 1
				select @substidx = 1
				end
			else
				select @substidx = @substidx + 1
			select @curchar = substring(@subschars, @substidx, 1)
			select @saverr = @@error
			if (@saverr <> 0)
				goto EXIT_LABEL
			select @name_out = stuff(@name_out, @pos, 1, @curchar)
			select @saverr = @@error
			if (@saverr <> 0)
				goto EXIT_LABEL
		end
		return (0)
EXIT_LABEL:
	if (@saverr <> 0)
		begin
			RAISERROR(15001, 16, -1, 'sp_MSuniquetempname')
			return (1)
		end
			
GO
exec dbo.sp_MS_marksystemobject sp_MSuniquetempname 
go

raiserror('Creating procedure sp_MSuniquecolname', 0,1)
GO

create procedure sp_MSuniquecolname
	@table_name nvarchar(258),  -- this is a qualified_name 		
	@base_colname sysname, 
	@unique_colname sysname output
as
begin
	
	set nocount on
	
	declare @icol_suffix int
	
	select @icol_suffix = ( max(colorder) + 1 ) from syscolumns 
		where id = object_id( @table_name )

	select @unique_colname = @base_colname 

	while exists( 
			select * from syscolumns 
				where id = object_id( @table_name ) 
				  and name = @unique_colname
	)
	begin
		select @unique_colname = @base_colname + convert( nvarchar(40), @icol_suffix )  	
		select @icol_suffix = @icol_suffix * ( @@spid + 1 )
	end
	
end
go

exec dbo.sp_MS_marksystemobject sp_MSuniquecolname
go

raiserror('Creating procedure sp_MSaddguidcolumn', 0,1)
GO

create procedure sp_MSaddguidcolumn 
	@source_owner	sysname,
	@source_table sysname 		/* table name */
as
	declare @rowguidcol 		sysname
	declare @qualified_name		nvarchar(258)

	set nocount on

	select @qualified_name = QUOTENAME(@source_owner) + '.' + QUOTENAME(@source_table)
	
	/* Alter the source table to add a rowguid column */
	begin tran
	exec dbo.sp_MSunmarkreplinfo @source_table, @source_owner
	if @@ERROR <>0 goto UNDO

	if not exists (select * from syscolumns
		where ObjectProperty(object_id(@qualified_name), 'tablehasrowguidcol')=1)
	begin
		exec dbo.sp_MSuniquecolname @qualified_name, 'rowguid', @rowguidcol output
		exec ('alter table ' + @qualified_name + ' add ' + @rowguidcol + ' uniqueidentifier ROWGUIDCOL default newid() not null')
		if @@ERROR<>0 goto UNDO
	end
	exec dbo.sp_MSunmarkreplinfo @source_table, @source_owner, 1
	if @@ERROR<>0 goto UNDO
	commit tran
	return (0)
UNDO:
	if @@TRANCOUNT = 1 
		ROLLBACK TRANSACTION 
	else
		COMMIT TRANSACTION
	return (1)	
go

exec dbo.sp_MS_marksystemobject sp_MSaddguidcolumn 
go
grant exec on dbo.sp_MSaddguidcolumn to public
go

raiserror('Creating procedure sp_MSaddguidindex', 0,1)
GO

create procedure sp_MSaddguidindex
	@source_owner	sysname,
	@source_table 	sysname		
as
	set nocount on
	declare @indexname 	nvarchar(270)
	declare @colname	sysname
	declare @retcode int
	declare @qualified_name nvarchar(258)

  
   select @qualified_name = QUOTENAME(@source_owner) + '.' + QUOTENAME(@source_table)
   
	select @indexname = 'index_' + convert(nvarchar(36), object_id(@qualified_name))

	/* Make sure index name is unique */
	exec @retcode = dbo.sp_MSuniqueobjectname @indexname, @indexname output
	if @retcode <>0 return (1)
	

	select @colname=name from syscolumns where id=object_id(@qualified_name) and columnproperty(object_id(@qualified_name), name, 'isrowguidcol')=1
	if (@colname is null)
		return (1)
		
	/* Alter the source table to add a rowguid column */
	if (not exists (select * from sysindexes
		where id = object_id(@qualified_name) and
			@colname = index_col(object_name(id), indid, 1)
			and indexproperty(id, name, 'IsUnique') = 1 and 
			index_col(object_name(id), indid, 2) is null))
			exec ('create unique index ' + @indexname  + ' on ' + @qualified_name + ' (' +  @colname + ')')
		if @@ERROR <>0 return (1) 
	return (0)
go


exec dbo.sp_MS_marksystemobject sp_MSaddguidindex
go
grant exec on dbo.sp_MSaddguidindex to public
go

raiserror('Creating procedure sp_MSrefcnt', 0,1)
GO

create procedure sp_MSrefcnt
	@objid int, @refcnt int output
as
	set @refcnt = 0
	create table #temprefs (objid int NOT NULL)
	insert into #temprefs select distinct rkeyid from sysreferences where fkeyid = @objid

	while (@@rowcount > 0)
		insert into #temprefs select distinct rkeyid from
			sysreferences where fkeyid in (select objid from #temprefs) and
				rkeyid not in (select objid from #temprefs)

	select @refcnt = count(*) from #temprefs
	return (0)
GO

exec dbo.sp_MS_marksystemobject sp_MSrefcnt
go


raiserror('Creating procedure sp_MSgentablenickname', 0,1)
GO

create procedure sp_MSgentablenickname
			@tablenick	int	output, @nickname int, @objid int
as

	declare @refcnt int
	declare @retval int
	
	/* Create a tablenickname from the following formula
	**		1.  Get the refcnt, use it for the high order digits so
	**		    that processing inserts by ascending tablenickname works well
	** 			and processing deletes by descending tablenickname works well.
	**		2.  Use a couple of digits from the nickname so that it is less likely
	**			to collide with tablenickname generated at another merge publisher.
	**		3.  Increment as necessary to make it unique within the publication and database.
	*/
	exec @retval = dbo.sp_MSrefcnt @objid, @refcnt output
	if @retval <> 0 return (1)

	if @nickname < 0
		set @nickname = 0 - @nickname
	set @tablenick = 1000 * ((@refcnt * 10000) + (@nickname % 10000))
	while exists (select * from sysmergearticles where nickname = @tablenick)
		set @tablenick = @tablenick + 1
	return (0)
go

exec dbo.sp_MS_marksystemobject sp_MSgentablenickname
go

raiserror('Creating procedure sp_MStablenickname', 0,1)
GO

create procedure sp_MStablenickname 
	@owner		sysname,
	@tablename 	sysname,
	@nick int 	output
as
	declare @qualified_name nvarchar(255)
	if @owner is not null
		select @qualified_name = QUOTENAME(@owner) + '.' + QUOTENAME(@tablename)
	else 
		select @qualified_name = QUOTENAME(@tablename)
		
	select @nick = nickname from sysmergearticles a, sysobjects o
			where a.objid = o.id and o.id = OBJECT_ID(@qualified_name) and
				(user_name(uid) = @owner or @owner is null)
	if @nick is NULL return (1) 			
	return (0)
go

exec dbo.sp_MS_marksystemobject sp_MStablenickname 
go

raiserror('Creating procedure sp_MStablenamefromnick', 0,1)
GO

create procedure sp_MStablenamefromnick
	@nick int,
	@tablename nvarchar(258) output,
	@pubid uniqueidentifier = NULL
as
	declare @owner sysname
	declare @table sysname
	if (@pubid is null)
		select @table = name, @owner = user_name(uid) from sysobjects where id in (select 
			objid from sysmergearticles where nickname = @nick)
	else
		select @table = name, @owner = user_name(uid) from sysobjects where id in (select 
			objid from sysmergearticles where nickname = @nick and pubid = @pubid)
			
	select @tablename = QUOTENAME(@owner) + '.' + QUOTENAME(@table)
	if (@table is NULL) or (@owner is NULL) 
    begin
        raiserror(211124, 16, -1, @nick)
        return (1) 
    end
	return (0)
go

exec dbo.sp_MS_marksystemobject sp_MStablenamefromnick
go

raiserror('Creating procedure sp_MSmakegeneration', 0,1)
GO

create procedure sp_MSmakegeneration
	@rowcount int = 0
	as
	declare @gen int
	declare @nick int
	declare @genguid uniqueidentifier
	declare @dt datetime
	declare @dt2 datetime
	declare @art_nick int
	declare @first_ts int
	declare @makenewrow int
	declare @retcode smallint
	declare @guidnull uniqueidentifier
	
	set nocount on
	set rowcount @rowcount
	set @guidnull = '00000000-0000-0000-0000-000000000000'
	
	/*
	** Check to see if current publication has permission
	*/
	exec @retcode=sp_MSreplcheck_connection
	if @retcode<>0 or @@ERROR<>0 return (1)
	
	set @genguid = newid()
	exec @retcode=sp_MSgetreplnick @nickname = @nick out
	if @retcode<>0 or @@error<>0 return (1)
	set @dt = getdate()

	-- If someone else is making generations / has just made one, exit so
	-- that we won't deadlock
	select @dt2 = max(coldate) from MSmerge_genhistory where guidsrc = guidlocal
	if datediff(dd, @dt2, @dt) = 0
		begin
		if 500 > datediff(ms, @dt2, @dt) and 0 < datediff(ms, @dt2, @dt)
			return 0
		end

	-- check for holes 
	select @gen = max(generation) from MSmerge_genhistory
	if exists (select * from MSmerge_genhistory where guidlocal = @guidnull and generation < @gen - 100 and
						generation not in (select gen_cur from sysmergearticles))
		begin
		-- before we delete the holes, move contents rows to generation 0 so they don't get forgotten

		if exists (select * from MSmerge_contents (readpast readcommitted) where generation in (select generation from MSmerge_genhistory where guidlocal = @guidnull and generation < @gen - 100 and
						generation not in (select gen_cur from sysmergearticles)))
				begin
				update MSmerge_contents set generation = 0 where generation in (select generation from MSmerge_genhistory where guidlocal = @guidnull and generation < @gen - 100 and
						generation not in (select gen_cur from sysmergearticles))
				if (@@error <> 0)
					begin
					goto FAILURE
					end	
				end
		if exists (select * from MSmerge_tombstone (readpast readcommitted) where generation in (select generation from MSmerge_genhistory where guidlocal = @guidnull and generation < @gen - 100 and
						generation not in (select gen_cur from sysmergearticles)))
				begin
				update MSmerge_tombstone set generation = 0 where generation in (select generation from MSmerge_genhistory where guidlocal = @guidnull and generation < @gen - 100 and
						generation not in (select gen_cur from sysmergearticles))
				if (@@error <> 0)
					begin
					goto FAILURE
					end	
				end
		delete from MSmerge_genhistory where guidlocal = @guidnull and generation < @gen - 100 and
						generation not in (select gen_cur from sysmergearticles)
		if (@@error <> 0)
			begin
			goto FAILURE
			end	
		end
	/*
	** If there are no zero generation tombstones or rows, add a dummy row in there. 
	*/
   	if not exists (select * from MSmerge_genhistory where guidlocal <> @guidnull)
		begin
		begin tran
	   	insert into MSmerge_genhistory (guidsrc, guidlocal, generation, art_nick, nicknames, coldate) values
			(@genguid, @genguid, 1, 0, @nick, @dt)
		if (@@error <> 0)
			begin
			goto FAILURE
			end	
		commit tran
		end

	select @art_nick = min(nickname) from sysmergearticles
	while @art_nick is not null
		begin
		begin tran
		select @gen = max(gen_cur) from sysmergearticles (updlock) where nickname = @art_nick and gen_cur is not null

		if @gen is null
			begin
			insert into MSmerge_genhistory (guidsrc, guidlocal, generation, art_nick, nicknames, coldate) 
				select @genguid, @guidnull, COALESCE(1 + max(generation), 1), @art_nick, @nick, @dt from MSmerge_genhistory (updlock)
			if (@@error <> 0)
				begin
				goto FAILURE
				end	
			select @gen =  generation from MSmerge_genhistory where guidsrc = @genguid
			update sysmergearticles set gen_cur = @gen where nickname = @art_nick
			if (@@error <> 0)
				begin
				goto FAILURE
				end	
			end

		-- these updates should be hitting zero rows...
		if exists (select * from MSmerge_contents (readpast readcommitted) where generation = 0 and tablenick = @art_nick)
			begin
			update MSmerge_contents set generation = @gen, partchangegen = @gen, joinchangegen = @gen
			 	where generation = 0 and partchangegen = 0 and tablenick = @art_nick
			if (@@error <> 0)
				begin
				goto FAILURE
				end	
			update MSmerge_contents set generation = @gen, joinchangegen = @gen
			 	where generation = 0 and joinchangegen = 0 and tablenick = @art_nick
			if (@@error <> 0)
				begin
				goto FAILURE
				end	
			update MSmerge_contents set generation = @gen where generation = 0 and tablenick = @art_nick
			if (@@error <> 0)
				begin
				goto FAILURE
				end
			end
			
		if exists (select * from MSmerge_tombstone (readpast readcommitted) where generation = 0 and tablenick = @art_nick)
			begin
			update MSmerge_tombstone set generation = @gen where generation = 0 and tablenick = @art_nick
			if (@@error <> 0)
				begin
				goto FAILURE
				end
			end
		if not exists (select * from MSmerge_contents where tablenick = @art_nick and
						generation = @gen) and
		   not exists (select * from MSmerge_tombstone where tablenick = @art_nick and
						generation = @gen)
			begin
			select @dt2 = coldate from MSmerge_genhistory where generation = @gen
			if datediff(dd, @dt2, @dt) = 0 and not exists (select * from MSmerge_genhistory
					where generation > 100 + @gen)
				begin
				set @makenewrow = 0
				end
			else
				begin
				set @makenewrow = 1
				delete from MSmerge_genhistory where generation = @gen
				if (@@error <> 0)
					begin
					goto FAILURE
					end	
				end
				
			if (@@error <> 0)
				begin
				goto FAILURE
				end	
			end
		else
			begin
			set @makenewrow = 1
			set @genguid = newid()
			update MSmerge_genhistory set guidsrc = @genguid, guidlocal = @genguid, coldate = @dt
				where generation = @gen
			if (@@error <> 0)
				begin
				goto FAILURE
				end	
			update MSmerge_replinfo set recgen = @gen, recguid = @genguid, 
				sentgen = @gen, sentguid = @genguid where replnickname = @nick
			if (@@error <> 0)
				begin
				goto FAILURE
				end	
			end

		if (@makenewrow = 1)
			begin
			/* reset next generation for this article */
			set @genguid = newid()
			insert into MSmerge_genhistory (guidsrc, guidlocal, generation, art_nick, nicknames, coldate) 
				select @genguid, @guidnull, COALESCE(1 + max(generation), 1), @art_nick, @nick, @dt from MSmerge_genhistory (updlock)
			if (@@error <> 0)
				begin
				goto FAILURE
				end	
			select @gen =  generation  from MSmerge_genhistory where guidsrc = @genguid
			update sysmergearticles set gen_cur = @gen where nickname = @art_nick
			if (@@error <> 0)
				begin
				goto FAILURE
				end	
			end
		commit transaction		

		-- set up for next time through the loop
		select @art_nick = min(nickname) from sysmergearticles where nickname > @art_nick
		
		set @dt = getdate()
		end
	return 0
FAILURE:
	/* UNDONE : This code is specific to 6.X nested transaction semantics */
	if @@TRANCOUNT = 1 
		ROLLBACK TRANSACTION makegeneration
	else
		COMMIT TRANSACTION
	return (1)	
go

exec dbo.sp_MS_marksystemobject sp_MSmakegeneration 
go
grant exec on dbo.sp_MSmakegeneration to public
go

dump tran master with no_log
go

raiserror('Creating procedure sp_MSaddupdatetrigger', 0,1)
GO

CREATE PROCEDURE sp_MSaddupdatetrigger 
	@source_table		nvarchar(258),		/* source table name */
	@owner				sysname,			/* Owner name of source table */
	@object 			sysname,			/* Object name */
	@artid				uniqueidentifier,	/* Article id */
	@column_tracking		int,
	@viewname			sysname 			/* name of view on syscontents */
    
AS
	declare @command1 nvarchar(4000)
	declare @command2 nvarchar(4000)
	declare @tablenick int	
	declare @nickname int
	declare @trigname sysname
	declare @ext nvarchar(10)
	declare @gstr sysname
	declare @tablenickchar nvarchar(11)
	declare @ccols int
	declare @guidstr	nvarchar(32)
	declare @colid smallint
	declare @colordinal		smallint
	declare @colordstr		varchar(4)

	declare @colname sysname
	declare @colpat nvarchar(34)
	declare @colchar nvarchar(5)
	declare @piece nvarchar(400)

	declare @retcode int
	declare @ifcol nvarchar(4000)
	declare @ccolchar nvarchar(5)
	declare @partchangecnt int
	declare @joinchangecnt int
	declare @partchangecnt2 int
	declare @cvstr1	nvarchar(500)
	declare @cvstr2 nvarchar(500)
	declare @flag smallint
	declare @missingbm varbinary(500)
	declare @missingcolid int
	declare @maxcolid int
	declare @missingbmstr varchar(1000)
	declare @objid int
	declare @partchbm varbinary(500)
	declare @joinchbm varbinary(500)
	declare @partchstr varchar(1002)
	declare @joinchstr varchar(1002)
	
	set @ifcol = ''
	
	select @flag = 0
	set @objid = OBJECT_ID(@source_table)
	select @ccols =  count(*) from syscolumns where id = @objid and iscomputed <> 1
	select @ccolchar = convert(nchar, @ccols)
	set @colordinal = 0
	
	execute @retcode=sp_MStablenickname @owner, @object, @tablenick output
	if @@ERROR<>0 or @retcode<>0 return (1)
	set @tablenickchar = convert(nchar, @tablenick)
	set @joinchbm = 0x0
	set @partchbm = 0x0
	
	declare col_cursor CURSOR LOCAL FAST_FORWARD for select name, colid from syscolumns where
		id = @objid  and iscomputed <> 1 order by colid
	FOR READ ONLY
	
	/* Try to set the ifcol pieces of the trigger */
	open col_cursor
	fetch next from col_cursor into @colname, @colid
	while (@@fetch_status <> -1)
		begin
		set @colordinal = @colordinal + 1
		set @colpat = '%' + @colname + '%'
		set @colname = QUOTENAME(@colname)
		/* Don't let them update the rowguid column */
		if columnproperty( @objid, @colname , 'isrowguidcol')=1
			set @ifcol = 'if update(' + @colname +	')
			begin
			if @@trancount > 0
				rollback tran
				
			RAISERROR (20062, 16, -1)
			end
				'
		/* does updating this column change membership in a partial replica? */
		select @partchangecnt = count(*) from sysmergearticles 
			where nickname = @tablenick and subset_filterclause like @colpat
		select @partchangecnt2 = count(*) from sysmergesubsetfilters
			where art_nickname = @tablenick and join_filterclause like @colpat
		select @joinchangecnt = count(*) from sysmergesubsetfilters
		 	where join_nickname = @tablenick and join_filterclause like @colpat
		if @partchangecnt > 0 or @partchangecnt2 > 0
			exec dbo.sp_MSsetbit @partchbm out, @colid
		else if @joinchangecnt > 0
			exec dbo.sp_MSsetbit @joinchbm out, @colid
		/* Repeat the loop with next column */
		fetch next from col_cursor into @colname, @colid
		end
	close col_cursor
	deallocate col_cursor

	/* Make strings to initialize variables for partchange, joinchange bitmaps */
	exec master..xp_varbintohexstr @partchbm, @partchstr out
	exec master..xp_varbintohexstr @joinchbm, @joinchstr out

	/* Figure out if there are any holes in the colid sequence */
	select @maxcolid = max(colid) from syscolumns where id = @objid
	if @maxcolid = @ccols
		set @missingbmstr = '0x00'
	else
		begin
		set @missingcolid = 1
		set @missingbm = 0x00
		while (@missingcolid <= @maxcolid)
			begin
			if not exists (select * from syscolumns where colid = @missingcolid and
					id = OBJECT_ID(@source_table) and iscomputed <> 1)
			exec dbo.sp_MSsetbit @missingbm out, @missingcolid
			set @missingcolid = @missingcolid + 1
			end
		exec master..xp_varbintohexstr @missingbm, @missingbmstr out
		end

	execute @retcode=sp_MSgetreplnick @nickname = @nickname output
	if @retcode<>0 or @@error<>0 return (1)
	set @ext = 'upd_'

	exec @retcode=sp_MSguidtostr @artid, @guidstr out
	if @retcode<>0 or @@error<>0 return (1)

	set @trigname =  @ext + @guidstr 

	/* Make sure trigger name is unique */
	exec @retcode=sp_MSuniqueobjectname @trigname, @trigname output
	if @retcode<>0 or @@error<>0 return (1)
	if @column_tracking <> 0
		begin
		/* Set cv pieces appropriately */
		set @cvstr1 = ' 
		    set @lineage = { fn UPDATELINEAGE(0x0, @nick) }
		    set @lineage = { fn UPDATELINEAGE(@lineage, @nick) }
		    set @cv = { fn INITCOLVS(@ccols, @nick) }
			if (@@error <> 0)
				begin
				goto FAILURE
				end
		    set @cv = { fn UPDATECOLVBM(@cv, @nick, @bm, @missingbm) }
		'
		set @cvstr2 = ' colv1 = { fn UPDATECOLVBM(colv1, @nick, @bm, @missingbm) } '
		end
	else
		begin
		set @cvstr1 = '   set @lineage = { fn UPDATELINEAGE(0x0, @nick) }
		    set @lineage = { fn UPDATELINEAGE(@lineage, @nick) }
			set @cv = NULL
 	'
		set @cvstr2 = ' colv1 = NULL '
		end
	/* UNDONE maybe remove null guid checks in SQL SERVER 7.0 */
	select @command1 = 'create trigger ' + @trigname + ' on ' + @source_table +
	' FOR UPDATE AS
	/* Declare variables */
	declare @bm varbinary(500)
	declare @missingbm varbinary(500)
	declare @tablenick int
	declare @rowguid uniqueidentifier
	declare @lineage varbinary(255)
	declare @cv varbinary(2048)
	declare @ver int
	declare @nick int
	declare @ccols int
	declare @partchange int
	declare @joinchange int
	declare @partgen int
	declare @joingen int
	declare	@partchangebm varbinary(500)
	declare @joinchangebm varbinary(500)
	declare @newgen int

	set nocount on
	select @newgen = gen_cur from sysmergearticles where nickname = ' + @tablenickchar + '
	if @newgen is null
		set @newgen = 0
	/* Use intrinsic funtion to set bits for updated columns */
	set @bm = columns_updated()
	set @missingbm = ' 
	
	select @command2 = '  

	/* See if the partition might have changed */
	if @partchangebm = 0x0
		set @partchange = 0
	else
		set @partchange= { fn INTERSECTBITMAPS (@bm, @partchangebm) }
	
	/* See if a column used in a join filter changed */
	if @joinchangebm = 0x0
		set @joinchange = 0
	else
		set @joinchange= { fn INTERSECTBITMAPS (@bm, @joinchangebm) }
	
	select @tablenick = ' + @tablenickchar + '
	exec dbo.sp_MSgetreplnick @nickname = @nick output
	select @ccols = ' + @ccolchar + '
	' + @cvstr1 + '
	if @joinchange = 1
		begin
		update ' + @viewname + ' set lineage = { fn UPDATELINEAGE(lineage, @nick) }, generation = @newgen, joinchangegen = @newgen, ' + @cvstr2 + ' where
			tablenick = @tablenick and rowguid in (select rowguidcol from inserted)
		if @@error <> 0
			GOTO FAILURE
		set @joingen = @newgen
		set @partgen = @newgen
		end
	else if @partchange = 1
		begin
		set @partgen = @newgen
		set @joingen = NULL
		update ' + @viewname + ' set lineage = { fn UPDATELINEAGE(lineage, @nick) }, generation = @newgen, partchangegen = @newgen, ' + @cvstr2 + ' where
			tablenick = @tablenick and rowguid in (select rowguidcol from inserted)
		if @@error <> 0
			GOTO FAILURE
		end
	else	
		begin
		set @partgen = NULL
		set @joingen = NULL
		update ' + @viewname + ' set lineage = { fn UPDATELINEAGE(lineage, @nick) }, generation = @newgen, ' + @cvstr2 + ' where
			tablenick = @tablenick and rowguid in (select rowguidcol from inserted)
		if @@error <> 0
			GOTO FAILURE
		end
	insert into ' + @viewname + ' (tablenick, rowguid, lineage, colv1, generation, partchangegen, joinchangegen) 
		select @tablenick, rowguidcol, @lineage, @cv, @newgen, @partgen, @joingen from inserted where
			rowguidcol not in (select rowguid from ' + @viewname + ' where tablenick = @tablenick)

	if @@error <> 0
		GOTO FAILURE
	return
FAILURE:
				if @@trancount > 0
					rollback tran
				raiserror (20041, 16, -1)
				return
					'
			
	execute (@command1 + @missingbmstr + '
		set @partchangebm = ' + @partchstr + '
		set @joinchangebm = ' + @joinchstr + '
			' + @ifcol +  
			@command2)
	if @@ERROR <> 0 
		begin
			raiserror(20064, 16, -1)
			return (1)
		end
	
	execute ('sp_MS_marksystemobject ''' + @trigname + '''')	
GO

exec dbo.sp_MS_marksystemobject sp_MSaddupdatetrigger
go

raiserror('Creating procedure sp_MSaddmergetriggers', 0,1)
GO
CREATE PROCEDURE sp_MSaddmergetriggers 
    @source_table 		sysname,		/* was type varchar(92), table name */
    @column_tracking 	int = NULL				/* Is column tracking on - default is FALSE */
AS
	set nocount on
	declare @command		nvarchar(4000)
	declare @ifcoltracking 	nvarchar(255)
	declare @tablenick 		int	
	declare @nickname 		int
	declare @artid 			uniqueidentifier
	declare @guidstr		nvarchar(32)
	declare @owner 			sysname
	declare @site 			sysname
	declare @db 			sysname
	declare @object 		sysname
	declare @updtrigname 		sysname
	declare @instrigname 		sysname
	declare @deltrigname 		sysname
	declare @ext 			nvarchar(10)
	declare @ext2 			nvarchar(10)
	declare @tablenickchar 	nvarchar(11)
	declare @ccols 			int
	declare @ccolchar 		nvarchar(5)
	declare @retcode 		int
	declare @objid			int
	declare @bitmap 		varbinary(40)
	declare @missing_count	int
	declare @viewname		sysname
	declare @tsview			sysname
	
	set @bitmap = 0x0
	set @missing_count = 0

    -- PARSENAME VARS
	declare  	@UnqualName      sysname  --rightmost name node
	declare  	@QualName1       sysname  
    -- END PARSENAME VARS


	execute @retcode=sp_MSgetreplnick @nickname = @nickname output
	if @retcode<>0 or @@ERROR<>0 return (1)

	select @ext = 'ins_'
	select @ext2 = 'del_'
	set @objid =  OBJECT_ID(@source_table)
	select @ccols =  count(*) from syscolumns where id = @objid  and iscomputed <> 1
	select @ccolchar = convert(nchar, @ccols)

    select @UnqualName = PARSENAME(@source_table, 1)
    select @QualName1 = PARSENAME(@source_table, 2)
    if @UnqualName IS NULL
         return 1

    if @QualName1 is NULL
 		select @QualName1 = user_name(uid) from sysobjects where id = object_id(@UnqualName)

	-- fixup for variable length differences.  remove when vars expanded
	-- to new SQL SERVER 7.0 lengths

	select @owner = @QualName1
	select @object = @UnqualName
		
	execute @retcode=sp_MStablenickname @owner, @object, @tablenick output
	if @retcode<>0 or @@ERROR<>0 return (1)
	select @artid = artid from sysmergearticles 
		where objid = @objid
		
	/* If column tracking wasn't passed in, just figure it out */
	if @column_tracking is null
		select @column_tracking = column_tracking from sysmergearticles 
		where artid = @artid
		
	select @tablenickchar = convert(nchar, @tablenick)
	exec @retcode=sp_MSguidtostr @artid, @guidstr out
	if @retcode<>0 or @@ERROR<>0 return (1)

	/* Drop the article's replication triggers if they preexist */
	exec dbo.sp_MSdroparticletriggers @source_table
	if @@ERROR <> 0
		return 1
	
	-- owner name removed
	set @instrigname = @ext + @guidstr 
	set @deltrigname = @ext2 + @guidstr
	set @updtrigname = 'upd_' + @guidstr
	set @viewname = 'ctsv_' + @guidstr
	set @tsview = 'tsvw_' + @guidstr
	
	/* Make sure trigger name is unique */
	exec @retcode=sp_MSuniqueobjectname @instrigname, @instrigname output
	if @retcode<>0 or @@ERROR<>0 return (1)
	exec @retcode=sp_MSuniqueobjectname @deltrigname, @deltrigname output
	if @retcode<>0 or @@ERROR<>0 return (1)
	exec @retcode=sp_MSuniqueobjectname @updtrigname, @updtrigname output
	if @retcode<>0 or @@ERROR<>0 return (1)

	/* Create the view if it doesn't already exist. */
	if not exists (select * from sysobjects where type = 'V' and name = @viewname)
		begin
		exec @retcode=sp_MSuniqueobjectname @viewname, @viewname output
		if @retcode<>0 or @@ERROR<>0 return (1)
		set @command = 'create view dbo.' + @viewname + ' as
			select * from MSmerge_contents where
				trigger_nestlevel(OBJECT_ID(''' + QUOTENAME(@owner) + '.'  + QUOTENAME(@instrigname) + ''')) > 0 or
				trigger_nestlevel(OBJECT_ID(''' + QUOTENAME(@owner) + '.'  + QUOTENAME(@updtrigname) + ''')) > 0 or
				trigger_nestlevel(OBJECT_ID(''' + QUOTENAME(@owner) + '.'  + QUOTENAME(@deltrigname) + ''')) > 0
				with check option'
		execute (@command)
		if @@ERROR<>0 return (1)
		set @command = 'grant update, insert, select, delete on ' + @viewname + ' to public'
		execute (@command)
		if @@ERROR<>0 return (1)
		execute ('sp_MS_marksystemobject ''' + @viewname + '''')	
		if @@ERROR<>0 return (1)	
		end

	/* Create the view if it doesn't already exist. */
	if not exists (select * from sysobjects where type = 'V' and name = @tsview)
		begin
		exec @retcode=sp_MSuniqueobjectname @tsview, @tsview output
		if @retcode<>0 or @@ERROR<>0 return (1)
		set @command = 'create view dbo. ' + @tsview + ' as
			select * from MSmerge_tombstone where
				trigger_nestlevel(OBJECT_ID(''' + QUOTENAME(@owner) + '.'  + QUOTENAME(@instrigname) + ''')) > 0 or
				trigger_nestlevel(OBJECT_ID(''' + QUOTENAME(@owner) + '.'  + QUOTENAME(@updtrigname) + ''')) > 0 or
				trigger_nestlevel(OBJECT_ID(''' + QUOTENAME(@owner) + '.'  + QUOTENAME(@deltrigname) + ''')) > 0
				with check option'
		execute (@command)
		if @@ERROR<>0 return (1)
		set @command = 'grant update, insert, select, delete on ' + @tsview + ' to public'
		execute (@command)
		if @@ERROR<>0 return (1)		
		execute ('sp_MS_marksystemobject ''' + @tsview + '''')	
		if @@ERROR<>0 return (1)	
		end
		
	/* If column tracking is on, construct the string to initialize colv's */
	if (@column_tracking <> 0)
		-- select @ifcoltracking = '	execute master..xp_initcolvs @ccols, @nickname, @colv1 output'
		select @ifcoltracking = '	set @colv1 = { fn INITCOLVS(@ccols, @nickname) }'
	else
		select @ifcoltracking = '	set @colv1 = NULL'
		
	/* UNDONE maybe remove null guid checks in SQL SERVER 7.0 */
	select @command = 'create trigger ' + @instrigname + ' on ' + @source_table +
	' for insert as 
	/* Declare variables */
	declare @tablenick int 
	declare @nickname int
	declare @lineage varbinary(255) 
	declare @colv1 varbinary(2048)
	declare @ccols int
	declare @retcode smallint
	declare @newgen int
	declare @version int
	declare @curversion int
	
	set nocount on
	set @tablenick = ' + @tablenickchar + '
	select @ccols = ' + @ccolchar + '
	set @lineage = 0x0
	set @retcode = 0
	select @newgen = gen_cur from sysmergearticles where nickname = @tablenick
	if @newgen is null
		set @newgen = 0
		
	execute dbo.sp_MSgetreplnick @nickname = @nickname output
	if (@@error <> 0)
		begin
		goto FAILURE
		end
	set @lineage = { fn UPDATELINEAGE (0x0, @nickname) }
	' + @ifcoltracking + '
	if (@@error <> 0)
		begin
		goto FAILURE
		end

	select @version = max(convert(int, substring(lineage, 5, 1)) + 256 * 
		(convert(int, substring(lineage, 6, 1)) +  256 *
	 	(convert(int, substring(lineage, 7, 1)) + 256 *
	  	(convert(int, substring(lineage, 8, 1)))))) from ' + @tsview + ' where tablenick = @tablenick and rowguid in
		(select rowguidcol from inserted)

	if @version is not null
		begin
		-- reset lineage and colv to higher version...
		set @curversion = 0
		while (@curversion <= @version)
			begin
			set @lineage = { fn UPDATELINEAGE (@lineage, @nickname) }
			if (@colv1 IS NOT NULL)
				set @colv1 = { fn UPDATECOLVBM(@colv1, @nickname, 0x01, 0x00) }
			set @curversion = @curversion + 1
			end
		
		delete from ' + @tsview + ' where tablenick = @tablenick and rowguid in
			(select rowguidcol from inserted)
		end
		
	insert into ' + @viewname + ' (tablenick, rowguid, lineage, colv1, generation, joinchangegen) select
		@tablenick, rowguidcol, @lineage, @colv1, @newgen, @newgen from inserted where rowguidcol not in
			(select rowguid from ' + @viewname + ' where tablenick = @tablenick)
	if @@error <> 0 
		goto FAILURE
	return
FAILURE:
				if @@trancount > 0
					rollback tran
				raiserror (20041, 16, -1)
				return
					'
	execute (@command)
	if @@ERROR <> 0 
		begin
			raiserror(20065, 16, -1)
			return (1)
		end
	
	execute ('sp_MS_marksystemobject ''' + @instrigname + '''')	

	/* Call separate routine to add update trigger */
	exec @retcode=sp_MSaddupdatetrigger @source_table, @owner, @object, @artid, @column_tracking, @viewname
	if @retcode<>0 or @@ERROR<>0 return (1)

	/* Now make the delete trigger */
	-- NOTE: owner name removed

	/* Make sure trigger name is unique */
	exec @retcode = dbo.sp_MSuniqueobjectname @deltrigname, @deltrigname output
	if @retcode<>0 or @@ERROR<>0 return (1)

	set @command = 'create trigger ' + @deltrigname + ' on ' + @source_table +
	' FOR DELETE AS
	/* Declare variables */
	declare @tablenick int
	declare @retcode smallint
	declare @reason nvarchar(255)
	declare @nickname int
	declare @lineage varbinary(255) 
	declare @newgen int
	
	set nocount on
	select @tablenick = ' + @tablenickchar + '
	select @newgen = gen_cur from sysmergearticles where nickname = @tablenick
	if @newgen is null
		set @newgen = 0

	select @reason = ''user delete''
	execute dbo.sp_MSgetreplnick @nickname = @nickname output
	if (@@error <> 0)
		begin
		goto FAILURE
		end

	set @lineage = { fn UPDATELINEAGE(0x0, @nickname) }
	set @lineage = { fn UPDATELINEAGE(@lineage, @nickname) }
	
	insert into ' + @tsview + ' (rowguid, tablenick, type, lineage, generation, reason)
		select rowguidcol, @tablenick, 1, @lineage, @newgen, @reason from deleted where
			rowguidcol not in (select rowguid from ' + @viewname + ' where tablenick = @tablenick)
	if @@error <> 0
		GOTO FAILURE
	/* Now get the ones that are in contents */
	insert into ' + @tsview + ' (rowguid, tablenick, type, lineage, generation, reason)
		select c.rowguid, @tablenick, 1, { fn UPDATELINEAGE(c.lineage, @nickname) }, @newgen, @reason from 
			deleted d, ' + @viewname + ' c where c.tablenick = @tablenick and c.rowguid = d.rowguidcol
	if @@error <> 0
		GOTO FAILURE
			
	delete from ' + @viewname + ' where tablenick = @tablenick and rowguid in 
		(select rowguidcol from deleted) 
	if @@error <> 0
		GOTO FAILURE
	return
FAILURE:
				if @@trancount > 0
					rollback tran
				raiserror (20041, 16, -1)
				return
				'
		
	execute (@command)
	if @@ERROR <> 0 
		begin
			raiserror(20066, 16, -1)
			return (1)
		end
	execute ('sp_MS_marksystemobject ''' + @deltrigname + '''')	

	update sysmergearticles set missing_col_count = @missing_count,
		missing_cols = @bitmap where artid = @artid
	if @@ERROR<>0 return (1)	
	return (0)
GO

exec dbo.sp_MS_marksystemobject sp_MSaddmergetriggers 
go
grant exec on dbo.sp_MSaddmergetriggers to public
go



raiserror('Creating procedure sp_MSmaptype', 0,1)
GO

create procedure sp_MSmaptype (@type nvarchar(60) output, 
								@len smallint, 
								@prec smallint, 
								@scale int)
as
	declare @typeout nvarchar(60)

select @typeout = case @type
	when 'binary' then 'varbinary'
	when 'char' then 'varchar'
	when 'nchar' then 'nvarchar'
	when 'datetimn' then 'datetime'
	when 'decimaln' then 'decimal'
	when 'floatn' then 'float'
	when 'intn' then 'int'
	when 'moneyn' then 'money'
	when 'numericn' then 'numeric'
	when 'timestamp' then 'varbinary'
	when 'bit' then 'tinyint'
	else @type  --for user defined data type which may contain space in between
	END
-- append length or scale and precision if needed
if (@typeout = 'varbinary' or @typeout = 'varchar' or @typeout = 'nvarchar')
	begin
	select @type = @typeout + '(' + rtrim(convert(nchar, @len)) + ')'
	return
	end
if (@typeout = 'numeric' or @typeout = 'decimal')
	begin
	select @type = @typeout + '(' + rtrim(convert(nchar, @prec)) + ',' + 
			rtrim(convert(nchar, @scale)) + ')'
	return
	end
select @type = @typeout
go

exec dbo.sp_MS_marksystemobject sp_MSmaptype 
go


dump tran master with no_log
go


checkpoint
go

set nocount on
go

execute dbo.sp_configure 'update',1
go
reconfigure with override
go

set ANSI_NULLS off
go

dump tran master with no_log
go

use master
go

/* 
** Drop the stored procedures in this script using the old dropping SP 
** and then drop itself
*/
if exists (select * from sysobjects
    where type = 'P '
            and name = 'sp_MSdrop_rladmin')
begin
    exec dbo.sp_MSdrop_rladmin
    drop procedure sp_MSdrop_rladmin
end

/*
** Create stored procedures to drop the stored procedures
** created by this script
*/

raiserror('Creating procedure sp_MSdrop_rladmin', 0,1)
GO
create procedure sp_MSdrop_rladmin
as

    if exists (select * from sysobjects
            where type in ('P ') 
                and name = 'sp_MSaddmergepub_snapshot')
        drop procedure sp_MSaddmergepub_snapshot


    if exists (select * from sysobjects
            where type in ('P ') 
                and name = 'sp_MScheckatpublisher')
        drop procedure sp_MScheckatpublisher    
    
    if exists (select * from sysobjects
            where type in ('P ') 
                and name = 'sp_MSdropmergepub_snapshot')
        drop procedure sp_MSdropmergepub_snapshot
    
    if exists (select * from sysobjects
            where type = 'P'
                and name = 'sp_addmergepublication')
        drop procedure sp_addmergepublication

    if exists (select * from sysobjects
        where type = 'P'
            and name = 'sp_changemergepublication')
        drop procedure sp_changemergepublication
    

    if exists (select * from sysobjects
            where type = 'P'
                and name = 'sp_helpmergepublication')
        drop procedure sp_helpmergepublication

    if exists (select * from sysobjects
            where type = 'P'
                and name = 'sp_MSpublicationview')
        drop procedure sp_MSpublicationview

     if exists (select * from sysobjects
                where type = 'P' and
                name = 'sp_reinitmergesubscription')
        drop procedure sp_reinitmergesubscription
        
    if exists (select * from sysobjects
            where type = 'P'
                and name = 'sp_MSdrop_expired_mergesubscription')
        drop procedure sp_MSdrop_expired_mergesubscription
    
    if exists (select * from sysobjects
        where type = 'P'
            and name = 'sp_dropmergepublication')
        drop procedure sp_dropmergepublication
    
    if exists (select * from sysobjects
            where type = 'P'
                and name = 'sp_addmergearticle')
        drop procedure sp_addmergearticle
    

    if exists (select * from sysobjects
        where type = 'P'
            and name = 'sp_changemergearticle')
        drop procedure sp_changemergearticle
    

    if exists (select * from sysobjects
        where type = 'P'
            and name = 'sp_helpmergearticle')
        drop procedure sp_helpmergearticle
    

    if exists (select * from sysobjects
        where type = 'P'
            and name = 'sp_dropmergearticle')
        drop procedure sp_dropmergearticle
    
    if exists (select * from sysobjects
        where type = 'P'
            and name = 'sp_addmergesubscription')
        drop procedure sp_addmergesubscription
    
    if exists (select * from sysobjects
        where type = 'P'
            and name = 'sp_changemergesubscription')
        drop procedure sp_changemergesubscription

    if exists (select * from sysobjects
        where type = 'P'
            and name = 'sp_helpmergesubscription')
        drop procedure sp_helpmergesubscription

    if exists (select * from sysobjects
        where type = 'P'
            and name = 'sp_dropmergesubscription')
        drop procedure sp_dropmergesubscription

    if exists (select * from sysobjects
        where type = 'P'
            and name = 'sp_helpmergefilter')
        drop procedure sp_helpmergefilter

    if exists (select * from sysobjects
        where type = 'P'
            and name = 'sp_changemergefilter')
        drop procedure sp_changemergefilter
    
    if exists (select * from sysobjects
        where type = 'P'
            and name = 'sp_addmergefilter')
        drop procedure sp_addmergefilter
    
    if exists (select * from sysobjects
        where type = 'P'
            and name = 'sp_dropmergefilter')
        drop procedure sp_dropmergefilter

    if exists (select * from sysobjects
            where type in ('P ') 
                and name = 'sp_MSmergepublishdb')
        drop procedure sp_MSmergepublishdb

    if exists (select * from sysobjects
            where type in ('P ') 
                and name = 'sp_helpallowmerge_publication')
        drop procedure sp_helpallowmerge_publication

    if exists (select * from sysobjects
            where type in ('P ') 
                and name = 'sp_enumcustomresolvers')
        drop procedure sp_enumcustomresolvers

    if exists (select * from sysobjects
            where type in ('P ') 
                and name = 'sp_MSenumpubreferences')
        drop procedure sp_MSenumpubreferences

    if exists (select * from sysobjects
        where type = 'P ' and name = 'sp_MSscript_dri')
    drop procedure sp_MSscript_dri
    
    if exists (select * from sysobjects
            where type in ('P ') 
                and name = 'sp_MSsubsetpublication')
        drop procedure sp_MSsubsetpublication
    if exists (select * from sysobjects
            where type = 'P'
                and name = 'sp_generatefilters')
        drop procedure sp_generatefilters
    if exists (select * from sysobjects
            where type = 'P'
                and name = 'sp_MSmakejoinfilter')
        drop procedure sp_MSmakejoinfilter
        go
    if exists (select * from sysobjects
            where type = 'P'
                and name = 'sp_MSmakeexpandproc')
        drop procedure sp_MSmakeexpandproc
        go
    if exists (select * from sysobjects
            where type = 'P'
                and name = 'sp_MSindexcolfrombin')
        drop procedure sp_MSindexcolfrombin

    if exists (select * from sysobjects
                where type = 'P' and
                name = 'sp_helpmergearticleconflicts')
        drop procedure sp_helpmergearticleconflicts

    if exists (select * from sysobjects
                where type = 'P' and
                name = 'sp_MShelpmergeconflictcounts')
        drop procedure sp_MShelpmergeconflictcounts

    if exists (select * from sysobjects
                where type = 'P' and
                name = 'sp_helpmergeconflictrows')
        drop procedure sp_helpmergeconflictrows

    if exists (select * from sysobjects
                where type = 'P' and
                name = 'sp_helpmergedeleteconflictrows')
        drop procedure sp_helpmergedeleteconflictrows

    if exists (select * from sysobjects
                where type = 'P' and
                name = 'sp_deletemergeconflictrow')
        drop procedure sp_deletemergeconflictrow

    if exists (select * from sysobjects
                where type = 'P' and
                name = 'sp_getmergedeletetype')
        drop procedure sp_getmergedeletetype

    if exists (select * from sysobjects
                where type = 'P' and
                name = 'sp_mergedummyupdate')
        drop procedure sp_mergedummyupdate

    if exists (select * from sysobjects
                where type = 'P' and
                name = 'sp_addtabletocontents')
        drop procedure sp_addtabletocontents

    if exists (select * from sysobjects
                where type = 'P' and
                name = 'sp_MSaddpubtocontents')
        drop procedure sp_MSaddpubtocontents

go

exec dbo.sp_MS_marksystemobject sp_MSdrop_rladmin
go

EXEC dbo.sp_MSdrop_rladmin
GO

raiserror('Creating procedure sp_MSaddmergepub_snapshot', 0,1)
GO

CREATE PROCEDURE sp_MSaddmergepub_snapshot (
    @publication            sysname,    
    @freqtype               int = 4 ,           /* 4== Daily */
    @freqinterval           int = 1,            /* Every day */
    @freqsubtype            int = 4,            /* Sub interval = Minute */
    @freqsubinterval        int = 5,            /* Every five minutes */
    @freqrelativeinterval   int = 1, 
    @freqrecurrencefactor   int = 0, 
    @activestartdate        int = 0,            /* 12:00 am - 11:59 pm */
    @activeenddate          int = 99991231 ,    /* No start date */ 
    @activestarttimeofday   int = 0,        
    @activeendtimeofday     int = 235959,       /* No end time */               
    @newtaskid              int = 0 OUTPUT
) AS

    SET NOCOUNT ON

    /*
    ** Declarations.
    */
    declare @retcode                int
    declare @distributor            sysname
    declare @dist_rpcname           sysname
    declare @distribdb              sysname
    declare @distproc               nvarchar(255)
    declare @taskname               nvarchar(100)
    declare @database               sysname
    declare @newid                  int
    declare @fFoundPublication      int
    declare @task_args              nvarchar(255)
    declare @command                nvarchar(255)
    declare @pubid                  uniqueidentifier
    declare @snapshot_jobid         binary(16)

    /*
    ** Initializations
    */
    select @fFoundPublication   = 0 

    EXEC @retcode = dbo.sp_helpmergepublication @publication, @fFoundPublication output, @pubid output

    if @@ERROR <> 0 OR @retcode <> 0
    BEGIN
        RETURN (1)
    END

    /* If the publication does not exist return error */
    if @fFoundPublication = 0 
    BEGIN
        RAISERROR (21040, 11, -1, @publication)
        RETURN (1)
    END

    /* 
    ** Make sure the publication does not already have a task.
    */
    if EXISTS (select * FROM MSmerge_replinfo WHERE repid = @pubid and snapshot_jobid IS NOT NULL)
    BEGIN
        RAISERROR (14101, 11, -1, @publication)
        RETURN(1)
    END

    /*
    ** Get distributor information
    */
    EXEC @retcode = dbo.sp_helpdistributor @distributor = @distributor OUTPUT, 
        @distribdb = @distribdb OUTPUT,
        @rpcsrvname = @dist_rpcname OUTPUT 
        if @@error <> 0 OR @retcode <> 0 or @distributor IS NULL OR @distribdb IS NULL
        BEGIN
            RAISERROR (14071, 16, -1)
            RETURN (1)
        END

    select @database = DB_NAME()

    select @task_args = '-Publisher ' + @@SERVERNAME
    select @task_args = @task_args + ' -PublisherDB ' + QUOTENAME(@database)
    select @task_args = @task_args + ' -Distributor ' + QUOTENAME(@distributor)
    select @task_args = @task_args + ' -Publication ' + QUOTENAME(@publication)
    select @task_args = @task_args + ' -ReplicationType 2'
    
    /* 
    ** Create task on distributor
    */
    SELECT @distproc = RTRIM(@dist_rpcname) + '.' + @distribdb + '.dbo.sp_MSadd_snapshot_agent'

    EXECUTE @retcode = @distproc 
        @publisher = @@SERVERNAME,
        @publisher_db = @database,
        @publication = @publication,  
        @publication_type = 2,          -- Merge type
        @local_job = 1,  
        @freqtype = @freqtype, 
        @freqinterval = @freqinterval, 
        @freqsubtype = @freqsubtype, 
        @freqsubinterval = @freqsubinterval, 
        @freqrelativeinterval = @freqrelativeinterval, 
        @freqrecurrencefactor = @freqrecurrencefactor, 
        @activestartdate = @activestartdate,
        @command = @task_args, 
        @snapshot_jobid = @snapshot_jobid OUTPUT 
   
   if @@ERROR <> 0 or @retcode <> 0
        RETURN(1)
    
    SELECT @newtaskid = 1

    UPDATE MSmerge_replinfo set snapshot_jobid = @snapshot_jobid WHERE repid = @pubid

    if @@ERROR <> 0 
        RETURN(1)
            
    return (0)
GO
exec dbo.sp_MS_marksystemobject sp_MSaddmergepub_snapshot
go

grant execute on dbo.sp_MSaddmergepub_snapshot to public
go


GO

raiserror('Creating procedure sp_MSdropmergepub_snapshot', 0,1)
GO

CREATE PROCEDURE sp_MSdropmergepub_snapshot (
    @publication sysname,
    @ignore_distributor bit = 0
) AS

    SET NOCOUNT ON

    /*
    ** Declarations.
    */
    declare @retcode            int
    declare @distributor        sysname
    declare @distproc           nvarchar(255)
    declare @snapshot_jobid     binary(16)
    declare @fFoundPublication  int
    declare @pubid              uniqueidentifier
    declare @distribdb          sysname

    /*
    ** Initializations
    */
    select @fFoundPublication   = 0

    /* validate the publication */
    /* If the publication is  not exist found return error */
    EXEC @retcode = dbo.sp_helpmergepublication @publication, @fFoundPublication output, @pubid output
    if @@ERROR <> 0 OR @fFoundPublication = 0 OR @retcode <> 0
    BEGIN
        RETURN (1)
    END

    /*
    ** Get taskid. Make sure the snapshot_jobid is not NULL only before using MAX
    ** Otherwise there will be a warnning.
    */
    select @snapshot_jobid = max(snapshot_jobid) FROM MSmerge_replinfo WHERE repid = @pubid
    
    if (@snapshot_jobid IS NOT NULL)        
    begin

    /*
    ** if @ignore_distributor = 1, we are in bruteforce cleanup mode, don't do RPC.
    */
    if @ignore_distributor = 0
        begin
            /*
            ** Get distributor information
            */
            EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
                @distribdb = @distribdb OUTPUT
                if @@error <> 0 OR @retcode <> 0
                BEGIN
                    RAISERROR (14071, 16, -1)
                    RETURN (1)
                END

            /*
            ** Delete sync agent of Publication.
            */
            declare @dbname sysname
            set @dbname = DB_NAME()
            SELECT @distproc = RTRIM(@distributor) + '.' + @distribdb + '.dbo.sp_MSdrop_snapshot_agent'
            EXECUTE @retcode = @distproc 
                @publisher = @@SERVERNAME,
                @publisher_db = @dbname,
                @publication = @publication

            IF @@ERROR <> 0 or @retcode <> 0
                RETURN(1)
        end


        /* Update publication's taskid */
        UPDATE MSmerge_replinfo set snapshot_jobid = NULL WHERE repid = @pubid
        IF @@ERROR <> 0
            BEGIN
            RAISERROR (20072, 16, -1)
            RETURN (1)
            END

    end
            
    return (0)      
GO 
exec dbo.sp_MS_marksystemobject sp_MSdropmergepub_snapshot 
go

grant execute on dbo.sp_MSdropmergepub_snapshot to public
go

raiserror('Creating procedure sp_MScheckatpublisher', 0,1)
GO

create procedure sp_MScheckatpublisher
    @pubid                  uniqueidentifier
    AS
    -- this routine will be called by sp_addmergearticle, sp_changemergearticle
    declare @db_name        sysname
    
    select @db_name =db_name from sysmergesubscriptions
        where (pubid=@pubid) and (subid=@pubid) 
        IF @db_name <> db_name() 
            RETURN 1
        ELSE 
            RETURN 0
            
go
exec dbo.sp_MS_marksystemobject sp_MScheckatpublisher
go

grant execute on dbo.sp_MScheckatpublisher to public
go
         
raiserror('Creating procedure sp_addmergearticle', 0,1)
GO

create procedure sp_addmergearticle
    @publication            sysname,                            /* publication name */
    @article                sysname,                            /* article name */
    @source_object          sysname,                            /* source object name */
    @type                   sysname = 'table',                  /* article type */
    @description            nvarchar(255)= NULL,                /* article description */
    @column_tracking        nvarchar(10) = 'false',             /* column level tracking */
    @status                 nvarchar(10) = 'unsynced',          /* unsynced, active */
    @pre_creation_cmd       nvarchar(10) = 'drop',              /* 'none', 'drop', 'delete', 'truncate' */
    @creation_script        nvarchar(255)= NULL,                /* article schema script */
    @schema_option          binary(8)   = 0x00000000000000f1,   /* article schema creation options */
    @subset_filterclause    nvarchar(2000) = '',                /* filter clause */
    @article_resolver       nvarchar(255)= NULL,                 /* custom resolver for article */
    @resolver_info          nvarchar(255) = NULL,                     /* custom resolver info */
    @source_owner           sysname = NULL
    AS

    set nocount on

    /*
    ** Declarations.
    */
    declare @resolver_info_len		int
    declare @sp_resolver			sysname
    declare @num_columns            smallint
    declare @pubid                  uniqueidentifier                /* Publication id */
    declare @db                     sysname
    declare @object                 sysname
    declare @owner                  sysname
    declare @destination_object     sysname
    declare @retcode                int
    declare @objid                  int
    declare @sync_objid             int
    declare @typeid                 smallint
    declare @nickname               int
    declare @merge_pub_object_bit int
    declare @column_tracking_id     int
    declare @cmd                    nvarchar(255)
    declare @statusid               tinyint
    declare @precmdid               int
    declare @resolver_clsid         nvarchar(50)
    declare @resolver_clsid_old     nvarchar(50)
    declare @tablenick              int
    declare @artid                  uniqueidentifier
    declare @distributor            sysname
    declare @distribdb              sysname
    declare @distproc               nvarchar(255)
    declare @dbname                 sysname
    declare @replinfo               int
    declare @db_name                sysname
    declare @subset                 int
    declare @row_size               int
    declare @sp_name				sysname
    declare @sp_owner				sysname
    declare @qualified_name         nvarchar(257)

    -- PARSENAME VARS
    declare     @UnqualName      nvarchar(258)  --rightmost name node
               ,@QualName1       nvarchar(258)  
               ,@QualName2       nvarchar(258)
    -- END PARSENAME VARS

    /*
    ** Initializations 
    */
    select @statusid        = 0
    select @resolver_clsid  = NULL
    select @subset          = 1     /* Const: publication type 'subset' */
    select @merge_pub_object_bit    = 128

    select @sp_resolver = 'Microsoft SQLServer Stored Procedure Resolver'
    
    if @source_owner is NULL
        begin
            select @source_owner = user_name(uid) from sysobjects where id = object_id(@source_object)
            if @source_owner is NULL  
                begin
                    raiserror (14027, 11, -1, @source_object)
                    return (1)
                end
        end
    select @qualified_name = QUOTENAME(@source_owner) + '.' + QUOTENAME(@source_object)
    
    /*
    ** Security Check
    */
    EXEC @retcode = dbo.sp_MSreplcheck_publish
    IF @@ERROR <> 0 or @retcode <> 0
        return (1)

    /*
    ** Parameter Check: @publication.
    ** The @publication id cannot be NULL and must conform to the rules
    ** for identifiers.
    */   
        
    if @publication is NULL
        begin
            raiserror (14043, 16, -1, '@publication')
            return (1)
        end

    select @pubid = pubid from sysmergepublications 
        where name = @publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()
    if @pubid is NULL
        begin
            raiserror (14027, 11, -1, @publication)
            return (1)
        end
    /*
    ** Only publisher can call sp_addmergearticle
    */
    EXEC @retcode = dbo.sp_MScheckatpublisher @pubid
    IF @@ERROR <> 0 or @retcode <>  0
        BEGIN
            RAISERROR (20073, 16, -1)
            RETURN (1)
        END
        
    select @sync_objid = id from sysobjects where id = OBJECT_ID(@qualified_name)
    if @sync_objid is NULL
        begin
            raiserror (14027, 11, -1, @qualified_name)
            return (1)
        end

    select @row_size=sum(length) from syscolumns where id=OBJECT_ID(@qualified_name)
    if @row_size>6000 
        begin
            RAISERROR (21062, 16, -1, @qualified_name)  
            -- RETURN (1)
        end

    select @num_columns=count(*) from syscolumns where id = object_id(@qualified_name)
    if @num_columns > 246
        begin
            RAISERROR (20068, 16, -1, @qualified_name, 246)
            RETURN (1)
        end

    /*
    ** Parameter Check: @article.
    ** Check to see that the @article is local, that it conforms
    ** to the rules for identifiers, and that it is a table, and not
    ** a view or another database object.
    */

    if @article is NULL
        begin
            raiserror (20045, 16, -1)
            return (1)
        end

	exec @retcode = dbo.sp_MSreplcheck_name @article
    if @@ERROR <> 0 or @retcode <> 0
        return(1)
        
    /*
    ** Merge does not really support destination object. It has the same value as source
    */
    select @destination_object = @source_object

    /*
    **  Get the id of the @qualified_name
    */
    select @objid = id, @replinfo = replinfo from sysobjects where id = OBJECT_ID(@qualified_name)
    if @objid is NULL
        begin
            raiserror (14027, 11, -1, @qualified_name)
            return (1)
        end

    /*
    ** If current publication contains a non-sync subscription, all articles to be added in it
    ** has to contain a rowguidcol.
    */
    if exists (select * from sysmergesubscriptions where pubid = @pubid and sync_type = 2)
        begin
            if not exists (select * from syscolumns c 
                where c.id=@objid and ColumnProperty(c.id, c.name, 'isrowguidcol') = 1)
                begin
                    raiserror(20085 , 16, -1, @article, @publication)
                    return (1)
                end
        end

    /*
    ** Make sure that the table name specified is a table and not a view.
    */

    if NOT exists (select * from sysobjects
        where id = (select OBJECT_ID(@qualified_name)) AND type = 'U')
        begin
            raiserror (20074, 16, -1)
            return (1)
        end

    /*
    ** Check that the underlying table has no timestamp columns.  If it does,
    ** return an appropriate error.
    */
    
    if EXISTS (SELECT * FROM syscolumns c WHERE c.id = @sync_objid
                AND type_name(c.xtype) = 'timestamp')
        BEGIN
            RAISERROR (20055, 16, -1, @qualified_name)
            RETURN (1)
        END
        
    /*
    ** Parameter Check:  @creation_script and @schema_option
    ** @schema_option cannot be null
    ** If @schema_option is 0, there have to be @creation_script defined.
    */
    IF @schema_option IS NULL
    BEGIN
        select @schema_option  = 0x00000000000000f1
    END

    /*
    ** Set the typeid.  The default type is table.  Anything else is
    ** currently undefined (reserved for future use).
    **
    **      @typeid     type
    **      =======     ========
    **          1       table
    ** UNDONE - message
    */

    IF LOWER(@type) NOT IN ('table')
       BEGIN
            RAISERROR (20074, 16, -1)
            RETURN (1)
       END

    IF LOWER(@type) = 'table'
       SET @typeid = 0x0a

    /*
    ** Validate the column tracking
    */
    if @column_tracking IS NULL OR LOWER(@column_tracking) NOT IN ('true', 'false')
        BEGIN
            RAISERROR (14148, 16, -1, '@column_tracking')
            RETURN (1)
        END
    if LOWER(@column_tracking) = 'true' 
        SET @column_tracking_id = 1
    else 
        SET @column_tracking_id = 0

    /*
    ** Get the pubid.
    */
    SELECT @pubid = pubid FROM sysmergepublications 
        WHERE name = @publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()
    if @pubid is NULL
        begin
            raiserror (14027, 11, -1, @publication)
            return (1)
        end

    /*
    ** Parameter Check:  @article, @publication.
    ** Check if the article already exists in this publication.
    */

    IF EXISTS (SELECT *
                 FROM sysmergearticles
                WHERE pubid = @pubid
                  AND name = @article)
        BEGIN
            RAISERROR (14030, 16, -1, @article, @publication)
            RETURN (1)
        END
        
    execute @retcode = dbo.sp_MSgetreplnick @pubid = @pubid, @nickname = @nickname output
    if (@@error <> 0) or @retcode <> 0 or @nickname IS NULL 
        begin
        RAISERROR (14055, 11, -1)
        RETURN(1)
        end                 

    /*
    ** Set the precmdid.  The default type is 'drop'.
    **
    **      @precmdid   pre_creation_cmd
    **      =========   ================
    **            0     none
    **          1     drop
    **          2     delete
    **          3     truncate
    */
    IF LOWER(@pre_creation_cmd) NOT IN ('none', 'drop', 'delete', 'truncate')
       BEGIN
          RAISERROR (14061, 16, -1)
          RETURN (1)
       END

    /*
    ** Determine the integer value for the pre_creation_cmd.
    */
    IF LOWER(@pre_creation_cmd) = 'none'
       select @precmdid = 0
    ELSE IF LOWER(@pre_creation_cmd) = 'drop'
       select @precmdid = 1
    ELSE IF LOWER(@pre_creation_cmd) = 'delete'
       select @precmdid = 2
    ELSE IF LOWER(@pre_creation_cmd) = 'truncate'
       select @precmdid = 3

    /*
    ** Validate the article resolver
    */
    if @article_resolver IS NOT NULL
        begin
            if @article_resolver = 'default' OR @article_resolver = ''
                begin
                    select @article_resolver = NULL
                    select @resolver_clsid = NULL
                end                 
            else
                begin
                    /*
                    ** Get the distributor info
                    */
                    EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT
                    IF @@error <> 0 OR @retcode <> 0 OR @distributor IS NULL
                        BEGIN
                            RAISERROR (20036, 16, -1)
                            RETURN (1)
                    END
                    select @distproc = RTRIM(@distributor) + '.master.dbo.xp_regread'
                    EXECUTE @retcode = @distproc 'HKEY_LOCAL_MACHINE',
                                  'SOFTWARE\Microsoft\MSSQLServer\Replication\ArticleResolver',
                                  @article_resolver,
                                  @param = @resolver_clsid  OUTPUT

                    IF @retcode <> 0 or @resolver_clsid IS NULL
                        BEGIN
                          RAISERROR (20020, 16, -1)
                          RETURN (1)
                        END
                end
        end

		/*
		** If article resolver is 'SP resolver', make sure that resolver_info refers to an SP or XP;
		** Also make sure it is stored with owner qualification
		*/
		if  @article_resolver = @sp_resolver
			begin
				if not exists (select * from sysobjects where id = object_id(@resolver_info) and ( type = 'P' or type = 'X'))
					begin
						select @resolver_info_len = datalength(@resolver_info)
						raiserror(2812, 16, -1, @resolver_info_len, @resolver_info)
						return (1)
					end
					
				select @sp_name = name, @sp_owner=user_name(uid) from sysobjects where id = object_id(@resolver_info)
				select @resolver_info = QUOTENAME(@sp_owner) + '.' + QUOTENAME(@sp_name) 
			end
    /*
    ** Validate the resolver procedure for the article - should be either a stored proc or an extended procedure.
    */
    if @resolver_info IS NOT NULL
        begin
            /*
            ** Get the distributor info
            */
            EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT
            IF @@error <> 0 OR @retcode <> 0 OR @distributor IS NULL
                BEGIN
                    RAISERROR (20036, 16, -1)
                    RETURN (1)
            END
            select @distproc = RTRIM(@distributor) + '.master.dbo.xp_regread'
            /* Don't force different resolver than one that was passed in. */
        end             


    /*
    **  Add article to sysmergearticles and update sysobjects category bit.
    */
    begin tran
    save TRAN sp_addmergearticle
        select @artid = artid from sysmergearticles where objid = OBJECT_ID(@qualified_name)
        select @statusid = 1  /*default status is inactive */
        if @artid is NULL
            begin
                set @artid = newid()
                if @@ERROR <> 0
                    goto FAILURE
                execute @retcode = dbo.sp_MSgentablenickname @tablenick output, @nickname, @objid
                if @@ERROR <> 0 OR @retcode <> 0
                    goto FAILURE
            end
        /* Clone the article properties if article has already been published (in a different pub) */
        else
            begin
            /*
            ** Parameter Check:  @article, @publication.
            ** Check if the table already exists in this publication.
            */
            if exists (select * from sysmergearticles
                where pubid = @pubid AND artid = @artid)
                begin
                    raiserror (14030, 16, -1, @article, @publication)
                    goto FAILURE
                end
            
            /* Make sure that coltracking option matches */
            if exists (select * from sysmergearticles where artid = @artid and
                         column_tracking <> @column_tracking_id)
                begin
                    raiserror (20030, 16, -1, @article)
                    goto FAILURE
                end

            /* Reuse the article nickname if article has already been published (in a different pub)*/
            select @tablenick = nickname from sysmergearticles where artid = @artid
            if @tablenick IS NULL
                goto FAILURE
                
            /* Make sure that @resolver_clsid matches the existing resolver_clsid */
            select @resolver_clsid_old = resolver_clsid from sysmergearticles where artid = @artid 
            if ((@resolver_clsid IS NULL AND @resolver_clsid_old IS NOT NULL) OR
                (@resolver_clsid IS NOT NULL AND @resolver_clsid_old IS NULL) OR
                (@resolver_clsid IS NOT NULL AND @resolver_clsid_old IS NOT NULL AND @resolver_clsid_old <> @resolver_clsid))
                begin
                    raiserror (20037, 16, -1, @article)
                    goto FAILURE
                end

            /* Insert to articles, copying some stuff from other article row */
            set rowcount 1
            insert into sysmergearticles (name, type, objid, sync_objid, artid, description,
                    pre_creation_command, pubid, nickname, column_tracking, status,
                    conflict_table, creation_script, conflict_script, article_resolver,
                    resolver_clsid, ins_conflict_proc, schema_option, 
                    destination_object, subset_filterclause, view_type, resolver_info, gen_cur)
                -- use top 1, distinct could return more than one matching row if status different on partitioned articles
                select top 1 @article, type, objid, @sync_objid, @artid, @description, @precmdid,
                    @pubid, nickname, column_tracking, 1, conflict_table, @creation_script,
                    conflict_script, article_resolver, resolver_clsid, ins_conflict_proc,
                    @schema_option, @destination_object, @subset_filterclause, 0, resolver_info, gen_cur
                    from sysmergearticles where artid = @artid
            set rowcount 0

            /* Jump to end of transaction  */
            goto DONE_TRAN
            end

        /* Add the specific GUID based replication columns to sys articles */
        insert sysmergearticles (name, objid, sync_objid, artid, type, description, pubid, nickname, 
                column_tracking, status, schema_option, pre_creation_command, destination_object, 
                article_resolver, resolver_clsid, subset_filterclause, view_type, resolver_info)
        values (@article, @objid, @sync_objid, @artid, @typeid, @description, @pubid, @tablenick, 
                @column_tracking_id, @statusid, @schema_option, @precmdid, @destination_object, 
                @article_resolver, @resolver_clsid, @subset_filterclause, 0, @resolver_info)
        if @@ERROR <> 0
            goto FAILURE

        exec @retcode = dbo.sp_replupdateschema @qualified_name
        if @@ERROR <> 0 or @retcode <> 0
            goto FAILURE
        update sysobjects set replinfo = (replinfo | @merge_pub_object_bit) where id = @objid
        if @@ERROR <> 0
            goto FAILURE
        /* Make a generation */
        execute @retcode = dbo.sp_MSmakegeneration 
        if @@ERROR <> 0 
            goto FAILURE

                /* If the article status is active then publish the user tables */
        if @status = 'active'
            begin
                /* Get a holdlock on the underlying table */
                select @cmd = 'select * into #tab1 from '
                select @cmd = @cmd + @qualified_name 
                select @cmd = @cmd + '(TABLOCK HOLDLOCK) where 1 = 2 '
                execute(@cmd)

                /* Add the guid column to the user table */
                execute @retcode = dbo.sp_MSaddguidcolumn @source_owner, @source_object
                if @@ERROR <> 0 OR  @retcode <> 0  -- NOTE: new change
                    goto FAILURE

                /* Create an index on the rowguid column in the user table */
                execute @retcode = dbo.sp_MSaddguidindex @source_owner, @source_object
                if @@ERROR <> 0 OR @retcode <> 0
                    goto FAILURE

                /* Create the merge triggers on the base table */
                execute @retcode = dbo.sp_MSaddmergetriggers @qualified_name, @column_tracking_id
                if @@ERROR <> 0 OR @retcode <> 0
                    goto FAILURE 

                /* Create the merge insert/update stored procedures for the base table */
                execute @retcode = dbo.sp_MSsetartprocs @publication, @article
                if @@ERROR <> 0 OR @retcode <> 0
                    goto FAILURE

                /* Set the article status to be active so that Snapshot does not do this again */
                select @statusid = 2 /* Active article */
                update sysmergearticles set status = @statusid where artid = @artid
                if @@ERROR <> 0 
                    goto FAILURE
            end
        
DONE_TRAN:
        /*
        ** For articles with subset filter clause - set the pub type to subset
        */
        if len(@subset_filterclause) > 0
            begin
                execute @retcode = dbo.sp_MSsubsetpublication @publication
                if @@ERROR <> 0 or @retcode<>0
                    goto FAILURE
            end                     
        /*
        ** Get distribution server information for remote RPC call.
        */
        EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
           @distribdb   = @distribdb OUTPUT
        IF @@ERROR <> 0 or @retcode <> 0
            BEGIN
                goto FAILURE
            END

        SELECT @dbname =  DB_NAME()
        
        SELECT @distproc = RTRIM(@distributor) + '.' + @distribdb + 
            '.dbo.sp_MSadd_article'
        EXECUTE @retcode = @distproc
            @publisher = @@SERVERNAME,
            @publisher_db = @dbname,
            @publication = @publication,
            @article = @article,
            @destination_object = @destination_object,
            @source_owner = @source_owner,
            @source_object = @source_object,
            @description = @description
            -- @article_id = NULL
        IF @@ERROR <> 0 or @retcode <> 0
            BEGIN
                goto FAILURE
            END

        COMMIT TRAN 

        /* If the article status is active adding the merge triggers to the base table */
         
        return (0)
FAILURE:
        RAISERROR (20009, 16, -1, @article, @publication)
        if @@TRANCOUNT > 0
        begin
            ROLLBACK TRANSACTION sp_addmergearticle
            COMMIT TRANSACTION
        end
        return (1)
go

exec dbo.sp_MS_marksystemobject sp_addmergearticle
go

grant execute on dbo.sp_addmergearticle to public
go

raiserror('Creating procedure sp_changemergearticle', 0,1)
GO

CREATE PROCEDURE sp_changemergearticle (
    @publication sysname,              /* Publication name */
    @article sysname,              /* Article name */
    @property sysname = NULL,          /* The property to change */
    @value nvarchar(2000) = NULL             /* The new property value */
    ) AS

    SET NOCOUNT ON

    /*
    ** Declarations.
    */
	declare @resolver_info_len	int
    declare @sp_resolver			sysname
    declare @db_name            sysname
    declare @artid              uniqueidentifier
    declare @pubid              uniqueidentifier
    declare @artidstr           nvarchar(38)
    declare @pubidstr           nvarchar(38)
    declare @object             sysname
    declare @owner              sysname
    declare @resolver_clsid     nvarchar(50)
    declare @article_resolver   nvarchar(255)
    declare @retcode            int
    declare @statusid           int
    declare @precmdid           tinyint
    declare @regkey             nvarchar(255)
    declare @distributor        sysname
    declare @distproc           nvarchar(255)
    
    declare @schemaversion      int 
    declare @schemaguid         uniqueidentifier
    declare @schematype         int
    declare @schematext         nvarchar(2000)

    /*
    ** Security Check
    */
    EXEC @retcode = dbo.sp_MSreplcheck_publish
    IF @@ERROR <> 0 or @retcode <> 0
        return (1)

    /*
    ** Check to see if the database has been activated for publication.
    */

    if (select category & 4
          FROM master..sysdatabases
         WHERE name = DB_NAME()) = 0

    BEGIN
        RAISERROR (14013, 16, -1)
        RETURN (1)
    END

    select @pubid = pubid from sysmergepublications 
        where name = @publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()
    if @pubid is NULL
        begin
            raiserror (14027, 11, -1, @publication)
            return (1)
        end


    select @db_name = db_name from sysmergesubscriptions
        where (pubid=@pubid) and (subid=@pubid)
        IF @db_name <> db_name()
        BEGIN
            RAISERROR (20047, 16, -1)
            RETURN (1)
        END

    /*
    ** Parameter Check:  @property.
    ** If the @property parameter is NULL, print the options.
    */

    if @property IS NULL
        BEGIN
            CREATE TABLE #tab1 (properties sysname)
            INSERT INTO #tab1 VALUES ('description')
            INSERT INTO #tab1 VALUES ('pre_creation_command')
            INSERT INTO #tab1 VALUES ('creation_script')
            INSERT INTO #tab1 VALUES ('column_tracking')
            INSERT INTO #tab1 VALUES ('article_resolver')
            INSERT INTO #tab1 VALUES ('resolver_info')
            INSERT INTO #tab1 VALUES ('status')
            INSERT INTO #tab1 VALUES ('subset_filterclause')
            INSERT INTO #tab1 VALUES ('schema_option')

            
            select * FROM #tab1
            RETURN (0)
        END

    /*
    ** Parameter Check:  @property.
    ** Check to make sure that @property is a valid property in
    ** sysmergearticles.
    */
    if @property IS NULL OR LOWER(@property) NOT IN ('name',
                                                     'description',
                                                     'pre_creation_command',
                                                     'creation_script',
                                                     'column_tracking',
                                                     'article_resolver',    
                                                     'resolver_info',
                                                     'status',
                                                     'subset_filterclause',
                                                     'schema_option')

        BEGIN
            RAISERROR (20019, 16, -1)
            RETURN (1)
        END


    /*
    ** Parameter Check:  @publication.
    ** Make sure that the publication exists.
    */

    if @publication IS NULL
        BEGIN
            RAISERROR (14043, 16, -1, '@publication')
            RETURN (1)
        END


    select @pubid = pubid from sysmergepublications 
        where name = @publication  and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()
    if @pubid IS NULL
        BEGIN
            RAISERROR (20026, 16, -1, @publication)
            RETURN (1)
        END

    /*
    ** Check to see that the article exists in sysmergearticles.
    ** Fetch the article identification number.
    */

    if @article IS NULL
        BEGIN
            RAISERROR (14043, 16, -1, '@article')
            RETURN (1)
        END


    select @artid = artid FROM sysmergearticles
        WHERE name = @article AND pubid = @pubid
    if @artid IS NULL
        BEGIN
            RAISERROR (20027, 16, -1, @article)
            RETURN (1)
        END

    set @artidstr = '''' + convert(nchar(36), @artid) + '''' 
    set @pubidstr = '''' + convert(nchar(36), @pubid) + '''' 
    select @sp_resolver = 'Microsoft SQLServer Stored Procedure Resolver'

    /*
    ** Change the property.
    */
    if LOWER(@property) = 'column_tracking'
        BEGIN
            /*
            ** This property can be modified for articles belonging to publications that are not active.
            */
            if EXISTS (select status FROM sysmergearticles WHERE artid = @artid AND status = 2)
                BEGIN
                    RAISERROR (20043, 16, -1, @article)
                    RETURN (1)
                END

            /*
            ** Check to make sure that we have a valid type.
            */
            if LOWER(@value) NOT IN ('true', 'false')
                BEGIN
                    RAISERROR (14137, 16, -1)
                    RETURN (1)
                END

            /*
            ** Update the syssubsetdefintions table with the new column tracking.
            */
            if LOWER(@value) = 'true'
                    update sysmergearticles set column_tracking = 1 where artid=@artid      
            else
                    update sysmergearticles set column_tracking = 0 where artid=@artid
            if @@ERROR <> 0 
                RETURN (1)

        END

     if LOWER(@property)='description'
        BEGIN
        UPDATE sysmergearticles  SET description = @value WHERE artid = @artid and pubid = @pubid
            AND pubid = @pubid
        if @@ERROR <> 0 
                RETURN (1)
    END

    if LOWER(@property) ='creation_script'
        BEGIN
            update sysmergearticles set creation_script=@value where artid=@artid and pubid=@pubid
            if @@ERROR <> 0 
                RETURN (1)
        END

    if LOWER(@property) = 'subset_filterclause'
        BEGIN
            /*
            ** This property can be modified for articles belonging to publications that are not active.
            */
            if EXISTS (select status FROM sysmergearticles WHERE artid = @artid AND pubid = @pubid AND status = 2)
                BEGIN
                    RAISERROR (20043, 16, -1, @article)
                    RETURN (1)
                END

            update sysmergearticles set subset_filterclause = @value where artid=@artid and pubid=@pubid
            if @@ERROR<>0 return (1)
            
            /*
            ** set the pub type to subset or full as appropriate
            */
            execute @retcode = dbo.sp_MSsubsetpublication @publication
            if @@ERROR <> 0 OR @retcode <> 0
                RETURN (1)
                
        END

    if LOWER(@property) ='article_resolver'
        BEGIN

            if @value IS NULL OR @value = 'default' OR @value = ''
                begin
                    set @article_resolver = NULL
                    set @resolver_clsid = NULL
                end                 
                    
            else
                begin
                    EXECUTE @retcode = master.dbo.xp_regread 'HKEY_LOCAL_MACHINE',
                                      'SOFTWARE\Microsoft\MSSQLServer\Replication\ArticleResolver',
                                      @value,
                                      @param = @resolver_clsid OUTPUT
                    IF @@ERROR <> 0 or @retcode <> 0 or @resolver_clsid IS NULL
                        BEGIN
                            RAISERROR (20020, 16, -1)
                            RETURN (1)
                        END
                end                     
                    
            /*
            ** Update the appropriate column in sysmergearticles with the new article resolver name.
            ** Note this could affect multiple publication if the same table spans publications
            */

            /* NOTE: new change */
            
            begin tran
            save TRANSACTION change_article  
                exec @retcode = dbo.sp_MSchangearticleresolver @value, @resolver_clsid, @artid
                if @@ERROR <> 0 OR @retcode <> 0
                    begin
                        if @@TRANCOUNT > 0 
                        begin
                            ROLLBACK TRANSACTION change_article
                            COMMIT TRANSACTION
                        end
                        RETURN (1)                          
                    end  
                
                declare one_pub CURSOR LOCAL FAST_FORWARD FOR 
                    select DISTINCT pubid from sysmergearticles where artid=@artid
                FOR READ ONLY
                open one_pub
                fetch next from one_pub into @pubid
                 
                while (@@fetch_status <> -1)
                    begin
                        select @schemaversion = schemaversion from sysmergeschemachange
                        if (@schemaversion is NULL) set @schemaversion = 1
                        else  
                            select @schemaversion = 1 + max(schemaversion) from sysmergeschemachange
                        set @schemaguid = newid()
                        set @schematype = 8
                        if @value is not NULL and @value <> ''
                            select @schematext = 'exec dbo.sp_MSchangearticleresolver ' + '''' + @value + '''' + ',' + '''' + @resolver_clsid + '''' + ',' + '''' + convert(nchar(36), @artid) + ''''
                        else
                            select @schematext = 'exec dbo.sp_MSchangearticleresolver NULL, NULL,' + '''' + convert(nchar(36), @artid) + ''''
                             
                        exec @retcode = dbo.sp_MSinsertschemachange @pubid, @artid, @schemaversion, @schemaguid, @schematype, @schematext 
                            if @@ERROR <> 0 OR @retcode <> 0
                                begin
                                    if @@TRANCOUNT > 0
                                    begin
                                        ROLLBACK TRANSACTION change_article
                                        COMMIT TRANSACTION
                                    end
                                    RETURN (1)                          
                                end
                        fetch next from one_pub into @pubid
                    end 
                close one_pub
                deallocate one_pub
            COMMIT TRANSACTION   

        END /* for property = 'article_resolver' */


    if LOWER(@property) ='resolver_info'
        BEGIN
	        /* allow non-sp's as resolver info; don't change the resolver class */
            select @article_resolver = article_resolver, @resolver_clsid = resolver_clsid from
                    sysmergearticles where artid = @artid

             -- Use empty string for nulls so that schema text won't be null
             if @article_resolver is null set @article_resolver = ''
             if @resolver_clsid is null set @resolver_clsid = ''
             if @value is null set @value = ''

		if  @article_resolver = @sp_resolver
			begin
				if not exists (select * from sysobjects where id = object_id(@value) and ( type = 'P' or type = 'X'))
					begin
						select @resolver_info_len = datalength(@value)
						raiserror(2812, 16, -1, @resolver_info_len, @value)
						return (1)
					end
			end
                    
            /*
            ** Update the appropriate column in sysmergearticles with the new resolver info.
            ** Note this could affect multiple publication if the same table spans publications
            */
            BEGIN TRANSACTION   
                exec @retcode = dbo.sp_MSchangearticleresolver @article_resolver, @resolver_clsid, @artid, @value
                if @@ERROR <> 0 OR @retcode <> 0
                    begin
                        if @@TRANCOUNT > 0
                        begin
                            ROLLBACK TRANSACTION change_article
                            COMMIT TRANSACTION
                        end
                        RETURN (1)                          
                    end         
                declare one_pub CURSOR LOCAL FAST_FORWARD FOR 
                    select DISTINCT pubid from sysmergearticles where artid=@artid
                FOR READ ONLY
                open one_pub
                fetch next from one_pub into @pubid
                 
                while (@@fetch_status <> -1)
                    begin
                        select @schemaversion = schemaversion from sysmergeschemachange
                        if (@schemaversion is NULL) set @schemaversion = 1
                        else  
                            select @schemaversion = 1 + max(schemaversion) from sysmergeschemachange
                        set @schemaguid = newid()
                        set @schematype = 8
                        select @schematext = 'exec dbo.sp_MSchangearticleresolver ' + '''' + @article_resolver + '''' + ',' + '''' + @resolver_clsid + '''' + ',' + '''' + convert(nchar(36), @artid) + '''' + ',' + '''' + @value + ''''
                         
                        exec @retcode = dbo.sp_MSinsertschemachange @pubid, @artid, @schemaversion, @schemaguid, @schematype, @schematext 
                            if @@ERROR <> 0 OR @retcode <> 0
                                begin
                                    if @@TRANCOUNT = 1 
                                        ROLLBACK TRANSACTION 
                                    else
                                        COMMIT TRANSACTION 
                                    RETURN (1)                          
                                end
                        fetch next from one_pub into @pubid
                    end 
                close one_pub
                deallocate one_pub
            COMMIT TRANSACTION    

        END /* for property = 'resolver_info' */


    if LOWER(@property) = 'pre_creation_command'
        BEGIN

            /*
            ** Check to make sure that we have a valid pre_creation_cmd.
            */

            if LOWER(@value) NOT IN ('none', 'drop', 'delete', 'truncate')
                BEGIN
                    RAISERROR (14061, 16, -1)
                    RETURN (1)
                END

            /*
            ** Determine the integer value for the pre_creation_cmd.
            */

            if LOWER(@value) = 'none'
                select @precmdid = 0
            else if LOWER(@value) = 'drop'
                select @precmdid = 1
            else if LOWER(@value) = 'delete'
                select @precmdid = 2
            else if LOWER(@value) = 'truncate'
                select @precmdid = 3

            /*
            ** Update the article with the new pre_creation_cmd.
            */
            UPDATE sysmergearticles
                SET pre_creation_command = @precmdid
                WHERE artid = @artid
                AND pubid = @pubid

            if @@ERROR <> 0 
                RETURN (1)

        END

    if LOWER(@property) = 'status'
        BEGIN

            /*
            ** Check to make sure that we have a valid status
            */

            if LOWER(@value) NOT IN ('active', 'unsynced')
                BEGIN
                    RAISERROR (20075, 16, -1)
                    RETURN (1)
                END

            /*
            ** Determine the integer value for the type.
            */

            if LOWER(@value) = 'unsynced'
                select @statusid = 1
            else if LOWER(@value) = 'active'
                select @statusid = 2

            /*
            ** Update the article with the new type. The same base table might be 
            ** in multiple publications - so qualify  with pubid.
            */
            UPDATE sysmergearticles
                SET status = @statusid
                WHERE artid = @artid and pubid = @pubid

            if @@ERROR <> 0 
                RETURN (1)

        END

    IF LOWER(@property) = 'schema_option'
        BEGIN
        
            IF @value IS NULL
                BEGIN
                    RAISERROR(14146, 16,1)
                    RETURN (1)
                END

            CREATE TABLE #tab_changearticle (value binary(8) NULL)
                                 
            IF @@ERROR <> 0 
                BEGIN
                    RETURN (1)
                END

            EXEC ('insert #tab_changearticle values (' + 
                    @value +')' )
                                 
            IF @@ERROR <> 0 
                BEGIN
                    RETURN (1)
                END
                      
            UPDATE sysmergearticles SET schema_option = tab.value from 
                #tab_changearticle tab 
                WHERE artid = @artid
                AND pubid = @pubid
            if @@ERROR <> 0
                BEGIN
                DROP TABLE #tab_changearticle 
                RETURN (1)
                END
                
            DROP TABLE #tab_changearticle 
                                 
            IF @@ERROR <> 0 
                BEGIN
                    RETURN (1)
                END

        END


    /*
    ** Return succeed.
    */

    RETURN (0)
go
exec dbo.sp_MS_marksystemobject sp_changemergearticle
go

grant execute on dbo.sp_changemergearticle to public
go

/*
** This SP is called to see if merge publication is still allowed for current database.
** Merge publishing is disallowed if current DB subscribes as local/anonymous subscriber
** 1 means OK, 0 for publication not allowed.
*/
raiserror('Creating procedure sp_helpallowmerge_publication', 0,1)
GO

CREATE PROCEDURE sp_helpallowmerge_publication 
AS
declare @srvid      int
declare @db_name    sysname

/* Select srvid = 0 for the local server name */
select @srvid = 0
select @db_name = db_name()
if exists (select name from sysobjects where name='sysmergesubscriptions')
    if exists (select priority from sysmergesubscriptions where db_name=@db_name and srvid = @srvid and priority=0)
        begin
            select 0
            RETURN (0)
        end
select 1
GO
exec dbo.sp_MS_marksystemobject sp_helpallowmerge_publication 
go

raiserror('Creating procedure sp_helpmergearticle', 0,1)
GO

CREATE PROCEDURE sp_helpmergearticle (
    @publication sysname = '%',   /* The publication name */
    @article sysname = '%'        /* The article name */
    ) AS

    SET NOCOUNT ON

    /*
    ** Declarations.
    */
    declare @retcode            int


    /*
    ** Running sp_help is OK from everywhere, whether enabled for publishing or not
    */
    IF not exists (select * from sysobjects where name= 'sysmergesubscriptions')
        RETURN (0)

    /*
    ** Security Check. To public.
    */
    

    /*
    ** Parameter Check:  @publication.
    ** Check to make sure that the publication exists, that it conforms
    ** to the rules for identifiers, and that it isn't NULL.
    */

    if @publication IS NULL
        BEGIN
            RAISERROR (14043, 16, -1, '@publication')
            RETURN (1)
        END

   /*
    ** Create a temporary table to hold all information.
    */
    create table #helpmergearticle
        (
            id                      int             identity NOT NULL,
            name                    sysname         NOT NULL,
            source_owner            sysname         NOT NULL,
            source_object           sysname         NOT NULL,      /* converted from objid */
            sync_object_owner       sysname         NOT NULL,
            sync_object             sysname         NOT NULL,      /* converted from sync_objid */
            description             nvarchar(255)   NULL,
            status                  tinyint         NULL,
            creation_script         nvarchar(127)   NULL,
            conflict_table          nvarchar(258)   NULL,
            article_resolver        nvarchar(255)   NULL,
            subset_filterclause     nvarchar(2000)  NULL,
            pre_creation_command    tinyint         NULL, 
            schema_option           binary(8)       NULL,
            type                    tinyint         NULL,
            column_tracking         int             NOT NULL,
            resolver_info           nvarchar(255)   NULL
        )
        
    if @publication <> '%'
        BEGIN
            if NOT EXISTS (select pubid 
                                FROM sysmergepublications
                                WHERE name = @publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name())
                BEGIN
                    RAISERROR (20026, 16, -1, @publication)
                    RETURN (1)
                END

        END

    /*
    ** Parameter Check:  @article.
    ** Check to make sure that the article exists, that it conforms
    ** to the rules for identifiers, and that it isn't NULL.
    */

    if @article IS NULL
        BEGIN
            RAISERROR (14043, 16, -1, '@article')
            RETURN (1)
        END

    if @article <> '%'
        BEGIN
            if NOT EXISTS (select *
                           FROM sysmergearticles
                           WHERE name = @article
                           AND pubid IN (select pubid 
                                         FROM sysmergepublications 
                                         WHERE name like @publication  
                                            and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()))
                BEGIN
                    RAISERROR (20027, 16, -1, @article)
                    RETURN (1)
                END

        END

    
    INSERT INTO #helpmergearticle 
        (name, 
        source_owner,
        source_object, 
        sync_object_owner,
        sync_object, 
        description, 
        status, 
        creation_script, 
        conflict_table, 
        pre_creation_command, 
        schema_option, 
        type, 
        column_tracking, 
        article_resolver, 
        subset_filterclause,
        resolver_info)(
    select  art.name,
            users.name,
            objects.name, 
            users.name,
            syncobjects.name, 
            art.description, 
            art.status, 
            art.creation_script, 
            art.conflict_table, 
            art.pre_creation_command,
            art.schema_option, 
            art.type, 
            art.column_tracking, 
            art.article_resolver, 
            art.subset_filterclause,
            art.resolver_info
    FROM    sysmergearticles art, 
            sysmergepublications pubs,
            sysobjects objects,
            sysobjects syncobjects,
            sysusers users
            WHERE art.name LIKE @article
                AND art.pubid = pubs.pubid 
                AND pubs.name LIKE @publication
                AND UPPER(pubs.publisher) = UPPER(@@servername)
                AND pubs.publisher_db = db_name()
                AND objects.id = art.objid
                AND objects.uid = users.uid
                AND syncobjects.id = art.sync_objid
                AND syncobjects.uid = users.uid)
            order by art.nickname desc

    select * from #helpmergearticle 
    RETURN (0)
go
exec dbo.sp_MS_marksystemobject sp_helpmergearticle 
go

grant execute on dbo.sp_helpmergearticle to public
go

raiserror('Creating procedure sp_dropmergearticle', 0,1)
GO

CREATE PROCEDURE sp_dropmergearticle(
    @publication sysname,     /* The publication name */
    @article sysname,         /* The article name */
    @ignore_distributor bit = 0,
    @reserved bit = 0
    ) AS

    set nocount on
    /*
    ** Declarations.
    */

    declare @db_name                sysname
    declare @cmd                    nvarchar(255)
    declare @artid                  uniqueidentifier
    declare @objid                  int
    declare @pubid                  uniqueidentifier
    declare @pubidstr               nvarchar(38)
    declare @merge_pub_object_bit   int
    declare @unpublish_bit          int
    declare @retcode                int
    declare @replinfo               int
    declare @dbname                 sysname
    declare @distributor            sysname
    declare @distribdb              sysname
    declare @distproc               nvarchar(255)
    declare @object_name            sysname
    declare @uid                    smallint
    declare @owner                  sysname
    declare @qualified_name         nvarchar(255)
	declare @filterid				int
	declare @proc_name				sysname
    declare @implicit_transaction	int
	declare @close_cursor_at_commit int
	declare @sync_objid 	int
	declare @view_type		int

	select @close_cursor_at_commit = 0
	select @implicit_transaction = 0
	/*
	** Save setting values first before changing them
	*/
	IF (@reserved = 0)
	BEGIN
		SELECT @implicit_transaction = @@options & 2
		SELECT @close_cursor_at_commit = @@options & 4
		SET IMPLICIT_TRANSACTIONS OFF
		SET CURSOR_CLOSE_ON_COMMIT OFF
	END
    
    /*
    ** Initializations.
    */
    -- merge uses bit 8 in replinfo
    select @merge_pub_object_bit    = 128  
    select @unpublish_bit = ~@merge_pub_object_bit


    /*
    ** Security Check
    */
    EXEC @retcode = dbo.sp_MSreplcheck_publish
    IF @@ERROR <> 0 or @retcode <> 0
        return (1)

    /*
    ** Check to make sure that this database is enabled for publishing
    */
    if not exists (select * from sysobjects where name = 'sysmergepublications')
        BEGIN
            RAISERROR (20054, 16, -1)
            RETURN (1)
        END

    /*
    ** Get the @pubid.
    */
    if NOT EXISTS (select * FROM sysmergepublications 
        WHERE name = @publication  and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name())
        BEGIN
            RAISERROR (20026, 16, -1, @publication)
            RETURN (1)
        END
    select @pubid = pubid FROM sysmergepublications 
        WHERE name = @publication  and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()

    select @db_name = db_name from sysmergesubscriptions
        where (pubid=@pubid) and (subid=@pubid) 
        IF @db_name <> db_name()
        BEGIN
            RAISERROR (20047, 16, -1)
            RETURN (1)
        END

    
    set @pubidstr = '''' + convert(nchar(36), @pubid) + ''''

    /*
    ** Parameter Check:  @article.
    ** If the @article is 'all', drop all articles for the specified
    ** publication (@publication).
    */

    if LOWER(@article) = 'all'
        BEGIN
            declare hC CURSOR LOCAL FAST_FORWARD FOR select DISTINCT name FROM sysmergearticles WHERE pubid=@pubid FOR READ ONLY
            
            OPEN hC
            FETCH hC INTO @article
            WHILE (@@fetch_status <> -1)
                BEGIN
                    EXECUTE dbo.sp_dropmergearticle @publication, @article,
                        @ignore_distributor = @ignore_distributor,
                        @reserved = 1
                    FETCH hC INTO @article
                END
            CLOSE hC
            DEALLOCATE hC
            RETURN (0)
        END

    /*
    ** Parameter Check: @article.
    ** The @article name must conform to the rules for identifiers.
    */

    if @article IS NULL
        BEGIN
            RAISERROR (14043, 16, -1, '@article')
            RETURN (1)
        END

    /*
    ** Parameter Check: @publication.
    ** The @publication name must conform to the rules for identifiers.
    */

    if @publication IS NULL
        BEGIN
            RAISERROR (14043, 16, -1, '@publication')
            RETURN (1)
        END

    /*
    ** Ascertain the existence of the article.
    */

    if NOT EXISTS (select * FROM sysmergearticles 
        WHERE name = @article
        AND pubid = @pubid)
        BEGIN
            RAISERROR (20027, 16, -1, @article)
            RETURN (1)
        END

    /*
    **  Delete article from sysmergearticles and clear publish bit in
    **  sysobjects.
    */

    begin tran 
    save TRAN dropmergearticle
        /*
        ** Retrieve the object id of the underlying table.
        */
        select @sync_objid = sync_objid, @view_type = view_type, @artid = artid, @objid = objid
        	from sysmergearticles where name = @article AND pubid = @pubid
        select @replinfo = replinfo, @object_name=name, @owner= user_name(uid) from sysobjects where id = @objid
        
        /*
        ** Remove the corresponding rows from sysmergeschemachange
        */
        DELETE FROM sysmergeschemachange WHERE artid = @artid AND pubid = @pubid
        if @@ERROR <> 0
            goto FAILURE
        /*
        ** If this is the last article that refers to the base table, drop the 
        ** triggers and stored procs 
        */
        if NOT exists (select * from sysmergearticles WHERE artid = @artid AND pubid <> @pubid)
            begin
            /*
            ** Cleanup the triggers and stored procs
            */
            EXECUTE @retcode = dbo.sp_MSarticlecleanup @artid = @artid, @pubid = @pubid
            if @@ERROR <> 0 OR @retcode <> 0
                BEGIN
                    GOTO FAILURE
                END
            
            /*
            ** Clear the replication bit in sysobjects. Now merge and transactional level
            ** uses different replication bit, checking transactional level is not needed.
            */

            select @qualified_name = (QUOTENAME(@owner) + '.' + QUOTENAME(@object_name))
            exec @retcode = dbo.sp_replupdateschema @qualified_name
            if @@ERROR <> 0 OR @retcode <> 0
                BEGIN
                    GOTO FAILURE
                END
            
            update sysobjects set replinfo = (replinfo & @unpublish_bit) where id = @objid

            IF @@ERROR <> 0
                goto FAILURE
            end             
		else
			begin
			/* Always drop the article proc's they are not shared among publications */
	        EXECUTE @retcode = dbo.sp_MSdroparticleprocs @artid = @artid, @pubid = @pubid
            if @@ERROR <> 0 OR @retcode <> 0
                BEGIN
                    GOTO FAILURE
                END
			/* If the article's has a temporary ( view type = 2) or a permanent view (view_type = 1 ) drop the sync object */
			if (@view_type = 1 OR @view_type = 2)
				begin
				declare @viewname sysname
				select @viewname = sysobjects.name from sysobjects where 
					ObjectProperty (sysobjects.id, 'IsView') = 1 
					and ObjectProperty (sysobjects.id, 'IsMSShipped') = 1 
					and sysobjects.id = @sync_objid
				if @viewname IS NOT NULL
					begin
						set @viewname = QUOTENAME(@viewname)
						exec ('drop view ' + @viewname)
						if @@ERROR<>0  GOTO FAILURE
					end
				end
			end
        /*
        ** Remove the row from sysmergearticles.
        */
        DELETE FROM sysmergearticles WHERE artid = @artid AND pubid = @pubid
        if @@ERROR <> 0
            BEGIN
                GOTO FAILURE
            END


        /* delete all the filter components that are defined upon the designated article */
		select @filterid = min(join_filterid) from sysmergesubsetfilters where
			artid = @artid AND pubid = @pubid
		while (@filterid is not null)
			begin
			select @proc_name = expand_proc from sysmergesubsetfilters where
				artid = @artid AND pubid = @pubid and join_filterid = @filterid

			if (@proc_name IS NOT NULL) and exists (select * from sysobjects where
				name = @proc_name and type = 'P')
				begin
					exec ('drop proc ' + @proc_name)
			        IF @@ERROR <> 0
            			goto FAILURE
				end
			delete from sysmergesubsetfilters where
				artid = @artid AND pubid = @pubid and join_filterid = @filterid
        	IF @@ERROR <> 0
          	 	goto FAILURE
			select @filterid = min(join_filterid) from sysmergesubsetfilters where
				artid = @artid AND pubid = @pubid
			end


        /*
        ** set the pub type to subset or full as appropriate
        */
        execute @retcode = dbo.sp_MSsubsetpublication @publication
        if @@ERROR <> 0 or @retcode <> 0 
            RETURN (1)
                
        /*
        ** if @ignore_distributor = 1, we are in bruteforce cleanup mode, don't do RPC.
        */
        if @ignore_distributor = 0
        begin
                /*
                ** Get distribution server information for remote RPC call.
                */
                EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
                   @distribdb   = @distribdb OUTPUT
                IF @@ERROR <> 0 or @retcode <> 0
                    BEGIN
                        goto FAILURE
                    END

                SELECT @dbname =  DB_NAME()
        
                SELECT @distproc = RTRIM(@distributor) + '.' + @distribdb + 
                    '.dbo.sp_MSdrop_article'
                EXECUTE @retcode = @distproc
                    @publisher = @@SERVERNAME,
                    @publisher_db = @dbname,
                    @publication = @publication,
                    @article = @article
                      
                IF @@ERROR <> 0 or @retcode <> 0
                    BEGIN
                        goto FAILURE
                    END
        end
                        

    COMMIT TRAN
    /*
	** Set back original settings
	*/	
	IF @reserved = 0
	BEGIN
		IF @implicit_transaction <>0 
			SET IMPLICIT_TRANSACTIONS ON
		IF @close_cursor_at_commit <>0 
			SET CURSOR_CLOSE_ON_COMMIT ON
	END
    RETURN (0)
FAILURE:
    RAISERROR (14047, 16, -1, @article)
    if @@TRANCOUNT > 0
    begin
        ROLLBACK TRANSACTION dropmergearticle
        COMMIT TRANSACTION
    end
    /*
	** Set back original settings
	*/	
	IF @reserved = 0
	BEGIN
		IF @implicit_transaction <>0 
			SET IMPLICIT_TRANSACTIONS ON
		IF @close_cursor_at_commit <>0 
			SET CURSOR_CLOSE_ON_COMMIT ON
	END
    RETURN (1)
go
exec dbo.sp_MS_marksystemobject sp_dropmergearticle
go

grant execute on dbo.sp_dropmergearticle to public
go


raiserror('Creating procedure sp_addmergepublication', 0,1)
GO

create procedure sp_addmergepublication (
    @publication            sysname,                /* Publication name */
    @description            nvarchar(255)= NULL,            /* Publication description */
    @retention              int         = 60,           /* Retention period of 60 days */
    @sync_mode              nvarchar(10) = 'native',    /* (bcp)native, (bcp)character */
    @allow_push             nvarchar(5)  = 'true',          /* Pulication allows push subscriptions */
    @allow_pull             nvarchar(5)  = 'true',          /* Pulication allows pull subscriptions*/
    @allow_anonymous        nvarchar(5)  = 'false',         /* Pulication allows anonymous subscriptions */
    @enabled_for_internet   nvarchar(5)     = 'false',      /* Pulication is enabled for internet */
    @centralized_conflicts  nvarchar(5)  = 'true',          /* Conflict records stored at publisher : true or false */
    @dynamic_filters            nvarchar(5) = 'false'           /* Will publication be filtered on dynamic clause? */
    ) as

    set nocount on

    /*
    ** Declarations.
    */
    
    declare @retcode                    int         /* return code value for procedure execution */
    declare @push                       tinyint     /* subscription type is push */
    declare @statid                     tinyint     /* status id based on @status */
    declare @sync_modeid                tinyint     /* sync mode id based on @sync_mode */
    declare @global                     tinyint     /* subscriber type of loop-back subscription */
    declare @db_name                    sysname     /* database name */
    declare @srvid                      int         /* Server ID */
    declare @nickname                   int         /* replica nickname */
    declare @tranpublish_bit            smallint    /* online publish bit (flag) in sysdatabases */
    declare @mergepublish_bit           smallint    /* merge publish bit (flag) in sysdatabases */
    declare @found                      int         /* flag indicating if publication is found */
    declare @pubid                      uniqueidentifier    /* Publication identifier */
    declare @allow_push_id              bit
    declare @allow_pull_id              bit
    declare @allow_anonymous_id         bit
    declare @dynamic_filters_id         bit         
    DECLARE @enabled_for_internet_id    bit
    declare @centralized_conflicts_id   bit
    declare @priority                   real        
    declare @automatic                  tinyint     
    declare @false                      bit
    declare @true                       bit
    declare @distributor                sysname
    declare @distproc                   nvarchar(255)
    declare @distribdb                  sysname
    declare @distpubid                  int
    declare @full                       int

    /*
    ** Initializations
    */
    select @mergepublish_bit    = 4 
    select @tranpublish_bit     = 1
    select @priority            = 100.0
    select @automatic           = 1     /* Const: synchronization type 'automatic' */
    select @true                = 1
    select @false               = 0
    select @full                = 0     /* Const: publication type 'full' */

    /*
    ** Set the status to unsynced (1)
    */
    select @statid      = 1
    select @global      = 1
    select @push        = 0
    select @db_name     = DB_NAME()

    /*
    ** Security Check
    */

    EXEC @retcode = dbo.sp_MSreplcheck_publish
    IF @@ERROR <> 0 or @retcode <> 0
        return (1)

    /*
    ** Only publisher can call sp_addmergepublication to add its own publications 
    */
    if not exists (select * from sysobjects where name = 'sysmergepublications')
            BEGIN
                RAISERROR (20054, 16, -1)
                RETURN (1)
            END

    /*
    ** Parameter Check: @publication.
    ** The @publication name must conform to the rules for identifiers,
    ** and must not be the keyword 'all'.
    */
    if @publication is NULL
        begin
            raiserror (14043, 16, -1, '@publication')
            return (1)
        end

	exec @retcode = dbo.sp_MSreplcheck_name @publication
    if @@ERROR <> 0 or @retcode <> 0
        return(1)
       
    if LOWER (@publication) = 'all'
        begin
            raiserror (14034, 16, -1)
            return (1)
        end

    /*
    ** Parameter Check: @retention.
    ** Make sure that the maximum retention period is 60 days
    */
        
    if @retention is not NULL and @retention<0 
        begin
            raiserror(20050, 16, -1, 0)
            return(1)
        end

    if @retention is NULL
    	select @retention = 0

    /*
    ** Parameter Check: @sync_mode.
    ** Make sure that the sync_mode is one of the following:
    **
    **  id  sync_mode
    **  ==  ==========
    **   0  (bcp)native
    **   1  (bcp)character
    */
    
    if LOWER(@sync_mode)='portable' select @sync_mode='character'

    if LOWER(@sync_mode) is NULL OR LOWER(@sync_mode) NOT IN ('bcp native', 'bcp character', 'native', 'character')
        begin
            raiserror (20076, 16, -1)
            return (1)
        end

    if LOWER(@sync_mode) = 'native' or LOWER(@sync_mode)='bcp native' 
        select @sync_modeid = 0
    else 
        select @sync_modeid = 1

    /*
    ** Parameter Check:  @allow_push.
    */

    if @allow_push IS NULL OR LOWER(@allow_push) NOT IN ('true', 'false')
        BEGIN
            RAISERROR (14148, 16, -1, '@allow_push')
            RETURN (1)
        END

    if LOWER(@allow_push) = 'true' 
        select @allow_push_id = 1
    else 
        select @allow_push_id = 0

    /*
    ** Parameter Check:  @allow_pull.
    */

    if @allow_pull IS NULL OR LOWER(@allow_pull) NOT IN ('true', 'false')
        BEGIN
            RAISERROR (14148, 16, -1, '@allow_pull')
            RETURN (1)
        END
    if LOWER(@allow_pull) = 'true' 
        select @allow_pull_id = 1
    else 
        select @allow_pull_id = 0

    /*
    ** Parameter Check:  @allow_anonymous.
    */

    if @allow_anonymous IS NULL OR LOWER(@allow_anonymous) NOT IN ('true', 'false')
        BEGIN
            RAISERROR (14148, 16, -1, '@allow_anonymous')
            RETURN (1)
        END
    if LOWER(@allow_anonymous) = 'true' 
        select @allow_anonymous_id = 1
    else 
        select @allow_anonymous_id = 0

    /*
    ** Parameter Check:  @enabled_for_internet.
    */

    IF @enabled_for_internet IS NULL OR LOWER(@enabled_for_internet) NOT IN ('true', 'false')
        BEGIN
            RAISERROR (14148, 16, -1, '@enabled_for_internet')
            RETURN (1)
        END

    IF LOWER(@enabled_for_internet) = 'true' 
        SELECT @enabled_for_internet_id = 1
    ELSE 
        SELECT @enabled_for_internet_id = 0

    /*
    ** Parameter Check:  @centralized_conflicts.
    */

    if @centralized_conflicts IS NULL OR LOWER(@centralized_conflicts) NOT IN ('true', 'false')
        BEGIN
            RAISERROR (14148, 16, -1, '@centralized_conflicts')
            RETURN (1)
        END
    if LOWER(@centralized_conflicts) = 'true' 
        select @centralized_conflicts_id = 1
    else 
        select @centralized_conflicts_id = 0

    /*
    ** Parameter Check:  @dynamic_filter.
    */

    IF @dynamic_filters IS NULL OR LOWER(@dynamic_filters) NOT IN ('true', 'false')
        BEGIN
            RAISERROR (14148, 16, -1, '@dynamic_filters')
            RETURN (1)
        END

    IF LOWER(@dynamic_filters) = 'true' 
        SELECT @dynamic_filters_id = 1
    ELSE 
        SELECT @dynamic_filters_id = 0

    /*
    ** Check to see if the publication name is already used.
    ** 1. check merge pubs
    ** 2. check online publications
    */
    if exists (select * from sysmergepublications 
        where name = @publication  and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name())
    begin
        RAISERROR (20025, 16, -1, @publication)
        RETURN (1)
    end

    if (select category & @tranpublish_bit from master..sysdatabases where name = @db_name) <> 0
    begin
        EXEC @retcode = dbo.sp_helppublication @publication, @found output

        if @@ERROR <> 0 OR @retcode <> 0
        BEGIN
            RETURN (1)
        END

        if @found <> 0 
        BEGIN
            RAISERROR (20025, 16, -1, @publication)
            RETURN (1)
        END
    end


    /*
    **  Add the publication as the designmaster of the replica set.
    */

    /* Generate a guid for the publication ID */
    set @pubid = newid()
        
    /* Select the server's ID as 0 since this is the LOCAL server */
    select @srvid = 0

    /* Look for existing nickname from any other subscription */
    exec @retcode=sp_MSgetreplnick NULL, NULL , NULL,  @nickname out
    if (@@error <> 0) or @retcode <> 0 
        begin
	        RETURN(1)
        end                 
            
    /* Generate a new replica nickname from the @pubid */
    if (@nickname is null)
    begin
        execute @retcode = dbo.sp_MSgenreplnickname @pubid, @nickname output
        IF @@ERROR <>0 OR @retcode <> 0
        BEGIN
            RAISERROR (20077, 16, -1)
            RETURN (1)
        END
    end
    else
        select @priority=max(priority) from sysmergesubscriptions where db_name=@db_name and srvid = @srvid
    /*
    ** A change in design.
    */
    if @priority = 0 
        begin
            RAISERROR(21087, 16, -1)
            return (1)
        end

    /*
    ** Get distributor information
    */
    EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT, 
        @distribdb = @distribdb OUTPUT
        if @@error <> 0 OR @retcode <> 0 or @distributor IS NULL OR @distribdb IS NULL
        BEGIN
            RAISERROR (14071, 16, -1)
            RETURN (1)
        END
    
    /*
    **  add an entry into sysmergepublications
    */
    begin tran
    save tran sp_addmergepublication
        /* Add row in the publications table */
        insert sysmergepublications
            (pubid, 
            name, 
            description, 
            designmasterid, 
            retention, 
            parentid, 
            sync_mode, 
            allow_push, 
            allow_pull, 
            allow_anonymous, 
            centralized_conflicts,
            status,
            snapshot_ready,
            enabled_for_internet,
            publication_type,
            dynamic_filters)
        values
            (@pubid, 
            @publication, 
            @description, 
            @pubid, 
            @retention, 
            @pubid, 
            @sync_modeid, 
            @allow_push_id, 
            @allow_pull_id, 
            @allow_anonymous_id, 
            @centralized_conflicts_id,
            @statid,
            @false,
            @enabled_for_internet_id,
            @full,
            @dynamic_filters_id)
        if @@ERROR <> 0
            begin
                goto FAILURE
            end

        /* Add row to represent reciprocal subscription */
        insert sysmergesubscriptions(subid, partnerid, datasource_type, srvid, db_name, status, priority, pubid, subscriber_type, subscription_type, sync_type, login_name)
            values (@pubid, @pubid, 0, @srvid, @db_name, @statid, @priority, @pubid, @global, @push, @automatic, suser_sname(suser_sid()))

        if @@ERROR <> 0
            begin
                goto FAILURE
            end
        /*
        **  Add row for merge publication to MSmerge_replinfo.
        */
        insert MSmerge_replinfo(repid, replnickname)
            values (@pubid, @nickname)
        if @@ERROR <> 0
            begin
                goto FAILURE
            end


        /*
        ** Add the publication to the distributor side
        */
        SELECT @distpubid = @nickname

        select @distproc = RTRIM(@distributor) + '.' + @distribdb + 
            '.dbo.sp_MSadd_publication'
        EXECUTE @retcode = @distproc
            @publisher = @@SERVERNAME,
            @publisher_db = @db_name,
            @publication = @publication,
            --@publication_id = NULL,
            @publication_type = 2,          -- 0 = Trans, 1 = Snapshot, 2 = Merge
            @independent_agent = @true,
            @immediate_sync = @true,
            @allow_push = @allow_push_id,
            @allow_pull = @allow_pull_id,
            @allow_anonymous = @allow_anonymous_id,
            --@snapshot_agent = NULL,
            --@logreader_agent = NULL,
            @description = @description,
            @retention = @retention

        IF @@ERROR <> 0 or @retcode <> 0
            BEGIN
                GOTO FAILURE
            END
        
		
		-- Populate the initial list.
		exec @retcode = dbo.sp_grant_publication_access 
			@publication = @publication,
			@login = null,
			@reserved = 'init'
		IF @@error <> 0 OR @retcode <> 0
			GOTO FAILURE
    
    commit tran
    return (0)

FAILURE:
    RAISERROR (14018, 16, -1)
    /* UNDONE : This code is specific to 6.X nested transaction semantics */
    if @@TRANCOUNT > 0
    begin
        ROLLBACK TRANSACTION sp_addmergepublication
        COMMIT TRANSACTION
    end
    return (1)
go
exec dbo.sp_MS_marksystemobject sp_addmergepublication 
go

grant execute on dbo.sp_addmergepublication to public
go

raiserror('Creating procedure sp_changemergepublication', 0,1)
GO

CREATE PROCEDURE sp_changemergepublication (
    @publication sysname,              /* Publication name */
    @property sysname = NULL,          /* The property to change */
    @value nvarchar(255) = NULL             /* The new property value */
    ) AS

    SET NOCOUNT ON

    /*
    ** Declarations.
    */

    declare @cmd                nvarchar(255)
    declare @pubid              uniqueidentifier
    declare @pubidstr           nvarchar(38)
    declare @retcode            int
    declare @retention          int
    declare @statusid           tinyint
    declare @sync_modeid        tinyint
    declare @distributor        sysname
    declare @distproc           nvarchar(255)
    declare @value_bit          bit
    declare @subscribed         int
    declare @dbname             sysname
    declare @distribdb          sysname


    /*
    ** Initializations
    */
    select @subscribed = 1

    /*
    ** Security Check
    */

    EXEC @retcode = dbo.sp_MSreplcheck_publish
    IF @@ERROR <> 0 or @retcode <> 0
        return (1)

    /* 
    ** Check if current DB is enabled for publication/subscription
    */
    
    if not exists (select * from sysobjects where name = 'sysmergepublications')
            BEGIN
                RAISERROR (20054, 16, -1)
                RETURN (1)
            END
            
    /*
    ** Parameter Check:  @property.
    ** If the @property parameter is NULL, print the options.
    */
    if @property IS NULL
        BEGIN
            CREATE TABLE #tab1 (properties sysname)
            INSERT INTO #tab1 VALUES ('description')
            INSERT INTO #tab1 VALUES ('status')
            INSERT INTO #tab1 VALUES ('retention')
            INSERT INTO #tab1 VALUES ('sync_mode')
            INSERT INTO #tab1 VALUES ('allow_push')
            INSERT INTO #tab1 VALUES ('allow_pull')
            INSERT INTO #tab1 VALUES ('allow_anonymous')
            INSERT INTO #tab1 VALUES ('enabled_for_internet')
            INSERT INTO #tab1 VALUES ('centralized_conflicts')
            INSERT INTO #tab1 VALUES ('snapshot_ready')
            select * FROM #tab1
            RETURN (0)
        END

    if @value is NULL and LOWER(@property) not in ('description', 'retention')
        begin
            RAISERROR (20081, 16, -1, @property)
            RETURN (1)
        end

    /*
    ** Parameter Check:  @publication.
    ** Make sure that the publication exists.
    */

    if @publication IS NULL
        BEGIN
            RAISERROR (14043, 16, -1, '@publication')
            RETURN (1)
        END

    select @pubid = pubid FROM sysmergepublications 
        WHERE name = @publication  and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()
    set @pubidstr = '''' + convert(nchar(36), @pubid) + ''''

    if @pubid IS NULL
        BEGIN
            RAISERROR (20026, 16, -1, @publication)
            RETURN (1)
        END
    else

    /*
    ** Parameter Check:  @property.
    ** Check to make sure that @property is a valid property in
    ** sysmergepublications.
    */
    if LOWER(@property) NOT IN ('description', 'status', 'retention', 'sync_mode', 'allow_push', 
        'allow_pull', 'allow_anonymous', 'enabled_for_internet', 'centralized_conflicts', 'snapshot_ready')
        BEGIN
            RAISERROR (21053, 16, -1)
            RETURN (1)
        END

    BEGIN TRAN sp_changemergepublication    

    /*
    ** Change the property.
    */

    if LOWER(@property) IN ('description')
        BEGIN
            UPDATE sysmergepublications  SET description = @value WHERE pubid = @pubid
            if @@ERROR <> 0 GOTO UNDO
        END

  
    if LOWER(@property) = 'status'
        BEGIN

            /*
            ** Check to make sure that we have a valid status.
            */

            if LOWER(@value) NOT IN ('active', 'inactive')
                BEGIN
                    RAISERROR (14012, 16, -1)
                    GOTO UNDO
                END

            /*
            ** Determine the integer value for the status.
            */

            if LOWER(@value) = 'active'
                select @statusid = 1
            else
                select @statusid = 0

            /*
            ** Update the publication with the new status.
            */

            UPDATE sysmergepublications SET status = @statusid WHERE pubid = @pubid

            if @@ERROR <> 0 GOTO UNDO

			/*
			** If setting to inactive, allow articles / join filters to be altered, and
			** clear the snapshot ready bit as well.
			*/
			if @statusid = 0
				begin
	            UPDATE sysmergepublications SET snapshot_ready = 0 WHERE pubid = @pubid
		        if @@ERROR <> 0 GOTO UNDO
				UPDATE sysmergearticles SET status = 1 WHERE pubid = @pubid
		        if @@ERROR <> 0 GOTO UNDO
				end
        END


    if LOWER(@property) = 'retention'
        BEGIN
        /*
        ** Update the publication with the new replication frequency.
        */

        select @retention = CONVERT(int, @value)

        if @retention is NULL 
        	select @retention = 0

       	if @retention < 0
       		begin
       			raiserror(20050, 16, -1, 0)
       			GOTO UNDO
       		end

        UPDATE sysmergepublications
            SET retention = @retention
            WHERE pubid = @pubid

        if @@ERROR <> 0 
            GOTO UNDO

        END


    if LOWER(@property) = 'sync_mode'
        BEGIN

            /*
            ** Check for a valid synchronization method.
            */

            if LOWER(@value) NOT IN ('native', 'character', 'bcp native', 'bcp character')
                begin
                raiserror (20076, 16, -1)
                GOTO UNDO
                end

            /*
            ** Determine the integer value for the sync_mode.
            */
            if LOWER(@value) IN ('native', 'bcp native')
                select @sync_modeid = 0
            else if LOWER(@value) IN ('character', 'bcp character')
                select @sync_modeid = 1

            /*
            ** Update the publication with the new synchronization method.
            */

            UPDATE sysmergepublications
               SET sync_mode = @sync_modeid
             WHERE pubid = @pubid

            if @@ERROR <> 0 GOTO UNDO
        END

    if LOWER(@property) IN ('allow_push', 'allow_pull', 'allow_anonymous', 'enabled_for_internet',
        'centralized_conflicts', 'snapshot_ready')
    BEGIN

        /*
        ** Check for a valid  value.
        */

        if LOWER(@value) NOT IN ('true', 'false')
        BEGIN
            RAISERROR (14137, 16, -1)
            GOTO UNDO
        END

        /*
        ** set value bit
        */
        if LOWER(@value) = 'true'
            select @value_bit = 1
        else 
            select @value_bit = 0


        if LOWER(@property) = 'allow_anonymous'
        BEGIN
            /* Update the allow_anonymous column */
            UPDATE sysmergepublications 
                SET allow_anonymous = @value_bit
                WHERE pubid = @pubid
            if @@error <> 0
            BEGIN
               GOTO UNDO
            END

        END

        if LOWER(@property) = 'allow_push'
        BEGIN
            /* Update the allow_push column */
            UPDATE sysmergepublications 
                SET allow_push = @value_bit
                WHERE pubid = @pubid
            if @@error <> 0
            BEGIN
               GOTO UNDO
            END
        END

        if LOWER(@property) = 'allow_pull'
        BEGIN

            /* Update the allow_pull column */
            UPDATE sysmergepublications 
                SET allow_pull = @value_bit
                WHERE pubid = @pubid
            if @@error <> 0
            BEGIN
               GOTO UNDO
            END
        END

        if LOWER(@property) = 'centralized_conflicts'
        BEGIN
            /* Update the centralized_conflicts column */
            UPDATE sysmergepublications 
                SET centralized_conflicts = @value_bit
                WHERE pubid = @pubid
            if @@error <> 0
            BEGIN
               GOTO UNDO
            END

        END

        if LOWER(@property) = 'enabled_for_internet'
        BEGIN
            /* Update the enabled_for_internet column */
            UPDATE sysmergepublications 
                SET enabled_for_internet = @value_bit
                WHERE pubid = @pubid
            if @@error <> 0
            BEGIN
               GOTO UNDO
            END

        END

        if LOWER(@property) = 'snapshot_ready'
        BEGIN
            /* Update the allow_anonymous column */
            UPDATE sysmergepublications 
                SET snapshot_ready = @value_bit
                WHERE pubid = @pubid
            if @@error <> 0
            BEGIN
               GOTO UNDO
            END

        END
    END

    /*
    ** Update merge publication property at distributor side if necessaray 
    */
    
    IF LOWER(@property) IN ('description','allow_push', 'allow_pull', 'allow_anonymous','retention')

        BEGIN

        IF LOWER(@property) IN ('allow_push', 'allow_pull', 'allow_anonymous')
            
        /* Translate values */
        BEGIN            
            IF LOWER(@value) = 'true'
                SELECT @value = '1'
            ELSE IF LOWER(@value) = 'false'
                    SELECT @value = '0'
        END
                
        /*
        ** Get distribution server information for remote RPC call.
        */
        EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
           @distribdb   = @distribdb OUTPUT
        IF @@ERROR <> 0 or @retcode <> 0
            BEGIN
                GOTO UNDO
            END

        SELECT @dbname =  DB_NAME()
        
        SELECT @distproc = RTRIM(@distributor) + '.' + @distribdb + 
            '.dbo.sp_MSchange_publication'
    
        EXECUTE @retcode = @distproc
            @publisher = @@SERVERNAME,
            @publisher_db = @dbname,
            @publication = @publication,
            @property = @property,
            @value = @value

        IF @@ERROR <> 0 OR @retcode <> 0
        BEGIN
            GOTO UNDO
        END
    END

    COMMIT TRAN

    /*
    ** Return succeed.
    */
    
    RAISERROR (14077, 10, -1)
    RETURN (0)

UNDO: 
    IF @@TRANCOUNT = 1
        ROLLBACK TRAN
    ELSE COMMIT TRAN
GO
    

go
exec dbo.sp_MS_marksystemobject sp_changemergepublication 
go

grant execute on dbo.sp_changemergepublication to public
go

raiserror('Creating procedure sp_helpmergepublication', 0,1)
GO


CREATE PROCEDURE sp_helpmergepublication (
    @publication    sysname = '%',    /* The publication name */
    @found          int         = NULL  OUTPUT,
    @publication_id uniqueidentifier = NULL OUTPUT,
    @reserved       nvarchar(20) = NULL
    ) AS

    SET NOCOUNT ON

    /*
    ** Declarations.
    */

    declare @retcode            int
    declare @no_row             bit
    declare @our_srvid          int
    declare @has_subscription   bit
    /*
    ** Initializations.
    */
    select @has_subscription = 0

    if @found is NULL 
    BEGIN
        select @no_row=0
    END
    else
    BEGIN
        select @no_row=1
    END
    select @found       = 0
    select @our_srvid = max(srvid) from master..sysservers where UPPER(srvname) = UPPER(@@SERVERNAME)

    
    /*
    ** Running sp_help is OK from everywhere, whether enabled for publishing or not
    */
    
    IF not exists (select * from sysobjects where name='sysmergesubscriptions')
        RETURN (0)


    /*
    ** Parameter Check:  @publication.
    ** Check to make sure that there are some publications
    ** to display.
    */

    if @publication IS NULL
        BEGIN
            RAISERROR (14043, 16, -1, '@publication')
            RETURN (1)
        END

    IF LOWER(@reserved) = 'internal'
        GOTO SelectPubs
    
    if  NOT EXISTS (select * FROM sysmergepublications pub, sysmergesubscriptions sub
        WHERE pub.name like @publication  
            and UPPER(pub.publisher)=UPPER(@@servername) 
            and pub.publisher_db=db_name() 
            and sub.pubid = pub.pubid  
            and sub.srvid = @our_srvid 
            and sub.db_name = db_name())
        BEGIN
            select @found = 0
            RETURN (0) 
        END
    else
        BEGIN
            select @found = 1
            select @publication_id = pubid FROM sysmergepublications 
                WHERE name = @publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()
            if exists (select * from sysmergesubscriptions where pubid<>subid and pubid in 
                (select pubid from sysmergepublications where name like @publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()))
                select @has_subscription = 1
            if @no_row <> 0
                RETURN(0)
        END

SelectPubs:
    CREATE TABLE #tab1 (
        id                      int                 identity NOT NULL,
        name                    sysname             NOT NULL,
        description             nvarchar(255)       NULL,
        status                  tinyint             NOT NULL,
        retention               int                 NULL,
        sync_mode               tinyint             NULL,
        allow_push              int                 NOT NULL,
        allow_pull              int                 NOT NULL,
        allow_anonymous         int                 NOT NULL,
        centralized_conflicts   int                 NOT NULL,
        priority                float(8)            NOT NULL,
        snapshot_ready          tinyint             NOT NULL,
        publication_type        int                 NULL,
        pubid                   uniqueidentifier    NOT NULL,
        snapshot_jobid          binary(16)          NULL,
        enabled_for_internet    int                 NULL,
        dynamic_filters         int                 NULL,
        has_subscription        bit                 NULL
        )

    /* This is valid at all sites - used for decentralized conflicts */
    IF LOWER(@reserved) = 'internal'
        begin
            INSERT into #tab1(name, description, status, retention, sync_mode, 
                    allow_push, allow_pull, allow_anonymous, centralized_conflicts, 
                    priority, snapshot_ready, publication_type, pubid, snapshot_jobid, 
                    enabled_for_internet, 
					dynamic_filters)
            select  pubs.name, pubs.description, pubs.status, pubs.retention, pubs.sync_mode, 
                    pubs.allow_push, pubs.allow_pull, pubs.allow_anonymous, pubs.centralized_conflicts, 
                    subs.priority, pubs.snapshot_ready, pubs.publication_type, pubs.pubid, replinfo.snapshot_jobid,
                    pubs.enabled_for_internet, 
					pubs.dynamic_filters
            FROM    sysmergesubscriptions   subs,
                    sysmergepublications    pubs,
                    MSmerge_replinfo        replinfo
                    WHERE pubs.name LIKE @publication
                        AND UPPER(pubs.publisher)=UPPER(@@servername) 
                        AND pubs.publisher_db=db_name()
                        AND subs.subid = pubs.pubid
                        AND replinfo.repid = pubs.pubid
                        AND subs.subscriber_type = 1
            ORDER BY name
        end
    /* This is valid only at publishers and republishers */
    else
        begin
            INSERT into #tab1(name, description, status, retention, sync_mode, 
                    allow_push, allow_pull, allow_anonymous, centralized_conflicts, 
                    priority, snapshot_ready, publication_type, pubid, snapshot_jobid, 
                    enabled_for_internet,
					dynamic_filters, has_subscription)
            select  pubs.name, pubs.description, pubs.status, pubs.retention, pubs.sync_mode, 
                    pubs.allow_push, pubs.allow_pull, pubs.allow_anonymous, pubs.centralized_conflicts, 
                    subs.priority, pubs.snapshot_ready, pubs.publication_type, pubs.pubid, replinfo.snapshot_jobid,
                    pubs.enabled_for_internet,
					pubs.dynamic_filters, case when exists (select * from sysmergesubscriptions where pubid<>subid and pubid in 
								                (select in_pubs.pubid from sysmergepublications in_pubs where in_pubs.name = pubs.name 
								                	and UPPER(in_pubs.publisher)=UPPER(@@servername) and in_pubs.publisher_db=db_name()))
								          then 1
								          else 0 end

            FROM    sysmergesubscriptions   subs,
                    sysmergepublications    pubs,
                    MSmerge_replinfo        replinfo
                    WHERE pubs.name LIKE @publication
                         and UPPER(pubs.publisher)=UPPER(@@servername) 
                         and pubs.publisher_db=db_name()
                        AND subs.subid = pubs.pubid
                        AND replinfo.repid = pubs.pubid
                        AND subs.subscriber_type = 1
                        AND subs.srvid = @our_srvid 
                        AND subs.db_name = db_name()
            ORDER BY name
        end
    if @@ERROR <> 0 
        RETURN (1)
    select * FROM #tab1
    RETURN (0)
go
exec dbo.sp_MS_marksystemobject sp_helpmergepublication 
go

grant execute on dbo.sp_helpmergepublication to public
go


raiserror('Creating procedure sp_dropmergepublication', 0,1)
GO

CREATE PROCEDURE sp_dropmergepublication(
        @publication sysname,      /* The publication name */
        @ignore_distributor bit = 0,
        @reserved bit = 0
        ) AS

    set nocount on
    /*
    ** Declarations.
    */

    declare @pubid              uniqueidentifier
    declare @article            sysname
    declare @cmd                nvarchar(255)
    declare @retcode            int
    declare @distproc           nvarchar(255)
    declare @distributor        sysname
    declare @distribdb          sysname
    declare @working_dir        varchar(255)
    declare @working_dir_drive  varchar(255)
    declare @pub_dir            nvarchar(255)
    declare @db_name            sysname
	declare @implicit_transaction	int
	declare @close_cursor_at_commit int

	select @close_cursor_at_commit = 0
	select @implicit_transaction = 0
	/*
	** Save setting values first before changing them
	*/
	IF (@reserved = 0)
	BEGIN
		SELECT @implicit_transaction = @@options & 2
		SELECT @close_cursor_at_commit = @@options & 4
		SET IMPLICIT_TRANSACTIONS OFF
		SET CURSOR_CLOSE_ON_COMMIT OFF
	END
    /*
    ** Initializations.
    */  
    select @db_name = db_name()

    /*
    ** Security Check
    */
    EXEC @retcode = dbo.sp_MSreplcheck_publish
    IF @@ERROR <> 0 or @retcode <> 0
        return (1)

    if not exists (select * from sysobjects where name = 'sysmergepublications')
        BEGIN   
            RAISERROR (20054, 16, -1)
            RETURN (1)              
        END 

    if LOWER(@publication) = 'all'
        BEGIN

            declare hC1 CURSOR LOCAL FAST_FORWARD FOR select DISTINCT name 
                FROM sysmergepublications where UPPER(publisher)=UPPER(@@SERVERNAME) and publisher_db=db_name() 
                    FOR READ ONLY
            
            OPEN hC1
            FETCH hC1 INTO @publication
            WHILE (@@fetch_status <> -1)
                BEGIN
                    EXECUTE dbo.sp_dropmergepublication @publication=@publication,
                        @ignore_distributor = @ignore_distributor,
                        @reserved = 1

                    FETCH hC1 INTO @publication
                END
            CLOSE hC1
            DEALLOCATE hC1
            RETURN (0)
        END

    if @publication IS NULL
        BEGIN
            RAISERROR (14003, 16, -1)
            RETURN (1)
        END
    /*
    ** Get the @pubid.
    */
    if NOT EXISTS (select * FROM sysmergepublications 
        WHERE name = @publication  and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name())
        BEGIN
            RAISERROR (20026, 16, -1, @publication)
            RETURN (1)
        END
    select @pubid = pubid FROM sysmergepublications 
        WHERE name = @publication  and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()
    
    /* 
    ** Ignore external publications
    */
    if exists (select * from sysmergesubscriptions where subid=@pubid 
        and pubid=@pubid and db_name<>db_name())
    RETURN (0)

    /*
    ** Check to make sure that there are push or pull subscriptions on the publication.
    */
    if EXISTS (select * FROM sysmergesubscriptions  subs, 
                    sysmergepublications                pubs, 
                    MSmerge_replinfo                    repinfo
                WHERE   pubs.name = @publication
                    AND UPPER(pubs.publisher)=UPPER(@@servername) 
                    AND pubs.publisher_db=db_name()
                    AND subs.pubid = pubs.pubid
                    AND subs.status <> 2  -- Having a deleted subscription row is fine
                    AND repinfo.repid <> @pubid
                    AND subs.subid <> subs.partnerid)
        BEGIN
            RAISERROR (14005, 16, -1)
            RETURN (1)
        END


    begin tran
    save TRANSACTION dropmergepublication

    /*
    ** Delete all articles from the publication.
    */
    EXECUTE @retcode = dbo.sp_dropmergearticle @publication = @publication, @article = 'all',
        @ignore_distributor = @ignore_distributor

    if @@ERROR <> 0 OR @retcode <> 0
        begin
            RAISERROR (20040, 16, -1, @publication)
            goto FAILURE
        end

    /*
    ** Delete sync task of Publication.
    */
    execute @retcode = dbo.sp_MSdropmergepub_snapshot @publication = @publication,
        @ignore_distributor = @ignore_distributor

    if @@ERROR <> 0 OR @retcode <> 0
        begin
            RAISERROR (20010, 16, -1, @publication)
            goto FAILURE
        end

    /*
    ** Remove my own subscription from sysmergesubscriptions.
    */
    if exists (select * from sysmergesubscriptions where subid = @pubid)
        begin
            DELETE from sysmergesubscriptions WHERE subid = @pubid
            if @@ERROR <> 0
                goto FAILURE
        end         

    if exists (select * from MSmerge_replinfo where repid = @pubid)
        begin
            DELETE from MSmerge_replinfo WHERE repid = @pubid
            if @@ERROR <> 0
                goto FAILURE
        end             

    /*
    ** if @ignore_distributor = 1, we are in bruteforce cleanup mode, don't do RPC.
    */
    if @ignore_distributor = 0
    begin
        /*
        ** Get distribution server information for remote RPC call.
        */
        EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
                                           @distribdb = @distribdb OUTPUT,
                                           @directory = @working_dir OUTPUT
        IF @@ERROR <> 0 OR  @retcode <> 0
            BEGIN
                RAISERROR (14071, 16, -1)
                goto FAILURE
            END

        /*
        ** Drop the publication info from the distributor
        */
        select @distproc = RTRIM(@distributor) + '.' + @distribdb + 
            '.dbo.sp_MSdrop_publication'
        EXECUTE @retcode = @distproc
            @publisher = @@SERVERNAME,
            @publisher_db = @db_name,
            @publication = @publication

        if @@ERROR <> 0 OR @retcode <> 0
        begin
            goto FAILURE
        end
    end



    /*
    ** Remove the corresponding rows from sysmergeschemachange
    */
    DELETE FROM sysmergeschemachange WHERE pubid = @pubid
    if @@ERROR <> 0
        goto FAILURE
    
    /*
    ** Delete publication from sysmergepublications.
    */
    DELETE
        FROM sysmergepublications
            WHERE name = @publication  and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()

    if @@ERROR <> 0
        goto FAILURE

       
    COMMIT TRANSACTION
    /*
	** Set back original settings
	*/	
	IF @reserved = 0
	BEGIN
		IF @implicit_transaction <>0 
			SET IMPLICIT_TRANSACTIONS ON
		IF @close_cursor_at_commit <>0 
			SET CURSOR_CLOSE_ON_COMMIT ON
	END
    return (0)

FAILURE:            
    RAISERROR (14006, 16, -1)
    /* UNDONE : This code is specific to 6.X nested transaction semantics */
    if @@TRANCOUNT > 0
    begin
        ROLLBACK TRANSACTION dropmergepublication
        COMMIT TRANSACTION
    end
    /*
	** Set back original settings
	*/	
	IF @reserved = 0
	BEGIN
		IF @implicit_transaction <>0 
			SET IMPLICIT_TRANSACTIONS ON
		IF @close_cursor_at_commit <>0 
			SET CURSOR_CLOSE_ON_COMMIT ON
	END        
    RETURN (1)
go
exec dbo.sp_MS_marksystemobject sp_dropmergepublication
go

grant execute on dbo.sp_dropmergepublication to public
go



raiserror('Creating procedure sp_reinitmergesubscription', 0, 1)
GO

create procedure sp_reinitmergesubscription
    @publication    sysname  = 'all',
    @subscriber     sysname  = 'all',
    @subscriber_db  sysname  = 'all'
AS
    declare @pubid                  uniqueidentifier
    declare @subid                  uniqueidentifier
    declare @subscription_type		int
    declare @reinit_bit				int
    declare @publisher				sysname
    declare @publisher_db			sysname
    declare @distribdb				sysname
	declare @distributor			sysname
	declare @distproc				nvarchar(255)
	declare @retcode				int
	
    /*
    ** Replace 'all' with '%'
    */

    if LOWER(@publication) = 'all'
        SELECT @publication = '%'

    if LOWER(@subscriber) = 'all'
        SELECT @subscriber = '%'

    if LOWER(@subscriber_db) = 'all'
        SELECT @subscriber_db = '%'

    /*
    ** At publisher side, publication name is unique
    */
    IF NOT EXISTS (SELECT * FROM sysmergepublications 
        WHERE name LIKE @publication)
        BEGIN
        IF @publication = '%'
                RAISERROR (14008, 11, -1)
        ELSE
                RAISERROR (20026, 11, -1, @publication)
        RETURN (1)
        END

    EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT, @distribdb   = @distribdb OUTPUT
    	IF @@ERROR <> 0 or @retcode <> 0
        		return (1)

    SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MSmarkreinit '

	BEGIN TRAN
	
    Declare SYN_CUR CURSOR LOCAL FAST_FORWARD FOR 
        select subs.subid, subs.subscription_type, pubs.publisher, pubs.publisher_db
            from sysmergepublications pubs, sysmergesubscriptions subs
                where pubs.name LIKE  @publication 
                     and UPPER(pubs.publisher)=UPPER(@@servername) 
                     and pubs.publisher_db=db_name()
                    AND pubs.pubid=subs.pubid
                    AND subs.pubid<>subs.subid
                    AND db_name like @subscriber_db
                    AND srvid in (select srvid from master..sysservers where ((@subscriber = N'%') or (UPPER(srvname) = UPPER(@subscriber))))
    FOR READ ONLY
    open SYN_CUR
    fetch SYN_CUR into @subid, @subscription_type, @publisher, @publisher_db
    while (@@fetch_status<>-1)
    BEGIN   
    	if @subscription_type = 0 
          update MSmerge_replinfo set schemaversion=0, recgen = NULL, recguid=NULL, sentgen=NULL, sentguid = NULL
	          where repid=@subid and schemaversion is NOT NULL
        else
        	 update MSmerge_replinfo set schemaversion= -1, recgen = NULL, recguid=NULL, sentgen=NULL, sentguid = NULL
        	 	where repid=@subid and schemaversion is NOT NULL
        	-- 0 for push and -1 for pull
	    exec @distproc @publisher, @publisher_db, @publication, @subscriber, @subscriber_db, 1
    	if @@ERROR<>0
	        BEGIN
    	        goto Failure
        	END        	
        fetch next from SYN_CUR into @subid, @subscription_type, @publisher, @publisher_db        
    END
    close SYN_CUR
    deallocate SYN_CUR
    commit TRAN
    return (0)
Failure:
    close SYN_CUR
    deallocate SYN_CUR
    
    if @@TRANCOUNT = 1 
        ROLLBACK TRAN 
    else
        COMMIT TRAN
    return (1)

GO

exec dbo.sp_MS_marksystemobject sp_reinitmergesubscription
go  

raiserror('Creating procedure sp_MSpublicationview', 0,1)
GO

CREATE PROCEDURE sp_MSpublicationview(
    @publication sysname,
    @force_flag int = 0
    ) AS
    declare     @pubid              uniqueidentifier
    declare     @artid              uniqueidentifier
    declare     @join_articlename       nvarchar(270)
    declare     @join_viewname      nvarchar(270)
    declare     @article            sysname
    declare     @art_nick           int
    declare     @join_nick          int
    declare     @join_filterclause  nvarchar(2000)
    declare     @bool_filterclause  nvarchar(2000)
    declare     @view_rule          nvarchar(2000)
    declare     @article_level      int
    declare     @progress           int
    declare     @art                int
    declare     @viewname           nvarchar(270)
    declare     @procname           nvarchar(290)
    declare     @source_objid       int
    declare     @source_object      nvarchar(258)
    declare     @sync_objid         int
    declare     @permanent          int
    declare     @temporary          int
    declare     @filter_id          int
    declare     @filter_id_str      nvarchar(10)
	declare 	@guidstr nvarchar(40)
	declare 	@pubidstr nvarchar(40)
    declare     @rgcol              sysname
    declare     @view_type          int
    declare     @belongsname        sysname
    declare     @join_nickstr       nvarchar(10)
    declare     @unqual_jointable   sysname  
    declare     @retcode            smallint
    declare     @hasguid            int
    declare     @join_unique_key    int
    declare     @simple_join_view   int
    declare     @join_filterid      int
    declare     @allhaveguids       int
    declare     @command            nvarchar(4000)
    declare     @objid              int
    declare     @owner              sysname
    declare		@table				sysname
    declare     @quoted_view        nvarchar(290)
    declare     @quoted_pub         nvarchar(290)
    declare     @quoted_proc        nvarchar(290)
	declare 	@snapshot_ready		int
	
    set @progress       = 1
    set @article_level  = 0
    set @permanent      = 1
    set @temporary      = 2
    set @allhaveguids   = 1
    /*
    ** Only legal publisher can run this stored procedure
    */
    if not exists (select * from sysobjects where name = 'sysmergepublications')
        BEGIN
            RAISERROR (20054, 16, -1)
            RETURN (1)
        END

    select @pubid = pubid, @snapshot_ready = snapshot_ready FROM sysmergepublications 
        WHERE name = @publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name() 
    IF @pubid IS NULL
        BEGIN
            RAISERROR (20026, 11, -1, @publication)
            RETURN (1)
        END

    -- If snapshot is already ready, views are good.  Don't drop and recreate as someone
    -- might be using them.
    
	if @snapshot_ready = 1 and @force_flag = 0
		return (0)
		
	exec @retcode = dbo.sp_MSguidtostr @pubid, @pubidstr out
	if @@ERROR <>0 OR @retcode <>0 return (1)

    create table #art(indexcol int identity NOT NULL, art_nick int NOT NULL, article_level int NOT NULL)
    if @@ERROR <> 0
        begin
        goto FAILURE
        end

    while @progress > 0
        BEGIN
        /*
        ** Select articles that have either a boolean_filter or atleast one join filter 
        ** into a temp table in an optimized order.
        */
        insert into #art(art_nick, article_level) select nickname, @article_level from sysmergearticles 
            where pubid=@pubid and nickname not in (select art_nick from #art)
                and nickname not in 
                (select  art_nickname from sysmergesubsetfilters
                    where pubid=@pubid and join_nickname not in 
                        (select art_nick from #art))
        /*
        ** NOTENOTE: add error checking here.
        */

        set @progress = @@rowcount
        select @article_level = @article_level + 1
        END

    /* Drop the old views and reset sync_objid */
    select @art_nick = min(nickname) from sysmergearticles where pubid = @pubid and sync_objid <> objid
    while @art_nick is not null
        begin
        /* Drop the old view */
        select @viewname = OBJECT_NAME (sync_objid) from sysmergearticles where
            pubid = @pubid and nickname = @art_nick
        if @viewname IS NOT NULL
        begin
            select @quoted_view = QUOTENAME(@viewname)
            exec ('drop view ' + @quoted_view)
        end
        
        /* Update the row in sysmergearticles */
        update sysmergearticles set view_type = 0, sync_objid = objid where 
            pubid = @pubid and nickname = @art_nick
        if @@ERROR <> 0 goto FAILURE

        /* Find the next one */
        select @art_nick = min(nickname) from sysmergearticles where pubid = @pubid and sync_objid <> objid
        end
        
    set @art = 0
    select @art=min(indexcol) from #art where indexcol>@art

    while (@art is not null)
        begin
        select @art_nick=art_nick, @article_level = article_level from #art 
                where indexcol = @art
        select @article = name, @artid = artid, @source_objid = objid, @sync_objid = sync_objid, @procname = view_sel_proc from sysmergearticles 
                where nickname=@art_nick and pubid = @pubid

        select @quoted_proc = QUOTENAME(@procname)
        
		exec @retcode = dbo.sp_MSguidtostr @artid, @guidstr out
		if @@ERROR <>0 OR @retcode <>0 return (1)

        select @source_object = QUOTENAME(user_name(uid)) + '.' + QUOTENAME(name) from sysobjects 
                where id = @source_objid 
        select @bool_filterclause=subset_filterclause from sysmergearticles 
                where name = @article and pubid = @pubid
                
        set @rgcol = NULL
        select @rgcol = QUOTENAME(name) from syscolumns where id = @source_objid and
                ColumnProperty(id, name, 'isrowguidcol') = 1
        if @rgcol is not NULL
            set @hasguid = 1
        else 
            begin
            set @hasguid = 0
            set @allhaveguids = 0
            end

        /*
        ** Process non looping articles that have either a boolean or a join_filter.
        */
        if ( @article_level > 0 OR (len(@bool_filterclause) > 0) ) 
            begin
            /*
            ** If the article has a previously generated view, then drop the view before 
            ** creating the new one.
            */
            set @viewname = NULL
            select @viewname =  name from sysobjects where id = @sync_objid and
                ObjectProperty (id, 'IsView') = 1  and
                ObjectProperty (id, 'IsMSShipped') = 1 
            if @viewname IS NOT NULL
                begin
                    select @quoted_view = QUOTENAME(@viewname)
                    exec ('drop view ' + @quoted_view)
                    if @@ERROR<>0 return (1)
                end
                /*
                ** Any join filter(s)? If any, process join filter(s)
            */
            if (@article_level > 0) 
                begin
                declare pub1 CURSOR LOCAL FAST_FORWARD FOR select join_filterclause, join_nickname, join_articlename,
                    join_unique_key, join_filterid from sysmergesubsetfilters where pubid=@pubid and artid=@artid
                FOR READ ONLY
                open pub1                                       
                fetch pub1 into @join_filterclause, @join_nick, @join_articlename, @join_unique_key, @join_filterid

                select @unqual_jointable = QUOTENAME(name) from sysobjects 
                    where id = (select objid from sysmergearticles where name=@join_articlename and pubid=@pubid) 
                
                select @join_viewname = object_name(sync_objid) from sysmergearticles where nickname = @join_nick and pubid = @pubid
                select @join_viewname = QUOTENAME(@join_viewname)

                if (@join_unique_key = 1 and (@bool_filterclause is null or len(@bool_filterclause) = 0) and
                    not exists (select * from sysmergesubsetfilters where pubid=@pubid and artid=@artid and join_filterid <> @join_filterid))
                    begin
                    set @simple_join_view = 1
                    set @view_rule = 'select ' + @source_object + '.* from ' + @source_object + ', ' +  @join_viewname + ' ' + @unqual_jointable + ' where ' + @join_filterclause
                    end
                else
                    begin
                    set @simple_join_view = 0
                    set @view_rule = 'select ' + @source_object + '.rowguidcol from ' + @source_object + ', ' +  @join_viewname + ' ' + @unqual_jointable + ' where ' + @join_filterclause
                    end
                    
                fetch next from pub1 into @join_filterclause, @join_nick, @join_articlename, @join_unique_key, @join_filterid
                WHILE (@@fetch_status <> -1)
                    begin
                    select @unqual_jointable = name from sysobjects 
                        where id = ( select objid from sysmergearticles where name=@join_articlename and pubid=@pubid) 
                
                    select @join_viewname = object_name(sync_objid) from sysmergearticles where nickname = @join_nick and pubid = @pubid
                    select @join_viewname = QUOTENAME(@join_viewname)
                    set @view_rule = @view_rule + ' union select ' + @source_object + '.rowguidcol from ' + @source_object + ', ' +  @join_viewname + ' ' + @unqual_jointable + ' where ' + @join_filterclause
                    fetch next from pub1 into @join_filterclause, @join_nick, @join_articlename, @join_unique_key, @join_filterid
                    end 
                close pub1
                deallocate pub1
                        
                if len(@bool_filterclause) > 0
                    set @view_rule = @view_rule + ' union select ' + @source_object + '.rowguidcol from '+ @source_object + ' where '+ @bool_filterclause
                -- Now do the actual view rule as a semi-join, if not a simple join on unique key
                if (@simple_join_view = 0)
                    set @view_rule = 'select * from ' + @source_object + ' where rowguidcol in (' + @view_rule + ')'
                end
            else  /* boolean filter only */
                select @view_rule = ' select * from '+ @source_object + ' where '+ @bool_filterclause
                            
            select @viewname = @publication + '_' + @article + '_VIEW'
            exec @retcode = dbo.sp_MSuniqueobjectname @viewname , @viewname output
            select @quoted_view = QUOTENAME(@viewname)
            
            if @retcode <> 0 or @@ERROR <> 0 return (1) 
            /* If we havent generated rowguidcol yet, use dummy rule that doesnt refer to it */
            if @hasguid = 0
                set @view_rule = ' select * from '+ @source_object
            exec ('create view '+ @quoted_view + ' as '+ @view_rule)
            /* Mark view as system object */                        
            execute ('sp_MS_marksystemobject ' + @quoted_view)
            if @hasguid = 1
                begin
                if @procname is not null
                    begin
                    exec ('drop procedure ' + @quoted_proc)
                    end
                else
                    begin
					set @procname = 'sel_' + substring(@guidstr, 1, 16) + substring(@pubidstr, 1, 16)
                    exec @retcode = dbo.sp_MSuniqueobjectname @procname , @procname output
                    if @retcode <> 0 or @@ERROR <> 0
                            return (1)
                    end
                select @owner = user_name(uid) from sysobjects 
                    where name = @viewname 
                exec dbo.sp_MSmakeviewproc @viewname, @owner, @procname, @rgcol
                end
            update sysmergearticles set sync_objid = OBJECT_ID (@viewname), view_type = @permanent,
                view_sel_proc = @procname where artid = @artid and pubid = @pubid 

            end /* end of view creation for this article */
        else if @procname is null and @hasguid = 1
            begin
            /* still make the select proc, although it selects directly from table */

			set @procname = 'sel_' + substring(@guidstr, 1, 16) + substring(@pubidstr, 1, 16)
            exec @retcode = dbo.sp_MSuniqueobjectname @procname , @procname output
            if @retcode <> 0 or @@ERROR <> 0 return (1) 
            select @owner = user_name(uid), @viewname = name from sysobjects 
                where id = @source_objid 
            exec dbo.sp_MSmakeviewproc @viewname, @owner, @procname, @rgcol
            update sysmergearticles set view_sel_proc = @procname
                where artid = @artid and pubid = @pubid 

            end
        
        select @art=min(indexcol) from #art where indexcol>@art
        end

    /* If there are looping articles, we must use a dynamic publication since no views on temp tables */
    update sysmergearticles set view_type = @temporary
        where pubid=@pubid and nickname not in (select art_nick from #art)
    if @@rowcount > 0
        begin
        if not exists (select * from sysmergepublications where dynamic_filters = 1 and pubid = @pubid)
            begin
            declare @repl_nick int
            /* treat these articles as if the publication were dynamic */
            execute @retcode = dbo.sp_MSgetreplnick @nickname = @repl_nick output
            if (@@error <> 0) or @retcode <> 0 or @repl_nick IS NULL 
		        begin
		        RAISERROR (14055, 11, -1)
		        RETURN(1)
		        end                 

            select @art_nick = min(nickname) from sysmergearticles where
                pubid = @pubid and view_type = @temporary
            while @art_nick is not null
                begin
                /* Loop over articles with circular filters.  Create dummy view and add rows to contents */
                select @article = name, @artid = artid, @source_objid = objid, @sync_objid = sync_objid, @procname = view_sel_proc from sysmergearticles 
                    where nickname=@art_nick and pubid = @pubid
                select @source_object = QUOTENAME(user_name(uid)) + '.' + QUOTENAME(name) from sysobjects 
                    where id = @source_objid 

                set @viewname = NULL
                select @viewname =  name from sysobjects where id = @sync_objid and
                    ObjectProperty (id, 'IsView') = 1  and
                    ObjectProperty (id, 'IsMSShipped') = 1 
                if @viewname IS NOT NULL
                    begin
                        select @quoted_view = QUOTENAME(@viewname)
                        exec ('drop view ' + @quoted_view)
                        if @@ERROR<>0 return (1)
                    end
                select @viewname = 'SYNC_' + @publication + '_' + @article 
                exec @retcode = dbo.sp_MSuniqueobjectname @viewname , @viewname output
                if @retcode <> 0 or @@ERROR <> 0 return (1) 
                select @quoted_view = QUOTENAME(@viewname)
                exec ('create view ' + @quoted_view + ' as select * from ' + @source_object + ' 
                        where 1 = 0 ')
                if @@ERROR<>0 return (1)
                update sysmergearticles set sync_objid = OBJECT_ID (@viewname),
                    view_sel_proc = NULL where artid = @artid and pubid = @pubid 
                if @@ERROR<>0 return (1)

				select @owner = user_name(uid) from sysobjects where id = @source_objid
				set @table = OBJECT_NAME(@source_objid)
        		exec @retcode = dbo.sp_addtabletocontents @table, @owner
                IF @@ERROR <> 0 or @retcode <> 0 return (1)
                
                select @art_nick = min(nickname) from sysmergearticles where
                    pubid = @pubid and view_type = @temporary and nickname > @art_nick
                end
            end
        end
        
    drop table #art
    if @allhaveguids = 1
        begin
        declare @dbname sysname
        set @dbname = db_name()
        /* create the filter expand procs now */
        set @filter_id = 0
        select @filter_id = min(join_filterid) from sysmergesubsetfilters where
                pubid = @pubid and join_filterid > @filter_id
        while @filter_id is not null
            begin
            set @filter_id_str = convert(nvarchar(10), @filter_id)
            select @procname = expand_proc
                from sysmergesubsetfilters where pubid = @pubid and join_filterid = @filter_id
            /* drop old proc, or generate a new procname */
            select @quoted_proc = QUOTENAME(@procname)
            if @procname is not null
                exec ('drop procedure ' + @quoted_proc)
            else
                begin
                set @procname = 'expand_' + @filter_id_str
                exec @retcode = dbo.sp_MSuniqueobjectname @procname, @procname output
                if @retcode <>0 return (1)
                update sysmergesubsetfilters set expand_proc = @procname where  pubid = @pubid and join_filterid = @filter_id
                end
            select @quoted_proc = QUOTENAME(@procname)
            select @quoted_pub = QUOTENAME(@publication)
            set @command = 'exec dbo.sp_MSmakeexpandproc ' + @quoted_pub + ' , ' + @filter_id_str + ', ' + @quoted_proc
            exec @retcode = master..xp_execresultset @command, @dbname
            if @retcode <> 0 return (1)
			exec dbo.sp_MS_marksystemobject @quoted_proc
            exec ('grant execute on ' + @quoted_proc + ' to public ')
            select @filter_id = min(join_filterid) from sysmergesubsetfilters where
                pubid = @pubid and join_filterid > @filter_id
            end
        end

    return (0)

FAILURE: 
    return (1)
go

exec dbo.sp_MS_marksystemobject sp_MSpublicationview
go

grant execute on dbo.sp_MSpublicationview to public
go

dump tran master with no_log
go

raiserror('Creating procedure sp_addmergesubscription', 0,1)
GO
CREATE PROCEDURE sp_addmergesubscription (
    @publication                    sysname,                    /* Publication name */
    @subscriber                     sysname = NULL,             /* Subscriber server */
    @subscriber_db                  sysname = NULL,             /* Subscription database */
    @subscription_type              nvarchar(15) = 'push',          /* Subscription type - push, pull */ 
    @subscriber_type                nvarchar(15) = 'local',         /* Subscriber type */ 
    @subscription_priority          real        = NULL,             /* Subscription priority */
    @sync_type                      nvarchar(15) = 'automatic',     /* subscription sync type */
    @frequency_type                 int = NULL,            
    @frequency_interval             int = NULL,        
    @frequency_relative_interval    int = NULL,
    @frequency_recurrence_factor    int = NULL,
    @frequency_subday               int = NULL,            
    @frequency_subday_interval      int = NULL,
    @active_start_time_of_day       int = NULL,
    @active_end_time_of_day         int = NULL,
    @active_start_date              int = NULL,
    @active_end_date                int = NULL,
    @optional_command_line          nvarchar(4000) = NULL,
    @description                    nvarchar(255) = NULL,
    @enabled_for_syncmgr            nvarchar(5) = 'false' /* Enabled for SYNCMGR: true or false */
    ) AS

    SET NOCOUNT ON

    /*
    ** Declarations.
    */
    declare @retcode                int
    declare @subnickname            int
    declare @subscriber_srvid       int 
    declare @publisher_srvid        int 
    declare @priority               real
    declare @subid                  uniqueidentifier
    declare @pubid                  uniqueidentifier    /* Publication id */
    declare @subscriber_typeid      smallint
    declare @merge_jobid            binary(16)          /* Scheduler jobid for the merge agent */
    declare @subscription_type_id   int   
    declare @distproc               nvarchar(255)
    declare @command                nvarchar(255)
    declare @inactive               tinyint
    declare @subscriber_bit         smallint
    declare @global                 tinyint     /* subscriber type is global */
    declare @push                   tinyint     /* subscription type is push */
    declare @partnerid              uniqueidentifier    /* Partner replica identifier */
    declare @sync_typeid            tinyint
    declare @nosync                 tinyint     
    declare @automatic              tinyint     
    declare @distributor            sysname
    declare @distribdb              sysname
    declare @active                 tinyint
    declare @publisher              sysname
    declare @publisher_db           sysname
    declare @found                  int
    declare @datasource_type        int
    declare @datasource_path        sysname
    DECLARE @platform_nt            binary
    declare @is_jet					int
    declare @Jet_datasource_path	sysname
    
    /*
    ** Initializations.
    */
    set @datasource_type = 0    /* Default SQL Server */
    set @datasource_path = NULL 
    set @platform_nt = 0x1  
    SET @nosync             = 2       /* Const: synchronization type 'nosync' */
    SET @automatic          = 1       /* Const: synchronization type 'automatic' */
    set @inactive           = 0
    SET @subscriber_bit     = 4  
    set @global             = 1
    set @push               = 0
    set @pubid              = NULL         
    set @active             = 1     /* Const: subscription status 'active', 0 for pull subscriptions at publisher side */
    set @publisher          = @@SERVERNAME
    set @publisher_db       = DB_NAME()
    select @found           = 1    /* Any non-NULL value is fine */
    /*
    ** Parameter Check: @subscription_type.
    ** Set subscriber_typeid based on the @subscription_type specified.
    **
    **   subscription_type    subscription_type
    **   =================    ===============
    **             0            push
    **             1            pull
    */
    if LOWER(@subscription_type) NOT IN ('push', 'pull')
        BEGIN
            RAISERROR (14128, 16, -1)
            RETURN (1)
        END
    IF LOWER(@subscription_type) = 'push'
        set @subscription_type_id = 0
    else 
        set @subscription_type_id = 1

    /*
    ** Security Check.
    */

    IF @subscription_type_id = 0 
    BEGIN
        exec @retcode = dbo.sp_MSreplcheck_publish
        if @@ERROR <> 0 or @retcode <> 0
            return(1)
    END
    ELSE
    BEGIN
        exec @retcode = dbo.sp_MSreplcheck_pull @publication
        if @@ERROR <> 0 or @retcode <> 0
            return(1)
    END

    /* This SP is called through UI with a subscription_type = pull; in this scenario
    ** the status of the subscription is inactive before merge agent is run
    */
    
    if @subscription_type_id = 1 
        select @active = 0


    /*
    ** Validate that the publisher is a valid server
    */
    select @publisher_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@publisher)
    IF @publisher_srvid IS NULL
        BEGIN
            RAISERROR (14010, 16, -1)
            RETURN (1)
        END

    /*
    ** Parameter Check: @subscriber
    ** Check to make sure that the subscriber is defined
    */
    IF @subscriber IS NULL
        BEGIN
            RAISERROR (14043, 16, -1, '@subscriber')
            RETURN (1)
        END

     IF NOT EXISTS (SELECT * FROM master..sysservers WHERE UPPER(srvname) = UPPER(@subscriber)
                     AND (srvstatus & @subscriber_bit) <> 0)
               BEGIN
                   RAISERROR (14010, 16, -1)
                   RETURN (1)
               END

    IF @subscriber = 'all'
        BEGIN
            RAISERROR (14136, 16, -1)
            RETURN (1)
        END

    /*
    ** Get distribution server information for remote RPC call.
    */
    EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
         @distribdb   = @distribdb OUTPUT
    IF @@ERROR <> 0 or @retcode <> 0
        BEGIN
        GOTO FAILURE
        END

        SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + 
            '.dbo.sp_MShelp_subscriber_info '
    exec @distproc @publisher, @subscriber, @found output
    if (@found <> 1) 
        BEGIN
            RAISERROR (14085, 16, -1)
            RETURN (1)
        END

	select @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MScheck_Jet_Subscriber '
	exec @retcode = @distproc @subscriber, @is_jet OUTPUT, @Jet_datasource_path OUTPUT
	if @retcode<>0
		return (1)
	
	IF @is_jet = 1
	BEGIN
        select @datasource_type = 2
        select @datasource_path = @Jet_datasource_path
    END

    EXECUTE @retcode = dbo.sp_validname @subscriber
    IF @@ERROR <> 0 OR @retcode <> 0
       RETURN (1)

    /*
    ** Parameter Check: @subscriber_db
    */
    IF @subscriber_db IS NULL
    BEGIN
        RAISERROR (14043, 16, -1, '@subscriber_db')
        RETURN (1)
    END

    IF @subscriber_db = 'all'
    BEGIN
        RAISERROR (14136, 16, -1)
        RETURN (1)
    END

    /*
    **  Check to see if system tables exist. If not create them. Since under current
    **  design every database is qualified for subscribing.
    */
    
    IF not exists (select name from sysobjects where name='sysmergesubscriptions')
        BEGIN
            execute @retcode = dbo.sp_MScreate_mergesystables
                if @@ERROR <> 0 or @retcode <> 0
                    begin
                        return (1)
                    end
        END 
        
    /*
    ** Parameter Check: @publication.
    ** Check to make sure that the publication exists and that it conforms
    ** to the rules for identifiers.
    */
    if NOT EXISTS (select * FROM sysmergepublications 
        WHERE name = @publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name())
        BEGIN
            RAISERROR (20026, 16, -1, @publication)
            RETURN (1)
        END

    if @pubid IS NULL
        select @pubid = pubid FROM sysmergepublications 
            WHERE name = @publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()
    if @partnerid IS NULL
        begin
            select @partnerid = subid FROM sysmergesubscriptions 
                WHERE srvid = @publisher_srvid and db_name = @publisher_db and pubid = @pubid
        end                     

    /*
    ** Parameter Check: @subscriber_type.
    ** Set subscriber_typeid based on the @subscriber_type specified.
    **
    **   subscriber_type     subscriber_type
    **   =================    ===============
    **             1            global
    **             2            local
    **             3            anonymous
    **                          Type 'republisher' is taken out for B3. We may want to add this back later.
    */
    if LOWER(@subscriber_type) NOT IN ('local', 'global', 'anonymous')
        BEGIN
            RAISERROR (20023, 16, -1)
            RETURN (1)
        END

    if LOWER(@subscriber_type) IN ('global')
        set @subscriber_typeid = 1
    else if LOWER(@subscriber_type) IN ('local')
        set @subscriber_typeid = 2
    else if LOWER(@subscriber_type) IN ('anonymous')       
        set @subscriber_typeid = 3

	/* Do not allow anonymous for a PUSH subscription */
	if @subscriber_typeid = 3 and @subscription_type_id = 0
        BEGIN
            RAISERROR (20087, 16, -1)
            RETURN (1)
        END
	
    /* 
    ** Assign priority appropriately - choose 0.99 times the minimum priority
    ** of the global replicas.
    */
    if (@subscription_priority >= 100.0 or @subscription_priority < 0.0)
        BEGIN
            RAISERROR (20088, 16, -1)
            RETURN (1)
        END
    if (@subscription_priority IS NULL)
        begin
            select @priority = 0.99 * min(priority) from sysmergesubscriptions where subscriber_type = 1
            if (@priority IS NOT NULL)
                select @subscription_priority = @priority
            if (@subscription_priority IS NULL) 
                select @subscription_priority = 0.0
        end
    /*
    ** For local and anonymous subscriptions the priority is 0.0
    */
    if LOWER(@subscriber_type) IN ('local', 'anonymous')
        select @subscription_priority = 0.0
    
    /*
    ** Validate that the subscriber is a valid server
    */
    select @subscriber_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@subscriber)
    IF @subscriber_srvid IS NULL
        BEGIN
            RAISERROR (14010, 16, -1)
            RETURN (1)
        END

    IF exists (select * from sysobjects where name= 'syssubscriptions')
    begin
        if exists (select name from sysmergearticles where pubid=@pubid and objid in
            (select objid from sysarticles where artid in
                (select artid from syssubscriptions where dest_db=@subscriber_db and srvid=@subscriber_srvid)))
        begin
            RAISERROR(20084, 16, -1, @publication, @subscriber_db)
            RETURN (1)
        end
    end

    /*
    ** Making it possible for a deleted subscription to come back.
    ** UNDONE : This disallows second pull subscription from being added unless the previous 
    ** subscription was initial synced.
    */
    if EXISTS (select db_name, srvid
            FROM sysmergesubscriptions
            WHERE db_name = @subscriber_db
            AND srvid = @subscriber_srvid                          
            AND pubid = @pubid AND status <>2) --We can definitely add back subscriptions that were deleted.
        BEGIN
            RAISERROR (14058, 16, -1)
            RETURN (1)
        END
        
    IF EXISTS (select db_name, srvid FROM sysmergesubscriptions 
        WHERE db_name = @subscriber_db AND srvid = @subscriber_srvid AND pubid = @pubid AND status = 2) 
            BEGIN
            	select @subid = subid from sysmergesubscriptions 
            		WHERE db_name = @subscriber_db AND srvid = @subscriber_srvid AND pubid = @pubid
				delete  from sysmergesubscriptions where subid = @subid
				delete from MSmerge_replinfo where repid = @subid
            END
	select @subid = newid()    
	
   /*
   ** Parameter Check: @sync_type.
   ** Set sync_typeid based on the @sync_type specified.
   **
   **   sync_typeid     sync_type
   **   ===========     =========
   **             1     automatic
   **             2     nosync
   */


   IF LOWER(@sync_type) NOT IN ('automatic', 'none')
       BEGIN
           RAISERROR (14052, 16, -1)
           RETURN (1)
       END


    /*
    ** If current publication contains an article without rowguidcol, do not allow no-sync subscription
    */
   IF LOWER(@sync_type) = 'automatic'
   BEGIN
        SET @sync_typeid = @automatic
   END
   ELSE
   BEGIN
        if exists (select * from sysmergearticles a where pubid=@pubid and 
            not exists (select * from syscolumns c where c.id = a.objid and ColumnProperty(c.id, c.name, 'IsRowGuidCol') = 1))
            
            BEGIN
                Raiserror(20086, 16, -1, @publication)
                RETURN (1)
            END
        else 
            SET @sync_typeid = @nosync
   END


    /*
    ** UNDONE: Validate that the publisher is of type "republisher"
    */
    begin tran
    save TRAN addmergesubscription
        /* Generate a guid for the Subscriber ID */
    
        /* Look for existing nickname from any other subscription */
        exec @retcode = dbo.sp_MSgetreplnick @subscriber, @subscriber_db , NULL,  @subnickname out
        if (@@error <> 0) or @retcode <> 0 
			GOTO FAILURE
            
        /* Generate a new replica nickname from the @subid */
        if (@subnickname is null)
        begin
            EXECUTE dbo.sp_MSgenreplnickname @subid, @subnickname output
            if @@ERROR<>0 
                GOTO FAILURE
        end
            
        /*
        ** The subscription doesn't exist, so let's add it to sysmergesubscriptions 
        */
        INSERT sysmergesubscriptions (subid, 
                                      partnerid,
                                      datasource_type, 
                                      datasource_path, 
                                      srvid, 
                                      db_name, 
                                      pubid,
                                      status, 
                                      subscriber_type,
                                      subscription_type,
                                      priority, 
                                      sync_type, 
                                      description,
                                      login_name)
                        VALUES (@subid,
                            @partnerid,
                            @datasource_type,
                            @datasource_path,
                            @subscriber_srvid,
                            @subscriber_db,
                            @pubid,
                            @active,
                            @subscriber_typeid,
                            @subscription_type_id,
                            @subscription_priority,
                            @sync_typeid,
                            @description,
                            suser_sname(suser_sid()))          
        if @@ERROR <> 0
            BEGIN
                GOTO FAILURE
            END
                
        /*
        ** Get distribution server information for remote RPC call.
        */
        EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
           @distribdb   = @distribdb OUTPUT
        IF @@ERROR <> 0 or @retcode <> 0
            BEGIN
                GOTO FAILURE
            END

        SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + 
            '.dbo.sp_MSadd_merge_subscription'
        EXEC @retcode = @distproc 
            @publisher = @@SERVERNAME, 
            @publisher_db = @publisher_db, 
            @publication = @publication,
            @subscriber = @subscriber, 
            @subscriber_db = @subscriber_db, 
            @subscription_type = @subscription_type_id,
            @sync_type = @sync_typeid, 
            @status = @active,
            @frequency_type = @frequency_type,
            @frequency_interval = @frequency_interval,
            @frequency_relative_interval = @frequency_relative_interval,
            @frequency_recurrence_factor = @frequency_recurrence_factor,
            @frequency_subday = @frequency_subday,
            @frequency_subday_interval = @frequency_subday_interval,
            @active_start_time_of_day = @active_start_time_of_day,
            @active_end_time_of_day = @active_end_time_of_day,
            @active_start_date = @active_start_date,
            @active_end_date = @active_end_date,
            @optional_command_line = @optional_command_line,
            @merge_jobid = @merge_jobid OUTPUT 
        IF @@ERROR <> 0 OR @retcode <> 0
            begin   
                goto FAILURE
            end
            
        /*
        **  Add row for subscription in MSmerge_replinfo.
        */
        insert MSmerge_replinfo(repid, replnickname, merge_jobid)
                values (@subid, @subnickname, @merge_jobid)
        if @@ERROR <> 0
        	BEGIN
                GOTO FAILURE
            END

        /* Conditional support for MobileSync */
        if LOWER(@enabled_for_syncmgr) = 'true'
        BEGIN

            /* MobileSync Support */
            declare @distributor_server                 sysname
            declare @distributor_security_mode          int
            declare @distributor_login                  sysname
            declare @distributor_password               sysname

            /* 
            ** The registry entry needs to be created only for push subscriptions -  
            ** i.e - need not be called when a pull subscription is created at the 
            ** subscriber and sp_addmergesubscription is being called then.
            */
            
            IF @subscription_type_id = 0 
            BEGIN
                EXECUTE @retcode = dbo.sp_helpdistributor
                    @distributor = @distributor_server OUTPUT               /* Distributor RPC server name */
                IF @@ERROR <> 0 or @retcode <> 0
                    BEGIN
                        GOTO FAILURE
                    END

                -- Always use integrated security on winNT
                if (@platform_nt = platform() & @platform_nt )
                    begin
                        set @distributor_security_mode = 1
                    end
                -- For Win9x the dist publisher and distributor are the same machine                
                else
                    begin
                        select  @distributor_security_mode = 0,
                            @distributor_login  = login,
                            @distributor_password = [REDACTED]
                        from msdb..MSdistpublishers where UPPER(name) = UPPER(@@servername)
                    end

                /* Call sp_MSregistersubscription so that the subscription can be synchronized via Onestop etc. */
                exec @retcode = dbo.sp_MSregistersubscription @replication_type = 2,
                                    @publisher = @@SERVERNAME,
                                    @publisher_db = @publisher_db,
                                    @publication = @publication,
                                    @subscriber = @subscriber,
                                    @subscriber_db = @subscriber_db,
                                    @distributor = @distributor,
                                    @distributor_security_mode = @distributor_security_mode,
                                    @distributor_login = @distributor_login,
                                    @distributor_password = [REDACTED]
                                    @subscription_id = @subid,
                                    @subscription_type = @subscription_type_id
                IF @@error <> 0 OR @retcode <> 0
                    BEGIN
                        GOTO FAILURE
                    END

            END                                    
        END     
    COMMIT TRAN
    return (0)

FAILURE:
    RAISERROR (14057, 16, -1)
    /* UNDONE : This code is specific to 6.X nested transaction semantics */
    if @@TRANCOUNT > 0
    begin
        ROLLBACK TRANSACTION addmergesubscription
        COMMIT TRANSACTION
    end
    RETURN (1)

go
exec dbo.sp_MS_marksystemobject sp_addmergesubscription 
go

grant execute on dbo.sp_addmergesubscription to public
go

raiserror('Creating procedure sp_changemergesubscription', 0,1)
GO

CREATE PROCEDURE sp_changemergesubscription (
    @publication        sysname = NULL, /* Publication name */
    @subscriber         sysname = NULL,  /* Subscriber server */
    @subscriber_db      sysname = NULL,  /* Subscription database */
    @property           sysname = NULL, /* The property to change */
    @value              nvarchar(255) = NULL    /* The new property value */
    ) AS

    SET NOCOUNT ON

    /*
    ** Declarations.
    */
    declare @subscriber_bit         smallint
    declare @subscriber_srvid       int
    declare @publisher_srvid        int
    declare @retcode                int
    declare @pubid                  uniqueidentifier
    declare @subid                  uniqueidentifier
    declare @partnerid              uniqueidentifier
    declare @sync_typeid            tinyint
    declare @nosync                 tinyint
    declare @automatic              tinyint
     
    declare @artid                  uniqueidentifier
    declare @schematype             int
    declare @schemaversion          int
    declare @schemaguid             uniqueidentifier
    declare @db_name                sysname
    declare @subscriber_type        int
    declare @schematext             nvarchar(2000)
    declare @publisher              sysname
    declare @publisher_db           sysname
     

    /*
    ** Initializations.
    */
    SET @nosync         = 2     /* Const: synchronization type 'none' */
    SET @automatic      = 1     /* Const: synchronization type 'automatic' */
    set @publisher      = @@SERVERNAME
    set @publisher_db   = DB_NAME()

    /*
    ** Security Check.
    */
    BEGIN
        exec @retcode = dbo.sp_MSreplcheck_subscribe
        if @@ERROR <> 0 or @retcode <> 0
            return(1)
    END


    /*
    **  Check to see if current database is doing publishing/subscribing
    */
    IF not exists (select name from sysobjects where name='sysmergesubscriptions')
        BEGIN
            RAISERROR (14055, 16, -1)
            RETURN (1)
        END

    /*
    ** Parameter Check:  @property.
    ** If the @property parameter is NULL, print the options.
    */

    IF @property IS NULL
        BEGIN
            CREATE TABLE #tab1 (properties sysname)
            INSERT INTO #tab1 VALUES ('sync_type')
            INSERT INTO #tab1 VALUES ('priority')
            INSERT INTO #tab1 VALUES ('description') 
            select * FROM #tab1
            RETURN (0)
        END

    /*
    ** Parameter Check:  @publication.
    ** Make sure that the publication exists.
    */

    IF @publication IS NULL
        BEGIN
            RAISERROR (14043, 16, -1, '@publication')
            RETURN (1)
        END

    select @pubid = pubid FROM sysmergepublications 
        WHERE name = @publication  and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()
    IF @pubid IS NULL
        BEGIN
            RAISERROR (20026, 11, -1, @publication)
            RETURN (1)
        END

    /*
    ** Validate that the publisher is a valid server
    */
    select @publisher_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@publisher)
    IF @publisher_srvid IS NULL
        BEGIN
            RAISERROR (14010, 16, -1)
            RETURN (1)
        END

    /*
    ** Parameter Check:  @subscriber.
    ** Check to make sure we have a valid subscriber.
    */
    IF @subscriber IS NULL
        BEGIN
            RAISERROR (14043, 16, -1, '@subscriber')
            RETURN (1)
        END
    /*
    ** Validate that the subscriber is a valid server
    */
    select @subscriber_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@subscriber)
    IF @subscriber_srvid IS NULL
        BEGIN
            RAISERROR (14010, 16, -1)
            RETURN (1)
        END

    /*
    ** Check to see if you have a local / global subscription on this publication
    */
    set @subid = NULL
    select @subid = subs1.subid, 
     
    @pubid = pubs.pubid, /* identified from publication name */
    @subscriber_type=subs1.subscriber_type,
     
        @partnerid = subs2.subid from
        sysmergesubscriptions   subs1,
        sysmergesubscriptions   subs2,
        sysmergepublications    pubs
        where subs1.srvid = @subscriber_srvid
            and subs1.db_name = @subscriber_db
            and subs2.srvid = @publisher_srvid
            and subs2.db_name = @publisher_db
            and subs1.pubid = subs2.subid
            and subs2.pubid = pubs.pubid
            and pubs.name = @publication 
            and UPPER(pubs.publisher)=UPPER(@@servername) 
            and pubs.publisher_db=db_name()

    if @subid IS NULL 
        begin
            RAISERROR (14050, 11, -1)
            RETURN(1)
        end                 

    /*
    ** Parameter Check:  @property.
    ** Check to make sure that @property is a valid property in
    ** sysarticles.
    */

    
    IF LOWER(@property) NOT IN ('sync_type', 'priority', 'description')
        BEGIN
            RAISERROR (20078, 16, -1)
            RETURN (1)
        END

    /*
    ** Change the property.
    */
    IF LOWER(@property) = 'sync_type'
        BEGIN

            /*
            ** Check to make sure that we have a valid sync_type.
            */

            IF LOWER(@value) NOT IN ('automatic', 'none')
                BEGIN
                    RAISERROR (14052, 16, -1)
                    RETURN (1)
                END

            /*
            ** Determine the integer value for the sync_type.
            */

            IF LOWER(@value) = 'automatic'
                SET @sync_typeid = @automatic
            ELSE
            BEGIN
    /*
    **  If current publication contains an article without rowguidcol, do not allow no-sync subscription
    */

                if exists (select * from sysmergearticles a where pubid = @pubid and 
                    not exists (select * from syscolumns c where c.id=a.objid and columnproperty (c.id, c.name, 'isrowguidcol')=1))
                begin
                    Raiserror(20086, 16, -1, @publication)
                    RETURN (1)
                end
                else SET @sync_typeid = @nosync
            END

            /*
            ** Update the subscription with the new sync_type.
            */

            UPDATE sysmergesubscriptions
                SET sync_type = @sync_typeid
                WHERE subid = @subid
            IF @@ERROR <> 0
                BEGIN
                    RAISERROR (14053, 16, -1)
                    RETURN (1)
                END

        END
        
    IF LOWER(@property) = 'description'
        BEGIN
        UPDATE sysmergesubscriptions
                SET description = @value
                WHERE subid = @subid
            IF @@ERROR <> 0
                BEGIN
                    RAISERROR (14053, 16, -1) 
              
                    RETURN (1)
                END

        END
        
     
    IF LOWER(@property) = 'priority'
    BEGIN

    select @db_name = db_name from sysmergesubscriptions
        where (pubid=@pubid) and (subid=@pubid)
        IF @db_name <> db_name()
        BEGIN
            RAISERROR (20047, 16, -1)
            RETURN (1)
        END  

    /* Only the original publisher can change priority of a global subscriptions */

        IF @subscriber_type<>1  
            BEGIN
                RAISERROR (20044, 16, -1)  /* Local subscriber does not have priority*/
                RETURN (1)
            END

        IF convert(real, @value)>100.0
            BEGIN
                RAISERROR (20049, 16, -1)  /* Don't accept priority greater than 100 */
                RETURN (1)
            END
        
        select @schemaversion = schemaversion from sysmergeschemachange
        if (@schemaversion is NULL)
        set @schemaversion = 1
        else
            select @schemaversion = 1 + max(schemaversion) from sysmergeschemachange
            
         
        set @schemaguid = newid()
        set @artid = newid()
        set @schematype = 8 /* change priority */
        select @schematext = 'exec dbo.sp_MSchange_priority '+ '''' + convert(nchar(36),@subid) + '''' + ',' + '''' + @value + '''' 
         
    BEGIN TRANSACTION change_priority
        exec dbo.sp_MSchange_priority @subid,  @value
            if @@ERROR<>0 goto UNDO
        exec @retcode=sp_MSinsertschemachange @pubid, @artid, @schemaversion, @schemaguid, @schematype, @schematext
            if @@ERROR<>0 or @retcode<>0 goto UNDO
    COMMIT TRANSACTION
    
    END
    
    /*
    ** Return succeed. It is not an error message.
    */

    RAISERROR (14054, 10, -1)
    RETURN (0)
UNDO:
    if @@TRANCOUNT = 1 
        ROLLBACK TRANSACTION 
    else
        COMMIT TRANSACTION 
    return (1)
go

exec dbo.sp_MS_marksystemobject sp_changemergesubscription 
go

grant execute on dbo.sp_changemergesubscription to public
go

raiserror('Creating procedure sp_helpmergesubscription', 0,1)
GO

CREATE PROCEDURE sp_helpmergesubscription(
    @publication            sysname = '%',      /* Publication name */
    @subscriber             sysname = '%',      /* Subscriber server */
    @subscriber_db          sysname = '%',      /* Subscription database */
    @publisher              sysname = '%',      /* Publisher server */
    @publisher_db           sysname = '%',      /* Publisher database */
    @subscription_type      nvarchar(15) = 'both', /* Subscription type - push or pull */ 
    @found int = NULL OUTPUT
    )AS

    SET NOCOUNT ON

    /*
    ** Declarations.
    */

    declare @db                 sysname
    declare @retcode            int
    declare @subscriber_bit     smallint
    declare @srvid              int
    declare @pubid              uniqueidentifier
    declare @subid              uniqueidentifier
    declare @partnerid          uniqueidentifier
    declare @cursor_open        int
    declare @no_row             bit
    declare @subscription_type_id int

    /*
    ** Initializations.
    */
    set @subscriber_bit     = 4
    set @cursor_open        = 0                 

    /*
    ** Initializations of @now_row.
    */
    IF @found is NULL
    BEGIN
        SELECT @no_row=0
    END
    ELSE
    BEGIN
        SELECT @no_row=1
    END

    select @db=db_name() -- so that it can appear in dynamic query

    /*
    **  Calling sp_help* is all right whether current database is enabled for pub/sub or not
    */

    IF not exists (select * from sysobjects where name='sysmergesubscriptions')
        RETURN (0)
    
    /* Security check */
    EXEC @retcode = dbo.sp_MSreplcheck_pull @publication = @publication, 
        @raise_fatal_error = 0
    if @@ERROR <> 0 or @retcode <> 0
        return(1)

    /*
    ** Parameter Check: @subscription_type.
    ** Set subscription_typeid based on the @subscription_type specified.
    **
    **   subscription_type    subscription_type
    **   =================    ===============
    **             0            push
    **             1            pull
    **            2         both
    */
    if LOWER(@subscription_type) NOT IN ('push', 'pull', 'both')
        BEGIN
            RAISERROR (20079, 16, -1)
            RETURN (1)
        END
    IF LOWER(@subscription_type) = 'both'
        set @subscription_type_id = 2
    else IF LOWER(@subscription_type) = 'push'
        set @subscription_type_id = 0
    else 
        set @subscription_type_id = 1

    /*
    ** Parameter Check: @publisher
    ** Check to make sure that the publisher is defined
    */
    IF @publisher <> '%'
    BEGIN
        EXECUTE @retcode = dbo.sp_validname @publisher
        IF @@ERROR <> 0 OR @retcode <> 0
            RETURN (1)
    END

    /*
    ** Parameter Check:  @subscriber.
    ** If remote server, limit the view to the remote server's subscriptions.
    ** Make sure that the name isn't NULL.
    */
    if @subscriber IS NULL
        BEGIN
            RAISERROR (14043, 16, -1, '@subscriber')
            RETURN (1)
        END

    /*
    ** Parameter Check:  @subscriber.
    ** Check if remote server is defined as a subscription server, and
    ** that the name conforms to the rules for identifiers.
    */

    if @subscriber <> '%'
        BEGIN
            EXECUTE @retcode = dbo.sp_validname @subscriber

            if @retcode <> 0 OR @@ERROR <> 0
                RETURN (1)

            if NOT EXISTS (select *
                            FROM master..sysservers
                            WHERE UPPER(srvname) = UPPER(@subscriber)
                            AND (srvstatus & @subscriber_bit) <> 0)
                BEGIN
                    --RAISERROR (14010, 16, -1)
                    RETURN (1)
                END
        END

    /*
    ** Parameter Check:  @publication.
    ** If the publication name is specified, check to make sure that it
    ** conforms to the rules for identifiers and that the publication
    ** actually exists.  Disallow NULL.
    */
    if @publication IS NULL
        BEGIN
            RAISERROR (14043, 16, -1, '@publication')
            RETURN (1)
        END

    /*
    ** Get subscriptions
    */
    if @publication <>'%'
    begin
        execute @retcode = dbo.sp_MSsubsetpublication @publication
        if @@ERROR <> 0 or @retcode<>0
                Return (1)
    end
    
    create table #helpsubscription
                (
                    publication             sysname     NOT NULL,
                    publisher               sysname     NOT NULL,
                    publisher_db            sysname     NOT NULL,
                    subscriber              sysname     NOT NULL,
                    subscriber_db           sysname     NOT NULL,
                    status                  int         NOT NULL,
                    subscriber_type         int         NOT NULL,
                    subscription_type       int         NOT NULL,
                    priority                float(8)    NOT NULL,
                    sync_type               tinyint     NOT NULL,
                    description             nvarchar(255) NULL,
                    merge_jobid             binary(16)  NULL,
                    full_publication        tinyint NULL 
                )


    /* 
    ** Performance Optimization: Eliminate the 'LIKE' clause for publication name.
    **                           Empirical evidence shows almost 50% speed improvement when
    **                           opening the cursor if publication name is provided.
    */
    IF (@publication <> '%')
        insert into #helpsubscription select distinct pubs.name, servers2.srvname, subs2.db_name, servers1.srvname, subs1.db_name, 
                        subs1.status, subs1.subscriber_type, subs1.subscription_type, subs1.priority, 
                        subs1.sync_type, subs1.description, replinfo.merge_jobid, pubs.publication_type

                FROM  sysmergesubscriptions     subs1,
                      sysmergesubscriptions     subs2,
                      MSmerge_replinfo      replinfo,
                      master..sysservers        servers1,
                      master..sysservers        servers2,
                      sysmergepublications  pubs
                    where subs1.subid <> subs2.subid 
                        and subs1.status <> 2 
                        and subs2.subid = subs1.partnerid
                        and pubs.pubid = subs1.pubid
                        and pubs.pubid = subs2.pubid
                        and servers1.srvid = subs1.srvid
                        and servers2.srvid = subs2.srvid
                        and pubs.name =  @publication 
                        and replinfo.repid = subs1.subid
                        and (suser_sname(suser_sid()) = subs1.login_name OR is_member('db_owner')=1 OR is_srvrolemember('sysadmin') = 1)
                        and subs1.db_name like @subscriber_db
                        and subs2.db_name like @publisher_db 
                        and ((@subscriber = N'%') or (UPPER(servers1.srvname) = UPPER(@subscriber))) 
                        and ((@publisher = N'%') or (UPPER(servers2.srvname) = UPPER(@publisher)))
                        and (subs1.subscription_type = @subscription_type_id or @subscription_type_id = 2)
    ELSE
        insert into #helpsubscription select distinct pubs.name, servers2.srvname, subs2.db_name, servers1.srvname, subs1.db_name, 
                        subs1.status, subs1.subscriber_type, subs1.subscription_type, subs1.priority, 
                        subs1.sync_type, subs1.description, replinfo.merge_jobid, pubs.publication_type

                FROM  sysmergesubscriptions     subs1,
                      sysmergesubscriptions     subs2,
                      MSmerge_replinfo      replinfo,
                      master..sysservers        servers1,
                      master..sysservers        servers2,
                      sysmergepublications  pubs
                    where subs1.subid <> subs2.subid 
                        and subs1.status <> 2 
                        and subs2.subid = subs1.partnerid
                        and pubs.pubid = subs1.pubid
                        and pubs.pubid = subs2.pubid
                        and servers1.srvid = subs1.srvid
                        and servers2.srvid = subs2.srvid
                        and replinfo.repid = subs1.subid
                        and (suser_sname(suser_sid()) = subs1.login_name OR is_member('db_owner')=1 OR is_srvrolemember('sysadmin') = 1)
                        and subs1.db_name like @subscriber_db
                        and subs2.db_name like @publisher_db 
                        and ((@subscriber = N'%') or (UPPER(servers1.srvname) = UPPER(@subscriber))) 
                        and ((@publisher = N'%') or (UPPER(servers2.srvname) = UPPER(@publisher)))
                        and (subs1.subscription_type = @subscription_type_id or @subscription_type_id = 2)
        

    if exists (select * from #helpsubscription)
        select @found = 1
    else
        select @found = 0 
        
    if @no_row = 1
        goto DONE

    IF LOWER(@subscription_type) = 'push' or LOWER(@subscription_type) = 'both'
        begin
            select 'subscription_name'  = subscriber + ':' + subscriber_db, *
                from #helpsubscription order by publisher, publisher_db, publication, subscriber, subscriber_db
        end
    else 
        begin
            select 'subscription_name'      = publisher + ':' + publisher_db + ':' + publication, *
                from #helpsubscription order by publisher, publisher_db, publication, subscriber, subscriber_db
        end

    select @retcode = 0
DONE:
    if (@cursor_open = 1)
        begin
            close #cursor
            deallocate #cursor
        end         
    drop table #helpsubscription
    return @retcode 
go
exec dbo.sp_MS_marksystemobject sp_helpmergesubscription
go

grant execute on dbo.sp_helpmergesubscription to public
go

raiserror('Creating procedure sp_dropmergesubscription', 0,1)
GO
CREATE PROCEDURE sp_dropmergesubscription(
    @publication        sysname = NULL,             /* Publication name */
    @subscriber         sysname = NULL,             /* Subscriber server */
    @subscriber_db      sysname = NULL,             /* Subscription database */
    @subscription_type  nvarchar(15) = 'push',          /* Subscription type - push, pull, both */ 
    @ignore_distributor bit = 0,
    @reserved 			bit = 0
    )AS

    SET NOCOUNT ON

    /*
    ** Declarations.
    */
    declare @retcode                int
    declare @subscriber_bit         smallint
    declare @subscriber_type        smallint
    declare @subscriber_srvid       int
    declare @publisher_srvid        int
    declare @pubid                  uniqueidentifier
    declare @subid                  uniqueidentifier
    declare @partnerid              uniqueidentifier
    declare @subscription_type_id   int   
    declare @found_subscription     int   
    declare @local_server           sysname
    declare @local_db               sysname
    declare @cmd                    nvarchar(290)
    declare @distributor            sysname
    declare @distribdb              sysname
    declare @distproc               nvarchar(512)
    declare @pubidstr               nvarchar(38)
    declare @publisher              sysname
    declare @publisher_db           sysname

    declare @implicit_transaction	int
	declare @close_cursor_at_commit int

	select @close_cursor_at_commit = 0
	select @implicit_transaction = 0

	/*
	** Save setting values first before changing them
	*/
	IF (@reserved = 0)
	BEGIN
		SELECT @implicit_transaction = @@options & 2
		SELECT @close_cursor_at_commit = @@options & 4
		SET IMPLICIT_TRANSACTIONS OFF
		SET CURSOR_CLOSE_ON_COMMIT OFF
	END

     /*
    ** Initializations.
    */
    set @subscriber_bit     = 4
    set @subscription_type_id = -1
    set @found_subscription = 0                     
    set @local_db           = DB_NAME()
    set @local_server       = @@SERVERNAME
    set @publisher          = @@SERVERNAME
    set @publisher_db       = DB_NAME()

    /*
    **  Check to see if current database is enabled for publishing/subscribing
    */
    IF not exists (select name from sysobjects where name='sysmergesubscriptions')
        BEGIN
            RAISERROR (14055, 16, -1)
            RETURN (1)
        END

    /*
    ** Parameter Check: @subscription_type.
    ** Set subscription_typeid based on the @subscription_type specified.
    **
    **   subscription_type    subscription_type
    **   =================    ===============
    **             0            push
    **             1            pull
    */
    if LOWER(@subscription_type) NOT IN ('both', 'push', 'pull')
        BEGIN
            RAISERROR (14128, 16, -1)
            RETURN (1)
        END
    IF LOWER(@subscription_type) = 'both'
        begin
            EXECUTE dbo.sp_dropmergesubscription @publication = @publication,
                            @subscriber = @subscriber,
                            @subscriber_db = @subscriber_db,
                            @subscription_type = 'push',
                            @ignore_distributor = @ignore_distributor,
                            @reserved = 1
            EXECUTE dbo.sp_dropmergesubscription @publication = @publication,
                            @subscriber = @subscriber,
                            @subscriber_db = @subscriber_db,
                            @subscription_type = 'pull',
                            @ignore_distributor = @ignore_distributor,
							@reserved = 1
            RETURN (0)
        end 
    IF LOWER(@subscription_type) = 'push'
        set @subscription_type_id = 0
    else 
        set @subscription_type_id = 1

    /*
    ** Parameter validation (different for push and pull modes)
    */

    IF LOWER(@subscription_type) = 'push'
        begin
            /*
            ** Assign parameter values appropriately
            */
            if @publisher IS NULL
                set @publisher = @@SERVERNAME
            if (@publisher_db IS NULL)
                set @publisher_db = DB_NAME()

            /*
            ** Parameter Check: @subscriber
            ** Check to make sure that the subscriber is defined
            */
            IF @subscriber IS NULL
            BEGIN
                RAISERROR (14043, 16, -1, '@subscriber')
                RETURN (1)
            END

            /*
            ** Parameter Check: @subscriber_db
            */
            IF @subscriber_db IS NULL
            BEGIN
                select @subscriber_db = 'all'
            END
                
        end
    else
        begin
            /*
            ** Assign parameter values appropriately
            */
            if @subscriber IS NULL
                set @subscriber = @@SERVERNAME
            if @subscriber_db IS NULL
                set @subscriber_db = DB_NAME()

            /*
            ** Parameter Check: @publisher
            ** Check to make sure that the publisher is defined
            */
            IF @publisher IS NULL
            BEGIN
                RAISERROR (14043, 16, -1, '@publisher')
                RETURN (1)
            END

            EXECUTE @retcode = dbo.sp_validname @publisher
            IF @@ERROR <> 0 OR @retcode <> 0
               RETURN (1)

            /*
            ** Parameter Check: @publisher_db
            */
            IF @publisher_db IS NULL
            BEGIN
                RAISERROR (14043, 16, -1, '@publisher_db')
                RETURN (1)
            END

        end     

    /*
    ** Parameter Check:  @publication.
    ** If the publication name is specified, check to make sure that it
    ** conforms to the rules for identifiers and that the publication
    ** actually exists.  Disallow NULL.
    */
    if @publication IS NULL
        BEGIN
            RAISERROR (14043, 16, -1, '@publication')
            RETURN (1)
        END

    IF LOWER(@publication) = 'all'
        BEGIN
            declare hC1 CURSOR LOCAL FAST_FORWARD FOR select DISTINCT name FROM sysmergepublications 
                where UPPER(publisher)=UPPER(@@SERVERNAME) and publisher_db=db_name() 
                FOR READ ONLY
            
            OPEN hC1
            FETCH hC1 INTO @publication
            WHILE (@@fetch_status <> -1)
                BEGIN
                    EXECUTE dbo.sp_dropmergesubscription @publication = @publication,
                                                @subscriber = @subscriber,
                                                @subscriber_db = @subscriber_db,
                                                @subscription_type = @subscription_type,
                                                @ignore_distributor = @ignore_distributor,
												@reserved = 1
                    FETCH hC1 INTO @publication
                END
            CLOSE hC1
            DEALLOCATE hC1
            RETURN (0)
        END
        
    if NOT EXISTS (select * FROM sysmergepublications 
        WHERE name = @publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name())
        BEGIN
            RAISERROR (20026, 16, -1, @publication)
            RETURN (1)
        END
    select @pubid = pubid from sysmergepublications 
        where name = @publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()
    set @pubidstr = '''' + convert(nchar(36), @pubid) + ''''
    if @pubid is null
        BEGIN
            RAISERROR (20026, 16, -1, @publication)
            RETURN (1)
        END

       
    IF LOWER(@subscriber) = 'all'
        BEGIN
            declare hC2 CURSOR LOCAL FAST_FORWARD FOR select DISTINCT srvname 
            FROM master..sysservers 
            WHERE (srvstatus & 4 <> 0) FOR READ ONLY
    
            OPEN hC2
            FETCH hC2 INTO @subscriber
            WHILE (@@fetch_status <> -1)
                BEGIN
                    EXECUTE dbo.sp_dropmergesubscription @publication = @publication,
                                                @subscriber = @subscriber,
                                                @subscriber_db = @subscriber_db,
                                                @subscription_type = @subscription_type,
                                                @ignore_distributor = @ignore_distributor,
												@reserved = 1
                    FETCH hC2 INTO @subscriber
                END
            CLOSE hC2
            DEALLOCATE hC2
            RETURN (0)
        END

    /*
    ** Validate that the subscriber is a valid server
    */
    select @subscriber_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@subscriber)
    IF @subscriber_srvid IS NULL
        BEGIN
            --RAISERROR (14010, 16, -1)
            RETURN (1)
        END

    /*
    ** NOTE: remove this batch
    */
    IF LOWER(@subscriber_db) = 'all'
        BEGIN
                declare hC3 CURSOR LOCAL FAST_FORWARD FOR select DISTINCT db_name FROM sysmergesubscriptions
                WHERE srvid =  @subscriber_srvid 
                    AND subid <> pubid 
                    AND sysmergesubscriptions.pubid = @pubid
                    AND sysmergesubscriptions.subscription_type = @subscription_type_id
                FOR READ ONLY       

            OPEN hC3
            FETCH hC3 INTO @subscriber_db
            WHILE (@@fetch_status <> -1)
                BEGIN
                    EXECUTE dbo.sp_dropmergesubscription @publication = @publication,
                                                @subscriber = @subscriber,
                                                @subscriber_db = @subscriber_db,
                                                @subscription_type = @subscription_type,
                                                @ignore_distributor = @ignore_distributor,
												@reserved = 1

                    FETCH hC3 INTO @subscriber_db
                END
            CLOSE hC3
            DEALLOCATE hC3
            RETURN (0)
        END

    /*
    ** Validate that the publisher is a valid server
    */
    select @publisher_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@publisher)
    IF @publisher_srvid IS NULL
        BEGIN
            --RAISERROR (14010, 16, -1)
            RETURN (1)
        END

    select @pubid=pubid from sysmergepublications where name=@publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()
    if @pubid is NULL return (0)
    
    if exists (select * from sysmergesubscriptions where subid=@pubid 
        and pubid=@pubid and db_name<>db_name())
    RETURN (0)
    
    /*
    ** Get subscriptions from either local replicas or global replicas
    */
    select @subid = subs1.subid, @partnerid = subs2.subid, @subscriber_type = subs1.subscriber_type from
        sysmergesubscriptions   subs1,
        sysmergesubscriptions   subs2,
        sysmergepublications        pubs
        where subs1.srvid = @subscriber_srvid
            and subs1.db_name = @subscriber_db
            and subs2.srvid = @publisher_srvid
            and subs2.db_name = @publisher_db
            and subs1.pubid = subs2.subid
            and subs2.pubid = pubs.pubid
            and pubs.name = @publication
            and UPPER(pubs.publisher)=UPPER(@@servername)
            and pubs.publisher_db=db_name()
            and subs1.subscription_type = @subscription_type_id
            and (suser_sname(suser_sid()) = subs1.login_name OR is_member('db_owner')=1 OR is_srvrolemember('sysadmin') = 1)

    if @subid IS NULL
        begin
            -- raiserror (14050, 16, -1) 
            RETURN (0)
        end                 

    begin tran
    save TRAN dropmergesubscription

        /*
        ** Do not drop the subscription corresponding to the loopback subscription 
        */
        if (@subid <> @partnerid) 
            begin
                /*
                ** global/republisher subscriptions have to stay for a while even after being
                ** dropped so that they won't regain lives for themselves. They would be cleanup eventually.
                */
                
                if (@subscriber_type<>1) 
                    begin
                        delete from sysmergesubscriptions where subid = @subid
                        IF @@ERROR <> 0
                            GOTO FAILURE        
                        delete MSmerge_replinfo WHERE repid = @subid 
                        IF @@ERROR <> 0
                            GOTO FAILURE
                    end
                else
                    begin
                        update sysmergesubscriptions set status=2 where subid=@subid
                        IF @@ERROR<>0
                            GOTO FAILURE
                    end 

                /* 
                ** The MobileSync registry entry needs to be dropped only for push subscriptions -  
                ** i.e - need not be called when a pull subscription is created at the 
                ** subscriber and sp_addmergesubscription is being called then.
                */
                IF LOWER(@subscription_type) = 'push'
                begin
                    /* Call sp_MSunregistersubscription so that the reg entries get deleted */
                    exec @retcode = dbo.sp_MSunregistersubscription @publisher = @@SERVERNAME,
                                    @publisher_db = @publisher_db,
                                    @publication = @publication,
                                    @subscriber = @subscriber,
                                    @subscriber_db = @subscriber_db
                    IF @retcode<>0 or @@ERROR<>0
                        GOTO FAILURE

                END             
            end     

        /*
        ** if @ignore_distributor = 1, we are in bruteforce cleanup mode, don't do RPC.
        */
        if @ignore_distributor = 0
        begin
            /*
            ** Get distribution server information for remote RPC call.
            */
            EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
               @distribdb   = @distribdb OUTPUT
            IF @@ERROR <> 0 or @retcode <> 0
                BEGIN
                    GOTO FAILURE
                END

            SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + 
                '.dbo.sp_MSdrop_merge_subscription'

            EXEC @retcode = @distproc 
                @@SERVERNAME, 
                @publisher_db, 
                @publication,
                @subscriber, 
                @subscriber_db,
                @subscription_type
            IF @@ERROR <> 0 OR @retcode <> 0
                begin   
                    goto FAILURE
                end 
        end 

        /* 
        ** If last subscription is dropped and the DB is not enabled for publishing,
        ** then remove the merge system tables
        */

        IF (not exists (select * from sysmergesubscriptions )) 
            AND (select category & 4 FROM master..sysdatabases WHERE name = DB_NAME())=0
            BEGIN
                execute @retcode = dbo.sp_MSdrop_mergesystables
                if @@ERROR <> 0 or @retcode <> 0
                    begin
                        return (1)
                    end
            END         

    COMMIT TRAN
    /*
	** Set back original settings
	*/	
	IF @reserved = 0
	BEGIN
		IF @implicit_transaction <>0 
			SET IMPLICIT_TRANSACTIONS ON
		IF @close_cursor_at_commit <>0 
			SET CURSOR_CLOSE_ON_COMMIT ON
	END
    RETURN(0)       

FAILURE:
    /* UNDONE : This code is specific to 6.X nested transaction semantics */
    RAISERROR (14056, 16, -1)
    if @@TRANCOUNT > 0
    begin
        ROLLBACK TRANSACTION dropmergesubscription
        COMMIT TRANSACTION
    end
    /*
	** Set back original settings
	*/	
	IF @reserved = 0
	BEGIN
		IF @implicit_transaction <>0 
			SET IMPLICIT_TRANSACTIONS ON
		IF @close_cursor_at_commit <>0 
			SET CURSOR_CLOSE_ON_COMMIT ON
	END
    return (1)
go
exec dbo.sp_MS_marksystemobject sp_dropmergesubscription
go

grant execute on dbo.sp_dropmergesubscription to public
go

raiserror('Creating procedure sp_MSmergepublishdb', 0,1)
GO

CREATE PROCEDURE sp_MSmergepublishdb(
      @value     sysname,
      @ignore_distributor bit = 0
    ) AS

    SET NOCOUNT ON

    /*
    ** Declarations.
    */
    declare @command        nvarchar(255)
    declare @description    nvarchar(500)
    declare @cmptlevel      tinyint
    declare @db_name        sysname 
    declare @retcode        int
    declare @distributor    sysname
    declare @distribdb      sysname
    declare @distproc       nvarchar (255)
    declare @category_name  sysname
    declare @agentname      sysname

    /*
    ** Initialization
    */

    select @db_name = DB_NAME()


    /*
    ** Parameter check
    ** @value
    */
    IF LOWER(@value) NOT IN ('true','false')
    BEGIN
      RAISERROR(14137,16,-1)
      RETURN(1)
    END

    /*
    ** if @ignore_distributor = 1, we are in bruteforce cleanup mode, don't do RPC.
    */
    if @ignore_distributor = 0
    begin
        /*
        ** Test to see if the distributor is installed and online.
        */
        EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
           @distribdb   = @distribdb OUTPUT

        IF @@ERROR <> 0 or @retcode <> 0 or @distributor IS NULL or @distribdb IS NULL
        BEGIN
            IF LOWER(@value) = 'true'
                RAISERROR (20028, 16, -1)
            ELSE
                RAISERROR (20029, 16, -1)
            RETURN (1)
        END
    end

    /*
    ** Enable the database for publishing.
    */
    IF LOWER(@value) = 'true'
        BEGIN
                
            select @cmptlevel = cmptlevel from master..sysdatabases where name=db_name()
            if @cmptlevel<70 OR @cmptlevel is NULL 
                begin
                    RAISERROR(20061, 16, -1)
                    goto FAILURE
                end
            execute @retcode = dbo.sp_MScreate_mergesystables
            if @@ERROR <> 0 or @retcode <> 0
                begin
                    goto FAILURE
                end

		    END

    ELSE    /* Disable the database for publishing. */
        BEGIN 
           
          /*
          ** Remove all the registration entries for subscriptions
          */
            if not exists(select * from sysobjects where name = 'sysmergesubscriptions')
                goto FAILURE
            exec @retcode = dbo.sp_dropmergesubscription @publication = 'all', 
                                            @subscriber = 'all', 
                                            @subscriber_db = 'all', 
                                            @subscription_type = 'both',
                                            @ignore_distributor = @ignore_distributor
            IF @@ERROR <> 0 or @retcode <> 0 
                begin
                    goto FAILURE
                end
            /*
            ** Remove all publications and articles in the database.
            */
            EXEC @retcode = dbo.sp_dropmergepublication @publication = 'all',
                @ignore_distributor = @ignore_distributor
            IF @@ERROR <> 0 or @retcode <> 0 
                begin
                    -- sp_dropmergepublication will raiserror 
                    goto FAILURE
                end
                
            If NOT EXISTS (select * from sysmergepublications)
                BEGIN
                    execute @retcode = dbo.sp_MSdrop_mergesystables
                    if @@ERROR <> 0 or @retcode <> 0
                        begin
                            goto FAILURE
                        end
                END
    
    END
        
        
        return 0
FAILURE:
    
    return (1)  

GO
exec dbo.sp_MS_marksystemobject sp_MSmergepublishdb
go

raiserror('Creating procedure sp_enumcustomresolvers', 0,1)
GO

CREATE PROCEDURE sp_enumcustomresolvers
--	@distributor parameter will be removed in the next version.   
    @distributor     sysname = NULL
    AS
    SET NOCOUNT ON

    declare @distributor_rpc sysname
    declare @return_status int
    declare @distproc nvarchar(100)
    declare @retcode int

    select @return_status = 0
 
   
    /*
    ** Get the distributor 
    ** Use local RPC if @distributor == @servername. This is used by UI
    ** before installing a distributor.
    */
    if @distributor = @@servername
        select @distributor_rpc = @@servername
    else
    begin
        EXEC @return_status = dbo.sp_helpdistributor @rpcsrvname = @distributor_rpc OUTPUT
        IF @@error <> 0 OR @return_status <> 0 OR @distributor_rpc IS NULL
        BEGIN
            RAISERROR (20036, 16, -1)
            RETURN (1)
        END
    end

    declare @key_exists int
    select @key_exists = 0
    create table #keyexists (keyexists int) 
    select @distproc = RTRIM(@distributor_rpc) + '.master..xp_regread'
    insert into #keyexists exec @distproc 'HKEY_LOCAL_MACHINE', 'SOFTWARE\Microsoft\MSSQLServer\Replication\ArticleResolver'
    select @key_exists = keyexists from #keyexists
    if (@key_exists = 1)
        begin
            select @distproc = RTRIM(@distributor_rpc) + '.master..xp_regenumvalues'
            exec @distproc 'HKEY_LOCAL_MACHINE', 'SOFTWARE\Microsoft\MSSQLServer\Replication\ArticleResolver'    
            if @@ERROR<>0 return (1)
        end
    drop table #keyexists
    RETURN (0)
GO
exec dbo.sp_MS_marksystemobject sp_enumcustomresolvers
go

grant execute on dbo.sp_enumcustomresolvers to public
go

raiserror('Creating procedure sp_changemergefilter', 0,1)
GO

create procedure sp_changemergefilter(
    @publication            sysname,
    @article                sysname,
    @filtername             sysname,
    @property               sysname,
    @value                  nvarchar(2000)
    )AS

    set nocount on

    declare @db_name        sysname
    declare @pubid          uniqueidentifier
    declare @artid          uniqueidentifier
    declare @retcode        int
    declare @join_filterid  int
    declare @join_objid     int
    declare @join_nickname  int

    /*
    ** Security Check.
    ** Only the System Administrator (SA) or the Database Owner (dbo) can
    ** call this procedure
    */
    exec @retcode = dbo.sp_MSreplcheck_publish
    if @@ERROR <> 0 or @retcode <> 0
        return(1)

    /*
    ** Parameter Check: @join_articlename.
    ** The join_articlename cannot be NULL 
    */
    if @filtername is NULL
        begin
            raiserror (14043, 11, -1, '@filtername')
            return (1)
        end

    if @value is NULL or @value = ''
        begin
            raiserror (14043, 11, -1, '@value')
            return (1)
        end

    /*
    ** Parameter Check: @publication.
    ** The @publication id cannot be NULL and must conform to the rules
    ** for identifiers.
    */
    if @publication is NULL
        begin
            raiserror (14043, 11, -1, '@publication')
            return (1)
        end
    /*
    ** Get the pubid and make sure the publication exists
    */
    select @pubid = pubid from sysmergepublications where 
        name = @publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()
    if @pubid is NULL
        begin
            raiserror (20026, 16, -1, @publication)
            return (1)
        end
    /* This can only be done at the publisher */
    exec @retcode = dbo.sp_MScheckatpublisher  @pubid
    if @retcode <> 0 or @@ERROR <> 0
        return (1)

    /*
    ** This can be done for articles that are not active.
    */
    if EXISTS (select status FROM sysmergearticles WHERE pubid = @pubid AND status = 2)
        BEGIN
           RAISERROR (20043, 16, -1, @article)
           RETURN (1)
        END

    select @db_name = db_name from sysmergesubscriptions
        where (pubid=@pubid) and (subid=@pubid)
        IF @db_name <> db_name()
        BEGIN
            RAISERROR (20047, 16, -1)
            RETURN (1)
        END

    /*
    ** Parameter Check: @article.
    ** Check to see that the @article is valid and does exist 
    */
    if @article is NULL
        begin
            raiserror (20045, 16, -1)
            return (1)
        end
        
    select @artid = artid from sysmergearticles where name = @article and pubid = @pubid  
    if @artid is NULL
        begin
            raiserror (20046, 16, -1)
            return (1)
        end

    
    select @join_filterid=join_filterid from sysmergesubsetfilters
        where pubid=@pubid and artid=@artid and filtername=@filtername

    if @join_filterid is null
        begin
            raiserror (14028, 16, -1) 
            return (1)
        end

     IF @property IS NULL
        BEGIN
            CREATE TABLE #temp (properties sysname)
            INSERT INTO #temp VALUES ('filtername')
            INSERT INTO #temp VALUES ('join_filterclause')
            INSERT INTO #temp VALUES ('join_articlename')
            select * FROM #tab1
            RETURN (0)
        END 


    if @value is null
        begin
            raiserror (14028, 16, -1) 
            return (1)
        end


    IF LOWER(@property)='join_filterclause'
        BEGIN
            update sysmergesubsetfilters set join_filterclause=@value
                where join_filterid=@join_filterid
            execute @retcode = dbo.sp_MSsubsetpublication @publication
            if @@ERROR <> 0 or @retcode<>0
                goto FAILURE
        END

    IF LOWER(@property)='filtername'
        BEGIN
            update sysmergesubsetfilters set filtername=@value
                where join_filterid=@join_filterid
        END

    IF LOWER(@property)='join_articlename'
        BEGIN
            select @join_objid = objid from sysmergearticles where name = @value and pubid = @pubid
            
            IF @join_objid is NULL
            BEGIN
                raiserror (14027, 11, -1, @value)
                return (1)
            END

            select @join_nickname = nickname from sysmergearticles where pubid = @pubid AND objid = @join_objid 
            if @join_nickname is NULL
            begin
                raiserror (20001, 11, -1, @article, @publication)
                return (1)
            end
            
            update sysmergesubsetfilters set join_articlename=@value, join_nickname=@join_nickname
                where join_filterid=@join_filterid
        END

    return(0)

FAILURE:
    RAISERROR (20038, 16, -1, @article, @publication)
    return(1)
 
go
exec dbo.sp_MS_marksystemobject sp_changemergefilter
go

grant execute on dbo.sp_changemergefilter to public
go

raiserror('Creating procedure sp_addmergefilter', 0,1)
GO

create procedure sp_addmergefilter(
    @publication            sysname,            /* publication name */
    @article                sysname,            /* article name */
    @filtername             sysname,            /* join filter name */
    @join_articlename       sysname,            /* Name of the table being joined to the base table */
    @join_filterclause      nvarchar(2000),        /* filter clause qualifying the join */             
    @join_unique_key        int = 0
    )AS

    set nocount on

    /*
    ** Declarations.
    */
    declare @db_name            sysname
    declare @pubid              uniqueidentifier                
    declare @artid              uniqueidentifier
    declare @art_nickname       int
    declare @join_nickname      int
    declare @db                 sysname
    declare @object             sysname
    declare @owner              sysname
    declare @retcode            int
    declare @join_objid         int
    declare @status             int
    
    /*
    ** Only publisher can run this stored procedure 
    */
    if not exists (select * from sysobjects where name = 'sysmergepublications')
        BEGIN
            RAISERROR (20054, 16, -1)
            RETURN (1)
        END

    /*
    ** Security Check.
    ** Only the System Administrator (SA) or the Database Owner (dbo) can
    ** add an article to a publication.
    */
    exec @retcode = dbo.sp_MSreplcheck_publish
    if @@ERROR <> 0 or @retcode <> 0
        return(1)

    /*
    ** Parameter Check: @filtername.
    ** The join_filter_name cannot be NULL 
    */
    if @filtername is NULL
        begin
            raiserror (14043, 11, -1, @filtername)
            return (1)
        end

    if @join_filterclause is NULL or @join_filterclause = ''
        begin
            raiserror (14043, 11, -1, '@join_filterclause')
            return (1)
        end

    /*
    ** Parameter Check: @publication.
    ** The @publication id cannot be NULL and must conform to the rules
    ** for identifiers.
    */
    if @publication is NULL
        begin
            raiserror (14003, 16, -1)
            return (1)
        end

    
    /*
    ** Get the pubid and make sure the publication exists
    */
    select @pubid = pubid from sysmergepublications 
        where name = @publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()
    if @pubid is NULL
        begin
            raiserror (14027, 16, -1, @publication)
            return (1)
        end

    /* This can only be done at the publisher */
    exec @retcode = dbo.sp_MScheckatpublisher  @pubid
    if @retcode <> 0 or @@ERROR <> 0
        return (1)


    select @db_name = db_name from sysmergesubscriptions
        where (pubid=@pubid) and (subid=@pubid) 
        IF @db_name <> db_name()
        BEGIN
            RAISERROR (20047, 16, -1)
            RETURN (1)
        END

    /*
    ** This can be done for articles belonging to publications that are not active.
    */
    if EXISTS (select status FROM sysmergepublications WHERE pubid = @pubid AND status = 2)
        BEGIN
            RAISERROR (20043, 16, -1, @article)
            RETURN (1)
        END
        
    /*
    ** Parameter Check: @article.
    ** Check to see that the @article is valid and does exist 
    */
    if @article is NULL
        begin
            raiserror (20045, 16, -1)
            return (1)
        end
        
    select @artid = artid, @art_nickname = nickname from sysmergearticles where name = @article and pubid = @pubid  
    if @artid is NULL
        begin
            raiserror (20046, 16, -1)
            return (1)
        end
        
    /*
    **  Get the id of the @join_articlename
    */
    select @join_objid = objid from sysmergearticles where name=@join_articlename and pubid = @pubid
    
    IF @join_objid is NULL
        BEGIN
            raiserror (14027, 11, -1, @join_articlename)
            return (1)
        END

    select @join_nickname = nickname from sysmergearticles where pubid = @pubid AND objid = @join_objid 
    if @join_nickname is NULL
        begin
            raiserror (20001, 11, -1, @article, @publication)
            return (1)
        end

    IF NOT EXISTS (select * from sysmergearticles where pubid=@pubid AND nickname = @join_nickname)
        BEGIN
            RAISERROR (20046, 16, -1) /* Only the original publisher can do so */
            RETURN (1)
        END
    
    /*
    ** Make sure that the table name specified is a table and not a view.
    */
    
    if NOT exists (select * from sysobjects
        where id = @join_objid AND type = 'U')
        begin
            raiserror (14028, 16, -1)
            return (1)
        end

    /*
    **  Add the join filter to sysmergesubsetfilters if it is not already there
    */

    IF exists (select * from sysmergesubsetfilters 
    where filtername=@filtername and  pubid=@pubid and artid=@artid) 
        begin
            raiserror (20002, 16, -1, @filtername, @article, @publication)
            return (1)
        end
    
    insert INTO sysmergesubsetfilters(filtername, pubid, artid, art_nickname, join_articlename, join_nickname, join_unique_key, join_filterclause)
        values(@filtername, @pubid, @artid, @art_nickname, @join_articlename, @join_nickname, @join_unique_key, @join_filterclause)                 
    if @@error <> 0
        begin
            goto FAILURE
        end
    execute @retcode = dbo.sp_MSsubsetpublication @publication
    if @@ERROR <> 0 or @retcode <>0
        goto FAILURE
    
    return (0)
    
FAILURE:
    RAISERROR (20038, 16, -1, @article, @publication)
    return (1)

go
exec dbo.sp_MS_marksystemobject sp_addmergefilter
go

grant execute on dbo.sp_addmergefilter to public
go

raiserror('Creating procedure sp_dropmergefilter', 0,1)
GO

create procedure sp_dropmergefilter
    @publication            sysname,            /* publication name */
    @article                sysname,            /* article name */
    @filtername             sysname             /* Name of the table being joined to the base table */
    AS

    set nocount on

    /*
    ** Declarations.
    */
    declare @pubid                  uniqueidentifier                
    declare @artid                  uniqueidentifier
    declare @join_objid             int
    declare @retcode                int
    declare @join_filterid          int
    declare @db_name                sysname

    /*
    ** Only publisher can run this stored procedure 
    */
    if not exists (select * from sysobjects where name = 'sysmergepublications')
        BEGIN
            RAISERROR (20054, 16, -1)
            RETURN (1)
        END

    /* 
    ** Security Check.
    */
    exec @retcode=sp_MSreplcheck_publish
    if @@ERROR <> 0 or @retcode <> 0
        return (1)

    /*
    ** Parameter Check: @publication.
    ** The @publication id cannot be NULL and must conform to the rules
    ** for identifiers.
    */
    
    if @publication is NULL
        begin
            raiserror (14003, 16, -1)
            return (1)
        end

    /*
    ** Get the pubid, and check if this publication exists.
    */
    select @pubid = pubid from sysmergepublications 
        where name = @publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()
    if @pubid is NULL
        begin
            raiserror (20026, 16, -1, @publication )
            return (1)
        end

    select @db_name = db_name from sysmergesubscriptions
        where (pubid=@pubid) and (subid=@pubid) 
        IF @db_name <> db_name()
        BEGIN
            RAISERROR (20047, 16, -1)
            RETURN (1)
        END
    
    /*
    ** Parameter Check: @article.
    ** Check to see that the @article is valid, and if it exists
    */
    if @article is NULL
        begin
            raiserror (20045, 16, -1)
            return (1)
        end

    /*
    ** This can be done for articles belonging to publications that are not active.
    */
    if EXISTS (select status FROM sysmergepublications WHERE pubid = @pubid AND status = 2)
        BEGIN
            RAISERROR (20043, 16, -1, @article)
            RETURN (1)
        END
        
       
    select @artid = artid from sysmergearticles where name = @article and pubid = @pubid  
    if @artid is NULL
        begin
            raiserror (20046, 16, -1)
            return (1)
        end
    

    select @join_filterid = join_filterid from sysmergesubsetfilters
        where pubid = @pubid AND artid= @artid AND filtername=@filtername  
    
    /*
    **  Remove the join filter from sysmergesubsetfilters
    */
    delete from sysmergesubsetfilters
        where join_filterid = @join_filterid
    if @@error <> 0
        begin
            goto FAILURE
        end

    /*
    ** set the pub type to subset or full as appropriate
    */
    exec @retcode=sp_MSsubsetpublication @publication
    if @@ERROR <> 0 or @retcode<>0
        begin
            goto FAILURE
        end

    return(0)
FAILURE:
    RAISERROR (20039, 16, -1, @article, @publication)
    return (1)
go

exec dbo.sp_MS_marksystemobject sp_dropmergefilter
go

raiserror('Creating procedure sp_helpmergefilter', 0,1)
GO

create procedure sp_helpmergefilter
    @publication            sysname,        /* publication name */
    @article                sysname = '%',          /* article name */ 
    @filtername             sysname = '%'
    AS

    set nocount on

    /*
    ** Declarations.
    */
    declare @pubid                  uniqueidentifier                
    declare @artid                  uniqueidentifier
    declare @retcode                int

    /* 
    ** Security Check.
    */
    exec @retcode = dbo.sp_MSreplcheck_publish
    if @@ERROR <> 0 or @retcode <> 0
        return(1)


    /*
    **  Calling sp_help* is all right whether current database is enabled for pub/sub or not
    */
    IF not exists (select * from sysobjects where name='sysmergesubscriptions')
        RETURN (0)
        
    /*
    ** Parameter Check: @publication.
    ** The @publication id cannot be NULL and must conform to the rules
    ** for identifiers.
    */
    if @publication is NULL
        begin
            raiserror (14003, 16, -1)
            return (1)
        end
    /*
    ** Get the pubid and check if the publication does exist
    */
    select @pubid = pubid from sysmergepublications 
        where name = @publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()
    if @pubid is NULL
        begin
            raiserror (20026, 16, -1, @publication)
            return (1)
        end

    /*
    ** Parameter Check: @article.
    ** If an @article is specified, make sure it exists
    */
    select @artid = artid from sysmergearticles where name = @article and pubid = @pubid  
    if @artid is NULL and (@article <> '%' or @filtername <> '%')
        begin
            raiserror (20046, 16, -1)
            return (1)
        end

    /*
    **  Return the join filters from sysmergesubsetfilters
    */

IF @filtername <> '%'
    select distinct join_filterid, filtername, 'join article name' = j_a.name, join_filterclause, f.join_unique_key,
            'base table owner' = b_u.name, 'base table name' = b_o.name, 'join table owner' = j_u.name, 'join table name' = j_o.name,
            'article name' = b_a.name
        from sysmergesubsetfilters f, sysobjects j_o, sysobjects b_o, sysusers j_u,
            sysusers b_u, sysmergearticles j_a, sysmergearticles b_a
        where   f.pubid = @pubid AND b_a.pubid = @pubid
            AND f.filtername = @filtername
            AND f.artid = @artid 
            AND f.artid = b_a.artid AND b_o.id = b_a.objid
            AND b_u.uid = b_o.uid
            AND f.join_nickname = j_a.nickname AND j_o.id = j_a.objid and j_a.pubid = @pubid
            AND j_u.uid = j_o.uid
           ORDER BY j_o.name, b_o.name
 ELSE
    begin
    if @artid is not null
    select distinct join_filterid, filtername, 'join article name' = j_a.name, join_filterclause, f.join_unique_key,
            'base table owner' = b_u.name, 'base table name' = b_o.name, 'join table owner' = j_u.name, 'join table name' = j_o.name,
            'article name' = b_a.name
        from sysmergesubsetfilters f, sysobjects j_o, sysobjects b_o, sysusers j_u,
            sysusers b_u, sysmergearticles j_a, sysmergearticles b_a
        where   f.pubid = @pubid AND b_a.pubid = @pubid
            AND f.artid = @artid 
            AND f.artid = b_a.artid AND b_o.id = b_a.objid
            AND b_u.uid = b_o.uid
            AND f.join_nickname = j_a.nickname AND j_o.id = j_a.objid and j_a.pubid = @pubid
            AND j_u.uid = j_o.uid
           ORDER BY j_o.name, b_o.name
    else
    select distinct join_filterid, filtername, 'join article name' = j_a.name, join_filterclause, f.join_unique_key,
            'base table owner' = b_u.name, 'base table name' = b_o.name, 'join table owner' = j_u.name, 'join table name' = j_o.name,
            'article name' = b_a.name
        from sysmergesubsetfilters f, sysobjects j_o, sysobjects b_o, sysusers j_u,
            sysusers b_u, sysmergearticles j_a, sysmergearticles b_a
        where   f.pubid = @pubid AND b_a.pubid = @pubid
            AND f.artid = b_a.artid AND b_o.id = b_a.objid
            AND b_u.uid = b_o.uid
            AND f.join_nickname = j_a.nickname AND j_o.id = j_a.objid and j_a.pubid = @pubid
            AND j_u.uid = j_o.uid
           ORDER BY j_o.name, b_o.name
    end
    return(0)
go
exec dbo.sp_MS_marksystemobject sp_helpmergefilter
go

grant execute on dbo.sp_helpmergefilter to public
go

raiserror('Creating procedure sp_MSscript_dri', 0,1)
go
create procedure sp_MSscript_dri
    (@publication   sysname, 
    @article        sysname)
AS

declare @pubid  uniqueidentifier
    
select @pubid = pubid from sysmergepublications where name = @publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()
        
select rkeyid, fkeyid from sysreferences 
        where fkeyid in (select objid from sysmergearticles where pubid = @pubid and name = @article) 
            and rkeyid not in (select objid from sysmergearticles   where pubid = @pubid)
go
exec dbo.sp_MS_marksystemobject sp_MSscript_dri
go
grant execute on dbo.sp_MSscript_dri to public
go


raiserror('Creating procedure sp_MSenumpubreferences', 0,1)
GO
create procedure sp_MSenumpubreferences (@publication sysname)
as
    declare @pubid uniqueidentifier
    declare @retcode int
    
    /* 
    ** Security Check.
    */
    exec @retcode = dbo.sp_MSreplcheck_publish
    if @@ERROR <> 0 or @retcode <> 0
        return(1)

    if not exists (select * from sysobjects where name = 'sysmergepublications')
        BEGIN
            RAISERROR (20054, 16, -1)
            RETURN (1)
        END

    select @pubid = pubid from sysmergepublications where
        name = @publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()
    if @pubid is null
        BEGIN
            RAISERROR (20026, 16, -1, @publication)
            RETURN (1)
        END
    select distinct ReferencingObject = object_name(rkeyid), ArticleObject  = object_name(fkeyid) 
        from sysreferences r, sysmergearticles
        where r.fkeyid in (select objid from sysmergearticles where pubid = @pubid) 
            and r.rkeyid not in (select objid from sysmergearticles where pubid = @pubid)

    select distinct ReferencedObject = object_name(fkeyid), ArticleObject = object_name(rkeyid) from sysreferences r
        where r.rkeyid in (select objid from sysmergearticles
            where pubid = @pubid) and
        r.fkeyid not in (select objid from sysmergearticles
            where pubid = @pubid)           
    return (0)
go

exec dbo.sp_MS_marksystemobject sp_MSenumpubreferences
go

grant execute on dbo.sp_MSenumpubreferences to public
go
 
raiserror('Creating procedure sp_MSsubsetpublication', 0,1)
GO

create procedure sp_MSsubsetpublication (@publication sysname)
as
    declare @pubid          uniqueidentifier
    declare @false          bit
    declare @true           bit
    declare @boolean_filter bit
    declare @join_filter    bit
    declare @full           int
    declare @subset         int
    declare @unsynced       int

    /*
    ** Initializations
    */
    select @true        = 1
    select @false       = 0
    select @full        = 0     /* Const: publication type 'full' */
    select @subset      = 1     /* Const: publication type 'subset' */
    select @unsynced    = 1
    
    if not exists (select * from sysobjects where name = 'sysmergepublications')
        BEGIN
            RAISERROR (20054, 16, -1)
            RETURN (1)
        END 

    select @pubid = pubid from sysmergepublications where
        name = @publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()
    if @pubid is null
        BEGIN
            RAISERROR (20026, 16, -1, @publication)
            RETURN (1)
        END

    /* 
    ** Set the publication_type to subset if the publication has either a boolean or a join filter
    */
    if exists (select * from sysmergearticles where pubid = @pubid and len(subset_filterclause) > 0)
        set @boolean_filter = @true
    if exists (select * from sysmergesubsetfilters where pubid = @pubid)
        set @join_filter = @true

    /*
    ** For subset publications set the article status to be unsynced so that the triggers can be regenerated.
    */
    if (@boolean_filter = 1 OR @join_filter = 1)        
        begin
            update sysmergepublications set publication_type = @subset where pubid = @pubid
            if @@ERROR <> 0 return (1)
            update sysmergearticles set status = @unsynced where pubid = @pubid
            if @@ERROR <> 0 return (1)
        end         
    else
        update sysmergepublications set publication_type = @full where pubid = @pubid               
    if @@ERROR <> 0 return (1)
        
    return(0)           
go

exec dbo.sp_MS_marksystemobject sp_MSsubsetpublication
go
raiserror('Creating procedure sp_MSindexcolfrombin', 0,1)
GO

create procedure sp_MSindexcolfrombin
    @object_id      int,
    @col_index      int,
    @colids_bin     varbinary(256),
    @colname        sysname output
    AS
    /* Declare variables */
    declare @start_byte int
    declare @colid int

    set @colid = unicode( substring( convert( nvarchar(128),@colids_bin ), @col_index, 1 ) )

    /* Use object id and colid to look up the column name in syscolumns */
    select @colname = name from syscolumns where id = @object_id and colid = @colid
    return (0)
GO
exec dbo.sp_MS_marksystemobject sp_MSindexcolfrombin
go

raiserror('Creating procedure sp_MSmakejoinfilter', 0,1)
GO

create procedure sp_MSmakejoinfilter
    @publication    sysname,
    @article        sysname,
    @base_objid     int,
    @join_objid     int,
    @join_unique    int
    AS

    /* Declare additional variables */
    declare     @table_name sysname
    declare     @join_table sysname
    declare     @join_article sysname
    declare     @filt_name  sysname
    declare     @basecol    sysname
    declare     @joincol    sysname
    declare     @keycnt     int
    declare     @basekeys       varbinary(32)
    declare     @joinkeys       varbinary(32)
    declare     @keyindex   int
    declare     @filtclause nvarchar(3000)
    declare     @filtpiece  nvarchar(500)
    declare     @qual_jointable nvarchar(258)
    declare     @retcode    smallint
    declare     @pubid      uniqueidentifier
    
    select @pubid = pubid from sysmergepublications where name = @publication and UPPER(publisher)=UPPER(@@SERVERNAME) and publisher_db=db_name()
    /* Are we adding join filter on referencing table (@join_unique = 1) or on unique key table ? */
    if @join_unique = 1
    /* Select the keycnt, fkeys, rkeys, and filter name from sysreferences */
        select @keycnt = keycnt, @basekeys = forkeys, @joinkeys = refkeys, @filt_name = object_name(constid)
            from sysreferences where fkeyid = @base_objid and rkeyid = @join_objid
    else
        select @keycnt = keycnt, @basekeys = refkeys, @joinkeys = forkeys, @filt_name = object_name(constid)
            from sysreferences where rkeyid = @base_objid and fkeyid = @join_objid
    
    /* Set up object names - we use them as correlation values */
    set @table_name = QUOTENAME(object_name(@base_objid))
    set @join_table = QUOTENAME(object_name(@join_objid))
    select @join_article = name from sysmergearticles where objid = @join_objid and pubid=@pubid

    -- set @qual_jointable = @join_owner + '.' + @join_table

    /* Loop over keys, building up our join filter clause */
    set @keyindex = 1
    while @keyindex <= @keycnt
        begin
        /* Get the column names */
        exec dbo.sp_MSindexcolfrombin @base_objid, @keyindex, @basekeys, @basecol output
        if @@ERROR<>0 return (1)
        exec dbo.sp_MSindexcolfrombin @join_objid, @keyindex, @joinkeys, @joincol output
        if @@ERROR<>0 return (1)

        /* Make the piece of predicate pertaining to this key column */
        set @filtpiece = @table_name + '.' + @basecol + ' = ' + @join_table + '.' + @joincol
        
        /* If first time through, initialize clause, else add to it */
        if @keyindex = 1
            set @filtclause = @filtpiece
        else
            set @filtclause = @filtclause + ' and ' + @filtpiece

        /* move on to the next key */
        set @keyindex = @keyindex + 1
        end

    /* Add the join filter */
    exec @retcode = dbo.sp_addmergefilter @publication, @article, @filt_name, @join_article, @filtclause, @join_unique
    if @@ERROR<>0 or @retcode<>0 return (1)
    return (0)
    GO

exec dbo.sp_MS_marksystemobject sp_MSmakejoinfilter
go

raiserror('Creating procedure sp_MSmakeexpandproc', 0,1)
GO

create procedure sp_MSmakeexpandproc
    @pubname        sysname,
    @filterid       int,
    @procname       sysname
    AS
    /* Declare additional variables */
    declare @pubid  uniqueidentifier
    declare @base_nick int
    declare @join_nick int
    declare @base_nickstr nvarchar(10)
    declare @join_nickstr nvarchar(10)
    declare @filterid_str nvarchar(10)
    declare @base_objid int
    declare @join_objid int
    declare @base_table sysname
    declare @join_table sysname
    declare @base_owner sysname
    declare @join_owner sysname
    declare @join_clause nvarchar(4000)
    declare @retcode    int
    declare @must_check int
    declare @view_type  int
    declare @guidcolname    sysname
    declare @view_objid int
    declare @view_name  sysname
    declare @cmd_piece  nvarchar(4000)

    select @pubid = pubid from sysmergepublications where name = @pubname and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()

    -- this procedure is to be called by xp_execresultset, so
    -- we create a temp table, put command pieces into it, and select them out
    
    -- create temp table to select the command text out of
    create table #tempcmd (step int identity NOT NULL, cmdtext nvarchar(4000) NULL)

    /* Figure out base table, join table for this join filter */
    select @base_nick = art_nickname, @join_nick = join_nickname,
        @join_clause = join_filterclause
        from sysmergesubsetfilters where pubid = @pubid and join_filterid = @filterid
    select @base_objid = objid, @view_type = view_type, @view_objid = sync_objid from sysmergearticles where pubid = @pubid and nickname = @base_nick
    select @join_objid = objid from sysmergearticles where pubid = @pubid and nickname = @join_nick
    select @base_table = QUOTENAME(name), @base_owner = QUOTENAME(user_name(uid)) from sysobjects where id = @base_objid
    select @join_table = QUOTENAME(name), @join_owner = QUOTENAME(user_name(uid)) from sysobjects where id = @join_objid
    select @guidcolname = name from syscolumns where id = @base_objid and 
            columnproperty (id, name, 'isrowguidcol')=1
    select @view_name = object_name(@view_objid)
    -- Quote the viewname.  It is made from pub name which may have odd characters.
    set @view_name = QUOTENAME(@view_name)
    set @base_nickstr = convert(nchar(10), @base_nick)
    set @join_nickstr = convert(nchar(10), @join_nick)
    set @filterid_str = convert(nchar(10), @filterid)
    
    set @cmd_piece = 'create procedure ' + @procname + ' 
        @belong int 
        AS 
            '
    insert into #tempcmd(cmdtext) values (@cmd_piece)
    set @cmd_piece = 'if @belong = 1
            begin
            /* Do a bulk insert to expand #belong */
            update #belong set flag = ' + @filterid_str + ' where flag < ' + @filterid_str + ' 
            insert into #belong (tablenick, rowguid, flag) select ' + @base_nickstr +
            ', ' + @base_table + '.rowguidcol, 0 from ' + @base_owner + '.' + @base_table + ', ' +
            @join_owner + '.' + @join_table + ', #belong b where (' + @join_clause + ') and ' + 
            @join_table + '.rowguidcol = b.rowguid and b.tablenick = ' + @join_nickstr
    insert into #tempcmd(cmdtext) values (@cmd_piece)
    set @cmd_piece = '  
        if @@ERROR <>0 return (1)
        /* Delete duplicates */
        delete from #belong where flag = 0 and rowguid in
            (select rowguid from #belong where flag <> 0)
        end '
        insert into #tempcmd(cmdtext) values (@cmd_piece)
        
    /* Will we have to check rows that we add to #notbelong? */
    if exists (select * from sysmergearticles where pubid = @pubid and nickname = @join_nick and
        len(subset_filterclause) > 0)
        set @must_check = 1
    else if exists (select * from sysmergesubsetfilters where pubid = @pubid and join_filterid = @filterid and
        join_unique_key <> 1)
        set @must_check = 1
    else if not exists (select * from sysmergesubsetfilters where pubid = @pubid and  art_nickname = @base_nick
            and join_filterid <> @filterid)
        set @must_check = 0
    
    set @cmd_piece = '
        else 
        begin
        /* Do a bulk insert to expand #notbelong */
        insert into #notbelong (tablenick, rowguid, flag) select ' + @base_nickstr +
            ', ' + @base_table + '.rowguidcol, -1 from ' + @base_owner + '.' + @base_table + ', ' +
            @join_owner + '.' + @join_table + ', #notbelong nb where (' + @join_clause + ') and ' + 
            @join_table + '.rowguidcol = nb.rowguid
            /* Remove duplicates */
            delete from #notbelong where flag = -1 and rowguid in
                (select rowguid from #notbelong where flag <> -1)
            '
    if @must_check = 0
        begin
        insert into #tempcmd(cmdtext) values (@cmd_piece)
        set @cmd_piece = ' update #notbelong set flag = 0 where flag = -1 
            end '
        insert into #tempcmd(cmdtext) values (@cmd_piece)
        end
    else if @view_type = 1
        begin
        insert into #tempcmd(cmdtext) values (@cmd_piece)
        set @cmd_piece =  '     -- We can do our check with a bulk delete, bulk update
            delete from #notbelong where flag = -1 and rowguid in
                (select ' + @guidcolname + ' from ' + @view_name + ')
            update #notbelong set flag = 0 where flag = -1
            end '
        insert into #tempcmd(cmdtext) values (@cmd_piece)
        end
    -- else we don't bother expanding #notbelong for this filter since there are cyclic
    -- join filters and this is not a unique key join.  The cursored calls to sp_belongs
    -- are unacceptably slow, and there would still be cases where orphaned rows could occur.

-- Now we select out the command text pieces in proper order so that our caller,
-- xp_execresultset will execute the command that creates the stored procedure.

select cmdtext from #tempcmd order by step

GO

exec dbo.sp_MS_marksystemobject sp_MSmakeexpandproc
go


raiserror('Creating procedure sp_MSdrop_expired_mergesubscription', 0,1)
GO

create procedure sp_MSdrop_expired_mergesubscription
AS
/*
** This stored procedure is to periodically check the status of all the subscriptions 
** of every merge publication. If any of them is out-of-date, i.e., has lost contact
** with publisher for a certain length of time, we can declare the death of that replica
** and cleanup their traces at the publisher side
*/
declare @subscription_type  int
declare @sub_type           nvarchar(5)
declare @publication        sysname
declare @pubid              uniqueidentifier
declare @subid              uniqueidentifier
declare @status             tinyint
declare @publisher_id       int
declare @subscriber         sysname
declare @subscriber_id      int
declare @subscriber_db      sysname
declare @publisher_db       sysname
declare @distributor        sysname
declare @distribdb          sysname
declare @retention          int  -- in days         
declare @retcode            smallint
declare @distproc           nvarchar(255)
declare @localproc          nvarchar(255)
declare @msg                nvarchar(255)
declare @recgen             int
declare @sentgen            int
declare @max_distretention  int
declare @recent_merge       datetime
declare @minus_retention2   datetime
declare @minus_retention    datetime
declare @send_ts            datetime
declare @receive_ts         datetime

/*
** Security Check
*/
    EXEC @retcode = dbo.sp_MSreplcheck_publish
    IF @@ERROR <> 0 or @retcode <> 0
        return (1)



declare PC CURSOR LOCAL FAST_FORWARD for select DISTINCT p.name, p.pubid, p.retention from sysmergepublications p, sysmergesubscriptions s 
        where s.subid=p.pubid and s.pubid=p.pubid for read only
    open PC
    fetch PC into @publication, @pubid, @retention 
    
    select @minus_retention2 = dateadd(day, -@retention * 2, getdate())
    select @minus_retention = dateadd(day, -@retention, getdate())

    WHILE (@@fetch_status <> -1)
        BEGIN
        	if @retention is not NULL and @retention > 0
        	begin
           	 	declare SC CURSOR LOCAL FAST_FORWARD for select srvid, db_name, subid, status, subscription_type from sysmergesubscriptions where 
            	    pubid = @pubid and pubid<>subid for read only
           		open SC
            	fetch SC into @subscriber_id, @subscriber_db, @subid, @status, @subscription_type
            	WHILE (@@fetch_status <> -1)
                	BEGIN
                    	select @subscriber=srvname from master..sysservers where srvid=@subscriber_id
	                    if @subscription_type = 0 select @sub_type = 'push' else select @sub_type = 'pull'
    	                select @receive_ts = coldate from MSmerge_genhistory where guidsrc = (select recguid from MSmerge_replinfo 
        	                    where repid = @subid)
            	        select @sentgen=sentgen from MSmerge_replinfo where repid=@subid
                	    select @send_ts = coldate from MSmerge_genhistory where generation=@sentgen
                    	if @receive_ts>@send_ts select @recent_merge = @receive_ts
                 	       else select @recent_merge = @send_ts
                            
 	                   if @status <> 2 and @recent_merge<@minus_retention
    	                begin
        	                exec @retcode = dbo.sp_dropmergesubscription  
            	                    @publication = @publication,
                	                @subscriber = @subscriber,
                    	            @subscriber_db = @subscriber_db,
                        	        @subscription_type = @sub_type  
                       		if @retcode <>0 or @@ERROR<>0
                            	goto FAILURE
                    	end
                    	if @recent_merge<@minus_retention2 
                    	begin
                        	delete from sysmergesubscriptions where subid = @subid --delete the row in sysmergesubscription
               		        if @@ERROR<>0
	                            goto FAILURE
    	                    delete from MSmerge_replinfo where repid = @subid
        	                if @@ERROR<>0
            	                goto FAILURE
                	    end     
	                    fetch SC into @subscriber_id, @subscriber_db, @subid, @status, @subscription_type
    	            END
        	    CLOSE SC
            	DEALLOCATE SC
            end
            fetch PC into @publication, @pubid, @retention
        END
    CLOSE PC
    DEALLOCATE PC
	return (0)
    
FAILURE:
    close SC
    deallocate SC
    close PC
    deallocate PC
    return (1)

GO
exec dbo.sp_MS_marksystemobject sp_MSdrop_expired_mergesubscription
go

raiserror('Creating procedure sp_generatefilters', 0,1)
GO

create procedure sp_generatefilters
    @publication                sysname
    AS
    /* Declare  a few variables */
    declare @pubid  uniqueidentifier
    declare @art_name sysname
    declare @object_id  int
    declare @join_objid int
    declare @retcode int
    declare @join_unique int
    declare @distance int
    
    /*
    ** Security Check
    */
    EXEC @retcode = dbo.sp_MSreplcheck_publish
    IF @@ERROR <> 0 or @retcode <> 0
        return (1)

    /*
    ** Parameter Check: @publication.
    ** The @publication id cannot be NULL and must conform to the rules
    ** for identifiers.
    */   
        
    if @publication is NULL
        begin
            raiserror (14043, 16, -1, '@publication')
            return (1)
        end
    /*
    ** Get the pubid and make sure the publication exists
    */
    select @pubid = pubid from sysmergepublications 
        where name = @publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()
    if @pubid is NULL
        begin
            raiserror (14027, 16, -1, @publication)
            return (1)
        end

    /* Set up some temp tables to help keep track of what to process */
    create table #filtered (object_id int NOT NULL, distance int NOT NULL)
    create table #unfiltered (object_id int NOT NULL, art_name sysname NOT NULL)

    /* Do initial population of temp tables */
    insert into #filtered (object_id, distance) select objid, 0 from sysmergearticles where
        pubid = @pubid and len(subset_filterclause) > 0
    insert into #unfiltered (object_id, art_name) select objid, name from sysmergearticles
        where pubid = @pubid and objid not in (select object_id from #filtered)

    /* remove self-referencing tables from #unfiltered as we should not try to filter them */
    delete from #unfiltered where object_id in
            (select rkeyid from sysreferences where rkeyid = fkeyid)
    select @distance = min(distance) from #filtered f, sysreferences r, #unfiltered u where
        (f.object_id = r.rkeyid and r.fkeyid = u.object_id) or
        (u.object_id = r.rkeyid and r.fkeyid = f.object_id)
        
    /* Look for something in sysreferences to add a join filter for */
    select @join_unique = 1, @object_id = fkeyid, @join_objid = rkeyid, @art_name = art_name
        from sysreferences r, #unfiltered u where r.fkeyid = u.object_id and
        r.rkeyid in (select object_id from #filtered where distance = @distance) 

    if @art_name is null
        select  @join_unique = 0, @object_id = rkeyid, @join_objid = fkeyid, @art_name = art_name
            from sysreferences r, #unfiltered u where r.rkeyid = u.object_id and
            r.fkeyid in (select object_id from #filtered where distance = @distance) 
    while @art_name is not null
        begin
        /* Make the join filter corresponding to this relationship */
        exec @retcode=sp_MSmakejoinfilter @publication, @art_name, @object_id, @join_objid, @join_unique
        if @@ERROR<>0 or @retcode<>0 return (1)
        /* Move row from #unfiltered to #filtered */
        insert into #filtered (object_id, distance) values (@object_id, @distance + 1)
        delete from #unfiltered where object_id = @object_id
        
        /* See if any more that can be added */
        select @distance = min(distance) from #filtered f, sysreferences r, #unfiltered u where
            (f.object_id = r.rkeyid and r.fkeyid = u.object_id) or
            (u.object_id = r.rkeyid and r.fkeyid = f.object_id)
        set @art_name = NULL
        select @join_unique = 1, @object_id = fkeyid, @join_objid = rkeyid, @art_name = art_name
            from sysreferences r, #unfiltered u where r.fkeyid = u.object_id and
            r.rkeyid in (select object_id from #filtered where distance = @distance) 
        if @art_name is null
            select  @join_unique = 0, @object_id = rkeyid, @join_objid = fkeyid, @art_name = art_name
                from sysreferences r, #unfiltered u where r.rkeyid = u.object_id and
                r.fkeyid in (select object_id from #filtered where distance = @distance) 
        end
    return (0)
go
            
exec dbo.sp_MS_marksystemobject sp_generatefilters
go

grant execute on dbo.sp_generatefilters to public
go

/*
** Name :       sp_MShelpmergeconflictcounts
** Description: This sp returns the count of conflicts (from MSmerge_delete_conflicts and 
**              each conflict table) in each publication. Results can optionally be filtered
**				to include only a single publication. Results are always ordered by article
**				name. Only articles with non-zero conflict counts are returned.
** Parameters:  1. Publication Name( sysname; default '%'==ALL PUBLICATIONS)
** Output Result Set has the following structure 
**  ----------------------------------------------------------------------------------
**      Name                Datatype                Description
**  ----------------------------------------------------------------------------------
**  a. article				(sysname)		    Article name
**  b. conflict_table		(sysname)			Associated conflict table
**  c. guidcolname			(sysname)			Article's rowguidcol name
**  d. centralized_conflicts(integer)			Centralized (1) or Decentralized (0) 
**												conflicts specified by the article
**  e. conflict_ucount		(integer)           Count of (update) conflicts in the 
**												conflict table for this article
**  f. conflicts_dcount		(integer)           Count of (delete) conflicts in the 
**												MSmerge_delete_conflicts table for this article
*/
raiserror('Creating procedure sp_MShelpmergeconflictcounts', 0,1)
GO

create procedure sp_MShelpmergeconflictcounts ( @publication_name sysname = '%' )
as 
begin

	set nocount on 

	declare @pname sysname, 
			@aname sysname, 
			@cmd nvarchar(2000), 
			@dbname sysname, 
			@conflict_table sysname, 
			@count integer,
			@db_mergepublish integer

	select @dbname = db_name(), @db_mergepublish = 4

	-- make sure current db has merge publishing tables (true on both pub and sub)
	if not exists ( select * from sysobjects where name = 'sysmergearticles')
	begin
		raiserror( 18757, 16, -1 )
		return(1)
	end

	-- allow null conflict table name to handle case where there are delete conflicts but no update conflicts
	create table #result_list ( article sysname, source_object sysname, conflict_table sysname null, guidcolname sysname, centralized_conflicts integer, conflicts_ucount integer, conflicts_dcount integer )
	create table #conflict_list ( article_name sysname, conflicts_ucount integer, conflicts_dcount integer )
	create table #update_list ( article_name sysname, conflicts_ucount integer )

	-- get delete counts
	if ( @publication_name = '%' )
		declare hCdcount CURSOR LOCAL FAST_FORWARD fast_forward for 
			select distinct a.name 
				from MSmerge_delete_conflicts d
				inner join sysmergepublications p on p.pubid = d.pubid
				inner join sysmergearticles a on a.pubid = p.pubid and a.nickname = d.tablenick
	else
		declare hCdcount CURSOR LOCAL FAST_FORWARD fast_forward for 
			select distinct a.name 
				from MSmerge_delete_conflicts d
				inner join sysmergepublications p on p.pubid = d.pubid
				inner join sysmergearticles a on a.pubid = p.pubid and a.nickname = d.tablenick
				where p.name = @publication_name

	open hCdcount
	fetch hCdcount into @aname
	while ( @@fetch_status <> -1 )
	begin

		select @cmd = 'select ''' + @aname + ''', 0, count(*) 
				from MSmerge_delete_conflicts d
					inner join sysmergepublications p on p.pubid = d.pubid
					inner join sysmergearticles a on a.pubid = p.pubid and a.nickname = d.tablenick
				where a.name = N''' + @aname + ''' '

		if ( @publication_name <> '%' ) 
			select @cmd = @cmd + ' and p.name = N''' + @publication_name + ''''

		insert #conflict_list ( article_name, conflicts_ucount, conflicts_dcount )
			exec ( @cmd )

		fetch hCdcount into @aname
	end
	close hCdcount
	deallocate hCdcount

	-- get update counts
	if ( @publication_name = '%' )
		declare hCucount CURSOR LOCAL FAST_FORWARD fast_forward for 
			select distinct a.name, a.conflict_table
				from sysmergepublications p
				inner join sysmergearticles a on a.pubid = p.pubid
			where a.conflict_table is not null
	else
		declare hCucount CURSOR LOCAL FAST_FORWARD fast_forward for 
			select distinct a.name, a.conflict_table
				from sysmergepublications p
				inner join sysmergearticles a on a.pubid = p.pubid
			where a.conflict_table is not null
			  and p.name = @publication_name

	open hCucount
	fetch hCucount into @aname, @conflict_table
	while ( @@fetch_status <> -1 )
	begin
		select @cmd = 'select ''' + @aname + ''', count(*) 
				from ' + QUOTENAME( @conflict_table ) + ' ct
					inner join sysmergepublications p on p.pubid = ct.pubid '

		if ( @publication_name <> '%' ) 
			select @cmd = @cmd + ' where p.name = N''' + @publication_name + ''''

		insert #update_list ( article_name, conflicts_ucount )
			exec( @cmd )

		fetch hCucount into @aname, @conflict_table
	end
	close hCucount
	deallocate hCucount

	update #conflict_list set conflicts_ucount = isnull( ul.conflicts_ucount, 0 )
		from #conflict_list cl
		inner join #update_list ul on ul.article_name = cl.article_name

	delete #update_list 
		from #update_list ul 
		inner join #conflict_list cl on ul.article_name = cl.article_name

	insert #conflict_list
		select *, 0 from #update_list where conflicts_ucount > 0

	drop table #update_list
	select @cmd = 'select distinct t.article_name, '''' + quotename(user_name( o.uid )) + ''.'' + quotename(o.name) + '''',' +
			' a.conflict_table, c.name, p.centralized_conflicts, t.conflicts_ucount, t.conflicts_dcount
			from #conflict_list t
				inner join sysmergearticles a on a.name = t.article_name
				inner join sysmergepublications p on p.pubid = a.pubid
				inner join sysobjects o on o.id = a.objid 
				inner join syscolumns c on c.id = o.id and ColumnProperty (o.id, c.name, ''IsRowGuidCol'') = 1
			where t.conflicts_ucount > 0 or t.conflicts_dcount > 0'

	insert #result_list
		exec ( @cmd )		
	if ( @@error <> 0 )
		return (1)

	drop table #conflict_list

	select * from #result_list
	drop table #result_list

return (0)
end
go

exec dbo.sp_MS_marksystemobject sp_MShelpmergeconflictcounts
go

grant execute on dbo.sp_MShelpmergeconflictcounts to public
go

/*
** Name :       sp_helpmergearticleconflicts
** Description: This sp returns the articles in the publication that have conflicts.
**              Optionally if the publication is not specified, all articles in the 
**              database that have conflicts is returned.
** Parameters:  Publication Name( default NULL)
** Output Result Set has the following columns
**              publication, article, source_object, conflict_table, guidcolname
*/
raiserror('Creating procedure sp_helpmergearticleconflicts', 0,1)
GO
CREATE PROCEDURE sp_helpmergearticleconflicts(
    @publication    sysname = '%'
    )
as
	set nocount on
    declare @publisher      sysname
    declare @publisher_db   sysname
    declare @pubid          uniqueidentifier
    declare @cmd            nvarchar(4000)

    declare @retcode		int
	declare @nickname		int
    declare @retcode2 		int
    declare @name			sysname
    declare @source_owner	sysname
    declare @source_object	sysname
    declare @conflict_table	sysname
    declare @guidcolname		sysname
    declare @centralized_conflicts int
	declare @objid			int
	declare @command		nvarchar(200)

    select @publisher = @@SERVERNAME
    select @publisher_db =db_name()

	if @publication <> '%'
        begin
            /*
            ** Parameter Check:  @publication.
            ** Make sure that the publication exists.
            */
            select @pubid = pubid from sysmergepublications 
                where name = @publication
            if @pubid IS NULL
                BEGIN
                    RAISERROR (20026, 16, -1, @publication)
                    RETURN (1)
                END
		end

	create table #temp_conflict(article 				sysname,
								source_owner			sysname,
								source_object			sysname,
								conflict_table			sysname,
								guidcolname				sysname,
								centralized_conflicts	int) 	

	declare #cur_conflict cursor local for 
		select name, objid, conflict_table, pubid, nickname from sysmergearticles 
			where conflict_table is not NULL and pubid in (select pubid from sysmergepublications where name like @publication)
				for read only
	open #cur_conflict
	fetch #cur_conflict into @name, @objid, @conflict_table, @pubid, @nickname
	while (@@fetch_status <> -1)
	begin
		select @command = 'if exists (select * from ' + QUOTENAME(@conflict_table) + ') select @retcode2 = 1
								else select @retcode2 = 0'
		EXEC @retcode = dbo.sp_executesql @command, N'@retcode2 int output', @retcode2 output
		if @retcode <>0
				return (1)
		if @retcode2 = 1 
		begin
			select @source_owner = user_name(uid) from sysobjects where id = @objid
			select @source_object = object_name (@objid)
			select @guidcolname = name from syscolumns where id = @objid and ColumnProperty(@objid, name, 'IsRowGuidCol') = 1
			select @centralized_conflicts = centralized_conflicts from sysmergepublications where pubid = @pubid
			insert into #temp_conflict 
				values (@name, @source_owner, @source_object, @conflict_table, @guidcolname, @centralized_conflicts)
		end
		if EXISTS (select * from MSmerge_delete_conflicts where tablenick = @nickname)
		begin
			insert into #temp_conflict
				values (@name, @source_owner, @source_object, 'MSmerge_delete_conflicts', @guidcolname, @centralized_conflicts)
		end
		fetch #cur_conflict into @name, @objid, @conflict_table, @pubid, @nickname
	end

	select * from #temp_conflict order by article

	drop table #temp_conflict
	close #cur_conflict
	deallocate #cur_conflict
return(0)       
go
exec dbo.sp_MS_marksystemobject sp_helpmergearticleconflicts 
go

/*
** Name :       sp_helpmergeconflictrows
** Description: This sp returns the rows in the conflict_table specified. 
**              Optionally if the publication is specified, all conflicts qualified by the
**              publication are returned. For instance if the Conflict_Customers table 
**              has conflict rows for the 'WA' and the 'CA' publication, passing in 
**              a publication name say 'CA' retrieves conflicts pertaining to the 
**              'CA' publication.
** Parameters:  1. Publication Name( default NULL)
**              2. Conflict Table Name
** Output Result Set has the same structure as the Conflict_<table> i.e the base
** table structure with the following additional columns:
**  ----------------------------------------------------------------------------------
**      Name                Datatype            Description
**  ----------------------------------------------------------------------------------
**  a. origin_datasource    (varchar(255))      Indicates the origin of the conflict                                                         
**  b. conflict_type        (int)               Code indicating type of conflict
**                                              UpdateConflict      = 1
**                                              UploadError         = 2
**                                              DownloadError       = 3
**                                              UpdateDeleteConflict= 4
**                                              ColumnUpdateConflict= 5
**  c. reason_code          (int)               Error code that may be context sensitive 
**  d. reason_text          (varchar(720))      Error description that may be context sensitive                                                          
**  e. pubid                (uniqueidentifier)  Publication identifier
*/
raiserror('Creating procedure sp_helpmergeconflictrows', 0,1)
GO
CREATE PROCEDURE sp_helpmergeconflictrows(
    @publication    sysname = '%',
    @conflict_table sysname
    )
as 
	set nocount on
    declare @publisher      sysname
    declare @publisher_db   sysname
    declare @pubid          uniqueidentifier
    declare @cmd            nvarchar(4000)  
    
    select @publisher = @@SERVERNAME
    select @publisher_db = db_name()
    select @cmd = 'select * from ' 
    select @cmd = @cmd + @conflict_table 
    if @publication <> '%'
        begin
            /*
            ** Parameter Check:  @publication.
            ** Make sure that the publication exists.
            */
            select @pubid = pubid from sysmergepublications 
                where name = @publication
            if @pubid IS NULL
                BEGIN
                    RAISERROR (20026, 16, -1, @publication)
                    RETURN (1)
                END

            
            select @cmd = @cmd + ' where pubid = (select pubid from sysmergepublications where name = ''' + @publication + ''') '
        end
    exec (@cmd)
    if (@@error <> 0)
        RETURN (1)
    
    return 0
go

exec dbo.sp_MS_marksystemobject sp_helpmergeconflictrows 
go

/*
** Name :       sp_helpmergedeleteconflictrows
** Description: This sp returns the rows in the MSmerge_delete_conflicts specified. 
**              Optionally if the publication is specified, all conflicts qualified by the
**              publication are returned. For instance if the MSmerge_delete_conflicts table 
**              has conflict rows for the 'WA' and the 'CA' publication, passing in 
**              a publication name say 'CA' retrieves conflicts pertaining to the 
**              'CA' publication only.
** Parameters:  1. Publication Name( default NULL)
**              2. Source Object Name
** Output Result Set has the following structure 
**  ----------------------------------------------------------------------------------
**      Name                Datatype                Description
**  ----------------------------------------------------------------------------------
**  a. source_object        (nvarchar(386))     Indicates the source object for the delete conflict                                                         
**  b. rowguid              (uniqueidentifier)  Row identifier for the delete conflict
**  c. origin_datasource    (varchar(255))      Indicates the origin of the conflict                                                         
**  d. conflict_type        (int)               Code indicating type of conflict
**                                              UpdateConflict      = 1
**                                              UploadError         = 2
**                                              DownloadError       = 3
**                                              UpdateDeleteConflict= 4
**                                              ColumnUpdateConflict= 5
**  e. reason_code          (int)               Error code that may be context sensitive 
**  f. reason_text          (varchar(720))      Error description that may be context sensitive                                                          
**  g. pubid                (uniqueidentifier)  Publication identifier
*/
raiserror('Creating procedure sp_helpmergedeleteconflictrows', 0,1)
GO

CREATE PROCEDURE sp_helpmergedeleteconflictrows(
    @publication    sysname = '%',
    @source_object  nvarchar(386) = NULL
    )
as
    declare @publisher      sysname
    declare @publisher_db   sysname
    declare @pubid          uniqueidentifier
    declare @cmd            nvarchar(4000)  

    select @publisher = @@SERVERNAME
    select @publisher_db = db_name()
    select @cmd = 'select distinct source_object =  user_name(sysobjects.uid) + '
    select @cmd = @cmd + '''.'''
    select @cmd = @cmd + ' + sysobjects.name, MSmerge_delete_conflicts.rowguid, MSmerge_delete_conflicts.conflict_type, '
    select @cmd = @cmd + ' MSmerge_delete_conflicts.reason_code, MSmerge_delete_conflicts.reason_text, '
    select @cmd = @cmd + ' MSmerge_delete_conflicts.origin_datasource, MSmerge_delete_conflicts.pubid from MSmerge_delete_conflicts, sysmergearticles, sysobjects'  
    select @cmd = @cmd + ' where sysmergearticles.nickname = MSmerge_delete_conflicts.tablenick and sysobjects.id = sysmergearticles.objid '
    if @publication <> '%'
        begin
            /*
            ** Parameter Check:  @publication.
            ** Make sure that the publication exists.
            */
            select @pubid = pubid from sysmergepublications where 
                name = @publication
            if @pubid IS NULL
                BEGIN
                    RAISERROR (20026, 16, -1, @publication)
                    RETURN (1)
                END

            select @cmd = @cmd + ' and MSmerge_delete_conflicts.pubid = (select pubid from sysmergepublications 
                        where name = ''' + @publication + ''') '
        end

    if @source_object IS NOT NULL
        begin
            declare @object         sysname  
            declare @owner          sysname  
            declare @tablenick      int
            declare @tablenickstr   nvarchar(11)
            
            select @object = PARSENAME(@source_object, 1)
            select @owner = PARSENAME(@source_object, 2)
            execute dbo.sp_MStablenickname @owner, @object, @tablenick output
            if @tablenick IS NULL
                BEGIN
                    raiserror (20003, 11, -1, @object)
                    RETURN (1)
                END
            set @tablenickstr = convert(nchar, @tablenick)
            select @cmd = @cmd + ' and MSmerge_delete_conflicts.tablenick = '
            select @cmd = @cmd + @tablenickstr
        end

    exec (@cmd)
    if (@@error <> 0)
        RETURN (1)
    
    return 0
go

exec dbo.sp_MS_marksystemobject sp_helpmergedeleteconflictrows 
go

/*
** Name :       sp_deletemergeconflictrow
** Description: This sp deletes the row matching rowguid and origin_datasource
**              If now rows are left in conflict_table
**                  --Set the conflict_table property of the article(s) to NULL
**                  --Drop the conflict table (optionally)
**              If the conflict_table is specified as NULL, the conflict is assumed
**              to be a delete conflict and the row matching rowguid and origin_datasource
**              and source_object is deleted from the MSmerge_delete_conflicts table. The
**              MSmerge_delete_conflicts table is a system table and is not deleted 
**              from the database even if it is empty.
** Parameters:  
**  ----------------------------------------------------------------------------------
**      Name                Datatype                Description
**  ----------------------------------------------------------------------------------
**  a. conflict_table       (sysname)           Indicates the conflict table name. If
                                                '%' then delete from MSmerge_delete_conflicts
**  b. source_object        (nvarchar(386))     Source table 
**  c. rowguid              (uniqueidentifier)  Row identifier for the delete conflict
**  d. origin_datasource    (varchar(255))      Indicates the origin of the conflict                                                         
**  e. drop_table_if_empty  (varchar(10))       Flag indicating if the Conflict_<table>
**                                              is to be dropped if is empty
*/
raiserror('Creating procedure sp_deletemergeconflictrow', 0,1)
GO

CREATE PROCEDURE sp_deletemergeconflictrow(
    @conflict_table         sysname = '%',
    @source_object          nvarchar(386) = NULL,
    @rowguid                uniqueidentifier,
    @origin_datasource      varchar(255),
    @drop_table_if_empty    varchar(10) = 'false')
as
    declare @retcode        smallint
    declare @cmd            nvarchar(4000)  
    declare @rowguidstr     nvarchar(40)
    declare @object         sysname  
    declare @owner          sysname  
    declare @tablenick      int
    declare @tablenickstr   nvarchar(11)


    set @rowguidstr = convert(nchar(36), @rowguid)

    /* Delete conflict from Conflict_<Table> */
    if @conflict_table <> '%'
        begin
            select @cmd = 'delete from '
            select @cmd = @cmd + @conflict_table 
            select @cmd = @cmd + ' where origin_datasource = '''
            select @cmd = @cmd + @origin_datasource 
            select @cmd = @cmd + ''' and rowguid = '''
            select @cmd = @cmd + @rowguidstr
            select @cmd = @cmd + ''''
            -- DEBUG select 'Delete conflict_table query' = @cmd
            exec (@cmd)
            if @@ERROR<>0 return (1)

            select @cmd = 'if not exists (select 1 from ' 
            select @cmd = @cmd + @conflict_table 
            select @cmd = @cmd + ')'
            select @cmd = @cmd + ' update sysmergearticles set ins_conflict_proc = NULL, conflict_table = NULL where conflict_table = '''
            select @cmd = @cmd + @conflict_table
            select @cmd = @cmd + ''''
            -- DEBUG select "Update conflict_table query" = @cmd
            exec (@cmd)
            if @@ERROR<>0 return (1)

            if LOWER(@drop_table_if_empty) = 'true'
                begin
                    select @cmd = 'if not exists (select 1 from ' 
                    select @cmd = @cmd + @conflict_table 
                    select @cmd = @cmd + ')'
                    select @cmd = @cmd + ' drop table '
                    select @cmd = @cmd + @conflict_table
                    select @cmd = @cmd + ''
                    -- DEBUG select "Drop conflict_table query" = @cmd
                    exec (@cmd)
                    if @@ERROR<>0 return (1)
                end
        end
    /* Delete conflict from MSmerge_delete_conflicts */
    else
        begin
            select @object = PARSENAME(@source_object, 1)
            select @owner = PARSENAME(@source_object, 2)
            execute @retcode=sp_MStablenickname @owner, @object, @tablenick output
        
            if @tablenick IS NULL or @@ERROR<>0 or @retcode<>0
                BEGIN
                    raiserror (20003, 11, -1, @object)
                    RETURN (1)
                END

            set @tablenickstr = convert(nchar, @tablenick)

            
            select @cmd = 'delete from MSmerge_delete_conflicts'
            select @cmd = @cmd + ' where origin_datasource = '''
            select @cmd = @cmd + @origin_datasource 
            select @cmd = @cmd + ''' and tablenick = '
            select @cmd = @cmd + @tablenickstr
            select @cmd = @cmd + ' and rowguid = '''
            select @cmd = @cmd + @rowguidstr
            select @cmd = @cmd + ''''
            -- DEBUG select 'MSMerge_Delete conflict_table query' = @cmd
            exec (@cmd)
            if @@ERROR<>0 return (1)

        end

go

exec dbo.sp_MS_marksystemobject sp_deletemergeconflictrow 
go

/*
** Name :       sp_getmergedeletetype
** Description: This sp returns the type of delete
** Parameters:  
**  ----------------------------------------------------------------------------------
**      Name                Datatype                Description
**  ----------------------------------------------------------------------------------
**  a. source_object        (nvarchar(386))     Indicates the source object
**  b. rowguid              (uniqueidentifier)  Row identifier for the delete conflict
**  c. delete_type(OUTPUT)  (int)               Code indicating delete type
**                                              User Delete     -   1
**                                              Partial Delete  -   5                                                       
**                                              System Delete   -   6                                                       
*/
raiserror('Creating procedure sp_getmergedeletetype', 0,1)
GO

CREATE PROCEDURE sp_getmergedeletetype(
    @source_object  nvarchar (386),
    @rowguid        uniqueidentifier,
    @delete_type    int OUTPUT
)
as
    declare @object         sysname  
    declare @owner          sysname  
    declare @tablenick      int

    select @object = PARSENAME(@source_object, 1)
    select @owner = PARSENAME(@source_object, 2)
    execute dbo.sp_MStablenickname @owner, @object, @tablenick output
    if @tablenick IS NULL OR @@ERROR<>0
        BEGIN
            raiserror (20003, 11, -1, @object)
            RETURN (1)
        END

    if @rowguid IS NULL 
        begin
            raiserror (14027, 11, -1, '@rowguid')
            return (1)
        end
        
    select @delete_type = type from MSmerge_tombstone where rowguid = @rowguid and tablenick = @tablenick
go

exec dbo.sp_MS_marksystemobject sp_getmergedeletetype 
go

/*
** Name :       sp_mergedummyupdate
** Description: This sp does a dummy updates on the given row so that it will be
**              resent during the next merge.
* Parameters:   
**  ----------------------------------------------------------------------------------
**      Name                Datatype                Description
**  ----------------------------------------------------------------------------------
**  a. source_object        (nvarchar(386))     Indicates the source object
**  b. rowguid              (uniqueidentifier)  Row identifier for the delete conflict
*/
raiserror('Creating procedure sp_mergedummyupdate', 0,1)
GO

CREATE PROCEDURE sp_mergedummyupdate(
    @source_object  nvarchar (386),
    @rowguid        uniqueidentifier
)
as
    declare @object         sysname  
    declare @owner          sysname  
    declare @tablenick      int
    declare @tablenickstr   nvarchar(11)

    select @object = PARSENAME(@source_object, 1)
    select @owner = PARSENAME(@source_object, 2)
    execute dbo.sp_MStablenickname @owner, @object, @tablenick output
    if @tablenick IS NULL or @@ERROR<>0
        BEGIN
            raiserror (20003, 11, -1, @object)
            RETURN (1)
        END
    set @tablenickstr = convert(nchar, @tablenick)

    declare @rowguidstr nvarchar(40)
    if @rowguid IS NULL 
        begin
            raiserror (14043, 11, -1, '@rowguid')
            return (1)
        end
    set @rowguidstr = convert(nchar(36), @rowguid)

    /* 
    ** If the row does not exist in the base table, call sp_MSdummyupdate with metadata_type = 1 (tombstone)
    */
    exec ('if not exists (select 1 from ' + @source_object + ' where rowguidcol = ''' +
        @rowguidstr + ''' ) exec dbo.sp_MSdummyupdate ''' + @rowguidstr + ''',' + @tablenickstr + ', 1')

    /* 
    ** If the row exists in the base table and MSmerge_contents , call sp_MSdummyupdate with metadata_type = 2 (contents)
    */
    exec ('if exists (select 1 from ' + @source_object + ' where rowguidcol = ''' +
        @rowguidstr + ''' ) and exists (select rowguid from MSmerge_contents where rowguid = ''' +
        @rowguidstr + ''' ) exec dbo.sp_MSdummyupdate ''' + @rowguidstr + ''',' + @tablenickstr + ', 2')

    /* 
    ** If the row exists in the base table, but not in MSmerge_contents , call sp_MSdummyupdate with metadata_type = 3 (contents_deferred)
    */
    exec ('if exists (select 1 from ' + @source_object + ' where rowguidcol = ''' +
        @rowguidstr + ''' ) and not exists (select rowguid from MSmerge_contents where rowguid = ''' +
        @rowguidstr + ''' ) exec dbo.sp_MSdummyupdate ''' + @rowguidstr + ''',' + @tablenickstr + ', 3')


go

exec dbo.sp_MS_marksystemobject sp_mergedummyupdate 
go

raiserror('Creating procedure sp_addtabletocontents', 0,1)
GO

create procedure sp_addtabletocontents 
    (@table_name sysname,
     @owner_name sysname = NULL)
AS

    declare @qualified_table_name nvarchar(268)
    declare @tablenick int
    declare @tablenickstr nvarchar(12)
    declare @repl_nick int
    declare @lineage varbinary(249)
    declare @colv varbinary(2000)
    declare @coltrack int
    declare @objid int
    declare @maxcolid int
    declare @retcode int
    declare @gen int
    
    set nocount on
    create table #temp_cont(rowguid uniqueidentifier)
    execute @retcode = dbo.sp_MSgetreplnick @nickname = @repl_nick output
    if (@@error <> 0) or @retcode <> 0 or @repl_nick IS NULL 
        begin
        RAISERROR (14055, 11, -1)
        RETURN(1)
        end                 

	if @owner_name is NULL
		begin
		select @owner_name = user_name(uid) from sysobjects where name = @table_name
		end
	set @qualified_table_name = QUOTENAME(@owner_name) + '.' + QUOTENAME(@table_name)
	
    set @objid = object_id(@qualified_table_name)
    if @objid is NULL return (1)
    select @gen = max(gen_cur), @tablenick = max(nickname), @coltrack = max(column_tracking) from sysmergearticles where objid = @objid
	if @gen is null
		set @gen = 0
    select @maxcolid = max(colid) from syscolumns where id = @objid

    if @coltrack = 1
		set @colv = { fn INITCOLVS(@maxcolid, @repl_nick) }
    else
        set @colv = NULL
    set @lineage = { fn UPDATELINEAGE(0x0, @repl_nick) }

    set @tablenickstr = convert(nchar, @tablenick)

    exec ('insert into #temp_cont(rowguid) select RowGuidCol from ' + @qualified_table_name + ' where
            RowGuidCol not in (select rowguid from MSmerge_contents where tablenick = 
            ' + @tablenickstr + ')')

    insert into MSmerge_contents (tablenick, rowguid, generation, joinchangegen, lineage, colv1)
        select @tablenick, rowguid, @gen, @gen, @lineage, @colv from #temp_cont

    drop table #temp_cont
GO
exec dbo.sp_MS_marksystemobject sp_addtabletocontents 
go
grant exec on dbo.sp_addtabletocontents to public
go

raiserror('Creating procedure sp_MSaddpubtocontents', 0,1)
GO

create procedure sp_MSaddpubtocontents 
    (@publication   sysname)
AS
    declare     @pubid  uniqueidentifier
    declare     @tablenick int
    declare     @retcode int
	declare 	@objid int
	declare 	@owner sysname
	declare		@table sysname
	
    set nocount on
    select @pubid = pubid from sysmergepublications 
        where name = @publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()
    if @pubid is NULL
        begin
            raiserror (14027, 11, -1, @publication)
            return (1)
        end
    
    select @tablenick = min(nickname) from sysmergearticles where pubid = @pubid

    while @tablenick is not null
        begin
		select @objid = objid from sysmergearticles where pubid = @pubid and
			nickname = @tablenick
		select @owner = user_name(uid) from sysobjects where id = @objid
		set @table = OBJECT_NAME(@objid)
        exec @retcode = dbo.sp_addtabletocontents @table, @owner
        
        IF @@ERROR <> 0 or @retcode <> 0
            return (1)

        select @tablenick = min(nickname) from sysmergearticles where pubid = @pubid and
                nickname > @tablenick
        end
GO
exec dbo.sp_MS_marksystemobject sp_MSaddpubtocontents 
go
grant exec on dbo.sp_MSaddpubtocontents to public
go



dump tran master with no_log
go

checkpoint
go
use master
go

execute dbo.sp_configure 'update',1
go
reconfigure with override
go

set ANSI_NULLS off
go

dump tran master with no_log
go

/* 
** Drop the stored procedures in this script using the old dropping SP 
** and then drop itself
*/
if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_MSdrop_rlrecon')
begin
	exec dbo.sp_MSdrop_rlrecon
	drop procedure sp_MSdrop_rlrecon
end

/*
** Create stored procedures to drop the stored procedures
** created by this script
*/

raiserror('Creating procedure sp_MSdrop_rlrecon', 0,1)
GO
create procedure sp_MSdrop_rlrecon
as

	if exists (select * from sysobjects
	where type = 'P'
		and name = 'sp_MSaddinitialpublication')
	drop procedure sp_MSaddinitialpublication

-- ****************************************************
-- THIS COMMENTED CODE SECTION WILL BE DELETED SOON
-- sp_MSgetversion is now part of XPSTAR.DLL and 
-- will not be installed by REPL code

	-- If sp_MSgetversion exists as SP drop it
	-- otherwise drop the extended proc
	/*
	if exists (select * from sysobjects
	where type = 'P'
		and name = 'sp_MSgetversion')
		drop procedure sp_MSgetversion
	else if exists (select * from sysobjects
	where type = 'X'
		and name = 'sp_MSgetversion')
		execute dbo.sp_dropextendedproc 'sp_MSgetversion'
	*/
-- ****************************************************

	if exists (select * from sysobjects
	where type = 'P'
		and name = 'sp_MSaddinitialsubscription')
	drop procedure sp_MSaddinitialsubscription

	if exists (select * from sysobjects
		where type = 'P'
			and name = 'sp_MSdropconstraints')
	drop procedure sp_MSdropconstraints

	if exists (select * from sysobjects
				where type = 'P' and
				name = 'sp_MSmakeinsertproc')
		drop procedure sp_MSmakeinsertproc
		
	if exists (select * from sysobjects
				where type = 'P' and
				name = 'sp_MSmakeupdateproc')
		drop procedure sp_MSmakeupdateproc 
		
	if exists (select * from sysobjects
				where type = 'P' and
				name = 'sp_MSmakeselectproc')
		drop procedure sp_MSmakeselectproc 

	if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_MSinsertschemachange')
	drop procedure sp_MSinsertschemachange

	if exists (select * from sysobjects
	where type = 'P'
		and name = 'sp_MSaddinitialarticle')
	drop procedure sp_MSaddinitialarticle
		
	
	
		
	if exists (select * from sysobjects
				where type = 'P' and
				name = 'sp_MSmakearticleprocs')
		drop procedure sp_MSmakearticleprocs

	if exists (select * from sysobjects
		where type = 'P'
			and name = 'sp_MSupdatesysmergearticles')
		drop procedure sp_MSupdatesysmergearticles		

	if exists (select * from sysobjects
		where type = 'P'
			and name = 'sp_MSdroparticletombstones')
		drop procedure sp_MSdroparticletombstones		

	if exists (select * from sysobjects
		where type = 'P'
			and name = 'sp_MSproxiedmetadata')
		drop procedure sp_MSproxiedmetadata		
	
	if exists (select * from sysobjects
				where type = 'P' and
				name = 'sp_MShelpmergearticles')
		drop procedure sp_MShelpmergearticles

	if exists (select * from sysobjects
				where type = 'P' and
				name = 'sp_MScreateretry')
		drop procedure sp_MScreateretry

	if exists (select * from sysobjects
				where type = 'P' and
				name = 'sp_MSdropretry')
		drop procedure sp_MSdropretry

	if exists (select * from sysobjects
				where type = 'P' and
				name = 'sp_MSenumretries')
		drop procedure sp_MSenumretries

	if exists (select * from sysobjects
				where type = 'P' and
				name = 'sp_MSdeleteretry')
		drop procedure sp_MSdeleteretry

	if exists (select * from sysobjects
				where type = 'P' and
				name = 'sp_MSgetonerow')
		drop procedure sp_MSgetonerow

	if exists (select * from sysobjects
				where type = 'P' and
				name = 'sp_MSchangearticleresolver')
	   	drop procedure sp_MSchangearticleresolver

	if exists (select * from sysobjects
				where type = 'P' and
				name = 'sp_MSgetlastrecgen')
		drop procedure sp_MSgetlastrecgen

	if exists (select * from sysobjects
				where type = 'P' and
				name = 'sp_MSgetlastsentgen')
		drop procedure sp_MSgetlastsentgen

	if exists (select * from sysobjects
				where type = 'P' and
				name = 'sp_MSsetlastrecgen')
		drop procedure sp_MSsetlastrecgen

	if exists (select * from sysobjects
				where type = 'P' and
				name = 'sp_MSbelongs')
		drop procedure sp_MSbelongs

	if exists (select * from sysobjects
				where type = 'P' and
				name = 'sp_MSsetupbelongs')
		drop procedure sp_MSsetupbelongs

	if exists (select * from sysobjects
				where type = 'P' and
				name = 'sp_MSexpandbelongs')
		drop procedure sp_MSexpandbelongs

	if exists (select * from sysobjects
				where type = 'P' and
				name = 'sp_MSexpandnotbelongs')
		drop procedure sp_MSexpandnotbelongs

	if exists (select * from sysobjects
				where type = 'P' and
				name = 'sp_MSenumpartialdeletes')
		drop procedure sp_MSenumpartialdeletes

	if exists (select * from sysobjects
				where type = 'P' and
				name = 'sp_MSsetlastsentgen')
		drop procedure sp_MSsetlastsentgen

	if exists (select * from sysobjects
				where type = 'P' and
				name = 'sp_MSdummyupdate')
		drop procedure sp_MSdummyupdate 

	if exists (select * from sysobjects
				where type = 'P' and
				name = 'sp_MSdeletepushagent')
		drop procedure sp_MSdeletepushagent
		
	if exists (select * from sysobjects
				where type = 'P' and
				name = 'sp_MScleanuptask')
		drop procedure sp_MScleanuptask

	if exists (select * from sysobjects
				where type = 'P' and
				name = 'sp_MSenumgenerations')
		drop procedure sp_MSenumgenerations

	if exists (select * from sysobjects
				where type = 'P' and
				name = 'sp_MScheckexistsgeneration')
		drop procedure sp_MScheckexistsgeneration

	if exists (select * from sysobjects
				where type = 'P' and
				name = 'sp_MSenumreplicas')
		drop procedure sp_MSenumreplicas

	if exists (select * from sysobjects
				where type = 'P' and
				name = 'sp_MSenumdeletesmetadata')
		drop procedure sp_MSenumdeletesmetadata

	if exists (select * from sysobjects
				where type = 'P' and
				name = 'sp_MSenumchanges')
		drop procedure sp_MSenumchanges
	
	if exists (select * from sysobjects
				where type = 'P' and
				name = 'sp_MSenumpartialchanges')
		drop procedure sp_MSenumpartialchanges


	if exists (select * from sysobjects
				where type = 'P' and
				name = 'sp_MSgetrowmetadata')
		drop procedure sp_MSgetrowmetadata

	if exists (select * from sysobjects
				where type = 'P' and
				name = 'sp_MSsetrowmetadata')
		drop procedure sp_MSsetrowmetadata

	if exists (select * from sysobjects
				where type = 'P' and
				name = 'sp_MSinsertgenhistory')
		drop procedure sp_MSinsertgenhistory

	if exists (select * from sysobjects
				where type = 'P' and
				name = 'sp_MSupdategenhistory')
		drop procedure sp_MSupdategenhistory

	if exists (select * from sysobjects
				where type = 'P' and
				name = 'sp_MSenumschemachange')
		drop procedure sp_MSenumschemachange

	if exists (select * from sysobjects
				where type = 'P' and
				name = 'sp_MSupdateschemachange')
		drop procedure sp_MSupdateschemachange

	if exists (select * from sysobjects
			where type = 'P'
				and name = 'sp_MSadd_mergereplcommand')
		drop procedure sp_MSadd_mergereplcommand

	if exists (select * from sysobjects
				where type = 'P' and
				name = 'sp_MSsetreplicainfo')
		drop procedure sp_MSsetreplicainfo

	if exists (select * from sysobjects
				where type = 'P' and
				name = 'sp_MSsetreplicastatus')
		drop procedure sp_MSsetreplicastatus

	if exists (select * from sysobjects
		where type = 'P'
			and name = 'sp_MScreateglobalreplica')
		drop procedure sp_MScreateglobalreplica

	if exists (select * from sysobjects
			where type = 'P'
				and name = 'sp_MSsetconflictscript')
		drop procedure sp_MSsetconflictscript

	if exists (select * from sysobjects
			where type = 'P'
				and name = 'sp_MSsetconflicttable')
		drop procedure sp_MSsetconflicttable
	go

	if exists (select * from sysobjects
				where type = 'P' and
				name = 'sp_MSmakeconflictinsertproc')
		drop procedure sp_MSmakeconflictinsertproc

	if exists (select * from sysobjects
				where type = 'P' and
				name = 'sp_MSmaketempinsertproc')
		drop procedure sp_MSmaketempinsertproc

	if exists (select * from sysobjects
			where type = 'P'
				and name = 'sp_MSgetconflictinsertproc')
		drop procedure sp_MSgetconflictinsertproc

	if exists (select * from sysobjects
				where type = 'P' and
				name = 'sp_MSinsertdeleteconflict')
		drop procedure sp_MSinsertdeleteconflict

	if exists (select * from sysobjects
				where type = 'P' and
				name = 'sp_MScheckmetadatamatch')
		drop procedure sp_MScheckmetadatamatch

	if exists (select * from sysobjects
				where type = 'P' and
				name = 'sp_MSdelrow')
		drop procedure sp_MSdelrow 

	if exists (select * from sysobjects
				where type = 'P' and
				name = 'sp_MSsetartprocs')
		drop procedure sp_MSsetartprocs

	if exists (select * from sysobjects
			where type = 'P'
				and name = 'sp_MSmakesystableviews')
		drop procedure sp_MSmakesystableviews

	if exists (select * from sysobjects
			where type = 'P'
				and name = 'sp_MSgetchangecount')
		drop procedure sp_MSgetchangecount

	if exists (select * from sysobjects
			where type = 'P'
				and name = 'sp_MSuplineageversion')
		drop procedure sp_MSuplineageversion

	if exists (select * from sysobjects
			where type = 'P'
				and name = 'sp_MSvalidatearticle')
		drop procedure sp_MSvalidatearticle
	if exists (select * from sysobjects
			where type = 'P'
				and name = 'sp_MSsubscriptionvalidated')
		drop procedure sp_MSsubscriptionvalidated
		
	if exists (select * from sysobjects
			where type = 'P'
				and name = 'sp_MSdelsubrows')
		drop procedure sp_MSdelsubrows

	if exists (select * from sysobjects
			where type = 'P'
				and name = 'sp_MScontractsubsnb')
		drop procedure sp_MScontractsubsnb

	if exists (select * from sysobjects
			where type = 'P'
				and name = 'sp_MSexpandsubsnb')
		drop procedure sp_MSexpandsubsnb

	if exists (select * from sysobjects
			where type = 'P'
				and name = 'sp_MSmakeviewproc')
		drop procedure sp_MSmakeviewproc


go
exec dbo.sp_MS_marksystemobject sp_MSdrop_rlrecon
go

EXEC dbo.sp_MSdrop_rlrecon
go

raiserror('Creating procedure sp_MShelpmergearticles', 0,1)
GO

CREATE PROCEDURE sp_MShelpmergearticles @publication sysname
as
	declare @pubid uniqueidentifier

	/*
	** To public.
	*/
	
	if (@publication is null)
		begin
		RAISERROR(14003, 16, -1)
		return (1)
		end
	if (not exists(select * from sysobjects where name = 'MSmerge_contents'))
		begin
		RAISERROR(20054 , 16, -1)
		return (1)
		end
	
	select @pubid = pubid from sysmergepublications
		where name = @publication and UPPER(publisher)=UPPER(@@SERVERNAME) and publisher_db=db_name()

	if (@pubid is null)
		begin
        RAISERROR (20026, 11, -1, @publication)
		return (1)
		end

	select a.name, o.name, user_name(o.uid), a.artid, a.pre_creation_command, a.pubid, a.nickname, 
		a.column_tracking, a.status, a.resolver_clsid, a.conflict_script, a.conflict_table,
		a.insert_proc, a.update_proc, a.select_proc, a.destination_object, a.missing_col_count, a.missing_cols, c.name, 
		a.article_resolver, a.resolver_info, a.subset_filterclause
		from sysmergearticles a, 
			sysobjects o left outer join syscolumns c
			on o.id = c.id and ColumnProperty(o.id, c.name, 'IsRowGuidCol') = 1
		where a.pubid = @pubid 
			and o.id = a.objid 
		order by a.nickname
	return (0)
go
exec dbo.sp_MS_marksystemobject sp_MShelpmergearticles 
go
grant exec on dbo.sp_MShelpmergearticles to public
go

raiserror('Creating procedure sp_MScreateretry', 0,1)
GO

CREATE PROCEDURE sp_MScreateretry 
as
	declare @tname sysname
	declare @pname sysname
	declare @tempname sysname
	declare @guid uniqueidentifier
	declare @guidstr varchar(40)
	declare @retcode smallint

	/*
	** To public.
	*/
	
	set @guid = newid()
	exec @retcode=sp_MSguidtostr @guid, @guidstr out
	if @retcode<>0 or @@ERROR<>0 return (1)
	set @tempname = '##retry_' + @guidstr

	exec @retcode = dbo.sp_MSuniquetempname @tempname, @tempname out
	if (@@error <> 0) OR @retcode <> 0
		begin
		RAISERROR(15001, 16, -1, 'sp_MSuniquetempname')
		return (1)
		end

	exec ('create table ' + @tempname + ' (tablenick int NOT NULL, rowguid uniqueidentifier ROWGUIDCOL default newid() not null, errcode int NOT NULL, errtext nvarchar(255) NULL, type tinyint NOT NULL)' )

	if (@@error <> 0)
		begin
		RAISERROR(15001, 16, -1, @tempname)
		return (1)
		end

	set	 @tname = @tempname
	set @tempname = '##insert_' + @guidstr

	exec @retcode = dbo.sp_MSuniquetempname @tempname, @tempname out
	if (@@error <> 0)
		begin
		RAISERROR(15001, 16, -1, 'sp_MSuniquetempname')
		return (1)
		end

	exec @retcode = dbo.sp_MSmaketempinsertproc @tname, @tempname
	if  @@ERROR <>0 or @retcode<>0 return (1)

	select @pname = @tempname
	select @tname, @pname
	return (0)	
go
exec dbo.sp_MS_marksystemobject sp_MScreateretry 
go
grant exec on dbo.sp_MScreateretry to public

raiserror('Creating procedure sp_MSdropretry', 0,1)
GO

CREATE PROCEDURE sp_MSdropretry (@tname sysname, @pname sysname)
as
	declare @retcode int
	/*
	** To public
	*/
	
	exec ('drop table ' + @tname)
	if @@ERROR <> 0 return(1)
	exec ('drop procedure ' + @pname)
	if @@ERROR <> 0 return(1)
	return (0)	
go
exec dbo.sp_MS_marksystemobject sp_MSdropretry 
go
grant exec on dbo.sp_MSdropretry to public

raiserror('Creating procedure sp_MSchangearticleresolver', 0,1)
GO

CREATE PROCEDURE sp_MSchangearticleresolver (
@article_resolver 		nvarchar(255),
@resolver_clsid			nvarchar(40),
@artid					uniqueidentifier,
@resolver_info			sysname = NULL
)
as
	if (@resolver_clsid='') select @resolver_clsid = NULL
	UPDATE sysmergearticles
		SET article_resolver = @article_resolver, resolver_clsid = @resolver_clsid, resolver_info = @resolver_info
		WHERE artid = @artid
    if @@ERROR <> 0 
      	RETURN (1)
	return (0)     
go

exec dbo.sp_MS_marksystemobject sp_MSchangearticleresolver
go

-- ****************************************************
-- THIS COMMENTED CODE SECTION WILL BE DELETED SOON
-- sp_MSgetversion is now part of XPSTAR.DLL and 
-- will not be installed by REPL code

--raiserror('Creating sp_MSgetversion', 0,1)
--GO
if not exists (select * from sysobjects where name = 'sp_MSgetversion')
begin
	exec dbo.sp_addextendedproc 'sp_MSgetversion', 'xpstar.dll'
	exec dbo.sp_MS_marksystemobject sp_MSgetversion
	grant exec on dbo.sp_MSgetversion to public
end
go
-- ****************************************************

raiserror('Creating procedure sp_MSenumretries', 0,1)
GO

CREATE PROCEDURE sp_MSenumretries
	(@tname nvarchar(386),
	 @maxrows int,
	 @tablenick int,
	 @rowguid uniqueidentifier)
as
	declare @tnstring nvarchar(12)
	declare @rgstring nvarchar(38)
	declare @retcode int
	
	/*
	** Modify temp table, granted to public.
	*/
	
	if (@tablenick < 1)
		begin
		set rowcount @maxrows
		execute ('select tablenick, rowguidcol, errcode, errtext, type from ' + @tname + 
				 ' order by tablenick, rowguidcol')
		IF @@ERROR <>0 RETURN (1) 		 
		end
	else
		begin
		set rowcount @maxrows
		set @tnstring = convert(nchar, @tablenick)
		set @rgstring = '''' + convert(nchar(36), @rowguid) + ''''
		execute ('select tablenick, rowguidcol, errcode, errtext, type from ' + @tname + 
				' where (tablenick = ' + @tnstring + ' and  rowguidcol > ' + @rgstring + ') or
					 tablenick > ' + @tnstring + ' order by tablenick, rowguidcol' )
		if @@ERROR <> 0 RETURN (1)
		end
	return (0)	
go
exec dbo.sp_MS_marksystemobject sp_MSenumretries
go
grant exec on dbo.sp_MSenumretries to public

raiserror('Creating procedure sp_MSdeleteretry', 0,1)
GO

CREATE PROCEDURE sp_MSdeleteretry 
	(@temptable nvarchar(386),
	 @tablenick int,
	 @rowguid uniqueidentifier)
as
	declare @guidstr nvarchar(38)
	declare @nickstr nvarchar(12)
	declare @retcode int
	
	/*
	** Modify temp table, granted to public.
	*/
	
	set @nickstr = convert(nchar, @tablenick)
	set @guidstr = '''' + convert(nchar(36), @rowguid) + ''''

	execute ('delete from ' + @temptable + ' where tablenick = ' +
			  @nickstr + ' and rowguidcol = ' + @guidstr)
	IF @@ERROR <>0 RETURN (1)
	return (0)
go
exec dbo.sp_MS_marksystemobject sp_MSdeleteretry 
go
grant exec on dbo.sp_MSdeleteretry to public
go

raiserror('Creating procedure sp_MSdeletepushagent', 0,1)
GO

/*
** This procedure is obselete for dropping push agent at distribution database.
** If we were to recover, don't use server id as parameter for RPC into distributor.
** Use server name instead.
*/
CREATE PROCEDURE sp_MSdeletepushagent (
	@publisher		 	sysname,
	@publisher_db	 	sysname,
	@publication 		sysname,
	@subscriber	 		sysname,
	@subscriber_db	 	sysname
	) AS

declare @distributor 	sysname
declare @distribdb		sysname
declare @pubid			uniqueidentifier
declare @distproc		nvarchar(512)
declare @pub_srvid		smallint
declare @sub_srvid		smallint
declare @retcode		smallint

EXECUTE @retcode = dbo.sp_helpdistributor @distributor = @distributor OUTPUT, @distribdb   = @distribdb OUTPUT
		IF @@ERROR <> 0 or @retcode <> 0
			return (1)
		
select @pub_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@publisher)
select @sub_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@subscriber)
select @pubid=pubid from sysmergepublications where name=@publication and UPPER(publisher)=UPPER(@publisher) and publisher_db=@publisher_db

SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MSdrop_agent_entry'

EXEC @retcode = @distproc @pub_srvid, @publisher_db, @publication, @sub_srvid, @subscriber_db
	    IF @@ERROR <> 0 OR @retcode <> 0
			return (1)
return (0)
GO
exec dbo.sp_MS_marksystemobject sp_MSdeletepushagent
go
grant exec on dbo.sp_MSdeletepushagent to public
go

raiserror('Creating procedure sp_MSgetonerow', 0,1)
GO

CREATE PROCEDURE sp_MSgetonerow
	(@tablenick int,
	 @rowguid uniqueidentifier,
	 @pubid uniqueidentifier = NULL)
as
	declare @retcode 	smallint
	declare @procname	sysname

	/*
	** Check to see if current publication has permission
	*/
	exec @retcode=sp_MSreplcheck_connection @tablenick = @tablenick
	if @retcode<>0 or @@ERROR<>0 return (1)
	
	select @procname = select_proc from sysmergearticles where nickname = @tablenick and pubid=@pubid
	
	exec @retcode = @procname @type =1, @rowguid=@rowguid
	IF @@ERROR<>0 or @retcode<>0 RETURN (1)
	return (0)
go
exec dbo.sp_MS_marksystemobject sp_MSgetonerow
go
grant exec on dbo.sp_MSgetonerow to public
go

raiserror('Creating procedure sp_MSuplineageversion', 0,1)
GO

CREATE PROCEDURE sp_MSuplineageversion
	(@tablenick int,
	 @rowguid uniqueidentifier,
	 @version int)
as
	declare @replnick int
	declare @curversion int
	declare @lineage varbinary(255)
	declare @retcode int
	declare @colv varbinary(2048)
	declare @col_tracking int
	
	/*
	** Check to see if current publication has permission
	*/
	exec @retcode=sp_MSreplcheck_connection
		@tablenick = @tablenick
	if @retcode<>0 or @@ERROR<>0 return (1)
	
	exec dbo.sp_MSgetreplnick @nickname = @replnick out
	if (@@error <> 0) or @replnick IS NULL 
        begin
        RAISERROR (14055, 11, -1)
        RETURN(1)
        end                 
	if (@rowguid is null)
		begin
		RAISERROR(14043, 16, -1, '@rowguid')
		return (1)
		end
	if (@tablenick is null)
		begin
		RAISERROR(14043, 16, -1, '@tablenick')
		return (1)
		end

	select @col_tracking = column_tracking
			 from sysmergearticles where nickname = @tablenick

	begin transaction
	-- get lineage, locking row in MSmerge_contents
	select @lineage = lineage, @colv = colv1 from MSmerge_contents (UPDLOCK ROWLOCK index = 1) where tablenick = @tablenick and
			rowguid = @rowguid
	if (@lineage is null)
		begin
		commit
		RAISERROR(14043, 16, -1, '@rowguid')
		return (1)
		end
	set @curversion = 0
	while (@curversion < @version)
		begin
		exec master..xp_updatelineage @lineage output, @replnick, @curversion output
		if (@col_tracking = 0)
			set @colv = NULL
		else
			set @colv = { fn UPDATECOLVBM(@colv, @replnick, 0x01, 0x00) }
		end
		
	update MSmerge_contents set lineage = @lineage, colv1 = @colv where
		tablenick = @tablenick and rowguid = @rowguid
	commit
	return (0)
go
exec dbo.sp_MS_marksystemobject sp_MSuplineageversion
go
grant exec on dbo.sp_MSuplineageversion to public

raiserror('Creating procedure sp_MSgetlastrecgen', 0,1)
GO

CREATE PROCEDURE sp_MSgetlastrecgen
	(@repid uniqueidentifier)
as

	-- To public	
	if (@repid is null)
		begin
		RAISERROR(14043, 16, -1, '@repid')
		return (1)
		end
	if (not exists(select * from sysobjects where name = 'MSmerge_contents'))
		begin
		RAISERROR(20054 , 16, -1)
		return (1)
		end
	select recgen, recguid from MSmerge_replinfo where repid = @repid
	return (0)
go
exec dbo.sp_MS_marksystemobject sp_MSgetlastrecgen
go
grant exec on dbo.sp_MSgetlastrecgen to public

raiserror('Creating procedure sp_MSgetlastsentgen', 0,1)
GO

CREATE PROCEDURE sp_MSgetlastsentgen
	(@repid uniqueidentifier)
as
	-- To public
	if (@repid is null)
		begin
		RAISERROR(14043, 16, -1, '@repid')
		return (1)
		end
	if (not exists(select * from sysobjects where name = 'MSmerge_contents'))
		begin
		RAISERROR(20054 , 16, -1)
		return (1)
		end
	select sentgen, sentguid from MSmerge_replinfo where repid = @repid
	return (0)
go
exec dbo.sp_MS_marksystemobject sp_MSgetlastsentgen
go
grant exec on dbo.sp_MSgetlastsentgen to public
go

raiserror('Creating procedure sp_MSdummyupdate', 0,1)
GO


CREATE PROCEDURE sp_MSdummyupdate
	(@rowguid uniqueidentifier, @tablenick int, @metatype tinyint, @pubid uniqueidentifier = NULL, @uplineage tinyint = 1)
as
	declare @retcode int
	declare @lineage varbinary(255)
	declare @mynickname int
	declare @objid int
	declare @col_tracking int
	declare @ccols int
	declare @missing_count int
	declare @colv varbinary(2048)

	/*
	** Check to see if current publication has permission
	*/
	exec @retcode=sp_MSreplcheck_connection
		@tablenick = @tablenick
	if @retcode<>0 or @@ERROR<>0 return (1)
	
	/* Parameter checks */
	if (@rowguid is null)
		begin
		RAISERROR(14043, 16, -1, '@rowguid')
		return (1)
		end
	if (@tablenick is null)
		begin
		RAISERROR(14043, 16, -1, '@tablenick')
		return (1)
		end
	if (@metatype is null)
		begin
		RAISERROR(14043, 16, -1, '@metatype')
		return (1)
		end

	/* Check if we have a merge publication by whether system table is there */
	if (not exists(select * from sysobjects where name = 'MSmerge_contents'))
		begin
		RAISERROR(20054 , 16, -1)
		return (1)
		end

	exec dbo.sp_MSgetreplnick @nickname = @mynickname out
	if (@@error <> 0) or @mynickname IS NULL 
        begin
        RAISERROR (14055, 11, -1)
        RETURN(1)
        end                 

	if (@metatype = 0) or @@ERROR<>0
		begin
		declare @reason nvarchar(255)
		/* We don't have the row.  Putting in a system delete tombstone should cause a delete and
		** eventual convergence.  We are already logging the row as a conflict / error.
		*/
	    set @lineage = { fn UPDATELINEAGE(0x0, @mynickname) }
		select @reason = formatmessage(20562)
	
		insert into MSmerge_tombstone (rowguid, tablenick, type, lineage, generation, reason) 
			values (@rowguid, @tablenick, 6, @lineage, 0, @reason)
		
		end
	else if (@metatype = 1)
		begin
		/* Update systombstone */
		select @lineage = lineage from MSmerge_tombstone (UPDLOCK ROWLOCK index = 1) where tablenick = @tablenick and
			rowguid = @rowguid
		if (@uplineage = 1)
			begin
		    set @lineage = { fn UPDATELINEAGE(@lineage, @mynickname) }
			end
		update MSmerge_tombstone set generation = 0, lineage = @lineage where
			tablenick = @tablenick and rowguid = @rowguid
		end
	else if (@metatype = 2)
		begin
		/* Update MSmerge_contents */
		select @lineage = lineage, @colv = colv1 from MSmerge_contents (UPDLOCK ROWLOCK index = 1) where tablenick = @tablenick and
			rowguid = @rowguid
		if (@uplineage = 1)
			begin
		    set @lineage = { fn UPDATELINEAGE(@lineage, @mynickname) }
			if @pubid is NULL
				select @objid = objid, @col_tracking = column_tracking, @missing_count = missing_col_count
				 from sysmergearticles where nickname = @tablenick
			else
				select @objid = objid, @col_tracking = column_tracking, @missing_count = missing_col_count
				 	from sysmergearticles where nickname = @tablenick and pubid = @pubid
			if (@col_tracking = 0)
				set @colv = NULL
			else
				set @colv = { fn UPDATECOLVBM(@colv, @mynickname, 0x01, 0x00) }
			
			end
		update MSmerge_contents set generation = 0, lineage = @lineage, colv1 = @colv where
			tablenick = @tablenick and rowguid = @rowguid
		end
	else if (@metatype = 3)
		begin
		set @lineage = { fn UPDATELINEAGE(0x0, @mynickname) }
		if @pubid is NULL
			select @objid = objid, @col_tracking = column_tracking, @missing_count = missing_col_count
				 from sysmergearticles where nickname = @tablenick
		else
			select @objid = objid, @col_tracking = column_tracking, @missing_count = missing_col_count
				 from sysmergearticles where nickname = @tablenick and pubid = @pubid
		if (@col_tracking = 0)
			set @colv = NULL
		else
			begin
			select @ccols= count(*) from syscolumns where id = @objid
			set @ccols = @ccols + @missing_count
		    set @colv = { fn INITCOLVS(@ccols, @mynickname ) }
			end
		insert into MSmerge_contents (tablenick, rowguid, lineage, generation, colv1)
			values (@tablenick, @rowguid, @lineage, 0, @colv)

		end
	return (0)
go
exec dbo.sp_MS_marksystemobject sp_MSdummyupdate
go
grant exec on dbo.sp_MSdummyupdate to public
go
raiserror('Creating procedure sp_MSsetlastrecgen', 0,1)
GO

CREATE PROCEDURE sp_MSsetlastrecgen
	(@repid uniqueidentifier, @srcgen int, @srcguid uniqueidentifier)
as
	/*
	** Check to see if current publication has permission
	*/
	declare @retcode int
	exec @retcode=sp_MSreplcheck_connection
		@repid = @repid
	if @retcode<>0 or @@ERROR<>0 return (1)
	
	if (@repid is null)
		begin
		RAISERROR(14043, 16, -1, '@repid')
		return (1)
		end
	if (@srcgen is null)
		begin
		RAISERROR(14043, 16, -1, '@srcgen')
		return (1)
		end
	if (@srcguid is null)
		begin
		RAISERROR(14043, 16, -1, '@srcguid')
		return (1)
		end
	if (not exists(select * from sysobjects where name = 'MSmerge_contents'))
		begin
		RAISERROR(20054 , 16, -1)
		return (1)
		end
	update MSmerge_replinfo set recgen = @srcgen, recguid = @srcguid 
		where repid = @repid
	IF @@ERROR <>0 return (1) 
	return (0)
go
exec dbo.sp_MS_marksystemobject sp_MSsetlastrecgen
go
grant exec on dbo.sp_MSsetlastrecgen to public
go


dump tran master with no_log
go

raiserror('Creating procedure sp_MSsetlastsentgen', 0,1)
GO

CREATE PROCEDURE sp_MSsetlastsentgen
	(@repid uniqueidentifier, @srcgen int, @srcguid uniqueidentifier)
as
	/*
	** Check to see if current publication has permission
	*/
	declare @retcode int
	declare @pubid uniqueidentifier
	
	exec @retcode=sp_MSreplcheck_connection
		@repid = @repid
	if @retcode<>0 or @@ERROR<>0 return (1)
	
	if (@repid is null)
		begin
		RAISERROR(14043, 16, -1, '@repid')
		return (1)
		end
	if (@srcgen is null)
		begin
		RAISERROR(14043, 16, -1, '@srcgen')
		return (1)
		end
	if (@srcguid is null)
		begin
		RAISERROR(14043, 16, -1, '@srcguid')
		return (1)
		end
	if (not exists(select * from sysobjects where name = 'MSmerge_contents'))
		begin
		RAISERROR(20054 , 16, -1)
		return (1)
		end
	-- check for setting a sentgen which is obviously too high
	select @pubid = pubid from sysmergesubscriptions where subid = @repid
	if (exists (select * from MSmerge_genhistory where generation < @srcgen and
				guidlocal = '00000000-0000-0000-0000-000000000000' and
				(art_nick = 0 or art_nick is null or art_nick in
					(select nickname from sysmergearticles where
							pubid = @pubid) )))
		begin
		RAISERROR('Setting sentgen too high', 16, -1)
		return (1)
		end
	update MSmerge_replinfo  set sentgen= @srcgen, sentguid = @srcguid 
		where repid = @repid
	IF @@ERROR <>0 return (1)
	return (0)
go
exec dbo.sp_MS_marksystemobject sp_MSsetlastsentgen
go
grant exec on dbo.sp_MSsetlastsentgen to public
go

raiserror('Creating procedure sp_MScleanuptask', 0,1)
GO

CREATE PROCEDURE sp_MScleanuptask
	(@pubid uniqueidentifier)
as
	/*
	** Check to see if current publication has permission
	*/
	declare @retention int
	declare @retcode int
	exec @retcode=sp_MSreplcheck_connection
		@pubid = @pubid
	if @retcode<>0 or @@ERROR<>0 return (1)
	
	set nocount on
	if (@pubid is null)
		begin
		RAISERROR(14043, 16, -1, '@pubid')
		return (1)
		end
	if (not exists(select * from sysobjects where name = 'MSmerge_contents'))
		begin
		RAISERROR(20054 , 16, -1)
		return (1)
		end
	declare @cutoff datetime

	/*
	** Bypass task cleanup if retention value is 0; Null value has been converted to 0
	*/
	select @retention = retention from sysmergepublications where pubid = @pubid
	if @retention = 0 
		return (0)
	
	select @cutoff = dateadd(dd, -@retention, getdate())
	
	delete from MSmerge_genhistory where coldate < @cutoff
	declare @mingen int
	select @mingen = min(generation) from MSmerge_genhistory
	delete from MSmerge_tombstone where generation > 0 and generation < @mingen
	IF @@ERROR <>0 return (1)
	return (0)
go
exec dbo.sp_MS_marksystemobject sp_MScleanuptask
go
grant exec on dbo.sp_MScleanuptask to public

raiserror('Creating procedure sp_MSenumgenerations', 0,1)
GO

CREATE PROCEDURE sp_MSenumgenerations
	(@genstart int, @pubid uniqueidentifier)
as
	declare @retcode smallint
	
	/*
	** To public
	*/
	
	if (@genstart is null)
		begin
		RAISERROR(14043, 16, -1, '@genstart')
		return (1)
		end
	if (@pubid is null)
		begin
		RAISERROR(14043, 16, -1, '@pubid')
		return (1)
		end
	if (not exists(select * from sysobjects where name = 'MSmerge_contents'))
		begin
		RAISERROR(20054 , 16, -1)
		return (1)
		end
	exec @retcode = dbo.sp_MScleanuptask @pubid
	if @@ERROR<>0 or @retcode<>0 
		begin
			return (1)
		end

	select DISTINCT generation, guidsrc, art_nick, guidlocal from MSmerge_genhistory where generation >= @genstart and
			(art_nick = 0 or art_nick is NULL or art_nick in (select nickname from sysmergearticles where
							pubid = @pubid)) ORDER BY generation ASC
	IF @@ERROR <>0 return (1)
	return (0)
go
exec dbo.sp_MS_marksystemobject sp_MSenumgenerations
go
grant exec on dbo.sp_MSenumgenerations to public

raiserror('Creating procedure sp_MScheckexistsgeneration', 0,1)
GO

CREATE PROCEDURE sp_MScheckexistsgeneration
	(@genguid uniqueidentifier, @gen int output, @pubid uniqueidentifier)
as
	/*
	** Check input parameter
	*/
	if (@genguid is null)
		begin
			RAISERROR(14043, 16, -1, '@genguid')
			return (1)
		end

	/* delete from MSmerge_genhistory where guidsrc = @genguid and pubid = @pubid and guidlocal = '00000000-0000-0000-0000-000000000000' */

	select @gen = max(generation) from MSmerge_genhistory where guidsrc = @genguid and guidlocal <> '00000000-0000-0000-0000-000000000000'
			and ((pubid = @pubid) or (pubid is null))

	IF @@ERROR <>0 return (1)
	return (0)
go
exec dbo.sp_MS_marksystemobject sp_MScheckexistsgeneration
go
grant exec on dbo.sp_MScheckexistsgeneration to public

raiserror('Creating procedure sp_MSenumreplicas', 0,1)
GO

CREATE PROCEDURE sp_MSenumreplicas (@pubid uniqueidentifier)
as
	declare @active tinyint
	declare @deleted tinyint

	/*
	** To public
	*/

	select @active = 1
	select @deleted = 2
	if (not exists(select * from sysobjects where name = 'MSmerge_contents'))
		begin
		RAISERROR(20054 , 16, -1)
		return (1)
		end

	select subs.subid, replinfo.replnickname, subs.subscriber_type, subs.subscription_type, 
		subs.priority, replinfo.schemaversion, replinfo.schemaguid, subs.datasource_type, subs.datasource_path, servers.srvname,  
		subs.db_name, subs.status, subs.partnerid, subs.sync_type, subs.description, subs.pubid
		from sysmergesubscriptions subs, MSmerge_replinfo replinfo, master..sysservers servers
			where replinfo.repid = subs.subid 
				and subs.srvid = servers.srvid
				and (subs.status = @active or subs.status=@deleted)
				and subs.subscriber_type = 1
				and (subs.pubid is null or exists (select * from sysmergearticles art1, sysmergearticles art2
							where art1.pubid = subs.pubid and art2.pubid = @pubid and
									art1.artid = art2.artid))
				order by convert(binary, subs.subid)
	IF @@ERROR <>0 return (1) 
	return (0)
go
exec dbo.sp_MS_marksystemobject sp_MSenumreplicas 
go
grant exec on dbo.sp_MSenumreplicas to public

raiserror('Creating procedure sp_MSenumdeletesmetadata', 0,1)
GO

CREATE PROCEDURE sp_MSenumdeletesmetadata 
	(@pubid uniqueidentifier, @maxrows int, @genlist varchar(1000), @tablenick int, @rowguid uniqueidentifier)
as
	declare @tnstring nvarchar(12)
	declare @rgstring nvarchar(38)
	declare @pubidstr nvarchar(38)

	/*
	** To public.
	*/
	
	if (@genlist is null)
		begin
		RAISERROR(14043, 16, -1, '@genlist')
		return (1)
		end
	if (not exists(select * from sysobjects where name = 'MSmerge_contents'))
		begin
		RAISERROR(20054 , 16, -1)
		return (1)
		end
			
	set @pubidstr = '''' + convert(nchar(36), @pubid) + ''''
	if (@tablenick = 0)
		begin
			set rowcount @maxrows
			execute ('select tablenick, rowguid, generation, lineage, ts.type from MSmerge_tombstone ts, sysmergearticles sm
					where generation in (' + @genlist + ') 
					and sm.pubid = ' + @pubidstr + ' 
					and ts.tablenick = sm.nickname
					order by tablenick desc, rowguid asc' )
		end
	else
		begin
			set rowcount @maxrows
			set @tnstring = convert(nchar, @tablenick)
			set @rgstring = '''' + convert(nchar(36), @rowguid) + ''''
			execute ('select tablenick, rowguid, generation, lineage, ts.type from MSmerge_tombstone ts, sysmergearticles sm
					where generation in (' + @genlist + ') and 
						((tablenick = ' + @tnstring + ' and 
						rowguid > ' + @rgstring + ') or
						 tablenick < ' + @tnstring + ') 
						 and sm.pubid = ' + @pubidstr + ' 
						 and ts.tablenick = sm.nickname
						 order by tablenick desc, rowguid asc' )
		end
	IF @@ERROR <>0 
		begin
			return (1) 	
		end
	return (0)
go
exec dbo.sp_MS_marksystemobject sp_MSenumdeletesmetadata 
go
grant exec on dbo.sp_MSenumdeletesmetadata to public

raiserror('Creating procedure sp_MSenumpartialdeletes', 0,1)
GO

CREATE PROCEDURE sp_MSenumpartialdeletes
	(@maxrows int,
	 @tablenick int,
	 @rowguid uniqueidentifier,
	 @tablenotbelongs nvarchar(255))
as

	declare @tnstring nvarchar(12)
	declare @rgstring nvarchar(38)

	/*
	** To public.
	*/
	
	if (not exists(select * from sysobjects where name = 'MSmerge_contents'))
		begin
		RAISERROR(20054 , 16, -1)
		return (1)
		end

	if (@tablenick < 1)
		begin
			set rowcount @maxrows
			execute ('select tablenick, rowguid, COALESCE (generation, 0), lineage, type from ' + @tablenotbelongs + '
					order by tablenick desc, rowguid asc' )
		end
	else
		begin
			set rowcount @maxrows
			set @tnstring = convert(nchar, @tablenick)
			set @rgstring = '''' + convert(nchar(36), @rowguid) + ''''
			execute ('select tablenick, rowguid, COALESCE (generation, 0), lineage, type from ' + @tablenotbelongs + '
					where  ((tablenick = ' + @tnstring + ' and 
						rowguid > ' + @rgstring + ') or
						 tablenick < ' + @tnstring + ') 
						 order by tablenick desc, rowguid asc' )
		end
	IF @@ERROR <>0 
		begin
			return (1) 	
		end
	return (0)
go		
exec dbo.sp_MS_marksystemobject sp_MSenumpartialdeletes
go
grant exec on dbo.sp_MSenumpartialdeletes to public
go

raiserror('Creating procedure sp_MSenumchanges', 0,1)
GO

CREATE PROCEDURE sp_MSenumchanges
	(@maxrows int, @genlist varchar(1000), @tablenick int, @rowguid uniqueidentifier, @pubid uniqueidentifier = NULL)
as
	declare @tnstring	nvarchar(12)
	declare @rgstring 	nvarchar(38)
	declare @tablename 	sysname
	declare @retcode 	smallint
	declare @ownername	sysname
	declare @procname	nvarchar(258)

	/*
	** To public.
	*/
	if (@tablenick is null)
		begin
		RAISERROR(14043, 16, -1, '@tablenick')
		return (1)
		end
	exec @retcode = dbo.sp_MStablenamefromnick @tablenick, @tablename out, @pubid
	
	if @@ERROR<>0 or @retcode<>0  
	begin
		return (1)
	end
	if (@genlist is null)
		begin
		RAISERROR(14043, 16, -1, '@genlist')
		return (1)
		end
	if (not exists(select * from sysobjects where name = 'MSmerge_contents'))
		begin
		RAISERROR(20054 , 16, -1)
		return (1)
		end

	create table #cont (tablenick int NOT NULL, rowguid uniqueidentifier NOT NULL, generation int NULL, lineage varbinary(249) NULL	,colv1 varbinary(2048) NULL)
	
	set rowcount @maxrows
	set @tnstring = convert(nchar, @tablenick)
	set @rgstring = '''' + convert(nchar(36), @rowguid) + ''''

	execute ('insert into #cont
					select tablenick, rowguid, generation, lineage, colv1
	          			from MSmerge_contents where generation in (' + @genlist + ') and 
							tablenick = ' + @tnstring + ' and rowguid > ' + @rgstring +
							' order by rowguid' )		
	if @@ERROR <>0 
		begin
			return (1)
		end

	select @ownername = user_name(uid) from sysobjects where id = object_id(@tablename)
	select @procname = select_proc from sysmergearticles where nickname=@tablenick and pubid = @pubid
	exec @retcode = @procname @type=2
	IF @@ERROR<>0 or @retcode<>0 RETURN (1)

	drop table #cont
	return (0)
go
exec dbo.sp_MS_marksystemobject sp_MSenumchanges
go
grant exec on dbo.sp_MSenumchanges to public
go

raiserror('Creating procedure sp_MSenumpartialchanges', 0,1)
GO

CREATE PROCEDURE sp_MSenumpartialchanges
	(@maxrows int, @temp_cont sysname, @tablenick int, @rowguid uniqueidentifier, @pubid uniqueidentifier = NULL)
as
	declare @retcode 		smallint
	declare @tnstring 		nvarchar(12)
	declare @rgstring 		nvarchar(38)
	-- Owner qualified
	declare @tablename	 	nvarchar(266)
	declare @procname		nvarchar(258)
	declare @ownername		sysname
	/*
	** To public.
	*/
	
	if (@tablenick is null)
		begin
		RAISERROR(14043, 16, -1, '@tablenick')
		return (1)
		end
	exec @retcode = dbo.sp_MStablenamefromnick @tablenick, @tablename out, @pubid
		
	if @@ERROR<>0 or @retcode<>0 
		begin
			return (1)
		end	
	if (not exists(select * from sysobjects where name = 'MSmerge_contents'))
		begin
		RAISERROR(20054 , 16, -1)
		return (1)
		end
	set rowcount @maxrows
	set @tnstring = convert(nchar, @tablenick)
	set @rgstring = '''' + convert(nchar(36), @rowguid) + ''''

	create table #cont (tablenick int NOT NULL, rowguid uniqueidentifier NOT NULL, generation int NULL, lineage varbinary(249) NULL	,colv1 varbinary(2048) NULL)
	
	execute ('insert into #cont 
					select tablenick, rowguid, generation, lineage, colv from ' + @temp_cont + ' where
							tablenick = ' + @tnstring + ' and rowguid > ' + @rgstring
							+ ' order by rowguid')
	if @@ERROR<>0
		begin
			return (1)
		end						

/*	execute ('select c.tablenick, c.rowguid, c.generation, c.lineage, c.colv, t.* from ' +
				 @tablename + ' t, ' + @temp_cont + ' c where
					(c.tablenick = ' + @tnstring + ' and c.rowguid > ' + @rgstring + ' and
					  t.rowguidcol = c.rowguid)
					 order by c.rowguid' )
*/

	select @ownername = user_name(uid) from sysobjects where id = object_id(@tablename)	
	select @procname = select_proc from sysmergearticles where nickname=@tablenick and pubid = @pubid
	
	exec @retcode = @procname @type =3
	IF @@ERROR<>0 or @retcode<>0 RETURN (1)
	drop table #cont
	return (0)
go
exec dbo.sp_MS_marksystemobject sp_MSenumpartialchanges
go
grant exec on dbo.sp_MSenumpartialchanges to public


raiserror('Creating procedure sp_MSgetrowmetadata', 0,1)
GO

CREATE PROCEDURE sp_MSgetrowmetadata
	(@tablenick int,
	 @rowguid uniqueidentifier,
	 @generation int output,
	 @type  tinyint output,
	 @lineage varbinary(255) output,
	 @colv varbinary(2048) output,
	 @pubid uniqueidentifier = NULL)
as
	declare @retcode 		smallint
	declare @saverr 		int
	declare @rc 			int
	declare @procname 		nvarchar(258)
	declare @ownername		sysname
	
	/*
	** To public.
	*/
	
	
	if (@tablenick is null)
		begin
		RAISERROR(14043, 16, -1, '@tablenick')
		return (1)
		end
	if (@rowguid is null)
		begin
		RAISERROR(14043, 16, -1, '@rowguid')
		return (1)
		end
	if (not exists(select * from sysobjects where name = 'MSmerge_contents'))
		begin
		RAISERROR(20054 , 16, -1)
		return (1)
		end
	select @colv = null
	select @type = type, @generation = generation, @lineage = lineage from MSmerge_tombstone where
		tablenick = @tablenick and rowguid = @rowguid
	if (@lineage is null)
		begin
		select @type = 0
		select @generation = 0
		end
	if (@type = 0)
		begin
		declare @tablename nvarchar(266)
		exec @retcode = dbo.sp_MStablenamefromnick @tablenick, @tablename out, @pubid
		if @@ERROR<>0  
			begin
			return (1)
			end	

		select @ownername = user_name(uid) from sysobjects where id = object_id(@tablename)
		select @procname = select_proc from sysmergearticles where objid = object_id(@tablename) and pubid = @pubid
		exec @retcode = @procname @type =4, @rowguid=@rowguid
		
		select @saverr = @@ERROR, @rc = @@rowcount
		if @saverr <>0 return (1)
		if (@rc = 1)
			begin
			select @type = 3
			select @type = 2,  @generation = generation, @lineage = lineage, @colv = colv1 from MSmerge_contents
				where tablenick = @tablenick and rowguid = @rowguid
			end
		end
	return (0)
go
exec dbo.sp_MS_marksystemobject sp_MSgetrowmetadata
go
grant exec on dbo.sp_MSgetrowmetadata to public
go

raiserror('Creating procedure sp_MSsetrowmetadata', 0,1)
GO

CREATE PROCEDURE sp_MSsetrowmetadata
	(@tablenick int, @rowguid uniqueidentifier, @generation int,
	 @lineage varbinary(255), @colv varbinary(2048), @type tinyint)
as
	declare @reason nvarchar(255)
	declare @cvcurrent varbinary(2048)

	/*
	** Check to see if current publication has permission
	*/
	declare @retcode int
	exec @retcode=sp_MSreplcheck_connection
		@tablenick = @tablenick
	if @retcode<>0 or @@ERROR<>0 return (1)
	
	if (@tablenick is null)
		begin
		RAISERROR(14043, 16, -1, '@tablenick')
		return (1)
		end
	if (@rowguid is null)
		begin
		RAISERROR(14043, 16, -1, '@rowguid')
		return (1)
		end
	if (@generation is null)
		begin
		RAISERROR(14043, 16, -1, '@generation')
		return (1)
		end
	if (@lineage is null)
		begin
		RAISERROR(14043, 16, -1, '@lineage')
		return (1)
		end
	if (not exists(select * from sysobjects where name = 'MSmerge_contents'))
		begin
		RAISERROR(20054 , 16, -1)
		return (1)
		end
	if (@type = 1 or @type =  5 or @type = 6)
		begin
		if @type = 5
			begin
			set @reason = formatmessage(20563) -- Out of partial range
			set @lineage = 0x00
			end
		else if @type = 6
			begin
			set @reason = formatmessage(20564) -- Deleted by system
			end
		else
			begin
			set @reason = formatmessage(20562) -- Deleted by user
			end
		-- update or insert MSmerge_tombstone
		update MSmerge_tombstone set generation = @generation, lineage = @lineage, type = @type, reason = @reason
			where tablenick = @tablenick and rowguid = @rowguid
		if (@@rowcount = 0)
			insert into MSmerge_tombstone (rowguid, tablenick, type, generation, lineage, reason)
			 values (@rowguid, @tablenick, @type, @generation, @lineage, @reason)
		end
	else
		begin
		-- update or insert to MSmerge_contents
		select @cvcurrent = colv1 from MSmerge_contents where tablenick = @tablenick and rowguid = @rowguid
		if (datalength(@colv) < datalength(@cvcurrent))
			set @colv = @cvcurrent

		/* If filter values have changed, don't change generation */
		update MSmerge_contents set generation = @generation, lineage = @lineage, colv1 = @colv
			where tablenick = @tablenick and rowguid = @rowguid and
				(partchangegen is null or partchangegen <> generation) and
				(joinchangegen is null or joinchangegen <> generation)
		/* If filter values have changed, still update lineage and colv */
		if (@@rowcount = 0)
			update MSmerge_contents set lineage = @lineage, colv1 = @colv
			where tablenick = @tablenick and rowguid = @rowguid
		if (@@rowcount = 0)
			begin
			if not exists (select * from MSmerge_contents where tablenick = @tablenick and rowguid = @rowguid)
				insert into MSmerge_contents (rowguid, tablenick, generation, lineage, colv1)
				 values (@rowguid, @tablenick, @generation, @lineage, @colv)
			delete from MSmerge_tombstone where tablenick = @tablenick and rowguid = @rowguid
			end
		end
	IF @@ERROR<>0 return (1) 
	return (0)
go
exec dbo.sp_MS_marksystemobject sp_MSsetrowmetadata
go
grant exec on dbo.sp_MSsetrowmetadata to public
go

raiserror('Creating procedure sp_MSinsertgenhistory', 0,1)
GO

CREATE PROCEDURE sp_MSinsertgenhistory
	(@guidsrc uniqueidentifier,
	 @gen int output,
	 @pubid uniqueidentifier)
as
	declare @dt datetime
	/*
	** Check to see if current publication has permission
	*/
	declare @retcode int
	declare @saverr int
	
	exec @retcode=sp_MSreplcheck_connection
		@pubid = @pubid
	if @retcode<>0 or @@ERROR<>0 return (1)
	
	if (@guidsrc is null)
		begin
		RAISERROR(14043, 16, -1, '@guidsrc')
		return (1)
		end
	if (not exists(select * from sysobjects where name = 'MSmerge_contents'))
		begin
		RAISERROR(20054 , 16, -1)
		return (1)
		end
	/* Check for older in process generation */
	if exists (select * from MSmerge_genhistory where guidsrc = @guidsrc)
		begin
		select @gen = max(generation) from MSmerge_genhistory where guidsrc = @guidsrc
		return (0)
		end
		
	select @dt = getdate()
	begin tran
	insert into MSmerge_genhistory (guidsrc, pubid, guidlocal, generation, nicknames, coldate) 
		select  @guidsrc, @pubid, '00000000-0000-0000-0000-000000000000', COALESCE(1 + max(generation), 1),  0x0, @dt from MSmerge_genhistory (updlock)

	select @saverr = @@error
	
	select @gen = generation from MSmerge_genhistory where guidsrc = @guidsrc
	if @gen is null 
		begin
		update MSmerge_genhistory set generation = 1 where guidsrc = @guidsrc
		set @gen = 1
		end

	if @saverr = 0
		begin
		/* Now put in rows for other publications that share articles with this one */
		insert into MSmerge_genhistory (guidsrc, pubid, guidlocal, generation, nicknames, coldate) 
			select distinct @guidsrc, pubid, '00000000-0000-0000-0000-000000000000', @gen, 0x0, @dt
				from sysmergearticles where pubid <> @pubid and artid in
					(select artid from sysmergearticles where pubid = @pubid)
		select @saverr = @@error
		end
	commit tran
	
	if (@saverr <> 0)
		begin
		RAISERROR(15001, 16, -1, 'MSmerge_genhistory')
		return (1)
		end
	return (0)
go
exec dbo.sp_MS_marksystemobject sp_MSinsertgenhistory
go
grant exec on dbo.sp_MSinsertgenhistory to public

raiserror('Creating procedure sp_MSupdategenhistory', 0,1)
GO

CREATE PROCEDURE sp_MSupdategenhistory
	(@guidsrc uniqueidentifier, @pubid uniqueidentifier, @gen int, @art_nick int = NULL)
as
	declare @guidlocal uniqueidentifier
	declare @dt datetime
	
	/*
	** Check to see if current publication has permission
	*/
	declare @retcode int
	exec @retcode=sp_MSreplcheck_connection
		@pubid = @pubid
	if @retcode<>0 or @@ERROR<>0 return (1)
	
	if (@guidsrc is null)
		begin
		RAISERROR(14043, 16, -1, '@guidsrc')
		return (1)
		end
		
	if (not exists(select * from sysobjects where name = 'MSmerge_contents'))
		begin
		RAISERROR(20054 , 16, -1)
		return (1)
		end

	select @dt = getdate()
	if @art_nick = 0 set @art_nick = NULL
	
	set @guidlocal = newid()
	begin tran
	if exists (select * from MSmerge_genhistory where guidsrc = @guidsrc and generation < @gen)
		begin
		update MSmerge_contents set generation = @gen where generation in
			(select generation from MSmerge_genhistory where guidsrc = @guidsrc and generation < @gen)
		if @@ERROR <> 0 goto FAILURE
		update MSmerge_tombstone set generation = @gen where generation in
			(select generation from MSmerge_genhistory where guidsrc = @guidsrc and generation < @gen)
		if @@ERROR <> 0 goto FAILURE
		delete from MSmerge_genhistory where guidsrc = @guidsrc and generation < @gen
		if @@ERROR <> 0 goto FAILURE
		end
	if exists (select * from MSmerge_genhistory where guidsrc = @guidsrc)
		update MSmerge_genhistory set guidlocal = @guidlocal, art_nick = @art_nick where guidsrc = @guidsrc 
	else
		insert into MSmerge_genhistory (guidsrc, guidlocal, generation, art_nick, nicknames, coldate) values
			(@guidsrc, @guidlocal, @gen, @art_nick, 0x0, @dt)
	commit
	
	IF @@ERROR<>0 return (1)
	return (0)

FAILURE:
	/* UNDONE : This code is specific to 6.X nested transaction semantics */
	if @@TRANCOUNT = 1 
		ROLLBACK TRANSACTION 
	else
		COMMIT TRANSACTION
	
	RETURN 1
go
exec dbo.sp_MS_marksystemobject sp_MSupdategenhistory
go
grant exec on dbo.sp_MSupdategenhistory to public



raiserror('Creating procedure sp_MSenumschemachange', 0,1)
GO

CREATE PROCEDURE sp_MSenumschemachange(
	@pubid 			uniqueidentifier,
	@schemaversion 	int
	)
as

	/*
	** To public
	*/
	
	if (@schemaversion is null)
		begin
		RAISERROR(14043, 16, -1, '@schemaversion')
		return (1)
		end

	if (not exists(select * from sysobjects where name = 'MSmerge_contents'))
		begin
		RAISERROR(20054 , 16, -1)
		return (1)
		end
	select pubid, artid, schemaversion, schemaguid, schematype, schematext
		 from sysmergeschemachange where schemaversion > @schemaversion 
		 	and pubid = @pubid
				 order by schemaversion		 
	return (0)
go
exec dbo.sp_MS_marksystemobject sp_MSenumschemachange
go
grant exec on dbo.sp_MSenumschemachange to public
go


raiserror('Creating procedure sp_MSupdateschemachange', 0,1)
GO

CREATE PROCEDURE sp_MSupdateschemachange(
	@pubid			uniqueidentifier,
	@artid			uniqueidentifier = NULL, /* Can be NULL for directory commands */
	@schemaversion 	int,
	@schemaguid		uniqueidentifier,
	@schematype		int,
	@schematext		nvarchar(2000)
	)
as
	/*
	** Check to see if current publication has permission
	*/
	declare @retcode int
	exec @retcode=sp_MSreplcheck_connection
		@pubid = @pubid
	if @retcode<>0 or @@ERROR<>0 return (1)
	
	/* Parameter validation */
	if (@schemaversion is null)
		begin
		RAISERROR(14043, 16, -1, '@schemaversion')
		return (1)
		end

	if (not exists(select * from sysobjects where name = 'MSmerge_contents'))
		begin
		RAISERROR(20054 , 16, -1)
		return (1)
		end

	update sysmergeschemachange set schematext = @schematext, schematype = @schematype
		where pubid = @pubid and artid = @artid and schemaguid = @schemaguid
	if @@error <> 0		
		begin
			RAISERROR(20054 , 16, -1)
			return (1)
		end		
	return (0)
go
exec dbo.sp_MS_marksystemobject sp_MSupdateschemachange
go
grant exec on dbo.sp_MSupdateschemachange to public
go

raiserror('Creating procedure sp_MSadd_mergereplcommand', 0,1)
GO

/* Add the replication command to the database - Used by snapshot */
CREATE PROCEDURE sp_MSadd_mergereplcommand (
	@publication		sysname,
	@article			sysname = NULL,
	@schematype			int,
	@schematext			nvarchar(2000)
	) AS
	declare @schemaguid			uniqueidentifier
	declare @schemaversion 		int
	declare @retcode 			int
	declare @pubid				uniqueidentifier
	declare @artid				uniqueidentifier
	
	/*
	** Publish permission check
	*/
	exec @retcode=sp_MSreplcheck_publish
	if @retcode<>0 or @@ERROR<>0 return (1)
	
	if @publication IS NULL
        BEGIN
            RAISERROR (14003, 16, -1)
            RETURN (1)
        END

    select @pubid = pubid FROM sysmergepublications WHERE name = @publication and UPPER(publisher)=UPPER(@@SERVERNAME) and publisher_db=db_name()
    select @artid = artid FROM sysmergearticles WHERE name = @article
    /* 
    ** For certain system tables that are bcped out such as MSmerge_contents 
    ** and MSmerge_tombstone use the article name as sysobjects.name and get
    ** sysobjects.id as the artid
    */
	if (@artid IS NULL) AND (@schematype <> 7)
		begin
			declare @binguid binary(16)
			set @binguid = OBJECT_ID(@article)
			set @artid = convert(uniqueidentifier, @binguid)
		end

	if exists (select *	from sysmergeschemachange
			where pubid = @pubid 
			AND artid = @artid
			AND (schematype = @schematype or @schematype in (3,4) and schematype in (3,4)) )
		begin
			/* Select the existing schema guid */
			select @schemaversion = schemaversion, @schemaguid = schemaguid from sysmergeschemachange
				where pubid = @pubid 
				AND artid = @artid
				AND (schematype = @schematype or @schematype in (3,4) and schematype in (3,4))


			/* For directory commands, delete the previous directory before the update */
			if (@schematype = 7)
				begin
					declare @dir 			nvarchar(255)
					declare @local_path		nvarchar(255)
					declare @delcmd 		nvarchar(255)
					declare @distributor 	sysname
					declare @distproc 		nvarchar(255)

					/*
				    ** Get distribution server information for remote RPC call.
				    */
				    EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT
				    IF @@ERROR <> 0 OR  @retcode <> 0
				        BEGIN
				            RAISERROR (14071, 16, -1)
				            RETURN (1)
				        END

					select @dir = schematext from sysmergeschemachange 
						where schemaversion = @schemaversion 
					/* 
					** We have to convert UNC to drive, otherwise will get 'Access denied' error in xp_cmdshell
					*/
					EXEC @retcode = master.dbo.sp_MSunc_to_drive @unc_path = @dir, 
						@local_server = @distributor, @local_path = @local_path OUTPUT
					if @retcode<>0 or @@ERROR<>0 return (1)
				    /*
				    ** Delete publication directory in the distributor machine.
				    */
				    SET @distproc = RTRIM(@distributor) + '.master..xp_cmdshell'
				    SET @delcmd = 'rmdir /S /Q ' + @local_path

				    EXECUTE @distproc @delcmd, NO_OUTPUT						
				    if @@ERROR<>0 return (1)
				end

			/*
			** Update the schema change version
			*/
			exec @retcode = dbo.sp_MSupdateschemachange @pubid, @artid, @schemaversion, 
				@schemaguid, @schematype, @schematext
			if @@error <> 0	or @retcode <> 0
				begin
				RAISERROR(20054 , 16, -1)
				return (1)
			end
		end
	else		
		begin
			/* Insert the schema change */
			select @schemaversion = schemaversion from sysmergeschemachange
			if (@schemaversion is NULL)
				set @schemaversion = 1
			else
				select @schemaversion = 1 + max(schemaversion) from sysmergeschemachange
				
			/* generate a new schema guid */
			set @schemaguid = newid()
			exec @retcode = dbo.sp_MSinsertschemachange @pubid, @artid, @schemaversion, 
				@schemaguid, @schematype, @schematext
			if @@error <> 0	or @retcode <> 0
				begin
					RAISERROR(20054 , 16, -1)
					return (1)
				end
		end				
	return (0)
go
exec dbo.sp_MS_marksystemobject sp_MSadd_mergereplcommand 
go
grant exec on dbo.sp_MSadd_mergereplcommand to public
go

raiserror('Creating procedure sp_MSsetreplicainfo', 0,1)
GO

CREATE PROCEDURE sp_MSsetreplicainfo
	(@publisher			sysname,
	 @publisher_db		sysname,
	 @publication 		sysname,
	 @datasource_type	int = 0, 			/* 0 = SQL Server, 1 = DSN, 2 = Jet */
	 @server_name		sysname	= NULL, /* Server Name */
	 @db_name			sysname = NULL, /* Database Name */
	 @datasource_path	nvarchar(255) = NULL,/* Datasource path - JET MDB file path etc */
	 @nickname 	int = NULL,
	 @schemaversion int = NULL,
	 @subid	uniqueidentifier = NULL)
as
	declare 	@pubid 		uniqueidentifier
	declare 	@repid 		uniqueidentifier
	declare		@srvid		int
	declare		@retcode	int

	/*
	** NOTE -- WORKAROUND ODBC PROBLEM
	*/
	select @publisher_db = RTRIM(@publisher_db)
	select @db_name = RTRIM(@db_name)
	
	/*
	** Subscriber permission check
	*/
	if UPPER(@@servername) = UPPER(@publisher) and db_name() = @publisher_db
	begin
		exec @retcode=sp_MSreplcheck_connection
			@publication = @publication
		if @retcode<>0 or @@ERROR<>0 return (1)
	end
	else
	begin
		exec @retcode=sp_MSreplcheck_subscribe
		if @retcode<>0 or @@ERROR<>0 return (1)
	end
	
    /*
    ** Parameter Check:  @publication.
    ** Make sure that the publication exists.
    */
	if (@publication is null)
		begin
		RAISERROR(14043, 16, -1, '@publication')
		return (1)
		end

	if (@server_name is NULL)
		SET @server_name = @@SERVERNAME

	if (@db_name is NULL)
		set @db_name = db_name()
		
	SELECT @srvid = srvid FROM master..sysservers WHERE UPPER(srvname) = UPPER(@server_name)
   	IF @@ERROR <> 0 or @srvid IS NULL
       	BEGIN
			RAISERROR(20021, 16, -1)
     		RETURN (1)
		END

	select @pubid = pubid from sysmergepublications 
		where name = @publication and UPPER(publisher)=UPPER(@publisher) and publisher_db=@publisher_db
	if (@pubid is null)
		begin
            RAISERROR (20026, 11, -1, @publication)
			return (1)
		end

	if (@datasource_type = 0)
		begin
			SELECT @repid = subid FROM sysmergesubscriptions
				WHERE srvid = @srvid and db_name = @db_name and pubid = @pubid
		END
	ELSE
		BEGIN
			SELECT @repid = subid FROM sysmergesubscriptions
				WHERE datasource_path = @datasource_path and pubid = @pubid
		END
	if @repid is NULL
		begin
			RAISERROR(20021, 16, -1)
			return (1)
		end
	if @schemaversion is not null
		begin
			update MSmerge_replinfo set schemaversion = @schemaversion where repid = @repid
			if @@error <> 0		
				begin
					RAISERROR(20054 , 16, -1)
					return (1)
				end
		end
		
	if @subid is not null and @subid <> @repid
		begin
		/* Fix the repid for pull subscribers before we copy around global replica rows */
		update MSmerge_replinfo set repid = @subid where repid = @repid
		if @@error <> 0		
			begin
				RAISERROR(20054 , 16, -1)
				return (1)
			end
		update sysmergesubscriptions set subid = @subid where subid = @repid
		if @@error <> 0		
			begin
				RAISERROR(20054 , 16, -1)
				return (1)
			end
		end
		
	if @nickname IS NOT NULL		
		begin
			/* If this nickname isn't already assigned, reset it */
			if exists (select * from MSmerge_replinfo, sysmergesubscriptions
					where replnickname = @nickname and repid = subid and (srvid <> @srvid or
								db_name <> @db_name))
				return (0)
			update MSmerge_replinfo set replnickname = @nickname where repid = @repid
			if @@error <> 0		
				begin
					RAISERROR(20054 , 16, -1)
					return (1)
				end
		end			
	
	return (0)
go

exec dbo.sp_MS_marksystemobject sp_MSsetreplicainfo
go
grant exec on dbo.sp_MSsetreplicainfo to public
go

raiserror('Creating procedure sp_MSsetreplicastatus', 0,1)
GO

CREATE PROCEDURE sp_MSsetreplicastatus
	(@subid uniqueidentifier,
	 @status_value int
	 ) AS
	 
	/*
	** Check to see if current publication has permission
	*/
	declare @retcode int
	exec @retcode=sp_MSreplcheck_connection
		@repid = @subid
	if @retcode<>0 or @@ERROR<>0 return (1)
	
	 IF EXISTS (select subid from sysmergesubscriptions where subid=@subid)
		 update sysmergesubscriptions set status = @status_value
				WHERE subid=@subid
	if @@ERROR<>0 return (1)
	return (0)
go
exec dbo.sp_MS_marksystemobject sp_MSsetreplicastatus
go
grant exec on dbo.sp_MSsetreplicastatus to public
go

raiserror('Creating procedure sp_MScreateglobalreplica', 0,1)
GO

CREATE PROCEDURE sp_MScreateglobalreplica(
	@pubid	 				uniqueidentifier = NULL,			/* Publication ID */
	@subid	 				uniqueidentifier,  		/* Replica ID */
	@partnerid	 			uniqueidentifier,  		/* Partner's Replica ID */
	@replica_server			sysname, 		/* Replica server */
	@replica_db				sysname,  		/* Replica database */
	@replica_priority		real,  				/* Replica priority */
	@subscriber_type		tinyint = 0,		/* Replica's subscriber type - global, hub */
	@subscription_type 		int = 0,			/* Replica's subscription type - push or pull */
	@datasource_type 		int = 0,
	@datasource_path 		nvarchar(255) = NULL,
    @nickname				int,				/* Replica nickname */
    @status					int,				/* Replica status */
    @sync_type 				tinyint = 2	    	/* Replica sync type 1 = no sync, 2 = automatic */
	) AS
	
    SET NOCOUNT ON

    /*
    ** Declarations.
    */
	DECLARE @replica_srvid		int
    DECLARE @pubnickname		int
	declare @retcode			int
	/*
	** Check to see if current publication has permission
	*/
	exec @retcode=sp_MSreplcheck_connection
		@pubid = @pubid
	if @retcode<>0 or @@ERROR<>0 return (1)
	
	/*
	** NOTE
	*/
	select @replica_db = RTRIM(@replica_db)
    /* 
    ** Initializations
    */
	SELECT @replica_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@replica_server)
	if @replica_srvid is NULL
		begin
	    EXECUTE @retcode = dbo.sp_addserver @replica_server

        IF @@error <> 0 OR @retcode <> 0
            BEGIN
	            RAISERROR (14042, 16, -1)
                RETURN (1)
            END
		end            	
	SELECT @replica_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@replica_server)

	BEGIN TRAN MScreateglobalreplica	
		/*
		** Populate the local copy of sysmergesubscriptions
		*/
		if exists (select * from sysmergesubscriptions where subid = @subid and pubid = @pubid )
			begin
				update sysmergesubscriptions 
					SET	subid 				= @subid,
						datasource_type 	= @datasource_type,
						datasource_path 	= @datasource_path,
	    				srvid 				= @replica_srvid,
	    				db_name 			= @replica_db,
	    				pubid 				= @pubid,
	    				status 				= @status,
	    				subscriber_type 	= @subscriber_type,
		    			subscription_type 	= @subscription_type,
	    				priority 			= @replica_priority,
	    				sync_type			= @sync_type,
	    				login_name			= suser_sname(suser_sid())
				where subid = @subid and pubid = @pubid 	    				
		    IF @@ERROR <> 0
	        	goto FAILURE
			end
		else
			begin
				/* 
				** If attempting to tell the current replica about another replica whose pubid IS NULL
				** ignore the insert because current replica has more current info.
				*/
				if exists (select * from sysmergesubscriptions where subid = @subid and @pubid IS NULL)
					goto SUCCESS
					
				IF EXISTS (SELECT * FROM sysmergesubscriptions WHERE
					srvid = @replica_srvid AND db_name = @replica_db and pubid = @pubid)
					goto SUCCESS
					
				insert sysmergesubscriptions(subid, partnerid, datasource_type, datasource_path, srvid, db_name, pubid, status, subscriber_type, subscription_type, priority, sync_type, login_name)
					values (@subid, @partnerid, @datasource_type, @datasource_path, @replica_srvid, @replica_db, @pubid, @status, @subscriber_type, @subscription_type, @replica_priority, @sync_type, suser_sname(suser_sid()))
			    IF @@ERROR <> 0
		        	goto FAILURE
			end
		if not exists (select * from MSmerge_replinfo where repid = @subid )
			begin
	
				INSERT INTO  MSmerge_replinfo(repid, replnickname)	
					values (@subid, @nickname) 
			    IF @@ERROR <> 0
		        	goto FAILURE
			end
SUCCESS:			
	COMMIT TRAN			
	RETURN 0

FAILURE:
	/* UNDONE : This code is specific to 6.X nested transaction semantics */
	if @@TRANCOUNT = 1 
		ROLLBACK TRANSACTION MScreateglobalreplica
	else
		COMMIT TRANSACTION
	
	RAISERROR (14057, 16, -1)
	RETURN 1
go
exec dbo.sp_MS_marksystemobject sp_MScreateglobalreplica
go
grant exec on dbo.sp_MScreateglobalreplica to public
go

raiserror('Creating procedure sp_MSsetconflictscript', 0,1)
GO

/* Add the conflict script pointer to sysmergearticles - Used by snapshot */
CREATE PROCEDURE sp_MSsetconflictscript (
	@publication		sysname,
	@article			sysname,
	@conflict_script	nvarchar(255),
	@login				sysname =NULL,
	@password			sysname =NULL
	) AS

	declare @artid uniqueidentifier
	declare @pubid uniqueidentifier
    DECLARE @osql_cmd1 nvarchar (255)
    DECLARE @osql_cmd_full varchar (255)

	DECLARE @install_path varchar (255)
	declare @db_name		sysname
	
	/*
	** Check for publish permission.
	*/
	declare @retcode int
	exec @retcode=sp_MSreplcheck_publish
	if @retcode<>0 or @@ERROR<>0 return (1)
	
	select @pubid = pubid from sysmergepublications where name = @publication and UPPER(publisher)=UPPER(@@SERVERNAME) and publisher_db=db_name()
    if @pubid IS NULL
        BEGIN
			RAISERROR (20026, 16, -1, @publication)
    	    RETURN (1)
        END
	
	select @artid = artid FROM sysmergearticles WHERE name = @article	AND pubid = @pubid
    if @artid IS NULL
        BEGIN
			RAISERROR (20027, 16, -1, @article)
            RETURN (1)
        END

	update sysmergearticles set conflict_script = @conflict_script where artid = @artid
	if @@ERROR <> 0
		return (1)

	/* if there is already a conflict table, don't run script */
	if exists (select * from sysmergearticles where artid = @artid and OBJECT_ID(conflict_table) is null)
        BEGIN

		/* Run the script and create the conflict table */
		EXECUTE @retcode = master.dbo.xp_regread 'HKEY_LOCAL_MACHINE',
				  'SOFTWARE\Microsoft\MSSQLServer\Setup',
				  'SQLPath',
				@param = @install_path OUTPUT
		IF @@ERROR<> 0 OR @retcode <> 0 or @install_path is NULL or @install_path=''
			return (1)

		IF @login is NULL
			SELECT @osql_cmd1 = @install_path + '\binn\osql -E ' 
		ELSE
			-- cannot specify -S w/ -E for local execution, SID does not map due to nofix bug
			SELECT @osql_cmd1 = @install_path + '\binn\osql -U' + @login + ' -P' + 
				isnull(@password,'') + ' -S' + @@SERVERNAME + ' '
		select @osql_cmd1 = @osql_cmd1 + '-l30 -t30 '
		set @db_name = db_name()
		SELECT @osql_cmd_full = @osql_cmd1 + 
			' -d' + @db_name +  ' -b ' +
			' -i' + @conflict_script + 
			' -o' + @install_path + '\install\conflict.out' 

		EXEC @retcode = master..xp_cmdshell @osql_cmd_full
		IF @@ERROR<> 0 OR @retcode <> 0
			return (1)
		END
		
	/* Create the conflict insert proc */
	if exists (select * from sysmergearticles where artid = @artid and OBJECT_ID(ins_conflict_proc) is null)
		BEGIN
		exec dbo.sp_MSgetconflictinsertproc @artid = @artid, @output = 0
		IF @@ERROR<> 0 OR @retcode <> 0
			return (1)
		END
	return (0)
go
exec dbo.sp_MS_marksystemobject sp_MSsetconflictscript 
go
grant exec on dbo.sp_MSsetconflictscript to public
go

raiserror('Creating procedure sp_MSsetconflicttable', 0,1)
GO

/* Add the conflict table pointer to sysmergearticles - Used by reconciler */
CREATE PROCEDURE sp_MSsetconflicttable (
	@article			sysname,
	@conflict_table		nvarchar(255)
	) AS

	declare @artid uniqueidentifier

		
	select @artid = artid FROM sysmergearticles WHERE name = @article	
    if @artid IS NULL
        BEGIN
			RAISERROR (20027, 16, -1, @article)
            RETURN (1)
        END

	/*
	** Check to see if current publication has permission
	*/
	declare @retcode int
	exec @retcode=sp_MSreplcheck_connection
		@artid = @artid
	if @retcode<>0 or @@ERROR<>0 return (1)
	
	exec @retcode = dbo.sp_MS_marksystemobject @conflict_table
	if @retcode<>0 or @@ERROR<>0 return (1)
	
	update sysmergearticles set conflict_table = @conflict_table where artid = @artid
	if @@ERROR <> 0
		return (1)
	return (0)
go
exec dbo.sp_MS_marksystemobject sp_MSsetconflicttable 
go
grant exec on dbo.sp_MSsetconflicttable to public
go

raiserror('Creating procedure sp_MSmakeconflictinsertproc', 0,1)
GO


create procedure sp_MSmakeconflictinsertproc 
	(@tablename sysname, @ownername sysname, @procname sysname, @basetableid int)
as
declare @arglist	nvarchar(4000)
declare @collist 	nvarchar(4000)
declare @vallist 	nvarchar(4000)
declare @setpc		nvarchar(4000)
declare @qualname   nvarchar(266)
declare @argname	sysname
declare @wherepc	nvarchar(255)
declare @id int
declare @colname sysname
declare @typename sysname
declare @colid smallint
declare @status tinyint
declare @len smallint
declare @prec smallint
declare @scale int
declare @retcode smallint
	
if (@ownername is null or @ownername = ' ')
	set @qualname = QUOTENAME(@tablename)
else
	set @qualname = QUOTENAME(@ownername) + '.' + QUOTENAME(@tablename)

/*
** To check if specified object exists in current database
*/
set @id = object_id(@qualname)
	if @id is NULL return (1)

select @colid = min(colid) from syscolumns where id = @id and iscomputed <>1
select @colname = c.name, @status = c.status, @typename = t.name, @len = c.length,
	@prec = c.prec, @scale = c.scale
	from syscolumns c, systypes t
	where c.id = @id and c.colid = @colid and c.xusertype = t.xusertype

while (@colname is not null)
	begin
	if @typename='nvarchar' or @typename='nchar' -- a unit of nchar takes 2 bytes
		select @len = @len/2
	exec @retcode = dbo.sp_MSmaptype @typename out, @len, @prec, @scale
	if @@ERROR<>0 or @retcode<>0 return (1)
	select @argname = '@p' + rtrim(convert(nchar, @colid))

	-- based on colid, add text to appropriate pieces
	if (COLUMNPROPERTY( @basetableid, @colname, 'IsRowGuidCol') = 1)  
		set @wherepc = ' where rowguidcol = ' + @argname
	else if (@colname = 'origin_datasource')
		select @wherepc = @wherepc + ' and origin_datasource = ' + @argname
	set @colname = QUOTENAME(@colname)
	if @arglist is null
		begin
		set @arglist = @argname + ' ' + @typename
		set @collist = @colname
		set @vallist = @argname
		set @setpc = @colname + ' = ' + @argname
		end
	else 
		begin
		set @arglist = @arglist + ', ' + @argname + ' ' + @typename
		set @collist = @collist + ', ' + @colname
		set @vallist = @vallist + ', ' + @argname
		set @setpc = @setpc + ', ' + @colname + ' = ' + @argname
		end

	select @colid = min(colid) from syscolumns where id = @id and colid > @colid and iscomputed<>1
	set @colname = NULL
	select @colname = c.name, @status = c.status, @typename = t.name, @len = c.length,
		@prec = c.prec, @scale = c.scale
		from syscolumns c, systypes t
		where c.id = @id and c.colid = @colid and c.xusertype = t.xusertype
	end

-- now create the procedure
select @procname = QUOTENAME(@procname)
execute ('Create procedure dbo.' + @procname + ' ( ' +
	@arglist  + ') as
	update ' + @qualname + ' set ' + @setpc +
		@wherepc + '
	if (@@rowcount = 0)
	insert into ' + @qualname + ' (' + @collist + ') values (' + @vallist + ')')
IF @@ERROR <> 0
	begin
		return(1)
	end
execute ('grant execute on ' + @procname + ' to public')

exec dbo.sp_MS_marksystemobject  @procname
go
exec dbo.sp_MS_marksystemobject sp_MSmakeconflictinsertproc 
go

dump tran master with no_log
go


raiserror('Creating procedure sp_MSmaketempinsertproc', 0,1)
GO

-- Create temp sp, no security check needed
create procedure sp_MSmaketempinsertproc 
	(@tablename sysname, @procname sysname)
as
declare @arglist	nvarchar(4000)
declare @collist	nvarchar(4000)
declare @vallist 	nvarchar(4000)
declare @argname	sysname
declare @setpc		nvarchar(4000)
declare @wherepc	nvarchar(255)

declare @qualname nvarchar(266)
declare @id int

set @qualname = 'tempdb..' + @tablename
select @id = id from tempdb..sysobjects where name = @tablename

declare @colname sysname
declare @typename sysname
declare @colid smallint
declare @status tinyint
declare @len smallint
declare @prec smallint
declare @scale int
declare @retcode smallint

	
set @wherepc = ' where rowguid = @p2 '
select @colid = 1
select @colname = c.name, @status = c.status, @typename = t.name, @len = c.length,
	@prec = COLUMNPROPERTY(c.id, c.name, 'precision'), @scale = c.scale
	from tempdb..syscolumns c, systypes t
	where c.id = @id and c.colid = @colid and c.xusertype = t.xusertype and c.iscomputed<>1
while (@colname is not null)
	begin
	if @typename='nvarchar' or @typename='nchar' -- a unit of nchar takes 2 bytes
		select @len = @len/2
	exec @retcode = dbo.sp_MSmaptype @typename out, @len, @prec, @scale
	if @@error<>0 or @retcode<>0 return (1)

	set @argname = '@p' + rtrim(convert(nchar, @colid))
			
	if (@colid = 1)
		begin
		set @arglist = @argname + ' ' + @typename
		set @collist = @colname
		set @vallist = @argname
		set @setpc = @colname + ' = ' + @argname
		end
	else
		begin
		set @arglist = @arglist + ', ' + @argname + ' ' + @typename
		set @collist = @collist + ', ' + @colname
		set @vallist = @vallist + ', ' + @argname
		set @setpc = @setpc + ', ' + @colname + ' = ' + @argname
		end
	set @colid = @colid + 1
	set @colname = NULL
	select @colname = c.name, @status = c.status, @typename = t.name, @len = c.length,
		@prec = COLUMNPROPERTY(c.id, c.name, 'precision'), @scale = c.scale
		from tempdb..syscolumns c, systypes t
		where c.id = @id and c.colid = @colid and c.xusertype = t.xusertype and c.iscomputed<>1
	end
select @procname = QUOTENAME(@procname)
select @tablename = QUOTENAME(@tablename)
-- now create the procedure
execute ('Create procedure dbo.' + @procname + ' ( ' + @arglist + ') as
	update ' + @tablename + ' set ' + @setpc + @wherepc + '
	if (@@rowcount = 0)
	insert into ' + @tablename + ' (' + @collist + ') values (' + @vallist + ')')
if @@ERROR<>0
	begin
		return(1)
	end
go
exec dbo.sp_MS_marksystemobject sp_MSmaketempinsertproc 
go
grant exec on dbo.sp_MSmaketempinsertproc to public
go

raiserror('Creating procedure sp_MSgetconflictinsertproc', 0,1)
GO

/* Add the conflict table pointer to sysmergearticles - Used by reconciler */
CREATE PROCEDURE sp_MSgetconflictinsertproc (
	@artid 				uniqueidentifier,
	@output	int = 1
	) AS
	declare @conflict_table sysname
	declare @conflict_proc	sysname
	declare @owner 			sysname
	declare @object			sysname
	declare @retcode 		int
	declare	@basetableid	int
	
	-- PARSENAME VARS
	declare @UnqualName     nvarchar(258)  --rightmost name node
	declare @QualName1      nvarchar(258)  
	declare @QualName2      nvarchar(258)  
	-- END PARSENAME VARS

	declare @guidstr varchar(40)
	exec @retcode=sp_MSguidtostr @artid, @guidstr out
	if @retcode<>0 or @@ERROR<>0 return (1)
	
	/*
	** Check to see if current publication has permission
	*/
	exec @retcode=sp_MSreplcheck_connection
		@artid = @artid
	if @retcode<>0 or @@ERROR<>0 return (1)
	
	select @conflict_table = conflict_table, @conflict_proc = ins_conflict_proc, @basetableid = objid from
		sysmergearticles where artid = @artid

	if @@ERROR <> 0
		return (1)

	-- Create an index on the conflict table if it doesn't have one
	if (OBJECT_ID(@conflict_table) is not null) and
		not exists (select * from sysindexes where id = OBJECT_ID(@conflict_table) and keys is not null)
		begin
		declare @rgcol sysname
		declare @indname sysname
		declare @quotedname sysname
		
		select @rgcol = QUOTENAME(name) from syscolumns where id = @basetableid and
                ColumnProperty(id, name, 'isrowguidcol') = 1
        select @indname = 'uc_' + @conflict_table
        set @indname = QUOTENAME(@indname)
        set @quotedname = QUOTENAME(@conflict_table)
        exec ('Create unique clustered index ' + @indname + ' on ' + @quotedname +
        		' (' + @rgcol + ', origin_datasource)' )
        if @@error <> 0
        	return (1)
		end
	if ((OBJECT_ID(@conflict_proc) is null) and (OBJECT_ID(@conflict_table) is not null))
		begin

		select @UnqualName = PARSENAME(@conflict_table, 1)
	    select @QualName1 = PARSENAME(@conflict_table, 2)
	    if @UnqualName IS NULL
	         return 1

		-- fixup for variable length differences.  remove when vars expanded
		-- to new SQL SERVER 7.0 lengths

		select @owner =  @QualName1
		select @object = @UnqualName

		-- first set up the procedure name variable
		select @conflict_proc = 'sp_cft_' + @guidstr
		exec @retcode=sp_MSuniqueobjectname @conflict_proc , @conflict_proc output
		if @@ERROR <> 0 OR @retcode <> 0 
			return(1)
		exec @retcode=sp_MSmakeconflictinsertproc @UnqualName, @owner, @conflict_proc, @basetableid
		if @@ERROR <> 0 OR @retcode <> 0 
		begin
			RAISERROR('Failure when creating conflict insertion procedure', 16, -1)
			return(1)
		end
		update sysmergearticles set ins_conflict_proc = @conflict_proc where artid = @artid
	end

	if @output = 1
		select @conflict_table, @conflict_proc
	if @@ERROR <> 0
		return (1)
	return (0)
	
go
exec dbo.sp_MS_marksystemobject sp_MSgetconflictinsertproc 
go
grant exec on dbo.sp_MSgetconflictinsertproc to public
go

raiserror('Creating procedure sp_MSinsertdeleteconflict', 0,1)
GO

create PROCEDURE sp_MSinsertdeleteconflict(	 
	@tablenick 			int,
	@rowguid 			uniqueidentifier,
	@conflict_type		int,
	@reason_code		int,
	@reason_text		nvarchar(720),
	@origin_datasource	nvarchar(255),
	@pubid				uniqueidentifier)
as
	
	declare @retcode int
	/*
	** Check to see if current publication has permission
	*/
	exec @retcode=sp_MSreplcheck_connection
		@tablenick = @tablenick
	if @retcode<>0 or @@ERROR<>0 return (1)

	/* Parameter validation */
	if (@tablenick is null)
		begin
		RAISERROR(14043, 16, -1, '@tablenick')
		return (1)
		end
	if (@rowguid is null)
		begin
		RAISERROR(14043, 16, -1, '@rowguid')
		return (1)
		end

	if (not exists(select * from sysobjects where name = 'MSmerge_contents'))
		begin
		RAISERROR(20054 , 16, -1)
		return (1)
		end
	/* Don't insert a duplicate row */
	if (not exists (select * from MSmerge_delete_conflicts where tablenick = @tablenick and
		rowguid = @rowguid and origin_datasource = @origin_datasource))
		insert into MSmerge_delete_conflicts
			(tablenick, rowguid, conflict_type, reason_code, reason_text, origin_datasource, pubid) values
			(@tablenick, @rowguid, @conflict_type, @reason_code, @reason_text, @origin_datasource, @pubid)
	if @@ERROR <> 0 return (1)
	return (0)
go
exec dbo.sp_MS_marksystemobject sp_MSinsertdeleteconflict
go
grant exec on dbo.sp_MSinsertdeleteconflict to public
go

raiserror('Creating procedure sp_MScheckmetadatamatch', 0,1)
GO

create procedure sp_MScheckmetadatamatch
	(@metatype tinyint, 
	 @rowguid uniqueidentifier,
	 @tablenick int,
	 @lineage varbinary(255),
	 @match int output)
as
	
	select @match = 0
	if (@metatype = 3 and not exists 
		(select * from MSmerge_contents where tablenick = @tablenick and rowguid = @rowguid))
		select @match = 1
	else
		select @match = count(*) from MSmerge_contents (updlock) where
			tablenick = @tablenick and rowguid = @rowguid and lineage = @lineage
	return (0)
go
exec dbo.sp_MS_marksystemobject sp_MScheckmetadatamatch
go
grant exec on dbo.sp_MScheckmetadatamatch to public

raiserror('Creating procedure sp_MSdelrow', 0,1)
GO

create PROCEDURE sp_MSdelrow 
	(@rowguid 		uniqueidentifier,
	@tablenick 	int,
	@metadata_type tinyint, /* 0 - Missing, 1 - Tombstone, 2 - Contents, 3 - ContentsDeferred */
	@lineage_old varbinary(255),
	@generation int,
	@lineage_new varbinary(255),
	@pubid uniqueidentifier = NULL)

as
	set nocount on
	declare @success int 
	declare @tablename 		nvarchar(266)
	declare @rowguidstr		nvarchar(40)
	declare @match 			int
	declare @new_metatype	tinyint
	declare @retcode 		smallint
	declare @reason 		nvarchar(255)
	declare @procname 		nvarchar(266)
	declare @ownername		sysname
	
	/*
	** Check to see if current publication has permission
	*/
	exec @retcode=sp_MSreplcheck_connection
		@tablenick = @tablenick
	if @retcode<>0 or @@ERROR<>0 return (1)
	
	select @success = 0
	/* Parameter validation */
	if (@rowguid is null)
		begin
		RAISERROR(14043, 16, -1, '@rowguid')
		return (0)
		end
	if (@tablenick is null)
		begin
		RAISERROR(14043, 16, -1, '@tablenick')
		return (0)
		end
	exec @retcode = dbo.sp_MStablenamefromnick	@tablenick, @tablename output, @pubid
	if @@ERROR<>0 return (0)

	if (@tablename is null)
		begin
		RAISERROR(14043, 16, -1, '@tablename')
		return (0)
		end
	if (@lineage_new is null)
		begin
		RAISERROR(14043, 16, -1, '@lineage_new')
		return (0)
		end

	if (not exists(select * from sysobjects where name = 'MSmerge_contents'))
		begin
		RAISERROR(20054 , 16, -1)
		return (0)
		end
	set @rowguidstr = '''' + convert(nchar(36), @rowguid) + ''''

	-- Are we just changing the type of a tombstone?
	if (@metadata_type = 5 and exists (select * from MSmerge_tombstone where
		rowguid = @rowguid and tablenick = @tablenick))
		begin
		set @reason = formatmessage (20563) -- Moved out of partial range
		update MSmerge_tombstone set type = @metadata_type, reason = @reason where
			rowguid = @rowguid and tablenick = @tablenick
		set @success = 1
		return @success
		end

	-- Are we just changing the type of a tombstone?
	if (@metadata_type = 6 and exists (select * from MSmerge_tombstone where
		rowguid = @rowguid and tablenick = @tablenick))
		begin
		set @reason = formatmessage (20564) -- System deleted
		update MSmerge_tombstone set type = @metadata_type, reason = @reason where
			rowguid = @rowguid and tablenick = @tablenick
		set @success = 1
		return @success
		end

	-- begin transaction and lock row that we plan to delete
	begin transaction

		select @ownername = user_name(uid) from sysobjects where id = object_id(@tablename)
		select @procname = select_proc from sysmergearticles where objid = object_id(@tablename)  and pubid = @pubid
		exec @retcode = @procname @type =8, @rowguid=@rowguid

	/*	
		execute ('if not exists (select * from ' + @tablename + '(UPDLOCK) where 
				rowguidcol = ' + @rowguidstr + ')
			RAISERROR(20031 , 16, -1) ')
	*/
			
	select @success = 2
	if @metadata_type = 5
		begin
		set @match = 1
		set @new_metatype = 5
		end
	else if @metadata_type = 6
		begin
		set @match = 1
		set @new_metatype = 6
		end
	else
		begin
		exec @retcode=sp_MScheckmetadatamatch @metadata_type, @rowguid, @tablenick, @lineage_old, @match output

		set @new_metatype = 1
		end
	if (@match = 1)
		begin
		
	/*	execute ('delete from ' + @tablename + ' where rowguidcol = ' + @rowguidstr) */
		
		/*
		** select_proc makes a delete with @type = 5, despite its name. 
		*/
		exec @retcode = @procname @type =5, @rowguid=@rowguid
		
		if (@@error = 0 and @@rowcount = 1)
			begin
			exec dbo.sp_MSsetrowmetadata @tablenick, @rowguid, @generation, @lineage_new, NULL, @new_metatype
			select @success = 1
			end
		else
			select @success = 3
		end
	commit
	return (@success)
go
exec dbo.sp_MS_marksystemobject sp_MSdelrow 
go
grant exec on dbo.sp_MSdelrow to public
go

raiserror('Creating procedure sp_MSsetartprocs', 0,1)
GO

-- Call by snapshot
create procedure sp_MSsetartprocs
	(@publication		sysname,
	@article			sysname,
	@force_flag 		int = 0)
as
	declare @ownername sysname
	declare @objectname sysname
	declare @guidstr nvarchar(40)
	declare @pubidstr nvarchar(40)
	declare @ins_procname sysname
	declare @sel_procname sysname
	declare @upd_procname sysname
	declare @view_selprocname sysname
	declare @viewname sysname
	declare @artid uniqueidentifier
	declare @pubid uniqueidentifier
	declare @objid int
    declare @rgcol sysname
	declare @sync_objid int
	declare @retcode smallint
	declare @dbname sysname
	declare @command  nvarchar(1000)
	
	set nocount on

	/*
	** Check to see if current publication has permission
	*/
	exec @retcode=sp_MSreplcheck_publish
	if @retcode<>0 or @@ERROR<>0 return (1)
	
	-- figure out pubid and artid
	if @force_flag = 1
		begin
		-- don't qualify that must be publisher when we are forcing remake at subscribers
		select @pubid = pubid from sysmergepublications where name = @publication
		end
	else
		select @pubid = pubid from sysmergepublications where name = @publication and UPPER(publisher)=UPPER(@@SERVERNAME) and publisher_db=db_name()
    if @pubid IS NULL
        BEGIN
			RAISERROR (20026, 16, -1, @publication)
    	    RETURN (1)
        END
	
	select @artid = artid, @objid = objid, @sync_objid = sync_objid FROM sysmergearticles WHERE name = @article	AND pubid = @pubid
    if @artid IS NULL
        BEGIN
			RAISERROR (20027, 16, -1, @article)
            RETURN (1)
        END

	/* Drop the article procs if they preexist */
	exec @retcode = dbo.sp_MSdroparticleprocs @pubid, @artid
	if @@ERROR<>0 OR @retcode<>0 
		begin
			return (1)
		end
	
	-- get owner name, and table name
	select @objectname = name, @ownername = user_name(uid)	from sysobjects
		where id = @objid 

	-- make the insert and update proc names
	exec @retcode = dbo.sp_MSguidtostr @artid, @guidstr out
	if @@ERROR <>0 OR @retcode <>0 return (1)

	exec @retcode = dbo.sp_MSguidtostr @pubid, @pubidstr out
	if @@ERROR <>0 OR @retcode <>0 return (1)

	select @ins_procname = 'sp_ins_' + substring(@guidstr, 1, 16) + substring(@pubidstr, 1, 16)
	exec dbo.sp_MSuniqueobjectname @ins_procname, @ins_procname output
	if @@ERROR <>0 OR @retcode <>0 return (1)
	
	select @upd_procname = 'sp_upd_' + substring(@guidstr, 1, 16) + substring(@pubidstr, 1, 16)
	exec dbo.sp_MSuniqueobjectname @upd_procname, @upd_procname output
	if @@ERROR <>0 OR @retcode <>0 return (1)

	select @sel_procname = 'sp_sel_' + substring(@guidstr, 1, 16) + substring(@pubidstr, 1, 16)
	exec dbo.sp_MSuniqueobjectname @sel_procname, @sel_procname output
	if @@ERROR <>0 OR @retcode <>0 return (1)

	set @view_selprocname = 'sel_' + substring(@guidstr, 1, 16) + substring(@pubidstr, 1, 16)
    exec @retcode = dbo.sp_MSuniqueobjectname @view_selprocname , @view_selprocname output
    if @retcode <> 0 or @@ERROR <> 0 return (1) 

	-- create the procs
	set @dbname = db_name()
	set @command = 'sp_MSmakeinsertproc ' + QUOTENAME(@objectname) + ' , ' + QUOTENAME(@ownername) + ' , ' + @ins_procname  + ', [' + convert(nchar(36), @pubid) + ']'
	exec @retcode = master..xp_execresultset @command, @dbname
	if @@ERROR<>0 OR @retcode<>0 
		begin
			return (1)
		end


	exec @retcode = dbo.sp_MS_marksystemobject  @ins_procname 
	if @@ERROR<>0  return (1)
	exec ('grant exec on ' + @ins_procname + ' to public')

	set @command = 'sp_MSmakeupdateproc ' + QUOTENAME(@objectname) + ' , ' + QUOTENAME(@ownername) + ' , ' + @upd_procname
	exec @retcode = master..xp_execresultset @command, @dbname
	if @@ERROR<>0 OR @retcode<>0 
		begin
			return (1)
		end
	exec @retcode = dbo.sp_MS_marksystemobject  @upd_procname 
	if @@ERROR<>0 return (1)
	exec ('grant exec on ' + @upd_procname + ' to public')

	set @command = 'sp_MSmakeselectproc ' + QUOTENAME(@objectname) + ' , ' + QUOTENAME(@ownername)+ ' , ' + @sel_procname
	exec (@command)
	if @@ERROR<>0 
		begin
			return (1)
		end
	 exec @retcode = dbo.sp_MS_marksystemobject  @sel_procname 
	 if @@ERROR<>0 return (1)	
	 exec ('grant exec on ' + @sel_procname + ' to public')

	if @sync_objid <> 0 
		begin

   	 	select @ownername = user_name(uid), @viewname = name from sysobjects 
                where id = @sync_objid 
    	select @rgcol = QUOTENAME(name) from syscolumns where id = @objid and
                ColumnProperty(id, name, 'isrowguidcol') = 1
    	exec dbo.sp_MSmakeviewproc @viewname, @ownername, @view_selprocname, @rgcol
		if @@ERROR<>0 
			begin
			return (1)
			end
		end
	else
		set @view_selprocname = ''

	-- update articles to set the names
	update sysmergearticles set insert_proc = @ins_procname, update_proc = @upd_procname ,
		select_proc = @sel_procname, view_sel_proc = @view_selprocname
		where artid = @artid and pubid = @pubid
	IF @@ERROR<>0 return (1)
	return (0)
go
exec dbo.sp_MS_marksystemobject sp_MSsetartprocs
go
grant exec on dbo.sp_MSsetartprocs to public
go

raiserror('Creating procedure sp_MSmakesystableviews', 0,1)
GO

-- Used by snapshot
create procedure sp_MSmakesystableviews
	(@publication sysname)
AS
	declare @guidstr 		nvarchar(40)
	declare @pubid  		uniqueidentifier
	declare @contentsview 	sysname 
	declare @tombstoneview 	sysname
	declare @genhistoryview	sysname
	declare @filtersview	sysname
	declare @retcode smallint
	
	/*
	** Check to see if current publication has permission
	*/
	exec @retcode=sp_MSreplcheck_publish
	if @retcode<>0 or @@ERROR<>0 return (1)
	
	select @pubid = pubid from sysmergepublications where name = @publication and UPPER(publisher)=UPPER(@@SERVERNAME) and publisher_db=db_name()
	if @pubid is null
        BEGIN
			RAISERROR (20026, 16, -1, @publication)
            RETURN (1)
        END

	exec @retcode = dbo.sp_MSguidtostr @pubid, @guidstr out
	if @@ERROR<>0 OR @retcode<>0 return (1)
	select @contentsview = 'cont' + @guidstr
	select @tombstoneview = 'ts' + @guidstr
	select @genhistoryview = 'gh' + @guidstr
	select @filtersview = 'filt' + @guidstr

	set @guidstr = '''' + convert(nchar(36), @pubid) + ''''
	
	exec @retcode = dbo.sp_MSuniqueobjectname @tombstoneview, @tombstoneview out
	if @@ERROR<>0 OR @retcode<>0 return (1)
	exec @retcode = dbo.sp_MSuniqueobjectname @contentsview, @contentsview out
	if @@ERROR<>0 OR @retcode<>0 return (1)
	exec @retcode = dbo.sp_MSuniqueobjectname @genhistoryview, @genhistoryview out
	if @@ERROR<>0 OR @retcode<>0 return (1)
	exec @retcode = dbo.sp_MSuniqueobjectname @filtersview, @filtersview out
	if @@ERROR<>0 OR @retcode<>0 return (1)

	/* generate view for MSmerge_contents qualified by the pubid */
	exec ('create view ' + @tombstoneview + ' as select * from MSmerge_tombstone where
			tablenick in (select nickname from sysmergearticles where convert(nchar(36), pubid) = ' +
			@guidstr + ')')
	if @@ERROR <>0 
		begin
			return (1)
		end
	exec ('create view ' + @contentsview + ' as select * from MSmerge_contents where
			tablenick in (select nickname from sysmergearticles where convert(nchar(36), pubid) = ' +
			@guidstr + ')' )
	if @@ERROR <>0	
		begin
			return (1)
		end	

	exec ('create view ' + @genhistoryview + '(guidsrc, guidlocal, pubid, generation,
			art_nick, nicknames, coldate) as select DISTINCT guidsrc, guidlocal, CONVERT(uniqueidentifier, ' 
			+ @guidstr + '), generation, art_nick, nicknames, coldate  from MSmerge_genhistory
			where guidlocal <> ''00000000-0000-0000-0000-000000000000'' and (art_nick = 0 or art_nick is NULL or
					art_nick in (select nickname from sysmergearticles where convert(nchar(36), pubid) = ' +
			@guidstr + ')) ')
	if @@ERROR <>0
		begin
			return (1)
		end

	exec ('create view ' + @filtersview + ' as select * from sysmergesubsetfilters where convert(nchar(36), pubid) = ' +
			@guidstr)
	if @@ERROR <>0
		begin
			return (1)
		end

	set nocount on
	select @contentsview, @tombstoneview, @genhistoryview, @filtersview
	return (0)
go
exec dbo.sp_MS_marksystemobject sp_MSmakesystableviews
go
grant exec on dbo.sp_MSmakesystableviews to public
go

raiserror('Creating procedure sp_MSgetchangecount', 0,1)
GO

create procedure sp_MSgetchangecount(
	@startgen 	int,
 	@changes 	int output,
 	@updates 	int output,
 	@deletes 	int output) as
	
	
	select @deletes = count(*) from MSmerge_tombstone where generation = 0 or generation > @startgen
	select @updates = count(*) from MSmerge_contents where generation = 0 or generation > @startgen
	select @changes = @updates + @deletes
	return (0)		
go

exec dbo.sp_MS_marksystemobject sp_MSgetchangecount
go
grant exec on dbo.sp_MSgetchangecount to public

raiserror('Creating procedure sp_MSbelongs', 0,1)
GO

-- Modify temp table. No security check needed.
create procedure sp_MSbelongs
	@publisher		sysname,
	@publisher_db	sysname,
	@publication 	sysname,
	@tablenick		int,
	@rowguid		uniqueidentifier,
	@retval			int output,
	@nested 		int = 0
AS
	declare @artid uniqueidentifier
	declare @join_guid uniqueidentifier
	declare @last_joinid int
	declare @join_id int
	declare @join_nick int
	declare @probe_id int
	declare @last_probe int
	declare @join_nickstr nvarchar(10)
	declare @pubid uniqueidentifier
	declare @guidstring nvarchar(38)
	declare @subset_filter nvarchar(4000)
	declare @tablename nvarchar(266)
	declare @join_table nvarchar(266)
	declare @boolean nvarchar(4000)
	declare @retcode smallint
	
	select @pubid = pubid from sysmergepublications where name = @publication and UPPER(publisher)=UPPER(@publisher) and publisher_db=@publisher_db

	/* Check for case of all rows  - do I trust subset_type ? */
	select @boolean = subset_filterclause, @artid = artid from sysmergearticles where
		pubid = @pubid and nickname = @tablenick

	if ((@boolean is null or @boolean = ' ') and not exists
		(select * from sysmergesubsetfilters where art_nickname = @tablenick))
		begin
		set @retval = 0
		return
		end
	if @nested = 0
		begin
		create table #found (flag int NOT NULL)
		insert into #found values (0)
		create table #probe (probe_id int identity NOT NULL, tablenick int NOT NULL, 
				rowguid uniqueidentifier ROWGUIDCOL default newid() not null, tested int NOT NULL)
		set @last_probe = 0
		end
	else
		begin
		select @last_probe = max(probe_id) from #probe
		end

	/* pubid is already available */
	
	exec @retcode = dbo.sp_MStablenamefromnick @tablenick, @tablename out, @pubid

	if  @@ERROR<>0 or @retcode<>0 return (1) 
	set @guidstring = '''' + convert(nchar(36), @rowguid) + ''''

	/* If there is boolean filter, check for it being satisfied */
	if @boolean is not null and @boolean <> ' '
		begin
		exec ('if exists (select * from ' + @tablename + ' where rowguidcol = ' +
			@guidstring + ' and (' + @boolean + ')) update #found set flag = 1')
		if @@ERROR<>0 return (1)
		select @retval = flag from #found
		if @retval = 1 goto EndLabel
		end
	
	/* Loop over join filters, populating #probe */
	select @join_id = min(join_filterid) from sysmergesubsetfilters where pubid = @pubid and art_nickname = @tablenick
	while @join_id is not null
		begin
		select @boolean = join_filterclause, @join_nick = join_nickname from sysmergesubsetfilters where pubid = @pubid and join_filterid = @join_id
		exec @retcode = dbo.sp_MStablenamefromnick @join_nick, @join_table out, @pubid
		if @@ERROR<>0 or @retcode<>0 return (1)
		set @join_nickstr = convert(nchar(10), @join_nick)

		/* execute a query to put these into the #probe table */
		exec ('insert into #probe (tablenick, rowguid, tested) select distinct ' + @join_nickstr + 
			', ' + @join_table + '.rowguidcol, 0 from ' + @tablename + ', ' + @join_table + '   
			where ' + @tablename + '.rowguidcol = ' + @guidstring + ' and (' + @boolean + ')
			and not exists (select * from #probe where tablenick = ' + @join_nickstr + 
			' and rowguidcol = ' + @join_table + '.rowguidcol) ' )
		if @@ERROR<>0 
			begin
				return (1)
			end	

		/* get to next join filter and repeat */
		set @last_joinid = @join_id
		select @join_id = min(join_filterid) from sysmergesubsetfilters where pubid = @pubid and art_nickname = @tablenick and join_filterid > @last_joinid
		end
	/* Loop over probe, making recursive call */
	select @probe_id = min(probe_id) from #probe where probe_id > @last_probe and tested = 0
	while @probe_id is not null
		begin
		select @join_nick = tablenick, @join_guid = rowguidcol from #probe where probe_id = @probe_id
		set @last_probe = @probe_id

		/* update tested flag on this row so we don't try it again while recursing */
		update #probe set tested = 1 where probe_id = @probe_id
	
		/* Make recursive call. If it belongs, we are done. */
		exec @retcode = dbo.sp_MSbelongs @publisher, @publisher_db, @publication, @join_nick, @join_guid, @retval output, 1
		if @@ERROR<>0 OR @retcode<>0
			begin
				return (1)
			end

		if @retval = 1 goto EndLabel
		/* get next probe_id and repeat */
		select @probe_id = min(probe_id) from #probe where probe_id > @last_probe and tested = 0
		end

	/* All Done, delete temps if not nested */
EndLabel:
	if @nested = 0
		begin
		drop table #found
		drop table #probe
		end
	return

go

exec dbo.sp_MS_marksystemobject sp_MSbelongs
go
grant exec on dbo.sp_MSbelongs to public
go

raiserror('Creating procedure sp_MSexpandbelongs', 0,1)
GO

-- Modify temp table. No security check needed.
create procedure sp_MSexpandbelongs
	@pubid 		uniqueidentifier
AS
	declare @filterid int
	declare @retval			int
	declare @expand_proc	sysname
	
	/* We iterate over the join filters */
	select @filterid = min(flag) from #belong
	select @filterid = min(join_filterid) from sysmergesubsetfilters where pubid = @pubid and join_filterid > @filterid and
			exists (select * from #belong where tablenick = join_nickname and flag < join_filterid)
	while (@filterid is not null)
		begin
		select @expand_proc = expand_proc from sysmergesubsetfilters where pubid = @pubid and
				join_filterid = @filterid
		exec @retval = @expand_proc @belong = 1
		if @retval <> 0 return (1)
		select @filterid = min(join_filterid) from sysmergesubsetfilters where pubid = @pubid and join_filterid > @filterid and
			exists (select * from #belong where tablenick = join_nickname and flag < join_filterid)
		end
		
	return (0)
go
exec dbo.sp_MS_marksystemobject sp_MSexpandbelongs
go
grant exec on dbo.sp_MSexpandbelongs to public
go

raiserror('Creating procedure sp_MSexpandnotbelongs', 0,1)
GO

-- Modify temp table. No security check needed.
create procedure sp_MSexpandnotbelongs
	@pubid 		uniqueidentifier
AS
	declare @filterid 		int
	declare @retval			int
	declare @expand_proc	sysname
	
	/* We iterate over the join filters */
	select @filterid = min(flag) from #notbelong
	select @filterid = min(join_filterid) from sysmergesubsetfilters where pubid = @pubid and join_filterid > @filterid and
			exists (select * from #notbelong where tablenick = join_nickname and flag < join_filterid)
	while (@filterid is not null)
		begin
		select @expand_proc = expand_proc from sysmergesubsetfilters where pubid = @pubid and
				join_filterid = @filterid
		exec @retval = @expand_proc @belong = 0
		if @retval <> 0 return (1)
		select @filterid = min(join_filterid) from sysmergesubsetfilters where pubid = @pubid and join_filterid > @filterid and
			exists (select * from #notbelong where tablenick = join_nickname and flag < join_filterid)
		end


go

exec dbo.sp_MS_marksystemobject sp_MSexpandnotbelongs
go
grant exec on dbo.sp_MSexpandnotbelongs to public
go

raiserror('Creating procedure sp_MSsetupbelongs', 0,1)
GO

-- Modify temp table. No security check needed.
create procedure sp_MSsetupbelongs
	@publisher			sysname,
	@publisher_db		sysname,
	@publication 		sysname,
	@genlist	 		varchar(1000),
	@commongen			int,
	@subissql			int

AS
	declare @pubid uniqueidentifier
	declare @temp_id int
	declare @retval int
	declare @tablenick int
	declare @tnstr nvarchar(12)
	declare @rowguid uniqueidentifier
	declare @rowguidstr nvarchar(40)
	declare @belongsname sysname
	declare @notbelongsname sysname
	declare @artnick	int
	declare @artnickstr nvarchar(10)
	declare @artviewobjid int
	declare @procname sysname

	declare @artbaseobjid int
	declare @artviewname sysname
	declare @artviewowner sysname

	declare @commongenstr nvarchar(12)
	declare @partchangegen int
	declare @joinchangegen int
	declare @rgcol sysname
	declare @maxfilterid int
	declare @view_type int
	declare @temp_view int
	declare @retcode smallint
	
	/*
	** To public
	*/
	
	set @temp_view = 2

	select @pubid = pubid from sysmergepublications where name = @publication and UPPER(publisher)=UPPER(@publisher) and publisher_db=@publisher_db
	set @commongenstr = convert(nchar(12), @commongen)

	/* Set up the ##belong and ##notbelong tables; return names as rowset */
	/* step 1 make temptable names, create tables */
	set @rowguid = newid()
	exec @retcode=sp_MSguidtostr @rowguid, @rowguidstr out
	if @retcode<>0 or @@ERROR<>0 return (1)
	
	set @belongsname = '##belong' + @rowguidstr
	exec @retcode = dbo.sp_MSuniquetempname @belongsname, @belongsname out
	IF @@ERROR<>0 OR @retcode<>0 return (1)
	create table #belong (tablenick int NOT NULL, rowguid uniqueidentifier NOT NULL, flag int NOT NULL,
		partchangegen int null, joinchangegen int null)
	create index #indbelong on #belong (rowguid)
	
	exec ('create table ' + @belongsname + ' (tablenick int NOT NULL, rowguid uniqueidentifier NOT NULL,
		generation int NULL, lineage varbinary(255) NULL, colv varbinary(2048) NULL) ')
	if @@ERROR <>0 return (1)
	create table #notbelong (bookmark int identity NOT NULL, tablenick int NOT NULL, rowguid uniqueidentifier NOT NULL,
		flag int NOT NULL, partchangegen int null, joinchangegen int null)
	create index #indnbelong on #notbelong (tablenick, rowguid)

	set @notbelongsname = '##notbelong' + @rowguidstr
	exec @retcode = dbo.sp_MSuniquetempname @notbelongsname, @notbelongsname out
	IF @@ERROR<>0 OR @retcode<>0 return (1)
	exec ('create table ' + @notbelongsname + ' (tablenick int NOT NULL, rowguid uniqueidentifier NOT NULL,
		generation int NULL, lineage varbinary(255) NULL, type tinyint NOT NULL) ')
	if @@ERROR <>0 return (1)
	create table #temp_cont (temp_id int identity NOT NULL, tablenick int NOT NULL, rowguid uniqueidentifier NOT NULL,
			partchangegen int null, joinchangegen int null)
	
	/* step 2 setup pass through MSmerge_contents */
	/* article with permanent views can be handled with bulk inserts */
	set @artnick = 0
	set rowcount 0
	
	/* Get first article, go into loop */
	select @artnick = min(nickname) from sysmergearticles where pubid = @pubid and
		 nickname > @artnick

	/* Put all relevant changes in #notbelong to start.  It simplifies the queries greatly,
	** and we can delete out the rows from #belong efficiently at the end.
	*/
	exec ('insert into #notbelong (tablenick, rowguid, flag, partchangegen, joinchangegen)
				select tablenick, c.rowguid, 0, partchangegen, joinchangegen
					from MSmerge_contents c where  generation in (' + @genlist + ')')
	if @@ERROR <>0 return (1)		


	while (@artnick is not null)
		begin
		set @artnickstr = convert(nchar(10), @artnick)
		select @artviewobjid = sync_objid, @artbaseobjid = objid, @view_type = view_type,
			@procname = view_sel_proc from sysmergearticles where
			pubid = @pubid and nickname = @artnick
		/* Get name of rowguidcol. Aliasing doesn't work through a view. */
		select @rgcol = name from syscolumns where id = @artbaseobjid and ColumnProperty(@artbaseobjid, name, 'isrowguidcol') = 1

		/* UNDONE get view type from sysmergearticle to see if permanent view to use */
		set @artviewname = NULL
		if @view_type <> @temp_view
			select @artviewname = name, @artviewowner = user_name(uid) from sysobjects where
				id = @artviewobjid
		if (@procname is not null)
			begin
			exec @retcode = @procname @artnick
			if @@ERROR <>0 or @retcode <> 0 return (1)
			end
		else
			begin
			delete from #temp_cont
			exec ('insert into #temp_cont (tablenick, rowguid, partchangegen, joinchangegen) 
						select tablenick, rowguid, partchangegen, joinchangegen from MSmerge_contents where
						tablenick  = ' + @artnickstr + ' and generation in (' +
					@genlist + ') ')
			if @@ERROR <>0 return (1)		
			set @temp_id = 0
			select @temp_id = min(temp_id) from #temp_cont where temp_id > @temp_id
			while (@temp_id is not null)
				begin
				select @tablenick = tablenick, @rowguid = rowguid,
				   @partchangegen = partchangegen, @joinchangegen = joinchangegen 
					from #temp_cont where temp_id = @temp_id
				set @rowguidstr = '''' + convert(nchar(36), @rowguid) + ''''
				exec @retcode = dbo.sp_MSbelongs @publisher, @publisher_db,	@publication, @tablenick, @rowguid, @retval	output, 0
				if @@ERROR<>0 OR @retcode <>0
				if @retval = 1
					begin
					insert into #belong (tablenick, rowguid, flag, partchangegen, joinchangegen) values
							(@artnick, @rowguid, 0, @partchangegen, @joinchangegen)
					if @@ERROR <>0 return (1)	
					end

				else
					begin
					/* Checking partchangegen will tell us if we need to insert this */
					if @partchangegen > @commongen
						insert into #notbelong (tablenick, rowguid, flag) values
							(@artnick, @rowguid, 0)
					end

				select @temp_id = min(temp_id) from #temp_cont where temp_id > @temp_id
				end

			end
		/* Move on to next article, repeat while loop */
		select @artnick = min(nickname) from sysmergearticles where pubid = @pubid and
			 nickname > @artnick
		end

	drop table #temp_cont 

	/* Clean up #notbelong by using #belong - we inserted with out really checking */
	delete from #notbelong where rowguid in (select rowguid from #belong)
	delete from #notbelong where partchangegen < @commongen
	
	/* Optimization: If joinchangegen and partchange are both null or < common gen,
	** it is not necessary to expand #belong for that particular row.
	*/
	
	select @maxfilterid = max(join_filterid) from sysmergesubsetfilters

	if @maxfilterid is not null
		begin
		update #belong set flag = @maxfilterid where (joinchangegen <= @commongen and
			(partchangegen is null or partchangegen <= @commongen))

		/* Expand the #belong temptable */
		exec @retcode = dbo.sp_MSexpandbelongs @pubid
		if @@ERROR<>0 OR @retcode<>0 return (1)
		end
		
	/* transfer rows from local temp to global temp */
	exec ('insert into ' + @belongsname + ' (tablenick, rowguid, generation, lineage, colv) 
		select b.tablenick, b.rowguid, c.generation, c.lineage, c.colv1 from
		#belong b left outer join MSmerge_contents c  
		on  c.tablenick = b.tablenick and c.rowguid = b.rowguid ')
	if @@ERROR <>0 return (1)	

	/* If subscriber is sql server, we don't have to expand belongs */
	if @subissql = 0
		begin
		/* Expand the #notbelong temptable */
		exec dbo.sp_MSexpandnotbelongs @pubid
		end

	/* transfer rows from local temp to global temp */
	exec ('insert into ' + @notbelongsname + ' (tablenick, rowguid, generation, lineage, type) 
		select b.tablenick, b.rowguid, c.generation, c.lineage, 5 from
		#notbelong b left outer join MSmerge_contents c  
		on  c.tablenick = b.tablenick and c.rowguid = b.rowguid ')
	if @@ERROR <>0 return (1)	
	drop table #notbelong

	/* Add tombstones to ##notbelong */
	exec ('insert into ' + @notbelongsname + ' (tablenick, rowguid, generation, lineage, type) 
		select  tablenick, rowguid,  generation,  lineage, type from
		MSmerge_tombstone where generation in (' + @genlist + ')')
	if @@ERROR <>0 return (1)
	if not exists (select * from #belong)
		select @belongsname, @notbelongsname, -1
	else
		select distinct @belongsname, @notbelongsname, tablenick from #belong
	drop table #belong
	return (0)
go

exec dbo.sp_MS_marksystemobject sp_MSsetupbelongs
go
grant exec on dbo.sp_MSsetupbelongs to public
go

raiserror('Creating procedure sp_MSaddinitialarticle', 0,1)
GO

-- Called at the subscriber
CREATE PROCEDURE sp_MSaddinitialarticle(
	@article				sysname, 		/* Name of the article */
	@artid	 				uniqueidentifier,			/* Article ID */
	@pubid	 				uniqueidentifier,			/* Publication ID */
	@nickname				int,				/* Article nickname */
	@column_tracking		int,				/* Does the article have column tracking ? */
	@status					int,				/* Status of the article */
	@pre_creation_command	int = 0, 			/* Precreate command of the article */
	@resolver_clsid			nvarchar(255) = NULL,/* Resolver module for the article */
	@insert_proc			nvarchar(255) = NULL,/* Insert sp for article */
	@update_proc			nvarchar(255) = NULL,/* Update sp for article */
	@select_proc			nvarchar(255) = NULL, /* Select SP for this article */
	@destination_object		sysname,			/* Destination object name */
	@missing_count			int			 = NULL,	
	@missing_cols			varbinary(32) = NULL,
	@article_resolver		nvarchar(255) = NULL,
	@resolver_info			nvarchar(255) = NULL,
	@filter_clause			nvarchar(2000) = NULL
	) AS
	
    SET NOCOUNT ON

	declare @objid int
	declare @retcode int
	/*
	** Check for subscribing permission
	*/
	exec @retcode=sp_MSreplcheck_subscribe
	if @retcode<>0 or @@ERROR<>0 return (1)
	
	if (@artid is NULL)
        BEGIN
			RAISERROR (14057, 16, -1)
			RETURN (1)
		END

	if (@resolver_clsid='') select @resolver_clsid = NULL
	if (@filter_clause='') set @filter_clause = NULL
	
	/*
	** Populate the local copy of sysmergearticles
	*/
	if exists (select * from sysmergearticles where artid = @artid and pubid = @pubid )
		begin
			update sysmergearticles 
				set name = @article,
					artid = @artid,
					pre_creation_command = pre_creation_command,
					pubid = @pubid,
					nickname = @nickname,
					column_tracking = @column_tracking,
					status	= @status,
					resolver_clsid = @resolver_clsid,
					insert_proc = @insert_proc,
					update_proc =  @update_proc,
					select_proc = @select_proc,
					destination_object = @destination_object,
					missing_col_count = @missing_count,
					missing_cols = @missing_cols,
					article_resolver = @article_resolver,
					resolver_info = @resolver_info,
					subset_filterclause = @filter_clause
				where artid = @artid and pubid = @pubid
		end
	else
		begin
			select @objid = 0
			insert sysmergearticles (name, objid, sync_objid, artid, pre_creation_command, pubid, 
				nickname, column_tracking, status, resolver_clsid, 
				insert_proc, update_proc, select_proc, destination_object, missing_col_count, missing_cols, 
				article_resolver, resolver_info, subset_filterclause)
			values (@article, @objid, @objid, @artid, @pre_creation_command, @pubid, 
				@nickname, @column_tracking, @status, @resolver_clsid, 
				@insert_proc, @update_proc, @select_proc, @destination_object, @missing_count, @missing_cols, 
				@article_resolver, @resolver_info, @filter_clause)
		end
    IF @@ERROR <> 0
        BEGIN
		RAISERROR (14057, 16, -1)
		RETURN (1)
	END

	RETURN 0
go

exec dbo.sp_MS_marksystemobject sp_MSaddinitialarticle
go
grant exec on dbo.sp_MSaddinitialarticle to public
go

raiserror('Creating procedure sp_MSaddinitialpublication', 0,1)
GO

CREATE PROCEDURE sp_MSaddinitialpublication(
	@publisher				sysname,
	@publisher_db 			sysname,
	@publication			sysname,	 		/* Name of the publication */
	@description			nvarchar(255), 		/* Description of the publication */
	@pubid	 				uniqueidentifier,	/* Publication ID */
	@retention				int,				/* Retention period of the publication */
	@sync_mode				int,				/* Sync mode of the publication */
	@allow_push				int,				/* does publication allow push ? */
	@allow_pull				int,				/* does publication allow pull ? */
	@allow_anonymous		int,				/* does publication allow anonymous ? */
	@centralized_conflicts	int, 				/* publication does centralized conflicts ? */
	@status					int, 				/* publication's status */
	@snapshot_ready			int, 				/* publication snapshto_ready flag ? */
	@enabled_for_internet	int, 				/* publication enabled_for_internet flag ? */
	@publication_type		int					/* a full publication or a partial one */
	) AS
	
    SET NOCOUNT ON
	declare @retcode int

	/*
	** NOTE -- WORKAROUND ODBC BUG WHICH have not been reproed.
	*/
	select @publication = RTRIM(@publication)
	select @publisher_db = RTRIM(@publisher_db)

	/*
	** Check for subscribing permission
	*/
	exec @retcode=sp_MSreplcheck_subscribe
	if @retcode<>0 or @@ERROR<>0 return (1)
	
	/*
	** Populate the local copy of sysmergepublications
	*/
	BEGIN TRAN
	save TRAN MSaddinitialpublication
	
	if exists (select * from sysmergepublications 
			where name = @publication and UPPER(publisher)=UPPER(@publisher) and publisher_db=@publisher_db)
		begin 
			declare @pubid_local uniqueidentifier
			select @pubid_local = pubid 
				from sysmergepublications where name = @publication and UPPER(publisher)=UPPER(@publisher) and publisher_db=@publisher_db
			update sysmergesubscriptions	SET pubid = @pubid where pubid = @pubid_local
		    IF @@ERROR <> 0
		        BEGIN
					RAISERROR (14057, 16, -1)
					goto FAILURE
				END
				
			if @pubid <> @pubid_local
				delete from sysmergesubscriptions where subid = @pubid
				
			update sysmergesubscriptions	SET subid = @pubid where subid = @pubid_local
		    IF @@ERROR <> 0
		        BEGIN
					RAISERROR (14057, 16, -1)
					goto FAILURE
				END

			update sysmergesubscriptions	
				SET partnerid = @pubid
				where partnerid = @pubid_local
		
		    IF @@ERROR <> 0
		        BEGIN
					RAISERROR (14057, 16, -1)
					goto FAILURE
				END

			update sysmergepublications 
				SET pubid = @pubid, 
					name = @publication, 
					description = @description, 
					designmasterid = @pubid, 
					retention = @retention, 
					parentid = pubid, 
					sync_mode = sync_mode, 
					allow_push = @allow_push, 
					allow_pull = @allow_pull, 
					allow_anonymous = @allow_anonymous, 
					centralized_conflicts = @centralized_conflicts,
					status = @status,
					snapshot_ready = @snapshot_ready,
					enabled_for_internet = @enabled_for_internet,
					publication_type = @publication_type
				where name = @publication
					  and UPPER(publisher) = UPPER(@publisher)
					  and publisher_db = @publisher_db
		end
	else
		begin
			insert sysmergepublications(publisher, publisher_db,pubid, name, description, designmasterid, 
				retention, parentid, sync_mode, allow_push, allow_pull, allow_anonymous, 
				centralized_conflicts, status, snapshot_ready, enabled_for_internet, publication_type)
			values(@publisher, @publisher_db, @pubid, @publication, @description, @pubid, 
				@retention, @pubid, @sync_mode, @allow_push, @allow_pull, @allow_anonymous, 
				@centralized_conflicts, @status, @snapshot_ready, @enabled_for_internet, @publication_type)
		end
    IF @@ERROR <> 0
        BEGIN
			RAISERROR (14057, 16, -1)
			goto FAILURE
		END
	COMMIT TRAN

	RETURN (0)

FAILURE:
	/* UNDONE : This code is specific to 6.X nested transaction semantics */
	if @@TRANCOUNT > 0
	begin
		ROLLBACK TRANSACTION MSaddinitialpublication
		COMMIT TRANSACTION
	end
	RETURN (1)
go
exec dbo.sp_MS_marksystemobject sp_MSaddinitialpublication
go
grant exec on dbo.sp_MSaddinitialpublication to public
go

raiserror('Creating procedure sp_MSaddinitialsubscription', 0,1)
GO

CREATE PROCEDURE sp_MSaddinitialsubscription(
	@pubid	 				uniqueidentifier,		/* Publication ID */
	@subid	 				uniqueidentifier,  		/* Subscription's replica ID */
	@partnerid	 			uniqueidentifier,  		/* Partner's replica ID */
	@subscriber				sysname, 				/* Subscriber server */
	@subscriber_db			sysname,  				/* Subscriber database */
	@subscriber_priority 	real = 0.0,	 			/* Subscriber priority */
	@subscriber_type		tinyint = 0,			/* Subscriber type - local, global, or anonymous */
	@subscription_type 		int = 0,				/* Subscription type - push or pull */
    @sync_type 				tinyint = 2	    		/* Subscription sync type 1 = no sync, 2 = automatic */
	) AS
	
    SET NOCOUNT ON

    /*
    ** Declarations.
    */
    DECLARE @local 				tinyint
    DECLARE @anonymous 			tinyint
	DECLARE @subscriber_srvid	int
	DECLARE @subnickname		int
    DECLARE @active 			tinyint
	DECLARE @retcode			int
	DECLARE	@subid_old			uniqueidentifier

	
    /* 
    ** Initializations
    */
    SET @local 				= 2
    SET @anonymous 			= 3
    set @active 			= 1 /* after this SP is called, the subscription is activated */

	select @subscriber_db = RTRIM(@subscriber_db)
	/*
	** Check for subscribing permission
	** It is called by merge agent at the publisher side
	** subscriber side?
	*/
	-- @pubid is not local
	exec @retcode= dbo.sp_MSreplcheck_connection
		@pubid = @pubid
	if @retcode<>0 or @@ERROR<>0 return (1)

	-- this gets executed at both publisher (for pull subscriptions) and at subscriber
	--  if server is not found use srvid of 0 for local srvid
	
	select @subscriber_srvid = srvid from master..sysservers where srvname = @subscriber
	if @subscriber_srvid is null
		set @subscriber_srvid = 0

	begin tran
	save TRAN MSaddinitialsubscription	
		/*
		** Populate the local copy of sysmergesubscriptions
		*/
	if exists (select * from sysmergesubscriptions where subid = @subid)
			begin
				update sysmergesubscriptions 
					SET	subid = @subid,
						datasource_type = 0,
						datasource_path = NULL,
	    				srvid = @subscriber_srvid,
	    				db_name = @subscriber_db,
	    				pubid = @pubid,
	    				status = @active,
	    				subscriber_type = @subscriber_type,
		    			subscription_type =	@subscription_type,
	    				priority = @subscriber_priority,
	    				sync_type = @sync_type
					where subid = @subid 
	    				    
			    IF @@ERROR <> 0
			        BEGIN
			        	goto FAILURE
					END
			end					
					
		if exists (select * from sysmergesubscriptions where srvid = @subscriber_srvid AND db_name = @subscriber_db AND pubid = @pubid)
			begin
				select @subid_old = subid from sysmergesubscriptions where srvid = @subscriber_srvid AND db_name = @subscriber_db AND pubid = @pubid
				update sysmergesubscriptions 
					SET	subid = @subid,
						datasource_type = 0,
						datasource_path = NULL,
	    				srvid = @subscriber_srvid,
	    				db_name = @subscriber_db,
	    				pubid = @pubid,
	    				status = @active,
	    				subscriber_type = @subscriber_type,
		    			subscription_type =	@subscription_type,
	    				priority = @subscriber_priority,
	    				sync_type = @sync_type
					where srvid = @subscriber_srvid AND db_name = @subscriber_db  AND pubid = @pubid
	    				    
			    IF @@ERROR <> 0
			        BEGIN
			        	goto FAILURE
					END
				if (@subid_old IS NOT NULL)
					begin
					    /*
					    **  Delete old row for subscriber from MSmerge_replinfo.
					    */
					    DELETE from MSmerge_replinfo where repid = @subid_old
					    IF @@ERROR <> 0
					        BEGIN
					        	goto FAILURE
							END

				    	EXECUTE @retcode = dbo.sp_MSgenreplnickname @subid, @subnickname output
				    	if @@ERROR<>0 or @retcode<>0 goto FAILURE
				    	
					    /*
					    **  Add new row for subscriber to MSmerge_replinfo.
					    */
					    INSERT INTO  MSmerge_replinfo(repid, replnickname)	
							values (@subid, @subnickname) 
					    IF @@ERROR <> 0
					        BEGIN
					        	goto FAILURE
							END
					end					
			end
		else
			begin
				INSERT sysmergesubscriptions(subid,
										  partnerid,
										  datasource_type, 
										  datasource_path, 
										  srvid, 
										  db_name, 
										  pubid,
										  status, 
										  subscriber_type,
										  subscription_type,
										  priority, 
										  sync_type, 
										  description,
										  login_name)
					VALUES (@subid,
							@partnerid,
							0,
							NULL,
			   			    @subscriber_srvid,
		  				    @subscriber_db,
		   				    @pubid,
			    			@active,
			    		    @subscriber_type,
							@subscription_type,
			    			@subscriber_priority,
			    			@sync_type, 
			    			NULL, 
			    			suser_sname(suser_sid()))

			    IF @@ERROR <> 0
			        BEGIN
			        	goto FAILURE
					END

				/* Look for existing nickname from any other subscription */
				select @subnickname = max(replnickname) from MSmerge_replinfo,
					 sysmergesubscriptions where repid = subid 
					 	and srvid = @subscriber_srvid 
					 	and	db_name = @subscriber_db
			    /* Generate a new replica nickname from the @subid */
				if (@subnickname is null)
					begin
			    		EXECUTE @retcode = dbo.sp_MSgenreplnickname @subid, @subnickname output
						if @@ERROR<>0 or @retcode<>0 goto FAILURE
					end
			    /*
			    **  Add row for subscriber to MSmerge_replinfo.
			    */
			    INSERT INTO  MSmerge_replinfo(repid, replnickname)	
					values (@subid, @subnickname) 
			    IF @@ERROR <> 0
			        BEGIN
			        	goto FAILURE
					END
			end				    				    


	COMMIT TRAN			
	RETURN 0

FAILURE:
	/* UNDONE : This code is specific to 6.X nested transaction semantics */
	if @@TRANCOUNT > 0
	begin
		ROLLBACK TRANSACTION MSaddinitialsubscription
		COMMIT TRANSACTION
	end
	
	RAISERROR (14057, 16, -1)
	RETURN 1
go
exec dbo.sp_MS_marksystemobject sp_MSaddinitialsubscription
go
grant exec on dbo.sp_MSaddinitialsubscription to public
go 

raiserror('Creating procedure sp_MSmakearticleprocs', 0,1)
GO

create procedure sp_MSmakearticleprocs
	(@pubid uniqueidentifier, @artid uniqueidentifier)
as
	declare @ownername sysname
	declare @objectname sysname
	declare @ins_procname sysname
	declare @sel_procname sysname
	declare @upd_procname sysname
	declare @guidstr nvarchar(40)
	declare @ext 			nvarchar(10)
	declare @trigname 		sysname
	declare @objid int
	declare @dbname			sysname
	declare @command		nvarchar(1000)
	
	-- to be called after article is set up in a subscriber
	declare @retcode smallint

	/*
	** Check for subscribing permission
	*/
	exec @retcode=sp_MSreplcheck_subscribe
	if @retcode<>0 or @@ERROR<>0 return (1)

	select @objid = max(objid) from sysmergearticles where artid = @artid
	-- get owner name, and table name
	select @objectname = name, @ownername = user_name(uid)
		from sysobjects	where id = @objid

	-- get the  insert and update proc names from sys articles
	select @ins_procname = insert_proc, @upd_procname = update_proc, @sel_procname = select_proc
		from sysmergearticles where pubid = @pubid and artid = @artid

	-- create the procs
	set @dbname = db_name()
	/* If procedure already exists because article in multiple pubs don't bother */
	if not exists (select * from sysobjects where name = @ins_procname and type = 'P')
		begin
		set @command = 'sp_MSmakeinsertproc ' + QUOTENAME(@objectname) + ' , ' + QUOTENAME(@ownername) + ' , ' + @ins_procname  + ', [' + convert(nchar(36), @pubid) + ']'
		exec @retcode = master..xp_execresultset @command, @dbname
		if @@ERROR<>0 OR @retcode <>0 return (1)
		exec @retcode = dbo.sp_MS_marksystemobject  @ins_procname 
		if @@ERROR<>0 return (1)
		end
		exec ('grant exec on ' + @ins_procname + ' to public')
		if @@ERROR<>0 return (1)

	/* If procedure already exists because article in multiple pubs don't bother */
	if not exists (select * from sysobjects where name = @upd_procname and type = 'P')
		begin
		set @command = 'sp_MSmakeupdateproc ' + QUOTENAME(@objectname) + ' , ' + QUOTENAME(@ownername) + ' , ' + @upd_procname
		exec @retcode = master..xp_execresultset @command, @dbname
		if @@ERROR<>0 OR @retcode <>0 return (1)
		exec @retcode = dbo.sp_MS_marksystemobject  @upd_procname 
		if @@ERROR<>0 return (1)
		exec ('grant exec on ' + @upd_procname + ' to public')
		if @@ERROR<>0 return (1)
		end
		
	/* If procedure already exists because article in multiple pubs don't bother */
	if not exists (select * from sysobjects where name = @sel_procname and type = 'P')
		begin
		set @command = 'sp_MSmakeselectproc ' + QUOTENAME(@objectname) + ' , ' + QUOTENAME(@ownername) + ' , ' + @sel_procname
		exec (@command)
		if @@ERROR<>0 return (1)
		exec @retcode = dbo.sp_MS_marksystemobject  @sel_procname 
		if @@ERROR<>0 return (1)
		exec ('grant exec on ' + @sel_procname + ' to public')
		if @@ERROR<>0 return (1)
		end
		
go
exec dbo.sp_MS_marksystemobject sp_MSmakearticleprocs
go
grant exec on dbo.sp_MSmakearticleprocs to public
go


raiserror('Creating procedure sp_MSupdatesysmergearticles', 0,1)
GO

CREATE PROCEDURE sp_MSupdatesysmergearticles(
	@object				sysname, 				/* Name of the table */
	@artid				uniqueidentifier,		/* Article ID */
	@owner				sysname = NULL
	) AS
	declare @merge_pub_object_bit 	int
	declare @id						int
	declare @qualified_name			nvarchar(268)
    SET NOCOUNT ON
	
	declare @retcode int

	if @owner is NULL or @owner = ''
	begin
		if exists (select name from sysobjects where id = object_id(@object))
			select @owner = user_name(uid) from sysobjects where id = object_id(QUOTENAME(@object))
		else 
			begin
				raiserror(21078, 16, -1, @object)
				return (1)
			end
	end
		
	select @qualified_name = QUOTENAME(@owner) + '.' + QUOTENAME(@object)
	
	/*
	** Check to see if current publication has permission
	*/
	/*
	** Check for subscribing permission
	*/
	exec @retcode=sp_MSreplcheck_subscribe
	if @retcode<>0 or @@ERROR<>0 return (1)
	
	select @merge_pub_object_bit 	= 128

	if (@artid is NULL)
        BEGIN
			RAISERROR (14057, 16, -1)
			RETURN (1)
		END
	begin tran
		if exists (select name from sysobjects where id = object_id(@qualified_name))
			begin
				exec dbo.sp_replupdateschema @qualified_name
				update sysobjects set replinfo = replinfo | @merge_pub_object_bit where id=object_id(@qualified_name)
				if @@ERROR<>0 goto UNDO
			/*
			** update the local copy of sysmergearticles
			*/
   				update sysmergearticles set objid = OBJECT_ID(@qualified_name) where artid = @artid
    			IF @@ERROR <> 0
        			BEGIN
						RAISERROR (14057, 16, -1)
						goto UNDO
					END
			end
		else -- THIS IS FINE. This dynimic query is there to provide a good error message. No need to use SP.
			raiserror(21078, 16, -1, @object)
	commit tran
	RETURN 0
UNDO:
	if @@TRANCOUNT = 1 
		ROLLBACK TRAN
	else
		COMMIT TRAN
	RETURN 1
go
exec dbo.sp_MS_marksystemobject sp_MSupdatesysmergearticles
go
grant exec on dbo.sp_MSupdatesysmergearticles to public
go


raiserror('Creating procedure sp_MSmakeinsertproc', 0,1)
GO

-- This will be called by snapshot at publisher side and 
-- merge at the subscriber side, check for dbo permission
create procedure sp_MSmakeinsertproc 
	(@tablename sysname, @ownername sysname, @procname sysname, @pubid uniqueidentifier)
as
declare @argname			sysname
declare @id 				int
declare @qualified_name		nvarchar(255)
declare @idstr				nvarchar(100)

if @ownername is NULL or @ownername=''
	select @qualified_name = QUOTENAME(@tablename)
else	
	select @qualified_name = QUOTENAME(@ownername) + '.' + QUOTENAME(@tablename)
	
select @id = object_id(@qualified_name)
if @id is NULL return (1)

set @idstr = rtrim(convert(nchar, @id))	

declare @retcode smallint
declare @colname sysname
declare @rgcolname sysname
declare @typename sysname
declare @colid smallint
declare @status tinyint
declare @len smallint
declare @prec smallint
declare @scale int
declare @tablenick int
declare @tablenickstr nvarchar(12)
declare @colordinal smallint
declare @cmdpiece nvarchar(4000)

set nocount on

	/*
	** Check for subscribing permission
	*/
	exec @retcode=sp_MSreplcheck_subscribe
	if @retcode<>0 or @@ERROR<>0 return (1)
	
execute @retcode = dbo.sp_MStablenickname @ownername, @tablename, @tablenick output
IF @@ERROR <> 0 or @retcode <>0 return (1)
set @tablenickstr = rtrim(convert(nchar, @tablenick))

-- create temp table to select the command text out of
create table #tempcmd (phase int NOT NULL, step int identity NOT NULL, cmdtext nvarchar(4000) NULL)

-- insert text pieces that don't repeat for each column

-- phase 0 : create procedure and fixed part of argument list
set @cmdpiece = 'create procedure dbo.'  + QUOTENAME(@procname) + ' (@rowguid uniqueidentifier, 
	@generation int, @lineage varbinary(255),  @colv varbinary(2048) '
insert into #tempcmd (phase, cmdtext) values (0, @cmdpiece)

-- phase 1 is rest of argument list; goes in during loop over columns
-- phase 2 : paren to close argument list, and variable declarations
set @cmdpiece = ') as
	declare @tablenick int
	declare @success int
	declare @retcode int

	exec @retcode = dbo.sp_MSreplcheck_connection @objid = ' + @idstr + '
		if @retcode<>0 or @@ERROR<>0 return (3)
	
	select @tablenick = ' + @tablenickstr + '
	set @success = 0
	'
insert into #tempcmd (phase, cmdtext) values (2, @cmdpiece)

-- phase 3 is optional set identity insert on, goes in during loop if needed
-- phase 4 is beginning a sub transaction, setting save point and starting insert statement
set @cmdpiece = '
	begin transaction sub
	save transaction sp1
	exec dbo.sp_MSsetrowmetadata @tablenick, @rowguid, @generation, @lineage, @colv, 2
	insert into ' + @qualified_name + ' ('
insert into #tempcmd (phase, cmdtext) values (4, @cmdpiece)

-- phase 5 is column list that we are inserting; done in loop

-- phase 6 is just the opening and closing parens and VALUES keyword
set @cmdpiece = ') values ('
insert into #tempcmd (phase, cmdtext) values (6, @cmdpiece)

-- phase 7 is all of those arguments as the list of value expressions; done in loop
-- phase 8 finish insert, check status, etc.
-- if we have a permanent view, check for case where we inserted a row that doesn't
-- meet filters of subscriber we are getting the insert from
set @cmdpiece = ')
		if (@@rowcount = 1)
			begin
			set @success = 1
			end
		else
			begin
			select @success = 3
			end
		'
insert into #tempcmd (phase, cmdtext) values (8, @cmdpiece)

if exists (select * from sysmergearticles where pubid = @pubid and objid = @id and
	view_type = 1)
	begin
	/* Get name of rowguidcol. Aliasing doesn't work through a view. */
	select @rgcolname = QUOTENAME(name) from syscolumns where id = @id and ColumnProperty(@id, name, 'isrowguidcol') = 1
	if @rgcolname is null
		set @rgcolname = 'rowguid'
	select @cmdpiece = ' if not exists (select * from ' + QUOTENAME(OBJECT_NAME(sync_objid))
		from sysmergearticles where pubid = @pubid and objid = @id
	set @cmdpiece = @cmdpiece + ' where ' + @rgcolname + ' = @rowguid) 
		begin
		update MSmerge_contents set generation = 0, partchangegen = 0 where
			rowguid = @rowguid and tablenick = @tablenick
		end
		'
	insert into #tempcmd (phase, cmdtext) values (8, @cmdpiece)
	end
 
set @cmdpiece = '
		if (@success = 3)
			begin
			rollback transaction sp1
			end
		commit transaction
		'
insert into #tempcmd (phase, cmdtext) values (8, @cmdpiece)

-- phase 9 is setting identity insert off if needed; done in loop
-- phase 10 is returning our success / failure status
set @cmdpiece = '
	return @success'
insert into #tempcmd (phase, cmdtext) values (10, @cmdpiece)
	
-- now loop over columns and insert missing command pieces
select @colid = min (colid) from syscolumns where id = @id and iscomputed<>1
select @colname = QUOTENAME(name), @status = status, @typename = type_name(xtype),
	@len = length, 	@prec = COLUMNPROPERTY(id, name, 'precision'), @scale = scale
	from syscolumns 
	where id = @id and colid = @colid
if @typename='nvarchar' or @typename='nchar' -- a unit of nchar takes 2 bytes
	select @len = @len/2
set @colordinal = 1

while (@colname is not null)
	begin
	exec @retcode = dbo.sp_MSmaptype @typename out, @len, @prec, @scale
	if @@error<>0 OR @retcode <>0 return (1)

	select @argname = '@p' + rtrim(convert(nchar, @colordinal))
	-- add to argument list (phase 1)
	set @cmdpiece = ', ' + @argname + ' ' + @typename
	insert into #tempcmd (phase, cmdtext) values (1, @cmdpiece)

	-- add to column list and value list
	if (@colordinal = 1)
		begin
		-- column list is phase 5
		set @cmdpiece = @colname
		insert into #tempcmd (phase, cmdtext) values (5, @cmdpiece)

		-- argname for values list is phase 7
		set @cmdpiece = @argname
		insert into #tempcmd (phase, cmdtext) values (7, @cmdpiece)
		end
	else
		begin
		-- column list is phase 5; need preceding comma since not the first one.
		set @cmdpiece = ', ' + @colname
		insert into #tempcmd (phase, cmdtext) values (5, @cmdpiece)

		-- argname for values list is phase 7 need preceding comma since not the first one.
		set @cmdpiece = ', ' + @argname
		insert into #tempcmd (phase, cmdtext) values (7, @cmdpiece)
		end
		
	-- is this an identity column?
	if (@status = 128)
		begin
		-- turning identity insert on is phase 3
		set @cmdpiece = ' set identity_insert ' + @qualified_name + ' on'
		insert into #tempcmd (phase, cmdtext) values (3, @cmdpiece)

		-- turning identity insert on is phase 9
		set @cmdpiece = ' set identity_insert ' + @qualified_name + ' off'
		insert into #tempcmd (phase, cmdtext) values (9, @cmdpiece)
		end

	-- now set up to repeat the loop with the next column
	select @colid = min (colid) from syscolumns where id = @id and colid > @colid and iscomputed<>1
	set @colname = NULL
	if @colid is not null
		select @colname = QUOTENAME(name), @status = status, @typename = type_name(xtype), @len = length,
		@prec = COLUMNPROPERTY(id, name, 'precision'), @scale = scale
		from syscolumns where id = @id and colid = @colid
	if @typename='nvarchar' or @typename='nchar' -- a unit of nchar takes 2 bytes
		select @len = @len/2
	set @colordinal = @colordinal + 1
	end

-- Now we select out the command text pieces in proper order so that our caller,
-- xp_execresultset will execute the command that creates the stored procedure.

select cmdtext from #tempcmd order by phase, step
go

exec dbo.sp_MS_marksystemobject sp_MSmakeinsertproc 
go
grant exec on dbo.sp_MSmakeinsertproc to public
go

raiserror('Creating procedure sp_MSmakeupdateproc', 0,1)
GO

-- This will be called by snapshot at publisher side and 
-- merge at the subscriber side, check for dbo permission
create procedure sp_MSmakeupdateproc 
	(@tablename sysname, @ownername sysname, @procname sysname)
as
declare @retcode 			smallint
declare @argname			nvarchar(10)
declare @varname			nvarchar(10)
declare @cmdpiece			nvarchar(4000)
declare @qualified_name		nvarchar(255)

declare @littlecomp nvarchar(300)

declare @id int
declare @idstr nvarchar(100) 
set nocount on

if @ownername is NULL or @ownername=''
	select @qualified_name = QUOTENAME(@tablename)
else	
	select @qualified_name = QUOTENAME(@ownername) + '.' + QUOTENAME(@tablename)

select @id = object_id(@qualified_name)
	if @id is NULL return (1)
	
set @idstr = rtrim(convert(nchar, @id))	

declare @colname sysname
declare @typename sysname
declare @colid smallint
declare @colordinal smallint
declare @colordstr nvarchar(4)

declare @status tinyint
declare @len smallint
declare @blen smallint
declare @prec smallint
declare @scale int
declare @tablenick int
declare @tablenickstr nvarchar(12)

	/*
	** Check for dbo permission
	*/
	exec @retcode=sp_MSreplcheck_subscribe
	if @retcode<>0 or @@ERROR<>0 return (1)
	
execute @retcode = dbo.sp_MStablenickname @ownername, @tablename, @tablenick output
if @@ERROR <>0 OR @retcode <>0 return (1)
set @tablenickstr = rtrim(convert(nchar, @tablenick))

-- create temp table to select the command text out of
create table #tempcmd (phase int NOT NULL, step int identity NOT NULL, cmdtext nvarchar(4000) NULL)

-- insert text pieces that don't repeat for each column

-- phase 0 : create procedure and fixed part of argument list
set @cmdpiece = 'Create procedure dbo.' + @procname + ' (@rowguid uniqueidentifier, @setbm varbinary(125) = NULL,
	@metadata_type tinyint, @lineage_old varbinary(255), @generation int,
	@lineage_new varbinary(255), @colv varbinary(2048) '
insert into #tempcmd (phase, cmdtext) values (0, @cmdpiece)

-- phase 1 is rest of argument list; goes in during loop over columns
-- phase 2 paren to close argument list and fixed variable declarations
set @cmdpiece = ') as
	declare @tablenick int
	declare @failure int
	declare @success int
	declare @fset int
	declare @match int
	declare @retcode smallint
	
	exec @retcode = dbo.sp_MSreplcheck_connection @objid = ' + @idstr + '
		if @retcode<>0 or @@ERROR<>0 return (3)

	select @tablenick = ' + @tablenickstr + '
	set @failure = 0
	'
insert into #tempcmd (phase, cmdtext) values (2, @cmdpiece)

-- phase 3 is rest of variable declarations; goes in during loop over columns
-- phase 4 begin a transaction, set savepoint in case we roll back, begin select to get current values
set @cmdpiece = 'begin transaction sub
	save transaction sp1
	select @success = 2'
insert into #tempcmd (phase, cmdtext) values (4, @cmdpiece)

-- phase 5 is middle part of select assigning column values to local variables -- goes in loop
-- phase 6 -- finish the select, check that metadata matches
set @cmdpiece = ' from ' + @qualified_name + ' (updlock) where rowguidcol = @rowguid
	set @match = @@rowcount
	exec dbo.sp_MScheckmetadatamatch @metadata_type, @rowguid, @tablenick, @lineage_old, @match output
	if (@match = 1)
		begin
		select @success = 1
	'
insert into #tempcmd (phase, cmdtext) values (6, @cmdpiece)

-- phase 7 is a bunch of if's that compare old values with new values ; goes in during loop
-- phase 8 finish the stored procedure
set @cmdpiece = '		if (@failure = 0)
		exec dbo.sp_MSsetrowmetadata @tablenick, @rowguid, @generation, @lineage_new, @colv, 2
		end
	if (@failure = 1)
		begin
		rollback transaction sp1
		select @success = 3
		end
	commit transaction
	return @success'
insert into #tempcmd (phase, cmdtext) values (8, @cmdpiece)

-- now do the loop over all columns and insert the missing pieces

-- don't script out computed columns
select @colid = min (colid) from syscolumns where id = @id and iscomputed <> 1
select @colname = QUOTENAME(name), @status = status, @typename = type_name(xtype), @blen = length,
	@prec = COLUMNPROPERTY(id, name, 'precision'), @scale = scale
	from syscolumns 
	where id = @id and colid = @colid
if @typename='nvarchar' or @typename='nchar' -- a unit of nchar takes 2 bytes
	set @len = @blen/2
else
	set @len = @blen
set @colordinal = 1

while (@colname is not null)
	begin
	if (@status = 128)
		begin
		-- just skip past identity columns as they can't be updated
		select @colid = min (colid) from syscolumns where id = @id and colid > @colid and iscomputed<>1
		set @colname = NULL
		select @colname = QUOTENAME(name), @status = status, @typename = type_name(xtype), @blen = length,
			@prec = COLUMNPROPERTY(id, name, 'precision'), @scale = scale
			from syscolumns 
			where id = @id and colid = @colid
		if @typename='nvarchar' or @typename='nchar' -- a unit of nchar takes 2 bytes
			set @len = @blen/2
		else
			set @len = @blen
		set @colordinal = @colordinal + 1
		end
	set @colordstr = convert(nvarchar(4), @colordinal)
	exec @retcode = dbo.sp_MSmaptype @typename out, @len, @prec, @scale
	if @@ERROR <>0 OR @retcode <>0 return (1)

	-- put in argument list element (phase 1)
	set @argname = '@p' + rtrim(@colordstr)
	set @cmdpiece = ',
		' + @argname + ' ' + @typename + ' = NULL '
	insert into #tempcmd (phase, cmdtext) values (1, @cmdpiece)

	-- put in declaration for variable (phase 3) -- text and image get no variable
	if (@typename <> 'ntext' and @typename <> 'text' and @typename <> 'image')
		begin
		set @varname = '@l' + rtrim(@colordstr)

		set @cmdpiece = 'declare ' + @varname + ' ' + @typename + '
'
		insert into #tempcmd (phase, cmdtext) values (3, @cmdpiece)

		-- put in set piece to initialize variable to old value in select statement (phase 5)
		set @cmdpiece = ', ' + @varname + ' = ' + @colname
		insert into #tempcmd (phase, cmdtext) values (5, @cmdpiece)

		-- put in if piece that compares old value with new, checks bit if argument is null
		if (@typename like '%char%')
			begin
			-- Compare binaries instead of variables so that case changes are caught as different
			set @littlecomp = 'convert(varbinary(' + rtrim(convert(nchar, @blen)) + '), ' + @argname + ')
				= convert(varbinary(' + rtrim(convert(nchar, @blen)) + '), ' + @varname + ')'
			end
		else
			begin
			set @littlecomp = @argname + ' = ' + @varname
			end
			
		set @cmdpiece = '			if ' + @littlecomp + '
			set @fset = 0
			else if ' + @argname + ' is not null
				set @fset = 1
			else exec @fset = dbo.sp_MStestbit @setbm, ' + @colordstr + '
			if @fset <> 0
				begin
				update ' + @qualified_name + ' set ' + @colname + ' = ' + @argname + ' where rowguidcol = @rowguid 
				if (@@rowcount <> 1)
					set @failure = 1
				end 
			'
		insert into #tempcmd (phase, cmdtext) values (7, @cmdpiece)
		end
	else
		begin
		-- for text and image, we just test if argument is null and whether bit is set
		-- build conditional update (phase 7)
		set @cmdpiece =  '			if ' + @argname + ' is not null
				set @fset = 1
			else exec @fset = dbo.sp_MStestbit @setbm, ' + @colordstr + '
			if @fset <> 0
				begin
				update ' + @qualified_name + ' set ' + @colname + ' = ' + @argname + ' where rowguidcol = @rowguid 
				if (@@rowcount <> 1)
					set @failure = 1
				end 
			'
		-- Now insert the command to temp table
		insert into #tempcmd (phase, cmdtext) values (7, @cmdpiece)	
		end
		
	-- Advance loop to next column and repeat!
	select @colid = min (colid) from syscolumns where id = @id and colid > @colid and iscomputed<>1
	set @colname = NULL
	if (@colid is not null)
		begin
		select @colname = QUOTENAME(name), @status = status, @typename = type_name(xtype), @blen = length,
			@prec = COLUMNPROPERTY(id, name, 'precision'), @scale = scale
			from syscolumns 
			where id = @id and colid = @colid
			if @typename='nvarchar' or @typename='nchar' -- a unit of nchar takes 2 bytes
				set @len = @blen/2
			else
				set @len = @blen
		set @colordinal = @colordinal + 1
		end
	end

-- Now we select out the command text pieces in proper order so that our caller,
-- xp_execresultset will execute the command that creates the stored procedure.

select cmdtext from #tempcmd order by phase, step

go

exec dbo.sp_MS_marksystemobject sp_MSmakeupdateproc 
go
grant exec on dbo.sp_MSmakeupdateproc to public
go

raiserror('Creating procedure sp_MSmakeselectproc', 0,1)
GO


create procedure sp_MSmakeselectproc 
	(@tablename sysname, @ownername sysname, @procname sysname)
as
declare @retcode 			smallint
declare @argname			nvarchar(10)
declare @varname			nvarchar(10)
declare @cmdpiece			nvarchar(4000)
declare @qualified_name		nvarchar(255)
declare @column_list		nvarchar(4000)
declare @littlecomp nvarchar(300)
declare @colid				int
declare @col_name			sysname
declare @id int
set nocount on

if @ownername is NULL or @ownername=''
	select @qualified_name = QUOTENAME(@tablename)
else	
	select @qualified_name = QUOTENAME(@ownername) + '.' + QUOTENAME(@tablename)

select @id = object_id(@qualified_name)
	if @id is NULL return (1)

/*
** Dynamically generate column list excluding computed columns
*/

if EXISTS (select name from syscolumns where id=@id and iscomputed=1)
BEGIN
	select @column_list = ''
	DECLARE column_cursor CURSOR LOCAL FAST_FORWARD FOR
		select name from syscolumns where id=@id and iscomputed<>1
	FOR READ ONLY
	open column_cursor
	fetch next from column_cursor into @col_name
	WHILE (@@fetch_status <> -1)
	BEGIN
			if LOWER(@col_name)='rowguid' 
				select @col_name = 'rowguidcol' --Use alias to avoid conflict with #cont table
			else
				set @col_name = QUOTENAME(@col_name)
			if @column_list=''
				select @column_list = @col_name
			else
				select @column_list = @column_list + ', ' + @col_name			
			fetch next from column_cursor into @col_name			
	END
	close column_cursor
	deallocate column_cursor

	if @column_list=''
	begin
		RAISERROR(21125, 16, -1)
		return (1)
	end
END
else 
	select @column_list = '*'

/*
** Check for dbo permission
*/
	exec @retcode=sp_MSreplcheck_subscribe
	if @retcode<>0 or @@ERROR<>0 return (1)

set @cmdpiece = 'Create procedure dbo.'  + QUOTENAME(@procname) + ' (@type int, @rowguid uniqueidentifier=NULL) AS
		declare @retcode 	int
		declare @objid		int
		select @objid = object_id(''' + @qualified_name + ''')
		exec @retcode = dbo.sp_MSreplcheck_connection @objid=@objid
		if @@ERROR<>0 or @retcode<>0 
			return (1)

		if @type = 1 
			select ' + @column_list + ' from ' + @qualified_name + ' where rowguidcol = @rowguid
			
		else if @type < 4 
			select c.tablenick, c.rowguid, c.generation, c.lineage, c.colv1, ' + @column_list + ' from ' +
				 @qualified_name + ' t,  #cont c where
					  t.rowguidcol = c.rowguid
					 order by c.rowguid
		else if @type = 4
			select 1 from ' + @qualified_name + ' where rowguidcol = @rowguid

		else if @type = 5
			delete ' + @qualified_name + ' where rowguidcol = @rowguid
		else if @type = 6 -- sp_MSenumcolumns
			select ' + @column_list + ' from ' + @qualified_name + ' where 1=2
		else if @type = 7 -- sp_MSlocktable
			select count(*) from ' + @qualified_name + '(tablock holdlock) where 1 = 2
		else if @type = 8 -- put update lock
			if not exists (select * from ' + @qualified_name + '(UPDLOCK) where rowguidcol = @rowguid)
				RAISERROR(20031 , 16, -1)'
			
exec (@cmdpiece)
go
			
exec dbo.sp_MS_marksystemobject sp_MSmakeselectproc 
go
grant exec on dbo.sp_MSmakeselectproc to public
go


raiserror('Creating procedure sp_MSdropconstraints', 0,1)
GO

-- This will be called merge at the subscriber side, check for dbo permission
create procedure sp_MSdropconstraints
 	 @table sysname
as
	declare @const_name sysname
	declare @objid int
	declare @retcode int
	
	/*
	** Check for subscribing permission
	*/
	exec @retcode=sp_MSreplcheck_subscribe
	if @retcode<>0 or @@ERROR<>0 return (1)

	select @table=QUOTENAME(@table)
	
	set @objid = object_id(@table)
	if @objid is null
		return
	select @const_name = object_name(constid) from 
		sysreferences where fkeyid = @objid
	while @const_name is not null
		begin
			exec ('alter table ' + @table +
				' drop constraint ' + @const_name)
			if @@ERROR <> 0
				return (1)
			set @const_name = NULL
			select @const_name = object_name(constid) from 
				sysreferences where fkeyid = @objid
		end
	return (0)		
go

exec dbo.sp_MS_marksystemobject sp_MSdropconstraints
go
grant exec on dbo.sp_MSdropconstraints to public
go

raiserror('Creating procedure sp_MSinsertschemachange', 0,1)
GO

CREATE PROCEDURE sp_MSinsertschemachange(
	@pubid			uniqueidentifier,
	@artid			uniqueidentifier = NULL, /* Can be NULL for directory commands */
	@schemaversion 	int,
	@schemaguid		uniqueidentifier,
	@schematype		int,
	@schematext		nvarchar(2000)
	)
as
	declare @retcode int
	/*
	** Check for subscribing permission
	*/
	exec @retcode=sp_MSreplcheck_subscribe
	if @retcode<>0 or @@ERROR<>0 return (1)
	
	/* Parameter validation */
	if (@schemaversion is null)
		begin
		RAISERROR(14043, 16, -1, '@schemaversion')
		return (1)
		end

	if (not exists(select * from sysobjects where name = 'MSmerge_contents'))
		begin
		RAISERROR(20001 , 16, -1)
		return (1)
		end

	insert into sysmergeschemachange with (HOLDLOCK TABLOCKX) (pubid, artid, schemaversion, schemaguid, schematype, schematext)
		 values (@pubid, @artid, @schemaversion, @schemaguid, @schematype, @schematext) 
	if @@error <> 0		
		begin
			RAISERROR(20001 , 16, -1)
			return (1)
		end
	/* update the schema version and schemaguid in MSmerge_replinfo */		
	declare @my_nickname int
	declare @srvid int
	select @srvid = 0
	declare @repid		 uniqueidentifier
	select  @my_nickname = replnickname,  @repid = repid from MSmerge_replinfo 
		where repid in (select subid from sysmergesubscriptions
			where srvid = @srvid and db_name = DB_NAME() and pubid = @pubid)


	update MSmerge_replinfo set schemaversion = @schemaversion where repid = @repid
	if @@error <> 0		
		begin
			RAISERROR(20001 , 16, -1)
			return (1)
		end
	update MSmerge_replinfo set schemaguid = @schemaguid where repid = @repid
	if @@error <> 0		
		begin
			RAISERROR(20001 , 16, -1)
			return (1)
		end
	return (0)		
go
exec dbo.sp_MS_marksystemobject sp_MSinsertschemachange
go
grant exec on dbo.sp_MSinsertschemachange to public
go

raiserror('Creating procedure sp_MSvalidatearticle', 0, 1)
GO

create procedure sp_MSvalidatearticle
	@artid 		uniqueidentifier,
	@pubid		uniqueidentifier,
	@expected_rowcount int = NULL OUTPUT,
	@expected_checksum numeric = NULL OUTPUT,
	@validation_type int = NULL,
	@full_or_fast tinyint = 2
as
-- get name of sync object and owner
	declare @objid int
	declare @syncobjid int
	declare @owner sysname
	declare @object sysname
	declare @view_type tinyint
	declare @temp_view tinyint
	declare @retcode int
	declare @rowcount_only bit
	/*
	** Check to see if current publication has permission
	*/
	if @validation_type = 2
		set @rowcount_only  = 0
	else
		set @rowcount_only  = 1

	exec @retcode=sp_MSreplcheck_connection
		@pubid = @pubid
	if @retcode<>0 or @@ERROR<>0 return (1)
	
	select @syncobjid = sync_objid, @objid = objid, @view_type = view_type from
		sysmergearticles where pubid = @pubid and artid = @artid
	if (@syncobjid is not null and @syncobjid <> 0)
		set @objid = @syncobjid
		
	select @object = name, @owner = user_name(uid) from sysobjects where id = @objid
	
--  if sync object is a temp view, we can't do this...
	set @temp_view = 2
	if @view_type = @temp_view
		begin
        RAISERROR (20069, 16, -1)
		return 1
		end
		
--  call sp_table_validation
	exec @retcode = dbo.sp_table_validation @object, @expected_rowcount OUTPUT, @expected_checksum  OUTPUT, @rowcount_only, @owner, @full_or_fast
	return @retcode
	
GO
exec dbo.sp_MS_marksystemobject sp_MSvalidatearticle
go
grant exec on dbo.sp_MSvalidatearticle to public
go

raiserror('Creating procedure sp_MSsubscriptionvalidated', 0, 1)
GO

create procedure sp_MSsubscriptionvalidated
	@subid 		uniqueidentifier,
	@pubid		uniqueidentifier
as
	/*
	** Check to see if current publication has permission
	*/
	declare @retcode int
	exec @retcode=sp_MSreplcheck_connection
		@pubid = @pubid
	if @retcode<>0 or @@ERROR<>0 return (1)
	
	update sysmergesubscriptions set last_validated = getdate()
		where subid = @subid and pubid = @pubid
	if @@rowcount <> 1 or @@error <> 0
		begin
        RAISERROR (20070, 16, -1)
		return (1)
		end
	return (0)
GO
exec dbo.sp_MS_marksystemobject sp_MSsubscriptionvalidated
go
grant exec on dbo.sp_MSsubscriptionvalidated to public

raiserror('Creating procedure sp_MSdroparticletombstones', 0, 1)
GO

create procedure sp_MSdroparticletombstones
	@artid 		uniqueidentifier
as
	declare @tablenick int
	select @tablenick = nickname from sysmergearticles where artid = @artid
	if @tablenick is not null
	begin
		delete from MSmerge_tombstone where tablenick = @tablenick
		delete from MSmerge_contents where tablenick = @tablenick
		delete from MSmerge_genhistory where art_nick=@tablenick
	end
	return (0)
GO
exec dbo.sp_MS_marksystemobject sp_MSdroparticletombstones
go
grant exec on dbo.sp_MSdroparticletombstones to public

raiserror('Creating procedure sp_MSproxiedmetadata', 0, 1)
GO

create procedure sp_MSproxiedmetadata
	@tablenick	int,
	@rowguid	uniqueidentifier,
	@lineage	varbinary(256),
	@colv		varbinary(2048)
as
	declare @old_lin varbinary(256)
	declare @old_colv varbinary(2048)

	select @old_lin = lineage, @old_colv = colv1 from MSmerge_contents where
		tablenick = @tablenick and rowguid = @rowguid
	if (@old_lin IS NOT NULL)
		begin
		exec master..xp_proxiedmetadata @lineage out, @colv out, @old_lin, @old_colv
		update MSmerge_contents set lineage = @lineage, colv1 = @colv
			where tablenick = @tablenick and rowguid = @rowguid
		end
	else
		begin
		select @old_lin = lineage from MSmerge_tombstone where
			tablenick = @tablenick and rowguid = @rowguid
		if (@old_lin IS NULL)
			return (0)
		exec master..xp_proxiedmetadata @lineage out, @colv, @old_lin, NULL
		update MSmerge_tombstone set lineage = @lineage
			where tablenick = @tablenick and rowguid = @rowguid
		end
	return (0)
GO
exec dbo.sp_MS_marksystemobject sp_MSproxiedmetadata
grant exec on dbo.sp_MSproxiedmetadata to public
go

raiserror('Creating procedure sp_MScontractsubsnb', 0,1)
GO

create PROCEDURE sp_MScontractsubsnb 
	(@pubid uniqueidentifier,
	 @tablenick int,
	 @basetable nvarchar(258))
AS
	declare		@filter_clause	nvarchar(4000)
	declare 	@join_nick int
	declare		@jointable		nvarchar(258)
	declare 	@filterid int
	declare 	@retcode int
	declare 	@tablenickstr nvarchar(10)
	set @tablenickstr = convert(nchar(10), @tablenick)
	
	/* First, try to remove rows from notbelong based on the article filter, if there is one */
	select @filter_clause = subset_filterclause from sysmergearticles where
		pubid = @pubid and nickname = @tablenick
	if len(@filter_clause) > 0
		begin
		exec ('delete from #notbelong where tablenick = ' + @tablenickstr + ' and rowguid in
				(select RowGuidCol from ' + @basetable + ' where ' + @filter_clause + ')' )
		end

	/* Now loop over any join filters that have this as the base_table */
	select @filterid = min(join_filterid) from sysmergesubsetfilters
		where pubid = @pubid and art_nickname = @tablenick
	while @filterid is not null
		begin
		/* Get joining table and filter clause */
		select @join_nick = join_nickname, @filter_clause = join_filterclause
				from sysmergesubsetfilters where pubid = @pubid and join_filterid = @filterid
		exec @retcode = dbo.sp_MStablenamefromnick @join_nick, @jointable out, @pubid

		/* Exec query to remove rows from #notbelong that still belong to partial */
		exec ('delete from #notbelong where tablenick = ' + @tablenickstr + ' and rowguid in
				(select ' + @basetable + '.RowGuidCol from ' + @basetable + ', ' +
				@jointable + ' where (' + @filter_clause + ') and ' + @jointable +
				'.RowGuidCol not in (select rowguid from #notbelong))')

		/* Find the next filter that might apply */
		select @filterid = min(join_filterid) from sysmergesubsetfilters
			where pubid = @pubid and art_nickname = @tablenick and join_filterid > @filterid
		end
go

exec dbo.sp_MS_marksystemobject sp_MScontractsubsnb 
go
grant exec on dbo.sp_MScontractsubsnb to public
go

raiserror('Creating procedure sp_MSexpandsubsnb', 0,1)
GO

create PROCEDURE sp_MSexpandsubsnb (@pubid uniqueidentifier)
AS
	declare @filterid int
	declare @base_nick int
	declare @join_nick int
	declare @basetable nvarchar(258)
	declare @jointable nvarchar(258)
	declare @join_clause nvarchar(4000)
	declare @retcode int
	declare @base_nickstr nvarchar(10)

	/* get first filter to expand on */
	select @filterid = min(join_filterid) from sysmergesubsetfilters f, #notbelong nb
		where pubid = @pubid and nb.tablenick = f.join_nickname and f.join_filterid > nb.flag

	while @filterid is not null
		begin
		/* get join clause and tables for this filter */
		select @join_nick = join_nickname, @join_clause = join_filterclause,
			@base_nick = art_nickname from sysmergesubsetfilters where
				pubid = @pubid and join_filterid = @filterid
		exec @retcode = dbo.sp_MStablenamefromnick @join_nick, @jointable out, @pubid
		exec @retcode = dbo.sp_MStablenamefromnick @base_nick, @basetable out, @pubid
		set @base_nickstr = convert(nchar(10), @base_nick)

		/* Mark rows so that we know we've expanded those rows for this filter */
		update #notbelong set flag = @filterid where flag < @filterid
		
		/* exec an insert/select query to expand #notbelong */
		exec ('insert into #notbelong (tablenick, rowguid, flag) select ' +
				@base_nickstr + ', ' + @basetable + '.RowGuidCol, 0 from ' + @basetable + 
				', ' + @jointable + ' where ( ' + @jointable + '.RowGuidCol in 
					(select rowguid from #notbelong) ) and ' + @join_clause)
		/* if any rows inserted, try to contract the #notbelong table */
		if @@rowcount <> 0 
			exec @retcode = dbo.sp_MScontractsubsnb @pubid, @base_nick, @basetable
		
		/* get next filter to expand with */
		select @filterid = min(join_filterid) from sysmergesubsetfilters f, #notbelong nb
			where pubid = @pubid and nb.tablenick = f.join_nickname and f.join_filterid > nb.flag
		end
go

exec dbo.sp_MS_marksystemobject sp_MSexpandsubsnb 
go
grant exec on dbo.sp_MSexpandsubsnb to public
go
raiserror('Creating procedure sp_MSdelsubrows', 0,1)
GO

create PROCEDURE sp_MSdelsubrows 
	(@rowguid 		uniqueidentifier,
	@tablenick 	int,
	@metadata_type tinyint, /* 0 - Missing, 1 - Tombstone, 2 - Contents, 3 - ContentsDeferred */
	@lineage_old varbinary(255),
	@generation int,
	@lineage_new varbinary(255),
	@pubid uniqueidentifier = NULL)

as
	set nocount on
	declare @success int 
	declare @tablename 		nvarchar(258)
	declare @rowguidstr		nvarchar(40)
	declare @match 			int
	declare @new_metatype	tinyint
	declare @retcode 		smallint
	declare @reason 		nvarchar(255)
	declare @procname 		nvarchar(258)
	declare @ownername		sysname
	
	/*
	** Check to see if current publication has permission
	*/
	exec @retcode=sp_MSreplcheck_connection
		@tablenick = @tablenick
	if @retcode<>0 or @@ERROR<>0 return (1)
	
	select @success = 0
	/* Parameter validation */
	if (@rowguid is null)
		begin
		RAISERROR(14043, 16, -1, '@rowguid')
		return (0)
		end
	if (@tablenick is null)
		begin
		RAISERROR(14043, 16, -1, '@tablenick')
		return (0)
		end
	if @pubid is NULL
		exec @retcode = dbo.sp_MStablenamefromnick	@tablenick, @tablename output
	else
		exec @retcode = dbo.sp_MStablenamefromnick	@tablenick, @tablename output, @pubid
	if @@ERROR<>0 return (0)

	if (@tablename is null)
		begin
		RAISERROR(14043, 16, -1, '@tablename')
		return (0)
		end
	if (@lineage_new is null)
		begin
		RAISERROR(14043, 16, -1, '@lineage_new')
		return (0)
		end

	if (not exists(select * from sysobjects where name = 'MSmerge_contents'))
		begin
		RAISERROR(20054 , 16, -1)
		return (0)
		end
	set @rowguidstr = '''' + convert(nchar(36), @rowguid) + ''''

	-- Are we just changing the type of a tombstone?
	if (@metadata_type = 5 and exists (select * from MSmerge_tombstone where
		rowguid = @rowguid and tablenick = @tablenick))
		begin
		set @reason = formatmessage (20563) -- Moved out of partial range
		update MSmerge_tombstone set type = @metadata_type, reason = @reason where
			rowguid = @rowguid and tablenick = @tablenick
		set @success = 1
		return @success
		end

	-- Are we just changing the type of a tombstone?
	if (@metadata_type = 6 and exists (select * from MSmerge_tombstone where
		rowguid = @rowguid and tablenick = @tablenick))
		begin
		set @reason = formatmessage (20564) -- System deleted
		update MSmerge_tombstone set type = @metadata_type, reason = @reason where
			rowguid = @rowguid and tablenick = @tablenick
		set @success = 1
		return @success
		end

	-- begin transaction and lock row that we plan to delete
	begin transaction

		select @ownername = user_name(uid) from sysobjects where id = object_id(@tablename)
		select @procname = select_proc from sysmergearticles where objid = object_id(@tablename)  and pubid = @pubid
		exec @retcode = @procname @type =8, @rowguid=@rowguid

		select @success = 2
		
	if @metadata_type = 5
		begin
		set @match = 1
		set @new_metatype = 5
		end
	else if @metadata_type = 6
		begin
		set @match = 1
		set @new_metatype = 6
		end
	else
		begin
		exec @retcode=sp_MScheckmetadatamatch @metadata_type, @rowguid, @tablenick, @lineage_old, @match output

		set @new_metatype = 1
		end
	if (@match = 1)
		begin
		
		/* If there are any joinfilters with this as the join table, try to expand to deleting
		** a set of related rows.
		*/
		if (exists (select * from sysmergesubsetfilters where pubid = @pubid and
						join_nickname = @tablenick))
			begin
			declare @tn int
			declare @table_name sysname
			
			set @reason = formatmessage (20563) -- Moved out of partial range
			/* create temp and put in our tablenick, rowguid */
			create table #notbelong (bookmark int identity NOT NULL, tablenick int NOT NULL,
				rowguid uniqueidentifier NOT NULL, flag int NOT NULL)
			create index #indnbelong on #notbelong (rowguid)
			insert into #notbelong (tablenick, rowguid, flag) values
					(@tablenick, @rowguid, 0)
					
			/* call expand proc */
			exec @retcode = dbo.sp_MSexpandsubsnb @pubid
			
			select @tn = max(tablenick) from #notbelong where flag > -1
			while @tn is not null
				begin
				exec @retcode = dbo.sp_MStablenamefromnick @tn, @table_name out, @pubid
				/* delete all rows indicated by the temp table */
				exec ('delete from ' + @table_name + ' where RowGuidCol in 
					(select rowguid from #notbelong)' )
			
				/* change tombstone type for those rows */
				update MSmerge_tombstone set type = 5, reason = @reason where tablenick = @tn and
					rowguid in (select rowguid from #notbelong)
					
				/* move on to next nickname - decreasing makes delete order correct */
				update #notbelong set flag = -1 where tablenick = @tn
				select @tn = max(tablenick) from #notbelong where flag > -1
				end

			/* drop temp, set success */
			drop table #notbelong
			exec dbo.sp_MSsetrowmetadata @tablenick, @rowguid, @generation, @lineage_new, NULL, @new_metatype
			select @success = 1
			end
		else
			begin
		
			/*
			** select_proc makes a delete with @type = 5, despite its name. 
			*/
			exec @retcode = @procname @type =5, @rowguid=@rowguid
		
			if (@@error = 0 and @@rowcount = 1)
				begin
				exec dbo.sp_MSsetrowmetadata @tablenick, @rowguid, @generation, @lineage_new, NULL, @new_metatype
				select @success = 1
				end
			else
				select @success = 3
			end
		end
	commit
	return (@success)
go
exec dbo.sp_MS_marksystemobject sp_MSdelsubrows 
go
grant exec on dbo.sp_MSdelsubrows to public
go

create procedure sp_MSmakeviewproc 
	(@viewname sysname, @ownername sysname, @procname nvarchar(290), @rgcol sysname)
as
declare @retcode 			smallint
declare @varname			nvarchar(10)
declare @cmdpiece			nvarchar(4000)

set nocount on

select @procname=QUOTENAME(@procname)

set @cmdpiece = 'create procedure dbo.' + @procname + ' (@tablenick int) 
	AS

	set nocount on
	set rowcount 0

	insert into #belong (tablenick, rowguid, flag, partchangegen, joinchangegen)
		select nb.tablenick, nb.rowguid, 0, nb.partchangegen, nb.joinchangegen
					from  #notbelong nb, ' + QUOTENAME(@ownername) + '.' +
					QUOTENAME(@viewname) + ' v where nb.tablenick = @tablenick
					and nb.rowguid = v.' + @rgcol + '
	if @@ERROR <> 0
		begin
		RAISERROR(''Error selecting from view'' , 16, -1)
		return (1)	
		end'

			
exec (@cmdpiece)
exec dbo.sp_MS_marksystemobject @procname
exec ('grant exec on ' + @procname + ' to public')
go
			
exec dbo.sp_MS_marksystemobject sp_MSmakeviewproc 
go
grant exec on dbo.sp_MSmakeviewproc to public
go


exec dbo.sp_configure 'allow updates',0

go

dump tran master with no_log
go


reconfigure with override
go

